All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gerhard Sittig <gsi@denx.de>
To: linuxppc-dev@lists.ozlabs.org, Anatolij Gustschin <agust@denx.de>,
	Mike Turquette <mturquette@linaro.org>,
	linux-arm-kernel@lists.infradead.org,
	devicetree-discuss@lists.ozlabs.org
Cc: Detlev Zundel <dzu@denx.de>, Wolfram Sang <wsa@the-dreams.de>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Gerhard Sittig <gsi@denx.de>,
	Rob Herring <rob.herring@calxeda.com>,
	Mark Brown <broonie@kernel.org>,
	Marc Kleine-Budde <mkl@pengutronix.de>,
	David Woodhouse <dwmw2@infradead.org>,
	Wolfgang Grandegger <wg@grandegger.com>,
	Mauro Carvalho Chehab <m.chehab@samsung.com>
Subject: [PATCH v2 09/24] clk: mpc512x: introduce COMMON_CLK for MPC512x
Date: Thu, 18 Jul 2013 19:00:40 +0200	[thread overview]
Message-ID: <1374166855-7280-10-git-send-email-gsi@denx.de> (raw)
In-Reply-To: <1374166855-7280-1-git-send-email-gsi@denx.de>

this change introduces a clock infrastructure implementation for the
MPC512x PowerPC platform which follows the COMMON_CLK approach and uses
common clock drivers shared with other platforms

this driver implements the publicly announced set of clocks (which can
get referenced by means of symbolic identifiers from the dt-bindings
header file), as well as generates additional 'struct clk' items where
the SoC hardware cannot easily get mapped to the common primitives of
the clock API, or requires "intermediate" clock nodes to represent
clocks that have both gates and dividers

the previous PPC_CLOCK implementation is kept in place and resides in
parallel to the common clock implementation for test and comparison
during migration, a compile time option picks one of the two
alternatives (Kconfig switch, common clock used by default)

since not all drivers for peripherals were adjusted yet to properly
allocate and release their clock items, this platform clock driver
implementation pre-enables some of the clock items to not break
peripheral drivers during migration -- these clock pre-enable
workarounds will get removed as peripheral drivers get adjusted

to provide clock names which the serial communication drivers are using
and where the PSC index number is encoded into, clkdev registration is
done to not break these peripheral drivers -- this workaround will get
removed as these drivers get adjusted after device tree based clock
lookup has become available

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/Kconfig           |   14 +-
 arch/powerpc/platforms/512x/Makefile          |    4 +-
 arch/powerpc/platforms/512x/clock-commonclk.c |  778 +++++++++++++++++++++++++
 include/linux/clk-provider.h                  |   16 +
 4 files changed, 810 insertions(+), 2 deletions(-)
 create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c

diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index fc9c1cb..c5fcdd0 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,9 +1,21 @@
+config MPC512x_COMMON_CLK
+	bool "MPC512x platform uses COMMON_CLK"
+	default y
+	depends on PPC_MPC512x
+	help
+	  This option is only here to support tests and comparison
+	  during development and migration.  This option will get
+	  removed after the COMMON_CLK support for MPC512x has become
+	  fully operational and all drivers were adjusted to explicitly
+	  acquire their required clocks.
+
 config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
 	select FSL_SOC
 	select IPIC
