Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm/rockchip Use ranges from the device tree.
details: https://anonhg.NetBSD.org/src/rev/d3da4d930192
branches: trunk
changeset: 451955:d3da4d930192
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Wed Jun 12 22:44:53 2019 +0000
description:
Use ranges from the device tree.
diffstat:
sys/arch/arm/rockchip/rk3399_pcie.c | 182 +++++++++++++----------------------
1 files changed, 70 insertions(+), 112 deletions(-)
diffs (truncated from 311 to 300 lines):
diff -r 4ea1f65b20c9 -r d3da4d930192 sys/arch/arm/rockchip/rk3399_pcie.c
--- a/sys/arch/arm/rockchip/rk3399_pcie.c Wed Jun 12 22:23:50 2019 +0000
+++ b/sys/arch/arm/rockchip/rk3399_pcie.c Wed Jun 12 22:44:53 2019 +0000
@@ -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 <kettenis%openbsd.org@localhost>
*
@@ -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 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 @@
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 @@
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 @@
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;
- /* 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;
+ /* 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]);
}
-#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 @@
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;
+ int region, i, ranges_len;
- /* 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]);
+ /* 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);
- const uint32_t *ranges = sc->sc_phsc.sc_pci_ranges;
- const int ranges_cells = sc->sc_phsc.sc_pci_ranges_cells;
+ 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 @@
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 @@
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 @@
return;
fail:
- extent_print(ex);
device_printf(sc->sc_phsc.sc_dev, "can't map ranges\n");
}
@@ -579,7 +529,7 @@
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 @@
}
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)
Home |
Main Index |
Thread Index |
Old Index