Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 657d7175 authored by Mahesh Sivasubramanian's avatar Mahesh Sivasubramanian Committed by Matt Wagantall
Browse files

qcom: msm-pm: Partial goods support for sleep status driver



On certains devices, some of the CPUs within the apps subsystem are not
functional and might be removed from the CPU possible map. To handle this
dynamic list of CPUs, sleep driver shouldn't make any assumptions with
regards to the logical mapping of the CPU.

Remove the assumption on how physical CPUs are mapped onto logical CPUs and
populate create a reference of sleep status driver in the corresponding
CPU phandles. When the sleep status driver is probed, it would probe
iterating the list of possble CPUs.

CRs-fixed: 756327
Change-Id: I3afe8c9afd26000ab08f0e0c2703f2ce9e15f374
Signed-off-by: default avatarMahesh Sivasubramanian <msivasub@codeaurora.org>
Signed-off-by: default avatarMurali Nalajala <mnalajal@codeaurora.org>
parent 086cc877
Loading
Loading
Loading
Loading
+33 −10
Original line number Diff line number Diff line
@@ -6,21 +6,44 @@ sleep status device before CPU_DEAD notifications are sent out. Some hardware
devices require that the offlined core is power collapsed before turning off
the resources that are used by the offlined core.

The required properties of sleep status device are:

The required properties of core sleep status node are:
- compatible: qcom,cpu-sleep-status

The required properties of sleep status node are:
- reg: physical address of the sleep status register for the cpus
- qcom,cpu-sleep-status-mask - The bit mask within the status register that
	indicates the Core's sleep state.

Optional properties:
- qcom,cpu-alias-addr - On MSM chipset, the each cores registers are at a
	fixed offset each other.

Example:
	qcom,cpu-sleep-status@f9088008 {
	qcom,cpu-sleep-status {
		compatible = "qcom,cpu-sleep-status";
		reg = <0xf9088008 0x4>;
		qcom,cpu-alias-addr = <0x10000>;
		qcom,sleep-status-mask= <0x80000>;
	};

	cpus {
		#address-cells = <2>;
		#size-cells = <0>;

		CPU0: cpu@0 {
			device_type = "cpu";
			compatible = "qcom,kryo";

			qcom,sleep-status = <&cpu0_slp_sts>;
		};

		CPU1: cpu@1 {
			device_type = "cpu";
			compatible = "qcom,kryo";

			qcom,sleep-status = <&cpu1_slp_sts>;
		};
	};

	cpu0_slp_sts: cpu-sleep-status@9981058 {
		reg = <0x9981058 0x100>;
		qcom,sleep-status-mask = <0xc00000>;
	};

	cpu1_slp_sts: cpu-sleep-status@9991058 {
		reg = <0x9991058 0x100>;
		qcom,sleep-status-mask = <0xc00000>;
	}
+1 −6
Original line number Diff line number Diff line
@@ -524,13 +524,8 @@
			 <&clock_cpu clk_cbf_hf_mux>;
	};

	qcom,cpu-sleep-status@9981058{
	qcom,cpu-sleep-status {
		compatible = "qcom,cpu-sleep-status";
		reg = <0x9981058 0x100>,
		<0x9991058 0x100>,
		<0x99B1058 0x100>,
		<0x99C1058 0x100>;
		qcom,sleep-status-mask= <0xC00000>;
	};

	qcom,mpm@681b8 {
+24 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@
			qcom,cpuss-pm = <&cpuss_pm>;
			qcom,cpuss-csr = <&cpuss_csr>;
			qcom,acc = <&acc0>;
			qcom,sleep-status = <&cpu0_slp_sts>;
			next-level-cache = <&L2_0>;
			L2_0: l2-cache {
			      compatible = "arm,arch-cache";
@@ -64,6 +65,7 @@
			reg = <0x0 0x1>;
			enable-method = "qcom,msm8996-acc";
			qcom,acc = <&acc1>;
			qcom,sleep-status = <&cpu1_slp_sts>;
			next-level-cache = <&L2_0>;
		};

@@ -73,6 +75,7 @@
			reg = <0x0 0x100>;
			enable-method = "qcom,msm8996-acc";
			qcom,acc = <&acc2>;
			qcom,sleep-status = <&cpu2_slp_sts>;
			next-level-cache = <&L2_1>;
			L2_1: l2-cache {
			      compatible = "arm,arch-cache";
@@ -86,6 +89,7 @@
			compatible = "qcom,kryo";
			reg = <0x0 0x101>;
			enable-method = "qcom,msm8996-acc";
			qcom,sleep-status = <&cpu3_slp_sts>;
			qcom,acc = <&acc3>;
			next-level-cache = <&L2_1>;
		};
@@ -2994,6 +2998,26 @@
			status = "disabled";
		};
	};

	cpu0_slp_sts: cpu-sleep-status@9981058 {
		reg = <0x9981058 0x100>;
		qcom,sleep-status-mask = <0xc00000>;
	};

	cpu1_slp_sts: cpu-sleep-status@9991058 {
		reg = <0x9991058 0x100>;
		qcom,sleep-status-mask = <0xc00000>;
	};

	cpu2_slp_sts: cpu-sleep-status@99b1058 {
		reg = <0x99b1058 0x100>;
		qcom,sleep-status-mask = <0xc00000>;
	};

	cpu3_slp_sts: cpu-sleep-status@99c1058 {
		reg = <0x99c1058 0x100>;
		qcom,sleep-status-mask = <0xc00000>;
	};
};

