xref: /freebsd/sys/arm/mv/mv_pci.c (revision db5ef4fc7754e1305d31f35018ead86b72ec644f)
16975124cSRafal Jaworowski /*-
2*db5ef4fcSRafal Jaworowski  * Copyright (c) 2008 MARVELL INTERNATIONAL LTD.
3*db5ef4fcSRafal Jaworowski  * Copyright (c) 2010 The FreeBSD Foundation
46975124cSRafal Jaworowski  * All rights reserved.
56975124cSRafal Jaworowski  *
66975124cSRafal Jaworowski  * Developed by Semihalf.
76975124cSRafal Jaworowski  *
8*db5ef4fcSRafal Jaworowski  * Portions of this software were developed by Semihalf
9*db5ef4fcSRafal Jaworowski  * under sponsorship from the FreeBSD Foundation.
10*db5ef4fcSRafal Jaworowski  *
116975124cSRafal Jaworowski  * Redistribution and use in source and binary forms, with or without
126975124cSRafal Jaworowski  * modification, are permitted provided that the following conditions
136975124cSRafal Jaworowski  * are met:
146975124cSRafal Jaworowski  * 1. Redistributions of source code must retain the above copyright
156975124cSRafal Jaworowski  *    notice, this list of conditions and the following disclaimer.
166975124cSRafal Jaworowski  * 2. Redistributions in binary form must reproduce the above copyright
176975124cSRafal Jaworowski  *    notice, this list of conditions and the following disclaimer in the
186975124cSRafal Jaworowski  *    documentation and/or other materials provided with the distribution.
196975124cSRafal Jaworowski  * 3. Neither the name of MARVELL nor the names of contributors
206975124cSRafal Jaworowski  *    may be used to endorse or promote products derived from this software
216975124cSRafal Jaworowski  *    without specific prior written permission.
226975124cSRafal Jaworowski  *
236975124cSRafal Jaworowski  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
246975124cSRafal Jaworowski  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
256975124cSRafal Jaworowski  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
266975124cSRafal Jaworowski  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
276975124cSRafal Jaworowski  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
286975124cSRafal Jaworowski  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
296975124cSRafal Jaworowski  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
306975124cSRafal Jaworowski  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
316975124cSRafal Jaworowski  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
326975124cSRafal Jaworowski  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
336975124cSRafal Jaworowski  * SUCH DAMAGE.
346975124cSRafal Jaworowski  */
356975124cSRafal Jaworowski 
366975124cSRafal Jaworowski /*
376975124cSRafal Jaworowski  * Marvell integrated PCI/PCI-Express controller driver.
386975124cSRafal Jaworowski  */
396975124cSRafal Jaworowski 
406975124cSRafal Jaworowski #include <sys/cdefs.h>
416975124cSRafal Jaworowski __FBSDID("$FreeBSD$");
426975124cSRafal Jaworowski 
436975124cSRafal Jaworowski #include <sys/param.h>
446975124cSRafal Jaworowski #include <sys/systm.h>
456975124cSRafal Jaworowski #include <sys/kernel.h>
466975124cSRafal Jaworowski #include <sys/lock.h>
476975124cSRafal Jaworowski #include <sys/malloc.h>
486975124cSRafal Jaworowski #include <sys/module.h>
496975124cSRafal Jaworowski #include <sys/mutex.h>
506975124cSRafal Jaworowski #include <sys/queue.h>
516975124cSRafal Jaworowski #include <sys/bus.h>
526975124cSRafal Jaworowski #include <sys/rman.h>
536975124cSRafal Jaworowski #include <sys/endian.h>
546975124cSRafal Jaworowski 
556975124cSRafal Jaworowski #include <vm/vm.h>
566975124cSRafal Jaworowski #include <vm/pmap.h>
576975124cSRafal Jaworowski 
58*db5ef4fcSRafal Jaworowski #include <dev/fdt/fdt_common.h>
59*db5ef4fcSRafal Jaworowski #include <dev/ofw/ofw_bus.h>
60*db5ef4fcSRafal Jaworowski #include <dev/ofw/ofw_bus_subr.h>
616975124cSRafal Jaworowski #include <dev/pci/pcivar.h>
626975124cSRafal Jaworowski #include <dev/pci/pcireg.h>
636975124cSRafal Jaworowski #include <dev/pci/pcib_private.h>
646975124cSRafal Jaworowski 
65*db5ef4fcSRafal Jaworowski #include "ofw_bus_if.h"
666975124cSRafal Jaworowski #include "pcib_if.h"
676975124cSRafal Jaworowski 
686975124cSRafal Jaworowski #include <machine/resource.h>
696975124cSRafal Jaworowski #include <machine/bus.h>
706975124cSRafal Jaworowski 
716975124cSRafal Jaworowski #include <arm/mv/mvreg.h>
726975124cSRafal Jaworowski #include <arm/mv/mvvar.h>
73*db5ef4fcSRafal Jaworowski #include <arm/mv/mvwin.h>
746975124cSRafal Jaworowski 
756975124cSRafal Jaworowski #define PCI_CFG_ENA		(1 << 31)
766975124cSRafal Jaworowski #define PCI_CFG_BUS(bus)	(((bus) & 0xff) << 16)
776975124cSRafal Jaworowski #define PCI_CFG_DEV(dev)	(((dev) & 0x1f) << 11)
786975124cSRafal Jaworowski #define PCI_CFG_FUN(fun)	(((fun) & 0x7) << 8)
796975124cSRafal Jaworowski #define PCI_CFG_PCIE_REG(reg)	((reg) & 0xfc)
806975124cSRafal Jaworowski 
816975124cSRafal Jaworowski #define PCI_REG_CFG_ADDR	0x0C78
826975124cSRafal Jaworowski #define PCI_REG_CFG_DATA	0x0C7C
836975124cSRafal Jaworowski #define PCI_REG_P2P_CONF	0x1D14
846975124cSRafal Jaworowski 
856975124cSRafal Jaworowski #define PCIE_REG_CFG_ADDR	0x18F8
866975124cSRafal Jaworowski #define PCIE_REG_CFG_DATA	0x18FC
876975124cSRafal Jaworowski #define PCIE_REG_CONTROL	0x1A00
886975124cSRafal Jaworowski #define   PCIE_CTRL_LINK1X	0x00000001
896975124cSRafal Jaworowski #define PCIE_REG_STATUS		0x1A04
906975124cSRafal Jaworowski #define PCIE_REG_IRQ_MASK	0x1910
916975124cSRafal Jaworowski 
924e883c81SRafal Jaworowski #define STATUS_LINK_DOWN	1
936975124cSRafal Jaworowski #define STATUS_BUS_OFFS		8
946975124cSRafal Jaworowski #define STATUS_BUS_MASK		(0xFF << STATUS_BUS_OFFS)
956975124cSRafal Jaworowski #define STATUS_DEV_OFFS		16
966975124cSRafal Jaworowski #define STATUS_DEV_MASK		(0x1F << STATUS_DEV_OFFS)
976975124cSRafal Jaworowski 
986975124cSRafal Jaworowski #define P2P_CONF_BUS_OFFS	16
996975124cSRafal Jaworowski #define P2P_CONF_BUS_MASK	(0xFF << P2P_CONF_BUS_OFFS)
1006975124cSRafal Jaworowski #define P2P_CONF_DEV_OFFS	24
1016975124cSRafal Jaworowski #define P2P_CONF_DEV_MASK	(0x1F << P2P_CONF_DEV_OFFS)
1026975124cSRafal Jaworowski 
1036975124cSRafal Jaworowski #define PCI_VENDORID_MRVL	0x11AB
1046975124cSRafal Jaworowski 
105*db5ef4fcSRafal Jaworowski struct mv_pcib_softc {
1066975124cSRafal Jaworowski 	device_t	sc_dev;
1076975124cSRafal Jaworowski 
108*db5ef4fcSRafal Jaworowski 	struct rman	sc_mem_rman;
109*db5ef4fcSRafal Jaworowski 	bus_addr_t	sc_mem_base;
110*db5ef4fcSRafal Jaworowski 	bus_addr_t	sc_mem_size;
111*db5ef4fcSRafal Jaworowski 	bus_addr_t	sc_mem_alloc;		/* Next allocation. */
112*db5ef4fcSRafal Jaworowski 	int		sc_mem_win_target;
113*db5ef4fcSRafal Jaworowski 	int		sc_mem_win_attr;
1146975124cSRafal Jaworowski 
115*db5ef4fcSRafal Jaworowski 	struct rman	sc_io_rman;
116*db5ef4fcSRafal Jaworowski 	bus_addr_t	sc_io_base;
117*db5ef4fcSRafal Jaworowski 	bus_addr_t	sc_io_size;
118*db5ef4fcSRafal Jaworowski 	bus_addr_t	sc_io_alloc;		/* Next allocation. */
119*db5ef4fcSRafal Jaworowski 	int		sc_io_win_target;
120*db5ef4fcSRafal Jaworowski 	int		sc_io_win_attr;
1216975124cSRafal Jaworowski 
1226975124cSRafal Jaworowski 	struct resource	*sc_res;
1236975124cSRafal Jaworowski 	bus_space_handle_t sc_bsh;
1246975124cSRafal Jaworowski 	bus_space_tag_t	sc_bst;
1256975124cSRafal Jaworowski 	int		sc_rid;
1266975124cSRafal Jaworowski 
1276975124cSRafal Jaworowski 	int		sc_busnr;		/* Host bridge bus number */
1286975124cSRafal Jaworowski 	int		sc_devnr;		/* Host bridge device number */
129*db5ef4fcSRafal Jaworowski 	int		sc_type;
1306975124cSRafal Jaworowski 
131*db5ef4fcSRafal Jaworowski 	struct fdt_pci_intr	sc_intr_info;
1326975124cSRafal Jaworowski };
1336975124cSRafal Jaworowski 
134*db5ef4fcSRafal Jaworowski /* Local forward prototypes */
135*db5ef4fcSRafal Jaworowski static int mv_pcib_decode_win(phandle_t, struct mv_pcib_softc *);
136*db5ef4fcSRafal Jaworowski static void mv_pcib_hw_cfginit(void);
137*db5ef4fcSRafal Jaworowski static uint32_t mv_pcib_hw_cfgread(struct mv_pcib_softc *, u_int, u_int,
138*db5ef4fcSRafal Jaworowski     u_int, u_int, int);
139*db5ef4fcSRafal Jaworowski static void mv_pcib_hw_cfgwrite(struct mv_pcib_softc *, u_int, u_int,
140*db5ef4fcSRafal Jaworowski     u_int, u_int, uint32_t, int);
141*db5ef4fcSRafal Jaworowski static int mv_pcib_init(struct mv_pcib_softc *, int, int);
142*db5ef4fcSRafal Jaworowski static int mv_pcib_init_all_bars(struct mv_pcib_softc *, int, int, int, int);
143*db5ef4fcSRafal Jaworowski static void mv_pcib_init_bridge(struct mv_pcib_softc *, int, int, int);
144*db5ef4fcSRafal Jaworowski static int mv_pcib_intr_info(phandle_t, struct mv_pcib_softc *);
145*db5ef4fcSRafal Jaworowski static inline void pcib_write_irq_mask(struct mv_pcib_softc *, uint32_t);
1466975124cSRafal Jaworowski 
147*db5ef4fcSRafal Jaworowski 
148*db5ef4fcSRafal Jaworowski /* Forward prototypes */
149*db5ef4fcSRafal Jaworowski static int mv_pcib_probe(device_t);
150*db5ef4fcSRafal Jaworowski static int mv_pcib_attach(device_t);
151*db5ef4fcSRafal Jaworowski 
152*db5ef4fcSRafal Jaworowski static struct resource *mv_pcib_alloc_resource(device_t, device_t, int, int *,
1536975124cSRafal Jaworowski     u_long, u_long, u_long, u_int);
154*db5ef4fcSRafal Jaworowski static int mv_pcib_release_resource(device_t, device_t, int, int,
1556975124cSRafal Jaworowski     struct resource *);
156*db5ef4fcSRafal Jaworowski static int mv_pcib_read_ivar(device_t, device_t, int, uintptr_t *);
157*db5ef4fcSRafal Jaworowski static int mv_pcib_write_ivar(device_t, device_t, int, uintptr_t);
1586975124cSRafal Jaworowski 
159*db5ef4fcSRafal Jaworowski static int mv_pcib_maxslots(device_t);
160*db5ef4fcSRafal Jaworowski static uint32_t mv_pcib_read_config(device_t, u_int, u_int, u_int, u_int, int);
161*db5ef4fcSRafal Jaworowski static void mv_pcib_write_config(device_t, u_int, u_int, u_int, u_int,
1626975124cSRafal Jaworowski     uint32_t, int);
163*db5ef4fcSRafal Jaworowski static int mv_pcib_route_interrupt(device_t, device_t, int);
1646975124cSRafal Jaworowski 
1656975124cSRafal Jaworowski /*
1666975124cSRafal Jaworowski  * Bus interface definitions.
1676975124cSRafal Jaworowski  */
168*db5ef4fcSRafal Jaworowski static device_method_t mv_pcib_methods[] = {
1696975124cSRafal Jaworowski 	/* Device interface */
170*db5ef4fcSRafal Jaworowski 	DEVMETHOD(device_probe,			mv_pcib_probe),
171*db5ef4fcSRafal Jaworowski 	DEVMETHOD(device_attach,		mv_pcib_attach),
1726975124cSRafal Jaworowski 
1736975124cSRafal Jaworowski 	/* Bus interface */
1746975124cSRafal Jaworowski 	DEVMETHOD(bus_print_child,		bus_generic_print_child),
175*db5ef4fcSRafal Jaworowski 	DEVMETHOD(bus_read_ivar,		mv_pcib_read_ivar),
176*db5ef4fcSRafal Jaworowski 	DEVMETHOD(bus_write_ivar,		mv_pcib_write_ivar),
177*db5ef4fcSRafal Jaworowski 	DEVMETHOD(bus_alloc_resource,		mv_pcib_alloc_resource),
178*db5ef4fcSRafal Jaworowski 	DEVMETHOD(bus_release_resource,		mv_pcib_release_resource),
1796975124cSRafal Jaworowski 	DEVMETHOD(bus_activate_resource,	bus_generic_activate_resource),
1806975124cSRafal Jaworowski 	DEVMETHOD(bus_deactivate_resource,	bus_generic_deactivate_resource),
1816975124cSRafal Jaworowski 	DEVMETHOD(bus_setup_intr,		bus_generic_setup_intr),
1826975124cSRafal Jaworowski 	DEVMETHOD(bus_teardown_intr,		bus_generic_teardown_intr),
1836975124cSRafal Jaworowski 
1846975124cSRafal Jaworowski 	/* pcib interface */
185*db5ef4fcSRafal Jaworowski 	DEVMETHOD(pcib_maxslots,		mv_pcib_maxslots),
186*db5ef4fcSRafal Jaworowski 	DEVMETHOD(pcib_read_config,		mv_pcib_read_config),
187*db5ef4fcSRafal Jaworowski 	DEVMETHOD(pcib_write_config,		mv_pcib_write_config),
188*db5ef4fcSRafal Jaworowski 	DEVMETHOD(pcib_route_interrupt,		mv_pcib_route_interrupt),
189*db5ef4fcSRafal Jaworowski 
190*db5ef4fcSRafal Jaworowski 	/* OFW bus interface */
191*db5ef4fcSRafal Jaworowski 	DEVMETHOD(ofw_bus_get_compat,   ofw_bus_gen_get_compat),
192*db5ef4fcSRafal Jaworowski 	DEVMETHOD(ofw_bus_get_model,    ofw_bus_gen_get_model),
193*db5ef4fcSRafal Jaworowski 	DEVMETHOD(ofw_bus_get_name,     ofw_bus_gen_get_name),
194*db5ef4fcSRafal Jaworowski 	DEVMETHOD(ofw_bus_get_node,     ofw_bus_gen_get_node),
195*db5ef4fcSRafal Jaworowski 	DEVMETHOD(ofw_bus_get_type,     ofw_bus_gen_get_type),
1966975124cSRafal Jaworowski 
1976975124cSRafal Jaworowski 	{ 0, 0 }
1986975124cSRafal Jaworowski };
1996975124cSRafal Jaworowski 
200*db5ef4fcSRafal Jaworowski static driver_t mv_pcib_driver = {
2016975124cSRafal Jaworowski 	"pcib",
202*db5ef4fcSRafal Jaworowski 	mv_pcib_methods,
203*db5ef4fcSRafal Jaworowski 	sizeof(struct mv_pcib_softc),
2046975124cSRafal Jaworowski };
2056975124cSRafal Jaworowski 
2066975124cSRafal Jaworowski devclass_t pcib_devclass;
2076975124cSRafal Jaworowski 
208*db5ef4fcSRafal Jaworowski DRIVER_MODULE(pcib, fdtbus, mv_pcib_driver, pcib_devclass, 0, 0);
2096975124cSRafal Jaworowski 
2106975124cSRafal Jaworowski static struct mtx pcicfg_mtx;
2116975124cSRafal Jaworowski 
212*db5ef4fcSRafal Jaworowski static int
213*db5ef4fcSRafal Jaworowski mv_pcib_probe(device_t self)
2146975124cSRafal Jaworowski {
215*db5ef4fcSRafal Jaworowski 	phandle_t parnode;
2166975124cSRafal Jaworowski 
217*db5ef4fcSRafal Jaworowski 	/*
218*db5ef4fcSRafal Jaworowski 	 * The PCI subnode does not have the 'compatible' property, so we need
219*db5ef4fcSRafal Jaworowski 	 * to check in the parent PCI node. However the parent is not
220*db5ef4fcSRafal Jaworowski 	 * represented by a separate ofw_bus child, and therefore
221*db5ef4fcSRafal Jaworowski 	 * ofw_bus_is_compatible() cannot be used, but direct fdt equivalent.
222*db5ef4fcSRafal Jaworowski 	 */
223*db5ef4fcSRafal Jaworowski 	parnode = OF_parent(ofw_bus_get_node(self));
224*db5ef4fcSRafal Jaworowski 	if (parnode == 0)
225*db5ef4fcSRafal Jaworowski 		return (ENXIO);
226*db5ef4fcSRafal Jaworowski 	if (!(fdt_is_compatible(parnode, "mrvl,pcie") ||
227*db5ef4fcSRafal Jaworowski 	    fdt_is_compatible(parnode, "mrvl,pci")))
228*db5ef4fcSRafal Jaworowski 		return (ENXIO);
2296975124cSRafal Jaworowski 
230*db5ef4fcSRafal Jaworowski 	device_set_desc(self, "Marvell Integrated PCI/PCI-E Controller");
231*db5ef4fcSRafal Jaworowski 
232*db5ef4fcSRafal Jaworowski 	return (BUS_PROBE_DEFAULT);
233*db5ef4fcSRafal Jaworowski }
234*db5ef4fcSRafal Jaworowski 
235*db5ef4fcSRafal Jaworowski static int
236*db5ef4fcSRafal Jaworowski mv_pcib_attach(device_t self)
237*db5ef4fcSRafal Jaworowski {
238*db5ef4fcSRafal Jaworowski 	struct mv_pcib_softc *sc;
239*db5ef4fcSRafal Jaworowski 	phandle_t node, parnode;
240*db5ef4fcSRafal Jaworowski 	uint32_t val;
241*db5ef4fcSRafal Jaworowski 	int err;
242*db5ef4fcSRafal Jaworowski 
243*db5ef4fcSRafal Jaworowski 	sc = device_get_softc(self);
244*db5ef4fcSRafal Jaworowski 	sc->sc_dev = self;
245*db5ef4fcSRafal Jaworowski 
246*db5ef4fcSRafal Jaworowski 	parnode = OF_parent(ofw_bus_get_node(self));
247*db5ef4fcSRafal Jaworowski 	if (fdt_is_compatible(parnode, "mrvl,pcie")) {
248*db5ef4fcSRafal Jaworowski 		sc->sc_type = MV_TYPE_PCIE;
249*db5ef4fcSRafal Jaworowski 		sc->sc_mem_win_target = MV_WIN_PCIE_MEM_TARGET;
250*db5ef4fcSRafal Jaworowski 		sc->sc_mem_win_attr = MV_WIN_PCIE_MEM_ATTR;
251*db5ef4fcSRafal Jaworowski 		sc->sc_io_win_target = MV_WIN_PCIE_IO_TARGET;
252*db5ef4fcSRafal Jaworowski 		sc->sc_io_win_attr = MV_WIN_PCIE_IO_ATTR;
253*db5ef4fcSRafal Jaworowski #ifdef SOC_MV_ORION
254*db5ef4fcSRafal Jaworowski 	} else if (fdt_is_compatible(parnode, "mrvl,pci")) {
255*db5ef4fcSRafal Jaworowski 		sc->sc_type = MV_TYPE_PCI;
256*db5ef4fcSRafal Jaworowski 		sc->sc_mem_win_target = MV_WIN_PCI_MEM_TARGET;
257*db5ef4fcSRafal Jaworowski 		sc->sc_mem_win_attr = MV_WIN_PCI_MEM_ATTR;
258*db5ef4fcSRafal Jaworowski 		sc->sc_io_win_target = MV_WIN_PCI_IO_TARGET;
259*db5ef4fcSRafal Jaworowski 		sc->sc_io_win_attr = MV_WIN_PCI_IO_ATTR;
260*db5ef4fcSRafal Jaworowski #endif
261*db5ef4fcSRafal Jaworowski 	} else
262*db5ef4fcSRafal Jaworowski 		return (ENXIO);
263*db5ef4fcSRafal Jaworowski 
264*db5ef4fcSRafal Jaworowski 	node = ofw_bus_get_node(self);
265*db5ef4fcSRafal Jaworowski 
266*db5ef4fcSRafal Jaworowski 	/*
267*db5ef4fcSRafal Jaworowski 	 * Get PCI interrupt info.
268*db5ef4fcSRafal Jaworowski 	 */
269*db5ef4fcSRafal Jaworowski 	if (mv_pcib_intr_info(node, sc) != 0) {
270*db5ef4fcSRafal Jaworowski 		device_printf(self, "could not retrieve interrupt info\n");
271*db5ef4fcSRafal Jaworowski 		return (ENXIO);
272*db5ef4fcSRafal Jaworowski 	}
273*db5ef4fcSRafal Jaworowski 
274*db5ef4fcSRafal Jaworowski 	/*
275*db5ef4fcSRafal Jaworowski 	 * Retrieve our mem-mapped registers range.
276*db5ef4fcSRafal Jaworowski 	 */
277*db5ef4fcSRafal Jaworowski 	sc->sc_rid = 0;
278*db5ef4fcSRafal Jaworowski 	sc->sc_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &sc->sc_rid,
279*db5ef4fcSRafal Jaworowski 	    RF_ACTIVE);
280*db5ef4fcSRafal Jaworowski 	if (sc->sc_res == NULL) {
281*db5ef4fcSRafal Jaworowski 		device_printf(self, "could not map memory\n");
282*db5ef4fcSRafal Jaworowski 		return (ENXIO);
283*db5ef4fcSRafal Jaworowski 	}
284*db5ef4fcSRafal Jaworowski 	sc->sc_bst = rman_get_bustag(sc->sc_res);
285*db5ef4fcSRafal Jaworowski 	sc->sc_bsh = rman_get_bushandle(sc->sc_res);
286*db5ef4fcSRafal Jaworowski 
287*db5ef4fcSRafal Jaworowski 	/*
288*db5ef4fcSRafal Jaworowski 	 * Configure decode windows for PCI(E) access.
289*db5ef4fcSRafal Jaworowski 	 */
290*db5ef4fcSRafal Jaworowski 	if (mv_pcib_decode_win(node, sc) != 0)
291*db5ef4fcSRafal Jaworowski 		return (ENXIO);
292*db5ef4fcSRafal Jaworowski 
293*db5ef4fcSRafal Jaworowski 	mv_pcib_hw_cfginit();
294*db5ef4fcSRafal Jaworowski 
295*db5ef4fcSRafal Jaworowski 	/*
296*db5ef4fcSRafal Jaworowski 	 * Enable PCI bridge.
297*db5ef4fcSRafal Jaworowski 	 */
298*db5ef4fcSRafal Jaworowski 	val = mv_pcib_hw_cfgread(sc, sc->sc_busnr, sc->sc_devnr, 0,
299*db5ef4fcSRafal Jaworowski 	    PCIR_COMMAND, 2);
300*db5ef4fcSRafal Jaworowski 	val |= PCIM_CMD_SERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN |
301*db5ef4fcSRafal Jaworowski 	    PCIM_CMD_PORTEN;
302*db5ef4fcSRafal Jaworowski 	mv_pcib_hw_cfgwrite(sc, sc->sc_busnr, sc->sc_devnr, 0,
303*db5ef4fcSRafal Jaworowski 	    PCIR_COMMAND, val, 2);
304*db5ef4fcSRafal Jaworowski 
305*db5ef4fcSRafal Jaworowski 	sc->sc_mem_alloc = sc->sc_mem_base;
306*db5ef4fcSRafal Jaworowski 	sc->sc_io_alloc = sc->sc_io_base;
307*db5ef4fcSRafal Jaworowski 
308*db5ef4fcSRafal Jaworowski 	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
309*db5ef4fcSRafal Jaworowski 	err = rman_init(&sc->sc_mem_rman);
310*db5ef4fcSRafal Jaworowski 	if (err)
311*db5ef4fcSRafal Jaworowski 		return (err);
312*db5ef4fcSRafal Jaworowski 
313*db5ef4fcSRafal Jaworowski 	sc->sc_io_rman.rm_type = RMAN_ARRAY;
314*db5ef4fcSRafal Jaworowski 	err = rman_init(&sc->sc_io_rman);
315*db5ef4fcSRafal Jaworowski 	if (err) {
316*db5ef4fcSRafal Jaworowski 		rman_fini(&sc->sc_mem_rman);
317*db5ef4fcSRafal Jaworowski 		return (err);
318*db5ef4fcSRafal Jaworowski 	}
319*db5ef4fcSRafal Jaworowski 
320*db5ef4fcSRafal Jaworowski 	err = rman_manage_region(&sc->sc_mem_rman, sc->sc_mem_base,
321*db5ef4fcSRafal Jaworowski 	    sc->sc_mem_base + sc->sc_mem_size - 1);
322*db5ef4fcSRafal Jaworowski 	if (err)
323*db5ef4fcSRafal Jaworowski 		goto error;
324*db5ef4fcSRafal Jaworowski 
325*db5ef4fcSRafal Jaworowski 	err = rman_manage_region(&sc->sc_io_rman, sc->sc_io_base,
326*db5ef4fcSRafal Jaworowski 	    sc->sc_io_base + sc->sc_io_size - 1);
327*db5ef4fcSRafal Jaworowski 	if (err)
328*db5ef4fcSRafal Jaworowski 		goto error;
329*db5ef4fcSRafal Jaworowski 
330*db5ef4fcSRafal Jaworowski 	err = mv_pcib_init(sc, sc->sc_busnr, mv_pcib_maxslots(sc->sc_dev));
331*db5ef4fcSRafal Jaworowski 	if (err)
332*db5ef4fcSRafal Jaworowski 		goto error;
333*db5ef4fcSRafal Jaworowski 
334*db5ef4fcSRafal Jaworowski 	device_add_child(self, "pci", -1);
335*db5ef4fcSRafal Jaworowski 	return (bus_generic_attach(self));
336*db5ef4fcSRafal Jaworowski 
337*db5ef4fcSRafal Jaworowski error:
338*db5ef4fcSRafal Jaworowski 	/* XXX SYS_RES_ should be released here */
339*db5ef4fcSRafal Jaworowski 	rman_fini(&sc->sc_mem_rman);
340*db5ef4fcSRafal Jaworowski 	rman_fini(&sc->sc_io_rman);
341*db5ef4fcSRafal Jaworowski 	return (err);
342*db5ef4fcSRafal Jaworowski }
343*db5ef4fcSRafal Jaworowski 
344*db5ef4fcSRafal Jaworowski static int
345*db5ef4fcSRafal Jaworowski mv_pcib_init_bar(struct mv_pcib_softc *sc, int bus, int slot, int func,
346*db5ef4fcSRafal Jaworowski     int barno)
347*db5ef4fcSRafal Jaworowski {
348*db5ef4fcSRafal Jaworowski 	bus_addr_t *allocp, limit;
349*db5ef4fcSRafal Jaworowski 	uint32_t addr, bar, mask, size;
350*db5ef4fcSRafal Jaworowski 	int reg, width;
351*db5ef4fcSRafal Jaworowski 
352*db5ef4fcSRafal Jaworowski 	reg = PCIR_BAR(barno);
353*db5ef4fcSRafal Jaworowski 	bar = mv_pcib_read_config(sc->sc_dev, bus, slot, func, reg, 4);
354*db5ef4fcSRafal Jaworowski 	if (bar == 0)
355*db5ef4fcSRafal Jaworowski 		return (1);
356*db5ef4fcSRafal Jaworowski 
357*db5ef4fcSRafal Jaworowski 	/* Calculate BAR size: 64 or 32 bit (in 32-bit units) */
358*db5ef4fcSRafal Jaworowski 	width = ((bar & 7) == 4) ? 2 : 1;
359*db5ef4fcSRafal Jaworowski 
360*db5ef4fcSRafal Jaworowski 	mv_pcib_write_config(sc->sc_dev, bus, slot, func, reg, ~0, 4);
361*db5ef4fcSRafal Jaworowski 	size = mv_pcib_read_config(sc->sc_dev, bus, slot, func, reg, 4);
362*db5ef4fcSRafal Jaworowski 
363*db5ef4fcSRafal Jaworowski 	/* Get BAR type and size */
364*db5ef4fcSRafal Jaworowski 	if (bar & 1) {
365*db5ef4fcSRafal Jaworowski 		/* I/O port */
366*db5ef4fcSRafal Jaworowski 		allocp = &sc->sc_io_alloc;
367*db5ef4fcSRafal Jaworowski 		limit = sc->sc_io_base + sc->sc_io_size;
368*db5ef4fcSRafal Jaworowski 		size &= ~0x3;
369*db5ef4fcSRafal Jaworowski 		if ((size & 0xffff0000) == 0)
370*db5ef4fcSRafal Jaworowski 			size |= 0xffff0000;
371*db5ef4fcSRafal Jaworowski 	} else {
372*db5ef4fcSRafal Jaworowski 		/* Memory */
373*db5ef4fcSRafal Jaworowski 		allocp = &sc->sc_mem_alloc;
374*db5ef4fcSRafal Jaworowski 		limit = sc->sc_mem_base + sc->sc_mem_size;
375*db5ef4fcSRafal Jaworowski 		size &= ~0xF;
376*db5ef4fcSRafal Jaworowski 	}
377*db5ef4fcSRafal Jaworowski 	mask = ~size;
378*db5ef4fcSRafal Jaworowski 	size = mask + 1;
379*db5ef4fcSRafal Jaworowski 
380*db5ef4fcSRafal Jaworowski 	/* Sanity check (must be a power of 2) */
381*db5ef4fcSRafal Jaworowski 	if (size & mask)
382*db5ef4fcSRafal Jaworowski 		return (width);
383*db5ef4fcSRafal Jaworowski 
384*db5ef4fcSRafal Jaworowski 	addr = (*allocp + mask) & ~mask;
385*db5ef4fcSRafal Jaworowski 	if ((*allocp = addr + size) > limit)
386*db5ef4fcSRafal Jaworowski 		return (-1);
387*db5ef4fcSRafal Jaworowski 
388*db5ef4fcSRafal Jaworowski 	if (bootverbose)
389*db5ef4fcSRafal Jaworowski 		printf("PCI %u:%u:%u: reg %x: size=%08x: addr=%08x\n",
390*db5ef4fcSRafal Jaworowski 		    bus, slot, func, reg, size, addr);
391*db5ef4fcSRafal Jaworowski 
392*db5ef4fcSRafal Jaworowski 	mv_pcib_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4);
393*db5ef4fcSRafal Jaworowski 	if (width == 2)
394*db5ef4fcSRafal Jaworowski 		mv_pcib_write_config(sc->sc_dev, bus, slot, func, reg + 4,
395*db5ef4fcSRafal Jaworowski 		    0, 4);
396*db5ef4fcSRafal Jaworowski 
397*db5ef4fcSRafal Jaworowski 	return (width);
3986975124cSRafal Jaworowski }
3996975124cSRafal Jaworowski 
4006975124cSRafal Jaworowski static void
401*db5ef4fcSRafal Jaworowski mv_pcib_init_bridge(struct mv_pcib_softc *sc, int bus, int slot, int func)
402*db5ef4fcSRafal Jaworowski {
403*db5ef4fcSRafal Jaworowski 	bus_addr_t io_base, mem_base;
404*db5ef4fcSRafal Jaworowski 	uint32_t io_limit, mem_limit;
405*db5ef4fcSRafal Jaworowski 	int secbus;
406*db5ef4fcSRafal Jaworowski 
407*db5ef4fcSRafal Jaworowski 	io_base = sc->sc_io_base;
408*db5ef4fcSRafal Jaworowski 	io_limit = io_base + sc->sc_io_size - 1;
409*db5ef4fcSRafal Jaworowski 	mem_base = sc->sc_mem_base;
410*db5ef4fcSRafal Jaworowski 	mem_limit = mem_base + sc->sc_mem_size - 1;
411*db5ef4fcSRafal Jaworowski 
412*db5ef4fcSRafal Jaworowski 	/* Configure I/O decode registers */
413*db5ef4fcSRafal Jaworowski 	mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_IOBASEL_1,
414*db5ef4fcSRafal Jaworowski 	    io_base >> 8, 1);
415*db5ef4fcSRafal Jaworowski 	mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_IOBASEH_1,
416*db5ef4fcSRafal Jaworowski 	    io_base >> 16, 2);
417*db5ef4fcSRafal Jaworowski 	mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_IOLIMITL_1,
418*db5ef4fcSRafal Jaworowski 	    io_limit >> 8, 1);
419*db5ef4fcSRafal Jaworowski 	mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_IOLIMITH_1,
420*db5ef4fcSRafal Jaworowski 	    io_limit >> 16, 2);
421*db5ef4fcSRafal Jaworowski 
422*db5ef4fcSRafal Jaworowski 	/* Configure memory decode registers */
423*db5ef4fcSRafal Jaworowski 	mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_MEMBASE_1,
424*db5ef4fcSRafal Jaworowski 	    mem_base >> 16, 2);
425*db5ef4fcSRafal Jaworowski 	mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_MEMLIMIT_1,
426*db5ef4fcSRafal Jaworowski 	    mem_limit >> 16, 2);
427*db5ef4fcSRafal Jaworowski 
428*db5ef4fcSRafal Jaworowski 	/* Disable memory prefetch decode */
429*db5ef4fcSRafal Jaworowski 	mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_PMBASEL_1,
430*db5ef4fcSRafal Jaworowski 	    0x10, 2);
431*db5ef4fcSRafal Jaworowski 	mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_PMBASEH_1,
432*db5ef4fcSRafal Jaworowski 	    0x0, 4);
433*db5ef4fcSRafal Jaworowski 	mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_PMLIMITL_1,
434*db5ef4fcSRafal Jaworowski 	    0xF, 2);
435*db5ef4fcSRafal Jaworowski 	mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_PMLIMITH_1,
436*db5ef4fcSRafal Jaworowski 	    0x0, 4);
437*db5ef4fcSRafal Jaworowski 
438*db5ef4fcSRafal Jaworowski 	secbus = mv_pcib_read_config(sc->sc_dev, bus, slot, func,
439*db5ef4fcSRafal Jaworowski 	    PCIR_SECBUS_1, 1);
440*db5ef4fcSRafal Jaworowski 
441*db5ef4fcSRafal Jaworowski 	/* Configure buses behind the bridge */
442*db5ef4fcSRafal Jaworowski 	mv_pcib_init(sc, secbus, PCI_SLOTMAX);
443*db5ef4fcSRafal Jaworowski }
444*db5ef4fcSRafal Jaworowski 
445*db5ef4fcSRafal Jaworowski static int
446*db5ef4fcSRafal Jaworowski mv_pcib_init(struct mv_pcib_softc *sc, int bus, int maxslot)
447*db5ef4fcSRafal Jaworowski {
448*db5ef4fcSRafal Jaworowski 	int slot, func, maxfunc, error;
449*db5ef4fcSRafal Jaworowski 	uint8_t hdrtype, command, class, subclass;
450*db5ef4fcSRafal Jaworowski 
451*db5ef4fcSRafal Jaworowski 	for (slot = 0; slot <= maxslot; slot++) {
452*db5ef4fcSRafal Jaworowski 		maxfunc = 0;
453*db5ef4fcSRafal Jaworowski 		for (func = 0; func <= maxfunc; func++) {
454*db5ef4fcSRafal Jaworowski 			hdrtype = mv_pcib_read_config(sc->sc_dev, bus, slot,
455*db5ef4fcSRafal Jaworowski 			    func, PCIR_HDRTYPE, 1);
456*db5ef4fcSRafal Jaworowski 
457*db5ef4fcSRafal Jaworowski 			if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
458*db5ef4fcSRafal Jaworowski 				continue;
459*db5ef4fcSRafal Jaworowski 
460*db5ef4fcSRafal Jaworowski 			if (func == 0 && (hdrtype & PCIM_MFDEV))
461*db5ef4fcSRafal Jaworowski 				maxfunc = PCI_FUNCMAX;
462*db5ef4fcSRafal Jaworowski 
463*db5ef4fcSRafal Jaworowski 			command = mv_pcib_read_config(sc->sc_dev, bus, slot,
464*db5ef4fcSRafal Jaworowski 			    func, PCIR_COMMAND, 1);
465*db5ef4fcSRafal Jaworowski 			command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN);
466*db5ef4fcSRafal Jaworowski 			mv_pcib_write_config(sc->sc_dev, bus, slot, func,
467*db5ef4fcSRafal Jaworowski 			    PCIR_COMMAND, command, 1);
468*db5ef4fcSRafal Jaworowski 
469*db5ef4fcSRafal Jaworowski 			error = mv_pcib_init_all_bars(sc, bus, slot, func,
470*db5ef4fcSRafal Jaworowski 			    hdrtype);
471*db5ef4fcSRafal Jaworowski 
472*db5ef4fcSRafal Jaworowski 			if (error)
473*db5ef4fcSRafal Jaworowski 				return (error);
474*db5ef4fcSRafal Jaworowski 
475*db5ef4fcSRafal Jaworowski 			command |= PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN |
476*db5ef4fcSRafal Jaworowski 			    PCIM_CMD_PORTEN;
477*db5ef4fcSRafal Jaworowski 			mv_pcib_write_config(sc->sc_dev, bus, slot, func,
478*db5ef4fcSRafal Jaworowski 			    PCIR_COMMAND, command, 1);
479*db5ef4fcSRafal Jaworowski 
480*db5ef4fcSRafal Jaworowski 			/* Handle PCI-PCI bridges */
481*db5ef4fcSRafal Jaworowski 			class = mv_pcib_read_config(sc->sc_dev, bus, slot,
482*db5ef4fcSRafal Jaworowski 			    func, PCIR_CLASS, 1);
483*db5ef4fcSRafal Jaworowski 			subclass = mv_pcib_read_config(sc->sc_dev, bus, slot,
484*db5ef4fcSRafal Jaworowski 			    func, PCIR_SUBCLASS, 1);
485*db5ef4fcSRafal Jaworowski 
486*db5ef4fcSRafal Jaworowski 			if (class != PCIC_BRIDGE ||
487*db5ef4fcSRafal Jaworowski 			    subclass != PCIS_BRIDGE_PCI)
488*db5ef4fcSRafal Jaworowski 				continue;
489*db5ef4fcSRafal Jaworowski 
490*db5ef4fcSRafal Jaworowski 			mv_pcib_init_bridge(sc, bus, slot, func);
491*db5ef4fcSRafal Jaworowski 		}
492*db5ef4fcSRafal Jaworowski 	}
493*db5ef4fcSRafal Jaworowski 
494*db5ef4fcSRafal Jaworowski 	/* Enable all ABCD interrupts */
495*db5ef4fcSRafal Jaworowski 	pcib_write_irq_mask(sc, (0xF << 24));
496*db5ef4fcSRafal Jaworowski 
497*db5ef4fcSRafal Jaworowski 	return (0);
498*db5ef4fcSRafal Jaworowski }
499*db5ef4fcSRafal Jaworowski 
500*db5ef4fcSRafal Jaworowski static int
501*db5ef4fcSRafal Jaworowski mv_pcib_init_all_bars(struct mv_pcib_softc *sc, int bus, int slot,
502*db5ef4fcSRafal Jaworowski     int func, int hdrtype)
503*db5ef4fcSRafal Jaworowski {
504*db5ef4fcSRafal Jaworowski 	int maxbar, bar, i;
505*db5ef4fcSRafal Jaworowski 
506*db5ef4fcSRafal Jaworowski 	maxbar = (hdrtype & PCIM_HDRTYPE) ? 0 : 6;
507*db5ef4fcSRafal Jaworowski 	bar = 0;
508*db5ef4fcSRafal Jaworowski 
509*db5ef4fcSRafal Jaworowski 	/* Program the base address registers */
510*db5ef4fcSRafal Jaworowski 	while (bar < maxbar) {
511*db5ef4fcSRafal Jaworowski 		i = mv_pcib_init_bar(sc, bus, slot, func, bar);
512*db5ef4fcSRafal Jaworowski 		bar += i;
513*db5ef4fcSRafal Jaworowski 		if (i < 0) {
514*db5ef4fcSRafal Jaworowski 			device_printf(sc->sc_dev,
515*db5ef4fcSRafal Jaworowski 			    "PCI IO/Memory space exhausted\n");
516*db5ef4fcSRafal Jaworowski 			return (ENOMEM);
517*db5ef4fcSRafal Jaworowski 		}
518*db5ef4fcSRafal Jaworowski 	}
519*db5ef4fcSRafal Jaworowski 
520*db5ef4fcSRafal Jaworowski 	return (0);
521*db5ef4fcSRafal Jaworowski }
522*db5ef4fcSRafal Jaworowski 
523*db5ef4fcSRafal Jaworowski static struct resource *
524*db5ef4fcSRafal Jaworowski mv_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
525*db5ef4fcSRafal Jaworowski     u_long start, u_long end, u_long count, u_int flags)
526*db5ef4fcSRafal Jaworowski {
527*db5ef4fcSRafal Jaworowski 	struct mv_pcib_softc *sc = device_get_softc(dev);
528*db5ef4fcSRafal Jaworowski 	struct rman *rm = NULL;
529*db5ef4fcSRafal Jaworowski 	struct resource *res;
530*db5ef4fcSRafal Jaworowski 
531*db5ef4fcSRafal Jaworowski 	switch (type) {
532*db5ef4fcSRafal Jaworowski 	case SYS_RES_IOPORT:
533*db5ef4fcSRafal Jaworowski 		rm = &sc->sc_io_rman;
534*db5ef4fcSRafal Jaworowski 		break;
535*db5ef4fcSRafal Jaworowski 	case SYS_RES_MEMORY:
536*db5ef4fcSRafal Jaworowski 		rm = &sc->sc_mem_rman;
537*db5ef4fcSRafal Jaworowski 		break;
538*db5ef4fcSRafal Jaworowski 	default:
539*db5ef4fcSRafal Jaworowski 		return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
540*db5ef4fcSRafal Jaworowski 		    type, rid, start, end, count, flags));
541*db5ef4fcSRafal Jaworowski 	};
542*db5ef4fcSRafal Jaworowski 
543*db5ef4fcSRafal Jaworowski 	res = rman_reserve_resource(rm, start, end, count, flags, child);
544*db5ef4fcSRafal Jaworowski 	if (res == NULL)
545*db5ef4fcSRafal Jaworowski 		return (NULL);
546*db5ef4fcSRafal Jaworowski 
547*db5ef4fcSRafal Jaworowski 	rman_set_rid(res, *rid);
548*db5ef4fcSRafal Jaworowski 	rman_set_bustag(res, fdtbus_bs_tag);
549*db5ef4fcSRafal Jaworowski 	rman_set_bushandle(res, start);
550*db5ef4fcSRafal Jaworowski 
551*db5ef4fcSRafal Jaworowski 	if (flags & RF_ACTIVE)
552*db5ef4fcSRafal Jaworowski 		if (bus_activate_resource(child, type, *rid, res)) {
553*db5ef4fcSRafal Jaworowski 			rman_release_resource(res);
554*db5ef4fcSRafal Jaworowski 			return (NULL);
555*db5ef4fcSRafal Jaworowski 		}
556*db5ef4fcSRafal Jaworowski 
557*db5ef4fcSRafal Jaworowski 	return (res);
558*db5ef4fcSRafal Jaworowski }
559*db5ef4fcSRafal Jaworowski 
560*db5ef4fcSRafal Jaworowski static int
561*db5ef4fcSRafal Jaworowski mv_pcib_release_resource(device_t dev, device_t child, int type, int rid,
562*db5ef4fcSRafal Jaworowski     struct resource *res)
563*db5ef4fcSRafal Jaworowski {
564*db5ef4fcSRafal Jaworowski 
565*db5ef4fcSRafal Jaworowski 	if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY)
566*db5ef4fcSRafal Jaworowski 		return (BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
567*db5ef4fcSRafal Jaworowski 		    type, rid, res));
568*db5ef4fcSRafal Jaworowski 
569*db5ef4fcSRafal Jaworowski 	return (rman_release_resource(res));
570*db5ef4fcSRafal Jaworowski }
571*db5ef4fcSRafal Jaworowski 
572*db5ef4fcSRafal Jaworowski static int
573*db5ef4fcSRafal Jaworowski mv_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
574*db5ef4fcSRafal Jaworowski {
575*db5ef4fcSRafal Jaworowski 	struct mv_pcib_softc *sc = device_get_softc(dev);
576*db5ef4fcSRafal Jaworowski 
577*db5ef4fcSRafal Jaworowski 	switch (which) {
578*db5ef4fcSRafal Jaworowski 	case PCIB_IVAR_BUS:
579*db5ef4fcSRafal Jaworowski 		*result = sc->sc_busnr;
580*db5ef4fcSRafal Jaworowski 		return (0);
581*db5ef4fcSRafal Jaworowski 	case PCIB_IVAR_DOMAIN:
582*db5ef4fcSRafal Jaworowski 		*result = device_get_unit(dev);
583*db5ef4fcSRafal Jaworowski 		return (0);
584*db5ef4fcSRafal Jaworowski 	}
585*db5ef4fcSRafal Jaworowski 
586*db5ef4fcSRafal Jaworowski 	return (ENOENT);
587*db5ef4fcSRafal Jaworowski }
588*db5ef4fcSRafal Jaworowski 
589*db5ef4fcSRafal Jaworowski static int
590*db5ef4fcSRafal Jaworowski mv_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
591*db5ef4fcSRafal Jaworowski {
592*db5ef4fcSRafal Jaworowski 	struct mv_pcib_softc *sc = device_get_softc(dev);
593*db5ef4fcSRafal Jaworowski 
594*db5ef4fcSRafal Jaworowski 	switch (which) {
595*db5ef4fcSRafal Jaworowski 	case PCIB_IVAR_BUS:
596*db5ef4fcSRafal Jaworowski 		sc->sc_busnr = value;
597*db5ef4fcSRafal Jaworowski 		return (0);
598*db5ef4fcSRafal Jaworowski 	}
599*db5ef4fcSRafal Jaworowski 
600*db5ef4fcSRafal Jaworowski 	return (ENOENT);
601*db5ef4fcSRafal Jaworowski }
602*db5ef4fcSRafal Jaworowski 
603*db5ef4fcSRafal Jaworowski static inline void
604*db5ef4fcSRafal Jaworowski pcib_write_irq_mask(struct mv_pcib_softc *sc, uint32_t mask)
605*db5ef4fcSRafal Jaworowski {
606*db5ef4fcSRafal Jaworowski 
607*db5ef4fcSRafal Jaworowski 	if (!sc->sc_type != MV_TYPE_PCI)
608*db5ef4fcSRafal Jaworowski 		return;
609*db5ef4fcSRafal Jaworowski 
610*db5ef4fcSRafal Jaworowski 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, PCIE_REG_IRQ_MASK, mask);
611*db5ef4fcSRafal Jaworowski }
612*db5ef4fcSRafal Jaworowski 
613*db5ef4fcSRafal Jaworowski static void
614*db5ef4fcSRafal Jaworowski mv_pcib_hw_cfginit(void)
6156975124cSRafal Jaworowski {
6166975124cSRafal Jaworowski 	static int opened = 0;
6176975124cSRafal Jaworowski 
6186975124cSRafal Jaworowski 	if (opened)
6196975124cSRafal Jaworowski 		return;
6206975124cSRafal Jaworowski 
6216975124cSRafal Jaworowski 	mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN);
6226975124cSRafal Jaworowski 	opened = 1;
6236975124cSRafal Jaworowski }
6246975124cSRafal Jaworowski 
6256975124cSRafal Jaworowski static uint32_t
626*db5ef4fcSRafal Jaworowski mv_pcib_hw_cfgread(struct mv_pcib_softc *sc, u_int bus, u_int slot,
6276975124cSRafal Jaworowski     u_int func, u_int reg, int bytes)
6286975124cSRafal Jaworowski {
6296975124cSRafal Jaworowski 	uint32_t addr, data, ca, cd;
6306975124cSRafal Jaworowski 
631*db5ef4fcSRafal Jaworowski 	ca = (sc->sc_type != MV_TYPE_PCI) ?
6326975124cSRafal Jaworowski 	    PCIE_REG_CFG_ADDR : PCI_REG_CFG_ADDR;
633*db5ef4fcSRafal Jaworowski 	cd = (sc->sc_type != MV_TYPE_PCI) ?
6346975124cSRafal Jaworowski 	    PCIE_REG_CFG_DATA : PCI_REG_CFG_DATA;
6356975124cSRafal Jaworowski 	addr = PCI_CFG_ENA | PCI_CFG_BUS(bus) | PCI_CFG_DEV(slot) |
6366975124cSRafal Jaworowski 	    PCI_CFG_FUN(func) | PCI_CFG_PCIE_REG(reg);
6376975124cSRafal Jaworowski 
6386975124cSRafal Jaworowski 	mtx_lock_spin(&pcicfg_mtx);
6396975124cSRafal Jaworowski 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, ca, addr);
6406975124cSRafal Jaworowski 
6416975124cSRafal Jaworowski 	data = ~0;
6426975124cSRafal Jaworowski 	switch (bytes) {
6436975124cSRafal Jaworowski 	case 1:
6446975124cSRafal Jaworowski 		data = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
6456975124cSRafal Jaworowski 		    cd + (reg & 3));
6466975124cSRafal Jaworowski 		break;
6476975124cSRafal Jaworowski 	case 2:
6486975124cSRafal Jaworowski 		data = le16toh(bus_space_read_2(sc->sc_bst, sc->sc_bsh,
6496975124cSRafal Jaworowski 		    cd + (reg & 2)));
6506975124cSRafal Jaworowski 		break;
6516975124cSRafal Jaworowski 	case 4:
6526975124cSRafal Jaworowski 		data = le32toh(bus_space_read_4(sc->sc_bst, sc->sc_bsh,
6536975124cSRafal Jaworowski 		    cd));
6546975124cSRafal Jaworowski 		break;
6556975124cSRafal Jaworowski 	}
6566975124cSRafal Jaworowski 	mtx_unlock_spin(&pcicfg_mtx);
6576975124cSRafal Jaworowski 	return (data);
6586975124cSRafal Jaworowski }
6596975124cSRafal Jaworowski 
6606975124cSRafal Jaworowski static void
661*db5ef4fcSRafal Jaworowski mv_pcib_hw_cfgwrite(struct mv_pcib_softc *sc, u_int bus, u_int slot,
6626975124cSRafal Jaworowski     u_int func, u_int reg, uint32_t data, int bytes)
6636975124cSRafal Jaworowski {
6646975124cSRafal Jaworowski 	uint32_t addr, ca, cd;
6656975124cSRafal Jaworowski 
666*db5ef4fcSRafal Jaworowski 	ca = (sc->sc_type != MV_TYPE_PCI) ?
6676975124cSRafal Jaworowski 	    PCIE_REG_CFG_ADDR : PCI_REG_CFG_ADDR;
668*db5ef4fcSRafal Jaworowski 	cd = (sc->sc_type != MV_TYPE_PCI) ?
6696975124cSRafal Jaworowski 	    PCIE_REG_CFG_DATA : PCI_REG_CFG_DATA;
6706975124cSRafal Jaworowski 	addr = PCI_CFG_ENA | PCI_CFG_BUS(bus) | PCI_CFG_DEV(slot) |
6716975124cSRafal Jaworowski 	    PCI_CFG_FUN(func) | PCI_CFG_PCIE_REG(reg);
6726975124cSRafal Jaworowski 
6736975124cSRafal Jaworowski 	mtx_lock_spin(&pcicfg_mtx);
6746975124cSRafal Jaworowski 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, ca, addr);
6756975124cSRafal Jaworowski 
6766975124cSRafal Jaworowski 	switch (bytes) {
6776975124cSRafal Jaworowski 	case 1:
6786975124cSRafal Jaworowski 		bus_space_write_1(sc->sc_bst, sc->sc_bsh,
6796975124cSRafal Jaworowski 		    cd + (reg & 3), data);
6806975124cSRafal Jaworowski 		break;
6816975124cSRafal Jaworowski 	case 2:
6826975124cSRafal Jaworowski 		bus_space_write_2(sc->sc_bst, sc->sc_bsh,
6836975124cSRafal Jaworowski 		    cd + (reg & 2), htole16(data));
6846975124cSRafal Jaworowski 		break;
6856975124cSRafal Jaworowski 	case 4:
6866975124cSRafal Jaworowski 		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
6876975124cSRafal Jaworowski 		    cd, htole32(data));
6886975124cSRafal Jaworowski 		break;
6896975124cSRafal Jaworowski 	}
6906975124cSRafal Jaworowski 	mtx_unlock_spin(&pcicfg_mtx);
6916975124cSRafal Jaworowski }
6926975124cSRafal Jaworowski 
6936975124cSRafal Jaworowski static int
694*db5ef4fcSRafal Jaworowski mv_pcib_maxslots(device_t dev)
6956975124cSRafal Jaworowski {
696*db5ef4fcSRafal Jaworowski 	struct mv_pcib_softc *sc = device_get_softc(dev);
6976975124cSRafal Jaworowski 
698*db5ef4fcSRafal Jaworowski 	return ((sc->sc_type != MV_TYPE_PCI) ? 1 : PCI_SLOTMAX);
6996975124cSRafal Jaworowski }
7006975124cSRafal Jaworowski 
7016975124cSRafal Jaworowski static uint32_t
702*db5ef4fcSRafal Jaworowski mv_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func,
7036975124cSRafal Jaworowski     u_int reg, int bytes)
7046975124cSRafal Jaworowski {
705*db5ef4fcSRafal Jaworowski 	struct mv_pcib_softc *sc = device_get_softc(dev);
7066975124cSRafal Jaworowski 
7076975124cSRafal Jaworowski 	/* Skip self */
7086975124cSRafal Jaworowski 	if (bus == sc->sc_busnr && slot == sc->sc_devnr)
7096975124cSRafal Jaworowski 		return (~0U);
7106975124cSRafal Jaworowski 
711*db5ef4fcSRafal Jaworowski 	return (mv_pcib_hw_cfgread(sc, bus, slot, func, reg, bytes));
7126975124cSRafal Jaworowski }
7136975124cSRafal Jaworowski 
7146975124cSRafal Jaworowski static void
715*db5ef4fcSRafal Jaworowski mv_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func,
7166975124cSRafal Jaworowski     u_int reg, uint32_t val, int bytes)
7176975124cSRafal Jaworowski {
718*db5ef4fcSRafal Jaworowski 	struct mv_pcib_softc *sc = device_get_softc(dev);
7196975124cSRafal Jaworowski 
7206975124cSRafal Jaworowski 	/* Skip self */
7216975124cSRafal Jaworowski 	if (bus == sc->sc_busnr && slot == sc->sc_devnr)
7226975124cSRafal Jaworowski 		return;
7236975124cSRafal Jaworowski 
724*db5ef4fcSRafal Jaworowski 	mv_pcib_hw_cfgwrite(sc, bus, slot, func, reg, val, bytes);
7256975124cSRafal Jaworowski }
7266975124cSRafal Jaworowski 
727*db5ef4fcSRafal Jaworowski static int
728*db5ef4fcSRafal Jaworowski mv_pcib_route_interrupt(device_t pcib, device_t dev, int pin)
7296975124cSRafal Jaworowski {
730*db5ef4fcSRafal Jaworowski 	struct mv_pcib_softc *sc;
731*db5ef4fcSRafal Jaworowski 	int err, interrupt;
732*db5ef4fcSRafal Jaworowski 
733*db5ef4fcSRafal Jaworowski 	sc = device_get_softc(pcib);
734*db5ef4fcSRafal Jaworowski 
735*db5ef4fcSRafal Jaworowski 	err = fdt_pci_route_intr(pci_get_bus(dev), pci_get_slot(dev),
736*db5ef4fcSRafal Jaworowski 	    pci_get_function(dev), pin, &sc->sc_intr_info, &interrupt);
737*db5ef4fcSRafal Jaworowski 	if (err == 0)
738*db5ef4fcSRafal Jaworowski 		return (interrupt);
739*db5ef4fcSRafal Jaworowski 
740*db5ef4fcSRafal Jaworowski 	device_printf(pcib, "could not route pin %d for device %d.%d\n",
741*db5ef4fcSRafal Jaworowski 	    pin, pci_get_slot(dev), pci_get_function(dev));
742*db5ef4fcSRafal Jaworowski 	return (PCI_INVALID_IRQ);
743*db5ef4fcSRafal Jaworowski }
744*db5ef4fcSRafal Jaworowski 
745*db5ef4fcSRafal Jaworowski static int
746*db5ef4fcSRafal Jaworowski mv_pcib_decode_win(phandle_t node, struct mv_pcib_softc *sc)
747*db5ef4fcSRafal Jaworowski {
748*db5ef4fcSRafal Jaworowski 	struct fdt_pci_range io_space, mem_space;
749*db5ef4fcSRafal Jaworowski 	device_t dev;
7506975124cSRafal Jaworowski 	int error;
7516975124cSRafal Jaworowski 
752*db5ef4fcSRafal Jaworowski 	dev = sc->sc_dev;
753*db5ef4fcSRafal Jaworowski 
754*db5ef4fcSRafal Jaworowski 	if ((error = fdt_pci_ranges(node, &io_space, &mem_space)) != 0) {
755*db5ef4fcSRafal Jaworowski 		device_printf(dev, "could not retrieve 'ranges' data\n");
756*db5ef4fcSRafal Jaworowski 		return (error);
757*db5ef4fcSRafal Jaworowski 	}
758*db5ef4fcSRafal Jaworowski 
7596975124cSRafal Jaworowski 	/* Configure CPU decoding windows */
760*db5ef4fcSRafal Jaworowski 	error = decode_win_cpu_set(sc->sc_io_win_target,
761*db5ef4fcSRafal Jaworowski 	    sc->sc_io_win_attr, io_space.base_parent, io_space.len, -1);
7626975124cSRafal Jaworowski 	if (error < 0) {
763*db5ef4fcSRafal Jaworowski 		device_printf(dev, "could not set up CPU decode "
7646975124cSRafal Jaworowski 		    "window for PCI IO\n");
765*db5ef4fcSRafal Jaworowski 		return (ENXIO);
7666975124cSRafal Jaworowski 	}
767*db5ef4fcSRafal Jaworowski 	error = decode_win_cpu_set(sc->sc_mem_win_target,
768*db5ef4fcSRafal Jaworowski 	    sc->sc_mem_win_attr, mem_space.base_parent, mem_space.len, -1);
7696975124cSRafal Jaworowski 	if (error < 0) {
770*db5ef4fcSRafal Jaworowski 		device_printf(dev, "could not set up CPU decode "
7716975124cSRafal Jaworowski 		    "windows for PCI MEM\n");
772*db5ef4fcSRafal Jaworowski 		return (ENXIO);
7736975124cSRafal Jaworowski 	}
7746975124cSRafal Jaworowski 
775*db5ef4fcSRafal Jaworowski 	sc->sc_io_base = io_space.base_parent;
776*db5ef4fcSRafal Jaworowski 	sc->sc_io_size = io_space.len;
777*db5ef4fcSRafal Jaworowski 
778*db5ef4fcSRafal Jaworowski 	sc->sc_mem_base = mem_space.base_parent;
779*db5ef4fcSRafal Jaworowski 	sc->sc_mem_size = mem_space.len;
780*db5ef4fcSRafal Jaworowski 
781*db5ef4fcSRafal Jaworowski 	return (0);
7826975124cSRafal Jaworowski }
7836975124cSRafal Jaworowski 
784*db5ef4fcSRafal Jaworowski static int
785*db5ef4fcSRafal Jaworowski mv_pcib_intr_info(phandle_t node, struct mv_pcib_softc *sc)
7866975124cSRafal Jaworowski {
787*db5ef4fcSRafal Jaworowski 	int error;
7886975124cSRafal Jaworowski 
789*db5ef4fcSRafal Jaworowski 	if ((error = fdt_pci_intr_info(node, &sc->sc_intr_info)) != 0)
790*db5ef4fcSRafal Jaworowski 		return (error);
7916975124cSRafal Jaworowski 
792*db5ef4fcSRafal Jaworowski 	return (0);
7936975124cSRafal Jaworowski }
7946975124cSRafal Jaworowski 
795*db5ef4fcSRafal Jaworowski #if 0
7966975124cSRafal Jaworowski 		control = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
7976975124cSRafal Jaworowski 		    PCIE_REG_CONTROL);
7986975124cSRafal Jaworowski 
7996975124cSRafal Jaworowski 		/*
8006975124cSRafal Jaworowski 		 * If this PCI-E port (controller) is configured (by the
8016975124cSRafal Jaworowski 		 * underlying firmware) with lane width other than 1x, there
8026975124cSRafal Jaworowski 		 * are auxiliary resources defined for aggregating more width
8036975124cSRafal Jaworowski 		 * on our lane. Skip all such entries as they are not
8046975124cSRafal Jaworowski 		 * standalone ports and must not have a device object
8056975124cSRafal Jaworowski 		 * instantiated.
8066975124cSRafal Jaworowski 		 */
8076975124cSRafal Jaworowski 		if ((control & PCIE_CTRL_LINK1X) == 0)
8086975124cSRafal Jaworowski 			while (info->op_base &&
8096975124cSRafal Jaworowski 			    info->op_type == MV_TYPE_PCIE_AGGR_LANE)
8106975124cSRafal Jaworowski 				info++;
8116975124cSRafal Jaworowski 
812*db5ef4fcSRafal Jaworowski 		mv_pcib_add_child(driver, parent, sc);
813*db5ef4fcSRafal Jaworowski #endif
814