Merge tag 'clk-for-linus' of git://git.linaro.org/people/mturquette/linux

Pull common clk framework changes from Michael Turquette:
 "This includes a small number of core framework improvments, platform
  ports and new DT bindings."

Fix up trivial conflicts in drivers/clk/Makefile

* tag 'clk-for-linus' of git://git.linaro.org/people/mturquette/linux: (21 commits)
  clk: fix compile for OF && !COMMON_CLK
  clk: fix clk_get on of_clk_get_by_name return check
  clk: mxs: clk_register_clkdev mx28 usb clocks
  clk: add highbank clock support
  dt: add clock binding doc to primecell bindings
  clk: add DT fixed-clock binding support
  clk: add DT clock binding support
  ARM: integrator: convert to common clock
  clk: add versatile ICST307 driver
  ARM: integrator: put symbolic bus names on devices
  ARM: u300: convert to common clock
  clk: cache parent clocks only for muxes
  clk: wm831x: Add initial WM831x clock driver
  clk: Constify struct clk_init_data
  clk: Add CLK_IS_BASIC flag to identify basic clocks
  clk: Add support for rate table based dividers
  clk: Add support for power of two type dividers
  clk: mxs: imx28: decrease the frequency of ref_io1 for SSP2 and SSP3
  clk: mxs: add clkdev lookup for pwm
  clk: mxs: Fix the GPMI clock name
  ...
diff --git a/Documentation/devicetree/bindings/arm/primecell.txt b/Documentation/devicetree/bindings/arm/primecell.txt
index 951ca46..64fc82b 100644
--- a/Documentation/devicetree/bindings/arm/primecell.txt
+++ b/Documentation/devicetree/bindings/arm/primecell.txt
@@ -13,11 +13,17 @@
 Optional properties:
 
 - arm,primecell-periphid : Value to override the h/w value with
+- clocks : From common clock binding. First clock is phandle to clock for apb
+	pclk. Additional clocks are optional and specific to those peripherals.
+- clock-names : From common clock binding. Shall be "apb_pclk" for first clock.
 
 Example:
 
 serial@fff36000 {
 	compatible = "arm,pl011", "arm,primecell";
 	arm,primecell-periphid = <0x00341011>;
+	clocks = <&pclk>;
+	clock-names = "apb_pclk";
+	
 };
 
diff --git a/Documentation/devicetree/bindings/clock/calxeda.txt b/Documentation/devicetree/bindings/clock/calxeda.txt
new file mode 100644
index 0000000..0a6ac1b
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/calxeda.txt
@@ -0,0 +1,17 @@
+Device Tree Clock bindings for Calxeda highbank platform
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be one of the following:
+	"calxeda,hb-pll-clock" - for a PLL clock
+	"calxeda,hb-a9periph-clock" - The A9 peripheral clock divided from the
+		A9 clock.
+	"calxeda,hb-a9bus-clock" - The A9 bus clock divided from the A9 clock.
+	"calxeda,hb-emmc-clock" - Divided clock for MMC/SD controller.
+- reg : shall be the control register offset from SYSREGs base for the clock.
+- clocks : shall be the input parent clock phandle for the clock. This is
+	either an oscillator or a pll output.
+- #clock-cells : from common clock binding; shall be set to 0.
diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
new file mode 100644
index 0000000..eb65d41
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
@@ -0,0 +1,117 @@
+This binding is a work-in-progress, and are based on some experimental
+work by benh[1].
+
+Sources of clock signal can be represented by any node in the device
+tree.  Those nodes are designated as clock providers.  Clock consumer
+nodes use a phandle and clock specifier pair to connect clock provider
+outputs to clock inputs.  Similar to the gpio specifiers, a clock
+specifier is an array of one more more cells identifying the clock
+output on a device.  The length of a clock specifier is defined by the
+value of a #clock-cells property in the clock provider node.
+
+[1] http://patchwork.ozlabs.org/patch/31551/
+
+==Clock providers==
+
+Required properties:
+#clock-cells:	   Number of cells in a clock specifier; Typically 0 for nodes
+		   with a single clock output and 1 for nodes with multiple
+		   clock outputs.
+
+Optional properties:
+clock-output-names: Recommended to be a list of strings of clock output signal
+		    names indexed by the first cell in the clock specifier.
+		    However, the meaning of clock-output-names is domain
+		    specific to the clock provider, and is only provided to
+		    encourage using the same meaning for the majority of clock
+		    providers.  This format may not work for clock providers
+		    using a complex clock specifier format.  In those cases it
+		    is recommended to omit this property and create a binding
+		    specific names property.
+
+		    Clock consumer nodes must never directly reference
+		    the provider's clock-output-names property.
+
+For example:
+
+    oscillator {
+        #clock-cells = <1>;
+        clock-output-names = "ckil", "ckih";
+    };
+
+- this node defines a device with two clock outputs, the first named
+  "ckil" and the second named "ckih".  Consumer nodes always reference
+  clocks by index. The names should reflect the clock output signal
+  names for the device.
+
+==Clock consumers==
+
+Required properties:
+clocks:		List of phandle and clock specifier pairs, one pair
+		for each clock input to the device.  Note: if the
+		clock provider specifies '0' for #clock-cells, then
+		only the phandle portion of the pair will appear.
+
+Optional properties:
+clock-names:	List of clock input name strings sorted in the same
+		order as the clocks property.  Consumers drivers
+		will use clock-names to match clock input names
+		with clocks specifiers.
+clock-ranges:	Empty property indicating that child nodes can inherit named
+		clocks from this node. Useful for bus nodes to provide a
+		clock to their children.
+
+For example:
+
+    device {
+        clocks = <&osc 1>, <&ref 0>;
+        clock-names = "baud", "register";
+    };
+
+
+This represents a device with two clock inputs, named "baud" and "register".
+The baud clock is connected to output 1 of the &osc device, and the register
+clock is connected to output 0 of the &ref.
+
+==Example==
+
+    /* external oscillator */
+    osc: oscillator {
+        compatible = "fixed-clock";
+        #clock-cells = <1>;
+        clock-frequency  = <32678>;
+        clock-output-names = "osc";
+    };
+
+    /* phase-locked-loop device, generates a higher frequency clock
+     * from the external oscillator reference */
+    pll: pll@4c000 {
+        compatible = "vendor,some-pll-interface"
+        #clock-cells = <1>;
+        clocks = <&osc 0>;
+        clock-names = "ref";
+        reg = <0x4c000 0x1000>;
+        clock-output-names = "pll", "pll-switched";
+    };
+
+    /* UART, using the low frequency oscillator for the baud clock,
+     * and the high frequency switched PLL output for register
+     * clocking */
+    uart@a000 {
+        compatible = "fsl,imx-uart";
+        reg = <0xa000 0x1000>;
+        interrupts = <33>;
+        clocks = <&osc 0>, <&pll 1>;
+        clock-names = "baud", "register";
+    };
+
+This DT fragment defines three devices: an external oscillator to provide a
+low-frequency reference clock, a PLL device to generate a higher frequency
+clock signal, and a UART.
+
+* The oscillator is fixed-frequency, and provides one clock output, named "osc".
+* The PLL is both a clock provider and a clock consumer. It uses the clock
+  signal generated by the external oscillator, and provides two output signals
+  ("pll" and "pll-switched").
+* The UART has its baud clock connected the external oscillator and its
+  register clock connected to the PLL clock (the "pll-switched" signal)
diff --git a/Documentation/devicetree/bindings/clock/fixed-clock.txt b/Documentation/devicetree/bindings/clock/fixed-clock.txt
new file mode 100644
index 0000000..0b1fe78
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/fixed-clock.txt
@@ -0,0 +1,21 @@
+Binding for simple fixed-rate clock sources.
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be "fixed-clock".
+- #clock-cells : from common clock binding; shall be set to 0.
+- clock-frequency : frequency of clock in Hz. Should be a single cell.
+
+Optional properties:
+- gpios : From common gpio binding; gpio connection to clock enable pin.
+- clock-output-names : From common clock binding.
+
+Example:
+	clock {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <1000000000>;
+	};
diff --git a/MAINTAINERS b/MAINTAINERS
index cd8a3f6..9b8a5da 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7605,6 +7605,7 @@
 S:	Supported
 F:	Documentation/hwmon/wm83??
 F:	arch/arm/mach-s3c64xx/mach-crag6410*
+F:	drivers/clk/clk-wm83*.c
 F:	drivers/leds/leds-wm83*.c
 F:	drivers/hwmon/wm83??-hwmon.c
 F:	drivers/input/misc/wm831x-on.c
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index c7e6d20..b25c9d3 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -273,8 +273,8 @@
 	bool "ARM Ltd. Integrator family"
 	select ARM_AMBA
 	select ARCH_HAS_CPUFREQ
-	select CLKDEV_LOOKUP
-	select HAVE_MACH_CLKDEV
+	select COMMON_CLK
+	select CLK_VERSATILE
 	select HAVE_TCM
 	select ICST
 	select GENERIC_CLOCKEVENTS
@@ -336,6 +336,7 @@
 	select ICST
 	select NO_IOPORT
 	select PLAT_VERSATILE
+	select PLAT_VERSATILE_CLOCK
 	select PLAT_VERSATILE_CLCD
 	select REGULATOR_FIXED_VOLTAGE if REGULATOR
 	help
@@ -372,6 +373,7 @@
 	select ARM_TIMER_SP804
 	select CACHE_L2X0
 	select CLKDEV_LOOKUP
+	select COMMON_CLK
 	select CPU_V7
 	select GENERIC_CLOCKEVENTS
 	select HAVE_ARM_SCU
@@ -929,7 +931,7 @@
 	select ARM_VIC
 	select GENERIC_CLOCKEVENTS
 	select CLKDEV_LOOKUP
-	select HAVE_MACH_CLKDEV
+	select COMMON_CLK
 	select GENERIC_GPIO
 	select ARCH_REQUIRE_GPIOLIB
 	help
diff --git a/arch/arm/boot/dts/highbank.dts b/arch/arm/boot/dts/highbank.dts
index 83e7229..2e1cfa0 100644
--- a/arch/arm/boot/dts/highbank.dts
+++ b/arch/arm/boot/dts/highbank.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011 Calxeda, Inc.
+ * Copyright 2011-2012 Calxeda, Inc.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -24,6 +24,7 @@
 	compatible = "calxeda,highbank";
 	#address-cells = <1>;
 	#size-cells = <1>;
+	clock-ranges;
 
 	cpus {
 		#address-cells = <1>;
@@ -33,24 +34,32 @@
 			compatible = "arm,cortex-a9";
 			reg = <0>;
 			next-level-cache = <&L2>;
+			clocks = <&a9pll>;
+			clock-names = "cpu";
 		};
 
 		cpu@1 {
 			compatible = "arm,cortex-a9";
 			reg = <1>;
 			next-level-cache = <&L2>;
+			clocks = <&a9pll>;
+			clock-names = "cpu";
 		};
 
 		cpu@2 {
 			compatible = "arm,cortex-a9";
 			reg = <2>;
 			next-level-cache = <&L2>;
+			clocks = <&a9pll>;
+			clock-names = "cpu";
 		};
 
 		cpu@3 {
 			compatible = "arm,cortex-a9";
 			reg = <3>;
 			next-level-cache = <&L2>;
+			clocks = <&a9pll>;
+			clock-names = "cpu";
 		};
 	};
 
@@ -75,12 +84,14 @@
 			compatible = "arm,cortex-a9-twd-timer";
 			reg = <0xfff10600 0x20>;
 			interrupts = <1 13 0xf01>;
