From 9a2edf01984b05d659501916e8ac4c5faebe15e5 Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Sat, 21 Dec 2013 04:31:54 +0000 Subject: [PATCH] Add suspend/resume state saving for OpenPIC on PowerMac. It's likely this can be used on the others (cpcht and psim), but that has not been tested. --- sys/powerpc/include/openpicreg.h | 1 + sys/powerpc/include/openpicvar.h | 19 ++++++++++ sys/powerpc/ofw/openpic_ofw.c | 3 ++ sys/powerpc/powermac/cpcht.c | 1 + sys/powerpc/powerpc/openpic.c | 61 ++++++++++++++++++++++++++++++++ sys/powerpc/psim/openpic_iobus.c | 1 + 6 files changed, 86 insertions(+) diff --git a/sys/powerpc/include/openpicreg.h b/sys/powerpc/include/openpicreg.h index 525e66feca4..3c4382421ac 100644 --- a/sys/powerpc/include/openpicreg.h +++ b/sys/powerpc/include/openpicreg.h @@ -99,6 +99,7 @@ */ /* interrupt vector/priority reg */ +#define OPENPIC_SRC_VECTOR_COUNT 64 #ifndef OPENPIC_SRC_VECTOR #define OPENPIC_SRC_VECTOR(irq) (0x10000 + (irq) * 0x20) #endif diff --git a/sys/powerpc/include/openpicvar.h b/sys/powerpc/include/openpicvar.h index 605dc0f8daa..2ff68b71075 100644 --- a/sys/powerpc/include/openpicvar.h +++ b/sys/powerpc/include/openpicvar.h @@ -32,6 +32,14 @@ #define OPENPIC_IRQMAX 256 /* h/w allows more */ +/* Names match the macros in openpicreg.h. */ +struct openpic_timer { + uint32_t tcnt; + uint32_t tbase; + uint32_t tvec; + uint32_t tdst; +}; + struct openpic_softc { device_t sc_dev; struct resource *sc_memr; @@ -45,6 +53,14 @@ struct openpic_softc { u_int sc_ncpu; u_int sc_nirq; int sc_psim; + + /* Saved states. */ + uint32_t sc_saved_config; + uint32_t sc_saved_ipis[4]; + uint32_t sc_saved_prios[4]; + struct openpic_timer sc_saved_timers[OPENPIC_TIMERS]; + uint32_t sc_saved_vectors[OPENPIC_SRC_VECTOR_COUNT]; + }; extern devclass_t openpic_devclass; @@ -66,4 +82,7 @@ void openpic_ipi(device_t, u_int); void openpic_mask(device_t, u_int); void openpic_unmask(device_t, u_int); +int openpic_suspend(device_t dev); +int openpic_resume(device_t dev); + #endif /* _POWERPC_OPENPICVAR_H_ */ diff --git a/sys/powerpc/ofw/openpic_ofw.c b/sys/powerpc/ofw/openpic_ofw.c index 0e85ddaa2ae..2ddfb61b561 100644 --- a/sys/powerpc/ofw/openpic_ofw.c +++ b/sys/powerpc/ofw/openpic_ofw.c @@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include "pic_if.h" @@ -68,6 +69,8 @@ static device_method_t openpic_ofw_methods[] = { /* Device interface */ DEVMETHOD(device_probe, openpic_ofw_probe), DEVMETHOD(device_attach, openpic_ofw_attach), + DEVMETHOD(device_suspend, openpic_suspend), + DEVMETHOD(device_resume, openpic_resume), /* PIC interface */ DEVMETHOD(pic_bind, openpic_bind), diff --git a/sys/powerpc/powermac/cpcht.c b/sys/powerpc/powermac/cpcht.c index 03d07e9b8ee..5e5b7b6e774 100644 --- a/sys/powerpc/powermac/cpcht.c +++ b/sys/powerpc/powermac/cpcht.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/powerpc/powerpc/openpic.c b/sys/powerpc/powerpc/openpic.c index 347dc3fb4ee..cc642a5f348 100644 --- a/sys/powerpc/powerpc/openpic.c +++ b/sys/powerpc/powerpc/openpic.c @@ -380,3 +380,64 @@ openpic_unmask(device_t dev, u_int irq) openpic_write(sc, OPENPIC_IPI_VECTOR(0), x); } } + +int +openpic_suspend(device_t dev) +{ + struct openpic_softc *sc; + int i; + + sc = device_get_softc(dev); + + sc->sc_saved_config = bus_read_4(sc->sc_memr, OPENPIC_CONFIG); + for (i = 0; i < 4; i++) { + sc->sc_saved_ipis[i] = bus_read_4(sc->sc_memr, OPENPIC_IPI_VECTOR(i)); + } + + for (i = 0; i < 4; i++) { + sc->sc_saved_prios[i] = bus_read_4(sc->sc_memr, OPENPIC_PCPU_TPR(i)); + } + + for (i = 0; i < OPENPIC_TIMERS; i++) { + sc->sc_saved_timers[i].tcnt = bus_read_4(sc->sc_memr, OPENPIC_TCNT(i)); + sc->sc_saved_timers[i].tbase = bus_read_4(sc->sc_memr, OPENPIC_TBASE(i)); + sc->sc_saved_timers[i].tvec = bus_read_4(sc->sc_memr, OPENPIC_TVEC(i)); + sc->sc_saved_timers[i].tdst = bus_read_4(sc->sc_memr, OPENPIC_TDST(i)); + } + + for (i = 0; i < OPENPIC_SRC_VECTOR_COUNT; i++) + sc->sc_saved_vectors[i] = + bus_read_4(sc->sc_memr, OPENPIC_SRC_VECTOR(i)) & ~OPENPIC_ACTIVITY; + + return (0); +} + +int +openpic_resume(device_t dev) +{ + struct openpic_softc *sc; + int i; + + sc = device_get_softc(dev); + + sc->sc_saved_config = bus_read_4(sc->sc_memr, OPENPIC_CONFIG); + for (i = 0; i < 4; i++) { + bus_write_4(sc->sc_memr, OPENPIC_IPI_VECTOR(i), sc->sc_saved_ipis[i]); + } + + for (i = 0; i < 4; i++) { + bus_write_4(sc->sc_memr, OPENPIC_PCPU_TPR(i), sc->sc_saved_prios[i]); + } + + for (i = 0; i < OPENPIC_TIMERS; i++) { + bus_write_4(sc->sc_memr, OPENPIC_TCNT(i), sc->sc_saved_timers[i].tcnt); + bus_write_4(sc->sc_memr, OPENPIC_TBASE(i), sc->sc_saved_timers[i].tbase); + bus_write_4(sc->sc_memr, OPENPIC_TVEC(i), sc->sc_saved_timers[i].tvec); + bus_write_4(sc->sc_memr, OPENPIC_TDST(i), sc->sc_saved_timers[i].tdst); + } + + for (i = 0; i < OPENPIC_SRC_VECTOR_COUNT; i++) + bus_write_4(sc->sc_memr, OPENPIC_SRC_VECTOR(i), sc->sc_saved_vectors[i]); + + return (0); +} diff --git a/sys/powerpc/psim/openpic_iobus.c b/sys/powerpc/psim/openpic_iobus.c index f2e7cdb7c9c..9a70b4e813e 100644 --- a/sys/powerpc/psim/openpic_iobus.c +++ b/sys/powerpc/psim/openpic_iobus.c @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include