From: Felipe Balbi <felipe.balbi@xxxxxxxxx> Introduce a new mechanism to omap's clk implementation to associate consumer device(s) with its clock during platform_device registration. With this mechanism we can also be sure drivers won't be able to clk_get the wrong clk (only true when we move all drivers to this new mechanism and drop the old ones). Signed-off-by: Felipe Balbi <felipe.balbi@xxxxxxxxx> --- arch/arm/plat-omap/clock.c | 47 ++++++++++++++++++++++++++++-- arch/arm/plat-omap/include/mach/clock.h | 4 ++ 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 5178701..083a3ff 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -44,6 +44,7 @@ static struct clk_functions *arch_clock; struct clk * clk_get(struct device *dev, const char *id) { struct clk *p, *clk = ERR_PTR(-ENOENT); + struct device *d; int idno; if (dev == NULL || dev->bus != &platform_bus_type) @@ -54,27 +55,65 @@ struct clk * clk_get(struct device *dev, const char *id) mutex_lock(&clocks_mutex); list_for_each_entry(p, &clocks, node) { + list_for_each_entry(d, &p->consumers, node) { + if (dev == d) { + clk = p; + break; + } + } + if (p->id == idno && strcmp(id, p->name) == 0 && try_module_get(p->owner)) { clk = p; - goto found; + break; } - } - list_for_each_entry(p, &clocks, node) { if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { clk = p; break; } } -found: mutex_unlock(&clocks_mutex); return clk; } EXPORT_SYMBOL(clk_get); +/** + * omap_clk_associate - associates a clock to its consumer device(s) + * @id: clock id as defined in arch/arm/mach-omapX/clkxxxx.h + * @dev: device pointer for the clock consumer + * + * This function attempts to simplify clock handling for device drivers + * by letting struct clk know which device is the correct consumer for + * that clock. By making this trick, we let drivers get the correct + * clock without knowing about different clock names between omap + * versions. + */ +void __init omap_clk_associate(const char *id, struct device *dev) +{ + struct clk *clk = clk_get(NULL, id); + + if (!clk || IS_ERR(clk)) { + pr_debug("%s: unable to get clock\n", __func__); + return; + } + + if (!dev) { + pr_debug("%s: missing device to associate with\n", __func__); + clk_put(clk); + return; + } + + if (list_empty(&clk->consumers)) + INIT_LIST_HEAD(&clk->consumers); + + /* add device to consumer list */ + list_add(&dev->node, &clk->consumers); + clk_put(clk); +}; + int clk_enable(struct clk *clk) { unsigned long flags; diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index 9088925..1600a14 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -13,6 +13,8 @@ #ifndef __ARCH_ARM_OMAP_CLOCK_H #define __ARCH_ARM_OMAP_CLOCK_H +#include <linux/device.h> + struct module; struct clk; struct clockdomain; @@ -61,6 +63,7 @@ struct dpll_data { struct clk { struct list_head node; + struct list_head consumers; struct module *owner; const char *name; int id; @@ -116,6 +119,7 @@ struct clk_functions { extern unsigned int mpurate; +extern void omap_clk_associate(const char *id, struct device *dev); extern int clk_init(struct clk_functions *custom_clocks); extern int clk_register(struct clk *clk); extern void clk_unregister(struct clk *clk); -- 1.6.0.2.307.gc427 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html