mtk_pcie.c revision 297717
1132734Skan/*- 272566Sobrien * Copyright (c) 2016 Stanislav Galabov. 3169699Skan * 4169699Skan * Redistribution and use in source and binary forms, with or without 518334Speter * modification, are permitted provided that the following conditions 690282Sobrien * are met: 718334Speter * 1. Redistributions of source code must retain the above copyright 890282Sobrien * notice, this list of conditions and the following disclaimer. 990282Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1090282Sobrien * notice, this list of conditions and the following disclaimer in the 1190282Sobrien * documentation and/or other materials provided with the distribution. 1218334Speter * 1390282Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1490282Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1590282Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1690282Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1718334Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1818334Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1990282Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20169699Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21169699Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2218334Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2352558Sobrien * SUCH DAMAGE. 2452558Sobrien * 2518334Speter * The pci allocator parts are based on code from sys/dev/arm/mv/: 2618334Speter * 2718334Speter * Copyright (c) 2008 MARVELL INTERNATIONAL LTD. 2818334Speter * Copyright (c) 2010 The FreeBSD Foundation 2918334Speter * Copyright (c) 2010-2012 Semihalf 3018334Speter * All rights reserved. 3150615Sobrien * 3250615Sobrien * Developed by Semihalf. 3350615Sobrien */ 34132734Skan#include <sys/cdefs.h> 35132734Skan__FBSDID("$FreeBSD: head/sys/mips/mediatek/mtk_pcie.c 297717 2016-04-08 15:26:49Z sgalabov $"); 3618334Speter 3718334Speter#include <sys/param.h> 3850615Sobrien#include <sys/systm.h> 3950615Sobrien 4018334Speter#include <sys/bus.h> 4150615Sobrien#include <sys/interrupt.h> 4250615Sobrien#include <sys/malloc.h> 4350615Sobrien#include <sys/kernel.h> 4418334Speter#include <sys/module.h> 4518334Speter#include <sys/rman.h> 46169699Skan#include <sys/lock.h> 4718334Speter#include <sys/mutex.h> 4818334Speter#include <sys/endian.h> 49169699Skan 5018334Speter#include <vm/vm.h> 5190282Sobrien#include <vm/pmap.h> 5218334Speter#include <vm/vm_extern.h> 5318334Speter 5450615Sobrien#include <machine/bus.h> 5590282Sobrien#include <machine/cpu.h> 5690282Sobrien#include <machine/intr.h> 5750615Sobrien#include <machine/pmap.h> 5818334Speter 5950615Sobrien#include <dev/pci/pcivar.h> 6090282Sobrien#include <dev/pci/pcireg.h> 6150615Sobrien 6252558Sobrien#include <dev/pci/pcib_private.h> 6352558Sobrien 6452558Sobrien#include <dev/fdt/fdt_common.h> 6590282Sobrien#include <dev/fdt/fdt_clock.h> 6690282Sobrien#include <dev/ofw/openfirm.h> 6790282Sobrien#include <dev/ofw/ofw_bus.h> 6890282Sobrien#include <dev/ofw/ofw_bus_subr.h> 6990282Sobrien 7090282Sobrien#include <mips/mediatek/mtk_pcie.h> 7190282Sobrien#include <mips/mediatek/mtk_soc.h> 7290282Sobrien#include <mips/mediatek/mtk_sysctl.h> 7390282Sobrien#include <mips/mediatek/fdt_reset.h> 74117414Skan 7590282Sobrien#include "pcib_if.h" 7690282Sobrien#include "pic_if.h" 7790282Sobrien 78117414Skan/* 79132734Skan * Note: We only support PCIe at the moment. 80132734Skan * Most SoCs in the Ralink/Mediatek family that we target actually don't 81132734Skan * support PCI anyway, with the notable exceptions being RT3662/RT3883, which 82132734Skan * support both PCI and PCIe. If there exists a board based on one of them 83132734Skan * which is of interest in the future it shouldn't be too hard to enable PCI 84132734Skan * support for it. 85132734Skan */ 86169699Skan 8718334Speter/* Chip specific function declarations */ 8850615Sobrienstatic int mtk_pcie_phy_init(device_t); 8950615Sobrienstatic int mtk_pcie_phy_start(device_t); 9050615Sobrienstatic int mtk_pcie_phy_stop(device_t); 9150615Sobrienstatic int mtk_pcie_phy_mt7621_init(device_t); 9250615Sobrienstatic int mtk_pcie_phy_mt7628_init(device_t); 9350615Sobrienstatic int mtk_pcie_phy_mt7620_init(device_t); 9450615Sobrienstatic int mtk_pcie_phy_rt3883_init(device_t); 9550615Sobrienstatic void mtk_pcie_phy_setup_slots(device_t); 9650615Sobrien 9750615Sobrien/* Generic declarations */ 9850615Sobrienstruct mtx mtk_pci_mtx; 9950615SobrienMTX_SYSINIT(mtk_pci_mtx, &mtk_pci_mtx, "MTK PCIe mutex", MTX_SPIN); 10018334Speter 10190282Sobrienstatic int mtk_pcib_init(device_t, int, int); 10290282Sobrienstatic int mtk_pci_intr(void *); 10318334Speter 104132734Skanstatic struct mtk_pci_softc *mt_sc = NULL; 105132734Skan 106132734Skanstruct mtk_pci_range { 107132734Skan u_long base; 108132734Skan u_long len; 109132734Skan}; 110132734Skan 111132734Skan#define FDT_RANGES_CELLS (3 * 2) 11218334Speter 113132734Skanstatic void 114132734Skanmtk_pci_range_dump(struct mtk_pci_range *range) 115132734Skan{ 11650615Sobrien#ifdef DEBUG 117132734Skan printf("\n"); 118132734Skan printf(" base = 0x%08lx\n", range->base); 119132734Skan printf(" len = 0x%08lx\n", range->len); 120132734Skan#endif 121132734Skan} 12218334Speter 123117414Skanstatic int 124117414Skanmtk_pci_ranges_decode(phandle_t node, struct mtk_pci_range *io_space, 125117414Skan struct mtk_pci_range *mem_space) 126132734Skan{ 127132734Skan struct mtk_pci_range *pci_space; 128132734Skan pcell_t ranges[FDT_RANGES_CELLS]; 12950615Sobrien pcell_t *rangesptr; 13050615Sobrien pcell_t cell0, cell1, cell2; 13118334Speter int tuples, i, rv, len; 13218334Speter 13318334Speter /* 13490282Sobrien * Retrieve 'ranges' property. 13518334Speter */ 136132734Skan if (!OF_hasprop(node, "ranges")) { 137132734Skan printf("%s: %d\n", __FUNCTION__, 1); 13818334Speter return (EINVAL); 13918334Speter } 14018334Speter 14118334Speter len = OF_getproplen(node, "ranges"); 14218334Speter if (len > sizeof(ranges)) { 14390282Sobrien printf("%s: %d\n", __FUNCTION__, 2); 14418334Speter return (ENOMEM); 145169699Skan } 146169699Skan 147169699Skan if (OF_getprop(node, "ranges", ranges, sizeof(ranges)) <= 0) { 148169699Skan printf("%s: %d\n", __FUNCTION__, 3); 149169699Skan return (EINVAL); 150169699Skan } 151169699Skan 152169699Skan tuples = len / (sizeof(pcell_t) * 3); 153132734Skan 15418334Speter /* 155132734Skan * Initialize the ranges so that we don't have to worry about 15618334Speter * having them all defined in the FDT. In particular, it is 157169699Skan * perfectly fine not to want I/O space on PCI busses. 158169699Skan */ 15952558Sobrien bzero(io_space, sizeof(*io_space)); 16052558Sobrien bzero(mem_space, sizeof(*mem_space)); 16152558Sobrien 16218334Speter rangesptr = &ranges[0]; 16318334Speter for (i = 0; i < tuples; i++) { 16418334Speter cell0 = fdt_data_get((void *)rangesptr, 1); 16518334Speter rangesptr++; 16618334Speter cell1 = fdt_data_get((void *)rangesptr, 1); 16718334Speter rangesptr++; 16818334Speter cell2 = fdt_data_get((void *)rangesptr, 1); 169169699Skan rangesptr++; 170169699Skan 171169699Skan if (cell0 == 2) { 172169699Skan pci_space = mem_space; 173169699Skan } else if (cell0 == 1) { 174169699Skan pci_space = io_space; 175169699Skan } else { 176169699Skan rv = ERANGE; 177169699Skan printf("%s: %d\n", __FUNCTION__, 4); 178169699Skan goto out; 17918334Speter } 18018334Speter 18152558Sobrien pci_space->base = cell1; 18218334Speter pci_space->len = cell2; 183117414Skan } 184117414Skan 185117414Skan rv = 0; 186117414Skanout: 18718334Speter return (rv); 18818334Speter} 18918334Speter 19018334Speterstatic int 19118334Spetermtk_pci_ranges(phandle_t node, struct mtk_pci_range *io_space, 19218334Speter struct mtk_pci_range *mem_space) 193117414Skan{ 194117414Skan int err; 195117414Skan 196117414Skan if ((err = mtk_pci_ranges_decode(node, io_space, mem_space)) != 0) { 197117414Skan return (err); 19890282Sobrien } 19918334Speter 200132734Skan mtk_pci_range_dump(io_space); 20190282Sobrien mtk_pci_range_dump(mem_space); 202169699Skan 20390282Sobrien return (0); 204169699Skan} 20590282Sobrien 20690282Sobrienstatic struct ofw_compat_data compat_data[] = { 20790282Sobrien { "ralink,rt3662-pcie", MTK_SOC_RT3883 }, 20890282Sobrien { "ralink,rt3883-pcie", MTK_SOC_RT3883 }, 20990282Sobrien { "ralink,mt7620a-pcie", MTK_SOC_MT7620A }, 21052558Sobrien { "ralink,mt7621-pcie", MTK_SOC_MT7621 }, 21118334Speter { "ralink,mt7628-pcie", MTK_SOC_MT7628 }, 21218334Speter { "ralink,mt7688-pcie", MTK_SOC_MT7628 }, 21318334Speter { NULL, MTK_SOC_UNKNOWN } 214132734Skan}; 21518334Speter 21618334Speterstatic int 21718334Spetermtk_pci_probe(device_t dev) 21818334Speter{ 21918334Speter struct mtk_pci_softc *sc = device_get_softc(dev); 22018334Speter 22118334Speter if (!ofw_bus_status_okay(dev)) 22218334Speter return (ENXIO); 22318334Speter 22418334Speter sc->socid = ofw_bus_search_compatible(dev, compat_data)->ocd_data; 22550615Sobrien if (sc->socid == MTK_SOC_UNKNOWN) 226117414Skan return (ENXIO); 227117414Skan 22850615Sobrien device_set_desc(dev, "MTK PCIe Controller"); 22950615Sobrien 23050615Sobrien return (0); 23150615Sobrien} 23290282Sobrien 23390282Sobrienstatic int 23490282Sobrienmtk_pci_attach(device_t dev) 23518334Speter{ 236169699Skan struct mtk_pci_softc *sc = device_get_softc(dev); 23790282Sobrien struct mtk_pci_range io_space, mem_space; 238169699Skan phandle_t node; 23990282Sobrien intptr_t xref; 24018334Speter int i, rid; 24118334Speter 24218334Speter sc->sc_dev = dev; 24318334Speter mt_sc = sc; 24418334Speter sc->addr_mask = 0xffffffff; 245132734Skan 24690282Sobrien /* Request our memory */ 24790282Sobrien rid = 0; 24890282Sobrien sc->pci_res[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 249132734Skan RF_ACTIVE); 250132734Skan if (sc->pci_res[0] == NULL) { 251132734Skan device_printf(dev, "could not allocate memory resource\n"); 252132734Skan return (ENXIO); 253132734Skan } 254132734Skan 255132734Skan /* See how many interrupts we need */ 256132734Skan if (sc->socid == MTK_SOC_MT7621) 25718334Speter sc->sc_num_irq = 3; 25818334Speter else { 25918334Speter sc->sc_num_irq = 1; 26018334Speter sc->pci_res[2] = sc->pci_res[3] = NULL; 26118334Speter sc->pci_intrhand[1] = sc->pci_intrhand[2] = NULL; 26218334Speter } 263169699Skan 264169699Skan /* Request our interrupts */ 26518334Speter for (i = 1; i <= sc->sc_num_irq ; i++) { 26618334Speter rid = i - 1; 26718334Speter sc->pci_res[i] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 26818334Speter RF_ACTIVE); 26918334Speter if (sc->pci_res[i] == NULL) { 27018334Speter device_printf(dev, "could not allocate interrupt " 27118334Speter "resource %d\n", rid); 27218334Speter goto cleanup_res; 27318334Speter } 27418334Speter } 27518334Speter 27618334Speter /* Parse our PCI 'ranges' property */ 27718334Speter node = ofw_bus_get_node(dev); 27818334Speter xref = OF_xref_from_node(node); 27918334Speter if (mtk_pci_ranges(node, &io_space, &mem_space)) { 28018334Speter device_printf(dev, "could not retrieve 'ranges' data\n"); 28152558Sobrien goto cleanup_res; 28252558Sobrien } 283169699Skan 28452558Sobrien /* Memory, I/O and IRQ resource limits */ 285169699Skan sc->sc_io_base = io_space.base; 28652558Sobrien sc->sc_io_size = io_space.len; 28796289Sobrien sc->sc_mem_base = mem_space.base; 28896289Sobrien sc->sc_mem_size = mem_space.len; 28996289Sobrien sc->sc_irq_start = MTK_PCIE0_IRQ; 29096289Sobrien sc->sc_irq_end = MTK_PCIE2_IRQ; 29196289Sobrien 29218334Speter /* Init resource managers for memory, I/O and IRQ */ 29318334Speter sc->sc_mem_rman.rm_type = RMAN_ARRAY; 29418334Speter sc->sc_mem_rman.rm_descr = "mtk pcie memory window"; 29518334Speter if (rman_init(&sc->sc_mem_rman) != 0 || 29618334Speter rman_manage_region(&sc->sc_mem_rman, sc->sc_mem_base, 29718334Speter sc->sc_mem_base + sc->sc_mem_size - 1) != 0) { 298132734Skan device_printf(dev, "failed to setup memory rman\n"); 29918334Speter goto cleanup_res; 300132734Skan } 301132734Skan 302132734Skan sc->sc_io_rman.rm_type = RMAN_ARRAY; 303132734Skan sc->sc_io_rman.rm_descr = "mtk pcie io window"; 304132734Skan if (rman_init(&sc->sc_io_rman) != 0 || 305169699Skan rman_manage_region(&sc->sc_io_rman, sc->sc_io_base, 306169699Skan sc->sc_io_base + sc->sc_io_size - 1) != 0) { 307169699Skan device_printf(dev, "failed to setup io rman\n"); 308169699Skan goto cleanup_res; 309169699Skan } 310169699Skan 311169699Skan sc->sc_irq_rman.rm_type = RMAN_ARRAY; 312169699Skan sc->sc_irq_rman.rm_descr = "mtk pcie irqs"; 313117414Skan if (rman_init(&sc->sc_irq_rman) != 0 || 314117414Skan rman_manage_region(&sc->sc_irq_rman, sc->sc_irq_start, 315117414Skan sc->sc_irq_end) != 0) { 316117414Skan device_printf(dev, "failed to setup irq rman\n"); 31718334Speter goto cleanup_res; 31818334Speter } 31918334Speter 32018334Speter /* Do SoC-specific PCIe initialization */ 32118334Speter if (mtk_pcie_phy_init(dev)) { 32250615Sobrien device_printf(dev, "pcie phy init failed\n"); 32350615Sobrien goto cleanup_rman; 32450615Sobrien } 32550615Sobrien 32650615Sobrien /* Register ourselves as an interrupt controller */ 32750615Sobrien if (intr_pic_register(dev, xref) != 0) { 32850615Sobrien device_printf(dev, "could not register PIC\n"); 32950615Sobrien goto cleanup_rman; 33050615Sobrien } 33190282Sobrien 33290282Sobrien /* Set up our interrupt handler */ 33390282Sobrien for (i = 1; i <= sc->sc_num_irq; i++) { 33490282Sobrien sc->pci_intrhand[i - 1] = NULL; 33590282Sobrien if (bus_setup_intr(dev, sc->pci_res[i], INTR_TYPE_MISC, 33690282Sobrien mtk_pci_intr, NULL, sc, &sc->pci_intrhand[i - 1])) { 33790282Sobrien device_printf(dev, "could not setup intr handler %d\n", 33890282Sobrien i); 33990282Sobrien goto cleanup; 34090282Sobrien } 34190282Sobrien } 34290282Sobrien 34350615Sobrien /* Do generic PCIe initialization and resource allocation */ 34490282Sobrien mtk_pcib_init(dev, 0, PCI_SLOTMAX); 34590282Sobrien 34690282Sobrien /* Attach our PCI child so bus enumeration can start */ 34790282Sobrien if (device_add_child(dev, "pci", -1) == NULL) { 34890282Sobrien device_printf(dev, "could not attach pci bus\n"); 349169699Skan goto cleanup; 350169699Skan } 351169699Skan 352169699Skan /* And finally, attach ourselves to the bus */ 353117414Skan if (bus_generic_attach(dev)) { 354169699Skan device_printf(dev, "could not attach to bus\n"); 355169699Skan goto cleanup; 356117414Skan } 357169699Skan 358117414Skan return (0); 35990282Sobrien 36090282Sobriencleanup: 36190282Sobrien#ifdef notyet 36290282Sobrien intr_pic_unregister(dev, xref); 36390282Sobrien#endif 36490282Sobrien for (i = 1; i <= sc->sc_num_irq; i++) { 36590282Sobrien if (sc->pci_intrhand[i - 1] != NULL) 36690282Sobrien bus_teardown_intr(dev, sc->pci_res[i], 36790282Sobrien sc->pci_intrhand[i - 1]); 36890282Sobrien } 36990282Sobriencleanup_rman: 37090282Sobrien mtk_pcie_phy_stop(dev); 37190282Sobrien rman_fini(&sc->sc_irq_rman); 37250615Sobrien rman_fini(&sc->sc_io_rman); 37350615Sobrien rman_fini(&sc->sc_mem_rman); 37490282Sobriencleanup_res: 37590282Sobrien mt_sc = NULL; 37690282Sobrien if (sc->pci_res[0] != NULL) 37750615Sobrien bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->pci_res[0]); 37850615Sobrien if (sc->pci_res[1] != NULL) 37950615Sobrien bus_release_resource(dev, SYS_RES_IRQ, 0, sc->pci_res[1]); 380132734Skan if (sc->pci_res[2] != NULL) 381132734Skan bus_release_resource(dev, SYS_RES_IRQ, 1, sc->pci_res[2]); 382132734Skan if (sc->pci_res[3] != NULL) 38352558Sobrien bus_release_resource(dev, SYS_RES_IRQ, 2, sc->pci_res[3]); 38452558Sobrien return (ENXIO); 38552558Sobrien} 38690282Sobrien 387169699Skanstatic int 388169699Skanmtk_pci_read_ivar(device_t dev, device_t child, int which, 38990282Sobrien uintptr_t *result) 39090282Sobrien{ 391169699Skan struct mtk_pci_softc *sc = device_get_softc(dev); 39290282Sobrien 39390282Sobrien switch (which) { 394132734Skan case PCIB_IVAR_DOMAIN: 395132734Skan *result = device_get_unit(dev); 39618334Speter return (0); 397132734Skan case PCIB_IVAR_BUS: 398132734Skan *result = sc->sc_busno; 399169699Skan return (0); 400169699Skan } 40118334Speter 402132734Skan return (ENOENT); 403132734Skan} 404132734Skan 405132734Skanstatic int 40690282Sobrienmtk_pci_write_ivar(device_t dev, device_t child, int which, 407132734Skan uintptr_t result) 40818334Speter{ 409132734Skan struct mtk_pci_softc *sc = device_get_softc(dev); 410132734Skan 411132734Skan switch (which) { 412132734Skan case PCIB_IVAR_BUS: 41318334Speter sc->sc_busno = result; 414132734Skan return (0); 415132734Skan } 416132734Skan 417132734Skan return (ENOENT); 418169699Skan} 419169699Skan 420169699Skanstatic struct resource * 421169699Skanmtk_pci_alloc_resource(device_t bus, device_t child, int type, int *rid, 422169699Skan rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) 423169699Skan{ 42418334Speter struct mtk_pci_softc *sc = device_get_softc(bus); 425132734Skan struct resource *rv; 426132734Skan struct rman *rm; 427132734Skan 42818334Speter switch (type) { 429132734Skan case SYS_RES_IRQ: 430132734Skan rm = &sc->sc_irq_rman; 431132734Skan break; 43218334Speter case SYS_RES_IOPORT: 433132734Skan rm = &sc->sc_io_rman; 434132734Skan break; 435132734Skan case SYS_RES_MEMORY: 436132734Skan rm = &sc->sc_mem_rman; 437169699Skan break; 438169699Skan default: 439169699Skan return (NULL); 440169699Skan } 441169699Skan 44290282Sobrien rv = rman_reserve_resource(rm, start, end, count, flags, child); 443132734Skan 444132734Skan if (rv == NULL) 44590282Sobrien return (NULL); 446132734Skan 447132734Skan rman_set_rid(rv, *rid); 44890282Sobrien 449132734Skan if ((flags & RF_ACTIVE) && type != SYS_RES_IRQ) { 45090282Sobrien if (bus_activate_resource(child, type, *rid, rv)) { 451132734Skan rman_release_resource(rv); 452132734Skan return (NULL); 453132734Skan } 454169699Skan } 455132734Skan 456169699Skan return (rv); 457132734Skan} 458132734Skan 459132734Skanstatic inline int 460132734Skanmtk_idx_to_irq(int idx) 46190282Sobrien{ 46290282Sobrien 463132734Skan return ((idx == 0) ? MTK_PCIE0_IRQ : 464132734Skan (idx == 1) ? MTK_PCIE1_IRQ : 46590282Sobrien (idx == 2) ? MTK_PCIE2_IRQ : -1); 466132734Skan} 467132734Skan 46890282Sobrienstatic inline int 469132734Skanmtk_irq_to_idx(int irq) 470132734Skan{ 471132734Skan 472132734Skan return ((irq == MTK_PCIE0_IRQ) ? 0 : 47390282Sobrien (irq == MTK_PCIE1_IRQ) ? 1 : 474132734Skan (irq == MTK_PCIE2_IRQ) ? 2 : -1); 475132734Skan} 476132734Skan 477132734Skanstatic void 478132734Skanmtk_pci_mask_irq(void *source) 479132734Skan{ 480132734Skan MT_WRITE32(mt_sc, MTK_PCI_PCIENA, 481132734Skan MT_READ32(mt_sc, MTK_PCI_PCIENA) & ~(1<<((int)source))); 482132734Skan} 483132734Skan 484132734Skanstatic void 485132734Skanmtk_pci_unmask_irq(void *source) 486132734Skan{ 487132734Skan 488132734Skan MT_WRITE32(mt_sc, MTK_PCI_PCIENA, 489132734Skan MT_READ32(mt_sc, MTK_PCI_PCIENA) | (1<<((int)source))); 490132734Skan} 491132734Skan 492132734Skanstatic int 493132734Skanmtk_pci_setup_intr(device_t bus, device_t child, struct resource *ires, 494132734Skan int flags, driver_filter_t *filt, driver_intr_t *handler, 495132734Skan void *arg, void **cookiep) 496132734Skan{ 49790282Sobrien struct mtk_pci_softc *sc = device_get_softc(bus); 49890282Sobrien struct intr_event *event; 49918334Speter int irq, error, irqidx; 50052558Sobrien 50152558Sobrien irq = rman_get_start(ires); 50252558Sobrien 50390282Sobrien if (irq < sc->sc_irq_start || irq > sc->sc_irq_end) 50490282Sobrien return (EINVAL); 50552558Sobrien 506132734Skan irqidx = irq - sc->sc_irq_start; 50752558Sobrien 50852558Sobrien event = sc->sc_eventstab[irqidx]; 50952558Sobrien if (event == NULL) { 51052558Sobrien error = intr_event_create(&event, (void *)irq, 0, irq, 51152558Sobrien mtk_pci_mask_irq, mtk_pci_unmask_irq, NULL, NULL, 51290282Sobrien "pci intr%d:", irq); 51352558Sobrien 51452558Sobrien if (error == 0) { 51552558Sobrien sc->sc_eventstab[irqidx] = event; 51652558Sobrien } 51752558Sobrien else { 51852558Sobrien return (error); 51952558Sobrien } 52052558Sobrien } 521169699Skan 52252558Sobrien intr_event_add_handler(event, device_get_nameunit(child), filt, 52352558Sobrien handler, arg, intr_priority(flags), flags, cookiep); 52452558Sobrien 52552558Sobrien mtk_pci_unmask_irq((void*)irq); 52652558Sobrien 52718334Speter return (0); 528169699Skan} 529169699Skan 530169699Skanstatic int 53118334Spetermtk_pci_teardown_intr(device_t dev, device_t child, struct resource *ires, 532169699Skan void *cookie) 53318334Speter{ 534169699Skan struct mtk_pci_softc *sc = device_get_softc(dev); 535169699Skan int irq, result, irqidx; 536169699Skan 53718334Speter irq = rman_get_start(ires); 538169699Skan if (irq < sc->sc_irq_start || irq > sc->sc_irq_end) 53918334Speter return (EINVAL); 540169699Skan 541169699Skan irqidx = irq - sc->sc_irq_start; 542169699Skan if (sc->sc_eventstab[irqidx] == NULL) 54318334Speter panic("Trying to teardown unoccupied IRQ"); 544169699Skan 545169699Skan mtk_pci_mask_irq((void*)irq); 546169699Skan 547169699Skan result = intr_event_remove_handler(cookie); 548169699Skan if (!result) 549169699Skan sc->sc_eventstab[irqidx] = NULL; 550169699Skan 551169699Skan 552169699Skan return (result); 553169699Skan} 554169699Skan 555169699Skanstatic inline uint32_t 556169699Skanmtk_pci_make_addr(int bus, int slot, int func, int reg) 557169699Skan{ 558169699Skan uint32_t addr; 559169699Skan 560169699Skan addr = ((((reg & 0xf00) >> 8) << 24) | (bus << 16) | (slot << 11) | 561169699Skan (func << 8) | (reg & 0xfc) | (1 << 31)); 562169699Skan 563169699Skan return (addr); 564169699Skan} 565169699Skan 566169699Skanstatic int 56718334Spetermtk_pci_maxslots(device_t dev) 56818334Speter{ 569169699Skan 570169699Skan return (PCI_SLOTMAX); 57118334Speter} 57218334Speter 573169699Skanstatic inline int 57418334Spetermtk_pci_slot_has_link(device_t dev, int slot) 575169699Skan{ 576169699Skan struct mtk_pci_softc *sc = device_get_softc(dev); 577169699Skan 578169699Skan return !!(sc->pcie_link_status & (1<<slot)); 579169699Skan} 580169699Skan 581169699Skanstatic uint32_t 58218334Spetermtk_pci_read_config(device_t dev, u_int bus, u_int slot, u_int func, 58318334Speter u_int reg, int bytes) 584169699Skan{ 585169699Skan struct mtk_pci_softc *sc = device_get_softc(dev); 58690282Sobrien uint32_t addr = 0, data = 0; 587132734Skan 588132734Skan /* Return ~0U if slot has no link */ 58918334Speter if (bus == 0 && mtk_pci_slot_has_link(dev, slot) == 0) { 59018334Speter return (~0U); 591132734Skan } 59218334Speter 593132734Skan mtx_lock_spin(&mtk_pci_mtx); 594169699Skan addr = mtk_pci_make_addr(bus, slot, func, (reg & ~3)) & sc->addr_mask; 595169699Skan MT_WRITE32(sc, MTK_PCI_CFGADDR, addr); 596169699Skan switch (bytes % 4) { 597169699Skan case 0: 598169699Skan data = MT_READ32(sc, MTK_PCI_CFGDATA); 599169699Skan break; 600169699Skan case 1: 601169699Skan data = MT_READ8(sc, MTK_PCI_CFGDATA + (reg & 0x3)); 602169699Skan break; 603117414Skan case 2: 60418334Speter data = MT_READ16(sc, MTK_PCI_CFGDATA + (reg & 0x3)); 60518334Speter break; 606132734Skan default: 607132734Skan panic("%s(): Wrong number of bytes (%d) requested!\n", 608132734Skan __FUNCTION__, bytes % 4); 609132734Skan } 610132734Skan mtx_unlock_spin(&mtk_pci_mtx); 611132734Skan 612132734Skan return (data); 613132734Skan} 614132734Skan 615132734Skanstatic void 616132734Skanmtk_pci_write_config(device_t dev, u_int bus, u_int slot, u_int func, 617132734Skan u_int reg, uint32_t val, int bytes) 618132734Skan{ 619132734Skan struct mtk_pci_softc *sc = device_get_softc(dev); 620132734Skan uint32_t addr = 0, data = val; 621132734Skan 622132734Skan /* Do not write if slot has no link */ 623132734Skan if (bus == 0 && mtk_pci_slot_has_link(dev, slot) == 0) 624132734Skan return; 625132734Skan 626132734Skan mtx_lock_spin(&mtk_pci_mtx); 627132734Skan addr = mtk_pci_make_addr(bus, slot, func, (reg & ~3)) & sc->addr_mask; 628132734Skan MT_WRITE32(sc, MTK_PCI_CFGADDR, addr); 62918334Speter switch (bytes % 4) { 63018334Speter case 0: 63150615Sobrien MT_WRITE32(sc, MTK_PCI_CFGDATA, data); 63290282Sobrien break; 63318334Speter case 1: 63418334Speter MT_WRITE8(sc, MTK_PCI_CFGDATA + (reg & 0x3), data); 635132734Skan break; 63618334Speter case 2: 63750615Sobrien MT_WRITE16(sc, MTK_PCI_CFGDATA + (reg & 0x3), data); 638117414Skan break; 63950615Sobrien default: 64050615Sobrien panic("%s(): Wrong number of bytes (%d) requested!\n", 64150615Sobrien __FUNCTION__, bytes % 4); 64250615Sobrien } 64350615Sobrien mtx_unlock_spin(&mtk_pci_mtx); 64450615Sobrien} 64550615Sobrien 64618334Speter#if 0 64718334Speter/* We take care of interrupt routing in the allocator code below */ 64818334Speterstatic int 64950615Sobrienmtk_pci_route_interrupt(device_t pcib, device_t device, int pin) 65018334Speter{ 651132734Skan //struct mtk_pci_softc *sc = device_get_softc(pcib); 65218334Speter int bus, sl, dev; 65350615Sobrien 65450615Sobrien if (1) return PCI_INVALID_IRQ; 65550615Sobrien 65618334Speter bus = pci_get_bus(device); 65718334Speter sl = pci_get_slot(device); 65818334Speter dev = pci_get_device(device); 65918334Speter 66018334Speter printf("%s: for %d:%d:%d, int = %d\n", __FUNCTION__, bus, sl, dev, pin); 66196289Sobrien 66296289Sobrien if (bus != 0) 66396289Sobrien panic("Unexpected bus number %d\n", bus); 66496289Sobrien 66596289Sobrien /* PCIe only */ 66696289Sobrien switch (sl) { 66796289Sobrien case 0: return MTK_PCIE0_IRQ; 668117414Skan case 1: return MTK_PCIE0_IRQ + 1; 66918334Speter case 2: return MTK_PCIE0_IRQ + 2; 67018334Speter default: return (-1); 67150615Sobrien } 67218334Speter 67318334Speter return (-1); 674132734Skan} 675132734Skan#endif 676117414Skan 677132734Skanstatic device_method_t mtk_pci_methods[] = { 678117414Skan /* Device interface */ 679132734Skan DEVMETHOD(device_probe, mtk_pci_probe), 680132734Skan DEVMETHOD(device_attach, mtk_pci_attach), 681117414Skan DEVMETHOD(device_shutdown, bus_generic_shutdown), 682132734Skan DEVMETHOD(device_suspend, bus_generic_suspend), 683132734Skan DEVMETHOD(device_resume, bus_generic_resume), 684117414Skan 685132734Skan /* Bus interface */ 686132734Skan DEVMETHOD(bus_read_ivar, mtk_pci_read_ivar), 687117414Skan DEVMETHOD(bus_write_ivar, mtk_pci_write_ivar), 68818334Speter DEVMETHOD(bus_alloc_resource, mtk_pci_alloc_resource), 68918334Speter DEVMETHOD(bus_release_resource, bus_generic_release_resource), 69018334Speter DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 69190282Sobrien DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 692117414Skan DEVMETHOD(bus_setup_intr, mtk_pci_setup_intr), 69318334Speter DEVMETHOD(bus_teardown_intr, mtk_pci_teardown_intr), 69418334Speter 69518334Speter /* pcib interface */ 69618334Speter DEVMETHOD(pcib_maxslots, mtk_pci_maxslots), 69718334Speter DEVMETHOD(pcib_read_config, mtk_pci_read_config), 69818334Speter DEVMETHOD(pcib_write_config, mtk_pci_write_config), 69918334Speter#if 0 70018334Speter DEVMETHOD(pcib_route_interrupt, mtk_pci_route_interrupt), 70118334Speter#endif 70218334Speter 70318334Speter DEVMETHOD_END 704132734Skan}; 705169699Skan 706169699Skanstatic driver_t mtk_pci_driver = { 707169699Skan "pcib", 70818334Speter mtk_pci_methods, 709169699Skan sizeof(struct mtk_pci_softc), 710169699Skan}; 71118334Speter 712169699Skanstatic devclass_t mtk_pci_devclass; 713169699Skan 714169699SkanDRIVER_MODULE(mtk_pci, simplebus, mtk_pci_driver, mtk_pci_devclass, 0, 0); 715169699Skan 716169699Skan/* Resource allocation code */ 71718334Speterstatic inline uint32_t 718169699Skanpcib_bit_get(uint32_t *map, uint32_t bit) 719169699Skan{ 720169699Skan uint32_t n = bit / BITS_PER_UINT32; 72150615Sobrien 722169699Skan bit = bit % BITS_PER_UINT32; 723169699Skan return (map[n] & (1 << bit)); 72450615Sobrien} 725169699Skan 726169699Skanstatic inline void 727169699Skanpcib_bit_set(uint32_t *map, uint32_t bit) 728169699Skan{ 729169699Skan uint32_t n = bit / BITS_PER_UINT32; 73050615Sobrien 731169699Skan bit = bit % BITS_PER_UINT32; 73250615Sobrien map[n] |= (1 << bit); 733169699Skan} 734169699Skan 735169699Skanstatic inline uint32_t 736169699Skanpcib_map_check(uint32_t *map, uint32_t start, uint32_t bits) 73750615Sobrien{ 738169699Skan uint32_t i; 739169699Skan 740169699Skan for (i = start; i < start + bits; i++) 741169699Skan if (pcib_bit_get(map, i)) 742169699Skan return (0); 743169699Skan 744169699Skan return (1); 745169699Skan} 74690282Sobrien 747169699Skanstatic inline void 748169699Skanpcib_map_set(uint32_t *map, uint32_t start, uint32_t bits) 749169699Skan{ 750169699Skan uint32_t i; 75190282Sobrien 752169699Skan for (i = start; i < start + bits; i++) 753169699Skan pcib_bit_set(map, i); 754169699Skan} 75590282Sobrien 756169699Skanstatic bus_addr_t 757169699Skanpcib_alloc(device_t dev, uint32_t smask) 758169699Skan{ 759169699Skan struct mtk_pci_softc *sc = device_get_softc(dev); 760169699Skan uint32_t bits, bits_limit, i, *map, min_alloc, size; 76150615Sobrien bus_addr_t addr = 0; 762169699Skan bus_addr_t base; 763169699Skan 764169699Skan if (smask & 1) { 765169699Skan base = sc->sc_io_base; 766169699Skan min_alloc = PCI_MIN_IO_ALLOC; 767169699Skan bits_limit = sc->sc_io_size / min_alloc; 768169699Skan map = sc->sc_io_map; 769169699Skan smask &= ~0x3; 770169699Skan } else { 771169699Skan base = sc->sc_mem_base; 772169699Skan min_alloc = PCI_MIN_MEM_ALLOC; 773169699Skan bits_limit = sc->sc_mem_size / min_alloc; 774169699Skan map = sc->sc_mem_map; 775169699Skan smask &= ~0xF; 776169699Skan } 777169699Skan 77890282Sobrien size = ~smask + 1; 779169699Skan bits = size / min_alloc; 780169699Skan 781169699Skan for (i = 0; i + bits <= bits_limit; i+= bits) 782169699Skan if (pcib_map_check(map, i, bits)) { 783169699Skan pcib_map_set(map, i, bits); 78490282Sobrien addr = base + (i * min_alloc); 78550615Sobrien return (addr); 786169699Skan } 78718334Speter 78818334Speter return (addr); 78952558Sobrien} 79052558Sobrien 79152558Sobrienstatic int 792117414Skanmtk_pcib_init_bar(device_t dev, int bus, int slot, int func, int barno) 79390282Sobrien{ 794169699Skan uint32_t addr, bar; 795132734Skan int reg, width; 79652558Sobrien 797169699Skan reg = PCIR_BAR(barno); 79852558Sobrien 79950615Sobrien mtk_pci_write_config(dev, bus, slot, func, reg, ~0, 4); 80052558Sobrien bar = mtk_pci_read_config(dev, bus, slot, func, reg, 4); 801169699Skan if (bar == 0) 80290282Sobrien return (1); 80352558Sobrien 80452558Sobrien /* Calculate BAR size: 64 or 32 bit (in 32-bit units) */ 80552558Sobrien width = ((bar & 7) == 4) ? 2 : 1; 80652558Sobrien 80752558Sobrien addr = pcib_alloc(dev, bar); 808169699Skan if (!addr) 80952558Sobrien return (-1); 810169699Skan 81152558Sobrien if (bootverbose) 812169699Skan printf("PCI %u:%u:%u: reg %x: smask=%08x: addr=%08x\n", 81352558Sobrien bus, slot, func, reg, bar, addr); 81452558Sobrien 81552558Sobrien mtk_pci_write_config(dev, bus, slot, func, reg, addr, 4); 81652558Sobrien if (width == 2) 81752558Sobrien mtk_pci_write_config(dev, bus, slot, func, reg + 4, 0, 4); 81852558Sobrien 819169699Skan return (width); 820169699Skan} 821169699Skan 822169699Skanstatic int 823169699Skanmtk_pcib_init_all_bars(device_t dev, int bus, int slot, int func, 824169699Skan int hdrtype) 825169699Skan{ 826169699Skan int maxbar, bar, i; 827169699Skan 828169699Skan maxbar = (hdrtype & PCIM_HDRTYPE) ? 0 : 6; 829169699Skan bar = 0; 830169699Skan 831169699Skan while (bar < maxbar) { 832169699Skan i = mtk_pcib_init_bar(dev, bus, slot, func, bar); 833169699Skan bar += i; 834169699Skan if (i < 0) { 835169699Skan device_printf(dev, "PCI IO/Memory space exhausted\n"); 836169699Skan return (ENOMEM); 837169699Skan } 838169699Skan } 839169699Skan 840169699Skan return (0); 841169699Skan} 842169699Skan 843169699Skanstatic void 844169699Skanmtk_pcib_init_bridge(device_t dev, int bus, int slot, int func) 845169699Skan{ 846169699Skan struct mtk_pci_softc *sc = device_get_softc(dev); 847169699Skan bus_addr_t io_base, mem_base; 848169699Skan uint32_t io_limit, mem_limit; 849169699Skan int secbus; 850169699Skan 851169699Skan if (bus == 0 && !mtk_pci_slot_has_link(dev, slot)) { 852169699Skan sc->sc_cur_secbus++; 853169699Skan device_printf(dev, "Skip bus %d due to no link\n", 854169699Skan sc->sc_cur_secbus); 855169699Skan return; 856169699Skan } 857169699Skan 858169699Skan io_base = sc->sc_io_base; 859169699Skan io_limit = io_base + sc->sc_io_size - 1; 860169699Skan mem_base = sc->sc_mem_base; 861169699Skan mem_limit = mem_base + sc->sc_mem_size - 1; 862169699Skan 863169699Skan mtk_pci_write_config(dev, bus, slot, func, PCIR_IOBASEL_1, 864169699Skan io_base >> 8, 1); 865169699Skan mtk_pci_write_config(dev, bus, slot, func, PCIR_IOBASEH_1, 866169699Skan io_base >> 16, 2); 867169699Skan mtk_pci_write_config(dev, bus, slot, func, PCIR_IOLIMITL_1, 86852558Sobrien io_limit >> 8, 1); 869169699Skan mtk_pci_write_config(dev, bus, slot, func, PCIR_IOLIMITH_1, 87090282Sobrien io_limit >> 16, 2); 87152558Sobrien 872132734Skan mtk_pci_write_config(dev, bus, slot, func, PCIR_MEMBASE_1, 87352558Sobrien mem_base >> 16, 2); 87452558Sobrien mtk_pci_write_config(dev, bus, slot, func, PCIR_MEMLIMIT_1, 87552558Sobrien mem_limit >> 16, 2); 87652558Sobrien 877169699Skan mtk_pci_write_config(dev, bus, slot, func, PCIR_PMBASEL_1, 878169699Skan 0x10, 2); 87952558Sobrien mtk_pci_write_config(dev, bus, slot, func, PCIR_PMBASEH_1, 880169699Skan 0x0, 4); 88152558Sobrien mtk_pci_write_config(dev, bus, slot, func, PCIR_PMLIMITL_1, 882169699Skan 0xF, 2); 883169699Skan mtk_pci_write_config(dev, bus, slot, func, PCIR_PMLIMITH_1, 884169699Skan 0x0, 4); 885169699Skan 88652558Sobrien mtk_pci_write_config(dev, bus, slot, func, PCIR_INTLINE, 0xff, 1); 887169699Skan 888169699Skan secbus = mtk_pci_read_config(dev, bus, slot, func, PCIR_SECBUS_1, 1); 889169699Skan 89052558Sobrien if (secbus == 0) { 891169699Skan sc->sc_cur_secbus++; 892169699Skan mtk_pci_write_config(dev, bus, slot, func, PCIR_SECBUS_1, 893169699Skan sc->sc_cur_secbus, 1); 894169699Skan mtk_pci_write_config(dev, bus, slot, func, PCIR_SUBBUS_1, 89552558Sobrien sc->sc_cur_secbus, 1); 89652558Sobrien secbus = sc->sc_cur_secbus; 897132734Skan } 898132734Skan 899132734Skan mtk_pcib_init(dev, secbus, PCI_SLOTMAX); 900132734Skan} 901132734Skan 902132734Skanstatic uint8_t 903132734Skanmtk_pci_get_int(device_t dev, int bus, int slot) 904132734Skan{ 905169699Skan 906169699Skan if (slot != 0) 907169699Skan return (PCI_INVALID_IRQ); 908169699Skan 909169699Skan switch (bus) { 910169699Skan case 1: 911169699Skan return (MTK_PCIE0_IRQ); 912132734Skan case 2: 913132734Skan return (MTK_PCIE1_IRQ); 914132734Skan case 3: 915132734Skan return (MTK_PCIE2_IRQ); 916132734Skan default: 917169699Skan device_printf(dev, "Bus %d out of range\n", slot); 918169699Skan return (PCI_INVALID_IRQ); 919169699Skan } 920169699Skan 921169699Skan /* Unreachable */ 922169699Skan return (PCI_INVALID_IRQ); 923169699Skan} 924169699Skan 925132734Skanstatic int 926169699Skanmtk_pcib_init(device_t dev, int bus, int maxslot) 927132734Skan{ 928169699Skan int slot, func, maxfunc, error; 929169699Skan uint8_t hdrtype, command, class, subclass; 930169699Skan 931169699Skan for (slot = 0; slot <= maxslot; slot++) { 932169699Skan maxfunc = 0; 933169699Skan for (func = 0; func <= maxfunc; func++) { 934132734Skan hdrtype = mtk_pci_read_config(dev, bus, slot, func, 935169699Skan PCIR_HDRTYPE, 1); 936169699Skan 937169699Skan if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE) 938132734Skan continue; 939132734Skan 940169699Skan if (func == 0 && (hdrtype & PCIM_MFDEV)) 941169699Skan maxfunc = PCI_FUNCMAX; 942169699Skan 943169699Skan command = mtk_pci_read_config(dev, bus, slot, func, 944169699Skan PCIR_COMMAND, 1); 945169699Skan command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN); 946132734Skan mtk_pci_write_config(dev, bus, slot, func, 947132734Skan PCIR_COMMAND, command, 1); 948132734Skan 949260919Spfg error = mtk_pcib_init_all_bars(dev, bus, slot, func, 950260919Spfg hdrtype); 951260919Spfg 952260919Spfg if (error) 953260919Spfg return (error); 954260919Spfg 955260919Spfg command |= PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN | 956260919Spfg PCIM_CMD_PORTEN; 957260919Spfg mtk_pci_write_config(dev, bus, slot, func, 958260919Spfg PCIR_COMMAND, command, 1); 959260919Spfg 960260919Spfg mtk_pci_write_config(dev, bus, slot, func, 961260919Spfg PCIR_CACHELNSZ, 16, 1); 962260919Spfg 963260919Spfg class = mtk_pci_read_config(dev, bus, slot, func, 964260919Spfg PCIR_CLASS, 1); 965260919Spfg subclass = mtk_pci_read_config(dev, bus, slot, func, 966260919Spfg PCIR_SUBCLASS, 1); 967260919Spfg 968260919Spfg if (class != PCIC_BRIDGE || 969260919Spfg subclass != PCIS_BRIDGE_PCI) { 970260919Spfg uint8_t val; 971260919Spfg 972260919Spfg val = mtk_pci_get_int(dev, bus, slot); 973260919Spfg 974260919Spfg mtk_pci_write_config(dev, bus, slot, func, 975260919Spfg PCIR_INTLINE, val, 1); /* XXX */ 976260919Spfg continue; 977260919Spfg } 978260919Spfg 979260919Spfg mtk_pcib_init_bridge(dev, bus, slot, func); 980260919Spfg } 981260919Spfg } 982260919Spfg 983260919Spfg return (0); 984260919Spfg} 985260919Spfg 986260919Spfg/* Our interrupt handler */ 987260919Spfgstatic int 988260919Spfgmtk_pci_intr(void *arg) 989132734Skan{ 99090282Sobrien struct mtk_pci_softc *sc = arg; 991132734Skan struct intr_event *event; 99218334Speter uint32_t reg, irq, irqidx; 99390282Sobrien 994169699Skan reg = MT_READ32(sc, MTK_PCI_PCIINT); 995169699Skan 996169699Skan for (irq = sc->sc_irq_start; irq <= sc->sc_irq_end; irq++) { 997132734Skan if (reg & (1u<<irq)) { 998169699Skan irqidx = irq - sc->sc_irq_start; 99918334Speter event = sc->sc_eventstab[irqidx]; 100090282Sobrien if (!event || TAILQ_EMPTY(&event->ie_handlers)) { 100118334Speter if (irq != 0) 1002169699Skan printf("Stray PCI IRQ %d\n", irq); 1003169699Skan continue; 1004169699Skan } 1005169699Skan 1006169699Skan intr_event_handle(event, NULL); 1007132734Skan } 100890282Sobrien } 1009169699Skan 1010169699Skan return (FILTER_HANDLED); 1011169699Skan} 1012132734Skan 1013132734Skan/* PCIe SoC-specific initialization */ 1014169699Skanstatic int 101590282Sobrienmtk_pcie_phy_init(device_t dev) 101690282Sobrien{ 1017169699Skan struct mtk_pci_softc *sc; 101890282Sobrien 101918334Speter /* Get our softc */ 102090282Sobrien sc = device_get_softc(dev); 1021132734Skan 1022132734Skan /* We don't know how many slots we have yet */ 102318334Speter sc->num_slots = 0; 102490282Sobrien 1025132734Skan /* Handle SoC specific PCIe init */ 102690282Sobrien switch (sc->socid) { 102790282Sobrien case MTK_SOC_MT7628: /* Fallthrough */ 102818334Speter case MTK_SOC_MT7688: 1029169699Skan if (mtk_pcie_phy_mt7628_init(dev)) 1030169699Skan return (ENXIO); 1031169699Skan break; 1032169699Skan case MTK_SOC_MT7621: 103390282Sobrien if (mtk_pcie_phy_mt7621_init(dev)) 1034132734Skan return (ENXIO); 103590282Sobrien break; 103690282Sobrien case MTK_SOC_MT7620A: 1037169699Skan if (mtk_pcie_phy_mt7620_init(dev)) 103890282Sobrien return (ENXIO); 103918334Speter break; 1040169699Skan case MTK_SOC_RT3662: /* Fallthrough */ 1041169699Skan case MTK_SOC_RT3883: 1042169699Skan if (mtk_pcie_phy_rt3883_init(dev)) 1043169699Skan return (ENXIO); 1044169699Skan break; 1045169699Skan default: 1046169699Skan device_printf(dev, "unsupported device %x\n", sc->socid); 1047169699Skan return (ENXIO); 1048169699Skan } 1049169699Skan 1050169699Skan /* 1051169699Skan * If we were successful so far go and set up the PCIe slots, so we 1052169699Skan * may allocate mem/io/irq resources and enumerate busses later. 1053169699Skan */ 1054169699Skan mtk_pcie_phy_setup_slots(dev); 105590282Sobrien 105690282Sobrien return (0); 105718334Speter} 105890282Sobrien 1059132734Skanstatic int 106090282Sobrienmtk_pcie_phy_start(device_t dev) 106118334Speter{ 106218334Speter struct mtk_pci_softc *sc = device_get_softc(dev); 1063169699Skan 106450615Sobrien if (sc->socid == MTK_SOC_MT7621 && 1065132734Skan (mtk_sysctl_get(SYSCTL_REVID) & SYSCTL_REVID_MASK) != 106618334Speter SYSCTL_MT7621_REV_E) { 106790282Sobrien if (fdt_reset_assert_all(dev)) 106818334Speter return (ENXIO); 1069117414Skan } else { 1070117414Skan if (fdt_reset_deassert_all(dev)) 1071169699Skan return (ENXIO); 107218334Speter } 107390282Sobrien 107490282Sobrien if (fdt_clock_enable_all(dev)) 1075169699Skan return (ENXIO); 107618334Speter 107718334Speter return (0); 107818334Speter} 107990282Sobrien 108018334Speterstatic int 1081169699Skanmtk_pcie_phy_stop(device_t dev) 108290282Sobrien{ 108352558Sobrien struct mtk_pci_softc *sc = device_get_softc(dev); 1084169699Skan 1085132734Skan if (sc->socid == MTK_SOC_MT7621 && 1086169699Skan (mtk_sysctl_get(SYSCTL_REVID) & SYSCTL_REVID_MASK) != 108718334Speter SYSCTL_MT7621_REV_E) { 1088132734Skan if (fdt_reset_deassert_all(dev)) 1089132734Skan return (ENXIO); 1090132734Skan } else { 1091132734Skan if (fdt_reset_assert_all(dev)) 109218334Speter return (ENXIO); 1093169699Skan } 1094169699Skan 1095169699Skan if (fdt_clock_disable_all(dev)) 1096169699Skan return (ENXIO); 1097169699Skan 1098169699Skan return (0); 1099169699Skan} 110018334Speter 110118334Speter#define mtk_pcie_phy_set(_sc, _reg, _s, _n, _v) \ 110218334Speter MT_WRITE32((_sc), (_reg), ((MT_READ32((_sc), (_reg)) & \ 110318334Speter (~(((1ull << (_n)) - 1) << (_s)))) | ((_v) << (_s)))) 110490282Sobrien 110590282Sobrienstatic void 110618334Spetermtk_pcie_phy_mt7621_bypass_pipe_rst(struct mtk_pci_softc *sc, uint32_t off) 1107169699Skan{ 110850615Sobrien 110950615Sobrien mtk_pcie_phy_set(sc, off + 0x002c, 12, 1, 1); 111050615Sobrien mtk_pcie_phy_set(sc, off + 0x002c, 4, 1, 1); 111150615Sobrien mtk_pcie_phy_set(sc, off + 0x012c, 12, 1, 1); 111290282Sobrien mtk_pcie_phy_set(sc, off + 0x012c, 4, 1, 1); 111390282Sobrien mtk_pcie_phy_set(sc, off + 0x102c, 12, 1, 1); 111450615Sobrien mtk_pcie_phy_set(sc, off + 0x102c, 4, 1, 1); 111518334Speter} 111618334Speter 111790282Sobrienstatic void 111890282Sobrienmtk_pcie_phy_mt7621_setup_ssc(struct mtk_pci_softc *sc, uint32_t off) 1119215840Sdim{ 1120169699Skan uint32_t xtal_sel; 1121146908Skan 112290282Sobrien xtal_sel = mtk_sysctl_get(SYSCTL_SYSCFG) >> 6; 112390282Sobrien xtal_sel &= 0x7; 112490282Sobrien 112590282Sobrien mtk_pcie_phy_set(sc, off + 0x400, 8, 1, 1); 112690282Sobrien mtk_pcie_phy_set(sc, off + 0x400, 9, 2, 0); 112790282Sobrien mtk_pcie_phy_set(sc, off + 0x000, 4, 1, 1); 112890282Sobrien mtk_pcie_phy_set(sc, off + 0x100, 4, 1, 1); 112952558Sobrien mtk_pcie_phy_set(sc, off + 0x000, 5, 1, 0); 113052558Sobrien mtk_pcie_phy_set(sc, off + 0x100, 5, 1, 0); 1131169699Skan 1132169699Skan if (xtal_sel <= 5 && xtal_sel >= 3) { 1133169699Skan mtk_pcie_phy_set(sc, off + 0x490, 6, 2, 1); 1134169699Skan mtk_pcie_phy_set(sc, off + 0x4a8, 0, 12, 0x1a); 113518334Speter mtk_pcie_phy_set(sc, off + 0x4a8, 16, 12, 0x1a); 1136132734Skan } else { 113790282Sobrien mtk_pcie_phy_set(sc, off + 0x490, 6, 2, 0); 113850615Sobrien if (xtal_sel >= 6) { 1139132734Skan mtk_pcie_phy_set(sc, off + 0x4bc, 4, 2, 0x01); 1140132734Skan mtk_pcie_phy_set(sc, off + 0x49c, 0, 31, 0x18000000); 114190282Sobrien mtk_pcie_phy_set(sc, off + 0x4a4, 0, 16, 0x18d); 1142169699Skan mtk_pcie_phy_set(sc, off + 0x4a8, 0, 12, 0x4a); 114350615Sobrien mtk_pcie_phy_set(sc, off + 0x4a8, 16, 12, 0x4a); 114490282Sobrien mtk_pcie_phy_set(sc, off + 0x4a8, 0, 12, 0x11); 114590282Sobrien mtk_pcie_phy_set(sc, off + 0x4a8, 16, 12, 0x11); 114690282Sobrien } else { 114790282Sobrien mtk_pcie_phy_set(sc, off + 0x4a8, 0, 12, 0x1a); 114890282Sobrien mtk_pcie_phy_set(sc, off + 0x4a8, 16, 12, 0x1a); 114990282Sobrien } 115090282Sobrien } 115190282Sobrien 115290282Sobrien mtk_pcie_phy_set(sc, off + 0x4a0, 5, 1, 1); 115390282Sobrien mtk_pcie_phy_set(sc, off + 0x490, 22, 2, 2); 1154117414Skan mtk_pcie_phy_set(sc, off + 0x490, 18, 4, 6); 1155117414Skan mtk_pcie_phy_set(sc, off + 0x490, 12, 4, 2); 1156117414Skan mtk_pcie_phy_set(sc, off + 0x490, 8, 4, 1); 115790282Sobrien mtk_pcie_phy_set(sc, off + 0x4ac, 16, 3, 0); 115890282Sobrien mtk_pcie_phy_set(sc, off + 0x490, 1, 3, 2); 115990282Sobrien 116090282Sobrien if (xtal_sel <= 5 && xtal_sel >= 3) { 116190282Sobrien mtk_pcie_phy_set(sc, off + 0x414, 6, 2, 1); 116290282Sobrien mtk_pcie_phy_set(sc, off + 0x414, 5, 1, 1); 116390282Sobrien } 1164117414Skan 116590282Sobrien mtk_pcie_phy_set(sc, off + 0x414, 28, 2, 1); 116690282Sobrien mtk_pcie_phy_set(sc, off + 0x040, 17, 4, 7); 116790282Sobrien mtk_pcie_phy_set(sc, off + 0x040, 16, 1, 1); 116890282Sobrien mtk_pcie_phy_set(sc, off + 0x140, 17, 4, 7); 1169132734Skan mtk_pcie_phy_set(sc, off + 0x140, 16, 1, 1); 1170132734Skan 1171132734Skan mtk_pcie_phy_set(sc, off + 0x000, 5, 1, 1); 117290282Sobrien mtk_pcie_phy_set(sc, off + 0x100, 5, 1, 1); 1173169699Skan mtk_pcie_phy_set(sc, off + 0x000, 4, 1, 0); 117490282Sobrien mtk_pcie_phy_set(sc, off + 0x100, 4, 1, 0); 1175169699Skan} 1176169699Skan 117790282Sobrien/* XXX: ugly, we need to fix this at some point */ 117890282Sobrien#define MT7621_GPIO_CTRL0 *((volatile uint32_t *)0xbe000600) 117990282Sobrien#define MT7621_GPIO_DATA0 *((volatile uint32_t *)0xbe000620) 118090282Sobrien 1181132734Skan#define mtk_gpio_clr_set(_reg, _clr, _set) \ 1182132734Skan do { \ 118350615Sobrien (_reg) = ((_reg) & (_clr)) | (_set); \ 1184169699Skan } while (0) 1185132734Skan 118650615Sobrienstatic int 118750615Sobrienmtk_pcie_phy_mt7621_init(device_t dev) 118850615Sobrien{ 118950615Sobrien struct mtk_pci_softc *sc = device_get_softc(dev); 119018334Speter 1191132734Skan /* First off, stop the PHY */ 1192132734Skan if (mtk_pcie_phy_stop(dev)) 119350615Sobrien return (ENXIO); 1194169699Skan 1195169699Skan /* PCIe resets are GPIO pins */ 1196169699Skan mtk_sysctl_clr_set(SYSCTL_GPIOMODE, MT7621_PERST_GPIO_MODE | 1197169699Skan MT7621_UARTL3_GPIO_MODE, MT7621_PERST_GPIO | MT7621_UARTL3_GPIO); 1198169699Skan 1199169699Skan /* Set GPIO pins as outputs */ 1200169699Skan mtk_gpio_clr_set(MT7621_GPIO_CTRL0, 0, MT7621_PCIE_RST); 1201169699Skan 1202169699Skan /* Assert resets to PCIe devices */ 120350615Sobrien mtk_gpio_clr_set(MT7621_GPIO_DATA0, MT7621_PCIE_RST, 0); 120452558Sobrien 120550615Sobrien /* Give everything a chance to sink in */ 1206169699Skan DELAY(100000); 1207169699Skan 1208169699Skan /* Now start the PHY again */ 120990282Sobrien if (mtk_pcie_phy_start(dev)) 121090282Sobrien return (ENXIO); 1211169699Skan 1212169699Skan /* Wait for things to settle */ 1213117414Skan DELAY(100000); 1214117414Skan 121550615Sobrien /* Only apply below to REV-E hardware */ 121618334Speter if ((mtk_sysctl_get(SYSCTL_REVID) & SYSCTL_REVID_MASK) == 121750615Sobrien SYSCTL_MT7621_REV_E) 121850615Sobrien mtk_pcie_phy_mt7621_bypass_pipe_rst(sc, 0x9000); 121950615Sobrien 122018334Speter /* Setup PCIe ports 0 and 1 */ 122152558Sobrien mtk_pcie_phy_mt7621_setup_ssc(sc, 0x9000); 1222132734Skan /* Setup PCIe port 2 */ 1223132734Skan mtk_pcie_phy_mt7621_setup_ssc(sc, 0xa000); 1224132734Skan 122518334Speter /* Deassert resets to PCIe devices */ 122650615Sobrien mtk_gpio_clr_set(MT7621_GPIO_DATA0, 0, MT7621_PCIE_RST); 122750615Sobrien 122850615Sobrien /* Set number of slots supported */ 122918334Speter sc->num_slots = 3; 123050615Sobrien 123150615Sobrien /* Give it a chance to sink in */ 123218334Speter DELAY(100000); 123350615Sobrien 123450615Sobrien return (0); 123518334Speter} 123650615Sobrien 123750615Sobrienstatic void 123850615Sobrienmtk_pcie_phy_mt7628_setup(struct mtk_pci_softc *sc, uint32_t off) 123950615Sobrien{ 124050615Sobrien uint32_t xtal_sel; 124150615Sobrien 124250615Sobrien xtal_sel = mtk_sysctl_get(SYSCTL_SYSCFG) >> 6; 124350615Sobrien xtal_sel &= 0x1; 124418334Speter 124590282Sobrien mtk_pcie_phy_set(sc, off + 0x400, 8, 1, 1); 124650615Sobrien mtk_pcie_phy_set(sc, off + 0x400, 9, 2, 0); 124750615Sobrien mtk_pcie_phy_set(sc, off + 0x000, 4, 1, 1); 124850615Sobrien mtk_pcie_phy_set(sc, off + 0x000, 5, 1, 0); 124950615Sobrien mtk_pcie_phy_set(sc, off + 0x4ac, 16, 3, 3); 125018334Speter 125152558Sobrien if (xtal_sel == 1) { 1252132734Skan mtk_pcie_phy_set(sc, off + 0x4bc, 24, 8, 0x7d); 1253132734Skan mtk_pcie_phy_set(sc, off + 0x490, 12, 4, 0x08); 125418334Speter mtk_pcie_phy_set(sc, off + 0x490, 6, 2, 0x01); 125550615Sobrien mtk_pcie_phy_set(sc, off + 0x4c0, 0, 32, 0x1f400000); 1256132734Skan mtk_pcie_phy_set(sc, off + 0x4a4, 0, 16, 0x013d); 125718334Speter mtk_pcie_phy_set(sc, off + 0x4a8, 16, 16, 0x74); 1258117414Skan mtk_pcie_phy_set(sc, off + 0x4a8, 0, 16, 0x74); 1259132734Skan } else { 1260132734Skan mtk_pcie_phy_set(sc, off + 0x4bc, 24, 8, 0x64); 1261117414Skan mtk_pcie_phy_set(sc, off + 0x490, 12, 4, 0x0a); 126250615Sobrien mtk_pcie_phy_set(sc, off + 0x490, 6, 2, 0x00); 126350615Sobrien mtk_pcie_phy_set(sc, off + 0x4c0, 0, 32, 0x19000000); 126452558Sobrien mtk_pcie_phy_set(sc, off + 0x4a4, 0, 16, 0x018d); 126550615Sobrien mtk_pcie_phy_set(sc, off + 0x4a8, 16, 16, 0x4a); 126650615Sobrien mtk_pcie_phy_set(sc, off + 0x4a8, 0, 16, 0x4a); 126750615Sobrien } 126850615Sobrien 126950615Sobrien mtk_pcie_phy_set(sc, off + 0x498, 0, 8, 5); 127050615Sobrien mtk_pcie_phy_set(sc, off + 0x000, 5, 1, 1); 127150615Sobrien mtk_pcie_phy_set(sc, off + 0x000, 4, 1, 0); 127250615Sobrien} 127350615Sobrien 127450615Sobrienstatic int 127550615Sobrienmtk_pcie_phy_mt7628_init(device_t dev) 127650615Sobrien{ 127750615Sobrien struct mtk_pci_softc *sc = device_get_softc(dev); 127850615Sobrien 127950615Sobrien /* Set PCIe reset to normal mode */ 128050615Sobrien mtk_sysctl_clr_set(SYSCTL_GPIOMODE, MT7628_PERST_GPIO_MODE, 128150615Sobrien MT7628_PERST); 128250615Sobrien 128350615Sobrien /* Start the PHY */ 128450615Sobrien if (mtk_pcie_phy_start(dev)) 128550615Sobrien return (ENXIO); 128650615Sobrien 128750615Sobrien /* Give it a chance to sink in */ 128850615Sobrien DELAY(100000); 128950615Sobrien 129050615Sobrien /* Setup the PHY */ 129150615Sobrien mtk_pcie_phy_mt7628_setup(sc, 0x9000); 129250615Sobrien 129352558Sobrien /* Deassert PCIe device reset */ 129450615Sobrien MT_CLR_SET32(sc, MTK_PCI_PCICFG, MTK_PCI_RESET, 0); 1295169699Skan 1296169699Skan /* Set number of slots supported */ 1297169699Skan sc->num_slots = 1; 129850615Sobrien 1299169699Skan return (0); 130018334Speter} 130150615Sobrien 130218334Speterstatic int 1303132734Skanmtk_pcie_phy_mt7620_wait_busy(struct mtk_pci_softc *sc) 130490282Sobrien{ 130590282Sobrien uint32_t reg_value, retry; 130690282Sobrien 130790282Sobrien reg_value = retry = 0; 130890282Sobrien 1309132734Skan while (retry++ < MT7620_MAX_RETRIES) { 131090282Sobrien reg_value = MT_READ32(sc, MT7620_PCIE_PHY_CFG); 131190282Sobrien if (reg_value & PHY_BUSY) 131290282Sobrien DELAY(100000); 131390282Sobrien else 131490282Sobrien break; 131590282Sobrien } 1316117414Skan 1317117414Skan if (retry >= MT7620_MAX_RETRIES) 1318169699Skan return (ENXIO); 1319117414Skan 1320117414Skan return (0); 1321117414Skan} 1322117414Skan 1323117414Skanstatic int 132490282Sobrienmtk_pcie_phy_mt7620_set(struct mtk_pci_softc *sc, uint32_t reg, 1325117414Skan uint32_t val) 132690282Sobrien{ 1327169699Skan uint32_t reg_val; 132890282Sobrien 1329169699Skan if (mtk_pcie_phy_mt7620_wait_busy(sc)) 133090282Sobrien return (ENXIO); 133150615Sobrien 133290282Sobrien reg_val = PHY_MODE_WRITE | ((reg & 0xff) << PHY_ADDR_OFFSET) | 133390282Sobrien (val & 0xff); 1334132734Skan MT_WRITE32(sc, MT7620_PCIE_PHY_CFG, reg_val); 133590282Sobrien DELAY(1000); 133690282Sobrien 133790282Sobrien if (mtk_pcie_phy_mt7620_wait_busy(sc)) 133890282Sobrien return (ENXIO); 133990282Sobrien 134090282Sobrien return (0); 134190282Sobrien} 134290282Sobrien 134390282Sobrienstatic int 134490282Sobrienmtk_pcie_phy_mt7620_init(device_t dev) 134590282Sobrien{ 134690282Sobrien struct mtk_pci_softc *sc = device_get_softc(dev); 134790282Sobrien 134890282Sobrien /* 134990282Sobrien * The below sets the PCIe PHY to bypass the PCIe DLL and enables 1350132734Skan * "elastic buffer control", whatever that may be... 1351169699Skan */ 1352169699Skan if (mtk_pcie_phy_mt7620_set(sc, 0x00, 0x80) || 1353169699Skan mtk_pcie_phy_mt7620_set(sc, 0x01, 0x04) || 1354169699Skan mtk_pcie_phy_mt7620_set(sc, 0x68, 0x84)) 1355169699Skan return (ENXIO); 1356169699Skan 1357169699Skan /* Stop PCIe */ 1358169699Skan if (mtk_pcie_phy_stop(dev)) 1359169699Skan return (ENXIO); 1360169699Skan 1361169699Skan /* Restore PPLL to a sane state before going on */ 1362169699Skan mtk_sysctl_clr_set(MT7620_PPLL_DRV, LC_CKDRVPD, PDRV_SW_SET); 1363169699Skan 1364169699Skan /* No PCIe on the MT7620N */ 1365169699Skan if (!(mtk_sysctl_get(SYSCTL_REVID) & MT7620_PKG_BGA)) { 1366132734Skan device_printf(dev, "PCIe disabled for MT7620N\n"); 1367132734Skan mtk_sysctl_clr_set(MT7620_PPLL_CFG0, 0, PPLL_SW_SET); 1368132734Skan mtk_sysctl_clr_set(MT7620_PPLL_CFG1, 0, PPLL_PD); 1369132734Skan return (ENXIO); 1370132734Skan } 1371132734Skan 1372132734Skan /* PCIe device reset pin is in normal mode */ 1373169699Skan mtk_sysctl_clr_set(SYSCTL_GPIOMODE, MT7620_PERST_GPIO_MODE, 1374132734Skan MT7620_PERST); 1375132734Skan 1376132734Skan /* Enable PCIe now */ 1377169699Skan if (mtk_pcie_phy_start(dev)) 1378169699Skan return (ENXIO); 1379169699Skan 1380169699Skan /* Give it a chance to sink in */ 1381169699Skan DELAY(100000); 1382169699Skan 1383132734Skan /* If PLL is not locked - bail */ 1384169699Skan if (!(mtk_sysctl_get(MT7620_PPLL_CFG1) & PPLL_LOCKED)) { 1385132734Skan device_printf(dev, "no PPLL not lock\n"); 1386132734Skan mtk_pcie_phy_stop(dev); 1387132734Skan return (ENXIO); 1388169699Skan } 1389132734Skan 1390169699Skan /* Configure PCIe PLL */ 1391169699Skan mtk_sysctl_clr_set(MT7620_PPLL_DRV, LC_CKDRVOHZ | LC_CKDRVHZ, 1392132734Skan LC_CKDRVPD | PDRV_SW_SET); 1393132734Skan 1394169699Skan /* and give it a chance to settle */ 1395169699Skan DELAY(100000); 1396169699Skan 1397169699Skan /* Deassert PCIe device reset */ 1398169699Skan MT_CLR_SET32(sc, MTK_PCI_PCICFG, MTK_PCI_RESET, 0); 1399169699Skan 1400169699Skan /* MT7620 supports one PCIe slot */ 1401132734Skan sc->num_slots = 1; 1402132734Skan 1403132734Skan return (0); 1404169699Skan} 1405169699Skan 1406169699Skanstatic int 1407169699Skanmtk_pcie_phy_rt3883_init(device_t dev) 1408169699Skan{ 1409169699Skan struct mtk_pci_softc *sc = device_get_softc(dev); 1410169699Skan 1411169699Skan /* Enable PCI host mode and PCIe RC mode */ 1412169699Skan mtk_sysctl_clr_set(SYSCTL_SYSCFG1, 0, RT3883_PCI_HOST_MODE | 1413169699Skan RT3883_PCIE_RC_MODE); 1414169699Skan 1415169699Skan /* Enable PCIe PHY */ 1416169699Skan if (mtk_pcie_phy_start(dev)) 1417169699Skan return (ENXIO); 1418132734Skan 1419132734Skan /* Disable PCI, we only support PCIe for now */ 1420132734Skan mtk_sysctl_clr_set(SYSCTL_RSTCTRL, 0, RT3883_PCI_RST); 1421132734Skan mtk_sysctl_clr_set(SYSCTL_CLKCFG1, RT3883_PCI_CLK, 0); 1422132734Skan 1423169699Skan /* Give things a chance to sink in */ 1424132734Skan DELAY(500000); 1425132734Skan 1426132734Skan /* Set PCIe port number to 0 and lift PCIe reset */ 1427132734Skan MT_WRITE32(sc, MTK_PCI_PCICFG, 0); 1428132734Skan 1429132734Skan /* Configure PCI Arbiter */ 1430132734Skan MT_WRITE32(sc, MTK_PCI_ARBCTL, 0x79); 1431132734Skan 1432132734Skan /* We have a single PCIe slot */ 1433132734Skan sc->num_slots = 1; 1434132734Skan 1435169699Skan return (0); 1436132734Skan} 1437169699Skan 1438169699Skanstatic void 1439132734Skanmtk_pcie_phy_setup_slots(device_t dev) 1440169699Skan{ 1441169699Skan struct mtk_pci_softc *sc = device_get_softc(dev); 1442169699Skan uint32_t bar0_val, val; 1443169699Skan int i; 1444169699Skan 1445169699Skan /* Disable all PCIe interrupts */ 1446132734Skan MT_WRITE32(sc, MTK_PCI_PCIENA, 0); 1447132734Skan 1448169699Skan /* Default bar0_val is 64M, enabled */ 1449169699Skan bar0_val = 0x03FF0001; 1450169699Skan 1451169699Skan /* But we override it to 2G, enabled for some SoCs */ 1452169699Skan if (sc->socid == MTK_SOC_MT7620A || sc->socid == MTK_SOC_MT7628 || 1453169699Skan sc->socid == MTK_SOC_MT7688 || sc->socid == MTK_SOC_MT7621) 1454169699Skan bar0_val = 0x7FFF0001; 1455169699Skan 1456132734Skan /* We still don't know which slots have linked up */ 1457132734Skan sc->pcie_link_status = 0; 1458132734Skan 1459132734Skan /* XXX: I am not sure if this delay is really necessary */ 1460132734Skan DELAY(500000); 1461132734Skan 1462169699Skan /* 1463169699Skan * See which slots have links and mark them. 1464132734Skan * Set up all slots' BARs and make them look like PCIe bridges. 1465169699Skan */ 1466169699Skan for (i = 0; i < sc->num_slots; i++) { 1467169699Skan /* If slot has link - mark it */ 1468169699Skan if (MT_READ32(sc, MTK_PCIE_STATUS(i)) & 1) 1469169699Skan sc->pcie_link_status |= (1<<i); 1470169699Skan 1471169699Skan /* Generic slot configuration follows */ 1472132734Skan 1473132734Skan /* We enable BAR0 */ 1474169699Skan MT_WRITE32(sc, MTK_PCIE_BAR0SETUP(i), bar0_val); 1475169699Skan /* and disable BAR1 */ 1476169699Skan MT_WRITE32(sc, MTK_PCIE_BAR1SETUP(i), 0); 1477169699Skan /* Internal memory base has no offset */ 1478169699Skan MT_WRITE32(sc, MTK_PCIE_IMBASEBAR0(i), 0); 1479132734Skan /* We're a PCIe bridge */ 1480132734Skan MT_WRITE32(sc, MTK_PCIE_CLASS(i), 0x06040001); 1481169699Skan 1482169699Skan val = mtk_pci_read_config(dev, 0, i, 0, 0x4, 4); 1483132734Skan mtk_pci_write_config(dev, 0, i, 0, 0x4, val | 0x4, 4); 1484132734Skan val = mtk_pci_read_config(dev, 0, i, 0, 0x70c, 4); 1485132734Skan val &= ~(0xff << 8); 1486132734Skan val |= (0x50 << 8); 1487169699Skan mtk_pci_write_config(dev, 0, i, 0, 0x4, val, 4); 1488169699Skan } 1489169699Skan} 1490169699Skan