clk: mvebu: migrate CP110 system controller to clk_hw API and registration

Now that we have clk_hw based provider APIs to register clks, we
can get rid of struct clk pointers while registering clks in Armada
CP110 system controller driver. This commit introduces new
API and registration for all clocks in CP110 HW blocks.

Signed-off-by: Marcin Wojtas <mw@semihalf.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
This commit is contained in:
Marcin Wojtas 2016-09-25 09:47:53 +02:00 committed by Stephen Boyd
parent 9c1b305c1e
commit 57ecc7a0d3
1 changed files with 72 additions and 78 deletions

View File

@ -87,7 +87,7 @@ struct cp110_gate_clk {
u8 bit_idx; u8 bit_idx;
}; };
#define to_cp110_gate_clk(clk) container_of(clk, struct cp110_gate_clk, hw) #define to_cp110_gate_clk(hw) container_of(hw, struct cp110_gate_clk, hw)
static int cp110_gate_enable(struct clk_hw *hw) static int cp110_gate_enable(struct clk_hw *hw)
{ {
@ -123,13 +123,14 @@ static const struct clk_ops cp110_gate_ops = {
.is_enabled = cp110_gate_is_enabled, .is_enabled = cp110_gate_is_enabled,
}; };
static struct clk *cp110_register_gate(const char *name, static struct clk_hw *cp110_register_gate(const char *name,
const char *parent_name, const char *parent_name,
struct regmap *regmap, u8 bit_idx) struct regmap *regmap, u8 bit_idx)
{ {
struct cp110_gate_clk *gate; struct cp110_gate_clk *gate;
struct clk *clk; struct clk_hw *hw;
struct clk_init_data init; struct clk_init_data init;
int ret;
gate = kzalloc(sizeof(*gate), GFP_KERNEL); gate = kzalloc(sizeof(*gate), GFP_KERNEL);
if (!gate) if (!gate)
@ -146,39 +147,37 @@ static struct clk *cp110_register_gate(const char *name,
gate->bit_idx = bit_idx; gate->bit_idx = bit_idx;
gate->hw.init = &init; gate->hw.init = &init;
clk = clk_register(NULL, &gate->hw); hw = &gate->hw;
if (IS_ERR(clk)) ret = clk_hw_register(NULL, hw);
if (ret) {
kfree(gate); kfree(gate);
hw = ERR_PTR(ret);
}
return clk; return hw;
} }
static void cp110_unregister_gate(struct clk *clk) static void cp110_unregister_gate(struct clk_hw *hw)
{ {
struct clk_hw *hw; clk_hw_unregister(hw);
hw = __clk_get_hw(clk);
if (!hw)
return;
clk_unregister(clk);
kfree(to_cp110_gate_clk(hw)); kfree(to_cp110_gate_clk(hw));
} }
static struct clk *cp110_of_clk_get(struct of_phandle_args *clkspec, void *data) static struct clk_hw *cp110_of_clk_get(struct of_phandle_args *clkspec,
void *data)
{ {
struct clk_onecell_data *clk_data = data; struct clk_hw_onecell_data *clk_data = data;
unsigned int type = clkspec->args[0]; unsigned int type = clkspec->args[0];
unsigned int idx = clkspec->args[1]; unsigned int idx = clkspec->args[1];
if (type == CP110_CLK_TYPE_CORE) { if (type == CP110_CLK_TYPE_CORE) {
if (idx > CP110_MAX_CORE_CLOCKS) if (idx > CP110_MAX_CORE_CLOCKS)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
return clk_data->clks[idx]; return clk_data->hws[idx];
} else if (type == CP110_CLK_TYPE_GATABLE) { } else if (type == CP110_CLK_TYPE_GATABLE) {
if (idx > CP110_MAX_GATABLE_CLOCKS) if (idx > CP110_MAX_GATABLE_CLOCKS)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
return clk_data->clks[CP110_MAX_CORE_CLOCKS + idx]; return clk_data->hws[CP110_MAX_CORE_CLOCKS + idx];
} }
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
@ -189,8 +188,8 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
struct regmap *regmap; struct regmap *regmap;
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
const char *ppv2_name, *apll_name, *core_name, *eip_name, *nand_name; const char *ppv2_name, *apll_name, *core_name, *eip_name, *nand_name;
struct clk_onecell_data *cp110_clk_data; struct clk_hw_onecell_data *cp110_clk_data;
struct clk *clk, **cp110_clks; struct clk_hw *hw, **cp110_clks;
u32 nand_clk_ctrl; u32 nand_clk_ctrl;
int i, ret; int i, ret;
@ -203,80 +202,75 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
if (ret) if (ret)
return ret; return ret;
cp110_clks = devm_kcalloc(&pdev->dev, sizeof(struct clk *), cp110_clk_data = devm_kzalloc(&pdev->dev, sizeof(*cp110_clk_data) +
CP110_CLK_NUM, GFP_KERNEL); sizeof(struct clk_hw *) * CP110_CLK_NUM,
if (!cp110_clks)
return -ENOMEM;
cp110_clk_data = devm_kzalloc(&pdev->dev,
sizeof(*cp110_clk_data),
GFP_KERNEL); GFP_KERNEL);
if (!cp110_clk_data) if (!cp110_clk_data)
return -ENOMEM; return -ENOMEM;
cp110_clk_data->clks = cp110_clks; cp110_clks = cp110_clk_data->hws;
cp110_clk_data->clk_num = CP110_CLK_NUM; cp110_clk_data->num = CP110_CLK_NUM;
/* Register the APLL which is the root of the clk tree */ /* Register the APLL which is the root of the hw tree */
of_property_read_string_index(np, "core-clock-output-names", of_property_read_string_index(np, "core-clock-output-names",
CP110_CORE_APLL, &apll_name); CP110_CORE_APLL, &apll_name);
clk = clk_register_fixed_rate(NULL, apll_name, NULL, 0, hw = clk_hw_register_fixed_rate(NULL, apll_name, NULL, 0,
1000 * 1000 * 1000); 1000 * 1000 * 1000);
if (IS_ERR(clk)) { if (IS_ERR(hw)) {
ret = PTR_ERR(clk); ret = PTR_ERR(hw);
goto fail0; goto fail0;
} }
cp110_clks[CP110_CORE_APLL] = clk; cp110_clks[CP110_CORE_APLL] = hw;
/* PPv2 is APLL/3 */ /* PPv2 is APLL/3 */
of_property_read_string_index(np, "core-clock-output-names", of_property_read_string_index(np, "core-clock-output-names",
CP110_CORE_PPV2, &ppv2_name); CP110_CORE_PPV2, &ppv2_name);
clk = clk_register_fixed_factor(NULL, ppv2_name, apll_name, 0, 1, 3); hw = clk_hw_register_fixed_factor(NULL, ppv2_name, apll_name, 0, 1, 3);
if (IS_ERR(clk)) { if (IS_ERR(hw)) {
ret = PTR_ERR(clk); ret = PTR_ERR(hw);
goto fail1; goto fail1;
} }
cp110_clks[CP110_CORE_PPV2] = clk; cp110_clks[CP110_CORE_PPV2] = hw;
/* EIP clock is APLL/2 */ /* EIP clock is APLL/2 */
of_property_read_string_index(np, "core-clock-output-names", of_property_read_string_index(np, "core-clock-output-names",
CP110_CORE_EIP, &eip_name); CP110_CORE_EIP, &eip_name);
clk = clk_register_fixed_factor(NULL, eip_name, apll_name, 0, 1, 2); hw = clk_hw_register_fixed_factor(NULL, eip_name, apll_name, 0, 1, 2);
if (IS_ERR(clk)) { if (IS_ERR(hw)) {
ret = PTR_ERR(clk); ret = PTR_ERR(hw);
goto fail2; goto fail2;
} }
cp110_clks[CP110_CORE_EIP] = clk; cp110_clks[CP110_CORE_EIP] = hw;
/* Core clock is EIP/2 */ /* Core clock is EIP/2 */
of_property_read_string_index(np, "core-clock-output-names", of_property_read_string_index(np, "core-clock-output-names",
CP110_CORE_CORE, &core_name); CP110_CORE_CORE, &core_name);
clk = clk_register_fixed_factor(NULL, core_name, eip_name, 0, 1, 2); hw = clk_hw_register_fixed_factor(NULL, core_name, eip_name, 0, 1, 2);
if (IS_ERR(clk)) { if (IS_ERR(hw)) {
ret = PTR_ERR(clk); ret = PTR_ERR(hw);
goto fail3; goto fail3;
} }
cp110_clks[CP110_CORE_CORE] = clk; cp110_clks[CP110_CORE_CORE] = hw;
/* NAND can be either APLL/2.5 or core clock */ /* NAND can be either APLL/2.5 or core clock */
of_property_read_string_index(np, "core-clock-output-names", of_property_read_string_index(np, "core-clock-output-names",
CP110_CORE_NAND, &nand_name); CP110_CORE_NAND, &nand_name);
if (nand_clk_ctrl & NF_CLOCK_SEL_400_MASK) if (nand_clk_ctrl & NF_CLOCK_SEL_400_MASK)
clk = clk_register_fixed_factor(NULL, nand_name, hw = clk_hw_register_fixed_factor(NULL, nand_name,
apll_name, 0, 2, 5); apll_name, 0, 2, 5);
else else
clk = clk_register_fixed_factor(NULL, nand_name, hw = clk_hw_register_fixed_factor(NULL, nand_name,
core_name, 0, 1, 1); core_name, 0, 1, 1);
if (IS_ERR(clk)) { if (IS_ERR(hw)) {
ret = PTR_ERR(clk); ret = PTR_ERR(hw);
goto fail4; goto fail4;
} }
cp110_clks[CP110_CORE_NAND] = clk; cp110_clks[CP110_CORE_NAND] = hw;
for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) { for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) {
const char *parent, *name; const char *parent, *name;
@ -335,16 +329,16 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
break; break;
} }
clk = cp110_register_gate(name, parent, regmap, i); hw = cp110_register_gate(name, parent, regmap, i);
if (IS_ERR(clk)) { if (IS_ERR(hw)) {
ret = PTR_ERR(clk); ret = PTR_ERR(hw);
goto fail_gate; goto fail_gate;
} }
cp110_clks[CP110_MAX_CORE_CLOCKS + i] = clk; cp110_clks[CP110_MAX_CORE_CLOCKS + i] = hw;
} }
ret = of_clk_add_provider(np, cp110_of_clk_get, cp110_clk_data); ret = of_clk_add_hw_provider(np, cp110_of_clk_get, cp110_clk_data);
if (ret) if (ret)
goto fail_clk_add; goto fail_clk_add;
@ -355,44 +349,44 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
fail_clk_add: fail_clk_add:
fail_gate: fail_gate:
for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) { for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) {
clk = cp110_clks[CP110_MAX_CORE_CLOCKS + i]; hw = cp110_clks[CP110_MAX_CORE_CLOCKS + i];
if (clk) if (hw)
cp110_unregister_gate(clk); cp110_unregister_gate(hw);
} }
clk_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]); clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]);
fail4: fail4:
clk_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]); clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]);
fail3: fail3:
clk_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]); clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]);
fail2: fail2:
clk_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]); clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]);
fail1: fail1:
clk_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]); clk_hw_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]);
fail0: fail0:
return ret; return ret;
} }
static int cp110_syscon_clk_remove(struct platform_device *pdev) static int cp110_syscon_clk_remove(struct platform_device *pdev)
{ {
struct clk **cp110_clks = platform_get_drvdata(pdev); struct clk_hw **cp110_clks = platform_get_drvdata(pdev);
int i; int i;
of_clk_del_provider(pdev->dev.of_node); of_clk_del_provider(pdev->dev.of_node);
for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) { for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) {
struct clk *clk = cp110_clks[CP110_MAX_CORE_CLOCKS + i]; struct clk_hw *hw = cp110_clks[CP110_MAX_CORE_CLOCKS + i];
if (clk) if (hw)
cp110_unregister_gate(clk); cp110_unregister_gate(hw);
} }
clk_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]); clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]);
clk_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]); clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]);
clk_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]); clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]);
clk_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]); clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]);
clk_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]); clk_hw_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]);
return 0; return 0;
} }