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.

>  
>  void
> @@ -100,3 +128,31 @@ psci_powerdown(void)
>       if (sc->callfn)
>               (*sc->callfn)(SYSTEM_OFF, 0, 0, 0);
>  }

Shouldn't all of these have a sc->sc_cpu_suspend != 0 type test as well
to avoid calls with a function id of 0?

You could skip the earlier != 0 tests and do them in these functions.

> +
> +int
> +psci_cpu_suspend()
> +{
> +     struct psci_softc *sc = psci_sc;
> +     if (sc->callfn)
> +             return (*sc->callfn)(sc->sc_cpu_suspend, 0, 0, 0);
> +     return -1;
> +}
> +
> +int
> +psci_cpu_off()
> +{
> +     struct psci_softc *sc = psci_sc;
> +     if (sc->callfn)
> +             return (*sc->callfn)(sc->sc_cpu_off, 0, 0, 0);
> +     return -1;
> +
> +}
> +
> +int
> +psci_cpu_on(uint64_t mpidr, uint64_t pc)
> +{
> +     struct psci_softc *sc = psci_sc;
> +     if (sc->callfn)
> +             return (*sc->callfn)(sc->sc_cpu_on, mpidr, pc, 0);
> +     return -1;
> +}
> 
> Dale Rahn                             dr...@dalerahn.com
> 

Reply via email to