+			clocks = <&a9periphclk>;
 		};
 
 		watchdog@fff10620 {
 			compatible = "arm,cortex-a9-twd-wdt";
 			reg = <0xfff10620 0x20>;
 			interrupts = <1 14 0xf01>;
+			clocks = <&a9periphclk>;
 		};
 
 		intc: interrupt-controller@fff11000 {
@@ -116,12 +127,15 @@
 			compatible = "calxeda,hb-sdhci";
 			reg = <0xffe0e000 0x1000>;
 			interrupts = <0 90 4>;
+			clocks = <&eclk>;
 		};
 
 		ipc@fff20000 {
 			compatible = "arm,pl320", "arm,primecell";
 			reg = <0xfff20000 0x1000>;
 			interrupts = <0 7 4>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		gpioe: gpio@fff30000 {
@@ -130,6 +144,8 @@
 			gpio-controller;
 			reg = <0xfff30000 0x1000>;
 			interrupts = <0 14 4>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		gpiof: gpio@fff31000 {
@@ -138,6 +154,8 @@
 			gpio-controller;
 			reg = <0xfff31000 0x1000>;
 			interrupts = <0 15 4>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		gpiog: gpio@fff32000 {
@@ -146,6 +164,8 @@
 			gpio-controller;
 			reg = <0xfff32000 0x1000>;
 			interrupts = <0 16 4>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		gpioh: gpio@fff33000 {
@@ -154,24 +174,32 @@
 			gpio-controller;
 			reg = <0xfff33000 0x1000>;
 			interrupts = <0 17 4>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		timer {
 			compatible = "arm,sp804", "arm,primecell";
 			reg = <0xfff34000 0x1000>;
 			interrupts = <0 18 4>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		rtc@fff35000 {
 			compatible = "arm,pl031", "arm,primecell";
 			reg = <0xfff35000 0x1000>;
 			interrupts = <0 19 4>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		serial@fff36000 {
 			compatible = "arm,pl011", "arm,primecell";
 			reg = <0xfff36000 0x1000>;
 			interrupts = <0 20 4>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		smic@fff3a000 {
@@ -186,12 +214,73 @@
 		sregs@fff3c000 {
 			compatible = "calxeda,hb-sregs";
 			reg = <0xfff3c000 0x1000>;
+
+			clocks {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				osc: oscillator {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+					clock-frequency = <33333000>;
+				};
+
+				ddrpll: ddrpll {
+					#clock-cells = <0>;
+					compatible = "calxeda,hb-pll-clock";
+					clocks = <&osc>;
+					reg = <0x108>;
+				};
+
+				a9pll: a9pll {
+					#clock-cells = <0>;
+					compatible = "calxeda,hb-pll-clock";
+					clocks = <&osc>;
+					reg = <0x100>;
+				};
+
+				a9periphclk: a9periphclk {
+					#clock-cells = <0>;
+					compatible = "calxeda,hb-a9periph-clock";
+					clocks = <&a9pll>;
+					reg = <0x104>;
+				};
+
+				a9bclk: a9bclk {
+					#clock-cells = <0>;
+					compatible = "calxeda,hb-a9bus-clock";
+					clocks = <&a9pll>;
+					reg = <0x104>;
+				};
+
+				emmcpll: emmcpll {
+					#clock-cells = <0>;
+					compatible = "calxeda,hb-pll-clock";
+					clocks = <&osc>;
+					reg = <0x10C>;
+				};
+
+				eclk: eclk {
+					#clock-cells = <0>;
+					compatible = "calxeda,hb-emmc-clock";
+					clocks = <&emmcpll>;
+					reg = <0x114>;
+				};
+
+				pclk: pclk {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+					clock-frequency = <150000000>;
+				};
+			};
 		};
 
 		dma@fff3d000 {
 			compatible = "arm,pl330", "arm,primecell";
 			reg = <0xfff3d000 0x1000>;
 			interrupts = <0 92 4>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
 		};
 
 		ethernet@fff50000 {
diff --git a/arch/arm/mach-highbank/Makefile b/arch/arm/mach-highbank/Makefile
index ded4652..3ec8bdd 100644
--- a/arch/arm/mach-highbank/Makefile
+++ b/arch/arm/mach-highbank/Makefile
@@ -1,4 +1,4 @@
-obj-y					:= clock.o highbank.o system.o smc.o
+obj-y					:= highbank.o system.o smc.o
 
 plus_sec := $(call as-instr,.arch_extension sec,+sec)
 AFLAGS_smc.o				:=-Wa,-march=armv7-a$(plus_sec)
diff --git a/arch/arm/mach-highbank/clock.c b/arch/arm/mach-highbank/clock.c
deleted file mode 100644
index c25a2ae..0000000
--- a/arch/arm/mach-highbank/clock.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2011 Calxeda, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/clk.h>
-#include <linux/clkdev.h>
-
-struct clk {
-	unsigned long rate;
-};
-
-int clk_enable(struct clk *clk)
-{
-	return 0;
-}
-
-void clk_disable(struct clk *clk)
-{}
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-	return clk->rate;
-}
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	return clk->rate;
-}
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	return 0;
-}
-
-static struct clk eclk = { .rate = 200000000 };
-static struct clk pclk = { .rate = 150000000 };
-
-static struct clk_lookup lookups[] = {
-	{ .clk = &pclk, .con_id = "apb_pclk", },
-	{ .clk = &pclk, .dev_id = "sp804", },
-	{ .clk = &eclk, .dev_id = "ffe0e000.sdhci", },
-	{ .clk = &pclk, .dev_id = "fff36000.serial", },
-};
-
-void __init highbank_clocks_init(void)
-{
-	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-}
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c
index 8777612..d75b0a7 100644
--- a/arch/arm/mach-highbank/highbank.c
+++ b/arch/arm/mach-highbank/highbank.c
@@ -105,6 +105,11 @@
 #endif
 }
 
+static struct clk_lookup lookup = {
+	.dev_id = "sp804",
+	.con_id = NULL,
+};
+
 static void __init highbank_timer_init(void)
 {
 	int irq;
@@ -122,6 +127,8 @@
 	irq = irq_of_parse_and_map(np, 0);
 
 	highbank_clocks_init();
+	lookup.clk = of_clk_get(np, 0);
+	clkdev_add(&lookup);
 
 	sp804_clocksource_and_sched_clock_init(timer_base + 0x20, "timer1");
 	sp804_clockevents_init(timer_base, irq, "timer0");
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c
index eaf6c63..ebf680b 100644
--- a/arch/arm/mach-integrator/core.c
+++ b/arch/arm/mach-integrator/core.c
@@ -21,7 +21,6 @@
 #include <linux/amba/bus.h>
 #include <linux/amba/serial.h>
 #include <linux/io.h>
-#include <linux/clkdev.h>
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
@@ -41,17 +40,17 @@
 #define KMI0_IRQ		{ IRQ_KMIINT0 }
 #define KMI1_IRQ		{ IRQ_KMIINT1 }
 
-static AMBA_APB_DEVICE(rtc, "mb:15", 0,
+static AMBA_APB_DEVICE(rtc, "rtc", 0,
 	INTEGRATOR_RTC_BASE, INTEGRATOR_RTC_IRQ, NULL);
 
-static AMBA_APB_DEVICE(uart0, "mb:16", 0,
+static AMBA_APB_DEVICE(uart0, "uart0", 0,
 	INTEGRATOR_UART0_BASE, INTEGRATOR_UART0_IRQ, &integrator_uart_data);
 
-static AMBA_APB_DEVICE(uart1, "mb:17", 0,
+static AMBA_APB_DEVICE(uart1, "uart1", 0,
 	INTEGRATOR_UART1_BASE, INTEGRATOR_UART1_IRQ, &integrator_uart_data);
 
-static AMBA_APB_DEVICE(kmi0, "mb:18", 0, KMI0_BASE, KMI0_IRQ, NULL);
-static AMBA_APB_DEVICE(kmi1, "mb:19", 0, KMI1_BASE, KMI1_IRQ, NULL);
+static AMBA_APB_DEVICE(kmi0, "kmi0", 0, KMI0_BASE, KMI0_IRQ, NULL);
+static AMBA_APB_DEVICE(kmi1, "kmi1", 0, KMI1_BASE, KMI1_IRQ, NULL);
 
 static struct amba_device *amba_devs[] __initdata = {
 	&rtc_device,
@@ -61,50 +60,6 @@
 	&kmi1_device,
 };
 
-/*
- * These are fixed clocks.
- */
-static struct clk clk24mhz = {
-	.rate	= 24000000,
-};
-
-static struct clk uartclk = {
-	.rate	= 14745600,
-};
-
-static struct clk dummy_apb_pclk;
-
-static struct clk_lookup lookups[] = {
-	{	/* Bus clock */
-		.con_id		= "apb_pclk",
-		.clk		= &dummy_apb_pclk,
-	}, {
-		/* Integrator/AP timer frequency */
-		.dev_id		= "ap_timer",
-		.clk		= &clk24mhz,
-	}, {	/* UART0 */
-		.dev_id		= "mb:16",
-		.clk		= &uartclk,
-	}, {	/* UART1 */
-		.dev_id		= "mb:17",
-		.clk		= &uartclk,
-	}, {	/* KMI0 */
-		.dev_id		= "mb:18",
-		.clk		= &clk24mhz,
-	}, {	/* KMI1 */
-		.dev_id		= "mb:19",
-		.clk		= &clk24mhz,
-	}, {	/* MMCI - IntegratorCP */
-		.dev_id		= "mb:1c",
-		.clk		= &uartclk,
-	}
-};
-
-void __init integrator_init_early(void)
-{
-	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-}
-
 static int __init integrator_init(void)
 {
 	int i;
diff --git a/arch/arm/mach-integrator/include/mach/clkdev.h b/arch/arm/mach-integrator/include/mach/clkdev.h
deleted file mode 100644
index bfe0767..0000000
--- a/arch/arm/mach-integrator/include/mach/clkdev.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#include <linux/module.h>
-#include <plat/clock.h>
-
-struct clk {
-	unsigned long		rate;
-	const struct clk_ops	*ops;
-	struct module		*owner;
-	const struct icst_params *params;
-	void __iomem		*vcoreg;
-	void			*data;
-};
-
-static inline int __clk_get(struct clk *clk)
-{
-	return try_module_get(clk->owner);
-}
-
-static inline void __clk_put(struct clk *clk)
-{
-	module_put(clk->owner);
-}
-
-#endif
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index c857501..7b1055c 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -33,6 +33,7 @@
 #include <linux/io.h>
 #include <linux/mtd/physmap.h>
 #include <linux/clk.h>
+#include <linux/platform_data/clk-integrator.h>
 #include <video/vga.h>
 
 #include <mach/hardware.h>
@@ -174,6 +175,7 @@
 
 	fpga_irq_init(VA_IC_BASE, "SC", IRQ_PIC_START,
 		-1, INTEGRATOR_SC_VALID_INT, NULL);
+	integrator_clk_init(false);
 }
 
 #ifdef CONFIG_PM
@@ -440,6 +442,10 @@
 					0xffffU);
 }
 
+void __init ap_init_early(void)
+{
+}
+
 /*
  * Set up timer(s).
  */
@@ -471,7 +477,7 @@
 	.reserve	= integrator_reserve,
 	.map_io		= ap_map_io,
 	.nr_irqs	= NR_IRQS_INTEGRATOR_AP,
-	.init_early	= integrator_init_early,
+	.init_early	= ap_init_early,
 	.init_irq	= ap_init_irq,
 	.handle_irq	= fpga_handle_irq,
 	.timer		= &ap_timer,
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index a56c536..82d5c83 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -21,8 +21,8 @@
 #include <linux/amba/mmci.h>
 #include <linux/io.h>
 #include <linux/gfp.h>
-#include <linux/clkdev.h>
 #include <linux/mtd/physmap.h>
+#include <linux/platform_data/clk-integrator.h>
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
@@ -171,65 +171,10 @@
 
 	fpga_irq_init(INTCP_VA_SIC_BASE, "SIC", IRQ_SIC_START,
 		      IRQ_CP_CPPLDINT, sic_mask, NULL);
+	integrator_clk_init(true);
 }
 
 /*
- * Clock handling
- */
-#define CM_LOCK		(__io_address(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET)
-#define CM_AUXOSC	(__io_address(INTEGRATOR_HDR_BASE)+0x1c)
-
-static const struct icst_params cp_auxvco_params = {
-	.ref		= 24000000,
-	.vco_max	= ICST525_VCO_MAX_5V,
-	.vco_min	= ICST525_VCO_MIN,
-	.vd_min 	= 8,
-	.vd_max 	= 263,
-	.rd_min 	= 3,
-	.rd_max 	= 65,
-	.s2div		= icst525_s2div,
-	.idx2s		= icst525_idx2s,
-};
-
-static void cp_auxvco_set(struct clk *clk, struct icst_vco vco)
-{
-	u32 val;
-
-	val = readl(clk->vcoreg) & ~0x7ffff;
-	val |= vco.v | (vco.r << 9) | (vco.s << 16);
-
-	writel(0xa05f, CM_LOCK);
-	writel(val, clk->vcoreg);
-	writel(0, CM_LOCK);
-}
-
-static const struct clk_ops cp_auxclk_ops = {
-	.round	= icst_clk_round,
-	.set	= icst_clk_set,
-	.setvco	= cp_auxvco_set,
-};
-
-static struct clk cp_auxclk = {
-	.ops	= &cp_auxclk_ops,
-	.params	= &cp_auxvco_params,
-	.vcoreg	= CM_AUXOSC,
-};
-
-static struct clk sp804_clk = {
-	.rate	= 1000000,
-};
-
-static struct clk_lookup cp_lookups[] = {
-	{	/* CLCD */
-		.dev_id		= "mb:c0",
-		.clk		= &cp_auxclk,
-	}, {	/* SP804 timers */
-		.dev_id		= "sp804",
-		.clk		= &sp804_clk,
-	},
-};
-
-/*
  * Flash handling.
  */
 static int intcp_flash_init(struct platform_device *dev)
@@ -336,10 +281,10 @@
 #define INTEGRATOR_CP_MMC_IRQS	{ IRQ_CP_MMCIINT0, IRQ_CP_MMCIINT1 }
 #define INTEGRATOR_CP_AACI_IRQS	{ IRQ_CP_AACIINT }
 
-static AMBA_APB_DEVICE(mmc, "mb:1c", 0, INTEGRATOR_CP_MMC_BASE,
+static AMBA_APB_DEVICE(mmc, "mmci", 0, INTEGRATOR_CP_MMC_BASE,
 	INTEGRATOR_CP_MMC_IRQS, &mmc_data);
 
-static AMBA_APB_DEVICE(aaci, "mb:1d", 0, INTEGRATOR_CP_AACI_BASE,
+static AMBA_APB_DEVICE(aaci, "aaci", 0, INTEGRATOR_CP_AACI_BASE,
 	INTEGRATOR_CP_AACI_IRQS, NULL);
 
 
@@ -393,7 +338,7 @@
 	.remove		= versatile_clcd_remove_dma,
 };
 
-static AMBA_AHB_DEVICE(clcd, "mb:c0", 0, INTCP_PA_CLCD_BASE,
+static AMBA_AHB_DEVICE(clcd, "clcd", 0, INTCP_PA_CLCD_BASE,
 	{ IRQ_CP_CLCDCINT }, &clcd_data);
 
 static struct amba_device *amba_devs[] __initdata = {
@@ -406,10 +351,6 @@
 
 static void __init intcp_init_early(void)
 {
-	clkdev_add_table(cp_lookups, ARRAY_SIZE(cp_lookups));
-
-	integrator_init_early();
-
 #ifdef CONFIG_PLAT_VERSATILE_SCHED_CLOCK
 	versatile_sched_clock_init(REFCOUNTER, 24000000);
 #endif
diff --git a/arch/arm/mach-u300/Makefile b/arch/arm/mach-u300/Makefile
index fd3a5c3..7e47d37 100644
--- a/arch/arm/mach-u300/Makefile
+++ b/arch/arm/mach-u300/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel, U300 machine.
 #
 
-obj-y		:= core.o clock.o timer.o
+obj-y		:= core.o timer.o
 obj-m		:=
 obj-n		:=
 obj-		:=
diff --git a/arch/arm/mach-u300/clock.c b/arch/arm/mach-u300/clock.c
deleted file mode 100644
index 5535dd0..0000000
--- a/arch/arm/mach-u300/clock.c
+++ /dev/null
@@ -1,1504 +0,0 @@
-/*
- *
- * arch/arm/mach-u300/clock.c
- *
- *
- * Copyright (C) 2007-2009 ST-Ericsson AB
- * License terms: GNU General Public License (GPL) version 2
- * Define clocks in the app platform.
- * Author: Linus Walleij <linus.walleij@stericsson.com>
- * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
- *
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/spinlock.h>
-#include <linux/debugfs.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/io.h>
-#include <linux/seq_file.h>
-#include <linux/clkdev.h>
-
-#include <mach/hardware.h>
-#include <mach/syscon.h>
-
-#include "clock.h"
-
-/*
- * TODO:
- * - move all handling of the CCR register into this file and create
- *   a spinlock for the CCR register
- * - switch to the clkdevice lookup mechanism that maps clocks to
- *   device ID:s instead when it becomes available in kernel 2.6.29.
- * - implement rate get/set for all clocks that need it.
- */
-
-/*
- * Syscon clock I/O registers lock so clock requests don't collide
- * NOTE: this is a local lock only used to lock access to clock and
- * reset registers in syscon.
- */
-static DEFINE_SPINLOCK(syscon_clkreg_lock);
-static DEFINE_SPINLOCK(syscon_resetreg_lock);
-
-/*
- * The clocking hierarchy currently looks like this.
- * NOTE: the idea is NOT to show how the clocks are routed on the chip!
- * The ideas is to show dependencies, so a clock higher up in the
- * hierarchy has to be on in order for another clock to be on. Now,
- * both CPU and DMA can actually be on top of the hierarchy, and that
- * is not modeled currently. Instead we have the backbone AMBA bus on
- * top. This bus cannot be programmed in any way but conceptually it
- * needs to be active for the bridges and devices to transport data.
- *
- * Please be aware that a few clocks are hw controlled, which mean that
- * the hw itself can turn on/off or change the rate of the clock when
- * needed!
- *
- *  AMBA bus
- *  |
- *  +- CPU
- *  +- FSMC NANDIF NAND Flash interface
- *  +- SEMI Shared Memory interface
- *  +- ISP Image Signal Processor (U335 only)
- *  +- CDS (U335 only)
- *  +- DMA Direct Memory Access Controller
- *  +- AAIF APP/ACC Inteface (Mobile Scalable Link, MSL)
- *  +- APEX
- *  +- VIDEO_ENC AVE2/3 Video Encoder
- *  +- XGAM Graphics Accelerator Controller
- *  +- AHB
- *  |
- *  +- ahb:0 AHB Bridge
- *  |  |
- *  |  +- ahb:1 INTCON Interrupt controller
- *  |  +- ahb:3 MSPRO  Memory Stick Pro controller
- *  |  +- ahb:4 EMIF   External Memory interface
- *  |
- *  +- fast:0 FAST bridge
- *  |  |
- *  |  +- fast:1 MMCSD MMC/SD card reader controller
- *  |  +- fast:2 I2S0  PCM I2S channel 0 controller
- *  |  +- fast:3 I2S1  PCM I2S channel 1 controller
- *  |  +- fast:4 I2C0  I2C channel 0 controller
- *  |  +- fast:5 I2C1  I2C channel 1 controller
- *  |  +- fast:6 SPI   SPI controller
- *  |  +- fast:7 UART1 Secondary UART (U335 only)
- *  |
- *  +- slow:0 SLOW bridge
- *     |
- *     +- slow:1 SYSCON (not possible to control)
- *     +- slow:2 WDOG Watchdog
- *     +- slow:3 UART0 primary UART
- *     +- slow:4 TIMER_APP Application timer - used in Linux
- *     +- slow:5 KEYPAD controller
- *     +- slow:6 GPIO controller
- *     +- slow:7 RTC controller
- *     +- slow:8 BT Bus Tracer (not used currently)
- *     +- slow:9 EH Event Handler (not used currently)
- *     +- slow:a TIMER_ACC Access style timer (not used currently)
- *     +- slow:b PPM (U335 only, what is that?)
- */
-
-/*
- * Reset control functions. We remember if a block has been
- * taken out of reset and don't remove the reset assertion again
- * and vice versa. Currently we only remove resets so the
- * enablement function is defined out.
- */
-static void syscon_block_reset_enable(struct clk *clk)
-{
-	u16 val;
-	unsigned long iflags;
-
-	/* Not all blocks support resetting */
-	if (!clk->res_reg || !clk->res_mask)
-		return;
-	spin_lock_irqsave(&syscon_resetreg_lock, iflags);
-	val = readw(clk->res_reg);
-	val |= clk->res_mask;
-	writew(val, clk->res_reg);
-	spin_unlock_irqrestore(&syscon_resetreg_lock, iflags);
-	clk->reset = true;
-}
-
-static void syscon_block_reset_disable(struct clk *clk)
-{
-	u16 val;
-	unsigned long iflags;
-
-	/* Not all blocks support resetting */
-	if (!clk->res_reg || !clk->res_mask)
-		return;
-	spin_lock_irqsave(&syscon_resetreg_lock, iflags);
-	val = readw(clk->res_reg);
-	val &= ~clk->res_mask;
-	writew(val, clk->res_reg);
-	spin_unlock_irqrestore(&syscon_resetreg_lock, iflags);
-	clk->reset = false;
-}
-
-int __clk_get(struct clk *clk)
-{
-	u16 val;
-
-	/* The MMC and MSPRO clocks need some special set-up */
-	if (!strcmp(clk->name, "MCLK")) {
-		/* Set default MMC clock divisor to 18.9 MHz */
-		writew(0x0054U, U300_SYSCON_VBASE + U300_SYSCON_MMF0R);
-		val = readw(U300_SYSCON_VBASE + U300_SYSCON_MMCR);
-		/* Disable the MMC feedback clock */
-		val &= ~U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE;
-		/* Disable MSPRO frequency */
-		val &= ~U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE;
-		writew(val, U300_SYSCON_VBASE + U300_SYSCON_MMCR);
-	}
-	if (!strcmp(clk->name, "MSPRO")) {
-		val = readw(U300_SYSCON_VBASE + U300_SYSCON_MMCR);
-		/* Disable the MMC feedback clock */
-		val &= ~U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE;
-		/* Enable MSPRO frequency */
-		val |= U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE;
-		writew(val, U300_SYSCON_VBASE + U300_SYSCON_MMCR);
-	}
-	return 1;
-}
-EXPORT_SYMBOL(__clk_get);
-
-void __clk_put(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(__clk_put);
-
-static void syscon_clk_disable(struct clk *clk)
-{
-	unsigned long iflags;
-
-	/* Don't touch the hardware controlled clocks */
-	if (clk->hw_ctrld)
-		return;
-
-	spin_lock_irqsave(&syscon_clkreg_lock, iflags);
-	writew(clk->clk_val, U300_SYSCON_VBASE + U300_SYSCON_SBCDR);
-	spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
-}
-
-static void syscon_clk_enable(struct clk *clk)
-{
-	unsigned long iflags;
-
-	/* Don't touch the hardware controlled clocks */
-	if (clk->hw_ctrld)
-		return;
-
-	spin_lock_irqsave(&syscon_clkreg_lock, iflags);
-	writew(clk->clk_val, U300_SYSCON_VBASE + U300_SYSCON_SBCER);
-	spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
-}
-
-static u16 syscon_clk_get_rate(void)
-{
-	u16 val;
-	unsigned long iflags;
-
-	spin_lock_irqsave(&syscon_clkreg_lock, iflags);
-	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
-	val &= U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK;
-	spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
-	return val;
-}
-
-#ifdef CONFIG_MACH_U300_USE_I2S_AS_MASTER
-static void enable_i2s0_vcxo(void)
-{
-	u16 val;
-	unsigned long iflags;
-
-	spin_lock_irqsave(&syscon_clkreg_lock, iflags);
-	/* Set I2S0 to use the VCXO 26 MHz clock */
-	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
-	val |= U300_SYSCON_CCR_TURN_VCXO_ON;
-	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
-	val |= U300_SYSCON_CCR_I2S0_USE_VCXO;
-	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
-	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR);
-	val |= U300_SYSCON_CEFR_I2S0_CLK_EN;
-	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR);
-	spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
-}
-
-static void enable_i2s1_vcxo(void)
-{
-	u16 val;
-	unsigned long iflags;
-
-	spin_lock_irqsave(&syscon_clkreg_lock, iflags);
-	/* Set I2S1 to use the VCXO 26 MHz clock */
-	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
-	val |= U300_SYSCON_CCR_TURN_VCXO_ON;
-	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
-	val |= U300_SYSCON_CCR_I2S1_USE_VCXO;
-	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
-	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR);
-	val |= U300_SYSCON_CEFR_I2S1_CLK_EN;
-	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR);
-	spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
-}
-
-static void disable_i2s0_vcxo(void)
-{
-	u16 val;
-	unsigned long iflags;
-
-	spin_lock_irqsave(&syscon_clkreg_lock, iflags);
-	/* Disable I2S0 use of the VCXO 26 MHz clock */
-	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
-	val &= ~U300_SYSCON_CCR_I2S0_USE_VCXO;
-	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
-	/* Deactivate VCXO if no one else is using VCXO */
-	if (!(val & U300_SYSCON_CCR_I2S1_USE_VCXO))
-		val &= ~U300_SYSCON_CCR_TURN_VCXO_ON;
-	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
-	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR);
-	val &= ~U300_SYSCON_CEFR_I2S0_CLK_EN;
-	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR);
-	spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
-}
-
-static void disable_i2s1_vcxo(void)
-{
-	u16 val;
-	unsigned long iflags;
-
-	spin_lock_irqsave(&syscon_clkreg_lock, iflags);
-	/* Disable I2S1 use of the VCXO 26 MHz clock */
-	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
-	val &= ~U300_SYSCON_CCR_I2S1_USE_VCXO;
-	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
-	/* Deactivate VCXO if no one else is using VCXO */
-	if (!(val & U300_SYSCON_CCR_I2S0_USE_VCXO))
-		val &= ~U300_SYSCON_CCR_TURN_VCXO_ON;
-	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
-	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR);
-	val &= ~U300_SYSCON_CEFR_I2S0_CLK_EN;
-	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR);
-	spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
-}
-#endif /* CONFIG_MACH_U300_USE_I2S_AS_MASTER */
-
-
-static void syscon_clk_rate_set_mclk(unsigned long rate)
-{
-	u16 val;
-	u32 reg;
-	unsigned long iflags;
-
-	switch (rate) {
-	case 18900000:
-		val = 0x0054;
-		break;
-	case 20800000:
-		val = 0x0044;
-		break;
-	case 23100000:
-		val = 0x0043;
-		break;
-	case 26000000:
-		val = 0x0033;
-		break;
-	case 29700000:
-		val = 0x0032;
-		break;
-	case 34700000:
-		val = 0x0022;
-		break;
-	case 41600000:
-		val = 0x0021;
-		break;
-	case 52000000:
-		val = 0x0011;
-		break;
-	case 104000000:
-		val = 0x0000;
-		break;
-	default:
-		printk(KERN_ERR "Trying to set MCLK to unknown speed! %ld\n",
-		       rate);
-		return;
-	}
-
-	spin_lock_irqsave(&syscon_clkreg_lock, iflags);
-	reg = readw(U300_SYSCON_VBASE + U300_SYSCON_MMF0R) &
-		~U300_SYSCON_MMF0R_MASK;
-	writew(reg | val, U300_SYSCON_VBASE + U300_SYSCON_MMF0R);
-	spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
-}
-
-void syscon_clk_rate_set_cpuclk(unsigned long rate)
-{
-	u16 val;
-	unsigned long iflags;
-
-	switch (rate) {
-	case 13000000:
-		val = U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER;
-		break;
-	case 52000000:
-		val = U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE;
-		break;
-	case 104000000:
-		val = U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH;
-		break;
-	case 208000000:
-		val = U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST;
-		break;
-	default:
-		return;
-	}
-	spin_lock_irqsave(&syscon_clkreg_lock, iflags);
-	val |= readw(U300_SYSCON_VBASE + U300_SYSCON_CCR) &
-		~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK ;
-	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
-	spin_unlock_irqrestore(&syscon_clkreg_lock, iflags);
-}
-EXPORT_SYMBOL(syscon_clk_rate_set_cpuclk);
-
-void clk_disable(struct clk *clk)
-{
-	unsigned long iflags;
-
-	spin_lock_irqsave(&clk->lock, iflags);
-	if (clk->usecount > 0 && !(--clk->usecount)) {
-		/* some blocks lack clocking registers and cannot be disabled */
-		if (clk->disable)
-			clk->disable(clk);
-		if (likely((u32)clk->parent))
-			clk_disable(clk->parent);
-	}
-#ifdef CONFIG_MACH_U300_USE_I2S_AS_MASTER
-	if (unlikely(!strcmp(clk->name, "I2S0")))
-		disable_i2s0_vcxo();
-	if (unlikely(!strcmp(clk->name, "I2S1")))
-		disable_i2s1_vcxo();
-#endif
-	spin_unlock_irqrestore(&clk->lock, iflags);
-}
-EXPORT_SYMBOL(clk_disable);
-
-int clk_enable(struct clk *clk)
-{
-	int ret = 0;
-	unsigned long iflags;
-
-	spin_lock_irqsave(&clk->lock, iflags);
-	if (clk->usecount++ == 0) {
-		if (likely((u32)clk->parent))
-			ret = clk_enable(clk->parent);
-
-		if (unlikely(ret != 0))
-			clk->usecount--;
-		else {
-			/* remove reset line (we never enable reset again) */
-			syscon_block_reset_disable(clk);
-			/* clocks without enable function are always on */
-			if (clk->enable)
-				clk->enable(clk);
-#ifdef CONFIG_MACH_U300_USE_I2S_AS_MASTER
-			if (unlikely(!strcmp(clk->name, "I2S0")))
-				enable_i2s0_vcxo();
-			if (unlikely(!strcmp(clk->name, "I2S1")))
-				enable_i2s1_vcxo();
-#endif
-		}
-	}
-	spin_unlock_irqrestore(&clk->lock, iflags);
-	return ret;
-
-}
-EXPORT_SYMBOL(clk_enable);
-
-/* Returns the clock rate in Hz */
-static unsigned long clk_get_rate_cpuclk(struct clk *clk)
-{
-	u16 val;
-
-	val = syscon_clk_get_rate();
-
-	switch (val) {
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
-		return 13000000;
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
-		return 52000000;
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH:
-		return 104000000;
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST:
-		return 208000000;
-	default:
-		break;
-	}
-	return clk->rate;
-}
-
-static unsigned long clk_get_rate_ahb_clk(struct clk *clk)
-{
-	u16 val;
-
-	val = syscon_clk_get_rate();
-
-	switch (val) {
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
-		return 6500000;
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
-		return 26000000;
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH:
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST:
-		return 52000000;
-	default:
-		break;
-	}
-	return clk->rate;
-
-}
-
-static unsigned long clk_get_rate_emif_clk(struct clk *clk)
-{
-	u16 val;
-
-	val = syscon_clk_get_rate();
-
-	switch (val) {
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
-		return 13000000;
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
-		return 52000000;
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH:
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST:
-		return 104000000;
-	default:
-		break;
-	}
-	return clk->rate;
-
-}
-
-static unsigned long clk_get_rate_xgamclk(struct clk *clk)
-{
-	u16 val;
-
-	val = syscon_clk_get_rate();
-
-	switch (val) {
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
-		return 6500000;
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
-		return 26000000;
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH:
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST:
-		return 52000000;
-	default:
-		break;
-	}
-
-	return clk->rate;
-}
-
-static unsigned long clk_get_rate_mclk(struct clk *clk)
-{
-	u16 val;
-
-	val = syscon_clk_get_rate();
-
-	switch (val) {
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
-		/*
-		 * Here, the 208 MHz PLL gets shut down and the always
-		 * on 13 MHz PLL used for RTC etc kicks into use
-		 * instead.
-		 */
-		return 13000000;
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH:
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST:
-	{
-		/*
-		 * This clock is under program control. The register is
-		 * divided in two nybbles, bit 7-4 gives cycles-1 to count
-		 * high, bit 3-0 gives cycles-1 to count low. Distribute
-		 * these with no more than 1 cycle difference between
-		 * low and high and add low and high to get the actual
-		 * divisor. The base PLL is 208 MHz. Writing 0x00 will
-		 * divide by 1 and 1 so the highest frequency possible
-		 * is 104 MHz.
-		 *
-		 * e.g. 0x54 =>
-		 * f = 208 / ((5+1) + (4+1)) = 208 / 11 = 18.9 MHz
-		 */
-		u16 val = readw(U300_SYSCON_VBASE + U300_SYSCON_MMF0R) &
-			U300_SYSCON_MMF0R_MASK;
-		switch (val) {
-		case 0x0054:
-			return 18900000;
-		case 0x0044:
-			return 20800000;
-		case 0x0043:
-			return 23100000;
-		case 0x0033:
-			return 26000000;
-		case 0x0032:
-			return 29700000;
-		case 0x0022:
-			return 34700000;
-		case 0x0021:
-			return 41600000;
-		case 0x0011:
-			return 52000000;
-		case 0x0000:
-			return 104000000;
-		default:
-			break;
-		}
-	}
-	default:
-		break;
-	}
-
-	return clk->rate;
-}
-
-static unsigned long clk_get_rate_i2s_i2c_spi(struct clk *clk)
-{
-	u16 val;
-
-	val = syscon_clk_get_rate();
-
-	switch (val) {
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
-		return 13000000;
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH:
-	case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST:
-		return 26000000;
-	default:
-		break;
-	}
-
-	return clk->rate;
-}
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-	if (clk->get_rate)
-		return clk->get_rate(clk);
-	else
-		return clk->rate;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-static unsigned long clk_round_rate_mclk(struct clk *clk, unsigned long rate)
-{
-	if (rate <= 18900000)
-		return 18900000;
-	if (rate <= 20800000)
-		return 20800000;
-	if (rate <= 23100000)
-		return 23100000;
-	if (rate <= 26000000)
-		return 26000000;
-	if (rate <= 29700000)
-		return 29700000;
-	if (rate <= 34700000)
-		return 34700000;
-	if (rate <= 41600000)
-		return 41600000;
-	if (rate <= 52000000)
-		return 52000000;
-	return -EINVAL;
-}
-
-static unsigned long clk_round_rate_cpuclk(struct clk *clk, unsigned long rate)
-{
-	if (rate <= 13000000)
-		return 13000000;
-	if (rate <= 52000000)
-		return 52000000;
-	if (rate <= 104000000)
-		return 104000000;
-	if (rate <= 208000000)
-		return 208000000;
-	return -EINVAL;
-}
-
-/*
- * This adjusts a requested rate to the closest exact rate
- * a certain clock can provide. For a fixed clock it's
- * mostly clk->rate.
- */
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	/* TODO: get appropriate switches for EMIFCLK, AHBCLK and MCLK */
-	/* Else default to fixed value */
-
-	if (clk->round_rate) {
-		return (long) clk->round_rate(clk, rate);
-	} else {
-		printk(KERN_ERR "clock: Failed to round rate of %s\n",
-		       clk->name);
-	}
-	return (long) clk->rate;
-}
-EXPORT_SYMBOL(clk_round_rate);
-
-static int clk_set_rate_mclk(struct clk *clk, unsigned long rate)
-{
-	syscon_clk_rate_set_mclk(clk_round_rate(clk, rate));
-	return 0;
-}
-
-static int clk_set_rate_cpuclk(struct clk *clk, unsigned long rate)
-{
-	syscon_clk_rate_set_cpuclk(clk_round_rate(clk, rate));
-	return 0;
-}
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	/* TODO: set for EMIFCLK and AHBCLK */
-	/* Else assume the clock is fixed and fail */
-	if (clk->set_rate) {
-		return clk->set_rate(clk, rate);
-	} else {
-		printk(KERN_ERR "clock: Failed to set %s to %ld hz\n",
-		       clk->name, rate);
-		return -EINVAL;
-	}
-}
-EXPORT_SYMBOL(clk_set_rate);
-
-/*
- * Clock definitions. The clock parents are set to respective
- * bridge and the clock framework makes sure that the clocks have
- * parents activated and are brought out of reset when in use.
- *
- * Clocks that have hw_ctrld = true are hw controlled, and the hw
- * can by itself turn these clocks on and off.
- * So in other words, we don't really have to care about them.
- */
-
-static struct clk amba_clk = {
-	.name	    = "AMBA",
-	.rate	    = 52000000, /* this varies! */
-	.hw_ctrld   = true,
-	.reset	    = false,
-	.lock       = __SPIN_LOCK_UNLOCKED(amba_clk.lock),
-};
-
-/*
- * These blocks are connected directly to the AMBA bus
- * with no bridge.
- */
-
-static struct clk cpu_clk = {
-	.name	    = "CPU",
-	.parent	    = &amba_clk,
-	.rate	    = 208000000, /* this varies! */
-	.hw_ctrld   = true,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
-	.res_mask   = U300_SYSCON_RRR_CPU_RESET_EN,
-	.set_rate   = clk_set_rate_cpuclk,
-	.get_rate   = clk_get_rate_cpuclk,
-	.round_rate = clk_round_rate_cpuclk,
-	.lock       = __SPIN_LOCK_UNLOCKED(cpu_clk.lock),
-};
-
-static struct clk nandif_clk = {
-	.name       = "FSMC",
-	.parent	    = &amba_clk,
-	.hw_ctrld   = false,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
-	.res_mask   = U300_SYSCON_RRR_NANDIF_RESET_EN,
-	.clk_val    = U300_SYSCON_SBCER_NANDIF_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.lock       = __SPIN_LOCK_UNLOCKED(nandif_clk.lock),
-};
-
-static struct clk semi_clk = {
-	.name       = "SEMI",
-	.parent	    = &amba_clk,
-	.rate       = 0, /* FIXME */
-	/* It is not possible to reset SEMI */
-	.hw_ctrld   = false,
-	.reset	    = false,
-	.clk_val    = U300_SYSCON_SBCER_SEMI_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.lock       = __SPIN_LOCK_UNLOCKED(semi_clk.lock),
-};
-
-#ifdef CONFIG_MACH_U300_BS335
-static struct clk isp_clk = {
-	.name	    = "ISP",
-	.parent	    = &amba_clk,
-	.rate	    = 0, /* FIXME */
-	.hw_ctrld   = false,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
-	.res_mask   = U300_SYSCON_RRR_ISP_RESET_EN,
-	.clk_val    = U300_SYSCON_SBCER_ISP_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.lock       = __SPIN_LOCK_UNLOCKED(isp_clk.lock),
-};
-
-static struct clk cds_clk = {
-	.name	    = "CDS",
-	.parent	    = &amba_clk,
-	.rate	    = 0, /* FIXME */
-	.hw_ctrld   = false,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
-	.res_mask   = U300_SYSCON_RRR_CDS_RESET_EN,
-	.clk_val    = U300_SYSCON_SBCER_CDS_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.lock       = __SPIN_LOCK_UNLOCKED(cds_clk.lock),
-};
-#endif
-
-static struct clk dma_clk = {
-	.name       = "DMA",
-	.parent	    = &amba_clk,
-	.rate       = 52000000, /* this varies! */
-	.hw_ctrld   = true,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
-	.res_mask   = U300_SYSCON_RRR_DMAC_RESET_EN,
-	.clk_val    = U300_SYSCON_SBCER_DMAC_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.lock       = __SPIN_LOCK_UNLOCKED(dma_clk.lock),
-};
-
-static struct clk aaif_clk = {
-	.name       = "AAIF",
-	.parent	    = &amba_clk,
-	.rate       = 52000000, /* this varies! */
-	.hw_ctrld   = true,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
-	.res_mask   = U300_SYSCON_RRR_AAIF_RESET_EN,
-	.clk_val    = U300_SYSCON_SBCER_AAIF_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.lock       = __SPIN_LOCK_UNLOCKED(aaif_clk.lock),
-};
-
-static struct clk apex_clk = {
-	.name       = "APEX",
-	.parent	    = &amba_clk,
-	.rate       = 0, /* FIXME */
-	.hw_ctrld   = true,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
-	.res_mask   = U300_SYSCON_RRR_APEX_RESET_EN,
-	.clk_val    = U300_SYSCON_SBCER_APEX_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.lock       = __SPIN_LOCK_UNLOCKED(apex_clk.lock),
-};
-
-static struct clk video_enc_clk = {
-	.name       = "VIDEO_ENC",
-	.parent	    = &amba_clk,
-	.rate       = 208000000, /* this varies! */
-	.hw_ctrld   = false,
-	.reset	    = false,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
-	/* This has XGAM in the name but refers to the video encoder */
-	.res_mask   = U300_SYSCON_RRR_XGAM_VC_SYNC_RESET_EN,
-	.clk_val    = U300_SYSCON_SBCER_VIDEO_ENC_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.lock       = __SPIN_LOCK_UNLOCKED(video_enc_clk.lock),
-};
-
-static struct clk xgam_clk = {
-	.name       = "XGAMCLK",
-	.parent	    = &amba_clk,
-	.rate       = 52000000, /* this varies! */
-	.hw_ctrld   = false,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
-	.res_mask   = U300_SYSCON_RRR_XGAM_RESET_EN,
-	.clk_val    = U300_SYSCON_SBCER_XGAM_CLK_EN,
-	.get_rate   = clk_get_rate_xgamclk,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.lock       = __SPIN_LOCK_UNLOCKED(xgam_clk.lock),
-};
-
-/* This clock is used to activate the video encoder */
-static struct clk ahb_clk = {
-	.name	    = "AHB",
-	.parent	    = &amba_clk,
-	.rate	    = 52000000, /* this varies! */
-	.hw_ctrld   = false, /* This one is set to false due to HW bug */
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
-	.res_mask   = U300_SYSCON_RRR_AHB_RESET_EN,
-	.clk_val    = U300_SYSCON_SBCER_AHB_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.get_rate   = clk_get_rate_ahb_clk,
-	.lock       = __SPIN_LOCK_UNLOCKED(ahb_clk.lock),
-};
-
-
-/*
- * Clocks on the AHB bridge
- */
-
-static struct clk ahb_subsys_clk = {
-	.name	    = "AHB_SUBSYS",
-	.parent	    = &amba_clk,
-	.rate	    = 52000000, /* this varies! */
-	.hw_ctrld   = true,
-	.reset	    = false,
-	.clk_val    = U300_SYSCON_SBCER_AHB_SUBSYS_BRIDGE_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.get_rate   = clk_get_rate_ahb_clk,
-	.lock       = __SPIN_LOCK_UNLOCKED(ahb_subsys_clk.lock),
-};
-
-static struct clk intcon_clk = {
-	.name	    = "INTCON",
-	.parent	    = &ahb_subsys_clk,
-	.rate	    = 52000000, /* this varies! */
-	.hw_ctrld   = false,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
-	.res_mask   = U300_SYSCON_RRR_INTCON_RESET_EN,
-	/* INTCON can be reset but not clock-gated */
-	.lock       = __SPIN_LOCK_UNLOCKED(intcon_clk.lock),
-
-};
-
-static struct clk mspro_clk = {
-	.name       = "MSPRO",
-	.parent	    = &ahb_subsys_clk,
-	.rate       = 0, /* FIXME */
-	.hw_ctrld   = false,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
-	.res_mask   = U300_SYSCON_RRR_MSPRO_RESET_EN,
-	.clk_val    = U300_SYSCON_SBCER_MSPRO_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.lock       = __SPIN_LOCK_UNLOCKED(mspro_clk.lock),
-};
-
-static struct clk emif_clk = {
-	.name	    = "EMIF",
-	.parent	    = &ahb_subsys_clk,
-	.rate	    = 104000000, /* this varies! */
-	.hw_ctrld   = false,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
-	.res_mask   = U300_SYSCON_RRR_EMIF_RESET_EN,
-	.clk_val    = U300_SYSCON_SBCER_EMIF_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.get_rate   = clk_get_rate_emif_clk,
-	.lock       = __SPIN_LOCK_UNLOCKED(emif_clk.lock),
-};
-
-
-/*
- * Clocks on the FAST bridge
- */
-static struct clk fast_clk = {
-	.name	    = "FAST_BRIDGE",
-	.parent	    = &amba_clk,
-	.rate	    = 13000000, /* this varies! */
-	.hw_ctrld   = true,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR,
-	.res_mask   = U300_SYSCON_RFR_FAST_BRIDGE_RESET_ENABLE,
-	.clk_val    = U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.lock       = __SPIN_LOCK_UNLOCKED(fast_clk.lock),
-};
-
-/*
- * The MMCI apb_pclk is hardwired to the same terminal as the
- * external MCI clock. Thus this will be referenced twice.
- */
-static struct clk mmcsd_clk = {
-	.name       = "MCLK",
-	.parent	    = &fast_clk,
-	.rate       = 18900000, /* this varies! */
-	.hw_ctrld   = false,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR,
-	.res_mask   = U300_SYSCON_RFR_MMC_RESET_ENABLE,
-	.clk_val    = U300_SYSCON_SBCER_MMC_CLK_EN,
-	.get_rate   = clk_get_rate_mclk,
-	.set_rate   = clk_set_rate_mclk,
-	.round_rate = clk_round_rate_mclk,
-	.disable    = syscon_clk_disable,
-	.enable     = syscon_clk_enable,
-	.lock       = __SPIN_LOCK_UNLOCKED(mmcsd_clk.lock),
-};
-
-static struct clk i2s0_clk = {
-	.name       = "i2s0",
-	.parent	    = &fast_clk,
-	.rate       = 26000000, /* this varies! */
-	.hw_ctrld   = true,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR,
-	.res_mask   = U300_SYSCON_RFR_PCM_I2S0_RESET_ENABLE,
-	.clk_val    = U300_SYSCON_SBCER_I2S0_CORE_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.get_rate   = clk_get_rate_i2s_i2c_spi,
-	.lock       = __SPIN_LOCK_UNLOCKED(i2s0_clk.lock),
-};
-
-static struct clk i2s1_clk = {
-	.name       = "i2s1",
-	.parent	    = &fast_clk,
-	.rate       = 26000000, /* this varies! */
-	.hw_ctrld   = true,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR,
-	.res_mask   = U300_SYSCON_RFR_PCM_I2S1_RESET_ENABLE,
-	.clk_val    = U300_SYSCON_SBCER_I2S1_CORE_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.get_rate   = clk_get_rate_i2s_i2c_spi,
-	.lock       = __SPIN_LOCK_UNLOCKED(i2s1_clk.lock),
-};
-
-static struct clk i2c0_clk = {
-	.name       = "I2C0",
-	.parent	    = &fast_clk,
-	.rate       = 26000000, /* this varies! */
-	.hw_ctrld   = false,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR,
-	.res_mask   = U300_SYSCON_RFR_I2C0_RESET_ENABLE,
-	.clk_val    = U300_SYSCON_SBCER_I2C0_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.get_rate   = clk_get_rate_i2s_i2c_spi,
-	.lock       = __SPIN_LOCK_UNLOCKED(i2c0_clk.lock),
-};
-
-static struct clk i2c1_clk = {
-	.name       = "I2C1",
-	.parent	    = &fast_clk,
-	.rate       = 26000000, /* this varies! */
-	.hw_ctrld   = false,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR,
-	.res_mask   = U300_SYSCON_RFR_I2C1_RESET_ENABLE,
-	.clk_val    = U300_SYSCON_SBCER_I2C1_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.get_rate   = clk_get_rate_i2s_i2c_spi,
-	.lock       = __SPIN_LOCK_UNLOCKED(i2c1_clk.lock),
-};
-
-/*
- * The SPI apb_pclk is hardwired to the same terminal as the
- * external SPI clock. Thus this will be referenced twice.
- */
-static struct clk spi_clk = {
-	.name       = "SPI",
-	.parent	    = &fast_clk,
-	.rate       = 26000000, /* this varies! */
-	.hw_ctrld   = false,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR,
-	.res_mask   = U300_SYSCON_RFR_SPI_RESET_ENABLE,
-	.clk_val    = U300_SYSCON_SBCER_SPI_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.get_rate   = clk_get_rate_i2s_i2c_spi,
-	.lock       = __SPIN_LOCK_UNLOCKED(spi_clk.lock),
-};
-
-#ifdef CONFIG_MACH_U300_BS335
-static struct clk uart1_pclk = {
-	.name	    = "UART1_PCLK",
-	.parent	    = &fast_clk,
-	.hw_ctrld   = false,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RFR,
-	.res_mask   = U300_SYSCON_RFR_UART1_RESET_ENABLE,
-	.clk_val    = U300_SYSCON_SBCER_UART1_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.lock       = __SPIN_LOCK_UNLOCKED(uart1_pclk.lock),
-};
-
-/* This one is hardwired to PLL13 */
-static struct clk uart1_clk = {
-	.name	    = "UART1_CLK",
-	.rate	    = 13000000,
-	.hw_ctrld   = true,
-	.lock       = __SPIN_LOCK_UNLOCKED(uart1_clk.lock),
-};
-#endif
-
-
-/*
- * Clocks on the SLOW bridge
- */
-static struct clk slow_clk = {
-	.name	    = "SLOW_BRIDGE",
-	.parent	    = &amba_clk,
-	.rate	    = 13000000,
-	.hw_ctrld   = true,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR,
-	.res_mask   = U300_SYSCON_RSR_SLOW_BRIDGE_RESET_EN,
-	.clk_val    = U300_SYSCON_SBCER_SLOW_BRIDGE_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.lock       = __SPIN_LOCK_UNLOCKED(slow_clk.lock),
-};
-
-/* TODO: implement SYSCON clock? */
-
-static struct clk wdog_clk = {
-	.name	    = "WDOG",
-	.parent	    = &slow_clk,
-	.hw_ctrld   = false,
-	.rate	    = 32768,
-	.reset	    = false,
-	/* This is always on, cannot be enabled/disabled or reset */
-	.lock       = __SPIN_LOCK_UNLOCKED(wdog_clk.lock),
-};
-
-static struct clk uart0_pclk = {
-	.name	    = "UART0_PCLK",
-	.parent	    = &slow_clk,
-	.hw_ctrld   = false,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR,
-	.res_mask   = U300_SYSCON_RSR_UART_RESET_EN,
-	.clk_val    = U300_SYSCON_SBCER_UART_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.lock       = __SPIN_LOCK_UNLOCKED(uart0_pclk.lock),
-};
-
-/* This one is hardwired to PLL13 */
-static struct clk uart0_clk = {
-	.name	    = "UART0_CLK",
-	.parent	    = &slow_clk,
-	.rate	    = 13000000,
-	.hw_ctrld   = true,
-	.lock       = __SPIN_LOCK_UNLOCKED(uart0_clk.lock),
-};
-
-static struct clk keypad_clk = {
-	.name       = "KEYPAD",
-	.parent	    = &slow_clk,
-	.rate       = 32768,
-	.hw_ctrld   = false,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR,
-	.res_mask   = U300_SYSCON_RSR_KEYPAD_RESET_EN,
-	.clk_val    = U300_SYSCON_SBCER_KEYPAD_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.lock       = __SPIN_LOCK_UNLOCKED(keypad_clk.lock),
-};
-
-static struct clk gpio_clk = {
-	.name       = "GPIO",
-	.parent	    = &slow_clk,
-	.rate       = 13000000,
-	.hw_ctrld   = true,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR,
-	.res_mask   = U300_SYSCON_RSR_GPIO_RESET_EN,
-	.clk_val    = U300_SYSCON_SBCER_GPIO_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.lock       = __SPIN_LOCK_UNLOCKED(gpio_clk.lock),
-};
-
-static struct clk rtc_clk = {
-	.name	    = "RTC",
-	.parent	    = &slow_clk,
-	.rate	    = 32768,
-	.hw_ctrld   = true,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR,
-	.res_mask   = U300_SYSCON_RSR_RTC_RESET_EN,
-	/* This clock is always on, cannot be enabled/disabled */
-	.lock       = __SPIN_LOCK_UNLOCKED(rtc_clk.lock),
-};
-
-static struct clk bustr_clk = {
-	.name       = "BUSTR",
-	.parent	    = &slow_clk,
-	.rate       = 13000000,
-	.hw_ctrld   = true,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR,
-	.res_mask   = U300_SYSCON_RSR_BTR_RESET_EN,
-	.clk_val    = U300_SYSCON_SBCER_BTR_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.lock       = __SPIN_LOCK_UNLOCKED(bustr_clk.lock),
-};
-
-static struct clk evhist_clk = {
-	.name       = "EVHIST",
-	.parent	    = &slow_clk,
-	.rate       = 13000000,
-	.hw_ctrld   = true,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR,
-	.res_mask   = U300_SYSCON_RSR_EH_RESET_EN,
-	.clk_val    = U300_SYSCON_SBCER_EH_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.lock       = __SPIN_LOCK_UNLOCKED(evhist_clk.lock),
-};
-
-static struct clk timer_clk = {
-	.name       = "TIMER",
-	.parent	    = &slow_clk,
-	.rate       = 13000000,
-	.hw_ctrld   = true,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR,
-	.res_mask   = U300_SYSCON_RSR_ACC_TMR_RESET_EN,
-	.clk_val    = U300_SYSCON_SBCER_ACC_TMR_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.lock       = __SPIN_LOCK_UNLOCKED(timer_clk.lock),
-};
-
-/*
- * There is a binary divider in the hardware that divides
- * the 13MHz PLL by 13 down to 1 MHz.
- */
-static struct clk app_timer_clk = {
-	.name       = "TIMER_APP",
-	.parent	    = &slow_clk,
-	.rate       = 1000000,
-	.hw_ctrld   = true,
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR,
-	.res_mask   = U300_SYSCON_RSR_APP_TMR_RESET_EN,
-	.clk_val    = U300_SYSCON_SBCER_APP_TMR_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.lock       = __SPIN_LOCK_UNLOCKED(app_timer_clk.lock),
-};
-
-#ifdef CONFIG_MACH_U300_BS335
-static struct clk ppm_clk = {
-	.name	    = "PPM",
-	.parent	    = &slow_clk,
-	.rate	    = 0, /* FIXME */
-	.hw_ctrld   = true, /* TODO: Look up if it is hw ctrld or not */
-	.reset	    = true,
-	.res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR,
-	.res_mask   = U300_SYSCON_RSR_PPM_RESET_EN,
-	.clk_val    = U300_SYSCON_SBCER_PPM_CLK_EN,
-	.enable     = syscon_clk_enable,
-	.disable    = syscon_clk_disable,
-	.lock       = __SPIN_LOCK_UNLOCKED(ppm_clk.lock),
-};
-#endif
-
-#define DEF_LOOKUP(devid, clkref)		\
-	{					\
-	.dev_id = devid,			\
-	.clk = clkref,				\
-	}
-
-#define DEF_LOOKUP_CON(devid, conid, clkref)	\
-	{					\
-	.dev_id = devid,			\
-	.con_id = conid,			\
-	.clk = clkref,				\
-	}
-
-/*
- * Here we only define clocks that are meaningful to
- * look up through clockdevice.
- */
-static struct clk_lookup lookups[] = {
-	/* Connected directly to the AMBA bus */
-	DEF_LOOKUP("amba",      &amba_clk),
-	DEF_LOOKUP("cpu",       &cpu_clk),
-	DEF_LOOKUP("fsmc-nand", &nandif_clk),
-	DEF_LOOKUP("semi",      &semi_clk),
-#ifdef CONFIG_MACH_U300_BS335
-	DEF_LOOKUP("isp",       &isp_clk),
-	DEF_LOOKUP("cds",       &cds_clk),
-#endif
-	DEF_LOOKUP("dma",       &dma_clk),
-	DEF_LOOKUP("msl",       &aaif_clk),
-	DEF_LOOKUP("apex",      &apex_clk),
-	DEF_LOOKUP("video_enc", &video_enc_clk),
-	DEF_LOOKUP("xgam",      &xgam_clk),
-	DEF_LOOKUP("ahb",       &ahb_clk),
-	/* AHB bridge clocks */
-	DEF_LOOKUP("ahb_subsys", &ahb_subsys_clk),
-	DEF_LOOKUP("intcon",    &intcon_clk),
-	DEF_LOOKUP_CON("intcon", "apb_pclk", &intcon_clk),
-	DEF_LOOKUP("mspro",     &mspro_clk),
-	DEF_LOOKUP("pl172",     &emif_clk),
-	DEF_LOOKUP_CON("pl172", "apb_pclk", &emif_clk),
-	/* FAST bridge clocks */
-	DEF_LOOKUP("fast",      &fast_clk),
-	DEF_LOOKUP("mmci",      &mmcsd_clk),
-	DEF_LOOKUP_CON("mmci", "apb_pclk", &mmcsd_clk),
-	/*
-	 * The .0 and .1 identifiers on these comes from the platform device
-	 * .id field and are assigned when the platform devices are registered.
-	 */
-	DEF_LOOKUP("i2s.0",     &i2s0_clk),
-	DEF_LOOKUP("i2s.1",     &i2s1_clk),
-	DEF_LOOKUP("stu300.0",  &i2c0_clk),
-	DEF_LOOKUP("stu300.1",  &i2c1_clk),
-	DEF_LOOKUP("pl022",     &spi_clk),
-	DEF_LOOKUP_CON("pl022", "apb_pclk", &spi_clk),
-#ifdef CONFIG_MACH_U300_BS335
-	DEF_LOOKUP("uart1",     &uart1_clk),
-	DEF_LOOKUP_CON("uart1", "apb_pclk", &uart1_pclk),
-#endif
-	/* SLOW bridge clocks */
-	DEF_LOOKUP("slow",      &slow_clk),
-	DEF_LOOKUP("coh901327_wdog",      &wdog_clk),
-	DEF_LOOKUP("uart0",     &uart0_clk),
-	DEF_LOOKUP_CON("uart0", "apb_pclk", &uart0_pclk),
-	DEF_LOOKUP("apptimer",  &app_timer_clk),
-	DEF_LOOKUP("coh901461-keypad",    &keypad_clk),
-	DEF_LOOKUP("u300-gpio", &gpio_clk),
-	DEF_LOOKUP("rtc-coh901331",      &rtc_clk),
-	DEF_LOOKUP("bustr",     &bustr_clk),
-	DEF_LOOKUP("evhist",    &evhist_clk),
-	DEF_LOOKUP("timer",     &timer_clk),
-#ifdef CONFIG_MACH_U300_BS335
-	DEF_LOOKUP("ppm",       &ppm_clk),
-#endif
-};
-
-static void __init clk_register(void)
-{
-	/* Register the lookups */
-	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-}
-
-#if (defined(CONFIG_DEBUG_FS) && defined(CONFIG_U300_DEBUG))
-/*
- * The following makes it possible to view the status (especially
- * reference count and reset status) for the clocks in the platform
- * by looking into the special file <debugfs>/u300_clocks
- */
-
-/* A list of all clocks in the platform */
-static struct clk *clks[] = {
-	/* Top node clock for the AMBA bus */
-	&amba_clk,
-	/* Connected directly to the AMBA bus */
-	&cpu_clk,
-	&nandif_clk,
-	&semi_clk,
-#ifdef CONFIG_MACH_U300_BS335
-	&isp_clk,
-	&cds_clk,
-#endif
-	&dma_clk,
-	&aaif_clk,
-	&apex_clk,
-	&video_enc_clk,
-	&xgam_clk,
-	&ahb_clk,
-
-	/* AHB bridge clocks */
-	&ahb_subsys_clk,
-	&intcon_clk,
-	&mspro_clk,
-	&emif_clk,
-	/* FAST bridge clocks */
-	&fast_clk,
-	&mmcsd_clk,
-	&i2s0_clk,
-	&i2s1_clk,
-	&i2c0_clk,
-	&i2c1_clk,
-	&spi_clk,
-#ifdef CONFIG_MACH_U300_BS335
-	&uart1_clk,
-	&uart1_pclk,
-#endif
-	/* SLOW bridge clocks */
-	&slow_clk,
-	&wdog_clk,
-	&uart0_clk,
-	&uart0_pclk,
-	&app_timer_clk,
-	&keypad_clk,
-	&gpio_clk,
-	&rtc_clk,
-	&bustr_clk,
-	&evhist_clk,
-	&timer_clk,
-#ifdef CONFIG_MACH_U300_BS335
-	&ppm_clk,
-#endif
-};
-
-static int u300_clocks_show(struct seq_file *s, void *data)
-{
-	struct clk *clk;
-	int i;
-
-	seq_printf(s, "CLOCK           DEVICE          RESET STATE\t" \
-		   "ACTIVE\tUSERS\tHW CTRL FREQ\n");
-	seq_printf(s, "---------------------------------------------" \
-		   "-----------------------------------------\n");
-	for (i = 0; i < ARRAY_SIZE(clks); i++) {
-		clk = clks[i];
-		if (clk != ERR_PTR(-ENOENT)) {
-			/* Format clock and device name nicely */
-			char cdp[33];
-			int chars;
-
-			chars = snprintf(&cdp[0], 17, "%s", clk->name);
-			while (chars < 16) {
-				cdp[chars] = ' ';
-				chars++;
-			}
-			chars = snprintf(&cdp[16], 17, "%s", clk->dev ?
-					 dev_name(clk->dev) : "N/A");
-			while (chars < 16) {
-				cdp[chars+16] = ' ';
-				chars++;
-			}
-			cdp[32] = '\0';
-			if (clk->get_rate || clk->rate != 0)
-				seq_printf(s,
-					   "%s%s\t%s\t%d\t%s\t%lu Hz\n",
-					   &cdp[0],
-					   clk->reset ?
-					   "ASSERTED" : "RELEASED",
-					   clk->usecount ? "ON" : "OFF",
-					   clk->usecount,
-					   clk->hw_ctrld  ? "YES" : "NO ",
-					   clk_get_rate(clk));
-			else
-				seq_printf(s,
-					   "%s%s\t%s\t%d\t%s\t" \
-					   "(unknown rate)\n",
-					   &cdp[0],
-					   clk->reset ?
-					   "ASSERTED" : "RELEASED",
-					   clk->usecount ? "ON" : "OFF",
-					   clk->usecount,
-					   clk->hw_ctrld  ? "YES" : "NO ");
-		}
-	}
-	return 0;
-}
-
-static int u300_clocks_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, u300_clocks_show, NULL);
-}
-
-static const struct file_operations u300_clocks_operations = {
-	.open		= u300_clocks_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int __init init_clk_read_debugfs(void)
-{
-	/* Expose a simple debugfs interface to view all clocks */
-	(void) debugfs_create_file("u300_clocks", S_IFREG | S_IRUGO,
-				   NULL, NULL,
-				   &u300_clocks_operations);
-	return 0;
-}
-/*
- * This needs to come in after the core_initcall() for the
- * overall clocks, because debugfs is not available until
- * the subsystems come up.
- */
-module_init(init_clk_read_debugfs);
-#endif
-
-int __init u300_clock_init(void)
-{
-	u16 val;
-
-	/*
-	 * FIXME: shall all this powermanagement stuff really live here???
-	 */
-
-	/* Set system to run at PLL208, max performance, a known state. */
-	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
-	val &= ~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK;
-	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
-	/* Wait for the PLL208 to lock if not locked in yet */
-	while (!(readw(U300_SYSCON_VBASE + U300_SYSCON_CSR) &
-		 U300_SYSCON_CSR_PLL208_LOCK_IND));
-
-	/* Power management enable */
-	val = readw(U300_SYSCON_VBASE + U300_SYSCON_PMCR);
-	val |= U300_SYSCON_PMCR_PWR_MGNT_ENABLE;
-	writew(val, U300_SYSCON_VBASE + U300_SYSCON_PMCR);
-
-	clk_register();
-
-	/*
-	 * Some of these may be on when we boot the system so make sure they
-	 * are turned OFF.
-	 */
-	syscon_block_reset_enable(&timer_clk);
-	timer_clk.disable(&timer_clk);
-
-	/*
-	 * These shall be turned on by default when we boot the system
-	 * so make sure they are ON. (Adding CPU here is a bit too much.)
-	 * These clocks will be claimed by drivers later.
-	 */
-	syscon_block_reset_disable(&semi_clk);
-	syscon_block_reset_disable(&emif_clk);
-	clk_enable(&semi_clk);
-	clk_enable(&emif_clk);
-
-	return 0;
-}
diff --git a/arch/arm/mach-u300/clock.h b/arch/arm/mach-u300/clock.h
deleted file mode 100644
index 4f50ca8..0000000
--- a/arch/arm/mach-u300/clock.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * arch/arm/mach-u300/include/mach/clock.h
- *
- * Copyright (C) 2004 - 2005 Nokia corporation
- * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
- * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc
- * Copyright (C) 2007-2009 ST-Ericsson AB
- * Adopted to ST-Ericsson U300 platforms by
- * Jonas Aaberg <jonas.aberg@stericsson.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#ifndef __MACH_CLOCK_H
-#define __MACH_CLOCK_H
-
-#include <linux/clk.h>
-
-struct clk {
-	struct list_head node;
-	struct module *owner;
-	struct device *dev;
-	const char *name;
-	struct clk *parent;
-
-	spinlock_t lock;
-	unsigned long rate;
-	bool reset;
-	__u16 clk_val;
-	__s8 usecount;
-	void __iomem * res_reg;
-	__u16 res_mask;
-
-	bool hw_ctrld;
-
-	void (*recalc) (struct clk *);
-	int (*set_rate) (struct clk *, unsigned long);
-	unsigned long (*get_rate) (struct clk *);
-	unsigned long (*round_rate) (struct clk *, unsigned long);
-	void (*init) (struct clk *);
-	void (*enable) (struct clk *);
-	void (*disable) (struct clk *);
-};
-
-int u300_clock_init(void);
-
-#endif
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index 3333974..03acf18 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -30,6 +30,7 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/pinctrl/pinconf-generic.h>
 #include <linux/dma-mapping.h>
+#include <linux/platform_data/clk-u300.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -44,7 +45,6 @@
 #include <mach/dma_channels.h>
 #include <mach/gpio-u300.h>
 
-#include "clock.h"
 #include "spi.h"
 #include "i2c.h"
 #include "u300-gpio.h"
@@ -1658,12 +1658,20 @@
 	int i;
 
 	/* initialize clocking early, we want to clock the INTCON */
-	u300_clock_init();
+	u300_clk_init(U300_SYSCON_VBASE);
+
+	/* Bootstrap EMIF and SEMI clocks */
+	clk = clk_get_sys("pl172", NULL);
+	BUG_ON(IS_ERR(clk));
+	clk_prepare_enable(clk);
+	clk = clk_get_sys("semi", NULL);
+	BUG_ON(IS_ERR(clk));
+	clk_prepare_enable(clk);
 
 	/* Clock the interrupt controller */
 	clk = clk_get_sys("intcon", NULL);
 	BUG_ON(IS_ERR(clk));
-	clk_enable(clk);
+	clk_prepare_enable(clk);
 
 	for (i = 0; i < U300_VIC_IRQS_END; i++)
 		set_bit(i, (unsigned long *) &mask[0]);
@@ -1811,13 +1819,6 @@
 	/* Check what platform we run and print some status information */
 	u300_init_check_chip();
 
-	/* Set system to run at PLL208, max performance, a known state. */
-	val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
-	val &= ~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK;
-	writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
-	/* Wait for the PLL208 to lock if not locked in yet */
-	while (!(readw(U300_SYSCON_VBASE + U300_SYSCON_CSR) &
-		 U300_SYSCON_CSR_PLL208_LOCK_IND));
 	/* Initialize SPI device with some board specifics */
 	u300_spi_init(&pl022_device);
 
diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c
index bc1c789..56ac06d 100644
--- a/arch/arm/mach-u300/timer.c
+++ b/arch/arm/mach-u300/timer.c
@@ -354,7 +354,7 @@
 	/* Clock the interrupt controller */
 	clk = clk_get_sys("apptimer", NULL);
 	BUG_ON(IS_ERR(clk));
-	clk_enable(clk);
+	clk_prepare_enable(clk);
 	rate = clk_get_rate(clk);
 
 	setup_sched_clock(u300_read_sched_clock, 32, rate);
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 4864407..3f99b90 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -34,4 +34,11 @@
 	  clk_flags, clk_prepare_count, clk_enable_count &
 	  clk_notifier_count.
 
+config COMMON_CLK_WM831X
+	tristate "Clock driver for WM831x/2x PMICs"
+	depends on MFD_WM831X
+	---help---
+          Supports the clocking subsystem of the WM831x/2x series of
+	  PMICs from Wolfson Microlectronics.
+
 endmenu
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 3669761..5869ea3 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,9 +1,15 @@
-
+# common clock types
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
 obj-$(CONFIG_COMMON_CLK)	+= clk.o clk-fixed-rate.o clk-gate.o \
 				   clk-mux.o clk-divider.o clk-fixed-factor.o
 # SoCs specific
 obj-$(CONFIG_ARCH_NOMADIK)	+= clk-nomadik.o
+obj-$(CONFIG_ARCH_HIGHBANK)	+= clk-highbank.o
 obj-$(CONFIG_ARCH_MXS)		+= mxs/
 obj-$(CONFIG_ARCH_SOCFPGA)	+= socfpga/
 obj-$(CONFIG_PLAT_SPEAR)	+= spear/
+obj-$(CONFIG_ARCH_U300)		+= clk-u300.o
+obj-$(CONFIG_ARCH_INTEGRATOR)	+= versatile/
+
+# Chip specific
+obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 8ea11b44..a9204c6 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -30,18 +30,89 @@
 #define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
 
 #define div_mask(d)	((1 << (d->width)) - 1)
+#define is_power_of_two(i)	!(i & ~i)
+
+static unsigned int _get_table_maxdiv(const struct clk_div_table *table)
+{
+	unsigned int maxdiv = 0;
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->div > maxdiv)
+			maxdiv = clkt->div;
+	return maxdiv;
+}
+
+static unsigned int _get_maxdiv(struct clk_divider *divider)
+{
+	if (divider->flags & CLK_DIVIDER_ONE_BASED)
+		return div_mask(divider);
+	if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
+		return 1 << div_mask(divider);
+	if (divider->table)
+		return _get_table_maxdiv(divider->table);
+	return div_mask(divider) + 1;
+}
+
+static unsigned int _get_table_div(const struct clk_div_table *table,
+							unsigned int val)
+{
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->val == val)
+			return clkt->div;
+	return 0;
+}
+
+static unsigned int _get_div(struct clk_divider *divider, unsigned int val)
+{
+	if (divider->flags & CLK_DIVIDER_ONE_BASED)
+		return val;
+	if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
+		return 1 << val;
+	if (divider->table)
+		return _get_table_div(divider->table, val);
+	return val + 1;
+}
+
+static unsigned int _get_table_val(const struct clk_div_table *table,
+							unsigned int div)
+{
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->div == div)
+			return clkt->val;
+	return 0;
+}
+
+static unsigned int _get_val(struct clk_divider *divider, u8 div)
+{
+	if (divider->flags & CLK_DIVIDER_ONE_BASED)
+		return div;
+	if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
+		return __ffs(div);
+	if (divider->table)
+		return  _get_table_val(divider->table, div);
+	return div - 1;
+}
 
 static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
 		unsigned long parent_rate)
 {
 	struct clk_divider *divider = to_clk_divider(hw);
-	unsigned int div;
+	unsigned int div, val;
 
-	div = readl(divider->reg) >> divider->shift;
-	div &= div_mask(divider);
+	val = readl(divider->reg) >> divider->shift;
+	val &= div_mask(divider);
 
-	if (!(divider->flags & CLK_DIVIDER_ONE_BASED))
-		div++;
+	div = _get_div(divider, val);
+	if (!div) {
+		WARN(1, "%s: Invalid divisor for clock %s\n", __func__,
+						__clk_get_name(hw->clk));
+		return parent_rate;
+	}
 
 	return parent_rate / div;
 }
