From owner-svn-src-all@FreeBSD.ORG Tue Mar 27 15:39:56 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 90793106566B; Tue, 27 Mar 2012 15:39:56 +0000 (UTC) (envelope-from jchandra@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 7997D8FC08; Tue, 27 Mar 2012 15:39:56 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q2RFdu5C092803; Tue, 27 Mar 2012 15:39:56 GMT (envelope-from jchandra@svn.freebsd.org) Received: (from jchandra@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q2RFduw6092794; Tue, 27 Mar 2012 15:39:56 GMT (envelope-from jchandra@svn.freebsd.org) Message-Id: <201203271539.q2RFduw6092794@svn.freebsd.org> From: "Jayachandran C." Date: Tue, 27 Mar 2012 15:39:56 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r233563 - in head/sys/mips/nlm: . hal X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 27 Mar 2012 15:39:56 -0000 Author: jchandra Date: Tue Mar 27 15:39:55 2012 New Revision: 233563 URL: http://svn.freebsd.org/changeset/base/233563 Log: Update memory and resource allocation code for SoC devices The XLP on-chip devices have PCI configuration headers, but some of the devices need custom resource allocation code. - devices with no MEM/IO BARs with registers in PCIe extended reg space have to be handled in memory resource allocation - devices without INTPIN/INTLINE in PCI header can be supported by having these faked with a shadow register. - Some devices does not allow 8/16 bit access to the register space, he default bus space cannot be used for these. Subclass pci and override attach and resource allocation methods to take care of this. Remove earlier code which did this partially. Deleted: head/sys/mips/nlm/intern_dev.c Modified: head/sys/mips/nlm/files.xlp head/sys/mips/nlm/hal/nlm_hal.c head/sys/mips/nlm/hal/pcibus.h head/sys/mips/nlm/hal/pic.h head/sys/mips/nlm/intr_machdep.c head/sys/mips/nlm/xlp.h head/sys/mips/nlm/xlp_machdep.c head/sys/mips/nlm/xlp_pci.c Modified: head/sys/mips/nlm/files.xlp ============================================================================== --- head/sys/mips/nlm/files.xlp Tue Mar 27 15:33:38 2012 (r233562) +++ head/sys/mips/nlm/files.xlp Tue Mar 27 15:39:55 2012 (r233563) @@ -12,7 +12,6 @@ mips/nlm/mpreset.S standard mips/nlm/board_eeprom.c standard mips/nlm/board_cpld.c standard mips/nlm/xlp_pci.c optional pci -mips/nlm/intern_dev.c optional pci mips/nlm/uart_cpu_xlp.c optional uart mips/nlm/usb_init.c optional usb # Modified: head/sys/mips/nlm/hal/nlm_hal.c ============================================================================== --- head/sys/mips/nlm/hal/nlm_hal.c Tue Mar 27 15:33:38 2012 (r233562) +++ head/sys/mips/nlm/hal/nlm_hal.c Tue Mar 27 15:39:55 2012 (r233563) @@ -37,23 +37,8 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include -#include -#include -#include -#include - -int pic_irt_ehci0; -int pic_irt_ehci1; -int pic_irt_uart0; -int pic_irt_uart1; -int pic_irt_pcie_lnk0; -int pic_irt_pcie_lnk1; -int pic_irt_pcie_lnk2; -int pic_irt_pcie_lnk3; - uint32_t xlp_get_cpu_frequency(int node, int core) { @@ -66,9 +51,9 @@ xlp_get_cpu_frequency(int node, int core pll_divf = ((rstval >> 10) & 0x7f) + 1; pll_divr = ((rstval >> 8) & 0x3) + 1; if (!nlm_is_xlp8xx_ax()) - ext_div = ((rstval >> 30) & 0x3) + 1; + ext_div = ((rstval >> 30) & 0x3) + 1; else - ext_div = 1; + ext_div = 1; dfs_div = ((dfsval >> (core << 2)) & 0xf) + 1; return ((800000000ULL * pll_divf)/(3 * pll_divr * ext_div * dfs_div)); @@ -122,98 +107,3 @@ nlm_set_device_frequency(int node, int d } return (nlm_get_device_frequency(sysbase, devtype)); } - -void -nlm_pic_irt_init(int node) -{ - pic_irt_ehci0 = nlm_irtstart(nlm_get_usb_pcibase(node, 0)); - pic_irt_ehci1 = nlm_irtstart(nlm_get_usb_pcibase(node, 3)); - pic_irt_uart0 = nlm_irtstart(nlm_get_uart_pcibase(node, 0)); - pic_irt_uart1 = nlm_irtstart(nlm_get_uart_pcibase(node, 1)); - - /* Hardcoding the PCIE IRT information as PIC doesn't - understand any value other than 78,79,80,81 for PCIE0/1/2/3 */ - pic_irt_pcie_lnk0 = 78; - pic_irt_pcie_lnk1 = 79; - pic_irt_pcie_lnk2 = 80; - pic_irt_pcie_lnk3 = 81; -} -/* - * Find the IRQ for the link, each link has a different interrupt - * at the XLP pic - */ -int xlp_pcie_link_irt(int link) -{ - - if( (link < 0) || (link > 3)) - return (-1); - - return (pic_irt_pcie_lnk0 + link); -} - -int -xlp_irt_to_irq(int irt) -{ - if (irt == pic_irt_ehci0) - return PIC_EHCI_0_IRQ; - else if (irt == pic_irt_ehci1) - return PIC_EHCI_1_IRQ; - else if (irt == pic_irt_uart0) - return PIC_UART_0_IRQ; - else if (irt == pic_irt_uart1) - return PIC_UART_1_IRQ; - else if (irt == pic_irt_pcie_lnk0) - return PIC_PCIE_0_IRQ; - else if (irt == pic_irt_pcie_lnk1) - return PIC_PCIE_1_IRQ; - else if (irt == pic_irt_pcie_lnk2) - return PIC_PCIE_2_IRQ; - else if (irt == pic_irt_pcie_lnk3) - return PIC_PCIE_3_IRQ; - else { - if (bootverbose) - printf("Cannot find irq for IRT %d\n", irt); - return 0; - } -} - -int -xlp_irq_to_irt(int irq) -{ - switch (irq) { - case PIC_EHCI_0_IRQ : - return pic_irt_ehci0; - case PIC_EHCI_1_IRQ : - return pic_irt_ehci1; - case PIC_UART_0_IRQ : - return pic_irt_uart0; - case PIC_UART_1_IRQ : - return pic_irt_uart1; - case PIC_PCIE_0_IRQ : - return pic_irt_pcie_lnk0; - case PIC_PCIE_1_IRQ : - return pic_irt_pcie_lnk1; - case PIC_PCIE_2_IRQ : - return pic_irt_pcie_lnk2; - case PIC_PCIE_3_IRQ : - return pic_irt_pcie_lnk3; - default: panic("Bad IRQ %d\n", irq); - } -} - -int -xlp_irq_is_picintr(int irq) -{ - switch (irq) { - case PIC_EHCI_0_IRQ : - case PIC_EHCI_1_IRQ : - case PIC_UART_0_IRQ : - case PIC_UART_1_IRQ : - case PIC_PCIE_0_IRQ : - case PIC_PCIE_1_IRQ : - case PIC_PCIE_2_IRQ : - case PIC_PCIE_3_IRQ : - return (1); - default: return (0); - } -} Modified: head/sys/mips/nlm/hal/pcibus.h ============================================================================== --- head/sys/mips/nlm/hal/pcibus.h Tue Mar 27 15:33:38 2012 (r233562) +++ head/sys/mips/nlm/hal/pcibus.h Tue Mar 27 15:39:55 2012 (r233563) @@ -84,6 +84,9 @@ /* PCIE_INT_EN0 */ #define PCIE_MSI_INT_EN (1 << 9) +/* XXXJC: Ax workaround */ +#define PCIE_LINK0_IRT 78 + #if !defined(LOCORE) && !defined(__ASSEMBLY__) #define nlm_read_pcie_reg(b, r) nlm_read_reg(b, r) @@ -93,6 +96,15 @@ #define nlm_get_pcie_regbase(node, inst) \ (nlm_get_pcie_base(node, inst) + XLP_IO_PCI_HDRSZ) +static __inline int +xlp_pcie_link_irt(int link) +{ + if ((link < 0) || (link > 3)) + return (-1); + + return (PCIE_LINK0_IRT + link); +} + /* * Build Intel MSI message and data values from a source. AMD64 systems * seem to be compatible, so we use the same function for both. @@ -106,8 +118,4 @@ MSI_MIPS_DATA_ASSERT | (irq)) #endif - -#ifndef LOCORE -int xlp_pcie_link_irt(int link); -#endif #endif /* __XLP_PCIBUS_H__ */ Modified: head/sys/mips/nlm/hal/pic.h ============================================================================== --- head/sys/mips/nlm/hal/pic.h Tue Mar 27 15:33:38 2012 (r233562) +++ head/sys/mips/nlm/hal/pic.h Tue Mar 27 15:39:55 2012 (r233563) @@ -174,7 +174,7 @@ #define PIC_IRT_FIRST_IRQ (PIC_IRQ_BASE) #define PIC_IRT_LAST_IRQ 63 -#define PIC_IRQ_IS_IRT(irq) ((irq) >= PIC_IRT_FIRST_IRQ) +#define XLP_IRQ_IS_PICINTR(irq) ((irq) >= PIC_IRT_FIRST_IRQ) /* * Misc Modified: head/sys/mips/nlm/intr_machdep.c ============================================================================== --- head/sys/mips/nlm/intr_machdep.c Tue Mar 27 15:33:38 2012 (r233562) +++ head/sys/mips/nlm/intr_machdep.c Tue Mar 27 15:39:55 2012 (r233563) @@ -141,13 +141,13 @@ xlp_establish_intr(const char *name, dri * PIC based interrupts need ack in PIC, and some SoC * components need additional acks (e.g. PCI) */ - if (xlp_irq_is_picintr(irq)) + if (XLP_IRQ_IS_PICINTR(irq)) errcode = intr_event_create(&ie, src, 0, irq, xlp_pre_ithread, xlp_post_ithread, xlp_post_filter, NULL, "hard intr%d:", irq); else { if (filt == NULL) - panic("Not supported - non filter percpu intr"); + panic("Unsupported non filter percpu intr %d", irq); errcode = intr_event_create(&ie, src, 0, irq, NULL, NULL, NULL, NULL, "hard intr%d:", irq); } Modified: head/sys/mips/nlm/xlp.h ============================================================================== --- head/sys/mips/nlm/xlp.h Tue Mar 27 15:33:38 2012 (r233562) +++ head/sys/mips/nlm/xlp.h Tue Mar 27 15:39:55 2012 (r233563) @@ -35,17 +35,15 @@ #include #define PIC_UART_0_IRQ 9 -#define PIC_UART_1_IRQ 10 #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 39 +#define PIC_EHCI_0_IRQ 16 +#define PIC_MMC_IRQ 21 /* 41 used by IRQ_SMP */ -#define PIC_EHCI_1_IRQ 42 -#define PIC_MMC_IRQ 43 /* XLP 8xx/4xx A0, A1, A2 CPU COP0 PRIDs */ @@ -75,10 +73,8 @@ 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); -void nlm_pic_irt_init(int node); int xlp_irt_to_irq(int irt); int xlp_irq_to_irt(int irq); -int xlp_irq_is_picintr(int irq); static __inline int nlm_processor_id(void) { Modified: head/sys/mips/nlm/xlp_machdep.c ============================================================================== --- head/sys/mips/nlm/xlp_machdep.c Tue Mar 27 15:33:38 2012 (r233562) +++ head/sys/mips/nlm/xlp_machdep.c Tue Mar 27 15:39:55 2012 (r233563) @@ -98,7 +98,7 @@ __FBSDID("$FreeBSD$"); char boot1_env[4096]; uint64_t xlp_cpu_frequency; -uint64_t xlp_io_base = MIPS_PHYS_TO_KSEG1(XLP_DEFAULT_IO_BASE); +uint64_t xlp_io_base = MIPS_PHYS_TO_DIRECT_UNCACHED(XLP_DEFAULT_IO_BASE); int xlp_ncores; int xlp_threads_per_core; @@ -521,7 +521,6 @@ platform_start(__register_t a0 __unused, /* initialize console so that we have printf */ boothowto |= (RB_SERIAL | RB_MULTIPLE); /* Use multiple consoles */ - nlm_pic_irt_init(0); /* complete before interrupts or console init */ init_static_kenv(boot1_env, sizeof(boot1_env)); xlp_bootargs_init(a0); Modified: head/sys/mips/nlm/xlp_pci.c ============================================================================== --- head/sys/mips/nlm/xlp_pci.c Tue Mar 27 15:33:38 2012 (r233562) +++ head/sys/mips/nlm/xlp_pci.c Tue Mar 27 15:39:55 2012 (r233563) @@ -1,32 +1,31 @@ /*- - * Copyright (c) 2003-2009 RMI Corporation - * All rights reserved. + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of RMI Corporation, nor the names of its contributors, - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * NETLOGIC_BSD */ + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #include __FBSDID("$FreeBSD$"); @@ -39,14 +38,16 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include -#include #include #include +#include + #include #include #include @@ -68,16 +69,260 @@ __FBSDID("$FreeBSD$"); #include #include "pcib_if.h" +#include "pci_if.h" + +#define EMUL_MEM_START 0x16000000UL +#define EMUL_MEM_END 0x18ffffffUL -struct xlp_pcib_softc { - bus_dma_tag_t sc_pci_dmat; /* PCI DMA tag pointer */ +/* 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 { + INTERNAL_DEV = 0x1, /* internal device, skip on enumeration */ + MEM_RES_EMUL = 0x2, /* no MEM or IO bar, custom res alloc */ + SHARED_IRQ = 0x4, + 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; + int flags; + 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) +{ + struct resource *r; + struct xlp_devinfo *xlp_devinfo; + int busno; + + /* + * Do custom allocation for MEMORY resource for SoC device if + * MEM_RES_EMUL flag is set + */ + busno = pci_get_bus(child); + if ((type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) && busno == 0) { + xlp_devinfo = (struct xlp_devinfo *)device_get_ivars(child); + if ((xlp_devinfo->flags & MEM_RES_EMUL) != 0) { + /* no emulation for IO ports */ + if (type == SYS_RES_IOPORT) + return (NULL); + start = xlp_devinfo->mem_res_start; + count = XLP_PCIE_CFG_SIZE - XLP_IO_PCI_HDRSZ; + end = start + count - 1; + r = BUS_ALLOC_RESOURCE(device_get_parent(bus), child, + type, rid, start, end, count, flags); + if (r == NULL) + return (NULL); + if ((xlp_devinfo->flags & DEV_MMIO32) != 0) + rman_set_bustag(r, rmi_uart_bus_space); + return (r); + } + } + + /* Not custom alloc, use PCI code */ + return (pci_alloc_resource(bus, child, type, rid, start, end, count, + flags)); +} + +static int +xlp_pci_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + u_long start; + + /* If custom alloc, handle that */ + start = rman_get_start(r); + if (type == SYS_RES_MEMORY && pci_get_bus(child) == 0 && + start >= EMUL_MEM_START && start <= EMUL_MEM_END) + return (BUS_RELEASE_RESOURCE(device_get_parent(bus), child, + type, rid, r)); + + /* use default PCI function */ + return (bus_generic_rl_release_resource(bus, child, type, rid, r)); +} + +static void +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; + uint16_t devid; + + domain = pcib_get_domain(dev); + node = s / 8; + devoffset = XLP_HDR_OFFSET(node, 0, s % 8, f); + if (!nlm_dev_exists(devoffset)) + return; + + /* 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) + 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; + xlp_dinfo = (struct xlp_devinfo *)dinfo; + xlp_dinfo->irq = irq; + xlp_dinfo->flags = flags; + if ((flags & MEM_RES_EMUL) != 0) + xlp_dinfo->mem_res_start = XLP_DEFAULT_IO_BASE + devoffset + + XLP_IO_PCI_HDRSZ; + pci_add_child(dev, dinfo); +} + +static int +xlp_pci_attach(device_t dev) +{ + device_t pcib = device_get_parent(dev); + int maxslots, s, f, pcifunchigh; + int busno; + uint8_t hdrtype; + + /* + * The on-chip devices are on a bus that is almost, but not + * quite, completely like PCI. Add those things by hand. + */ + busno = pcib_get_bus(dev); + maxslots = PCIB_MAXSLOTS(pcib); + for (s = 0; s <= maxslots; s++) { + pcifunchigh = 0; + f = 0; + hdrtype = PCIB_READ_CONFIG(pcib, busno, s, f, PCIR_HDRTYPE, 1); + if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE) + continue; + if (hdrtype & PCIM_MFDEV) + pcifunchigh = PCI_FUNCMAX; + for (f = 0; f <= pcifunchigh; f++) + xlp_add_soc_child(pcib, dev, busno, s, f); + } + return (bus_generic_attach(dev)); +} + +static int +xlp_pci_probe(device_t dev) +{ + device_t pcib; + + pcib = device_get_parent(dev); + /* + * Only the top level bus has SoC devices, leave the rest to + * Generic PCI code + */ + if (strcmp(device_get_nameunit(pcib), "pcib0") != 0) + return (ENXIO); + device_set_desc(dev, "XLP SoCbus"); + return (BUS_PROBE_DEFAULT); +} + +static devclass_t pci_devclass; +static device_method_t xlp_pci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, xlp_pci_probe), + DEVMETHOD(device_attach, xlp_pci_attach), + DEVMETHOD(bus_alloc_resource, xlp_pci_alloc_resource), + DEVMETHOD(bus_release_resource, xlp_pci_release_resource), + + DEVMETHOD_END +}; + +DEFINE_CLASS_1(pci, xlp_pci_driver, xlp_pci_methods, 0, pci_driver); +DRIVER_MODULE(xlp_pci, pcib, xlp_pci_driver, pci_devclass, 0, 0); + static devclass_t pcib_devclass; static struct rman irq_rman, port_rman, mem_rman, emul_rman; static void -xlp_pci_init_resources(void) +xlp_pcib_init_resources(void) { irq_rman.rm_start = 0; irq_rman.rm_end = 255; @@ -112,7 +357,7 @@ xlp_pci_init_resources(void) emul_rman.rm_type = RMAN_ARRAY; emul_rman.rm_descr = "Emulated MEMIO"; if (rman_init(&emul_rman) - || rman_manage_region(&emul_rman, 0x16000000UL, 0x18ffffffUL)) + || rman_manage_region(&emul_rman, EMUL_MEM_START, EMUL_MEM_END)) panic("pci_init_resources emul_rman"); } @@ -121,7 +366,7 @@ xlp_pcib_probe(device_t dev) { device_set_desc(dev, "XLP PCI bus"); - xlp_pci_init_resources(); + xlp_pcib_init_resources(); return (0); } @@ -173,20 +418,15 @@ xlp_pcib_read_config(device_t dev, u_int else if ((width == 4) && (reg & 3)) return 0xFFFFFFFF; - data = nlm_read_pci_reg(cfgaddr, regindex); - /* - * Fix up read data in some SoC devices - * to emulate complete PCIe header + * The intline and int pin of SoC devices are DOA, except + * for bridges (slot %8 == 1). + * use the values we stashed in a writable PCI scratch reg. */ - if (b == 0) { - int dev = s % 8; + if (b == 0 && regindex == 0xf && s % 8 > 1) + regindex = XLP_PCI_DEVSCRATCH_REG0; - /* Fake intpin on config read for UART/I2C, USB, SD/Flash */ - if (regindex == 0xf && - (dev == 6 || dev == 2 || dev == 7)) - data |= 0x1 << 8; /* Fake int pin */ - } + data = nlm_read_pci_reg(cfgaddr, regindex); if (width == 1) return ((data >> ((reg & 3) << 3)) & 0xff); else if (width == 2) @@ -221,8 +461,12 @@ xlp_pcib_write_config(device_t dev, u_in data = val; } + /* + * use shadow reg for intpin/intline which are dead + */ + if (b == 0 && regindex == 0xf && s % 8 > 1) + regindex = XLP_PCI_DEVSCRATCH_REG0; nlm_write_pci_reg(cfgaddr, regindex, data); - return; } /* @@ -230,7 +474,7 @@ xlp_pcib_write_config(device_t dev, u_in * from the link's IO and MEM address ranges. */ static void -xlp_pci_hardware_swap_enable(int node, int link) +xlp_pcib_hardware_swap_enable(int node, int link) { uint64_t bbase, linkpcibase; uint32_t bar; @@ -263,7 +507,7 @@ xlp_pcib_attach(device_t dev) /* enable hardware swap on all nodes/links */ for (node = 0; node < XLP_MAX_NODES; node++) for (link = 0; link < 4; link++) - xlp_pci_hardware_swap_enable(node, link); + xlp_pcib_hardware_swap_enable(node, link); device_add_child(dev, "pci", 0); bus_generic_attach(dev); @@ -384,7 +628,7 @@ bridge_pcie_ack(int irq) } static int -mips_platform_pci_setup_intr(device_t dev, device_t child, +mips_platform_pcib_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) { @@ -401,11 +645,11 @@ mips_platform_pci_setup_intr(device_t de return (EINVAL); } xlpirq = rman_get_start(irq); + if (xlpirq == 0) + return (0); - if (strcmp(device_get_name(dev), "pcib") != 0) { - device_printf(dev, "ret 0 on dev\n"); + if (strcmp(device_get_name(dev), "pcib") != 0) return (0); - } /* * temporary hack for MSI, we support just one device per @@ -465,7 +709,7 @@ mips_platform_pci_setup_intr(device_t de } static int -mips_platform_pci_teardown_intr(device_t dev, device_t child, +mips_platform_pcib_teardown_intr(device_t dev, device_t child, struct resource *irq, void *cookie) { if (strcmp(device_get_name(child), "pci") == 0) { @@ -475,146 +719,65 @@ mips_platform_pci_teardown_intr(device_t return (bus_generic_teardown_intr(dev, child, irq, cookie)); } -static void -assign_soc_resource(device_t child, int type, u_long *startp, u_long *endp, - u_long *countp, struct rman **rm, bus_space_tag_t *bst, vm_offset_t *va) -{ - int devid, inst, node, unit; - uint32_t val; - - devid = pci_get_device(child); - inst = pci_get_function(child); - node = pci_get_slot(child) / 8; - unit = device_get_unit(child); - - *rm = NULL; - *va = 0; - *bst = 0; - if (type == SYS_RES_MEMORY) { - switch (devid) { - case PCI_DEVICE_ID_NLM_UART: - *va = nlm_get_uart_regbase(node, inst); - *startp = MIPS_KSEG1_TO_PHYS(*va); - *countp = 0x100; - *rm = &emul_rman; - *bst = uart_bus_space_mem; - break; - - case PCI_DEVICE_ID_NLM_I2C: - *va = nlm_pcicfg_base(XLP_IO_I2C_OFFSET(node, unit)) + - XLP_IO_PCI_HDRSZ; - *startp = MIPS_KSEG1_TO_PHYS(*va); - *countp = 0x100; - *rm = &emul_rman; - *bst = uart_bus_space_mem; - break; - case PCI_DEVICE_ID_NLM_NOR: - /* XXXJC: support multiple chip selects */ - val = nlm_read_pci_reg(nlm_get_gbu_regbase(node), 0); - *startp = val << 8; - *va = MIPS_PHYS_TO_KSEG1(*startp); - /* XXXJC: count is not correct */ - *countp = 0x100; - *rm = &emul_rman; - break; - } - /* calculate end if allocated */ - if (*rm) - *endp = *startp + *countp - 1; - } else if (type != SYS_RES_IRQ) { - /* - * IRQ allocation is done by route_interrupt, - * for any other request print warning. - */ - printf("Unknown type %d in req for [%x%x]\n", - type, devid, inst); - } -} - static struct resource * -xlp_pci_alloc_resource(device_t bus, device_t child, int type, int *rid, +xlp_pcib_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct rman *rm = NULL; struct resource *rv; - vm_offset_t va = 0; + void *va; int needactivate = flags & RF_ACTIVE; - bus_space_tag_t bst = 0; - /* - * For SoC PCI devices, we have to assign resources correctly - * since the IRQ and MEM resources depend on the block. - * If the address is not from BAR0, then we use emul_rman - */ - if (pci_get_bus(child) == 0 && - pci_get_vendor(child) == PCI_VENDOR_NETLOGIC) - assign_soc_resource(child, type, &start, &end, - &count, &rm, &bst, &va); - if (rm == NULL) { - switch (type) { - case SYS_RES_IRQ: - rm = &irq_rman; - break; + switch (type) { + case SYS_RES_IRQ: + rm = &irq_rman; + break; - case SYS_RES_IOPORT: - rm = &port_rman; - break; - - case SYS_RES_MEMORY: + case SYS_RES_IOPORT: + rm = &port_rman; + break; + + case SYS_RES_MEMORY: + if (start >= EMUL_MEM_START && start <= EMUL_MEM_END) + rm = &emul_rman; + else rm = &mem_rman; break; - default: - return (0); - } + default: + return (0); } rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv == 0) - return (0); + if (rv == NULL) + return (NULL); rman_set_rid(rv, *rid); if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { - if (va == 0) - va = (vm_offset_t)pmap_mapdev(start, count); - if (bst == 0) - bst = rmi_bus_space; - - rman_set_bushandle(rv, va); - rman_set_virtual(rv, (void *)va); - rman_set_bustag(rv, bst); + va = pmap_mapdev(start, count); + rman_set_bushandle(rv, (bus_space_handle_t)va); + rman_set_bustag(rv, rmi_bus_space); } - if (needactivate) { if (bus_activate_resource(child, type, *rid, rv)) { rman_release_resource(rv); return (NULL); } } - return (rv); } static int -xlp_pci_release_resource(device_t bus, device_t child, int type, int rid, +xlp_pcib_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { return (rman_release_resource(r)); } -static bus_dma_tag_t -xlp_pci_get_dma_tag(device_t bus, device_t child) -{ - struct xlp_pcib_softc *sc; - - sc = device_get_softc(bus); - return (sc->sc_pci_dmat); -} - static int -xlp_pci_activate_resource(device_t bus, device_t child, int type, int rid, +xlp_pcib_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { @@ -622,7 +785,7 @@ xlp_pci_activate_resource(device_t bus, } static int -xlp_pci_deactivate_resource(device_t bus, device_t child, int type, int rid, +xlp_pcib_deactivate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { @@ -630,7 +793,7 @@ xlp_pci_deactivate_resource(device_t bus } static int -mips_pci_route_interrupt(device_t bus, device_t dev, int pin) +mips_pcib_route_interrupt(device_t bus, device_t dev, int pin) { int irt, link; @@ -685,19 +848,18 @@ static device_method_t xlp_pcib_methods[ /* Bus interface */ DEVMETHOD(bus_read_ivar, xlp_pcib_read_ivar), DEVMETHOD(bus_write_ivar, xlp_pcib_write_ivar), - DEVMETHOD(bus_alloc_resource, xlp_pci_alloc_resource), - DEVMETHOD(bus_release_resource, xlp_pci_release_resource), - DEVMETHOD(bus_get_dma_tag, xlp_pci_get_dma_tag), - DEVMETHOD(bus_activate_resource, xlp_pci_activate_resource), - DEVMETHOD(bus_deactivate_resource, xlp_pci_deactivate_resource), - DEVMETHOD(bus_setup_intr, mips_platform_pci_setup_intr), - DEVMETHOD(bus_teardown_intr, mips_platform_pci_teardown_intr), + DEVMETHOD(bus_alloc_resource, xlp_pcib_alloc_resource), + DEVMETHOD(bus_release_resource, xlp_pcib_release_resource), + DEVMETHOD(bus_activate_resource, xlp_pcib_activate_resource), + DEVMETHOD(bus_deactivate_resource, xlp_pcib_deactivate_resource), + DEVMETHOD(bus_setup_intr, mips_platform_pcib_setup_intr), + DEVMETHOD(bus_teardown_intr, mips_platform_pcib_teardown_intr), /* pcib interface */ DEVMETHOD(pcib_maxslots, xlp_pcib_maxslots), DEVMETHOD(pcib_read_config, xlp_pcib_read_config), DEVMETHOD(pcib_write_config, xlp_pcib_write_config), - DEVMETHOD(pcib_route_interrupt, mips_pci_route_interrupt), + DEVMETHOD(pcib_route_interrupt, mips_pcib_route_interrupt), DEVMETHOD(pcib_alloc_msi, xlp_alloc_msi), DEVMETHOD(pcib_release_msi, xlp_release_msi), @@ -709,7 +871,7 @@ static device_method_t xlp_pcib_methods[ static driver_t xlp_pcib_driver = { "pcib", xlp_pcib_methods, - sizeof(struct xlp_pcib_softc), + 1, /* no softc */ }; DRIVER_MODULE(pcib, nexus, xlp_pcib_driver, pcib_devclass, 0, 0);