mv_pci.c revision 240489
190075Sobrien/*-
290075Sobrien * Copyright (c) 2008 MARVELL INTERNATIONAL LTD.
390075Sobrien * Copyright (c) 2010 The FreeBSD Foundation
490075Sobrien * Copyright (c) 2010-2012 Semihalf
590075Sobrien * All rights reserved.
690075Sobrien *
790075Sobrien * Developed by Semihalf.
890075Sobrien *
990075Sobrien * Portions of this software were developed by Semihalf
1090075Sobrien * under sponsorship from the FreeBSD Foundation.
1190075Sobrien *
1290075Sobrien * Redistribution and use in source and binary forms, with or without
1390075Sobrien * modification, are permitted provided that the following conditions
1490075Sobrien * are met:
1590075Sobrien * 1. Redistributions of source code must retain the above copyright
1690075Sobrien *    notice, this list of conditions and the following disclaimer.
1790075Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1890075Sobrien *    notice, this list of conditions and the following disclaimer in the
1990075Sobrien *    documentation and/or other materials provided with the distribution.
2090075Sobrien * 3. Neither the name of MARVELL nor the names of contributors
2190075Sobrien *    may be used to endorse or promote products derived from this software
2290075Sobrien *    without specific prior written permission.
2390075Sobrien *
2490075Sobrien * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2590075Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2690075Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2790075Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
2890075Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2990075Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3090075Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3190075Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3290075Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3390075Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3490075Sobrien * SUCH DAMAGE.
3590075Sobrien */
3690075Sobrien
3790075Sobrien/*
3890075Sobrien * Marvell integrated PCI/PCI-Express controller driver.
3990075Sobrien */
4090075Sobrien
41117395Skan#include <sys/cdefs.h>
42117395Skan__FBSDID("$FreeBSD: head/sys/arm/mv/mv_pci.c 240489 2012-09-14 09:57:41Z gber $");
43117395Skan
44117395Skan#include <sys/param.h>
45117395Skan#include <sys/systm.h>
46117395Skan#include <sys/kernel.h>
4790075Sobrien#include <sys/lock.h>
4890075Sobrien#include <sys/malloc.h>
49117395Skan#include <sys/module.h>
50117395Skan#include <sys/mutex.h>
5190075Sobrien#include <sys/queue.h>
5290075Sobrien#include <sys/bus.h>
5390075Sobrien#include <sys/rman.h>
5490075Sobrien#include <sys/endian.h>
5590075Sobrien
5690075Sobrien#include <vm/vm.h>
5790075Sobrien#include <vm/pmap.h>
5890075Sobrien
5990075Sobrien#include <dev/fdt/fdt_common.h>
6090075Sobrien#include <dev/ofw/ofw_bus.h>
6190075Sobrien#include <dev/ofw/ofw_bus_subr.h>
6290075Sobrien#include <dev/pci/pcivar.h>
6390075Sobrien#include <dev/pci/pcireg.h>
6490075Sobrien#include <dev/pci/pcib_private.h>
6590075Sobrien
6690075Sobrien#include "ofw_bus_if.h"
6790075Sobrien#include "pcib_if.h"
6890075Sobrien
6990075Sobrien#include <machine/resource.h>
7090075Sobrien#include <machine/bus.h>
7190075Sobrien
7290075Sobrien#include <arm/mv/mvreg.h>
7390075Sobrien#include <arm/mv/mvvar.h>
7490075Sobrien#include <arm/mv/mvwin.h>
7590075Sobrien
7690075Sobrien#define PCI_CFG_ENA		(1 << 31)
7790075Sobrien#define PCI_CFG_BUS(bus)	(((bus) & 0xff) << 16)
7890075Sobrien#define PCI_CFG_DEV(dev)	(((dev) & 0x1f) << 11)
7990075Sobrien#define PCI_CFG_FUN(fun)	(((fun) & 0x7) << 8)
8090075Sobrien#define PCI_CFG_PCIE_REG(reg)	((reg) & 0xfc)
8190075Sobrien
8290075Sobrien#define PCI_REG_CFG_ADDR	0x0C78
8390075Sobrien#define PCI_REG_CFG_DATA	0x0C7C
8490075Sobrien#define PCI_REG_P2P_CONF	0x1D14
8590075Sobrien
8690075Sobrien#define PCIE_REG_CFG_ADDR	0x18F8
8790075Sobrien#define PCIE_REG_CFG_DATA	0x18FC
8890075Sobrien#define PCIE_REG_CONTROL	0x1A00
8990075Sobrien#define   PCIE_CTRL_LINK1X	0x00000001
9090075Sobrien#define PCIE_REG_STATUS		0x1A04
9190075Sobrien#define PCIE_REG_IRQ_MASK	0x1910
9290075Sobrien
9390075Sobrien#define PCIE_CONTROL_ROOT_CMPLX	(1 << 1)
9490075Sobrien#define PCIE_CONTROL_HOT_RESET	(1 << 24)
9590075Sobrien
9690075Sobrien#define PCIE_LINK_TIMEOUT	1000000
9790075Sobrien
9890075Sobrien#define PCIE_STATUS_LINK_DOWN	1
9990075Sobrien#define PCIE_STATUS_DEV_OFFS	16
10090075Sobrien
10190075Sobrien/* Minimum PCI Memory and I/O allocations taken from PCI spec (in bytes) */
10290075Sobrien#define PCI_MIN_IO_ALLOC	4
10390075Sobrien#define PCI_MIN_MEM_ALLOC	16
10490075Sobrien
10590075Sobrien#define BITS_PER_UINT32		(NBBY * sizeof(uint32_t))
10690075Sobrien
10790075Sobrienstruct mv_pcib_softc {
10890075Sobrien	device_t	sc_dev;
10990075Sobrien
11090075Sobrien	struct rman	sc_mem_rman;
11190075Sobrien	bus_addr_t	sc_mem_base;
11290075Sobrien	bus_addr_t	sc_mem_size;
11390075Sobrien	uint32_t	sc_mem_map[MV_PCI_MEM_SLICE_SIZE /
11490075Sobrien	    (PCI_MIN_MEM_ALLOC * BITS_PER_UINT32)];
11590075Sobrien	int		sc_win_target;
11690075Sobrien	int		sc_mem_win_attr;
117117395Skan
118117395Skan	struct rman	sc_io_rman;
11990075Sobrien	bus_addr_t	sc_io_base;
12090075Sobrien	bus_addr_t	sc_io_size;
121117395Skan	uint32_t	sc_io_map[MV_PCI_IO_SLICE_SIZE /
122117395Skan	    (PCI_MIN_IO_ALLOC * BITS_PER_UINT32)];
123117395Skan	int		sc_io_win_attr;
124117395Skan
125117395Skan	struct resource	*sc_res;
126117395Skan	bus_space_handle_t sc_bsh;
127117395Skan	bus_space_tag_t	sc_bst;
128117395Skan	int		sc_rid;
129117395Skan
13090075Sobrien	int		sc_busnr;		/* Host bridge bus number */
13190075Sobrien	int		sc_devnr;		/* Host bridge device number */
13290075Sobrien	int		sc_type;
13390075Sobrien	int		sc_mode;		/* Endpoint / Root Complex */
13490075Sobrien
13590075Sobrien	struct fdt_pci_intr	sc_intr_info;
13690075Sobrien};
13790075Sobrien
13890075Sobrien/* Local forward prototypes */
13990075Sobrienstatic int mv_pcib_decode_win(phandle_t, struct mv_pcib_softc *);
14090075Sobrienstatic void mv_pcib_hw_cfginit(void);
14190075Sobrienstatic uint32_t mv_pcib_hw_cfgread(struct mv_pcib_softc *, u_int, u_int,
14290075Sobrien    u_int, u_int, int);
14390075Sobrienstatic void mv_pcib_hw_cfgwrite(struct mv_pcib_softc *, u_int, u_int,
14490075Sobrien    u_int, u_int, uint32_t, int);
14590075Sobrienstatic int mv_pcib_init(struct mv_pcib_softc *, int, int);
14690075Sobrienstatic int mv_pcib_init_all_bars(struct mv_pcib_softc *, int, int, int, int);
14790075Sobrienstatic void mv_pcib_init_bridge(struct mv_pcib_softc *, int, int, int);
14890075Sobrienstatic int mv_pcib_intr_info(phandle_t, struct mv_pcib_softc *);
14990075Sobrienstatic inline void pcib_write_irq_mask(struct mv_pcib_softc *, uint32_t);
15090075Sobrienstatic void mv_pcib_enable(struct mv_pcib_softc *, uint32_t);
15190075Sobrienstatic int mv_pcib_mem_init(struct mv_pcib_softc *);
15290075Sobrien
15390075Sobrien/* Forward prototypes */
15490075Sobrienstatic int mv_pcib_probe(device_t);
15590075Sobrienstatic int mv_pcib_attach(device_t);
15690075Sobrien
15790075Sobrienstatic struct resource *mv_pcib_alloc_resource(device_t, device_t, int, int *,
15890075Sobrien    u_long, u_long, u_long, u_int);
15990075Sobrienstatic int mv_pcib_release_resource(device_t, device_t, int, int,
16090075Sobrien    struct resource *);
16190075Sobrienstatic int mv_pcib_read_ivar(device_t, device_t, int, uintptr_t *);
16290075Sobrienstatic int mv_pcib_write_ivar(device_t, device_t, int, uintptr_t);
16390075Sobrien
16490075Sobrienstatic int mv_pcib_maxslots(device_t);
16590075Sobrienstatic uint32_t mv_pcib_read_config(device_t, u_int, u_int, u_int, u_int, int);
16690075Sobrienstatic void mv_pcib_write_config(device_t, u_int, u_int, u_int, u_int,
16790075Sobrien    uint32_t, int);
16890075Sobrienstatic int mv_pcib_route_interrupt(device_t, device_t, int);
16990075Sobrien
17090075Sobrien/*
17190075Sobrien * Bus interface definitions.
17290075Sobrien */
17390075Sobrienstatic device_method_t mv_pcib_methods[] = {
17490075Sobrien	/* Device interface */
17590075Sobrien	DEVMETHOD(device_probe,			mv_pcib_probe),
176117395Skan	DEVMETHOD(device_attach,		mv_pcib_attach),
17790075Sobrien
17890075Sobrien	/* Bus interface */
17990075Sobrien	DEVMETHOD(bus_read_ivar,		mv_pcib_read_ivar),
18090075Sobrien	DEVMETHOD(bus_write_ivar,		mv_pcib_write_ivar),
18190075Sobrien	DEVMETHOD(bus_alloc_resource,		mv_pcib_alloc_resource),
18290075Sobrien	DEVMETHOD(bus_release_resource,		mv_pcib_release_resource),
18390075Sobrien	DEVMETHOD(bus_activate_resource,	bus_generic_activate_resource),
18490075Sobrien	DEVMETHOD(bus_deactivate_resource,	bus_generic_deactivate_resource),
185117395Skan	DEVMETHOD(bus_setup_intr,		bus_generic_setup_intr),
18690075Sobrien	DEVMETHOD(bus_teardown_intr,		bus_generic_teardown_intr),
18790075Sobrien
18890075Sobrien	/* pcib interface */
18990075Sobrien	DEVMETHOD(pcib_maxslots,		mv_pcib_maxslots),
19090075Sobrien	DEVMETHOD(pcib_read_config,		mv_pcib_read_config),
19190075Sobrien	DEVMETHOD(pcib_write_config,		mv_pcib_write_config),
19290075Sobrien	DEVMETHOD(pcib_route_interrupt,		mv_pcib_route_interrupt),
19390075Sobrien
19490075Sobrien	/* OFW bus interface */
19590075Sobrien	DEVMETHOD(ofw_bus_get_compat,   ofw_bus_gen_get_compat),
19690075Sobrien	DEVMETHOD(ofw_bus_get_model,    ofw_bus_gen_get_model),
197117395Skan	DEVMETHOD(ofw_bus_get_name,     ofw_bus_gen_get_name),
198117395Skan	DEVMETHOD(ofw_bus_get_node,     ofw_bus_gen_get_node),
19990075Sobrien	DEVMETHOD(ofw_bus_get_type,     ofw_bus_gen_get_type),
20090075Sobrien
20190075Sobrien	DEVMETHOD_END
20290075Sobrien};
20390075Sobrien
20490075Sobrienstatic driver_t mv_pcib_driver = {
20590075Sobrien	"pcib",
20690075Sobrien	mv_pcib_methods,
20790075Sobrien	sizeof(struct mv_pcib_softc),
20890075Sobrien};
209117395Skan
21090075Sobriendevclass_t pcib_devclass;
21190075Sobrien
21290075SobrienDRIVER_MODULE(pcib, fdtbus, mv_pcib_driver, pcib_devclass, 0, 0);
21390075Sobrien
214117395Skanstatic struct mtx pcicfg_mtx;
215117395Skan
216117395Skanstatic int
217117395Skanmv_pcib_probe(device_t self)
21890075Sobrien{
21990075Sobrien	phandle_t node;
220117395Skan
22190075Sobrien	node = ofw_bus_get_node(self);
22290075Sobrien	if (!fdt_is_type(node, "pci"))
223117395Skan		return (ENXIO);
224117395Skan
225117395Skan	if (!(fdt_is_compatible(node, "mrvl,pcie") ||
226117395Skan	    fdt_is_compatible(node, "mrvl,pci")))
22790075Sobrien		return (ENXIO);
22890075Sobrien
22990075Sobrien	device_set_desc(self, "Marvell Integrated PCI/PCI-E Controller");
230117395Skan	return (BUS_PROBE_DEFAULT);
23190075Sobrien}
23290075Sobrien
23390075Sobrienstatic int
23490075Sobrienmv_pcib_attach(device_t self)
23590075Sobrien{
23690075Sobrien	struct mv_pcib_softc *sc;
23790075Sobrien	phandle_t node, parnode;
23890075Sobrien	uint32_t val, unit;
23990075Sobrien	int err;
24090075Sobrien
24190075Sobrien	sc = device_get_softc(self);
24290075Sobrien	sc->sc_dev = self;
24390075Sobrien	unit = fdt_get_unit(self);
24490075Sobrien
24590075Sobrien
24690075Sobrien	node = ofw_bus_get_node(self);
24790075Sobrien	parnode = OF_parent(node);
24890075Sobrien	if (fdt_is_compatible(node, "mrvl,pcie")) {
24990075Sobrien		sc->sc_type = MV_TYPE_PCIE;
25090075Sobrien		sc->sc_win_target = MV_WIN_PCIE_TARGET(unit);
25190075Sobrien		sc->sc_mem_win_attr = MV_WIN_PCIE_MEM_ATTR(unit);
25290075Sobrien		sc->sc_io_win_attr = MV_WIN_PCIE_IO_ATTR(unit);
25390075Sobrien	} else if (fdt_is_compatible(node, "mrvl,pci")) {
25490075Sobrien		sc->sc_type = MV_TYPE_PCI;
25590075Sobrien		sc->sc_win_target = MV_WIN_PCI_TARGET;
25690075Sobrien		sc->sc_mem_win_attr = MV_WIN_PCI_MEM_ATTR;
25790075Sobrien		sc->sc_io_win_attr = MV_WIN_PCI_IO_ATTR;
25890075Sobrien	} else
25990075Sobrien		return (ENXIO);
26090075Sobrien
26190075Sobrien	/*
26290075Sobrien	 * Retrieve our mem-mapped registers range.
26390075Sobrien	 */
26490075Sobrien	sc->sc_rid = 0;
26590075Sobrien	sc->sc_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &sc->sc_rid,
26690075Sobrien	    RF_ACTIVE);
26790075Sobrien	if (sc->sc_res == NULL) {
26890075Sobrien		device_printf(self, "could not map memory\n");
26990075Sobrien		return (ENXIO);
27090075Sobrien	}
27190075Sobrien	sc->sc_bst = rman_get_bustag(sc->sc_res);
27290075Sobrien	sc->sc_bsh = rman_get_bushandle(sc->sc_res);
27390075Sobrien
27490075Sobrien	val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, PCIE_REG_CONTROL);
27590075Sobrien	sc->sc_mode = (val & PCIE_CONTROL_ROOT_CMPLX ? MV_MODE_ROOT :
27690075Sobrien	    MV_MODE_ENDPOINT);
27790075Sobrien
27890075Sobrien	/*
27990075Sobrien	 * Get PCI interrupt info.
28090075Sobrien	 */
28190075Sobrien	if ((sc->sc_mode == MV_MODE_ROOT) &&
28290075Sobrien	    (mv_pcib_intr_info(node, sc) != 0)) {
28390075Sobrien		device_printf(self, "could not retrieve interrupt info\n");
28490075Sobrien		return (ENXIO);
28590075Sobrien	}
28690075Sobrien
28790075Sobrien	/*
288117395Skan	 * Configure decode windows for PCI(E) access.
28990075Sobrien	 */
29090075Sobrien	if (mv_pcib_decode_win(node, sc) != 0)
29190075Sobrien		return (ENXIO);
29290075Sobrien
29390075Sobrien	mv_pcib_hw_cfginit();
29490075Sobrien
29590075Sobrien	/*
29690075Sobrien	 * Enable PCIE device.
29790075Sobrien	 */
29890075Sobrien	mv_pcib_enable(sc, unit);
29990075Sobrien
30090075Sobrien	/*
30190075Sobrien	 * Memory management.
30290075Sobrien	 */
30390075Sobrien	err = mv_pcib_mem_init(sc);
30490075Sobrien	if (err)
30590075Sobrien		return (err);
30690075Sobrien
30790075Sobrien	if (sc->sc_mode == MV_MODE_ROOT) {
30890075Sobrien		err = mv_pcib_init(sc, sc->sc_busnr,
30990075Sobrien		    mv_pcib_maxslots(sc->sc_dev));
31090075Sobrien		if (err)
31190075Sobrien			goto error;
31290075Sobrien
31390075Sobrien		device_add_child(self, "pci", -1);
31490075Sobrien	} else {
31590075Sobrien		sc->sc_devnr = 1;
31690075Sobrien		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
31790075Sobrien		    PCIE_REG_STATUS, 1 << PCIE_STATUS_DEV_OFFS);
31890075Sobrien		device_add_child(self, "pci_ep", -1);
31990075Sobrien	}
320117395Skan
321117395Skan	return (bus_generic_attach(self));
322117395Skan
323117395Skanerror:
324117395Skan	/* XXX SYS_RES_ should be released here */
325117395Skan	rman_fini(&sc->sc_mem_rman);
326117395Skan	rman_fini(&sc->sc_io_rman);
327117395Skan
328117395Skan	return (err);
329117395Skan}
330117395Skan
331117395Skanstatic void
332117395Skanmv_pcib_enable(struct mv_pcib_softc *sc, uint32_t unit)
333117395Skan{
334117395Skan	uint32_t val;
335117395Skan#if !defined(SOC_MV_ARMADAXP)
336117395Skan	int timeout;
337117395Skan
338117395Skan	/*
339117395Skan	 * Check if PCIE device is enabled.
340117395Skan	 */
341117395Skan	if (read_cpu_ctrl(CPU_CONTROL) & CPU_CONTROL_PCIE_DISABLE(unit)) {
342117395Skan		write_cpu_ctrl(CPU_CONTROL, read_cpu_ctrl(CPU_CONTROL) &
343117395Skan		    ~(CPU_CONTROL_PCIE_DISABLE(unit)));
344117395Skan
345117395Skan		timeout = PCIE_LINK_TIMEOUT;
346117395Skan		val = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
347117395Skan		    PCIE_REG_STATUS);
348117395Skan		while (((val & PCIE_STATUS_LINK_DOWN) == 1) && (timeout > 0)) {
349117395Skan			DELAY(1000);
350117395Skan			timeout -= 1000;
351117395Skan			val = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
352117395Skan			    PCIE_REG_STATUS);
353117395Skan		}
354117395Skan	}
355117395Skan#endif
356117395Skan
357117395Skan
358117395Skan	if (sc->sc_mode == MV_MODE_ROOT) {
359117395Skan		/*
360117395Skan		 * Enable PCI bridge.
361117395Skan		 */
362117395Skan		val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, PCIR_COMMAND);
363117395Skan		val |= PCIM_CMD_SERRESPEN | PCIM_CMD_BUSMASTEREN |
364117395Skan		    PCIM_CMD_MEMEN | PCIM_CMD_PORTEN;
365117395Skan		bus_space_write_4(sc->sc_bst, sc->sc_bsh, PCIR_COMMAND, val);
366117395Skan	}
367117395Skan}
368117395Skan
369117395Skanstatic int
370117395Skanmv_pcib_mem_init(struct mv_pcib_softc *sc)
371117395Skan{
372117395Skan	int err;
373117395Skan
374117395Skan	/*
375117395Skan	 * Memory management.
376117395Skan	 */
377117395Skan	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
378117395Skan	err = rman_init(&sc->sc_mem_rman);
379117395Skan	if (err)
380117395Skan		return (err);
381117395Skan
382117395Skan	sc->sc_io_rman.rm_type = RMAN_ARRAY;
38390075Sobrien	err = rman_init(&sc->sc_io_rman);
38490075Sobrien	if (err) {
385117395Skan		rman_fini(&sc->sc_mem_rman);
38690075Sobrien		return (err);
38790075Sobrien	}
38890075Sobrien
38990075Sobrien	err = rman_manage_region(&sc->sc_mem_rman, sc->sc_mem_base,
39090075Sobrien	    sc->sc_mem_base + sc->sc_mem_size - 1);
39190075Sobrien	if (err)
39290075Sobrien		goto error;
39390075Sobrien
39490075Sobrien	err = rman_manage_region(&sc->sc_io_rman, sc->sc_io_base,
39590075Sobrien	    sc->sc_io_base + sc->sc_io_size - 1);
39690075Sobrien	if (err)
39790075Sobrien		goto error;
39890075Sobrien
39990075Sobrien	return (0);
40090075Sobrien
40190075Sobrienerror:
40290075Sobrien	rman_fini(&sc->sc_mem_rman);
40390075Sobrien	rman_fini(&sc->sc_io_rman);
40490075Sobrien
40590075Sobrien	return (err);
40690075Sobrien}
40790075Sobrien
40890075Sobrienstatic inline uint32_t
409117395Skanpcib_bit_get(uint32_t *map, uint32_t bit)
41090075Sobrien{
41190075Sobrien	uint32_t n = bit / BITS_PER_UINT32;
41290075Sobrien
41390075Sobrien	bit = bit % BITS_PER_UINT32;
41490075Sobrien	return (map[n] & (1 << bit));
41590075Sobrien}
41690075Sobrien
41790075Sobrienstatic inline void
41890075Sobrienpcib_bit_set(uint32_t *map, uint32_t bit)
41990075Sobrien{
42090075Sobrien	uint32_t n = bit / BITS_PER_UINT32;
42190075Sobrien
42290075Sobrien	bit = bit % BITS_PER_UINT32;
42390075Sobrien	map[n] |= (1 << bit);
42490075Sobrien}
42590075Sobrien
42690075Sobrienstatic inline uint32_t
42790075Sobrienpcib_map_check(uint32_t *map, uint32_t start, uint32_t bits)
42890075Sobrien{
42990075Sobrien	uint32_t i;
43090075Sobrien
43190075Sobrien	for (i = start; i < start + bits; i++)
43290075Sobrien		if (pcib_bit_get(map, i))
43390075Sobrien			return (0);
43490075Sobrien
435117395Skan	return (1);
436117395Skan}
437117395Skan
438117395Skanstatic inline void
439117395Skanpcib_map_set(uint32_t *map, uint32_t start, uint32_t bits)
44090075Sobrien{
44190075Sobrien	uint32_t i;
442117395Skan
44390075Sobrien	for (i = start; i < start + bits; i++)
444117395Skan		pcib_bit_set(map, i);
445117395Skan}
446117395Skan
44790075Sobrien/*
44890075Sobrien * The idea of this allocator is taken from ARM No-Cache memory
44990075Sobrien * management code (sys/arm/arm/vm_machdep.c).
45090075Sobrien */
45190075Sobrienstatic bus_addr_t
452117395Skanpcib_alloc(struct mv_pcib_softc *sc, uint32_t smask)
45390075Sobrien{
45490075Sobrien	uint32_t bits, bits_limit, i, *map, min_alloc, size;
45590075Sobrien	bus_addr_t addr = 0;
456117395Skan	bus_addr_t base;
457117395Skan
458117395Skan	if (smask & 1) {
459117395Skan		base = sc->sc_io_base;
460117395Skan		min_alloc = PCI_MIN_IO_ALLOC;
46190075Sobrien		bits_limit = sc->sc_io_size / min_alloc;
46290075Sobrien		map = sc->sc_io_map;
46390075Sobrien		smask &= ~0x3;
46490075Sobrien	} else {
465117395Skan		base = sc->sc_mem_base;
466117395Skan		min_alloc = PCI_MIN_MEM_ALLOC;
46790075Sobrien		bits_limit = sc->sc_mem_size / min_alloc;
46890075Sobrien		map = sc->sc_mem_map;
469117395Skan		smask &= ~0xF;
47090075Sobrien	}
47190075Sobrien
47290075Sobrien	size = ~smask + 1;
47390075Sobrien	bits = size / min_alloc;
474117395Skan
475117395Skan	for (i = 0; i + bits <= bits_limit; i += bits)
476117395Skan		if (pcib_map_check(map, i, bits)) {
477117395Skan			pcib_map_set(map, i, bits);
478117395Skan			addr = base + (i * min_alloc);
479117395Skan			return (addr);
480117395Skan		}
481117395Skan
48290075Sobrien	return (addr);
48390075Sobrien}
48490075Sobrien
48590075Sobrienstatic int
48690075Sobrienmv_pcib_init_bar(struct mv_pcib_softc *sc, int bus, int slot, int func,
48790075Sobrien    int barno)
48890075Sobrien{
48990075Sobrien	uint32_t addr, bar;
49090075Sobrien	int reg, width;
49190075Sobrien
49290075Sobrien	reg = PCIR_BAR(barno);
49390075Sobrien
49490075Sobrien	/*
49590075Sobrien	 * Need to init the BAR register with 0xffffffff before correct
49690075Sobrien	 * value can be read.
49790075Sobrien	 */
49890075Sobrien	mv_pcib_write_config(sc->sc_dev, bus, slot, func, reg, ~0, 4);
49990075Sobrien	bar = mv_pcib_read_config(sc->sc_dev, bus, slot, func, reg, 4);
50090075Sobrien	if (bar == 0)
50190075Sobrien		return (1);
50290075Sobrien
50390075Sobrien	/* Calculate BAR size: 64 or 32 bit (in 32-bit units) */
50490075Sobrien	width = ((bar & 7) == 4) ? 2 : 1;
50590075Sobrien
50690075Sobrien	addr = pcib_alloc(sc, bar);
50790075Sobrien	if (!addr)
50890075Sobrien		return (-1);
50990075Sobrien
51090075Sobrien	if (bootverbose)
51190075Sobrien		printf("PCI %u:%u:%u: reg %x: smask=%08x: addr=%08x\n",
51290075Sobrien		    bus, slot, func, reg, bar, addr);
513117395Skan
51490075Sobrien	mv_pcib_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4);
51590075Sobrien	if (width == 2)
51690075Sobrien		mv_pcib_write_config(sc->sc_dev, bus, slot, func, reg + 4,
51790075Sobrien		    0, 4);
518117395Skan
519117395Skan	return (width);
520117395Skan}
521117395Skan
522117395Skanstatic void
523117395Skanmv_pcib_init_bridge(struct mv_pcib_softc *sc, int bus, int slot, int func)
524117395Skan{
525117395Skan	bus_addr_t io_base, mem_base;
526117395Skan	uint32_t io_limit, mem_limit;
527117395Skan	int secbus;
528117395Skan
529117395Skan	io_base = sc->sc_io_base;
530117395Skan	io_limit = io_base + sc->sc_io_size - 1;
531117395Skan	mem_base = sc->sc_mem_base;
532117395Skan	mem_limit = mem_base + sc->sc_mem_size - 1;
533117395Skan
534117395Skan	/* Configure I/O decode registers */
535117395Skan	mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_IOBASEL_1,
536117395Skan	    io_base >> 8, 1);
537117395Skan	mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_IOBASEH_1,
538117395Skan	    io_base >> 16, 2);
539117395Skan	mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_IOLIMITL_1,
540117395Skan	    io_limit >> 8, 1);
541117395Skan	mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_IOLIMITH_1,
54290075Sobrien	    io_limit >> 16, 2);
54390075Sobrien
54490075Sobrien	/* Configure memory decode registers */
54590075Sobrien	mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_MEMBASE_1,
54690075Sobrien	    mem_base >> 16, 2);
54790075Sobrien	mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_MEMLIMIT_1,
54890075Sobrien	    mem_limit >> 16, 2);
54990075Sobrien
55090075Sobrien	/* Disable memory prefetch decode */
55190075Sobrien	mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_PMBASEL_1,
55290075Sobrien	    0x10, 2);
55390075Sobrien	mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_PMBASEH_1,
55490075Sobrien	    0x0, 4);
55590075Sobrien	mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_PMLIMITL_1,
55690075Sobrien	    0xF, 2);
55790075Sobrien	mv_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_PMLIMITH_1,
55890075Sobrien	    0x0, 4);
55990075Sobrien
56090075Sobrien	secbus = mv_pcib_read_config(sc->sc_dev, bus, slot, func,
56190075Sobrien	    PCIR_SECBUS_1, 1);
56290075Sobrien
56390075Sobrien	/* Configure buses behind the bridge */
56490075Sobrien	mv_pcib_init(sc, secbus, PCI_SLOTMAX);
56590075Sobrien}
56690075Sobrien
56790075Sobrienstatic int
56890075Sobrienmv_pcib_init(struct mv_pcib_softc *sc, int bus, int maxslot)
56990075Sobrien{
57090075Sobrien	int slot, func, maxfunc, error;
57190075Sobrien	uint8_t hdrtype, command, class, subclass;
57290075Sobrien
57390075Sobrien	for (slot = 0; slot <= maxslot; slot++) {
57490075Sobrien		maxfunc = 0;
57590075Sobrien		for (func = 0; func <= maxfunc; func++) {
57690075Sobrien			hdrtype = mv_pcib_read_config(sc->sc_dev, bus, slot,
57790075Sobrien			    func, PCIR_HDRTYPE, 1);
57890075Sobrien
57990075Sobrien			if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
58090075Sobrien				continue;
58190075Sobrien
58290075Sobrien			if (func == 0 && (hdrtype & PCIM_MFDEV))
58390075Sobrien				maxfunc = PCI_FUNCMAX;
58490075Sobrien
58590075Sobrien			command = mv_pcib_read_config(sc->sc_dev, bus, slot,
58690075Sobrien			    func, PCIR_COMMAND, 1);
58790075Sobrien			command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN);
58890075Sobrien			mv_pcib_write_config(sc->sc_dev, bus, slot, func,
58990075Sobrien			    PCIR_COMMAND, command, 1);
59090075Sobrien
59190075Sobrien			error = mv_pcib_init_all_bars(sc, bus, slot, func,
59290075Sobrien			    hdrtype);
59390075Sobrien
59490075Sobrien			if (error)
59590075Sobrien				return (error);
59690075Sobrien
59790075Sobrien			command |= PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN |
59890075Sobrien			    PCIM_CMD_PORTEN;
59990075Sobrien			mv_pcib_write_config(sc->sc_dev, bus, slot, func,
600117395Skan			    PCIR_COMMAND, command, 1);
60190075Sobrien
602117395Skan			/* Handle PCI-PCI bridges */
603117395Skan			class = mv_pcib_read_config(sc->sc_dev, bus, slot,
604117395Skan			    func, PCIR_CLASS, 1);
60590075Sobrien			subclass = mv_pcib_read_config(sc->sc_dev, bus, slot,
60690075Sobrien			    func, PCIR_SUBCLASS, 1);
60790075Sobrien
608117395Skan			if (class != PCIC_BRIDGE ||
609117395Skan			    subclass != PCIS_BRIDGE_PCI)
610117395Skan				continue;
61190075Sobrien
61290075Sobrien			mv_pcib_init_bridge(sc, bus, slot, func);
61390075Sobrien		}
61490075Sobrien	}
61590075Sobrien
616117395Skan	/* Enable all ABCD interrupts */
617117395Skan	pcib_write_irq_mask(sc, (0xF << 24));
618117395Skan
61990075Sobrien	return (0);
62090075Sobrien}
62190075Sobrien
62290075Sobrienstatic int
62390075Sobrienmv_pcib_init_all_bars(struct mv_pcib_softc *sc, int bus, int slot,
62490075Sobrien    int func, int hdrtype)
62590075Sobrien{
62690075Sobrien	int maxbar, bar, i;
62790075Sobrien
62890075Sobrien	maxbar = (hdrtype & PCIM_HDRTYPE) ? 0 : 6;
62990075Sobrien	bar = 0;
63090075Sobrien
631117395Skan	/* Program the base address registers */
63290075Sobrien	while (bar < maxbar) {
633117395Skan		i = mv_pcib_init_bar(sc, bus, slot, func, bar);
634117395Skan		bar += i;
63590075Sobrien		if (i < 0) {
63690075Sobrien			device_printf(sc->sc_dev,
637117395Skan			    "PCI IO/Memory space exhausted\n");
63890075Sobrien			return (ENOMEM);
63990075Sobrien		}
64096263Sobrien	}
64196263Sobrien
64290075Sobrien	return (0);
64390075Sobrien}
64490075Sobrien
64590075Sobrienstatic struct resource *
64690075Sobrienmv_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
64790075Sobrien    u_long start, u_long end, u_long count, u_int flags)
64890075Sobrien{
64990075Sobrien	struct mv_pcib_softc *sc = device_get_softc(dev);
65090075Sobrien	struct rman *rm = NULL;
65190075Sobrien	struct resource *res;
65290075Sobrien
65390075Sobrien	switch (type) {
65490075Sobrien	case SYS_RES_IOPORT:
65590075Sobrien		rm = &sc->sc_io_rman;
65690075Sobrien		break;
65790075Sobrien	case SYS_RES_MEMORY:
65890075Sobrien		rm = &sc->sc_mem_rman;
65990075Sobrien		break;
66090075Sobrien	default:
66190075Sobrien		return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
66290075Sobrien		    type, rid, start, end, count, flags));
66390075Sobrien	};
66490075Sobrien
66590075Sobrien	if ((start == 0UL) && (end == ~0UL)) {
666117395Skan		start = sc->sc_mem_base;
667117395Skan		end = sc->sc_mem_base + sc->sc_mem_size - 1;
668117395Skan		count = sc->sc_mem_size;
669117395Skan	}
67090075Sobrien
67190075Sobrien	if ((start < sc->sc_mem_base) || (start + count - 1 != end) ||
67290075Sobrien	    (end > sc->sc_mem_base + sc->sc_mem_size - 1))
67390075Sobrien		return (NULL);
67490075Sobrien
67590075Sobrien	res = rman_reserve_resource(rm, start, end, count, flags, child);
67690075Sobrien	if (res == NULL)
67790075Sobrien		return (NULL);
67890075Sobrien
679117395Skan	rman_set_rid(res, *rid);
680117395Skan	rman_set_bustag(res, fdtbus_bs_tag);
681117395Skan	rman_set_bushandle(res, start);
682117395Skan
683117395Skan	if (flags & RF_ACTIVE)
684117395Skan		if (bus_activate_resource(child, type, *rid, res)) {
685117395Skan			rman_release_resource(res);
686117395Skan			return (NULL);
687117395Skan		}
688117395Skan
689117395Skan	return (res);
69090075Sobrien}
69190075Sobrien
69290075Sobrienstatic int
69390075Sobrienmv_pcib_release_resource(device_t dev, device_t child, int type, int rid,
69490075Sobrien    struct resource *res)
695117395Skan{
69690075Sobrien
69790075Sobrien	if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY)
698117395Skan		return (BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
69990075Sobrien		    type, rid, res));
70090075Sobrien
70190075Sobrien	return (rman_release_resource(res));
702117395Skan}
703117395Skan
704117395Skanstatic int
705117395Skanmv_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
70690075Sobrien{
70790075Sobrien	struct mv_pcib_softc *sc = device_get_softc(dev);
70890075Sobrien
70990075Sobrien	switch (which) {
71090075Sobrien	case PCIB_IVAR_BUS:
71190075Sobrien		*result = sc->sc_busnr;
71290075Sobrien		return (0);
713117395Skan	case PCIB_IVAR_DOMAIN:
71490075Sobrien		*result = device_get_unit(dev);
71590075Sobrien		return (0);
71690075Sobrien	}
71790075Sobrien
71890075Sobrien	return (ENOENT);
71990075Sobrien}
72090075Sobrien
72190075Sobrienstatic int
72290075Sobrienmv_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
72390075Sobrien{
72490075Sobrien	struct mv_pcib_softc *sc = device_get_softc(dev);
72590075Sobrien
72690075Sobrien	switch (which) {
72790075Sobrien	case PCIB_IVAR_BUS:
72890075Sobrien		sc->sc_busnr = value;
72990075Sobrien		return (0);
73090075Sobrien	}
73190075Sobrien
73290075Sobrien	return (ENOENT);
73390075Sobrien}
73490075Sobrien
73590075Sobrienstatic inline void
73690075Sobrienpcib_write_irq_mask(struct mv_pcib_softc *sc, uint32_t mask)
73790075Sobrien{
73896263Sobrien
73996263Sobrien	if (!sc->sc_type != MV_TYPE_PCI)
740117395Skan		return;
741117395Skan
74296263Sobrien	bus_space_write_4(sc->sc_bst, sc->sc_bsh, PCIE_REG_IRQ_MASK, mask);
74396263Sobrien}
74496263Sobrien
74596263Sobrienstatic void
74696263Sobrienmv_pcib_hw_cfginit(void)
74796263Sobrien{
74896263Sobrien	static int opened = 0;
74996263Sobrien
75096263Sobrien	if (opened)
751117395Skan		return;
752117395Skan
753117395Skan	mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN);
754117395Skan	opened = 1;
755117395Skan}
756117395Skan
757117395Skanstatic uint32_t
758117395Skanmv_pcib_hw_cfgread(struct mv_pcib_softc *sc, u_int bus, u_int slot,
759117395Skan    u_int func, u_int reg, int bytes)
760117395Skan{
761117395Skan	uint32_t addr, data, ca, cd;
762117395Skan
763117395Skan	ca = (sc->sc_type != MV_TYPE_PCI) ?
764117395Skan	    PCIE_REG_CFG_ADDR : PCI_REG_CFG_ADDR;
76590075Sobrien	cd = (sc->sc_type != MV_TYPE_PCI) ?
76690075Sobrien	    PCIE_REG_CFG_DATA : PCI_REG_CFG_DATA;
767117395Skan	addr = PCI_CFG_ENA | PCI_CFG_BUS(bus) | PCI_CFG_DEV(slot) |
76890075Sobrien	    PCI_CFG_FUN(func) | PCI_CFG_PCIE_REG(reg);
76990075Sobrien
77090075Sobrien	mtx_lock_spin(&pcicfg_mtx);
77190075Sobrien	bus_space_write_4(sc->sc_bst, sc->sc_bsh, ca, addr);
77296263Sobrien
77390075Sobrien	data = ~0;
77490075Sobrien	switch (bytes) {
77590075Sobrien	case 1:
77690075Sobrien		data = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
77790075Sobrien		    cd + (reg & 3));
77890075Sobrien		break;
77990075Sobrien	case 2:
78090075Sobrien		data = le16toh(bus_space_read_2(sc->sc_bst, sc->sc_bsh,
78190075Sobrien		    cd + (reg & 2)));
78290075Sobrien		break;
78390075Sobrien	case 4:
78490075Sobrien		data = le32toh(bus_space_read_4(sc->sc_bst, sc->sc_bsh,
785117395Skan		    cd));
786117395Skan		break;
787117395Skan	}
788117395Skan	mtx_unlock_spin(&pcicfg_mtx);
78990075Sobrien	return (data);
79090075Sobrien}
79190075Sobrien
79290075Sobrienstatic void
79390075Sobrienmv_pcib_hw_cfgwrite(struct mv_pcib_softc *sc, u_int bus, u_int slot,
79490075Sobrien    u_int func, u_int reg, uint32_t data, int bytes)
79590075Sobrien{
796117395Skan	uint32_t addr, ca, cd;
79790075Sobrien
79890075Sobrien	ca = (sc->sc_type != MV_TYPE_PCI) ?
79990075Sobrien	    PCIE_REG_CFG_ADDR : PCI_REG_CFG_ADDR;
80090075Sobrien	cd = (sc->sc_type != MV_TYPE_PCI) ?
801117395Skan	    PCIE_REG_CFG_DATA : PCI_REG_CFG_DATA;
802117395Skan	addr = PCI_CFG_ENA | PCI_CFG_BUS(bus) | PCI_CFG_DEV(slot) |
803117395Skan	    PCI_CFG_FUN(func) | PCI_CFG_PCIE_REG(reg);
804117395Skan
805117395Skan	mtx_lock_spin(&pcicfg_mtx);
806117395Skan	bus_space_write_4(sc->sc_bst, sc->sc_bsh, ca, addr);
80790075Sobrien
80890075Sobrien	switch (bytes) {
80990075Sobrien	case 1:
810117395Skan		bus_space_write_1(sc->sc_bst, sc->sc_bsh,
81190075Sobrien		    cd + (reg & 3), data);
812117395Skan		break;
81390075Sobrien	case 2:
81490075Sobrien		bus_space_write_2(sc->sc_bst, sc->sc_bsh,
81590075Sobrien		    cd + (reg & 2), htole16(data));
81690075Sobrien		break;
81790075Sobrien	case 4:
81890075Sobrien		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
819117395Skan		    cd, htole32(data));
82090075Sobrien		break;
821117395Skan	}
822117395Skan	mtx_unlock_spin(&pcicfg_mtx);
823117395Skan}
82490075Sobrien
82590075Sobrienstatic int
82690075Sobrienmv_pcib_maxslots(device_t dev)
827117395Skan{
82890075Sobrien	struct mv_pcib_softc *sc = device_get_softc(dev);
82990075Sobrien
83090075Sobrien	return ((sc->sc_type != MV_TYPE_PCI) ? 1 : PCI_SLOTMAX);
83190075Sobrien}
83290075Sobrien
83390075Sobrienstatic uint32_t
83490075Sobrienmv_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func,
83590075Sobrien    u_int reg, int bytes)
83690075Sobrien{
83790075Sobrien	struct mv_pcib_softc *sc = device_get_softc(dev);
83890075Sobrien
83990075Sobrien	/* Return ~0 if link is inactive or trying to read from Root */
84090075Sobrien	if ((bus_space_read_4(sc->sc_bst, sc->sc_bsh, PCIE_REG_STATUS) &
84190075Sobrien	    PCIE_STATUS_LINK_DOWN) || (slot == 0))
84290075Sobrien		return (~0U);
84390075Sobrien
84490075Sobrien	return (mv_pcib_hw_cfgread(sc, bus, slot, func, reg, bytes));
84590075Sobrien}
84690075Sobrien
84790075Sobrienstatic void
84890075Sobrienmv_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func,
84990075Sobrien    u_int reg, uint32_t val, int bytes)
85090075Sobrien{
85190075Sobrien	struct mv_pcib_softc *sc = device_get_softc(dev);
85290075Sobrien
853117395Skan	/* Return if link is inactive or trying to write to Root */
854117395Skan	if ((bus_space_read_4(sc->sc_bst, sc->sc_bsh, PCIE_REG_STATUS) &
855117395Skan	    PCIE_STATUS_LINK_DOWN) || (slot == 0))
856117395Skan		return;
857117395Skan
858117395Skan	mv_pcib_hw_cfgwrite(sc, bus, slot, func, reg, val, bytes);
859117395Skan}
860117395Skan
861117395Skanstatic int
862117395Skanmv_pcib_route_interrupt(device_t pcib, device_t dev, int pin)
863117395Skan{
864117395Skan	struct mv_pcib_softc *sc;
86590075Sobrien	int err, interrupt;
86690075Sobrien
86790075Sobrien	sc = device_get_softc(pcib);
86890075Sobrien
86990075Sobrien	err = fdt_pci_route_intr(pci_get_bus(dev), pci_get_slot(dev),
87090075Sobrien	    pci_get_function(dev), pin, &sc->sc_intr_info, &interrupt);
871117395Skan	if (err == 0)
87290075Sobrien		return (interrupt);
87390075Sobrien
87490075Sobrien	device_printf(pcib, "could not route pin %d for device %d.%d\n",
87590075Sobrien	    pin, pci_get_slot(dev), pci_get_function(dev));
87690075Sobrien	return (PCI_INVALID_IRQ);
87790075Sobrien}
87890075Sobrien
87990075Sobrienstatic int
880117395Skanmv_pcib_decode_win(phandle_t node, struct mv_pcib_softc *sc)
881117395Skan{
882117395Skan	struct fdt_pci_range io_space, mem_space;
883117395Skan	device_t dev;
884117395Skan	int error;
885117395Skan
886117395Skan	dev = sc->sc_dev;
887117395Skan
888117395Skan	if ((error = fdt_pci_ranges(node, &io_space, &mem_space)) != 0) {
889117395Skan		device_printf(dev, "could not retrieve 'ranges' data\n");
890117395Skan		return (error);
891117395Skan	}
892117395Skan
893117395Skan	/* Configure CPU decoding windows */
894117395Skan	error = decode_win_cpu_set(sc->sc_win_target,
895117395Skan	    sc->sc_io_win_attr, io_space.base_parent, io_space.len, ~0);
896117395Skan	if (error < 0) {
897117395Skan		device_printf(dev, "could not set up CPU decode "
898117395Skan		    "window for PCI IO\n");
899117395Skan		return (ENXIO);
900117395Skan	}
901117395Skan	error = decode_win_cpu_set(sc->sc_win_target,
902117395Skan	    sc->sc_mem_win_attr, mem_space.base_parent, mem_space.len,
903117395Skan	    mem_space.base_parent);
904117395Skan	if (error < 0) {
905117395Skan		device_printf(dev, "could not set up CPU decode "
906117395Skan		    "windows for PCI MEM\n");
907117395Skan		return (ENXIO);
908117395Skan	}
909117395Skan
910117395Skan	sc->sc_io_base = io_space.base_parent;
911117395Skan	sc->sc_io_size = io_space.len;
912117395Skan
913117395Skan	sc->sc_mem_base = mem_space.base_parent;
914117395Skan	sc->sc_mem_size = mem_space.len;
915117395Skan
916117395Skan	return (0);
917117395Skan}
918117395Skan
919117395Skanstatic int
920117395Skanmv_pcib_intr_info(phandle_t node, struct mv_pcib_softc *sc)
921117395Skan{
922117395Skan	int error;
923117395Skan
924117395Skan	if ((error = fdt_pci_intr_info(node, &sc->sc_intr_info)) != 0)
925117395Skan		return (error);
926117395Skan
92790075Sobrien	return (0);
92890075Sobrien}
92990075Sobrien
93090075Sobrien