@@ -52,6 +123,26 @@
  */
 #define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
 
+static bool _is_valid_table_div(const struct clk_div_table *table,
+							 unsigned int div)
+{
+	const struct clk_div_table *clkt;
+
+	for (clkt = table; clkt->div; clkt++)
+		if (clkt->div == div)
+			return true;
+	return false;
+}
+
+static bool _is_valid_div(struct clk_divider *divider, unsigned int div)
+{
+	if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
+		return is_power_of_two(div);
+	if (divider->table)
+		return _is_valid_table_div(divider->table, div);
+	return true;
+}
+
 static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
 		unsigned long *best_parent_rate)
 {
@@ -62,10 +153,7 @@
 	if (!rate)
 		rate = 1;
 
-	maxdiv = (1 << divider->width);
-
-	if (divider->flags & CLK_DIVIDER_ONE_BASED)
-		maxdiv--;
+	maxdiv = _get_maxdiv(divider);
 
 	if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
 		parent_rate = *best_parent_rate;
@@ -82,6 +170,8 @@
 	maxdiv = min(ULONG_MAX / rate, maxdiv);
 
 	for (i = 1; i <= maxdiv; i++) {
+		if (!_is_valid_div(divider, i))
+			continue;
 		parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
 				MULT_ROUND_UP(rate, i));
 		now = parent_rate / i;
@@ -93,9 +183,7 @@
 	}
 
 	if (!bestdiv) {
-		bestdiv = (1 << divider->width);
-		if (divider->flags & CLK_DIVIDER_ONE_BASED)
-			bestdiv--;
+		bestdiv = _get_maxdiv(divider);
 		*best_parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), 1);
 	}
 
