Merge branch 'pm-cpufreq'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 30 Mar 2020 12:46:27 +0000 (14:46 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 30 Mar 2020 12:46:27 +0000 (14:46 +0200)
* pm-cpufreq:
  cpufreq: intel_pstate: Simplify intel_pstate_cpu_init()
  cpufreq: qcom: Add support for krait based socs
  cpufreq: imx6q-cpufreq: Improve the logic of -EPROBE_DEFER handling
  cpufreq: Use scnprintf() for avoiding potential buffer overflow
  Documentation: intel_pstate: update links for references
  cpufreq: intel_pstate: Consolidate policy verification
  cpufreq: dt: Allow platform specific intermediate callbacks
  cpufreq: imx-cpufreq-dt: Correct i.MX8MP's market segment fuse location
  cpufreq: imx6q: read OCOTP through nvmem for imx6q
  cpufreq: imx6q: fix error handling
  cpufreq: imx-cpufreq-dt: Add "cpu-supply" property check
  cpufreq: ti-cpufreq: Add support for OPP_PLUS
  cpufreq: imx6q: Fixes unwanted cpu overclocking on i.MX6ULL

12 files changed:
Documentation/admin-guide/pm/intel_pstate.rst
Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt
drivers/cpufreq/Kconfig.arm
drivers/cpufreq/cpufreq-dt-platdev.c
drivers/cpufreq/cpufreq-dt.c
drivers/cpufreq/cpufreq-dt.h
drivers/cpufreq/cpufreq_stats.c
drivers/cpufreq/imx-cpufreq-dt.c
drivers/cpufreq/imx6q-cpufreq.c
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/qcom-cpufreq-nvmem.c
drivers/cpufreq/ti-cpufreq.c

index 67e414e..ad392f3 100644 (file)
@@ -734,10 +734,10 @@ References
 ==========
 
 .. [1] Kristen Accardi, *Balancing Power and Performance in the Linux Kernel*,
-       http://events.linuxfoundation.org/sites/events/files/slides/LinuxConEurope_2015.pdf
+       https://events.static.linuxfound.org/sites/events/files/slides/LinuxConEurope_2015.pdf
 
 .. [2] *Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 3: System Programming Guide*,
-       http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-system-programming-manual-325384.html
+       https://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-system-programming-manual-325384.html
 
 .. [3] *Advanced Configuration and Power Interface Specification*,
        https://uefi.org/sites/default/files/resources/ACPI_6_3_final_Jan30.pdf
index 4751029..64f0741 100644 (file)
@@ -19,7 +19,8 @@ In 'cpu' nodes:
 
 In 'operating-points-v2' table:
 - compatible: Should be
-       - 'operating-points-v2-kryo-cpu' for apq8096 and msm8996.
+       - 'operating-points-v2-kryo-cpu' for apq8096, msm8996, msm8974,
+                                            apq8064, ipq8064, msm8960 and ipq8074.
 
 Optional properties:
 --------------------
index 3858d86..15c1a12 100644 (file)
@@ -128,7 +128,7 @@ config ARM_OMAP2PLUS_CPUFREQ
 
 config ARM_QCOM_CPUFREQ_NVMEM
        tristate "Qualcomm nvmem based CPUFreq"
-       depends on ARM64
+       depends on ARCH_QCOM
        depends on QCOM_QFPROM
        depends on QCOM_SMEM
        select PM_OPP
index f2ae9cd..cb9db16 100644 (file)
@@ -141,6 +141,11 @@ static const struct of_device_id blacklist[] __initconst = {
        { .compatible = "ti,dra7", },
        { .compatible = "ti,omap3", },
 
+       { .compatible = "qcom,ipq8064", },
+       { .compatible = "qcom,apq8064", },
+       { .compatible = "qcom,msm8974", },
+       { .compatible = "qcom,msm8960", },
+
        { }
 };
 
index d2b5f06..26fe8df 100644 (file)
@@ -363,6 +363,10 @@ static int dt_cpufreq_probe(struct platform_device *pdev)
                dt_cpufreq_driver.resume = data->resume;
                if (data->suspend)
                        dt_cpufreq_driver.suspend = data->suspend;
+               if (data->get_intermediate) {
+                       dt_cpufreq_driver.target_intermediate = data->target_intermediate;
+                       dt_cpufreq_driver.get_intermediate = data->get_intermediate;
+               }
        }
 
        ret = cpufreq_register_driver(&dt_cpufreq_driver);
