diff options
Diffstat (limited to 'drivers/mfd/asic3.c')
-rw-r--r-- | drivers/mfd/asic3.c | 388 |
1 files changed, 223 insertions, 165 deletions
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index ef8a492766a7..3b870e7fb3e1 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c | |||
@@ -9,7 +9,7 @@ | |||
9 | * | 9 | * |
10 | * Copyright 2001 Compaq Computer Corporation. | 10 | * Copyright 2001 Compaq Computer Corporation. |
11 | * Copyright 2004-2005 Phil Blundell | 11 | * Copyright 2004-2005 Phil Blundell |
12 | * Copyright 2007 OpenedHand Ltd. | 12 | * Copyright 2007-2008 OpenedHand Ltd. |
13 | * | 13 | * |
14 | * Authors: Phil Blundell <pb@handhelds.org>, | 14 | * Authors: Phil Blundell <pb@handhelds.org>, |
15 | * Samuel Ortiz <sameo@openedhand.com> | 15 | * Samuel Ortiz <sameo@openedhand.com> |
@@ -19,12 +19,26 @@ | |||
19 | #include <linux/version.h> | 19 | #include <linux/version.h> |
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
22 | #include <linux/gpio.h> | ||
22 | #include <linux/io.h> | 23 | #include <linux/io.h> |
23 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
24 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
25 | 26 | ||
26 | #include <linux/mfd/asic3.h> | 27 | #include <linux/mfd/asic3.h> |
27 | 28 | ||
29 | struct asic3 { | ||
30 | void __iomem *mapping; | ||
31 | unsigned int bus_shift; | ||
32 | unsigned int irq_nr; | ||
33 | unsigned int irq_base; | ||
34 | spinlock_t lock; | ||
35 | u16 irq_bothedge[4]; | ||
36 | struct gpio_chip gpio; | ||
37 | struct device *dev; | ||
38 | }; | ||
39 | |||
40 | static int asic3_gpio_get(struct gpio_chip *chip, unsigned offset); | ||
41 | |||
28 | static inline void asic3_write_register(struct asic3 *asic, | 42 | static inline void asic3_write_register(struct asic3 *asic, |
29 | unsigned int reg, u32 value) | 43 | unsigned int reg, u32 value) |
30 | { | 44 | { |
@@ -41,8 +55,8 @@ static inline u32 asic3_read_register(struct asic3 *asic, | |||
41 | 55 | ||
42 | /* IRQs */ | 56 | /* IRQs */ |
43 | #define MAX_ASIC_ISR_LOOPS 20 | 57 | #define MAX_ASIC_ISR_LOOPS 20 |
44 | #define ASIC3_GPIO_Base_INCR \ | 58 | #define ASIC3_GPIO_BASE_INCR \ |
45 | (ASIC3_GPIO_B_Base - ASIC3_GPIO_A_Base) | 59 | (ASIC3_GPIO_B_BASE - ASIC3_GPIO_A_BASE) |
46 | 60 | ||
47 | static void asic3_irq_flip_edge(struct asic3 *asic, | 61 | static void asic3_irq_flip_edge(struct asic3 *asic, |
48 | u32 base, int bit) | 62 | u32 base, int bit) |
@@ -52,10 +66,10 @@ static void asic3_irq_flip_edge(struct asic3 *asic, | |||
52 | 66 | ||
53 | spin_lock_irqsave(&asic->lock, flags); | 67 | spin_lock_irqsave(&asic->lock, flags); |
54 | edge = asic3_read_register(asic, | 68 | edge = asic3_read_register(asic, |
55 | base + ASIC3_GPIO_EdgeTrigger); | 69 | base + ASIC3_GPIO_EDGE_TRIGGER); |
56 | edge ^= bit; | 70 | edge ^= bit; |
57 | asic3_write_register(asic, | 71 | asic3_write_register(asic, |
58 | base + ASIC3_GPIO_EdgeTrigger, edge); | 72 | base + ASIC3_GPIO_EDGE_TRIGGER, edge); |
59 | spin_unlock_irqrestore(&asic->lock, flags); | 73 | spin_unlock_irqrestore(&asic->lock, flags); |
60 | } | 74 | } |
61 | 75 | ||
@@ -75,7 +89,7 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc) | |||
75 | 89 | ||
76 | spin_lock_irqsave(&asic->lock, flags); | 90 | spin_lock_irqsave(&asic->lock, flags); |
77 | status = asic3_read_register(asic, | 91 | status = asic3_read_register(asic, |
78 | ASIC3_OFFSET(INTR, PIntStat)); | 92 | ASIC3_OFFSET(INTR, P_INT_STAT)); |
79 | spin_unlock_irqrestore(&asic->lock, flags); | 93 | spin_unlock_irqrestore(&asic->lock, flags); |
80 | 94 | ||
81 | /* Check all ten register bits */ | 95 | /* Check all ten register bits */ |
@@ -87,17 +101,17 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc) | |||
87 | if (status & (1 << bank)) { | 101 | if (status & (1 << bank)) { |
88 | unsigned long base, istat; | 102 | unsigned long base, istat; |
89 | 103 | ||
90 | base = ASIC3_GPIO_A_Base | 104 | base = ASIC3_GPIO_A_BASE |
91 | + bank * ASIC3_GPIO_Base_INCR; | 105 | + bank * ASIC3_GPIO_BASE_INCR; |
92 | 106 | ||
93 | spin_lock_irqsave(&asic->lock, flags); | 107 | spin_lock_irqsave(&asic->lock, flags); |
94 | istat = asic3_read_register(asic, | 108 | istat = asic3_read_register(asic, |
95 | base + | 109 | base + |
96 | ASIC3_GPIO_IntStatus); | 110 | ASIC3_GPIO_INT_STATUS); |
97 | /* Clearing IntStatus */ | 111 | /* Clearing IntStatus */ |
98 | asic3_write_register(asic, | 112 | asic3_write_register(asic, |
99 | base + | 113 | base + |
100 | ASIC3_GPIO_IntStatus, 0); | 114 | ASIC3_GPIO_INT_STATUS, 0); |
101 | spin_unlock_irqrestore(&asic->lock, flags); | 115 | spin_unlock_irqrestore(&asic->lock, flags); |
102 | 116 | ||
103 | for (i = 0; i < ASIC3_GPIOS_PER_BANK; i++) { | 117 | for (i = 0; i < ASIC3_GPIOS_PER_BANK; i++) { |
@@ -123,7 +137,7 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc) | |||
123 | for (i = ASIC3_NUM_GPIOS; i < ASIC3_NR_IRQS; i++) { | 137 | for (i = ASIC3_NUM_GPIOS; i < ASIC3_NR_IRQS; i++) { |
124 | /* They start at bit 4 and go up */ | 138 | /* They start at bit 4 and go up */ |
125 | if (status & (1 << (i - ASIC3_NUM_GPIOS + 4))) { | 139 | if (status & (1 << (i - ASIC3_NUM_GPIOS + 4))) { |
126 | desc = irq_desc + + i; | 140 | desc = irq_desc + asic->irq_base + i; |
127 | desc->handle_irq(asic->irq_base + i, | 141 | desc->handle_irq(asic->irq_base + i, |
128 | desc); | 142 | desc); |
129 | } | 143 | } |
@@ -131,8 +145,7 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc) | |||
131 | } | 145 | } |
132 | 146 | ||
133 | if (iter >= MAX_ASIC_ISR_LOOPS) | 147 | if (iter >= MAX_ASIC_ISR_LOOPS) |
134 | printk(KERN_ERR "%s: interrupt processing overrun\n", | 148 | dev_err(asic->dev, "interrupt processing overrun\n"); |
135 | __func__); | ||
136 | } | 149 | } |
137 | 150 | ||
138 | static inline int asic3_irq_to_bank(struct asic3 *asic, int irq) | 151 | static inline int asic3_irq_to_bank(struct asic3 *asic, int irq) |
@@ -141,7 +154,7 @@ static inline int asic3_irq_to_bank(struct asic3 *asic, int irq) | |||
141 | 154 | ||
142 | n = (irq - asic->irq_base) >> 4; | 155 | n = (irq - asic->irq_base) >> 4; |
143 | 156 | ||
144 | return (n * (ASIC3_GPIO_B_Base - ASIC3_GPIO_A_Base)); | 157 | return (n * (ASIC3_GPIO_B_BASE - ASIC3_GPIO_A_BASE)); |
145 | } | 158 | } |
146 | 159 | ||
147 | static inline int asic3_irq_to_index(struct asic3 *asic, int irq) | 160 | static inline int asic3_irq_to_index(struct asic3 *asic, int irq) |
@@ -159,9 +172,9 @@ static void asic3_mask_gpio_irq(unsigned int irq) | |||
159 | index = asic3_irq_to_index(asic, irq); | 172 | index = asic3_irq_to_index(asic, irq); |
160 | 173 | ||
161 | spin_lock_irqsave(&asic->lock, flags); | 174 | spin_lock_irqsave(&asic->lock, flags); |
162 | val = asic3_read_register(asic, bank + ASIC3_GPIO_Mask); | 175 | val = asic3_read_register(asic, bank + ASIC3_GPIO_MASK); |
163 | val |= 1 << index; | 176 | val |= 1 << index; |
164 | asic3_write_register(asic, bank + ASIC3_GPIO_Mask, val); | 177 | asic3_write_register(asic, bank + ASIC3_GPIO_MASK, val); |
165 | spin_unlock_irqrestore(&asic->lock, flags); | 178 | spin_unlock_irqrestore(&asic->lock, flags); |
166 | } | 179 | } |
167 | 180 | ||
@@ -173,15 +186,15 @@ static void asic3_mask_irq(unsigned int irq) | |||
173 | 186 | ||
174 | spin_lock_irqsave(&asic->lock, flags); | 187 | spin_lock_irqsave(&asic->lock, flags); |
175 | regval = asic3_read_register(asic, | 188 | regval = asic3_read_register(asic, |
176 | ASIC3_INTR_Base + | 189 | ASIC3_INTR_BASE + |
177 | ASIC3_INTR_IntMask); | 190 | ASIC3_INTR_INT_MASK); |
178 | 191 | ||
179 | regval &= ~(ASIC3_INTMASK_MASK0 << | 192 | regval &= ~(ASIC3_INTMASK_MASK0 << |
180 | (irq - (asic->irq_base + ASIC3_NUM_GPIOS))); | 193 | (irq - (asic->irq_base + ASIC3_NUM_GPIOS))); |
181 | 194 | ||
182 | asic3_write_register(asic, | 195 | asic3_write_register(asic, |
183 | ASIC3_INTR_Base + | 196 | ASIC3_INTR_BASE + |
184 | ASIC3_INTR_IntMask, | 197 | ASIC3_INTR_INT_MASK, |
185 | regval); | 198 | regval); |
186 | spin_unlock_irqrestore(&asic->lock, flags); | 199 | spin_unlock_irqrestore(&asic->lock, flags); |
187 | } | 200 | } |
@@ -196,9 +209,9 @@ static void asic3_unmask_gpio_irq(unsigned int irq) | |||
196 | index = asic3_irq_to_index(asic, irq); | 209 | index = asic3_irq_to_index(asic, irq); |
197 | 210 | ||
198 | spin_lock_irqsave(&asic->lock, flags); | 211 | spin_lock_irqsave(&asic->lock, flags); |
199 | val = asic3_read_register(asic, bank + ASIC3_GPIO_Mask); | 212 | val = asic3_read_register(asic, bank + ASIC3_GPIO_MASK); |
200 | val &= ~(1 << index); | 213 | val &= ~(1 << index); |
201 | asic3_write_register(asic, bank + ASIC3_GPIO_Mask, val); | 214 | asic3_write_register(asic, bank + ASIC3_GPIO_MASK, val); |
202 | spin_unlock_irqrestore(&asic->lock, flags); | 215 | spin_unlock_irqrestore(&asic->lock, flags); |
203 | } | 216 | } |
204 | 217 | ||
@@ -210,15 +223,15 @@ static void asic3_unmask_irq(unsigned int irq) | |||
210 | 223 | ||
211 | spin_lock_irqsave(&asic->lock, flags); | 224 | spin_lock_irqsave(&asic->lock, flags); |
212 | regval = asic3_read_register(asic, | 225 | regval = asic3_read_register(asic, |
213 | ASIC3_INTR_Base + | 226 | ASIC3_INTR_BASE + |
214 | ASIC3_INTR_IntMask); | 227 | ASIC3_INTR_INT_MASK); |
215 | 228 | ||
216 | regval |= (ASIC3_INTMASK_MASK0 << | 229 | regval |= (ASIC3_INTMASK_MASK0 << |
217 | (irq - (asic->irq_base + ASIC3_NUM_GPIOS))); | 230 | (irq - (asic->irq_base + ASIC3_NUM_GPIOS))); |
218 | 231 | ||
219 | asic3_write_register(asic, | 232 | asic3_write_register(asic, |
220 | ASIC3_INTR_Base + | 233 | ASIC3_INTR_BASE + |
221 | ASIC3_INTR_IntMask, | 234 | ASIC3_INTR_INT_MASK, |
222 | regval); | 235 | regval); |
223 | spin_unlock_irqrestore(&asic->lock, flags); | 236 | spin_unlock_irqrestore(&asic->lock, flags); |
224 | } | 237 | } |
@@ -236,11 +249,11 @@ static int asic3_gpio_irq_type(unsigned int irq, unsigned int type) | |||
236 | 249 | ||
237 | spin_lock_irqsave(&asic->lock, flags); | 250 | spin_lock_irqsave(&asic->lock, flags); |
238 | level = asic3_read_register(asic, | 251 | level = asic3_read_register(asic, |
239 | bank + ASIC3_GPIO_LevelTrigger); | 252 | bank + ASIC3_GPIO_LEVEL_TRIGGER); |
240 | edge = asic3_read_register(asic, | 253 | edge = asic3_read_register(asic, |
241 | bank + ASIC3_GPIO_EdgeTrigger); | 254 | bank + ASIC3_GPIO_EDGE_TRIGGER); |
242 | trigger = asic3_read_register(asic, | 255 | trigger = asic3_read_register(asic, |
243 | bank + ASIC3_GPIO_TriggerType); | 256 | bank + ASIC3_GPIO_TRIGGER_TYPE); |
244 | asic->irq_bothedge[(irq - asic->irq_base) >> 4] &= ~bit; | 257 | asic->irq_bothedge[(irq - asic->irq_base) >> 4] &= ~bit; |
245 | 258 | ||
246 | if (type == IRQT_RISING) { | 259 | if (type == IRQT_RISING) { |
@@ -251,7 +264,7 @@ static int asic3_gpio_irq_type(unsigned int irq, unsigned int type) | |||
251 | edge &= ~bit; | 264 | edge &= ~bit; |
252 | } else if (type == IRQT_BOTHEDGE) { | 265 | } else if (type == IRQT_BOTHEDGE) { |
253 | trigger |= bit; | 266 | trigger |= bit; |
254 | if (asic3_gpio_get_value(asic, irq - asic->irq_base)) | 267 | if (asic3_gpio_get(&asic->gpio, irq - asic->irq_base)) |
255 | edge &= ~bit; | 268 | edge &= ~bit; |
256 | else | 269 | else |
257 | edge |= bit; | 270 | edge |= bit; |
@@ -268,13 +281,13 @@ static int asic3_gpio_irq_type(unsigned int irq, unsigned int type) | |||
268 | * be careful to not unmask them if mask was also called. | 281 | * be careful to not unmask them if mask was also called. |
269 | * Probably need internal state for mask. | 282 | * Probably need internal state for mask. |
270 | */ | 283 | */ |
271 | printk(KERN_NOTICE "asic3: irq type not changed.\n"); | 284 | dev_notice(asic->dev, "irq type not changed\n"); |
272 | } | 285 | } |
273 | asic3_write_register(asic, bank + ASIC3_GPIO_LevelTrigger, | 286 | asic3_write_register(asic, bank + ASIC3_GPIO_LEVEL_TRIGGER, |
274 | level); | 287 | level); |
275 | asic3_write_register(asic, bank + ASIC3_GPIO_EdgeTrigger, | 288 | asic3_write_register(asic, bank + ASIC3_GPIO_EDGE_TRIGGER, |
276 | edge); | 289 | edge); |
277 | asic3_write_register(asic, bank + ASIC3_GPIO_TriggerType, | 290 | asic3_write_register(asic, bank + ASIC3_GPIO_TRIGGER_TYPE, |
278 | trigger); | 291 | trigger); |
279 | spin_unlock_irqrestore(&asic->lock, flags); | 292 | spin_unlock_irqrestore(&asic->lock, flags); |
280 | return 0; | 293 | return 0; |
@@ -295,11 +308,12 @@ static struct irq_chip asic3_irq_chip = { | |||
295 | .unmask = asic3_unmask_irq, | 308 | .unmask = asic3_unmask_irq, |
296 | }; | 309 | }; |
297 | 310 | ||
298 | static int asic3_irq_probe(struct platform_device *pdev) | 311 | static int __init asic3_irq_probe(struct platform_device *pdev) |
299 | { | 312 | { |
300 | struct asic3 *asic = platform_get_drvdata(pdev); | 313 | struct asic3 *asic = platform_get_drvdata(pdev); |
301 | unsigned long clksel = 0; | 314 | unsigned long clksel = 0; |
302 | unsigned int irq, irq_base; | 315 | unsigned int irq, irq_base; |
316 | int map_size; | ||
303 | 317 | ||
304 | asic->irq_nr = platform_get_irq(pdev, 0); | 318 | asic->irq_nr = platform_get_irq(pdev, 0); |
305 | if (asic->irq_nr < 0) | 319 | if (asic->irq_nr < 0) |
@@ -323,7 +337,7 @@ static int asic3_irq_probe(struct platform_device *pdev) | |||
323 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | 337 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); |
324 | } | 338 | } |
325 | 339 | ||
326 | asic3_write_register(asic, ASIC3_OFFSET(INTR, IntMask), | 340 | asic3_write_register(asic, ASIC3_OFFSET(INTR, INT_MASK), |
327 | ASIC3_INTMASK_GINTMASK); | 341 | ASIC3_INTMASK_GINTMASK); |
328 | 342 | ||
329 | set_irq_chained_handler(asic->irq_nr, asic3_irq_demux); | 343 | set_irq_chained_handler(asic->irq_nr, asic3_irq_demux); |
@@ -350,149 +364,182 @@ static void asic3_irq_remove(struct platform_device *pdev) | |||
350 | } | 364 | } |
351 | 365 | ||
352 | /* GPIOs */ | 366 | /* GPIOs */ |
353 | static inline u32 asic3_get_gpio(struct asic3 *asic, unsigned int base, | 367 | static int asic3_gpio_direction(struct gpio_chip *chip, |
354 | unsigned int function) | 368 | unsigned offset, int out) |
355 | { | ||
356 | return asic3_read_register(asic, base + function); | ||
357 | } | ||
358 | |||
359 | static void asic3_set_gpio(struct asic3 *asic, unsigned int base, | ||
360 | unsigned int function, u32 bits, u32 val) | ||
361 | { | 369 | { |
370 | u32 mask = ASIC3_GPIO_TO_MASK(offset), out_reg; | ||
371 | unsigned int gpio_base; | ||
362 | unsigned long flags; | 372 | unsigned long flags; |
373 | struct asic3 *asic; | ||
374 | |||
375 | asic = container_of(chip, struct asic3, gpio); | ||
376 | gpio_base = ASIC3_GPIO_TO_BASE(offset); | ||
377 | |||
378 | if (gpio_base > ASIC3_GPIO_D_BASE) { | ||
379 | dev_err(asic->dev, "Invalid base (0x%x) for gpio %d\n", | ||
380 | gpio_base, offset); | ||
381 | return -EINVAL; | ||
382 | } | ||
363 | 383 | ||
364 | spin_lock_irqsave(&asic->lock, flags); | 384 | spin_lock_irqsave(&asic->lock, flags); |
365 | val |= (asic3_read_register(asic, base + function) & ~bits); | ||
366 | 385 | ||
367 | asic3_write_register(asic, base + function, val); | 386 | out_reg = asic3_read_register(asic, gpio_base + ASIC3_GPIO_DIRECTION); |
387 | |||
388 | /* Input is 0, Output is 1 */ | ||
389 | if (out) | ||
390 | out_reg |= mask; | ||
391 | else | ||
392 | out_reg &= ~mask; | ||
393 | |||
394 | asic3_write_register(asic, gpio_base + ASIC3_GPIO_DIRECTION, out_reg); | ||
395 | |||
368 | spin_unlock_irqrestore(&asic->lock, flags); | 396 | spin_unlock_irqrestore(&asic->lock, flags); |
397 | |||
398 | return 0; | ||
399 | |||
400 | } | ||
401 | |||
402 | static int asic3_gpio_direction_input(struct gpio_chip *chip, | ||
403 | unsigned offset) | ||
404 | { | ||
405 | return asic3_gpio_direction(chip, offset, 0); | ||
406 | } | ||
407 | |||
408 | static int asic3_gpio_direction_output(struct gpio_chip *chip, | ||
409 | unsigned offset, int value) | ||
410 | { | ||
411 | return asic3_gpio_direction(chip, offset, 1); | ||
369 | } | 412 | } |
370 | 413 | ||
371 | #define asic3_get_gpio_a(asic, fn) \ | 414 | static int asic3_gpio_get(struct gpio_chip *chip, |
372 | asic3_get_gpio(asic, ASIC3_GPIO_A_Base, ASIC3_GPIO_##fn) | 415 | unsigned offset) |
373 | #define asic3_get_gpio_b(asic, fn) \ | ||
374 | asic3_get_gpio(asic, ASIC3_GPIO_B_Base, ASIC3_GPIO_##fn) | ||
375 | #define asic3_get_gpio_c(asic, fn) \ | ||
376 | asic3_get_gpio(asic, ASIC3_GPIO_C_Base, ASIC3_GPIO_##fn) | ||
377 | #define asic3_get_gpio_d(asic, fn) \ | ||
378 | asic3_get_gpio(asic, ASIC3_GPIO_D_Base, ASIC3_GPIO_##fn) | ||
379 | |||
380 | #define asic3_set_gpio_a(asic, fn, bits, val) \ | ||
381 | asic3_set_gpio(asic, ASIC3_GPIO_A_Base, ASIC3_GPIO_##fn, bits, val) | ||
382 | #define asic3_set_gpio_b(asic, fn, bits, val) \ | ||
383 | asic3_set_gpio(asic, ASIC3_GPIO_B_Base, ASIC3_GPIO_##fn, bits, val) | ||
384 | #define asic3_set_gpio_c(asic, fn, bits, val) \ | ||
385 | asic3_set_gpio(asic, ASIC3_GPIO_C_Base, ASIC3_GPIO_##fn, bits, val) | ||
386 | #define asic3_set_gpio_d(asic, fn, bits, val) \ | ||
387 | asic3_set_gpio(asic, ASIC3_GPIO_D_Base, ASIC3_GPIO_##fn, bits, val) | ||
388 | |||
389 | #define asic3_set_gpio_banks(asic, fn, bits, pdata, field) \ | ||
390 | do { \ | ||
391 | asic3_set_gpio_a((asic), fn, (bits), (pdata)->gpio_a.field); \ | ||
392 | asic3_set_gpio_b((asic), fn, (bits), (pdata)->gpio_b.field); \ | ||
393 | asic3_set_gpio_c((asic), fn, (bits), (pdata)->gpio_c.field); \ | ||
394 | asic3_set_gpio_d((asic), fn, (bits), (pdata)->gpio_d.field); \ | ||
395 | } while (0) | ||
396 | |||
397 | int asic3_gpio_get_value(struct asic3 *asic, unsigned gpio) | ||
398 | { | 416 | { |
399 | u32 mask = ASIC3_GPIO_bit(gpio); | 417 | unsigned int gpio_base; |
400 | 418 | u32 mask = ASIC3_GPIO_TO_MASK(offset); | |
401 | switch (gpio >> 4) { | 419 | struct asic3 *asic; |
402 | case ASIC3_GPIO_BANK_A: | 420 | |
403 | return asic3_get_gpio_a(asic, Status) & mask; | 421 | asic = container_of(chip, struct asic3, gpio); |
404 | case ASIC3_GPIO_BANK_B: | 422 | gpio_base = ASIC3_GPIO_TO_BASE(offset); |
405 | return asic3_get_gpio_b(asic, Status) & mask; | 423 | |
406 | case ASIC3_GPIO_BANK_C: | 424 | if (gpio_base > ASIC3_GPIO_D_BASE) { |
407 | return asic3_get_gpio_c(asic, Status) & mask; | 425 | dev_err(asic->dev, "Invalid base (0x%x) for gpio %d\n", |
408 | case ASIC3_GPIO_BANK_D: | 426 | gpio_base, offset); |
409 | return asic3_get_gpio_d(asic, Status) & mask; | ||
410 | default: | ||
411 | printk(KERN_ERR "%s: invalid GPIO value 0x%x", | ||
412 | __func__, gpio); | ||
413 | return -EINVAL; | 427 | return -EINVAL; |
414 | } | 428 | } |
429 | |||
430 | return asic3_read_register(asic, gpio_base + ASIC3_GPIO_STATUS) & mask; | ||
415 | } | 431 | } |
416 | EXPORT_SYMBOL(asic3_gpio_get_value); | ||
417 | 432 | ||
418 | void asic3_gpio_set_value(struct asic3 *asic, unsigned gpio, int val) | 433 | static void asic3_gpio_set(struct gpio_chip *chip, |
434 | unsigned offset, int value) | ||
419 | { | 435 | { |
420 | u32 mask = ASIC3_GPIO_bit(gpio); | 436 | u32 mask, out_reg; |
421 | u32 bitval = 0; | 437 | unsigned int gpio_base; |
422 | if (val) | 438 | unsigned long flags; |
423 | bitval = mask; | 439 | struct asic3 *asic; |
424 | 440 | ||
425 | switch (gpio >> 4) { | 441 | asic = container_of(chip, struct asic3, gpio); |
426 | case ASIC3_GPIO_BANK_A: | 442 | gpio_base = ASIC3_GPIO_TO_BASE(offset); |
427 | asic3_set_gpio_a(asic, Out, mask, bitval); | 443 | |
428 | return; | 444 | if (gpio_base > ASIC3_GPIO_D_BASE) { |
429 | case ASIC3_GPIO_BANK_B: | 445 | dev_err(asic->dev, "Invalid base (0x%x) for gpio %d\n", |
430 | asic3_set_gpio_b(asic, Out, mask, bitval); | 446 | gpio_base, offset); |
431 | return; | ||
432 | case ASIC3_GPIO_BANK_C: | ||
433 | asic3_set_gpio_c(asic, Out, mask, bitval); | ||
434 | return; | ||
435 | case ASIC3_GPIO_BANK_D: | ||
436 | asic3_set_gpio_d(asic, Out, mask, bitval); | ||
437 | return; | ||
438 | default: | ||
439 | printk(KERN_ERR "%s: invalid GPIO value 0x%x", | ||
440 | __func__, gpio); | ||
441 | return; | 447 | return; |
442 | } | 448 | } |
449 | |||
450 | mask = ASIC3_GPIO_TO_MASK(offset); | ||
451 | |||
452 | spin_lock_irqsave(&asic->lock, flags); | ||
453 | |||
454 | out_reg = asic3_read_register(asic, gpio_base + ASIC3_GPIO_OUT); | ||
455 | |||
456 | if (value) | ||
457 | out_reg |= mask; | ||
458 | else | ||
459 | out_reg &= ~mask; | ||
460 | |||
461 | asic3_write_register(asic, gpio_base + ASIC3_GPIO_OUT, out_reg); | ||
462 | |||
463 | spin_unlock_irqrestore(&asic->lock, flags); | ||
464 | |||
465 | return; | ||
443 | } | 466 | } |
444 | EXPORT_SYMBOL(asic3_gpio_set_value); | ||
445 | 467 | ||
446 | static int asic3_gpio_probe(struct platform_device *pdev) | 468 | static __init int asic3_gpio_probe(struct platform_device *pdev, |
469 | u16 *gpio_config, int num) | ||
447 | { | 470 | { |
448 | struct asic3_platform_data *pdata = pdev->dev.platform_data; | ||
449 | struct asic3 *asic = platform_get_drvdata(pdev); | 471 | struct asic3 *asic = platform_get_drvdata(pdev); |
472 | u16 alt_reg[ASIC3_NUM_GPIO_BANKS]; | ||
473 | u16 out_reg[ASIC3_NUM_GPIO_BANKS]; | ||
474 | u16 dir_reg[ASIC3_NUM_GPIO_BANKS]; | ||
475 | int i; | ||
476 | |||
477 | memzero(alt_reg, ASIC3_NUM_GPIO_BANKS * sizeof(u16)); | ||
478 | memzero(out_reg, ASIC3_NUM_GPIO_BANKS * sizeof(u16)); | ||
479 | memzero(dir_reg, ASIC3_NUM_GPIO_BANKS * sizeof(u16)); | ||
480 | |||
481 | /* Enable all GPIOs */ | ||
482 | asic3_write_register(asic, ASIC3_GPIO_OFFSET(A, MASK), 0xffff); | ||
483 | asic3_write_register(asic, ASIC3_GPIO_OFFSET(B, MASK), 0xffff); | ||
484 | asic3_write_register(asic, ASIC3_GPIO_OFFSET(C, MASK), 0xffff); | ||
485 | asic3_write_register(asic, ASIC3_GPIO_OFFSET(D, MASK), 0xffff); | ||
486 | |||
487 | for (i = 0; i < num; i++) { | ||
488 | u8 alt, pin, dir, init, bank_num, bit_num; | ||
489 | u16 config = gpio_config[i]; | ||
490 | |||
491 | pin = ASIC3_CONFIG_GPIO_PIN(config); | ||
492 | alt = ASIC3_CONFIG_GPIO_ALT(config); | ||
493 | dir = ASIC3_CONFIG_GPIO_DIR(config); | ||
494 | init = ASIC3_CONFIG_GPIO_INIT(config); | ||
495 | |||
496 | bank_num = ASIC3_GPIO_TO_BANK(pin); | ||
497 | bit_num = ASIC3_GPIO_TO_BIT(pin); | ||
498 | |||
499 | alt_reg[bank_num] |= (alt << bit_num); | ||
500 | out_reg[bank_num] |= (init << bit_num); | ||
501 | dir_reg[bank_num] |= (dir << bit_num); | ||
502 | } | ||
450 | 503 | ||
451 | asic3_write_register(asic, ASIC3_GPIO_OFFSET(A, Mask), 0xffff); | 504 | for (i = 0; i < ASIC3_NUM_GPIO_BANKS; i++) { |
452 | asic3_write_register(asic, ASIC3_GPIO_OFFSET(B, Mask), 0xffff); | 505 | asic3_write_register(asic, |
453 | asic3_write_register(asic, ASIC3_GPIO_OFFSET(C, Mask), 0xffff); | 506 | ASIC3_BANK_TO_BASE(i) + |
454 | asic3_write_register(asic, ASIC3_GPIO_OFFSET(D, Mask), 0xffff); | 507 | ASIC3_GPIO_DIRECTION, |
455 | 508 | dir_reg[i]); | |
456 | asic3_set_gpio_a(asic, SleepMask, 0xffff, 0xffff); | 509 | asic3_write_register(asic, |
457 | asic3_set_gpio_b(asic, SleepMask, 0xffff, 0xffff); | 510 | ASIC3_BANK_TO_BASE(i) + ASIC3_GPIO_OUT, |
458 | asic3_set_gpio_c(asic, SleepMask, 0xffff, 0xffff); | 511 | out_reg[i]); |
459 | asic3_set_gpio_d(asic, SleepMask, 0xffff, 0xffff); | 512 | asic3_write_register(asic, |
460 | 513 | ASIC3_BANK_TO_BASE(i) + | |
461 | if (pdata) { | 514 | ASIC3_GPIO_ALT_FUNCTION, |
462 | asic3_set_gpio_banks(asic, Out, 0xffff, pdata, init); | 515 | alt_reg[i]); |
463 | asic3_set_gpio_banks(asic, Direction, 0xffff, pdata, dir); | ||
464 | asic3_set_gpio_banks(asic, SleepMask, 0xffff, pdata, | ||
465 | sleep_mask); | ||
466 | asic3_set_gpio_banks(asic, SleepOut, 0xffff, pdata, sleep_out); | ||
467 | asic3_set_gpio_banks(asic, BattFaultOut, 0xffff, pdata, | ||
468 | batt_fault_out); | ||
469 | asic3_set_gpio_banks(asic, SleepConf, 0xffff, pdata, | ||
470 | sleep_conf); | ||
471 | asic3_set_gpio_banks(asic, AltFunction, 0xffff, pdata, | ||
472 | alt_function); | ||
473 | } | 516 | } |
474 | 517 | ||
475 | return 0; | 518 | return gpiochip_add(&asic->gpio); |
476 | } | 519 | } |
477 | 520 | ||
478 | static void asic3_gpio_remove(struct platform_device *pdev) | 521 | static int asic3_gpio_remove(struct platform_device *pdev) |
479 | { | 522 | { |
480 | return; | 523 | struct asic3 *asic = platform_get_drvdata(pdev); |
524 | |||
525 | return gpiochip_remove(&asic->gpio); | ||
481 | } | 526 | } |
482 | 527 | ||
483 | 528 | ||
484 | /* Core */ | 529 | /* Core */ |
485 | static int asic3_probe(struct platform_device *pdev) | 530 | static int __init asic3_probe(struct platform_device *pdev) |
486 | { | 531 | { |
487 | struct asic3_platform_data *pdata = pdev->dev.platform_data; | 532 | struct asic3_platform_data *pdata = pdev->dev.platform_data; |
488 | struct asic3 *asic; | 533 | struct asic3 *asic; |
489 | struct resource *mem; | 534 | struct resource *mem; |
490 | unsigned long clksel; | 535 | unsigned long clksel; |
491 | int ret; | 536 | int ret = 0; |
492 | 537 | ||
493 | asic = kzalloc(sizeof(struct asic3), GFP_KERNEL); | 538 | asic = kzalloc(sizeof(struct asic3), GFP_KERNEL); |
494 | if (!asic) | 539 | if (asic == NULL) { |
540 | printk(KERN_ERR "kzalloc failed\n"); | ||
495 | return -ENOMEM; | 541 | return -ENOMEM; |
542 | } | ||
496 | 543 | ||
497 | spin_lock_init(&asic->lock); | 544 | spin_lock_init(&asic->lock); |
498 | platform_set_drvdata(pdev, asic); | 545 | platform_set_drvdata(pdev, asic); |
@@ -501,49 +548,58 @@ static int asic3_probe(struct platform_device *pdev) | |||
501 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 548 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
502 | if (!mem) { | 549 | if (!mem) { |
503 | ret = -ENOMEM; | 550 | ret = -ENOMEM; |
504 | printk(KERN_ERR "asic3: no MEM resource\n"); | 551 | dev_err(asic->dev, "no MEM resource\n"); |
505 | goto err_out_1; | 552 | goto out_free; |
506 | } | 553 | } |
507 | 554 | ||
508 | asic->mapping = ioremap(mem->start, PAGE_SIZE); | 555 | map_size = mem->end - mem->start + 1; |
556 | asic->mapping = ioremap(mem->start, map_size); | ||
509 | if (!asic->mapping) { | 557 | if (!asic->mapping) { |
510 | ret = -ENOMEM; | 558 | ret = -ENOMEM; |
511 | printk(KERN_ERR "asic3: couldn't ioremap\n"); | 559 | dev_err(asic->dev, "Couldn't ioremap\n"); |
512 | goto err_out_1; | 560 | goto out_free; |
513 | } | 561 | } |
514 | 562 | ||
515 | asic->irq_base = pdata->irq_base; | 563 | asic->irq_base = pdata->irq_base; |
516 | 564 | ||
517 | if (pdata && pdata->bus_shift) | 565 | /* calculate bus shift from mem resource */ |
518 | asic->bus_shift = 2 - pdata->bus_shift; | 566 | asic->bus_shift = 2 - (map_size >> 12); |
519 | else | ||
520 | asic->bus_shift = 0; | ||
521 | 567 | ||
522 | clksel = 0; | 568 | clksel = 0; |
523 | asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL), clksel); | 569 | asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL), clksel); |
524 | 570 | ||
525 | ret = asic3_irq_probe(pdev); | 571 | ret = asic3_irq_probe(pdev); |
526 | if (ret < 0) { | 572 | if (ret < 0) { |
527 | printk(KERN_ERR "asic3: couldn't probe IRQs\n"); | 573 | dev_err(asic->dev, "Couldn't probe IRQs\n"); |
528 | goto err_out_2; | 574 | goto out_unmap; |
529 | } | 575 | } |
530 | asic3_gpio_probe(pdev); | ||
531 | 576 | ||
532 | if (pdata->children) { | 577 | asic->gpio.base = pdata->gpio_base; |
533 | int i; | 578 | asic->gpio.ngpio = ASIC3_NUM_GPIOS; |
534 | for (i = 0; i < pdata->n_children; i++) { | 579 | asic->gpio.get = asic3_gpio_get; |
535 | pdata->children[i]->dev.parent = &pdev->dev; | 580 | asic->gpio.set = asic3_gpio_set; |
536 | platform_device_register(pdata->children[i]); | 581 | asic->gpio.direction_input = asic3_gpio_direction_input; |
537 | } | 582 | asic->gpio.direction_output = asic3_gpio_direction_output; |
583 | |||
584 | ret = asic3_gpio_probe(pdev, | ||
585 | pdata->gpio_config, | ||
586 | pdata->gpio_config_num); | ||
587 | if (ret < 0) { | ||
588 | dev_err(asic->dev, "GPIO probe failed\n"); | ||
589 | goto out_irq; | ||
538 | } | 590 | } |
539 | 591 | ||
540 | printk(KERN_INFO "ASIC3 Core driver\n"); | 592 | dev_info(asic->dev, "ASIC3 Core driver\n"); |
541 | 593 | ||
542 | return 0; | 594 | return 0; |
543 | 595 | ||
544 | err_out_2: | 596 | out_irq: |
597 | asic3_irq_remove(pdev); | ||
598 | |||
599 | out_unmap: | ||
545 | iounmap(asic->mapping); | 600 | iounmap(asic->mapping); |
546 | err_out_1: | 601 | |
602 | out_free: | ||
547 | kfree(asic); | 603 | kfree(asic); |
548 | 604 | ||
549 | return ret; | 605 | return ret; |
@@ -551,9 +607,12 @@ static int asic3_probe(struct platform_device *pdev) | |||
551 | 607 | ||
552 | static int asic3_remove(struct platform_device *pdev) | 608 | static int asic3_remove(struct platform_device *pdev) |
553 | { | 609 | { |
610 | int ret; | ||
554 | struct asic3 *asic = platform_get_drvdata(pdev); | 611 | struct asic3 *asic = platform_get_drvdata(pdev); |
555 | 612 | ||
556 | asic3_gpio_remove(pdev); | 613 | ret = asic3_gpio_remove(pdev); |
614 | if (ret < 0) | ||
615 | return ret; | ||
557 | asic3_irq_remove(pdev); | 616 | asic3_irq_remove(pdev); |
558 | 617 | ||
559 | asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL), 0); | 618 | asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL), 0); |
@@ -573,7 +632,6 @@ static struct platform_driver asic3_device_driver = { | |||
573 | .driver = { | 632 | .driver = { |
574 | .name = "asic3", | 633 | .name = "asic3", |
575 | }, | 634 | }, |
576 | .probe = asic3_probe, | ||
577 | .remove = __devexit_p(asic3_remove), | 635 | .remove = __devexit_p(asic3_remove), |
578 | .shutdown = asic3_shutdown, | 636 | .shutdown = asic3_shutdown, |
579 | }; | 637 | }; |
@@ -581,7 +639,7 @@ static struct platform_driver asic3_device_driver = { | |||
581 | static int __init asic3_init(void) | 639 | static int __init asic3_init(void) |
582 | { | 640 | { |
583 | int retval = 0; | 641 | int retval = 0; |
584 | retval = platform_driver_register(&asic3_device_driver); | 642 | retval = platform_driver_probe(&asic3_device_driver, asic3_probe); |
585 | return retval; | 643 | return retval; |
586 | } | 644 | } |
587 | 645 | ||