* [PATCH 0/3] clock (clk.h) framework for mpc52xx @ 2007-07-11 9:31 Domen Puncer 2007-07-11 9:32 ` [PATCH 1/3] powerpc clk.h interface for platforms Domen Puncer ` (2 more replies) 0 siblings, 3 replies; 20+ messages in thread From: Domen Puncer @ 2007-07-11 9:31 UTC (permalink / raw) To: linuxppc-dev; +Cc: David Brownell, Sylvain Munaut Hi! Clock managing in mpc52xx psc spi driver grew a bit, to do it "the right way" ;-) 1/3 - Generic powerpc clock interface, platforms that implement it should fill clk_functions. This is needed because powerpc supports multiple platforms in same kernel image. 2/3 - psc spi clocks (mclk) for mpc52xx 3/3 - Use the spi clocks in mpc52xx psc spi driver. Thanks to David Brownell and Sylvain Munaut for feedback and help on patches. Domen ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 1/3] powerpc clk.h interface for platforms 2007-07-11 9:31 [PATCH 0/3] clock (clk.h) framework for mpc52xx Domen Puncer @ 2007-07-11 9:32 ` Domen Puncer 2007-07-11 10:36 ` Christoph Hellwig 2007-08-06 6:58 ` [PATCH 1/3] powerpc clk.h interface for platforms Domen Puncer 2007-07-11 9:33 ` [PATCH 2/3] mpc52xx clk.h interface Domen Puncer 2007-07-11 9:34 ` [PATCH 3/3] mpc52xx_psc_spi: use clk.h subsystem Domen Puncer 2 siblings, 2 replies; 20+ messages in thread From: Domen Puncer @ 2007-07-11 9:32 UTC (permalink / raw) To: linuxppc-dev; +Cc: David Brownell, Sylvain Munaut clk interface for arch/powerpc, platforms should fill clk_functions. Signed-off-by: Domen Puncer <domen.puncer@telargo.com> --- arch/powerpc/kernel/Makefile | 3 - arch/powerpc/kernel/clock.c | 82 ++++++++++++++++++++++++++++++++++++ include/asm-powerpc/clk_interface.h | 20 ++++++++ 3 files changed, 104 insertions(+), 1 deletion(-) Index: work-powerpc.git/arch/powerpc/kernel/clock.c =================================================================== --- /dev/null +++ work-powerpc.git/arch/powerpc/kernel/clock.c @@ -0,0 +1,82 @@ +/* + * Dummy clk implementations for powerpc. + * These need to be overridden in platform code. + */ + +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/errno.h> +#include <linux/module.h> +#include <asm/clk_interface.h> + +struct clk_interface clk_functions; + +struct clk *clk_get(struct device *dev, const char *id) +{ + if (clk_functions.clk_get) + return clk_functions.clk_get(dev, id); + return ERR_PTR(-ENOSYS); +} +EXPORT_SYMBOL(clk_get); + +void clk_put(struct clk *clk) +{ + if (clk_functions.clk_put) + clk_functions.clk_put(clk); +} +EXPORT_SYMBOL(clk_put); + +int clk_enable(struct clk *clk) +{ + if (clk_functions.clk_enable) + return clk_functions.clk_enable(clk); + return -ENOSYS; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ + if (clk_functions.clk_disable) + clk_functions.clk_disable(clk); +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + if (clk_functions.clk_get_rate) + return clk_functions.clk_get_rate(clk); + return 0; +} +EXPORT_SYMBOL(clk_get_rate); + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + if (clk_functions.clk_round_rate) + return clk_functions.clk_round_rate(clk, rate); + return -ENOSYS; +} +EXPORT_SYMBOL(clk_round_rate); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + if (clk_functions.clk_set_rate) + return clk_functions.clk_set_rate(clk, rate); + return -ENOSYS; +} +EXPORT_SYMBOL(clk_set_rate); + +struct clk *clk_get_parent(struct clk *clk) +{ + if (clk_functions.clk_get_parent) + return clk_functions.clk_get_parent(clk); + return ERR_PTR(-ENOSYS); +} +EXPORT_SYMBOL(clk_get_parent); + +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + if (clk_functions.clk_set_parent) + return clk_functions.clk_set_parent(clk, parent); + return -ENOSYS; +} +EXPORT_SYMBOL(clk_set_parent); Index: work-powerpc.git/include/asm-powerpc/clk_interface.h =================================================================== --- /dev/null +++ work-powerpc.git/include/asm-powerpc/clk_interface.h @@ -0,0 +1,20 @@ +#ifndef __ASM_POWERPC_CLK_INTERFACE_H +#define __ASM_POWERPC_CLK_INTERFACE_H + +#include <linux/clk.h> + +struct clk_interface { + struct clk* (*clk_get) (struct device *dev, const char *id); + int (*clk_enable) (struct clk *clk); + void (*clk_disable) (struct clk *clk); + unsigned long (*clk_get_rate) (struct clk *clk); + void (*clk_put) (struct clk *clk); + long (*clk_round_rate) (struct clk *clk, unsigned long rate); + int (*clk_set_rate) (struct clk *clk, unsigned long rate); + int (*clk_set_parent) (struct clk *clk, struct clk *parent); + struct clk* (*clk_get_parent) (struct clk *clk); +}; + +extern struct clk_interface clk_functions; + +#endif /* __ASM_POWERPC_CLK_INTERFACE_H */ Index: work-powerpc.git/arch/powerpc/kernel/Makefile =================================================================== --- work-powerpc.git.orig/arch/powerpc/kernel/Makefile +++ work-powerpc.git/arch/powerpc/kernel/Makefile @@ -12,7 +12,8 @@ endif obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ irq.o align.o signal_32.o pmc.o vdso.o \ - init_task.o process.o systbl.o idle.o + init_task.o process.o systbl.o idle.o \ + clock.o obj-y += vdso32/ obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ signal_64.o ptrace32.o \ ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/3] powerpc clk.h interface for platforms 2007-07-11 9:32 ` [PATCH 1/3] powerpc clk.h interface for platforms Domen Puncer @ 2007-07-11 10:36 ` Christoph Hellwig 2007-07-11 15:56 ` David Brownell 2007-08-06 6:58 ` [PATCH 1/3] powerpc clk.h interface for platforms Domen Puncer 1 sibling, 1 reply; 20+ messages in thread From: Christoph Hellwig @ 2007-07-11 10:36 UTC (permalink / raw) To: Domen Puncer; +Cc: David Brownell, linuxppc-dev, Sylvain Munaut, linux-mips On Wed, Jul 11, 2007 at 11:32:20AM +0200, Domen Puncer wrote: > clk interface for arch/powerpc, platforms should fill > clk_functions. Umm, this is about the fifth almost identical implementation of the clk_ functions. Please, please put it into common code. And talk to the mips folks which just got a similar comment from me. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/3] powerpc clk.h interface for platforms 2007-07-11 10:36 ` Christoph Hellwig @ 2007-07-11 15:56 ` David Brownell 2007-07-11 16:16 ` Christoph Hellwig 0 siblings, 1 reply; 20+ messages in thread From: David Brownell @ 2007-07-11 15:56 UTC (permalink / raw) To: Christoph Hellwig; +Cc: linuxppc-dev, Domen Puncer, Russell King, linux-mips On Wednesday 11 July 2007, Christoph Hellwig wrote: > On Wed, Jul 11, 2007 at 11:32:20AM +0200, Domen Puncer wrote: > > clk interface for arch/powerpc, platforms should fill > > clk_functions. > > Umm, this is about the fifth almost identical implementation of > the clk_ functions. Please, please put it into common code. > > And talk to the mips folks which just got a similar comment from me. You mean like a lib/clock.c core, rather than an opsvector? ISTR that allowing custom platform-specific implementations was intended to be a feature. But it's also true that some folks see lack of shared implementation code as a drawback; so I've CC'd Russell King (who originated the interface for ARM platforms). - Dave ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/3] powerpc clk.h interface for platforms 2007-07-11 15:56 ` David Brownell @ 2007-07-11 16:16 ` Christoph Hellwig 2007-07-11 17:02 ` David Brownell 0 siblings, 1 reply; 20+ messages in thread From: Christoph Hellwig @ 2007-07-11 16:16 UTC (permalink / raw) To: David Brownell Cc: linux-mips, linuxppc-dev, Domen Puncer, Christoph Hellwig, Russell King On Wed, Jul 11, 2007 at 08:56:58AM -0700, David Brownell wrote: > > Umm, this is about the fifth almost identical implementation of > > the clk_ functions. Please, please put it into common code. > > > > And talk to the mips folks which just got a similar comment from me. > > You mean like a lib/clock.c core, rather than an opsvector? I mean an ops vector and surrounding wrappers. Every architecture is reimplementing their own dispatch table which is rather annoying. What would a lib/clock.c do? ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/3] powerpc clk.h interface for platforms 2007-07-11 16:16 ` Christoph Hellwig @ 2007-07-11 17:02 ` David Brownell 2007-07-11 20:34 ` Russell King 0 siblings, 1 reply; 20+ messages in thread From: David Brownell @ 2007-07-11 17:02 UTC (permalink / raw) To: Christoph Hellwig; +Cc: linuxppc-dev, Domen Puncer, Russell King, linux-mips On Wednesday 11 July 2007, Christoph Hellwig wrote: > On Wed, Jul 11, 2007 at 08:56:58AM -0700, David Brownell wrote: > > > Umm, this is about the fifth almost identical implementation of > > > the clk_ functions. Please, please put it into common code. > > > > > > And talk to the mips folks which just got a similar comment from me. > > > > You mean like a lib/clock.c core, rather than an opsvector? > > I mean an ops vector and surrounding wrappers. Every architecture > is reimplementing their own dispatch table which is rather annoying. ARM doesn't. :) But then, nobody expects one kernel to support more than one vendor's ARM chips; or usually, more than one generation of that vendor's chips. So any dispatch table is specific to a given platform, and tuned to its quirks. Not much to share between OMAP and AT91, for example, except in some cases maybe an arm926ejs block. > What would a lib/clock.c do? Some folk have suggested defining a core "struct clk {...}" with some of the basics -- refcount, parent, maybe enough to support the clk_get() lookup or even more -- so that the more obvious stuff doesn't need constant re-implementation, and so that new implementations become easier. Platforms would wrap that with whatever extensions they need. I've not seen a solid proposal for such a thing, and it's not clear to me how that would play with with older code (e.g. any of the ARM implementations). And I'm sure there are other suggestions ... I was mostly just wondering just what you were suggesting. - Dave ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/3] powerpc clk.h interface for platforms 2007-07-11 17:02 ` David Brownell @ 2007-07-11 20:34 ` Russell King 2007-07-11 20:52 ` David Brownell 2007-07-13 9:12 ` Domen Puncer 0 siblings, 2 replies; 20+ messages in thread From: Russell King @ 2007-07-11 20:34 UTC (permalink / raw) To: David Brownell; +Cc: linuxppc-dev, linux-mips, Christoph Hellwig, Domen Puncer On Wed, Jul 11, 2007 at 10:02:54AM -0700, David Brownell wrote: > On Wednesday 11 July 2007, Christoph Hellwig wrote: > > On Wed, Jul 11, 2007 at 08:56:58AM -0700, David Brownell wrote: > > > > Umm, this is about the fifth almost identical implementation of > > > > the clk_ functions. Please, please put it into common code. > > > > > > > > And talk to the mips folks which just got a similar comment from me. > > > > > > You mean like a lib/clock.c core, rather than an opsvector? > > > > I mean an ops vector and surrounding wrappers. Every architecture > > is reimplementing their own dispatch table which is rather annoying. > > ARM doesn't. :) > > But then, nobody expects one kernel to support more than one > vendor's ARM chips; or usually, more than one generation of > that vendor's chips. So any dispatch table is specific to > a given platform, and tuned to its quirks. Not much to share > between OMAP and AT91, for example, except in some cases maybe > an arm926ejs block. And also the information stored within a 'struct clk' is very platform dependent. In the most basic situation, 'struct clk' may not actually be a structure, but the clock rate. All functions with the exception of clk_get() and clk_get_rate() could well be no-ops, clk_get() just returns the 'struct clk' representing the rate and 'clk_get_rate' returns that as an integer. More complex setups might want 'struct clk' to contain the address of a clock enable register, the bit position to enable that clock source, the clock rate, a refcount, and so on, all of which would be utterly useless for a platform which had fixed rate clocks. > I've not seen a solid proposal for such a thing, and it's not > clear to me how that would play with with older code (e.g. any > of the ARM implementations). If people are implementing their own incompatible changes without reference to the API they're invalid implementations as far as I'm concerned. If they can't bothered to lift a finger to even _talk_ to me about their requirements they just don't have any say concerning any future developments IMO. IOW, talk to me and I'll talk back. Ignore me and I'll ignore them. -- Russell King Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/ maintainer of: ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/3] powerpc clk.h interface for platforms 2007-07-11 20:34 ` Russell King @ 2007-07-11 20:52 ` David Brownell 2007-07-13 9:12 ` Domen Puncer 1 sibling, 0 replies; 20+ messages in thread From: David Brownell @ 2007-07-11 20:52 UTC (permalink / raw) To: Russell King; +Cc: linuxppc-dev, linux-mips, Christoph Hellwig, Domen Puncer On Wednesday 11 July 2007, Russell King wrote: > > IOW, talk to me and I'll talk back. Ignore me and I'll ignore them. Exactly why I cc'd you ... if folk want any more sharable cross-platform code than just the clk.h interface, I expect you'll have useful comments. - Dave ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/3] powerpc clk.h interface for platforms 2007-07-11 20:34 ` Russell King 2007-07-11 20:52 ` David Brownell @ 2007-07-13 9:12 ` Domen Puncer 2007-08-01 7:28 ` Generic clk.h wrappers? [Was: Re: [PATCH 1/3] powerpc clk.h interface for platforms] Domen Puncer 1 sibling, 1 reply; 20+ messages in thread From: Domen Puncer @ 2007-07-13 9:12 UTC (permalink / raw) To: Russell King; +Cc: David Brownell, linuxppc-dev, Christoph Hellwig, linux-mips On 11/07/07 21:34 +0100, Russell King wrote: > On Wed, Jul 11, 2007 at 10:02:54AM -0700, David Brownell wrote: > > On Wednesday 11 July 2007, Christoph Hellwig wrote: > > > On Wed, Jul 11, 2007 at 08:56:58AM -0700, David Brownell wrote: > > > > > Umm, this is about the fifth almost identical implementation of > > > > > the clk_ functions. Please, please put it into common code. > > > > > > > > > > And talk to the mips folks which just got a similar comment from me. > > > > > > > > You mean like a lib/clock.c core, rather than an opsvector? > > > > > > I mean an ops vector and surrounding wrappers. Every architecture > > > is reimplementing their own dispatch table which is rather annoying. > > > > ARM doesn't. :) > > > > But then, nobody expects one kernel to support more than one > > vendor's ARM chips; or usually, more than one generation of > > that vendor's chips. So any dispatch table is specific to > > a given platform, and tuned to its quirks. Not much to share > > between OMAP and AT91, for example, except in some cases maybe > > an arm926ejs block. > > And also the information stored within a 'struct clk' is very platform > dependent. In the most basic situation, 'struct clk' may not actually > be a structure, but the clock rate. All functions with the exception of > clk_get() and clk_get_rate() could well be no-ops, clk_get() just returns > the 'struct clk' representing the rate and 'clk_get_rate' returns that > as an integer. > > More complex setups might want 'struct clk' to contain the address of a > clock enable register, the bit position to enable that clock source, the > clock rate, a refcount, and so on, all of which would be utterly useless > for a platform which had fixed rate clocks. The patch that triggered this discussion is at the end. It doesn't make any assumption on struct clk, it's just a wrapper around functions from clk.h. Point of this patch was to abstract exported functions, since arch/powerpc/ can support multiple platfroms in one binary. > > > I've not seen a solid proposal for such a thing, and it's not > > clear to me how that would play with with older code (e.g. any > > of the ARM implementations). > > If people are implementing their own incompatible changes without reference > to the API they're invalid implementations as far as I'm concerned. If > they can't bothered to lift a finger to even _talk_ to me about their > requirements they just don't have any say concerning any future > developments IMO. My changes were implemented according to clk.h API. And honestly, I just wanted to rework clocks in some SPI driver and others made me do all the clk work. ;-) Domen > > IOW, talk to me and I'll talk back. Ignore me and I'll ignore them. > > -- > Russell King > Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/ > maintainer of: clk interface for arch/powerpc, platforms should fill clk_functions. Signed-off-by: Domen Puncer <domen.puncer@telargo.com> --- arch/powerpc/kernel/Makefile | 3 - arch/powerpc/kernel/clock.c | 82 ++++++++++++++++++++++++++++++++++++ include/asm-powerpc/clk_interface.h | 20 ++++++++ 3 files changed, 104 insertions(+), 1 deletion(-) Index: work-powerpc.git/arch/powerpc/kernel/clock.c =================================================================== --- /dev/null +++ work-powerpc.git/arch/powerpc/kernel/clock.c @@ -0,0 +1,82 @@ +/* + * Dummy clk implementations for powerpc. + * These need to be overridden in platform code. + */ + +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/errno.h> +#include <linux/module.h> +#include <asm/clk_interface.h> + +struct clk_interface clk_functions; + +struct clk *clk_get(struct device *dev, const char *id) +{ + if (clk_functions.clk_get) + return clk_functions.clk_get(dev, id); + return ERR_PTR(-ENOSYS); +} +EXPORT_SYMBOL(clk_get); + +void clk_put(struct clk *clk) +{ + if (clk_functions.clk_put) + clk_functions.clk_put(clk); +} +EXPORT_SYMBOL(clk_put); + +int clk_enable(struct clk *clk) +{ + if (clk_functions.clk_enable) + return clk_functions.clk_enable(clk); + return -ENOSYS; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ + if (clk_functions.clk_disable) + clk_functions.clk_disable(clk); +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + if (clk_functions.clk_get_rate) + return clk_functions.clk_get_rate(clk); + return 0; +} +EXPORT_SYMBOL(clk_get_rate); + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + if (clk_functions.clk_round_rate) + return clk_functions.clk_round_rate(clk, rate); + return -ENOSYS; +} +EXPORT_SYMBOL(clk_round_rate); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + if (clk_functions.clk_set_rate) + return clk_functions.clk_set_rate(clk, rate); + return -ENOSYS; +} +EXPORT_SYMBOL(clk_set_rate); + +struct clk *clk_get_parent(struct clk *clk) +{ + if (clk_functions.clk_get_parent) + return clk_functions.clk_get_parent(clk); + return ERR_PTR(-ENOSYS); +} +EXPORT_SYMBOL(clk_get_parent); + +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + if (clk_functions.clk_set_parent) + return clk_functions.clk_set_parent(clk, parent); + return -ENOSYS; +} +EXPORT_SYMBOL(clk_set_parent); Index: work-powerpc.git/include/asm-powerpc/clk_interface.h =================================================================== --- /dev/null +++ work-powerpc.git/include/asm-powerpc/clk_interface.h @@ -0,0 +1,20 @@ +#ifndef __ASM_POWERPC_CLK_INTERFACE_H +#define __ASM_POWERPC_CLK_INTERFACE_H + +#include <linux/clk.h> + +struct clk_interface { + struct clk* (*clk_get) (struct device *dev, const char *id); + int (*clk_enable) (struct clk *clk); + void (*clk_disable) (struct clk *clk); + unsigned long (*clk_get_rate) (struct clk *clk); + void (*clk_put) (struct clk *clk); + long (*clk_round_rate) (struct clk *clk, unsigned long rate); + int (*clk_set_rate) (struct clk *clk, unsigned long rate); + int (*clk_set_parent) (struct clk *clk, struct clk *parent); + struct clk* (*clk_get_parent) (struct clk *clk); +}; + +extern struct clk_interface clk_functions; + +#endif /* __ASM_POWERPC_CLK_INTERFACE_H */ Index: work-powerpc.git/arch/powerpc/kernel/Makefile =================================================================== --- work-powerpc.git.orig/arch/powerpc/kernel/Makefile +++ work-powerpc.git/arch/powerpc/kernel/Makefile @@ -12,7 +12,8 @@ endif obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ irq.o align.o signal_32.o pmc.o vdso.o \ - init_task.o process.o systbl.o idle.o + init_task.o process.o systbl.o idle.o \ + clock.o obj-y += vdso32/ obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ signal_64.o ptrace32.o \ ^ permalink raw reply [flat|nested] 20+ messages in thread
* Generic clk.h wrappers? [Was: Re: [PATCH 1/3] powerpc clk.h interface for platforms] 2007-07-13 9:12 ` Domen Puncer @ 2007-08-01 7:28 ` Domen Puncer 2007-08-01 12:57 ` Christoph Hellwig 0 siblings, 1 reply; 20+ messages in thread From: Domen Puncer @ 2007-08-01 7:28 UTC (permalink / raw) To: Domen Puncer Cc: David Brownell, linuxppc-dev, Christoph Hellwig, Russell King, linux-mips On 13/07/07 11:12 +0200, Domen Puncer wrote: > On 11/07/07 21:34 +0100, Russell King wrote: > > On Wed, Jul 11, 2007 at 10:02:54AM -0700, David Brownell wrote: > > > On Wednesday 11 July 2007, Christoph Hellwig wrote: > > > > On Wed, Jul 11, 2007 at 08:56:58AM -0700, David Brownell wrote: > > > > > > Umm, this is about the fifth almost identical implementation of > > > > > > the clk_ functions. Please, please put it into common code. > > > > > > > > > > > > And talk to the mips folks which just got a similar comment from me. > > > > > > > > > > You mean like a lib/clock.c core, rather than an opsvector? > > > > > > > > I mean an ops vector and surrounding wrappers. Every architecture > > > > is reimplementing their own dispatch table which is rather annoying. > > > > > > ARM doesn't. :) > > > > > > But then, nobody expects one kernel to support more than one > > > vendor's ARM chips; or usually, more than one generation of > > > that vendor's chips. So any dispatch table is specific to > > > a given platform, and tuned to its quirks. Not much to share > > > between OMAP and AT91, for example, except in some cases maybe > > > an arm926ejs block. > > > > And also the information stored within a 'struct clk' is very platform > > dependent. In the most basic situation, 'struct clk' may not actually > > be a structure, but the clock rate. All functions with the exception of > > clk_get() and clk_get_rate() could well be no-ops, clk_get() just returns > > the 'struct clk' representing the rate and 'clk_get_rate' returns that > > as an integer. > > > > More complex setups might want 'struct clk' to contain the address of a > > clock enable register, the bit position to enable that clock source, the > > clock rate, a refcount, and so on, all of which would be utterly useless > > for a platform which had fixed rate clocks. > > The patch that triggered this discussion is at the end. > It doesn't make any assumption on struct clk, it's just a > wrapper around functions from clk.h. > Point of this patch was to abstract exported functions, since > arch/powerpc/ can support multiple platfroms in one binary. So... the thread just ended without any consensus, ACK or whatever. Choices I see: - have EXPORT_SYMBOL for clk.h functions in ie. lib/clock.c and have every implemenation fill some global struct. - leave this patch as it is, abstraction only for arch/powerpc/. - or I can just forget about this, and leave it for the next sucker who will want nicer clock handling in some driver. Domen ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Generic clk.h wrappers? [Was: Re: [PATCH 1/3] powerpc clk.h interface for platforms] 2007-08-01 7:28 ` Generic clk.h wrappers? [Was: Re: [PATCH 1/3] powerpc clk.h interface for platforms] Domen Puncer @ 2007-08-01 12:57 ` Christoph Hellwig 2007-08-02 23:32 ` David Brownell 0 siblings, 1 reply; 20+ messages in thread From: Christoph Hellwig @ 2007-08-01 12:57 UTC (permalink / raw) To: Domen Puncer Cc: David Brownell, linuxppc-dev, Christoph Hellwig, Russell King, linux-mips On Wed, Aug 01, 2007 at 09:28:07AM +0200, Domen Puncer wrote: > > It doesn't make any assumption on struct clk, it's just a > > wrapper around functions from clk.h. > > Point of this patch was to abstract exported functions, since > > arch/powerpc/ can support multiple platfroms in one binary. > > So... the thread just ended without any consensus, ACK or whatever. > > Choices I see: > - have EXPORT_SYMBOL for clk.h functions in ie. lib/clock.c and have > every implemenation fill some global struct. > - leave this patch as it is, abstraction only for arch/powerpc/. > - or I can just forget about this, and leave it for the next sucker > who will want nicer clock handling in some driver It seems like arm really wants this optimized to the last cycle and no abstraction inbetween so we're probably stuck with the status quo. I'm pretty sure this will get too messy sooner and later and people will clean the mess up, but due to the political issues I don't think it's fair to put that burden on you just for submitting the powerpc implementation. So, please leave the patch as-is. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Generic clk.h wrappers? [Was: Re: [PATCH 1/3] powerpc clk.h interface for platforms] 2007-08-01 12:57 ` Christoph Hellwig @ 2007-08-02 23:32 ` David Brownell 2007-08-03 8:36 ` Russell King 0 siblings, 1 reply; 20+ messages in thread From: David Brownell @ 2007-08-02 23:32 UTC (permalink / raw) To: Christoph Hellwig; +Cc: linuxppc-dev, Domen Puncer, Russell King, linux-mips On Wednesday 01 August 2007, Christoph Hellwig wrote: > On Wed, Aug 01, 2007 at 09:28:07AM +0200, Domen Puncer wrote: > > > It doesn't make any assumption on struct clk, it's just a > > > wrapper around functions from clk.h. > > > Point of this patch was to abstract exported functions, since > > > arch/powerpc/ can support multiple platfroms in one binary. > > > > So... the thread just ended without any consensus, ACK or whatever. > > > > Choices I see: > > - have EXPORT_SYMBOL for clk.h functions in ie. lib/clock.c and have > > every implemenation fill some global struct. > > - leave this patch as it is, abstraction only for arch/powerpc/. That seems the best solution for now, I agree. > > - or I can just forget about this, and leave it for the next sucker > > who will want nicer clock handling in some driver > > It seems like arm really wants this optimized to the last cycle > and no abstraction inbetween so we're probably stuck with the status > quo. I'm pretty sure this will get too messy sooner and later and > people will clean the mess up, but due to the political issues I > don't think it's fair to put that burden on you just for submitting > the powerpc implementation. > > So, please leave the patch as-is. > ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Generic clk.h wrappers? [Was: Re: [PATCH 1/3] powerpc clk.h interface for platforms] 2007-08-02 23:32 ` David Brownell @ 2007-08-03 8:36 ` Russell King 0 siblings, 0 replies; 20+ messages in thread From: Russell King @ 2007-08-03 8:36 UTC (permalink / raw) To: David Brownell; +Cc: linuxppc-dev, linux-mips, Christoph Hellwig, Domen Puncer On Thu, Aug 02, 2007 at 04:32:13PM -0700, David Brownell wrote: > On Wednesday 01 August 2007, Christoph Hellwig wrote: > > On Wed, Aug 01, 2007 at 09:28:07AM +0200, Domen Puncer wrote: > > > > It doesn't make any assumption on struct clk, it's just a > > > > wrapper around functions from clk.h. > > > > Point of this patch was to abstract exported functions, since > > > > arch/powerpc/ can support multiple platfroms in one binary. > > > > > > So... the thread just ended without any consensus, ACK or whatever. > > > > > > Choices I see: > > > - have EXPORT_SYMBOL for clk.h functions in ie. lib/clock.c and have > > > every implemenation fill some global struct. > > > - leave this patch as it is, abstraction only for arch/powerpc/. > > That seems the best solution for now, I agree. I've not been avoiding replying further to this thread in spite, it's just that I've not had any time what so ever to look at this further. It's very low priority for me at the moment, so it's getting zero time, and will continue to be in that state for at least the next month and a bit. Sorry. -- Russell King Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/ maintainer of: ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/3] powerpc clk.h interface for platforms 2007-07-11 9:32 ` [PATCH 1/3] powerpc clk.h interface for platforms Domen Puncer 2007-07-11 10:36 ` Christoph Hellwig @ 2007-08-06 6:58 ` Domen Puncer 2007-09-19 3:47 ` Paul Mackerras 1 sibling, 1 reply; 20+ messages in thread From: Domen Puncer @ 2007-08-06 6:58 UTC (permalink / raw) To: Paul Mackerras; +Cc: David Brownell, linuxppc-dev, Sylvain Munaut Hi! Paul, what do you say about this? Sylvain suggested it could also be integrated with define_machine interface. If it's OK, it would be cool if it got merged in next release cycle. Domen On 11/07/07 11:32 +0200, Domen Puncer wrote: > clk interface for arch/powerpc, platforms should fill > clk_functions. > > Signed-off-by: Domen Puncer <domen.puncer@telargo.com> > > --- > arch/powerpc/kernel/Makefile | 3 - > arch/powerpc/kernel/clock.c | 82 ++++++++++++++++++++++++++++++++++++ > include/asm-powerpc/clk_interface.h | 20 ++++++++ > 3 files changed, 104 insertions(+), 1 deletion(-) > > Index: work-powerpc.git/arch/powerpc/kernel/clock.c > =================================================================== > --- /dev/null > +++ work-powerpc.git/arch/powerpc/kernel/clock.c > @@ -0,0 +1,82 @@ > +/* > + * Dummy clk implementations for powerpc. > + * These need to be overridden in platform code. > + */ > + > +#include <linux/clk.h> > +#include <linux/err.h> > +#include <linux/errno.h> > +#include <linux/module.h> > +#include <asm/clk_interface.h> > + > +struct clk_interface clk_functions; > + > +struct clk *clk_get(struct device *dev, const char *id) > +{ > + if (clk_functions.clk_get) > + return clk_functions.clk_get(dev, id); > + return ERR_PTR(-ENOSYS); > +} > +EXPORT_SYMBOL(clk_get); > + > +void clk_put(struct clk *clk) > +{ > + if (clk_functions.clk_put) > + clk_functions.clk_put(clk); > +} > +EXPORT_SYMBOL(clk_put); > + > +int clk_enable(struct clk *clk) > +{ > + if (clk_functions.clk_enable) > + return clk_functions.clk_enable(clk); > + return -ENOSYS; > +} > +EXPORT_SYMBOL(clk_enable); > + > +void clk_disable(struct clk *clk) > +{ > + if (clk_functions.clk_disable) > + clk_functions.clk_disable(clk); > +} > +EXPORT_SYMBOL(clk_disable); > + > +unsigned long clk_get_rate(struct clk *clk) > +{ > + if (clk_functions.clk_get_rate) > + return clk_functions.clk_get_rate(clk); > + return 0; > +} > +EXPORT_SYMBOL(clk_get_rate); > + > +long clk_round_rate(struct clk *clk, unsigned long rate) > +{ > + if (clk_functions.clk_round_rate) > + return clk_functions.clk_round_rate(clk, rate); > + return -ENOSYS; > +} > +EXPORT_SYMBOL(clk_round_rate); > + > +int clk_set_rate(struct clk *clk, unsigned long rate) > +{ > + if (clk_functions.clk_set_rate) > + return clk_functions.clk_set_rate(clk, rate); > + return -ENOSYS; > +} > +EXPORT_SYMBOL(clk_set_rate); > + > +struct clk *clk_get_parent(struct clk *clk) > +{ > + if (clk_functions.clk_get_parent) > + return clk_functions.clk_get_parent(clk); > + return ERR_PTR(-ENOSYS); > +} > +EXPORT_SYMBOL(clk_get_parent); > + > +int clk_set_parent(struct clk *clk, struct clk *parent) > +{ > + if (clk_functions.clk_set_parent) > + return clk_functions.clk_set_parent(clk, parent); > + return -ENOSYS; > +} > +EXPORT_SYMBOL(clk_set_parent); > Index: work-powerpc.git/include/asm-powerpc/clk_interface.h > =================================================================== > --- /dev/null > +++ work-powerpc.git/include/asm-powerpc/clk_interface.h > @@ -0,0 +1,20 @@ > +#ifndef __ASM_POWERPC_CLK_INTERFACE_H > +#define __ASM_POWERPC_CLK_INTERFACE_H > + > +#include <linux/clk.h> > + > +struct clk_interface { > + struct clk* (*clk_get) (struct device *dev, const char *id); > + int (*clk_enable) (struct clk *clk); > + void (*clk_disable) (struct clk *clk); > + unsigned long (*clk_get_rate) (struct clk *clk); > + void (*clk_put) (struct clk *clk); > + long (*clk_round_rate) (struct clk *clk, unsigned long rate); > + int (*clk_set_rate) (struct clk *clk, unsigned long rate); > + int (*clk_set_parent) (struct clk *clk, struct clk *parent); > + struct clk* (*clk_get_parent) (struct clk *clk); > +}; > + > +extern struct clk_interface clk_functions; > + > +#endif /* __ASM_POWERPC_CLK_INTERFACE_H */ > Index: work-powerpc.git/arch/powerpc/kernel/Makefile > =================================================================== > --- work-powerpc.git.orig/arch/powerpc/kernel/Makefile > +++ work-powerpc.git/arch/powerpc/kernel/Makefile > @@ -12,7 +12,8 @@ endif > > obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ > irq.o align.o signal_32.o pmc.o vdso.o \ > - init_task.o process.o systbl.o idle.o > + init_task.o process.o systbl.o idle.o \ > + clock.o > obj-y += vdso32/ > obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ > signal_64.o ptrace32.o \ > _______________________________________________ > Linuxppc-dev mailing list > Linuxppc-dev@ozlabs.org > https://ozlabs.org/mailman/listinfo/linuxppc-dev ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/3] powerpc clk.h interface for platforms 2007-08-06 6:58 ` [PATCH 1/3] powerpc clk.h interface for platforms Domen Puncer @ 2007-09-19 3:47 ` Paul Mackerras 2007-09-19 5:11 ` Domen Puncer 0 siblings, 1 reply; 20+ messages in thread From: Paul Mackerras @ 2007-09-19 3:47 UTC (permalink / raw) To: Domen Puncer; +Cc: David Brownell, linuxppc-dev, Sylvain Munaut Domen Puncer writes: > Paul, what do you say about this? > Sylvain suggested it could also be integrated with define_machine > interface. As it stands, your patch adds the clk_* functions on all platforms. What platforms would actually want to use them? Paul. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/3] powerpc clk.h interface for platforms 2007-09-19 3:47 ` Paul Mackerras @ 2007-09-19 5:11 ` Domen Puncer 2007-09-20 5:07 ` Paul Mackerras 0 siblings, 1 reply; 20+ messages in thread From: Domen Puncer @ 2007-09-19 5:11 UTC (permalink / raw) To: Paul Mackerras; +Cc: David Brownell, linuxppc-dev, Sylvain Munaut On 19/09/07 13:47 +1000, Paul Mackerras wrote: > Domen Puncer writes: > > > Paul, what do you say about this? > > Sylvain suggested it could also be integrated with define_machine > > interface. > > As it stands, your patch adds the clk_* functions on all platforms. > What platforms would actually want to use them? 52xx Reason for adding it to all was that EXPORT_SYMBOL's would clash if one were to add clk support for another platform. Domen > > Paul. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/3] powerpc clk.h interface for platforms 2007-09-19 5:11 ` Domen Puncer @ 2007-09-20 5:07 ` Paul Mackerras 2007-09-20 14:00 ` [PATCH 1/3 v2] " Domen Puncer 0 siblings, 1 reply; 20+ messages in thread From: Paul Mackerras @ 2007-09-20 5:07 UTC (permalink / raw) To: Domen Puncer; +Cc: David Brownell, linuxppc-dev, Sylvain Munaut Domen Puncer writes: > 52xx > Reason for adding it to all was that EXPORT_SYMBOL's would clash if > one were to add clk support for another platform. What I meant was, why aren't you using a config symbol so that we don't build it on platforms that don't need any "clk" support at all? Paul. ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 1/3 v2] powerpc clk.h interface for platforms 2007-09-20 5:07 ` Paul Mackerras @ 2007-09-20 14:00 ` Domen Puncer 0 siblings, 0 replies; 20+ messages in thread From: Domen Puncer @ 2007-09-20 14:00 UTC (permalink / raw) To: Paul Mackerras; +Cc: David Brownell, linuxppc-dev, Sylvain Munaut clk interface for arch/powerpc, platforms should fill clk_functions. Signed-off-by: Domen Puncer <domen.puncer@telargo.com> --- On 20/09/07 15:07 +1000, Paul Mackerras wrote: > Domen Puncer writes: > > > 52xx > > Reason for adding it to all was that EXPORT_SYMBOL's would clash if > > one were to add clk support for another platform. > > What I meant was, why aren't you using a config symbol so that we > don't build it on platforms that don't need any "clk" support at all? Right, doh! > > Paul. arch/powerpc/Kconfig | 4 + arch/powerpc/kernel/Makefile | 1 arch/powerpc/kernel/clock.c | 82 ++++++++++++++++++++++++++++++++++++ arch/powerpc/platforms/52xx/Kconfig | 1 include/asm-powerpc/clk_interface.h | 20 ++++++++ 5 files changed, 108 insertions(+) Index: linux.git/arch/powerpc/kernel/clock.c =================================================================== --- /dev/null +++ linux.git/arch/powerpc/kernel/clock.c @@ -0,0 +1,82 @@ +/* + * Dummy clk implementations for powerpc. + * These need to be overridden in platform code. + */ + +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/errno.h> +#include <linux/module.h> +#include <asm/clk_interface.h> + +struct clk_interface clk_functions; + +struct clk *clk_get(struct device *dev, const char *id) +{ + if (clk_functions.clk_get) + return clk_functions.clk_get(dev, id); + return ERR_PTR(-ENOSYS); +} +EXPORT_SYMBOL(clk_get); + +void clk_put(struct clk *clk) +{ + if (clk_functions.clk_put) + clk_functions.clk_put(clk); +} +EXPORT_SYMBOL(clk_put); + +int clk_enable(struct clk *clk) +{ + if (clk_functions.clk_enable) + return clk_functions.clk_enable(clk); + return -ENOSYS; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ + if (clk_functions.clk_disable) + clk_functions.clk_disable(clk); +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + if (clk_functions.clk_get_rate) + return clk_functions.clk_get_rate(clk); + return 0; +} +EXPORT_SYMBOL(clk_get_rate); + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + if (clk_functions.clk_round_rate) + return clk_functions.clk_round_rate(clk, rate); + return -ENOSYS; +} +EXPORT_SYMBOL(clk_round_rate); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + if (clk_functions.clk_set_rate) + return clk_functions.clk_set_rate(clk, rate); + return -ENOSYS; +} +EXPORT_SYMBOL(clk_set_rate); + +struct clk *clk_get_parent(struct clk *clk) +{ + if (clk_functions.clk_get_parent) + return clk_functions.clk_get_parent(clk); + return ERR_PTR(-ENOSYS); +} +EXPORT_SYMBOL(clk_get_parent); + +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + if (clk_functions.clk_set_parent) + return clk_functions.clk_set_parent(clk, parent); + return -ENOSYS; +} +EXPORT_SYMBOL(clk_set_parent); Index: linux.git/include/asm-powerpc/clk_interface.h =================================================================== --- /dev/null +++ linux.git/include/asm-powerpc/clk_interface.h @@ -0,0 +1,20 @@ +#ifndef __ASM_POWERPC_CLK_INTERFACE_H +#define __ASM_POWERPC_CLK_INTERFACE_H + +#include <linux/clk.h> + +struct clk_interface { + struct clk* (*clk_get) (struct device *dev, const char *id); + int (*clk_enable) (struct clk *clk); + void (*clk_disable) (struct clk *clk); + unsigned long (*clk_get_rate) (struct clk *clk); + void (*clk_put) (struct clk *clk); + long (*clk_round_rate) (struct clk *clk, unsigned long rate); + int (*clk_set_rate) (struct clk *clk, unsigned long rate); + int (*clk_set_parent) (struct clk *clk, struct clk *parent); + struct clk* (*clk_get_parent) (struct clk *clk); +}; + +extern struct clk_interface clk_functions; + +#endif /* __ASM_POWERPC_CLK_INTERFACE_H */ Index: linux.git/arch/powerpc/kernel/Makefile =================================================================== --- linux.git.orig/arch/powerpc/kernel/Makefile +++ linux.git/arch/powerpc/kernel/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_PPC64) += vdso64/ obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o obj-$(CONFIG_PPC_970_NAP) += idle_power4.o obj-$(CONFIG_PPC_OF) += of_device.o of_platform.o prom_parse.o +obj-$(CONFIG_PPC_CLOCK) += clock.o procfs-$(CONFIG_PPC64) := proc_ppc64.o obj-$(CONFIG_PROC_FS) += $(procfs-y) rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI) := rtas_pci.o Index: linux.git/arch/powerpc/Kconfig =================================================================== --- linux.git.orig/arch/powerpc/Kconfig +++ linux.git/arch/powerpc/Kconfig @@ -664,3 +664,7 @@ config KEYS_COMPAT default y source "crypto/Kconfig" + +config PPC_CLOCK + bool + default n Index: linux.git/arch/powerpc/platforms/52xx/Kconfig =================================================================== --- linux.git.orig/arch/powerpc/platforms/52xx/Kconfig +++ linux.git/arch/powerpc/platforms/52xx/Kconfig @@ -1,6 +1,7 @@ config PPC_MPC52xx bool select FSL_SOC + select PPC_CLOCK default n config PPC_MPC5200 ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 2/3] mpc52xx clk.h interface 2007-07-11 9:31 [PATCH 0/3] clock (clk.h) framework for mpc52xx Domen Puncer 2007-07-11 9:32 ` [PATCH 1/3] powerpc clk.h interface for platforms Domen Puncer @ 2007-07-11 9:33 ` Domen Puncer 2007-07-11 9:34 ` [PATCH 3/3] mpc52xx_psc_spi: use clk.h subsystem Domen Puncer 2 siblings, 0 replies; 20+ messages in thread From: Domen Puncer @ 2007-07-11 9:33 UTC (permalink / raw) To: linuxppc-dev; +Cc: David Brownell, Sylvain Munaut clk.h interface for mpc52xx Currently only psc_mclks are defined. Signed-off-by: Domen Puncer <domen.puncer@telargo.com> --- arch/powerpc/platforms/52xx/Makefile | 2 arch/powerpc/platforms/52xx/mpc52xx_clock.c | 352 +++++++++++++++++++++++++++ arch/powerpc/platforms/52xx/mpc52xx_common.c | 3 include/asm-powerpc/mpc52xx.h | 2 4 files changed, 358 insertions(+), 1 deletion(-) Index: work-powerpc.git/arch/powerpc/platforms/52xx/Makefile =================================================================== --- work-powerpc.git.orig/arch/powerpc/platforms/52xx/Makefile +++ work-powerpc.git/arch/powerpc/platforms/52xx/Makefile @@ -2,7 +2,7 @@ # Makefile for 52xx based boards # ifeq ($(CONFIG_PPC_MERGE),y) -obj-y += mpc52xx_pic.o mpc52xx_common.o +obj-y += mpc52xx_pic.o mpc52xx_common.o mpc52xx_clock.o obj-$(CONFIG_PCI) += mpc52xx_pci.o endif Index: work-powerpc.git/arch/powerpc/platforms/52xx/mpc52xx_clock.c =================================================================== --- /dev/null +++ work-powerpc.git/arch/powerpc/platforms/52xx/mpc52xx_clock.c @@ -0,0 +1,352 @@ +/* + * arch/powerpc/platforms/52xx/mpc52xx_clock.c + * based on linux/arch/arm/mach-at91/clock.c + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/spinlock.h> +#include <linux/clk.h> + +#include <asm/io.h> +#include <asm/mpc52xx.h> +#include <asm/clk_interface.h> + + +struct clk { + struct list_head node; + const char *name; /* unique clock name */ + struct device_node *of_node; /* device node associated with this clock */ + const char *function; /* clock function */ + unsigned long rate_hz; + struct clk *parent; + void (*mode)(struct clk *, int); + u16 users; + int cdm_id; /* == bit number in datasheet, or 0 */ + long (*set_rate)(struct clk *, unsigned long rate, int round_only); +}; + +#define CDM_ID_PSC3 24 +#define CDM_ID_PSC2 25 +#define CDM_ID_PSC1 26 +#define CDM_ID_PSC6 27 + +static long psc_set_rate(struct clk *clk, unsigned long rate, int round_only); + +static struct clk clk_system = { + .name = "system", + .rate_hz = 528000000, /* default if there's no system-frequency in dts */ + .users = 1, /* always on */ +}; +static struct clk clk_psc1 = { + .name = "psc1_mclk", + .cdm_id = CDM_ID_PSC1, + .parent = &clk_system, + .set_rate = psc_set_rate, +}; +static struct clk clk_psc2 = { + .name = "psc2_mclk", + .cdm_id = CDM_ID_PSC2, + .parent = &clk_system, + .set_rate = psc_set_rate, +}; +static struct clk clk_psc3 = { + .name = "psc3_mclk", + .cdm_id = CDM_ID_PSC3, + .parent = &clk_system, + .set_rate = psc_set_rate, +}; +static struct clk clk_psc6 = { + .name = "psc6_mclk", + .cdm_id = CDM_ID_PSC6, + .parent = &clk_system, + .set_rate = psc_set_rate, +}; + + + +static LIST_HEAD(clocks); +static DEFINE_SPINLOCK(clk_lock); + +static struct mpc52xx_cdm __iomem *cdm; +static DEFINE_SPINLOCK(cdm_lock); + + +static long psc_set_rate(struct clk *clk, unsigned long rate, int round_only) +{ + u16 mclkdiv; + u16 __iomem *divreg; + + /* pick a divider that will get the closest clock */ + mclkdiv = (clk->parent->rate_hz + rate/2) / rate - 1; + + /* trim to closest possible. or should we return an error? */ + mclkdiv = min(mclkdiv, (u16)0x1ff); + mclkdiv = max(mclkdiv, (u16)1); + + rate = clk->parent->rate_hz / (mclkdiv + 1); + mclkdiv |= 0x8000; /* enable (this is not clk_enable!) */ + + if (round_only) + return rate; + + if (clk->cdm_id == CDM_ID_PSC1) + divreg = &cdm->mclken_div_psc1; + else if (clk->cdm_id == CDM_ID_PSC2) + divreg = &cdm->mclken_div_psc2; + else if (clk->cdm_id == CDM_ID_PSC3) + divreg = &cdm->mclken_div_psc3; + else if (clk->cdm_id == CDM_ID_PSC6) + divreg = &cdm->mclken_div_psc6; + else + return -ENODEV; + + out_be16(divreg, mclkdiv); + + return 0; +} + +/* clocks cannot be de-registered no refcounting necessary */ +static struct clk *mpc52xx_clk_get(struct device *dev, const char *id) +{ + struct clk *clk; + + list_for_each_entry(clk, &clocks, node) { + if (strcmp(id, clk->name) == 0) + return clk; + if (clk->function && strcmp(id, clk->function) == 0 && dev && + dev->archdata.of_node == clk->of_node) + return clk; + } + + return ERR_PTR(-ENOENT); +} + +static void mpc52xx_clock_associate(const char *id, struct device_node *of_node, + const char *function) +{ + struct clk *clk = mpc52xx_clk_get(NULL, id); + + if (IS_ERR(clk)) + return; + + clk->function = function; + clk->of_node = of_node; +} + +static void mpc52xx_clk_put(struct clk *clk) +{ +} + + +static void clk_mode_cdm(int cdm_id, int enabled) +{ + unsigned long flags; + u32 clk_enables; + + if (cdm_id < 12 || cdm_id > 31) { + printk(KERN_ERR "%s: %i invalid cdm_id: %i\n", __func__, __LINE__, cdm_id); + return; + } + + spin_lock_irqsave(&cdm_lock, flags); + clk_enables = in_be32(&cdm->clk_enables); + if (enabled) + clk_enables |= 1 << (31-cdm_id); + else + clk_enables &= ~(1 << (31-cdm_id)); + + out_be32(&cdm->clk_enables, clk_enables); + spin_unlock_irqrestore(&cdm_lock, flags); +} + +static void __clk_enable(struct clk *clk) +{ + if (clk->parent) + __clk_enable(clk->parent); + if (clk->users++ == 0 && clk->mode) { + if (clk->cdm_id) + clk_mode_cdm(clk->cdm_id, 1); + else + clk->mode(clk, 1); + } +} + +static int mpc52xx_clk_enable(struct clk *clk) +{ + unsigned long flags; + + spin_lock_irqsave(&clk_lock, flags); + __clk_enable(clk); + spin_unlock_irqrestore(&clk_lock, flags); + return 0; +} + +static void __clk_disable(struct clk *clk) +{ + BUG_ON(clk->users == 0); + if (--clk->users == 0 && clk->mode) { + if (clk->cdm_id) + clk_mode_cdm(clk->cdm_id, 0); + else + clk->mode(clk, 0); + } + if (clk->parent) + __clk_disable(clk->parent); +} + +static void mpc52xx_clk_disable(struct clk *clk) +{ + unsigned long flags; + + spin_lock_irqsave(&clk_lock, flags); + __clk_disable(clk); + spin_unlock_irqrestore(&clk_lock, flags); +} + +static unsigned long mpc52xx_clk_get_rate(struct clk *clk) +{ + unsigned long flags; + unsigned long rate; + + spin_lock_irqsave(&clk_lock, flags); + for (;;) { + rate = clk->rate_hz; + if (rate || !clk->parent) + break; + clk = clk->parent; + } + spin_unlock_irqrestore(&clk_lock, flags); + return rate; +} + +static long mpc52xx_clk_round_rate(struct clk *clk, unsigned long rate) +{ + unsigned long flags; + long ret; + + if (!clk->set_rate) + return -EINVAL; + + spin_lock_irqsave(&clk_lock, flags); + ret = clk->set_rate(clk, rate, 1); + spin_unlock_irqrestore(&clk_lock, flags); + + return ret; +} + +static int mpc52xx_clk_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned long flags; + int ret; + + if (!clk->set_rate) + return -EINVAL; + if (clk->users) + return -EBUSY; + + spin_lock_irqsave(&clk_lock, flags); + clk->rate_hz = clk->set_rate(clk, rate, 1); + ret = clk->set_rate(clk, rate, 0); + spin_unlock_irqrestore(&clk_lock, flags); + + return ret; +} + +static struct clk *mpc52xx_clk_get_parent(struct clk *clk) +{ + return clk->parent; +} + +static int mpc52xx_clk_set_parent(struct clk *clk, struct clk *parent) +{ + unsigned long flags; + + if (clk->users) + return -EBUSY; + spin_lock_irqsave(&clk_lock, flags); + + clk->rate_hz = parent->rate_hz; + clk->parent = parent; + + spin_unlock_irqrestore(&clk_lock, flags); + return 0; +} + + + +static struct clk *const mpc5200_clocks[] __initdata = { + &clk_system, + &clk_psc1, + &clk_psc2, + &clk_psc3, + &clk_psc6, +}; + +int __init mpc52xx_clock_init(void) +{ + int i; + struct device_node *np, *child = NULL; + const unsigned int *fp; + + /* map Clock Distribution Module registers */ + cdm = mpc52xx_find_and_map("mpc5200-cdm"); + if (!cdm) { + printk(KERN_ERR "%s: %i couldn't map mpc5200-cdm\n", __func__, __LINE__); + return -EFAULT; + } + + /* register clocks */ + for (i = 0; i < ARRAY_SIZE(mpc5200_clocks); i++) + list_add_tail(&mpc5200_clocks[i]->node, &clocks); + + + /* get clk_system rate from device tree */ + np = of_find_node_by_type(NULL, "soc"); + if (!np) + return 0; + + fp = of_get_property(np, "system-frequency", NULL); + if (fp && *fp) + clk_system.rate_hz = *fp; + + /* associate psc_mclks with device_nodes */ + while ((child = of_get_next_child(np, child))) { + if (of_device_is_compatible(child, "mpc5200-psc")) { + char clock[10]; + int ci = -1; + const int *pci; + + pci = of_get_property(child, "cell-index", NULL); + if (pci) + ci = *pci; + if (ci < 0 || ci > 5 || ci == 3 || ci == 4) { + printk(KERN_ALERT "%s: %i psc node '%s' has invalid " + "cell-index: %i\n", __func__, __LINE__, + child->name, ci); + continue; + } + + snprintf(clock, 10, "psc%i_mclk", ci + 1); + mpc52xx_clock_associate(clock, child, "psc_mclk"); + } + } + of_node_put(np); + + /* register clocks */ + clk_functions = (struct clk_interface) { + .clk_get = mpc52xx_clk_get, + .clk_enable = mpc52xx_clk_enable, + .clk_disable = mpc52xx_clk_disable, + .clk_get_rate = mpc52xx_clk_get_rate, + .clk_put = mpc52xx_clk_put, + .clk_round_rate = mpc52xx_clk_round_rate, + .clk_set_rate = mpc52xx_clk_set_rate, + .clk_set_parent = mpc52xx_clk_set_parent, + .clk_get_parent = mpc52xx_clk_get_parent, + }; + return 0; +} Index: work-powerpc.git/arch/powerpc/platforms/52xx/mpc52xx_common.c =================================================================== --- work-powerpc.git.orig/arch/powerpc/platforms/52xx/mpc52xx_common.c +++ work-powerpc.git/arch/powerpc/platforms/52xx/mpc52xx_common.c @@ -110,6 +110,9 @@ mpc52xx_setup_cpu(void) transaction and re-enable it afterwards ...) */ out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS); + /* setup clk system */ + mpc52xx_clock_init(); + /* Unmap zones */ unmap_regs: if (cdm) iounmap(cdm); Index: work-powerpc.git/include/asm-powerpc/mpc52xx.h =================================================================== --- work-powerpc.git.orig/include/asm-powerpc/mpc52xx.h +++ work-powerpc.git/include/asm-powerpc/mpc52xx.h @@ -274,5 +274,7 @@ extern char saved_sram[0x4000]; /* reuse #endif #endif /* CONFIG_PM */ +extern int __init mpc52xx_clock_init(void); + #endif /* __ASM_POWERPC_MPC52xx_H__ */ ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 3/3] mpc52xx_psc_spi: use clk.h subsystem 2007-07-11 9:31 [PATCH 0/3] clock (clk.h) framework for mpc52xx Domen Puncer 2007-07-11 9:32 ` [PATCH 1/3] powerpc clk.h interface for platforms Domen Puncer 2007-07-11 9:33 ` [PATCH 2/3] mpc52xx clk.h interface Domen Puncer @ 2007-07-11 9:34 ` Domen Puncer 2 siblings, 0 replies; 20+ messages in thread From: Domen Puncer @ 2007-07-11 9:34 UTC (permalink / raw) To: linuxppc-dev; +Cc: David Brownell, Sylvain Munaut Use clocks subsystem in spi driver. Signed-off-by: Domen Puncer <domen.puncer@telargo.com> --- drivers/spi/mpc52xx_psc_spi.c | 64 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 7 deletions(-) Index: work-powerpc.git/drivers/spi/mpc52xx_psc_spi.c =================================================================== --- work-powerpc.git.orig/drivers/spi/mpc52xx_psc_spi.c +++ work-powerpc.git/drivers/spi/mpc52xx_psc_spi.c @@ -18,6 +18,7 @@ #if defined(CONFIG_PPC_MERGE) #include <asm/of_platform.h> +#include <linux/clk.h> #else #include <linux/platform_device.h> #endif @@ -53,6 +54,8 @@ struct mpc52xx_psc_spi { spinlock_t lock; struct completion done; + + struct clk *clk; }; /* controller state */ @@ -85,6 +88,13 @@ static void mpc52xx_psc_spi_activate_cs( u32 sicr; u16 ccr; +#ifdef CONFIG_PPC_MERGE + u8 bitclkdiv = 2; /* minimum bitclkdiv */ + int speed = cs->speed_hz ? cs->speed_hz : 1000000; + int mclk; + int system; +#endif + sicr = in_be32(&psc->sicr); /* Set clock phase and polarity */ @@ -106,13 +116,39 @@ static void mpc52xx_psc_spi_activate_cs( /* Set clock frequency and bits per word * Because psc->ccr is defined as 16bit register instead of 32bit * just set the lower byte of BitClkDiv + * Because BitClkDiv is 8-bit on mpc5200. Lets stay compatible. */ ccr = in_be16(&psc->ccr); ccr &= 0xFF00; + +#ifdef CONFIG_PPC_MERGE + /* + * pscclk = mclk/(bitclkdiv+1)) bitclkdiv is 8-bit, >= 2 + * mclk = fsys/(mclkdiv+1) mclkdiv is 9-bit, >= 1 + * as mclkdiv has higher precision, we want is as big as possible + * => we get < 0.002*clock error + */ + + system = clk_get_rate(clk_get_parent(mps->clk)); + mclk = speed * (bitclkdiv+1); + if (system/mclk > 512) { /* bigger than mclkdiv */ + bitclkdiv = (system/512) / speed; + mclk = speed * (bitclkdiv+1); + } + + if (clk_set_rate(mps->clk, mclk)) + dev_err(&spi->dev, "couldn't set psc_mclk's rate\n"); + + dev_info(&spi->dev, "clock: wanted: %i, got: %li\n", speed, + clk_round_rate(mps->clk, mclk) / (bitclkdiv+1)); + + ccr |= bitclkdiv; +#else if (cs->speed_hz) ccr |= (MCLK / cs->speed_hz - 1) & 0xFF; else /* by default SPI Clk 1MHz */ ccr |= (MCLK / 1000000 - 1) & 0xFF; +#endif out_be16(&psc->ccr, ccr); mps->bits_per_word = cs->bits_per_word; @@ -321,20 +357,17 @@ static void mpc52xx_psc_spi_cleanup(stru static int mpc52xx_psc_spi_port_config(int psc_id, struct mpc52xx_psc_spi *mps) { + struct mpc52xx_psc __iomem *psc = mps->psc; + int ret = 0; + +#if !defined(CONFIG_PPC_MERGE) struct mpc52xx_cdm __iomem *cdm; struct mpc52xx_gpio __iomem *gpio; - struct mpc52xx_psc __iomem *psc = mps->psc; u32 ul; u32 mclken_div; - int ret = 0; -#if defined(CONFIG_PPC_MERGE) - cdm = mpc52xx_find_and_map("mpc5200-cdm"); - gpio = mpc52xx_find_and_map("mpc5200-gpio"); -#else cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE); gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE); -#endif if (!cdm || !gpio) { printk(KERN_ERR "Error mapping CDM/GPIO\n"); ret = -EFAULT; @@ -390,6 +423,7 @@ static int mpc52xx_psc_spi_port_config(i ret = -EINVAL; goto unmap_regs; } +#endif /* Reset the PSC into a known state */ out_8(&psc->command, MPC52xx_PSC_RST_RX); @@ -413,11 +447,13 @@ static int mpc52xx_psc_spi_port_config(i mps->bits_per_word = 8; +#if !defined(CONFIG_PPC_MERGE) unmap_regs: if (cdm) iounmap(cdm); if (gpio) iounmap(gpio); +#endif return ret; } @@ -502,11 +538,22 @@ static int __init mpc52xx_psc_spi_do_pro ret = spi_register_master(master); if (ret < 0) + goto destr_wq; + +#ifdef CONFIG_PPC_MERGE + mps->clk = clk_get(dev, "psc_mclk"); + if (IS_ERR(mps->clk)) { + dev_err(dev, "couldn't get psc_mclk clock\n"); + ret = -ENOENT; goto unreg_master; + } +#endif return ret; unreg_master: + spi_unregister_master(master); +destr_wq: destroy_workqueue(mps->workqueue); free_irq: free_irq(mps->irq, mps); @@ -523,6 +570,9 @@ static int __exit mpc52xx_psc_spi_do_rem struct spi_master *master = dev_get_drvdata(dev); struct mpc52xx_psc_spi *mps = spi_master_get_devdata(master); +#ifdef CONFIG_PPC_MERGE + clk_put(mps->clk); +#endif flush_workqueue(mps->workqueue); destroy_workqueue(mps->workqueue); spi_unregister_master(master); ^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2007-09-20 14:00 UTC | newest] Thread overview: 20+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2007-07-11 9:31 [PATCH 0/3] clock (clk.h) framework for mpc52xx Domen Puncer 2007-07-11 9:32 ` [PATCH 1/3] powerpc clk.h interface for platforms Domen Puncer 2007-07-11 10:36 ` Christoph Hellwig 2007-07-11 15:56 ` David Brownell 2007-07-11 16:16 ` Christoph Hellwig 2007-07-11 17:02 ` David Brownell 2007-07-11 20:34 ` Russell King 2007-07-11 20:52 ` David Brownell 2007-07-13 9:12 ` Domen Puncer 2007-08-01 7:28 ` Generic clk.h wrappers? [Was: Re: [PATCH 1/3] powerpc clk.h interface for platforms] Domen Puncer 2007-08-01 12:57 ` Christoph Hellwig 2007-08-02 23:32 ` David Brownell 2007-08-03 8:36 ` Russell King 2007-08-06 6:58 ` [PATCH 1/3] powerpc clk.h interface for platforms Domen Puncer 2007-09-19 3:47 ` Paul Mackerras 2007-09-19 5:11 ` Domen Puncer 2007-09-20 5:07 ` Paul Mackerras 2007-09-20 14:00 ` [PATCH 1/3 v2] " Domen Puncer 2007-07-11 9:33 ` [PATCH 2/3] mpc52xx clk.h interface Domen Puncer 2007-07-11 9:34 ` [PATCH 3/3] mpc52xx_psc_spi: use clk.h subsystem Domen Puncer
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).