diff options
35 files changed, 1960 insertions, 2475 deletions
diff --git a/sys/conf/Makefile.powerpc b/sys/conf/Makefile.powerpc index 81b1bb483359..7cd664722f7c 100644 --- a/sys/conf/Makefile.powerpc +++ b/sys/conf/Makefile.powerpc @@ -30,6 +30,8 @@ S= ../../.. .endif .include "$S/conf/kern.pre.mk" +INCLUDES+= -I$S/contrib/libfdt + CFLAGS+= -msoft-float DDB_ENABLED!= grep DDB opt_ddb.h || true diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc index af0d8575d82a..902c648530d9 100644 --- a/sys/conf/files.powerpc +++ b/sys/conf/files.powerpc @@ -14,7 +14,6 @@ font.h optional sc \ no-obj no-implicit-rule before-depend \ clean "font.h ${SC_DFLT_FONT}-8x14 ${SC_DFLT_FONT}-8x16 ${SC_DFLT_FONT}-8x8" # - crypto/blowfish/bf_enc.c optional crypto | ipsec crypto/des/des_enc.c optional crypto | ipsec | netsmb dev/bm/if_bm.c optional bm powermac @@ -23,21 +22,23 @@ dev/adb/adb_kbd.c optional adb dev/adb/adb_mouse.c optional adb dev/adb/adb_hb_if.m optional adb dev/adb/adb_if.m optional adb -dev/cfi/cfi_bus_lbc.c optional cfi +dev/cfi/cfi_bus_fdt.c optional cfi fdt dev/fb/fb.c optional sc +dev/fdt/fdt_powerpc.c optional fdt dev/hwpmc/hwpmc_powerpc.c optional hwpmc dev/kbd/kbd.c optional sc -dev/ofw/openfirm.c optional aim -dev/ofw/openfirmio.c optional aim -dev/ofw/ofw_bus_if.m optional aim -dev/ofw/ofw_if.m optional aim -dev/ofw/ofw_bus_subr.c optional aim +dev/ofw/openfirm.c optional aim | fdt +dev/ofw/openfirmio.c optional aim | fdt +dev/ofw/ofw_bus_if.m optional aim | fdt +dev/ofw/ofw_if.m optional aim | fdt +dev/ofw/ofw_bus_subr.c optional aim | fdt dev/ofw/ofw_console.c optional aim dev/ofw/ofw_disk.c optional ofwd aim +dev/ofw/ofw_fdt.c optional fdt dev/ofw/ofw_iicbus.c optional iicbus aim dev/ofw/ofw_standard.c optional aim dev/powermac_nvram/powermac_nvram.c optional powermac_nvram powermac -dev/quicc/quicc_bfe_ocp.c optional quicc mpc85xx +dev/quicc/quicc_bfe_fdt.c optional quicc mpc85xx dev/scc/scc_bfe_macio.c optional scc powermac dev/sec/sec.c optional sec mpc85xx dev/sound/macio/aoa.c optional snd_davbus | snd_ai2s powermac @@ -49,9 +50,8 @@ dev/syscons/scgfbrndr.c optional sc dev/syscons/scterm-teken.c optional sc dev/syscons/scvtb.c optional sc dev/tsec/if_tsec.c optional tsec -dev/tsec/if_tsec_ocp.c optional tsec mpc85xx -dev/uart/uart_bus_ocp.c optional uart mpc85xx -dev/uart/uart_cpu_powerpc.c optional uart +dev/tsec/if_tsec_fdt.c optional tsec fdt +dev/uart/uart_cpu_powerpc.c optional uart aim kern/syscalls.c optional ktr libkern/ashldi3.c standard libkern/ashrdi3.c standard @@ -63,6 +63,7 @@ libkern/ffsl.c standard libkern/fls.c standard libkern/flsl.c standard libkern/lshrdi3.c standard +libkern/memchr.c optional fdt libkern/memmove.c standard libkern/memset.c standard libkern/moddi3.c standard @@ -109,16 +110,15 @@ powerpc/fpu/fpu_mul.c optional fpu_emu powerpc/fpu/fpu_sqrt.c optional fpu_emu powerpc/fpu/fpu_subr.c optional fpu_emu powerpc/mpc85xx/atpic.c optional mpc85xx isa -powerpc/mpc85xx/ds1553_bus_lbc.c optional ds1553 +powerpc/mpc85xx/ds1553_bus_fdt.c optional ds1553 fdt powerpc/mpc85xx/ds1553_core.c optional ds1553 -powerpc/mpc85xx/i2c.c optional iicbus mpc85xx +powerpc/mpc85xx/i2c.c optional iicbus fdt powerpc/mpc85xx/isa.c optional mpc85xx isa powerpc/mpc85xx/lbc.c optional mpc85xx powerpc/mpc85xx/mpc85xx.c optional mpc85xx powerpc/mpc85xx/nexus.c optional mpc85xx -powerpc/mpc85xx/ocpbus.c optional mpc85xx -powerpc/mpc85xx/opic.c optional mpc85xx -powerpc/mpc85xx/pci_ocp.c optional pci mpc85xx +powerpc/mpc85xx/openpic_fdt.c optional fdt +powerpc/mpc85xx/pci_fdt.c optional pci mpc85xx powerpc/ofw/ofw_cpu.c optional aim powerpc/ofw/ofw_pcibus.c optional pci aim powerpc/ofw/ofw_pcib_pci.c optional pci aim diff --git a/sys/dev/cfi/cfi_bus_lbc.c b/sys/dev/cfi/cfi_bus_fdt.c index df24f389998d..bfbd65f80654 100644 --- a/sys/dev/cfi/cfi_bus_lbc.c +++ b/sys/dev/cfi/cfi_bus_fdt.c @@ -35,49 +35,39 @@ __FBSDID("$FreeBSD$"); #include <sys/bus.h> #include <sys/conf.h> #include <sys/kernel.h> -#include <sys/malloc.h> #include <sys/module.h> -#include <sys/rman.h> -#include <sys/sysctl.h> #include <machine/bus.h> #include <dev/cfi/cfi_var.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> -#include <powerpc/mpc85xx/lbc.h> +static int cfi_fdt_probe(device_t); -static int cfi_lbc_probe(device_t); - -static device_method_t cfi_lbc_methods[] = { +static device_method_t cfi_fdt_methods[] = { /* device interface */ - DEVMETHOD(device_probe, cfi_lbc_probe), + DEVMETHOD(device_probe, cfi_fdt_probe), DEVMETHOD(device_attach, cfi_attach), DEVMETHOD(device_detach, cfi_detach), {0, 0} }; -static driver_t cfi_lbc_driver = { +static driver_t cfi_fdt_driver = { cfi_driver_name, - cfi_lbc_methods, + cfi_fdt_methods, sizeof(struct cfi_softc), }; -DRIVER_MODULE (cfi, lbc, cfi_lbc_driver, cfi_devclass, 0, 0); +DRIVER_MODULE (cfi, lbc, cfi_fdt_driver, cfi_devclass, 0, 0); static int -cfi_lbc_probe(device_t dev) +cfi_fdt_probe(device_t dev) { - uintptr_t devtype; - int error; - - error = BUS_READ_IVAR(device_get_parent(dev), dev, LBC_IVAR_DEVTYPE, - &devtype); - if (error) - return (error); - if (devtype != LBC_DEVTYPE_CFI) - return (EINVAL); + if (!ofw_bus_is_compatible(dev, "cfi-flash")) + return (ENXIO); return (cfi_probe(dev)); } diff --git a/sys/dev/fdt/fdt_pci.c b/sys/dev/fdt/fdt_pci.c index fd708efea45f..44e0dbfd17cd 100644 --- a/sys/dev/fdt/fdt_pci.c +++ b/sys/dev/fdt/fdt_pci.c @@ -325,8 +325,9 @@ fdt_pci_route_intr(int bus, int slot, int func, int pin, debugf("decoded intr = %d, trig = %d, pol = %d\n", *interrupt, trig, pol); - /* XXX we should probably call powerpc_config() here... */ - +#if defined(__powerpc__) + powerpc_config_intr(INTR_VEC(intr_par, *interrupt), trig, pol); +#endif return (0); next: diff --git a/sys/dev/quicc/quicc_bfe_ocp.c b/sys/dev/quicc/quicc_bfe_fdt.c index e0a98e0532ef..e1fd2d5ad1ec 100644 --- a/sys/dev/quicc/quicc_bfe_ocp.c +++ b/sys/dev/quicc/quicc_bfe_fdt.c @@ -41,15 +41,15 @@ __FBSDID("$FreeBSD$"); #include <sys/tty.h> #include <machine/bus.h> -#include <machine/ocpbus.h> - +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> #include <dev/quicc/quicc_bfe.h> -static int quicc_ocp_probe(device_t dev); +static int quicc_fdt_probe(device_t dev); -static device_method_t quicc_ocp_methods[] = { +static device_method_t quicc_fdt_methods[] = { /* Device interface */ - DEVMETHOD(device_probe, quicc_ocp_probe), + DEVMETHOD(device_probe, quicc_fdt_probe), DEVMETHOD(device_attach, quicc_bfe_attach), DEVMETHOD(device_detach, quicc_bfe_detach), @@ -65,30 +65,26 @@ static device_method_t quicc_ocp_methods[] = { { 0, 0 } }; -static driver_t quicc_ocp_driver = { +static driver_t quicc_fdt_driver = { quicc_driver_name, - quicc_ocp_methods, + quicc_fdt_methods, sizeof(struct quicc_softc), }; static int -quicc_ocp_probe(device_t dev) +quicc_fdt_probe(device_t dev) { - device_t parent; - uintptr_t clock, devtype; - int error; - - parent = device_get_parent(dev); + phandle_t par; + pcell_t clock; - error = BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_DEVTYPE, &devtype); - if (error) - return (error); - if (devtype != OCPBUS_DEVTYPE_QUICC) + if (!ofw_bus_is_compatible(dev, "fsl,cpm2")) return (ENXIO); - if (BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_CLOCK, &clock)) + par = OF_parent(ofw_bus_get_node(dev)); + if (OF_getprop(par, "bus-frequency", &clock, sizeof(clock)) <= 0) clock = 0; - return (quicc_bfe_probe(dev, clock)); + + return (quicc_bfe_probe(dev, (uintptr_t)clock)); } -DRIVER_MODULE(quicc, ocpbus, quicc_ocp_driver, quicc_devclass, 0, 0); +DRIVER_MODULE(quicc, simplebus, quicc_fdt_driver, quicc_devclass, 0, 0); diff --git a/sys/dev/sec/sec.c b/sys/dev/sec/sec.c index 6b0a62f9e9fa..36fc9cea7435 100644 --- a/sys/dev/sec/sec.c +++ b/sys/dev/sec/sec.c @@ -45,12 +45,12 @@ __FBSDID("$FreeBSD$"); #include <sys/rman.h> #include <machine/bus.h> -#include <machine/ocpbus.h> #include <machine/resource.h> #include <opencrypto/cryptodev.h> #include "cryptodev_if.h" +#include <dev/ofw/ofw_bus_subr.h> #include <dev/sec/sec.h> static int sec_probe(device_t dev); @@ -153,7 +153,7 @@ static driver_t sec_driver = { }; static devclass_t sec_devclass; -DRIVER_MODULE(sec, ocpbus, sec_driver, sec_devclass, 0, 0); +DRIVER_MODULE(sec, simplebus, sec_driver, sec_devclass, 0, 0); MODULE_DEPEND(sec, crypto, 1, 1, 1); static struct sec_eu_methods sec_eus[] = { @@ -201,24 +201,16 @@ static int sec_probe(device_t dev) { struct sec_softc *sc; - device_t parent; - uintptr_t devtype; uint64_t id; - int error; - parent = device_get_parent(dev); - error = BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_DEVTYPE, &devtype); - if (error) - return (error); - - if (devtype != OCPBUS_DEVTYPE_SEC) + if (!ofw_bus_is_compatible(dev, "fsl,sec2.0")) return (ENXIO); sc = device_get_softc(dev); sc->sc_rrid = 0; - sc->sc_rres = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->sc_rrid, - 0ul, ~0ul, SEC_IO_SIZE, RF_ACTIVE); + sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rrid, + RF_ACTIVE); if (sc->sc_rres == NULL) return (ENXIO); @@ -276,8 +268,8 @@ sec_attach(device_t dev) /* Allocate I/O memory for SEC registers */ sc->sc_rrid = 0; - sc->sc_rres = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->sc_rrid, - 0ul, ~0ul, SEC_IO_SIZE, RF_ACTIVE); + sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rrid, + RF_ACTIVE); if (sc->sc_rres == NULL) { device_printf(dev, "could not allocate I/O memory!\n"); @@ -295,12 +287,15 @@ sec_attach(device_t dev) if (error) goto fail2; - sc->sc_sec_irid = 1; - error = sec_setup_intr(sc, &sc->sc_sec_ires, &sc->sc_sec_ihand, - &sc->sc_sec_irid, sec_secondary_intr, "secondary"); - if (error) - goto fail3; + if (sc->sc_version == 3) { + sc->sc_sec_irid = 1; + error = sec_setup_intr(sc, &sc->sc_sec_ires, &sc->sc_sec_ihand, + &sc->sc_sec_irid, sec_secondary_intr, "secondary"); + + if (error) + goto fail3; + } /* Alloc DMA memory for descriptors and link tables */ error = sec_alloc_dma_mem(sc, &(sc->sc_desc_dmem), diff --git a/sys/dev/tsec/if_tsec.c b/sys/dev/tsec/if_tsec.c index 204fce932b2b..7ba7dc68528b 100644 --- a/sys/dev/tsec/if_tsec.c +++ b/sys/dev/tsec/if_tsec.c @@ -1,6 +1,6 @@ /*- - * Copyright (C) 2007-2008 Semihalf, Rafal Jaworowski <raj@semihalf.com> - * Copyright (C) 2006-2007 Semihalf, Piotr Kruszynski <ppk@semihalf.com> + * Copyright (C) 2007-2008 Semihalf, Rafal Jaworowski + * Copyright (C) 2006-2007 Semihalf, Piotr Kruszynski * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1563,7 +1563,7 @@ tsec_miibus_readreg(device_t dev, int phy, int reg) sc = device_get_softc(dev); - if (device_get_unit(dev) != phy) + if (sc->phyaddr != phy) return (0); sc = tsec0_sc; @@ -1591,9 +1591,8 @@ tsec_miibus_writereg(device_t dev, int phy, int reg, int value) sc = device_get_softc(dev); - if (device_get_unit(dev) != phy) - device_printf(dev, "Trying to write to an alien PHY(%d)\n", - phy); + if (sc->phyaddr != phy) + return (0); sc = tsec0_sc; diff --git a/sys/dev/tsec/if_tsec.h b/sys/dev/tsec/if_tsec.h index a0ac722b681b..b98032202548 100644 --- a/sys/dev/tsec/if_tsec.h +++ b/sys/dev/tsec/if_tsec.h @@ -1,5 +1,5 @@ /*- - * Copyright (C) 2006-2007 Semihalf, Piotr Kruszynski <ppk@semihalf.com> + * Copyright (C) 2006-2007 Semihalf, Piotr Kruszynski * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,6 +28,8 @@ #ifndef _IF_TSEC_H #define _IF_TSEC_H +#include <dev/ofw/openfirm.h> + #define TSEC_RX_NUM_DESC 256 #define TSEC_TX_NUM_DESC 256 @@ -49,6 +51,7 @@ struct tsec_softc { struct mtx transmit_lock; /* transmitter lock */ struct mtx receive_lock; /* receiver lock */ + phandle_t node; device_t dev; device_t tsec_miibus; struct mii_data *tsec_mii; /* MII media control */ @@ -128,6 +131,8 @@ struct tsec_softc { /* currently received frame */ struct mbuf *frame; + + int phyaddr; }; /* interface to get/put generic objects */ diff --git a/sys/dev/tsec/if_tsec_ocp.c b/sys/dev/tsec/if_tsec_fdt.c index 1787aa7a5ffc..e355e61a2b98 100644 --- a/sys/dev/tsec/if_tsec_ocp.c +++ b/sys/dev/tsec/if_tsec_fdt.c @@ -1,6 +1,6 @@ /*- - * Copyright (C) 2007-2008 Semihalf, Rafal Jaworowski <raj@semihalf.com> - * Copyright (C) 2006-2007 Semihalf, Piotr Kruszynski <ppk@semihalf.com> + * Copyright (C) 2007-2008 Semihalf, Rafal Jaworowski + * Copyright (C) 2006-2007 Semihalf, Piotr Kruszynski * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -22,10 +22,12 @@ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * From: FreeBSD: head/sys/dev/tsec/if_tsec_ocp.c 188712 2009-02-17 14:59:47Z raj */ /* - * OCP attachment driver for Freescale TSEC controller. + * FDT 'simple-bus' attachment for Freescale TSEC controller. */ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); @@ -50,36 +52,37 @@ __FBSDID("$FreeBSD$"); #include <net/if_media.h> #include <net/if_arp.h> +#include <dev/fdt/fdt_common.h> #include <dev/mii/mii.h> #include <dev/mii/miivar.h> - -#include <machine/bootinfo.h> -#include <machine/ocpbus.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> +#include <dev/ofw/openfirm.h> #include <dev/tsec/if_tsec.h> #include <dev/tsec/if_tsecreg.h> #include "miibus_if.h" -#define OCP_TSEC_RID_TXIRQ 0 -#define OCP_TSEC_RID_RXIRQ 1 -#define OCP_TSEC_RID_ERRIRQ 2 +#define TSEC_RID_TXIRQ 0 +#define TSEC_RID_RXIRQ 1 +#define TSEC_RID_ERRIRQ 2 extern struct tsec_softc *tsec0_sc; -static int tsec_ocp_probe(device_t dev); -static int tsec_ocp_attach(device_t dev); -static int tsec_ocp_detach(device_t dev); -static int tsec_setup_intr(struct tsec_softc *sc, struct resource **ires, +static int tsec_fdt_probe(device_t dev); +static int tsec_fdt_attach(device_t dev); +static int tsec_fdt_detach(device_t dev); +static int tsec_setup_intr(struct tsec_softc *sc, struct resource **ires, void **ihand, int *irid, driver_intr_t handler, const char *iname); -static void tsec_release_intr(struct tsec_softc *sc, struct resource *ires, +static void tsec_release_intr(struct tsec_softc *sc, struct resource *ires, void *ihand, int irid, const char *iname); static device_method_t tsec_methods[] = { /* Device interface */ - DEVMETHOD(device_probe, tsec_ocp_probe), - DEVMETHOD(device_attach, tsec_ocp_attach), - DEVMETHOD(device_detach, tsec_ocp_detach), + DEVMETHOD(device_probe, tsec_fdt_probe), + DEVMETHOD(device_attach, tsec_fdt_attach), + DEVMETHOD(device_detach, tsec_fdt_detach), DEVMETHOD(device_shutdown, tsec_shutdown), DEVMETHOD(device_suspend, tsec_suspend), @@ -96,38 +99,30 @@ static device_method_t tsec_methods[] = { { 0, 0 } }; -static driver_t tsec_ocp_driver = { +static driver_t tsec_fdt_driver = { "tsec", tsec_methods, sizeof(struct tsec_softc), }; -DRIVER_MODULE(tsec, ocpbus, tsec_ocp_driver, tsec_devclass, 0, 0); -MODULE_DEPEND(tsec, ocpbus, 1, 1, 1); +DRIVER_MODULE(tsec, simplebus, tsec_fdt_driver, tsec_devclass, 0, 0); +MODULE_DEPEND(tsec, simplebus, 1, 1, 1); MODULE_DEPEND(tsec, ether, 1, 1, 1); static int -tsec_ocp_probe(device_t dev) +tsec_fdt_probe(device_t dev) { struct tsec_softc *sc; - device_t parent; - uintptr_t devtype; - int error; uint32_t id; - parent = device_get_parent(dev); - - error = BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_DEVTYPE, &devtype); - if (error) - return (error); - if (devtype != OCPBUS_DEVTYPE_TSEC) + if (!ofw_bus_is_compatible(dev, "gianfar")) return (ENXIO); sc = device_get_softc(dev); sc->sc_rrid = 0; - sc->sc_rres = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->sc_rrid, - 0ul, ~0ul, TSEC_IO_SIZE, RF_ACTIVE); + sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rrid, + RF_ACTIVE); if (sc->sc_rres == NULL) return (ENXIO); @@ -155,18 +150,23 @@ tsec_ocp_probe(device_t dev) } static int -tsec_ocp_attach(device_t dev) +tsec_fdt_attach(device_t dev) { struct tsec_softc *sc; int error = 0; sc = device_get_softc(dev); sc->dev = dev; + sc->node = ofw_bus_get_node(dev); /* XXX add comment on weird FSL's MII registers access design */ if (device_get_unit(dev) == 0) tsec0_sc = sc; + /* Get phy address from fdt */ + if (fdt_get_phyaddr(sc->node, &sc->phyaddr) != 0) + return (ENXIO); + /* Init timer */ callout_init(&sc->tsec_callout, 1); @@ -177,11 +177,11 @@ tsec_ocp_attach(device_t dev) MTX_DEF); mtx_init(&sc->ic_lock, device_get_nameunit(dev), "TSEC IC lock", MTX_DEF); - + /* Allocate IO memory for TSEC registers */ sc->sc_rrid = 0; - sc->sc_rres = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->sc_rrid, - 0ul, ~0ul, TSEC_IO_SIZE, RF_ACTIVE); + sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rrid, + RF_ACTIVE); if (sc->sc_rres == NULL) { device_printf(dev, "could not allocate IO memory range!\n"); goto fail1; @@ -196,21 +196,21 @@ tsec_ocp_attach(device_t dev) } /* Set up interrupts (TX/RX/ERR) */ - sc->sc_transmit_irid = OCP_TSEC_RID_TXIRQ; + sc->sc_transmit_irid = TSEC_RID_TXIRQ; error = tsec_setup_intr(sc, &sc->sc_transmit_ires, &sc->sc_transmit_ihand, &sc->sc_transmit_irid, tsec_transmit_intr, "TX"); if (error) goto fail2; - sc->sc_receive_irid = OCP_TSEC_RID_RXIRQ; + sc->sc_receive_irid = TSEC_RID_RXIRQ; error = tsec_setup_intr(sc, &sc->sc_receive_ires, &sc->sc_receive_ihand, &sc->sc_receive_irid, tsec_receive_intr, "RX"); if (error) goto fail3; - sc->sc_error_irid = OCP_TSEC_RID_ERRIRQ; + sc->sc_error_irid = TSEC_RID_ERRIRQ; error = tsec_setup_intr(sc, &sc->sc_error_ires, &sc->sc_error_ihand, &sc->sc_error_irid, tsec_error_intr, "ERR"); @@ -239,8 +239,8 @@ tsec_setup_intr(struct tsec_softc *sc, struct resource **ires, void **ihand, { int error; - (*ires) = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, irid, RF_ACTIVE); - if ((*ires) == NULL) { + *ires = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, irid, RF_ACTIVE); + if (*ires == NULL) { device_printf(sc->dev, "could not allocate %s IRQ\n", iname); return (ENXIO); } @@ -250,7 +250,7 @@ tsec_setup_intr(struct tsec_softc *sc, struct resource **ires, void **ihand, device_printf(sc->dev, "failed to set up %s IRQ\n", iname); if (bus_release_resource(sc->dev, SYS_RES_IRQ, *irid, *ires)) device_printf(sc->dev, "could not release %s IRQ\n", iname); - (*ires) = NULL; + *ires = NULL; return (error); } return (0); @@ -277,7 +277,7 @@ tsec_release_intr(struct tsec_softc *sc, struct resource *ires, void *ihand, } static int -tsec_ocp_detach(device_t dev) +tsec_fdt_detach(device_t dev) { struct tsec_softc *sc; int error; @@ -322,14 +322,15 @@ tsec_get_hwaddr(struct tsec_softc *sc, uint8_t *addr) uint8_t addr[6]; } curmac; uint32_t a[6]; - device_t parent; - uintptr_t macaddr; + uint8_t lma[6]; int i; - parent = device_get_parent(sc->dev); - if (BUS_READ_IVAR(parent, sc->dev, OCPBUS_IVAR_MACADDR, - &macaddr) == 0) { - bcopy((uint8_t *)macaddr, addr, 6); + /* + * Retrieve hw address from the device tree. + */ + i = OF_getprop(sc->node, "local-mac-address", (void *)lma, 6); + if (i == 6) { + bcopy(lma, addr, 6); return; } diff --git a/sys/dev/uart/uart_bus_ocp.c b/sys/dev/uart/uart_bus_ocp.c deleted file mode 100644 index e7f09710ecf0..000000000000 --- a/sys/dev/uart/uart_bus_ocp.c +++ /dev/null @@ -1,88 +0,0 @@ -/*- - * Copyright 2006 by Juniper Networks. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> -#include <sys/conf.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/tty.h> -#include <machine/bus.h> - -#include <machine/ocpbus.h> - -#include <dev/uart/uart.h> -#include <dev/uart/uart_bus.h> - -static int uart_ocp_probe(device_t); - -static device_method_t uart_ocp_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uart_ocp_probe), - DEVMETHOD(device_attach, uart_bus_attach), - DEVMETHOD(device_detach, uart_bus_detach), - { 0, 0 } -}; - -static driver_t uart_ocp_driver = { - uart_driver_name, - uart_ocp_methods, - sizeof(struct uart_softc), -}; - -static int -uart_ocp_probe(device_t dev) -{ - device_t parent; - struct uart_softc *sc; - uintptr_t clock, devtype; - int error; - - parent = device_get_parent(dev); - - error = BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_DEVTYPE, &devtype); - if (error) - return (error); - if (devtype != OCPBUS_DEVTYPE_UART) - return (ENXIO); - - sc = device_get_softc(dev); - sc->sc_class = &uart_ns8250_class; - - if (BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_CLOCK, &clock)) - clock = 0; - return (uart_bus_probe(dev, 0, clock, 0, 0)); -} - -DRIVER_MODULE(uart, ocpbus, uart_ocp_driver, uart_devclass, 0, 0); diff --git a/sys/dev/uart/uart_cpu_powerpc.c b/sys/dev/uart/uart_cpu_powerpc.c index 8e4c1dab7709..997bdd8bcfc4 100644 --- a/sys/dev/uart/uart_cpu_powerpc.c +++ b/sys/dev/uart/uart_cpu_powerpc.c @@ -27,57 +27,28 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); -#include "opt_platform.h" - #include <sys/param.h> #include <sys/systm.h> #include <vm/vm.h> #include <vm/pmap.h> #include <machine/bus.h> - -#ifndef MPC85XX -#include <dev/ofw/openfirm.h> #include <machine/ofw_machdep.h> -#endif +#include <dev/ofw/openfirm.h> #include <dev/uart/uart.h> #include <dev/uart/uart_cpu.h> -#ifdef MPC85XX -bus_space_tag_t uart_bus_space_io = &bs_be_tag; -bus_space_tag_t uart_bus_space_mem = &bs_be_tag; -#else bus_space_tag_t uart_bus_space_io = &bs_le_tag; bus_space_tag_t uart_bus_space_mem = &bs_le_tag; -#endif int uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) { -#ifdef MPC85XX - return ((b1->bsh == b2->bsh) ? 1 : 0); -#else + return ((pmap_kextract(b1->bsh) == pmap_kextract(b2->bsh)) ? 1 : 0); -#endif } -#ifdef MPC85XX -int -uart_cpu_getdev(int devtype, struct uart_devinfo *di) -{ - struct uart_class *class; - - class = &uart_ns8250_class; - if (class == NULL) - class = &uart_quicc_class; - if (class == NULL) - return (ENXIO); - - /* Check the environment. */ - return (uart_getenv(devtype, di, class)); -} -#else static int ofw_get_uart_console(phandle_t opts, phandle_t *result, const char *inputdev, const char *outputdev) @@ -174,4 +145,3 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) di->parity = UART_PARITY_NONE; return (0); } -#endif diff --git a/sys/powerpc/booke/locore.S b/sys/powerpc/booke/locore.S index 86dff0088494..b5b509097046 100644 --- a/sys/powerpc/booke/locore.S +++ b/sys/powerpc/booke/locore.S @@ -39,7 +39,6 @@ #include <machine/trap.h> #include <machine/vmparam.h> #include <machine/tlb.h> -#include <machine/bootinfo.h> #define TMPSTACKSZ 16384 diff --git a/sys/powerpc/booke/machdep.c b/sys/powerpc/booke/machdep.c index 274fe6e0d03f..054b0ed347bb 100644 --- a/sys/powerpc/booke/machdep.c +++ b/sys/powerpc/booke/machdep.c @@ -130,13 +130,14 @@ __FBSDID("$FreeBSD$"); #include <machine/mmuvar.h> #include <machine/sigframe.h> #include <machine/metadata.h> -#include <machine/bootinfo.h> #include <machine/platform.h> #include <sys/linker.h> #include <sys/reboot.h> -#include <powerpc/mpc85xx/ocpbus.h> +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> + #include <powerpc/mpc85xx/mpc85xx.h> #ifdef DDB @@ -169,8 +170,6 @@ int cold = 1; long realmem = 0; long Maxmem = 0; -struct bootinfo *bootinfo; - char machine[] = "powerpc"; SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); @@ -185,7 +184,6 @@ static void cpu_e500_startup(void *); SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_e500_startup, NULL); void print_kernel_section_addr(void); -void print_bootinfo(void); void print_kenv(void); u_int e500_init(u_int32_t, u_int32_t, void *); @@ -259,40 +257,6 @@ print_kenv(void) } void -print_bootinfo(void) -{ - struct bi_mem_region *mr; - struct bi_eth_addr *eth; - int i, j; - - debugf("bootinfo:\n"); - if (bootinfo == NULL) { - debugf(" no bootinfo, null ptr\n"); - return; - } - - debugf(" version = 0x%08x\n", bootinfo->bi_version); - debugf(" ccsrbar = 0x%08x\n", bootinfo->bi_bar_base); - debugf(" cpu_clk = 0x%08x\n", bootinfo->bi_cpu_clk); - debugf(" bus_clk = 0x%08x\n", bootinfo->bi_bus_clk); - - debugf(" mem regions:\n"); - mr = (struct bi_mem_region *)bootinfo->bi_data; - for (i = 0; i < bootinfo->bi_mem_reg_no; i++, mr++) - debugf(" #%d, base = 0x%08x, size = 0x%08x\n", i, - mr->mem_base, mr->mem_size); - - debugf(" eth addresses:\n"); - eth = (struct bi_eth_addr *)mr; - for (i = 0; i < bootinfo->bi_eth_addr_no; i++, eth++) { - debugf(" #%d, addr = ", i); - for (j = 0; j < 6; j++) - debugf("%02x ", eth->mac_addr[j]); - debugf("\n"); - } -} - -void print_kernel_section_addr(void) { @@ -306,54 +270,29 @@ print_kernel_section_addr(void) debugf(" _end = 0x%08x\n", (uint32_t)_end); } -struct bi_mem_region * -bootinfo_mr(void) -{ - - return ((struct bi_mem_region *)bootinfo->bi_data); -} - -struct bi_eth_addr * -bootinfo_eth(void) -{ - struct bi_mem_region *mr; - struct bi_eth_addr *eth; - int i; - - /* Advance to the eth section */ - mr = bootinfo_mr(); - for (i = 0; i < bootinfo->bi_mem_reg_no; i++, mr++) - ; - - eth = (struct bi_eth_addr *)mr; - return (eth); -} - u_int e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp) { struct pcpu *pc; void *kmdp; - vm_offset_t end; + vm_offset_t dtbp, end; uint32_t csr; kmdp = NULL; end = endkernel; + dtbp = (vm_offset_t)NULL; /* - * Parse metadata and fetch parameters. This must be done as the first - * step as we need bootinfo data to at least init the console + * Parse metadata and fetch parameters. */ if (mdp != NULL) { preload_metadata = mdp; kmdp = preload_search_by_type("elf kernel"); if (kmdp != NULL) { - bootinfo = (struct bootinfo *)preload_search_info(kmdp, - MODINFO_METADATA | MODINFOMD_BOOTINFO); - boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); + dtbp = MD_FETCH(kmdp, MODINFOMD_DTBP, vm_offset_t); end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t); #ifdef DDB ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t); @@ -362,8 +301,7 @@ e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp) } } else { /* - * We should scream but how? - without CCSR bar (in bootinfo) - * cannot even output anything... + * We should scream but how? Cannot even output anything... */ /* @@ -372,11 +310,22 @@ e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp) * restore everything as the TLB have all been reprogrammed * in the locore etc...) */ - while(1); + while (1); } + if (OF_install(OFW_FDT, 0) == FALSE) + while (1); + + if (OF_init((void *)dtbp) != 0) + while (1); + + if (fdt_immr_addr() != 0) + while (1); + + OF_interpret("perform-fixup", 0); + /* Initialize TLB1 handling */ - tlb1_init(bootinfo->bi_bar_base); + tlb1_init(fdt_immr_pa); /* Reset Time Base */ mttb(0); @@ -417,7 +366,8 @@ e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp) csr = ccsr_read4(OCP85XX_L2CTL); debugf(" L2CTL = 0x%08x\n", csr); - print_bootinfo(); + debugf(" dtbp = 0x%08x\n", (uint32_t)dtbp); + print_kernel_section_addr(); print_kenv(); //tlb1_print_entries(); diff --git a/sys/powerpc/booke/platform_bare.c b/sys/powerpc/booke/platform_bare.c index 92d8ec807f62..627470d6ccee 100644 --- a/sys/powerpc/booke/platform_bare.c +++ b/sys/powerpc/booke/platform_bare.c @@ -35,7 +35,6 @@ __FBSDID("$FreeBSD$"); #include <sys/proc.h> #include <sys/smp.h> -#include <machine/bootinfo.h> #include <machine/bus.h> #include <machine/cpu.h> #include <machine/hid.h> @@ -45,8 +44,12 @@ __FBSDID("$FreeBSD$"); #include <machine/spr.h> #include <machine/vmparam.h> +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> +#include <dev/ofw/openfirm.h> + #include <powerpc/mpc85xx/mpc85xx.h> -#include <powerpc/mpc85xx/ocpbus.h> #include "platform_if.h" @@ -91,7 +94,8 @@ PLATFORM_DEF(bare_platform); static int bare_probe(platform_t plat) { - uint32_t ver; + uint32_t ver, sr; + int i, law_max, tgt; ver = SVR_VER(mfspr(SPR_SVR)); if (ver == SVR_MPC8572E || ver == SVR_MPC8572) @@ -99,6 +103,23 @@ bare_probe(platform_t plat) else maxcpu = 1; + /* + * Clear local access windows. Skip DRAM entries, so we don't shoot + * ourselves in the foot. + */ + law_max = law_getmax(); + for (i = 0; i < law_max; i++) { + sr = ccsr_read4(OCP85XX_LAWSR(i)); + if ((sr & 0x80000000) == 0) + continue; + tgt = (sr & 0x01f00000) >> 20; + if (tgt == OCP85XX_TGTIF_RAM1 || tgt == OCP85XX_TGTIF_RAM2 || + tgt == OCP85XX_TGTIF_RAM_INTL) + continue; + + ccsr_write4(OCP85XX_LAWSR(i), sr & 0x7fffffff); + } + return (BUS_PROBE_GENERIC); } @@ -109,24 +130,22 @@ void bare_mem_regions(platform_t plat, struct mem_region **phys, int *physsz, struct mem_region **avail, int *availsz) { - struct bi_mem_region *mr; - int i; - - /* Initialize memory regions table */ - mr = bootinfo_mr(); - for (i = 0; i < bootinfo->bi_mem_reg_no; i++, mr++) { - if (i == MEM_REGIONS) - break; - if (mr->mem_base < 1048576) { + uint32_t memsize; + int i, rv; + + rv = fdt_get_mem_regions(avail_regions, availsz, &memsize); + + if (rv != 0) + return; + + for (i = 0; i < *availsz; i++) { + if (avail_regions[i].mr_start < 1048576) { + avail_regions[i].mr_size = + avail_regions[i].mr_size - + (1048576 - avail_regions[i].mr_start); avail_regions[i].mr_start = 1048576; - avail_regions[i].mr_size = mr->mem_size - - (1048576 - mr->mem_base); - } else { - avail_regions[i].mr_start = mr->mem_base; - avail_regions[i].mr_size = mr->mem_size; } } - *availsz = i; *avail = avail_regions; /* On the bare metal platform phys == avail memory */ @@ -138,12 +157,24 @@ static u_long bare_timebase_freq(platform_t plat, struct cpuref *cpuref) { u_long ticks = -1; + phandle_t cpus, child; + pcell_t freq; + + if ((cpus = OF_finddevice("/cpus")) == 0) + goto out; + + if ((child = OF_child(cpus)) == 0) + goto out; + if (OF_getprop(child, "bus-frequency", (void *)&freq, + sizeof(freq)) <= 0) + goto out; /* * Time Base and Decrementer are updated every 8 CCB bus clocks. * HID0[SEL_TBCLK] = 0 */ - ticks = bootinfo->bi_bus_clk / 8; + ticks = freq / 8; +out: if (ticks <= 0) panic("Unable to determine timebase frequency!"); diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c index 11a67afd2bd3..7f2feb947dc1 100644 --- a/sys/powerpc/booke/pmap.c +++ b/sys/powerpc/booke/pmap.c @@ -77,7 +77,6 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_pager.h> #include <vm/uma.h> -#include <machine/bootinfo.h> #include <machine/cpu.h> #include <machine/pcb.h> #include <machine/platform.h> @@ -2507,7 +2506,6 @@ struct pmap_md * mmu_booke_scan_md(mmu_t mmu, struct pmap_md *prev) { static struct pmap_md md; - struct bi_mem_region *mr; pte_t *pte; vm_offset_t va; @@ -2565,16 +2563,18 @@ mmu_booke_scan_md(mmu_t mmu, struct pmap_md *prev) return (NULL); } } else { /* minidumps */ - mr = bootinfo_mr(); + mem_regions(&physmem_regions, &physmem_regions_sz, + &availmem_regions, &availmem_regions_sz); + if (prev == NULL) { /* first physical chunk. */ - md.md_paddr = mr->mem_base; - md.md_size = mr->mem_size; + md.md_paddr = physmem_regions[0].mr_start; + md.md_size = physmem_regions[0].mr_size; md.md_vaddr = ~0UL; md.md_index = 1; - } else if (md.md_index < bootinfo->bi_mem_reg_no) { - md.md_paddr = mr[md.md_index].mem_base; - md.md_size = mr[md.md_index].mem_size; + } else if (md.md_index < physmem_regions_sz) { + md.md_paddr = physmem_regions[md.md_index].mr_start; + md.md_size = physmem_regions[md.md_index].mr_size; md.md_vaddr = ~0UL; md.md_index++; } else { diff --git a/sys/powerpc/conf/MPC85XX b/sys/powerpc/conf/MPC85XX index a2a8de4a9a3f..ef36ab5f2e0f 100644 --- a/sys/powerpc/conf/MPC85XX +++ b/sys/powerpc/conf/MPC85XX @@ -24,8 +24,10 @@ options COMPAT_43 options DDB #options DEADLKRES options DEVICE_POLLING -options HZ=1000 #options DIAGNOSTIC +options FDT +makeoptions FDT_DTS_FILE=mpc8572ds.dts +#makeoptions FDT_DTS_FILE=mpc8555cds.dts options FFS options GDB options GEOM_PART_GPT @@ -64,7 +66,7 @@ device ether device fxp device iic device iicbus -device isa +#device isa device loop device md device miibus diff --git a/sys/powerpc/include/bootinfo.h b/sys/powerpc/include/bootinfo.h deleted file mode 100644 index 599516e57e6f..000000000000 --- a/sys/powerpc/include/bootinfo.h +++ /dev/null @@ -1,72 +0,0 @@ -/*- - * Copyright (C) 2006-2008 Semihalf, Marian Balakowicz <m8@semihalf.com> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _MACHINE_BOOTINFO_H_ -#define _MACHINE_BOOTINFO_H_ - -#if !defined(LOCORE) - -/* Platform hardware spec, received from loader(8) */ - -#define BI_VERSION 1 - -struct bi_mem_region { - vm_paddr_t mem_base; - vm_size_t mem_size; -}; - -struct bi_eth_addr { - u_int8_t mac_addr[6]; -}; - -struct bootinfo { - u_int32_t bi_version; - vm_offset_t bi_bar_base; - u_int32_t bi_cpu_clk; - u_int32_t bi_bus_clk; - u_int8_t bi_mem_reg_no; - u_int8_t bi_eth_addr_no; - - u_int8_t bi_data[1]; - /* - * The bi_data container is allocated in run time and has the - * following layout: - * - * - bi_mem_reg_no elements of struct bi_mem_region - * - bi_eth_addr_no elements of struct bi_eth_addr - */ -}; - -extern struct bootinfo *bootinfo; - -struct bi_mem_region *bootinfo_mr(void); -struct bi_eth_addr *bootinfo_eth(void); -#endif - -#endif /* _MACHINE_BOOTINFO_H_ */ diff --git a/sys/powerpc/include/fdt.h b/sys/powerpc/include/fdt.h new file mode 100644 index 000000000000..ea29d6850c9e --- /dev/null +++ b/sys/powerpc/include/fdt.h @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 2010 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Semihalf under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_FDT_H_ +#define _MACHINE_FDT_H_ + +#include <machine/bus.h> +#include <machine/intr_machdep.h> +#include <machine/platform.h> +#include <machine/vmparam.h> + +/* + * This is the base virtual address the internal mem-mapped registers (IMMR) + * range is available at. + */ +#define FDT_IMMR_VA CCSRBAR_VA + +/* Max interrupt number */ +#define FDT_INTR_MAX INTR_VECTORS + +/* + * Bus space tag. XXX endianess info needs to be derived from the blob. + */ +#define fdtbus_bs_tag (&bs_be_tag) + +#endif /* _MACHINE_FDT_H_ */ diff --git a/sys/powerpc/include/metadata.h b/sys/powerpc/include/metadata.h index 8c15e6a734ef..5a58839681c2 100644 --- a/sys/powerpc/include/metadata.h +++ b/sys/powerpc/include/metadata.h @@ -32,7 +32,6 @@ #define MODINFOMD_ENVP 0x1001 #define MODINFOMD_HOWTO 0x1002 #define MODINFOMD_KERNEND 0x1003 -#define MODINFOMD_BOOTINFO 0x1004 -#define MODINFOMD_DTBP 0x1005 +#define MODINFOMD_DTBP 0x1004 #endif /* !_MACHINE_METADATA_H_ */ diff --git a/sys/powerpc/include/ocpbus.h b/sys/powerpc/include/ocpbus.h deleted file mode 100644 index daa952bfd705..000000000000 --- a/sys/powerpc/include/ocpbus.h +++ /dev/null @@ -1,51 +0,0 @@ -/*- - * Copyright (c) 2006 Juniper Networks - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _MACHINE_OCPBUS_H_ -#define _MACHINE_OCPBUS_H_ - -#define OCPBUS_IVAR_DEVTYPE 1 -#define OCPBUS_IVAR_CLOCK 2 -#define OCPBUS_IVAR_HWUNIT 3 -#define OCPBUS_IVAR_MACADDR 4 - -/* Device types. */ -#define OCPBUS_DEVTYPE_PIC 1 -#define OCPBUS_DEVTYPE_TSEC 2 -#define OCPBUS_DEVTYPE_UART 3 -#define OCPBUS_DEVTYPE_QUICC 4 -#define OCPBUS_DEVTYPE_PCIB 5 -#define OCPBUS_DEVTYPE_LBC 6 -#define OCPBUS_DEVTYPE_I2C 7 -#define OCPBUS_DEVTYPE_SEC 8 - -/* PIC IDs */ -#define OPIC_ID 0 -#define ATPIC_ID 1 - -#endif /* _MACHINE_OCPBUS_H_ */ diff --git a/sys/powerpc/mpc85xx/atpic.c b/sys/powerpc/mpc85xx/atpic.c index 3a749c7db4e2..e903dbc81762 100644 --- a/sys/powerpc/mpc85xx/atpic.c +++ b/sys/powerpc/mpc85xx/atpic.c @@ -39,7 +39,7 @@ __FBSDID("$FreeBSD$"); #include <machine/ocpbus.h> #include <machine/pio.h> -#include <powerpc/mpc85xx/ocpbus.h> +#include <powerpc/mpc85xx/mpc85xx.h> #include <dev/ic/i8259.h> diff --git a/sys/powerpc/mpc85xx/ds1553_bus_lbc.c b/sys/powerpc/mpc85xx/ds1553_bus_fdt.c index 419a8a8c8e3c..ffbbee195fdf 100644 --- a/sys/powerpc/mpc85xx/ds1553_bus_lbc.c +++ b/sys/powerpc/mpc85xx/ds1553_bus_fdt.c @@ -23,6 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * From: FreeBSD: src/sys/powerpc/mpc85xx/ds1553_bus_lbc.c,v 1.2 2009/06/24 15:48:20 raj */ #include <sys/cdefs.h> @@ -43,9 +44,9 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> #include <machine/resource.h> -#include <powerpc/mpc85xx/ds1553_reg.h> -#include <powerpc/mpc85xx/lbc.h> +#include <dev/ofw/ofw_bus_subr.h> +#include "ds1553_reg.h" #include "clock_if.h" static devclass_t rtc_devclass; @@ -76,20 +77,12 @@ DRIVER_MODULE(rtc, lbc, rtc_driver, rtc_devclass, 0, 0); static int rtc_probe(device_t dev) { - uintptr_t devtype; - int error; - - error = BUS_READ_IVAR(device_get_parent(dev), dev, LBC_IVAR_DEVTYPE, - &devtype); - if (error) - return (error); - if (devtype != LBC_DEVTYPE_RTC) - return (EINVAL); + if (!ofw_bus_is_compatible(dev, "dallas,ds1553")) + return (ENXIO); device_set_desc(dev, "Dallas Semiconductor DS1553 RTC"); - - return (0); + return (BUS_PROBE_DEFAULT); } static int diff --git a/sys/powerpc/mpc85xx/i2c.c b/sys/powerpc/mpc85xx/i2c.c index 003bd6fb5d72..5b698f1b957c 100644 --- a/sys/powerpc/mpc85xx/i2c.c +++ b/sys/powerpc/mpc85xx/i2c.c @@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> #include <machine/resource.h> -#include <machine/ocpbus.h> #include <sys/rman.h> #include <sys/lock.h> @@ -46,7 +45,8 @@ __FBSDID("$FreeBSD$"); #include <dev/iicbus/iicbus.h> #include "iicbus_if.h" -#include <powerpc/mpc85xx/ocpbus.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> #define I2C_ADDR_REG 0x00 /* I2C slave address register */ #define I2C_FDR_REG 0x04 /* I2C frequency divider register */ @@ -124,7 +124,7 @@ static driver_t i2c_driver = { }; static devclass_t i2c_devclass; -DRIVER_MODULE(i2c, ocpbus, i2c_driver, i2c_devclass, 0, 0); +DRIVER_MODULE(i2c, simplebus, i2c_driver, i2c_devclass, 0, 0); DRIVER_MODULE(iicbus, i2c, iicbus_driver, iicbus_devclass, 0, 0); static __inline void @@ -157,7 +157,7 @@ i2c_do_wait(device_t dev, struct i2c_softc *sc, int write, int start) int err; uint8_t status; - status = i2c_read_reg(sc,I2C_STATUS_REG); + status = i2c_read_reg(sc, I2C_STATUS_REG); if (status & I2CSR_MIF) { if (write && start && (status & I2CSR_RXAK)) { debugf("no ack %s", start ? @@ -188,19 +188,9 @@ error: static int i2c_probe(device_t dev) { - device_t parent; struct i2c_softc *sc; - uintptr_t devtype; - int error; - - parent = device_get_parent(dev); - - error = BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_DEVTYPE, &devtype); - if (error) - return (error); - - if (devtype != OCPBUS_DEVTYPE_I2C) + if (!ofw_bus_is_compatible(dev, "fsl-i2c")) return (ENXIO); sc = device_get_softc(dev); @@ -209,7 +199,7 @@ i2c_probe(device_t dev) sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid, RF_ACTIVE); if (sc->res == NULL) { - device_printf(dev, "could not allocate resources"); + device_printf(dev, "could not allocate resources\n"); return (ENXIO); } diff --git a/sys/powerpc/mpc85xx/lbc.c b/sys/powerpc/mpc85xx/lbc.c index 2267245da080..e993bced9ae0 100644 --- a/sys/powerpc/mpc85xx/lbc.c +++ b/sys/powerpc/mpc85xx/lbc.c @@ -1,8 +1,12 @@ /*- * Copyright (c) 2006-2008, Juniper Networks, Inc. * Copyright (c) 2008 Semihalf, Rafal Czubak + * Copyright (c) 2009 The FreeBSD Foundation * All rights reserved. * + * Portions of this software were developed by Semihalf + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,70 +43,54 @@ __FBSDID("$FreeBSD$"); #include <sys/bus.h> #include <sys/rman.h> #include <machine/bus.h> -#include <machine/ocpbus.h> #include <vm/vm.h> #include <vm/pmap.h> -#include <powerpc/mpc85xx/lbc.h> +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + #include <powerpc/mpc85xx/mpc85xx.h> -#include <powerpc/mpc85xx/ocpbus.h> -struct lbc_softc { - device_t sc_dev; +#include "ofw_bus_if.h" +#include "lbc.h" - struct resource *sc_res; - bus_space_handle_t sc_bsh; - bus_space_tag_t sc_bst; - int sc_rid; +#define DEBUG +#undef DEBUG - struct rman sc_rman; - vm_offset_t sc_kva[LBC_DEV_MAX]; -}; +#ifdef DEBUG +#define debugf(fmt, args...) do { printf("%s(): ", __func__); \ + printf(fmt,##args); } while (0) +#else +#define debugf(fmt, args...) +#endif -struct lbc_devinfo { - int lbc_devtype; - /* LBC child unit. It also represents resource table entry number */ - int lbc_unit; -}; +static __inline void +lbc_write_reg(struct lbc_softc *sc, bus_size_t off, uint32_t val) +{ -/* Resources for MPC8555CDS system */ -const struct lbc_resource mpc85xx_lbc_resources[] = { - /* Boot flash bank */ - { - LBC_DEVTYPE_CFI, 0, 0xff800000, 0x00800000, 16, - LBCRES_MSEL_GPCM, LBCRES_DECC_DISABLED, - LBCRES_ATOM_DISABLED, 0 - }, - - /* Second flash bank */ - { - LBC_DEVTYPE_CFI, 1, 0xff000000, 0x00800000, 16, - LBCRES_MSEL_GPCM, LBCRES_DECC_DISABLED, - LBCRES_ATOM_DISABLED, 0 - }, - - /* DS1553 RTC/NVRAM */ - { - LBC_DEVTYPE_RTC, 2, 0xf8000000, 0x8000, 8, - LBCRES_MSEL_GPCM, LBCRES_DECC_DISABLED, - LBCRES_ATOM_DISABLED, 0 - }, - - {0} -}; + bus_space_write_4(sc->sc_bst, sc->sc_bsh, off, val); +} + +static __inline uint32_t +lbc_read_reg(struct lbc_softc *sc, bus_size_t off) +{ + + return (bus_space_read_4(sc->sc_bst, sc->sc_bsh, off)); +} + +static MALLOC_DEFINE(M_LBC, "localbus", "localbus devices information"); static int lbc_probe(device_t); static int lbc_attach(device_t); static int lbc_shutdown(device_t); -static int lbc_get_resource(device_t, device_t, int, int, u_long *, - u_long *); static struct resource *lbc_alloc_resource(device_t, device_t, int, int *, u_long, u_long, u_long, u_int); static int lbc_print_child(device_t, device_t); static int lbc_release_resource(device_t, device_t, int, int, struct resource *); -static int lbc_read_ivar(device_t, device_t, int, uintptr_t *); +static const struct ofw_bus_devinfo *lbc_get_devinfo(device_t, device_t); /* * Bus interface definition @@ -115,16 +103,22 @@ static device_method_t lbc_methods[] = { /* Bus interface */ DEVMETHOD(bus_print_child, lbc_print_child), - DEVMETHOD(bus_read_ivar, lbc_read_ivar), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, NULL), - DEVMETHOD(bus_get_resource, NULL), DEVMETHOD(bus_alloc_resource, lbc_alloc_resource), DEVMETHOD(bus_release_resource, lbc_release_resource), DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + /* OFW bus interface */ + DEVMETHOD(ofw_bus_get_devinfo, lbc_get_devinfo), + DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), + DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), + DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), + DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), + DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), + { 0, 0 } }; @@ -133,22 +127,10 @@ static driver_t lbc_driver = { lbc_methods, sizeof(struct lbc_softc) }; -devclass_t lbc_devclass; -DRIVER_MODULE(lbc, ocpbus, lbc_driver, lbc_devclass, 0, 0); - -static __inline void -lbc_write_reg(struct lbc_softc *sc, bus_size_t off, uint32_t val) -{ - bus_space_write_4(sc->sc_bst, sc->sc_bsh, off, val); -} - -static __inline uint32_t -lbc_read_reg(struct lbc_softc *sc, bus_size_t off) -{ +devclass_t lbc_devclass; - return (bus_space_read_4(sc->sc_bst, sc->sc_bsh, off)); -} +DRIVER_MODULE(lbc, fdtbus, lbc_driver, lbc_devclass, 0, 0); /* * Calculate address mask used by OR(n) registers. Use memory region size to @@ -176,103 +158,101 @@ lbc_address_mask(uint32_t size) return (0xffff8000 << (n - 15)); } -static device_t -lbc_mk_child(device_t dev, const struct lbc_resource *lbcres) +static void +lbc_banks_unmap(struct lbc_softc *sc) { - struct lbc_devinfo *dinfo; - device_t child; + int i; - if (lbcres->lbr_unit > LBC_DEV_MAX - 1) - return (NULL); + for (i = 0; i < LBC_DEV_MAX; i++) { + if (sc->sc_banks[i].size == 0) + continue; - child = device_add_child(dev, NULL, -1); - if (child == NULL) { - device_printf(dev, "could not add LBC child device\n"); - return (NULL); + law_disable(OCP85XX_TGTIF_LBC, sc->sc_banks[i].pa, + sc->sc_banks[i].size); + pmap_unmapdev(sc->sc_banks[i].va, sc->sc_banks[i].size); } - dinfo = malloc(sizeof(struct lbc_devinfo), M_DEVBUF, M_WAITOK | M_ZERO); - dinfo->lbc_devtype = lbcres->lbr_devtype; - dinfo->lbc_unit = lbcres->lbr_unit; - device_set_ivars(child, dinfo); - return (child); } static int -lbc_init_child(device_t dev, device_t child) +lbc_banks_map(struct lbc_softc *sc) { - struct lbc_softc *sc; - struct lbc_devinfo *dinfo; - const struct lbc_resource *res; u_long start, size; - uint32_t regbuff; - int error, unit; - - sc = device_get_softc(dev); - dinfo = device_get_ivars(child); + int error, i; - res = mpc85xx_lbc_resources; - - regbuff = 0; - unit = -1; - for (; res->lbr_devtype; res++) { - if (res->lbr_unit != dinfo->lbc_unit) + for (i = 0; i < LBC_DEV_MAX; i++) { + if (sc->sc_banks[i].size == 0) continue; - start = res->lbr_base_addr; - size = res->lbr_size; - unit = res->lbr_unit; + /* Physical address start/size. */ + start = sc->sc_banks[i].pa; + size = sc->sc_banks[i].size; /* - * Configure LAW for this LBC device and map its physical - * memory region into KVA + * Configure LAW for this LBC bank (CS) and map its physical + * memory region into KVA. */ error = law_enable(OCP85XX_TGTIF_LBC, start, size); if (error) return (error); - sc->sc_kva[unit] = (vm_offset_t)pmap_mapdev(start, size); - if (sc->sc_kva[unit] == 0) { - law_disable(OCP85XX_TGTIF_LBC, start, size); + sc->sc_banks[i].va = (vm_offset_t)pmap_mapdev(start, size); + if (sc->sc_banks[i].va == 0) { + lbc_banks_unmap(sc); return (ENOSPC); } + } + return (0); +} + +static int +lbc_banks_enable(struct lbc_softc *sc) +{ + u_long size; + uint32_t regval; + int error, i; + for (i = 0; i < LBC_DEV_MAX; i++) { + size = sc->sc_banks[i].size; + if (size == 0) + continue; /* - * Compute and program BR value + * Compute and program BR value. */ - regbuff |= start; + regval = 0; + regval |= sc->sc_banks[i].pa; - switch (res->lbr_port_size) { + switch (sc->sc_banks[i].width) { case 8: - regbuff |= (1 << 11); + regval |= (1 << 11); break; case 16: - regbuff |= (2 << 11); + regval |= (2 << 11); break; case 32: - regbuff |= (3 << 11); + regval |= (3 << 11); break; default: error = EINVAL; goto fail; } - regbuff |= (res->lbr_decc << 9); - regbuff |= (res->lbr_wp << 8); - regbuff |= (res->lbr_msel << 5); - regbuff |= (res->lbr_atom << 2); - regbuff |= 1; + regval |= (sc->sc_banks[i].decc << 9); + regval |= (sc->sc_banks[i].wp << 8); + regval |= (sc->sc_banks[i].msel << 5); + regval |= (sc->sc_banks[i].atom << 2); + regval |= 1; - lbc_write_reg(sc, LBC85XX_BR(unit), regbuff); + lbc_write_reg(sc, LBC85XX_BR(i), regval); /* - * Compute and program OR value + * Compute and program OR value. */ - regbuff = 0; - regbuff |= lbc_address_mask(size); + regval = 0; + regval |= lbc_address_mask(size); - switch (res->lbr_msel) { + switch (sc->sc_banks[i].msel) { case LBCRES_MSEL_GPCM: /* TODO Add flag support for option registers */ - regbuff |= 0x00000ff7; + regval |= 0x00000ff7; break; case LBCRES_MSEL_FCM: printf("FCM mode not supported yet!"); @@ -285,35 +265,114 @@ lbc_init_child(device_t dev, device_t child) error = ENOSYS; goto fail; } + lbc_write_reg(sc, LBC85XX_OR(i), regval); + } - lbc_write_reg(sc, LBC85XX_OR(unit), regbuff); + /* + * Initialize configuration register: + * - enable Local Bus + * - set data buffer control signal function + * - disable parity byte select + * - set ECC parity type + * - set bus monitor timing and timer prescale + */ + lbc_write_reg(sc, LBC85XX_LBCR, 0); + + /* + * Initialize clock ratio register: + * - disable PLL bypass mode + * - configure LCLK delay cycles for the assertion of LALE + * - set system clock divider + */ + lbc_write_reg(sc, LBC85XX_LCRR, 0x00030008); + + return (0); + +fail: + lbc_banks_unmap(sc); + return (error); +} + +static void +fdt_lbc_fixup(phandle_t node, struct lbc_softc *sc, struct lbc_devinfo *di) +{ + pcell_t width; + int bank; + if (OF_getprop(node, "bank-width", (void *)&width, sizeof(width)) <= 0) + return; + + bank = di->di_bank; + if (sc->sc_banks[bank].size == 0) + return; + + /* Express width in bits. */ + sc->sc_banks[bank].width = width * 8; +} + +static int +fdt_lbc_reg_decode(phandle_t node, struct lbc_softc *sc, + struct lbc_devinfo *di) +{ + u_long start, end, count; + pcell_t *reg, *regptr; + pcell_t addr_cells, size_cells; + int tuple_size, tuples; + int i, rv, bank; + + if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells) != 0) + return (ENXIO); + + tuple_size = sizeof(pcell_t) * (addr_cells + size_cells); + tuples = OF_getprop_alloc(node, "reg", tuple_size, (void **)®); + debugf("addr_cells = %d, size_cells = %d\n", addr_cells, size_cells); + debugf("tuples = %d, tuple size = %d\n", tuples, tuple_size); + if (tuples <= 0) + /* No 'reg' property in this node. */ return (0); + + regptr = reg; + for (i = 0; i < tuples; i++) { + + bank = fdt_data_get((void *)reg, 1); + di->di_bank = bank; + reg += 1; + + /* Get address/size. */ + rv = fdt_data_to_res(reg, addr_cells - 1, size_cells, &start, + &count); + if (rv != 0) { + resource_list_free(&di->di_res); + goto out; + } + reg += addr_cells - 1 + size_cells; + + /* Calculate address range relative to VA base. */ + start = sc->sc_banks[bank].va + start; + end = start + count - 1; + + debugf("reg addr bank = %d, start = %lx, end = %lx, " + "count = %lx\n", bank, start, end, count); + + /* Use bank (CS) cell as rid. */ + resource_list_add(&di->di_res, SYS_RES_MEMORY, bank, start, + end, count); } -fail: - if (unit != -1) { - law_disable(OCP85XX_TGTIF_LBC, start, size); - pmap_unmapdev(sc->sc_kva[unit], size); - return (error); - } else - return (ENOENT); + rv = 0; +out: + free(regptr, M_OFWPROP); + return (rv); } static int lbc_probe(device_t dev) { - device_t parent; - uintptr_t devtype; - int error; - parent = device_get_parent(dev); - error = BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_DEVTYPE, &devtype); - if (error) - return (error); - if (devtype != OCPBUS_DEVTYPE_LBC) + if (!(ofw_bus_is_compatible(dev, "fsl,lbc") || + ofw_bus_is_compatible(dev, "fsl,elbc"))) return (ENXIO); - device_set_desc(dev, "Freescale MPC85xx Local Bus Controller"); + device_set_desc(dev, "Freescale Local Bus Controller"); return (BUS_PROBE_DEFAULT); } @@ -321,9 +380,15 @@ static int lbc_attach(device_t dev) { struct lbc_softc *sc; + struct lbc_devinfo *di; struct rman *rm; - const struct lbc_resource *lbcres; - int error; + u_long offset, start, size; + device_t cdev; + phandle_t node, child; + pcell_t *ranges, *rangesptr; + int tuple_size, tuples; + int par_addr_cells; + int bank, error, i; sc = device_get_softc(dev); sc->sc_dev = dev; @@ -336,10 +401,11 @@ lbc_attach(device_t dev) sc->sc_bst = rman_get_bustag(sc->sc_res); sc->sc_bsh = rman_get_bushandle(sc->sc_res); + rangesptr = NULL; rm = &sc->sc_rman; rm->rm_type = RMAN_ARRAY; - rm->rm_descr = "MPC85XX Local Bus Space"; + rm->rm_descr = "Local Bus Space"; rm->rm_start = 0UL; rm->rm_end = ~0UL; error = rman_init(rm); @@ -353,34 +419,139 @@ lbc_attach(device_t dev) } /* - * Initialize configuration register: - * - enable Local Bus - * - set data buffer control signal function - * - disable parity byte select - * - set ECC parity type - * - set bus monitor timing and timer prescale + * Process 'ranges' property. */ - lbc_write_reg(sc, LBC85XX_LBCR, 0x00000000); + node = ofw_bus_get_node(dev); + if ((fdt_addrsize_cells(node, &sc->sc_addr_cells, + &sc->sc_size_cells)) != 0) { + error = ENXIO; + goto fail; + } + + par_addr_cells = fdt_parent_addr_cells(node); + if (par_addr_cells > 2) { + device_printf(dev, "unsupported parent #addr-cells\n"); + error = ERANGE; + goto fail; + } + tuple_size = sizeof(pcell_t) * (sc->sc_addr_cells + par_addr_cells + + sc->sc_size_cells); + + tuples = OF_getprop_alloc(node, "ranges", tuple_size, + (void **)&ranges); + if (tuples < 0) { + device_printf(dev, "could not retrieve 'ranges' property\n"); + error = ENXIO; + goto fail; + } + rangesptr = ranges; + + debugf("par addr_cells = %d, addr_cells = %d, size_cells = %d, " + "tuple_size = %d, tuples = %d\n", par_addr_cells, + sc->sc_addr_cells, sc->sc_size_cells, tuple_size, tuples); + + start = 0; + size = 0; + for (i = 0; i < tuples; i++) { + + /* The first cell is the bank (chip select) number. */ + bank = fdt_data_get((void *)ranges, 1); + if (bank < 0 || bank > LBC_DEV_MAX) { + device_printf(dev, "bank out of range: %d\n", bank); + error = ERANGE; + goto fail; + } + ranges += 1; + + /* + * Remaining cells of the child address define offset into + * this CS. + */ + offset = fdt_data_get((void *)ranges, sc->sc_addr_cells - 1); + ranges += sc->sc_addr_cells - 1; + + /* Parent bus start address of this bank. */ + start = fdt_data_get((void *)ranges, par_addr_cells); + ranges += par_addr_cells; + + size = fdt_data_get((void *)ranges, sc->sc_size_cells); + ranges += sc->sc_size_cells; + debugf("bank = %d, start = %lx, size = %lx\n", bank, + start, size); + + sc->sc_banks[bank].pa = start + offset; + sc->sc_banks[bank].size = size; + + /* + * Attributes for the bank. + * + * XXX Note there are no DT bindings defined for them at the + * moment, so we need to provide some defaults. + */ + sc->sc_banks[bank].width = 16; + sc->sc_banks[bank].msel = LBCRES_MSEL_GPCM; + sc->sc_banks[bank].decc = LBCRES_DECC_DISABLED; + sc->sc_banks[bank].atom = LBCRES_ATOM_DISABLED; + sc->sc_banks[bank].wp = 0; + } /* - * Initialize clock ratio register: - * - disable PLL bypass mode - * - configure LCLK delay cycles for the assertion of LALE - * - set system clock divider + * Initialize mem-mappings for the LBC banks (i.e. chip selects). */ - lbc_write_reg(sc, LBC85XX_LCRR, 0x00030008); + error = lbc_banks_map(sc); + if (error) + goto fail; - lbcres = mpc85xx_lbc_resources; + /* + * Walk the localbus and add direct subordinates as our children. + */ + for (child = OF_child(node); child != 0; child = OF_peer(child)) { - for (; lbcres->lbr_devtype; lbcres++) - if (!lbc_mk_child(dev, lbcres)) { - error = ENXIO; - goto fail; + di = malloc(sizeof(*di), M_LBC, M_WAITOK | M_ZERO); + + if (ofw_bus_gen_setup_devinfo(&di->di_ofw, child) != 0) { + free(di, M_LBC); + device_printf(dev, "could not set up devinfo\n"); + continue; + } + + resource_list_init(&di->di_res); + + if (fdt_lbc_reg_decode(child, sc, di)) { + device_printf(dev, "could not process 'reg' " + "property\n"); + ofw_bus_gen_destroy_devinfo(&di->di_ofw); + free(di, M_LBC); + continue; + } + + fdt_lbc_fixup(child, sc, di); + + /* Add newbus device for this FDT node */ + cdev = device_add_child(dev, NULL, -1); + if (cdev == NULL) { + device_printf(dev, "could not add child: %s\n", + di->di_ofw.obd_name); + resource_list_free(&di->di_res); + ofw_bus_gen_destroy_devinfo(&di->di_ofw); + free(di, M_LBC); + continue; } + debugf("added child name='%s', node=%p\n", di->di_ofw.obd_name, + (void *)child); + device_set_ivars(cdev, di); + } + + /* + * Enable the LBC. + */ + lbc_banks_enable(sc); + free(rangesptr, M_OFWPROP); return (bus_generic_attach(dev)); fail: + free(rangesptr, M_OFWPROP); bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res); return (error); } @@ -394,137 +565,114 @@ lbc_shutdown(device_t dev) } static struct resource * -lbc_alloc_resource(device_t dev, device_t child, int type, int *rid, +lbc_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct lbc_softc *sc; - struct lbc_devinfo *dinfo; - struct resource *rv; + struct lbc_devinfo *di; + struct resource_list_entry *rle; + struct resource *res; struct rman *rm; - int error; - - sc = device_get_softc(dev); - dinfo = device_get_ivars(child); - - if (type != SYS_RES_MEMORY && type != SYS_RES_IRQ) - return (NULL); + int needactivate; /* We only support default allocations. */ if (start != 0ul || end != ~0ul) return (NULL); + sc = device_get_softc(bus); if (type == SYS_RES_IRQ) - return (bus_alloc_resource(dev, type, rid, start, end, count, + return (bus_alloc_resource(bus, type, rid, start, end, count, flags)); - if (!sc->sc_kva[dinfo->lbc_unit]) { - error = lbc_init_child(dev, child); - if (error) - return (NULL); - } - - error = lbc_get_resource(dev, child, type, *rid, &start, &count); - if (error) + /* + * Request for the default allocation with a given rid: use resource + * list stored in the local device info. + */ + if ((di = device_get_ivars(child)) == NULL) return (NULL); - rm = &sc->sc_rman; - end = start + count - 1; - rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv != NULL) { - rman_set_bustag(rv, &bs_be_tag); - rman_set_bushandle(rv, rman_get_start(rv)); + if (type == SYS_RES_IOPORT) + type = SYS_RES_MEMORY; + + rid = &di->di_bank; + + rle = resource_list_find(&di->di_res, type, *rid); + if (rle == NULL) { + device_printf(bus, "no default resources for " + "rid = %d, type = %d\n", *rid, type); + return (NULL); } - return (rv); -} + start = rle->start; + count = rle->count; + end = start + count - 1; -static int -lbc_print_child(device_t dev, device_t child) -{ - u_long size, start; - int error, retval, rid; + sc = device_get_softc(bus); - retval = bus_print_child_header(dev, child); + needactivate = flags & RF_ACTIVE; + flags &= ~RF_ACTIVE; - rid = 0; - while (1) { - error = lbc_get_resource(dev, child, SYS_RES_MEMORY, rid, - &start, &size); - if (error) - break; - retval += (rid == 0) ? printf(" iomem ") : printf(","); - retval += printf("%#lx", start); - if (size > 1) - retval += printf("-%#lx", start + size - 1); - rid++; + rm = &sc->sc_rman; + + res = rman_reserve_resource(rm, start, end, count, flags, child); + if (res == NULL) { + device_printf(bus, "failed to reserve resource %#lx - %#lx " + "(%#lx)\n", start, end, count); + return (NULL); } - retval += bus_print_child_footer(dev, child); - return (retval); + rman_set_rid(res, *rid); + rman_set_bustag(res, &bs_be_tag); + rman_set_bushandle(res, rman_get_start(res)); + + if (needactivate) + if (bus_activate_resource(child, type, *rid, res)) { + device_printf(child, "resource activation failed\n"); + rman_release_resource(res); + return (NULL); + } + + return (res); } static int -lbc_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) +lbc_print_child(device_t dev, device_t child) { - struct lbc_devinfo *dinfo; + struct lbc_devinfo *di; + struct resource_list *rl; + int rv; - if (device_get_parent(child) != dev) - return (EINVAL); + di = device_get_ivars(child); + rl = &di->di_res; - dinfo = device_get_ivars(child); + rv = 0; + rv += bus_print_child_header(dev, child); + rv += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx"); + rv += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); + rv += bus_print_child_footer(dev, child); - switch (index) { - case LBC_IVAR_DEVTYPE: - *result = dinfo->lbc_devtype; - return (0); - default: - break; - } - return (EINVAL); + return (rv); } static int lbc_release_resource(device_t dev, device_t child, int type, int rid, struct resource *res) { + int err; + + if (rman_get_flags(res) & RF_ACTIVE) { + err = bus_deactivate_resource(child, type, rid, res); + if (err) + return (err); + } return (rman_release_resource(res)); } -static int -lbc_get_resource(device_t dev, device_t child, int type, int rid, - u_long *startp, u_long *countp) +static const struct ofw_bus_devinfo * +lbc_get_devinfo(device_t bus, device_t child) { - struct lbc_softc *sc; - struct lbc_devinfo *dinfo; - const struct lbc_resource *lbcres; - - if (type != SYS_RES_MEMORY) - return (ENOENT); - - /* Currently all LBC devices have a single RID per type. */ - if (rid != 0) - return (ENOENT); - - sc = device_get_softc(dev); - dinfo = device_get_ivars(child); - - if ((dinfo->lbc_unit < 0) || (dinfo->lbc_unit > (LBC_DEV_MAX - 1))) - return (EINVAL); + struct lbc_devinfo *di; - lbcres = mpc85xx_lbc_resources; - - switch (dinfo->lbc_devtype) { - case LBC_DEVTYPE_CFI: - case LBC_DEVTYPE_RTC: - for (; lbcres->lbr_devtype; lbcres++) { - if (dinfo->lbc_unit == lbcres->lbr_unit) { - *startp = sc->sc_kva[lbcres->lbr_unit]; - *countp = lbcres->lbr_size; - return (0); - } - } - default: - return (EDOOFUS); - } - return (0); + di = device_get_ivars(child); + return (&di->di_ofw); } diff --git a/sys/powerpc/mpc85xx/lbc.h b/sys/powerpc/mpc85xx/lbc.h index c5d19e2aa7ac..ee58607661d5 100644 --- a/sys/powerpc/mpc85xx/lbc.h +++ b/sys/powerpc/mpc85xx/lbc.h @@ -29,15 +29,9 @@ #ifndef _MACHINE_LBC_H_ #define _MACHINE_LBC_H_ -#define LBC_IVAR_DEVTYPE 1 - /* Maximum number of devices on Local Bus */ #define LBC_DEV_MAX 8 -/* Device types. */ -#define LBC_DEVTYPE_CFI 1 -#define LBC_DEVTYPE_RTC 2 - /* Local access registers */ #define LBC85XX_BR(n) (8 * n) #define LBC85XX_OR(n) (4 + (8 * n)) @@ -61,18 +55,42 @@ #define LBCRES_ATOM_RAWA 1 #define LBCRES_ATOM_WARA 2 -struct lbc_resource { - int lbr_devtype; /* LBC device type */ - int lbr_unit; /* Resource table entry number */ - vm_paddr_t lbr_base_addr; /* Device mem region base address */ - size_t lbr_size; /* Device mem region size */ - int lbr_port_size; /* Data bus width */ - uint8_t lbr_msel; /* LBC machine select */ - uint8_t lbr_decc; /* Data error checking mode */ - uint8_t lbr_atom; /* Atomic operation mode */ - uint8_t lbr_wp; /* Write protect */ +struct lbc_bank { + u_long pa; /* physical addr of the bank */ + u_long size; /* bank size */ + vm_offset_t va; /* VA of the bank */ + + /* + * XXX the following bank attributes do not have properties specified + * in the LBC DTS bindings yet (11.2009), so they are mainly a + * placeholder for future extensions. + */ + int width; /* data bus width */ + uint8_t msel; /* machine select */ + uint8_t atom; /* atomic op mode */ + uint8_t wp; /* write protect */ + uint8_t decc; /* data error checking */ }; -extern const struct lbc_resource mpc85xx_lbc_resources[]; +struct lbc_softc { + device_t sc_dev; + struct resource *sc_res; + bus_space_handle_t sc_bsh; + bus_space_tag_t sc_bst; + int sc_rid; + + struct rman sc_rman; + + int sc_addr_cells; + int sc_size_cells; + + struct lbc_bank sc_banks[LBC_DEV_MAX]; +}; + +struct lbc_devinfo { + struct ofw_bus_devinfo di_ofw; + struct resource_list di_res; + int di_bank; +}; #endif /* _MACHINE_LBC_H_ */ diff --git a/sys/powerpc/mpc85xx/mpc85xx.c b/sys/powerpc/mpc85xx/mpc85xx.c index b6de50d6b5e9..75304496d2f0 100644 --- a/sys/powerpc/mpc85xx/mpc85xx.c +++ b/sys/powerpc/mpc85xx/mpc85xx.c @@ -29,6 +29,9 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/rman.h> #include <vm/vm.h> #include <vm/vm_param.h> @@ -37,7 +40,6 @@ __FBSDID("$FreeBSD$"); #include <machine/cpufunc.h> #include <machine/spr.h> -#include <powerpc/mpc85xx/ocpbus.h> #include <powerpc/mpc85xx/mpc85xx.h> /* @@ -129,6 +131,39 @@ law_disable(int trgt, u_long addr, u_long size) return (ENOENT); } +int +law_pci_target(struct resource *res, int *trgt_mem, int *trgt_io) +{ + u_long start; + uint32_t ver; + int trgt, rv; + + ver = SVR_VER(mfspr(SPR_SVR)); + + start = rman_get_start(res) & 0xf000; + + rv = 0; + trgt = -1; + switch (start) { + case 0x8000: + trgt = 0; + break; + case 0x9000: + trgt = 1; + break; + case 0xa000: + if (ver == SVR_MPC8572E || ver == SVR_MPC8572) + trgt = 2; + else + rv = EINVAL; + break; + default: + rv = ENXIO; + } + *trgt_mem = *trgt_io = trgt; + return (rv); +} + void cpu_reset(void) { diff --git a/sys/powerpc/mpc85xx/mpc85xx.h b/sys/powerpc/mpc85xx/mpc85xx.h index e558489e288f..7621f2c641b1 100644 --- a/sys/powerpc/mpc85xx/mpc85xx.h +++ b/sys/powerpc/mpc85xx/mpc85xx.h @@ -1,5 +1,6 @@ /*- * Copyright (C) 2008 Semihalf, Rafal Jaworowski + * Copyright 2006 by Juniper Networks. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,10 +30,61 @@ #ifndef _MPC85XX_H_ #define _MPC85XX_H_ +/* + * Configuration control and status registers + */ +#define OCP85XX_CCSRBAR (CCSRBAR_VA + 0x0) +#define OCP85XX_BPTR (CCSRBAR_VA + 0x20) + +/* + * E500 Coherency Module registers + */ +#define OCP85XX_EEBPCR (CCSRBAR_VA + 0x1010) + +/* + * Local access registers + */ +#define OCP85XX_LAWBAR(n) (CCSRBAR_VA + 0xc08 + 0x20 * (n)) +#define OCP85XX_LAWSR(n) (CCSRBAR_VA + 0xc10 + 0x20 * (n)) + +#define OCP85XX_TGTIF_LBC 4 +#define OCP85XX_TGTIF_RAM_INTL 11 +#define OCP85XX_TGTIF_RIO 12 +#define OCP85XX_TGTIF_RAM1 15 +#define OCP85XX_TGTIF_RAM2 22 + +/* + * L2 cache registers + */ +#define OCP85XX_L2CTL (CCSRBAR_VA + 0x20000) + +/* + * Power-On Reset configuration + */ +#define OCP85XX_PORDEVSR (CCSRBAR_VA + 0xe000c) +#define OCP85XX_PORDEVSR_IO_SEL 0x00780000 +#define OCP85XX_PORDEVSR_IO_SEL_SHIFT 19 + +#define OCP85XX_PORDEVSR2 (CCSRBAR_VA + 0xe0014) + +#define OCP85XX_DEVDISR (CCSRBAR_VA + 0xe0070) +#define OCP85XX_DEVDISR_PCIE0 0x20000000 +#define OCP85XX_DEVDISR_PCIE1 0x04000000 +#define OCP85XX_DEVDISR_PCIE2 0x02000000 + +/* + * Status Registers. + */ +#define OCP85XX_RSTCR (CCSRBAR_VA + 0xe00b0) + +/* + * Prototypes. + */ uint32_t ccsr_read4(uintptr_t addr); void ccsr_write4(uintptr_t addr, uint32_t val); int law_enable(int trgt, u_long addr, u_long size); int law_disable(int trgt, u_long addr, u_long size); int law_getmax(void); +int law_pci_target(struct resource *, int *, int *); #endif /* _MPC85XX_H_ */ diff --git a/sys/powerpc/mpc85xx/nexus.c b/sys/powerpc/mpc85xx/nexus.c index fa072472e2fe..6b07b10a7e33 100644 --- a/sys/powerpc/mpc85xx/nexus.c +++ b/sys/powerpc/mpc85xx/nexus.c @@ -112,13 +112,10 @@ static int nexus_probe (device_t dev) { - /* - * Add OCP (on-chip peripheral) bus - */ - device_add_child(dev, "ocpbus", 0); + device_add_child(dev, "fdtbus", 0); + device_quiet(dev); - device_set_desc(dev, "MPC85xx Nexus device"); - return (0); + return (BUS_PROBE_DEFAULT); } static int diff --git a/sys/powerpc/mpc85xx/ocpbus.c b/sys/powerpc/mpc85xx/ocpbus.c deleted file mode 100644 index 483c620e4b56..000000000000 --- a/sys/powerpc/mpc85xx/ocpbus.c +++ /dev/null @@ -1,622 +0,0 @@ -/*- - * Copyright 2006 by Juniper Networks. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/ktr.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/rman.h> -#include <sys/malloc.h> - -#include <machine/spr.h> -#include <machine/ocpbus.h> -#include <machine/intr_machdep.h> -#include <machine/md_var.h> -#include <machine/vmparam.h> -#include <machine/bootinfo.h> - -#include <powerpc/mpc85xx/ocpbus.h> -#include <powerpc/mpc85xx/mpc85xx.h> - -#include "pic_if.h" - -extern struct bus_space bs_be_tag; - -struct ocpbus_softc { - struct rman sc_mem; - struct rman sc_irq; -}; - -struct ocp_devinfo { - int ocp_devtype; - int ocp_unit; -}; - -static int ocpbus_probe(device_t); -static int ocpbus_attach(device_t); -static int ocpbus_shutdown(device_t); -static int ocpbus_get_resource(device_t, device_t, int, int, u_long *, - u_long *); -static struct resource *ocpbus_alloc_resource(device_t, device_t, int, int *, - u_long, u_long, u_long, u_int); -static int ocpbus_print_child(device_t, device_t); -static int ocpbus_release_resource(device_t, device_t, int, int, - struct resource *); -static int ocpbus_read_ivar(device_t, device_t, int, uintptr_t *); -static int ocpbus_setup_intr(device_t, device_t, struct resource *, int, - driver_filter_t *, driver_intr_t *, void *, void **); -static int ocpbus_teardown_intr(device_t, device_t, struct resource *, void *); -static int ocpbus_config_intr(device_t, int, enum intr_trigger, - enum intr_polarity); - -/* - * Bus interface definition - */ -static device_method_t ocpbus_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ocpbus_probe), - DEVMETHOD(device_attach, ocpbus_attach), - DEVMETHOD(device_shutdown, ocpbus_shutdown), - - /* Bus interface */ - DEVMETHOD(bus_print_child, ocpbus_print_child), - DEVMETHOD(bus_read_ivar, ocpbus_read_ivar), - DEVMETHOD(bus_setup_intr, ocpbus_setup_intr), - DEVMETHOD(bus_teardown_intr, ocpbus_teardown_intr), - DEVMETHOD(bus_config_intr, ocpbus_config_intr), - - DEVMETHOD(bus_get_resource, ocpbus_get_resource), - DEVMETHOD(bus_alloc_resource, ocpbus_alloc_resource), - DEVMETHOD(bus_release_resource, ocpbus_release_resource), - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), - DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), - - { 0, 0 } -}; - -static driver_t ocpbus_driver = { - "ocpbus", - ocpbus_methods, - sizeof(struct ocpbus_softc) -}; - -devclass_t ocpbus_devclass; - -DRIVER_MODULE(ocpbus, nexus, ocpbus_driver, ocpbus_devclass, 0, 0); - -static device_t -ocpbus_mk_child(device_t dev, int type, int unit) -{ - struct ocp_devinfo *dinfo; - device_t child; - - child = device_add_child(dev, NULL, -1); - if (child == NULL) { - device_printf(dev, "could not add child device\n"); - return (NULL); - } - dinfo = malloc(sizeof(struct ocp_devinfo), M_DEVBUF, M_WAITOK|M_ZERO); - dinfo->ocp_devtype = type; - dinfo->ocp_unit = unit; - device_set_ivars(child, dinfo); - return (child); -} - -static int -ocpbus_write_law(int trgt, int type, u_long *startp, u_long *countp) -{ - u_long addr, size; - - switch (type) { - case SYS_RES_MEMORY: - switch (trgt) { - case OCP85XX_TGTIF_PCI0: - addr = 0x80000000; - size = 0x10000000; - break; - case OCP85XX_TGTIF_PCI1: - addr = 0x90000000; - size = 0x10000000; - break; - case OCP85XX_TGTIF_PCI2: - addr = 0xA0000000; - size = 0x10000000; - break; - case OCP85XX_TGTIF_PCI3: - addr = 0xB0000000; - size = 0x10000000; - break; - default: - return (EINVAL); - } - break; - case SYS_RES_IOPORT: - switch (trgt) { - case OCP85XX_TGTIF_PCI0: - addr = 0xfee00000; - size = 0x00010000; - break; - case OCP85XX_TGTIF_PCI1: - addr = 0xfee10000; - size = 0x00010000; - break; - case OCP85XX_TGTIF_PCI2: - addr = 0xfee20000; - size = 0x00010000; - break; - case OCP85XX_TGTIF_PCI3: - addr = 0xfee30000; - size = 0x00010000; - break; - default: - return (EINVAL); - } - break; - default: - return (EINVAL); - } - - *startp = addr; - *countp = size; - - return (law_enable(trgt, *startp, *countp)); -} - -static int -ocpbus_probe(device_t dev) -{ - - device_set_desc(dev, "Freescale on-chip peripherals bus"); - return (BUS_PROBE_DEFAULT); -} - -static int -ocpbus_attach(device_t dev) -{ - struct ocpbus_softc *sc; - int error, i, tgt, law_max; - uint32_t sr; - u_long start, end; - - sc = device_get_softc(dev); - - ocpbus_mk_child(dev, OCPBUS_DEVTYPE_I2C, 0); - ocpbus_mk_child(dev, OCPBUS_DEVTYPE_I2C, 1); - ocpbus_mk_child(dev, OCPBUS_DEVTYPE_UART, 0); - ocpbus_mk_child(dev, OCPBUS_DEVTYPE_UART, 1); - ocpbus_mk_child(dev, OCPBUS_DEVTYPE_LBC, 0); - ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PCIB, 0); - ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PCIB, 1); - ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PCIB, 2); - ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PCIB, 3); - ocpbus_mk_child(dev, OCPBUS_DEVTYPE_TSEC, 0); - ocpbus_mk_child(dev, OCPBUS_DEVTYPE_TSEC, 1); - ocpbus_mk_child(dev, OCPBUS_DEVTYPE_TSEC, 2); - ocpbus_mk_child(dev, OCPBUS_DEVTYPE_TSEC, 3); - ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PIC, 0); - ocpbus_mk_child(dev, OCPBUS_DEVTYPE_QUICC, 0); - ocpbus_mk_child(dev, OCPBUS_DEVTYPE_SEC, 0); - - /* Set up IRQ rman */ - start = 0; - end = INTR_VECTORS - 1; - sc->sc_irq.rm_start = start; - sc->sc_irq.rm_end = end; - sc->sc_irq.rm_type = RMAN_ARRAY; - sc->sc_irq.rm_descr = "Interrupt request lines"; - if (rman_init(&sc->sc_irq) || - rman_manage_region(&sc->sc_irq, start, end)) - panic("ocpbus_attach IRQ rman"); - - /* Set up I/O mem rman */ - sc->sc_mem.rm_type = RMAN_ARRAY; - sc->sc_mem.rm_descr = "OCPBus Device Memory"; - error = rman_init(&sc->sc_mem); - if (error) { - device_printf(dev, "rman_init() failed. error = %d\n", error); - return (error); - } - - error = rman_manage_region(&sc->sc_mem, CCSRBAR_VA, - CCSRBAR_VA + CCSRBAR_SIZE - 1); - if (error) { - device_printf(dev, "rman_manage_region() failed. error = %d\n", - error); - return (error); - } - - /* - * Clear local access windows. Skip DRAM entries, so we don't shoot - * ourselves in the foot. - */ - law_max = law_getmax(); - for (i = 0; i < law_max; i++) { - sr = ccsr_read4(OCP85XX_LAWSR(i)); - if ((sr & 0x80000000) == 0) - continue; - tgt = (sr & 0x01f00000) >> 20; - if (tgt == OCP85XX_TGTIF_RAM1 || tgt == OCP85XX_TGTIF_RAM2 || - tgt == OCP85XX_TGTIF_RAM_INTL) - continue; - - ccsr_write4(OCP85XX_LAWSR(i), sr & 0x7fffffff); - } - - if (bootverbose) - device_printf(dev, "PORDEVSR=%08x, PORDEVSR2=%08x\n", - ccsr_read4(OCP85XX_PORDEVSR), - ccsr_read4(OCP85XX_PORDEVSR2)); - - /* - * Internal interrupt are always active-high. Since the sense cannot - * be specified, we program as edge-triggered to make sure we write - * a 0 value to the reserved bit in the OpenPIC compliant PIC. This - * is not to say anything about the sense of any of the internal - * interrupt sources. - */ - for (i = PIC_IRQ_INT(0); i < PIC_IRQ_INT(32); i++) - powerpc_config_intr(i, INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH); - - return (bus_generic_attach(dev)); -} - -static int -ocpbus_shutdown(device_t dev) -{ - - return(0); -} - -struct ocp_resource { - int sr_devtype; - int sr_unit; - int sr_resource; - int sr_rid; - int sr_offset; - int sr_size; -}; - -const struct ocp_resource mpc8555_resources[] = { - {OCPBUS_DEVTYPE_PIC, 0, SYS_RES_MEMORY, 0, OCP85XX_OPENPIC_OFF, - OCP85XX_OPENPIC_SIZE}, - - {OCPBUS_DEVTYPE_QUICC, 0, SYS_RES_MEMORY, 0, OCP85XX_QUICC_OFF, - OCP85XX_QUICC_SIZE}, - {OCPBUS_DEVTYPE_QUICC, 0, SYS_RES_IRQ, 0, 30, 1}, - - {OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_MEMORY, 0, OCP85XX_TSEC0_OFF, - OCP85XX_TSEC_SIZE}, - {OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_IRQ, 0, 13, 1}, - {OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_IRQ, 1, 14, 1}, - {OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_IRQ, 2, 18, 1}, - {OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_MEMORY, 0, OCP85XX_TSEC1_OFF, - OCP85XX_TSEC_SIZE}, - {OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_IRQ, 0, 19, 1}, - {OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_IRQ, 1, 20, 1}, - {OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_IRQ, 2, 24, 1}, - {OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_MEMORY, 0, OCP85XX_TSEC2_OFF, - OCP85XX_TSEC_SIZE}, - {OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_IRQ, 0, 15, 1}, - {OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_IRQ, 1, 16, 1}, - {OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_IRQ, 2, 17, 1}, - {OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_MEMORY, 0, OCP85XX_TSEC3_OFF, - OCP85XX_TSEC_SIZE}, - {OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_IRQ, 0, 21, 1}, - {OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_IRQ, 1, 22, 1}, - {OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_IRQ, 2, 23, 1}, - - {OCPBUS_DEVTYPE_UART, 0, SYS_RES_MEMORY, 0, OCP85XX_UART0_OFF, - OCP85XX_UART_SIZE}, - {OCPBUS_DEVTYPE_UART, 0, SYS_RES_IRQ, 0, 26, 1}, - {OCPBUS_DEVTYPE_UART, 1, SYS_RES_MEMORY, 0, OCP85XX_UART1_OFF, - OCP85XX_UART_SIZE}, - {OCPBUS_DEVTYPE_UART, 1, SYS_RES_IRQ, 0, 26, 1}, - - {OCPBUS_DEVTYPE_PCIB, 0, SYS_RES_MEMORY, 0, OCP85XX_PCI0_OFF, - OCP85XX_PCI_SIZE}, - {OCPBUS_DEVTYPE_PCIB, 0, SYS_RES_MEMORY, 1, 0, OCP85XX_TGTIF_PCI0}, - {OCPBUS_DEVTYPE_PCIB, 0, SYS_RES_IOPORT, 1, 0, OCP85XX_TGTIF_PCI0}, - {OCPBUS_DEVTYPE_PCIB, 1, SYS_RES_MEMORY, 0, OCP85XX_PCI1_OFF, - OCP85XX_PCI_SIZE}, - {OCPBUS_DEVTYPE_PCIB, 1, SYS_RES_MEMORY, 1, 0, OCP85XX_TGTIF_PCI1}, - {OCPBUS_DEVTYPE_PCIB, 1, SYS_RES_IOPORT, 1, 0, OCP85XX_TGTIF_PCI1}, - {OCPBUS_DEVTYPE_PCIB, 2, SYS_RES_MEMORY, 0, OCP85XX_PCI2_OFF, - OCP85XX_PCI_SIZE}, - {OCPBUS_DEVTYPE_PCIB, 2, SYS_RES_MEMORY, 1, 0, OCP85XX_TGTIF_PCI2}, - {OCPBUS_DEVTYPE_PCIB, 2, SYS_RES_IOPORT, 1, 0, OCP85XX_TGTIF_PCI2}, - {OCPBUS_DEVTYPE_PCIB, 3, SYS_RES_MEMORY, 0, OCP85XX_PCI3_OFF, - OCP85XX_PCI_SIZE}, - {OCPBUS_DEVTYPE_PCIB, 3, SYS_RES_MEMORY, 1, 0, OCP85XX_TGTIF_PCI3}, - {OCPBUS_DEVTYPE_PCIB, 3, SYS_RES_IOPORT, 1, 0, OCP85XX_TGTIF_PCI3}, - - {OCPBUS_DEVTYPE_LBC, 0, SYS_RES_MEMORY, 0, OCP85XX_LBC_OFF, - OCP85XX_LBC_SIZE}, - - {OCPBUS_DEVTYPE_I2C, 0, SYS_RES_MEMORY, 0, OCP85XX_I2C0_OFF, - OCP85XX_I2C_SIZE}, - {OCPBUS_DEVTYPE_I2C, 0, SYS_RES_IRQ, 0, 27, 1}, - {OCPBUS_DEVTYPE_I2C, 1, SYS_RES_MEMORY, 0, OCP85XX_I2C1_OFF, - OCP85XX_I2C_SIZE}, - {OCPBUS_DEVTYPE_I2C, 1, SYS_RES_IRQ, 0, 27, 1}, - - {OCPBUS_DEVTYPE_SEC, 0, SYS_RES_MEMORY, 0, OCP85XX_SEC_OFF, - OCP85XX_SEC_SIZE}, - {OCPBUS_DEVTYPE_SEC, 0, SYS_RES_IRQ, 0, 29, 1}, - {OCPBUS_DEVTYPE_SEC, 0, SYS_RES_IRQ, 1, 42, 1}, - - {0} -}; - -static int -ocpbus_get_resource(device_t dev, device_t child, int type, int rid, - u_long *startp, u_long *countp) -{ - const struct ocp_resource *res; - struct ocp_devinfo *dinfo; - u_long start = 0, count = 0; - int error; - - dinfo = device_get_ivars(child); - - /* - * Lookup the correct values. - */ - res = mpc8555_resources; - for (; res->sr_devtype; res++) { - if (res->sr_devtype != dinfo->ocp_devtype) - continue; - if (res->sr_unit != dinfo->ocp_unit) - continue; - if (res->sr_rid != rid) - continue; - if (res->sr_resource != type) - continue; - - if (res->sr_offset != 0) { - error = 0; - switch (type) { - case SYS_RES_MEMORY: - start = res->sr_offset + CCSRBAR_VA; - break; - case SYS_RES_IRQ: - start = PIC_IRQ_INT(res->sr_offset); - break; - default: - error = EINVAL; - break; - } - count = res->sr_size; - } else - error = ocpbus_write_law(res->sr_size, type, &start, - &count); - - if (!error) { - if (startp != NULL) - *startp = start; - if (countp != NULL) - *countp = count; - } - return (error); - } - - return (ENOENT); -} - -static struct resource * -ocpbus_alloc_resource(device_t dev, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) -{ - struct ocpbus_softc *sc; - struct resource *rv; - int error; - - sc = device_get_softc(dev); - - switch (type) { - case SYS_RES_IRQ: - if (start == 0ul && end == ~0ul) { - error = ocpbus_get_resource(dev, child, type, *rid, - &start, &count); - if (error) - return (NULL); - } - - rv = rman_reserve_resource(&sc->sc_irq, start, - start + count - 1, count, flags, child); - if (rv == NULL) - return (NULL); - break; - - case SYS_RES_MEMORY: - if (start != 0ul || end != ~0ul) - return (NULL); - - error = ocpbus_get_resource(dev, child, type, *rid, &start, - &count); - if (error) - return (NULL); - - rv = rman_reserve_resource(&sc->sc_mem, start, - start + count - 1, count, flags, child); - if (rv == NULL) - return (NULL); - - rman_set_bustag(rv, &bs_be_tag); - rman_set_bushandle(rv, rman_get_start(rv)); - break; - - default: - return (NULL); - } - - rman_set_rid(rv, *rid); - return (rv); -} - -static int -ocpbus_print_child(device_t dev, device_t child) -{ - u_long size, start; - int error, retval, rid; - - retval = bus_print_child_header(dev, child); - - rid = 0; - while (1) { - error = ocpbus_get_resource(dev, child, SYS_RES_MEMORY, rid, - &start, &size); - if (error) - break; - retval += (rid == 0) ? printf(" iomem ") : printf(","); - retval += printf("%#lx", start); - if (size > 1) - retval += printf("-%#lx", start + size - 1); - rid++; - } - - /* - * The SYS_RES_IOPORT resource of the PCIB has rid 1 because the - * the SYS_RES_MEMORY resource related to the decoding window also - * has rid 1. This is friendlier for the PCIB child... - */ - rid = 1; - while (1) { - error = ocpbus_get_resource(dev, child, SYS_RES_IOPORT, rid, - &start, &size); - if (error) - break; - retval += (rid == 1) ? printf(" ioport ") : printf(","); - retval += printf("%#lx", start); - if (size > 1) - retval += printf("-%#lx", start + size - 1); - rid++; - } - - rid = 0; - while (1) { - error = ocpbus_get_resource(dev, child, SYS_RES_IRQ, rid, - &start, &size); - if (error) - break; - retval += (rid == 0) ? printf(" irq ") : printf(","); - retval += printf("%ld", start); - rid++; - } - - retval += bus_print_child_footer(dev, child); - return (retval); -} - -static int -ocpbus_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) -{ - struct ocp_devinfo *dinfo; - struct bi_eth_addr *eth; - int unit; - - if (device_get_parent(child) != dev) - return (EINVAL); - - dinfo = device_get_ivars(child); - - switch (index) { - case OCPBUS_IVAR_CLOCK: - *result = bootinfo->bi_bus_clk; - return (0); - case OCPBUS_IVAR_DEVTYPE: - *result = dinfo->ocp_devtype; - return (0); - case OCPBUS_IVAR_HWUNIT: - *result = dinfo->ocp_unit; - return (0); - case OCPBUS_IVAR_MACADDR: - unit = device_get_unit(child); - if (unit > bootinfo->bi_eth_addr_no - 1) - return (EINVAL); - eth = bootinfo_eth() + unit; - *result = (uintptr_t)eth; - return (0); - } - - return (EINVAL); -} - -static int -ocpbus_release_resource(device_t dev, device_t child, int type, int rid, - struct resource *res) -{ - - return (rman_release_resource(res)); -} - -static int -ocpbus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, - driver_filter_t *filter, driver_intr_t *ihand, void *arg, void **cookiep) -{ - int error; - - if (res == NULL) - panic("ocpbus_setup_intr: NULL irq resource!"); - - *cookiep = 0; - if ((rman_get_flags(res) & RF_SHAREABLE) == 0) - flags |= INTR_EXCL; - - /* - * We depend here on rman_activate_resource() being idempotent. - */ - error = rman_activate_resource(res); - if (error) - return (error); - - error = powerpc_setup_intr(device_get_nameunit(child), - rman_get_start(res), filter, ihand, arg, flags, cookiep); - - return (error); -} - -static int -ocpbus_teardown_intr(device_t dev, device_t child, struct resource *res, - void *cookie) -{ - - return (powerpc_teardown_intr(cookie)); -} - -static int -ocpbus_config_intr(device_t dev, int irq, enum intr_trigger trig, - enum intr_polarity pol) -{ - - return (powerpc_config_intr(irq, trig, pol)); -} diff --git a/sys/powerpc/mpc85xx/ocpbus.h b/sys/powerpc/mpc85xx/ocpbus.h deleted file mode 100644 index 69c9569d7a4f..000000000000 --- a/sys/powerpc/mpc85xx/ocpbus.h +++ /dev/null @@ -1,112 +0,0 @@ -/*- - * Copyright 2006 by Juniper Networks. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _MACHINE_OCP85XX_H_ -#define _MACHINE_OCP85XX_H_ - -/* - * Configuration control and status registers - */ -#define OCP85XX_CCSRBAR (CCSRBAR_VA + 0x0) -#define OCP85XX_BPTR (CCSRBAR_VA + 0x20) - -/* - * E500 Coherency Module registers - */ -#define OCP85XX_EEBPCR (CCSRBAR_VA + 0x1010) - -/* - * Local access registers - */ -#define OCP85XX_LAWBAR(n) (CCSRBAR_VA + 0xc08 + 0x20 * (n)) -#define OCP85XX_LAWSR(n) (CCSRBAR_VA + 0xc10 + 0x20 * (n)) - -#define OCP85XX_TGTIF_PCI0 0 -#define OCP85XX_TGTIF_PCI1 1 -#define OCP85XX_TGTIF_PCI2 2 -#define OCP85XX_TGTIF_PCI3 3 -#define OCP85XX_TGTIF_LBC 4 -#define OCP85XX_TGTIF_RAM_INTL 11 -#define OCP85XX_TGTIF_RIO 12 -#define OCP85XX_TGTIF_RAM1 15 -#define OCP85XX_TGTIF_RAM2 22 - -/* - * L2 cache registers - */ -#define OCP85XX_L2CTL (CCSRBAR_VA + 0x20000) - -/* - * Power-On Reset configuration - */ -#define OCP85XX_PORDEVSR (CCSRBAR_VA + 0xe000c) -#define OCP85XX_PORDEVSR2 (CCSRBAR_VA + 0xe0014) - -/* - * Status Registers. - */ -#define OCP85XX_RSTCR (CCSRBAR_VA + 0xe00b0) - -/* - * OCP Bus Definitions - */ -#define OCP85XX_I2C0_OFF 0x03000 -#define OCP85XX_I2C1_OFF 0x03100 -#define OCP85XX_I2C_SIZE 0x16 -#define OCP85XX_UART0_OFF 0x04500 -#define OCP85XX_UART1_OFF 0x04600 -#define OCP85XX_UART_SIZE 0x10 -#define OCP85XX_LBC_OFF 0x05000 -#define OCP85XX_LBC_SIZE 0x1000 -#define OCP85XX_PCI0_OFF 0x08000 -#define OCP85XX_PCI1_OFF 0x09000 -#define OCP85XX_PCI2_OFF 0x0A000 -#define OCP85XX_PCI3_OFF 0x0B000 -#define OCP85XX_PCI_SIZE 0x1000 -#define OCP85XX_TSEC0_OFF 0x24000 -#define OCP85XX_TSEC1_OFF 0x25000 -#define OCP85XX_TSEC2_OFF 0x26000 -#define OCP85XX_TSEC3_OFF 0x27000 -#define OCP85XX_TSEC_SIZE 0x1000 -#define OCP85XX_OPENPIC_OFF 0x40000 -#define OCP85XX_OPENPIC_SIZE 0x200B4 -#define OCP85XX_QUICC_OFF 0x80000 -#define OCP85XX_QUICC_SIZE 0x20000 -#define OCP85XX_SEC_OFF 0x30000 -#define OCP85XX_SEC_SIZE 0x10000 - -/* - * PIC definitions - */ - -#define ISA_IRQ(n) (INTR_VEC(ATPIC_ID, n)) -#define PIC_IRQ_EXT(n) (INTR_VEC(OPIC_ID, (n))) -#define PIC_IRQ_INT(n) (INTR_VEC(OPIC_ID, (16 + (n)))) - -#endif /* _MACHINE_OCP85XX_H */ diff --git a/sys/powerpc/mpc85xx/openpic_fdt.c b/sys/powerpc/mpc85xx/openpic_fdt.c new file mode 100644 index 000000000000..da70542bbaf1 --- /dev/null +++ b/sys/powerpc/mpc85xx/openpic_fdt.c @@ -0,0 +1,93 @@ +/*- + * Copyright (c) 2009-2010 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Semihalf under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus.h> + +#include <machine/bus.h> +#include <machine/intr_machdep.h> +#include <machine/openpicvar.h> + +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include "pic_if.h" + +static int openpic_fdt_probe(device_t); +static uint32_t openpic_fdt_id(device_t); + +static device_method_t openpic_fdt_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, openpic_fdt_probe), + DEVMETHOD(device_attach, openpic_attach), + + /* PIC interface */ + DEVMETHOD(pic_bind, openpic_bind), + DEVMETHOD(pic_config, openpic_config), + DEVMETHOD(pic_dispatch, openpic_dispatch), + DEVMETHOD(pic_enable, openpic_enable), + DEVMETHOD(pic_eoi, openpic_eoi), + DEVMETHOD(pic_ipi, openpic_ipi), + DEVMETHOD(pic_mask, openpic_mask), + DEVMETHOD(pic_unmask, openpic_unmask), + DEVMETHOD(pic_id, openpic_fdt_id), + + { 0, 0 }, +}; + +static driver_t openpic_fdt_driver = { + "openpic", + openpic_fdt_methods, + sizeof(struct openpic_softc) +}; + +DRIVER_MODULE(openpic, simplebus, openpic_fdt_driver, openpic_devclass, 0, 0); + +static int +openpic_fdt_probe(device_t dev) +{ + + if (!ofw_bus_is_compatible(dev, "chrp,open-pic")) + return (ENXIO); + + device_set_desc(dev, OPENPIC_DEVSTR); + return (BUS_PROBE_DEFAULT); +} + +static uint32_t +openpic_fdt_id(device_t dev) +{ + + return (ofw_bus_get_node(dev)); +} diff --git a/sys/powerpc/mpc85xx/opic.c b/sys/powerpc/mpc85xx/opic.c deleted file mode 100644 index 3bd5db0c4f68..000000000000 --- a/sys/powerpc/mpc85xx/opic.c +++ /dev/null @@ -1,105 +0,0 @@ -/*- - * Copyright 2006 by Juniper Networks. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/rman.h> -#include <sys/bus.h> - -#include <machine/bus.h> -#include <machine/intr_machdep.h> -#include <machine/openpicvar.h> -#include <machine/ocpbus.h> - -#include "pic_if.h" - -/* - * OpenPIC attachment to ocpbus - */ -static int openpic_ocpbus_probe(device_t); -static uint32_t openpic_ocpbus_id(device_t); - -static device_method_t openpic_ocpbus_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, openpic_ocpbus_probe), - DEVMETHOD(device_attach, openpic_attach), - - /* PIC interface */ - DEVMETHOD(pic_bind, openpic_bind), - DEVMETHOD(pic_config, openpic_config), - DEVMETHOD(pic_dispatch, openpic_dispatch), - DEVMETHOD(pic_enable, openpic_enable), - DEVMETHOD(pic_eoi, openpic_eoi), - DEVMETHOD(pic_ipi, openpic_ipi), - DEVMETHOD(pic_mask, openpic_mask), - DEVMETHOD(pic_unmask, openpic_unmask), - DEVMETHOD(pic_id, openpic_ocpbus_id), - - { 0, 0 }, -}; - -static driver_t openpic_ocpbus_driver = { - "openpic", - openpic_ocpbus_methods, - sizeof(struct openpic_softc) -}; - -DRIVER_MODULE(openpic, ocpbus, openpic_ocpbus_driver, openpic_devclass, 0, 0); - -static int -openpic_ocpbus_probe (device_t dev) -{ - device_t parent; - uintptr_t devtype; - int error; - - parent = device_get_parent(dev); - - error = BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_DEVTYPE, &devtype); - if (error) - return (error); - if (devtype != OCPBUS_DEVTYPE_PIC) - return (ENXIO); - - device_set_desc(dev, OPENPIC_DEVSTR); - return (BUS_PROBE_DEFAULT); -} - -static uint32_t -openpic_ocpbus_id (device_t dev) -{ - return (OPIC_ID); -} - - diff --git a/sys/powerpc/mpc85xx/pci_fdt.c b/sys/powerpc/mpc85xx/pci_fdt.c new file mode 100644 index 000000000000..9d67aae81851 --- /dev/null +++ b/sys/powerpc/mpc85xx/pci_fdt.c @@ -0,0 +1,1067 @@ +/*- + * Copyright 2006-2007 by Juniper Networks. + * Copyright 2008 Semihalf. + * Copyright 2010 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by Semihalf + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * From: FreeBSD: src/sys/powerpc/mpc85xx/pci_ocp.c,v 1.9 2010/03/23 23:46:28 marcel + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/ktr.h> +#include <sys/sockio.h> +#include <sys/mbuf.h> +#include <sys/malloc.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/socket.h> +#include <sys/queue.h> +#include <sys/bus.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/rman.h> +#include <sys/endian.h> + +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcireg.h> +#include <dev/pci/pcib_private.h> + +#include "ofw_bus_if.h" +#include "pcib_if.h" + +#include <machine/resource.h> +#include <machine/bus.h> +#include <machine/intr_machdep.h> + +#include <powerpc/mpc85xx/mpc85xx.h> + +#define REG_CFG_ADDR 0x0000 +#define CONFIG_ACCESS_ENABLE 0x80000000 + +#define REG_CFG_DATA 0x0004 +#define REG_INT_ACK 0x0008 + +#define REG_POTAR(n) (0x0c00 + 0x20 * (n)) +#define REG_POTEAR(n) (0x0c04 + 0x20 * (n)) +#define REG_POWBAR(n) (0x0c08 + 0x20 * (n)) +#define REG_POWAR(n) (0x0c10 + 0x20 * (n)) + +#define REG_PITAR(n) (0x0e00 - 0x20 * (n)) +#define REG_PIWBAR(n) (0x0e08 - 0x20 * (n)) +#define REG_PIWBEAR(n) (0x0e0c - 0x20 * (n)) +#define REG_PIWAR(n) (0x0e10 - 0x20 * (n)) + +#define REG_PEX_MES_DR 0x0020 +#define REG_PEX_MES_IER 0x0028 +#define REG_PEX_ERR_DR 0x0e00 +#define REG_PEX_ERR_EN 0x0e08 + +#define PCIR_LTSSM 0x404 +#define LTSSM_STAT_L0 0x16 + +#define DEVFN(b, s, f) ((b << 16) | (s << 8) | f) + +struct fsl_pcib_softc { + device_t sc_dev; + + struct rman sc_iomem; + bus_addr_t sc_iomem_va; /* Virtual mapping. */ + bus_addr_t sc_iomem_size; + bus_addr_t sc_iomem_alloc; /* Next allocation. */ + int sc_iomem_target; + struct rman sc_ioport; + bus_addr_t sc_ioport_va; /* Virtual mapping. */ + bus_addr_t sc_ioport_size; + bus_addr_t sc_ioport_alloc; /* Next allocation. */ + int sc_ioport_target; + + struct resource *sc_res; + bus_space_handle_t sc_bsh; + bus_space_tag_t sc_bst; + int sc_rid; + + int sc_busnr; + int sc_pcie; + uint8_t sc_pcie_capreg; /* PCI-E Capability Reg Set */ + + /* Devices that need special attention. */ + int sc_devfn_tundra; + int sc_devfn_via_ide; + + struct fdt_pci_intr sc_intr_info; +}; + +/* Local forward declerations. */ +static uint32_t fsl_pcib_cfgread(struct fsl_pcib_softc *, u_int, u_int, u_int, + u_int, int); +static void fsl_pcib_cfgwrite(struct fsl_pcib_softc *, u_int, u_int, u_int, + u_int, uint32_t, int); +static int fsl_pcib_decode_win(phandle_t, struct fsl_pcib_softc *); +static void fsl_pcib_err_init(device_t); +static void fsl_pcib_inbound(struct fsl_pcib_softc *, int, int, u_long, + u_long, u_long); +static int fsl_pcib_init(struct fsl_pcib_softc *, int, int, int); +static int fsl_pcib_intr_info(phandle_t, struct fsl_pcib_softc *); +static int fsl_pcib_set_range(struct fsl_pcib_softc *, int, int, u_long, + u_long); +static void fsl_pcib_outbound(struct fsl_pcib_softc *, int, int, u_long, + u_long, u_long); + +/* Forward declerations. */ +static int fsl_pcib_attach(device_t); +static int fsl_pcib_detach(device_t); +static int fsl_pcib_probe(device_t); + +static struct resource *fsl_pcib_alloc_resource(device_t, device_t, int, int *, + u_long, u_long, u_long, u_int); +static int fsl_pcib_read_ivar(device_t, device_t, int, uintptr_t *); +static int fsl_pcib_release_resource(device_t, device_t, int, int, + struct resource *); +static int fsl_pcib_write_ivar(device_t, device_t, int, uintptr_t); + +static int fsl_pcib_maxslots(device_t); +static uint32_t fsl_pcib_read_config(device_t, u_int, u_int, u_int, u_int, int); +static void fsl_pcib_write_config(device_t, u_int, u_int, u_int, u_int, + uint32_t, int); + +static int next_busnr = 0; + +/* Configuration r/w mutex. */ +struct mtx pcicfg_mtx; +static int mtx_initialized = 0; + +/* + * Bus interface definitions. + */ +static device_method_t fsl_pcib_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, fsl_pcib_probe), + DEVMETHOD(device_attach, fsl_pcib_attach), + DEVMETHOD(device_detach, fsl_pcib_detach), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_read_ivar, fsl_pcib_read_ivar), + DEVMETHOD(bus_write_ivar, fsl_pcib_write_ivar), + DEVMETHOD(bus_alloc_resource, fsl_pcib_alloc_resource), + DEVMETHOD(bus_release_resource, fsl_pcib_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + /* pcib interface */ + DEVMETHOD(pcib_maxslots, fsl_pcib_maxslots), + DEVMETHOD(pcib_read_config, fsl_pcib_read_config), + DEVMETHOD(pcib_write_config, fsl_pcib_write_config), + DEVMETHOD(pcib_route_interrupt, pcib_route_interrupt), + + /* OFW bus interface */ + DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), + DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), + DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), + DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), + DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), + + { 0, 0 } +}; + +static driver_t fsl_pcib_driver = { + "pcib", + fsl_pcib_methods, + sizeof(struct fsl_pcib_softc), +}; + +devclass_t pcib_devclass; + +DRIVER_MODULE(pcib, fdtbus, fsl_pcib_driver, pcib_devclass, 0, 0); + +static int +fsl_pcib_probe(device_t dev) +{ + phandle_t parnode; + + /* + * The PCI subnode does not have the 'compatible' property, so we need + * to check in the parent PCI node. However the parent is not + * represented by a separate ofw_bus child, and therefore + * ofw_bus_is_compatible() cannot be used, but direct fdt equivalent. + */ + parnode = OF_parent(ofw_bus_get_node(dev)); + if (parnode == 0) + return (ENXIO); + if (!(fdt_is_compatible(parnode, "fsl,mpc8548-pcie") || + fdt_is_compatible(parnode, "fsl,mpc8548-pcie"))) + return (ENXIO); + + device_set_desc(dev, "Freescale Integrated PCI/PCI-E Controller"); + + return (BUS_PROBE_DEFAULT); +} + +static int +fsl_pcib_attach(device_t dev) +{ + struct fsl_pcib_softc *sc; + phandle_t node; + uint32_t cfgreg; + int maxslot, subbus; + uint8_t ltssm, capptr; + + sc = device_get_softc(dev); + sc->sc_dev = dev; + + sc->sc_rid = 0; + sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid, + RF_ACTIVE); + if (sc->sc_res == NULL) { + device_printf(dev, "could not map I/O memory\n"); + return (ENXIO); + } + sc->sc_bst = rman_get_bustag(sc->sc_res); + sc->sc_bsh = rman_get_bushandle(sc->sc_res); + sc->sc_busnr = 0; + + if (!mtx_initialized) { + mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN); + mtx_initialized = 1; + } + + cfgreg = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_VENDOR, 2); + if (cfgreg != 0x1057 && cfgreg != 0x1957) + goto err; + + capptr = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_CAP_PTR, 1); + while (capptr != 0) { + cfgreg = fsl_pcib_cfgread(sc, 0, 0, 0, capptr, 2); + switch (cfgreg & 0xff) { + case PCIY_PCIX: + break; + case PCIY_EXPRESS: + sc->sc_pcie = 1; + sc->sc_pcie_capreg = capptr; + break; + } + capptr = (cfgreg >> 8) & 0xff; + } + + node = ofw_bus_get_node(dev); + /* + * Get PCI interrupt info. + */ + if (fsl_pcib_intr_info(node, sc) != 0) { + device_printf(dev, "could not retrieve interrupt info\n"); + goto err; + } + + /* + * Configure decode windows for PCI(E) access. + */ + if (fsl_pcib_decode_win(node, sc) != 0) + goto err; + + cfgreg = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_COMMAND, 2); + cfgreg |= PCIM_CMD_SERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN | + PCIM_CMD_PORTEN; + fsl_pcib_cfgwrite(sc, 0, 0, 0, PCIR_COMMAND, cfgreg, 2); + + sc->sc_devfn_tundra = -1; + sc->sc_devfn_via_ide = -1; + + maxslot = (sc->sc_pcie) ? 1 : 31; + + /* + * Scan bus using firmware configured, 0 based bus numbering, + * let fsl_pcib_init() shift bus number by next_busnr offset. + */ + sc->sc_busnr = 1; + subbus = fsl_pcib_init(sc, 0, next_busnr, maxslot); + + if (bootverbose) + printf("PCI: domain %d, busnr = %d, next_busnr = %d\n", + device_get_unit(dev), next_busnr + 1, + next_busnr + subbus + 1); + + /* Set final busnr */ + sc->sc_busnr = next_busnr + 1; + next_busnr += subbus + 1; + + if (sc->sc_pcie) { + ltssm = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_LTSSM, 1); + if (ltssm < LTSSM_STAT_L0) { + if (bootverbose) + printf("PCI %d: no PCIE link, skipping\n", + device_get_unit(dev)); + return (0); + } + } + + fsl_pcib_err_init(dev); + + device_add_child(dev, "pci", -1); + return (bus_generic_attach(dev)); + +err: + bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res); + return (ENXIO); +} + +static uint32_t +fsl_pcib_cfgread(struct fsl_pcib_softc *sc, u_int bus, u_int slot, u_int func, + u_int reg, int bytes) +{ + uint32_t addr, data; + + if (bus == sc->sc_busnr - 1) + bus = 0; + + addr = CONFIG_ACCESS_ENABLE; + addr |= (bus & 0xff) << 16; + addr |= (slot & 0x1f) << 11; + addr |= (func & 0x7) << 8; + addr |= reg & 0xfc; + if (sc->sc_pcie) + addr |= (reg & 0xf00) << 16; + + mtx_lock_spin(&pcicfg_mtx); + bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_CFG_ADDR, addr); + + switch (bytes) { + case 1: + data = bus_space_read_1(sc->sc_bst, sc->sc_bsh, + REG_CFG_DATA + (reg & 3)); + break; + case 2: + data = le16toh(bus_space_read_2(sc->sc_bst, sc->sc_bsh, + REG_CFG_DATA + (reg & 2))); + break; + case 4: + data = le32toh(bus_space_read_4(sc->sc_bst, sc->sc_bsh, + REG_CFG_DATA)); + break; + default: + data = ~0; + break; + } + mtx_unlock_spin(&pcicfg_mtx); + return (data); +} + +static void +fsl_pcib_cfgwrite(struct fsl_pcib_softc *sc, u_int bus, u_int slot, u_int func, + u_int reg, uint32_t data, int bytes) +{ + uint32_t addr; + + if (bus == sc->sc_busnr - 1) + bus = 0; + + addr = CONFIG_ACCESS_ENABLE; + addr |= (bus & 0xff) << 16; + addr |= (slot & 0x1f) << 11; + addr |= (func & 0x7) << 8; + addr |= reg & 0xfc; + if (sc->sc_pcie) + addr |= (reg & 0xf00) << 16; + + mtx_lock_spin(&pcicfg_mtx); + bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_CFG_ADDR, addr); + + switch (bytes) { + case 1: + bus_space_write_1(sc->sc_bst, sc->sc_bsh, + REG_CFG_DATA + (reg & 3), data); + break; + case 2: + bus_space_write_2(sc->sc_bst, sc->sc_bsh, + REG_CFG_DATA + (reg & 2), htole16(data)); + break; + case 4: + bus_space_write_4(sc->sc_bst, sc->sc_bsh, + REG_CFG_DATA, htole32(data)); + break; + } + mtx_unlock_spin(&pcicfg_mtx); +} + +#if 0 +static void +dump(struct fsl_pcib_softc *sc) +{ + unsigned int i; + +#define RD(o) bus_space_read_4(sc->sc_bst, sc->sc_bsh, o) + for (i = 0; i < 5; i++) { + printf("POTAR%u =0x%08x\n", i, RD(REG_POTAR(i))); + printf("POTEAR%u =0x%08x\n", i, RD(REG_POTEAR(i))); + printf("POWBAR%u =0x%08x\n", i, RD(REG_POWBAR(i))); + printf("POWAR%u =0x%08x\n", i, RD(REG_POWAR(i))); + } + printf("\n"); + for (i = 1; i < 4; i++) { + printf("PITAR%u =0x%08x\n", i, RD(REG_PITAR(i))); + printf("PIWBAR%u =0x%08x\n", i, RD(REG_PIWBAR(i))); + printf("PIWBEAR%u=0x%08x\n", i, RD(REG_PIWBEAR(i))); + printf("PIWAR%u =0x%08x\n", i, RD(REG_PIWAR(i))); + } + printf("\n"); +#undef RD + + for (i = 0; i < 0x48; i += 4) { + printf("cfg%02x=0x%08x\n", i, fsl_pcib_cfgread(sc, 0, 0, 0, + i, 4)); + } +} +#endif + +static int +fsl_pcib_maxslots(device_t dev) +{ + struct fsl_pcib_softc *sc = device_get_softc(dev); + + return ((sc->sc_pcie) ? 1 : 31); +} + +static uint32_t +fsl_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func, + u_int reg, int bytes) +{ + struct fsl_pcib_softc *sc = device_get_softc(dev); + u_int devfn; + + if (bus == sc->sc_busnr && !sc->sc_pcie && slot < 10) + return (~0); + devfn = DEVFN(bus, slot, func); + if (devfn == sc->sc_devfn_tundra) + return (~0); + if (devfn == sc->sc_devfn_via_ide && reg == PCIR_INTPIN) + return (1); + return (fsl_pcib_cfgread(sc, bus, slot, func, reg, bytes)); +} + +static void +fsl_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func, + u_int reg, uint32_t val, int bytes) +{ + struct fsl_pcib_softc *sc = device_get_softc(dev); + + if (bus == sc->sc_busnr && !sc->sc_pcie && slot < 10) + return; + fsl_pcib_cfgwrite(sc, bus, slot, func, reg, val, bytes); +} + +static void +fsl_pcib_init_via(struct fsl_pcib_softc *sc, uint16_t device, int bus, + int slot, int fn) +{ + + if (device == 0x0686) { + fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x52, 0x34, 1); + fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x77, 0x00, 1); + fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x83, 0x98, 1); + fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x85, 0x03, 1); + } else if (device == 0x0571) { + sc->sc_devfn_via_ide = DEVFN(bus, slot, fn); + fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x40, 0x0b, 1); + } +} + +static int +fsl_pcib_init_bar(struct fsl_pcib_softc *sc, int bus, int slot, int func, + int barno) +{ + bus_addr_t *allocp; + uint32_t addr, mask, size; + int reg, width; + + reg = PCIR_BAR(barno); + + if (DEVFN(bus, slot, func) == sc->sc_devfn_via_ide) { + switch (barno) { + case 0: addr = 0x1f0; break; + case 1: addr = 0x3f4; break; + case 2: addr = 0x170; break; + case 3: addr = 0x374; break; + case 4: addr = 0xcc0; break; + default: return (1); + } + fsl_pcib_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4); + return (1); + } + + fsl_pcib_write_config(sc->sc_dev, bus, slot, func, reg, ~0, 4); + size = fsl_pcib_read_config(sc->sc_dev, bus, slot, func, reg, 4); + if (size == 0) + return (1); + width = ((size & 7) == 4) ? 2 : 1; + + if (size & 1) { /* I/O port */ + allocp = &sc->sc_ioport_alloc; + size &= ~3; + if ((size & 0xffff0000) == 0) + size |= 0xffff0000; + } else { /* memory */ + allocp = &sc->sc_iomem_alloc; + size &= ~15; + } + mask = ~size; + size = mask + 1; + /* Sanity check (must be a power of 2). */ + if (size & mask) + return (width); + + addr = (*allocp + mask) & ~mask; + *allocp = addr + size; + + if (bootverbose) + printf("PCI %u:%u:%u:%u: reg %x: size=%08x: addr=%08x\n", + device_get_unit(sc->sc_dev), bus, slot, func, reg, + size, addr); + + fsl_pcib_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4); + if (width == 2) + fsl_pcib_write_config(sc->sc_dev, bus, slot, func, reg + 4, + 0, 4); + return (width); +} + +static u_int +fsl_pcib_route_int(struct fsl_pcib_softc *sc, u_int bus, u_int slot, u_int func, + u_int intpin) +{ + int err, unit; + u_int devfn, intline; + + unit = device_get_unit(sc->sc_dev); + + devfn = DEVFN(bus, slot, func); + if (devfn == sc->sc_devfn_via_ide) +#if 0 + intline = INTR_VEC(ATPIC_ID, 14); + else if (devfn == sc->sc_devfn_via_ide + 1) + intline = INTR_VEC(ATPIC_ID, 10); + else if (devfn == sc->sc_devfn_via_ide + 2) + intline = INTR_VEC(ATPIC_ID, 10); +#endif + ; + else { + if (intpin != 0) + err = fdt_pci_route_intr(bus, slot, func, intpin, + &sc->sc_intr_info, &intline); + else + intline = 0xff; + } + + if (bootverbose) + printf("PCI %u:%u:%u:%u: intpin %u: intline=%u\n", + unit, bus, slot, func, intpin, intline); + + return (intline); +} + +static int +fsl_pcib_init(struct fsl_pcib_softc *sc, int bus, int busnr_offset, + int maxslot) +{ + int secbus, subbus; + int old_pribus, old_secbus, old_subbus; + int new_pribus, new_secbus, new_subbus; + int slot, func, maxfunc; + int bar, maxbar; + uint16_t vendor, device; + uint8_t command, hdrtype, class, subclass; + uint8_t intline, intpin; + + subbus = bus; + for (slot = 0; slot <= maxslot; slot++) { + maxfunc = 0; + for (func = 0; func <= maxfunc; func++) { + + hdrtype = fsl_pcib_read_config(sc->sc_dev, bus, slot, + func, PCIR_HDRTYPE, 1); + + if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE) + continue; + + if (func == 0 && (hdrtype & PCIM_MFDEV)) + maxfunc = PCI_FUNCMAX; + + vendor = fsl_pcib_read_config(sc->sc_dev, bus, slot, + func, PCIR_VENDOR, 2); + device = fsl_pcib_read_config(sc->sc_dev, bus, slot, + func, PCIR_DEVICE, 2); + + if (vendor == 0x1957 && device == 0x3fff) { + sc->sc_devfn_tundra = DEVFN(bus, slot, func); + continue; + } + + command = fsl_pcib_read_config(sc->sc_dev, bus, slot, + func, PCIR_COMMAND, 1); + command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN); + fsl_pcib_write_config(sc->sc_dev, bus, slot, func, + PCIR_COMMAND, command, 1); + + if (vendor == 0x1106) + fsl_pcib_init_via(sc, device, bus, slot, func); + + /* Program the base address registers. */ + maxbar = (hdrtype & PCIM_HDRTYPE) ? 1 : 6; + bar = 0; + while (bar < maxbar) + bar += fsl_pcib_init_bar(sc, bus, slot, func, + bar); + + /* Perform interrupt routing. */ + intpin = fsl_pcib_read_config(sc->sc_dev, bus, slot, + func, PCIR_INTPIN, 1); + intline = fsl_pcib_route_int(sc, bus, slot, func, + intpin); + fsl_pcib_write_config(sc->sc_dev, bus, slot, func, + PCIR_INTLINE, intline, 1); + + command |= PCIM_CMD_MEMEN | PCIM_CMD_PORTEN; + fsl_pcib_write_config(sc->sc_dev, bus, slot, func, + PCIR_COMMAND, command, 1); + + /* + * Handle PCI-PCI bridges + */ + class = fsl_pcib_read_config(sc->sc_dev, bus, slot, + func, PCIR_CLASS, 1); + subclass = fsl_pcib_read_config(sc->sc_dev, bus, slot, + func, PCIR_SUBCLASS, 1); +#if 0 + /* Allow only proper PCI-PCI briges */ + if (class != PCIC_BRIDGE) + continue; + if (subclass != PCIS_BRIDGE_PCI) + continue; +#endif + /* Allow all DEVTYPE 1 devices */ + if (hdrtype != PCIM_HDRTYPE_BRIDGE) + continue; + + subbus++; + secbus = subbus; + + /* Program I/O decoder. */ + fsl_pcib_write_config(sc->sc_dev, bus, slot, func, + PCIR_IOBASEL_1, sc->sc_ioport.rm_start >> 8, 1); + fsl_pcib_write_config(sc->sc_dev, bus, slot, func, + PCIR_IOLIMITL_1, sc->sc_ioport.rm_end >> 8, 1); + fsl_pcib_write_config(sc->sc_dev, bus, slot, func, + PCIR_IOBASEH_1, sc->sc_ioport.rm_start >> 16, 2); + fsl_pcib_write_config(sc->sc_dev, bus, slot, func, + PCIR_IOLIMITH_1, sc->sc_ioport.rm_end >> 16, 2); + + /* Program (non-prefetchable) memory decoder. */ + fsl_pcib_write_config(sc->sc_dev, bus, slot, func, + PCIR_MEMBASE_1, sc->sc_iomem.rm_start >> 16, 2); + fsl_pcib_write_config(sc->sc_dev, bus, slot, func, + PCIR_MEMLIMIT_1, sc->sc_iomem.rm_end >> 16, 2); + + /* Program prefetchable memory decoder. */ + fsl_pcib_write_config(sc->sc_dev, bus, slot, func, + PCIR_PMBASEL_1, 0x0010, 2); + fsl_pcib_write_config(sc->sc_dev, bus, slot, func, + PCIR_PMLIMITL_1, 0x000f, 2); + fsl_pcib_write_config(sc->sc_dev, bus, slot, func, + PCIR_PMBASEH_1, 0x00000000, 4); + fsl_pcib_write_config(sc->sc_dev, bus, slot, func, + PCIR_PMLIMITH_1, 0x00000000, 4); + + /* Read currect bus register configuration */ + old_pribus = fsl_pcib_read_config(sc->sc_dev, bus, + slot, func, PCIR_PRIBUS_1, 1); + old_secbus = fsl_pcib_read_config(sc->sc_dev, bus, + slot, func, PCIR_SECBUS_1, 1); + old_subbus = fsl_pcib_read_config(sc->sc_dev, bus, + slot, func, PCIR_SUBBUS_1, 1); + + if (bootverbose) + printf("PCI: reading firmware bus numbers for " + "secbus = %d (bus/sec/sub) = (%d/%d/%d)\n", + secbus + busnr_offset, old_pribus, + old_secbus, old_subbus); + + /* Skip unconfigured devices */ + if ((old_pribus == 0) && + (old_secbus == 0) && (old_subbus == 0)) + continue; + + subbus += fsl_pcib_init(sc, secbus, busnr_offset, + (subclass == PCIS_BRIDGE_PCI) ? 31 : 1); + + new_pribus = bus + busnr_offset; + new_secbus = secbus + busnr_offset; + new_subbus = subbus + busnr_offset; + + /* Fixup pribus for MPC8572 PCIE controller */ + if ((vendor == 0x1957) && ((device = 0x0040) || + (device == 0x0041))) + new_pribus = 0; + + if (bootverbose) + printf("PCI: translate firmware bus numbers for " + "secbus %d (%d/%d/%d) -> (%d/%d/%d)\n", + secbus + busnr_offset, + old_pribus, old_secbus, old_subbus, + new_pribus, new_secbus, new_subbus); + + fsl_pcib_write_config(sc->sc_dev, bus, slot, func, + PCIR_PRIBUS_1, new_pribus, 1); + fsl_pcib_write_config(sc->sc_dev, bus, slot, func, + PCIR_SECBUS_1, new_secbus, 1); + fsl_pcib_write_config(sc->sc_dev, bus, slot, func, + PCIR_SUBBUS_1, new_subbus, 1); + } + } + + if (bootverbose) + printf("PCI: bus %d, #subbus = %d\n", + bus + busnr_offset, subbus - bus); + + return (subbus - bus); +} + +static void +fsl_pcib_inbound(struct fsl_pcib_softc *sc, int wnd, int tgt, u_long start, + u_long size, u_long pci_start) +{ + uint32_t attr, bar, tar; + + KASSERT(wnd > 0, ("%s: inbound window 0 is invalid", __func__)); + + switch (tgt) { + /* XXX OCP85XX_TGTIF_RAM2, OCP85XX_TGTIF_RAM_INTL should be handled */ + case OCP85XX_TGTIF_RAM1: + attr = 0xa0f55000 | (ffsl(size) - 2); + break; + default: + attr = 0; + break; + } + tar = start >> 12; + bar = pci_start >> 12; + + bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PITAR(wnd), tar); + bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWBEAR(wnd), 0); + bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWBAR(wnd), bar); + bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWAR(wnd), attr); +} + +static void +fsl_pcib_outbound(struct fsl_pcib_softc *sc, int wnd, int res, u_long start, + u_long size, u_long pci_start) +{ + uint32_t attr, bar, tar; + + switch (res) { + case SYS_RES_MEMORY: + attr = 0x80044000 | (ffsl(size) - 2); + break; + case SYS_RES_IOPORT: + attr = 0x80088000 | (ffsl(size) - 2); + break; + default: + attr = 0x0004401f; + break; + } + bar = start >> 12; + tar = pci_start >> 12; + + bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POTAR(wnd), tar); + bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POTEAR(wnd), 0); + bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POWBAR(wnd), bar); + bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POWAR(wnd), attr); +} + +static int +fsl_pcib_set_range(struct fsl_pcib_softc *sc, int type, int wnd, u_long start, + u_long size) +{ + struct rman *rm; + u_long end, alloc; + bus_addr_t pci_start, pci_end; + bus_addr_t *vap, *allocp; + int error; + + end = start + size - 1; + + switch (type) { + case SYS_RES_IOPORT: + rm = &sc->sc_ioport; + pci_start = 0x0000; + pci_end = 0xffff; + alloc = 0x1000; + vap = &sc->sc_ioport_va; + allocp = &sc->sc_ioport_alloc; + break; + case SYS_RES_MEMORY: + rm = &sc->sc_iomem; + pci_start = start; + pci_end = end; + alloc = 0; + vap = &sc->sc_iomem_va; + allocp = &sc->sc_iomem_alloc; + break; + default: + return (EINVAL); + } + + rm->rm_type = RMAN_ARRAY; + rm->rm_start = pci_start; + rm->rm_end = pci_end; + error = rman_init(rm); + if (error) + return (error); + + error = rman_manage_region(rm, pci_start, pci_end); + if (error) { + rman_fini(rm); + return (error); + } + + *allocp = pci_start + alloc; + *vap = (uintptr_t)pmap_mapdev(start, size); + fsl_pcib_outbound(sc, wnd, type, start, size, pci_start); + return (0); +} + +static void +fsl_pcib_err_init(device_t dev) +{ + struct fsl_pcib_softc *sc; + uint16_t sec_stat, dsr; + uint32_t dcr, err_en; + + sc = device_get_softc(dev); + + sec_stat = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_SECSTAT_1, 2); + if (sec_stat) + fsl_pcib_cfgwrite(sc, 0, 0, 0, PCIR_SECSTAT_1, 0xffff, 2); + if (sc->sc_pcie) { + /* Clear error bits */ + bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_MES_IER, + 0xffffffff); + bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_MES_DR, + 0xffffffff); + bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_ERR_DR, + 0xffffffff); + + dsr = fsl_pcib_cfgread(sc, 0, 0, 0, + sc->sc_pcie_capreg + PCIR_EXPRESS_DEVICE_STA, 2); + if (dsr) + fsl_pcib_cfgwrite(sc, 0, 0, 0, + sc->sc_pcie_capreg + PCIR_EXPRESS_DEVICE_STA, + 0xffff, 2); + + /* Enable all errors reporting */ + err_en = 0x00bfff00; + bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_ERR_EN, + err_en); + + /* Enable error reporting: URR, FER, NFER */ + dcr = fsl_pcib_cfgread(sc, 0, 0, 0, + sc->sc_pcie_capreg + PCIR_EXPRESS_DEVICE_CTL, 4); + dcr |= PCIM_EXP_CTL_URR_ENABLE | PCIM_EXP_CTL_FER_ENABLE | + PCIM_EXP_CTL_NFER_ENABLE; + fsl_pcib_cfgwrite(sc, 0, 0, 0, + sc->sc_pcie_capreg + PCIR_EXPRESS_DEVICE_CTL, dcr, 4); + } +} + +static int +fsl_pcib_detach(device_t dev) +{ + + if (mtx_initialized) { + mtx_destroy(&pcicfg_mtx); + mtx_initialized = 0; + } + return (bus_generic_detach(dev)); +} + +static struct resource * +fsl_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct fsl_pcib_softc *sc = device_get_softc(dev); + struct rman *rm; + struct resource *res; + bus_addr_t va; + + switch (type) { + case SYS_RES_IOPORT: + rm = &sc->sc_ioport; + va = sc->sc_ioport_va; + break; + case SYS_RES_MEMORY: + rm = &sc->sc_iomem; + va = sc->sc_iomem_va; + break; + case SYS_RES_IRQ: +#if 0 + if (INTR_IGN(start) == powerpc_ign_lookup(ATPIC_ID)) { + device_printf(dev, "%s requested ISA interrupt %lu\n", + device_get_nameunit(child), start); + } +#endif + flags |= RF_SHAREABLE; + return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child, + type, rid, start, end, count, flags)); + default: + return (NULL); + } + + res = rman_reserve_resource(rm, start, end, count, flags, child); + if (res == NULL) + return (NULL); + + rman_set_bustag(res, &bs_le_tag); + rman_set_bushandle(res, va + rman_get_start(res) - rm->rm_start); + return (res); +} + +static int +fsl_pcib_release_resource(device_t dev, device_t child, int type, int rid, + struct resource *res) +{ + + return (rman_release_resource(res)); +} + +static int +fsl_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +{ + struct fsl_pcib_softc *sc = device_get_softc(dev); + + switch (which) { + case PCIB_IVAR_BUS: + *result = sc->sc_busnr; + return (0); + case PCIB_IVAR_DOMAIN: + *result = device_get_unit(dev); + return (0); + } + return (ENOENT); +} + +static int +fsl_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value) +{ + struct fsl_pcib_softc *sc = device_get_softc(dev); + + switch (which) { + case PCIB_IVAR_BUS: + sc->sc_busnr = value; + return (0); + } + return (ENOENT); +} + +static int +fsl_pcib_intr_info(phandle_t node, struct fsl_pcib_softc *sc) +{ + int error; + + if ((error = fdt_pci_intr_info(node, &sc->sc_intr_info)) != 0) + return (error); + + return (0); +} + +static int +fsl_pcib_decode_win(phandle_t node, struct fsl_pcib_softc *sc) +{ + struct fdt_pci_range io_space, mem_space; + device_t dev; + int error; + + dev = sc->sc_dev; + + if ((error = fdt_pci_ranges(node, &io_space, &mem_space)) != 0) { + device_printf(dev, "could not retrieve 'ranges' data\n"); + return (error); + } + + /* + * Configure LAW decode windows. + */ + error = law_pci_target(sc->sc_res, &sc->sc_iomem_target, + &sc->sc_ioport_target); + if (error != 0) { + device_printf(dev, "could not retrieve PCI LAW target info\n"); + return (error); + } + error = law_enable(sc->sc_iomem_target, mem_space.base_parent, + mem_space.len); + if (error != 0) { + device_printf(dev, "could not program LAW for PCI MEM range\n"); + return (error); + } + error = law_enable(sc->sc_ioport_target, io_space.base_parent, + io_space.len); + if (error != 0) { + device_printf(dev, "could not program LAW for PCI IO range\n"); + return (error); + } + + /* + * Set outbout and inbound windows. + */ + fsl_pcib_outbound(sc, 0, -1, 0, 0, 0); + if ((error = fsl_pcib_set_range(sc, SYS_RES_MEMORY, 1, + mem_space.base_parent, mem_space.len)) != 0) + return (error); + if ((error = fsl_pcib_set_range(sc, SYS_RES_IOPORT, 2, + io_space.base_parent, io_space.len)) != 0) + return (error); + + fsl_pcib_outbound(sc, 3, -1, 0, 0, 0); + fsl_pcib_outbound(sc, 4, -1, 0, 0, 0); + + fsl_pcib_inbound(sc, 1, -1, 0, 0, 0); + fsl_pcib_inbound(sc, 2, -1, 0, 0, 0); + fsl_pcib_inbound(sc, 3, OCP85XX_TGTIF_RAM1, 0, + 2U * 1024U * 1024U * 1024U, 0); + + return (0); +} diff --git a/sys/powerpc/mpc85xx/pci_ocp.c b/sys/powerpc/mpc85xx/pci_ocp.c deleted file mode 100644 index 857f222cd265..000000000000 --- a/sys/powerpc/mpc85xx/pci_ocp.c +++ /dev/null @@ -1,850 +0,0 @@ -/*- - * Copyright 2006-2007 by Juniper Networks. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/ktr.h> -#include <sys/sockio.h> -#include <sys/mbuf.h> -#include <sys/malloc.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/socket.h> -#include <sys/queue.h> -#include <sys/bus.h> -#include <sys/rman.h> -#include <sys/endian.h> - -#include <vm/vm.h> -#include <vm/pmap.h> - -#include <dev/pci/pcivar.h> -#include <dev/pci/pcireg.h> -#include <dev/pci/pcib_private.h> - -#include "pcib_if.h" - -#include <machine/resource.h> -#include <machine/bus.h> -#include <machine/intr_machdep.h> -#include <machine/ocpbus.h> -#include <machine/spr.h> - -#include <powerpc/mpc85xx/ocpbus.h> - -#define REG_CFG_ADDR 0x0000 -#define CONFIG_ACCESS_ENABLE 0x80000000 - -#define REG_CFG_DATA 0x0004 -#define REG_INT_ACK 0x0008 - -#define REG_POTAR(n) (0x0c00 + 0x20 * (n)) -#define REG_POTEAR(n) (0x0c04 + 0x20 * (n)) -#define REG_POWBAR(n) (0x0c08 + 0x20 * (n)) -#define REG_POWAR(n) (0x0c10 + 0x20 * (n)) - -#define REG_PITAR(n) (0x0e00 - 0x20 * (n)) -#define REG_PIWBAR(n) (0x0e08 - 0x20 * (n)) -#define REG_PIWBEAR(n) (0x0e0c - 0x20 * (n)) -#define REG_PIWAR(n) (0x0e10 - 0x20 * (n)) - -#define PCIR_FSL_LTSSM 0x404 -#define FSL_LTSSM_L0 0x16 - -#define DEVFN(b, s, f) ((b << 16) | (s << 8) | f) - -struct pci_ocp_softc { - device_t sc_dev; - - struct rman sc_iomem; - bus_addr_t sc_iomem_va; /* Virtual mapping. */ - bus_addr_t sc_iomem_alloc; /* Next allocation. */ - struct rman sc_ioport; - bus_addr_t sc_ioport_va; /* Virtual mapping. */ - bus_addr_t sc_ioport_alloc; /* Next allocation. */ - - struct resource *sc_res; - bus_space_handle_t sc_bsh; - bus_space_tag_t sc_bst; - int sc_rid; - - int sc_busnr; - uint8_t sc_pcie_cap; - - /* Devices that need special attention. */ - int sc_devfn_tundra; - int sc_devfn_via_ide; -}; - -static int pci_ocp_attach(device_t); -static int pci_ocp_probe(device_t); - -static struct resource *pci_ocp_alloc_resource(device_t, device_t, int, int *, - u_long, u_long, u_long, u_int); -static int pci_ocp_read_ivar(device_t, device_t, int, uintptr_t *); -static int pci_ocp_release_resource(device_t, device_t, int, int, - struct resource *); -static int pci_ocp_write_ivar(device_t, device_t, int, uintptr_t); - -static int pci_ocp_maxslots(device_t); -static uint32_t pci_ocp_read_config(device_t, u_int, u_int, u_int, u_int, int); -static void pci_ocp_write_config(device_t, u_int, u_int, u_int, u_int, - uint32_t, int); - -/* - * Bus interface definitions. - */ -static device_method_t pci_ocp_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, pci_ocp_probe), - DEVMETHOD(device_attach, pci_ocp_attach), - - /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_read_ivar, pci_ocp_read_ivar), - DEVMETHOD(bus_write_ivar, pci_ocp_write_ivar), - DEVMETHOD(bus_alloc_resource, pci_ocp_alloc_resource), - DEVMETHOD(bus_release_resource, pci_ocp_release_resource), - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), - DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), - DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), - DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), - - /* pcib interface */ - DEVMETHOD(pcib_maxslots, pci_ocp_maxslots), - DEVMETHOD(pcib_read_config, pci_ocp_read_config), - DEVMETHOD(pcib_write_config, pci_ocp_write_config), - DEVMETHOD(pcib_route_interrupt, pcib_route_interrupt), - - { 0, 0 } -}; - -static driver_t pci_ocp_driver = { - "pcib", - pci_ocp_methods, - sizeof(struct pci_ocp_softc), -}; - -devclass_t pcib_devclass; - -DRIVER_MODULE(pcib, ocpbus, pci_ocp_driver, pcib_devclass, 0, 0); - -static uint32_t -pci_ocp_cfgread(struct pci_ocp_softc *sc, u_int bus, u_int slot, u_int func, - u_int reg, int bytes) -{ - uint32_t addr, data; - - if (bus == sc->sc_busnr) - bus = 0; - - addr = CONFIG_ACCESS_ENABLE; - addr |= (bus & 0xff) << 16; - addr |= (slot & 0x1f) << 11; - addr |= (func & 0x7) << 8; - addr |= reg & 0xfc; - if (sc->sc_pcie_cap) - addr |= (reg & 0xf00) << 16; - bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_CFG_ADDR, addr); - - switch (bytes) { - case 1: - data = bus_space_read_1(sc->sc_bst, sc->sc_bsh, - REG_CFG_DATA + (reg & 3)); - break; - case 2: - data = le16toh(bus_space_read_2(sc->sc_bst, sc->sc_bsh, - REG_CFG_DATA + (reg & 2))); - break; - case 4: - data = le32toh(bus_space_read_4(sc->sc_bst, sc->sc_bsh, - REG_CFG_DATA)); - break; - default: - data = ~0; - break; - } - return (data); -} - -static void -pci_ocp_cfgwrite(struct pci_ocp_softc *sc, u_int bus, u_int slot, u_int func, - u_int reg, uint32_t data, int bytes) -{ - uint32_t addr; - - if (bus == sc->sc_busnr) - bus = 0; - - addr = CONFIG_ACCESS_ENABLE; - addr |= (bus & 0xff) << 16; - addr |= (slot & 0x1f) << 11; - addr |= (func & 0x7) << 8; - addr |= reg & 0xfc; - if (sc->sc_pcie_cap) - addr |= (reg & 0xf00) << 16; - bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_CFG_ADDR, addr); - - switch (bytes) { - case 1: - bus_space_write_1(sc->sc_bst, sc->sc_bsh, - REG_CFG_DATA + (reg & 3), data); - break; - case 2: - bus_space_write_2(sc->sc_bst, sc->sc_bsh, - REG_CFG_DATA + (reg & 2), htole16(data)); - break; - case 4: - bus_space_write_4(sc->sc_bst, sc->sc_bsh, - REG_CFG_DATA, htole32(data)); - break; - } -} - -#if 0 -static void -dump(struct pci_ocp_softc *sc) -{ - unsigned int i; - -#define RD(o) bus_space_read_4(sc->sc_bst, sc->sc_bsh, o) - for (i = 0; i < 5; i++) { - printf("POTAR%u =0x%08x\n", i, RD(REG_POTAR(i))); - printf("POTEAR%u =0x%08x\n", i, RD(REG_POTEAR(i))); - printf("POWBAR%u =0x%08x\n", i, RD(REG_POWBAR(i))); - printf("POWAR%u =0x%08x\n", i, RD(REG_POWAR(i))); - } - printf("\n"); - for (i = 1; i < 4; i++) { - printf("PITAR%u =0x%08x\n", i, RD(REG_PITAR(i))); - printf("PIWBAR%u =0x%08x\n", i, RD(REG_PIWBAR(i))); - printf("PIWBEAR%u=0x%08x\n", i, RD(REG_PIWBEAR(i))); - printf("PIWAR%u =0x%08x\n", i, RD(REG_PIWAR(i))); - } - printf("\n"); -#undef RD - - for (i = 0; i < 0x48; i += 4) { - printf("cfg%02x=0x%08x\n", i, pci_ocp_cfgread(sc, 0, 0, 0, - i, 4)); - } -} -#endif - -static int -pci_ocp_maxslots(device_t dev) -{ - struct pci_ocp_softc *sc = device_get_softc(dev); - - return ((sc->sc_pcie_cap) ? 0 : 31); -} - -static uint32_t -pci_ocp_read_config(device_t dev, u_int bus, u_int slot, u_int func, - u_int reg, int bytes) -{ - struct pci_ocp_softc *sc = device_get_softc(dev); - u_int devfn; - - if (bus == sc->sc_busnr && !sc->sc_pcie_cap && slot < 10) - return (~0); - devfn = DEVFN(bus, slot, func); - /* - * For the host controller itself, pretend to be a standard - * PCI bridge, rather than a PowerPC processor. That way the - * generic PCI code will enumerate all subordinate busses - * and devices as usual. - */ - if (sc->sc_pcie_cap && devfn == 0) { - if (reg == PCIR_CLASS && bytes == 1) - return (PCIC_BRIDGE); - if (reg == PCIR_SUBCLASS && bytes == 1) - return (PCIS_BRIDGE_PCI); - } - if (devfn == sc->sc_devfn_tundra) - return (~0); - if (devfn == sc->sc_devfn_via_ide && reg == PCIR_INTPIN) - return (1); - return (pci_ocp_cfgread(sc, bus, slot, func, reg, bytes)); -} - -static void -pci_ocp_write_config(device_t dev, u_int bus, u_int slot, u_int func, - u_int reg, uint32_t val, int bytes) -{ - struct pci_ocp_softc *sc = device_get_softc(dev); - - if (bus == sc->sc_busnr && !sc->sc_pcie_cap && slot < 10) - return; - pci_ocp_cfgwrite(sc, bus, slot, func, reg, val, bytes); -} - -static int -pci_ocp_probe(device_t dev) -{ - char buf[128]; - struct pci_ocp_softc *sc; - const char *type; - device_t parent; - u_long start, size; - uintptr_t devtype; - uint32_t cfgreg; - uint8_t capptr; - int error; - - parent = device_get_parent(dev); - error = BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_DEVTYPE, &devtype); - if (error) - return (error); - if (devtype != OCPBUS_DEVTYPE_PCIB) - return (ENXIO); - - sc = device_get_softc(dev); - sc->sc_dev = dev; - - sc->sc_rid = 0; - sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid, - RF_ACTIVE); - if (sc->sc_res == NULL) - return (ENXIO); - - sc->sc_bst = rman_get_bustag(sc->sc_res); - sc->sc_bsh = rman_get_bushandle(sc->sc_res); - sc->sc_busnr = 0; - - error = ENOENT; - cfgreg = pci_ocp_cfgread(sc, 0, 0, 0, PCIR_VENDOR, 2); - if (cfgreg != 0x1057 && cfgreg != 0x1957) - goto out; - - cfgreg = pci_ocp_cfgread(sc, 0, 0, 0, PCIR_CLASS, 1); - if (cfgreg != PCIC_PROCESSOR) - goto out; - - cfgreg = pci_ocp_cfgread(sc, 0, 0, 0, PCIR_SUBCLASS, 1); - if (cfgreg != PCIS_PROCESSOR_POWERPC) - goto out; - - cfgreg = pci_ocp_cfgread(sc, 0, 0, 0, PCIR_PROGIF, 1); - if (cfgreg != 0) /* RC mode = 0, EP mode = 1 */ - goto out; - - type = "PCI"; - capptr = pci_ocp_cfgread(sc, 0, 0, 0, PCIR_CAP_PTR, 1); - while (capptr != 0) { - cfgreg = pci_ocp_cfgread(sc, 0, 0, 0, capptr, 2); - switch (cfgreg & 0xff) { - case PCIY_PCIX: /* PCI-X */ - type = "PCI-X"; - break; - case PCIY_EXPRESS: /* PCI Express */ - type = "PCI Express"; - sc->sc_pcie_cap = capptr; - break; - } - capptr = (cfgreg >> 8) & 0xff; - } - - error = bus_get_resource(dev, SYS_RES_MEMORY, 1, &start, &size); - if (error || start == 0 || size == 0) - goto out; - - snprintf(buf, sizeof(buf), - "Freescale on-chip %s host controller", type); - device_set_desc_copy(dev, buf); - error = BUS_PROBE_DEFAULT; - -out: - bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res); - return (error); -} - -static void -pci_ocp_init_via(struct pci_ocp_softc *sc, uint16_t device, int bus, - int slot, int fn) -{ - - if (device == 0x0686) { - pci_ocp_write_config(sc->sc_dev, bus, slot, fn, 0x52, 0x34, 1); - pci_ocp_write_config(sc->sc_dev, bus, slot, fn, 0x77, 0x00, 1); - pci_ocp_write_config(sc->sc_dev, bus, slot, fn, 0x83, 0x98, 1); - pci_ocp_write_config(sc->sc_dev, bus, slot, fn, 0x85, 0x03, 1); - } else if (device == 0x0571) { - sc->sc_devfn_via_ide = DEVFN(bus, slot, fn); - pci_ocp_write_config(sc->sc_dev, bus, slot, fn, 0x40, 0x0b, 1); - } -} - -static int -pci_ocp_init_bar(struct pci_ocp_softc *sc, int bus, int slot, int func, - int barno) -{ - bus_addr_t *allocp; - uint32_t addr, mask, size; - int reg, width; - - reg = PCIR_BAR(barno); - - if (DEVFN(bus, slot, func) == sc->sc_devfn_via_ide) { - switch (barno) { - case 0: addr = 0x1f0; break; - case 1: addr = 0x3f4; break; - case 2: addr = 0x170; break; - case 3: addr = 0x374; break; - case 4: addr = 0xcc0; break; - default: return (1); - } - pci_ocp_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4); - return (1); - } - - pci_ocp_write_config(sc->sc_dev, bus, slot, func, reg, ~0, 4); - size = pci_ocp_read_config(sc->sc_dev, bus, slot, func, reg, 4); - if (size == 0) - return (1); - width = ((size & 7) == 4) ? 2 : 1; - - if (size & 1) { /* I/O port */ - allocp = &sc->sc_ioport_alloc; - size &= ~3; - if ((size & 0xffff0000) == 0) - size |= 0xffff0000; - } else { /* memory */ - allocp = &sc->sc_iomem_alloc; - size &= ~15; - } - mask = ~size; - size = mask + 1; - /* Sanity check (must be a power of 2). */ - if (size & mask) - return (width); - - addr = (*allocp + mask) & ~mask; - *allocp = addr + size; - - if (bootverbose) - printf("PCI %u:%u:%u:%u: reg %x: size=%08x: addr=%08x\n", - device_get_unit(sc->sc_dev), bus, slot, func, reg, - size, addr); - - pci_ocp_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4); - if (width == 2) - pci_ocp_write_config(sc->sc_dev, bus, slot, func, reg + 4, - 0, 4); - return (width); -} - -static u_int -pci_ocp_route_int(struct pci_ocp_softc *sc, u_int bus, u_int slot, u_int func, - u_int intpin) -{ - u_int devfn, intline; - - devfn = DEVFN(bus, slot, func); - if (devfn == sc->sc_devfn_via_ide) - intline = INTR_VEC(ATPIC_ID, 14); - else if (devfn == sc->sc_devfn_via_ide + 1) - intline = INTR_VEC(ATPIC_ID, 10); - else if (devfn == sc->sc_devfn_via_ide + 2) - intline = INTR_VEC(ATPIC_ID, 10); - else { - if (intpin != 0) { - intline = intpin - 1; - intline += (bus != sc->sc_busnr) ? slot : 0; - intline = PIC_IRQ_EXT(intline & 3); - } else - intline = 0xff; - } - - if (bootverbose) - printf("PCI %u:%u:%u:%u: intpin %u: intline=%u\n", - device_get_unit(sc->sc_dev), bus, slot, func, - intpin, intline); - - return (intline); -} - -static int -pci_ocp_init(struct pci_ocp_softc *sc, int bus, int nslots) -{ - int secbus, slot; - int func, maxfunc; - int bar, maxbar; - uint16_t vendor, device; - uint8_t command, hdrtype, class, subclass; - uint8_t intline, intpin; - - secbus = bus; - for (slot = 0; slot < nslots; slot++) { - maxfunc = 0; - for (func = 0; func <= maxfunc; func++) { - hdrtype = pci_ocp_read_config(sc->sc_dev, bus, slot, - func, PCIR_HDRTYPE, 1); - if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE) - continue; - - if (func == 0 && (hdrtype & PCIM_MFDEV)) - maxfunc = PCI_FUNCMAX; - - vendor = pci_ocp_read_config(sc->sc_dev, bus, slot, - func, PCIR_VENDOR, 2); - device = pci_ocp_read_config(sc->sc_dev, bus, slot, - func, PCIR_DEVICE, 2); - - if (vendor == 0x1957 && device == 0x3fff) { - sc->sc_devfn_tundra = DEVFN(bus, slot, func); - continue; - } - - command = pci_ocp_read_config(sc->sc_dev, bus, slot, - func, PCIR_COMMAND, 1); - command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN); - pci_ocp_write_config(sc->sc_dev, bus, slot, func, - PCIR_COMMAND, command, 1); - - if (vendor == 0x1106) - pci_ocp_init_via(sc, device, bus, slot, func); - - /* Program the base address registers. */ - maxbar = (hdrtype & PCIM_HDRTYPE) ? 1 : 6; - bar = 0; - while (bar < maxbar) - bar += pci_ocp_init_bar(sc, bus, slot, func, - bar); - - /* Perform interrupt routing. */ - intpin = pci_ocp_read_config(sc->sc_dev, bus, slot, - func, PCIR_INTPIN, 1); - intline = pci_ocp_route_int(sc, bus, slot, func, - intpin); - pci_ocp_write_config(sc->sc_dev, bus, slot, func, - PCIR_INTLINE, intline, 1); - - command |= PCIM_CMD_MEMEN | PCIM_CMD_PORTEN; - pci_ocp_write_config(sc->sc_dev, bus, slot, func, - PCIR_COMMAND, command, 1); - - /* - * Handle PCI-PCI bridges - */ - class = pci_ocp_read_config(sc->sc_dev, bus, slot, - func, PCIR_CLASS, 1); - if (class != PCIC_BRIDGE) - continue; - subclass = pci_ocp_read_config(sc->sc_dev, bus, slot, - func, PCIR_SUBCLASS, 1); - if (subclass != PCIS_BRIDGE_PCI) - continue; - - secbus++; - - /* Program I/O decoder. */ - pci_ocp_write_config(sc->sc_dev, bus, slot, func, - PCIR_IOBASEL_1, sc->sc_ioport.rm_start >> 8, 1); - pci_ocp_write_config(sc->sc_dev, bus, slot, func, - PCIR_IOLIMITL_1, sc->sc_ioport.rm_end >> 8, 1); - pci_ocp_write_config(sc->sc_dev, bus, slot, func, - PCIR_IOBASEH_1, sc->sc_ioport.rm_start >> 16, 2); - pci_ocp_write_config(sc->sc_dev, bus, slot, func, - PCIR_IOLIMITH_1, sc->sc_ioport.rm_end >> 16, 2); - - /* Program (non-prefetchable) memory decoder. */ - pci_ocp_write_config(sc->sc_dev, bus, slot, func, - PCIR_MEMBASE_1, sc->sc_iomem.rm_start >> 16, 2); - pci_ocp_write_config(sc->sc_dev, bus, slot, func, - PCIR_MEMLIMIT_1, sc->sc_iomem.rm_end >> 16, 2); - - /* Program prefetchable memory decoder. */ - pci_ocp_write_config(sc->sc_dev, bus, slot, func, - PCIR_PMBASEL_1, 0x0010, 2); - pci_ocp_write_config(sc->sc_dev, bus, slot, func, - PCIR_PMLIMITL_1, 0x000f, 2); - pci_ocp_write_config(sc->sc_dev, bus, slot, func, - PCIR_PMBASEH_1, 0x00000000, 4); - pci_ocp_write_config(sc->sc_dev, bus, slot, func, - PCIR_PMLIMITH_1, 0x00000000, 4); - - pci_ocp_write_config(sc->sc_dev, bus, slot, func, - PCIR_PRIBUS_1, bus, 1); - pci_ocp_write_config(sc->sc_dev, bus, slot, func, - PCIR_SECBUS_1, secbus, 1); - pci_ocp_write_config(sc->sc_dev, bus, slot, func, - PCIR_SUBBUS_1, 0xff, 1); - - secbus = pci_ocp_init(sc, secbus, - (subclass == PCIS_BRIDGE_PCI) ? 32 : 1); - - pci_ocp_write_config(sc->sc_dev, bus, slot, func, - PCIR_SUBBUS_1, secbus, 1); - } - } - - return (secbus); -} - -static void -pci_ocp_inbound(struct pci_ocp_softc *sc, int wnd, int tgt, u_long start, - u_long size, u_long pci_start) -{ - uint32_t attr, bar, tar; - - KASSERT(wnd > 0, ("%s: inbound window 0 is invalid", __func__)); - - switch (tgt) { - case OCP85XX_TGTIF_RAM1: - attr = 0xa0f55000 | (ffsl(size) - 2); - break; - default: - attr = 0; - break; - } - tar = start >> 12; - bar = pci_start >> 12; - - bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PITAR(wnd), tar); - bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWBEAR(wnd), 0); - bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWBAR(wnd), bar); - bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWAR(wnd), attr); -} - -static void -pci_ocp_outbound(struct pci_ocp_softc *sc, int wnd, int res, u_long start, - u_long size, u_long pci_start) -{ - uint32_t attr, bar, tar; - - switch (res) { - case SYS_RES_MEMORY: - attr = 0x80044000 | (ffsl(size) - 2); - break; - case SYS_RES_IOPORT: - attr = 0x80088000 | (ffsl(size) - 2); - break; - default: - attr = 0x0004401f; - break; - } - bar = start >> 12; - tar = pci_start >> 12; - - bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POTAR(wnd), tar); - bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POTEAR(wnd), 0); - bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POWBAR(wnd), bar); - bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POWAR(wnd), attr); -} - -static int -pci_ocp_iorange(struct pci_ocp_softc *sc, int type, int wnd) -{ - struct rman *rm; - u_long start, end, size, alloc; - bus_addr_t pci_start, pci_end; - bus_addr_t *vap, *allocp; - int error; - - error = bus_get_resource(sc->sc_dev, type, 1, &start, &size); - if (error) - return (error); - - end = start + size - 1; - - switch (type) { - case SYS_RES_IOPORT: - rm = &sc->sc_ioport; - pci_start = 0x0000; - pci_end = 0xffff; - alloc = 0x1000; - vap = &sc->sc_ioport_va; - allocp = &sc->sc_ioport_alloc; - break; - case SYS_RES_MEMORY: - rm = &sc->sc_iomem; - pci_start = start; - pci_end = end; - alloc = 0; - vap = &sc->sc_iomem_va; - allocp = &sc->sc_iomem_alloc; - break; - default: - return (EINVAL); - } - - rm->rm_type = RMAN_ARRAY; - rm->rm_start = pci_start; - rm->rm_end = pci_end; - error = rman_init(rm); - if (error) - return (error); - - error = rman_manage_region(rm, pci_start, pci_end); - if (error) { - rman_fini(rm); - return (error); - } - - *allocp = pci_start + alloc; - *vap = (uintptr_t)pmap_mapdev(start, size); - if (wnd != -1) - pci_ocp_outbound(sc, wnd, type, start, size, pci_start); - return (0); -} - -static int -pci_ocp_attach(device_t dev) -{ - struct pci_ocp_softc *sc; - uint32_t cfgreg; - int error, nslots; - - sc = device_get_softc(dev); - sc->sc_dev = dev; - - sc->sc_rid = 0; - sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid, - RF_ACTIVE); - if (sc->sc_res == NULL) { - device_printf(dev, "could not map I/O memory\n"); - return (ENXIO); - } - sc->sc_bst = rman_get_bustag(sc->sc_res); - sc->sc_bsh = rman_get_bushandle(sc->sc_res); - - cfgreg = pci_ocp_cfgread(sc, 0, 0, 0, PCIR_COMMAND, 2); - cfgreg |= PCIM_CMD_SERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN | - PCIM_CMD_PORTEN; - pci_ocp_cfgwrite(sc, 0, 0, 0, PCIR_COMMAND, cfgreg, 2); - - pci_ocp_outbound(sc, 0, -1, 0, 0, 0); - error = pci_ocp_iorange(sc, SYS_RES_MEMORY, 1); - error = pci_ocp_iorange(sc, SYS_RES_IOPORT, 2); - pci_ocp_outbound(sc, 3, -1, 0, 0, 0); - pci_ocp_outbound(sc, 4, -1, 0, 0, 0); - - pci_ocp_inbound(sc, 1, -1, 0, 0, 0); - pci_ocp_inbound(sc, 2, -1, 0, 0, 0); - pci_ocp_inbound(sc, 3, OCP85XX_TGTIF_RAM1, 0, 2U*1024U*1024U*1024U, 0); - - sc->sc_devfn_tundra = -1; - sc->sc_devfn_via_ide = -1; - - /* - * PCI Express host controllers require a link. We don't - * fail the attach if there's no link, but we also don't - * create a child pci(4) device. - */ - if (sc->sc_pcie_cap) { - cfgreg = pci_ocp_cfgread(sc, 0, 0, 0, PCIR_FSL_LTSSM, 4); - if (cfgreg < FSL_LTSSM_L0) - return (0); - } - - nslots = (sc->sc_pcie_cap) ? 1 : 32; - pci_ocp_init(sc, sc->sc_busnr, nslots); - - device_add_child(dev, "pci", -1); - return (bus_generic_attach(dev)); -} - -static struct resource * -pci_ocp_alloc_resource(device_t dev, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) -{ - struct pci_ocp_softc *sc = device_get_softc(dev); - struct rman *rm; - struct resource *res; - bus_addr_t va; - - switch (type) { - case SYS_RES_IOPORT: - rm = &sc->sc_ioport; - va = sc->sc_ioport_va; - break; - case SYS_RES_MEMORY: - rm = &sc->sc_iomem; - va = sc->sc_iomem_va; - break; - case SYS_RES_IRQ: - if (INTR_IGN(start) == powerpc_ign_lookup(ATPIC_ID)) { - device_printf(dev, "%s requested ISA interrupt %lu\n", - device_get_nameunit(child), start); - } - flags |= RF_SHAREABLE; - return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child, - type, rid, start, end, count, flags)); - default: - return (NULL); - } - - res = rman_reserve_resource(rm, start, end, count, flags, child); - if (res == NULL) - return (NULL); - - rman_set_bustag(res, &bs_le_tag); - rman_set_bushandle(res, va + rman_get_start(res) - rm->rm_start); - return (res); -} - -static int -pci_ocp_release_resource(device_t dev, device_t child, int type, int rid, - struct resource *res) -{ - - return (rman_release_resource(res)); -} - -static int -pci_ocp_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) -{ - struct pci_ocp_softc *sc = device_get_softc(dev); - - switch (which) { - case PCIB_IVAR_BUS: - *result = sc->sc_busnr; - return (0); - case PCIB_IVAR_DOMAIN: - *result = device_get_unit(dev); - return (0); - } - return (ENOENT); -} - -static int -pci_ocp_write_ivar(device_t dev, device_t child, int which, uintptr_t value) -{ - struct pci_ocp_softc *sc = device_get_softc(dev); - - switch (which) { - case PCIB_IVAR_BUS: - sc->sc_busnr = value; - return (0); - } - return (ENOENT); -} diff --git a/sys/powerpc/powerpc/intr_machdep.c b/sys/powerpc/powerpc/intr_machdep.c index 697f4b0d324a..5a0ff8cadf5a 100644 --- a/sys/powerpc/powerpc/intr_machdep.c +++ b/sys/powerpc/powerpc/intr_machdep.c @@ -60,8 +60,6 @@ * $FreeBSD$ */ -#include "opt_platform.h" - #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> |