Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 6/7] ARM: ux500: Add support for gpio-keys and Proximity Sensor for HREF
From: Lee Jones @ 2012-10-01 10:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349088228-8582-1-git-send-email-lee.jones@linaro.org>

Here we ensure the SFH7741 Proximity Sensor is registered through
gpio-keys when booting with Device Tree enabled.

Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 arch/arm/boot/dts/href.dtsi       |   11 +++++++++++
 arch/arm/boot/dts/hrefprev60.dts  |    6 ++++++
 arch/arm/boot/dts/hrefv60plus.dts |    6 ++++++
 3 files changed, 23 insertions(+)

diff --git a/arch/arm/boot/dts/href.dtsi b/arch/arm/boot/dts/href.dtsi
index 27baa44..592fb9d 100644
--- a/arch/arm/boot/dts/href.dtsi
+++ b/arch/arm/boot/dts/href.dtsi
@@ -16,6 +16,17 @@
 		reg = <0x00000000 0x20000000>;
 	};
 
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		button at 1 {
+			linux,code = <11>;
+			label = "SFH7741 Proximity Sensor";
+		};
+	};
+
 	soc-u9500 {
 		uart at 80120000 {
 			status = "okay";
diff --git a/arch/arm/boot/dts/hrefprev60.dts b/arch/arm/boot/dts/hrefprev60.dts
index 2dd28b9..0756f97 100644
--- a/arch/arm/boot/dts/hrefprev60.dts
+++ b/arch/arm/boot/dts/hrefprev60.dts
@@ -17,6 +17,12 @@
 	model = "ST-Ericsson HREF (pre-v60) platform with Device Tree";
 	compatible = "st-ericsson,mop500";
 
+	gpio_keys {
+		button at 1 {
+			gpios = <&tc3589x_gpio 7 0x4>;
+		};
+	};
+
 	soc-u9500 {
 		i2c at 80004000 {
 			tps61052 at 33 {
diff --git a/arch/arm/boot/dts/hrefv60plus.dts b/arch/arm/boot/dts/hrefv60plus.dts
index 2a85893..4b867b2 100644
--- a/arch/arm/boot/dts/hrefv60plus.dts
+++ b/arch/arm/boot/dts/hrefv60plus.dts
@@ -16,4 +16,10 @@
 / {
 	model = "ST-Ericsson HREF (v60+) platform with Device Tree";
 	compatible = "st-ericsson,hrefv60+";
+
+	gpio_keys {
+		button at 1 {
+			gpios = <&gpio6 25 0x4>;
+		};
+	};
 };
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 7/7] ARM: ux500: Remove platform specific device registration when DT is enabled
From: Lee Jones @ 2012-10-01 10:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349088228-8582-1-git-send-email-lee.jones@linaro.org>

Most devices have now been successfully DT:ed and each supported
platform has its own Device Tree source file. Hence the majority
of the platform specific device registration calls can now be
successfully removed.

Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 arch/arm/mach-ux500/board-mop500.c |   29 +----------------------------
 1 file changed, 1 insertion(+), 28 deletions(-)

diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index 38e53b2..5dd4a59 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -793,8 +793,6 @@ static const struct of_device_id u8500_local_bus_nodes[] = {
 static void __init u8500_init_machine(void)
 {
 	struct device *parent = NULL;
-	int i2c0_devs;
-	int i;
 
 	/* Pinmaps must be in place before devices register */
 	if (of_machine_is_compatible("st-ericsson,mop500"))
@@ -804,37 +802,12 @@ static void __init u8500_init_machine(void)
 	else if (of_machine_is_compatible("st-ericsson,hrefv60+"))
 		hrefv60_pinmaps_init();
 
+	/* TODO: Export SoC, USB, cpu-freq and DMA40 */
 	parent = u8500_of_init_devices();
 
-	for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++)
-		mop500_platform_devs[i]->dev.parent = parent;
-
 	/* automatically probe child nodes of db8500 device */
 	of_platform_populate(NULL, u8500_local_bus_nodes, u8500_auxdata_lookup, parent);
 
-	if (of_machine_is_compatible("st-ericsson,mop500")) {
-		mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
-
-		platform_add_devices(mop500_platform_devs,
-				ARRAY_SIZE(mop500_platform_devs));
-
-		mop500_audio_init(parent);
-		i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
-		i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
-		i2c_register_board_info(2, mop500_i2c2_devices,
-					ARRAY_SIZE(mop500_i2c2_devices));
-
-	} else if (of_machine_is_compatible("st-ericsson,hrefv60+")) {
-		/*
-		 * The HREFv60 board removed a GPIO expander and routed
-		 * all these GPIO pins to the internal GPIO controller
-		 * instead.
-		 */
-		mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
-		platform_add_devices(mop500_platform_devs,
-				ARRAY_SIZE(mop500_platform_devs));
-	}
-
 	/* This board has full regulator constraints */
 	regulator_has_full_constraints();
 }
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH] [ARM] Build failure CONFIG_ARCH_KIRKWOOD_DT relies on CACHE_FEROCEON_L2
From: Jason Cooper @ 2012-10-01 10:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAOesGMgpDs60jGsV4Wu-A7M+ThXh7YVkgb_mPgMJfPwNa_QbSw@mail.gmail.com>

On Sun, Sep 30, 2012 at 07:44:10PM -0700, Olof Johansson wrote:
> Hi,
> 
> On Sun, Sep 30, 2012 at 4:22 PM, Jason Gunthorpe
> <jgunthorpe@obsidianresearch.com> wrote:
> > Move the CACHE_FEROCEON_L2 test to kirkwood_l2_init, since linking
> > fails on the reference to feroceon_l2_init.
> >
> > Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
> > ---
> >  arch/arm/mach-kirkwood/board-dt.c |    2 --
> >  arch/arm/mach-kirkwood/common.c   |    4 ++--
> >  2 files changed, 2 insertions(+), 4 deletions(-)
> >
> > diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c
> > index e4eb450..d00223e 100644
> > --- a/arch/arm/mach-kirkwood/board-dt.c
> > +++ b/arch/arm/mach-kirkwood/board-dt.c
> > @@ -50,9 +50,7 @@ static void __init kirkwood_dt_init(void)
> >
> >         kirkwood_setup_cpu_mbus();
> >
> > -#ifdef CONFIG_CACHE_FEROCEON_L2
> >         kirkwood_l2_init();
> > -#endif
> >
> >         /* Setup root of clk tree */
> >         kirkwood_clk_init();
> > diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
> > index 1201191..4177304 100644
> > --- a/arch/arm/mach-kirkwood/common.c
> > +++ b/arch/arm/mach-kirkwood/common.c
> > @@ -645,6 +645,7 @@ char * __init kirkwood_id(void)
> >
> >  void __init kirkwood_l2_init(void)
> >  {
> > +#ifdef CONFIG_CACHE_FEROCEON_L2
> >  #ifdef CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH
> 
> Aren't these added ifdefs completely redundant? L2_WRITETHROUGH is
> dependent on the outer options anyway.

I thought so as well, so I went and looked at the code.  There is a
#else between the original #ifdef/#endif pair.  So, feroceon_l2_init()
gets called in both cases.

hth,

Jason.

^ permalink raw reply

* [PATCHv3 0/4] Add mfd driver for smsc-ece1099 chip
From: Sourav Poddar @ 2012-10-01 11:00 UTC (permalink / raw)
  To: linux-arm-kernel

Add a smsc-ece1099 mfd driver which will work as
keypad scan device or a gpio expander device.

Patch 1 creates the parent mfd driver.
Patch 2 add keypad support. Patch 3 adds dts
support for keypad in omap5 dts file.
Patch 4 add gpio expansion driver for chip (RFC).

Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Felipe Balbi <balbi@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>

G, Manjunath Kondaiah (1):
  Input: keypad: Add smsc ece1099 keypad driver

Sourav Poddar (3):
  mfd: smsc: Add support for smsc gpio io/keypad driver
  arm/dts: omap5-evm: Add keypad support
  gpio: smscece: Add support for gpio IO expander feature

 Documentation/smsc_ece1099.txt               |   56 ++++
 arch/arm/boot/dts/omap5-evm.dts              |   95 +++++++
 drivers/gpio/Kconfig                         |    7 +
 drivers/gpio/Makefile                        |    1 +
 drivers/gpio/gpio-smscece.c                  |  381 ++++++++++++++++++++++++++
 drivers/input/keyboard/Kconfig               |   11 +
 drivers/input/keyboard/Makefile              |    1 +
 drivers/input/keyboard/smsc-ece1099-keypad.c |  304 ++++++++++++++++++++
 drivers/mfd/Kconfig                          |   12 +
 drivers/mfd/Makefile                         |    1 +
 drivers/mfd/smsc-ece1099.c                   |  113 ++++++++
 include/linux/mfd/smsc.h                     |  109 ++++++++
 12 files changed, 1091 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/smsc_ece1099.txt
 create mode 100644 drivers/gpio/gpio-smscece.c
 create mode 100644 drivers/input/keyboard/smsc-ece1099-keypad.c
 create mode 100644 drivers/mfd/smsc-ece1099.c
 create mode 100644 include/linux/mfd/smsc.h

^ permalink raw reply

* [PATCHv3 1/4] mfd: smsc: Add support for smsc gpio io/keypad driver
From: Sourav Poddar @ 2012-10-01 11:01 UTC (permalink / raw)
  To: linux-arm-kernel

smsc ece1099 is a keyboard scan or gpio expansion device.
The patch create keypad and gpio expander child for this
multi function smsc driver.

Tested on omap5430 evm with 3.6-rc6 custom kernel.

Cc: Samuel Ortiz <sameo@linux.intel.com>
Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Felipe Balbi <balbi@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
---
Changes since v2:
 - Change the cache type, max register assignment
 - remove of_device_table, since i2c based device gets 
probed according to i2c_device_id through dt.
 - Modify the remove function
 - Minor return patch cleanups.
 Documentation/smsc_ece1099.txt |   56 ++++++++++++++++++++
 drivers/mfd/Kconfig            |   12 ++++
 drivers/mfd/Makefile           |    1 +
 drivers/mfd/smsc-ece1099.c     |  113 ++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/smsc.h       |  109 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 291 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/smsc_ece1099.txt
 create mode 100644 drivers/mfd/smsc-ece1099.c
 create mode 100644 include/linux/mfd/smsc.h

diff --git a/Documentation/smsc_ece1099.txt b/Documentation/smsc_ece1099.txt
new file mode 100644
index 0000000..6b492e8
--- /dev/null
+++ b/Documentation/smsc_ece1099.txt
@@ -0,0 +1,56 @@
+What is smsc-ece1099?
+----------------------
+
+The ECE1099 is a 40-Pin 3.3V Keyboard Scan Expansion
+or GPIO Expansion device. The device supports a keyboard
+scan matrix of 23x8. The device is connected to a Master
+via the SMSC BC-Link interface or via the SMBus.
+Keypad scan Input(KSI) and Keypad Scan Output(KSO) signals
+are multiplexed with GPIOs.
+
+Interrupt generation
+--------------------
+
+Interrupts can be generated by an edge detection on a GPIO
+pin or an edge detection on one of the bus interface pins.
+Interrupts can also be detected on the keyboard scan interface.
+The bus interrupt pin (BC_INT# or SMBUS_INT#) is asserted if
+any bit in one of the Interrupt Status registers is 1 and
+the corresponding Interrupt Mask bit is also 1.
+
+In order for software to determine which device is the source
+of an interrupt, it should first read the Group Interrupt Status Register
+to determine which Status register group is a source for the interrupt.
+Software should read both the Status register and the associated Mask register,
+then AND the two values together. Bits that are 1 in the result of the AND
+are active interrupts. Software clears an interrupt by writing a 1 to the
+corresponding bit in the Status register.
+
+Communication Protocol
+----------------------
+
+- SMbus slave Interface
+	The host processor communicates with the ECE1099 device
+	through a series of read/write registers via the SMBus
+	interface. SMBus is a serial communication protocol between
+	a computer host and its peripheral devices. The SMBus data
+	rate is 10KHz minimum to 400 KHz maximum
+
+- Slave Bus Interface
+	The ECE1099 device SMBus implementation is a subset of the
+	SMBus interface to the host. The device is a slave-only SMBus device.
+	The implementation in the device is a subset of SMBus since it
+	only supports four protocols.
+
+	The Write Byte, Read Byte, Send Byte, and Receive Byte protocols are the
+	only valid SMBus protocols for the device.
+
+- BC-LinkTM Interface
+	The BC-Link is a proprietary bus that allows communication
+	between a Master device and a Companion device. The Master
+	device uses this serial bus to read and write registers
+	located on the Companion device. The bus comprises three signals,
+	BC_CLK, BC_DAT and BC_INT#. The Master device always provides the
+	clock, BC_CLK, and the Companion device is the source for an
+	independent asynchronous interrupt signal, BC_INT#. The ECE1099
+	supports BC-Link speeds up to 24MHz.
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index b1a1462..dedc874 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -385,6 +385,18 @@ config MFD_T7L66XB
 	help
 	  Support for Toshiba Mobile IO Controller T7L66XB
 
+config MFD_SMSC
+       bool "Support for the SMSC ECE1099 series chips"
+       depends on I2C=y
+       select MFD_CORE
+       select REGMAP_I2C
+       help
+        If you say yes here you get support for the
+        ece1099 chips from SMSC.
+
+        To compile this driver as a module, choose M here: the
+        module will be called smsc.
+
 config MFD_TC6387XB
 	bool "Support Toshiba TC6387XB"
 	depends on ARM && HAVE_CLK
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 79dd22d..3323345 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_EZX_PCAP)		+= ezx-pcap.o
 obj-$(CONFIG_MCP)		+= mcp-core.o
 obj-$(CONFIG_MCP_SA11X0)	+= mcp-sa11x0.o
 obj-$(CONFIG_MCP_UCB1200)	+= ucb1x00-core.o
+obj-$(CONFIG_MFD_SMSC)        += smsc-ece1099.o
 obj-$(CONFIG_MCP_UCB1200_TS)	+= ucb1x00-ts.o
 
 ifeq ($(CONFIG_SA1100_ASSABET),y)
diff --git a/drivers/mfd/smsc-ece1099.c b/drivers/mfd/smsc-ece1099.c
new file mode 100644
index 0000000..220aec2
--- /dev/null
+++ b/drivers/mfd/smsc-ece1099.c
@@ -0,0 +1,113 @@
+/*
+ * TI SMSC MFD Driver
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Author: Sourav Poddar <sourav.poddar@ti.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;  GPL v2.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/workqueue.h>
+#include <linux/irq.h>
+#include <linux/regmap.h>
+#include <linux/err.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/smsc.h>
+#include <linux/of_platform.h>
+
+static struct regmap_config smsc_regmap_config = {
+		.reg_bits = 8,
+		.val_bits = 8,
+		.max_register = SMSC_VEN_ID_H,
+		.cache_type = REGCACHE_RBTREE,
+};
+
+static int smsc_i2c_probe(struct i2c_client *i2c,
+			const struct i2c_device_id *id)
+{
+	struct device_node              *node = i2c->dev.of_node;
+	struct smsc *smsc;
+	int devid, rev, venid_l, venid_h;
+	int ret = 0;
+
+	smsc = devm_kzalloc(&i2c->dev, sizeof(struct smsc),
+				GFP_KERNEL);
+	if (!smsc) {
+		dev_err(&i2c->dev, "smsc mfd driver memory allocation failed\n");
+		return -ENOMEM;
+	}
+
+	smsc->regmap = devm_regmap_init_i2c(i2c, &smsc_regmap_config);
+	if (IS_ERR(smsc->regmap)) {
+		ret = PTR_ERR(smsc->regmap);
+		goto err;
+	}
+
+	i2c_set_clientdata(i2c, smsc);
+	smsc->dev = &i2c->dev;
+
+#ifdef CONFIG_OF
+	of_property_read_u32(node, "clock", &smsc->clk);
+#endif
+
+	regmap_read(smsc->regmap, SMSC_DEV_ID, &devid);
+	regmap_read(smsc->regmap, SMSC_DEV_REV, &rev);
+	regmap_read(smsc->regmap, SMSC_VEN_ID_L, &venid_l);
+	regmap_read(smsc->regmap, SMSC_VEN_ID_H, &venid_h);
+
+	dev_info(&i2c->dev, "SMSCxxx devid: %02x rev: %02x venid: %02x\n",
+		devid, rev, (venid_h << 8) | venid_l);
+
+	ret = regmap_write(smsc->regmap, SMSC_CLK_CTRL, smsc->clk);
+	if (ret)
+		goto err;
+
+#ifdef CONFIG_OF
+	if (node)
+		ret = of_platform_populate(node, NULL, NULL, &i2c->dev);
+#endif
+
+err:
+	return ret;
+}
+
+static int smsc_i2c_remove(struct i2c_client *i2c)
+{
+	struct smsc *smsc = i2c_get_clientdata(i2c);
+
+	mfd_remove_devices(smsc->dev);
+
+	return 0;
+}
+
+static const struct i2c_device_id smsc_i2c_id[] = {
+	{ "smscece1099", 0},
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, smsc_i2c_id);
+
+static struct i2c_driver smsc_i2c_driver = {
+	.driver = {
+		   .name = "smsc",
+		   .owner = THIS_MODULE,
+	},
+	.probe = smsc_i2c_probe,
+	.remove = smsc_i2c_remove,
+	.id_table = smsc_i2c_id,
+};
+
+module_i2c_driver(smsc_i2c_driver);
+
+MODULE_AUTHOR("Sourav Poddar <sourav.poddar@ti.com>");
+MODULE_DESCRIPTION("SMSC chip multi-function driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/smsc.h b/include/linux/mfd/smsc.h
new file mode 100644
index 0000000..9747b29
--- /dev/null
+++ b/include/linux/mfd/smsc.h
@@ -0,0 +1,109 @@
+/*
+ * SMSC ECE1099
+ *
+ * Copyright 2012 Texas Instruments Inc.
+ *
+ * Author: Sourav Poddar <sourav.poddar@ti.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.
+ *
+ */
+
+#ifndef __LINUX_MFD_SMSC_H
+#define __LINUX_MFD_SMSC_H
+
+#include <linux/regmap.h>
+
+#define SMSC_ID_ECE1099			1
+#define SMSC_NUM_CLIENTS		2
+
+#define SMSC_BASE_ADDR			0x38
+#define OMAP_GPIO_SMSC_IRQ		151
+
+#define SMSC_MAXGPIO         32
+#define SMSC_BANK(offs)      ((offs) >> 3)
+#define SMSC_BIT(offs)       (1u << ((offs) & 0x7))
+
+struct smsc {
+	struct device *dev;
+	struct i2c_client *i2c_clients[SMSC_NUM_CLIENTS];
+	struct regmap *regmap;
+	int clk;
+	/* Stored chip id */
+	int id;
+};
+
+struct smsc_gpio;
+struct smsc_keypad;
+
+static inline int smsc_read(struct device *child, unsigned int reg,
+	unsigned int *dest)
+{
+	struct smsc     *smsc = dev_get_drvdata(child->parent);
+
+	return regmap_read(smsc->regmap, reg, dest);
+}
+
+static inline int smsc_write(struct device *child, unsigned int reg,
+	unsigned int value)
+{
+	struct smsc     *smsc = dev_get_drvdata(child->parent);
+
+	return regmap_write(smsc->regmap, reg, value);
+}
+
+/* Registers for SMSC */
+#define SMSC_RESET						0xF5
+#define SMSC_GRP_INT						0xF9
+#define SMSC_CLK_CTRL						0xFA
+#define SMSC_WKUP_CTRL						0xFB
+#define SMSC_DEV_ID						0xFC
+#define SMSC_DEV_REV						0xFD
+#define SMSC_VEN_ID_L						0xFE
+#define SMSC_VEN_ID_H						0xFF
+
+/* CLK VALUE */
+#define SMSC_CLK_VALUE						0x13
+
+/* Registers for function GPIO INPUT */
+#define SMSC_GPIO_DATA_IN_START					0x00
+
+/* Registers for function GPIO OUPUT */
+#define SMSC_GPIO_DATA_OUT_START                                       0x05
+
+/* Definitions for SMSC GPIO CONFIGURATION REGISTER*/
+#define SMSC_GPIO_INPUT_LOW					0x01
+#define SMSC_GPIO_INPUT_RISING					0x09
+#define SMSC_GPIO_INPUT_FALLING					0x11
+#define SMSC_GPIO_INPUT_BOTH_EDGE				0x19
+#define SMSC_GPIO_OUTPUT_PP					0x21
+#define SMSC_GPIO_OUTPUT_OP					0x31
+
+#define GRP_INT_STAT						0xf9
+#define	SMSC_GPI_INT						0x0f
+#define SMSC_CFG_START						0x0A
+
+/* Registers for SMSC GPIO INTERRUPT STATUS REGISTER*/
+#define SMSC_GPIO_INT_STAT_START                                  0x32
+
+/* Registers for SMSC GPIO INTERRUPT MASK REGISTER*/
+#define SMSC_GPIO_INT_MASK_START                               0x37
+
+/* Registers for SMSC function KEYPAD*/
+#define SMSC_KP_OUT						0x40
+#define SMSC_KP_IN						0x41
+#define SMSC_KP_INT_STAT					0x42
+#define SMSC_KP_INT_MASK					0x43
+
+/* Definitions for keypad */
+#define SMSC_KP_KSO           0x70
+#define SMSC_KP_KSI           0x51
+#define SMSC_KSO_ALL_LOW        0x20
+#define SMSC_KP_SET_LOW_PWR        0x0B
+#define SMSC_KP_SET_HIGH           0xFF
+#define SMSC_KSO_EVAL           0x00
+
+#endif /*  __LINUX_MFD_SMSC_H */
-- 
1.7.1

^ permalink raw reply related

* [PATCHv3 2/4] Input: keypad: Add smsc ece1099 keypad driver
From: Sourav Poddar @ 2012-10-01 11:01 UTC (permalink / raw)
  To: linux-arm-kernel

From: G, Manjunath Kondaiah <manjugk@ti.com>

SMSC ECE1099 is a keyboard scan or GPIO expansion device.The device
supports a keypad scan matrix of 23*8.This driver uses this
device as a keypad driver.

Tested on omap5430 evm with 3.6-rc6 custom kernel.

Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Felipe Balbi <balbi@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
---
Changes since v2:
 - Replace magic numbers through driver variable.
 - Provide comments for some initialisation done in probe.
 drivers/input/keyboard/Kconfig               |   11 +
 drivers/input/keyboard/Makefile              |    1 +
 drivers/input/keyboard/smsc-ece1099-keypad.c |  304 ++++++++++++++++++++++++++
 3 files changed, 316 insertions(+), 0 deletions(-)
 create mode 100644 drivers/input/keyboard/smsc-ece1099-keypad.c

diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index c50fa75..b03a39c 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -593,6 +593,17 @@ config KEYBOARD_TWL4030
 	  To compile this driver as a module, choose M here: the
 	  module will be called twl4030_keypad.
 
+config KEYBOARD_SMSC
+       tristate "SMSC ECE1099 keypad support"
+       depends on I2C
+       help
+         Say Y here if your board use the smsc keypad controller
+         for omap5 defconfig. It's safe to say enable this
+         even on boards that don't use the keypad controller.
+
+         To compile this driver as a module, choose M here: the
+         module will be called smsc-ece1099-keypad.
+
 config KEYBOARD_XTKBD
 	tristate "XT keyboard"
 	select SERIO
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 44e7600..0f2aa26 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -52,5 +52,6 @@ obj-$(CONFIG_KEYBOARD_TC3589X)		+= tc3589x-keypad.o
 obj-$(CONFIG_KEYBOARD_TEGRA)		+= tegra-kbc.o
 obj-$(CONFIG_KEYBOARD_TNETV107X)	+= tnetv107x-keypad.o
 obj-$(CONFIG_KEYBOARD_TWL4030)		+= twl4030_keypad.o
+obj-$(CONFIG_KEYBOARD_SMSC)            += smsc-ece1099-keypad.o
 obj-$(CONFIG_KEYBOARD_XTKBD)		+= xtkbd.o
 obj-$(CONFIG_KEYBOARD_W90P910)		+= w90p910_keypad.o
diff --git a/drivers/input/keyboard/smsc-ece1099-keypad.c b/drivers/input/keyboard/smsc-ece1099-keypad.c
new file mode 100644
index 0000000..15dc147
--- /dev/null
+++ b/drivers/input/keyboard/smsc-ece1099-keypad.c
@@ -0,0 +1,304 @@
+/*
+ * SMSC_ECE1099 Keypad driver
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/input/matrix_keypad.h>
+#include <linux/delay.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/smsc.h>
+#include <linux/of_gpio.h>
+#include <linux/of.h>
+
+#define KEYPRESS_TIME          200
+
+struct smsc_keypad {
+	struct smsc *smsc;
+	struct matrix_keymap_data *keymap_data;
+	unsigned int last_key_state[16];
+	unsigned int last_col;
+	unsigned int last_key_ms[16];
+	unsigned short *keymap;
+	struct i2c_client *client;
+	struct input_dev *input;
+	int rows, cols;
+	int row_shift;
+	bool no_autorepeat;
+	unsigned        irq;
+	struct device *dev;
+};
+
+static void smsc_kp_scan(struct smsc_keypad *kp)
+{
+	struct input_dev *input = kp->input;
+	int i, j;
+	int row, col;
+	int temp, code;
+	unsigned int new_state[16];
+	unsigned int bits_changed;
+	int this_ms;
+
+	smsc_write(kp->dev, SMSC_KP_INT_MASK, 0x00);
+	smsc_write(kp->dev, SMSC_KP_INT_STAT, 0xFF);
+
+	/* Scan for row and column */
+	for (i = 0; i < kp->cols; i++) {
+		smsc_write(kp->dev, SMSC_KP_OUT, SMSC_KSO_EVAL + i);
+		/* Read Row Status */
+		smsc_read(kp->dev, SMSC_KP_IN, &temp);
+		if (temp == 0xFF)
+			continue;
+
+		col = i;
+		for (j = 0; j < kp->rows; j++) {
+			if ((temp & 0x01) != 0x00) {
+				temp = temp >> 1;
+				continue;
+			}
+
+			row = j;
+			new_state[col] =  (1 << row);
+			bits_changed = kp->last_key_state[col] ^ new_state[col];
+			this_ms = jiffies_to_msecs(jiffies);
+			if (bits_changed != 0 || (!bits_changed &&
+					((this_ms - kp->last_key_ms[col]) >= KEYPRESS_TIME))) {
+				code = MATRIX_SCAN_CODE(row, col, kp->row_shift);
+				input_event(input, EV_MSC, MSC_SCAN, code);
+				input_report_key(input, kp->keymap[code], 1);
+				input_report_key(input, kp->keymap[code], 0);
+				kp->last_key_state[col] = new_state[col];
+				if (kp->last_col != col)
+					kp->last_key_state[kp->last_col] = 0;
+				kp->last_key_ms[col] = this_ms;
+			}
+			temp = temp >> 1;
+		}
+	}
+	input_sync(input);
+
+	smsc_write(kp->dev, SMSC_KP_INT_MASK, 0xFF);
+
+	/* Set up Low Power Mode (Wake-up) (0xFB) */
+	smsc_write(kp->dev, SMSC_WKUP_CTRL, SMSC_KP_SET_LOW_PWR);
+
+	/*Enable Keypad Scan (generate interrupt on key press) (0x40)*/
+	smsc_write(kp->dev, SMSC_KP_OUT, SMSC_KSO_ALL_LOW);
+}
+
+static irqreturn_t do_kp_irq(int irq, void *_kp)
+{
+	struct smsc_keypad *kp = _kp;
+	int int_status;
+
+	smsc_read(kp->dev, SMSC_KP_INT_STAT, &int_status);
+	if (int_status)
+		smsc_kp_scan(kp);
+
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_OF
+static int __devinit smsc_keypad_parse_dt(struct device *dev,
+				struct smsc_keypad *kp)
+{
+	struct device_node *np = dev->of_node;
+
+	if (!np) {
+		dev_err(dev, "missing DT data");
+		return -EINVAL;
+	}
+
+	of_property_read_u32(np, "keypad,num-rows", &kp->rows);
+	of_property_read_u32(np, "keypad,num-columns", &kp->cols);
+	if (!kp->rows || !kp->cols) {
+		dev_err(dev, "number of keypad rows/columns not specified\n");
+		return -EINVAL;
+	}
+
+	if (of_property_read_bool(np, "linux,input-no-autorepeat"))
+		kp->no_autorepeat = true;
+
+	return 0;
+}
+#else
+static inline int smsc_keypad_parse_dt(struct device *dev,
+				struct smsc_keypad *kp)
+{
+	return -ENOSYS;
+}
+#endif
+
+static int __devinit
+smsc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct smsc *smsc = dev_get_drvdata(pdev->dev.parent);
+	struct input_dev *input;
+	struct smsc_keypad *kp;
+	int ret = 0, error;
+	int col, i, max_keys, row_shift;
+	int irq;
+	int addr;
+
+	kp = devm_kzalloc(dev, sizeof(*kp), GFP_KERNEL);
+
+	input = input_allocate_device();
+	if (!kp || !input) {
+		error = -ENOMEM;
+		goto err1;
+	}
+
+	error = smsc_keypad_parse_dt(&pdev->dev, kp);
+	if (error)
+		return error;
+
+	/* Get the debug Device */
+	kp->input = input;
+	kp->smsc = smsc;
+	kp->irq = platform_get_irq(pdev, 0);
+	kp->dev = dev;
+
+	for (col = 0; col < 16; col++) {
+		kp->last_key_state[col] = 0;
+		kp->last_key_ms[col] = 0;
+	}
+
+	/* setup input device */
+	 __set_bit(EV_KEY, input->evbit);
+
+	/* Enable auto repeat feature of Linux input subsystem */
+	if (!(kp->no_autorepeat))
+		__set_bit(EV_REP, input->evbit);
+
+	input_set_capability(input, EV_MSC, MSC_SCAN);
+	input->name             = "SMSC Keypad";
+	input->phys             = "smsc_keypad/input0";
+	input->dev.parent       = &pdev->dev;
+	input->id.bustype       = BUS_HOST;
+	input->id.vendor        = 0x0001;
+	input->id.product       = 0x0001;
+	input->id.version       = 0x0003;
+
+	error = input_register_device(input);
+	if (error) {
+		dev_err(kp->dev,
+			"Unable to register twl4030 keypad device\n");
+		goto err1;
+	}
+
+	/* Mask all GPIO interrupts (0x37-0x3B) */
+	for (addr = SMSC_GPIO_INT_MASK_START;
+			addr < SMSC_GPIO_INT_MASK_START + 4; addr++)
+		smsc_write(dev, addr, 0);
+
+	/* Set all outputs high (0x05-0x09) */
+	for (addr = SMSC_GPIO_DATA_OUT_START;
+			addr < SMSC_GPIO_DATA_OUT_START + 4; addr++)
+		smsc_write(dev, addr, 0xff);
+
+	/* Clear all GPIO interrupts (0x32-0x36) */
+	for (addr = SMSC_GPIO_INT_STAT_START;
+			addr < SMSC_GPIO_INT_STAT_START + 4; addr++)
+		smsc_write(dev, addr, 0xff);
+
+	/* Configure the smsc pins as Keyboard scan Input */
+	for (i = 0; i <= kp->rows; i++) {
+		addr = 0x12 + i;
+		smsc_write(dev, addr, SMSC_KP_KSI);
+	}
+
+	/* Configure the smsc pins as Keyboard scan output */
+	for (i = 0; i <= kp->cols; i++) {
+		addr = 0x1A + i;
+		smsc_write(dev, addr, SMSC_KP_KSO);
+	}
+
+	smsc_write(dev, SMSC_KP_INT_STAT, SMSC_KP_SET_HIGH);
+	smsc_write(dev, SMSC_WKUP_CTRL, SMSC_KP_SET_LOW_PWR);
+	smsc_write(dev, SMSC_KP_OUT, SMSC_KSO_ALL_LOW);
+
+	row_shift = get_count_order(kp->cols);
+	max_keys = kp->rows << row_shift;
+
+	kp->row_shift = row_shift;
+	kp->keymap = devm_kzalloc(dev, max_keys * sizeof(kp->keymap[0]),
+					GFP_KERNEL);
+	if (!kp->keymap) {
+		dev_err(&pdev->dev, "Not enough memory for keymap\n");
+		error = -ENOMEM;
+	}
+
+	matrix_keypad_build_keymap(NULL, NULL, kp->rows,
+			kp->cols, kp->keymap, input);
+
+	/*
+	* This ISR will always execute in kernel thread context because of
+	* the need to access the SMSC over the I2C bus.
+	*/
+	ret = devm_request_threaded_irq(dev, kp->irq, NULL, do_kp_irq,
+			IRQF_TRIGGER_FALLING | IRQF_ONESHOT, pdev->name, kp);
+	if (ret) {
+		dev_dbg(&pdev->dev, "request_irq failed for irq no=%d\n",
+			irq);
+		goto err2;
+	}
+
+	/* Enable smsc keypad interrupts */
+	ret = smsc_write(dev, SMSC_KP_INT_MASK, 0xff);
+	if (ret < 0)
+		goto err2;
+
+	return 0;
+
+err2:
+	input_unregister_device(input);
+err1:
+	input_free_device(input);
+	return ret;
+}
+
+static int __devexit smsc_remove(struct platform_device *pdev)
+{
+	struct smsc_keypad *kp = platform_get_drvdata(pdev);
+	input_unregister_device(kp->input);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id smsc_keypad_dt_match[] = {
+	{ .compatible = "smsc,keypad" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, smsc_keypad_dt_match);
+#endif
+
+static struct platform_driver smsc_driver = {
+	.driver = {
+		.name	= "smsc-keypad",
+		.of_match_table = of_match_ptr(smsc_keypad_dt_match),
+		.owner  = THIS_MODULE,
+	},
+	.probe		= smsc_probe,
+	.remove		= __devexit_p(smsc_remove),
+};
+
+module_platform_driver(smsc_driver);
+
+MODULE_AUTHOR("G Kondaiah Manjunath <manjugk@ti.com>");
+MODULE_DESCRIPTION("SMSC ECE1099 Keypad driver");
+MODULE_LICENSE("GPL v2");
-- 
1.7.1

^ permalink raw reply related

* [PATCHv3 3/4] arm/dts: omap5-evm: Add keypad support
From: Sourav Poddar @ 2012-10-01 11:02 UTC (permalink / raw)
  To: linux-arm-kernel

Add keypad data node in omap5-evm.

Based on I2C support patch for omap5, which has been
already posted as a different series.

Tested on omap5430 evm with 3.6-rc6 custom kernel.

Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Felipe Balbi <balbi@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>

Tested on omap5430 sdp with 3.666666 custom kernel.

Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
---
Changes since v2:
 - Change the compatible string name.
 arch/arm/boot/dts/omap5-evm.dts |   95 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 95 insertions(+), 0 deletions(-)

diff --git a/arch/arm/boot/dts/omap5-evm.dts b/arch/arm/boot/dts/omap5-evm.dts
index 200c39a..2d8903b 100644
--- a/arch/arm/boot/dts/omap5-evm.dts
+++ b/arch/arm/boot/dts/omap5-evm.dts
@@ -18,3 +18,98 @@
 		reg = <0x80000000 0x40000000>; /* 1 GB */
 	};
 };
+
+&i2c5 {
+	clock-frequency = <400000>;
+
+	smsc at 38 {
+		compatible = "smscece1099";
+		reg = <0x38>;
+		clock = <0x13>;
+		keypad {
+			compatible = "smsc,keypad";
+			interrupt-parent = <&gpio5>;
+			interrupts = <23>; /* gpio line 151 */
+			keypad,num-rows = <8>;
+			keypad,num-columns = <16>;
+			linux,keymap = < 0x20041 /* KEY_F7 */
+					0x30001 /* KEY_ESC */
+					0x4003e /* KEY_F4 */
+					0x50022 /* KEY_G */
+					0x70023 /* KEY_H */
+					0x9009a /* KEY_CYCLEWINDOWS */
+					0xc000e /* KEY_BACKSPACE */
+					0xd0057 /* KEY_F11 */
+					0xe009f /* KEY_FORWARD */
+					0xf006e /* KEY_INSERT */
+					0x1020036 /* KEY_RIGHTSHIFT */
+					0x1030011 /* KEY_W */
+					0x1040010 /* KEY_Q */
+					0x1050012 /* KEY_E */
+					0x1070013 /* KEY_R */
+					0x1080016 /* KEY_U */
+					0x10c0017 /* KEY_I */
+					0x10d0067 /* KEY_UP */
+					0x10e0018 /* KEY_O */
+					0x10f0019 /* KEY_LEFT */
+					0x2020003 /* KEY_2 */
+					0x2040004 /* KEY_1 */
+					0x2050005 /* KEY_3 */
+					0x2070008 /* KEY_4 */
+					0x2080009 /* KEY_7 */
+					0x20b0064 /* KEY_8 */
+					0x20c006c /* KEY_RIGHTALT */
+					0x20d000a /* KEY_DOWN */
+					0x20e0001 /* KEY_0 */
+					0x20f006a /* KEY_RIGHT */
+					0x3010061 /* KEY_RIGHTCTRL */
+					0x302001f /* KEY_S */
+					0x303001e /* KEY_A */
+					0x3040020 /* KEY_D */
+					0x3050021 /* KEY_F */
+					0x3070024 /* KEY_J */
+					0x3080025 /* KEY_K */
+					0x30c001c /* KEY_ENTER */
+					0x30d0026 /* KEY_L */
+					0x30e0027 /* KEY_SEMICOLON */
+					0x400002a /* KEY_LEFTSHIFT */
+					0x402002d /* KEY_X */
+					0x403002c /* KEY_Z */
+					0x404002e /* KEY_C */
+					0x405002f /* KEY_V */
+					0x4070032 /* KEY_M */
+					0x4080033 /* KEY_COMMA */
+					0x40c0039 /* KEY_SPACE */
+					0x40d0033 /* KEY_DOT */
+					0x40e0035 /* KEY_SLASH */
+					0x40f006b /* KEY_END */
+					0x501001d /* KEY_LEFTCTRL */
+					0x5020040 /* KEY_F6 */
+					0x503000f /* KEY_TAB */
+					0x504003d /* KEY_F3 */
+					0x5050014 /* KEY_T */
+					0x5070015 /* KEY_Y */
+					0x508001a /* KEY_LEFTBRACE */
+					0x50d0044 /* KEY_F10 */
+					0x50e001b /* KEY_RIGHTBRACE */
+					0x50f0066 /* KEY_HOME */
+					0x602003f /* KEY_F5 */
+					0x604003c /* KEY_F2 */
+					0x6050006 /* KEY_5 */
+					0x60601d0 /* KEY_FN */
+					0x6070007 /* KEY_6 */
+					0x60a008b /* KEY_MENU */
+					0x60c002b /* KEY_BACKSLASH */
+					0x60d0043 /* KEY_F9 */
+					0x7020042 /* KEY_F8 */
+					0x703003a /* KEY_CAPSLOCK */
+					0x704003b /* KEY_F1 */
+					0x7050030 /* KEY_B */
+					0x7070031 /* KEY_N */
+					0x70b0038 /* KEY_LEFTALT */
+					0x70d0058 /* KEY_F12 */
+					0x70f006f >; /* KEY_DELETE */
+			linux,input-no-autorepeat;
+		};
+	};
+};
-- 
1.7.1

^ permalink raw reply related

* [RFC/PATCHv3 4/4] gpio: smscece: Add support for gpio IO expander feature
From: Sourav Poddar @ 2012-10-01 11:02 UTC (permalink / raw)
  To: linux-arm-kernel

smsc can be used as an gpio io expander device also. So adding
support for configuring smsc pins as a gpio.

Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Felipe Balbi <balbi@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
---
Changes since v2:
 - Update the license.
 - Minor ret patch changes.
 drivers/gpio/Kconfig        |    7 +
 drivers/gpio/Makefile       |    1 +
 drivers/gpio/gpio-smscece.c |  381 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 389 insertions(+), 0 deletions(-)
 create mode 100644 drivers/gpio/gpio-smscece.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index ba7926f..68ea0a4 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -444,6 +444,13 @@ config GPIO_ADP5588_IRQ
 	  Say yes here to enable the adp5588 to be used as an interrupt
 	  controller. It requires the driver to be built in the kernel.
 
+config GPIO_SMSCECE
+	tristate "SMSCECE 1099 I2C GPIO expander"
+	depends on I2C
+	help
+	  This option enables support for 18 GPIOs found
+	  on SMSC ECE 1099 GPIO Expanders.
+
 comment "PCI GPIO expanders:"
 
 config GPIO_CS5535
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 153cace..7c803c5 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_GPIO_74X164)	+= gpio-74x164.o
 obj-$(CONFIG_GPIO_AB8500)	+= gpio-ab8500.o
 obj-$(CONFIG_GPIO_ADP5520)	+= gpio-adp5520.o
 obj-$(CONFIG_GPIO_ADP5588)	+= gpio-adp5588.o
+obj-$(CONFIG_GPIO_SMSCECE)      += gpio-smscece.o
 obj-$(CONFIG_GPIO_AMD8111)	+= gpio-amd8111.o
 obj-$(CONFIG_GPIO_ARIZONA)	+= gpio-arizona.o
 obj-$(CONFIG_GPIO_BT8XX)	+= gpio-bt8xx.o
diff --git a/drivers/gpio/gpio-smscece.c b/drivers/gpio/gpio-smscece.c
new file mode 100644
index 0000000..54e377a
--- /dev/null
+++ b/drivers/gpio/gpio-smscece.c
@@ -0,0 +1,381 @@
+/*
+ * GPIO Chip driver for smsc
+ * SMSC I/O Expander and QWERTY Keypad Controller
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
+#include <linux/mfd/smsc.h>
+#include <linux/err.h>
+
+struct smsc_gpio {
+	struct device *dev;
+	struct smsc *smsc;
+	struct gpio_chip gpio_chip;
+	struct mutex lock;	/* protect cached dir, dat_out */
+	/* protect serialized access to the interrupt controller bus */
+	struct mutex irq_lock;
+	struct irq_domain       *irq_domain;
+	unsigned gpio_start;
+	int type;
+	int flags;
+	int irq;
+	int irq_base;
+	unsigned int gpio_base;
+	unsigned int dat_out[5];
+	unsigned int dir[5];
+	unsigned int irq_trig_fall[5];
+	unsigned int irq_trig_raise[5];
+	unsigned int int_en[5];
+	unsigned int irq_mask[5];
+	unsigned int irq_stat[5];
+};
+
+static int smsc_gpio_get_value(struct gpio_chip *chip, unsigned off)
+{
+	struct smsc_gpio *sg =
+		container_of(chip, struct smsc_gpio, gpio_chip);
+	unsigned int get;
+	return !!(smsc_read(sg->dev,
+		(SMSC_GPIO_DATA_IN_START + SMSC_BANK(off)) & SMSC_BIT(off),
+					&get));
+}
+
+static void smsc_gpio_set_value(struct gpio_chip *chip,
+			unsigned off, int val)
+{
+	unsigned bank, bit;
+	struct smsc_gpio *sg =
+		container_of(chip, struct smsc_gpio, gpio_chip);
+
+	bank = SMSC_BANK(off);
+	bit = SMSC_BIT(off);
+
+	mutex_lock(&sg->lock);
+	if (val)
+		sg->dat_out[bank] |= bit;
+	else
+		sg->dat_out[bank] &= ~bit;
+
+	smsc_write(sg->dev, SMSC_GPIO_DATA_OUT_START + bank,
+			   sg->dat_out[bank]);
+	mutex_unlock(&sg->lock);
+}
+
+static int smsc_gpio_direction_input(struct gpio_chip *chip, unsigned off)
+{
+	unsigned int reg;
+	struct smsc_gpio *sg =
+	    container_of(chip, struct smsc_gpio, gpio_chip);
+	int reg_dir;
+
+	mutex_lock(&sg->lock);
+	reg_dir = SMSC_CFG_START + off;
+	smsc_read(sg->dev, reg_dir, &reg);
+	reg |= SMSC_GPIO_INPUT_LOW;
+	mutex_unlock(&sg->lock);
+
+	return smsc_write(sg->dev, reg_dir, reg);
+}
+
+static int smsc_gpio_direction_output(struct gpio_chip *chip,
+					 unsigned off, int val)
+{
+	unsigned int reg;
+	struct smsc_gpio *sg =
+	    container_of(chip, struct smsc_gpio, gpio_chip);
+	int reg_dir;
+
+	mutex_lock(&sg->lock);
+	reg_dir = SMSC_CFG_START + off;
+	smsc_read(sg->dev, reg_dir, &reg);
+	reg |= SMSC_GPIO_OUTPUT_PP;
+	mutex_unlock(&sg->lock);
+
+	return smsc_write(sg->dev, reg_dir, reg);
+}
+
+static int smsc_gpio_to_irq(struct gpio_chip *chip, unsigned off)
+{
+	struct smsc_gpio *sg =
+		container_of(chip, struct smsc_gpio, gpio_chip);
+	return sg->irq_base + off;
+}
+
+static void smsc_irq_bus_lock(struct irq_data *d)
+{
+	struct smsc_gpio *sg = irq_data_get_irq_chip_data(d);
+
+	mutex_lock(&sg->irq_lock);
+}
+
+static void smsc_irq_bus_sync_unlock(struct irq_data *d)
+{
+	struct smsc_gpio *sg = irq_data_get_irq_chip_data(d);
+	int i;
+
+	for (i = 0; i < SMSC_BANK(SMSC_MAXGPIO); i++)
+		if (sg->int_en[i] ^ sg->irq_mask[i]) {
+			sg->int_en[i] = sg->irq_mask[i];
+			smsc_write(sg->dev, SMSC_GPIO_INT_MASK_START + i,
+					   sg->int_en[i]);
+		}
+
+	mutex_unlock(&sg->irq_lock);
+}
+
+static void smsc_irq_mask(struct irq_data *d)
+{
+	struct smsc_gpio *sg = irq_data_get_irq_chip_data(d);
+	unsigned gpio = d->irq - sg->irq_base;
+
+	sg->irq_mask[SMSC_BANK(gpio)] &= ~SMSC_BIT(gpio);
+}
+
+static void smsc_irq_unmask(struct irq_data *d)
+{
+	struct smsc_gpio *sg = irq_data_get_irq_chip_data(d);
+	unsigned gpio = d->irq - sg->irq_base;
+
+	sg->irq_mask[SMSC_BANK(gpio)] |= SMSC_BIT(gpio);
+}
+
+static int smsc_irq_set_type(struct irq_data *d, unsigned int type)
+{
+	struct smsc_gpio *sg = irq_data_get_irq_chip_data(d);
+	uint16_t gpio = d->irq - sg->irq_base;
+	unsigned bank, bit;
+
+	if ((type & IRQ_TYPE_EDGE_BOTH)) {
+		dev_err(sg->dev, "irq %d: unsupported type %d\n",
+			d->irq, type);
+		return -EINVAL;
+	}
+
+	bank = SMSC_BANK(gpio);
+	bit = SMSC_BIT(gpio);
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		sg->irq_trig_fall[bank] |= bit;
+	else
+		sg->irq_trig_fall[bank] &= ~bit;
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		sg->irq_trig_raise[bank] |= bit;
+	else
+		sg->irq_trig_raise[bank] &= ~bit;
+
+	smsc_gpio_direction_input(&sg->gpio_chip, gpio);
+	smsc_write(sg->dev, SMSC_CFG_START + gpio,
+			sg->irq_trig_fall[bank] | sg->irq_trig_raise[bank]);
+
+	return 0;
+}
+
+static struct irq_chip smsc_irq_chip = {
+	.name			= "smsc",
+	.irq_mask		= smsc_irq_mask,
+	.irq_unmask		= smsc_irq_unmask,
+	.irq_bus_lock		= smsc_irq_bus_lock,
+	.irq_bus_sync_unlock	= smsc_irq_bus_sync_unlock,
+	.irq_set_type		= smsc_irq_set_type,
+};
+
+static int smsc_gpio_read_intstat(struct smsc_gpio *sg,
+				unsigned int *buf, int i)
+{
+	int ret = smsc_read(sg->dev,
+			SMSC_GPIO_INT_STAT_START + i, buf);
+
+	if (ret < 0)
+		dev_err(sg->dev, "Read INT_STAT Error\n");
+
+	return ret;
+}
+
+static irqreturn_t smsc_irq_handler(int irq, void *devid)
+{
+	struct smsc_gpio *sg = devid;
+	unsigned int status, bank, pending;
+	int ret;
+
+	smsc_read(sg->dev, GRP_INT_STAT, &status);
+
+	if (!(status & SMSC_GPI_INT))
+		goto out;
+
+	for (bank = 0; bank <= SMSC_BANK(SMSC_MAXGPIO);
+		bank++) {
+		pending = sg->irq_stat[bank] & sg->irq_mask[bank];
+		ret = smsc_gpio_read_intstat(sg,
+				&sg->irq_stat[bank], bank);
+		if (ret < 0)
+			memset(&sg->irq_stat[bank], 0,
+				ARRAY_SIZE(sg->irq_stat));
+
+		while (pending) {
+			unsigned long   bit = __ffs(pending);
+			unsigned int    irq;
+
+			pending &= ~BIT(bit);
+			irq = bit + sg->irq_base;
+			handle_nested_irq(irq);
+		}
+	}
+
+out:
+	smsc_write(sg->dev, GRP_INT_STAT, status); /* Status is W1C */
+
+	return IRQ_HANDLED;
+}
+
+static int smsc_irq_setup(struct smsc_gpio *sg)
+{
+	unsigned gpio;
+	int ret;
+
+	mutex_init(&sg->irq_lock);
+
+	for (gpio = 0; gpio < sg->gpio_chip.ngpio; gpio++) {
+		int irq = gpio + sg->irq_base;
+		irq_set_chip_data(irq, sg);
+		irq_set_chip_and_handler(irq, &smsc_irq_chip,
+				handle_level_irq);
+		irq_set_nested_thread(irq, 1);
+#ifdef CONFIG_ARM
+		set_irq_flags(irq, IRQF_VALID);
+#else
+		irq_set_noprobe(irq);
+#endif
+	}
+
+	ret = devm_request_threaded_irq(sg->dev, sg->irq, NULL,
+			smsc_irq_handler, sg->flags,
+			"smsc_gpio", sg);
+	if (ret) {
+		dev_err(sg->dev, "failed to request irq %d\n",
+			sg->irq);
+		return ret;
+	}
+
+	sg->gpio_chip.to_irq = smsc_gpio_to_irq;
+
+	return 0;
+}
+
+static int __devinit smsc_gpio_probe(struct platform_device *pdev)
+{
+	struct smsc_gpio *sg;
+	struct gpio_chip *gc;
+	struct smsc *smsc = dev_get_drvdata(pdev->dev.parent);
+	int ret, i, temp;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	int irq_base;
+
+	sg = devm_kzalloc(dev, sizeof(*sg), GFP_KERNEL);
+	if (sg == NULL) {
+		dev_err(&pdev->dev, "failed to alloc memory\n");
+		return -ENOMEM;
+	}
+
+	sg->irq = platform_get_irq(pdev, 0);
+	if (np) {
+		of_property_read_u32(np, "gpio,base", &temp);
+		of_property_read_u32(np, "flags", &sg->flags);
+	}
+
+	gc = &sg->gpio_chip;
+	gc->direction_input = smsc_gpio_direction_input;
+	gc->direction_output = smsc_gpio_direction_output;
+	gc->get = smsc_gpio_get_value;
+	gc->set = smsc_gpio_set_value;
+	gc->can_sleep = 1;
+
+	gc->base = temp;
+	gc->ngpio = SMSC_MAXGPIO;
+	gc->owner = THIS_MODULE;
+
+	sg->smsc = smsc;
+	sg->dev = dev;
+	mutex_init(&sg->lock);
+
+	for (i = 0; i <= SMSC_BANK(SMSC_MAXGPIO); i++)
+		smsc_read(sg->dev, SMSC_GPIO_DATA_OUT_START + i,
+					&sg->dat_out[i]);
+
+	for (i = 0; i < SMSC_MAXGPIO; i++)
+		smsc_read(sg->dev, SMSC_CFG_START + i, &sg->dir[i]);
+
+	irq_base = irq_alloc_descs(-1, 0, sg->gpio_chip.ngpio, 0);
+	if (IS_ERR_VALUE(irq_base)) {
+		dev_err(sg->dev, "Fail to allocate IRQ descs\n");
+		return irq_base;
+	}
+	sg->irq_base = irq_base;
+
+	sg->irq_domain = irq_domain_add_legacy(pdev->dev.of_node,
+		sg->gpio_chip.ngpio, sg->irq_base, 0,
+			&irq_domain_simple_ops, NULL);
+
+	ret = smsc_irq_setup(sg);
+	if (ret)
+		goto err;
+
+	ret = gpiochip_add(&sg->gpio_chip);
+	if (ret)
+		goto err;
+
+err:
+	return ret;
+}
+
+static int __devexit smsc_gpio_remove(struct platform_device *pdev)
+{
+	struct smsc_gpio *sg = dev_get_drvdata(&pdev->dev);
+	int ret;
+
+	ret = gpiochip_remove(&sg->gpio_chip);
+	if (ret) {
+		dev_err(&pdev->dev, "gpiochip_remove failed %d\n", ret);
+		return ret;
+	}
+
+	irq_domain_remove(sg->irq_domain);
+	irq_free_descs(sg->irq_base, sg->gpio_chip.ngpio);
+
+	return 0;
+}
+
+static const struct of_device_id smsc_gpio_dt_match[] = {
+	{ .compatible = "smsc,gpio" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, smsc_gpio_dt_match);
+
+static struct platform_driver smsc_gpio_driver = {
+	.driver = {
+		   .name = "smsc_gpio",
+		   .of_match_table = of_match_ptr(smsc_gpio_dt_match),
+		   },
+	.probe = smsc_gpio_probe,
+	.remove = __devexit_p(smsc_gpio_remove),
+};
+
+module_platform_driver(smsc_gpio_driver);
+
+MODULE_AUTHOR("Sourav Poddar <sourav.poddar@ti.com>");
+MODULE_DESCRIPTION("GPIO SMSC Driver");
+MODULE_LICENSE("GPL v2");
-- 
1.7.1

^ permalink raw reply related

* [PATCH 03/12] mmc: dw_mmc: fix building exynos driver as a module
From: Will Newton @ 2012-10-01 11:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1348868177-21205-4-git-send-email-arnd@arndb.de>

On Fri, Sep 28, 2012 at 10:36 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> The MODULE_DEVICE_TABLE() entry in the dw_mmc_exynos driver
> points to the wrong symbol which results in a link error
> when building as a loadable module.
>
> Further, we get a warning about the driver_data being
> marked constant, which requires annotating a few pointers
> as const.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> Cc: Chris Ball <cjb@laptop.org>
> Cc: Thomas Abraham <thomas.abraham@linaro.org>
> Cc: Will Newton <will.newton@imgtec.com>
> Cc: Jaehoon Chung <jh80.chung@samsung.com>
> Cc: Seungwon Jeon <tgih.jun@samsung.com>
> Cc: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: linux-mmc at vger.kernel.org
> ---
>  drivers/mmc/host/dw_mmc-exynos.c |    4 ++--
>  drivers/mmc/host/dw_mmc-pltfm.c  |    2 +-
>  drivers/mmc/host/dw_mmc-pltfm.h  |    2 +-
>  drivers/mmc/host/dw_mmc.c        |    2 +-
>  include/linux/mmc/dw_mmc.h       |    2 +-
>  5 files changed, 6 insertions(+), 6 deletions(-)

This looks ok to me, but I'll let one of the Exynos guys ack those
specific changes as I don't have the hardware.

There's already a patch for the dev_info warning in dw_mmc.c frm
Seungwon Jeon, and it seems to me like a separate change but I don't
really mind how it gets merged.

^ permalink raw reply

* [PATCH 1/2] dm644x: replace the obsolete preset API by the timings API.
From: Sekhar Nori @ 2012-10-01 11:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1344429020-27616-2-git-send-email-prabhakar.lad@ti.com>

On 8/8/2012 6:00 PM, Prabhakar Lad wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
> 
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> Signed-off-by: Lad, Prabhakar <prabhakar.lad@ti.com>
> Signed-off-by: Manjunath Hadli <manjunath.hadli@ti.com>

Please have a patch description. For the DaVinci platform portion:

Acked-by: Sekhar Nori <nsekhar@ti.com>

Thanks,
Sekhar

^ permalink raw reply

* [PATCHv3 1/4] mfd: smsc: Add support for smsc gpio io/keypad driver
From: ABRAHAM, KISHON VIJAY @ 2012-10-01 11:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349089282-22105-1-git-send-email-sourav.poddar@ti.com>

Hi,

On Mon, Oct 1, 2012 at 4:31 PM, Sourav Poddar <sourav.poddar@ti.com> wrote:
> smsc ece1099 is a keyboard scan or gpio expansion device.
> The patch create keypad and gpio expander child for this
> multi function smsc driver.
>
> Tested on omap5430 evm with 3.6-rc6 custom kernel.
Can we have this line in comment section and not in commit log?

>
> Cc: Samuel Ortiz <sameo@linux.intel.com>
> Cc: Benoit Cousson <b-cousson@ti.com>
> Cc: Felipe Balbi <balbi@ti.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
> ---
> Changes since v2:
>  - Change the cache type, max register assignment
>  - remove of_device_table, since i2c based device gets
> probed according to i2c_device_id through dt.
>  - Modify the remove function
>  - Minor return patch cleanups.
>  Documentation/smsc_ece1099.txt |   56 ++++++++++++++++++++
>  drivers/mfd/Kconfig            |   12 ++++
>  drivers/mfd/Makefile           |    1 +
>  drivers/mfd/smsc-ece1099.c     |  113 ++++++++++++++++++++++++++++++++++++++++
>  include/linux/mfd/smsc.h       |  109 ++++++++++++++++++++++++++++++++++++++
>  5 files changed, 291 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/smsc_ece1099.txt
>  create mode 100644 drivers/mfd/smsc-ece1099.c
>  create mode 100644 include/linux/mfd/smsc.h
>
> diff --git a/Documentation/smsc_ece1099.txt b/Documentation/smsc_ece1099.txt
> new file mode 100644
> index 0000000..6b492e8
> --- /dev/null
> +++ b/Documentation/smsc_ece1099.txt
> @@ -0,0 +1,56 @@
> +What is smsc-ece1099?
> +----------------------
> +
> +The ECE1099 is a 40-Pin 3.3V Keyboard Scan Expansion
> +or GPIO Expansion device. The device supports a keyboard
> +scan matrix of 23x8. The device is connected to a Master
> +via the SMSC BC-Link interface or via the SMBus.
> +Keypad scan Input(KSI) and Keypad Scan Output(KSO) signals
> +are multiplexed with GPIOs.
> +
> +Interrupt generation
> +--------------------
> +
> +Interrupts can be generated by an edge detection on a GPIO
> +pin or an edge detection on one of the bus interface pins.
> +Interrupts can also be detected on the keyboard scan interface.
> +The bus interrupt pin (BC_INT# or SMBUS_INT#) is asserted if
> +any bit in one of the Interrupt Status registers is 1 and
> +the corresponding Interrupt Mask bit is also 1.
> +
> +In order for software to determine which device is the source
> +of an interrupt, it should first read the Group Interrupt Status Register
> +to determine which Status register group is a source for the interrupt.
> +Software should read both the Status register and the associated Mask register,
> +then AND the two values together. Bits that are 1 in the result of the AND
> +are active interrupts. Software clears an interrupt by writing a 1 to the
> +corresponding bit in the Status register.
> +
> +Communication Protocol
> +----------------------
> +
> +- SMbus slave Interface
> +       The host processor communicates with the ECE1099 device
> +       through a series of read/write registers via the SMBus
> +       interface. SMBus is a serial communication protocol between
> +       a computer host and its peripheral devices. The SMBus data
> +       rate is 10KHz minimum to 400 KHz maximum
> +
> +- Slave Bus Interface
> +       The ECE1099 device SMBus implementation is a subset of the
> +       SMBus interface to the host. The device is a slave-only SMBus device.
> +       The implementation in the device is a subset of SMBus since it
> +       only supports four protocols.
> +
> +       The Write Byte, Read Byte, Send Byte, and Receive Byte protocols are the
> +       only valid SMBus protocols for the device.
> +
> +- BC-LinkTM Interface
> +       The BC-Link is a proprietary bus that allows communication
> +       between a Master device and a Companion device. The Master
> +       device uses this serial bus to read and write registers
> +       located on the Companion device. The bus comprises three signals,
> +       BC_CLK, BC_DAT and BC_INT#. The Master device always provides the
> +       clock, BC_CLK, and the Companion device is the source for an
> +       independent asynchronous interrupt signal, BC_INT#. The ECE1099
> +       supports BC-Link speeds up to 24MHz.
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index b1a1462..dedc874 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -385,6 +385,18 @@ config MFD_T7L66XB
>         help
>           Support for Toshiba Mobile IO Controller T7L66XB
>
> +config MFD_SMSC
> +       bool "Support for the SMSC ECE1099 series chips"
> +       depends on I2C=y
> +       select MFD_CORE
> +       select REGMAP_I2C
> +       help
> +        If you say yes here you get support for the
> +        ece1099 chips from SMSC.
> +
> +        To compile this driver as a module, choose M here: the
> +        module will be called smsc.
*bool* attribute for MFD_SMSC, does not allow to select the driver as
module. use *trisate* instead.
> +
>  config MFD_TC6387XB
>         bool "Support Toshiba TC6387XB"
>         depends on ARM && HAVE_CLK
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index 79dd22d..3323345 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -77,6 +77,7 @@ obj-$(CONFIG_EZX_PCAP)                += ezx-pcap.o
>  obj-$(CONFIG_MCP)              += mcp-core.o
>  obj-$(CONFIG_MCP_SA11X0)       += mcp-sa11x0.o
>  obj-$(CONFIG_MCP_UCB1200)      += ucb1x00-core.o
> +obj-$(CONFIG_MFD_SMSC)        += smsc-ece1099.o
>  obj-$(CONFIG_MCP_UCB1200_TS)   += ucb1x00-ts.o
>
>  ifeq ($(CONFIG_SA1100_ASSABET),y)
> diff --git a/drivers/mfd/smsc-ece1099.c b/drivers/mfd/smsc-ece1099.c
> new file mode 100644
> index 0000000..220aec2
> --- /dev/null
> +++ b/drivers/mfd/smsc-ece1099.c
> @@ -0,0 +1,113 @@
> +/*
> + * TI SMSC MFD Driver
> + *
> + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com
> + *
> + * Author: Sourav Poddar <sourav.poddar@ti.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;  GPL v2.
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/moduleparam.h>
> +#include <linux/init.h>
> +#include <linux/slab.h>
> +#include <linux/i2c.h>
> +#include <linux/gpio.h>
> +#include <linux/workqueue.h>
> +#include <linux/irq.h>
> +#include <linux/regmap.h>
> +#include <linux/err.h>
> +#include <linux/mfd/core.h>
> +#include <linux/mfd/smsc.h>
> +#include <linux/of_platform.h>
> +
> +static struct regmap_config smsc_regmap_config = {
> +               .reg_bits = 8,
> +               .val_bits = 8,
> +               .max_register = SMSC_VEN_ID_H,
> +               .cache_type = REGCACHE_RBTREE,
> +};
> +
> +static int smsc_i2c_probe(struct i2c_client *i2c,
> +                       const struct i2c_device_id *id)
> +{
> +       struct device_node              *node = i2c->dev.of_node;
> +       struct smsc *smsc;
> +       int devid, rev, venid_l, venid_h;
> +       int ret = 0;
> +
> +       smsc = devm_kzalloc(&i2c->dev, sizeof(struct smsc),
> +                               GFP_KERNEL);
> +       if (!smsc) {
> +               dev_err(&i2c->dev, "smsc mfd driver memory allocation failed\n");
> +               return -ENOMEM;
> +       }
> +
> +       smsc->regmap = devm_regmap_init_i2c(i2c, &smsc_regmap_config);
> +       if (IS_ERR(smsc->regmap)) {
> +               ret = PTR_ERR(smsc->regmap);
> +               goto err;
> +       }
> +
> +       i2c_set_clientdata(i2c, smsc);
> +       smsc->dev = &i2c->dev;
> +
> +#ifdef CONFIG_OF
> +       of_property_read_u32(node, "clock", &smsc->clk);
This functions need not come under macro.
> +#endif
> +
> +       regmap_read(smsc->regmap, SMSC_DEV_ID, &devid);
> +       regmap_read(smsc->regmap, SMSC_DEV_REV, &rev);
> +       regmap_read(smsc->regmap, SMSC_VEN_ID_L, &venid_l);
> +       regmap_read(smsc->regmap, SMSC_VEN_ID_H, &venid_h);
> +
> +       dev_info(&i2c->dev, "SMSCxxx devid: %02x rev: %02x venid: %02x\n",
> +               devid, rev, (venid_h << 8) | venid_l);
dev_info makes the boot noisy.
> +
> +       ret = regmap_write(smsc->regmap, SMSC_CLK_CTRL, smsc->clk);
> +       if (ret)
> +               goto err;
> +
> +#ifdef CONFIG_OF
> +       if (node)
> +               ret = of_platform_populate(node, NULL, NULL, &i2c->dev);
of_platform_populate() need not come under macro.
> +#endif
> +
> +err:
> +       return ret;
> +}
> +
> +static int smsc_i2c_remove(struct i2c_client *i2c)
> +{
> +       struct smsc *smsc = i2c_get_clientdata(i2c);
> +
> +       mfd_remove_devices(smsc->dev);
IMO, this should have resulted in an abort (hint: see
mfd_remove_devices_fn()). Trying to do mfd_remove_devices without
mfd_add_devices(). Use device_for_each_child here to remove the
device.

Thanks
Kishon

^ permalink raw reply

* [PATCH] i2c-nomadik: Fixup clock handling
From: Ulf Hansson @ 2012-10-01 11:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACRpkdZZ-gNBi7EDwhXHawmzPD9dE8wo9voX-MJ7CYQ058k-Jw@mail.gmail.com>

Hi Wolfram,

Juts a kind reminder on this. Do you see any problem merging this?

Kind regards
Ulf Hansson

On 20 September 2012 21:17, Linus Walleij <linus.walleij@linaro.org> wrote:
> On Thu, Sep 20, 2012 at 5:20 PM, Ulf Hansson <ulf.hansson@stericsson.com> wrote:
>
>> From: Philippe Begnic <philippe.begnic@stericsson.com>
>>
>> Make sure to clk_prepare as well as clk_enable.
>
> Looks correct. xfer() is slowpatch so we might as well call
> prepare/unprepare functions there.
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
>
> Yours,
> Linus Walleij

^ permalink raw reply

* [PATCHv3 1/4] mfd: smsc: Add support for smsc gpio io/keypad driver
From: Mark Brown @ 2012-10-01 11:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAAe_U6+zEGuwMC1yn7O=LXE6PhPvPc2i7DCF0EAprkE8s+-iEw@mail.gmail.com>

On Mon, Oct 01, 2012 at 05:00:06PM +0530, ABRAHAM, KISHON VIJAY wrote:
> On Mon, Oct 1, 2012 at 4:31 PM, Sourav Poddar <sourav.poddar@ti.com> wrote:

Delete irrelevant context from your replies, it makes it much easier to
find new text.

> > +static int smsc_i2c_remove(struct i2c_client *i2c)
> > +{
> > +       struct smsc *smsc = i2c_get_clientdata(i2c);
> > +
> > +       mfd_remove_devices(smsc->dev);

> IMO, this should have resulted in an abort (hint: see
> mfd_remove_devices_fn()). Trying to do mfd_remove_devices without
> mfd_add_devices(). Use device_for_each_child here to remove the
> device.

No, this is not at all sensible - if there's an mfd_remove_devices()
function we really ought to be able to use it to remove the children.
If we can't do that we should fix the API usability, not open code the
same stuff in every user.

^ permalink raw reply

* [PATCHv3 1/4] mfd: smsc: Add support for smsc gpio io/keypad driver
From: ABRAHAM, KISHON VIJAY @ 2012-10-01 11:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121001114454.GA9170@sirena.org.uk>

Hi,

On Mon, Oct 1, 2012 at 5:14 PM, Mark Brown
<broonie@opensource.wolfsonmicro.com> wrote:
> On Mon, Oct 01, 2012 at 05:00:06PM +0530, ABRAHAM, KISHON VIJAY wrote:
>> On Mon, Oct 1, 2012 at 4:31 PM, Sourav Poddar <sourav.poddar@ti.com> wrote:
>
> Delete irrelevant context from your replies, it makes it much easier to
> find new text.
>
>> > +static int smsc_i2c_remove(struct i2c_client *i2c)
>> > +{
>> > +       struct smsc *smsc = i2c_get_clientdata(i2c);
>> > +
>> > +       mfd_remove_devices(smsc->dev);
>
>> IMO, this should have resulted in an abort (hint: see
>> mfd_remove_devices_fn()). Trying to do mfd_remove_devices without
>> mfd_add_devices(). Use device_for_each_child here to remove the
>> device.
>
> No, this is not at all sensible - if there's an mfd_remove_devices()
> function we really ought to be able to use it to remove the children.
> If we can't do that we should fix the API usability, not open code the
> same stuff in every user.

What makes more sense to me is extend mfd_add_devices to create child
devices from dt data. Then for removing devices, one can use
mfd_remove_devices().

Thanks
Kishon

^ permalink raw reply

* [PATCHv3 1/4] mfd: smsc: Add support for smsc gpio io/keypad driver
From: Samuel Ortiz @ 2012-10-01 12:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349089282-22105-1-git-send-email-sourav.poddar@ti.com>

Hi Sourav,

On Mon, Oct 01, 2012 at 04:31:22PM +0530, Sourav Poddar wrote:
> smsc ece1099 is a keyboard scan or gpio expansion device.
> The patch create keypad and gpio expander child for this
> multi function smsc driver.
> 
> Tested on omap5430 evm with 3.6-rc6 custom kernel.
> 
> Cc: Samuel Ortiz <sameo@linux.intel.com>
> Cc: Benoit Cousson <b-cousson@ti.com>
> Cc: Felipe Balbi <balbi@ti.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
> ---
> Changes since v2:
>  - Change the cache type, max register assignment
>  - remove of_device_table, since i2c based device gets 
> probed according to i2c_device_id through dt.
>  - Modify the remove function
>  - Minor return patch cleanups.
>  Documentation/smsc_ece1099.txt |   56 ++++++++++++++++++++
>  drivers/mfd/Kconfig            |   12 ++++
>  drivers/mfd/Makefile           |    1 +
>  drivers/mfd/smsc-ece1099.c     |  113 ++++++++++++++++++++++++++++++++++++++++
>  include/linux/mfd/smsc.h       |  109 ++++++++++++++++++++++++++++++++++++++
>  5 files changed, 291 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/smsc_ece1099.txt
>  create mode 100644 drivers/mfd/smsc-ece1099.c
>  create mode 100644 include/linux/mfd/smsc.h
Applied with a warning fix for the !CONFIG_OF case.

Cheers,
Samuel.

-- 
Intel Open Source Technology Centre
http://oss.intel.com/

^ permalink raw reply

* [PATCH v2 4/7] ARM: davinci: Add support for an L3RAM gen_pool
From: Sekhar Nori @ 2012-10-01 12:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1348861072-14507-5-git-send-email-mporter@ti.com>

Hi Matt,

On 9/29/2012 1:07 AM, Matt Porter wrote:
> L3RAM (shared SRAM) is needed for use by several drivers.
> This creates a genalloc pool and a hook for the platform code
> to provide the struct gen_pool * in platform data.
> 
> Signed-off-by: Matt Porter <mporter@ti.com>

I am not sure if any of the DaVinci devices have a need to allocate from
*both* ARM RAM and shared RAM. Shared RAM is not present on all DaVinci
devices AFAIR, and on DA850, there is just 8KB ARM RAM so I am not sure
if there is much point in trying to allocate from there.

Can you instead see if Ben's earlier patch[1] to use shared RAM for SRAM
allocation on DA850 makes sense for your case? If yes, can you repost
with Ben's patch included in your series instead of this patch? I would
prefer that over creating a new pool for shared RAM.

Thanks,
Sekhar

[1] https://patchwork.kernel.org/patch/840552/

Thanks,
Sekhar

^ permalink raw reply

* [PATCHv3 1/4] mfd: smsc: Add support for smsc gpio io/keypad driver
From: Mark Brown @ 2012-10-01 12:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAAe_U6JX9QDWvWA3KH7E9sOv0EHGkozVONuXDgn+a2MZ4GTE7Q@mail.gmail.com>

On Mon, Oct 01, 2012 at 05:23:15PM +0530, ABRAHAM, KISHON VIJAY wrote:
> On Mon, Oct 1, 2012 at 5:14 PM, Mark Brown

> > No, this is not at all sensible - if there's an mfd_remove_devices()
> > function we really ought to be able to use it to remove the children.
> > If we can't do that we should fix the API usability, not open code the
> > same stuff in every user.

> What makes more sense to me is extend mfd_add_devices to create child
> devices from dt data. Then for removing devices, one can use
> mfd_remove_devices().

Why would that be helpful?  Most platforms don't support DT at all, and
having the API behave differently depending on the platform doesn't seem
like a step forwards.  I would really expect any usage of DT to be
totally orthogonal here.

^ permalink raw reply

* [PATCH 0/2] ARM: Exynos4: Migrate to common clock framework.
From: chander.kashyap at linaro.org @ 2012-10-01 12:09 UTC (permalink / raw)
  To: linux-arm-kernel

From: Thomas Abraham <thomas.abraham@linaro.org>

This patch series migrates Exynos4 clock support to common clock framework.
The first patch in this series removes the existing Exynos4 clock support
that uses the Samsung specific clock framework. The second patch in this
series add Exynos4 clock support using common clock framework.

Thomas Abraham (2):
  ARM: Exynos4: Remove Samsung clock type support
  ARM: Exynos4: Register clocks via common clock framework

 arch/arm/mach-exynos/Kconfig               |    1 +
 arch/arm/mach-exynos/Makefile              |    3 -
 arch/arm/mach-exynos/clock-exynos4.c       | 1572 ----------------------------
 arch/arm/mach-exynos/clock-exynos4.h       |   35 -
 arch/arm/mach-exynos/clock-exynos4210.c    |  188 ----
 arch/arm/mach-exynos/clock-exynos4212.c    |  192 ----
 arch/arm/mach-exynos/common.c              |   18 +-
 arch/arm/mach-exynos/common.h              |    3 +
 arch/arm/mach-exynos/mach-armlex4210.c     |    1 -
 arch/arm/mach-exynos/mach-exynos4-dt.c     |    1 -
 arch/arm/mach-exynos/mach-nuri.c           |    1 -
 arch/arm/mach-exynos/mach-origen.c         |    1 -
 arch/arm/mach-exynos/mach-smdk4x12.c       |    1 -
 arch/arm/mach-exynos/mach-smdkv310.c       |    1 -
 arch/arm/mach-exynos/mach-universal_c210.c |    1 -
 arch/arm/mach-exynos/mct.c                 |   11 +-
 arch/arm/plat-samsung/Kconfig              |    4 +-
 drivers/clk/Makefile                       |    1 +
 drivers/clk/clk.c                          |   12 +-
 drivers/clk/samsung/Makefile               |    6 +
 drivers/clk/samsung/clk-exynos4.c          |  585 +++++++++++
 drivers/clk/samsung/clk.c                  |  231 ++++
 drivers/clk/samsung/clk.h                  |  190 ++++
 23 files changed, 1043 insertions(+), 2016 deletions(-)
 delete mode 100644 arch/arm/mach-exynos/clock-exynos4.c
 delete mode 100644 arch/arm/mach-exynos/clock-exynos4.h
 delete mode 100644 arch/arm/mach-exynos/clock-exynos4210.c
 delete mode 100644 arch/arm/mach-exynos/clock-exynos4212.c
 create mode 100644 drivers/clk/samsung/Makefile
 create mode 100644 drivers/clk/samsung/clk-exynos4.c
 create mode 100644 drivers/clk/samsung/clk.c
 create mode 100644 drivers/clk/samsung/clk.h

^ permalink raw reply

* [PATCH 1/2] ARM: Exynos4: Remove Samsung clock type support
From: chander.kashyap at linaro.org @ 2012-10-01 12:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349093361-18820-1-git-send-email-thomas.abraham@linaro.org>

From: Thomas Abraham <thomas.abraham@linaro.org>

In preparation to migrate Exynos4 based platforms to commom clock framework,
remove the support for Samsung type clock support.

Cc: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 arch/arm/mach-exynos/Makefile              |    3 -
 arch/arm/mach-exynos/clock-exynos4.c       | 1572 ----------------------------
 arch/arm/mach-exynos/clock-exynos4.h       |   35 -
 arch/arm/mach-exynos/clock-exynos4210.c    |  188 ----
 arch/arm/mach-exynos/clock-exynos4212.c    |  192 ----
 arch/arm/mach-exynos/common.c              |   18 +-
 arch/arm/mach-exynos/mach-armlex4210.c     |    1 -
 arch/arm/mach-exynos/mach-exynos4-dt.c     |    1 -
 arch/arm/mach-exynos/mach-nuri.c           |    1 -
 arch/arm/mach-exynos/mach-origen.c         |    1 -
 arch/arm/mach-exynos/mach-smdk4x12.c       |    1 -
 arch/arm/mach-exynos/mach-smdkv310.c       |    1 -
 arch/arm/mach-exynos/mach-universal_c210.c |    1 -
 13 files changed, 6 insertions(+), 2009 deletions(-)
 delete mode 100644 arch/arm/mach-exynos/clock-exynos4.c
 delete mode 100644 arch/arm/mach-exynos/clock-exynos4.h
 delete mode 100644 arch/arm/mach-exynos/clock-exynos4210.c
 delete mode 100644 arch/arm/mach-exynos/clock-exynos4212.c

diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
index 9b58024..ad66c9f 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -13,10 +13,7 @@ obj-				:=
 # Core
 
 obj-$(CONFIG_ARCH_EXYNOS)	+= common.o
-obj-$(CONFIG_ARCH_EXYNOS4)	+= clock-exynos4.o
 obj-$(CONFIG_ARCH_EXYNOS5)	+= clock-exynos5.o
-obj-$(CONFIG_CPU_EXYNOS4210)	+= clock-exynos4210.o
-obj-$(CONFIG_SOC_EXYNOS4212)	+= clock-exynos4212.o
 
 obj-$(CONFIG_PM)		+= pm.o
 obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
diff --git a/arch/arm/mach-exynos/clock-exynos4.c b/arch/arm/mach-exynos/clock-exynos4.c
deleted file mode 100644
index 2f51293..0000000
--- a/arch/arm/mach-exynos/clock-exynos4.c
+++ /dev/null
@@ -1,1572 +0,0 @@
-/*
- * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - Clock support
- *
- * 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.
-*/
-
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-#include <plat/pm.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/sysmmu.h>
-
-#include "common.h"
-#include "clock-exynos4.h"
-
-#ifdef CONFIG_PM_SLEEP
-static struct sleep_save exynos4_clock_save[] = {
-	SAVE_ITEM(EXYNOS4_CLKDIV_LEFTBUS),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_LEFTBUS),
-	SAVE_ITEM(EXYNOS4_CLKDIV_RIGHTBUS),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_RIGHTBUS),
-	SAVE_ITEM(EXYNOS4_CLKSRC_TOP0),
-	SAVE_ITEM(EXYNOS4_CLKSRC_TOP1),
-	SAVE_ITEM(EXYNOS4_CLKSRC_CAM),
-	SAVE_ITEM(EXYNOS4_CLKSRC_TV),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MFC),
-	SAVE_ITEM(EXYNOS4_CLKSRC_G3D),
-	SAVE_ITEM(EXYNOS4_CLKSRC_LCD0),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MAUDIO),
-	SAVE_ITEM(EXYNOS4_CLKSRC_FSYS),
-	SAVE_ITEM(EXYNOS4_CLKSRC_PERIL0),
-	SAVE_ITEM(EXYNOS4_CLKSRC_PERIL1),
-	SAVE_ITEM(EXYNOS4_CLKDIV_CAM),
-	SAVE_ITEM(EXYNOS4_CLKDIV_TV),
-	SAVE_ITEM(EXYNOS4_CLKDIV_MFC),
-	SAVE_ITEM(EXYNOS4_CLKDIV_G3D),
-	SAVE_ITEM(EXYNOS4_CLKDIV_LCD0),
-	SAVE_ITEM(EXYNOS4_CLKDIV_MAUDIO),
-	SAVE_ITEM(EXYNOS4_CLKDIV_FSYS0),
-	SAVE_ITEM(EXYNOS4_CLKDIV_FSYS1),
-	SAVE_ITEM(EXYNOS4_CLKDIV_FSYS2),
-	SAVE_ITEM(EXYNOS4_CLKDIV_FSYS3),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL0),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL1),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL2),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL3),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL4),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL5),
-	SAVE_ITEM(EXYNOS4_CLKDIV_TOP),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_TOP),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_CAM),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_TV),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_LCD0),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_MAUDIO),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_FSYS),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_PERIL0),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_PERIL1),
-	SAVE_ITEM(EXYNOS4_CLKDIV2_RATIO),
-	SAVE_ITEM(EXYNOS4_CLKGATE_SCLKCAM),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_CAM),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_TV),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_MFC),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_G3D),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_LCD0),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_FSYS),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_GPS),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_PERIL),
-	SAVE_ITEM(EXYNOS4_CLKGATE_BLOCK),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_DMC),
-	SAVE_ITEM(EXYNOS4_CLKSRC_DMC),
-	SAVE_ITEM(EXYNOS4_CLKDIV_DMC0),
-	SAVE_ITEM(EXYNOS4_CLKDIV_DMC1),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_DMC),
-	SAVE_ITEM(EXYNOS4_CLKSRC_CPU),
-	SAVE_ITEM(EXYNOS4_CLKDIV_CPU),
-	SAVE_ITEM(EXYNOS4_CLKDIV_CPU + 0x4),
-	SAVE_ITEM(EXYNOS4_CLKGATE_SCLKCPU),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_CPU),
-};
-#endif
-
-static struct clk exynos4_clk_sclk_hdmi27m = {
-	.name		= "sclk_hdmi27m",
-	.rate		= 27000000,
-};
-
-static struct clk exynos4_clk_sclk_hdmiphy = {
-	.name		= "sclk_hdmiphy",
-};
-
-static struct clk exynos4_clk_sclk_usbphy0 = {
-	.name		= "sclk_usbphy0",
-	.rate		= 27000000,
-};
-
-static struct clk exynos4_clk_sclk_usbphy1 = {
-	.name		= "sclk_usbphy1",
-};
-
-static struct clk dummy_apb_pclk = {
-	.name		= "apb_pclk",
-	.id		= -1,
-};
-
-static int exynos4_clksrc_mask_top_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_TOP, clk, enable);
-}
-
-static int exynos4_clksrc_mask_cam_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_CAM, clk, enable);
-}
-
-static int exynos4_clksrc_mask_lcd0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_LCD0, clk, enable);
-}
-
-int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_FSYS, clk, enable);
-}
-
-static int exynos4_clksrc_mask_peril0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_PERIL0, clk, enable);
-}
-
-static int exynos4_clksrc_mask_peril1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_PERIL1, clk, enable);
-}
-
-static int exynos4_clk_ip_mfc_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_MFC, clk, enable);
-}
-
-static int exynos4_clksrc_mask_tv_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_TV, clk, enable);
-}
-
-static int exynos4_clk_ip_cam_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_CAM, clk, enable);
-}
-
-static int exynos4_clk_ip_tv_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_TV, clk, enable);
-}
-
-int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_IMAGE, clk, enable);
-}
-
-static int exynos4_clk_ip_lcd0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_LCD0, clk, enable);
-}
-
-int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4210_CLKGATE_IP_LCD1, clk, enable);
-}
-
-int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_FSYS, clk, enable);
-}
-
-static int exynos4_clk_ip_peril_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_PERIL, clk, enable);
-}
-
-static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_PERIR, clk, enable);
-}
-
-int exynos4_clk_ip_dmc_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_DMC, clk, enable);
-}
-
-static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
-}
-
-static int exynos4_clk_dac_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable);
-}
-
-/* Core list of CMU_CPU side */
-
-static struct clksrc_clk exynos4_clk_mout_apll = {
-	.clk	= {
-		.name		= "mout_apll",
-	},
-	.sources = &clk_src_apll,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_CPU, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_apll = {
-	.clk	= {
-		.name		= "sclk_apll",
-		.parent		= &exynos4_clk_mout_apll.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 24, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_mout_epll = {
-	.clk	= {
-		.name		= "mout_epll",
-	},
-	.sources = &clk_src_epll,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 4, .size = 1 },
-};
-
-struct clksrc_clk exynos4_clk_mout_mpll = {
-	.clk	= {
-		.name		= "mout_mpll",
-	},
-	.sources = &clk_src_mpll,
-
-	/* reg_src will be added in each SoCs' clock */
-};
-
-static struct clk *exynos4_clkset_moutcore_list[] = {
-	[0] = &exynos4_clk_mout_apll.clk,
-	[1] = &exynos4_clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_moutcore = {
-	.sources	= exynos4_clkset_moutcore_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_moutcore_list),
-};
-
-static struct clksrc_clk exynos4_clk_moutcore = {
-	.clk	= {
-		.name		= "moutcore",
-	},
-	.sources = &exynos4_clkset_moutcore,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_CPU, .shift = 16, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_coreclk = {
-	.clk	= {
-		.name		= "core_clk",
-		.parent		= &exynos4_clk_moutcore.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_armclk = {
-	.clk	= {
-		.name		= "armclk",
-		.parent		= &exynos4_clk_coreclk.clk,
-	},
-};
-
-static struct clksrc_clk exynos4_clk_aclk_corem0 = {
-	.clk	= {
-		.name		= "aclk_corem0",
-		.parent		= &exynos4_clk_coreclk.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 4, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_cores = {
-	.clk	= {
-		.name		= "aclk_cores",
-		.parent		= &exynos4_clk_coreclk.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 4, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_corem1 = {
-	.clk	= {
-		.name		= "aclk_corem1",
-		.parent		= &exynos4_clk_coreclk.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 8, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_periphclk = {
-	.clk	= {
-		.name		= "periphclk",
-		.parent		= &exynos4_clk_coreclk.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 12, .size = 3 },
-};
-
-/* Core list of CMU_CORE side */
-
-static struct clk *exynos4_clkset_corebus_list[] = {
-	[0] = &exynos4_clk_mout_mpll.clk,
-	[1] = &exynos4_clk_sclk_apll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_mout_corebus = {
-	.sources	= exynos4_clkset_corebus_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_corebus_list),
-};
-
-static struct clksrc_clk exynos4_clk_mout_corebus = {
-	.clk	= {
-		.name		= "mout_corebus",
-	},
-	.sources = &exynos4_clkset_mout_corebus,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_dmc = {
-	.clk	= {
-		.name		= "sclk_dmc",
-		.parent		= &exynos4_clk_mout_corebus.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 12, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_cored = {
-	.clk	= {
-		.name		= "aclk_cored",
-		.parent		= &exynos4_clk_sclk_dmc.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 16, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_corep = {
-	.clk	= {
-		.name		= "aclk_corep",
-		.parent		= &exynos4_clk_aclk_cored.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 20, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_acp = {
-	.clk	= {
-		.name		= "aclk_acp",
-		.parent		= &exynos4_clk_mout_corebus.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_pclk_acp = {
-	.clk	= {
-		.name		= "pclk_acp",
-		.parent		= &exynos4_clk_aclk_acp.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 4, .size = 3 },
-};
-
-/* Core list of CMU_TOP side */
-
-struct clk *exynos4_clkset_aclk_top_list[] = {
-	[0] = &exynos4_clk_mout_mpll.clk,
-	[1] = &exynos4_clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_aclk = {
-	.sources	= exynos4_clkset_aclk_top_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_aclk_top_list),
-};
-
-static struct clksrc_clk exynos4_clk_aclk_200 = {
-	.clk	= {
-		.name		= "aclk_200",
-	},
-	.sources = &exynos4_clkset_aclk,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 12, .size = 1 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_100 = {
-	.clk	= {
-		.name		= "aclk_100",
-	},
-	.sources = &exynos4_clkset_aclk,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 16, .size = 1 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_160 = {
-	.clk	= {
-		.name		= "aclk_160",
-	},
-	.sources = &exynos4_clkset_aclk,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 20, .size = 1 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 8, .size = 3 },
-};
-
-struct clksrc_clk exynos4_clk_aclk_133 = {
-	.clk	= {
-		.name		= "aclk_133",
-	},
-	.sources = &exynos4_clkset_aclk,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 24, .size = 1 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 12, .size = 3 },
-};
-
-static struct clk *exynos4_clkset_vpllsrc_list[] = {
-	[0] = &clk_fin_vpll,
-	[1] = &exynos4_clk_sclk_hdmi27m,
-};
-
-static struct clksrc_sources exynos4_clkset_vpllsrc = {
-	.sources	= exynos4_clkset_vpllsrc_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_vpllsrc_list),
-};
-
-static struct clksrc_clk exynos4_clk_vpllsrc = {
-	.clk	= {
-		.name		= "vpll_src",
-		.enable		= exynos4_clksrc_mask_top_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.sources = &exynos4_clkset_vpllsrc,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP1, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_sclk_vpll_list[] = {
-	[0] = &exynos4_clk_vpllsrc.clk,
-	[1] = &clk_fout_vpll,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_vpll = {
-	.sources	= exynos4_clkset_sclk_vpll_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_sclk_vpll_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_vpll = {
-	.clk	= {
-		.name		= "sclk_vpll",
-	},
-	.sources = &exynos4_clkset_sclk_vpll,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 8, .size = 1 },
-};
-
-static struct clk exynos4_init_clocks_off[] = {
-	{
-		.name		= "timers",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1<<24),
-	}, {
-		.name		= "csis",
-		.devname	= "s5p-mipi-csis.0",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "csis",
-		.devname	= "s5p-mipi-csis.1",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "jpeg",
-		.id		= 0,
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.0",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.1",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.2",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.3",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "exynos4-sdhci.0",
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "exynos4-sdhci.1",
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "exynos4-sdhci.2",
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "exynos4-sdhci.3",
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "dwmmc",
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "dac",
-		.devname	= "s5p-sdo",
-		.enable		= exynos4_clk_ip_tv_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "mixer",
-		.devname	= "s5p-mixer",
-		.enable		= exynos4_clk_ip_tv_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "vp",
-		.devname	= "s5p-mixer",
-		.enable		= exynos4_clk_ip_tv_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "hdmi",
-		.devname	= "exynos4-hdmi",
-		.enable		= exynos4_clk_ip_tv_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "hdmiphy",
-		.devname	= "exynos4-hdmi",
-		.enable		= exynos4_clk_hdmiphy_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "dacphy",
-		.devname	= "s5p-sdo",
-		.enable		= exynos4_clk_dac_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "adc",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 15),
-	}, {
-		.name		= "keypad",
-		.enable		= exynos4_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 16),
-	}, {
-		.name		= "rtc",
-		.enable		= exynos4_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 15),
-	}, {
-		.name		= "watchdog",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 14),
-	}, {
-		.name		= "usbhost",
-		.enable		= exynos4_clk_ip_fsys_ctrl ,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "otg",
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 13),
-	}, {
-		.name		= "spi",
-		.devname	= "exynos4210-spi.0",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 16),
-	}, {
-		.name		= "spi",
-		.devname	= "exynos4210-spi.1",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 17),
-	}, {
-		.name		= "spi",
-		.devname	= "exynos4210-spi.2",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 18),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.0",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 19),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.1",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 20),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.2",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 21),
-	}, {
-		.name		= "ac97",
-		.devname	= "samsung-ac97",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 27),
-	}, {
-		.name		= "mfc",
-		.devname	= "s5p-mfc",
-		.enable		= exynos4_clk_ip_mfc_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.0",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.1",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.2",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.3",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.4",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.5",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 11),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.6",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.7",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 13),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-hdmiphy-i2c",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 14),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(mfc_l, 0),
-		.enable		= exynos4_clk_ip_mfc_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(mfc_r, 1),
-		.enable		= exynos4_clk_ip_mfc_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(tv, 2),
-		.enable		= exynos4_clk_ip_tv_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(jpeg, 3),
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 11),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(rot, 4),
-		.enable		= exynos4_clk_ip_image_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(fimc0, 5),
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(fimc1, 6),
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(fimc2, 7),
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(fimc3, 8),
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(fimd0, 10),
-		.enable		= exynos4_clk_ip_lcd0_ctrl,
-		.ctrlbit	= (1 << 4),
-	}
-};
-
-static struct clk exynos4_init_clocks_on[] = {
-	{
-		.name		= "uart",
-		.devname	= "s5pv210-uart.0",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.1",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.2",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.3",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.4",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.5",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 5),
-	}
-};
-
-static struct clk exynos4_clk_pdma0 = {
-	.name		= "dma",
-	.devname	= "dma-pl330.0",
-	.enable		= exynos4_clk_ip_fsys_ctrl,
-	.ctrlbit	= (1 << 0),
-};
-
-static struct clk exynos4_clk_pdma1 = {
-	.name		= "dma",
-	.devname	= "dma-pl330.1",
-	.enable		= exynos4_clk_ip_fsys_ctrl,
-	.ctrlbit	= (1 << 1),
-};
-
-static struct clk exynos4_clk_mdma1 = {
-	.name		= "dma",
-	.devname	= "dma-pl330.2",
-	.enable		= exynos4_clk_ip_image_ctrl,
-	.ctrlbit	= ((1 << 8) | (1 << 5) | (1 << 2)),
-};
-
-static struct clk exynos4_clk_fimd0 = {
-	.name		= "fimd",
-	.devname	= "exynos4-fb.0",
-	.enable		= exynos4_clk_ip_lcd0_ctrl,
-	.ctrlbit	= (1 << 0),
-};
-
-struct clk *exynos4_clkset_group_list[] = {
-	[0] = &clk_ext_xtal_mux,
-	[1] = &clk_xusbxti,
-	[2] = &exynos4_clk_sclk_hdmi27m,
-	[3] = &exynos4_clk_sclk_usbphy0,
-	[4] = &exynos4_clk_sclk_usbphy1,
-	[5] = &exynos4_clk_sclk_hdmiphy,
-	[6] = &exynos4_clk_mout_mpll.clk,
-	[7] = &exynos4_clk_mout_epll.clk,
-	[8] = &exynos4_clk_sclk_vpll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_group = {
-	.sources	= exynos4_clkset_group_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_group_list),
-};
-
-static struct clk *exynos4_clkset_mout_g2d0_list[] = {
-	[0] = &exynos4_clk_mout_mpll.clk,
-	[1] = &exynos4_clk_sclk_apll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_mout_g2d0 = {
-	.sources	= exynos4_clkset_mout_g2d0_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_mout_g2d0_list),
-};
-
-static struct clk *exynos4_clkset_mout_g2d1_list[] = {
-	[0] = &exynos4_clk_mout_epll.clk,
-	[1] = &exynos4_clk_sclk_vpll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_mout_g2d1 = {
-	.sources	= exynos4_clkset_mout_g2d1_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_mout_g2d1_list),
-};
-
-static struct clk *exynos4_clkset_mout_mfc0_list[] = {
-	[0] = &exynos4_clk_mout_mpll.clk,
-	[1] = &exynos4_clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_mout_mfc0 = {
-	.sources	= exynos4_clkset_mout_mfc0_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_mout_mfc0_list),
-};
-
-static struct clksrc_clk exynos4_clk_mout_mfc0 = {
-	.clk	= {
-		.name		= "mout_mfc0",
-	},
-	.sources = &exynos4_clkset_mout_mfc0,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_MFC, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_mout_mfc1_list[] = {
-	[0] = &exynos4_clk_mout_epll.clk,
-	[1] = &exynos4_clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_mout_mfc1 = {
-	.sources	= exynos4_clkset_mout_mfc1_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_mout_mfc1_list),
-};
-
-static struct clksrc_clk exynos4_clk_mout_mfc1 = {
-	.clk	= {
-		.name		= "mout_mfc1",
-	},
-	.sources = &exynos4_clkset_mout_mfc1,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_MFC, .shift = 4, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_mout_mfc_list[] = {
-	[0] = &exynos4_clk_mout_mfc0.clk,
-	[1] = &exynos4_clk_mout_mfc1.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_mout_mfc = {
-	.sources	= exynos4_clkset_mout_mfc_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_mout_mfc_list),
-};
-
-static struct clk *exynos4_clkset_sclk_dac_list[] = {
-	[0] = &exynos4_clk_sclk_vpll.clk,
-	[1] = &exynos4_clk_sclk_hdmiphy,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_dac = {
-	.sources	= exynos4_clkset_sclk_dac_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_sclk_dac_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_dac = {
-	.clk		= {
-		.name		= "sclk_dac",
-		.enable		= exynos4_clksrc_mask_tv_ctrl,
-		.ctrlbit	= (1 << 8),
-	},
-	.sources = &exynos4_clkset_sclk_dac,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TV, .shift = 8, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_pixel = {
-	.clk		= {
-		.name		= "sclk_pixel",
-		.parent		= &exynos4_clk_sclk_vpll.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_TV, .shift = 0, .size = 4 },
-};
-
-static struct clk *exynos4_clkset_sclk_hdmi_list[] = {
-	[0] = &exynos4_clk_sclk_pixel.clk,
-	[1] = &exynos4_clk_sclk_hdmiphy,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_hdmi = {
-	.sources	= exynos4_clkset_sclk_hdmi_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_sclk_hdmi_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_hdmi = {
-	.clk		= {
-		.name		= "sclk_hdmi",
-		.enable		= exynos4_clksrc_mask_tv_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.sources = &exynos4_clkset_sclk_hdmi,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TV, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_sclk_mixer_list[] = {
-	[0] = &exynos4_clk_sclk_dac.clk,
-	[1] = &exynos4_clk_sclk_hdmi.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_mixer = {
-	.sources	= exynos4_clkset_sclk_mixer_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_sclk_mixer_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mixer = {
-	.clk	= {
-		.name		= "sclk_mixer",
-		.enable		= exynos4_clksrc_mask_tv_ctrl,
-		.ctrlbit	= (1 << 4),
-	},
-	.sources = &exynos4_clkset_sclk_mixer,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TV, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk *exynos4_sclk_tv[] = {
-	&exynos4_clk_sclk_dac,
-	&exynos4_clk_sclk_pixel,
-	&exynos4_clk_sclk_hdmi,
-	&exynos4_clk_sclk_mixer,
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc0 = {
-	.clk	= {
-		.name		= "dout_mmc0",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 0, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc1 = {
-	.clk	= {
-		.name		= "dout_mmc1",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 4, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc2 = {
-	.clk	= {
-		.name		= "dout_mmc2",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 8, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc3 = {
-	.clk	= {
-		.name		= "dout_mmc3",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 12, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc4 = {
-	.clk		= {
-		.name		= "dout_mmc4",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 16, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS3, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clksrcs[] = {
-	{
-		.clk	= {
-			.name		= "sclk_pwm",
-			.enable		= exynos4_clksrc_mask_peril0_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 24, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL3, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_csis",
-			.devname	= "s5p-mipi-csis.0",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 24, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 24, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_csis",
-			.devname	= "s5p-mipi-csis.1",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 28),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 28, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 28, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_cam0",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 16),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 16, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 16, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_cam1",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 20),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 20, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 20, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimc",
-			.devname	= "exynos4-fimc.0",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 0, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimc",
-			.devname	= "exynos4-fimc.1",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 4),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 4, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 4, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimc",
-			.devname	= "exynos4-fimc.2",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 8),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 8, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 8, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimc",
-			.devname	= "exynos4-fimc.3",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 12),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 12, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 12, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimd",
-			.devname	= "exynos4-fb.0",
-			.enable		= exynos4_clksrc_mask_lcd0_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_LCD0, .shift = 0, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_LCD0, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_mfc",
-			.devname	= "s5p-mfc",
-		},
-		.sources = &exynos4_clkset_mout_mfc,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_MFC, .shift = 8, .size = 1 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_MFC, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_dwmmc",
-			.parent		= &exynos4_clk_dout_mmc4.clk,
-			.enable		= exynos4_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 16),
-		},
-		.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS3, .shift = 8, .size = 8 },
-	}
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart0 = {
-	.clk	= {
-		.name		= "uclk1",
-		.devname	= "exynos4210-uart.0",
-		.enable		= exynos4_clksrc_mask_peril0_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 0, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart1 = {
-	.clk	= {
-		.name		= "uclk1",
-		.devname	= "exynos4210-uart.1",
-		.enable		= exynos4_clksrc_mask_peril0_ctrl,
-		.ctrlbit	= (1 << 4),
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 4, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart2 = {
-	.clk	= {
-		.name		= "uclk1",
-		.devname	= "exynos4210-uart.2",
-		.enable		= exynos4_clksrc_mask_peril0_ctrl,
-		.ctrlbit	= (1 << 8),
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 8, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart3 = {
-	.clk	= {
-		.name		= "uclk1",
-		.devname	= "exynos4210-uart.3",
-		.enable		= exynos4_clksrc_mask_peril0_ctrl,
-		.ctrlbit	= (1 << 12),
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 12, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 12, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc0 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "exynos4-sdhci.0",
-		.parent		= &exynos4_clk_dout_mmc0.clk,
-		.enable		= exynos4_clksrc_mask_fsys_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc1 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "exynos4-sdhci.1",
-		.parent		= &exynos4_clk_dout_mmc1.clk,
-		.enable		= exynos4_clksrc_mask_fsys_ctrl,
-		.ctrlbit	= (1 << 4),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc2 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "exynos4-sdhci.2",
-		.parent		= &exynos4_clk_dout_mmc2.clk,
-		.enable		= exynos4_clksrc_mask_fsys_ctrl,
-		.ctrlbit	= (1 << 8),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc3 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "exynos4-sdhci.3",
-		.parent		= &exynos4_clk_dout_mmc3.clk,
-		.enable		= exynos4_clksrc_mask_fsys_ctrl,
-		.ctrlbit	= (1 << 12),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_mdout_spi0 = {
-	.clk	= {
-		.name		= "mdout_spi",
-		.devname	= "exynos4210-spi.0",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 16, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_mdout_spi1 = {
-	.clk	= {
-		.name		= "mdout_spi",
-		.devname	= "exynos4210-spi.1",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 20, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_mdout_spi2 = {
-	.clk	= {
-		.name		= "mdout_spi",
-		.devname	= "exynos4210-spi.2",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 24, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_spi0 = {
-	.clk	= {
-		.name		= "sclk_spi",
-		.devname	= "exynos4210-spi.0",
-		.parent		= &exynos4_clk_mdout_spi0.clk,
-		.enable		= exynos4_clksrc_mask_peril1_ctrl,
-		.ctrlbit	= (1 << 16),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_spi1 = {
-	.clk	= {
-		.name		= "sclk_spi",
-		.devname	= "exynos4210-spi.1",
-		.parent		= &exynos4_clk_mdout_spi1.clk,
-		.enable		= exynos4_clksrc_mask_peril1_ctrl,
-		.ctrlbit	= (1 << 20),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_spi2 = {
-	.clk	= {
-		.name		= "sclk_spi",
-		.devname	= "exynos4210-spi.2",
-		.parent		= &exynos4_clk_mdout_spi2.clk,
-		.enable		= exynos4_clksrc_mask_peril1_ctrl,
-		.ctrlbit	= (1 << 24),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL2, .shift = 8, .size = 8 },
-};
-
-/* Clock initialization code */
-static struct clksrc_clk *exynos4_sysclks[] = {
-	&exynos4_clk_mout_apll,
-	&exynos4_clk_sclk_apll,
-	&exynos4_clk_mout_epll,
-	&exynos4_clk_mout_mpll,
-	&exynos4_clk_moutcore,
-	&exynos4_clk_coreclk,
-	&exynos4_clk_armclk,
-	&exynos4_clk_aclk_corem0,
-	&exynos4_clk_aclk_cores,
-	&exynos4_clk_aclk_corem1,
-	&exynos4_clk_periphclk,
-	&exynos4_clk_mout_corebus,
-	&exynos4_clk_sclk_dmc,
-	&exynos4_clk_aclk_cored,
-	&exynos4_clk_aclk_corep,
-	&exynos4_clk_aclk_acp,
-	&exynos4_clk_pclk_acp,
-	&exynos4_clk_vpllsrc,
-	&exynos4_clk_sclk_vpll,
-	&exynos4_clk_aclk_200,
-	&exynos4_clk_aclk_100,
-	&exynos4_clk_aclk_160,
-	&exynos4_clk_aclk_133,
-	&exynos4_clk_dout_mmc0,
-	&exynos4_clk_dout_mmc1,
-	&exynos4_clk_dout_mmc2,
-	&exynos4_clk_dout_mmc3,
-	&exynos4_clk_dout_mmc4,
-	&exynos4_clk_mout_mfc0,
-	&exynos4_clk_mout_mfc1,
-};
-
-static struct clk *exynos4_clk_cdev[] = {
-	&exynos4_clk_pdma0,
-	&exynos4_clk_pdma1,
-	&exynos4_clk_mdma1,
-	&exynos4_clk_fimd0,
-};
-
-static struct clksrc_clk *exynos4_clksrc_cdev[] = {
-	&exynos4_clk_sclk_uart0,
-	&exynos4_clk_sclk_uart1,
-	&exynos4_clk_sclk_uart2,
-	&exynos4_clk_sclk_uart3,
-	&exynos4_clk_sclk_mmc0,
-	&exynos4_clk_sclk_mmc1,
-	&exynos4_clk_sclk_mmc2,
-	&exynos4_clk_sclk_mmc3,
-	&exynos4_clk_sclk_spi0,
-	&exynos4_clk_sclk_spi1,
-	&exynos4_clk_sclk_spi2,
-	&exynos4_clk_mdout_spi0,
-	&exynos4_clk_mdout_spi1,
-	&exynos4_clk_mdout_spi2,
-};
-
-static struct clk_lookup exynos4_clk_lookup[] = {
-	CLKDEV_INIT("exynos4210-uart.0", "clk_uart_baud0", &exynos4_clk_sclk_uart0.clk),
-	CLKDEV_INIT("exynos4210-uart.1", "clk_uart_baud0", &exynos4_clk_sclk_uart1.clk),
-	CLKDEV_INIT("exynos4210-uart.2", "clk_uart_baud0", &exynos4_clk_sclk_uart2.clk),
-	CLKDEV_INIT("exynos4210-uart.3", "clk_uart_baud0", &exynos4_clk_sclk_uart3.clk),
-	CLKDEV_INIT("exynos4-sdhci.0", "mmc_busclk.2", &exynos4_clk_sclk_mmc0.clk),
-	CLKDEV_INIT("exynos4-sdhci.1", "mmc_busclk.2", &exynos4_clk_sclk_mmc1.clk),
-	CLKDEV_INIT("exynos4-sdhci.2", "mmc_busclk.2", &exynos4_clk_sclk_mmc2.clk),
-	CLKDEV_INIT("exynos4-sdhci.3", "mmc_busclk.2", &exynos4_clk_sclk_mmc3.clk),
-	CLKDEV_INIT("exynos4-fb.0", "lcd", &exynos4_clk_fimd0),
-	CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos4_clk_pdma0),
-	CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos4_clk_pdma1),
-	CLKDEV_INIT("dma-pl330.2", "apb_pclk", &exynos4_clk_mdma1),
-	CLKDEV_INIT("exynos4210-spi.0", "spi_busclk0", &exynos4_clk_sclk_spi0.clk),
-	CLKDEV_INIT("exynos4210-spi.1", "spi_busclk0", &exynos4_clk_sclk_spi1.clk),
-	CLKDEV_INIT("exynos4210-spi.2", "spi_busclk0", &exynos4_clk_sclk_spi2.clk),
-};
-
-static int xtal_rate;
-
-static unsigned long exynos4_fout_apll_get_rate(struct clk *clk)
-{
-	if (soc_is_exynos4210())
-		return s5p_get_pll45xx(xtal_rate, __raw_readl(EXYNOS4_APLL_CON0),
-					pll_4508);
-	else if (soc_is_exynos4212() || soc_is_exynos4412())
-		return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_APLL_CON0));
-	else
-		return 0;
-}
-
-static struct clk_ops exynos4_fout_apll_ops = {
-	.get_rate = exynos4_fout_apll_get_rate,
-};
-
-static u32 exynos4_vpll_div[][8] = {
-	{  54000000, 3, 53, 3, 1024, 0, 17, 0 },
-	{ 108000000, 3, 53, 2, 1024, 0, 17, 0 },
-};
-
-static unsigned long exynos4_vpll_get_rate(struct clk *clk)
-{
-	return clk->rate;
-}
-
-static int exynos4_vpll_set_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned int vpll_con0, vpll_con1 = 0;
-	unsigned int i;
-
-	/* Return if nothing changed */
-	if (clk->rate == rate)
-		return 0;
-
-	vpll_con0 = __raw_readl(EXYNOS4_VPLL_CON0);
-	vpll_con0 &= ~(0x1 << 27 |					\
-			PLL90XX_MDIV_MASK << PLL46XX_MDIV_SHIFT |	\
-			PLL90XX_PDIV_MASK << PLL46XX_PDIV_SHIFT |	\
-			PLL90XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
-
-	vpll_con1 = __raw_readl(EXYNOS4_VPLL_CON1);
-	vpll_con1 &= ~(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT |	\
-			PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT |	\
-			PLL4650C_KDIV_MASK << PLL46XX_KDIV_SHIFT);
-
-	for (i = 0; i < ARRAY_SIZE(exynos4_vpll_div); i++) {
-		if (exynos4_vpll_div[i][0] == rate) {
-			vpll_con0 |= exynos4_vpll_div[i][1] << PLL46XX_PDIV_SHIFT;
-			vpll_con0 |= exynos4_vpll_div[i][2] << PLL46XX_MDIV_SHIFT;
-			vpll_con0 |= exynos4_vpll_div[i][3] << PLL46XX_SDIV_SHIFT;
-			vpll_con1 |= exynos4_vpll_div[i][4] << PLL46XX_KDIV_SHIFT;
-			vpll_con1 |= exynos4_vpll_div[i][5] << PLL46XX_MFR_SHIFT;
-			vpll_con1 |= exynos4_vpll_div[i][6] << PLL46XX_MRR_SHIFT;
-			vpll_con0 |= exynos4_vpll_div[i][7] << 27;
-			break;
-		}
-	}
-
-	if (i == ARRAY_SIZE(exynos4_vpll_div)) {
-		printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n",
-				__func__);
-		return -EINVAL;
-	}
-
-	__raw_writel(vpll_con0, EXYNOS4_VPLL_CON0);
-	__raw_writel(vpll_con1, EXYNOS4_VPLL_CON1);
-
-	/* Wait for VPLL lock */
-	while (!(__raw_readl(EXYNOS4_VPLL_CON0) & (1 << PLL46XX_LOCKED_SHIFT)))
-		continue;
-
-	clk->rate = rate;
-	return 0;
-}
-
-static struct clk_ops exynos4_vpll_ops = {
-	.get_rate = exynos4_vpll_get_rate,
-	.set_rate = exynos4_vpll_set_rate,
-};
-
-void __init_or_cpufreq exynos4_setup_clocks(void)
-{
-	struct clk *xtal_clk;
-	unsigned long apll = 0;
-	unsigned long mpll = 0;
-	unsigned long epll = 0;
-	unsigned long vpll = 0;
-	unsigned long vpllsrc;
-	unsigned long xtal;
-	unsigned long armclk;
-	unsigned long sclk_dmc;
-	unsigned long aclk_200;
-	unsigned long aclk_100;
-	unsigned long aclk_160;
-	unsigned long aclk_133;
-	unsigned int ptr;
-
-	printk(KERN_DEBUG "%s: registering clocks\n", __func__);
-
-	xtal_clk = clk_get(NULL, "xtal");
-	BUG_ON(IS_ERR(xtal_clk));
-
-	xtal = clk_get_rate(xtal_clk);
-
-	xtal_rate = xtal;
-
-	clk_put(xtal_clk);
-
-	printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
-
-	if (soc_is_exynos4210()) {
-		apll = s5p_get_pll45xx(xtal, __raw_readl(EXYNOS4_APLL_CON0),
-					pll_4508);
-		mpll = s5p_get_pll45xx(xtal, __raw_readl(EXYNOS4_MPLL_CON0),
-					pll_4508);
-		epll = s5p_get_pll46xx(xtal, __raw_readl(EXYNOS4_EPLL_CON0),
-					__raw_readl(EXYNOS4_EPLL_CON1), pll_4600);
-
-		vpllsrc = clk_get_rate(&exynos4_clk_vpllsrc.clk);
-		vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(EXYNOS4_VPLL_CON0),
-					__raw_readl(EXYNOS4_VPLL_CON1), pll_4650c);
-	} else if (soc_is_exynos4212() || soc_is_exynos4412()) {
-		apll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS4_APLL_CON0));
-		mpll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS4_MPLL_CON0));
-		epll = s5p_get_pll36xx(xtal, __raw_readl(EXYNOS4_EPLL_CON0),
-					__raw_readl(EXYNOS4_EPLL_CON1));
-
-		vpllsrc = clk_get_rate(&exynos4_clk_vpllsrc.clk);
-		vpll = s5p_get_pll36xx(vpllsrc, __raw_readl(EXYNOS4_VPLL_CON0),
-					__raw_readl(EXYNOS4_VPLL_CON1));
-	} else {
-		/* nothing */
-	}
-
-	clk_fout_apll.ops = &exynos4_fout_apll_ops;
-	clk_fout_mpll.rate = mpll;
-	clk_fout_epll.rate = epll;
-	clk_fout_vpll.ops = &exynos4_vpll_ops;
-	clk_fout_vpll.rate = vpll;
-
-	printk(KERN_INFO "EXYNOS4: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
-			apll, mpll, epll, vpll);
-
-	armclk = clk_get_rate(&exynos4_clk_armclk.clk);
-	sclk_dmc = clk_get_rate(&exynos4_clk_sclk_dmc.clk);
-
-	aclk_200 = clk_get_rate(&exynos4_clk_aclk_200.clk);
-	aclk_100 = clk_get_rate(&exynos4_clk_aclk_100.clk);
-	aclk_160 = clk_get_rate(&exynos4_clk_aclk_160.clk);
-	aclk_133 = clk_get_rate(&exynos4_clk_aclk_133.clk);
-
-	printk(KERN_INFO "EXYNOS4: ARMCLK=%ld, DMC=%ld, ACLK200=%ld\n"
-			 "ACLK100=%ld, ACLK160=%ld, ACLK133=%ld\n",
-			armclk, sclk_dmc, aclk_200,
-			aclk_100, aclk_160, aclk_133);
-
-	clk_f.rate = armclk;
-	clk_h.rate = sclk_dmc;
-	clk_p.rate = aclk_100;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos4_clksrcs); ptr++)
-		s3c_set_clksrc(&exynos4_clksrcs[ptr], true);
-}
-
-static struct clk *exynos4_clks[] __initdata = {
-	&exynos4_clk_sclk_hdmi27m,
-	&exynos4_clk_sclk_hdmiphy,
-	&exynos4_clk_sclk_usbphy0,
-	&exynos4_clk_sclk_usbphy1,
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos4_clock_suspend(void)
-{
-	s3c_pm_do_save(exynos4_clock_save, ARRAY_SIZE(exynos4_clock_save));
-	return 0;
-}
-
-static void exynos4_clock_resume(void)
-{
-	s3c_pm_do_restore_core(exynos4_clock_save, ARRAY_SIZE(exynos4_clock_save));
-}
-
-#else
-#define exynos4_clock_suspend NULL
-#define exynos4_clock_resume NULL
-#endif
-
-static struct syscore_ops exynos4_clock_syscore_ops = {
-	.suspend	= exynos4_clock_suspend,
-	.resume		= exynos4_clock_resume,
-};
-
-void __init exynos4_register_clocks(void)
-{
-	int ptr;
-
-	s3c24xx_register_clocks(exynos4_clks, ARRAY_SIZE(exynos4_clks));
-
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos4_sysclks); ptr++)
-		s3c_register_clksrc(exynos4_sysclks[ptr], 1);
-
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos4_sclk_tv); ptr++)
-		s3c_register_clksrc(exynos4_sclk_tv[ptr], 1);
-
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos4_clksrc_cdev); ptr++)
-		s3c_register_clksrc(exynos4_clksrc_cdev[ptr], 1);
-
-	s3c_register_clksrc(exynos4_clksrcs, ARRAY_SIZE(exynos4_clksrcs));
-	s3c_register_clocks(exynos4_init_clocks_on, ARRAY_SIZE(exynos4_init_clocks_on));
-
-	s3c24xx_register_clocks(exynos4_clk_cdev, ARRAY_SIZE(exynos4_clk_cdev));
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos4_clk_cdev); ptr++)
-		s3c_disable_clocks(exynos4_clk_cdev[ptr], 1);
-
-	s3c_register_clocks(exynos4_init_clocks_off, ARRAY_SIZE(exynos4_init_clocks_off));
-	s3c_disable_clocks(exynos4_init_clocks_off, ARRAY_SIZE(exynos4_init_clocks_off));
-	clkdev_add_table(exynos4_clk_lookup, ARRAY_SIZE(exynos4_clk_lookup));
-
-	register_syscore_ops(&exynos4_clock_syscore_ops);
-	s3c24xx_register_clock(&dummy_apb_pclk);
-
-	s3c_pwmclk_init();
-}
diff --git a/arch/arm/mach-exynos/clock-exynos4.h b/arch/arm/mach-exynos/clock-exynos4.h
deleted file mode 100644
index bd12d5f..0000000
--- a/arch/arm/mach-exynos/clock-exynos4.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Header file for exynos4 clock support
- *
- * 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 __ASM_ARCH_CLOCK_H
-#define __ASM_ARCH_CLOCK_H __FILE__
-
-#include <linux/clk.h>
-
-extern struct clksrc_clk exynos4_clk_aclk_133;
-extern struct clksrc_clk exynos4_clk_mout_mpll;
-
-extern struct clksrc_sources exynos4_clkset_mout_corebus;
-extern struct clksrc_sources exynos4_clkset_group;
-
-extern struct clk *exynos4_clkset_aclk_top_list[];
-extern struct clk *exynos4_clkset_group_list[];
-
-extern struct clksrc_sources exynos4_clkset_mout_g2d0;
-extern struct clksrc_sources exynos4_clkset_mout_g2d1;
-
-extern int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable);
-extern int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable);
-extern int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable);
-extern int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable);
-extern int exynos4_clk_ip_dmc_ctrl(struct clk *clk, int enable);
-
-#endif /* __ASM_ARCH_CLOCK_H */
diff --git a/arch/arm/mach-exynos/clock-exynos4210.c b/arch/arm/mach-exynos/clock-exynos4210.c
deleted file mode 100644
index fed4c26..0000000
--- a/arch/arm/mach-exynos/clock-exynos4210.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4210 - Clock support
- *
- * 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.
-*/
-
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-#include <plat/pm.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/sysmmu.h>
-
-#include "common.h"
-#include "clock-exynos4.h"
-
-#ifdef CONFIG_PM_SLEEP
-static struct sleep_save exynos4210_clock_save[] = {
-	SAVE_ITEM(EXYNOS4_CLKSRC_IMAGE),
-	SAVE_ITEM(EXYNOS4_CLKDIV_IMAGE),
-	SAVE_ITEM(EXYNOS4210_CLKSRC_LCD1),
-	SAVE_ITEM(EXYNOS4210_CLKDIV_LCD1),
-	SAVE_ITEM(EXYNOS4210_CLKSRC_MASK_LCD1),
-	SAVE_ITEM(EXYNOS4210_CLKGATE_IP_IMAGE),
-	SAVE_ITEM(EXYNOS4210_CLKGATE_IP_LCD1),
-	SAVE_ITEM(EXYNOS4210_CLKGATE_IP_PERIR),
-};
-#endif
-
-static struct clksrc_clk *sysclks[] = {
-	/* nothing here yet */
-};
-
-static struct clksrc_clk exynos4210_clk_mout_g2d0 = {
-	.clk	= {
-		.name		= "mout_g2d0",
-	},
-	.sources = &exynos4_clkset_mout_g2d0,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk exynos4210_clk_mout_g2d1 = {
-	.clk	= {
-		.name		= "mout_g2d1",
-	},
-	.sources = &exynos4_clkset_mout_g2d1,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 4, .size = 1 },
-};
-
-static struct clk *exynos4210_clkset_mout_g2d_list[] = {
-	[0] = &exynos4210_clk_mout_g2d0.clk,
-	[1] = &exynos4210_clk_mout_g2d1.clk,
-};
-
-static struct clksrc_sources exynos4210_clkset_mout_g2d = {
-	.sources	= exynos4210_clkset_mout_g2d_list,
-	.nr_sources	= ARRAY_SIZE(exynos4210_clkset_mout_g2d_list),
-};
-
-static int exynos4_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4210_CLKSRC_MASK_LCD1, clk, enable);
-}
-
-static struct clksrc_clk clksrcs[] = {
-	{
-		.clk		= {
-			.name		= "sclk_sata",
-			.id		= -1,
-			.enable		= exynos4_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &exynos4_clkset_mout_corebus,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 24, .size = 1 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS0, .shift = 20, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimd",
-			.devname	= "exynos4-fb.1",
-			.enable		= exynos4_clksrc_mask_lcd1_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4210_CLKSRC_LCD1, .shift = 0, .size = 4 },
-		.reg_div = { .reg = EXYNOS4210_CLKDIV_LCD1, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimg2d",
-		},
-		.sources = &exynos4210_clkset_mout_g2d,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 8, .size = 1 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_IMAGE, .shift = 0, .size = 4 },
-	},
-};
-
-static struct clk init_clocks_off[] = {
-	{
-		.name		= "sataphy",
-		.id		= -1,
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "sata",
-		.id		= -1,
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "fimd",
-		.devname	= "exynos4-fb.1",
-		.enable		= exynos4_clk_ip_lcd1_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(2d, 14),
-		.enable		= exynos4_clk_ip_image_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(fimd1, 11),
-		.enable		= exynos4_clk_ip_lcd1_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "fimg2d",
-		.enable		= exynos4_clk_ip_image_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos4210_clock_suspend(void)
-{
-	s3c_pm_do_save(exynos4210_clock_save, ARRAY_SIZE(exynos4210_clock_save));
-
-	return 0;
-}
-
-static void exynos4210_clock_resume(void)
-{
-	s3c_pm_do_restore_core(exynos4210_clock_save, ARRAY_SIZE(exynos4210_clock_save));
-}
-
-#else
-#define exynos4210_clock_suspend NULL
-#define exynos4210_clock_resume NULL
-#endif
-
-static struct syscore_ops exynos4210_clock_syscore_ops = {
-	.suspend	= exynos4210_clock_suspend,
-	.resume		= exynos4210_clock_resume,
-};
-
-void __init exynos4210_register_clocks(void)
-{
-	int ptr;
-
-	exynos4_clk_mout_mpll.reg_src.reg = EXYNOS4_CLKSRC_CPU;
-	exynos4_clk_mout_mpll.reg_src.shift = 8;
-	exynos4_clk_mout_mpll.reg_src.size = 1;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
-		s3c_register_clksrc(sysclks[ptr], 1);
-
-	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
-
-	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-
-	register_syscore_ops(&exynos4210_clock_syscore_ops);
-}
diff --git a/arch/arm/mach-exynos/clock-exynos4212.c b/arch/arm/mach-exynos/clock-exynos4212.c
deleted file mode 100644
index 8fba0b5..0000000
--- a/arch/arm/mach-exynos/clock-exynos4212.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4212 - Clock support
- *
- * 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.
-*/
-
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-#include <plat/pm.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/sysmmu.h>
-
-#include "common.h"
-#include "clock-exynos4.h"
-
-#ifdef CONFIG_PM_SLEEP
-static struct sleep_save exynos4212_clock_save[] = {
-	SAVE_ITEM(EXYNOS4_CLKSRC_IMAGE),
-	SAVE_ITEM(EXYNOS4_CLKDIV_IMAGE),
-	SAVE_ITEM(EXYNOS4212_CLKGATE_IP_IMAGE),
-	SAVE_ITEM(EXYNOS4212_CLKGATE_IP_PERIR),
-};
-#endif
-
-static int exynos4212_clk_ip_isp0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_ISP0, clk, enable);
-}
-
-static int exynos4212_clk_ip_isp1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_ISP1, clk, enable);
-}
-
-static struct clk *clk_src_mpll_user_list[] = {
-	[0] = &clk_fin_mpll,
-	[1] = &exynos4_clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources clk_src_mpll_user = {
-	.sources	= clk_src_mpll_user_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_mpll_user_list),
-};
-
-static struct clksrc_clk clk_mout_mpll_user = {
-	.clk = {
-		.name		= "mout_mpll_user",
-	},
-	.sources	= &clk_src_mpll_user,
-	.reg_src	= { .reg = EXYNOS4_CLKSRC_CPU, .shift = 24, .size = 1 },
-};
-
-static struct clksrc_clk exynos4x12_clk_mout_g2d0 = {
-	.clk	= {
-		.name		= "mout_g2d0",
-	},
-	.sources = &exynos4_clkset_mout_g2d0,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 20, .size = 1 },
-};
-
-static struct clksrc_clk exynos4x12_clk_mout_g2d1 = {
-	.clk	= {
-		.name		= "mout_g2d1",
-	},
-	.sources = &exynos4_clkset_mout_g2d1,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 24, .size = 1 },
-};
-
-static struct clk *exynos4x12_clkset_mout_g2d_list[] = {
-	[0] = &exynos4x12_clk_mout_g2d0.clk,
-	[1] = &exynos4x12_clk_mout_g2d1.clk,
-};
-
-static struct clksrc_sources exynos4x12_clkset_mout_g2d = {
-	.sources	= exynos4x12_clkset_mout_g2d_list,
-	.nr_sources	= ARRAY_SIZE(exynos4x12_clkset_mout_g2d_list),
-};
-
-static struct clksrc_clk *sysclks[] = {
-	&clk_mout_mpll_user,
-};
-
-static struct clksrc_clk clksrcs[] = {
-	{
-		.clk	= {
-			.name		= "sclk_fimg2d",
-		},
-		.sources = &exynos4x12_clkset_mout_g2d,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 28, .size = 1 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_DMC1, .shift = 0, .size = 4 },
-	},
-};
-
-static struct clk init_clocks_off[] = {
-	{
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(2d, 14),
-		.enable		= exynos4_clk_ip_dmc_ctrl,
-		.ctrlbit	= (1 << 24),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(isp, 9),
-		.enable		= exynos4212_clk_ip_isp0_ctrl,
-		.ctrlbit	= (7 << 8),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME2,
-		.devname	= SYSMMU_CLOCK_DEVNAME(isp, 9),
-		.enable		= exynos4212_clk_ip_isp1_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "flite",
-		.devname	= "exynos-fimc-lite.0",
-		.enable		= exynos4212_clk_ip_isp0_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "flite",
-		.devname	= "exynos-fimc-lite.1",
-		.enable		= exynos4212_clk_ip_isp0_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "fimg2d",
-		.enable		= exynos4_clk_ip_dmc_ctrl,
-		.ctrlbit	= (1 << 23),
-	},
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos4212_clock_suspend(void)
-{
-	s3c_pm_do_save(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save));
-
-	return 0;
-}
-
-static void exynos4212_clock_resume(void)
-{
-	s3c_pm_do_restore_core(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save));
-}
-
-#else
-#define exynos4212_clock_suspend NULL
-#define exynos4212_clock_resume NULL
-#endif
-
-static struct syscore_ops exynos4212_clock_syscore_ops = {
-	.suspend	= exynos4212_clock_suspend,
-	.resume		= exynos4212_clock_resume,
-};
-
-void __init exynos4212_register_clocks(void)
-{
-	int ptr;
-
-	/* usbphy1 is removed */
-	exynos4_clkset_group_list[4] = NULL;
-
-	/* mout_mpll_user is used */
-	exynos4_clkset_group_list[6] = &clk_mout_mpll_user.clk;
-	exynos4_clkset_aclk_top_list[0] = &clk_mout_mpll_user.clk;
-
-	exynos4_clk_mout_mpll.reg_src.reg = EXYNOS4_CLKSRC_DMC;
-	exynos4_clk_mout_mpll.reg_src.shift = 12;
-	exynos4_clk_mout_mpll.reg_src.size = 1;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
-		s3c_register_clksrc(sysclks[ptr], 1);
-
-	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
-
-	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-
-	register_syscore_ops(&exynos4212_clock_syscore_ops);
-}
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 4eb39cd..864adce 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -370,29 +370,23 @@ static void __init exynos5_map_io(void)
 
 static void __init exynos4_init_clocks(int xtal)
 {
-	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
-
-	s3c24xx_register_baseclocks(xtal);
-	s5p_register_clocks(xtal);
-
-	if (soc_is_exynos4210())
-		exynos4210_register_clocks();
-	else if (soc_is_exynos4212() || soc_is_exynos4412())
-		exynos4212_register_clocks();
-
-	exynos4_register_clocks();
-	exynos4_setup_clocks();
+	/*
+	 * TODO: Remove this function after migrating all Samsung platforms
+	 * to common clock framework.
+	 */
 }
 
 static void __init exynos5_init_clocks(int xtal)
 {
 	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
 
+#ifndef CONFIG_COMMON_CLK
 	s3c24xx_register_baseclocks(xtal);
 	s5p_register_clocks(xtal);
 
 	exynos5_register_clocks();
 	exynos5_setup_clocks();
+#endif
 }
 
 #define COMBINER_ENABLE_SET	0x0
diff --git a/arch/arm/mach-exynos/mach-armlex4210.c b/arch/arm/mach-exynos/mach-armlex4210.c
index 5a3daa0..83e2410 100644
--- a/arch/arm/mach-exynos/mach-armlex4210.c
+++ b/arch/arm/mach-exynos/mach-armlex4210.c
@@ -179,7 +179,6 @@ static void __init armlex4210_smsc911x_init(void)
 static void __init armlex4210_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(24000000);
 	s3c24xx_init_uarts(armlex4210_uartcfgs,
 			   ARRAY_SIZE(armlex4210_uartcfgs));
 }
diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c
index b2b5d5f..c851b13 100644
--- a/arch/arm/mach-exynos/mach-exynos4-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos4-dt.c
@@ -69,7 +69,6 @@ static const struct of_dev_auxdata exynos4210_auxdata_lookup[] __initconst = {
 static void __init exynos4210_dt_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(24000000);
 }
 
 static void __init exynos4210_dt_machine_init(void)
diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c
index ea785fc..976ec4c 100644
--- a/arch/arm/mach-exynos/mach-nuri.c
+++ b/arch/arm/mach-exynos/mach-nuri.c
@@ -1338,7 +1338,6 @@ static struct platform_device *nuri_devices[] __initdata = {
 static void __init nuri_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(clk_xusbxti.rate);
 	s3c24xx_init_uarts(nuri_uartcfgs, ARRAY_SIZE(nuri_uartcfgs));
 }
 
diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c
index 5ca8030..3addaf9 100644
--- a/arch/arm/mach-exynos/mach-origen.c
+++ b/arch/arm/mach-exynos/mach-origen.c
@@ -745,7 +745,6 @@ static void s5p_tv_setup(void)
 static void __init origen_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(clk_xusbxti.rate);
 	s3c24xx_init_uarts(origen_uartcfgs, ARRAY_SIZE(origen_uartcfgs));
 }
 
diff --git a/arch/arm/mach-exynos/mach-smdk4x12.c b/arch/arm/mach-exynos/mach-smdk4x12.c
index b26beb1..00809fe 100644
--- a/arch/arm/mach-exynos/mach-smdk4x12.c
+++ b/arch/arm/mach-exynos/mach-smdk4x12.c
@@ -321,7 +321,6 @@ static struct platform_device *smdk4x12_devices[] __initdata = {
 static void __init smdk4x12_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(clk_xusbxti.rate);
 	s3c24xx_init_uarts(smdk4x12_uartcfgs, ARRAY_SIZE(smdk4x12_uartcfgs));
 }
 
diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c
index 3cfa688..fd59f1f 100644
--- a/arch/arm/mach-exynos/mach-smdkv310.c
+++ b/arch/arm/mach-exynos/mach-smdkv310.c
@@ -365,7 +365,6 @@ static void s5p_tv_setup(void)
 static void __init smdkv310_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(clk_xusbxti.rate);
 	s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs));
 }
 
diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c
index 4d1f40d..80ddb0a 100644
--- a/arch/arm/mach-exynos/mach-universal_c210.c
+++ b/arch/arm/mach-exynos/mach-universal_c210.c
@@ -1100,7 +1100,6 @@ static struct platform_device *universal_devices[] __initdata = {
 static void __init universal_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(clk_xusbxti.rate);
 	s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
 	s5p_set_timer_source(S5P_PWM2, S5P_PWM4);
 }
-- 
1.7.1

^ permalink raw reply related

* [PATCH 2/2] ARM: Exynos4: Register clocks via common clock framework
From: chander.kashyap at linaro.org @ 2012-10-01 12:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349093361-18820-1-git-send-email-thomas.abraham@linaro.org>

From: Thomas Abraham <thomas.abraham@linaro.org>

Register clocks for Exynos4 platfotms using common clock framework.
Also included are set of helper functions for clock registration
that can be reused on other Samsung platforms as well.

Cc: Mike Turquette <mturquette@linaro.org>
Cc: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 arch/arm/mach-exynos/Kconfig      |    1 +
 arch/arm/mach-exynos/common.h     |    3 +
 arch/arm/mach-exynos/mct.c        |   11 +-
 arch/arm/plat-samsung/Kconfig     |    4 +-
 drivers/clk/Makefile              |    1 +
 drivers/clk/clk.c                 |   12 +-
 drivers/clk/samsung/Makefile      |    6 +
 drivers/clk/samsung/clk-exynos4.c |  585 +++++++++++++++++++++++++++++++++++++
 drivers/clk/samsung/clk.c         |  231 +++++++++++++++
 drivers/clk/samsung/clk.h         |  190 ++++++++++++
 10 files changed, 1037 insertions(+), 7 deletions(-)
 create mode 100644 drivers/clk/samsung/Makefile
 create mode 100644 drivers/clk/samsung/clk-exynos4.c
 create mode 100644 drivers/clk/samsung/clk.c
 create mode 100644 drivers/clk/samsung/clk.h

diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index b5b4c8c..4866ec7 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -15,6 +15,7 @@ config ARCH_EXYNOS4
 	bool "SAMSUNG EXYNOS4"
 	default y
 	select HAVE_SMP
+	select COMMON_CLK
 	select MIGHT_HAVE_CACHE_L2X0
 	help
 	  Samsung EXYNOS4 SoCs based systems
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index aed2eeb..2274431 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -21,6 +21,9 @@ void exynos4_restart(char mode, const char *cmd);
 void exynos5_restart(char mode, const char *cmd);
 void exynos_init_late(void);
 
+void exynos4210_clk_init(void);
+void exynos4212_clk_init(void);
+
 #ifdef CONFIG_PM_GENERIC_DOMAINS
 int exynos_pm_late_initcall(void);
 #else
diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c
index b601fb8..a7cace0 100644
--- a/arch/arm/mach-exynos/mct.c
+++ b/arch/arm/mach-exynos/mct.c
@@ -30,6 +30,8 @@
 #include <mach/regs-mct.h>
 #include <asm/mach/time.h>
 
+#include "common.h"
+
 #define TICK_BASE_CNT	1
 
 enum {
@@ -457,7 +459,7 @@ static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = {
 static void __init exynos4_timer_resources(void)
 {
 	struct clk *mct_clk;
-	mct_clk = clk_get(NULL, "xtal");
+	mct_clk = clk_get(NULL, "fin_pll");
 
 	clk_rate = clk_get_rate(mct_clk);
 
@@ -478,6 +480,13 @@ static void __init exynos4_timer_resources(void)
 
 static void __init exynos4_timer_init(void)
 {
+#ifdef CONFIG_COMMON_CLK
+	if (soc_is_exynos4210())
+		exynos4210_clk_init();
+	else if (soc_is_exynos4212() || soc_is_exynos4412())
+		exynos4212_clk_init();
+#endif
+
 	if ((soc_is_exynos4210()) || (soc_is_exynos5250()))
 		mct_int_type = MCT_INT_SPI;
 	else
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 9c3b90c..35b4cb8 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -26,7 +26,7 @@ config PLAT_S5P
 	select S5P_GPIO_DRVSTR
 	select SAMSUNG_GPIOLIB_4BIT
 	select PLAT_SAMSUNG
-	select SAMSUNG_CLKSRC
+	select SAMSUNG_CLKSRC if !COMMON_CLK
 	select SAMSUNG_IRQ_VIC_TIMER
 	help
 	  Base platform code for Samsung's S5P series SoC.
@@ -89,7 +89,7 @@ config SAMSUNG_CLKSRC
 	  used by newer systems such as the S3C64XX.
 
 config S5P_CLOCK
-	def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
+	def_bool ((ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS) && !COMMON_CLK)
 	help
 	  Support common clock part for ARCH_S5P and ARCH_EXYNOS SoCs
 
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 6327536..5f5b060 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_ARCH_MMP)		+= mmp/
 endif
 obj-$(CONFIG_MACH_LOONGSON1)	+= clk-ls1x.o
 obj-$(CONFIG_ARCH_U8500)	+= ux500/
+obj-$(CONFIG_PLAT_SAMSUNG)	+= samsung/
 
 # Chip specific
 obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 56e4495..456c50b 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1196,6 +1196,7 @@ EXPORT_SYMBOL_GPL(clk_set_parent);
 int __clk_init(struct device *dev, struct clk *clk)
 {
 	int i, ret = 0;
+	u8 index;
 	struct clk *orphan;
 	struct hlist_node *tmp, *tmp2;
 
@@ -1259,6 +1260,7 @@ int __clk_init(struct device *dev, struct clk *clk)
 					__clk_lookup(clk->parent_names[i]);
 	}
 
+
 	clk->parent = __clk_init_parent(clk);
 
 	/*
@@ -1298,11 +1300,13 @@ int __clk_init(struct device *dev, struct clk *clk)
 	 * this clock
 	 */
 	hlist_for_each_entry_safe(orphan, tmp, tmp2, &clk_orphan_list, child_node)
-		for (i = 0; i < orphan->num_parents; i++)
-			if (!strcmp(clk->name, orphan->parent_names[i])) {
+		if (orphan->num_parents > 1) {
+			index = orphan->ops->get_parent(orphan->hw);
+			if (!strcmp(clk->name, orphan->parent_names[index]))
 				__clk_reparent(orphan, clk);
-				break;
-			}
+		} else if (!strcmp(clk->name, orphan->parent_names[0])) {
+			__clk_reparent(orphan, clk);
+		}
 
 	/*
 	 * optional platform-specific magic
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
new file mode 100644
index 0000000..69487f7
--- /dev/null
+++ b/drivers/clk/samsung/Makefile
@@ -0,0 +1,6 @@
+#
+# Samsung Clock specific Makefile
+#
+
+obj-$(CONFIG_PLAT_SAMSUNG)	+= clk.o
+obj-$(CONFIG_ARCH_EXYNOS4)	+= clk-exynos4.o
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
new file mode 100644
index 0000000..74a6f03
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -0,0 +1,585 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2012 Linaro 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.
+ *
+ * Common Clock Framework support for all Exynos4 platforms
+*/
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+
+#include <plat/pll.h>
+#include <plat/cpu.h>
+#include <mach/regs-clock.h>
+#include <mach/sysmmu.h>
+#include <plat/map-s5p.h>
+
+#include "clk.h"
+
+#define EXYNOS4_OP_MODE		(S5P_VA_CHIPID + 8)
+
+static const char *pll_parent_names[] __initdata = { "fin_pll" };
+static const char *fin_pll_parents[] __initdata = { "xxti", "xusbxti" };
+static const char *mout_apll_parents[] __initdata = { "fin_pll", "fout_apll", };
+static const char *mout_mpll_parents[] __initdata = { "fin_pll", "fout_mpll", };
+static const char *mout_epll_parents[] __initdata = { "fin_pll", "fout_epll", };
+
+static const char *sclk_ampll_parents[] __initdata = {
+		"mout_mpll", "sclk_apll", };
+
+static const char *sclk_evpll_parents[] __initdata = {
+		"mout_epll", "mout_vpll", };
+
+static const char *mout_core_parents[] __initdata = {
+		"mout_apll", "mout_mpll", };
+
+static const char *mout_mfc_parents[] __initdata = {
+		"mout_mfc0", "mout_mfc1", };
+
+static const char *mout_dac_parents[] __initdata = {
+		"mout_vpll", "sclk_hdmiphy", };
+
+static const char *mout_hdmi_parents[] __initdata = {
+		"sclk_pixel", "sclk_hdmiphy", };
+
+static const char *mout_mixer_parents[] __initdata = {
+		"sclk_dac", "sclk_hdmi", };
+
+static const char *group1_parents[] __initdata = {
+		"xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
+		"none", "sclk_hdmiphy", "mout_mpll", "mout_epll",
+		"mout_vpll" };
+
+static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] = {
+	FRATE_CLK(NULL, "xxti", NULL, CLK_IS_ROOT, 24000000),
+	FRATE_CLK(NULL, "xusbxti", NULL, CLK_IS_ROOT, 24000000),
+	FRATE_CLK(NULL, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000),
+	FRATE_CLK(NULL, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
+	FRATE_CLK(NULL, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
+};
+
+static struct samsung_mux_clock exynos4_mux_clks[] = {
+	MUXCLK(NULL, "fin_pll", fin_pll_parents, 0,
+			EXYNOS4_OP_MODE, 0, 1, 0),
+	MUXCLK(NULL, "mout_apll", mout_apll_parents, 0,
+			EXYNOS4_CLKSRC_CPU, 0, 1, 0),
+	MUXCLK(NULL, "mout_epll", mout_epll_parents, 0,
+			EXYNOS4_CLKSRC_TOP0, 4, 1, 0),
+	MUXCLK(NULL, "mout_core", mout_core_parents, 0,
+			EXYNOS4_CLKSRC_CPU, 16, 1, 0),
+	MUXCLK(NULL, "mout_aclk_200", sclk_ampll_parents, 0,
+			EXYNOS4_CLKSRC_TOP0, 12, 1, 0),
+	MUXCLK(NULL, "mout_aclk_100", sclk_ampll_parents, 0,
+			EXYNOS4_CLKSRC_TOP0, 16, 1, 0),
+	MUXCLK(NULL, "mout_aclk_160", sclk_ampll_parents, 0,
+			EXYNOS4_CLKSRC_TOP0, 20, 1, 0),
+	MUXCLK(NULL, "mout_aclk_133", sclk_ampll_parents, 0,
+			EXYNOS4_CLKSRC_TOP0, 24, 1, 0),
+	MUXCLK("exynos4210-uart.0", "mout_uart0", group1_parents, 0,
+			EXYNOS4_CLKSRC_PERIL0, 0, 4, 0),
+	MUXCLK("exynos4210-uart.1", "mout_uart1", group1_parents, 0,
+			EXYNOS4_CLKSRC_PERIL0, 4, 4, 0),
+	MUXCLK("exynos4210-uart.2", "mout_uart2", group1_parents, 0,
+			EXYNOS4_CLKSRC_PERIL0, 8, 4, 0),
+	MUXCLK("exynos4210-uart.3", "mout_uart3", group1_parents, 0,
+			EXYNOS4_CLKSRC_PERIL0, 12, 4, 0),
+	MUXCLK("exynos4-sdhci.0", "mout_mmc0", group1_parents, 0,
+			EXYNOS4_CLKSRC_FSYS, 0, 4, 0),
+	MUXCLK("exynos4-sdhci.1", "mout_mmc1", group1_parents, 0,
+			EXYNOS4_CLKSRC_FSYS, 4, 4, 0),
+	MUXCLK("exynos4-sdhci.1", "mout_mmc2", group1_parents, 0,
+			EXYNOS4_CLKSRC_FSYS, 8, 4, 0),
+	MUXCLK("exynos4-sdhci.1", "mout_mmc3", group1_parents, 0,
+			EXYNOS4_CLKSRC_FSYS, 12, 4, 0),
+	MUXCLK("exynos4210-spi.0", "mout_spi0", group1_parents, 0,
+			EXYNOS4_CLKSRC_PERIL1, 16, 4, 0),
+	MUXCLK("exynos4210-spi.1", "mout_spi1", group1_parents, 0,
+			EXYNOS4_CLKSRC_PERIL1, 20, 4, 0),
+	MUXCLK("exynos4210-spi.2", "mout_spi2", group1_parents, 0,
+			EXYNOS4_CLKSRC_PERIL1, 24, 4, 0),
+	MUXCLK(NULL, "mout_sata", sclk_ampll_parents, 0,
+			EXYNOS4_CLKSRC_FSYS, 24, 1, 0),
+	MUXCLK(NULL, "mout_mfc0", sclk_ampll_parents, 0,
+			EXYNOS4_CLKSRC_MFC, 0, 1, 0),
+	MUXCLK(NULL, "mout_mfc1", sclk_evpll_parents, 0,
+			EXYNOS4_CLKSRC_MFC, 4, 1, 0),
+	MUXCLK("s5p-mfc", "mout_mfc", mout_mfc_parents, 0,
+			EXYNOS4_CLKSRC_MFC, 8, 1, 0),
+	MUXCLK("s5p-mipi-csis.0", "mout_csis0", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 24, 4, 0),
+	MUXCLK("s5p-mipi-csis.1", "mout_csis1", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 28, 4, 0),
+	MUXCLK(NULL, "mout_cam0", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 16, 4, 0),
+	MUXCLK(NULL, "mout_cam1", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 20, 4, 0),
+	MUXCLK("exynos4-fimc.0", "mout_fimc0", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 0, 4, 0),
+	MUXCLK("exynos4-fimc.1", "mout_fimc1", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 4, 4, 0),
+	MUXCLK("exynos4-fimc.2", "mout_fimc2", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 8, 4, 0),
+	MUXCLK("exynos4-fimc.3", "mout_fimc3", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 12, 4, 0),
+	MUXCLK("exynos4-fb.0", "mout_fimd0", group1_parents, 0,
+			EXYNOS4_CLKSRC_LCD0, 0, 4, 0),
+	MUXCLK(NULL, "sclk_dac", mout_dac_parents, 0,
+			EXYNOS4_CLKSRC_TV, 8, 1, 0),
+	MUXCLK(NULL, "sclk_hdmi", mout_hdmi_parents, 0,
+			EXYNOS4_CLKSRC_TV, 0, 1, 0),
+	MUXCLK(NULL, "sclk_mixer", mout_mixer_parents, 0,
+			EXYNOS4_CLKSRC_TV, 4, 1, 0),
+};
+
+static struct samsung_div_clock exynos4_div_clks[] = {
+	DIVCLK(NULL, "sclk_apll", "mout_apll", 0,
+			EXYNOS4_CLKDIV_CPU, 24, 3, 0),
+	DIVCLK(NULL, "div_core", "mout_core", 0,
+			EXYNOS4_CLKDIV_CPU, 0, 3, 0),
+	DIVCLK(NULL, "armclk", "div_core", 0,
+			EXYNOS4_CLKDIV_CPU, 28, 3, 0),
+	DIVCLK(NULL, "aclk_200", "mout_aclk_200", 0,
+			EXYNOS4_CLKDIV_TOP, 0, 3, 0),
+	DIVCLK(NULL, "aclk_100", "mout_aclk_100", 0,
+			EXYNOS4_CLKDIV_TOP, 4, 4, 0),
+	DIVCLK(NULL, "aclk_160", "mout_aclk_160", 0,
+			EXYNOS4_CLKDIV_TOP, 8, 3, 0),
+	DIVCLK(NULL, "aclk_133", "mout_aclk_133", 0,
+			EXYNOS4_CLKDIV_TOP, 12, 3, 0),
+	DIVCLK("exynos4210-uart.0", "div_uart0", "mout_uart0", 0,
+			EXYNOS4_CLKDIV_PERIL0, 0, 4, 0),
+	DIVCLK("exynos4210-uart.1", "div_uart1", "mout_uart1", 0,
+			EXYNOS4_CLKDIV_PERIL0, 4, 4, 0),
+	DIVCLK("exynos4210-uart.2", "div_uart2", "mout_uart2", 0,
+			EXYNOS4_CLKDIV_PERIL0, 8, 4, 0),
+	DIVCLK("exynos4210-uart.3", "div_uart3", "mout_uart3", 0,
+			EXYNOS4_CLKDIV_PERIL0, 12, 4, 0),
+	DIVCLK("exynos4-sdhci.0", "div_mmc0", "mout_mmc0", 0,
+			EXYNOS4_CLKDIV_FSYS1, 0, 4, 0),
+	DIVCLK("exynos4-sdhci.0", "div_mmc0_pre", "div_mmc0", 0,
+			EXYNOS4_CLKDIV_FSYS1, 8, 8, 0),
+	DIVCLK("exynos4-sdhci.1", "div_mmc1", "mout_mmc1", 0,
+			EXYNOS4_CLKDIV_FSYS1, 16, 4, 0),
+	DIVCLK("exynos4-sdhci.1", "div_mmc1_pre", "div_mmc1", 0,
+			EXYNOS4_CLKDIV_FSYS1, 24, 8, 0),
+	DIVCLK("exynos4-sdhci.2", "div_mmc2", "mout_mmc2", 0,
+			EXYNOS4_CLKDIV_FSYS2, 0, 4, 0),
+	DIVCLK("exynos4-sdhci.2", "div_mmc2_pre", "div_mmc2", 0,
+			EXYNOS4_CLKDIV_FSYS2, 8, 8, 0),
+	DIVCLK("exynos4-sdhci.3", "div_mmc3", "mout_mmc3", 0,
+			EXYNOS4_CLKDIV_FSYS2, 16, 4, 0),
+	DIVCLK("exynos4-sdhci.3", "div_mmc3_pre", "div_mmc3", 0,
+			EXYNOS4_CLKDIV_FSYS2, 24, 8, 0),
+	DIVCLK("exynos4210-spi.0", "div_spi0", "mout_spi0", 0,
+			EXYNOS4_CLKDIV_PERIL1, 0, 4, 0),
+	DIVCLK("exynos4210-spi.1", "div_spi1", "mout_spi1", 0,
+			EXYNOS4_CLKDIV_PERIL1, 16, 4, 0),
+	DIVCLK("exynos4210-spi.2", "div_spi2", "mout_spi2", 0,
+			EXYNOS4_CLKDIV_PERIL2, 0, 4, 0),
+	DIVCLK("exynos4210-spi.0", "div_spi0_pre", "div_spi0", 0,
+			EXYNOS4_CLKDIV_PERIL1, 8, 8, 0),
+	DIVCLK("exynos4210-spi.1", "div_spi1_pre", "div_spi1", 0,
+			EXYNOS4_CLKDIV_PERIL1, 24, 8, 0),
+	DIVCLK("exynos4210-spi.2", "div_spi2_pre", "div_spi2", 0,
+			EXYNOS4_CLKDIV_PERIL2, 8, 8, 0),
+	DIVCLK(NULL, "div_sata", "mout_sata", 0,
+			EXYNOS4_CLKDIV_FSYS0, 20, 4, 0),
+	DIVCLK("s5p-mfc", "div_mfc", "mout_mfc", 0,
+			EXYNOS4_CLKDIV_MFC, 0, 4, 0),
+	DIVCLK("s5p-mipi-csis.0", "div_csis0", "mout_csis0", 0,
+			EXYNOS4_CLKDIV_CAM, 24, 4, 0),
+	DIVCLK("s5p-mipi-csis.1", "div_csis1", "mout_csis1", 0,
+			EXYNOS4_CLKDIV_CAM, 28, 4, 0),
+	DIVCLK(NULL, "div_cam0", "mout_cam0", 0,
+			EXYNOS4_CLKDIV_CAM, 16, 4, 0),
+	DIVCLK(NULL, "div_cam1", "mout_cam1", 0,
+			EXYNOS4_CLKDIV_CAM, 20, 4, 0),
+	DIVCLK("exynos4-fimc.0", "div_fimc0", "mout_fimc0", 0,
+			EXYNOS4_CLKDIV_CAM, 0, 4, 0),
+	DIVCLK("exynos4-fimc.1", "div_fimc1", "mout_fimc1", 0,
+			EXYNOS4_CLKDIV_CAM, 4, 4, 0),
+	DIVCLK("exynos4-fimc.2", "div_fimc2", "mout_fimc2", 0,
+			EXYNOS4_CLKDIV_CAM, 4, 4, 0),
+	DIVCLK("exynos4-fimc.3", "div_fimc3", "mout_fimc3", 0,
+			EXYNOS4_CLKDIV_CAM, 4, 4, 0),
+	DIVCLK("exynos4-fb.0", "div_fimd0", "mout_fimd0", 0,
+			EXYNOS4_CLKDIV_LCD0, 0, 4, 0),
+	DIVCLK(NULL, "sclk_pixel", "mout_vpll", 0,
+			EXYNOS4_CLKDIV_TV, 0, 4, 0),
+};
+
+struct samsung_gate_clock exynos4_gate_clks[] = {
+	GATECLK("exynos4210-uart.0", "uart0", "aclk_100", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKGATE_IP_PERIL, 0, "uart"),
+	GATECLK("exynos4210-uart.1", "uart1", "aclk_100", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKGATE_IP_PERIL, 1, "uart"),
+	GATECLK("exynos4210-uart.2", "uart2", "aclk_100", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKGATE_IP_PERIL, 2, "uart"),
+	GATECLK("exynos4210-uart.3", "uart3", "aclk_100", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKGATE_IP_PERIL, 3, "uart"),
+	GATECLK("exynos4210-uart.4", "uart4", "aclk_100", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKGATE_IP_PERIL, 4, "uart"),
+	GATECLK("exynos4210-uart.5", "uart5", "aclk_100", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKGATE_IP_PERIL, 5, "uart"),
+	GATECLK("exynos4210-uart.0", "uclk0", "div_uart0", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKSRC_MASK_PERIL0, 0, "clk_uart_baud0"),
+	GATECLK("exynos4210-uart.1", "uclk1", "div_uart1", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKSRC_MASK_PERIL0, 4, "clk_uart_baud0"),
+	GATECLK("exynos4210-uart.2", "uclk2", "div_uart2", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKSRC_MASK_PERIL0, 8, "clk_uart_baud0"),
+	GATECLK("exynos4210-uart.3", "uclk3", "div_uart3", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKSRC_MASK_PERIL0, 12, "clk_uart_baud0"),
+	GATECLK(NULL, "timers", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 24, NULL),
+	GATECLK("s5p-mipi-csis.0", "csis", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 5, NULL),
+	GATECLK(NULL, "jpeg", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 6, NULL),
+	GATECLK("exynos4-fimc.0", "fimc0", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 0, "fimc"),
+	GATECLK("exynos4-fimc.1", "fimc1", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 1, "fimc"),
+	GATECLK("exynos4-fimc.2", "fimc2", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 2, "fimc"),
+	GATECLK("exynos4-fimc.3", "fimc3", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 3, "fimc"),
+	GATECLK("exynos4-sdhci.0", "hsmmc0", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 5, "hsmmc"),
+	GATECLK("exynos4-sdhci.1", "hsmmc1", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 6, "hsmmc"),
+	GATECLK("exynos4-sdhci.2", "hsmmc2", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 7, "hsmmc"),
+	GATECLK("exynos4-sdhci.3", "hsmmc3", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 8, "hsmmc"),
+	GATECLK(NULL, "dwmmc", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 9, NULL),
+	GATECLK("s5p-sdo", "dac", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_TV, 2, NULL),
+	GATECLK("s5p-mixer", "mixer", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_TV, 1, NULL),
+	GATECLK("s5p-mixer", "vp", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_TV, 0, NULL),
+	GATECLK("exynos4-hdmi", "hdmi", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_TV, 3, NULL),
+	GATECLK("exynos4-hdmi", "hdmiphy", "aclk_160", 0,
+			S5P_HDMI_PHY_CONTROL, 0, NULL),
+	GATECLK("s5p-sdo", "dacphy", "aclk_160", 0,
+			S5P_DAC_PHY_CONTROL, 0, NULL),
+	GATECLK(NULL, "adc", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 15, NULL),
+	GATECLK(NULL, "keypad", "aclk_100", 0,
+			EXYNOS4210_CLKGATE_IP_PERIR, 16, NULL),
+	GATECLK(NULL, "rtc", "aclk_100", 0,
+			EXYNOS4210_CLKGATE_IP_PERIR, 15, NULL),
+	GATECLK(NULL, "watchdog", "aclk_100", 0,
+			EXYNOS4210_CLKGATE_IP_PERIR, 14, NULL),
+	GATECLK(NULL, "usbhost", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 12, NULL),
+	GATECLK(NULL, "otg", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 13, NULL),
+	GATECLK("exynos4210-spi.0", "spi0", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 16, "spi"),
+	GATECLK("exynos4210-spi.1", "spi1", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 17, "spi"),
+	GATECLK("exynos4210-spi.2", "spi2", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 18, "spi"),
+	GATECLK("samsung-i2s.0", "iis0", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 19, "iis"),
+	GATECLK("samsung-i2s.1", "iis1", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 20, "iis"),
+	GATECLK("samsung-i2s.2", "iis2", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 21, "iis"),
+	GATECLK("samsung-ac97", "ac97", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 27, NULL),
+	GATECLK("s5p-mfc", "mfc", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_MFC, 0, NULL),
+	GATECLK("s3c2440-i2c.0", "i2c0", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 6, "i2c"),
+	GATECLK("s3c2440-i2c.1", "i2c1", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 7, "i2c"),
+	GATECLK("s3c2440-i2c.2", "i2c2", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 8, "i2c"),
+	GATECLK("s3c2440-i2c.3", "i2c3", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 9, "i2c"),
+	GATECLK("s3c2440-i2c.4", "i2c4", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 10, "i2c"),
+	GATECLK("s3c2440-i2c.5", "i2c5", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 11, "i2c"),
+	GATECLK("s3c2440-i2c.6", "i2c6", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 12, "i2c"),
+	GATECLK("s3c2440-i2c.7", "i2c7", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 13, "i2c"),
+	GATECLK("s3c2440-hdmiphy-i2c", "i2c", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 14, NULL),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(mfc_l, 0), "sysmmu0", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_MFC, 1, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(mfc_r, 1), "sysmmu1", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_MFC, 2, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(tv, 2), "sysmmu2", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_TV, 4, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(jpeg, 3), "sysmmu3", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 11, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(rot, 4), "sysmmu4", "aclk_200", 0,
+			EXYNOS4210_CLKGATE_IP_IMAGE, 4, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(fimc0, 5), "sysmmu5", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 7, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(fimc1, 6), "sysmmu6", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 8, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(fimc2, 7), "sysmmu7", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 9, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(fimc3, 8), "sysmmu8", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 10, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(fimd, 10), "sysmmu10", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_LCD0, 4, "sysmmu"),
+	GATECLK("dma-pl330.0", "dma0", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 0, "dma"),
+	GATECLK("dma-pl330.1", "dma1", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 1, "dma"),
+	GATECLK("exynos4-fb.0", "fimd", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_LCD0, 0, "lcd"),
+	GATECLK("exynos4210-spi.0", "sclk_spi0", "div_spi0_pre", 0,
+			EXYNOS4_CLKSRC_MASK_PERIL1, 16, "spi_busclk0"),
+	GATECLK("exynos4210-spi.1", "sclk_spi1", "div_spi1_pre", 0,
+			EXYNOS4_CLKSRC_MASK_PERIL1, 20, "spi_busclk0"),
+	GATECLK("exynos4210-spi.2", "sclk_spi2", "div_spi2_pre", 0,
+			EXYNOS4_CLKSRC_MASK_PERIL1, 24, "spi_busclk0"),
+	GATECLK("exynos4-sdhci.0", "sclk_mmc0", "div_mmc0_pre", 0,
+			EXYNOS4_CLKSRC_MASK_FSYS, 0, "mmc_busclk.2"),
+	GATECLK("exynos4-sdhci.1", "sclk_mmc1", "div_mmc1_pre", 0,
+			EXYNOS4_CLKSRC_MASK_FSYS, 4, "mmc_busclk.2"),
+	GATECLK("exynos4-sdhci.2", "sclk_mmc2", "div_mmc2_pre", 0,
+			EXYNOS4_CLKSRC_MASK_FSYS, 8, "mmc_busclk.2"),
+	GATECLK("exynos4-sdhci.3", "sclk_mmc3", "div_mmc3_pre", 0,
+			EXYNOS4_CLKSRC_MASK_FSYS, 12, "mmc_busclk.2"),
+	GATECLK("s5p-mipi-csis.0", "sclk_csis0", "div_csis0", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 24, "sclk_csis"),
+	GATECLK("s5p-mipi-csis.1", "sclk_csis1", "div_csis1", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 28, "sclk_csis"),
+	GATECLK(NULL, "sclk_cam0", "div_cam0", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 16, NULL),
+	GATECLK(NULL, "sclk_cam1", "div_cam1", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 20, NULL),
+	GATECLK("exynos4-fimc.0", "sclk_fimc", "div_fimc0", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 0, "sclk_fimc"),
+	GATECLK("exynos4-fimc.1", "sclk_fimc", "div_fimc1", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 4, "sclk_fimc"),
+	GATECLK("exynos4-fimc.2", "sclk_fimc", "div_fimc2", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 8, "sclk_fimc"),
+	GATECLK("exynos4-fimc.3", "sclk_fimc", "div_fimc3", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 12, "sclk_fimc"),
+	GATECLK("exynos4-fb.0", "sclk_fimd", "div_fimd0", 0,
+			EXYNOS4_CLKSRC_MASK_LCD0, 0, "sclk_fimd"),
+};
+
+/* register clock common to all Exynos4 platforms */
+void __init exynos4_clk_init(void)
+{
+	samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
+			ARRAY_SIZE(exynos4_fixed_rate_clks));
+	samsung_clk_register_mux(exynos4_mux_clks,
+			ARRAY_SIZE(exynos4_mux_clks));
+	samsung_clk_register_div(exynos4_div_clks,
+			ARRAY_SIZE(exynos4_div_clks));
+	samsung_clk_register_gate(exynos4_gate_clks,
+			ARRAY_SIZE(exynos4_gate_clks));
+}
+
+/*
+ * Exynos4210 Specific Clocks
+ */
+
+static const char *exynos4210_vpll_parent_names[] __initdata = {
+		"mout_vpll_src" };
+static const char *mout_vpll_src_parents[] __initdata = {
+		"fin_pll", "sclk_hdmi24m" };
+static const char *exynos4210_mout_vpll_parents[] __initdata = {
+		"mout_vpll_src", "fout_vpll", };
+
+/* Exynos4210 specific fixed rate clocks */
+static struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] = {
+	FRATE_CLK(NULL, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
+};
+
+/* Exynos4210 specific mux-type clocks */
+static struct samsung_mux_clock exynos4210_mux_clks[] = {
+	MUXCLK(NULL, "mout_vpll_src", mout_vpll_src_parents, 0,
+			EXYNOS4_CLKSRC_TOP1, 0, 1, 0),
+	MUXCLK(NULL, "mout_vpll", exynos4210_mout_vpll_parents, 0,
+			EXYNOS4_CLKSRC_TOP0, 8, 1, 0),
+	MUXCLK(NULL, "mout_mpll", mout_mpll_parents, 0,
+			EXYNOS4_CLKSRC_CPU, 8, 1, 0),
+};
+
+static unsigned long exynos4210_get_rate_apll(unsigned long xtal_rate)
+{
+	return s5p_get_pll45xx(xtal_rate,
+		__raw_readl(EXYNOS4_APLL_CON0), pll_4508);
+}
+
+static unsigned long exynos4210_get_rate_mpll(unsigned long xtal_rate)
+{
+	return s5p_get_pll45xx(xtal_rate,
+		__raw_readl(EXYNOS4_MPLL_CON0), pll_4508);
+}
+
+static unsigned long exynos4210_get_rate_epll(unsigned long xtal_rate)
+{
+	return s5p_get_pll46xx(xtal_rate, __raw_readl(EXYNOS4_EPLL_CON0),
+		__raw_readl(EXYNOS4_EPLL_CON1), pll_4600);
+}
+
+static unsigned long exynos4210_get_rate_vpll(unsigned long vpllsrc_rate)
+{
+	return s5p_get_pll46xx(vpllsrc_rate, __raw_readl(EXYNOS4_VPLL_CON0),
+		__raw_readl(EXYNOS4_VPLL_CON1), pll_4650c);
+}
+
+static u32 exynos4_vpll_div[][8] = {
+	{  54000000, 3, 53, 3, 1024, 0, 17, 0 },
+	{ 108000000, 3, 53, 2, 1024, 0, 17, 0 },
+};
+
+static int exynos4210_vpll_set_rate(unsigned long rate)
+{
+	unsigned int vpll_con0, vpll_con1 = 0;
+	unsigned int i;
+
+	vpll_con0 = __raw_readl(EXYNOS4_VPLL_CON0);
+	vpll_con0 &= ~(0x1 << 27 |					\
+			PLL90XX_MDIV_MASK << PLL46XX_MDIV_SHIFT |	\
+			PLL90XX_PDIV_MASK << PLL46XX_PDIV_SHIFT |	\
+			PLL90XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
+
+	vpll_con1 = __raw_readl(EXYNOS4_VPLL_CON1);
+	vpll_con1 &= ~(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT |	\
+			PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT |	\
+			PLL4650C_KDIV_MASK << PLL46XX_KDIV_SHIFT);
+
+	for (i = 0; i < ARRAY_SIZE(exynos4_vpll_div); i++) {
+		if (exynos4_vpll_div[i][0] == rate) {
+			vpll_con0 |= exynos4_vpll_div[i][1] << PLL46XX_PDIV_SHIFT;
+			vpll_con0 |= exynos4_vpll_div[i][2] << PLL46XX_MDIV_SHIFT;
+			vpll_con0 |= exynos4_vpll_div[i][3] << PLL46XX_SDIV_SHIFT;
+			vpll_con1 |= exynos4_vpll_div[i][4] << PLL46XX_KDIV_SHIFT;
+			vpll_con1 |= exynos4_vpll_div[i][5] << PLL46XX_MFR_SHIFT;
+			vpll_con1 |= exynos4_vpll_div[i][6] << PLL46XX_MRR_SHIFT;
+			vpll_con0 |= exynos4_vpll_div[i][7] << 27;
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(exynos4_vpll_div)) {
+		pr_err("%s: Invalid Clock VPLL Frequency\n", __func__);
+		return -EINVAL;
+	}
+
+	__raw_writel(vpll_con0, EXYNOS4_VPLL_CON0);
+	__raw_writel(vpll_con1, EXYNOS4_VPLL_CON1);
+
+	/* Wait for VPLL lock */
+	while (!(__raw_readl(EXYNOS4_VPLL_CON0) & (1 << PLL46XX_LOCKED_SHIFT)))
+		continue;
+
+	return 0;
+}
+
+/* Exynos4210 specific clock registration */
+void __init exynos4210_clk_init(void)
+{
+	group1_parents[4] = "sclk_usbphy1";
+
+	exynos4_clk_init();
+
+	samsung_clk_register_pll("fout_apll", pll_parent_names,
+		NULL, exynos4210_get_rate_apll);
+	samsung_clk_register_pll("fout_mpll", pll_parent_names,
+		NULL, exynos4210_get_rate_mpll);
+	samsung_clk_register_pll("fout_epll", pll_parent_names,
+		NULL, exynos4210_get_rate_epll);
+	samsung_clk_register_pll("fout_vpll", exynos4210_vpll_parent_names,
+		exynos4210_vpll_set_rate, exynos4210_get_rate_vpll);
+
+	samsung_clk_register_fixed_rate(exynos4210_fixed_rate_clks,
+			ARRAY_SIZE(exynos4210_fixed_rate_clks));
+	samsung_clk_register_mux(exynos4210_mux_clks,
+			ARRAY_SIZE(exynos4210_mux_clks));
+
+	pr_info("EXYNOS4210: PLL settings: A=%ld, M=%ld, E=%ld, V=%ld\n",
+		_get_rate("fout_apll"), _get_rate("fout_mpll"),
+		_get_rate("fout_epll"), _get_rate("fout_vpll"));
+
+	pr_info("EXYNOS4210: ARMCLK=%ld, ACLK200=%ld, ACLK100=%ld\n"
+		"         ACLK160=%ld, ACLK133=%ld\n", _get_rate("armclk"),
+		_get_rate("aclk_200"), _get_rate("aclk_100"),
+		_get_rate("aclk_160"), _get_rate("aclk_133"));
+}
+
+/*
+ * Exynos4212 Specific Clocks
+ */
+
+static const char *exynos4212_mout_vpll_parents[] __initdata = {
+		"fin_pll", "fout_vpll", };
+
+/* Exynos4212 specific mux clocks */
+static struct samsung_mux_clock exynos4212_mux_clks[] = {
+	MUXCLK(NULL, "mout_mpll", mout_mpll_parents, 0,
+			EXYNOS4_CLKSRC_DMC, 12, 1, 0),
+	MUXCLK(NULL, "mout_vpll", exynos4212_mout_vpll_parents, 0,
+			EXYNOS4_CLKSRC_TOP0, 8, 1, 0),
+};
+
+static unsigned long exynos4212_get_rate_apll(unsigned long xtal_rate)
+{
+	return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_APLL_CON0));
+}
+
+static unsigned long exynos4212_get_rate_mpll(unsigned long xtal_rate)
+{
+	return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_MPLL_CON0));
+}
+
+static unsigned long exynos4212_get_rate_epll(unsigned long xtal_rate)
+{
+	return s5p_get_pll36xx(xtal_rate, __raw_readl(EXYNOS4_EPLL_CON0),
+		__raw_readl(EXYNOS4_EPLL_CON1));
+}
+
+static unsigned long exynos4212_get_rate_vpll(unsigned long vpllsrc_rate)
+{
+	return s5p_get_pll36xx(vpllsrc_rate, __raw_readl(EXYNOS4_VPLL_CON0),
+		__raw_readl(EXYNOS4_VPLL_CON1));
+}
+
+/* Exynos4212 specific clock registeration */
+void __init exynos4212_clk_init(void)
+{
+	exynos4_clk_init();
+
+	samsung_clk_register_pll("fout_apll", pll_parent_names,
+		NULL, exynos4212_get_rate_apll);
+	samsung_clk_register_pll("fout_mpll", pll_parent_names,
+		NULL, exynos4212_get_rate_mpll);
+	samsung_clk_register_pll("fout_epll", pll_parent_names,
+		NULL, exynos4212_get_rate_epll);
+	samsung_clk_register_pll("fout_vpll", pll_parent_names,
+		NULL, exynos4212_get_rate_vpll);
+
+	samsung_clk_register_mux(exynos4212_mux_clks,
+			ARRAY_SIZE(exynos4212_mux_clks));
+
+	pr_info("EXYNOS4210: PLL settings: A=%ld, M=%ld, E=%ld, V=%ld\n",
+		_get_rate("fout_apll"), _get_rate("fout_mpll"),
+		_get_rate("fout_epll"), _get_rate("fout_vpll"));
+
+	pr_info("EXYNOS4210: ARMCLK=%ld, ACLK200=%ld, ACLK100=%ld\n"
+		"         ACLK160=%ld, ACLK133=%ld\n", _get_rate("armclk"),
+		_get_rate("aclk_200"), _get_rate("aclk_100"),
+		_get_rate("aclk_160"), _get_rate("aclk_133"));
+}
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
new file mode 100644
index 0000000..65156b9
--- /dev/null
+++ b/drivers/clk/samsung/clk.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2012 Linaro 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.
+ *
+ * This file includes utility functions to register clocks to common
+ * clock framework for Samsung platforms. This includes an implementation
+ * of Samsung 'pll type' clock to represent the implementation of the
+ * pll found on Samsung platforms. In addition to that, utility functions
+ * to register mux, div, gate and fixed rate types of clocks are included.
+*/
+
+#include "clk.h"
+
+static DEFINE_SPINLOCK(lock);
+
+#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
+
+/* determine the output clock speed of the pll */
+static unsigned long samsung_clk_pll_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct samsung_clk_pll *clk_pll = to_clk_pll(hw);
+
+	if (clk_pll->get_rate)
+		return to_clk_pll(hw)->get_rate(parent_rate);
+
+	return 0;
+}
+
+/* round operation not supported */
+static long samsung_clk_pll_round_rate(struct clk_hw *hw, unsigned long drate,
+				unsigned long *prate)
+{
+	return samsung_clk_pll_recalc_rate(hw, *prate);
+}
+
+/* set the clock output rate of the pll */
+static int samsung_clk_pll_set_rate(struct clk_hw *hw, unsigned long drate,
+				unsigned long prate)
+{
+	struct samsung_clk_pll *clk_pll = to_clk_pll(hw);
+
+	if (clk_pll->set_rate)
+		return to_clk_pll(hw)->set_rate(drate);
+
+	return 0;
+}
+
+/* clock operations for samsung pll clock type */
+static const struct clk_ops samsung_clk_pll_ops = {
+	.recalc_rate = samsung_clk_pll_recalc_rate,
+	.round_rate = samsung_clk_pll_round_rate,
+	.set_rate = samsung_clk_pll_set_rate,
+};
+
+/* register a samsung pll type clock */
+void __init samsung_clk_register_pll(const char *name, const char **pnames,
+				int (*set_rate)(unsigned long rate),
+				unsigned long (*get_rate)(unsigned long rate))
+{
+	struct samsung_clk_pll *clk_pll;
+	struct clk *clk;
+	struct clk_init_data init;
+	int ret;
+
+	clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
+	if (!clk_pll) {
+		pr_err("%s: could not allocate pll clk %s\n", __func__, name);
+		return;
+	}
+
+	init.name = name;
+	init.ops = &samsung_clk_pll_ops;
+	init.flags = CLK_GET_RATE_NOCACHE;
+	init.parent_names = pnames;
+	init.num_parents = 1;
+
+	clk_pll->set_rate = set_rate;
+	clk_pll->get_rate = get_rate;
+	clk_pll->hw.init = &init;
+
+	/* register the clock */
+	clk = clk_register(NULL, &clk_pll->hw);
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed to register pll clock %s\n", __func__,
+				name);
+		kfree(clk_pll);
+		return;
+	}
+
+	ret = clk_register_clkdev(clk, name, NULL);
+	if (ret)
+		pr_err("%s: failed to register clock lookup for %s", __func__,
+				name);
+}
+
+/* register a list of fixed clocks */
+void __init samsung_clk_register_fixed_rate(
+		struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk)
+{
+	struct clk *clk;
+	unsigned int idx, ret;
+
+	for (idx = 0; idx < nr_clk; idx++, clk_list++) {
+		clk = clk_register_fixed_rate(NULL, clk_list->name,
+				clk_list->parent_name, clk_list->flags,
+				clk_list->fixed_rate);
+		if (IS_ERR_OR_NULL(clk)) {
+			pr_err("clock: failed to register clock %s\n",
+				clk_list->name);
+			continue;
+		}
+
+		ret = clk_register_clkdev(clk, clk_list->name,
+						clk_list->dev_name);
+		if (ret)
+			pr_err("clock: failed to register clock lookup for %s",
+				clk_list->name);
+	}
+}
+
+/* register a list of mux clocks */
+void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
+						unsigned int nr_clk)
+{
+	struct clk *clk;
+	unsigned int idx, ret;
+
+	for (idx = 0; idx < nr_clk; idx++, clk_list++) {
+		clk = clk_register_mux(NULL, clk_list->name,
+			clk_list->parent_names, clk_list->num_parents,
+			clk_list->flags, clk_list->reg, clk_list->shift,
+			clk_list->width, clk_list->mux_flags, &lock);
+		if (IS_ERR_OR_NULL(clk)) {
+			pr_err("clock: failed to register clock %s\n",
+				clk_list->name);
+			continue;
+		}
+
+		ret = clk_register_clkdev(clk, clk_list->name,
+						clk_list->dev_name);
+		if (ret)
+			pr_err("clock: failed to register clock lookup for %s",
+				clk_list->name);
+
+		if (clk_list->alias)
+			clk_register_clkdev(clk, clk_list->alias,
+						clk_list->dev_name);
+	}
+}
+
+/* reguster a list of div clocks */
+void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
+						unsigned int nr_clk)
+{
+	struct clk *clk;
+	unsigned int idx, ret;
+
+	for (idx = 0; idx < nr_clk; idx++, clk_list++) {
+		clk = clk_register_divider(NULL, clk_list->name,
+			clk_list->parent_name, clk_list->flags, clk_list->reg,
+			clk_list->shift, clk_list->width, clk_list->div_flags,
+			&lock);
+		if (IS_ERR_OR_NULL(clk)) {
+			pr_err("clock: failed to register clock %s\n",
+				clk_list->name);
+			continue;
+		}
+
+		ret = clk_register_clkdev(clk, clk_list->name,
+						clk_list->dev_name);
+		if (ret)
+			pr_err("clock: failed to register clock lookup for %s",
+				clk_list->name);
+
+		if (clk_list->alias)
+			clk_register_clkdev(clk, clk_list->alias,
+						clk_list->dev_name);
+	}
+}
+
+/* register a list of gate clocks */
+void __init samsung_clk_register_gate(struct samsung_gate_clock *clk_list,
+						unsigned int nr_clk)
+{
+	struct clk *clk;
+	unsigned int idx, ret;
+
+	for (idx = 0; idx < nr_clk; idx++, clk_list++) {
+		clk = clk_register_gate(NULL, clk_list->name,
+			clk_list->parent_name, clk_list->flags, clk_list->reg,
+			clk_list->bit_idx, clk_list->gate_flags, &lock);
+		if (IS_ERR_OR_NULL(clk)) {
+			pr_err("clock: failed to register clock %s\n",
+				clk_list->name);
+			continue;
+		}
+
+		ret = clk_register_clkdev(clk, clk_list->name,
+						clk_list->dev_name);
+		if (ret) {
+			pr_err("clock: failed to register clock lookup for %s",
+				clk_list->name);
+			continue;
+		}
+
+		ret = clk_register_clkdev(clk, clk_list->alias,
+						clk_list->dev_name);
+		if (ret)
+			pr_err("clock: failed to register alias %s for clock "
+					" %s", clk_list->alias, clk_list->name);
+	}
+}
+
+/* utility function to get the rate of a specified clock */
+unsigned long _get_rate(const char *clk_name)
+{
+	struct clk *clk;
+	unsigned long rate;
+
+	clk = clk_get(NULL, clk_name);
+	if (IS_ERR(clk))
+		return 0;
+	rate = clk_get_rate(clk);
+	clk_put(clk);
+	return rate;
+}
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
new file mode 100644
index 0000000..40bdff9
--- /dev/null
+++ b/drivers/clk/samsung/clk.h
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2012 Linaro 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.
+ *
+ * Common Clock Framework support for all Samsung platforms
+*/
+
+#ifndef __SAMSUNG_CLK_H
+#define __SAMSUNG_CLK_H
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+#include <mach/regs-clock.h>
+
+/**
+ * struct samsung_clk_pll: represents a samsung pll type clock
+ * @hw: connection to struct clk.
+ * @set_rate: callback for setting the pll clock rate
+ * @get_rate: callback for determing the pll clock rate
+ *
+ * Internal representation of the pll type clock. Platform specific
+ * implementation can instantiate clocks of this type by calling
+ * samsung_clk_register_pll() function.
+ */
+struct samsung_clk_pll {
+	struct clk_hw		hw;
+	int			(*set_rate)(unsigned long rate);
+	unsigned long		(*get_rate)(unsigned long xtal_rate);
+};
+
+/**
+ * struct samsung_fixed_rate_clock: information about fixed-rate clock
+ * @dev_name: name of the device to which this clock belongs.
+ * @name: name of this fixed-rate clock.
+ * @parent_name: optional parent clock name.
+ * @flags: optional fixed-rate clock flags.
+ * @fixed-rate: fixed clock rate of this clock.
+ */
+struct samsung_fixed_rate_clock {
+	const char		*dev_name;
+	const char		*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	unsigned long		fixed_rate;
+};
+
+#define FRATE_CLK(dname, cname, pname, f, frate)	\
+	{						\
+		.dev_name	= dname,		\
+		.name		= cname,		\
+		.parent_name	= pname,		\
+		.flags		= f,			\
+		.fixed_rate	= frate,		\
+	}
+
+/**
+ * struct samsung_mux_clock: information about mux clock
+ * @dev_name: name of the device to which this clock belongs.
+ * @name: name of this mux clock.
+ * @parent_names: array of pointer to parent clock names.
+ * @num_parents: number of parents listed in @parent_names.
+ * @flags: optional flags for basic clock.
+ * @reg: address of register for configuring the mux.
+ * @shift: starting bit location of the mux control bit-field in @reg.
+ * @width: width of the mux control bit-field in @reg.
+ * @mux_flags: flags for mux-type clock.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_mux_clock {
+	const char		*dev_name;
+	const char		*name;
+	const char		**parent_names;
+	u8			num_parents;
+	unsigned long		flags;
+	void __iomem		*reg;
+	u8			shift;
+	u8			width;
+	u8			mux_flags;
+	const char		*alias;
+};
+
+#define MUXCLK(dname, cname, pnames, f, r, s, w, mf)		\
+	{							\
+		.dev_name	= dname,			\
+		.name		= cname,			\
+		.parent_names	= pnames,			\
+		.num_parents	= ARRAY_SIZE(pnames),		\
+		.flags		= f,				\
+		.reg		= r,				\
+		.shift		= s,				\
+		.width		= w,				\
+		.mux_flags	= mf,				\
+	}
+
+/**
+ * struct samsung_div_clock: information about div clock
+ * @dev_name: name of the device to which this clock belongs.
+ * @name: name of this div clock.
+ * @parent_name: name of the parent clock.
+ * @flags: optional flags for basic clock.
+ * @reg: address of register for configuring the div.
+ * @shift: starting bit location of the div control bit-field in @reg.
+ * @div_flags: flags for div-type clock.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_div_clock {
+	const char		*dev_name;
+	const char		*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	void __iomem		*reg;
+	u8			shift;
+	u8			width;
+	u8			div_flags;
+	const char		*alias;
+};
+
+#define DIVCLK(dname, cname, pname, f, r, s, w, df)		\
+	{							\
+		.dev_name	= dname,			\
+		.name		= cname,			\
+		.parent_name	= pname,			\
+		.flags		= f,				\
+		.reg		= r,				\
+		.shift		= s,				\
+		.width		= w,				\
+		.div_flags	= df,				\
+	}
+
+/**
+ * struct samsung_gate_clock: information about gate clock
+ * @dev_name: name of the device to which this clock belongs.
+ * @name: name of this gate clock.
+ * @parent_name: name of the parent clock.
+ * @flags: optional flags for basic clock.
+ * @reg: address of register for configuring the gate.
+ * @bit_idx: bit index of the gate control bit-field in @reg.
+ * @gate_flags: flags for gate-type clock.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_gate_clock {
+	const char		*dev_name;
+	const char		*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	void __iomem		*reg;
+	u8			bit_idx;
+	u8			gate_flags;
+	const char		*alias;
+};
+
+#define GATECLK(dname, cname, pname, f, r, b, a)		\
+	{							\
+		.dev_name	= dname,			\
+		.name		= cname,			\
+		.parent_name	= pname,			\
+		.flags		= f,				\
+		.reg		= r,				\
+		.bit_idx	= b,				\
+		.alias		= a,				\
+	}
+
+extern void __init samsung_clk_register_pll(const char *name,
+		const char **parent_names,
+		int (*set_rate)(unsigned long rate),
+		unsigned long (*get_rate)(unsigned long rate));
+
+extern void __init samsung_clk_register_fixed_rate(
+		struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk);
+
+extern void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
+		unsigned int nr_clk);
+
+extern void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
+		unsigned int nr_clk);
+
+extern void __init samsung_clk_register_gate(
+		struct samsung_gate_clock *clk_list, unsigned int nr_clk);
+
+extern unsigned long samsung_get_rate_xtal(void);
+
+extern unsigned long _get_rate(const char *clk_name);
+
+#endif /* __SAMSUNG_CLK_H */
-- 
1.7.1

