2010-12-08 02:08:30

by Jeremy Kerr

[permalink] [raw]
Subject: [PATCH 0/2] Common struct clk implementation, v8

[apologies for the resend: missed this series description]

Hi all,

These patches are an attempt to allow platforms to share clock code. At
present, the definitions of 'struct clk' are local to platform code,
which makes allocating and initialising cross-platform clock sources
difficult, and makes it impossible to compile a single image containing
support for two ARM platforms with different struct clks.

The two patches are for the architecture-independent kernel code,
introducing the common clk infrastructure. The changelog for the first
patch includes details about the new clock definitions.

As requested by rmk, I've put together a small series of patches
illustrating the usage of the common struct clock on the ARM imx51
platform. These are available in my git tree:

git://kernel.ubuntu.com/jk/dt/linux-2.6

in the clk-common-mx51 branch (clk-common..clk-common-mx51). There is
also a port for versatile (clk-common-versatile) in this tree too.

The approach I've taken with the imx51 port is to temporarly duplicate
the platform-common clock code (ie, for all mxc-based boards) to enable
usage of the common struct clk on one machine (imx51), while leaving the
others as-is. For a proper platform-wide usage of the common struct clk,
we'd be better off doing the whole platform at once. However, mx51 is
the only mxc-based HW I have, hence the duplicated example port.

In the example port, the first change simply converts the mxc's struct
clk to a struct clk_mxc, using the new API. The subsequent patches move
certain clocks to more specific data structures (eg clk_fixed and
clk_pll) where possible.

Ben Herrenschmidt is looking at using common struct clk code for powerpc
too, hence the kernel-wide approach.

Many thanks to the following for their input:
* Ben Dooks <[email protected]>
* Baruch Siach <[email protected]>
* Russell King <[email protected]>
* Uwe Kleine-König <[email protected]>
* Lorenzo Pieralisi <[email protected]>
* Vincent Guittot <[email protected]>

Russell - now that we've had a few platforms ported to the common clk
infrastructure, I believe it's ready to merge. If so, do you want this
in the patch tracker? Otherwise, let me know what needs changing.

Cheers,


Jeremy

--
v8:
* add atomic clocks, and locking wrappers
* expand comments on clk and clk_ops

v7:
* change CLK_INIT to initialise clk->mutex statically

v6:
* fixed up references to 'clk_operations' in the changelog

v5:
* uninline main API, and share definitions with !USE_COMMON_STRUCT_CLK
* add __clk_get
* delay mutex init
* kerneldoc for struct clk

v4:
* use mutex for enable/disable locking
* DEFINE_CLK -> INIT_CLK, and pass the clk name for mutex init
* struct clk_operations -> struct clk_ops

v3:
* do clock usage refcounting in common code
* provide sample port

v2:
* no longer ARM-specific
* use clk_operations

---
Jeremy Kerr (2):
Add a common struct clk
clk: Generic support for fixed-rate clocks


2010-12-08 02:08:29

by Jeremy Kerr

[permalink] [raw]
Subject: [PATCH 2/2] clk: Generic support for fixed-rate clocks

Since most platforms will need a fixed-rate clock, add one. This will
also serve as a basic example of an implementation of struct clk.

Signed-off-by: Jeremy Kerr <[email protected]>

---
include/linux/clk.h | 13 +++++++++++++
kernel/clk.c | 14 ++++++++++++++
2 files changed, 27 insertions(+)

diff --git a/include/linux/clk.h b/include/linux/clk.h
index e09e40e..ae7e4ed 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -158,6 +158,19 @@ static inline void clk_common_init(struct clk *clk)
mutex_init(&clk->lock.mutex);
}

+/* Simple fixed-rate clock */
+struct clk_fixed {
+ struct clk clk;
+ unsigned long rate;
+};
+
+extern struct clk_ops clk_fixed_ops;
+
+#define INIT_CLK_FIXED(name, r) { \
+ .clk = INIT_CLK(name.clk, clk_fixed_ops), \
+ .rate = (r) \
+}
+
#else /* !CONFIG_USE_COMMON_STRUCT_CLK */

