clk: Add common __clk_get(), __clk_put() implementations
authorSylwester Nawrocki <s.nawrocki@samsung.com>
Sat, 24 Aug 2013 18:10:41 +0000 (20:10 +0200)
committerSylwester Nawrocki <s.nawrocki@samsung.com>
Wed, 4 Dec 2013 16:19:44 +0000 (17:19 +0100)
This patch adds common __clk_get(), __clk_put() clkdev helpers that
replace their platform specific counterparts when the common clock
API is used.

The owner module pointer field is added to struct clk so a reference
to the clock supplier module can be taken by the clock consumers.

The owner module is assigned while the clock is being registered,
in functions _clk_register() and __clk_register().

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/include/asm/clkdev.h
arch/blackfin/include/asm/clkdev.h
arch/mips/include/asm/clkdev.h
arch/sh/include/asm/clkdev.h
drivers/clk/clk.c
include/linux/clk-private.h
include/linux/clkdev.h

index 80751c15c3005b4e5b1460d9d9380112c6ba7a1e..4e8a4b27d7c7948ed1104f247e4ba5f85e0104c7 100644 (file)
 
 #include <linux/slab.h>
 
+#ifndef CONFIG_COMMON_CLK
 #ifdef CONFIG_HAVE_MACH_CLKDEV
 #include <mach/clkdev.h>
 #else
 #define __clk_get(clk) ({ 1; })
 #define __clk_put(clk) do { } while (0)
 #endif
+#endif
 
 static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
 {
index 9053beda8c5065d0c4fe4a7c148baea406f623ba..7ac2436856a523074f301c5c3f884efc3bc0bb72 100644 (file)
@@ -8,7 +8,9 @@ static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
        return kzalloc(size, GFP_KERNEL);
 }
 
+#ifndef CONFIG_COMMON_CLK
 #define __clk_put(clk)
 #define __clk_get(clk) ({ 1; })
+#endif
 
 #endif
index 262475414e5ffd452e816c5e6156fc57243b80ef..1b3ad7b09dc1e2887f9624a9a8770041aab27b6b 100644 (file)
 
 #include <linux/slab.h>
 
+#ifndef CONFIG_COMMON_CLK
 #define __clk_get(clk) ({ 1; })
 #define __clk_put(clk) do { } while (0)
+#endif
 
 static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
 {
index 6ba91868201ce947f625a5c982c0b4ec3a290653..c41901465fb065f702083781d34b4c187473151d 100644 (file)
@@ -25,7 +25,9 @@ static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
                return kzalloc(size, GFP_KERNEL);
 }
 
+#ifndef CONFIG_COMMON_CLK
 #define __clk_put(clk)
 #define __clk_get(clk) ({ 1; })
+#endif
 
 #endif /* __CLKDEV_H__ */
index c687dc8d0b64868491a75dbb2199e1ed477b6358..baa2f66a7d19d58ffbc9966c0cb54de69fd2df33 100644 (file)
@@ -1813,6 +1813,10 @@ struct clk *__clk_register(struct device *dev, struct clk_hw *hw)
        clk->flags = hw->init->flags;
        clk->parent_names = hw->init->parent_names;
        clk->num_parents = hw->init->num_parents;
+       if (dev && dev->driver)
+               clk->owner = dev->driver->owner;
+       else
+               clk->owner = NULL;
 
        ret = __clk_init(dev, clk);
        if (ret)
@@ -1833,6 +1837,8 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk)
                goto fail_name;
        }
        clk->ops = hw->init->ops;
+       if (dev && dev->driver)
+               clk->owner = dev->driver->owner;
        clk->hw = hw;
        clk->flags = hw->init->flags;
        clk->num_parents = hw->init->num_parents;
@@ -1973,6 +1979,26 @@ void devm_clk_unregister(struct device *dev, struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(devm_clk_unregister);
 
+/*
+ * clkdev helpers
+ */
+int __clk_get(struct clk *clk)
+{
+       if (clk && !try_module_get(clk->owner))
+               return 0;
+
+       return 1;
+}
+
+void __clk_put(struct clk *clk)
+{
+       if (WARN_ON_ONCE(IS_ERR(clk)))
+               return;
+
+       if (clk)
+               module_put(clk->owner);
+}
+
 /***        clk rate change notifiers        ***/
 
 /**
index 8138c94409f3f3d1253c2b83e62c3f131ff70d84..8cb1865e7d9d2098173173254f81aed96a8991f7 100644 (file)
 
 #ifdef CONFIG_COMMON_CLK
 
+struct module;
+
 struct clk {
        const char              *name;
        const struct clk_ops    *ops;
        struct clk_hw           *hw;
+       struct module           *owner;
        struct clk              *parent;
        const char              **parent_names;
        struct clk              **parents;
index a6a6f603103be9903caf75180b71f3499a48d047..94bad77eeb4a19d4fbfeef6461a103f5b7e9dbcc 100644 (file)
@@ -43,4 +43,9 @@ int clk_add_alias(const char *, const char *, char *, struct device *);
 int clk_register_clkdev(struct clk *, const char *, const char *, ...);
 int clk_register_clkdevs(struct clk *, struct clk_lookup *, size_t);
 
+#ifdef CONFIG_COMMON_CLK
+int __clk_get(struct clk *clk);
+void __clk_put(struct clk *clk);
+#endif
+
 #endif