diff mbox series

[SCHEME,1] Add new idle device-tree format

Message ID 1527735105-23475-1-git-send-email-akshay.adiga@linux.vnet.ibm.com
State Superseded
Headers show
Series [SCHEME,1] Add new idle device-tree format | expand

Commit Message

Akshay Adiga May 31, 2018, 2:51 a.m. UTC
Add stop states under ibm,idle-states in addition to the current array
based device tree properties.

Drawback of the array based dt node is that versioning of idle states is
not possible. Future kernels will have capability to handle newer stop
sates, hence versioning will help kenrnel to selectively enable states
based on its capability. The new device tree node is extensible and
has a compatible string for each idle-state.

Linux kernel can now look at the version string and decide if it has the
ability to handle that idle state. Henceforth, if kernel does not know
about a version it will skip it.

Final output
    power-mgt {
        ...
	ibm,enabled-stop-levels = <0xec000000>;
	ibm,cpu-idle-state-psscr-mask = <0x0 0x3003ff 0x0 0x3003ff>;
	ibm,cpu-idle-state-latencies-ns = <0x3e8 0x7d0>;
	ibm,cpu-idle-state-psscr = <0x0 0x330 0x0 0x300330>;
	ibm,cpu-idle-state-flags = <0x100000 0x101000>;
	ibm,cpu-idle-state-residency-ns = <0x2710 0x4e20>;
	ibm,idle-states {
		phandle = <0xff>;
                stop4 {
			flags = <0x207000>;
			compatible = "ibm,cpuidle-state-v1";
			psscr-mask = <0x0 0x3003ff>;
			handle = <0x102>;
			latency-ns = <0x186a0>;
			residency-ns = <0x989680>;
			psscr = <0x0 0x300374>;
		 };

                ...
                stop11 {
			...
			compatible = "ibm,cpuoffline-state-v1";
			...

	   };
       };

Signed-off-by: Akshay Adiga <akshay.adiga@linux.vnet.ibm.com>
---
 hw/slw.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 82 insertions(+), 20 deletions(-)
diff mbox series

Patch

diff --git a/hw/slw.c b/hw/slw.c
index 49bcd83..23cc08e 100644
--- a/hw/slw.c
+++ b/hw/slw.c
@@ -414,8 +414,11 @@  static bool idle_prepare_core(struct proc_chip *chip, struct cpu_thread *c)
 
 /* Define device-tree fields */
 #define MAX_NAME_LEN	16
+#define MAX_VERSION_LEN	16
 struct cpu_idle_states {
 	char name[MAX_NAME_LEN];
+	char version[MAX_VERSION_LEN];
+	u32 dt_node_type;
 	u32 latency_ns;
 	u32 residency_ns;
 	/*
@@ -504,6 +507,8 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 	{
 		.name = "stop0_lite", /* Enter stop0 with no state loss */
 		.latency_ns = 1000,
+		.dt_node_type = 0,
+		.version = "ibm,cpuidle-state-v1",
 		.residency_ns = 10000,
 		.flags = 0*OPAL_PM_DEC_STOP \
 		       | 0*OPAL_PM_TIMEBASE_STOP  \
@@ -518,6 +523,8 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 	{
 		.name = "stop0",
 		.latency_ns = 2000,
+		.dt_node_type = 0,
+		.version = "ibm,cpuidle-state-v1",
 		.residency_ns = 20000,
 		.flags = 0*OPAL_PM_DEC_STOP \
 		       | 0*OPAL_PM_TIMEBASE_STOP  \
@@ -536,6 +543,8 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 
 	{
 		.name = "stop1",
+		.dt_node_type = 1,
+		.version = "ibm,cpuidle-state-v1",
 		.latency_ns = 5000,
 		.residency_ns = 50000,
 		.flags = 0*OPAL_PM_DEC_STOP \
@@ -557,6 +566,8 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 
 	{
 		.name = "stop2",
+		.dt_node_type = 1,
+		.version = "ibm,cpuidle-state-v1",
 		.latency_ns = 10000,
 		.residency_ns = 100000,
 		.flags = 0*OPAL_PM_DEC_STOP \
@@ -573,6 +584,8 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 		.pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
 	{
 		.name = "stop4",
+		.dt_node_type = 1,
+		.version = "ibm,cpuidle-state-v1",
 		.latency_ns = 100000,
 		.residency_ns = 10000000,
 		.flags = 0*OPAL_PM_DEC_STOP \
@@ -589,6 +602,8 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 		.pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
 	{
 		.name = "stop5",
+		.dt_node_type = 1,
+		.version = "ibm,cpuidle-state-v1",
 		.latency_ns = 200000,
 		.residency_ns = 20000000,
 		.flags = 0*OPAL_PM_DEC_STOP \
@@ -606,6 +621,8 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 
 	{
 		.name = "stop8",
+		.dt_node_type = 1,
+		.version = "ibm,cpuoffline-state-v1",
 		.latency_ns = 2000000,
 		.residency_ns = 20000000,
 		.flags = 1*OPAL_PM_DEC_STOP \
@@ -623,6 +640,8 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 
 	{
 		.name = "stop11",
+		.dt_node_type = 1,
+		.version = "ibm,cpuoffline-state-v1",
 		.latency_ns = 10000000,
 		.residency_ns = 100000000,
 		.flags = 1*OPAL_PM_DEC_STOP \
@@ -1011,34 +1030,77 @@  void add_cpu_idle_state_properties(void)
 				}
 			}
 		}
+		if ( states[i].dt_node_type == 0) {
+			prlog(PR_NOTICE, "SLW: Enabling: %s\n", states[i].name);
 
-		prlog(PR_NOTICE, "SLW: Enabling: %s\n", states[i].name);
+			/*
+			 * If a state is supported add each of its property
+			 * to its corresponding property buffer.
+			 */
+			strncpy(name_buf, states[i].name, MAX_NAME_LEN);
+			name_buf = name_buf + strlen(states[i].name) + 1;
 
-		/*
-		 * If a state is supported add each of its property
-		 * to its corresponding property buffer.
-		 */
-		strncpy(name_buf, states[i].name, MAX_NAME_LEN);
-		name_buf = name_buf + strlen(states[i].name) + 1;
+			*latency_ns_buf = cpu_to_fdt32(states[i].latency_ns);
+			latency_ns_buf++;
+
+			*residency_ns_buf = cpu_to_fdt32(states[i].residency_ns);
+			residency_ns_buf++;
+
+			*flags_buf = cpu_to_fdt32(states[i].flags);
+			flags_buf++;
+
+			*pm_ctrl_reg_val_buf = cpu_to_fdt64(states[i].pm_ctrl_reg_val);
+			pm_ctrl_reg_val_buf++;
 
-		*latency_ns_buf = cpu_to_fdt32(states[i].latency_ns);
-		latency_ns_buf++;
+			*pm_ctrl_reg_mask_buf = cpu_to_fdt64(states[i].pm_ctrl_reg_mask);
+			pm_ctrl_reg_mask_buf++;
 
-		*residency_ns_buf = cpu_to_fdt32(states[i].residency_ns);
-		residency_ns_buf++;
+			/* Increment buffer length trackers */
+			name_buf_len += strlen(states[i].name) + 1;
+			num_supported_idle_states++;
 
-		*flags_buf = cpu_to_fdt32(states[i].flags);
-		flags_buf++;
+		} else	if ( states[i].dt_node_type == 1 ) {
 
-		*pm_ctrl_reg_val_buf = cpu_to_fdt64(states[i].pm_ctrl_reg_val);
-		pm_ctrl_reg_val_buf++;
+			struct dt_node *parent_node , *dt_state_node;
+			char version_buf[MAX_VERSION_LEN];
+			u32 *lat_buf, *res_buf , *flg_buf;
+			u64 *psscr_buf , *psscr_mask_buf;
 
-		*pm_ctrl_reg_mask_buf = cpu_to_fdt64(states[i].pm_ctrl_reg_mask);
-		pm_ctrl_reg_mask_buf++;
+			lat_buf = malloc(sizeof(u32));
+			res_buf = malloc(sizeof(u32));
+			flg_buf = malloc(sizeof(u32));
+			psscr_buf = malloc(sizeof(u64));
+			psscr_mask_buf = malloc(sizeof(u64));
+			prlog(PR_NOTICE, "SLW: Enabling: %s in new format\n", states[i].name);
 
-		/* Increment buffer length trackers */
-		name_buf_len += strlen(states[i].name) + 1;
-		num_supported_idle_states++;
+			parent_node = dt_new_check(power_mgt,  "ibm,idle-states");
+			if (!parent_node) {
+				prlog(PR_ERR, "Error creating ibm,idle-states\n");
+			}
+			dt_state_node = dt_new_check(parent_node, states[i].name);
+			if (!dt_state_node) {
+				prlog(PR_ERR, "Error creating %s\n", states[i].name);
+			}
+			strncpy(version_buf,states[i].version, strlen(states[i].version)+1);
+			dt_add_property(dt_state_node, "compatible", version_buf , strlen(states[i].version)+1);
+
+			*lat_buf = cpu_to_fdt32(states[i].latency_ns);
+			dt_add_property(dt_state_node, "latency-ns",lat_buf, sizeof(u32));
+			*res_buf = cpu_to_fdt32(states[i].residency_ns);
+			dt_add_property(dt_state_node, "residency-ns",res_buf,sizeof(u32));
+			*flg_buf = cpu_to_fdt32(states[i].flags);
+			dt_add_property(dt_state_node, "flags",flg_buf,sizeof(u32));
+			*psscr_buf = cpu_to_fdt64(states[i].pm_ctrl_reg_val);
+			dt_add_property(dt_state_node, "psscr", psscr_buf , sizeof(u64));
+			*psscr_mask_buf = cpu_to_fdt64(states[i].pm_ctrl_reg_mask);
+			dt_add_property(dt_state_node, "psscr-mask", psscr_mask_buf ,sizeof(u64));
+			free(res_buf);
+			free(lat_buf);
+			free(flg_buf);
+			free(psscr_buf);
+			free(psscr_mask_buf);
+
+		}
 
 	}