linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCHv3 0/7] clk: ti add support for hwmod clk type
@ 2016-06-30 14:13 Tero Kristo
  2016-06-30 14:13 ` [PATCHv3 1/7] clkdev: add helper registration API Tero Kristo
                   ` (6 more replies)
  0 siblings, 7 replies; 13+ messages in thread
From: Tero Kristo @ 2016-06-30 14:13 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Changes from v3:
- moved mach-omap2 related patches to their own sets
- moved DT_CLK cleanup patches to their own series (which depends on this)
- added patch #1 to add clkdev helper support, this helps
  getting rid of some 4...5 patches from v2 of the series, and keeping
  the clk_get API uniform
- made ti_clk_get function static, not used outside the file anymore,
  as this will be providing support via tha API added in patch #1 in
  this set

This series can be applied separately, without any dependencies on the
other sets. I will be posting the DT_CLK cleanup set separately if this
series gets approval.

Test results:

  : Board           : Boot WRN version                 
 1: am335x-evm      : PASS   0 4.7.0-rc1-00007-g958a12a
 2: am335x-evmsk    : PASS   0 4.7.0-rc1-00007-g958a12a
 3: am3517-evm      : PASS   1 4.7.0-rc1-00007-g958a12a
 4: am37x-evm       : PASS   0 4.7.0-rc1-00007-g958a12a
 5: am437x-sk       : PASS   0 4.7.0-rc1-00007-g958a12a
 6: am43x-epos-evm  : PASS   0 4.7.0-rc1-00007-g958a12a
 7: am437x-gp-evm   : PASS   0 4.7.0-rc1-00007-g958a12a
 8: am57xx-evm      : PASS   3 4.7.0-rc1-00007-g958a12a
 9: omap3-beagle-xm : PASS   0 4.7.0-rc1-00007-g958a12a
10: omap3-beagle    : PASS   0 4.7.0-rc1-00007-g958a12a
11: am335x-boneblack: PASS   0 4.7.0-rc1-00007-g958a12a
12: am335x-bone     : PASS   0 4.7.0-rc1-00007-g958a12a
13: craneboard      : PASS   1 4.7.0-rc1-00007-g958a12a
14: dra72x-evm      : FAIL   3 4.7.0-rc1-00007-g958a12a
15: dra7xx-evm      : PASS   3 4.7.0-rc1-00007-g958a12a
16: ldp3430         : FAIL   0                         
17: omap3-n900      : PASS   0 4.7.0-rc1-00007-g958a12a
18: omap5-uevm      : PASS   0 4.7.0-rc1-00007-g958a12a
19: omap4-panda-es  : PASS   0 4.7.0-rc1-00007-g958a12a
20: omap4-panda     : PASS   0 4.7.0-rc1-00007-g958a12a
21: omap2430-sdp    : PASS   0 4.7.0-rc1-00007-g958a12a
22: omap3430-sdp    : PASS   0 4.7.0-rc1-00007-g958a12a
23: omap4-sdp-es23plus: PASS   0 4.7.0-rc1-00007-g958a12a
TOTAL = 23 boards, Booted Boards = 21, No Boot boards = 2

The couple of failing boards seem to have hardware issues on the farm, as
they fail with any kernel.

Patches also available here:

tree: https://github.com/t-kristo/linux-pm.git
branch: 4.7-rc1-hwmod-clks-v3

-Tero

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCHv3 1/7] clkdev: add helper registration API
  2016-06-30 14:13 [PATCHv3 0/7] clk: ti add support for hwmod clk type Tero Kristo
@ 2016-06-30 14:13 ` Tero Kristo
  2016-06-30 14:13 ` [PATCHv3 2/7] clk: ti: add clkdev get helper Tero Kristo
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Tero Kristo @ 2016-06-30 14:13 UTC (permalink / raw)
  To: linux-arm-kernel

In certain cases, it is desirable to extend the implementation of the
clkdev lookup, to avoid registering massive amounts of clkdev aliases.
A simple helper implementation can instead be used to search and
automatically create the clkdev entries. A sample of this is the TI
clock implementation, which currently registers a large number of
clkdev entries with a very simple mapping strategy.

This patch adds an API to register a helper function that gets called
during clk_get(), in case everything else fails to look up the clock.
Individual clock drivers are then free to register the helper and
implement it the way they want.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
Cc: Russell King <linux@armlinux.org.uk>
---
 drivers/clk/clkdev.c   | 22 +++++++++++++++++++++-
 include/linux/clkdev.h |  1 +
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 89cc700..788c0b2 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -26,6 +26,8 @@
 
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
+static struct clk * (*clkdev_get_helper)(const char *dev_id,
+					 const char *con_id);
 
 #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
 static struct clk *__of_clk_get(struct device_node *np, int index,
@@ -190,7 +192,13 @@ struct clk *clk_get_sys(const char *dev_id, const char *con_id)
 out:
 	mutex_unlock(&clocks_mutex);
 
-	return cl ? clk : ERR_PTR(-ENOENT);
+	if (cl)
+		return clk;
+
+	if (clkdev_get_helper)
+		return clkdev_get_helper(dev_id, con_id);
+
+	return ERR_PTR(-ENOENT);
 }
 EXPORT_SYMBOL(clk_get_sys);
 
@@ -209,6 +217,18 @@ struct clk *clk_get(struct device *dev, const char *con_id)
 }
 EXPORT_SYMBOL(clk_get);
 
+int clkdev_helper_register(struct clk * (*helper)(const char *,
+						  const char *))
+{
+	if (clkdev_get_helper)
+		return -EBUSY;
+
+	clkdev_get_helper = helper;
+
+	return 0;
+}
+EXPORT_SYMBOL(clkdev_helper_register);
+
 void clk_put(struct clk *clk)
 {
 	__clk_put(clk);
diff --git a/include/linux/clkdev.h b/include/linux/clkdev.h
index 2eabc86..173e2fa 100644
--- a/include/linux/clkdev.h
+++ b/include/linux/clkdev.h
@@ -51,6 +51,7 @@ int clk_add_alias(const char *, const char *, const char *, struct device *);
 
 int clk_register_clkdev(struct clk *, const char *, const char *);
 int clk_hw_register_clkdev(struct clk_hw *, const char *, const char *);
+int clkdev_helper_register(struct clk * (*)(const char *, const char *));
 
 #ifdef CONFIG_COMMON_CLK
 int __clk_get(struct clk *clk);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv3 2/7] clk: ti: add clkdev get helper
  2016-06-30 14:13 [PATCHv3 0/7] clk: ti add support for hwmod clk type Tero Kristo
  2016-06-30 14:13 ` [PATCHv3 1/7] clkdev: add helper registration API Tero Kristo
@ 2016-06-30 14:13 ` Tero Kristo
  2016-07-12 10:22   ` Russell King - ARM Linux
  2016-06-30 14:13 ` [PATCHv3 3/7] clk: ti: remove un-used definitions from public clk_hw_omap struct Tero Kristo
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 13+ messages in thread
From: Tero Kristo @ 2016-06-30 14:13 UTC (permalink / raw)
  To: linux-arm-kernel