@@ -115,24 +203,22 @@
 				unsigned long parent_rate)
 {
 	struct clk_divider *divider = to_clk_divider(hw);
-	unsigned int div;
+	unsigned int div, value;
 	unsigned long flags = 0;
 	u32 val;
 
 	div = parent_rate / rate;
+	value = _get_val(divider, div);
 
-	if (!(divider->flags & CLK_DIVIDER_ONE_BASED))
-		div--;
-
-	if (div > div_mask(divider))
-		div = div_mask(divider);
+	if (value > div_mask(divider))
+		value = div_mask(divider);
 
 	if (divider->lock)
 		spin_lock_irqsave(divider->lock, flags);
 
 	val = readl(divider->reg);
 	val &= ~(div_mask(divider) << divider->shift);
-	val |= div << divider->shift;
+	val |= value << divider->shift;
 	writel(val, divider->reg);
 
 	if (divider->lock)
@@ -148,6 +234,47 @@
 };
 EXPORT_SYMBOL_GPL(clk_divider_ops);
 
+static struct clk *_register_divider(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 shift, u8 width,
+		u8 clk_divider_flags, const struct clk_div_table *table,
+		spinlock_t *lock)
+{
+	struct clk_divider *div;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/* allocate the divider */
+	div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
+	if (!div) {
+		pr_err("%s: could not allocate divider clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	init.name = name;
+	init.ops = &clk_divider_ops;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = (parent_name ? &parent_name: NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	/* struct clk_divider assignments */
+	div->reg = reg;
+	div->shift = shift;
+	div->width = width;
+	div->flags = clk_divider_flags;
+	div->lock = lock;
+	div->hw.init = &init;
+	div->table = table;
+
+	/* register the clock */
+	clk = clk_register(dev, &div->hw);
+
+	if (IS_ERR(clk))
+		kfree(div);
+
+	return clk;
+}
+
 /**
  * clk_register_divider - register a divider clock with the clock framework
  * @dev: device registering this clock
@@ -165,36 +292,30 @@
 		void __iomem *reg, u8 shift, u8 width,
 		u8 clk_divider_flags, spinlock_t *lock)
 {
-	struct clk_divider *div;
-	struct clk *clk;
-	struct clk_init_data init;
+	return _register_divider(dev, name, parent_name, flags, reg, shift,
+			width, clk_divider_flags, NULL, lock);
+}
 
-	/* allocate the divider */
-	div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
-	if (!div) {
-		pr_err("%s: could not allocate divider clk\n", __func__);
-		return ERR_PTR(-ENOMEM);
-	}
-
-	init.name = name;
-	init.ops = &clk_divider_ops;
-	init.flags = flags;
-	init.parent_names = (parent_name ? &parent_name: NULL);
-	init.num_parents = (parent_name ? 1 : 0);
-
-	/* struct clk_divider assignments */
-	div->reg = reg;
-	div->shift = shift;
-	div->width = width;
-	div->flags = clk_divider_flags;
-	div->lock = lock;
-	div->hw.init = &init;
-
-	/* register the clock */
-	clk = clk_register(dev, &div->hw);
-
-	if (IS_ERR(clk))
-		kfree(div);
-
-	return clk;
+/**
+ * clk_register_divider_table - register a table based divider clock with
+ * the clock framework
+ * @dev: device registering this clock
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @flags: framework-specific flags
+ * @reg: register address to adjust divider
+ * @shift: number of bits to shift the bitfield
+ * @width: width of the bitfield
+ * @clk_divider_flags: divider-specific flags for this clock
+ * @table: array of divider/value pairs ending with a div set to 0
+ * @lock: shared register lock for this clock
+ */
+struct clk *clk_register_divider_table(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 shift, u8 width,
+		u8 clk_divider_flags, const struct clk_div_table *table,
+		spinlock_t *lock)
+{
+	return _register_divider(dev, name, parent_name, flags, reg, shift,
+			width, clk_divider_flags, table, lock);
 }
diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index c8c003e..a489985 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -82,7 +82,7 @@
 
 	init.name = name;
 	init.ops = &clk_fixed_factor_ops;
-	init.flags = flags;
+	init.flags = flags | CLK_IS_BASIC;
 	init.parent_names = &parent_name;
 	init.num_parents = 1;
 
diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c
index cbd2462..f5ec0ee 100644
--- a/drivers/clk/clk-fixed-rate.c
+++ b/drivers/clk/clk-fixed-rate.c
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/err.h>
+#include <linux/of.h>
 
 /*
  * DOC: basic fixed-rate clock that cannot gate
@@ -63,7 +64,7 @@
 
 	init.name = name;
 	init.ops = &clk_fixed_rate_ops;
-	init.flags = flags;
+	init.flags = flags | CLK_IS_BASIC;
 	init.parent_names = (parent_name ? &parent_name: NULL);
 	init.num_parents = (parent_name ? 1 : 0);
 
@@ -79,3 +80,25 @@
 
 	return clk;
 }
+
+#ifdef CONFIG_OF
+/**
+ * of_fixed_clk_setup() - Setup function for simple fixed rate clock
+ */
+void __init of_fixed_clk_setup(struct device_node *node)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	u32 rate;
+
+	if (of_property_read_u32(node, "clock-frequency", &rate))
+		return;
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
+	clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, rate);
+	if (clk)
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+EXPORT_SYMBOL_GPL(of_fixed_clk_setup);
+#endif
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 578465e..15114fe 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -130,7 +130,7 @@
 
 	init.name = name;
 	init.ops = &clk_gate_ops;
-	init.flags = flags;
+	init.flags = flags | CLK_IS_BASIC;
 	init.parent_names = (parent_name ? &parent_name: NULL);
 	init.num_parents = (parent_name ? 1 : 0);
 
diff --git a/drivers/clk/clk-highbank.c b/drivers/clk/clk-highbank.c
new file mode 100644
index 0000000..52fecad
--- /dev/null
+++ b/drivers/clk/clk-highbank.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright 2011-2012 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+extern void __iomem *sregs_base;
+
+#define HB_PLL_LOCK_500		0x20000000
+#define HB_PLL_LOCK		0x10000000
+#define HB_PLL_DIVF_SHIFT	20
+#define HB_PLL_DIVF_MASK	0x0ff00000
+#define HB_PLL_DIVQ_SHIFT	16
+#define HB_PLL_DIVQ_MASK	0x00070000
+#define HB_PLL_DIVR_SHIFT	8
+#define HB_PLL_DIVR_MASK	0x00001f00
+#define HB_PLL_RANGE_SHIFT	4
+#define HB_PLL_RANGE_MASK	0x00000070
+#define HB_PLL_BYPASS		0x00000008
+#define HB_PLL_RESET		0x00000004
+#define HB_PLL_EXT_BYPASS	0x00000002
+#define HB_PLL_EXT_ENA		0x00000001
+
+#define HB_PLL_VCO_MIN_FREQ	2133000000
+#define HB_PLL_MAX_FREQ		HB_PLL_VCO_MIN_FREQ
+#define HB_PLL_MIN_FREQ		(HB_PLL_VCO_MIN_FREQ / 64)
+
+#define HB_A9_BCLK_DIV_MASK	0x00000006
+#define HB_A9_BCLK_DIV_SHIFT	1
+#define HB_A9_PCLK_DIV		0x00000001
+
+struct hb_clk {
+        struct clk_hw	hw;
+	void __iomem	*reg;
+	char *parent_name;
+};
+#define to_hb_clk(p) container_of(p, struct hb_clk, hw)
+
+static int clk_pll_prepare(struct clk_hw *hwclk)
+	{
+	struct hb_clk *hbclk = to_hb_clk(hwclk);
+	u32 reg;
+
+	reg = readl(hbclk->reg);
+	reg &= ~HB_PLL_RESET;
+	writel(reg, hbclk->reg);
+
+	while ((readl(hbclk->reg) & HB_PLL_LOCK) == 0)
+		;
+	while ((readl(hbclk->reg) & HB_PLL_LOCK_500) == 0)
+		;
+
+	return 0;
+}
+
+static void clk_pll_unprepare(struct clk_hw *hwclk)
+{
+	struct hb_clk *hbclk = to_hb_clk(hwclk);
+	u32 reg;
+
+	reg = readl(hbclk->reg);
+	reg |= HB_PLL_RESET;
+	writel(reg, hbclk->reg);
+}
+
+static int clk_pll_enable(struct clk_hw *hwclk)
+{
+	struct hb_clk *hbclk = to_hb_clk(hwclk);
+	u32 reg;
+
+	reg = readl(hbclk->reg);
+	reg |= HB_PLL_EXT_ENA;
+	writel(reg, hbclk->reg);
+
+	return 0;
+}
+
+static void clk_pll_disable(struct clk_hw *hwclk)
+{
+	struct hb_clk *hbclk = to_hb_clk(hwclk);
+	u32 reg;
+
+	reg = readl(hbclk->reg);
+	reg &= ~HB_PLL_EXT_ENA;
+	writel(reg, hbclk->reg);
+}
+
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
+					 unsigned long parent_rate)
+{
+	struct hb_clk *hbclk = to_hb_clk(hwclk);
+	unsigned long divf, divq, vco_freq, reg;
+
+	reg = readl(hbclk->reg);
+	if (reg & HB_PLL_EXT_BYPASS)
+		return parent_rate;
+
+	divf = (reg & HB_PLL_DIVF_MASK) >> HB_PLL_DIVF_SHIFT;
+	divq = (reg & HB_PLL_DIVQ_MASK) >> HB_PLL_DIVQ_SHIFT;
+	vco_freq = parent_rate * (divf + 1);
+
+	return vco_freq / (1 << divq);
+}
+
+static void clk_pll_calc(unsigned long rate, unsigned long ref_freq,
+			u32 *pdivq, u32 *pdivf)
+{
+	u32 divq, divf;
+	unsigned long vco_freq;
+
+	if (rate < HB_PLL_MIN_FREQ)
+		rate = HB_PLL_MIN_FREQ;
+	if (rate > HB_PLL_MAX_FREQ)
+		rate = HB_PLL_MAX_FREQ;
+
+	for (divq = 1; divq <= 6; divq++) {
+		if ((rate * (1 << divq)) >= HB_PLL_VCO_MIN_FREQ)
+			break;
+	}
+
+	vco_freq = rate * (1 << divq);
+	divf = (vco_freq + (ref_freq / 2)) / ref_freq;
+	divf--;
+
+	*pdivq = divq;
+	*pdivf = divf;
+}
+
+static long clk_pll_round_rate(struct clk_hw *hwclk, unsigned long rate,
+			       unsigned long *parent_rate)
+{
+	u32 divq, divf;
+	unsigned long ref_freq = *parent_rate;
+
+	clk_pll_calc(rate, ref_freq, &divq, &divf);
+
+	return (ref_freq * (divf + 1)) / (1 << divq);
+}
+
+static int clk_pll_set_rate(struct clk_hw *hwclk, unsigned long rate,
+			    unsigned long parent_rate)
+{
+	struct hb_clk *hbclk = to_hb_clk(hwclk);
+	u32 divq, divf;
+	u32 reg;
+
+	clk_pll_calc(rate, parent_rate, &divq, &divf);
+
+	reg = readl(hbclk->reg);
+	if (divf != ((reg & HB_PLL_DIVF_MASK) >> HB_PLL_DIVF_SHIFT)) {
+		/* Need to re-lock PLL, so put it into bypass mode */
+		reg |= HB_PLL_EXT_BYPASS;
+		writel(reg | HB_PLL_EXT_BYPASS, hbclk->reg);
+
+		writel(reg | HB_PLL_RESET, hbclk->reg);
+		reg &= ~(HB_PLL_DIVF_MASK | HB_PLL_DIVQ_MASK);
+		reg |= (divf << HB_PLL_DIVF_SHIFT) | (divq << HB_PLL_DIVQ_SHIFT);
+		writel(reg | HB_PLL_RESET, hbclk->reg);
+		writel(reg, hbclk->reg);
+
+		while ((readl(hbclk->reg) & HB_PLL_LOCK) == 0)
+			;
+		while ((readl(hbclk->reg) & HB_PLL_LOCK_500) == 0)
+			;
+		reg |= HB_PLL_EXT_ENA;
+		reg &= ~HB_PLL_EXT_BYPASS;
+	} else {
+		reg &= ~HB_PLL_DIVQ_MASK;
+		reg |= divq << HB_PLL_DIVQ_SHIFT;
+	}
+	writel(reg, hbclk->reg);
+
+	return 0;
+}
+
+static const struct clk_ops clk_pll_ops = {
+	.prepare = clk_pll_prepare,
+	.unprepare = clk_pll_unprepare,
+	.enable = clk_pll_enable,
+	.disable = clk_pll_disable,
+	.recalc_rate = clk_pll_recalc_rate,
+	.round_rate = clk_pll_round_rate,
+	.set_rate = clk_pll_set_rate,
+};
+
+static unsigned long clk_cpu_periphclk_recalc_rate(struct clk_hw *hwclk,
+						   unsigned long parent_rate)
+{
+	struct hb_clk *hbclk = to_hb_clk(hwclk);
+	u32 div = (readl(hbclk->reg) & HB_A9_PCLK_DIV) ? 8 : 4;
+	return parent_rate / div;
+}
+
+static const struct clk_ops a9periphclk_ops = {
+	.recalc_rate = clk_cpu_periphclk_recalc_rate,
+};
+
+static unsigned long clk_cpu_a9bclk_recalc_rate(struct clk_hw *hwclk,
+						unsigned long parent_rate)
+{
+	struct hb_clk *hbclk = to_hb_clk(hwclk);
+	u32 div = (readl(hbclk->reg) & HB_A9_BCLK_DIV_MASK) >> HB_A9_BCLK_DIV_SHIFT;
+
+	return parent_rate / (div + 2);
+}
+
+static const struct clk_ops a9bclk_ops = {
+	.recalc_rate = clk_cpu_a9bclk_recalc_rate,
+};
+
+static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk,
+					     unsigned long parent_rate)
+{
+	struct hb_clk *hbclk = to_hb_clk(hwclk);
+	u32 div;
+
+	div = readl(hbclk->reg) & 0x1f;
+	div++;
+	div *= 2;
+
+	return parent_rate / div;
+}
+
+static long clk_periclk_round_rate(struct clk_hw *hwclk, unsigned long rate,
+				   unsigned long *parent_rate)
+{
+	u32 div;
+
+	div = *parent_rate / rate;
+	div++;
+	div &= ~0x1;
+
+	return *parent_rate / div;
+}
+
+static int clk_periclk_set_rate(struct clk_hw *hwclk, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct hb_clk *hbclk = to_hb_clk(hwclk);
+	u32 div;
+
+	div = parent_rate / rate;
+	if (div & 0x1)
+		return -EINVAL;
+
+	writel(div >> 1, hbclk->reg);
+	return 0;
+}
+
+static const struct clk_ops periclk_ops = {
+	.recalc_rate = clk_periclk_recalc_rate,
+	.round_rate = clk_periclk_round_rate,
+	.set_rate = clk_periclk_set_rate,
+};
+
+static __init struct clk *hb_clk_init(struct device_node *node, const struct clk_ops *ops)
+{
+	u32 reg;
+	struct clk *clk;
+	struct hb_clk *hb_clk;
+	const char *clk_name = node->name;
+	const char *parent_name;
+	struct clk_init_data init;
+	int rc;
+
+	rc = of_property_read_u32(node, "reg", &reg);
+	if (WARN_ON(rc))
+		return NULL;
+
+	hb_clk = kzalloc(sizeof(*hb_clk), GFP_KERNEL);
+	if (WARN_ON(!hb_clk))
+		return NULL;
+
+	hb_clk->reg = sregs_base + reg;
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
+	init.name = clk_name;
+	init.ops = ops;
+	init.flags = 0;
+	parent_name = of_clk_get_parent_name(node, 0);
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	hb_clk->hw.init = &init;
+
+	clk = clk_register(NULL, &hb_clk->hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(hb_clk);
+		return NULL;
+	}
+	rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	return clk;
+}
+
+static void __init hb_pll_init(struct device_node *node)
+{
+	hb_clk_init(node, &clk_pll_ops);
+}
+
+static void __init hb_a9periph_init(struct device_node *node)
+{
+	hb_clk_init(node, &a9periphclk_ops);
+}
+
+static void __init hb_a9bus_init(struct device_node *node)
+{
+	struct clk *clk = hb_clk_init(node, &a9bclk_ops);
+	clk_prepare_enable(clk);
+}
+
+static void __init hb_emmc_init(struct device_node *node)
+{
+	hb_clk_init(node, &periclk_ops);
+}
+
+static const __initconst struct of_device_id clk_match[] = {
+	{ .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
+	{ .compatible = "calxeda,hb-pll-clock", .data = hb_pll_init, },
+	{ .compatible = "calxeda,hb-a9periph-clock", .data = hb_a9periph_init, },
+	{ .compatible = "calxeda,hb-a9bus-clock", .data = hb_a9bus_init, },
+	{ .compatible = "calxeda,hb-emmc-clock", .data = hb_emmc_init, },
+	{}
+};
+
+void __init highbank_clocks_init(void)
+{
+	of_clk_init(clk_match);
+}
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index fd36a8e..508c032 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -106,7 +106,7 @@
 
 	init.name = name;
 	init.ops = &clk_mux_ops;
-	init.flags = flags;
+	init.flags = flags | CLK_IS_BASIC;
 	init.parent_names = parent_names;
 	init.num_parents = num_parents;
 
diff --git a/drivers/clk/clk-u300.c b/drivers/clk/clk-u300.c
new file mode 100644
index 0000000..a15f792
--- /dev/null
+++ b/drivers/clk/clk-u300.c
@@ -0,0 +1,746 @@
+/*
+ * U300 clock implementation
+ * Copyright (C) 2007-2012 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
+ */
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+#include <linux/spinlock.h>
+#include <mach/syscon.h>
+
+/*
+ * The clocking hierarchy currently looks like this.
+ * NOTE: the idea is NOT to show how the clocks are routed on the chip!
+ * The ideas is to show dependencies, so a clock higher up in the
+ * hierarchy has to be on in order for another clock to be on. Now,
+ * both CPU and DMA can actually be on top of the hierarchy, and that
+ * is not modeled currently. Instead we have the backbone AMBA bus on
+ * top. This bus cannot be programmed in any way but conceptually it
+ * needs to be active for the bridges and devices to transport data.
+ *
+ * Please be aware that a few clocks are hw controlled, which mean that
+ * the hw itself can turn on/off or change the rate of the clock when
+ * needed!
+ *
+ *  AMBA bus
+ *  |
+ *  +- CPU
+ *  +- FSMC NANDIF NAND Flash interface
+ *  +- SEMI Shared Memory interface
+ *  +- ISP Image Signal Processor (U335 only)
+ *  +- CDS (U335 only)
+ *  +- DMA Direct Memory Access Controller
+ *  +- AAIF APP/ACC Inteface (Mobile Scalable Link, MSL)
+ *  +- APEX
+ *  +- VIDEO_ENC AVE2/3 Video Encoder
+ *  +- XGAM Graphics Accelerator Controller
+ *  +- AHB
+ *  |
+ *  +- ahb:0 AHB Bridge
+ *  |  |
+ *  |  +- ahb:1 INTCON Interrupt controller
+ *  |  +- ahb:3 MSPRO  Memory Stick Pro controller
+ *  |  +- ahb:4 EMIF   External Memory interface
+ *  |
+ *  +- fast:0 FAST bridge
+ *  |  |
+ *  |  +- fast:1 MMCSD MMC/SD card reader controller
+ *  |  +- fast:2 I2S0  PCM I2S channel 0 controller
+ *  |  +- fast:3 I2S1  PCM I2S channel 1 controller
+ *  |  +- fast:4 I2C0  I2C channel 0 controller
+ *  |  +- fast:5 I2C1  I2C channel 1 controller
+ *  |  +- fast:6 SPI   SPI controller
+ *  |  +- fast:7 UART1 Secondary UART (U335 only)
+ *  |
+ *  +- slow:0 SLOW bridge
+ *     |
+ *     +- slow:1 SYSCON (not possible to control)
+ *     +- slow:2 WDOG Watchdog
+ *     +- slow:3 UART0 primary UART
+ *     +- slow:4 TIMER_APP Application timer - used in Linux
+ *     +- slow:5 KEYPAD controller
+ *     +- slow:6 GPIO controller
+ *     +- slow:7 RTC controller
+ *     +- slow:8 BT Bus Tracer (not used currently)
+ *     +- slow:9 EH Event Handler (not used currently)
+ *     +- slow:a TIMER_ACC Access style timer (not used currently)
+ *     +- slow:b PPM (U335 only, what is that?)
+ */
+
+/* Global syscon virtual base */
+static void __iomem *syscon_vbase;
+
+/**
+ * struct clk_syscon - U300 syscon clock
+ * @hw: corresponding clock hardware entry
+ * @hw_ctrld: whether this clock is hardware controlled (for refcount etc)
+ *	and does not need any magic pokes to be enabled/disabled
+ * @reset: state holder, whether this block's reset line is asserted or not
+ * @res_reg: reset line enable/disable flag register
+ * @res_bit: bit for resetting or taking this consumer out of reset
+ * @en_reg: clock line enable/disable flag register
+ * @en_bit: bit for enabling/disabling this consumer clock line
+ * @clk_val: magic value to poke in the register to enable/disable
+ *	this one clock
+ */
+struct clk_syscon {
+	struct clk_hw hw;
+	bool hw_ctrld;
+	bool reset;
+	void __iomem *res_reg;
+	u8 res_bit;
+	void __iomem *en_reg;
+	u8 en_bit;
+	u16 clk_val;
+};
+
+#define to_syscon(_hw) container_of(_hw, struct clk_syscon, hw)
+
+static DEFINE_SPINLOCK(syscon_resetreg_lock);
+
+/*
+ * Reset control functions. We remember if a block has been
+ * taken out of reset and don't remove the reset assertion again
+ * and vice versa. Currently we only remove resets so the
+ * enablement function is defined out.
+ */
+static void syscon_block_reset_enable(struct clk_syscon *sclk)
+{
+	unsigned long iflags;
+	u16 val;
+
+	/* Not all blocks support resetting */
+	if (!sclk->res_reg)
+		return;
+	spin_lock_irqsave(&syscon_resetreg_lock, iflags);
+	val = readw(sclk->res_reg);
+	val |= BIT(sclk->res_bit);
+	writew(val, sclk->res_reg);
+	spin_unlock_irqrestore(&syscon_resetreg_lock, iflags);
+	sclk->reset = true;
+}
+
+static void syscon_block_reset_disable(struct clk_syscon *sclk)
+{
+	unsigned long iflags;
+	u16 val;
+
+	/* Not all blocks support resetting */
+	if (!sclk->res_reg)
+		return;
+	spin_lock_irqsave(&syscon_resetreg_lock, iflags);
+	val = readw(sclk->res_reg);
+	val &= ~BIT(sclk->res_bit);
+	writew(val, sclk->res_reg);
+	spin_unlock_irqrestore(&syscon_resetreg_lock, iflags);
+	sclk->reset = false;
+}
+
+static int syscon_clk_prepare(struct clk_hw *hw)
+{
+	struct clk_syscon *sclk = to_syscon(hw);
+
+	/* If the block is in reset, bring it out */
+	if (sclk->reset)
+		syscon_block_reset_disable(sclk);
+	return 0;
+}
+
+static void syscon_clk_unprepare(struct clk_hw *hw)
+{
+	struct clk_syscon *sclk = to_syscon(hw);
+
+	/* Please don't force the console into reset */
+	if (sclk->clk_val == U300_SYSCON_SBCER_UART_CLK_EN)
+		return;
+	/* When unpreparing, force block into reset */
+	if (!sclk->reset)
+		syscon_block_reset_enable(sclk);
+}
+
+static int syscon_clk_enable(struct clk_hw *hw)
+{
+	struct clk_syscon *sclk = to_syscon(hw);
+
+	/* Don't touch the hardware controlled clocks */
+	if (sclk->hw_ctrld)
+		return 0;
+	/* These cannot be controlled */
+	if (sclk->clk_val == 0xFFFFU)
+		return 0;
+
+	writew(sclk->clk_val, syscon_vbase + U300_SYSCON_SBCER);
+	return 0;
+}
+
+static void syscon_clk_disable(struct clk_hw *hw)
+{
+	struct clk_syscon *sclk = to_syscon(hw);
+
+	/* Don't touch the hardware controlled clocks */
+	if (sclk->hw_ctrld)
+		return;
+	if (sclk->clk_val == 0xFFFFU)
+		return;
+	/* Please don't disable the console port */
+	if (sclk->clk_val == U300_SYSCON_SBCER_UART_CLK_EN)
+		return;
+
+	writew(sclk->clk_val, syscon_vbase + U300_SYSCON_SBCDR);
+}
+
+static int syscon_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_syscon *sclk = to_syscon(hw);
+	u16 val;
+
+	/* If no enable register defined, it's always-on */
+	if (!sclk->en_reg)
+		return 1;
+
+	val = readw(sclk->en_reg);
+	val &= BIT(sclk->en_bit);
+
+	return val ? 1 : 0;
+}
+
+static u16 syscon_get_perf(void)
+{
+	u16 val;
+
+	val = readw(syscon_vbase + U300_SYSCON_CCR);
+	val &= U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK;
+	return val;
+}
+
+static unsigned long
+syscon_clk_recalc_rate(struct clk_hw *hw,
+		       unsigned long parent_rate)
+{
+	struct clk_syscon *sclk = to_syscon(hw);
+	u16 perf = syscon_get_perf();
+
+	switch(sclk->clk_val) {
+	case U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN:
+	case U300_SYSCON_SBCER_I2C0_CLK_EN:
+	case U300_SYSCON_SBCER_I2C1_CLK_EN:
+	case U300_SYSCON_SBCER_MMC_CLK_EN:
+	case U300_SYSCON_SBCER_SPI_CLK_EN:
+		/* The FAST clocks have one progression */
+		switch(perf) {
+		case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
+		case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
+			return 13000000;
+		default:
+			return parent_rate; /* 26 MHz */
+		}
+	case U300_SYSCON_SBCER_DMAC_CLK_EN:
+	case U300_SYSCON_SBCER_NANDIF_CLK_EN:
+	case U300_SYSCON_SBCER_XGAM_CLK_EN:
+		/* AMBA interconnect peripherals */
+		switch(perf) {
+		case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
+		case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
+			return 6500000;
+		case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
+			return 26000000;
+		default:
+			return parent_rate; /* 52 MHz */
+		}
+	case U300_SYSCON_SBCER_SEMI_CLK_EN:
+	case U300_SYSCON_SBCER_EMIF_CLK_EN:
+		/* EMIF speeds */
+		switch(perf) {
+		case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
+		case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
+			return 13000000;
+		case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
+			return 52000000;
+		default:
+			return 104000000;
+		}
+	case U300_SYSCON_SBCER_CPU_CLK_EN:
+		/* And the fast CPU clock */
+		switch(perf) {
+		case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
+		case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
+			return 13000000;
+		case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
+			return 52000000;
+		case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH:
+			return 104000000;
+		default:
+			return parent_rate; /* 208 MHz */
+		}
+	default:
+		/*
+		 * The SLOW clocks and default just inherit the rate of
+		 * their parent (typically PLL13 13 MHz).
+		 */
+		return parent_rate;
+	}
+}
+
+static long
+syscon_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+		      unsigned long *prate)
+{
+	struct clk_syscon *sclk = to_syscon(hw);
+
+	if (sclk->clk_val != U300_SYSCON_SBCER_CPU_CLK_EN)
+		return *prate;
+	/* We really only support setting the rate of the CPU clock */
+	if (rate <= 13000000)
+		return 13000000;
+	if (rate <= 52000000)
+		return 52000000;
+	if (rate <= 104000000)
+		return 104000000;
+	return 208000000;
+}
+
+static int syscon_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long parent_rate)
+{
+	struct clk_syscon *sclk = to_syscon(hw);
+	u16 val;
+
+	/* We only support setting the rate of the CPU clock */
+	if (sclk->clk_val != U300_SYSCON_SBCER_CPU_CLK_EN)
+		return -EINVAL;
+	switch (rate) {
+	case 13000000:
+		val = U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER;
+		break;
+	case 52000000:
+		val = U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE;
+		break;
+	case 104000000:
+		val = U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH;
+		break;
+	case 208000000:
+		val = U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST;
+		break;
+	default:
+		return -EINVAL;
+	}
+	val |= readw(syscon_vbase + U300_SYSCON_CCR) &
+		~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK ;
+	writew(val, syscon_vbase + U300_SYSCON_CCR);
+	return 0;
+}
+
+static const struct clk_ops syscon_clk_ops = {
+	.prepare = syscon_clk_prepare,
+	.unprepare = syscon_clk_unprepare,
+	.enable = syscon_clk_enable,
+	.disable = syscon_clk_disable,
+	.is_enabled = syscon_clk_is_enabled,
+	.recalc_rate = syscon_clk_recalc_rate,
+	.round_rate = syscon_clk_round_rate,
+	.set_rate = syscon_clk_set_rate,
+};
+
+static struct clk * __init
+syscon_clk_register(struct device *dev, const char *name,
+		    const char *parent_name, unsigned long flags,
+		    bool hw_ctrld,
+		    void __iomem *res_reg, u8 res_bit,
+		    void __iomem *en_reg, u8 en_bit,
+		    u16 clk_val)
+{
+	struct clk *clk;
+	struct clk_syscon *sclk;
+	struct clk_init_data init;
+
+	sclk = kzalloc(sizeof(struct clk_syscon), GFP_KERNEL);
+	if (!sclk) {
+		pr_err("could not allocate syscon clock %s\n",
+			name);
+		return ERR_PTR(-ENOMEM);
+	}
+	init.name = name;
+	init.ops = &syscon_clk_ops;
+	init.flags = flags;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+	sclk->hw.init = &init;
+	sclk->hw_ctrld = hw_ctrld;
+	/* Assume the block is in reset at registration */
+	sclk->reset = true;
+	sclk->res_reg = res_reg;
+	sclk->res_bit = res_bit;
+	sclk->en_reg = en_reg;
+	sclk->en_bit = en_bit;
+	sclk->clk_val = clk_val;
+
+	clk = clk_register(dev, &sclk->hw);
+	if (IS_ERR(clk))
+		kfree(sclk);
+
+	return clk;
+}
+
+/**
+ * struct clk_mclk - U300 MCLK clock (MMC/SD clock)
+ * @hw: corresponding clock hardware entry
+ * @is_mspro: if this is the memory stick clock rather than MMC/SD
+ */
+struct clk_mclk {
+	struct clk_hw hw;
+	bool is_mspro;
+};
+
+#define to_mclk(_hw) container_of(_hw, struct clk_mclk, hw)
+
+static int mclk_clk_prepare(struct clk_hw *hw)
+{
+	struct clk_mclk *mclk = to_mclk(hw);
+	u16 val;
+
+	/* The MMC and MSPRO clocks need some special set-up */
+	if (!mclk->is_mspro) {
+		/* Set default MMC clock divisor to 18.9 MHz */
+		writew(0x0054U, syscon_vbase + U300_SYSCON_MMF0R);
+		val = readw(syscon_vbase + U300_SYSCON_MMCR);
+		/* Disable the MMC feedback clock */
+		val &= ~U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE;
+		/* Disable MSPRO frequency */
+		val &= ~U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE;
+		writew(val, syscon_vbase + U300_SYSCON_MMCR);
+	} else {
+		val = readw(syscon_vbase + U300_SYSCON_MMCR);
+		/* Disable the MMC feedback clock */
+		val &= ~U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE;
+		/* Enable MSPRO frequency */
+		val |= U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE;
+		writew(val, syscon_vbase + U300_SYSCON_MMCR);
+	}
+
+	return 0;
+}
+
+static unsigned long
+mclk_clk_recalc_rate(struct clk_hw *hw,
+		     unsigned long parent_rate)
+{
+	u16 perf = syscon_get_perf();
+
+	switch (perf) {
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
+		/*
+		 * Here, the 208 MHz PLL gets shut down and the always
+		 * on 13 MHz PLL used for RTC etc kicks into use
+		 * instead.
+		 */
+		return 13000000;
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH:
+	case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST:
+	{
+		/*
+		 * This clock is under program control. The register is
+		 * divided in two nybbles, bit 7-4 gives cycles-1 to count
+		 * high, bit 3-0 gives cycles-1 to count low. Distribute
+		 * these with no more than 1 cycle difference between
+		 * low and high and add low and high to get the actual
+		 * divisor. The base PLL is 208 MHz. Writing 0x00 will
+		 * divide by 1 and 1 so the highest frequency possible
+		 * is 104 MHz.
+		 *
+		 * e.g. 0x54 =>
+		 * f = 208 / ((5+1) + (4+1)) = 208 / 11 = 18.9 MHz
+		 */
+		u16 val = readw(syscon_vbase + U300_SYSCON_MMF0R) &
+			U300_SYSCON_MMF0R_MASK;
+		switch (val) {
+		case 0x0054:
+			return 18900000;
+		case 0x0044:
+			return 20800000;
+		case 0x0043:
+			return 23100000;
+		case 0x0033:
+			return 26000000;
+		case 0x0032:
+			return 29700000;
+		case 0x0022:
+			return 34700000;
+		case 0x0021:
+			return 41600000;
+		case 0x0011:
+			return 52000000;
+		case 0x0000:
+			return 104000000;
+		default:
+			break;
+		}
+	}
+	default:
+		break;
+	}
+	return parent_rate;
+}
+
+static long
+mclk_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+		    unsigned long *prate)
+{
+	if (rate <= 18900000)
+		return 18900000;
+	if (rate <= 20800000)
+		return 20800000;
+	if (rate <= 23100000)
+		return 23100000;
+	if (rate <= 26000000)
+		return 26000000;
+	if (rate <= 29700000)
+		return 29700000;
+	if (rate <= 34700000)
+		return 34700000;
+	if (rate <= 41600000)
+		return 41600000;
+	/* Highest rate */
+	return 52000000;
+}
+
+static int mclk_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+			     unsigned long parent_rate)
+{
+	u16 val;
+	u16 reg;
+
+	switch (rate) {
+	case 18900000:
+		val = 0x0054;
+		break;
+	case 20800000:
+		val = 0x0044;
+		break;
+	case 23100000:
+		val = 0x0043;
+		break;
+	case 26000000:
+		val = 0x0033;
+		break;
+	case 29700000:
+		val = 0x0032;
+		break;
+	case 34700000:
+		val = 0x0022;
+		break;
+	case 41600000:
+		val = 0x0021;
+		break;
+	case 52000000:
+		val = 0x0011;
+		break;
+	case 104000000:
+		val = 0x0000;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	reg = readw(syscon_vbase + U300_SYSCON_MMF0R) &
+		~U300_SYSCON_MMF0R_MASK;
+	writew(reg | val, syscon_vbase + U300_SYSCON_MMF0R);
+	return 0;
+}
+
+static const struct clk_ops mclk_ops = {
+	.prepare = mclk_clk_prepare,
+	.recalc_rate = mclk_clk_recalc_rate,
+	.round_rate = mclk_clk_round_rate,
+	.set_rate = mclk_clk_set_rate,
+};
+
+static struct clk * __init
+mclk_clk_register(struct device *dev, const char *name,
+		  const char *parent_name, bool is_mspro)
+{
+	struct clk *clk;
+	struct clk_mclk *mclk;
+	struct clk_init_data init;
+
+	mclk = kzalloc(sizeof(struct clk_mclk), GFP_KERNEL);
+	if (!mclk) {
+		pr_err("could not allocate MMC/SD clock %s\n",
+		       name);
+		return ERR_PTR(-ENOMEM);
+	}
+	init.name = "mclk";
+	init.ops = &mclk_ops;
+	init.flags = 0;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+	mclk->hw.init = &init;
+	mclk->is_mspro = is_mspro;
+
+	clk = clk_register(dev, &mclk->hw);
+	if (IS_ERR(clk))
+		kfree(mclk);
+
+	return clk;
+}
+
+void __init u300_clk_init(void __iomem *base)
+{
+	u16 val;
+	struct clk *clk;
+
+	syscon_vbase = base;
+
+	/* Set system to run at PLL208, max performance, a known state. */
+	val = readw(syscon_vbase + U300_SYSCON_CCR);
+	val &= ~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK;
+	writew(val, syscon_vbase + U300_SYSCON_CCR);
+	/* Wait for the PLL208 to lock if not locked in yet */
+	while (!(readw(syscon_vbase + U300_SYSCON_CSR) &
+		 U300_SYSCON_CSR_PLL208_LOCK_IND));
+
+	/* Power management enable */
+	val = readw(syscon_vbase + U300_SYSCON_PMCR);
+	val |= U300_SYSCON_PMCR_PWR_MGNT_ENABLE;
+	writew(val, syscon_vbase + U300_SYSCON_PMCR);
+
+	/* These are always available (RTC and PLL13) */
+	clk = clk_register_fixed_rate(NULL, "app_32_clk", NULL,
+				      CLK_IS_ROOT, 32768);
+	/* The watchdog sits directly on the 32 kHz clock */
+	clk_register_clkdev(clk, NULL, "coh901327_wdog");
+	clk = clk_register_fixed_rate(NULL, "pll13", NULL,
+				      CLK_IS_ROOT, 13000000);
+
+	/* These derive from PLL208 */
+	clk = clk_register_fixed_rate(NULL, "pll208", NULL,
+				      CLK_IS_ROOT, 208000000);
+	clk = clk_register_fixed_factor(NULL, "app_208_clk", "pll208",
+					0, 1, 1);
+	clk = clk_register_fixed_factor(NULL, "app_104_clk", "pll208",
+					0, 1, 2);
+	clk = clk_register_fixed_factor(NULL, "app_52_clk", "pll208",
+					0, 1, 4);
+	/* The 52 MHz is divided down to 26 MHz */
+	clk = clk_register_fixed_factor(NULL, "app_26_clk", "app_52_clk",
+					0, 1, 2);
+
+	/* Directly on the AMBA interconnect */
+	clk = syscon_clk_register(NULL, "cpu_clk", "app_208_clk", 0, true,
+				  syscon_vbase + U300_SYSCON_RRR, 3,
+				  syscon_vbase + U300_SYSCON_CERR, 3,
+				  U300_SYSCON_SBCER_CPU_CLK_EN);
+	clk = syscon_clk_register(NULL, "dmac_clk", "app_52_clk", 0, true,
+				  syscon_vbase + U300_SYSCON_RRR, 4,
+				  syscon_vbase + U300_SYSCON_CERR, 4,
+				  U300_SYSCON_SBCER_DMAC_CLK_EN);
+	clk_register_clkdev(clk, NULL, "dma");
+	clk = syscon_clk_register(NULL, "fsmc_clk", "app_52_clk", 0, false,
+				  syscon_vbase + U300_SYSCON_RRR, 6,
+				  syscon_vbase + U300_SYSCON_CERR, 6,
+				  U300_SYSCON_SBCER_NANDIF_CLK_EN);
+	clk_register_clkdev(clk, NULL, "fsmc-nand");
+	clk = syscon_clk_register(NULL, "xgam_clk", "app_52_clk", 0, true,
+				  syscon_vbase + U300_SYSCON_RRR, 8,
+				  syscon_vbase + U300_SYSCON_CERR, 8,
+				  U300_SYSCON_SBCER_XGAM_CLK_EN);
+	clk_register_clkdev(clk, NULL, "xgam");
+	clk = syscon_clk_register(NULL, "semi_clk", "app_104_clk", 0, false,
+				  syscon_vbase + U300_SYSCON_RRR, 9,
+				  syscon_vbase + U300_SYSCON_CERR, 9,
+				  U300_SYSCON_SBCER_SEMI_CLK_EN);
+	clk_register_clkdev(clk, NULL, "semi");
+
+	/* AHB bridge clocks */
+	clk = syscon_clk_register(NULL, "ahb_subsys_clk", "app_52_clk", 0, true,
+				  syscon_vbase + U300_SYSCON_RRR, 10,
+				  syscon_vbase + U300_SYSCON_CERR, 10,
+				  U300_SYSCON_SBCER_AHB_SUBSYS_BRIDGE_CLK_EN);
+	clk = syscon_clk_register(NULL, "intcon_clk", "ahb_subsys_clk", 0, false,
+				  syscon_vbase + U300_SYSCON_RRR, 12,
+				  syscon_vbase + U300_SYSCON_CERR, 12,
+				  /* Cannot be enabled, just taken out of reset */
+				  0xFFFFU);
+	clk_register_clkdev(clk, NULL, "intcon");
+	clk = syscon_clk_register(NULL, "emif_clk", "ahb_subsys_clk", 0, false,
+				  syscon_vbase + U300_SYSCON_RRR, 5,
+				  syscon_vbase + U300_SYSCON_CERR, 5,
+				  U300_SYSCON_SBCER_EMIF_CLK_EN);
+	clk_register_clkdev(clk, NULL, "pl172");
+
+	/* FAST bridge clocks */
+	clk = syscon_clk_register(NULL, "fast_clk", "app_26_clk", 0, true,
+				  syscon_vbase + U300_SYSCON_RFR, 0,
+				  syscon_vbase + U300_SYSCON_CEFR, 0,
+				  U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN);
+	clk = syscon_clk_register(NULL, "i2c0_p_clk", "fast_clk", 0, false,
+				  syscon_vbase + U300_SYSCON_RFR, 1,
+				  syscon_vbase + U300_SYSCON_CEFR, 1,
+				  U300_SYSCON_SBCER_I2C0_CLK_EN);
+	clk_register_clkdev(clk, NULL, "stu300.0");
+	clk = syscon_clk_register(NULL, "i2c1_p_clk", "fast_clk", 0, false,
+				  syscon_vbase + U300_SYSCON_RFR, 2,
+				  syscon_vbase + U300_SYSCON_CEFR, 2,
+				  U300_SYSCON_SBCER_I2C1_CLK_EN);
+	clk_register_clkdev(clk, NULL, "stu300.1");
+	clk = syscon_clk_register(NULL, "mmc_p_clk", "fast_clk", 0, false,
+				  syscon_vbase + U300_SYSCON_RFR, 5,
+				  syscon_vbase + U300_SYSCON_CEFR, 5,
+				  U300_SYSCON_SBCER_MMC_CLK_EN);
+	clk_register_clkdev(clk, "apb_pclk", "mmci");
+	clk = syscon_clk_register(NULL, "spi_p_clk", "fast_clk", 0, false,
+				  syscon_vbase + U300_SYSCON_RFR, 6,
+				  syscon_vbase + U300_SYSCON_CEFR, 6,
+				  U300_SYSCON_SBCER_SPI_CLK_EN);
+	/* The SPI has no external clock for the outward bus, uses the pclk */
+	clk_register_clkdev(clk, NULL, "pl022");
+	clk_register_clkdev(clk, "apb_pclk", "pl022");
+
+	/* SLOW bridge clocks */
+	clk = syscon_clk_register(NULL, "slow_clk", "pll13", 0, true,
+				  syscon_vbase + U300_SYSCON_RSR, 0,
+				  syscon_vbase + U300_SYSCON_CESR, 0,
+				  U300_SYSCON_SBCER_SLOW_BRIDGE_CLK_EN);
+	clk = syscon_clk_register(NULL, "uart0_clk", "slow_clk", 0, false,
+				  syscon_vbase + U300_SYSCON_RSR, 1,
+				  syscon_vbase + U300_SYSCON_CESR, 1,
+				  U300_SYSCON_SBCER_UART_CLK_EN);
+	/* Same clock is used for APB and outward bus */
+	clk_register_clkdev(clk, NULL, "uart0");
+	clk_register_clkdev(clk, "apb_pclk", "uart0");
+	clk = syscon_clk_register(NULL, "gpio_clk", "slow_clk", 0, false,
+				  syscon_vbase + U300_SYSCON_RSR, 4,
+				  syscon_vbase + U300_SYSCON_CESR, 4,
+				  U300_SYSCON_SBCER_GPIO_CLK_EN);
+	clk_register_clkdev(clk, NULL, "u300-gpio");
+	clk = syscon_clk_register(NULL, "keypad_clk", "slow_clk", 0, false,
+				  syscon_vbase + U300_SYSCON_RSR, 5,
+				  syscon_vbase + U300_SYSCON_CESR, 6,
+				  U300_SYSCON_SBCER_KEYPAD_CLK_EN);
+	clk_register_clkdev(clk, NULL, "coh901461-keypad");
+	clk = syscon_clk_register(NULL, "rtc_clk", "slow_clk", 0, true,
+				  syscon_vbase + U300_SYSCON_RSR, 6,
+				  /* No clock enable register bit */
+				  NULL, 0, 0xFFFFU);
+	clk_register_clkdev(clk, NULL, "rtc-coh901331");
+	clk = syscon_clk_register(NULL, "app_tmr_clk", "slow_clk", 0, false,
+				  syscon_vbase + U300_SYSCON_RSR, 7,
+				  syscon_vbase + U300_SYSCON_CESR, 7,
+				  U300_SYSCON_SBCER_APP_TMR_CLK_EN);
+	clk_register_clkdev(clk, NULL, "apptimer");
+	clk = syscon_clk_register(NULL, "acc_tmr_clk", "slow_clk", 0, false,
+				  syscon_vbase + U300_SYSCON_RSR, 8,
+				  syscon_vbase + U300_SYSCON_CESR, 8,
+				  U300_SYSCON_SBCER_ACC_TMR_CLK_EN);
+	clk_register_clkdev(clk, NULL, "timer");
+
+	/* Then this special MMC/SD clock */
+	clk = mclk_clk_register(NULL, "mmc_clk", "mmc_p_clk", false);
+	clk_register_clkdev(clk, NULL, "mmci");
+}
diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c
new file mode 100644
index 0000000..e7b7765
--- /dev/null
+++ b/drivers/clk/clk-wm831x.c
@@ -0,0 +1,428 @@
+/*
+ * WM831x clock control
+ *
+ * Copyright 2011-2 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/wm831x/core.h>
+
+struct wm831x_clk {
+	struct wm831x *wm831x;
+	struct clk_hw xtal_hw;
+	struct clk_hw fll_hw;
+	struct clk_hw clkout_hw;
+	struct clk *xtal;
+	struct clk *fll;
+	struct clk *clkout;
+	bool xtal_ena;
+};
+
+static int wm831x_xtal_is_enabled(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  xtal_hw);
+
+	return clkdata->xtal_ena;
+}
+
+static unsigned long wm831x_xtal_recalc_rate(struct clk_hw *hw,
+					     unsigned long parent_rate)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  xtal_hw);
+
+	if (clkdata->xtal_ena)
+		return 32768;
+	else
+		return 0;
+}
+
+static const struct clk_ops wm831x_xtal_ops = {
+	.is_enabled = wm831x_xtal_is_enabled,
+	.recalc_rate = wm831x_xtal_recalc_rate,
+};
+
+static struct clk_init_data wm831x_xtal_init = {
+	.name = "xtal",
+	.ops = &wm831x_xtal_ops,
+	.flags = CLK_IS_ROOT,
+};
+
+static const unsigned long wm831x_fll_auto_rates[] = {
+	 2048000,
+	11289600,
+	12000000,
+	12288000,
+	19200000,
+	22579600,
+	24000000,
+	24576000,
+};
+
+static int wm831x_fll_is_enabled(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  fll_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	ret = wm831x_reg_read(wm831x, WM831X_FLL_CONTROL_1);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Unable to read FLL_CONTROL_1: %d\n",
+			ret);
+		return true;
+	}
+
+	return (ret & WM831X_FLL_ENA) != 0;
+}
+
+static int wm831x_fll_prepare(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  fll_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_2,
+			      WM831X_FLL_ENA, WM831X_FLL_ENA);
+	if (ret != 0)
+		dev_crit(wm831x->dev, "Failed to enable FLL: %d\n", ret);
+
+	usleep_range(2000, 2000);
+
+	return ret;
+}
+
+static void wm831x_fll_unprepare(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  fll_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_2, WM831X_FLL_ENA, 0);
+	if (ret != 0)
+		dev_crit(wm831x->dev, "Failed to disaable FLL: %d\n", ret);
+}
+
+static unsigned long wm831x_fll_recalc_rate(struct clk_hw *hw,
+					    unsigned long parent_rate)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  fll_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
+			ret);
+		return 0;
+	}
+
+	if (ret & WM831X_FLL_AUTO)
+		return wm831x_fll_auto_rates[ret & WM831X_FLL_AUTO_FREQ_MASK];
+
+	dev_err(wm831x->dev, "FLL only supported in AUTO mode\n");
+
+	return 0;
+}
+
+static long wm831x_fll_round_rate(struct clk_hw *hw, unsigned long rate,
+				  unsigned long *unused)
+{
+	int best = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(wm831x_fll_auto_rates); i++)
+		if (abs(wm831x_fll_auto_rates[i] - rate) <
+		    abs(wm831x_fll_auto_rates[best] - rate))
+			best = i;
+
+	return wm831x_fll_auto_rates[best];
+}
+
+static int wm831x_fll_set_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long parent_rate)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  fll_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(wm831x_fll_auto_rates); i++)
+		if (wm831x_fll_auto_rates[i] == rate)
+			break;
+	if (i == ARRAY_SIZE(wm831x_fll_auto_rates))
+		return -EINVAL;
+
+	if (wm831x_fll_is_enabled(hw))
+		return -EPERM;
+
+	return wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_2,
+			       WM831X_FLL_AUTO_FREQ_MASK, i);
+}
+
+static const char *wm831x_fll_parents[] = {
+	"xtal",
+	"clkin",
+};
+
+static u8 wm831x_fll_get_parent(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  fll_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	/* AUTO mode is always clocked from the crystal */
+	ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
+			ret);
+		return 0;
+	}
+
+	if (ret & WM831X_FLL_AUTO)
+		return 0;
+
+	ret = wm831x_reg_read(wm831x, WM831X_FLL_CONTROL_5);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Unable to read FLL_CONTROL_5: %d\n",
+			ret);
+		return 0;
+	}
+
+	switch (ret & WM831X_FLL_CLK_SRC_MASK) {
+	case 0:
+		return 0;
+	case 1:
+		return 1;
+	default:
+		dev_err(wm831x->dev, "Unsupported FLL clock source %d\n",
+			ret & WM831X_FLL_CLK_SRC_MASK);
+		return 0;
+	}
+}
+
+static const struct clk_ops wm831x_fll_ops = {
+	.is_enabled = wm831x_fll_is_enabled,
+	.prepare = wm831x_fll_prepare,
+	.unprepare = wm831x_fll_unprepare,
+	.round_rate = wm831x_fll_round_rate,
+	.recalc_rate = wm831x_fll_recalc_rate,
+	.set_rate = wm831x_fll_set_rate,
+	.get_parent = wm831x_fll_get_parent,
+};
+
+static struct clk_init_data wm831x_fll_init = {
+	.name = "fll",
+	.ops = &wm831x_fll_ops,
+	.parent_names = wm831x_fll_parents,
+	.num_parents = ARRAY_SIZE(wm831x_fll_parents),
+	.flags = CLK_SET_RATE_GATE,
+};
+
+static int wm831x_clkout_is_enabled(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  clkout_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_1);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_1: %d\n",
+			ret);
+		return true;
+	}
+
+	return (ret & WM831X_CLKOUT_ENA) != 0;
+}
+
+static int wm831x_clkout_prepare(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  clkout_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	ret = wm831x_reg_unlock(wm831x);
+	if (ret != 0) {
+		dev_crit(wm831x->dev, "Failed to lock registers: %d\n", ret);
+		return ret;
+	}
+
+	ret = wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,
+			      WM831X_CLKOUT_ENA, WM831X_CLKOUT_ENA);
+	if (ret != 0)
+		dev_crit(wm831x->dev, "Failed to enable CLKOUT: %d\n", ret);
+
+	wm831x_reg_lock(wm831x);
+
+	return ret;
+}
+
+static void wm831x_clkout_unprepare(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  clkout_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	ret = wm831x_reg_unlock(wm831x);
+	if (ret != 0) {
+		dev_crit(wm831x->dev, "Failed to lock registers: %d\n", ret);
+		return;
+	}
+
+	ret = wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,
+			      WM831X_CLKOUT_ENA, 0);
+	if (ret != 0)
+		dev_crit(wm831x->dev, "Failed to disable CLKOUT: %d\n", ret);
+
+	wm831x_reg_lock(wm831x);
+}
+
+static const char *wm831x_clkout_parents[] = {
+	"xtal",
+	"fll",
+};
+
+static u8 wm831x_clkout_get_parent(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  clkout_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_1);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_1: %d\n",
+			ret);
+		return 0;
+	}
+
+	if (ret & WM831X_CLKOUT_SRC)
+		return 0;
+	else
+		return 1;
+}
+
+static int wm831x_clkout_set_parent(struct clk_hw *hw, u8 parent)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  clkout_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+
+	return wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,
+			       WM831X_CLKOUT_SRC,
+			       parent << WM831X_CLKOUT_SRC_SHIFT);
+}
+
+static const struct clk_ops wm831x_clkout_ops = {
+	.is_enabled = wm831x_clkout_is_enabled,
+	.prepare = wm831x_clkout_prepare,
+	.unprepare = wm831x_clkout_unprepare,
+	.get_parent = wm831x_clkout_get_parent,
+	.set_parent = wm831x_clkout_set_parent,
+};
+
+static struct clk_init_data wm831x_clkout_init = {
+	.name = "clkout",
+	.ops = &wm831x_clkout_ops,
+	.parent_names = wm831x_clkout_parents,
+	.num_parents = ARRAY_SIZE(wm831x_clkout_parents),
+	.flags = CLK_SET_RATE_PARENT,
+};
+
+static __devinit int wm831x_clk_probe(struct platform_device *pdev)
+{
+	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+	struct wm831x_clk *clkdata;
+	int ret;
+
+	clkdata = devm_kzalloc(&pdev->dev, sizeof(*clkdata), GFP_KERNEL);
+	if (!clkdata)
+		return -ENOMEM;
+
+	/* XTAL_ENA can only be set via OTP/InstantConfig so just read once */
+	ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
+			ret);
+		return ret;
+	}
+	clkdata->xtal_ena = ret & WM831X_XTAL_ENA;
+
+	clkdata->xtal_hw.init = &wm831x_xtal_init;
+	clkdata->xtal = clk_register(&pdev->dev, &clkdata->xtal_hw);
+	if (!clkdata->xtal)
+		return -EINVAL;
+
+	clkdata->fll_hw.init = &wm831x_fll_init;
+	clkdata->fll = clk_register(&pdev->dev, &clkdata->fll_hw);
+	if (!clkdata->fll) {
+		ret = -EINVAL;
+		goto err_xtal;
+	}
+
+	clkdata->clkout_hw.init = &wm831x_clkout_init;
+	clkdata->clkout = clk_register(&pdev->dev, &clkdata->clkout_hw);
+	if (!clkdata->clkout) {
+		ret = -EINVAL;
+		goto err_fll;
+	}
+
+	dev_set_drvdata(&pdev->dev, clkdata);
+
+	return 0;
+
+err_fll:
+	clk_unregister(clkdata->fll);
+err_xtal:
+	clk_unregister(clkdata->xtal);
+	return ret;
+}
+
+static int __devexit wm831x_clk_remove(struct platform_device *pdev)
+{
+	struct wm831x_clk *clkdata = dev_get_drvdata(&pdev->dev);
+
+	clk_unregister(clkdata->clkout);
+	clk_unregister(clkdata->fll);
+	clk_unregister(clkdata->xtal);
+
+	return 0;
+}
+
+static struct platform_driver wm831x_clk_driver = {
+	.probe = wm831x_clk_probe,
+	.remove = __devexit_p(wm831x_clk_remove),
+	.driver		= {
+		.name	= "wm831x-clk",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(wm831x_clk_driver);
+
+/* Module information */
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("WM831x clock driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm831x-clk");
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 9a1eb0c..c87fdd7 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -16,6 +16,7 @@
 #include <linux/err.h>
 #include <linux/list.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 
 static DEFINE_SPINLOCK(enable_lock);
 static DEFINE_MUTEX(prepare_lock);
@@ -1235,8 +1236,8 @@
 	 * If clk->parents is not NULL we skip this entire block.  This allows
 	 * for clock drivers to statically initialize clk->parents.
 	 */
-	if (clk->num_parents && !clk->parents) {
-		clk->parents = kmalloc((sizeof(struct clk*) * clk->num_parents),
+	if (clk->num_parents > 1 && !clk->parents) {
+		clk->parents = kzalloc((sizeof(struct clk*) * clk->num_parents),
 				GFP_KERNEL);
 		/*
 		 * __clk_lookup returns NULL for parents that have not been
@@ -1550,3 +1551,142 @@
 	return ret;
 }
 EXPORT_SYMBOL_GPL(clk_notifier_unregister);
+
+#ifdef CONFIG_OF
+/**
+ * struct of_clk_provider - Clock provider registration structure
+ * @link: Entry in global list of clock providers
+ * @node: Pointer to device tree node of clock provider
+ * @get: Get clock callback.  Returns NULL or a struct clk for the
+ *       given clock specifier
+ * @data: context pointer to be passed into @get callback
+ */
+struct of_clk_provider {
+	struct list_head link;
+
+	struct device_node *node;
+	struct clk *(*get)(struct of_phandle_args *clkspec, void *data);
+	void *data;
+};
+
+static LIST_HEAD(of_clk_providers);
+static DEFINE_MUTEX(of_clk_lock);
+
+struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
+				     void *data)
+{
+	return data;
+}
+EXPORT_SYMBOL_GPL(of_clk_src_simple_get);
+
+/**
+ * of_clk_add_provider() - Register a clock provider for a node
+ * @np: Device node pointer associated with clock provider
+ * @clk_src_get: callback for decoding clock
+ * @data: context pointer for @clk_src_get callback.
+ */
+int of_clk_add_provider(struct device_node *np,
+			struct clk *(*clk_src_get)(struct of_phandle_args *clkspec,
+						   void *data),
+			void *data)
+{
+	struct of_clk_provider *cp;
+
+	cp = kzalloc(sizeof(struct of_clk_provider), GFP_KERNEL);
+	if (!cp)
+		return -ENOMEM;
+
+	cp->node = of_node_get(np);
+	cp->data = data;
+	cp->get = clk_src_get;
+
+	mutex_lock(&of_clk_lock);
+	list_add(&cp->link, &of_clk_providers);
+	mutex_unlock(&of_clk_lock);
+	pr_debug("Added clock from %s\n", np->full_name);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_clk_add_provider);
+
+/**
+ * of_clk_del_provider() - Remove a previously registered clock provider
+ * @np: Device node pointer associated with clock provider
+ */
+void of_clk_del_provider(struct device_node *np)
+{
+	struct of_clk_provider *cp;
+
+	mutex_lock(&of_clk_lock);
+	list_for_each_entry(cp, &of_clk_providers, link) {
+		if (cp->node == np) {
+			list_del(&cp->link);
+			of_node_put(cp->node);
+			kfree(cp);
+			break;
+		}
+	}
+	mutex_unlock(&of_clk_lock);
+}
+EXPORT_SYMBOL_GPL(of_clk_del_provider);
+
+struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec)
+{
+	struct of_clk_provider *provider;
+	struct clk *clk = ERR_PTR(-ENOENT);
+
+	/* Check if we have such a provider in our array */
+	mutex_lock(&of_clk_lock);
+	list_for_each_entry(provider, &of_clk_providers, link) {
+		if (provider->node == clkspec->np)
+			clk = provider->get(clkspec, provider->data);
+		if (!IS_ERR(clk))
+			break;
+	}
+	mutex_unlock(&of_clk_lock);
+
+	return clk;
+}
+
+const char *of_clk_get_parent_name(struct device_node *np, int index)
+{
+	struct of_phandle_args clkspec;
+	const char *clk_name;
+	int rc;
+
+	if (index < 0)
+		return NULL;
+
+	rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
+					&clkspec);
+	if (rc)
+		return NULL;
+
+	if (of_property_read_string_index(clkspec.np, "clock-output-names",
+					  clkspec.args_count ? clkspec.args[0] : 0,
+					  &clk_name) < 0)
+		clk_name = clkspec.np->name;
+
+	of_node_put(clkspec.np);
+	return clk_name;
+}
+EXPORT_SYMBOL_GPL(of_clk_get_parent_name);
+
+/**
+ * of_clk_init() - Scan and init clock providers from the DT
+ * @matches: array of compatible values and init functions for providers.
+ *
+ * This function scans the device tree for matching clock providers and
+ * calls their initialization functions
+ */
+void __init of_clk_init(const struct of_device_id *matches)
+{
+	struct device_node *np;
+
+	for_each_matching_node(np, matches) {
+		const struct of_device_id *match = of_match_node(matches, np);
+		of_clk_init_cb_t clk_init_cb = match->data;
+		clk_init_cb(np);
+	}
+}
+#endif
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index c535cf8..d423c9b 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -19,10 +19,80 @@
 #include <linux/mutex.h>
 #include <linux/clk.h>
 #include <linux/clkdev.h>
+#include <linux/of.h>
 
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
 
+#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
+struct clk *of_clk_get(struct device_node *np, int index)
+{
+	struct of_phandle_args clkspec;
+	struct clk *clk;
+	int rc;
+
+	if (index < 0)
+		return ERR_PTR(-EINVAL);
+
+	rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
+					&clkspec);
+	if (rc)
+		return ERR_PTR(rc);
+
+	clk = of_clk_get_from_provider(&clkspec);
+	of_node_put(clkspec.np);
+	return clk;
+}
+EXPORT_SYMBOL(of_clk_get);
+
+/**
+ * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node
+ * @np: pointer to clock consumer node
+ * @name: name of consumer's clock input, or NULL for the first clock reference
+ *
+ * This function parses the clocks and clock-names properties,
+ * and uses them to look up the struct clk from the registered list of clock
+ * providers.
+ */
+struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
+{
+	struct clk *clk = ERR_PTR(-ENOENT);
+
+	/* Walk up the tree of devices looking for a clock that matches */
+	while (np) {
+		int index = 0;
+
+		/*
+		 * For named clocks, first look up the name in the
+		 * "clock-names" property.  If it cannot be found, then
+		 * index will be an error code, and of_clk_get() will fail.
+		 */
+		if (name)
+			index = of_property_match_string(np, "clock-names", name);
+		clk = of_clk_get(np, index);
+		if (!IS_ERR(clk))
+			break;
+		else if (name && index >= 0) {
+			pr_err("ERROR: could not get clock %s:%s(%i)\n",
+				np->full_name, name ? name : "", index);
+			return clk;
+		}
+
+		/*
+		 * No matching clock found on this node.  If the parent node
+		 * has a "clock-ranges" property, then we can try one of its
+		 * clocks.
+		 */
+		np = np->parent;
+		if (np && !of_get_property(np, "clock-ranges", NULL))
+			break;
+	}
+
+	return clk;
+}
+EXPORT_SYMBOL(of_clk_get_by_name);
+#endif
+
 /*
  * Find the correct struct clk for the device and connection ID.
  * We do slightly fuzzy matching here:
@@ -83,6 +153,13 @@
 struct clk *clk_get(struct device *dev, const char *con_id)
 {
 	const char *dev_id = dev ? dev_name(dev) : NULL;
+	struct clk *clk;
+
+	if (dev) {
+		clk = of_clk_get_by_name(dev->of_node, con_id);
+		if (!IS_ERR(clk) && __clk_get(clk))
+			return clk;
+	}
 
 	return clk_get_sys(dev_id, con_id);
 }
diff --git a/drivers/clk/mxs/clk-imx23.c b/drivers/clk/mxs/clk-imx23.c
index db2391c..844043a 100644
--- a/drivers/clk/mxs/clk-imx23.c
+++ b/drivers/clk/mxs/clk-imx23.c
@@ -106,7 +106,7 @@
 
 static struct clk_lookup gpmi_lookups[] = {
 	{ .dev_id = "imx23-gpmi-nand", },
-	{ .dev_id = "8000c000.gpmi", },
+	{ .dev_id = "8000c000.gpmi-nand", },
 };
 
 static const char *sel_pll[]  __initconst = { "pll", "ref_xtal", };
@@ -189,6 +189,7 @@
 		}
 
 	clk_register_clkdev(clks[clk32k], NULL, "timrot");
+	clk_register_clkdev(clks[pwm], NULL, "80064000.pwm");
 	clk_register_clkdevs(clks[hbus], hbus_lookups, ARRAY_SIZE(hbus_lookups));
 	clk_register_clkdevs(clks[xbus], xbus_lookups, ARRAY_SIZE(xbus_lookups));
 	clk_register_clkdevs(clks[uart], uart_lookups, ARRAY_SIZE(uart_lookups));
diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c
index 7fad6c8..e3aab67 100644
--- a/drivers/clk/mxs/clk-imx28.c
+++ b/drivers/clk/mxs/clk-imx28.c
@@ -112,11 +112,11 @@
 
 	/*
 	 * 480 MHz seems too high to be ssp clock source directly,
-	 * so set frac0 to get a 288 MHz ref_io0.
+	 * so set frac0 to get a 288 MHz ref_io0 and ref_io1.
 	 */
 	val = readl_relaxed(FRAC0);
-	val &= ~(0x3f << BP_FRAC0_IO0FRAC);
-	val |= 30 << BP_FRAC0_IO0FRAC;
+	val &= ~((0x3f << BP_FRAC0_IO0FRAC) | (0x3f << BP_FRAC0_IO1FRAC));
+	val |= (30 << BP_FRAC0_IO0FRAC) | (30 << BP_FRAC0_IO1FRAC);
 	writel_relaxed(val, FRAC0);
 }
 
