Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0cd3be6e authored by Sebastian Hesselbarth's avatar Sebastian Hesselbarth Committed by Michael Turquette
Browse files

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: default avatarSebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Reported-by: default avatarMichael Welling <mwelling@ieee.org>
Reported-by: default avatarJean-Francois Moine <moinejf@free.fr>
Reported-by: default avatarRussell King <rmk+linux@arm.linux.org.uk>
Tested-by: default avatarMichael Welling <mwelling@ieee.org>
Tested-by: default avatarJean-Francois Moine <moinejf@free.fr>
Signed-off-by: default avatarMichael Turquette <mturquette@linaro.org>
parent f94029d8
Loading
Loading
Loading
Loading
+45 −18
Original line number Diff line number Diff line
@@ -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[] = {
+0 −4
Original line number Diff line number Diff line
@@ -5,8 +5,6 @@
#ifndef __LINUX_PLATFORM_DATA_SI5351_H__
#define __LINUX_PLATFORM_DATA_SI5351_H__

struct clk;

/**
 * enum si5351_pll_src - Si5351 pll clock source
 * @SI5351_PLL_SRC_DEFAULT: default, do not change eeprom config
@@ -107,8 +105,6 @@ struct si5351_clkout_config {
 * @clkout: array of clkout configuration
 */
struct si5351_platform_data {
	struct clk *clk_xtal;
	struct clk *clk_clkin;
	enum si5351_pll_src pll_src[2];
	struct si5351_clkout_config clkout[8];
};