&gdsc_venus {
+24 −49
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/of_address.h>
#include <linux/msm-bus.h>
#include <linux/uaccess.h>
#include <linux/dma-mapping.h>
@@ -558,11 +559,10 @@ snoc_cl_probe_done:

static int msm_cpu_status_probe(struct platform_device *pdev)
{
	struct msm_pm_sleep_status_data *pdata;
	char *key;
	u32 cpu;
	int rc;

	if (!pdev)
	if (!pdev | !pdev->dev.of_node)
		return -EFAULT;

	msm_pm_slp_sts = devm_kzalloc(&pdev->dev,
@@ -572,59 +572,34 @@ static int msm_cpu_status_probe(struct platform_device *pdev)
	if (!msm_pm_slp_sts)
		return -ENOMEM;

	if (pdev->dev.of_node) {
		struct resource *res;
		u32 offset;
		int rc;
		u32 mask;
		bool offset_available = true;

		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
		if (!res)
			return -ENODEV;

		key = "qcom,cpu-alias-addr";
		rc = of_property_read_u32(pdev->dev.of_node, key, &offset);
	for_each_possible_cpu(cpu) {
		struct device_node *cpun, *node;
		char *key;

		if (rc)
			offset_available = false;
		cpun = of_get_cpu_node(cpu, NULL);

		key = "qcom,sleep-status-mask";
		rc = of_property_read_u32(pdev->dev.of_node, key, &mask);
		if (!cpun) {
			__WARN();
			continue;
		}

		if (rc)
		node = of_parse_phandle(cpun, "qcom,sleep-status", 0);
		if (!node)
			return -ENODEV;

		for_each_possible_cpu(cpu) {
			phys_addr_t base_c;

			if (offset_available)
				base_c = res->start + cpu * offset;
			else {
				res = platform_get_resource(pdev,
							IORESOURCE_MEM, cpu);
				if (!res)
		msm_pm_slp_sts[cpu].base_addr = of_iomap(node, 0);
		if (!msm_pm_slp_sts[cpu].base_addr) {
			pr_err("%s: Can't find base addr\n", __func__);
			return -ENODEV;
				base_c = res->start;
			}

			msm_pm_slp_sts[cpu].base_addr =
				devm_ioremap(&pdev->dev, base_c,
						resource_size(res));
			msm_pm_slp_sts[cpu].mask = mask;

			if (!msm_pm_slp_sts[cpu].base_addr)
				return -ENOMEM;
		}
	} else {
		pdata = pdev->dev.platform_data;
		if (!pdev->dev.platform_data)
			return -EINVAL;

		for_each_possible_cpu(cpu) {
			msm_pm_slp_sts[cpu].base_addr =
				pdata->base_addr + cpu * pdata->cpu_offset;
			msm_pm_slp_sts[cpu].mask = pdata->mask;
		key = "qcom,sleep-status-mask";
		rc = of_property_read_u32(node, key, &msm_pm_slp_sts[cpu].mask);
		if (rc) {
			pr_err("%s: Can't find %s property\n", __func__, key);
			iounmap(msm_pm_slp_sts[cpu].base_addr);
			return rc;
		}
	}

+0 −1
Original line number Diff line number Diff line
@@ -59,7 +59,6 @@ struct msm_pm_time_params {

struct msm_pm_sleep_status_data {
	void *base_addr;
	uint32_t cpu_offset;
	uint32_t mask;
};