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/init.h>
24 #include <linux/delay.h>
25 #include <linux/platform_device.h>
27 #include <linux/i2c.h>
28 #include <linux/i2c-algo-bit.h>
32 struct simtec_i2c_data
{
33 struct resource
*ioarea
;
35 struct i2c_adapter adap
;
36 struct i2c_algo_bit_data bit
;
39 #define CMD_SET_SDA (1<<2)
40 #define CMD_SET_SCL (1<<3)
42 #define STATE_SDA (1<<0)
43 #define STATE_SCL (1<<1)
45 /* i2c bit-bus functions */
47 static void simtec_i2c_setsda(void *pw
, int state
)
49 struct simtec_i2c_data
*pd
= pw
;
50 writeb(CMD_SET_SDA
| (state
? STATE_SDA
: 0), pd
->reg
);
53 static void simtec_i2c_setscl(void *pw
, int state
)
55 struct simtec_i2c_data
*pd
= pw
;
56 writeb(CMD_SET_SCL
| (state
? STATE_SCL
: 0), pd
->reg
);
59 static int simtec_i2c_getsda(void *pw
)
61 struct simtec_i2c_data
*pd
= pw
;
62 return readb(pd
->reg
) & STATE_SDA
? 1 : 0;
65 static int simtec_i2c_getscl(void *pw
)
67 struct simtec_i2c_data
*pd
= pw
;
68 return readb(pd
->reg
) & STATE_SCL
? 1 : 0;
71 /* device registration */
73 static int simtec_i2c_probe(struct platform_device
*dev
)
75 struct simtec_i2c_data
*pd
;
80 pd
= kzalloc(sizeof(struct simtec_i2c_data
), GFP_KERNEL
);
82 dev_err(&dev
->dev
, "cannot allocate private data\n");
86 platform_set_drvdata(dev
, pd
);
88 res
= platform_get_resource(dev
, IORESOURCE_MEM
, 0);
90 dev_err(&dev
->dev
, "cannot find IO resource\n");
95 size
= resource_size(res
);
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");
104 pd
->reg
= ioremap(res
->start
, size
);
105 if (pd
->reg
== NULL
) {
106 dev_err(&dev
->dev
, "cannot map IO\n");
111 /* setup the private data */
113 pd
->adap
.owner
= THIS_MODULE
;
114 pd
->adap
.algo_data
= &pd
->bit
;
115 pd
->adap
.dev
.parent
= &dev
->dev
;
117 strlcpy(pd
->adap
.name
, "Simtec I2C", sizeof(pd
->adap
.name
));
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
;
127 ret
= i2c_bit_add_bus(&pd
->adap
);
137 release_resource(pd
->ioarea
);
145 static int simtec_i2c_remove(struct platform_device
*dev
)
147 struct simtec_i2c_data
*pd
= platform_get_drvdata(dev
);
149 i2c_del_adapter(&pd
->adap
);
152 release_resource(pd
->ioarea
);
162 /* work with hotplug and coldplug */
163 MODULE_ALIAS("platform:simtec-i2c");
165 static struct platform_driver simtec_i2c_driver
= {
167 .name
= "simtec-i2c",
168 .owner
= THIS_MODULE
,
170 .probe
= simtec_i2c_probe
,
171 .remove
= simtec_i2c_remove
,
174 static int __init
i2c_adap_simtec_init(void)
176 return platform_driver_register(&simtec_i2c_driver
);
179 static void __exit
i2c_adap_simtec_exit(void)
181 platform_driver_unregister(&simtec_i2c_driver
);
184 module_init(i2c_adap_simtec_init
);
185 module_exit(i2c_adap_simtec_exit
);
187 MODULE_DESCRIPTION("Simtec Generic I2C Bus driver");
188 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
189 MODULE_LICENSE("GPL");