^ permalink raw reply related

* [PATCH v6 0/5] watchdog: orion_wdt & at91sam9_wdt: improve dt support
From: Fabio Porcedda @ 2012-10-01 12:24 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

This set of patches is for adding device tree support to the
at91sam9_wdt driver and to add the new timeout property to
the watchdog core.

I've tested the at91sam9_wdt modifications on an at91sam9260 board (evk-pro3).

Changes:
v6:
 - add watchdog core proprty timeout binding
 - add as example to the orion_wdt driver the new timeout binding
v5:
 - split dts commit in two, one for socs and one for boards.
v4:
 - use "atmel,at91sam9260-wdt" as compatible
v3:
 - add heartbeat option
 - default disabled for all the soc, enable only for evk-pro3 board
 - add at91sam9263 and at91sam9g45 soc
v2:
 - add missing to and cc addresses



Fabio Porcedda (5):
  watchdog: core: dt: add support for the timeout device tree property
  watchdog: orion_wdt: dt: add the timeout property binding
  watchdog: at91sam9_wdt: add device tree support
  ARM: at91/dts: add at91sam9_wdt driver to at91sam926x, at91sam9g45
  ARM: at91/dts: evk-pro3: enable watchdog

 .../devicetree/bindings/watchdog/atmel-wdt.txt      | 19 +++++++++++++++++++
 .../devicetree/bindings/watchdog/marvel.txt         |  5 +++++
 Documentation/watchdog/watchdog-kernel-api.txt      |  3 +++
 arch/arm/boot/dts/at91sam9260.dtsi                  |  6 ++++++
 arch/arm/boot/dts/at91sam9263.dtsi                  |  6 ++++++
 arch/arm/boot/dts/at91sam9g45.dtsi                  |  6 ++++++
 arch/arm/boot/dts/evk-pro3.dts                      |  4 ++++
 drivers/watchdog/at91sam9_wdt.c                     | 21 +++++++++++++++++++++
 drivers/watchdog/orion_wdt.c                        |  2 +-
 include/linux/watchdog.h                            | 11 +++++++++++
 10 files changed, 82 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/watchdog/atmel-wdt.txt

