On Thu, Feb 23, 2017 at 01:03:57PM +1100, Jonathan Gray wrote: > On Wed, Feb 22, 2017 at 06:45:52PM -0500, Dale Rahn wrote: > > Add psci 2.0 features to spin up/down/suspend processors. > > > > This change uses extern weak symbols to determine if the platform supports > > the cpu_on/cpu_off/cpu_suspend features. If available, it saves the fdt > > provided argument values. > > > > Some PSCI calls will return an int status, so the callfn has been updated > > to return that status (eg cpu_on fail) > > > > diff --git a/sys/dev/fdt/psci.c b/sys/dev/fdt/psci.c > > index fceafd0e9ba..3177ff06beb 100644 > > --- a/sys/dev/fdt/psci.c > > +++ b/sys/dev/fdt/psci.c > > @@ -29,12 +29,19 @@ > > extern void (*cpuresetfn)(void); > > extern void (*powerdownfn)(void); > > > > +extern int (*cpu_suspend_fn)(void) __attribute__((weak)) ; > > +extern int (*cpu_off_fn)(void) __attribute__((weak)) ; > > +extern int (*cpu_on_fn)(uint64_t, uint64_t) __attribute__((weak)) ; > > + > > #define SYSTEM_OFF 0x84000008 > > #define SYSTEM_RESET 0x84000009 > > > > struct psci_softc { > > struct device sc_dev; > > - void (*callfn)(uint32_t, uint32_t, uint32_t, > > uint32_t); > > + int (*callfn)(uint32_t, uint32_t, uint32_t, > > uint32_t); > > + int sc_cpu_on; > > + int sc_cpu_off; > > + int sc_cpu_suspend; > > }; > > spacing is out here > > > > > struct psci_softc *psci_sc; > > @@ -43,9 +50,12 @@ int psci_match(struct device *, void *, void *); > > void psci_attach(struct device *, struct device *, void *); > > void psci_reset(void); > > void psci_powerdown(void); > > +int psci_cpu_suspend(void); > > +int psci_cpu_off(void); > > +int psci_cpu_on(uint64_t, uint64_t); > > > > -extern void hvc_call(uint32_t, uint32_t, uint32_t, uint32_t); > > -extern void smc_call(uint32_t, uint32_t, uint32_t, uint32_t); > > +extern int hvc_call(uint32_t, uint32_t, uint32_t, uint32_t); > > +extern int smc_call(uint32_t, uint32_t, uint32_t, uint32_t); > > > > struct cfattach psci_ca = { > > sizeof(struct psci_softc), psci_match, psci_attach > > @@ -83,6 +93,24 @@ psci_attach(struct device *parent, struct device *self, > > void *aux) > > psci_sc = sc; > > cpuresetfn = psci_reset; > > powerdownfn = psci_powerdown; > > + > > + if (&cpu_suspend_fn != NULL) { > > + sc->sc_cpu_suspend = OF_getpropint(faa->fa_node, "cpu_suspend", > > 0); > > + if (sc->sc_cpu_suspend != 0) > > + cpu_suspend_fn = psci_cpu_suspend; > > + } > > + > > + if (&cpu_on_fn != NULL) { > > + sc->sc_cpu_on = OF_getpropint(faa->fa_node, "cpu_on", 0); > > + if (sc->sc_cpu_on != 0) > > + cpu_on_fn = psci_cpu_on; > > + } > > + > > + if (&cpu_off_fn != NULL) { > > + sc->sc_cpu_off = OF_getpropint(faa->fa_node, "cpu_off", 0); > > + if (sc->sc_cpu_off != 0) > > + cpu_off_fn = psci_cpu_off; > > + } > > } > > Can these nodes be relied on as being present? > > Outside of qemu -M virt > > psci { > migrate = <0x84000005>; > cpu_on = <0x84000003>; > cpu_off = <0x84000002>; > cpu_suspend = <0x84000001>; > method = "hvc"; > compatible = "arm,psci-0.2", "arm,psci"; > }; > > I can only find > > arm/boot/dts/artpec6.dtsi: cpu_on = <0x84000003>; > arm/boot/dts/ecx-common.dtsi: cpu_on = <0x84000006>; > arm/boot/dts/keystone.dtsi: cpu_on = <0x84000003>; > arm/boot/dts/xenvm-4.2.dts: cpu_on = <2>; > arm64/boot/dts/al/alpine-v2.dtsi: cpu_on = <0x84000003>; > arm64/boot/dts/exynos/exynos5433.dtsi: cpu_on = <0xC4000003>; > arm64/boot/dts/lg/lg1312.dtsi: cpu_on = <0x84000003>; > arm64/boot/dts/lg/lg1313.dtsi: cpu_on = <0x84000003>; > arm64/boot/dts/mediatek/mt8173.dtsi: cpu_on = <0x84000003>; > arm64/boot/dts/sprd/sc9836.dtsi: cpu_on = > <0xc4000003>; > > 0x84000003 is SMC32, 0xC4000003 is SMC64 and there is actually > a different calling convention for these... > > The existing SYSTEM_OFF and SYSTEM_RESET uses are fine as they are just > a 32 bit function id with no arguments. But these new functions > need to care about the arguments. > > There is also PSCI_FEATURES in PSCI 1.0 that tests if function ids are > supported. >
Updated diff, this has changed a bit since the psci driver has changed. diff --git a/sys/dev/fdt/psci.c b/sys/dev/fdt/psci.c index b24613a275c..2ba500ea718 100644 --- a/sys/dev/fdt/psci.c +++ b/sys/dev/fdt/psci.c @@ -29,14 +29,18 @@ extern void (*cpuresetfn)(void); extern void (*powerdownfn)(void); +extern int (*cpu_on_fn)(uint64_t, uint64_t) __attribute__((weak)) ; + #define SYSTEM_OFF 0x84000008 #define SYSTEM_RESET 0x84000009 +#define SYSTEM_CPU_ON64 0xC4000003 struct psci_softc { struct device sc_dev; - void (*callfn)(uint32_t, uint32_t, uint32_t, uint32_t); + int (*callfn)(uint32_t, uint32_t, uint32_t, uint32_t); int sc_system_off; int sc_system_reset; + int sc_system_on; }; struct psci_softc *psci_sc; @@ -45,9 +49,10 @@ int psci_match(struct device *, void *, void *); void psci_attach(struct device *, struct device *, void *); void psci_reset(void); void psci_powerdown(void); +int psci_cpu_on(uint64_t, uint64_t); -extern void hvc_call(uint32_t, uint32_t, uint32_t, uint32_t); -extern void smc_call(uint32_t, uint32_t, uint32_t, uint32_t); +extern int hvc_call(uint32_t, uint32_t, uint32_t, uint32_t); +extern int smc_call(uint32_t, uint32_t, uint32_t, uint32_t); struct cfattach psci_ca = { sizeof(struct psci_softc), psci_match, psci_attach @@ -90,11 +95,13 @@ psci_attach(struct device *parent, struct device *self, void *aux) OF_is_compatible(faa->fa_node, "arm,psci-1.0")) { sc->sc_system_off = SYSTEM_OFF; sc->sc_system_reset = SYSTEM_RESET; + sc->sc_system_on = OF_getpropint(faa->fa_node, "cpu_on", 0); } else if (OF_is_compatible(faa->fa_node, "arm,psci")) { sc->sc_system_off = OF_getpropint(faa->fa_node, "system_off", 0); sc->sc_system_reset = OF_getpropint(faa->fa_node, "system_reset", 0); + sc->sc_system_on = OF_getpropint(faa->fa_node, "cpu_on", 0); } printf("\n"); @@ -104,6 +111,10 @@ psci_attach(struct device *parent, struct device *self, void *aux) powerdownfn = psci_powerdown; if (sc->sc_system_reset != 0) cpuresetfn = psci_reset; + + if ((&cpu_on_fn != NULL) && (sc->sc_system_on == SYSTEM_CPU_ON64)) { + cpu_on_fn = psci_cpu_on; + } } void @@ -121,3 +132,12 @@ psci_powerdown(void) if (sc->callfn) (*sc->callfn)(sc->sc_system_off, 0, 0, 0); } + +int +psci_cpu_on(uint64_t mpidr, uint64_t pc) +{ + struct psci_softc *sc = psci_sc; + if (sc->callfn) + return (*sc->callfn)(sc->sc_system_on, mpidr, pc, 0); + return -1; +} Dale Rahn dr...@dalerahn.com