summaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
authorVitaly Wool <vitalywool@gmail.com>2006-12-10 21:21:29 +0100
committerJean Delvare <khali@arrakis.delvare>2006-12-10 21:21:29 +0100
commit41561f28e76a47dc6de0a954da85d0b5c42874eb (patch)
tree0113700403e5fffb57ee41b564ea68bcaab311d9 /arch/arm
parent51fd554b6547b74c7e6d1f52885ba8532b531023 (diff)
i2c: New Philips PNX bus driver
New I2C bus driver for Philips ARM boards (Philips IP3204 I2C IP block). This I2C controller can be found on (at least) PNX010x, PNX52xx and PNX4008 Philips boards. Signed-off-by: Vitaly Wool <vitalywool@gmail.com> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-pnx4008/Makefile2
-rw-r--r--arch/arm/mach-pnx4008/i2c.c167
2 files changed, 168 insertions, 1 deletions
diff --git a/arch/arm/mach-pnx4008/Makefile b/arch/arm/mach-pnx4008/Makefile
index b457ca0a431a..777564c90a12 100644
--- a/arch/arm/mach-pnx4008/Makefile
+++ b/arch/arm/mach-pnx4008/Makefile
@@ -2,7 +2,7 @@
# Makefile for the linux kernel.
#
-obj-y := core.o irq.o time.o clock.o gpio.o serial.o dma.o
+obj-y := core.o irq.o time.o clock.o gpio.o serial.o dma.o i2c.o
obj-m :=
obj-n :=
obj- :=
diff --git a/arch/arm/mach-pnx4008/i2c.c b/arch/arm/mach-pnx4008/i2c.c
new file mode 100644
index 000000000000..6f308827c4fe
--- /dev/null
+++ b/arch/arm/mach-pnx4008/i2c.c
@@ -0,0 +1,167 @@
+/*
+ * I2C initialization for PNX4008.
+ *
+ * Author: Vitaly Wool <vitalywool@gmail.com>
+ *
+ * 2005-2006 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/i2c-pnx.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <asm/arch/platform.h>
+#include <asm/arch/i2c.h>
+
+static int set_clock_run(struct platform_device *pdev)
+{
+ struct clk *clk;
+ char name[10];
+ int retval = 0;
+
+ snprintf(name, 10, "i2c%d_ck", pdev->id);
+ clk = clk_get(&pdev->dev, name);
+ if (!IS_ERR(clk)) {
+ clk_set_rate(clk, 1);
+ clk_put(clk);
+ } else
+ retval = -ENOENT;
+
+ return retval;
+}
+
+static int set_clock_stop(struct platform_device *pdev)
+{
+ struct clk *clk;
+ char name[10];
+ int retval = 0;
+
+ snprintf(name, 10, "i2c%d_ck", pdev->id);
+ clk = clk_get(&pdev->dev, name);
+ if (!IS_ERR(clk)) {
+ clk_set_rate(clk, 0);
+ clk_put(clk);
+ } else
+ retval = -ENOENT;
+
+ return retval;
+}
+
+static int i2c_pnx_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ int retval = 0;
+#ifdef CONFIG_PM
+ retval = set_clock_run(pdev);
+#endif
+ return retval;
+}
+
+static int i2c_pnx_resume(struct platform_device *pdev)
+{
+ int retval = 0;
+#ifdef CONFIG_PM
+ retval = set_clock_run(pdev);
+#endif
+ return retval;
+}
+
+static u32 calculate_input_freq(struct platform_device *pdev)
+{
+ return HCLK_MHZ;
+}
+
+
+static struct i2c_pnx_algo_data pnx_algo_data0 = {
+ .base = PNX4008_I2C1_BASE,
+ .irq = I2C_1_INT,
+};
+
+static struct i2c_pnx_algo_data pnx_algo_data1 = {
+ .base = PNX4008_I2C2_BASE,
+ .irq = I2C_2_INT,
+};
+
+static struct i2c_pnx_algo_data pnx_algo_data2 = {
+ .base = (PNX4008_USB_CONFIG_BASE + 0x300),
+ .irq = USB_I2C_INT,
+};
+
+static struct i2c_adapter pnx_adapter0 = {
+ .name = I2C_CHIP_NAME "0",
+ .algo_data = &pnx_algo_data0,
+};
+static struct i2c_adapter pnx_adapter1 = {
+ .name = I2C_CHIP_NAME "1",
+ .algo_data = &pnx_algo_data1,
+};
+
+static struct i2c_adapter pnx_adapter2 = {
+ .name = "USB-I2C",
+ .algo_data = &pnx_algo_data2,
+};
+
+static struct i2c_pnx_data i2c0_data = {
+ .suspend = i2c_pnx_suspend,
+ .resume = i2c_pnx_resume,
+ .calculate_input_freq = calculate_input_freq,
+ .set_clock_run = set_clock_run,
+ .set_clock_stop = set_clock_stop,
+ .adapter = &pnx_adapter0,
+};
+
+static struct i2c_pnx_data i2c1_data = {
+ .suspend = i2c_pnx_suspend,
+ .resume = i2c_pnx_resume,
+ .calculate_input_freq = calculate_input_freq,
+ .set_clock_run = set_clock_run,
+ .set_clock_stop = set_clock_stop,
+ .adapter = &pnx_adapter1,
+};
+
+static struct i2c_pnx_data i2c2_data = {
+ .suspend = i2c_pnx_suspend,
+ .resume = i2c_pnx_resume,
+ .calculate_input_freq = calculate_input_freq,
+ .set_clock_run = set_clock_run,
+ .set_clock_stop = set_clock_stop,
+ .adapter = &pnx_adapter2,
+};
+
+static struct platform_device i2c0_device = {
+ .name = "pnx-i2c",
+ .id = 0,
+ .dev = {
+ .platform_data = &i2c0_data,
+ },
+};
+
+static struct platform_device i2c1_device = {
+ .name = "pnx-i2c",
+ .id = 1,
+ .dev = {
+ .platform_data = &i2c1_data,
+ },
+};
+
+static struct platform_device i2c2_device = {
+ .name = "pnx-i2c",
+ .id = 2,
+ .dev = {
+ .platform_data = &i2c2_data,
+ },
+};
+
+static struct platform_device *devices[] __initdata = {
+ &i2c0_device,
+ &i2c1_device,
+ &i2c2_device,
+};
+
+void __init pnx4008_register_i2c_devices(void)
+{
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+}