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