xref: /openbmc/linux/drivers/i2c/busses/i2c-parport.c (revision b34e08d5)
1 /* ------------------------------------------------------------------------ *
2  * i2c-parport.c I2C bus over parallel port                                 *
3  * ------------------------------------------------------------------------ *
4    Copyright (C) 2003-2011 Jean Delvare <jdelvare@suse.de>
5 
6    Based on older i2c-philips-par.c driver
7    Copyright (C) 1995-2000 Simon G. Vogl
8    With some changes from:
9    Frodo Looijaard <frodol@dds.nl>
10    Kyösti Mälkki <kmalkki@cc.hut.fi>
11 
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 2 of the License, or
15    (at your option) any later version.
16 
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21 
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25  * ------------------------------------------------------------------------ */
26 
27 #include <linux/kernel.h>
28 #include <linux/module.h>
29 #include <linux/init.h>
30 #include <linux/delay.h>
31 #include <linux/parport.h>
32 #include <linux/i2c.h>
33 #include <linux/i2c-algo-bit.h>
34 #include <linux/i2c-smbus.h>
35 #include <linux/slab.h>
36 #include <linux/list.h>
37 #include <linux/mutex.h>
38 #include "i2c-parport.h"
39 
40 /* ----- Device list ------------------------------------------------------ */
41 
42 struct i2c_par {
43 	struct pardevice *pdev;
44 	struct i2c_adapter adapter;
45 	struct i2c_algo_bit_data algo_data;
46 	struct i2c_smbus_alert_setup alert_data;
47 	struct i2c_client *ara;
48 	struct list_head node;
49 };
50 
51 static LIST_HEAD(adapter_list);
52 static DEFINE_MUTEX(adapter_list_lock);
53 
54 /* ----- Low-level parallel port access ----------------------------------- */
55 
56 static void port_write_data(struct parport *p, unsigned char d)
57 {
58 	parport_write_data(p, d);
59 }
60 
61 static void port_write_control(struct parport *p, unsigned char d)
62 {
63 	parport_write_control(p, d);
64 }
65 
66 static unsigned char port_read_data(struct parport *p)
67 {
68 	return parport_read_data(p);
69 }
70 
71 static unsigned char port_read_status(struct parport *p)
72 {
73 	return parport_read_status(p);
74 }
75 
76 static unsigned char port_read_control(struct parport *p)
77 {
78 	return parport_read_control(p);
79 }
80 
81 static void (* const port_write[])(struct parport *, unsigned char) = {
82 	port_write_data,
83 	NULL,
84 	port_write_control,
85 };
86 
87 static unsigned char (* const port_read[])(struct parport *) = {
88 	port_read_data,
89 	port_read_status,
90 	port_read_control,
91 };
92 
93 /* ----- Unified line operation functions --------------------------------- */
94 
95 static inline void line_set(struct parport *data, int state,
96 	const struct lineop *op)
97 {
98 	u8 oldval = port_read[op->port](data);
99 
100 	/* Touch only the bit(s) needed */
101 	if ((op->inverted && !state) || (!op->inverted && state))
102 		port_write[op->port](data, oldval | op->val);
103 	else
104 		port_write[op->port](data, oldval & ~op->val);
105 }
106 
107 static inline int line_get(struct parport *data,
108 	const struct lineop *op)
109 {
110 	u8 oldval = port_read[op->port](data);
111 
112 	return ((op->inverted && (oldval & op->val) != op->val)
113 	    || (!op->inverted && (oldval & op->val) == op->val));
114 }
115 
116 /* ----- I2C algorithm call-back functions and structures ----------------- */
117 
118 static void parport_setscl(void *data, int state)
119 {
120 	line_set((struct parport *) data, state, &adapter_parm[type].setscl);
121 }
122 
123 static void parport_setsda(void *data, int state)
124 {
125 	line_set((struct parport *) data, state, &adapter_parm[type].setsda);
126 }
127 
128 static int parport_getscl(void *data)
129 {
130 	return line_get((struct parport *) data, &adapter_parm[type].getscl);
131 }
132 
133 static int parport_getsda(void *data)
134 {
135 	return line_get((struct parport *) data, &adapter_parm[type].getsda);
136 }
137 
138 /* Encapsulate the functions above in the correct structure.
139    Note that this is only a template, from which the real structures are
140    copied. The attaching code will set getscl to NULL for adapters that
141    cannot read SCL back, and will also make the data field point to
142    the parallel port structure. */
143 static const struct i2c_algo_bit_data parport_algo_data = {
144 	.setsda		= parport_setsda,
145 	.setscl		= parport_setscl,
146 	.getsda		= parport_getsda,
147 	.getscl		= parport_getscl,
148 	.udelay		= 10, /* ~50 kbps */
149 	.timeout	= HZ,
150 };
151 
152 /* ----- I2c and parallel port call-back functions and structures --------- */
153 
154 static void i2c_parport_irq(void *data)
155 {
156 	struct i2c_par *adapter = data;
157 	struct i2c_client *ara = adapter->ara;
158 
159 	if (ara) {
160 		dev_dbg(&ara->dev, "SMBus alert received\n");
161 		i2c_handle_smbus_alert(ara);
162 	} else
163 		dev_dbg(&adapter->adapter.dev,
164 			"SMBus alert received but no ARA client!\n");
165 }
166 
167 static void i2c_parport_attach(struct parport *port)
168 {
169 	struct i2c_par *adapter;
170 
171 	adapter = kzalloc(sizeof(struct i2c_par), GFP_KERNEL);
172 	if (adapter == NULL) {
173 		printk(KERN_ERR "i2c-parport: Failed to kzalloc\n");
174 		return;
175 	}
176 
177 	pr_debug("i2c-parport: attaching to %s\n", port->name);
178 	parport_disable_irq(port);
179 	adapter->pdev = parport_register_device(port, "i2c-parport",
180 		NULL, NULL, i2c_parport_irq, PARPORT_FLAG_EXCL, adapter);
181 	if (!adapter->pdev) {
182 		printk(KERN_ERR "i2c-parport: Unable to register with parport\n");
183 		goto err_free;
184 	}
185 
186 	/* Fill the rest of the structure */
187 	adapter->adapter.owner = THIS_MODULE;
188 	adapter->adapter.class = I2C_CLASS_HWMON;
189 	strlcpy(adapter->adapter.name, "Parallel port adapter",
190 		sizeof(adapter->adapter.name));
191 	adapter->algo_data = parport_algo_data;
192 	/* Slow down if we can't sense SCL */
193 	if (!adapter_parm[type].getscl.val) {
194 		adapter->algo_data.getscl = NULL;
195 		adapter->algo_data.udelay = 50; /* ~10 kbps */
196 	}
197 	adapter->algo_data.data = port;
198 	adapter->adapter.algo_data = &adapter->algo_data;
199 	adapter->adapter.dev.parent = port->physport->dev;
200 
201 	if (parport_claim_or_block(adapter->pdev) < 0) {
202 		printk(KERN_ERR "i2c-parport: Could not claim parallel port\n");
203 		goto err_unregister;
204 	}
205 
206 	/* Reset hardware to a sane state (SCL and SDA high) */
207 	parport_setsda(port, 1);
208 	parport_setscl(port, 1);
209 	/* Other init if needed (power on...) */
210 	if (adapter_parm[type].init.val) {
211 		line_set(port, 1, &adapter_parm[type].init);
212 		/* Give powered devices some time to settle */
213 		msleep(100);
214 	}
215 
216 	if (i2c_bit_add_bus(&adapter->adapter) < 0) {
217 		printk(KERN_ERR "i2c-parport: Unable to register with I2C\n");
218 		goto err_unregister;
219 	}
220 
221 	/* Setup SMBus alert if supported */
222 	if (adapter_parm[type].smbus_alert) {
223 		adapter->alert_data.alert_edge_triggered = 1;
224 		adapter->ara = i2c_setup_smbus_alert(&adapter->adapter,
225 						     &adapter->alert_data);
226 		if (adapter->ara)
227 			parport_enable_irq(port);
228 		else
229 			printk(KERN_WARNING "i2c-parport: Failed to register "
230 			       "ARA client\n");
231 	}
232 
233 	/* Add the new adapter to the list */
234 	mutex_lock(&adapter_list_lock);
235 	list_add_tail(&adapter->node, &adapter_list);
236 	mutex_unlock(&adapter_list_lock);
237 	return;
238 
239  err_unregister:
240 	parport_release(adapter->pdev);
241 	parport_unregister_device(adapter->pdev);
242  err_free:
243 	kfree(adapter);
244 }
245 
246 static void i2c_parport_detach(struct parport *port)
247 {
248 	struct i2c_par *adapter, *_n;
249 
250 	/* Walk the list */
251 	mutex_lock(&adapter_list_lock);
252 	list_for_each_entry_safe(adapter, _n, &adapter_list, node) {
253 		if (adapter->pdev->port == port) {
254 			if (adapter->ara) {
255 				parport_disable_irq(port);
256 				i2c_unregister_device(adapter->ara);
257 			}
258 			i2c_del_adapter(&adapter->adapter);
259 
260 			/* Un-init if needed (power off...) */
261 			if (adapter_parm[type].init.val)
262 				line_set(port, 0, &adapter_parm[type].init);
263 
264 			parport_release(adapter->pdev);
265 			parport_unregister_device(adapter->pdev);
266 			list_del(&adapter->node);
267 			kfree(adapter);
268 		}
269 	}
270 	mutex_unlock(&adapter_list_lock);
271 }
272 
273 static struct parport_driver i2c_parport_driver = {
274 	.name	= "i2c-parport",
275 	.attach	= i2c_parport_attach,
276 	.detach	= i2c_parport_detach,
277 };
278 
279 /* ----- Module loading, unloading and information ------------------------ */
280 
281 static int __init i2c_parport_init(void)
282 {
283 	if (type < 0) {
284 		printk(KERN_WARNING "i2c-parport: adapter type unspecified\n");
285 		return -ENODEV;
286 	}
287 
288 	if (type >= ARRAY_SIZE(adapter_parm)) {
289 		printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
290 		return -ENODEV;
291 	}
292 
293 	return parport_register_driver(&i2c_parport_driver);
294 }
295 
296 static void __exit i2c_parport_exit(void)
297 {
298 	parport_unregister_driver(&i2c_parport_driver);
299 }
300 
301 MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
302 MODULE_DESCRIPTION("I2C bus over parallel port");
303 MODULE_LICENSE("GPL");
304 
305 module_init(i2c_parport_init);
306 module_exit(i2c_parport_exit);
307