diff options
author | Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> | 2015-05-04 17:04:16 -0400 |
---|---|---|
committer | Michael Turquette <mturquette@linaro.org> | 2015-05-08 14:22:30 -0400 |
commit | 0cd3be6e9a46f84ef7a42e1a5645d32ad547b12e (patch) | |
tree | bae0942e47885b7ddf6b6ea1897a53abf649b6e4 | |
parent | f94029d8801d7c27a94a3ea6c4967aa33c49c34b (diff) |
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: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Reported-by: Michael Welling <mwelling@ieee.org>
Reported-by: Jean-Francois Moine <moinejf@free.fr>
Reported-by: Russell King <rmk+linux@arm.linux.org.uk>
Tested-by: Michael Welling <mwelling@ieee.org>
Tested-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Michael Turquette <mturquette@linaro.org>
-rw-r--r-- | drivers/clk/clk-si5351.c | 63 | ||||
-rw-r--r-- | include/linux/platform_data/si5351.h | 4 |
2 files changed, 45 insertions, 22 deletions
diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c index 44ea107cfc67..30335d3b99af 100644 --- a/drivers/clk/clk-si5351.c +++ b/drivers/clk/clk-si5351.c | |||
@@ -1128,13 +1128,6 @@ static int si5351_dt_parse(struct i2c_client *client, | |||
1128 | if (!pdata) | 1128 | if (!pdata) |
1129 | return -ENOMEM; | 1129 | return -ENOMEM; |
1130 | 1130 | ||
1131 | pdata->clk_xtal = of_clk_get(np, 0); | ||
1132 | if (!IS_ERR(pdata->clk_xtal)) | ||
1133 | clk_put(pdata->clk_xtal); | ||
1134 | pdata->clk_clkin = of_clk_get(np, 1); | ||
1135 | if (!IS_ERR(pdata->clk_clkin)) | ||
1136 | clk_put(pdata->clk_clkin); | ||
1137 | |||
1138 | /* | 1131 | /* |
1139 | * property silabs,pll-source : <num src>, [<..>] | 1132 | * property silabs,pll-source : <num src>, [<..>] |
1140 | * allow to selectively set pll source | 1133 | * allow to selectively set pll source |
@@ -1328,8 +1321,22 @@ static int si5351_i2c_probe(struct i2c_client *client, | |||
1328 | i2c_set_clientdata(client, drvdata); | 1321 | i2c_set_clientdata(client, drvdata); |
1329 | drvdata->client = client; | 1322 | drvdata->client = client; |
1330 | drvdata->variant = variant; | 1323 | drvdata->variant = variant; |
1331 | drvdata->pxtal = pdata->clk_xtal; | 1324 | drvdata->pxtal = devm_clk_get(&client->dev, "xtal"); |
1332 | drvdata->pclkin = pdata->clk_clkin; | 1325 | drvdata->pclkin = devm_clk_get(&client->dev, "clkin"); |
1326 | |||
1327 | if (PTR_ERR(drvdata->pxtal) == -EPROBE_DEFER || | ||
1328 | PTR_ERR(drvdata->pclkin) == -EPROBE_DEFER) | ||
1329 | return -EPROBE_DEFER; | ||
1330 | |||
1331 | /* | ||
1332 | * Check for valid parent clock: VARIANT_A and VARIANT_B need XTAL, | ||
1333 | * VARIANT_C can have CLKIN instead. | ||
1334 | */ | ||
1335 | if (IS_ERR(drvdata->pxtal) && | ||
1336 | (drvdata->variant != SI5351_VARIANT_C || IS_ERR(drvdata->pclkin))) { | ||
1337 | dev_err(&client->dev, "missing parent clock\n"); | ||
1338 | return -EINVAL; | ||
1339 | } | ||
1333 | 1340 | ||
1334 | drvdata->regmap = devm_regmap_init_i2c(client, &si5351_regmap_config); | 1341 | drvdata->regmap = devm_regmap_init_i2c(client, &si5351_regmap_config); |
1335 | if (IS_ERR(drvdata->regmap)) { | 1342 | if (IS_ERR(drvdata->regmap)) { |
@@ -1393,6 +1400,11 @@ static int si5351_i2c_probe(struct i2c_client *client, | |||
1393 | } | 1400 | } |
1394 | } | 1401 | } |
1395 | 1402 | ||
1403 | if (!IS_ERR(drvdata->pxtal)) | ||
1404 | clk_prepare_enable(drvdata->pxtal); | ||
1405 | if (!IS_ERR(drvdata->pclkin)) | ||
1406 | clk_prepare_enable(drvdata->pclkin); | ||
1407 | |||
1396 | /* register xtal input clock gate */ | 1408 | /* register xtal input clock gate */ |
1397 | memset(&init, 0, sizeof(init)); | 1409 | memset(&init, 0, sizeof(init)); |
1398 | init.name = si5351_input_names[0]; | 1410 | init.name = si5351_input_names[0]; |
@@ -1407,7 +1419,8 @@ static int si5351_i2c_probe(struct i2c_client *client, | |||
1407 | clk = devm_clk_register(&client->dev, &drvdata->xtal); | 1419 | clk = devm_clk_register(&client->dev, &drvdata->xtal); |
1408 | if (IS_ERR(clk)) { | 1420 | if (IS_ERR(clk)) { |
1409 | dev_err(&client->dev, "unable to register %s\n", init.name); | 1421 | dev_err(&client->dev, "unable to register %s\n", init.name); |
1410 | return PTR_ERR(clk); | 1422 | ret = PTR_ERR(clk); |
1423 | goto err_clk; | ||
1411 | } | 1424 | } |
1412 | 1425 | ||
1413 | /* register clkin input clock gate */ | 1426 | /* register clkin input clock gate */ |
@@ -1425,7 +1438,8 @@ static int si5351_i2c_probe(struct i2c_client *client, | |||
1425 | if (IS_ERR(clk)) { | 1438 | if (IS_ERR(clk)) { |
1426 | dev_err(&client->dev, "unable to register %s\n", | 1439 | dev_err(&client->dev, "unable to register %s\n", |
1427 | init.name); | 1440 | init.name); |
1428 | return PTR_ERR(clk); | 1441 | ret = PTR_ERR(clk); |
1442 | goto err_clk; | ||
1429 | } | 1443 | } |
1430 | } | 1444 | } |
1431 | 1445 | ||
@@ -1447,7 +1461,8 @@ static int si5351_i2c_probe(struct i2c_client *client, | |||
1447 | clk = devm_clk_register(&client->dev, &drvdata->pll[0].hw); | 1461 | clk = devm_clk_register(&client->dev, &drvdata->pll[0].hw); |
1448 | if (IS_ERR(clk)) { | 1462 | if (IS_ERR(clk)) { |
1449 | dev_err(&client->dev, "unable to register %s\n", init.name); | 1463 | dev_err(&client->dev, "unable to register %s\n", init.name); |
1450 | return -EINVAL; | 1464 | ret = PTR_ERR(clk); |
1465 | goto err_clk; | ||
1451 | } | 1466 | } |
1452 | 1467 | ||
1453 | /* register PLLB or VXCO (Si5351B) */ | 1468 | /* register PLLB or VXCO (Si5351B) */ |
@@ -1471,7 +1486,8 @@ static int si5351_i2c_probe(struct i2c_client *client, | |||
1471 | clk = devm_clk_register(&client->dev, &drvdata->pll[1].hw); | 1486 | clk = devm_clk_register(&client->dev, &drvdata->pll[1].hw); |
1472 | if (IS_ERR(clk)) { | 1487 | if (IS_ERR(clk)) { |
1473 | dev_err(&client->dev, "unable to register %s\n", init.name); | 1488 | dev_err(&client->dev, "unable to register %s\n", init.name); |
1474 | return -EINVAL; | 1489 | ret = PTR_ERR(clk); |
1490 | goto err_clk; | ||
1475 | } | 1491 | } |
1476 | 1492 | ||
1477 | /* register clk multisync and clk out divider */ | 1493 | /* register clk multisync and clk out divider */ |
@@ -1492,8 +1508,10 @@ static int si5351_i2c_probe(struct i2c_client *client, | |||
1492 | num_clocks * sizeof(*drvdata->onecell.clks), GFP_KERNEL); | 1508 | num_clocks * sizeof(*drvdata->onecell.clks), GFP_KERNEL); |
1493 | 1509 | ||
1494 | if (WARN_ON(!drvdata->msynth || !drvdata->clkout || | 1510 | if (WARN_ON(!drvdata->msynth || !drvdata->clkout || |
1495 | !drvdata->onecell.clks)) | 1511 | !drvdata->onecell.clks)) { |
1496 | return -ENOMEM; | 1512 | ret = -ENOMEM; |
1513 | goto err_clk; | ||
1514 | } | ||
1497 | 1515 | ||
1498 | for (n = 0; n < num_clocks; n++) { | 1516 | for (n = 0; n < num_clocks; n++) { |
1499 | drvdata->msynth[n].num = n; | 1517 | drvdata->msynth[n].num = n; |
@@ -1511,7 +1529,8 @@ static int si5351_i2c_probe(struct i2c_client *client, | |||
1511 | if (IS_ERR(clk)) { | 1529 | if (IS_ERR(clk)) { |
1512 | dev_err(&client->dev, "unable to register %s\n", | 1530 | dev_err(&client->dev, "unable to register %s\n", |
1513 | init.name); | 1531 | init.name); |
1514 | return -EINVAL; | 1532 | ret = PTR_ERR(clk); |
1533 | goto err_clk; | ||
1515 | } | 1534 | } |
1516 | } | 1535 | } |
1517 | 1536 | ||
@@ -1538,7 +1557,8 @@ static int si5351_i2c_probe(struct i2c_client *client, | |||
1538 | if (IS_ERR(clk)) { | 1557 | if (IS_ERR(clk)) { |
1539 | dev_err(&client->dev, "unable to register %s\n", | 1558 | dev_err(&client->dev, "unable to register %s\n", |
1540 | init.name); | 1559 | init.name); |
1541 | return -EINVAL; | 1560 | ret = PTR_ERR(clk); |
1561 | goto err_clk; | ||
1542 | } | 1562 | } |
1543 | drvdata->onecell.clks[n] = clk; | 1563 | drvdata->onecell.clks[n] = clk; |
1544 | 1564 | ||
@@ -1557,10 +1577,17 @@ static int si5351_i2c_probe(struct i2c_client *client, | |||
1557 | &drvdata->onecell); | 1577 | &drvdata->onecell); |
1558 | if (ret) { | 1578 | if (ret) { |
1559 | dev_err(&client->dev, "unable to add clk provider\n"); | 1579 | dev_err(&client->dev, "unable to add clk provider\n"); |
1560 | return ret; | 1580 | goto err_clk; |
1561 | } | 1581 | } |
1562 | 1582 | ||
1563 | return 0; | 1583 | return 0; |
1584 | |||
1585 | err_clk: | ||
1586 | if (!IS_ERR(drvdata->pxtal)) | ||
1587 | clk_disable_unprepare(drvdata->pxtal); | ||
1588 | if (!IS_ERR(drvdata->pclkin)) | ||
1589 | clk_disable_unprepare(drvdata->pclkin); | ||
1590 | return ret; | ||
1564 | } | 1591 | } |
1565 | 1592 | ||
1566 | static const struct i2c_device_id si5351_i2c_ids[] = { | 1593 | static const struct i2c_device_id si5351_i2c_ids[] = { |
diff --git a/include/linux/platform_data/si5351.h b/include/linux/platform_data/si5351.h index a947ab8b441a..533d9807e543 100644 --- a/include/linux/platform_data/si5351.h +++ b/include/linux/platform_data/si5351.h | |||
@@ -5,8 +5,6 @@ | |||
5 | #ifndef __LINUX_PLATFORM_DATA_SI5351_H__ | 5 | #ifndef __LINUX_PLATFORM_DATA_SI5351_H__ |
6 | #define __LINUX_PLATFORM_DATA_SI5351_H__ | 6 | #define __LINUX_PLATFORM_DATA_SI5351_H__ |
7 | 7 | ||
8 | struct clk; | ||
9 | |||
10 | /** | 8 | /** |
11 | * enum si5351_pll_src - Si5351 pll clock source | 9 | * enum si5351_pll_src - Si5351 pll clock source |
12 | * @SI5351_PLL_SRC_DEFAULT: default, do not change eeprom config | 10 | * @SI5351_PLL_SRC_DEFAULT: default, do not change eeprom config |
@@ -107,8 +105,6 @@ struct si5351_clkout_config { | |||
107 | * @clkout: array of clkout configuration | 105 | * @clkout: array of clkout configuration |
108 | */ | 106 | */ |
109 | struct si5351_platform_data { | 107 | struct si5351_platform_data { |
110 | struct clk *clk_xtal; | ||
111 | struct clk *clk_clkin; | ||
112 | enum si5351_pll_src pll_src[2]; | 108 | enum si5351_pll_src pll_src[2]; |
113 | struct si5351_clkout_config clkout[8]; | 109 | struct si5351_clkout_config clkout[8]; |
114 | }; | 110 | }; |