-- 
1.7.11.3

^ permalink raw reply

* [PATCH v6 1/5] watchdog: core: dt: add support for the timeout device tree property
From: Fabio Porcedda @ 2012-10-01 12:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349094281-28889-1-git-send-email-fabio.porcedda@gmail.com>

Signed-off-by: Fabio Porcedda <fabio.porcedda@gmail.com>
---
 Documentation/watchdog/watchdog-kernel-api.txt |  3 +++
 include/linux/watchdog.h                       | 11 +++++++++++
 2 files changed, 14 insertions(+)

diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
index 086638f..decd981 100644
--- a/Documentation/watchdog/watchdog-kernel-api.txt
+++ b/Documentation/watchdog/watchdog-kernel-api.txt
@@ -212,3 +212,6 @@ driver specific data to and a pointer to the data itself.
 The watchdog_get_drvdata function allows you to retrieve driver specific data.
 The argument of this function is the watchdog device where you want to retrieve
 data from. The function returns the pointer to the driver specific data.
+
+The watchdog_probe_dt function allows you to retrieve the timeout property
+from the device tree.
diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
index da70f0f..06f9384 100644
--- a/include/linux/watchdog.h
+++ b/include/linux/watchdog.h
@@ -11,6 +11,7 @@
 
 #include <linux/ioctl.h>
 #include <linux/types.h>
