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 | }; |