index a5a45b5..28c8af7 100644 (file)
@@ -14,6 +14,10 @@ struct cpufreq_policy;
 struct cpufreq_dt_platform_data {
        bool have_governor_per_policy;
 
+       unsigned int    (*get_intermediate)(struct cpufreq_policy *policy,
+                                           unsigned int index);
+       int             (*target_intermediate)(struct cpufreq_policy *policy,
+                                              unsigned int index);
        int (*suspend)(struct cpufreq_policy *policy);
        int (*resume)(struct cpufreq_policy *policy);
 };
index f9bcf0f..94d959a 100644 (file)
@@ -90,35 +90,35 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
        if (policy->fast_switch_enabled)
                return 0;
 
-       len += snprintf(buf + len, PAGE_SIZE - len, "   From  :    To\n");
-       len += snprintf(buf + len, PAGE_SIZE - len, "         : ");
+       len += scnprintf(buf + len, PAGE_SIZE - len, "   From  :    To\n");
+       len += scnprintf(buf + len, PAGE_SIZE - len, "         : ");
        for (i = 0; i < stats->state_num; i++) {
                if (len >= PAGE_SIZE)
                        break;
-               len += snprintf(buf + len, PAGE_SIZE - len, "%9u ",
+               len += scnprintf(buf + len, PAGE_SIZE - len, "%9u ",
                                stats->freq_table[i]);
        }
        if (len >= PAGE_SIZE)
                return PAGE_SIZE;
 
-       len += snprintf(buf + len, PAGE_SIZE - len, "\n");
+       len += scnprintf(buf + len, PAGE_SIZE - len, "\n");
 
        for (i = 0; i < stats->state_num; i++) {
                if (len >= PAGE_SIZE)
                        break;
 
-               len += snprintf(buf + len, PAGE_SIZE - len, "%9u: ",
+               len += scnprintf(buf + len, PAGE_SIZE - len, "%9u: ",
                                stats->freq_table[i]);
 
                for (j = 0; j < stats->state_num; j++) {
                        if (len >= PAGE_SIZE)
                                break;
-                       len += snprintf(buf + len, PAGE_SIZE - len, "%9u ",
+                       len += scnprintf(buf + len, PAGE_SIZE - len, "%9u ",
                                        stats->trans_table[i*stats->max_state+j]);
                }
                if (len >= PAGE_SIZE)
                        break;
-               len += snprintf(buf + len, PAGE_SIZE - len, "\n");
+               len += scnprintf(buf + len, PAGE_SIZE - len, "\n");
        }
 
        if (len >= PAGE_SIZE) {
index 6cb8193..de206d2 100644 (file)
@@ -19,6 +19,8 @@
 #define IMX8MN_OCOTP_CFG3_SPEED_GRADE_MASK     (0xf << 8)
 #define OCOTP_CFG3_MKT_SEGMENT_SHIFT    6
 #define OCOTP_CFG3_MKT_SEGMENT_MASK     (0x3 << 6)
+#define IMX8MP_OCOTP_CFG3_MKT_SEGMENT_SHIFT    5
+#define IMX8MP_OCOTP_CFG3_MKT_SEGMENT_MASK     (0x3 << 5)
 
 /* cpufreq-dt device registered by imx-cpufreq-dt */
 static struct platform_device *cpufreq_dt_pdev;
@@ -31,6 +33,9 @@ static int imx_cpufreq_dt_probe(struct platform_device *pdev)
        int speed_grade, mkt_segment;
        int ret;
 
+       if (!of_find_property(cpu_dev->of_node, "cpu-supply", NULL))
+               return -ENODEV;
+
        ret = nvmem_cell_read_u32(cpu_dev, "speed_grade", &cell_value);
        if (ret)
                return ret;
@@ -42,7 +47,13 @@ static int imx_cpufreq_dt_probe(struct platform_device *pdev)
        else
                speed_grade = (cell_value & OCOTP_CFG3_SPEED_GRADE_MASK)
                              >> OCOTP_CFG3_SPEED_GRADE_SHIFT;
-       mkt_segment = (cell_value & OCOTP_CFG3_MKT_SEGMENT_MASK) >> OCOTP_CFG3_MKT_SEGMENT_SHIFT;
+
+       if (of_machine_is_compatible("fsl,imx8mp"))
+               mkt_segment = (cell_value & IMX8MP_OCOTP_CFG3_MKT_SEGMENT_MASK)
+                              >> IMX8MP_OCOTP_CFG3_MKT_SEGMENT_SHIFT;
+       else
+               mkt_segment = (cell_value & OCOTP_CFG3_MKT_SEGMENT_MASK)
+                              >> OCOTP_CFG3_MKT_SEGMENT_SHIFT;
 
        /*
         * Early samples without fuses written report "0 0" which may NOT
index 648a09a..fdb2fff 100644 (file)
@@ -216,31 +216,41 @@ static struct cpufreq_driver imx6q_cpufreq_driver = {
 #define OCOTP_CFG3_SPEED_996MHZ                0x2
 #define OCOTP_CFG3_SPEED_852MHZ                0x1
 
-static void imx6q_opp_check_speed_grading(struct device *dev)
+static int imx6q_opp_check_speed_grading(struct device *dev)
 {
        struct device_node *np;
        void __iomem *base;
        u32 val;
+       int ret;
 
-       np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ocotp");
-       if (!np)
-               return;
+       if (of_find_property(dev->of_node, "nvmem-cells", NULL)) {
+               ret = nvmem_cell_read_u32(dev, "speed_grade", &val);
+               if (ret)
+                       return ret;
+       } else {
+               np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ocotp");
+               if (!np)
+                       return -ENOENT;
 
-       base = of_iomap(np, 0);
-       if (!base) {
-               dev_err(dev, "failed to map ocotp\n");
-               goto put_node;
+               base = of_iomap(np, 0);
+               of_node_put(np);
+               if (!base) {
+                       dev_err(dev, "failed to map ocotp\n");
+                       return -EFAULT;
+               }
+
+               /*
+                * SPEED_GRADING[1:0] defines the max speed of ARM:
+                * 2b'11: 1200000000Hz;
+                * 2b'10: 996000000Hz;
+                * 2b'01: 852000000Hz; -- i.MX6Q Only, exclusive with 996MHz.
+                * 2b'00: 792000000Hz;
+                * We need to set the max speed of ARM according to fuse map.
+                */
+               val = readl_relaxed(base + OCOTP_CFG3);
+               iounmap(base);
        }
 
-       /*
-        * SPEED_GRADING[1:0] defines the max speed of ARM:
-        * 2b'11: 1200000000Hz;
-        * 2b'10: 996000000Hz;
-        * 2b'01: 852000000Hz; -- i.MX6Q Only, exclusive with 996MHz.
-        * 2b'00: 792000000Hz;
-        * We need to set the max speed of ARM according to fuse map.
-        */
-       val = readl_relaxed(base + OCOTP_CFG3);
        val >>= OCOTP_CFG3_SPEED_SHIFT;
        val &= 0x3;
 
@@ -257,9 +267,8 @@ static void imx6q_opp_check_speed_grading(struct device *dev)
                        if (dev_pm_opp_disable(dev, 1200000000))
                                dev_warn(dev, "failed to disable 1.2GHz OPP\n");
        }
-       iounmap(base);
-put_node:
-       of_node_put(np);
+
+       return 0;
 }
 
 #define OCOTP_CFG3_6UL_SPEED_696MHZ    0x2
@@ -281,6 +290,9 @@ static int imx6ul_opp_check_speed_grading(struct device *dev)
 
                np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-ocotp");
                if (!np)
+                       np = of_find_compatible_node(NULL, NULL,
+                                                    "fsl,imx6ull-ocotp");
+               if (!np)
                        return -ENOENT;
 
                base = of_iomap(np, 0);
@@ -378,23 +390,22 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
                goto put_reg;
        }
 
