[AVR32] Portmux API update
authorHaavard Skinnemoen <hskinnemoen@atmel.com>
Mon, 4 Dec 2006 12:46:52 +0000 (13:46 +0100)
committerHaavard Skinnemoen <hskinnemoen@atmel.com>
Fri, 8 Dec 2006 12:06:17 +0000 (13:06 +0100)
Rename portmux_set_func to at32_select_periph, add at32_select_gpio
and add flags parameter to specify the initial state of the pins.

Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
arch/avr32/mach-at32ap/at32ap7000.c
arch/avr32/mach-at32ap/pio.c
include/asm-avr32/arch-at32ap/at32ap7000.h [new file with mode: 0644]
include/asm-avr32/arch-at32ap/portmux.h

index 7ff6ad8..ada7930 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <asm/io.h>
 
+#include <asm/arch/at32ap7000.h>
 #include <asm/arch/board.h>
 #include <asm/arch/portmux.h>
 #include <asm/arch/sm.h>
@@ -57,6 +58,9 @@ static struct platform_device _name##_id##_device = {         \
        .num_resources  = ARRAY_SIZE(_name##_id##_resource),    \
 }
 
+#define select_peripheral(pin, periph, flags)                  \
+       at32_select_periph(GPIO_PIN_##pin, GPIO_##periph, flags)
+
 #define DEV_CLK(_name, devname, bus, _index)                   \
 static struct clk devname##_##_name = {                                \
        .name           = #_name,                               \
@@ -67,18 +71,6 @@ static struct clk devname##_##_name = {                              \
        .index          = _index,                               \
 }
 
