@@ -543,7 +543,8 @@ static int clk_disable_unused(void)
}
late_initcall_sync(clk_disable_unused);
-struct clk *__clk_create_clk(struct clk_core *clk_core)
+struct clk *__clk_create_clk(struct clk_core *clk_core, const char *dev,
+ const char *con)
{
struct clk *clk;
@@ -556,6 +557,8 @@ struct clk *__clk_create_clk(struct clk_core *clk_core)
return ERR_PTR(-ENOMEM);
clk->core = clk_core;
+ clk->dev_id = dev;
+ clk->con_id = con;
return clk;
}
@@ -936,10 +939,25 @@ EXPORT_SYMBOL_GPL(clk_provider_disable);
*/
void clk_disable(struct clk *clk_user)
{
+ struct clk_core *clk;
+ unsigned long flags;
+
if (IS_ERR_OR_NULL(clk_user))
return;
- clk_provider_disable(clk_to_clk_core(clk_user));
+ clk = clk_to_clk_core(clk_user);
+
+ flags = clk_enable_lock();
+ if (!WARN(clk_user->enable_count == 0,
+ "incorrect disable clk dev %s con %s last disabler %pF\n",
+ clk_user->dev_id, clk_user->con_id, clk_user->last_disable)) {
+
+ clk_user->last_disable = __builtin_return_address(0);
+ clk_user->enable_count--;
+
+ __clk_disable(clk);
+ }
+ clk_enable_unlock(flags);
}
EXPORT_SYMBOL_GPL(clk_disable);
@@ -1000,10 +1018,22 @@ EXPORT_SYMBOL_GPL(clk_provider_enable);
*/
int clk_enable(struct clk *clk_user)
{
+ struct clk_core *clk;
+ unsigned long flags;
+ int ret;
+
if (!clk_user)
return 0;
- return clk_provider_enable(clk_to_clk_core(clk_user));
+ clk = clk_to_clk_core(clk_user);
+
+ flags = clk_enable_lock();
+ ret = __clk_enable(clk);
+ if (!ret)
+ clk_user->enable_count++;
+ clk_enable_unlock(flags);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(clk_enable);
@@ -1698,7 +1728,7 @@ struct clk *clk_get_parent(struct clk *clk_user)
clk = clk_to_clk_core(clk_user);
parent = clk_provider_get_parent(clk);
- return __clk_create_clk(parent);
+ return __clk_create_clk(parent, clk_user->dev_id, clk_user->con_id);
}
EXPORT_SYMBOL_GPL(clk_get_parent);
@@ -19,5 +19,6 @@ void of_clk_unlock(void);
#endif
#if defined(CONFIG_COMMON_CLK)
-struct clk *__clk_create_clk(struct clk_core *clk_core);
+struct clk *__clk_create_clk(struct clk_core *clk_core, const char *dev,
+ const char *con);
#endif
@@ -77,7 +77,9 @@ EXPORT_SYMBOL(of_clk_provider_get);
struct clk *of_clk_get(struct device_node *np, int index)
{
- return __clk_create_clk(of_clk_provider_get(np, index));
+ struct clk_core *clk = of_clk_provider_get(np, index);
+
+ return __clk_create_clk(clk, np->full_name, NULL);
}
EXPORT_SYMBOL(of_clk_get);
@@ -130,7 +132,9 @@ struct clk_core *of_clk_provider_get_by_name(struct device_node *np, const char
*/
struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
{
- return __clk_create_clk(of_clk_provider_get_by_name(np, name));
+ struct clk_core *clk = of_clk_provider_get_by_name(np, name);
+
+ return __clk_create_clk(clk, np->full_name, NULL);
}
EXPORT_SYMBOL(of_clk_get_by_name);
#endif
@@ -202,7 +206,7 @@ struct clk *clk_get_sys(const char *dev_id, const char *con_id)
#if defined(CONFIG_COMMON_CLK)
struct clk_core *clk = clk_provider_get_sys(dev_id, con_id);
- return __clk_create_clk(clk);
+ return __clk_create_clk(clk, dev_id, con_id);
#else
struct clk_lookup *cl;
@@ -242,7 +246,9 @@ EXPORT_SYMBOL(clk_provider_get);
struct clk *clk_get(struct device *dev, const char *con_id)
{
#if defined(CONFIG_COMMON_CLK)
- return __clk_create_clk(clk_provider_get(dev, con_id));
+ const char *dev_id = dev ? dev_name(dev) : NULL;
+
+ return __clk_create_clk(clk_provider_get(dev, con_id), dev_id, con_id);
#else
const char *dev_id = dev ? dev_name(dev) : NULL;
struct clk *clk;
@@ -57,6 +57,11 @@ struct clk_core {
struct clk {
struct clk_core *core;
+ const char *dev_id;
+ const char *con_id;
+
+ unsigned int enable_count;
+ void *last_disable;
};
/*