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.
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/delay.h>
20 #include <linux/platform_device.h>
21 #include <linux/slab.h>
24 #include <linux/i2c.h>
25 #include <linux/i2c-algo-bit.h>
27 struct simtec_i2c_data
{
28 struct resource
*ioarea
;
30 struct i2c_adapter adap
;
31 struct i2c_algo_bit_data bit
;
34 #define CMD_SET_SDA (1<<2)
35 #define CMD_SET_SCL (1<<3)
37 #define STATE_SDA (1<<0)
38 #define STATE_SCL (1<<1)
40 /* i2c bit-bus functions */
42 static void simtec_i2c_setsda(void *pw
, int state
)
44 struct simtec_i2c_data
*pd
= pw
;
45 writeb(CMD_SET_SDA
| (state
? STATE_SDA
: 0), pd
->reg
);
48 static void simtec_i2c_setscl(void *pw
, int state
)
50 struct simtec_i2c_data
*pd
= pw
;
51 writeb(CMD_SET_SCL
| (state
? STATE_SCL
: 0), pd
->reg
);
54 static int simtec_i2c_getsda(void *pw
)
56 struct simtec_i2c_data
*pd
= pw
;
57 return readb(pd
->reg
) & STATE_SDA
? 1 : 0;
60 static int simtec_i2c_getscl(void *pw
)
62 struct simtec_i2c_data
*pd
= pw
;
63 return readb(pd
->reg
) & STATE_SCL
? 1 : 0;
66 /* device registration */
68 static int simtec_i2c_probe(struct platform_device
*dev
)
70 struct simtec_i2c_data
*pd
;
75 pd
= kzalloc(sizeof(struct simtec_i2c_data
), GFP_KERNEL
);
79 platform_set_drvdata(dev
, pd
);
81 res
= platform_get_resource(dev
, IORESOURCE_MEM
, 0);
83 dev_err(&dev
->dev
, "cannot find IO resource\n");
88 size
= resource_size(res
);
90 pd
->ioarea
= request_mem_region(res
->start
, size
, dev
->name
);
91 if (pd
->ioarea
== NULL
) {
92 dev_err(&dev
->dev
, "cannot request IO\n");
97 pd
->reg
= ioremap(res
->start
, size
);
98 if (pd
->reg
== NULL
) {
99 dev_err(&dev
->dev
, "cannot map IO\n");
104 /* setup the private data */
106 pd
->adap
.owner
= THIS_MODULE
;
107 pd
->adap
.algo_data
= &pd
->bit
;
108 pd
->adap
.dev
.parent
= &dev
->dev
;
110 strlcpy(pd
->adap
.name
, "Simtec I2C", sizeof(pd
->adap
.name
));
113 pd
->bit
.setsda
= simtec_i2c_setsda
;
114 pd
->bit
.setscl
= simtec_i2c_setscl
;
115 pd
->bit
.getsda
= simtec_i2c_getsda
;
116 pd
->bit
.getscl
= simtec_i2c_getscl
;
117 pd
->bit
.timeout
= HZ
;
120 ret
= i2c_bit_add_bus(&pd
->adap
);
130 release_resource(pd
->ioarea
);
138 static int simtec_i2c_remove(struct platform_device
*dev
)
140 struct simtec_i2c_data
*pd
= platform_get_drvdata(dev
);
142 i2c_del_adapter(&pd
->adap
);
145 release_resource(pd
->ioarea
);
154 static struct platform_driver simtec_i2c_driver
= {
156 .name
= "simtec-i2c",
158 .probe
= simtec_i2c_probe
,
159 .remove
= simtec_i2c_remove
,
162 module_platform_driver(simtec_i2c_driver
);
164 MODULE_DESCRIPTION("Simtec Generic I2C Bus driver");
165 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
166 MODULE_LICENSE("GPL");
167 MODULE_ALIAS("platform:simtec-i2c");