TI clocks can be found based on a simple query against the clock name,
thus add a clkdev helper functionality for this. Using this new helper
implementation  allows getting rid of most of the DT_CLK() entries under
drivers/clk/ti.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/clk/ti/clk.c | 38 +++++++++++++++++++++++++++++++++-----
 1 file changed, 33 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index 5fcf247..17554c3 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -68,6 +68,36 @@ static u32 clk_memmap_readl(void __iomem *reg)
 }
 
 /**
+ * ti_clk_get - lookup a TI clock handle
+ * @dev_id: device to lookup clock for
+ * @con_id: connection ID to find
+ *
+ * Searches for a TI clock handle based on the DT node name.
+ * Returns the pointer to the clock handle, or ERR_PTR in failure.
+ */
+static struct clk *ti_clk_get(const char *dev_id, const char *con_id)
+{
+	struct of_phandle_args clkspec;
+	struct device_node *node;
+	struct clk *clk;
+
+	/* Only check for cases of type clk_get_sys(NULL, "xyz") */
+	if (dev_id || !con_id)
+		return ERR_PTR(-ENOENT);
+
+	if (of_have_populated_dt()) {
+		node = of_find_node_by_name(NULL, con_id);
+		clkspec.np = node;
+		clk = of_clk_get_from_provider(&clkspec);
+
+		if (!IS_ERR(clk))
+			return clk;
+	}
+
+	return ERR_PTR(-ENOENT);
+}
+
+/**
  * ti_clk_setup_ll_ops - setup low level clock operations
  * @ops: low level clock ops descriptor
  *
@@ -87,6 +117,8 @@ int ti_clk_setup_ll_ops(struct ti_clk_ll_ops *ops)
 	ops->clk_readl = clk_memmap_readl;
 	ops->clk_writel = clk_memmap_writel;
 
+	clkdev_helper_register(ti_clk_get);
+
 	return 0;
 }
 
@@ -102,14 +134,10 @@ int ti_clk_setup_ll_ops(struct ti_clk_ll_ops *ops)
 void __init ti_dt_clocks_register(struct ti_dt_clk oclks[])
 {
 	struct ti_dt_clk *c;
-	struct device_node *node;
 	struct clk *clk;
-	struct of_phandle_args clkspec;
 
 	for (c = oclks; c->node_name != NULL; c++) {
-		node = of_find_node_by_name(NULL, c->node_name);
-		clkspec.np = node;
-		clk = of_clk_get_from_provider(&clkspec);
+		clk = ti_clk_get(NULL, c->node_name);
 
 		if (!IS_ERR(clk)) {
 			c->lk.clk = clk;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv3 3/7] clk: ti: remove un-used definitions from public clk_hw_omap struct
  2016-06-30 14:13 [PATCHv3 0/7] clk: ti add support for hwmod clk type Tero Kristo
  2016-06-30 14:13 ` [PATCHv3 1/7] clkdev: add helper registration API Tero Kristo
  2016-06-30 14:13 ` [PATCHv3 2/7] clk: ti: add clkdev get helper Tero Kristo
@ 2016-06-30 14:13 ` Tero Kristo
  2016-06-30 14:13 ` [PATCHv3 4/7] clk: ti: mux: export mux clock APIs locally Tero Kristo
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Tero Kristo @ 2016-06-30 14:13 UTC (permalink / raw)
  To: linux-arm-kernel

Clksel support has been deprecated a while back, so remove these from
the struct also.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 include/linux/clk/ti.h | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 6110fe0..07308db 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -129,8 +129,6 @@ struct clk_hw_omap_ops {
  * @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg)
  * @flags: see "struct clk.flags possibilities" above
  * @clksel_reg: for clksel clks, register va containing src/divisor select
- * @clksel_mask: bitmask in @clksel_reg for the src/divisor selector
- * @clksel: for clksel clks, pointer to struct clksel for this clock
  * @dpll_data: for DPLLs, pointer to struct dpll_data for this clock
  * @clkdm_name: clockdomain name that this clock is contained in
  * @clkdm: pointer to struct clockdomain, resolved from @clkdm_name at runtime
@@ -145,8 +143,6 @@ struct clk_hw_omap {
 	u8			enable_bit;
 	u8			flags;
 	void __iomem		*clksel_reg;
-	u32			clksel_mask;
-	const struct clksel	*clksel;
 	struct dpll_data	*dpll_data;
 	const char		*clkdm_name;
 	struct clockdomain	*clkdm;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv3 4/7] clk: ti: mux: export mux clock APIs locally
  2016-06-30 14:13 [PATCHv3 0/7] clk: ti add support for hwmod clk type Tero Kristo
                   ` (2 preceding siblings ...)
  2016-06-30 14:13 ` [PATCHv3 3/7] clk: ti: remove un-used definitions from public clk_hw_omap struct Tero Kristo
@ 2016-06-30 14:13 ` Tero Kristo
  2016-06-30 14:13 ` [PATCHv3 5/7] clk: ti: am33xx: fix timer3/6 init time setup for module clocks Tero Kristo
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Tero Kristo @ 2016-06-30 14:13 UTC (permalink / raw)
  To: linux-arm-kernel

get_parent and set_parent are going to be required by the support of
module clocks, so export these locally.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/clk/ti/clock.h | 3 +++
 drivers/clk/ti/mux.c   | 4 ++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h
index 90f3f47..7eca8a1 100644
--- a/drivers/clk/ti/clock.h
+++ b/drivers/clk/ti/clock.h
@@ -224,6 +224,9 @@ extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait;
 extern const struct clk_ops ti_clk_divider_ops;
 extern const struct clk_ops ti_clk_mux_ops;
 
+u8 ti_clk_mux_get_parent(struct clk_hw *hw);
+int ti_clk_mux_set_parent(struct clk_hw *hw, u8 index);
+
 int omap2_clkops_enable_clkdm(struct clk_hw *hw);
 void omap2_clkops_disable_clkdm(struct clk_hw *hw);
 
diff --git a/drivers/clk/ti/mux.c b/drivers/clk/ti/mux.c
index 44777ab..57ff471 100644
--- a/drivers/clk/ti/mux.c
+++ b/drivers/clk/ti/mux.c
@@ -26,7 +26,7 @@
 #undef pr_fmt
 #define pr_fmt(fmt) "%s: " fmt, __func__
 
-static u8 ti_clk_mux_get_parent(struct clk_hw *hw)
+u8 ti_clk_mux_get_parent(struct clk_hw *hw)
 {
 	struct clk_mux *mux = to_clk_mux(hw);
 	int num_parents = clk_hw_get_num_parents(hw);
@@ -63,7 +63,7 @@ static u8 ti_clk_mux_get_parent(struct clk_hw *hw)
 	return val;
 }
 
-static int ti_clk_mux_set_parent(struct clk_hw *hw, u8 index)
+int ti_clk_mux_set_parent(struct clk_hw *hw, u8 index)
 {
 	struct clk_mux *mux = to_clk_mux(hw);
 	u32 val;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv3 5/7] clk: ti: am33xx: fix timer3/6 init time setup for module clocks
  2016-06-30 14:13 [PATCHv3 0/7] clk: ti add support for hwmod clk type Tero Kristo
                   ` (3 preceding siblings ...)
  2016-06-30 14:13 ` [PATCHv3 4/7] clk: ti: mux: export mux clock APIs locally Tero Kristo
@ 2016-06-30 14:13 ` Tero Kristo
  2016-06-30 14:13 ` [PATCHv3 6/7] dt-bindings: clk: ti: Document module clock type Tero Kristo
  2016-06-30 14:13 ` [PATCHv3 7/7] clk: ti: add support for omap4 module clocks Tero Kristo
  6 siblings, 0 replies; 13+ messages in thread
From: Tero Kristo @ 2016-06-30 14:13 UTC (permalink / raw)
  To: linux-arm-kernel

timer*_fck are going to be renamed as timer*_mod_ck:s. Fix the init
time configuration of timer3/timer6 to take this into account, and
lookup for the module clock in case the lookup for fck fails.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/clk/ti/clk-33xx.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/clk/ti/clk-33xx.c b/drivers/clk/ti/clk-33xx.c
index ef2ec64..c69fed5 100644
--- a/drivers/clk/ti/clk-33xx.c
+++ b/drivers/clk/ti/clk-33xx.c
@@ -144,9 +144,15 @@ int __init am33xx_dt_clk_init(void)
 
 	clk1 = clk_get_sys(NULL, "sys_clkin_ck");
 	clk2 = clk_get_sys(NULL, "timer3_fck");
+	if (IS_ERR(clk2))
+		clk2 = clk_get_sys(NULL, "timer3_mod_ck");
+
 	clk_set_parent(clk2, clk1);
 
 	clk2 = clk_get_sys(NULL, "timer6_fck");
+	if (IS_ERR(clk2))
+		clk2 = clk_get_sys(NULL, "timer6_mod_ck");
+
 	clk_set_parent(clk2, clk1);
 	/*
 	 * The On-Chip 32K RC Osc clock is not an accurate clock-source as per
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv3 6/7] dt-bindings: clk: ti: Document module clock type
  2016-06-30 14:13 [PATCHv3 0/7] clk: ti add support for hwmod clk type Tero Kristo
                   ` (4 preceding siblings ...)
  2016-06-30 14:13 ` [PATCHv3 5/7] clk: ti: am33xx: fix timer3/6 init time setup for module clocks Tero Kristo
@ 2016-06-30 14:13 ` Tero Kristo
  2016-06-30 14:13 ` [PATCHv3 7/7] clk: ti: add support for omap4 module clocks Tero Kristo
  6 siblings, 0 replies; 13+ messages in thread
From: Tero Kristo @ 2016-06-30 14:13 UTC (permalink / raw)
  To: linux-arm-kernel

Document the new TI module clock type, which is intended to replace the
internal clock control handling within omap_hwmod. Module clock is
effectively a gate clock controlling both interface and functional
clocks for a single hardware IP block.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 .../devicetree/bindings/clock/ti/module.txt        | 59 ++++++++++++++++++++++
 1 file changed, 59 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/ti/module.txt

diff --git a/Documentation/devicetree/bindings/clock/ti/module.txt b/Documentation/devicetree/bindings/clock/ti/module.txt
new file mode 100644
index 0000000..0329667
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti/module.txt
@@ -0,0 +1,59 @@
+Binding for Texas Instruments module clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1]. This clock is
+quite much similar to the basic gate-clock [2], however, internally
+it controls an OMAP module clock, which effectively handles
+both interface and functional clocks for a single module. In some
+cases, support for mux clock [3] is composited to the same clock node,
+currently only needed for proper support of timer module clocks.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/ti/gate.txt
+[3] Documentation/devicetree/bindings/clock/ti/mux.txt
+
+Required properties:
+- compatible : shall be one of:
+  "ti,omap4-mod-clock" - basic module clock, no gating supported
+  "ti,omap4-hw-mod-clock" - module clock with hardware gating support
+  "ti,omap4-sw-mod-clock" - module clock with software forced gating support
+  "ti,omap4-sw-no-idlest-mod-clock" - module clock with software forced gating
+				      support, misses idlest
+  "ti,omap4-mux-mod-clock" - composite clock with mux and module clocks, no
+			     gating supported
+  "ti,omap4-hw-mux-mod-clock" - composite clock with mux and module clocks,
+				with hardware gating
+  "ti,omap4-sw-mux-mod-clock" - composite clock with mux and module clocks,
+				with software forced gating
+
+- #clock-cells : from common clock binding; shall be set to 0
+- clocks : link to phandle of parent clock(s)
+- reg : offset for register controlling adjustable gate and optional mux
+
+Optional properties:
+- ti,bit-shift : bit shift for programming the clock mux, only needed for
+		 the nodes of the mux variant
+
+Examples:
+	timer6_mod_ck: timer6_mod_ck {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-sw-mux-mod-clock";
+		reg = <0x0570>;
+		clocks = <&syc_clk_div_ck>, <&sys_32k_ck>;
+		ti,bit-shift = <24>;
+	};
+
+	i2c1_mod_ck: i2c1_mod_ck {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-sw-mod-clock";
+		reg = <0x14a0>;
+		clocks = <&func_96m_fclk>;
+	};
+
+	hsi_mod_ck: hsi_mod_ck {
+		#clock-cells = <0>;
+		compatible = "ti,omap4-hw-mod-clock";
+		reg = <0x1338>;
+		clocks = <&hsi_fck>;
+	};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv3 7/7] clk: ti: add support for omap4 module clocks
  2016-06-30 14:13 [PATCHv3 0/7] clk: ti add support for hwmod clk type Tero Kristo
                   ` (5 preceding siblings ...)
  2016-06-30 14:13 ` [PATCHv3 6/7] dt-bindings: clk: ti: Document module clock type Tero Kristo
@ 2016-06-30 14:13 ` Tero Kristo
  6 siblings, 0 replies; 13+ messages in thread
From: Tero Kristo @ 2016-06-30 14:13 UTC (permalink / raw)
  To: linux-arm-kernel

Previously, hwmod core has been used for controlling the hwmod level
clocks. This has certain drawbacks, like being unable to share the
clocks for multiple users, missing usecounting and generally being
totally incompatible with common clock framework.

Add support for new clock type under the TI clock driver, which will
be used to convert all the existing hwmdo clocks to. This helps to
get rid of the clock related hwmod data from kernel and instead
parsing this from DT.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/clk/ti/Makefile   |   3 +-
 drivers/clk/ti/clkt_mod.c | 414 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk/ti.h    |   2 +
 3 files changed, 418 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/ti/clkt_mod.c

diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile
index 0deac98..15886ef 100644
--- a/drivers/clk/ti/Makefile
+++ b/drivers/clk/ti/Makefile
@@ -3,7 +3,8 @@ ifeq ($(CONFIG_ARCH_OMAP2PLUS), y)
 obj-y					+= clk.o autoidle.o clockdomain.o
 clk-common				= dpll.o composite.o divider.o gate.o \
 					  fixed-factor.o mux.o apll.o \
-					  clkt_dpll.o clkt_iclk.o clkt_dflt.o
+					  clkt_dpll.o clkt_iclk.o clkt_dflt.o \
+					  clkt_mod.o
 obj-$(CONFIG_SOC_AM33XX)		+= $(clk-common) clk-33xx.o dpll3xxx.o
 obj-$(CONFIG_SOC_TI81XX)		+= $(clk-common) fapll.o clk-814x.o clk-816x.o
 obj-$(CONFIG_ARCH_OMAP2)		+= $(clk-common) interface.o clk-2xxx.o
diff --git a/drivers/clk/ti/clkt_mod.c b/drivers/clk/ti/clkt_mod.c
new file mode 100644
index 0000000..9a29eb4
--- /dev/null
+++ b/drivers/clk/ti/clkt_mod.c
@@ -0,0 +1,414 @@
+/*
+ * OMAP hardware module clock support
+ *
+ * Copyright (C) 2015 Texas Instruments, Inc.
+ *
+ * Tero Kristo <t-kristo@ti.com>
+ *
+ * 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/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+#include <linux/delay.h>
+#include "clock.h"
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#define NO_IDLEST			0x1
+
+#define OMAP4_MODULEMODE_MASK		0x3
+
+#define MODULEMODE_HWCTRL		0x1
+#define MODULEMODE_SWCTRL		0x2
+
+#define OMAP4_IDLEST_MASK		(0x3 << 16)
+#define OMAP4_IDLEST_SHIFT		16
+
+#define CLKCTRL_IDLEST_FUNCTIONAL	0x0
+#define CLKCTRL_IDLEST_INTERFACE_IDLE	0x2
+#define CLKCTRL_IDLEST_DISABLED		0x3
+
+/* These timeouts are in us */
+#define OMAP4_MAX_MODULE_READY_TIME	2000
+#define OMAP4_MAX_MODULE_DISABLE_TIME	5000
+
+static bool _early_timeout = true;
+
+union omap4_timeout {
+	u32 cycles;
+	ktime_t start;
+};
+
+static u32 _omap4_idlest(u32 val)
+{
+	val &= OMAP4_IDLEST_MASK;
+	val >>= OMAP4_IDLEST_SHIFT;
+
+	return val;
+}
+
+static bool _omap4_is_idle(u32 val)
+{
+	val = _omap4_idlest(val);
+
+	return val == CLKCTRL_IDLEST_DISABLED;
+}
+
+static bool _omap4_is_ready(u32 val)
+{
+	val = _omap4_idlest(val);
+
+	return val == CLKCTRL_IDLEST_FUNCTIONAL ||
+	       val == CLKCTRL_IDLEST_INTERFACE_IDLE;
+}
+
+static bool _omap4_is_timeout(union omap4_timeout *time, u32 timeout)
+{
+	if (unlikely(_early_timeout)) {
+		if (time->cycles++ < timeout) {
+			udelay(1);
+			return false;
+		}
+	} else {
+		if (!ktime_to_ns(time->start)) {
+			time->start = ktime_get();
+			return false;
+		}
+
+		if (ktime_us_delta(ktime_get(), time->start) < timeout) {
+			cpu_relax();
+			return false;
+		}
+	}
+
+	return true;
+}
+
+static int __init _omap4_disable_early_timeout(void)
+{
+	_early_timeout = false;
+
+	return 0;
+}
+arch_initcall(_omap4_disable_early_timeout);
+
+static int _omap4_hwmod_clk_enable(struct clk_hw *hw)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+	u32 val;
+	int ret;
+	union omap4_timeout timeout = { 0 };
+
+	if (!clk->enable_bit)
+		return 0;
+
+	if (clk->clkdm) {
+		ret = ti_clk_ll_ops->clkdm_clk_enable(clk->clkdm, hw->clk);
+		if (ret) {
+			WARN(1,
+			     "%s: could not enable %s's clockdomain %s: %d\n",
+			     __func__, clk_hw_get_name(hw),
+			     clk->clkdm_name, ret);
+			return ret;
+		}
+	}
+
+	val = ti_clk_ll_ops->clk_readl(clk->enable_reg);
+
+	val &= ~OMAP4_MODULEMODE_MASK;
+	val |= clk->enable_bit;
+
+	ti_clk_ll_ops->clk_writel(val, clk->enable_reg);
+
+	if (clk->flags & NO_IDLEST)
+		return 0;
+
+	/* Wait until module is enabled */
+	while (!_omap4_is_ready(ti_clk_ll_ops->clk_readl(clk->enable_reg))) {
+		if (_omap4_is_timeout(&timeout, OMAP4_MAX_MODULE_READY_TIME)) {
+			pr_err("%s: failed to enable\n", clk_hw_get_name(hw));
+			return -EBUSY;
+		}
+	}
+
+	return 0;
+}
+
+static void _omap4_hwmod_clk_disable(struct clk_hw *hw)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+	u32 val;
+	union omap4_timeout timeout = { 0 };
+
+	if (!clk->enable_bit)
+		return;
+
+	val = ti_clk_ll_ops->clk_readl(clk->enable_reg);
+
+	val &= ~OMAP4_MODULEMODE_MASK;
+
+	ti_clk_ll_ops->clk_writel(val, clk->enable_reg);
+
+	if (clk->flags & NO_IDLEST)
+		return;
+
+	/* Wait until module is disabled */
+	while (!_omap4_is_idle(ti_clk_ll_ops->clk_readl(clk->enable_reg))) {
+		if (_omap4_is_timeout(&timeout,
+				      OMAP4_MAX_MODULE_DISABLE_TIME)) {
+			pr_err("%s: failed to disable\n", clk_hw_get_name(hw));
+			break;
+		}
+	}
+
+	if (clk->clkdm)
+		ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk);
+}
+
+static int _omap4_hwmod_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+	u32 val;
+
+	val = ti_clk_ll_ops->clk_readl(clk->enable_reg);
+
+	if (val & clk->enable_bit)
+		return 1;
+
+	return 0;
+}
+
+static const struct clk_ops omap4_module_clk_ops = {
+	.enable		= _omap4_hwmod_clk_enable,
+	.disable	= _omap4_hwmod_clk_disable,
+	.is_enabled	= _omap4_hwmod_clk_is_enabled,
+};
+
+static void __init _of_ti_hwmod_clk_setup(struct device_node *node,
+					  u8 modulemode, u8 flags)
+{
+	const char *parent_name;
+	void __iomem *reg;
+	u8 enable_bit;
+	struct clk_hw_omap *clk_hw;
+	struct clk_init_data init = { NULL };
+	struct clk *clk;
+
+	reg = ti_clk_get_reg_addr(node, 0);
+	if (IS_ERR(reg))
+		return;
+
+	parent_name = of_clk_get_parent_name(node, 0);
+	if (!parent_name) {
+		pr_err("%s must have 1 parent\n", node->name);
+		return;
+	}
+
+	enable_bit = modulemode;
+
+	clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
+
+	clk_hw->flags = flags;
+
+	clk_hw->enable_reg = reg;
+	clk_hw->enable_bit = enable_bit;
+
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+	init.flags = 0;
+
+	init.ops = &omap4_module_clk_ops;
+	clk_hw->hw.init = &init;
+	init.name = node->name;
+
+	clk = clk_register(NULL, &clk_hw->hw);
+
+	if (!IS_ERR(clk))
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+
+static void __init of_ti_omap4_hwmod_clk_setup(struct device_node *node)
+{
+	_of_ti_hwmod_clk_setup(node, 0, 0);
+}
+
+CLK_OF_DECLARE(ti_omap4_hwmod_clk, "ti,omap4-mod-clock",
+	       of_ti_omap4_hwmod_clk_setup);
+
+static void __init of_ti_omap4_hwmod_hw_clk_setup(struct device_node *node)
+{
+	_of_ti_hwmod_clk_setup(node, MODULEMODE_HWCTRL, 0);
+}
+
+CLK_OF_DECLARE(ti_omap4_hwmod_hw_clk, "ti,omap4-hw-mod-clock",
+	       of_ti_omap4_hwmod_hw_clk_setup);
+
+static void __init of_ti_omap4_hwmod_sw_clk_setup(struct device_node *node)
+{
+	_of_ti_hwmod_clk_setup(node, MODULEMODE_SWCTRL, 0);
+}
+
+CLK_OF_DECLARE(ti_omap4_hwmod_sw_clk, "ti,omap4-sw-mod-clock",
+	       of_ti_omap4_hwmod_sw_clk_setup);
+
+static void __init
+of_ti_omap4_hwmod_sw_no_idlest_clk_setup(struct device_node *node)
+{
+	_of_ti_hwmod_clk_setup(node, MODULEMODE_SWCTRL, NO_IDLEST);
+}
+
+CLK_OF_DECLARE(ti_omap4_hwmod_sw_no_idlest_clk,
+	       "ti,omap4-sw-no-idlest-mod-clock",
+	       of_ti_omap4_hwmod_sw_no_idlest_clk_setup);
+
+static u8 _omap4_mux_mod_get_parent(struct clk_hw *hw)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+	struct clk_hw *mux_hw = clk->mux;
+
+	__clk_hw_set_clk(mux_hw, hw);
+
+	return ti_clk_mux_get_parent(mux_hw);
+}
+
+static int _omap4_mux_mod_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+	struct clk_hw *mux_hw = clk->mux;
+
+	__clk_hw_set_clk(mux_hw, hw);
+
+	return ti_clk_mux_set_parent(mux_hw, index);
+}
+
+static int _omap4_mux_mod_determine_rate(struct clk_hw *hw,
+					 struct clk_rate_request *req)
+{
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+	struct clk_hw *mux_hw = clk->mux;
+
+	__clk_hw_set_clk(mux_hw, hw);
+
+	return __clk_mux_determine_rate(mux_hw, req);
+}
+
+static const struct clk_ops omap4_mux_module_clk_ops = {
+	.enable		= _omap4_hwmod_clk_enable,
+	.disable	= _omap4_hwmod_clk_disable,
+	.is_enabled	= _omap4_hwmod_clk_is_enabled,
+	.get_parent	= _omap4_mux_mod_get_parent,
+	.set_parent	= _omap4_mux_mod_set_parent,
+	.determine_rate	= _omap4_mux_mod_determine_rate,
+};
+
+static void __init _of_ti_omap4_hwmod_mux_clk_setup(struct device_node *node,
+						    u8 modulemode)
+{
+	struct clk_hw_omap *gate;
+	struct clk_mux *mux;
+	int num_parents;
+	const char **parent_names = NULL;
+	u32 val;
+	void __iomem *reg;
+	struct clk *clk;
+	struct clk_init_data init = { NULL };
+
+	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+
+	if (!mux || !gate)
+		goto err;
+
+	gate->mux = &mux->hw;
+
+	if (!of_property_read_u32(node, "ti,bit-shift", &val))
+		mux->shift = val;
+
+	if (of_property_read_bool(node, "ti,index-starts-at-one"))
+		mux->flags |= CLK_MUX_INDEX_ONE;
+
+	num_parents = of_clk_get_parent_count(node);
+
+	if (num_parents < 2) {
+		pr_err("%s: must have parents\n", node->name);
+		goto err;
+	}
+
+	parent_names = kzalloc((sizeof(char *) * num_parents), GFP_KERNEL);
+	if (!parent_names)
+		goto err;
+
+	of_clk_parent_fill(node, parent_names, num_parents);
+
+	reg = ti_clk_get_reg_addr(node, 0);
+
+	if (IS_ERR(reg))
+		goto err;
+
+	gate->enable_bit = modulemode;
+	gate->enable_reg = reg;
+
+	reg = ti_clk_get_reg_addr(node, 1);
+
+	if (IS_ERR(reg))
+		goto err;
+
+	mux->reg = reg;
+
+	init.parent_names = parent_names;
+	init.num_parents = num_parents;
+	init.flags = 0;
+
+	init.ops = &omap4_mux_module_clk_ops;
+	gate->hw.init = &init;
+	init.name = node->name;
+
+	clk = clk_register(NULL, &gate->hw);
+
+	if (!IS_ERR(clk)) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		goto cleanup;
+	}
+err:
+	kfree(gate);
+	kfree(mux);
+
+cleanup:
+	kfree(parent_names);
+}
+
+static void __init of_ti_omap4_hwmod_mux_clk_setup(struct device_node *node)
+{
+	_of_ti_omap4_hwmod_mux_clk_setup(node, 0);
+}
+
+CLK_OF_DECLARE(ti_omap4_mux_hwmod_clk, "ti,omap4-mux-mod-clock",
+	       of_ti_omap4_hwmod_mux_clk_setup);
+
+static void __init of_ti_omap4_hwmod_sw_mux_clk_setup(struct device_node *node)
+{
+	_of_ti_omap4_hwmod_mux_clk_setup(node, MODULEMODE_SWCTRL);
+}
+
+CLK_OF_DECLARE(ti_omap4_mux_hwmod_sw_clk, "ti,omap4-sw-mux-mod-clock",
+	       of_ti_omap4_hwmod_sw_mux_clk_setup);
+
+static void __init of_ti_omap4_hwmod_hw_mux_clk_setup(struct device_node *node)
+{
+	_of_ti_omap4_hwmod_mux_clk_setup(node, MODULEMODE_HWCTRL);
+}
+
+CLK_OF_DECLARE(ti_omap4_mux_hwmod_hw_clk, "ti,omap4-hw-mux-mod-clock",
+	       of_ti_omap4_hwmod_hw_mux_clk_setup);
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 07308db..043966e 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -129,6 +129,7 @@ struct clk_hw_omap_ops {
  * @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg)
  * @flags: see "struct clk.flags possibilities" above
  * @clksel_reg: for clksel clks, register va containing src/divisor select
