Skip to contentSkip to conversation

clk: add DT support for clock gating control

PATCH RESEND In review Sebastian Hesselbarth 3 participants 7 messages Jul 12, 2012 – Jul 15, 2012

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

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.

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

(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
index b97f61e..499eac2 100644
@@ -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>
#1 lore raw
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..05f5728
Documentation/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 register

with 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 gate

Documentation/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
index 578465e..1e88907 100644
@@ -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
index b97f61e..499eac2 100644
@@ -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
  *
#2 lore raw
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

#3 lore raw
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_gate needs 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

#4 lore raw
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>;
};

#5 lore raw
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

#6 lore raw
In reply to Sebastian Hesselbarh

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.