clk: add DT support for clock gating control
Subsystems (2)
PATCH RESEND 1/1 clk: add DT support for clock gating control
As Rob's clock binding support patch is now up on clk-next, I'd like to draw attention on this patch again.
--
This patch adds support for using clock gates (clk-gate) from DT based on Rob Herrings DT clk binding support for 3.6.
It adds a helper function to clk-gate to allocate all resources required by a set of individual clock gates, i.e. register base address and lock. Each clock gate is described as a child of the clock-gating-control in DT and also created by the helper function.
--- .../bindings/clock/clock-gating-control.txt | 80 +++++++++++++++++++ drivers/clk/clk-gate.c | 84 ++++++++++++++++++++ include/linux/clk-provider.h | 2 + 3 files changed, 166 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/clock-gating-control.txt
(quoted diff) +0 -0
b/Documentation/devicetree/bindings/clock/clock-gating-control.txt new file mode 100644
index 0000000..05f5728
Documentation/devicetree/bindings/clock/clock-gating-control.txt new file +80 -0
80 lines not on this page · raw message
drivers/clk/clk-gate.c +84 -0
91 lines not on this page · raw message
include/linux/clk-provider.h +1 -0
@@ -205,6 +205,8 @@ struct clk *clk_register_gate(struct device *dev, const char *name, void __iomem *reg, u8 bit_idx, u8 clk_gate_flags, spinlock_t *lock); +void of_clock_gating_control_setup(struct device_node *np); +/** * struct clk_divider - adjustable divider clock *
Signature · 6 lines
1.7.10 -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: Attached Message Part URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120712/397fe449/attachment.ksh>
Quoted 61 lines · Sebastian Hesselbarth
As Rob's clock binding support patch is now up on clk-next, I'd like to draw attention on this patch again.
Signature · 32 lines
This patch adds support for using clock gates (clk-gate) from DT based on Rob Herrings DT clk binding support for 3.6. It adds a helper function to clk-gate to allocate all resources required by a set of individual clock gates, i.e. register base address and lock. Each clock gate is described as a child of the clock-gating-control in DT and also created by the helper function. Signed-off-by: Sebastian Hesselbarth <[email protected]> Cc: Grant Likely <[email protected]> Cc: Rob Herring <[email protected]> Cc: Rob Landley <[email protected]> Cc: Mike Turquette <[email protected]> Cc: devicetree-discuss at lists.ozlabs.org Cc: linux-doc at vger.kernel.org Cc: linux-kernel at vger.kernel.org Cc: linux-arm-kernel at lists.infradead.org --- .../bindings/clock/clock-gating-control.txt | 80 +++++++++++++++++++ drivers/clk/clk-gate.c | 84 ++++++++++++++++++++ include/linux/clk-provider.h | 2 + 3 files changed, 166 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/clock-gating-control.txt diff --git a/Documentation/devicetree/bindings/clock/clock-gating-control.txt b/Documentation/devicetree/bindings/clock/clock-gating-control.txt new file mode 100644 index 0000000..05f5728Documentation/devicetree/bindings/clock/clock-gating-control.txt new file +1
-0@@ -0,0 +1,80 @@ +Binding for simple clock gating control based on clock gate registerwith one
+bit per clock gate. This is a clock consumer and also a clock provider for a
+set of gated clocks that are described as children of this node. Each clock gateDocumentation/devicetree/bindings/clock/clock-gating-control.txt new file +17
-0+is described by a bit number and polarity to control the gate. + +This binding uses the common clock binding[1]. + +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt + +==Clock gating control== + +Required properties: +- compatible : shall be "clock-gating-control". +- reg : should contain the register physical address and length for + the clock gating control. +- clocks : shared parent clock for all gated clocks. +- #clock-cells : from common clock binding; shall be set to 0. +- #address-cells : number of cells required to describe a clock gate; + should be <2>. +- #size-cells : should be zero.
Documentation/devicetree/bindings/clock/clock-gating-control.txt line 30
Quoted 10 lines
Documentation/devicetree/bindings/clock/clock-gating-control.txt new file +10
-0+ +Each individual clock gate bit is described as a child of the +corresponding gating control register with the following properties. + +Required child properties: +- reg : should contain the individual bit and polarity to control + the clock gate. A polarity of 0 means that by setting the + bit to 1 the clock passes through the clock gate while + setting the bit to 0 disables the clock. Any other value + for polarity inverts the meaning of the control bit.
This is a bit of overloading reg to specify the polarity.
Quoted 39 lines
Documentation/devicetree/bindings/clock/clock-gating-control.txt new file +39
-0+ +Optional child properties: +- clocks : overrides the shared parent clock for this clock gate + by the clock passed in this property. +- clock-output-names : from common clock binding; allows to set + a specific name for the gated clock output. + +==Example== + + /* fixed root clock */ + osc: oscillator { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <166666667>; + }; + + /* sata peripheral clock */ + sata_clk: ext-oscillator { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + }; + + /* register-based clock gating control */ + gating-control at f10d0038 { + compatible = "clock-gating-control"; + reg = <0xf10d0038 0x4>; + clocks = <&osc>; + #clock-cells = <0>; + #address-cells = <2>; + #size-cells = <0>; + + /* USB0 clock gate on register bit 0 with inverted polarity */ + cg_usb0: clockgate at 0 { + reg = <0 1>; /* register bit 0, inverted polarity */ + }; + + /* PCIe0 clock gate on register bit 1 with normal polarity + * and named output clock */
Documentation/devicetree/bindings/clock/clock-gating-control.txt line 79
Quoted 10 lines
Documentation/devicetree/bindings/clock/clock-gating-control.txt new file +10
-0+ cg_pcie0: clockgate at 1 { + reg = <1 0>; /* register bit 1, normal polarity */ + clock-output-names = "pcie0_clk"; + }; + + /* SATA clock gate with different parent clock */ + cg_sata: clockgate at 3 { + reg = <3 0>; /* register bit 3, normal polarity */ + clocks = <&sata_clk>; + };
I'm not sure I like the node per bit. What about a bit mask for valid bits and polarities. Then add a clock cell to specify the bit or index.
i.MX has 2-bit enable fields for its leaf clocks, so how and if you would support that is something to think about.
Rob
Quoted 113 lines
Documentation/devicetree/bindings/clock/clock-gating-control.txt new file +1
-0+ };drivers/clk/clk-gate.c +9
-0@@ -15,6 +15,9 @@#include <linux/io.h> #include <linux/err.h> #include <linux/string.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_platform.h> /** * DOC: basic gatable clock which can gate and ungate it's ouput @@ -148,3 +151,84 @@ struct clk *clk_register_gate(struct device *dev,const char *name, return clk; } + +#ifdef CONFIG_OF +/** +* of_clock_gating_control_setup() - Setup function for clock gate control +* This is a helper for using clk-gate from OF device tree. It allocates +* a common lock for a base register and creates the individual clk-gates.
+ */drivers/clk/clk-gate.c +74
-0+void __init of_clock_gating_control_setup (struct device_node *np) +{ +struct device_node *child; +const char *pclk_name; +void __iomem *base; +spinlock_t *lockp; +unsigned int rnum; +u64 addr; + + pclk_name =of_clk_get_parent_name (np,0 ); +if (!pclk_name) { +pr_debug ("%s: unable to get parent clock for %s\n" , + __func__, np->full_name); +return ; + } + + lockp =kzalloc (sizeof (spinlock_t),GFP_KERNEL ); +if (!lockp) { +pr_debug ("%s: unable to allocate spinlock for %s\n" , + __func__, np->full_name); +return ; + } + +spin_lock_init (lockp); + base =of_iomap (np,0 ); + rnum =sizeof (resource_size_t) *8 ; + addr =of_translate_address (np,of_get_property (np,"reg" ,NULL )); + +pr_debug ("create clock gate control %s\n" , np->full_name); + +for_each_child_of_node (np, child) { +struct clk *cg; +const char *cg_name; +const char *cg_pclk_name; +u32 propval[2 ]; +unsigned int rbit; + +if (of_property_read_u32_array (child,"reg" , propval,2 )) { +pr_debug ("%s: wrong #reg on %s\n" , + __func__, child->full_name); +continue ; + } + + rbit = propval[0 ]; +if (rbit >= rnum) { +pr_debug ("%s: bit position of %s exceeds resources\n" , + __func__, child->full_name); +continue ; + } + + cg_pclk_name =of_clk_get_parent_name (child,0 ); +if (!pclk_name) + cg_pclk_name = pclk_name; + +if (of_property_read_string (child,"clock-output-names" , + &cg_name)) { +unsigned int nlen =4 +16 +strlen (child->name); +char *name =kzalloc (nlen+1 ,GFP_KERNEL ); +if (!name) +continue ; +snprintf (name, nlen,"%u@%llx.%s" , rbit, + (unsigned long long )addr, child->name); + cg_name = name; + } + +pr_debug (" create clock gate: %s\n" , cg_name); + + cg =clk_register_gate (NULL , cg_name, cg_pclk_name,0 , + base, rbit, propval[1 ], lockp); +if (cg) +of_clk_add_provider (child, of_clk_src_simple_get, cg); + } +} +#endif include/linux/clk-provider.h +1
-0@@ -205,6 +205,8 @@ struct clk *clk_register_gate(struct device *dev,const char *name, void __iomem *reg, u8 bit_idx, u8 clk_gate_flags, spinlock_t *lock); +void of_clock_gating_control_setup(struct device_node *np); +/** * struct clk_divider - adjustable divider clock *
Quoted 8 lines · Rob Herring
Documentation/devicetree/bindings/clock/clock-gating-control.txt line 30
Quoted 6 lines
Documentation/devicetree/bindings/clock/clock-gating-control.txt new file +6
-0+Required child properties: +- reg : should contain the individual bit and polarity to control + the clock gate. A polarity of 0 means that by setting the + bit to 1 the clock passes through the clock gate while + setting the bit to 0 disables the clock. Any other value + for polarity inverts the meaning of the control bit.This is a bit of overloading reg to specify the polarity.
Well, yes it is overloading but still matches reg somehow, as the extra information is required to access the resource. But I agree, expecially wrt more-than-one-bit clk-gate (see below).
Quoted 11 lines
Documentation/devicetree/bindings/clock/clock-gating-control.txt line 79
Quoted 5 lines
Documentation/devicetree/bindings/clock/clock-gating-control.txt new file +5
-0+ /* SATA clock gate with different parent clock */ + cg_sata: clockgate at 3 { + reg =<3 0>; /* register bit 3, normal polarity */ + clocks =<&sata_clk>; + };I'm not sure I like the node per bit. What about a bit mask for valid bits and polarities. Then add a clock cell to specify the bit or index.
i.MX has 2-bit enable fields for its leaf clocks, so how and if you would support that is something to think about.
Yeah, I thought of "what if the clk_gate needs to be enabled with more than 1 bit" already. But this is a short-comming of the current clk-gate implementation.
Just to get it right, i.MX requires to set more than one bit to change the state of the gate for one leaf clock?
If this is true, that would require a change of the generic clk-gate anyway.
I had a look at pinctrl-bindings.txt maybe this is the way to go for clock gating control, too. That would require clk-gate to handle an 'active' and 'gated' state and leave it to a clock gate control to actually set the required bits in any registers. This would allow other special implementations of clock gating controllers to reuse clk-gate DT description. Additionally, there could be a simple-clock-gating-control that can set states by reg address and for each controlled gate a mask, enable value, and disable value.
Sebastian
Quoted 8 lines · Sebastian Hesselbarh
Quoted 7 lines · Rob Herring
Quoted 6 lines
Documentation/devicetree/bindings/clock/clock-gating-control.txt new file +6
-0+Required child properties: +- reg : should contain the individual bit and polarity to control + the clock gate. A polarity of 0 means that by setting the + bit to 1 the clock passes through the clock gate while + setting the bit to 0 disables the clock. Any other value + for polarity inverts the meaning of the control bit.
Quoted 6 lines
Quoted 1 line
This is a bit of overloading reg to specify the polarity.
Well, yes it is overloading but still matches reg somehow, as the extra information is required to access the resource. But I agree, expecially wrt more-than-one-bit clk-gate (see below).
You can define your own property names.
Quoted 9 lines
Quoted 9 lines
Documentation/devicetree/bindings/clock/clock-gating-control.txt line 79
Quoted 5 lines
Documentation/devicetree/bindings/clock/clock-gating-control.txt new file +5
-0+ /* SATA clock gate with different parent clock */ + cg_sata: clockgate at 3 { + reg =<3 0>; /* register bit 3, normal polarity */ + clocks =<&sata_clk>; + };I'm not sure I like the node per bit. What about a bit mask for valid bits and polarities. Then add a clock cell to specify the bit or index.
Quoted 6 lines
Quoted 2 lines
i.MX has 2-bit enable fields for its leaf clocks, so how and if you would support that is something to think about.
Yeah, I thought of "what if the
clk_gateneeds to be enabled with more than 1 bit" already. But this is a short-comming of the current clk-gate implementation.
What's implemented in Linux should not define the binding. The binding should describe the hardware.
Quoted 2 lines
Just to get it right, i.MX requires to set more than one bit to change the state of the gate for one leaf clock?
It's basically ON, OFF, and "ON in run/OFF in wfi".
Perhaps the iMX case is unique enough we don't try to make it use a common binding.
Quoted 2 lines
If this is true, that would require a change of the generic clk-gate anyway.
True, but not your problem to implement. A binding doesn't necessarily mean there is a full Linux implementation. We just don't want to create something only to find others need something completely different.
Rob
Quoted 10 lines
I had a look at pinctrl-bindings.txt maybe this is the way to go for clock gating control, too. That would require clk-gate to handle an 'active' and 'gated' state and leave it to a clock gate control to actually set the required bits in any registers. This would allow other special implementations of clock gating controllers to reuse clk-gate DT description. Additionally, there could be a simple-clock-gating-control that can set states by reg address and for each controlled gate a mask, enable value, and disable value.
Sebastian
Quoted 6 lines · Rob Herring
What's implemented in Linux should not define the binding. The binding should describe the hardware.
[...]
True, but not your problem to implement. A binding doesn't necessarily mean there is a full Linux implementation. We just don't want to create something only to find others need something completely different.
Ok, what about a DT describing the following for a simple register-based clock gating controller and the corresponding gated-clock independent of the controller. I am sure there are a bunch of SoCs out there that control their clock gates by writing some bits to a register. If that DT description matches your expectations, I ll prepare patches with documentation and implementation for common clock framework.
Sebastian
--
/* Simple clock gating controller based on bitmasks and register */
cgc: clock-gating-control at f1000000 {
compatible = "clock-gating-control-register";
reg = <0xf1000000 0x4>;
/* Clock gating control with one bit at bit position 0
enable with (1<<0), disable with (0<<0) */
cgctrl_usb0: cgc_usb0 {
clock-gating-control,shift = <0>;
clock-gating-control,mask = <1>;
clock-gating-control,enable = <1>;
clock-gating-control,disable = <0>;
};/* Clock gating control with two bits at bit position 1-2
enable with (2<<1), disable with (0<<1) */
cgctrl_sata: cgc_sata {
clock-gating-control,shift = <1>;
clock-gating-control,mask = <3>;
clock-gating-control,enable = <2>;
clock-gating-control,disable = <0>; };
};
/* Generic clock gate description that can be used with
any clock gating controller */cg_usb0: clockgate at 0 {
compatible = "gated-clock";
#clock-cells = <0>;
clocks = <&osc>;
clock-gate-control = <&cgctrl_usb0>;
};
Quoted 8 lines · Sebastian Hesselbarh
Quoted 6 lines · Rob Herring
What's implemented in Linux should not define the binding. The binding should describe the hardware.
[...]
True, but not your problem to implement. A binding doesn't necessarily mean there is a full Linux implementation. We just don't want to create something only to find others need something completely different.
Quoted 7 lines
Ok, what about a DT describing the following for a simple register-based clock gating controller and the corresponding gated-clock independent of the controller. I am sure there are a bunch of SoCs out there that control their clock gates by writing some bits to a register. If that DT description matches your expectations, I ll prepare patches with documentation and implementation for common clock framework.
Clock gates are just 1 part. There's muxes, dividers, plls, etc. I'm not convinced that it makes sense to define clocks at this level. For complex chips, I think just defining the chips clock controller module as a single node with lots of clock outputs. The primary need is to describe board specific changes not SOC level clock tree. Much of it is static and generally only a few clocks may change config board to board.
Quoted 35 lines
Sebastian
Signature · 32 lines
/* Simple clock gating controller based on bitmasks and register */ cgc: clock-gating-control at f1000000 { compatible = "clock-gating-control-register"; reg = <0xf1000000 0x4>; /* Clock gating control with one bit at bit position 0 enable with (1<<0), disable with (0<<0) */ cgctrl_usb0: cgc_usb0 { clock-gating-control,shift = <0>; clock-gating-control,mask = <1>; clock-gating-control,enable = <1>; clock-gating-control,disable = <0>; }; /* Clock gating control with two bits at bit position 1-2 enable with (2<<1), disable with (0<<1) */ cgctrl_sata: cgc_sata { clock-gating-control,shift = <1>; clock-gating-control,mask = <3>; clock-gating-control,enable = <2>; clock-gating-control,disable = <0>; }; }; /* Generic clock gate description that can be used with any clock gating controller */ cg_usb0: clockgate at 0 { compatible = "gated-clock"; #clock-cells = <0>; clocks = <&osc>; clock-gate-control = <&cgctrl_usb0>; };
I don't see this scaling to ~50 clocks.
Rob
I believe clock anything is Thomas Gleixner, just making sure he's seen it...
Rob
Quoted 51 lines · Sebastian Hesselbarh
Quoted 6 lines · Rob Herring
What's implemented in Linux should not define the binding. The binding should describe the hardware.
[...]
True, but not your problem to implement. A binding doesn't necessarily mean there is a full Linux implementation. We just don't want to create something only to find others need something completely different.Ok, what about a DT describing the following for a simple register-based clock gating controller and the corresponding gated-clock independent of the controller. I am sure there are a bunch of SoCs out there that control their clock gates by writing some bits to a register. If that DT description matches your expectations, I ll prepare patches with documentation and implementation for common clock framework.
Sebastian
Signature · 32 lines
/* Simple clock gating controller based on bitmasks and register */ cgc: clock-gating-control at f1000000 { compatible = "clock-gating-control-register"; reg = <0xf1000000 0x4>; /* Clock gating control with one bit at bit position 0 enable with (1<<0), disable with (0<<0) */ cgctrl_usb0: cgc_usb0 { clock-gating-control,shift = <0>; clock-gating-control,mask = <1>; clock-gating-control,enable = <1>; clock-gating-control,disable = <0>; }; /* Clock gating control with two bits at bit position 1-2 enable with (2<<1), disable with (0<<1) */ cgctrl_sata: cgc_sata { clock-gating-control,shift = <1>; clock-gating-control,mask = <3>; clock-gating-control,enable = <2>; clock-gating-control,disable = <0>; }; }; /* Generic clock gate description that can be used with any clock gating controller */ cg_usb0: clockgate at 0 { compatible = "gated-clock"; #clock-cells = <0>; clocks = <&osc>; clock-gate-control = <&cgctrl_usb0>; };
Signature · 2 lines
GNU/Linux isn't: Linux=GPLv2, GNU=GPLv3+, they can't share code. Either it's "mere aggregation", or a license violation. Pick one.