/*
diff --git a/kernel/clk.c b/kernel/clk.c
index 1545e69..2779abb 100644
--- a/kernel/clk.c
+++ b/kernel/clk.c
@@ -98,3 +98,17 @@ struct clk *clk_get_parent(struct clk *clk)
return ERR_PTR(-ENOSYS);
}
EXPORT_SYMBOL_GPL(clk_get_parent);
+
+/* clk_fixed support */
+
+#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
+
+static unsigned long clk_fixed_get_rate(struct clk *clk)
+{
+ return to_clk_fixed(clk)->rate;
+}
+
+struct clk_ops clk_fixed_ops = {
+ .get_rate = clk_fixed_get_rate,
+};
+EXPORT_SYMBOL_GPL(clk_fixed_ops);

2010-12-08 02:08:28

by Jeremy Kerr

[permalink] [raw]
Subject: [PATCH 1/2] Add a common struct clk

We currently have ~21 definitions of struct clk in the ARM architecture,
each defined on a per-platform basis. This makes it difficult to define
platform- (or architecture-) independent clock sources without making
assumptions about struct clk, and impossible to compile two
platforms with different struct clks into a single image.

This change is an effort to unify struct clk where possible, by defining
a common struct clk, containing a set of clock operations. Different
clock implementations can set their own operations, and have a standard
interface for generic code. The callback interface is exposed to the
kernel proper, while the clock implementations only need to be seen by
the platform internals.

This allows us to share clock code among platforms, and makes it
possible to dynamically create clock devices in platform-independent
code.

Platforms can enable the generic struct clock through
CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
consists of a common struct clk:

struct clk {
const struct clk_ops *ops;
unsigned int enable_count;
int flags;
union {
struct mutex mutex;
spinlock_t spinlock;
} lock;
};

And a set of clock operations (defined per type of clock):

struct clk_ops {
int (*enable)(struct clk *);
void (*disable)(struct clk *);
unsigned long (*get_rate)(struct clk *);
[...]
};

To define a hardware-specific clock, machine code can "subclass" the
struct clock into a new struct (adding any device-specific data), and
provide a set of operations:

struct clk_foo {
struct clk clk;
void __iomem *some_register;
};

struct clk_ops clk_foo_ops = {
.get_rate = clk_foo_get_rate,
};

The common clock definitions are based on a development patch from Ben
Herrenschmidt <[email protected]>.

Signed-off-by: Jeremy Kerr <[email protected]>
Acked-by: Paulius Zaleckas <[email protected]>

