[cns3xxx]: preliminary 3.0 support
[openwrt/svn-archive/archive.git] / target / linux / cns3xxx / patches-3.0 / 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 @@ -609,7 +609,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();