Skip to contentSkip to conversation

clk: Add brcm,bcm6345-gate-clk device tree binding

PATCH In review Simon Arlott 3 participants 5 messages Dec 10, 2015 – Jan 1, 2016

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

PATCH 1/2 clk: Add brcm,bcm6345-gate-clk device tree binding

Add device tree binding for the BCM6345's gated clocks.

The BCM6345 contains clocks gated with a register. Clocks are indexed by bits in the register and are active high. Most MIPS-based BCM63xx SoCs have a clock gating set of registers, but some have clock gate bits interleaved with other status bits and configurable clocks in the same register.

---
v2: Added clock-indices, clock-output-names (from clock-bindings.txt),
these are required properties.

v1: Renamed from BCM63xx to BCM6345.

 .../bindings/clock/brcm,bcm6345-gate-clk.txt       | 62 ++++++++++++++++++++++
 1 file changed, 62 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/brcm,bcm6345-gate-clk.txt
Documentation/devicetree/bindings/clock/brcm,bcm6345-gate-clk.txt new file +62 -0
new file mode 100644
index 0000000..a6e264c
@@ -0,0 +1,62 @@
+Broadcom BCM6345 clocks
+
+This binding uses the common clock binding:
+	Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+The BCM6345 contains clocks gated with a register. Clocks are indexed
+by bits in the register and are active high. Most MIPS-based BCM63xx
+SoCs have a clock gating set of registers, but some have clock gate bits
+interleaved with other status bits and configurable clocks in the same
+register.
+
+Required properties:
+- compatible:         Should be "brcm,bcm<soc>-gate-clk", "brcm,bcm6345-gate-clk"
+- #clock-cells:       Should be <1>.
+- regmap:             The register map phandle
+- offset:             Offset in the register map for the clock register (in bytes)
+- clocks:             The external oscillator clock phandle
+- clock-indices:      The bits in the register used for gated clocks.
+- clock-output-names: Should be a list of strings of clock output signal
+                      names indexed by the clock indices.
+
+Example:
+
+periph_clk: periph_clk {
+	compatible = "brcm,bcm63168-gate-clk", "brcm,bcm6345-gate-clk";
+	regmap = <&periph_cntl>;
+	offset = <0x4>;
+
+	#clock-cells = <1>;
+	clock-indices =
+		<1>,          <2>,        <3>,       <4>,     <5>,
+		<6>,          <7>,        <8>,       <9>,     <10>,
+		<11>,         <12>,       <13>,      <14>,    <15>,
+		<16>,         <17>,       <18>,      <19>,    <20>,
+		<27>,         <31>;
+	clock-output-names =
+		"vdsl_qproc", "vdsl_afe", "vdsl",    "mips",  "wlan_ocp",
+		"dect",       "fap0",     "fap1",    "sar",   "robosw",
+		"pcm",        "usbd",     "usbh",    "ipsec", "spi",
+		"hsspi",      "pcie",     "phymips", "gmac",  "nand",
+		"tbus",       "robosw250";
+};
+
+timer_clk: timer_clk {
+	compatible = "brcm,bcm63168-gate-clk", "brcm,bcm6345-gate-clk";
+	regmap = <&timer_cntl>;
+	offset = <0x4>;
+
+	#clock-cells = <1>;
+	clock-indices = <17>, <18>;
+	clock-output-names = "uto_extin", "usb_ref";
+};
+
+ehci0: usb@10002500 {
+	compatible = "brcm,bcm63168-ehci", "brcm,bcm6345-ehci", "generic-ehci";
+	reg = <0x10002500 0x100>;
+	big-endian;
+	interrupt-parent = <&periph_intc>;
+	interrupts = <10>;
+	clocks = <&periph_clk 13>, <&timer_clk 18>;
+	phys = <&usbh>;
+};
Signature · 4 lines
2.1.4

-- 
Simon Arlott
#1 lore raw

PATCH 2/2 clk: bcm6345: Add BCM6345 gated clock support

The BCM6345 contains clocks gated with a register. Clocks are indexed by bits in the register and are active high. Most MIPS-based BCM63xx SoCs have a clock gating set of registers, but some have clock gate bits interleaved with other status bits and configurable clocks in the same register.

Enabled by default for BMIPS_GENERIC.

