soc/intel/common/block: Manage power state variable from common PMC block

This patch helps managing power state variables from within the
library. Adds migrate_power_state which migrates the chipset
power state variable, reads global power variable and adds it
in cbmem for future use. This also adds get_soc_power_state_values
function which returns the power state variable from cbmem or
global power state variable if cbmem is not populated yet.

Change-Id: If65341c1492e3a35a1a927100e0d893f923b9e68
Signed-off-by: Shaunak Saha <shaunak.saha@intel.com>
Reviewed-on: https://review.coreboot.org/21851
Reviewed-by: Furquan Shaikh <furquan@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
diff --git a/src/soc/intel/common/block/pmc/pmclib.c b/src/soc/intel/common/block/pmc/pmclib.c
index 78b43e44e..0afcdb2 100644
--- a/src/soc/intel/common/block/pmc/pmclib.c
+++ b/src/soc/intel/common/block/pmc/pmclib.c
@@ -13,6 +13,7 @@
  * GNU General Public License for more details.
  */
 
+#include <arch/early_variables.h>
 #include <arch/io.h>
 #include <cbmem.h>
 #include <console/console.h>
@@ -20,9 +21,42 @@
 #include <intelblocks/pmclib.h>
 #include <intelblocks/gpio.h>
 #include <soc/pm.h>
+#include <string.h>
 #include <timer.h>
 #include <vboot/vboot_common.h>
 
+static struct chipset_power_state power_state CAR_GLOBAL;
+
+struct chipset_power_state *pmc_get_power_state(void)
+{
+	struct chipset_power_state *ptr = NULL;
+
+	if (cbmem_possibly_online())
+		ptr = cbmem_find(CBMEM_ID_POWER_STATE);
+
+	/* cbmem is online but ptr is not populated yet */
+	if (ptr == NULL && !(ENV_RAMSTAGE || ENV_POSTCAR))
+		return car_get_var_ptr(&power_state);
+
+	return ptr;
+}
+
+static void migrate_power_state(int is_recovery)
+{
+	struct chipset_power_state *ps_cbmem;
+	struct chipset_power_state *ps_car;
+
+	ps_car = car_get_var_ptr(&power_state);
+	ps_cbmem = cbmem_add(CBMEM_ID_POWER_STATE, sizeof(*ps_cbmem));
+
+	if (ps_cbmem == NULL) {
+		printk(BIOS_DEBUG, "Not adding power state to cbmem!\n");
+		return;
+	}
+	memcpy(ps_cbmem, ps_car, sizeof(*ps_cbmem));
+}
+ROMSTAGE_CBMEM_INIT_HOOK(migrate_power_state)
+
 static void print_num_status_bits(int num_bits, uint32_t status,
 				  const char *const bit_names[])
 {
@@ -322,7 +356,7 @@
 	int i;
 	struct chipset_power_state *ps;
 
-	ps = cbmem_find(CBMEM_ID_POWER_STATE);
+	ps = pmc_get_power_state();
 	if (ps == NULL)
 		return;