+       /* Because we have added the OPPs here, we must free them */
+       free_opp = true;
+
        if (of_machine_is_compatible("fsl,imx6ul") ||
            of_machine_is_compatible("fsl,imx6ull")) {
                ret = imx6ul_opp_check_speed_grading(cpu_dev);
-               if (ret) {
-                       if (ret == -EPROBE_DEFER)
-                               goto put_node;
-
+       } else {
+               ret = imx6q_opp_check_speed_grading(cpu_dev);
+       }
+       if (ret) {
+               if (ret != -EPROBE_DEFER)
                        dev_err(cpu_dev, "failed to read ocotp: %d\n",
                                ret);
-                       goto put_node;
-               }
-       } else {
-               imx6q_opp_check_speed_grading(cpu_dev);
+               goto out_free_opp;
        }
 
-       /* Because we have added the OPPs here, we must free them */
-       free_opp = true;
        num = dev_pm_opp_get_opp_count(cpu_dev);
        if (num < 0) {
                ret = num;
index c81e1ff..d229783 100644 (file)
@@ -2155,15 +2155,19 @@ static void intel_pstate_adjust_policy_max(struct cpudata *cpu,
        }
 }
 
-static int intel_pstate_verify_policy(struct cpufreq_policy_data *policy)
+static void intel_pstate_verify_cpu_policy(struct cpudata *cpu,
+                                          struct cpufreq_policy_data *policy)
 {
-       struct cpudata *cpu = all_cpu_data[policy->cpu];
-
        update_turbo_state();
        cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
                                     intel_pstate_get_max_freq(cpu));
 
        intel_pstate_adjust_policy_max(cpu, policy);