+ * @mux: for module clocks, pointer to the optional mux component
  * @dpll_data: for DPLLs, pointer to struct dpll_data for this clock
  * @clkdm_name: clockdomain name that this clock is contained in
  * @clkdm: pointer to struct clockdomain, resolved from @clkdm_name at runtime
@@ -143,6 +144,7 @@ struct clk_hw_omap {
 	u8			enable_bit;
 	u8			flags;
 	void __iomem		*clksel_reg;
+	struct clk_hw		*mux;
 	struct dpll_data	*dpll_data;
 	const char		*clkdm_name;
 	struct clockdomain	*clkdm;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv3 2/7] clk: ti: add clkdev get helper
  2016-06-30 14:13 ` [PATCHv3 2/7] clk: ti: add clkdev get helper Tero Kristo
@ 2016-07-12 10:22   ` Russell King - ARM Linux
  2016-07-12 15:18     ` Tero Kristo
  0 siblings, 1 reply; 13+ messages in thread
From: Russell King - ARM Linux @ 2016-07-12 10:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jun 30, 2016 at 05:13:33PM +0300, Tero Kristo wrote:
>  /**
> + * ti_clk_get - lookup a TI clock handle
> + * @dev_id: device to lookup clock for
> + * @con_id: connection ID to find
> + *
> + * Searches for a TI clock handle based on the DT node name.
> + * Returns the pointer to the clock handle, or ERR_PTR in failure.
> + */
> +static struct clk *ti_clk_get(const char *dev_id, const char *con_id)
> +{
> +	struct of_phandle_args clkspec;
> +	struct device_node *node;
> +	struct clk *clk;
> +
> +	/* Only check for cases of type clk_get_sys(NULL, "xyz") */
> +	if (dev_id || !con_id)
> +		return ERR_PTR(-ENOENT);
> +
> +	if (of_have_populated_dt()) {
> +		node = of_find_node_by_name(NULL, con_id);
> +		clkspec.np = node;
> +		clk = of_clk_get_from_provider(&clkspec);
> +
> +		if (!IS_ERR(clk))
> +			return clk;
> +	}
> +
> +	return ERR_PTR(-ENOENT);
> +}

I _really_ don't like this.  This takes us back to the totally broken
idea, that's already been proven to be greatly harmful in OMAP land,
that the "con_id" is not a _DEVICE SPECIFIC CONNECTION NAME_ but is a
CLOCK NAME.  The connection ID is supposed to be a static string in
the requestor of the clock, not some random string picked out from
DT.

This series started out with the assertion that the new clkdev hook
was to avoid registering lots of clock aliases, but it seems with
this patch we're going to end up with lots of specifically named
nodes in DT instead.  It's just moving the problem to somewhere else.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCHv3 2/7] clk: ti: add clkdev get helper
  2016-07-12 10:22   ` Russell King - ARM Linux
