mtk_pcie.c revision 298350
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: head/sys/mips/mediatek/mtk_pcie.c 298350 2016-04-20 14:47:16Z sgalabov $"); 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 }, 206298059Ssgalabov { "mediatek,mt7621-pci", MTK_SOC_MT7621 }, 207297717Ssgalabov { NULL, MTK_SOC_UNKNOWN } 208297717Ssgalabov}; 209297717Ssgalabov 210297717Ssgalabovstatic int 211297717Ssgalabovmtk_pci_probe(device_t dev) 212297717Ssgalabov{ 213297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 214297717Ssgalabov 215297717Ssgalabov if (!ofw_bus_status_okay(dev)) 216297717Ssgalabov return (ENXIO); 217297717Ssgalabov 218297717Ssgalabov sc->socid = ofw_bus_search_compatible(dev, compat_data)->ocd_data; 219297717Ssgalabov if (sc->socid == MTK_SOC_UNKNOWN) 220297717Ssgalabov return (ENXIO); 221297717Ssgalabov 222297717Ssgalabov device_set_desc(dev, "MTK PCIe Controller"); 223297717Ssgalabov 224297717Ssgalabov return (0); 225297717Ssgalabov} 226297717Ssgalabov 227297717Ssgalabovstatic int 228297717Ssgalabovmtk_pci_attach(device_t dev) 229297717Ssgalabov{ 230297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 231297717Ssgalabov struct mtk_pci_range io_space, mem_space; 232297717Ssgalabov phandle_t node; 233297717Ssgalabov intptr_t xref; 234297717Ssgalabov int i, rid; 235297717Ssgalabov 236297717Ssgalabov sc->sc_dev = dev; 237297717Ssgalabov mt_sc = sc; 238297717Ssgalabov sc->addr_mask = 0xffffffff; 239297717Ssgalabov 240297717Ssgalabov /* Request our memory */ 241297717Ssgalabov rid = 0; 242297717Ssgalabov sc->pci_res[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 243297717Ssgalabov RF_ACTIVE); 244297717Ssgalabov if (sc->pci_res[0] == NULL) { 245297717Ssgalabov device_printf(dev, "could not allocate memory resource\n"); 246297717Ssgalabov return (ENXIO); 247297717Ssgalabov } 248297717Ssgalabov 249297717Ssgalabov /* See how many interrupts we need */ 250297717Ssgalabov if (sc->socid == MTK_SOC_MT7621) 251297717Ssgalabov sc->sc_num_irq = 3; 252297717Ssgalabov else { 253297717Ssgalabov sc->sc_num_irq = 1; 254297717Ssgalabov sc->pci_res[2] = sc->pci_res[3] = NULL; 255297717Ssgalabov sc->pci_intrhand[1] = sc->pci_intrhand[2] = NULL; 256297717Ssgalabov } 257297717Ssgalabov 258297717Ssgalabov /* Request our interrupts */ 259297717Ssgalabov for (i = 1; i <= sc->sc_num_irq ; i++) { 260297717Ssgalabov rid = i - 1; 261297717Ssgalabov sc->pci_res[i] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 262297717Ssgalabov RF_ACTIVE); 263297717Ssgalabov if (sc->pci_res[i] == NULL) { 264297717Ssgalabov device_printf(dev, "could not allocate interrupt " 265297717Ssgalabov "resource %d\n", rid); 266297717Ssgalabov goto cleanup_res; 267297717Ssgalabov } 268297717Ssgalabov } 269297717Ssgalabov 270297717Ssgalabov /* Parse our PCI 'ranges' property */ 271297717Ssgalabov node = ofw_bus_get_node(dev); 272297717Ssgalabov xref = OF_xref_from_node(node); 273297717Ssgalabov if (mtk_pci_ranges(node, &io_space, &mem_space)) { 274297717Ssgalabov device_printf(dev, "could not retrieve 'ranges' data\n"); 275297717Ssgalabov goto cleanup_res; 276297717Ssgalabov } 277297717Ssgalabov 278297717Ssgalabov /* Memory, I/O and IRQ resource limits */ 279297717Ssgalabov sc->sc_io_base = io_space.base; 280297717Ssgalabov sc->sc_io_size = io_space.len; 281297717Ssgalabov sc->sc_mem_base = mem_space.base; 282297717Ssgalabov sc->sc_mem_size = mem_space.len; 283297717Ssgalabov sc->sc_irq_start = MTK_PCIE0_IRQ; 284297717Ssgalabov sc->sc_irq_end = MTK_PCIE2_IRQ; 285297717Ssgalabov 286297717Ssgalabov /* Init resource managers for memory, I/O and IRQ */ 287297717Ssgalabov sc->sc_mem_rman.rm_type = RMAN_ARRAY; 288297717Ssgalabov sc->sc_mem_rman.rm_descr = "mtk pcie memory window"; 289297717Ssgalabov if (rman_init(&sc->sc_mem_rman) != 0 || 290297717Ssgalabov rman_manage_region(&sc->sc_mem_rman, sc->sc_mem_base, 291297717Ssgalabov sc->sc_mem_base + sc->sc_mem_size - 1) != 0) { 292297717Ssgalabov device_printf(dev, "failed to setup memory rman\n"); 293297717Ssgalabov goto cleanup_res; 294297717Ssgalabov } 295297717Ssgalabov 296297717Ssgalabov sc->sc_io_rman.rm_type = RMAN_ARRAY; 297297717Ssgalabov sc->sc_io_rman.rm_descr = "mtk pcie io window"; 298297717Ssgalabov if (rman_init(&sc->sc_io_rman) != 0 || 299297717Ssgalabov rman_manage_region(&sc->sc_io_rman, sc->sc_io_base, 300297717Ssgalabov sc->sc_io_base + sc->sc_io_size - 1) != 0) { 301297717Ssgalabov device_printf(dev, "failed to setup io rman\n"); 302297717Ssgalabov goto cleanup_res; 303297717Ssgalabov } 304297717Ssgalabov 305297717Ssgalabov sc->sc_irq_rman.rm_type = RMAN_ARRAY; 306297717Ssgalabov sc->sc_irq_rman.rm_descr = "mtk pcie irqs"; 307297717Ssgalabov if (rman_init(&sc->sc_irq_rman) != 0 || 308297717Ssgalabov rman_manage_region(&sc->sc_irq_rman, sc->sc_irq_start, 309297717Ssgalabov sc->sc_irq_end) != 0) { 310297717Ssgalabov device_printf(dev, "failed to setup irq rman\n"); 311297717Ssgalabov goto cleanup_res; 312297717Ssgalabov } 313297717Ssgalabov 314297717Ssgalabov /* Do SoC-specific PCIe initialization */ 315297717Ssgalabov if (mtk_pcie_phy_init(dev)) { 316297717Ssgalabov device_printf(dev, "pcie phy init failed\n"); 317297717Ssgalabov goto cleanup_rman; 318297717Ssgalabov } 319297717Ssgalabov 320297717Ssgalabov /* Register ourselves as an interrupt controller */ 321297717Ssgalabov if (intr_pic_register(dev, xref) != 0) { 322297717Ssgalabov device_printf(dev, "could not register PIC\n"); 323297717Ssgalabov goto cleanup_rman; 324297717Ssgalabov } 325297717Ssgalabov 326297717Ssgalabov /* Set up our interrupt handler */ 327297717Ssgalabov for (i = 1; i <= sc->sc_num_irq; i++) { 328297717Ssgalabov sc->pci_intrhand[i - 1] = NULL; 329297717Ssgalabov if (bus_setup_intr(dev, sc->pci_res[i], INTR_TYPE_MISC, 330297717Ssgalabov mtk_pci_intr, NULL, sc, &sc->pci_intrhand[i - 1])) { 331297717Ssgalabov device_printf(dev, "could not setup intr handler %d\n", 332297717Ssgalabov i); 333297717Ssgalabov goto cleanup; 334297717Ssgalabov } 335297717Ssgalabov } 336297717Ssgalabov 337297717Ssgalabov /* Attach our PCI child so bus enumeration can start */ 338297717Ssgalabov if (device_add_child(dev, "pci", -1) == NULL) { 339297717Ssgalabov device_printf(dev, "could not attach pci bus\n"); 340297717Ssgalabov goto cleanup; 341297717Ssgalabov } 342297717Ssgalabov 343297717Ssgalabov /* And finally, attach ourselves to the bus */ 344297717Ssgalabov if (bus_generic_attach(dev)) { 345297717Ssgalabov device_printf(dev, "could not attach to bus\n"); 346297717Ssgalabov goto cleanup; 347297717Ssgalabov } 348297717Ssgalabov 349297717Ssgalabov return (0); 350297717Ssgalabov 351297717Ssgalabovcleanup: 352297717Ssgalabov#ifdef notyet 353297717Ssgalabov intr_pic_unregister(dev, xref); 354297717Ssgalabov#endif 355297717Ssgalabov for (i = 1; i <= sc->sc_num_irq; i++) { 356297717Ssgalabov if (sc->pci_intrhand[i - 1] != NULL) 357297717Ssgalabov bus_teardown_intr(dev, sc->pci_res[i], 358297717Ssgalabov sc->pci_intrhand[i - 1]); 359297717Ssgalabov } 360297717Ssgalabovcleanup_rman: 361297717Ssgalabov mtk_pcie_phy_stop(dev); 362297717Ssgalabov rman_fini(&sc->sc_irq_rman); 363297717Ssgalabov rman_fini(&sc->sc_io_rman); 364297717Ssgalabov rman_fini(&sc->sc_mem_rman); 365297717Ssgalabovcleanup_res: 366297717Ssgalabov mt_sc = NULL; 367297717Ssgalabov if (sc->pci_res[0] != NULL) 368297717Ssgalabov bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->pci_res[0]); 369297717Ssgalabov if (sc->pci_res[1] != NULL) 370297717Ssgalabov bus_release_resource(dev, SYS_RES_IRQ, 0, sc->pci_res[1]); 371297717Ssgalabov if (sc->pci_res[2] != NULL) 372297717Ssgalabov bus_release_resource(dev, SYS_RES_IRQ, 1, sc->pci_res[2]); 373297717Ssgalabov if (sc->pci_res[3] != NULL) 374297717Ssgalabov bus_release_resource(dev, SYS_RES_IRQ, 2, sc->pci_res[3]); 375297717Ssgalabov return (ENXIO); 376297717Ssgalabov} 377297717Ssgalabov 378297717Ssgalabovstatic int 379297717Ssgalabovmtk_pci_read_ivar(device_t dev, device_t child, int which, 380297717Ssgalabov uintptr_t *result) 381297717Ssgalabov{ 382297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 383297717Ssgalabov 384297717Ssgalabov switch (which) { 385297717Ssgalabov case PCIB_IVAR_DOMAIN: 386297717Ssgalabov *result = device_get_unit(dev); 387297717Ssgalabov return (0); 388297717Ssgalabov case PCIB_IVAR_BUS: 389297717Ssgalabov *result = sc->sc_busno; 390297717Ssgalabov return (0); 391297717Ssgalabov } 392297717Ssgalabov 393297717Ssgalabov return (ENOENT); 394297717Ssgalabov} 395297717Ssgalabov 396297717Ssgalabovstatic int 397297717Ssgalabovmtk_pci_write_ivar(device_t dev, device_t child, int which, 398297717Ssgalabov uintptr_t result) 399297717Ssgalabov{ 400297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 401297717Ssgalabov 402297717Ssgalabov switch (which) { 403297717Ssgalabov case PCIB_IVAR_BUS: 404297717Ssgalabov sc->sc_busno = result; 405297717Ssgalabov return (0); 406297717Ssgalabov } 407297717Ssgalabov 408297717Ssgalabov return (ENOENT); 409297717Ssgalabov} 410297717Ssgalabov 411297717Ssgalabovstatic struct resource * 412297717Ssgalabovmtk_pci_alloc_resource(device_t bus, device_t child, int type, int *rid, 413297717Ssgalabov rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) 414297717Ssgalabov{ 415297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(bus); 416297717Ssgalabov struct resource *rv; 417297717Ssgalabov struct rman *rm; 418297717Ssgalabov 419297717Ssgalabov switch (type) { 420297850Ssgalabov case PCI_RES_BUS: 421297850Ssgalabov return pci_domain_alloc_bus(0, child, rid, start, end, count, 422297850Ssgalabov flags); 423297717Ssgalabov case SYS_RES_IRQ: 424297717Ssgalabov rm = &sc->sc_irq_rman; 425297717Ssgalabov break; 426297717Ssgalabov case SYS_RES_IOPORT: 427297717Ssgalabov rm = &sc->sc_io_rman; 428297717Ssgalabov break; 429297717Ssgalabov case SYS_RES_MEMORY: 430297717Ssgalabov rm = &sc->sc_mem_rman; 431297717Ssgalabov break; 432297717Ssgalabov default: 433297717Ssgalabov return (NULL); 434297717Ssgalabov } 435297717Ssgalabov 436297717Ssgalabov rv = rman_reserve_resource(rm, start, end, count, flags, child); 437297717Ssgalabov 438297717Ssgalabov if (rv == NULL) 439297717Ssgalabov return (NULL); 440297717Ssgalabov 441297717Ssgalabov rman_set_rid(rv, *rid); 442297717Ssgalabov 443297717Ssgalabov if ((flags & RF_ACTIVE) && type != SYS_RES_IRQ) { 444297717Ssgalabov if (bus_activate_resource(child, type, *rid, rv)) { 445297717Ssgalabov rman_release_resource(rv); 446297717Ssgalabov return (NULL); 447297717Ssgalabov } 448297717Ssgalabov } 449297717Ssgalabov 450297717Ssgalabov return (rv); 451297717Ssgalabov} 452297717Ssgalabov 453297850Ssgalabovstatic int 454297850Ssgalabovmtk_pci_release_resource(device_t bus, device_t child, int type, int rid, 455297850Ssgalabov struct resource *res) 456297850Ssgalabov{ 457297850Ssgalabov 458297850Ssgalabov if (type == PCI_RES_BUS) 459297850Ssgalabov return (pci_domain_release_bus(0, child, rid, res)); 460297850Ssgalabov 461297850Ssgalabov return (bus_generic_release_resource(bus, child, type, rid, res)); 462297850Ssgalabov} 463297850Ssgalabov 464297850Ssgalabovstatic int 465297850Ssgalabovmtk_pci_adjust_resource(device_t bus, device_t child, int type, 466297850Ssgalabov struct resource *res, rman_res_t start, rman_res_t end) 467297850Ssgalabov{ 468297850Ssgalabov struct mtk_pci_softc *sc = device_get_softc(bus); 469297850Ssgalabov struct rman *rm; 470297850Ssgalabov 471297850Ssgalabov switch (type) { 472297850Ssgalabov case PCI_RES_BUS: 473297850Ssgalabov return pci_domain_adjust_bus(0, child, res, start, end); 474297850Ssgalabov case SYS_RES_IRQ: 475297850Ssgalabov rm = &sc->sc_irq_rman; 476297850Ssgalabov break; 477297850Ssgalabov case SYS_RES_IOPORT: 478297850Ssgalabov rm = &sc->sc_io_rman; 479297850Ssgalabov break; 480297850Ssgalabov case SYS_RES_MEMORY: 481297850Ssgalabov rm = &sc->sc_mem_rman; 482297850Ssgalabov break; 483297850Ssgalabov default: 484297850Ssgalabov rm = NULL; 485297850Ssgalabov break; 486297850Ssgalabov } 487297850Ssgalabov 488297850Ssgalabov if (rm != NULL) 489297850Ssgalabov return (rman_adjust_resource(res, start, end)); 490297850Ssgalabov 491297850Ssgalabov return (bus_generic_adjust_resource(bus, child, type, res, start, end)); 492297850Ssgalabov} 493297850Ssgalabov 494297717Ssgalabovstatic inline int 495297717Ssgalabovmtk_idx_to_irq(int idx) 496297717Ssgalabov{ 497297717Ssgalabov 498297717Ssgalabov return ((idx == 0) ? MTK_PCIE0_IRQ : 499297717Ssgalabov (idx == 1) ? MTK_PCIE1_IRQ : 500297717Ssgalabov (idx == 2) ? MTK_PCIE2_IRQ : -1); 501297717Ssgalabov} 502297717Ssgalabov 503297717Ssgalabovstatic inline int 504297717Ssgalabovmtk_irq_to_idx(int irq) 505297717Ssgalabov{ 506297717Ssgalabov 507297717Ssgalabov return ((irq == MTK_PCIE0_IRQ) ? 0 : 508297717Ssgalabov (irq == MTK_PCIE1_IRQ) ? 1 : 509297717Ssgalabov (irq == MTK_PCIE2_IRQ) ? 2 : -1); 510297717Ssgalabov} 511297717Ssgalabov 512297717Ssgalabovstatic void 513297717Ssgalabovmtk_pci_mask_irq(void *source) 514297717Ssgalabov{ 515297717Ssgalabov MT_WRITE32(mt_sc, MTK_PCI_PCIENA, 516297717Ssgalabov MT_READ32(mt_sc, MTK_PCI_PCIENA) & ~(1<<((int)source))); 517297717Ssgalabov} 518297717Ssgalabov 519297717Ssgalabovstatic void 520297717Ssgalabovmtk_pci_unmask_irq(void *source) 521297717Ssgalabov{ 522297717Ssgalabov 523297717Ssgalabov MT_WRITE32(mt_sc, MTK_PCI_PCIENA, 524297717Ssgalabov MT_READ32(mt_sc, MTK_PCI_PCIENA) | (1<<((int)source))); 525297717Ssgalabov} 526297717Ssgalabov 527297717Ssgalabovstatic int 528297717Ssgalabovmtk_pci_setup_intr(device_t bus, device_t child, struct resource *ires, 529297717Ssgalabov int flags, driver_filter_t *filt, driver_intr_t *handler, 530297717Ssgalabov void *arg, void **cookiep) 531297717Ssgalabov{ 532297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(bus); 533297717Ssgalabov struct intr_event *event; 534297717Ssgalabov int irq, error, irqidx; 535297717Ssgalabov 536297717Ssgalabov irq = rman_get_start(ires); 537297717Ssgalabov 538297717Ssgalabov if (irq < sc->sc_irq_start || irq > sc->sc_irq_end) 539297717Ssgalabov return (EINVAL); 540297717Ssgalabov 541297717Ssgalabov irqidx = irq - sc->sc_irq_start; 542297717Ssgalabov 543297717Ssgalabov event = sc->sc_eventstab[irqidx]; 544297717Ssgalabov if (event == NULL) { 545297717Ssgalabov error = intr_event_create(&event, (void *)irq, 0, irq, 546297717Ssgalabov mtk_pci_mask_irq, mtk_pci_unmask_irq, NULL, NULL, 547297717Ssgalabov "pci intr%d:", irq); 548297717Ssgalabov 549297717Ssgalabov if (error == 0) { 550297717Ssgalabov sc->sc_eventstab[irqidx] = event; 551297717Ssgalabov } 552297717Ssgalabov else { 553297717Ssgalabov return (error); 554297717Ssgalabov } 555297717Ssgalabov } 556297717Ssgalabov 557297717Ssgalabov intr_event_add_handler(event, device_get_nameunit(child), filt, 558297717Ssgalabov handler, arg, intr_priority(flags), flags, cookiep); 559297717Ssgalabov 560297717Ssgalabov mtk_pci_unmask_irq((void*)irq); 561297717Ssgalabov 562297717Ssgalabov return (0); 563297717Ssgalabov} 564297717Ssgalabov 565297717Ssgalabovstatic int 566297717Ssgalabovmtk_pci_teardown_intr(device_t dev, device_t child, struct resource *ires, 567297717Ssgalabov void *cookie) 568297717Ssgalabov{ 569297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 570297717Ssgalabov int irq, result, irqidx; 571297717Ssgalabov 572297717Ssgalabov irq = rman_get_start(ires); 573297717Ssgalabov if (irq < sc->sc_irq_start || irq > sc->sc_irq_end) 574297717Ssgalabov return (EINVAL); 575297717Ssgalabov 576297717Ssgalabov irqidx = irq - sc->sc_irq_start; 577297717Ssgalabov if (sc->sc_eventstab[irqidx] == NULL) 578297717Ssgalabov panic("Trying to teardown unoccupied IRQ"); 579297717Ssgalabov 580297717Ssgalabov mtk_pci_mask_irq((void*)irq); 581297717Ssgalabov 582297717Ssgalabov result = intr_event_remove_handler(cookie); 583297717Ssgalabov if (!result) 584297717Ssgalabov sc->sc_eventstab[irqidx] = NULL; 585297717Ssgalabov 586297717Ssgalabov 587297717Ssgalabov return (result); 588297717Ssgalabov} 589297717Ssgalabov 590297717Ssgalabovstatic inline uint32_t 591297717Ssgalabovmtk_pci_make_addr(int bus, int slot, int func, int reg) 592297717Ssgalabov{ 593297717Ssgalabov uint32_t addr; 594297717Ssgalabov 595297717Ssgalabov addr = ((((reg & 0xf00) >> 8) << 24) | (bus << 16) | (slot << 11) | 596297717Ssgalabov (func << 8) | (reg & 0xfc) | (1 << 31)); 597297717Ssgalabov 598297717Ssgalabov return (addr); 599297717Ssgalabov} 600297717Ssgalabov 601297717Ssgalabovstatic int 602297717Ssgalabovmtk_pci_maxslots(device_t dev) 603297717Ssgalabov{ 604297717Ssgalabov 605297717Ssgalabov return (PCI_SLOTMAX); 606297717Ssgalabov} 607297717Ssgalabov 608297717Ssgalabovstatic inline int 609297717Ssgalabovmtk_pci_slot_has_link(device_t dev, int slot) 610297717Ssgalabov{ 611297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 612297717Ssgalabov 613297717Ssgalabov return !!(sc->pcie_link_status & (1<<slot)); 614297717Ssgalabov} 615297717Ssgalabov 616297717Ssgalabovstatic uint32_t 617297717Ssgalabovmtk_pci_read_config(device_t dev, u_int bus, u_int slot, u_int func, 618297717Ssgalabov u_int reg, int bytes) 619297717Ssgalabov{ 620297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 621297717Ssgalabov uint32_t addr = 0, data = 0; 622297717Ssgalabov 623297717Ssgalabov /* Return ~0U if slot has no link */ 624297717Ssgalabov if (bus == 0 && mtk_pci_slot_has_link(dev, slot) == 0) { 625297717Ssgalabov return (~0U); 626297717Ssgalabov } 627297717Ssgalabov 628297717Ssgalabov mtx_lock_spin(&mtk_pci_mtx); 629297717Ssgalabov addr = mtk_pci_make_addr(bus, slot, func, (reg & ~3)) & sc->addr_mask; 630297717Ssgalabov MT_WRITE32(sc, MTK_PCI_CFGADDR, addr); 631297717Ssgalabov switch (bytes % 4) { 632297717Ssgalabov case 0: 633297717Ssgalabov data = MT_READ32(sc, MTK_PCI_CFGDATA); 634297717Ssgalabov break; 635297717Ssgalabov case 1: 636297717Ssgalabov data = MT_READ8(sc, MTK_PCI_CFGDATA + (reg & 0x3)); 637297717Ssgalabov break; 638297717Ssgalabov case 2: 639297717Ssgalabov data = MT_READ16(sc, MTK_PCI_CFGDATA + (reg & 0x3)); 640297717Ssgalabov break; 641297717Ssgalabov default: 642297717Ssgalabov panic("%s(): Wrong number of bytes (%d) requested!\n", 643297717Ssgalabov __FUNCTION__, bytes % 4); 644297717Ssgalabov } 645297717Ssgalabov mtx_unlock_spin(&mtk_pci_mtx); 646297717Ssgalabov 647297717Ssgalabov return (data); 648297717Ssgalabov} 649297717Ssgalabov 650297717Ssgalabovstatic void 651297717Ssgalabovmtk_pci_write_config(device_t dev, u_int bus, u_int slot, u_int func, 652297717Ssgalabov u_int reg, uint32_t val, int bytes) 653297717Ssgalabov{ 654297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 655297717Ssgalabov uint32_t addr = 0, data = val; 656297717Ssgalabov 657297717Ssgalabov /* Do not write if slot has no link */ 658297717Ssgalabov if (bus == 0 && mtk_pci_slot_has_link(dev, slot) == 0) 659297717Ssgalabov return; 660297717Ssgalabov 661297717Ssgalabov mtx_lock_spin(&mtk_pci_mtx); 662297717Ssgalabov addr = mtk_pci_make_addr(bus, slot, func, (reg & ~3)) & sc->addr_mask; 663297717Ssgalabov MT_WRITE32(sc, MTK_PCI_CFGADDR, addr); 664297717Ssgalabov switch (bytes % 4) { 665297717Ssgalabov case 0: 666297717Ssgalabov MT_WRITE32(sc, MTK_PCI_CFGDATA, data); 667297717Ssgalabov break; 668297717Ssgalabov case 1: 669297717Ssgalabov MT_WRITE8(sc, MTK_PCI_CFGDATA + (reg & 0x3), data); 670297717Ssgalabov break; 671297717Ssgalabov case 2: 672297717Ssgalabov MT_WRITE16(sc, MTK_PCI_CFGDATA + (reg & 0x3), data); 673297717Ssgalabov break; 674297717Ssgalabov default: 675297717Ssgalabov panic("%s(): Wrong number of bytes (%d) requested!\n", 676297717Ssgalabov __FUNCTION__, bytes % 4); 677297717Ssgalabov } 678297717Ssgalabov mtx_unlock_spin(&mtk_pci_mtx); 679297717Ssgalabov} 680297717Ssgalabov 681297717Ssgalabovstatic int 682297717Ssgalabovmtk_pci_route_interrupt(device_t pcib, device_t device, int pin) 683297717Ssgalabov{ 684297717Ssgalabov int bus, sl, dev; 685297717Ssgalabov 686297717Ssgalabov bus = pci_get_bus(device); 687297717Ssgalabov sl = pci_get_slot(device); 688297717Ssgalabov dev = pci_get_device(device); 689297717Ssgalabov 690297717Ssgalabov if (bus != 0) 691297717Ssgalabov panic("Unexpected bus number %d\n", bus); 692297717Ssgalabov 693297717Ssgalabov /* PCIe only */ 694297717Ssgalabov switch (sl) { 695297717Ssgalabov case 0: return MTK_PCIE0_IRQ; 696297717Ssgalabov case 1: return MTK_PCIE0_IRQ + 1; 697297717Ssgalabov case 2: return MTK_PCIE0_IRQ + 2; 698297717Ssgalabov default: return (-1); 699297717Ssgalabov } 700297717Ssgalabov 701297717Ssgalabov return (-1); 702297717Ssgalabov} 703297717Ssgalabov 704297717Ssgalabovstatic device_method_t mtk_pci_methods[] = { 705297717Ssgalabov /* Device interface */ 706297717Ssgalabov DEVMETHOD(device_probe, mtk_pci_probe), 707297717Ssgalabov DEVMETHOD(device_attach, mtk_pci_attach), 708297717Ssgalabov DEVMETHOD(device_shutdown, bus_generic_shutdown), 709297717Ssgalabov DEVMETHOD(device_suspend, bus_generic_suspend), 710297717Ssgalabov DEVMETHOD(device_resume, bus_generic_resume), 711297717Ssgalabov 712297717Ssgalabov /* Bus interface */ 713297717Ssgalabov DEVMETHOD(bus_read_ivar, mtk_pci_read_ivar), 714297717Ssgalabov DEVMETHOD(bus_write_ivar, mtk_pci_write_ivar), 715297717Ssgalabov DEVMETHOD(bus_alloc_resource, mtk_pci_alloc_resource), 716297850Ssgalabov DEVMETHOD(bus_release_resource, mtk_pci_release_resource), 717297850Ssgalabov DEVMETHOD(bus_adjust_resource, mtk_pci_adjust_resource), 718297717Ssgalabov DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 719297717Ssgalabov DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 720297717Ssgalabov DEVMETHOD(bus_setup_intr, mtk_pci_setup_intr), 721297717Ssgalabov DEVMETHOD(bus_teardown_intr, mtk_pci_teardown_intr), 722297717Ssgalabov 723297717Ssgalabov /* pcib interface */ 724297717Ssgalabov DEVMETHOD(pcib_maxslots, mtk_pci_maxslots), 725297717Ssgalabov DEVMETHOD(pcib_read_config, mtk_pci_read_config), 726297717Ssgalabov DEVMETHOD(pcib_write_config, mtk_pci_write_config), 727297717Ssgalabov DEVMETHOD(pcib_route_interrupt, mtk_pci_route_interrupt), 728297717Ssgalabov 729297850Ssgalabov /* OFW bus interface */ 730297850Ssgalabov DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 731297850Ssgalabov DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 732297850Ssgalabov DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 733297850Ssgalabov DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 734297850Ssgalabov DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 735297850Ssgalabov 736297717Ssgalabov DEVMETHOD_END 737297717Ssgalabov}; 738297717Ssgalabov 739297717Ssgalabovstatic driver_t mtk_pci_driver = { 740297717Ssgalabov "pcib", 741297717Ssgalabov mtk_pci_methods, 742297717Ssgalabov sizeof(struct mtk_pci_softc), 743297717Ssgalabov}; 744297717Ssgalabov 745297717Ssgalabovstatic devclass_t mtk_pci_devclass; 746297717Ssgalabov 747297717SsgalabovDRIVER_MODULE(mtk_pci, simplebus, mtk_pci_driver, mtk_pci_devclass, 0, 0); 748297717Ssgalabov 749297717Ssgalabov/* Our interrupt handler */ 750297717Ssgalabovstatic int 751297717Ssgalabovmtk_pci_intr(void *arg) 752297717Ssgalabov{ 753297717Ssgalabov struct mtk_pci_softc *sc = arg; 754297717Ssgalabov struct intr_event *event; 755297717Ssgalabov uint32_t reg, irq, irqidx; 756297717Ssgalabov 757297717Ssgalabov reg = MT_READ32(sc, MTK_PCI_PCIINT); 758297717Ssgalabov 759297717Ssgalabov for (irq = sc->sc_irq_start; irq <= sc->sc_irq_end; irq++) { 760297717Ssgalabov if (reg & (1u<<irq)) { 761297717Ssgalabov irqidx = irq - sc->sc_irq_start; 762297717Ssgalabov event = sc->sc_eventstab[irqidx]; 763297717Ssgalabov if (!event || TAILQ_EMPTY(&event->ie_handlers)) { 764297717Ssgalabov if (irq != 0) 765297717Ssgalabov printf("Stray PCI IRQ %d\n", irq); 766297717Ssgalabov continue; 767297717Ssgalabov } 768297717Ssgalabov 769297717Ssgalabov intr_event_handle(event, NULL); 770297717Ssgalabov } 771297717Ssgalabov } 772297717Ssgalabov 773297717Ssgalabov return (FILTER_HANDLED); 774297717Ssgalabov} 775297717Ssgalabov 776297717Ssgalabov/* PCIe SoC-specific initialization */ 777297717Ssgalabovstatic int 778297717Ssgalabovmtk_pcie_phy_init(device_t dev) 779297717Ssgalabov{ 780297717Ssgalabov struct mtk_pci_softc *sc; 781297717Ssgalabov 782297717Ssgalabov /* Get our softc */ 783297717Ssgalabov sc = device_get_softc(dev); 784297717Ssgalabov 785297717Ssgalabov /* We don't know how many slots we have yet */ 786297717Ssgalabov sc->num_slots = 0; 787297717Ssgalabov 788297717Ssgalabov /* Handle SoC specific PCIe init */ 789297717Ssgalabov switch (sc->socid) { 790297717Ssgalabov case MTK_SOC_MT7628: /* Fallthrough */ 791297717Ssgalabov case MTK_SOC_MT7688: 792297717Ssgalabov if (mtk_pcie_phy_mt7628_init(dev)) 793297717Ssgalabov return (ENXIO); 794297717Ssgalabov break; 795297717Ssgalabov case MTK_SOC_MT7621: 796297717Ssgalabov if (mtk_pcie_phy_mt7621_init(dev)) 797297717Ssgalabov return (ENXIO); 798297717Ssgalabov break; 799297717Ssgalabov case MTK_SOC_MT7620A: 800297717Ssgalabov if (mtk_pcie_phy_mt7620_init(dev)) 801297717Ssgalabov return (ENXIO); 802297717Ssgalabov break; 803297717Ssgalabov case MTK_SOC_RT3662: /* Fallthrough */ 804297717Ssgalabov case MTK_SOC_RT3883: 805297717Ssgalabov if (mtk_pcie_phy_rt3883_init(dev)) 806297717Ssgalabov return (ENXIO); 807297717Ssgalabov break; 808297717Ssgalabov default: 809297717Ssgalabov device_printf(dev, "unsupported device %x\n", sc->socid); 810297717Ssgalabov return (ENXIO); 811297717Ssgalabov } 812297717Ssgalabov 813297717Ssgalabov /* 814297717Ssgalabov * If we were successful so far go and set up the PCIe slots, so we 815297717Ssgalabov * may allocate mem/io/irq resources and enumerate busses later. 816297717Ssgalabov */ 817297717Ssgalabov mtk_pcie_phy_setup_slots(dev); 818297717Ssgalabov 819297717Ssgalabov return (0); 820297717Ssgalabov} 821297717Ssgalabov 822297717Ssgalabovstatic int 823297717Ssgalabovmtk_pcie_phy_start(device_t dev) 824297717Ssgalabov{ 825297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 826297717Ssgalabov 827297717Ssgalabov if (sc->socid == MTK_SOC_MT7621 && 828297717Ssgalabov (mtk_sysctl_get(SYSCTL_REVID) & SYSCTL_REVID_MASK) != 829297717Ssgalabov SYSCTL_MT7621_REV_E) { 830297717Ssgalabov if (fdt_reset_assert_all(dev)) 831297717Ssgalabov return (ENXIO); 832297717Ssgalabov } else { 833297717Ssgalabov if (fdt_reset_deassert_all(dev)) 834297717Ssgalabov return (ENXIO); 835297717Ssgalabov } 836297717Ssgalabov 837297717Ssgalabov if (fdt_clock_enable_all(dev)) 838297717Ssgalabov return (ENXIO); 839297717Ssgalabov 840297717Ssgalabov return (0); 841297717Ssgalabov} 842297717Ssgalabov 843297717Ssgalabovstatic int 844297717Ssgalabovmtk_pcie_phy_stop(device_t dev) 845297717Ssgalabov{ 846297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 847297717Ssgalabov 848297717Ssgalabov if (sc->socid == MTK_SOC_MT7621 && 849297717Ssgalabov (mtk_sysctl_get(SYSCTL_REVID) & SYSCTL_REVID_MASK) != 850297717Ssgalabov SYSCTL_MT7621_REV_E) { 851297717Ssgalabov if (fdt_reset_deassert_all(dev)) 852297717Ssgalabov return (ENXIO); 853297717Ssgalabov } else { 854297717Ssgalabov if (fdt_reset_assert_all(dev)) 855297717Ssgalabov return (ENXIO); 856297717Ssgalabov } 857297717Ssgalabov 858297717Ssgalabov if (fdt_clock_disable_all(dev)) 859297717Ssgalabov return (ENXIO); 860297717Ssgalabov 861297717Ssgalabov return (0); 862297717Ssgalabov} 863297717Ssgalabov 864297717Ssgalabov#define mtk_pcie_phy_set(_sc, _reg, _s, _n, _v) \ 865297717Ssgalabov MT_WRITE32((_sc), (_reg), ((MT_READ32((_sc), (_reg)) & \ 866297717Ssgalabov (~(((1ull << (_n)) - 1) << (_s)))) | ((_v) << (_s)))) 867297717Ssgalabov 868297717Ssgalabovstatic void 869297717Ssgalabovmtk_pcie_phy_mt7621_bypass_pipe_rst(struct mtk_pci_softc *sc, uint32_t off) 870297717Ssgalabov{ 871297717Ssgalabov 872297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x002c, 12, 1, 1); 873297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x002c, 4, 1, 1); 874297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x012c, 12, 1, 1); 875297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x012c, 4, 1, 1); 876297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x102c, 12, 1, 1); 877297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x102c, 4, 1, 1); 878297717Ssgalabov} 879297717Ssgalabov 880297717Ssgalabovstatic void 881297717Ssgalabovmtk_pcie_phy_mt7621_setup_ssc(struct mtk_pci_softc *sc, uint32_t off) 882297717Ssgalabov{ 883297717Ssgalabov uint32_t xtal_sel; 884297717Ssgalabov 885297717Ssgalabov xtal_sel = mtk_sysctl_get(SYSCTL_SYSCFG) >> 6; 886297717Ssgalabov xtal_sel &= 0x7; 887297717Ssgalabov 888297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x400, 8, 1, 1); 889297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x400, 9, 2, 0); 890297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x000, 4, 1, 1); 891297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x100, 4, 1, 1); 892297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x000, 5, 1, 0); 893297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x100, 5, 1, 0); 894297717Ssgalabov 895297717Ssgalabov if (xtal_sel <= 5 && xtal_sel >= 3) { 896297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x490, 6, 2, 1); 897297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 0, 12, 0x1a); 898297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 16, 12, 0x1a); 899297717Ssgalabov } else { 900297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x490, 6, 2, 0); 901297717Ssgalabov if (xtal_sel >= 6) { 902297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4bc, 4, 2, 0x01); 903297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x49c, 0, 31, 0x18000000); 904297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a4, 0, 16, 0x18d); 905297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 0, 12, 0x4a); 906297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 16, 12, 0x4a); 907297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 0, 12, 0x11); 908297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 16, 12, 0x11); 909297717Ssgalabov } else { 910297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 0, 12, 0x1a); 911297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 16, 12, 0x1a); 912297717Ssgalabov } 913297717Ssgalabov } 914297717Ssgalabov 915297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a0, 5, 1, 1); 916297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x490, 22, 2, 2); 917297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x490, 18, 4, 6); 918297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x490, 12, 4, 2); 919297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x490, 8, 4, 1); 920297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4ac, 16, 3, 0); 921297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x490, 1, 3, 2); 922297717Ssgalabov 923297717Ssgalabov if (xtal_sel <= 5 && xtal_sel >= 3) { 924297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x414, 6, 2, 1); 925297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x414, 5, 1, 1); 926297717Ssgalabov } 927297717Ssgalabov 928297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x414, 28, 2, 1); 929297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x040, 17, 4, 7); 930297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x040, 16, 1, 1); 931297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x140, 17, 4, 7); 932297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x140, 16, 1, 1); 933297717Ssgalabov 934297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x000, 5, 1, 1); 935297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x100, 5, 1, 1); 936297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x000, 4, 1, 0); 937297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x100, 4, 1, 0); 938297717Ssgalabov} 939297717Ssgalabov 940297717Ssgalabov/* XXX: ugly, we need to fix this at some point */ 941297717Ssgalabov#define MT7621_GPIO_CTRL0 *((volatile uint32_t *)0xbe000600) 942297717Ssgalabov#define MT7621_GPIO_DATA0 *((volatile uint32_t *)0xbe000620) 943297717Ssgalabov 944297717Ssgalabov#define mtk_gpio_clr_set(_reg, _clr, _set) \ 945297717Ssgalabov do { \ 946297717Ssgalabov (_reg) = ((_reg) & (_clr)) | (_set); \ 947297717Ssgalabov } while (0) 948297717Ssgalabov 949297717Ssgalabovstatic int 950297717Ssgalabovmtk_pcie_phy_mt7621_init(device_t dev) 951297717Ssgalabov{ 952297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 953297717Ssgalabov 954297717Ssgalabov /* First off, stop the PHY */ 955297717Ssgalabov if (mtk_pcie_phy_stop(dev)) 956297717Ssgalabov return (ENXIO); 957297717Ssgalabov 958297717Ssgalabov /* PCIe resets are GPIO pins */ 959297717Ssgalabov mtk_sysctl_clr_set(SYSCTL_GPIOMODE, MT7621_PERST_GPIO_MODE | 960297717Ssgalabov MT7621_UARTL3_GPIO_MODE, MT7621_PERST_GPIO | MT7621_UARTL3_GPIO); 961297717Ssgalabov 962297717Ssgalabov /* Set GPIO pins as outputs */ 963297717Ssgalabov mtk_gpio_clr_set(MT7621_GPIO_CTRL0, 0, MT7621_PCIE_RST); 964297717Ssgalabov 965297717Ssgalabov /* Assert resets to PCIe devices */ 966297717Ssgalabov mtk_gpio_clr_set(MT7621_GPIO_DATA0, MT7621_PCIE_RST, 0); 967297717Ssgalabov 968297717Ssgalabov /* Give everything a chance to sink in */ 969297717Ssgalabov DELAY(100000); 970297717Ssgalabov 971297717Ssgalabov /* Now start the PHY again */ 972297717Ssgalabov if (mtk_pcie_phy_start(dev)) 973297717Ssgalabov return (ENXIO); 974297717Ssgalabov 975297717Ssgalabov /* Wait for things to settle */ 976297717Ssgalabov DELAY(100000); 977297717Ssgalabov 978297717Ssgalabov /* Only apply below to REV-E hardware */ 979297717Ssgalabov if ((mtk_sysctl_get(SYSCTL_REVID) & SYSCTL_REVID_MASK) == 980297717Ssgalabov SYSCTL_MT7621_REV_E) 981297717Ssgalabov mtk_pcie_phy_mt7621_bypass_pipe_rst(sc, 0x9000); 982297717Ssgalabov 983297717Ssgalabov /* Setup PCIe ports 0 and 1 */ 984297717Ssgalabov mtk_pcie_phy_mt7621_setup_ssc(sc, 0x9000); 985297717Ssgalabov /* Setup PCIe port 2 */ 986297717Ssgalabov mtk_pcie_phy_mt7621_setup_ssc(sc, 0xa000); 987297717Ssgalabov 988297717Ssgalabov /* Deassert resets to PCIe devices */ 989297717Ssgalabov mtk_gpio_clr_set(MT7621_GPIO_DATA0, 0, MT7621_PCIE_RST); 990297717Ssgalabov 991297717Ssgalabov /* Set number of slots supported */ 992297717Ssgalabov sc->num_slots = 3; 993297717Ssgalabov 994297717Ssgalabov /* Give it a chance to sink in */ 995297717Ssgalabov DELAY(100000); 996297717Ssgalabov 997297717Ssgalabov return (0); 998297717Ssgalabov} 999297717Ssgalabov 1000297717Ssgalabovstatic void 1001297717Ssgalabovmtk_pcie_phy_mt7628_setup(struct mtk_pci_softc *sc, uint32_t off) 1002297717Ssgalabov{ 1003297717Ssgalabov uint32_t xtal_sel; 1004297717Ssgalabov 1005297717Ssgalabov xtal_sel = mtk_sysctl_get(SYSCTL_SYSCFG) >> 6; 1006297717Ssgalabov xtal_sel &= 0x1; 1007297717Ssgalabov 1008297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x400, 8, 1, 1); 1009297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x400, 9, 2, 0); 1010297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x000, 4, 1, 1); 1011297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x000, 5, 1, 0); 1012297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4ac, 16, 3, 3); 1013297717Ssgalabov 1014297717Ssgalabov if (xtal_sel == 1) { 1015297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4bc, 24, 8, 0x7d); 1016297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x490, 12, 4, 0x08); 1017297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x490, 6, 2, 0x01); 1018297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4c0, 0, 32, 0x1f400000); 1019297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a4, 0, 16, 0x013d); 1020297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 16, 16, 0x74); 1021297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 0, 16, 0x74); 1022297717Ssgalabov } else { 1023297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4bc, 24, 8, 0x64); 1024297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x490, 12, 4, 0x0a); 1025297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x490, 6, 2, 0x00); 1026297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4c0, 0, 32, 0x19000000); 1027297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a4, 0, 16, 0x018d); 1028297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 16, 16, 0x4a); 1029297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x4a8, 0, 16, 0x4a); 1030297717Ssgalabov } 1031297717Ssgalabov 1032297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x498, 0, 8, 5); 1033297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x000, 5, 1, 1); 1034297717Ssgalabov mtk_pcie_phy_set(sc, off + 0x000, 4, 1, 0); 1035297717Ssgalabov} 1036297717Ssgalabov 1037297717Ssgalabovstatic int 1038297717Ssgalabovmtk_pcie_phy_mt7628_init(device_t dev) 1039297717Ssgalabov{ 1040297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 1041297717Ssgalabov 1042297717Ssgalabov /* Set PCIe reset to normal mode */ 1043297717Ssgalabov mtk_sysctl_clr_set(SYSCTL_GPIOMODE, MT7628_PERST_GPIO_MODE, 1044297717Ssgalabov MT7628_PERST); 1045297717Ssgalabov 1046297717Ssgalabov /* Start the PHY */ 1047297717Ssgalabov if (mtk_pcie_phy_start(dev)) 1048297717Ssgalabov return (ENXIO); 1049297717Ssgalabov 1050297717Ssgalabov /* Give it a chance to sink in */ 1051297717Ssgalabov DELAY(100000); 1052297717Ssgalabov 1053297717Ssgalabov /* Setup the PHY */ 1054297717Ssgalabov mtk_pcie_phy_mt7628_setup(sc, 0x9000); 1055297717Ssgalabov 1056297717Ssgalabov /* Deassert PCIe device reset */ 1057297717Ssgalabov MT_CLR_SET32(sc, MTK_PCI_PCICFG, MTK_PCI_RESET, 0); 1058297717Ssgalabov 1059297717Ssgalabov /* Set number of slots supported */ 1060297717Ssgalabov sc->num_slots = 1; 1061297717Ssgalabov 1062297717Ssgalabov return (0); 1063297717Ssgalabov} 1064297717Ssgalabov 1065297717Ssgalabovstatic int 1066297717Ssgalabovmtk_pcie_phy_mt7620_wait_busy(struct mtk_pci_softc *sc) 1067297717Ssgalabov{ 1068297717Ssgalabov uint32_t reg_value, retry; 1069297717Ssgalabov 1070297717Ssgalabov reg_value = retry = 0; 1071297717Ssgalabov 1072297717Ssgalabov while (retry++ < MT7620_MAX_RETRIES) { 1073297717Ssgalabov reg_value = MT_READ32(sc, MT7620_PCIE_PHY_CFG); 1074297717Ssgalabov if (reg_value & PHY_BUSY) 1075297717Ssgalabov DELAY(100000); 1076297717Ssgalabov else 1077297717Ssgalabov break; 1078297717Ssgalabov } 1079297717Ssgalabov 1080297717Ssgalabov if (retry >= MT7620_MAX_RETRIES) 1081297717Ssgalabov return (ENXIO); 1082297717Ssgalabov 1083297717Ssgalabov return (0); 1084297717Ssgalabov} 1085297717Ssgalabov 1086297717Ssgalabovstatic int 1087297717Ssgalabovmtk_pcie_phy_mt7620_set(struct mtk_pci_softc *sc, uint32_t reg, 1088297717Ssgalabov uint32_t val) 1089297717Ssgalabov{ 1090297717Ssgalabov uint32_t reg_val; 1091297717Ssgalabov 1092297717Ssgalabov if (mtk_pcie_phy_mt7620_wait_busy(sc)) 1093297717Ssgalabov return (ENXIO); 1094297717Ssgalabov 1095297717Ssgalabov reg_val = PHY_MODE_WRITE | ((reg & 0xff) << PHY_ADDR_OFFSET) | 1096297717Ssgalabov (val & 0xff); 1097297717Ssgalabov MT_WRITE32(sc, MT7620_PCIE_PHY_CFG, reg_val); 1098297717Ssgalabov DELAY(1000); 1099297717Ssgalabov 1100297717Ssgalabov if (mtk_pcie_phy_mt7620_wait_busy(sc)) 1101297717Ssgalabov return (ENXIO); 1102297717Ssgalabov 1103297717Ssgalabov return (0); 1104297717Ssgalabov} 1105297717Ssgalabov 1106297717Ssgalabovstatic int 1107297717Ssgalabovmtk_pcie_phy_mt7620_init(device_t dev) 1108297717Ssgalabov{ 1109297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 1110297717Ssgalabov 1111297717Ssgalabov /* 1112297717Ssgalabov * The below sets the PCIe PHY to bypass the PCIe DLL and enables 1113297717Ssgalabov * "elastic buffer control", whatever that may be... 1114297717Ssgalabov */ 1115297717Ssgalabov if (mtk_pcie_phy_mt7620_set(sc, 0x00, 0x80) || 1116297717Ssgalabov mtk_pcie_phy_mt7620_set(sc, 0x01, 0x04) || 1117297717Ssgalabov mtk_pcie_phy_mt7620_set(sc, 0x68, 0x84)) 1118297717Ssgalabov return (ENXIO); 1119297717Ssgalabov 1120297717Ssgalabov /* Stop PCIe */ 1121297717Ssgalabov if (mtk_pcie_phy_stop(dev)) 1122297717Ssgalabov return (ENXIO); 1123297717Ssgalabov 1124297717Ssgalabov /* Restore PPLL to a sane state before going on */ 1125297717Ssgalabov mtk_sysctl_clr_set(MT7620_PPLL_DRV, LC_CKDRVPD, PDRV_SW_SET); 1126297717Ssgalabov 1127297717Ssgalabov /* No PCIe on the MT7620N */ 1128297717Ssgalabov if (!(mtk_sysctl_get(SYSCTL_REVID) & MT7620_PKG_BGA)) { 1129297717Ssgalabov device_printf(dev, "PCIe disabled for MT7620N\n"); 1130297717Ssgalabov mtk_sysctl_clr_set(MT7620_PPLL_CFG0, 0, PPLL_SW_SET); 1131297717Ssgalabov mtk_sysctl_clr_set(MT7620_PPLL_CFG1, 0, PPLL_PD); 1132297717Ssgalabov return (ENXIO); 1133297717Ssgalabov } 1134297717Ssgalabov 1135297717Ssgalabov /* PCIe device reset pin is in normal mode */ 1136297717Ssgalabov mtk_sysctl_clr_set(SYSCTL_GPIOMODE, MT7620_PERST_GPIO_MODE, 1137297717Ssgalabov MT7620_PERST); 1138297717Ssgalabov 1139297717Ssgalabov /* Enable PCIe now */ 1140297717Ssgalabov if (mtk_pcie_phy_start(dev)) 1141297717Ssgalabov return (ENXIO); 1142297717Ssgalabov 1143297717Ssgalabov /* Give it a chance to sink in */ 1144297717Ssgalabov DELAY(100000); 1145297717Ssgalabov 1146297717Ssgalabov /* If PLL is not locked - bail */ 1147297717Ssgalabov if (!(mtk_sysctl_get(MT7620_PPLL_CFG1) & PPLL_LOCKED)) { 1148297717Ssgalabov device_printf(dev, "no PPLL not lock\n"); 1149297717Ssgalabov mtk_pcie_phy_stop(dev); 1150297717Ssgalabov return (ENXIO); 1151297717Ssgalabov } 1152297717Ssgalabov 1153297717Ssgalabov /* Configure PCIe PLL */ 1154297717Ssgalabov mtk_sysctl_clr_set(MT7620_PPLL_DRV, LC_CKDRVOHZ | LC_CKDRVHZ, 1155297717Ssgalabov LC_CKDRVPD | PDRV_SW_SET); 1156297717Ssgalabov 1157297717Ssgalabov /* and give it a chance to settle */ 1158297717Ssgalabov DELAY(100000); 1159297717Ssgalabov 1160297717Ssgalabov /* Deassert PCIe device reset */ 1161297717Ssgalabov MT_CLR_SET32(sc, MTK_PCI_PCICFG, MTK_PCI_RESET, 0); 1162297717Ssgalabov 1163297717Ssgalabov /* MT7620 supports one PCIe slot */ 1164297717Ssgalabov sc->num_slots = 1; 1165297717Ssgalabov 1166297717Ssgalabov return (0); 1167297717Ssgalabov} 1168297717Ssgalabov 1169297717Ssgalabovstatic int 1170297717Ssgalabovmtk_pcie_phy_rt3883_init(device_t dev) 1171297717Ssgalabov{ 1172297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 1173297717Ssgalabov 1174297717Ssgalabov /* Enable PCI host mode and PCIe RC mode */ 1175297717Ssgalabov mtk_sysctl_clr_set(SYSCTL_SYSCFG1, 0, RT3883_PCI_HOST_MODE | 1176297717Ssgalabov RT3883_PCIE_RC_MODE); 1177297717Ssgalabov 1178297717Ssgalabov /* Enable PCIe PHY */ 1179297717Ssgalabov if (mtk_pcie_phy_start(dev)) 1180297717Ssgalabov return (ENXIO); 1181297717Ssgalabov 1182297717Ssgalabov /* Disable PCI, we only support PCIe for now */ 1183297717Ssgalabov mtk_sysctl_clr_set(SYSCTL_RSTCTRL, 0, RT3883_PCI_RST); 1184297717Ssgalabov mtk_sysctl_clr_set(SYSCTL_CLKCFG1, RT3883_PCI_CLK, 0); 1185297717Ssgalabov 1186297717Ssgalabov /* Give things a chance to sink in */ 1187297717Ssgalabov DELAY(500000); 1188297717Ssgalabov 1189297717Ssgalabov /* Set PCIe port number to 0 and lift PCIe reset */ 1190297717Ssgalabov MT_WRITE32(sc, MTK_PCI_PCICFG, 0); 1191297717Ssgalabov 1192297717Ssgalabov /* Configure PCI Arbiter */ 1193297717Ssgalabov MT_WRITE32(sc, MTK_PCI_ARBCTL, 0x79); 1194297717Ssgalabov 1195297717Ssgalabov /* We have a single PCIe slot */ 1196297717Ssgalabov sc->num_slots = 1; 1197297717Ssgalabov 1198297717Ssgalabov return (0); 1199297717Ssgalabov} 1200297717Ssgalabov 1201297717Ssgalabovstatic void 1202297717Ssgalabovmtk_pcie_phy_setup_slots(device_t dev) 1203297717Ssgalabov{ 1204297717Ssgalabov struct mtk_pci_softc *sc = device_get_softc(dev); 1205297717Ssgalabov uint32_t bar0_val, val; 1206297717Ssgalabov int i; 1207297717Ssgalabov 1208297717Ssgalabov /* Disable all PCIe interrupts */ 1209297717Ssgalabov MT_WRITE32(sc, MTK_PCI_PCIENA, 0); 1210297717Ssgalabov 1211297717Ssgalabov /* Default bar0_val is 64M, enabled */ 1212297717Ssgalabov bar0_val = 0x03FF0001; 1213297717Ssgalabov 1214297717Ssgalabov /* But we override it to 2G, enabled for some SoCs */ 1215297717Ssgalabov if (sc->socid == MTK_SOC_MT7620A || sc->socid == MTK_SOC_MT7628 || 1216297717Ssgalabov sc->socid == MTK_SOC_MT7688 || sc->socid == MTK_SOC_MT7621) 1217297717Ssgalabov bar0_val = 0x7FFF0001; 1218297717Ssgalabov 1219297717Ssgalabov /* We still don't know which slots have linked up */ 1220297717Ssgalabov sc->pcie_link_status = 0; 1221297717Ssgalabov 1222297717Ssgalabov /* XXX: I am not sure if this delay is really necessary */ 1223297717Ssgalabov DELAY(500000); 1224297717Ssgalabov 1225297717Ssgalabov /* 1226297717Ssgalabov * See which slots have links and mark them. 1227297717Ssgalabov * Set up all slots' BARs and make them look like PCIe bridges. 1228297717Ssgalabov */ 1229297717Ssgalabov for (i = 0; i < sc->num_slots; i++) { 1230297717Ssgalabov /* If slot has link - mark it */ 1231297717Ssgalabov if (MT_READ32(sc, MTK_PCIE_STATUS(i)) & 1) 1232297717Ssgalabov sc->pcie_link_status |= (1<<i); 1233297850Ssgalabov else 1234297850Ssgalabov continue; 1235297717Ssgalabov 1236297717Ssgalabov /* Generic slot configuration follows */ 1237297717Ssgalabov 1238297717Ssgalabov /* We enable BAR0 */ 1239297717Ssgalabov MT_WRITE32(sc, MTK_PCIE_BAR0SETUP(i), bar0_val); 1240297717Ssgalabov /* and disable BAR1 */ 1241297717Ssgalabov MT_WRITE32(sc, MTK_PCIE_BAR1SETUP(i), 0); 1242297717Ssgalabov /* Internal memory base has no offset */ 1243297717Ssgalabov MT_WRITE32(sc, MTK_PCIE_IMBASEBAR0(i), 0); 1244297717Ssgalabov /* We're a PCIe bridge */ 1245297717Ssgalabov MT_WRITE32(sc, MTK_PCIE_CLASS(i), 0x06040001); 1246297717Ssgalabov 1247297717Ssgalabov val = mtk_pci_read_config(dev, 0, i, 0, 0x4, 4); 1248297717Ssgalabov mtk_pci_write_config(dev, 0, i, 0, 0x4, val | 0x4, 4); 1249297717Ssgalabov val = mtk_pci_read_config(dev, 0, i, 0, 0x70c, 4); 1250297717Ssgalabov val &= ~(0xff << 8); 1251297717Ssgalabov val |= (0x50 << 8); 1252297850Ssgalabov mtk_pci_write_config(dev, 0, i, 0, 0x70c, val, 4); 1253297850Ssgalabov 1254297850Ssgalabov mtk_pci_write_config(dev, 0, i, 0, PCIR_IOBASEL_1, 0xff, 1); 1255297850Ssgalabov mtk_pci_write_config(dev, 0, i, 0, PCIR_IOBASEH_1, 0xffff, 2); 1256297850Ssgalabov mtk_pci_write_config(dev, 0, i, 0, PCIR_IOLIMITL_1, 0, 1); 1257297850Ssgalabov mtk_pci_write_config(dev, 0, i, 0, PCIR_IOLIMITH_1, 0, 2); 1258297850Ssgalabov mtk_pci_write_config(dev, 0, i, 0, PCIR_MEMBASE_1, 0xffff, 2); 1259297850Ssgalabov mtk_pci_write_config(dev, 0, i, 0, PCIR_MEMLIMIT_1, 0, 2); 1260297850Ssgalabov mtk_pci_write_config(dev, 0, i, 0, PCIR_PMBASEL_1, 0xffff, 2); 1261297850Ssgalabov mtk_pci_write_config(dev, 0, i, 0, PCIR_PMBASEH_1, 0xffffffff, 1262297850Ssgalabov 4); 1263297850Ssgalabov mtk_pci_write_config(dev, 0, i, 0, PCIR_PMLIMITL_1, 0, 2); 1264297850Ssgalabov mtk_pci_write_config(dev, 0, i, 0, PCIR_PMLIMITH_1, 0, 4); 1265297717Ssgalabov } 1266297717Ssgalabov} 1267