summaryrefslogtreecommitdiff
path: root/drivers/clk
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/clk-gemini.c14
-rw-r--r--drivers/clk/keystone/sci-clk.c66
-rw-r--r--drivers/clk/meson/clk-mpll.c7
-rw-r--r--drivers/clk/meson/clkc.h1
-rw-r--r--drivers/clk/meson/gxbb.c5
-rw-r--r--drivers/clk/meson/meson8b.c5
-rw-r--r--drivers/clk/samsung/clk-exynos5420.c16
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun5i.c2
-rw-r--r--drivers/clk/x86/clk-pmc-atom.c7
9 files changed, 90 insertions, 33 deletions
diff --git a/drivers/clk/clk-gemini.c b/drivers/clk/clk-gemini.c
index c391a49aaaff..b4cf2f699a21 100644
--- a/drivers/clk/clk-gemini.c
+++ b/drivers/clk/clk-gemini.c
@@ -237,6 +237,18 @@ static int gemini_reset(struct reset_controller_dev *rcdev,
BIT(GEMINI_RESET_CPU1) | BIT(id));
}
+static int gemini_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return 0;
+}
+
+static int gemini_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return 0;
+}
+
static int gemini_reset_status(struct reset_controller_dev *rcdev,
unsigned long id)
{
@@ -253,6 +265,8 @@ static int gemini_reset_status(struct reset_controller_dev *rcdev,
static const struct reset_control_ops gemini_reset_ops = {
.reset = gemini_reset,
+ .assert = gemini_reset_assert,
+ .deassert = gemini_reset_deassert,
.status = gemini_reset_status,
};
diff --git a/drivers/clk/keystone/sci-clk.c b/drivers/clk/keystone/sci-clk.c
index 43b0f2f08df2..9cdf9d5050ac 100644
--- a/drivers/clk/keystone/sci-clk.c
+++ b/drivers/clk/keystone/sci-clk.c
@@ -22,6 +22,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/soc/ti/ti_sci_protocol.h>
+#include <linux/bsearch.h>
#define SCI_CLK_SSC_ENABLE BIT(0)
#define SCI_CLK_ALLOW_FREQ_CHANGE BIT(1)
@@ -44,6 +45,7 @@ struct sci_clk_data {
* @dev: Device pointer for the clock provider
* @clk_data: Clock data
* @clocks: Clocks array for this device
+ * @num_clocks: Total number of clocks for this provider
*/
struct sci_clk_provider {
const struct ti_sci_handle *sci;
@@ -51,6 +53,7 @@ struct sci_clk_provider {
struct device *dev;
const struct sci_clk_data *clk_data;
struct clk_hw **clocks;
+ int num_clocks;
};
/**
@@ -58,7 +61,6 @@ struct sci_clk_provider {
* @hw: Hardware clock cookie for common clock framework
* @dev_id: Device index
* @clk_id: Clock index
- * @node: Clocks list link
* @provider: Master clock provider
* @flags: Flags for the clock
*/
@@ -66,7 +68,6 @@ struct sci_clk {
struct clk_hw hw;
u16 dev_id;
u8 clk_id;
- struct list_head node;
struct sci_clk_provider *provider;
u8 flags;
};
@@ -367,6 +368,19 @@ err:
return &sci_clk->hw;
}
+static int _cmp_sci_clk(const void *a, const void *b)
+{
+ const struct sci_clk *ca = a;
+ const struct sci_clk *cb = *(struct sci_clk **)b;
+
+ if (ca->dev_id == cb->dev_id && ca->clk_id == cb->clk_id)
+ return 0;
+ if (ca->dev_id > cb->dev_id ||
+ (ca->dev_id == cb->dev_id && ca->clk_id > cb->clk_id))
+ return 1;
+ return -1;
+}
+
/**
* sci_clk_get - Xlate function for getting clock handles
* @clkspec: device tree clock specifier
@@ -380,29 +394,22 @@ err:
static struct clk_hw *sci_clk_get(struct of_phandle_args *clkspec, void *data)
{
struct sci_clk_provider *provider = data;
- u16 dev_id;
- u8 clk_id;
- const struct sci_clk_data *clks = provider->clk_data;
- struct clk_hw **clocks = provider->clocks;
+ struct sci_clk **clk;
+ struct sci_clk key;
if (clkspec->args_count != 2)
return ERR_PTR(-EINVAL);
- dev_id = clkspec->args[0];
- clk_id = clkspec->args[1];
+ key.dev_id = clkspec->args[0];
+ key.clk_id = clkspec->args[1];
- while (clks->num_clks) {
- if (clks->dev == dev_id) {
- if (clk_id >= clks->num_clks)
- return ERR_PTR(-EINVAL);
-
- return clocks[clk_id];
- }
+ clk = bsearch(&key, provider->clocks, provider->num_clocks,
+ sizeof(clk), _cmp_sci_clk);
- clks++;
- }
+ if (!clk)
+ return ERR_PTR(-ENODEV);
- return ERR_PTR(-ENODEV);
+ return &(*clk)->hw;
}
static int ti_sci_init_clocks(struct sci_clk_provider *p)
@@ -410,18 +417,29 @@ static int ti_sci_init_clocks(struct sci_clk_provider *p)
const struct sci_clk_data *data = p->clk_data;
struct clk_hw *hw;
int i;
+ int num_clks = 0;
while (data->num_clks) {
- p->clocks = devm_kcalloc(p->dev, data->num_clks,
- sizeof(struct sci_clk),
- GFP_KERNEL);
- if (!p->clocks)
- return -ENOMEM;
+ num_clks += data->num_clks;
+ data++;
+ }
+ p->num_clocks = num_clks;
+
+ p->clocks = devm_kcalloc(p->dev, num_clks, sizeof(struct sci_clk),
+ GFP_KERNEL);
+ if (!p->clocks)
+ return -ENOMEM;
+
+ num_clks = 0;
+
+ data = p->clk_data;
+
+ while (data->num_clks) {
for (i = 0; i < data->num_clks; i++) {
hw = _sci_clk_build(p, data->dev, i);
if (!IS_ERR(hw)) {
- p->clocks[i] = hw;
+ p->clocks[num_clks++] = hw;
continue;
}
diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c
index 39eab69fe51a..44a5a535ca63 100644
--- a/drivers/clk/meson/clk-mpll.c
+++ b/drivers/clk/meson/clk-mpll.c
@@ -161,6 +161,13 @@ static int mpll_set_rate(struct clk_hw *hw,
reg = PARM_SET(p->width, p->shift, reg, 1);
writel(reg, mpll->base + p->reg_off);
+ p = &mpll->ssen;
+ if (p->width != 0) {
+ reg = readl(mpll->base + p->reg_off);
+ reg = PARM_SET(p->width, p->shift, reg, 1);
+ writel(reg, mpll->base + p->reg_off);
+ }
+
p = &mpll->n2;
reg = readl(mpll->base + p->reg_off);
reg = PARM_SET(p->width, p->shift, reg, n2);
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
index d6feafe8bd6c..1629da9b4141 100644
--- a/drivers/clk/meson/clkc.h
+++ b/drivers/clk/meson/clkc.h
@@ -118,6 +118,7 @@ struct meson_clk_mpll {
struct parm sdm_en;
struct parm n2;
struct parm en;
+ struct parm ssen;
spinlock_t *lock;
};
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index a897ea45327c..a7ea5f3da89d 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -528,6 +528,11 @@ static struct meson_clk_mpll gxbb_mpll0 = {
.shift = 14,
.width = 1,
},
+ .ssen = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 25,
+ .width = 1,
+ },
.lock = &clk_lock,
.hw.init = &(struct clk_init_data){
.name = "mpll0",
diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index bb3f1de876b1..6ec512ad2598 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -267,6 +267,11 @@ static struct meson_clk_mpll meson8b_mpll0 = {
.shift = 14,
.width = 1,
},
+ .ssen = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 25,
+ .width = 1,
+ },
.lock = &clk_lock,
.hw.init = &(struct clk_init_data){
.name = "mpll0",
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index 0748a0b333c5..9a6476aa7d81 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -1283,16 +1283,16 @@ static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] __ini
static const struct samsung_pll_rate_table exynos5420_epll_24mhz_tbl[] = {
PLL_36XX_RATE(600000000U, 100, 2, 1, 0),
PLL_36XX_RATE(400000000U, 200, 3, 2, 0),
- PLL_36XX_RATE(393216000U, 197, 3, 2, 25690),
- PLL_36XX_RATE(361267200U, 301, 5, 2, 3671),
+ PLL_36XX_RATE(393216003U, 197, 3, 2, -25690),
+ PLL_36XX_RATE(361267218U, 301, 5, 2, 3671),
PLL_36XX_RATE(200000000U, 200, 3, 3, 0),
- PLL_36XX_RATE(196608000U, 197, 3, 3, -25690),
- PLL_36XX_RATE(180633600U, 301, 5, 3, 3671),
- PLL_36XX_RATE(131072000U, 131, 3, 3, 4719),
+ PLL_36XX_RATE(196608001U, 197, 3, 3, -25690),
+ PLL_36XX_RATE(180633609U, 301, 5, 3, 3671),
+ PLL_36XX_RATE(131072006U, 131, 3, 3, 4719),
PLL_36XX_RATE(100000000U, 200, 3, 4, 0),
- PLL_36XX_RATE(65536000U, 131, 3, 4, 4719),
- PLL_36XX_RATE(49152000U, 197, 3, 5, 25690),
- PLL_36XX_RATE(32768000U, 131, 3, 5, 4719),
+ PLL_36XX_RATE( 65536003U, 131, 3, 4, 4719),
+ PLL_36XX_RATE( 49152000U, 197, 3, 5, -25690),
+ PLL_36XX_RATE( 32768001U, 131, 3, 5, 4719),
};
static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = {
diff --git a/drivers/clk/sunxi-ng/ccu-sun5i.c b/drivers/clk/sunxi-ng/ccu-sun5i.c
index 5372bf8be5e6..31d7ffda9aab 100644
--- a/drivers/clk/sunxi-ng/ccu-sun5i.c
+++ b/drivers/clk/sunxi-ng/ccu-sun5i.c
@@ -184,7 +184,7 @@ static struct ccu_mux cpu_clk = {
.hw.init = CLK_HW_INIT_PARENTS("cpu",
cpu_parents,
&ccu_mux_ops,
- CLK_IS_CRITICAL),
+ CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
}
};
diff --git a/drivers/clk/x86/clk-pmc-atom.c b/drivers/clk/x86/clk-pmc-atom.c
index f99abc1106f0..08ef69945ffb 100644
--- a/drivers/clk/x86/clk-pmc-atom.c
+++ b/drivers/clk/x86/clk-pmc-atom.c
@@ -186,6 +186,13 @@ static struct clk_plt *plt_clk_register(struct platform_device *pdev, int id,
pclk->reg = base + PMC_CLK_CTL_OFFSET + id * PMC_CLK_CTL_SIZE;
spin_lock_init(&pclk->lock);
+ /*
+ * If the clock was already enabled by the firmware mark it as critical
+ * to avoid it being gated by the clock framework if no driver owns it.
+ */
+ if (plt_clk_is_enabled(&pclk->hw))
+ init.flags |= CLK_IS_CRITICAL;
+
ret = devm_clk_hw_register(&pdev->dev, &pclk->hw);
if (ret) {
pclk = ERR_PTR(ret);