aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/rb532/gpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/rb532/gpio.c')
-rw-r--r--arch/mips/rb532/gpio.c238
1 files changed, 166 insertions, 72 deletions
diff --git a/arch/mips/rb532/gpio.c b/arch/mips/rb532/gpio.c
index 00a1c7877bf4..76a7fd96d564 100644
--- a/arch/mips/rb532/gpio.c
+++ b/arch/mips/rb532/gpio.c
@@ -27,28 +27,31 @@
27 */ 27 */
28 28
29#include <linux/kernel.h> 29#include <linux/kernel.h>
30#include <linux/gpio.h>
31#include <linux/init.h> 30#include <linux/init.h>
32#include <linux/types.h> 31#include <linux/types.h>
33#include <linux/pci.h>
34#include <linux/spinlock.h> 32#include <linux/spinlock.h>
35#include <linux/io.h>
36#include <linux/platform_device.h> 33#include <linux/platform_device.h>
37 34#include <linux/gpio.h>
38#include <asm/addrspace.h>
39 35
40#include <asm/mach-rc32434/rb.h> 36#include <asm/mach-rc32434/rb.h>
41 37#include <asm/mach-rc32434/gpio.h>
42struct rb532_gpio_reg __iomem *rb532_gpio_reg0; 38
43EXPORT_SYMBOL(rb532_gpio_reg0); 39struct rb532_gpio_chip {
40 struct gpio_chip chip;
41 void __iomem *regbase;
42 void (*set_int_level)(struct gpio_chip *chip, unsigned offset, int value);
43 int (*get_int_level)(struct gpio_chip *chip, unsigned offset);
44 void (*set_int_status)(struct gpio_chip *chip, unsigned offset, int value);
45 int (*get_int_status)(struct gpio_chip *chip, unsigned offset);
46};
44 47
45struct mpmc_device dev3; 48struct mpmc_device dev3;
46 49
47static struct resource rb532_gpio_reg0_res[] = { 50static struct resource rb532_gpio_reg0_res[] = {
48 { 51 {
49 .name = "gpio_reg0", 52 .name = "gpio_reg0",
50 .start = (u32)(IDT434_REG_BASE + GPIOBASE), 53 .start = REGBASE + GPIOBASE,
51 .end = (u32)(IDT434_REG_BASE + GPIOBASE + sizeof(struct rb532_gpio_reg)), 54 .end = REGBASE + GPIOBASE + sizeof(struct rb532_gpio_reg) - 1,
52 .flags = IORESOURCE_MEM, 55 .flags = IORESOURCE_MEM,
53 } 56 }
54}; 57};
@@ -56,8 +59,8 @@ static struct resource rb532_gpio_reg0_res[] = {
56static struct resource rb532_dev3_ctl_res[] = { 59static struct resource rb532_dev3_ctl_res[] = {
57 { 60 {
58 .name = "dev3_ctl", 61 .name = "dev3_ctl",
59 .start = (u32)(IDT434_REG_BASE + DEV3BASE), 62 .start = REGBASE + DEV3BASE,
60 .end = (u32)(IDT434_REG_BASE + DEV3BASE + sizeof(struct dev_reg)), 63 .end = REGBASE + DEV3BASE + sizeof(struct dev_reg) - 1,
61 .flags = IORESOURCE_MEM, 64 .flags = IORESOURCE_MEM,
62 } 65 }
63}; 66};
@@ -70,7 +73,7 @@ void set_434_reg(unsigned reg_offs, unsigned bit, unsigned len, unsigned val)
70 73
71 spin_lock_irqsave(&dev3.lock, flags); 74 spin_lock_irqsave(&dev3.lock, flags);
72 75
73 data = *(volatile unsigned *) (IDT434_REG_BASE + reg_offs); 76 data = readl(IDT434_REG_BASE + reg_offs);
74 for (i = 0; i != len; ++i) { 77 for (i = 0; i != len; ++i) {
75 if (val & (1 << i)) 78 if (val & (1 << i))
76 data |= (1 << (i + bit)); 79 data |= (1 << (i + bit));
@@ -108,108 +111,199 @@ unsigned char get_latch_u5(void)
108} 111}
109EXPORT_SYMBOL(get_latch_u5); 112EXPORT_SYMBOL(get_latch_u5);
110 113
111int rb532_gpio_get_value(unsigned gpio) 114/*
115 * Return GPIO level */
116static int rb532_gpio_get(struct gpio_chip *chip, unsigned offset)
112{ 117{
113 return readl(&rb532_gpio_reg0->gpiod) & (1 << gpio); 118 u32 mask = 1 << offset;
119 struct rb532_gpio_chip *gpch;
120
121 gpch = container_of(chip, struct rb532_gpio_chip, chip);
122 return readl(gpch->regbase + GPIOD) & mask;
114} 123}
115EXPORT_SYMBOL(rb532_gpio_get_value);
116 124
117void rb532_gpio_set_value(unsigned gpio, int value) 125/*
126 * Set output GPIO level
127 */
128static void rb532_gpio_set(struct gpio_chip *chip,
129 unsigned offset, int value)
118{ 130{
119 unsigned tmp; 131 unsigned long flags;
132 u32 mask = 1 << offset;
133 u32 tmp;
134 struct rb532_gpio_chip *gpch;
135 void __iomem *gpvr;
120 136
121 tmp = readl(&rb532_gpio_reg0->gpiod) & ~(1 << gpio); 137 gpch = container_of(chip, struct rb532_gpio_chip, chip);
122 if (value) 138 gpvr = gpch->regbase + GPIOD;
123 tmp |= 1 << gpio;
124 139
125 writel(tmp, (void *)&rb532_gpio_reg0->gpiod); 140 local_irq_save(flags);
141 tmp = readl(gpvr);
142 if (value)
143 tmp |= mask;
144 else
145 tmp &= ~mask;
146 writel(tmp, gpvr);
147 local_irq_restore(flags);
126} 148}
127EXPORT_SYMBOL(rb532_gpio_set_value);
128 149
129int rb532_gpio_direction_input(unsigned gpio) 150/*
151 * Set GPIO direction to input
152 */
153static int rb532_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
130{ 154{
131 writel(readl(&rb532_gpio_reg0->gpiocfg) & ~(1 << gpio), 155 unsigned long flags;
132 (void *)&rb532_gpio_reg0->gpiocfg); 156 u32 mask = 1 << offset;
157 u32 value;
158 struct rb532_gpio_chip *gpch;
159 void __iomem *gpdr;
133 160
134 return 0; 161 gpch = container_of(chip, struct rb532_gpio_chip, chip);
135} 162 gpdr = gpch->regbase + GPIOCFG;
136EXPORT_SYMBOL(rb532_gpio_direction_input);
137 163
138int rb532_gpio_direction_output(unsigned gpio, int value) 164 local_irq_save(flags);
139{ 165 value = readl(gpdr);
140 gpio_set_value(gpio, value); 166 value &= ~mask;
141 writel(readl(&rb532_gpio_reg0->gpiocfg) | (1 << gpio), 167 writel(value, gpdr);
142 (void *)&rb532_gpio_reg0->gpiocfg); 168 local_irq_restore(flags);
143 169
144 return 0; 170 return 0;
145} 171}
146EXPORT_SYMBOL(rb532_gpio_direction_output);
147 172
148void rb532_gpio_set_int_level(unsigned gpio, int value) 173/*
174 * Set GPIO direction to output
175 */
176static int rb532_gpio_direction_output(struct gpio_chip *chip,
177 unsigned offset, int value)
149{ 178{
150 unsigned tmp; 179 unsigned long flags;
180 u32 mask = 1 << offset;
181 u32 tmp;
182 struct rb532_gpio_chip *gpch;
183 void __iomem *gpdr;
184
185 gpch = container_of(chip, struct rb532_gpio_chip, chip);
186 writel(mask, gpch->regbase + GPIOD);
187 gpdr = gpch->regbase + GPIOCFG;
188
189 local_irq_save(flags);
190 tmp = readl(gpdr);
191 tmp |= mask;
192 writel(tmp, gpdr);
193 local_irq_restore(flags);
151 194
152 tmp = readl(&rb532_gpio_reg0->gpioilevel) & ~(1 << gpio); 195 return 0;
153 if (value)
154 tmp |= 1 << gpio;
155 writel(tmp, (void *)&rb532_gpio_reg0->gpioilevel);
156} 196}
157EXPORT_SYMBOL(rb532_gpio_set_int_level);
158 197
159int rb532_gpio_get_int_level(unsigned gpio) 198/*
199 * Set the GPIO interrupt level
200 */
201static void rb532_gpio_set_int_level(struct gpio_chip *chip,
202 unsigned offset, int value)
160{ 203{
161 return readl(&rb532_gpio_reg0->gpioilevel) & (1 << gpio); 204 unsigned long flags;
162} 205 u32 mask = 1 << offset;
163EXPORT_SYMBOL(rb532_gpio_get_int_level); 206 u32 tmp;
207 struct rb532_gpio_chip *gpch;
208 void __iomem *gpil;
164 209
165void rb532_gpio_set_int_status(unsigned gpio, int value) 210 gpch = container_of(chip, struct rb532_gpio_chip, chip);
166{ 211 gpil = gpch->regbase + GPIOILEVEL;
167 unsigned tmp;
168 212
169 tmp = readl(&rb532_gpio_reg0->gpioistat); 213 local_irq_save(flags);
214 tmp = readl(gpil);
170 if (value) 215 if (value)
171 tmp |= 1 << gpio; 216 tmp |= mask;
172 writel(tmp, (void *)&rb532_gpio_reg0->gpioistat); 217 else
218 tmp &= ~mask;
219 writel(tmp, gpil);
220 local_irq_restore(flags);
173} 221}
174EXPORT_SYMBOL(rb532_gpio_set_int_status);
175 222
176int rb532_gpio_get_int_status(unsigned gpio) 223/*
224 * Get the GPIO interrupt level
225 */
226static int rb532_gpio_get_int_level(struct gpio_chip *chip, unsigned offset)
177{ 227{
178 return readl(&rb532_gpio_reg0->gpioistat) & (1 << gpio); 228 u32 mask = 1 << offset;
229 struct rb532_gpio_chip *gpch;
230
231 gpch = container_of(chip, struct rb532_gpio_chip, chip);
232 return readl(gpch->regbase + GPIOILEVEL) & mask;
179} 233}
180EXPORT_SYMBOL(rb532_gpio_get_int_status);
181 234
182void rb532_gpio_set_func(unsigned gpio, int value) 235/*
236 * Set the GPIO interrupt status
237 */
238static void rb532_gpio_set_int_status(struct gpio_chip *chip,
239 unsigned offset, int value)
183{ 240{
184 unsigned tmp; 241 unsigned long flags;
242 u32 mask = 1 << offset;
243 u32 tmp;
244 struct rb532_gpio_chip *gpch;
245 void __iomem *gpis;
246
247 gpch = container_of(chip, struct rb532_gpio_chip, chip);
248 gpis = gpch->regbase + GPIOISTAT;
185 249
186 tmp = readl(&rb532_gpio_reg0->gpiofunc); 250 local_irq_save(flags);
251 tmp = readl(gpis);
187 if (value) 252 if (value)
188 tmp |= 1 << gpio; 253 tmp |= mask;
189 writel(tmp, (void *)&rb532_gpio_reg0->gpiofunc); 254 else
255 tmp &= ~mask;
256 writel(tmp, gpis);
257 local_irq_restore(flags);
190} 258}
191EXPORT_SYMBOL(rb532_gpio_set_func);
192 259
193int rb532_gpio_get_func(unsigned gpio) 260/*
261 * Get the GPIO interrupt status
262 */
263static int rb532_gpio_get_int_status(struct gpio_chip *chip, unsigned offset)
194{ 264{
195 return readl(&rb532_gpio_reg0->gpiofunc) & (1 << gpio); 265 u32 mask = 1 << offset;
266 struct rb532_gpio_chip *gpch;
267
268 gpch = container_of(chip, struct rb532_gpio_chip, chip);
269 return readl(gpch->regbase + GPIOISTAT) & mask;
196} 270}
197EXPORT_SYMBOL(rb532_gpio_get_func); 271
272static struct rb532_gpio_chip rb532_gpio_chip[] = {
273 [0] = {
274 .chip = {
275 .label = "gpio0",
276 .direction_input = rb532_gpio_direction_input,
277 .direction_output = rb532_gpio_direction_output,
278 .get = rb532_gpio_get,
279 .set = rb532_gpio_set,
280 .base = 0,
281 .ngpio = 32,
282 },
283 .get_int_level = rb532_gpio_get_int_level,
284 .set_int_level = rb532_gpio_set_int_level,
285 .get_int_status = rb532_gpio_get_int_status,
286 .set_int_status = rb532_gpio_set_int_status,
287 },
288};
198 289
199int __init rb532_gpio_init(void) 290int __init rb532_gpio_init(void)
200{ 291{
201 rb532_gpio_reg0 = ioremap_nocache(rb532_gpio_reg0_res[0].start, 292 struct resource *r;
202 rb532_gpio_reg0_res[0].end -
203 rb532_gpio_reg0_res[0].start);
204 293
205 if (!rb532_gpio_reg0) { 294 r = rb532_gpio_reg0_res;
295 rb532_gpio_chip->regbase = ioremap_nocache(r->start, r->end - r->start);
296
297 if (!rb532_gpio_chip->regbase) {
206 printk(KERN_ERR "rb532: cannot remap GPIO register 0\n"); 298 printk(KERN_ERR "rb532: cannot remap GPIO register 0\n");
207 return -ENXIO; 299 return -ENXIO;
208 } 300 }
209 301
210 dev3.base = ioremap_nocache(rb532_dev3_ctl_res[0].start, 302 /* Register our GPIO chip */
211 rb532_dev3_ctl_res[0].end - 303 gpiochip_add(&rb532_gpio_chip->chip);
212 rb532_dev3_ctl_res[0].start); 304
305 r = rb532_dev3_ctl_res;
306 dev3.base = ioremap_nocache(r->start, r->end - r->start);
213 307
214 if (!dev3.base) { 308 if (!dev3.base) {
215 printk(KERN_ERR "rb532: cannot remap device controller 3\n"); 309 printk(KERN_ERR "rb532: cannot remap device controller 3\n");