Module Name: src Committed By: jmcneill Date: Wed Jun 12 22:44:54 UTC 2019
Modified Files: src/sys/arch/arm/rockchip: rk3399_pcie.c Log Message: Use ranges from the device tree. To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/rockchip/rk3399_pcie.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/rockchip/rk3399_pcie.c diff -u src/sys/arch/arm/rockchip/rk3399_pcie.c:1.2 src/sys/arch/arm/rockchip/rk3399_pcie.c:1.3 --- src/sys/arch/arm/rockchip/rk3399_pcie.c:1.2 Wed Jun 12 10:13:44 2019 +++ src/sys/arch/arm/rockchip/rk3399_pcie.c Wed Jun 12 22:44:53 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: rk3399_pcie.c,v 1.2 2019/06/12 10:13:44 jmcneill Exp $ */ +/* $NetBSD: rk3399_pcie.c,v 1.3 2019/06/12 22:44:53 jmcneill Exp $ */ /* * Copyright (c) 2018 Mark Kettenis <kette...@openbsd.org> * @@ -17,7 +17,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: rk3399_pcie.c,v 1.2 2019/06/12 10:13:44 jmcneill Exp $"); +__KERNEL_RCSID(1, "$NetBSD: rk3399_pcie.c,v 1.3 2019/06/12 22:44:53 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -126,24 +126,11 @@ struct rkpcie_softc { struct pcihost_softc sc_phsc; bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; - bus_space_handle_t sc_bus_cfgh[32]; + bus_space_handle_t sc_axi_ioh; bus_addr_t sc_axi_addr; bus_addr_t sc_apb_addr; bus_size_t sc_axi_size; bus_size_t sc_apb_size; - - struct extent *sc_regionex; -}; - -/* - * XXX ignore DT ranges and use our own for now - */ -static const uint32_t rk3399_pcie_bus_range[] = { 0, 3 }; -static const uint32_t rk3399_pcie_ranges[] = { - 0xc3000000, 0x0, 0xf8000000, 0x0, 0xf8000000, 0x0, 0x2000000, /* 32M region 0, prefmem */ - 0x82000000, 0x0, 0xfa000000, 0x0, 0xfa000000, 0x0, 0x1c00000, /* 28M regions 1-28, mem */ - 0x81000000, 0x0, 0x00000000, 0x0, 0xfbc00000, 0x0, 0x0100000, /* 1M region 29, i/o */ - 0x00010000, 0x0, 0x00000000, 0x0, 0xfbd00000, 0x0, 0x0300000, /* 3M regions 30-32, config */ }; static int rkpcie_match(device_t, cfdata_t, void *); @@ -225,7 +212,8 @@ rkpcie_attach(device_t parent, device_t struct fdt_attach_args *faa = aux; //struct pcibus_attach_args pba; struct fdtbus_gpio_pin *ep_gpio; - uint32_t bus_range[2]; + const u_int *bus_range; + int len; uint32_t status; bool retry = false; int timo; @@ -247,8 +235,8 @@ rkpcie_attach(device_t parent, device_t return; } - if (bus_space_map(sc->sc_iot, sc->sc_apb_addr, - sc->sc_apb_size, 0, &sc->sc_ioh)) { + if (bus_space_map(sc->sc_iot, sc->sc_apb_addr, sc->sc_apb_size, 0, &sc->sc_ioh) != 0 || + bus_space_map(sc->sc_iot, sc->sc_axi_addr, sc->sc_axi_size, 0, &sc->sc_axi_ioh) != 0) { printf(": can't map registers\n"); sc->sc_axi_size = 0; sc->sc_apb_size = 0; @@ -420,37 +408,22 @@ again: status |= __SHIFTIN(1, PCIE_DCSR_MAX_PAYLOAD); HWRITE4(sc, PCIE_RC_CONFIG_DCSR, status); - /* Create extents for our address space. */ - sc->sc_regionex = extent_create("rkpcie", sc->sc_axi_addr, - sc->sc_axi_addr - 1 + 64 * 1048576, NULL, 0, EX_WAITOK); - if (sc->sc_regionex == NULL) { - aprint_error_dev(self, "extent_create failed\n"); - return; + /* Default bus ranges */ + sc->sc_phsc.sc_bus_min = 0; + sc->sc_phsc.sc_bus_max = 31; + + /* Override bus range from DT */ + bus_range = fdtbus_get_prop(phandle, "bus-range", &len); + if (len == 8) { + sc->sc_phsc.sc_bus_min = be32dec(&bus_range[0]); + sc->sc_phsc.sc_bus_max = be32dec(&bus_range[1]); } - /* Set up bus range. */ -#if notyet - if (OF_getpropintarray(phandle, "bus-range", bus_range, - sizeof(bus_range)) != sizeof(bus_range) || - bus_range[0] >= 32 || bus_range[1] >= 32) { - bus_range[0] = 0; - bus_range[1] = 31; - } -#else - bus_range[0] = rk3399_pcie_bus_range[0]; - bus_range[1] = rk3399_pcie_bus_range[1]; -#endif - sc->sc_phsc.sc_bus_min = bus_range[0]; - sc->sc_phsc.sc_bus_max = bus_range[1]; - if (sc->sc_phsc.sc_bus_min != 0) { aprint_error_dev(self, "bus-range doesn't start at 0\n"); return; } - sc->sc_phsc.sc_pci_ranges = rk3399_pcie_ranges; - sc->sc_phsc.sc_pci_ranges_cells = __arraycount(rk3399_pcie_ranges); - /* Configure Address Translation. */ rkpcie_atr_init(sc); @@ -474,25 +447,28 @@ again: static void rkpcie_atr_init(struct rkpcie_softc *sc) { - struct extent * const ex = sc->sc_regionex; + const u_int *ranges; bus_addr_t aaddr; bus_addr_t addr; bus_size_t size, offset; uint32_t type; - int region, i; - - /* get root bus's config space out of the APB space */ - bus_space_subregion(sc->sc_iot, sc->sc_ioh, PCIE_RC_NORMAL_BASE, PCI_EXTCONF_SIZE * 8, &sc->sc_bus_cfgh[0]); + int region, i, ranges_len; - const uint32_t *ranges = sc->sc_phsc.sc_pci_ranges; - const int ranges_cells = sc->sc_phsc.sc_pci_ranges_cells; + /* Use region 0 to map PCI configuration space */ + HWRITE4(sc, PCIE_ATR_OB_ADDR0(0), 25 - 1); + HWRITE4(sc, PCIE_ATR_OB_ADDR1(0), 0); + HWRITE4(sc, PCIE_ATR_OB_DESC0(0), + PCIE_ATR_HDR_CFG_TYPE0 | PCIE_ATR_HDR_RID); + HWRITE4(sc, PCIE_ATR_OB_DESC1(0), 0); + + ranges = fdtbus_get_prop(sc->sc_phsc.sc_phandle, "ranges", &ranges_len); + if (ranges == NULL) + goto fail; + const int ranges_cells = ranges_len / 4; for (i = 0; i < ranges_cells; i += 7) { /* Handle IO and MMIO. */ - switch (ranges[i] & 0x03000000) { - case 0x00000000: - type = PCIE_ATR_HDR_CFG_TYPE0; - break; + switch (be32toh(ranges[i]) & 0x03000000) { case 0x01000000: type = PCIE_ATR_HDR_IO; break; @@ -504,13 +480,9 @@ rkpcie_atr_init(struct rkpcie_softc *sc) continue; } - addr = ((uint64_t)ranges[i + 1] << 32) + ranges[i + 2]; - aaddr = ((uint64_t)ranges[i + 3] << 32) + ranges[i + 4]; - size = (uint64_t)ranges[i+5] << 32 | ranges[i + 6]; - - if (type == PCIE_ATR_HDR_CFG_TYPE0) { - addr = __SHIFTOUT(ranges[i], PHYS_HI_BUS) << 20; - } + addr = ((uint64_t)be32toh(ranges[i + 1]) << 32) + be32toh(ranges[i + 2]); + aaddr = ((uint64_t)be32toh(ranges[i + 3]) << 32) + be32toh(ranges[i + 4]); + size = (uint64_t)be32toh(ranges[i + 5]) << 32 | be32toh(ranges[i + 6]); /* Only support mappings aligned on a region boundary. */ if (addr & (PCIE_ATR_OB_REGION_SIZE - 1)) @@ -525,40 +497,19 @@ rkpcie_atr_init(struct rkpcie_softc *sc) goto fail; if (aaddr + size > sc->sc_axi_addr + 64*1024*1024) goto fail; - + + offset = addr - sc->sc_axi_addr - PCIE_ATR_OB_REGION0_SIZE; + region = 1 + (offset / PCIE_ATR_OB_REGION_SIZE); while (size > 0) { - offset = aaddr - sc->sc_axi_addr; - region = (offset / PCIE_ATR_OB_REGION_SIZE); - if (region >= 0x20) - region -= 0x1f; - if (region > 32) - continue; - u_long regionsize = region ? - PCIE_ATR_OB_REGION_SIZE : PCIE_ATR_OB_REGION0_SIZE; - uint32_t regionbits = ilog2(regionsize); - - //printf("%s %lx %lx %lx\n", __func__, addr, aaddr, regionsize); - if (extent_alloc_region(ex, aaddr, regionsize, EX_WAITOK) != 0) - goto fail; - if (type == PCIE_ATR_HDR_CFG_TYPE0) { - const uint32_t bus = (addr >> 20) & 0xff; - if (bus == 0 || - bus >= __arraycount(sc->sc_bus_cfgh)) - continue; - bus_space_map(sc->sc_iot, aaddr, regionsize, 0, &sc->sc_bus_cfgh[bus]); - if (bus > 1) - type = PCIE_ATR_HDR_CFG_TYPE1; - } - HWRITE4(sc, PCIE_ATR_OB_ADDR0(region), - addr | (regionbits-1)); - HWRITE4(sc, PCIE_ATR_OB_ADDR1(region), addr >> 32); + HWRITE4(sc, PCIE_ATR_OB_ADDR0(region), 32 - 1); + HWRITE4(sc, PCIE_ATR_OB_ADDR1(region), 0); HWRITE4(sc, PCIE_ATR_OB_DESC0(region), type | PCIE_ATR_HDR_RID); HWRITE4(sc, PCIE_ATR_OB_DESC1(region), 0); - - aaddr += regionsize; - addr += regionsize; - size -= regionsize; + + addr += PCIE_ATR_OB_REGION_SIZE; + size -= PCIE_ATR_OB_REGION_SIZE; + region++; } } @@ -569,7 +520,6 @@ rkpcie_atr_init(struct rkpcie_softc *sc) return; fail: - extent_print(ex); device_printf(sc->sc_phsc.sc_dev, "can't map ranges\n"); } @@ -579,7 +529,7 @@ rkpcie_bus_maxdevs(void *v, int bus) struct rkpcie_softc *rksc = v; struct pcihost_softc *sc = &rksc->sc_phsc; - if (bus == sc->sc_bus_min) + if (bus == sc->sc_bus_min || bus == sc->sc_bus_min + 1) return 1; return 32; } @@ -603,47 +553,55 @@ rkpcie_decompose_tag(void *v, pcitag_t t } pcireg_t -rkpcie_conf_read(void *v, pcitag_t tag, int reg) +rkpcie_conf_read(void *v, pcitag_t tag, int offset) { struct rkpcie_softc *sc = v; struct pcihost_softc *phsc = &sc->sc_phsc; int bus, dev, fn; - bus_size_t offset; - uint32_t data; + u_int reg; - KASSERT(reg >= 0); - KASSERT(reg < PCI_EXTCONF_SIZE); + KASSERT(offset >= 0); + KASSERT(offset < PCI_EXTCONF_SIZE); rkpcie_decompose_tag(sc, tag, &bus, &dev, &fn); - if (bus > phsc->sc_bus_max) - return 0xffffffff; - if (bus == phsc->sc_bus_min + 1 && dev > 0) - return 0xffffffff; - offset = dev << 15 | fn << 12 | reg; - if (bus_space_peek_4(sc->sc_iot, sc->sc_bus_cfgh[bus], offset, &data) == 0) - return data; - + reg = (bus << 20) | (dev << 15) | (fn << 12) | offset; + + if (bus == phsc->sc_bus_min) { + KASSERT(dev == 0); + return HREAD4(sc, PCIE_RC_NORMAL_BASE + reg); + } + if (bus == phsc->sc_bus_min + 1) { + KASSERT(dev == 0); + return bus_space_read_4(sc->sc_iot, sc->sc_axi_ioh, reg); + } + return 0xffffffff; } void -rkpcie_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) +rkpcie_conf_write(void *v, pcitag_t tag, int offset, pcireg_t data) { struct rkpcie_softc *sc = v; struct pcihost_softc *phsc = &sc->sc_phsc; int bus, dev, fn; - bus_size_t offset; + u_int reg; - KASSERT(reg >= 0); - KASSERT(reg < PCI_EXTCONF_SIZE); + KASSERT(offset >= 0); + KASSERT(offset < PCI_EXTCONF_SIZE); rkpcie_decompose_tag(sc, tag, &bus, &dev, &fn); - if (bus > phsc->sc_bus_max) + reg = (bus << 20) | (dev << 15) | (fn << 12) | offset; + + if (bus == phsc->sc_bus_min) { + KASSERT(dev == 0); + HWRITE4(sc, PCIE_RC_NORMAL_BASE + reg, data); return; - if (bus == phsc->sc_bus_min + 1 && dev > 0) + } + if (bus == phsc->sc_bus_min + 1) { + KASSERT(dev == 0); + bus_space_write_4(sc->sc_iot, sc->sc_axi_ioh, reg, data); return; - offset = dev << 15 | fn << 12 | reg; - bus_space_poke_4(sc->sc_iot, sc->sc_bus_cfgh[bus], offset, data); + } } static int