[ramips] add GPIO configuration feature
[openwrt/svn-archive/archive.git] / target / linux / ramips / files / arch / mips / ralink / common / gpio.c
1 /*
2 * Ralink SoC specific GPIO support
3 *
4 * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation.
9 */
10
11 #include <linux/init.h>
12 #include <linux/io.h>
13
14 #include <linux/gpio.h>
15
16 #include <ralink_soc.h>
17
18 #define GPIO0_REG_INT 0x00
19 #define GPIO0_REG_EDGE 0x04
20 #define GPIO0_REG_RENA 0x08
21 #define GPIO0_REG_FENA 0x0c
22 #define GPIO0_REG_DATA 0x20
23 #define GPIO0_REG_DIR 0x24
24 #define GPIO0_REG_POL 0x28
25 #define GPIO0_REG_SET 0x2c
26 #define GPIO0_REG_RESET 0x30
27 #define GPIO0_REG_TOGGLE 0x34
28
29 #define GPIO1_REG_INT 0x38
30 #define GPIO1_REG_EDGE 0x3c
31 #define GPIO1_REG_RENA 0x40
32 #define GPIO1_REG_FENA 0x44
33 #define GPIO1_REG_DATA 0x48
34 #define GPIO1_REG_DIR 0x4c
35 #define GPIO1_REG_POL 0x50
36 #define GPIO1_REG_SET 0x54
37 #define GPIO1_REG_RESET 0x58
38 #define GPIO1_REG_TOGGLE 0x5c
39
40 #define GPIO2_REG_INT 0x60
41 #define GPIO2_REG_EDGE 0x64
42 #define GPIO2_REG_RENA 0x68
43 #define GPIO2_REG_FENA 0x6c
44 #define GPIO2_REG_DATA 0x70
45 #define GPIO2_REG_DIR 0x74
46 #define GPIO2_REG_POL 0x78
47 #define GPIO2_REG_SET 0x7c
48 #define GPIO2_REG_RESET 0x80
49 #define GPIO2_REG_TOGGLE 0x84
50
51 enum ramips_pio_reg {
52 RAMIPS_GPIO_REG_INT, /* Interrupt status */
53 RAMIPS_GPIO_REG_EDGE,
54 RAMIPS_GPIO_REG_RENA,
55 RAMIPS_GPIO_REG_DATA,
56 RAMIPS_GPIO_REG_DIR, /* Direction, 0:in, 1: out */
57 RAMIPS_GPIO_REG_POL, /* Polarity, 0: normal, 1: invert */
58 RAMIPS_GPIO_REG_SET,
59 RAMIPS_GPIO_REG_RESET,
60 RAMIPS_GPIO_REG_TOGGLE,
61 RAMIPS_GPIO_REG_MAX
62 };
63
64 struct ramips_gpio_chip {
65 struct gpio_chip chip;
66 u8 regs[RAMIPS_GPIO_REG_MAX];
67 };
68
69 static void __iomem *ramips_gpio_base;
70
71 static inline struct ramips_gpio_chip *to_ramips_gpio(struct gpio_chip *chip)
72 {
73 struct ramips_gpio_chip *rg;
74
75 rg = container_of(chip, struct ramips_gpio_chip, chip);
76 return rg;
77 }
78
79 static inline void ramips_gpio_wr(struct ramips_gpio_chip *rg, u8 reg, u32 val)
80 {
81 __raw_writel(val, ramips_gpio_base + rg->regs[reg]);
82 }
83
84 static inline u32 ramips_gpio_rr(struct ramips_gpio_chip *rg, u8 reg)
85 {
86 return __raw_readl(ramips_gpio_base + rg->regs[reg]);
87 }
88
89 static int ramips_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
90 {
91 struct ramips_gpio_chip *rg = to_ramips_gpio(chip);
92 u32 t;
93
94 t = ramips_gpio_rr(rg, RAMIPS_GPIO_REG_DIR);
95 t &= ~(1 << offset);
96 ramips_gpio_wr(rg, RAMIPS_GPIO_REG_DIR, t);
97
98 return 0;
99 }
100
101 static int ramips_gpio_direction_output(struct gpio_chip *chip,
102 unsigned offset, int value)
103 {
104 struct ramips_gpio_chip *rg = to_ramips_gpio(chip);
105 u32 reg;
106 u32 t;
107
108 reg = (value) ? RAMIPS_GPIO_REG_SET : RAMIPS_GPIO_REG_RESET;
109 ramips_gpio_wr(rg, reg, 1 << offset);
110
111 t = ramips_gpio_rr(rg, RAMIPS_GPIO_REG_DIR);
112 t |= 1 << offset;
113 ramips_gpio_wr(rg, RAMIPS_GPIO_REG_DIR, t);
114
115 return 0;
116 }
117
118 static void ramips_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
119 {
120 struct ramips_gpio_chip *rg = to_ramips_gpio(chip);
121 u32 reg;
122
123 reg = (value) ? RAMIPS_GPIO_REG_SET : RAMIPS_GPIO_REG_RESET;
124 ramips_gpio_wr(rg, reg, 1 << offset);
125 }
126
127 static int ramips_gpio_get(struct gpio_chip *chip, unsigned offset)
128 {
129 struct ramips_gpio_chip *rg = to_ramips_gpio(chip);
130 u32 t;
131
132 t = ramips_gpio_rr(rg, RAMIPS_GPIO_REG_DATA);
133 return (t & (1 << offset));
134 }
135
136 static struct ramips_gpio_chip ramips_gpio_chip0 = {
137 .chip = {
138 .label = "ramips-gpio0",
139 .direction_input = ramips_gpio_direction_input,
140 .direction_output = ramips_gpio_direction_output,
141 .get = ramips_gpio_get,
142 .set = ramips_gpio_set,
143 .base = 0,
144 .ngpio = RALINK_SOC_GPIO0_COUNT,
145 },
146 .regs = {
147 [RAMIPS_GPIO_REG_INT] = GPIO0_REG_INT,
148 [RAMIPS_GPIO_REG_EDGE] = GPIO0_REG_EDGE,
149 [RAMIPS_GPIO_REG_RENA] = GPIO0_REG_RENA,
150 [RAMIPS_GPIO_REG_DATA] = GPIO0_REG_DATA,
151 [RAMIPS_GPIO_REG_DIR] = GPIO0_REG_DIR,
152 [RAMIPS_GPIO_REG_POL] = GPIO0_REG_POL,
153 [RAMIPS_GPIO_REG_SET] = GPIO0_REG_SET,
154 [RAMIPS_GPIO_REG_RESET] = GPIO0_REG_RESET,
155 [RAMIPS_GPIO_REG_TOGGLE] = GPIO0_REG_TOGGLE,
156 },
157 };
158
159 static struct ramips_gpio_chip ramips_gpio_chip1 = {
160 .chip = {
161 .label = "ramips-gpio1",
162 .direction_input = ramips_gpio_direction_input,
163 .direction_output = ramips_gpio_direction_output,
164 .get = ramips_gpio_get,
165 .set = ramips_gpio_set,
166 .base = 32,
167 .ngpio = RALINK_SOC_GPIO1_COUNT,
168 },
169 .regs = {
170 [RAMIPS_GPIO_REG_INT] = GPIO1_REG_INT,
171 [RAMIPS_GPIO_REG_EDGE] = GPIO1_REG_EDGE,
172 [RAMIPS_GPIO_REG_RENA] = GPIO1_REG_RENA,
173 [RAMIPS_GPIO_REG_DATA] = GPIO1_REG_DATA,
174 [RAMIPS_GPIO_REG_DIR] = GPIO1_REG_DIR,
175 [RAMIPS_GPIO_REG_POL] = GPIO1_REG_POL,
176 [RAMIPS_GPIO_REG_SET] = GPIO1_REG_SET,
177 [RAMIPS_GPIO_REG_RESET] = GPIO1_REG_RESET,
178 [RAMIPS_GPIO_REG_TOGGLE] = GPIO1_REG_TOGGLE,
179 },
180 };
181
182 static struct ramips_gpio_chip ramips_gpio_chip2 = {
183 .chip = {
184 .label = "ramips-gpio2",
185 .direction_input = ramips_gpio_direction_input,
186 .direction_output = ramips_gpio_direction_output,
187 .get = ramips_gpio_get,
188 .set = ramips_gpio_set,
189 .base = 64,
190 .ngpio = RALINK_SOC_GPIO2_COUNT,
191 },
192 .regs = {
193 [RAMIPS_GPIO_REG_INT] = GPIO2_REG_INT,
194 [RAMIPS_GPIO_REG_EDGE] = GPIO2_REG_EDGE,
195 [RAMIPS_GPIO_REG_RENA] = GPIO2_REG_RENA,
196 [RAMIPS_GPIO_REG_DATA] = GPIO2_REG_DATA,
197 [RAMIPS_GPIO_REG_DIR] = GPIO2_REG_DIR,
198 [RAMIPS_GPIO_REG_POL] = GPIO2_REG_POL,
199 [RAMIPS_GPIO_REG_SET] = GPIO2_REG_SET,
200 [RAMIPS_GPIO_REG_RESET] = GPIO2_REG_RESET,
201 [RAMIPS_GPIO_REG_TOGGLE] = GPIO2_REG_TOGGLE,
202 },
203 };
204
205 static __init void ramips_gpio_chip_add(struct ramips_gpio_chip *rg)
206 {
207 /* set polarity to low for all lines */
208 ramips_gpio_wr(rg, RAMIPS_GPIO_REG_POL, 0);
209
210 gpiochip_add(&rg->chip);
211 }
212
213 __init int ramips_gpio_init(void)
214 {
215 ramips_gpio_base = ioremap_nocache(RALINK_SOC_GPIO_BASE, PAGE_SIZE);
216
217 ramips_gpio_chip_add(&ramips_gpio_chip0);
218 ramips_gpio_chip_add(&ramips_gpio_chip1);
219 ramips_gpio_chip_add(&ramips_gpio_chip2);
220
221 return 0;
222 }