@ 2016-07-12 15:18     ` Tero Kristo
  2016-07-12 15:34       ` Russell King - ARM Linux
  0 siblings, 1 reply; 13+ messages in thread
From: Tero Kristo @ 2016-07-12 15:18 UTC (permalink / raw)
  To: linux-arm-kernel

On 12/07/16 13:22, Russell King - ARM Linux wrote:
> On Thu, Jun 30, 2016 at 05:13:33PM +0300, Tero Kristo wrote:
>>   /**
>> + * ti_clk_get - lookup a TI clock handle
>> + * @dev_id: device to lookup clock for
>> + * @con_id: connection ID to find
>> + *
>> + * Searches for a TI clock handle based on the DT node name.
>> + * Returns the pointer to the clock handle, or ERR_PTR in failure.
>> + */
>> +static struct clk *ti_clk_get(const char *dev_id, const char *con_id)
>> +{
>> +	struct of_phandle_args clkspec;
>> +	struct device_node *node;
>> +	struct clk *clk;
>> +
>> +	/* Only check for cases of type clk_get_sys(NULL, "xyz") */
>> +	if (dev_id || !con_id)
>> +		return ERR_PTR(-ENOENT);
>> +
>> +	if (of_have_populated_dt()) {
>> +		node = of_find_node_by_name(NULL, con_id);
>> +		clkspec.np = node;
>> +		clk = of_clk_get_from_provider(&clkspec);
>> +
>> +		if (!IS_ERR(clk))
>> +			return clk;
>> +	}
>> +
>> +	return ERR_PTR(-ENOENT);
>> +}
>
> I _really_ don't like this.  This takes us back to the totally broken
> idea, that's already been proven to be greatly harmful in OMAP land,
> that the "con_id" is not a _DEVICE SPECIFIC CONNECTION NAME_ but is a
> CLOCK NAME.  The connection ID is supposed to be a static string in
> the requestor of the clock, not some random string picked out from
> DT.

What is the harm in that actually? I have most likely missed some 
discussion but please educate me. The problem is, we are already using 
this convention all over the place in the kernel (not only OMAPs), and 
trying to clean up the kernel requires some intermediate steps being 
taken, otherwise we end up doing all the clean-ups in a single massive 
patch I fear (change all the hwmod data + clock data + any 
implementations related to these at the same time.)

This specific implementation should be possible to deprecate later once 
the hwmod database is gone btw, and is mostly required for hwmod data 
only (+ OMAP timer implementation, maybe some others.) The biggest 
abuser of clk_get interface atm is omap-hwmod.

>
> This series started out with the assertion that the new clkdev hook
> was to avoid registering lots of clock aliases, but it seems with
> this patch we're going to end up with lots of specifically named
> nodes in DT instead.  It's just moving the problem to somewhere else.

That is true, it will end up adding new DT nodes. However, as OMAP 
already is doing this extensively, I wonder what would be the 
alternative. Maybe move all the clock data back to kernel space to 
increase the size of multi-v7 builds?

-Tero

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCHv3 2/7] clk: ti: add clkdev get helper
  2016-07-12 15:18     ` Tero Kristo
@ 2016-07-12 15:34       ` Russell King - ARM Linux
  2016-07-12 15:49         ` Tero Kristo
  0 siblings, 1 reply; 13+ messages in thread
From: Russell King - ARM Linux @ 2016-07-12 15:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 12, 2016 at 06:18:01PM +0300, Tero Kristo wrote:
> On 12/07/16 13:22, Russell King - ARM Linux wrote:
> >On Thu, Jun 30, 2016 at 05:13:33PM +0300, Tero Kristo wrote:
> >>  /**
> >>+ * ti_clk_get - lookup a TI clock handle
> >>+ * @dev_id: device to lookup clock for
> >>+ * @con_id: connection ID to find
> >>+ *
> >>+ * Searches for a TI clock handle based on the DT node name.
> >>+ * Returns the pointer to the clock handle, or ERR_PTR in failure.
> >>+ */
> >>+static struct clk *ti_clk_get(const char *dev_id, const char *con_id)
> >>+{
> >>+	struct of_phandle_args clkspec;
> >>+	struct device_node *node;
> >>+	struct clk *clk;
> >>+
> >>+	/* Only check for cases of type clk_get_sys(NULL, "xyz") */
> >>+	if (dev_id || !con_id)
> >>+		return ERR_PTR(-ENOENT);
> >>+
> >>+	if (of_have_populated_dt()) {
> >>+		node = of_find_node_by_name(NULL, con_id);
> >>+		clkspec.np = node;
> >>+		clk = of_clk_get_from_provider(&clkspec);
> >>+
> >>+		if (!IS_ERR(clk))
> >>+			return clk;
> >>+	}
> >>+
> >>+	return ERR_PTR(-ENOENT);
> >>+}
> >
> >I _really_ don't like this.  This takes us back to the totally broken
> >idea, that's already been proven to be greatly harmful in OMAP land,
> >that the "con_id" is not a _DEVICE SPECIFIC CONNECTION NAME_ but is a
> >CLOCK NAME.  The connection ID is supposed to be a static string in
> >the requestor of the clock, not some random string picked out from
> >DT.
> 
> What is the harm in that actually? I have most likely missed some discussion
> but please educate me.

The problem is that we end up with drivers that we end up needing platform
information to know what clocks they should get, and what "connection names"
to use to get their clocks.

We've been there before with OMAP, pre-DT times, and I fixed it up by
creating clkdev and converting much of OMAP over to clkdev, doing
everything the right way.  Now, we're heading around the same mistake
that I already solved several years ago.

It's _well_ documented that the _connection id_ is a connection id and
not a clock name.  It's been documented that way ever since the clk API
was first published, and I'm on record for having brought up this point
_many_ times.

So, when I see something reintroducing ways to persist with this crap,
I'm just not going to allow it.  This is 2016 after all, it's a full
_ten_ years after this API was created.

> The problem is, we are already using this convention
> all over the place in the kernel (not only OMAPs), and trying to clean up
> the kernel requires some intermediate steps being taken, otherwise we end up
> doing all the clean-ups in a single massive patch I fear (change all the
> hwmod data + clock data + any implementations related to these at the same
> time.)

This isn't an intermediate step if you're having to put stuff into DT
in order to support it.  Anything you throw into DT needs to be supported
for years by the kernel, since we have the requirement that newer kernels
are bootable with older DT files without regression.  That effectively
means we'll never be able to remove this, and we'll end up fighting other
people abusing the hook.

> That is true, it will end up adding new DT nodes. However, as OMAP already
> is doing this extensively, I wonder what would be the alternative. Maybe
> move all the clock data back to kernel space to increase the size of
> multi-v7 builds?

Why can't you use:

	clocks = <&clk_provider fck_index>, <&clk_provider ick_index>, ...;
	clock-names = "fck", "ick", ...;

when describing the hardware?  If you don't have a struct device, but
only a struct device_node, you can use of_clk_get(), which allows you
to omit the connection ID and look up by index in the clocks property.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCHv3 2/7] clk: ti: add clkdev get helper
  2016-07-12 15:34       ` Russell King - ARM Linux