@@ -174,7 +174,7 @@
 
 static struct clk_lookup gpmi_lookups[] = {
 	{ .dev_id = "imx28-gpmi-nand", },
-	{ .dev_id = "8000c000.gpmi", },
+	{ .dev_id = "8000c000.gpmi-nand", },
 };
 
 static struct clk_lookup fec_lookups[] = {
@@ -314,6 +314,7 @@
 
 	clk_register_clkdev(clks[clk32k], NULL, "timrot");
 	clk_register_clkdev(clks[enet_out], NULL, "enet_out");
+	clk_register_clkdev(clks[pwm], NULL, "80064000.pwm");
 	clk_register_clkdevs(clks[hbus], hbus_lookups, ARRAY_SIZE(hbus_lookups));
 	clk_register_clkdevs(clks[xbus], xbus_lookups, ARRAY_SIZE(xbus_lookups));
 	clk_register_clkdevs(clks[uart], uart_lookups, ARRAY_SIZE(uart_lookups));
@@ -328,6 +329,10 @@
 	clk_register_clkdevs(clks[fec], fec_lookups, ARRAY_SIZE(fec_lookups));
 	clk_register_clkdevs(clks[can0], can0_lookups, ARRAY_SIZE(can0_lookups));
 	clk_register_clkdevs(clks[can1], can1_lookups, ARRAY_SIZE(can1_lookups));
+	clk_register_clkdev(clks[usb0_pwr], NULL, "8007c000.usbphy");
+	clk_register_clkdev(clks[usb1_pwr], NULL, "8007e000.usbphy");
+	clk_register_clkdev(clks[usb0], NULL, "80080000.usb");
+	clk_register_clkdev(clks[usb1], NULL, "80090000.usb");
 
 	for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
 		clk_prepare_enable(clks[clks_init_on[i]]);
diff --git a/drivers/clk/versatile/Makefile b/drivers/clk/versatile/Makefile
new file mode 100644
index 0000000..50cf6a2
--- /dev/null
+++ b/drivers/clk/versatile/Makefile
@@ -0,0 +1,3 @@
+# Makefile for Versatile-specific clocks
+obj-$(CONFIG_ICST)		+= clk-icst.o
+obj-$(CONFIG_ARCH_INTEGRATOR)	+= clk-integrator.o
diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c
new file mode 100644
index 0000000..f555b50
--- /dev/null
+++ b/drivers/clk/versatile/clk-icst.c
@@ -0,0 +1,100 @@
+/*
+ * Driver for the ICST307 VCO clock found in the ARM Reference designs.
+ * We wrap the custom interface from <asm/hardware/icst.h> into the generic
+ * clock framework.
+ *
+ * TODO: when all ARM reference designs are migrated to generic clocks, the
+ * ICST clock code from the ARM tree should probably be merged into this
+ * file.
+ */
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/clk-provider.h>
+
+#include "clk-icst.h"
+
+/**
+ * struct clk_icst - ICST VCO clock wrapper
+ * @hw: corresponding clock hardware entry
+ * @params: parameters for this ICST instance
+ * @rate: current rate
+ * @setvco: function to commit ICST settings to hardware
+ */
+struct clk_icst {
+	struct clk_hw hw;
+	const struct icst_params *params;
+	unsigned long rate;
+	struct icst_vco (*getvco)(void);
+	void (*setvco)(struct icst_vco);
+};
+
+#define to_icst(_hw) container_of(_hw, struct clk_icst, hw)
+
+static unsigned long icst_recalc_rate(struct clk_hw *hw,
+				      unsigned long parent_rate)
+{
+	struct clk_icst *icst = to_icst(hw);
+	struct icst_vco vco;
+
+	vco = icst->getvco();
+	icst->rate = icst_hz(icst->params, vco);
+	return icst->rate;
+}
+
+static long icst_round_rate(struct clk_hw *hw, unsigned long rate,
+			    unsigned long *prate)
+{
+	struct clk_icst *icst = to_icst(hw);
+	struct icst_vco vco;
+
+	vco = icst_hz_to_vco(icst->params, rate);
+	return icst_hz(icst->params, vco);
+}
+
+static int icst_set_rate(struct clk_hw *hw, unsigned long rate,
+			 unsigned long parent_rate)
+{
+	struct clk_icst *icst = to_icst(hw);
+	struct icst_vco vco;
+
+	vco = icst_hz_to_vco(icst->params, rate);
+	icst->rate = icst_hz(icst->params, vco);
+	icst->setvco(vco);
+	return 0;
+}
+
+static const struct clk_ops icst_ops = {
+	.recalc_rate = icst_recalc_rate,
+	.round_rate = icst_round_rate,
+	.set_rate = icst_set_rate,
+};
+
+struct clk * __init icst_clk_register(struct device *dev,
+				      const struct clk_icst_desc *desc)
+{
+	struct clk *clk;
+	struct clk_icst *icst;
+	struct clk_init_data init;
+
+	icst = kzalloc(sizeof(struct clk_icst), GFP_KERNEL);
+	if (!icst) {
+		pr_err("could not allocate ICST clock!\n");
+		return ERR_PTR(-ENOMEM);
+	}
+	init.name = "icst";
+	init.ops = &icst_ops;
+	init.flags = CLK_IS_ROOT;
+	init.parent_names = NULL;
+	init.num_parents = 0;
+	icst->hw.init = &init;
+	icst->params = desc->params;
+	icst->getvco = desc->getvco;
+	icst->setvco = desc->setvco;
+
+	clk = clk_register(dev, &icst->hw);
+	if (IS_ERR(clk))
+		kfree(icst);
+
+	return clk;
+}
diff --git a/drivers/clk/versatile/clk-icst.h b/drivers/clk/versatile/clk-icst.h
new file mode 100644
index 0000000..71b4c56
--- /dev/null
+++ b/drivers/clk/versatile/clk-icst.h
@@ -0,0 +1,10 @@
+#include <asm/hardware/icst.h>
+
+struct clk_icst_desc {
+	const struct icst_params *params;
+	struct icst_vco (*getvco)(void);
+	void (*setvco)(struct icst_vco);
+};
+
+struct clk *icst_clk_register(struct device *dev,
+			      const struct clk_icst_desc *desc);
diff --git a/drivers/clk/versatile/clk-integrator.c b/drivers/clk/versatile/clk-integrator.c
new file mode 100644
index 0000000..a505392
--- /dev/null
+++ b/drivers/clk/versatile/clk-integrator.c
@@ -0,0 +1,111 @@
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+
+#include "clk-icst.h"
+
+/*
+ * Implementation of the ARM Integrator/AP and Integrator/CP clock tree.
+ * Inspired by portions of:
+ * plat-versatile/clock.c and plat-versatile/include/plat/clock.h
+ */
+#define CM_LOCK		(__io_address(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET)
+#define CM_AUXOSC	(__io_address(INTEGRATOR_HDR_BASE)+0x1c)
+
+/**
+ * cp_auxvco_get() - get ICST VCO settings for the Integrator/CP
+ * @vco: ICST VCO parameters to update with hardware status
+ */
+static struct icst_vco cp_auxvco_get(void)
+{
+	u32 val;
+	struct icst_vco vco;
+
+	val = readl(CM_AUXOSC);
+	vco.v = val & 0x1ff;
+	vco.r = (val >> 9) & 0x7f;
+	vco.s = (val >> 16) & 03;
+	return vco;
+}
+
+/**
+ * cp_auxvco_set() - commit changes to Integrator/CP ICST VCO
+ * @vco: ICST VCO parameters to commit
+ */
+static void cp_auxvco_set(struct icst_vco vco)
+{
+	u32 val;
+
+	val = readl(CM_AUXOSC) & ~0x7ffff;
+	val |= vco.v | (vco.r << 9) | (vco.s << 16);
+
+	/* This magic unlocks the CM VCO so it can be controlled */
+	writel(0xa05f, CM_LOCK);
+	writel(val, CM_AUXOSC);
+	/* This locks the CM again */
+	writel(0, CM_LOCK);
+}
+
+static const struct icst_params cp_auxvco_params = {
+	.ref		= 24000000,
+	.vco_max	= ICST525_VCO_MAX_5V,
+	.vco_min	= ICST525_VCO_MIN,
+	.vd_min 	= 8,
+	.vd_max 	= 263,
+	.rd_min 	= 3,
+	.rd_max 	= 65,
+	.s2div		= icst525_s2div,
+	.idx2s		= icst525_idx2s,
+};
+
+static const struct clk_icst_desc __initdata cp_icst_desc = {
+	.params = &cp_auxvco_params,
+	.getvco = cp_auxvco_get,
+	.setvco = cp_auxvco_set,
+};
+
+/*
+ * integrator_clk_init() - set up the integrator clock tree
+ * @is_cp: pass true if it's the Integrator/CP else AP is assumed
+ */
+void __init integrator_clk_init(bool is_cp)
+{
+	struct clk *clk;
+
+	/* APB clock dummy */
+	clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
+	clk_register_clkdev(clk, "apb_pclk", NULL);
+
+	/* UART reference clock */
+	clk = clk_register_fixed_rate(NULL, "uartclk", NULL, CLK_IS_ROOT,
+				14745600);
+	clk_register_clkdev(clk, NULL, "uart0");
+	clk_register_clkdev(clk, NULL, "uart1");
+	if (is_cp)
+		clk_register_clkdev(clk, NULL, "mmci");
+
+	/* 24 MHz clock */
+	clk = clk_register_fixed_rate(NULL, "clk24mhz", NULL, CLK_IS_ROOT,
+				24000000);
+	clk_register_clkdev(clk, NULL, "kmi0");
+	clk_register_clkdev(clk, NULL, "kmi1");
+	if (!is_cp)
+		clk_register_clkdev(clk, NULL, "ap_timer");
+
+	if (!is_cp)
+		return;
+
+	/* 1 MHz clock */
+	clk = clk_register_fixed_rate(NULL, "clk1mhz", NULL, CLK_IS_ROOT,
+				1000000);
+	clk_register_clkdev(clk, NULL, "sp804");
+
+	/* ICST VCO clock used on the Integrator/CP CLCD */
+	clk = icst_clk_register(NULL, &cp_icst_desc);
+	clk_register_clkdev(clk, NULL, "clcd");
+}
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index eb3f84b..9c7f580 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -64,7 +64,7 @@
 		.parent_names = _parent_names,			\
 		.num_parents = ARRAY_SIZE(_parent_names),	\
 		.parents = _parents,				\
-		.flags = _flags,				\
+		.flags = _flags | CLK_IS_BASIC,			\
 	}
 
 #define DEFINE_CLK_FIXED_RATE(_name, _flags, _rate,		\
