From: Peng Fan <[email protected]>
V2:
Per Stephen's comments, I drop the cpuv2 clk code, and find another
solution to change ARM clk
Included get_intermediate/target_intermedate for cpufreq-dt
Add i.MX7ULP intermedidate implementation.
Per Fabio's comments, disallow HSRUN when LDO enabled.
Add dt-bindings and pmc node
V1:
https://patchwork.kernel.org/patch/11364609/
This patchset aims to use cpufreq-dt for i.MX7ULP to avoid
plaform specific cpufreq driver. i.MX7ULP has some specicial
requirements to change ARM core clock, see patch 11/13,
"cpufreq: imx-cpufreq-dt: support i.MX7ULP"
Patch [1,2]/13: add pmc bindings and node. We need read pmc registers
to get system info.
Patch [3-6]/13: i.MX7ULP clk pfd/pll code change to make sure to get the
expected pfd output clk. For RUN/HSRUN clock, we use API
imx_clk_hw_cpu to make sure RUN or HSRUN could not shutdown clock output.
Patch [7-8]/13: Make sure we could run into HSRUN mode and not when LDO
enabled.
Patch 9/13: let cpufred-dt could have get_intermediate/target_intermediate
hooks to allow platform specific freq set.
Patch [10-12]/13: i.MX7ULP cpufreq support
Patch 13/13: Test dts, should not apply.
For rpmsg/vitio part, I have posted patchset, if you wanna rpmsg regulator:
https://patchwork.kernel.org/cover/11390481/
Anson Huang (1):
clk: imx: Fix division by zero warning on pfdv2
Peng Fan (13):
dt-bindings: fsl: add i.MX7ULP PMC binding doc
ARM: dts: imx7ulp: add pmc node
clk: imx: pfdv2: switch to use determine_rate
clk: imx: pfdv2: determine best parent rate
clk: imx: pllv4: use prepare/unprepare
clk: imx7ulp: make it easy to change ARM core clk
ARM: imx: imx7ulp: support HSRUN mode
ARM: imx: cpuidle-imx7ulp: Stop mode disallowed when HSRUN
cpufreq: dt: Allow platform specific intermediate callbacks
cpufreq: Add i.MX7ULP to cpufreq-dt-platdev blacklist
cpufreq: imx-cpufreq-dt: support i.MX7ULP
ARM: imx7ulp: enable cpufreq
[Do not Apply] ARM: dts: imx7ulp: add cpu OPP points
.../bindings/arm/freescale/imx7ulp_pmc.yaml | 32 +++++++++
arch/arm/boot/dts/imx7ulp.dtsi | 38 ++++++++++
arch/arm/mach-imx/common.h | 1 +
arch/arm/mach-imx/cpuidle-imx7ulp.c | 14 +++-
arch/arm/mach-imx/mach-imx7ulp.c | 3 +
arch/arm/mach-imx/pm-imx7ulp.c | 25 +++++++
drivers/clk/imx/clk-imx7ulp.c | 6 +-
drivers/clk/imx/clk-pfdv2.c | 61 +++++++++++-----
drivers/clk/imx/clk-pllv4.c | 12 ++--
drivers/cpufreq/cpufreq-dt-platdev.c | 1 +
drivers/cpufreq/cpufreq-dt.c | 4 ++
drivers/cpufreq/cpufreq-dt.h | 4 ++
drivers/cpufreq/imx-cpufreq-dt.c | 83 +++++++++++++++++++++-
include/dt-bindings/clock/imx7ulp-clock.h | 5 +-
14 files changed, 257 insertions(+), 32 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/freescale/imx7ulp_pmc.yaml
--
2.16.4
From: Peng Fan <[email protected]>
Add i.MX7ULP pmc0/1 node
Signed-off-by: Peng Fan <[email protected]>
---
arch/arm/boot/dts/imx7ulp.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm/boot/dts/imx7ulp.dtsi b/arch/arm/boot/dts/imx7ulp.dtsi
index ab91c98f2124..32c218123662 100644
--- a/arch/arm/boot/dts/imx7ulp.dtsi
+++ b/arch/arm/boot/dts/imx7ulp.dtsi
@@ -286,6 +286,11 @@
assigned-clock-parents = <&scg1 IMX7ULP_CLK_SOSC_BUS_CLK>;
};
+ pmc1: pmc1@40400000 {
+ compatible = "fsl,imx7ulp-pmc1";
+ reg = <0x40400000 0x1000>;
+ };
+
smc1: clock-controller@40410000 {
compatible = "fsl,imx7ulp-smc1";
reg = <0x40410000 0x1000>;
@@ -447,6 +452,11 @@
reg = <0x41080000 0x80000>;
ranges;
+ pmc0: pmc0@410a1000 {
+ compatible = "fsl,imx7ulp-pmc0";
+ reg = <0x410a1000 0x1000>;
+ };
+
sim: sim@410a3000 {
compatible = "fsl,imx7ulp-sim", "syscon";
reg = <0x410a3000 0x1000>;
--
2.16.4
From: Anson Huang <[email protected]>
Fix below division by zero warning:
[ 3.176443] Division by zero in kernel.
[ 3.181809] CPU: 0 PID: 88 Comm: kworker/0:2 Not tainted 5.3.0-rc2-next-20190730-63758-ge08da51-dirty #124
[ 3.191817] Hardware name: Freescale i.MX7ULP (Device Tree)
[ 3.197821] Workqueue: events dbs_work_handler
[ 3.202849] [<c01127d8>] (unwind_backtrace) from [<c010cd80>] (show_stack+0x10/0x14)
[ 3.211058] [<c010cd80>] (show_stack) from [<c0c77e68>] (dump_stack+0xd8/0x110)
[ 3.218820] [<c0c77e68>] (dump_stack) from [<c0c753c0>] (Ldiv0_64+0x8/0x18)
[ 3.226263] [<c0c753c0>] (Ldiv0_64) from [<c05984b4>] (clk_pfdv2_set_rate+0x54/0xac)
[ 3.234487] [<c05984b4>] (clk_pfdv2_set_rate) from [<c059192c>] (clk_change_rate+0x1a4/0x698)
[ 3.243468] [<c059192c>] (clk_change_rate) from [<c0591a08>] (clk_change_rate+0x280/0x698)
[ 3.252180] [<c0591a08>] (clk_change_rate) from [<c0591fc0>] (clk_core_set_rate_nolock+0x1a0/0x278)
[ 3.261679] [<c0591fc0>] (clk_core_set_rate_nolock) from [<c05920c8>] (clk_set_rate+0x30/0x64)
[ 3.270743] [<c05920c8>] (clk_set_rate) from [<c089cb88>] (imx7ulp_set_target+0x184/0x2a4)
[ 3.279501] [<c089cb88>] (imx7ulp_set_target) from [<c0896358>] (__cpufreq_driver_target+0x188/0x514)
[ 3.289196] [<c0896358>] (__cpufreq_driver_target) from [<c0899b0c>] (od_dbs_update+0x130/0x15c)
[ 3.298438] [<c0899b0c>] (od_dbs_update) from [<c089a5d0>] (dbs_work_handler+0x2c/0x5c)
[ 3.306914] [<c089a5d0>] (dbs_work_handler) from [<c0156858>] (process_one_work+0x2ac/0x704)
[ 3.315826] [<c0156858>] (process_one_work) from [<c0156cdc>] (worker_thread+0x2c/0x574)
[ 3.324404] [<c0156cdc>] (worker_thread) from [<c015cfe8>] (kthread+0x134/0x148)
[ 3.332278] [<c015cfe8>] (kthread) from [<c01010b4>] (ret_from_fork+0x14/0x20)
[ 3.339858] Exception stack(0xe82d5fb0 to 0xe82d5ff8)
[ 3.345314] 5fa0: 00000000 00000000 00000000 00000000
[ 3.353926] 5fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 3.362519] 5fe0: 00000000 00000000 00000000 00000000 00000013 00000000
Signed-off-by: Anson Huang <[email protected]>
Signed-off-by: Peng Fan <[email protected]>
---
drivers/clk/imx/clk-pfdv2.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/clk/imx/clk-pfdv2.c b/drivers/clk/imx/clk-pfdv2.c
index de93ce73101b..f8707278aad9 100644
--- a/drivers/clk/imx/clk-pfdv2.c
+++ b/drivers/clk/imx/clk-pfdv2.c
@@ -139,6 +139,12 @@ static int clk_pfdv2_set_rate(struct clk_hw *hw, unsigned long rate,
u32 val;
u8 frac;
+ if (!rate)
+ return -EINVAL;
+
+ /* PFD can NOT change rate without gating */
+ WARN_ON(clk_pfdv2_is_enabled(hw));
+
tmp = tmp * 18 + rate / 2;
do_div(tmp, rate);
frac = tmp;
--
2.16.4
From: Peng Fan <[email protected]>
Per clk_ops, compared with round_rate, determine_rate could optionally
support the parent clock that should be used to provide the clock rate.
In this patch, the parent clock is just parent->rate as round_rate.
The following patch will calculate the best parent clock.
Signed-off-by: Peng Fan <[email protected]>
---
drivers/clk/imx/clk-pfdv2.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/drivers/clk/imx/clk-pfdv2.c b/drivers/clk/imx/clk-pfdv2.c
index f8707278aad9..28b5f208ced9 100644
--- a/drivers/clk/imx/clk-pfdv2.c
+++ b/drivers/clk/imx/clk-pfdv2.c
@@ -98,10 +98,11 @@ static unsigned long clk_pfdv2_recalc_rate(struct clk_hw *hw,
return tmp;
}
-static long clk_pfdv2_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
+static int clk_pfdv2_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
- u64 tmp = *prate;
+ u64 tmp = req->best_parent_rate;
+ u64 rate = req->rate;
u8 frac;
tmp = tmp * 18 + rate / 2;
@@ -113,11 +114,13 @@ static long clk_pfdv2_round_rate(struct clk_hw *hw, unsigned long rate,
else if (frac > 35)
frac = 35;
- tmp = *prate;
+ tmp = req->best_parent_rate;
tmp *= 18;
do_div(tmp, frac);
- return tmp;
+ req->rate = tmp;
+
+ return 0;
}
static int clk_pfdv2_is_enabled(struct clk_hw *hw)
@@ -167,7 +170,7 @@ static const struct clk_ops clk_pfdv2_ops = {
.enable = clk_pfdv2_enable,
.disable = clk_pfdv2_disable,
.recalc_rate = clk_pfdv2_recalc_rate,
- .round_rate = clk_pfdv2_round_rate,
+ .determine_rate = clk_pfdv2_determine_rate,
.set_rate = clk_pfdv2_set_rate,
.is_enabled = clk_pfdv2_is_enabled,
};
--
2.16.4
From: Peng Fan <[email protected]>
It is not good to use enable/disable for PLLv4 which needs time to
lock, because enable/disable is expected to be able run in
interrupt context. So use prepare/unprepare.
Signed-off-by: Peng Fan <[email protected]>
---
drivers/clk/imx/clk-pllv4.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/clk/imx/clk-pllv4.c b/drivers/clk/imx/clk-pllv4.c
index f51a800c268c..a49450431855 100644
--- a/drivers/clk/imx/clk-pllv4.c
+++ b/drivers/clk/imx/clk-pllv4.c
@@ -54,7 +54,7 @@ static inline int clk_pllv4_wait_lock(struct clk_pllv4 *pll)
csr, csr & PLL_VLD, 0, LOCK_TIMEOUT_US);
}
-static int clk_pllv4_is_enabled(struct clk_hw *hw)
+static int clk_pllv4_is_prepared(struct clk_hw *hw)
{
struct clk_pllv4 *pll = to_clk_pllv4(hw);
@@ -175,7 +175,7 @@ static int clk_pllv4_set_rate(struct clk_hw *hw, unsigned long rate,
return 0;
}
-static int clk_pllv4_enable(struct clk_hw *hw)
+static int clk_pllv4_prepare(struct clk_hw *hw)
{
u32 val;
struct clk_pllv4 *pll = to_clk_pllv4(hw);
@@ -187,7 +187,7 @@ static int clk_pllv4_enable(struct clk_hw *hw)
return clk_pllv4_wait_lock(pll);
}
-static void clk_pllv4_disable(struct clk_hw *hw)
+static void clk_pllv4_unprepare(struct clk_hw *hw)
{
u32 val;
struct clk_pllv4 *pll = to_clk_pllv4(hw);
@@ -201,9 +201,9 @@ static const struct clk_ops clk_pllv4_ops = {
.recalc_rate = clk_pllv4_recalc_rate,
.round_rate = clk_pllv4_round_rate,
.set_rate = clk_pllv4_set_rate,
- .enable = clk_pllv4_enable,
- .disable = clk_pllv4_disable,
- .is_enabled = clk_pllv4_is_enabled,
+ .prepare = clk_pllv4_prepare,
+ .unprepare = clk_pllv4_unprepare,
+ .is_prepared = clk_pllv4_is_prepared,
};
struct clk_hw *imx_clk_hw_pllv4(const char *name, const char *parent_name,
--
2.16.4
From: Peng Fan <[email protected]>
Configure PMPROT to let ARM core could run into HSRUN mode.
In LDO-enabled mode, HSRUN mode is not allowed, so add a check before
configure PMPROT.
Signed-off-by: Peng Fan <[email protected]>
---
arch/arm/mach-imx/pm-imx7ulp.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/arch/arm/mach-imx/pm-imx7ulp.c b/arch/arm/mach-imx/pm-imx7ulp.c
index 2e756d8191fa..393faf1e8382 100644
--- a/arch/arm/mach-imx/pm-imx7ulp.c
+++ b/arch/arm/mach-imx/pm-imx7ulp.c
@@ -11,6 +11,10 @@
#include "common.h"
+#define PMC0_CTRL 0x28
+#define BM_CTRL_LDOEN BIT(31)
+
+#define SMC_PMPROT 0x8
#define SMC_PMCTRL 0x10
#define BP_PMCTRL_PSTOPO 16
#define PSTOPO_PSTOP3 0x3
@@ -25,7 +29,10 @@
#define BM_PMCTRL_RUNM (3 << BP_PMCTRL_RUNM)
#define BM_PMCTRL_STOPM (7 << BP_PMCTRL_STOPM)
+#define BM_PMPROT_AHSRUN BIT(7)
+
static void __iomem *smc1_base;
+static void __iomem *pmc0_base;
int imx7ulp_set_lpm(enum ulp_cpu_pwr_mode mode)
{
@@ -65,5 +72,13 @@ void __init imx7ulp_pm_init(void)
of_node_put(np);
WARN_ON(!smc1_base);
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-pmc0");
+ pmc0_base = of_iomap(np, 0);
+ WARN_ON(!pmc0_base);
+ of_node_put(np);
+
+ if (!(readl_relaxed(pmc0_base + PMC0_CTRL) & BM_CTRL_LDOEN))
+ writel_relaxed(BM_PMPROT_AHSRUN, smc1_base + SMC_PMPROT);
+
imx7ulp_set_lpm(ULP_PM_RUN);
}
--
2.16.4
From: Peng Fan <[email protected]>
Add i.MX7ULP Power Management Controller binding doc
Signed-off-by: Peng Fan <[email protected]>
---
.../bindings/arm/freescale/imx7ulp_pmc.yaml | 32 ++++++++++++++++++++++
1 file changed, 32 insertions(+)
create mode 100644 Documentation/devicetree/bindings/arm/freescale/imx7ulp_pmc.yaml
diff --git a/Documentation/devicetree/bindings/arm/freescale/imx7ulp_pmc.yaml b/Documentation/devicetree/bindings/arm/freescale/imx7ulp_pmc.yaml
new file mode 100644
index 000000000000..992a5ea29d39
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/freescale/imx7ulp_pmc.yaml
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/bindings/arm/freescale/imx7ulp_pmc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: i.MX7ULP Power Management Controller(PMC) Device Tree Bindings
+
+maintainers:
+ - Peng Fan <[email protected]>
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - fsl,imx7ulp-pmc0
+ - fsl,imx7ulp-pmc1
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+examples:
+ - |
+ pmc0: pmc0@410a1000 {
+ compatible = "fsl,imx7ulp-pmc0";
+ reg = <0x410a1000 0x1000>;
+ };
+...
--
2.16.4
From: Peng Fan <[email protected]>
Add i.MX7ULP to cpufreq-dt-platdev blacklist.
Signed-off-by: Peng Fan <[email protected]>
---
drivers/cpufreq/cpufreq-dt-platdev.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index f2ae9cd455c1..648dffdbafa5 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -105,6 +105,7 @@ static const struct of_device_id blacklist[] __initconst = {
{ .compatible = "calxeda,highbank", },
{ .compatible = "calxeda,ecx-2000", },
+ { .compatible = "fsl,imx7ulp", },
{ .compatible = "fsl,imx7d", },
{ .compatible = "fsl,imx8mq", },
{ .compatible = "fsl,imx8mm", },
--
2.16.4
From: Peng Fan <[email protected]>
pfdv2 is only used in i.MX7ULP. To get best pfd output, the i.MX7ULP
Datasheet defines two best PLL rate and pfd frac.
Per Datasheel
All PLLs on i.MX 7ULP either have VCO base frequency of
480 MHz or 528 MHz. So when determine best rate, we also
determine best parent rate which could match the requirement.
For some reason the current parent might not be 480MHz or 528MHz,
so we still take current parent rate as a choice.
And we also enable flag CLK_SET_RATE_PARENT to let parent rate
to be configured.
Signed-off-by: Peng Fan <[email protected]>
---
drivers/clk/imx/clk-pfdv2.c | 50 ++++++++++++++++++++++++++++++---------------
1 file changed, 33 insertions(+), 17 deletions(-)
diff --git a/drivers/clk/imx/clk-pfdv2.c b/drivers/clk/imx/clk-pfdv2.c
index 28b5f208ced9..78e1f7641aaa 100644
--- a/drivers/clk/imx/clk-pfdv2.c
+++ b/drivers/clk/imx/clk-pfdv2.c
@@ -101,24 +101,40 @@ static unsigned long clk_pfdv2_recalc_rate(struct clk_hw *hw,
static int clk_pfdv2_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
- u64 tmp = req->best_parent_rate;
- u64 rate = req->rate;
+ unsigned long parent_rates[] = {
+ 480000000,
+ 528000000,
+ req->best_parent_rate
+ };
+ unsigned long best_rate = -1UL, rate = req->rate;
+ unsigned long best_parent_rate = req->best_parent_rate;
+ u64 tmp;
u8 frac;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(parent_rates); i++) {
+ tmp = parent_rates[i];
+ tmp = tmp * 18 + rate / 2;
+ do_div(tmp, rate);
+ frac = tmp;
+
+ if (frac < 12)
+ frac = 12;
+ else if (frac > 35)
+ frac = 35;
+
+ tmp = parent_rates[i];
+ tmp *= 18;
+ do_div(tmp, frac);
+
+ if (abs(tmp - req->rate) < abs(best_rate - req->rate)) {
+ best_rate = tmp;
+ best_parent_rate = parent_rates[i];
+ }
+ }
- tmp = tmp * 18 + rate / 2;
- do_div(tmp, rate);
- frac = tmp;
-
- if (frac < 12)
- frac = 12;
- else if (frac > 35)
- frac = 35;
-
- tmp = req->best_parent_rate;
- tmp *= 18;
- do_div(tmp, frac);
-
- req->rate = tmp;
+ req->best_parent_rate = best_parent_rate;
+ req->rate = best_rate;
return 0;
}
@@ -198,7 +214,7 @@ struct clk_hw *imx_clk_hw_pfdv2(const char *name, const char *parent_name,
init.ops = &clk_pfdv2_ops;
init.parent_names = &parent_name;
init.num_parents = 1;
- init.flags = CLK_SET_RATE_GATE;
+ init.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT;
pfd->hw.init = &init;
--
2.16.4
From: Peng Fan <[email protected]>
ARM clk could only source from divcore or hsrun_divcore.
However when ARM core is running normaly, whether divcore or
hwrun_divcore will finally source from SPLL_PFD0. However SPLL_PFD0
is marked with CLK_SET_GATE, so we need to disable SPLL_PFD0, when
configure the rate. So add CORE and HSRUN_CORE virtual clk to make it
easy to configure the clk using imx_clk_hw_cpu API.
Since CORE and HSRUN_CORE already marked with CLK_IS_CRITICAL, no
need to set ARM as CLK_IS_CRITICAL. And when set the rate of ARM clk,
prograting it the parent with CLK_SET_RATE_PARENT will finally set
the SPLL_PFD0 clk.
Signed-off-by: Peng Fan <[email protected]>
---
drivers/clk/imx/clk-imx7ulp.c | 6 ++++--
include/dt-bindings/clock/imx7ulp-clock.h | 5 ++++-
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/imx/clk-imx7ulp.c b/drivers/clk/imx/clk-imx7ulp.c
index 3710aa0dee9b..634c0b6636b0 100644
--- a/drivers/clk/imx/clk-imx7ulp.c
+++ b/drivers/clk/imx/clk-imx7ulp.c
@@ -29,7 +29,7 @@ static const char * const ddr_sels[] = { "apll_pfd_sel", "dummy", "dummy", "dum
static const char * const nic_sels[] = { "firc", "ddr_clk", };
static const char * const periph_plat_sels[] = { "dummy", "nic1_bus_clk", "nic1_clk", "ddr_clk", "apll_pfd2", "apll_pfd1", "apll_pfd0", "upll", };
static const char * const periph_bus_sels[] = { "dummy", "sosc_bus_clk", "dummy", "firc_bus_clk", "rosc", "nic1_bus_clk", "nic1_clk", "spll_bus_clk", };
-static const char * const arm_sels[] = { "divcore", "dummy", "dummy", "hsrun_divcore", };
+static const char * const arm_sels[] = { "core", "dummy", "dummy", "hsrun_core", };
/* used by sosc/sirc/firc/ddr/spll/apll dividers */
static const struct clk_div_table ulp_div_table[] = {
@@ -121,7 +121,9 @@ static void __init imx7ulp_clk_scg1_init(struct device_node *np)
hws[IMX7ULP_CLK_DDR_SEL] = imx_clk_hw_mux_flags("ddr_sel", base + 0x30, 24, 2, ddr_sels, ARRAY_SIZE(ddr_sels), CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE);
hws[IMX7ULP_CLK_CORE_DIV] = imx_clk_hw_divider_flags("divcore", "scs_sel", base + 0x14, 16, 4, CLK_SET_RATE_PARENT);
+ hws[IMX7ULP_CLK_CORE] = imx_clk_hw_cpu("core", "divcore", hws[IMX7ULP_CLK_CORE_DIV]->clk, hws[IMX7ULP_CLK_SYS_SEL]->clk, hws[IMX7ULP_CLK_SPLL_SEL]->clk, hws[IMX7ULP_CLK_FIRC]->clk);
hws[IMX7ULP_CLK_HSRUN_CORE_DIV] = imx_clk_hw_divider_flags("hsrun_divcore", "hsrun_scs_sel", base + 0x1c, 16, 4, CLK_SET_RATE_PARENT);
+ hws[IMX7ULP_CLK_HSRUN_CORE] = imx_clk_hw_cpu("hsrun_core", "hsrun_divcore", hws[IMX7ULP_CLK_HSRUN_CORE_DIV]->clk, hws[IMX7ULP_CLK_HSRUN_SYS_SEL]->clk, hws[IMX7ULP_CLK_SPLL_SEL]->clk, hws[IMX7ULP_CLK_FIRC]->clk);
hws[IMX7ULP_CLK_DDR_DIV] = imx_clk_hw_divider_gate("ddr_clk", "ddr_sel", CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, base + 0x30, 0, 3,
0, ulp_div_table, &imx_ccm_lock);
@@ -270,7 +272,7 @@ static void __init imx7ulp_clk_smc1_init(struct device_node *np)
base = of_iomap(np, 0);
WARN_ON(!base);
- hws[IMX7ULP_CLK_ARM] = imx_clk_hw_mux_flags("arm", base + 0x10, 8, 2, arm_sels, ARRAY_SIZE(arm_sels), CLK_IS_CRITICAL);
+ hws[IMX7ULP_CLK_ARM] = imx_clk_hw_mux_flags("arm", base + 0x10, 8, 2, arm_sels, ARRAY_SIZE(arm_sels), CLK_SET_RATE_PARENT);
imx_check_clk_hws(hws, clk_data->num);
diff --git a/include/dt-bindings/clock/imx7ulp-clock.h b/include/dt-bindings/clock/imx7ulp-clock.h
index 38145bdcd975..b58370d146e2 100644
--- a/include/dt-bindings/clock/imx7ulp-clock.h
+++ b/include/dt-bindings/clock/imx7ulp-clock.h
@@ -58,7 +58,10 @@
#define IMX7ULP_CLK_HSRUN_SYS_SEL 44
#define IMX7ULP_CLK_HSRUN_CORE_DIV 45
-#define IMX7ULP_CLK_SCG1_END 46
+#define IMX7ULP_CLK_CORE 46
+#define IMX7ULP_CLK_HSRUN_CORE 47
+
+#define IMX7ULP_CLK_SCG1_END 48
/* PCC2 */
#define IMX7ULP_CLK_DMA1 0
--
2.16.4
From: Peng Fan <[email protected]>
When cpu runs in HSRUN mode, cpuidle is not allowed to run into
Stop mode. So add imx7ulp_get_mode to get thr cpu run mode,
and use WAIT mode instead, when cpu in HSRUN mode.
Signed-off-by: Peng Fan <[email protected]>
---
arch/arm/mach-imx/common.h | 1 +
arch/arm/mach-imx/cpuidle-imx7ulp.c | 14 +++++++++++---
arch/arm/mach-imx/pm-imx7ulp.c | 10 ++++++++++
3 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index 5aa5796cff0e..db542da4fe67 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -104,6 +104,7 @@ void imx6_set_int_mem_clk_lpm(bool enable);
void imx6sl_set_wait_clk(bool enter);
int imx_mmdc_get_ddr_type(void);
int imx7ulp_set_lpm(enum ulp_cpu_pwr_mode mode);
+u32 imx7ulp_get_mode(void);
void imx_cpu_die(unsigned int cpu);
int imx_cpu_kill(unsigned int cpu);
diff --git a/arch/arm/mach-imx/cpuidle-imx7ulp.c b/arch/arm/mach-imx/cpuidle-imx7ulp.c
index ca86c967d19e..e7009d10b331 100644
--- a/arch/arm/mach-imx/cpuidle-imx7ulp.c
+++ b/arch/arm/mach-imx/cpuidle-imx7ulp.c
@@ -15,10 +15,18 @@
static int imx7ulp_enter_wait(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
- if (index == 1)
+ u32 mode;
+
+ if (index == 1) {
imx7ulp_set_lpm(ULP_PM_WAIT);
- else
- imx7ulp_set_lpm(ULP_PM_STOP);
+ } else {
+ mode = imx7ulp_get_mode();
+
+ if (mode == 3)
+ imx7ulp_set_lpm(ULP_PM_WAIT);
+ else
+ imx7ulp_set_lpm(ULP_PM_STOP);
+ }
cpu_do_idle();
diff --git a/arch/arm/mach-imx/pm-imx7ulp.c b/arch/arm/mach-imx/pm-imx7ulp.c
index 393faf1e8382..1410ccfc71bd 100644
--- a/arch/arm/mach-imx/pm-imx7ulp.c
+++ b/arch/arm/mach-imx/pm-imx7ulp.c
@@ -63,6 +63,16 @@ int imx7ulp_set_lpm(enum ulp_cpu_pwr_mode mode)
return 0;
}
+u32 imx7ulp_get_mode(void)
+{
+ u32 mode;
+
+ mode = readl_relaxed(smc1_base + SMC_PMCTRL) & BM_PMCTRL_RUNM;
+ mode >>= BP_PMCTRL_RUNM;
+
+ return mode;
+}
+
void __init imx7ulp_pm_init(void)
{
struct device_node *np;
--
2.16.4
From: Peng Fan <[email protected]>
i.MX7ULP's ARM core clock design is totally different compared
with i.MX7D/8M SoCs which supported by imx-cpufreq-dt. It needs
get_intermediate and target_intermedate to configure clk MUX ready,
before let OPP configure ARM core clk.
|---FIRC
|------RUN---...---SCS(MUX2) --------|
ARM --(MUX1) |---SPLL_PFD0(CLK_SET_RATE_GATE)
|------HSRUN--...--HSRUN_SCS(MUX3)---|
|---SRIC
FIRC is step clk, SPLL_PFD0 is the normal clk driving ARM core.
MUX2 and MUX3 share same inputs. So if MUX2/MUX3 both sources from
SPLL_PFD0, both MUXes will lose input when configure SPLL_PFD0.
So the target_intermediate will configure MUX2/MUX3 to FIRC, to avoid
ARM core lose clk when configure SPLL_PFD0.
Signed-off-by: Peng Fan <[email protected]>
---
drivers/cpufreq/imx-cpufreq-dt.c | 83 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 81 insertions(+), 2 deletions(-)
diff --git a/drivers/cpufreq/imx-cpufreq-dt.c b/drivers/cpufreq/imx-cpufreq-dt.c
index 6cb8193421ea..504dd3ac1170 100644
--- a/drivers/cpufreq/imx-cpufreq-dt.c
+++ b/drivers/cpufreq/imx-cpufreq-dt.c
@@ -3,7 +3,9 @@
* Copyright 2019 NXP
*/
+#include <linux/clk.h>
#include <linux/cpu.h>
+#include <linux/cpufreq.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -12,25 +14,100 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
+#include <linux/regulator/consumer.h>
#include <linux/slab.h>
+#include "cpufreq-dt.h"
+
#define OCOTP_CFG3_SPEED_GRADE_SHIFT 8
#define OCOTP_CFG3_SPEED_GRADE_MASK (0x3 << 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 IMX7ULP_MAX_RUN_FREQ 528000
+
/* cpufreq-dt device registered by imx-cpufreq-dt */
static struct platform_device *cpufreq_dt_pdev;
static struct opp_table *cpufreq_opp_table;
+static struct device *cpu_dev;
+
+enum IMX7ULP_CPUFREQ_CLKS {
+ ARM,
+ CORE,
+ SCS_SEL,
+ HSRUN_CORE,
+ HSRUN_SCS_SEL,
+ FIRC,
+};
+
+static struct clk_bulk_data imx7ulp_clks[] = {
+ { .id = "arm" },
+ { .id = "core" },
+ { .id = "scs_sel" },
+ { .id = "hsrun_core" },
+ { .id = "hsrun_scs_sel" },
+ { .id = "firc" },
+};
+
+static unsigned int imx7ulp_get_intermediate(struct cpufreq_policy *policy,
+ unsigned int index)
+{
+ return clk_get_rate(imx7ulp_clks[FIRC].clk);
+}
+
+static int imx7ulp_target_intermediate(struct cpufreq_policy *policy,
+ unsigned int index)
+{
+ unsigned int newfreq = policy->freq_table[index].frequency;
+
+ clk_set_parent(imx7ulp_clks[SCS_SEL].clk, imx7ulp_clks[FIRC].clk);
+ clk_set_parent(imx7ulp_clks[HSRUN_SCS_SEL].clk, imx7ulp_clks[FIRC].clk);
+
+ if (newfreq > IMX7ULP_MAX_RUN_FREQ)
+ clk_set_parent(imx7ulp_clks[ARM].clk,
+ imx7ulp_clks[HSRUN_CORE].clk);
+ else
+ clk_set_parent(imx7ulp_clks[ARM].clk, imx7ulp_clks[CORE].clk);
+
+ return 0;
+}
+
+static struct cpufreq_dt_platform_data imx7ulp_data = {
+ .target_intermediate = imx7ulp_target_intermediate,
+ .get_intermediate = imx7ulp_get_intermediate,
+};
static int imx_cpufreq_dt_probe(struct platform_device *pdev)
{
- struct device *cpu_dev = get_cpu_device(0);
+ struct platform_device *dt_pdev;
u32 cell_value, supported_hw[2];
int speed_grade, mkt_segment;
int ret;
+ cpu_dev = get_cpu_device(0);
+
+ if (of_machine_is_compatible("fsl,imx7ulp")) {
+ ret = clk_bulk_get(cpu_dev, ARRAY_SIZE(imx7ulp_clks),
+ imx7ulp_clks);
+ if (ret)
+ return ret;
+
+ dt_pdev = platform_device_register_data(NULL, "cpufreq-dt",
+ -1, &imx7ulp_data,
+ sizeof(imx7ulp_data));
+ if (IS_ERR(dt_pdev)) {
+ clk_bulk_put(ARRAY_SIZE(imx7ulp_clks), imx7ulp_clks);
+ ret = PTR_ERR(dt_pdev);
+ dev_err(&pdev->dev, "Failed to register cpufreq-dt: %d\n", ret);
+ return ret;
+ }
+
+ cpufreq_dt_pdev = dt_pdev;
+
+ return 0;
+ }
+
ret = nvmem_cell_read_u32(cpu_dev, "speed_grade", &cell_value);
if (ret)
return ret;
@@ -87,7 +164,9 @@ static int imx_cpufreq_dt_probe(struct platform_device *pdev)
static int imx_cpufreq_dt_remove(struct platform_device *pdev)
{
platform_device_unregister(cpufreq_dt_pdev);
- dev_pm_opp_put_supported_hw(cpufreq_opp_table);
+ if (!of_machine_is_compatible("fsl,imx7ulp")) {
+ dev_pm_opp_put_supported_hw(cpufreq_opp_table);
+ }
return 0;
}
--
2.16.4
From: Peng Fan <[email protected]>
Platforms may need to implement platform specific get_intermediate and
target_intermediate hooks.
Update cpufreq-dt driver's platform data to contain those for such
platforms.
Signed-off-by: Peng Fan <[email protected]>
---
drivers/cpufreq/cpufreq-dt.c | 4 ++++
drivers/cpufreq/cpufreq-dt.h | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index d2b5f062a07b..26fe8dfb9ce6 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -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);
diff --git a/drivers/cpufreq/cpufreq-dt.h b/drivers/cpufreq/cpufreq-dt.h
index a5a45b547d0b..28c8af7ec5ef 100644
--- a/drivers/cpufreq/cpufreq-dt.h
+++ b/drivers/cpufreq/cpufreq-dt.h
@@ -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);
};
--
2.16.4
From: Peng Fan <[email protected]>
Add cpu OPP points. voltage part not ready, only clk freq now.
Signed-off-by: Peng Fan <[email protected]>
---
arch/arm/boot/dts/imx7ulp.dtsi | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/arch/arm/boot/dts/imx7ulp.dtsi b/arch/arm/boot/dts/imx7ulp.dtsi
index 32c218123662..a5bf6605f729 100644
--- a/arch/arm/boot/dts/imx7ulp.dtsi
+++ b/arch/arm/boot/dts/imx7ulp.dtsi
@@ -41,6 +41,34 @@
compatible = "arm,cortex-a7";
device_type = "cpu";
reg = <0xf00>;
+ clocks = <&smc1 IMX7ULP_CLK_ARM>,
+ <&scg1 IMX7ULP_CLK_CORE>,
+ <&scg1 IMX7ULP_CLK_SYS_SEL>,
+ <&scg1 IMX7ULP_CLK_HSRUN_CORE>,
+ <&scg1 IMX7ULP_CLK_HSRUN_SYS_SEL>,
+ <&scg1 IMX7ULP_CLK_FIRC>;
+ clock-names = "arm", "core", "scs_sel",
+ "hsrun_core", "hsrun_scs_sel",
+ "firc";
+ clock-frequency = <500210000>;
+ operating-points-v2 = <&cpu0_opp_table>;
+ };
+ };
+
+ cpu0_opp_table: opp-table {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-500210000 {
+ opp-hz = /bits/ 64 <500210000>;
+ /*opp-microvolt = <1025000>;*/
+ clock-latency-ns = <150000>;
+ };
+
+ opp-720000000 {
+ opp-hz = /bits/ 64 <720000000>;
+ /*opp-microvolt = <1125000>;*/
+ clock-latency-ns = <150000>;
};
};
--
2.16.4
From: Peng Fan <[email protected]>
Enable cpufreq for i.MX7ULP when imx cpufreq dt driver enabled.
Signed-off-by: Peng Fan <[email protected]>
---
arch/arm/mach-imx/mach-imx7ulp.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm/mach-imx/mach-imx7ulp.c b/arch/arm/mach-imx/mach-imx7ulp.c
index 11ac71aaf965..bf22d19e02f6 100644
--- a/arch/arm/mach-imx/mach-imx7ulp.c
+++ b/arch/arm/mach-imx/mach-imx7ulp.c
@@ -67,6 +67,9 @@ static const char *const imx7ulp_dt_compat[] __initconst = {
static void __init imx7ulp_init_late(void)
{
+ if (IS_ENABLED(CONFIG_ARM_IMX_CPUFREQ_DT))
+ platform_device_register_simple("imx-cpufreq-dt", -1, NULL, 0);
+
imx7ulp_cpuidle_init();
}
--
2.16.4
On 19-02-20, 15:59, [email protected] wrote:
> From: Peng Fan <[email protected]>
>
> Platforms may need to implement platform specific get_intermediate and
> target_intermediate hooks.
>
> Update cpufreq-dt driver's platform data to contain those for such
> platforms.
>
> Signed-off-by: Peng Fan <[email protected]>
> ---
> drivers/cpufreq/cpufreq-dt.c | 4 ++++
> drivers/cpufreq/cpufreq-dt.h | 4 ++++
> 2 files changed, 8 insertions(+)
>
> diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
> index d2b5f062a07b..26fe8dfb9ce6 100644
> --- a/drivers/cpufreq/cpufreq-dt.c
> +++ b/drivers/cpufreq/cpufreq-dt.c
> @@ -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);
> diff --git a/drivers/cpufreq/cpufreq-dt.h b/drivers/cpufreq/cpufreq-dt.h
> index a5a45b547d0b..28c8af7ec5ef 100644
> --- a/drivers/cpufreq/cpufreq-dt.h
> +++ b/drivers/cpufreq/cpufreq-dt.h
> @@ -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);
Who calls them ?
--
viresh
Hi Viresh,
> Subject: Re: [PATCH v2 10/14] cpufreq: dt: Allow platform specific
> intermediate callbacks
>
> On 19-02-20, 15:59, [email protected] wrote:
> > From: Peng Fan <[email protected]>
> >
> > Platforms may need to implement platform specific get_intermediate and
> > target_intermediate hooks.
> >
> > Update cpufreq-dt driver's platform data to contain those for such
> > platforms.
> >
> > Signed-off-by: Peng Fan <[email protected]>
> > ---
> > drivers/cpufreq/cpufreq-dt.c | 4 ++++ drivers/cpufreq/cpufreq-dt.h |
> > 4 ++++
> > 2 files changed, 8 insertions(+)
> >
> > diff --git a/drivers/cpufreq/cpufreq-dt.c
> > b/drivers/cpufreq/cpufreq-dt.c index d2b5f062a07b..26fe8dfb9ce6 100644
> > --- a/drivers/cpufreq/cpufreq-dt.c
> > +++ b/drivers/cpufreq/cpufreq-dt.c
> > @@ -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);
> > diff --git a/drivers/cpufreq/cpufreq-dt.h
> > b/drivers/cpufreq/cpufreq-dt.h index a5a45b547d0b..28c8af7ec5ef 100644
> > --- a/drivers/cpufreq/cpufreq-dt.h
> > +++ b/drivers/cpufreq/cpufreq-dt.h
> > @@ -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);
>
> Who calls them ?
In drivers/cpufreq/cpufreq.c, function __target_index. Line 2065, see below:
2062 notify = !(cpufreq_driver->flags & CPUFREQ_ASYNC_NOTIFICATION);
2063 if (notify) {
2064 /* Handle switching to intermediate frequency */
2065 if (cpufreq_driver->get_intermediate) {
2066 retval = __target_intermediate(policy, &freqs, index);
2067 if (retval)
2068 return retval;
2069
2070 intermediate_freq = freqs.new;
2071 /* Set old freq to intermediate */
2072 if (intermediate_freq)
2073 freqs.old = freqs.new;
2074 }
Inspired from tegra20-cpufreq.c, use target_intermediate could handle
i.MX7ULP cpufreq easier.
Thanks,
Peng.
>
> --
> viresh
On 19-02-20, 15:59, [email protected] wrote:
> From: Peng Fan <[email protected]>
>
> Platforms may need to implement platform specific get_intermediate and
> target_intermediate hooks.
>
> Update cpufreq-dt driver's platform data to contain those for such
> platforms.
>
> Signed-off-by: Peng Fan <[email protected]>
> ---
> drivers/cpufreq/cpufreq-dt.c | 4 ++++
> drivers/cpufreq/cpufreq-dt.h | 4 ++++
> 2 files changed, 8 insertions(+)
Looks fine to me, please lemme know the patches you want me to apply
to the cpufreq tree.
--
viresh
On 19-02-20, 09:41, Peng Fan wrote:
> In drivers/cpufreq/cpufreq.c, function __target_index. Line 2065, see below:
>
> 2062 notify = !(cpufreq_driver->flags & CPUFREQ_ASYNC_NOTIFICATION);
> 2063 if (notify) {
> 2064 /* Handle switching to intermediate frequency */
> 2065 if (cpufreq_driver->get_intermediate) {
> 2066 retval = __target_intermediate(policy, &freqs, index);
> 2067 if (retval)
> 2068 return retval;
> 2069
> 2070 intermediate_freq = freqs.new;
> 2071 /* Set old freq to intermediate */
> 2072 if (intermediate_freq)
> 2073 freqs.old = freqs.new;
> 2074 }
>
> Inspired from tegra20-cpufreq.c, use target_intermediate could handle
> i.MX7ULP cpufreq easier.
Ahh, sorry about that. Completely forgot this stuff existed :)
--
viresh
Hi Viresh,
> Subject: Re: [PATCH v2 10/14] cpufreq: dt: Allow platform specific
> intermediate callbacks
>
> On 19-02-20, 15:59, [email protected] wrote:
> > From: Peng Fan <[email protected]>
> >
> > Platforms may need to implement platform specific get_intermediate and
> > target_intermediate hooks.
> >
> > Update cpufreq-dt driver's platform data to contain those for such
> > platforms.
> >
> > Signed-off-by: Peng Fan <[email protected]>
> > ---
> > drivers/cpufreq/cpufreq-dt.c | 4 ++++ drivers/cpufreq/cpufreq-dt.h |
> > 4 ++++
> > 2 files changed, 8 insertions(+)
>
> Looks fine to me, please lemme know the patches you want me to apply to
> the cpufreq tree.
Thanks for quick reply.
Patch 1-9,13 needs to go into i.MX tree. Patch 10-12 needs to go into your tree.
But patch 11,12 depends on patch 3-9 to make i.MX7ULP cpufreq work. So
for now, only patch 10 could be directly taken into your tree.
Will let you know after CLK and i.MX maintainer agree on the clk part, then
you could take patches 10-12 in a whole.
Thanks,
Peng.
>
> --
> viresh
Hi Shawn,
> Subject: [PATCH v2 00/14] ARM: imx7ulp: add cpufreq using cpufreq-dt
Is it possible for you to pick up patch 1~8, 12? Or any comments?
Thanks,
Peng.
>
> From: Peng Fan <[email protected]>
>
> V2:
> Per Stephen's comments, I drop the cpuv2 clk code, and find another
> solution to change ARM clk Included get_intermediate/target_intermedate
> for cpufreq-dt Add i.MX7ULP intermedidate implementation.
> Per Fabio's comments, disallow HSRUN when LDO enabled.
> Add dt-bindings and pmc node
>
> V1:
> https://patchwork.kernel.org/patch/11364609/
>
> This patchset aims to use cpufreq-dt for i.MX7ULP to avoid plaform specific
> cpufreq driver. i.MX7ULP has some specicial requirements to change ARM
> core clock, see patch 11/13,
> "cpufreq: imx-cpufreq-dt: support i.MX7ULP"
>
> Patch [1,2]/13: add pmc bindings and node. We need read pmc registers
> to get system info.
> Patch [3-6]/13: i.MX7ULP clk pfd/pll code change to make sure to get the
> expected pfd output clk. For RUN/HSRUN clock, we use API
> imx_clk_hw_cpu to make sure RUN or HSRUN could not shutdown clock
> output.
>
> Patch [7-8]/13: Make sure we could run into HSRUN mode and not when LDO
> enabled.
>
> Patch 9/13: let cpufred-dt could have get_intermediate/target_intermediate
> hooks to allow platform specific freq set.
>
> Patch [10-12]/13: i.MX7ULP cpufreq support
>
> Patch 13/13: Test dts, should not apply.
>
> For rpmsg/vitio part, I have posted patchset, if you wanna rpmsg regulator:
> https://patchwork.kernel.org/cover/11390481/
>
> Anson Huang (1):
> clk: imx: Fix division by zero warning on pfdv2
>
> Peng Fan (13):
> dt-bindings: fsl: add i.MX7ULP PMC binding doc
> ARM: dts: imx7ulp: add pmc node
> clk: imx: pfdv2: switch to use determine_rate
> clk: imx: pfdv2: determine best parent rate
> clk: imx: pllv4: use prepare/unprepare
> clk: imx7ulp: make it easy to change ARM core clk
> ARM: imx: imx7ulp: support HSRUN mode
> ARM: imx: cpuidle-imx7ulp: Stop mode disallowed when HSRUN
> cpufreq: dt: Allow platform specific intermediate callbacks
> cpufreq: Add i.MX7ULP to cpufreq-dt-platdev blacklist
> cpufreq: imx-cpufreq-dt: support i.MX7ULP
> ARM: imx7ulp: enable cpufreq
> [Do not Apply] ARM: dts: imx7ulp: add cpu OPP points
>
> .../bindings/arm/freescale/imx7ulp_pmc.yaml | 32 +++++++++
> arch/arm/boot/dts/imx7ulp.dtsi | 38 ++++++++++
> arch/arm/mach-imx/common.h | 1 +
> arch/arm/mach-imx/cpuidle-imx7ulp.c | 14 +++-
> arch/arm/mach-imx/mach-imx7ulp.c | 3 +
> arch/arm/mach-imx/pm-imx7ulp.c | 25 +++++++
> drivers/clk/imx/clk-imx7ulp.c | 6 +-
> drivers/clk/imx/clk-pfdv2.c | 61
> +++++++++++-----
> drivers/clk/imx/clk-pllv4.c | 12 ++--
> drivers/cpufreq/cpufreq-dt-platdev.c | 1 +
> drivers/cpufreq/cpufreq-dt.c | 4 ++
> drivers/cpufreq/cpufreq-dt.h | 4 ++
> drivers/cpufreq/imx-cpufreq-dt.c | 83
> +++++++++++++++++++++-
> include/dt-bindings/clock/imx7ulp-clock.h | 5 +-
> 14 files changed, 257 insertions(+), 32 deletions(-) create mode 100644
> Documentation/devicetree/bindings/arm/freescale/imx7ulp_pmc.yaml
>
> --
> 2.16.4
Hi Peng,
On Sun, Mar 1, 2020 at 10:40 PM Peng Fan <[email protected]> wrote:
>
> Hi Shawn,
>
> > Subject: [PATCH v2 00/14] ARM: imx7ulp: add cpufreq using cpufreq-dt
>
> Is it possible for you to pick up patch 1~8, 12? Or any comments?
I haven't tested this series, but just wanted to be sure that 720MHz
operational point will not be populated on a system in LDO-enabled
mode.
Please confirm.
Thanks
Hi Fabio,
> Subject: Re: [PATCH v2 00/14] ARM: imx7ulp: add cpufreq using cpufreq-dt
>
> Hi Peng,
>
> On Sun, Mar 1, 2020 at 10:40 PM Peng Fan <[email protected]> wrote:
> >
> > Hi Shawn,
> >
> > > Subject: [PATCH v2 00/14] ARM: imx7ulp: add cpufreq using cpufreq-dt
> >
> > Is it possible for you to pick up patch 1~8, 12? Or any comments?
>
> I haven't tested this series, but just wanted to be sure that 720MHz
> operational point will not be populated on a system in LDO-enabled mode.
>
> Please confirm.
Currently I added a check to disable HSRUN mode when LDO-enabled.
Thanks,
Peng.
>
> Thanks
On Wed, Feb 19, 2020 at 03:59:44PM +0800, [email protected] wrote:
> From: Peng Fan <[email protected]>
>
> Add i.MX7ULP Power Management Controller binding doc
>
> Signed-off-by: Peng Fan <[email protected]>
This is a new binding, and I would like get an ACK from Rob on it.
> ---
> .../bindings/arm/freescale/imx7ulp_pmc.yaml | 32 ++++++++++++++++++++++
> 1 file changed, 32 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/arm/freescale/imx7ulp_pmc.yaml
>
> diff --git a/Documentation/devicetree/bindings/arm/freescale/imx7ulp_pmc.yaml b/Documentation/devicetree/bindings/arm/freescale/imx7ulp_pmc.yaml
> new file mode 100644
> index 000000000000..992a5ea29d39
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/freescale/imx7ulp_pmc.yaml
> @@ -0,0 +1,32 @@
> +# SPDX-License-Identifier: GPL-2.0
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/bindings/arm/freescale/imx7ulp_pmc.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: i.MX7ULP Power Management Controller(PMC) Device Tree Bindings
> +
> +maintainers:
> + - Peng Fan <[email protected]>
> +
> +properties:
> + compatible:
> + items:
> + - enum:
> + - fsl,imx7ulp-pmc0
> + - fsl,imx7ulp-pmc1
We usually do not encode number suffix in the compatible string. Do
they really have different programming model?
Shawn
> +
> + reg:
> + maxItems: 1
> +
> +required:
> + - compatible
> + - reg
> +
> +examples:
> + - |
> + pmc0: pmc0@410a1000 {
> + compatible = "fsl,imx7ulp-pmc0";
> + reg = <0x410a1000 0x1000>;
> + };
> +...
> --
> 2.16.4
>
On Wed, Feb 19, 2020 at 03:59:46PM +0800, [email protected] wrote:
> From: Anson Huang <[email protected]>
>
> Fix below division by zero warning:
>
> [ 3.176443] Division by zero in kernel.
> [ 3.181809] CPU: 0 PID: 88 Comm: kworker/0:2 Not tainted 5.3.0-rc2-next-20190730-63758-ge08da51-dirty #124
> [ 3.191817] Hardware name: Freescale i.MX7ULP (Device Tree)
> [ 3.197821] Workqueue: events dbs_work_handler
> [ 3.202849] [<c01127d8>] (unwind_backtrace) from [<c010cd80>] (show_stack+0x10/0x14)
> [ 3.211058] [<c010cd80>] (show_stack) from [<c0c77e68>] (dump_stack+0xd8/0x110)
> [ 3.218820] [<c0c77e68>] (dump_stack) from [<c0c753c0>] (Ldiv0_64+0x8/0x18)
> [ 3.226263] [<c0c753c0>] (Ldiv0_64) from [<c05984b4>] (clk_pfdv2_set_rate+0x54/0xac)
> [ 3.234487] [<c05984b4>] (clk_pfdv2_set_rate) from [<c059192c>] (clk_change_rate+0x1a4/0x698)
> [ 3.243468] [<c059192c>] (clk_change_rate) from [<c0591a08>] (clk_change_rate+0x280/0x698)
> [ 3.252180] [<c0591a08>] (clk_change_rate) from [<c0591fc0>] (clk_core_set_rate_nolock+0x1a0/0x278)
> [ 3.261679] [<c0591fc0>] (clk_core_set_rate_nolock) from [<c05920c8>] (clk_set_rate+0x30/0x64)
> [ 3.270743] [<c05920c8>] (clk_set_rate) from [<c089cb88>] (imx7ulp_set_target+0x184/0x2a4)
> [ 3.279501] [<c089cb88>] (imx7ulp_set_target) from [<c0896358>] (__cpufreq_driver_target+0x188/0x514)
> [ 3.289196] [<c0896358>] (__cpufreq_driver_target) from [<c0899b0c>] (od_dbs_update+0x130/0x15c)
> [ 3.298438] [<c0899b0c>] (od_dbs_update) from [<c089a5d0>] (dbs_work_handler+0x2c/0x5c)
> [ 3.306914] [<c089a5d0>] (dbs_work_handler) from [<c0156858>] (process_one_work+0x2ac/0x704)
> [ 3.315826] [<c0156858>] (process_one_work) from [<c0156cdc>] (worker_thread+0x2c/0x574)
> [ 3.324404] [<c0156cdc>] (worker_thread) from [<c015cfe8>] (kthread+0x134/0x148)
> [ 3.332278] [<c015cfe8>] (kthread) from [<c01010b4>] (ret_from_fork+0x14/0x20)
> [ 3.339858] Exception stack(0xe82d5fb0 to 0xe82d5ff8)
> [ 3.345314] 5fa0: 00000000 00000000 00000000 00000000
> [ 3.353926] 5fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> [ 3.362519] 5fe0: 00000000 00000000 00000000 00000000 00000013 00000000
>
> Signed-off-by: Anson Huang <[email protected]>
> Signed-off-by: Peng Fan <[email protected]>
Applied, thanks.
> Subject: Re: [PATCH v2 01/14] dt-bindings: fsl: add i.MX7ULP PMC binding doc
>
> On Wed, Feb 19, 2020 at 03:59:44PM +0800, [email protected] wrote:
> > From: Peng Fan <[email protected]>
> >
> > Add i.MX7ULP Power Management Controller binding doc
> >
> > Signed-off-by: Peng Fan <[email protected]>
>
> This is a new binding, and I would like get an ACK from Rob on it.
Rob,
Would you help Ack if you are fine with this patch?
>
> > ---
> > .../bindings/arm/freescale/imx7ulp_pmc.yaml | 32
> ++++++++++++++++++++++
> > 1 file changed, 32 insertions(+)
> > create mode 100644
> > Documentation/devicetree/bindings/arm/freescale/imx7ulp_pmc.yaml
> >
> > diff --git
> > a/Documentation/devicetree/bindings/arm/freescale/imx7ulp_pmc.yaml
> > b/Documentation/devicetree/bindings/arm/freescale/imx7ulp_pmc.yaml
> > new file mode 100644
> > index 000000000000..992a5ea29d39
> > --- /dev/null
> > +++
> b/Documentation/devicetree/bindings/arm/freescale/imx7ulp_pmc.yaml
> > @@ -0,0 +1,32 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +%YAML 1.2
> > +---
> > +$id:
> > +https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdevi
> >
> +cetree.org%2Fschemas%2Fbindings%2Farm%2Ffreescale%2Fimx7ulp_pmc.y
> aml%
> >
> +23&data=02%7C01%7Cpeng.fan%40nxp.com%7Cc1a27bc0347845099
> 80908d7c4
> >
> +b6dbe3%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C63719416
> 196456308
> >
> +7&sdata=EJausMj4W3mpgP%2BGdKpHpyTmZY4ipbxyUAurDVTKj5A%3
> D&rese
> > +rved=0
> > +$schema:
> > +https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdevi
> >
> +cetree.org%2Fmeta-schemas%2Fcore.yaml%23&data=02%7C01%7Cpe
> ng.fan%
> >
> +40nxp.com%7Cc1a27bc034784509980908d7c4b6dbe3%7C686ea1d3bc2b4c
> 6fa92cd9
> >
> +9c5c301635%7C0%7C0%7C637194161964563087&sdata=2UJYpLt69cd
> NiA%2BGA
> > +CI%2Bdqme0BFkqx%2FLrdt1fm3TzlM%3D&reserved=0
> > +
> > +title: i.MX7ULP Power Management Controller(PMC) Device Tree Bindings
> > +
> > +maintainers:
> > + - Peng Fan <[email protected]>
> > +
> > +properties:
> > + compatible:
> > + items:
> > + - enum:
> > + - fsl,imx7ulp-pmc0
> > + - fsl,imx7ulp-pmc1
>
> We usually do not encode number suffix in the compatible string. Do they
> really have different programming model?
The register layout is different and some has different name/meaning.
And pmc0 is used by M4, pmc1 is used by Linux.
A brief intro about pmc0/1.
The PMC 0 has the following features:
a high-power (HP) and a low-power (LP) Core Regulator;
a high-power (HP) and a low-power (LP) Array Regulator;
a high-power (HP) and a low-power (LP) 1.2V Low Voltage Detector (LVD)
monitor (in regulator input);
a high-power (HP) 1.8V High Voltage Detector (HVD) monitor (in regulator
supply);
a bandgap;
a forward back bias (FBB) and a reverse back bias (RBB) regulator.
a temperature sensor.
The PMC 1 has the following features:
a high-power (HP) and a low-power (LP) Linear LDO regulator;
a set of power switches;
a high-power (HP) and a low-power (LP) Low Voltage Detector (LVD) monitor;
a high-power (HP) 1.2V High Voltage Detector (HVD) monitor;
configurable LVD/HVD sense point between regulator supply and regulator output;
a forward back bias (FBB) and a reverse back bias (RBB) regulator.
Thanks,
Peng.
>
> Shawn
>
> > +
> > + reg:
> > + maxItems: 1
> > +
> > +required:
> > + - compatible
> > + - reg
> > +
> > +examples:
> > + - |
> > + pmc0: pmc0@410a1000 {
> > + compatible = "fsl,imx7ulp-pmc0";
> > + reg = <0x410a1000 0x1000>;
> > + };
> > +...
> > --
> > 2.16.4
> >
On Wed, Feb 19, 2020 at 03:59:47PM +0800, [email protected] wrote:
> From: Peng Fan <[email protected]>
>
> Per clk_ops, compared with round_rate, determine_rate could optionally
> support the parent clock that should be used to provide the clock rate.
>
> In this patch, the parent clock is just parent->rate as round_rate.
>
> The following patch will calculate the best parent clock.
>
> Signed-off-by: Peng Fan <[email protected]>
Applied, thanks.
On Wed, Feb 19, 2020 at 03:59:48PM +0800, [email protected] wrote:
> From: Peng Fan <[email protected]>
>
> pfdv2 is only used in i.MX7ULP. To get best pfd output, the i.MX7ULP
> Datasheet defines two best PLL rate and pfd frac.
>
> Per Datasheel
> All PLLs on i.MX 7ULP either have VCO base frequency of
> 480 MHz or 528 MHz. So when determine best rate, we also
> determine best parent rate which could match the requirement.
>
> For some reason the current parent might not be 480MHz or 528MHz,
> so we still take current parent rate as a choice.
>
> And we also enable flag CLK_SET_RATE_PARENT to let parent rate
> to be configured.
>
> Signed-off-by: Peng Fan <[email protected]>
Applied, thanks.
On Wed, Feb 19, 2020 at 03:59:49PM +0800, [email protected] wrote:
> From: Peng Fan <[email protected]>
>
> It is not good to use enable/disable for PLLv4 which needs time to
> lock, because enable/disable is expected to be able run in
> interrupt context. So use prepare/unprepare.
>
> Signed-off-by: Peng Fan <[email protected]>
Applied, thanks.
On Wed, Feb 19, 2020 at 03:59:50PM +0800, [email protected] wrote:
> From: Peng Fan <[email protected]>
>
> ARM clk could only source from divcore or hsrun_divcore.
>
> However when ARM core is running normaly, whether divcore or
> hwrun_divcore will finally source from SPLL_PFD0. However SPLL_PFD0
> is marked with CLK_SET_GATE, so we need to disable SPLL_PFD0, when
> configure the rate. So add CORE and HSRUN_CORE virtual clk to make it
> easy to configure the clk using imx_clk_hw_cpu API.
It sounds a bit hackish, so would like to hear an ACK from Stephen on
it.
Shawn
>
> Since CORE and HSRUN_CORE already marked with CLK_IS_CRITICAL, no
> need to set ARM as CLK_IS_CRITICAL. And when set the rate of ARM clk,
> prograting it the parent with CLK_SET_RATE_PARENT will finally set
> the SPLL_PFD0 clk.
>
> Signed-off-by: Peng Fan <[email protected]>
> ---
> drivers/clk/imx/clk-imx7ulp.c | 6 ++++--
> include/dt-bindings/clock/imx7ulp-clock.h | 5 ++++-
> 2 files changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/clk/imx/clk-imx7ulp.c b/drivers/clk/imx/clk-imx7ulp.c
> index 3710aa0dee9b..634c0b6636b0 100644
> --- a/drivers/clk/imx/clk-imx7ulp.c
> +++ b/drivers/clk/imx/clk-imx7ulp.c
> @@ -29,7 +29,7 @@ static const char * const ddr_sels[] = { "apll_pfd_sel", "dummy", "dummy", "dum
> static const char * const nic_sels[] = { "firc", "ddr_clk", };
> static const char * const periph_plat_sels[] = { "dummy", "nic1_bus_clk", "nic1_clk", "ddr_clk", "apll_pfd2", "apll_pfd1", "apll_pfd0", "upll", };
> static const char * const periph_bus_sels[] = { "dummy", "sosc_bus_clk", "dummy", "firc_bus_clk", "rosc", "nic1_bus_clk", "nic1_clk", "spll_bus_clk", };
> -static const char * const arm_sels[] = { "divcore", "dummy", "dummy", "hsrun_divcore", };
> +static const char * const arm_sels[] = { "core", "dummy", "dummy", "hsrun_core", };
>
> /* used by sosc/sirc/firc/ddr/spll/apll dividers */
> static const struct clk_div_table ulp_div_table[] = {
> @@ -121,7 +121,9 @@ static void __init imx7ulp_clk_scg1_init(struct device_node *np)
> hws[IMX7ULP_CLK_DDR_SEL] = imx_clk_hw_mux_flags("ddr_sel", base + 0x30, 24, 2, ddr_sels, ARRAY_SIZE(ddr_sels), CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE);
>
> hws[IMX7ULP_CLK_CORE_DIV] = imx_clk_hw_divider_flags("divcore", "scs_sel", base + 0x14, 16, 4, CLK_SET_RATE_PARENT);
> + hws[IMX7ULP_CLK_CORE] = imx_clk_hw_cpu("core", "divcore", hws[IMX7ULP_CLK_CORE_DIV]->clk, hws[IMX7ULP_CLK_SYS_SEL]->clk, hws[IMX7ULP_CLK_SPLL_SEL]->clk, hws[IMX7ULP_CLK_FIRC]->clk);
> hws[IMX7ULP_CLK_HSRUN_CORE_DIV] = imx_clk_hw_divider_flags("hsrun_divcore", "hsrun_scs_sel", base + 0x1c, 16, 4, CLK_SET_RATE_PARENT);
> + hws[IMX7ULP_CLK_HSRUN_CORE] = imx_clk_hw_cpu("hsrun_core", "hsrun_divcore", hws[IMX7ULP_CLK_HSRUN_CORE_DIV]->clk, hws[IMX7ULP_CLK_HSRUN_SYS_SEL]->clk, hws[IMX7ULP_CLK_SPLL_SEL]->clk, hws[IMX7ULP_CLK_FIRC]->clk);
>
> hws[IMX7ULP_CLK_DDR_DIV] = imx_clk_hw_divider_gate("ddr_clk", "ddr_sel", CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, base + 0x30, 0, 3,
> 0, ulp_div_table, &imx_ccm_lock);
> @@ -270,7 +272,7 @@ static void __init imx7ulp_clk_smc1_init(struct device_node *np)
> base = of_iomap(np, 0);
> WARN_ON(!base);
>
> - hws[IMX7ULP_CLK_ARM] = imx_clk_hw_mux_flags("arm", base + 0x10, 8, 2, arm_sels, ARRAY_SIZE(arm_sels), CLK_IS_CRITICAL);
> + hws[IMX7ULP_CLK_ARM] = imx_clk_hw_mux_flags("arm", base + 0x10, 8, 2, arm_sels, ARRAY_SIZE(arm_sels), CLK_SET_RATE_PARENT);
>
> imx_check_clk_hws(hws, clk_data->num);
>
> diff --git a/include/dt-bindings/clock/imx7ulp-clock.h b/include/dt-bindings/clock/imx7ulp-clock.h
> index 38145bdcd975..b58370d146e2 100644
> --- a/include/dt-bindings/clock/imx7ulp-clock.h
> +++ b/include/dt-bindings/clock/imx7ulp-clock.h
> @@ -58,7 +58,10 @@
> #define IMX7ULP_CLK_HSRUN_SYS_SEL 44
> #define IMX7ULP_CLK_HSRUN_CORE_DIV 45
>
> -#define IMX7ULP_CLK_SCG1_END 46
> +#define IMX7ULP_CLK_CORE 46
> +#define IMX7ULP_CLK_HSRUN_CORE 47
> +
> +#define IMX7ULP_CLK_SCG1_END 48
>
> /* PCC2 */
> #define IMX7ULP_CLK_DMA1 0
> --
> 2.16.4
>
On Wed, Feb 19, 2020 at 03:59:52PM +0800, [email protected] wrote:
> From: Peng Fan <[email protected]>
>
> When cpu runs in HSRUN mode, cpuidle is not allowed to run into
> Stop mode. So add imx7ulp_get_mode to get thr cpu run mode,
> and use WAIT mode instead, when cpu in HSRUN mode.
>
> Signed-off-by: Peng Fan <[email protected]>
Why do you have cpuidle patches in a series titled as adding cpufreq
support?
Shawn
> ---
> arch/arm/mach-imx/common.h | 1 +
> arch/arm/mach-imx/cpuidle-imx7ulp.c | 14 +++++++++++---
> arch/arm/mach-imx/pm-imx7ulp.c | 10 ++++++++++
> 3 files changed, 22 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
> index 5aa5796cff0e..db542da4fe67 100644
> --- a/arch/arm/mach-imx/common.h
> +++ b/arch/arm/mach-imx/common.h
> @@ -104,6 +104,7 @@ void imx6_set_int_mem_clk_lpm(bool enable);
> void imx6sl_set_wait_clk(bool enter);
> int imx_mmdc_get_ddr_type(void);
> int imx7ulp_set_lpm(enum ulp_cpu_pwr_mode mode);
> +u32 imx7ulp_get_mode(void);
>
> void imx_cpu_die(unsigned int cpu);
> int imx_cpu_kill(unsigned int cpu);
> diff --git a/arch/arm/mach-imx/cpuidle-imx7ulp.c b/arch/arm/mach-imx/cpuidle-imx7ulp.c
> index ca86c967d19e..e7009d10b331 100644
> --- a/arch/arm/mach-imx/cpuidle-imx7ulp.c
> +++ b/arch/arm/mach-imx/cpuidle-imx7ulp.c
> @@ -15,10 +15,18 @@
> static int imx7ulp_enter_wait(struct cpuidle_device *dev,
> struct cpuidle_driver *drv, int index)
> {
> - if (index == 1)
> + u32 mode;
> +
> + if (index == 1) {
> imx7ulp_set_lpm(ULP_PM_WAIT);
> - else
> - imx7ulp_set_lpm(ULP_PM_STOP);
> + } else {
> + mode = imx7ulp_get_mode();
> +
> + if (mode == 3)
> + imx7ulp_set_lpm(ULP_PM_WAIT);
> + else
> + imx7ulp_set_lpm(ULP_PM_STOP);
> + }
>
> cpu_do_idle();
>
> diff --git a/arch/arm/mach-imx/pm-imx7ulp.c b/arch/arm/mach-imx/pm-imx7ulp.c
> index 393faf1e8382..1410ccfc71bd 100644
> --- a/arch/arm/mach-imx/pm-imx7ulp.c
> +++ b/arch/arm/mach-imx/pm-imx7ulp.c
> @@ -63,6 +63,16 @@ int imx7ulp_set_lpm(enum ulp_cpu_pwr_mode mode)
> return 0;
> }
>
> +u32 imx7ulp_get_mode(void)
> +{
> + u32 mode;
> +
> + mode = readl_relaxed(smc1_base + SMC_PMCTRL) & BM_PMCTRL_RUNM;
> + mode >>= BP_PMCTRL_RUNM;
> +
> + return mode;
> +}
> +
> void __init imx7ulp_pm_init(void)
> {
> struct device_node *np;
> --
> 2.16.4
>
Hi Shawn,
> Subject: Re: [PATCH v2 07/14] clk: imx7ulp: make it easy to change ARM core
> clk
>
> On Wed, Feb 19, 2020 at 03:59:50PM +0800, [email protected] wrote:
> > From: Peng Fan <[email protected]>
> >
> > ARM clk could only source from divcore or hsrun_divcore.
> >
> > However when ARM core is running normaly, whether divcore or
> > hwrun_divcore will finally source from SPLL_PFD0. However SPLL_PFD0 is
> > marked with CLK_SET_GATE, so we need to disable SPLL_PFD0, when
> > configure the rate. So add CORE and HSRUN_CORE virtual clk to make it
> > easy to configure the clk using imx_clk_hw_cpu API.
>
> It sounds a bit hackish, so would like to hear an ACK from Stephen on it.
Same to i.MX7/8M SoCs, the cpu clk could not change on the fly,
That's why we use a imx_clk_hw_cpu for i.MX7/8M cpu clock.
To i.MX7ULP, it is a bit different, cpu could sources from two clocks
based on a SMC setting which is abstract as a mux in clk-imx7ulp.c.
However we still could not change HSRUN_CORE or CORE clk
on the fly whether the cpu sources form HSRUN_CORE or CORE clk.
That's why I add virtual clk for HSRUN and CORE, same as i.MX7/8M.
Stephen rejected my original patch to use a virtual clk for the final
output which add imx_hw_clk_cpuv2,
https://patchwork.kernel.org/patch/11364633/
So I implement the method in this patch which is cleaner and
simple. With this approach, it is easy to reuse cpufreq-dt driver,
we no need a new clk driver and no need a new cpufreq driver
for i.MX7ULP.
Please consider this patch.
Thanks,
Peng.
>
> Shawn
>
> >
> > Since CORE and HSRUN_CORE already marked with CLK_IS_CRITICAL, no
> need
> > to set ARM as CLK_IS_CRITICAL. And when set the rate of ARM clk,
> > prograting it the parent with CLK_SET_RATE_PARENT will finally set the
> > SPLL_PFD0 clk.
> >
> > Signed-off-by: Peng Fan <[email protected]>
> > ---
> > drivers/clk/imx/clk-imx7ulp.c | 6 ++++--
> > include/dt-bindings/clock/imx7ulp-clock.h | 5 ++++-
> > 2 files changed, 8 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/clk/imx/clk-imx7ulp.c
> > b/drivers/clk/imx/clk-imx7ulp.c index 3710aa0dee9b..634c0b6636b0
> > 100644
> > --- a/drivers/clk/imx/clk-imx7ulp.c
> > +++ b/drivers/clk/imx/clk-imx7ulp.c
> > @@ -29,7 +29,7 @@ static const char * const ddr_sels[] =
> { "apll_pfd_sel", "dummy", "dummy", "dum
> > static const char * const nic_sels[] = { "firc", "ddr_clk", };
> > static const char * const periph_plat_sels[] = { "dummy", "nic1_bus_clk",
> "nic1_clk", "ddr_clk", "apll_pfd2", "apll_pfd1", "apll_pfd0", "upll", };
> > static const char * const periph_bus_sels[] = { "dummy", "sosc_bus_clk",
> "dummy", "firc_bus_clk", "rosc", "nic1_bus_clk", "nic1_clk", "spll_bus_clk", };
> > -static const char * const arm_sels[] = { "divcore", "dummy", "dummy",
> "hsrun_divcore", };
> > +static const char * const arm_sels[] = { "core", "dummy", "dummy",
> "hsrun_core", };
> >
> > /* used by sosc/sirc/firc/ddr/spll/apll dividers */ static const
> > struct clk_div_table ulp_div_table[] = { @@ -121,7 +121,9 @@ static
> > void __init imx7ulp_clk_scg1_init(struct device_node *np)
> > hws[IMX7ULP_CLK_DDR_SEL] = imx_clk_hw_mux_flags("ddr_sel",
> base + 0x30, 24, 2, ddr_sels, ARRAY_SIZE(ddr_sels), CLK_SET_RATE_PARENT |
> CLK_OPS_PARENT_ENABLE);
> >
> > hws[IMX7ULP_CLK_CORE_DIV] = imx_clk_hw_divider_flags("divcore",
> "scs_sel", base + 0x14, 16, 4, CLK_SET_RATE_PARENT);
> > + hws[IMX7ULP_CLK_CORE] = imx_clk_hw_cpu("core", "divcore",
> hws[IMX7ULP_CLK_CORE_DIV]->clk, hws[IMX7ULP_CLK_SYS_SEL]->clk,
> hws[IMX7ULP_CLK_SPLL_SEL]->clk, hws[IMX7ULP_CLK_FIRC]->clk);
> > hws[IMX7ULP_CLK_HSRUN_CORE_DIV] =
> > imx_clk_hw_divider_flags("hsrun_divcore", "hsrun_scs_sel", base +
> > 0x1c, 16, 4, CLK_SET_RATE_PARENT);
> > + hws[IMX7ULP_CLK_HSRUN_CORE] = imx_clk_hw_cpu("hsrun_core",
> > +"hsrun_divcore", hws[IMX7ULP_CLK_HSRUN_CORE_DIV]->clk,
> > +hws[IMX7ULP_CLK_HSRUN_SYS_SEL]->clk,
> hws[IMX7ULP_CLK_SPLL_SEL]->clk,
> > +hws[IMX7ULP_CLK_FIRC]->clk);
> >
> > hws[IMX7ULP_CLK_DDR_DIV] = imx_clk_hw_divider_gate("ddr_clk",
> "ddr_sel", CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, base + 0x30, 0, 3,
> > 0, ulp_div_table, &imx_ccm_lock);
> @@ -270,7 +272,7 @@
> > static void __init imx7ulp_clk_smc1_init(struct device_node *np)
> > base = of_iomap(np, 0);
> > WARN_ON(!base);
> >
> > - hws[IMX7ULP_CLK_ARM] = imx_clk_hw_mux_flags("arm", base + 0x10,
> 8, 2, arm_sels, ARRAY_SIZE(arm_sels), CLK_IS_CRITICAL);
> > + hws[IMX7ULP_CLK_ARM] = imx_clk_hw_mux_flags("arm", base + 0x10,
> 8,
> > +2, arm_sels, ARRAY_SIZE(arm_sels), CLK_SET_RATE_PARENT);
> >
> > imx_check_clk_hws(hws, clk_data->num);
> >
> > diff --git a/include/dt-bindings/clock/imx7ulp-clock.h
> > b/include/dt-bindings/clock/imx7ulp-clock.h
> > index 38145bdcd975..b58370d146e2 100644
> > --- a/include/dt-bindings/clock/imx7ulp-clock.h
> > +++ b/include/dt-bindings/clock/imx7ulp-clock.h
> > @@ -58,7 +58,10 @@
> > #define IMX7ULP_CLK_HSRUN_SYS_SEL 44
> > #define IMX7ULP_CLK_HSRUN_CORE_DIV 45
> >
> > -#define IMX7ULP_CLK_SCG1_END 46
> > +#define IMX7ULP_CLK_CORE 46
> > +#define IMX7ULP_CLK_HSRUN_CORE 47
> > +
> > +#define IMX7ULP_CLK_SCG1_END 48
> >
> > /* PCC2 */
> > #define IMX7ULP_CLK_DMA1 0
> > --
> > 2.16.4
> >
Hi Shawn,
> Subject: Re: [PATCH v2 09/14] ARM: imx: cpuidle-imx7ulp: Stop mode
> disallowed when HSRUN
>
> On Wed, Feb 19, 2020 at 03:59:52PM +0800, [email protected] wrote:
> > From: Peng Fan <[email protected]>
> >
> > When cpu runs in HSRUN mode, cpuidle is not allowed to run into Stop
> > mode. So add imx7ulp_get_mode to get thr cpu run mode, and use WAIT
> > mode instead, when cpu in HSRUN mode.
> >
> > Signed-off-by: Peng Fan <[email protected]>
>
> Why do you have cpuidle patches in a series titled as adding cpufreq support?
The whole patchset is to add cpufreq support for i.MX7ULP.
But i.MX7ULP only support two freq points. One freq point is HSRUN point,
When cpu runs in this point, cpu is not allowed to run into STOP mode from
hardware perspective. Should I submit this patch as a standalone patch?
Thanks,
Peng.
>
> Shawn
>
> > ---
> > arch/arm/mach-imx/common.h | 1 +
> > arch/arm/mach-imx/cpuidle-imx7ulp.c | 14 +++++++++++---
> > arch/arm/mach-imx/pm-imx7ulp.c | 10 ++++++++++
> > 3 files changed, 22 insertions(+), 3 deletions(-)
> >
> > diff --git a/arch/arm/mach-imx/common.h
> b/arch/arm/mach-imx/common.h
> > index 5aa5796cff0e..db542da4fe67 100644
> > --- a/arch/arm/mach-imx/common.h
> > +++ b/arch/arm/mach-imx/common.h
> > @@ -104,6 +104,7 @@ void imx6_set_int_mem_clk_lpm(bool enable);
> void
> > imx6sl_set_wait_clk(bool enter); int imx_mmdc_get_ddr_type(void);
> > int imx7ulp_set_lpm(enum ulp_cpu_pwr_mode mode);
> > +u32 imx7ulp_get_mode(void);
> >
> > void imx_cpu_die(unsigned int cpu);
> > int imx_cpu_kill(unsigned int cpu);
> > diff --git a/arch/arm/mach-imx/cpuidle-imx7ulp.c
> > b/arch/arm/mach-imx/cpuidle-imx7ulp.c
> > index ca86c967d19e..e7009d10b331 100644
> > --- a/arch/arm/mach-imx/cpuidle-imx7ulp.c
> > +++ b/arch/arm/mach-imx/cpuidle-imx7ulp.c
> > @@ -15,10 +15,18 @@
> > static int imx7ulp_enter_wait(struct cpuidle_device *dev,
> > struct cpuidle_driver *drv, int index) {
> > - if (index == 1)
> > + u32 mode;
> > +
> > + if (index == 1) {
> > imx7ulp_set_lpm(ULP_PM_WAIT);
> > - else
> > - imx7ulp_set_lpm(ULP_PM_STOP);
> > + } else {
> > + mode = imx7ulp_get_mode();
> > +
> > + if (mode == 3)
> > + imx7ulp_set_lpm(ULP_PM_WAIT);
> > + else
> > + imx7ulp_set_lpm(ULP_PM_STOP);
> > + }
> >
> > cpu_do_idle();
> >
> > diff --git a/arch/arm/mach-imx/pm-imx7ulp.c
> > b/arch/arm/mach-imx/pm-imx7ulp.c index 393faf1e8382..1410ccfc71bd
> > 100644
> > --- a/arch/arm/mach-imx/pm-imx7ulp.c
> > +++ b/arch/arm/mach-imx/pm-imx7ulp.c
> > @@ -63,6 +63,16 @@ int imx7ulp_set_lpm(enum ulp_cpu_pwr_mode
> mode)
> > return 0;
> > }
> >
> > +u32 imx7ulp_get_mode(void)
> > +{
> > + u32 mode;
> > +
> > + mode = readl_relaxed(smc1_base + SMC_PMCTRL) &
> BM_PMCTRL_RUNM;
> > + mode >>= BP_PMCTRL_RUNM;
> > +
> > + return mode;
> > +}
> > +
> > void __init imx7ulp_pm_init(void)
> > {
> > struct device_node *np;
> > --
> > 2.16.4
> >
Hi Rob,
> Subject: [PATCH v2 01/14] dt-bindings: fsl: add i.MX7ULP PMC binding doc
Would you help Ack if you are fine with this patch?
Thanks,
Peng.
>
> From: Peng Fan <[email protected]>
>
> Add i.MX7ULP Power Management Controller binding doc
>
> Signed-off-by: Peng Fan <[email protected]>
> ---
> .../bindings/arm/freescale/imx7ulp_pmc.yaml | 32
> ++++++++++++++++++++++
> 1 file changed, 32 insertions(+)
> create mode 100644
> Documentation/devicetree/bindings/arm/freescale/imx7ulp_pmc.yaml
>
> diff --git
> a/Documentation/devicetree/bindings/arm/freescale/imx7ulp_pmc.yaml
> b/Documentation/devicetree/bindings/arm/freescale/imx7ulp_pmc.yaml
> new file mode 100644
> index 000000000000..992a5ea29d39
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/freescale/imx7ulp_pmc.yaml
> @@ -0,0 +1,32 @@
> +# SPDX-License-Identifier: GPL-2.0
> +%YAML 1.2
> +---
> +$id:
> http://devicetree.org/schemas/bindings/arm/freescale/imx7ulp_pmc.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: i.MX7ULP Power Management Controller(PMC) Device Tree Bindings
> +
> +maintainers:
> + - Peng Fan <[email protected]>
> +
> +properties:
> + compatible:
> + items:
> + - enum:
> + - fsl,imx7ulp-pmc0
> + - fsl,imx7ulp-pmc1
> +
> + reg:
> + maxItems: 1
> +
> +required:
> + - compatible
> + - reg
> +
> +examples:
> + - |
> + pmc0: pmc0@410a1000 {
> + compatible = "fsl,imx7ulp-pmc0";
> + reg = <0x410a1000 0x1000>;
> + };
> +...
> --
> 2.16.4
On 19-02-20, 15:59, [email protected] wrote:
> From: Peng Fan <[email protected]>
>
> Platforms may need to implement platform specific get_intermediate and
> target_intermediate hooks.
>
> Update cpufreq-dt driver's platform data to contain those for such
> platforms.
>
> Signed-off-by: Peng Fan <[email protected]>
> ---
> drivers/cpufreq/cpufreq-dt.c | 4 ++++
> drivers/cpufreq/cpufreq-dt.h | 4 ++++
> 2 files changed, 8 insertions(+)
Applied. Thanks.
--
viresh