-	select PPC_CLOCK
+	select PPC_CLOCK if !MPC512x_COMMON_CLK
+	select COMMON_CLK if MPC512x_COMMON_CLK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 72fb934..1e05f9d 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,7 +1,9 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-y				+= clock.o mpc512x_shared.o
+obj-$(CONFIG_PPC_CLOCK)		+= clock.o
+obj-$(CONFIG_COMMON_CLK)	+= clock-commonclk.o
+obj-y				+= mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
 obj-$(CONFIG_PDM360NG)		+= pdm360ng.o
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
new file mode 100644
index 0000000..6627957
--- /dev/null
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -0,0 +1,778 @@
+/*
+ * Copyright (C) 2013 DENX Software Engineering
+ *
+ * Gerhard Sittig, <gsi@denx.de>
+ *
+ * common clock driver support for the MPC512x platform
+ *
+ * This 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/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#include <asm/mpc5121.h>
+#include <dt-bindings/clock/mpc512x-clock.h>
+
+#include "mpc512x.h"		/* our public mpc5121_clk_init() API */
+
+/* helpers to keep the MCLK intermediates "somewhere" in our table */
+enum {
+	MCLK_IDX_MUX0,
+	MCLK_IDX_EN0,
+	MCLK_IDX_DIV0,
+	MCLK_IDX_MUX1,
+	MCLK_MAX_IDX,
+};
+
+#define NR_PSCS			12
+#define NR_MSCANS		4
+#define NR_SPDIFS		1
+#define NR_MCLKS		(NR_PSCS + NR_MSCANS + NR_SPDIFS)
+
+/* extend the public set of clocks by adding internal slots for management */
+enum {
+	/* arrange for adjacent numbers after the public set */
+	MPC512x_CLK_START_PRIVATE = MPC512x_CLK_LAST_PUBLIC,
+	/* clocks which aren't announced to the public */
+	MPC512x_CLK_DDR,
+	MPC512x_CLK_MEM,
+	MPC512x_CLK_IIM,
+	MPC512x_CLK_SDHC_2,
+	/* intermediates in div+gate combos or fractional dividers */
+	MPC512x_CLK_DDR_UG,
+	MPC512x_CLK_SDHC_x4,
+	MPC512x_CLK_SDHC_UG,
+	MPC512x_CLK_DIU_x4,
+	MPC512x_CLK_DIU_UG,
+	MPC512x_CLK_MBX_BUS_UG,
+	MPC512x_CLK_MBX_UG,
+	MPC512x_CLK_MBX_3D_UG,
+	MPC512x_CLK_PCI_UG,
+	MPC512x_CLK_NFC_UG,
+	MPC512x_CLK_LPC_UG,
+	MPC512x_CLK_SPDIF_TX_IN,
+	/* intermediates for the mux+gate+div+mux MCLK generation */
+	MPC512x_CLK_MCLKS_FIRST,
+	MPC512x_CLK_MCLKS_LAST = MPC512x_CLK_MCLKS_FIRST
+				+ NR_MCLKS * MCLK_MAX_IDX,
+	/* internal, symbolic spec for the number of slots */
+	MPC512x_CLK_LAST_PRIVATE,
+};
+
+/* data required for the OF clock provider registration */
+static struct clk *clks[MPC512x_CLK_LAST_PRIVATE];
+static struct clk_onecell_data clk_data;
+
+/* CCM register access */
+static struct mpc512x_ccm __iomem *clkregs;
+static DEFINE_SPINLOCK(clklock);
+
+/* convenience wrappers around the common clk API */
+static inline struct clk *mpc512x_clk_fixed(const char *name, int rate)
+{
+	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
+}
+
+static inline struct clk *mpc512x_clk_factor(
+	const char *name, const char *parent_name,
+	int mul, int div)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	return clk_register_fixed_factor(NULL, name, parent_name, clkflags,
+					 mul, div);
+}
+
+static inline struct clk *mpc512x_clk_divider(
+	const char *name, const char *parent_name, u8 clkflags,
+	u32 __iomem *reg, u8 pos, u8 len, int divflags)
+{
+	return clk_register_divider(NULL, name, parent_name, clkflags,
+				    reg, pos, len, divflags, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_divtable(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos, u8 len,
+	const struct clk_div_table *divtab)
+{
+	u8 divflags;
+
+	divflags = 0;
+	return clk_register_divider_table(NULL, name, parent_name, 0,
+					  reg, pos, len, divflags,
+					  divtab, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_gated(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	return clk_register_gate(NULL, name, parent_name, clkflags,
+				 reg, pos, 0, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_muxed(const char *name,
+	const char **parent_names, int parent_count,
+	u32 __iomem *reg, u8 pos, u8 len)
+{
+	int clkflags;
+	u8 muxflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	muxflags = 0;
+	return clk_register_mux(NULL, name,
+				parent_names, parent_count, clkflags,
+				reg, pos, len, muxflags, &clklock);
+}
+
+/* helper to isolate a bit field from a register */
+static inline int get_bit_field(uint32_t __iomem *reg, uint8_t pos, uint8_t len)
+{
+	uint32_t val;
+
+	val = in_be32(reg);
+	val >>= pos;
+	val &= (1 << len) - 1;
+	return val;
+}
+
+/* get the SPMF and translate it into the "sys pll" multiplier */
+static int get_spmf_mult(void)
+{
+	static int spmf_to_mult[] = {
+		68, 1, 12, 16, 20, 24, 28, 32,
+		36, 40, 44, 48, 52, 56, 60, 64,
+	};
+	int spmf;
+
+	spmf = get_bit_field(&clkregs->spmr, 24, 4);
+	return spmf_to_mult[spmf];
+}
+
+/*
+ * get the SYS_DIV value and translate it into a divide factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * divide ratio is fractional
+ */
+static int get_sys_div_x2(void)
+{
+	static int sysdiv_code_to_x2[] = {
+		4, 5, 6, 7, 8, 9, 10, 14,
+		12, 16, 18, 22, 20, 24, 26, 30,
+		28, 32, 34, 38, 36, 40, 42, 46,
+		44, 48, 50, 54, 52, 56, 58, 62,
+		60, 64, 66,
+	};
+	int divcode;
+
+	divcode = get_bit_field(&clkregs->scfr2, 26, 6);
+	return sysdiv_code_to_x2[divcode];
+}
+
+/*
+ * get the CPMF value and translate it into a multiplier factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * multiplier ratio is fractional
+ */
+static int get_cpmf_mult_x2(void)
+{
+	static int cpmf_to_mult[] = {
+		72, 2, 2, 3, 4, 5, 6, 7,
+	};
+	int cpmf;
+
+	cpmf = get_bit_field(&clkregs->spmr, 16, 4);
+	return cpmf_to_mult[cpmf];
+}
+
+/*
+ * some of the clock dividers do scale in a linear way, yet not all of
+ * their bit combinations are legal; use a divider table to get a
+ * resulting set of applicable divider values
+ */
+
+/* applies to the IPS_DIV, and PCI_DIV values */
+static struct clk_div_table divtab_2346[] = {
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 3, },
+	{ .val = 4, .div = 4, },
+	{ .val = 6, .div = 6, },
+	{ .div = 0, },
+};
+
+/* applies to the MBX_DIV, LPC_DIV, and NFC_DIV values */
+static struct clk_div_table divtab_1234[] = {
+	{ .val = 1, .div = 1, },
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 3, },
+	{ .val = 4, .div = 4, },
+	{ .div = 0, },
+};
+
+static int get_freq_from_dt(char *propname)
+{
+	struct device_node *np;
+	const unsigned int *prop;
+	int val;
+
+	val = 0;
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
+	if (np) {
+		prop = of_get_property(np, propname, NULL);
+		if (prop)
+			val = *prop;
+	    of_node_put(np);
+	}
+	return val;
+}
+
+static void mpc512x_clk_preset_data(void)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(clks); i++)
+		clks[i] = ERR_PTR(-ENODEV);
+}
+
+/*
+ * - receives the "bus frequency" from the caller (that's the IPS clock
+ *   rate, the historical source of clock information)
+ * - fetches the system PLL multiplier and divider values as well as the
+ *   IPS divider value from hardware
+ * - determines the REF clock rate either from the XTAL/OSC spec (if
+ *   there is a device tree node describing the oscillator) or from the
+ *   IPS bus clock (supported for backwards compatibility, such that
+ *   setups without XTAL/OSC specs keep working)
+ * - creates the "ref" clock item in the clock tree, such that
+ *   subsequent code can create the remainder of the hierarchy (REF ->
+ *   SYS -> CSB -> IPS) from the REF clock rate and the returned mul/div
+ *   values
+ */
+static void mpc512x_clk_setup_ref_clock(int bus_freq,
+	int *sys_mul, int *sys_div, int *ips_div)
+{
+	struct clk *osc_clk;
+	int calc_freq;
+
+	/* fetch mul/div factors from the hardware */
+	*sys_mul = get_spmf_mult();
+	*sys_mul *= 2;		/* compensate for the fractional divider */
+	*sys_div = get_sys_div_x2();
+	*ips_div = get_bit_field(&clkregs->scfr1, 23, 3);
+
+	/* lookup the oscillator node */
+	osc_clk = clk_get(NULL, "osc");
+	if (osc_clk) {
+		/* descend REF directly from OSC, verify the IPS rate */
+		clks[MPC512x_CLK_REF] = mpc512x_clk_factor("ref", "osc", 1, 1);
+		calc_freq = clk_get_rate(clks[MPC512x_CLK_REF]);
+		calc_freq *= *sys_mul;
+		calc_freq /= *sys_div;
+		calc_freq /= 2;
+		calc_freq /= *ips_div;
+		if (bus_freq && calc_freq != bus_freq)
+			pr_warn("calc rate %d != OF spec %d\n",
+				calc_freq, bus_freq);
+	} else {
+		/* calculate OSC rate and create REF from the freq value */
+		calc_freq = bus_freq;	/* start with IPS */
+		calc_freq *= *ips_div;	/* IPS -> CSB */
+		calc_freq *= 2;		/* CSB -> SYS */
+		calc_freq *= *sys_div;	/* SYS -> PLL out */
+		calc_freq /= *sys_mul;	/* PLL out -> REF == OSC */
+		clks[MPC512x_CLK_REF] = mpc512x_clk_fixed("ref", calc_freq);
+	}
+}
+
+/*
+ * helper code for the MCLK subtree setup
+ *
+ * the overview in section 5.2.4 of the MPC5121e Reference Manual rev4
+ * suggests that all instances of the "PSC clock generation" are equal,
+ * and that one might re-use the PSC setup for MSCAN clock generation
+ * (section 5.2.5) as well, at least the logic if not the data for
+ * description
+ *
+ * the details (starting at page 5-20) show differences in the specific
+ * inputs of the first mux stage ("can clk in", "spdif tx"), and the
+ * factual non-availability of the second mux stage (it's present yet
+ * only one input is valid)
+ *
+ * the MSCAN clock related registers (starting at page 5-35) all
+ * reference "spdif clk" at the first mux stage and don't mention any
+ * "can clk" at all, which somehow is unexpected
+ *
+ * TODO re-check the document, and clarify whether the RM is correct in
+ * the overview or in the details, and whether the difference is a
+ * clipboard induced error or results from chip revisions
+ *
+ * it turns out that the RM rev4 as of 2012-06 talks about "can" for the
+ * PSCs while RM rev3 as of 2008-10 talks about "spdif", so I guess that
+ * first a doc update is required which better reflects reality in the
+ * SoC before the implementation should follow while no questions remain
+ */
+
+/*
+ * note that this declaration raises a checkpatch warning, but
+ * it's the very data type which <linux/clk-provider.h> expects,
+ * making this declaration pass checkpatch will break compilation
+ */
+static const char *parent_names_mux0[] = {
+	"sys", "ref", "psc-mclk-in", "spdif-tx",
+};
+
+enum mclk_type {
+	MCLK_TYPE_PSC,
+	MCLK_TYPE_MSCAN,
+	MCLK_TYPE_SPDIF,
+};
+
+struct mclk_setup_data {
+	enum mclk_type type;
+	int comp_idx;
+	bool has_mclk1;
+	int bit_sccr1, bit_sccr2;
+	const char *name_mux0;
+	const char *name_en0;
+	const char *name_div0;
+	const char *parent_names_mux1[2];
+	const char *name_mux1;
+	const char *name_mclk;
+};
+
+#define MCLK_SETUP_DATA_PSC(id) { \
+	MCLK_TYPE_PSC, id, \
+	0, 27 - id, -1, \
+	"psc" #id "-mux0", \
+	"psc" #id "-en0", \
+	"psc" #id "_mclk_div", \
+	{ "psc" #id "_mclk_div", "dummy", }, \
+	"psc" #id "_mclk_out", \
+	"psc" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_MSCAN(id) { \
+	MCLK_TYPE_MSCAN, id, \
+	0, -1, 25, \
+	"mscan" #id "-mux0", \
+	"mscan" #id "-en0", \
+	"mscan" #id "_mclk_div", \
+	{ "mscan" #id "_mclk_div", "dummy", }, \
+	"mscan" #id "_mclk_out", \
+	"mscan" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_SPDIF { \
+	MCLK_TYPE_SPDIF, 0, \
+	1, -1, 23, \
+	"spdif-mux0", \
+	"spdif-en0", \
+	"spdif_mclk_div", \
+	{ "spdif_mclk_div", "spdif-rx", }, \
+	"spdif_mclk_out", \
+	"spdif_mclk", \
+}
+
+static struct mclk_setup_data mclk_psc_data[] = {
+	MCLK_SETUP_DATA_PSC(0),
+	MCLK_SETUP_DATA_PSC(1),
+	MCLK_SETUP_DATA_PSC(2),
+	MCLK_SETUP_DATA_PSC(3),
+	MCLK_SETUP_DATA_PSC(4),
+	MCLK_SETUP_DATA_PSC(5),
+	MCLK_SETUP_DATA_PSC(6),
+	MCLK_SETUP_DATA_PSC(7),
+	MCLK_SETUP_DATA_PSC(8),
+	MCLK_SETUP_DATA_PSC(9),
+	MCLK_SETUP_DATA_PSC(10),
+	MCLK_SETUP_DATA_PSC(11),
+};
+
+static struct mclk_setup_data mclk_mscan_data[] = {
+	MCLK_SETUP_DATA_MSCAN(0),
+	MCLK_SETUP_DATA_MSCAN(1),
+	MCLK_SETUP_DATA_MSCAN(2),
+	MCLK_SETUP_DATA_MSCAN(3),
+};
+
+static struct mclk_setup_data mclk_spdif_data[] = {
+	MCLK_SETUP_DATA_SPDIF,
+};
+
+/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
+static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
+{
+	size_t clks_idx_pub, clks_idx_int;
+	u32 __iomem *mccr_reg;	/* MCLK control register (mux, en, div) */
+	u32 __iomem *sccr_reg;	/* system clock control register (enable) */
+	int sccr_bit;
+	int div;
+
+	/* derive a few parameters from the component type and index */
+	switch (entry->type) {
+	case MCLK_TYPE_PSC:
+		clks_idx_pub = MPC512x_CLK_PSC0_MCLK + entry->comp_idx;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (entry->comp_idx) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->psc_ccr[entry->comp_idx];
+		break;
+	case MCLK_TYPE_MSCAN:
+		clks_idx_pub = MPC512x_CLK_MSCAN0_MCLK + entry->comp_idx;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (NR_PSCS + entry->comp_idx) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->mscan_ccr[entry->comp_idx];
+		break;
+	case MCLK_TYPE_SPDIF:
+		clks_idx_pub = MPC512x_CLK_SPDIF_MCLK;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->spccr;
+		break;
+	default:
+		return;
+	}
+	if (entry->bit_sccr1 >= 0) {
+		sccr_reg = &clkregs->sccr1;
+		sccr_bit = entry->bit_sccr1;
+	} else if (entry->bit_sccr2 >= 0) {
+		sccr_reg = &clkregs->sccr2;
+		sccr_bit = entry->bit_sccr2;
+	} else {
+		sccr_reg = NULL;
+	}
+
+	/*
+	 * this was grabbed from the PPC_CLOCK implementation, which
+	 * enforced a specific MCLK divider while the clock was gated
+	 * during setup (that's a documented hardware requirement)
+	 *
+	 * the PPC_CLOCK implementation might even have violated the
+	 * "MCLK <= IPS" constraint, the fixed divider value of 1
+	 * results in a divider of 2 and thus MCLK = SYS/2 which equals
+	 * CSB which is greater than IPS; the serial port setup may have
+	 * adjusted the divider which the clock setup might have left in
+	 * an undesirable state
+	 *
+	 * initial setup is:
+	 * - MCLK 0 from SYS
+	 * - MCLK DIV such to not exceed the IPS clock
+	 * - MCLK 0 enabled
+	 * - MCLK 1 from MCLK DIV
+	 */
+	div = clk_get_rate(clks[MPC512x_CLK_SYS]);
+	div /= clk_get_rate(clks[MPC512x_CLK_IPS]);
+	out_be32(mccr_reg, (0 << 16));
+	out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
+	out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
+
+	/*
+	 * create the 'struct clk' items of the MCLK's clock subtree
+	 *
+	 * note that by design we always create all nodes and won't take
+	 * shortcuts here, because
+	 * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are
+	 *   selectable inputs to the CFM while those who "actually use"
+	 *   the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK
+	 *   for their bitrate
+	 * - in the absence of "aliases" for clocks we need to create
+	 *   individial 'struct clk' items for whatever might get
+	 *   referenced or looked up, even if several of those items are
+	 *   identical from the logical POV (their rate value)
+	 * - for easier future maintenance and for better reflection of
+	 *   the SoC's documentation, it appears appropriate to generate
+	 *   clock items even for those muxers which actually are NOPs
+	 *   (those with two inputs of which one is reserved)
+	 */
+	clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed(
+			entry->name_mux0,
+			&parent_names_mux0[0], ARRAY_SIZE(parent_names_mux0),
+			mccr_reg, 14, 2);
+	clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated(
+			entry->name_en0, entry->name_mux0,
+			mccr_reg, 16);
+	clks[clks_idx_int + MCLK_IDX_DIV0] = mpc512x_clk_divider(
+			entry->name_div0,
+			entry->name_en0, CLK_SET_RATE_GATE,
+			mccr_reg, 17, 15, 0);
+	if (entry->has_mclk1) {
+		clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_muxed(
+				entry->name_mux1,
+				&entry->parent_names_mux1[0],
+				ARRAY_SIZE(entry->parent_names_mux1),
+				mccr_reg, 7, 1);
+	} else {
+		clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_factor(
+				entry->name_mux1, entry->parent_names_mux1[0],
+				1, 1);
+	}
+	if (sccr_reg) {
+		clks[clks_idx_pub] = mpc512x_clk_gated(
+				entry->name_mclk,
+				entry->name_mux1, sccr_reg, sccr_bit);
+	} else {
+		clks[clks_idx_pub] = mpc512x_clk_factor(
+				entry->name_mclk,
+				entry->name_mux1, 1, 1);
+	}
+
+	/*
+	 * without this "clock device" registration, "simple" lookups in
+	 * the SPI master initialization and serial port setup will fail
+	 *
+	 * those drivers need to get adjusted to lookup their required
+	 * clocks from device tree specs, and device tree nodes need to
+	 * provide the clock specs, before this clkdev registration
+	 * becomes obsolete
+	 */
+	clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
+}
+
+static void mpc512x_clk_setup_mclks(struct mclk_setup_data *table, size_t count)
+{
+	while (count-- > 0)
+		mpc512x_clk_setup_mclk(table++);
+}
+
+static void mpc512x_clk_setup_clock_tree(int busfreq)
+{
+	int sys_mul, sys_div, ips_div;
+	int mul, div;
+	int freq;
+
+	/*
+	 * TODO
+	 * - consider whether to handle clocks which have both gates and
+	 *   dividers via intermediates or by means of composites
+	 * - fractional dividers appear to not map well to composites
+	 *   since they can be seen as a fixed multiplier and an
+	 *   adjustable divider, while composites can only combine at
+	 *   most one of a mux, div, and gate each into one 'struct clk'
+	 *   item
+	 * - PSC/MSCAN/SPDIF clock generation OTOH already is very
+	 *   specific and cannot get mapped to componsites (at least not
+	 *   a single one, maybe two of them, but see the comment about
+	 *   "intermediates are referenced from elsewhere, too")
+	 * - trim the list of auto-enabled clocks after drivers acquire
+	 *   them correctly as needed
+	 */
+
+	/* regardless of whether XTAL/OSC exists, have REF created */
+	mpc512x_clk_setup_ref_clock(busfreq, &sys_mul, &sys_div, &ips_div);
+
+	/* now setup the REF -> SYS -> CSB -> IPS hierarchy */
+	clks[MPC512x_CLK_SYS] = mpc512x_clk_factor("sys", "ref",
+						   sys_mul, sys_div);
+	clks[MPC512x_CLK_CSB] = mpc512x_clk_factor("csb", "sys", 1, 2);
+	clks[MPC512x_CLK_IPS] = mpc512x_clk_divtable("ips", "csb",
+						     &clkregs->scfr1, 23, 3,
+						     divtab_2346);
+
+	/* now setup anything below SYS and CSB and IPS */
+	clks[MPC512x_CLK_DDR_UG] = mpc512x_clk_factor("ddr-ug", "sys", 1, 2);
+	clks[MPC512x_CLK_SDHC_x4] = mpc512x_clk_factor("sdhc-x4", "csb", 4, 1);
+	clks[MPC512x_CLK_SDHC_UG] = mpc512x_clk_divider("sdhc-ug", "sdhc-x4", 0,
+							&clkregs->scfr2, 0, 8,
+							CLK_DIVIDER_ONE_BASED);
+	clks[MPC512x_CLK_DIU_x4] = mpc512x_clk_factor("diu-x4", "csb", 4, 1);
+	clks[MPC512x_CLK_DIU_UG] = mpc512x_clk_divider("diu-ug", "diu-x4", 0,
+						       &clkregs->scfr1, 0, 8,
+						       CLK_DIVIDER_ONE_BASED);
+
+	/*
+	 * the "power architecture PLL" was setup from data which was
+	 * sampled from the reset config word, at this point in time the
+	 * configuration can be considered fixed and read only (i.e. no
+	 * longer adjustable, or no longer in need of adjustment), which
+	 * is why we don't register a PLL here but assume fixed factors
+	 */
+	mul = get_cpmf_mult_x2();
+	div = 2;	/* compensate for the fractional factor */
+	clks[MPC512x_CLK_E300] = mpc512x_clk_factor("e300", "csb", mul, div);
+
+	clks[MPC512x_CLK_MBX_BUS_UG] = mpc512x_clk_factor("mbx-bus-ug", "csb",
+							  1, 2);
+	clks[MPC512x_CLK_MBX_UG] = mpc512x_clk_divtable("mbx-ug", "mbx-bus-ug",
+							&clkregs->scfr1, 14, 3,
+							divtab_1234);
+	clks[MPC512x_CLK_MBX_3D_UG] = mpc512x_clk_factor("mbx-3d-ug", "mbx-ug",
+							 1, 1);
+	clks[MPC512x_CLK_PCI_UG] = mpc512x_clk_divtable("pci-ug", "csb",
+							&clkregs->scfr1, 20, 3,
+							divtab_2346);
+	clks[MPC512x_CLK_NFC_UG] = mpc512x_clk_divtable("nfc-ug", "ips",
+							&clkregs->scfr1, 8, 3,
+							divtab_1234);
+	clks[MPC512x_CLK_LPC_UG] = mpc512x_clk_divtable("lpc-ug", "ips",
+							&clkregs->scfr1, 11, 3,
+							divtab_1234);
+
+	clks[MPC512x_CLK_LPC] = mpc512x_clk_gated("lpc", "lpc-ug",
+						  &clkregs->sccr1, 30);
+	clks[MPC512x_CLK_NFC] = mpc512x_clk_gated("nfc", "nfc-ug",
+						  &clkregs->sccr1, 29);
+	clks[MPC512x_CLK_PATA] = mpc512x_clk_gated("pata", "ips",
+						   &clkregs->sccr1, 28);
+	mpc512x_clk_setup_mclks(mclk_psc_data, ARRAY_SIZE(mclk_psc_data));
+	clks[MPC512x_CLK_PSC_FIFO] = mpc512x_clk_gated("psc-fifo", "ips",
+						       &clkregs->sccr1, 15);
+	clks[MPC512x_CLK_SATA] = mpc512x_clk_gated("sata", "ips",
+						   &clkregs->sccr1, 14);
+	clks[MPC512x_CLK_FEC] = mpc512x_clk_gated("fec", "ips",
+						  &clkregs->sccr1, 13);
+	clks[MPC512x_CLK_PCI] = mpc512x_clk_gated("pci", "pci-ug",
+						  &clkregs->sccr1, 11);
+	clks[MPC512x_CLK_DDR] = mpc512x_clk_gated("ddr", "ddr-ug",
+						  &clkregs->sccr1, 10);
+
+	clks[MPC512x_CLK_DIU] = mpc512x_clk_gated("diu", "diu-ug",
+						  &clkregs->sccr2, 31);
+	clks[MPC512x_CLK_AXE] = mpc512x_clk_gated("axe", "csb",
+						  &clkregs->sccr2, 30);
+	clks[MPC512x_CLK_MEM] = mpc512x_clk_gated("mem", "ips",
+						  &clkregs->sccr2, 29);
+	clks[MPC512x_CLK_USB1] = mpc512x_clk_gated("usb1", "csb",
+						   &clkregs->sccr2, 28);
+	clks[MPC512x_CLK_USB2] = mpc512x_clk_gated("usb2", "csb",
+						   &clkregs->sccr2, 27);
+	clks[MPC512x_CLK_I2C] = mpc512x_clk_gated("i2c", "ips",
+						  &clkregs->sccr2, 26);
+	mpc512x_clk_setup_mclks(mclk_mscan_data, ARRAY_SIZE(mclk_mscan_data));
+	clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug",
+						   &clkregs->sccr2, 24);
+	mpc512x_clk_setup_mclks(mclk_spdif_data, ARRAY_SIZE(mclk_spdif_data));
+	clks[MPC512x_CLK_MBX_BUS] = mpc512x_clk_gated("mbx-bus", "mbx-bus-ug",
+						      &clkregs->sccr2, 22);
+	clks[MPC512x_CLK_MBX] = mpc512x_clk_gated("mbx", "mbx-ug",
+						  &clkregs->sccr2, 21);
+	clks[MPC512x_CLK_MBX_3D] = mpc512x_clk_gated("mbx-3d", "mbx-3d-ug",
+						     &clkregs->sccr2, 20);
+	clks[MPC512x_CLK_IIM] = mpc512x_clk_gated("iim", "csb",
+						  &clkregs->sccr2, 19);
+	clks[MPC512x_CLK_VIU] = mpc512x_clk_gated("viu", "csb",
+						  &clkregs->sccr2, 18);
+	clks[MPC512x_CLK_SDHC_2] = mpc512x_clk_gated("sdhc-2", "sdhc-ug",
+						     &clkregs->sccr2, 17);
+
+	/*
+	 * externally provided clocks (when implemented in hardware,
+	 * device tree may specify values which otherwise were unknown)
+	 */
+	freq = get_freq_from_dt("psc_mclk_in");
+	if (!freq)
+		freq = 25000000;
+	clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
+	freq = get_freq_from_dt("spdif_tx_in");
+	clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq);
+	freq = get_freq_from_dt("spdif_rx_in");
+	clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq);
+
+	/* fixed frequency for AC97, always 24.567MHz */
+	clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
+
+	pr_debug("clock tree setup complete\n");
+	freq = clk_get_rate(clks[MPC512x_CLK_E300]);
+	pr_debug("derived PPC freq [%d]\n", freq);
+	freq = clk_get_rate(clks[MPC512x_CLK_IPS]);
+	pr_debug("derived IPS freq [%d]\n", freq);
+	freq = clk_get_rate(clks[MPC512x_CLK_LPC]);
+	pr_debug("derived LPC freq [%d]\n", freq);
+
+	/* enable some of the clocks here unconditionally because ... */
+	pr_debug("automatically enabling some clocks\n");
+	/* some are essential yet never get claimed by any driver */
+	clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
+	clk_prepare_enable(clks[MPC512x_CLK_E300]);	/* PowerPC CPU */
+	clk_prepare_enable(clks[MPC512x_CLK_DDR]);	/* DRAM */
+	clk_prepare_enable(clks[MPC512x_CLK_MEM]);	/* SRAM */
+	clk_prepare_enable(clks[MPC512x_CLK_IPS]);	/* SoC periph */
+	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
+	/* some are required yet no dependencies were declared */
+	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
+	/* some are not yet acquired by their respective drivers */
+	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
+	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
+	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
+	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
+	/*
+	 * some have their individual clock subtree with separate clock
+	 * items and their individual enable counters, yet share a
+	 * common gate (refer to the same register location) while the
+	 * common clock driver code is not aware of the fact and the
+	 * platform's code doesn't provide specific support either
+	 *
+	 * what might happen is that e.g. enabling two MSCAN clock items
+	 * and disabling one of them will disable the common gate and
+	 * thus break the other MSCAN clock as well
+	 */
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN1_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN2_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN3_MCLK]);
+}
+
+/*
+ * registers the set of public clocks (those listed in the dt-bindings/
+ * header file) for OF lookups, keeps the intermediates private to us
+ */
+static void mpc5121_clk_register_of_provider(struct device_node *np)
+{
+	clk_data.clks = clks;
+	clk_data.clk_num = MPC512x_CLK_LAST_PUBLIC + 1;	/* _not_ ARRAY_SIZE() */
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+
+int __init mpc5121_clk_init(void)
+{
+	struct device_node *clk_np;
+	int busfreq;
+
+	/* map the clock control registers */
+	clk_np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+	if (!clk_np)
+		return -ENODEV;
+	clkregs = of_iomap(clk_np, 0);
+	WARN_ON(!clkregs);
+
+	/* invalidate all not yet registered clock slots */
+	mpc512x_clk_preset_data();
+
+	/*
+	 * have the device tree scanned for "fixed-clock" nodes (which
+	 * includes the oscillator node if the board's DT provides one)
+	 */
+	of_clk_init(NULL);
+
+	/*
+	 * add a dummy clock for those situations where a clock spec is
+	 * required yet no real clock is involved
+	 */
+	clks[MPC512x_CLK_DUMMY] = mpc512x_clk_fixed("dummy", 0);
+
+	/*
+	 * have all the real nodes in the clock tree populated from REF
+	 * down to all leaves, either starting from the OSC node or from
+	 * a REF root that was created from the IPS bus clock input
+	 */
+	busfreq = get_freq_from_dt("bus-frequency");
+	mpc512x_clk_setup_clock_tree(busfreq);
+
+	/* register as an OF clock provider */
+	mpc5121_clk_register_of_provider(clk_np);
+
+	return 0;
+}
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index c4f7799..7f8fc64 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -497,6 +497,20 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
  * for improved portability across platforms
  */
 
+#if IS_ENABLED(CONFIG_PPC)
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+	return ioread32be(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+	iowrite32be(val, reg);
+}
+
+#else	/* platform dependent I/O accessors */
+
 static inline u32 clk_readl(u32 __iomem *reg)
 {
 	return readl(reg);
@@ -507,5 +521,7 @@ static inline void clk_writel(u32 val, u32 __iomem *reg)
 	writel(val, reg);
 }
 
+#endif	/* platform dependent I/O accessors */
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
-- 
1.7.10.4

WARNING: multiple messages have this Message-ID (diff)
From: gsi@denx.de (Gerhard Sittig)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2 09/24] clk: mpc512x: introduce COMMON_CLK for MPC512x
Date: Thu, 18 Jul 2013 19:00:40 +0200	[thread overview]
Message-ID: <1374166855-7280-10-git-send-email-gsi@denx.de> (raw)
In-Reply-To: <1374166855-7280-1-git-send-email-gsi@denx.de>

