diff options
author | Thomas Bogendoerfer <tsbogend@alpha.franken.de> | 2014-06-04 06:00:37 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2014-06-04 16:50:42 -0400 |
commit | 1d421ca9d7edbac1eb118631ee039d50ab54771e (patch) | |
tree | 5268e99e5fbf4c7c9513b45f9bfd6265df1a1aab | |
parent | a53825ef4e9b2f42a21ad2b903f4d0ce691a5d63 (diff) |
MIPS: IP22/IP28: Improve GIO support
- added interrupt support for GIO devices
- improved detection of GIO cards on Indigo2
- added more known GIO cards
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/7055/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | arch/mips/include/asm/gio_device.h | 4 | ||||
-rw-r--r-- | arch/mips/include/asm/sgi/ip22.h | 2 | ||||
-rw-r--r-- | arch/mips/sgi-ip22/ip22-gio.c | 42 | ||||
-rw-r--r-- | arch/mips/sgi-ip22/ip22-int.c | 7 |
4 files changed, 38 insertions, 17 deletions
diff --git a/arch/mips/include/asm/gio_device.h b/arch/mips/include/asm/gio_device.h index 0878701712f8..4be1a57cdbb0 100644 --- a/arch/mips/include/asm/gio_device.h +++ b/arch/mips/include/asm/gio_device.h | |||
@@ -50,7 +50,7 @@ static inline void gio_device_free(struct gio_device *dev) | |||
50 | extern int gio_register_driver(struct gio_driver *); | 50 | extern int gio_register_driver(struct gio_driver *); |
51 | extern void gio_unregister_driver(struct gio_driver *); | 51 | extern void gio_unregister_driver(struct gio_driver *); |
52 | 52 | ||
53 | #define gio_get_drvdata(_dev) drv_get_drvdata(&(_dev)->dev) | 53 | #define gio_get_drvdata(_dev) dev_get_drvdata(&(_dev)->dev) |
54 | #define gio_set_drvdata(_dev, data) drv_set_drvdata(&(_dev)->dev, (data)) | 54 | #define gio_set_drvdata(_dev, data) dev_set_drvdata(&(_dev)->dev, (data)) |
55 | 55 | ||
56 | extern void gio_set_master(struct gio_device *); | 56 | extern void gio_set_master(struct gio_device *); |
diff --git a/arch/mips/include/asm/sgi/ip22.h b/arch/mips/include/asm/sgi/ip22.h index 8db1a3588cf2..87ec9eaa04e3 100644 --- a/arch/mips/include/asm/sgi/ip22.h +++ b/arch/mips/include/asm/sgi/ip22.h | |||
@@ -69,6 +69,8 @@ | |||
69 | #define SGI_EISA_IRQ SGINT_LOCAL2 + 3 /* EISA interrupts */ | 69 | #define SGI_EISA_IRQ SGINT_LOCAL2 + 3 /* EISA interrupts */ |
70 | #define SGI_KEYBD_IRQ SGINT_LOCAL2 + 4 /* keyboard */ | 70 | #define SGI_KEYBD_IRQ SGINT_LOCAL2 + 4 /* keyboard */ |
71 | #define SGI_SERIAL_IRQ SGINT_LOCAL2 + 5 /* onboard serial */ | 71 | #define SGI_SERIAL_IRQ SGINT_LOCAL2 + 5 /* onboard serial */ |
72 | #define SGI_GIOEXP0_IRQ (SGINT_LOCAL2 + 6) /* Indy GIO EXP0 */ | ||
73 | #define SGI_GIOEXP1_IRQ (SGINT_LOCAL2 + 7) /* Indy GIO EXP1 */ | ||
72 | 74 | ||
73 | #define ip22_is_fullhouse() (sgioc->sysid & SGIOC_SYSID_FULLHOUSE) | 75 | #define ip22_is_fullhouse() (sgioc->sysid & SGIOC_SYSID_FULLHOUSE) |
74 | 76 | ||
diff --git a/arch/mips/sgi-ip22/ip22-gio.c b/arch/mips/sgi-ip22/ip22-gio.c index ab0e379dc7e0..8e52446286ca 100644 --- a/arch/mips/sgi-ip22/ip22-gio.c +++ b/arch/mips/sgi-ip22/ip22-gio.c | |||
@@ -19,6 +19,9 @@ static struct { | |||
19 | } gio_name_table[] = { | 19 | } gio_name_table[] = { |
20 | { .name = "SGI Impact", .id = 0x10 }, | 20 | { .name = "SGI Impact", .id = 0x10 }, |
21 | { .name = "Phobos G160", .id = 0x35 }, | 21 | { .name = "Phobos G160", .id = 0x35 }, |
22 | { .name = "Phobos G130", .id = 0x36 }, | ||
23 | { .name = "Phobos G100", .id = 0x37 }, | ||
24 | { .name = "Set Engineering GFE", .id = 0x38 }, | ||
22 | /* fake IDs */ | 25 | /* fake IDs */ |
23 | { .name = "SGI Newport", .id = 0x7e }, | 26 | { .name = "SGI Newport", .id = 0x7e }, |
24 | { .name = "SGI GR2/GR3", .id = 0x7f }, | 27 | { .name = "SGI GR2/GR3", .id = 0x7f }, |
@@ -293,7 +296,16 @@ static int ip22_gio_id(unsigned long addr, u32 *res) | |||
293 | * data matches | 296 | * data matches |
294 | */ | 297 | */ |
295 | ptr8 = (void *)CKSEG1ADDR(addr + 3); | 298 | ptr8 = (void *)CKSEG1ADDR(addr + 3); |
296 | get_dbe(tmp8, ptr8); | 299 | if (get_dbe(tmp8, ptr8)) { |
300 | /* | ||
301 | * 32bit access worked, but 8bit doesn't | ||
302 | * so we don't see phantom reads on | ||
303 | * a pipelined bus, but a real card which | ||
304 | * doesn't support 8 bit reads | ||
305 | */ | ||
306 | *res = tmp32; | ||
307 | return 1; | ||
308 | } | ||
297 | ptr16 = (void *)CKSEG1ADDR(addr + 2); | 309 | ptr16 = (void *)CKSEG1ADDR(addr + 2); |
298 | get_dbe(tmp16, ptr16); | 310 | get_dbe(tmp16, ptr16); |
299 | if (tmp8 == (tmp16 & 0xff) && | 311 | if (tmp8 == (tmp16 & 0xff) && |
@@ -324,7 +336,7 @@ static int ip22_is_gr2(unsigned long addr) | |||
324 | } | 336 | } |
325 | 337 | ||
326 | 338 | ||
327 | static void ip22_check_gio(int slotno, unsigned long addr) | 339 | static void ip22_check_gio(int slotno, unsigned long addr, int irq) |
328 | { | 340 | { |
329 | const char *name = "Unknown"; | 341 | const char *name = "Unknown"; |
330 | struct gio_device *gio_dev; | 342 | struct gio_device *gio_dev; |
@@ -338,9 +350,9 @@ static void ip22_check_gio(int slotno, unsigned long addr) | |||
338 | else { | 350 | else { |
339 | if (!ip22_gio_id(addr, &tmp)) { | 351 | if (!ip22_gio_id(addr, &tmp)) { |
340 | /* | 352 | /* |
341 | * no GIO signature at start address of slot, but | 353 | * no GIO signature at start address of slot |
342 | * Newport doesn't have one, so let's check usea | 354 | * since Newport doesn't have one, we check if |
343 | * status register | 355 | * user status register is readable |
344 | */ | 356 | */ |
345 | if (ip22_gio_id(addr + NEWPORT_USTATUS_OFFS, &tmp)) | 357 | if (ip22_gio_id(addr + NEWPORT_USTATUS_OFFS, &tmp)) |
346 | tmp = 0x7e; | 358 | tmp = 0x7e; |
@@ -369,6 +381,7 @@ static void ip22_check_gio(int slotno, unsigned long addr) | |||
369 | gio_dev->resource.start = addr; | 381 | gio_dev->resource.start = addr; |
370 | gio_dev->resource.end = addr + 0x3fffff; | 382 | gio_dev->resource.end = addr + 0x3fffff; |
371 | gio_dev->resource.flags = IORESOURCE_MEM; | 383 | gio_dev->resource.flags = IORESOURCE_MEM; |
384 | gio_dev->irq = irq; | ||
372 | dev_set_name(&gio_dev->dev, "%d", slotno); | 385 | dev_set_name(&gio_dev->dev, "%d", slotno); |
373 | gio_device_register(gio_dev); | 386 | gio_device_register(gio_dev); |
374 | } else | 387 | } else |
@@ -408,16 +421,17 @@ int __init ip22_gio_init(void) | |||
408 | request_resource(&iomem_resource, &gio_bus_resource); | 421 | request_resource(&iomem_resource, &gio_bus_resource); |
409 | printk(KERN_INFO "GIO: Probing bus...\n"); | 422 | printk(KERN_INFO "GIO: Probing bus...\n"); |
410 | 423 | ||
411 | if (ip22_is_fullhouse() || | 424 | if (ip22_is_fullhouse()) { |
412 | !get_dbe(pbdma, (unsigned int *)&hpc3c1->pbdma[1])) { | 425 | /* Indigo2 */ |
413 | /* Indigo2 and ChallengeS */ | 426 | ip22_check_gio(0, GIO_SLOT_GFX_BASE, SGI_GIO_1_IRQ); |
414 | ip22_check_gio(0, GIO_SLOT_GFX_BASE); | 427 | ip22_check_gio(1, GIO_SLOT_EXP0_BASE, SGI_GIO_1_IRQ); |
415 | ip22_check_gio(1, GIO_SLOT_EXP0_BASE); | ||
416 | } else { | 428 | } else { |
417 | /* Indy */ | 429 | /* Indy/Challenge S */ |
418 | ip22_check_gio(0, GIO_SLOT_GFX_BASE); | 430 | if (get_dbe(pbdma, (unsigned int *)&hpc3c1->pbdma[1])) |
419 | ip22_check_gio(1, GIO_SLOT_EXP0_BASE); | 431 | ip22_check_gio(0, GIO_SLOT_GFX_BASE, |
420 | ip22_check_gio(2, GIO_SLOT_EXP1_BASE); | 432 | SGI_GIO_0_IRQ); |
433 | ip22_check_gio(1, GIO_SLOT_EXP0_BASE, SGI_GIOEXP0_IRQ); | ||
434 | ip22_check_gio(2, GIO_SLOT_EXP1_BASE, SGI_GIOEXP1_IRQ); | ||
421 | } | 435 | } |
422 | } else | 436 | } else |
423 | device_unregister(&gio_bus); | 437 | device_unregister(&gio_bus); |
diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c index 58b40ae59335..c66889fc4913 100644 --- a/arch/mips/sgi-ip22/ip22-int.c +++ b/arch/mips/sgi-ip22/ip22-int.c | |||
@@ -119,9 +119,14 @@ static void indy_local0_irqdispatch(void) | |||
119 | } else | 119 | } else |
120 | irq = lc0msk_to_irqnr[mask]; | 120 | irq = lc0msk_to_irqnr[mask]; |
121 | 121 | ||
122 | /* if irq == 0, then the interrupt has already been cleared */ | 122 | /* |
123 | * workaround for INT2 bug; if irq == 0, INT2 has seen a fifo full | ||
124 | * irq, but failed to latch it into status register | ||
125 | */ | ||
123 | if (irq) | 126 | if (irq) |
124 | do_IRQ(irq); | 127 | do_IRQ(irq); |
128 | else | ||
129 | do_IRQ(SGINT_LOCAL0 + 0); | ||
125 | } | 130 | } |
126 | 131 | ||
127 | static void indy_local1_irqdispatch(void) | 132 | static void indy_local1_irqdispatch(void) |