+#include <linux/of.h>
 
 #define	WATCHDOG_IOCTL_BASE	'W'
 
@@ -174,6 +175,16 @@ static inline void *watchdog_get_drvdata(struct watchdog_device *wdd)
 	return wdd->driver_data;
 }
 
+/* Use the following function to retrieve the timeout property from dt */
+static inline void watchdog_probe_dt(struct watchdog_device *wdd,
+				     struct device_node *node)
+{
+	if (!node)
+		return;
+
+	of_property_read_u32(node, "timeout", &wdd->timeout);
+}
+
 /* drivers/watchdog/core/watchdog_core.c */
 extern int watchdog_register_device(struct watchdog_device *);
 extern void watchdog_unregister_device(struct watchdog_device *);
-- 
1.7.11.3

^ permalink raw reply related

* [PATCH v6 2/5] watchdog: orion_wdt: dt: add the timeout property binding
From: Fabio Porcedda @ 2012-10-01 12:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349094281-28889-1-git-send-email-fabio.porcedda@gmail.com>

The binding is provided by the watchdog core.

Signed-off-by: Fabio Porcedda <fabio.porcedda@gmail.com>
---
 Documentation/devicetree/bindings/watchdog/marvel.txt | 5 +++++
 drivers/watchdog/orion_wdt.c                          | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/watchdog/marvel.txt b/Documentation/devicetree/bindings/watchdog/marvel.txt
