1*896e217aSJessica Clarke /*- 2*896e217aSJessica Clarke * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*896e217aSJessica Clarke * 4*896e217aSJessica Clarke * Copyright 2021 Jessica Clarke <jrtc27@FreeBSD.org> 5*896e217aSJessica Clarke * 6*896e217aSJessica Clarke * Redistribution and use in source and binary forms, with or without 7*896e217aSJessica Clarke * modification, are permitted provided that the following conditions 8*896e217aSJessica Clarke * are met: 9*896e217aSJessica Clarke * 1. Redistributions of source code must retain the above copyright 10*896e217aSJessica Clarke * notice, this list of conditions and the following disclaimer. 11*896e217aSJessica Clarke * 2. Redistributions in binary form must reproduce the above copyright 12*896e217aSJessica Clarke * notice, this list of conditions and the following disclaimer in the 13*896e217aSJessica Clarke * documentation and/or other materials provided with the distribution. 14*896e217aSJessica Clarke * 15*896e217aSJessica Clarke * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16*896e217aSJessica Clarke * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17*896e217aSJessica Clarke * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18*896e217aSJessica Clarke * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19*896e217aSJessica Clarke * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20*896e217aSJessica Clarke * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21*896e217aSJessica Clarke * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22*896e217aSJessica Clarke * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23*896e217aSJessica Clarke * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24*896e217aSJessica Clarke * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25*896e217aSJessica Clarke * SUCH DAMAGE. 26*896e217aSJessica Clarke * 27*896e217aSJessica Clarke */ 28*896e217aSJessica Clarke 29*896e217aSJessica Clarke /* SiFive FU740 DesignWare PCIe driver */ 30*896e217aSJessica Clarke 31*896e217aSJessica Clarke #include <sys/cdefs.h> 32*896e217aSJessica Clarke __FBSDID("$FreeBSD$"); 33*896e217aSJessica Clarke 34*896e217aSJessica Clarke #include <sys/param.h> 35*896e217aSJessica Clarke #include <sys/systm.h> 36*896e217aSJessica Clarke #include <sys/bus.h> 37*896e217aSJessica Clarke #include <sys/gpio.h> 38*896e217aSJessica Clarke #include <sys/kernel.h> 39*896e217aSJessica Clarke #include <sys/module.h> 40*896e217aSJessica Clarke #include <sys/rman.h> 41*896e217aSJessica Clarke 42*896e217aSJessica Clarke #include <machine/bus.h> 43*896e217aSJessica Clarke #include <machine/intr.h> 44*896e217aSJessica Clarke #include <machine/resource.h> 45*896e217aSJessica Clarke 46*896e217aSJessica Clarke #include <dev/extres/clk/clk.h> 47*896e217aSJessica Clarke #include <dev/extres/hwreset/hwreset.h> 48*896e217aSJessica Clarke #include <dev/gpio/gpiobusvar.h> 49*896e217aSJessica Clarke #include <dev/ofw/ofw_bus.h> 50*896e217aSJessica Clarke #include <dev/ofw/ofw_bus_subr.h> 51*896e217aSJessica Clarke #include <dev/ofw/ofw_pci.h> 52*896e217aSJessica Clarke #include <dev/ofw/ofwpci.h> 53*896e217aSJessica Clarke #include <dev/pci/pcivar.h> 54*896e217aSJessica Clarke #include <dev/pci/pcireg.h> 55*896e217aSJessica Clarke #include <dev/pci/pcib_private.h> 56*896e217aSJessica Clarke #include <dev/pci/pci_dw.h> 57*896e217aSJessica Clarke 58*896e217aSJessica Clarke #include "pcib_if.h" 59*896e217aSJessica Clarke #include "pci_dw_if.h" 60*896e217aSJessica Clarke 61*896e217aSJessica Clarke #define FUDW_PHYS 2 62*896e217aSJessica Clarke #define FUDW_LANES_PER_PHY 4 63*896e217aSJessica Clarke 64*896e217aSJessica Clarke #define FUDW_MGMT_PERST_N 0x0 65*896e217aSJessica Clarke #define FUDW_MGMT_LTSSM_EN 0x10 66*896e217aSJessica Clarke #define FUDW_MGMT_HOLD_PHY_RST 0x18 67*896e217aSJessica Clarke #define FUDW_MGMT_DEVICE_TYPE 0x708 68*896e217aSJessica Clarke #define FUDW_MGMT_DEVICE_TYPE_RC 0x4 69*896e217aSJessica Clarke #define FUDW_MGMT_PHY_CR_PARA_REG(_n, _r) \ 70*896e217aSJessica Clarke (0x860 + (_n) * 0x40 + FUDW_MGMT_PHY_CR_PARA_##_r) 71*896e217aSJessica Clarke #define FUDW_MGMT_PHY_CR_PARA_ADDR 0x0 72*896e217aSJessica Clarke #define FUDW_MGMT_PHY_CR_PARA_READ_EN 0x10 73*896e217aSJessica Clarke #define FUDW_MGMT_PHY_CR_PARA_READ_DATA 0x18 74*896e217aSJessica Clarke #define FUDW_MGMT_PHY_CR_PARA_SEL 0x20 75*896e217aSJessica Clarke #define FUDW_MGMT_PHY_CR_PARA_WRITE_DATA 0x28 76*896e217aSJessica Clarke #define FUDW_MGMT_PHY_CR_PARA_WRITE_EN 0x30 77*896e217aSJessica Clarke #define FUDW_MGMT_PHY_CR_PARA_ACK 0x38 78*896e217aSJessica Clarke 79*896e217aSJessica Clarke #define FUDW_MGMT_PHY_LANE(_n) (0x1008 + (_n) * 0x100) 80*896e217aSJessica Clarke #define FUDW_MGMT_PHY_LANE_CDR_TRACK_EN (1 << 0) 81*896e217aSJessica Clarke #define FUDW_MGMT_PHY_LANE_LOS_THRESH (1 << 5) 82*896e217aSJessica Clarke #define FUDW_MGMT_PHY_LANE_TERM_EN (1 << 9) 83*896e217aSJessica Clarke #define FUDW_MGMT_PHY_LANE_TERM_ACDC (1 << 10) 84*896e217aSJessica Clarke #define FUDW_MGMT_PHY_LANE_EN (1 << 11) 85*896e217aSJessica Clarke #define FUDW_MGMT_PHY_LANE_INIT \ 86*896e217aSJessica Clarke (FUDW_MGMT_PHY_LANE_CDR_TRACK_EN | FUDW_MGMT_PHY_LANE_LOS_THRESH | \ 87*896e217aSJessica Clarke FUDW_MGMT_PHY_LANE_TERM_EN | FUDW_MGMT_PHY_LANE_TERM_ACDC | \ 88*896e217aSJessica Clarke FUDW_MGMT_PHY_LANE_EN) 89*896e217aSJessica Clarke 90*896e217aSJessica Clarke #define FUDW_DBI_PORT_DBG1 0x72c 91*896e217aSJessica Clarke #define FUDW_DBI_PORT_DBG1_LINK_UP (1 << 4) 92*896e217aSJessica Clarke #define FUDW_DBI_PORT_DBG1_LINK_IN_TRAINING (1 << 29) 93*896e217aSJessica Clarke 94*896e217aSJessica Clarke struct fupci_softc { 95*896e217aSJessica Clarke struct pci_dw_softc dw_sc; 96*896e217aSJessica Clarke device_t dev; 97*896e217aSJessica Clarke struct resource *mgmt_res; 98*896e217aSJessica Clarke gpio_pin_t porst_pin; 99*896e217aSJessica Clarke gpio_pin_t pwren_pin; 100*896e217aSJessica Clarke clk_t pcie_aux_clk; 101*896e217aSJessica Clarke hwreset_t pcie_aux_rst; 102*896e217aSJessica Clarke }; 103*896e217aSJessica Clarke 104*896e217aSJessica Clarke #define FUDW_MGMT_READ(_sc, _o) bus_read_4((_sc)->mgmt_res, (_o)) 105*896e217aSJessica Clarke #define FUDW_MGMT_WRITE(_sc, _o, _v) bus_write_4((_sc)->mgmt_res, (_o), (_v)) 106*896e217aSJessica Clarke 107*896e217aSJessica Clarke static struct ofw_compat_data compat_data[] = { 108*896e217aSJessica Clarke { "sifive,fu740-pcie", 1 }, 109*896e217aSJessica Clarke { NULL, 0 }, 110*896e217aSJessica Clarke }; 111*896e217aSJessica Clarke 112*896e217aSJessica Clarke /* Currently unused; included for completeness */ 113*896e217aSJessica Clarke static int __unused 114*896e217aSJessica Clarke fupci_phy_read(struct fupci_softc *sc, int phy, uint32_t reg, uint32_t *val) 115*896e217aSJessica Clarke { 116*896e217aSJessica Clarke unsigned timeout; 117*896e217aSJessica Clarke uint32_t ack; 118*896e217aSJessica Clarke 119*896e217aSJessica Clarke FUDW_MGMT_WRITE(sc, FUDW_MGMT_PHY_CR_PARA_REG(phy, ADDR), reg); 120*896e217aSJessica Clarke FUDW_MGMT_WRITE(sc, FUDW_MGMT_PHY_CR_PARA_REG(phy, READ_EN), 1); 121*896e217aSJessica Clarke 122*896e217aSJessica Clarke timeout = 10; 123*896e217aSJessica Clarke do { 124*896e217aSJessica Clarke ack = FUDW_MGMT_READ(sc, FUDW_MGMT_PHY_CR_PARA_REG(phy, ACK)); 125*896e217aSJessica Clarke if (ack != 0) 126*896e217aSJessica Clarke break; 127*896e217aSJessica Clarke DELAY(10); 128*896e217aSJessica Clarke } while (--timeout > 0); 129*896e217aSJessica Clarke 130*896e217aSJessica Clarke if (timeout == 0) { 131*896e217aSJessica Clarke device_printf(sc->dev, "Timeout waiting for read ACK\n"); 132*896e217aSJessica Clarke return (ETIMEDOUT); 133*896e217aSJessica Clarke } 134*896e217aSJessica Clarke 135*896e217aSJessica Clarke *val = FUDW_MGMT_READ(sc, FUDW_MGMT_PHY_CR_PARA_REG(phy, READ_DATA)); 136*896e217aSJessica Clarke FUDW_MGMT_WRITE(sc, FUDW_MGMT_PHY_CR_PARA_REG(phy, READ_EN), 0); 137*896e217aSJessica Clarke 138*896e217aSJessica Clarke timeout = 10; 139*896e217aSJessica Clarke do { 140*896e217aSJessica Clarke ack = FUDW_MGMT_READ(sc, FUDW_MGMT_PHY_CR_PARA_REG(phy, ACK)); 141*896e217aSJessica Clarke if (ack == 0) 142*896e217aSJessica Clarke break; 143*896e217aSJessica Clarke DELAY(10); 144*896e217aSJessica Clarke } while (--timeout > 0); 145*896e217aSJessica Clarke 146*896e217aSJessica Clarke if (timeout == 0) { 147*896e217aSJessica Clarke device_printf(sc->dev, "Timeout waiting for read un-ACK\n"); 148*896e217aSJessica Clarke return (ETIMEDOUT); 149*896e217aSJessica Clarke } 150*896e217aSJessica Clarke 151*896e217aSJessica Clarke return (0); 152*896e217aSJessica Clarke } 153*896e217aSJessica Clarke 154*896e217aSJessica Clarke static int 155*896e217aSJessica Clarke fupci_phy_write(struct fupci_softc *sc, int phy, uint32_t reg, uint32_t val) 156*896e217aSJessica Clarke { 157*896e217aSJessica Clarke unsigned timeout; 158*896e217aSJessica Clarke uint32_t ack; 159*896e217aSJessica Clarke 160*896e217aSJessica Clarke FUDW_MGMT_WRITE(sc, FUDW_MGMT_PHY_CR_PARA_REG(phy, ADDR), reg); 161*896e217aSJessica Clarke FUDW_MGMT_WRITE(sc, FUDW_MGMT_PHY_CR_PARA_REG(phy, WRITE_DATA), val); 162*896e217aSJessica Clarke FUDW_MGMT_WRITE(sc, FUDW_MGMT_PHY_CR_PARA_REG(phy, WRITE_EN), 1); 163*896e217aSJessica Clarke 164*896e217aSJessica Clarke timeout = 10; 165*896e217aSJessica Clarke do { 166*896e217aSJessica Clarke ack = FUDW_MGMT_READ(sc, FUDW_MGMT_PHY_CR_PARA_REG(phy, ACK)); 167*896e217aSJessica Clarke if (ack != 0) 168*896e217aSJessica Clarke break; 169*896e217aSJessica Clarke DELAY(10); 170*896e217aSJessica Clarke } while (--timeout > 0); 171*896e217aSJessica Clarke 172*896e217aSJessica Clarke if (timeout == 0) { 173*896e217aSJessica Clarke device_printf(sc->dev, "Timeout waiting for write ACK\n"); 174*896e217aSJessica Clarke return (ETIMEDOUT); 175*896e217aSJessica Clarke } 176*896e217aSJessica Clarke 177*896e217aSJessica Clarke FUDW_MGMT_WRITE(sc, FUDW_MGMT_PHY_CR_PARA_REG(phy, WRITE_EN), 0); 178*896e217aSJessica Clarke 179*896e217aSJessica Clarke timeout = 10; 180*896e217aSJessica Clarke do { 181*896e217aSJessica Clarke ack = FUDW_MGMT_READ(sc, FUDW_MGMT_PHY_CR_PARA_REG(phy, ACK)); 182*896e217aSJessica Clarke if (ack == 0) 183*896e217aSJessica Clarke break; 184*896e217aSJessica Clarke DELAY(10); 185*896e217aSJessica Clarke } while (--timeout > 0); 186*896e217aSJessica Clarke 187*896e217aSJessica Clarke if (timeout == 0) { 188*896e217aSJessica Clarke device_printf(sc->dev, "Timeout waiting for write un-ACK\n"); 189*896e217aSJessica Clarke return (ETIMEDOUT); 190*896e217aSJessica Clarke } 191*896e217aSJessica Clarke 192*896e217aSJessica Clarke return (0); 193*896e217aSJessica Clarke } 194*896e217aSJessica Clarke 195*896e217aSJessica Clarke static int 196*896e217aSJessica Clarke fupci_phy_init(struct fupci_softc *sc) 197*896e217aSJessica Clarke { 198*896e217aSJessica Clarke device_t dev; 199*896e217aSJessica Clarke int error, phy, lane; 200*896e217aSJessica Clarke 201*896e217aSJessica Clarke dev = sc->dev; 202*896e217aSJessica Clarke 203*896e217aSJessica Clarke /* Assert core power-on reset (active low) */ 204*896e217aSJessica Clarke error = gpio_pin_set_active(sc->porst_pin, false); 205*896e217aSJessica Clarke if (error != 0) { 206*896e217aSJessica Clarke device_printf(dev, "Cannot assert power-on reset: %d\n", 207*896e217aSJessica Clarke error); 208*896e217aSJessica Clarke return (error); 209*896e217aSJessica Clarke } 210*896e217aSJessica Clarke 211*896e217aSJessica Clarke /* Assert PERST_N */ 212*896e217aSJessica Clarke FUDW_MGMT_WRITE(sc, FUDW_MGMT_PERST_N, 0); 213*896e217aSJessica Clarke 214*896e217aSJessica Clarke /* Enable power */ 215*896e217aSJessica Clarke error = gpio_pin_set_active(sc->pwren_pin, true); 216*896e217aSJessica Clarke if (error != 0) { 217*896e217aSJessica Clarke device_printf(dev, "Cannot enable power: %d\n", error); 218*896e217aSJessica Clarke return (error); 219*896e217aSJessica Clarke } 220*896e217aSJessica Clarke 221*896e217aSJessica Clarke /* Hold PERST for 100ms as per the PCIe spec */ 222*896e217aSJessica Clarke DELAY(100); 223*896e217aSJessica Clarke 224*896e217aSJessica Clarke /* Deassert PERST_N */ 225*896e217aSJessica Clarke FUDW_MGMT_WRITE(sc, FUDW_MGMT_PERST_N, 1); 226*896e217aSJessica Clarke 227*896e217aSJessica Clarke /* Deassert core power-on reset (active low) */ 228*896e217aSJessica Clarke error = gpio_pin_set_active(sc->porst_pin, true); 229*896e217aSJessica Clarke if (error != 0) { 230*896e217aSJessica Clarke device_printf(dev, "Cannot deassert power-on reset: %d\n", 231*896e217aSJessica Clarke error); 232*896e217aSJessica Clarke return (error); 233*896e217aSJessica Clarke } 234*896e217aSJessica Clarke 235*896e217aSJessica Clarke /* Enable the aux clock */ 236*896e217aSJessica Clarke error = clk_enable(sc->pcie_aux_clk); 237*896e217aSJessica Clarke if (error != 0) { 238*896e217aSJessica Clarke device_printf(dev, "Cannot enable aux clock: %d\n", error); 239*896e217aSJessica Clarke return (error); 240*896e217aSJessica Clarke } 241*896e217aSJessica Clarke 242*896e217aSJessica Clarke /* Hold LTSSM in reset whilst initialising the PHYs */ 243*896e217aSJessica Clarke FUDW_MGMT_WRITE(sc, FUDW_MGMT_HOLD_PHY_RST, 1); 244*896e217aSJessica Clarke 245*896e217aSJessica Clarke /* Deassert the aux reset */ 246*896e217aSJessica Clarke error = hwreset_deassert(sc->pcie_aux_rst); 247*896e217aSJessica Clarke if (error != 0) { 248*896e217aSJessica Clarke device_printf(dev, "Cannot deassert aux reset: %d\n", error); 249*896e217aSJessica Clarke return (error); 250*896e217aSJessica Clarke } 251*896e217aSJessica Clarke 252*896e217aSJessica Clarke /* Enable control register interface */ 253*896e217aSJessica Clarke for (phy = 0; phy < FUDW_PHYS; ++phy) 254*896e217aSJessica Clarke FUDW_MGMT_WRITE(sc, FUDW_MGMT_PHY_CR_PARA_REG(phy, SEL), 1); 255*896e217aSJessica Clarke 256*896e217aSJessica Clarke /* Wait for enable to take effect */ 257*896e217aSJessica Clarke DELAY(1); 258*896e217aSJessica Clarke 259*896e217aSJessica Clarke /* Initialise lane configuration */ 260*896e217aSJessica Clarke for (phy = 0; phy < FUDW_PHYS; ++phy) { 261*896e217aSJessica Clarke for (lane = 0; lane < FUDW_LANES_PER_PHY; ++lane) 262*896e217aSJessica Clarke fupci_phy_write(sc, phy, FUDW_MGMT_PHY_LANE(lane), 263*896e217aSJessica Clarke FUDW_MGMT_PHY_LANE_INIT); 264*896e217aSJessica Clarke } 265*896e217aSJessica Clarke 266*896e217aSJessica Clarke /* Disable the aux clock whilst taking the LTSSM out of reset */ 267*896e217aSJessica Clarke error = clk_disable(sc->pcie_aux_clk); 268*896e217aSJessica Clarke if (error != 0) { 269*896e217aSJessica Clarke device_printf(dev, "Cannot disable aux clock: %d\n", error); 270*896e217aSJessica Clarke return (error); 271*896e217aSJessica Clarke } 272*896e217aSJessica Clarke 273*896e217aSJessica Clarke /* Take LTSSM out of reset */ 274*896e217aSJessica Clarke FUDW_MGMT_WRITE(sc, FUDW_MGMT_HOLD_PHY_RST, 0); 275*896e217aSJessica Clarke 276*896e217aSJessica Clarke /* Enable the aux clock again */ 277*896e217aSJessica Clarke error = clk_enable(sc->pcie_aux_clk); 278*896e217aSJessica Clarke if (error != 0) { 279*896e217aSJessica Clarke device_printf(dev, "Cannot re-enable aux clock: %d\n", error); 280*896e217aSJessica Clarke return (error); 281*896e217aSJessica Clarke } 282*896e217aSJessica Clarke 283*896e217aSJessica Clarke /* Put the controller in Root Complex mode */ 284*896e217aSJessica Clarke FUDW_MGMT_WRITE(sc, FUDW_MGMT_DEVICE_TYPE, FUDW_MGMT_DEVICE_TYPE_RC); 285*896e217aSJessica Clarke 286*896e217aSJessica Clarke return (0); 287*896e217aSJessica Clarke } 288*896e217aSJessica Clarke 289*896e217aSJessica Clarke static void 290*896e217aSJessica Clarke fupci_dbi_protect(struct fupci_softc *sc, bool protect) 291*896e217aSJessica Clarke { 292*896e217aSJessica Clarke uint32_t reg; 293*896e217aSJessica Clarke 294*896e217aSJessica Clarke reg = pci_dw_dbi_rd4(sc->dev, DW_MISC_CONTROL_1); 295*896e217aSJessica Clarke if (protect) 296*896e217aSJessica Clarke reg &= ~DBI_RO_WR_EN; 297*896e217aSJessica Clarke else 298*896e217aSJessica Clarke reg |= DBI_RO_WR_EN; 299*896e217aSJessica Clarke pci_dw_dbi_wr4(sc->dev, DW_MISC_CONTROL_1, reg); 300*896e217aSJessica Clarke } 301*896e217aSJessica Clarke 302*896e217aSJessica Clarke static int 303*896e217aSJessica Clarke fupci_init(struct fupci_softc *sc) 304*896e217aSJessica Clarke { 305*896e217aSJessica Clarke /* Enable 32-bit I/O window */ 306*896e217aSJessica Clarke fupci_dbi_protect(sc, false); 307*896e217aSJessica Clarke pci_dw_dbi_wr2(sc->dev, PCIR_IOBASEL_1, 308*896e217aSJessica Clarke (PCIM_BRIO_32 << 8) | PCIM_BRIO_32); 309*896e217aSJessica Clarke fupci_dbi_protect(sc, true); 310*896e217aSJessica Clarke 311*896e217aSJessica Clarke /* Enable LTSSM */ 312*896e217aSJessica Clarke FUDW_MGMT_WRITE(sc, FUDW_MGMT_LTSSM_EN, 1); 313*896e217aSJessica Clarke 314*896e217aSJessica Clarke return (0); 315*896e217aSJessica Clarke } 316*896e217aSJessica Clarke 317*896e217aSJessica Clarke static int 318*896e217aSJessica Clarke fupci_probe(device_t dev) 319*896e217aSJessica Clarke { 320*896e217aSJessica Clarke if (!ofw_bus_status_okay(dev)) 321*896e217aSJessica Clarke return (ENXIO); 322*896e217aSJessica Clarke 323*896e217aSJessica Clarke if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) 324*896e217aSJessica Clarke return (ENXIO); 325*896e217aSJessica Clarke 326*896e217aSJessica Clarke device_set_desc(dev, "SiFive FU740 PCIe Controller"); 327*896e217aSJessica Clarke 328*896e217aSJessica Clarke return (BUS_PROBE_DEFAULT); 329*896e217aSJessica Clarke } 330*896e217aSJessica Clarke 331*896e217aSJessica Clarke static int 332*896e217aSJessica Clarke fupci_attach(device_t dev) 333*896e217aSJessica Clarke { 334*896e217aSJessica Clarke struct fupci_softc *sc; 335*896e217aSJessica Clarke phandle_t node; 336*896e217aSJessica Clarke int error, rid; 337*896e217aSJessica Clarke 338*896e217aSJessica Clarke sc = device_get_softc(dev); 339*896e217aSJessica Clarke node = ofw_bus_get_node(dev); 340*896e217aSJessica Clarke sc->dev = dev; 341*896e217aSJessica Clarke 342*896e217aSJessica Clarke rid = 0; 343*896e217aSJessica Clarke error = ofw_bus_find_string_index(node, "reg-names", "dbi", &rid); 344*896e217aSJessica Clarke if (error != 0) { 345*896e217aSJessica Clarke device_printf(dev, "Cannot get DBI memory: %d\n", error); 346*896e217aSJessica Clarke goto fail; 347*896e217aSJessica Clarke } 348*896e217aSJessica Clarke sc->dw_sc.dbi_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 349*896e217aSJessica Clarke RF_ACTIVE); 350*896e217aSJessica Clarke if (sc->dw_sc.dbi_res == NULL) { 351*896e217aSJessica Clarke device_printf(dev, "Cannot allocate DBI memory\n"); 352*896e217aSJessica Clarke error = ENXIO; 353*896e217aSJessica Clarke goto fail; 354*896e217aSJessica Clarke } 355*896e217aSJessica Clarke 356*896e217aSJessica Clarke rid = 0; 357*896e217aSJessica Clarke error = ofw_bus_find_string_index(node, "reg-names", "mgmt", &rid); 358*896e217aSJessica Clarke if (error != 0) { 359*896e217aSJessica Clarke device_printf(dev, "Cannot get management space memory: %d\n", 360*896e217aSJessica Clarke error); 361*896e217aSJessica Clarke goto fail; 362*896e217aSJessica Clarke } 363*896e217aSJessica Clarke sc->mgmt_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 364*896e217aSJessica Clarke RF_ACTIVE); 365*896e217aSJessica Clarke if (sc->mgmt_res == NULL) { 366*896e217aSJessica Clarke device_printf(dev, "Cannot allocate management space memory\n"); 367*896e217aSJessica Clarke error = ENXIO; 368*896e217aSJessica Clarke goto fail; 369*896e217aSJessica Clarke } 370*896e217aSJessica Clarke 371*896e217aSJessica Clarke error = gpio_pin_get_by_ofw_property(dev, node, "reset-gpios", 372*896e217aSJessica Clarke &sc->porst_pin); 373*896e217aSJessica Clarke /* Old U-Boot device tree uses perstn-gpios */ 374*896e217aSJessica Clarke if (error == ENOENT) 375*896e217aSJessica Clarke error = gpio_pin_get_by_ofw_property(dev, node, "perstn-gpios", 376*896e217aSJessica Clarke &sc->porst_pin); 377*896e217aSJessica Clarke if (error != 0) { 378*896e217aSJessica Clarke device_printf(dev, "Cannot get power-on reset GPIO: %d\n", 379*896e217aSJessica Clarke error); 380*896e217aSJessica Clarke goto fail; 381*896e217aSJessica Clarke } 382*896e217aSJessica Clarke error = gpio_pin_setflags(sc->porst_pin, GPIO_PIN_OUTPUT); 383*896e217aSJessica Clarke if (error != 0) { 384*896e217aSJessica Clarke device_printf(dev, "Cannot configure power-on reset GPIO: %d\n", 385*896e217aSJessica Clarke error); 386*896e217aSJessica Clarke goto fail; 387*896e217aSJessica Clarke } 388*896e217aSJessica Clarke 389*896e217aSJessica Clarke error = gpio_pin_get_by_ofw_property(dev, node, "pwren-gpios", 390*896e217aSJessica Clarke &sc->pwren_pin); 391*896e217aSJessica Clarke if (error != 0) { 392*896e217aSJessica Clarke device_printf(dev, "Cannot get power enable GPIO: %d\n", 393*896e217aSJessica Clarke error); 394*896e217aSJessica Clarke goto fail; 395*896e217aSJessica Clarke } 396*896e217aSJessica Clarke error = gpio_pin_setflags(sc->pwren_pin, GPIO_PIN_OUTPUT); 397*896e217aSJessica Clarke if (error != 0) { 398*896e217aSJessica Clarke device_printf(dev, "Cannot configure power enable GPIO: %d\n", 399*896e217aSJessica Clarke error); 400*896e217aSJessica Clarke goto fail; 401*896e217aSJessica Clarke } 402*896e217aSJessica Clarke 403*896e217aSJessica Clarke error = clk_get_by_ofw_name(dev, node, "pcie_aux", &sc->pcie_aux_clk); 404*896e217aSJessica Clarke /* Old U-Boot device tree uses pcieaux */ 405*896e217aSJessica Clarke if (error == ENOENT) 406*896e217aSJessica Clarke error = clk_get_by_ofw_name(dev, node, "pcieaux", 407*896e217aSJessica Clarke &sc->pcie_aux_clk); 408*896e217aSJessica Clarke if (error != 0) { 409*896e217aSJessica Clarke device_printf(dev, "Cannot get aux clock: %d\n", error); 410*896e217aSJessica Clarke goto fail; 411*896e217aSJessica Clarke } 412*896e217aSJessica Clarke 413*896e217aSJessica Clarke error = hwreset_get_by_ofw_idx(dev, node, 0, &sc->pcie_aux_rst); 414*896e217aSJessica Clarke if (error != 0) { 415*896e217aSJessica Clarke device_printf(dev, "Cannot get aux reset: %d\n", error); 416*896e217aSJessica Clarke goto fail; 417*896e217aSJessica Clarke } 418*896e217aSJessica Clarke 419*896e217aSJessica Clarke error = fupci_phy_init(sc); 420*896e217aSJessica Clarke if (error != 0) 421*896e217aSJessica Clarke goto fail; 422*896e217aSJessica Clarke 423*896e217aSJessica Clarke error = pci_dw_init(dev); 424*896e217aSJessica Clarke if (error != 0) 425*896e217aSJessica Clarke goto fail; 426*896e217aSJessica Clarke 427*896e217aSJessica Clarke error = fupci_init(sc); 428*896e217aSJessica Clarke if (error != 0) 429*896e217aSJessica Clarke goto fail; 430*896e217aSJessica Clarke 431*896e217aSJessica Clarke return (bus_generic_attach(dev)); 432*896e217aSJessica Clarke 433*896e217aSJessica Clarke fail: 434*896e217aSJessica Clarke /* XXX Cleanup */ 435*896e217aSJessica Clarke return (error); 436*896e217aSJessica Clarke } 437*896e217aSJessica Clarke 438*896e217aSJessica Clarke static int 439*896e217aSJessica Clarke fupci_get_link(device_t dev, bool *status) 440*896e217aSJessica Clarke { 441*896e217aSJessica Clarke uint32_t reg; 442*896e217aSJessica Clarke 443*896e217aSJessica Clarke reg = pci_dw_dbi_rd4(dev, FUDW_DBI_PORT_DBG1); 444*896e217aSJessica Clarke *status = (reg & FUDW_DBI_PORT_DBG1_LINK_UP) != 0 && 445*896e217aSJessica Clarke (reg & FUDW_DBI_PORT_DBG1_LINK_IN_TRAINING) == 0; 446*896e217aSJessica Clarke 447*896e217aSJessica Clarke return (0); 448*896e217aSJessica Clarke } 449*896e217aSJessica Clarke 450*896e217aSJessica Clarke static device_method_t fupci_methods[] = { 451*896e217aSJessica Clarke /* Device interface */ 452*896e217aSJessica Clarke DEVMETHOD(device_probe, fupci_probe), 453*896e217aSJessica Clarke DEVMETHOD(device_attach, fupci_attach), 454*896e217aSJessica Clarke 455*896e217aSJessica Clarke /* PCI DW interface */ 456*896e217aSJessica Clarke DEVMETHOD(pci_dw_get_link, fupci_get_link), 457*896e217aSJessica Clarke 458*896e217aSJessica Clarke DEVMETHOD_END 459*896e217aSJessica Clarke }; 460*896e217aSJessica Clarke 461*896e217aSJessica Clarke DEFINE_CLASS_1(pcib, fupci_driver, fupci_methods, 462*896e217aSJessica Clarke sizeof(struct fupci_softc), pci_dw_driver); 463*896e217aSJessica Clarke static devclass_t fupci_devclass; 464*896e217aSJessica Clarke DRIVER_MODULE(fu740_pci_dw, simplebus, fupci_driver, fupci_devclass, 465*896e217aSJessica Clarke NULL, NULL); 466