+}
+
+static int intel_pstate_verify_policy(struct cpufreq_policy_data *policy)
+{
+       intel_pstate_verify_cpu_policy(all_cpu_data[policy->cpu], policy);
 
        return 0;
 }
@@ -2243,10 +2247,11 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
        if (ret)
                return ret;
 
-       if (IS_ENABLED(CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE))
-               policy->policy = CPUFREQ_POLICY_PERFORMANCE;
-       else
-               policy->policy = CPUFREQ_POLICY_POWERSAVE;
+       /*
+        * Set the policy to powersave to provide a valid fallback value in case
+        * the default cpufreq governor is neither powersave nor performance.
+        */
+       policy->policy = CPUFREQ_POLICY_POWERSAVE;
 
        return 0;
 }
@@ -2268,12 +2273,7 @@ static int intel_cpufreq_verify_policy(struct cpufreq_policy_data *policy)
 {
        struct cpudata *cpu = all_cpu_data[policy->cpu];
 
-       update_turbo_state();
-       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
-                                    intel_pstate_get_max_freq(cpu));
-
-       intel_pstate_adjust_policy_max(cpu, policy);
-
+       intel_pstate_verify_cpu_policy(cpu, policy);
        intel_pstate_update_perf_limits(cpu, policy->min, policy->max);
 
        return 0;
