|
@@ -1128,13 +1128,6 @@ static int si5351_dt_parse(struct i2c_client *client,
|
|
|
if (!pdata)
|
|
|
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>, [<..>]
|
|
|
* allow to selectively set pll source
|
|
@@ -1328,8 +1321,22 @@ static int si5351_i2c_probe(struct i2c_client *client,
|
|
|
i2c_set_clientdata(client, drvdata);
|
|
|
drvdata->client = client;
|
|
|
drvdata->variant = variant;
|
|
|
- drvdata->pxtal = pdata->clk_xtal;
|
|
|
- drvdata->pclkin = pdata->clk_clkin;
|
|
|
+ drvdata->pxtal = devm_clk_get(&client->dev, "xtal");
|
|
|
+ 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);
|
|
|
if (IS_ERR(drvdata->regmap)) {
|
|
@@ -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 */
|
|
|
memset(&init, 0, sizeof(init));
|
|
|
init.name = si5351_input_names[0];
|
|
@@ -1407,7 +1419,8 @@ static int si5351_i2c_probe(struct i2c_client *client,
|
|
|
clk = devm_clk_register(&client->dev, &drvdata->xtal);
|
|
|
if (IS_ERR(clk)) {
|
|
|
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 */
|
|
@@ -1425,7 +1438,8 @@ static int si5351_i2c_probe(struct i2c_client *client,
|
|
|
if (IS_ERR(clk)) {
|
|
|
dev_err(&client->dev, "unable to register %s\n",
|
|
|
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,
|
|
|
clk = devm_clk_register(&client->dev, &drvdata->pll[0].hw);
|
|
|
if (IS_ERR(clk)) {
|
|
|
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) */
|
|
@@ -1471,7 +1486,8 @@ static int si5351_i2c_probe(struct i2c_client *client,
|
|
|
clk = devm_clk_register(&client->dev, &drvdata->pll[1].hw);
|
|
|
if (IS_ERR(clk)) {
|
|
|
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 */
|
|
@@ -1492,8 +1508,10 @@ static int si5351_i2c_probe(struct i2c_client *client,
|
|
|
num_clocks * sizeof(*drvdata->onecell.clks), GFP_KERNEL);
|
|
|
|
|
|
if (WARN_ON(!drvdata->msynth || !drvdata->clkout ||
|
|
|
- !drvdata->onecell.clks))
|
|
|
- return -ENOMEM;
|
|
|
+ !drvdata->onecell.clks)) {
|
|
|
+ ret = -ENOMEM;
|
|
|
+ goto err_clk;
|
|
|
+ }
|
|
|
|
|
|
for (n = 0; n < num_clocks; n++) {
|
|
|
drvdata->msynth[n].num = n;
|
|
@@ -1511,7 +1529,8 @@ static int si5351_i2c_probe(struct i2c_client *client,
|
|
|
if (IS_ERR(clk)) {
|
|
|
dev_err(&client->dev, "unable to register %s\n",
|
|
|
init.name);
|
|
|
- return -EINVAL;
|
|
|
+ ret = PTR_ERR(clk);
|
|
|
+ goto err_clk;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1538,7 +1557,8 @@ static int si5351_i2c_probe(struct i2c_client *client,
|
|
|
if (IS_ERR(clk)) {
|
|
|
dev_err(&client->dev, "unable to register %s\n",
|
|
|
init.name);
|
|
|
- return -EINVAL;
|
|
|
+ ret = PTR_ERR(clk);
|
|
|
+ goto err_clk;
|
|
|
}
|
|
|
drvdata->onecell.clks[n] = clk;
|
|
|
|
|
@@ -1557,10 +1577,17 @@ static int si5351_i2c_probe(struct i2c_client *client,
|
|
|
&drvdata->onecell);
|
|
|
if (ret) {
|
|
|
dev_err(&client->dev, "unable to add clk provider\n");
|
|
|
- return ret;
|
|
|
+ goto err_clk;
|
|
|
}
|
|
|
|
|
|
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[] = {
|