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