2 * Copyright (C) 2005 Simtec Electronics
3 * Ben Dooks <ben@simtec.co.uk>
5 * Simtec Generic I2C Controller
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
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.
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
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <linux/delay.h>
24 #include <linux/platform_device.h>
25 #include <linux/slab.h>
28 #include <linux/i2c.h>
29 #include <linux/i2c-algo-bit.h>
31 struct simtec_i2c_data
{
32 struct resource
*ioarea
;
34 struct i2c_adapter adap
;
35 struct i2c_algo_bit_data bit
;
38 #define CMD_SET_SDA (1<<2)
39 #define CMD_SET_SCL (1<<3)
41 #define STATE_SDA (1<<0)
42 #define STATE_SCL (1<<1)
44 /* i2c bit-bus functions */
46 static void simtec_i2c_setsda(void *pw
, int state
)
48 struct simtec_i2c_data
*pd
= pw
;
49 writeb(CMD_SET_SDA
| (state
? STATE_SDA
: 0), pd
->reg
);
52 static void simtec_i2c_setscl(void *pw
, int state
)
54 struct simtec_i2c_data
*pd
= pw
;
55 writeb(CMD_SET_SCL
| (state
? STATE_SCL
: 0), pd
->reg
);
58 static int simtec_i2c_getsda(void *pw
)
60 struct simtec_i2c_data
*pd
= pw
;
61 return readb(pd
->reg
) & STATE_SDA
? 1 : 0;
64 static int simtec_i2c_getscl(void *pw
)
66 struct simtec_i2c_data
*pd
= pw
;
67 return readb(pd
->reg
) & STATE_SCL
? 1 : 0;
70 /* device registration */
72 static int simtec_i2c_probe(struct platform_device
*dev
)
74 struct simtec_i2c_data
*pd
;
79 pd
= kzalloc(sizeof(struct simtec_i2c_data
), GFP_KERNEL
);
81 dev_err(&dev
->dev
, "cannot allocate private data\n");
85 platform_set_drvdata(dev
, pd
);
87 res
= platform_get_resource(dev
, IORESOURCE_MEM
, 0);
89 dev_err(&dev
->dev
, "cannot find IO resource\n");
94 size
= resource_size(res
);
96 pd
->ioarea
= request_mem_region(res
->start
, size
, dev
->name
);
97 if (pd
->ioarea
== NULL
) {
98 dev_err(&dev
->dev
, "cannot request IO\n");
103 pd
->reg
= ioremap(res
->start
, size
);
104 if (pd
->reg
== NULL
) {
105 dev_err(&dev
->dev
, "cannot map IO\n");
110 /* setup the private data */
112 pd
->adap
.owner
= THIS_MODULE
;
113 pd
->adap
.algo_data
= &pd
->bit
;
114 pd
->adap
.dev
.parent
= &dev
->dev
;
116 strlcpy(pd
->adap
.name
, "Simtec I2C", sizeof(pd
->adap
.name
));
119 pd
->bit
.setsda
= simtec_i2c_setsda
;
120 pd
->bit
.setscl
= simtec_i2c_setscl
;
121 pd
->bit
.getsda
= simtec_i2c_getsda
;
122 pd
->bit
.getscl
= simtec_i2c_getscl
;
123 pd
->bit
.timeout
= HZ
;
126 ret
= i2c_bit_add_bus(&pd
->adap
);
136 release_resource(pd
->ioarea
);
144 static int simtec_i2c_remove(struct platform_device
*dev
)
146 struct simtec_i2c_data
*pd
= platform_get_drvdata(dev
);
148 i2c_del_adapter(&pd
->adap
);
151 release_resource(pd
->ioarea
);
160 static struct platform_driver simtec_i2c_driver
= {
162 .name
= "simtec-i2c",
163 .owner
= THIS_MODULE
,
165 .probe
= simtec_i2c_probe
,
166 .remove
= simtec_i2c_remove
,
169 module_platform_driver(simtec_i2c_driver
);
171 MODULE_DESCRIPTION("Simtec Generic I2C Bus driver");
172 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
173 MODULE_LICENSE("GPL");
174 MODULE_ALIAS("platform:simtec-i2c");