clock (clk.h) framework for mpc52xx
Subsystems (4)
cover clock (clk.h) framework for mpc52xx
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
PATCH 1/3 powerpc clk.h interface for platforms
clk interface for arch/powerpc, platforms should fill clk_functions.
--- 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(-)
arch/powerpc/kernel/clock.c new file +82 -0
@@ -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);
include/asm-powerpc/clk_interface.h new file +20 -0
@@ -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 */
arch/powerpc/kernel/Makefile +2 -1
@@ -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 \
Re: [PATCH 1/3] powerpc clk.h interface for platforms
Quoted 2 lines · Domen Puncer
clk interface for
arch/powerpc, platforms should fillclk_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.
Re: [PATCH 1/3] powerpc clk.h interface for platforms
Quoted 8 lines · Christoph Hellwig
Quoted 2 lines · Domen Puncer
clk interface for
arch/powerpc, platforms should fillclk_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
Re: [PATCH 1/3] powerpc clk.h interface for platforms
Quoted 6 lines · David Brownell
Quoted 4 lines
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.ccore, 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?
Re: [PATCH 1/3] powerpc clk.h interface for platforms
Quoted 10 lines · Christoph Hellwig
Quoted 6 lines · David Brownell
Quoted 4 lines
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.ccore, 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.
Quoted 1 line
What would a
lib/clock.cdo?
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
Re: [PATCH 1/3] powerpc clk.h interface for platforms
Quoted 12 lines · David Brownell
Quoted 10 lines · Christoph Hellwig
Quoted 6 lines · David Brownell
Quoted 4 lines
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.ccore, rather than an opsvector?I mean an ops vector and surrounding wrappers. Every architecture is reimplementing their own dispatch table which is rather annoying.
Quoted 8 lines
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.
Quoted 3 lines
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.
Signature · 3 lines
Russell King Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/ maintainer of:
Re: [PATCH 1/3] powerpc clk.h interface for platforms
Quoted 2 lines · Russell King
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
Re: [PATCH 1/3] powerpc clk.h interface for platforms
In reply to Russell KingQuoted 29 lines · Russell King
Quoted 12 lines · David Brownell
Quoted 10 lines · Christoph Hellwig
Quoted 6 lines · David Brownell
Quoted 4 lines
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.ccore, rather than an opsvector?I mean an ops vector and surrounding wrappers. Every architecture is reimplementing their own dispatch table which is rather annoying.
Quoted 8 lines
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()andclk_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.
Quoted 4 lines
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.
Quoted 10 lines
Quoted 4 lines
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
Quoted 7 lines
IOW, talk to me and I'll talk back. Ignore me and I'll ignore them.
Signature · 3 lines
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.
--- 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(-)
arch/powerpc/kernel/clock.c new file +82 -0
@@ -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);
include/asm-powerpc/clk_interface.h new file +20 -0
@@ -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 */
arch/powerpc/kernel/Makefile +2 -1
@@ -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 \
Generic clk.h wrappers? [Was: Re: [PATCH 1/3] powerpc clk.h interface for platforms]
Quoted 35 lines · Domen Puncer
Quoted 29 lines · Russell King
Quoted 12 lines · David Brownell
Quoted 10 lines · Christoph Hellwig
Quoted 6 lines · David Brownell
Quoted 4 lines
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.ccore, rather than an opsvector?I mean an ops vector and surrounding wrappers. Every architecture is reimplementing their own dispatch table which is rather annoying.
Quoted 8 lines
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()andclk_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.Quoted 4 lines
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.
Quoted 5 lines
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, sincearch/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
Re: Generic clk.h wrappers? [Was: Re: [PATCH 1/3] powerpc clk.h interface for platforms]
Quoted 5 lines · Domen Puncer
Quoted 4 lines
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, sincearch/powerpc/can support multiple platfroms in one binary.
Quoted 8 lines
So... the thread just ended without any consensus, ACK or whatever.
Choices I see:
- haveEXPORT_SYMBOLforclk.hfunctions in ie.lib/clock.cand have every implemenation fill some global struct.
- leave this patch as it is, abstraction only forarch/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.
Re: Generic clk.h wrappers? [Was: Re: [PATCH 1/3] powerpc clk.h interface for platforms]
Quoted 6 lines · Christoph Hellwig
Quoted 5 lines · Domen Puncer
Quoted 4 lines
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, sincearch/powerpc/can support multiple platfroms in one binary.
Quoted 6 lines
Quoted 6 lines
So... the thread just ended without any consensus, ACK or whatever.
Choices I see:
- haveEXPORT_SYMBOLforclk.hfunctions in ie.lib/clock.cand have every implemenation fill some global struct.
- leave this patch as it is, abstraction only forarch/powerpc/.
That seems the best solution for now, I agree.
Quoted 12 lines
Quoted 2 lines
- 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.
Re: Generic clk.h wrappers? [Was: Re: [PATCH 1/3] powerpc clk.h interface for platforms]
Quoted 7 lines · David Brownell
Quoted 6 lines · Christoph Hellwig
Quoted 5 lines · Domen Puncer
Quoted 4 lines
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, sincearch/powerpc/can support multiple platfroms in one binary.
Quoted 8 lines
Quoted 6 lines
Quoted 6 lines
So... the thread just ended without any consensus, ACK or whatever.
Choices I see:
- haveEXPORT_SYMBOLforclk.hfunctions in ie.lib/clock.cand have every implemenation fill some global struct.
- leave this patch as it is, abstraction only forarch/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.
Signature · 3 lines
Russell King Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/ maintainer of:
Re: [PATCH 1/3] powerpc clk.h interface for platforms
In reply to Domen PuncerHi!
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
Quoted 141 lines · Domen Puncer
clk interface for
arch/powerpc, platforms should fillclk_functions.Signed-off-by Domen Puncer <[email protected]>--- 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
===================================================================arch/powerpc/kernel/clock.c new file +82
-0@@ -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
===================================================================include/asm-powerpc/clk_interface.h new file +20
-0@@ -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
===================================================================arch/powerpc/kernel/Makefile +2
-1@@ -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
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-dev
Re: [PATCH 1/3] powerpc clk.h interface for platforms
Quoted 3 lines · Domen Puncer
Paul, what do you say about this?
Sylvain suggested it could also be integrated withdefine_machineinterface.
As it stands, your patch adds the clk_* functions on all platforms. What platforms would actually want to use them?
Paul.
Re: [PATCH 1/3] powerpc clk.h interface for platforms
Quoted 8 lines · Paul Mackerras
Quoted 3 lines · Domen Puncer
Paul, what do you say about this?
Sylvain suggested it could also be integrated withdefine_machineinterface.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
Quoted 2 lines
Paul.
Re: [PATCH 1/3] powerpc clk.h interface for platforms
Quoted 3 lines · Domen Puncer
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.
PATCH v2 1/3 powerpc clk.h interface for platforms
clk interface for arch/powerpc, platforms should fill clk_functions.
---
Quoted 8 lines · Paul Mackerras
Quoted 3 lines · Domen Puncer
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!
Quoted 2 lines
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(+)
arch/powerpc/kernel/clock.c new file +82 -0
@@ -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);
include/asm-powerpc/clk_interface.h new file +20 -0
@@ -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 */
arch/powerpc/kernel/Makefile +1 -0
@@ -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
arch/powerpc/Kconfig +4 -0
@@ -664,3 +664,7 @@ config KEYS_COMPAT default y source "crypto/Kconfig" + +config PPC_CLOCK + bool + default n
arch/powerpc/platforms/52xx/Kconfig +1 -0
@@ -1,6 +1,7 @@ config PPC_MPC52xx bool select FSL_SOC + select PPC_CLOCK default n config PPC_MPC5200
PATCH 2/3 mpc52xx clk.h interface
In reply to Domen Puncerclk.h interface for mpc52xx
Currently only psc_mclks are defined.
--- 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(-)
arch/powerpc/platforms/52xx/Makefile +1 -1
@@ -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
arch/powerpc/platforms/52xx/mpc52xx_clock.c new file +352 -0
352 lines not on this page · raw message
arch/powerpc/platforms/52xx/mpc52xx_common.c +3 -0
@@ -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);
include/asm-powerpc/mpc52xx.h +2 -0
@@ -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__ */
PATCH 3/3 mpc52xx_psc_spi: use clk.h subsystem
In reply to Domen PuncerUse clocks subsystem in spi driver.
--- drivers/spi/mpc52xx_psc_spi.c | 64 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 7 deletions(-)
drivers/spi/mpc52xx_psc_spi.c +57 -7
@@ -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(strustatic 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_remstruct 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);