CSS: Implement support for NODE_HW_STATE
authorJeenu Viswambharan <[email protected]>
Thu, 4 Aug 2016 08:43:15 +0000 (09:43 +0100)
committerJeenu Viswambharan <[email protected]>
Thu, 15 Sep 2016 10:18:48 +0000 (11:18 +0100)
This patch implements CSS platform hook to support NODE_HW_STATE PSCI
API. The platform hook queries SCP to obtain CSS power state. Power
states returned by SCP are then converted to expected PSCI return codes.

Juno's PSCI operation structure is modified to use the CSS
implementation.

Change-Id: I4a5edac0e5895dd77b51398cbd78f934831dafc0

include/plat/arm/css/common/css_def.h
include/plat/arm/css/common/css_pm.h
plat/arm/board/juno/juno_pm.c
plat/arm/css/common/css_pm.c

index 636daf294a567aea5cf8fae2c376c74694c6555c..173de1b4d32f9cfbb8d7e96a6887e1b13ee5c6ce 100644 (file)
 /* Trusted mailbox base address common to all CSS */
 #define PLAT_ARM_TRUSTED_MAILBOX_BASE  ARM_TRUSTED_SRAM_BASE
 
+/*
+ * Parsing of CPU and Cluster states, as returned by 'Get CSS Power State' SCP
+ * command
+ */
+#define CSS_CLUSTER_PWR_STATE_ON       0
+#define CSS_CLUSTER_PWR_STATE_OFF      3
+
+#define CSS_CPU_PWR_STATE_ON           1
+#define CSS_CPU_PWR_STATE_OFF          0
+#define CSS_CPU_PWR_STATE(state, n)    (((state) >> (n)) & 1)
 
 #endif /* __CSS_DEF_H__ */
index ea6a5d251fd9a99822a78c13fd45f7f2f6b6ff87..4a6ca816162317c5328e895611962d280703acd5 100644 (file)
@@ -45,5 +45,6 @@ void __dead2 css_system_off(void);
 void __dead2 css_system_reset(void);
 void css_cpu_standby(plat_local_state_t cpu_state);
 void css_get_sys_suspend_power_state(psci_power_state_t *req_state);
+int css_node_hw_state(u_register_t mpidr, unsigned int power_level);
 
 #endif /* __CSS_PM_H__ */
index cbf994a4713f0ff10a6b33b4c892520c245ab905..c355d94dfbbb4da985d6d2251c92f7c374537967 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -88,5 +88,6 @@ const plat_psci_ops_t plat_arm_psci_pm_ops = {
        .validate_power_state           = juno_validate_power_state,
        .validate_ns_entrypoint         = arm_validate_ns_entrypoint,
        .get_sys_suspend_power_state    = css_get_sys_suspend_power_state,
-       .translate_power_state_by_mpidr = juno_translate_power_state_by_mpidr
+       .translate_power_state_by_mpidr = juno_translate_power_state_by_mpidr,
+       .get_node_hw_state              = css_node_hw_state
 };
index 801d937578567e2823a42f583cb96da6e99eb1fb..7607f617762dcdb7be5fdb74a8d057b2551a39b5 100644 (file)
@@ -298,6 +298,43 @@ void css_get_sys_suspend_power_state(psci_power_state_t *req_state)
                req_state->pwr_domain_state[i] = ARM_LOCAL_STATE_OFF;
 }
 
+/*******************************************************************************
+ * Handler to query CPU/cluster power states from SCP
+ ******************************************************************************/
+int css_node_hw_state(u_register_t mpidr, unsigned int power_level)
+{
+       int rc, element;
+       unsigned int cpu_state, cluster_state;
+
+       /*
+        * The format of 'power_level' is implementation-defined, but 0 must
+        * mean a CPU. We also allow 1 to denote the cluster
+        */
+       if (power_level != ARM_PWR_LVL0 && power_level != ARM_PWR_LVL1)
+               return PSCI_E_INVALID_PARAMS;
+
+       /* Query SCP */
+       rc = scpi_get_css_power_state(mpidr, &cpu_state, &cluster_state);
+       if (rc != 0)
+               return PSCI_E_INVALID_PARAMS;
+
+       /* Map power states of CPU and cluster to expected PSCI return codes */
+       if (power_level == ARM_PWR_LVL0) {
+               /*
+                * The CPU state returned by SCP is an 8-bit bit mask
+                * corresponding to each CPU in the cluster
+                */
+               element = mpidr & MPIDR_AFFLVL_MASK;
+               return CSS_CPU_PWR_STATE(cpu_state, element) ==
+                       CSS_CPU_PWR_STATE_ON ? HW_ON : HW_OFF;
+       } else {
+               assert(cluster_state == CSS_CLUSTER_PWR_STATE_ON ||
+                               cluster_state == CSS_CLUSTER_PWR_STATE_OFF);
+               return cluster_state == CSS_CLUSTER_PWR_STATE_ON ? HW_ON :
+                       HW_OFF;
+       }
+}
+
 /*******************************************************************************
  * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
  * platform will take care of registering the handlers with PSCI.
@@ -312,5 +349,6 @@ const plat_psci_ops_t plat_arm_psci_pm_ops = {
        .system_off             = css_system_off,
        .system_reset           = css_system_reset,
        .validate_power_state   = arm_validate_power_state,
-       .validate_ns_entrypoint = arm_validate_ns_entrypoint
+       .validate_ns_entrypoint = arm_validate_ns_entrypoint,
+       .get_node_hw_state      = css_node_hw_state
 };