@@ -103,9 +103,9 @@
 	DEFINE_CLK(_name, clk_gate_ops, _flags,			\
 			_name##_parent_names, _name##_parents);
 
-#define DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr,	\
+#define _DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr,	\
 				_flags, _reg, _shift, _width,	\
-				_divider_flags, _lock)		\
+				_divider_flags, _table, _lock)	\
 	static struct clk _name;				\
 	static const char *_name##_parent_names[] = {		\
 		_parent_name,					\
@@ -121,11 +121,27 @@
 		.shift = _shift,				\
 		.width = _width,				\
 		.flags = _divider_flags,			\
+		.table = _table,				\
 		.lock = _lock,					\
 	};							\
 	DEFINE_CLK(_name, clk_divider_ops, _flags,		\
 			_name##_parent_names, _name##_parents);
 
+#define DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr,	\
+				_flags, _reg, _shift, _width,	\
+				_divider_flags, _lock)		\
+	_DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr,	\
+				_flags, _reg, _shift, _width,	\
+				_divider_flags, NULL, _lock)
+
+#define DEFINE_CLK_DIVIDER_TABLE(_name, _parent_name,		\
+				_parent_ptr, _flags, _reg,	\
+				_shift, _width, _divider_flags,	\
+				_table, _lock)			\
+	_DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr,	\
+				_flags, _reg, _shift, _width,	\
+				_divider_flags, _table, _lock)	\
+
 #define DEFINE_CLK_MUX(_name, _parent_names, _parents, _flags,	\
 				_reg, _shift, _width,		\
 				_mux_flags, _lock)		\
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 4a0b483..77335fa 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -25,6 +25,7 @@
 #define CLK_SET_RATE_PARENT	BIT(2) /* propagate rate change up one level */
 #define CLK_IGNORE_UNUSED	BIT(3) /* do not gate even if unused */
 #define CLK_IS_ROOT		BIT(4) /* root clk, has no parent */
