Merge branches 'tz1090_8250_tolerance', 'tz1090_clk_specified', 'tz1090_clks' (early part), 'tz1090_metag' (early part) and 'img_wdt_fixes' into tmp

$ git merge tz1090_8250_tolerance tz1090_clk_specified tz1090_clks~2 tz1090_metag~ img_wdt_fixes
diff --git a/Documentation/devicetree/bindings/clock/img,tz1090-hep-cr.txt b/Documentation/devicetree/bindings/clock/img,tz1090-hep-cr.txt
new file mode 100644
index 0000000..79a3f7a
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/img,tz1090-hep-cr.txt
@@ -0,0 +1,53 @@
+Binding for TZ1090 High end peripheral clocks.
+
+This binding uses the common clock binding[1]. It represents the clocks
+controlled from the high end peripheral registers of the TZ1090:
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible         : Shall be "img,tz1090-hep-cr", "syscon".
+- #clock-cells       : From common clock binding; shall be set to 1.
+- reg                : Base address for clock registers in high end peripheral
+                       register region.
+- clocks             : Clock specifiers for each input clock.
+- clock-names        : Labels for each input clock specified in clocks.
+                       Can contain the following entries:
+                       "sys"              : Main system clock.
+                       "sys_x2_undeleted" : System clock before division and
+                                            deletion.
+
+Optional properties:
+- clock-indices      : From common clock binding. Allows clock-output-names to
+                       be sparse.
+- clock-output-names : From common clock binding. May be used to name specific
+                       output clocks so that other clock providers can find
+                       the clocks by name before the provider has been
+                       instantiated. Can contain:
+                       "sys_2d", "ddr_en", "sys_pdp"
+
+Clock Specifier Definition:
+- <1st-cell>: Output clock number. Use constants from
+              <dt-bindings/clock/tz1090-hep.h>.
+
+Examples:
+	hep_cr: hep_cr {
+		compatible = "img,tz1090-hep-cr", "syscon";
+		#clock-cells = <1>;
+		reg = <0x02008c00 0x08>;
+		/* input clocks */
+		clocks = <&top_clks CLK_TOP_SYS>,
+			 <&top_clks CLK_TOP_SYS_X2_UNDELETED>;
+		clock-names = "sys",
+			      "sys_x2_undeleted";
+		/* output clocks for other clock providers */
+		clock-indices = <CLK_HEP_DDR_EN>;
+		clock-output-names = "ddr_en";
+	};
+
+	pdp {
+		...
+		clocks = <&hep_cr CLK_HEP_PDP>;
+		clock-names = "pdp";
+		...
+	};
diff --git a/Documentation/devicetree/bindings/clock/img,tz1090-pdc-cr.txt b/Documentation/devicetree/bindings/clock/img,tz1090-pdc-cr.txt
new file mode 100644
index 0000000..37d36d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/img,tz1090-pdc-cr.txt
@@ -0,0 +1,59 @@
+Binding for TZ1090 PDC clocks.
+
+This binding uses the common clock binding[1]. It represents the clocks
+required to generate the 32KHz PDC clock used by the devices in the low power
+domain:
+
+          ___________
+xtal1 ___| xtal1_div |____________________________
+         |___________|  |    ________   xtal1_div
+                        `--o| rtc_sw \____________
+xtal3 ----------------------|________/  32khz
+
+xtal1_div = xtal1 / (reg[26:16] + 1)
+xtal3 = reg[30] ? xtal3 : xtal1_div
+
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible         : Shall be "img,tz1090-pdc-cr", "syscon".
+- #clock-cells       : From common clock binding; shall be set to 1.
+- reg                : Base address for registers controlling PDC clocks.
+- clocks             : Clock specifiers for each input clock.
+- clock-names        : Labels for each input clock specified in clocks.
+                       Can contain the following entries:
+                       "xtal1" : XTAL1 oscillator.
+                       "xtal3" : XTAL3 32KHz oscillator.
+
+Optional properties:
+- clock-indices      : From common clock binding. Allows clock-output-names to
+                       be sparse.
+- clock-output-names : From common clock binding. May be used to name specific
+                       output clocks so that other clock providers can find
+                       the clocks by name before the provider has been
+                       instantiated. Can contain:
+                       "32khz"     : 32khz PDC clock.
+
+Clock Specifier Definition:
+- <1st-cell>: Output clock number. Use constants from
+              <dt-bindings/clock/tz1090-pdc.h>.
+
+Examples:
+	pdc_cr: pdc_cr {
+		compatible = "img,tz1090-pdc-cr", "syscon";
+		#clock-cells = <1>;
+		reg = <0x02006500 0x4>;	/* SOC_GPIO_CONTROL0 */
+		clocks = <&xtal1>,
+			 <&xtal3>;
+		clock-names = "xtal1",
+			      "xtal3";
+	};
+
+	ir {
+		...
+		clocks = <&pdc_cr CLK_PDC_32KHZ>,
+			 <&top_cr CLK_TOP_PDC>;
+		clock-names = "core", "sys";
+		...
+	};
diff --git a/Documentation/devicetree/bindings/clock/img,tz1090-perip-cr.txt b/Documentation/devicetree/bindings/clock/img,tz1090-perip-cr.txt
new file mode 100644
index 0000000..f9c293d
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/img,tz1090-perip-cr.txt
@@ -0,0 +1,49 @@
+Binding for TZ1090 Peripheral register clocks.
+
+This binding uses the common clock binding[1]. It represents the clocks
+controlled from the peripheral registers of the TZ1090:
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible         : Shall be "img,tz1090-perip-cr", "syscon".
+- #clock-cells       : From common clock binding; shall be set to 1.
+- reg                : Base address for clock registers in peripheral register
+                       region.
+- clocks             : Clock specifiers for each input clock.
+- clock-names        : Labels for each input clock specified in clocks.
+                       Can contain the following entries:
+                       "sys" : Main system clock.
+
+Optional properties:
+- clock-indices      : From common clock binding. Allows clock-output-names to
+                       be sparse.
+- clock-output-names : From common clock binding. May be used to name specific
+                       output clocks so that other clock providers can find
+                       the clocks by name before the provider has been
+                       instantiated. Can contain:
+                       "sys_scb0", "sys_scb1", "sys_scb2", "sys_sdio",
+                       "sys_uart0", "sys_uart1", "sys_spim", "sys_spis",
+                       "sys_spim1", "sys_i2sout", "sys_i2sin", "sys_lcd",
+                       "sys_sdhost", "sys_usb"
+
+Clock Specifier Definition:
+- <1st-cell>: Output clock number. Use constants from
+              <dt-bindings/clock/tz1090-perip.h>.
+
+Examples:
+	perip_cr: perip_cr {
+		compatible = "img,tz1090-perip-cr", "syscon";
+		#clock-cells = <1>;
+		reg = <0x02004000 0x18>;
+		clocks = <&top_cr CLK_TOP_SYS>;
+		clock-names = "sys";
+	};
+
+	i2c {
+		...
+		clocks = <&top_cr CLK_TOP_SCB>,
+			 <&perip_cr CLK_PERIP_SCB0>;
+		clock-names = "scb", "sys";
+		...
+	};
diff --git a/Documentation/devicetree/bindings/clock/img,tz1090-top-cr.txt b/Documentation/devicetree/bindings/clock/img,tz1090-top-cr.txt
new file mode 100644
index 0000000..6c4f0b7
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/img,tz1090-top-cr.txt
@@ -0,0 +1,68 @@
+Binding for TZ1090 Top level register clocks.
+
+This binding uses the common clock binding[1]. It represents the clocks
+controlled from the top level registers of the TZ1090, and encompasses most of
+the complexity of the TZ1090 clock tree:
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible         : Shall be "img,tz1090-top-cr", "syscon".
+- #clock-cells       : From common clock binding; shall be set to 1.
+- reg                : Base address for clock registers in top level register
+                       region.
+- clocks             : Clock specifiers for each input clock.
+- clock-names        : Labels for each input clock specified in clocks.
+                       Can contain the following entries:
+                       "xtal1"        : XTAL1 oscillator.
+                       "xtal3"        : XTAL2 oscillator.
+                       "ext_adc_dac"  : External ADC/DAC clock input.
+                       "ddr_en"       : Output of HEP DDR clock gate.
+                       "afe_progdiv1",
+                       "afe_progdiv3",
+                       "afe_rxsync",
+                       "afe_txsync",
+                       "iqadc_sync"   : Output clocks from AFE block.
+
+Optional properties:
+- clock-indices      : From common clock binding. Allows clock-output-names to
+                       be sparse.
+- clock-output-names : From common clock binding. May be used to name specific
+                       output clocks so that other clock providers can find
+                       the clocks by name before the provider has been
+                       instantiated. Can contain:
+                       "sys", "sys_x2_undeleted" "scb", "ext_stc0", "ext_stc1",
+                       "if1", "if0", "sys_ucc1", "sys_mtx", "meta", "ucc0",
+                       "ucc1_del", "sys_undeleted", "afe", "adcpll_div", "uart",
+                       "pdm", "spi0", "spi1", "i2sm", "usb_phy", "sdhost",
+                       "ring_osc", "i2s", "meta_trace", "pixel", "out0", "out1",
+                       "ddr", "sys_pll", "sys_pdc"
+
+Clock Specifier Definition:
+- <1st-cell>: Output clock number. Use constants from
+              <dt-bindings/clock/tz1090-top.h>.
+
+Examples:
+	top_cr: top_cr {
+		compatible = "img,tz1090-top-cr", "syscon";
+		#clock-cells = <1>;
+		reg = <0x02005900 0xb0>;
+		/* input clocks */
+		clocks = <&xtal1>, <&xtal2>, <&ext_adc_dac>,
+			 <&hep_cr CLK_HEP_DDR_EN>;
+		clock-names = "xtal1", "xtal2", "ext_adc_dac",
+			      "ddr_en";
+		/* output clocks for other clock providers */
+		clock-indices = <CLK_TOP_SYS>,
+				<CLK_TOP_SYS_X2_UNDELETED>;
+		clock-output-names = "sys",
+				     "sys_x2_undeleted";
+	};
+
+	ir {
+		...
+		clocks = <&pdc_cr CLK_PDC_32KHZ>,
+			 <&top_cr CLK_TOP_PDC>;
+		clock-names = "core", "sys";
+		...
+	};
diff --git a/Documentation/devicetree/bindings/clock/specified-clock.txt b/Documentation/devicetree/bindings/clock/specified-clock.txt
new file mode 100644
index 0000000..7135adda
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/specified-clock.txt
@@ -0,0 +1,62 @@
+Binding for discoverable-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 "specified-clock".
+- #clock-cells : from common clock binding; shall be set to 0.
+- bit-mask : Mask of bits in the field specifying the frequency.
+- table : array of integer pairs defining register field values and
+          corresponding clock frequencies in Hz.
+
+Optional properties:
+- reg : Base address of configuration register specifying the frequency.
+- syscon-reg : Phandle to syscon node and offset of syscon register.
+- bit-shift : Number of bits to shift the masked register value.
+              Defaults to (ffs(bit-mask) - 1) if absent.
+- clock-accuracy : accuracy of clock in ppb (parts per billion).
+                   Should be a single cell.
+- clock-output-names : From common clock binding.
+
+NOTE: One of reg or syscon-reg must be provided.
+
+Examples:
+	clock {
+		compatible = "specified-clock";
+		#clock-cells = <0>;
+		reg = <0x02004004 0x4>;		/* CR_PERIP_RESET_CFG */
+		bit-mask = <0x00000f00>;	/* FXTAL */
+		table =	/*	FXTAL	Frequency */
+				<0	16384000>,
+				<1	19200000>,
+				<2	24000000>,
+				<3	24576000>,
+				<4	26000000>,
+				<5	36000000>,
+				<6	36864000>,
+				<7	38400000>,
+				<8	40000000>;
+		clock-accuracy = <100>;
+		clock-output-names = "xtal1";
+	};
+
+	clock {
+		compatible = "specified-clock";
+		#clock-cells = <0>;
+		syscon-reg = <&perip_cr 0x4>;	/* CR_PERIP_RESET_CFG */
+		bit-mask = <0x00000f00>;	/* FXTAL */
+		table =	/*	FXTAL	Frequency */
+				<0	16384000>,
+				<1	19200000>,
+				<2	24000000>,
+				<3	24576000>,
+				<4	26000000>,
+				<5	36000000>,
+				<6	36864000>,
+				<7	38400000>,
+				<8	40000000>;
+		clock-accuracy = <100>;
+		clock-output-names = "xtal1";
+	};
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index d478ceb..7262958 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -65,6 +65,7 @@
 obj-$(CONFIG_ARCH_STI)			+= st/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
 obj-$(CONFIG_ARCH_TEGRA)		+= tegra/
+obj-$(CONFIG_SOC_TZ1090)		+= tz1090/
 obj-$(CONFIG_ARCH_OMAP2PLUS)		+= ti/
 obj-$(CONFIG_ARCH_U8500)		+= ux500/
 obj-$(CONFIG_COMMON_CLK_VERSATILE)	+= versatile/
diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c
index 0fc56ab..c76241b 100644
--- a/drivers/clk/clk-fixed-rate.c
+++ b/drivers/clk/clk-fixed-rate.c
@@ -9,12 +9,16 @@
  * Fixed rate clock implementation
  */
 
+#include <linux/bitops.h>
 #include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/regmap.h>
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 
 /*
  * DOC: basic fixed-rate clock that cannot gate
@@ -134,4 +138,90 @@
 }
 EXPORT_SYMBOL_GPL(of_fixed_clk_setup);
 CLK_OF_DECLARE(fixed_clk, "fixed-clock", of_fixed_clk_setup);
+
+/**
+ * of_specified_clk_read() - Read the register specifying the clock rate.
+ * @node:	Device tree node.
+ * @reg_val:	Output pointer to write register value.
+ *
+ * Returns:	0 on success, -errno on failure.
+ */
+static int of_specified_clk_read(struct device_node *node, u32 *reg_val)
+{
+	void __iomem *reg;
+	struct regmap *syscon;
+	int ret;
+	u32 offset;
+
+	/* First try iomapping and reading the configuration register */
+	reg = of_iomap(node, 0);
+	if (reg) {
+		*reg_val = readl(reg);
+		iounmap(reg);
+		return 0;
+	}
+
+	/* Next look for a syscon phandle */
+	syscon = syscon_regmap_lookup_by_phandle(node, "syscon-reg");
+	if (IS_ERR(syscon))
+		return PTR_ERR(syscon);
+
+	/* Get the register offset from the second element */
+	ret = of_property_read_u32_index(node, "syscon-reg", 1, &offset);
+	if (ret)
+		return ret;
+
+	/* Read the register value */
+	return regmap_read(syscon, offset, reg_val);
+}
+
+/**
+ * of_specified_clk_setup() - Setup function for discoverable fixed rate clock.
+ * @node:	Device tree node.
+ */
+void of_specified_clk_setup(struct device_node *node)
+{
+	struct clk *clk;
+	const char *clk_name = node->name;
+	u32 shift, mask, rate, reg_val, val;
+	u32 accuracy = 0;
+	struct property *prop;
+	const __be32 *p;
+
+	/* Read the register value specifying the clock rate */
+	if (of_specified_clk_read(node, &reg_val))
+		return;
+
+	/* Apply bit-mask */
+	if (of_property_read_u32(node, "bit-mask", &mask))
+		return;
+	reg_val &= mask;
+	/* Apply bit-shift */
+	if (of_property_read_u32(node, "bit-shift", &shift))
+		shift = ffs(mask) - 1;
+	reg_val >>= shift;
+
+	/* Look through the mapping for a matching frequency */
+	of_property_for_each_u32(node, "table", prop, p, val) {
+		p = of_prop_next_u32(prop, p, &rate);
+		if (!p)
+			break;
+		if (val == reg_val)
+			goto found_rate;
+	}
+	/* No match found */
+	return;
+found_rate:
+	of_property_read_u32(node, "clock-accuracy", &accuracy);
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
+	clk = clk_register_fixed_rate_with_accuracy(NULL, clk_name, NULL,
+						    CLK_IS_ROOT, rate,
+						    accuracy);
+	if (!IS_ERR(clk))
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+EXPORT_SYMBOL_GPL(of_specified_clk_setup);
+CLK_OF_DECLARE(specified_clk, "specified-clock", of_specified_clk_setup);
 #endif
diff --git a/drivers/clk/tz1090/Makefile b/drivers/clk/tz1090/Makefile
new file mode 100644
index 0000000..1df6b8a
--- /dev/null
+++ b/drivers/clk/tz1090/Makefile
@@ -0,0 +1,13 @@
+# Makefile for TZ1090-specific clocks
+obj-y		+= clk.o
+
+obj-y		+= clk-tz1090-deleter.o
+obj-y		+= clk-tz1090-divider.o
+obj-y		+= clk-tz1090-gate-bank.o
+obj-y		+= clk-tz1090-mux-bank.o
+obj-y		+= clk-tz1090-pll.o
+
+obj-y		+= clk-tz1090-hep.o
+obj-y		+= clk-tz1090-pdc.o
+obj-y		+= clk-tz1090-perip.o
+obj-y		+= clk-tz1090-top.o
diff --git a/drivers/clk/tz1090/clk-tz1090-deleter.c b/drivers/clk/tz1090/clk-tz1090-deleter.c
new file mode 100644
index 0000000..9ec604d
--- /dev/null
+++ b/drivers/clk/tz1090/clk-tz1090-deleter.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2012-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Clock deleter in TZ1090
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+#include "clk.h"
+
+/**
+ * struct tz1090_clk_deleter_priv - Clock deleter
+ *
+ * @hw:		handle between common and hardware-specific interfaces
+ * @reg:	delete register
+ * @period:	cycle period
+ * @mask:	bit mask of delete field
+ * @shift:	start bit of delete field
+ *
+ * Deleter in TZ1090, allowing up to period-1 out of each period cycles to be
+ * deleted.
+ */
+struct tz1090_clk_deleter_priv {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+	u32		period;
+	u32		mask;
+	u8		shift;
+};
+
+#define to_tz1090_clk_deleter(_hw) \
+	container_of(_hw, struct tz1090_clk_deleter_priv, hw)
+
+static unsigned long tz1090_clk_deleter_recalc_rate(struct clk_hw *hw,
+						    unsigned long parent_rate)
+{
+	struct tz1090_clk_deleter_priv *deleter = to_tz1090_clk_deleter(hw);
+	u32 delete;
+	u64 rate;
+
+	delete = (readl(deleter->reg) & deleter->mask) >> deleter->shift;
+	rate = (u64)parent_rate * (deleter->period - delete);
+	do_div(rate, deleter->period);
+	return rate;
+}
+
+static const struct clk_ops tz1090_clk_deleter_ops = {
+	.recalc_rate = tz1090_clk_deleter_recalc_rate,
+};
+
+/**
+ * __register_deleter() - register a clock deleter
+ * @name:		name of this clock
+ * @parent_name:	name of clock's parent
+ * @flags:		framework-specific flags
+ * @reg:		register address to adjust deleter
+ * @period:		delete cycle period
+ * @mask:		mask of delete field
+ * @shift:		start bit of delete field
+ *
+ * Register a TZ1090 clock deleter with the clock framework.
+ */
+static struct clk *__init __register_deleter(const char *name,
+					     const char *parent_name,
+					     unsigned long flags,
+					     void __iomem *reg,
+					     u32 period,
+					     u32 mask,
+					     u8 shift)
+{
+	struct tz1090_clk_deleter_priv *deleter;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/* allocate the deleter */
+	deleter = kzalloc(sizeof(struct tz1090_clk_deleter_priv), GFP_KERNEL);
+	if (!deleter)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &tz1090_clk_deleter_ops;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	/* struct tz1090_clk_deleter_priv assignments */
+	deleter->reg = reg;
+	deleter->period = period;
+	deleter->mask = mask;
+	deleter->shift = shift;
+	deleter->hw.init = &init;
+
+	/* register the clock */
+	clk = clk_register(NULL, &deleter->hw);
+
+	if (IS_ERR(clk))
+		kfree(deleter);
+
+	return clk;
+}
+
+/**
+ * tz1090_clk_register_deleters() - Register set of deleters with a provider.
+ * @p:		TZ1090 clock provider.
+ * @deleters:	Array of deleter descriptions.
+ * @count	Number of deleters described in the array.
+ */
+void __init tz1090_clk_register_deleters(struct tz1090_clk_provider *p,
+				const struct tz1090_clk_deleter *deleters,
+				unsigned int count)
+{
+	const struct tz1090_clk_deleter *del;
+	struct clk *clk;
+	unsigned int i;
+
+	for (del = deleters, i = 0; i < count; ++del, ++i) {
+		clk = __register_deleter(tz1090_clk_xlate(p, del->name),
+					 tz1090_clk_xlate(p, del->parent), 0,
+					 p->base + del->reg, 1024, 0x3ff, 0);
+		p->clk_data.clks[del->id] = clk;
+	}
+}
diff --git a/drivers/clk/tz1090/clk-tz1090-divider.c b/drivers/clk/tz1090/clk-tz1090-divider.c
new file mode 100644
index 0000000..22db67d
--- /dev/null
+++ b/drivers/clk/tz1090/clk-tz1090-divider.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2013-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ *
+ * TZ1090 Divider Clock.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <asm/global_lock.h>
+
+#include "clk.h"
+
+/**
+ * struct tz1090_clk_div_priv - tz1090 divider clock
+ *
+ * @div:	the parent class
+ * @ops:	pointer to clk_ops of parent class
+ *
+ * Divider clock whose field shares a register with other fields which may be
+ * used by multiple threads/cores and other drivers.
+ */
+struct tz1090_clk_div_priv {
+	struct clk_divider	div;
+	const struct clk_ops	*ops;
+};
+
+static inline struct tz1090_clk_div_priv *to_tz1090_clk_div(struct clk_hw *hw)
+{
+	struct clk_divider *div = container_of(hw, struct clk_divider, hw);
+
+	return container_of(div, struct tz1090_clk_div_priv, div);
+}
+
+static unsigned long tz1090_clk_divider_recalc_rate(struct clk_hw *hw,
+						    unsigned long parent_rate)
+{
+	struct tz1090_clk_div_priv *div = to_tz1090_clk_div(hw);
+
+	return div->ops->recalc_rate(&div->div.hw, parent_rate);
+}
+
+static long tz1090_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
+					  unsigned long *prate)
+{
+	struct tz1090_clk_div_priv *div = to_tz1090_clk_div(hw);
+
+	return div->ops->round_rate(&div->div.hw, rate, prate);
+}
+
+/* Acquire exclusive lock since other cores may access the same register */
+static int tz1090_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
+				       unsigned long parent_rate)
+{
+	struct tz1090_clk_div_priv *div = to_tz1090_clk_div(hw);
+	int ret;
+	unsigned long flags;
+
+	__global_lock2(flags);
+	ret = div->ops->set_rate(&div->div.hw, rate, parent_rate);
+	__global_unlock2(flags);
+
+	return ret;
+}
+
+static const struct clk_ops tz1090_clk_div_ops = {
+	.recalc_rate	= tz1090_clk_divider_recalc_rate,
+	.round_rate	= tz1090_clk_divider_round_rate,
+	.set_rate	= tz1090_clk_divider_set_rate,
+};
+
+static struct clk *__init __register_divider(const char *name,
+					     const char *parent_name,
+					     unsigned long flags,
+					     void __iomem *reg, u8 shift,
+					     u8 width, u8 clk_divider_flags)
+{
+	struct tz1090_clk_div_priv *div;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/* allocate the divider */
+	div = kzalloc(sizeof(struct tz1090_clk_div_priv), GFP_KERNEL);
+	if (!div)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &tz1090_clk_div_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->div.reg = reg;
+	div->div.shift = shift;
+	div->div.width = width;
+	div->div.flags = clk_divider_flags;
+	div->div.hw.init = &init;
+
+	/* struct tz1090_clk_div_priv assignments */
+	div->ops = &clk_divider_ops;
+
+	/* register the clock */
+	clk = clk_register(NULL, &div->div.hw);
+
+	if (IS_ERR(clk))
+		kfree(div);
+
+	return clk;
+}
+
+/**
+ * tz1090_clk_register_dividers() - Register set of dividers with a provider.
+ * @p:		TZ1090 clock provider.
+ * @dividers:	Array of divider descriptions.
+ * @count	Number of dividers described in the array.
+ */
+void __init tz1090_clk_register_dividers(struct tz1090_clk_provider *p,
+				const struct tz1090_clk_divider *dividers,
+				unsigned int count)
+{
+	const struct tz1090_clk_divider *div;
+	struct clk *clk;
+	unsigned int i;
+
+	for (div = dividers, i = 0; i < count; ++div, ++i) {
+		/*
+		 * Dividers in registers shared between OSes must protect the
+		 * register with a global lock. Others with dedicated registers
+		 * can just use a normal divider.
+		 */
+		if (div->shared)
+			clk = __register_divider(tz1090_clk_xlate(p, div->name),
+					tz1090_clk_xlate(p, div->parent),
+					div->flags, p->base + div->reg,
+					div->shift, div->width, div->div_flags);
+		else
+			clk = clk_register_divider(NULL,
+					tz1090_clk_xlate(p, div->name),
+					tz1090_clk_xlate(p, div->parent),
+					div->flags, p->base + div->reg,
+					div->shift, div->width, div->div_flags,
+					NULL);
+		p->clk_data.clks[div->id] = clk;
+	}
+}
diff --git a/drivers/clk/tz1090/clk-tz1090-gate-bank.c b/drivers/clk/tz1090/clk-tz1090-gate-bank.c
new file mode 100644
index 0000000..5834afd
--- /dev/null
+++ b/drivers/clk/tz1090/clk-tz1090-gate-bank.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2013-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ *
+ * TZ1090 Clock gate bank
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <asm/global_lock.h>
+
+#include "clk.h"
+
+/**
+ * struct tz1090_clk_gate_priv - tz1090 gating clock
+ *
+ * @mux:	the parent class
+ * @ops:	pointer to clk_ops of parent class
+ *
+ * Clock which can gate its output. Extends basic mux by using a global
+ * exclusive lock when read-modify-writing the mux field so that multiple
+ * threads/cores can use different fields in the same register.
+ */
+struct tz1090_clk_gate_priv {
+	struct clk_gate		gate;
+	const struct clk_ops	*ops;
+};
+
+static inline struct tz1090_clk_gate_priv *to_tz1090_clk_gate(struct clk_hw *hw)
+{
+	struct clk_gate *gate = container_of(hw, struct clk_gate, hw);
+
+	return container_of(gate, struct tz1090_clk_gate_priv, gate);
+}
+
+/* Acquire exclusive lock since other cores may access the same register */
+static int tz1090_clk_gate_enable(struct clk_hw *hw)
+{
+	struct tz1090_clk_gate_priv *gate = to_tz1090_clk_gate(hw);
+	int ret;
+	unsigned long flags;
+
+	__global_lock2(flags);
+	ret = gate->ops->enable(&gate->gate.hw);
+	__global_unlock2(flags);
+
+	return ret;
+}
+
+/* Acquire exclusive lock since other cores may access the same register */
+static void tz1090_clk_gate_disable(struct clk_hw *hw)
+{
+	struct tz1090_clk_gate_priv *gate = to_tz1090_clk_gate(hw);
+	unsigned long flags;
+
+	__global_lock2(flags);
+	gate->ops->disable(&gate->gate.hw);
+	__global_unlock2(flags);
+}
+
+static int tz1090_clk_gate_is_enabled(struct clk_hw *hw)
+{
+	struct tz1090_clk_gate_priv *gate = to_tz1090_clk_gate(hw);
+
+	return gate->ops->is_enabled(&gate->gate.hw);
+}
+
+static const struct clk_ops tz1090_clk_gate_ops = {
+	.enable = tz1090_clk_gate_enable,
+	.disable = tz1090_clk_gate_disable,
+	.is_enabled = tz1090_clk_gate_is_enabled,
+};
+
+/**
+ * __register_gate() - register a TZ1090 gate clock with clock framework.
+ * @name: name of this clock
+ * @parent_name: name of this clock's parent
+ * @flags: framework-specific flags for this clock
+ * @reg: register address to control gating of this clock
+ * @bit_idx: which bit in the register controls gating of this clock
+ * @clk_gate_flags: gate-specific flags for this clock
+ */
+static struct clk *__init __register_gate(const char *name,
+					  const char *parent_name,
+					  unsigned long flags,
+					  void __iomem *reg,
+					  u8 bit_idx,
+					  u8 clk_gate_flags)
+{
+	struct tz1090_clk_gate_priv *gate;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/* allocate the gate */
+	gate = kzalloc(sizeof(struct tz1090_clk_gate_priv), GFP_KERNEL);
+	if (!gate)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &tz1090_clk_gate_ops;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	/* struct clk_gate assignments */
+	gate->gate.reg = reg;
+	gate->gate.bit_idx = bit_idx;
+	gate->gate.flags = clk_gate_flags;
+	gate->gate.hw.init = &init;
+
+	/* struct tz1090_clk_gate_priv assignments */
+	gate->ops = &clk_gate_ops;
+
+	clk = clk_register(NULL, &gate->gate.hw);
+
+	if (IS_ERR(clk))
+		kfree(gate);
+
+	return clk;
+}
+
+/**
+ * tz1090_clk_register_gate_bank() - Register bank of gates with a provider.
+ * @p:		TZ1090 clock provider.
+ * @bank:	Data describing gate bank.
+ */
+void __init tz1090_clk_register_gate_bank(struct tz1090_clk_provider *p,
+					const struct tz1090_clk_gate_bank *bank)
+{
+	const struct tz1090_clk_gate *gate;
+	struct clk *clk;
+	unsigned int id = bank->id_base;
+
+	for (gate = bank->gates; gate->name; ++gate, ++id) {
+		clk = __register_gate(tz1090_clk_xlate(p, gate->name),
+				      tz1090_clk_xlate(p, gate->parent),
+				      CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT,
+				      p->base + bank->reg_base, gate->shift, 0);
+		p->clk_data.clks[id] = clk;
+	}
+}
diff --git a/drivers/clk/tz1090/clk-tz1090-hep.c b/drivers/clk/tz1090/clk-tz1090-hep.c
new file mode 100644
index 0000000..0aa8dc1
--- /dev/null
+++ b/drivers/clk/tz1090/clk-tz1090-hep.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2013-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ *
+ * TZ1090 High End Peripheral (HEP) Clocks
+ */
+
+#include <dt-bindings/clock/tz1090-hep.h>
+
+#include "clk.h"
+
+/* Register offsets into high end peripheral memory region */
+#define HEP_CLK_EN		0x04
+
+/*
+ *                      CR_HEP_CLK_EN
+ *                      =============
+ *
+ * sys              -+--[ 2d_en      ]--- 0 sys_2d
+ * sys_x2_undeleted -|--[ ddr_en     ]--- 1 ddr_en
+ * sys               `--[ pdp_pdi_en ]--- 2 sys_pdp
+ */
+GATE_BANK(tz1090_hep_clken, 0, HEP_CLK_EN,
+	/*   bit in			out	*/
+	GATE( 0, "@sys",		"sys_2d")
+	GATE( 1, "@sys_x2_undeleted",	"ddr_en")
+	GATE( 2, "@sys",		"sys_pdp")
+	/* bits 3..31 unused */
+);
+
+static void __init tz1090_hep_cr_init(struct device_node *np)
+{
+	struct tz1090_clk_provider *p;
+
+	p = tz1090_clk_alloc_provider(np, CLK_HEP_MAX);
+	if (!p)
+		return;
+
+	tz1090_clk_register_gate_bank(p, &tz1090_hep_clken);
+
+	tz1090_clk_register_provider(p);
+}
+CLK_OF_DECLARE(tz1090_hep_cr, "img,tz1090-hep-cr", tz1090_hep_cr_init);
diff --git a/drivers/clk/tz1090/clk-tz1090-mux-bank.c b/drivers/clk/tz1090/clk-tz1090-mux-bank.c
new file mode 100644
index 0000000..bdfb243
--- /dev/null
+++ b/drivers/clk/tz1090/clk-tz1090-mux-bank.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2013-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ *
+ * TZ1090 Clock mux bank
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <asm/global_lock.h>
+
+#include "clk.h"
+
+/**
+ * struct tz1090_clk_mux_priv - tz1090 multiplexer clock
+ *
+ * @mux:	the parent class
+ * @ops:	pointer to clk_ops of parent class
+ *
+ * Clock with multiple selectable parents. Extends basic mux by using a global
+ * exclusive lock when read-modify-writing the mux field so that multiple
+ * threads/cores can use different fields in the same register.
+ */
+struct tz1090_clk_mux_priv {
+	struct clk_mux		mux;
+	const struct clk_ops	*ops;
+};
+
+static inline struct tz1090_clk_mux_priv *to_tz1090_clk_mux(struct clk_hw *hw)
+{
+	struct clk_mux *mux = container_of(hw, struct clk_mux, hw);
+
+	return container_of(mux, struct tz1090_clk_mux_priv, mux);
+}
+
+static u8 tz1090_clk_mux_get_parent(struct clk_hw *hw)
+{
+	struct tz1090_clk_mux_priv *mux = to_tz1090_clk_mux(hw);
+
+	return mux->ops->get_parent(&mux->mux.hw);
+}
+
+/* Acquire exclusive lock since other cores may access the same register */
+static int tz1090_clk_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct tz1090_clk_mux_priv *mux = to_tz1090_clk_mux(hw);
+	int ret;
+	unsigned long flags;
+
+	__global_lock2(flags);
+	ret = mux->ops->set_parent(&mux->mux.hw, index);
+	__global_unlock2(flags);
+
+	return ret;
+}
+
+static long tz1090_clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
+					  unsigned long min_rate,
+					  unsigned long max_rate,
+					  unsigned long *prate,
+					  struct clk_hw **best_parent)
+{
+	struct tz1090_clk_mux_priv *mux = to_tz1090_clk_mux(hw);
+
+	return mux->ops->determine_rate(&mux->mux.hw, rate, min_rate, max_rate,
+					prate, best_parent);
+}
+
+static const struct clk_ops tz1090_clk_mux_ops = {
+	.get_parent = tz1090_clk_mux_get_parent,
+	.set_parent = tz1090_clk_mux_set_parent,
+	.determine_rate = tz1090_clk_mux_determine_rate,
+};
+
+static struct clk *__init __register_mux(const char *name,
+					 const char **parent_names,
+					 unsigned long flags, void __iomem *reg,
+					 u8 shift, u8 clk_mux_flags)
+{
+	struct tz1090_clk_mux_priv *mux;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/* allocate the mux */
+	mux = kzalloc(sizeof(struct tz1090_clk_mux_priv), GFP_KERNEL);
+	if (!mux)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &tz1090_clk_mux_ops;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = parent_names;
+	init.num_parents = 2;
+
+	/* struct clk_mux assignments */
+	mux->mux.reg = reg;
+	mux->mux.shift = shift;
+	mux->mux.mask = 0x1;
+	mux->mux.flags = clk_mux_flags;
+	mux->mux.hw.init = &init;
+
+	/* struct tz1090_clk_mux_priv assignments */
+	if (clk_mux_flags & CLK_MUX_READ_ONLY)
+		mux->ops = &clk_mux_ro_ops;
+	else
+		mux->ops = &clk_mux_ops;
+
+	clk = clk_register(NULL, &mux->mux.hw);
+
+	if (IS_ERR(clk))
+		kfree(mux);
+
+	return clk;
+}
+
+/**
+ * tz1090_clk_register_mux_bank() - Register bank of muxes with a provider.
+ * @p:		TZ1090 clock provider.
+ * @bank:	Data describing mux bank.
+ */
+void __init tz1090_clk_register_mux_bank(struct tz1090_clk_provider *p,
+					 const struct tz1090_clk_mux_bank *bank)
+{
+	const struct tz1090_clk_mux *mux;
+	struct clk *clk;
+	unsigned int id = bank->id_base;
+	const char *parents[2];
+	unsigned long flags;
+	u32 val;
+
+	for (mux = bank->muxes; mux->name; ++mux, ++id) {
+		if (mux->default_parent >= 0) {
+			__global_lock2(flags);
+			val = ioread32(p->base + bank->reg_base);
+			if (mux->default_parent)
+				val |= BIT(mux->shift);
+			else
+				val &= ~BIT(mux->shift);
+			iowrite32(val, p->base + bank->reg_base);
+			__global_unlock2(flags);
+		}
+
+		parents[0] = tz1090_clk_xlate(p, mux->parents[0]);
+		parents[1] = tz1090_clk_xlate(p, mux->parents[1]);
+		clk = __register_mux(tz1090_clk_xlate(p, mux->name), parents,
+				     CLK_SET_RATE_PARENT,
+				     p->base + bank->reg_base, mux->shift,
+				     mux->mux_flags);
+		p->clk_data.clks[id] = clk;
+	}
+}
diff --git a/drivers/clk/tz1090/clk-tz1090-pdc.c b/drivers/clk/tz1090/clk-tz1090-pdc.c
new file mode 100644
index 0000000..89789b4
--- /dev/null
+++ b/drivers/clk/tz1090/clk-tz1090-pdc.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2013-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ *
+ * TZ1090 PDC Clocks.
+ */
+
+#include <dt-bindings/clock/tz1090-pdc.h>
+
+#include "clk.h"
+
+/* Register offsets into PDC SoC region */
+#define PDC_SOC0		0x00
+
+/*
+ *                  SOC_GPIO_CONTROL 0
+ *                  ==================
+ *           ___________
+ * xtal1 ___| xtal1_div |____________________________
+ *          |___________|  |    ________   xtal1_div
+ *                         `--o| rtc_sw \____________
+ * xtal3 ----------------------|________/  32khz
+ */
+
+static const struct tz1090_clk_divider tz1090_pdc_dividers[] __initconst = {
+	/*         id                  in        out         reg  width shift */
+	DIV_SHARED(CLK_PDC_XTAL1_DIV, "@xtal1", "xtal1_div", PDC_SOC0, 11, 16),
+};
+
+MUX_BANK(tz1090_pdc_mux, CLK_PDC_32KHZ, PDC_SOC0,
+	/*  bit in[0]		 in[1]		out	*/
+	MUX(30, "xtal1_div",	 "@xtal3",	"32khz")
+);
+
+static void __init tz1090_pdc_cr_init(struct device_node *np)
+{
+	struct tz1090_clk_provider *p;
+
+	p = tz1090_clk_alloc_provider(np, CLK_PDC_MAX);
+	if (!p)
+		return;
+
+	tz1090_clk_register_dividers(p, tz1090_pdc_dividers,
+				     ARRAY_SIZE(tz1090_pdc_dividers));
+	tz1090_clk_register_mux_bank(p, &tz1090_pdc_mux);
+
+	tz1090_clk_register_provider(p);
+}
+CLK_OF_DECLARE(tz1090_pdc_cr, "img,tz1090-pdc-cr", tz1090_pdc_cr_init);
diff --git a/drivers/clk/tz1090/clk-tz1090-perip.c b/drivers/clk/tz1090/clk-tz1090-perip.c
new file mode 100644
index 0000000..ba7b2db
--- /dev/null
+++ b/drivers/clk/tz1090/clk-tz1090-perip.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2013-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ *
+ * TZ1090 Peripheral Clocks
+ */
+
+#include <dt-bindings/clock/tz1090-perip.h>
+
+#include "clk.h"
+
+/* Register offsets into peripheral memory region */
+#define PERIP_SRST		0x00
+#define PERIP_CLKEN		0x10
+#define PERIP_CLKSTATUS		0x14
+
+/*
+ *            CR_PERIP_CLKEN
+ *            ==============
+ *
+ * sys ---[CR_PERIP_*_SYS_CLK_EN]--- sys_*
+ */
+GATE_BANK(tz1090_perip_clken, 0, PERIP_CLKEN,
+	/*   bit in      out */
+	GATE( 0, "@sys", "sys_scb0")
+	GATE( 1, "@sys", "sys_scb1")
+	GATE( 2, "@sys", "sys_scb2")
+	GATE( 3, "@sys", "sys_sdio")
+	GATE( 4, "@sys", "sys_uart0")
+	GATE( 5, "@sys", "sys_uart1")
+	GATE( 6, "@sys", "sys_spim")
+	GATE( 7, "@sys", "sys_spis")
+	GATE( 8, "@sys", "sys_spim1")
+	GATE( 9, "@sys", "sys_i2sout")
+	GATE(10, "@sys", "sys_i2sin")
+	GATE(11, "@sys", "sys_lcd")
+	GATE(12, "@sys", "sys_sdhost")
+	GATE(13, "@sys", "sys_usb")
+	/* bits 14..31 unused */
+);
+
+static void __init tz1090_perip_cr_init(struct device_node *np)
+{
+	struct tz1090_clk_provider *p;
+
+	p = tz1090_clk_alloc_provider(np, CLK_PERIP_MAX);
+	if (!p)
+		return;
+
+	tz1090_clk_register_gate_bank(p, &tz1090_perip_clken);
+
+	tz1090_clk_register_provider(p);
+}
+CLK_OF_DECLARE(tz1090_perip_cr, "img,tz1090-perip-cr", tz1090_perip_cr_init);
diff --git a/drivers/clk/tz1090/clk-tz1090-pll.c b/drivers/clk/tz1090/clk-tz1090-pll.c
new file mode 100644
index 0000000..ca8260b
--- /dev/null
+++ b/drivers/clk/tz1090/clk-tz1090-pll.c
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ * Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org>
+ * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
+ * Copyright (C) 2013-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * True Circuits PLL in TZ1090 SoC.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include "clk.h"
+
+/* Register definitions */
+
+#define PLL_CTL0		0
+#define  PLL_CTL0_BWADJ_M		0xfff
+#define  PLL_CTL0_BWADJ_S		20
+#define  PLL_CTL0_CLKF_M		0x1fff
+#define  PLL_CTL0_CLKF_S		4
+#define  PLL_CTL0_CLKOD_M		0x7
+#define  PLL_CTL0_CLKOD_S		0
+#define PLL_CTL1		4
+#define  PLL_CTL1_RESET_B		BIT(28)
+#define  PLL_CTL1_FASTEN_B		BIT(27)
+#define  PLL_CTL1_ENSAT_B		BIT(26)
+#define  PLL_CTL1_BYPASS_B		BIT(25)
+#define  PLL_CTL1_PWRDN_B		BIT(24)
+#define  PLL_CTL1_CLKR_M		0x3f
+#define  PLL_CTL1_CLKR_S		0
+
+/**
+ * struct tz1090_clk_pll_priv - PLL in TZ1090
+ *
+ * @hw:		handle between common and hardware-specific interfaces
+ * @reg:	first of two registers
+ *
+ * PLL in TZ1090.
+ */
+struct tz1090_clk_pll_priv {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+};
+
+#define to_tz1090_clk_pll(_hw) container_of(_hw, struct tz1090_clk_pll_priv, hw)
+
+static unsigned long tz1090_clk_pll_recalc_rate(struct clk_hw *hw,
+						unsigned long f_in)
+{
+	struct tz1090_clk_pll_priv *pll = to_tz1090_clk_pll(hw);
+	u32 ctl0, ctl1;
+	unsigned int clk_f;	/* feedback divide */
+	unsigned int clk_od;	/* output divide */
+	unsigned int clk_r;	/* reference divide */
+	unsigned long f_out;
+
+	ctl0 = readl(pll->reg + PLL_CTL0);
+	ctl1 = readl(pll->reg + PLL_CTL1);
+
+	/* Bypass? */
+	if (ctl1 & PLL_CTL1_BYPASS_B)
+		return f_in;
+
+	/* Get divider values */
+	clk_f  = 1 + ((ctl0 >> PLL_CTL0_CLKF_S)  & PLL_CTL0_CLKF_M);
+	clk_od = 1 + ((ctl0 >> PLL_CTL0_CLKOD_S) & PLL_CTL0_CLKOD_M);
+	clk_r  = 1 + ((ctl1 >> PLL_CTL1_CLKR_S)  & PLL_CTL1_CLKR_M);
+
+	/*
+	 * formula:
+	 * f_out = (f_in / clk_r) * (clk_f / 2) / clk_od
+	 *       = (f_in * clk_f) / (2 * clk_r * clk_od)
+	 */
+	f_out = div_u64((u64)f_in * clk_f,
+			2 * clk_r * clk_od);
+	return f_out;
+}
+
+/* finds best pll parameters and returns rate on success (or 0) */
+static int tz1090_clk_pll_bestvals(struct clk_hw *hw, unsigned long parent_rate,
+				   unsigned long rate, unsigned long *clkf,
+				   unsigned long *clkr, unsigned long *clkod)
+{
+	unsigned long odmin, odmax;
+	unsigned long bestf = 1, bestr = 1, bestod = 1;
+	unsigned long rod2, cur, best = 0;
+	unsigned long f, r, od;
+
+	/* 120MHz/freq < od < 600MHz/freq */
+	odmin = 120000000/rate + 1;
+	odmax = 600000000/rate;
+
+	if (odmin < 1)
+		odmin = 1;
+	if (odmax > PLL_CTL0_CLKOD_M + 1)
+		odmax = PLL_CTL0_CLKOD_M + 1;
+
+	/*
+	 * Search through valid combinations of od and r, starting with lower
+	 * output divider values to get a lower intermediate frequency.
+	 */
+	for (od = odmin; od <= odmax; ++od) {
+		for (r = 1; r <= PLL_CTL1_CLKR_M + 1; ++r) {
+			/*
+			 * Calculate best f for given r and od, rounding down
+			 * So for f, freq <= rate
+			 * And for f+1, freq > rate
+			 * We have to do rate+1 because rate may have itself
+			 * been rounded down.
+			 */
+			rod2 = 2 * r * od;
+			f = div_u64((u64)(rate + 1) * rod2, parent_rate);
+			if (f < 1)
+				continue;
+			if (f > PLL_CTL0_CLKF_M + 1)
+				f = PLL_CTL0_CLKF_M + 1;
+
+			/* Calculate final rate and see if it's the best */
+			cur = div_u64((u64)parent_rate * f, rod2);
+			if (cur > best) {
+				bestf = f;
+				bestr = r;
+				bestod = od;
+				best = cur;
+				/* Can't improve on a perfect match */
+				if (cur == rate)
+					goto done;
+			}
+		}
+	}
+	if (!best)
+		return 0;
+done:
+	pr_debug("tz1090_clk_pll: final %lu/%lu * %lu/2/%lu=%lu (req=%lu, err=%ld)\n",
+		 parent_rate, bestr, bestf, bestod, best, rate, best - rate);
+
+	*clkf = bestf;
+	*clkr = bestr;
+	*clkod = bestod;
+	return best;
+}
+
+static long tz1090_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+				      unsigned long *prate)
+{
+	unsigned long clkf, clkr, clkod;
+	unsigned long parent_rate = *prate;
+
+	return tz1090_clk_pll_bestvals(hw, parent_rate, rate, &clkf, &clkr,
+				       &clkod);
+}
+
+static int tz1090_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+				   unsigned long parent_rate)
+{
+	struct tz1090_clk_pll_priv *pll = to_tz1090_clk_pll(hw);
+	unsigned long clkf, clkr, clkod, bwadj;
+	u32 ctl0, ctl1;
+
+	if (!tz1090_clk_pll_bestvals(hw, parent_rate, rate,
+				     &clkf, &clkr, &clkod))
+		return -EINVAL;
+
+	/* offset the values ready to go in the PLL registers */
+	--clkr;
+	--clkf;
+	--clkod;
+	bwadj = clkf / 2;
+
+	/* bypass, reset and configure PLL */
+	ctl0 =	(bwadj << PLL_CTL0_BWADJ_S) |
+		(clkf  << PLL_CTL0_CLKF_S)  |
+		(clkod << PLL_CTL0_CLKOD_S);
+	ctl1 =	PLL_CTL1_RESET_B  |
+		PLL_CTL1_ENSAT_B  |
+		PLL_CTL1_BYPASS_B |
+		(clkr  << PLL_CTL1_CLKR_S);
+	writel(ctl1, pll->reg + PLL_CTL1);
+	writel(ctl0, pll->reg + PLL_CTL0);
+
+	/* allow 5us after clkf before deasserting reset */
+	udelay(5);
+
+	/* take PLL out of reset and enable fasten */
+	ctl1 &= ~PLL_CTL1_RESET_B;
+	ctl1 |= PLL_CTL1_FASTEN_B;
+	writel(ctl1, pll->reg + PLL_CTL1);
+
+	/* count at least 500 divided ref clks to allow time to lock */
+	msleep(1 + 500*1000*(clkr+1)/parent_rate);
+
+	/* take PLL out of fasten / bypass */
+	ctl1 &= ~PLL_CTL1_FASTEN_B;
+	ctl1 &= ~PLL_CTL1_BYPASS_B;
+	writel(ctl1, pll->reg + PLL_CTL1);
+
+	return 0;
+}
+
+static const struct clk_ops tz1090_clk_pll_ops = {
+	.recalc_rate	= tz1090_clk_pll_recalc_rate,
+	.round_rate	= tz1090_clk_pll_round_rate,
+	.set_rate	= tz1090_clk_pll_set_rate,
+};
+
+/**
+ * __register_pll() - register a PLL with the clock framework
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @flags: framework-specific flags
+ * @reg: register address to adjust PLL
+ *
+ * Register a TZ1090 PLL clock to the clock framework.
+ */
+static struct clk *__init __register_pll(const char *name,
+					 const char *parent_name,
+					 unsigned long flags,
+					 void __iomem *reg)
+{
+	struct tz1090_clk_pll_priv *pll;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/* allocate the pll */
+	pll = kzalloc(sizeof(struct tz1090_clk_pll_priv), GFP_KERNEL);
+	if (!pll)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &tz1090_clk_pll_ops;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	/* struct tz1090_clk_pll_priv assignments */
+	pll->reg = reg;
+	pll->hw.init = &init;
+
+	/* register the clock */
+	clk = clk_register(NULL, &pll->hw);
+
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+/**
+ * tz1090_clk_register_plls() - Register set of PLLs with a provider.
+ * @p:		TZ1090 clock provider.
+ * @plls:	Array of PLL descriptions.
+ * @count	Number of PLLs described in the array.
+ */
+void __init tz1090_clk_register_plls(struct tz1090_clk_provider *p,
+				     const struct tz1090_clk_pll *plls,
+				     unsigned int count)
+{
+	const struct tz1090_clk_pll *pll;
+	struct clk *clk;
+	unsigned int i;
+
+	for (pll = plls, i = 0; i < count; ++pll, ++i) {
+		clk = __register_pll(tz1090_clk_xlate(p, pll->name),
+				     tz1090_clk_xlate(p, pll->parent), 0,
+				     p->base + pll->reg_base);
+		p->clk_data.clks[pll->id] = clk;
+	}
+}
diff --git a/drivers/clk/tz1090/clk-tz1090-top.c b/drivers/clk/tz1090/clk-tz1090-top.c
new file mode 100644
index 0000000..724c925
--- /dev/null
+++ b/drivers/clk/tz1090/clk-tz1090-top.c
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2013-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ *
+ * TZ1090 TOP Clocks
+ */
+
+#include <dt-bindings/clock/tz1090-top.h>
+
+#include "clk.h"
+
+/* Register offsets into top level memory region */
+#define TOP_CLKEN		0x00
+#define TOP_CLKSTATUS		0x04
+#define TOP_CLKSWITCH		0x08
+#define TOP_CLKENAB		0x0c
+#define TOP_CLKDELETE		0x10
+#define TOP_SYSCLK_DIV		0x14
+#define TOP_META_CLKDIV		0x18
+#define TOP_META_CLKDELETE	0x1c
+#define TOP_AFE_DIV		0x20
+#define TOP_ADCPLL_DIV		0x24
+#define TOP_UARTCLK_DIV		0x28
+#define TOP_PDMCK_CTL		0x30
+#define TOP_SPICLK_DIV		0x34
+#define TOP_SPI1CLK_DIV		0x38
+#define TOP_I2SCLK_DIV		0x3c
+#define TOP_USB_PLLDIV		0x40
+#define TOP_SDHOSTCLK_DIV	0x44
+#define TOP_RING_OP_DIV		0x48
+#define TOP_SYSPLL_CTL0		0x50
+#define TOP_ADCPLL_CTL0		0x58
+#define TOP_META_CLK		0x80
+#define TOP_CLKSWITCH2		0x88
+#define TOP_CLKENAB2		0x8c
+#define TOP_I2S_DIV2		0x90
+#define TOP_META_TRACE_CLK_DIV	0x94
+#define TOP_PIXEL_CLK_DIV	0x98
+#define TOP_CLKOUT0_DIV		0x9c
+#define TOP_CLKOUT1_DIV		0xa0
+#define TOP_UCC0_CLKDELETE	0xa4
+#define TOP_UCC1_CLKDELETE	0xa8
+#define TOP_DDR_CLKDIV		0xac
+
+/*
+ *                    CR_TOP_CLKSWITCH
+ *                    ================
+ *                       ___________        _________   _____________
+ * xtal1         ------o| sys_sw    \______| sys_pll |_| sys_clk_div |__
+ * xtal2         -------|___________/  0   |_________| |_____________|  |
+ *                    __________________________________________________|
+ *                   |   ___________
+ * xtal1         ----|-o|sysclk1_sw \____________________________
+ * sys_clk_div       `--|___________/  1 sys_clk_x2_undeleted
+ * xtal1         ------o|clkout0_sw0\______
+ * afe_progdiv1  -------|___________/  2   |
+ * sys_undeleted ------o|clkout0_sw1\____  |
+ * if0_sw        -------|___________/  3 | |   CR_TOP_CLKENAB
+ *                 ,-;==================='-'   ==============
+ *                 | |   ___________            ___________
+ * clkout0_sw0     | `-o|clkout0_sw2\____     _| out0_inv  \_____
+ * xtal2         --|----|___________/  4 |   | |___________/  4
+ *                 |  ___________________|   |__________________
+ *                 | |   ___________            ___________     |
+ * clkout0_sw2     | `-o|clkout0_sw3\__________| out0_en   \____|
+ * clkout0_sw1     `----|___________/  5       |___________/  5
+ * xtal1         ------o|clkout1_sw0\______     .
+ * xtal2         -------|___________/  6   |    .
+ * sys_undeleted ------o|clkout1_sw1\____  |    .
+ * if1_sw        -------|___________/  7 | |    .
+ *                 ,-;==================='-'    .
+ *                 | |   ___________            ___________
+ * adcpll_clk    --|-|-o|clkout1_sw2\____     _| out1_inv  \_____
+ * clkout1_sw1     `-|--|___________/  8 |   | |___________/  8
+ *                  _|___________________|   |__________________
+ *                 | |   ___________            ___________     |
+ * clkout1_sw0     | `-o|clkout1_sw3\__________| out1_en   \____|
+ * clkout1_sw2     `----|___________/  9       |___________/  9
+ * xtal1         ------o| i2s_sw2   \______     .
+ * sys_undeleted -------|___________/ 10   |    .
+ * xtal2         ------o| i2s_sw0   \____  |    .
+ * adcpll_clk    -------|___________/ 11 | |    .
+ *                 ,-;==================='-'    .
+ *                 | |   ___________            ___________
+ * i2s_sw2         | `-o| i2s_sw1   \__________| i2s_en    \_____
+ * i2s_sw0         `----|___________/ 12       |___________/ 12
+ * xtal1         ------o| scb_sw    \__________| scb_en    \_____
+ * sys_undeleted -------|___________/ 13       |___________/ 13
+ * xtal1         ------o| uart_sw   \__________| uart_en   \_____
+ * sys_undeleted -------|___________/ 14       |___________/ 14
+ * xtal1         ------o|ext_stc0_sw\__________|ext_stc0_en\_____
+ * xtal2         -------|___________/ 16       |___________/ 16
+ * xtal1         ------o|ext_stc1_sw\__________|ext_stc1_en\_____
+ * xtal2         -------|___________/ 17       |___________/ 17
+ * adcpll_clk    ------o|  usb_sw0  \____       .
+ * afe_progdiv3  -------|___________/ 18 |      .
+ *                    ___________________|      .
+ *                   |   ___________            ___________
+ * usb_sw3         ,-|-o|  usb_sw1  \__________| usb_en    \_____
+ * usb_sw0         | `--|___________/ 19       |___________/ 19
+ * xtal1         --|---o|  afe_sw0  \________________
+ * afe_sw1       ,-|----|___________/ 20        .    |    _____________
+ *               `-`=====================:-.    .    |___| afe_clk_div |________
+ *                       ___________     | |    .        |_____________| afe_clk
+ * adcpll_en       ,---o|  afe_sw1  \____| |    .
+ * xtal2         --|----|___________/ 21   |    .         ________
+ * xtal1         --|---o|adcpll_sw0 \______|_____________| adcpll |_____________
+ * xtal2         --|----|___________/ 22   |    .        |________| adcpll_clk
+ * xtal1         --|---o|adcpll_sw1 \____  |    .
+ * xtal2         --|----|___________/ 23 | |    .
+ *                 |  ___________________| |    .
+ *                 | |   ___________       |    .         ________________
+ * adcpll_en       +-|-o|adcpll_sw2 \______|_____________| adcpll_clk_div |_____
+ * adcpll_sw1      | `--|___________/ 24   |    .        |________________|
+ *                 |_______________________|_____________________
+ *                       ___________       |    ___________      |
+ * sys_undeleted -------|adcpll_sw3 \______|___| adcpll_en \_____|
+ * adcpll_clk    -------|___________/ 25   |   |___________/ 25
+ * xtal1         -------|  usb_sw2  \____  |
+ * xtal2         -------|___________/ 28 | |
+ *                    ___________________| |
+ *                   |   ___________       |
+ * usb_sw2           `--|  usb_sw3  \______|
+ * sys_undeleted -------|___________/ 29
+ */
+MUX_BANK(tz1090_top_clkswitch, CLK_TOP_CLKSWITCH_BASE, TOP_CLKSWITCH,
+	/*  bit in[0]		 in[1]			out	*/
+	MUX( 0, "@xtal1",	 "@xtal2",		"sys_sw")
+	MUX( 1, "@xtal1",	 "sys_div",		"sys_x2_undeleted")
+	MUX( 2, "@xtal1",	 "@afe_progdiv1",	"out0_sw0")
+	MUX( 3, "sys_undeleted", "if0_sw",		"out0_sw1")
+	MUX( 4, "out0_sw0",	 "@xtal2",		"out0_sw2")
+	MUX( 5, "out0_sw2",	 "out0_sw1",		"out0_sw3")
+	MUX( 6, "@xtal1",	 "@xtal2",		"out1_sw0")
+	MUX( 7, "sys_undeleted", "if1_sw",		"out1_sw1")
+	MUX( 8, "adcpll",	 "out1_sw1",		"out1_sw2")
+	MUX( 9, "out1_sw0",	 "out1_sw2",		"out1_sw3")
+	MUX(10, "@xtal1",	 "sys_undeleted",	"i2s_sw2")
+	MUX(11, "@xtal2",	 "adcpll",		"i2s_sw0")
+	MUX(12, "i2s_sw2",	 "i2s_sw0",		"i2s_sw1")
+	/*
+	 * SCB clock must be derived from system clock to workaround clock
+	 * domain crossing problems in SCB automatic mode.
+	 */
+	MUX_FIXED(13, "@xtal1",	 "sys_undeleted",	"scb_sw",	1)
+	MUX(14, "@xtal1",	 "sys_undeleted",	"uart_sw")
+	/* bit 15 unused */
+	MUX(16, "@xtal1",	 "@xtal2",		"ext_stc0_sw")
+	MUX(17, "@xtal1",	 "@xtal2",		"ext_stc1_sw")
+	MUX(18, "adcpll",	 "@afe_progdiv3",	"usb_sw0")
+	MUX(19, "usb_sw3",	 "usb_sw0",		"usb_sw1")
+	MUX(20, "@xtal1",	 "afe_sw1",		"afe_sw0")
+	MUX(21, "adcpll_en",	 "@xtal2",		"afe_sw1")
+	MUX(22, "@xtal1",	 "@xtal2",		"adcpll_sw0")
+	MUX(23, "@xtal1",	 "@xtal2",		"adcpll_sw1")
+	MUX(24, "adcpll_en",	 "adcpll_sw1",		"adcpll_sw2")
+	MUX(25, "sys_undeleted", "adcpll",		"adcpll_sw3")
+	/* bits 26..27 unused */
+	MUX(28, "@xtal1",	 "@xtal2",		"usb_sw2")
+	MUX(29, "usb_sw2",	 "sys_undeleted",	"usb_sw3")
+	/* bits 30..31 unused */
+);
+
+GATE_BANK(tz1090_top_clkenab, CLK_TOP_CLKENAB_BASE, TOP_CLKENAB,
+	/*   bit in			out	*/
+	/* bits 0..4 unused */
+	GATE( 5, "out0_sw3",		"out0_en")
+	/* bits 6..8 unused */
+	GATE( 9, "out1_sw3",		"out1_en")
+	/* bits 10..11 unused */
+	GATE(12, "i2s_sw1",		"i2s_en")
+	GATE(13, "scb_sw",		"scb")
+	GATE(14, "uart_sw",		"uart_en")
+	/* bit 15 unused */
+	GATE(16, "ext_stc0_sw",		"ext_stc0")
+	GATE(17, "ext_stc1_sw",		"ext_stc1")
+	/* bit 18 unused */
+	GATE(19, "usb_sw1",		"usb_en")
+	/* bits 20..24 unused */
+	GATE(25, "adcpll_sw3",		"adcpll_en")
+	/* bits 26..31 unused */
+);
+
+/*
+ *                    CR_TOP_CLKSWITCH2
+ *                    =================
+ *                       ___________
+ * xtal1         ------o| pixel_sw0 \______
+ * pixel_sw3       ,----|___________/  0   |
+ * sys_undeleted --+---o| pixel_sw1 \____  |
+ * pixel_sw4       | ,--|___________/  1 | |
+ *                 `-`===================|=|=:-.  CR_TOP_CLKENAB2
+ *                 ,-;==================='-' | |  ===============
+ *                 | |   ___________         | |    __________
+ * pixel_sw0       | `-o| pixel_sw2 \________|_|___| pixel_en \_____
+ * pixel_sw1       `----|___________/  2     | |   |__________/  2
+ * adcpll_clk    ------o| pixel_sw3 \________| |    .
+ * afe_progdiv3  -------|___________/  3       |    .
+ * usb_phy_clk   ------o| pixel_sw4 \__________|    .
+ * xtal2         -------|___________/  4            __________
+ * iqadc_sync    ------o| if1_sw    \______________| if1_en   \_____
+ * ext_adc_dac   --+----|___________/  5           |__________/  5
+ * afe_rxsync    --|---o| if0_sw    \______________| if0_en   \_____
+ * ext_adc_dac     |`---|___________/  6      _____|__________/  6
+ *                 |.________________________| ext_adc_dac_en \_____
+ *                 |     ___________         |________________/  7
+ * afe_txsync    --|---o| dac0_sw   \______________| dac0_en  \_____
+ * ext_adc_dac     `----|___________/  8           |__________/  8
+ * ucc1_clk_del  ------o| ucc1_sw   \______________| ucc1_en  \_____
+ * ucc0_clk_del  --+----|___________/  9           |__________/  9
+ * ucc0_clk_del    `---o| ucc0_sw   \______________| ucc0_en  \_____
+ * sys_clk       -------|___________/ 10           |__________/ 10
+ */
+MUX_BANK(tz1090_top_clkswitch2, CLK_TOP_CLKSWITCH2_BASE, TOP_CLKSWITCH2,
+	/*  bit in[0]			in[1]			out	*/
+	MUX( 0, "@xtal1",		"pixel_sw3",		"pixel_sw0")
+	MUX( 1, "sys_undeleted",	"pixel_sw4",		"pixel_sw1")
+	MUX( 2, "pixel_sw0",		"pixel_sw1",		"pixel_sw2")
+	MUX( 3, "adcpll",		"@afe_progdiv3",	"pixel_sw3")
+	MUX( 4, "usb_phy",		"@xtal2",		"pixel_sw4")
+	MUX( 5, "@iqadc_sync",		"@ext_adc_dac",		"if1_sw")
+	MUX( 6, "@afe_rxsync",		"@ext_adc_dac",		"if0_sw")
+	/* bit 7 unused */
+	MUX( 8, "@afe_txsync",		"@ext_adc_dac",		"dac0_sw")
+	MUX( 9, "ucc1_del",		"ucc0",			"ucc1_sw")
+	MUX(10, "ucc0",			"sys",			"ucc0_sw")
+	/* bits 11..31 unused */
+);
+
+GATE_BANK(tz1090_top_clkenab2, CLK_TOP_CLKENAB2_BASE, TOP_CLKENAB2,
+	/*   bit in			out	*/
+	/* bits 0..1 unused */
+	GATE( 2, "pixel_sw2",		"pixel_en")
+	/* bits 3..4 unused */
+	GATE( 5, "if1_sw",		"if1")
+	GATE( 6, "if0_sw",		"if0")
+	GATE( 7, "@ext_adc_dac",	"ext_adc_dac_en")
+	GATE( 8, "dac0_sw",		"dac0")
+	GATE( 9, "ucc1_sw",		"sys_ucc1")
+	GATE(10, "ucc0_sw",		"sys_mtx")
+	/* bits 11..31 unused */
+);
+
+/*
+ *                       Deleters
+ *                       ========
+ *
+ * sys_undeleted    ---[ clkdelete      ]--- sys_clk
+ * sys_x2_undeleted ---[ meta_clkdelete ]--- meta_core_clk
+ * sys_undeleted    ---[ clkdelete      ]--- ucc0_clk_del
+ * sys_undeleted    ---[ clkdelete      ]--- ucc1_clk_del
+ */
+
+static const struct tz1090_clk_deleter tz1090_top_deleters[] __initconst = {
+	DEL(CLK_TOP_SYS,      "sys_undeleted",    "sys",      TOP_CLKDELETE),
+	DEL(CLK_TOP_META,     "sys_x2_undeleted", "meta",     TOP_META_CLKDELETE),
+	DEL(CLK_TOP_UCC0,     "sys_undeleted",    "ucc0",     TOP_UCC0_CLKDELETE),
+	DEL(CLK_TOP_UCC1_DEL, "sys_undeleted",    "ucc1_del", TOP_UCC1_CLKDELETE),
+};
+
+/*
+ *                       Dividers
+ *                       ========
+ *
+ * sys_pll          ---[ sys_clk_div        ]--- sys_div
+ * sys_x2_undeleted ---[ meta_clk_div       ]--- sys_undeleted
+ * afe_sw0          ---[ afe_clk_div        ]--- afe_clk
+ * adcpll_sw2       ---[ adcpll_clk_div     ]--- adcpll_div
+ * uart_en          ---[ uart_clk_div       ]--- uart_clk
+ * sys_undeleted    ---[ pdm_clk_div        ]--- pdm_clk
+ * sys_undeleted    ---[ spi0_clk_div       ]--- spi0_clk
+ * sys_undeleted    ---[ spi1_clk_div       ]--- spi1_clk
+ * i2s_en           ---[ i2sm_clk_div       ]--- i2sm
+ * usb_en           ---[ usbpll_clk_div     ]--- usb_phy_clk
+ * sys_undeleted    ---[ sdhost_clk_div     ]--- sdhost_clk
+ * sys_undeleted    ---[ ring_osc_clk_div   ]--- ring_osc_clk
+ * i2sm_clk         ---[ i2s_clk_div2       ]--- i2s_clk
+ * sys_undeleted    ---[ meta_trace_clk_div ]--- meta_trace_clk
+ * pixel_en         ---[ pixel_clk_div      ]--- pixel_clk
+ * clkout0_en       ---[ clkout0_clk_div    ]--- clkout0
+ * clkout1_en       ---[ clkout1_clk_div    ]--- clkout1
+ * ddr_en           ---[ ddr_clk_div        ]--- ddr_clk
+ */
+
+static const struct tz1090_clk_divider tz1090_top_dividers[] __initconst = {
+	DIV(CLK_TOP_SYS_DIV,    "sys_pll",       "sys_div",    TOP_SYSCLK_DIV,         8),
+	/*
+	 * CLK_DIVIDER_READ_ONLY: sys_undeleted is set up by the bootloader
+	 * along with sys_pll, and has a whole bunch of derivative peripheral
+	 * clocks. It would be really bad for it to change on the fly.
+	 */
+	DIV_FLAGS(CLK_TOP_SYS_UNDELETED, "sys_x2_undeleted", "sys_undeleted", TOP_META_CLKDIV, 2,
+		  0, CLK_DIVIDER_READ_ONLY),
+	DIV(CLK_TOP_AFE,        "afe_sw0",       "afe",        TOP_AFE_DIV,            8),
+	DIV(CLK_TOP_ADCPLL_DIV, "adcpll_sw2",    "adcpll_div", TOP_ADCPLL_DIV,         8),
+	/*
+	 * CLK_SET_RATE_PARENT: UART clock changes must propagate up to uart_sw,
+	 * which muxes between XTAL1 and sys_undeleted, in order to get enough
+	 * precision.
+	 */
+	DIV_FLAGS(CLK_TOP_UART, "uart_en",       "uart",       TOP_UARTCLK_DIV,        8,
+		  CLK_SET_RATE_PARENT, CLK_DIVIDER_ROUND_CLOSEST),
+	DIV(CLK_TOP_PDM,        "sys_undeleted", "pdm",        TOP_PDMCK_CTL,          3),
+	DIV(CLK_TOP_SPI0,       "sys_undeleted", "spi0",       TOP_SPICLK_DIV,         8),
+	DIV(CLK_TOP_SPI1,       "sys_undeleted", "spi1",       TOP_SPI1CLK_DIV,        8),
+	DIV(CLK_TOP_I2SM,       "i2s_en",        "i2sm",       TOP_I2SCLK_DIV,         8),
+	DIV(CLK_TOP_USB_PHY,    "usb_en",        "usb_phy",    TOP_USB_PLLDIV,         8),
+	DIV(CLK_TOP_SDHOST,     "sys_undeleted", "sdhost",     TOP_SDHOSTCLK_DIV,      8),
+	DIV(CLK_TOP_RING_OSC,   "sys_undeleted", "ring_osc",   TOP_RING_OP_DIV,        4),
+	DIV(CLK_TOP_I2S,        "i2sm",          "i2s",        TOP_I2S_DIV2,           8),
+	DIV(CLK_TOP_META_TRACE, "sys_undeleted", "meta_trace", TOP_META_TRACE_CLK_DIV, 8),
+	DIV(CLK_TOP_PIXEL,      "pixel_en",      "pixel",      TOP_PIXEL_CLK_DIV,      8),
+	DIV(CLK_TOP_OUT0,       "out0_en",       "out0",       TOP_CLKOUT0_DIV,        8),
+	DIV(CLK_TOP_OUT1,       "out1_en",       "out1",       TOP_CLKOUT1_DIV,        8),
+	DIV(CLK_TOP_DDR,        "@ddr_en",       "ddr",        TOP_DDR_CLKDIV,         8),
+};
+
+/*
+ *                 PLLs
+ *                 ====
+ *
+ * sys_sw     ---[ sys_pll ]---
+ * adcpll_sw0 ---[ adcpll  ]---
+ */
+
+static const struct tz1090_clk_pll tz1090_top_plls[] __initconst = {
+	PLL(CLK_TOP_SYSPLL, "sys_sw",     "sys_pll", TOP_SYSPLL_CTL0),
+	PLL(CLK_TOP_ADCPLL, "adcpll_sw0", "adcpll",  TOP_ADCPLL_CTL0),
+};
+
+/*
+ *          CR_TOP_CLKEN
+ *          ============
+ *
+ * sys ----[ pdc_sys_en ]--- 0 sys_pdc
+ */
+GATE_BANK(tz1090_top_clken, CLK_TOP_CLKEN_BASE, TOP_CLKEN,
+	/*   bit in	out	*/
+	GATE( 0, "sys",	"sys_pdc")
+	/* bits 1..31 unused */
+);
+
+static void __init tz1090_top_cr_init(struct device_node *np)
+{
+	struct tz1090_clk_provider *p;
+
+	p = tz1090_clk_alloc_provider(np, CLK_TOP_MAX);
+	if (!p)
+		return;
+
+	tz1090_clk_register_mux_bank(p, &tz1090_top_clkswitch);
+	tz1090_clk_register_mux_bank(p, &tz1090_top_clkswitch2);
+	tz1090_clk_register_gate_bank(p, &tz1090_top_clkenab);
+	tz1090_clk_register_gate_bank(p, &tz1090_top_clkenab2);
+	tz1090_clk_register_gate_bank(p, &tz1090_top_clken);
+	tz1090_clk_register_deleters(p, tz1090_top_deleters,
+				     ARRAY_SIZE(tz1090_top_deleters));
+	tz1090_clk_register_dividers(p, tz1090_top_dividers,
+				     ARRAY_SIZE(tz1090_top_dividers));
+	tz1090_clk_register_plls(p, tz1090_top_plls,
+				 ARRAY_SIZE(tz1090_top_plls));
+
+	tz1090_clk_register_provider(p);
+}
+CLK_OF_DECLARE(tz1090_top_cr, "img,tz1090-top-cr", tz1090_top_cr_init);
diff --git a/drivers/clk/tz1090/clk.c b/drivers/clk/tz1090/clk.c
new file mode 100644
index 0000000..5f4e8f28
--- /dev/null
+++ b/drivers/clk/tz1090/clk.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2014 Google, Inc.
+ * Copyright (C) 2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ *
+ * TZ1090 Clocks
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+#include "clk.h"
+
+struct tz1090_clk_provider *tz1090_clk_alloc_provider(struct device_node *node,
+						      unsigned int num_clks)
+{
+	struct tz1090_clk_provider *p;
+
+	p = kzalloc(sizeof(*p), GFP_KERNEL);
+	if (!p)
+		return p;
+
+	p->clk_data.clks = kcalloc(num_clks, sizeof(struct clk *), GFP_KERNEL);
+	if (!p->clk_data.clks)
+		goto free_provider;
+	p->clk_data.clk_num = num_clks;
+	p->node = node;
+	p->base = of_iomap(node, 0);
+	if (!p->base) {
+		pr_err("%s: Failed to map clock provider registers\n",
+		       node->full_name);
+		goto free_clks;
+	}
+
+	return p;
+
+free_clks:
+	kfree(p->clk_data.clks);
+free_provider:
+	kfree(p);
+	return NULL;
+}
+
+const char *tz1090_clk_xlate(struct tz1090_clk_provider *p,
+			     const char *clk_name)
+{
+	/*
+	 * If clock name begins with @, the rest refers to an external clock.
+	 *
+	 * Look for the index of the parent clock with a matching label in
+	 * clock-names. If found, find the name of the specified parent clock.
+	 *
+	 * If not found, we leave it unchanged. The @ at the beginning should
+	 * ensure it doesn't accidentally match a real clock.
+	 */
+	if (*clk_name == '@') {
+		const char *clk_label = clk_name + 1;
+		int idx = of_property_match_string(p->node, "clock-names",
+						   clk_label);
+		if (idx >= 0) {
+			clk_name = of_clk_get_parent_name(p->node, idx);
+			pr_debug("%s: Parent clock '%s' found as '%s'\n",
+				 p->node->full_name, clk_label, clk_name);
+		} else {
+			pr_err("%s: No parent clock '%s' found\n",
+			       p->node->full_name, clk_label);
+		}
+	}
+
+	return clk_name;
+}
+
+void tz1090_clk_register_provider(struct tz1090_clk_provider *p)
+{
+	unsigned int i;
+
+	for (i = 0; i < p->clk_data.clk_num; i++)
+		if (IS_ERR(p->clk_data.clks[i]))
+			pr_warn("%s: Failed to register clock %d: %ld\n",
+				p->node->full_name, i,
+				PTR_ERR(p->clk_data.clks[i]));
+
+	of_clk_add_provider(p->node, of_clk_src_onecell_get, &p->clk_data);
+}
diff --git a/drivers/clk/tz1090/clk.h b/drivers/clk/tz1090/clk.h
new file mode 100644
index 0000000..1d430a4
--- /dev/null
+++ b/drivers/clk/tz1090/clk.h
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ *
+ * TZ1090 Clocks
+ */
+
+#ifndef CLK_TZ1090_CLK_H
+#define CLK_TZ1090_CLK_H
+
+#include <linux/clk-provider.h>
+#include <linux/init.h>
+
+/* Generic TZ1090 clock provider */
+
+/**
+ * struct tz1090_clk_provider - Clock provider data.
+ * @node:	Device tree node for the clock provider.
+ * @base:	IO remapped base address.
+ * @clk_data:	Standard onecell clock data including list of clocks.
+ */
+struct tz1090_clk_provider {
+	struct device_node		*node;
+	void __iomem			*base;
+	struct clk_onecell_data		clk_data;
+};
+
+struct tz1090_clk_provider *tz1090_clk_alloc_provider(struct device_node *node,
+						      unsigned int num_clks);
+const char *tz1090_clk_xlate(struct tz1090_clk_provider *p,
+			     const char *clk_name);
+void tz1090_clk_register_provider(struct tz1090_clk_provider *p);
+
+
+/* Clock gate banks */
+
+/**
+ * struct tz1090_clk_gate - Describes an individual gate in a bank.
+ * @shift:	Shift of bit controlling gate within the bank control register.
+ * @name:	Name of gated clock to provide.
+ * @parent:	Name of parent/source clock.
+ */
+struct tz1090_clk_gate {
+	unsigned int	shift;
+	const char	*name;
+	const char	*parent;
+};
+
+/**
+ * struct tz1090_clk_gate_bank - Describes a gate bank.
+ * @id_base:	Base id of bank in provider.
+ *		Individual gates get the id id_base + index in gates array.
+ * @reg_base:	Offset of gate bank register in the MMIO region.
+ * @gates:	Pointer to array of gates in the bank, terminated by one with a
+ *		NULL name field.
+ */
+struct tz1090_clk_gate_bank {
+	unsigned int			id_base;
+	unsigned long			reg_base;
+	const struct tz1090_clk_gate	*gates;
+};
+
+#define GATE(_shift, _parent, _name)					\
+	{								\
+		.shift		= (_shift),				\
+		.name		= (_name),				\
+		.parent		= (_parent),				\
+	},
+
+#define GATE_BANK(_name, _id, _reg, _gates)				\
+	static const struct tz1090_clk_gate_bank _name __initconst = {	\
+		.id_base	= (_id),				\
+		.reg_base	= (_reg),				\
+		.gates		= (const struct tz1090_clk_gate[]) {	\
+			_gates						\
+			{ .name	= NULL }				\
+		},							\
+	}
+
+void tz1090_clk_register_gate_bank(struct tz1090_clk_provider *p,
+				   const struct tz1090_clk_gate_bank *bank);
+
+
+/* Clock mux banks */
+
+/**
+ * struct tz1090_clk_mux - Describes an individual mux in a bank.
+ * @shift:	Shift of bit controlling mux within the bank control register.
+ * @name:	Name of muxed clock to provide.
+ * @parents:	Name of two parent/source clocks for when the bit is 0 and 1.
+ * @default_parent:	Default parent to set the mux to.
+ * @mux_flags:	Mux flags.
+ */
+struct tz1090_clk_mux {
+	unsigned int	shift;
+	const char	*name;
+	const char	*parents[2];
+	s8		default_parent;
+	u8		mux_flags;
+};
+
+/**
+ * struct tz1090_clk_mux_bank - Describes a mux bank.
+ * @id_base:	Base id of bank in provider.
+ *		Individual muxes get the id id_base + index in muxes array.
+ * @reg_base:	Offset of mux bank register in the MMIO region.
+ * @muxes:	Pointer to array of muxes in the bank, terminated by one with a
+ *		NULL name field.
+ */
+struct tz1090_clk_mux_bank {
+	unsigned int			id_base;
+	unsigned long			reg_base;
+	const struct tz1090_clk_mux	*muxes;
+};
+
+#define MUX(_shift, _parent0, _parent1, _name)				\
+	{								\
+		.shift		= (_shift),				\
+		.name		= (_name),				\
+		.parents	= {					\
+			_parent0,					\
+			_parent1					\
+		},							\
+		.default_parent	= -1,					\
+		.mux_flags	= 0,					\
+	},
+
+#define MUX_FIXED(_shift, _parent0, _parent1, _name, _default)		\
+	{								\
+		.shift		= (_shift),				\
+		.name		= (_name),				\
+		.parents	= {					\
+			_parent0,					\
+			_parent1					\
+		},							\
+		.default_parent	= (_default),				\
+		.mux_flags	= CLK_MUX_READ_ONLY,			\
+	},
+
+#define MUX_BANK(_name, _id, _reg, _muxes)				\
+	static const struct tz1090_clk_mux_bank _name __initconst = {	\
+		.id_base	= (_id),				\
+		.reg_base	= (_reg),				\
+		.muxes		= (const struct tz1090_clk_mux[]) {	\
+			_muxes						\
+			{ .name	= NULL }				\
+		},							\
+	}
+
+void tz1090_clk_register_mux_bank(struct tz1090_clk_provider *p,
+				  const struct tz1090_clk_mux_bank *bank);
+
+
+/* Deleters */
+
+/**
+ * struct tz1090_clk_deleter - Describes a clock deleter.
+ * @id:		Id of output clock in provider.
+ * @reg:	Offset of deleter register in the MMIO region.
+ * @name:	Name of deleted clock to provide.
+ * @parent:	Name of parent/source clocks.
+ *
+ * The deleter is assumed to have a period of 1024.
+ */
+struct tz1090_clk_deleter {
+	unsigned int		id;
+	unsigned long		reg;
+	const char		*name;
+	const char		*parent;
+};
+
+#define DEL(_id, _parent, _name, _reg)		\
+	{					\
+		.id		= (_id),	\
+		.reg		= (_reg),	\
+		.name		= (_name),	\
+		.parent		= (_parent),	\
+	}
+
+void tz1090_clk_register_deleters(struct tz1090_clk_provider *p,
+				  const struct tz1090_clk_deleter *deleters,
+				  unsigned int count);
+
+
+/* Dividers */
+
+/**
+ * struct tz1090_clk_divider - Describes a clock divider.
+ * @id:		Id of output clock in provider.
+ * @reg:	Offset of divider register in the MMIO region.
+ * @flags:	Clock flags.
+ * @div_flags:	Divider flags.
+ * @shift:	Shift of field controlling divider.
+ * @width:	Width of field controlling divider.
+ * @shared:	1 if register is shared with other important fields and requires
+ *		global locking.
+ * @name:	Name of divided clock to provide.
+ * @parent:	Name of parent/source clocks.
+ */
+struct tz1090_clk_divider {
+	unsigned int		id;
+	unsigned long		reg;
+	unsigned long		flags;
+	u8			div_flags;
+	u8			shift;
+	u8			width;
+	u8			shared;
+	const char		*name;
+	const char		*parent;
+};
+
+#define DIV(_id, _parent, _name, _reg, _width)	\
+	{								\
+		.id		= (_id),				\
+		.reg		= (_reg),				\
+		.width		= (_width),				\
+		.name		= (_name),				\
+		.parent		= (_parent),				\
+	}
+
+#define DIV_FLAGS(_id, _parent, _name, _reg, _width, _flags, _divflags)	\
+	{								\
+		.id		= (_id),				\
+		.reg		= (_reg),				\
+		.flags		= (_flags),				\
+		.div_flags	= (_divflags),				\
+		.width		= (_width),				\
+		.name		= (_name),				\
+		.parent		= (_parent),				\
+	}
+
+#define DIV_SHARED(_id, _parent, _name, _reg, _width, _shift)		\
+	{								\
+		.id		= (_id),				\
+		.reg		= (_reg),				\
+		.shift		= (_shift),				\
+		.width		= (_width),				\
+		.shared		= 1,					\
+		.name		= (_name),				\
+		.parent		= (_parent),				\
+	}
+
+void tz1090_clk_register_dividers(struct tz1090_clk_provider *p,
+				  const struct tz1090_clk_divider *dividers,
+				  unsigned int count);
+
+
+/* PLLs */
+
+struct tz1090_clk_pll {
+	unsigned int		id;
+	unsigned long		reg_base;
+	const char		*name;
+	const char		*parent;
+};
+
+#define PLL(_id, _parent, _name, _reg)			\
+	{						\
+		.id		= (_id),		\
+		.reg_base	= (_reg),		\
+		.name		= (_name),		\
+		.parent		= (_parent),		\
+	}
+
+void tz1090_clk_register_plls(struct tz1090_clk_provider *p,
+			      const struct tz1090_clk_pll *plls,
+			      unsigned int count);
+
+#endif
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index deae122..105d4a9 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -2536,16 +2536,18 @@
 	struct uart_8250_port *up = up_to_u8250p(port);
 	unsigned char cval;
 	unsigned long flags;
-	unsigned int baud, quot, frac = 0;
+	unsigned int baud, quot, frac = 0, uartclk_hi;
 
 	cval = serial8250_compute_lcr(up, termios->c_cflag);
 
 	/*
-	 * Ask the core to calculate the divisor for us.
+	 * Ask the core to calculate the divisor for us, but tolerate some
+	 * variance (e.g. if the uartclk is only slightly under 1.8432MHz).
 	 */
+	uartclk_hi = port->uartclk + port->uartclk / 128;
 	baud = uart_get_baud_rate(port, termios, old,
 				  port->uartclk / 16 / 0xffff,
-				  port->uartclk / 16);
+				  uartclk_hi / 16);
 	quot = serial8250_get_divisor(up, baud, &frac);
 
 	/*
@@ -3269,15 +3271,16 @@
 	/* check scratch reg to see if port powered off during system sleep */
 	if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) {
 		struct ktermios termios;
-		unsigned int baud, quot, frac = 0;
+		unsigned int baud, quot, frac = 0, uartclk_hi;
 
 		termios.c_cflag = port->cons->cflag;
 		if (port->state->port.tty && termios.c_cflag == 0)
 			termios.c_cflag = port->state->port.tty->termios.c_cflag;
 
+		uartclk_hi = port->uartclk + port->uartclk / 128;
 		baud = uart_get_baud_rate(port, &termios, NULL,
 					  port->uartclk / 16 / 0xffff,
-					  port->uartclk / 16);
+					  uartclk_hi / 16);
 		quot = serial8250_get_divisor(up, baud, &frac);
 
 		serial8250_set_divisor(port, baud, quot, frac);