---
v2: Resend, no changes.

v1: Renamed from BCM63xx to BCM6345.

 MAINTAINERS                   |   1 +
 drivers/clk/bcm/Kconfig       |   9 ++
 drivers/clk/bcm/Makefile      |   1 +
 drivers/clk/bcm/clk-bcm6345.c | 191 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 202 insertions(+)
 create mode 100644 drivers/clk/bcm/clk-bcm6345.c
MAINTAINERS +1 -0
index 5ac17b0..9b54ddc 100644
@@ -2389,6 +2389,7 @@ F:	arch/mips/bmips/*
 F:	arch/mips/include/asm/mach-bmips/*
 F:	arch/mips/kernel/*bmips*
 F:	arch/mips/boot/dts/brcm/bcm*.dts*
+F:	drivers/clk/bcm/clk-bcm6345*
 F:	drivers/irqchip/irq-bcm63*
 F:	drivers/irqchip/irq-bcm7*
 F:	drivers/irqchip/irq-brcmstb*
drivers/clk/bcm/Kconfig +9 -0
index f287845..043353a 100644
@@ -8,6 +8,15 @@ config CLK_BCM_63XX
 	  Enable common clock framework support for Broadcom BCM63xx DSL SoCs
 	  based on the ARM architecture
 
+config CLK_BCM_6345
+	bool "Broadcom BCM6345 clock support"
+	depends on BMIPS_GENERIC || COMPILE_TEST
+	depends on COMMON_CLK
+	default BMIPS_GENERIC
+	help
+	  Enable common clock framework support for Broadcom BCM6345 DSL SoCs
+	  based on the MIPS architecture
+
 config CLK_BCM_KONA
 	bool "Broadcom Kona CCU clock support"
 	depends on ARCH_BCM_MOBILE || COMPILE_TEST
drivers/clk/bcm/Makefile +1 -0
index 247c267..e2bac43 100644
@@ -1,4 +1,5 @@
 obj-$(CONFIG_CLK_BCM_63XX)	+= clk-bcm63xx.o
+obj-$(CONFIG_CLK_BCM_6345)	+= clk-bcm6345.o
 obj-$(CONFIG_CLK_BCM_KONA)	+= clk-kona.o
 obj-$(CONFIG_CLK_BCM_KONA)	+= clk-kona-setup.o
 obj-$(CONFIG_CLK_BCM_KONA)	+= clk-bcm281xx.o
drivers/clk/bcm/clk-bcm6345.c new file +191 -0

191 lines not on this page · raw message

Signature · 4 lines
2.1.4

-- 
Simon Arlott
#2 lore raw

Re: [PATCH linux-next (v2) 2/2] clk: bcm6345: Add BCM6345 gated clock support

Hi Simon,

Quoting Simon Arlott (2015-12-10 13:50:59)

drivers/clk/bcm/clk-bcm6345.c line 55

Quoted 8 lines
drivers/clk/bcm/clk-bcm6345.c new file +8 -0
+#define to_clk_bcm6345(_hw) container_of(_hw, struct clk_bcm6345, hw)
+
+static int clk_bcm6345_enable(struct clk_hw *hw)
+{
+       struct clk_bcm6345 *gate =3D to_clk_bcm6345(hw);
+
+       return regmap_write_bits(gate->map, gate->offset,
+                                       gate->mask, gate->mask);

Does your regmap hold a spinlock or mutex? If a mutex then this should be a .prepare callback instead of .enable. If it's a spinlock then nothing to see here, move along.

Quoted 22 lines
drivers/clk/bcm/clk-bcm6345.c new file +22 -0
+}
+
+static void clk_bcm6345_disable(struct clk_hw *hw)
+{
+       struct clk_bcm6345 *gate =3D to_clk_bcm6345(hw);
+
+       regmap_write_bits(gate->map, gate->offset,
+                                       gate->mask, 0);
+}
+
+static int clk_bcm6345_is_enabled(struct clk_hw *hw)
+{
+       struct clk_bcm6345 *gate =3D to_clk_bcm6345(hw);
+       unsigned int val;
+       int ret;
+
+       ret =3D regmap_read(gate->map, gate->offset, &val);
+       if (ret)
+               return ret;
+
+       val &=3D gate->mask;
+

drivers/clk/bcm/clk-bcm6345.c

Quoted 10 lines
drivers/clk/bcm/clk-bcm6345.c new file +10 -0
+       return val ? 1 : 0;
+}
+
+const struct clk_ops clk_bcm6345_ops =3D {
+       .enable =3D clk_bcm6345_enable,
+       .disable =3D clk_bcm6345_disable,
+       .is_enabled =3D clk_bcm6345_is_enabled,
+};
+
+static struct clk * __init of_bcm6345_clk_register(const char *parent_na=

me,

drivers/clk/bcm/clk-bcm6345.c

Quoted 13 lines
drivers/clk/bcm/clk-bcm6345.c new file +13 -0
+       const char *clk_name, struct regmap *map, u32 offset, u32 mask)
+{
+       struct clk_bcm6345 *gate;
+       struct clk_init_data init;
+       struct clk *ret;
+
+       gate =3D kzalloc(sizeof(*gate), GFP_KERNEL);
+       if (!gate)
+               return ERR_PTR(-ENOMEM);
+
+       init.name =3D clk_name;
+       init.ops =3D &clk_bcm6345_ops;
+       init.flags =3D CLK_IS_BASIC;

Why is CLK_IS_BASIC set?

Quoted 40 lines
drivers/clk/bcm/clk-bcm6345.c new file +40 -0
+       init.parent_names =3D (parent_name ? &parent_name : NULL);
+       init.num_parents =3D (parent_name ? 1 : 0);
+       gate->hw.init =3D &init;
+       gate->map =3D map;
+       gate->offset =3D offset;
+       gate->mask =3D mask;
+
+       ret =3D clk_register(NULL, &gate->hw);
+       if (IS_ERR(ret))
+               kfree(gate);
+
+       return ret;
+}
+
+static void __init of_bcm6345_clk_setup(struct device_node *node)
+{
+       struct clk_onecell_data *clk_data;
+       const char *parent_name =3D NULL;
+       struct regmap *map;
+       u32 offset;
+       unsigned int clocks =3D 0;
+       int i;
+
+       clk_data =3D kzalloc(sizeof(*clk_data), GFP_KERNEL);
+       if (!clk_data)
+               return;
+
+       clk_data->clk_num =3D 32;
+       clk_data->clks =3D kmalloc_array(clk_data->clk_num,
+               sizeof(*clk_data->clks), GFP_KERNEL);
+
+       for (i =3D 0; i < clk_data->clk_num; i++)
+               clk_data->clks[i] =3D ERR_PTR(-ENODEV);
+
+       if (of_clk_get_parent_count(node) > 0)
+               parent_name =3D of_clk_get_parent_name(node, 0);
+
+       map =3D syscon_regmap_lookup_by_phandle(node, "regmap");
+       if (IS_ERR(map)) {
+               pr_err("%s: regmap lookup error %ld\n",

drivers/clk/bcm/clk-bcm6345.c

Quoted 10 lines
drivers/clk/bcm/clk-bcm6345.c new file +10 -0
+                       node->full_name, PTR_ERR(map));
+               goto out;
+       }
+
+       if (of_property_read_u32(node, "offset", &offset)) {
+               pr_err("%s: offset not specified\n", node->full_name);
+               goto out;
+       }
+
+       /* clks[] is sparse, indexed by bit, maximum clocks checked using=

i */