+#define CLK_IS_BASIC		BIT(5) /* Basic clk, can't do a to_clk_foo() */
 
 struct clk_hw;
 
@@ -143,7 +144,7 @@
  */
 struct clk_hw {
 	struct clk *clk;
-	struct clk_init_data *init;
+	const struct clk_init_data *init;
 };
 
 /*
@@ -171,6 +172,8 @@
 		const char *parent_name, unsigned long flags,
 		unsigned long fixed_rate);
 
+void of_fixed_clk_setup(struct device_node *np);
+
 /**
  * struct clk_gate - gating clock
  *
@@ -203,6 +206,11 @@
 		void __iomem *reg, u8 bit_idx,
 		u8 clk_gate_flags, spinlock_t *lock);
 
+struct clk_div_table {
+	unsigned int	val;
+	unsigned int	div;
+};
+
 /**
  * struct clk_divider - adjustable divider clock
  *
@@ -210,6 +218,7 @@
  * @reg:	register containing the divider
  * @shift:	shift to the divider bit field
  * @width:	width of the divider bit field
+ * @table:	array of value/divider pairs, last entry should have div = 0
  * @lock:	register lock
  *
  * Clock with an adjustable divider affecting its output frequency.  Implements
@@ -229,6 +238,7 @@
 	u8		shift;
 	u8		width;
 	u8		flags;
+	const struct clk_div_table	*table;
 	spinlock_t	*lock;
 };
 
@@ -240,6 +250,11 @@
 		const char *parent_name, unsigned long flags,
 		void __iomem *reg, u8 shift, u8 width,
 		u8 clk_divider_flags, spinlock_t *lock);
+struct clk *clk_register_divider_table(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 shift, u8 width,
+		u8 clk_divider_flags, const struct clk_div_table *table,
+		spinlock_t *lock);
 
 /**
  * struct clk_mux - multiplexer clock
@@ -334,5 +349,19 @@
 void __clk_reparent(struct clk *clk, struct clk *new_parent);
 unsigned long __clk_round_rate(struct clk *clk, unsigned long rate);
 
+struct of_device_id;
+
+typedef void (*of_clk_init_cb_t)(struct device_node *);
+
+int of_clk_add_provider(struct device_node *np,
+			struct clk *(*clk_src_get)(struct of_phandle_args *args,
+						   void *data),
+			void *data);
+void of_clk_del_provider(struct device_node *np);
+struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
+				  void *data);
+const char *of_clk_get_parent_name(struct device_node *np, int index);
+void of_clk_init(const struct of_device_id *matches);
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
diff --git a/include/linux/clk.h b/include/linux/clk.h
index f6fb40c..2fd6a42 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -12,6 +12,7 @@
 #ifndef __LINUX_CLK_H
 #define __LINUX_CLK_H
 
+#include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/notifier.h>
 
@@ -310,4 +311,23 @@
 int clk_add_alias(const char *alias, const char *alias_dev_name, char *id,
 			struct device *dev);
 
+struct device_node;
+struct of_phandle_args;
+
+#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
+struct clk *of_clk_get(struct device_node *np, int index);
+struct clk *of_clk_get_by_name(struct device_node *np, const char *name);
+struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec);
+#else
+static inline struct clk *of_clk_get(struct device_node *np, int index)
+{
+	return ERR_PTR(-ENOENT);
+}
+static inline struct clk *of_clk_get_by_name(struct device_node *np,
+					     const char *name)
+{
+	return ERR_PTR(-ENOENT);
+}
+#endif
+
 #endif
diff --git a/include/linux/platform_data/clk-integrator.h b/include/linux/platform_data/clk-integrator.h
new file mode 100644
index 0000000..83fe9c2
--- /dev/null
+++ b/include/linux/platform_data/clk-integrator.h
@@ -0,0 +1 @@
+void integrator_clk_init(bool is_cp);
diff --git a/include/linux/platform_data/clk-u300.h b/include/linux/platform_data/clk-u300.h
new file mode 100644
index 0000000..8429e73
--- /dev/null
+++ b/include/linux/platform_data/clk-u300.h
@@ -0,0 +1 @@
+void __init u300_clk_init(void __iomem *base);