diff --git a/sys/boot/fdt/dts/mips/xlp-basic.dts b/sys/boot/fdt/dts/mips/xlp-basic.dts index 18cb04c927d0..2284db81c1ef 100644 --- a/sys/boot/fdt/dts/mips/xlp-basic.dts +++ b/sys/boot/fdt/dts/mips/xlp-basic.dts @@ -62,7 +62,7 @@ current-speed = <115200>; clock-frequency = <133000000>; interrupt-parent = <&pic>; - interrupts = <9>; + interrupts = <17>; }; }; diff --git a/sys/mips/nlm/interrupt.h b/sys/mips/nlm/interrupt.h index 293e584c0414..e2aeb69f5f9c 100644 --- a/sys/mips/nlm/interrupt.h +++ b/sys/mips/nlm/interrupt.h @@ -43,13 +43,26 @@ #define XLP_IRQ_IS_PICINTR(irq) ((irq) >= PIC_IRQ_BASE && \ (irq) <= PIC_IRT_LAST_IRQ) -#define PIC_UART_0_IRQ 9 -#define PIC_PCIE_0_IRQ 11 -#define PIC_PCIE_1_IRQ 12 -#define PIC_PCIE_2_IRQ 13 -#define PIC_PCIE_3_IRQ 14 -#define PIC_EHCI_0_IRQ 16 -#define PIC_MMC_IRQ 21 +#define PIC_UART_0_IRQ 17 +#define PIC_UART_1_IRQ 18 + +#define PIC_PCIE_0_IRQ 19 +#define PIC_PCIE_1_IRQ 20 +#define PIC_PCIE_2_IRQ 21 +#define PIC_PCIE_3_IRQ 22 +#define PIC_PCIE_IRQ(l) (PIC_PCIE_0_IRQ + (l)) + +#define PIC_USB_0_IRQ 23 +#define PIC_USB_1_IRQ 24 +#define PIC_USB_2_IRQ 25 +#define PIC_USB_3_IRQ 26 +#define PIC_USB_4_IRQ 27 +#define PIC_USB_IRQ(n) (PIC_USB_0_IRQ + (n)) + +#define PIC_MMC_IRQ 29 +#define PIC_I2C_0_IRQ 30 +#define PIC_I2C_1_IRQ 31 +#define PIC_I2C_IRQ(n) (PIC_I2C_0_IRQ + (n)) /* * XLR needs custom pre and post handlers for PCI/PCI-e interrupts diff --git a/sys/mips/nlm/intr_machdep.c b/sys/mips/nlm/intr_machdep.c index 442cdced9a2f..3d9c902e9aa5 100644 --- a/sys/mips/nlm/intr_machdep.c +++ b/sys/mips/nlm/intr_machdep.c @@ -61,12 +61,46 @@ struct xlp_intrsrc { void (*busack)(int); /* Additional ack */ struct intr_event *ie; /* event corresponding to intr */ int irq; + int irt; }; static struct xlp_intrsrc xlp_interrupts[XLR_MAX_INTR]; static mips_intrcnt_t mips_intr_counters[XLR_MAX_INTR]; static int intrcnt_index; +int +xlp_irq_to_irt(int irq) +{ + uint32_t offset; + + switch (irq) { + case PIC_UART_0_IRQ: + case PIC_UART_1_IRQ: + offset = XLP_IO_UART_OFFSET(0, irq - PIC_UART_0_IRQ); + return (xlp_socdev_irt(offset)); + case PIC_PCIE_0_IRQ: + case PIC_PCIE_1_IRQ: + case PIC_PCIE_2_IRQ: + case PIC_PCIE_3_IRQ: + offset = XLP_IO_PCIE_OFFSET(0, irq - PIC_PCIE_0_IRQ); + return (xlp_socdev_irt(offset)); + case PIC_USB_0_IRQ: + case PIC_USB_1_IRQ: + case PIC_USB_2_IRQ: + case PIC_USB_3_IRQ: + case PIC_USB_4_IRQ: + offset = XLP_IO_USB_OFFSET(0, irq - PIC_USB_0_IRQ); + return (xlp_socdev_irt(offset)); + case PIC_I2C_0_IRQ: + case PIC_I2C_1_IRQ: + offset = XLP_IO_I2C0_OFFSET(0); + return (xlp_socdev_irt(offset) + irq - PIC_I2C_0_IRQ); + default: + printf("ERROR: %s: unknown irq %d\n", __func__, irq); + return (-1); + } +} + void xlp_enable_irq(int irq) { @@ -102,7 +136,7 @@ xlp_post_filter(void *source) if (src->busack) src->busack(src->irq); - nlm_pic_ack(xlp_pic_base, xlp_irq_to_irt(src->irq)); + nlm_pic_ack(xlp_pic_base, src->irt); } static void @@ -119,7 +153,7 @@ xlp_post_ithread(void *source) { struct xlp_intrsrc *src = source; - nlm_pic_ack(xlp_pic_base, xlp_irq_to_irt(src->irq)); + nlm_pic_ack(xlp_pic_base, src->irt); } void @@ -163,6 +197,13 @@ xlp_establish_intr(const char *name, driver_filter_t filt, src->busack = busack; src->ie = ie; } + if (XLP_IRQ_IS_PICINTR(irq)) { + /* Set all irqs to CPU 0 for now */ + src->irt = xlp_irq_to_irt(irq); + nlm_pic_write_irt_direct(xlp_pic_base, src->irt, 1, 0, + PIC_LOCAL_SCHEDULING, irq, 0); + } + intr_event_add_handler(ie, name, filt, handler, arg, intr_priority(flags), flags, cookiep); xlp_enable_irq(irq); diff --git a/sys/mips/nlm/xlp.h b/sys/mips/nlm/xlp.h index 2cb8165e4f84..a119ecd22f2a 100644 --- a/sys/mips/nlm/xlp.h +++ b/sys/mips/nlm/xlp.h @@ -62,7 +62,6 @@ extern void xlp_enable_threads(int code); #endif uint32_t xlp_get_cpu_frequency(int node, int core); int nlm_set_device_frequency(int node, int devtype, int frequency); -int xlp_irt_to_irq(int irt); int xlp_irq_to_irt(int irq); static __inline int nlm_processor_id(void) @@ -127,5 +126,12 @@ static __inline int nlm_is_xlp8xx_b0(void) rev == XLP_REVISION_B0); } +static __inline int xlp_socdev_irt(uint32_t offset) +{ + uint64_t base; + + base = nlm_pcicfg_base(offset); + return (nlm_irtstart(base)); +} #endif /* LOCORE */ #endif /* __NLM_XLP_H__ */ diff --git a/sys/mips/nlm/xlp_pci.c b/sys/mips/nlm/xlp_pci.c index 71f1d196a689..3c5f9680fcd0 100644 --- a/sys/mips/nlm/xlp_pci.c +++ b/sys/mips/nlm/xlp_pci.c @@ -74,31 +74,6 @@ __FBSDID("$FreeBSD$"); #define EMUL_MEM_START 0x16000000UL #define EMUL_MEM_END 0x18ffffffUL -/* SoC device qurik handling */ -static int irt_irq_map[4 * 256]; -static int irq_irt_map[64]; - -static void -xlp_add_irq(int node, int irt, int irq) -{ - int nodeirt = node * 256 + irt; - - irt_irq_map[nodeirt] = irq; - irq_irt_map[irq] = nodeirt; -} - -int -xlp_irq_to_irt(int irq) -{ - return irq_irt_map[irq]; -} - -int -xlp_irt_to_irq(int nodeirt) -{ - return irt_irq_map[nodeirt]; -} - /* Override PCI a bit for SoC devices */ enum { @@ -108,24 +83,6 @@ enum { DEV_MMIO32 = 0x8, /* byte access not allowed to mmio */ }; -struct soc_dev_desc { - u_int devid; /* device ID */ - int irqbase; /* start IRQ */ - u_int flags; /* flags */ - int ndevs; /* to keep track of number of devices */ -}; - -struct soc_dev_desc xlp_dev_desc[] = { - { PCI_DEVICE_ID_NLM_ICI, 0, INTERNAL_DEV }, - { PCI_DEVICE_ID_NLM_PIC, 0, INTERNAL_DEV }, - { PCI_DEVICE_ID_NLM_FMN, 0, INTERNAL_DEV }, - { PCI_DEVICE_ID_NLM_UART, PIC_UART_0_IRQ, MEM_RES_EMUL | DEV_MMIO32}, - { PCI_DEVICE_ID_NLM_I2C, 0, MEM_RES_EMUL | DEV_MMIO32 }, - { PCI_DEVICE_ID_NLM_NOR, 0, MEM_RES_EMUL }, - { PCI_DEVICE_ID_NLM_MMC, PIC_MMC_IRQ, MEM_RES_EMUL }, - { PCI_DEVICE_ID_NLM_EHCI, PIC_EHCI_0_IRQ, 0 } -}; - struct xlp_devinfo { struct pci_devinfo pcidev; int irq; @@ -133,19 +90,6 @@ struct xlp_devinfo { u_long mem_res_start; }; -static __inline struct soc_dev_desc * -xlp_find_soc_desc(int devid) -{ - struct soc_dev_desc *p; - int i, n; - - n = sizeof(xlp_dev_desc) / sizeof(xlp_dev_desc[0]); - for (i = 0, p = xlp_dev_desc; i < n; i++, p++) - if (p->devid == devid) - return (p); - return (NULL); -} - static struct resource * xlp_pci_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) @@ -219,9 +163,7 @@ xlp_add_soc_child(device_t pcib, device_t dev, int b, int s, int f) { struct pci_devinfo *dinfo; struct xlp_devinfo *xlp_dinfo; - struct soc_dev_desc *si; - uint64_t pcibase; - int domain, node, irt, irq, flags, devoffset, num; + int domain, node, irq, devoffset, flags; uint16_t devid; domain = pcib_get_domain(dev); @@ -232,36 +174,35 @@ xlp_add_soc_child(device_t pcib, device_t dev, int b, int s, int f) /* Find if there is a desc for the SoC device */ devid = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_DEVICE, 2); - si = xlp_find_soc_desc(devid); - - /* update flags and irq from desc if available */ - irq = 0; flags = 0; - if (si != NULL) { - if (si->irqbase != 0) - irq = si->irqbase + si->ndevs; - flags = si->flags; - si->ndevs++; - } - - /* skip internal devices */ - if ((flags & INTERNAL_DEV) != 0) + irq = 0; + switch (devid) { + case PCI_DEVICE_ID_NLM_UART: + irq = PIC_UART_0_IRQ + f; + flags = MEM_RES_EMUL | DEV_MMIO32; + break; + case PCI_DEVICE_ID_NLM_I2C: + flags = MEM_RES_EMUL | DEV_MMIO32; + break; + case PCI_DEVICE_ID_NLM_NOR: + flags = MEM_RES_EMUL; + break; + case PCI_DEVICE_ID_NLM_MMC: + irq = PIC_MMC_IRQ; + flags = MEM_RES_EMUL; + break; + case PCI_DEVICE_ID_NLM_EHCI: + irq = PIC_USB_0_IRQ + f; + break; + case PCI_DEVICE_ID_NLM_PCIE: + break; + case PCI_DEVICE_ID_NLM_ICI: + case PCI_DEVICE_ID_NLM_PIC: + case PCI_DEVICE_ID_NLM_FMN: + default: return; - - /* PCIe interfaces are special, bug in Ax */ - if (devid == PCI_DEVICE_ID_NLM_PCIE) { - xlp_add_irq(node, xlp_pcie_link_irt(f), PIC_PCIE_0_IRQ + f); - } else { - /* Stash intline and pin in shadow reg for devices */ - pcibase = nlm_pcicfg_base(devoffset); - irt = nlm_irtstart(pcibase); - num = nlm_irtnum(pcibase); - if (irq != 0 && num > 0) { - xlp_add_irq(node, irt, irq); - nlm_write_reg(pcibase, XLP_PCI_DEVSCRATCH_REG0, - (1 << 8) | irq); - } } + dinfo = pci_read_device(pcib, domain, b, s, f, sizeof(*xlp_dinfo)); if (dinfo == NULL) return; @@ -269,6 +210,11 @@ xlp_add_soc_child(device_t pcib, device_t dev, int b, int s, int f) xlp_dinfo->irq = irq; xlp_dinfo->flags = flags; + /* SoC device with interrupts need fixup (except PCIe controllers) */ + if (irq != 0 && devid != PCI_DEVICE_ID_NLM_PCIE) + PCIB_WRITE_CONFIG(pcib, b, s, f, XLP_PCI_DEVSCRATCH_REG0 << 2, + (1 << 8) | irq, 4); + /* memory resource from ecfg space, if MEM_RES_EMUL is set */ if ((flags & MEM_RES_EMUL) != 0) xlp_dinfo->mem_res_start = XLP_DEFAULT_IO_BASE + devoffset + @@ -601,21 +547,17 @@ static int xlp_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, uint32_t *data) { - int msi, irt; + int link; - if (irq >= 64) { - msi = irq - 64; - *addr = MIPS_MSI_ADDR(0); - - irt = xlp_pcie_link_irt(msi/32); - if (irt != -1) - *data = MIPS_MSI_DATA(xlp_irt_to_irq(irt)); - return (0); - } else { + if (irq < 64) { device_printf(dev, "%s: map_msi for irq %d - ignored", device_get_nameunit(pcib), irq); return (ENXIO); } + link = (irq - 64) / 32; + *addr = MIPS_MSI_ADDR(0); + *data = MIPS_MSI_DATA(PIC_PCIE_IRQ(link)); + return (0); } static void @@ -711,18 +653,13 @@ mips_platform_pcib_setup_intr(device_t dev, device_t child, nlm_write_pci_reg(base, PCIE_BRIDGE_MSI_CAP, (val | (PCIM_MSICTRL_MSI_ENABLE << 16) | (PCIM_MSICTRL_MMC_32 << 16))); - - xlpirq = xlp_pcie_link_irt(xlpirq / 32); - if (xlpirq == -1) - return (EINVAL); - xlpirq = xlp_irt_to_irq(xlpirq); + xlpirq = PIC_PCIE_IRQ(link); } - /* Set all irqs to CPU 0 for now */ - nlm_pic_write_irt_direct(xlp_pic_base, xlp_irq_to_irt(xlpirq), 1, 0, - PIC_LOCAL_SCHEDULING, xlpirq, 0); - extra_ack = NULL; + if (xlpirq >= PIC_PCIE_0_IRQ && xlpirq <= PIC_PCIE_3_IRQ) extra_ack = bridge_pcie_ack; + else + extra_ack = NULL; xlp_establish_intr(device_get_name(child), filt, intr, arg, xlpirq, flags, cookiep, extra_ack); @@ -816,7 +753,7 @@ xlp_pcib_deactivate_resource(device_t bus, device_t child, int type, int rid, static int mips_pcib_route_interrupt(device_t bus, device_t dev, int pin) { - int irt, link; + int f, d; /* * Validate requested pin number. @@ -826,38 +763,21 @@ mips_pcib_route_interrupt(device_t bus, device_t dev, int pin) if (pci_get_bus(dev) == 0 && pci_get_vendor(dev) == PCI_VENDOR_NETLOGIC) { - /* SoC devices */ - uint64_t pcibase; - int f, n, d, num; - f = pci_get_function(dev); - n = pci_get_slot(dev) / 8; d = pci_get_slot(dev) % 8; /* * For PCIe links, return link IRT, for other SoC devices * get the IRT from its PCIe header */ - if (d == 1) { - irt = xlp_pcie_link_irt(f); - } else { - pcibase = nlm_pcicfg_base(XLP_HDR_OFFSET(n, 0, d, f)); - irt = nlm_irtstart(pcibase); - num = nlm_irtnum(pcibase); - if (num != 1) - device_printf(bus, "[%d:%d:%d] Error %d IRQs\n", - n, d, f, num); - } + if (d == 1) + return (PIC_PCIE_IRQ(f)); + else + return (255); /* use intline, don't reroute */ } else { /* Regular PCI devices */ - link = xlp_pcie_link(bus, dev); - irt = xlp_pcie_link_irt(link); + return (PIC_PCIE_IRQ(xlp_pcie_link(bus, dev))); } - - if (irt != -1) - return (xlp_irt_to_irq(irt)); - - return (255); } static device_method_t xlp_pcib_methods[] = {