cns3xxx: switch to 3.1
[openwrt.git] / target / linux / cns3xxx / patches-2.6.39 / 104-cns3xxx_gpio.patch
1 --- a/arch/arm/mach-cns3xxx/cns3420vb.c
2 +++ b/arch/arm/mach-cns3xxx/cns3420vb.c
3 @@ -191,7 +191,7 @@ static struct map_desc cns3420_io_desc[]
4  
5  static void __init cns3420_map_io(void)
6  {
7 -       cns3xxx_map_io();
8 +       cns3xxx_common_init();
9         iotable_init(cns3420_io_desc, ARRAY_SIZE(cns3420_io_desc));
10  
11         cns3420_early_serial_setup();
12 --- a/arch/arm/mach-cns3xxx/core.c
13 +++ b/arch/arm/mach-cns3xxx/core.c
14 @@ -18,6 +18,7 @@
15  #include <asm/hardware/cache-l2x0.h>
16  #include <asm/hardware/gic.h>
17  #include <asm/smp_twd.h>
18 +#include <asm/gpio.h>
19  #include <mach/cns3xxx.h>
20  #include "core.h"
21  
22 @@ -80,7 +81,89 @@ static struct map_desc cns3xxx_io_desc[]
23         },
24  };
25  
26 -void __init cns3xxx_map_io(void)
27 +int gpio_to_irq(int gpio)
28 +{
29 +       if (gpio > 63)
30 +               return -EINVAL;
31 +
32 +       if (gpio < 32)
33 +               return IRQ_CNS3XXX_GPIOA;
34 +       else
35 +               return IRQ_CNS3XXX_GPIOB;
36 +}
37 +EXPORT_SYMBOL(gpio_to_irq);
38 +
39 +int irq2gpio(int irq)
40 +{
41 +       if (irq == IRQ_CNS3XXX_GPIOA)
42 +               return 0;
43 +       else if (irq == IRQ_CNS3XXX_GPIOB)
44 +               return 32;
45 +       else
46 +               return -EINVAL;
47 +}
48 +EXPORT_SYMBOL(irq2gpio);
49 +
50 +static inline void gpio_line_config(u8 line, u32 direction)
51 +{
52 +       u32 reg;
53 +       if (direction) {
54 +               if (line < 32) {
55 +                       reg = __raw_readl(CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_DIR);
56 +                       reg |= (1 << line);
57 +                       __raw_writel(reg, CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_DIR);
58 +               } else {
59 +                       reg = __raw_readl(CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_DIR);
60 +                       reg |= (1 << (line - 32));
61 +                       __raw_writel(reg, CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_DIR);
62 +               }
63 +       } else {
64 +               if (line < 32) {
65 +                       reg = __raw_readl(CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_DIR);
66 +                       reg &= ~(1 << line);
67 +                       __raw_writel(reg, CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_DIR);
68 +               } else {
69 +                       reg = __raw_readl(CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_DIR);
70 +                       reg &= ~(1 << (line - 32));
71 +                       __raw_writel(reg, CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_DIR);
72 +               }
73 +       }
74 +}
75 +
76 +static int cns3xxx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
77 +{
78 +       gpio_line_config(gpio, CNS3XXX_GPIO_IN);
79 +       return 0;
80 +}
81 +
82 +static int cns3xxx_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int level)
83 +{
84 +       gpio_line_set(gpio, level);
85 +       gpio_line_config(gpio, CNS3XXX_GPIO_OUT);
86 +       return 0;
87 +}
88 +
89 +static int cns3xxx_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
90 +{
91 +       return gpio_get_value(gpio);
92 +}
93 +
94 +static void cns3xxx_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value)
95 +{
96 +       gpio_set_value(gpio, value);
97 +}
98 +
99 +static struct gpio_chip cns3xxx_gpio_chip = {
100 +       .label                  = "CNS3XXX_GPIO_CHIP",
101 +       .direction_input        = cns3xxx_gpio_direction_input,
102 +       .direction_output       = cns3xxx_gpio_direction_output,
103 +       .get                    = cns3xxx_gpio_get_value,
104 +       .set                    = cns3xxx_gpio_set_value,
105 +       .base                   = 0,
106 +       .ngpio                  = 64,
107 +};
108 +
109 +void __init cns3xxx_common_init(void)
110  {
111         iotable_init(cns3xxx_io_desc, ARRAY_SIZE(cns3xxx_io_desc));
112  #ifdef CONFIG_CACHE_L2X0
113 @@ -95,6 +178,7 @@ void __init cns3xxx_map_io(void)
114  #ifdef CONFIG_LOCAL_TIMERS
115         twd_base = (void __iomem *) CNS3XXX_TC11MP_TWD_BASE_VIRT;
116  #endif
117 +       gpiochip_add(&cns3xxx_gpio_chip);
118  }
119  
120  /* used by entry-macro.S */
121 --- a/arch/arm/mach-cns3xxx/core.h
122 +++ b/arch/arm/mach-cns3xxx/core.h
123 @@ -13,7 +13,7 @@
124  
125  extern struct sys_timer cns3xxx_timer;
126  
127 -void __init cns3xxx_map_io(void);
128 +void __init cns3xxx_common_init(void);
129  void __init cns3xxx_init_irq(void);
130  void cns3xxx_power_off(void);
131  
132 --- a/arch/arm/mach-cns3xxx/laguna.c
133 +++ b/arch/arm/mach-cns3xxx/laguna.c
134 @@ -520,7 +520,7 @@ static struct map_desc laguna_io_desc[]
135  
136  static void __init laguna_map_io(void)
137  {
138 -       cns3xxx_map_io();
139 +       cns3xxx_common_init();
140         iotable_init(laguna_io_desc, ARRAY_SIZE(laguna_io_desc));
141  
142         laguna_early_serial_setup();