---
arch/Kconfig | 3
include/linux/clk.h | 158 +++++++++++++++++++++++++++++++++++++++++---
kernel/Makefile | 1
kernel/clk.c | 100 +++++++++++++++++++++++++++
4 files changed, 253 insertions(+), 9 deletions(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 8bf0fa6..212bd3c 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -165,6 +165,9 @@ config HAVE_MIXED_BREAKPOINTS_REGS
config HAVE_USER_RETURN_NOTIFIER
bool

+config USE_COMMON_STRUCT_CLK
+ bool
+
config HAVE_PERF_EVENTS_NMI
bool
help
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 1d37f42..e09e40e 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -3,6 +3,7 @@
*
* Copyright (C) 2004 ARM Limited.
* Written by Deep Blue Solutions Limited.
+ * Copyright (c) 2010 Jeremy Kerr <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -11,18 +12,163 @@
#ifndef __LINUX_CLK_H
#define __LINUX_CLK_H

+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
struct device;

-/*
- * The base API.
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+
+#define CLK_ATOMIC 0x1
+
+/* If we're using the common struct clk, we define the base clk object here */
+
+/**
+ * struct clk - hardware independent clock structure
+ * @clk_ops: implementation-specific ops for this clock
+ * @enable_count: count of clk_enable() calls active on this clock
+ * @flags: platform-independent flags
+ * @lock: lock for enable/disable or other HW-specific ops
+ *
+ * The base clock object, used by drivers for hardware-independent manipulation
+ * of clock lines. This will be 'subclassed' by device-specific implementations,
+ * which add device-specific data to struct clk. For example:
+ *
+ * struct clk_foo {
+ * struct clk;
+ * [device specific fields]
+ * };
+ *
+ * The clock driver code will manage the device-specific data, and pass
+ * clk_foo.clk to the common clock code. The clock driver will be called
+ * through the @ops callbacks.
+ *
+ * The @lock member provides either a spinlock or a mutex to protect (at least)
+ * @enable_count. The type of lock used will depend on @flags; if CLK_ATOMIC is
+ * set, then the core clock code will use a spinlock, otherwise a mutex. This
+ * lock will be acquired during clk_enable and clk_disable, so for atomic
+ * clocks, these ops callbacks must not sleep.
+ *
+ * The choice of atomic or non-atomic clock depends on how the clock is enabled.
+ * Typically, you'll want to use a non-atomic clock. For clocks that need to be
+ * enabled/disabled in interrupt context, use CLK_ATOMIC. Note that atomic
+ * clocks with parents will typically cascade enable/disable operations to
+ * their parent, so the parent of an atomic clock *must* be atomic too.
+ */
+struct clk {
+ const struct clk_ops *ops;
+ unsigned int enable_count;
+ int flags;
+ union {
+ struct mutex mutex;
+ spinlock_t spinlock;
+ } lock;
+};
+
+/* static initialiser for non-atomic clocks */
+#define INIT_CLK(name, o) { \
+ .ops = &o, \
+ .enable_count = 0, \
+ .flags = 0, \
+ .lock.mutex = __MUTEX_INITIALIZER(name.lock.mutex), \
+}
+
+/* static initialiser for atomic clocks */
+#define INIT_CLK_ATOMIC(name, o) { \
+ .ops = &o, \
+ .enable_count = 0, \
+ .flags = CLK_ATOMIC, \
+ .lock.spinlock = __SPIN_LOCK_UNLOCKED(name.lock.spinlock), \
+}
+
+/**
+ * clk_ops: Callback operations for clocks; these are to be provided by the
+ * clock implementation, and will be called by drivers through the clk_* API.
+ *
+ * @enable: Enable the clock. This must not return until the clock is
+ * generating a valid clock signal, usable by consumer devices.
+ * Called with clk->lock held.
+ *
+ * @disable: Disable the clock. Called with clk->lock held.
+ *
+ * @get / @put: Called by the core clock code to notify the driver about
+ * refounts as clk is passed to drivers. Optional.
+ *
+ * For other callbacks, see the corresponding clk_* functions. Parameters and
+ * return values are passed directly from/to these API functions directly, or
+ * -ENOSYS is returned if the callback is NULL, see kernel/clk.c for
+ * implementation details. All are optional.
*/
+struct clk_ops {
+ int (*enable)(struct clk *);
+ void (*disable)(struct clk *);
+ int (*get)(struct clk *);
+ void (*put)(struct clk *);
+ unsigned long (*get_rate)(struct clk *);
+ long (*round_rate)(struct clk *, unsigned long);
+ int (*set_rate)(struct clk *, unsigned long);
+ int (*set_parent)(struct clk *, struct clk *);
+ struct clk * (*get_parent)(struct clk *);
+};

+static inline void __clk_lock(struct clk *clk)
+{
+ if (clk->flags & CLK_ATOMIC)
+ spin_lock(&clk->lock.spinlock);
+ else
+ mutex_lock(&clk->lock.mutex);
+}
+
+static inline void __clk_unlock(struct clk *clk)
+{
+ if (clk->flags & CLK_ATOMIC)
+ spin_unlock(&clk->lock.spinlock);
+ else
+ mutex_unlock(&clk->lock.mutex);
+}
+
+/**
+ * __clk_get - update clock-specific refcounter
+ *
+ * @clk: The clock to refcount
+ *
+ * Before a clock is returned from clk_get, this function should be called
+ * to update any clock-specific refcounting.
+ *
+ * Returns non-zero on success, zero on failure.
+ *
+ * Drivers should not need this function; it is only needed by the
+ * arch-specific clk_get() implementations.
+ */
+int __clk_get(struct clk *clk);
+
+/**
+ * clk_common_init - initialise a clock for driver usage
+ *
+ * Used for runtime intialization of clocks; you don't need to call this
+ * if your clock has been (statically) initialized with INIT_CLK.
+ */
+static inline void clk_common_init(struct clk *clk)
+{
+ clk->enable_count = 0;
+ if (clk->flags & CLK_ATOMIC)
+ spin_lock_init(&clk->lock.spinlock);
+ else
+ mutex_init(&clk->lock.mutex);
+}
+
+#else /* !CONFIG_USE_COMMON_STRUCT_CLK */

