From 6e33eba59f2e695b6549a42507218f04575859fa Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Fri, 11 Jun 2021 00:16:07 -0400 Subject: clk: Allow force setting clock defaults before relocation Since 291da96b8e ("clk: Allow clock defaults to be set during re-reloc state for SPL only") it has been impossible to set clock defaults before relocation. This is annoying on boards without SPL, since there is no way to set clock defaults before U-Boot proper. In particular, the aisram rate must be changed before relocation on the K210, since U-Boot will hang if we try and change the rate while we are using aisram. To get around this, extend the stage parameter to allow force setting defaults, even if they would be otherwise postponed for later. A device tree property was decided against because of the concerns in the original commit thread about the overhead of repeatedly parsing the device tree. Signed-off-by: Sean Anderson Reviewed-by: Simon Glass --- include/clk.h | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/clk.h b/include/clk.h index ca6b85fa6fe..f3c88fe68aa 100644 --- a/include/clk.h +++ b/include/clk.h @@ -277,19 +277,41 @@ static inline int clk_release_all(struct clk *clk, int count) } #endif +/** + * enum clk_defaults_stage - What stage clk_set_defaults() is called at + * @CLK_DEFAULTS_PRE: Called before probe. Setting of defaults for clocks owned + * by this clock driver will be defered until after probing. + * @CLK_DEFAULTS_POST: Called after probe. Only defaults for clocks owned by + * this clock driver will be set. + * @CLK_DEFAULTS_POST_FORCE: Called after probe, and always set defaults, even + * before relocation. Usually, defaults are not set + * pre-relocation to avoid setting them twice (when + * the device is probed again post-relocation). This + * may incur a performance cost as device tree + * properties must be parsed for a second time. + * However, when not using SPL, pre-relocation may be + * the only time we can set defaults for some clocks + * (such as those used for the RAM we will relocate + * into). + */ +enum clk_defaults_stage { + CLK_DEFAULTS_PRE = 0, + CLK_DEFAULTS_POST = 1, + CLK_DEFAULTS_POST_FORCE, +}; + #if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) && \ CONFIG_IS_ENABLED(CLK) + /** * clk_set_defaults - Process 'assigned-{clocks/clock-parents/clock-rates}' * properties to configure clocks * * @dev: A device to process (the ofnode associated with this device * will be processed). - * @stage: A integer. 0 indicates that this is called before the device - * is probed. 1 indicates that this is called just after the - * device has been probed + * @stage: The stage of the probing process this function is called during. */ -int clk_set_defaults(struct udevice *dev, int stage); +int clk_set_defaults(struct udevice *dev, enum clk_defaults_stage stage); #else static inline int clk_set_defaults(struct udevice *dev, int stage) { -- cgit v1.2.3 From 609bd60b943b17784b1cd245dc1bfb6384dab640 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Fri, 11 Jun 2021 00:16:08 -0400 Subject: clk: k210: Rewrite to remove CCF This is effectively a complete rewrite to remove all dependency on CCF. The code is now smaller, and so is the binary. It also takes up less memory at runtime (since we don't have to create 40 udevices). In general, I am much happier with this driver as much of the complexity and late binding has been removed. The k210_*_params structs which were previously used to initialize CCF clocks are now used as the complete configuration. Since we can write our own division logic, we can now do away with several "half" clocks which only existed to provide constant factors of two. The clock IDs have been renumbered to remove unused clocks. This may not be the last time they are renumbered, since we have diverged with Linux. There are also still a few clocks left out which may need to be added back in. In general, I have tried to leave out behavioral changes. However, there is a small bugfix regarding ACLK. According to the technical reference manual, its mux comes *after* its divider (which is present only for PLL0). This would have required yet another intermediate clock to fix with CCF, but with the new driver it is just 2 lines of code :) Signed-off-by: Sean Anderson Reviewed-by: Leo Yu-Chi Liang --- include/dt-bindings/clock/k210-sysctl.h | 94 ++++++++++++++++----------------- include/kendryte/pll.h | 26 ++++----- 2 files changed, 59 insertions(+), 61 deletions(-) (limited to 'include') diff --git a/include/dt-bindings/clock/k210-sysctl.h b/include/dt-bindings/clock/k210-sysctl.h index fe852bbd92a..6b0d5b46f87 100644 --- a/include/dt-bindings/clock/k210-sysctl.h +++ b/include/dt-bindings/clock/k210-sysctl.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Copyright (C) 2019-20 Sean Anderson + * Copyright (C) 2019-21 Sean Anderson */ #ifndef CLOCK_K210_SYSCTL_H @@ -9,52 +9,50 @@ /* * Arbitrary identifiers for clocks. */ -#define K210_CLK_NONE 0 -#define K210_CLK_IN0_H 1 -#define K210_CLK_PLL0_H 2 -#define K210_CLK_PLL0 3 -#define K210_CLK_PLL1 4 -#define K210_CLK_PLL2 5 -#define K210_CLK_PLL2_H 6 -#define K210_CLK_CPU 7 -#define K210_CLK_SRAM0 8 -#define K210_CLK_SRAM1 9 -#define K210_CLK_APB0 10 -#define K210_CLK_APB1 11 -#define K210_CLK_APB2 12 -#define K210_CLK_ROM 13 -#define K210_CLK_DMA 14 -#define K210_CLK_AI 15 -#define K210_CLK_DVP 16 -#define K210_CLK_FFT 17 -#define K210_CLK_GPIO 18 -#define K210_CLK_SPI0 19 -#define K210_CLK_SPI1 20 -#define K210_CLK_SPI2 21 -#define K210_CLK_SPI3 22 -#define K210_CLK_I2S0 23 -#define K210_CLK_I2S1 24 -#define K210_CLK_I2S2 25 -#define K210_CLK_I2S0_M 26 -#define K210_CLK_I2S1_M 27 -#define K210_CLK_I2S2_M 28 -#define K210_CLK_I2C0 29 -#define K210_CLK_I2C1 30 -#define K210_CLK_I2C2 31 -#define K210_CLK_UART1 32 -#define K210_CLK_UART2 33 -#define K210_CLK_UART3 34 -#define K210_CLK_AES 35 -#define K210_CLK_FPIOA 36 -#define K210_CLK_TIMER0 37 -#define K210_CLK_TIMER1 38 -#define K210_CLK_TIMER2 39 -#define K210_CLK_WDT0 40 -#define K210_CLK_WDT1 41 -#define K210_CLK_SHA 42 -#define K210_CLK_OTP 43 -#define K210_CLK_RTC 44 -#define K210_CLK_ACLK 45 -#define K210_CLK_CLINT 46 + +#define K210_CLK_PLL0 0 +#define K210_CLK_PLL1 1 +#define K210_CLK_PLL2 2 +#define K210_CLK_CPU 3 +#define K210_CLK_SRAM0 4 +#define K210_CLK_SRAM1 5 +#define K210_CLK_ACLK 6 +#define K210_CLK_CLINT 7 +#define K210_CLK_APB0 8 +#define K210_CLK_APB1 9 +#define K210_CLK_APB2 10 +#define K210_CLK_ROM 11 +#define K210_CLK_DMA 12 +#define K210_CLK_AI 13 +#define K210_CLK_DVP 14 +#define K210_CLK_FFT 15 +#define K210_CLK_GPIO 16 +#define K210_CLK_SPI0 17 +#define K210_CLK_SPI1 18 +#define K210_CLK_SPI2 19 +#define K210_CLK_SPI3 20 +#define K210_CLK_I2S0 21 +#define K210_CLK_I2S1 22 +#define K210_CLK_I2S2 23 +#define K210_CLK_I2S0_M 24 +#define K210_CLK_I2S1_M 25 +#define K210_CLK_I2S2_M 26 +#define K210_CLK_I2C0 27 +#define K210_CLK_I2C1 28 +#define K210_CLK_I2C2 29 +#define K210_CLK_UART1 30 +#define K210_CLK_UART2 31 +#define K210_CLK_UART3 32 +#define K210_CLK_AES 33 +#define K210_CLK_FPIOA 34 +#define K210_CLK_TIMER0 35 +#define K210_CLK_TIMER1 36 +#define K210_CLK_TIMER2 37 +#define K210_CLK_WDT0 38 +#define K210_CLK_WDT1 39 +#define K210_CLK_SHA 40 +#define K210_CLK_OTP 41 +#define K210_CLK_RTC 42 +#define K210_CLK_IN0 43 #endif /* CLOCK_K210_SYSCTL_H */ diff --git a/include/kendryte/pll.h b/include/kendryte/pll.h index 95b8494f40f..16fd5a5b688 100644 --- a/include/kendryte/pll.h +++ b/include/kendryte/pll.h @@ -25,16 +25,6 @@ #define K210_PLL_CLEAR_SLIP 2 #define K210_PLL_TEST_OUT 3 -struct k210_pll { - struct clk clk; - void __iomem *reg; /* Base PLL register */ - void __iomem *lock; /* Common PLL lock register */ - u8 shift; /* Offset of bits in lock register */ - u8 width; /* Width of lock bits to test against */ -}; - -#define to_k210_pll(_clk) container_of(_clk, struct k210_pll, clk) - struct k210_pll_config { u8 r; u8 f; @@ -51,8 +41,18 @@ TEST_STATIC int k210_pll_calc_config(u32 rate, u32 rate_in, #endif -extern const struct clk_ops k210_pll_ops; +/** + * struct k210_clk_priv - K210 clock driver private data + * @base: The base address of the sysctl device + * @in0: The "in0" external oscillator + */ +struct k210_clk_priv { + void __iomem *base; + struct clk in0; +}; -struct clk *k210_register_pll_struct(const char *name, const char *parent_name, - struct k210_pll *pll); +ulong k210_pll_set_rate(struct k210_clk_priv *priv, int id, ulong rate, ulong rate_in); +ulong k210_pll_get_rate(struct k210_clk_priv *priv, int id, ulong rate_in); +int k210_pll_enable(struct k210_clk_priv *priv, int id); +int k210_pll_disable(struct k210_clk_priv *priv, int id); #endif /* K210_PLL_H */ -- cgit v1.2.3 From af9f997436595495748fccf6232987c72b2e58c8 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Fri, 11 Jun 2021 00:16:09 -0400 Subject: clk: k210: Move pll into the rest of the driver Now that there no separate PLL driver, we can no longer make the PLL functions static. By moving the PLL driver in with the rest of the clock code, we can make these functions static again. We still keep the pll header for unit testing, but it is pretty reduced. Signed-off-by: Sean Anderson Reviewed-by: Leo Yu-Chi Liang --- include/kendryte/clk.h | 35 ----------------------------------- include/kendryte/pll.h | 34 ---------------------------------- 2 files changed, 69 deletions(-) delete mode 100644 include/kendryte/clk.h (limited to 'include') diff --git a/include/kendryte/clk.h b/include/kendryte/clk.h deleted file mode 100644 index 9c6245d468b..00000000000 --- a/include/kendryte/clk.h +++ /dev/null @@ -1,35 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 2019-20 Sean Anderson - */ - -#ifndef K210_CLK_H -#define K210_CLK_H - -#define LOG_CATEGORY UCLASS_CLK -#include -#include - -static inline struct clk *k210_clk_gate(const char *name, - const char *parent_name, - void __iomem *reg, u8 bit_idx) -{ - return clk_register_gate(NULL, name, parent_name, 0, reg, bit_idx, 0, - NULL); -} - -static inline struct clk *k210_clk_half(const char *name, - const char *parent_name) -{ - return clk_register_fixed_factor(NULL, name, parent_name, 0, 1, 2); -} - -static inline struct clk *k210_clk_div(const char *name, - const char *parent_name, - void __iomem *reg, u8 shift, u8 width) -{ - return clk_register_divider(NULL, name, parent_name, 0, reg, shift, - width, 0); -} - -#endif /* K210_CLK_H */ diff --git a/include/kendryte/pll.h b/include/kendryte/pll.h index 16fd5a5b688..fd16a89cb20 100644 --- a/include/kendryte/pll.h +++ b/include/kendryte/pll.h @@ -5,25 +5,7 @@ #ifndef K210_PLL_H #define K210_PLL_H -#include #include -#include - -#define K210_PLL_CLKR GENMASK(3, 0) -#define K210_PLL_CLKF GENMASK(9, 4) -#define K210_PLL_CLKOD GENMASK(13, 10) /* Output Divider */ -#define K210_PLL_BWADJ GENMASK(19, 14) /* BandWidth Adjust */ -#define K210_PLL_RESET BIT(20) -#define K210_PLL_PWRD BIT(21) /* PoWeReD */ -#define K210_PLL_INTFB BIT(22) /* Internal FeedBack */ -#define K210_PLL_BYPASS BIT(23) -#define K210_PLL_TEST BIT(24) -#define K210_PLL_EN BIT(25) -#define K210_PLL_TEST_EN BIT(26) - -#define K210_PLL_LOCK 0 -#define K210_PLL_CLEAR_SLIP 2 -#define K210_PLL_TEST_OUT 3 struct k210_pll_config { u8 r; @@ -34,25 +16,9 @@ struct k210_pll_config { #ifdef CONFIG_UNIT_TEST TEST_STATIC int k210_pll_calc_config(u32 rate, u32 rate_in, struct k210_pll_config *best); - #ifndef nop #define nop() #endif #endif - -/** - * struct k210_clk_priv - K210 clock driver private data - * @base: The base address of the sysctl device - * @in0: The "in0" external oscillator - */ -struct k210_clk_priv { - void __iomem *base; - struct clk in0; -}; - -ulong k210_pll_set_rate(struct k210_clk_priv *priv, int id, ulong rate, ulong rate_in); -ulong k210_pll_get_rate(struct k210_clk_priv *priv, int id, ulong rate_in); -int k210_pll_enable(struct k210_clk_priv *priv, int id); -int k210_pll_disable(struct k210_clk_priv *priv, int id); #endif /* K210_PLL_H */ -- cgit v1.2.3 From c29efc157d3bd9cf4f021df9ea522383aa304ce6 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Fri, 11 Jun 2021 00:16:13 -0400 Subject: clk: k210: Remove bypass driver This driver no longer serves a purpose now that we have moved away from CCF. Drop it. Signed-off-by: Sean Anderson Reviewed-by: Leo Yu-Chi Liang --- include/kendryte/bypass.h | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 include/kendryte/bypass.h (limited to 'include') diff --git a/include/kendryte/bypass.h b/include/kendryte/bypass.h deleted file mode 100644 index ab85bbcbfca..00000000000 --- a/include/kendryte/bypass.h +++ /dev/null @@ -1,31 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 2020 Sean Anderson - */ -#ifndef K210_BYPASS_H -#define K210_BYPASS_H - -struct clk; - -struct k210_bypass { - struct clk clk; - struct clk **children; /* Clocks to reparent */ - struct clk **saved_parents; /* Parents saved over en-/dis-able */ - struct clk *bypassee; /* Clock to bypass */ - const struct clk_ops *bypassee_ops; /* Ops of the bypass clock */ - struct clk *alt; /* Clock to set children to when bypassing */ - size_t child_count; -}; - -#define to_k210_bypass(_clk) container_of(_clk, struct k210_bypass, clk) - -int k210_bypass_set_children(struct clk *clk, struct clk **children, - size_t child_count); -struct clk *k210_register_bypass_struct(const char *name, - const char *parent_name, - struct k210_bypass *bypass); -struct clk *k210_register_bypass(const char *name, const char *parent_name, - struct clk *bypassee, - const struct clk_ops *bypassee_ops, - struct clk *alt); -#endif /* K210_BYPASS_H */ -- cgit v1.2.3