aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/i2c/busses/Kconfig12
-rw-r--r--drivers/i2c/busses/Makefile1
-rw-r--r--drivers/i2c/busses/i2c-simtec.c186
3 files changed, 199 insertions, 0 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 33a8a67f161b..2178c9bebfc9 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -413,6 +413,18 @@ config I2C_SIBYTE
413 help 413 help
414 Supports the SiByte SOC on-chip I2C interfaces (2 channels). 414 Supports the SiByte SOC on-chip I2C interfaces (2 channels).
415 415
416config I2C_SIMTEC
417 tristate "Simtec Generic I2C interface"
418 select I2C_ALGOBIT
419 help
420 If you say yes to this option, support will be inclyded for
421 the Simtec Generic I2C interface. This driver is for the
422 simple I2C bus used on newer Simtec products for general
423 I2C, such as DDC on the Simtec BBD2016A.
424
425 This driver can also be build as a module. If so, the module
426 will be called i2c-simtec.
427
416config SCx200_I2C 428config SCx200_I2C
417 tristate "NatSemi SCx200 I2C using GPIO pins" 429 tristate "NatSemi SCx200 I2C using GPIO pins"
418 depends on SCx200_GPIO 430 depends on SCx200_GPIO
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 5689165f6d6a..3a020ea8edef 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o
39obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o 39obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
40obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o 40obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o
41obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o 41obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
42obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o
42obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o 43obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o
43obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o 44obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o
44obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o 45obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o
diff --git a/drivers/i2c/busses/i2c-simtec.c b/drivers/i2c/busses/i2c-simtec.c
new file mode 100644
index 000000000000..10af8d31e12a
--- /dev/null
+++ b/drivers/i2c/busses/i2c-simtec.c
@@ -0,0 +1,186 @@
1/*
2 * Copyright (C) 2005 Simtec Electronics
3 * Ben Dooks <ben@simtec.co.uk>
4 *
5 * Simtec Generic I2C Controller
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 as published by
9 * the Free Software Foundation; either version 2 of the License
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19*/
20
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/init.h>
24#include <linux/delay.h>
25#include <linux/platform_device.h>
26
27#include <linux/i2c.h>
28#include <linux/i2c-algo-bit.h>
29
30#include <asm/io.h>
31
32struct simtec_i2c_data {
33 struct resource *ioarea;
34 void __iomem *reg;
35 struct i2c_adapter adap;
36 struct i2c_algo_bit_data bit;
37};
38
39#define CMD_SET_SDA (1<<2)
40#define CMD_SET_SCL (1<<3)
41
42#define STATE_SDA (1<<0)
43#define STATE_SCL (1<<1)
44
45/* i2c bit-bus functions */
46
47static void simtec_i2c_setsda(void *pw, int state)
48{
49 struct simtec_i2c_data *pd = pw;
50 writeb(CMD_SET_SDA | (state ? STATE_SDA : 0), pd->reg);
51}
52
53static void simtec_i2c_setscl(void *pw, int state)
54{
55 struct simtec_i2c_data *pd = pw;
56 writeb(CMD_SET_SCL | (state ? STATE_SCL : 0), pd->reg);
57}
58
59static int simtec_i2c_getsda(void *pw)
60{
61 struct simtec_i2c_data *pd = pw;
62 return readb(pd->reg) & STATE_SDA ? 1 : 0;
63}
64
65static int simtec_i2c_getscl(void *pw)
66{
67 struct simtec_i2c_data *pd = pw;
68 return readb(pd->reg) & STATE_SCL ? 1 : 0;
69}
70
71/* device registration */
72
73static int simtec_i2c_probe(struct platform_device *dev)
74{
75 struct simtec_i2c_data *pd;
76 struct resource *res;
77 int size;
78 int ret;
79
80 pd = kzalloc(sizeof(struct simtec_i2c_data), GFP_KERNEL);
81 if (pd == NULL) {
82 dev_err(&dev->dev, "cannot allocate private data\n");
83 return -ENOMEM;
84 }
85
86 platform_set_drvdata(dev, pd);
87
88 res = platform_get_resource(dev, IORESOURCE_MEM, 0);
89 if (res == NULL) {
90 dev_err(&dev->dev, "cannot find IO resource\n");
91 ret = -ENOENT;
92 goto err;
93 }
94
95 size = (res->end-res->start)+1;
96
97 pd->ioarea = request_mem_region(res->start, size, dev->name);
98 if (pd->ioarea == NULL) {
99 dev_err(&dev->dev, "cannot request IO\n");
100 ret = -ENXIO;
101 goto err;
102 }
103
104 pd->reg = ioremap(res->start, size);
105 if (pd->reg == NULL) {
106 dev_err(&dev->dev, "cannot map IO\n");
107 ret = -ENXIO;
108 goto err_res;
109 }
110
111 /* setup the private data */
112
113 pd->adap.owner = THIS_MODULE;
114 pd->adap.algo_data = &pd->bit;
115 pd->adap.dev.parent = &dev->dev;
116
117 strlcpy(pd->adap.name, "Simtec I2C", sizeof(pd->adap.name));
118
119 pd->bit.data = pd;
120 pd->bit.setsda = simtec_i2c_setsda;
121 pd->bit.setscl = simtec_i2c_setscl;
122 pd->bit.getsda = simtec_i2c_getsda;
123 pd->bit.getscl = simtec_i2c_getscl;
124 pd->bit.timeout = HZ;
125 pd->bit.udelay = 20;
126
127 ret = i2c_bit_add_bus(&pd->adap);
128 if (ret)
129 goto err_all;
130
131 return 0;
132
133 err_all:
134 iounmap(pd->reg);
135
136 err_res:
137 release_resource(pd->ioarea);
138 kfree(pd->ioarea);
139
140 err:
141 kfree(pd);
142 return ret;
143}
144
145static int simtec_i2c_remove(struct platform_device *dev)
146{
147 struct simtec_i2c_data *pd = platform_get_drvdata(dev);
148
149 i2c_del_adapter(&pd->adap);
150
151 iounmap(pd->reg);
152 release_resource(pd->ioarea);
153 kfree(pd->ioarea);
154 kfree(pd);
155
156 return 0;
157}
158
159
160/* device driver */
161
162static struct platform_driver simtec_i2c_driver = {
163 .driver = {
164 .name = "simtec-i2c",
165 .owner = THIS_MODULE,
166 },
167 .probe = simtec_i2c_probe,
168 .remove = simtec_i2c_remove,
169};
170
171static int __init i2c_adap_simtec_init(void)
172{
173 return platform_driver_register(&simtec_i2c_driver);
174}
175
176static void __exit i2c_adap_simtec_exit(void)
177{
178 platform_driver_unregister(&simtec_i2c_driver);
179}
180
181module_init(i2c_adap_simtec_init);
182module_exit(i2c_adap_simtec_exit);
183
184MODULE_DESCRIPTION("Simtec Generic I2C Bus driver");
185MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
186MODULE_LICENSE("GPL");