index f0d2d50..a1b8238 100644 (file)
@@ -49,12 +49,14 @@ struct qcom_cpufreq_drv;
 struct qcom_cpufreq_match_data {
        int (*get_version)(struct device *cpu_dev,
                           struct nvmem_cell *speedbin_nvmem,
+                          char **pvs_name,
                           struct qcom_cpufreq_drv *drv);
        const char **genpd_names;
 };
 
 struct qcom_cpufreq_drv {
-       struct opp_table **opp_tables;
+       struct opp_table **names_opp_tables;
+       struct opp_table **hw_opp_tables;
        struct opp_table **genpd_opp_tables;
        u32 versions;
        const struct qcom_cpufreq_match_data *data;
@@ -62,6 +64,84 @@ struct qcom_cpufreq_drv {
 
 static struct platform_device *cpufreq_dt_pdev, *cpufreq_pdev;
 
+static void get_krait_bin_format_a(struct device *cpu_dev,
+                                         int *speed, int *pvs, int *pvs_ver,
+                                         struct nvmem_cell *pvs_nvmem, u8 *buf)
+{
+       u32 pte_efuse;
+
+       pte_efuse = *((u32 *)buf);
+
+       *speed = pte_efuse & 0xf;
+       if (*speed == 0xf)
+               *speed = (pte_efuse >> 4) & 0xf;
+
+       if (*speed == 0xf) {
+               *speed = 0;
+               dev_warn(cpu_dev, "Speed bin: Defaulting to %d\n", *speed);
+       } else {
+               dev_dbg(cpu_dev, "Speed bin: %d\n", *speed);
+       }
+
+       *pvs = (pte_efuse >> 10) & 0x7;
+       if (*pvs == 0x7)
+               *pvs = (pte_efuse >> 13) & 0x7;
+
+       if (*pvs == 0x7) {
+               *pvs = 0;
+               dev_warn(cpu_dev, "PVS bin: Defaulting to %d\n", *pvs);
+       } else {
+               dev_dbg(cpu_dev, "PVS bin: %d\n", *pvs);
+       }
+}
+
+static void get_krait_bin_format_b(struct device *cpu_dev,
+                                         int *speed, int *pvs, int *pvs_ver,
+                                         struct nvmem_cell *pvs_nvmem, u8 *buf)
+{
+       u32 pte_efuse, redundant_sel;
+
+       pte_efuse = *((u32 *)buf);
+       redundant_sel = (pte_efuse >> 24) & 0x7;
+
+       *pvs_ver = (pte_efuse >> 4) & 0x3;
+
+       switch (redundant_sel) {
+       case 1:
+               *pvs = ((pte_efuse >> 28) & 0x8) | ((pte_efuse >> 6) & 0x7);
+               *speed = (pte_efuse >> 27) & 0xf;
+               break;
+       case 2:
+               *pvs = (pte_efuse >> 27) & 0xf;
+               *speed = pte_efuse & 0x7;
+               break;
+       default:
+               /* 4 bits of PVS are in efuse register bits 31, 8-6. */
+               *pvs = ((pte_efuse >> 28) & 0x8) | ((pte_efuse >> 6) & 0x7);
+               *speed = pte_efuse & 0x7;
+       }
+
+       /* Check SPEED_BIN_BLOW_STATUS */
+       if (pte_efuse & BIT(3)) {
+               dev_dbg(cpu_dev, "Speed bin: %d\n", *speed);
+       } else {
+               dev_warn(cpu_dev, "Speed bin not set. Defaulting to 0!\n");
+               *speed = 0;
+       }
+
+       /* Check PVS_BLOW_STATUS */
+       pte_efuse = *(((u32 *)buf) + 4);
+       pte_efuse &= BIT(21);
+       if (pte_efuse) {
+               dev_dbg(cpu_dev, "PVS bin: %d\n", *pvs);
+       } else {
+               dev_warn(cpu_dev, "PVS bin not set. Defaulting to 0!\n");
+               *pvs = 0;
+       }
+
+       dev_dbg(cpu_dev, "PVS version: %d\n", *pvs_ver);
+}
+
 static enum _msm8996_version qcom_cpufreq_get_msm_id(void)
 {
        size_t len;
@@ -93,11 +173,13 @@ static enum _msm8996_version qcom_cpufreq_get_msm_id(void)
 
 static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev,
                                          struct nvmem_cell *speedbin_nvmem,
+                                         char **pvs_name,
                                          struct qcom_cpufreq_drv *drv)
 {
        size_t len;
        u8 *speedbin;
        enum _msm8996_version msm8996_version;
+       *pvs_name = NULL;
 
        msm8996_version = qcom_cpufreq_get_msm_id();
        if (NUM_OF_MSM8996_VERSIONS == msm8996_version) {
@@ -125,10 +207,51 @@ static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev,
        return 0;
 }
 
+static int qcom_cpufreq_krait_name_version(struct device *cpu_dev,
+                                          struct nvmem_cell *speedbin_nvmem,
+                                          char **pvs_name,
+                                          struct qcom_cpufreq_drv *drv)
+{
+       int speed = 0, pvs = 0, pvs_ver = 0;
+       u8 *speedbin;
+       size_t len;
+
+       speedbin = nvmem_cell_read(speedbin_nvmem, &len);
+
+       if (IS_ERR(speedbin))
+               return PTR_ERR(speedbin);
+
+       switch (len) {
+       case 4:
+               get_krait_bin_format_a(cpu_dev, &speed, &pvs, &pvs_ver,
+                                      speedbin_nvmem, speedbin);
+               break;
+       case 8:
+               get_krait_bin_format_b(cpu_dev, &speed, &pvs, &pvs_ver,
+                                      speedbin_nvmem, speedbin);
+               break;
+       default:
+               dev_err(cpu_dev, "Unable to read nvmem data. Defaulting to 0!\n");
+               return -ENODEV;
+       }
+
+       snprintf(*pvs_name, sizeof("speedXX-pvsXX-vXX"), "speed%d-pvs%d-v%d",
+                speed, pvs, pvs_ver);
+
+       drv->versions = (1 << speed);
+
+       kfree(speedbin);
+       return 0;
+}
+
 static const struct qcom_cpufreq_match_data match_data_kryo = {
        .get_version = qcom_cpufreq_kryo_name_version,
 };
 
+static const struct qcom_cpufreq_match_data match_data_krait = {
+       .get_version = qcom_cpufreq_krait_name_version,
+};
+
 static const char *qcs404_genpd_names[] = { "cpr", NULL };
 
 static const struct qcom_cpufreq_match_data match_data_qcs404 = {
@@ -141,6 +264,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
        struct nvmem_cell *speedbin_nvmem;
        struct device_node *np;
        struct device *cpu_dev;
+       char *pvs_name = "speedXX-pvsXX-vXX";
        unsigned cpu;
        const struct of_device_id *match;
        int ret;
@@ -153,7 +277,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
        if (!np)
                return -ENOENT;
 
-       ret = of_device_is_compatible(np, "operating-points-v2-kryo-cpu");
+       ret = of_device_is_compatible(np, "operating-points-v2-qcom-cpu");
        if (!ret) {
                of_node_put(np);
                return -ENOENT;
@@ -181,7 +305,8 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
                        goto free_drv;
                }
 
-               ret = drv->data->get_version(cpu_dev, speedbin_nvmem, drv);
+               ret = drv->data->get_version(cpu_dev,
+                                                       speedbin_nvmem, &pvs_name, drv);
                if (ret) {
                        nvmem_cell_put(speedbin_nvmem);
                        goto free_drv;
@@ -190,12 +315,20 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
        }
        of_node_put(np);
 
-       drv->opp_tables = kcalloc(num_possible_cpus(), sizeof(*drv->opp_tables),
+       drv->names_opp_tables = kcalloc(num_possible_cpus(),
+                                 sizeof(*drv->names_opp_tables),
                                  GFP_KERNEL);
-       if (!drv->opp_tables) {
+       if (!drv->names_opp_tables) {
                ret = -ENOMEM;
                goto free_drv;
        }
+       drv->hw_opp_tables = kcalloc(num_possible_cpus(),
+                                 sizeof(*drv->hw_opp_tables),
+                                 GFP_KERNEL);
+       if (!drv->hw_opp_tables) {
+               ret = -ENOMEM;
+               goto free_opp_names;
+       }
 
        drv->genpd_opp_tables = kcalloc(num_possible_cpus(),
                                        sizeof(*drv->genpd_opp_tables),
@@ -213,11 +346,23 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
                }
 
                if (drv->data->get_version) {
-                       drv->opp_tables[cpu] =
-                               dev_pm_opp_set_supported_hw(cpu_dev,
-                                                           &drv->versions, 1);
-                       if (IS_ERR(drv->opp_tables[cpu])) {
-                               ret = PTR_ERR(drv->opp_tables[cpu]);
+
+                       if (pvs_name) {
+                               drv->names_opp_tables[cpu] = dev_pm_opp_set_prop_name(
+                                                                    cpu_dev,
+                                                                    pvs_name);
+                               if (IS_ERR(drv->names_opp_tables[cpu])) {
+                                       ret = PTR_ERR(drv->names_opp_tables[cpu]);
+                                       dev_err(cpu_dev, "Failed to add OPP name %s\n",
+                                               pvs_name);
+                                       goto free_opp;
+                               }
+                       }
+
+                       drv->hw_opp_tables[cpu] = dev_pm_opp_set_supported_hw(
+                                                                        cpu_dev, &drv->versions, 1);
+                       if (IS_ERR(drv->hw_opp_tables[cpu])) {
+                               ret = PTR_ERR(drv->hw_opp_tables[cpu]);
                                dev_err(cpu_dev,
                                        "Failed to set supported hardware\n");
                                goto free_genpd_opp;
@@ -259,11 +404,18 @@ free_genpd_opp:
        kfree(drv->genpd_opp_tables);
 free_opp:
        for_each_possible_cpu(cpu) {
-               if (IS_ERR_OR_NULL(drv->opp_tables[cpu]))
+               if (IS_ERR_OR_NULL(drv->names_opp_tables[cpu]))
+                       break;
+               dev_pm_opp_put_prop_name(drv->names_opp_tables[cpu]);
+       }
+       for_each_possible_cpu(cpu) {
+               if (IS_ERR_OR_NULL(drv->hw_opp_tables[cpu]))
                        break;
-               dev_pm_opp_put_supported_hw(drv->opp_tables[cpu]);
+               dev_pm_opp_put_supported_hw(drv->hw_opp_tables[cpu]);
        }
-       kfree(drv->opp_tables);
+       kfree(drv->hw_opp_tables);
+free_opp_names:
+       kfree(drv->names_opp_tables);
 free_drv:
        kfree(drv);
 
@@ -278,13 +430,16 @@ static int qcom_cpufreq_remove(struct platform_device *pdev)
        platform_device_unregister(cpufreq_dt_pdev);
 
        for_each_possible_cpu(cpu) {
-               if (drv->opp_tables[cpu])
-                       dev_pm_opp_put_supported_hw(drv->opp_tables[cpu]);
+               if (drv->names_opp_tables[cpu])
+                       dev_pm_opp_put_supported_hw(drv->names_opp_tables[cpu]);
+               if (drv->hw_opp_tables[cpu])
+                       dev_pm_opp_put_supported_hw(drv->hw_opp_tables[cpu]);
                if (drv->genpd_opp_tables[cpu])
                        dev_pm_opp_detach_genpd(drv->genpd_opp_tables[cpu]);
        }
 
-       kfree(drv->opp_tables);
+       kfree(drv->names_opp_tables);
+       kfree(drv->hw_opp_tables);
        kfree(drv->genpd_opp_tables);
        kfree(drv);
 
@@ -303,6 +458,10 @@ static const struct of_device_id qcom_cpufreq_match_list[] __initconst = {
        { .compatible = "qcom,apq8096", .data = &match_data_kryo },
        { .compatible = "qcom,msm8996", .data = &match_data_kryo },
        { .compatible = "qcom,qcs404", .data = &match_data_qcs404 },
+       { .compatible = "qcom,ipq8064", .data = &match_data_krait },
+       { .compatible = "qcom,apq8064", .data = &match_data_krait },
+       { .compatible = "qcom,msm8974", .data = &match_data_krait },
+       { .compatible = "qcom,msm8960", .data = &match_data_krait },
        {},
 };
 
index 557cb51..ab0de27 100644 (file)
 
 #define DRA7_EFUSE_HAS_OD_MPU_OPP              11
 #define DRA7_EFUSE_HAS_HIGH_MPU_OPP            15
+#define DRA76_EFUSE_HAS_PLUS_MPU_OPP           18
 #define DRA7_EFUSE_HAS_ALL_MPU_OPP             23
+#define DRA76_EFUSE_HAS_ALL_MPU_OPP            24
 
 #define DRA7_EFUSE_NOM_MPU_OPP                 BIT(0)
 #define DRA7_EFUSE_OD_MPU_OPP                  BIT(1)
 #define DRA7_EFUSE_HIGH_MPU_OPP                        BIT(2)
+#define DRA76_EFUSE_PLUS_MPU_OPP               BIT(3)
 
 #define OMAP3_CONTROL_DEVICE_STATUS            0x4800244C
 #define OMAP3_CONTROL_IDCODE                   0x4830A204
@@ -80,6 +83,10 @@ static unsigned long dra7_efuse_xlate(struct ti_cpufreq_data *opp_data,
         */
 
        switch (efuse) {
+       case DRA76_EFUSE_HAS_PLUS_MPU_OPP:
+       case DRA76_EFUSE_HAS_ALL_MPU_OPP:
+               calculated_efuse |= DRA76_EFUSE_PLUS_MPU_OPP;
+               /* Fall through */
        case DRA7_EFUSE_HAS_ALL_MPU_OPP:
        case DRA7_EFUSE_HAS_HIGH_MPU_OPP:
                calculated_efuse |= DRA7_EFUSE_HIGH_MPU_OPP;