
Now that the PLLs get properly enabled, the bypass clock is no longer necessary.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
Changes in v2: - New
drivers/clk/kendryte/Makefile | 2 +- drivers/clk/kendryte/bypass.c | 273 ---------------------------------- drivers/clk/kendryte/clk.c | 43 ++---- include/kendryte/bypass.h | 31 ---- 4 files changed, 15 insertions(+), 334 deletions(-) delete mode 100644 drivers/clk/kendryte/bypass.c delete mode 100644 include/kendryte/bypass.h
diff --git a/drivers/clk/kendryte/Makefile b/drivers/clk/kendryte/Makefile index 6fb68253ae..d26bce954f 100644 --- a/drivers/clk/kendryte/Makefile +++ b/drivers/clk/kendryte/Makefile @@ -1 +1 @@ -obj-y += bypass.o clk.o pll.o +obj-y += clk.o pll.o diff --git a/drivers/clk/kendryte/bypass.c b/drivers/clk/kendryte/bypass.c deleted file mode 100644 index 5f1986f2cb..0000000000 --- a/drivers/clk/kendryte/bypass.c +++ /dev/null @@ -1,273 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2020 Sean Anderson seanga2@gmail.com - */ - -#define LOG_CATEGORY UCLASS_CLK - -#include <common.h> -#include <clk.h> -#include <clk-uclass.h> -#include <dm.h> -#include <log.h> -#include <kendryte/bypass.h> -#include <linux/clk-provider.h> -#include <linux/err.h> - -#define CLK_K210_BYPASS "k210_clk_bypass" - -/* - * This is a small driver to do a software bypass of a clock if hardware bypass - * is not working. I have tried to write this in a generic fashion, so that it - * could be potentially broken out of the kendryte code at some future date. - * - * Say you have the following clock configuration - * - * +---+ +---+ - * |osc| |pll| - * +---+ +---+ - * ^ - * /| - * / | - * / | - * / | - * / | - * +---+ +---+ - * |clk| |clk| - * +---+ +---+ - * - * But the pll does not have a bypass, so when you configure the pll, the - * configuration needs to change to look like - * - * +---+ +---+ - * |osc| |pll| - * +---+ +---+ - * ^ - * |\ - * | \ - * | \ - * | \ - * | \ - * +---+ +---+ - * |clk| |clk| - * +---+ +---+ - * - * To set this up, create a bypass clock with bypassee=pll and alt=osc. When - * creating the child clocks, set their parent to the bypass clock. After - * creating all the children, call k210_bypass_setchildren(). - */ - -static int k210_bypass_dobypass(struct k210_bypass *bypass) -{ - int ret, i; - - /* - * If we already have saved parents, then the children are already - * bypassed - */ - if (bypass->child_count && bypass->saved_parents[0]) - return 0; - - for (i = 0; i < bypass->child_count; i++) { - struct clk *child = bypass->children[i]; - struct clk *parent = clk_get_parent(child); - - if (IS_ERR(parent)) { - for (; i; i--) - bypass->saved_parents[i] = NULL; - return PTR_ERR(parent); - } - bypass->saved_parents[i] = parent; - } - - for (i = 0; i < bypass->child_count; i++) { - struct clk *child = bypass->children[i]; - - ret = clk_set_parent(child, bypass->alt); - if (ret) { - for (; i; i--) - clk_set_parent(bypass->children[i], - bypass->saved_parents[i]); - for (i = 0; i < bypass->child_count; i++) - bypass->saved_parents[i] = NULL; - return ret; - } - } - - return 0; -} - -static int k210_bypass_unbypass(struct k210_bypass *bypass) -{ - int err, ret, i; - - if (!bypass->child_count && !bypass->saved_parents[0]) { - log_warning("Cannot unbypass children; dobypass not called first\n"); - return 0; - } - - ret = 0; - for (i = 0; i < bypass->child_count; i++) { - err = clk_set_parent(bypass->children[i], - bypass->saved_parents[i]); - if (err) - ret = err; - bypass->saved_parents[i] = NULL; - } - return ret; -} - -static ulong k210_bypass_get_rate(struct clk *clk) -{ - struct k210_bypass *bypass = to_k210_bypass(clk); - const struct clk_ops *ops = bypass->bypassee_ops; - - if (ops->get_rate) - return ops->get_rate(bypass->bypassee); - else - return clk_get_parent_rate(bypass->bypassee); -} - -static ulong k210_bypass_set_rate(struct clk *clk, unsigned long rate) -{ - int ret; - struct k210_bypass *bypass = to_k210_bypass(clk); - const struct clk_ops *ops = bypass->bypassee_ops; - - /* Don't bother bypassing if we aren't going to set the rate */ - if (!ops->set_rate) - return k210_bypass_get_rate(clk); - - ret = k210_bypass_dobypass(bypass); - if (ret) - return ret; - - ret = ops->set_rate(bypass->bypassee, rate); - if (ret < 0) - return ret; - - return k210_bypass_unbypass(bypass); -} - -static int k210_bypass_set_parent(struct clk *clk, struct clk *parent) -{ - struct k210_bypass *bypass = to_k210_bypass(clk); - const struct clk_ops *ops = bypass->bypassee_ops; - - if (ops->set_parent) - return ops->set_parent(bypass->bypassee, parent); - else - return -ENOTSUPP; -} - -/* - * For these next two functions, do the bypassing even if there is no - * en-/-disable function, since the bypassing itself can be observed in between - * calls. - */ -static int k210_bypass_enable(struct clk *clk) -{ - int ret; - struct k210_bypass *bypass = to_k210_bypass(clk); - const struct clk_ops *ops = bypass->bypassee_ops; - - ret = k210_bypass_dobypass(bypass); - if (ret) - return ret; - - if (ops->enable) - ret = ops->enable(bypass->bypassee); - else - ret = 0; - if (ret) - return ret; - - return k210_bypass_unbypass(bypass); -} - -static int k210_bypass_disable(struct clk *clk) -{ - int ret; - struct k210_bypass *bypass = to_k210_bypass(clk); - const struct clk_ops *ops = bypass->bypassee_ops; - - ret = k210_bypass_dobypass(bypass); - if (ret) - return ret; - - if (ops->disable) - return ops->disable(bypass->bypassee); - else - return 0; -} - -static const struct clk_ops k210_bypass_ops = { - .get_rate = k210_bypass_get_rate, - .set_rate = k210_bypass_set_rate, - .set_parent = k210_bypass_set_parent, - .enable = k210_bypass_enable, - .disable = k210_bypass_disable, -}; - -int k210_bypass_set_children(struct clk *clk, struct clk **children, - size_t child_count) -{ - struct k210_bypass *bypass = to_k210_bypass(clk); - - kfree(bypass->saved_parents); - if (child_count) { - bypass->saved_parents = - kcalloc(child_count, sizeof(struct clk *), GFP_KERNEL); - if (!bypass->saved_parents) - return -ENOMEM; - } - bypass->child_count = child_count; - bypass->children = children; - - return 0; -} - -struct clk *k210_register_bypass_struct(const char *name, - const char *parent_name, - struct k210_bypass *bypass) -{ - int ret; - struct clk *clk; - - clk = &bypass->clk; - - ret = clk_register(clk, CLK_K210_BYPASS, name, parent_name); - if (ret) - return ERR_PTR(ret); - - bypass->bypassee->dev = clk->dev; - return clk; -} - -struct clk *k210_register_bypass(const char *name, const char *parent_name, - struct clk *bypassee, - const struct clk_ops *bypassee_ops, - struct clk *alt) -{ - struct clk *clk; - struct k210_bypass *bypass; - - bypass = kzalloc(sizeof(*bypass), GFP_KERNEL); - if (!bypass) - return ERR_PTR(-ENOMEM); - - bypass->bypassee = bypassee; - bypass->bypassee_ops = bypassee_ops; - bypass->alt = alt; - - clk = k210_register_bypass_struct(name, parent_name, bypass); - if (IS_ERR(clk)) - kfree(bypass); - return clk; -} - -U_BOOT_DRIVER(k210_bypass) = { - .name = CLK_K210_BYPASS, - .id = UCLASS_CLK, - .ops = &k210_bypass_ops, -}; diff --git a/drivers/clk/kendryte/clk.c b/drivers/clk/kendryte/clk.c index bb196961af..e657efc572 100644 --- a/drivers/clk/kendryte/clk.c +++ b/drivers/clk/kendryte/clk.c @@ -11,7 +11,6 @@ #include <log.h> #include <mapmem.h>
-#include <kendryte/bypass.h> #include <kendryte/pll.h>
/* All methods are delegated to CCF clocks */ @@ -347,10 +346,6 @@ static const struct k210_comp_params k210_comps[] = { #undef COMP_NOMUX_ID #undef COMP_LIST
-static struct clk *k210_bypass_children = { - NULL, -}; - /* Helper functions to create sub-clocks */ static struct clk_mux *k210_create_mux(const struct k210_mux_params *params, void *base) @@ -482,7 +477,7 @@ static int k210_clk_probe(struct udevice *dev) { int ret; const char *in0; - struct clk *in0_clk, *bypass; + struct clk *in0_clk; struct clk_mux *mux; struct clk_divider *div; struct k210_pll *pll; @@ -516,17 +511,13 @@ static int k210_clk_probe(struct udevice *dev) aclk_sels[0] = in0; pll2_sels[0] = in0;
- /* - * All PLLs have a broken bypass, but pll0 has the CPU downstream, so we - * need to manually reparent it whenever we configure pll0 - */ - pll = k210_create_pll(&k210_plls[0], base); - if (pll) { - bypass = k210_register_bypass("pll0", in0, &pll->clk, - &k210_pll_ops, in0_clk); - clk_dm(K210_CLK_PLL0, bypass); - } else { - return -ENOMEM; + { + const struct k210_pll_params *params = &k210_plls[0]; + + clk_dm(K210_CLK_PLL0, + k210_register_pll("pll0", in0, base + params->off, + base + params->lock_off, params->shift, + params->width)); }
{ @@ -565,18 +556,12 @@ static int k210_clk_probe(struct udevice *dev) free(mux); free(div); } else { - struct clk *aclk = - clk_register_composite(NULL, "aclk", aclk_sels, - ARRAY_SIZE(aclk_sels), - &mux->clk, &clk_mux_ops, - &div->clk, &clk_divider_ops, - NULL, NULL, 0); - clk_dm(K210_CLK_ACLK, aclk); - if (!IS_ERR(aclk)) { - k210_bypass_children = aclk; - k210_bypass_set_children(bypass, - &k210_bypass_children, 1); - } + clk_dm(K210_CLK_ACLK, + clk_register_composite(NULL, "aclk", aclk_sels, + ARRAY_SIZE(aclk_sels), + &mux->clk, &clk_mux_ops, + &div->clk, &clk_divider_ops, + NULL, NULL, 0)); }
#define REGISTER_COMP(id, name) \ diff --git a/include/kendryte/bypass.h b/include/kendryte/bypass.h deleted file mode 100644 index ab85bbcbfc..0000000000 --- a/include/kendryte/bypass.h +++ /dev/null @@ -1,31 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 2020 Sean Anderson seanga2@gmail.com - */ -#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 */