Commit ecb1f1f7 authored by Marek Szyprowski's avatar Marek Szyprowski Committed by Sylwester Nawrocki

clk: samsung: Convert common drivers to the new clk_hw API

Clock providers should use the new struct clk_hw based API, so convert
Samsung clock providers and their helper functions to the new approach.
Signed-off-by: default avatarMarek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: default avatarKrzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: default avatarSylwester Nawrocki <s.nawrocki@samsung.com>
parent 7288de74
......@@ -411,7 +411,6 @@ int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
struct exynos_cpuclk *cpuclk;
struct clk_init_data init;
struct clk *parent_clk;
struct clk *clk;
int ret = 0;
cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL);
......@@ -464,14 +463,13 @@ int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
goto unregister_clk_nb;
}
clk = clk_register(NULL, &cpuclk->hw);
if (IS_ERR(clk)) {
ret = clk_hw_register(NULL, &cpuclk->hw);
if (ret) {
pr_err("%s: could not register cpuclk %s\n", __func__, name);
ret = PTR_ERR(clk);
goto free_cpuclk_data;
}
samsung_clk_add_lookup(ctx, clk, lookup_id);
samsung_clk_add_lookup(ctx, &cpuclk->hw, lookup_id);
return 0;
free_cpuclk_data:
......
......@@ -1244,7 +1244,6 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
void __iomem *base)
{
struct samsung_clk_pll *pll;
struct clk *clk;
struct clk_init_data init;
int ret, len;
......@@ -1376,20 +1375,21 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
pll->lock_reg = base + pll_clk->lock_offset;
pll->con_reg = base + pll_clk->con_offset;
clk = clk_register(NULL, &pll->hw);
if (IS_ERR(clk)) {
pr_err("%s: failed to register pll clock %s : %ld\n",
__func__, pll_clk->name, PTR_ERR(clk));
ret = clk_hw_register(NULL, &pll->hw);
if (ret) {
pr_err("%s: failed to register pll clock %s : %d\n",
__func__, pll_clk->name, ret);
kfree(pll);
return;
}
samsung_clk_add_lookup(ctx, clk, pll_clk->id);
samsung_clk_add_lookup(ctx, &pll->hw, pll_clk->id);
if (!pll_clk->alias)
return;
ret = clk_register_clkdev(clk, pll_clk->alias, pll_clk->dev_name);
ret = clk_hw_register_clkdev(&pll->hw, pll_clk->alias,
pll_clk->dev_name);
if (ret)
pr_err("%s: failed to register lookup for %s : %d",
__func__, pll_clk->name, ret);
......
......@@ -90,13 +90,13 @@ static const struct clk_ops s3c24xx_clkout_ops = {
.determine_rate = __clk_mux_determine_rate,
};
static struct clk *s3c24xx_register_clkout(struct device *dev, const char *name,
const char **parent_names, u8 num_parents,
static struct clk_hw *s3c24xx_register_clkout(struct device *dev,
const char *name, const char **parent_names, u8 num_parents,
u8 shift, u32 mask)
{
struct s3c24xx_clkout *clkout;
struct clk *clk;
struct clk_init_data init;
int ret;
/* allocate the clkout */
clkout = kzalloc(sizeof(*clkout), GFP_KERNEL);
......@@ -113,9 +113,11 @@ static struct clk *s3c24xx_register_clkout(struct device *dev, const char *name,
clkout->mask = mask;
clkout->hw.init = &init;
clk = clk_register(dev, &clkout->hw);
ret = clk_hw_register(dev, &clkout->hw);
if (ret)
return ERR_PTR(ret);
return clk;
return &clkout->hw;
}
/*
......@@ -125,11 +127,12 @@ static struct clk *s3c24xx_register_clkout(struct device *dev, const char *name,
struct s3c24xx_dclk {
struct device *dev;
void __iomem *base;
struct clk_onecell_data clk_data;
struct notifier_block dclk0_div_change_nb;
struct notifier_block dclk1_div_change_nb;
spinlock_t dclk_lock;
unsigned long reg_save;
/* clk_data must be the last entry in the structure */
struct clk_hw_onecell_data clk_data;
};
#define to_s3c24xx_dclk0(x) \
......@@ -240,28 +243,23 @@ static int s3c24xx_dclk_probe(struct platform_device *pdev)
{
struct s3c24xx_dclk *s3c24xx_dclk;
struct resource *mem;
struct clk **clk_table;
struct s3c24xx_dclk_drv_data *dclk_variant;
struct clk_hw **clk_table;
int ret, i;
s3c24xx_dclk = devm_kzalloc(&pdev->dev, sizeof(*s3c24xx_dclk),
GFP_KERNEL);
s3c24xx_dclk = devm_kzalloc(&pdev->dev, sizeof(*s3c24xx_dclk) +
sizeof(*s3c24xx_dclk->clk_data.hws) * DCLK_MAX_CLKS,
GFP_KERNEL);
if (!s3c24xx_dclk)
return -ENOMEM;
clk_table = s3c24xx_dclk->clk_data.hws;
s3c24xx_dclk->dev = &pdev->dev;
s3c24xx_dclk->clk_data.num = DCLK_MAX_CLKS;
platform_set_drvdata(pdev, s3c24xx_dclk);
spin_lock_init(&s3c24xx_dclk->dclk_lock);
clk_table = devm_kzalloc(&pdev->dev,
sizeof(struct clk *) * DCLK_MAX_CLKS,
GFP_KERNEL);
if (!clk_table)
return -ENOMEM;
s3c24xx_dclk->clk_data.clks = clk_table;
s3c24xx_dclk->clk_data.clk_num = DCLK_MAX_CLKS;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
s3c24xx_dclk->base = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(s3c24xx_dclk->base))
......@@ -271,29 +269,29 @@ static int s3c24xx_dclk_probe(struct platform_device *pdev)
platform_get_device_id(pdev)->driver_data;
clk_table[MUX_DCLK0] = clk_register_mux(&pdev->dev, "mux_dclk0",
clk_table[MUX_DCLK0] = clk_hw_register_mux(&pdev->dev, "mux_dclk0",
dclk_variant->mux_parent_names,
dclk_variant->mux_num_parents, 0,
s3c24xx_dclk->base, 1, 1, 0,
&s3c24xx_dclk->dclk_lock);
clk_table[MUX_DCLK1] = clk_register_mux(&pdev->dev, "mux_dclk1",
clk_table[MUX_DCLK1] = clk_hw_register_mux(&pdev->dev, "mux_dclk1",
dclk_variant->mux_parent_names,
dclk_variant->mux_num_parents, 0,
s3c24xx_dclk->base, 17, 1, 0,
&s3c24xx_dclk->dclk_lock);
clk_table[DIV_DCLK0] = clk_register_divider(&pdev->dev, "div_dclk0",
clk_table[DIV_DCLK0] = clk_hw_register_divider(&pdev->dev, "div_dclk0",
"mux_dclk0", 0, s3c24xx_dclk->base,
4, 4, 0, &s3c24xx_dclk->dclk_lock);
clk_table[DIV_DCLK1] = clk_register_divider(&pdev->dev, "div_dclk1",
clk_table[DIV_DCLK1] = clk_hw_register_divider(&pdev->dev, "div_dclk1",
"mux_dclk1", 0, s3c24xx_dclk->base,
20, 4, 0, &s3c24xx_dclk->dclk_lock);
clk_table[GATE_DCLK0] = clk_register_gate(&pdev->dev, "gate_dclk0",
clk_table[GATE_DCLK0] = clk_hw_register_gate(&pdev->dev, "gate_dclk0",
"div_dclk0", CLK_SET_RATE_PARENT,
s3c24xx_dclk->base, 0, 0,
&s3c24xx_dclk->dclk_lock);
clk_table[GATE_DCLK1] = clk_register_gate(&pdev->dev, "gate_dclk1",
clk_table[GATE_DCLK1] = clk_hw_register_gate(&pdev->dev, "gate_dclk1",
"div_dclk1", CLK_SET_RATE_PARENT,
s3c24xx_dclk->base, 16, 0,
&s3c24xx_dclk->dclk_lock);
......@@ -312,15 +310,16 @@ static int s3c24xx_dclk_probe(struct platform_device *pdev)
goto err_clk_register;
}
ret = clk_register_clkdev(clk_table[MUX_DCLK0], "dclk0", NULL);
ret = clk_hw_register_clkdev(clk_table[MUX_DCLK0], "dclk0", NULL);
if (!ret)
ret = clk_register_clkdev(clk_table[MUX_DCLK1], "dclk1", NULL);
ret = clk_hw_register_clkdev(clk_table[MUX_DCLK1], "dclk1",
NULL);
if (!ret)
ret = clk_register_clkdev(clk_table[MUX_CLKOUT0],
"clkout0", NULL);
ret = clk_hw_register_clkdev(clk_table[MUX_CLKOUT0],
"clkout0", NULL);
if (!ret)
ret = clk_register_clkdev(clk_table[MUX_CLKOUT1],
"clkout1", NULL);
ret = clk_hw_register_clkdev(clk_table[MUX_CLKOUT1],
"clkout1", NULL);
if (ret) {
dev_err(&pdev->dev, "failed to register aliases, %d\n", ret);
goto err_clk_register;
......@@ -332,12 +331,12 @@ static int s3c24xx_dclk_probe(struct platform_device *pdev)
s3c24xx_dclk->dclk1_div_change_nb.notifier_call =
s3c24xx_dclk1_div_notify;
ret = clk_notifier_register(clk_table[DIV_DCLK0],
ret = clk_notifier_register(clk_table[DIV_DCLK0]->clk,
&s3c24xx_dclk->dclk0_div_change_nb);
if (ret)
goto err_clk_register;
ret = clk_notifier_register(clk_table[DIV_DCLK1],
ret = clk_notifier_register(clk_table[DIV_DCLK1]->clk,
&s3c24xx_dclk->dclk1_div_change_nb);
if (ret)
goto err_dclk_notify;
......@@ -345,12 +344,12 @@ static int s3c24xx_dclk_probe(struct platform_device *pdev)
return 0;
err_dclk_notify:
clk_notifier_unregister(clk_table[DIV_DCLK0],
clk_notifier_unregister(clk_table[DIV_DCLK0]->clk,
&s3c24xx_dclk->dclk0_div_change_nb);
err_clk_register:
for (i = 0; i < DCLK_MAX_CLKS; i++)
if (clk_table[i] && !IS_ERR(clk_table[i]))
clk_unregister(clk_table[i]);
clk_hw_unregister(clk_table[i]);
return ret;
}
......@@ -358,16 +357,16 @@ static int s3c24xx_dclk_probe(struct platform_device *pdev)
static int s3c24xx_dclk_remove(struct platform_device *pdev)
{
struct s3c24xx_dclk *s3c24xx_dclk = platform_get_drvdata(pdev);
struct clk **clk_table = s3c24xx_dclk->clk_data.clks;
struct clk_hw **clk_table = s3c24xx_dclk->clk_data.hws;
int i;
clk_notifier_unregister(clk_table[DIV_DCLK1],
clk_notifier_unregister(clk_table[DIV_DCLK1]->clk,
&s3c24xx_dclk->dclk1_div_change_nb);
clk_notifier_unregister(clk_table[DIV_DCLK0],
clk_notifier_unregister(clk_table[DIV_DCLK0]->clk,
&s3c24xx_dclk->dclk0_div_change_nb);
for (i = 0; i < DCLK_MAX_CLKS; i++)
clk_unregister(clk_table[i]);
clk_hw_unregister(clk_table[i]);
return 0;
}
......
......@@ -60,23 +60,18 @@ struct samsung_clk_provider *__init samsung_clk_init(struct device_node *np,
void __iomem *base, unsigned long nr_clks)
{
struct samsung_clk_provider *ctx;
struct clk **clk_table;
int i;
ctx = kzalloc(sizeof(struct samsung_clk_provider), GFP_KERNEL);
ctx = kzalloc(sizeof(struct samsung_clk_provider) +
sizeof(*ctx->clk_data.hws) * nr_clks, GFP_KERNEL);
if (!ctx)
panic("could not allocate clock provider context.\n");
clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL);
if (!clk_table)
panic("could not allocate clock lookup table\n");
for (i = 0; i < nr_clks; ++i)
clk_table[i] = ERR_PTR(-ENOENT);
ctx->clk_data.hws[i] = ERR_PTR(-ENOENT);
ctx->reg_base = base;
ctx->clk_data.clks = clk_table;
ctx->clk_data.clk_num = nr_clks;
ctx->clk_data.num = nr_clks;
spin_lock_init(&ctx->lock);
return ctx;
......@@ -86,18 +81,18 @@ void __init samsung_clk_of_add_provider(struct device_node *np,
struct samsung_clk_provider *ctx)
{
if (np) {
if (of_clk_add_provider(np, of_clk_src_onecell_get,
if (of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
&ctx->clk_data))
panic("could not register clk provider\n");
}
}
/* add a clock instance to the clock lookup table used for dt based lookup */
void samsung_clk_add_lookup(struct samsung_clk_provider *ctx, struct clk *clk,
unsigned int id)
void samsung_clk_add_lookup(struct samsung_clk_provider *ctx,
struct clk_hw *clk_hw, unsigned int id)
{
if (ctx->clk_data.clks && id)
ctx->clk_data.clks[id] = clk;
if (id)
ctx->clk_data.hws[id] = clk_hw;
}
/* register a list of aliases */
......@@ -105,14 +100,9 @@ void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
const struct samsung_clock_alias *list,
unsigned int nr_clk)
{
struct clk *clk;
struct clk_hw *clk_hw;
unsigned int idx, ret;
if (!ctx->clk_data.clks) {
pr_err("%s: clock table missing\n", __func__);
return;
}
for (idx = 0; idx < nr_clk; idx++, list++) {
if (!list->id) {
pr_err("%s: clock id missing for index %d\n", __func__,
......@@ -120,14 +110,15 @@ void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
continue;
}
clk = ctx->clk_data.clks[list->id];
if (!clk) {
clk_hw = ctx->clk_data.hws[list->id];
if (!clk_hw) {
pr_err("%s: failed to find clock %d\n", __func__,
list->id);
continue;
}
ret = clk_register_clkdev(clk, list->alias, list->dev_name);
ret = clk_hw_register_clkdev(clk_hw, list->alias,
list->dev_name);
if (ret)
pr_err("%s: failed to register lookup %s\n",
__func__, list->alias);
......@@ -139,25 +130,25 @@ void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx,
const struct samsung_fixed_rate_clock *list,
unsigned int nr_clk)
{
struct clk *clk;
struct clk_hw *clk_hw;
unsigned int idx, ret;
for (idx = 0; idx < nr_clk; idx++, list++) {
clk = clk_register_fixed_rate(NULL, list->name,
clk_hw = clk_hw_register_fixed_rate(NULL, list->name,
list->parent_name, list->flags, list->fixed_rate);
if (IS_ERR(clk)) {
if (IS_ERR(clk_hw)) {
pr_err("%s: failed to register clock %s\n", __func__,
list->name);
continue;
}
samsung_clk_add_lookup(ctx, clk, list->id);
samsung_clk_add_lookup(ctx, clk_hw, list->id);
/*
* Unconditionally add a clock lookup for the fixed rate clocks.
* There are not many of these on any of Samsung platforms.
*/
ret = clk_register_clkdev(clk, list->name, NULL);
ret = clk_hw_register_clkdev(clk_hw, list->name, NULL);
if (ret)
pr_err("%s: failed to register clock lookup for %s",
__func__, list->name);
......@@ -168,19 +159,19 @@ void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx,
void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx,
const struct samsung_fixed_factor_clock *list, unsigned int nr_clk)
{
struct clk *clk;
struct clk_hw *clk_hw;
unsigned int idx;
for (idx = 0; idx < nr_clk; idx++, list++) {
clk = clk_register_fixed_factor(NULL, list->name,
clk_hw = clk_hw_register_fixed_factor(NULL, list->name,
list->parent_name, list->flags, list->mult, list->div);
if (IS_ERR(clk)) {
if (IS_ERR(clk_hw)) {
pr_err("%s: failed to register clock %s\n", __func__,
list->name);
continue;
}
samsung_clk_add_lookup(ctx, clk, list->id);
samsung_clk_add_lookup(ctx, clk_hw, list->id);
}
}
......@@ -189,25 +180,25 @@ void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
const struct samsung_mux_clock *list,
unsigned int nr_clk)
{
struct clk *clk;
struct clk_hw *clk_hw;
unsigned int idx, ret;
for (idx = 0; idx < nr_clk; idx++, list++) {
clk = clk_register_mux(NULL, list->name, list->parent_names,
list->num_parents, list->flags,
clk_hw = clk_hw_register_mux(NULL, list->name,
list->parent_names, list->num_parents, list->flags,
ctx->reg_base + list->offset,
list->shift, list->width, list->mux_flags, &ctx->lock);
if (IS_ERR(clk)) {
if (IS_ERR(clk_hw)) {
pr_err("%s: failed to register clock %s\n", __func__,
list->name);
continue;
}
samsung_clk_add_lookup(ctx, clk, list->id);
samsung_clk_add_lookup(ctx, clk_hw, list->id);
/* register a clock lookup only if a clock alias is specified */
if (list->alias) {
ret = clk_register_clkdev(clk, list->alias,
ret = clk_hw_register_clkdev(clk_hw, list->alias,
list->dev_name);
if (ret)
pr_err("%s: failed to register lookup %s\n",
......@@ -221,32 +212,32 @@ void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
const struct samsung_div_clock *list,
unsigned int nr_clk)
{
struct clk *clk;
struct clk_hw *clk_hw;
unsigned int idx, ret;
for (idx = 0; idx < nr_clk; idx++, list++) {
if (list->table)
clk = clk_register_divider_table(NULL, list->name,
list->parent_name, list->flags,
clk_hw = clk_hw_register_divider_table(NULL,
list->name, list->parent_name, list->flags,
ctx->reg_base + list->offset,
list->shift, list->width, list->div_flags,
list->table, &ctx->lock);
else
clk = clk_register_divider(NULL, list->name,
clk_hw = clk_hw_register_divider(NULL, list->name,
list->parent_name, list->flags,
ctx->reg_base + list->offset, list->shift,
list->width, list->div_flags, &ctx->lock);
if (IS_ERR(clk)) {
if (IS_ERR(clk_hw)) {
pr_err("%s: failed to register clock %s\n", __func__,
list->name);
continue;
}
samsung_clk_add_lookup(ctx, clk, list->id);
samsung_clk_add_lookup(ctx, clk_hw, list->id);
/* register a clock lookup only if a clock alias is specified */
if (list->alias) {
ret = clk_register_clkdev(clk, list->alias,
ret = clk_hw_register_clkdev(clk_hw, list->alias,
list->dev_name);
if (ret)
pr_err("%s: failed to register lookup %s\n",
......@@ -260,14 +251,14 @@ void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
const struct samsung_gate_clock *list,
unsigned int nr_clk)
{
struct clk *clk;
struct clk_hw *clk_hw;
unsigned int idx, ret;
for (idx = 0; idx < nr_clk; idx++, list++) {
clk = clk_register_gate(NULL, list->name, list->parent_name,
clk_hw = clk_hw_register_gate(NULL, list->name, list->parent_name,
list->flags, ctx->reg_base + list->offset,
list->bit_idx, list->gate_flags, &ctx->lock);
if (IS_ERR(clk)) {
if (IS_ERR(clk_hw)) {
pr_err("%s: failed to register clock %s\n", __func__,
list->name);
continue;
......@@ -275,14 +266,14 @@ void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
/* register a clock lookup only if a clock alias is specified */
if (list->alias) {
ret = clk_register_clkdev(clk, list->alias,
ret = clk_hw_register_clkdev(clk_hw, list->alias,
list->dev_name);
if (ret)
pr_err("%s: failed to register lookup %s\n",
__func__, list->alias);
}
samsung_clk_add_lookup(ctx, clk, list->id);
samsung_clk_add_lookup(ctx, clk_hw, list->id);
}
}
......
......@@ -16,18 +16,17 @@
#include <linux/clk-provider.h>
#include "clk-pll.h"
struct clk;
/**
* struct samsung_clk_provider: information about clock provider
* @reg_base: virtual address for the register base.
* @clk_data: holds clock related data like clk* and number of clocks.
* @lock: maintains exclusion between callbacks for a given clock-provider.
* @clk_data: holds clock related data like clk_hw* and number of clocks.
*/
struct samsung_clk_provider {
void __iomem *reg_base;
struct clk_onecell_data clk_data;
spinlock_t lock;
/* clk_data must be the last entry due to variable lenght 'hws' array */
struct clk_hw_onecell_data clk_data;
};
/**
......@@ -367,7 +366,7 @@ extern void __init samsung_clk_of_register_fixed_ext(
const struct of_device_id *clk_matches);
extern void samsung_clk_add_lookup(struct samsung_clk_provider *ctx,
struct clk *clk, unsigned int id);
struct clk_hw *clk_hw, unsigned int id);
extern void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
const struct samsung_clock_alias *list,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment