From 691dc382769e350d4bc6f90a8edcacf7f8863d70 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 12 Feb 2019 18:50:51 +0100 Subject: clk: samsung: exynos5410: Add gate clock for ADC Add the gate clock for ADC block on Exynos5410. Signed-off-by: Krzysztof Kozlowski Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5410.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/clk') diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c index 0a0b09591e6f..b2da2c8fa0c7 100644 --- a/drivers/clk/samsung/clk-exynos5410.c +++ b/drivers/clk/samsung/clk-exynos5410.c @@ -209,6 +209,7 @@ static const struct samsung_gate_clock exynos5410_gate_clks[] __initconst = { GATE(CLK_USI1, "usi1", "aclk66", GATE_IP_PERIC, 11, 0, 0), GATE(CLK_USI2, "usi2", "aclk66", GATE_IP_PERIC, 12, 0, 0), GATE(CLK_USI3, "usi3", "aclk66", GATE_IP_PERIC, 13, 0, 0), + GATE(CLK_TSADC, "tsadc", "aclk66", GATE_IP_PERIC, 15, 0, 0), GATE(CLK_PWM, "pwm", "aclk66", GATE_IP_PERIC, 24, 0, 0), GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0", -- cgit v1.2.3 From 60d74e011c8e7450846563739a8530f823e5d77a Mon Sep 17 00:00:00 2001 From: Rajan Vaja Date: Mon, 4 Mar 2019 15:27:46 -0800 Subject: drivers: clk: zynqmp: Allow zero divisor value Zero divider is valid and default for some of ZynqMP clocks. Allow zero divisor when CLK_DIVIDER_ALLOW_ZERO for the clock is set. Signed-off-by: Rajan Vaja Signed-off-by: Jolly Shah Signed-off-by: Stephen Boyd --- drivers/clk/zynqmp/divider.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/zynqmp/divider.c b/drivers/clk/zynqmp/divider.c index a371c66e72ef..e146b6fac6b2 100644 --- a/drivers/clk/zynqmp/divider.c +++ b/drivers/clk/zynqmp/divider.c @@ -76,6 +76,13 @@ static unsigned long zynqmp_clk_divider_recalc_rate(struct clk_hw *hw, else value = div >> 16; + if (!value) { + WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO), + "%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n", + clk_name); + return parent_rate; + } + return DIV_ROUND_UP_ULL(parent_rate, value); } -- cgit v1.2.3 From d3e4ebc18753c429e64cf92cd70616f51fa6f543 Mon Sep 17 00:00:00 2001 From: Rajan Vaja Date: Mon, 4 Mar 2019 15:19:10 -0800 Subject: drivers: clk: Update clock driver to handle clock attribute Versal EEMI APIs uses clock device ID which is combination of class, subclass, type and clock index (e.g. 0x8104006 in which 0-13 bits are for index(6 in given example), 14-19 bits are for clock type (i.e pll, out or ref, 1 in given example), 20-25 bits are for subclass which is nothing but clock type only), 26-32 bits are for device class, which is clock(0x2) for all clocks) while zynqmp firmware uses clock ID which is index only (e.g 0, 1, to n, where n is max_clock id). To use zynqmp clock driver for versal platform also, extend use of QueryAttribute API to fetch device class, subclass and clock type to create clock device ID. In case of zynqmp this attributes would be 0 only, so there won't be any effect on clock id as it would use clock index only. Signed-off-by: Tejas Patel Signed-off-by: Rajan Vaja Signed-off-by: Michal Simek Signed-off-by: Jolly Shah Signed-off-by: Stephen Boyd --- drivers/clk/zynqmp/clkc.c | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/zynqmp/clkc.c b/drivers/clk/zynqmp/clkc.c index b0908ec62f73..112ae7d157e1 100644 --- a/drivers/clk/zynqmp/clkc.c +++ b/drivers/clk/zynqmp/clkc.c @@ -53,6 +53,10 @@ #define RESERVED_CLK_NAME "" #define CLK_VALID_MASK 0x1 +#define NODE_CLASS_SHIFT 26U +#define NODE_SUBCLASS_SHIFT 20U +#define NODE_TYPE_SHIFT 14U +#define NODE_INDEX_SHIFT 0U enum clk_type { CLK_TYPE_OUTPUT, @@ -80,6 +84,7 @@ struct clock_parent { * @num_nodes: Number of nodes present in topology * @parent: Parent of clock * @num_parents: Number of parents of clock + * @clk_id: Clock id */ struct zynqmp_clock { char clk_name[MAX_NAME_LEN]; @@ -89,6 +94,7 @@ struct zynqmp_clock { u32 num_nodes; struct clock_parent parent[MAX_PARENT]; u32 num_parents; + u32 clk_id; }; static const char clk_type_postfix[][10] = { @@ -396,7 +402,8 @@ static int zynqmp_clock_get_topology(u32 clk_id, *num_nodes = 0; for (j = 0; j <= MAX_NODES; j += 3) { - ret = zynqmp_pm_clock_get_topology(clk_id, j, pm_resp); + ret = zynqmp_pm_clock_get_topology(clock[clk_id].clk_id, j, + pm_resp); if (ret) return ret; ret = __zynqmp_clock_get_topology(topology, pm_resp, num_nodes); @@ -459,7 +466,8 @@ static int zynqmp_clock_get_parents(u32 clk_id, struct clock_parent *parents, *num_parents = 0; do { /* Get parents from firmware */ - ret = zynqmp_pm_clock_get_parents(clk_id, j, pm_resp); + ret = zynqmp_pm_clock_get_parents(clock[clk_id].clk_id, j, + pm_resp); if (ret) return ret; @@ -528,13 +536,14 @@ static struct clk_hw *zynqmp_register_clk_topology(int clk_id, char *clk_name, const char **parent_names) { int j; - u32 num_nodes; + u32 num_nodes, clk_dev_id; char *clk_out = NULL; struct clock_topology *nodes; struct clk_hw *hw = NULL; nodes = clock[clk_id].node; num_nodes = clock[clk_id].num_nodes; + clk_dev_id = clock[clk_id].clk_id; for (j = 0; j < num_nodes; j++) { /* @@ -551,13 +560,14 @@ static struct clk_hw *zynqmp_register_clk_topology(int clk_id, char *clk_name, if (!clk_topology[nodes[j].type]) continue; - hw = (*clk_topology[nodes[j].type])(clk_out, clk_id, + hw = (*clk_topology[nodes[j].type])(clk_out, clk_dev_id, parent_names, num_parents, &nodes[j]); if (IS_ERR(hw)) - pr_warn_once("%s() %s register fail with %ld\n", - __func__, clk_name, PTR_ERR(hw)); + pr_warn_once("%s() 0x%x: %s register fail with %ld\n", + __func__, clk_dev_id, clk_name, + PTR_ERR(hw)); parent_names[0] = clk_out; } @@ -621,20 +631,26 @@ static int zynqmp_register_clocks(struct device_node *np) static void zynqmp_get_clock_info(void) { int i, ret; - u32 attr, type = 0; + u32 attr, type = 0, nodetype, subclass, class; for (i = 0; i < clock_max_idx; i++) { - zynqmp_pm_clock_get_name(i, clock[i].clk_name); - if (!strcmp(clock[i].clk_name, RESERVED_CLK_NAME)) - continue; - ret = zynqmp_pm_clock_get_attributes(i, &attr); if (ret) continue; clock[i].valid = attr & CLK_VALID_MASK; - clock[i].type = attr >> CLK_TYPE_SHIFT ? CLK_TYPE_EXTERNAL : - CLK_TYPE_OUTPUT; + clock[i].type = ((attr >> CLK_TYPE_SHIFT) & 0x1) ? + CLK_TYPE_EXTERNAL : CLK_TYPE_OUTPUT; + nodetype = (attr >> NODE_TYPE_SHIFT) & 0x3F; + subclass = (attr >> NODE_SUBCLASS_SHIFT) & 0x3F; + class = (attr >> NODE_CLASS_SHIFT) & 0x3F; + + clock[i].clk_id = (class << NODE_CLASS_SHIFT) | + (subclass << NODE_SUBCLASS_SHIFT) | + (nodetype << NODE_TYPE_SHIFT) | + (i << NODE_INDEX_SHIFT); + + zynqmp_pm_clock_get_name(clock[i].clk_id, clock[i].clk_name); } /* Get topology of all clock */ -- cgit v1.2.3 From 5e088faecb4b880d0c9e11324714631610237397 Mon Sep 17 00:00:00 2001 From: Michael Tretter Date: Tue, 19 Mar 2019 11:01:44 +0100 Subject: clk: zynqmp: fix kerneldoc of __zynqmp_clock_get_parents The kerneldoc refers to __zynqmp_clock_get_topology(), but actually documents __zynqmp_clock_get_parents(). Refer to the correct function name in the kerneldoc. Signed-off-by: Michael Tretter Signed-off-by: Stephen Boyd --- drivers/clk/zynqmp/clkc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/zynqmp/clkc.c b/drivers/clk/zynqmp/clkc.c index 112ae7d157e1..8b9d94a2e775 100644 --- a/drivers/clk/zynqmp/clkc.c +++ b/drivers/clk/zynqmp/clkc.c @@ -415,7 +415,7 @@ static int zynqmp_clock_get_topology(u32 clk_id, } /** - * __zynqmp_clock_get_topology() - Get parents info of clock from firmware + * __zynqmp_clock_get_parents() - Get parents info of clock from firmware * response data * @parents: Clock parents * @data: Clock parents data received from firmware -- cgit v1.2.3 From e91158f1be5b157329ab8f21f86728d591c8f747 Mon Sep 17 00:00:00 2001 From: Michael Tretter Date: Tue, 19 Mar 2019 11:01:45 +0100 Subject: clk: zynqmp: do not export zynqmp_clk_register_* functions The zynqmp_clk_register_* functions are internal functions of the driver. Only clkc.c uses these functions to register these clocks. Therefore, there is no need to export these functions. The gate and pll already don't export their register_* functions. Signed-off-by: Michael Tretter Signed-off-by: Stephen Boyd --- drivers/clk/zynqmp/clk-mux-zynqmp.c | 1 - drivers/clk/zynqmp/divider.c | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/zynqmp/clk-mux-zynqmp.c b/drivers/clk/zynqmp/clk-mux-zynqmp.c index 4143f560c28d..0af8f74c5fa5 100644 --- a/drivers/clk/zynqmp/clk-mux-zynqmp.c +++ b/drivers/clk/zynqmp/clk-mux-zynqmp.c @@ -138,4 +138,3 @@ struct clk_hw *zynqmp_clk_register_mux(const char *name, u32 clk_id, return hw; } -EXPORT_SYMBOL_GPL(zynqmp_clk_register_mux); diff --git a/drivers/clk/zynqmp/divider.c b/drivers/clk/zynqmp/divider.c index e146b6fac6b2..a621c6619abe 100644 --- a/drivers/clk/zynqmp/divider.c +++ b/drivers/clk/zynqmp/divider.c @@ -221,4 +221,3 @@ struct clk_hw *zynqmp_clk_register_divider(const char *name, return hw; } -EXPORT_SYMBOL_GPL(zynqmp_clk_register_divider); -- cgit v1.2.3 From c06e64407e031e71c67f45f07981510ca4c880a1 Mon Sep 17 00:00:00 2001 From: Michael Tretter Date: Tue, 19 Mar 2019 11:01:46 +0100 Subject: clk: zynqmp: fix check for fractional clock The firmware sets BIT(13) in clkflag to mark a divider as fractional divider. The clock driver copies the clkflag straight to the flags of the common clock framework. In the common clk framework flags, BIT(13) is defined as CLK_DUTY_CYCLE_PARENT. Add a new field to the zynqmp_clk_divider to specify if a divider is a fractional devider. Set this field based on the clkflag when registering a divider. At the same time, unset BIT(13) from clkflag when copying the flags to the common clk framework flags. Signed-off-by: Michael Tretter Signed-off-by: Stephen Boyd --- drivers/clk/zynqmp/divider.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/zynqmp/divider.c b/drivers/clk/zynqmp/divider.c index a621c6619abe..d8f5b70d2709 100644 --- a/drivers/clk/zynqmp/divider.c +++ b/drivers/clk/zynqmp/divider.c @@ -31,12 +31,14 @@ * struct zynqmp_clk_divider - adjustable divider clock * @hw: handle between common and hardware-specific interfaces * @flags: Hardware specific flags + * @is_frac: The divider is a fractional divider * @clk_id: Id of clock * @div_type: divisor type (TYPE_DIV1 or TYPE_DIV2) */ struct zynqmp_clk_divider { struct clk_hw hw; u8 flags; + bool is_frac; u32 clk_id; u32 div_type; }; @@ -123,8 +125,7 @@ static long zynqmp_clk_divider_round_rate(struct clk_hw *hw, bestdiv = zynqmp_divider_get_val(*prate, rate); - if ((clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) && - (divider->flags & CLK_FRAC)) + if ((clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) && divider->is_frac) bestdiv = rate % *prate ? 1 : bestdiv; *prate = rate * bestdiv; @@ -202,11 +203,13 @@ struct clk_hw *zynqmp_clk_register_divider(const char *name, init.name = name; init.ops = &zynqmp_clk_divider_ops; - init.flags = nodes->flag; + /* CLK_FRAC is not defined in the common clk framework */ + init.flags = nodes->flag & ~CLK_FRAC; init.parent_names = parents; init.num_parents = 1; /* struct clk_divider assignments */ + div->is_frac = !!(nodes->flag & CLK_FRAC); div->flags = nodes->type_flag; div->hw.init = &init; div->clk_id = clk_id; -- cgit v1.2.3 From 33c70c13992fef95d95df9a0b71d114e02cdae97 Mon Sep 17 00:00:00 2001 From: Ding Xiang Date: Fri, 15 Mar 2019 15:29:24 +0800 Subject: clk: davinci: cfgchip: use PTR_ERR_OR_ZERO in da8xx_cfgchip_register_div4p5 use PTR_ERR_OR_ZERO inetead of return code Signed-off-by: Ding Xiang Signed-off-by: Stephen Boyd --- drivers/clk/davinci/da8xx-cfgchip.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/davinci/da8xx-cfgchip.c b/drivers/clk/davinci/da8xx-cfgchip.c index d1bbee19ed0f..bdc52364b421 100644 --- a/drivers/clk/davinci/da8xx-cfgchip.c +++ b/drivers/clk/davinci/da8xx-cfgchip.c @@ -160,10 +160,8 @@ static int __init da8xx_cfgchip_register_div4p5(struct device *dev, struct da8xx_cfgchip_gate_clk *gate; gate = da8xx_cfgchip_gate_clk_register(dev, &da8xx_div4p5ena_info, regmap); - if (IS_ERR(gate)) - return PTR_ERR(gate); - return 0; + return PTR_ERR_OR_ZERO(gate); } static int __init -- cgit v1.2.3 From b331db554815d0552c537e189b897eb062486166 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Tue, 19 Mar 2019 23:35:04 +0800 Subject: clk: tegra: Make tegra_clk_super_mux_ops static Fix sparse warning: drivers/clk/tegra/clk-super.c:124:22: warning: symbol 'tegra_clk_super_mux_ops' was not declared. Should it be static? Signed-off-by: YueHaibing Acked-by: Thierry Reding Signed-off-by: Stephen Boyd --- drivers/clk/tegra/clk-super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/tegra/clk-super.c b/drivers/clk/tegra/clk-super.c index 84267cfc4433..b5ff76c663f8 100644 --- a/drivers/clk/tegra/clk-super.c +++ b/drivers/clk/tegra/clk-super.c @@ -121,7 +121,7 @@ out: return err; } -const struct clk_ops tegra_clk_super_mux_ops = { +static const struct clk_ops tegra_clk_super_mux_ops = { .get_parent = clk_super_get_parent, .set_parent = clk_super_set_parent, }; -- cgit v1.2.3 From c942081c87dd532397d796b5c0196e95d5d45092 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Thu, 11 Apr 2019 13:04:11 +0200 Subject: clk: ux500: add range to usleep_range Providing a range for usleep_range() allows the hrtimer subsystem to coalesce timers - the delay is runtime configurable so a factor 2 is taken to provide the range. With the expected range for enable_delay_us being milliseconds, the range should lie in the 250us range which is sufficient for hrtimer optimization. Signed-off-by: Nicholas Mc Guire Acked-by: Ulf Hansson Signed-off-by: Stephen Boyd --- drivers/clk/ux500/clk-sysctrl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/ux500/clk-sysctrl.c b/drivers/clk/ux500/clk-sysctrl.c index 7c0403b733ae..698306f4801f 100644 --- a/drivers/clk/ux500/clk-sysctrl.c +++ b/drivers/clk/ux500/clk-sysctrl.c @@ -42,7 +42,8 @@ static int clk_sysctrl_prepare(struct clk_hw *hw) clk->reg_bits[0]); if (!ret && clk->enable_delay_us) - usleep_range(clk->enable_delay_us, clk->enable_delay_us); + usleep_range(clk->enable_delay_us, clk->enable_delay_us + + (clk->enable_delay_us >> 2)); return ret; } -- cgit v1.2.3 From eaa9558d35aee594c9658d92852e537a0fb897d7 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Tue, 19 Mar 2019 15:05:36 +0100 Subject: clk: ingenic: jz4725b: Add UDC PHY clock Add clock for the USB Device Controller PHY. Signed-off-by: Paul Cercueil Signed-off-by: Stephen Boyd --- drivers/clk/ingenic/jz4725b-cgu.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/ingenic/jz4725b-cgu.c b/drivers/clk/ingenic/jz4725b-cgu.c index 584ff4ff81c7..8901ea0295b7 100644 --- a/drivers/clk/ingenic/jz4725b-cgu.c +++ b/drivers/clk/ingenic/jz4725b-cgu.c @@ -205,6 +205,12 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = { .parents = { JZ4725B_CLK_EXT512, JZ4725B_CLK_OSC32K, -1, -1 }, .mux = { CGU_REG_OPCR, 2, 1}, }, + + [JZ4725B_CLK_UDC_PHY] = { + "udc_phy", CGU_CLK_GATE, + .parents = { JZ4725B_CLK_EXT, -1, -1, -1 }, + .gate = { CGU_REG_OPCR, 6, true }, + }, }; static void __init jz4725b_cgu_init(struct device_node *np) -- cgit v1.2.3 From 7fbb639aea353832046a72ad3201510cada27f9a Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 16 Apr 2019 12:56:16 +0100 Subject: clk: mvebu: fix spelling mistake "gatable" -> "gateable" There are a few spelling mistakes in comments and a pr_err error message. Fix these. Signed-off-by: Colin Ian King Reviewed-by: Mukesh Ojha Signed-off-by: Stephen Boyd --- drivers/clk/mvebu/common.c | 2 +- drivers/clk/mvebu/cp110-system-controller.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/mvebu/common.c b/drivers/clk/mvebu/common.c index 6ab3c2e627c7..785dbede4835 100644 --- a/drivers/clk/mvebu/common.c +++ b/drivers/clk/mvebu/common.c @@ -240,7 +240,7 @@ void __init mvebu_clk_gating_setup(struct device_node *np, int n; if (ctrl) { - pr_err("mvebu-clk-gating: cannot instantiate more than one gatable clock device\n"); + pr_err("mvebu-clk-gating: cannot instantiate more than one gateable clock device\n"); return; } diff --git a/drivers/clk/mvebu/cp110-system-controller.c b/drivers/clk/mvebu/cp110-system-controller.c index 9235a331b588..b6de283f45e3 100644 --- a/drivers/clk/mvebu/cp110-system-controller.c +++ b/drivers/clk/mvebu/cp110-system-controller.c @@ -21,7 +21,7 @@ * - Equal to SDIO clock * - 2/5 PLL0 * - * CP110 has 32 gatable clocks, for the various peripherals in the IP. + * CP110 has 32 gateable clocks, for the various peripherals in the IP. */ #define pr_fmt(fmt) "cp110-system-controller: " fmt @@ -57,7 +57,7 @@ enum { #define CP110_CORE_NAND 4 #define CP110_CORE_SDIO 5 -/* A number of gatable clocks need special handling */ +/* A number of gateable clocks need special handling */ #define CP110_GATE_AUDIO 0 #define CP110_GATE_COMM_UNIT 1 #define CP110_GATE_NAND 2 -- cgit v1.2.3 From defb149ba42f571017fb4bc265eecf3648ab7d6e Mon Sep 17 00:00:00 2001 From: Eddie James Date: Tue, 2 Apr 2019 18:25:03 +0000 Subject: clk: Aspeed: Setup video engine clocking Add eclk mux and clock divider table. Also change the video engine reset to the correct clock; it was previously on the video capture but needs to be on the video engine clock. Signed-off-by: Eddie James Reviewed-by: Joel Stanley Signed-off-by: Stephen Boyd --- drivers/clk/clk-aspeed.c | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/clk-aspeed.c b/drivers/clk/clk-aspeed.c index 596136793fc4..42b4df6ba249 100644 --- a/drivers/clk/clk-aspeed.c +++ b/drivers/clk/clk-aspeed.c @@ -87,10 +87,10 @@ struct aspeed_clk_gate { /* TODO: ask Aspeed about the actual parent data */ static const struct aspeed_gate_data aspeed_gates[] = { /* clk rst name parent flags */ - [ASPEED_CLK_GATE_ECLK] = { 0, -1, "eclk-gate", "eclk", 0 }, /* Video Engine */ + [ASPEED_CLK_GATE_ECLK] = { 0, 6, "eclk-gate", "eclk", 0 }, /* Video Engine */ [ASPEED_CLK_GATE_GCLK] = { 1, 7, "gclk-gate", NULL, 0 }, /* 2D engine */ [ASPEED_CLK_GATE_MCLK] = { 2, -1, "mclk-gate", "mpll", CLK_IS_CRITICAL }, /* SDRAM */ - [ASPEED_CLK_GATE_VCLK] = { 3, 6, "vclk-gate", NULL, 0 }, /* Video Capture */ + [ASPEED_CLK_GATE_VCLK] = { 3, -1, "vclk-gate", NULL, 0 }, /* Video Capture */ [ASPEED_CLK_GATE_BCLK] = { 4, 8, "bclk-gate", "bclk", CLK_IS_CRITICAL }, /* PCIe/PCI */ [ASPEED_CLK_GATE_DCLK] = { 5, -1, "dclk-gate", NULL, CLK_IS_CRITICAL }, /* DAC */ [ASPEED_CLK_GATE_REFCLK] = { 6, -1, "refclk-gate", "clkin", CLK_IS_CRITICAL }, @@ -113,6 +113,24 @@ static const struct aspeed_gate_data aspeed_gates[] = { [ASPEED_CLK_GATE_LHCCLK] = { 28, -1, "lhclk-gate", "lhclk", 0 }, /* LPC master/LPC+ */ }; +static const char * const eclk_parent_names[] = { + "mpll", + "hpll", + "dpll", +}; + +static const struct clk_div_table ast2500_eclk_div_table[] = { + { 0x0, 2 }, + { 0x1, 2 }, + { 0x2, 3 }, + { 0x3, 4 }, + { 0x4, 5 }, + { 0x5, 6 }, + { 0x6, 7 }, + { 0x7, 8 }, + { 0 } +}; + static const struct clk_div_table ast2500_mac_div_table[] = { { 0x0, 4 }, /* Yep, really. Aspeed confirmed this is correct */ { 0x1, 4 }, @@ -192,18 +210,21 @@ static struct clk_hw *aspeed_ast2500_calc_pll(const char *name, u32 val) struct aspeed_clk_soc_data { const struct clk_div_table *div_table; + const struct clk_div_table *eclk_div_table; const struct clk_div_table *mac_div_table; struct clk_hw *(*calc_pll)(const char *name, u32 val); }; static const struct aspeed_clk_soc_data ast2500_data = { .div_table = ast2500_div_table, + .eclk_div_table = ast2500_eclk_div_table, .mac_div_table = ast2500_mac_div_table, .calc_pll = aspeed_ast2500_calc_pll, }; static const struct aspeed_clk_soc_data ast2400_data = { .div_table = ast2400_div_table, + .eclk_div_table = ast2400_div_table, .mac_div_table = ast2400_div_table, .calc_pll = aspeed_ast2400_calc_pll, }; @@ -522,6 +543,22 @@ static int aspeed_clk_probe(struct platform_device *pdev) return PTR_ERR(hw); aspeed_clk_data->hws[ASPEED_CLK_24M] = hw; + hw = clk_hw_register_mux(dev, "eclk-mux", eclk_parent_names, + ARRAY_SIZE(eclk_parent_names), 0, + scu_base + ASPEED_CLK_SELECTION, 2, 0x3, 0, + &aspeed_clk_lock); + if (IS_ERR(hw)) + return PTR_ERR(hw); + aspeed_clk_data->hws[ASPEED_CLK_ECLK_MUX] = hw; + + hw = clk_hw_register_divider_table(dev, "eclk", "eclk-mux", 0, + scu_base + ASPEED_CLK_SELECTION, 28, + 3, 0, soc_data->eclk_div_table, + &aspeed_clk_lock); + if (IS_ERR(hw)) + return PTR_ERR(hw); + aspeed_clk_data->hws[ASPEED_CLK_ECLK] = hw; + /* * TODO: There are a number of clocks that not included in this driver * as more information is required: @@ -531,7 +568,6 @@ static int aspeed_clk_probe(struct platform_device *pdev) * RGMII * RMII * UART[1..5] clock source mux - * Video Engine (ECLK) mux and clock divider */ for (i = 0; i < ARRAY_SIZE(aspeed_gates); i++) { -- cgit v1.2.3 From 5852b1365df4414523210e444ac7df1dec09acb4 Mon Sep 17 00:00:00 2001 From: Michael Tretter Date: Fri, 12 Apr 2019 11:52:20 +0200 Subject: clk: zynqmp: use structs for clk query responses The driver retrieves the clock tree by querying the ATF for the clock names, the clock topology, the parents and other attributes. The driver needs to unmarshal the responses. The definition of the fields in the firmware responses to the queries is inconsistent. Some are specified as a mask, some as a shift, and by the length of the previous field. Define C structs for the entire firmware responses to avoid passing pointers to arrays of an implicit size and make the format of the responses to the queries obvious. Signed-off-by: Michael Tretter Reviewed-by: Jolly Shah [sboyd@kernel.org: Drop 0 initializers because sparse complains] Signed-off-by: Stephen Boyd --- drivers/clk/zynqmp/clk-zynqmp.h | 6 -- drivers/clk/zynqmp/clkc.c | 170 +++++++++++++++++++++++----------------- 2 files changed, 99 insertions(+), 77 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/zynqmp/clk-zynqmp.h b/drivers/clk/zynqmp/clk-zynqmp.h index 7ab163b67249..fec9a15c8786 100644 --- a/drivers/clk/zynqmp/clk-zynqmp.h +++ b/drivers/clk/zynqmp/clk-zynqmp.h @@ -10,12 +10,6 @@ #include -/* Clock APIs payload parameters */ -#define CLK_GET_NAME_RESP_LEN 16 -#define CLK_GET_TOPOLOGY_RESP_WORDS 3 -#define CLK_GET_PARENTS_RESP_WORDS 3 -#define CLK_GET_ATTR_RESP_WORDS 1 - enum topology_type { TYPE_INVALID, TYPE_MUX, diff --git a/drivers/clk/zynqmp/clkc.c b/drivers/clk/zynqmp/clkc.c index 8b9d94a2e775..8febd2431545 100644 --- a/drivers/clk/zynqmp/clkc.c +++ b/drivers/clk/zynqmp/clkc.c @@ -21,24 +21,6 @@ #define MAX_NODES 6 #define MAX_NAME_LEN 50 -#define CLK_TYPE_SHIFT 2 - -#define PM_API_PAYLOAD_LEN 3 - -#define NA_PARENT 0xFFFFFFFF -#define DUMMY_PARENT 0xFFFFFFFE - -#define CLK_TYPE_FIELD_LEN 4 -#define CLK_TOPOLOGY_NODE_OFFSET 16 -#define NODES_PER_RESP 3 - -#define CLK_TYPE_FIELD_MASK 0xF -#define CLK_FLAG_FIELD_MASK GENMASK(21, 8) -#define CLK_TYPE_FLAG_FIELD_MASK GENMASK(31, 24) - -#define CLK_PARENTS_ID_LEN 16 -#define CLK_PARENTS_ID_MASK 0xFFFF - /* Flags for parents */ #define PARENT_CLK_SELF 0 #define PARENT_CLK_NODE1 1 @@ -52,11 +34,10 @@ #define END_OF_PARENTS 1 #define RESERVED_CLK_NAME "" -#define CLK_VALID_MASK 0x1 -#define NODE_CLASS_SHIFT 26U -#define NODE_SUBCLASS_SHIFT 20U -#define NODE_TYPE_SHIFT 14U -#define NODE_INDEX_SHIFT 0U +#define CLK_GET_NAME_RESP_LEN 16 +#define CLK_GET_TOPOLOGY_RESP_WORDS 3 +#define CLK_GET_PARENTS_RESP_WORDS 3 +#define CLK_GET_ATTR_RESP_WORDS 1 enum clk_type { CLK_TYPE_OUTPUT, @@ -97,6 +78,35 @@ struct zynqmp_clock { u32 clk_id; }; +struct name_resp { + char name[CLK_GET_NAME_RESP_LEN]; +}; + +struct topology_resp { +#define CLK_TOPOLOGY_TYPE GENMASK(3, 0) +#define CLK_TOPOLOGY_FLAGS GENMASK(23, 8) +#define CLK_TOPOLOGY_TYPE_FLAGS GENMASK(31, 24) + u32 topology[CLK_GET_TOPOLOGY_RESP_WORDS]; +}; + +struct parents_resp { +#define NA_PARENT 0xFFFFFFFF +#define DUMMY_PARENT 0xFFFFFFFE +#define CLK_PARENTS_ID GENMASK(15, 0) +#define CLK_PARENTS_FLAGS GENMASK(31, 16) + u32 parents[CLK_GET_PARENTS_RESP_WORDS]; +}; + +struct attr_resp { +#define CLK_ATTR_VALID BIT(0) +#define CLK_ATTR_TYPE BIT(2) +#define CLK_ATTR_NODE_INDEX GENMASK(13, 0) +#define CLK_ATTR_NODE_TYPE GENMASK(19, 14) +#define CLK_ATTR_NODE_SUBCLASS GENMASK(25, 20) +#define CLK_ATTR_NODE_CLASS GENMASK(31, 26) + u32 attr[CLK_GET_ATTR_RESP_WORDS]; +}; + static const char clk_type_postfix[][10] = { [TYPE_INVALID] = "", [TYPE_MUX] = "_mux", @@ -205,14 +215,15 @@ static int zynqmp_pm_clock_get_num_clocks(u32 *nclocks) /** * zynqmp_pm_clock_get_name() - Get the name of clock for given id * @clock_id: ID of the clock to be queried - * @name: Name of given clock + * @response: Name of the clock with the given id * * This function is used to get name of clock specified by given * clock ID. * - * Return: Returns 0, in case of error name would be 0 + * Return: Returns 0 */ -static int zynqmp_pm_clock_get_name(u32 clock_id, char *name) +static int zynqmp_pm_clock_get_name(u32 clock_id, + struct name_resp *response) { struct zynqmp_pm_query_data qdata = {0}; u32 ret_payload[PAYLOAD_ARG_CNT]; @@ -221,7 +232,7 @@ static int zynqmp_pm_clock_get_name(u32 clock_id, char *name) qdata.arg1 = clock_id; eemi_ops->query_data(qdata, ret_payload); - memcpy(name, ret_payload, CLK_GET_NAME_RESP_LEN); + memcpy(response, ret_payload, sizeof(*response)); return 0; } @@ -230,7 +241,7 @@ static int zynqmp_pm_clock_get_name(u32 clock_id, char *name) * zynqmp_pm_clock_get_topology() - Get the topology of clock for given id * @clock_id: ID of the clock to be queried * @index: Node index of clock topology - * @topology: Buffer to store nodes in topology and flags + * @response: Buffer used for the topology response * * This function is used to get topology information for the clock * specified by given clock ID. @@ -243,7 +254,8 @@ static int zynqmp_pm_clock_get_name(u32 clock_id, char *name) * * Return: 0 on success else error+reason */ -static int zynqmp_pm_clock_get_topology(u32 clock_id, u32 index, u32 *topology) +static int zynqmp_pm_clock_get_topology(u32 clock_id, u32 index, + struct topology_resp *response) { struct zynqmp_pm_query_data qdata = {0}; u32 ret_payload[PAYLOAD_ARG_CNT]; @@ -254,7 +266,7 @@ static int zynqmp_pm_clock_get_topology(u32 clock_id, u32 index, u32 *topology) qdata.arg2 = index; ret = eemi_ops->query_data(qdata, ret_payload); - memcpy(topology, &ret_payload[1], CLK_GET_TOPOLOGY_RESP_WORDS * 4); + memcpy(response, &ret_payload[1], sizeof(*response)); return ret; } @@ -303,7 +315,7 @@ struct clk_hw *zynqmp_clk_register_fixed_factor(const char *name, u32 clk_id, * zynqmp_pm_clock_get_parents() - Get the first 3 parents of clock for given id * @clock_id: Clock ID * @index: Parent index - * @parents: 3 parents of the given clock + * @response: Parents of the given clock * * This function is used to get 3 parents for the clock specified by * given clock ID. @@ -316,7 +328,8 @@ struct clk_hw *zynqmp_clk_register_fixed_factor(const char *name, u32 clk_id, * * Return: 0 on success else error+reason */ -static int zynqmp_pm_clock_get_parents(u32 clock_id, u32 index, u32 *parents) +static int zynqmp_pm_clock_get_parents(u32 clock_id, u32 index, + struct parents_resp *response) { struct zynqmp_pm_query_data qdata = {0}; u32 ret_payload[PAYLOAD_ARG_CNT]; @@ -327,7 +340,7 @@ static int zynqmp_pm_clock_get_parents(u32 clock_id, u32 index, u32 *parents) qdata.arg2 = index; ret = eemi_ops->query_data(qdata, ret_payload); - memcpy(parents, &ret_payload[1], CLK_GET_PARENTS_RESP_WORDS * 4); + memcpy(response, &ret_payload[1], sizeof(*response)); return ret; } @@ -335,13 +348,14 @@ static int zynqmp_pm_clock_get_parents(u32 clock_id, u32 index, u32 *parents) /** * zynqmp_pm_clock_get_attributes() - Get the attributes of clock for given id * @clock_id: Clock ID - * @attr: Clock attributes + * @response: Clock attributes response * * This function is used to get clock's attributes(e.g. valid, clock type, etc). * * Return: 0 on success else error+reason */ -static int zynqmp_pm_clock_get_attributes(u32 clock_id, u32 *attr) +static int zynqmp_pm_clock_get_attributes(u32 clock_id, + struct attr_resp *response) { struct zynqmp_pm_query_data qdata = {0}; u32 ret_payload[PAYLOAD_ARG_CNT]; @@ -351,7 +365,7 @@ static int zynqmp_pm_clock_get_attributes(u32 clock_id, u32 *attr) qdata.arg1 = clock_id; ret = eemi_ops->query_data(qdata, ret_payload); - memcpy(attr, &ret_payload[1], CLK_GET_ATTR_RESP_WORDS * 4); + memcpy(response, &ret_payload[1], sizeof(*response)); return ret; } @@ -360,24 +374,28 @@ static int zynqmp_pm_clock_get_attributes(u32 clock_id, u32 *attr) * __zynqmp_clock_get_topology() - Get topology data of clock from firmware * response data * @topology: Clock topology - * @data: Clock topology data received from firmware + * @response: Clock topology data received from firmware * @nnodes: Number of nodes * * Return: 0 on success else error+reason */ static int __zynqmp_clock_get_topology(struct clock_topology *topology, - u32 *data, u32 *nnodes) + struct topology_resp *response, + u32 *nnodes) { int i; + u32 type; - for (i = 0; i < PM_API_PAYLOAD_LEN; i++) { - if (!(data[i] & CLK_TYPE_FIELD_MASK)) + for (i = 0; i < ARRAY_SIZE(response->topology); i++) { + type = FIELD_GET(CLK_TOPOLOGY_TYPE, response->topology[i]); + if (type == TYPE_INVALID) return END_OF_TOPOLOGY_NODE; - topology[*nnodes].type = data[i] & CLK_TYPE_FIELD_MASK; - topology[*nnodes].flag = FIELD_GET(CLK_FLAG_FIELD_MASK, - data[i]); + topology[*nnodes].type = type; + topology[*nnodes].flag = FIELD_GET(CLK_TOPOLOGY_FLAGS, + response->topology[i]); topology[*nnodes].type_flag = - FIELD_GET(CLK_TYPE_FLAG_FIELD_MASK, data[i]); + FIELD_GET(CLK_TOPOLOGY_TYPE_FLAGS, + response->topology[i]); (*nnodes)++; } @@ -398,15 +416,16 @@ static int zynqmp_clock_get_topology(u32 clk_id, u32 *num_nodes) { int j, ret; - u32 pm_resp[PM_API_PAYLOAD_LEN] = {0}; + struct topology_resp response = { }; *num_nodes = 0; - for (j = 0; j <= MAX_NODES; j += 3) { + for (j = 0; j <= MAX_NODES; j += ARRAY_SIZE(response.topology)) { ret = zynqmp_pm_clock_get_topology(clock[clk_id].clk_id, j, - pm_resp); + &response); if (ret) return ret; - ret = __zynqmp_clock_get_topology(topology, pm_resp, num_nodes); + ret = __zynqmp_clock_get_topology(topology, &response, + num_nodes); if (ret == END_OF_TOPOLOGY_NODE) return 0; } @@ -418,28 +437,30 @@ static int zynqmp_clock_get_topology(u32 clk_id, * __zynqmp_clock_get_parents() - Get parents info of clock from firmware * response data * @parents: Clock parents - * @data: Clock parents data received from firmware + * @response: Clock parents data received from firmware * @nparent: Number of parent * * Return: 0 on success else error+reason */ -static int __zynqmp_clock_get_parents(struct clock_parent *parents, u32 *data, +static int __zynqmp_clock_get_parents(struct clock_parent *parents, + struct parents_resp *response, u32 *nparent) { int i; struct clock_parent *parent; - for (i = 0; i < PM_API_PAYLOAD_LEN; i++) { - if (data[i] == NA_PARENT) + for (i = 0; i < ARRAY_SIZE(response->parents); i++) { + if (response->parents[i] == NA_PARENT) return END_OF_PARENTS; parent = &parents[i]; - parent->id = data[i] & CLK_PARENTS_ID_MASK; - if (data[i] == DUMMY_PARENT) { + parent->id = FIELD_GET(CLK_PARENTS_ID, response->parents[i]); + if (response->parents[i] == DUMMY_PARENT) { strcpy(parent->name, "dummy_name"); parent->flag = 0; } else { - parent->flag = data[i] >> CLK_PARENTS_ID_LEN; + parent->flag = FIELD_GET(CLK_PARENTS_FLAGS, + response->parents[i]); if (zynqmp_get_clock_name(parent->id, parent->name)) continue; } @@ -461,21 +482,21 @@ static int zynqmp_clock_get_parents(u32 clk_id, struct clock_parent *parents, u32 *num_parents) { int j = 0, ret; - u32 pm_resp[PM_API_PAYLOAD_LEN] = {0}; + struct parents_resp response = { }; *num_parents = 0; do { /* Get parents from firmware */ ret = zynqmp_pm_clock_get_parents(clock[clk_id].clk_id, j, - pm_resp); + &response); if (ret) return ret; - ret = __zynqmp_clock_get_parents(&parents[j], pm_resp, + ret = __zynqmp_clock_get_parents(&parents[j], &response, num_parents); if (ret == END_OF_PARENTS) return 0; - j += PM_API_PAYLOAD_LEN; + j += ARRAY_SIZE(response.parents); } while (*num_parents <= MAX_PARENT); return 0; @@ -631,26 +652,33 @@ static int zynqmp_register_clocks(struct device_node *np) static void zynqmp_get_clock_info(void) { int i, ret; - u32 attr, type = 0, nodetype, subclass, class; + u32 type = 0; + u32 nodetype, subclass, class; + struct attr_resp attr; + struct name_resp name; for (i = 0; i < clock_max_idx; i++) { ret = zynqmp_pm_clock_get_attributes(i, &attr); if (ret) continue; - clock[i].valid = attr & CLK_VALID_MASK; - clock[i].type = ((attr >> CLK_TYPE_SHIFT) & 0x1) ? - CLK_TYPE_EXTERNAL : CLK_TYPE_OUTPUT; - nodetype = (attr >> NODE_TYPE_SHIFT) & 0x3F; - subclass = (attr >> NODE_SUBCLASS_SHIFT) & 0x3F; - class = (attr >> NODE_CLASS_SHIFT) & 0x3F; + clock[i].valid = FIELD_GET(CLK_ATTR_VALID, attr.attr[0]); + clock[i].type = FIELD_GET(CLK_ATTR_TYPE, attr.attr[0]) ? + CLK_TYPE_EXTERNAL : CLK_TYPE_OUTPUT; - clock[i].clk_id = (class << NODE_CLASS_SHIFT) | - (subclass << NODE_SUBCLASS_SHIFT) | - (nodetype << NODE_TYPE_SHIFT) | - (i << NODE_INDEX_SHIFT); + nodetype = FIELD_GET(CLK_ATTR_NODE_TYPE, attr.attr[0]); + subclass = FIELD_GET(CLK_ATTR_NODE_SUBCLASS, attr.attr[0]); + class = FIELD_GET(CLK_ATTR_NODE_CLASS, attr.attr[0]); - zynqmp_pm_clock_get_name(clock[i].clk_id, clock[i].clk_name); + clock[i].clk_id = FIELD_PREP(CLK_ATTR_NODE_CLASS, class) | + FIELD_PREP(CLK_ATTR_NODE_SUBCLASS, subclass) | + FIELD_PREP(CLK_ATTR_NODE_TYPE, nodetype) | + FIELD_PREP(CLK_ATTR_NODE_INDEX, i); + + zynqmp_pm_clock_get_name(clock[i].clk_id, &name); + if (!strcmp(name.name, RESERVED_CLK_NAME)) + continue; + strncpy(clock[i].clk_name, name.name, MAX_NAME_LEN); } /* Get topology of all clock */ -- cgit v1.2.3