soc/intel/cannonlake: Add support for C state and P state

This patch adds the C state and P state configurations for
cannonlake soc.

TEST = Boot and test the CPU states for all the cores are
       present in "powertop" tool output.

Change-Id: I4ba156354f87646b25d0f9114ebf0583eedf72df
Signed-off-by: Shaunak Saha <shaunak.saha@intel.com>
Reviewed-on: https://review.coreboot.org/21891
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
diff --git a/src/soc/intel/cannonlake/acpi.c b/src/soc/intel/cannonlake/acpi.c
index 4e2a027..9dcaa33 100644
--- a/src/soc/intel/cannonlake/acpi.c
+++ b/src/soc/intel/cannonlake/acpi.c
@@ -33,9 +33,143 @@
 #include <soc/nvs.h>
 #include <soc/pci_devs.h>
 #include <soc/pm.h>
+#include <string.h>
 #include <vendorcode/google/chromeos/gnvs.h>
 #include <wrdd.h>
 
+/*
+ * List of supported C-states in this processor.
+ */
+enum {
+	C_STATE_C0,		/* 0 */
+	C_STATE_C1,		/* 1 */
+	C_STATE_C1E,		/* 2 */
+	C_STATE_C6_SHORT_LAT,	/* 3 */
+	C_STATE_C6_LONG_LAT,	/* 4 */
+	C_STATE_C7_SHORT_LAT,	/* 5 */
+	C_STATE_C7_LONG_LAT,	/* 6 */
+	C_STATE_C7S_SHORT_LAT,	/* 7 */
+	C_STATE_C7S_LONG_LAT,	/* 8 */
+	C_STATE_C8,		/* 9 */
+	C_STATE_C9,		/* 10 */
+	C_STATE_C10,		/* 11 */
+	NUM_C_STATES
+};
+
+#define MWAIT_RES(state, sub_state)				\
+	{							\
+		.addrl = (((state) << 4) | (sub_state)),	\
+		.space_id = ACPI_ADDRESS_SPACE_FIXED,		\
+		.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,	\
+		.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,	\
+		.access_size = ACPI_FFIXEDHW_FLAG_HW_COORD,	\
+	}
+
+static const acpi_cstate_t cstate_map[NUM_C_STATES] = {
+	[C_STATE_C0] = {},
+	[C_STATE_C1] = {
+		.latency = 0,
+		.power = C1_POWER,
+		.resource = MWAIT_RES(0, 0),
+	},
+	[C_STATE_C1E] = {
+		.latency = 0,
+		.power = C1_POWER,
+		.resource = MWAIT_RES(0, 1),
+	},
+	[C_STATE_C6_SHORT_LAT] = {
+		.latency = C_STATE_LATENCY_FROM_LAT_REG(0),
+		.power = C6_POWER,
+		.resource = MWAIT_RES(2, 0),
+	},
+	[C_STATE_C6_LONG_LAT] = {
+		.latency = C_STATE_LATENCY_FROM_LAT_REG(0),
+		.power = C6_POWER,
+		.resource = MWAIT_RES(2, 1),
+	},
+	[C_STATE_C7_SHORT_LAT] = {
+		.latency = C_STATE_LATENCY_FROM_LAT_REG(0),
+		.power = C7_POWER,
+		.resource = MWAIT_RES(3, 0),
+	},
+	[C_STATE_C7_LONG_LAT] = {
+		.latency = C_STATE_LATENCY_FROM_LAT_REG(0),
+		.power = C7_POWER,
+		.resource = MWAIT_RES(3, 1),
+	},
+	[C_STATE_C7S_SHORT_LAT] = {
+		.latency = C_STATE_LATENCY_FROM_LAT_REG(0),
+		.power = C7_POWER,
+		.resource = MWAIT_RES(3, 2),
+	},
+	[C_STATE_C7S_LONG_LAT] = {
+		.latency = C_STATE_LATENCY_FROM_LAT_REG(0),
+		.power = C7_POWER,
+		.resource = MWAIT_RES(3, 3),
+	},
+	[C_STATE_C8] = {
+		.latency = C_STATE_LATENCY_FROM_LAT_REG(0),
+		.power = C8_POWER,
+		.resource = MWAIT_RES(4, 0),
+	},
+	[C_STATE_C9] = {
+		.latency = C_STATE_LATENCY_FROM_LAT_REG(0),
+		.power = C9_POWER,
+		.resource = MWAIT_RES(5, 0),
+	},
+	[C_STATE_C10] = {
+		.latency = C_STATE_LATENCY_FROM_LAT_REG(0),
+		.power = C10_POWER,
+		.resource = MWAIT_RES(6, 0),
+	},
+};
+
+static int cstate_set_s0ix[] = {
+	C_STATE_C1E,
+	C_STATE_C6_LONG_LAT,
+	C_STATE_C7S_LONG_LAT
+};
+
+static int cstate_set_non_s0ix[] = {
+	C_STATE_C1E,
+	C_STATE_C7S_LONG_LAT,
+	C_STATE_C10
+};
+
+acpi_cstate_t *soc_get_cstate_map(size_t *entries)
+{
+	static acpi_cstate_t map[MAX(ARRAY_SIZE(cstate_set_s0ix),
+				ARRAY_SIZE(cstate_set_non_s0ix))];
+	int *set;
+	int i;
+	device_t dev = SA_DEV_ROOT;
+	config_t *config = dev->chip_info;
+	int is_s0ix_enable = config->s0ix_enable;
+
+	if (is_s0ix_enable) {
+		*entries = ARRAY_SIZE(cstate_set_s0ix);
+		set = cstate_set_s0ix;
+	} else {
+		*entries = ARRAY_SIZE(cstate_set_non_s0ix);
+		set = cstate_set_non_s0ix;
+	}
+
+	for (i = 0; i < *entries; i++) {
+		memcpy(&map[i], &cstate_map[set[i]], sizeof(acpi_cstate_t));
+		map[i].ctype = i + 1;
+	}
+	return map;
+}
+
+void soc_power_states_generation(int core_id, int cores_per_package)
+{
+	device_t dev = SA_DEV_ROOT;
+	config_t *config = dev->chip_info;
+	if (config->eist_enable)
+		/* Generate P-state tables */
+		generate_p_state_entries(core_id, cores_per_package);
+}
+
 void soc_fill_fadt(acpi_fadt_t *fadt)
 {
 	const uint16_t pmbase = ACPI_BASE_ADDRESS;