aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Bogendoerfer <tsbogend@alpha.franken.de>2014-06-04 06:00:37 -0400
committerRalf Baechle <ralf@linux-mips.org>2014-06-04 16:50:42 -0400
commit1d421ca9d7edbac1eb118631ee039d50ab54771e (patch)
tree5268e99e5fbf4c7c9513b45f9bfd6265df1a1aab
parenta53825ef4e9b2f42a21ad2b903f4d0ce691a5d63 (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.h4
-rw-r--r--arch/mips/include/asm/sgi/ip22.h2
-rw-r--r--arch/mips/sgi-ip22/ip22-gio.c42
-rw-r--r--arch/mips/sgi-ip22/ip22-int.c7
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)
50extern int gio_register_driver(struct gio_driver *); 50extern int gio_register_driver(struct gio_driver *);
51extern void gio_unregister_driver(struct gio_driver *); 51extern 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
56extern void gio_set_master(struct gio_device *); 56extern 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
327static void ip22_check_gio(int slotno, unsigned long addr) 339static 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
127static void indy_local1_irqdispatch(void) 132static void indy_local1_irqdispatch(void)