qualcommax: add ipq60xx support
[openwrt/staging/jow.git] / target / linux / qualcommax / patches-6.1 / 0038-v6.7-cpufreq-qcom-nvmem-add-support-for-IPQ6018.patch
1 From 47e161a7873b0891f4e01a69a839f6161d816ea8 Mon Sep 17 00:00:00 2001
2 From: Robert Marko <robimarko@gmail.com>
3 Date: Wed, 25 Oct 2023 14:57:57 +0530
4 Subject: [PATCH] cpufreq: qcom-nvmem: add support for IPQ6018
5
6 IPQ6018 SoC series comes in multiple SKU-s, and not all of them support
7 high frequency OPP points.
8
9 SoC itself does however have a single bit in QFPROM to indicate the CPU
10 speed-bin.
11 That bit is used to indicate frequency limit of 1.5GHz, but that alone is
12 not enough as IPQ6000 only goes up to 1.2GHz, but SMEM ID can be used to
13 limit it further.
14
15 IPQ6018 compatible is blacklisted from DT platdev as the cpufreq device
16 will get created by NVMEM CPUFreq driver.
17
18 Signed-off-by: Robert Marko <robimarko@gmail.com>
19 [ Viresh: Fixed rebase conflict. ]
20 Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
21 ---
22 drivers/cpufreq/cpufreq-dt-platdev.c | 1 +
23 drivers/cpufreq/qcom-cpufreq-nvmem.c | 58 ++++++++++++++++++++++++++++++++++++
24 2 files changed, 59 insertions(+)
25
26 --- a/drivers/cpufreq/cpufreq-dt-platdev.c
27 +++ b/drivers/cpufreq/cpufreq-dt-platdev.c
28 @@ -163,6 +163,7 @@ static const struct of_device_id blockli
29 { .compatible = "ti,dra7", },
30 { .compatible = "ti,omap3", },
31
32 + { .compatible = "qcom,ipq6018", },
33 { .compatible = "qcom,ipq8064", },
34 { .compatible = "qcom,ipq8074", },
35 { .compatible = "qcom,apq8064", },
36 --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
37 +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
38 @@ -36,6 +36,8 @@ enum ipq8074_versions {
39 IPQ8074_ACORN_VERSION,
40 };
41
42 +#define IPQ6000_VERSION BIT(2)
43 +
44 struct qcom_cpufreq_drv;
45
46 struct qcom_cpufreq_match_data {
47 @@ -209,6 +211,57 @@ len_error:
48 return ret;
49 }
50
51 +static int qcom_cpufreq_ipq6018_name_version(struct device *cpu_dev,
52 + struct nvmem_cell *speedbin_nvmem,
53 + char **pvs_name,
54 + struct qcom_cpufreq_drv *drv)
55 +{
56 + u32 msm_id;
57 + int ret;
58 + u8 *speedbin;
59 + *pvs_name = NULL;
60 +
61 + ret = qcom_smem_get_soc_id(&msm_id);
62 + if (ret)
63 + return ret;
64 +
65 + speedbin = nvmem_cell_read(speedbin_nvmem, NULL);
66 + if (IS_ERR(speedbin))
67 + return PTR_ERR(speedbin);
68 +
69 + switch (msm_id) {
70 + case QCOM_ID_IPQ6005:
71 + case QCOM_ID_IPQ6010:
72 + case QCOM_ID_IPQ6018:
73 + case QCOM_ID_IPQ6028:
74 + /* Fuse Value Freq BIT to set
75 + * ---------------------------------
76 + * 2’b0 No Limit BIT(0)
77 + * 2’b1 1.5 GHz BIT(1)
78 + */
79 + drv->versions = 1 << (unsigned int)(*speedbin);
80 + break;
81 + case QCOM_ID_IPQ6000:
82 + /*
83 + * IPQ6018 family only has one bit to advertise the CPU
84 + * speed-bin, but that is not enough for IPQ6000 which
85 + * is only rated up to 1.2GHz.
86 + * So for IPQ6000 manually set BIT(2) based on SMEM ID.
87 + */
88 + drv->versions = IPQ6000_VERSION;
89 + break;
90 + default:
91 + dev_err(cpu_dev,
92 + "SoC ID %u is not part of IPQ6018 family, limiting to 1.2GHz!\n",
93 + msm_id);
94 + drv->versions = IPQ6000_VERSION;
95 + break;
96 + }
97 +
98 + kfree(speedbin);
99 + return 0;
100 +}
101 +
102 static int qcom_cpufreq_ipq8074_name_version(struct device *cpu_dev,
103 struct nvmem_cell *speedbin_nvmem,
104 char **pvs_name,
105 @@ -265,6 +318,10 @@ static const struct qcom_cpufreq_match_d
106 .get_version = qcom_cpufreq_ipq8074_name_version,
107 };
108
109 +static const struct qcom_cpufreq_match_data match_data_ipq6018 = {
110 + .get_version = qcom_cpufreq_ipq6018_name_version,
111 +};
112 +
113 static int qcom_cpufreq_probe(struct platform_device *pdev)
114 {
115 struct qcom_cpufreq_drv *drv;
116 @@ -409,6 +466,7 @@ static const struct of_device_id qcom_cp
117 { .compatible = "qcom,apq8096", .data = &match_data_kryo },
118 { .compatible = "qcom,msm8996", .data = &match_data_kryo },
119 { .compatible = "qcom,qcs404", .data = &match_data_qcs404 },
120 + { .compatible = "qcom,ipq6018", .data = &match_data_ipq6018 },
121 { .compatible = "qcom,ipq8064", .data = &match_data_krait },
122 { .compatible = "qcom,ipq8074", .data = &match_data_ipq8074 },
123 { .compatible = "qcom,apq8064", .data = &match_data_krait },