/*
- * struct clk - an machine class defined object / cookie.
+ * Global clock object, actual structure is declared per-machine
*/
struct clk;

+static inline void clk_common_init(struct clk *clk) { }
+
+#endif /* !CONFIG_USE_COMMON_STRUCT_CLK */
+
/**
* clk_get - lookup and obtain a reference to a clock producer.
* @dev: device for clock "consumer"
@@ -83,12 +229,6 @@ unsigned long clk_get_rate(struct clk *clk);
*/
void clk_put(struct clk *clk);

-
-/*
- * The remaining APIs are optional for machine class support.
- */
-
-
/**
* clk_round_rate - adjust a rate to the exact rate a clock can provide
* @clk: clock source
diff --git a/kernel/Makefile b/kernel/Makefile
index 0b5ff08..01383a0 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -106,6 +106,7 @@ obj-$(CONFIG_PERF_EVENTS) += perf_event.o
obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
obj-$(CONFIG_USER_RETURN_NOTIFIER) += user-return-notifier.o
obj-$(CONFIG_PADATA) += padata.o
+obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o

ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y)
# According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
diff --git a/kernel/clk.c b/kernel/clk.c
new file mode 100644
index 0000000..1545e69
--- /dev/null
+++ b/kernel/clk.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2010 Canonical Ltd <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Standard functionality for the common clock API.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+
+int clk_enable(struct clk *clk)
+{
+ int ret = 0;
+
+ if (!clk->ops->enable)
+ return 0;
+
+ __clk_lock(clk);
+ if (!clk->enable_count)
+ ret = clk->ops->enable(clk);
+
+ if (!ret)
+ clk->enable_count++;
+ __clk_unlock(clk);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+ if (!clk->ops->disable)
+ return;
+
+ __clk_lock(clk);
+
+ if (!--clk->enable_count)
+ clk->ops->disable(clk);
+
+ __clk_unlock(clk);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ if (clk->ops->get_rate)
+ return clk->ops->get_rate(clk);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+int __clk_get(struct clk *clk)
+{
+ if (clk->ops->get)
+ return clk->ops->get(clk);
+ return 1;
+}
+EXPORT_SYMBOL_GPL(__clk_get);
+
+void clk_put(struct clk *clk)
+{
+ if (clk->ops->put)
+ clk->ops->put(clk);
+}
+EXPORT_SYMBOL_GPL(clk_put);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ if (clk->ops->round_rate)
+ return clk->ops->round_rate(clk, rate);
+ return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ if (clk->ops->set_rate)
+ return clk->ops->set_rate(clk, rate);
+ return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ if (clk->ops->set_parent)
+ return clk->ops->set_parent(clk, parent);
+ return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+ if (clk->ops->get_parent)
+ return clk->ops->get_parent(clk);
+ return ERR_PTR(-ENOSYS);
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);

2010-12-08 10:33:58

by Uwe Kleine-König

[permalink] [raw]
Subject: Re: [PATCH 0/2] Common struct clk implementation, v8

Hello Jeremy,

On Wed, Dec 08, 2010 at 10:08:14AM +0800, Jeremy Kerr wrote:
> [apologies for the resend: missed this series description]
>
> Hi all,
>
> These patches are an attempt to allow platforms to share clock code. At
> present, the definitions of 'struct clk' are local to platform code,
> which makes allocating and initialising cross-platform clock sources
> difficult, and makes it impossible to compile a single image containing
> support for two ARM platforms with different struct clks.
>
> The two patches are for the architecture-independent kernel code,
> introducing the common clk infrastructure. The changelog for the first
> patch includes details about the new clock definitions.
>
> As requested by rmk, I've put together a small series of patches
> illustrating the usage of the common struct clock on the ARM imx51
> platform. These are available in my git tree:
>
> git://kernel.ubuntu.com/jk/dt/linux-2.6
>
> in the clk-common-mx51 branch (clk-common..clk-common-mx51). There is
I would have expected that clk-common is an ancestor of clk-common-mx51.
Currently it bases on v7(?) that doesn't have the spinlock.

BTW, I took a quick look over the patches in clk-common-mx51 and I think
arch/arm/plat-mxc/include/mach/clock.h doesn't compile without
CONFIG_USE_COMMON_STRUCT_CLK (because then there is no struct clk_mxc),
so either you need more magic or just remove the #ifndef
CONFIG_USE_COMMON_STRUCT_CLK.

> also a port for versatile (clk-common-versatile) in this tree too.
>
> The approach I've taken with the imx51 port is to temporarly duplicate
> the platform-common clock code (ie, for all mxc-based boards) to enable
> usage of the common struct clk on one machine (imx51), while leaving the
> others as-is. For a proper platform-wide usage of the common struct clk,
> we'd be better off doing the whole platform at once. However, mx51 is
> the only mxc-based HW I have, hence the duplicated example port.
>
> In the example port, the first change simply converts the mxc's struct
> clk to a struct clk_mxc, using the new API. The subsequent patches move
> certain clocks to more specific data structures (eg clk_fixed and
> clk_pll) where possible.
>
> Ben Herrenschmidt is looking at using common struct clk code for powerpc
> too, hence the kernel-wide approach.
>
> Many thanks to the following for their input:
> * Ben Dooks <[email protected]>
> * Baruch Siach <[email protected]>
> * Russell King <[email protected]>
> * Uwe Kleine-K?nig <[email protected]>
> * Lorenzo Pieralisi <[email protected]>
> * Vincent Guittot <[email protected]>
>
> Russell - now that we've had a few platforms ported to the common clk
> infrastructure, I believe it's ready to merge. If so, do you want this
> in the patch tracker? Otherwise, let me know what needs changing.
>
> Cheers,

Thanks
Uwe

--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |

2010-12-08 10:51:37

by Jeremy Kerr

[permalink] [raw]
Subject: Re: [PATCH 0/2] Common struct clk implementation, v8

Hi Uwe,

> I would have expected that clk-common is an ancestor of clk-common-mx51.
> Currently it bases on v7(?) that doesn't have the spinlock.
>
> BTW, I took a quick look over the patches in clk-common-mx51 and I think
> arch/arm/plat-mxc/include/mach/clock.h doesn't compile without
> CONFIG_USE_COMMON_STRUCT_CLK (because then there is no struct clk_mxc),
> so either you need more magic or just remove the #ifndef
> CONFIG_USE_COMMON_STRUCT_CLK.

Ah, I haven't pushed updates to the clk-common-mx51 branch yet, I'll get to
this soon.

Cheers,


Jeremy

2010-12-13 12:14:32

by Sascha Hauer

[permalink] [raw]
Subject: Re: [PATCH 2/2] clk: Generic support for fixed-rate clocks

Hi Jeremy,

On Wed, Dec 08, 2010 at 10:08:14AM +0800, Jeremy Kerr wrote:
> Since most platforms will need a fixed-rate clock, add one. This will
> also serve as a basic example of an implementation of struct clk.
>
> Signed-off-by: Jeremy Kerr <[email protected]>
>
> ---
> include/linux/clk.h | 13 +++++++++++++
> kernel/clk.c | 14 ++++++++++++++
> 2 files changed, 27 insertions(+)
>
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index e09e40e..ae7e4ed 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -158,6 +158,19 @@ static inline void clk_common_init(struct clk *clk)
> mutex_init(&clk->lock.mutex);
> }
>
> +/* Simple fixed-rate clock */
> +struct clk_fixed {
> + struct clk clk;
> + unsigned long rate;
> +};
> +
> +extern struct clk_ops clk_fixed_ops;
> +
> +#define INIT_CLK_FIXED(name, r) { \
> + .clk = INIT_CLK(name.clk, clk_fixed_ops), \
> + .rate = (r) \
> +}

