1297717Ssgalabov/*- 2297717Ssgalabov * Copyright (c) 2016 Stanislav Galabov. 3297717Ssgalabov * 4297717Ssgalabov * Redistribution and use in source and binary forms, with or without 5297717Ssgalabov * modification, are permitted provided that the following conditions 6297717Ssgalabov * are met: 7297717Ssgalabov * 1. Redistributions of source code must retain the above copyright 8297717Ssgalabov * notice, this list of conditions and the following disclaimer. 9297717Ssgalabov * 2. Redistributions in binary form must reproduce the above copyright 10297717Ssgalabov * notice, this list of conditions and the following disclaimer in the 11297717Ssgalabov * documentation and/or other materials provided with the distribution. 12297717Ssgalabov * 13297717Ssgalabov * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14297717Ssgalabov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15297717Ssgalabov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16297717Ssgalabov * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17297717Ssgalabov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18297717Ssgalabov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19297717Ssgalabov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20297717Ssgalabov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21297717Ssgalabov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22297717Ssgalabov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23297717Ssgalabov * SUCH DAMAGE. 24297717Ssgalabov */ 25297717Ssgalabov#include <sys/cdefs.h> 26297717Ssgalabov__FBSDID("$FreeBSD$"); 27297717Ssgalabov 28297717Ssgalabov#include <sys/param.h> 29297717Ssgalabov#include <sys/systm.h> 30297717Ssgalabov 31297717Ssgalabov#include <sys/bus.h> 32297717Ssgalabov#include <sys/interrupt.h> 33297717Ssgalabov#include <sys/malloc.h> 34297717Ssgalabov#include <sys/kernel.h> 35297717Ssgalabov#include <sys/module.h> 36297717Ssgalabov#include <sys/rman.h> 37297717Ssgalabov#include <sys/lock.h> 38297717Ssgalabov#include <sys/mutex.h> 39297717Ssgalabov#include <sys/endian.h> 40297717Ssgalabov 41297717Ssgalabov#include <vm/vm.h> 42297717Ssgalabov#include <vm/pmap.h> 43297717Ssgalabov#include <vm/vm_extern.h> 44297717Ssgalabov 45297717Ssgalabov#include <machine/bus.h> 46297717Ssgalabov#include <machine/cpu.h> 47297717Ssgalabov#include <machine/intr.h> 48297717Ssgalabov#include <machine/pmap.h> 49297717Ssgalabov 50297717Ssgalabov#include <dev/pci/pcivar.h> 51297717Ssgalabov#include <dev/pci/pcireg.h> 52297717Ssgalabov 53297717Ssgalabov#include <dev/pci/pcib_private.h> 54297717Ssgalabov 55297717Ssgalabov#include <dev/fdt/fdt_common.h> 56297717Ssgalabov#include <dev/fdt/fdt_clock.h> 57297717Ssgalabov#include <dev/ofw/openfirm.h> 58297717Ssgalabov#include <dev/ofw/ofw_bus.h> 59297717Ssgalabov#include <dev/ofw/ofw_bus_subr.h> 60297717Ssgalabov 61297717Ssgalabov#include <mips/mediatek/mtk_pcie.h> 62297717Ssgalabov#include <mips/mediatek/mtk_soc.h> 63297717Ssgalabov#include <mips/mediatek/mtk_sysctl.h> 64297717Ssgalabov#include <mips/mediatek/fdt_reset.h> 65297717Ssgalabov 66297850Ssgalabov#include "ofw_bus_if.h" 67297717Ssgalabov#include "pcib_if.h" 68297717Ssgalabov#include "pic_if.h" 69297717Ssgalabov 70297717Ssgalabov/* 71297717Ssgalabov * Note: We only support PCIe at the moment. 72297717Ssgalabov * Most SoCs in the Ralink/Mediatek family that we target actually don't 73297717Ssgalabov * support PCI anyway, with the notable exceptions being RT3662/RT3883, which 74297717Ssgalabov * support both PCI and PCIe. If there exists a board based on one of them 75297717Ssgalabov * which is of interest in the future it shouldn't be too hard to enable PCI 76297717Ssgalabov * support for it. 77297717Ssgalabov */ 78297717Ssgalabov 79297717Ssgalabov/* Chip specific function declarations */ 80297717Ssgalabovstatic int mtk_pcie_phy_init(device_t); 81297717Ssgalabovstatic int mtk_pcie_phy_start(device_t); 82297717Ssgalabovstatic int mtk_pcie_phy_stop(device_t); 83297717Ssgalabovstatic int mtk_pcie_phy_mt7621_init(device_t); 84297717Ssgalabovstatic int mtk_pcie_phy_mt7628_init(device_t); 85297717Ssgalabovstatic int mtk_pcie_phy_mt7620_init(device_t); 86297717Ssgalabovstatic int mtk_pcie_phy_rt3883_init(device_t); 87297717Ssgalabovstatic void mtk_pcie_phy_setup_slots(device_t); 88297717Ssgalabov 89297717Ssgalabov/* Generic declarations */ 90297717Ssgalabovstruct mtx mtk_pci_mtx; 91297717SsgalabovMTX_SYSINIT(mtk_pci_mtx, &mtk_pci_mtx, "MTK PCIe mutex", MTX_SPIN); 92297717Ssgalabov 93297717Ssgalabovstatic int mtk_pci_intr(void *); 94297717Ssgalabov 95297717Ssgalabovstatic struct mtk_pci_softc *mt_sc = NULL; 96297717Ssgalabov 97297717Ssgalabovstruct mtk_pci_range { 98297717Ssgalabov u_long base; 99297717Ssgalabov u_long len; 100297717Ssgalabov}; 101297717Ssgalabov 102298059Ssgalabov#define FDT_RANGES_CELLS ((1 + 2 + 3) * 2) 103297717Ssgalabov 104297717Ssgalabovstatic void 105297717Ssgalabovmtk_pci_range_dump(struct mtk_pci_range *range) 106297717Ssgalabov{ 107297717Ssgalabov#ifdef DEBUG 108297717Ssgalabov printf("\n"); 109297717Ssgalabov printf(" base = 0x%08lx\n", range->base); 110297717Ssgalabov printf(" len = 0x%08lx\n", range->len); 111297717Ssgalabov#endif 112297717Ssgalabov} 113297717Ssgalabov 114297717Ssgalabovstatic int 115297717Ssgalabovmtk_pci_ranges_decode(phandle_t node, struct mtk_pci_range *io_space, 116297717Ssgalabov struct mtk_pci_range *mem_space) 117297717Ssgalabov{ 118297717Ssgalabov struct mtk_pci_range *pci_space; 119297717Ssgalabov pcell_t ranges[FDT_RANGES_CELLS]; 120298059Ssgalabov pcell_t addr_cells, size_cells, par_addr_cells; 121297717Ssgalabov pcell_t *rangesptr; 122297717Ssgalabov pcell_t cell0, cell1, cell2; 123298059Ssgalabov int tuple_size, tuples, i, rv, len; 124297717Ssgalabov 125297717Ssgalabov /* 126297717Ssgalabov * Retrieve 'ranges' property. 127297717Ssgalabov */ 128298059Ssgalabov if ((fdt_addrsize_cells(node, &addr_cells, &size_cells)) != 0) 129297717Ssgalabov return (EINVAL); 130298059Ssgalabov if (addr_cells != 3 || size_cells != 2) 131298059Ssgalabov return (ERANGE); 132297717Ssgalabov 133298059Ssgalabov par_addr_cells = fdt_parent_addr_cells(node); 134298059Ssgalabov if (par_addr_cells != 1) 135298059Ssgalabov return (ERANGE); 136298059Ssgalabov 137297717Ssgalabov len = OF_getproplen(node, "ranges"); 138298059Ssgalabov if (len > sizeof(ranges)) 139297717Ssgalabov return (ENOMEM); 140297717Ssgalabov 141298059Ssgalabov if (OF_getprop(node, "ranges", ranges, sizeof(ranges)) <= 0) 142297717Ssgalabov return (EINVAL); 143297717Ssgalabov 144298059Ssgalabov tuple_size = sizeof(pcell_t) * (addr_cells + par_addr_cells + 145298059Ssgalabov size_cells); 146298059Ssgalabov tuples = len / tuple_size; 147297717Ssgalabov 148297717Ssgalabov /* 149297717Ssgalabov * Initialize the ranges so that we don't have to worry about 150297717Ssgalabov * having them all defined in the FDT. In particular, it is 151297717Ssgalabov * perfectly fine not to want I/O space on PCI busses. 152297717Ssgalabov */ 153297717Ssgalabov bzero(io_space, sizeof(*io_space)); 154297717Ssgalabov bzero(mem_space, sizeof(*mem_space)); 155297717Ssgalabov 156297717Ssgalabov rangesptr = &ranges[0]; 157297717Ssgalabov for (i = 0; i < tuples; i++) { 158297717Ssgalabov cell0 = fdt_data_get((void *)rangesptr, 1); 159297717Ssgalabov rangesptr++; 160297717Ssgalabov cell1 = fdt_data_get((void *)rangesptr, 1); 161297717Ssgalabov rangesptr++; 162297717Ssgalabov cell2 = fdt_data_get((void *)rangesptr, 1); 163297717Ssgalabov rangesptr++; 164297717Ssgalabov 165298059Ssgalabov if (cell0 & 0x02000000) { 166297717Ssgalabov pci_space = mem_space; 167298059Ssgalabov } else if (cell0 & 0x01000000) { 168297717Ssgalabov pci_space = io_space; 169297717Ssgalabov } else { 170297717Ssgalabov rv = ERANGE; 171297717Ssgalabov goto out; 172297717Ssgalabov } 173297717Ssgalabov 174298059Ssgalabov pci_space->base = fdt_data_get((void *)rangesptr, 175298059Ssgalabov par_addr_cells); 176298059Ssgalabov rangesptr += par_addr_cells; 177298059Ssgalabov 178298059Ssgalabov pci_space->len = fdt_data_get((void *)rangesptr, size_cells); 179298059Ssgalabov rangesptr += size_cells; 180297717Ssgalabov } 181297717Ssgalabov 182297717Ssgalabov rv = 0; 183297717Ssgalabovout: 184297717Ssgalabov return (rv); 185297717Ssgalabov} 186297717Ssgalabov 187297717Ssgalabovstatic int 188297717Ssgalabovmtk_pci_ranges(phandle_t node, struct mtk_pci_range *io_space, 189297717Ssgalabov struct mtk_pci_range *mem_space) 190297717Ssgalabov{ 191297717Ssgalabov int err; 192297717Ssgalabov 193297717Ssgalabov if ((err = mtk_pci_ranges_decode(node, io_space, mem_space)) != 0) { 194297717Ssgalabov return (err); 195297717Ssgalabov } 196297717Ssgalabov 197297717Ssgalabov mtk_pci_range_dump(io_space); 198297717Ssgalabov mtk_pci_range_dump(mem_space); 199297717Ssgalabov 200297717Ssgalabov return (0); 201297717Ssgalabov} 202297717Ssgalabov 203297717Ssgalabovstatic struct ofw_compat_data compat_data[] = { 204298350Ssgalabov { "ralink,rt3883-pci", MTK_SOC_RT3883 }, 205298350Ssgalabov { "mediatek,mt7620-pci", MTK_SOC_MT7620A }, 206300014Ssgalabov { "mediatek,mt7628-pci", MTK_SOC_MT7628 }, 207298059Ssgalabov { "mediatek,mt7621-pci", MTK_SOC_MT7621 }, 208297717Ssgalabov { NULL, MTK_SOC_UNKNOWN } 209297717Ssgalabov}; 210297717Ssgalabov 211297717Ssgalabovstatic int 212297717Ssgalabovmtk_pci_probe(device_t dev) 213297717Ssgalabov{ 214297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 215297717Ssgalabov 216297717Ssgalabov if (!ofw_bus_status_okay(dev)) 217297717Ssgalabov return (ENXIO); 218297717Ssgalabov 219297717Ssgalabov sc->socid = ofw_bus_search_compatible(dev, compat_data)->ocd_data; 220297717Ssgalabov if (sc->socid == MTK_SOC_UNKNOWN) 221297717Ssgalabov return (ENXIO); 222297717Ssgalabov 223297717Ssgalabov device_set_desc(dev, "MTK PCIe Controller"); 224297717Ssgalabov 225297717Ssgalabov return (0); 226297717Ssgalabov} 227297717Ssgalabov 228297717Ssgalabovstatic int 229297717Ssgalabovmtk_pci_attach(device_t dev) 230297717Ssgalabov{ 231297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 232297717Ssgalabov struct mtk_pci_range io_space, mem_space; 233297717Ssgalabov phandle_t node; 234297717Ssgalabov intptr_t xref; 235297717Ssgalabov int i, rid; 236297717Ssgalabov 237297717Ssgalabov sc->sc_dev = dev; 238297717Ssgalabov mt_sc = sc; 239297717Ssgalabov sc->addr_mask = 0xffffffff; 240297717Ssgalabov 241297717Ssgalabov /* Request our memory */ 242297717Ssgalabov rid = 0; 243297717Ssgalabov sc->pci_res[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 244297717Ssgalabov RF_ACTIVE); 245297717Ssgalabov if (sc->pci_res[0] == NULL) { 246297717Ssgalabov device_printf(dev, "could not allocate memory resource\n"); 247297717Ssgalabov return (ENXIO); 248297717Ssgalabov } 249297717Ssgalabov 250297717Ssgalabov /* See how many interrupts we need */ 251297717Ssgalabov if (sc->socid == MTK_SOC_MT7621) 252297717Ssgalabov sc->sc_num_irq = 3; 253297717Ssgalabov else { 254297717Ssgalabov sc->sc_num_irq = 1; 255297717Ssgalabov sc->pci_res[2] = sc->pci_res[3] = NULL; 256297717Ssgalabov sc->pci_intrhand[1] = sc->pci_intrhand[2] = NULL; 257297717Ssgalabov } 258297717Ssgalabov 259297717Ssgalabov /* Request our interrupts */ 260297717Ssgalabov for (i = 1; i <= sc->sc_num_irq ; i++) { 261297717Ssgalabov rid = i - 1; 262297717Ssgalabov sc->pci_res[i] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 263297717Ssgalabov RF_ACTIVE); 264297717Ssgalabov if (sc->pci_res[i] == NULL) { 265297717Ssgalabov device_printf(dev, "could not allocate interrupt " 266297717Ssgalabov "resource %d\n", rid); 267297717Ssgalabov goto cleanup_res; 268297717Ssgalabov } 269297717Ssgalabov } 270297717Ssgalabov 271297717Ssgalabov /* Parse our PCI 'ranges' property */ 272297717Ssgalabov node = ofw_bus_get_node(dev); 273297717Ssgalabov xref = OF_xref_from_node(node); 274297717Ssgalabov if (mtk_pci_ranges(node, &io_space, &mem_space)) { 275297717Ssgalabov device_printf(dev, "could not retrieve 'ranges' data\n"); 276297717Ssgalabov goto cleanup_res; 277297717Ssgalabov } 278297717Ssgalabov 279297717Ssgalabov /* Memory, I/O and IRQ resource limits */ 280297717Ssgalabov sc->sc_io_base = io_space.base; 281297717Ssgalabov sc->sc_io_size = io_space.len; 282297717Ssgalabov sc->sc_mem_base = mem_space.base; 283297717Ssgalabov sc->sc_mem_size = mem_space.len; 284297717Ssgalabov sc->sc_irq_start = MTK_PCIE0_IRQ; 285297717Ssgalabov sc->sc_irq_end = MTK_PCIE2_IRQ; 286297717Ssgalabov 287297717Ssgalabov /* Init resource managers for memory, I/O and IRQ */ 288297717Ssgalabov sc->sc_mem_rman.rm_type = RMAN_ARRAY; 289297717Ssgalabov sc->sc_mem_rman.rm_descr = "mtk pcie memory window"; 290297717Ssgalabov if (rman_init(&sc->sc_mem_rman) != 0 || 291297717Ssgalabov rman_manage_region(&sc->sc_mem_rman, sc->sc_mem_base, 292297717Ssgalabov sc->sc_mem_base + sc->sc_mem_size - 1) != 0) { 293297717Ssgalabov device_printf(dev, "failed to setup memory rman\n"); 294297717Ssgalabov goto cleanup_res; 295297717Ssgalabov } 296297717Ssgalabov 297297717Ssgalabov sc->sc_io_rman.rm_type = RMAN_ARRAY; 298297717Ssgalabov sc->sc_io_rman.rm_descr = "mtk pcie io window"; 299297717Ssgalabov if (rman_init(&sc->sc_io_rman) != 0 || 300297717Ssgalabov rman_manage_region(&sc->sc_io_rman, sc->sc_io_base, 301297717Ssgalabov sc->sc_io_base + sc->sc_io_size - 1) != 0) { 302297717Ssgalabov device_printf(dev, "failed to setup io rman\n"); 303297717Ssgalabov goto cleanup_res; 304297717Ssgalabov } 305297717Ssgalabov 306297717Ssgalabov sc->sc_irq_rman.rm_type = RMAN_ARRAY; 307297717Ssgalabov sc->sc_irq_rman.rm_descr = "mtk pcie irqs"; 308297717Ssgalabov if (rman_init(&sc->sc_irq_rman) != 0 || 309297717Ssgalabov rman_manage_region(&sc->sc_irq_rman, sc->sc_irq_start, 310297717Ssgalabov sc->sc_irq_end) != 0) { 311297717Ssgalabov device_printf(dev, "failed to setup irq rman\n"); 312297717Ssgalabov goto cleanup_res; 313297717Ssgalabov } 314297717Ssgalabov 315297717Ssgalabov /* Do SoC-specific PCIe initialization */ 316297717Ssgalabov if (mtk_pcie_phy_init(dev)) { 317297717Ssgalabov device_printf(dev, "pcie phy init failed\n"); 318297717Ssgalabov goto cleanup_rman; 319297717Ssgalabov } 320297717Ssgalabov 321297717Ssgalabov /* Register ourselves as an interrupt controller */ 322300149Sandrew if (intr_pic_register(dev, xref) == NULL) { 323297717Ssgalabov device_printf(dev, "could not register PIC\n"); 324297717Ssgalabov goto cleanup_rman; 325297717Ssgalabov } 326297717Ssgalabov 327297717Ssgalabov /* Set up our interrupt handler */ 328297717Ssgalabov for (i = 1; i <= sc->sc_num_irq; i++) { 329297717Ssgalabov sc->pci_intrhand[i - 1] = NULL; 330297717Ssgalabov if (bus_setup_intr(dev, sc->pci_res[i], INTR_TYPE_MISC, 331297717Ssgalabov mtk_pci_intr, NULL, sc, &sc->pci_intrhand[i - 1])) { 332297717Ssgalabov device_printf(dev, "could not setup intr handler %d\n", 333297717Ssgalabov i); 334297717Ssgalabov goto cleanup; 335297717Ssgalabov } 336297717Ssgalabov } 337297717Ssgalabov 338297717Ssgalabov /* Attach our PCI child so bus enumeration can start */ 339297717Ssgalabov if (device_add_child(dev, "pci", -1) == NULL) { 340297717Ssgalabov device_printf(dev, "could not attach pci bus\n"); 341297717Ssgalabov goto cleanup; 342297717Ssgalabov } 343297717Ssgalabov 344297717Ssgalabov /* And finally, attach ourselves to the bus */ 345297717Ssgalabov if (bus_generic_attach(dev)) { 346297717Ssgalabov device_printf(dev, "could not attach to bus\n"); 347297717Ssgalabov goto cleanup; 348297717Ssgalabov } 349297717Ssgalabov 350297717Ssgalabov return (0); 351297717Ssgalabov 352297717Ssgalabovcleanup: 353297717Ssgalabov#ifdef notyet 354297717Ssgalabov intr_pic_unregister(dev, xref); 355297717Ssgalabov#endif 356297717Ssgalabov for (i = 1; i <= sc->sc_num_irq; i++) { 357297717Ssgalabov if (sc->pci_intrhand[i - 1] != NULL) 358297717Ssgalabov bus_teardown_intr(dev, sc->pci_res[i], 359297717Ssgalabov sc->pci_intrhand[i - 1]); 360297717Ssgalabov } 361297717Ssgalabovcleanup_rman: 362297717Ssgalabov mtk_pcie_phy_stop(dev); 363297717Ssgalabov rman_fini(&sc->sc_irq_rman); 364297717Ssgalabov rman_fini(&sc->sc_io_rman); 365297717Ssgalabov rman_fini(&sc->sc_mem_rman); 366297717Ssgalabovcleanup_res: 367297717Ssgalabov mt_sc = NULL; 368297717Ssgalabov if (sc->pci_res[0] != NULL) 369297717Ssgalabov bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->pci_res[0]); 370297717Ssgalabov if (sc->pci_res[1] != NULL) 371297717Ssgalabov bus_release_resource(dev, SYS_RES_IRQ, 0, sc->pci_res[1]); 372297717Ssgalabov if (sc->pci_res[2] != NULL) 373297717Ssgalabov bus_release_resource(dev, SYS_RES_IRQ, 1, sc->pci_res[2]); 374297717Ssgalabov if (sc->pci_res[3] != NULL) 375297717Ssgalabov bus_release_resource(dev, SYS_RES_IRQ, 2, sc->pci_res[3]); 376297717Ssgalabov return (ENXIO); 377297717Ssgalabov} 378297717Ssgalabov 379297717Ssgalabovstatic int 380297717Ssgalabovmtk_pci_read_ivar(device_t dev, device_t child, int which, 381297717Ssgalabov uintptr_t *result) 382297717Ssgalabov{ 383297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 384297717Ssgalabov 385297717Ssgalabov switch (which) { 386297717Ssgalabov case PCIB_IVAR_DOMAIN: 387297717Ssgalabov *result = device_get_unit(dev); 388297717Ssgalabov return (0); 389297717Ssgalabov case PCIB_IVAR_BUS: 390297717Ssgalabov *result = sc->sc_busno; 391297717Ssgalabov return (0); 392297717Ssgalabov } 393297717Ssgalabov 394297717Ssgalabov return (ENOENT); 395297717Ssgalabov} 396297717Ssgalabov 397297717Ssgalabovstatic int 398297717Ssgalabovmtk_pci_write_ivar(device_t dev, device_t child, int which, 399297717Ssgalabov uintptr_t result) 400297717Ssgalabov{ 401297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 402297717Ssgalabov 403297717Ssgalabov switch (which) { 404297717Ssgalabov case PCIB_IVAR_BUS: 405297717Ssgalabov sc->sc_busno = result; 406297717Ssgalabov return (0); 407297717Ssgalabov } 408297717Ssgalabov 409297717Ssgalabov return (ENOENT); 410297717Ssgalabov} 411297717Ssgalabov 412297717Ssgalabovstatic struct resource * 413297717Ssgalabovmtk_pci_alloc_resource(device_t bus, device_t child, int type, int *rid, 414297717Ssgalabov rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) 415297717Ssgalabov{ 416297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(bus); 417297717Ssgalabov struct resource *rv; 418297717Ssgalabov struct rman *rm; 419297717Ssgalabov 420297717Ssgalabov switch (type) { 421297850Ssgalabov case PCI_RES_BUS: 422297850Ssgalabov return pci_domain_alloc_bus(0, child, rid, start, end, count, 423297850Ssgalabov flags); 424297717Ssgalabov case SYS_RES_IRQ: 425297717Ssgalabov rm = &sc->sc_irq_rman; 426297717Ssgalabov break; 427297717Ssgalabov case SYS_RES_IOPORT: 428297717Ssgalabov rm = &sc->sc_io_rman; 429297717Ssgalabov break; 430297717Ssgalabov case SYS_RES_MEMORY: 431297717Ssgalabov rm = &sc->sc_mem_rman; 432297717Ssgalabov break; 433297717Ssgalabov default: 434297717Ssgalabov return (NULL); 435297717Ssgalabov } 436297717Ssgalabov 437297717Ssgalabov rv = rman_reserve_resource(rm, start, end, count, flags, child); 438297717Ssgalabov 439297717Ssgalabov if (rv == NULL) 440297717Ssgalabov return (NULL); 441297717Ssgalabov 442297717Ssgalabov rman_set_rid(rv, *rid); 443297717Ssgalabov 444297717Ssgalabov if ((flags & RF_ACTIVE) && type != SYS_RES_IRQ) { 445297717Ssgalabov if (bus_activate_resource(child, type, *rid, rv)) { 446297717Ssgalabov rman_release_resource(rv); 447297717Ssgalabov return (NULL); 448297717Ssgalabov } 449297717Ssgalabov } 450297717Ssgalabov 451297717Ssgalabov return (rv); 452297717Ssgalabov} 453297717Ssgalabov 454297850Ssgalabovstatic int 455297850Ssgalabovmtk_pci_release_resource(device_t bus, device_t child, int type, int rid, 456297850Ssgalabov struct resource *res) 457297850Ssgalabov{ 458297850Ssgalabov 459297850Ssgalabov if (type == PCI_RES_BUS) 460297850Ssgalabov return (pci_domain_release_bus(0, child, rid, res)); 461297850Ssgalabov 462297850Ssgalabov return (bus_generic_release_resource(bus, child, type, rid, res)); 463297850Ssgalabov} 464297850Ssgalabov 465297850Ssgalabovstatic int 466297850Ssgalabovmtk_pci_adjust_resource(device_t bus, device_t child, int type, 467297850Ssgalabov struct resource *res, rman_res_t start, rman_res_t end) 468297850Ssgalabov{ 469297850Ssgalabov struct mtk_pci_softc *sc = device_get_softc(bus); 470297850Ssgalabov struct rman *rm; 471297850Ssgalabov 472297850Ssgalabov switch (type) { 473297850Ssgalabov case PCI_RES_BUS: 474297850Ssgalabov return pci_domain_adjust_bus(0, child, res, start, end); 475297850Ssgalabov case SYS_RES_IRQ: 476297850Ssgalabov rm = &sc->sc_irq_rman; 477297850Ssgalabov break; 478297850Ssgalabov case SYS_RES_IOPORT: 479297850Ssgalabov rm = &sc->sc_io_rman; 480297850Ssgalabov break; 481297850Ssgalabov case SYS_RES_MEMORY: 482297850Ssgalabov rm = &sc->sc_mem_rman; 483297850Ssgalabov break; 484297850Ssgalabov default: 485297850Ssgalabov rm = NULL; 486297850Ssgalabov break; 487297850Ssgalabov } 488297850Ssgalabov 489297850Ssgalabov if (rm != NULL) 490297850Ssgalabov return (rman_adjust_resource(res, start, end)); 491297850Ssgalabov 492297850Ssgalabov return (bus_generic_adjust_resource(bus, child, type, res, start, end)); 493297850Ssgalabov} 494297850Ssgalabov 495297717Ssgalabovstatic inline int 496297717Ssgalabovmtk_idx_to_irq(int idx) 497297717Ssgalabov{ 498297717Ssgalabov 499297717Ssgalabov return ((idx == 0) ? MTK_PCIE0_IRQ : 500297717Ssgalabov (idx == 1) ? MTK_PCIE1_IRQ : 501297717Ssgalabov (idx == 2) ? MTK_PCIE2_IRQ : -1); 502297717Ssgalabov} 503297717Ssgalabov 504297717Ssgalabovstatic inline int 505297717Ssgalabovmtk_irq_to_idx(int irq) 506297717Ssgalabov{ 507297717Ssgalabov 508297717Ssgalabov return ((irq == MTK_PCIE0_IRQ) ? 0 : 509297717Ssgalabov (irq == MTK_PCIE1_IRQ) ? 1 : 510297717Ssgalabov (irq == MTK_PCIE2_IRQ) ? 2 : -1); 511297717Ssgalabov} 512297717Ssgalabov 513297717Ssgalabovstatic void 514297717Ssgalabovmtk_pci_mask_irq(void *source) 515297717Ssgalabov{ 516297717Ssgalabov MT_WRITE32(mt_sc, MTK_PCI_PCIENA, 517297717Ssgalabov MT_READ32(mt_sc, MTK_PCI_PCIENA) & ~(1<<((int)source))); 518297717Ssgalabov} 519297717Ssgalabov 520297717Ssgalabovstatic void 521297717Ssgalabovmtk_pci_unmask_irq(void *source) 522297717Ssgalabov{ 523297717Ssgalabov 524297717Ssgalabov MT_WRITE32(mt_sc, MTK_PCI_PCIENA, 525297717Ssgalabov MT_READ32(mt_sc, MTK_PCI_PCIENA) | (1<<((int)source))); 526297717Ssgalabov} 527297717Ssgalabov 528297717Ssgalabovstatic int 529297717Ssgalabovmtk_pci_setup_intr(device_t bus, device_t child, struct resource *ires, 530297717Ssgalabov int flags, driver_filter_t *filt, driver_intr_t *handler, 531297717Ssgalabov void *arg, void **cookiep) 532297717Ssgalabov{ 533297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(bus); 534297717Ssgalabov struct intr_event *event; 535297717Ssgalabov int irq, error, irqidx; 536297717Ssgalabov 537297717Ssgalabov irq = rman_get_start(ires); 538297717Ssgalabov 539297717Ssgalabov if (irq < sc->sc_irq_start || irq > sc->sc_irq_end) 540297717Ssgalabov return (EINVAL); 541297717Ssgalabov 542297717Ssgalabov irqidx = irq - sc->sc_irq_start; 543297717Ssgalabov 544297717Ssgalabov event = sc->sc_eventstab[irqidx]; 545297717Ssgalabov if (event == NULL) { 546297717Ssgalabov error = intr_event_create(&event, (void *)irq, 0, irq, 547297717Ssgalabov mtk_pci_mask_irq, mtk_pci_unmask_irq, NULL, NULL, 548297717Ssgalabov "pci intr%d:", irq); 549297717Ssgalabov 550297717Ssgalabov if (error == 0) { 551297717Ssgalabov sc->sc_eventstab[irqidx] = event; 552297717Ssgalabov } 553297717Ssgalabov else { 554297717Ssgalabov return (error); 555297717Ssgalabov } 556297717Ssgalabov } 557297717Ssgalabov 558297717Ssgalabov intr_event_add_handler(event, device_get_nameunit(child), filt, 559297717Ssgalabov handler, arg, intr_priority(flags), flags, cookiep); 560297717Ssgalabov 561297717Ssgalabov mtk_pci_unmask_irq((void*)irq); 562297717Ssgalabov 563297717Ssgalabov return (0); 564297717Ssgalabov} 565297717Ssgalabov 566297717Ssgalabovstatic int 567297717Ssgalabovmtk_pci_teardown_intr(device_t dev, device_t child, struct resource *ires, 568297717Ssgalabov void *cookie) 569297717Ssgalabov{ 570297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 571297717Ssgalabov int irq, result, irqidx; 572297717Ssgalabov 573297717Ssgalabov irq = rman_get_start(ires); 574297717Ssgalabov if (irq < sc->sc_irq_start || irq > sc->sc_irq_end) 575297717Ssgalabov return (EINVAL); 576297717Ssgalabov 577297717Ssgalabov irqidx = irq - sc->sc_irq_start; 578297717Ssgalabov if (sc->sc_eventstab[irqidx] == NULL) 579297717Ssgalabov panic("Trying to teardown unoccupied IRQ"); 580297717Ssgalabov 581297717Ssgalabov mtk_pci_mask_irq((void*)irq); 582297717Ssgalabov 583297717Ssgalabov result = intr_event_remove_handler(cookie); 584297717Ssgalabov if (!result) 585297717Ssgalabov sc->sc_eventstab[irqidx] = NULL; 586297717Ssgalabov 587297717Ssgalabov 588297717Ssgalabov return (result); 589297717Ssgalabov} 590297717Ssgalabov 591297717Ssgalabovstatic inline uint32_t 592297717Ssgalabovmtk_pci_make_addr(int bus, int slot, int func, int reg) 593297717Ssgalabov{ 594297717Ssgalabov uint32_t addr; 595297717Ssgalabov 596297717Ssgalabov addr = ((((reg & 0xf00) >> 8) << 24) | (bus << 16) | (slot << 11) | 597297717Ssgalabov (func << 8) | (reg & 0xfc) | (1 << 31)); 598297717Ssgalabov 599297717Ssgalabov return (addr); 600297717Ssgalabov} 601297717Ssgalabov 602297717Ssgalabovstatic int 603297717Ssgalabovmtk_pci_maxslots(device_t dev) 604297717Ssgalabov{ 605297717Ssgalabov 606297717Ssgalabov return (PCI_SLOTMAX); 607297717Ssgalabov} 608297717Ssgalabov 609297717Ssgalabovstatic inline int 610297717Ssgalabovmtk_pci_slot_has_link(device_t dev, int slot) 611297717Ssgalabov{ 612297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 613297717Ssgalabov 614297717Ssgalabov return !!(sc->pcie_link_status & (1<<slot)); 615297717Ssgalabov} 616297717Ssgalabov 617297717Ssgalabovstatic uint32_t 618297717Ssgalabovmtk_pci_read_config(device_t dev, u_int bus, u_int slot, u_int func, 619297717Ssgalabov u_int reg, int bytes) 620297717Ssgalabov{ 621297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 622297717Ssgalabov uint32_t addr = 0, data = 0; 623297717Ssgalabov 624297717Ssgalabov /* Return ~0U if slot has no link */ 625297717Ssgalabov if (bus == 0 && mtk_pci_slot_has_link(dev, slot) == 0) { 626297717Ssgalabov return (~0U); 627297717Ssgalabov } 628297717Ssgalabov 629297717Ssgalabov mtx_lock_spin(&mtk_pci_mtx); 630297717Ssgalabov addr = mtk_pci_make_addr(bus, slot, func, (reg & ~3)) & sc->addr_mask; 631297717Ssgalabov MT_WRITE32(sc, MTK_PCI_CFGADDR, addr); 632297717Ssgalabov switch (bytes % 4) { 633297717Ssgalabov case 0: 634297717Ssgalabov data = MT_READ32(sc, MTK_PCI_CFGDATA); 635297717Ssgalabov break; 636297717Ssgalabov case 1: 637297717Ssgalabov data = MT_READ8(sc, MTK_PCI_CFGDATA + (reg & 0x3)); 638297717Ssgalabov break; 639297717Ssgalabov case 2: 640297717Ssgalabov data = MT_READ16(sc, MTK_PCI_CFGDATA + (reg & 0x3)); 641297717Ssgalabov break; 642297717Ssgalabov default: 643297717Ssgalabov panic("%s(): Wrong number of bytes (%d) requested!\n", 644297717Ssgalabov __FUNCTION__, bytes % 4); 645297717Ssgalabov } 646297717Ssgalabov mtx_unlock_spin(&mtk_pci_mtx); 647297717Ssgalabov 648297717Ssgalabov return (data); 649297717Ssgalabov} 650297717Ssgalabov 651297717Ssgalabovstatic void 652297717Ssgalabovmtk_pci_write_config(device_t dev, u_int bus, u_int slot, u_int func, 653297717Ssgalabov u_int reg, uint32_t val, int bytes) 654297717Ssgalabov{ 655297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 656297717Ssgalabov uint32_t addr = 0, data = val; 657297717Ssgalabov 658297717Ssgalabov /* Do not write if slot has no link */ 659297717Ssgalabov if (bus == 0 && mtk_pci_slot_has_link(dev, slot) == 0) 660297717Ssgalabov return; 661297717Ssgalabov 662297717Ssgalabov mtx_lock_spin(&mtk_pci_mtx); 663297717Ssgalabov addr = mtk_pci_make_addr(bus, slot, func, (reg & ~3)) & sc->addr_mask; 664297717Ssgalabov MT_WRITE32(sc, MTK_PCI_CFGADDR, addr); 665297717Ssgalabov switch (bytes % 4) { 666297717Ssgalabov case 0: 667297717Ssgalabov MT_WRITE32(sc, MTK_PCI_CFGDATA, data); 668297717Ssgalabov break; 669297717Ssgalabov case 1: 670297717Ssgalabov MT_WRITE8(sc, MTK_PCI_CFGDATA + (reg & 0x3), data); 671297717Ssgalabov break; 672297717Ssgalabov case 2: 673297717Ssgalabov MT_WRITE16(sc, MTK_PCI_CFGDATA + (reg & 0x3), data); 674297717Ssgalabov break; 675297717Ssgalabov default: 676297717Ssgalabov panic("%s(): Wrong number of bytes (%d) requested!\n", 677297717Ssgalabov __FUNCTION__, bytes % 4); 678297717Ssgalabov } 679297717Ssgalabov mtx_unlock_spin(&mtk_pci_mtx); 680297717Ssgalabov} 681297717Ssgalabov 682297717Ssgalabovstatic int 683297717Ssgalabovmtk_pci_route_interrupt(device_t pcib, device_t device, int pin) 684297717Ssgalabov{ 685297717Ssgalabov int bus, sl, dev; 686297717Ssgalabov 687297717Ssgalabov bus = pci_get_bus(device); 688297717Ssgalabov sl = pci_get_slot(device); 689297717Ssgalabov dev = pci_get_device(device); 690297717Ssgalabov 691297717Ssgalabov if (bus != 0) 692297717Ssgalabov panic("Unexpected bus number %d\n", bus); 693297717Ssgalabov 694297717Ssgalabov /* PCIe only */ 695297717Ssgalabov switch (sl) { 696297717Ssgalabov case 0: return MTK_PCIE0_IRQ; 697297717Ssgalabov case 1: return MTK_PCIE0_IRQ + 1; 698297717Ssgalabov case 2: return MTK_PCIE0_IRQ + 2; 699297717Ssgalabov default: return (-1); 700297717Ssgalabov } 701297717Ssgalabov 702297717Ssgalabov return (-1); 703297717Ssgalabov} 704297717Ssgalabov 705297717Ssgalabovstatic device_method_t mtk_pci_methods[] = { 706297717Ssgalabov /* Device interface */ 707297717Ssgalabov DEVMETHOD(device_probe, mtk_pci_probe), 708297717Ssgalabov DEVMETHOD(device_attach, mtk_pci_attach), 709297717Ssgalabov DEVMETHOD(device_shutdown, bus_generic_shutdown), 710297717Ssgalabov DEVMETHOD(device_suspend, bus_generic_suspend), 711297717Ssgalabov DEVMETHOD(device_resume, bus_generic_resume), 712297717Ssgalabov 713297717Ssgalabov /* Bus interface */ 714297717Ssgalabov DEVMETHOD(bus_read_ivar, mtk_pci_read_ivar), 715297717Ssgalabov DEVMETHOD(bus_write_ivar, mtk_pci_write_ivar), 716297717Ssgalabov DEVMETHOD(bus_alloc_resource, mtk_pci_alloc_resource), 717297850Ssgalabov DEVMETHOD(bus_release_resource, mtk_pci_release_resource), 718297850Ssgalabov DEVMETHOD(bus_adjust_resource, mtk_pci_adjust_resource), 719297717Ssgalabov DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 720297717Ssgalabov DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 721297717Ssgalabov DEVMETHOD(bus_setup_intr, mtk_pci_setup_intr), 722297717Ssgalabov DEVMETHOD(bus_teardown_intr, mtk_pci_teardown_intr), 723297717Ssgalabov 724297717Ssgalabov /* pcib interface */ 725297717Ssgalabov DEVMETHOD(pcib_maxslots, mtk_pci_maxslots), 726297717Ssgalabov DEVMETHOD(pcib_read_config, mtk_pci_read_config), 727297717Ssgalabov DEVMETHOD(pcib_write_config, mtk_pci_write_config), 728297717Ssgalabov DEVMETHOD(pcib_route_interrupt, mtk_pci_route_interrupt), 729297717Ssgalabov 730297850Ssgalabov /* OFW bus interface */ 731297850Ssgalabov DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 732297850Ssgalabov DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 733297850Ssgalabov DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 734297850Ssgalabov DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 735297850Ssgalabov DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 736297850Ssgalabov 737297717Ssgalabov DEVMETHOD_END 738297717Ssgalabov}; 739297717Ssgalabov 740297717Ssgalabovstatic driver_t mtk_pci_driver = { 741297717Ssgalabov "pcib", 742297717Ssgalabov mtk_pci_methods, 743297717Ssgalabov sizeof(struct mtk_pci_softc), 744297717Ssgalabov}; 745297717Ssgalabov 746297717Ssgalabovstatic devclass_t mtk_pci_devclass; 747297717Ssgalabov 748297717SsgalabovDRIVER_MODULE(mtk_pci, simplebus, mtk_pci_driver, mtk_pci_devclass, 0, 0); 749297717Ssgalabov 750297717Ssgalabov/* Our interrupt handler */ 751297717Ssgalabovstatic int 752297717Ssgalabovmtk_pci_intr(void *arg) 753297717Ssgalabov{ 754297717Ssgalabov struct mtk_pci_softc *sc = arg; 755297717Ssgalabov struct intr_event *event; 756297717Ssgalabov uint32_t reg, irq, irqidx; 757297717Ssgalabov 758297717Ssgalabov reg = MT_READ32(sc, MTK_PCI_PCIINT); 759297717Ssgalabov 760297717Ssgalabov for (irq = sc->sc_irq_start; irq <= sc->sc_irq_end; irq++) { 761297717Ssgalabov if (reg & (1u<<irq)) { 762297717Ssgalabov irqidx = irq - sc->sc_irq_start; 763297717Ssgalabov event = sc->sc_eventstab[irqidx]; 764297717Ssgalabov if (!event || TAILQ_EMPTY(&event->ie_handlers)) { 765297717Ssgalabov if (irq != 0) 766297717Ssgalabov printf("Stray PCI IRQ %d\n", irq); 767297717Ssgalabov continue; 768297717Ssgalabov } 769297717Ssgalabov 770297717Ssgalabov intr_event_handle(event, NULL); 771297717Ssgalabov } 772297717Ssgalabov } 773297717Ssgalabov 774297717Ssgalabov return (FILTER_HANDLED); 775297717Ssgalabov} 776297717Ssgalabov 777297717Ssgalabov/* PCIe SoC-specific initialization */ 778297717Ssgalabovstatic int 779297717Ssgalabovmtk_pcie_phy_init(device_t dev) 780297717Ssgalabov{ 781297717Ssgalabov struct mtk_pci_softc *sc; 782297717Ssgalabov 783297717Ssgalabov /* Get our softc */ 784297717Ssgalabov sc = device_get_softc(dev); 785297717Ssgalabov 786297717Ssgalabov /* We don't know how many slots we have yet */ 787297717Ssgalabov sc->num_slots = 0; 788297717Ssgalabov 789297717Ssgalabov /* Handle SoC specific PCIe init */ 790297717Ssgalabov switch (sc->socid) { 791297717Ssgalabov case MTK_SOC_MT7628: /* Fallthrough */ 792297717Ssgalabov case MTK_SOC_MT7688: 793297717Ssgalabov if (mtk_pcie_phy_mt7628_init(dev)) 794297717Ssgalabov return (ENXIO); 795297717Ssgalabov break; 796297717Ssgalabov case MTK_SOC_MT7621: 797297717Ssgalabov if (mtk_pcie_phy_mt7621_init(dev)) 798297717Ssgalabov return (ENXIO); 799297717Ssgalabov break; 800297717Ssgalabov case MTK_SOC_MT7620A: 801297717Ssgalabov if (mtk_pcie_phy_mt7620_init(dev)) 802297717Ssgalabov return (ENXIO); 803297717Ssgalabov break; 804297717Ssgalabov case MTK_SOC_RT3662: /* Fallthrough */ 805297717Ssgalabov case MTK_SOC_RT3883: 806297717Ssgalabov if (mtk_pcie_phy_rt3883_init(dev)) 807297717Ssgalabov return (ENXIO); 808297717Ssgalabov break; 809297717Ssgalabov default: 810297717Ssgalabov device_printf(dev, "unsupported device %x\n", sc->socid); 811297717Ssgalabov return (ENXIO); 812297717Ssgalabov } 813297717Ssgalabov 814297717Ssgalabov /* 815297717Ssgalabov * If we were successful so far go and set up the PCIe slots, so we 816297717Ssgalabov * may allocate mem/io/irq resources and enumerate busses later. 817297717Ssgalabov */ 818297717Ssgalabov mtk_pcie_phy_setup_slots(dev); 819297717Ssgalabov 820297717Ssgalabov return (0); 821297717Ssgalabov} 822297717Ssgalabov 823297717Ssgalabovstatic int 824297717Ssgalabovmtk_pcie_phy_start(device_t dev) 825297717Ssgalabov{ 826297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 827297717Ssgalabov 828297717Ssgalabov if (sc->socid == MTK_SOC_MT7621 && 829297717Ssgalabov (mtk_sysctl_get(SYSCTL_REVID) & SYSCTL_REVID_MASK) != 830297717Ssgalabov SYSCTL_MT7621_REV_E) { 831297717Ssgalabov if (fdt_reset_assert_all(dev)) 832297717Ssgalabov return (ENXIO); 833297717Ssgalabov } else { 834297717Ssgalabov if (fdt_reset_deassert_all(dev)) 835297717Ssgalabov return (ENXIO); 836297717Ssgalabov } 837297717Ssgalabov 838297717Ssgalabov if (fdt_clock_enable_all(dev)) 839297717Ssgalabov return (ENXIO); 840297717Ssgalabov 841297717Ssgalabov return (0); 842297717Ssgalabov} 843297717Ssgalabov 844297717Ssgalabovstatic int 845297717Ssgalabovmtk_pcie_phy_stop(device_t dev) 846297717Ssgalabov{ 847297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 848297717Ssgalabov 849297717Ssgalabov if (sc->socid == MTK_SOC_MT7621 && 850297717Ssgalabov (mtk_sysctl_get(SYSCTL_REVID) & SYSCTL_REVID_MASK) != 851297717Ssgalabov SYSCTL_MT7621_REV_E) { 852297717Ssgalabov if (fdt_reset_deassert_all(dev)) 853297717Ssgalabov return (ENXIO); 854297717Ssgalabov } else { 855297717Ssgalabov if (fdt_reset_assert_all(dev)) 856297717Ssgalabov return (ENXIO); 857297717Ssgalabov } 858297717Ssgalabov 859297717Ssgalabov if (fdt_clock_disable_all(dev)) 860297717Ssgalabov return (ENXIO); 861297717Ssgalabov 862297717Ssgalabov return (0); 863297717Ssgalabov} 864297717Ssgalabov 865297717Ssgalabov#define mtk_pcie_phy_set(_sc, _reg, _s, _n, _v) \ 866297717Ssgalabov MT_WRITE32((_sc), (_reg), ((MT_READ32((_sc), (_reg)) & \ 867297717Ssgalabov (~(((1ull << (_n)) - 1) << (_s)))) | ((_v) << (_s)))) 868297717Ssgalabov 869297717Ssgalabovstatic void 870297717Ssgalabovmtk_pcie_phy_mt7621_bypass_pipe_rst(struct mtk_pci_softc *sc, uint32_t off) 871297717Ssgalabov{ 872297717Ssgalabov 873297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x002c, 12, 1, 1); 874297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x002c, 4, 1, 1); 875297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x012c, 12, 1, 1); 876297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x012c, 4, 1, 1); 877297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x102c, 12, 1, 1); 878297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x102c, 4, 1, 1); 879297717Ssgalabov} 880297717Ssgalabov 881297717Ssgalabovstatic void 882297717Ssgalabovmtk_pcie_phy_mt7621_setup_ssc(struct mtk_pci_softc *sc, uint32_t off) 883297717Ssgalabov{ 884297717Ssgalabov uint32_t xtal_sel; 885297717Ssgalabov 886297717Ssgalabov xtal_sel = mtk_sysctl_get(SYSCTL_SYSCFG) >> 6; 887297717Ssgalabov xtal_sel &= 0x7; 888297717Ssgalabov 889297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x400, 8, 1, 1); 890297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x400, 9, 2, 0); 891297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x000, 4, 1, 1); 892297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x100, 4, 1, 1); 893297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x000, 5, 1, 0); 894297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x100, 5, 1, 0); 895297717Ssgalabov 896297717Ssgalabov if (xtal_sel <= 5 && xtal_sel >= 3) { 897297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x490, 6, 2, 1); 898297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 0, 12, 0x1a); 899297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 16, 12, 0x1a); 900297717Ssgalabov } else { 901297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x490, 6, 2, 0); 902297717Ssgalabov if (xtal_sel >= 6) { 903297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4bc, 4, 2, 0x01); 904297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x49c, 0, 31, 0x18000000); 905297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a4, 0, 16, 0x18d); 906297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 0, 12, 0x4a); 907297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 16, 12, 0x4a); 908297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 0, 12, 0x11); 909297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 16, 12, 0x11); 910297717Ssgalabov } else { 911297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 0, 12, 0x1a); 912297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 16, 12, 0x1a); 913297717Ssgalabov } 914297717Ssgalabov } 915297717Ssgalabov 916297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a0, 5, 1, 1); 917297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x490, 22, 2, 2); 918297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x490, 18, 4, 6); 919297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x490, 12, 4, 2); 920297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x490, 8, 4, 1); 921297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4ac, 16, 3, 0); 922297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x490, 1, 3, 2); 923297717Ssgalabov 924297717Ssgalabov if (xtal_sel <= 5 && xtal_sel >= 3) { 925297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x414, 6, 2, 1); 926297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x414, 5, 1, 1); 927297717Ssgalabov } 928297717Ssgalabov 929297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x414, 28, 2, 1); 930297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x040, 17, 4, 7); 931297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x040, 16, 1, 1); 932297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x140, 17, 4, 7); 933297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x140, 16, 1, 1); 934297717Ssgalabov 935297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x000, 5, 1, 1); 936297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x100, 5, 1, 1); 937297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x000, 4, 1, 0); 938297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x100, 4, 1, 0); 939297717Ssgalabov} 940297717Ssgalabov 941297717Ssgalabov/* XXX: ugly, we need to fix this at some point */ 942297717Ssgalabov#define MT7621_GPIO_CTRL0 *((volatile uint32_t *)0xbe000600) 943297717Ssgalabov#define MT7621_GPIO_DATA0 *((volatile uint32_t *)0xbe000620) 944297717Ssgalabov 945297717Ssgalabov#define mtk_gpio_clr_set(_reg, _clr, _set) \ 946297717Ssgalabov do { \ 947297717Ssgalabov (_reg) = ((_reg) & (_clr)) | (_set); \ 948297717Ssgalabov } while (0) 949297717Ssgalabov 950297717Ssgalabovstatic int 951297717Ssgalabovmtk_pcie_phy_mt7621_init(device_t dev) 952297717Ssgalabov{ 953297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 954297717Ssgalabov 955297717Ssgalabov /* First off, stop the PHY */ 956297717Ssgalabov if (mtk_pcie_phy_stop(dev)) 957297717Ssgalabov return (ENXIO); 958297717Ssgalabov 959297717Ssgalabov /* PCIe resets are GPIO pins */ 960297717Ssgalabov mtk_sysctl_clr_set(SYSCTL_GPIOMODE, MT7621_PERST_GPIO_MODE | 961297717Ssgalabov MT7621_UARTL3_GPIO_MODE, MT7621_PERST_GPIO | MT7621_UARTL3_GPIO); 962297717Ssgalabov 963297717Ssgalabov /* Set GPIO pins as outputs */ 964297717Ssgalabov mtk_gpio_clr_set(MT7621_GPIO_CTRL0, 0, MT7621_PCIE_RST); 965297717Ssgalabov 966297717Ssgalabov /* Assert resets to PCIe devices */ 967297717Ssgalabov mtk_gpio_clr_set(MT7621_GPIO_DATA0, MT7621_PCIE_RST, 0); 968297717Ssgalabov 969297717Ssgalabov /* Give everything a chance to sink in */ 970297717Ssgalabov DELAY(100000); 971297717Ssgalabov 972297717Ssgalabov /* Now start the PHY again */ 973297717Ssgalabov if (mtk_pcie_phy_start(dev)) 974297717Ssgalabov return (ENXIO); 975297717Ssgalabov 976297717Ssgalabov /* Wait for things to settle */ 977297717Ssgalabov DELAY(100000); 978297717Ssgalabov 979297717Ssgalabov /* Only apply below to REV-E hardware */ 980297717Ssgalabov if ((mtk_sysctl_get(SYSCTL_REVID) & SYSCTL_REVID_MASK) == 981297717Ssgalabov SYSCTL_MT7621_REV_E) 982297717Ssgalabov mtk_pcie_phy_mt7621_bypass_pipe_rst(sc, 0x9000); 983297717Ssgalabov 984297717Ssgalabov /* Setup PCIe ports 0 and 1 */ 985297717Ssgalabov mtk_pcie_phy_mt7621_setup_ssc(sc, 0x9000); 986297717Ssgalabov /* Setup PCIe port 2 */ 987297717Ssgalabov mtk_pcie_phy_mt7621_setup_ssc(sc, 0xa000); 988297717Ssgalabov 989297717Ssgalabov /* Deassert resets to PCIe devices */ 990297717Ssgalabov mtk_gpio_clr_set(MT7621_GPIO_DATA0, 0, MT7621_PCIE_RST); 991297717Ssgalabov 992297717Ssgalabov /* Set number of slots supported */ 993297717Ssgalabov sc->num_slots = 3; 994297717Ssgalabov 995297717Ssgalabov /* Give it a chance to sink in */ 996297717Ssgalabov DELAY(100000); 997297717Ssgalabov 998297717Ssgalabov return (0); 999297717Ssgalabov} 1000297717Ssgalabov 1001297717Ssgalabovstatic void 1002297717Ssgalabovmtk_pcie_phy_mt7628_setup(struct mtk_pci_softc *sc, uint32_t off) 1003297717Ssgalabov{ 1004297717Ssgalabov uint32_t xtal_sel; 1005297717Ssgalabov 1006297717Ssgalabov xtal_sel = mtk_sysctl_get(SYSCTL_SYSCFG) >> 6; 1007297717Ssgalabov xtal_sel &= 0x1; 1008297717Ssgalabov 1009297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x400, 8, 1, 1); 1010297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x400, 9, 2, 0); 1011297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x000, 4, 1, 1); 1012297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x000, 5, 1, 0); 1013297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4ac, 16, 3, 3); 1014297717Ssgalabov 1015297717Ssgalabov if (xtal_sel == 1) { 1016297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4bc, 24, 8, 0x7d); 1017297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x490, 12, 4, 0x08); 1018297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x490, 6, 2, 0x01); 1019297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4c0, 0, 32, 0x1f400000); 1020297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a4, 0, 16, 0x013d); 1021297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 16, 16, 0x74); 1022297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 0, 16, 0x74); 1023297717Ssgalabov } else { 1024297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4bc, 24, 8, 0x64); 1025297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x490, 12, 4, 0x0a); 1026297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x490, 6, 2, 0x00); 1027297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4c0, 0, 32, 0x19000000); 1028297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a4, 0, 16, 0x018d); 1029297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 16, 16, 0x4a); 1030297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 0, 16, 0x4a); 1031297717Ssgalabov } 1032297717Ssgalabov 1033297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x498, 0, 8, 5); 1034297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x000, 5, 1, 1); 1035297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x000, 4, 1, 0); 1036297717Ssgalabov} 1037297717Ssgalabov 1038297717Ssgalabovstatic int 1039297717Ssgalabovmtk_pcie_phy_mt7628_init(device_t dev) 1040297717Ssgalabov{ 1041297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 1042297717Ssgalabov 1043297717Ssgalabov /* Set PCIe reset to normal mode */ 1044297717Ssgalabov mtk_sysctl_clr_set(SYSCTL_GPIOMODE, MT7628_PERST_GPIO_MODE, 1045297717Ssgalabov MT7628_PERST); 1046297717Ssgalabov 1047297717Ssgalabov /* Start the PHY */ 1048297717Ssgalabov if (mtk_pcie_phy_start(dev)) 1049297717Ssgalabov return (ENXIO); 1050297717Ssgalabov 1051297717Ssgalabov /* Give it a chance to sink in */ 1052297717Ssgalabov DELAY(100000); 1053297717Ssgalabov 1054297717Ssgalabov /* Setup the PHY */ 1055297717Ssgalabov mtk_pcie_phy_mt7628_setup(sc, 0x9000); 1056297717Ssgalabov 1057297717Ssgalabov /* Deassert PCIe device reset */ 1058297717Ssgalabov MT_CLR_SET32(sc, MTK_PCI_PCICFG, MTK_PCI_RESET, 0); 1059297717Ssgalabov 1060297717Ssgalabov /* Set number of slots supported */ 1061297717Ssgalabov sc->num_slots = 1; 1062297717Ssgalabov 1063297717Ssgalabov return (0); 1064297717Ssgalabov} 1065297717Ssgalabov 1066297717Ssgalabovstatic int 1067297717Ssgalabovmtk_pcie_phy_mt7620_wait_busy(struct mtk_pci_softc *sc) 1068297717Ssgalabov{ 1069297717Ssgalabov uint32_t reg_value, retry; 1070297717Ssgalabov 1071297717Ssgalabov reg_value = retry = 0; 1072297717Ssgalabov 1073297717Ssgalabov while (retry++ < MT7620_MAX_RETRIES) { 1074297717Ssgalabov reg_value = MT_READ32(sc, MT7620_PCIE_PHY_CFG); 1075297717Ssgalabov if (reg_value & PHY_BUSY) 1076297717Ssgalabov DELAY(100000); 1077297717Ssgalabov else 1078297717Ssgalabov break; 1079297717Ssgalabov } 1080297717Ssgalabov 1081297717Ssgalabov if (retry >= MT7620_MAX_RETRIES) 1082297717Ssgalabov return (ENXIO); 1083297717Ssgalabov 1084297717Ssgalabov return (0); 1085297717Ssgalabov} 1086297717Ssgalabov 1087297717Ssgalabovstatic int 1088297717Ssgalabovmtk_pcie_phy_mt7620_set(struct mtk_pci_softc *sc, uint32_t reg, 1089297717Ssgalabov uint32_t val) 1090297717Ssgalabov{ 1091297717Ssgalabov uint32_t reg_val; 1092297717Ssgalabov 1093297717Ssgalabov if (mtk_pcie_phy_mt7620_wait_busy(sc)) 1094297717Ssgalabov return (ENXIO); 1095297717Ssgalabov 1096297717Ssgalabov reg_val = PHY_MODE_WRITE | ((reg & 0xff) << PHY_ADDR_OFFSET) | 1097297717Ssgalabov (val & 0xff); 1098297717Ssgalabov MT_WRITE32(sc, MT7620_PCIE_PHY_CFG, reg_val); 1099297717Ssgalabov DELAY(1000); 1100297717Ssgalabov 1101297717Ssgalabov if (mtk_pcie_phy_mt7620_wait_busy(sc)) 1102297717Ssgalabov return (ENXIO); 1103297717Ssgalabov 1104297717Ssgalabov return (0); 1105297717Ssgalabov} 1106297717Ssgalabov 1107297717Ssgalabovstatic int 1108297717Ssgalabovmtk_pcie_phy_mt7620_init(device_t dev) 1109297717Ssgalabov{ 1110297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 1111297717Ssgalabov 1112297717Ssgalabov /* 1113297717Ssgalabov * The below sets the PCIe PHY to bypass the PCIe DLL and enables 1114297717Ssgalabov * "elastic buffer control", whatever that may be... 1115297717Ssgalabov */ 1116297717Ssgalabov if (mtk_pcie_phy_mt7620_set(sc, 0x00, 0x80) || 1117297717Ssgalabov mtk_pcie_phy_mt7620_set(sc, 0x01, 0x04) || 1118297717Ssgalabov mtk_pcie_phy_mt7620_set(sc, 0x68, 0x84)) 1119297717Ssgalabov return (ENXIO); 1120297717Ssgalabov 1121297717Ssgalabov /* Stop PCIe */ 1122297717Ssgalabov if (mtk_pcie_phy_stop(dev)) 1123297717Ssgalabov return (ENXIO); 1124297717Ssgalabov 1125297717Ssgalabov /* Restore PPLL to a sane state before going on */ 1126297717Ssgalabov mtk_sysctl_clr_set(MT7620_PPLL_DRV, LC_CKDRVPD, PDRV_SW_SET); 1127297717Ssgalabov 1128297717Ssgalabov /* No PCIe on the MT7620N */ 1129297717Ssgalabov if (!(mtk_sysctl_get(SYSCTL_REVID) & MT7620_PKG_BGA)) { 1130297717Ssgalabov device_printf(dev, "PCIe disabled for MT7620N\n"); 1131297717Ssgalabov mtk_sysctl_clr_set(MT7620_PPLL_CFG0, 0, PPLL_SW_SET); 1132297717Ssgalabov mtk_sysctl_clr_set(MT7620_PPLL_CFG1, 0, PPLL_PD); 1133297717Ssgalabov return (ENXIO); 1134297717Ssgalabov } 1135297717Ssgalabov 1136297717Ssgalabov /* PCIe device reset pin is in normal mode */ 1137297717Ssgalabov mtk_sysctl_clr_set(SYSCTL_GPIOMODE, MT7620_PERST_GPIO_MODE, 1138297717Ssgalabov MT7620_PERST); 1139297717Ssgalabov 1140297717Ssgalabov /* Enable PCIe now */ 1141297717Ssgalabov if (mtk_pcie_phy_start(dev)) 1142297717Ssgalabov return (ENXIO); 1143297717Ssgalabov 1144297717Ssgalabov /* Give it a chance to sink in */ 1145297717Ssgalabov DELAY(100000); 1146297717Ssgalabov 1147297717Ssgalabov /* If PLL is not locked - bail */ 1148297717Ssgalabov if (!(mtk_sysctl_get(MT7620_PPLL_CFG1) & PPLL_LOCKED)) { 1149297717Ssgalabov device_printf(dev, "no PPLL not lock\n"); 1150297717Ssgalabov mtk_pcie_phy_stop(dev); 1151297717Ssgalabov return (ENXIO); 1152297717Ssgalabov } 1153297717Ssgalabov 1154297717Ssgalabov /* Configure PCIe PLL */ 1155297717Ssgalabov mtk_sysctl_clr_set(MT7620_PPLL_DRV, LC_CKDRVOHZ | LC_CKDRVHZ, 1156297717Ssgalabov LC_CKDRVPD | PDRV_SW_SET); 1157297717Ssgalabov 1158297717Ssgalabov /* and give it a chance to settle */ 1159297717Ssgalabov DELAY(100000); 1160297717Ssgalabov 1161297717Ssgalabov /* Deassert PCIe device reset */ 1162297717Ssgalabov MT_CLR_SET32(sc, MTK_PCI_PCICFG, MTK_PCI_RESET, 0); 1163297717Ssgalabov 1164297717Ssgalabov /* MT7620 supports one PCIe slot */ 1165297717Ssgalabov sc->num_slots = 1; 1166297717Ssgalabov 1167297717Ssgalabov return (0); 1168297717Ssgalabov} 1169297717Ssgalabov 1170297717Ssgalabovstatic int 1171297717Ssgalabovmtk_pcie_phy_rt3883_init(device_t dev) 1172297717Ssgalabov{ 1173297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 1174297717Ssgalabov 1175297717Ssgalabov /* Enable PCI host mode and PCIe RC mode */ 1176297717Ssgalabov mtk_sysctl_clr_set(SYSCTL_SYSCFG1, 0, RT3883_PCI_HOST_MODE | 1177297717Ssgalabov RT3883_PCIE_RC_MODE); 1178297717Ssgalabov 1179297717Ssgalabov /* Enable PCIe PHY */ 1180297717Ssgalabov if (mtk_pcie_phy_start(dev)) 1181297717Ssgalabov return (ENXIO); 1182297717Ssgalabov 1183297717Ssgalabov /* Disable PCI, we only support PCIe for now */ 1184297717Ssgalabov mtk_sysctl_clr_set(SYSCTL_RSTCTRL, 0, RT3883_PCI_RST); 1185297717Ssgalabov mtk_sysctl_clr_set(SYSCTL_CLKCFG1, RT3883_PCI_CLK, 0); 1186297717Ssgalabov 1187297717Ssgalabov /* Give things a chance to sink in */ 1188297717Ssgalabov DELAY(500000); 1189297717Ssgalabov 1190297717Ssgalabov /* Set PCIe port number to 0 and lift PCIe reset */ 1191297717Ssgalabov MT_WRITE32(sc, MTK_PCI_PCICFG, 0); 1192297717Ssgalabov 1193297717Ssgalabov /* Configure PCI Arbiter */ 1194297717Ssgalabov MT_WRITE32(sc, MTK_PCI_ARBCTL, 0x79); 1195297717Ssgalabov 1196297717Ssgalabov /* We have a single PCIe slot */ 1197297717Ssgalabov sc->num_slots = 1; 1198297717Ssgalabov 1199297717Ssgalabov return (0); 1200297717Ssgalabov} 1201297717Ssgalabov 1202297717Ssgalabovstatic void 1203297717Ssgalabovmtk_pcie_phy_setup_slots(device_t dev) 1204297717Ssgalabov{ 1205297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 1206297717Ssgalabov uint32_t bar0_val, val; 1207297717Ssgalabov int i; 1208297717Ssgalabov 1209297717Ssgalabov /* Disable all PCIe interrupts */ 1210297717Ssgalabov MT_WRITE32(sc, MTK_PCI_PCIENA, 0); 1211297717Ssgalabov 1212297717Ssgalabov /* Default bar0_val is 64M, enabled */ 1213297717Ssgalabov bar0_val = 0x03FF0001; 1214297717Ssgalabov 1215297717Ssgalabov /* But we override it to 2G, enabled for some SoCs */ 1216297717Ssgalabov if (sc->socid == MTK_SOC_MT7620A || sc->socid == MTK_SOC_MT7628 || 1217297717Ssgalabov sc->socid == MTK_SOC_MT7688 || sc->socid == MTK_SOC_MT7621) 1218297717Ssgalabov bar0_val = 0x7FFF0001; 1219297717Ssgalabov 1220297717Ssgalabov /* We still don't know which slots have linked up */ 1221297717Ssgalabov sc->pcie_link_status = 0; 1222297717Ssgalabov 1223297717Ssgalabov /* XXX: I am not sure if this delay is really necessary */ 1224297717Ssgalabov DELAY(500000); 1225297717Ssgalabov 1226297717Ssgalabov /* 1227297717Ssgalabov * See which slots have links and mark them. 1228297717Ssgalabov * Set up all slots' BARs and make them look like PCIe bridges. 1229297717Ssgalabov */ 1230297717Ssgalabov for (i = 0; i < sc->num_slots; i++) { 1231297717Ssgalabov /* If slot has link - mark it */ 1232297717Ssgalabov if (MT_READ32(sc, MTK_PCIE_STATUS(i)) & 1) 1233297717Ssgalabov sc->pcie_link_status |= (1<<i); 1234297850Ssgalabov else 1235297850Ssgalabov continue; 1236297717Ssgalabov 1237297717Ssgalabov /* Generic slot configuration follows */ 1238297717Ssgalabov 1239297717Ssgalabov /* We enable BAR0 */ 1240297717Ssgalabov MT_WRITE32(sc, MTK_PCIE_BAR0SETUP(i), bar0_val); 1241297717Ssgalabov /* and disable BAR1 */ 1242297717Ssgalabov MT_WRITE32(sc, MTK_PCIE_BAR1SETUP(i), 0); 1243297717Ssgalabov /* Internal memory base has no offset */ 1244297717Ssgalabov MT_WRITE32(sc, MTK_PCIE_IMBASEBAR0(i), 0); 1245297717Ssgalabov /* We're a PCIe bridge */ 1246297717Ssgalabov MT_WRITE32(sc, MTK_PCIE_CLASS(i), 0x06040001); 1247297717Ssgalabov 1248297717Ssgalabov val = mtk_pci_read_config(dev, 0, i, 0, 0x4, 4); 1249297717Ssgalabov mtk_pci_write_config(dev, 0, i, 0, 0x4, val | 0x4, 4); 1250297717Ssgalabov val = mtk_pci_read_config(dev, 0, i, 0, 0x70c, 4); 1251297717Ssgalabov val &= ~(0xff << 8); 1252297717Ssgalabov val |= (0x50 << 8); 1253297850Ssgalabov mtk_pci_write_config(dev, 0, i, 0, 0x70c, val, 4); 1254297850Ssgalabov 1255297850Ssgalabov mtk_pci_write_config(dev, 0, i, 0, PCIR_IOBASEL_1, 0xff, 1); 1256297850Ssgalabov mtk_pci_write_config(dev, 0, i, 0, PCIR_IOBASEH_1, 0xffff, 2); 1257297850Ssgalabov mtk_pci_write_config(dev, 0, i, 0, PCIR_IOLIMITL_1, 0, 1); 1258297850Ssgalabov mtk_pci_write_config(dev, 0, i, 0, PCIR_IOLIMITH_1, 0, 2); 1259297850Ssgalabov mtk_pci_write_config(dev, 0, i, 0, PCIR_MEMBASE_1, 0xffff, 2); 1260297850Ssgalabov mtk_pci_write_config(dev, 0, i, 0, PCIR_MEMLIMIT_1, 0, 2); 1261297850Ssgalabov mtk_pci_write_config(dev, 0, i, 0, PCIR_PMBASEL_1, 0xffff, 2); 1262297850Ssgalabov mtk_pci_write_config(dev, 0, i, 0, PCIR_PMBASEH_1, 0xffffffff, 1263297850Ssgalabov 4); 1264297850Ssgalabov mtk_pci_write_config(dev, 0, i, 0, PCIR_PMLIMITL_1, 0, 2); 1265297850Ssgalabov mtk_pci_write_config(dev, 0, i, 0, PCIR_PMLIMITH_1, 0, 4); 1266297717Ssgalabov } 1267297717Ssgalabov} 1268