@ 2016-07-12 15:49         ` Tero Kristo
  2016-07-12 17:40           ` Michael Turquette
  0 siblings, 1 reply; 13+ messages in thread
From: Tero Kristo @ 2016-07-12 15:49 UTC (permalink / raw)
  To: linux-arm-kernel

On 12/07/16 18:34, Russell King - ARM Linux wrote:
> On Tue, Jul 12, 2016 at 06:18:01PM +0300, Tero Kristo wrote:
>> On 12/07/16 13:22, Russell King - ARM Linux wrote:
>>> On Thu, Jun 30, 2016 at 05:13:33PM +0300, Tero Kristo wrote:
>>>>   /**
>>>> + * ti_clk_get - lookup a TI clock handle
>>>> + * @dev_id: device to lookup clock for
>>>> + * @con_id: connection ID to find
>>>> + *
>>>> + * Searches for a TI clock handle based on the DT node name.
>>>> + * Returns the pointer to the clock handle, or ERR_PTR in failure.
>>>> + */
>>>> +static struct clk *ti_clk_get(const char *dev_id, const char *con_id)
>>>> +{
>>>> +	struct of_phandle_args clkspec;
>>>> +	struct device_node *node;
>>>> +	struct clk *clk;
>>>> +
>>>> +	/* Only check for cases of type clk_get_sys(NULL, "xyz") */
>>>> +	if (dev_id || !con_id)
>>>> +		return ERR_PTR(-ENOENT);
>>>> +
>>>> +	if (of_have_populated_dt()) {
>>>> +		node = of_find_node_by_name(NULL, con_id);
>>>> +		clkspec.np = node;
>>>> +		clk = of_clk_get_from_provider(&clkspec);
>>>> +
>>>> +		if (!IS_ERR(clk))
>>>> +			return clk;
>>>> +	}
>>>> +
>>>> +	return ERR_PTR(-ENOENT);
>>>> +}
>>>
>>> I _really_ don't like this.  This takes us back to the totally broken
>>> idea, that's already been proven to be greatly harmful in OMAP land,
>>> that the "con_id" is not a _DEVICE SPECIFIC CONNECTION NAME_ but is a
>>> CLOCK NAME.  The connection ID is supposed to be a static string in
>>> the requestor of the clock, not some random string picked out from
>>> DT.
>>
>> What is the harm in that actually? I have most likely missed some discussion
>> but please educate me.
>
> The problem is that we end up with drivers that we end up needing platform
> information to know what clocks they should get, and what "connection names"
> to use to get their clocks.
>
> We've been there before with OMAP, pre-DT times, and I fixed it up by
> creating clkdev and converting much of OMAP over to clkdev, doing
> everything the right way.  Now, we're heading around the same mistake
> that I already solved several years ago.
>
> It's _well_ documented that the _connection id_ is a connection id and
> not a clock name.  It's been documented that way ever since the clk API
> was first published, and I'm on record for having brought up this point
> _many_ times.

Yeah I know this is documented this way, the problem is we have plenty 
of code around which doesn't really use it this way. >.<

>
> So, when I see something reintroducing ways to persist with this crap,
> I'm just not going to allow it.  This is 2016 after all, it's a full
> _ten_ years after this API was created.

Ok fair enough, lets try to figure out something else. I was pretty much 
worried before posting this patch/approach that you will shoot it down, 
thus was requesting your feedback specifically. :P

>
>> The problem is, we are already using this convention
>> all over the place in the kernel (not only OMAPs), and trying to clean up
>> the kernel requires some intermediate steps being taken, otherwise we end up
>> doing all the clean-ups in a single massive patch I fear (change all the
>> hwmod data + clock data + any implementations related to these at the same
>> time.)
>
> This isn't an intermediate step if you're having to put stuff into DT
> in order to support it.  Anything you throw into DT needs to be supported
> for years by the kernel, since we have the requirement that newer kernels
> are bootable with older DT files without regression.  That effectively
> means we'll never be able to remove this, and we'll end up fighting other
> people abusing the hook.
>
>> That is true, it will end up adding new DT nodes. However, as OMAP already
>> is doing this extensively, I wonder what would be the alternative. Maybe
>> move all the clock data back to kernel space to increase the size of
>> multi-v7 builds?
>
> Why can't you use:
>
> 	clocks = <&clk_provider fck_index>, <&clk_provider ick_index>, ...;
> 	clock-names = "fck", "ick", ...;
>
> when describing the hardware?  If you don't have a struct device, but
> only a struct device_node, you can use of_clk_get(), which allows you
> to omit the connection ID and look up by index in the clocks property.

That can be done. However, this means the individual clock provider must 
implement all the clocks in the kernel, adding loads of static data. And 
the data is different for every TI SoC we have out there in the 
wild..... aaand, we can't load the clock data as modules either due to 
early boot time dependencies. This is a royal mess we have here in our 
hands I am trying to clean-up somehow. I think I have posted several 
different series along the years trying to get rid of the hwmod static 
boot time dependency, but it always seems to get shot down. See this 
approach from last year for example:

http://comments.gmane.org/gmane.linux.ports.arm.omap/125555

-Tero

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCHv3 2/7] clk: ti: add clkdev get helper
  2016-07-12 15:49         ` Tero Kristo
@ 2016-07-12 17:40           ` Michael Turquette
  0 siblings, 0 replies; 13+ messages in thread
