mbox series

[v10,00/14] Krait clocks + Krait CPUfreq

Message ID 1529415925-28915-1-git-send-email-sricharan@codeaurora.org
Headers show
Series Krait clocks + Krait CPUfreq | expand

Message

Sricharan Ramabadhran June 19, 2018, 1:45 p.m. UTC
[v10]
  * Addressed Stephen's comments to add clocks bindings properties
    to the newly introduced nodes.
  * Added a change to include opp-supported-hw to qcom-cpufreq.c
  * Rebased on top of clk-next
  * Although there were minor changes to bindings and the driver
    retained the acked-by tags from Rob and Viresh respectively.    

[v9]
  * Fixed a rebase issue in Makefile and added Tag from Robh.

[v8]
  * Fixed a bug in path#14 pointed out by Viresh and also added tags.
    No change in any other patch.

[v7]
  * Fixed comments from Viresh for cleaning up the error handling
    in qcom-cpufreq.c. Also changed the init function to lateinit
    call. This is required because nvmem which gets initialised with
    module_init needs to go first.
  * Fixed Rob's comments for bindings documentation
  * Fixed kbuild build issue in clk-lpc32xx.c
  * Rebased on top of clk-next

[v6]
  * Adrressed comments from Viresh for patch #14 in v5 [5]
  * Introduced a new binding operating-points-v2-krait-cpu
    as per discussion with Rob
  * Added Review tags

[v5]
  * Addressed comments from Rob for bindings
  * Addressed comments from Viresh to use dev_pm_opp_set_prop_name, accordingly
    dropped patch #12 and corrected patch #11 from previous patch set in [4]
  * Converted to use #spdx tags for newly introduced files

Mostly a resend of the v3 posted by Stephen quite some time back [1]
except for few changes.
  Based on reading some feedback from list,
  * Dropped the patch "clk: Add safe switch hook" from v3 [2].
    Now this is taken care by patch#10 in this series only for Krait.
  * Dropped the path "clk: Avoid sending high rates to downstream
		      clocks during set_rate" from v3 [3].
  * Rebased on top of clk-next.
  * Dropped the DT update from the series. Will send separately
  * Now with cpufreq-dt+opp supporting voltage scaling, registering the
    krait cpu supplies in DT should be sufficient. But one issue is,
    the qcom-cpufreq drivers reads the efuse and based on that registers
    the opp data and then registers the cpufreq-dt device. So when
    cpufreq-dt driver probes and registers the regulator to the OPP framework,
    it expects that the opp data for the device should not be registered before
    the regulator. Will send a RFC patch removing that check, to find out the
    right way of doing it.

These patches provide cpufreq scaling on devices with Krait CPUs.
In Krait CPU designs there's one PLL and two muxes per CPU, allowing
us to switch CPU frequencies independently.

				 secondary
	 +-----+                    +
	 | QSB |-------+------------|\
	 +-----+       |            | |-+
		       |    +-------|/  |
		       |    |       +   |
	 +-----+       |    |           |
	 | PLL |----+-------+           |   primary
	 +-----+    |  |                |     +
		    |  |                +-----|\       +------+
	 +-------+  |  |                      | \      |      |
	 | HFPLL |----------+-----------------|  |-----| CPU0 |
	 +-------+  |  |    |                 |  |     |      |
		    |  |    | +-----+         | /      +------+
		    |  |    +-| / 2 |---------|/
		    |  |      +-----+         +
		    |  |         secondary
		    |  |            +
		    |  +------------|\
		    |               | |-+
		    +---------------|/  |   primary
				    +   |     +
					+-----|\       +------+
	 +-------+                            | \      |      |
	 | HFPLL |----------------------------|  |-----| CPU1 |
	 +-------+          |                 |  |     |      |
			    | +-----+         | /      +------+
			    +-| / 2 |---------|/
			      +-----+         +

To support this in the common clock framework we model the muxes,
dividers, and PLLs as different clocks. CPUfreq only interacts
with the primary mux (farthest right in the diagram). When CPUfreq
sets a rate, the mux code finds the best parent that can provide the rate.
Due to the design, QSB and the top PLL are always a fixed rate and thus
only support one frequency each. These sources provide the lowest
frequencies for the CPUs. The HFPLLs are where we can make the CPU go
faster (GHz range). Sometimes we need to run the HFPLL twice as
fast and divide it by two to get a particular frequency.