-enum {
-       PIOA,
-       PIOB,
-       PIOC,
-       PIOD,
-};
-
-enum {
-       FUNC_A,
-       FUNC_B,
-};
-
 unsigned long at32ap7000_osc_rates[3] = {
        [0] = 32768,
        /* FIXME: these are ATSTK1002-specific */
@@ -569,26 +561,26 @@ DEV_CLK(usart, atmel_usart3, pba, 6);
 
 static inline void configure_usart0_pins(void)
 {
-       portmux_set_func(PIOA,  8, FUNC_B);     /* RXD  */
-       portmux_set_func(PIOA,  9, FUNC_B);     /* TXD  */
+       select_peripheral(PA(8),  PERIPH_B, 0); /* RXD  */
+       select_peripheral(PA(9),  PERIPH_B, 0); /* TXD  */
 }
 
 static inline void configure_usart1_pins(void)
 {
-       portmux_set_func(PIOA, 17, FUNC_A);     /* RXD  */
-       portmux_set_func(PIOA, 18, FUNC_A);     /* TXD  */
+       select_peripheral(PA(17), PERIPH_A, 0); /* RXD  */
+       select_peripheral(PA(18), PERIPH_A, 0); /* TXD  */
 }
 
 static inline void configure_usart2_pins(void)
 {
-       portmux_set_func(PIOB, 26, FUNC_B);     /* RXD  */
-       portmux_set_func(PIOB, 27, FUNC_B);     /* TXD  */
+       select_peripheral(PB(26), PERIPH_B, 0); /* RXD  */
+       select_peripheral(PB(27), PERIPH_B, 0); /* TXD  */
 }
 
 static inline void configure_usart3_pins(void)
 {
-       portmux_set_func(PIOB, 18, FUNC_B);     /* RXD  */
-       portmux_set_func(PIOB, 17, FUNC_B);     /* TXD  */
+       select_peripheral(PB(18), PERIPH_B, 0); /* RXD  */
+       select_peripheral(PB(17), PERIPH_B, 0); /* TXD  */
 }
 
 static struct platform_device *at32_usarts[4];
@@ -663,27 +655,27 @@ at32_add_device_eth(unsigned int id, struct eth_platform_data *data)
        case 0:
                pdev = &macb0_device;
 
-               portmux_set_func(PIOC,  3, FUNC_A);     /* TXD0 */
-               portmux_set_func(PIOC,  4, FUNC_A);     /* TXD1 */
-               portmux_set_func(PIOC,  7, FUNC_A);     /* TXEN */
-               portmux_set_func(PIOC,  8, FUNC_A);     /* TXCK */
-               portmux_set_func(PIOC,  9, FUNC_A);     /* RXD0 */
-               portmux_set_func(PIOC, 10, FUNC_A);     /* RXD1 */
-               portmux_set_func(PIOC, 13, FUNC_A);     /* RXER */
-               portmux_set_func(PIOC, 15, FUNC_A);     /* RXDV */
-               portmux_set_func(PIOC, 16, FUNC_A);     /* MDC  */
-               portmux_set_func(PIOC, 17, FUNC_A);     /* MDIO */
+               select_peripheral(PC(3),  PERIPH_A, 0); /* TXD0 */
+               select_peripheral(PC(4),  PERIPH_A, 0); /* TXD1 */
+               select_peripheral(PC(7),  PERIPH_A, 0); /* TXEN */
+               select_peripheral(PC(8),  PERIPH_A, 0); /* TXCK */
+               select_peripheral(PC(9),  PERIPH_A, 0); /* RXD0 */
+               select_peripheral(PC(10), PERIPH_A, 0); /* RXD1 */
+               select_peripheral(PC(13), PERIPH_A, 0); /* RXER */
+               select_peripheral(PC(15), PERIPH_A, 0); /* RXDV */
+               select_peripheral(PC(16), PERIPH_A, 0); /* MDC  */
+               select_peripheral(PC(17), PERIPH_A, 0); /* MDIO */
 
                if (!data->is_rmii) {
-                       portmux_set_func(PIOC,  0, FUNC_A);     /* COL  */
-                       portmux_set_func(PIOC,  1, FUNC_A);     /* CRS  */
-                       portmux_set_func(PIOC,  2, FUNC_A);     /* TXER */
-                       portmux_set_func(PIOC,  5, FUNC_A);     /* TXD2 */
-                       portmux_set_func(PIOC,  6, FUNC_A);     /* TXD3 */
-                       portmux_set_func(PIOC, 11, FUNC_A);     /* RXD2 */
-                       portmux_set_func(PIOC, 12, FUNC_A);     /* RXD3 */
-                       portmux_set_func(PIOC, 14, FUNC_A);     /* RXCK */
-                       portmux_set_func(PIOC, 18, FUNC_A);     /* SPD  */
+                       select_peripheral(PC(0),  PERIPH_A, 0); /* COL  */
+                       select_peripheral(PC(1),  PERIPH_A, 0); /* CRS  */
+                       select_peripheral(PC(2),  PERIPH_A, 0); /* TXER */
+                       select_peripheral(PC(5),  PERIPH_A, 0); /* TXD2 */
+                       select_peripheral(PC(6),  PERIPH_A, 0); /* TXD3 */
+                       select_peripheral(PC(11), PERIPH_A, 0); /* RXD2 */
+                       select_peripheral(PC(12), PERIPH_A, 0); /* RXD3 */
+                       select_peripheral(PC(14), PERIPH_A, 0); /* RXCK */
+                       select_peripheral(PC(18), PERIPH_A, 0); /* SPD  */
                }
                break;
 
@@ -714,12 +706,12 @@ struct platform_device *__init at32_add_device_spi(unsigned int id)
        switch (id) {
        case 0:
                pdev = &spi0_device;
-               portmux_set_func(PIOA,  0, FUNC_A);     /* MISO  */
-               portmux_set_func(PIOA,  1, FUNC_A);     /* MOSI  */
-               portmux_set_func(PIOA,  2, FUNC_A);     /* SCK   */
-               portmux_set_func(PIOA,  3, FUNC_A);     /* NPCS0 */
-               portmux_set_func(PIOA,  4, FUNC_A);     /* NPCS1 */
-               portmux_set_func(PIOA,  5, FUNC_A);     /* NPCS2 */
+               select_peripheral(PA(0),  PERIPH_A, 0); /* MISO  */
+               select_peripheral(PA(1),  PERIPH_A, 0); /* MOSI  */
+               select_peripheral(PA(2),  PERIPH_A, 0); /* SCK   */
+               select_peripheral(PA(3),  PERIPH_A, 0); /* NPCS0 */
+               select_peripheral(PA(4),  PERIPH_A, 0); /* NPCS1 */
+               select_peripheral(PA(5),  PERIPH_A, 0); /* NPCS2 */
                break;
 
        default:
@@ -762,37 +754,37 @@ at32_add_device_lcdc(unsigned int id, struct lcdc_platform_data *data)
        switch (id) {
        case 0:
                pdev = &lcdc0_device;
-               portmux_set_func(PIOC, 19, FUNC_A);     /* CC     */
-               portmux_set_func(PIOC, 20, FUNC_A);     /* HSYNC  */
-               portmux_set_func(PIOC, 21, FUNC_A);     /* PCLK   */
-               portmux_set_func(PIOC, 22, FUNC_A);     /* VSYNC  */
-               portmux_set_func(PIOC, 23, FUNC_A);     /* DVAL   */
-               portmux_set_func(PIOC, 24, FUNC_A);     /* MODE   */
-               portmux_set_func(PIOC, 25, FUNC_A);     /* PWR    */
-               portmux_set_func(PIOC, 26, FUNC_A);     /* DATA0  */
-               portmux_set_func(PIOC, 27, FUNC_A);     /* DATA1  */
-               portmux_set_func(PIOC, 28, FUNC_A);     /* DATA2  */
-               portmux_set_func(PIOC, 29, FUNC_A);     /* DATA3  */
-               portmux_set_func(PIOC, 30, FUNC_A);     /* DATA4  */
-               portmux_set_func(PIOC, 31, FUNC_A);     /* DATA5  */
-               portmux_set_func(PIOD,  0, FUNC_A);     /* DATA6  */
-               portmux_set_func(PIOD,  1, FUNC_A);     /* DATA7  */
-               portmux_set_func(PIOD,  2, FUNC_A);     /* DATA8  */
-               portmux_set_func(PIOD,  3, FUNC_A);     /* DATA9  */
-               portmux_set_func(PIOD,  4, FUNC_A);     /* DATA10 */
-               portmux_set_func(PIOD,  5, FUNC_A);     /* DATA11 */
-               portmux_set_func(PIOD,  6, FUNC_A);     /* DATA12 */
-               portmux_set_func(PIOD,  7, FUNC_A);     /* DATA13 */
-               portmux_set_func(PIOD,  8, FUNC_A);     /* DATA14 */
-               portmux_set_func(PIOD,  9, FUNC_A);     /* DATA15 */
-               portmux_set_func(PIOD, 10, FUNC_A);     /* DATA16 */
-               portmux_set_func(PIOD, 11, FUNC_A);     /* DATA17 */
-               portmux_set_func(PIOD, 12, FUNC_A);     /* DATA18 */
-               portmux_set_func(PIOD, 13, FUNC_A);     /* DATA19 */
-               portmux_set_func(PIOD, 14, FUNC_A);     /* DATA20 */
-               portmux_set_func(PIOD, 15, FUNC_A);     /* DATA21 */
-               portmux_set_func(PIOD, 16, FUNC_A);     /* DATA22 */
-               portmux_set_func(PIOD, 17, FUNC_A);     /* DATA23 */
+               select_peripheral(PC(19), PERIPH_A, 0); /* CC     */
+               select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC  */
+               select_peripheral(PC(21), PERIPH_A, 0); /* PCLK   */
+               select_peripheral(PC(22), PERIPH_A, 0); /* VSYNC  */
+               select_peripheral(PC(23), PERIPH_A, 0); /* DVAL   */
+               select_peripheral(PC(24), PERIPH_A, 0); /* MODE   */
+               select_peripheral(PC(25), PERIPH_A, 0); /* PWR    */
+               select_peripheral(PC(26), PERIPH_A, 0); /* DATA0  */
+               select_peripheral(PC(27), PERIPH_A, 0); /* DATA1  */
+               select_peripheral(PC(28), PERIPH_A, 0); /* DATA2  */
+               select_peripheral(PC(29), PERIPH_A, 0); /* DATA3  */
+               select_peripheral(PC(30), PERIPH_A, 0); /* DATA4  */
+               select_peripheral(PC(31), PERIPH_A, 0); /* DATA5  */
+               select_peripheral(PD(0),  PERIPH_A, 0); /* DATA6  */
+               select_peripheral(PD(1),  PERIPH_A, 0); /* DATA7  */
+               select_peripheral(PD(2),  PERIPH_A, 0); /* DATA8  */
+               select_peripheral(PD(3),  PERIPH_A, 0); /* DATA9  */
+               select_peripheral(PD(4),  PERIPH_A, 0); /* DATA10 */
+               select_peripheral(PD(5),  PERIPH_A, 0); /* DATA11 */
+               select_peripheral(PD(6),  PERIPH_A, 0); /* DATA12 */
+               select_peripheral(PD(7),  PERIPH_A, 0); /* DATA13 */
+               select_peripheral(PD(8),  PERIPH_A, 0); /* DATA14 */
+               select_peripheral(PD(9),  PERIPH_A, 0); /* DATA15 */
+               select_peripheral(PD(10), PERIPH_A, 0); /* DATA16 */
+               select_peripheral(PD(11), PERIPH_A, 0); /* DATA17 */
+               select_peripheral(PD(12), PERIPH_A, 0); /* DATA18 */
+               select_peripheral(PD(13), PERIPH_A, 0); /* DATA19 */
+               select_peripheral(PD(14), PERIPH_A, 0); /* DATA20 */
+               select_peripheral(PD(15), PERIPH_A, 0); /* DATA21 */
+               select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */
+               select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */
 
                clk_set_parent(&lcdc0_pixclk, &pll0);
                clk_set_rate(&lcdc0_pixclk, clk_get_rate(&pll0));
index d3aabfc..f1280ed 100644 (file)
@@ -25,27 +25,98 @@ struct pio_device {
        void __iomem *regs;
        const struct platform_device *pdev;
        struct clk *clk;
-       u32 alloc_mask;
+       u32 pinmux_mask;
        char name[32];
 };
 
 static struct pio_device pio_dev[MAX_NR_PIO_DEVICES];
 
-void portmux_set_func(unsigned int portmux_id, unsigned int pin_id,
-                     unsigned int function_id)
+static struct pio_device *gpio_to_pio(unsigned int gpio)
 {
        struct pio_device *pio;
-       u32 mask = 1 << pin_id;
+       unsigned int index;
 
-       BUG_ON(portmux_id >= MAX_NR_PIO_DEVICES);
+       index = gpio >> 5;
+       if (index >= MAX_NR_PIO_DEVICES)
+               return NULL;
+       pio = &pio_dev[index];
+       if (!pio->regs)
+               return NULL;
 
-       pio = &pio_dev[portmux_id];
+       return pio;
+}
+
+/* Pin multiplexing API */
+
+void __init at32_select_periph(unsigned int pin, unsigned int periph,
+                              unsigned long flags)
+{
+       struct pio_device *pio;
+       unsigned int pin_index = pin & 0x1f;
+       u32 mask = 1 << pin_index;
+
+       pio = gpio_to_pio(pin);
+       if (unlikely(!pio)) {
+               printk("pio: invalid pin %u\n", pin);
+               goto fail;
+       }
 
-       if (function_id)
+       if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
+               printk("%s: pin %u is busy\n", pio->name, pin_index);
+               goto fail;
+       }
+
+       pio_writel(pio, PUER, mask);
+       if (periph)
                pio_writel(pio, BSR, mask);
        else
                pio_writel(pio, ASR, mask);
+
        pio_writel(pio, PDR, mask);
+       if (!(flags & AT32_GPIOF_PULLUP))
+               pio_writel(pio, PUDR, mask);
+
+       return;
+
+fail:
+       dump_stack();
+}
+
+void __init at32_select_gpio(unsigned int pin, unsigned long flags)
+{
+       struct pio_device *pio;
+       unsigned int pin_index = pin & 0x1f;
+       u32 mask = 1 << pin_index;
+
+       pio = gpio_to_pio(pin);
+       if (unlikely(!pio)) {
+               printk("pio: invalid pin %u\n", pin);
+               goto fail;
+       }
+
+       if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
+               printk("%s: pin %u is busy\n", pio->name, pin_index);
+               goto fail;
+       }
+
+       pio_writel(pio, PUER, mask);
+       if (flags & AT32_GPIOF_HIGH)
+               pio_writel(pio, SODR, mask);
+       else
+               pio_writel(pio, CODR, mask);
+       if (flags & AT32_GPIOF_OUTPUT)
+               pio_writel(pio, OER, mask);
+       else
+               pio_writel(pio, ODR, mask);
+
+       pio_writel(pio, PER, mask);
+       if (!(flags & AT32_GPIOF_PULLUP))
+               pio_writel(pio, PUDR, mask);
+
+       return;
+
+fail:
+       dump_stack();
 }
 
 static int __init pio_probe(struct platform_device *pdev)
diff --git a/include/asm-avr32/arch-at32ap/at32ap7000.h b/include/asm-avr32/arch-at32ap/at32ap7000.h
new file mode 100644 (file)
index 0000000..ba85e04
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Pin definitions for AT32AP7000.
+ *
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_AT32AP7000_H__
+#define __ASM_ARCH_AT32AP7000_H__
+
+#define GPIO_PERIPH_A  0
+#define GPIO_PERIPH_B  1
+
+#define NR_GPIO_CONTROLLERS    4
+
+/*
+ * Pin numbers identifying specific GPIO pins on the chip. They can
+ * also be converted to IRQ numbers by passing them through
+ * gpio_to_irq().
+ */
+#define GPIO_PIOA_BASE (0)
+#define GPIO_PIOB_BASE (GPIO_PIOA_BASE + 32)
+#define GPIO_PIOC_BASE (GPIO_PIOB_BASE + 32)
+#define GPIO_PIOD_BASE (GPIO_PIOC_BASE + 32)
+
+#define GPIO_PIN_PA(N) (GPIO_PIOA_BASE + (N))
+#define GPIO_PIN_PB(N) (GPIO_PIOB_BASE + (N))
+#define GPIO_PIN_PC(N) (GPIO_PIOC_BASE + (N))
+#define GPIO_PIN_PD(N) (GPIO_PIOD_BASE + (N))
+
+#endif /* __ASM_ARCH_AT32AP7000_H__ */
index 4d50421..83c6905 100644 (file)
@@ -7,10 +7,20 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#ifndef __ASM_AVR32_AT32_PORTMUX_H__
-#define __ASM_AVR32_AT32_PORTMUX_H__
+#ifndef __ASM_ARCH_PORTMUX_H__
+#define __ASM_ARCH_PORTMUX_H__
 
-void portmux_set_func(unsigned int portmux_id, unsigned int pin_id,
-                     unsigned int function_id);
+/*
+ * Set up pin multiplexing, called from board init only.
+ *
+ * The following flags determine the initial state of the pin.
+ */
+#define AT32_GPIOF_PULLUP      0x00000001      /* Enable pull-up */
+#define AT32_GPIOF_OUTPUT      0x00000002      /* Enable output driver */
+#define AT32_GPIOF_HIGH                0x00000004      /* Set output high */
+
+void at32_select_periph(unsigned int pin, unsigned int periph,
+                       unsigned long flags);
+void at32_select_gpio(unsigned int pin, unsigned long flags);
 
-#endif /* __ASM_AVR32_AT32_PORTMUX_H__ */
+#endif /* __ASM_ARCH_PORTMUX_H__ */