commit
965386c97616c ("ASoC: rsnd: call unregister for null_hw when
removed") tried unregister null_clk, but it has some issues.
1st issue is kernel will indicate below message when unregistering,
because of its timing. unregistering should be happen after clk_disable().
clk_unregister: unregistering prepared clock: rsnd_adg_null
2nd issue is, it is using priv->null_clk, but it should be adg->null_clk.
3rd issue is it is using very complex clk registering method.
more simple clk_register/unregister_fixed_rate() should be OK.
This patch fixes these.
Fixes:
965386c97616c ("ASoC: rsnd: call unregister for null_hw when removed")
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Link: https://lore.kernel.org/r/87r1hli215.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
struct rsnd_adg {
struct clk *clk[CLKMAX];
struct clk *clkout[CLKOUTMAX];
struct rsnd_adg {
struct clk *clk[CLKMAX];
struct clk *clkout[CLKOUTMAX];
struct clk_onecell_data onecell;
struct rsnd_mod mod;
int clk_rate[CLKMAX];
struct clk_onecell_data onecell;
struct rsnd_mod mod;
int clk_rate[CLKMAX];
void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
{
struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
{
struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
- struct device *dev = rsnd_priv_to_dev(priv);
struct clk *clk;
int i;
for_each_rsnd_clk(clk, adg, i) {
if (enable) {
struct clk *clk;
int i;
for_each_rsnd_clk(clk, adg, i) {
if (enable) {
- int ret = clk_prepare_enable(clk);
+ clk_prepare_enable(clk);
/*
* We shouldn't use clk_get_rate() under
* atomic context. Let's keep it when
* rsnd_adg_clk_enable() was called
*/
/*
* We shouldn't use clk_get_rate() under
* atomic context. Let's keep it when
* rsnd_adg_clk_enable() was called
*/
- adg->clk_rate[i] = 0;
- if (ret < 0)
- dev_warn(dev, "can't use clk %d\n", i);
- else
- adg->clk_rate[i] = clk_get_rate(clk);
+ adg->clk_rate[i] = clk_get_rate(clk);
- if (adg->clk_rate[i])
- clk_disable_unprepare(clk);
- adg->clk_rate[i] = 0;
+ clk_disable_unprepare(clk);
-#define NULL_CLK "rsnd_adg_null"
-static struct clk *rsnd_adg_null_clk_get(struct rsnd_priv *priv)
+static struct clk *rsnd_adg_create_null_clk(struct rsnd_priv *priv,
+ const char * const name,
+ const char *parent)
{
struct device *dev = rsnd_priv_to_dev(priv);
{
struct device *dev = rsnd_priv_to_dev(priv);
+ struct clk *clk;
+
+ clk = clk_register_fixed_rate(dev, name, parent, 0, 0);
+ if (IS_ERR(clk)) {
+ dev_err(dev, "create null clk error\n");
+ return NULL;
+ }
- if (!priv->null_hw) {
- struct clk_hw *_hw;
- int ret;
- _hw = clk_hw_register_fixed_rate_with_accuracy(dev, NULL_CLK, NULL, 0, 0, 0);
- if (IS_ERR(_hw))
- return NULL;
+static struct clk *rsnd_adg_null_clk_get(struct rsnd_priv *priv)
+{
+ struct rsnd_adg *adg = priv->adg;
- ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_simple_get, _hw);
- if (ret < 0)
- clk_hw_unregister_fixed_rate(_hw);
+ if (!adg->null_clk) {
+ static const char * const name = "rsnd_adg_null";
+ adg->null_clk = rsnd_adg_create_null_clk(priv, name, NULL);
- return clk_hw_get_clk(priv->null_hw, NULL_CLK);
}
static void rsnd_adg_get_clkin(struct rsnd_priv *priv)
}
static void rsnd_adg_get_clkin(struct rsnd_priv *priv)
for_each_rsnd_clkout(clk, adg, i)
if (adg->clkout[i])
clk_unregister_fixed_rate(adg->clkout[i]);
for_each_rsnd_clkout(clk, adg, i)
if (adg->clkout[i])
clk_unregister_fixed_rate(adg->clkout[i]);
- if (priv->null_hw)
- clk_hw_unregister_fixed_rate(priv->null_hw);
of_clk_del_provider(np);
rsnd_adg_clk_disable(priv);
of_clk_del_provider(np);
rsnd_adg_clk_disable(priv);
+
+ /* It should be called after rsnd_adg_clk_disable() */
+ if (adg->null_clk)
+ clk_unregister_fixed_rate(adg->null_clk);
* below value will be filled on rsnd_adg_probe()
*/
void *adg;
* below value will be filled on rsnd_adg_probe()
*/
void *adg;
- struct clk_hw *null_hw;
/*
* below value will be filled on rsnd_dma_probe()
/*
* below value will be filled on rsnd_dma_probe()