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

Reply via email to