aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk@arm.linux.org.uk>2006-12-10 15:21:32 -0500
committerJean Delvare <khali@arrakis.delvare>2006-12-10 15:21:32 -0500
commit6b65cd742823f78a6538491982159098ab5fcae1 (patch)
tree1ab913871887b73418583da527716df9da692419
parent763d9c046a2e511ec090a8986d3f85edf7448e7e (diff)
i2c: New ARM Versatile/Realview bus driver
Add support for the I2C bus found on the ARM Versatile and Realview platforms. The I2C bus has a RTC and optionally some EEPROMs attached. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Signed-off-by: Jean Delvare <khali@linux-fr.org>
-rw-r--r--arch/arm/mach-realview/core.c13
-rw-r--r--arch/arm/mach-realview/core.h1
-rw-r--r--arch/arm/mach-realview/realview_eb.c1
-rw-r--r--arch/arm/mach-versatile/core.c14
-rw-r--r--drivers/i2c/busses/Kconfig11
-rw-r--r--drivers/i2c/busses/Makefile1
-rw-r--r--drivers/i2c/busses/i2c-versatile.c153
7 files changed, 194 insertions, 0 deletions
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 68c67053f479..84d3fe76e94e 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -141,6 +141,19 @@ struct platform_device realview_smc91x_device = {
141 .resource = realview_smc91x_resources, 141 .resource = realview_smc91x_resources,
142}; 142};
143 143
144static struct resource realview_i2c_resource = {
145 .start = REALVIEW_I2C_BASE,
146 .end = REALVIEW_I2C_BASE + SZ_4K - 1,
147 .flags = IORESOURCE_MEM,
148};
149
150struct platform_device realview_i2c_device = {
151 .name = "versatile-i2c",
152 .id = -1,
153 .num_resources = 1,
154 .resource = &realview_i2c_resource,
155};
156
144#define REALVIEW_SYSMCI (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_MCI_OFFSET) 157#define REALVIEW_SYSMCI (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_MCI_OFFSET)
145 158
146static unsigned int realview_mmc_status(struct device *dev) 159static unsigned int realview_mmc_status(struct device *dev)
diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h
index 93e86d9f439c..2b53420f9c1b 100644
--- a/arch/arm/mach-realview/core.h
+++ b/arch/arm/mach-realview/core.h
@@ -108,6 +108,7 @@ static struct amba_device name##_device = { \
108 108
109extern struct platform_device realview_flash_device; 109extern struct platform_device realview_flash_device;
110extern struct platform_device realview_smc91x_device; 110extern struct platform_device realview_smc91x_device;
111extern struct platform_device realview_i2c_device;
111extern struct mmc_platform_data realview_mmc0_plat_data; 112extern struct mmc_platform_data realview_mmc0_plat_data;
112extern struct mmc_platform_data realview_mmc1_plat_data; 113extern struct mmc_platform_data realview_mmc1_plat_data;
113extern struct clk realview_clcd_clk; 114extern struct clk realview_clcd_clk;
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index 84a959530fb6..9741b4d3c9cf 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -155,6 +155,7 @@ static void __init realview_eb_init(void)
155 155
156 platform_device_register(&realview_flash_device); 156 platform_device_register(&realview_flash_device);
157 platform_device_register(&realview_smc91x_device); 157 platform_device_register(&realview_smc91x_device);
158 platform_device_register(&realview_i2c_device);
158 159
159 for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { 160 for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
160 struct amba_device *d = amba_devs[i]; 161 struct amba_device *d = amba_devs[i];
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 57196947559f..bf71507c76fd 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -325,6 +325,19 @@ static struct platform_device smc91x_device = {
325 .resource = smc91x_resources, 325 .resource = smc91x_resources,
326}; 326};
327 327
328static struct resource versatile_i2c_resource = {
329 .start = VERSATILE_I2C_BASE,
330 .end = VERSATILE_I2C_BASE + SZ_4K - 1,
331 .flags = IORESOURCE_MEM,
332};
333
334static struct platform_device versatile_i2c_device = {
335 .name = "versatile-i2c",
336 .id = -1,
337 .num_resources = 1,
338 .resource = &versatile_i2c_resource,
339};
340
328#define VERSATILE_SYSMCI (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_MCI_OFFSET) 341#define VERSATILE_SYSMCI (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_MCI_OFFSET)
329 342
330unsigned int mmc_status(struct device *dev) 343unsigned int mmc_status(struct device *dev)
@@ -775,6 +788,7 @@ void __init versatile_init(void)
775 clk_register(&versatile_clcd_clk); 788 clk_register(&versatile_clcd_clk);
776 789
777 platform_device_register(&versatile_flash_device); 790 platform_device_register(&versatile_flash_device);
791 platform_device_register(&versatile_i2c_device);
778 platform_device_register(&smc91x_device); 792 platform_device_register(&smc91x_device);
779 793
780 for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { 794 for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index ab398b700586..e1989f3a2684 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -476,6 +476,17 @@ config I2C_STUB
476 476
477 If you don't know what to do here, definitely say N. 477 If you don't know what to do here, definitely say N.
478 478
479config I2C_VERSATILE
480 tristate "ARM Versatile/Realview I2C bus support"
481 depends on I2C && (ARCH_VERSATILE || ARCH_REALVIEW)
482 select I2C_ALGOBIT
483 help
484 Say yes if you want to support the I2C serial bus on ARMs Versatile
485 range of platforms.
486
487 This driver can also be built as a module. If so, the module
488 will be called i2c-versatile.
489
479config I2C_VIA 490config I2C_VIA
480 tristate "VIA 82C586B" 491 tristate "VIA 82C586B"
481 depends on I2C && PCI && EXPERIMENTAL 492 depends on I2C && PCI && EXPERIMENTAL
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index a82b6bfad046..37196c1d0794 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o
40obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o 40obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o
41obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o 41obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o
42obj-$(CONFIG_I2C_STUB) += i2c-stub.o 42obj-$(CONFIG_I2C_STUB) += i2c-stub.o
43obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
43obj-$(CONFIG_I2C_VIA) += i2c-via.o 44obj-$(CONFIG_I2C_VIA) += i2c-via.o
44obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o 45obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o
45obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o 46obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o
diff --git a/drivers/i2c/busses/i2c-versatile.c b/drivers/i2c/busses/i2c-versatile.c
new file mode 100644
index 000000000000..081d9578ce10
--- /dev/null
+++ b/drivers/i2c/busses/i2c-versatile.c
@@ -0,0 +1,153 @@
1/*
2 * i2c-versatile.c
3 *
4 * Copyright (C) 2006 ARM Ltd.
5 * written by Russell King, Deep Blue Solutions Ltd.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/i2c.h>
14#include <linux/i2c-algo-bit.h>
15#include <linux/init.h>
16#include <linux/platform_device.h>
17
18#include <asm/io.h>
19
20#define I2C_CONTROL 0x00
21#define I2C_CONTROLS 0x00
22#define I2C_CONTROLC 0x04
23#define SCL (1 << 0)
24#define SDA (1 << 1)
25
26struct i2c_versatile {
27 struct i2c_adapter adap;
28 struct i2c_algo_bit_data algo;
29 void __iomem *base;
30};
31
32static void i2c_versatile_setsda(void *data, int state)
33{
34 struct i2c_versatile *i2c = data;
35
36 writel(SDA, i2c->base + (state ? I2C_CONTROLS : I2C_CONTROLC));
37}
38
39static void i2c_versatile_setscl(void *data, int state)
40{
41 struct i2c_versatile *i2c = data;
42
43 writel(SCL, i2c->base + (state ? I2C_CONTROLS : I2C_CONTROLC));
44}
45
46static int i2c_versatile_getsda(void *data)
47{
48 struct i2c_versatile *i2c = data;
49 return !!(readl(i2c->base + I2C_CONTROL) & SDA);
50}
51
52static int i2c_versatile_getscl(void *data)
53{
54 struct i2c_versatile *i2c = data;
55 return !!(readl(i2c->base + I2C_CONTROL) & SCL);
56}
57
58static struct i2c_algo_bit_data i2c_versatile_algo = {
59 .setsda = i2c_versatile_setsda,
60 .setscl = i2c_versatile_setscl,
61 .getsda = i2c_versatile_getsda,
62 .getscl = i2c_versatile_getscl,
63 .udelay = 30,
64 .timeout = HZ,
65};
66
67static int i2c_versatile_probe(struct platform_device *dev)
68{
69 struct i2c_versatile *i2c;
70 struct resource *r;
71 int ret;
72
73 r = platform_get_resource(dev, IORESOURCE_MEM, 0);
74 if (!r) {
75 ret = -EINVAL;
76 goto err_out;
77 }
78
79 if (!request_mem_region(r->start, r->end - r->start + 1, "versatile-i2c")) {
80 ret = -EBUSY;
81 goto err_out;
82 }
83
84 i2c = kzalloc(sizeof(struct i2c_versatile), GFP_KERNEL);
85 if (!i2c) {
86 ret = -ENOMEM;
87 goto err_release;
88 }
89
90 i2c->base = ioremap(r->start, r->end - r->start + 1);
91 if (!i2c->base) {
92 ret = -ENOMEM;
93 goto err_free;
94 }
95
96 writel(SCL | SDA, i2c->base + I2C_CONTROLS);
97
98 i2c->adap.owner = THIS_MODULE;
99 strlcpy(i2c->adap.name, "Versatile I2C adapter", sizeof(i2c->adap.name));
100 i2c->adap.algo_data = &i2c->algo;
101 i2c->adap.dev.parent = &dev->dev;
102 i2c->algo = i2c_versatile_algo;
103 i2c->algo.data = i2c;
104
105 ret = i2c_bit_add_bus(&i2c->adap);
106 if (ret >= 0) {
107 platform_set_drvdata(dev, i2c);
108 return 0;
109 }
110
111 iounmap(i2c->base);
112 err_free:
113 kfree(i2c);
114 err_release:
115 release_mem_region(r->start, r->end - r->start + 1);
116 err_out:
117 return ret;
118}
119
120static int i2c_versatile_remove(struct platform_device *dev)
121{
122 struct i2c_versatile *i2c = platform_get_drvdata(dev);
123
124 platform_set_drvdata(dev, NULL);
125
126 i2c_del_adapter(&i2c->adap);
127 return 0;
128}
129
130static struct platform_driver i2c_versatile_driver = {
131 .probe = i2c_versatile_probe,
132 .remove = i2c_versatile_remove,
133 .driver = {
134 .name = "versatile-i2c",
135 .owner = THIS_MODULE,
136 },
137};
138
139static int __init i2c_versatile_init(void)
140{
141 return platform_driver_register(&i2c_versatile_driver);
142}
143
144static void __exit i2c_versatile_exit(void)
145{
146 platform_driver_unregister(&i2c_versatile_driver);
147}
148
149module_init(i2c_versatile_init);
150module_exit(i2c_versatile_exit);
151
152MODULE_DESCRIPTION("ARM Versatile I2C bus driver");
153MODULE_LICENSE("GPL");