提交 0cd3be6e 编写于 作者: S Sebastian Hesselbarth 提交者: Michael Turquette

clk: si5351: Do not pass struct clk in platform_data

When registering clk-si5351 by platform_data, we should not pass struct clk
for the reference clocks. Drop struct clk from platform_data and rework the
driver to use devm_clk_get of named clock references.

While at it, check for at least one valid input clock and properly prepare/
enable valid reference clocks.
Signed-off-by: NSebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Reported-by: NMichael Welling <mwelling@ieee.org>
Reported-by: NJean-Francois Moine <moinejf@free.fr>
Reported-by: NRussell King <rmk+linux@arm.linux.org.uk>
Tested-by: NMichael Welling <mwelling@ieee.org>
Tested-by: NJean-Francois Moine <moinejf@free.fr>
Signed-off-by: NMichael Turquette <mturquette@linaro.org>
上级 f94029d8
...@@ -1128,13 +1128,6 @@ static int si5351_dt_parse(struct i2c_client *client, ...@@ -1128,13 +1128,6 @@ static int si5351_dt_parse(struct i2c_client *client,
if (!pdata) if (!pdata)
return -ENOMEM; return -ENOMEM;
pdata->clk_xtal = of_clk_get(np, 0);
if (!IS_ERR(pdata->clk_xtal))
clk_put(pdata->clk_xtal);
pdata->clk_clkin = of_clk_get(np, 1);
if (!IS_ERR(pdata->clk_clkin))
clk_put(pdata->clk_clkin);
/* /*
* property silabs,pll-source : <num src>, [<..>] * property silabs,pll-source : <num src>, [<..>]
* allow to selectively set pll source * allow to selectively set pll source
...@@ -1328,8 +1321,22 @@ static int si5351_i2c_probe(struct i2c_client *client, ...@@ -1328,8 +1321,22 @@ static int si5351_i2c_probe(struct i2c_client *client,
i2c_set_clientdata(client, drvdata); i2c_set_clientdata(client, drvdata);
drvdata->client = client; drvdata->client = client;
drvdata->variant = variant; drvdata->variant = variant;
drvdata->pxtal = pdata->clk_xtal; drvdata->pxtal = devm_clk_get(&client->dev, "xtal");
drvdata->pclkin = pdata->clk_clkin; drvdata->pclkin = devm_clk_get(&client->dev, "clkin");
if (PTR_ERR(drvdata->pxtal) == -EPROBE_DEFER ||
PTR_ERR(drvdata->pclkin) == -EPROBE_DEFER)
return -EPROBE_DEFER;
/*
* Check for valid parent clock: VARIANT_A and VARIANT_B need XTAL,
* VARIANT_C can have CLKIN instead.
*/
if (IS_ERR(drvdata->pxtal) &&
(drvdata->variant != SI5351_VARIANT_C || IS_ERR(drvdata->pclkin))) {
dev_err(&client->dev, "missing parent clock\n");
return -EINVAL;
}
drvdata->regmap = devm_regmap_init_i2c(client, &si5351_regmap_config); drvdata->regmap = devm_regmap_init_i2c(client, &si5351_regmap_config);
if (IS_ERR(drvdata->regmap)) { if (IS_ERR(drvdata->regmap)) {
...@@ -1393,6 +1400,11 @@ static int si5351_i2c_probe(struct i2c_client *client, ...@@ -1393,6 +1400,11 @@ static int si5351_i2c_probe(struct i2c_client *client,
} }
} }
if (!IS_ERR(drvdata->pxtal))
clk_prepare_enable(drvdata->pxtal);
if (!IS_ERR(drvdata->pclkin))
clk_prepare_enable(drvdata->pclkin);
/* register xtal input clock gate */ /* register xtal input clock gate */
memset(&init, 0, sizeof(init)); memset(&init, 0, sizeof(init));
init.name = si5351_input_names[0]; init.name = si5351_input_names[0];
...@@ -1407,7 +1419,8 @@ static int si5351_i2c_probe(struct i2c_client *client, ...@@ -1407,7 +1419,8 @@ static int si5351_i2c_probe(struct i2c_client *client,
clk = devm_clk_register(&client->dev, &drvdata->xtal); clk = devm_clk_register(&client->dev, &drvdata->xtal);
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
dev_err(&client->dev, "unable to register %s\n", init.name); dev_err(&client->dev, "unable to register %s\n", init.name);
return PTR_ERR(clk); ret = PTR_ERR(clk);
goto err_clk;
} }
/* register clkin input clock gate */ /* register clkin input clock gate */
...@@ -1425,7 +1438,8 @@ static int si5351_i2c_probe(struct i2c_client *client, ...@@ -1425,7 +1438,8 @@ static int si5351_i2c_probe(struct i2c_client *client,
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
dev_err(&client->dev, "unable to register %s\n", dev_err(&client->dev, "unable to register %s\n",
init.name); init.name);
return PTR_ERR(clk); ret = PTR_ERR(clk);
goto err_clk;
} }
} }
...@@ -1447,7 +1461,8 @@ static int si5351_i2c_probe(struct i2c_client *client, ...@@ -1447,7 +1461,8 @@ static int si5351_i2c_probe(struct i2c_client *client,
clk = devm_clk_register(&client->dev, &drvdata->pll[0].hw); clk = devm_clk_register(&client->dev, &drvdata->pll[0].hw);
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
dev_err(&client->dev, "unable to register %s\n", init.name); dev_err(&client->dev, "unable to register %s\n", init.name);
return -EINVAL; ret = PTR_ERR(clk);
goto err_clk;
} }
/* register PLLB or VXCO (Si5351B) */ /* register PLLB or VXCO (Si5351B) */
...@@ -1471,7 +1486,8 @@ static int si5351_i2c_probe(struct i2c_client *client, ...@@ -1471,7 +1486,8 @@ static int si5351_i2c_probe(struct i2c_client *client,
clk = devm_clk_register(&client->dev, &drvdata->pll[1].hw); clk = devm_clk_register(&client->dev, &drvdata->pll[1].hw);
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
dev_err(&client->dev, "unable to register %s\n", init.name); dev_err(&client->dev, "unable to register %s\n", init.name);
return -EINVAL; ret = PTR_ERR(clk);
goto err_clk;
} }
/* register clk multisync and clk out divider */ /* register clk multisync and clk out divider */
...@@ -1492,8 +1508,10 @@ static int si5351_i2c_probe(struct i2c_client *client, ...@@ -1492,8 +1508,10 @@ static int si5351_i2c_probe(struct i2c_client *client,
num_clocks * sizeof(*drvdata->onecell.clks), GFP_KERNEL); num_clocks * sizeof(*drvdata->onecell.clks), GFP_KERNEL);
if (WARN_ON(!drvdata->msynth || !drvdata->clkout || if (WARN_ON(!drvdata->msynth || !drvdata->clkout ||
!drvdata->onecell.clks)) !drvdata->onecell.clks)) {
return -ENOMEM; ret = -ENOMEM;
goto err_clk;
}
for (n = 0; n < num_clocks; n++) { for (n = 0; n < num_clocks; n++) {
drvdata->msynth[n].num = n; drvdata->msynth[n].num = n;
...@@ -1511,7 +1529,8 @@ static int si5351_i2c_probe(struct i2c_client *client, ...@@ -1511,7 +1529,8 @@ static int si5351_i2c_probe(struct i2c_client *client,
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
dev_err(&client->dev, "unable to register %s\n", dev_err(&client->dev, "unable to register %s\n",
init.name); init.name);
return -EINVAL; ret = PTR_ERR(clk);
goto err_clk;
} }
} }
...@@ -1538,7 +1557,8 @@ static int si5351_i2c_probe(struct i2c_client *client, ...@@ -1538,7 +1557,8 @@ static int si5351_i2c_probe(struct i2c_client *client,
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
dev_err(&client->dev, "unable to register %s\n", dev_err(&client->dev, "unable to register %s\n",
init.name); init.name);
return -EINVAL; ret = PTR_ERR(clk);
goto err_clk;
} }
drvdata->onecell.clks[n] = clk; drvdata->onecell.clks[n] = clk;
...@@ -1557,10 +1577,17 @@ static int si5351_i2c_probe(struct i2c_client *client, ...@@ -1557,10 +1577,17 @@ static int si5351_i2c_probe(struct i2c_client *client,
&drvdata->onecell); &drvdata->onecell);
if (ret) { if (ret) {
dev_err(&client->dev, "unable to add clk provider\n"); dev_err(&client->dev, "unable to add clk provider\n");
return ret; goto err_clk;
} }
return 0; return 0;
err_clk:
if (!IS_ERR(drvdata->pxtal))
clk_disable_unprepare(drvdata->pxtal);
if (!IS_ERR(drvdata->pclkin))
clk_disable_unprepare(drvdata->pclkin);
return ret;
} }
static const struct i2c_device_id si5351_i2c_ids[] = { static const struct i2c_device_id si5351_i2c_ids[] = {
......
...@@ -5,8 +5,6 @@ ...@@ -5,8 +5,6 @@
#ifndef __LINUX_PLATFORM_DATA_SI5351_H__ #ifndef __LINUX_PLATFORM_DATA_SI5351_H__
#define __LINUX_PLATFORM_DATA_SI5351_H__ #define __LINUX_PLATFORM_DATA_SI5351_H__
struct clk;
/** /**
* enum si5351_pll_src - Si5351 pll clock source * enum si5351_pll_src - Si5351 pll clock source
* @SI5351_PLL_SRC_DEFAULT: default, do not change eeprom config * @SI5351_PLL_SRC_DEFAULT: default, do not change eeprom config
...@@ -107,8 +105,6 @@ struct si5351_clkout_config { ...@@ -107,8 +105,6 @@ struct si5351_clkout_config {
* @clkout: array of clkout configuration * @clkout: array of clkout configuration
*/ */
struct si5351_platform_data { struct si5351_platform_data {
struct clk *clk_xtal;
struct clk *clk_clkin;
enum si5351_pll_src pll_src[2]; enum si5351_pll_src pll_src[2];
struct si5351_clkout_config clkout[8]; struct si5351_clkout_config clkout[8];
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册