diff options
| author | Marcel Moolenaar <marcel@FreeBSD.org> | 2010-04-01 02:41:50 +0000 |
|---|---|---|
| committer | Marcel Moolenaar <marcel@FreeBSD.org> | 2010-04-01 02:41:50 +0000 |
| commit | 56a526f031776639bbc2fcfb263f6846e61daf15 (patch) | |
| tree | 6d60a88f9d2c705897f048b6d0d096ad2693cc4e /sys/powerpc | |
| parent | e55b9df7b370f3f1c243a960ce951733ab79312e (diff) | |
Notes
Diffstat (limited to 'sys/powerpc')
| -rw-r--r-- | sys/powerpc/booke/clock.c | 9 | ||||
| -rw-r--r-- | sys/powerpc/booke/interrupt.c | 2 | ||||
| -rw-r--r-- | sys/powerpc/booke/machdep.c | 16 | ||||
| -rw-r--r-- | sys/powerpc/booke/trap_subr.S | 1 | ||||
| -rw-r--r-- | sys/powerpc/mpc85xx/ocpbus.c | 15 | ||||
| -rw-r--r-- | sys/powerpc/mpc85xx/ocpbus.h | 2 | ||||
| -rw-r--r-- | sys/powerpc/mpc85xx/pci_ocp.c | 104 | ||||
| -rw-r--r-- | sys/powerpc/powerpc/cpu.c | 7 |
8 files changed, 90 insertions, 66 deletions
diff --git a/sys/powerpc/booke/clock.c b/sys/powerpc/booke/clock.c index 1d9043ebbed9..74f7d7490c21 100644 --- a/sys/powerpc/booke/clock.c +++ b/sys/powerpc/booke/clock.c @@ -197,15 +197,8 @@ DELAY(int n) { u_quad_t start, end, now; -#define USECS_IN_SEC 1000000ULL - - if (n > USECS_IN_SEC) { - printf("WARNING: %s(%d) called from %p", __func__, n, - __builtin_return_address(0)); - } - start = mftb(); - end = start + (u_quad_t)ticks_per_sec / (USECS_IN_SEC / n); + end = start + (u_quad_t)ticks_per_sec / (1000000ULL / n); do { now = mftb(); } while (now < end || (now > start && end < start)); diff --git a/sys/powerpc/booke/interrupt.c b/sys/powerpc/booke/interrupt.c index 2367bf94b33e..91ceeb7bf1d0 100644 --- a/sys/powerpc/booke/interrupt.c +++ b/sys/powerpc/booke/interrupt.c @@ -123,6 +123,7 @@ powerpc_decr_interrupt(struct trapframe *framep) decr_intr(framep); atomic_subtract_int(&td->td_intr_nesting_level, 1); critical_exit(); + framep->srr1 &= ~PSL_WE; } /* @@ -135,4 +136,5 @@ powerpc_extr_interrupt(struct trapframe *framep) critical_enter(); PIC_DISPATCH(pic, framep); critical_exit(); + framep->srr1 &= ~PSL_WE; } diff --git a/sys/powerpc/booke/machdep.c b/sys/powerpc/booke/machdep.c index d2e25e79ded9..e9a0099497cd 100644 --- a/sys/powerpc/booke/machdep.c +++ b/sys/powerpc/booke/machdep.c @@ -706,6 +706,7 @@ cpu_idle (int busy) register_t msr; msr = mfmsr(); + #ifdef INVARIANTS if ((msr & PSL_EE) != PSL_EE) { struct thread *td = curthread; @@ -713,19 +714,10 @@ cpu_idle (int busy) panic("ints disabled in idleproc!"); } #endif -#if 0 - /* - * Freescale E500 core RM section 6.4.1 - */ - msr = msr | PSL_WE; - __asm__(" msync;" - " mtmsr %0;" - " isync;" - "loop: b loop" : - /* no output */ : - "r" (msr)); -#endif + /* Freescale E500 core RM section 6.4.1. */ + msr = msr | PSL_WE; + __asm __volatile("msync; mtmsr %0; isync" :: "r" (msr)); } int diff --git a/sys/powerpc/booke/trap_subr.S b/sys/powerpc/booke/trap_subr.S index 2e67725dc4f4..b71f4bdb790e 100644 --- a/sys/powerpc/booke/trap_subr.S +++ b/sys/powerpc/booke/trap_subr.S @@ -441,6 +441,7 @@ INTERRUPT(int_instr_storage) INTERRUPT(int_external_input) STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1) FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_EXI) + addi %r3, %r1, 8 bl CNAME(powerpc_extr_interrupt) b trapexit diff --git a/sys/powerpc/mpc85xx/ocpbus.c b/sys/powerpc/mpc85xx/ocpbus.c index 2adec47b25b1..6c6515e4be66 100644 --- a/sys/powerpc/mpc85xx/ocpbus.c +++ b/sys/powerpc/mpc85xx/ocpbus.c @@ -152,6 +152,10 @@ ocpbus_write_law(int trgt, int type, u_long *startp, u_long *countp) addr = 0xA0000000; size = 0x10000000; break; + case OCP85XX_TGTIF_PCI3: + addr = 0xB0000000; + size = 0x10000000; + break; default: return (EINVAL); } @@ -170,6 +174,10 @@ ocpbus_write_law(int trgt, int type, u_long *startp, u_long *countp) addr = 0xfee20000; size = 0x00010000; break; + case OCP85XX_TGTIF_PCI3: + addr = 0xfee30000; + size = 0x00010000; + break; default: return (EINVAL); } @@ -188,7 +196,7 @@ static int ocpbus_probe(device_t dev) { - device_set_desc(dev, "On-Chip Peripherals bus"); + device_set_desc(dev, "Freescale on-chip peripherals bus"); return (BUS_PROBE_DEFAULT); } @@ -210,6 +218,7 @@ ocpbus_attach(device_t dev) 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); @@ -338,6 +347,10 @@ const struct ocp_resource mpc8555_resources[] = { 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}, diff --git a/sys/powerpc/mpc85xx/ocpbus.h b/sys/powerpc/mpc85xx/ocpbus.h index 6aa6de3b0631..fb715da5af13 100644 --- a/sys/powerpc/mpc85xx/ocpbus.h +++ b/sys/powerpc/mpc85xx/ocpbus.h @@ -50,6 +50,7 @@ #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 @@ -86,6 +87,7 @@ #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 diff --git a/sys/powerpc/mpc85xx/pci_ocp.c b/sys/powerpc/mpc85xx/pci_ocp.c index b98f62c7e905..cdcf986b940d 100644 --- a/sys/powerpc/mpc85xx/pci_ocp.c +++ b/sys/powerpc/mpc85xx/pci_ocp.c @@ -76,6 +76,9 @@ __FBSDID("$FreeBSD$"); #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 { @@ -94,7 +97,7 @@ struct pci_ocp_softc { int sc_rid; int sc_busnr; - int sc_pcie:1; + uint8_t sc_pcie_cap; /* Devices that need special attention. */ int sc_devfn_tundra; @@ -168,7 +171,7 @@ pci_ocp_cfgread(struct pci_ocp_softc *sc, u_int bus, u_int slot, u_int func, addr |= (slot & 0x1f) << 11; addr |= (func & 0x7) << 8; addr |= reg & 0xfc; - if (sc->sc_pcie) + if (sc->sc_pcie_cap) addr |= (reg & 0xf00) << 16; bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_CFG_ADDR, addr); @@ -206,7 +209,7 @@ pci_ocp_cfgwrite(struct pci_ocp_softc *sc, u_int bus, u_int slot, u_int func, addr |= (slot & 0x1f) << 11; addr |= (func & 0x7) << 8; addr |= reg & 0xfc; - if (sc->sc_pcie) + if (sc->sc_pcie_cap) addr |= (reg & 0xf00) << 16; bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_CFG_ADDR, addr); @@ -261,7 +264,7 @@ pci_ocp_maxslots(device_t dev) { struct pci_ocp_softc *sc = device_get_softc(dev); - return ((sc->sc_pcie) ? 0 : 30); + return ((sc->sc_pcie_cap) ? 0 : 31); } static uint32_t @@ -271,9 +274,21 @@ pci_ocp_read_config(device_t dev, u_int bus, u_int slot, u_int func, struct pci_ocp_softc *sc = device_get_softc(dev); u_int devfn; - if (bus == sc->sc_busnr && !sc->sc_pcie && slot < 10) + 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) @@ -287,7 +302,7 @@ pci_ocp_write_config(device_t dev, u_int bus, u_int slot, u_int func, { struct pci_ocp_softc *sc = device_get_softc(dev); - if (bus == sc->sc_busnr && !sc->sc_pcie && slot < 10) + if (bus == sc->sc_busnr && !sc->sc_pcie_cap && slot < 10) return; pci_ocp_cfgwrite(sc, bus, slot, func, reg, val, bytes); } @@ -297,11 +312,12 @@ pci_ocp_probe(device_t dev) { char buf[128]; struct pci_ocp_softc *sc; - const char *mpcid, *type; + 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); @@ -312,6 +328,7 @@ pci_ocp_probe(device_t dev) 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, @@ -327,48 +344,33 @@ pci_ocp_probe(device_t dev) 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_DEVICE, 2); - switch (cfgreg) { - case 0x000a: - mpcid = "8555E"; - break; - case 0x0012: - mpcid = "8548E"; - break; - case 0x0013: - mpcid = "8548"; - break; - /* - * Documentation from Freescale is incorrect. - * Use right values after documentation is corrected. - */ - case 0x0030: - mpcid = "8544E"; - break; - case 0x0031: - mpcid = "8544"; - break; - case 0x0032: - mpcid = "8544"; - break; - default: + + 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"; - cfgreg = pci_ocp_cfgread(sc, 0, 0, 0, PCIR_CAP_PTR, 1); - while (cfgreg != 0) { - cfgreg = pci_ocp_cfgread(sc, 0, 0, 0, cfgreg, 2); + 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 = 1; + sc->sc_pcie_cap = capptr; break; } - cfgreg = (cfgreg >> 8) & 0xff; + capptr = (cfgreg >> 8) & 0xff; } error = bus_get_resource(dev, SYS_RES_MEMORY, 1, &start, &size); @@ -376,7 +378,7 @@ pci_ocp_probe(device_t dev) goto out; snprintf(buf, sizeof(buf), - "Freescale MPC%s %s host controller", mpcid, type); + "Freescale on-chip %s host controller", type); device_set_desc_copy(dev, buf); error = BUS_PROBE_DEFAULT; @@ -491,7 +493,7 @@ pci_ocp_route_int(struct pci_ocp_softc *sc, u_int bus, u_int slot, u_int func, } static int -pci_ocp_init(struct pci_ocp_softc *sc, int bus, int maxslot) +pci_ocp_init(struct pci_ocp_softc *sc, int bus, int nslots) { int secbus, slot; int func, maxfunc; @@ -501,7 +503,7 @@ pci_ocp_init(struct pci_ocp_softc *sc, int bus, int maxslot) uint8_t intline, intpin; secbus = bus; - for (slot = 0; slot < maxslot; slot++) { + for (slot = 0; slot < nslots; slot++) { maxfunc = 0; for (func = 0; func <= maxfunc; func++) { hdrtype = pci_ocp_read_config(sc->sc_dev, bus, slot, @@ -598,7 +600,7 @@ pci_ocp_init(struct pci_ocp_softc *sc, int bus, int maxslot) PCIR_SUBBUS_1, 0xff, 1); secbus = pci_ocp_init(sc, secbus, - (subclass == PCIS_BRIDGE_PCI) ? 31 : 1); + (subclass == PCIS_BRIDGE_PCI) ? 32 : 1); pci_ocp_write_config(sc->sc_dev, bus, slot, func, PCIR_SUBBUS_1, secbus, 1); @@ -720,7 +722,7 @@ pci_ocp_attach(device_t dev) { struct pci_ocp_softc *sc; uint32_t cfgreg; - int error, maxslot; + int error, nslots; sc = device_get_softc(dev); sc->sc_dev = dev; @@ -753,8 +755,19 @@ pci_ocp_attach(device_t dev) sc->sc_devfn_tundra = -1; sc->sc_devfn_via_ide = -1; - maxslot = (sc->sc_pcie) ? 1 : 31; - pci_ocp_init(sc, sc->sc_busnr, maxslot); + /* + * 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)); @@ -783,6 +796,7 @@ pci_ocp_alloc_resource(device_t dev, device_t child, int type, int *rid, 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: diff --git a/sys/powerpc/powerpc/cpu.c b/sys/powerpc/powerpc/cpu.c index ebf36ee161b9..b49b1af5f620 100644 --- a/sys/powerpc/powerpc/cpu.c +++ b/sys/powerpc/powerpc/cpu.c @@ -433,6 +433,13 @@ cpu_e500_setup(int cpuid, uint16_t vers) register_t hid0; hid0 = mfspr(SPR_HID0); + + /* Programe power-management mode. */ + hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); + hid0 |= HID0_DOZE; + + mtspr(SPR_HID0, hid0); + printf("cpu%d: HID0 %b\n", cpuid, (int)hid0, HID0_E500_BITMASK); } |