index 0b2503a..66c2b8c 100644
--- a/Documentation/devicetree/bindings/watchdog/marvel.txt
+++ b/Documentation/devicetree/bindings/watchdog/marvel.txt
@@ -5,10 +5,15 @@ Required Properties:
 - Compatibility : "marvell,orion-wdt"
 - reg		: Address of the timer registers
 
+Optional properties:
+
+- timeout	: Contains the watchdog timeout in seconds
+
 Example:
 
 	wdt at 20300 {
 		compatible = "marvell,orion-wdt";
 		reg = <0x20300 0x28>;
+		timeout = <10>;
 		status = "okay";
 	};
diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index c20f96b..3dc7481 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -24,7 +24,6 @@
 #include <linux/spinlock.h>
 #include <linux/clk.h>
 #include <linux/err.h>
-#include <linux/of.h>
 #include <mach/bridge-regs.h>
 
 /*
@@ -168,6 +167,7 @@ static int __devinit orion_wdt_probe(struct platform_device *pdev)
 	orion_wdt.timeout = heartbeat;
 	orion_wdt.min_timeout = 1;
 	orion_wdt.max_timeout = wdt_max_duration;
+	watchdog_probe_dt(&orion_wdt, pdev->dev.of_node);
 
 	watchdog_set_nowayout(&orion_wdt, nowayout);
 	ret = watchdog_register_device(&orion_wdt);
-- 
1.7.11.3

^ permalink raw reply related

* [PATCH v6 3/5] watchdog: at91sam9_wdt: add device tree support
From: Fabio Porcedda @ 2012-10-01 12:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349094281-28889-1-git-send-email-fabio.porcedda@gmail.com>

Tested on an at91sam9260 board (evk-pro3)

Signed-off-by: Fabio Porcedda <fabio.porcedda@gmail.com>
---
 .../devicetree/bindings/watchdog/atmel-wdt.txt      | 19 +++++++++++++++++++
 drivers/watchdog/at91sam9_wdt.c                     | 21 +++++++++++++++++++++
 2 files changed, 40 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/atmel-wdt.txt

diff --git a/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt b/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt
new file mode 100644
index 0000000..65c1755
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/atmel-wdt.txt
@@ -0,0 +1,19 @@
+* Atmel Watchdog Timers
+
+** at91sam9-wdt
+
+Required properties:
+- compatible: must be "atmel,at91sam9260-wdt".
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+Optional properties:
+- timeout: contains the watchdog timeout in seconds.
+
+Example:
+
+	watchdog at fffffd40 {
+		compatible = "atmel,at91sam9260-wdt";
+		reg = <0xfffffd40 0x10>;
+		timeout = <10>;
+	};
diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c
index 05e1be8..c9e6bfa 100644
--- a/drivers/watchdog/at91sam9_wdt.c
+++ b/drivers/watchdog/at91sam9_wdt.c
@@ -32,6 +32,7 @@
 #include <linux/timer.h>
 #include <linux/bitops.h>
 #include <linux/uaccess.h>
+#include <linux/of.h>
 
 #include "at91sam9_wdt.h"
 
@@ -254,6 +255,14 @@ static struct miscdevice at91wdt_miscdev = {
 	.fops		= &at91wdt_fops,
 };
 
+static inline void __init at91wdt_probe_dt(struct device_node *node)
+{
+	if (!node)
+		return;
+
+	of_property_read_u32(node, "timeout", &heartbeat);
+}
+
 static int __init at91wdt_probe(struct platform_device *pdev)
 {
 	struct resource	*r;
@@ -272,6 +281,8 @@ static int __init at91wdt_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
+	at91wdt_probe_dt(pdev->dev.of_node);
+
 	/* Set watchdog */
 	res = at91_wdt_settimeout(ms_to_ticks(WDT_HW_TIMEOUT * 1000));
 	if (res)
