aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/bcm
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2018-04-04 16:11:49 -0700
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2018-04-04 16:11:49 -0700
commit664b0bae0b87f69bc9deb098f5e0158b9cf18e04 (patch)
treed5841492b396ff483723b9339c7c11dc33b67688 /drivers/clk/bcm
parentInput: ALPS - fix TrackStick detection on Thinkpad L570 and Latitude 7370 (diff)
parentInput: i8042 - enable MUX on Sony VAIO VGN-CS series to fix touchpad (diff)
downloadlinux-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/Kconfig9
-rw-r--r--drivers/clk/bcm/Makefile1
-rw-r--r--drivers/clk/bcm/clk-bcm2835-aux.c1
-rw-r--r--drivers/clk/bcm/clk-bcm2835.c30
-rw-r--r--drivers/clk/bcm/clk-cygnus.c25
-rw-r--r--drivers/clk/bcm/clk-hr2.c27
-rw-r--r--drivers/clk/bcm/clk-iproc-pll.c260
-rw-r--r--drivers/clk/bcm/clk-iproc.h5
-rw-r--r--drivers/clk/bcm/clk-kona-setup.c7
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);