1 Subject: [PATCH v12 14/14] cpufreq: qcom: Add support for krait based socs
2 Date: Tue, 14 Aug 2018 17:42:33 +0530
3 Message-Id: <1534248753-2440-15-git-send-email-sricharan@codeaurora.org>
4 X-Mailer: git-send-email 1.9.1
5 In-Reply-To: <1534248753-2440-1-git-send-email-sricharan@codeaurora.org>
6 References: <1534248753-2440-1-git-send-email-sricharan@codeaurora.org>
7 Sender: linux-kernel-owner@vger.kernel.org
9 List-ID: <linux-kernel.vger.kernel.org>
10 X-Mailing-List: linux-kernel@vger.kernel.org
12 In Certain QCOM SoCs like ipq8064, apq8064, msm8960, msm8974
13 that has KRAIT processors the voltage/current value of each OPP
14 varies based on the silicon variant in use.
16 The required OPP related data is determined based on
17 the efuse value. This is similar to the existing code for
18 kryo cores. So adding support for krait cores here.
20 Signed-off-by: Sricharan R <sricharan@codeaurora.org>
22 .../devicetree/bindings/opp/qcom-nvmem-cpufreq.txt | 3 +-
23 drivers/cpufreq/Kconfig.arm | 2 +-
24 drivers/cpufreq/cpufreq-dt-platdev.c | 5 +
25 drivers/cpufreq/qcom-cpufreq-nvmem.c | 151 +++++++++++++++++++--
26 4 files changed, 149 insertions(+), 12 deletions(-)
28 # diff --git a/Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt b/Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt
29 # index 6dcdfcd..7bc0f1a 100644
30 # --- a/Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt
31 # +++ b/Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt
32 # @@ -19,7 +19,8 @@ In 'cpus' nodes:
34 # In 'operating-points-v2' table:
35 # - compatible: Should be
36 # - - 'operating-points-v2-qcom-cpu' for apq8096 and msm8996.
37 # + - 'operating-points-v2-qcom-cpu' for apq8096, msm8996, msm8974,
38 # + apq8064, msm8960 and ipq8074.
39 # - nvmem-cells: A phandle pointing to a nvmem-cells node representing the
40 # efuse registers that has information about the
41 # speedbin that is used to select the right frequency/voltage
42 --- a/drivers/cpufreq/Kconfig.arm
43 +++ b/drivers/cpufreq/Kconfig.arm
44 @@ -134,7 +134,7 @@ config ARM_OMAP2PLUS_CPUFREQ
46 config ARM_QCOM_CPUFREQ_NVMEM
47 tristate "Qualcomm nvmem based CPUFreq"
49 + depends on ARCH_QCOM
50 depends on QCOM_QFPROM
53 --- a/drivers/cpufreq/cpufreq-dt-platdev.c
54 +++ b/drivers/cpufreq/cpufreq-dt-platdev.c
55 @@ -138,6 +138,11 @@ static const struct of_device_id blackli
56 { .compatible = "ti,am43", },
57 { .compatible = "ti,dra7", },
59 + { .compatible = "qcom,ipq8064", },
60 + { .compatible = "qcom,apq8064", },
61 + { .compatible = "qcom,msm8974", },
62 + { .compatible = "qcom,msm8960", },
67 --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
68 +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
69 @@ -49,12 +49,14 @@ struct qcom_cpufreq_drv;
70 struct qcom_cpufreq_match_data {
71 int (*get_version)(struct device *cpu_dev,
72 struct nvmem_cell *speedbin_nvmem,
74 struct qcom_cpufreq_drv *drv);
75 const char **genpd_names;
78 struct qcom_cpufreq_drv {
79 - struct opp_table **opp_tables;
80 + struct opp_table **opp_tables1;
81 + struct opp_table **opp_tables2;
82 struct opp_table **genpd_opp_tables;
84 const struct qcom_cpufreq_match_data *data;
85 @@ -62,6 +64,79 @@ struct qcom_cpufreq_drv {
87 static struct platform_device *cpufreq_dt_pdev, *cpufreq_pdev;
89 +static void get_krait_bin_format_a(int *speed, int *pvs, int *pvs_ver,
90 + struct nvmem_cell *pvs_nvmem, u8 *buf)
94 + pte_efuse = *((u32 *)buf);
96 + *speed = pte_efuse & 0xf;
98 + *speed = (pte_efuse >> 4) & 0xf;
100 + if (*speed == 0xf) {
102 + pr_warn("Speed bin: Defaulting to %d\n", *speed);
104 + pr_info("Speed bin: %d\n", *speed);
107 + *pvs = (pte_efuse >> 10) & 0x7;
109 + *pvs = (pte_efuse >> 13) & 0x7;
113 + pr_warn("PVS bin: Defaulting to %d\n", *pvs);
115 + pr_info("PVS bin: %d\n", *pvs);
119 +static void get_krait_bin_format_b(int *speed, int *pvs, int *pvs_ver,
120 + struct nvmem_cell *pvs_nvmem, u8 *buf)
122 + u32 pte_efuse, redundant_sel;
124 + pte_efuse = *((u32 *)buf);
125 + redundant_sel = (pte_efuse >> 24) & 0x7;
126 + *speed = pte_efuse & 0x7;
128 + /* 4 bits of PVS are in efuse register bits 31, 8-6. */
129 + *pvs = ((pte_efuse >> 28) & 0x8) | ((pte_efuse >> 6) & 0x7);
130 + *pvs_ver = (pte_efuse >> 4) & 0x3;
132 + switch (redundant_sel) {
134 + *speed = (pte_efuse >> 27) & 0xf;
137 + *pvs = (pte_efuse >> 27) & 0xf;
141 + /* Check SPEED_BIN_BLOW_STATUS */
142 + if (pte_efuse & BIT(3)) {
143 + pr_info("Speed bin: %d\n", *speed);
145 + pr_warn("Speed bin not set. Defaulting to 0!\n");
149 + /* Check PVS_BLOW_STATUS */
150 + pte_efuse = *(((u32 *)buf) + 4);
151 + pte_efuse &= BIT(21);
153 + pr_info("PVS bin: %d\n", *pvs);
155 + pr_warn("PVS bin not set. Defaulting to 0!\n");
159 + pr_info("PVS version: %d\n", *pvs_ver);
162 static enum _msm8996_version qcom_cpufreq_get_msm_id(void)
165 @@ -93,11 +168,13 @@ static enum _msm8996_version qcom_cpufre
167 static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev,
168 struct nvmem_cell *speedbin_nvmem,
170 struct qcom_cpufreq_drv *drv)
174 enum _msm8996_version msm8996_version;
177 msm8996_version = qcom_cpufreq_get_msm_id();
178 if (NUM_OF_MSM8996_VERSIONS == msm8996_version) {
179 @@ -125,10 +202,44 @@ static int qcom_cpufreq_kryo_name_versio
183 +static int qcom_cpufreq_krait_name_version(struct device *cpu_dev,
184 + struct nvmem_cell *speedbin_nvmem,
186 + struct qcom_cpufreq_drv *drv)
188 + int speed = 0, pvs = 0, pvs_ver = 0;
192 + speedbin = nvmem_cell_read(speedbin_nvmem, &len);
194 + get_krait_bin_format_a(&speed, &pvs, &pvs_ver,
195 + speedbin_nvmem, speedbin);
196 + } else if (len == 8) {
197 + get_krait_bin_format_b(&speed, &pvs, &pvs_ver,
198 + speedbin_nvmem, speedbin);
200 + dev_err(cpu_dev, "Unable to read nvmem data. Defaulting to 0!\n");
204 + snprintf(*pvs_name, sizeof("speedXX-pvsXX-vXX"), "speed%d-pvs%d-v%d",
205 + speed, pvs, pvs_ver);
207 + drv->versions = (1 << speed);
213 static const struct qcom_cpufreq_match_data match_data_kryo = {
214 .get_version = qcom_cpufreq_kryo_name_version,
217 +static const struct qcom_cpufreq_match_data match_data_krait = {
218 + .get_version = qcom_cpufreq_krait_name_version,
221 static const char *qcs404_genpd_names[] = { "cpr", NULL };
223 static const struct qcom_cpufreq_match_data match_data_qcs404 = {
224 @@ -141,6 +252,7 @@ static int qcom_cpufreq_probe(struct pla
225 struct nvmem_cell *speedbin_nvmem;
226 struct device_node *np;
227 struct device *cpu_dev;
228 + char *pvs_name = "speedXX-pvsXX-vXX";
230 const struct of_device_id *match;
232 @@ -153,7 +265,7 @@ static int qcom_cpufreq_probe(struct pla
236 - ret = of_device_is_compatible(np, "operating-points-v2-kryo-cpu");
237 + ret = of_device_is_compatible(np, "operating-points-v2-qcom-cpu");
241 @@ -181,7 +293,7 @@ static int qcom_cpufreq_probe(struct pla
245 - ret = drv->data->get_version(cpu_dev, speedbin_nvmem, drv);
246 + ret = drv->data->get_version(cpu_dev, speedbin_nvmem, &pvs_name, drv);
248 nvmem_cell_put(speedbin_nvmem);
250 @@ -190,12 +302,18 @@ static int qcom_cpufreq_probe(struct pla
254 - drv->opp_tables = kcalloc(num_possible_cpus(), sizeof(*drv->opp_tables),
255 + drv->opp_tables1 = kcalloc(num_possible_cpus(), sizeof(*drv->opp_tables1),
257 - if (!drv->opp_tables) {
258 + if (!drv->opp_tables1) {
262 + drv->opp_tables2 = kcalloc(num_possible_cpus(), sizeof(*drv->opp_tables2),
264 + if (!drv->opp_tables2) {
269 drv->genpd_opp_tables = kcalloc(num_possible_cpus(),
270 sizeof(*drv->genpd_opp_tables),
271 @@ -213,11 +331,22 @@ static int qcom_cpufreq_probe(struct pla
274 if (drv->data->get_version) {
275 - drv->opp_tables[cpu] =
276 - dev_pm_opp_set_supported_hw(cpu_dev,
279 + drv->opp_tables1[cpu] = dev_pm_opp_set_prop_name(cpu_dev,
281 + if (IS_ERR(drv->opp_tables1[cpu])) {
282 + ret = PTR_ERR(drv->opp_tables1[cpu]);
283 + dev_err(cpu_dev, "Failed to add OPP name %s\n",
289 + drv->opp_tables2[cpu] = dev_pm_opp_set_supported_hw(cpu_dev,
291 - if (IS_ERR(drv->opp_tables[cpu])) {
292 - ret = PTR_ERR(drv->opp_tables[cpu]);
293 + if (IS_ERR(drv->opp_tables2[cpu])) {
294 + ret = PTR_ERR(drv->opp_tables2[cpu]);
296 "Failed to set supported hardware\n");
298 @@ -259,11 +388,18 @@ free_genpd_opp:
299 kfree(drv->genpd_opp_tables);
301 for_each_possible_cpu(cpu) {
302 - if (IS_ERR_OR_NULL(drv->opp_tables[cpu]))
303 + if (IS_ERR_OR_NULL(drv->opp_tables1[cpu]))
305 + dev_pm_opp_put_prop_name(drv->opp_tables1[cpu]);
307 + for_each_possible_cpu(cpu) {
308 + if (IS_ERR_OR_NULL(drv->opp_tables2[cpu]))
310 - dev_pm_opp_put_supported_hw(drv->opp_tables[cpu]);
311 + dev_pm_opp_put_supported_hw(drv->opp_tables2[cpu]);
313 - kfree(drv->opp_tables);
314 + kfree(drv->opp_tables2);
316 + kfree(drv->opp_tables1);
320 @@ -278,13 +414,16 @@ static int qcom_cpufreq_remove(struct pl
321 platform_device_unregister(cpufreq_dt_pdev);
323 for_each_possible_cpu(cpu) {
324 - if (drv->opp_tables[cpu])
325 - dev_pm_opp_put_supported_hw(drv->opp_tables[cpu]);
326 + if (drv->opp_tables1[cpu])
327 + dev_pm_opp_put_supported_hw(drv->opp_tables1[cpu]);
328 + if (drv->opp_tables2[cpu])
329 + dev_pm_opp_put_supported_hw(drv->opp_tables2[cpu]);
330 if (drv->genpd_opp_tables[cpu])
331 dev_pm_opp_detach_genpd(drv->genpd_opp_tables[cpu]);
334 - kfree(drv->opp_tables);
335 + kfree(drv->opp_tables1);
336 + kfree(drv->opp_tables2);
337 kfree(drv->genpd_opp_tables);
340 @@ -303,6 +442,10 @@ static const struct of_device_id qcom_cp
341 { .compatible = "qcom,apq8096", .data = &match_data_kryo },
342 { .compatible = "qcom,msm8996", .data = &match_data_kryo },
343 { .compatible = "qcom,qcs404", .data = &match_data_qcs404 },
344 + { .compatible = "qcom,ipq8064", .data = &match_data_krait },
345 + { .compatible = "qcom,apq8064", .data = &match_data_krait },
346 + { .compatible = "qcom,msm8974", .data = &match_data_krait },
347 + { .compatible = "qcom,msm8960", .data = &match_data_krait },