aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/common/locomo.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/common/locomo.c')
-rw-r--r--arch/arm/common/locomo.c362
1 files changed, 31 insertions, 331 deletions
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index bd36c778c819..90ae00b631c2 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -32,6 +32,12 @@
32 32
33#include <asm/hardware/locomo.h> 33#include <asm/hardware/locomo.h>
34 34
35/* LoCoMo Interrupts */
36#define IRQ_LOCOMO_KEY (0)
37#define IRQ_LOCOMO_GPIO (1)
38#define IRQ_LOCOMO_LT (2)
39#define IRQ_LOCOMO_SPI (3)
40
35/* M62332 output channel selection */ 41/* M62332 output channel selection */
36#define M62332_EVR_CH 1 /* M62332 volume channel number */ 42#define M62332_EVR_CH 1 /* M62332 volume channel number */
37 /* 0 : CH.1 , 1 : CH. 2 */ 43 /* 0 : CH.1 , 1 : CH. 2 */
@@ -58,6 +64,7 @@ struct locomo {
58 struct device *dev; 64 struct device *dev;
59 unsigned long phys; 65 unsigned long phys;
60 unsigned int irq; 66 unsigned int irq;
67 int irq_base;
61 spinlock_t lock; 68 spinlock_t lock;
62 void __iomem *base; 69 void __iomem *base;
63#ifdef CONFIG_PM 70#ifdef CONFIG_PM
@@ -81,9 +88,7 @@ struct locomo_dev_info {
81static struct locomo_dev_info locomo_devices[] = { 88static struct locomo_dev_info locomo_devices[] = {
82 { 89 {
83 .devid = LOCOMO_DEVID_KEYBOARD, 90 .devid = LOCOMO_DEVID_KEYBOARD,
84 .irq = { 91 .irq = { IRQ_LOCOMO_KEY },
85 IRQ_LOCOMO_KEY,
86 },
87 .name = "locomo-keyboard", 92 .name = "locomo-keyboard",
88 .offset = LOCOMO_KEYBOARD, 93 .offset = LOCOMO_KEYBOARD,
89 .length = 16, 94 .length = 16,
@@ -133,53 +138,20 @@ static struct locomo_dev_info locomo_devices[] = {
133 }, 138 },
134}; 139};
135 140
136
137/** LoCoMo interrupt handling stuff.
138 * NOTE: LoCoMo has a 1 to many mapping on all of its IRQs.
139 * that is, there is only one real hardware interrupt
140 * we determine which interrupt it is by reading some IO memory.
141 * We have two levels of expansion, first in the handler for the
142 * hardware interrupt we generate an interrupt
143 * IRQ_LOCOMO_*_BASE and those handlers generate more interrupts
144 *
145 * hardware irq reads LOCOMO_ICR & 0x0f00
146 * IRQ_LOCOMO_KEY_BASE
147 * IRQ_LOCOMO_GPIO_BASE
148 * IRQ_LOCOMO_LT_BASE
149 * IRQ_LOCOMO_SPI_BASE
150 * IRQ_LOCOMO_KEY_BASE reads LOCOMO_KIC & 0x0001
151 * IRQ_LOCOMO_KEY
152 * IRQ_LOCOMO_GPIO_BASE reads LOCOMO_GIR & LOCOMO_GPD & 0xffff
153 * IRQ_LOCOMO_GPIO[0-15]
154 * IRQ_LOCOMO_LT_BASE reads LOCOMO_LTINT & 0x0001
155 * IRQ_LOCOMO_LT
156 * IRQ_LOCOMO_SPI_BASE reads LOCOMO_SPIIR & 0x000F
157 * IRQ_LOCOMO_SPI_RFR
158 * IRQ_LOCOMO_SPI_RFW
159 * IRQ_LOCOMO_SPI_OVRN
160 * IRQ_LOCOMO_SPI_TEND
161 */
162
163#define LOCOMO_IRQ_START (IRQ_LOCOMO_KEY_BASE)
164#define LOCOMO_IRQ_KEY_START (IRQ_LOCOMO_KEY)
165#define LOCOMO_IRQ_GPIO_START (IRQ_LOCOMO_GPIO0)
166#define LOCOMO_IRQ_LT_START (IRQ_LOCOMO_LT)
167#define LOCOMO_IRQ_SPI_START (IRQ_LOCOMO_SPI_RFR)
168
169static void locomo_handler(unsigned int irq, struct irq_desc *desc) 141static void locomo_handler(unsigned int irq, struct irq_desc *desc)
170{ 142{
143 struct locomo *lchip = get_irq_chip_data(irq);
171 int req, i; 144 int req, i;
172 void __iomem *mapbase = get_irq_chip_data(irq);
173 145
174 /* Acknowledge the parent IRQ */ 146 /* Acknowledge the parent IRQ */
175 desc->chip->ack(irq); 147 desc->chip->ack(irq);
176 148
177 /* check why this interrupt was generated */ 149 /* check why this interrupt was generated */
178 req = locomo_readl(mapbase + LOCOMO_ICR) & 0x0f00; 150 req = locomo_readl(lchip->base + LOCOMO_ICR) & 0x0f00;
179 151
180 if (req) { 152 if (req) {
181 /* generate the next interrupt(s) */ 153 /* generate the next interrupt(s) */
182 irq = LOCOMO_IRQ_START; 154 irq = lchip->irq_base;
183 for (i = 0; i <= 3; i++, irq++) { 155 for (i = 0; i <= 3; i++, irq++) {
184 if (req & (0x0100 << i)) { 156 if (req & (0x0100 << i)) {
185 generic_handle_irq(irq); 157 generic_handle_irq(irq);
@@ -195,20 +167,20 @@ static void locomo_ack_irq(unsigned int irq)
195 167
196static void locomo_mask_irq(unsigned int irq) 168static void locomo_mask_irq(unsigned int irq)
197{ 169{
198 void __iomem *mapbase = get_irq_chip_data(irq); 170 struct locomo *lchip = get_irq_chip_data(irq);
199 unsigned int r; 171 unsigned int r;
200 r = locomo_readl(mapbase + LOCOMO_ICR); 172 r = locomo_readl(lchip->base + LOCOMO_ICR);
201 r &= ~(0x0010 << (irq - LOCOMO_IRQ_START)); 173 r &= ~(0x0010 << (irq - lchip->irq_base));
202 locomo_writel(r, mapbase + LOCOMO_ICR); 174 locomo_writel(r, lchip->base + LOCOMO_ICR);
203} 175}
204 176
205static void locomo_unmask_irq(unsigned int irq) 177static void locomo_unmask_irq(unsigned int irq)
206{ 178{
207 void __iomem *mapbase = get_irq_chip_data(irq); 179 struct locomo *lchip = get_irq_chip_data(irq);
208 unsigned int r; 180 unsigned int r;
209 r = locomo_readl(mapbase + LOCOMO_ICR); 181 r = locomo_readl(lchip->base + LOCOMO_ICR);
210 r |= (0x0010 << (irq - LOCOMO_IRQ_START)); 182 r |= (0x0010 << (irq - lchip->irq_base));
211 locomo_writel(r, mapbase + LOCOMO_ICR); 183 locomo_writel(r, lchip->base + LOCOMO_ICR);
212} 184}
213 185
214static struct irq_chip locomo_chip = { 186static struct irq_chip locomo_chip = {
@@ -218,297 +190,22 @@ static struct irq_chip locomo_chip = {
218 .unmask = locomo_unmask_irq, 190 .unmask = locomo_unmask_irq,
219}; 191};
220 192
221static void locomo_key_handler(unsigned int irq, struct irq_desc *desc)
222{
223 void __iomem *mapbase = get_irq_chip_data(irq);
224
225 if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) {
226 generic_handle_irq(LOCOMO_IRQ_KEY_START);
227 }
228}
229
230static void locomo_key_ack_irq(unsigned int irq)
231{
232 void __iomem *mapbase = get_irq_chip_data(irq);
233 unsigned int r;
234 r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
235 r &= ~(0x0100 << (irq - LOCOMO_IRQ_KEY_START));
236 locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
237}
238
239static void locomo_key_mask_irq(unsigned int irq)
240{
241 void __iomem *mapbase = get_irq_chip_data(irq);
242 unsigned int r;
243 r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
244 r &= ~(0x0010 << (irq - LOCOMO_IRQ_KEY_START));
245 locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
246}
247
248static void locomo_key_unmask_irq(unsigned int irq)
249{
250 void __iomem *mapbase = get_irq_chip_data(irq);
251 unsigned int r;
252 r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
253 r |= (0x0010 << (irq - LOCOMO_IRQ_KEY_START));
254 locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
255}
256
257static struct irq_chip locomo_key_chip = {
258 .name = "LOCOMO-key",
259 .ack = locomo_key_ack_irq,
260 .mask = locomo_key_mask_irq,
261 .unmask = locomo_key_unmask_irq,
262};
263
264static void locomo_gpio_handler(unsigned int irq, struct irq_desc *desc)
265{
266 int req, i;
267 void __iomem *mapbase = get_irq_chip_data(irq);
268
269 req = locomo_readl(mapbase + LOCOMO_GIR) &
270 locomo_readl(mapbase + LOCOMO_GPD) &
271 0xffff;
272
273 if (req) {
274 irq = LOCOMO_IRQ_GPIO_START;
275 for (i = 0; i <= 15; i++, irq++) {
276 if (req & (0x0001 << i)) {
277 generic_handle_irq(irq);
278 }
279 }
280 }
281}
282
283static void locomo_gpio_ack_irq(unsigned int irq)
284{
285 void __iomem *mapbase = get_irq_chip_data(irq);
286 unsigned int r;
287 r = locomo_readl(mapbase + LOCOMO_GWE);
288 r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START));
289 locomo_writel(r, mapbase + LOCOMO_GWE);
290
291 r = locomo_readl(mapbase + LOCOMO_GIS);
292 r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START));
293 locomo_writel(r, mapbase + LOCOMO_GIS);
294
295 r = locomo_readl(mapbase + LOCOMO_GWE);
296 r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START));
297 locomo_writel(r, mapbase + LOCOMO_GWE);
298}
299
300static void locomo_gpio_mask_irq(unsigned int irq)
301{
302 void __iomem *mapbase = get_irq_chip_data(irq);
303 unsigned int r;
304 r = locomo_readl(mapbase + LOCOMO_GIE);
305 r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START));
306 locomo_writel(r, mapbase + LOCOMO_GIE);
307}
308
309static void locomo_gpio_unmask_irq(unsigned int irq)
310{
311 void __iomem *mapbase = get_irq_chip_data(irq);
312 unsigned int r;
313 r = locomo_readl(mapbase + LOCOMO_GIE);
314 r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START));
315 locomo_writel(r, mapbase + LOCOMO_GIE);
316}
317
318static int GPIO_IRQ_rising_edge;
319static int GPIO_IRQ_falling_edge;
320
321static int locomo_gpio_type(unsigned int irq, unsigned int type)
322{
323 unsigned int mask;
324 void __iomem *mapbase = get_irq_chip_data(irq);
325
326 mask = 1 << (irq - LOCOMO_IRQ_GPIO_START);
327
328 if (type == IRQ_TYPE_PROBE) {
329 if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
330 return 0;
331 type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
332 }
333
334 if (type & IRQ_TYPE_EDGE_RISING)
335 GPIO_IRQ_rising_edge |= mask;
336 else
337 GPIO_IRQ_rising_edge &= ~mask;
338 if (type & IRQ_TYPE_EDGE_FALLING)
339 GPIO_IRQ_falling_edge |= mask;
340 else
341 GPIO_IRQ_falling_edge &= ~mask;
342 locomo_writel(GPIO_IRQ_rising_edge, mapbase + LOCOMO_GRIE);
343 locomo_writel(GPIO_IRQ_falling_edge, mapbase + LOCOMO_GFIE);
344
345 return 0;
346}
347
348static struct irq_chip locomo_gpio_chip = {
349 .name = "LOCOMO-gpio",
350 .ack = locomo_gpio_ack_irq,
351 .mask = locomo_gpio_mask_irq,
352 .unmask = locomo_gpio_unmask_irq,
353 .set_type = locomo_gpio_type,
354};
355
356static void locomo_lt_handler(unsigned int irq, struct irq_desc *desc)
357{
358 void __iomem *mapbase = get_irq_chip_data(irq);
359
360 if (locomo_readl(mapbase + LOCOMO_LTINT) & 0x0001) {
361 generic_handle_irq(LOCOMO_IRQ_LT_START);
362 }
363}
364
365static void locomo_lt_ack_irq(unsigned int irq)
366{
367 void __iomem *mapbase = get_irq_chip_data(irq);
368 unsigned int r;
369 r = locomo_readl(mapbase + LOCOMO_LTINT);
370 r &= ~(0x0100 << (irq - LOCOMO_IRQ_LT_START));
371 locomo_writel(r, mapbase + LOCOMO_LTINT);
372}
373
374static void locomo_lt_mask_irq(unsigned int irq)
375{
376 void __iomem *mapbase = get_irq_chip_data(irq);
377 unsigned int r;
378 r = locomo_readl(mapbase + LOCOMO_LTINT);
379 r &= ~(0x0010 << (irq - LOCOMO_IRQ_LT_START));
380 locomo_writel(r, mapbase + LOCOMO_LTINT);
381}
382
383static void locomo_lt_unmask_irq(unsigned int irq)
384{
385 void __iomem *mapbase = get_irq_chip_data(irq);
386 unsigned int r;
387 r = locomo_readl(mapbase + LOCOMO_LTINT);
388 r |= (0x0010 << (irq - LOCOMO_IRQ_LT_START));
389 locomo_writel(r, mapbase + LOCOMO_LTINT);
390}
391
392static struct irq_chip locomo_lt_chip = {
393 .name = "LOCOMO-lt",
394 .ack = locomo_lt_ack_irq,
395 .mask = locomo_lt_mask_irq,
396 .unmask = locomo_lt_unmask_irq,
397};
398
399static void locomo_spi_handler(unsigned int irq, struct irq_desc *desc)
400{
401 int req, i;
402 void __iomem *mapbase = get_irq_chip_data(irq);
403
404 req = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIR) & 0x000F;
405 if (req) {
406 irq = LOCOMO_IRQ_SPI_START;
407
408 for (i = 0; i <= 3; i++, irq++) {
409 if (req & (0x0001 << i)) {
410 generic_handle_irq(irq);
411 }
412 }
413 }
414}
415
416static void locomo_spi_ack_irq(unsigned int irq)
417{
418 void __iomem *mapbase = get_irq_chip_data(irq);
419 unsigned int r;
420 r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIWE);
421 r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START));
422 locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIWE);
423
424 r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIS);
425 r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START));
426 locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIIS);
427
428 r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIWE);
429 r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START));
430 locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIWE);
431}
432
433static void locomo_spi_mask_irq(unsigned int irq)
434{
435 void __iomem *mapbase = get_irq_chip_data(irq);
436 unsigned int r;
437 r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIE);
438 r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START));
439 locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIIE);
440}
441
442static void locomo_spi_unmask_irq(unsigned int irq)
443{
444 void __iomem *mapbase = get_irq_chip_data(irq);
445 unsigned int r;
446 r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIE);
447 r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START));
448 locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIIE);
449}
450
451static struct irq_chip locomo_spi_chip = {
452 .name = "LOCOMO-spi",
453 .ack = locomo_spi_ack_irq,
454 .mask = locomo_spi_mask_irq,
455 .unmask = locomo_spi_unmask_irq,
456};
457
458static void locomo_setup_irq(struct locomo *lchip) 193static void locomo_setup_irq(struct locomo *lchip)
459{ 194{
460 int irq; 195 int irq = lchip->irq_base;
461 void __iomem *irqbase = lchip->base;
462 196
463 /* 197 /*
464 * Install handler for IRQ_LOCOMO_HW. 198 * Install handler for IRQ_LOCOMO_HW.
465 */ 199 */
466 set_irq_type(lchip->irq, IRQ_TYPE_EDGE_FALLING); 200 set_irq_type(lchip->irq, IRQ_TYPE_EDGE_FALLING);
467 set_irq_chip_data(lchip->irq, irqbase); 201 set_irq_chip_data(lchip->irq, lchip);
468 set_irq_chained_handler(lchip->irq, locomo_handler); 202 set_irq_chained_handler(lchip->irq, locomo_handler);
469 203
470 /* Install handlers for IRQ_LOCOMO_*_BASE */ 204 /* Install handlers for IRQ_LOCOMO_* */
471 set_irq_chip(IRQ_LOCOMO_KEY_BASE, &locomo_chip); 205 for ( ; irq <= lchip->irq_base + 3; irq++) {
472 set_irq_chip_data(IRQ_LOCOMO_KEY_BASE, irqbase); 206 set_irq_chip(irq, &locomo_chip);
473 set_irq_chained_handler(IRQ_LOCOMO_KEY_BASE, locomo_key_handler); 207 set_irq_chip_data(irq, lchip);
474 208 set_irq_handler(irq, handle_level_irq);
475 set_irq_chip(IRQ_LOCOMO_GPIO_BASE, &locomo_chip);
476 set_irq_chip_data(IRQ_LOCOMO_GPIO_BASE, irqbase);
477 set_irq_chained_handler(IRQ_LOCOMO_GPIO_BASE, locomo_gpio_handler);
478
479 set_irq_chip(IRQ_LOCOMO_LT_BASE, &locomo_chip);
480 set_irq_chip_data(IRQ_LOCOMO_LT_BASE, irqbase);
481 set_irq_chained_handler(IRQ_LOCOMO_LT_BASE, locomo_lt_handler);
482
483 set_irq_chip(IRQ_LOCOMO_SPI_BASE, &locomo_chip);
484 set_irq_chip_data(IRQ_LOCOMO_SPI_BASE, irqbase);
485 set_irq_chained_handler(IRQ_LOCOMO_SPI_BASE, locomo_spi_handler);
486
487 /* install handlers for IRQ_LOCOMO_KEY_BASE generated interrupts */
488 set_irq_chip(LOCOMO_IRQ_KEY_START, &locomo_key_chip);
489 set_irq_chip_data(LOCOMO_IRQ_KEY_START, irqbase);
490 set_irq_handler(LOCOMO_IRQ_KEY_START, handle_edge_irq);
491 set_irq_flags(LOCOMO_IRQ_KEY_START, IRQF_VALID | IRQF_PROBE);
492
493 /* install handlers for IRQ_LOCOMO_GPIO_BASE generated interrupts */
494 for (irq = LOCOMO_IRQ_GPIO_START; irq < LOCOMO_IRQ_GPIO_START + 16; irq++) {
495 set_irq_chip(irq, &locomo_gpio_chip);
496 set_irq_chip_data(irq, irqbase);
497 set_irq_handler(irq, handle_edge_irq);
498 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
499 }
500
501 /* install handlers for IRQ_LOCOMO_LT_BASE generated interrupts */
502 set_irq_chip(LOCOMO_IRQ_LT_START, &locomo_lt_chip);
503 set_irq_chip_data(LOCOMO_IRQ_LT_START, irqbase);
504 set_irq_handler(LOCOMO_IRQ_LT_START, handle_edge_irq);
505 set_irq_flags(LOCOMO_IRQ_LT_START, IRQF_VALID | IRQF_PROBE);
506
507 /* install handlers for IRQ_LOCOMO_SPI_BASE generated interrupts */
508 for (irq = LOCOMO_IRQ_SPI_START; irq < LOCOMO_IRQ_SPI_START + 4; irq++) {
509 set_irq_chip(irq, &locomo_spi_chip);
510 set_irq_chip_data(irq, irqbase);
511 set_irq_handler(irq, handle_edge_irq);
512 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); 209 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
513 } 210 }
514} 211}
@@ -555,7 +252,8 @@ locomo_init_one_child(struct locomo *lchip, struct locomo_dev_info *info)
555 dev->mapbase = 0; 252 dev->mapbase = 0;
556 dev->length = info->length; 253 dev->length = info->length;
557 254
558 memmove(dev->irq, info->irq, sizeof(dev->irq)); 255 dev->irq[0] = (lchip->irq_base == NO_IRQ) ?
256 NO_IRQ : lchip->irq_base + info->irq[0];
559 257
560 ret = device_register(&dev->dev); 258 ret = device_register(&dev->dev);
561 if (ret) { 259 if (ret) {
@@ -672,6 +370,7 @@ static int locomo_resume(struct platform_device *dev)
672static int 370static int
673__locomo_probe(struct device *me, struct resource *mem, int irq) 371__locomo_probe(struct device *me, struct resource *mem, int irq)
674{ 372{
373 struct locomo_platform_data *pdata = me->platform_data;
675 struct locomo *lchip; 374 struct locomo *lchip;
676 unsigned long r; 375 unsigned long r;
677 int i, ret = -ENODEV; 376 int i, ret = -ENODEV;
@@ -687,6 +386,7 @@ __locomo_probe(struct device *me, struct resource *mem, int irq)
687 386
688 lchip->phys = mem->start; 387 lchip->phys = mem->start;
689 lchip->irq = irq; 388 lchip->irq = irq;
389 lchip->irq_base = (pdata) ? pdata->irq_base : NO_IRQ;
690 390
691 /* 391 /*
692 * Map the whole region. This also maps the 392 * Map the whole region. This also maps the
@@ -753,7 +453,7 @@ __locomo_probe(struct device *me, struct resource *mem, int irq)
753 * The interrupt controller must be initialised before any 453 * The interrupt controller must be initialised before any
754 * other device to ensure that the interrupts are available. 454 * other device to ensure that the interrupts are available.
755 */ 455 */
756 if (lchip->irq != NO_IRQ) 456 if (lchip->irq != NO_IRQ && lchip->irq_base != NO_IRQ)
757 locomo_setup_irq(lchip); 457 locomo_setup_irq(lchip);
758 458
759 for (i = 0; i < ARRAY_SIZE(locomo_devices); i++) 459 for (i = 0; i < ARRAY_SIZE(locomo_devices); i++)