diff options
Diffstat (limited to 'sys/arm64/rockchip/rk_pcie.c')
-rw-r--r-- | sys/arm64/rockchip/rk_pcie.c | 97 |
1 files changed, 70 insertions, 27 deletions
diff --git a/sys/arm64/rockchip/rk_pcie.c b/sys/arm64/rockchip/rk_pcie.c index dabd7931e442..69ae4254a235 100644 --- a/sys/arm64/rockchip/rk_pcie.c +++ b/sys/arm64/rockchip/rk_pcie.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2019 Michal Meloun <mmel@FreeBSD.org> * @@ -28,9 +28,6 @@ /* Rockchip PCIe controller driver */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #include <sys/param.h> #include <sys/systm.h> #include <sys/bus.h> @@ -47,10 +44,10 @@ __FBSDID("$FreeBSD$"); #include <machine/intr.h> #include <machine/resource.h> -#include <dev/extres/clk/clk.h> -#include <dev/extres/hwreset/hwreset.h> -#include <dev/extres/phy/phy.h> -#include <dev/extres/regulator/regulator.h> +#include <dev/clk/clk.h> +#include <dev/hwreset/hwreset.h> +#include <dev/phy/phy.h> +#include <dev/regulator/regulator.h> #include <dev/gpio/gpiobusvar.h> #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> @@ -336,7 +333,7 @@ rk_pcie_map_out_atu(struct rk_pcie_softc *sc, int idx, int type, int num_bits, uint64_t pa) { uint32_t addr0; - uint64_t max_size; + uint64_t max_size __diagused; /* Check HW constrains */ max_size = idx == 0 ? ATU_OB_REGION_0_SIZE: ATU_OB_REGION_SIZE; @@ -405,17 +402,17 @@ rk_pcie_decode_ranges(struct rk_pcie_softc *sc, struct ofw_pci_range *ranges, int i; for (i = 0; i < nranges; i++) { - if ((ranges[i].pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) == - OFW_PCI_PHYS_HI_SPACE_IO) { + switch(ranges[i].pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) { + case OFW_PCI_PHYS_HI_SPACE_IO: if (sc->io_range.size != 0) { device_printf(sc->dev, "Duplicated IO range found in DT\n"); return (ENXIO); } sc->io_range = ranges[i]; - } - if (((ranges[i].pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) == - OFW_PCI_PHYS_HI_SPACE_MEM64)) { + break; + case OFW_PCI_PHYS_HI_SPACE_MEM32: + case OFW_PCI_PHYS_HI_SPACE_MEM64: if (ranges[i].pci_hi & OFW_PCI_PHYS_HI_PREFETCHABLE) { if (sc->pref_mem_range.size != 0) { device_printf(sc->dev, @@ -1143,7 +1140,10 @@ rk_pcie_probe(device_t dev) static int rk_pcie_attach(device_t dev) -{ struct rk_pcie_softc *sc; +{ + struct resource_map_request req; + struct resource_map map; + struct rk_pcie_softc *sc; uint32_t val; int rv, rid, max_speed; @@ -1162,7 +1162,7 @@ rk_pcie_attach(device_t dev) /* Read FDT properties */ rv = rk_pcie_parse_fdt_resources(sc); if (rv != 0) - return (rv); + goto out; sc->coherent = OF_hasprop(sc->node, "dma-coherent"); sc->no_l0s = OF_hasprop(sc->node, "aspm-no-l0s"); @@ -1192,13 +1192,24 @@ rk_pcie_attach(device_t dev) goto out; } sc->axi_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, - RF_ACTIVE); + RF_ACTIVE | RF_UNMAPPED); if (sc->axi_mem_res == NULL) { device_printf(dev, "Cannot allocate 'axi-base' (rid: %d)\n", rid); rv = ENXIO; goto out; } + resource_init_map_request(&req); + req.memattr = VM_MEMATTR_DEVICE_NP; + rv = bus_map_resource(dev, SYS_RES_MEMORY, sc->axi_mem_res, &req, + &map); + if (rv != 0) { + device_printf(dev, "Cannot map 'axi-base' (rid: %d)\n", + rid); + goto out; + } + rman_set_mapping(sc->axi_mem_res, &map); + rv = ofw_bus_find_string_index(sc->node, "reg-names", "apb-base", &rid); if (rv != 0) { device_printf(dev, "Cannot get 'apb-base' memory\n"); @@ -1283,21 +1294,21 @@ rk_pcie_attach(device_t dev) rv = rk_pcie_decode_ranges(sc, sc->ofw_pci.sc_range, sc->ofw_pci.sc_nrange); if (rv != 0) - goto out; + goto out_full; rv = rk_pcie_setup_hw(sc); if (rv != 0) - goto out; + goto out_full; rv = rk_pcie_setup_sw(sc); if (rv != 0) - goto out; + goto out_full; rv = bus_setup_intr(dev, sc->client_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, rk_pcie_client_irq, NULL, sc, &sc->client_irq_cookie); if (rv != 0) { device_printf(dev, "cannot setup client interrupt handler\n"); rv = ENXIO; - goto out; + goto out_full; } rv = bus_setup_intr(dev, sc->legacy_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, @@ -1305,7 +1316,7 @@ rk_pcie_attach(device_t dev) if (rv != 0) { device_printf(dev, "cannot setup client interrupt handler\n"); rv = ENXIO; - goto out; + goto out_full; } rv = bus_setup_intr(dev, sc->sys_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, @@ -1313,7 +1324,7 @@ rk_pcie_attach(device_t dev) if (rv != 0) { device_printf(dev, "cannot setup client interrupt handler\n"); rv = ENXIO; - goto out; + goto out_full; } /* Enable interrupts */ @@ -1344,8 +1355,42 @@ rk_pcie_attach(device_t dev) DELAY(250000); device_add_child(dev, "pci", -1); return (bus_generic_attach(dev)); + +out_full: + bus_teardown_intr(dev, sc->sys_irq_res, sc->sys_irq_cookie); + bus_teardown_intr(dev, sc->legacy_irq_res, sc->legacy_irq_cookie); + bus_teardown_intr(dev, sc->client_irq_res, sc->client_irq_cookie); + ofw_pcib_fini(dev); out: - /* XXX Cleanup */ + bus_dma_tag_destroy(sc->dmat); + bus_free_resource(dev, SYS_RES_IRQ, sc->sys_irq_res); + bus_free_resource(dev, SYS_RES_IRQ, sc->legacy_irq_res); + bus_free_resource(dev, SYS_RES_IRQ, sc->client_irq_res); + bus_free_resource(dev, SYS_RES_MEMORY, sc->apb_mem_res); + bus_free_resource(dev, SYS_RES_MEMORY, sc->axi_mem_res); + /* GPIO */ + gpio_pin_release(sc->gpio_ep); + /* Phys */ + for (int i = 0; i < MAX_LANES; i++) { + phy_release(sc->phys[i]); + } + /* Clocks */ + clk_release(sc->clk_aclk); + clk_release(sc->clk_aclk_perf); + clk_release(sc->clk_hclk); + clk_release(sc->clk_pm); + /* Resets */ + hwreset_release(sc->hwreset_core); + hwreset_release(sc->hwreset_mgmt); + hwreset_release(sc->hwreset_pipe); + hwreset_release(sc->hwreset_pm); + hwreset_release(sc->hwreset_aclk); + hwreset_release(sc->hwreset_pclk); + /* Regulators */ + regulator_release(sc->supply_12v); + regulator_release(sc->supply_3v3); + regulator_release(sc->supply_1v8); + regulator_release(sc->supply_0v9); return (rv); } @@ -1384,6 +1429,4 @@ static device_method_t rk_pcie_methods[] = { DEFINE_CLASS_1(pcib, rk_pcie_driver, rk_pcie_methods, sizeof(struct rk_pcie_softc), ofw_pcib_driver); -static devclass_t rk_pcie_devclass; -DRIVER_MODULE( rk_pcie, simplebus, rk_pcie_driver, rk_pcie_devclass, - NULL, NULL); +DRIVER_MODULE( rk_pcie, simplebus, rk_pcie_driver, NULL, NULL); |