drivers/clk/bcm/clk-bcm6345.c

Quoted 9 lines
drivers/clk/bcm/clk-bcm6345.c new file +9 -0
+       for (i =3D 0; i < clk_data->clk_num; i++) {
+               u32 bit;
+               const char *clk_name;
+
+               if (of_property_read_u32_index(node, "clock-indices",
+                               i, &bit))
+                       goto out;
+
+               if (of_property_read_string_index(node, "clock-output-nam=

es",

Quoted 6 lines
drivers/clk/bcm/clk-bcm6345.c new file +6 -0
+                               i, &clk_name))
+                       goto out;
+
+               if (bit >=3D clk_data->clk_num) {
+                       pr_err("%s: clock bit %u out of range\n",
+                               node->full_name, bit);

drivers/clk/bcm/clk-bcm6345.c

Quoted 10 lines
drivers/clk/bcm/clk-bcm6345.c new file +10 -0
+                       continue;
+               }
+
+               if (!IS_ERR(clk_data->clks[bit])) {
+                       pr_err("%s: clock bit %u already exists\n",
+                               node->full_name, bit);
+                       continue;
+               }
+
+               clk_data->clks[bit] =3D of_bcm6345_clk_register(parent_na=

me,

drivers/clk/bcm/clk-bcm6345.c

Quoted 8 lines
drivers/clk/bcm/clk-bcm6345.c new file +8 -0
+                                       clk_name, map, offset, BIT(bit));
+               if (!IS_ERR(clk_data->clks[bit]))
+                       clocks++;
+       }
+
+out:
+       if (clocks) {
+               of_clk_add_provider(node, of_clk_src_onecell_get, clk_dat=

a);

drivers/clk/bcm/clk-bcm6345.c

Quoted 8 lines
drivers/clk/bcm/clk-bcm6345.c new file +8 -0
+               pr_info("%s: registered %u clocks\n", node->name, clocks);
+       } else {
+               kfree(clk_data->clks);
+               kfree(clk_data);
+       }
+}
+
+CLK_OF_DECLARE(bcm6345_clk, "brcm,bcm6345-gate-clk", of_bcm6345_clk_setu=

p);

Please do not use CLK_OF_DECLARE unless there is a good reason. Ideally this should be a platform_driver.

Regards,
Mike

Quoted 8 lines

-- =

2.1.4
=

-- =

Simon Arlott

maintainer Acked-by on v1 1/2
#3 lore raw
In reply to Simon Arlott
Quoted 9 lines · Simon Arlott

Add device tree binding for the BCM6345's gated clocks.

The BCM6345 contains clocks gated with a register. Clocks are indexed by bits in the register and are active high. Most MIPS-based BCM63xx SoCs have a clock gating set of registers, but some have clock gate bits interleaved with other status bits and configurable clocks in the same register.

Quoted 83 lines

---
v2: Added clock-indices, clock-output-names (from clock-bindings.txt),
these are required properties.

v1: Renamed from BCM63xx to BCM6345.

 .../bindings/clock/brcm,bcm6345-gate-clk.txt       | 62 ++++++++++++++++++++++
 1 file changed, 62 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/brcm,bcm6345-gate-clk.txt
Documentation/devicetree/bindings/clock/brcm,bcm6345-gate-clk.txt new file +62 -0
new file mode 100644
index 0000000..a6e264c
@@ -0,0 +1,62 @@
+Broadcom BCM6345 clocks
+
+This binding uses the common clock binding:
+	Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+The BCM6345 contains clocks gated with a register. Clocks are indexed
+by bits in the register and are active high. Most MIPS-based BCM63xx
+SoCs have a clock gating set of registers, but some have clock gate bits
+interleaved with other status bits and configurable clocks in the same
+register.
+
+Required properties:
+- compatible:         Should be "brcm,bcm<soc>-gate-clk", "brcm,bcm6345-gate-clk"
+- #clock-cells:       Should be <1>.
+- regmap:             The register map phandle
+- offset:             Offset in the register map for the clock register (in bytes)
+- clocks:             The external oscillator clock phandle
+- clock-indices:      The bits in the register used for gated clocks.
+- clock-output-names: Should be a list of strings of clock output signal
+                      names indexed by the clock indices.
+
+Example:
+
+periph_clk: periph_clk {
+	compatible = "brcm,bcm63168-gate-clk", "brcm,bcm6345-gate-clk";
+	regmap = <&periph_cntl>;
+	offset = <0x4>;
+
+	#clock-cells = <1>;
+	clock-indices =
+		<1>,          <2>,        <3>,       <4>,     <5>,
+		<6>,          <7>,        <8>,       <9>,     <10>,
+		<11>,         <12>,       <13>,      <14>,    <15>,
+		<16>,         <17>,       <18>,      <19>,    <20>,
+		<27>,         <31>;
+	clock-output-names =
+		"vdsl_qproc", "vdsl_afe", "vdsl",    "mips",  "wlan_ocp",
+		"dect",       "fap0",     "fap1",    "sar",   "robosw",
+		"pcm",        "usbd",     "usbh",    "ipsec", "spi",
+		"hsspi",      "pcie",     "phymips", "gmac",  "nand",
+		"tbus",       "robosw250";
+};
+
+timer_clk: timer_clk {
+	compatible = "brcm,bcm63168-gate-clk", "brcm,bcm6345-gate-clk";
+	regmap = <&timer_cntl>;
+	offset = <0x4>;
+
+	#clock-cells = <1>;
+	clock-indices = <17>, <18>;
+	clock-output-names = "uto_extin", "usb_ref";
+};
+
+ehci0: usb@10002500 {
+	compatible = "brcm,bcm63168-ehci", "brcm,bcm6345-ehci", "generic-ehci";
+	reg = <0x10002500 0x100>;
+	big-endian;
+	interrupt-parent = <&periph_intc>;
+	interrupts = <10>;
+	clocks = <&periph_clk 13>, <&timer_clk 18>;
+	phys = <&usbh>;
+};
Signature · 4 lines
2.1.4

-- 
Simon Arlott
#4 lore raw

Re: [PATCH linux-next (v2) 1/2] clk: Add brcm, bcm6345-gate-clk device tree binding

In reply to Simon Arlott

Hi Simon,

Quoting Simon Arlott (2015-12-10 13:49:21)

Quoted 8 lines
Documentation/devicetree/bindings/clock/brcm,bcm6345-gate-clk.txt new file +8 -0
+periph_clk: periph_clk {
+       compatible =3D "brcm,bcm63168-gate-clk", "brcm,bcm6345-gate-clk";
+       regmap =3D <&periph_cntl>;
+       offset =3D <0x4>;
+
+       #clock-cells =3D <1>;
+       clock-indices =3D
+               <1>,          <2>,        <3>,       <4>,     <5>,

Documentation/devicetree/bindings/clock/brcm,bcm6345-gate-clk.txt line 41

Quoted 10 lines
Documentation/devicetree/bindings/clock/brcm,bcm6345-gate-clk.txt new file +10 -0
+               <6>,          <7>,        <8>,       <9>,     <10>,
+               <11>,         <12>,       <13>,      <14>,    <15>,
+               <16>,         <17>,       <18>,      <19>,    <20>,
+               <27>,         <31>;
+       clock-output-names =3D
+               "vdsl_qproc", "vdsl_afe", "vdsl",    "mips",  "wlan_ocp",
+               "dect",       "fap0",     "fap1",    "sar",   "robosw",
+               "pcm",        "usbd",     "usbh",    "ipsec", "spi",
+               "hsspi",      "pcie",     "phymips", "gmac",  "nand",
+               "tbus",       "robosw250";

Why is clock-output-names required? Because you don't have any clock data in your driver? Or is there another reason?

FYI, I'm not a fan of clock-output-names, and prefer for the clk consumer devices to specify the clock-names property.

Another question, is it correct that this binding requires a DT node for every register that contains clock control bits? If so, I'm skeptical of that approach. What if you have a clock controller IP block on a future soc that has several registers worth of clock controls?

Regards,
Mike

Quoted 4 lines
Documentation/devicetree/bindings/clock/brcm,bcm6345-gate-clk.txt new file +4 -0
+};
+
+timer_clk: timer_clk {
+       compatible =3D "brcm,bcm63168-gate-clk", "brcm,bcm6345-gate-clk";

Documentation/devicetree/bindings/clock/brcm,bcm6345-gate-clk.txt

Quoted 10 lines
Documentation/devicetree/bindings/clock/brcm,bcm6345-gate-clk.txt new file +10 -0
+       regmap =3D <&timer_cntl>;
+       offset =3D <0x4>;
+
+       #clock-cells =3D <1>;
+       clock-indices =3D <17>, <18>;
+       clock-output-names =3D "uto_extin", "usb_ref";
+};
+
+ehci0: usb@10002500 {
+       compatible =3D "brcm,bcm63168-ehci", "brcm,bcm6345-ehci", "generi=

c-ehci";

Quoted 15 lines
(quoted diff) +7 -1
+       reg =3D <0x10002500 0x100>;
+       big-endian;
+       interrupt-parent =3D <&periph_intc>;
+       interrupts =3D <10>;
+       clocks =3D <&periph_clk 13>, <&timer_clk 18>;
+       phys =3D <&usbh>;
+};
-- =

2.1.4
=

-- =

Simon Arlott