When switching rates we can't leave the CPU clocked by the HFPLL because
we need to turn off the output of the PLL when changing its frequency.
This means we have to switch over to the secondary mux and use one of the
fixed sources. This is why we need something like the safe parent patch.

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-March/332607.html
[2] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-March/332615.html
[3] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-March/332608.html
[4] https://lwn.net/Articles/740994/ 
[5] https://lkml.org/lkml/2017/12/19/537

Sricharan R (2):
  clk: qcom: Add safe switch hook for krait mux clocks
  dt-bindings: cpufreq: Document operating-points-v2-krait-cpu

Stephen Boyd (12):
  ARM: Add Krait L2 register accessor functions
  clk: qcom: Add support for High-Frequency PLLs (HFPLLs)
  clk: qcom: Add HFPLL driver
  dt-bindings: clock: Document qcom,hfpll
  clk: qcom: Add MSM8960/APQ8064's HFPLLs
  clk: qcom: Add IPQ806X's HFPLLs
  clk: qcom: Add support for Krait clocks
  clk: qcom: Add KPSS ACC/GCC driver
  dt-bindings: arm: Document qcom,kpss-gcc
  clk: qcom: Add Krait clock controller driver
  dt-bindings: clock: Document qcom,krait-cc
  cpufreq: Add module to register cpufreq on Krait CPUs

 .../devicetree/bindings/arm/msm/qcom,kpss-acc.txt  |  19 +
 .../devicetree/bindings/arm/msm/qcom,kpss-gcc.txt  |  44 +++
 .../devicetree/bindings/clock/qcom,hfpll.txt       |  60 ++++
 .../devicetree/bindings/clock/qcom,krait-cc.txt    |  34 ++
 .../devicetree/bindings/cpufreq/krait-cpufreq.txt  | 363 +++++++++++++++++++
 arch/arm/common/Kconfig                            |   3 +
 arch/arm/common/Makefile                           |   1 +
 arch/arm/common/krait-l2-accessors.c               |  48 +++
 arch/arm/include/asm/krait-l2-accessors.h          |   9 +
 drivers/clk/qcom/Kconfig                           |  28 ++
 drivers/clk/qcom/Makefile                          |   5 +
 drivers/clk/qcom/clk-hfpll.c                       | 244 +++++++++++++
 drivers/clk/qcom/clk-hfpll.h                       |  44 +++
 drivers/clk/qcom/clk-krait.c                       | 126 +++++++
 drivers/clk/qcom/clk-krait.h                       |  40 +++
 drivers/clk/qcom/gcc-ipq806x.c                     |  82 +++++
 drivers/clk/qcom/gcc-msm8960.c                     | 172 +++++++++
 drivers/clk/qcom/hfpll.c                           |  96 +++++
 drivers/clk/qcom/kpss-xcc.c                        |  87 +++++
 drivers/clk/qcom/krait-cc.c                        | 397 +++++++++++++++++++++
 drivers/cpufreq/Kconfig.arm                        |  10 +
 drivers/cpufreq/Makefile                           |   1 +
 drivers/cpufreq/cpufreq-dt-platdev.c               |   5 +
 drivers/cpufreq/qcom-cpufreq.c                     | 201 +++++++++++
 include/dt-bindings/clock/qcom,gcc-msm8960.h       |   2 +
 25 files changed, 2121 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,kpss-gcc.txt
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,hfpll.txt
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,krait-cc.txt
 create mode 100644 Documentation/devicetree/bindings/cpufreq/krait-cpufreq.txt
 create mode 100644 arch/arm/common/krait-l2-accessors.c
 create mode 100644 arch/arm/include/asm/krait-l2-accessors.h
 create mode 100644 drivers/clk/qcom/clk-hfpll.c
 create mode 100644 drivers/clk/qcom/clk-hfpll.h
 create mode 100644 drivers/clk/qcom/clk-krait.c
 create mode 100644 drivers/clk/qcom/clk-krait.h
 create mode 100644 drivers/clk/qcom/hfpll.c
 create mode 100644 drivers/clk/qcom/kpss-xcc.c
 create mode 100644 drivers/clk/qcom/krait-cc.c
 create mode 100644 drivers/cpufreq/qcom-cpufreq.c

Comments

Sudeep Holla June 19, 2018, 1:56 p.m. UTC | #1
On 19/06/18 14:45, Sricharan R wrote:
> From: Stephen Boyd <sboyd@codeaurora.org>
> 
> Register a cpufreq-generic device whenever we detect that a
> "qcom,krait" compatible CPU is present in DT.
> 