Is there any other valid usecase for this other than

struct clk_fixed bla = INIT_CLK_FIXED(bla, rate);

Otherwise I suggest to convert the macro to:

#define INIT_CLK_FIXED(name, r) \
struct clk_fixed name = { \
.clk = INIT_CLK(name.clk, clk_fixed_ops), \
.rate = (r) \
}

This way we do not have to specify the same name twice (and it has
to be exactly the same name, otherwise it won't compile).

Sascha

--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |

2010-12-13 12:35:57

by Jeremy Kerr

[permalink] [raw]
Subject: Re: [PATCH 2/2] clk: Generic support for fixed-rate clocks

Hi Sascha,

> > +extern struct clk_ops clk_fixed_ops;
> > +
> > +#define INIT_CLK_FIXED(name, r) { \
> > + .clk = INIT_CLK(name.clk, clk_fixed_ops), \
> > + .rate = (r) \
> > +}
>
> Is there any other valid usecase for this other than
>
> struct clk_fixed bla = INIT_CLK_FIXED(bla, rate);
>
> Otherwise I suggest to convert the macro to:
>
> #define INIT_CLK_FIXED(name, r) \
> struct clk_fixed name = { \
> .clk = INIT_CLK(name.clk, clk_fixed_ops), \
> .rate = (r) \
> }
>
> This way we do not have to specify the same name twice (and it has
> to be exactly the same name, otherwise it won't compile).

For the system-wide INIT_CLK* macros, I've intentionally made them initalisers
rather than declarators, so that we can use them in other declarators (ie, the
usage of INIT_CLK() above). This would be relevant if someone is using
clk_fixed in their struct - probably not likely, but good to be consistent.

But yes, it would be good to avoid having to specify the name twice - how
about adding a:

#define DEFINE_CLK_FIXED(name, r) \
struct clk_fixed name = INIT_CLK_FIXED(name, r)

- just like DEFINE_MUTEX and MUTEX_INITIALIZER.

Cheers,


Jeremy

2010-12-13 12:42:56

by Sascha Hauer

[permalink] [raw]
Subject: Re: [PATCH 2/2] clk: Generic support for fixed-rate clocks

On Mon, Dec 13, 2010 at 08:35:37PM +0800, Jeremy Kerr wrote:
> Hi Sascha,
>
> > > +extern struct clk_ops clk_fixed_ops;
> > > +
> > > +#define INIT_CLK_FIXED(name, r) { \
> > > + .clk = INIT_CLK(name.clk, clk_fixed_ops), \
> > > + .rate = (r) \
> > > +}
> >
> > Is there any other valid usecase for this other than
> >
> > struct clk_fixed bla = INIT_CLK_FIXED(bla, rate);
> >
> > Otherwise I suggest to convert the macro to:
> >
> > #define INIT_CLK_FIXED(name, r) \
> > struct clk_fixed name = { \
> > .clk = INIT_CLK(name.clk, clk_fixed_ops), \
> > .rate = (r) \
> > }
> >
> > This way we do not have to specify the same name twice (and it has
> > to be exactly the same name, otherwise it won't compile).
>
> For the system-wide INIT_CLK* macros, I've intentionally made them initalisers
> rather than declarators, so that we can use them in other declarators (ie, the
> usage of INIT_CLK() above). This would be relevant if someone is using
> clk_fixed in their struct - probably not likely, but good to be consistent.
>
> But yes, it would be good to avoid having to specify the name twice - how
> about adding a:
>
> #define DEFINE_CLK_FIXED(name, r) \
> struct clk_fixed name = INIT_CLK_FIXED(name, r)
>
> - just like DEFINE_MUTEX and MUTEX_INITIALIZER.

Jup, sounds good.

Sascha

--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |