[RFC][PATCH 1/2] ARM: OMAP4: clock: Add device tree support for AUXCLKs

Nishanth Menon nm at ti.com
Wed Apr 10 07:54:19 EST 2013


On 15:49-20130409, Nishanth Menon wrote:
> On 10:43-20130409, Tony Lindgren wrote:
> > * Tony Lindgren <tony at atomide.com> [130409 09:54]:
> > > * Roger Quadros <rogerq at ti.com> [130409 03:00]:
> > > > On 04/05/2013 06:58 PM, Tony Lindgren wrote:
> > > > > 
> > > > > Can't you just use the clock name there to get it?
> > > > 
> > > > In device tree we don't pass around clock names. You can either get
> > > > a phandle or an index to the clock.
> > > > 
> > > > e.g. Documentation/devicetree/bindings/clock/imx31-clock.txt
> > > 
> > > Yes I understand that. But the driver/clock/omap driver can just
> > > remap the DT device initially so the board specific clock is
> > > found from the clock alias table. Basically initially a passthrough
> > > driver that can be enhanced to parse DT clock bindings and load
> > > data from /lib/firmware.
> > 
> > Actually probably the driver/clock/omap can even do even less
> > initially. There probably even no need to remap clocks there.
> > 
> > As long as the DT clock driver understands that a board specific
> > auxclk is specified in the DT it can just call clk_add_alias() so
> > the driver will get the right auxclk from cclock44xx_data.c.
> > 
> > Then other features can be added later on like to allocate a
> > clock entirely based on the binding etc.
> I did try to have an implementation for cpufreq using clock nodes.
> unfortunately, device tree wont let me have arguments of strings :(
> So, I am unable to do clock = <&clk mpu_dpll>;
> instead, I am forced to do clock = <&clk 249>;
> 
> Here is an attempt on beagleXM - adds every clock node to the list.
> Tons of un-necessary prints added to give an idea - see log:
> http://pastebin.com/F9A2zSTr
> 
> Would an cleaned up version be good enough as a step #1 of transition?
> 
Approach #2:
Here is yet another revision -> here I am trying to avoid the risk of
folks messing up indexing. for example: using an older DTB with newer
kernel, clocks being inserted into existing list etc. to prevent these,
we add an "DT_ID" for omap clock nodes, and use it to uniquely identify
the clock node. We try to minimize(not avoidable with integer indexing)
mistakes during development/productization.

>From 2b576affdc6f6bf0b51ebf9b85ef4319357a7994 Mon Sep 17 00:00:00 2001
From: Nishanth Menon <nm at ti.com>
Date: Tue, 26 Mar 2013 10:23:27 +0000
Subject: [RFC PATCH V2] OMAP: add devicetree support for clock nodes.(rev 2)

Dummy patch based on Roger's original idea
this time have lesser possibiltiy of screwing up indices. instead
use a specific integer ID to uniquely (TI SoC wide) identify an clock.
on the flip side, we do not all make clock nodes to be accesible from DT
clock indexing.

Nyet-Signed-off-by: Nishanth Menon <nm at ti.com>
---
 .../devicetree/bindings/clock/ti,clock.txt         |   48 +++++++++++
 arch/arm/boot/dts/omap3.dtsi                       |    5 ++
 arch/arm/boot/dts/omap34xx.dtsi                    |    2 +
 arch/arm/boot/dts/omap4.dtsi                       |    5 ++
 arch/arm/boot/dts/omap443x.dtsi                    |    2 +
 arch/arm/mach-omap2/cclock3xxx_data.c              |    5 +-
 arch/arm/mach-omap2/cclock44xx_data.c              |    5 +-
 arch/arm/mach-omap2/clock.h                        |   12 +++
 arch/arm/mach-omap2/pm.c                           |   11 ++-
 drivers/clk/Kconfig                                |    6 ++
 drivers/clk/Makefile                               |    2 +
 drivers/clk/ti.c                                   |   85 ++++++++++++++++++++
 include/linux/clk/ti.h                             |   30 +++++++
 13 files changed, 211 insertions(+), 7 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ti,clock.txt
 create mode 100644 drivers/clk/ti.c
 create mode 100644 include/linux/clk/ti.h

diff --git a/Documentation/devicetree/bindings/clock/ti,clock.txt b/Documentation/devicetree/bindings/clock/ti,clock.txt
new file mode 100644
index 0000000..53c947c
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti,clock.txt
@@ -0,0 +1,48 @@
+* Clock bindings for Texas Instruments clocks
+
+Required properties:
+- compatible: Should be "ti,clock"
+- #clock-cells: Should be <1>
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.  The following is a list of ID reservations
+across TI SoCs
+
+       Clock           ID
+       ------------------
+       cpu clock	1
+
+The definition is used by SoC clock data using CLKDT() macro
+(example of OMAP2+).
+
+Example Steps:
+/* step 1: definiting an SoC nodes compatible with ti clocks -skip if already done */
+clks: clocks {
+	compatible = "ti,clock";
+	#clock-cells = <1>;
+};
+
+/* step 2: Modify the bindings documentation to reserve an ID */
+	auxclk0_ck      2
+	auxclk1_ck      3
+	auxclk2_ck      4
+	auxclk3_ck      5
+	auxclk4_ck      6
+	auxclk5_ck      7
+etc. use an unique number not conflicting with previous reservations.
+WARNING: DONOT insert values - this breaks backward compatibility.
+/* Step 3: replace in clock data file */
+	CLK(NULL,	"auxclk0_ck",			&auxclk0_ck,	CK_443X),
+with
+	CLKDT(2, NULL,	"auxclk0_ck",			&auxclk0_ck,	CK_443X),
+
+/* step 4: in device tree entry, now we can use index 2 to uniquely identify auxclk0 clock */
+
+hsusb1_phy: hsusb1_phy {
+	compatible = "usb-nop-xceiv";
+	reset-supply = <&hsusb1_reset>;
+	clocks = <&aux_clks 2>;
+	clock-names = "main_clk";
+	clock-frequency = <19200000>;
+};
+
diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index 3344f05..a08990d 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -73,6 +73,11 @@
 			ti,hwmods = "counter_32k";
 		};
 
+		clks: clocks {
+			compatible = "ti,clock";
+			#clock-cells = <1>;
+		};
+
 		intc: interrupt-controller at 48200000 {
 			compatible = "ti,omap2-intc";
 			interrupt-controller;
diff --git a/arch/arm/boot/dts/omap34xx.dtsi b/arch/arm/boot/dts/omap34xx.dtsi
index 75ed4ae..de59fb8 100644
--- a/arch/arm/boot/dts/omap34xx.dtsi
+++ b/arch/arm/boot/dts/omap34xx.dtsi
@@ -23,6 +23,8 @@
 				600000  1350000
 			>;
 			clock-latency = <300000>; /* From legacy driver */
+			clocks = <&clks 1>;
+			clock-names = "cpu";
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 3329140..ad18d6a 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -106,6 +106,11 @@
 			ti,hwmods = "counter_32k";
 		};
 
+		clks: clocks {
+			compatible = "ti,clock";
+			#clock-cells = <1>;
+		};
+
 		omap4_pmx_core: pinmux at 4a100040 {
 			compatible = "ti,omap4-padconf", "pinctrl-single";
 			reg = <0x4a100040 0x0196>;
diff --git a/arch/arm/boot/dts/omap443x.dtsi b/arch/arm/boot/dts/omap443x.dtsi
index cccf39a..5bfc02b 100644
--- a/arch/arm/boot/dts/omap443x.dtsi
+++ b/arch/arm/boot/dts/omap443x.dtsi
@@ -22,6 +22,8 @@
 				1008000 1375000
 			>;
 			clock-latency = <300000>; /* From legacy driver */
+			clocks = <&clks 1>;
+			clock-names = "cpu";
 		};
 	};
 };
diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c
index 4579c3c..2f2932b 100644
--- a/arch/arm/mach-omap2/cclock3xxx_data.c
+++ b/arch/arm/mach-omap2/cclock3xxx_data.c
@@ -22,6 +22,7 @@
 #include <linux/clk-private.h>
 #include <linux/list.h>
 #include <linux/io.h>
+#include <linux/clk/ti.h>
 
 #include "soc.h"
 #include "iomap.h"
@@ -3501,7 +3502,7 @@ static struct omap_clk omap3xxx_clks[] = {
 	CLK(NULL,	"uart4_ick",	&uart4_ick_am35xx,	CK_AM35XX),
 	CLK(NULL,	"timer_32k_ck",	&omap_32k_fck,  CK_3XXX),
 	CLK(NULL,	"timer_sys_ck",	&sys_ck,	CK_3XXX),
-	CLK(NULL,	"cpufreq_ck",	&dpll1_ck,	CK_3XXX),
+	CLKDT(1, NULL,	"cpufreq_ck",	&dpll1_ck,	CK_3XXX),
 };
 
 static const char *enable_init_clks[] = {
@@ -3574,7 +3575,7 @@ int __init omap3xxx_clk_init(void)
 	for (c = omap3xxx_clks; c < omap3xxx_clks + ARRAY_SIZE(omap3xxx_clks);
 	     c++)
 		if (c->cpu & cpu_clkflg) {
-			clkdev_add(&c->lk);
+			ti_clk_node_add(&c->lk, c->dt_clkid);
 			if (!__clk_init(NULL, c->lk.clk))
 				omap2_init_clk_hw_omap_clocks(c->lk.clk);
 		}
diff --git a/arch/arm/mach-omap2/cclock44xx_data.c b/arch/arm/mach-omap2/cclock44xx_data.c
index 0c6834a..74d4e8c 100644
--- a/arch/arm/mach-omap2/cclock44xx_data.c
+++ b/arch/arm/mach-omap2/cclock44xx_data.c
@@ -27,6 +27,7 @@
 #include <linux/clk-private.h>
 #include <linux/clkdev.h>
 #include <linux/io.h>
+#include <linux/clk/ti.h>
 
 #include "soc.h"
 #include "iomap.h"
@@ -1672,7 +1673,7 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK("4013a000.timer",	"timer_sys_ck",	&syc_clk_div_ck,	CK_443X),
 	CLK("4013c000.timer",	"timer_sys_ck",	&syc_clk_div_ck,	CK_443X),
 	CLK("4013e000.timer",	"timer_sys_ck",	&syc_clk_div_ck,	CK_443X),
-	CLK(NULL,	"cpufreq_ck",	&dpll_mpu_ck,	CK_443X),
+	CLKDT(1, NULL,	"cpufreq_ck",	&dpll_mpu_ck,	CK_443X),
 };
 
 int __init omap4xxx_clk_init(void)
@@ -1697,7 +1698,7 @@ int __init omap4xxx_clk_init(void)
 	for (c = omap44xx_clks; c < omap44xx_clks + ARRAY_SIZE(omap44xx_clks);
 									c++) {
 		if (c->cpu & cpu_clkflg) {
-			clkdev_add(&c->lk);
+			ti_clk_node_add(&c->lk, c->dt_clkid);
 			if (!__clk_init(NULL, c->lk.clk))
 				omap2_init_clk_hw_omap_clocks(c->lk.clk);
 		}
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 60ddd86..9a7c95b 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -23,10 +23,22 @@
 #include <linux/clk-provider.h>
 
 struct omap_clk {
+	u16				dt_clkid;
 	u16				cpu;
 	struct clk_lookup		lk;
 };
 
+#define CLKDT(id, dev, con, ck, cp)	\
+	{				\
+		.dt_clkid = id,		\
+		.cpu = cp,		\
+		.lk = {			\
+			.dev_id = dev,	\
+			.con_id = con,	\
+			.clk = ck,	\
+		},			\
+	}
+
 #define CLK(dev, con, ck, cp)		\
 	{				\
 		 .cpu = cp,		\
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index a47e6ee..03c6e48 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -55,6 +55,12 @@ config COMMON_CLK_MAX77686
 	---help---
 	  This driver supports Maxim 77686 crystal oscillator clock. 
 
+config COMMON_CLK_TI
+	tristate "Clock driver for TI SoCs"
+	depends on ARCH_OMAP && OF
+	---help---
+	  Fill me up.. some generic statement ofcourse (lets start with OMAP)
+
 config CLK_TWL6040
 	tristate "External McPDM functional clock from twl6040"
 	depends on TWL6040_CORE
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 300d477..9621815 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -30,6 +30,8 @@ obj-$(CONFIG_ARCH_TEGRA)	+= tegra/
 
 obj-$(CONFIG_X86)		+= x86/
 
+obj-$(CONFIG_COMMON_CLK_TI)	+= ti.o
+
 # Chip specific
 obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
 obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
diff --git a/drivers/clk/ti.c b/drivers/clk/ti.c
new file mode 100644
index 0000000..56b8754
--- /dev/null
+++ b/drivers/clk/ti.c
@@ -0,0 +1,85 @@
+/*
+ * TI Clock node provider
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ *	Nishanth Menon
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/clk-private.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/clk/ti.h>
+
+struct ti_clk {
+	struct clk_lookup *lk;
+	u16	id;
+	struct list_head node;
+};
+
+static LIST_HEAD(ti_clk_list);
+
+static struct clk *ti_bypass_clk_get_by_name(struct of_phandle_args *clkspec,
+					     void *data)
+{
+	struct ti_clk *c;
+	int idx = clkspec->args[0];
+
+	list_for_each_entry(c, &ti_clk_list, node) {
+		if (idx == c->id)
+			return c->lk->clk;
+	}
+
+	pr_err("%s: Clock ID %d not found in list\n", __func__, idx);
+	return ERR_PTR(-ENODEV);
+}
+
+static void __init ti_clock_init(struct device_node *node)
+{
+
+	pr_err("%s: START\n", __func__);
+	of_clk_add_provider(node, ti_bypass_clk_get_by_name, NULL);
+	pr_err("%s: END\n", __func__);
+}
+CLK_OF_DECLARE(ti_clk, "ti,clock", ti_clock_init);
+
+void __init ti_clk_node_add(struct clk_lookup *lk, u16 id)
+{
+	struct ti_clk *c;
+	static bool of_added;
+
+	if (lk->dev_id || !id)
+		goto out;
+
+	/* No lists if we did not boot supported by DT entries */
+	if (!of_have_populated_dt())
+		goto out;
+
+	c = kzalloc(sizeof(struct ti_clk), GFP_KERNEL);
+	if (!c) {
+		pr_err("%s: No memory!! cannot add clk node for DT!\n",
+			__func__);
+		/* lets try atleast an regular clock node */
+		goto out;
+	}
+	c->lk = lk;
+	c->id = id;
+	list_add_tail(&c->node, &ti_clk_list);
+	pr_err("%s: Added clock node %s\n", __func__, lk->con_id);
+	if (!of_added) {
+		of_clk_init(NULL);
+		of_added =  true;
+	}
+out:
+	clkdev_add(lk);
+};
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
new file mode 100644
index 0000000..ebed98a
--- /dev/null
+++ b/include/linux/clk/ti.h
@@ -0,0 +1,30 @@
+/*
+ * TI Clock node provider header
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ *	Nishanth Menon
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __TI_CLK_H
+#define __TI_CLK_H
+
+#include <linux/clkdev.h>
+
+#ifdef CONFIG_OF
+extern void ti_clk_node_add(struct clk_lookup *lk, u16 id);
+#else
+static inline void ti_clk_node_add(struct clk_lookup *lk, u16 id)
+{
+	clkdev_add(lk);
+}
+#endif /* CONFIG_OF */
+
+#endif	/* __TI_CLK_H */
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 8d15f9a..6cf95160 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -267,7 +267,12 @@ static void __init omap4_init_voltages(void)
 
 static inline void omap_init_cpufreq(void)
 {
-	struct platform_device_info devinfo = { .name = "omap-cpufreq", };
+	struct platform_device_info devinfo = { };
+
+	if (!of_have_populated_dt())
+		devinfo.name = "omap-cpufreq";
+	else
+		devinfo.name = "cpufreq-cpu0";
 	platform_device_register_full(&devinfo);
 }
 
@@ -301,9 +306,9 @@ int __init omap2_common_pm_late_init(void)
 		/* Smartreflex device init */
 		omap_devinit_smartreflex();
 
-		/* cpufreq dummy device instantiation */
-		omap_init_cpufreq();
 	}
+	/* cpufreq dummy device instantiation */
+	omap_init_cpufreq();
 
 #ifdef CONFIG_SUSPEND
 	suspend_set_ops(&omap_pm_ops);
-- 
1.7.9.5

-- 
Regards,
Nishanth Menon


More information about the devicetree-discuss mailing list