Just curious to know how different is this from qcom kryo driver
that was added recently. IIRC even that gets the speedbin from nvmem.
Can they be merged ? I don't see need to have different driver for Krait
and Kryo CPUs when the code is not even remotely related to CPU type.

Sorry if I have missed anything from previous versions, I just happen
to open and looked at this series first time today.
Craig Tatlor June 19, 2018, 3:29 p.m. UTC | #2
The pvs refuse check is incorrect... With downstream it says it isn't
blown and that it is 11, which also happens on upstream if I import it's
efuse reading code from an older revision, or comment out the check.

Also, I'm still getting my issue about clocks above 2,147,483,647hz
however I think this may be related to the division in the hfpll driver
so I'll have a debug around there.

On Tue, Jun 19, 2018 at 07:15:24PM +0530, Sricharan R wrote:
> From: Stephen Boyd <sboyd@codeaurora.org>
> 
> Register a cpufreq-generic device whenever we detect that a
> "qcom,krait" compatible CPU is present in DT.
> 
> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> [Sricharan: updated to use dev_pm_opp_set_prop_name and
> 	    nvmem apis]
> Signed-off-by: Sricharan R <sricharan@codeaurora.org>
> [Thierry Escande: update to add support for opp-supported-hw]
> Signed-off-by: Thierry Escande <thierry.escande@linaro.org>
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
>  [v10] updated to add support for opp-supported-hw given by
>        Thierry Escande <thierry.escande@linaro.org>
> 
>  drivers/cpufreq/Kconfig.arm          |  10 ++
>  drivers/cpufreq/Makefile             |   1 +
>  drivers/cpufreq/cpufreq-dt-platdev.c |   5 +
>  drivers/cpufreq/qcom-cpufreq.c       | 201 +++++++++++++++++++++++++++++++++++
>  4 files changed, 217 insertions(+)
>  create mode 100644 drivers/cpufreq/qcom-cpufreq.c
> 
> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
> index 7f56fe5..87e5d8d 100644
> --- a/drivers/cpufreq/Kconfig.arm
> +++ b/drivers/cpufreq/Kconfig.arm
> @@ -134,6 +134,16 @@ config ARM_OMAP2PLUS_CPUFREQ
>  	depends on ARCH_OMAP2PLUS
>  	default ARCH_OMAP2PLUS
>  
> +config ARM_QCOM_CPUFREQ
> +	bool "CPUfreq driver for the QCOM SoCs with KRAIT processors"
> +	depends on ARCH_QCOM
> +	select PM_OPP
> +	help
> +	  This enables the CPUFreq driver for Qualcomm SoCs with
> +	  KRAIT processors.
> +
> +	  If in doubt, say N.
> +
>  config ARM_S3C_CPUFREQ
>  	bool
>  	help
> diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
> index 8d24ade..c591e1e 100644
> --- a/drivers/cpufreq/Makefile
> +++ b/drivers/cpufreq/Makefile
> @@ -65,6 +65,7 @@ obj-$(CONFIG_MACH_MVEBU_V7)		+= mvebu-cpufreq.o
>  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)		+= qcom-cpufreq.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
> diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
> index 3b585e4..e2e9a99 100644
> --- a/drivers/cpufreq/cpufreq-dt-platdev.c
> +++ b/drivers/cpufreq/cpufreq-dt-platdev.c
> @@ -127,6 +127,11 @@
>  	{ .compatible = "ti,am43", },
>  	{ .compatible = "ti,dra7", },
>  
> +	{ .compatible = "qcom,ipq8064", },
> +	{ .compatible = "qcom,apq8064", },
> +	{ .compatible = "qcom,msm8974", },
> +	{ .compatible = "qcom,msm8960", },
> +
>  	{ }
>  };
>  
> diff --git a/drivers/cpufreq/qcom-cpufreq.c b/drivers/cpufreq/qcom-cpufreq.c
> new file mode 100644
> index 0000000..1d4ab54
> --- /dev/null
> +++ b/drivers/cpufreq/qcom-cpufreq.c
> @@ -0,0 +1,201 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (c) 2018, The Linux Foundation. All rights reserved.
> +
> +#include <linux/cpu.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>
> +
> +static void __init get_krait_bin_format_a(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;
> +		pr_warn("Speed bin: Defaulting to %d\n", *speed);
> +	} else {
> +		pr_info("Speed bin: %d\n", *speed);
> +	}
> +
> +	*pvs = (pte_efuse >> 10) & 0x7;
> +	if (*pvs == 0x7)
> +		*pvs = (pte_efuse >> 13) & 0x7;
> +
> +	if (*pvs == 0x7) {
> +		*pvs = 0;
> +		pr_warn("PVS bin: Defaulting to %d\n", *pvs);
> +	} else {
> +		pr_info("PVS bin: %d\n", *pvs);
> +	}
> +
> +	kfree(buf);
> +}
> +
> +static void __init get_krait_bin_format_b(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;
> +	*speed = pte_efuse & 0x7;
> +
> +	/* 4 bits of PVS are in efuse register bits 31, 8-6. */
> +	*pvs = ((pte_efuse >> 28) & 0x8) | ((pte_efuse >> 6) & 0x7);
> +	*pvs_ver = (pte_efuse >> 4) & 0x3;
> +
> +	switch (redundant_sel) {
> +	case 1:
> +		*speed = (pte_efuse >> 27) & 0xf;
> +		break;
> +	case 2:
> +		*pvs = (pte_efuse >> 27) & 0xf;
> +		break;
> +	}
> +
> +	/* Check SPEED_BIN_BLOW_STATUS */
> +	if (pte_efuse & BIT(3)) {
> +		pr_info("Speed bin: %d\n", *speed);
> +	} else {
> +		pr_warn("Speed bin not set. Defaulting to 0!\n");
> +		*speed = 0;
> +	}
> +
> +	/* Check PVS_BLOW_STATUS */
> +	pte_efuse = *(((u32 *)buf) + 4);
> +	if (pte_efuse) {
> +		pr_info("PVS bin: %d\n", *pvs);
> +	} else {
> +		pr_warn("PVS bin not set. Defaulting to 0!\n");
> +		*pvs = 0;
> +	}
> +
> +	pr_info("PVS version: %d\n", *pvs_ver);
> +	kfree(buf);
> +}
> +
> +static int __init qcom_cpufreq_populate_opps(struct nvmem_cell *pvs_nvmem,
> +					     struct opp_table **tbl1,
> +					     struct opp_table **tbl2)
> +{
> +	int speed = 0, pvs = 0, pvs_ver = 0, cpu, ret;
> +	struct device *cpu_dev;
> +	u8 *buf;
> +	size_t len;
> +	char pvs_name[] = "speedXX-pvsXX-vXX";
> +	u32 hw_version;
> +
> +	buf = nvmem_cell_read(pvs_nvmem, &len);
> +	if (len == 4)
> +		get_krait_bin_format_a(&speed, &pvs, &pvs_ver, pvs_nvmem, buf);
> +	else if (len == 8)
> +		get_krait_bin_format_b(&speed, &pvs, &pvs_ver, pvs_nvmem, buf);
> +	else
> +		pr_warn("Unable to read nvmem data. Defaulting to 0!\n");
> +
> +	snprintf(pvs_name, sizeof(pvs_name), "speed%d-pvs%d-v%d",
> +		 speed, pvs, pvs_ver);
> +
> +	hw_version = (1 << speed);
> +
> +	for (cpu = 0; cpu < num_possible_cpus(); cpu++) {
> +		cpu_dev = get_cpu_device(cpu);
> +		if (!cpu_dev)
> +			return -ENODEV;
> +
> +		tbl1[cpu] = dev_pm_opp_set_prop_name(cpu_dev, pvs_name);
> +		if (IS_ERR(tbl1[cpu])) {
> +			ret = PTR_ERR(tbl1[cpu]);
> +			tbl1[cpu] = 0;
> +			pr_warn("failed to add OPP name %s\n", pvs_name);
> +			return ret;
> +		}
> +
> +		tbl2[cpu] = dev_pm_opp_set_supported_hw(cpu_dev, &hw_version,
> +							1);
> +		if (IS_ERR(tbl2[cpu])) {
> +			ret = PTR_ERR(tbl2[cpu]);
> +			tbl2[cpu] = 0;
> +			pr_warn("failed to set supported hw version\n");
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int __init qcom_cpufreq_driver_init(void)
> +{
> +	struct platform_device *pdev;
> +	struct device *cpu_dev;
> +	struct device_node *np;
> +	struct nvmem_cell *pvs_nvmem;
> +	struct opp_table *tbl1[NR_CPUS] = { NULL }, *tbl2[NR_CPUS] = { NULL };
> +	int ret, cpu = 0;
> +
> +	cpu_dev = get_cpu_device(0);
> +	if (!cpu_dev)
> +		return -ENODEV;
> +
> +	np = dev_pm_opp_of_get_opp_desc_node(cpu_dev);
> +	if (!np)
> +		return -ENOENT;
> +
> +	if (!of_device_is_compatible(np, "operating-points-v2-krait-cpu")) {
> +		ret = -ENOENT;
> +		goto free_np;
> +	}
> +
> +	pvs_nvmem = of_nvmem_cell_get(np, NULL);
> +	if (IS_ERR(pvs_nvmem)) {
> +		dev_err(cpu_dev, "Could not get nvmem cell\n");
> +		ret = PTR_ERR(pvs_nvmem);
> +		goto free_np;
> +	}
> +
> +	ret = qcom_cpufreq_populate_opps(pvs_nvmem, tbl1, tbl2);
> +	if (ret)
> +		goto free_opp_name;
> +
> +	pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
> +	if (IS_ERR(pdev)) {
> +		ret = PTR_ERR(pdev);
> +		goto free_opp_name;
> +	}
> +
> +	of_node_put(np);
> +
> +	return 0;
> +
> +free_opp_name:
> +	while (tbl1[cpu]) {
> +		dev_pm_opp_put_prop_name(tbl1[cpu]);
> +		cpu++;
> +	}
> +
> +	cpu = 0;
> +	while (tbl2[cpu]) {
> +		dev_pm_opp_put_supported_hw(tbl2[cpu]);
> +		cpu++;
> +	}
> +
> +free_np:
> +	of_node_put(np);
> +
> +	return ret;
> +}
> +late_initcall(qcom_cpufreq_driver_init);
> +
> +MODULE_DESCRIPTION("Qualcomm CPUfreq driver");
> +MODULE_AUTHOR("Stephen Boyd <sboyd@codeaurora.org>");
> +MODULE_LICENSE("GPL v2");
> -- 
> 1.9.1
> 
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sricharan Ramabadhran June 20, 2018, 8:48 a.m. UTC | #3
On 2018-06-19 20:59, Craig Tatlor wrote:
> The pvs refuse check is incorrect... With downstream it says it isn't
> blown and that it is 11, which also happens on upstream if I import 
> it's
> efuse reading code from an older revision, or comment out the check.
> 

  ok, atleast on my ipq8064, it works the same. let me check once.

> Also, I'm still getting my issue about clocks above 2,147,483,647hz
> however I think this may be related to the division in the hfpll driver
> so I'll have a debug around there.
> 

   hmm, atleast on ipq8064, it goes till the max frequency. As you said
   it might be to do with the hfpll driver that runs on 8974. I will try 
to test
   on that hardware.

   That said, just realized that i missed a minor comment from Bjorn.
   Will anyway update it.

Regards,
  Sricharan



> On Tue, Jun 19, 2018 at 07:15:24PM +0530, Sricharan R wrote:
>> From: Stephen Boyd <sboyd@codeaurora.org>
>> 
>> Register a cpufreq-generic device whenever we detect that a
>> "qcom,krait" compatible CPU is present in DT.
>> 
>> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
>> [Sricharan: updated to use dev_pm_opp_set_prop_name and
>> 	    nvmem apis]
>> Signed-off-by: Sricharan R <sricharan@codeaurora.org>
>> [Thierry Escande: update to add support for opp-supported-hw]
>> Signed-off-by: Thierry Escande <thierry.escande@linaro.org>
>> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
>> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
>> ---
>>  [v10] updated to add support for opp-supported-hw given by
>>        Thierry Escande <thierry.escande@linaro.org>
>> 
>>  drivers/cpufreq/Kconfig.arm          |  10 ++
>>  drivers/cpufreq/Makefile             |   1 +
>>  drivers/cpufreq/cpufreq-dt-platdev.c |   5 +
>>  drivers/cpufreq/qcom-cpufreq.c       | 201 
>> +++++++++++++++++++++++++++++++++++
>>  4 files changed, 217 insertions(+)
>>  create mode 100644 drivers/cpufreq/qcom-cpufreq.c
>> 
>> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
>> index 7f56fe5..87e5d8d 100644
>> --- a/drivers/cpufreq/Kconfig.arm
>> +++ b/drivers/cpufreq/Kconfig.arm
>> @@ -134,6 +134,16 @@ config ARM_OMAP2PLUS_CPUFREQ
>>  	depends on ARCH_OMAP2PLUS
>>  	default ARCH_OMAP2PLUS
>> 
>> +config ARM_QCOM_CPUFREQ
>> +	bool "CPUfreq driver for the QCOM SoCs with KRAIT processors"
>> +	depends on ARCH_QCOM
>> +	select PM_OPP
>> +	help
>> +	  This enables the CPUFreq driver for Qualcomm SoCs with
>> +	  KRAIT processors.
>> +
>> +	  If in doubt, say N.
>> +
>>  config ARM_S3C_CPUFREQ
>>  	bool
>>  	help
>> diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
>> index 8d24ade..c591e1e 100644
>> --- a/drivers/cpufreq/Makefile
>> +++ b/drivers/cpufreq/Makefile
>> @@ -65,6 +65,7 @@ obj-$(CONFIG_MACH_MVEBU_V7)		+= mvebu-cpufreq.o
>>  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)		+= qcom-cpufreq.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
>> diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c 
>> b/drivers/cpufreq/cpufreq-dt-platdev.c
>> index 3b585e4..e2e9a99 100644
>> --- a/drivers/cpufreq/cpufreq-dt-platdev.c
>> +++ b/drivers/cpufreq/cpufreq-dt-platdev.c
>> @@ -127,6 +127,11 @@
>>  	{ .compatible = "ti,am43", },
>>  	{ .compatible = "ti,dra7", },
>> 
>> +	{ .compatible = "qcom,ipq8064", },
>> +	{ .compatible = "qcom,apq8064", },
>> +	{ .compatible = "qcom,msm8974", },
>> +	{ .compatible = "qcom,msm8960", },
>> +
>>  	{ }
>>  };
>> 
>> diff --git a/drivers/cpufreq/qcom-cpufreq.c 
>> b/drivers/cpufreq/qcom-cpufreq.c
>> new file mode 100644
>> index 0000000..1d4ab54
>> --- /dev/null
>> +++ b/drivers/cpufreq/qcom-cpufreq.c
>> @@ -0,0 +1,201 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +// Copyright (c) 2018, The Linux Foundation. All rights reserved.
>> +
>> +#include <linux/cpu.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>
>> +
>> +static void __init get_krait_bin_format_a(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;
>> +		pr_warn("Speed bin: Defaulting to %d\n", *speed);
>> +	} else {
>> +		pr_info("Speed bin: %d\n", *speed);
>> +	}
>> +
>> +	*pvs = (pte_efuse >> 10) & 0x7;
>> +	if (*pvs == 0x7)
>> +		*pvs = (pte_efuse >> 13) & 0x7;
>> +
>> +	if (*pvs == 0x7) {
>> +		*pvs = 0;
>> +		pr_warn("PVS bin: Defaulting to %d\n", *pvs);
>> +	} else {
>> +		pr_info("PVS bin: %d\n", *pvs);
>> +	}
>> +
>> +	kfree(buf);
>> +}
>> +
>> +static void __init get_krait_bin_format_b(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;
>> +	*speed = pte_efuse & 0x7;
>> +
>> +	/* 4 bits of PVS are in efuse register bits 31, 8-6. */
>> +	*pvs = ((pte_efuse >> 28) & 0x8) | ((pte_efuse >> 6) & 0x7);
>> +	*pvs_ver = (pte_efuse >> 4) & 0x3;
>> +
>> +	switch (redundant_sel) {
>> +	case 1:
>> +		*speed = (pte_efuse >> 27) & 0xf;
>> +		break;
>> +	case 2:
>> +		*pvs = (pte_efuse >> 27) & 0xf;
>> +		break;
>> +	}
>> +
>> +	/* Check SPEED_BIN_BLOW_STATUS */
>> +	if (pte_efuse & BIT(3)) {
>> +		pr_info("Speed bin: %d\n", *speed);
>> +	} else {
>> +		pr_warn("Speed bin not set. Defaulting to 0!\n");
>> +		*speed = 0;
>> +	}
>> +
>> +	/* Check PVS_BLOW_STATUS */
>> +	pte_efuse = *(((u32 *)buf) + 4);
>> +	if (pte_efuse) {
>> +		pr_info("PVS bin: %d\n", *pvs);
>> +	} else {
>> +		pr_warn("PVS bin not set. Defaulting to 0!\n");
>> +		*pvs = 0;
>> +	}
>> +
>> +	pr_info("PVS version: %d\n", *pvs_ver);
>> +	kfree(buf);
>> +}
>> +
>> +static int __init qcom_cpufreq_populate_opps(struct nvmem_cell 
>> *pvs_nvmem,
>> +					     struct opp_table **tbl1,
>> +					     struct opp_table **tbl2)
>> +{
>> +	int speed = 0, pvs = 0, pvs_ver = 0, cpu, ret;
>> +	struct device *cpu_dev;
>> +	u8 *buf;
>> +	size_t len;
>> +	char pvs_name[] = "speedXX-pvsXX-vXX";
>> +	u32 hw_version;
>> +
>> +	buf = nvmem_cell_read(pvs_nvmem, &len);
>> +	if (len == 4)
>> +		get_krait_bin_format_a(&speed, &pvs, &pvs_ver, pvs_nvmem, buf);
>> +	else if (len == 8)
>> +		get_krait_bin_format_b(&speed, &pvs, &pvs_ver, pvs_nvmem, buf);
>> +	else
>> +		pr_warn("Unable to read nvmem data. Defaulting to 0!\n");
>> +
>> +	snprintf(pvs_name, sizeof(pvs_name), "speed%d-pvs%d-v%d",
>> +		 speed, pvs, pvs_ver);
>> +
>> +	hw_version = (1 << speed);
>> +
>> +	for (cpu = 0; cpu < num_possible_cpus(); cpu++) {
>> +		cpu_dev = get_cpu_device(cpu);
>> +		if (!cpu_dev)
>> +			return -ENODEV;
>> +
>> +		tbl1[cpu] = dev_pm_opp_set_prop_name(cpu_dev, pvs_name);
>> +		if (IS_ERR(tbl1[cpu])) {
>> +			ret = PTR_ERR(tbl1[cpu]);
>> +			tbl1[cpu] = 0;
>> +			pr_warn("failed to add OPP name %s\n", pvs_name);
>> +			return ret;
>> +		}
>> +
>> +		tbl2[cpu] = dev_pm_opp_set_supported_hw(cpu_dev, &hw_version,
>> +							1);
>> +		if (IS_ERR(tbl2[cpu])) {
>> +			ret = PTR_ERR(tbl2[cpu]);
>> +			tbl2[cpu] = 0;
>> +			pr_warn("failed to set supported hw version\n");
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int __init qcom_cpufreq_driver_init(void)
>> +{
>> +	struct platform_device *pdev;
>> +	struct device *cpu_dev;
>> +	struct device_node *np;
>> +	struct nvmem_cell *pvs_nvmem;
>> +	struct opp_table *tbl1[NR_CPUS] = { NULL }, *tbl2[NR_CPUS] = { NULL 
>> };
>> +	int ret, cpu = 0;
>> +
>> +	cpu_dev = get_cpu_device(0);
>> +	if (!cpu_dev)
>> +		return -ENODEV;
>> +
>> +	np = dev_pm_opp_of_get_opp_desc_node(cpu_dev);
>> +	if (!np)
>> +		return -ENOENT;
>> +
>> +	if (!of_device_is_compatible(np, "operating-points-v2-krait-cpu")) {
>> +		ret = -ENOENT;
>> +		goto free_np;
>> +	}
>> +
>> +	pvs_nvmem = of_nvmem_cell_get(np, NULL);
>> +	if (IS_ERR(pvs_nvmem)) {
>> +		dev_err(cpu_dev, "Could not get nvmem cell\n");
>> +		ret = PTR_ERR(pvs_nvmem);
>> +		goto free_np;
>> +	}
>> +
>> +	ret = qcom_cpufreq_populate_opps(pvs_nvmem, tbl1, tbl2);
>> +	if (ret)
>> +		goto free_opp_name;
>> +
>> +	pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
>> +	if (IS_ERR(pdev)) {
>> +		ret = PTR_ERR(pdev);
>> +		goto free_opp_name;
>> +	}
>> +
>> +	of_node_put(np);
>> +
>> +	return 0;
>> +
>> +free_opp_name:
>> +	while (tbl1[cpu]) {
>> +		dev_pm_opp_put_prop_name(tbl1[cpu]);
>> +		cpu++;
>> +	}
>> +
>> +	cpu = 0;
>> +	while (tbl2[cpu]) {
>> +		dev_pm_opp_put_supported_hw(tbl2[cpu]);
>> +		cpu++;
>> +	}
>> +
>> +free_np:
>> +	of_node_put(np);
>> +
>> +	return ret;
>> +}
>> +late_initcall(qcom_cpufreq_driver_init);
>> +
>> +MODULE_DESCRIPTION("Qualcomm CPUfreq driver");
>> +MODULE_AUTHOR("Stephen Boyd <sboyd@codeaurora.org>");
>> +MODULE_LICENSE("GPL v2");
>> --
>> 1.9.1
>> 
> --
> To unsubscribe from this list: send the line "unsubscribe 
> linux-arm-msm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sricharan Ramabadhran June 20, 2018, 9:08 a.m. UTC | #4
Hi Sudeep,

>> 
>> Register a cpufreq-generic device whenever we detect that a
>> "qcom,krait" compatible CPU is present in DT.
>> 
> 
> Just curious to know how different is this from qcom kryo driver
> that was added recently. IIRC even that gets the speedbin from nvmem.
> Can they be merged ? I don't see need to have different driver for 
> Krait
> and Kryo CPUs when the code is not even remotely related to CPU type.
> 
> Sorry if I have missed anything from previous versions, I just happen
> to open and looked at this series first time today.

  Correct, having these two merged was pointed out earlier as well by 
Viresh.
  Now that kryo is merged, i will check once and see if they can be 
nicely
  merged.

Regards,
  Sricharan
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thierry Escande June 27, 2018, 9:31 a.m. UTC | #5
Hi Sricharan,

On 19/06/2018 15:45, Sricharan R wrote:
> Sricharan R (2):
>    clk: qcom: Add safe switch hook for krait mux clocks
>    dt-bindings: cpufreq: Document operating-points-v2-krait-cpu
> 
> Stephen Boyd (12):
>    ARM: Add Krait L2 register accessor functions
>    clk: qcom: Add support for High-Frequency PLLs (HFPLLs)
>    clk: qcom: Add HFPLL driver
>    dt-bindings: clock: Document qcom,hfpll
>    clk: qcom: Add MSM8960/APQ8064's HFPLLs
>    clk: qcom: Add IPQ806X's HFPLLs
>    clk: qcom: Add support for Krait clocks
>    clk: qcom: Add KPSS ACC/GCC driver
>    dt-bindings: arm: Document qcom,kpss-gcc
>    clk: qcom: Add Krait clock controller driver
>    dt-bindings: clock: Document qcom,krait-cc
>    cpufreq: Add module to register cpufreq on Krait CPUs

Tested on apq8064 (db600c).

Tested-By: Thierry Escande <thierry.escande@linaro.org>

Best regards,
Thierry

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sricharan Ramabadhran June 28, 2018, 4:29 a.m. UTC | #6
Hi Thierry,

On 6/27/2018 3:01 PM, Thierry Escande wrote:
> Hi Sricharan,
> 
> On 19/06/2018 15:45, Sricharan R wrote:
>> Sricharan R (2):
>>    clk: qcom: Add safe switch hook for krait mux clocks
>>    dt-bindings: cpufreq: Document operating-points-v2-krait-cpu
>>
>> Stephen Boyd (12):
>>    ARM: Add Krait L2 register accessor functions
>>    clk: qcom: Add support for High-Frequency PLLs (HFPLLs)
>>    clk: qcom: Add HFPLL driver
>>    dt-bindings: clock: Document qcom,hfpll
>>    clk: qcom: Add MSM8960/APQ8064's HFPLLs
>>    clk: qcom: Add IPQ806X's HFPLLs
>>    clk: qcom: Add support for Krait clocks
>>    clk: qcom: Add KPSS ACC/GCC driver
>>    dt-bindings: arm: Document qcom,kpss-gcc
>>    clk: qcom: Add Krait clock controller driver
>>    dt-bindings: clock: Document qcom,krait-cc
>>    cpufreq: Add module to register cpufreq on Krait CPUs
> 
> Tested on apq8064 (db600c).
> 
> Tested-By: Thierry Escande <thierry.escande@linaro.org>
> 

  Thanks for testing this !!
  I Will try to merge the kryo cpu-freq and this one if that looks neat.

Regards,
 Sricharan