@@ -302,11 +313,21 @@ static int __exit at91wdt_remove(struct platform_device *pdev)
 	return res;
 }
 
+#if defined(CONFIG_OF)
+static const struct of_device_id at91_wdt_dt_ids[] = {
+	{ .compatible = "atmel,at91sam9260-wdt" },
+	{ /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, at91_wdt_dt_ids);
+#endif
+
 static struct platform_driver at91wdt_driver = {
 	.remove		= __exit_p(at91wdt_remove),
 	.driver		= {
 		.name	= "at91_wdt",
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(at91_wdt_dt_ids),
 	},
 };
 
-- 
1.7.11.3

^ permalink raw reply related

* [PATCH v6 4/5] ARM: at91/dts: add at91sam9_wdt driver to at91sam926x, at91sam9g45
From: Fabio Porcedda @ 2012-10-01 12:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349094281-28889-1-git-send-email-fabio.porcedda@gmail.com>

Tested on an at91sam9260 board (evk-pro3).

Signed-off-by: Fabio Porcedda <fabio.porcedda@gmail.com>
---
 arch/arm/boot/dts/at91sam9260.dtsi | 6 ++++++
 arch/arm/boot/dts/at91sam9263.dtsi | 6 ++++++
 arch/arm/boot/dts/at91sam9g45.dtsi | 6 ++++++
 3 files changed, 18 insertions(+)

diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
index 7c95f76..7612193 100644
--- a/arch/arm/boot/dts/at91sam9260.dtsi
+++ b/arch/arm/boot/dts/at91sam9260.dtsi
@@ -236,6 +236,12 @@
 					trigger-external;
 				};
 			};