this change introduces a clock infrastructure implementation for the
MPC512x PowerPC platform which follows the COMMON_CLK approach and uses
common clock drivers shared with other platforms

this driver implements the publicly announced set of clocks (which can
get referenced by means of symbolic identifiers from the dt-bindings
header file), as well as generates additional 'struct clk' items where
the SoC hardware cannot easily get mapped to the common primitives of
the clock API, or requires "intermediate" clock nodes to represent
clocks that have both gates and dividers

the previous PPC_CLOCK implementation is kept in place and resides in
parallel to the common clock implementation for test and comparison
during migration, a compile time option picks one of the two
alternatives (Kconfig switch, common clock used by default)

since not all drivers for peripherals were adjusted yet to properly
allocate and release their clock items, this platform clock driver
implementation pre-enables some of the clock items to not break
peripheral drivers during migration -- these clock pre-enable
workarounds will get removed as peripheral drivers get adjusted

to provide clock names which the serial communication drivers are using
and where the PSC index number is encoded into, clkdev registration is
done to not break these peripheral drivers -- this workaround will get
removed as these drivers get adjusted after device tree based clock
lookup has become available

Signed-off-by: Gerhard Sittig <gsi@denx.de>
---
 arch/powerpc/platforms/512x/Kconfig           |   14 +-
 arch/powerpc/platforms/512x/Makefile          |    4 +-
 arch/powerpc/platforms/512x/clock-commonclk.c |  778 +++++++++++++++++++++++++
 include/linux/clk-provider.h                  |   16 +
 4 files changed, 810 insertions(+), 2 deletions(-)
 create mode 100644 arch/powerpc/platforms/512x/clock-commonclk.c

diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index fc9c1cb..c5fcdd0 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -1,9 +1,21 @@
+config MPC512x_COMMON_CLK
+	bool "MPC512x platform uses COMMON_CLK"
+	default y
+	depends on PPC_MPC512x
+	help
+	  This option is only here to support tests and comparison
+	  during development and migration.  This option will get
+	  removed after the COMMON_CLK support for MPC512x has become
+	  fully operational and all drivers were adjusted to explicitly
+	  acquire their required clocks.
+
 config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
 	select FSL_SOC
 	select IPIC
-	select PPC_CLOCK
+	select PPC_CLOCK if !MPC512x_COMMON_CLK
+	select COMMON_CLK if MPC512x_COMMON_CLK
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 72fb934..1e05f9d 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -1,7 +1,9 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-y				+= clock.o mpc512x_shared.o
+obj-$(CONFIG_PPC_CLOCK)		+= clock.o
+obj-$(CONFIG_COMMON_CLK)	+= clock-commonclk.o
+obj-y				+= mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)	+= mpc512x_generic.o
 obj-$(CONFIG_PDM360NG)		+= pdm360ng.o
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
new file mode 100644
index 0000000..6627957
--- /dev/null
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -0,0 +1,778 @@
+/*
+ * Copyright (C) 2013 DENX Software Engineering
+ *
+ * Gerhard Sittig, <gsi@denx.de>
+ *
+ * common clock driver support for the MPC512x platform
+ *
+ * This 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/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#include <asm/mpc5121.h>
+#include <dt-bindings/clock/mpc512x-clock.h>
+
+#include "mpc512x.h"		/* our public mpc5121_clk_init() API */
+
+/* helpers to keep the MCLK intermediates "somewhere" in our table */
+enum {
+	MCLK_IDX_MUX0,
+	MCLK_IDX_EN0,
+	MCLK_IDX_DIV0,
+	MCLK_IDX_MUX1,
+	MCLK_MAX_IDX,
+};
+
+#define NR_PSCS			12
+#define NR_MSCANS		4
+#define NR_SPDIFS		1
+#define NR_MCLKS		(NR_PSCS + NR_MSCANS + NR_SPDIFS)
+
+/* extend the public set of clocks by adding internal slots for management */
+enum {
+	/* arrange for adjacent numbers after the public set */
+	MPC512x_CLK_START_PRIVATE = MPC512x_CLK_LAST_PUBLIC,
+	/* clocks which aren't announced to the public */
+	MPC512x_CLK_DDR,
+	MPC512x_CLK_MEM,
+	MPC512x_CLK_IIM,
+	MPC512x_CLK_SDHC_2,
+	/* intermediates in div+gate combos or fractional dividers */
+	MPC512x_CLK_DDR_UG,
+	MPC512x_CLK_SDHC_x4,
+	MPC512x_CLK_SDHC_UG,
+	MPC512x_CLK_DIU_x4,
+	MPC512x_CLK_DIU_UG,
+	MPC512x_CLK_MBX_BUS_UG,
+	MPC512x_CLK_MBX_UG,
+	MPC512x_CLK_MBX_3D_UG,
+	MPC512x_CLK_PCI_UG,
+	MPC512x_CLK_NFC_UG,
+	MPC512x_CLK_LPC_UG,
+	MPC512x_CLK_SPDIF_TX_IN,
+	/* intermediates for the mux+gate+div+mux MCLK generation */
+	MPC512x_CLK_MCLKS_FIRST,
+	MPC512x_CLK_MCLKS_LAST = MPC512x_CLK_MCLKS_FIRST
+				+ NR_MCLKS * MCLK_MAX_IDX,
+	/* internal, symbolic spec for the number of slots */
+	MPC512x_CLK_LAST_PRIVATE,
+};
+
+/* data required for the OF clock provider registration */
+static struct clk *clks[MPC512x_CLK_LAST_PRIVATE];
+static struct clk_onecell_data clk_data;
+
+/* CCM register access */
+static struct mpc512x_ccm __iomem *clkregs;
+static DEFINE_SPINLOCK(clklock);
+
+/* convenience wrappers around the common clk API */
+static inline struct clk *mpc512x_clk_fixed(const char *name, int rate)
+{
+	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
+}
+
+static inline struct clk *mpc512x_clk_factor(
+	const char *name, const char *parent_name,
+	int mul, int div)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	return clk_register_fixed_factor(NULL, name, parent_name, clkflags,
+					 mul, div);
+}
+
+static inline struct clk *mpc512x_clk_divider(
+	const char *name, const char *parent_name, u8 clkflags,
+	u32 __iomem *reg, u8 pos, u8 len, int divflags)
+{
+	return clk_register_divider(NULL, name, parent_name, clkflags,
+				    reg, pos, len, divflags, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_divtable(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos, u8 len,
+	const struct clk_div_table *divtab)
+{
+	u8 divflags;
+
+	divflags = 0;
+	return clk_register_divider_table(NULL, name, parent_name, 0,
+					  reg, pos, len, divflags,
+					  divtab, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_gated(
+	const char *name, const char *parent_name,
+	u32 __iomem *reg, u8 pos)
+{
+	int clkflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	return clk_register_gate(NULL, name, parent_name, clkflags,
+				 reg, pos, 0, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_muxed(const char *name,
+	const char **parent_names, int parent_count,
+	u32 __iomem *reg, u8 pos, u8 len)
+{
+	int clkflags;
+	u8 muxflags;
+
+	clkflags = CLK_SET_RATE_PARENT;
+	muxflags = 0;
+	return clk_register_mux(NULL, name,
+				parent_names, parent_count, clkflags,
+				reg, pos, len, muxflags, &clklock);
+}
+
+/* helper to isolate a bit field from a register */
+static inline int get_bit_field(uint32_t __iomem *reg, uint8_t pos, uint8_t len)
+{
+	uint32_t val;
+
+	val = in_be32(reg);
+	val >>= pos;
+	val &= (1 << len) - 1;
+	return val;
+}
+
+/* get the SPMF and translate it into the "sys pll" multiplier */
+static int get_spmf_mult(void)
+{
+	static int spmf_to_mult[] = {
+		68, 1, 12, 16, 20, 24, 28, 32,
+		36, 40, 44, 48, 52, 56, 60, 64,
+	};
+	int spmf;
+
+	spmf = get_bit_field(&clkregs->spmr, 24, 4);
+	return spmf_to_mult[spmf];
+}
+
+/*
+ * get the SYS_DIV value and translate it into a divide factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * divide ratio is fractional
+ */
+static int get_sys_div_x2(void)
+{
+	static int sysdiv_code_to_x2[] = {
+		4, 5, 6, 7, 8, 9, 10, 14,
+		12, 16, 18, 22, 20, 24, 26, 30,
+		28, 32, 34, 38, 36, 40, 42, 46,
+		44, 48, 50, 54, 52, 56, 58, 62,
+		60, 64, 66,
+	};
+	int divcode;
+
+	divcode = get_bit_field(&clkregs->scfr2, 26, 6);
+	return sysdiv_code_to_x2[divcode];
+}
+
+/*
+ * get the CPMF value and translate it into a multiplier factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * multiplier ratio is fractional
+ */
+static int get_cpmf_mult_x2(void)
+{
+	static int cpmf_to_mult[] = {
+		72, 2, 2, 3, 4, 5, 6, 7,
+	};
+	int cpmf;
+
+	cpmf = get_bit_field(&clkregs->spmr, 16, 4);
+	return cpmf_to_mult[cpmf];
+}
+
+/*
+ * some of the clock dividers do scale in a linear way, yet not all of
+ * their bit combinations are legal; use a divider table to get a
+ * resulting set of applicable divider values
+ */
+
+/* applies to the IPS_DIV, and PCI_DIV values */
+static struct clk_div_table divtab_2346[] = {
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 3, },
+	{ .val = 4, .div = 4, },
+	{ .val = 6, .div = 6, },
+	{ .div = 0, },
+};
+
+/* applies to the MBX_DIV, LPC_DIV, and NFC_DIV values */
+static struct clk_div_table divtab_1234[] = {
+	{ .val = 1, .div = 1, },
+	{ .val = 2, .div = 2, },
+	{ .val = 3, .div = 3, },
+	{ .val = 4, .div = 4, },
+	{ .div = 0, },
+};
+
+static int get_freq_from_dt(char *propname)
+{
+	struct device_node *np;
+	const unsigned int *prop;
+	int val;
+
+	val = 0;
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
+	if (np) {
+		prop = of_get_property(np, propname, NULL);
+		if (prop)
+			val = *prop;
+	    of_node_put(np);
+	}
+	return val;
+}
+
+static void mpc512x_clk_preset_data(void)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(clks); i++)
+		clks[i] = ERR_PTR(-ENODEV);
+}
+
+/*
+ * - receives the "bus frequency" from the caller (that's the IPS clock
+ *   rate, the historical source of clock information)
+ * - fetches the system PLL multiplier and divider values as well as the
+ *   IPS divider value from hardware
+ * - determines the REF clock rate either from the XTAL/OSC spec (if
+ *   there is a device tree node describing the oscillator) or from the
+ *   IPS bus clock (supported for backwards compatibility, such that
+ *   setups without XTAL/OSC specs keep working)
+ * - creates the "ref" clock item in the clock tree, such that
+ *   subsequent code can create the remainder of the hierarchy (REF ->
+ *   SYS -> CSB -> IPS) from the REF clock rate and the returned mul/div
+ *   values
+ */
+static void mpc512x_clk_setup_ref_clock(int bus_freq,
+	int *sys_mul, int *sys_div, int *ips_div)
+{
+	struct clk *osc_clk;
+	int calc_freq;
+
+	/* fetch mul/div factors from the hardware */
+	*sys_mul = get_spmf_mult();
+	*sys_mul *= 2;		/* compensate for the fractional divider */
+	*sys_div = get_sys_div_x2();
+	*ips_div = get_bit_field(&clkregs->scfr1, 23, 3);
+
+	/* lookup the oscillator node */
+	osc_clk = clk_get(NULL, "osc");
+	if (osc_clk) {
+		/* descend REF directly from OSC, verify the IPS rate */
+		clks[MPC512x_CLK_REF] = mpc512x_clk_factor("ref", "osc", 1, 1);
+		calc_freq = clk_get_rate(clks[MPC512x_CLK_REF]);
+		calc_freq *= *sys_mul;
+		calc_freq /= *sys_div;
+		calc_freq /= 2;
+		calc_freq /= *ips_div;
+		if (bus_freq && calc_freq != bus_freq)
+			pr_warn("calc rate %d != OF spec %d\n",
+				calc_freq, bus_freq);
+	} else {
+		/* calculate OSC rate and create REF from the freq value */
+		calc_freq = bus_freq;	/* start with IPS */
+		calc_freq *= *ips_div;	/* IPS -> CSB */
+		calc_freq *= 2;		/* CSB -> SYS */
+		calc_freq *= *sys_div;	/* SYS -> PLL out */
+		calc_freq /= *sys_mul;	/* PLL out -> REF == OSC */
+		clks[MPC512x_CLK_REF] = mpc512x_clk_fixed("ref", calc_freq);
+	}
+}
+
+/*
+ * helper code for the MCLK subtree setup
+ *
+ * the overview in section 5.2.4 of the MPC5121e Reference Manual rev4
+ * suggests that all instances of the "PSC clock generation" are equal,
+ * and that one might re-use the PSC setup for MSCAN clock generation
+ * (section 5.2.5) as well, at least the logic if not the data for
+ * description
+ *
+ * the details (starting at page 5-20) show differences in the specific
+ * inputs of the first mux stage ("can clk in", "spdif tx"), and the
+ * factual non-availability of the second mux stage (it's present yet
+ * only one input is valid)
+ *
+ * the MSCAN clock related registers (starting at page 5-35) all
+ * reference "spdif clk" at the first mux stage and don't mention any
+ * "can clk" at all, which somehow is unexpected
+ *
+ * TODO re-check the document, and clarify whether the RM is correct in
+ * the overview or in the details, and whether the difference is a
+ * clipboard induced error or results from chip revisions
+ *
+ * it turns out that the RM rev4 as of 2012-06 talks about "can" for the
+ * PSCs while RM rev3 as of 2008-10 talks about "spdif", so I guess that
+ * first a doc update is required which better reflects reality in the
+ * SoC before the implementation should follow while no questions remain
+ */
+
+/*
+ * note that this declaration raises a checkpatch warning, but
+ * it's the very data type which <linux/clk-provider.h> expects,
+ * making this declaration pass checkpatch will break compilation
+ */
+static const char *parent_names_mux0[] = {
+	"sys", "ref", "psc-mclk-in", "spdif-tx",
+};
+
+enum mclk_type {
+	MCLK_TYPE_PSC,
+	MCLK_TYPE_MSCAN,
+	MCLK_TYPE_SPDIF,
+};
+
+struct mclk_setup_data {
+	enum mclk_type type;
+	int comp_idx;
+	bool has_mclk1;
+	int bit_sccr1, bit_sccr2;
+	const char *name_mux0;
+	const char *name_en0;
+	const char *name_div0;
+	const char *parent_names_mux1[2];
+	const char *name_mux1;
+	const char *name_mclk;
+};
+
+#define MCLK_SETUP_DATA_PSC(id) { \
+	MCLK_TYPE_PSC, id, \
+	0, 27 - id, -1, \
+	"psc" #id "-mux0", \
+	"psc" #id "-en0", \
+	"psc" #id "_mclk_div", \
+	{ "psc" #id "_mclk_div", "dummy", }, \
+	"psc" #id "_mclk_out", \
+	"psc" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_MSCAN(id) { \
+	MCLK_TYPE_MSCAN, id, \
+	0, -1, 25, \
+	"mscan" #id "-mux0", \
+	"mscan" #id "-en0", \
+	"mscan" #id "_mclk_div", \
+	{ "mscan" #id "_mclk_div", "dummy", }, \
+	"mscan" #id "_mclk_out", \
+	"mscan" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_SPDIF { \
+	MCLK_TYPE_SPDIF, 0, \
+	1, -1, 23, \
+	"spdif-mux0", \
+	"spdif-en0", \
+	"spdif_mclk_div", \
+	{ "spdif_mclk_div", "spdif-rx", }, \
+	"spdif_mclk_out", \
+	"spdif_mclk", \
+}
+
+static struct mclk_setup_data mclk_psc_data[] = {
+	MCLK_SETUP_DATA_PSC(0),
+	MCLK_SETUP_DATA_PSC(1),
+	MCLK_SETUP_DATA_PSC(2),
+	MCLK_SETUP_DATA_PSC(3),
+	MCLK_SETUP_DATA_PSC(4),
+	MCLK_SETUP_DATA_PSC(5),
+	MCLK_SETUP_DATA_PSC(6),
+	MCLK_SETUP_DATA_PSC(7),
+	MCLK_SETUP_DATA_PSC(8),
+	MCLK_SETUP_DATA_PSC(9),
+	MCLK_SETUP_DATA_PSC(10),
+	MCLK_SETUP_DATA_PSC(11),
+};
+
+static struct mclk_setup_data mclk_mscan_data[] = {
+	MCLK_SETUP_DATA_MSCAN(0),
+	MCLK_SETUP_DATA_MSCAN(1),
+	MCLK_SETUP_DATA_MSCAN(2),
+	MCLK_SETUP_DATA_MSCAN(3),
+};
+
+static struct mclk_setup_data mclk_spdif_data[] = {
+	MCLK_SETUP_DATA_SPDIF,
+};
+
+/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
+static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry)
+{
+	size_t clks_idx_pub, clks_idx_int;
+	u32 __iomem *mccr_reg;	/* MCLK control register (mux, en, div) */
+	u32 __iomem *sccr_reg;	/* system clock control register (enable) */
+	int sccr_bit;
+	int div;
+
+	/* derive a few parameters from the component type and index */
+	switch (entry->type) {
+	case MCLK_TYPE_PSC:
+		clks_idx_pub = MPC512x_CLK_PSC0_MCLK + entry->comp_idx;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (entry->comp_idx) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->psc_ccr[entry->comp_idx];
+		break;
+	case MCLK_TYPE_MSCAN:
+		clks_idx_pub = MPC512x_CLK_MSCAN0_MCLK + entry->comp_idx;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (NR_PSCS + entry->comp_idx) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->mscan_ccr[entry->comp_idx];
+		break;
+	case MCLK_TYPE_SPDIF:
+		clks_idx_pub = MPC512x_CLK_SPDIF_MCLK;
+		clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+			     + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
+		mccr_reg = &clkregs->spccr;
+		break;
+	default:
+		return;
+	}
+	if (entry->bit_sccr1 >= 0) {
+		sccr_reg = &clkregs->sccr1;
+		sccr_bit = entry->bit_sccr1;
+	} else if (entry->bit_sccr2 >= 0) {
+		sccr_reg = &clkregs->sccr2;
+		sccr_bit = entry->bit_sccr2;
+	} else {
+		sccr_reg = NULL;
+	}
+
+	/*
+	 * this was grabbed from the PPC_CLOCK implementation, which
+	 * enforced a specific MCLK divider while the clock was gated
+	 * during setup (that's a documented hardware requirement)
+	 *
+	 * the PPC_CLOCK implementation might even have violated the
+	 * "MCLK <= IPS" constraint, the fixed divider value of 1
+	 * results in a divider of 2 and thus MCLK = SYS/2 which equals
+	 * CSB which is greater than IPS; the serial port setup may have
+	 * adjusted the divider which the clock setup might have left in
+	 * an undesirable state
+	 *
+	 * initial setup is:
+	 * - MCLK 0 from SYS
+	 * - MCLK DIV such to not exceed the IPS clock
+	 * - MCLK 0 enabled
+	 * - MCLK 1 from MCLK DIV
+	 */
+	div = clk_get_rate(clks[MPC512x_CLK_SYS]);
+	div /= clk_get_rate(clks[MPC512x_CLK_IPS]);
+	out_be32(mccr_reg, (0 << 16));
+	out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
+	out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
+
+	/*
+	 * create the 'struct clk' items of the MCLK's clock subtree
+	 *
+	 * note that by design we always create all nodes and won't take
+	 * shortcuts here, because
+	 * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are
+	 *   selectable inputs to the CFM while those who "actually use"
+	 *   the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK
+	 *   for their bitrate
+	 * - in the absence of "aliases" for clocks we need to create
+	 *   individial 'struct clk' items for whatever might get
+	 *   referenced or looked up, even if several of those items are
+	 *   identical from the logical POV (their rate value)
+	 * - for easier future maintenance and for better reflection of
+	 *   the SoC's documentation, it appears appropriate to generate
+	 *   clock items even for those muxers which actually are NOPs
+	 *   (those with two inputs of which one is reserved)
+	 */
+	clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed(
+			entry->name_mux0,
+			&parent_names_mux0[0], ARRAY_SIZE(parent_names_mux0),
+			mccr_reg, 14, 2);
+	clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated(
+			entry->name_en0, entry->name_mux0,
+			mccr_reg, 16);
+	clks[clks_idx_int + MCLK_IDX_DIV0] = mpc512x_clk_divider(
+			entry->name_div0,
+			entry->name_en0, CLK_SET_RATE_GATE,
+			mccr_reg, 17, 15, 0);
+	if (entry->has_mclk1) {
+		clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_muxed(
+				entry->name_mux1,
+				&entry->parent_names_mux1[0],
+				ARRAY_SIZE(entry->parent_names_mux1),
+				mccr_reg, 7, 1);
+	} else {
+		clks[clks_idx_int + MCLK_IDX_MUX1] = mpc512x_clk_factor(
+				entry->name_mux1, entry->parent_names_mux1[0],
+				1, 1);
+	}
+	if (sccr_reg) {
+		clks[clks_idx_pub] = mpc512x_clk_gated(
+				entry->name_mclk,
+				entry->name_mux1, sccr_reg, sccr_bit);
+	} else {
+		clks[clks_idx_pub] = mpc512x_clk_factor(
+				entry->name_mclk,
+				entry->name_mux1, 1, 1);
+	}
+
+	/*
+	 * without this "clock device" registration, "simple" lookups in
+	 * the SPI master initialization and serial port setup will fail
+	 *
+	 * those drivers need to get adjusted to lookup their required
+	 * clocks from device tree specs, and device tree nodes need to
+	 * provide the clock specs, before this clkdev registration
+	 * becomes obsolete
+	 */
+	clk_register_clkdev(clks[clks_idx_pub], entry->name_mclk, NULL);
+}
+
+static void mpc512x_clk_setup_mclks(struct mclk_setup_data *table, size_t count)
+{
+	while (count-- > 0)
+		mpc512x_clk_setup_mclk(table++);
+}
+
+static void mpc512x_clk_setup_clock_tree(int busfreq)
+{
+	int sys_mul, sys_div, ips_div;
+	int mul, div;
+	int freq;
+
+	/*
+	 * TODO
+	 * - consider whether to handle clocks which have both gates and
+	 *   dividers via intermediates or by means of composites
+	 * - fractional dividers appear to not map well to composites
+	 *   since they can be seen as a fixed multiplier and an
+	 *   adjustable divider, while composites can only combine at
+	 *   most one of a mux, div, and gate each into one 'struct clk'
+	 *   item
+	 * - PSC/MSCAN/SPDIF clock generation OTOH already is very
+	 *   specific and cannot get mapped to componsites (at least not
+	 *   a single one, maybe two of them, but see the comment about
+	 *   "intermediates are referenced from elsewhere, too")
+	 * - trim the list of auto-enabled clocks after drivers acquire
+	 *   them correctly as needed
+	 */
+
+	/* regardless of whether XTAL/OSC exists, have REF created */
+	mpc512x_clk_setup_ref_clock(busfreq, &sys_mul, &sys_div, &ips_div);
+
+	/* now setup the REF -> SYS -> CSB -> IPS hierarchy */
+	clks[MPC512x_CLK_SYS] = mpc512x_clk_factor("sys", "ref",
+						   sys_mul, sys_div);
+	clks[MPC512x_CLK_CSB] = mpc512x_clk_factor("csb", "sys", 1, 2);
+	clks[MPC512x_CLK_IPS] = mpc512x_clk_divtable("ips", "csb",
+						     &clkregs->scfr1, 23, 3,
+						     divtab_2346);
+
+	/* now setup anything below SYS and CSB and IPS */
+	clks[MPC512x_CLK_DDR_UG] = mpc512x_clk_factor("ddr-ug", "sys", 1, 2);
+	clks[MPC512x_CLK_SDHC_x4] = mpc512x_clk_factor("sdhc-x4", "csb", 4, 1);
+	clks[MPC512x_CLK_SDHC_UG] = mpc512x_clk_divider("sdhc-ug", "sdhc-x4", 0,
+							&clkregs->scfr2, 0, 8,
+							CLK_DIVIDER_ONE_BASED);
+	clks[MPC512x_CLK_DIU_x4] = mpc512x_clk_factor("diu-x4", "csb", 4, 1);
+	clks[MPC512x_CLK_DIU_UG] = mpc512x_clk_divider("diu-ug", "diu-x4", 0,
+						       &clkregs->scfr1, 0, 8,
+						       CLK_DIVIDER_ONE_BASED);
+
+	/*
+	 * the "power architecture PLL" was setup from data which was
+	 * sampled from the reset config word, at this point in time the
+	 * configuration can be considered fixed and read only (i.e. no
+	 * longer adjustable, or no longer in need of adjustment), which
+	 * is why we don't register a PLL here but assume fixed factors
+	 */
+	mul = get_cpmf_mult_x2();
+	div = 2;	/* compensate for the fractional factor */
+	clks[MPC512x_CLK_E300] = mpc512x_clk_factor("e300", "csb", mul, div);
+
+	clks[MPC512x_CLK_MBX_BUS_UG] = mpc512x_clk_factor("mbx-bus-ug", "csb",
+							  1, 2);
+	clks[MPC512x_CLK_MBX_UG] = mpc512x_clk_divtable("mbx-ug", "mbx-bus-ug",
+							&clkregs->scfr1, 14, 3,
+							divtab_1234);
+	clks[MPC512x_CLK_MBX_3D_UG] = mpc512x_clk_factor("mbx-3d-ug", "mbx-ug",
+							 1, 1);
+	clks[MPC512x_CLK_PCI_UG] = mpc512x_clk_divtable("pci-ug", "csb",
+							&clkregs->scfr1, 20, 3,
+							divtab_2346);
+	clks[MPC512x_CLK_NFC_UG] = mpc512x_clk_divtable("nfc-ug", "ips",
+							&clkregs->scfr1, 8, 3,
+							divtab_1234);
+	clks[MPC512x_CLK_LPC_UG] = mpc512x_clk_divtable("lpc-ug", "ips",
+							&clkregs->scfr1, 11, 3,
+							divtab_1234);
+
+	clks[MPC512x_CLK_LPC] = mpc512x_clk_gated("lpc", "lpc-ug",
+						  &clkregs->sccr1, 30);
+	clks[MPC512x_CLK_NFC] = mpc512x_clk_gated("nfc", "nfc-ug",
+						  &clkregs->sccr1, 29);
+	clks[MPC512x_CLK_PATA] = mpc512x_clk_gated("pata", "ips",
+						   &clkregs->sccr1, 28);
+	mpc512x_clk_setup_mclks(mclk_psc_data, ARRAY_SIZE(mclk_psc_data));
+	clks[MPC512x_CLK_PSC_FIFO] = mpc512x_clk_gated("psc-fifo", "ips",
+						       &clkregs->sccr1, 15);
+	clks[MPC512x_CLK_SATA] = mpc512x_clk_gated("sata", "ips",
+						   &clkregs->sccr1, 14);
+	clks[MPC512x_CLK_FEC] = mpc512x_clk_gated("fec", "ips",
+						  &clkregs->sccr1, 13);
+	clks[MPC512x_CLK_PCI] = mpc512x_clk_gated("pci", "pci-ug",
+						  &clkregs->sccr1, 11);
+	clks[MPC512x_CLK_DDR] = mpc512x_clk_gated("ddr", "ddr-ug",
+						  &clkregs->sccr1, 10);
+
+	clks[MPC512x_CLK_DIU] = mpc512x_clk_gated("diu", "diu-ug",
+						  &clkregs->sccr2, 31);
+	clks[MPC512x_CLK_AXE] = mpc512x_clk_gated("axe", "csb",
+						  &clkregs->sccr2, 30);
+	clks[MPC512x_CLK_MEM] = mpc512x_clk_gated("mem", "ips",
+						  &clkregs->sccr2, 29);
+	clks[MPC512x_CLK_USB1] = mpc512x_clk_gated("usb1", "csb",
+						   &clkregs->sccr2, 28);
+	clks[MPC512x_CLK_USB2] = mpc512x_clk_gated("usb2", "csb",
+						   &clkregs->sccr2, 27);
+	clks[MPC512x_CLK_I2C] = mpc512x_clk_gated("i2c", "ips",
+						  &clkregs->sccr2, 26);
+	mpc512x_clk_setup_mclks(mclk_mscan_data, ARRAY_SIZE(mclk_mscan_data));
+	clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug",
+						   &clkregs->sccr2, 24);
+	mpc512x_clk_setup_mclks(mclk_spdif_data, ARRAY_SIZE(mclk_spdif_data));
+	clks[MPC512x_CLK_MBX_BUS] = mpc512x_clk_gated("mbx-bus", "mbx-bus-ug",
+						      &clkregs->sccr2, 22);
+	clks[MPC512x_CLK_MBX] = mpc512x_clk_gated("mbx", "mbx-ug",
+						  &clkregs->sccr2, 21);
+	clks[MPC512x_CLK_MBX_3D] = mpc512x_clk_gated("mbx-3d", "mbx-3d-ug",
+						     &clkregs->sccr2, 20);
+	clks[MPC512x_CLK_IIM] = mpc512x_clk_gated("iim", "csb",
+						  &clkregs->sccr2, 19);
+	clks[MPC512x_CLK_VIU] = mpc512x_clk_gated("viu", "csb",
+						  &clkregs->sccr2, 18);
+	clks[MPC512x_CLK_SDHC_2] = mpc512x_clk_gated("sdhc-2", "sdhc-ug",
+						     &clkregs->sccr2, 17);
+
+	/*
+	 * externally provided clocks (when implemented in hardware,
+	 * device tree may specify values which otherwise were unknown)
+	 */
+	freq = get_freq_from_dt("psc_mclk_in");
+	if (!freq)
+		freq = 25000000;
+	clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
+	freq = get_freq_from_dt("spdif_tx_in");
+	clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq);
+	freq = get_freq_from_dt("spdif_rx_in");
+	clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq);
+
+	/* fixed frequency for AC97, always 24.567MHz */
+	clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
+
+	pr_debug("clock tree setup complete\n");
+	freq = clk_get_rate(clks[MPC512x_CLK_E300]);
+	pr_debug("derived PPC freq [%d]\n", freq);
+	freq = clk_get_rate(clks[MPC512x_CLK_IPS]);
+	pr_debug("derived IPS freq [%d]\n", freq);
+	freq = clk_get_rate(clks[MPC512x_CLK_LPC]);
+	pr_debug("derived LPC freq [%d]\n", freq);
+
+	/* enable some of the clocks here unconditionally because ... */
+	pr_debug("automatically enabling some clocks\n");
+	/* some are essential yet never get claimed by any driver */
+	clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
+	clk_prepare_enable(clks[MPC512x_CLK_E300]);	/* PowerPC CPU */
+	clk_prepare_enable(clks[MPC512x_CLK_DDR]);	/* DRAM */
+	clk_prepare_enable(clks[MPC512x_CLK_MEM]);	/* SRAM */
+	clk_prepare_enable(clks[MPC512x_CLK_IPS]);	/* SoC periph */
+	clk_prepare_enable(clks[MPC512x_CLK_LPC]);	/* boot media */
+	/* some are required yet no dependencies were declared */
+	clk_prepare_enable(clks[MPC512x_CLK_PSC_FIFO]);
+	/* some are not yet acquired by their respective drivers */
+	clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
+	clk_prepare_enable(clks[MPC512x_CLK_FEC]);	/* network, NFS */
+	clk_prepare_enable(clks[MPC512x_CLK_DIU]);	/* display */
+	clk_prepare_enable(clks[MPC512x_CLK_I2C]);
+	/*
+	 * some have their individual clock subtree with separate clock
+	 * items and their individual enable counters, yet share a
+	 * common gate (refer to the same register location) while the
+	 * common clock driver code is not aware of the fact and the
+	 * platform's code doesn't provide specific support either
+	 *
+	 * what might happen is that e.g. enabling two MSCAN clock items
+	 * and disabling one of them will disable the common gate and
+	 * thus break the other MSCAN clock as well
+	 */
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN0_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN1_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN2_MCLK]);
+	clk_prepare_enable(clks[MPC512x_CLK_MSCAN3_MCLK]);
+}
+
+/*
+ * registers the set of public clocks (those listed in the dt-bindings/
+ * header file) for OF lookups, keeps the intermediates private to us
+ */
+static void mpc5121_clk_register_of_provider(struct device_node *np)
+{
+	clk_data.clks = clks;
+	clk_data.clk_num = MPC512x_CLK_LAST_PUBLIC + 1;	/* _not_ ARRAY_SIZE() */
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+
+int __init mpc5121_clk_init(void)
+{
+	struct device_node *clk_np;
+	int busfreq;
+
+	/* map the clock control registers */
+	clk_np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+	if (!clk_np)
+		return -ENODEV;
+	clkregs = of_iomap(clk_np, 0);
+	WARN_ON(!clkregs);
+
+	/* invalidate all not yet registered clock slots */
+	mpc512x_clk_preset_data();
+
+	/*
+	 * have the device tree scanned for "fixed-clock" nodes (which
+	 * includes the oscillator node if the board's DT provides one)
+	 */
+	of_clk_init(NULL);
+
+	/*
+	 * add a dummy clock for those situations where a clock spec is
+	 * required yet no real clock is involved
+	 */
+	clks[MPC512x_CLK_DUMMY] = mpc512x_clk_fixed("dummy", 0);
+
+	/*
+	 * have all the real nodes in the clock tree populated from REF
+	 * down to all leaves, either starting from the OSC node or from
+	 * a REF root that was created from the IPS bus clock input
+	 */
+	busfreq = get_freq_from_dt("bus-frequency");
+	mpc512x_clk_setup_clock_tree(busfreq);
+
+	/* register as an OF clock provider */
+	mpc5121_clk_register_of_provider(clk_np);
+
+	return 0;
+}
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index c4f7799..7f8fc64 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -497,6 +497,20 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
  * for improved portability across platforms
  */
 
+#if IS_ENABLED(CONFIG_PPC)
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+	return ioread32be(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+	iowrite32be(val, reg);
+}
+
+#else	/* platform dependent I/O accessors */
+
 static inline u32 clk_readl(u32 __iomem *reg)
 {
 	return readl(reg);
@@ -507,5 +521,7 @@ static inline void clk_writel(u32 val, u32 __iomem *reg)
 	writel(val, reg);
 }
 
+#endif	/* platform dependent I/O accessors */
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
-- 
1.7.10.4

  parent reply	other threads:[~2013-07-18 17:00 UTC|newest]

Thread overview: 432+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-15 18:47 [PATCH v1 00/24] add COMMON_CLK support for PowerPC MPC512x Gerhard Sittig
2013-07-15 18:47 ` Gerhard Sittig
2013-07-15 18:47 ` [PATCH v1 02/24] serial: mpc512x: prepare clocks before enabling them Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
2013-07-15 18:47 ` [PATCH v1 03/24] mtd: mpc5121_nfc: " Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
2013-07-15 18:47 ` [PATCH v1 04/24] powerpc: mpc512x: array decl for MCLK registers in CCM Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
2013-07-15 18:47 ` [PATCH v1 06/24] dts: mpc512x: prepare for preprocessor support Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
2013-07-15 18:47 ` [PATCH v1 07/24] dts: mpc512x: introduce dt-bindings/clock/ header Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
2013-07-15 18:47 ` [PATCH v1 09/24] clk: mpc512x: introduce COMMON_CLK for MPC512x Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
2013-07-15 18:47 ` [PATCH v1 10/24] dts: mpc512x: add clock specs for client lookups Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
2013-07-15 18:47 ` [PATCH v1 13/24] spi: mpc512x: OF clock lookup, use the 'mclk' name Gerhard Sittig
2013-07-15 18:47   ` Gerhard Sittig
     [not found] ` <1373914074-20889-1-git-send-email-gsi-ynQEQJNshbs@public.gmane.org>
2013-07-15 18:47   ` [PATCH v1 01/24] spi: mpc512x: prepare clocks before enabling them Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
     [not found]     ` <1373914074-20889-2-git-send-email-gsi-ynQEQJNshbs@public.gmane.org>
2013-07-15 20:17       ` Mark Brown
2013-07-15 20:17         ` Mark Brown
2013-07-15 20:17         ` Mark Brown
     [not found]         ` <20130715201734.GF11538-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
2013-07-17 11:22           ` Gerhard Sittig
2013-07-17 11:22             ` Gerhard Sittig
2013-07-17 11:22             ` Gerhard Sittig
2013-07-17 12:07             ` Mark Brown
2013-07-17 12:07               ` Mark Brown
2013-07-17 12:07               ` Mark Brown
     [not found]               ` <20130717120758.GR22506-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
2013-07-17 14:26                 ` Gerhard Sittig
2013-07-17 14:26                   ` Gerhard Sittig
2013-07-17 14:26                   ` Gerhard Sittig
     [not found]                   ` <20130717142628.GN7080-kDjWylLy9wD0K7fsECOQyeGNnDKD8DIp@public.gmane.org>
2013-07-17 16:53                     ` Mark Brown
2013-07-17 16:53                       ` Mark Brown
2013-07-17 16:53                       ` Mark Brown
2013-07-15 18:47   ` [PATCH v1 05/24] clk: wrap I/O access for improved portability Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
2013-07-15 19:38     ` Sascha Hauer
2013-07-15 19:38       ` Sascha Hauer
2013-07-17 12:07       ` Gerhard Sittig
2013-07-17 12:07         ` Gerhard Sittig
2013-07-18  7:04       ` Gerhard Sittig
2013-07-18  7:04         ` Gerhard Sittig
2013-07-18  8:06         ` Sascha Hauer
2013-07-18  8:06           ` Sascha Hauer
     [not found]           ` <20130718080657.GI10380-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2013-07-18 10:08             ` Mark Brown
2013-07-18 10:08               ` Mark Brown
2013-07-18 10:08               ` Mark Brown
     [not found]         ` <20130718070402.GO7080-kDjWylLy9wD0K7fsECOQyeGNnDKD8DIp@public.gmane.org>
2013-07-18  9:17           ` Russell King - ARM Linux
2013-07-18  9:17             ` Russell King - ARM Linux
2013-07-18  9:17             ` Russell King - ARM Linux
2013-07-18 17:47             ` Nicolas Pitre
2013-07-18 17:47               ` Nicolas Pitre
2013-08-02 22:09               ` Mike Turquette
2013-08-02 22:09                 ` Mike Turquette
2013-08-02 22:09                 ` Mike Turquette
2013-07-15 18:47   ` [PATCH v1 08/24] dts: mpc512x: add clock related device tree specs Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
2013-07-15 18:47   ` [PATCH v1 11/24] net: can: mscan: add a comment on reg to idx mapping Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
2013-07-15 18:47   ` [PATCH v1 12/24] net: can: mscan: make mpc512x code use common clock Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
2013-07-15 18:47   ` [PATCH v1 14/24] powerpc/mpc512x: improve DIU related clock setup Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
2013-07-15 18:47     ` Gerhard Sittig
2013-07-15 21:46   ` [PATCH v1 15/24] serial: mpc512x: OF clock lookup, use the 'mclk' name Gerhard Sittig
2013-07-15 21:46     ` Gerhard Sittig
2013-07-15 21:46     ` Gerhard Sittig
2013-07-15 21:54     ` Sascha Hauer
2013-07-15 21:54       ` Sascha Hauer
     [not found]       ` <20130715215423.GU14452-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2013-07-17 11:27         ` Gerhard Sittig
2013-07-17 11:27           ` Gerhard Sittig
2013-07-17 11:27           ` Gerhard Sittig
2013-07-16  6:05   ` [PATCH v1 16/24] clk: mpc512x: remove now obsolete clkdev registration Gerhard Sittig
2013-07-16  6:05     ` Gerhard Sittig
2013-07-16  6:05     ` Gerhard Sittig
2013-07-16  8:45   ` [PATCH v1 21/24] [media] fsl-viu: OF clock lookup, prepare before enable Gerhard Sittig
2013-07-16  8:45     ` Gerhard Sittig
2013-07-16  8:45     ` Gerhard Sittig
2013-07-16  8:45   ` [PATCH v1 23/24] clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK Gerhard Sittig
2013-07-16  8:45     ` Gerhard Sittig
2013-07-16  8:45     ` Gerhard Sittig
2013-07-18 17:00   ` [PATCH v2 00/24] add COMMON_CLK support for PowerPC MPC512x Gerhard Sittig
2013-07-18 17:00     ` Gerhard Sittig
2013-07-18 17:00     ` Gerhard Sittig
     [not found]     ` <1374166855-7280-1-git-send-email-gsi-ynQEQJNshbs@public.gmane.org>
2013-07-18 17:00       ` [PATCH v2 01/24] spi: mpc512x: cleanup clock API use Gerhard Sittig
2013-07-18 17:00         ` Gerhard Sittig
2013-07-18 17:00         ` Gerhard Sittig
     [not found]         ` <1374166855-7280-2-git-send-email-gsi-ynQEQJNshbs@public.gmane.org>
2013-07-18 20:49           ` Mark Brown
2013-07-18 20:49             ` Mark Brown
2013-07-18 20:49             ` Mark Brown
2013-07-18 17:00       ` [PATCH v2 02/24] serial: " Gerhard Sittig
2013-07-18 17:00         ` Gerhard Sittig
2013-07-18 17:00         ` Gerhard Sittig
2013-07-18 17:00       ` [PATCH v2 07/24] dts: mpc512x: introduce dt-bindings/clock/ header Gerhard Sittig
2013-07-18 17:00         ` Gerhard Sittig
2013-07-18 17:00         ` Gerhard Sittig
2013-07-18 20:20       ` [PATCH v2 16/24] net: can: mscan: make mpc512x code use common clock Gerhard Sittig
2013-07-18 20:20         ` Gerhard Sittig
2013-07-18 20:20         ` Gerhard Sittig
2013-07-19  7:34         ` Marc Kleine-Budde
2013-07-19  7:34           ` Marc Kleine-Budde
2013-07-19  7:34           ` Marc Kleine-Budde
     [not found]           ` <51E8EC17.9060703-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2013-07-19  9:41             ` Gerhard Sittig
2013-07-19  9:41               ` Gerhard Sittig
2013-07-19  9:41               ` Gerhard Sittig
     [not found]               ` <20130719094143.GQ7080-kDjWylLy9wD0K7fsECOQyeGNnDKD8DIp@public.gmane.org>
2013-07-19 10:46                 ` Marc Kleine-Budde
2013-07-19 10:46                   ` Marc Kleine-Budde
2013-07-19 10:46                   ` Marc Kleine-Budde
2013-07-18 20:20       ` [PATCH v2 17/24] powerpc/mpc512x: improve DIU related clock setup Gerhard Sittig
2013-07-18 20:20         ` Gerhard Sittig
2013-07-18 20:20         ` Gerhard Sittig
2013-07-18 20:20       ` [PATCH v2 22/24] powerpc/fsl-pci: OF clock lookup, prepare before enable Gerhard Sittig
2013-07-18 20:20         ` Gerhard Sittig
2013-07-18 20:20         ` Gerhard Sittig
2013-07-18 20:20       ` [PATCH v2 23/24] clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK Gerhard Sittig
2013-07-18 20:20         ` Gerhard Sittig
2013-07-18 20:20         ` Gerhard Sittig
2013-07-18 17:00     ` [PATCH v2 03/24] mtd: mpc5121_nfc: prepare clocks before enabling them Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00     ` [PATCH v2 04/24] powerpc: mpc512x: array decl for MCLK registers in CCM Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00     ` [PATCH v2 05/24] clk: wrap I/O access for improved portability Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00     ` [PATCH v2 06/24] dts: mpc512x: prepare for preprocessor support Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00     ` [PATCH v2 08/24] dts: mpc512x: add clock related device tree specs Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00     ` Gerhard Sittig [this message]
2013-07-18 17:00       ` [PATCH v2 09/24] clk: mpc512x: introduce COMMON_CLK for MPC512x Gerhard Sittig
2013-07-18 17:00     ` [PATCH v2 10/24] dts: mpc512x: add clock specs for client lookups Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00     ` [PATCH v2 11/24] spi: mpc512x: remove now obsolete clock lookup name Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00     ` [PATCH v2 12/24] serial: " Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00     ` [PATCH v2 13/24] clk: mpc512x: remove now obsolete clkdev registration Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 17:00     ` [PATCH v2 14/24] serial: mpc512x: setup the PSC FIFO clock as well Gerhard Sittig
2013-07-18 17:00       ` Gerhard Sittig
2013-07-18 20:20     ` [PATCH v2 15/24] net: can: mscan: add a comment on reg to idx mapping Gerhard Sittig
2013-07-18 20:20       ` Gerhard Sittig
2013-07-18 20:20       ` Gerhard Sittig
2013-07-18 20:20     ` [PATCH v2 18/24] i2c: mpc: OF clock lookup for MPC512x Gerhard Sittig
2013-07-18 20:20       ` Gerhard Sittig
2013-07-18 20:20       ` Gerhard Sittig
2013-07-18 20:33       ` Russell King - ARM Linux
2013-07-18 20:33         ` Russell King - ARM Linux
     [not found]         ` <20130718203324.GB24642-l+eeeJia6m9vn6HldHNs0ANdhmdF6hFW@public.gmane.org>
2013-07-19  8:42           ` Gerhard Sittig
2013-07-19  8:42             ` Gerhard Sittig
2013-07-19  8:42             ` Gerhard Sittig
2013-07-18 20:20     ` [PATCH v2 19/24] USB: fsl-mph-dr-of: OF clock lookup, prepare and enable Gerhard Sittig
2013-07-18 20:20       ` Gerhard Sittig
2013-07-18 20:20     ` [PATCH v2 20/24] fs_enet: OF clock lookup (non-fatal), " Gerhard Sittig
2013-07-18 20:20       ` Gerhard Sittig
2013-07-18 20:20       ` Gerhard Sittig
2013-07-18 20:20     ` [PATCH v2 21/24] [media] fsl-viu: OF clock lookup, prepare before enable Gerhard Sittig
2013-07-18 20:20       ` Gerhard Sittig
2013-07-18 20:20       ` Gerhard Sittig
2013-07-18 20:20     ` [PATCH v2 24/24] net: can: mscan: remove MPC512x non-COMMON_CLK code path Gerhard Sittig
2013-07-18 20:20       ` Gerhard Sittig
2013-07-22 12:14     ` [PATCH v3 00/31] add COMMON_CLK support for PowerPC MPC512x Gerhard Sittig
2013-07-22 12:14       ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 01/31] spi: mpc512x: cleanup clock API use Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 14:09         ` Mark Brown
2013-07-22 14:09           ` Mark Brown
2013-07-22 14:09           ` Mark Brown
2013-07-23 11:58           ` Gerhard Sittig
2013-07-23 11:58             ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 02/31] serial: " Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 03/31] USB: fsl-mph-dr-of: " Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 04/31] mtd: mpc5121_nfc: " Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 05/31] [media] fsl-viu: " Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 06/31] i2c: mpc: " Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 07/31] fs_enet: silence a build warning (unused variable) Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 08/31] fs_enet: cleanup clock API use Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:28         ` Marc Kleine-Budde
2013-07-22 12:28           ` Marc Kleine-Budde
2013-07-22 12:28           ` Marc Kleine-Budde
2013-07-22 12:14       ` [PATCH v3 09/31] powerpc/fsl-pci: improve " Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 10/31] net: can: mscan: add a comment on reg to idx mapping Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 11/31] net: can: mscan: improve clock API use Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:31         ` Marc Kleine-Budde
2013-07-22 12:31           ` Marc Kleine-Budde
2013-07-22 12:31           ` Marc Kleine-Budde
2013-07-23 11:53           ` Gerhard Sittig
2013-07-23 11:53             ` Gerhard Sittig
2013-07-23 12:33             ` Marc Kleine-Budde
2013-07-23 12:33               ` Marc Kleine-Budde
2013-07-23 12:33               ` Marc Kleine-Budde
2013-08-03 17:07               ` Gerhard Sittig
2013-08-03 17:07                 ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 12/31] powerpc: mpc512x: array decl for MCLK registers in CCM Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 13/31] clk: wrap I/O access for improved portability Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-08-02 22:30         ` Mike Turquette
2013-08-02 22:30           ` Mike Turquette
2013-08-02 22:30           ` Mike Turquette
2013-08-03 14:08           ` Gerhard Sittig
2013-08-03 14:08             ` Gerhard Sittig
2013-08-23 22:05           ` Anatolij Gustschin
2013-08-23 22:05             ` Anatolij Gustschin
2013-08-28  0:55             ` Mike Turquette
2013-08-28  0:55               ` Mike Turquette
2013-07-22 12:14       ` [PATCH v3 14/31] dts: mpc512x: prepare for preprocessor support Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 15/31] dts: mpc512x: introduce dt-bindings/clock/ header Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-08-02 22:43         ` Mike Turquette
2013-08-02 22:43           ` Mike Turquette
2013-08-02 22:43           ` Mike Turquette
2013-08-03 14:19           ` Gerhard Sittig
2013-08-03 14:19             ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 16/31] dts: mpc512x: add clock related device tree specs Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-08-02 22:46         ` Mike Turquette
2013-08-02 22:46           ` Mike Turquette
2013-08-02 22:46           ` Mike Turquette
2013-07-22 12:14       ` [PATCH v3 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-23 13:14         ` Gerhard Sittig
2013-07-23 13:14           ` Gerhard Sittig
2013-08-02 23:30           ` Mike Turquette
2013-08-02 23:30             ` Mike Turquette
2013-08-03 14:39             ` Gerhard Sittig
2013-08-03 14:39               ` Gerhard Sittig
2013-08-05 17:11               ` Mike Turquette
2013-08-05 17:11                 ` Mike Turquette
2013-08-02 23:41         ` Mike Turquette
2013-08-02 23:41           ` Mike Turquette
2013-08-02 23:41           ` Mike Turquette
2013-08-03 15:03           ` Gerhard Sittig
2013-08-03 15:03             ` Gerhard Sittig
2013-08-05 11:37         ` Mark Rutland
2013-08-05 11:37           ` Mark Rutland
2013-08-05 11:37           ` Mark Rutland
2013-08-05 17:01           ` Gerhard Sittig
2013-08-05 17:01             ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 18/31] dts: mpc512x: add clock specs for client lookups Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-08-02 23:41         ` Mike Turquette
2013-08-02 23:41           ` Mike Turquette
2013-08-02 23:41           ` Mike Turquette
2013-08-03 15:36           ` Gerhard Sittig
2013-08-03 15:36             ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 19/31] clk: mpc512x: don't pre-enable FEC and I2C clocks Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 20/31] spi: mpc512x: remove now obsolete clock lookup name Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 21/31] serial: " Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 22/31] clk: mpc512x: remove clkdev registration (uart, spi) Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 23/31] serial: mpc512x: setup the PSC FIFO clock as well Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 24/31] USB: fsl-mph-dr-of: remove now obsolete clock lookup name Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 25/31] mtd: mpc5121_nfc: " Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 26/31] [media] fsl-viu: " Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 27/31] net: can: mscan: add common clock support for mpc512x Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 13:04         ` Marc Kleine-Budde
2013-07-22 13:04           ` Marc Kleine-Budde
2013-07-22 13:04           ` Marc Kleine-Budde
2013-07-23 12:07           ` Gerhard Sittig
2013-07-23 12:07             ` Gerhard Sittig
2013-07-23 12:37             ` Marc Kleine-Budde
2013-07-23 12:37               ` Marc Kleine-Budde
2013-07-22 12:14       ` [PATCH v3 28/31] powerpc/mpc512x: improve DIU related clock setup Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 29/31] clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 30/31] net: can: mscan: remove non-common_clock code for MPC512x Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:14       ` [PATCH v3 31/31] clk: mpc512x: remove clkdev registration (sys/ref, header) Gerhard Sittig
2013-07-22 12:14         ` Gerhard Sittig
2013-07-22 12:33       ` [PATCH v3 00/31] add COMMON_CLK support for PowerPC MPC512x Gerhard Sittig
2013-07-22 12:33         ` Gerhard Sittig
2013-08-06 20:43       ` [PATCH v4 " Gerhard Sittig
2013-08-06 20:43         ` Gerhard Sittig
2013-08-06 20:43         ` [PATCH v4 01/31] spi: mpc512x: cleanup clock API use Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-21 19:22           ` Anatolij Gustschin
2013-08-21 19:48             ` Mark Brown
2013-08-21 20:38               ` Anatolij Gustschin
2013-08-22 10:02           ` Mark Brown
2013-08-22 10:02             ` Mark Brown
2013-08-06 20:43         ` [PATCH v4 02/31] serial: " Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-12 18:27           ` Greg Kroah-Hartman
2013-08-12 18:27             ` Greg Kroah-Hartman
2013-08-21 19:52           ` Anatolij Gustschin
2013-08-06 20:43         ` [PATCH v4 03/31] USB: fsl-mph-dr-of: " Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-21 20:45           ` Anatolij Gustschin
2013-08-06 20:43         ` [PATCH v4 04/31] mtd: mpc5121_nfc: " Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-23 21:47           ` Anatolij Gustschin
2013-08-06 20:43         ` [PATCH v4 05/31] [media] fsl-viu: " Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-23 21:48           ` Anatolij Gustschin
2013-08-06 20:43         ` [PATCH v4 06/31] i2c: mpc: " Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-06 20:43         ` [PATCH v4 07/31] fs_enet: silence a build warning (unused variable) Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-06 20:43         ` [PATCH v4 08/31] fs_enet: cleanup clock API use Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-06 20:43         ` [PATCH v4 09/31] powerpc/fsl-pci: improve " Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-08 20:12           ` Anatolij Gustschin
2013-08-12  7:57             ` Gerhard Sittig
2013-08-28 12:08           ` Gerhard Sittig
2013-08-28 12:08             ` Gerhard Sittig
2013-08-28 15:59             ` Gerhard Sittig
2013-08-28 15:59               ` Gerhard Sittig
2013-08-28 22:10               ` Benjamin Herrenschmidt
2013-08-28 22:10                 ` Benjamin Herrenschmidt
2013-08-06 20:43         ` [PATCH v4 10/31] net: can: mscan: add a comment on reg to idx mapping Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-06 20:43         ` [PATCH v4 11/31] net: can: mscan: improve clock API use Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-07  7:28           ` Marc Kleine-Budde
2013-08-07  7:28             ` Marc Kleine-Budde
2013-08-08 19:50             ` Gerhard Sittig
2013-08-08 19:50               ` Gerhard Sittig
2013-08-07  7:30           ` Marc Kleine-Budde
2013-08-07  7:30             ` Marc Kleine-Budde
2013-08-07  7:35             ` Marc Kleine-Budde
2013-08-07  7:35               ` Marc Kleine-Budde
2013-08-06 20:43         ` [PATCH v4 12/31] powerpc: mpc512x: array decl for MCLK registers in CCM Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-23 21:49           ` Anatolij Gustschin
2013-08-06 20:43         ` [PATCH v4 13/31] clk: wrap I/O access for improved portability Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-06 20:43         ` [PATCH v4 14/31] dts: mpc512x: prepare for preprocessor support Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-23 22:18           ` Anatolij Gustschin
2013-08-06 20:43         ` [PATCH v4 15/31] dts: mpc512x: introduce dt-bindings/clock/ header Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-06 20:43         ` [PATCH v4 16/31] dts: mpc512x: add clock related device tree specs Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-06 20:43         ` [PATCH v4 17/31] clk: mpc512x: introduce COMMON_CLK for MPC512x Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-06 20:43         ` [PATCH v4 18/31] dts: mpc512x: add clock specs for client lookups Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-06 20:43         ` [PATCH v4 19/31] clk: mpc512x: don't pre-enable FEC and I2C clocks Gerhard Sittig
2013-08-06 20:43           ` Gerhard Sittig
2013-08-06 20:44         ` [PATCH v4 20/31] spi: mpc512x: switch to CCF names in clock lookup Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-06 20:44         ` [PATCH v4 21/31] serial: " Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-12 18:27           ` Greg Kroah-Hartman
2013-08-12 18:27             ` Greg Kroah-Hartman
2013-08-06 20:44         ` [PATCH v4 22/31] clk: mpc512x: remove PSC (UART, SPI) compat workarounds Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-06 20:44         ` [PATCH v4 23/31] serial: mpc512x: setup the PSC FIFO clock as well Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-12 18:27           ` Greg Kroah-Hartman
2013-08-12 18:27             ` Greg Kroah-Hartman
2013-08-06 20:44         ` [PATCH v4 24/31] USB: fsl-mph-dr-of: remove now obsolete clock lookup name Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-06 20:44         ` [PATCH v4 25/31] mtd: mpc5121_nfc: " Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-06 20:44         ` [PATCH v4 26/31] [media] fsl-viu: " Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-06 20:44         ` [PATCH v4 27/31] net: can: mscan: add common clock support for mpc512x Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-06 20:44         ` [PATCH v4 28/31] powerpc/mpc512x: improve DIU related clock setup Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-06 20:44         ` [PATCH v4 29/31] clk: mpc512x: switch to COMMON_CLK, remove PPC_CLOCK Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-06 20:44         ` [PATCH v4 30/31] net: can: mscan: remove non-CCF code for MPC512x Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-06 20:44         ` [PATCH v4 31/31] clk: mpc512x: remove remaining migration workarounds Gerhard Sittig
2013-08-06 20:44           ` Gerhard Sittig
2013-08-06 21:31         ` [PATCH v4 00/31] add COMMON_CLK support for PowerPC MPC512x Gerhard Sittig
2013-08-06 21:31           ` Gerhard Sittig
2013-08-07  7:36           ` Gerhard Sittig
2013-08-07  7:36             ` Gerhard Sittig
2013-08-07 15:40         ` Kumar Gala
2013-08-07 15:40           ` Kumar Gala
2013-08-08 18:41           ` Gerhard Sittig
2013-08-08 18:41             ` Gerhard Sittig
2013-08-28 13:50         ` Gerhard Sittig
2013-08-28 13:50           ` Gerhard Sittig
2013-07-16  6:05 ` [PATCH v1 17/24] serial: mpc512x: setup the PSC FIFO clock as well Gerhard Sittig
2013-07-16  6:05   ` Gerhard Sittig
2013-07-16  6:05 ` [PATCH v1 18/24] i2c: mpc: OF clock lookup for MPC512x Gerhard Sittig
2013-07-16  6:05   ` Gerhard Sittig
2013-07-16  6:05   ` Gerhard Sittig
2013-07-16  6:05 ` [PATCH v1 19/24] USB: fsl-mph-dr-of: OF clock lookup, prepare and enable Gerhard Sittig
2013-07-16  6:05   ` Gerhard Sittig
2013-07-16  6:05   ` Gerhard Sittig
2013-07-16  6:05 ` [PATCH v1 20/24] fs_enet: OF clock lookup (non-fatal), " Gerhard Sittig
2013-07-16  6:05   ` Gerhard Sittig
2013-07-16  6:05   ` Gerhard Sittig
2013-07-16  8:45 ` [PATCH v1 22/24] powerpc/fsl-pci: OF clock lookup, prepare before enable Gerhard Sittig
2013-07-16  8:45   ` Gerhard Sittig
2013-07-16  8:45 ` [PATCH v1 24/24] net: can: mscan: remove MPC512x non-COMMON_CLK code path Gerhard Sittig
2013-07-16  8:45   ` Gerhard Sittig
2013-07-16  8:45   ` Gerhard Sittig

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1374166855-7280-10-git-send-email-gsi@denx.de \
    --to=gsi@denx.de \
    --cc=agust@denx.de \
    --cc=broonie@kernel.org \
    --cc=devicetree-discuss@lists.ozlabs.org \
    --cc=dwmw2@infradead.org \
    --cc=dzu@denx.de \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=m.chehab@samsung.com \
    --cc=mkl@pengutronix.de \
    --cc=mturquette@linaro.org \
    --cc=rob.herring@calxeda.com \
    --cc=wg@grandegger.com \
    --cc=wsa@the-dreams.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.