Rework PSCI so it only searches for the call function once.
This is in preperation for supporting newer smccc functions that also use the same call method. Reviewed by: manu Differential Revision: https://reviews.freebsd.org/D15745
This commit is contained in:
parent
3489c7d4d3
commit
97d4f019bc
@ -74,7 +74,6 @@ __FBSDID("$FreeBSD$");
|
||||
struct psci_softc {
|
||||
device_t dev;
|
||||
|
||||
psci_callfn_t psci_call;
|
||||
uint32_t psci_fnids[PSCI_FN_MAX];
|
||||
};
|
||||
|
||||
@ -107,6 +106,41 @@ static struct ofw_compat_data compat_data[] = {
|
||||
static int psci_attach(device_t, psci_initfn_t);
|
||||
static void psci_shutdown(void *, int);
|
||||
|
||||
static int psci_find_callfn(psci_callfn_t *);
|
||||
static int psci_def_callfn(register_t, register_t, register_t, register_t);
|
||||
|
||||
static psci_callfn_t psci_callfn = psci_def_callfn;
|
||||
|
||||
static inline int
|
||||
psci_call(register_t a, register_t b, register_t c, register_t d)
|
||||
{
|
||||
|
||||
return (psci_callfn(a, b, c, d));
|
||||
}
|
||||
|
||||
static void
|
||||
psci_init(void *dummy)
|
||||
{
|
||||
psci_callfn_t new_callfn;
|
||||
|
||||
if (psci_find_callfn(&new_callfn) != PSCI_RETVAL_SUCCESS) {
|
||||
printf("No PSCI/SMCCC call function found");
|
||||
return;
|
||||
}
|
||||
|
||||
psci_callfn = new_callfn;
|
||||
}
|
||||
/* This needs to be before cpu_mp at SI_SUB_CPU, SI_ORDER_THIRD */
|
||||
SYSINIT(psci_start, SI_SUB_CPU, SI_ORDER_FIRST, psci_init, NULL);
|
||||
|
||||
static int
|
||||
psci_def_callfn(register_t a __unused, register_t b __unused,
|
||||
register_t c __unused, register_t d __unused)
|
||||
{
|
||||
|
||||
panic("No PSCI/SMCCC call function set");
|
||||
}
|
||||
|
||||
#ifdef FDT
|
||||
static int psci_fdt_probe(device_t dev);
|
||||
static int psci_fdt_attach(device_t dev);
|
||||
@ -169,17 +203,12 @@ psci_fdt_probe(device_t dev)
|
||||
static int
|
||||
psci_fdt_attach(device_t dev)
|
||||
{
|
||||
struct psci_softc *sc = device_get_softc(dev);
|
||||
const struct ofw_compat_data *ocd;
|
||||
psci_initfn_t psci_init;
|
||||
phandle_t node;
|
||||
|
||||
ocd = ofw_bus_search_compatible(dev, compat_data);
|
||||
psci_init = (psci_initfn_t)ocd->ocd_data;
|
||||
|
||||
node = ofw_bus_get_node(dev);
|
||||
sc->psci_call = psci_fdt_get_callfn(node);
|
||||
|
||||
return (psci_attach(dev, psci_init));
|
||||
}
|
||||
#endif
|
||||
@ -280,14 +309,6 @@ psci_acpi_probe(device_t dev)
|
||||
static int
|
||||
psci_acpi_attach(device_t dev)
|
||||
{
|
||||
struct psci_softc *sc = device_get_softc(dev);
|
||||
uintptr_t flags;
|
||||
|
||||
flags = (uintptr_t)acpi_get_private(dev);
|
||||
if ((flags & ACPI_FADT_PSCI_USE_HVC) != 0)
|
||||
sc->psci_call = psci_hvc_despatch;
|
||||
else
|
||||
sc->psci_call = psci_smc_despatch;
|
||||
|
||||
return (psci_attach(dev, psci_v0_2_init));
|
||||
}
|
||||
@ -301,9 +322,6 @@ psci_attach(device_t dev, psci_initfn_t psci_init)
|
||||
if (psci_softc != NULL)
|
||||
return (ENXIO);
|
||||
|
||||
if (sc->psci_call == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
KASSERT(psci_init != NULL, ("PSCI init function cannot be NULL"));
|
||||
if (psci_init(dev))
|
||||
return (ENXIO);
|
||||
@ -321,7 +339,7 @@ _psci_get_version(struct psci_softc *sc)
|
||||
/* PSCI version wasn't supported in v0.1. */
|
||||
fnid = sc->psci_fnids[PSCI_FN_VERSION];
|
||||
if (fnid)
|
||||
return (sc->psci_call(fnid, 0, 0, 0));
|
||||
return (psci_call(fnid, 0, 0, 0));
|
||||
|
||||
return (PSCI_RETVAL_NOT_SUPPORTED);
|
||||
}
|
||||
@ -368,40 +386,44 @@ psci_acpi_callfn(psci_callfn_t *callfn)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
psci_find_callfn(psci_callfn_t *callfn)
|
||||
{
|
||||
int error;
|
||||
|
||||
*callfn = NULL;
|
||||
#ifdef FDT
|
||||
if (USE_FDT) {
|
||||
error = psci_fdt_callfn(callfn);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
}
|
||||
#endif
|
||||
#ifdef DEV_ACPI
|
||||
if (*callfn == NULL && USE_ACPI) {
|
||||
error = psci_acpi_callfn(callfn);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (*callfn == NULL)
|
||||
return (PSCI_MISSING);
|
||||
|
||||
return (PSCI_RETVAL_SUCCESS);
|
||||
}
|
||||
|
||||
int
|
||||
psci_cpu_on(unsigned long cpu, unsigned long entry, unsigned long context_id)
|
||||
{
|
||||
psci_callfn_t callfn;
|
||||
uint32_t fnid;
|
||||
int error;
|
||||
|
||||
if (psci_softc == NULL) {
|
||||
fnid = PSCI_FNID_CPU_ON;
|
||||
callfn = NULL;
|
||||
#ifdef FDT
|
||||
if (USE_FDT) {
|
||||
error = psci_fdt_callfn(&callfn);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
}
|
||||
#endif
|
||||
#ifdef DEV_ACPI
|
||||
if (callfn == NULL && USE_ACPI) {
|
||||
error = psci_acpi_callfn(&callfn);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (callfn == NULL)
|
||||
return (PSCI_MISSING);
|
||||
} else {
|
||||
callfn = psci_softc->psci_call;
|
||||
fnid = PSCI_FNID_CPU_ON;
|
||||
if (psci_softc != NULL)
|
||||
fnid = psci_softc->psci_fnids[PSCI_FN_CPU_ON];
|
||||
}
|
||||
|
||||
/* PSCI v0.1 and v0.2 both support cpu_on. */
|
||||
return (callfn(fnid, cpu, entry, context_id));
|
||||
return (psci_call(fnid, cpu, entry, context_id));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -419,7 +441,7 @@ psci_shutdown(void *xsc, int howto)
|
||||
fn = psci_softc->psci_fnids[PSCI_FN_SYSTEM_RESET];
|
||||
|
||||
if (fn)
|
||||
psci_softc->psci_call(fn, 0, 0, 0);
|
||||
psci_call(fn, 0, 0, 0);
|
||||
|
||||
/* System reset and off do not return. */
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user