All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v0 00/15] clk: st: Add new driver
@ 2014-02-27 15:24 ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: mturquette, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, rob, linux, devicetree, linux-doc, linux-kernel,
	linux-arm-kernel
  Cc: Lee Jones, Gabriel Fernandez

The goal of this series is to add Clocks support to ST SoCs.
The DT definition is added for STiH415 and STiH416 SoCs on
B2000 and B2020 boards.

The series has been tested working on STiH416-B2020 board.
It applies on top of v3.14-rc3.

Gabriel Fernandez (15):
  drivers: clk: st: Support for DIVMUX and PreDiv Clocks
  drivers: clk: st: Support for PLLs inside ClockGenA(s)
  drivers: clk: st: Support for VCC-mux and MUX clocks
  drivers: clk: st: Support for QUADFS inside ClockGenB/C/D/E/F
  drivers: clk: st: Support for ClockGenA9/DDR/GPU
  drivers: clk: st: Support for A9 MUX clocks
  clk: st: Adds divmux and prediv clock binding
  clk: st: Adds clockgen clock binding
  clk: st: Adds clockgen-vcc and clockgen-mux clock binding
  clk: st: Adds quadfs clock binding
  ARM: STi: DT: STiH416: 416 DT Entry for clockgen A0/1/10/11/12
  ARM: STi: DT: STiH416: 416 DT Entry for clockgen B/C/D/E/F
  ARM: STi: DT: STiH416: 416 DT Entry for clockgen A9/DDR/GPU
  ARM: STi: DT: STiH415: 415 DT Entry for clockgen A0/1/10/11/12
  ARM: STi: DT: STiH415: 415 DT Entry for clockgen A9

 .../bindings/clock/st/st,clkgen-divmux.txt         |   49 +
 .../devicetree/bindings/clock/st/st,clkgen-mux.txt |   36 +
 .../devicetree/bindings/clock/st/st,clkgen-pll.txt |   48 +
 .../bindings/clock/st/st,clkgen-prediv.txt         |   36 +
 .../devicetree/bindings/clock/st/st,clkgen-vcc.txt |   53 +
 .../devicetree/bindings/clock/st/st,clkgen.txt     |   83 ++
 .../devicetree/bindings/clock/st/st,quadfs.txt     |   45 +
 arch/arm/boot/dts/stih415-clks.h                   |   11 +
 arch/arm/boot/dts/stih415-clock.dtsi               |  530 +++++++++-
 arch/arm/boot/dts/stih415.dtsi                     |    6 +-
 arch/arm/boot/dts/stih416-clks.h                   |   11 +
 arch/arm/boot/dts/stih416-clock.dtsi               |  717 +++++++++++++-
 arch/arm/boot/dts/stih416.dtsi                     |    6 +-
 drivers/clk/Makefile                               |    1 +
 drivers/clk/st/Makefile                            |    1 +
 drivers/clk/st/clkgen-fsyn.c                       | 1039 ++++++++++++++++++++
 drivers/clk/st/clkgen-mux.c                        |  820 +++++++++++++++
 drivers/clk/st/clkgen-pll.c                        |  698 +++++++++++++
 drivers/clk/st/clkgen.h                            |   48 +
 19 files changed, 4214 insertions(+), 24 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen.txt
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,quadfs.txt
 create mode 100644 arch/arm/boot/dts/stih415-clks.h
 create mode 100644 arch/arm/boot/dts/stih416-clks.h
 create mode 100644 drivers/clk/st/Makefile
 create mode 100644 drivers/clk/st/clkgen-fsyn.c
 create mode 100644 drivers/clk/st/clkgen-mux.c
 create mode 100644 drivers/clk/st/clkgen-pll.c
 create mode 100644 drivers/clk/st/clkgen.h

-- 
1.9.0


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

* [PATCH v0 00/15] clk: st: Add new driver
@ 2014-02-27 15:24 ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

The goal of this series is to add Clocks support to ST SoCs.
The DT definition is added for STiH415 and STiH416 SoCs on
B2000 and B2020 boards.

The series has been tested working on STiH416-B2020 board.
It applies on top of v3.14-rc3.

Gabriel Fernandez (15):
  drivers: clk: st: Support for DIVMUX and PreDiv Clocks
  drivers: clk: st: Support for PLLs inside ClockGenA(s)
  drivers: clk: st: Support for VCC-mux and MUX clocks
  drivers: clk: st: Support for QUADFS inside ClockGenB/C/D/E/F
  drivers: clk: st: Support for ClockGenA9/DDR/GPU
  drivers: clk: st: Support for A9 MUX clocks
  clk: st: Adds divmux and prediv clock binding
  clk: st: Adds clockgen clock binding
  clk: st: Adds clockgen-vcc and clockgen-mux clock binding
  clk: st: Adds quadfs clock binding
  ARM: STi: DT: STiH416: 416 DT Entry for clockgen A0/1/10/11/12
  ARM: STi: DT: STiH416: 416 DT Entry for clockgen B/C/D/E/F
  ARM: STi: DT: STiH416: 416 DT Entry for clockgen A9/DDR/GPU
  ARM: STi: DT: STiH415: 415 DT Entry for clockgen A0/1/10/11/12
  ARM: STi: DT: STiH415: 415 DT Entry for clockgen A9

 .../bindings/clock/st/st,clkgen-divmux.txt         |   49 +
 .../devicetree/bindings/clock/st/st,clkgen-mux.txt |   36 +
 .../devicetree/bindings/clock/st/st,clkgen-pll.txt |   48 +
 .../bindings/clock/st/st,clkgen-prediv.txt         |   36 +
 .../devicetree/bindings/clock/st/st,clkgen-vcc.txt |   53 +
 .../devicetree/bindings/clock/st/st,clkgen.txt     |   83 ++
 .../devicetree/bindings/clock/st/st,quadfs.txt     |   45 +
 arch/arm/boot/dts/stih415-clks.h                   |   11 +
 arch/arm/boot/dts/stih415-clock.dtsi               |  530 +++++++++-
 arch/arm/boot/dts/stih415.dtsi                     |    6 +-
 arch/arm/boot/dts/stih416-clks.h                   |   11 +
 arch/arm/boot/dts/stih416-clock.dtsi               |  717 +++++++++++++-
 arch/arm/boot/dts/stih416.dtsi                     |    6 +-
 drivers/clk/Makefile                               |    1 +
 drivers/clk/st/Makefile                            |    1 +
 drivers/clk/st/clkgen-fsyn.c                       | 1039 ++++++++++++++++++++
 drivers/clk/st/clkgen-mux.c                        |  820 +++++++++++++++
 drivers/clk/st/clkgen-pll.c                        |  698 +++++++++++++
 drivers/clk/st/clkgen.h                            |   48 +
 19 files changed, 4214 insertions(+), 24 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen.txt
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,quadfs.txt
 create mode 100644 arch/arm/boot/dts/stih415-clks.h
 create mode 100644 arch/arm/boot/dts/stih416-clks.h
 create mode 100644 drivers/clk/st/Makefile
 create mode 100644 drivers/clk/st/clkgen-fsyn.c
 create mode 100644 drivers/clk/st/clkgen-mux.c
 create mode 100644 drivers/clk/st/clkgen-pll.c
 create mode 100644 drivers/clk/st/clkgen.h

-- 
1.9.0

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

* [PATCH v0 01/15] drivers: clk: st: Support for DIVMUX and PreDiv Clocks
  2014-02-27 15:24 ` Gabriel FERNANDEZ
  (?)
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  -1 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: mturquette, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, rob, linux, devicetree, linux-doc, linux-kernel,
	linux-arm-kernel
  Cc: Lee Jones, Gabriel Fernandez, Pankaj Dev

The patch supports the DIVMUX and PreDiv clocks used by ClockGenA(s)

DIVMUX clock : Divider-Multiplexer-Gate inside ClockGenA(s)
It includes support for each channel : 3-parent Multiplexer,
Divider for each Parent, Gate to switch OFF the output channel. The
clock is implemented using generic clocks implemented in the kernel
clk_divider and clk_mux.

PreDiv clock : Fixed Divider Clock used inside ClockGenA(s) to divide
the oscillator clock by factor-of-16. The clock is implemented using
generic clocks implemented in the kernel clk_divider.

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 drivers/clk/Makefile        |   1 +
 drivers/clk/st/Makefile     |   1 +
 drivers/clk/st/clkgen-mux.c | 529 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 531 insertions(+)
 create mode 100644 drivers/clk/st/Makefile
 create mode 100644 drivers/clk/st/clkgen-mux.c

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index a367a98..7867c511 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_ARCH_SHMOBILE_MULTI)	+= shmobile/
 obj-$(CONFIG_ARCH_SIRF)			+= sirf/
 obj-$(CONFIG_ARCH_SOCFPGA)		+= socfpga/
 obj-$(CONFIG_PLAT_SPEAR)		+= spear/
+obj-$(CONFIG_ARCH_STI)			+= st/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
 obj-$(CONFIG_ARCH_TEGRA)		+= tegra/
 obj-$(CONFIG_ARCH_OMAP2PLUS)		+= ti/
diff --git a/drivers/clk/st/Makefile b/drivers/clk/st/Makefile
new file mode 100644
index 0000000..e42b370
--- /dev/null
+++ b/drivers/clk/st/Makefile
@@ -0,0 +1 @@
+obj-y += clkgen-mux.o
diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c
new file mode 100644
index 0000000..65d702c
--- /dev/null
+++ b/drivers/clk/st/clkgen-mux.c
@@ -0,0 +1,529 @@
+/*
+ * clkgen-mux.c: ST GEN-MUX Clock driver
+ *
+ * Copyright (C) 2014 STMicroelectronics (R&D) Limited
+ *
+ * Authors: Stephen Gallimore <stephen.gallimore@st.com>
+ *	    Pankaj Dev <pankaj.dev@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/of_address.h>
+#include <linux/clk-provider.h>
+
+static DEFINE_SPINLOCK(clkgena_divmux_lock);
+
+static const char ** __init clkgen_mux_get_parents(struct device_node *np,
+						       int *num_parents)
+{
+	const char **parents;
+	int nparents, i;
+
+	nparents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+	if (WARN_ON(nparents <= 0))
+		return ERR_PTR(-EINVAL);
+
+	parents = kzalloc(nparents * sizeof(const char *), GFP_KERNEL);
+	if (!parents)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < nparents; i++)
+		parents[i] = of_clk_get_parent_name(np, i);
+
+	*num_parents = nparents;
+	return parents;
+}
+
+/**
+ * DOC: Clock mux with a programmable divider on each of its three inputs.
+ *      The mux has an input setting which effectively gates its output.
+ *
+ * Traits of this clock:
+ * prepare - clk_(un)prepare only ensures parent is (un)prepared
+ * enable - clk_enable and clk_disable are functional & control gating
+ * rate - set rate is supported
+ * parent - set/get parent
+ */
+
+#define NUM_INPUTS 3
+
+struct clkgena_divmux {
+	struct clk_hw hw;
+	/* Subclassed mux and divider structures */
+	struct clk_mux mux;
+	struct clk_divider div[NUM_INPUTS];
+	/* Enable/running feedback register bits for each input */
+	void __iomem *feedback_reg[NUM_INPUTS];
+	int feedback_bit_idx;
+
+	u8              muxsel;
+};
+
+#define to_clkgena_divmux(_hw) container_of(_hw, struct clkgena_divmux, hw)
+
+struct clkgena_divmux_data {
+	int num_outputs;
+	int mux_offset;
+	int mux_offset2;
+	int mux_start_bit;
+	int div_offsets[NUM_INPUTS];
+	int fb_offsets[NUM_INPUTS];
+	int fb_start_bit_idx;
+};
+
+#define CKGAX_CLKOPSRC_SWITCH_OFF 0x3
+
+static int clkgena_divmux_is_running(struct clkgena_divmux *mux)
+{
+	u32 regval = readl(mux->feedback_reg[mux->muxsel]);
+	u32 running = regval & BIT(mux->feedback_bit_idx);
+	return !!running;
+}
+
+static int clkgena_divmux_enable(struct clk_hw *hw)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+	struct clk_hw *mux_hw = &genamux->mux.hw;
+	unsigned long timeout;
+	int ret = 0;
+
+	mux_hw->clk = hw->clk;
+
+	ret = clk_mux_ops.set_parent(mux_hw, genamux->muxsel);
+	if (ret)
+		return ret;
+
+	timeout = jiffies + msecs_to_jiffies(10);
+
+	while (!clkgena_divmux_is_running(genamux)) {
+		if (time_after(jiffies, timeout))
+			return -ETIMEDOUT;
+		cpu_relax();
+	}
+
+	return 0;
+}
+
+static void clkgena_divmux_disable(struct clk_hw *hw)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+	struct clk_hw *mux_hw = &genamux->mux.hw;
+
+	mux_hw->clk = hw->clk;
+
+	clk_mux_ops.set_parent(mux_hw, CKGAX_CLKOPSRC_SWITCH_OFF);
+}
+
+static int clkgena_divmux_is_enabled(struct clk_hw *hw)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+	struct clk_hw *mux_hw = &genamux->mux.hw;
+
+	mux_hw->clk = hw->clk;
+
+	return (s8)clk_mux_ops.get_parent(mux_hw) > 0;
+}
+
+u8 clkgena_divmux_get_parent(struct clk_hw *hw)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+	struct clk_hw *mux_hw = &genamux->mux.hw;
+
+	mux_hw->clk = hw->clk;
+
+	genamux->muxsel = clk_mux_ops.get_parent(mux_hw);
+	if ((s8)genamux->muxsel < 0) {
+		pr_debug("%s: %s: Invalid parent, setting to default.\n",
+		      __func__, __clk_get_name(hw->clk));
+		genamux->muxsel = 0;
+	}
+
+	return genamux->muxsel;
+}
+
+static int clkgena_divmux_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+
+	if (index >= CKGAX_CLKOPSRC_SWITCH_OFF)
+		return -EINVAL;
+
+	genamux->muxsel = index;
+
+	/*
+	 * If the mux is already enabled, call enable directly to set the
+	 * new mux position and wait for it to start running again. Otherwise
+	 * do nothing.
+	 */
+	if (clkgena_divmux_is_enabled(hw))
+		clkgena_divmux_enable(hw);
+
+	return 0;
+}
+
+unsigned long clkgena_divmux_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+	struct clk_hw *div_hw = &genamux->div[genamux->muxsel].hw;
+
+	div_hw->clk = hw->clk;
+
+	return clk_divider_ops.recalc_rate(div_hw, parent_rate);
+}
+
+static int clkgena_divmux_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+	struct clk_hw *div_hw = &genamux->div[genamux->muxsel].hw;
+
+	div_hw->clk = hw->clk;
+
+	return clk_divider_ops.set_rate(div_hw, rate, parent_rate);
+}
+
+static long clkgena_divmux_round_rate(struct clk_hw *hw, unsigned long rate,
+				   unsigned long *prate)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+	struct clk_hw *div_hw = &genamux->div[genamux->muxsel].hw;
+
+	div_hw->clk = hw->clk;
+
+	return clk_divider_ops.round_rate(div_hw, rate, prate);
+}
+
+static const struct clk_ops clkgena_divmux_ops = {
+	.enable = clkgena_divmux_enable,
+	.disable = clkgena_divmux_disable,
+	.is_enabled = clkgena_divmux_is_enabled,
+	.get_parent = clkgena_divmux_get_parent,
+	.set_parent = clkgena_divmux_set_parent,
+	.round_rate = clkgena_divmux_round_rate,
+	.recalc_rate = clkgena_divmux_recalc_rate,
+	.set_rate = clkgena_divmux_set_rate,
+};
+
+/**
+ * clk_register_genamux - register a genamux clock with the clock framework
+ */
+struct clk *clk_register_genamux(const char *name,
+				const char **parent_names, u8 num_parents,
+				void __iomem *reg,
+				const struct clkgena_divmux_data *muxdata,
+				u32 idx)
+{
+	/*
+	 * Fixed constants across all ClockgenA variants
+	 */
+	const int mux_width = 2;
+	const int divider_width = 5;
+	struct clkgena_divmux *genamux;
+	struct clk *clk;
+	struct clk_init_data init;
+	int i;
+
+	genamux = kzalloc(sizeof(*genamux), GFP_KERNEL);
+	if (!genamux)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &clkgena_divmux_ops;
+	init.flags = CLK_IS_BASIC;
+	init.parent_names = parent_names;
+	init.num_parents = num_parents;
+
+	genamux->mux.lock  = &clkgena_divmux_lock;
+	genamux->mux.mask = BIT(mux_width) - 1;
+	genamux->mux.shift = muxdata->mux_start_bit + (idx * mux_width);
+	if (genamux->mux.shift > 31) {
+		/*
+		 * We have spilled into the second mux register so
+		 * adjust the register address and the bit shift accordingly
+		 */
+		genamux->mux.reg = reg + muxdata->mux_offset2;
+		genamux->mux.shift -= 32;
+	} else {
+		genamux->mux.reg   = reg + muxdata->mux_offset;
+	}
+
+	for (i = 0; i < NUM_INPUTS; i++) {
+		/*
+		 * Divider config for each input
+		 */
+		void __iomem *divbase = reg + muxdata->div_offsets[i];
+		genamux->div[i].width = divider_width;
+		genamux->div[i].reg = divbase + (idx * sizeof(u32));
+
+		/*
+		 * Mux enabled/running feedback register for each input.
+		 */
+		genamux->feedback_reg[i] = reg + muxdata->fb_offsets[i];
+	}
+
+	genamux->feedback_bit_idx = muxdata->fb_start_bit_idx + idx;
+	genamux->hw.init = &init;
+
+	clk = clk_register(NULL, &genamux->hw);
+	if (IS_ERR(clk)) {
+		kfree(genamux);
+		goto err;
+	}
+
+	pr_debug("%s: parent %s rate %lu\n",
+			__clk_get_name(clk),
+			__clk_get_name(clk_get_parent(clk)),
+			clk_get_rate(clk));
+err:
+	return clk;
+}
+
+static struct clkgena_divmux_data st_divmux_c65hs = {
+	.num_outputs = 4,
+	.mux_offset = 0x14,
+	.mux_start_bit = 0,
+	.div_offsets = { 0x800, 0x900, 0xb00 },
+	.fb_offsets = { 0x18, 0x1c, 0x20 },
+	.fb_start_bit_idx = 0,
+};
+
+static struct clkgena_divmux_data st_divmux_c65ls = {
+	.num_outputs = 14,
+	.mux_offset = 0x14,
+	.mux_offset2 = 0x24,
+	.mux_start_bit = 8,
+	.div_offsets = { 0x810, 0xa10, 0xb10 },
+	.fb_offsets = { 0x18, 0x1c, 0x20 },
+	.fb_start_bit_idx = 4,
+};
+
+static struct clkgena_divmux_data st_divmux_c32odf0 = {
+	.num_outputs = 8,
+	.mux_offset = 0x1c,
+	.mux_start_bit = 0,
+	.div_offsets = { 0x800, 0x900, 0xa60 },
+	.fb_offsets = { 0x2c, 0x24, 0x28 },
+	.fb_start_bit_idx = 0,
+};
+
+static struct clkgena_divmux_data st_divmux_c32odf1 = {
+	.num_outputs = 8,
+	.mux_offset = 0x1c,
+	.mux_start_bit = 16,
+	.div_offsets = { 0x820, 0x980, 0xa80 },
+	.fb_offsets = { 0x2c, 0x24, 0x28 },
+	.fb_start_bit_idx = 8,
+};
+
+static struct clkgena_divmux_data st_divmux_c32odf2 = {
+	.num_outputs = 8,
+	.mux_offset = 0x20,
+	.mux_start_bit = 0,
+	.div_offsets = { 0x840, 0xa20, 0xb10 },
+	.fb_offsets = { 0x2c, 0x24, 0x28 },
+	.fb_start_bit_idx = 16,
+};
+
+static struct clkgena_divmux_data st_divmux_c32odf3 = {
+	.num_outputs = 8,
+	.mux_offset = 0x20,
+	.mux_start_bit = 16,
+	.div_offsets = { 0x860, 0xa40, 0xb30 },
+	.fb_offsets = { 0x2c, 0x24, 0x28 },
+	.fb_start_bit_idx = 24,
+};
+
+static struct of_device_id clkgena_divmux_of_match[] = {
+	{
+		.compatible = "st,clkgena-divmux-c65-hs",
+		.data = &st_divmux_c65hs,
+	},
+	{
+		.compatible = "st,clkgena-divmux-c65-ls",
+		.data = &st_divmux_c65ls,
+	},
+	{
+		.compatible = "st,clkgena-divmux-c32-odf0",
+		.data = &st_divmux_c32odf0,
+	},
+	{
+		.compatible = "st,clkgena-divmux-c32-odf1",
+		.data = &st_divmux_c32odf1,
+	},
+	{
+		.compatible = "st,clkgena-divmux-c32-odf2",
+		.data = &st_divmux_c32odf2,
+	},
+	{
+		.compatible = "st,clkgena-divmux-c32-odf3",
+		.data = &st_divmux_c32odf3,
+	},
+	{}
+};
+
+static void __iomem * __init clkgen_get_register_base(
+				struct device_node *np)
+{
+	struct device_node *pnode;
+	void __iomem *reg = NULL;
+
+	pnode = of_get_parent(np);
+	if (!pnode)
+		return NULL;
+
+	reg = of_iomap(pnode, 0);
+
+	of_node_put(pnode);
+	return reg;
+}
+
+void __init st_of_clkgena_divmux_setup(struct device_node *np)
+{
+	const struct of_device_id *match;
+	const struct clkgena_divmux_data *data;
+	struct clk_onecell_data *clk_data;
+	void __iomem *reg;
+	const char **parents;
+	int num_parents = 0, i;
+
+	match = of_match_node(clkgena_divmux_of_match, np);
+	if (WARN_ON(!match))
+		return;
+
+	data = (struct clkgena_divmux_data *)match->data;
+
+	reg = clkgen_get_register_base(np);
+	if (!reg)
+		return;
+
+	parents = clkgen_mux_get_parents(np, &num_parents);
+	if (IS_ERR(parents))
+		return;
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		goto err;
+
+	clk_data->clk_num = data->num_outputs;
+	clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *),
+				 GFP_KERNEL);
+
+	if (!clk_data->clks)
+		goto err;
+
+	for (i = 0; i < clk_data->clk_num; i++) {
+		struct clk *clk;
+		const char *clk_name;
+
+		if (of_property_read_string_index(np, "clock-output-names",
+						  i, &clk_name))
+			break;
+
+		/*
+		 * If we read an empty clock name then the output is unused
+		 */
+		if (*clk_name == '\0')
+			continue;
+
+		clk = clk_register_genamux(clk_name, parents, num_parents,
+					   reg, data, i);
+
+		if (IS_ERR(clk))
+			goto err;
+
+		clk_data->clks[i] = clk;
+	}
+
+	kfree(parents);
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+	return;
+err:
+	if (clk_data)
+		kfree(clk_data->clks);
+
+	kfree(clk_data);
+	kfree(parents);
+}
+CLK_OF_DECLARE(clkgenadivmux, "st,clkgena-divmux", st_of_clkgena_divmux_setup);
+
+struct clkgena_prediv_data {
+	u32 offset;
+	u8 shift;
+	struct clk_div_table *table;
+};
+
+static struct clk_div_table prediv_table16[] = {
+	{ .val = 0, .div = 1 },
+	{ .val = 1, .div = 16 },
+	{ .div = 0 },
+};
+
+static struct clkgena_prediv_data prediv_c65_data = {
+	.offset = 0x4c,
+	.shift = 31,
+	.table = prediv_table16,
+};
+
+static struct clkgena_prediv_data prediv_c32_data = {
+	.offset = 0x50,
+	.shift = 1,
+	.table = prediv_table16,
+};
+
+static struct of_device_id clkgena_prediv_of_match[] = {
+	{ .compatible = "st,clkgena-prediv-c65", .data = &prediv_c65_data },
+	{ .compatible = "st,clkgena-prediv-c32", .data = &prediv_c32_data },
+	{}
+};
+
+void __init st_of_clkgena_prediv_setup(struct device_node *np)
+{
+	const struct of_device_id *match;
+	void __iomem *reg;
+	const char *parent_name, *clk_name;
+	struct clk *clk;
+	struct clkgena_prediv_data *data;
+
+	match = of_match_node(clkgena_prediv_of_match, np);
+	if (!match) {
+		pr_err("%s: No matching data\n", __func__);
+		return;
+	}
+
+	data = (struct clkgena_prediv_data *)match->data;
+
+	reg = clkgen_get_register_base(np);
+	if (!reg)
+		return;
+
+	parent_name = of_clk_get_parent_name(np, 0);
+	if (!parent_name)
+		return;
+
+	if (of_property_read_string_index(np, "clock-output-names",
+					  0, &clk_name))
+		return;
+
+	clk = clk_register_divider_table(NULL, clk_name, parent_name, 0,
+					 reg + data->offset, data->shift, 1,
+					 0, data->table, NULL);
+	if (IS_ERR(clk))
+		return;
+
+	of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	pr_debug("%s: parent %s rate %u\n",
+		__clk_get_name(clk),
+		__clk_get_name(clk_get_parent(clk)),
+		(unsigned int)clk_get_rate(clk));
+
+	return;
+}
+CLK_OF_DECLARE(clkgenaprediv, "st,clkgena-prediv", st_of_clkgena_prediv_setup);
-- 
1.9.0


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

* [PATCH v0 01/15] drivers: clk: st: Support for DIVMUX and PreDiv Clocks
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: mturquette, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, rob, linux, devicetree, linux-doc, linux-kernel,
	linux-arm-kernel
  Cc: Pankaj Dev, Lee Jones, Gabriel Fernandez

The patch supports the DIVMUX and PreDiv clocks used by ClockGenA(s)

DIVMUX clock : Divider-Multiplexer-Gate inside ClockGenA(s)
It includes support for each channel : 3-parent Multiplexer,
Divider for each Parent, Gate to switch OFF the output channel. The
clock is implemented using generic clocks implemented in the kernel
clk_divider and clk_mux.

PreDiv clock : Fixed Divider Clock used inside ClockGenA(s) to divide
the oscillator clock by factor-of-16. The clock is implemented using
generic clocks implemented in the kernel clk_divider.

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 drivers/clk/Makefile        |   1 +
 drivers/clk/st/Makefile     |   1 +
 drivers/clk/st/clkgen-mux.c | 529 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 531 insertions(+)
 create mode 100644 drivers/clk/st/Makefile
 create mode 100644 drivers/clk/st/clkgen-mux.c

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index a367a98..7867c511 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_ARCH_SHMOBILE_MULTI)	+= shmobile/
 obj-$(CONFIG_ARCH_SIRF)			+= sirf/
 obj-$(CONFIG_ARCH_SOCFPGA)		+= socfpga/
 obj-$(CONFIG_PLAT_SPEAR)		+= spear/
+obj-$(CONFIG_ARCH_STI)			+= st/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
 obj-$(CONFIG_ARCH_TEGRA)		+= tegra/
 obj-$(CONFIG_ARCH_OMAP2PLUS)		+= ti/
diff --git a/drivers/clk/st/Makefile b/drivers/clk/st/Makefile
new file mode 100644
index 0000000..e42b370
--- /dev/null
+++ b/drivers/clk/st/Makefile
@@ -0,0 +1 @@
+obj-y += clkgen-mux.o
diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c
new file mode 100644
index 0000000..65d702c
--- /dev/null
+++ b/drivers/clk/st/clkgen-mux.c
@@ -0,0 +1,529 @@
+/*
+ * clkgen-mux.c: ST GEN-MUX Clock driver
+ *
+ * Copyright (C) 2014 STMicroelectronics (R&D) Limited
+ *
+ * Authors: Stephen Gallimore <stephen.gallimore@st.com>
+ *	    Pankaj Dev <pankaj.dev@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/of_address.h>
+#include <linux/clk-provider.h>
+
+static DEFINE_SPINLOCK(clkgena_divmux_lock);
+
+static const char ** __init clkgen_mux_get_parents(struct device_node *np,
+						       int *num_parents)
+{
+	const char **parents;
+	int nparents, i;
+
+	nparents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+	if (WARN_ON(nparents <= 0))
+		return ERR_PTR(-EINVAL);
+
+	parents = kzalloc(nparents * sizeof(const char *), GFP_KERNEL);
+	if (!parents)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < nparents; i++)
+		parents[i] = of_clk_get_parent_name(np, i);
+
+	*num_parents = nparents;
+	return parents;
+}
+
+/**
+ * DOC: Clock mux with a programmable divider on each of its three inputs.
+ *      The mux has an input setting which effectively gates its output.
+ *
+ * Traits of this clock:
+ * prepare - clk_(un)prepare only ensures parent is (un)prepared
+ * enable - clk_enable and clk_disable are functional & control gating
+ * rate - set rate is supported
+ * parent - set/get parent
+ */
+
+#define NUM_INPUTS 3
+
+struct clkgena_divmux {
+	struct clk_hw hw;
+	/* Subclassed mux and divider structures */
+	struct clk_mux mux;
+	struct clk_divider div[NUM_INPUTS];
+	/* Enable/running feedback register bits for each input */
+	void __iomem *feedback_reg[NUM_INPUTS];
+	int feedback_bit_idx;
+
+	u8              muxsel;
+};
+
+#define to_clkgena_divmux(_hw) container_of(_hw, struct clkgena_divmux, hw)
+
+struct clkgena_divmux_data {
+	int num_outputs;
+	int mux_offset;
+	int mux_offset2;
+	int mux_start_bit;
+	int div_offsets[NUM_INPUTS];
+	int fb_offsets[NUM_INPUTS];
+	int fb_start_bit_idx;
+};
+
+#define CKGAX_CLKOPSRC_SWITCH_OFF 0x3
+
+static int clkgena_divmux_is_running(struct clkgena_divmux *mux)
+{
+	u32 regval = readl(mux->feedback_reg[mux->muxsel]);
+	u32 running = regval & BIT(mux->feedback_bit_idx);
+	return !!running;
+}
+
+static int clkgena_divmux_enable(struct clk_hw *hw)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+	struct clk_hw *mux_hw = &genamux->mux.hw;
+	unsigned long timeout;
+	int ret = 0;
+
+	mux_hw->clk = hw->clk;
+
+	ret = clk_mux_ops.set_parent(mux_hw, genamux->muxsel);
+	if (ret)
+		return ret;
+
+	timeout = jiffies + msecs_to_jiffies(10);
+
+	while (!clkgena_divmux_is_running(genamux)) {
+		if (time_after(jiffies, timeout))
+			return -ETIMEDOUT;
+		cpu_relax();
+	}
+
+	return 0;
+}
+
+static void clkgena_divmux_disable(struct clk_hw *hw)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+	struct clk_hw *mux_hw = &genamux->mux.hw;
+
+	mux_hw->clk = hw->clk;
+
+	clk_mux_ops.set_parent(mux_hw, CKGAX_CLKOPSRC_SWITCH_OFF);
+}
+
+static int clkgena_divmux_is_enabled(struct clk_hw *hw)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+	struct clk_hw *mux_hw = &genamux->mux.hw;
+
+	mux_hw->clk = hw->clk;
+
+	return (s8)clk_mux_ops.get_parent(mux_hw) > 0;
+}
+
+u8 clkgena_divmux_get_parent(struct clk_hw *hw)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+	struct clk_hw *mux_hw = &genamux->mux.hw;
+
+	mux_hw->clk = hw->clk;
+
+	genamux->muxsel = clk_mux_ops.get_parent(mux_hw);
+	if ((s8)genamux->muxsel < 0) {
+		pr_debug("%s: %s: Invalid parent, setting to default.\n",
+		      __func__, __clk_get_name(hw->clk));
+		genamux->muxsel = 0;
+	}
+
+	return genamux->muxsel;
+}
+
+static int clkgena_divmux_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+
+	if (index >= CKGAX_CLKOPSRC_SWITCH_OFF)
+		return -EINVAL;
+
+	genamux->muxsel = index;
+
+	/*
+	 * If the mux is already enabled, call enable directly to set the
+	 * new mux position and wait for it to start running again. Otherwise
+	 * do nothing.
+	 */
+	if (clkgena_divmux_is_enabled(hw))
+		clkgena_divmux_enable(hw);
+
+	return 0;
+}
+
+unsigned long clkgena_divmux_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+	struct clk_hw *div_hw = &genamux->div[genamux->muxsel].hw;
+
+	div_hw->clk = hw->clk;
+
+	return clk_divider_ops.recalc_rate(div_hw, parent_rate);
+}
+
+static int clkgena_divmux_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+	struct clk_hw *div_hw = &genamux->div[genamux->muxsel].hw;
+
+	div_hw->clk = hw->clk;
+
+	return clk_divider_ops.set_rate(div_hw, rate, parent_rate);
+}
+
+static long clkgena_divmux_round_rate(struct clk_hw *hw, unsigned long rate,
+				   unsigned long *prate)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+	struct clk_hw *div_hw = &genamux->div[genamux->muxsel].hw;
+
+	div_hw->clk = hw->clk;
+
+	return clk_divider_ops.round_rate(div_hw, rate, prate);
+}
+
+static const struct clk_ops clkgena_divmux_ops = {
+	.enable = clkgena_divmux_enable,
+	.disable = clkgena_divmux_disable,
+	.is_enabled = clkgena_divmux_is_enabled,
+	.get_parent = clkgena_divmux_get_parent,
+	.set_parent = clkgena_divmux_set_parent,
+	.round_rate = clkgena_divmux_round_rate,
+	.recalc_rate = clkgena_divmux_recalc_rate,
+	.set_rate = clkgena_divmux_set_rate,
+};
+
+/**
+ * clk_register_genamux - register a genamux clock with the clock framework
+ */
+struct clk *clk_register_genamux(const char *name,
+				const char **parent_names, u8 num_parents,
+				void __iomem *reg,
+				const struct clkgena_divmux_data *muxdata,
+				u32 idx)
+{
+	/*
+	 * Fixed constants across all ClockgenA variants
+	 */
+	const int mux_width = 2;
+	const int divider_width = 5;
+	struct clkgena_divmux *genamux;
+	struct clk *clk;
+	struct clk_init_data init;
+	int i;
+
+	genamux = kzalloc(sizeof(*genamux), GFP_KERNEL);
+	if (!genamux)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &clkgena_divmux_ops;
+	init.flags = CLK_IS_BASIC;
+	init.parent_names = parent_names;
+	init.num_parents = num_parents;
+
+	genamux->mux.lock  = &clkgena_divmux_lock;
+	genamux->mux.mask = BIT(mux_width) - 1;
+	genamux->mux.shift = muxdata->mux_start_bit + (idx * mux_width);
+	if (genamux->mux.shift > 31) {
+		/*
+		 * We have spilled into the second mux register so
+		 * adjust the register address and the bit shift accordingly
+		 */
+		genamux->mux.reg = reg + muxdata->mux_offset2;
+		genamux->mux.shift -= 32;
+	} else {
+		genamux->mux.reg   = reg + muxdata->mux_offset;
+	}
+
+	for (i = 0; i < NUM_INPUTS; i++) {
+		/*
+		 * Divider config for each input
+		 */
+		void __iomem *divbase = reg + muxdata->div_offsets[i];
+		genamux->div[i].width = divider_width;
+		genamux->div[i].reg = divbase + (idx * sizeof(u32));
+
+		/*
+		 * Mux enabled/running feedback register for each input.
+		 */
+		genamux->feedback_reg[i] = reg + muxdata->fb_offsets[i];
+	}
+
+	genamux->feedback_bit_idx = muxdata->fb_start_bit_idx + idx;
+	genamux->hw.init = &init;
+
+	clk = clk_register(NULL, &genamux->hw);
+	if (IS_ERR(clk)) {
+		kfree(genamux);
+		goto err;
+	}
+
+	pr_debug("%s: parent %s rate %lu\n",
+			__clk_get_name(clk),
+			__clk_get_name(clk_get_parent(clk)),
+			clk_get_rate(clk));
+err:
+	return clk;
+}
+
+static struct clkgena_divmux_data st_divmux_c65hs = {
+	.num_outputs = 4,
+	.mux_offset = 0x14,
+	.mux_start_bit = 0,
+	.div_offsets = { 0x800, 0x900, 0xb00 },
+	.fb_offsets = { 0x18, 0x1c, 0x20 },
+	.fb_start_bit_idx = 0,
+};
+
+static struct clkgena_divmux_data st_divmux_c65ls = {
+	.num_outputs = 14,
+	.mux_offset = 0x14,
+	.mux_offset2 = 0x24,
+	.mux_start_bit = 8,
+	.div_offsets = { 0x810, 0xa10, 0xb10 },
+	.fb_offsets = { 0x18, 0x1c, 0x20 },
+	.fb_start_bit_idx = 4,
+};
+
+static struct clkgena_divmux_data st_divmux_c32odf0 = {
+	.num_outputs = 8,
+	.mux_offset = 0x1c,
+	.mux_start_bit = 0,
+	.div_offsets = { 0x800, 0x900, 0xa60 },
+	.fb_offsets = { 0x2c, 0x24, 0x28 },
+	.fb_start_bit_idx = 0,
+};
+
+static struct clkgena_divmux_data st_divmux_c32odf1 = {
+	.num_outputs = 8,
+	.mux_offset = 0x1c,
+	.mux_start_bit = 16,
+	.div_offsets = { 0x820, 0x980, 0xa80 },
+	.fb_offsets = { 0x2c, 0x24, 0x28 },
+	.fb_start_bit_idx = 8,
+};
+
+static struct clkgena_divmux_data st_divmux_c32odf2 = {
+	.num_outputs = 8,
+	.mux_offset = 0x20,
+	.mux_start_bit = 0,
+	.div_offsets = { 0x840, 0xa20, 0xb10 },
+	.fb_offsets = { 0x2c, 0x24, 0x28 },
+	.fb_start_bit_idx = 16,
+};
+
+static struct clkgena_divmux_data st_divmux_c32odf3 = {
+	.num_outputs = 8,
+	.mux_offset = 0x20,
+	.mux_start_bit = 16,
+	.div_offsets = { 0x860, 0xa40, 0xb30 },
+	.fb_offsets = { 0x2c, 0x24, 0x28 },
+	.fb_start_bit_idx = 24,
+};
+
+static struct of_device_id clkgena_divmux_of_match[] = {
+	{
+		.compatible = "st,clkgena-divmux-c65-hs",
+		.data = &st_divmux_c65hs,
+	},
+	{
+		.compatible = "st,clkgena-divmux-c65-ls",
+		.data = &st_divmux_c65ls,
+	},
+	{
+		.compatible = "st,clkgena-divmux-c32-odf0",
+		.data = &st_divmux_c32odf0,
+	},
+	{
+		.compatible = "st,clkgena-divmux-c32-odf1",
+		.data = &st_divmux_c32odf1,
+	},
+	{
+		.compatible = "st,clkgena-divmux-c32-odf2",
+		.data = &st_divmux_c32odf2,
+	},
+	{
+		.compatible = "st,clkgena-divmux-c32-odf3",
+		.data = &st_divmux_c32odf3,
+	},
+	{}
+};
+
+static void __iomem * __init clkgen_get_register_base(
+				struct device_node *np)
+{
+	struct device_node *pnode;
+	void __iomem *reg = NULL;
+
+	pnode = of_get_parent(np);
+	if (!pnode)
+		return NULL;
+
+	reg = of_iomap(pnode, 0);
+
+	of_node_put(pnode);
+	return reg;
+}
+
+void __init st_of_clkgena_divmux_setup(struct device_node *np)
+{
+	const struct of_device_id *match;
+	const struct clkgena_divmux_data *data;
+	struct clk_onecell_data *clk_data;
+	void __iomem *reg;
+	const char **parents;
+	int num_parents = 0, i;
+
+	match = of_match_node(clkgena_divmux_of_match, np);
+	if (WARN_ON(!match))
+		return;
+
+	data = (struct clkgena_divmux_data *)match->data;
+
+	reg = clkgen_get_register_base(np);
+	if (!reg)
+		return;
+
+	parents = clkgen_mux_get_parents(np, &num_parents);
+	if (IS_ERR(parents))
+		return;
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		goto err;
+
+	clk_data->clk_num = data->num_outputs;
+	clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *),
+				 GFP_KERNEL);
+
+	if (!clk_data->clks)
+		goto err;
+
+	for (i = 0; i < clk_data->clk_num; i++) {
+		struct clk *clk;
+		const char *clk_name;
+
+		if (of_property_read_string_index(np, "clock-output-names",
+						  i, &clk_name))
+			break;
+
+		/*
+		 * If we read an empty clock name then the output is unused
+		 */
+		if (*clk_name == '\0')
+			continue;
+
+		clk = clk_register_genamux(clk_name, parents, num_parents,
+					   reg, data, i);
+
+		if (IS_ERR(clk))
+			goto err;
+
+		clk_data->clks[i] = clk;
+	}
+
+	kfree(parents);
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+	return;
+err:
+	if (clk_data)
+		kfree(clk_data->clks);
+
+	kfree(clk_data);
+	kfree(parents);
+}
+CLK_OF_DECLARE(clkgenadivmux, "st,clkgena-divmux", st_of_clkgena_divmux_setup);
+
+struct clkgena_prediv_data {
+	u32 offset;
+	u8 shift;
+	struct clk_div_table *table;
+};
+
+static struct clk_div_table prediv_table16[] = {
+	{ .val = 0, .div = 1 },
+	{ .val = 1, .div = 16 },
+	{ .div = 0 },
+};
+
+static struct clkgena_prediv_data prediv_c65_data = {
+	.offset = 0x4c,
+	.shift = 31,
+	.table = prediv_table16,
+};
+
+static struct clkgena_prediv_data prediv_c32_data = {
+	.offset = 0x50,
+	.shift = 1,
+	.table = prediv_table16,
+};
+
+static struct of_device_id clkgena_prediv_of_match[] = {
+	{ .compatible = "st,clkgena-prediv-c65", .data = &prediv_c65_data },
+	{ .compatible = "st,clkgena-prediv-c32", .data = &prediv_c32_data },
+	{}
+};
+
+void __init st_of_clkgena_prediv_setup(struct device_node *np)
+{
+	const struct of_device_id *match;
+	void __iomem *reg;
+	const char *parent_name, *clk_name;
+	struct clk *clk;
+	struct clkgena_prediv_data *data;
+
+	match = of_match_node(clkgena_prediv_of_match, np);
+	if (!match) {
+		pr_err("%s: No matching data\n", __func__);
+		return;
+	}
+
+	data = (struct clkgena_prediv_data *)match->data;
+
+	reg = clkgen_get_register_base(np);
+	if (!reg)
+		return;
+
+	parent_name = of_clk_get_parent_name(np, 0);
+	if (!parent_name)
+		return;
+
+	if (of_property_read_string_index(np, "clock-output-names",
+					  0, &clk_name))
+		return;
+
+	clk = clk_register_divider_table(NULL, clk_name, parent_name, 0,
+					 reg + data->offset, data->shift, 1,
+					 0, data->table, NULL);
+	if (IS_ERR(clk))
+		return;
+
+	of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	pr_debug("%s: parent %s rate %u\n",
+		__clk_get_name(clk),
+		__clk_get_name(clk_get_parent(clk)),
+		(unsigned int)clk_get_rate(clk));
+
+	return;
+}
+CLK_OF_DECLARE(clkgenaprediv, "st,clkgena-prediv", st_of_clkgena_prediv_setup);
-- 
1.9.0

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

* [PATCH v0 01/15] drivers: clk: st: Support for DIVMUX and PreDiv Clocks
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

The patch supports the DIVMUX and PreDiv clocks used by ClockGenA(s)

DIVMUX clock : Divider-Multiplexer-Gate inside ClockGenA(s)
It includes support for each channel : 3-parent Multiplexer,
Divider for each Parent, Gate to switch OFF the output channel. The
clock is implemented using generic clocks implemented in the kernel
clk_divider and clk_mux.

PreDiv clock : Fixed Divider Clock used inside ClockGenA(s) to divide
the oscillator clock by factor-of-16. The clock is implemented using
generic clocks implemented in the kernel clk_divider.

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 drivers/clk/Makefile        |   1 +
 drivers/clk/st/Makefile     |   1 +
 drivers/clk/st/clkgen-mux.c | 529 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 531 insertions(+)
 create mode 100644 drivers/clk/st/Makefile
 create mode 100644 drivers/clk/st/clkgen-mux.c

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index a367a98..7867c511 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_ARCH_SHMOBILE_MULTI)	+= shmobile/
 obj-$(CONFIG_ARCH_SIRF)			+= sirf/
 obj-$(CONFIG_ARCH_SOCFPGA)		+= socfpga/
 obj-$(CONFIG_PLAT_SPEAR)		+= spear/
+obj-$(CONFIG_ARCH_STI)			+= st/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
 obj-$(CONFIG_ARCH_TEGRA)		+= tegra/
 obj-$(CONFIG_ARCH_OMAP2PLUS)		+= ti/
diff --git a/drivers/clk/st/Makefile b/drivers/clk/st/Makefile
new file mode 100644
index 0000000..e42b370
--- /dev/null
+++ b/drivers/clk/st/Makefile
@@ -0,0 +1 @@
+obj-y += clkgen-mux.o
diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c
new file mode 100644
index 0000000..65d702c
--- /dev/null
+++ b/drivers/clk/st/clkgen-mux.c
@@ -0,0 +1,529 @@
+/*
+ * clkgen-mux.c: ST GEN-MUX Clock driver
+ *
+ * Copyright (C) 2014 STMicroelectronics (R&D) Limited
+ *
+ * Authors: Stephen Gallimore <stephen.gallimore@st.com>
+ *	    Pankaj Dev <pankaj.dev@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/of_address.h>
+#include <linux/clk-provider.h>
+
+static DEFINE_SPINLOCK(clkgena_divmux_lock);
+
+static const char ** __init clkgen_mux_get_parents(struct device_node *np,
+						       int *num_parents)
+{
+	const char **parents;
+	int nparents, i;
+
+	nparents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+	if (WARN_ON(nparents <= 0))
+		return ERR_PTR(-EINVAL);
+
+	parents = kzalloc(nparents * sizeof(const char *), GFP_KERNEL);
+	if (!parents)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < nparents; i++)
+		parents[i] = of_clk_get_parent_name(np, i);
+
+	*num_parents = nparents;
+	return parents;
+}
+
+/**
+ * DOC: Clock mux with a programmable divider on each of its three inputs.
+ *      The mux has an input setting which effectively gates its output.
+ *
+ * Traits of this clock:
+ * prepare - clk_(un)prepare only ensures parent is (un)prepared
+ * enable - clk_enable and clk_disable are functional & control gating
+ * rate - set rate is supported
+ * parent - set/get parent
+ */
+
+#define NUM_INPUTS 3
+
+struct clkgena_divmux {
+	struct clk_hw hw;
+	/* Subclassed mux and divider structures */
+	struct clk_mux mux;
+	struct clk_divider div[NUM_INPUTS];
+	/* Enable/running feedback register bits for each input */
+	void __iomem *feedback_reg[NUM_INPUTS];
+	int feedback_bit_idx;
+
+	u8              muxsel;
+};
+
+#define to_clkgena_divmux(_hw) container_of(_hw, struct clkgena_divmux, hw)
+
+struct clkgena_divmux_data {
+	int num_outputs;
+	int mux_offset;
+	int mux_offset2;
+	int mux_start_bit;
+	int div_offsets[NUM_INPUTS];
+	int fb_offsets[NUM_INPUTS];
+	int fb_start_bit_idx;
+};
+
+#define CKGAX_CLKOPSRC_SWITCH_OFF 0x3
+
+static int clkgena_divmux_is_running(struct clkgena_divmux *mux)
+{
+	u32 regval = readl(mux->feedback_reg[mux->muxsel]);
+	u32 running = regval & BIT(mux->feedback_bit_idx);
+	return !!running;
+}
+
+static int clkgena_divmux_enable(struct clk_hw *hw)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+	struct clk_hw *mux_hw = &genamux->mux.hw;
+	unsigned long timeout;
+	int ret = 0;
+
+	mux_hw->clk = hw->clk;
+
+	ret = clk_mux_ops.set_parent(mux_hw, genamux->muxsel);
+	if (ret)
+		return ret;
+
+	timeout = jiffies + msecs_to_jiffies(10);
+
+	while (!clkgena_divmux_is_running(genamux)) {
+		if (time_after(jiffies, timeout))
+			return -ETIMEDOUT;
+		cpu_relax();
+	}
+
+	return 0;
+}
+
+static void clkgena_divmux_disable(struct clk_hw *hw)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+	struct clk_hw *mux_hw = &genamux->mux.hw;
+
+	mux_hw->clk = hw->clk;
+
+	clk_mux_ops.set_parent(mux_hw, CKGAX_CLKOPSRC_SWITCH_OFF);
+}
+
+static int clkgena_divmux_is_enabled(struct clk_hw *hw)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+	struct clk_hw *mux_hw = &genamux->mux.hw;
+
+	mux_hw->clk = hw->clk;
+
+	return (s8)clk_mux_ops.get_parent(mux_hw) > 0;
+}
+
+u8 clkgena_divmux_get_parent(struct clk_hw *hw)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+	struct clk_hw *mux_hw = &genamux->mux.hw;
+
+	mux_hw->clk = hw->clk;
+
+	genamux->muxsel = clk_mux_ops.get_parent(mux_hw);
+	if ((s8)genamux->muxsel < 0) {
+		pr_debug("%s: %s: Invalid parent, setting to default.\n",
+		      __func__, __clk_get_name(hw->clk));
+		genamux->muxsel = 0;
+	}
+
+	return genamux->muxsel;
+}
+
+static int clkgena_divmux_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+
+	if (index >= CKGAX_CLKOPSRC_SWITCH_OFF)
+		return -EINVAL;
+
+	genamux->muxsel = index;
+
+	/*
+	 * If the mux is already enabled, call enable directly to set the
+	 * new mux position and wait for it to start running again. Otherwise
+	 * do nothing.
+	 */
+	if (clkgena_divmux_is_enabled(hw))
+		clkgena_divmux_enable(hw);
+
+	return 0;
+}
+
+unsigned long clkgena_divmux_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+	struct clk_hw *div_hw = &genamux->div[genamux->muxsel].hw;
+
+	div_hw->clk = hw->clk;
+
+	return clk_divider_ops.recalc_rate(div_hw, parent_rate);
+}
+
+static int clkgena_divmux_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+	struct clk_hw *div_hw = &genamux->div[genamux->muxsel].hw;
+
+	div_hw->clk = hw->clk;
+
+	return clk_divider_ops.set_rate(div_hw, rate, parent_rate);
+}
+
+static long clkgena_divmux_round_rate(struct clk_hw *hw, unsigned long rate,
+				   unsigned long *prate)
+{
+	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
+	struct clk_hw *div_hw = &genamux->div[genamux->muxsel].hw;
+
+	div_hw->clk = hw->clk;
+
+	return clk_divider_ops.round_rate(div_hw, rate, prate);
+}
+
+static const struct clk_ops clkgena_divmux_ops = {
+	.enable = clkgena_divmux_enable,
+	.disable = clkgena_divmux_disable,
+	.is_enabled = clkgena_divmux_is_enabled,
+	.get_parent = clkgena_divmux_get_parent,
+	.set_parent = clkgena_divmux_set_parent,
+	.round_rate = clkgena_divmux_round_rate,
+	.recalc_rate = clkgena_divmux_recalc_rate,
+	.set_rate = clkgena_divmux_set_rate,
+};
+
+/**
+ * clk_register_genamux - register a genamux clock with the clock framework
+ */
+struct clk *clk_register_genamux(const char *name,
+				const char **parent_names, u8 num_parents,
+				void __iomem *reg,
+				const struct clkgena_divmux_data *muxdata,
+				u32 idx)
+{
+	/*
+	 * Fixed constants across all ClockgenA variants
+	 */
+	const int mux_width = 2;
+	const int divider_width = 5;
+	struct clkgena_divmux *genamux;
+	struct clk *clk;
+	struct clk_init_data init;
+	int i;
+
+	genamux = kzalloc(sizeof(*genamux), GFP_KERNEL);
+	if (!genamux)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &clkgena_divmux_ops;
+	init.flags = CLK_IS_BASIC;
+	init.parent_names = parent_names;
+	init.num_parents = num_parents;
+
+	genamux->mux.lock  = &clkgena_divmux_lock;
+	genamux->mux.mask = BIT(mux_width) - 1;
+	genamux->mux.shift = muxdata->mux_start_bit + (idx * mux_width);
+	if (genamux->mux.shift > 31) {
+		/*
+		 * We have spilled into the second mux register so
+		 * adjust the register address and the bit shift accordingly
+		 */
+		genamux->mux.reg = reg + muxdata->mux_offset2;
+		genamux->mux.shift -= 32;
+	} else {
+		genamux->mux.reg   = reg + muxdata->mux_offset;
+	}
+
+	for (i = 0; i < NUM_INPUTS; i++) {
+		/*
+		 * Divider config for each input
+		 */
+		void __iomem *divbase = reg + muxdata->div_offsets[i];
+		genamux->div[i].width = divider_width;
+		genamux->div[i].reg = divbase + (idx * sizeof(u32));
+
+		/*
+		 * Mux enabled/running feedback register for each input.
+		 */
+		genamux->feedback_reg[i] = reg + muxdata->fb_offsets[i];
+	}
+
+	genamux->feedback_bit_idx = muxdata->fb_start_bit_idx + idx;
+	genamux->hw.init = &init;
+
+	clk = clk_register(NULL, &genamux->hw);
+	if (IS_ERR(clk)) {
+		kfree(genamux);
+		goto err;
+	}
+
+	pr_debug("%s: parent %s rate %lu\n",
+			__clk_get_name(clk),
+			__clk_get_name(clk_get_parent(clk)),
+			clk_get_rate(clk));
+err:
+	return clk;
+}
+
+static struct clkgena_divmux_data st_divmux_c65hs = {
+	.num_outputs = 4,
+	.mux_offset = 0x14,
+	.mux_start_bit = 0,
+	.div_offsets = { 0x800, 0x900, 0xb00 },
+	.fb_offsets = { 0x18, 0x1c, 0x20 },
+	.fb_start_bit_idx = 0,
+};
+
+static struct clkgena_divmux_data st_divmux_c65ls = {
+	.num_outputs = 14,
+	.mux_offset = 0x14,
+	.mux_offset2 = 0x24,
+	.mux_start_bit = 8,
+	.div_offsets = { 0x810, 0xa10, 0xb10 },
+	.fb_offsets = { 0x18, 0x1c, 0x20 },
+	.fb_start_bit_idx = 4,
+};
+
+static struct clkgena_divmux_data st_divmux_c32odf0 = {
+	.num_outputs = 8,
+	.mux_offset = 0x1c,
+	.mux_start_bit = 0,
+	.div_offsets = { 0x800, 0x900, 0xa60 },
+	.fb_offsets = { 0x2c, 0x24, 0x28 },
+	.fb_start_bit_idx = 0,
+};
+
+static struct clkgena_divmux_data st_divmux_c32odf1 = {
+	.num_outputs = 8,
+	.mux_offset = 0x1c,
+	.mux_start_bit = 16,
+	.div_offsets = { 0x820, 0x980, 0xa80 },
+	.fb_offsets = { 0x2c, 0x24, 0x28 },
+	.fb_start_bit_idx = 8,
+};
+
+static struct clkgena_divmux_data st_divmux_c32odf2 = {
+	.num_outputs = 8,
+	.mux_offset = 0x20,
+	.mux_start_bit = 0,
+	.div_offsets = { 0x840, 0xa20, 0xb10 },
+	.fb_offsets = { 0x2c, 0x24, 0x28 },
+	.fb_start_bit_idx = 16,
+};
+
+static struct clkgena_divmux_data st_divmux_c32odf3 = {
+	.num_outputs = 8,
+	.mux_offset = 0x20,
+	.mux_start_bit = 16,
+	.div_offsets = { 0x860, 0xa40, 0xb30 },
+	.fb_offsets = { 0x2c, 0x24, 0x28 },
+	.fb_start_bit_idx = 24,
+};
+
+static struct of_device_id clkgena_divmux_of_match[] = {
+	{
+		.compatible = "st,clkgena-divmux-c65-hs",
+		.data = &st_divmux_c65hs,
+	},
+	{
+		.compatible = "st,clkgena-divmux-c65-ls",
+		.data = &st_divmux_c65ls,
+	},
+	{
+		.compatible = "st,clkgena-divmux-c32-odf0",
+		.data = &st_divmux_c32odf0,
+	},
+	{
+		.compatible = "st,clkgena-divmux-c32-odf1",
+		.data = &st_divmux_c32odf1,
+	},
+	{
+		.compatible = "st,clkgena-divmux-c32-odf2",
+		.data = &st_divmux_c32odf2,
+	},
+	{
+		.compatible = "st,clkgena-divmux-c32-odf3",
+		.data = &st_divmux_c32odf3,
+	},
+	{}
+};
+
+static void __iomem * __init clkgen_get_register_base(
+				struct device_node *np)
+{
+	struct device_node *pnode;
+	void __iomem *reg = NULL;
+
+	pnode = of_get_parent(np);
+	if (!pnode)
+		return NULL;
+
+	reg = of_iomap(pnode, 0);
+
+	of_node_put(pnode);
+	return reg;
+}
+
+void __init st_of_clkgena_divmux_setup(struct device_node *np)
+{
+	const struct of_device_id *match;
+	const struct clkgena_divmux_data *data;
+	struct clk_onecell_data *clk_data;
+	void __iomem *reg;
+	const char **parents;
+	int num_parents = 0, i;
+
+	match = of_match_node(clkgena_divmux_of_match, np);
+	if (WARN_ON(!match))
+		return;
+
+	data = (struct clkgena_divmux_data *)match->data;
+
+	reg = clkgen_get_register_base(np);
+	if (!reg)
+		return;
+
+	parents = clkgen_mux_get_parents(np, &num_parents);
+	if (IS_ERR(parents))
+		return;
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		goto err;
+
+	clk_data->clk_num = data->num_outputs;
+	clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *),
+				 GFP_KERNEL);
+
+	if (!clk_data->clks)
+		goto err;
+
+	for (i = 0; i < clk_data->clk_num; i++) {
+		struct clk *clk;
+		const char *clk_name;
+
+		if (of_property_read_string_index(np, "clock-output-names",
+						  i, &clk_name))
+			break;
+
+		/*
+		 * If we read an empty clock name then the output is unused
+		 */
+		if (*clk_name == '\0')
+			continue;
+
+		clk = clk_register_genamux(clk_name, parents, num_parents,
+					   reg, data, i);
+
+		if (IS_ERR(clk))
+			goto err;
+
+		clk_data->clks[i] = clk;
+	}
+
+	kfree(parents);
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+	return;
+err:
+	if (clk_data)
+		kfree(clk_data->clks);
+
+	kfree(clk_data);
+	kfree(parents);
+}
+CLK_OF_DECLARE(clkgenadivmux, "st,clkgena-divmux", st_of_clkgena_divmux_setup);
+
+struct clkgena_prediv_data {
+	u32 offset;
+	u8 shift;
+	struct clk_div_table *table;
+};
+
+static struct clk_div_table prediv_table16[] = {
+	{ .val = 0, .div = 1 },
+	{ .val = 1, .div = 16 },
+	{ .div = 0 },
+};
+
+static struct clkgena_prediv_data prediv_c65_data = {
+	.offset = 0x4c,
+	.shift = 31,
+	.table = prediv_table16,
+};
+
+static struct clkgena_prediv_data prediv_c32_data = {
+	.offset = 0x50,
+	.shift = 1,
+	.table = prediv_table16,
+};
+
+static struct of_device_id clkgena_prediv_of_match[] = {
+	{ .compatible = "st,clkgena-prediv-c65", .data = &prediv_c65_data },
+	{ .compatible = "st,clkgena-prediv-c32", .data = &prediv_c32_data },
+	{}
+};
+
+void __init st_of_clkgena_prediv_setup(struct device_node *np)
+{
+	const struct of_device_id *match;
+	void __iomem *reg;
+	const char *parent_name, *clk_name;
+	struct clk *clk;
+	struct clkgena_prediv_data *data;
+
+	match = of_match_node(clkgena_prediv_of_match, np);
+	if (!match) {
+		pr_err("%s: No matching data\n", __func__);
+		return;
+	}
+
+	data = (struct clkgena_prediv_data *)match->data;
+
+	reg = clkgen_get_register_base(np);
+	if (!reg)
+		return;
+
+	parent_name = of_clk_get_parent_name(np, 0);
+	if (!parent_name)
+		return;
+
+	if (of_property_read_string_index(np, "clock-output-names",
+					  0, &clk_name))
+		return;
+
+	clk = clk_register_divider_table(NULL, clk_name, parent_name, 0,
+					 reg + data->offset, data->shift, 1,
+					 0, data->table, NULL);
+	if (IS_ERR(clk))
+		return;
+
+	of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	pr_debug("%s: parent %s rate %u\n",
+		__clk_get_name(clk),
+		__clk_get_name(clk_get_parent(clk)),
+		(unsigned int)clk_get_rate(clk));
+
+	return;
+}
+CLK_OF_DECLARE(clkgenaprediv, "st,clkgena-prediv", st_of_clkgena_prediv_setup);
-- 
1.9.0

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

* [PATCH v0 02/15] drivers: clk: st: Support for PLLs inside ClockGenA(s)
  2014-02-27 15:24 ` Gabriel FERNANDEZ
  (?)
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  -1 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: mturquette, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, rob, linux, devicetree, linux-doc, linux-kernel,
	linux-arm-kernel
  Cc: Lee Jones, Gabriel Fernandez, Pankaj Dev

The patch supports the c65/c32 type PLLs used by ClockGenA(s)

PLL clock : It includes support for all c65/c32 type PLLs
inside ClockGenA(s) : implemented as Fixed Parent / Fixed Rate clock,
with clock rate calculated reading H/w settings done at BOOT.

c65 PLLs have 2 outputs : HS and LS
c32 PLLs have 1-4 outputs : ODFx

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 drivers/clk/st/Makefile     |   2 +-
 drivers/clk/st/clkgen-pll.c | 559 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/st/clkgen.h     |  48 ++++
 3 files changed, 608 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/st/clkgen-pll.c
 create mode 100644 drivers/clk/st/clkgen.h

diff --git a/drivers/clk/st/Makefile b/drivers/clk/st/Makefile
index e42b370..b7b10f9 100644
--- a/drivers/clk/st/Makefile
+++ b/drivers/clk/st/Makefile
@@ -1 +1 @@
-obj-y += clkgen-mux.o
+obj-y += clkgen-mux.o clkgen-pll.o
diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c
new file mode 100644
index 0000000..c6b38b0
--- /dev/null
+++ b/drivers/clk/st/clkgen-pll.c
@@ -0,0 +1,559 @@
+/*
+ * Copyright (C) 2014 STMicroelectronics (R&D) Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+/*
+ * Authors:
+ * Stephen Gallimore <stephen.gallimore@st.com>,
+ * Pankaj Dev <pankaj.dev@st.com>.
+ */
+
+#include <linux/slab.h>
+#include <linux/of_address.h>
+#include <linux/clk-provider.h>
+
+#include "clkgen.h"
+
+static DEFINE_SPINLOCK(clkgena_c32_odf_lock);
+
+/*
+ * Common PLL configuration register bits for PLL800 and PLL1600 C65
+ */
+#define C65_MDIV_PLL800_MASK	(0xff)
+#define C65_MDIV_PLL1600_MASK	(0x7)
+#define C65_NDIV_MASK		(0xff)
+#define C65_PDIV_MASK		(0x7)
+
+/*
+ * PLL configuration register bits for PLL3200 C32
+ */
+#define C32_NDIV_MASK (0xff)
+#define C32_IDF_MASK (0x7)
+#define C32_ODF_MASK (0x3f)
+#define C32_LDF_MASK (0x7f)
+
+#define C32_MAX_ODFS (4)
+
+struct clkgen_pll_data {
+	struct clkgen_field pdn_status;
+	struct clkgen_field locked_status;
+	struct clkgen_field mdiv;
+	struct clkgen_field ndiv;
+	struct clkgen_field pdiv;
+	struct clkgen_field idf;
+	struct clkgen_field ldf;
+	unsigned int num_odfs;
+	struct clkgen_field odf[C32_MAX_ODFS];
+	struct clkgen_field odf_gate[C32_MAX_ODFS];
+	const struct clk_ops *ops;
+};
+
+static const struct clk_ops st_pll1600c65_ops;
+static const struct clk_ops st_pll800c65_ops;
+static const struct clk_ops stm_pll3200c32_ops;
+static const struct clk_ops st_pll1200c32_ops;
+
+static struct clkgen_pll_data st_pll1600c65_ax = {
+	.pdn_status	= CLKGEN_FIELD(0x0, 0x1,			19),
+	.locked_status	= CLKGEN_FIELD(0x0, 0x1,			31),
+	.mdiv		= CLKGEN_FIELD(0x0, C65_MDIV_PLL1600_MASK,	0),
+	.ndiv		= CLKGEN_FIELD(0x0, C65_NDIV_MASK,		8),
+	.ops		= &st_pll1600c65_ops
+};
+
+static struct clkgen_pll_data st_pll800c65_ax = {
+	.pdn_status	= CLKGEN_FIELD(0x0,	0x1,			19),
+	.locked_status	= CLKGEN_FIELD(0x0,	0x1,			31),
+	.mdiv		= CLKGEN_FIELD(0x0,	C65_MDIV_PLL800_MASK,	0),
+	.ndiv		= CLKGEN_FIELD(0x0,	C65_NDIV_MASK,		8),
+	.pdiv		= CLKGEN_FIELD(0x0,	C65_PDIV_MASK,		16),
+	.ops		= &st_pll800c65_ops
+};
+
+static struct clkgen_pll_data st_pll3200c32_a1x_0 = {
+	.pdn_status	= CLKGEN_FIELD(0x0,	0x1,			31),
+	.locked_status	= CLKGEN_FIELD(0x4,	0x1,			31),
+	.ndiv		= CLKGEN_FIELD(0x0,	C32_NDIV_MASK,		0x0),
+	.idf		= CLKGEN_FIELD(0x4,	C32_IDF_MASK,		0x0),
+	.num_odfs = 4,
+	.odf =	{	CLKGEN_FIELD(0x54,	C32_ODF_MASK,		4),
+			CLKGEN_FIELD(0x54,	C32_ODF_MASK,		10),
+			CLKGEN_FIELD(0x54,	C32_ODF_MASK,		16),
+			CLKGEN_FIELD(0x54,	C32_ODF_MASK,		22) },
+	.odf_gate = {	CLKGEN_FIELD(0x54,	0x1,			0),
+			CLKGEN_FIELD(0x54,	0x1,			1),
+			CLKGEN_FIELD(0x54,	0x1,			2),
+			CLKGEN_FIELD(0x54,	0x1,			3) },
+	.ops		= &stm_pll3200c32_ops,
+};
+
+static struct clkgen_pll_data st_pll3200c32_a1x_1 = {
+	.pdn_status	= CLKGEN_FIELD(0xC,	0x1,			31),
+	.locked_status	= CLKGEN_FIELD(0x10,	0x1,			31),
+	.ndiv		= CLKGEN_FIELD(0xC,	C32_NDIV_MASK,		0x0),
+	.idf		= CLKGEN_FIELD(0x10,	C32_IDF_MASK,		0x0),
+	.num_odfs = 4,
+	.odf = {	CLKGEN_FIELD(0x58,	C32_ODF_MASK,		4),
+			CLKGEN_FIELD(0x58,	C32_ODF_MASK,		10),
+			CLKGEN_FIELD(0x58,	C32_ODF_MASK,		16),
+			CLKGEN_FIELD(0x58,	C32_ODF_MASK,		22) },
+	.odf_gate = {	CLKGEN_FIELD(0x58,	0x1,			0),
+			CLKGEN_FIELD(0x58,	0x1,			1),
+			CLKGEN_FIELD(0x58,	0x1,			2),
+			CLKGEN_FIELD(0x58,	0x1,			3) },
+	.ops		= &stm_pll3200c32_ops,
+};
+
+/**
+ * DOC: Clock Generated by PLL, rate set and enabled by bootloader
+ *
+ * Traits of this clock:
+ * prepare - clk_(un)prepare only ensures parent is (un)prepared
+ * enable - clk_enable/disable only ensures parent is enabled
+ * rate - rate is fixed. No clk_set_rate support
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+/**
+ * PLL clock that is integrated in the ClockGenA instances on the STiH415
+ * and STiH416.
+ *
+ * @hw: handle between common and hardware-specific interfaces.
+ * @type: PLL instance type.
+ * @regs_base: base of the PLL configuration register(s).
+ *
+ */
+struct clkgen_pll {
+	struct clk_hw		hw;
+	struct clkgen_pll_data	*data;
+	void __iomem		*regs_base;
+};
+
+#define to_clkgen_pll(_hw) container_of(_hw, struct clkgen_pll, hw)
+
+static int clkgen_pll_is_locked(struct clk_hw *hw)
+{
+	struct clkgen_pll *pll = to_clkgen_pll(hw);
+	u32 locked = CLKGEN_READ(pll, locked_status);
+
+	return !!locked;
+}
+
+static int clkgen_pll_is_enabled(struct clk_hw *hw)
+{
+	struct clkgen_pll *pll = to_clkgen_pll(hw);
+	u32 poweroff = CLKGEN_READ(pll, pdn_status);
+	return !poweroff;
+}
+
+unsigned long recalc_stm_pll800c65(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clkgen_pll *pll = to_clkgen_pll(hw);
+	unsigned long mdiv, ndiv, pdiv;
+	unsigned long rate;
+	uint64_t res;
+
+	if (!clkgen_pll_is_enabled(hw) || !clkgen_pll_is_locked(hw))
+		return 0;
+
+	pdiv = CLKGEN_READ(pll, pdiv);
+	mdiv = CLKGEN_READ(pll, mdiv);
+	ndiv = CLKGEN_READ(pll, ndiv);
+
+	if (!mdiv)
+		mdiv++; /* mdiv=0 or 1 => MDIV=1 */
+
+	res = (uint64_t)2 * (uint64_t)parent_rate * (uint64_t)ndiv;
+	rate = (unsigned long)div64_u64(res, mdiv * (1 << pdiv));
+
+	pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+
+	return rate;
+
+}
+
+unsigned long recalc_stm_pll1600c65(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clkgen_pll *pll = to_clkgen_pll(hw);
+	unsigned long mdiv, ndiv;
+	unsigned long rate;
+
+	if (!clkgen_pll_is_enabled(hw) || !clkgen_pll_is_locked(hw))
+		return 0;
+
+	mdiv = CLKGEN_READ(pll, mdiv);
+	ndiv = CLKGEN_READ(pll, ndiv);
+
+	if (!mdiv)
+		mdiv = 1;
+
+	/* Note: input is divided by 1000 to avoid overflow */
+	rate = ((2 * (parent_rate / 1000) * ndiv) / mdiv) * 1000;
+
+	pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+
+	return rate;
+}
+
+unsigned long recalc_stm_pll3200c32(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clkgen_pll *pll = to_clkgen_pll(hw);
+	unsigned long ndiv, idf;
+	unsigned long rate = 0;
+
+	if (!clkgen_pll_is_enabled(hw) || !clkgen_pll_is_locked(hw))
+		return 0;
+
+	ndiv = CLKGEN_READ(pll, ndiv);
+	idf = CLKGEN_READ(pll, idf);
+
+	if (idf)
+		/* Note: input is divided to avoid overflow */
+		rate = ((2 * (parent_rate/1000) * ndiv) / idf) * 1000;
+
+	pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+
+	return rate;
+}
+
+unsigned long recalc_stm_pll1200c32(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clkgen_pll *pll = to_clkgen_pll(hw);
+	unsigned long odf, ldf, idf;
+	unsigned long rate;
+
+	if (!clkgen_pll_is_enabled(hw) || !clkgen_pll_is_locked(hw))
+		return 0;
+
+	odf = CLKGEN_READ(pll, odf[0]);
+	ldf = CLKGEN_READ(pll, ldf);
+	idf = CLKGEN_READ(pll, idf);
+
+	if (!idf) /* idf==0 means 1 */
+		idf = 1;
+	if (!odf) /* odf==0 means 1 */
+		odf = 1;
+
+	/* Note: input is divided by 1000 to avoid overflow */
+	rate = (((parent_rate / 1000) * ldf) / (odf * idf)) * 1000;
+
+	pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+
+	return rate;
+}
+
+static const struct clk_ops st_pll1600c65_ops = {
+	.is_enabled	= clkgen_pll_is_enabled,
+	.recalc_rate	= recalc_stm_pll1600c65,
+};
+
+static const struct clk_ops st_pll800c65_ops = {
+	.is_enabled	= clkgen_pll_is_enabled,
+	.recalc_rate	= recalc_stm_pll800c65,
+};
+
+static const struct clk_ops stm_pll3200c32_ops = {
+	.is_enabled	= clkgen_pll_is_enabled,
+	.recalc_rate	= recalc_stm_pll3200c32,
+};
+
+static const struct clk_ops st_pll1200c32_ops = {
+	.is_enabled	= clkgen_pll_is_enabled,
+	.recalc_rate	= recalc_stm_pll1200c32,
+};
+
+static struct clk * __init clkgen_pll_register(const char *parent_name,
+				struct clkgen_pll_data	*pll_data,
+				void __iomem *reg,
+				const char *clk_name)
+{
+	struct clkgen_pll *pll;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = clk_name;
+	init.ops = pll_data->ops;
+
+	init.flags = CLK_IS_BASIC;
+	init.parent_names = &parent_name;
+	init.num_parents  = 1;
+
+	pll->data = pll_data;
+	pll->regs_base = reg;
+	pll->hw.init = &init;
+
+	clk = clk_register(NULL, &pll->hw);
+	if (IS_ERR(clk)) {
+		kfree(pll);
+		return clk;
+	}
+
+	pr_debug("%s: parent %s rate %lu\n",
+			__clk_get_name(clk),
+			__clk_get_name(clk_get_parent(clk)),
+			clk_get_rate(clk));
+
+	return clk;
+}
+
+static struct clk * __init clkgen_c65_lsdiv_register(const char *parent_name,
+						     const char *clk_name)
+{
+	struct clk *clk;
+
+	clk = clk_register_fixed_factor(NULL, clk_name, parent_name, 0, 1, 2);
+	if (IS_ERR(clk))
+		return clk;
+
+	pr_debug("%s: parent %s rate %lu\n",
+			__clk_get_name(clk),
+			__clk_get_name(clk_get_parent(clk)),
+			clk_get_rate(clk));
+	return clk;
+}
+
+static void __iomem * __init clkgen_get_register_base(
+				struct device_node *np)
+{
+	struct device_node *pnode;
+	void __iomem *reg = NULL;
+
+	pnode = of_get_parent(np);
+	if (!pnode)
+		return NULL;
+
+	reg = of_iomap(pnode, 0);
+
+	of_node_put(pnode);
+	return reg;
+}
+
+#define CLKGENAx_PLL0_OFFSET 0x0
+#define CLKGENAx_PLL1_OFFSET 0x4
+
+static void __init clkgena_c65_pll_setup(struct device_node *np)
+{
+	const int num_pll_outputs = 3;
+	struct clk_onecell_data *clk_data;
+	const char *parent_name;
+	void __iomem *reg;
+	const char *clk_name;
+
+	parent_name = of_clk_get_parent_name(np, 0);
+	if (!parent_name)
+		return;
+
+	reg = clkgen_get_register_base(np);
+	if (!reg)
+		return;
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return;
+
+	clk_data->clk_num = num_pll_outputs;
+	clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *),
+				 GFP_KERNEL);
+
+	if (!clk_data->clks)
+		goto err;
+
+	if (of_property_read_string_index(np, "clock-output-names",
+					  0, &clk_name))
+		goto err;
+
+	/*
+	 * PLL0 HS (high speed) output
+	 */
+	clk_data->clks[0] = clkgen_pll_register(parent_name,
+						&st_pll1600c65_ax,
+						reg + CLKGENAx_PLL0_OFFSET,
+						clk_name);
+
+	if (IS_ERR(clk_data->clks[0]))
+		goto err;
+
+	if (of_property_read_string_index(np, "clock-output-names",
+					  1, &clk_name))
+		goto err;
+
+	/*
+	 * PLL0 LS (low speed) output, which is a fixed divide by 2 of the
+	 * high speed output.
+	 */
+	clk_data->clks[1] = clkgen_c65_lsdiv_register(__clk_get_name
+						      (clk_data->clks[0]),
+						      clk_name);
+
+	if (IS_ERR(clk_data->clks[1]))
+		goto err;
+
+	if (of_property_read_string_index(np, "clock-output-names",
+					  2, &clk_name))
+		goto err;
+
+	/*
+	 * PLL1 output
+	 */
+	clk_data->clks[2] = clkgen_pll_register(parent_name,
+						&st_pll800c65_ax,
+						reg + CLKGENAx_PLL1_OFFSET,
+						clk_name);
+
+	if (IS_ERR(clk_data->clks[2]))
+		goto err;
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+	return;
+
+err:
+	kfree(clk_data->clks);
+	kfree(clk_data);
+}
+CLK_OF_DECLARE(clkgena_c65_plls,
+	       "st,clkgena-plls-c65", clkgena_c65_pll_setup);
+
+static struct clk * __init clkgen_odf_register(const char *parent_name,
+					       void * __iomem reg,
+					       struct clkgen_pll_data *pll_data,
+					       int odf,
+					       spinlock_t *odf_lock,
+					       const char *odf_name)
+{
+	struct clk *clk;
+	unsigned long flags;
+	struct clk_gate *gate;
+	struct clk_divider *div;
+
+	flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_GATE;
+
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+	if (!gate)
+		return ERR_PTR(-ENOMEM);
+
+	gate->flags = CLK_GATE_SET_TO_DISABLE;
+	gate->reg = reg + pll_data->odf_gate[odf].offset;
+	gate->bit_idx = pll_data->odf_gate[odf].shift;
+	gate->lock = odf_lock;
+
+	div = kzalloc(sizeof(*div), GFP_KERNEL);
+	if (!div)
+		return ERR_PTR(-ENOMEM);
+
+	div->flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;
+	div->reg = reg + pll_data->odf[odf].offset;
+	div->shift = pll_data->odf[odf].shift;
+	div->width = fls(pll_data->odf[odf].mask);
+	div->lock = odf_lock;
+
+	clk = clk_register_composite(NULL, odf_name, &parent_name, 1,
+				     NULL, NULL,
+				     &div->hw, &clk_divider_ops,
+				     &gate->hw, &clk_gate_ops,
+				     flags);
+	if (IS_ERR(clk))
+		return clk;
+
+	pr_debug("%s: parent %s rate %lu\n",
+			__clk_get_name(clk),
+			__clk_get_name(clk_get_parent(clk)),
+			clk_get_rate(clk));
+	return clk;
+}
+
+static struct of_device_id c32_pll_of_match[] = {
+	{
+		.compatible = "st,plls-c32-a1x-0",
+		.data = &st_pll3200c32_a1x_0,
+	},
+	{
+		.compatible = "st,plls-c32-a1x-1",
+		.data = &st_pll3200c32_a1x_1,
+	},
+	{}
+};
+
+static void __init clkgen_c32_pll_setup(struct device_node *np)
+{
+	const struct of_device_id *match;
+	struct clk *clk;
+	const char *parent_name, *pll_name;
+	void __iomem *pll_base;
+	int num_odfs, odf;
+	struct clk_onecell_data *clk_data;
+	struct clkgen_pll_data	*data;
+
+	match = of_match_node(c32_pll_of_match, np);
+	if (!match) {
+		pr_err("%s: No matching data\n", __func__);
+		return;
+	}
+
+	data = (struct clkgen_pll_data *) match->data;
+
+	parent_name = of_clk_get_parent_name(np, 0);
+	if (!parent_name)
+		return;
+
+	pll_base = clkgen_get_register_base(np);
+	if (!pll_base)
+		return;
+
+	clk = clkgen_pll_register(parent_name, data, pll_base, np->name);
+	if (IS_ERR(clk))
+		return;
+
+	pll_name = __clk_get_name(clk);
+
+	num_odfs = data->num_odfs;
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return;
+
+	clk_data->clk_num = num_odfs;
+	clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *),
+				 GFP_KERNEL);
+
+	if (!clk_data->clks)
+		goto err;
+
+	for (odf = 0; odf < num_odfs; odf++) {
+		struct clk *clk;
+		const char *clk_name;
+
+		if (of_property_read_string_index(np, "clock-output-names",
+						  odf, &clk_name))
+			return;
+
+		clk = clkgen_odf_register(pll_name, pll_base, data,
+				odf, &clkgena_c32_odf_lock, clk_name);
+		if (IS_ERR(clk))
+			goto err;
+
+		clk_data->clks[odf] = clk;
+	}
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+	return;
+
+err:
+	kfree(pll_name);
+	kfree(clk_data->clks);
+	kfree(clk_data);
+}
+CLK_OF_DECLARE(clkgen_c32_pll, "st,clkgen-plls-c32", clkgen_c32_pll_setup);
diff --git a/drivers/clk/st/clkgen.h b/drivers/clk/st/clkgen.h
new file mode 100644
index 0000000..35c8632
--- /dev/null
+++ b/drivers/clk/st/clkgen.h
@@ -0,0 +1,48 @@
+/************************************************************************
+File  : Clock H/w specific Information
+
+Author: Pankaj Dev <pankaj.dev@st.com>
+
+Copyright (C) 2014 STMicroelectronics
+************************************************************************/
+
+#ifndef __CLKGEN_INFO_H
+#define __CLKGEN_INFO_H
+
+struct clkgen_field {
+	unsigned int offset;
+	unsigned int mask;
+	unsigned int shift;
+};
+
+static inline unsigned long clkgen_read(void __iomem	*base,
+					  struct clkgen_field *field)
+{
+	return (readl(base + field->offset) >> field->shift) & field->mask;
+}
+
+
+static inline void clkgen_write(void __iomem *base, struct clkgen_field *field,
+				  unsigned long val)
+{
+	writel((readl(base + field->offset) &
+	       ~(field->mask << field->shift)) | (val << field->shift),
+	       base + field->offset);
+
+	return;
+}
+
+#define CLKGEN_FIELD(_offset, _mask, _shift) {		\
+				.offset	= _offset,	\
+				.mask	= _mask,	\
+				.shift	= _shift,	\
+				}
+
+#define CLKGEN_READ(pll, field) clkgen_read(pll->regs_base, \
+		&pll->data->field)
+
+#define CLKGEN_WRITE(pll, field, val) clkgen_write(pll->regs_base, \
+		&pll->data->field, val)
+
+#endif /*__CLKGEN_INFO_H*/
+
-- 
1.9.0


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

* [PATCH v0 02/15] drivers: clk: st: Support for PLLs inside ClockGenA(s)
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: mturquette, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, rob, linux, devicetree, linux-doc, linux-kernel,
	linux-arm-kernel
  Cc: Pankaj Dev, Lee Jones, Gabriel Fernandez

The patch supports the c65/c32 type PLLs used by ClockGenA(s)

PLL clock : It includes support for all c65/c32 type PLLs
inside ClockGenA(s) : implemented as Fixed Parent / Fixed Rate clock,
with clock rate calculated reading H/w settings done at BOOT.

c65 PLLs have 2 outputs : HS and LS
c32 PLLs have 1-4 outputs : ODFx

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 drivers/clk/st/Makefile     |   2 +-
 drivers/clk/st/clkgen-pll.c | 559 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/st/clkgen.h     |  48 ++++
 3 files changed, 608 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/st/clkgen-pll.c
 create mode 100644 drivers/clk/st/clkgen.h

diff --git a/drivers/clk/st/Makefile b/drivers/clk/st/Makefile
index e42b370..b7b10f9 100644
--- a/drivers/clk/st/Makefile
+++ b/drivers/clk/st/Makefile
@@ -1 +1 @@
-obj-y += clkgen-mux.o
+obj-y += clkgen-mux.o clkgen-pll.o
diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c
new file mode 100644
index 0000000..c6b38b0
--- /dev/null
+++ b/drivers/clk/st/clkgen-pll.c
@@ -0,0 +1,559 @@
+/*
+ * Copyright (C) 2014 STMicroelectronics (R&D) Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+/*
+ * Authors:
+ * Stephen Gallimore <stephen.gallimore@st.com>,
+ * Pankaj Dev <pankaj.dev@st.com>.
+ */
+
+#include <linux/slab.h>
+#include <linux/of_address.h>
+#include <linux/clk-provider.h>
+
+#include "clkgen.h"
+
+static DEFINE_SPINLOCK(clkgena_c32_odf_lock);
+
+/*
+ * Common PLL configuration register bits for PLL800 and PLL1600 C65
+ */
+#define C65_MDIV_PLL800_MASK	(0xff)
+#define C65_MDIV_PLL1600_MASK	(0x7)
+#define C65_NDIV_MASK		(0xff)
+#define C65_PDIV_MASK		(0x7)
+
+/*
+ * PLL configuration register bits for PLL3200 C32
+ */
+#define C32_NDIV_MASK (0xff)
+#define C32_IDF_MASK (0x7)
+#define C32_ODF_MASK (0x3f)
+#define C32_LDF_MASK (0x7f)
+
+#define C32_MAX_ODFS (4)
+
+struct clkgen_pll_data {
+	struct clkgen_field pdn_status;
+	struct clkgen_field locked_status;
+	struct clkgen_field mdiv;
+	struct clkgen_field ndiv;
+	struct clkgen_field pdiv;
+	struct clkgen_field idf;
+	struct clkgen_field ldf;
+	unsigned int num_odfs;
+	struct clkgen_field odf[C32_MAX_ODFS];
+	struct clkgen_field odf_gate[C32_MAX_ODFS];
+	const struct clk_ops *ops;
+};
+
+static const struct clk_ops st_pll1600c65_ops;
+static const struct clk_ops st_pll800c65_ops;
+static const struct clk_ops stm_pll3200c32_ops;
+static const struct clk_ops st_pll1200c32_ops;
+
+static struct clkgen_pll_data st_pll1600c65_ax = {
+	.pdn_status	= CLKGEN_FIELD(0x0, 0x1,			19),
+	.locked_status	= CLKGEN_FIELD(0x0, 0x1,			31),
+	.mdiv		= CLKGEN_FIELD(0x0, C65_MDIV_PLL1600_MASK,	0),
+	.ndiv		= CLKGEN_FIELD(0x0, C65_NDIV_MASK,		8),
+	.ops		= &st_pll1600c65_ops
+};
+
+static struct clkgen_pll_data st_pll800c65_ax = {
+	.pdn_status	= CLKGEN_FIELD(0x0,	0x1,			19),
+	.locked_status	= CLKGEN_FIELD(0x0,	0x1,			31),
+	.mdiv		= CLKGEN_FIELD(0x0,	C65_MDIV_PLL800_MASK,	0),
+	.ndiv		= CLKGEN_FIELD(0x0,	C65_NDIV_MASK,		8),
+	.pdiv		= CLKGEN_FIELD(0x0,	C65_PDIV_MASK,		16),
+	.ops		= &st_pll800c65_ops
+};
+
+static struct clkgen_pll_data st_pll3200c32_a1x_0 = {
+	.pdn_status	= CLKGEN_FIELD(0x0,	0x1,			31),
+	.locked_status	= CLKGEN_FIELD(0x4,	0x1,			31),
+	.ndiv		= CLKGEN_FIELD(0x0,	C32_NDIV_MASK,		0x0),
+	.idf		= CLKGEN_FIELD(0x4,	C32_IDF_MASK,		0x0),
+	.num_odfs = 4,
+	.odf =	{	CLKGEN_FIELD(0x54,	C32_ODF_MASK,		4),
+			CLKGEN_FIELD(0x54,	C32_ODF_MASK,		10),
+			CLKGEN_FIELD(0x54,	C32_ODF_MASK,		16),
+			CLKGEN_FIELD(0x54,	C32_ODF_MASK,		22) },
+	.odf_gate = {	CLKGEN_FIELD(0x54,	0x1,			0),
+			CLKGEN_FIELD(0x54,	0x1,			1),
+			CLKGEN_FIELD(0x54,	0x1,			2),
+			CLKGEN_FIELD(0x54,	0x1,			3) },
+	.ops		= &stm_pll3200c32_ops,
+};
+
+static struct clkgen_pll_data st_pll3200c32_a1x_1 = {
+	.pdn_status	= CLKGEN_FIELD(0xC,	0x1,			31),
+	.locked_status	= CLKGEN_FIELD(0x10,	0x1,			31),
+	.ndiv		= CLKGEN_FIELD(0xC,	C32_NDIV_MASK,		0x0),
+	.idf		= CLKGEN_FIELD(0x10,	C32_IDF_MASK,		0x0),
+	.num_odfs = 4,
+	.odf = {	CLKGEN_FIELD(0x58,	C32_ODF_MASK,		4),
+			CLKGEN_FIELD(0x58,	C32_ODF_MASK,		10),
+			CLKGEN_FIELD(0x58,	C32_ODF_MASK,		16),
+			CLKGEN_FIELD(0x58,	C32_ODF_MASK,		22) },
+	.odf_gate = {	CLKGEN_FIELD(0x58,	0x1,			0),
+			CLKGEN_FIELD(0x58,	0x1,			1),
+			CLKGEN_FIELD(0x58,	0x1,			2),
+			CLKGEN_FIELD(0x58,	0x1,			3) },
+	.ops		= &stm_pll3200c32_ops,
+};
+
+/**
+ * DOC: Clock Generated by PLL, rate set and enabled by bootloader
+ *
+ * Traits of this clock:
+ * prepare - clk_(un)prepare only ensures parent is (un)prepared
+ * enable - clk_enable/disable only ensures parent is enabled
+ * rate - rate is fixed. No clk_set_rate support
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+/**
+ * PLL clock that is integrated in the ClockGenA instances on the STiH415
+ * and STiH416.
+ *
+ * @hw: handle between common and hardware-specific interfaces.
+ * @type: PLL instance type.
+ * @regs_base: base of the PLL configuration register(s).
+ *
+ */
+struct clkgen_pll {
+	struct clk_hw		hw;
+	struct clkgen_pll_data	*data;
+	void __iomem		*regs_base;
+};
+
+#define to_clkgen_pll(_hw) container_of(_hw, struct clkgen_pll, hw)
+
+static int clkgen_pll_is_locked(struct clk_hw *hw)
+{
+	struct clkgen_pll *pll = to_clkgen_pll(hw);
+	u32 locked = CLKGEN_READ(pll, locked_status);
+
+	return !!locked;
+}
+
+static int clkgen_pll_is_enabled(struct clk_hw *hw)
+{
+	struct clkgen_pll *pll = to_clkgen_pll(hw);
+	u32 poweroff = CLKGEN_READ(pll, pdn_status);
+	return !poweroff;
+}
+
+unsigned long recalc_stm_pll800c65(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clkgen_pll *pll = to_clkgen_pll(hw);
+	unsigned long mdiv, ndiv, pdiv;
+	unsigned long rate;
+	uint64_t res;
+
+	if (!clkgen_pll_is_enabled(hw) || !clkgen_pll_is_locked(hw))
+		return 0;
+
+	pdiv = CLKGEN_READ(pll, pdiv);
+	mdiv = CLKGEN_READ(pll, mdiv);
+	ndiv = CLKGEN_READ(pll, ndiv);
+
+	if (!mdiv)
+		mdiv++; /* mdiv=0 or 1 => MDIV=1 */
+
+	res = (uint64_t)2 * (uint64_t)parent_rate * (uint64_t)ndiv;
+	rate = (unsigned long)div64_u64(res, mdiv * (1 << pdiv));
+
+	pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+
+	return rate;
+
+}
+
+unsigned long recalc_stm_pll1600c65(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clkgen_pll *pll = to_clkgen_pll(hw);
+	unsigned long mdiv, ndiv;
+	unsigned long rate;
+
+	if (!clkgen_pll_is_enabled(hw) || !clkgen_pll_is_locked(hw))
+		return 0;
+
+	mdiv = CLKGEN_READ(pll, mdiv);
+	ndiv = CLKGEN_READ(pll, ndiv);
+
+	if (!mdiv)
+		mdiv = 1;
+
+	/* Note: input is divided by 1000 to avoid overflow */
+	rate = ((2 * (parent_rate / 1000) * ndiv) / mdiv) * 1000;
+
+	pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+
+	return rate;
+}
+
+unsigned long recalc_stm_pll3200c32(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clkgen_pll *pll = to_clkgen_pll(hw);
+	unsigned long ndiv, idf;
+	unsigned long rate = 0;
+
+	if (!clkgen_pll_is_enabled(hw) || !clkgen_pll_is_locked(hw))
+		return 0;
+
+	ndiv = CLKGEN_READ(pll, ndiv);
+	idf = CLKGEN_READ(pll, idf);
+
+	if (idf)
+		/* Note: input is divided to avoid overflow */
+		rate = ((2 * (parent_rate/1000) * ndiv) / idf) * 1000;
+
+	pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+
+	return rate;
+}
+
+unsigned long recalc_stm_pll1200c32(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clkgen_pll *pll = to_clkgen_pll(hw);
+	unsigned long odf, ldf, idf;
+	unsigned long rate;
+
+	if (!clkgen_pll_is_enabled(hw) || !clkgen_pll_is_locked(hw))
+		return 0;
+
+	odf = CLKGEN_READ(pll, odf[0]);
+	ldf = CLKGEN_READ(pll, ldf);
+	idf = CLKGEN_READ(pll, idf);
+
+	if (!idf) /* idf==0 means 1 */
+		idf = 1;
+	if (!odf) /* odf==0 means 1 */
+		odf = 1;
+
+	/* Note: input is divided by 1000 to avoid overflow */
+	rate = (((parent_rate / 1000) * ldf) / (odf * idf)) * 1000;
+
+	pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+
+	return rate;
+}
+
+static const struct clk_ops st_pll1600c65_ops = {
+	.is_enabled	= clkgen_pll_is_enabled,
+	.recalc_rate	= recalc_stm_pll1600c65,
+};
+
+static const struct clk_ops st_pll800c65_ops = {
+	.is_enabled	= clkgen_pll_is_enabled,
+	.recalc_rate	= recalc_stm_pll800c65,
+};
+
+static const struct clk_ops stm_pll3200c32_ops = {
+	.is_enabled	= clkgen_pll_is_enabled,
+	.recalc_rate	= recalc_stm_pll3200c32,
+};
+
+static const struct clk_ops st_pll1200c32_ops = {
+	.is_enabled	= clkgen_pll_is_enabled,
+	.recalc_rate	= recalc_stm_pll1200c32,
+};
+
+static struct clk * __init clkgen_pll_register(const char *parent_name,
+				struct clkgen_pll_data	*pll_data,
+				void __iomem *reg,
+				const char *clk_name)
+{
+	struct clkgen_pll *pll;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = clk_name;
+	init.ops = pll_data->ops;
+
+	init.flags = CLK_IS_BASIC;
+	init.parent_names = &parent_name;
+	init.num_parents  = 1;
+
+	pll->data = pll_data;
+	pll->regs_base = reg;
+	pll->hw.init = &init;
+
+	clk = clk_register(NULL, &pll->hw);
+	if (IS_ERR(clk)) {
+		kfree(pll);
+		return clk;
+	}
+
+	pr_debug("%s: parent %s rate %lu\n",
+			__clk_get_name(clk),
+			__clk_get_name(clk_get_parent(clk)),
+			clk_get_rate(clk));
+
+	return clk;
+}
+
+static struct clk * __init clkgen_c65_lsdiv_register(const char *parent_name,
+						     const char *clk_name)
+{
+	struct clk *clk;
+
+	clk = clk_register_fixed_factor(NULL, clk_name, parent_name, 0, 1, 2);
+	if (IS_ERR(clk))
+		return clk;
+
+	pr_debug("%s: parent %s rate %lu\n",
+			__clk_get_name(clk),
+			__clk_get_name(clk_get_parent(clk)),
+			clk_get_rate(clk));
+	return clk;
+}
+
+static void __iomem * __init clkgen_get_register_base(
+				struct device_node *np)
+{
+	struct device_node *pnode;
+	void __iomem *reg = NULL;
+
+	pnode = of_get_parent(np);
+	if (!pnode)
+		return NULL;
+
+	reg = of_iomap(pnode, 0);
+
+	of_node_put(pnode);
+	return reg;
+}
+
+#define CLKGENAx_PLL0_OFFSET 0x0
+#define CLKGENAx_PLL1_OFFSET 0x4
+
+static void __init clkgena_c65_pll_setup(struct device_node *np)
+{
+	const int num_pll_outputs = 3;
+	struct clk_onecell_data *clk_data;
+	const char *parent_name;
+	void __iomem *reg;
+	const char *clk_name;
+
+	parent_name = of_clk_get_parent_name(np, 0);
+	if (!parent_name)
+		return;
+
+	reg = clkgen_get_register_base(np);
+	if (!reg)
+		return;
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return;
+
+	clk_data->clk_num = num_pll_outputs;
+	clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *),
+				 GFP_KERNEL);
+
+	if (!clk_data->clks)
+		goto err;
+
+	if (of_property_read_string_index(np, "clock-output-names",
+					  0, &clk_name))
+		goto err;
+
+	/*
+	 * PLL0 HS (high speed) output
+	 */
+	clk_data->clks[0] = clkgen_pll_register(parent_name,
+						&st_pll1600c65_ax,
+						reg + CLKGENAx_PLL0_OFFSET,
+						clk_name);
+
+	if (IS_ERR(clk_data->clks[0]))
+		goto err;
+
+	if (of_property_read_string_index(np, "clock-output-names",
+					  1, &clk_name))
+		goto err;
+
+	/*
+	 * PLL0 LS (low speed) output, which is a fixed divide by 2 of the
+	 * high speed output.
+	 */
+	clk_data->clks[1] = clkgen_c65_lsdiv_register(__clk_get_name
+						      (clk_data->clks[0]),
+						      clk_name);
+
+	if (IS_ERR(clk_data->clks[1]))
+		goto err;
+
+	if (of_property_read_string_index(np, "clock-output-names",
+					  2, &clk_name))
+		goto err;
+
+	/*
+	 * PLL1 output
+	 */
+	clk_data->clks[2] = clkgen_pll_register(parent_name,
+						&st_pll800c65_ax,
+						reg + CLKGENAx_PLL1_OFFSET,
+						clk_name);
+
+	if (IS_ERR(clk_data->clks[2]))
+		goto err;
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+	return;
+
+err:
+	kfree(clk_data->clks);
+	kfree(clk_data);
+}
+CLK_OF_DECLARE(clkgena_c65_plls,
+	       "st,clkgena-plls-c65", clkgena_c65_pll_setup);
+
+static struct clk * __init clkgen_odf_register(const char *parent_name,
+					       void * __iomem reg,
+					       struct clkgen_pll_data *pll_data,
+					       int odf,
+					       spinlock_t *odf_lock,
+					       const char *odf_name)
+{
+	struct clk *clk;
+	unsigned long flags;
+	struct clk_gate *gate;
+	struct clk_divider *div;
+
+	flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_GATE;
+
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+	if (!gate)
+		return ERR_PTR(-ENOMEM);
+
+	gate->flags = CLK_GATE_SET_TO_DISABLE;
+	gate->reg = reg + pll_data->odf_gate[odf].offset;
+	gate->bit_idx = pll_data->odf_gate[odf].shift;
+	gate->lock = odf_lock;
+
+	div = kzalloc(sizeof(*div), GFP_KERNEL);
+	if (!div)
+		return ERR_PTR(-ENOMEM);
+
+	div->flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;
+	div->reg = reg + pll_data->odf[odf].offset;
+	div->shift = pll_data->odf[odf].shift;
+	div->width = fls(pll_data->odf[odf].mask);
+	div->lock = odf_lock;
+
+	clk = clk_register_composite(NULL, odf_name, &parent_name, 1,
+				     NULL, NULL,
+				     &div->hw, &clk_divider_ops,
+				     &gate->hw, &clk_gate_ops,
+				     flags);
+	if (IS_ERR(clk))
+		return clk;
+
+	pr_debug("%s: parent %s rate %lu\n",
+			__clk_get_name(clk),
+			__clk_get_name(clk_get_parent(clk)),
+			clk_get_rate(clk));
+	return clk;
+}
+
+static struct of_device_id c32_pll_of_match[] = {
+	{
+		.compatible = "st,plls-c32-a1x-0",
+		.data = &st_pll3200c32_a1x_0,
+	},
+	{
+		.compatible = "st,plls-c32-a1x-1",
+		.data = &st_pll3200c32_a1x_1,
+	},
+	{}
+};
+
+static void __init clkgen_c32_pll_setup(struct device_node *np)
+{
+	const struct of_device_id *match;
+	struct clk *clk;
+	const char *parent_name, *pll_name;
+	void __iomem *pll_base;
+	int num_odfs, odf;
+	struct clk_onecell_data *clk_data;
+	struct clkgen_pll_data	*data;
+
+	match = of_match_node(c32_pll_of_match, np);
+	if (!match) {
+		pr_err("%s: No matching data\n", __func__);
+		return;
+	}
+
+	data = (struct clkgen_pll_data *) match->data;
+
+	parent_name = of_clk_get_parent_name(np, 0);
+	if (!parent_name)
+		return;
+
+	pll_base = clkgen_get_register_base(np);
+	if (!pll_base)
+		return;
+
+	clk = clkgen_pll_register(parent_name, data, pll_base, np->name);
+	if (IS_ERR(clk))
+		return;
+
+	pll_name = __clk_get_name(clk);
+
+	num_odfs = data->num_odfs;
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return;
+
+	clk_data->clk_num = num_odfs;
+	clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *),
+				 GFP_KERNEL);
+
+	if (!clk_data->clks)
+		goto err;
+
+	for (odf = 0; odf < num_odfs; odf++) {
+		struct clk *clk;
+		const char *clk_name;
+
+		if (of_property_read_string_index(np, "clock-output-names",
+						  odf, &clk_name))
+			return;
+
+		clk = clkgen_odf_register(pll_name, pll_base, data,
+				odf, &clkgena_c32_odf_lock, clk_name);
+		if (IS_ERR(clk))
+			goto err;
+
+		clk_data->clks[odf] = clk;
+	}
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+	return;
+
+err:
+	kfree(pll_name);
+	kfree(clk_data->clks);
+	kfree(clk_data);
+}
+CLK_OF_DECLARE(clkgen_c32_pll, "st,clkgen-plls-c32", clkgen_c32_pll_setup);
diff --git a/drivers/clk/st/clkgen.h b/drivers/clk/st/clkgen.h
new file mode 100644
index 0000000..35c8632
--- /dev/null
+++ b/drivers/clk/st/clkgen.h
@@ -0,0 +1,48 @@
+/************************************************************************
+File  : Clock H/w specific Information
+
+Author: Pankaj Dev <pankaj.dev@st.com>
+
+Copyright (C) 2014 STMicroelectronics
+************************************************************************/
+
+#ifndef __CLKGEN_INFO_H
+#define __CLKGEN_INFO_H
+
+struct clkgen_field {
+	unsigned int offset;
+	unsigned int mask;
+	unsigned int shift;
+};
+
+static inline unsigned long clkgen_read(void __iomem	*base,
+					  struct clkgen_field *field)
+{
+	return (readl(base + field->offset) >> field->shift) & field->mask;
+}
+
+
+static inline void clkgen_write(void __iomem *base, struct clkgen_field *field,
+				  unsigned long val)
+{
+	writel((readl(base + field->offset) &
+	       ~(field->mask << field->shift)) | (val << field->shift),
+	       base + field->offset);
+
+	return;
+}
+
+#define CLKGEN_FIELD(_offset, _mask, _shift) {		\
+				.offset	= _offset,	\
+				.mask	= _mask,	\
+				.shift	= _shift,	\
+				}
+
+#define CLKGEN_READ(pll, field) clkgen_read(pll->regs_base, \
+		&pll->data->field)
+
+#define CLKGEN_WRITE(pll, field, val) clkgen_write(pll->regs_base, \
+		&pll->data->field, val)
+
+#endif /*__CLKGEN_INFO_H*/
+
-- 
1.9.0

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

* [PATCH v0 02/15] drivers: clk: st: Support for PLLs inside ClockGenA(s)
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

The patch supports the c65/c32 type PLLs used by ClockGenA(s)

PLL clock : It includes support for all c65/c32 type PLLs
inside ClockGenA(s) : implemented as Fixed Parent / Fixed Rate clock,
with clock rate calculated reading H/w settings done at BOOT.

c65 PLLs have 2 outputs : HS and LS
c32 PLLs have 1-4 outputs : ODFx

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 drivers/clk/st/Makefile     |   2 +-
 drivers/clk/st/clkgen-pll.c | 559 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/st/clkgen.h     |  48 ++++
 3 files changed, 608 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/st/clkgen-pll.c
 create mode 100644 drivers/clk/st/clkgen.h

diff --git a/drivers/clk/st/Makefile b/drivers/clk/st/Makefile
index e42b370..b7b10f9 100644
--- a/drivers/clk/st/Makefile
+++ b/drivers/clk/st/Makefile
@@ -1 +1 @@
-obj-y += clkgen-mux.o
+obj-y += clkgen-mux.o clkgen-pll.o
diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c
new file mode 100644
index 0000000..c6b38b0
--- /dev/null
+++ b/drivers/clk/st/clkgen-pll.c
@@ -0,0 +1,559 @@
+/*
+ * Copyright (C) 2014 STMicroelectronics (R&D) Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+/*
+ * Authors:
+ * Stephen Gallimore <stephen.gallimore@st.com>,
+ * Pankaj Dev <pankaj.dev@st.com>.
+ */
+
+#include <linux/slab.h>
+#include <linux/of_address.h>
+#include <linux/clk-provider.h>
+
+#include "clkgen.h"
+
+static DEFINE_SPINLOCK(clkgena_c32_odf_lock);
+
+/*
+ * Common PLL configuration register bits for PLL800 and PLL1600 C65
+ */
+#define C65_MDIV_PLL800_MASK	(0xff)
+#define C65_MDIV_PLL1600_MASK	(0x7)
+#define C65_NDIV_MASK		(0xff)
+#define C65_PDIV_MASK		(0x7)
+
+/*
+ * PLL configuration register bits for PLL3200 C32
+ */
+#define C32_NDIV_MASK (0xff)
+#define C32_IDF_MASK (0x7)
+#define C32_ODF_MASK (0x3f)
+#define C32_LDF_MASK (0x7f)
+
+#define C32_MAX_ODFS (4)
+
+struct clkgen_pll_data {
+	struct clkgen_field pdn_status;
+	struct clkgen_field locked_status;
+	struct clkgen_field mdiv;
+	struct clkgen_field ndiv;
+	struct clkgen_field pdiv;
+	struct clkgen_field idf;
+	struct clkgen_field ldf;
+	unsigned int num_odfs;
+	struct clkgen_field odf[C32_MAX_ODFS];
+	struct clkgen_field odf_gate[C32_MAX_ODFS];
+	const struct clk_ops *ops;
+};
+
+static const struct clk_ops st_pll1600c65_ops;
+static const struct clk_ops st_pll800c65_ops;
+static const struct clk_ops stm_pll3200c32_ops;
+static const struct clk_ops st_pll1200c32_ops;
+
+static struct clkgen_pll_data st_pll1600c65_ax = {
+	.pdn_status	= CLKGEN_FIELD(0x0, 0x1,			19),
+	.locked_status	= CLKGEN_FIELD(0x0, 0x1,			31),
+	.mdiv		= CLKGEN_FIELD(0x0, C65_MDIV_PLL1600_MASK,	0),
+	.ndiv		= CLKGEN_FIELD(0x0, C65_NDIV_MASK,		8),
+	.ops		= &st_pll1600c65_ops
+};
+
+static struct clkgen_pll_data st_pll800c65_ax = {
+	.pdn_status	= CLKGEN_FIELD(0x0,	0x1,			19),
+	.locked_status	= CLKGEN_FIELD(0x0,	0x1,			31),
+	.mdiv		= CLKGEN_FIELD(0x0,	C65_MDIV_PLL800_MASK,	0),
+	.ndiv		= CLKGEN_FIELD(0x0,	C65_NDIV_MASK,		8),
+	.pdiv		= CLKGEN_FIELD(0x0,	C65_PDIV_MASK,		16),
+	.ops		= &st_pll800c65_ops
+};
+
+static struct clkgen_pll_data st_pll3200c32_a1x_0 = {
+	.pdn_status	= CLKGEN_FIELD(0x0,	0x1,			31),
+	.locked_status	= CLKGEN_FIELD(0x4,	0x1,			31),
+	.ndiv		= CLKGEN_FIELD(0x0,	C32_NDIV_MASK,		0x0),
+	.idf		= CLKGEN_FIELD(0x4,	C32_IDF_MASK,		0x0),
+	.num_odfs = 4,
+	.odf =	{	CLKGEN_FIELD(0x54,	C32_ODF_MASK,		4),
+			CLKGEN_FIELD(0x54,	C32_ODF_MASK,		10),
+			CLKGEN_FIELD(0x54,	C32_ODF_MASK,		16),
+			CLKGEN_FIELD(0x54,	C32_ODF_MASK,		22) },
+	.odf_gate = {	CLKGEN_FIELD(0x54,	0x1,			0),
+			CLKGEN_FIELD(0x54,	0x1,			1),
+			CLKGEN_FIELD(0x54,	0x1,			2),
+			CLKGEN_FIELD(0x54,	0x1,			3) },
+	.ops		= &stm_pll3200c32_ops,
+};
+
+static struct clkgen_pll_data st_pll3200c32_a1x_1 = {
+	.pdn_status	= CLKGEN_FIELD(0xC,	0x1,			31),
+	.locked_status	= CLKGEN_FIELD(0x10,	0x1,			31),
+	.ndiv		= CLKGEN_FIELD(0xC,	C32_NDIV_MASK,		0x0),
+	.idf		= CLKGEN_FIELD(0x10,	C32_IDF_MASK,		0x0),
+	.num_odfs = 4,
+	.odf = {	CLKGEN_FIELD(0x58,	C32_ODF_MASK,		4),
+			CLKGEN_FIELD(0x58,	C32_ODF_MASK,		10),
+			CLKGEN_FIELD(0x58,	C32_ODF_MASK,		16),
+			CLKGEN_FIELD(0x58,	C32_ODF_MASK,		22) },
+	.odf_gate = {	CLKGEN_FIELD(0x58,	0x1,			0),
+			CLKGEN_FIELD(0x58,	0x1,			1),
+			CLKGEN_FIELD(0x58,	0x1,			2),
+			CLKGEN_FIELD(0x58,	0x1,			3) },
+	.ops		= &stm_pll3200c32_ops,
+};
+
+/**
+ * DOC: Clock Generated by PLL, rate set and enabled by bootloader
+ *
+ * Traits of this clock:
+ * prepare - clk_(un)prepare only ensures parent is (un)prepared
+ * enable - clk_enable/disable only ensures parent is enabled
+ * rate - rate is fixed. No clk_set_rate support
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+/**
+ * PLL clock that is integrated in the ClockGenA instances on the STiH415
+ * and STiH416.
+ *
+ * @hw: handle between common and hardware-specific interfaces.
+ * @type: PLL instance type.
+ * @regs_base: base of the PLL configuration register(s).
+ *
+ */
+struct clkgen_pll {
+	struct clk_hw		hw;
+	struct clkgen_pll_data	*data;
+	void __iomem		*regs_base;
+};
+
+#define to_clkgen_pll(_hw) container_of(_hw, struct clkgen_pll, hw)
+
+static int clkgen_pll_is_locked(struct clk_hw *hw)
+{
+	struct clkgen_pll *pll = to_clkgen_pll(hw);
+	u32 locked = CLKGEN_READ(pll, locked_status);
+
+	return !!locked;
+}
+
+static int clkgen_pll_is_enabled(struct clk_hw *hw)
+{
+	struct clkgen_pll *pll = to_clkgen_pll(hw);
+	u32 poweroff = CLKGEN_READ(pll, pdn_status);
+	return !poweroff;
+}
+
+unsigned long recalc_stm_pll800c65(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clkgen_pll *pll = to_clkgen_pll(hw);
+	unsigned long mdiv, ndiv, pdiv;
+	unsigned long rate;
+	uint64_t res;
+
+	if (!clkgen_pll_is_enabled(hw) || !clkgen_pll_is_locked(hw))
+		return 0;
+
+	pdiv = CLKGEN_READ(pll, pdiv);
+	mdiv = CLKGEN_READ(pll, mdiv);
+	ndiv = CLKGEN_READ(pll, ndiv);
+
+	if (!mdiv)
+		mdiv++; /* mdiv=0 or 1 => MDIV=1 */
+
+	res = (uint64_t)2 * (uint64_t)parent_rate * (uint64_t)ndiv;
+	rate = (unsigned long)div64_u64(res, mdiv * (1 << pdiv));
+
+	pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+
+	return rate;
+
+}
+
+unsigned long recalc_stm_pll1600c65(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clkgen_pll *pll = to_clkgen_pll(hw);
+	unsigned long mdiv, ndiv;
+	unsigned long rate;
+
+	if (!clkgen_pll_is_enabled(hw) || !clkgen_pll_is_locked(hw))
+		return 0;
+
+	mdiv = CLKGEN_READ(pll, mdiv);
+	ndiv = CLKGEN_READ(pll, ndiv);
+
+	if (!mdiv)
+		mdiv = 1;
+
+	/* Note: input is divided by 1000 to avoid overflow */
+	rate = ((2 * (parent_rate / 1000) * ndiv) / mdiv) * 1000;
+
+	pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+
+	return rate;
+}
+
+unsigned long recalc_stm_pll3200c32(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clkgen_pll *pll = to_clkgen_pll(hw);
+	unsigned long ndiv, idf;
+	unsigned long rate = 0;
+
+	if (!clkgen_pll_is_enabled(hw) || !clkgen_pll_is_locked(hw))
+		return 0;
+
+	ndiv = CLKGEN_READ(pll, ndiv);
+	idf = CLKGEN_READ(pll, idf);
+
+	if (idf)
+		/* Note: input is divided to avoid overflow */
+		rate = ((2 * (parent_rate/1000) * ndiv) / idf) * 1000;
+
+	pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+
+	return rate;
+}
+
+unsigned long recalc_stm_pll1200c32(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clkgen_pll *pll = to_clkgen_pll(hw);
+	unsigned long odf, ldf, idf;
+	unsigned long rate;
+
+	if (!clkgen_pll_is_enabled(hw) || !clkgen_pll_is_locked(hw))
+		return 0;
+
+	odf = CLKGEN_READ(pll, odf[0]);
+	ldf = CLKGEN_READ(pll, ldf);
+	idf = CLKGEN_READ(pll, idf);
+
+	if (!idf) /* idf==0 means 1 */
+		idf = 1;
+	if (!odf) /* odf==0 means 1 */
+		odf = 1;
+
+	/* Note: input is divided by 1000 to avoid overflow */
+	rate = (((parent_rate / 1000) * ldf) / (odf * idf)) * 1000;
+
+	pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+
+	return rate;
+}
+
+static const struct clk_ops st_pll1600c65_ops = {
+	.is_enabled	= clkgen_pll_is_enabled,
+	.recalc_rate	= recalc_stm_pll1600c65,
+};
+
+static const struct clk_ops st_pll800c65_ops = {
+	.is_enabled	= clkgen_pll_is_enabled,
+	.recalc_rate	= recalc_stm_pll800c65,
+};
+
+static const struct clk_ops stm_pll3200c32_ops = {
+	.is_enabled	= clkgen_pll_is_enabled,
+	.recalc_rate	= recalc_stm_pll3200c32,
+};
+
+static const struct clk_ops st_pll1200c32_ops = {
+	.is_enabled	= clkgen_pll_is_enabled,
+	.recalc_rate	= recalc_stm_pll1200c32,
+};
+
+static struct clk * __init clkgen_pll_register(const char *parent_name,
+				struct clkgen_pll_data	*pll_data,
+				void __iomem *reg,
+				const char *clk_name)
+{
+	struct clkgen_pll *pll;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = clk_name;
+	init.ops = pll_data->ops;
+
+	init.flags = CLK_IS_BASIC;
+	init.parent_names = &parent_name;
+	init.num_parents  = 1;
+
+	pll->data = pll_data;
+	pll->regs_base = reg;
+	pll->hw.init = &init;
+
+	clk = clk_register(NULL, &pll->hw);
+	if (IS_ERR(clk)) {
+		kfree(pll);
+		return clk;
+	}
+
+	pr_debug("%s: parent %s rate %lu\n",
+			__clk_get_name(clk),
+			__clk_get_name(clk_get_parent(clk)),
+			clk_get_rate(clk));
+
+	return clk;
+}
+
+static struct clk * __init clkgen_c65_lsdiv_register(const char *parent_name,
+						     const char *clk_name)
+{
+	struct clk *clk;
+
+	clk = clk_register_fixed_factor(NULL, clk_name, parent_name, 0, 1, 2);
+	if (IS_ERR(clk))
+		return clk;
+
+	pr_debug("%s: parent %s rate %lu\n",
+			__clk_get_name(clk),
+			__clk_get_name(clk_get_parent(clk)),
+			clk_get_rate(clk));
+	return clk;
+}
+
+static void __iomem * __init clkgen_get_register_base(
+				struct device_node *np)
+{
+	struct device_node *pnode;
+	void __iomem *reg = NULL;
+
+	pnode = of_get_parent(np);
+	if (!pnode)
+		return NULL;
+
+	reg = of_iomap(pnode, 0);
+
+	of_node_put(pnode);
+	return reg;
+}
+
+#define CLKGENAx_PLL0_OFFSET 0x0
+#define CLKGENAx_PLL1_OFFSET 0x4
+
+static void __init clkgena_c65_pll_setup(struct device_node *np)
+{
+	const int num_pll_outputs = 3;
+	struct clk_onecell_data *clk_data;
+	const char *parent_name;
+	void __iomem *reg;
+	const char *clk_name;
+
+	parent_name = of_clk_get_parent_name(np, 0);
+	if (!parent_name)
+		return;
+
+	reg = clkgen_get_register_base(np);
+	if (!reg)
+		return;
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return;
+
+	clk_data->clk_num = num_pll_outputs;
+	clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *),
+				 GFP_KERNEL);
+
+	if (!clk_data->clks)
+		goto err;
+
+	if (of_property_read_string_index(np, "clock-output-names",
+					  0, &clk_name))
+		goto err;
+
+	/*
+	 * PLL0 HS (high speed) output
+	 */
+	clk_data->clks[0] = clkgen_pll_register(parent_name,
+						&st_pll1600c65_ax,
+						reg + CLKGENAx_PLL0_OFFSET,
+						clk_name);
+
+	if (IS_ERR(clk_data->clks[0]))
+		goto err;
+
+	if (of_property_read_string_index(np, "clock-output-names",
+					  1, &clk_name))
+		goto err;
+
+	/*
+	 * PLL0 LS (low speed) output, which is a fixed divide by 2 of the
+	 * high speed output.
+	 */
+	clk_data->clks[1] = clkgen_c65_lsdiv_register(__clk_get_name
+						      (clk_data->clks[0]),
+						      clk_name);
+
+	if (IS_ERR(clk_data->clks[1]))
+		goto err;
+
+	if (of_property_read_string_index(np, "clock-output-names",
+					  2, &clk_name))
+		goto err;
+
+	/*
+	 * PLL1 output
+	 */
+	clk_data->clks[2] = clkgen_pll_register(parent_name,
+						&st_pll800c65_ax,
+						reg + CLKGENAx_PLL1_OFFSET,
+						clk_name);
+
+	if (IS_ERR(clk_data->clks[2]))
+		goto err;
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+	return;
+
+err:
+	kfree(clk_data->clks);
+	kfree(clk_data);
+}
+CLK_OF_DECLARE(clkgena_c65_plls,
+	       "st,clkgena-plls-c65", clkgena_c65_pll_setup);
+
+static struct clk * __init clkgen_odf_register(const char *parent_name,
+					       void * __iomem reg,
+					       struct clkgen_pll_data *pll_data,
+					       int odf,
+					       spinlock_t *odf_lock,
+					       const char *odf_name)
+{
+	struct clk *clk;
+	unsigned long flags;
+	struct clk_gate *gate;
+	struct clk_divider *div;
+
+	flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_GATE;
+
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+	if (!gate)
+		return ERR_PTR(-ENOMEM);
+
+	gate->flags = CLK_GATE_SET_TO_DISABLE;
+	gate->reg = reg + pll_data->odf_gate[odf].offset;
+	gate->bit_idx = pll_data->odf_gate[odf].shift;
+	gate->lock = odf_lock;
+
+	div = kzalloc(sizeof(*div), GFP_KERNEL);
+	if (!div)
+		return ERR_PTR(-ENOMEM);
+
+	div->flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;
+	div->reg = reg + pll_data->odf[odf].offset;
+	div->shift = pll_data->odf[odf].shift;
+	div->width = fls(pll_data->odf[odf].mask);
+	div->lock = odf_lock;
+
+	clk = clk_register_composite(NULL, odf_name, &parent_name, 1,
+				     NULL, NULL,
+				     &div->hw, &clk_divider_ops,
+				     &gate->hw, &clk_gate_ops,
+				     flags);
+	if (IS_ERR(clk))
+		return clk;
+
+	pr_debug("%s: parent %s rate %lu\n",
+			__clk_get_name(clk),
+			__clk_get_name(clk_get_parent(clk)),
+			clk_get_rate(clk));
+	return clk;
+}
+
+static struct of_device_id c32_pll_of_match[] = {
+	{
+		.compatible = "st,plls-c32-a1x-0",
+		.data = &st_pll3200c32_a1x_0,
+	},
+	{
+		.compatible = "st,plls-c32-a1x-1",
+		.data = &st_pll3200c32_a1x_1,
+	},
+	{}
+};
+
+static void __init clkgen_c32_pll_setup(struct device_node *np)
+{
+	const struct of_device_id *match;
+	struct clk *clk;
+	const char *parent_name, *pll_name;
+	void __iomem *pll_base;
+	int num_odfs, odf;
+	struct clk_onecell_data *clk_data;
+	struct clkgen_pll_data	*data;
+
+	match = of_match_node(c32_pll_of_match, np);
+	if (!match) {
+		pr_err("%s: No matching data\n", __func__);
+		return;
+	}
+
+	data = (struct clkgen_pll_data *) match->data;
+
+	parent_name = of_clk_get_parent_name(np, 0);
+	if (!parent_name)
+		return;
+
+	pll_base = clkgen_get_register_base(np);
+	if (!pll_base)
+		return;
+
+	clk = clkgen_pll_register(parent_name, data, pll_base, np->name);
+	if (IS_ERR(clk))
+		return;
+
+	pll_name = __clk_get_name(clk);
+
+	num_odfs = data->num_odfs;
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return;
+
+	clk_data->clk_num = num_odfs;
+	clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *),
+				 GFP_KERNEL);
+
+	if (!clk_data->clks)
+		goto err;
+
+	for (odf = 0; odf < num_odfs; odf++) {
+		struct clk *clk;
+		const char *clk_name;
+
+		if (of_property_read_string_index(np, "clock-output-names",
+						  odf, &clk_name))
+			return;
+
+		clk = clkgen_odf_register(pll_name, pll_base, data,
+				odf, &clkgena_c32_odf_lock, clk_name);
+		if (IS_ERR(clk))
+			goto err;
+
+		clk_data->clks[odf] = clk;
+	}
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+	return;
+
+err:
+	kfree(pll_name);
+	kfree(clk_data->clks);
+	kfree(clk_data);
+}
+CLK_OF_DECLARE(clkgen_c32_pll, "st,clkgen-plls-c32", clkgen_c32_pll_setup);
diff --git a/drivers/clk/st/clkgen.h b/drivers/clk/st/clkgen.h
new file mode 100644
index 0000000..35c8632
--- /dev/null
+++ b/drivers/clk/st/clkgen.h
@@ -0,0 +1,48 @@
+/************************************************************************
+File  : Clock H/w specific Information
+
+Author: Pankaj Dev <pankaj.dev@st.com>
+
+Copyright (C) 2014 STMicroelectronics
+************************************************************************/
+
+#ifndef __CLKGEN_INFO_H
+#define __CLKGEN_INFO_H
+
+struct clkgen_field {
+	unsigned int offset;
+	unsigned int mask;
+	unsigned int shift;
+};
+
+static inline unsigned long clkgen_read(void __iomem	*base,
+					  struct clkgen_field *field)
+{
+	return (readl(base + field->offset) >> field->shift) & field->mask;
+}
+
+
+static inline void clkgen_write(void __iomem *base, struct clkgen_field *field,
+				  unsigned long val)
+{
+	writel((readl(base + field->offset) &
+	       ~(field->mask << field->shift)) | (val << field->shift),
+	       base + field->offset);
+
+	return;
+}
+
+#define CLKGEN_FIELD(_offset, _mask, _shift) {		\
+				.offset	= _offset,	\
+				.mask	= _mask,	\
+				.shift	= _shift,	\
+				}
+
+#define CLKGEN_READ(pll, field) clkgen_read(pll->regs_base, \
+		&pll->data->field)
+
+#define CLKGEN_WRITE(pll, field, val) clkgen_write(pll->regs_base, \
+		&pll->data->field, val)
+
+#endif /*__CLKGEN_INFO_H*/
+
-- 
1.9.0

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

* [PATCH v0 03/15] drivers: clk: st: Support for VCC-mux and MUX clocks
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: mturquette, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, rob, linux, devicetree, linux-doc, linux-kernel,
	linux-arm-kernel
  Cc: Lee Jones, Gabriel Fernandez, Pankaj Dev

The patch supports the VCC-mux and MUX clocks used by ClockGenC/F

VCC-mux clock : Divider-Multiplexer-Gate inside ClockGenC/F
It includes support for each channel : 4-parent Multiplexer, Post Divide
by 1, 2, 4 or 8, Gate to switch OFF the output channel. The clock is
implemented using generic clocks implemented in the kernel clk_divider, clk_mux,
clk_gate and clk_composite (to combine all)

MUX clock : 2-parent clock used inside ClockGenC/F. The clock is implemented
using generic clocks implemented in the kernel clk_mux.

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 drivers/clk/st/clkgen-mux.c | 272 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 272 insertions(+)

diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c
index 65d702c..7ccff62 100644
--- a/drivers/clk/st/clkgen-mux.c
+++ b/drivers/clk/st/clkgen-mux.c
@@ -18,6 +18,7 @@
 #include <linux/clk-provider.h>
 
 static DEFINE_SPINLOCK(clkgena_divmux_lock);
+static DEFINE_SPINLOCK(clkgenf_lock);
 
 static const char ** __init clkgen_mux_get_parents(struct device_node *np,
 						       int *num_parents)
@@ -527,3 +528,274 @@ void __init st_of_clkgena_prediv_setup(struct device_node *np)
 	return;
 }
 CLK_OF_DECLARE(clkgenaprediv, "st,clkgena-prediv", st_of_clkgena_prediv_setup);
+
+struct clkgen_mux_data {
+	u32 offset;
+	u8 shift;
+	u8 width;
+	spinlock_t *lock;
+	unsigned long clk_flags;
+	u8 mux_flags;
+};
+
+static struct clkgen_mux_data clkgen_mux_c_vcc_hd_416 = {
+	.offset = 0,
+	.shift = 0,
+	.width = 1,
+};
+
+static struct clkgen_mux_data clkgen_mux_f_vcc_fvdp_416 = {
+	.offset = 0,
+	.shift = 0,
+	.width = 1,
+};
+
+static struct clkgen_mux_data clkgen_mux_f_vcc_hva_416 = {
+	.offset = 0,
+	.shift = 0,
+	.width = 1,
+};
+
+static struct clkgen_mux_data clkgen_mux_f_vcc_hd_416 = {
+	.offset = 0,
+	.shift = 16,
+	.width = 1,
+	.lock = &clkgenf_lock,
+};
+
+static struct clkgen_mux_data clkgen_mux_c_vcc_sd_416 = {
+	.offset = 0,
+	.shift = 17,
+	.width = 1,
+	.lock = &clkgenf_lock,
+};
+
+static struct of_device_id mux_of_match[] = {
+	{
+		.compatible = "st,stih416-clkgenc-vcc-hd",
+		.data = &clkgen_mux_c_vcc_hd_416,
+	},
+	{
+		.compatible = "st,stih416-clkgenf-vcc-fvdp",
+		.data = &clkgen_mux_f_vcc_fvdp_416,
+	},
+	{
+		.compatible = "st,stih416-clkgenf-vcc-hva",
+		.data = &clkgen_mux_f_vcc_hva_416,
+	},
+	{
+		.compatible = "st,stih416-clkgenf-vcc-hd",
+		.data = &clkgen_mux_f_vcc_hd_416,
+	},
+	{
+		.compatible = "st,stih416-clkgenf-vcc-sd",
+		.data = &clkgen_mux_c_vcc_sd_416,
+	},
+	{}
+};
+
+void __init st_of_clkgen_mux_setup(struct device_node *np)
+{
+	const struct of_device_id *match;
+	struct clk *clk;
+	void __iomem *reg;
+	const char **parents;
+	int num_parents;
+	struct clkgen_mux_data *data;
+
+	match = of_match_node(mux_of_match, np);
+	if (!match) {
+		pr_err("%s: No matching data\n", __func__);
+		return;
+	}
+
+	data = (struct clkgen_mux_data *)match->data;
+
+	reg = of_iomap(np, 0);
+	if (!reg) {
+		pr_err("%s: Failed to get base address\n", __func__);
+		return;
+	}
+
+	parents = clkgen_mux_get_parents(np, &num_parents);
+	if (IS_ERR(parents)) {
+		pr_err("%s: Failed to get parents (%ld)\n",
+				__func__, PTR_ERR(parents));
+		return;
+	}
+
+	clk = clk_register_mux(NULL, np->name, parents, num_parents,
+				data->clk_flags | CLK_SET_RATE_PARENT,
+				reg + data->offset,
+				data->shift, data->width, data->mux_flags,
+				data->lock);
+	if (IS_ERR(clk))
+		goto err;
+
+	pr_debug("%s: parent %s rate %u\n",
+			__clk_get_name(clk),
+			__clk_get_name(clk_get_parent(clk)),
+			(unsigned int)clk_get_rate(clk));
+
+	of_clk_add_provider(np, of_clk_src_simple_get, clk);
+
+err:
+	kfree(parents);
+
+	return;
+}
+CLK_OF_DECLARE(clkgen_mux, "st,clkgen-mux", st_of_clkgen_mux_setup);
+
+#define VCC_MAX_CHANNELS 16
+
+#define VCC_GATE_OFFSET 0x0
+#define VCC_MUX_OFFSET 0x4
+#define VCC_DIV_OFFSET 0x8
+
+struct clkgen_vcc_data {
+	spinlock_t *lock;
+	unsigned long clk_flags;
+};
+
+static struct clkgen_vcc_data st_clkgenc_vcc_416 = {
+	.clk_flags = CLK_SET_RATE_PARENT,
+};
+
+static struct clkgen_vcc_data st_clkgenf_vcc_416 = {
+	.lock = &clkgenf_lock,
+};
+
+static struct of_device_id vcc_of_match[] = {
+	{ .compatible = "st,stih416-clkgenc", .data = &st_clkgenc_vcc_416 },
+	{ .compatible = "st,stih416-clkgenf", .data = &st_clkgenf_vcc_416 },
+	{}
+};
+
+void __init st_of_clkgen_vcc_setup(struct device_node *np)
+{
+	const struct of_device_id *match;
+	void __iomem *reg;
+	const char **parents;
+	int num_parents, i;
+	struct clk_onecell_data *clk_data;
+	struct clkgen_vcc_data *data;
+
+	match = of_match_node(vcc_of_match, np);
+	if (WARN_ON(!match))
+		return;
+	data = (struct clkgen_vcc_data *)match->data;
+
+	reg = of_iomap(np, 0);
+	if (!reg)
+		return;
+
+	parents = clkgen_mux_get_parents(np, &num_parents);
+	if (IS_ERR(parents))
+		return;
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		goto err;
+
+	clk_data->clk_num = VCC_MAX_CHANNELS;
+	clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *),
+				 GFP_KERNEL);
+
+	if (!clk_data->clks)
+		goto err;
+
+	for (i = 0; i < clk_data->clk_num; i++) {
+		struct clk *clk;
+		const char *clk_name;
+		struct clk_gate *gate;
+		struct clk_divider *div;
+		struct clk_mux *mux;
+
+		if (of_property_read_string_index(np, "clock-output-names",
+						  i, &clk_name))
+			break;
+
+		/*
+		 * If we read an empty clock name then the output is unused
+		 */
+		if (*clk_name == '\0')
+			continue;
+
+		gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+		if (!gate)
+			break;
+
+		div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
+		if (!div) {
+			kfree(gate);
+			break;
+		}
+
+		mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
+		if (!mux) {
+			kfree(gate);
+			kfree(div);
+			break;
+		}
+
+		gate->reg = reg + VCC_GATE_OFFSET;
+		gate->bit_idx = i;
+		gate->flags = CLK_GATE_SET_TO_DISABLE;
+		gate->lock = data->lock;
+
+		div->reg = reg + VCC_DIV_OFFSET;
+		div->shift = 2 * i;
+		div->width = 2;
+		div->flags = CLK_DIVIDER_POWER_OF_TWO;
+
+		mux->reg = reg + VCC_MUX_OFFSET;
+		mux->shift = 2 * i;
+		mux->mask = 0x3;
+
+		clk = clk_register_composite(NULL, clk_name, parents,
+					     num_parents,
+					     &mux->hw, &clk_mux_ops,
+					     &div->hw, &clk_divider_ops,
+					     &gate->hw, &clk_gate_ops,
+					     data->clk_flags);
+		if (IS_ERR(clk)) {
+			kfree(gate);
+			kfree(div);
+			kfree(mux);
+			goto err;
+		}
+
+		pr_debug("%s: parent %s rate %u\n",
+			__clk_get_name(clk),
+			__clk_get_name(clk_get_parent(clk)),
+			(unsigned int)clk_get_rate(clk));
+
+		clk_data->clks[i] = clk;
+	}
+
+	kfree(parents);
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+	return;
+
+err:
+	for (i = 0; i < clk_data->clk_num; i++) {
+		struct clk_composite *composite;
+
+		if (!clk_data->clks[i])
+			continue;
+
+		composite = container_of(__clk_get_hw(clk_data->clks[i]),
+					 struct clk_composite, hw);
+		kfree(container_of(composite->gate_hw, struct clk_gate, hw));
+		kfree(container_of(composite->rate_hw, struct clk_divider, hw));
+		kfree(container_of(composite->mux_hw, struct clk_mux, hw));
+	}
+
+	if (clk_data)
+		kfree(clk_data->clks);
+
+	kfree(clk_data);
+	kfree(parents);
+}
+CLK_OF_DECLARE(clkgen_vcc, "st,clkgen-vcc", st_of_clkgen_vcc_setup);
-- 
1.9.0


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

* [PATCH v0 03/15] drivers: clk: st: Support for VCC-mux and MUX clocks
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: mturquette-QSEj5FYQhm4dnm+yROfE0A,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, pawel.moll-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, rob-VoJi6FS/r0vR7s880joybQ,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Lee Jones, Gabriel Fernandez, Pankaj Dev

The patch supports the VCC-mux and MUX clocks used by ClockGenC/F

VCC-mux clock : Divider-Multiplexer-Gate inside ClockGenC/F
It includes support for each channel : 4-parent Multiplexer, Post Divide
by 1, 2, 4 or 8, Gate to switch OFF the output channel. The clock is
implemented using generic clocks implemented in the kernel clk_divider, clk_mux,
clk_gate and clk_composite (to combine all)

MUX clock : 2-parent clock used inside ClockGenC/F. The clock is implemented
using generic clocks implemented in the kernel clk_mux.

Signed-off-by: Pankaj Dev <pankaj.dev-qxv4g6HH51o@public.gmane.org>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez-qxv4g6HH51o@public.gmane.org>
---
 drivers/clk/st/clkgen-mux.c | 272 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 272 insertions(+)

diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c
index 65d702c..7ccff62 100644
--- a/drivers/clk/st/clkgen-mux.c
+++ b/drivers/clk/st/clkgen-mux.c
@@ -18,6 +18,7 @@
 #include <linux/clk-provider.h>
 
 static DEFINE_SPINLOCK(clkgena_divmux_lock);
+static DEFINE_SPINLOCK(clkgenf_lock);
 
 static const char ** __init clkgen_mux_get_parents(struct device_node *np,
 						       int *num_parents)
@@ -527,3 +528,274 @@ void __init st_of_clkgena_prediv_setup(struct device_node *np)
 	return;
 }
 CLK_OF_DECLARE(clkgenaprediv, "st,clkgena-prediv", st_of_clkgena_prediv_setup);
+
+struct clkgen_mux_data {
+	u32 offset;
+	u8 shift;
+	u8 width;
+	spinlock_t *lock;
+	unsigned long clk_flags;
+	u8 mux_flags;
+};
+
+static struct clkgen_mux_data clkgen_mux_c_vcc_hd_416 = {
+	.offset = 0,
+	.shift = 0,
+	.width = 1,
+};
+
+static struct clkgen_mux_data clkgen_mux_f_vcc_fvdp_416 = {
+	.offset = 0,
+	.shift = 0,
+	.width = 1,
+};
+
+static struct clkgen_mux_data clkgen_mux_f_vcc_hva_416 = {
+	.offset = 0,
+	.shift = 0,
+	.width = 1,
+};
+
+static struct clkgen_mux_data clkgen_mux_f_vcc_hd_416 = {
+	.offset = 0,
+	.shift = 16,
+	.width = 1,
+	.lock = &clkgenf_lock,
+};
+
+static struct clkgen_mux_data clkgen_mux_c_vcc_sd_416 = {
+	.offset = 0,
+	.shift = 17,
+	.width = 1,
+	.lock = &clkgenf_lock,
+};
+
+static struct of_device_id mux_of_match[] = {
+	{
+		.compatible = "st,stih416-clkgenc-vcc-hd",
+		.data = &clkgen_mux_c_vcc_hd_416,
+	},
+	{
+		.compatible = "st,stih416-clkgenf-vcc-fvdp",
+		.data = &clkgen_mux_f_vcc_fvdp_416,
+	},
+	{
+		.compatible = "st,stih416-clkgenf-vcc-hva",
+		.data = &clkgen_mux_f_vcc_hva_416,
+	},
+	{
+		.compatible = "st,stih416-clkgenf-vcc-hd",
+		.data = &clkgen_mux_f_vcc_hd_416,
+	},
+	{
+		.compatible = "st,stih416-clkgenf-vcc-sd",
+		.data = &clkgen_mux_c_vcc_sd_416,
+	},
+	{}
+};
+
+void __init st_of_clkgen_mux_setup(struct device_node *np)
+{
+	const struct of_device_id *match;
+	struct clk *clk;
+	void __iomem *reg;
+	const char **parents;
+	int num_parents;
+	struct clkgen_mux_data *data;
+
+	match = of_match_node(mux_of_match, np);
+	if (!match) {
+		pr_err("%s: No matching data\n", __func__);
+		return;
+	}
+
+	data = (struct clkgen_mux_data *)match->data;
+
+	reg = of_iomap(np, 0);
+	if (!reg) {
+		pr_err("%s: Failed to get base address\n", __func__);
+		return;
+	}
+
+	parents = clkgen_mux_get_parents(np, &num_parents);
+	if (IS_ERR(parents)) {
+		pr_err("%s: Failed to get parents (%ld)\n",
+				__func__, PTR_ERR(parents));
+		return;
+	}
+
+	clk = clk_register_mux(NULL, np->name, parents, num_parents,
+				data->clk_flags | CLK_SET_RATE_PARENT,
+				reg + data->offset,
+				data->shift, data->width, data->mux_flags,
+				data->lock);
+	if (IS_ERR(clk))
+		goto err;
+
+	pr_debug("%s: parent %s rate %u\n",
+			__clk_get_name(clk),
+			__clk_get_name(clk_get_parent(clk)),
+			(unsigned int)clk_get_rate(clk));
+
+	of_clk_add_provider(np, of_clk_src_simple_get, clk);
+
+err:
+	kfree(parents);
+
+	return;
+}
+CLK_OF_DECLARE(clkgen_mux, "st,clkgen-mux", st_of_clkgen_mux_setup);
+
+#define VCC_MAX_CHANNELS 16
+
+#define VCC_GATE_OFFSET 0x0
+#define VCC_MUX_OFFSET 0x4
+#define VCC_DIV_OFFSET 0x8
+
+struct clkgen_vcc_data {
+	spinlock_t *lock;
+	unsigned long clk_flags;
+};
+
+static struct clkgen_vcc_data st_clkgenc_vcc_416 = {
+	.clk_flags = CLK_SET_RATE_PARENT,
+};
+
+static struct clkgen_vcc_data st_clkgenf_vcc_416 = {
+	.lock = &clkgenf_lock,
+};
+
+static struct of_device_id vcc_of_match[] = {
+	{ .compatible = "st,stih416-clkgenc", .data = &st_clkgenc_vcc_416 },
+	{ .compatible = "st,stih416-clkgenf", .data = &st_clkgenf_vcc_416 },
+	{}
+};
+
+void __init st_of_clkgen_vcc_setup(struct device_node *np)
+{
+	const struct of_device_id *match;
+	void __iomem *reg;
+	const char **parents;
+	int num_parents, i;
+	struct clk_onecell_data *clk_data;
+	struct clkgen_vcc_data *data;
+
+	match = of_match_node(vcc_of_match, np);
+	if (WARN_ON(!match))
+		return;
+	data = (struct clkgen_vcc_data *)match->data;
+
+	reg = of_iomap(np, 0);
+	if (!reg)
+		return;
+
+	parents = clkgen_mux_get_parents(np, &num_parents);
+	if (IS_ERR(parents))
+		return;
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		goto err;
+
+	clk_data->clk_num = VCC_MAX_CHANNELS;
+	clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *),
+				 GFP_KERNEL);
+
+	if (!clk_data->clks)
+		goto err;
+
+	for (i = 0; i < clk_data->clk_num; i++) {
+		struct clk *clk;
+		const char *clk_name;
+		struct clk_gate *gate;
+		struct clk_divider *div;
+		struct clk_mux *mux;
+
+		if (of_property_read_string_index(np, "clock-output-names",
+						  i, &clk_name))
+			break;
+
+		/*
+		 * If we read an empty clock name then the output is unused
+		 */
+		if (*clk_name == '\0')
+			continue;
+
+		gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+		if (!gate)
+			break;
+
+		div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
+		if (!div) {
+			kfree(gate);
+			break;
+		}
+
+		mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
+		if (!mux) {
+			kfree(gate);
+			kfree(div);
+			break;
+		}
+
+		gate->reg = reg + VCC_GATE_OFFSET;
+		gate->bit_idx = i;
+		gate->flags = CLK_GATE_SET_TO_DISABLE;
+		gate->lock = data->lock;
+
+		div->reg = reg + VCC_DIV_OFFSET;
+		div->shift = 2 * i;
+		div->width = 2;
+		div->flags = CLK_DIVIDER_POWER_OF_TWO;
+
+		mux->reg = reg + VCC_MUX_OFFSET;
+		mux->shift = 2 * i;
+		mux->mask = 0x3;
+
+		clk = clk_register_composite(NULL, clk_name, parents,
+					     num_parents,
+					     &mux->hw, &clk_mux_ops,
+					     &div->hw, &clk_divider_ops,
+					     &gate->hw, &clk_gate_ops,
+					     data->clk_flags);
+		if (IS_ERR(clk)) {
+			kfree(gate);
+			kfree(div);
+			kfree(mux);
+			goto err;
+		}
+
+		pr_debug("%s: parent %s rate %u\n",
+			__clk_get_name(clk),
+			__clk_get_name(clk_get_parent(clk)),
+			(unsigned int)clk_get_rate(clk));
+
+		clk_data->clks[i] = clk;
+	}
+
+	kfree(parents);
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+	return;
+
+err:
+	for (i = 0; i < clk_data->clk_num; i++) {
+		struct clk_composite *composite;
+
+		if (!clk_data->clks[i])
+			continue;
+
+		composite = container_of(__clk_get_hw(clk_data->clks[i]),
+					 struct clk_composite, hw);
+		kfree(container_of(composite->gate_hw, struct clk_gate, hw));
+		kfree(container_of(composite->rate_hw, struct clk_divider, hw));
+		kfree(container_of(composite->mux_hw, struct clk_mux, hw));
+	}
+
+	if (clk_data)
+		kfree(clk_data->clks);
+
+	kfree(clk_data);
+	kfree(parents);
+}
+CLK_OF_DECLARE(clkgen_vcc, "st,clkgen-vcc", st_of_clkgen_vcc_setup);
-- 
1.9.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v0 03/15] drivers: clk: st: Support for VCC-mux and MUX clocks
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

The patch supports the VCC-mux and MUX clocks used by ClockGenC/F

VCC-mux clock : Divider-Multiplexer-Gate inside ClockGenC/F
It includes support for each channel : 4-parent Multiplexer, Post Divide
by 1, 2, 4 or 8, Gate to switch OFF the output channel. The clock is
implemented using generic clocks implemented in the kernel clk_divider, clk_mux,
clk_gate and clk_composite (to combine all)

MUX clock : 2-parent clock used inside ClockGenC/F. The clock is implemented
using generic clocks implemented in the kernel clk_mux.

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 drivers/clk/st/clkgen-mux.c | 272 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 272 insertions(+)

diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c
index 65d702c..7ccff62 100644
--- a/drivers/clk/st/clkgen-mux.c
+++ b/drivers/clk/st/clkgen-mux.c
@@ -18,6 +18,7 @@
 #include <linux/clk-provider.h>
 
 static DEFINE_SPINLOCK(clkgena_divmux_lock);
+static DEFINE_SPINLOCK(clkgenf_lock);
 
 static const char ** __init clkgen_mux_get_parents(struct device_node *np,
 						       int *num_parents)
@@ -527,3 +528,274 @@ void __init st_of_clkgena_prediv_setup(struct device_node *np)
 	return;
 }
 CLK_OF_DECLARE(clkgenaprediv, "st,clkgena-prediv", st_of_clkgena_prediv_setup);
+
+struct clkgen_mux_data {
+	u32 offset;
+	u8 shift;
+	u8 width;
+	spinlock_t *lock;
+	unsigned long clk_flags;
+	u8 mux_flags;
+};
+
+static struct clkgen_mux_data clkgen_mux_c_vcc_hd_416 = {
+	.offset = 0,
+	.shift = 0,
+	.width = 1,
+};
+
+static struct clkgen_mux_data clkgen_mux_f_vcc_fvdp_416 = {
+	.offset = 0,
+	.shift = 0,
+	.width = 1,
+};
+
+static struct clkgen_mux_data clkgen_mux_f_vcc_hva_416 = {
+	.offset = 0,
+	.shift = 0,
+	.width = 1,
+};
+
+static struct clkgen_mux_data clkgen_mux_f_vcc_hd_416 = {
+	.offset = 0,
+	.shift = 16,
+	.width = 1,
+	.lock = &clkgenf_lock,
+};
+
+static struct clkgen_mux_data clkgen_mux_c_vcc_sd_416 = {
+	.offset = 0,
+	.shift = 17,
+	.width = 1,
+	.lock = &clkgenf_lock,
+};
+
+static struct of_device_id mux_of_match[] = {
+	{
+		.compatible = "st,stih416-clkgenc-vcc-hd",
+		.data = &clkgen_mux_c_vcc_hd_416,
+	},
+	{
+		.compatible = "st,stih416-clkgenf-vcc-fvdp",
+		.data = &clkgen_mux_f_vcc_fvdp_416,
+	},
+	{
+		.compatible = "st,stih416-clkgenf-vcc-hva",
+		.data = &clkgen_mux_f_vcc_hva_416,
+	},
+	{
+		.compatible = "st,stih416-clkgenf-vcc-hd",
+		.data = &clkgen_mux_f_vcc_hd_416,
+	},
+	{
+		.compatible = "st,stih416-clkgenf-vcc-sd",
+		.data = &clkgen_mux_c_vcc_sd_416,
+	},
+	{}
+};
+
+void __init st_of_clkgen_mux_setup(struct device_node *np)
+{
+	const struct of_device_id *match;
+	struct clk *clk;
+	void __iomem *reg;
+	const char **parents;
+	int num_parents;
+	struct clkgen_mux_data *data;
+
+	match = of_match_node(mux_of_match, np);
+	if (!match) {
+		pr_err("%s: No matching data\n", __func__);
+		return;
+	}
+
+	data = (struct clkgen_mux_data *)match->data;
+
+	reg = of_iomap(np, 0);
+	if (!reg) {
+		pr_err("%s: Failed to get base address\n", __func__);
+		return;
+	}
+
+	parents = clkgen_mux_get_parents(np, &num_parents);
+	if (IS_ERR(parents)) {
+		pr_err("%s: Failed to get parents (%ld)\n",
+				__func__, PTR_ERR(parents));
+		return;
+	}
+
+	clk = clk_register_mux(NULL, np->name, parents, num_parents,
+				data->clk_flags | CLK_SET_RATE_PARENT,
+				reg + data->offset,
+				data->shift, data->width, data->mux_flags,
+				data->lock);
+	if (IS_ERR(clk))
+		goto err;
+
+	pr_debug("%s: parent %s rate %u\n",
+			__clk_get_name(clk),
+			__clk_get_name(clk_get_parent(clk)),
+			(unsigned int)clk_get_rate(clk));
+
+	of_clk_add_provider(np, of_clk_src_simple_get, clk);
+
+err:
+	kfree(parents);
+
+	return;
+}
+CLK_OF_DECLARE(clkgen_mux, "st,clkgen-mux", st_of_clkgen_mux_setup);
+
+#define VCC_MAX_CHANNELS 16
+
+#define VCC_GATE_OFFSET 0x0
+#define VCC_MUX_OFFSET 0x4
+#define VCC_DIV_OFFSET 0x8
+
+struct clkgen_vcc_data {
+	spinlock_t *lock;
+	unsigned long clk_flags;
+};
+
+static struct clkgen_vcc_data st_clkgenc_vcc_416 = {
+	.clk_flags = CLK_SET_RATE_PARENT,
+};
+
+static struct clkgen_vcc_data st_clkgenf_vcc_416 = {
+	.lock = &clkgenf_lock,
+};
+
+static struct of_device_id vcc_of_match[] = {
+	{ .compatible = "st,stih416-clkgenc", .data = &st_clkgenc_vcc_416 },
+	{ .compatible = "st,stih416-clkgenf", .data = &st_clkgenf_vcc_416 },
+	{}
+};
+
+void __init st_of_clkgen_vcc_setup(struct device_node *np)
+{
+	const struct of_device_id *match;
+	void __iomem *reg;
+	const char **parents;
+	int num_parents, i;
+	struct clk_onecell_data *clk_data;
+	struct clkgen_vcc_data *data;
+
+	match = of_match_node(vcc_of_match, np);
+	if (WARN_ON(!match))
+		return;
+	data = (struct clkgen_vcc_data *)match->data;
+
+	reg = of_iomap(np, 0);
+	if (!reg)
+		return;
+
+	parents = clkgen_mux_get_parents(np, &num_parents);
+	if (IS_ERR(parents))
+		return;
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		goto err;
+
+	clk_data->clk_num = VCC_MAX_CHANNELS;
+	clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *),
+				 GFP_KERNEL);
+
+	if (!clk_data->clks)
+		goto err;
+
+	for (i = 0; i < clk_data->clk_num; i++) {
+		struct clk *clk;
+		const char *clk_name;
+		struct clk_gate *gate;
+		struct clk_divider *div;
+		struct clk_mux *mux;
+
+		if (of_property_read_string_index(np, "clock-output-names",
+						  i, &clk_name))
+			break;
+
+		/*
+		 * If we read an empty clock name then the output is unused
+		 */
+		if (*clk_name == '\0')
+			continue;
+
+		gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+		if (!gate)
+			break;
+
+		div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
+		if (!div) {
+			kfree(gate);
+			break;
+		}
+
+		mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
+		if (!mux) {
+			kfree(gate);
+			kfree(div);
+			break;
+		}
+
+		gate->reg = reg + VCC_GATE_OFFSET;
+		gate->bit_idx = i;
+		gate->flags = CLK_GATE_SET_TO_DISABLE;
+		gate->lock = data->lock;
+
+		div->reg = reg + VCC_DIV_OFFSET;
+		div->shift = 2 * i;
+		div->width = 2;
+		div->flags = CLK_DIVIDER_POWER_OF_TWO;
+
+		mux->reg = reg + VCC_MUX_OFFSET;
+		mux->shift = 2 * i;
+		mux->mask = 0x3;
+
+		clk = clk_register_composite(NULL, clk_name, parents,
+					     num_parents,
+					     &mux->hw, &clk_mux_ops,
+					     &div->hw, &clk_divider_ops,
+					     &gate->hw, &clk_gate_ops,
+					     data->clk_flags);
+		if (IS_ERR(clk)) {
+			kfree(gate);
+			kfree(div);
+			kfree(mux);
+			goto err;
+		}
+
+		pr_debug("%s: parent %s rate %u\n",
+			__clk_get_name(clk),
+			__clk_get_name(clk_get_parent(clk)),
+			(unsigned int)clk_get_rate(clk));
+
+		clk_data->clks[i] = clk;
+	}
+
+	kfree(parents);
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+	return;
+
+err:
+	for (i = 0; i < clk_data->clk_num; i++) {
+		struct clk_composite *composite;
+
+		if (!clk_data->clks[i])
+			continue;
+
+		composite = container_of(__clk_get_hw(clk_data->clks[i]),
+					 struct clk_composite, hw);
+		kfree(container_of(composite->gate_hw, struct clk_gate, hw));
+		kfree(container_of(composite->rate_hw, struct clk_divider, hw));
+		kfree(container_of(composite->mux_hw, struct clk_mux, hw));
+	}
+
+	if (clk_data)
+		kfree(clk_data->clks);
+
+	kfree(clk_data);
+	kfree(parents);
+}
+CLK_OF_DECLARE(clkgen_vcc, "st,clkgen-vcc", st_of_clkgen_vcc_setup);
-- 
1.9.0

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

* [PATCH v0 04/15] drivers: clk: st: Support for QUADFS inside ClockGenB/C/D/E/F
  2014-02-27 15:24 ` Gabriel FERNANDEZ
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  -1 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: mturquette, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, rob, linux, devicetree, linux-doc, linux-kernel,
	linux-arm-kernel
  Cc: Lee Jones, Gabriel Fernandez, Pankaj Dev

The patch supports the 216/432/660 type Quad Frequency Synthesizers
used by ClockGenB/C/D/E/F

QUADFS clock : It includes support for all 216/432/660 type Quad
Frequency Synthesizers : implemented as Fixed Parent / Rate / Gate clock,
with clock rate calculated reading H/w settings done at BOOT.

QuadFS have 4 outputs : chan0 chan1 chan2 chan3

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 drivers/clk/st/Makefile      |    2 +-
 drivers/clk/st/clkgen-fsyn.c | 1039 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1040 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/st/clkgen-fsyn.c

diff --git a/drivers/clk/st/Makefile b/drivers/clk/st/Makefile
index b7b10f9..c7455ff 100644
--- a/drivers/clk/st/Makefile
+++ b/drivers/clk/st/Makefile
@@ -1 +1 @@
-obj-y += clkgen-mux.o clkgen-pll.o
+obj-y += clkgen-mux.o clkgen-pll.o clkgen-fsyn.o
diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c
new file mode 100644
index 0000000..4f53ee0
--- /dev/null
+++ b/drivers/clk/st/clkgen-fsyn.c
@@ -0,0 +1,1039 @@
+/*
+ * Copyright (C) 2014 STMicroelectronics R&D Ltd
+ *
+ * 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.
+ *
+ */
+
+/*
+ * Authors:
+ * Stephen Gallimore <stephen.gallimore@st.com>,
+ * Pankaj Dev <pankaj.dev@st.com>.
+ */
+
+#include <linux/slab.h>
+#include <linux/of_address.h>
+#include <linux/clk-provider.h>
+
+#include "clkgen.h"
+
+/*
+ * Maximum input clock to the PLL before we divide it down by 2
+ * although in reality in actual systems this has never been seen to
+ * be used.
+ */
+#define QUADFS_NDIV_THRESHOLD 30000000
+
+#define PLL_BW_GOODREF   (0L)
+#define PLL_BW_VBADREF   (1L)
+#define PLL_BW_BADREF    (2L)
+#define PLL_BW_VGOODREF  (3L)
+
+#define QUADFS_MAX_CHAN 4
+
+struct stm_fs {
+	unsigned long ndiv;
+	unsigned long mdiv;
+	unsigned long pe;
+	unsigned long sdiv;
+	unsigned long nsdiv;
+};
+
+static struct stm_fs fs216c65_rtbl[] = {
+	{ .mdiv = 0x1f, .pe = 0x0,	.sdiv = 0x7,	.nsdiv = 0 },	/* 312.5 Khz */
+	{ .mdiv = 0x17, .pe = 0x25ed,	.sdiv = 0x1,	.nsdiv = 0 },	/* 27    MHz */
+	{ .mdiv = 0x1a, .pe = 0x7b36,	.sdiv = 0x2,	.nsdiv = 1 },	/* 36.87 MHz */
+	{ .mdiv = 0x13, .pe = 0x0,	.sdiv = 0x2,	.nsdiv = 1 },	/* 48    MHz */
+	{ .mdiv = 0x11, .pe = 0x1c72,	.sdiv = 0x1,	.nsdiv = 1 },	/* 108   MHz */
+};
+
+static struct stm_fs fs432c65_rtbl[] = {
+	{ .mdiv = 0x1f, .pe = 0x0,	.sdiv = 0x7,	.nsdiv = 0 },	/* 625   Khz */
+	{ .mdiv = 0x11, .pe = 0x1c72,	.sdiv = 0x2,	.nsdiv = 1 },	/* 108   MHz */
+	{ .mdiv = 0x19, .pe = 0x121a,	.sdiv = 0x0,	.nsdiv = 1 },	/* 297   MHz */
+};
+
+static struct stm_fs fs660c32_rtbl[] = {
+	{ .mdiv = 0x01, .pe = 0x2aaa,	.sdiv = 0x8,	.nsdiv = 0 },	/* 600   KHz */
+	{ .mdiv = 0x02, .pe = 0x3d33,	.sdiv = 0x0,	.nsdiv = 0 },	/* 148.5 Mhz */
+	{ .mdiv = 0x13, .pe = 0x5bcc,	.sdiv = 0x0,	.nsdiv = 1 },	/* 297   Mhz */
+	{ .mdiv = 0x0e, .pe = 0x1025,	.sdiv = 0x0,	.nsdiv = 1 },	/* 333   Mhz */
+	{ .mdiv = 0x0b, .pe = 0x715f,	.sdiv = 0x0,	.nsdiv = 1 },	/* 350   Mhz */
+};
+
+struct clkgen_quadfs_data {
+	bool reset_present;
+	bool bwfilter_present;
+	bool lockstatus_present;
+	bool nsdiv_present;
+	struct clkgen_field ndiv;
+	struct clkgen_field ref_bw;
+	struct clkgen_field nreset;
+	struct clkgen_field npda;
+	struct clkgen_field lock_status;
+
+	struct clkgen_field nsb[QUADFS_MAX_CHAN];
+	struct clkgen_field en[QUADFS_MAX_CHAN];
+	struct clkgen_field mdiv[QUADFS_MAX_CHAN];
+	struct clkgen_field pe[QUADFS_MAX_CHAN];
+	struct clkgen_field sdiv[QUADFS_MAX_CHAN];
+	struct clkgen_field nsdiv[QUADFS_MAX_CHAN];
+
+	const struct clk_ops *pll_ops;
+	struct stm_fs *rtbl;
+	u8 rtbl_cnt;
+	int  (*get_rate)(unsigned long , struct stm_fs *,
+			unsigned long *);
+};
+
+static const struct clk_ops st_quadfs_pll_c65_ops;
+static const struct clk_ops st_quadfs_pll_c32_ops;
+static const struct clk_ops st_quadfs_fs216c65_ops;
+static const struct clk_ops st_quadfs_fs432c65_ops;
+static const struct clk_ops st_quadfs_fs660c32_ops;
+
+static int clk_fs216c65_get_rate(unsigned long, struct stm_fs *,
+		unsigned long *);
+static int clk_fs432c65_get_rate(unsigned long, struct stm_fs *,
+		unsigned long *);
+static int clk_fs660c32_dig_get_rate(unsigned long, struct stm_fs *,
+		unsigned long *);
+/*
+ * Values for all of the standalone instances of this clock
+ * generator found in STiH415 and STiH416 SYSCFG register banks. Note
+ * that the individual channel standby control bits (nsb) are in the
+ * first register along with the PLL control bits.
+ */
+static struct clkgen_quadfs_data st_fs216c65_416 = {
+	/* 416 specific */
+	.npda	= CLKGEN_FIELD(0x0, 0x1, 14),
+	.nsb	= { CLKGEN_FIELD(0x0, 0x1, 10),
+		    CLKGEN_FIELD(0x0, 0x1, 11),
+		    CLKGEN_FIELD(0x0, 0x1, 12),
+		    CLKGEN_FIELD(0x0, 0x1, 13) },
+	.nsdiv_present = true,
+	.nsdiv	= { CLKGEN_FIELD(0x0, 0x1, 18),
+		    CLKGEN_FIELD(0x0, 0x1, 19),
+		    CLKGEN_FIELD(0x0, 0x1, 20),
+		    CLKGEN_FIELD(0x0, 0x1, 21) },
+	.mdiv	= { CLKGEN_FIELD(0x4, 0x1f, 0),
+		    CLKGEN_FIELD(0x14, 0x1f, 0),
+		    CLKGEN_FIELD(0x24, 0x1f, 0),
+		    CLKGEN_FIELD(0x34, 0x1f, 0) },
+	.en	= { CLKGEN_FIELD(0x10, 0x1, 0),
+		    CLKGEN_FIELD(0x20, 0x1, 0),
+		    CLKGEN_FIELD(0x30, 0x1, 0),
+		    CLKGEN_FIELD(0x40, 0x1, 0) },
+	.ndiv	= CLKGEN_FIELD(0x0, 0x1, 15),
+	.bwfilter_present = true,
+	.ref_bw = CLKGEN_FIELD(0x0, 0x3, 16),
+	.pe	= { CLKGEN_FIELD(0x8, 0xffff, 0),
+		    CLKGEN_FIELD(0x18, 0xffff, 0),
+		    CLKGEN_FIELD(0x28, 0xffff, 0),
+		    CLKGEN_FIELD(0x38, 0xffff, 0) },
+	.sdiv	= { CLKGEN_FIELD(0xC, 0x7, 0),
+		    CLKGEN_FIELD(0x1C, 0x7, 0),
+		    CLKGEN_FIELD(0x2C, 0x7, 0),
+		    CLKGEN_FIELD(0x3C, 0x7, 0) },
+	.pll_ops	= &st_quadfs_pll_c65_ops,
+	.rtbl		= fs216c65_rtbl,
+	.rtbl_cnt	= ARRAY_SIZE(fs216c65_rtbl),
+	.get_rate	= clk_fs216c65_get_rate,
+};
+
+static struct clkgen_quadfs_data st_fs432c65_416 = {
+	.npda	= CLKGEN_FIELD(0x0, 0x1, 14),
+	.nsb	= { CLKGEN_FIELD(0x0, 0x1, 10),
+		    CLKGEN_FIELD(0x0, 0x1, 11),
+		    CLKGEN_FIELD(0x0, 0x1, 12),
+		    CLKGEN_FIELD(0x0, 0x1, 13) },
+	.nsdiv_present = true,
+	.nsdiv	= { CLKGEN_FIELD(0x0, 0x1, 18),
+		   CLKGEN_FIELD(0x0, 0x1, 19),
+		   CLKGEN_FIELD(0x0, 0x1, 20),
+		   CLKGEN_FIELD(0x0, 0x1, 21) },
+	.mdiv	= { CLKGEN_FIELD(0x4, 0x1f, 0),
+		    CLKGEN_FIELD(0x14, 0x1f, 0),
+		    CLKGEN_FIELD(0x24, 0x1f, 0),
+		    CLKGEN_FIELD(0x34, 0x1f, 0) },
+	.en	= { CLKGEN_FIELD(0x10, 0x1, 0),
+		    CLKGEN_FIELD(0x20, 0x1, 0),
+		    CLKGEN_FIELD(0x30, 0x1, 0),
+		    CLKGEN_FIELD(0x40, 0x1, 0) },
+	.ndiv	= CLKGEN_FIELD(0x0, 0x1, 15),
+	.bwfilter_present = true,
+	.ref_bw = CLKGEN_FIELD(0x0, 0x3, 16),
+	.pe	= { CLKGEN_FIELD(0x8, 0xffff, 0),
+		    CLKGEN_FIELD(0x18, 0xffff, 0),
+		    CLKGEN_FIELD(0x28, 0xffff, 0),
+		    CLKGEN_FIELD(0x38, 0xffff, 0) },
+	.sdiv	= { CLKGEN_FIELD(0xC, 0x7, 0),
+		    CLKGEN_FIELD(0x1C, 0x7, 0),
+		    CLKGEN_FIELD(0x2C, 0x7, 0),
+		    CLKGEN_FIELD(0x3C, 0x7, 0) },
+	.pll_ops	= &st_quadfs_pll_c65_ops,
+	.rtbl		= fs432c65_rtbl,
+	.rtbl_cnt	= ARRAY_SIZE(fs432c65_rtbl),
+	.get_rate	= clk_fs432c65_get_rate,
+};
+
+static struct clkgen_quadfs_data st_fs660c32_E_416 = {
+	.npda	= CLKGEN_FIELD(0x0, 0x1, 14),
+	.nsb	= { CLKGEN_FIELD(0x0, 0x1, 10),
+		    CLKGEN_FIELD(0x0, 0x1, 11),
+		    CLKGEN_FIELD(0x0, 0x1, 12),
+		    CLKGEN_FIELD(0x0, 0x1, 13) },
+	.nsdiv_present = true,
+	.nsdiv	= { CLKGEN_FIELD(0x0, 0x1, 18),
+		    CLKGEN_FIELD(0x0, 0x1, 19),
+		    CLKGEN_FIELD(0x0, 0x1, 20),
+		    CLKGEN_FIELD(0x0, 0x1, 21) },
+	.mdiv	= { CLKGEN_FIELD(0x4, 0x1f, 0),
+		    CLKGEN_FIELD(0x14, 0x1f, 0),
+		    CLKGEN_FIELD(0x24, 0x1f, 0),
+		    CLKGEN_FIELD(0x34, 0x1f, 0) },
+	.en	= { CLKGEN_FIELD(0x10, 0x1, 0),
+		    CLKGEN_FIELD(0x20, 0x1, 0),
+		    CLKGEN_FIELD(0x30, 0x1, 0),
+		    CLKGEN_FIELD(0x40, 0x1, 0) },
+	.ndiv	= CLKGEN_FIELD(0x0, 0x7, 15),
+	.pe	= { CLKGEN_FIELD(0x8, 0x7fff, 0),
+		    CLKGEN_FIELD(0x18, 0x7fff, 0),
+		    CLKGEN_FIELD(0x28, 0x7fff, 0),
+		    CLKGEN_FIELD(0x38, 0x7fff, 0) },
+	.sdiv	= { CLKGEN_FIELD(0xC, 0xf, 0),
+		    CLKGEN_FIELD(0x1C, 0xf, 0),
+		    CLKGEN_FIELD(0x2C, 0xf, 0),
+		    CLKGEN_FIELD(0x3C, 0xf, 0) },
+	.lockstatus_present = true,
+	.lock_status = CLKGEN_FIELD(0xAC, 0x1, 0),
+	.pll_ops	= &st_quadfs_pll_c32_ops,
+	.rtbl		= fs660c32_rtbl,
+	.rtbl_cnt	= ARRAY_SIZE(fs660c32_rtbl),
+	.get_rate	= clk_fs660c32_dig_get_rate,
+};
+
+static struct clkgen_quadfs_data st_fs660c32_F_416 = {
+	.npda	= CLKGEN_FIELD(0x0, 0x1, 14),
+	.nsb	= { CLKGEN_FIELD(0x0, 0x1, 10),
+		    CLKGEN_FIELD(0x0, 0x1, 11),
+		    CLKGEN_FIELD(0x0, 0x1, 12),
+		    CLKGEN_FIELD(0x0, 0x1, 13) },
+	.nsdiv_present = true,
+	.nsdiv	= { CLKGEN_FIELD(0x0, 0x1, 18),
+		    CLKGEN_FIELD(0x0, 0x1, 19),
+		    CLKGEN_FIELD(0x0, 0x1, 20),
+		    CLKGEN_FIELD(0x0, 0x1, 21) },
+	.mdiv	= { CLKGEN_FIELD(0x4, 0x1f, 0),
+		    CLKGEN_FIELD(0x14, 0x1f, 0),
+		    CLKGEN_FIELD(0x24, 0x1f, 0),
+		    CLKGEN_FIELD(0x34, 0x1f, 0) },
+	.en	= { CLKGEN_FIELD(0x10, 0x1, 0),
+		    CLKGEN_FIELD(0x20, 0x1, 0),
+		    CLKGEN_FIELD(0x30, 0x1, 0),
+		    CLKGEN_FIELD(0x40, 0x1, 0) },
+	.ndiv	= CLKGEN_FIELD(0x0, 0x7, 15),
+	.pe	= { CLKGEN_FIELD(0x8, 0x7fff, 0),
+		    CLKGEN_FIELD(0x18, 0x7fff, 0),
+		    CLKGEN_FIELD(0x28, 0x7fff, 0),
+		    CLKGEN_FIELD(0x38, 0x7fff, 0) },
+	.sdiv	= { CLKGEN_FIELD(0xC, 0xf, 0),
+		    CLKGEN_FIELD(0x1C, 0xf, 0),
+		    CLKGEN_FIELD(0x2C, 0xf, 0),
+		    CLKGEN_FIELD(0x3C, 0xf, 0) },
+	.lockstatus_present = true,
+	.lock_status = CLKGEN_FIELD(0xEC, 0x1, 0),
+	.pll_ops	= &st_quadfs_pll_c32_ops,
+	.rtbl		= fs660c32_rtbl,
+	.rtbl_cnt	= ARRAY_SIZE(fs660c32_rtbl),
+	.get_rate	= clk_fs660c32_dig_get_rate,
+};
+
+/**
+ * DOC: A Frequency Synthesizer that multiples its input clock by a fixed factor
+ *
+ * Traits of this clock:
+ * prepare - clk_(un)prepare only ensures parent is (un)prepared
+ * enable - clk_enable and clk_disable are functional & control the Fsyn
+ * rate - inherits rate from parent. set_rate/round_rate/recalc_rate
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+/**
+ * struct st_clk_quadfs_pll - A pll which outputs a fixed multiplier of
+ *                                  its parent clock, found inside a type of
+ *                                  ST quad channel frequency synthesizer block
+ *
+ * @hw: handle between common and hardware-specific interfaces.
+ * @ndiv: regmap field for the ndiv control.
+ * @regs_base: base address of the configuration registers.
+ * @lock: spinlock.
+ *
+ */
+struct st_clk_quadfs_pll {
+	struct clk_hw	hw;
+	void __iomem	*regs_base;
+	spinlock_t	*lock;
+	struct clkgen_quadfs_data *data;
+	u32 ndiv;
+};
+
+#define to_quadfs_pll(_hw) container_of(_hw, struct st_clk_quadfs_pll, hw)
+
+static int quadfs_pll_enable(struct clk_hw *hw)
+{
+	struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw);
+	unsigned long flags = 0, timeout = jiffies + msecs_to_jiffies(10);
+
+	if (pll->lock)
+		spin_lock_irqsave(pll->lock, flags);
+
+	/*
+	 * Bring block out of reset if we have reset control.
+	 */
+	if (pll->data->reset_present)
+		CLKGEN_WRITE(pll, nreset, 1);
+
+	/*
+	 * Use a fixed input clock noise bandwidth filter for the moment
+	 */
+	if (pll->data->bwfilter_present)
+		CLKGEN_WRITE(pll, ref_bw, PLL_BW_GOODREF);
+
+
+	CLKGEN_WRITE(pll, ndiv, pll->ndiv);
+
+	/*
+	 * Power up the PLL
+	 */
+	CLKGEN_WRITE(pll, npda, 1);
+
+	if (pll->lock)
+		spin_unlock_irqrestore(pll->lock, flags);
+
+	if (pll->data->lockstatus_present)
+		while (!CLKGEN_READ(pll, lock_status)) {
+			if (time_after(jiffies, timeout))
+				return -ETIMEDOUT;
+			cpu_relax();
+		}
+
+	return 0;
+}
+
+static void quadfs_pll_disable(struct clk_hw *hw)
+{
+	struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw);
+	unsigned long flags = 0;
+
+	if (pll->lock)
+		spin_lock_irqsave(pll->lock, flags);
+
+	/*
+	 * Powerdown the PLL and then put block into soft reset if we have
+	 * reset control.
+	 */
+	CLKGEN_WRITE(pll, npda, 0);
+
+	if (pll->data->reset_present)
+		CLKGEN_WRITE(pll, nreset, 0);
+
+	if (pll->lock)
+		spin_unlock_irqrestore(pll->lock, flags);
+}
+
+static int quadfs_pll_is_enabled(struct clk_hw *hw)
+{
+	struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw);
+	u32 npda = CLKGEN_READ(pll, npda);
+
+	return !!npda;
+}
+
+int clk_fs660c32_vco_get_rate(unsigned long input, struct stm_fs *fs,
+			   unsigned long *rate)
+{
+	unsigned long nd = fs->ndiv + 16; /* ndiv value */
+
+	*rate = input * nd;
+
+	return 0;
+}
+
+static unsigned long quadfs_pll_fs660c32_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw);
+	unsigned long rate = 0;
+	struct stm_fs params;
+
+	params.ndiv = CLKGEN_READ(pll, ndiv);
+	if (clk_fs660c32_vco_get_rate(parent_rate, &params, &rate))
+		pr_err("%s:%s error calculating rate\n",
+		       __clk_get_name(hw->clk), __func__);
+
+	pll->ndiv = params.ndiv;
+
+	return rate;
+}
+
+int clk_fs660c32_vco_get_params(unsigned long input,
+				unsigned long output, struct stm_fs *fs)
+{
+/* Formula
+   VCO frequency = (fin x ndiv) / pdiv
+   ndiv = VCOfreq * pdiv / fin
+   */
+	unsigned long pdiv = 1, n;
+
+	/* Output clock range: 384Mhz to 660Mhz */
+	if (output < 384000000 || output > 660000000)
+		return -EINVAL;
+
+	if (input > 40000000)
+		/* This means that PDIV would be 2 instead of 1.
+		   Not supported today. */
+		return -EINVAL;
+
+	input /= 1000;
+	output /= 1000;
+
+	n = output * pdiv / input;
+	if (n < 16)
+		n = 16;
+	fs->ndiv = n - 16; /* Converting formula value to reg value */
+
+	return 0;
+}
+
+static long quadfs_pll_fs660c32_round_rate(struct clk_hw *hw, unsigned long rate
+		, unsigned long *prate)
+{
+	struct stm_fs params;
+
+	if (!clk_fs660c32_vco_get_params(*prate, rate, &params))
+		clk_fs660c32_vco_get_rate(*prate, &params, &rate);
+
+	pr_debug("%s: %s new rate %ld [sdiv=0x%x,md=0x%x,pe=0x%x,nsdiv3=%u]\n",
+		 __func__, __clk_get_name(hw->clk),
+		 rate, (unsigned int)params.sdiv,
+		 (unsigned int)params.mdiv,
+		 (unsigned int)params.pe, (unsigned int)params.nsdiv);
+
+	return rate;
+}
+
+static int quadfs_pll_fs660c32_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw);
+	struct stm_fs params;
+	long hwrate = 0;
+	unsigned long flags = 0;
+
+	if (!rate || !parent_rate)
+		return -EINVAL;
+
+	if (!clk_fs660c32_vco_get_params(parent_rate, rate, &params))
+		clk_fs660c32_vco_get_rate(parent_rate, &params, &hwrate);
+
+	pr_debug("%s: %s new rate %ld [ndiv=0x%x]\n",
+		 __func__, __clk_get_name(hw->clk),
+		 hwrate, (unsigned int)params.ndiv);
+
+	if (!hwrate)
+		return -EINVAL;
+
+	pll->ndiv = params.ndiv;
+
+	if (pll->lock)
+		spin_lock_irqsave(pll->lock, flags);
+
+	CLKGEN_WRITE(pll, ndiv, pll->ndiv);
+
+	if (pll->lock)
+		spin_unlock_irqrestore(pll->lock, flags);
+
+	return 0;
+}
+
+static const struct clk_ops st_quadfs_pll_c65_ops = {
+	.enable		= quadfs_pll_enable,
+	.disable	= quadfs_pll_disable,
+	.is_enabled	= quadfs_pll_is_enabled,
+};
+
+static const struct clk_ops st_quadfs_pll_c32_ops = {
+	.enable		= quadfs_pll_enable,
+	.disable	= quadfs_pll_disable,
+	.is_enabled	= quadfs_pll_is_enabled,
+	.recalc_rate	= quadfs_pll_fs660c32_recalc_rate,
+	.round_rate	= quadfs_pll_fs660c32_round_rate,
+	.set_rate	= quadfs_pll_fs660c32_set_rate,
+};
+
+static struct clk * __init st_clk_register_quadfs_pll(
+		const char *name, const char *parent_name,
+		struct clkgen_quadfs_data *quadfs, void __iomem *reg,
+		spinlock_t *lock)
+{
+	struct st_clk_quadfs_pll *pll;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/*
+	 * Sanity check required pointers.
+	 */
+	if (WARN_ON(!name || !parent_name))
+		return ERR_PTR(-EINVAL);
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = quadfs->pll_ops;
+	init.flags = CLK_IS_BASIC;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	pll->data = quadfs;
+	pll->regs_base = reg;
+	pll->lock = lock;
+	pll->hw.init = &init;
+
+	clk = clk_register(NULL, &pll->hw);
+
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+/**
+ * DOC: A digital frequency synthesizer
+ *
+ * Traits of this clock:
+ * prepare - clk_(un)prepare only ensures parent is (un)prepared
+ * enable - clk_enable and clk_disable are functional
+ * rate - set rate is functional
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+/**
+ * struct st_clk_quadfs_fsynth - One clock output from a four channel digital
+ *                                  frequency synthesizer (fsynth) block.
+ *
+ * @hw: handle between common and hardware-specific interfaces
+ *
+ * @nsb: regmap field in the output control register for the digital
+ *       standby of this fsynth channel. This control is active low so
+ *       the channel is in standby when the control bit is cleared.
+ *
+ * @nsdiv: regmap field in the output control register for
+ *          for the optional divide by 3 of this fsynth channel. This control
+ *          is active low so the divide by 3 is active when the control bit is
+ *          cleared and the divide is bypassed when the bit is set.
+ */
+struct st_clk_quadfs_fsynth {
+	struct clk_hw	hw;
+	void __iomem	*regs_base;
+	spinlock_t	*lock;
+	struct clkgen_quadfs_data *data;
+
+	u32 chan;
+	/*
+	 * Cached hardware values from set_rate so we can program the
+	 * hardware in enable. There are two reasons for this:
+	 *
+	 *  1. The registers may not be writable until the parent has been
+	 *     enabled.
+	 *
+	 *  2. It restores the clock rate when a driver does an enable
+	 *     on PM restore, after a suspend to RAM has lost the hardware
+	 *     setup.
+	 */
+	u32 md;
+	u32 pe;
+	u32 sdiv;
+	u32 nsdiv;
+};
+
+#define to_quadfs_fsynth(_hw) \
+	container_of(_hw, struct st_clk_quadfs_fsynth, hw)
+
+static void quadfs_fsynth_program_enable(struct st_clk_quadfs_fsynth *fs)
+{
+	/*
+	 * Pulse the program enable register lsb to make the hardware take
+	 * notice of the new md/pe values with a glitchless transition.
+	 */
+	CLKGEN_WRITE(fs, en[fs->chan], 1);
+	CLKGEN_WRITE(fs, en[fs->chan], 0);
+}
+
+static void quadfs_fsynth_program_rate(struct st_clk_quadfs_fsynth *fs)
+{
+	unsigned long flags = 0;
+
+	/*
+	 * Ensure the md/pe parameters are ignored while we are
+	 * reprogramming them so we can get a glitchless change
+	 * when fine tuning the speed of a running clock.
+	 */
+	CLKGEN_WRITE(fs, en[fs->chan], 0);
+
+	CLKGEN_WRITE(fs, mdiv[fs->chan], fs->md);
+	CLKGEN_WRITE(fs, pe[fs->chan], fs->pe);
+	CLKGEN_WRITE(fs, sdiv[fs->chan], fs->sdiv);
+
+	if (fs->lock)
+		spin_lock_irqsave(fs->lock, flags);
+
+	if (fs->data->nsdiv_present)
+		CLKGEN_WRITE(fs, nsdiv[fs->chan], fs->nsdiv);
+
+	if (fs->lock)
+		spin_unlock_irqrestore(fs->lock, flags);
+}
+
+static int quadfs_fsynth_enable(struct clk_hw *hw)
+{
+	struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
+	unsigned long flags = 0;
+
+	pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk));
+
+	quadfs_fsynth_program_rate(fs);
+
+	if (fs->lock)
+		spin_lock_irqsave(fs->lock, flags);
+
+	CLKGEN_WRITE(fs, nsb[fs->chan], 1);
+
+	if (fs->lock)
+		spin_unlock_irqrestore(fs->lock, flags);
+
+	quadfs_fsynth_program_enable(fs);
+
+	return 0;
+}
+
+static void quadfs_fsynth_disable(struct clk_hw *hw)
+{
+	struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
+	unsigned long flags = 0;
+
+	pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk));
+
+	if (fs->lock)
+		spin_lock_irqsave(fs->lock, flags);
+
+	CLKGEN_WRITE(fs, nsb[fs->chan], 0);
+
+	if (fs->lock)
+		spin_unlock_irqrestore(fs->lock, flags);
+}
+
+static int quadfs_fsynth_is_enabled(struct clk_hw *hw)
+{
+	struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
+	u32 nsb = CLKGEN_READ(fs, nsb[fs->chan]);
+
+	pr_debug("%s: %s enable bit = 0x%x\n",
+		 __func__, __clk_get_name(hw->clk), nsb);
+
+	return !!nsb;
+}
+
+#define P15			(uint64_t)(1 << 15)
+
+static int clk_fs216c65_get_rate(unsigned long input, struct stm_fs *fs,
+		unsigned long *rate)
+{
+	uint64_t res;
+	unsigned long ns;
+	unsigned long nd = 8; /* ndiv stuck at 0 => val = 8 */
+	unsigned long s;
+	long m;
+
+	m = fs->mdiv - 32;
+	s = 1 << (fs->sdiv + 1);
+	ns = (fs->nsdiv ? 1 : 3);
+
+	res = (uint64_t)(s * ns * P15 * (uint64_t)(m + 33));
+	res = res - (s * ns * fs->pe);
+	*rate = div64_u64(P15 * nd * input * 32, res);
+
+	return 0;
+}
+
+static int clk_fs432c65_get_rate(unsigned long input, struct stm_fs *fs,
+		unsigned long *rate)
+{
+	uint64_t res;
+	unsigned long nd = 16; /* ndiv value; stuck at 0 (30Mhz input) */
+	long m;
+	unsigned long sd;
+	unsigned long ns;
+
+	m = fs->mdiv - 32;
+	sd = 1 << (fs->sdiv + 1);
+	ns = (fs->nsdiv ? 1 : 3);
+
+	res = (uint64_t)(sd * ns * P15 * (uint64_t)(m + 33));
+	res = res - (sd * ns * fs->pe);
+	*rate = div64_u64(P15 * nd * input * 32, res);
+
+	return 0;
+}
+
+#define P20		(uint64_t)(1 << 20)
+
+static int clk_fs660c32_dig_get_rate(unsigned long input,
+				struct stm_fs *fs, unsigned long *rate)
+{
+	unsigned long s = (1 << fs->sdiv);
+	unsigned long ns;
+	uint64_t res;
+
+	/*
+	 * 'nsdiv' is a register value ('BIN') which is translated
+	 * to a decimal value according to following rules.
+	 *
+	 *     nsdiv      ns.dec
+	 *       0        3
+	 *       1        1
+	 */
+	ns = (fs->nsdiv == 1) ? 1 : 3;
+
+	res = (P20 * (32 + fs->mdiv) + 32 * fs->pe) * s * ns;
+	*rate = (unsigned long)div64_u64(input * P20 * 32, res);
+
+	return 0;
+}
+
+static int quadfs_fsynt_get_hw_value_for_recalc(struct st_clk_quadfs_fsynth *fs,
+		struct stm_fs *params)
+{
+	/*
+	 * Get the initial hardware values for recalc_rate
+	 */
+	params->mdiv	= CLKGEN_READ(fs, mdiv[fs->chan]);
+	params->pe	= CLKGEN_READ(fs, pe[fs->chan]);
+	params->sdiv	= CLKGEN_READ(fs, sdiv[fs->chan]);
+
+	if (fs->data->nsdiv_present)
+		params->nsdiv = CLKGEN_READ(fs, nsdiv[fs->chan]);
+	else
+		params->nsdiv = 1;
+
+	/*
+	 * If All are NULL then assume no clock rate is programmed.
+	 */
+	if (!params->mdiv && !params->pe && !params->sdiv)
+		return 1;
+
+	fs->md = params->mdiv;
+	fs->pe = params->pe;
+	fs->sdiv = params->sdiv;
+	fs->nsdiv = params->nsdiv;
+
+	return 0;
+}
+
+static long quadfs_find_best_rate(struct clk_hw *hw, unsigned long drate,
+				unsigned long prate, struct stm_fs *params)
+{
+	struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
+	int (*clk_fs_get_rate)(unsigned long ,
+				struct stm_fs *, unsigned long *);
+	struct stm_fs prev_params;
+	unsigned long prev_rate, rate = 0;
+	unsigned long diff_rate, prev_diff_rate = ~0;
+	int index;
+
+	clk_fs_get_rate = fs->data->get_rate;
+
+	for (index = 0; index < fs->data->rtbl_cnt; index++) {
+		prev_rate = rate;
+
+		*params = fs->data->rtbl[index];
+		prev_params = *params;
+
+		clk_fs_get_rate(prate, &fs->data->rtbl[index], &rate);
+
+		diff_rate = abs(drate - rate);
+
+		if (diff_rate > prev_diff_rate) {
+			rate = prev_rate;
+			*params = prev_params;
+			break;
+		}
+
+		prev_diff_rate = diff_rate;
+
+		if (drate == rate)
+			return rate;
+	}
+
+
+	if (index == fs->data->rtbl_cnt)
+		*params = prev_params;
+
+	return rate;
+}
+
+static unsigned long quadfs_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
+	unsigned long rate = 0;
+	struct stm_fs params;
+	int (*clk_fs_get_rate)(unsigned long ,
+				struct stm_fs *, unsigned long *);
+
+	clk_fs_get_rate = fs->data->get_rate;
+
+	if (quadfs_fsynt_get_hw_value_for_recalc(fs, &params))
+		return 0;
+
+	if (clk_fs_get_rate(parent_rate, &params, &rate)) {
+		pr_err("%s:%s error calculating rate\n",
+		       __clk_get_name(hw->clk), __func__);
+	}
+
+	pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+
+	return rate;
+}
+
+static long quadfs_round_rate(struct clk_hw *hw, unsigned long rate,
+				     unsigned long *prate)
+{
+	struct stm_fs params;
+
+	rate = quadfs_find_best_rate(hw, rate, *prate, &params);
+
+	pr_debug("%s: %s new rate %ld [sdiv=0x%x,md=0x%x,pe=0x%x,nsdiv3=%u]\n",
+		 __func__, __clk_get_name(hw->clk),
+		 rate, (unsigned int)params.sdiv, (unsigned int)params.mdiv,
+			 (unsigned int)params.pe, (unsigned int)params.nsdiv);
+
+	return rate;
+}
+
+
+static void quadfs_program_and_enable(struct st_clk_quadfs_fsynth *fs,
+		struct stm_fs *params)
+{
+	fs->md = params->mdiv;
+	fs->pe = params->pe;
+	fs->sdiv = params->sdiv;
+	fs->nsdiv = params->nsdiv;
+
+	/*
+	 * In some integrations you can only change the fsynth programming when
+	 * the parent entity containing it is enabled.
+	 */
+	quadfs_fsynth_program_rate(fs);
+	quadfs_fsynth_program_enable(fs);
+}
+
+static int quadfs_set_rate(struct clk_hw *hw, unsigned long rate,
+				  unsigned long parent_rate)
+{
+	struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
+	struct stm_fs params;
+	long hwrate;
+	int uninitialized_var(i);
+
+	if (!rate || !parent_rate)
+		return -EINVAL;
+
+	memset(&params, 0, sizeof(struct stm_fs));
+
+	hwrate = quadfs_find_best_rate(hw, rate, parent_rate, &params);
+	if (!hwrate)
+		return -EINVAL;
+
+	quadfs_program_and_enable(fs, &params);
+
+	return 0;
+}
+
+
+
+static const struct clk_ops st_quadfs_ops = {
+	.enable		= quadfs_fsynth_enable,
+	.disable	= quadfs_fsynth_disable,
+	.is_enabled	= quadfs_fsynth_is_enabled,
+	.round_rate	= quadfs_round_rate,
+	.set_rate	= quadfs_set_rate,
+	.recalc_rate	= quadfs_recalc_rate,
+};
+
+static struct clk * __init st_clk_register_quadfs_fsynth(
+		const char *name, const char *parent_name,
+		struct clkgen_quadfs_data *quadfs, void __iomem *reg, u32 chan,
+		spinlock_t *lock)
+{
+	struct st_clk_quadfs_fsynth *fs;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/*
+	 * Sanity check required pointers, note that nsdiv3 is optional.
+	 */
+	if (WARN_ON(!name || !parent_name))
+		return ERR_PTR(-EINVAL);
+
+	fs = kzalloc(sizeof(*fs), GFP_KERNEL);
+	if (!fs)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &st_quadfs_ops;
+	init.flags = CLK_GET_RATE_NOCACHE | CLK_IS_BASIC;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	fs->data = quadfs;
+	fs->regs_base = reg;
+	fs->chan = chan;
+	fs->lock = lock;
+	fs->hw.init = &init;
+
+	clk = clk_register(NULL, &fs->hw);
+
+	if (IS_ERR(clk))
+		kfree(fs);
+
+	return clk;
+}
+
+static struct of_device_id quadfs_of_match[] = {
+	{
+		.compatible = "st,stih416-quadfs216",
+		.data = (void *)&st_fs216c65_416
+	},
+	{
+		.compatible = "st,stih416-quadfs432",
+		.data = (void *)&st_fs432c65_416
+	},
+	{
+		.compatible = "st,stih416-quadfs660-E",
+		.data = (void *)&st_fs660c32_E_416
+	},
+	{
+		.compatible = "st,stih416-quadfs660-F",
+		.data = (void *)&st_fs660c32_F_416
+	},
+	{}
+};
+
+static void __init st_of_create_quadfs_fsynths(
+		struct device_node *np, const char *pll_name,
+		struct clkgen_quadfs_data *quadfs, void __iomem *reg,
+		spinlock_t *lock)
+{
+	struct clk_onecell_data *clk_data;
+	int fschan;
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return;
+
+	clk_data->clk_num = QUADFS_MAX_CHAN;
+	clk_data->clks = kzalloc(QUADFS_MAX_CHAN * sizeof(struct clk *),
+				 GFP_KERNEL);
+
+	if (!clk_data->clks) {
+		kfree(clk_data);
+		return;
+	}
+
+	for (fschan = 0; fschan < QUADFS_MAX_CHAN; fschan++) {
+		struct clk *clk;
+		const char *clk_name;
+
+		if (of_property_read_string_index(np, "clock-output-names",
+						  fschan, &clk_name)) {
+			break;
+		}
+
+		/*
+		 * If we read an empty clock name then the channel is unused
+		 */
+		if (*clk_name == '\0')
+			continue;
+
+		clk = st_clk_register_quadfs_fsynth(clk_name, pll_name,
+				quadfs, reg, fschan, lock);
+
+		/*
+		 * If there was an error registering this clock output, clean
+		 * up and move on to the next one.
+		 */
+		if (!IS_ERR(clk)) {
+			clk_data->clks[fschan] = clk;
+			pr_debug("%s: parent %s rate %u\n",
+				__clk_get_name(clk),
+				__clk_get_name(clk_get_parent(clk)),
+				(unsigned int)clk_get_rate(clk));
+		}
+	}
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+}
+
+static void __init st_of_quadfs_setup(struct device_node *np)
+{
+	const struct of_device_id *match;
+	struct clk *clk;
+	const char *pll_name, *clk_parent_name;
+	void __iomem *reg;
+	spinlock_t *lock;
+
+	match = of_match_node(quadfs_of_match, np);
+	if (WARN_ON(!match))
+		return;
+
+	reg = of_iomap(np, 0);
+	if (!reg)
+		return;
+
+	clk_parent_name = of_clk_get_parent_name(np, 0);
+	if (!clk_parent_name)
+		return;
+
+	pll_name = kasprintf(GFP_KERNEL, "%s.pll", np->name);
+	if (!pll_name)
+		return;
+
+	lock = kzalloc(sizeof(*lock), GFP_KERNEL);
+	if (!lock)
+		goto err_exit;
+
+	spin_lock_init(lock);
+
+	clk = st_clk_register_quadfs_pll(pll_name, clk_parent_name,
+			(struct clkgen_quadfs_data *) match->data, reg, lock);
+	if (IS_ERR(clk))
+		goto err_exit;
+	else
+		pr_debug("%s: parent %s rate %u\n",
+			__clk_get_name(clk),
+			__clk_get_name(clk_get_parent(clk)),
+			(unsigned int)clk_get_rate(clk));
+
+	st_of_create_quadfs_fsynths(np, pll_name,
+				    (struct clkgen_quadfs_data *)match->data,
+				    reg, lock);
+
+err_exit:
+	kfree(pll_name); /* No longer need local copy of the PLL name */
+}
+CLK_OF_DECLARE(quadfs, "st,quadfs", st_of_quadfs_setup);
-- 
1.9.0


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

* [PATCH v0 04/15] drivers: clk: st: Support for QUADFS inside ClockGenB/C/D/E/F
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

The patch supports the 216/432/660 type Quad Frequency Synthesizers
used by ClockGenB/C/D/E/F

QUADFS clock : It includes support for all 216/432/660 type Quad
Frequency Synthesizers : implemented as Fixed Parent / Rate / Gate clock,
with clock rate calculated reading H/w settings done at BOOT.

QuadFS have 4 outputs : chan0 chan1 chan2 chan3

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 drivers/clk/st/Makefile      |    2 +-
 drivers/clk/st/clkgen-fsyn.c | 1039 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1040 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/st/clkgen-fsyn.c

diff --git a/drivers/clk/st/Makefile b/drivers/clk/st/Makefile
index b7b10f9..c7455ff 100644
--- a/drivers/clk/st/Makefile
+++ b/drivers/clk/st/Makefile
@@ -1 +1 @@
-obj-y += clkgen-mux.o clkgen-pll.o
+obj-y += clkgen-mux.o clkgen-pll.o clkgen-fsyn.o
diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c
new file mode 100644
index 0000000..4f53ee0
--- /dev/null
+++ b/drivers/clk/st/clkgen-fsyn.c
@@ -0,0 +1,1039 @@
+/*
+ * Copyright (C) 2014 STMicroelectronics R&D Ltd
+ *
+ * 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.
+ *
+ */
+
+/*
+ * Authors:
+ * Stephen Gallimore <stephen.gallimore@st.com>,
+ * Pankaj Dev <pankaj.dev@st.com>.
+ */
+
+#include <linux/slab.h>
+#include <linux/of_address.h>
+#include <linux/clk-provider.h>
+
+#include "clkgen.h"
+
+/*
+ * Maximum input clock to the PLL before we divide it down by 2
+ * although in reality in actual systems this has never been seen to
+ * be used.
+ */
+#define QUADFS_NDIV_THRESHOLD 30000000
+
+#define PLL_BW_GOODREF   (0L)
+#define PLL_BW_VBADREF   (1L)
+#define PLL_BW_BADREF    (2L)
+#define PLL_BW_VGOODREF  (3L)
+
+#define QUADFS_MAX_CHAN 4
+
+struct stm_fs {
+	unsigned long ndiv;
+	unsigned long mdiv;
+	unsigned long pe;
+	unsigned long sdiv;
+	unsigned long nsdiv;
+};
+
+static struct stm_fs fs216c65_rtbl[] = {
+	{ .mdiv = 0x1f, .pe = 0x0,	.sdiv = 0x7,	.nsdiv = 0 },	/* 312.5 Khz */
+	{ .mdiv = 0x17, .pe = 0x25ed,	.sdiv = 0x1,	.nsdiv = 0 },	/* 27    MHz */
+	{ .mdiv = 0x1a, .pe = 0x7b36,	.sdiv = 0x2,	.nsdiv = 1 },	/* 36.87 MHz */
+	{ .mdiv = 0x13, .pe = 0x0,	.sdiv = 0x2,	.nsdiv = 1 },	/* 48    MHz */
+	{ .mdiv = 0x11, .pe = 0x1c72,	.sdiv = 0x1,	.nsdiv = 1 },	/* 108   MHz */
+};
+
+static struct stm_fs fs432c65_rtbl[] = {
+	{ .mdiv = 0x1f, .pe = 0x0,	.sdiv = 0x7,	.nsdiv = 0 },	/* 625   Khz */
+	{ .mdiv = 0x11, .pe = 0x1c72,	.sdiv = 0x2,	.nsdiv = 1 },	/* 108   MHz */
+	{ .mdiv = 0x19, .pe = 0x121a,	.sdiv = 0x0,	.nsdiv = 1 },	/* 297   MHz */
+};
+
+static struct stm_fs fs660c32_rtbl[] = {
+	{ .mdiv = 0x01, .pe = 0x2aaa,	.sdiv = 0x8,	.nsdiv = 0 },	/* 600   KHz */
+	{ .mdiv = 0x02, .pe = 0x3d33,	.sdiv = 0x0,	.nsdiv = 0 },	/* 148.5 Mhz */
+	{ .mdiv = 0x13, .pe = 0x5bcc,	.sdiv = 0x0,	.nsdiv = 1 },	/* 297   Mhz */
+	{ .mdiv = 0x0e, .pe = 0x1025,	.sdiv = 0x0,	.nsdiv = 1 },	/* 333   Mhz */
+	{ .mdiv = 0x0b, .pe = 0x715f,	.sdiv = 0x0,	.nsdiv = 1 },	/* 350   Mhz */
+};
+
+struct clkgen_quadfs_data {
+	bool reset_present;
+	bool bwfilter_present;
+	bool lockstatus_present;
+	bool nsdiv_present;
+	struct clkgen_field ndiv;
+	struct clkgen_field ref_bw;
+	struct clkgen_field nreset;
+	struct clkgen_field npda;
+	struct clkgen_field lock_status;
+
+	struct clkgen_field nsb[QUADFS_MAX_CHAN];
+	struct clkgen_field en[QUADFS_MAX_CHAN];
+	struct clkgen_field mdiv[QUADFS_MAX_CHAN];
+	struct clkgen_field pe[QUADFS_MAX_CHAN];
+	struct clkgen_field sdiv[QUADFS_MAX_CHAN];
+	struct clkgen_field nsdiv[QUADFS_MAX_CHAN];
+
+	const struct clk_ops *pll_ops;
+	struct stm_fs *rtbl;
+	u8 rtbl_cnt;
+	int  (*get_rate)(unsigned long , struct stm_fs *,
+			unsigned long *);
+};
+
+static const struct clk_ops st_quadfs_pll_c65_ops;
+static const struct clk_ops st_quadfs_pll_c32_ops;
+static const struct clk_ops st_quadfs_fs216c65_ops;
+static const struct clk_ops st_quadfs_fs432c65_ops;
+static const struct clk_ops st_quadfs_fs660c32_ops;
+
+static int clk_fs216c65_get_rate(unsigned long, struct stm_fs *,
+		unsigned long *);
+static int clk_fs432c65_get_rate(unsigned long, struct stm_fs *,
+		unsigned long *);
+static int clk_fs660c32_dig_get_rate(unsigned long, struct stm_fs *,
+		unsigned long *);
+/*
+ * Values for all of the standalone instances of this clock
+ * generator found in STiH415 and STiH416 SYSCFG register banks. Note
+ * that the individual channel standby control bits (nsb) are in the
+ * first register along with the PLL control bits.
+ */
+static struct clkgen_quadfs_data st_fs216c65_416 = {
+	/* 416 specific */
+	.npda	= CLKGEN_FIELD(0x0, 0x1, 14),
+	.nsb	= { CLKGEN_FIELD(0x0, 0x1, 10),
+		    CLKGEN_FIELD(0x0, 0x1, 11),
+		    CLKGEN_FIELD(0x0, 0x1, 12),
+		    CLKGEN_FIELD(0x0, 0x1, 13) },
+	.nsdiv_present = true,
+	.nsdiv	= { CLKGEN_FIELD(0x0, 0x1, 18),
+		    CLKGEN_FIELD(0x0, 0x1, 19),
+		    CLKGEN_FIELD(0x0, 0x1, 20),
+		    CLKGEN_FIELD(0x0, 0x1, 21) },
+	.mdiv	= { CLKGEN_FIELD(0x4, 0x1f, 0),
+		    CLKGEN_FIELD(0x14, 0x1f, 0),
+		    CLKGEN_FIELD(0x24, 0x1f, 0),
+		    CLKGEN_FIELD(0x34, 0x1f, 0) },
+	.en	= { CLKGEN_FIELD(0x10, 0x1, 0),
+		    CLKGEN_FIELD(0x20, 0x1, 0),
+		    CLKGEN_FIELD(0x30, 0x1, 0),
+		    CLKGEN_FIELD(0x40, 0x1, 0) },
+	.ndiv	= CLKGEN_FIELD(0x0, 0x1, 15),
+	.bwfilter_present = true,
+	.ref_bw = CLKGEN_FIELD(0x0, 0x3, 16),
+	.pe	= { CLKGEN_FIELD(0x8, 0xffff, 0),
+		    CLKGEN_FIELD(0x18, 0xffff, 0),
+		    CLKGEN_FIELD(0x28, 0xffff, 0),
+		    CLKGEN_FIELD(0x38, 0xffff, 0) },
+	.sdiv	= { CLKGEN_FIELD(0xC, 0x7, 0),
+		    CLKGEN_FIELD(0x1C, 0x7, 0),
+		    CLKGEN_FIELD(0x2C, 0x7, 0),
+		    CLKGEN_FIELD(0x3C, 0x7, 0) },
+	.pll_ops	= &st_quadfs_pll_c65_ops,
+	.rtbl		= fs216c65_rtbl,
+	.rtbl_cnt	= ARRAY_SIZE(fs216c65_rtbl),
+	.get_rate	= clk_fs216c65_get_rate,
+};
+
+static struct clkgen_quadfs_data st_fs432c65_416 = {
+	.npda	= CLKGEN_FIELD(0x0, 0x1, 14),
+	.nsb	= { CLKGEN_FIELD(0x0, 0x1, 10),
+		    CLKGEN_FIELD(0x0, 0x1, 11),
+		    CLKGEN_FIELD(0x0, 0x1, 12),
+		    CLKGEN_FIELD(0x0, 0x1, 13) },
+	.nsdiv_present = true,
+	.nsdiv	= { CLKGEN_FIELD(0x0, 0x1, 18),
+		   CLKGEN_FIELD(0x0, 0x1, 19),
+		   CLKGEN_FIELD(0x0, 0x1, 20),
+		   CLKGEN_FIELD(0x0, 0x1, 21) },
+	.mdiv	= { CLKGEN_FIELD(0x4, 0x1f, 0),
+		    CLKGEN_FIELD(0x14, 0x1f, 0),
+		    CLKGEN_FIELD(0x24, 0x1f, 0),
+		    CLKGEN_FIELD(0x34, 0x1f, 0) },
+	.en	= { CLKGEN_FIELD(0x10, 0x1, 0),
+		    CLKGEN_FIELD(0x20, 0x1, 0),
+		    CLKGEN_FIELD(0x30, 0x1, 0),
+		    CLKGEN_FIELD(0x40, 0x1, 0) },
+	.ndiv	= CLKGEN_FIELD(0x0, 0x1, 15),
+	.bwfilter_present = true,
+	.ref_bw = CLKGEN_FIELD(0x0, 0x3, 16),
+	.pe	= { CLKGEN_FIELD(0x8, 0xffff, 0),
+		    CLKGEN_FIELD(0x18, 0xffff, 0),
+		    CLKGEN_FIELD(0x28, 0xffff, 0),
+		    CLKGEN_FIELD(0x38, 0xffff, 0) },
+	.sdiv	= { CLKGEN_FIELD(0xC, 0x7, 0),
+		    CLKGEN_FIELD(0x1C, 0x7, 0),
+		    CLKGEN_FIELD(0x2C, 0x7, 0),
+		    CLKGEN_FIELD(0x3C, 0x7, 0) },
+	.pll_ops	= &st_quadfs_pll_c65_ops,
+	.rtbl		= fs432c65_rtbl,
+	.rtbl_cnt	= ARRAY_SIZE(fs432c65_rtbl),
+	.get_rate	= clk_fs432c65_get_rate,
+};
+
+static struct clkgen_quadfs_data st_fs660c32_E_416 = {
+	.npda	= CLKGEN_FIELD(0x0, 0x1, 14),
+	.nsb	= { CLKGEN_FIELD(0x0, 0x1, 10),
+		    CLKGEN_FIELD(0x0, 0x1, 11),
+		    CLKGEN_FIELD(0x0, 0x1, 12),
+		    CLKGEN_FIELD(0x0, 0x1, 13) },
+	.nsdiv_present = true,
+	.nsdiv	= { CLKGEN_FIELD(0x0, 0x1, 18),
+		    CLKGEN_FIELD(0x0, 0x1, 19),
+		    CLKGEN_FIELD(0x0, 0x1, 20),
+		    CLKGEN_FIELD(0x0, 0x1, 21) },
+	.mdiv	= { CLKGEN_FIELD(0x4, 0x1f, 0),
+		    CLKGEN_FIELD(0x14, 0x1f, 0),
+		    CLKGEN_FIELD(0x24, 0x1f, 0),
+		    CLKGEN_FIELD(0x34, 0x1f, 0) },
+	.en	= { CLKGEN_FIELD(0x10, 0x1, 0),
+		    CLKGEN_FIELD(0x20, 0x1, 0),
+		    CLKGEN_FIELD(0x30, 0x1, 0),
+		    CLKGEN_FIELD(0x40, 0x1, 0) },
+	.ndiv	= CLKGEN_FIELD(0x0, 0x7, 15),
+	.pe	= { CLKGEN_FIELD(0x8, 0x7fff, 0),
+		    CLKGEN_FIELD(0x18, 0x7fff, 0),
+		    CLKGEN_FIELD(0x28, 0x7fff, 0),
+		    CLKGEN_FIELD(0x38, 0x7fff, 0) },
+	.sdiv	= { CLKGEN_FIELD(0xC, 0xf, 0),
+		    CLKGEN_FIELD(0x1C, 0xf, 0),
+		    CLKGEN_FIELD(0x2C, 0xf, 0),
+		    CLKGEN_FIELD(0x3C, 0xf, 0) },
+	.lockstatus_present = true,
+	.lock_status = CLKGEN_FIELD(0xAC, 0x1, 0),
+	.pll_ops	= &st_quadfs_pll_c32_ops,
+	.rtbl		= fs660c32_rtbl,
+	.rtbl_cnt	= ARRAY_SIZE(fs660c32_rtbl),
+	.get_rate	= clk_fs660c32_dig_get_rate,
+};
+
+static struct clkgen_quadfs_data st_fs660c32_F_416 = {
+	.npda	= CLKGEN_FIELD(0x0, 0x1, 14),
+	.nsb	= { CLKGEN_FIELD(0x0, 0x1, 10),
+		    CLKGEN_FIELD(0x0, 0x1, 11),
+		    CLKGEN_FIELD(0x0, 0x1, 12),
+		    CLKGEN_FIELD(0x0, 0x1, 13) },
+	.nsdiv_present = true,
+	.nsdiv	= { CLKGEN_FIELD(0x0, 0x1, 18),
+		    CLKGEN_FIELD(0x0, 0x1, 19),
+		    CLKGEN_FIELD(0x0, 0x1, 20),
+		    CLKGEN_FIELD(0x0, 0x1, 21) },
+	.mdiv	= { CLKGEN_FIELD(0x4, 0x1f, 0),
+		    CLKGEN_FIELD(0x14, 0x1f, 0),
+		    CLKGEN_FIELD(0x24, 0x1f, 0),
+		    CLKGEN_FIELD(0x34, 0x1f, 0) },
+	.en	= { CLKGEN_FIELD(0x10, 0x1, 0),
+		    CLKGEN_FIELD(0x20, 0x1, 0),
+		    CLKGEN_FIELD(0x30, 0x1, 0),
+		    CLKGEN_FIELD(0x40, 0x1, 0) },
+	.ndiv	= CLKGEN_FIELD(0x0, 0x7, 15),
+	.pe	= { CLKGEN_FIELD(0x8, 0x7fff, 0),
+		    CLKGEN_FIELD(0x18, 0x7fff, 0),
+		    CLKGEN_FIELD(0x28, 0x7fff, 0),
+		    CLKGEN_FIELD(0x38, 0x7fff, 0) },
+	.sdiv	= { CLKGEN_FIELD(0xC, 0xf, 0),
+		    CLKGEN_FIELD(0x1C, 0xf, 0),
+		    CLKGEN_FIELD(0x2C, 0xf, 0),
+		    CLKGEN_FIELD(0x3C, 0xf, 0) },
+	.lockstatus_present = true,
+	.lock_status = CLKGEN_FIELD(0xEC, 0x1, 0),
+	.pll_ops	= &st_quadfs_pll_c32_ops,
+	.rtbl		= fs660c32_rtbl,
+	.rtbl_cnt	= ARRAY_SIZE(fs660c32_rtbl),
+	.get_rate	= clk_fs660c32_dig_get_rate,
+};
+
+/**
+ * DOC: A Frequency Synthesizer that multiples its input clock by a fixed factor
+ *
+ * Traits of this clock:
+ * prepare - clk_(un)prepare only ensures parent is (un)prepared
+ * enable - clk_enable and clk_disable are functional & control the Fsyn
+ * rate - inherits rate from parent. set_rate/round_rate/recalc_rate
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+/**
+ * struct st_clk_quadfs_pll - A pll which outputs a fixed multiplier of
+ *                                  its parent clock, found inside a type of
+ *                                  ST quad channel frequency synthesizer block
+ *
+ * @hw: handle between common and hardware-specific interfaces.
+ * @ndiv: regmap field for the ndiv control.
+ * @regs_base: base address of the configuration registers.
+ * @lock: spinlock.
+ *
+ */
+struct st_clk_quadfs_pll {
+	struct clk_hw	hw;
+	void __iomem	*regs_base;
+	spinlock_t	*lock;
+	struct clkgen_quadfs_data *data;
+	u32 ndiv;
+};
+
+#define to_quadfs_pll(_hw) container_of(_hw, struct st_clk_quadfs_pll, hw)
+
+static int quadfs_pll_enable(struct clk_hw *hw)
+{
+	struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw);
+	unsigned long flags = 0, timeout = jiffies + msecs_to_jiffies(10);
+
+	if (pll->lock)
+		spin_lock_irqsave(pll->lock, flags);
+
+	/*
+	 * Bring block out of reset if we have reset control.
+	 */
+	if (pll->data->reset_present)
+		CLKGEN_WRITE(pll, nreset, 1);
+
+	/*
+	 * Use a fixed input clock noise bandwidth filter for the moment
+	 */
+	if (pll->data->bwfilter_present)
+		CLKGEN_WRITE(pll, ref_bw, PLL_BW_GOODREF);
+
+
+	CLKGEN_WRITE(pll, ndiv, pll->ndiv);
+
+	/*
+	 * Power up the PLL
+	 */
+	CLKGEN_WRITE(pll, npda, 1);
+
+	if (pll->lock)
+		spin_unlock_irqrestore(pll->lock, flags);
+
+	if (pll->data->lockstatus_present)
+		while (!CLKGEN_READ(pll, lock_status)) {
+			if (time_after(jiffies, timeout))
+				return -ETIMEDOUT;
+			cpu_relax();
+		}
+
+	return 0;
+}
+
+static void quadfs_pll_disable(struct clk_hw *hw)
+{
+	struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw);
+	unsigned long flags = 0;
+
+	if (pll->lock)
+		spin_lock_irqsave(pll->lock, flags);
+
+	/*
+	 * Powerdown the PLL and then put block into soft reset if we have
+	 * reset control.
+	 */
+	CLKGEN_WRITE(pll, npda, 0);
+
+	if (pll->data->reset_present)
+		CLKGEN_WRITE(pll, nreset, 0);
+
+	if (pll->lock)
+		spin_unlock_irqrestore(pll->lock, flags);
+}
+
+static int quadfs_pll_is_enabled(struct clk_hw *hw)
+{
+	struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw);
+	u32 npda = CLKGEN_READ(pll, npda);
+
+	return !!npda;
+}
+
+int clk_fs660c32_vco_get_rate(unsigned long input, struct stm_fs *fs,
+			   unsigned long *rate)
+{
+	unsigned long nd = fs->ndiv + 16; /* ndiv value */
+
+	*rate = input * nd;
+
+	return 0;
+}
+
+static unsigned long quadfs_pll_fs660c32_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw);
+	unsigned long rate = 0;
+	struct stm_fs params;
+
+	params.ndiv = CLKGEN_READ(pll, ndiv);
+	if (clk_fs660c32_vco_get_rate(parent_rate, &params, &rate))
+		pr_err("%s:%s error calculating rate\n",
+		       __clk_get_name(hw->clk), __func__);
+
+	pll->ndiv = params.ndiv;
+
+	return rate;
+}
+
+int clk_fs660c32_vco_get_params(unsigned long input,
+				unsigned long output, struct stm_fs *fs)
+{
+/* Formula
+   VCO frequency = (fin x ndiv) / pdiv
+   ndiv = VCOfreq * pdiv / fin
+   */
+	unsigned long pdiv = 1, n;
+
+	/* Output clock range: 384Mhz to 660Mhz */
+	if (output < 384000000 || output > 660000000)
+		return -EINVAL;
+
+	if (input > 40000000)
+		/* This means that PDIV would be 2 instead of 1.
+		   Not supported today. */
+		return -EINVAL;
+
+	input /= 1000;
+	output /= 1000;
+
+	n = output * pdiv / input;
+	if (n < 16)
+		n = 16;
+	fs->ndiv = n - 16; /* Converting formula value to reg value */
+
+	return 0;
+}
+
+static long quadfs_pll_fs660c32_round_rate(struct clk_hw *hw, unsigned long rate
+		, unsigned long *prate)
+{
+	struct stm_fs params;
+
+	if (!clk_fs660c32_vco_get_params(*prate, rate, &params))
+		clk_fs660c32_vco_get_rate(*prate, &params, &rate);
+
+	pr_debug("%s: %s new rate %ld [sdiv=0x%x,md=0x%x,pe=0x%x,nsdiv3=%u]\n",
+		 __func__, __clk_get_name(hw->clk),
+		 rate, (unsigned int)params.sdiv,
+		 (unsigned int)params.mdiv,
+		 (unsigned int)params.pe, (unsigned int)params.nsdiv);
+
+	return rate;
+}
+
+static int quadfs_pll_fs660c32_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw);
+	struct stm_fs params;
+	long hwrate = 0;
+	unsigned long flags = 0;
+
+	if (!rate || !parent_rate)
+		return -EINVAL;
+
+	if (!clk_fs660c32_vco_get_params(parent_rate, rate, &params))
+		clk_fs660c32_vco_get_rate(parent_rate, &params, &hwrate);
+
+	pr_debug("%s: %s new rate %ld [ndiv=0x%x]\n",
+		 __func__, __clk_get_name(hw->clk),
+		 hwrate, (unsigned int)params.ndiv);
+
+	if (!hwrate)
+		return -EINVAL;
+
+	pll->ndiv = params.ndiv;
+
+	if (pll->lock)
+		spin_lock_irqsave(pll->lock, flags);
+
+	CLKGEN_WRITE(pll, ndiv, pll->ndiv);
+
+	if (pll->lock)
+		spin_unlock_irqrestore(pll->lock, flags);
+
+	return 0;
+}
+
+static const struct clk_ops st_quadfs_pll_c65_ops = {
+	.enable		= quadfs_pll_enable,
+	.disable	= quadfs_pll_disable,
+	.is_enabled	= quadfs_pll_is_enabled,
+};
+
+static const struct clk_ops st_quadfs_pll_c32_ops = {
+	.enable		= quadfs_pll_enable,
+	.disable	= quadfs_pll_disable,
+	.is_enabled	= quadfs_pll_is_enabled,
+	.recalc_rate	= quadfs_pll_fs660c32_recalc_rate,
+	.round_rate	= quadfs_pll_fs660c32_round_rate,
+	.set_rate	= quadfs_pll_fs660c32_set_rate,
+};
+
+static struct clk * __init st_clk_register_quadfs_pll(
+		const char *name, const char *parent_name,
+		struct clkgen_quadfs_data *quadfs, void __iomem *reg,
+		spinlock_t *lock)
+{
+	struct st_clk_quadfs_pll *pll;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/*
+	 * Sanity check required pointers.
+	 */
+	if (WARN_ON(!name || !parent_name))
+		return ERR_PTR(-EINVAL);
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = quadfs->pll_ops;
+	init.flags = CLK_IS_BASIC;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	pll->data = quadfs;
+	pll->regs_base = reg;
+	pll->lock = lock;
+	pll->hw.init = &init;
+
+	clk = clk_register(NULL, &pll->hw);
+
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+/**
+ * DOC: A digital frequency synthesizer
+ *
+ * Traits of this clock:
+ * prepare - clk_(un)prepare only ensures parent is (un)prepared
+ * enable - clk_enable and clk_disable are functional
+ * rate - set rate is functional
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+/**
+ * struct st_clk_quadfs_fsynth - One clock output from a four channel digital
+ *                                  frequency synthesizer (fsynth) block.
+ *
+ * @hw: handle between common and hardware-specific interfaces
+ *
+ * @nsb: regmap field in the output control register for the digital
+ *       standby of this fsynth channel. This control is active low so
+ *       the channel is in standby when the control bit is cleared.
+ *
+ * @nsdiv: regmap field in the output control register for
+ *          for the optional divide by 3 of this fsynth channel. This control
+ *          is active low so the divide by 3 is active when the control bit is
+ *          cleared and the divide is bypassed when the bit is set.
+ */
+struct st_clk_quadfs_fsynth {
+	struct clk_hw	hw;
+	void __iomem	*regs_base;
+	spinlock_t	*lock;
+	struct clkgen_quadfs_data *data;
+
+	u32 chan;
+	/*
+	 * Cached hardware values from set_rate so we can program the
+	 * hardware in enable. There are two reasons for this:
+	 *
+	 *  1. The registers may not be writable until the parent has been
+	 *     enabled.
+	 *
+	 *  2. It restores the clock rate when a driver does an enable
+	 *     on PM restore, after a suspend to RAM has lost the hardware
+	 *     setup.
+	 */
+	u32 md;
+	u32 pe;
+	u32 sdiv;
+	u32 nsdiv;
+};
+
+#define to_quadfs_fsynth(_hw) \
+	container_of(_hw, struct st_clk_quadfs_fsynth, hw)
+
+static void quadfs_fsynth_program_enable(struct st_clk_quadfs_fsynth *fs)
+{
+	/*
+	 * Pulse the program enable register lsb to make the hardware take
+	 * notice of the new md/pe values with a glitchless transition.
+	 */
+	CLKGEN_WRITE(fs, en[fs->chan], 1);
+	CLKGEN_WRITE(fs, en[fs->chan], 0);
+}
+
+static void quadfs_fsynth_program_rate(struct st_clk_quadfs_fsynth *fs)
+{
+	unsigned long flags = 0;
+
+	/*
+	 * Ensure the md/pe parameters are ignored while we are
+	 * reprogramming them so we can get a glitchless change
+	 * when fine tuning the speed of a running clock.
+	 */
+	CLKGEN_WRITE(fs, en[fs->chan], 0);
+
+	CLKGEN_WRITE(fs, mdiv[fs->chan], fs->md);
+	CLKGEN_WRITE(fs, pe[fs->chan], fs->pe);
+	CLKGEN_WRITE(fs, sdiv[fs->chan], fs->sdiv);
+
+	if (fs->lock)
+		spin_lock_irqsave(fs->lock, flags);
+
+	if (fs->data->nsdiv_present)
+		CLKGEN_WRITE(fs, nsdiv[fs->chan], fs->nsdiv);
+
+	if (fs->lock)
+		spin_unlock_irqrestore(fs->lock, flags);
+}
+
+static int quadfs_fsynth_enable(struct clk_hw *hw)
+{
+	struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
+	unsigned long flags = 0;
+
+	pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk));
+
+	quadfs_fsynth_program_rate(fs);
+
+	if (fs->lock)
+		spin_lock_irqsave(fs->lock, flags);
+
+	CLKGEN_WRITE(fs, nsb[fs->chan], 1);
+
+	if (fs->lock)
+		spin_unlock_irqrestore(fs->lock, flags);
+
+	quadfs_fsynth_program_enable(fs);
+
+	return 0;
+}
+
+static void quadfs_fsynth_disable(struct clk_hw *hw)
+{
+	struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
+	unsigned long flags = 0;
+
+	pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk));
+
+	if (fs->lock)
+		spin_lock_irqsave(fs->lock, flags);
+
+	CLKGEN_WRITE(fs, nsb[fs->chan], 0);
+
+	if (fs->lock)
+		spin_unlock_irqrestore(fs->lock, flags);
+}
+
+static int quadfs_fsynth_is_enabled(struct clk_hw *hw)
+{
+	struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
+	u32 nsb = CLKGEN_READ(fs, nsb[fs->chan]);
+
+	pr_debug("%s: %s enable bit = 0x%x\n",
+		 __func__, __clk_get_name(hw->clk), nsb);
+
+	return !!nsb;
+}
+
+#define P15			(uint64_t)(1 << 15)
+
+static int clk_fs216c65_get_rate(unsigned long input, struct stm_fs *fs,
+		unsigned long *rate)
+{
+	uint64_t res;
+	unsigned long ns;
+	unsigned long nd = 8; /* ndiv stuck@0 => val = 8 */
+	unsigned long s;
+	long m;
+
+	m = fs->mdiv - 32;
+	s = 1 << (fs->sdiv + 1);
+	ns = (fs->nsdiv ? 1 : 3);
+
+	res = (uint64_t)(s * ns * P15 * (uint64_t)(m + 33));
+	res = res - (s * ns * fs->pe);
+	*rate = div64_u64(P15 * nd * input * 32, res);
+
+	return 0;
+}
+
+static int clk_fs432c65_get_rate(unsigned long input, struct stm_fs *fs,
+		unsigned long *rate)
+{
+	uint64_t res;
+	unsigned long nd = 16; /* ndiv value; stuck at 0 (30Mhz input) */
+	long m;
+	unsigned long sd;
+	unsigned long ns;
+
+	m = fs->mdiv - 32;
+	sd = 1 << (fs->sdiv + 1);
+	ns = (fs->nsdiv ? 1 : 3);
+
+	res = (uint64_t)(sd * ns * P15 * (uint64_t)(m + 33));
+	res = res - (sd * ns * fs->pe);
+	*rate = div64_u64(P15 * nd * input * 32, res);
+
+	return 0;
+}
+
+#define P20		(uint64_t)(1 << 20)
+
+static int clk_fs660c32_dig_get_rate(unsigned long input,
+				struct stm_fs *fs, unsigned long *rate)
+{
+	unsigned long s = (1 << fs->sdiv);
+	unsigned long ns;
+	uint64_t res;
+
+	/*
+	 * 'nsdiv' is a register value ('BIN') which is translated
+	 * to a decimal value according to following rules.
+	 *
+	 *     nsdiv      ns.dec
+	 *       0        3
+	 *       1        1
+	 */
+	ns = (fs->nsdiv == 1) ? 1 : 3;
+
+	res = (P20 * (32 + fs->mdiv) + 32 * fs->pe) * s * ns;
+	*rate = (unsigned long)div64_u64(input * P20 * 32, res);
+
+	return 0;
+}
+
+static int quadfs_fsynt_get_hw_value_for_recalc(struct st_clk_quadfs_fsynth *fs,
+		struct stm_fs *params)
+{
+	/*
+	 * Get the initial hardware values for recalc_rate
+	 */
+	params->mdiv	= CLKGEN_READ(fs, mdiv[fs->chan]);
+	params->pe	= CLKGEN_READ(fs, pe[fs->chan]);
+	params->sdiv	= CLKGEN_READ(fs, sdiv[fs->chan]);
+
+	if (fs->data->nsdiv_present)
+		params->nsdiv = CLKGEN_READ(fs, nsdiv[fs->chan]);
+	else
+		params->nsdiv = 1;
+
+	/*
+	 * If All are NULL then assume no clock rate is programmed.
+	 */
+	if (!params->mdiv && !params->pe && !params->sdiv)
+		return 1;
+
+	fs->md = params->mdiv;
+	fs->pe = params->pe;
+	fs->sdiv = params->sdiv;
+	fs->nsdiv = params->nsdiv;
+
+	return 0;
+}
+
+static long quadfs_find_best_rate(struct clk_hw *hw, unsigned long drate,
+				unsigned long prate, struct stm_fs *params)
+{
+	struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
+	int (*clk_fs_get_rate)(unsigned long ,
+				struct stm_fs *, unsigned long *);
+	struct stm_fs prev_params;
+	unsigned long prev_rate, rate = 0;
+	unsigned long diff_rate, prev_diff_rate = ~0;
+	int index;
+
+	clk_fs_get_rate = fs->data->get_rate;
+
+	for (index = 0; index < fs->data->rtbl_cnt; index++) {
+		prev_rate = rate;
+
+		*params = fs->data->rtbl[index];
+		prev_params = *params;
+
+		clk_fs_get_rate(prate, &fs->data->rtbl[index], &rate);
+
+		diff_rate = abs(drate - rate);
+
+		if (diff_rate > prev_diff_rate) {
+			rate = prev_rate;
+			*params = prev_params;
+			break;
+		}
+
+		prev_diff_rate = diff_rate;
+
+		if (drate == rate)
+			return rate;
+	}
+
+
+	if (index == fs->data->rtbl_cnt)
+		*params = prev_params;
+
+	return rate;
+}
+
+static unsigned long quadfs_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
+	unsigned long rate = 0;
+	struct stm_fs params;
+	int (*clk_fs_get_rate)(unsigned long ,
+				struct stm_fs *, unsigned long *);
+
+	clk_fs_get_rate = fs->data->get_rate;
+
+	if (quadfs_fsynt_get_hw_value_for_recalc(fs, &params))
+		return 0;
+
+	if (clk_fs_get_rate(parent_rate, &params, &rate)) {
+		pr_err("%s:%s error calculating rate\n",
+		       __clk_get_name(hw->clk), __func__);
+	}
+
+	pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+
+	return rate;
+}
+
+static long quadfs_round_rate(struct clk_hw *hw, unsigned long rate,
+				     unsigned long *prate)
+{
+	struct stm_fs params;
+
+	rate = quadfs_find_best_rate(hw, rate, *prate, &params);
+
+	pr_debug("%s: %s new rate %ld [sdiv=0x%x,md=0x%x,pe=0x%x,nsdiv3=%u]\n",
+		 __func__, __clk_get_name(hw->clk),
+		 rate, (unsigned int)params.sdiv, (unsigned int)params.mdiv,
+			 (unsigned int)params.pe, (unsigned int)params.nsdiv);
+
+	return rate;
+}
+
+
+static void quadfs_program_and_enable(struct st_clk_quadfs_fsynth *fs,
+		struct stm_fs *params)
+{
+	fs->md = params->mdiv;
+	fs->pe = params->pe;
+	fs->sdiv = params->sdiv;
+	fs->nsdiv = params->nsdiv;
+
+	/*
+	 * In some integrations you can only change the fsynth programming when
+	 * the parent entity containing it is enabled.
+	 */
+	quadfs_fsynth_program_rate(fs);
+	quadfs_fsynth_program_enable(fs);
+}
+
+static int quadfs_set_rate(struct clk_hw *hw, unsigned long rate,
+				  unsigned long parent_rate)
+{
+	struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
+	struct stm_fs params;
+	long hwrate;
+	int uninitialized_var(i);
+
+	if (!rate || !parent_rate)
+		return -EINVAL;
+
+	memset(&params, 0, sizeof(struct stm_fs));
+
+	hwrate = quadfs_find_best_rate(hw, rate, parent_rate, &params);
+	if (!hwrate)
+		return -EINVAL;
+
+	quadfs_program_and_enable(fs, &params);
+
+	return 0;
+}
+
+
+
+static const struct clk_ops st_quadfs_ops = {
+	.enable		= quadfs_fsynth_enable,
+	.disable	= quadfs_fsynth_disable,
+	.is_enabled	= quadfs_fsynth_is_enabled,
+	.round_rate	= quadfs_round_rate,
+	.set_rate	= quadfs_set_rate,
+	.recalc_rate	= quadfs_recalc_rate,
+};
+
+static struct clk * __init st_clk_register_quadfs_fsynth(
+		const char *name, const char *parent_name,
+		struct clkgen_quadfs_data *quadfs, void __iomem *reg, u32 chan,
+		spinlock_t *lock)
+{
+	struct st_clk_quadfs_fsynth *fs;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/*
+	 * Sanity check required pointers, note that nsdiv3 is optional.
+	 */
+	if (WARN_ON(!name || !parent_name))
+		return ERR_PTR(-EINVAL);
+
+	fs = kzalloc(sizeof(*fs), GFP_KERNEL);
+	if (!fs)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &st_quadfs_ops;
+	init.flags = CLK_GET_RATE_NOCACHE | CLK_IS_BASIC;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	fs->data = quadfs;
+	fs->regs_base = reg;
+	fs->chan = chan;
+	fs->lock = lock;
+	fs->hw.init = &init;
+
+	clk = clk_register(NULL, &fs->hw);
+
+	if (IS_ERR(clk))
+		kfree(fs);
+
+	return clk;
+}
+
+static struct of_device_id quadfs_of_match[] = {
+	{
+		.compatible = "st,stih416-quadfs216",
+		.data = (void *)&st_fs216c65_416
+	},
+	{
+		.compatible = "st,stih416-quadfs432",
+		.data = (void *)&st_fs432c65_416
+	},
+	{
+		.compatible = "st,stih416-quadfs660-E",
+		.data = (void *)&st_fs660c32_E_416
+	},
+	{
+		.compatible = "st,stih416-quadfs660-F",
+		.data = (void *)&st_fs660c32_F_416
+	},
+	{}
+};
+
+static void __init st_of_create_quadfs_fsynths(
+		struct device_node *np, const char *pll_name,
+		struct clkgen_quadfs_data *quadfs, void __iomem *reg,
+		spinlock_t *lock)
+{
+	struct clk_onecell_data *clk_data;
+	int fschan;
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return;
+
+	clk_data->clk_num = QUADFS_MAX_CHAN;
+	clk_data->clks = kzalloc(QUADFS_MAX_CHAN * sizeof(struct clk *),
+				 GFP_KERNEL);
+
+	if (!clk_data->clks) {
+		kfree(clk_data);
+		return;
+	}
+
+	for (fschan = 0; fschan < QUADFS_MAX_CHAN; fschan++) {
+		struct clk *clk;
+		const char *clk_name;
+
+		if (of_property_read_string_index(np, "clock-output-names",
+						  fschan, &clk_name)) {
+			break;
+		}
+
+		/*
+		 * If we read an empty clock name then the channel is unused
+		 */
+		if (*clk_name == '\0')
+			continue;
+
+		clk = st_clk_register_quadfs_fsynth(clk_name, pll_name,
+				quadfs, reg, fschan, lock);
+
+		/*
+		 * If there was an error registering this clock output, clean
+		 * up and move on to the next one.
+		 */
+		if (!IS_ERR(clk)) {
+			clk_data->clks[fschan] = clk;
+			pr_debug("%s: parent %s rate %u\n",
+				__clk_get_name(clk),
+				__clk_get_name(clk_get_parent(clk)),
+				(unsigned int)clk_get_rate(clk));
+		}
+	}
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+}
+
+static void __init st_of_quadfs_setup(struct device_node *np)
+{
+	const struct of_device_id *match;
+	struct clk *clk;
+	const char *pll_name, *clk_parent_name;
+	void __iomem *reg;
+	spinlock_t *lock;
+
+	match = of_match_node(quadfs_of_match, np);
+	if (WARN_ON(!match))
+		return;
+
+	reg = of_iomap(np, 0);
+	if (!reg)
+		return;
+
+	clk_parent_name = of_clk_get_parent_name(np, 0);
+	if (!clk_parent_name)
+		return;
+
+	pll_name = kasprintf(GFP_KERNEL, "%s.pll", np->name);
+	if (!pll_name)
+		return;
+
+	lock = kzalloc(sizeof(*lock), GFP_KERNEL);
+	if (!lock)
+		goto err_exit;
+
+	spin_lock_init(lock);
+
+	clk = st_clk_register_quadfs_pll(pll_name, clk_parent_name,
+			(struct clkgen_quadfs_data *) match->data, reg, lock);
+	if (IS_ERR(clk))
+		goto err_exit;
+	else
+		pr_debug("%s: parent %s rate %u\n",
+			__clk_get_name(clk),
+			__clk_get_name(clk_get_parent(clk)),
+			(unsigned int)clk_get_rate(clk));
+
+	st_of_create_quadfs_fsynths(np, pll_name,
+				    (struct clkgen_quadfs_data *)match->data,
+				    reg, lock);
+
+err_exit:
+	kfree(pll_name); /* No longer need local copy of the PLL name */
+}
+CLK_OF_DECLARE(quadfs, "st,quadfs", st_of_quadfs_setup);
-- 
1.9.0

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

* [PATCH v0 05/15] drivers: clk: st: Support for ClockGenA9/DDR/GPU
  2014-02-27 15:24 ` Gabriel FERNANDEZ
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  -1 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: mturquette, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, rob, linux, devicetree, linux-doc, linux-kernel,
	linux-arm-kernel
  Cc: Lee Jones, Gabriel Fernandez, Pankaj Dev

The patch added support for DT registration of ClockGenA9/DDR/GPU

ClockgenA9/DDR : It includes c32 type PLL (also in ClockgenA1x), hence
only CLK_OF_DECLARE implementation is required.

ClockgenGPU : It includes c65 type PLL (also in ClockgenAx), hence
only CLK_OF_DECLARE implementation is required.

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 drivers/clk/st/clkgen-pll.c | 139 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 139 insertions(+)

diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c
index c6b38b0..bca0a0b 100644
--- a/drivers/clk/st/clkgen-pll.c
+++ b/drivers/clk/st/clkgen-pll.c
@@ -110,6 +110,76 @@ static struct clkgen_pll_data st_pll3200c32_a1x_1 = {
 	.ops		= &stm_pll3200c32_ops,
 };
 
+/* 415 specific */
+static struct clkgen_pll_data st_pll3200c32_a9_415 = {
+	.pdn_status	= CLKGEN_FIELD(0x0,	0x1,			0),
+	.locked_status	= CLKGEN_FIELD(0x6C,	0x1,			0),
+	.ndiv		= CLKGEN_FIELD(0x0,	C32_NDIV_MASK,		9),
+	.idf		= CLKGEN_FIELD(0x0,	C32_IDF_MASK,		22),
+	.num_odfs = 1,
+	.odf =		{ CLKGEN_FIELD(0x0,	C32_ODF_MASK,		3) },
+	.odf_gate =	{ CLKGEN_FIELD(0x0,	0x1,			28) },
+	.ops		= &stm_pll3200c32_ops,
+};
+
+static struct clkgen_pll_data st_pll3200c32_ddr_415 = {
+	.pdn_status	= CLKGEN_FIELD(0x0,	0x1,			0),
+	.locked_status	= CLKGEN_FIELD(0x100,	0x1,			0),
+	.ndiv		= CLKGEN_FIELD(0x8,	C32_NDIV_MASK,		0),
+	.idf		= CLKGEN_FIELD(0x0,	C32_IDF_MASK,		25),
+	.num_odfs = 2,
+	.odf		= { CLKGEN_FIELD(0x8,	C32_ODF_MASK,		8),
+			    CLKGEN_FIELD(0x8,	C32_ODF_MASK,		14) },
+	.odf_gate	= { CLKGEN_FIELD(0x4,	0x1,			28),
+			    CLKGEN_FIELD(0x4,	0x1,			29) },
+	.ops		= &stm_pll3200c32_ops,
+};
+
+static struct clkgen_pll_data st_pll1200c32_gpu_415 = {
+	.pdn_status	= CLKGEN_FIELD(0x144,	0x1,			3),
+	.locked_status	= CLKGEN_FIELD(0x168,	0x1,			0),
+	.ldf		= CLKGEN_FIELD(0x0,	C32_LDF_MASK,		3),
+	.idf		= CLKGEN_FIELD(0x0,	C32_IDF_MASK,		0),
+	.num_odfs = 0,
+	.odf		= { CLKGEN_FIELD(0x0,	C32_ODF_MASK,		10) },
+	.ops		= &st_pll1200c32_ops,
+};
+
+/* 416 specific */
+static struct clkgen_pll_data st_pll3200c32_a9_416 = {
+	.pdn_status	= CLKGEN_FIELD(0x0,	0x1,			0),
+	.locked_status	= CLKGEN_FIELD(0x6C,	0x1,			0),
+	.ndiv		= CLKGEN_FIELD(0x8,	C32_NDIV_MASK,		0),
+	.idf		= CLKGEN_FIELD(0x0,	C32_IDF_MASK,		25),
+	.num_odfs = 1,
+	.odf		= { CLKGEN_FIELD(0x8,	C32_ODF_MASK,		8) },
+	.odf_gate	= { CLKGEN_FIELD(0x4,	0x1,			28) },
+	.ops		= &stm_pll3200c32_ops,
+};
+
+static struct clkgen_pll_data st_pll3200c32_ddr_416 = {
+	.pdn_status	= CLKGEN_FIELD(0x0,	0x1,			0),
+	.locked_status	= CLKGEN_FIELD(0x10C,	0x1,			0),
+	.ndiv		= CLKGEN_FIELD(0x8,	C32_NDIV_MASK,		0),
+	.idf		= CLKGEN_FIELD(0x0,	C32_IDF_MASK,		25),
+	.num_odfs = 2,
+	.odf		= { CLKGEN_FIELD(0x8,	C32_ODF_MASK,		8),
+			    CLKGEN_FIELD(0x8,	C32_ODF_MASK,		14) },
+	.odf_gate	= { CLKGEN_FIELD(0x4,	0x1,			28),
+			    CLKGEN_FIELD(0x4,	0x1,			29) },
+	.ops		= &stm_pll3200c32_ops,
+};
+
+static struct clkgen_pll_data st_pll1200c32_gpu_416 = {
+	.pdn_status	= CLKGEN_FIELD(0x8E4,	0x1,			3),
+	.locked_status	= CLKGEN_FIELD(0x90C,	0x1,			0),
+	.ldf		= CLKGEN_FIELD(0x0,	C32_LDF_MASK,		3),
+	.idf		= CLKGEN_FIELD(0x0,	C32_IDF_MASK,		0),
+	.num_odfs = 0,
+	.odf		= { CLKGEN_FIELD(0x0,	C32_ODF_MASK,		10) },
+	.ops		= &st_pll1200c32_ops,
+};
+
 /**
  * DOC: Clock Generated by PLL, rate set and enabled by bootloader
  *
@@ -484,6 +554,22 @@ static struct of_device_id c32_pll_of_match[] = {
 		.compatible = "st,plls-c32-a1x-1",
 		.data = &st_pll3200c32_a1x_1,
 	},
+	{
+		.compatible = "st,stih415-plls-c32-a9",
+		.data = &st_pll3200c32_a9_415,
+	},
+	{
+		.compatible = "st,stih415-plls-c32-ddr",
+		.data = &st_pll3200c32_ddr_415,
+	},
+	{
+		.compatible = "st,stih416-plls-c32-a9",
+		.data = &st_pll3200c32_a9_416,
+	},
+	{
+		.compatible = "st,stih416-plls-c32-ddr",
+		.data = &st_pll3200c32_ddr_416,
+	},
 	{}
 };
 
@@ -557,3 +643,56 @@ err:
 	kfree(clk_data);
 }
 CLK_OF_DECLARE(clkgen_c32_pll, "st,clkgen-plls-c32", clkgen_c32_pll_setup);
+
+static struct of_device_id c32_gpu_pll_of_match[] = {
+	{
+		.compatible = "st,stih415-gpu-pll-c32",
+		.data = &st_pll1200c32_gpu_415,
+	},
+	{
+		.compatible = "st,stih416-gpu-pll-c32",
+		.data = &st_pll1200c32_gpu_416,
+	},
+};
+
+static void __init clkgengpu_c32_pll_setup(struct device_node *np)
+{
+	const struct of_device_id *match;
+	struct clk *clk;
+	const char *parent_name;
+	void __iomem *reg;
+	const char *clk_name;
+	struct clkgen_pll_data	*data;
+
+	match = of_match_node(c32_gpu_pll_of_match, np);
+	if (!match) {
+		pr_err("%s: No matching data\n", __func__);
+		return;
+	}
+
+	data = (struct clkgen_pll_data *)match->data;
+
+	parent_name = of_clk_get_parent_name(np, 0);
+	if (!parent_name)
+		return;
+
+	reg = clkgen_get_register_base(np);
+	if (!reg)
+		return;
+
+	if (of_property_read_string_index(np, "clock-output-names",
+					  0, &clk_name))
+		return;
+
+	/*
+	 * PLL 1200MHz output
+	 */
+	clk = clkgen_pll_register(parent_name, data, reg, clk_name);
+
+	if (!IS_ERR(clk))
+		of_clk_add_provider(np, of_clk_src_simple_get, clk);
+
+	return;
+}
+CLK_OF_DECLARE(clkgengpu_c32_pll,
+	       "st,clkgengpu-pll-c32", clkgengpu_c32_pll_setup);
-- 
1.9.0


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

* [PATCH v0 05/15] drivers: clk: st: Support for ClockGenA9/DDR/GPU
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

The patch added support for DT registration of ClockGenA9/DDR/GPU

ClockgenA9/DDR : It includes c32 type PLL (also in ClockgenA1x), hence
only CLK_OF_DECLARE implementation is required.

ClockgenGPU : It includes c65 type PLL (also in ClockgenAx), hence
only CLK_OF_DECLARE implementation is required.

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 drivers/clk/st/clkgen-pll.c | 139 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 139 insertions(+)

diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c
index c6b38b0..bca0a0b 100644
--- a/drivers/clk/st/clkgen-pll.c
+++ b/drivers/clk/st/clkgen-pll.c
@@ -110,6 +110,76 @@ static struct clkgen_pll_data st_pll3200c32_a1x_1 = {
 	.ops		= &stm_pll3200c32_ops,
 };
 
+/* 415 specific */
+static struct clkgen_pll_data st_pll3200c32_a9_415 = {
+	.pdn_status	= CLKGEN_FIELD(0x0,	0x1,			0),
+	.locked_status	= CLKGEN_FIELD(0x6C,	0x1,			0),
+	.ndiv		= CLKGEN_FIELD(0x0,	C32_NDIV_MASK,		9),
+	.idf		= CLKGEN_FIELD(0x0,	C32_IDF_MASK,		22),
+	.num_odfs = 1,
+	.odf =		{ CLKGEN_FIELD(0x0,	C32_ODF_MASK,		3) },
+	.odf_gate =	{ CLKGEN_FIELD(0x0,	0x1,			28) },
+	.ops		= &stm_pll3200c32_ops,
+};
+
+static struct clkgen_pll_data st_pll3200c32_ddr_415 = {
+	.pdn_status	= CLKGEN_FIELD(0x0,	0x1,			0),
+	.locked_status	= CLKGEN_FIELD(0x100,	0x1,			0),
+	.ndiv		= CLKGEN_FIELD(0x8,	C32_NDIV_MASK,		0),
+	.idf		= CLKGEN_FIELD(0x0,	C32_IDF_MASK,		25),
+	.num_odfs = 2,
+	.odf		= { CLKGEN_FIELD(0x8,	C32_ODF_MASK,		8),
+			    CLKGEN_FIELD(0x8,	C32_ODF_MASK,		14) },
+	.odf_gate	= { CLKGEN_FIELD(0x4,	0x1,			28),
+			    CLKGEN_FIELD(0x4,	0x1,			29) },
+	.ops		= &stm_pll3200c32_ops,
+};
+
+static struct clkgen_pll_data st_pll1200c32_gpu_415 = {
+	.pdn_status	= CLKGEN_FIELD(0x144,	0x1,			3),
+	.locked_status	= CLKGEN_FIELD(0x168,	0x1,			0),
+	.ldf		= CLKGEN_FIELD(0x0,	C32_LDF_MASK,		3),
+	.idf		= CLKGEN_FIELD(0x0,	C32_IDF_MASK,		0),
+	.num_odfs = 0,
+	.odf		= { CLKGEN_FIELD(0x0,	C32_ODF_MASK,		10) },
+	.ops		= &st_pll1200c32_ops,
+};
+
+/* 416 specific */
+static struct clkgen_pll_data st_pll3200c32_a9_416 = {
+	.pdn_status	= CLKGEN_FIELD(0x0,	0x1,			0),
+	.locked_status	= CLKGEN_FIELD(0x6C,	0x1,			0),
+	.ndiv		= CLKGEN_FIELD(0x8,	C32_NDIV_MASK,		0),
+	.idf		= CLKGEN_FIELD(0x0,	C32_IDF_MASK,		25),
+	.num_odfs = 1,
+	.odf		= { CLKGEN_FIELD(0x8,	C32_ODF_MASK,		8) },
+	.odf_gate	= { CLKGEN_FIELD(0x4,	0x1,			28) },
+	.ops		= &stm_pll3200c32_ops,
+};
+
+static struct clkgen_pll_data st_pll3200c32_ddr_416 = {
+	.pdn_status	= CLKGEN_FIELD(0x0,	0x1,			0),
+	.locked_status	= CLKGEN_FIELD(0x10C,	0x1,			0),
+	.ndiv		= CLKGEN_FIELD(0x8,	C32_NDIV_MASK,		0),
+	.idf		= CLKGEN_FIELD(0x0,	C32_IDF_MASK,		25),
+	.num_odfs = 2,
+	.odf		= { CLKGEN_FIELD(0x8,	C32_ODF_MASK,		8),
+			    CLKGEN_FIELD(0x8,	C32_ODF_MASK,		14) },
+	.odf_gate	= { CLKGEN_FIELD(0x4,	0x1,			28),
+			    CLKGEN_FIELD(0x4,	0x1,			29) },
+	.ops		= &stm_pll3200c32_ops,
+};
+
+static struct clkgen_pll_data st_pll1200c32_gpu_416 = {
+	.pdn_status	= CLKGEN_FIELD(0x8E4,	0x1,			3),
+	.locked_status	= CLKGEN_FIELD(0x90C,	0x1,			0),
+	.ldf		= CLKGEN_FIELD(0x0,	C32_LDF_MASK,		3),
+	.idf		= CLKGEN_FIELD(0x0,	C32_IDF_MASK,		0),
+	.num_odfs = 0,
+	.odf		= { CLKGEN_FIELD(0x0,	C32_ODF_MASK,		10) },
+	.ops		= &st_pll1200c32_ops,
+};
+
 /**
  * DOC: Clock Generated by PLL, rate set and enabled by bootloader
  *
@@ -484,6 +554,22 @@ static struct of_device_id c32_pll_of_match[] = {
 		.compatible = "st,plls-c32-a1x-1",
 		.data = &st_pll3200c32_a1x_1,
 	},
+	{
+		.compatible = "st,stih415-plls-c32-a9",
+		.data = &st_pll3200c32_a9_415,
+	},
+	{
+		.compatible = "st,stih415-plls-c32-ddr",
+		.data = &st_pll3200c32_ddr_415,
+	},
+	{
+		.compatible = "st,stih416-plls-c32-a9",
+		.data = &st_pll3200c32_a9_416,
+	},
+	{
+		.compatible = "st,stih416-plls-c32-ddr",
+		.data = &st_pll3200c32_ddr_416,
+	},
 	{}
 };
 
@@ -557,3 +643,56 @@ err:
 	kfree(clk_data);
 }
 CLK_OF_DECLARE(clkgen_c32_pll, "st,clkgen-plls-c32", clkgen_c32_pll_setup);
+
+static struct of_device_id c32_gpu_pll_of_match[] = {
+	{
+		.compatible = "st,stih415-gpu-pll-c32",
+		.data = &st_pll1200c32_gpu_415,
+	},
+	{
+		.compatible = "st,stih416-gpu-pll-c32",
+		.data = &st_pll1200c32_gpu_416,
+	},
+};
+
+static void __init clkgengpu_c32_pll_setup(struct device_node *np)
+{
+	const struct of_device_id *match;
+	struct clk *clk;
+	const char *parent_name;
+	void __iomem *reg;
+	const char *clk_name;
+	struct clkgen_pll_data	*data;
+
+	match = of_match_node(c32_gpu_pll_of_match, np);
+	if (!match) {
+		pr_err("%s: No matching data\n", __func__);
+		return;
+	}
+
+	data = (struct clkgen_pll_data *)match->data;
+
+	parent_name = of_clk_get_parent_name(np, 0);
+	if (!parent_name)
+		return;
+
+	reg = clkgen_get_register_base(np);
+	if (!reg)
+		return;
+
+	if (of_property_read_string_index(np, "clock-output-names",
+					  0, &clk_name))
+		return;
+
+	/*
+	 * PLL 1200MHz output
+	 */
+	clk = clkgen_pll_register(parent_name, data, reg, clk_name);
+
+	if (!IS_ERR(clk))
+		of_clk_add_provider(np, of_clk_src_simple_get, clk);
+
+	return;
+}
+CLK_OF_DECLARE(clkgengpu_c32_pll,
+	       "st,clkgengpu-pll-c32", clkgengpu_c32_pll_setup);
-- 
1.9.0

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

* [PATCH v0 06/15] drivers: clk: st: Support for A9 MUX clocks
  2014-02-27 15:24 ` Gabriel FERNANDEZ
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  -1 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: mturquette, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, rob, linux, devicetree, linux-doc, linux-kernel,
	linux-arm-kernel
  Cc: Lee Jones, Gabriel Fernandez, Pankaj Dev

The patch supports the A9-mux clocks used by ClockGenA9

A9-mux clock : Multiplexer inside ClockGenA9. A9 clock can be driven by
either PLL or External clock (with an optional divide-by-2). This is
implemented as 3-parent clock : PLL, Ext-clk OR Ext-clk/2

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
---
 drivers/clk/st/clkgen-mux.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c
index 7ccff62..a329906 100644
--- a/drivers/clk/st/clkgen-mux.c
+++ b/drivers/clk/st/clkgen-mux.c
@@ -570,6 +570,17 @@ static struct clkgen_mux_data clkgen_mux_c_vcc_sd_416 = {
 	.lock = &clkgenf_lock,
 };
 
+static struct clkgen_mux_data stih415_a9_mux_data = {
+	.offset = 0,
+	.shift = 1,
+	.width = 2,
+};
+static struct clkgen_mux_data stih416_a9_mux_data = {
+	.offset = 0,
+	.shift = 0,
+	.width = 2,
+};
+
 static struct of_device_id mux_of_match[] = {
 	{
 		.compatible = "st,stih416-clkgenc-vcc-hd",
@@ -591,6 +602,14 @@ static struct of_device_id mux_of_match[] = {
 		.compatible = "st,stih416-clkgenf-vcc-sd",
 		.data = &clkgen_mux_c_vcc_sd_416,
 	},
+	{
+		.compatible = "st,stih415-clkgen-a9-mux",
+		.data = &stih415_a9_mux_data,
+	},
+	{
+		.compatible = "st,stih416-clkgen-a9-mux",
+		.data = &stih416_a9_mux_data,
+	},
 	{}
 };
 
-- 
1.9.0


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

* [PATCH v0 06/15] drivers: clk: st: Support for A9 MUX clocks
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

The patch supports the A9-mux clocks used by ClockGenA9

A9-mux clock : Multiplexer inside ClockGenA9. A9 clock can be driven by
either PLL or External clock (with an optional divide-by-2). This is
implemented as 3-parent clock : PLL, Ext-clk OR Ext-clk/2

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
---
 drivers/clk/st/clkgen-mux.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c
index 7ccff62..a329906 100644
--- a/drivers/clk/st/clkgen-mux.c
+++ b/drivers/clk/st/clkgen-mux.c
@@ -570,6 +570,17 @@ static struct clkgen_mux_data clkgen_mux_c_vcc_sd_416 = {
 	.lock = &clkgenf_lock,
 };
 
+static struct clkgen_mux_data stih415_a9_mux_data = {
+	.offset = 0,
+	.shift = 1,
+	.width = 2,
+};
+static struct clkgen_mux_data stih416_a9_mux_data = {
+	.offset = 0,
+	.shift = 0,
+	.width = 2,
+};
+
 static struct of_device_id mux_of_match[] = {
 	{
 		.compatible = "st,stih416-clkgenc-vcc-hd",
@@ -591,6 +602,14 @@ static struct of_device_id mux_of_match[] = {
 		.compatible = "st,stih416-clkgenf-vcc-sd",
 		.data = &clkgen_mux_c_vcc_sd_416,
 	},
+	{
+		.compatible = "st,stih415-clkgen-a9-mux",
+		.data = &stih415_a9_mux_data,
+	},
+	{
+		.compatible = "st,stih416-clkgen-a9-mux",
+		.data = &stih416_a9_mux_data,
+	},
 	{}
 };
 
-- 
1.9.0

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

* [PATCH v0 07/15] clk: st: Adds divmux and prediv clock binding
  2014-02-27 15:24 ` Gabriel FERNANDEZ
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  -1 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: mturquette, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, rob, linux, devicetree, linux-doc, linux-kernel,
	linux-arm-kernel
  Cc: Lee Jones, Gabriel Fernandez

Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 .../bindings/clock/st/st,clkgen-divmux.txt         | 49 +++++++++++++
 .../bindings/clock/st/st,clkgen-prediv.txt         | 36 ++++++++++
 .../devicetree/bindings/clock/st/st,clkgen.txt     | 83 ++++++++++++++++++++++
 3 files changed, 168 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen.txt

diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt
new file mode 100644
index 0000000..ae56315
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt
@@ -0,0 +1,49 @@
+Binding for a ST divider and multiplexer clock driver.
+
+This binding uses the common clock binding[1].
+Base address is located to the parent node. See clock binding[2]
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/st/st,clkgen.txt
+
+Required properties:
+
+- compatible : shall be:
+	"st,clkgena-divmux-c65-hs",	"st,clkgena-divmux"
+	"st,clkgena-divmux-c65-ls",	"st,clkgena-divmux"
+	"st,clkgena-divmux-c32-odf0",	"st,clkgena-divmux"
+	"st,clkgena-divmux-c32-odf1",	"st,clkgena-divmux"
+	"st,clkgena-divmux-c32-odf2",	"st,clkgena-divmux"
+	"st,clkgena-divmux-c32-odf3",	"st,clkgena-divmux"
+
+- #clock-cells : From common clock binding; shall be set to 1.
+
+- clocks : From common clock binding
+
+- clock-output-names : From common clock binding.
+
+Example:
+
+	clockgenA@fd345000 {
+		reg = <0xfd345000 0xb50>;
+
+		CLK_M_A1_DIV1: CLK_M_A1_DIV1 {
+			#clock-cells = <1>;
+			compatible = "st,clkgena-divmux-c32-odf1",
+				     "st,clkgena-divmux";
+
+			clocks = <&CLK_M_A1_OSC_PREDIV>,
+				 <&CLK_M_A1_PLL0 1>, /* PLL0 PHI1 */
+				 <&CLK_M_A1_PLL1 1>; /* PLL1 PHI1 */
+
+			clock-output-names = "CLK_M_RX_ICN_TS",
+					     "CLK_M_RX_ICN_VDP_0",
+					     "", /* Unused */
+					     "CLK_M_PRV_T1_BUS",
+					     "CLK_M_ICN_REG_12",
+					     "CLK_M_ICN_REG_10",
+					     "", /* Unused */
+					     "CLK_M_ICN_ST231";
+		};
+	};
+
diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt
new file mode 100644
index 0000000..566c9d7
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt
@@ -0,0 +1,36 @@
+Binding for a ST pre-divider clock driver.
+
+This binding uses the common clock binding[1].
+Base address is located to the parent node. See clock binding[2]
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/st/st,clkgen.txt
+
+Required properties:
+
+- compatible : shall be:
+	"st,clkgena-prediv-c65",	"st,clkgena-prediv"
+	"st,clkgena-prediv-c32",	"st,clkgena-prediv"
+
+- #clock-cells : From common clock binding; shall be set to 0.
+
+- clocks : From common clock binding
+
+- clock-output-names : From common clock binding.
+
+Example:
+
+	clockgenA@fd345000 {
+		reg = <0xfd345000 0xb50>;
+
+		CLK_M_A2_OSC_PREDIV: CLK_M_A2_OSC_PREDIV {
+			#clock-cells = <0>;
+			compatible = "st,clkgena-prediv-c32",
+				     "st,clkgena-prediv";
+
+			clocks = <&CLK_SYSIN>;
+
+			clock-output-names = "CLK_M_A2_OSC_PREDIV";
+		};
+	};
+
diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen.txt
new file mode 100644
index 0000000..49ec5ae
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/st/st,clkgen.txt
@@ -0,0 +1,83 @@
+Binding for a Clockgen hardware block found on
+certain STMicroelectronics consumer electronics SoC devices.
+
+A Clockgen node can contain pll, diviser or multiplexer nodes.
+
+We will find only the base address of the Clockgen, this base
+address is common of all subnode.
+
+	clockgen_node {
+		reg = <>;
+
+		pll_node {
+			...
+		};
+
+		prediv_node {
+			...
+		};
+
+		divmux_node {
+			...
+		};
+
+		quadfs_node {
+			...
+		};
+		...
+	};
+
+This binding uses the common clock binding[1].
+Each subnode should use the binding discribe in [2]..[4]
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/st,quadfs.txt
+[3] Documentation/devicetree/bindings/clock/st,quadfs.txt
+[4] Documentation/devicetree/bindings/clock/st,quadfs.txt
+
+Required properties:
+- reg : A Base address and length of the register set.
+
+Example:
+
+	clockgenA@fee62000 {
+
+		reg = <0xfee62000 0xb48>;
+
+		CLK_S_A0_PLL: CLK_S_A0_PLL {
+			#clock-cells = <1>;
+			compatible = "st,clkgena-plls-c65";
+
+			clocks = <&CLK_SYSIN>;
+
+			clock-output-names = "CLK_S_A0_PLL0_HS",
+					     "CLK_S_A0_PLL0_LS",
+					     "CLK_S_A0_PLL1";
+		};
+
+		CLK_S_A0_OSC_PREDIV: CLK_S_A0_OSC_PREDIV {
+			#clock-cells = <0>;
+			compatible = "st,clkgena-prediv-c65",
+				     "st,clkgena-prediv";
+
+			clocks = <&CLK_SYSIN>;
+
+			clock-output-names = "CLK_S_A0_OSC_PREDIV";
+		};
+
+		CLK_S_A0_HS: CLK_S_A0_HS {
+			#clock-cells = <1>;
+			compatible = "st,clkgena-divmux-c65-hs",
+				     "st,clkgena-divmux";
+
+			clocks = <&CLK_S_A0_OSC_PREDIV>,
+				 <&CLK_S_A0_PLL 0>, /* PLL0 HS */
+				 <&CLK_S_A0_PLL 2>; /* PLL1 */
+
+			clock-output-names = "CLK_S_FDMA_0",
+					     "CLK_S_FDMA_1",
+					     ""; /* CLK_S_JIT_SENSE */
+					     /* Fourth output unused */
+		};
+	};
+
-- 
1.9.0


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

* [PATCH v0 07/15] clk: st: Adds divmux and prediv clock binding
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 .../bindings/clock/st/st,clkgen-divmux.txt         | 49 +++++++++++++
 .../bindings/clock/st/st,clkgen-prediv.txt         | 36 ++++++++++
 .../devicetree/bindings/clock/st/st,clkgen.txt     | 83 ++++++++++++++++++++++
 3 files changed, 168 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen.txt

diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt
new file mode 100644
index 0000000..ae56315
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt
@@ -0,0 +1,49 @@
+Binding for a ST divider and multiplexer clock driver.
+
+This binding uses the common clock binding[1].
+Base address is located to the parent node. See clock binding[2]
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/st/st,clkgen.txt
+
+Required properties:
+
+- compatible : shall be:
+	"st,clkgena-divmux-c65-hs",	"st,clkgena-divmux"
+	"st,clkgena-divmux-c65-ls",	"st,clkgena-divmux"
+	"st,clkgena-divmux-c32-odf0",	"st,clkgena-divmux"
+	"st,clkgena-divmux-c32-odf1",	"st,clkgena-divmux"
+	"st,clkgena-divmux-c32-odf2",	"st,clkgena-divmux"
+	"st,clkgena-divmux-c32-odf3",	"st,clkgena-divmux"
+
+- #clock-cells : From common clock binding; shall be set to 1.
+
+- clocks : From common clock binding
+
+- clock-output-names : From common clock binding.
+
+Example:
+
+	clockgenA at fd345000 {
+		reg = <0xfd345000 0xb50>;
+
+		CLK_M_A1_DIV1: CLK_M_A1_DIV1 {
+			#clock-cells = <1>;
+			compatible = "st,clkgena-divmux-c32-odf1",
+				     "st,clkgena-divmux";
+
+			clocks = <&CLK_M_A1_OSC_PREDIV>,
+				 <&CLK_M_A1_PLL0 1>, /* PLL0 PHI1 */
+				 <&CLK_M_A1_PLL1 1>; /* PLL1 PHI1 */
+
+			clock-output-names = "CLK_M_RX_ICN_TS",
+					     "CLK_M_RX_ICN_VDP_0",
+					     "", /* Unused */
+					     "CLK_M_PRV_T1_BUS",
+					     "CLK_M_ICN_REG_12",
+					     "CLK_M_ICN_REG_10",
+					     "", /* Unused */
+					     "CLK_M_ICN_ST231";
+		};
+	};
+
diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt
new file mode 100644
index 0000000..566c9d7
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt
@@ -0,0 +1,36 @@
+Binding for a ST pre-divider clock driver.
+
+This binding uses the common clock binding[1].
+Base address is located to the parent node. See clock binding[2]
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/st/st,clkgen.txt
+
+Required properties:
+
+- compatible : shall be:
+	"st,clkgena-prediv-c65",	"st,clkgena-prediv"
+	"st,clkgena-prediv-c32",	"st,clkgena-prediv"
+
+- #clock-cells : From common clock binding; shall be set to 0.
+
+- clocks : From common clock binding
+
+- clock-output-names : From common clock binding.
+
+Example:
+
+	clockgenA at fd345000 {
+		reg = <0xfd345000 0xb50>;
+
+		CLK_M_A2_OSC_PREDIV: CLK_M_A2_OSC_PREDIV {
+			#clock-cells = <0>;
+			compatible = "st,clkgena-prediv-c32",
+				     "st,clkgena-prediv";
+
+			clocks = <&CLK_SYSIN>;
+
+			clock-output-names = "CLK_M_A2_OSC_PREDIV";
+		};
+	};
+
diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen.txt
new file mode 100644
index 0000000..49ec5ae
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/st/st,clkgen.txt
@@ -0,0 +1,83 @@
+Binding for a Clockgen hardware block found on
+certain STMicroelectronics consumer electronics SoC devices.
+
+A Clockgen node can contain pll, diviser or multiplexer nodes.
+
+We will find only the base address of the Clockgen, this base
+address is common of all subnode.
+
+	clockgen_node {
+		reg = <>;
+
+		pll_node {
+			...
+		};
+
+		prediv_node {
+			...
+		};
+
+		divmux_node {
+			...
+		};
+
+		quadfs_node {
+			...
+		};
+		...
+	};
+
+This binding uses the common clock binding[1].
+Each subnode should use the binding discribe in [2]..[4]
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/st,quadfs.txt
+[3] Documentation/devicetree/bindings/clock/st,quadfs.txt
+[4] Documentation/devicetree/bindings/clock/st,quadfs.txt
+
+Required properties:
+- reg : A Base address and length of the register set.
+
+Example:
+
+	clockgenA at fee62000 {
+
+		reg = <0xfee62000 0xb48>;
+
+		CLK_S_A0_PLL: CLK_S_A0_PLL {
+			#clock-cells = <1>;
+			compatible = "st,clkgena-plls-c65";
+
+			clocks = <&CLK_SYSIN>;
+
+			clock-output-names = "CLK_S_A0_PLL0_HS",
+					     "CLK_S_A0_PLL0_LS",
+					     "CLK_S_A0_PLL1";
+		};
+
+		CLK_S_A0_OSC_PREDIV: CLK_S_A0_OSC_PREDIV {
+			#clock-cells = <0>;
+			compatible = "st,clkgena-prediv-c65",
+				     "st,clkgena-prediv";
+
+			clocks = <&CLK_SYSIN>;
+
+			clock-output-names = "CLK_S_A0_OSC_PREDIV";
+		};
+
+		CLK_S_A0_HS: CLK_S_A0_HS {
+			#clock-cells = <1>;
+			compatible = "st,clkgena-divmux-c65-hs",
+				     "st,clkgena-divmux";
+
+			clocks = <&CLK_S_A0_OSC_PREDIV>,
+				 <&CLK_S_A0_PLL 0>, /* PLL0 HS */
+				 <&CLK_S_A0_PLL 2>; /* PLL1 */
+
+			clock-output-names = "CLK_S_FDMA_0",
+					     "CLK_S_FDMA_1",
+					     ""; /* CLK_S_JIT_SENSE */
+					     /* Fourth output unused */
+		};
+	};
+
-- 
1.9.0

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

* [PATCH v0 08/15] clk: st: Adds clockgen clock binding
  2014-02-27 15:24 ` Gabriel FERNANDEZ
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  -1 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: mturquette, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, rob, linux, devicetree, linux-doc, linux-kernel,
	linux-arm-kernel
  Cc: Lee Jones, Gabriel Fernandez

Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 .../devicetree/bindings/clock/st/st,clkgen-pll.txt | 48 ++++++++++++++++++++++
 1 file changed, 48 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt

diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt
new file mode 100644
index 0000000..81eb385
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt
@@ -0,0 +1,48 @@
+Binding for a ST pll clock driver.
+
+This binding uses the common clock binding[1].
+Base address is located to the parent node. See clock binding[2]
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/st/st,clkgen.txt
+
+Required properties:
+
+- compatible : shall be:
+	"st,clkgena-prediv-c65",	"st,clkgena-prediv"
+	"st,clkgena-prediv-c32",	"st,clkgena-prediv"
+
+	"st,clkgena-plls-c65"
+	"st,plls-c32-a1x-0",		"st,clkgen-plls-c32"
+	"st,plls-c32-a1x-1",		"st,clkgen-plls-c32"
+	"st,stih415-plls-c32-a9",	"st,clkgen-plls-c32"
+	"st,stih415-plls-c32-ddr",	"st,clkgen-plls-c32"
+	"st,stih416-plls-c32-a9",	"st,clkgen-plls-c32"
+	"st,stih416-plls-c32-ddr",	"st,clkgen-plls-c32"
+
+	"st,stih415-gpu-pll-c32",	"st,clkgengpu-pll-c32"
+	"st,stih416-gpu-pll-c32",	"st,clkgengpu-pll-c32"
+
+
+- #clock-cells : From common clock binding; shall be set to 1.
+
+- clocks : From common clock binding
+
+- clock-output-names : From common clock binding.
+
+Example:
+
+	clockgenA@fee62000 {
+		reg = <0xfee62000 0xb48>;
+
+		CLK_S_A0_PLL: CLK_S_A0_PLL {
+			#clock-cells = <1>;
+			compatible = "st,clkgena-plls-c65";
+
+			clocks = <&CLK_SYSIN>;
+
+			clock-output-names = "CLK_S_A0_PLL0_HS",
+					     "CLK_S_A0_PLL0_LS",
+					     "CLK_S_A0_PLL1";
+		};
+	};
-- 
1.9.0


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

* [PATCH v0 08/15] clk: st: Adds clockgen clock binding
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 .../devicetree/bindings/clock/st/st,clkgen-pll.txt | 48 ++++++++++++++++++++++
 1 file changed, 48 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt

diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt
new file mode 100644
index 0000000..81eb385
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt
@@ -0,0 +1,48 @@
+Binding for a ST pll clock driver.
+
+This binding uses the common clock binding[1].
+Base address is located to the parent node. See clock binding[2]
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/st/st,clkgen.txt
+
+Required properties:
+
+- compatible : shall be:
+	"st,clkgena-prediv-c65",	"st,clkgena-prediv"
+	"st,clkgena-prediv-c32",	"st,clkgena-prediv"
+
+	"st,clkgena-plls-c65"
+	"st,plls-c32-a1x-0",		"st,clkgen-plls-c32"
+	"st,plls-c32-a1x-1",		"st,clkgen-plls-c32"
+	"st,stih415-plls-c32-a9",	"st,clkgen-plls-c32"
+	"st,stih415-plls-c32-ddr",	"st,clkgen-plls-c32"
+	"st,stih416-plls-c32-a9",	"st,clkgen-plls-c32"
+	"st,stih416-plls-c32-ddr",	"st,clkgen-plls-c32"
+
+	"st,stih415-gpu-pll-c32",	"st,clkgengpu-pll-c32"
+	"st,stih416-gpu-pll-c32",	"st,clkgengpu-pll-c32"
+
+
+- #clock-cells : From common clock binding; shall be set to 1.
+
+- clocks : From common clock binding
+
+- clock-output-names : From common clock binding.
+
+Example:
+
+	clockgenA at fee62000 {
+		reg = <0xfee62000 0xb48>;
+
+		CLK_S_A0_PLL: CLK_S_A0_PLL {
+			#clock-cells = <1>;
+			compatible = "st,clkgena-plls-c65";
+
+			clocks = <&CLK_SYSIN>;
+
+			clock-output-names = "CLK_S_A0_PLL0_HS",
+					     "CLK_S_A0_PLL0_LS",
+					     "CLK_S_A0_PLL1";
+		};
+	};
-- 
1.9.0

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

* [PATCH v0 09/15] clk: st: Adds clockgen-vcc and clockgen-mux clock binding
  2014-02-27 15:24 ` Gabriel FERNANDEZ
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  -1 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: mturquette, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, rob, linux, devicetree, linux-doc, linux-kernel,
	linux-arm-kernel
  Cc: Lee Jones, Gabriel Fernandez

Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 .../devicetree/bindings/clock/st/st,clkgen-mux.txt | 36 +++++++++++++++
 .../devicetree/bindings/clock/st/st,clkgen-vcc.txt | 53 ++++++++++++++++++++++
 2 files changed, 89 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt

diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt
new file mode 100644
index 0000000..943e080
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt
@@ -0,0 +1,36 @@
+Binding for a ST multiplexed clock driver.
+
+This binding supports only simple indexed multiplexers, it does not
+support table based parent index to hardware value translations.
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+
+- compatible : shall be:
+	"st,stih416-clkgenc-vcc-hd",	"st,clkgen-mux"
+	"st,stih416-clkgenf-vcc-fvdp",	"st,clkgen-mux"
+	"st,stih416-clkgenf-vcc-hva", 	"st,clkgen-mux"
+	"st,stih416-clkgenf-vcc-hd",	"st,clkgen-mux"
+	"st,stih416-clkgenf-vcc-sd",	"st,clkgen-mux"
+	"st,stih415-clkgen-a9-mux",	"st,clkgen-mux"
+	"st,stih416-clkgen-a9-mux",	"st,clkgen-mux"
+
+
+- #clock-cells : from common clock binding; shall be set to 0.
+
+- reg : A Base address and length of the register set.
+
+- clocks : from common clock binding
+
+Example:
+
+	CLK_M_HVA: CLK_M_HVA {
+		#clock-cells = <0>;
+		compatible = "st,stih416-clkgenf-vcc-hva", "st,clkgen-mux";
+		reg = <0xfd690868 4>;
+
+		clocks = <&CLOCKGEN_F 1>, <&CLK_M_A1_DIV0 3>;
+	};
diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt
new file mode 100644
index 0000000..4e3ff28
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt
@@ -0,0 +1,53 @@
+Binding for a type of STMicroelectronics clock crossbar (VCC).
+
+The crossbar can take up to 4 input clocks and control up to 16
+output clocks. Not all inputs or outputs have to be in use in a
+particular instantiation. Each output can be individually enabled,
+select any of the input clocks and apply a divide (by 1,2,4 or 8) to
+that selected clock.
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+
+- compatible : shall be:
+	"st,stih416-clkgenc",		"st,vcc"
+	"st,stih416-clkgenf",		"st,vcc"
+
+- #clock-cells : from common clock binding; shall be set to 1.
+
+- reg : A Base address and length of the register set.
+
+- clocks : from common clock binding
+
+- clock-output-names : From common clock binding. The block has 16
+                       clock outputs but not all of them in a specific instance
+                       have to be used in the SoC. If a clock name is left as
+                       an empty string then no clock will be created for the
+                       output associated with that string index. If fewer than
+                       16 strings are provided then no clocks will be created
+                       for the remaining outputs.
+
+Example:
+
+	CLOCKGEN_C_VCC: CLOCKGEN_C_VCC {
+		#clock-cells = <1>;
+		compatible = "st,stih416-clkgenc", "st,clkgen-vcc";
+		reg = <0xfe8308ac 12>;
+
+		clocks = <&CLK_S_VCC_HD>, <&CLOCKGEN_C 1>,
+			<&CLK_S_TMDS_FROMPHY>, <&CLOCKGEN_C 2>;
+
+		clock-output-names  =
+			"CLK_S_PIX_HDMI",  "CLK_S_PIX_DVO",
+			"CLK_S_OUT_DVO",   "CLK_S_PIX_HD",
+			"CLK_S_HDDAC",     "CLK_S_DENC",
+			"CLK_S_SDDAC",     "CLK_S_PIX_MAIN",
+			"CLK_S_PIX_AUX",   "CLK_S_STFE_FRC_0",
+			"CLK_S_REF_MCRU",  "CLK_S_SLAVE_MCRU",
+			"CLK_S_TMDS_HDMI", "CLK_S_HDMI_REJECT_PLL",
+			"CLK_S_THSENS";
+	};
+
-- 
1.9.0


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

* [PATCH v0 09/15] clk: st: Adds clockgen-vcc and clockgen-mux clock binding
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 .../devicetree/bindings/clock/st/st,clkgen-mux.txt | 36 +++++++++++++++
 .../devicetree/bindings/clock/st/st,clkgen-vcc.txt | 53 ++++++++++++++++++++++
 2 files changed, 89 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt

diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt
new file mode 100644
index 0000000..943e080
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt
@@ -0,0 +1,36 @@
+Binding for a ST multiplexed clock driver.
+
+This binding supports only simple indexed multiplexers, it does not
+support table based parent index to hardware value translations.
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+
+- compatible : shall be:
+	"st,stih416-clkgenc-vcc-hd",	"st,clkgen-mux"
+	"st,stih416-clkgenf-vcc-fvdp",	"st,clkgen-mux"
+	"st,stih416-clkgenf-vcc-hva", 	"st,clkgen-mux"
+	"st,stih416-clkgenf-vcc-hd",	"st,clkgen-mux"
+	"st,stih416-clkgenf-vcc-sd",	"st,clkgen-mux"
+	"st,stih415-clkgen-a9-mux",	"st,clkgen-mux"
+	"st,stih416-clkgen-a9-mux",	"st,clkgen-mux"
+
+
+- #clock-cells : from common clock binding; shall be set to 0.
+
+- reg : A Base address and length of the register set.
+
+- clocks : from common clock binding
+
+Example:
+
+	CLK_M_HVA: CLK_M_HVA {
+		#clock-cells = <0>;
+		compatible = "st,stih416-clkgenf-vcc-hva", "st,clkgen-mux";
+		reg = <0xfd690868 4>;
+
+		clocks = <&CLOCKGEN_F 1>, <&CLK_M_A1_DIV0 3>;
+	};
diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt
new file mode 100644
index 0000000..4e3ff28
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt
@@ -0,0 +1,53 @@
+Binding for a type of STMicroelectronics clock crossbar (VCC).
+
+The crossbar can take up to 4 input clocks and control up to 16
+output clocks. Not all inputs or outputs have to be in use in a
+particular instantiation. Each output can be individually enabled,
+select any of the input clocks and apply a divide (by 1,2,4 or 8) to
+that selected clock.
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+
+- compatible : shall be:
+	"st,stih416-clkgenc",		"st,vcc"
+	"st,stih416-clkgenf",		"st,vcc"
+
+- #clock-cells : from common clock binding; shall be set to 1.
+
+- reg : A Base address and length of the register set.
+
+- clocks : from common clock binding
+
+- clock-output-names : From common clock binding. The block has 16
+                       clock outputs but not all of them in a specific instance
+                       have to be used in the SoC. If a clock name is left as
+                       an empty string then no clock will be created for the
+                       output associated with that string index. If fewer than
+                       16 strings are provided then no clocks will be created
+                       for the remaining outputs.
+
+Example:
+
+	CLOCKGEN_C_VCC: CLOCKGEN_C_VCC {
+		#clock-cells = <1>;
+		compatible = "st,stih416-clkgenc", "st,clkgen-vcc";
+		reg = <0xfe8308ac 12>;
+
+		clocks = <&CLK_S_VCC_HD>, <&CLOCKGEN_C 1>,
+			<&CLK_S_TMDS_FROMPHY>, <&CLOCKGEN_C 2>;
+
+		clock-output-names  =
+			"CLK_S_PIX_HDMI",  "CLK_S_PIX_DVO",
+			"CLK_S_OUT_DVO",   "CLK_S_PIX_HD",
+			"CLK_S_HDDAC",     "CLK_S_DENC",
+			"CLK_S_SDDAC",     "CLK_S_PIX_MAIN",
+			"CLK_S_PIX_AUX",   "CLK_S_STFE_FRC_0",
+			"CLK_S_REF_MCRU",  "CLK_S_SLAVE_MCRU",
+			"CLK_S_TMDS_HDMI", "CLK_S_HDMI_REJECT_PLL",
+			"CLK_S_THSENS";
+	};
+
-- 
1.9.0

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

* [PATCH v0 10/15] clk: st: Adds quadfs clock binding
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: mturquette, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, rob, linux, devicetree, linux-doc, linux-kernel,
	linux-arm-kernel
  Cc: Lee Jones, Gabriel Fernandez

Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 .../devicetree/bindings/clock/st/st,quadfs.txt     | 45 ++++++++++++++++++++++
 1 file changed, 45 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,quadfs.txt

diff --git a/Documentation/devicetree/bindings/clock/st/st,quadfs.txt b/Documentation/devicetree/bindings/clock/st/st,quadfs.txt
new file mode 100644
index 0000000..ec86d62
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/st/st,quadfs.txt
@@ -0,0 +1,45 @@
+Binding for a type of quad channel digital frequency synthesizer found on
+certain STMicroelectronics consumer electronics SoC devices.
+
+This version contains a programmable PLL which can generate up to 216, 432
+or 660MHz (from a 30MHz oscillator input) as the input to the digital
+synthesizers.
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be:
+  "st,stih416-quadfs216",	"st,quadfs"
+  "st,stih416-quadfs432",	"st,quadfs"
+  "st,stih416-quadfs660-E",	"st,quadfs"
+  "st,stih416-quadfs660-F",	"st,quadfs"
+
+- #clock-cells : from common clock binding; shall be set to 1.
+
+- reg : A Base address and length of the register set.
+
+- clocks : from common clock binding
+
+- clock-output-names : From common clock binding. The block has 4
+                       clock outputs but not all of them in a specific instance
+                       have to be used in the SoC. If a clock name is left as
+                       an empty string then no clock will be created for the
+                       output associated with that string index. If fewer than
+                       4 strings are provided then no clocks will be created
+                       for the remaining outputs.
+
+Example:
+
+	CLOCKGEN_E: CLOCKGEN_E {
+                #clock-cells = <1>;
+                compatible = "st,stih416-quadfs660-E", "st,quadfs";
+                reg = <0xfd3208bc 0xB0>;
+
+                clocks = <&CLK_SYSIN>;
+                clock-output-names = "CLK_M_PIX_MDTP_0",
+                                        "CLK_M_PIX_MDTP_1",
+                                        "CLK_M_PIX_MDTP_2",
+                                        "CLK_M_MPELPC";
+        };
-- 
1.9.0


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

* [PATCH v0 10/15] clk: st: Adds quadfs clock binding
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: mturquette-QSEj5FYQhm4dnm+yROfE0A,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, pawel.moll-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, rob-VoJi6FS/r0vR7s880joybQ,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Lee Jones, Gabriel Fernandez

Signed-off-by: Gabriel Fernandez <gabriel.fernandez-qxv4g6HH51o@public.gmane.org>
---
 .../devicetree/bindings/clock/st/st,quadfs.txt     | 45 ++++++++++++++++++++++
 1 file changed, 45 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,quadfs.txt

diff --git a/Documentation/devicetree/bindings/clock/st/st,quadfs.txt b/Documentation/devicetree/bindings/clock/st/st,quadfs.txt
new file mode 100644
index 0000000..ec86d62
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/st/st,quadfs.txt
@@ -0,0 +1,45 @@
+Binding for a type of quad channel digital frequency synthesizer found on
+certain STMicroelectronics consumer electronics SoC devices.
+
+This version contains a programmable PLL which can generate up to 216, 432
+or 660MHz (from a 30MHz oscillator input) as the input to the digital
+synthesizers.
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be:
+  "st,stih416-quadfs216",	"st,quadfs"
+  "st,stih416-quadfs432",	"st,quadfs"
+  "st,stih416-quadfs660-E",	"st,quadfs"
+  "st,stih416-quadfs660-F",	"st,quadfs"
+
+- #clock-cells : from common clock binding; shall be set to 1.
+
+- reg : A Base address and length of the register set.
+
+- clocks : from common clock binding
+
+- clock-output-names : From common clock binding. The block has 4
+                       clock outputs but not all of them in a specific instance
+                       have to be used in the SoC. If a clock name is left as
+                       an empty string then no clock will be created for the
+                       output associated with that string index. If fewer than
+                       4 strings are provided then no clocks will be created
+                       for the remaining outputs.
+
+Example:
+
+	CLOCKGEN_E: CLOCKGEN_E {
+                #clock-cells = <1>;
+                compatible = "st,stih416-quadfs660-E", "st,quadfs";
+                reg = <0xfd3208bc 0xB0>;
+
+                clocks = <&CLK_SYSIN>;
+                clock-output-names = "CLK_M_PIX_MDTP_0",
+                                        "CLK_M_PIX_MDTP_1",
+                                        "CLK_M_PIX_MDTP_2",
+                                        "CLK_M_MPELPC";
+        };
-- 
1.9.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v0 10/15] clk: st: Adds quadfs clock binding
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 .../devicetree/bindings/clock/st/st,quadfs.txt     | 45 ++++++++++++++++++++++
 1 file changed, 45 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/st/st,quadfs.txt

diff --git a/Documentation/devicetree/bindings/clock/st/st,quadfs.txt b/Documentation/devicetree/bindings/clock/st/st,quadfs.txt
new file mode 100644
index 0000000..ec86d62
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/st/st,quadfs.txt
@@ -0,0 +1,45 @@
+Binding for a type of quad channel digital frequency synthesizer found on
+certain STMicroelectronics consumer electronics SoC devices.
+
+This version contains a programmable PLL which can generate up to 216, 432
+or 660MHz (from a 30MHz oscillator input) as the input to the digital
+synthesizers.
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be:
+  "st,stih416-quadfs216",	"st,quadfs"
+  "st,stih416-quadfs432",	"st,quadfs"
+  "st,stih416-quadfs660-E",	"st,quadfs"
+  "st,stih416-quadfs660-F",	"st,quadfs"
+
+- #clock-cells : from common clock binding; shall be set to 1.
+
+- reg : A Base address and length of the register set.
+
+- clocks : from common clock binding
+
+- clock-output-names : From common clock binding. The block has 4
+                       clock outputs but not all of them in a specific instance
+                       have to be used in the SoC. If a clock name is left as
+                       an empty string then no clock will be created for the
+                       output associated with that string index. If fewer than
+                       4 strings are provided then no clocks will be created
+                       for the remaining outputs.
+
+Example:
+
+	CLOCKGEN_E: CLOCKGEN_E {
+                #clock-cells = <1>;
+                compatible = "st,stih416-quadfs660-E", "st,quadfs";
+                reg = <0xfd3208bc 0xB0>;
+
+                clocks = <&CLK_SYSIN>;
+                clock-output-names = "CLK_M_PIX_MDTP_0",
+                                        "CLK_M_PIX_MDTP_1",
+                                        "CLK_M_PIX_MDTP_2",
+                                        "CLK_M_MPELPC";
+        };
-- 
1.9.0

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

* [PATCH v0 11/15] ARM: STi: DT: STiH416: 416 DT Entry for clockgen A0/1/10/11/12
  2014-02-27 15:24 ` Gabriel FERNANDEZ
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  -1 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: mturquette, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, rob, linux, devicetree, linux-doc, linux-kernel,
	linux-arm-kernel
  Cc: Lee Jones, Gabriel Fernandez, Pankaj Dev

Patch adds DT entries for clockgen A0/1/10/11/12

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 arch/arm/boot/dts/stih416-clks.h     |  11 +
 arch/arm/boot/dts/stih416-clock.dtsi | 478 ++++++++++++++++++++++++++++++++++-
 arch/arm/boot/dts/stih416.dtsi       |   6 +-
 3 files changed, 486 insertions(+), 9 deletions(-)
 create mode 100644 arch/arm/boot/dts/stih416-clks.h

diff --git a/arch/arm/boot/dts/stih416-clks.h b/arch/arm/boot/dts/stih416-clks.h
new file mode 100644
index 0000000..2088a55
--- /dev/null
+++ b/arch/arm/boot/dts/stih416-clks.h
@@ -0,0 +1,11 @@
+/*
+ * This header provides constants clk index STMicroelectronics
+ * STiH416 SoC.
+ */
+#ifndef _CLK_STIH416
+#define _CLK_STIH416
+
+/* CLOCKGEN A0 */
+#define CLK_S_ICN_REG_0		0
+
+#endif
diff --git a/arch/arm/boot/dts/stih416-clock.dtsi b/arch/arm/boot/dts/stih416-clock.dtsi
index 7026bf1..f63b0a1 100644
--- a/arch/arm/boot/dts/stih416-clock.dtsi
+++ b/arch/arm/boot/dts/stih416-clock.dtsi
@@ -6,8 +6,15 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+
+#include "stih416-clks.h"
+
 / {
 	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
 		/*
 		 * Fixed 30MHz oscillator inputs to SoC
 		 */
@@ -28,14 +35,473 @@
 		};
 
 		/*
-		 * Bootloader initialized system infrastructure clock for
-		 * serial devices.
+		 * ClockGenAs on SASG2
+		 */
+		clockgenA@fee62000 {
+			reg = <0xfee62000 0xb48>;
+
+			CLK_S_A0_PLL: CLK_S_A0_PLL {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-plls-c65";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_S_A0_PLL0_HS",
+						     "CLK_S_A0_PLL0_LS",
+						     "CLK_S_A0_PLL1";
+			};
+
+			CLK_S_A0_OSC_PREDIV: CLK_S_A0_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c65",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_S_A0_OSC_PREDIV";
+			};
+
+			CLK_S_A0_HS: CLK_S_A0_HS {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c65-hs",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_S_A0_OSC_PREDIV>,
+					 <&CLK_S_A0_PLL 0>, /* PLL0 HS */
+					 <&CLK_S_A0_PLL 2>; /* PLL1 */
+
+				clock-output-names = "CLK_S_FDMA_0",
+						     "CLK_S_FDMA_1",
+						     ""; /* CLK_S_JIT_SENSE */
+						     /* Fourth output unused */
+			};
+
+			CLK_S_A0_LS: CLK_S_A0_LS {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c65-ls",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_S_A0_OSC_PREDIV>,
+					 <&CLK_S_A0_PLL 1>, /* PLL0 LS */
+					 <&CLK_S_A0_PLL 2>; /* PLL1 */
+
+				clock-output-names = "CLK_S_ICN_REG_0",
+						     "CLK_S_ICN_IF_0",
+						     "CLK_S_ICN_REG_LP_0",
+						     "CLK_S_EMISS",
+						     "CLK_S_ETH1_PHY",
+						     "CLK_S_MII_REF_OUT";
+						 /* Remaining outputs unused */
+			};
+		};
+
+		clockgenA@fee81000 {
+			reg = <0xfee81000 0xb48>;
+
+			CLK_S_A1_PLL: CLK_S_A1_PLL {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-plls-c65";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_S_A1_PLL0_HS",
+						     "CLK_S_A1_PLL0_LS",
+						     "CLK_S_A1_PLL1";
+			};
+
+			CLK_S_A1_OSC_PREDIV: CLK_S_A1_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c65",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_S_A1_OSC_PREDIV";
+			};
+
+			CLK_S_A1_HS: CLK_S_A1_HS {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c65-hs",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_S_A1_OSC_PREDIV>,
+					 <&CLK_S_A1_PLL 0>, /* PLL0 HS */
+					 <&CLK_S_A1_PLL 2>; /* PLL1 */
+
+				clock-output-names = "", /* Reserved */
+						     "", /* Reserved */
+						     "CLK_S_STAC_PHY",
+						     "CLK_S_VTAC_TX_PHY";
+			};
+
+			CLK_S_A1_LS: CLK_S_A1_LS {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c65-ls",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_S_A1_OSC_PREDIV>,
+					 <&CLK_S_A1_PLL 1>, /* PLL0 LS */
+					 <&CLK_S_A1_PLL 2>; /* PLL1 */
+
+				clock-output-names = "CLK_S_ICN_IF_2",
+						     "CLK_S_CARD_MMC_0",
+						     "CLK_S_ICN_IF_1",
+						     "CLK_S_GMAC0_PHY",
+						     "CLK_S_NAND_CTRL",
+						     "", /* Reserved */
+						     "CLK_S_MII0_REF_OUT",
+						     "CLK_S_STAC_SYS",
+						     "CLK_S_CARD_MMC_1";
+						 /* Remaining outputs unused */
+			};
+		};
+
+		/*
+		 * ClockGenAs on MPE42
 		 */
-		CLK_S_ICN_REG_0: clockgenA0@4 {
+		clockgenA@fde12000 {
+			reg = <0xfde12000 0xb50>;
+
+			CLK_M_A0_PLL0: CLK_M_A0_PLL0 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-0", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A0_PLL0_PHI0",
+						     "CLK_M_A0_PLL0_PHI1",
+						     "CLK_M_A0_PLL0_PHI2",
+						     "CLK_M_A0_PLL0_PHI3";
+			};
+
+			CLK_M_A0_PLL1: CLK_M_A0_PLL1 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-1", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A0_PLL1_PHI0",
+						     "CLK_M_A0_PLL1_PHI1",
+						     "CLK_M_A0_PLL1_PHI2",
+						     "CLK_M_A0_PLL1_PHI3";
+			};
+
+			CLK_M_A0_OSC_PREDIV: CLK_M_A0_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c32",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A0_OSC_PREDIV";
+			};
+
+			CLK_M_A0_DIV0: CLK_M_A0_DIV0 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf0",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A0_OSC_PREDIV>,
+					 <&CLK_M_A0_PLL0 0>, /* PLL0 PHI0 */
+					 <&CLK_M_A0_PLL1 0>; /* PLL1 PHI0 */
+
+				clock-output-names = "", /* Unused */
+						     "", /* Unused */
+						     "CLK_M_FDMA_12",
+						     "", /* Unused */
+						     "CLK_M_PP_DMU_0",
+						     "CLK_M_PP_DMU_1",
+						     "CLK_M_ICM_LMI",
+						     "CLK_M_VID_DMU_0";
+			};
+
+			CLK_M_A0_DIV1: CLK_M_A0_DIV1 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf1",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A0_OSC_PREDIV>,
+					 <&CLK_M_A0_PLL0 1>, /* PLL0 PHI1 */
+					 <&CLK_M_A0_PLL1 1>; /* PLL1 PHI1 */
+
+				clock-output-names = "CLK_M_VID_DMU_1",
+						     "", /* Unused */
+						     "CLK_M_A9_EXT2F",
+						     "CLK_M_ST40RT",
+						     "CLK_M_ST231_DMU_0",
+						     "CLK_M_ST231_DMU_1",
+						     "CLK_M_ST231_AUD",
+						     "CLK_M_ST231_GP_0";
+			};
+
+			CLK_M_A0_DIV2: CLK_M_A0_DIV2 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf2",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A0_OSC_PREDIV>,
+					 <&CLK_M_A0_PLL0 2>, /* PLL0 PHI2 */
+					 <&CLK_M_A0_PLL1 2>; /* PLL1 PHI2 */
+
+				clock-output-names = "CLK_M_ST231_GP_1",
+						     "CLK_M_ICN_CPU",
+						     "CLK_M_ICN_STAC",
+						     "CLK_M_TX_ICN_DMU_0",
+						     "CLK_M_TX_ICN_DMU_1",
+						     "CLK_M_TX_ICN_TS",
+						     "CLK_M_ICN_VDP_0",
+						     "CLK_M_ICN_VDP_1";
+			};
+
+			CLK_M_A0_DIV3: CLK_M_A0_DIV3 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf3",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A0_OSC_PREDIV>,
+					 <&CLK_M_A0_PLL0 3>, /* PLL0 PHI3 */
+					 <&CLK_M_A0_PLL1 3>; /* PLL1 PHI3 */
+
+				clock-output-names = "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "CLK_M_ICN_VP8",
+						     "", /* Unused */
+						     "CLK_M_ICN_REG_11",
+						     "CLK_M_A9_TRACE";
+			};
+		};
+
+		clockgenA@fd6db000 {
+			reg = <0xfd6db000 0xb50>;
+
+			CLK_M_A1_PLL0: CLK_M_A1_PLL0 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-0", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A1_PLL0_PHI0",
+						     "CLK_M_A1_PLL0_PHI1",
+						     "CLK_M_A1_PLL0_PHI2",
+						     "CLK_M_A1_PLL0_PHI3";
+			};
+
+			CLK_M_A1_PLL1: CLK_M_A1_PLL1 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-1", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A1_PLL1_PHI0",
+						     "CLK_M_A1_PLL1_PHI1",
+						     "CLK_M_A1_PLL1_PHI2",
+						     "CLK_M_A1_PLL1_PHI3";
+			};
+
+			CLK_M_A1_OSC_PREDIV: CLK_M_A1_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c32",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A1_OSC_PREDIV";
+			};
+
+			CLK_M_A1_DIV0: CLK_M_A1_DIV0 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf0",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A1_OSC_PREDIV>,
+					 <&CLK_M_A1_PLL0 0>, /* PLL0 PHI0 */
+					 <&CLK_M_A1_PLL1 0>; /* PLL1 PHI0 */
+
+				clock-output-names = "", /* Unused */
+						     "CLK_M_FDMA_10",
+						     "CLK_M_FDMA_11",
+						     "CLK_M_HVA_ALT",
+						     "CLK_M_PROC_SC",
+						     "CLK_M_TP",
+						     "CLK_M_RX_ICN_DMU_0",
+						     "CLK_M_RX_ICN_DMU_1";
+			};
+
+			CLK_M_A1_DIV1: CLK_M_A1_DIV1 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf1",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A1_OSC_PREDIV>,
+					 <&CLK_M_A1_PLL0 1>, /* PLL0 PHI1 */
+					 <&CLK_M_A1_PLL1 1>; /* PLL1 PHI1 */
+
+				clock-output-names = "CLK_M_RX_ICN_TS",
+						     "CLK_M_RX_ICN_VDP_0",
+						     "", /* Unused */
+						     "CLK_M_PRV_T1_BUS",
+						     "CLK_M_ICN_REG_12",
+						     "CLK_M_ICN_REG_10",
+						     "", /* Unused */
+						     "CLK_M_ICN_ST231";
+			};
+
+			CLK_M_A1_DIV2: CLK_M_A1_DIV2 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf2",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A1_OSC_PREDIV>,
+					 <&CLK_M_A1_PLL0 2>, /* PLL0 PHI2 */
+					 <&CLK_M_A1_PLL1 2>; /* PLL1 PHI2 */
+
+				clock-output-names = "CLK_M_FVDP_PROC_ALT",
+						     "CLK_M_ICN_REG_13",
+						     "CLK_M_TX_ICN_GPU",
+						     "CLK_M_RX_ICN_GPU",
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* CLK_M_APB_PM_12 */
+						     ""; /* Unused */
+			};
+
+			CLK_M_A1_DIV3: CLK_M_A1_DIV3 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf3",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A1_OSC_PREDIV>,
+					 <&CLK_M_A1_PLL0 3>, /* PLL0 PHI3 */
+					 <&CLK_M_A1_PLL1 3>; /* PLL1 PHI3 */
+
+				clock-output-names = "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     ""; /* CLK_M_GPU_ALT */
+			};
+		};
+
+		CLK_M_A9_EXT2F_DIV2: CLK_M_A9_EXT2F_DIV2S {
 			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <100000000>;
-			clock-output-names = "CLK_S_ICN_REG_0";
+			compatible = "fixed-factor-clock";
+			clocks = <&CLK_M_A0_DIV1 2>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+
+		clockgenA@fd345000 {
+			reg = <0xfd345000 0xb50>;
+
+			CLK_M_A2_PLL0: CLK_M_A2_PLL0 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-0", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A2_PLL0_PHI0",
+						     "CLK_M_A2_PLL0_PHI1",
+						     "CLK_M_A2_PLL0_PHI2",
+						     "CLK_M_A2_PLL0_PHI3";
+			};
+
+			CLK_M_A2_PLL1: CLK_M_A2_PLL1 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-1", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A2_PLL1_PHI0",
+						     "CLK_M_A2_PLL1_PHI1",
+						     "CLK_M_A2_PLL1_PHI2",
+						     "CLK_M_A2_PLL1_PHI3";
+			};
+
+			CLK_M_A2_OSC_PREDIV: CLK_M_A2_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c32",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A2_OSC_PREDIV";
+			};
+
+			CLK_M_A2_DIV0: CLK_M_A2_DIV0 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf0",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A2_OSC_PREDIV>,
+					 <&CLK_M_A2_PLL0 0>, /* PLL0 PHI0 */
+					 <&CLK_M_A2_PLL1 0>; /* PLL1 PHI0 */
+
+				clock-output-names = "CLK_M_VTAC_MAIN_PHY",
+						     "CLK_M_VTAC_AUX_PHY",
+						     "CLK_M_STAC_PHY",
+						     "CLK_M_STAC_SYS",
+						     "", /* CLK_M_MPESTAC_PG */
+						     "", /* CLK_M_MPESTAC_WC */
+						     "", /* CLK_M_MPEVTACAUX_PG*/
+						     ""; /* CLK_M_MPEVTACMAIN_PG*/
+			};
+
+			CLK_M_A2_DIV1: CLK_M_A2_DIV1 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf1",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A2_OSC_PREDIV>,
+					 <&CLK_M_A2_PLL0 1>, /* PLL0 PHI1 */
+					 <&CLK_M_A2_PLL1 1>; /* PLL1 PHI1 */
+
+				clock-output-names = "", /* CLK_M_MPEVTACRX0_WC */
+						     "", /* CLK_M_MPEVTACRX1_WC */
+						     "CLK_M_COMPO_MAIN",
+						     "CLK_M_COMPO_AUX",
+						     "CLK_M_BDISP_0",
+						     "CLK_M_BDISP_1",
+						     "CLK_M_ICN_BDISP",
+						     "CLK_M_ICN_COMPO";
+			};
+
+			CLK_M_A2_DIV2: CLK_M_A2_DIV2 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf2",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A2_OSC_PREDIV>,
+					 <&CLK_M_A2_PLL0 2>, /* PLL0 PHI2 */
+					 <&CLK_M_A2_PLL1 2>; /* PLL1 PHI2 */
+
+				clock-output-names = "CLK_M_ICN_VDP_2",
+						     "", /* Unused */
+						     "CLK_M_ICN_REG_14",
+						     "CLK_M_MDTP",
+						     "CLK_M_JPEGDEC",
+						     "", /* Unused */
+						     "CLK_M_DCEPHY_IMPCTRL",
+						     ""; /* Unused */
+			};
+
+			CLK_M_A2_DIV3: CLK_M_A2_DIV3 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf3",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A2_OSC_PREDIV>,
+					 <&CLK_M_A2_PLL0 3>, /* PLL0 PHI3 */
+					 <&CLK_M_A2_PLL1 3>; /* PLL1 PHI3 */
+
+				clock-output-names = "", /* Unused */
+						     ""; /* CLK_M_APB_PM_11 */
+						/* Remaining outputs unused */
+			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/stih416.dtsi b/arch/arm/boot/dts/stih416.dtsi
index b7ab47b..cf29d44 100644
--- a/arch/arm/boot/dts/stih416.dtsi
+++ b/arch/arm/boot/dts/stih416.dtsi
@@ -78,7 +78,7 @@
 			status 		= "disabled";
 			reg		= <0xfed32000 0x2c>;
 			interrupts	= <0 197 0>;
-			clocks          = <&CLK_S_ICN_REG_0>;
+			clocks 		= <&CLK_S_A0_LS CLK_S_ICN_REG_0>;
 			pinctrl-names 	= "default";
 			pinctrl-0 	= <&pinctrl_serial2 &pinctrl_serial2_oe>;
 		};
@@ -98,7 +98,7 @@
 			compatible	= "st,comms-ssc4-i2c";
 			reg		= <0xfed40000 0x110>;
 			interrupts	= <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
-			clocks		= <&CLK_S_ICN_REG_0>;
+			clocks 		= <&CLK_S_A0_LS CLK_S_ICN_REG_0>;
 			clock-names	= "ssc";
 			clock-frequency = <400000>;
 			pinctrl-names	= "default";
@@ -111,7 +111,7 @@
 			compatible	= "st,comms-ssc4-i2c";
 			reg		= <0xfed41000 0x110>;
 			interrupts	= <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
-			clocks		= <&CLK_S_ICN_REG_0>;
+			clocks 		= <&CLK_S_A0_LS CLK_S_ICN_REG_0>;
 			clock-names	= "ssc";
 			clock-frequency = <400000>;
 			pinctrl-names	= "default";
-- 
1.9.0


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

* [PATCH v0 11/15] ARM: STi: DT: STiH416: 416 DT Entry for clockgen A0/1/10/11/12
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

Patch adds DT entries for clockgen A0/1/10/11/12

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 arch/arm/boot/dts/stih416-clks.h     |  11 +
 arch/arm/boot/dts/stih416-clock.dtsi | 478 ++++++++++++++++++++++++++++++++++-
 arch/arm/boot/dts/stih416.dtsi       |   6 +-
 3 files changed, 486 insertions(+), 9 deletions(-)
 create mode 100644 arch/arm/boot/dts/stih416-clks.h

diff --git a/arch/arm/boot/dts/stih416-clks.h b/arch/arm/boot/dts/stih416-clks.h
new file mode 100644
index 0000000..2088a55
--- /dev/null
+++ b/arch/arm/boot/dts/stih416-clks.h
@@ -0,0 +1,11 @@
+/*
+ * This header provides constants clk index STMicroelectronics
+ * STiH416 SoC.
+ */
+#ifndef _CLK_STIH416
+#define _CLK_STIH416
+
+/* CLOCKGEN A0 */
+#define CLK_S_ICN_REG_0		0
+
+#endif
diff --git a/arch/arm/boot/dts/stih416-clock.dtsi b/arch/arm/boot/dts/stih416-clock.dtsi
index 7026bf1..f63b0a1 100644
--- a/arch/arm/boot/dts/stih416-clock.dtsi
+++ b/arch/arm/boot/dts/stih416-clock.dtsi
@@ -6,8 +6,15 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+
+#include "stih416-clks.h"
+
 / {
 	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
 		/*
 		 * Fixed 30MHz oscillator inputs to SoC
 		 */
@@ -28,14 +35,473 @@
 		};
 
 		/*
-		 * Bootloader initialized system infrastructure clock for
-		 * serial devices.
+		 * ClockGenAs on SASG2
+		 */
+		clockgenA at fee62000 {
+			reg = <0xfee62000 0xb48>;
+
+			CLK_S_A0_PLL: CLK_S_A0_PLL {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-plls-c65";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_S_A0_PLL0_HS",
+						     "CLK_S_A0_PLL0_LS",
+						     "CLK_S_A0_PLL1";
+			};
+
+			CLK_S_A0_OSC_PREDIV: CLK_S_A0_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c65",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_S_A0_OSC_PREDIV";
+			};
+
+			CLK_S_A0_HS: CLK_S_A0_HS {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c65-hs",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_S_A0_OSC_PREDIV>,
+					 <&CLK_S_A0_PLL 0>, /* PLL0 HS */
+					 <&CLK_S_A0_PLL 2>; /* PLL1 */
+
+				clock-output-names = "CLK_S_FDMA_0",
+						     "CLK_S_FDMA_1",
+						     ""; /* CLK_S_JIT_SENSE */
+						     /* Fourth output unused */
+			};
+
+			CLK_S_A0_LS: CLK_S_A0_LS {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c65-ls",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_S_A0_OSC_PREDIV>,
+					 <&CLK_S_A0_PLL 1>, /* PLL0 LS */
+					 <&CLK_S_A0_PLL 2>; /* PLL1 */
+
+				clock-output-names = "CLK_S_ICN_REG_0",
+						     "CLK_S_ICN_IF_0",
+						     "CLK_S_ICN_REG_LP_0",
+						     "CLK_S_EMISS",
+						     "CLK_S_ETH1_PHY",
+						     "CLK_S_MII_REF_OUT";
+						 /* Remaining outputs unused */
+			};
+		};
+
+		clockgenA at fee81000 {
+			reg = <0xfee81000 0xb48>;
+
+			CLK_S_A1_PLL: CLK_S_A1_PLL {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-plls-c65";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_S_A1_PLL0_HS",
+						     "CLK_S_A1_PLL0_LS",
+						     "CLK_S_A1_PLL1";
+			};
+
+			CLK_S_A1_OSC_PREDIV: CLK_S_A1_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c65",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_S_A1_OSC_PREDIV";
+			};
+
+			CLK_S_A1_HS: CLK_S_A1_HS {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c65-hs",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_S_A1_OSC_PREDIV>,
+					 <&CLK_S_A1_PLL 0>, /* PLL0 HS */
+					 <&CLK_S_A1_PLL 2>; /* PLL1 */
+
+				clock-output-names = "", /* Reserved */
+						     "", /* Reserved */
+						     "CLK_S_STAC_PHY",
+						     "CLK_S_VTAC_TX_PHY";
+			};
+
+			CLK_S_A1_LS: CLK_S_A1_LS {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c65-ls",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_S_A1_OSC_PREDIV>,
+					 <&CLK_S_A1_PLL 1>, /* PLL0 LS */
+					 <&CLK_S_A1_PLL 2>; /* PLL1 */
+
+				clock-output-names = "CLK_S_ICN_IF_2",
+						     "CLK_S_CARD_MMC_0",
+						     "CLK_S_ICN_IF_1",
+						     "CLK_S_GMAC0_PHY",
+						     "CLK_S_NAND_CTRL",
+						     "", /* Reserved */
+						     "CLK_S_MII0_REF_OUT",
+						     "CLK_S_STAC_SYS",
+						     "CLK_S_CARD_MMC_1";
+						 /* Remaining outputs unused */
+			};
+		};
+
+		/*
+		 * ClockGenAs on MPE42
 		 */
-		CLK_S_ICN_REG_0: clockgenA0 at 4 {
+		clockgenA at fde12000 {
+			reg = <0xfde12000 0xb50>;
+
+			CLK_M_A0_PLL0: CLK_M_A0_PLL0 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-0", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A0_PLL0_PHI0",
+						     "CLK_M_A0_PLL0_PHI1",
+						     "CLK_M_A0_PLL0_PHI2",
+						     "CLK_M_A0_PLL0_PHI3";
+			};
+
+			CLK_M_A0_PLL1: CLK_M_A0_PLL1 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-1", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A0_PLL1_PHI0",
+						     "CLK_M_A0_PLL1_PHI1",
+						     "CLK_M_A0_PLL1_PHI2",
+						     "CLK_M_A0_PLL1_PHI3";
+			};
+
+			CLK_M_A0_OSC_PREDIV: CLK_M_A0_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c32",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A0_OSC_PREDIV";
+			};
+
+			CLK_M_A0_DIV0: CLK_M_A0_DIV0 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf0",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A0_OSC_PREDIV>,
+					 <&CLK_M_A0_PLL0 0>, /* PLL0 PHI0 */
+					 <&CLK_M_A0_PLL1 0>; /* PLL1 PHI0 */
+
+				clock-output-names = "", /* Unused */
+						     "", /* Unused */
+						     "CLK_M_FDMA_12",
+						     "", /* Unused */
+						     "CLK_M_PP_DMU_0",
+						     "CLK_M_PP_DMU_1",
+						     "CLK_M_ICM_LMI",
+						     "CLK_M_VID_DMU_0";
+			};
+
+			CLK_M_A0_DIV1: CLK_M_A0_DIV1 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf1",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A0_OSC_PREDIV>,
+					 <&CLK_M_A0_PLL0 1>, /* PLL0 PHI1 */
+					 <&CLK_M_A0_PLL1 1>; /* PLL1 PHI1 */
+
+				clock-output-names = "CLK_M_VID_DMU_1",
+						     "", /* Unused */
+						     "CLK_M_A9_EXT2F",
+						     "CLK_M_ST40RT",
+						     "CLK_M_ST231_DMU_0",
+						     "CLK_M_ST231_DMU_1",
+						     "CLK_M_ST231_AUD",
+						     "CLK_M_ST231_GP_0";
+			};
+
+			CLK_M_A0_DIV2: CLK_M_A0_DIV2 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf2",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A0_OSC_PREDIV>,
+					 <&CLK_M_A0_PLL0 2>, /* PLL0 PHI2 */
+					 <&CLK_M_A0_PLL1 2>; /* PLL1 PHI2 */
+
+				clock-output-names = "CLK_M_ST231_GP_1",
+						     "CLK_M_ICN_CPU",
+						     "CLK_M_ICN_STAC",
+						     "CLK_M_TX_ICN_DMU_0",
+						     "CLK_M_TX_ICN_DMU_1",
+						     "CLK_M_TX_ICN_TS",
+						     "CLK_M_ICN_VDP_0",
+						     "CLK_M_ICN_VDP_1";
+			};
+
+			CLK_M_A0_DIV3: CLK_M_A0_DIV3 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf3",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A0_OSC_PREDIV>,
+					 <&CLK_M_A0_PLL0 3>, /* PLL0 PHI3 */
+					 <&CLK_M_A0_PLL1 3>; /* PLL1 PHI3 */
+
+				clock-output-names = "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "CLK_M_ICN_VP8",
+						     "", /* Unused */
+						     "CLK_M_ICN_REG_11",
+						     "CLK_M_A9_TRACE";
+			};
+		};
+
+		clockgenA at fd6db000 {
+			reg = <0xfd6db000 0xb50>;
+
+			CLK_M_A1_PLL0: CLK_M_A1_PLL0 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-0", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A1_PLL0_PHI0",
+						     "CLK_M_A1_PLL0_PHI1",
+						     "CLK_M_A1_PLL0_PHI2",
+						     "CLK_M_A1_PLL0_PHI3";
+			};
+
+			CLK_M_A1_PLL1: CLK_M_A1_PLL1 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-1", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A1_PLL1_PHI0",
+						     "CLK_M_A1_PLL1_PHI1",
+						     "CLK_M_A1_PLL1_PHI2",
+						     "CLK_M_A1_PLL1_PHI3";
+			};
+
+			CLK_M_A1_OSC_PREDIV: CLK_M_A1_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c32",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A1_OSC_PREDIV";
+			};
+
+			CLK_M_A1_DIV0: CLK_M_A1_DIV0 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf0",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A1_OSC_PREDIV>,
+					 <&CLK_M_A1_PLL0 0>, /* PLL0 PHI0 */
+					 <&CLK_M_A1_PLL1 0>; /* PLL1 PHI0 */
+
+				clock-output-names = "", /* Unused */
+						     "CLK_M_FDMA_10",
+						     "CLK_M_FDMA_11",
+						     "CLK_M_HVA_ALT",
+						     "CLK_M_PROC_SC",
+						     "CLK_M_TP",
+						     "CLK_M_RX_ICN_DMU_0",
+						     "CLK_M_RX_ICN_DMU_1";
+			};
+
+			CLK_M_A1_DIV1: CLK_M_A1_DIV1 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf1",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A1_OSC_PREDIV>,
+					 <&CLK_M_A1_PLL0 1>, /* PLL0 PHI1 */
+					 <&CLK_M_A1_PLL1 1>; /* PLL1 PHI1 */
+
+				clock-output-names = "CLK_M_RX_ICN_TS",
+						     "CLK_M_RX_ICN_VDP_0",
+						     "", /* Unused */
+						     "CLK_M_PRV_T1_BUS",
+						     "CLK_M_ICN_REG_12",
+						     "CLK_M_ICN_REG_10",
+						     "", /* Unused */
+						     "CLK_M_ICN_ST231";
+			};
+
+			CLK_M_A1_DIV2: CLK_M_A1_DIV2 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf2",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A1_OSC_PREDIV>,
+					 <&CLK_M_A1_PLL0 2>, /* PLL0 PHI2 */
+					 <&CLK_M_A1_PLL1 2>; /* PLL1 PHI2 */
+
+				clock-output-names = "CLK_M_FVDP_PROC_ALT",
+						     "CLK_M_ICN_REG_13",
+						     "CLK_M_TX_ICN_GPU",
+						     "CLK_M_RX_ICN_GPU",
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* CLK_M_APB_PM_12 */
+						     ""; /* Unused */
+			};
+
+			CLK_M_A1_DIV3: CLK_M_A1_DIV3 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf3",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A1_OSC_PREDIV>,
+					 <&CLK_M_A1_PLL0 3>, /* PLL0 PHI3 */
+					 <&CLK_M_A1_PLL1 3>; /* PLL1 PHI3 */
+
+				clock-output-names = "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     ""; /* CLK_M_GPU_ALT */
+			};
+		};
+
+		CLK_M_A9_EXT2F_DIV2: CLK_M_A9_EXT2F_DIV2S {
 			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <100000000>;
-			clock-output-names = "CLK_S_ICN_REG_0";
+			compatible = "fixed-factor-clock";
+			clocks = <&CLK_M_A0_DIV1 2>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+
+		clockgenA at fd345000 {
+			reg = <0xfd345000 0xb50>;
+
+			CLK_M_A2_PLL0: CLK_M_A2_PLL0 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-0", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A2_PLL0_PHI0",
+						     "CLK_M_A2_PLL0_PHI1",
+						     "CLK_M_A2_PLL0_PHI2",
+						     "CLK_M_A2_PLL0_PHI3";
+			};
+
+			CLK_M_A2_PLL1: CLK_M_A2_PLL1 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-1", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A2_PLL1_PHI0",
+						     "CLK_M_A2_PLL1_PHI1",
+						     "CLK_M_A2_PLL1_PHI2",
+						     "CLK_M_A2_PLL1_PHI3";
+			};
+
+			CLK_M_A2_OSC_PREDIV: CLK_M_A2_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c32",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A2_OSC_PREDIV";
+			};
+
+			CLK_M_A2_DIV0: CLK_M_A2_DIV0 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf0",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A2_OSC_PREDIV>,
+					 <&CLK_M_A2_PLL0 0>, /* PLL0 PHI0 */
+					 <&CLK_M_A2_PLL1 0>; /* PLL1 PHI0 */
+
+				clock-output-names = "CLK_M_VTAC_MAIN_PHY",
+						     "CLK_M_VTAC_AUX_PHY",
+						     "CLK_M_STAC_PHY",
+						     "CLK_M_STAC_SYS",
+						     "", /* CLK_M_MPESTAC_PG */
+						     "", /* CLK_M_MPESTAC_WC */
+						     "", /* CLK_M_MPEVTACAUX_PG*/
+						     ""; /* CLK_M_MPEVTACMAIN_PG*/
+			};
+
+			CLK_M_A2_DIV1: CLK_M_A2_DIV1 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf1",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A2_OSC_PREDIV>,
+					 <&CLK_M_A2_PLL0 1>, /* PLL0 PHI1 */
+					 <&CLK_M_A2_PLL1 1>; /* PLL1 PHI1 */
+
+				clock-output-names = "", /* CLK_M_MPEVTACRX0_WC */
+						     "", /* CLK_M_MPEVTACRX1_WC */
+						     "CLK_M_COMPO_MAIN",
+						     "CLK_M_COMPO_AUX",
+						     "CLK_M_BDISP_0",
+						     "CLK_M_BDISP_1",
+						     "CLK_M_ICN_BDISP",
+						     "CLK_M_ICN_COMPO";
+			};
+
+			CLK_M_A2_DIV2: CLK_M_A2_DIV2 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf2",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A2_OSC_PREDIV>,
+					 <&CLK_M_A2_PLL0 2>, /* PLL0 PHI2 */
+					 <&CLK_M_A2_PLL1 2>; /* PLL1 PHI2 */
+
+				clock-output-names = "CLK_M_ICN_VDP_2",
+						     "", /* Unused */
+						     "CLK_M_ICN_REG_14",
+						     "CLK_M_MDTP",
+						     "CLK_M_JPEGDEC",
+						     "", /* Unused */
+						     "CLK_M_DCEPHY_IMPCTRL",
+						     ""; /* Unused */
+			};
+
+			CLK_M_A2_DIV3: CLK_M_A2_DIV3 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf3",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A2_OSC_PREDIV>,
+					 <&CLK_M_A2_PLL0 3>, /* PLL0 PHI3 */
+					 <&CLK_M_A2_PLL1 3>; /* PLL1 PHI3 */
+
+				clock-output-names = "", /* Unused */
+						     ""; /* CLK_M_APB_PM_11 */
+						/* Remaining outputs unused */
+			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/stih416.dtsi b/arch/arm/boot/dts/stih416.dtsi
index b7ab47b..cf29d44 100644
--- a/arch/arm/boot/dts/stih416.dtsi
+++ b/arch/arm/boot/dts/stih416.dtsi
@@ -78,7 +78,7 @@
 			status 		= "disabled";
 			reg		= <0xfed32000 0x2c>;
 			interrupts	= <0 197 0>;
-			clocks          = <&CLK_S_ICN_REG_0>;
+			clocks 		= <&CLK_S_A0_LS CLK_S_ICN_REG_0>;
 			pinctrl-names 	= "default";
 			pinctrl-0 	= <&pinctrl_serial2 &pinctrl_serial2_oe>;
 		};
@@ -98,7 +98,7 @@
 			compatible	= "st,comms-ssc4-i2c";
 			reg		= <0xfed40000 0x110>;
 			interrupts	= <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
-			clocks		= <&CLK_S_ICN_REG_0>;
+			clocks 		= <&CLK_S_A0_LS CLK_S_ICN_REG_0>;
 			clock-names	= "ssc";
 			clock-frequency = <400000>;
 			pinctrl-names	= "default";
@@ -111,7 +111,7 @@
 			compatible	= "st,comms-ssc4-i2c";
 			reg		= <0xfed41000 0x110>;
 			interrupts	= <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
-			clocks		= <&CLK_S_ICN_REG_0>;
+			clocks 		= <&CLK_S_A0_LS CLK_S_ICN_REG_0>;
 			clock-names	= "ssc";
 			clock-frequency = <400000>;
 			pinctrl-names	= "default";
-- 
1.9.0

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

* [PATCH v0 12/15] ARM: STi: DT: STiH416: 416 DT Entry for clockgen B/C/D/E/F
  2014-02-27 15:24 ` Gabriel FERNANDEZ
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  -1 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: mturquette, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, rob, linux, devicetree, linux-doc, linux-kernel,
	linux-arm-kernel
  Cc: Lee Jones, Gabriel Fernandez, Pankaj Dev

Patch adds DT entries for clockgen B/C/D/E/F

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
---
 arch/arm/boot/dts/stih416-clock.dtsi | 170 +++++++++++++++++++++++++++++++++++
 1 file changed, 170 insertions(+)

diff --git a/arch/arm/boot/dts/stih416-clock.dtsi b/arch/arm/boot/dts/stih416-clock.dtsi
index f63b0a1..6b2e387 100644
--- a/arch/arm/boot/dts/stih416-clock.dtsi
+++ b/arch/arm/boot/dts/stih416-clock.dtsi
@@ -503,5 +503,175 @@
 						/* Remaining outputs unused */
 			};
 		};
+                /*
+                 * Frequency synthesizers on the SASG2.
+                 *
+                 */
+                CLOCKGEN_B0: CLOCKGEN_B0 {
+                        #clock-cells = <1>;
+                        compatible = "st,stih416-quadfs216", "st,quadfs";
+                        reg = <0xfee108b4 0x44>;
+
+                        clocks = <&CLK_SYSIN>;
+                        clock-output-names = "CLK_S_USB48",
+                                             "CLK_S_DSS",
+                                             "CLK_S_STFE_FRC_2",
+                                             "CLK_S_THSENS_SCARD";
+                };
+
+                CLOCKGEN_B1: CLOCKGEN_B1 {
+                        #clock-cells = <1>;
+                        compatible = "st,stih416-quadfs216", "st,quadfs";
+                        reg = <0xfe8308c4 0x44>;
+
+                        clocks = <&CLK_SYSIN>;
+                        clock-output-names = "CLK_S_PCM_0",
+                                             "CLK_S_PCM_1",
+                                             "CLK_S_PCM_2",
+                                             "CLK_S_PCM_3";
+                };
+
+                CLOCKGEN_C: CLOCKGEN_C {
+                        #clock-cells = <1>;
+                        compatible = "st,stih416-quadfs432", "st,quadfs";
+                        reg = <0xfe8307d0 0x44>;
+
+                        clocks = <&CLK_SYSIN>;
+                        clock-output-names = "CLK_S_C_FS0_CH0",
+                                             "CLK_S_C_VCC_SD",
+                                             "CLK_S_C_FS0_CH2";
+                };
+
+                CLK_S_VCC_HD: CLK_S_VCC_HD {
+                        #clock-cells = <0>;
+                        compatible = "st,stih416-clkgenc-vcc-hd", "st,clkgen-mux";
+                        reg = <0xfe8308b8 4>; /* SYSCFG2558 */
+
+                        clocks = <&CLK_SYSIN>, <&CLOCKGEN_C 0>;
+                };
+
+                /*
+                 * Add a dummy clock for the HDMI PHY for the VCC input mux
+                 */
+                CLK_S_TMDS_FROMPHY: CLK_S_TMDS_FROMPHY {
+                        #clock-cells = <0>;
+                        compatible = "fixed-clock";
+                        clock-frequency = <0>;
+                };
+
+                CLOCKGEN_C_VCC: CLOCKGEN_C_VCC {
+                        #clock-cells = <1>;
+                        compatible = "st,stih416-clkgenc", "st,clkgen-vcc";
+                        reg = <0xfe8308ac 12>; /* SYSCFG2555,2556,2557 */
+
+                        clocks = <&CLK_S_VCC_HD>, <&CLOCKGEN_C 1>,
+                                 <&CLK_S_TMDS_FROMPHY>, <&CLOCKGEN_C 2>;
+
+                        clock-output-names  =
+                                "CLK_S_PIX_HDMI",  "CLK_S_PIX_DVO",
+                                "CLK_S_OUT_DVO",   "CLK_S_PIX_HD",
+                                "CLK_S_HDDAC",     "CLK_S_DENC",
+                                "CLK_S_SDDAC",     "CLK_S_PIX_MAIN",
+                                "CLK_S_PIX_AUX",   "CLK_S_STFE_FRC_0",
+                                "CLK_S_REF_MCRU",  "CLK_S_SLAVE_MCRU",
+                                "CLK_S_TMDS_HDMI", "CLK_S_HDMI_REJECT_PLL",
+                                "CLK_S_THSENS";
+                };
+
+                CLOCKGEN_D: CLOCKGEN_D {
+                        #clock-cells = <1>;
+                        compatible = "st,stih416-quadfs216", "st,quadfs";
+                        reg = <0xfee107e0 0x44>;
+
+                        clocks = <&CLK_SYSIN>;
+                        clock-output-names = "CLK_S_CCSC",
+                                             "CLK_S_STFE_FRC_1",
+                                             "CLK_S_TSOUT_1",
+                                             "CLK_S_MCHI";
+                };
+
+		/*
+		 * Frequency synthesizers on the MPE42
+		 */
+                CLOCKGEN_E: CLOCKGEN_E {
+                        #clock-cells = <1>;
+                        compatible = "st,stih416-quadfs660-E", "st,quadfs";
+                        reg = <0xfd3208bc 0xB0>;
+
+                        clocks = <&CLK_SYSIN>;
+                        clock-output-names = "CLK_M_PIX_MDTP_0",
+                                             "CLK_M_PIX_MDTP_1",
+                                             "CLK_M_PIX_MDTP_2",
+                                             "CLK_M_MPELPC";
+                };
+
+                CLOCKGEN_F: CLOCKGEN_F {
+                        #clock-cells = <1>;
+                        compatible = "st,stih416-quadfs660-F", "st,quadfs";
+                        reg = <0xfd320878 0xF0>;
+
+                        clocks = <&CLK_SYSIN>;
+                        clock-output-names = "CLK_M_MAIN_VIDFS",
+                                             "CLK_M_HVA_FS",
+                                             "CLK_M_FVDP_VCPU",
+					     "CLK_M_FVDP_PROC_FS";
+                };
+
+                CLK_M_FVDP_PROC: CLK_M_FVDP_PROC {
+                        #clock-cells = <0>;
+                        compatible = "st,stih416-clkgenf-vcc-fvdp", "st,clkgen-mux";
+                        reg = <0xfd320910 4>; /* SYSCFG8580 */
+
+                        clocks = <&CLK_M_A1_DIV2 0>, <&CLOCKGEN_F 3>;
+                };
+
+                CLK_M_HVA: CLK_M_HVA {
+                        #clock-cells = <0>;
+                        compatible = "st,stih416-clkgenf-vcc-hva", "st,clkgen-mux";
+                        reg = <0xfd690868 4>; /* SYSCFG9538 */
+
+                        clocks = <&CLOCKGEN_F 1>, <&CLK_M_A1_DIV0 3>;
+                };
+
+                CLK_M_F_VCC_HD: CLK_M_F_VCC_HD {
+                        #clock-cells = <0>;
+                        compatible = "st,stih416-clkgenf-vcc-hd", "st,clkgen-mux";
+                        reg = <0xfd32086c 4>; /* SYSCFG8539 */
+
+                        clocks = <&CLOCKGEN_C_VCC 7>, <&CLOCKGEN_F 0>;
+                };
+
+                CLK_M_F_VCC_SD: CLK_M_F_VCC_SD {
+                        #clock-cells = <0>;
+                        compatible = "st,stih416-clkgenf-vcc-sd", "st,clkgen-mux";
+                        reg = <0xfd32086c 4>; /* SYSCFG8539 */
+
+                        clocks = <&CLOCKGEN_C_VCC 8>, <&CLOCKGEN_F 1>;
+                };
+
+                /*
+                 * Add a dummy clock for the HDMIRx external signal clock
+                 */
+                CLK_M_PIX_HDMIRX_SAS: CLK_M_PIX_HDMIRX_SAS {
+                        #clock-cells = <0>;
+                        compatible = "fixed-clock";
+                        clock-frequency = <0>;
+                };
+
+                CLOCKGEN_F_VCC: CLOCKGEN_F_VCC {
+                        #clock-cells = <1>;
+                        compatible = "st,stih416-clkgenf", "st,clkgen-vcc";
+                        reg = <0xfd32086c 12>; /* SYSCFG8539,8540,8541 */
+
+                        clocks = <&CLK_M_F_VCC_HD>, <&CLK_M_F_VCC_SD>,
+                                 <&CLOCKGEN_F 0>, <&CLK_M_PIX_HDMIRX_SAS>;
+
+                        clock-output-names  =
+                                "CLK_M_PIX_MAIN_PIPE",  "CLK_M_PIX_AUX_PIPE",
+                                "CLK_M_PIX_MAIN_CRU",   "CLK_M_PIX_AUX_CRU",
+                                "CLK_M_XFER_BE_COMPO",  "CLK_M_XFER_PIP_COMPO",
+                                "CLK_M_XFER_AUX_COMPO", "CLK_M_VSENS",
+                                "CLK_M_PIX_HDMIRX_0",   "CLK_M_PIX_HDMIRX_1";
+                };
 	};
 };
-- 
1.9.0


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

* [PATCH v0 12/15] ARM: STi: DT: STiH416: 416 DT Entry for clockgen B/C/D/E/F
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

Patch adds DT entries for clockgen B/C/D/E/F

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
---
 arch/arm/boot/dts/stih416-clock.dtsi | 170 +++++++++++++++++++++++++++++++++++
 1 file changed, 170 insertions(+)

diff --git a/arch/arm/boot/dts/stih416-clock.dtsi b/arch/arm/boot/dts/stih416-clock.dtsi
index f63b0a1..6b2e387 100644
--- a/arch/arm/boot/dts/stih416-clock.dtsi
+++ b/arch/arm/boot/dts/stih416-clock.dtsi
@@ -503,5 +503,175 @@
 						/* Remaining outputs unused */
 			};
 		};
+                /*
+                 * Frequency synthesizers on the SASG2.
+                 *
+                 */
+                CLOCKGEN_B0: CLOCKGEN_B0 {
+                        #clock-cells = <1>;
+                        compatible = "st,stih416-quadfs216", "st,quadfs";
+                        reg = <0xfee108b4 0x44>;
+
+                        clocks = <&CLK_SYSIN>;
+                        clock-output-names = "CLK_S_USB48",
+                                             "CLK_S_DSS",
+                                             "CLK_S_STFE_FRC_2",
+                                             "CLK_S_THSENS_SCARD";
+                };
+
+                CLOCKGEN_B1: CLOCKGEN_B1 {
+                        #clock-cells = <1>;
+                        compatible = "st,stih416-quadfs216", "st,quadfs";
+                        reg = <0xfe8308c4 0x44>;
+
+                        clocks = <&CLK_SYSIN>;
+                        clock-output-names = "CLK_S_PCM_0",
+                                             "CLK_S_PCM_1",
+                                             "CLK_S_PCM_2",
+                                             "CLK_S_PCM_3";
+                };
+
+                CLOCKGEN_C: CLOCKGEN_C {
+                        #clock-cells = <1>;
+                        compatible = "st,stih416-quadfs432", "st,quadfs";
+                        reg = <0xfe8307d0 0x44>;
+
+                        clocks = <&CLK_SYSIN>;
+                        clock-output-names = "CLK_S_C_FS0_CH0",
+                                             "CLK_S_C_VCC_SD",
+                                             "CLK_S_C_FS0_CH2";
+                };
+
+                CLK_S_VCC_HD: CLK_S_VCC_HD {
+                        #clock-cells = <0>;
+                        compatible = "st,stih416-clkgenc-vcc-hd", "st,clkgen-mux";
+                        reg = <0xfe8308b8 4>; /* SYSCFG2558 */
+
+                        clocks = <&CLK_SYSIN>, <&CLOCKGEN_C 0>;
+                };
+
+                /*
+                 * Add a dummy clock for the HDMI PHY for the VCC input mux
+                 */
+                CLK_S_TMDS_FROMPHY: CLK_S_TMDS_FROMPHY {
+                        #clock-cells = <0>;
+                        compatible = "fixed-clock";
+                        clock-frequency = <0>;
+                };
+
+                CLOCKGEN_C_VCC: CLOCKGEN_C_VCC {
+                        #clock-cells = <1>;
+                        compatible = "st,stih416-clkgenc", "st,clkgen-vcc";
+                        reg = <0xfe8308ac 12>; /* SYSCFG2555,2556,2557 */
+
+                        clocks = <&CLK_S_VCC_HD>, <&CLOCKGEN_C 1>,
+                                 <&CLK_S_TMDS_FROMPHY>, <&CLOCKGEN_C 2>;
+
+                        clock-output-names  =
+                                "CLK_S_PIX_HDMI",  "CLK_S_PIX_DVO",
+                                "CLK_S_OUT_DVO",   "CLK_S_PIX_HD",
+                                "CLK_S_HDDAC",     "CLK_S_DENC",
+                                "CLK_S_SDDAC",     "CLK_S_PIX_MAIN",
+                                "CLK_S_PIX_AUX",   "CLK_S_STFE_FRC_0",
+                                "CLK_S_REF_MCRU",  "CLK_S_SLAVE_MCRU",
+                                "CLK_S_TMDS_HDMI", "CLK_S_HDMI_REJECT_PLL",
+                                "CLK_S_THSENS";
+                };
+
+                CLOCKGEN_D: CLOCKGEN_D {
+                        #clock-cells = <1>;
+                        compatible = "st,stih416-quadfs216", "st,quadfs";
+                        reg = <0xfee107e0 0x44>;
+
+                        clocks = <&CLK_SYSIN>;
+                        clock-output-names = "CLK_S_CCSC",
+                                             "CLK_S_STFE_FRC_1",
+                                             "CLK_S_TSOUT_1",
+                                             "CLK_S_MCHI";
+                };
+
+		/*
+		 * Frequency synthesizers on the MPE42
+		 */
+                CLOCKGEN_E: CLOCKGEN_E {
+                        #clock-cells = <1>;
+                        compatible = "st,stih416-quadfs660-E", "st,quadfs";
+                        reg = <0xfd3208bc 0xB0>;
+
+                        clocks = <&CLK_SYSIN>;
+                        clock-output-names = "CLK_M_PIX_MDTP_0",
+                                             "CLK_M_PIX_MDTP_1",
+                                             "CLK_M_PIX_MDTP_2",
+                                             "CLK_M_MPELPC";
+                };
+
+                CLOCKGEN_F: CLOCKGEN_F {
+                        #clock-cells = <1>;
+                        compatible = "st,stih416-quadfs660-F", "st,quadfs";
+                        reg = <0xfd320878 0xF0>;
+
+                        clocks = <&CLK_SYSIN>;
+                        clock-output-names = "CLK_M_MAIN_VIDFS",
+                                             "CLK_M_HVA_FS",
+                                             "CLK_M_FVDP_VCPU",
+					     "CLK_M_FVDP_PROC_FS";
+                };
+
+                CLK_M_FVDP_PROC: CLK_M_FVDP_PROC {
+                        #clock-cells = <0>;
+                        compatible = "st,stih416-clkgenf-vcc-fvdp", "st,clkgen-mux";
+                        reg = <0xfd320910 4>; /* SYSCFG8580 */
+
+                        clocks = <&CLK_M_A1_DIV2 0>, <&CLOCKGEN_F 3>;
+                };
+
+                CLK_M_HVA: CLK_M_HVA {
+                        #clock-cells = <0>;
+                        compatible = "st,stih416-clkgenf-vcc-hva", "st,clkgen-mux";
+                        reg = <0xfd690868 4>; /* SYSCFG9538 */
+
+                        clocks = <&CLOCKGEN_F 1>, <&CLK_M_A1_DIV0 3>;
+                };
+
+                CLK_M_F_VCC_HD: CLK_M_F_VCC_HD {
+                        #clock-cells = <0>;
+                        compatible = "st,stih416-clkgenf-vcc-hd", "st,clkgen-mux";
+                        reg = <0xfd32086c 4>; /* SYSCFG8539 */
+
+                        clocks = <&CLOCKGEN_C_VCC 7>, <&CLOCKGEN_F 0>;
+                };
+
+                CLK_M_F_VCC_SD: CLK_M_F_VCC_SD {
+                        #clock-cells = <0>;
+                        compatible = "st,stih416-clkgenf-vcc-sd", "st,clkgen-mux";
+                        reg = <0xfd32086c 4>; /* SYSCFG8539 */
+
+                        clocks = <&CLOCKGEN_C_VCC 8>, <&CLOCKGEN_F 1>;
+                };
+
+                /*
+                 * Add a dummy clock for the HDMIRx external signal clock
+                 */
+                CLK_M_PIX_HDMIRX_SAS: CLK_M_PIX_HDMIRX_SAS {
+                        #clock-cells = <0>;
+                        compatible = "fixed-clock";
+                        clock-frequency = <0>;
+                };
+
+                CLOCKGEN_F_VCC: CLOCKGEN_F_VCC {
+                        #clock-cells = <1>;
+                        compatible = "st,stih416-clkgenf", "st,clkgen-vcc";
+                        reg = <0xfd32086c 12>; /* SYSCFG8539,8540,8541 */
+
+                        clocks = <&CLK_M_F_VCC_HD>, <&CLK_M_F_VCC_SD>,
+                                 <&CLOCKGEN_F 0>, <&CLK_M_PIX_HDMIRX_SAS>;
+
+                        clock-output-names  =
+                                "CLK_M_PIX_MAIN_PIPE",  "CLK_M_PIX_AUX_PIPE",
+                                "CLK_M_PIX_MAIN_CRU",   "CLK_M_PIX_AUX_CRU",
+                                "CLK_M_XFER_BE_COMPO",  "CLK_M_XFER_PIP_COMPO",
+                                "CLK_M_XFER_AUX_COMPO", "CLK_M_VSENS",
+                                "CLK_M_PIX_HDMIRX_0",   "CLK_M_PIX_HDMIRX_1";
+                };
 	};
 };
-- 
1.9.0

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

* [PATCH v0 13/15] ARM: STi: DT: STiH416: 416 DT Entry for clockgen A9/DDR/GPU
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: mturquette, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, rob, linux, devicetree, linux-doc, linux-kernel,
	linux-arm-kernel
  Cc: Lee Jones, Gabriel Fernandez, Pankaj Dev

Patch adds DT entries for clockgen A9/DDR/GPU

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
---
 arch/arm/boot/dts/stih416-clock.dtsi | 79 ++++++++++++++++++++++++++++++++----
 1 file changed, 70 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/stih416-clock.dtsi b/arch/arm/boot/dts/stih416-clock.dtsi
index 6b2e387..5ff0e6f 100644
--- a/arch/arm/boot/dts/stih416-clock.dtsi
+++ b/arch/arm/boot/dts/stih416-clock.dtsi
@@ -26,15 +26,6 @@
 		};
 
 		/*
-		 * ARM Peripheral clock for timers
-		 */
-		arm_periph_clk: arm_periph_clk {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <600000000>;
-		};
-
-		/*
 		 * ClockGenAs on SASG2
 		 */
 		clockgenA@fee62000 {
@@ -503,6 +494,44 @@
 						/* Remaining outputs unused */
 			};
 		};
+
+		/*
+		 * A9 PLL.
+		 *
+		 */
+		clockgenA9 {
+			reg = <0xfdde08b0 0x70>;
+
+			CLOCKGEN_A9_PLL: CLOCKGEN_A9_PLL {
+				#clock-cells = <1>;
+				compatible = "st,stih416-plls-c32-a9", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+				clock-output-names = "CLOCKGEN_A9_PLL_ODF";
+			};
+		};
+
+		/*
+		 * ARM CPU related clocks.
+		 */
+		CLK_M_A9: CLK_M_A9 {
+			#clock-cells = <0>;
+			compatible = "st,stih416-clkgen-a9-mux", "st,clkgen-mux";
+			reg = <0xfdde08ac 0x4>;
+			clocks = <&CLOCKGEN_A9_PLL 0>, <&CLOCKGEN_A9_PLL 0>, <&CLK_M_A0_DIV1 2>, <&CLK_M_A9_EXT2F_DIV2>;
+		};
+
+		/*
+		 * ARM Peripheral clock for timers
+		 */
+		arm_periph_clk: CLK_M_A9_PERIPHS {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&CLK_M_A9>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+
                 /*
                  * Frequency synthesizers on the SASG2.
                  *
@@ -673,5 +702,37 @@
                                 "CLK_M_XFER_AUX_COMPO", "CLK_M_VSENS",
                                 "CLK_M_PIX_HDMIRX_0",   "CLK_M_PIX_HDMIRX_1";
                 };
+
+		/*
+		 * DDR PLL.
+		 *
+		 */
+		clockgenDDR {
+			reg = <0xfdde07d8 0x110>;
+
+			CLOCKGEN_DDR_PLL: CLOCKGEN_DDR_PLL {
+				#clock-cells = <1>;
+				compatible = "st,stih416-plls-c32-ddr", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+				clock-output-names = "CLOCKGEN_DDR0", "CLOCKGEN_DDR1";
+			};
+		};
+
+		/*
+		 * GPU PLL.
+		 *
+		 */
+		clockgenGPU {
+			reg = <0xfd68ff00 0x910>;
+
+			CLOCKGEN_GPU_PLL: CLOCKGEN_GPU_PLL {
+				#clock-cells = <1>;
+				compatible = "st,stih416-gpu-pll-c32", "st,clkgengpu-pll-c32";
+
+				clocks = <&CLK_SYSIN>;
+				clock-output-names = "CLOCKGEN_GPU_PLL";
+			};
+		};
 	};
 };
-- 
1.9.0


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

* [PATCH v0 13/15] ARM: STi: DT: STiH416: 416 DT Entry for clockgen A9/DDR/GPU
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: mturquette-QSEj5FYQhm4dnm+yROfE0A,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, pawel.moll-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
	galak-sgV2jX0FEOL9JmXXK+q4OQ, rob-VoJi6FS/r0vR7s880joybQ,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Lee Jones, Gabriel Fernandez, Pankaj Dev

Patch adds DT entries for clockgen A9/DDR/GPU

Signed-off-by: Pankaj Dev <pankaj.dev-qxv4g6HH51o@public.gmane.org>
---
 arch/arm/boot/dts/stih416-clock.dtsi | 79 ++++++++++++++++++++++++++++++++----
 1 file changed, 70 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/stih416-clock.dtsi b/arch/arm/boot/dts/stih416-clock.dtsi
index 6b2e387..5ff0e6f 100644
--- a/arch/arm/boot/dts/stih416-clock.dtsi
+++ b/arch/arm/boot/dts/stih416-clock.dtsi
@@ -26,15 +26,6 @@
 		};
 
 		/*
-		 * ARM Peripheral clock for timers
-		 */
-		arm_periph_clk: arm_periph_clk {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <600000000>;
-		};
-
-		/*
 		 * ClockGenAs on SASG2
 		 */
 		clockgenA@fee62000 {
@@ -503,6 +494,44 @@
 						/* Remaining outputs unused */
 			};
 		};
+
+		/*
+		 * A9 PLL.
+		 *
+		 */
+		clockgenA9 {
+			reg = <0xfdde08b0 0x70>;
+
+			CLOCKGEN_A9_PLL: CLOCKGEN_A9_PLL {
+				#clock-cells = <1>;
+				compatible = "st,stih416-plls-c32-a9", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+				clock-output-names = "CLOCKGEN_A9_PLL_ODF";
+			};
+		};
+
+		/*
+		 * ARM CPU related clocks.
+		 */
+		CLK_M_A9: CLK_M_A9 {
+			#clock-cells = <0>;
+			compatible = "st,stih416-clkgen-a9-mux", "st,clkgen-mux";
+			reg = <0xfdde08ac 0x4>;
+			clocks = <&CLOCKGEN_A9_PLL 0>, <&CLOCKGEN_A9_PLL 0>, <&CLK_M_A0_DIV1 2>, <&CLK_M_A9_EXT2F_DIV2>;
+		};
+
+		/*
+		 * ARM Peripheral clock for timers
+		 */
+		arm_periph_clk: CLK_M_A9_PERIPHS {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&CLK_M_A9>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+
                 /*
                  * Frequency synthesizers on the SASG2.
                  *
@@ -673,5 +702,37 @@
                                 "CLK_M_XFER_AUX_COMPO", "CLK_M_VSENS",
                                 "CLK_M_PIX_HDMIRX_0",   "CLK_M_PIX_HDMIRX_1";
                 };
+
+		/*
+		 * DDR PLL.
+		 *
+		 */
+		clockgenDDR {
+			reg = <0xfdde07d8 0x110>;
+
+			CLOCKGEN_DDR_PLL: CLOCKGEN_DDR_PLL {
+				#clock-cells = <1>;
+				compatible = "st,stih416-plls-c32-ddr", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+				clock-output-names = "CLOCKGEN_DDR0", "CLOCKGEN_DDR1";
+			};
+		};
+
+		/*
+		 * GPU PLL.
+		 *
+		 */
+		clockgenGPU {
+			reg = <0xfd68ff00 0x910>;
+
+			CLOCKGEN_GPU_PLL: CLOCKGEN_GPU_PLL {
+				#clock-cells = <1>;
+				compatible = "st,stih416-gpu-pll-c32", "st,clkgengpu-pll-c32";
+
+				clocks = <&CLK_SYSIN>;
+				clock-output-names = "CLOCKGEN_GPU_PLL";
+			};
+		};
 	};
 };
-- 
1.9.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v0 13/15] ARM: STi: DT: STiH416: 416 DT Entry for clockgen A9/DDR/GPU
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

Patch adds DT entries for clockgen A9/DDR/GPU

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
---
 arch/arm/boot/dts/stih416-clock.dtsi | 79 ++++++++++++++++++++++++++++++++----
 1 file changed, 70 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/stih416-clock.dtsi b/arch/arm/boot/dts/stih416-clock.dtsi
index 6b2e387..5ff0e6f 100644
--- a/arch/arm/boot/dts/stih416-clock.dtsi
+++ b/arch/arm/boot/dts/stih416-clock.dtsi
@@ -26,15 +26,6 @@
 		};
 
 		/*
-		 * ARM Peripheral clock for timers
-		 */
-		arm_periph_clk: arm_periph_clk {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <600000000>;
-		};
-
-		/*
 		 * ClockGenAs on SASG2
 		 */
 		clockgenA at fee62000 {
@@ -503,6 +494,44 @@
 						/* Remaining outputs unused */
 			};
 		};
+
+		/*
+		 * A9 PLL.
+		 *
+		 */
+		clockgenA9 {
+			reg = <0xfdde08b0 0x70>;
+
+			CLOCKGEN_A9_PLL: CLOCKGEN_A9_PLL {
+				#clock-cells = <1>;
+				compatible = "st,stih416-plls-c32-a9", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+				clock-output-names = "CLOCKGEN_A9_PLL_ODF";
+			};
+		};
+
+		/*
+		 * ARM CPU related clocks.
+		 */
+		CLK_M_A9: CLK_M_A9 {
+			#clock-cells = <0>;
+			compatible = "st,stih416-clkgen-a9-mux", "st,clkgen-mux";
+			reg = <0xfdde08ac 0x4>;
+			clocks = <&CLOCKGEN_A9_PLL 0>, <&CLOCKGEN_A9_PLL 0>, <&CLK_M_A0_DIV1 2>, <&CLK_M_A9_EXT2F_DIV2>;
+		};
+
+		/*
+		 * ARM Peripheral clock for timers
+		 */
+		arm_periph_clk: CLK_M_A9_PERIPHS {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&CLK_M_A9>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+
                 /*
                  * Frequency synthesizers on the SASG2.
                  *
@@ -673,5 +702,37 @@
                                 "CLK_M_XFER_AUX_COMPO", "CLK_M_VSENS",
                                 "CLK_M_PIX_HDMIRX_0",   "CLK_M_PIX_HDMIRX_1";
                 };
+
+		/*
+		 * DDR PLL.
+		 *
+		 */
+		clockgenDDR {
+			reg = <0xfdde07d8 0x110>;
+
+			CLOCKGEN_DDR_PLL: CLOCKGEN_DDR_PLL {
+				#clock-cells = <1>;
+				compatible = "st,stih416-plls-c32-ddr", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+				clock-output-names = "CLOCKGEN_DDR0", "CLOCKGEN_DDR1";
+			};
+		};
+
+		/*
+		 * GPU PLL.
+		 *
+		 */
+		clockgenGPU {
+			reg = <0xfd68ff00 0x910>;
+
+			CLOCKGEN_GPU_PLL: CLOCKGEN_GPU_PLL {
+				#clock-cells = <1>;
+				compatible = "st,stih416-gpu-pll-c32", "st,clkgengpu-pll-c32";
+
+				clocks = <&CLK_SYSIN>;
+				clock-output-names = "CLOCKGEN_GPU_PLL";
+			};
+		};
 	};
 };
-- 
1.9.0

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

* [PATCH v0 14/15] ARM: STi: DT: STiH415: 415 DT Entry for clockgen A0/1/10/11/12
  2014-02-27 15:24 ` Gabriel FERNANDEZ
  (?)
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  -1 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: mturquette, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, rob, linux, devicetree, linux-doc, linux-kernel,
	linux-arm-kernel
  Cc: Lee Jones, Gabriel Fernandez, Pankaj Dev

Patch adds DT entries for clockgen A0/1/10/11/12

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 arch/arm/boot/dts/stih415-clks.h     |  11 +
 arch/arm/boot/dts/stih415-clock.dtsi | 475 ++++++++++++++++++++++++++++++++++-
 arch/arm/boot/dts/stih415.dtsi       |   6 +-
 3 files changed, 484 insertions(+), 8 deletions(-)
 create mode 100644 arch/arm/boot/dts/stih415-clks.h

diff --git a/arch/arm/boot/dts/stih415-clks.h b/arch/arm/boot/dts/stih415-clks.h
new file mode 100644
index 0000000..341c05b
--- /dev/null
+++ b/arch/arm/boot/dts/stih415-clks.h
@@ -0,0 +1,11 @@
+/*
+ * This header provides constants clk index STMicroelectronics
+ * STiH415 SoC.
+ */
+#ifndef _CLK_STIH415
+#define _CLK_STIH415
+
+/* CLOCKGEN A0 */
+#define CLK_S_ICN_REG_0		0
+
+#endif
diff --git a/arch/arm/boot/dts/stih415-clock.dtsi b/arch/arm/boot/dts/stih415-clock.dtsi
index 174c799..24a7508 100644
--- a/arch/arm/boot/dts/stih415-clock.dtsi
+++ b/arch/arm/boot/dts/stih415-clock.dtsi
@@ -5,8 +5,15 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+
+#include "stih415-clks.h"
+
 / {
 	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
 		/*
 		 * Fixed 30MHz oscillator input to SoC
 		 */
@@ -26,13 +33,471 @@
 		};
 
 		/*
-		 * Bootloader initialized system infrastructure clock for
-		 * serial devices.
+		 * ClockGenAs on SASG1
+		 */
+		clockgenA@fee62000 {
+			reg = <0xfee62000 0xb48>;
+
+			CLK_S_A0_PLL: CLK_S_A0_PLL {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-plls-c65";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_S_A0_PLL0_HS",
+						     "CLK_S_A0_PLL0_LS",
+						     "CLK_S_A0_PLL1";
+			};
+
+			CLK_S_A0_OSC_PREDIV: CLK_S_A0_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c65",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_S_A0_OSC_PREDIV";
+			};
+
+			CLK_S_A0_HS: CLK_S_A0_HS {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c65-hs",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_S_A0_OSC_PREDIV>,
+					 <&CLK_S_A0_PLL 0>, /* PLL0 HS */
+					 <&CLK_S_A0_PLL 2>; /* PLL1 */
+
+				clock-output-names = "CLK_S_FDMA_0",
+						     "CLK_S_FDMA_1",
+						     ""; /* CLK_S_JIT_SENSE */
+						     /* Fourth output unused */
+			};
+
+			CLK_S_A0_LS: CLK_S_A0_LS {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c65-ls",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_S_A0_OSC_PREDIV>,
+					 <&CLK_S_A0_PLL 1>, /* PLL0 LS */
+					 <&CLK_S_A0_PLL 2>; /* PLL1 */
+
+				clock-output-names = "CLK_S_ICN_REG_0",
+						     "CLK_S_ICN_IF_0",
+						     "CLK_S_ICN_REG_LP_0",
+						     "CLK_S_EMISS",
+						     "CLK_S_ETH1_PHY",
+						     "CLK_S_MII_REF_OUT";
+						 /* Remaining outputs unused */
+			};
+		};
+
+		clockgenA@fee81000 {
+			reg = <0xfee81000 0xb48>;
+
+			CLK_S_A1_PLL: CLK_S_A1_PLL {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-plls-c65";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_S_A1_PLL0_HS",
+						     "CLK_S_A1_PLL0_LS",
+						     "CLK_S_A1_PLL1";
+			};
+
+			CLK_S_A1_OSC_PREDIV: CLK_S_A1_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c65",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_S_A1_OSC_PREDIV";
+			};
+
+			CLK_S_A1_HS: CLK_S_A1_HS {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c65-hs",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_S_A1_OSC_PREDIV>,
+					 <&CLK_S_A1_PLL 0>, /* PLL0 HS */
+					 <&CLK_S_A1_PLL 2>; /* PLL1 */
+
+				clock-output-names = "", /* Reserved */
+						     "", /* Reserved */
+						     "CLK_S_STAC_PHY",
+						     "CLK_S_VTAC_TX_PHY";
+			};
+
+			CLK_S_A1_LS: CLK_S_A1_LS {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c65-ls",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_S_A1_OSC_PREDIV>,
+					 <&CLK_S_A1_PLL 1>, /* PLL0 LS */
+					 <&CLK_S_A1_PLL 2>; /* PLL1 */
+
+				clock-output-names = "CLK_S_ICN_IF_2",
+						     "CLK_S_CARD_MMC",
+						     "CLK_S_ICN_IF_1",
+						     "CLK_S_GMAC0_PHY",
+						     "CLK_S_NAND_CTRL",
+						     "", /* Reserved */
+						     "CLK_S_MII0_REF_OUT",
+						     ""; /* CLK_S_STAC_SYS */
+						 /* Remaining outputs unused */
+			};
+		};
+
+		/*
+		 * ClockGenAs on MPE41
 		 */
-		CLKS_ICN_REG_0: CLKS_ICN_REG_0 {
+		clockgenA@fde12000 {
+			reg = <0xfde12000 0xb50>;
+
+			CLK_M_A0_PLL0: CLK_M_A0_PLL0 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-0", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A0_PLL0_PHI0",
+						     "CLK_M_A0_PLL0_PHI1",
+						     "CLK_M_A0_PLL0_PHI2",
+						     "CLK_M_A0_PLL0_PHI3";
+			};
+
+			CLK_M_A0_PLL1: CLK_M_A0_PLL1 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-1", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A0_PLL1_PHI0",
+						     "CLK_M_A0_PLL1_PHI1",
+						     "CLK_M_A0_PLL1_PHI2",
+						     "CLK_M_A0_PLL1_PHI3";
+			};
+
+			CLK_M_A0_OSC_PREDIV: CLK_M_A0_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c32",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A0_OSC_PREDIV";
+			};
+
+			CLK_M_A0_DIV0: CLK_M_A0_DIV0 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf0",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A0_OSC_PREDIV>,
+					 <&CLK_M_A0_PLL0 0>, /* PLL0 PHI0 */
+					 <&CLK_M_A0_PLL1 0>; /* PLL1 PHI0 */
+
+				clock-output-names = "CLK_M_APB_PM", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "CLK_M_PP_DMU_0",
+						     "CLK_M_PP_DMU_1",
+						     "CLK_M_ICM_DISP",
+						     ""; /* Unused */
+			};
+
+			CLK_M_A0_DIV1: CLK_M_A0_DIV1 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf1",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A0_OSC_PREDIV>,
+					 <&CLK_M_A0_PLL0 1>, /* PLL0 PHI1 */
+					 <&CLK_M_A0_PLL1 1>; /* PLL1 PHI1 */
+
+				clock-output-names = "", /* Unused */
+						     "", /* Unused */
+						     "CLK_M_A9_EXT2F",
+						     "CLK_M_ST40RT",
+						     "CLK_M_ST231_DMU_0",
+						     "CLK_M_ST231_DMU_1",
+						     "CLK_M_ST231_AUD",
+						     "CLK_M_ST231_GP_0";
+			};
+
+			CLK_M_A0_DIV2: CLK_M_A0_DIV2 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf2",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A0_OSC_PREDIV>,
+					 <&CLK_M_A0_PLL0 2>, /* PLL0 PHI2 */
+					 <&CLK_M_A0_PLL1 2>; /* PLL1 PHI2 */
+
+				clock-output-names = "CLK_M_ST231_GP_1",
+						     "CLK_M_ICN_CPU",
+						     "CLK_M_ICN_STAC",
+						     "CLK_M_ICN_DMU_0",
+						     "CLK_M_ICN_DMU_1",
+						     "", /* Unused */
+						     "", /* Unused */
+						     ""; /* Unused */
+			};
+
+			CLK_M_A0_DIV3: CLK_M_A0_DIV3 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf3",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A0_OSC_PREDIV>,
+					 <&CLK_M_A0_PLL0 3>, /* PLL0 PHI3 */
+					 <&CLK_M_A0_PLL1 3>; /* PLL1 PHI3 */
+
+				clock-output-names = "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "CLK_M_ICN_ERAM",
+						     "CLK_M_A9_TRACE";
+			};
+		};
+
+		clockgenA@fd6db000 {
+			reg = <0xfd6db000 0xb50>;
+
+			CLK_M_A1_PLL0: CLK_M_A1_PLL0 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-0", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A1_PLL0_PHI0",
+						     "CLK_M_A1_PLL0_PHI1",
+						     "CLK_M_A1_PLL0_PHI2",
+						     "CLK_M_A1_PLL0_PHI3";
+			};
+
+			CLK_M_A1_PLL1: CLK_M_A1_PLL1 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-1", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A1_PLL1_PHI0",
+						     "CLK_M_A1_PLL1_PHI1",
+						     "CLK_M_A1_PLL1_PHI2",
+						     "CLK_M_A1_PLL1_PHI3";
+			};
+
+			CLK_M_A1_OSC_PREDIV: CLK_M_A1_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c32",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A1_OSC_PREDIV";
+			};
+
+			CLK_M_A1_DIV0: CLK_M_A1_DIV0 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf0",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A1_OSC_PREDIV>,
+					 <&CLK_M_A1_PLL0 0>, /* PLL0 PHI0 */
+					 <&CLK_M_A1_PLL1 0>; /* PLL1 PHI0 */
+
+				clock-output-names = "CLK_M_FDMA_12",
+						     "CLK_M_FDMA_10",
+						     "CLK_M_FDMA_11",
+						     "CLK_M_HVA_LMI",
+						     "CLK_M_PROC_SC",
+						     "CLK_M_TP",
+						     "CLK_M_ICN_GPU",
+						     "CLK_M_ICN_VDP_0";
+			};
+
+			CLK_M_A1_DIV1: CLK_M_A1_DIV1 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf1",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A1_OSC_PREDIV>,
+					 <&CLK_M_A1_PLL0 1>, /* PLL0 PHI1 */
+					 <&CLK_M_A1_PLL1 1>; /* PLL1 PHI1 */
+
+				clock-output-names = "CLK_M_ICN_VDP_1",
+						     "CLK_M_ICN_VDP_2",
+						     "CLK_M_ICN_VDP_3",
+						     "CLK_M_PRV_T1_BUS",
+						     "CLK_M_ICN_VDP_4",
+						     "CLK_M_ICN_REG_10",
+						     "", /* Unused */
+						     ""; /* CLK_M_ICN_ST231 */
+			};
+
+			CLK_M_A1_DIV2: CLK_M_A1_DIV2 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf2",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A1_OSC_PREDIV>,
+					 <&CLK_M_A1_PLL0 2>, /* PLL0 PHI2 */
+					 <&CLK_M_A1_PLL1 2>; /* PLL1 PHI2 */
+
+				clock-output-names = "CLK_M_FVDP_PROC_ALT",
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     ""; /* Unused */
+			};
+
+			CLK_M_A1_DIV3: CLK_M_A1_DIV3 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf3",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A1_OSC_PREDIV>,
+					 <&CLK_M_A1_PLL0 3>, /* PLL0 PHI3 */
+					 <&CLK_M_A1_PLL1 3>; /* PLL1 PHI3 */
+
+				clock-output-names = "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     ""; /* Unused */
+			};
+		};
+
+		CLK_M_A9_EXT2F_DIV2: CLK_M_A9_EXT2F_DIV2S {
 			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <100000000>;
+			compatible = "fixed-factor-clock";
+			clocks = <&CLK_M_A0_DIV1 2>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+
+		clockgenA@fd345000 {
+			reg = <0xfd345000 0xb50>;
+
+			CLK_M_A2_PLL0: CLK_M_A2_PLL0 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-0", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A2_PLL0_PHI0",
+						     "CLK_M_A2_PLL0_PHI1",
+						     "CLK_M_A2_PLL0_PHI2",
+						     "CLK_M_A2_PLL0_PHI3";
+			};
+
+			CLK_M_A2_PLL1: CLK_M_A2_PLL1 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-1", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A2_PLL1_PHI0",
+						     "CLK_M_A2_PLL1_PHI1",
+						     "CLK_M_A2_PLL1_PHI2",
+						     "CLK_M_A2_PLL1_PHI3";
+			};
+
+			CLK_M_A2_OSC_PREDIV: CLK_M_A2_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c32",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A2_OSC_PREDIV";
+			};
+
+			CLK_M_A2_DIV0: CLK_M_A2_DIV0 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf0",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A2_OSC_PREDIV>,
+					 <&CLK_M_A2_PLL0 0>, /* PLL0 PHI0 */
+					 <&CLK_M_A2_PLL1 0>; /* PLL1 PHI0 */
+
+				clock-output-names = "CLK_M_VTAC_MAIN_PHY",
+						     "CLK_M_VTAC_AUX_PHY",
+						     "CLK_M_STAC_PHY",
+						     "CLK_M_STAC_SYS",
+						     "", /* CLK_M_MPESTAC_PG */
+						     "", /* CLK_M_MPESTAC_WC */
+						     "", /* CLK_M_MPEVTACAUX_PG*/
+						     ""; /* CLK_M_MPEVTACMAIN_PG*/
+			};
+
+			CLK_M_A2_DIV1: CLK_M_A2_DIV1 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf1",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A2_OSC_PREDIV>,
+					 <&CLK_M_A2_PLL0 1>, /* PLL0 PHI1 */
+					 <&CLK_M_A2_PLL1 1>; /* PLL1 PHI1 */
+
+				clock-output-names = "", /* CLK_M_MPEVTACRX0_WC */
+						     "", /* CLK_M_MPEVTACRX1_WC */
+						     "CLK_M_COMPO_MAIN",
+						     "CLK_M_COMPO_AUX",
+						     "CLK_M_BDISP_0",
+						     "CLK_M_BDISP_1",
+						     "CLK_M_ICN_BDISP_0",
+						     "CLK_M_ICN_BDISP_1";
+			};
+
+			CLK_M_A2_DIV2: CLK_M_A2_DIV2 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf2",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A2_OSC_PREDIV>,
+					 <&CLK_M_A2_PLL0 2>, /* PLL0 PHI2 */
+					 <&CLK_M_A2_PLL1 2>; /* PLL1 PHI2 */
+
+				clock-output-names = "", /* CLK_M_ICN_HQVDP0 */
+						     "", /* CLK_M_ICN_HQVDP1 */
+						     "CLK_M_ICN_COMPO",
+						     "", /* CLK_M_ICN_VDPAUX */
+						     "CLK_M_ICN_TS",
+						     "CLK_M_ICN_REG_LP_10",
+						     "CLK_M_DCEPHY_IMPCTRL",
+						     ""; /* Unused */
+			};
+
+			CLK_M_A2_DIV3: CLK_M_A2_DIV3 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf3",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A2_OSC_PREDIV>,
+					 <&CLK_M_A2_PLL0 3>, /* PLL0 PHI3 */
+					 <&CLK_M_A2_PLL1 3>; /* PLL1 PHI3 */
+
+				clock-output-names = ""; /* Unused */
+						/* Remaining outputs unused */
+			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/stih415.dtsi b/arch/arm/boot/dts/stih415.dtsi
index d9c7dd1..fcda687 100644
--- a/arch/arm/boot/dts/stih415.dtsi
+++ b/arch/arm/boot/dts/stih415.dtsi
@@ -71,7 +71,7 @@
 			interrupts	= <0 197 0>;
 			pinctrl-names 	= "default";
 			pinctrl-0 	= <&pinctrl_serial2>;
-			clocks		= <&CLKS_ICN_REG_0>;
+			clocks		= <&CLK_S_A0_LS CLK_S_ICN_REG_0>;
 		};
 
 		/* SBC comms block ASCs in SASG1 */
@@ -89,7 +89,7 @@
 			compatible	= "st,comms-ssc4-i2c";
 			reg		= <0xfed40000 0x110>;
 			interrupts	= <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
-			clocks		= <&CLKS_ICN_REG_0>;
+			clocks		= <&CLK_S_A0_LS CLK_S_ICN_REG_0>;
 			clock-names	= "ssc";
 			clock-frequency = <400000>;
 			pinctrl-names	= "default";
@@ -102,7 +102,7 @@
 			compatible	= "st,comms-ssc4-i2c";
 			reg		= <0xfed41000 0x110>;
 			interrupts	= <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
-			clocks		= <&CLKS_ICN_REG_0>;
+			clocks		= <&CLK_S_A0_LS CLK_S_ICN_REG_0>;
 			clock-names	= "ssc";
 			clock-frequency = <400000>;
 			pinctrl-names	= "default";
-- 
1.9.0


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

* [PATCH v0 14/15] ARM: STi: DT: STiH415: 415 DT Entry for clockgen A0/1/10/11/12
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: mturquette, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, rob, linux, devicetree, linux-doc, linux-kernel,
	linux-arm-kernel
  Cc: Pankaj Dev, Lee Jones, Gabriel Fernandez

Patch adds DT entries for clockgen A0/1/10/11/12

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 arch/arm/boot/dts/stih415-clks.h     |  11 +
 arch/arm/boot/dts/stih415-clock.dtsi | 475 ++++++++++++++++++++++++++++++++++-
 arch/arm/boot/dts/stih415.dtsi       |   6 +-
 3 files changed, 484 insertions(+), 8 deletions(-)
 create mode 100644 arch/arm/boot/dts/stih415-clks.h

diff --git a/arch/arm/boot/dts/stih415-clks.h b/arch/arm/boot/dts/stih415-clks.h
new file mode 100644
index 0000000..341c05b
--- /dev/null
+++ b/arch/arm/boot/dts/stih415-clks.h
@@ -0,0 +1,11 @@
+/*
+ * This header provides constants clk index STMicroelectronics
+ * STiH415 SoC.
+ */
+#ifndef _CLK_STIH415
+#define _CLK_STIH415
+
+/* CLOCKGEN A0 */
+#define CLK_S_ICN_REG_0		0
+
+#endif
diff --git a/arch/arm/boot/dts/stih415-clock.dtsi b/arch/arm/boot/dts/stih415-clock.dtsi
index 174c799..24a7508 100644
--- a/arch/arm/boot/dts/stih415-clock.dtsi
+++ b/arch/arm/boot/dts/stih415-clock.dtsi
@@ -5,8 +5,15 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+
+#include "stih415-clks.h"
+
 / {
 	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
 		/*
 		 * Fixed 30MHz oscillator input to SoC
 		 */
@@ -26,13 +33,471 @@
 		};
 
 		/*
-		 * Bootloader initialized system infrastructure clock for
-		 * serial devices.
+		 * ClockGenAs on SASG1
+		 */
+		clockgenA@fee62000 {
+			reg = <0xfee62000 0xb48>;
+
+			CLK_S_A0_PLL: CLK_S_A0_PLL {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-plls-c65";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_S_A0_PLL0_HS",
+						     "CLK_S_A0_PLL0_LS",
+						     "CLK_S_A0_PLL1";
+			};
+
+			CLK_S_A0_OSC_PREDIV: CLK_S_A0_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c65",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_S_A0_OSC_PREDIV";
+			};
+
+			CLK_S_A0_HS: CLK_S_A0_HS {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c65-hs",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_S_A0_OSC_PREDIV>,
+					 <&CLK_S_A0_PLL 0>, /* PLL0 HS */
+					 <&CLK_S_A0_PLL 2>; /* PLL1 */
+
+				clock-output-names = "CLK_S_FDMA_0",
+						     "CLK_S_FDMA_1",
+						     ""; /* CLK_S_JIT_SENSE */
+						     /* Fourth output unused */
+			};
+
+			CLK_S_A0_LS: CLK_S_A0_LS {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c65-ls",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_S_A0_OSC_PREDIV>,
+					 <&CLK_S_A0_PLL 1>, /* PLL0 LS */
+					 <&CLK_S_A0_PLL 2>; /* PLL1 */
+
+				clock-output-names = "CLK_S_ICN_REG_0",
+						     "CLK_S_ICN_IF_0",
+						     "CLK_S_ICN_REG_LP_0",
+						     "CLK_S_EMISS",
+						     "CLK_S_ETH1_PHY",
+						     "CLK_S_MII_REF_OUT";
+						 /* Remaining outputs unused */
+			};
+		};
+
+		clockgenA@fee81000 {
+			reg = <0xfee81000 0xb48>;
+
+			CLK_S_A1_PLL: CLK_S_A1_PLL {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-plls-c65";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_S_A1_PLL0_HS",
+						     "CLK_S_A1_PLL0_LS",
+						     "CLK_S_A1_PLL1";
+			};
+
+			CLK_S_A1_OSC_PREDIV: CLK_S_A1_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c65",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_S_A1_OSC_PREDIV";
+			};
+
+			CLK_S_A1_HS: CLK_S_A1_HS {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c65-hs",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_S_A1_OSC_PREDIV>,
+					 <&CLK_S_A1_PLL 0>, /* PLL0 HS */
+					 <&CLK_S_A1_PLL 2>; /* PLL1 */
+
+				clock-output-names = "", /* Reserved */
+						     "", /* Reserved */
+						     "CLK_S_STAC_PHY",
+						     "CLK_S_VTAC_TX_PHY";
+			};
+
+			CLK_S_A1_LS: CLK_S_A1_LS {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c65-ls",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_S_A1_OSC_PREDIV>,
+					 <&CLK_S_A1_PLL 1>, /* PLL0 LS */
+					 <&CLK_S_A1_PLL 2>; /* PLL1 */
+
+				clock-output-names = "CLK_S_ICN_IF_2",
+						     "CLK_S_CARD_MMC",
+						     "CLK_S_ICN_IF_1",
+						     "CLK_S_GMAC0_PHY",
+						     "CLK_S_NAND_CTRL",
+						     "", /* Reserved */
+						     "CLK_S_MII0_REF_OUT",
+						     ""; /* CLK_S_STAC_SYS */
+						 /* Remaining outputs unused */
+			};
+		};
+
+		/*
+		 * ClockGenAs on MPE41
 		 */
-		CLKS_ICN_REG_0: CLKS_ICN_REG_0 {
+		clockgenA@fde12000 {
+			reg = <0xfde12000 0xb50>;
+
+			CLK_M_A0_PLL0: CLK_M_A0_PLL0 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-0", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A0_PLL0_PHI0",
+						     "CLK_M_A0_PLL0_PHI1",
+						     "CLK_M_A0_PLL0_PHI2",
+						     "CLK_M_A0_PLL0_PHI3";
+			};
+
+			CLK_M_A0_PLL1: CLK_M_A0_PLL1 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-1", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A0_PLL1_PHI0",
+						     "CLK_M_A0_PLL1_PHI1",
+						     "CLK_M_A0_PLL1_PHI2",
+						     "CLK_M_A0_PLL1_PHI3";
+			};
+
+			CLK_M_A0_OSC_PREDIV: CLK_M_A0_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c32",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A0_OSC_PREDIV";
+			};
+
+			CLK_M_A0_DIV0: CLK_M_A0_DIV0 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf0",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A0_OSC_PREDIV>,
+					 <&CLK_M_A0_PLL0 0>, /* PLL0 PHI0 */
+					 <&CLK_M_A0_PLL1 0>; /* PLL1 PHI0 */
+
+				clock-output-names = "CLK_M_APB_PM", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "CLK_M_PP_DMU_0",
+						     "CLK_M_PP_DMU_1",
+						     "CLK_M_ICM_DISP",
+						     ""; /* Unused */
+			};
+
+			CLK_M_A0_DIV1: CLK_M_A0_DIV1 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf1",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A0_OSC_PREDIV>,
+					 <&CLK_M_A0_PLL0 1>, /* PLL0 PHI1 */
+					 <&CLK_M_A0_PLL1 1>; /* PLL1 PHI1 */
+
+				clock-output-names = "", /* Unused */
+						     "", /* Unused */
+						     "CLK_M_A9_EXT2F",
+						     "CLK_M_ST40RT",
+						     "CLK_M_ST231_DMU_0",
+						     "CLK_M_ST231_DMU_1",
+						     "CLK_M_ST231_AUD",
+						     "CLK_M_ST231_GP_0";
+			};
+
+			CLK_M_A0_DIV2: CLK_M_A0_DIV2 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf2",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A0_OSC_PREDIV>,
+					 <&CLK_M_A0_PLL0 2>, /* PLL0 PHI2 */
+					 <&CLK_M_A0_PLL1 2>; /* PLL1 PHI2 */
+
+				clock-output-names = "CLK_M_ST231_GP_1",
+						     "CLK_M_ICN_CPU",
+						     "CLK_M_ICN_STAC",
+						     "CLK_M_ICN_DMU_0",
+						     "CLK_M_ICN_DMU_1",
+						     "", /* Unused */
+						     "", /* Unused */
+						     ""; /* Unused */
+			};
+
+			CLK_M_A0_DIV3: CLK_M_A0_DIV3 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf3",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A0_OSC_PREDIV>,
+					 <&CLK_M_A0_PLL0 3>, /* PLL0 PHI3 */
+					 <&CLK_M_A0_PLL1 3>; /* PLL1 PHI3 */
+
+				clock-output-names = "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "CLK_M_ICN_ERAM",
+						     "CLK_M_A9_TRACE";
+			};
+		};
+
+		clockgenA@fd6db000 {
+			reg = <0xfd6db000 0xb50>;
+
+			CLK_M_A1_PLL0: CLK_M_A1_PLL0 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-0", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A1_PLL0_PHI0",
+						     "CLK_M_A1_PLL0_PHI1",
+						     "CLK_M_A1_PLL0_PHI2",
+						     "CLK_M_A1_PLL0_PHI3";
+			};
+
+			CLK_M_A1_PLL1: CLK_M_A1_PLL1 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-1", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A1_PLL1_PHI0",
+						     "CLK_M_A1_PLL1_PHI1",
+						     "CLK_M_A1_PLL1_PHI2",
+						     "CLK_M_A1_PLL1_PHI3";
+			};
+
+			CLK_M_A1_OSC_PREDIV: CLK_M_A1_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c32",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A1_OSC_PREDIV";
+			};
+
+			CLK_M_A1_DIV0: CLK_M_A1_DIV0 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf0",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A1_OSC_PREDIV>,
+					 <&CLK_M_A1_PLL0 0>, /* PLL0 PHI0 */
+					 <&CLK_M_A1_PLL1 0>; /* PLL1 PHI0 */
+
+				clock-output-names = "CLK_M_FDMA_12",
+						     "CLK_M_FDMA_10",
+						     "CLK_M_FDMA_11",
+						     "CLK_M_HVA_LMI",
+						     "CLK_M_PROC_SC",
+						     "CLK_M_TP",
+						     "CLK_M_ICN_GPU",
+						     "CLK_M_ICN_VDP_0";
+			};
+
+			CLK_M_A1_DIV1: CLK_M_A1_DIV1 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf1",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A1_OSC_PREDIV>,
+					 <&CLK_M_A1_PLL0 1>, /* PLL0 PHI1 */
+					 <&CLK_M_A1_PLL1 1>; /* PLL1 PHI1 */
+
+				clock-output-names = "CLK_M_ICN_VDP_1",
+						     "CLK_M_ICN_VDP_2",
+						     "CLK_M_ICN_VDP_3",
+						     "CLK_M_PRV_T1_BUS",
+						     "CLK_M_ICN_VDP_4",
+						     "CLK_M_ICN_REG_10",
+						     "", /* Unused */
+						     ""; /* CLK_M_ICN_ST231 */
+			};
+
+			CLK_M_A1_DIV2: CLK_M_A1_DIV2 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf2",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A1_OSC_PREDIV>,
+					 <&CLK_M_A1_PLL0 2>, /* PLL0 PHI2 */
+					 <&CLK_M_A1_PLL1 2>; /* PLL1 PHI2 */
+
+				clock-output-names = "CLK_M_FVDP_PROC_ALT",
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     ""; /* Unused */
+			};
+
+			CLK_M_A1_DIV3: CLK_M_A1_DIV3 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf3",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A1_OSC_PREDIV>,
+					 <&CLK_M_A1_PLL0 3>, /* PLL0 PHI3 */
+					 <&CLK_M_A1_PLL1 3>; /* PLL1 PHI3 */
+
+				clock-output-names = "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     ""; /* Unused */
+			};
+		};
+
+		CLK_M_A9_EXT2F_DIV2: CLK_M_A9_EXT2F_DIV2S {
 			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <100000000>;
+			compatible = "fixed-factor-clock";
+			clocks = <&CLK_M_A0_DIV1 2>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+
+		clockgenA@fd345000 {
+			reg = <0xfd345000 0xb50>;
+
+			CLK_M_A2_PLL0: CLK_M_A2_PLL0 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-0", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A2_PLL0_PHI0",
+						     "CLK_M_A2_PLL0_PHI1",
+						     "CLK_M_A2_PLL0_PHI2",
+						     "CLK_M_A2_PLL0_PHI3";
+			};
+
+			CLK_M_A2_PLL1: CLK_M_A2_PLL1 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-1", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A2_PLL1_PHI0",
+						     "CLK_M_A2_PLL1_PHI1",
+						     "CLK_M_A2_PLL1_PHI2",
+						     "CLK_M_A2_PLL1_PHI3";
+			};
+
+			CLK_M_A2_OSC_PREDIV: CLK_M_A2_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c32",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A2_OSC_PREDIV";
+			};
+
+			CLK_M_A2_DIV0: CLK_M_A2_DIV0 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf0",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A2_OSC_PREDIV>,
+					 <&CLK_M_A2_PLL0 0>, /* PLL0 PHI0 */
+					 <&CLK_M_A2_PLL1 0>; /* PLL1 PHI0 */
+
+				clock-output-names = "CLK_M_VTAC_MAIN_PHY",
+						     "CLK_M_VTAC_AUX_PHY",
+						     "CLK_M_STAC_PHY",
+						     "CLK_M_STAC_SYS",
+						     "", /* CLK_M_MPESTAC_PG */
+						     "", /* CLK_M_MPESTAC_WC */
+						     "", /* CLK_M_MPEVTACAUX_PG*/
+						     ""; /* CLK_M_MPEVTACMAIN_PG*/
+			};
+
+			CLK_M_A2_DIV1: CLK_M_A2_DIV1 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf1",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A2_OSC_PREDIV>,
+					 <&CLK_M_A2_PLL0 1>, /* PLL0 PHI1 */
+					 <&CLK_M_A2_PLL1 1>; /* PLL1 PHI1 */
+
+				clock-output-names = "", /* CLK_M_MPEVTACRX0_WC */
+						     "", /* CLK_M_MPEVTACRX1_WC */
+						     "CLK_M_COMPO_MAIN",
+						     "CLK_M_COMPO_AUX",
+						     "CLK_M_BDISP_0",
+						     "CLK_M_BDISP_1",
+						     "CLK_M_ICN_BDISP_0",
+						     "CLK_M_ICN_BDISP_1";
+			};
+
+			CLK_M_A2_DIV2: CLK_M_A2_DIV2 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf2",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A2_OSC_PREDIV>,
+					 <&CLK_M_A2_PLL0 2>, /* PLL0 PHI2 */
+					 <&CLK_M_A2_PLL1 2>; /* PLL1 PHI2 */
+
+				clock-output-names = "", /* CLK_M_ICN_HQVDP0 */
+						     "", /* CLK_M_ICN_HQVDP1 */
+						     "CLK_M_ICN_COMPO",
+						     "", /* CLK_M_ICN_VDPAUX */
+						     "CLK_M_ICN_TS",
+						     "CLK_M_ICN_REG_LP_10",
+						     "CLK_M_DCEPHY_IMPCTRL",
+						     ""; /* Unused */
+			};
+
+			CLK_M_A2_DIV3: CLK_M_A2_DIV3 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf3",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A2_OSC_PREDIV>,
+					 <&CLK_M_A2_PLL0 3>, /* PLL0 PHI3 */
+					 <&CLK_M_A2_PLL1 3>; /* PLL1 PHI3 */
+
+				clock-output-names = ""; /* Unused */
+						/* Remaining outputs unused */
+			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/stih415.dtsi b/arch/arm/boot/dts/stih415.dtsi
index d9c7dd1..fcda687 100644
--- a/arch/arm/boot/dts/stih415.dtsi
+++ b/arch/arm/boot/dts/stih415.dtsi
@@ -71,7 +71,7 @@
 			interrupts	= <0 197 0>;
 			pinctrl-names 	= "default";
 			pinctrl-0 	= <&pinctrl_serial2>;
-			clocks		= <&CLKS_ICN_REG_0>;
+			clocks		= <&CLK_S_A0_LS CLK_S_ICN_REG_0>;
 		};
 
 		/* SBC comms block ASCs in SASG1 */
@@ -89,7 +89,7 @@
 			compatible	= "st,comms-ssc4-i2c";
 			reg		= <0xfed40000 0x110>;
 			interrupts	= <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
-			clocks		= <&CLKS_ICN_REG_0>;
+			clocks		= <&CLK_S_A0_LS CLK_S_ICN_REG_0>;
 			clock-names	= "ssc";
 			clock-frequency = <400000>;
 			pinctrl-names	= "default";
@@ -102,7 +102,7 @@
 			compatible	= "st,comms-ssc4-i2c";
 			reg		= <0xfed41000 0x110>;
 			interrupts	= <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
-			clocks		= <&CLKS_ICN_REG_0>;
+			clocks		= <&CLK_S_A0_LS CLK_S_ICN_REG_0>;
 			clock-names	= "ssc";
 			clock-frequency = <400000>;
 			pinctrl-names	= "default";
-- 
1.9.0

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

* [PATCH v0 14/15] ARM: STi: DT: STiH415: 415 DT Entry for clockgen A0/1/10/11/12
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

Patch adds DT entries for clockgen A0/1/10/11/12

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 arch/arm/boot/dts/stih415-clks.h     |  11 +
 arch/arm/boot/dts/stih415-clock.dtsi | 475 ++++++++++++++++++++++++++++++++++-
 arch/arm/boot/dts/stih415.dtsi       |   6 +-
 3 files changed, 484 insertions(+), 8 deletions(-)
 create mode 100644 arch/arm/boot/dts/stih415-clks.h

diff --git a/arch/arm/boot/dts/stih415-clks.h b/arch/arm/boot/dts/stih415-clks.h
new file mode 100644
index 0000000..341c05b
--- /dev/null
+++ b/arch/arm/boot/dts/stih415-clks.h
@@ -0,0 +1,11 @@
+/*
+ * This header provides constants clk index STMicroelectronics
+ * STiH415 SoC.
+ */
+#ifndef _CLK_STIH415
+#define _CLK_STIH415
+
+/* CLOCKGEN A0 */
+#define CLK_S_ICN_REG_0		0
+
+#endif
diff --git a/arch/arm/boot/dts/stih415-clock.dtsi b/arch/arm/boot/dts/stih415-clock.dtsi
index 174c799..24a7508 100644
--- a/arch/arm/boot/dts/stih415-clock.dtsi
+++ b/arch/arm/boot/dts/stih415-clock.dtsi
@@ -5,8 +5,15 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+
+#include "stih415-clks.h"
+
 / {
 	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
 		/*
 		 * Fixed 30MHz oscillator input to SoC
 		 */
@@ -26,13 +33,471 @@
 		};
 
 		/*
-		 * Bootloader initialized system infrastructure clock for
-		 * serial devices.
+		 * ClockGenAs on SASG1
+		 */
+		clockgenA at fee62000 {
+			reg = <0xfee62000 0xb48>;
+
+			CLK_S_A0_PLL: CLK_S_A0_PLL {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-plls-c65";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_S_A0_PLL0_HS",
+						     "CLK_S_A0_PLL0_LS",
+						     "CLK_S_A0_PLL1";
+			};
+
+			CLK_S_A0_OSC_PREDIV: CLK_S_A0_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c65",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_S_A0_OSC_PREDIV";
+			};
+
+			CLK_S_A0_HS: CLK_S_A0_HS {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c65-hs",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_S_A0_OSC_PREDIV>,
+					 <&CLK_S_A0_PLL 0>, /* PLL0 HS */
+					 <&CLK_S_A0_PLL 2>; /* PLL1 */
+
+				clock-output-names = "CLK_S_FDMA_0",
+						     "CLK_S_FDMA_1",
+						     ""; /* CLK_S_JIT_SENSE */
+						     /* Fourth output unused */
+			};
+
+			CLK_S_A0_LS: CLK_S_A0_LS {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c65-ls",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_S_A0_OSC_PREDIV>,
+					 <&CLK_S_A0_PLL 1>, /* PLL0 LS */
+					 <&CLK_S_A0_PLL 2>; /* PLL1 */
+
+				clock-output-names = "CLK_S_ICN_REG_0",
+						     "CLK_S_ICN_IF_0",
+						     "CLK_S_ICN_REG_LP_0",
+						     "CLK_S_EMISS",
+						     "CLK_S_ETH1_PHY",
+						     "CLK_S_MII_REF_OUT";
+						 /* Remaining outputs unused */
+			};
+		};
+
+		clockgenA at fee81000 {
+			reg = <0xfee81000 0xb48>;
+
+			CLK_S_A1_PLL: CLK_S_A1_PLL {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-plls-c65";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_S_A1_PLL0_HS",
+						     "CLK_S_A1_PLL0_LS",
+						     "CLK_S_A1_PLL1";
+			};
+
+			CLK_S_A1_OSC_PREDIV: CLK_S_A1_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c65",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_S_A1_OSC_PREDIV";
+			};
+
+			CLK_S_A1_HS: CLK_S_A1_HS {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c65-hs",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_S_A1_OSC_PREDIV>,
+					 <&CLK_S_A1_PLL 0>, /* PLL0 HS */
+					 <&CLK_S_A1_PLL 2>; /* PLL1 */
+
+				clock-output-names = "", /* Reserved */
+						     "", /* Reserved */
+						     "CLK_S_STAC_PHY",
+						     "CLK_S_VTAC_TX_PHY";
+			};
+
+			CLK_S_A1_LS: CLK_S_A1_LS {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c65-ls",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_S_A1_OSC_PREDIV>,
+					 <&CLK_S_A1_PLL 1>, /* PLL0 LS */
+					 <&CLK_S_A1_PLL 2>; /* PLL1 */
+
+				clock-output-names = "CLK_S_ICN_IF_2",
+						     "CLK_S_CARD_MMC",
+						     "CLK_S_ICN_IF_1",
+						     "CLK_S_GMAC0_PHY",
+						     "CLK_S_NAND_CTRL",
+						     "", /* Reserved */
+						     "CLK_S_MII0_REF_OUT",
+						     ""; /* CLK_S_STAC_SYS */
+						 /* Remaining outputs unused */
+			};
+		};
+
+		/*
+		 * ClockGenAs on MPE41
 		 */
-		CLKS_ICN_REG_0: CLKS_ICN_REG_0 {
+		clockgenA at fde12000 {
+			reg = <0xfde12000 0xb50>;
+
+			CLK_M_A0_PLL0: CLK_M_A0_PLL0 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-0", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A0_PLL0_PHI0",
+						     "CLK_M_A0_PLL0_PHI1",
+						     "CLK_M_A0_PLL0_PHI2",
+						     "CLK_M_A0_PLL0_PHI3";
+			};
+
+			CLK_M_A0_PLL1: CLK_M_A0_PLL1 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-1", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A0_PLL1_PHI0",
+						     "CLK_M_A0_PLL1_PHI1",
+						     "CLK_M_A0_PLL1_PHI2",
+						     "CLK_M_A0_PLL1_PHI3";
+			};
+
+			CLK_M_A0_OSC_PREDIV: CLK_M_A0_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c32",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A0_OSC_PREDIV";
+			};
+
+			CLK_M_A0_DIV0: CLK_M_A0_DIV0 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf0",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A0_OSC_PREDIV>,
+					 <&CLK_M_A0_PLL0 0>, /* PLL0 PHI0 */
+					 <&CLK_M_A0_PLL1 0>; /* PLL1 PHI0 */
+
+				clock-output-names = "CLK_M_APB_PM", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "CLK_M_PP_DMU_0",
+						     "CLK_M_PP_DMU_1",
+						     "CLK_M_ICM_DISP",
+						     ""; /* Unused */
+			};
+
+			CLK_M_A0_DIV1: CLK_M_A0_DIV1 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf1",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A0_OSC_PREDIV>,
+					 <&CLK_M_A0_PLL0 1>, /* PLL0 PHI1 */
+					 <&CLK_M_A0_PLL1 1>; /* PLL1 PHI1 */
+
+				clock-output-names = "", /* Unused */
+						     "", /* Unused */
+						     "CLK_M_A9_EXT2F",
+						     "CLK_M_ST40RT",
+						     "CLK_M_ST231_DMU_0",
+						     "CLK_M_ST231_DMU_1",
+						     "CLK_M_ST231_AUD",
+						     "CLK_M_ST231_GP_0";
+			};
+
+			CLK_M_A0_DIV2: CLK_M_A0_DIV2 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf2",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A0_OSC_PREDIV>,
+					 <&CLK_M_A0_PLL0 2>, /* PLL0 PHI2 */
+					 <&CLK_M_A0_PLL1 2>; /* PLL1 PHI2 */
+
+				clock-output-names = "CLK_M_ST231_GP_1",
+						     "CLK_M_ICN_CPU",
+						     "CLK_M_ICN_STAC",
+						     "CLK_M_ICN_DMU_0",
+						     "CLK_M_ICN_DMU_1",
+						     "", /* Unused */
+						     "", /* Unused */
+						     ""; /* Unused */
+			};
+
+			CLK_M_A0_DIV3: CLK_M_A0_DIV3 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf3",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A0_OSC_PREDIV>,
+					 <&CLK_M_A0_PLL0 3>, /* PLL0 PHI3 */
+					 <&CLK_M_A0_PLL1 3>; /* PLL1 PHI3 */
+
+				clock-output-names = "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "CLK_M_ICN_ERAM",
+						     "CLK_M_A9_TRACE";
+			};
+		};
+
+		clockgenA at fd6db000 {
+			reg = <0xfd6db000 0xb50>;
+
+			CLK_M_A1_PLL0: CLK_M_A1_PLL0 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-0", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A1_PLL0_PHI0",
+						     "CLK_M_A1_PLL0_PHI1",
+						     "CLK_M_A1_PLL0_PHI2",
+						     "CLK_M_A1_PLL0_PHI3";
+			};
+
+			CLK_M_A1_PLL1: CLK_M_A1_PLL1 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-1", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A1_PLL1_PHI0",
+						     "CLK_M_A1_PLL1_PHI1",
+						     "CLK_M_A1_PLL1_PHI2",
+						     "CLK_M_A1_PLL1_PHI3";
+			};
+
+			CLK_M_A1_OSC_PREDIV: CLK_M_A1_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c32",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A1_OSC_PREDIV";
+			};
+
+			CLK_M_A1_DIV0: CLK_M_A1_DIV0 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf0",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A1_OSC_PREDIV>,
+					 <&CLK_M_A1_PLL0 0>, /* PLL0 PHI0 */
+					 <&CLK_M_A1_PLL1 0>; /* PLL1 PHI0 */
+
+				clock-output-names = "CLK_M_FDMA_12",
+						     "CLK_M_FDMA_10",
+						     "CLK_M_FDMA_11",
+						     "CLK_M_HVA_LMI",
+						     "CLK_M_PROC_SC",
+						     "CLK_M_TP",
+						     "CLK_M_ICN_GPU",
+						     "CLK_M_ICN_VDP_0";
+			};
+
+			CLK_M_A1_DIV1: CLK_M_A1_DIV1 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf1",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A1_OSC_PREDIV>,
+					 <&CLK_M_A1_PLL0 1>, /* PLL0 PHI1 */
+					 <&CLK_M_A1_PLL1 1>; /* PLL1 PHI1 */
+
+				clock-output-names = "CLK_M_ICN_VDP_1",
+						     "CLK_M_ICN_VDP_2",
+						     "CLK_M_ICN_VDP_3",
+						     "CLK_M_PRV_T1_BUS",
+						     "CLK_M_ICN_VDP_4",
+						     "CLK_M_ICN_REG_10",
+						     "", /* Unused */
+						     ""; /* CLK_M_ICN_ST231 */
+			};
+
+			CLK_M_A1_DIV2: CLK_M_A1_DIV2 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf2",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A1_OSC_PREDIV>,
+					 <&CLK_M_A1_PLL0 2>, /* PLL0 PHI2 */
+					 <&CLK_M_A1_PLL1 2>; /* PLL1 PHI2 */
+
+				clock-output-names = "CLK_M_FVDP_PROC_ALT",
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     ""; /* Unused */
+			};
+
+			CLK_M_A1_DIV3: CLK_M_A1_DIV3 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf3",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A1_OSC_PREDIV>,
+					 <&CLK_M_A1_PLL0 3>, /* PLL0 PHI3 */
+					 <&CLK_M_A1_PLL1 3>; /* PLL1 PHI3 */
+
+				clock-output-names = "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     "", /* Unused */
+						     ""; /* Unused */
+			};
+		};
+
+		CLK_M_A9_EXT2F_DIV2: CLK_M_A9_EXT2F_DIV2S {
 			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <100000000>;
+			compatible = "fixed-factor-clock";
+			clocks = <&CLK_M_A0_DIV1 2>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+
+		clockgenA at fd345000 {
+			reg = <0xfd345000 0xb50>;
+
+			CLK_M_A2_PLL0: CLK_M_A2_PLL0 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-0", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A2_PLL0_PHI0",
+						     "CLK_M_A2_PLL0_PHI1",
+						     "CLK_M_A2_PLL0_PHI2",
+						     "CLK_M_A2_PLL0_PHI3";
+			};
+
+			CLK_M_A2_PLL1: CLK_M_A2_PLL1 {
+				#clock-cells = <1>;
+				compatible = "st,plls-c32-a1x-1", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A2_PLL1_PHI0",
+						     "CLK_M_A2_PLL1_PHI1",
+						     "CLK_M_A2_PLL1_PHI2",
+						     "CLK_M_A2_PLL1_PHI3";
+			};
+
+			CLK_M_A2_OSC_PREDIV: CLK_M_A2_OSC_PREDIV {
+				#clock-cells = <0>;
+				compatible = "st,clkgena-prediv-c32",
+					     "st,clkgena-prediv";
+
+				clocks = <&CLK_SYSIN>;
+
+				clock-output-names = "CLK_M_A2_OSC_PREDIV";
+			};
+
+			CLK_M_A2_DIV0: CLK_M_A2_DIV0 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf0",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A2_OSC_PREDIV>,
+					 <&CLK_M_A2_PLL0 0>, /* PLL0 PHI0 */
+					 <&CLK_M_A2_PLL1 0>; /* PLL1 PHI0 */
+
+				clock-output-names = "CLK_M_VTAC_MAIN_PHY",
+						     "CLK_M_VTAC_AUX_PHY",
+						     "CLK_M_STAC_PHY",
+						     "CLK_M_STAC_SYS",
+						     "", /* CLK_M_MPESTAC_PG */
+						     "", /* CLK_M_MPESTAC_WC */
+						     "", /* CLK_M_MPEVTACAUX_PG*/
+						     ""; /* CLK_M_MPEVTACMAIN_PG*/
+			};
+
+			CLK_M_A2_DIV1: CLK_M_A2_DIV1 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf1",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A2_OSC_PREDIV>,
+					 <&CLK_M_A2_PLL0 1>, /* PLL0 PHI1 */
+					 <&CLK_M_A2_PLL1 1>; /* PLL1 PHI1 */
+
+				clock-output-names = "", /* CLK_M_MPEVTACRX0_WC */
+						     "", /* CLK_M_MPEVTACRX1_WC */
+						     "CLK_M_COMPO_MAIN",
+						     "CLK_M_COMPO_AUX",
+						     "CLK_M_BDISP_0",
+						     "CLK_M_BDISP_1",
+						     "CLK_M_ICN_BDISP_0",
+						     "CLK_M_ICN_BDISP_1";
+			};
+
+			CLK_M_A2_DIV2: CLK_M_A2_DIV2 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf2",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A2_OSC_PREDIV>,
+					 <&CLK_M_A2_PLL0 2>, /* PLL0 PHI2 */
+					 <&CLK_M_A2_PLL1 2>; /* PLL1 PHI2 */
+
+				clock-output-names = "", /* CLK_M_ICN_HQVDP0 */
+						     "", /* CLK_M_ICN_HQVDP1 */
+						     "CLK_M_ICN_COMPO",
+						     "", /* CLK_M_ICN_VDPAUX */
+						     "CLK_M_ICN_TS",
+						     "CLK_M_ICN_REG_LP_10",
+						     "CLK_M_DCEPHY_IMPCTRL",
+						     ""; /* Unused */
+			};
+
+			CLK_M_A2_DIV3: CLK_M_A2_DIV3 {
+				#clock-cells = <1>;
+				compatible = "st,clkgena-divmux-c32-odf3",
+					     "st,clkgena-divmux";
+
+				clocks = <&CLK_M_A2_OSC_PREDIV>,
+					 <&CLK_M_A2_PLL0 3>, /* PLL0 PHI3 */
+					 <&CLK_M_A2_PLL1 3>; /* PLL1 PHI3 */
+
+				clock-output-names = ""; /* Unused */
+						/* Remaining outputs unused */
+			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/stih415.dtsi b/arch/arm/boot/dts/stih415.dtsi
index d9c7dd1..fcda687 100644
--- a/arch/arm/boot/dts/stih415.dtsi
+++ b/arch/arm/boot/dts/stih415.dtsi
@@ -71,7 +71,7 @@
 			interrupts	= <0 197 0>;
 			pinctrl-names 	= "default";
 			pinctrl-0 	= <&pinctrl_serial2>;
-			clocks		= <&CLKS_ICN_REG_0>;
+			clocks		= <&CLK_S_A0_LS CLK_S_ICN_REG_0>;
 		};
 
 		/* SBC comms block ASCs in SASG1 */
@@ -89,7 +89,7 @@
 			compatible	= "st,comms-ssc4-i2c";
 			reg		= <0xfed40000 0x110>;
 			interrupts	= <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
-			clocks		= <&CLKS_ICN_REG_0>;
+			clocks		= <&CLK_S_A0_LS CLK_S_ICN_REG_0>;
 			clock-names	= "ssc";
 			clock-frequency = <400000>;
 			pinctrl-names	= "default";
@@ -102,7 +102,7 @@
 			compatible	= "st,comms-ssc4-i2c";
 			reg		= <0xfed41000 0x110>;
 			interrupts	= <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
-			clocks		= <&CLKS_ICN_REG_0>;
+			clocks		= <&CLK_S_A0_LS CLK_S_ICN_REG_0>;
 			clock-names	= "ssc";
 			clock-frequency = <400000>;
 			pinctrl-names	= "default";
-- 
1.9.0

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

* [PATCH v0 15/15] ARM: STi: DT: STiH415: 415 DT Entry for clockgen A9
  2014-02-27 15:24 ` Gabriel FERNANDEZ
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  -1 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: mturquette, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, rob, linux, devicetree, linux-doc, linux-kernel,
	linux-arm-kernel
  Cc: Lee Jones, Gabriel Fernandez, Pankaj Dev

Patch adds DT entries for clockgen A9

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 arch/arm/boot/dts/stih415-clock.dtsi | 67 +++++++++++++++++++++++++++++++-----
 1 file changed, 58 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/stih415-clock.dtsi b/arch/arm/boot/dts/stih415-clock.dtsi
index 24a7508..8563636 100644
--- a/arch/arm/boot/dts/stih415-clock.dtsi
+++ b/arch/arm/boot/dts/stih415-clock.dtsi
@@ -24,15 +24,6 @@
 		};
 
 		/*
-		 * ARM Peripheral clock for timers
-		 */
-		arm_periph_clk: arm_periph_clk {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <500000000>;
-		};
-
-		/*
 		 * ClockGenAs on SASG1
 		 */
 		clockgenA@fee62000 {
@@ -499,5 +490,63 @@
 						/* Remaining outputs unused */
 			};
 		};
+
+		/*
+		 * A9 PLL.
+		 *
+		 */
+		clockgenA9 {
+			reg = <0xfdde00d8 0x70>;
+
+			CLOCKGEN_A9_PLL: CLOCKGEN_A9_PLL {
+				#clock-cells = <1>;
+				compatible = "st,stih415-plls-c32-a9", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+				clock-output-names = "CLOCKGEN_A9_PLL_ODF";
+			};
+		};
+
+		/*
+		 * ARM CPU related clocks.
+		 */
+		CLK_M_A9: CLK_M_A9 {
+			#clock-cells = <0>;
+			compatible = "st,stih415-clkgen-a9-mux", "st,clkgen-mux";
+			reg = <0xfdde00d8 0x4>;
+			clocks = <&CLOCKGEN_A9_PLL 0>, <&CLOCKGEN_A9_PLL 0>, <&CLK_M_A0_DIV1 2>, <&CLK_M_A9_EXT2F_DIV2>;
+		};
+
+		/*
+		 * ARM Peripheral clock for timers
+		 */
+		arm_periph_clk: CLK_M_A9_PERIPHS {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&CLK_M_A9>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+
+		CLK_S_USB48: clockgenB0@0 {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <48000000>;
+			clock-output-names = "CLK_S_USB48";
+		};
+
+		CLKS_B_THSENS: clockgenB@3 {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <996000>;
+			clock-output-names = "CLKS_B_THSENS";
+		};
+
+		CLKM_MPETHSENS: clockgenE@3 {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <996000>;
+			clock-output-names = "CLKM_MPETHSENS";
+		};
 	};
 };
-- 
1.9.0


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

* [PATCH v0 15/15] ARM: STi: DT: STiH415: 415 DT Entry for clockgen A9
@ 2014-02-27 15:24   ` Gabriel FERNANDEZ
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel FERNANDEZ @ 2014-02-27 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

Patch adds DT entries for clockgen A9

Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
 arch/arm/boot/dts/stih415-clock.dtsi | 67 +++++++++++++++++++++++++++++++-----
 1 file changed, 58 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/stih415-clock.dtsi b/arch/arm/boot/dts/stih415-clock.dtsi
index 24a7508..8563636 100644
--- a/arch/arm/boot/dts/stih415-clock.dtsi
+++ b/arch/arm/boot/dts/stih415-clock.dtsi
@@ -24,15 +24,6 @@
 		};
 
 		/*
-		 * ARM Peripheral clock for timers
-		 */
-		arm_periph_clk: arm_periph_clk {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <500000000>;
-		};
-
-		/*
 		 * ClockGenAs on SASG1
 		 */
 		clockgenA at fee62000 {
@@ -499,5 +490,63 @@
 						/* Remaining outputs unused */
 			};
 		};
+
+		/*
+		 * A9 PLL.
+		 *
+		 */
+		clockgenA9 {
+			reg = <0xfdde00d8 0x70>;
+
+			CLOCKGEN_A9_PLL: CLOCKGEN_A9_PLL {
+				#clock-cells = <1>;
+				compatible = "st,stih415-plls-c32-a9", "st,clkgen-plls-c32";
+
+				clocks = <&CLK_SYSIN>;
+				clock-output-names = "CLOCKGEN_A9_PLL_ODF";
+			};
+		};
+
+		/*
+		 * ARM CPU related clocks.
+		 */
+		CLK_M_A9: CLK_M_A9 {
+			#clock-cells = <0>;
+			compatible = "st,stih415-clkgen-a9-mux", "st,clkgen-mux";
+			reg = <0xfdde00d8 0x4>;
+			clocks = <&CLOCKGEN_A9_PLL 0>, <&CLOCKGEN_A9_PLL 0>, <&CLK_M_A0_DIV1 2>, <&CLK_M_A9_EXT2F_DIV2>;
+		};
+
+		/*
+		 * ARM Peripheral clock for timers
+		 */
+		arm_periph_clk: CLK_M_A9_PERIPHS {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&CLK_M_A9>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+
+		CLK_S_USB48: clockgenB0 at 0 {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <48000000>;
+			clock-output-names = "CLK_S_USB48";
+		};
+
+		CLKS_B_THSENS: clockgenB at 3 {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <996000>;
+			clock-output-names = "CLKS_B_THSENS";
+		};
+
+		CLKM_MPETHSENS: clockgenE at 3 {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <996000>;
+			clock-output-names = "CLKM_MPETHSENS";
+		};
 	};
 };
-- 
1.9.0

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

* Re: [PATCH v0 12/15] ARM: STi: DT: STiH416: 416 DT Entry for clockgen B/C/D/E/F
  2014-02-27 15:24   ` Gabriel FERNANDEZ
@ 2014-02-27 16:36     ` Lee Jones
  -1 siblings, 0 replies; 49+ messages in thread
From: Lee Jones @ 2014-02-27 16:36 UTC (permalink / raw)
  To: Gabriel FERNANDEZ
  Cc: mturquette, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, rob, linux, devicetree, linux-doc, linux-kernel,
	linux-arm-kernel, Pankaj Dev

> Patch adds DT entries for clockgen B/C/D/E/F
> 
> Signed-off-by: Pankaj Dev <pankaj.dev@st.com>

You need to add your Signed-off-by too.

> ---
>  arch/arm/boot/dts/stih416-clock.dtsi | 170 +++++++++++++++++++++++++++++++++++
>  1 file changed, 170 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/stih416-clock.dtsi b/arch/arm/boot/dts/stih416-clock.dtsi
> index f63b0a1..6b2e387 100644
> --- a/arch/arm/boot/dts/stih416-clock.dtsi
> +++ b/arch/arm/boot/dts/stih416-clock.dtsi
> @@ -503,5 +503,175 @@
>  						/* Remaining outputs unused */
>  			};
>  		};

This doesn't look right. Have you indented one tab too far?

> +                /*
> +                 * Frequency synthesizers on the SASG2.
> +                 *
> +                 */

Too many *'s

<snip>

> +                CLK_S_VCC_HD: CLK_S_VCC_HD {
> +                        #clock-cells = <0>;
> +                        compatible = "st,stih416-clkgenc-vcc-hd", "st,clkgen-mux";
> +                        reg = <0xfe8308b8 4>; /* SYSCFG2558 */

0x4

> +                /*
> +                 * Add a dummy clock for the HDMI PHY for the VCC input mux
> +                 */
> +                CLK_S_TMDS_FROMPHY: CLK_S_TMDS_FROMPHY {
> +                        #clock-cells = <0>;
> +                        compatible = "fixed-clock";
> +                        clock-frequency = <0>;

What happens when the clock frequency is 0?
> +                };
> +
> +                CLOCKGEN_C_VCC: CLOCKGEN_C_VCC {
> +                        #clock-cells = <1>;
> +                        compatible = "st,stih416-clkgenc", "st,clkgen-vcc";
> +                        reg = <0xfe8308ac 12>; /* SYSCFG2555,2556,2557 */

0x12, or 0x0C, whichever is appropriate.

> +                        clocks = <&CLK_S_VCC_HD>, <&CLOCKGEN_C 1>,
> +                                 <&CLK_S_TMDS_FROMPHY>, <&CLOCKGEN_C 2>;

One per line would probably be better, save confusing them for pairs.

<snip>

> +		/*
> +		 * Frequency synthesizers on the MPE42
> +		 */

Alignment.

<snip>

> +                CLOCKGEN_F: CLOCKGEN_F {
> +                        #clock-cells = <1>;
> +                        compatible = "st,stih416-quadfs660-F", "st,quadfs";
> +                        reg = <0xfd320878 0xF0>;
> +
> +                        clocks = <&CLK_SYSIN>;
> +                        clock-output-names = "CLK_M_MAIN_VIDFS",
> +                                             "CLK_M_HVA_FS",
> +                                             "CLK_M_FVDP_VCPU",
> +					     "CLK_M_FVDP_PROC_FS";

Tabbing. Ensure you're using tabs (and not spaces) everywhere.

<snip>

> +                        reg = <0xfd320910 4>; /* SYSCFG8580 */

0x...

Do this for all of the below too.


<snip>

> +                        clock-output-names  =
> +                                "CLK_M_PIX_MAIN_PIPE",  "CLK_M_PIX_AUX_PIPE",
> +                                "CLK_M_PIX_MAIN_CRU",   "CLK_M_PIX_AUX_CRU",
> +                                "CLK_M_XFER_BE_COMPO",  "CLK_M_XFER_PIP_COMPO",
> +                                "CLK_M_XFER_AUX_COMPO", "CLK_M_VSENS",
> +                                "CLK_M_PIX_HDMIRX_0",   "CLK_M_PIX_HDMIRX_1";
> +                };
>  	};
>  };

Something strange going on with these.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* [PATCH v0 12/15] ARM: STi: DT: STiH416: 416 DT Entry for clockgen B/C/D/E/F
@ 2014-02-27 16:36     ` Lee Jones
  0 siblings, 0 replies; 49+ messages in thread
From: Lee Jones @ 2014-02-27 16:36 UTC (permalink / raw)
  To: linux-arm-kernel

> Patch adds DT entries for clockgen B/C/D/E/F
> 
> Signed-off-by: Pankaj Dev <pankaj.dev@st.com>

You need to add your Signed-off-by too.

> ---
>  arch/arm/boot/dts/stih416-clock.dtsi | 170 +++++++++++++++++++++++++++++++++++
>  1 file changed, 170 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/stih416-clock.dtsi b/arch/arm/boot/dts/stih416-clock.dtsi
> index f63b0a1..6b2e387 100644
> --- a/arch/arm/boot/dts/stih416-clock.dtsi
> +++ b/arch/arm/boot/dts/stih416-clock.dtsi
> @@ -503,5 +503,175 @@
>  						/* Remaining outputs unused */
>  			};
>  		};

This doesn't look right. Have you indented one tab too far?

> +                /*
> +                 * Frequency synthesizers on the SASG2.
> +                 *
> +                 */

Too many *'s

<snip>

> +                CLK_S_VCC_HD: CLK_S_VCC_HD {
> +                        #clock-cells = <0>;
> +                        compatible = "st,stih416-clkgenc-vcc-hd", "st,clkgen-mux";
> +                        reg = <0xfe8308b8 4>; /* SYSCFG2558 */

0x4

> +                /*
> +                 * Add a dummy clock for the HDMI PHY for the VCC input mux
> +                 */
> +                CLK_S_TMDS_FROMPHY: CLK_S_TMDS_FROMPHY {
> +                        #clock-cells = <0>;
> +                        compatible = "fixed-clock";
> +                        clock-frequency = <0>;

What happens when the clock frequency is 0?
> +                };
> +
> +                CLOCKGEN_C_VCC: CLOCKGEN_C_VCC {
> +                        #clock-cells = <1>;
> +                        compatible = "st,stih416-clkgenc", "st,clkgen-vcc";
> +                        reg = <0xfe8308ac 12>; /* SYSCFG2555,2556,2557 */

0x12, or 0x0C, whichever is appropriate.

> +                        clocks = <&CLK_S_VCC_HD>, <&CLOCKGEN_C 1>,
> +                                 <&CLK_S_TMDS_FROMPHY>, <&CLOCKGEN_C 2>;

One per line would probably be better, save confusing them for pairs.

<snip>

> +		/*
> +		 * Frequency synthesizers on the MPE42
> +		 */

Alignment.

<snip>

> +                CLOCKGEN_F: CLOCKGEN_F {
> +                        #clock-cells = <1>;
> +                        compatible = "st,stih416-quadfs660-F", "st,quadfs";
> +                        reg = <0xfd320878 0xF0>;
> +
> +                        clocks = <&CLK_SYSIN>;
> +                        clock-output-names = "CLK_M_MAIN_VIDFS",
> +                                             "CLK_M_HVA_FS",
> +                                             "CLK_M_FVDP_VCPU",
> +					     "CLK_M_FVDP_PROC_FS";

Tabbing. Ensure you're using tabs (and not spaces) everywhere.

<snip>

> +                        reg = <0xfd320910 4>; /* SYSCFG8580 */

0x...

Do this for all of the below too.


<snip>

> +                        clock-output-names  =
> +                                "CLK_M_PIX_MAIN_PIPE",  "CLK_M_PIX_AUX_PIPE",
> +                                "CLK_M_PIX_MAIN_CRU",   "CLK_M_PIX_AUX_CRU",
> +                                "CLK_M_XFER_BE_COMPO",  "CLK_M_XFER_PIP_COMPO",
> +                                "CLK_M_XFER_AUX_COMPO", "CLK_M_VSENS",
> +                                "CLK_M_PIX_HDMIRX_0",   "CLK_M_PIX_HDMIRX_1";
> +                };
>  	};
>  };

Something strange going on with these.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v0 12/15] ARM: STi: DT: STiH416: 416 DT Entry for clockgen B/C/D/E/F
  2014-02-27 16:36     ` Lee Jones
  (?)
@ 2014-02-28 13:53     ` Gabriel Fernandez
  -1 siblings, 0 replies; 49+ messages in thread
From: Gabriel Fernandez @ 2014-02-28 13:53 UTC (permalink / raw)
  To: Lee Jones
  Cc: mturquette, robh+dt, pawel.moll, mark.rutland, ijc+devicetree,
	galak, rob, linux, devicetree, linux-doc, linux-kernel,
	linux-arm-kernel, Pankaj Dev

[-- Attachment #1: Type: text/plain, Size: 3641 bytes --]

Hi Lee,

On 02/27/2014 05:36 PM, Lee Jones wrote:
>> Patch adds DT entries for clockgen B/C/D/E/F
>>
>> Signed-off-by: Pankaj Dev <pankaj.dev@st.com>
> You need to add your Signed-off-by too.
ok
>
>> ---
>>   arch/arm/boot/dts/stih416-clock.dtsi | 170 +++++++++++++++++++++++++++++++++++
>>   1 file changed, 170 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/stih416-clock.dtsi b/arch/arm/boot/dts/stih416-clock.dtsi
>> index f63b0a1..6b2e387 100644
>> --- a/arch/arm/boot/dts/stih416-clock.dtsi
>> +++ b/arch/arm/boot/dts/stih416-clock.dtsi
>> @@ -503,5 +503,175 @@
>>   						/* Remaining outputs unused */
>>   			};
>>   		};
> This doesn't look right. Have you indented one tab too far?
ok i have reworked tabulation on this patch
>
>> +                /*
>> +                 * Frequency synthesizers on the SASG2.
>> +                 *
>> +                 */
> Too many *'s
ok
>
> <snip>
>
>> +                CLK_S_VCC_HD: CLK_S_VCC_HD {
>> +                        #clock-cells = <0>;
>> +                        compatible = "st,stih416-clkgenc-vcc-hd", "st,clkgen-mux";
>> +                        reg = <0xfe8308b8 4>; /* SYSCFG2558 */
> 0x4
ok
>
>> +                /*
>> +                 * Add a dummy clock for the HDMI PHY for the VCC input mux
>> +                 */
>> +                CLK_S_TMDS_FROMPHY: CLK_S_TMDS_FROMPHY {
>> +                        #clock-cells = <0>;
>> +                        compatible = "fixed-clock";
>> +                        clock-frequency = <0>;
> What happens when the clock frequency is 0?
Nothing, this poses no problem.
This input clock is not managed by the driver.

>> +                };
>> +
>> +                CLOCKGEN_C_VCC: CLOCKGEN_C_VCC {
>> +                        #clock-cells = <1>;
>> +                        compatible = "st,stih416-clkgenc", "st,clkgen-vcc";
>> +                        reg = <0xfe8308ac 12>; /* SYSCFG2555,2556,2557 */
> 0x12, or 0x0C, whichever is appropriate.
ok
>
>> +                        clocks = <&CLK_S_VCC_HD>, <&CLOCKGEN_C 1>,
>> +                                 <&CLK_S_TMDS_FROMPHY>, <&CLOCKGEN_C 2>;
> One per line would probably be better, save confusing them for pairs.
ok
>
> <snip>
>
>> +		/*
>> +		 * Frequency synthesizers on the MPE42
>> +		 */
> Alignment.

ok i transform into 1 line : /* Frequency synthesizers on the MPE42*/

>
> <snip>
>
>> +                CLOCKGEN_F: CLOCKGEN_F {
>> +                        #clock-cells = <1>;
>> +                        compatible = "st,stih416-quadfs660-F", "st,quadfs";
>> +                        reg = <0xfd320878 0xF0>;
>> +
>> +                        clocks = <&CLK_SYSIN>;
>> +                        clock-output-names = "CLK_M_MAIN_VIDFS",
>> +                                             "CLK_M_HVA_FS",
>> +                                             "CLK_M_FVDP_VCPU",
>> +					     "CLK_M_FVDP_PROC_FS";
> Tabbing. Ensure you're using tabs (and not spaces) everywhere.
ok
>
> <snip>
>
>> +                        reg = <0xfd320910 4>; /* SYSCFG8580 */
> 0x...
>
> Do this for all of the below too.
ok
>
>
> <snip>
>
>> +                        clock-output-names  =
>> +                                "CLK_M_PIX_MAIN_PIPE",  "CLK_M_PIX_AUX_PIPE",
>> +                                "CLK_M_PIX_MAIN_CRU",   "CLK_M_PIX_AUX_CRU",
>> +                                "CLK_M_XFER_BE_COMPO",  "CLK_M_XFER_PIP_COMPO",
>> +                                "CLK_M_XFER_AUX_COMPO", "CLK_M_VSENS",
>> +                                "CLK_M_PIX_HDMIRX_0",   "CLK_M_PIX_HDMIRX_1";
>> +                };
>>   	};
>>   };
ok
> Something strange going on with these.
>


[-- Attachment #2: Type: text/html, Size: 7211 bytes --]

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

* Re: [PATCH v0 01/15] drivers: clk: st: Support for DIVMUX and PreDiv Clocks
  2014-02-27 15:24   ` Gabriel FERNANDEZ
  (?)
@ 2014-03-25  5:27     ` Mike Turquette
  -1 siblings, 0 replies; 49+ messages in thread
From: Mike Turquette @ 2014-03-25  5:27 UTC (permalink / raw)
  To: Gabriel FERNANDEZ, robh+dt, pawel.moll, mark.rutland,
	ijc+devicetree, galak, rob, linux, devicetree, linux-doc,
	linux-kernel, linux-arm-kernel
  Cc: Lee Jones, Gabriel Fernandez, Pankaj Dev

Quoting Gabriel FERNANDEZ (2014-02-27 07:24:14)
> +/**
> + * DOC: Clock mux with a programmable divider on each of its three inputs.
> + *      The mux has an input setting which effectively gates its output.
> + *
> + * Traits of this clock:
> + * prepare - clk_(un)prepare only ensures parent is (un)prepared

Minor nitpick but it doesn't look like .prepare or .unprepare are
supported below. It looks like this copy/paste comment applies to most
of the clk patches as well.

It's a small problem and doesn't require a patch respin. But perhaps can
be cleaned up some day in the future.

Do you want me to take these patches directly or are you just looking
for an Ack?

Regards,
Mike

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

* Re: [PATCH v0 01/15] drivers: clk: st: Support for DIVMUX and PreDiv Clocks
@ 2014-03-25  5:27     ` Mike Turquette
  0 siblings, 0 replies; 49+ messages in thread
From: Mike Turquette @ 2014-03-25  5:27 UTC (permalink / raw)
  To: robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak, rob,
	linux, devicetree, linux-doc, linux-kernel, linux-arm-kernel
  Cc: Lee Jones, Gabriel Fernandez, Pankaj Dev

Quoting Gabriel FERNANDEZ (2014-02-27 07:24:14)
> +/**
> + * DOC: Clock mux with a programmable divider on each of its three inputs.
> + *      The mux has an input setting which effectively gates its output.
> + *
> + * Traits of this clock:
> + * prepare - clk_(un)prepare only ensures parent is (un)prepared

Minor nitpick but it doesn't look like .prepare or .unprepare are
supported below. It looks like this copy/paste comment applies to most
of the clk patches as well.

It's a small problem and doesn't require a patch respin. But perhaps can
be cleaned up some day in the future.

Do you want me to take these patches directly or are you just looking
for an Ack?

Regards,
Mike

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

* [PATCH v0 01/15] drivers: clk: st: Support for DIVMUX and PreDiv Clocks
@ 2014-03-25  5:27     ` Mike Turquette
  0 siblings, 0 replies; 49+ messages in thread
From: Mike Turquette @ 2014-03-25  5:27 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Gabriel FERNANDEZ (2014-02-27 07:24:14)
> +/**
> + * DOC: Clock mux with a programmable divider on each of its three inputs.
> + *      The mux has an input setting which effectively gates its output.
> + *
> + * Traits of this clock:
> + * prepare - clk_(un)prepare only ensures parent is (un)prepared

Minor nitpick but it doesn't look like .prepare or .unprepare are
supported below. It looks like this copy/paste comment applies to most
of the clk patches as well.

It's a small problem and doesn't require a patch respin. But perhaps can
be cleaned up some day in the future.

Do you want me to take these patches directly or are you just looking
for an Ack?

Regards,
Mike

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

* Re: [PATCH v0 01/15] drivers: clk: st: Support for DIVMUX and PreDiv Clocks
  2014-03-25  5:27     ` Mike Turquette
  (?)
@ 2014-03-25  8:28       ` Gabriel Fernandez
  -1 siblings, 0 replies; 49+ messages in thread
From: Gabriel Fernandez @ 2014-03-25  8:28 UTC (permalink / raw)
  To: Mike Turquette, robh+dt, pawel.moll, mark.rutland,
	ijc+devicetree, galak, rob, linux, devicetree, linux-doc,
	linux-kernel, linux-arm-kernel
  Cc: Lee Jones, Pankaj Dev

Hi Mike,

I want that you take theses patches directly.

Many thanks


Best regards

Gabriel.


On 03/25/2014 06:27 AM, Mike Turquette wrote:
> Quoting Gabriel FERNANDEZ (2014-02-27 07:24:14)
>> +/**
>> + * DOC: Clock mux with a programmable divider on each of its three inputs.
>> + *      The mux has an input setting which effectively gates its output.
>> + *
>> + * Traits of this clock:
>> + * prepare - clk_(un)prepare only ensures parent is (un)prepared
> Minor nitpick but it doesn't look like .prepare or .unprepare are
> supported below. It looks like this copy/paste comment applies to most
> of the clk patches as well.
>
> It's a small problem and doesn't require a patch respin. But perhaps can
> be cleaned up some day in the future.
>
> Do you want me to take these patches directly or are you just looking
> for an Ack?
>
> Regards,
> Mike


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

* Re: [PATCH v0 01/15] drivers: clk: st: Support for DIVMUX and PreDiv Clocks
@ 2014-03-25  8:28       ` Gabriel Fernandez
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel Fernandez @ 2014-03-25  8:28 UTC (permalink / raw)
  To: Mike Turquette, robh+dt, pawel.moll, mark.rutland,
	ijc+devicetree, galak, rob, linux, devicetree, linux-doc,
	linux-kernel, linux-arm-kernel
  Cc: Pankaj Dev, Lee Jones

Hi Mike,

I want that you take theses patches directly.

Many thanks


Best regards

Gabriel.


On 03/25/2014 06:27 AM, Mike Turquette wrote:
> Quoting Gabriel FERNANDEZ (2014-02-27 07:24:14)
>> +/**
>> + * DOC: Clock mux with a programmable divider on each of its three inputs.
>> + *      The mux has an input setting which effectively gates its output.
>> + *
>> + * Traits of this clock:
>> + * prepare - clk_(un)prepare only ensures parent is (un)prepared
> Minor nitpick but it doesn't look like .prepare or .unprepare are
> supported below. It looks like this copy/paste comment applies to most
> of the clk patches as well.
>
> It's a small problem and doesn't require a patch respin. But perhaps can
> be cleaned up some day in the future.
>
> Do you want me to take these patches directly or are you just looking
> for an Ack?
>
> Regards,
> Mike

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

* [PATCH v0 01/15] drivers: clk: st: Support for DIVMUX and PreDiv Clocks
@ 2014-03-25  8:28       ` Gabriel Fernandez
  0 siblings, 0 replies; 49+ messages in thread
From: Gabriel Fernandez @ 2014-03-25  8:28 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Mike,

I want that you take theses patches directly.

Many thanks


Best regards

Gabriel.


On 03/25/2014 06:27 AM, Mike Turquette wrote:
> Quoting Gabriel FERNANDEZ (2014-02-27 07:24:14)
>> +/**
>> + * DOC: Clock mux with a programmable divider on each of its three inputs.
>> + *      The mux has an input setting which effectively gates its output.
>> + *
>> + * Traits of this clock:
>> + * prepare - clk_(un)prepare only ensures parent is (un)prepared
> Minor nitpick but it doesn't look like .prepare or .unprepare are
> supported below. It looks like this copy/paste comment applies to most
> of the clk patches as well.
>
> It's a small problem and doesn't require a patch respin. But perhaps can
> be cleaned up some day in the future.
>
> Do you want me to take these patches directly or are you just looking
> for an Ack?
>
> Regards,
> Mike

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

* Re: [PATCH v0 01/15] drivers: clk: st: Support for DIVMUX and PreDiv Clocks
  2014-03-25  8:28       ` Gabriel Fernandez
@ 2014-03-25 22:59         ` Mike Turquette
  -1 siblings, 0 replies; 49+ messages in thread
From: Mike Turquette @ 2014-03-25 22:59 UTC (permalink / raw)
  To: Gabriel Fernandez, robh+dt, pawel.moll, mark.rutland,
	ijc+devicetree, galak, rob, linux, devicetree, linux-doc,
	linux-kernel, linux-arm-kernel
  Cc: Lee Jones, Pankaj Dev

Quoting Gabriel Fernandez (2014-03-25 01:28:41)
> Hi Mike,
> 
> I want that you take theses patches directly.

Sure, I've taken patches #1-10 into clk-next.

Regards,
Mike

> 
> Many thanks
> 
> 
> Best regards
> 
> Gabriel.
> 
> 
> On 03/25/2014 06:27 AM, Mike Turquette wrote:
> > Quoting Gabriel FERNANDEZ (2014-02-27 07:24:14)
> >> +/**
> >> + * DOC: Clock mux with a programmable divider on each of its three inputs.
> >> + *      The mux has an input setting which effectively gates its output.
> >> + *
> >> + * Traits of this clock:
> >> + * prepare - clk_(un)prepare only ensures parent is (un)prepared
> > Minor nitpick but it doesn't look like .prepare or .unprepare are
> > supported below. It looks like this copy/paste comment applies to most
> > of the clk patches as well.
> >
> > It's a small problem and doesn't require a patch respin. But perhaps can
> > be cleaned up some day in the future.
> >
> > Do you want me to take these patches directly or are you just looking
> > for an Ack?
> >
> > Regards,
> > Mike
> 

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

* [PATCH v0 01/15] drivers: clk: st: Support for DIVMUX and PreDiv Clocks
@ 2014-03-25 22:59         ` Mike Turquette
  0 siblings, 0 replies; 49+ messages in thread
From: Mike Turquette @ 2014-03-25 22:59 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Gabriel Fernandez (2014-03-25 01:28:41)
> Hi Mike,
> 
> I want that you take theses patches directly.

Sure, I've taken patches #1-10 into clk-next.

Regards,
Mike

> 
> Many thanks
> 
> 
> Best regards
> 
> Gabriel.
> 
> 
> On 03/25/2014 06:27 AM, Mike Turquette wrote:
> > Quoting Gabriel FERNANDEZ (2014-02-27 07:24:14)
> >> +/**
> >> + * DOC: Clock mux with a programmable divider on each of its three inputs.
> >> + *      The mux has an input setting which effectively gates its output.
> >> + *
> >> + * Traits of this clock:
> >> + * prepare - clk_(un)prepare only ensures parent is (un)prepared
> > Minor nitpick but it doesn't look like .prepare or .unprepare are
> > supported below. It looks like this copy/paste comment applies to most
> > of the clk patches as well.
> >
> > It's a small problem and doesn't require a patch respin. But perhaps can
> > be cleaned up some day in the future.
> >
> > Do you want me to take these patches directly or are you just looking
> > for an Ack?
> >
> > Regards,
> > Mike
> 

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

end of thread, other threads:[~2014-03-25 23:00 UTC | newest]

Thread overview: 49+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-27 15:24 [PATCH v0 00/15] clk: st: Add new driver Gabriel FERNANDEZ
2014-02-27 15:24 ` Gabriel FERNANDEZ
2014-02-27 15:24 ` [PATCH v0 01/15] drivers: clk: st: Support for DIVMUX and PreDiv Clocks Gabriel FERNANDEZ
2014-02-27 15:24   ` Gabriel FERNANDEZ
2014-02-27 15:24   ` Gabriel FERNANDEZ
2014-03-25  5:27   ` Mike Turquette
2014-03-25  5:27     ` Mike Turquette
2014-03-25  5:27     ` Mike Turquette
2014-03-25  8:28     ` Gabriel Fernandez
2014-03-25  8:28       ` Gabriel Fernandez
2014-03-25  8:28       ` Gabriel Fernandez
2014-03-25 22:59       ` Mike Turquette
2014-03-25 22:59         ` Mike Turquette
2014-02-27 15:24 ` [PATCH v0 02/15] drivers: clk: st: Support for PLLs inside ClockGenA(s) Gabriel FERNANDEZ
2014-02-27 15:24   ` Gabriel FERNANDEZ
2014-02-27 15:24   ` Gabriel FERNANDEZ
2014-02-27 15:24 ` [PATCH v0 03/15] drivers: clk: st: Support for VCC-mux and MUX clocks Gabriel FERNANDEZ
2014-02-27 15:24   ` Gabriel FERNANDEZ
2014-02-27 15:24   ` Gabriel FERNANDEZ
2014-02-27 15:24 ` [PATCH v0 04/15] drivers: clk: st: Support for QUADFS inside ClockGenB/C/D/E/F Gabriel FERNANDEZ
2014-02-27 15:24   ` Gabriel FERNANDEZ
2014-02-27 15:24 ` [PATCH v0 05/15] drivers: clk: st: Support for ClockGenA9/DDR/GPU Gabriel FERNANDEZ
2014-02-27 15:24   ` Gabriel FERNANDEZ
2014-02-27 15:24 ` [PATCH v0 06/15] drivers: clk: st: Support for A9 MUX clocks Gabriel FERNANDEZ
2014-02-27 15:24   ` Gabriel FERNANDEZ
2014-02-27 15:24 ` [PATCH v0 07/15] clk: st: Adds divmux and prediv clock binding Gabriel FERNANDEZ
2014-02-27 15:24   ` Gabriel FERNANDEZ
2014-02-27 15:24 ` [PATCH v0 08/15] clk: st: Adds clockgen " Gabriel FERNANDEZ
2014-02-27 15:24   ` Gabriel FERNANDEZ
2014-02-27 15:24 ` [PATCH v0 09/15] clk: st: Adds clockgen-vcc and clockgen-mux " Gabriel FERNANDEZ
2014-02-27 15:24   ` Gabriel FERNANDEZ
2014-02-27 15:24 ` [PATCH v0 10/15] clk: st: Adds quadfs " Gabriel FERNANDEZ
2014-02-27 15:24   ` Gabriel FERNANDEZ
2014-02-27 15:24   ` Gabriel FERNANDEZ
2014-02-27 15:24 ` [PATCH v0 11/15] ARM: STi: DT: STiH416: 416 DT Entry for clockgen A0/1/10/11/12 Gabriel FERNANDEZ
2014-02-27 15:24   ` Gabriel FERNANDEZ
2014-02-27 15:24 ` [PATCH v0 12/15] ARM: STi: DT: STiH416: 416 DT Entry for clockgen B/C/D/E/F Gabriel FERNANDEZ
2014-02-27 15:24   ` Gabriel FERNANDEZ
2014-02-27 16:36   ` Lee Jones
2014-02-27 16:36     ` Lee Jones
2014-02-28 13:53     ` Gabriel Fernandez
2014-02-27 15:24 ` [PATCH v0 13/15] ARM: STi: DT: STiH416: 416 DT Entry for clockgen A9/DDR/GPU Gabriel FERNANDEZ
2014-02-27 15:24   ` Gabriel FERNANDEZ
2014-02-27 15:24   ` Gabriel FERNANDEZ
2014-02-27 15:24 ` [PATCH v0 14/15] ARM: STi: DT: STiH415: 415 DT Entry for clockgen A0/1/10/11/12 Gabriel FERNANDEZ
2014-02-27 15:24   ` Gabriel FERNANDEZ
2014-02-27 15:24   ` Gabriel FERNANDEZ
2014-02-27 15:24 ` [PATCH v0 15/15] ARM: STi: DT: STiH415: 415 DT Entry for clockgen A9 Gabriel FERNANDEZ
2014-02-27 15:24   ` Gabriel FERNANDEZ

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.