diff options
Diffstat (limited to 'target/linux/ipq806x/patches-5.4/0036-qcom-cpufreq-nvmem-Re-organise-kryo-cpufreq-driver.patch')
-rw-r--r-- | target/linux/ipq806x/patches-5.4/0036-qcom-cpufreq-nvmem-Re-organise-kryo-cpufreq-driver.patch | 579 |
1 files changed, 0 insertions, 579 deletions
diff --git a/target/linux/ipq806x/patches-5.4/0036-qcom-cpufreq-nvmem-Re-organise-kryo-cpufreq-driver.patch b/target/linux/ipq806x/patches-5.4/0036-qcom-cpufreq-nvmem-Re-organise-kryo-cpufreq-driver.patch deleted file mode 100644 index c7e4569616..0000000000 --- a/target/linux/ipq806x/patches-5.4/0036-qcom-cpufreq-nvmem-Re-organise-kryo-cpufreq-driver.patch +++ /dev/null @@ -1,579 +0,0 @@ -From 7d12709544b8b3fb9727a34a664b8380e1e3493a Mon Sep 17 00:00:00 2001 -From: Sricharan R <sricharan@codeaurora.org> -Date: Thu, 25 Jul 2019 12:41:31 +0200 -Subject: [PATCH] cpufreq: qcom: Re-organise kryo cpufreq to use it for other - nvmem based qcom socs - -The kryo cpufreq driver reads the nvmem cell and uses that data to -populate the opps. There are other qcom cpufreq socs like krait which -does similar thing. Except for the interpretation of the read data, -rest of the driver is same for both the cases. So pull the common things -out for reuse. - -Signed-off-by: Sricharan R <sricharan@codeaurora.org> -[niklas.cassel@linaro.org: split dt-binding into a separate patch and -do not rename the compatible string. Update MAINTAINERS file.] -Signed-off-by: Niklas Cassel <niklas.cassel@linaro.org> -Reviewed-by: Ilia Lin <ilia.lin@kernel.org> -Reviewed-by: Stephen Boyd <sboyd@kernel.org> -Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> ---- - MAINTAINERS | 4 +- - drivers/cpufreq/Kconfig.arm | 4 +- - drivers/cpufreq/Makefile | 2 +- - ...om-cpufreq-kryo.c => qcom-cpufreq-nvmem.c} | 122 +++++++++++------- - 4 files changed, 78 insertions(+), 54 deletions(-) - rename drivers/cpufreq/{qcom-cpufreq-kryo.c => qcom-cpufreq-nvmem.c} (69%) - ---- a/drivers/cpufreq/Kconfig.arm -+++ b/drivers/cpufreq/Kconfig.arm -@@ -110,8 +110,8 @@ config ARM_OMAP2PLUS_CPUFREQ - depends on ARCH_OMAP2PLUS - default ARCH_OMAP2PLUS - --config ARM_QCOM_CPUFREQ_KRYO -- tristate "Qualcomm Kryo based CPUFreq" -+config ARM_QCOM_CPUFREQ_NVMEM -+ tristate "Qualcomm nvmem based CPUFreq" - depends on ARM64 - depends on QCOM_QFPROM - depends on QCOM_SMEM ---- a/drivers/cpufreq/Makefile -+++ b/drivers/cpufreq/Makefile -@@ -64,7 +64,7 @@ obj-$(CONFIG_MACH_MVEBU_V7) += mvebu-cp - obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o - obj-$(CONFIG_ARM_PXA2xx_CPUFREQ) += pxa2xx-cpufreq.o - obj-$(CONFIG_PXA3xx) += pxa3xx-cpufreq.o --obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRYO) += qcom-cpufreq-kryo.o -+obj-$(CONFIG_ARM_QCOM_CPUFREQ_NVMEM) += qcom-cpufreq-nvmem.o - obj-$(CONFIG_ARM_S3C2410_CPUFREQ) += s3c2410-cpufreq.o - obj-$(CONFIG_ARM_S3C2412_CPUFREQ) += s3c2412-cpufreq.o - obj-$(CONFIG_ARM_S3C2416_CPUFREQ) += s3c2416-cpufreq.o ---- a/drivers/cpufreq/qcom-cpufreq-kryo.c -+++ /dev/null -@@ -1,249 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0 --/* -- * Copyright (c) 2018, The Linux Foundation. All rights reserved. -- */ -- --/* -- * In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors, -- * the CPU frequency subset and voltage value of each OPP varies -- * based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables -- * defines the voltage and frequency value based on the msm-id in SMEM -- * and speedbin blown in the efuse combination. -- * The qcom-cpufreq-kryo driver reads the msm-id and efuse value from the SoC -- * to provide the OPP framework with required information. -- * This is used to determine the voltage and frequency value for each OPP of -- * operating-points-v2 table when it is parsed by the OPP framework. -- */ -- --#include <linux/cpu.h> --#include <linux/err.h> --#include <linux/init.h> --#include <linux/kernel.h> --#include <linux/module.h> --#include <linux/nvmem-consumer.h> --#include <linux/of.h> --#include <linux/platform_device.h> --#include <linux/pm_opp.h> --#include <linux/slab.h> --#include <linux/soc/qcom/smem.h> -- --#define MSM_ID_SMEM 137 -- --enum _msm_id { -- MSM8996V3 = 0xF6ul, -- APQ8096V3 = 0x123ul, -- MSM8996SG = 0x131ul, -- APQ8096SG = 0x138ul, --}; -- --enum _msm8996_version { -- MSM8996_V3, -- MSM8996_SG, -- NUM_OF_MSM8996_VERSIONS, --}; -- --static struct platform_device *cpufreq_dt_pdev, *kryo_cpufreq_pdev; -- --static enum _msm8996_version qcom_cpufreq_kryo_get_msm_id(void) --{ -- size_t len; -- u32 *msm_id; -- enum _msm8996_version version; -- -- msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len); -- if (IS_ERR(msm_id)) -- return NUM_OF_MSM8996_VERSIONS; -- -- /* The first 4 bytes are format, next to them is the actual msm-id */ -- msm_id++; -- -- switch ((enum _msm_id)*msm_id) { -- case MSM8996V3: -- case APQ8096V3: -- version = MSM8996_V3; -- break; -- case MSM8996SG: -- case APQ8096SG: -- version = MSM8996_SG; -- break; -- default: -- version = NUM_OF_MSM8996_VERSIONS; -- } -- -- return version; --} -- --static int qcom_cpufreq_kryo_probe(struct platform_device *pdev) --{ -- struct opp_table **opp_tables; -- enum _msm8996_version msm8996_version; -- struct nvmem_cell *speedbin_nvmem; -- struct device_node *np; -- struct device *cpu_dev; -- unsigned cpu; -- u8 *speedbin; -- u32 versions; -- size_t len; -- int ret; -- -- cpu_dev = get_cpu_device(0); -- if (!cpu_dev) -- return -ENODEV; -- -- msm8996_version = qcom_cpufreq_kryo_get_msm_id(); -- if (NUM_OF_MSM8996_VERSIONS == msm8996_version) { -- dev_err(cpu_dev, "Not Snapdragon 820/821!"); -- return -ENODEV; -- } -- -- np = dev_pm_opp_of_get_opp_desc_node(cpu_dev); -- if (!np) -- return -ENOENT; -- -- ret = of_device_is_compatible(np, "operating-points-v2-kryo-cpu"); -- if (!ret) { -- of_node_put(np); -- return -ENOENT; -- } -- -- speedbin_nvmem = of_nvmem_cell_get(np, NULL); -- of_node_put(np); -- if (IS_ERR(speedbin_nvmem)) { -- if (PTR_ERR(speedbin_nvmem) != -EPROBE_DEFER) -- dev_err(cpu_dev, "Could not get nvmem cell: %ld\n", -- PTR_ERR(speedbin_nvmem)); -- return PTR_ERR(speedbin_nvmem); -- } -- -- speedbin = nvmem_cell_read(speedbin_nvmem, &len); -- nvmem_cell_put(speedbin_nvmem); -- if (IS_ERR(speedbin)) -- return PTR_ERR(speedbin); -- -- switch (msm8996_version) { -- case MSM8996_V3: -- versions = 1 << (unsigned int)(*speedbin); -- break; -- case MSM8996_SG: -- versions = 1 << ((unsigned int)(*speedbin) + 4); -- break; -- default: -- BUG(); -- break; -- } -- kfree(speedbin); -- -- opp_tables = kcalloc(num_possible_cpus(), sizeof(*opp_tables), GFP_KERNEL); -- if (!opp_tables) -- return -ENOMEM; -- -- for_each_possible_cpu(cpu) { -- cpu_dev = get_cpu_device(cpu); -- if (NULL == cpu_dev) { -- ret = -ENODEV; -- goto free_opp; -- } -- -- opp_tables[cpu] = dev_pm_opp_set_supported_hw(cpu_dev, -- &versions, 1); -- if (IS_ERR(opp_tables[cpu])) { -- ret = PTR_ERR(opp_tables[cpu]); -- dev_err(cpu_dev, "Failed to set supported hardware\n"); -- goto free_opp; -- } -- } -- -- cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1, -- NULL, 0); -- if (!IS_ERR(cpufreq_dt_pdev)) { -- platform_set_drvdata(pdev, opp_tables); -- return 0; -- } -- -- ret = PTR_ERR(cpufreq_dt_pdev); -- dev_err(cpu_dev, "Failed to register platform device\n"); -- --free_opp: -- for_each_possible_cpu(cpu) { -- if (IS_ERR_OR_NULL(opp_tables[cpu])) -- break; -- dev_pm_opp_put_supported_hw(opp_tables[cpu]); -- } -- kfree(opp_tables); -- -- return ret; --} -- --static int qcom_cpufreq_kryo_remove(struct platform_device *pdev) --{ -- struct opp_table **opp_tables = platform_get_drvdata(pdev); -- unsigned int cpu; -- -- platform_device_unregister(cpufreq_dt_pdev); -- -- for_each_possible_cpu(cpu) -- dev_pm_opp_put_supported_hw(opp_tables[cpu]); -- -- kfree(opp_tables); -- -- return 0; --} -- --static struct platform_driver qcom_cpufreq_kryo_driver = { -- .probe = qcom_cpufreq_kryo_probe, -- .remove = qcom_cpufreq_kryo_remove, -- .driver = { -- .name = "qcom-cpufreq-kryo", -- }, --}; -- --static const struct of_device_id qcom_cpufreq_kryo_match_list[] __initconst = { -- { .compatible = "qcom,apq8096", }, -- { .compatible = "qcom,msm8996", }, -- {} --}; -- --/* -- * Since the driver depends on smem and nvmem drivers, which may -- * return EPROBE_DEFER, all the real activity is done in the probe, -- * which may be defered as well. The init here is only registering -- * the driver and the platform device. -- */ --static int __init qcom_cpufreq_kryo_init(void) --{ -- struct device_node *np = of_find_node_by_path("/"); -- const struct of_device_id *match; -- int ret; -- -- if (!np) -- return -ENODEV; -- -- match = of_match_node(qcom_cpufreq_kryo_match_list, np); -- of_node_put(np); -- if (!match) -- return -ENODEV; -- -- ret = platform_driver_register(&qcom_cpufreq_kryo_driver); -- if (unlikely(ret < 0)) -- return ret; -- -- kryo_cpufreq_pdev = platform_device_register_simple( -- "qcom-cpufreq-kryo", -1, NULL, 0); -- ret = PTR_ERR_OR_ZERO(kryo_cpufreq_pdev); -- if (0 == ret) -- return 0; -- -- platform_driver_unregister(&qcom_cpufreq_kryo_driver); -- return ret; --} --module_init(qcom_cpufreq_kryo_init); -- --static void __exit qcom_cpufreq_kryo_exit(void) --{ -- platform_device_unregister(kryo_cpufreq_pdev); -- platform_driver_unregister(&qcom_cpufreq_kryo_driver); --} --module_exit(qcom_cpufreq_kryo_exit); -- --MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Kryo CPUfreq driver"); --MODULE_LICENSE("GPL v2"); ---- /dev/null -+++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c -@@ -0,0 +1,273 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2018, The Linux Foundation. All rights reserved. -+ */ -+ -+/* -+ * In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors, -+ * the CPU frequency subset and voltage value of each OPP varies -+ * based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables -+ * defines the voltage and frequency value based on the msm-id in SMEM -+ * and speedbin blown in the efuse combination. -+ * The qcom-cpufreq-nvmem driver reads the msm-id and efuse value from the SoC -+ * to provide the OPP framework with required information. -+ * This is used to determine the voltage and frequency value for each OPP of -+ * operating-points-v2 table when it is parsed by the OPP framework. -+ */ -+ -+#include <linux/cpu.h> -+#include <linux/err.h> -+#include <linux/init.h> -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/nvmem-consumer.h> -+#include <linux/of.h> -+#include <linux/of_device.h> -+#include <linux/platform_device.h> -+#include <linux/pm_opp.h> -+#include <linux/slab.h> -+#include <linux/soc/qcom/smem.h> -+ -+#define MSM_ID_SMEM 137 -+ -+enum _msm_id { -+ MSM8996V3 = 0xF6ul, -+ APQ8096V3 = 0x123ul, -+ MSM8996SG = 0x131ul, -+ APQ8096SG = 0x138ul, -+}; -+ -+enum _msm8996_version { -+ MSM8996_V3, -+ MSM8996_SG, -+ NUM_OF_MSM8996_VERSIONS, -+}; -+ -+static struct platform_device *cpufreq_dt_pdev, *cpufreq_pdev; -+ -+static enum _msm8996_version qcom_cpufreq_get_msm_id(void) -+{ -+ size_t len; -+ u32 *msm_id; -+ enum _msm8996_version version; -+ -+ msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len); -+ if (IS_ERR(msm_id)) -+ return NUM_OF_MSM8996_VERSIONS; -+ -+ /* The first 4 bytes are format, next to them is the actual msm-id */ -+ msm_id++; -+ -+ switch ((enum _msm_id)*msm_id) { -+ case MSM8996V3: -+ case APQ8096V3: -+ version = MSM8996_V3; -+ break; -+ case MSM8996SG: -+ case APQ8096SG: -+ version = MSM8996_SG; -+ break; -+ default: -+ version = NUM_OF_MSM8996_VERSIONS; -+ } -+ -+ return version; -+} -+ -+static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev, -+ struct nvmem_cell *speedbin_nvmem, -+ u32 *versions) -+{ -+ size_t len; -+ u8 *speedbin; -+ enum _msm8996_version msm8996_version; -+ -+ msm8996_version = qcom_cpufreq_get_msm_id(); -+ if (NUM_OF_MSM8996_VERSIONS == msm8996_version) { -+ dev_err(cpu_dev, "Not Snapdragon 820/821!"); -+ return -ENODEV; -+ } -+ -+ speedbin = nvmem_cell_read(speedbin_nvmem, &len); -+ if (IS_ERR(speedbin)) -+ return PTR_ERR(speedbin); -+ -+ switch (msm8996_version) { -+ case MSM8996_V3: -+ *versions = 1 << (unsigned int)(*speedbin); -+ break; -+ case MSM8996_SG: -+ *versions = 1 << ((unsigned int)(*speedbin) + 4); -+ break; -+ default: -+ BUG(); -+ break; -+ } -+ -+ kfree(speedbin); -+ return 0; -+} -+ -+static int qcom_cpufreq_probe(struct platform_device *pdev) -+{ -+ struct opp_table **opp_tables; -+ int (*get_version)(struct device *cpu_dev, -+ struct nvmem_cell *speedbin_nvmem, -+ u32 *versions); -+ struct nvmem_cell *speedbin_nvmem; -+ struct device_node *np; -+ struct device *cpu_dev; -+ unsigned cpu; -+ u32 versions; -+ const struct of_device_id *match; -+ int ret; -+ -+ cpu_dev = get_cpu_device(0); -+ if (!cpu_dev) -+ return -ENODEV; -+ -+ match = pdev->dev.platform_data; -+ get_version = match->data; -+ if (!get_version) -+ return -ENODEV; -+ -+ np = dev_pm_opp_of_get_opp_desc_node(cpu_dev); -+ if (!np) -+ return -ENOENT; -+ -+ ret = of_device_is_compatible(np, "operating-points-v2-kryo-cpu"); -+ if (!ret) { -+ of_node_put(np); -+ return -ENOENT; -+ } -+ -+ speedbin_nvmem = of_nvmem_cell_get(np, NULL); -+ of_node_put(np); -+ if (IS_ERR(speedbin_nvmem)) { -+ if (PTR_ERR(speedbin_nvmem) != -EPROBE_DEFER) -+ dev_err(cpu_dev, "Could not get nvmem cell: %ld\n", -+ PTR_ERR(speedbin_nvmem)); -+ return PTR_ERR(speedbin_nvmem); -+ } -+ -+ ret = get_version(cpu_dev, speedbin_nvmem, &versions); -+ nvmem_cell_put(speedbin_nvmem); -+ if (ret) -+ return ret; -+ -+ opp_tables = kcalloc(num_possible_cpus(), sizeof(*opp_tables), GFP_KERNEL); -+ if (!opp_tables) -+ return -ENOMEM; -+ -+ for_each_possible_cpu(cpu) { -+ cpu_dev = get_cpu_device(cpu); -+ if (NULL == cpu_dev) { -+ ret = -ENODEV; -+ goto free_opp; -+ } -+ -+ opp_tables[cpu] = dev_pm_opp_set_supported_hw(cpu_dev, -+ &versions, 1); -+ if (IS_ERR(opp_tables[cpu])) { -+ ret = PTR_ERR(opp_tables[cpu]); -+ dev_err(cpu_dev, "Failed to set supported hardware\n"); -+ goto free_opp; -+ } -+ } -+ -+ cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1, -+ NULL, 0); -+ if (!IS_ERR(cpufreq_dt_pdev)) { -+ platform_set_drvdata(pdev, opp_tables); -+ return 0; -+ } -+ -+ ret = PTR_ERR(cpufreq_dt_pdev); -+ dev_err(cpu_dev, "Failed to register platform device\n"); -+ -+free_opp: -+ for_each_possible_cpu(cpu) { -+ if (IS_ERR_OR_NULL(opp_tables[cpu])) -+ break; -+ dev_pm_opp_put_supported_hw(opp_tables[cpu]); -+ } -+ kfree(opp_tables); -+ -+ return ret; -+} -+ -+static int qcom_cpufreq_remove(struct platform_device *pdev) -+{ -+ struct opp_table **opp_tables = platform_get_drvdata(pdev); -+ unsigned int cpu; -+ -+ platform_device_unregister(cpufreq_dt_pdev); -+ -+ for_each_possible_cpu(cpu) -+ dev_pm_opp_put_supported_hw(opp_tables[cpu]); -+ -+ kfree(opp_tables); -+ -+ return 0; -+} -+ -+static struct platform_driver qcom_cpufreq_driver = { -+ .probe = qcom_cpufreq_probe, -+ .remove = qcom_cpufreq_remove, -+ .driver = { -+ .name = "qcom-cpufreq-nvmem", -+ }, -+}; -+ -+static const struct of_device_id qcom_cpufreq_match_list[] __initconst = { -+ { .compatible = "qcom,apq8096", -+ .data = qcom_cpufreq_kryo_name_version }, -+ { .compatible = "qcom,msm8996", -+ .data = qcom_cpufreq_kryo_name_version }, -+ {}, -+}; -+ -+/* -+ * Since the driver depends on smem and nvmem drivers, which may -+ * return EPROBE_DEFER, all the real activity is done in the probe, -+ * which may be defered as well. The init here is only registering -+ * the driver and the platform device. -+ */ -+static int __init qcom_cpufreq_init(void) -+{ -+ struct device_node *np = of_find_node_by_path("/"); -+ const struct of_device_id *match; -+ int ret; -+ -+ if (!np) -+ return -ENODEV; -+ -+ match = of_match_node(qcom_cpufreq_match_list, np); -+ of_node_put(np); -+ if (!match) -+ return -ENODEV; -+ -+ ret = platform_driver_register(&qcom_cpufreq_driver); -+ if (unlikely(ret < 0)) -+ return ret; -+ -+ cpufreq_pdev = platform_device_register_data(NULL, "qcom-cpufreq-nvmem", -+ -1, match, sizeof(*match)); -+ ret = PTR_ERR_OR_ZERO(cpufreq_pdev); -+ if (0 == ret) -+ return 0; -+ -+ platform_driver_unregister(&qcom_cpufreq_driver); -+ return ret; -+} -+module_init(qcom_cpufreq_init); -+ -+static void __exit qcom_cpufreq_exit(void) -+{ -+ platform_device_unregister(cpufreq_pdev); -+ platform_driver_unregister(&qcom_cpufreq_driver); -+} -+module_exit(qcom_cpufreq_exit); -+ -+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. CPUfreq driver"); -+MODULE_LICENSE("GPL v2"); |