From 6befc1f900db638ae54ea1bbab51a42cd1d5a153 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 15 Feb 2020 21:27:38 +0100 Subject: [PATCH 01/14] clk: ICS8N3QV01 remove superfluous code Do not calculate a unused value of n which is overwritten in both branches of the subsequent if statement. Identified by cppcheck. Signed-off-by: Heinrich Schuchardt Reviewed-by: Lukasz Majewski --- drivers/clk/ics8n3qv01.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/ics8n3qv01.c b/drivers/clk/ics8n3qv01.c index 4f80bf6e52..76b27ad7fd 100644 --- a/drivers/clk/ics8n3qv01.c +++ b/drivers/clk/ics8n3qv01.c @@ -82,7 +82,6 @@ static int ics8n3qv01_calc_parameters(uint fout, uint *_mint, uint *_mfrac, uint n, foutiic, fvcoiic, mint; u64 mfrac; - n = (2215000000U + fout / 2) / fout; if (fout < 417000000U) n = 2 * ((2215000000U / 2 + fout / 2) / fout); else From d71fac847904af35ebf8c47c42ccf9ee442190b3 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Mon, 24 Feb 2020 14:55:24 +0100 Subject: [PATCH 02/14] clk: imx6: Add definition for IMX6QDL_CLK_ENET clock After commit 673f6597321d ("net: fec_mxc: support i.MX8M with CLK_CCF") all NXP boards, which are not IMX8 and in the same time are supporting CCF need to provide IMX6QDL_CLK_ENET. This change defines the missing clock in i.MX6Q's CCF. Signed-off-by: Lukasz Majewski --- drivers/clk/imx/clk-imx6q.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c index 11d194363d..d954af9a07 100644 --- a/drivers/clk/imx/clk-imx6q.c +++ b/drivers/clk/imx/clk-imx6q.c @@ -183,6 +183,7 @@ static int imx6q_clk_probe(struct udevice *dev) clk_dm(IMX6QDL_CLK_I2C2, imx_clk_gate2("i2c2", "ipg_per", base + 0x70, 8)); + clk_dm(IMX6QDL_CLK_ENET, imx_clk_gate2("enet", "ipg", base + 0x6c, 10)); return 0; } From 8d540ccb1128bac033eac77be997d28a1236d9f4 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Mon, 24 Feb 2020 14:55:25 +0100 Subject: [PATCH 03/14] clk: imx: Add support for pllv3 enet clock This code has been ported from Linux kernel v5.5.5 (tag) and has been adjusted to U-Boot's DM. It adds support for correct recognition of IMX_PLLV3_ENET flag in the clk-pllv3.c driver. Signed-off-by: Lukasz Majewski --- drivers/clk/imx/clk-pllv3.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c index b4a9d587e1..feacaee1c4 100644 --- a/drivers/clk/imx/clk-pllv3.c +++ b/drivers/clk/imx/clk-pllv3.c @@ -20,6 +20,7 @@ #define UBOOT_DM_CLK_IMX_PLLV3_SYS "imx_clk_pllv3_sys" #define UBOOT_DM_CLK_IMX_PLLV3_USB "imx_clk_pllv3_usb" #define UBOOT_DM_CLK_IMX_PLLV3_AV "imx_clk_pllv3_av" +#define UBOOT_DM_CLK_IMX_PLLV3_ENET "imx_clk_pllv3_enet" #define PLL_NUM_OFFSET 0x10 #define PLL_DENOM_OFFSET 0x20 @@ -36,6 +37,7 @@ struct clk_pllv3 { u32 enable_bit; u32 div_mask; u32 div_shift; + unsigned long ref_clock; }; #define to_clk_pllv3(_clk) container_of(_clk, struct clk_pllv3, clk) @@ -232,6 +234,19 @@ static const struct clk_ops clk_pllv3_av_ops = { .set_rate = clk_pllv3_av_set_rate, }; +static ulong clk_pllv3_enet_get_rate(struct clk *clk) +{ + struct clk_pllv3 *pll = to_clk_pllv3(clk); + + return pll->ref_clock; +} + +static const struct clk_ops clk_pllv3_enet_ops = { + .enable = clk_pllv3_generic_enable, + .disable = clk_pllv3_generic_disable, + .get_rate = clk_pllv3_enet_get_rate, +}; + struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, const char *parent_name, void __iomem *base, u32 div_mask) @@ -269,6 +284,10 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, pll->div_shift = 0; pll->powerup_set = false; break; + case IMX_PLLV3_ENET: + drv_name = UBOOT_DM_CLK_IMX_PLLV3_ENET; + pll->ref_clock = 500000000; + break; default: kfree(pll); return ERR_PTR(-ENOTSUPP); @@ -314,3 +333,9 @@ U_BOOT_DRIVER(clk_pllv3_av) = { .ops = &clk_pllv3_av_ops, .flags = DM_FLAG_PRE_RELOC, }; + +U_BOOT_DRIVER(clk_pllv3_enet) = { + .name = UBOOT_DM_CLK_IMX_PLLV3_ENET, + .id = UCLASS_CLK, + .ops = &clk_pllv3_enet_ops, +}; From 32f462ba3bf0c8794653e6ff92ca5cbec9856c54 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Mon, 24 Feb 2020 14:55:26 +0100 Subject: [PATCH 04/14] clk: imx6: Add definition for IMX6QDL_CLK_ENET_REF clock After commit 673f6597321d ("net: fec_mxc: support i.MX8M with CLK_CCF") all NXP boards, which are not IMX8 and in the same time are supporting CCF need to provide PTP clock. On the i.MX6Q this clock is provided with IMX6QDL_CLK_ENET_REF in the Linux kernel's CCF. Code in this change models the simplest case when enet reference clock is generated from 'osc' clock. Signed-off-by: Lukasz Majewski --- drivers/clk/imx/clk-imx6q.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c index d954af9a07..5343036bab 100644 --- a/drivers/clk/imx/clk-imx6q.c +++ b/drivers/clk/imx/clk-imx6q.c @@ -113,6 +113,10 @@ static int imx6q_clk_probe(struct udevice *dev) imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0)); clk_dm(IMX6QDL_CLK_PLL2_PFD2_396M, imx_clk_pfd("pll2_pfd2_396m", "pll2_bus", base + 0x100, 2)); + clk_dm(IMX6QDL_CLK_PLL6, + imx_clk_pllv3(IMX_PLLV3_ENET, "pll6", "osc", base + 0xe0, 0x3)); + clk_dm(IMX6QDL_CLK_PLL6_ENET, + imx_clk_gate("pll6_enet", "pll6", base + 0xe0, 13)); /* CCM clocks */ base = dev_read_addr_ptr(dev); @@ -184,6 +188,9 @@ static int imx6q_clk_probe(struct udevice *dev) imx_clk_gate2("i2c2", "ipg_per", base + 0x70, 8)); clk_dm(IMX6QDL_CLK_ENET, imx_clk_gate2("enet", "ipg", base + 0x6c, 10)); + clk_dm(IMX6QDL_CLK_ENET_REF, + imx_clk_fixed_factor("enet_ref", "pll6_enet", 1, 1)); + return 0; } From cd16c57bd0d6c498d5c180d70c6f0f690e9c32de Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Mon, 13 Apr 2020 14:36:26 +0200 Subject: [PATCH 05/14] dm: test: clk: add the test for the ccf gated clock Unlike the other clock types, in the case of the gated clock, a new driver has been developed which does not use the registering routine provided by the common clock framework. The addition of the ecspi0 clock to sandbox therefore allows testing the ccf gate clock. Signed-off-by: Dario Binacchi Reviewed-by: Simon Glass --- drivers/clk/clk_sandbox_ccf.c | 4 ++++ include/sandbox-clk.h | 8 ++++++++ test/dm/clk_ccf.c | 8 ++++++++ 3 files changed, 20 insertions(+) diff --git a/drivers/clk/clk_sandbox_ccf.c b/drivers/clk/clk_sandbox_ccf.c index 0619d04f0e..e90b860257 100644 --- a/drivers/clk/clk_sandbox_ccf.c +++ b/drivers/clk/clk_sandbox_ccf.c @@ -250,6 +250,10 @@ static int sandbox_clk_ccf_probe(struct udevice *dev) clk_dm(SANDBOX_CLK_ECSPI_ROOT, sandbox_clk_divider("ecspi_root", "pll3_60m", ®, 19, 6)); + reg = 0; + clk_dm(SANDBOX_CLK_ECSPI0, + sandbox_clk_gate("ecspi0", "ecspi_root", ®, 0, 0)); + clk_dm(SANDBOX_CLK_ECSPI1, sandbox_clk_gate2("ecspi1", "ecspi_root", base + 0x6c, 0)); diff --git a/include/sandbox-clk.h b/include/sandbox-clk.h index 296cddfbb0..c2616c27a4 100644 --- a/include/sandbox-clk.h +++ b/include/sandbox-clk.h @@ -50,6 +50,14 @@ static inline struct clk *sandbox_clk_divider(const char *name, reg, shift, width, 0); } +static inline struct clk *sandbox_clk_gate(const char *name, const char *parent, + void __iomem *reg, u8 bit_idx, + u8 clk_gate_flags) +{ + return clk_register_gate(NULL, name, parent, CLK_SET_RATE_PARENT, + reg, bit_idx, clk_gate_flags, NULL); +} + struct clk *sandbox_clk_register_gate2(struct device *dev, const char *name, const char *parent_name, unsigned long flags, diff --git a/test/dm/clk_ccf.c b/test/dm/clk_ccf.c index 050fa80453..960cb2db0d 100644 --- a/test/dm/clk_ccf.c +++ b/test/dm/clk_ccf.c @@ -39,6 +39,14 @@ static int dm_test_clk_ccf(struct unit_test_state *uts) rate = clk_get_parent_rate(clk); ut_asserteq(rate, 20000000); + /* test the gate of CCF */ + ret = clk_get_by_id(SANDBOX_CLK_ECSPI0, &clk); + ut_assertok(ret); + ut_asserteq_str("ecspi0", clk->dev->name); + + rate = clk_get_parent_rate(clk); + ut_asserteq(rate, 20000000); + /* Test the mux of CCF */ ret = clk_get_by_id(SANDBOX_CLK_USDHC1_SEL, &clk); ut_assertok(ret); From 16bdc85b488dd2f9463a71d6aa09bdf5ea9a9978 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Mon, 13 Apr 2020 14:36:27 +0200 Subject: [PATCH 06/14] clk: set flags in the ccf registration routines The top-level framework flags are passed as parameter to the common clock framework (ccf) registration routines without being used. Checks of the flags setting added by the patch have been added in the ccf test. Signed-off-by: Dario Binacchi --- drivers/clk/clk-composite.c | 1 + drivers/clk/clk-divider.c | 1 + drivers/clk/clk-fixed-factor.c | 1 + drivers/clk/clk-gate.c | 1 + drivers/clk/clk-mux.c | 1 + drivers/clk/clk_sandbox_ccf.c | 3 ++- test/dm/clk_ccf.c | 7 +++++++ 7 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index 819bfca2fc..7e99c5b910 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -145,6 +145,7 @@ struct clk *clk_register_composite(struct device *dev, const char *name, } clk = &composite->clk; + clk->flags = flags; ret = clk_register(clk, UBOOT_DM_CLK_COMPOSITE, name, parent_names[clk_composite_get_parent(clk)]); if (ret) { diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 34658536c4..8f59d7fb72 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -212,6 +212,7 @@ static struct clk *_register_divider(struct device *dev, const char *name, /* register the clock */ clk = &div->clk; + clk->flags = flags; ret = clk_register(clk, UBOOT_DM_CLK_CCF_DIVIDER, name, parent_name); if (ret) { diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index 0eb24b87fc..8d9823bdab 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -49,6 +49,7 @@ struct clk *clk_hw_register_fixed_factor(struct device *dev, fix->mult = mult; fix->div = div; clk = &fix->clk; + clk->flags = flags; ret = clk_register(clk, UBOOT_DM_CLK_IMX_FIXED_FACTOR, name, parent_name); diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index 98e4b80b32..006d3b6629 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c @@ -142,6 +142,7 @@ struct clk *clk_register_gate(struct device *dev, const char *name, #endif clk = &gate->clk; + clk->flags = flags; ret = clk_register(clk, UBOOT_DM_CLK_GATE, name, parent_name); if (ret) { diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 26991a5bc8..679d66a85b 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -185,6 +185,7 @@ struct clk *clk_hw_register_mux_table(struct device *dev, const char *name, #endif clk = &mux->clk; + clk->flags = flags; /* * Read the current mux setup - so we assign correct parent. diff --git a/drivers/clk/clk_sandbox_ccf.c b/drivers/clk/clk_sandbox_ccf.c index e90b860257..fedcdd4044 100644 --- a/drivers/clk/clk_sandbox_ccf.c +++ b/drivers/clk/clk_sandbox_ccf.c @@ -130,6 +130,7 @@ struct clk *sandbox_clk_register_gate2(struct device *dev, const char *name, gate->state = 0; clk = &gate->clk; + clk->flags = flags; ret = clk_register(clk, "sandbox_clk_gate2", name, parent_name); if (ret) { @@ -272,7 +273,7 @@ static int sandbox_clk_ccf_probe(struct udevice *dev) reg = BIT(28) | BIT(24) | BIT(16); clk_dm(SANDBOX_CLK_I2C, sandbox_clk_composite("i2c", i2c_sels, ARRAY_SIZE(i2c_sels), - ®, 0)); + ®, CLK_SET_RATE_UNGATE)); clk_dm(SANDBOX_CLK_I2C_ROOT, sandbox_clk_gate2("i2c_root", "i2c", base + 0x7c, 0)); diff --git a/test/dm/clk_ccf.c b/test/dm/clk_ccf.c index 960cb2db0d..242d2d756f 100644 --- a/test/dm/clk_ccf.c +++ b/test/dm/clk_ccf.c @@ -30,11 +30,13 @@ static int dm_test_clk_ccf(struct unit_test_state *uts) ret = clk_get_by_id(SANDBOX_CLK_ECSPI_ROOT, &clk); ut_assertok(ret); ut_asserteq_str("ecspi_root", clk->dev->name); + ut_asserteq(CLK_SET_RATE_PARENT, clk->flags); /* Test for clk_get_parent_rate() */ ret = clk_get_by_id(SANDBOX_CLK_ECSPI1, &clk); ut_assertok(ret); ut_asserteq_str("ecspi1", clk->dev->name); + ut_asserteq(CLK_SET_RATE_PARENT, clk->flags); rate = clk_get_parent_rate(clk); ut_asserteq(rate, 20000000); @@ -43,6 +45,7 @@ static int dm_test_clk_ccf(struct unit_test_state *uts) ret = clk_get_by_id(SANDBOX_CLK_ECSPI0, &clk); ut_assertok(ret); ut_asserteq_str("ecspi0", clk->dev->name); + ut_asserteq(CLK_SET_RATE_PARENT, clk->flags); rate = clk_get_parent_rate(clk); ut_asserteq(rate, 20000000); @@ -51,6 +54,7 @@ static int dm_test_clk_ccf(struct unit_test_state *uts) ret = clk_get_by_id(SANDBOX_CLK_USDHC1_SEL, &clk); ut_assertok(ret); ut_asserteq_str("usdhc1_sel", clk->dev->name); + ut_asserteq(CLK_SET_RATE_NO_REPARENT, clk->flags); rate = clk_get_parent_rate(clk); ut_asserteq(rate, 60000000); @@ -58,17 +62,20 @@ static int dm_test_clk_ccf(struct unit_test_state *uts) ret = clk_get_by_id(SANDBOX_CLK_USDHC2_SEL, &clk); ut_assertok(ret); ut_asserteq_str("usdhc2_sel", clk->dev->name); + ut_asserteq(CLK_SET_RATE_NO_REPARENT, clk->flags); rate = clk_get_parent_rate(clk); ut_asserteq(rate, 80000000); pclk = clk_get_parent(clk); ut_asserteq_str("pll3_80m", pclk->dev->name); + ut_asserteq(CLK_SET_RATE_PARENT, pclk->flags); /* Test the composite of CCF */ ret = clk_get_by_id(SANDBOX_CLK_I2C, &clk); ut_assertok(ret); ut_asserteq_str("i2c", clk->dev->name); + ut_asserteq(CLK_SET_RATE_UNGATE, clk->flags); rate = clk_get_rate(clk); ut_asserteq(rate, 60000000); From 7b0830d41f9e0350207ae3f5137ad8c50731374b Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Sat, 2 May 2020 17:38:11 +0200 Subject: [PATCH 07/14] clk: fix the console output of clk_register The parent->name variable can be used only in case the uclass_get_device_by_name routine returns successfully. Signed-off-by: Dario Binacchi --- drivers/clk/clk.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 0f55ba751c..786f4e887e 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -22,13 +22,13 @@ int clk_register(struct clk *clk, const char *drv_name, ret = uclass_get_device_by_name(UCLASS_CLK, parent_name, &parent); if (ret) { - printf("%s: name: %s parent: %s [0x%p]\n", - __func__, name, parent->name, parent); + printf("%s: failed to get %s device (parent of %s)\n", + __func__, parent_name, name); + } else { + debug("%s: name: %s parent: %s [0x%p]\n", __func__, name, + parent->name, parent); } - debug("%s: name: %s parent: %s [0x%p]\n", __func__, name, parent->name, - parent); - drv = lists_driver_lookup_name(drv_name); if (!drv) { printf("%s: %s is not a valid driver name\n", From 76eaa2d0ed655da19fc1ea00cab054e19be33ecc Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Sat, 2 May 2020 17:58:31 +0200 Subject: [PATCH 08/14] clk: ccf: mux: change include order Apply u-boot coding style on include files order. Signed-off-by: Dario Binacchi --- drivers/clk/clk-mux.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 679d66a85b..69f1e9cc99 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -22,16 +22,16 @@ */ #include -#include -#include +#include #include #include #include #include +#include +#include #include -#include -#include "clk.h" #include +#include "clk.h" #define UBOOT_DM_CLK_CCF_MUX "ccf_clk_mux" From 40559d277481a47abc8e42f287fd67a19e9592d9 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Sat, 2 May 2020 17:58:32 +0200 Subject: [PATCH 09/14] clk: ccf: mux: fix typo Close the opening bracket. Signed-off-by: Dario Binacchi --- drivers/clk/clk-mux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 69f1e9cc99..978f3a8a14 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -191,7 +191,7 @@ struct clk *clk_hw_register_mux_table(struct device *dev, const char *name, * Read the current mux setup - so we assign correct parent. * * Changing parent would require changing internals of udevice struct - * for the corresponding clock (to do that define .set_parent() method. + * for the corresponding clock (to do that define .set_parent() method). */ ret = clk_register(clk, UBOOT_DM_CLK_CCF_MUX, name, parent_names[clk_mux_get_parent(clk)]); From e3b5d74c778a8782f763412679ca4c3cb2d496c3 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Sat, 2 May 2020 17:58:33 +0200 Subject: [PATCH 10/14] clk: ccf: mux: fix access to the sandbox register The tests developed for the mux clock are run on the sandbox. They don't call the clk_mux_set_parent routine and therefore they do not detect this error. Signed-off-by: Dario Binacchi --- drivers/clk/clk-mux.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 978f3a8a14..e10baaf83b 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -131,12 +131,20 @@ static int clk_mux_set_parent(struct clk *clk, struct clk *parent) if (mux->flags & CLK_MUX_HIWORD_MASK) { reg = mux->mask << (mux->shift + 16); } else { +#if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF) + reg = mux->io_mux_val; +#else reg = readl(mux->reg); +#endif reg &= ~(mux->mask << mux->shift); } val = val << mux->shift; reg |= val; +#if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF) + mux->io_mux_val = reg; +#else writel(reg, mux->reg); +#endif return 0; } From 12d152620d9de9ea966e1136b7f48f641c981bac Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 3 Jun 2020 15:36:25 +0200 Subject: [PATCH 11/14] clk: ccf: mux: change the get_rate helper The previous version of the get_rate helper does not work if the mux clock parent is changed after the probe. This error has not been detected because this condition has not been tested. The error occurs because the set_parent helper does not change the parent of the clock device but only the clock selection register. Since changing the parent of a probed device can be tricky, the new version of the get_rate helper provides the rate of the selected clock and not that of the parent. Signed-off-by: Dario Binacchi --- drivers/clk/clk-mux.c | 26 +++++++++++++++++++++++++- test/dm/clk_ccf.c | 24 ++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index e10baaf83b..ec8017b7d2 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -149,8 +149,32 @@ static int clk_mux_set_parent(struct clk *clk, struct clk *parent) return 0; } +static ulong clk_mux_get_rate(struct clk *clk) +{ + struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ? + dev_get_clk_ptr(clk->dev) : clk); + struct udevice *parent; + struct clk *pclk; + int err, index; + + index = clk_mux_get_parent(clk); + if (index >= mux->num_parents) + return -EFAULT; + + err = uclass_get_device_by_name(UCLASS_CLK, mux->parent_names[index], + &parent); + if (err) + return err; + + pclk = dev_get_clk_ptr(parent); + if (!pclk) + return -ENODEV; + + return clk_get_rate(pclk); +} + const struct clk_ops clk_mux_ops = { - .get_rate = clk_generic_get_rate, + .get_rate = clk_mux_get_rate, .set_parent = clk_mux_set_parent, }; diff --git a/test/dm/clk_ccf.c b/test/dm/clk_ccf.c index 242d2d756f..32bc4d2b8a 100644 --- a/test/dm/clk_ccf.c +++ b/test/dm/clk_ccf.c @@ -59,6 +59,18 @@ static int dm_test_clk_ccf(struct unit_test_state *uts) rate = clk_get_parent_rate(clk); ut_asserteq(rate, 60000000); + rate = clk_get_rate(clk); + ut_asserteq(rate, 60000000); + + ret = clk_get_by_id(SANDBOX_CLK_PLL3_80M, &pclk); + ut_assertok(ret); + + ret = clk_set_parent(clk, pclk); + ut_assertok(ret); + + rate = clk_get_rate(clk); + ut_asserteq(rate, 80000000); + ret = clk_get_by_id(SANDBOX_CLK_USDHC2_SEL, &clk); ut_assertok(ret); ut_asserteq_str("usdhc2_sel", clk->dev->name); @@ -71,6 +83,18 @@ static int dm_test_clk_ccf(struct unit_test_state *uts) ut_asserteq_str("pll3_80m", pclk->dev->name); ut_asserteq(CLK_SET_RATE_PARENT, pclk->flags); + rate = clk_get_rate(clk); + ut_asserteq(rate, 80000000); + + ret = clk_get_by_id(SANDBOX_CLK_PLL3_60M, &pclk); + ut_assertok(ret); + + ret = clk_set_parent(clk, pclk); + ut_assertok(ret); + + rate = clk_get_rate(clk); + ut_asserteq(rate, 60000000); + /* Test the composite of CCF */ ret = clk_get_by_id(SANDBOX_CLK_I2C, &clk); ut_assertok(ret); From cc6328412c3ba40c324f531fa5648d08573db110 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 30 Jul 2020 14:04:09 +0200 Subject: [PATCH 12/14] cmd: clk: cosmetic: correct code alignment in show_clks Correct code alignment in show_clks() function. Signed-off-by: Patrick Delaunay Reviewed-by: Simon Glass --- cmd/clk.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/cmd/clk.c b/cmd/clk.c index 439736d072..ba4540334a 100644 --- a/cmd/clk.c +++ b/cmd/clk.c @@ -25,24 +25,24 @@ static void show_clks(struct udevice *dev, int depth, int last_flag) if (device_get_uclass_id(dev) == UCLASS_CLK && clkp) { rate = clk_get_rate(clkp); - printf(" %-12u %8d ", rate, clkp->enable_count); + printf(" %-12u %8d ", rate, clkp->enable_count); - for (i = depth; i >= 0; i--) { - is_last = (last_flag >> i) & 1; - if (i) { - if (is_last) - printf(" "); - else - printf("| "); - } else { - if (is_last) - printf("`-- "); - else - printf("|-- "); + for (i = depth; i >= 0; i--) { + is_last = (last_flag >> i) & 1; + if (i) { + if (is_last) + printf(" "); + else + printf("| "); + } else { + if (is_last) + printf("`-- "); + else + printf("|-- "); + } } - } - printf("%s\n", dev->name); + printf("%s\n", dev->name); } list_for_each_entry(child, &dev->child_head, sibling_node) { From 689ca8c5d123445a1d23f515fd1c8fb407cfb622 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 30 Jul 2020 14:04:10 +0200 Subject: [PATCH 13/14] cmd: clk: correctly handle depth for clk dump Update depth only when clock uclass is found to have correct display of command "clk dump". Without this patch, the displayed depth is the binding depth for all the uclass and that can be strange as only clock uclass nodes are displayed. Signed-off-by: Patrick Delaunay Reviewed-by: Simon Glass --- cmd/clk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/clk.c b/cmd/clk.c index ba4540334a..e3c3d2f9bb 100644 --- a/cmd/clk.c +++ b/cmd/clk.c @@ -23,6 +23,7 @@ static void show_clks(struct udevice *dev, int depth, int last_flag) clkp = dev_get_clk_ptr(dev); if (device_get_uclass_id(dev) == UCLASS_CLK && clkp) { + depth++; rate = clk_get_rate(clkp); printf(" %-12u %8d ", rate, clkp->enable_count); @@ -47,7 +48,7 @@ static void show_clks(struct udevice *dev, int depth, int last_flag) list_for_each_entry(child, &dev->child_head, sibling_node) { is_last = list_is_last(&child->sibling_node, &dev->child_head); - show_clks(child, depth + 1, (last_flag << 1) | is_last); + show_clks(child, depth, (last_flag << 1) | is_last); } } From ebd3f1f0d032cc35dfb8d03da7f7ade6e9a51aef Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Mon, 24 Aug 2020 11:12:18 +0200 Subject: [PATCH 14/14] clk: ccf: Add missing #include to clk-mux.c After adding custom get_rate helper function it was necessary to include to avoid warnings about missing uclass_get_device_by_name. Signed-off-by: Lukasz Majewski Series-to: u-boot --- drivers/clk/clk-mux.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index ec8017b7d2..7a5ee7a45f 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include