diff --git a/drivers/watchdog/imgpdc_wdt.c b/drivers/watchdog/imgpdc_wdt.c
index c8def68..0deaa4f 100644
--- a/drivers/watchdog/imgpdc_wdt.c
+++ b/drivers/watchdog/imgpdc_wdt.c
@@ -42,10 +42,10 @@
 #define PDC_WDT_MIN_TIMEOUT		1
 #define PDC_WDT_DEF_TIMEOUT		64
 
-static int heartbeat;
+static int heartbeat = PDC_WDT_DEF_TIMEOUT;
 module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds. "
-	"(default = " __MODULE_STRING(PDC_WDT_DEF_TIMEOUT) ")");
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds "
+	"(default=" __MODULE_STRING(PDC_WDT_DEF_TIMEOUT) ")");
 
 static bool nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, bool, 0);
@@ -191,6 +191,7 @@
 	pdc_wdt->wdt_dev.ops = &pdc_wdt_ops;
 	pdc_wdt->wdt_dev.max_timeout = 1 << PDC_WDT_CONFIG_DELAY_MASK;
 	pdc_wdt->wdt_dev.parent = &pdev->dev;
+	watchdog_set_drvdata(&pdc_wdt->wdt_dev, pdc_wdt);
 
 	ret = watchdog_init_timeout(&pdc_wdt->wdt_dev, heartbeat, &pdev->dev);
 	if (ret < 0) {
@@ -232,7 +233,6 @@
 	watchdog_set_nowayout(&pdc_wdt->wdt_dev, nowayout);
 
 	platform_set_drvdata(pdev, pdc_wdt);
-	watchdog_set_drvdata(&pdc_wdt->wdt_dev, pdc_wdt);
 
 	ret = watchdog_register_device(&pdc_wdt->wdt_dev);
 	if (ret)
diff --git a/include/dt-bindings/clock/tz1090-hep.h b/include/dt-bindings/clock/tz1090-hep.h
new file mode 100644
index 0000000..44398ef
--- /dev/null
+++ b/include/dt-bindings/clock/tz1090-hep.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2013-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _DT_BINDINGS_CLK_TZ1090_HEP_H
+#define _DT_BINDINGS_CLK_TZ1090_HEP_H
+
+/* CR_HEP_CLK_EN - High End Peripheral clocks */
+#define CLK_HEP_2D		0
+#define CLK_HEP_DDR_EN		1
+#define CLK_HEP_PDP		2
+
+#define CLK_HEP_MAX		3
+
+#endif
diff --git a/include/dt-bindings/clock/tz1090-pdc.h b/include/dt-bindings/clock/tz1090-pdc.h
new file mode 100644
index 0000000..fa9a11c
--- /dev/null
+++ b/include/dt-bindings/clock/tz1090-pdc.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2013-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _DT_BINDINGS_CLK_TZ1090_PDC_H
+#define _DT_BINDINGS_CLK_TZ1090_PDC_H
+
+/* Powerdown Controller clocks */
+#define CLK_PDC_XTAL1_DIV	0
+#define CLK_PDC_32KHZ		1
+
+#define CLK_PDC_MAX		2
+
+#endif
diff --git a/include/dt-bindings/clock/tz1090-perip.h b/include/dt-bindings/clock/tz1090-perip.h
new file mode 100644
index 0000000..b2990ea
--- /dev/null
+++ b/include/dt-bindings/clock/tz1090-perip.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2013-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _DT_BINDINGS_CLK_TZ1090_PERIP_H
+#define _DT_BINDINGS_CLK_TZ1090_PERIP_H
+
+/* CR_PERIP_CLKEN - Peripheral system clocks */
+#define CLK_PERIP_SCB0		 0
+#define CLK_PERIP_SCB1		 1
+#define CLK_PERIP_SCB2		 2
+#define CLK_PERIP_SDIO		 3
+#define CLK_PERIP_UART0		 4
+#define CLK_PERIP_UART1		 5
+#define CLK_PERIP_SPIM		 6
+#define CLK_PERIP_SPIS		 7
+#define CLK_PERIP_SPIM1		 8
+#define CLK_PERIP_I2SOUT	 9
+#define CLK_PERIP_I2SIN		10
+#define CLK_PERIP_LCD		11
+#define CLK_PERIP_SDHOST	12
+#define CLK_PERIP_USB		13
+
+#define CLK_PERIP_MAX		14
+
+#endif
diff --git a/include/dt-bindings/clock/tz1090-top.h b/include/dt-bindings/clock/tz1090-top.h
new file mode 100644
index 0000000..effb06a
--- /dev/null
+++ b/include/dt-bindings/clock/tz1090-top.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2013-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _DT_BINDINGS_CLK_TZ1090_TOP_H
+#define _DT_BINDINGS_CLK_TZ1090_TOP_H
+
+/* Ranges of top level clock numbers */
+#define CLK_TOP_CLKSWITCH_BASE		0
+#define CLK_TOP_CLKENAB_BASE		(CLK_TOP_CLKSWITCH_BASE  + 27)
+#define CLK_TOP_CLKSWITCH2_BASE		(CLK_TOP_CLKENAB_BASE    +  9)
+#define CLK_TOP_CLKENAB2_BASE		(CLK_TOP_CLKSWITCH2_BASE + 10)
+#define CLK_TOP_DEL_BASE		(CLK_TOP_CLKENAB2_BASE   +  7)
+#define CLK_TOP_DIV_BASE		(CLK_TOP_DEL_BASE        +  4)
+#define CLK_TOP_PLL_BASE		(CLK_TOP_DIV_BASE        + 18)
+#define CLK_TOP_CLKEN_BASE		(CLK_TOP_PLL_BASE        +  2)
+#define CLK_TOP_MAX			(CLK_TOP_CLKEN_BASE      +  1)
+
+
+/* CR_TOP_CLKSWITCH clocks */
+#define CLK_TOP_SYS_SW			(CLK_TOP_CLKSWITCH_BASE + 0)
+#define CLK_TOP_SYS_X2_UNDELETED	(CLK_TOP_CLKSWITCH_BASE + 1)
+#define CLK_TOP_OUT0_SW0		(CLK_TOP_CLKSWITCH_BASE + 2)
+#define CLK_TOP_OUT0_SW1		(CLK_TOP_CLKSWITCH_BASE + 3)
+#define CLK_TOP_OUT0_SW2		(CLK_TOP_CLKSWITCH_BASE + 4)
+#define CLK_TOP_OUT0_SW3		(CLK_TOP_CLKSWITCH_BASE + 5)
+#define CLK_TOP_OUT1_SW0		(CLK_TOP_CLKSWITCH_BASE + 6)
+#define CLK_TOP_OUT1_SW1		(CLK_TOP_CLKSWITCH_BASE + 7)
+#define CLK_TOP_OUT1_SW2		(CLK_TOP_CLKSWITCH_BASE + 8)
+#define CLK_TOP_OUT1_SW3		(CLK_TOP_CLKSWITCH_BASE + 9)
+#define CLK_TOP_I2S_SW2			(CLK_TOP_CLKSWITCH_BASE + 10)
+#define CLK_TOP_I2S_SW0			(CLK_TOP_CLKSWITCH_BASE + 11)
+#define CLK_TOP_I2S_SW1			(CLK_TOP_CLKSWITCH_BASE + 12)
+#define CLK_TOP_SCB_SW			(CLK_TOP_CLKSWITCH_BASE + 13)
+#define CLK_TOP_UART_SW			(CLK_TOP_CLKSWITCH_BASE + 14)
+#define CLK_TOP_EXT_STC0_SW		(CLK_TOP_CLKSWITCH_BASE + 15)
+#define CLK_TOP_EXT_STC1_SW		(CLK_TOP_CLKSWITCH_BASE + 16)
+#define CLK_TOP_USB_SW0			(CLK_TOP_CLKSWITCH_BASE + 17)
+#define CLK_TOP_USB_SW1			(CLK_TOP_CLKSWITCH_BASE + 18)
+#define CLK_TOP_AFE_SW0			(CLK_TOP_CLKSWITCH_BASE + 19)
+#define CLK_TOP_AFE_SW1			(CLK_TOP_CLKSWITCH_BASE + 20)
+#define CLK_TOP_ADCPLL_SW0		(CLK_TOP_CLKSWITCH_BASE + 21)
+#define CLK_TOP_ADCPLL_SW1		(CLK_TOP_CLKSWITCH_BASE + 22)
+#define CLK_TOP_ADCPLL_SW2		(CLK_TOP_CLKSWITCH_BASE + 23)
+#define CLK_TOP_ADCPLL_SW3		(CLK_TOP_CLKSWITCH_BASE + 24)
+#define CLK_TOP_USB_SW2			(CLK_TOP_CLKSWITCH_BASE + 25)
+#define CLK_TOP_USB_SW3			(CLK_TOP_CLKSWITCH_BASE + 26)
+
+/* CR_TOP_CLKENAB clocks */
+#define CLK_TOP_OUT0_EN			(CLK_TOP_CLKENAB_BASE + 0)
+#define CLK_TOP_OUT1_EN			(CLK_TOP_CLKENAB_BASE + 1)
+#define CLK_TOP_I2S_EN			(CLK_TOP_CLKENAB_BASE + 2)
+#define CLK_TOP_SCB			(CLK_TOP_CLKENAB_BASE + 3)
+#define CLK_TOP_UART_EN			(CLK_TOP_CLKENAB_BASE + 4)
+#define CLK_TOP_EXT_STC0		(CLK_TOP_CLKENAB_BASE + 5)
+#define CLK_TOP_EXT_STC1		(CLK_TOP_CLKENAB_BASE + 6)
+#define CLK_TOP_USB_EN			(CLK_TOP_CLKENAB_BASE + 7)
+#define CLK_TOP_ADCPLL_EN		(CLK_TOP_CLKENAB_BASE + 8)
+
+/* CR_TOP_CLKSWITCH2 clocks */
+#define CLK_TOP_PIXEL_SW0		(CLK_TOP_CLKSWITCH2_BASE + 0)
+#define CLK_TOP_PIXEL_SW1		(CLK_TOP_CLKSWITCH2_BASE + 1)
+#define CLK_TOP_PIXEL_SW2		(CLK_TOP_CLKSWITCH2_BASE + 2)
+#define CLK_TOP_PIXEL_SW3		(CLK_TOP_CLKSWITCH2_BASE + 3)
+#define CLK_TOP_PIXEL_SW4		(CLK_TOP_CLKSWITCH2_BASE + 4)
+#define CLK_TOP_IF1_SW			(CLK_TOP_CLKSWITCH2_BASE + 5)
+#define CLK_TOP_IF0_SW			(CLK_TOP_CLKSWITCH2_BASE + 6)
+#define CLK_TOP_DAC0_SW			(CLK_TOP_CLKSWITCH2_BASE + 7)
+#define CLK_TOP_UCC1_SW			(CLK_TOP_CLKSWITCH2_BASE + 8)
+#define CLK_TOP_UCC0_SW			(CLK_TOP_CLKSWITCH2_BASE + 9)
+
+/* CR_TOP_CLKENAB2 clocks */
+#define CLK_TOP_PIXEL_EN		(CLK_TOP_CLKENAB2_BASE + 0)
+#define CLK_TOP_IF1			(CLK_TOP_CLKENAB2_BASE + 1)
+#define CLK_TOP_IF0			(CLK_TOP_CLKENAB2_BASE + 2)
+#define CLK_TOP_EXT_ADC_EN		(CLK_TOP_CLKENAB2_BASE + 3)
+#define CLK_TOP_DAC0			(CLK_TOP_CLKENAB2_BASE + 4)
+#define CLK_TOP_SYS_UCC1		(CLK_TOP_CLKENAB2_BASE + 5)
+#define CLK_TOP_SYS_MTX			(CLK_TOP_CLKENAB2_BASE + 6)
+
+/* Clock deleters */
+#define CLK_TOP_SYS			(CLK_TOP_DEL_BASE + 0)
+#define CLK_TOP_META			(CLK_TOP_DEL_BASE + 1)
+#define CLK_TOP_UCC0			(CLK_TOP_DEL_BASE + 2)
+#define CLK_TOP_UCC1_DEL		(CLK_TOP_DEL_BASE + 3)
+
+/* Clock dividers */
+#define CLK_TOP_SYS_DIV			(CLK_TOP_DIV_BASE +  0)
+#define CLK_TOP_SYS_UNDELETED		(CLK_TOP_DIV_BASE +  1)
+#define CLK_TOP_AFE			(CLK_TOP_DIV_BASE +  2)
+#define CLK_TOP_ADCPLL_DIV		(CLK_TOP_DIV_BASE +  3)
+#define CLK_TOP_UART			(CLK_TOP_DIV_BASE +  4)
+#define CLK_TOP_PDM			(CLK_TOP_DIV_BASE +  5)
+#define CLK_TOP_SPI0			(CLK_TOP_DIV_BASE +  6)
+#define CLK_TOP_SPI1			(CLK_TOP_DIV_BASE +  7)
+#define CLK_TOP_I2SM			(CLK_TOP_DIV_BASE +  8)
+#define CLK_TOP_USB_PHY			(CLK_TOP_DIV_BASE +  9)
+#define CLK_TOP_SDHOST			(CLK_TOP_DIV_BASE + 10)
+#define CLK_TOP_RING_OSC		(CLK_TOP_DIV_BASE + 11)
+#define CLK_TOP_I2S			(CLK_TOP_DIV_BASE + 12)
+#define CLK_TOP_META_TRACE		(CLK_TOP_DIV_BASE + 13)
+#define CLK_TOP_PIXEL			(CLK_TOP_DIV_BASE + 14)
+#define CLK_TOP_OUT0			(CLK_TOP_DIV_BASE + 15)
+#define CLK_TOP_OUT1			(CLK_TOP_DIV_BASE + 16)
+#define CLK_TOP_DDR			(CLK_TOP_DIV_BASE + 17)
+
+/* PLL clocks */
+#define CLK_TOP_SYSPLL			(CLK_TOP_PLL_BASE + 0)
+#define CLK_TOP_ADCPLL			(CLK_TOP_PLL_BASE + 1)
+
+/* CR_TOP_CLKEN clocks */
+#define CLK_TOP_PDC			(CLK_TOP_CLKEN_BASE + 0)
+
+#endif
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 5591ea7..80e54bf 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -265,6 +265,7 @@
 		unsigned long fixed_rate, unsigned long fixed_accuracy);
 
 void of_fixed_clk_setup(struct device_node *np);
+void of_specified_clk_setup(struct device_node *np);
 
 /**
  * struct clk_gate - gating clock