From: Michael Turquette @ 2016-07-12 17:40 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Tero Kristo (2016-07-12 08:49:15)
> On 12/07/16 18:34, Russell King - ARM Linux wrote:
> > On Tue, Jul 12, 2016 at 06:18:01PM +0300, Tero Kristo wrote:
> >> On 12/07/16 13:22, Russell King - ARM Linux wrote:
> >>> On Thu, Jun 30, 2016 at 05:13:33PM +0300, Tero Kristo wrote:
> >>>>   /**
> >>>> + * ti_clk_get - lookup a TI clock handle
> >>>> + * @dev_id: device to lookup clock for
> >>>> + * @con_id: connection ID to find
> >>>> + *
> >>>> + * Searches for a TI clock handle based on the DT node name.
> >>>> + * Returns the pointer to the clock handle, or ERR_PTR in failure.
> >>>> + */
> >>>> +static struct clk *ti_clk_get(const char *dev_id, const char *con_id)
> >>>> +{
> >>>> +  struct of_phandle_args clkspec;
> >>>> +  struct device_node *node;
> >>>> +  struct clk *clk;
> >>>> +
> >>>> +  /* Only check for cases of type clk_get_sys(NULL, "xyz") */
> >>>> +  if (dev_id || !con_id)
> >>>> +          return ERR_PTR(-ENOENT);
> >>>> +
> >>>> +  if (of_have_populated_dt()) {
> >>>> +          node = of_find_node_by_name(NULL, con_id);
> >>>> +          clkspec.np = node;
> >>>> +          clk = of_clk_get_from_provider(&clkspec);
> >>>> +
> >>>> +          if (!IS_ERR(clk))
> >>>> +                  return clk;
> >>>> +  }
> >>>> +
> >>>> +  return ERR_PTR(-ENOENT);
> >>>> +}
> >>>
> >>> I _really_ don't like this.  This takes us back to the totally broken
> >>> idea, that's already been proven to be greatly harmful in OMAP land,
> >>> that the "con_id" is not a _DEVICE SPECIFIC CONNECTION NAME_ but is a
> >>> CLOCK NAME.  The connection ID is supposed to be a static string in
> >>> the requestor of the clock, not some random string picked out from
> >>> DT.
> >>
> >> What is the harm in that actually? I have most likely missed some discussion
> >> but please educate me.
> >
> > The problem is that we end up with drivers that we end up needing platform
> > information to know what clocks they should get, and what "connection names"
> > to use to get their clocks.
> >
> > We've been there before with OMAP, pre-DT times, and I fixed it up by
> > creating clkdev and converting much of OMAP over to clkdev, doing
> > everything the right way.  Now, we're heading around the same mistake
> > that I already solved several years ago.
> >
> > It's _well_ documented that the _connection id_ is a connection id and
> > not a clock name.  It's been documented that way ever since the clk API
> > was first published, and I'm on record for having brought up this point
> > _many_ times.
> 
> Yeah I know this is documented this way, the problem is we have plenty 
> of code around which doesn't really use it this way. >.<
> 
> >
> > So, when I see something reintroducing ways to persist with this crap,
> > I'm just not going to allow it.  This is 2016 after all, it's a full
> > _ten_ years after this API was created.
> 
> Ok fair enough, lets try to figure out something else. I was pretty much 
> worried before posting this patch/approach that you will shoot it down, 
> thus was requesting your feedback specifically. :P
> 
> >
> >> The problem is, we are already using this convention
> >> all over the place in the kernel (not only OMAPs), and trying to clean up
> >> the kernel requires some intermediate steps being taken, otherwise we end up
> >> doing all the clean-ups in a single massive patch I fear (change all the
> >> hwmod data + clock data + any implementations related to these at the same
> >> time.)
> >
> > This isn't an intermediate step if you're having to put stuff into DT
> > in order to support it.  Anything you throw into DT needs to be supported
> > for years by the kernel, since we have the requirement that newer kernels
> > are bootable with older DT files without regression.  That effectively
> > means we'll never be able to remove this, and we'll end up fighting other
> > people abusing the hook.
> >
> >> That is true, it will end up adding new DT nodes. However, as OMAP already
> >> is doing this extensively, I wonder what would be the alternative. Maybe
> >> move all the clock data back to kernel space to increase the size of
> >> multi-v7 builds?
> >
> > Why can't you use:
> >
> >       clocks = <&clk_provider fck_index>, <&clk_provider ick_index>, ...;
> >       clock-names = "fck", "ick", ...;
> >
> > when describing the hardware?  If you don't have a struct device, but
> > only a struct device_node, you can use of_clk_get(), which allows you
> > to omit the connection ID and look up by index in the clocks property.
> 
> That can be done. However, this means the individual clock provider must 
> implement all the clocks in the kernel, adding loads of static data. And 

Clock provider drivers *should* initialize all of their clock data
statically. Are you trying to opportunistically register only the clocks
found in DT? This goes against the current direction of clock DT
bindings where we model only the controller and use it to hook up
provider and consumer resources. We are *not* using DT to enumerate
per-clock data.

> the data is different for every TI SoC we have out there in the 
> wild..... aaand, we can't load the clock data as modules either due to 
> early boot time dependencies. This is a royal mess we have here in our 

Boot time deps are a separate issue. On ARMv8 you can probably get away
with it due to architected timers not needing clocks very early.

If you have software dependencies caused by the hwmod framework, again
that is a separate issue from how you should structure your clock data
and your clock controller DT binding.

> hands I am trying to clean-up somehow. I think I have posted several 
> different series along the years trying to get rid of the hwmod static 
> boot time dependency, but it always seems to get shot down. See this 
> approach from last year for example:
> 
> http://comments.gmane.org/gmane.linux.ports.arm.omap/125555

Tony has had a dream to move the clk data into /lib/firmware for a
while. We've talked about that over beers before. But note that no one
else is doing that stuff and I would be happy for the OMAP clock code to
achieve style-parity with the more recent clock provider driver
submissions before going off and trying to do something fancy.

Regards,
Mike

> 
> -Tero

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2016-07-12 17:40 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-30 14:13 [PATCHv3 0/7] clk: ti add support for hwmod clk type Tero Kristo
2016-06-30 14:13 ` [PATCHv3 1/7] clkdev: add helper registration API Tero Kristo
2016-06-30 14:13 ` [PATCHv3 2/7] clk: ti: add clkdev get helper Tero Kristo
2016-07-12 10:22   ` Russell King - ARM Linux
2016-07-12 15:18     ` Tero Kristo
2016-07-12 15:34       ` Russell King - ARM Linux
2016-07-12 15:49         ` Tero Kristo
2016-07-12 17:40           ` Michael Turquette
2016-06-30 14:13 ` [PATCHv3 3/7] clk: ti: remove un-used definitions from public clk_hw_omap struct Tero Kristo
2016-06-30 14:13 ` [PATCHv3 4/7] clk: ti: mux: export mux clock APIs locally Tero Kristo
2016-06-30 14:13 ` [PATCHv3 5/7] clk: ti: am33xx: fix timer3/6 init time setup for module clocks Tero Kristo
2016-06-30 14:13 ` [PATCHv3 6/7] dt-bindings: clk: ti: Document module clock type Tero Kristo
2016-06-30 14:13 ` [PATCHv3 7/7] clk: ti: add support for omap4 module clocks Tero Kristo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).