+
+			watchdog at fffffd40 {
+				compatible = "atmel,at91sam9260-wdt";
+				reg = <0xfffffd40 0x10>;
+				status = "disabled";
+			};
 		};
 
 		nand0: nand at 40000000 {
diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi
index 195019b..d822240 100644
--- a/arch/arm/boot/dts/at91sam9263.dtsi
+++ b/arch/arm/boot/dts/at91sam9263.dtsi
@@ -185,6 +185,12 @@
 				interrupts = <24 4 2>;
 				status = "disabled";
 			};
+
+			watchdog at fffffd40 {
+				compatible = "atmel,at91sam9260-wdt";
+				reg = <0xfffffd40 0x10>;
+				status = "disabled";
+			};
 		};
 
 		nand0: nand at 40000000 {
diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
index 63751b1..df998ab 100644
--- a/arch/arm/boot/dts/at91sam9g45.dtsi
+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
@@ -242,6 +242,12 @@
 					trigger-value = <0x6>;
 				};
 			};
+
+			watchdog at fffffd40 {
+				compatible = "atmel,at91sam9260-wdt";
+				reg = <0xfffffd40 0x10>;
+				status = "disabled";
+			};
 		};
 
 		nand0: nand at 40000000 {
-- 
1.7.11.3

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox