diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2018-04-04 16:11:49 -0700 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2018-04-04 16:11:49 -0700 |
commit | 664b0bae0b87f69bc9deb098f5e0158b9cf18e04 (patch) | |
tree | d5841492b396ff483723b9339c7c11dc33b67688 /drivers/clk/bcm | |
parent | Input: ALPS - fix TrackStick detection on Thinkpad L570 and Latitude 7370 (diff) | |
parent | Input: i8042 - enable MUX on Sony VAIO VGN-CS series to fix touchpad (diff) | |
download | linux-dev-664b0bae0b87f69bc9deb098f5e0158b9cf18e04.tar.xz linux-dev-664b0bae0b87f69bc9deb098f5e0158b9cf18e04.zip |
Merge branch 'next' into for-linus
Prepare input updates for 4.17 merge window.
Diffstat (limited to 'drivers/clk/bcm')
-rw-r--r-- | drivers/clk/bcm/Kconfig | 9 | ||||
-rw-r--r-- | drivers/clk/bcm/Makefile | 1 | ||||
-rw-r--r-- | drivers/clk/bcm/clk-bcm2835-aux.c | 1 | ||||
-rw-r--r-- | drivers/clk/bcm/clk-bcm2835.c | 30 | ||||
-rw-r--r-- | drivers/clk/bcm/clk-cygnus.c | 25 | ||||
-rw-r--r-- | drivers/clk/bcm/clk-hr2.c | 27 | ||||
-rw-r--r-- | drivers/clk/bcm/clk-iproc-pll.c | 260 | ||||
-rw-r--r-- | drivers/clk/bcm/clk-iproc.h | 5 | ||||
-rw-r--r-- | drivers/clk/bcm/clk-kona-setup.c | 7 |
9 files changed, 230 insertions, 135 deletions
diff --git a/drivers/clk/bcm/Kconfig b/drivers/clk/bcm/Kconfig index 1d9187df167b..4c4bd85f707c 100644 --- a/drivers/clk/bcm/Kconfig +++ b/drivers/clk/bcm/Kconfig @@ -30,6 +30,15 @@ config CLK_BCM_CYGNUS help Enable common clock framework support for the Broadcom Cygnus SoC +config CLK_BCM_HR2 + bool "Broadcom Hurricane 2 clock support" + depends on ARCH_BCM_HR2 || COMPILE_TEST + select COMMON_CLK_IPROC + default ARCH_BCM_HR2 + help + Enable common clock framework support for the Broadcom Hurricane 2 + SoC + config CLK_BCM_NSP bool "Broadcom Northstar/Northstar Plus clock support" depends on ARCH_BCM_5301X || ARCH_BCM_NSP || COMPILE_TEST diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile index e3f0cb0d90f3..002661d39128 100644 --- a/drivers/clk/bcm/Makefile +++ b/drivers/clk/bcm/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835-aux.o obj-$(CONFIG_ARCH_BCM_53573) += clk-bcm53573-ilp.o obj-$(CONFIG_CLK_BCM_CYGNUS) += clk-cygnus.o +obj-$(CONFIG_CLK_BCM_HR2) += clk-hr2.o obj-$(CONFIG_CLK_BCM_NSP) += clk-nsp.o obj-$(CONFIG_CLK_BCM_NS2) += clk-ns2.o obj-$(CONFIG_CLK_BCM_SR) += clk-sr.o diff --git a/drivers/clk/bcm/clk-bcm2835-aux.c b/drivers/clk/bcm/clk-bcm2835-aux.c index bd750cf2238d..77e276d61702 100644 --- a/drivers/clk/bcm/clk-bcm2835-aux.c +++ b/drivers/clk/bcm/clk-bcm2835-aux.c @@ -14,7 +14,6 @@ #include <linux/clk.h> #include <linux/clk-provider.h> -#include <linux/clk/bcm2835.h> #include <linux/module.h> #include <linux/platform_device.h> #include <dt-bindings/clock/bcm2835-aux.h> diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index 58ce6af8452d..44301a3d9963 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -37,7 +37,6 @@ #include <linux/clk-provider.h> #include <linux/clkdev.h> #include <linux/clk.h> -#include <linux/clk/bcm2835.h> #include <linux/debugfs.h> #include <linux/delay.h> #include <linux/module.h> @@ -416,35 +415,6 @@ static int bcm2835_debugfs_regset(struct bcm2835_cprman *cprman, u32 base, return regdump ? 0 : -ENOMEM; } -/* - * These are fixed clocks. They're probably not all root clocks and it may - * be possible to turn them on and off but until this is mapped out better - * it's the only way they can be used. - */ -void __init bcm2835_init_clocks(void) -{ - struct clk_hw *hw; - int ret; - - hw = clk_hw_register_fixed_rate(NULL, "apb_pclk", NULL, 0, 126000000); - if (IS_ERR(hw)) - pr_err("apb_pclk not registered\n"); - - hw = clk_hw_register_fixed_rate(NULL, "uart0_pclk", NULL, 0, 3000000); - if (IS_ERR(hw)) - pr_err("uart0_pclk not registered\n"); - ret = clk_hw_register_clkdev(hw, NULL, "20201000.uart"); - if (ret) - pr_err("uart0_pclk alias not registered\n"); - - hw = clk_hw_register_fixed_rate(NULL, "uart1_pclk", NULL, 0, 125000000); - if (IS_ERR(hw)) - pr_err("uart1_pclk not registered\n"); - ret = clk_hw_register_clkdev(hw, NULL, "20215000.uart"); - if (ret) - pr_err("uart1_pclk alias not registered\n"); -} - struct bcm2835_pll_data { const char *name; u32 cm_ctrl_reg; diff --git a/drivers/clk/bcm/clk-cygnus.c b/drivers/clk/bcm/clk-cygnus.c index 464fdc4bc66b..b8d073e4855f 100644 --- a/drivers/clk/bcm/clk-cygnus.c +++ b/drivers/clk/bcm/clk-cygnus.c @@ -269,23 +269,10 @@ static void __init cygnus_asiu_init(struct device_node *node) } CLK_OF_DECLARE(cygnus_asiu_clk, "brcm,cygnus-asiu-clk", cygnus_asiu_init); -/* - * AUDIO PLL VCO frequency parameter table - * - * PLL output frequency = ((ndiv_int + ndiv_frac / 2^20) * - * (parent clock rate / pdiv) - * - * On Cygnus, parent is the 25MHz oscillator - */ -static const struct iproc_pll_vco_param audiopll_vco_params[] = { - /* rate (Hz) ndiv_int ndiv_frac pdiv */ - { 1354750204UL, 54, 199238, 1 }, - { 1769470191UL, 70, 816639, 1 }, -}; - static const struct iproc_pll_ctrl audiopll = { .flags = IPROC_CLK_PLL_NEEDS_SW_CFG | IPROC_CLK_PLL_HAS_NDIV_FRAC | - IPROC_CLK_PLL_USER_MODE_ON | IPROC_CLK_PLL_RESET_ACTIVE_LOW, + IPROC_CLK_PLL_USER_MODE_ON | IPROC_CLK_PLL_RESET_ACTIVE_LOW | + IPROC_CLK_PLL_CALC_PARAM, .reset = RESET_VAL(0x5c, 0, 1), .dig_filter = DF_VAL(0x48, 0, 3, 6, 4, 3, 3), .sw_ctrl = SW_CTRL_VAL(0x4, 0), @@ -300,8 +287,7 @@ static const struct iproc_pll_ctrl audiopll = { static const struct iproc_clk_ctrl audiopll_clk[] = { [BCM_CYGNUS_AUDIOPLL_CH0] = { .channel = BCM_CYGNUS_AUDIOPLL_CH0, - .flags = IPROC_CLK_AON | - IPROC_CLK_MCLK_DIV_BY_2, + .flags = IPROC_CLK_AON | IPROC_CLK_MCLK_DIV_BY_2, .enable = ENABLE_VAL(0x14, 8, 10, 9), .mdiv = REG_VAL(0x14, 0, 8), }, @@ -321,9 +307,8 @@ static const struct iproc_clk_ctrl audiopll_clk[] = { static void __init cygnus_audiopll_clk_init(struct device_node *node) { - iproc_pll_clk_setup(node, &audiopll, audiopll_vco_params, - ARRAY_SIZE(audiopll_vco_params), audiopll_clk, - ARRAY_SIZE(audiopll_clk)); + iproc_pll_clk_setup(node, &audiopll, NULL, 0, + audiopll_clk, ARRAY_SIZE(audiopll_clk)); } CLK_OF_DECLARE(cygnus_audiopll, "brcm,cygnus-audiopll", cygnus_audiopll_clk_init); diff --git a/drivers/clk/bcm/clk-hr2.c b/drivers/clk/bcm/clk-hr2.c new file mode 100644 index 000000000000..f7c5b7379475 --- /dev/null +++ b/drivers/clk/bcm/clk-hr2.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2017 Broadcom + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/err.h> +#include <linux/clk-provider.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/of_address.h> + +#include "clk-iproc.h" + +static void __init hr2_armpll_init(struct device_node *node) +{ + iproc_armpll_setup(node); +} +CLK_OF_DECLARE(hr2_armpll, "brcm,hr2-armpll", hr2_armpll_init); diff --git a/drivers/clk/bcm/clk-iproc-pll.c b/drivers/clk/bcm/clk-iproc-pll.c index 375d8dd80d45..43a58ae5a89d 100644 --- a/drivers/clk/bcm/clk-iproc-pll.c +++ b/drivers/clk/bcm/clk-iproc-pll.c @@ -69,16 +69,6 @@ enum vco_freq_range { VCO_MAX = 4000000000U, }; -struct iproc_pll; - -struct iproc_clk { - struct clk_hw hw; - const char *name; - struct iproc_pll *pll; - unsigned long rate; - const struct iproc_clk_ctrl *ctrl; -}; - struct iproc_pll { void __iomem *status_base; void __iomem *control_base; @@ -88,13 +78,49 @@ struct iproc_pll { const struct iproc_pll_ctrl *ctrl; const struct iproc_pll_vco_param *vco_param; unsigned int num_vco_entries; +}; - struct clk_hw_onecell_data *clk_data; - struct iproc_clk *clks; +struct iproc_clk { + struct clk_hw hw; + struct iproc_pll *pll; + const struct iproc_clk_ctrl *ctrl; }; #define to_iproc_clk(hw) container_of(hw, struct iproc_clk, hw) +static int pll_calc_param(unsigned long target_rate, + unsigned long parent_rate, + struct iproc_pll_vco_param *vco_out) +{ + u64 ndiv_int, ndiv_frac, residual; + + ndiv_int = target_rate / parent_rate; + + if (!ndiv_int || (ndiv_int > 255)) + return -EINVAL; + + residual = target_rate - (ndiv_int * parent_rate); + residual <<= 20; + + /* + * Add half of the divisor so the result will be rounded to closest + * instead of rounded down. + */ + residual += (parent_rate / 2); + ndiv_frac = div64_u64((u64)residual, (u64)parent_rate); + + vco_out->ndiv_int = ndiv_int; + vco_out->ndiv_frac = ndiv_frac; + vco_out->pdiv = 1; + + vco_out->rate = vco_out->ndiv_int * parent_rate; + residual = (u64)vco_out->ndiv_frac * (u64)parent_rate; + residual >>= 20; + vco_out->rate += residual; + + return 0; +} + /* * Based on the target frequency, find a match from the VCO frequency parameter * table and return its index @@ -252,17 +278,51 @@ static void __pll_bring_out_reset(struct iproc_pll *pll, unsigned int kp, iproc_pll_write(pll, pll->control_base, reset->offset, val); } -static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index, +/* + * Determines if the change to be applied to the PLL is minor (just an update + * or the fractional divider). If so, then we can avoid going through a + * disruptive reset and lock sequence. + */ +static bool pll_fractional_change_only(struct iproc_pll *pll, + struct iproc_pll_vco_param *vco) +{ + const struct iproc_pll_ctrl *ctrl = pll->ctrl; + u32 val; + u32 ndiv_int; + unsigned int pdiv; + + /* PLL needs to be locked */ + val = readl(pll->status_base + ctrl->status.offset); + if ((val & (1 << ctrl->status.shift)) == 0) + return false; + + val = readl(pll->control_base + ctrl->ndiv_int.offset); + ndiv_int = (val >> ctrl->ndiv_int.shift) & + bit_mask(ctrl->ndiv_int.width); + + if (ndiv_int != vco->ndiv_int) + return false; + + val = readl(pll->control_base + ctrl->pdiv.offset); + pdiv = (val >> ctrl->pdiv.shift) & bit_mask(ctrl->pdiv.width); + + if (pdiv != vco->pdiv) + return false; + + return true; +} + +static int pll_set_rate(struct iproc_clk *clk, struct iproc_pll_vco_param *vco, unsigned long parent_rate) { struct iproc_pll *pll = clk->pll; - const struct iproc_pll_vco_param *vco = &pll->vco_param[rate_index]; const struct iproc_pll_ctrl *ctrl = pll->ctrl; int ka = 0, ki, kp, ret; unsigned long rate = vco->rate; u32 val; enum kp_band kp_index; unsigned long ref_freq; + const char *clk_name = clk_hw_get_name(&clk->hw); /* * reference frequency = parent frequency / PDIV @@ -285,22 +345,35 @@ static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index, kp_index = KP_BAND_HIGH_HIGH; } else { pr_err("%s: pll: %s has invalid rate: %lu\n", __func__, - clk->name, rate); + clk_name, rate); return -EINVAL; } kp = get_kp(ref_freq, kp_index); if (kp < 0) { - pr_err("%s: pll: %s has invalid kp\n", __func__, clk->name); + pr_err("%s: pll: %s has invalid kp\n", __func__, clk_name); return kp; } ret = __pll_enable(pll); if (ret) { - pr_err("%s: pll: %s fails to enable\n", __func__, clk->name); + pr_err("%s: pll: %s fails to enable\n", __func__, clk_name); return ret; } + if (pll_fractional_change_only(clk->pll, vco)) { + /* program fractional part of NDIV */ + if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) { + val = readl(pll->control_base + ctrl->ndiv_frac.offset); + val &= ~(bit_mask(ctrl->ndiv_frac.width) << + ctrl->ndiv_frac.shift); + val |= vco->ndiv_frac << ctrl->ndiv_frac.shift; + iproc_pll_write(pll, pll->control_base, + ctrl->ndiv_frac.offset, val); + return 0; + } + } + /* put PLL in reset */ __pll_put_in_reset(pll); @@ -354,7 +427,7 @@ static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index, ret = pll_wait_for_lock(pll); if (ret < 0) { - pr_err("%s: pll: %s failed to lock\n", __func__, clk->name); + pr_err("%s: pll: %s failed to lock\n", __func__, clk_name); return ret; } @@ -390,16 +463,15 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw, u32 val; u64 ndiv, ndiv_int, ndiv_frac; unsigned int pdiv; + unsigned long rate; if (parent_rate == 0) return 0; /* PLL needs to be locked */ val = readl(pll->status_base + ctrl->status.offset); - if ((val & (1 << ctrl->status.shift)) == 0) { - clk->rate = 0; + if ((val & (1 << ctrl->status.shift)) == 0) return 0; - } /* * PLL output frequency = @@ -421,35 +493,60 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw, val = readl(pll->control_base + ctrl->pdiv.offset); pdiv = (val >> ctrl->pdiv.shift) & bit_mask(ctrl->pdiv.width); - clk->rate = (ndiv * parent_rate) >> 20; + rate = (ndiv * parent_rate) >> 20; if (pdiv == 0) - clk->rate *= 2; + rate *= 2; else - clk->rate /= pdiv; + rate /= pdiv; - return clk->rate; + return rate; } -static long iproc_pll_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int iproc_pll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { - unsigned i; + unsigned int i; struct iproc_clk *clk = to_iproc_clk(hw); struct iproc_pll *pll = clk->pll; + const struct iproc_pll_ctrl *ctrl = pll->ctrl; + unsigned long diff, best_diff; + unsigned int best_idx = 0; + int ret; + + if (req->rate == 0 || req->best_parent_rate == 0) + return -EINVAL; + + if (ctrl->flags & IPROC_CLK_PLL_CALC_PARAM) { + struct iproc_pll_vco_param vco_param; - if (rate == 0 || *parent_rate == 0 || !pll->vco_param) + ret = pll_calc_param(req->rate, req->best_parent_rate, + &vco_param); + if (ret) + return ret; + + req->rate = vco_param.rate; + return 0; + } + + if (!pll->vco_param) return -EINVAL; + best_diff = ULONG_MAX; for (i = 0; i < pll->num_vco_entries; i++) { - if (rate <= pll->vco_param[i].rate) + diff = abs(req->rate - pll->vco_param[i].rate); + if (diff <= best_diff) { + best_diff = diff; + best_idx = i; + } + /* break now if perfect match */ + if (diff == 0) break; } - if (i == pll->num_vco_entries) - i--; + req->rate = pll->vco_param[best_idx].rate; - return pll->vco_param[i].rate; + return 0; } static int iproc_pll_set_rate(struct clk_hw *hw, unsigned long rate, @@ -457,13 +554,23 @@ static int iproc_pll_set_rate(struct clk_hw *hw, unsigned long rate, { struct iproc_clk *clk = to_iproc_clk(hw); struct iproc_pll *pll = clk->pll; + const struct iproc_pll_ctrl *ctrl = pll->ctrl; + struct iproc_pll_vco_param vco_param; int rate_index, ret; - rate_index = pll_get_rate_index(pll, rate); - if (rate_index < 0) - return rate_index; + if (ctrl->flags & IPROC_CLK_PLL_CALC_PARAM) { + ret = pll_calc_param(rate, parent_rate, &vco_param); + if (ret) + return ret; + } else { + rate_index = pll_get_rate_index(pll, rate); + if (rate_index < 0) + return rate_index; - ret = pll_set_rate(clk, rate_index, parent_rate); + vco_param = pll->vco_param[rate_index]; + } + + ret = pll_set_rate(clk, &vco_param, parent_rate); return ret; } @@ -471,7 +578,7 @@ static const struct clk_ops iproc_pll_ops = { .enable = iproc_pll_enable, .disable = iproc_pll_disable, .recalc_rate = iproc_pll_recalc_rate, - .round_rate = iproc_pll_round_rate, + .determine_rate = iproc_pll_determine_rate, .set_rate = iproc_pll_set_rate, }; @@ -518,6 +625,7 @@ static unsigned long iproc_clk_recalc_rate(struct clk_hw *hw, struct iproc_pll *pll = clk->pll; u32 val; unsigned int mdiv; + unsigned long rate; if (parent_rate == 0) return 0; @@ -528,32 +636,33 @@ static unsigned long iproc_clk_recalc_rate(struct clk_hw *hw, mdiv = 256; if (ctrl->flags & IPROC_CLK_MCLK_DIV_BY_2) - clk->rate = parent_rate / (mdiv * 2); + rate = parent_rate / (mdiv * 2); else - clk->rate = parent_rate / mdiv; + rate = parent_rate / mdiv; - return clk->rate; + return rate; } -static long iproc_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int iproc_clk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { - unsigned int div; + unsigned int bestdiv; - if (rate == 0 || *parent_rate == 0) + if (req->rate == 0) return -EINVAL; + if (req->rate == req->best_parent_rate) + return 0; - if (rate == *parent_rate) - return *parent_rate; + bestdiv = DIV_ROUND_CLOSEST(req->best_parent_rate, req->rate); + if (bestdiv < 2) + req->rate = req->best_parent_rate; - div = DIV_ROUND_UP(*parent_rate, rate); - if (div < 2) - return *parent_rate; + if (bestdiv > 256) + bestdiv = 256; - if (div > 256) - div = 256; + req->rate = req->best_parent_rate / bestdiv; - return *parent_rate / div; + return 0; } static int iproc_clk_set_rate(struct clk_hw *hw, unsigned long rate, @@ -568,10 +677,10 @@ static int iproc_clk_set_rate(struct clk_hw *hw, unsigned long rate, if (rate == 0 || parent_rate == 0) return -EINVAL; + div = DIV_ROUND_CLOSEST(parent_rate, rate); if (ctrl->flags & IPROC_CLK_MCLK_DIV_BY_2) - div = DIV_ROUND_UP(parent_rate, rate * 2); - else - div = DIV_ROUND_UP(parent_rate, rate); + div /= 2; + if (div > 256) return -EINVAL; @@ -583,10 +692,6 @@ static int iproc_clk_set_rate(struct clk_hw *hw, unsigned long rate, val |= div << ctrl->mdiv.shift; } iproc_pll_write(pll, pll->control_base, ctrl->mdiv.offset, val); - if (ctrl->flags & IPROC_CLK_MCLK_DIV_BY_2) - clk->rate = parent_rate / (div * 2); - else - clk->rate = parent_rate / div; return 0; } @@ -595,7 +700,7 @@ static const struct clk_ops iproc_clk_ops = { .enable = iproc_clk_enable, .disable = iproc_clk_disable, .recalc_rate = iproc_clk_recalc_rate, - .round_rate = iproc_clk_round_rate, + .determine_rate = iproc_clk_determine_rate, .set_rate = iproc_clk_set_rate, }; @@ -629,6 +734,8 @@ void iproc_pll_clk_setup(struct device_node *node, struct iproc_clk *iclk; struct clk_init_data init; const char *parent_name; + struct iproc_clk *iclk_array; + struct clk_hw_onecell_data *clk_data; if (WARN_ON(!pll_ctrl) || WARN_ON(!clk_ctrl)) return; @@ -637,14 +744,14 @@ void iproc_pll_clk_setup(struct device_node *node, if (WARN_ON(!pll)) return; - pll->clk_data = kzalloc(sizeof(*pll->clk_data->hws) * num_clks + - sizeof(*pll->clk_data), GFP_KERNEL); - if (WARN_ON(!pll->clk_data)) + clk_data = kzalloc(sizeof(*clk_data->hws) * num_clks + + sizeof(*clk_data), GFP_KERNEL); + if (WARN_ON(!clk_data)) goto err_clk_data; - pll->clk_data->num = num_clks; + clk_data->num = num_clks; - pll->clks = kcalloc(num_clks, sizeof(*pll->clks), GFP_KERNEL); - if (WARN_ON(!pll->clks)) + iclk_array = kcalloc(num_clks, sizeof(struct iproc_clk), GFP_KERNEL); + if (WARN_ON(!iclk_array)) goto err_clks; pll->control_base = of_iomap(node, 0); @@ -674,9 +781,8 @@ void iproc_pll_clk_setup(struct device_node *node, /* initialize and register the PLL itself */ pll->ctrl = pll_ctrl; - iclk = &pll->clks[0]; + iclk = &iclk_array[0]; iclk->pll = pll; - iclk->name = node->name; init.name = node->name; init.ops = &iproc_pll_ops; @@ -697,7 +803,7 @@ void iproc_pll_clk_setup(struct device_node *node, if (WARN_ON(ret)) goto err_pll_register; - pll->clk_data->hws[0] = &iclk->hw; + clk_data->hws[0] = &iclk->hw; /* now initialize and register all leaf clocks */ for (i = 1; i < num_clks; i++) { @@ -711,8 +817,7 @@ void iproc_pll_clk_setup(struct device_node *node, if (WARN_ON(ret)) goto err_clk_register; - iclk = &pll->clks[i]; - iclk->name = clk_name; + iclk = &iclk_array[i]; iclk->pll = pll; iclk->ctrl = &clk_ctrl[i]; @@ -727,11 +832,10 @@ void iproc_pll_clk_setup(struct device_node *node, if (WARN_ON(ret)) goto err_clk_register; - pll->clk_data->hws[i] = &iclk->hw; + clk_data->hws[i] = &iclk->hw; } - ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, - pll->clk_data); + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (WARN_ON(ret)) goto err_clk_register; @@ -739,7 +843,7 @@ void iproc_pll_clk_setup(struct device_node *node, err_clk_register: while (--i >= 0) - clk_hw_unregister(pll->clk_data->hws[i]); + clk_hw_unregister(clk_data->hws[i]); err_pll_register: if (pll->status_base != pll->control_base) @@ -756,10 +860,10 @@ err_asiu_iomap: iounmap(pll->control_base); err_pll_iomap: - kfree(pll->clks); + kfree(iclk_array); err_clks: - kfree(pll->clk_data); + kfree(clk_data); err_clk_data: kfree(pll); diff --git a/drivers/clk/bcm/clk-iproc.h b/drivers/clk/bcm/clk-iproc.h index 2148b4ea9f28..a48ddd3e0b28 100644 --- a/drivers/clk/bcm/clk-iproc.h +++ b/drivers/clk/bcm/clk-iproc.h @@ -81,6 +81,11 @@ #define IPROC_CLK_PLL_RESET_ACTIVE_LOW BIT(9) /* + * Calculate the PLL parameters are runtime, instead of using table + */ +#define IPROC_CLK_PLL_CALC_PARAM BIT(10) + +/* * Parameters for VCO frequency configuration * * VCO frequency = diff --git a/drivers/clk/bcm/clk-kona-setup.c b/drivers/clk/bcm/clk-kona-setup.c index c37a7f0e83aa..281f4322355c 100644 --- a/drivers/clk/bcm/clk-kona-setup.c +++ b/drivers/clk/bcm/clk-kona-setup.c @@ -579,18 +579,13 @@ static u32 *parent_process(const char *clocks[], */ parent_names = kmalloc_array(parent_count, sizeof(*parent_names), GFP_KERNEL); - if (!parent_names) { - pr_err("%s: error allocating %u parent names\n", __func__, - parent_count); + if (!parent_names) return ERR_PTR(-ENOMEM); - } /* There is at least one parent, so allocate a selector array */ parent_sel = kmalloc_array(parent_count, sizeof(*parent_sel), GFP_KERNEL); if (!parent_sel) { - pr_err("%s: error allocating %u parent selectors\n", __func__, - parent_count); kfree(parent_names); return ERR_PTR(-ENOMEM); |