]> git.sur5r.net Git - u-boot/blobdiff - drivers/gpio/at91_gpio.c
bfin: Move gpio support for bf54x and bf60x into the generic driver folder.
[u-boot] / drivers / gpio / at91_gpio.c
index c0a97bc5dad7722fd4fb4e36e8a7d1108f3e7966..ac3b322af23cbcbb239e31f28b4032d122993253 100644 (file)
  * MA 02111-1307 USA
  */
 
+/*
+ * WARNING:
+ *
+ * As the code is right now, it expects all PIO ports A,B,C,...
+ * to be evenly spaced in the memory map:
+ * ATMEL_BASE_PIOA + port * sizeof at91pio_t
+ * This might not necessaryly be true in future Atmel SoCs.
+ * This code should be fixed to use a pointer array to the ports.
+ */
+
 #include <config.h>
 #include <common.h>
+#include <asm/io.h>
 #include <asm/sizes.h>
 #include <asm/arch/hardware.h>
-#include <asm/arch/io.h>
 #include <asm/arch/at91_pio.h>
 
 int at91_set_pio_pullup(unsigned port, unsigned pin, int use_pullup)
 {
-       at91_pio_t      *pio    = (at91_pio_t *) AT91_PIO_BASE;
+       at91_pio_t      *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
        u32             mask;
 
-       if ((port < AT91_PIO_PORTS) && (pin < 32)) {
+       if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
                mask = 1 << pin;
                if (use_pullup)
                        writel(1 << pin, &pio->port[port].puer);
@@ -52,10 +62,10 @@ int at91_set_pio_pullup(unsigned port, unsigned pin, int use_pullup)
  */
 int at91_set_pio_periph(unsigned port, unsigned pin, int use_pullup)
 {
-       at91_pio_t      *pio    = (at91_pio_t *) AT91_PIO_BASE;
+       at91_pio_t      *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
        u32             mask;
 
-       if ((port < AT91_PIO_PORTS) && (pin < 32)) {
+       if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
                mask = 1 << pin;
                writel(mask, &pio->port[port].idr);
                at91_set_pio_pullup(port, pin, use_pullup);
@@ -69,14 +79,21 @@ int at91_set_pio_periph(unsigned port, unsigned pin, int use_pullup)
  */
 int at91_set_a_periph(unsigned port, unsigned pin, int use_pullup)
 {
-       at91_pio_t      *pio    = (at91_pio_t *) AT91_PIO_BASE;
+       at91_pio_t      *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
        u32             mask;
 
-       if ((port < AT91_PIO_PORTS) && (pin < 32)) {
+       if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
                mask = 1 << pin;
                writel(mask, &pio->port[port].idr);
                at91_set_pio_pullup(port, pin, use_pullup);
+#if defined(CPU_HAS_PIO3)
+               writel(readl(&pio->port[port].abcdsr1) & ~mask,
+                       &pio->port[port].abcdsr1);
+               writel(readl(&pio->port[port].abcdsr2) & ~mask,
+                       &pio->port[port].abcdsr2);
+#else
                writel(mask, &pio->port[port].asr);
+#endif
                writel(mask, &pio->port[port].pdr);
        }
        return 0;
@@ -87,29 +104,80 @@ int at91_set_a_periph(unsigned port, unsigned pin, int use_pullup)
  */
 int at91_set_b_periph(unsigned port, unsigned pin, int use_pullup)
 {
-       at91_pio_t      *pio    = (at91_pio_t *) AT91_PIO_BASE;
+       at91_pio_t      *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
        u32             mask;
 
-       if ((port < AT91_PIO_PORTS) && (pin < 32)) {
+       if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
                mask = 1 << pin;
                writel(mask, &pio->port[port].idr);
                at91_set_pio_pullup(port, pin, use_pullup);
+#if defined(CPU_HAS_PIO3)
+               writel(readl(&pio->port[port].abcdsr1) | mask,
+                       &pio->port[port].abcdsr1);
+               writel(readl(&pio->port[port].abcdsr2) & ~mask,
+                       &pio->port[port].abcdsr2);
+#else
                writel(mask, &pio->port[port].bsr);
+#endif
+               writel(mask, &pio->port[port].pdr);
+       }
+       return 0;
+}
+
+#if defined(CPU_HAS_PIO3)
+/*
+ * mux the pin to the "C" internal peripheral role.
+ */
+int at91_set_c_periph(unsigned port, unsigned pin, int use_pullup)
+{
+       at91_pio_t      *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
+       u32             mask;
+
+       if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
+               mask = 1 << pin;
+               writel(mask, &pio->port[port].idr);
+               at91_set_pio_pullup(port, pin, use_pullup);
+               writel(readl(&pio->port[port].abcdsr1) & ~mask,
+                       &pio->port[port].abcdsr1);
+               writel(readl(&pio->port[port].abcdsr2) | mask,
+                       &pio->port[port].abcdsr2);
                writel(mask, &pio->port[port].pdr);
        }
        return 0;
 }
 
+/*
+ * mux the pin to the "D" internal peripheral role.
+ */
+int at91_set_d_periph(unsigned port, unsigned pin, int use_pullup)
+{
+       at91_pio_t      *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
+       u32             mask;
+
+       if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
+               mask = 1 << pin;
+               writel(mask, &pio->port[port].idr);
+               at91_set_pio_pullup(port, pin, use_pullup);
+               writel(readl(&pio->port[port].abcdsr1) | mask,
+                       &pio->port[port].abcdsr1);
+               writel(readl(&pio->port[port].abcdsr2) | mask,
+                       &pio->port[port].abcdsr2);
+               writel(mask, &pio->port[port].pdr);
+       }
+       return 0;
+}
+#endif
+
 /*
  * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and
  * configure it for an input.
  */
 int at91_set_pio_input(unsigned port, u32 pin, int use_pullup)
 {
-       at91_pio_t      *pio    = (at91_pio_t *) AT91_PIO_BASE;
+       at91_pio_t      *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
        u32             mask;
 
-       if ((port < AT91_PIO_PORTS) && (pin < 32)) {
+       if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
                mask = 1 << pin;
                writel(mask, &pio->port[port].idr);
                at91_set_pio_pullup(port, pin, use_pullup);
@@ -125,10 +193,10 @@ int at91_set_pio_input(unsigned port, u32 pin, int use_pullup)
  */
 int at91_set_pio_output(unsigned port, u32 pin, int value)
 {
-       at91_pio_t      *pio    = (at91_pio_t *) AT91_PIO_BASE;
+       at91_pio_t      *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
        u32             mask;
 
-       if ((port < AT91_PIO_PORTS) && (pin < 32)) {
+       if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
                mask = 1 << pin;
                writel(mask, &pio->port[port].idr);
                writel(mask, &pio->port[port].pudr);
@@ -147,18 +215,81 @@ int at91_set_pio_output(unsigned port, u32 pin, int value)
  */
 int at91_set_pio_deglitch(unsigned port, unsigned pin, int is_on)
 {
-       at91_pio_t      *pio    = (at91_pio_t *) AT91_PIO_BASE;
+       at91_pio_t      *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
        u32             mask;
 
-       if ((port < AT91_PIO_PORTS) && (pin < 32)) {
+       if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
                mask = 1 << pin;
-               if (is_on)
+               if (is_on) {
+#if defined(CPU_HAS_PIO3)
+                       writel(mask, &pio->port[port].ifscdr);
+#endif
                        writel(mask, &pio->port[port].ifer);
-               else
+               } else {
                        writel(mask, &pio->port[port].ifdr);
+               }
+       }
+       return 0;
+}
+
+#if defined(CPU_HAS_PIO3)
+/*
+ * enable/disable the debounce filter.
+ */
+int at91_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div)
+{
+       at91_pio_t      *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
+       u32             mask;
+
+       if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
+               mask = 1 << pin;
+               if (is_on) {
+                       writel(mask, &pio->port[port].ifscer);
+                       writel(div & PIO_SCDR_DIV, &pio->port[port].scdr);
+                       writel(mask, &pio->port[port].ifer);
+               } else {
+                       writel(mask, &pio->port[port].ifdr);
+               }
+       }
+       return 0;
+}
+
+/*
+ * enable/disable the pull-down.
+ * If pull-up already enabled while calling the function, we disable it.
+ */
+int at91_set_pio_pulldown(unsigned port, unsigned pin, int is_on)
+{
+       at91_pio_t      *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
+       u32             mask;
+
+       if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
+               mask = 1 << pin;
+               writel(mask, &pio->port[port].pudr);
+               if (is_on)
+                       writel(mask, &pio->port[port].ppder);
+               else
+                       writel(mask, &pio->port[port].ppddr);
+       }
+       return 0;
+}
+
+/*
+ * disable Schmitt trigger
+ */
+int at91_set_pio_disable_schmitt_trig(unsigned port, unsigned pin)
+{
+       at91_pio_t      *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
+       u32             mask;
+
+       if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
+               mask = 1 << pin;
+               writel(readl(&pio->port[port].schmitt) | mask,
+                       &pio->port[port].schmitt);
        }
        return 0;
 }
+#endif
 
 /*
  * enable/disable the multi-driver. This is only valid for output and
@@ -166,10 +297,10 @@ int at91_set_pio_deglitch(unsigned port, unsigned pin, int is_on)
  */
 int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on)
 {
-       at91_pio_t      *pio    = (at91_pio_t *) AT91_PIO_BASE;
+       at91_pio_t      *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
        u32             mask;
 
-       if ((port < AT91_PIO_PORTS) && (pin < 32)) {
+       if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
                mask = 1 << pin;
                if (is_on)
                        writel(mask, &pio->port[port].mder);
@@ -184,10 +315,10 @@ int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on)
  */
 int at91_set_pio_value(unsigned port, unsigned pin, int value)
 {
-       at91_pio_t      *pio    = (at91_pio_t *) AT91_PIO_BASE;
+       at91_pio_t      *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
        u32             mask;
 
-       if ((port < AT91_PIO_PORTS) && (pin < 32)) {
+       if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
                mask = 1 << pin;
                if (value)
                        writel(mask, &pio->port[port].sodr);
@@ -202,11 +333,11 @@ int at91_set_pio_value(unsigned port, unsigned pin, int value)
  */
 int at91_get_pio_value(unsigned port, unsigned pin)
 {
-       u32             pdsr    = 0;
-       at91_pio_t      *pio    = (at91_pio_t *) AT91_PIO_BASE;
+       u32             pdsr = 0;
+       at91_pio_t      *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
        u32             mask;
 
-       if ((port < AT91_PIO_PORTS) && (pin < 32)) {
+       if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
                mask = 1 << pin;
                pdsr = readl(&pio->port[port].pdsr) & mask;
        }