[cns3xxx]: update 3.1 patches
[openwrt.git] / target / linux / cns3xxx / patches-3.1 / 104-cns3xxx_gpio.patch
1 --- a/arch/arm/mach-cns3xxx/cns3420vb.c
2 +++ b/arch/arm/mach-cns3xxx/cns3420vb.c
3 @@ -215,7 +215,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/gic.h>
16  #include <asm/smp_twd.h>
17  #include <asm/hardware/cache-l2x0.h>
18 +#include <asm/gpio.h>
19  #include <mach/cns3xxx.h>
20  #include "core.h"
21  
22 @@ -75,12 +76,96 @@ 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  #ifdef CONFIG_LOCAL_TIMERS
112         twd_base = (void __iomem *) CNS3XXX_TC11MP_TWD_BASE_VIRT;
113  #endif
114         iotable_init(cns3xxx_io_desc, ARRAY_SIZE(cns3xxx_io_desc));
115 +
116 +       gpiochip_add(&cns3xxx_gpio_chip);
117  }
118  
119  /* used by entry-macro.S */
120 --- a/arch/arm/mach-cns3xxx/core.h
121 +++ b/arch/arm/mach-cns3xxx/core.h
122 @@ -20,7 +20,7 @@ void __init cns3xxx_l2x0_init(void);
123  static inline void cns3xxx_l2x0_init(void) {}
124  #endif /* CONFIG_CACHE_L2X0 */
125  
126 -void __init cns3xxx_map_io(void);
127 +void __init cns3xxx_common_init(void);
128  void __init cns3xxx_init_irq(void);
129  void cns3xxx_power_off(void);
130  
131 --- a/arch/arm/mach-cns3xxx/laguna.c
132 +++ b/arch/arm/mach-cns3xxx/laguna.c
133 @@ -611,7 +611,7 @@ static struct map_desc laguna_io_desc[]
134  
135  static void __init laguna_map_io(void)
136  {
137 -       cns3xxx_map_io();
138 +       cns3xxx_common_init();
139         iotable_init(laguna_io_desc, ARRAY_SIZE(laguna_io_desc));
140         laguna_early_serial_setup();
141  }