From 1d421ca9d7edbac1eb118631ee039d50ab54771e Mon Sep 17 00:00:00 2001 From: Thomas Bogendoerfer Date: Wed, 4 Jun 2014 12:00:37 +0200 Subject: 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 Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/7055/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/gio_device.h | 4 ++-- arch/mips/include/asm/sgi/ip22.h | 2 ++ arch/mips/sgi-ip22/ip22-gio.c | 42 +++++++++++++++++++++++++------------- arch/mips/sgi-ip22/ip22-int.c | 7 ++++++- 4 files changed, 38 insertions(+), 17 deletions(-) (limited to 'arch') 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) extern int gio_register_driver(struct gio_driver *); extern void gio_unregister_driver(struct gio_driver *); -#define gio_get_drvdata(_dev) drv_get_drvdata(&(_dev)->dev) -#define gio_set_drvdata(_dev, data) drv_set_drvdata(&(_dev)->dev, (data)) +#define gio_get_drvdata(_dev) dev_get_drvdata(&(_dev)->dev) +#define gio_set_drvdata(_dev, data) dev_set_drvdata(&(_dev)->dev, (data)) 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 @@ #define SGI_EISA_IRQ SGINT_LOCAL2 + 3 /* EISA interrupts */ #define SGI_KEYBD_IRQ SGINT_LOCAL2 + 4 /* keyboard */ #define SGI_SERIAL_IRQ SGINT_LOCAL2 + 5 /* onboard serial */ +#define SGI_GIOEXP0_IRQ (SGINT_LOCAL2 + 6) /* Indy GIO EXP0 */ +#define SGI_GIOEXP1_IRQ (SGINT_LOCAL2 + 7) /* Indy GIO EXP1 */ #define ip22_is_fullhouse() (sgioc->sysid & SGIOC_SYSID_FULLHOUSE) 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 { } gio_name_table[] = { { .name = "SGI Impact", .id = 0x10 }, { .name = "Phobos G160", .id = 0x35 }, + { .name = "Phobos G130", .id = 0x36 }, + { .name = "Phobos G100", .id = 0x37 }, + { .name = "Set Engineering GFE", .id = 0x38 }, /* fake IDs */ { .name = "SGI Newport", .id = 0x7e }, { .name = "SGI GR2/GR3", .id = 0x7f }, @@ -293,7 +296,16 @@ static int ip22_gio_id(unsigned long addr, u32 *res) * data matches */ ptr8 = (void *)CKSEG1ADDR(addr + 3); - get_dbe(tmp8, ptr8); + if (get_dbe(tmp8, ptr8)) { + /* + * 32bit access worked, but 8bit doesn't + * so we don't see phantom reads on + * a pipelined bus, but a real card which + * doesn't support 8 bit reads + */ + *res = tmp32; + return 1; + } ptr16 = (void *)CKSEG1ADDR(addr + 2); get_dbe(tmp16, ptr16); if (tmp8 == (tmp16 & 0xff) && @@ -324,7 +336,7 @@ static int ip22_is_gr2(unsigned long addr) } -static void ip22_check_gio(int slotno, unsigned long addr) +static void ip22_check_gio(int slotno, unsigned long addr, int irq) { const char *name = "Unknown"; struct gio_device *gio_dev; @@ -338,9 +350,9 @@ static void ip22_check_gio(int slotno, unsigned long addr) else { if (!ip22_gio_id(addr, &tmp)) { /* - * no GIO signature at start address of slot, but - * Newport doesn't have one, so let's check usea - * status register + * no GIO signature at start address of slot + * since Newport doesn't have one, we check if + * user status register is readable */ if (ip22_gio_id(addr + NEWPORT_USTATUS_OFFS, &tmp)) tmp = 0x7e; @@ -369,6 +381,7 @@ static void ip22_check_gio(int slotno, unsigned long addr) gio_dev->resource.start = addr; gio_dev->resource.end = addr + 0x3fffff; gio_dev->resource.flags = IORESOURCE_MEM; + gio_dev->irq = irq; dev_set_name(&gio_dev->dev, "%d", slotno); gio_device_register(gio_dev); } else @@ -408,16 +421,17 @@ int __init ip22_gio_init(void) request_resource(&iomem_resource, &gio_bus_resource); printk(KERN_INFO "GIO: Probing bus...\n"); - if (ip22_is_fullhouse() || - !get_dbe(pbdma, (unsigned int *)&hpc3c1->pbdma[1])) { - /* Indigo2 and ChallengeS */ - ip22_check_gio(0, GIO_SLOT_GFX_BASE); - ip22_check_gio(1, GIO_SLOT_EXP0_BASE); + if (ip22_is_fullhouse()) { + /* Indigo2 */ + ip22_check_gio(0, GIO_SLOT_GFX_BASE, SGI_GIO_1_IRQ); + ip22_check_gio(1, GIO_SLOT_EXP0_BASE, SGI_GIO_1_IRQ); } else { - /* Indy */ - ip22_check_gio(0, GIO_SLOT_GFX_BASE); - ip22_check_gio(1, GIO_SLOT_EXP0_BASE); - ip22_check_gio(2, GIO_SLOT_EXP1_BASE); + /* Indy/Challenge S */ + if (get_dbe(pbdma, (unsigned int *)&hpc3c1->pbdma[1])) + ip22_check_gio(0, GIO_SLOT_GFX_BASE, + SGI_GIO_0_IRQ); + ip22_check_gio(1, GIO_SLOT_EXP0_BASE, SGI_GIOEXP0_IRQ); + ip22_check_gio(2, GIO_SLOT_EXP1_BASE, SGI_GIOEXP1_IRQ); } } else 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) } else irq = lc0msk_to_irqnr[mask]; - /* if irq == 0, then the interrupt has already been cleared */ + /* + * workaround for INT2 bug; if irq == 0, INT2 has seen a fifo full + * irq, but failed to latch it into status register + */ if (irq) do_IRQ(irq); + else + do_IRQ(SGINT_LOCAL0 + 0); } static void indy_local1_irqdispatch(void) -- cgit v1.2.3