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