added a lot of printk output to ease writing of emulator
[linux-2.4.21-pre4.git] / drivers / i2c / i2c-philips-par.c
1 /* ------------------------------------------------------------------------- */
2 /* i2c-philips-par.c i2c-hw access for philips style parallel port adapters  */
3 /* ------------------------------------------------------------------------- */
4 /*   Copyright (C) 1995-2000 Simon G. Vogl
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
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., 675 Mass Ave, Cambridge, MA 02139, USA.                */
19 /* ------------------------------------------------------------------------- */ 
20
21 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
22    Frodo Looijaard <frodol@dds.nl> */
23
24 /* $Id: i2c-philips-par.c,v 1.1.1.1 2005/04/11 02:50:21 jack Exp $ */
25
26 #include <linux/kernel.h>
27 #include <linux/ioport.h>
28 #include <linux/module.h>
29 #include <linux/init.h>
30 #include <linux/stddef.h>
31 #include <linux/parport.h>
32
33 #include <linux/i2c.h>
34 #include <linux/i2c-algo-bit.h>
35
36 #ifndef __exit
37 #define __exit __init
38 #endif
39
40 static int type;
41
42 struct i2c_par
43 {
44         struct pardevice *pdev;
45         struct i2c_adapter adapter;
46         struct i2c_algo_bit_data bit_lp_data;
47         struct i2c_par *next;
48 };
49
50 static struct i2c_par *adapter_list;
51
52
53 /* ----- global defines ----------------------------------------------- */
54 #define DEB(x)          /* should be reasonable open, close &c.         */
55 #define DEB2(x)         /* low level debugging - very slow              */
56 #define DEBE(x) x       /* error messages                               */
57
58 /* ----- printer port defines ------------------------------------------*/
59                                         /* Pin Port  Inverted   name    */
60 #define I2C_ON          0x20            /* 12 status N  paper           */
61                                         /* ... only for phil. not used  */
62 #define I2C_SDA         0x80            /*  9 data   N  data7           */
63 #define I2C_SCL         0x08            /* 17 ctrl   N  dsel            */
64
65 #define I2C_SDAIN       0x80            /* 11 stat   Y  busy            */
66 #define I2C_SCLIN       0x08            /* 15 stat   Y  enable          */
67
68 #define I2C_DMASK       0x7f
69 #define I2C_CMASK       0xf7
70
71 /* ----- local functions ---------------------------------------------- */
72
73 static void bit_lp_setscl(void *data, int state)
74 {
75         /*be cautious about state of the control register - 
76                 touch only the one bit needed*/
77         if (state) {
78                 parport_write_control((struct parport *) data,
79                       parport_read_control((struct parport *) data)|I2C_SCL);
80         } else {
81                 parport_write_control((struct parport *) data,
82                       parport_read_control((struct parport *) data)&I2C_CMASK);
83         }
84 }
85
86 static void bit_lp_setsda(void *data, int state)
87 {
88         if (state) {
89                 parport_write_data((struct parport *) data, I2C_DMASK);
90         } else {
91                 parport_write_data((struct parport *) data, I2C_SDA);
92         }
93 }
94
95 static int bit_lp_getscl(void *data)
96 {
97         return parport_read_status((struct parport *) data) & I2C_SCLIN;
98 }
99
100 static int bit_lp_getsda(void *data)
101 {
102         return parport_read_status((struct parport *) data) & I2C_SDAIN;
103 }
104
105 static void bit_lp_setscl2(void *data, int state)
106 {
107         if (state) {
108                 parport_write_data((struct parport *) data,
109                       parport_read_data((struct parport *) data)|0x1);
110         } else {
111                 parport_write_data((struct parport *) data,
112                       parport_read_data((struct parport *) data)&0xfe);
113         }
114 }
115
116 static void bit_lp_setsda2(void *data, int state)
117 {
118         if (state) {
119                 parport_write_data((struct parport *) data,
120                       parport_read_data((struct parport *) data)|0x2);
121         } else {
122                 parport_write_data((struct parport *) data,
123                       parport_read_data((struct parport *) data)&0xfd);
124         }
125 }
126
127 static int bit_lp_getsda2(void *data)
128 {
129         return (parport_read_status((struct parport *) data) & 
130                                      PARPORT_STATUS_BUSY) ? 0 : 1;
131 }
132
133 static int bit_lp_reg(struct i2c_client *client)
134 {
135         return 0;
136 }
137
138 static int bit_lp_unreg(struct i2c_client *client)
139 {
140         return 0;
141 }
142
143 static void bit_lp_inc_use(struct i2c_adapter *adap)
144 {
145         MOD_INC_USE_COUNT;
146 }
147
148 static void bit_lp_dec_use(struct i2c_adapter *adap)
149 {
150         MOD_DEC_USE_COUNT;
151 }
152
153 /* ------------------------------------------------------------------------
154  * Encapsulate the above functions in the correct operations structure.
155  * This is only done when more than one hardware adapter is supported.
156  */
157  
158 static struct i2c_algo_bit_data bit_lp_data = {
159         NULL,
160         bit_lp_setsda,
161         bit_lp_setscl,
162         bit_lp_getsda,
163         bit_lp_getscl,
164         80, 80, 100,            /*      waits, timeout */
165 }; 
166
167 static struct i2c_algo_bit_data bit_lp_data2 = {
168         NULL,
169         bit_lp_setsda2,
170         bit_lp_setscl2,
171         bit_lp_getsda2,
172         NULL,
173         80, 80, 100,            /*      waits, timeout */
174 }; 
175
176 static struct i2c_adapter bit_lp_ops = {
177         "Philips Parallel port adapter",
178         I2C_HW_B_LP,
179         NULL,
180         NULL,
181         bit_lp_inc_use,
182         bit_lp_dec_use,
183         bit_lp_reg,
184
185         bit_lp_unreg,
186 };
187
188 static void i2c_parport_attach (struct parport *port)
189 {
190         struct i2c_par *adapter = kmalloc(sizeof(struct i2c_par),
191                                           GFP_KERNEL);
192         if (!adapter) {
193                 printk("i2c-philips-par: Unable to malloc.\n");
194                 return;
195         }
196
197         printk("i2c-philips-par.o: attaching to %s\n", port->name);
198
199         adapter->pdev = parport_register_device(port, "i2c-philips-par",
200                                                 NULL, NULL, NULL, 
201                                                 PARPORT_FLAG_EXCL,
202                                                 NULL);
203         if (!adapter->pdev) {
204                 printk("i2c-philips-par: Unable to register with parport.\n");
205                 return;
206         }
207
208         adapter->adapter = bit_lp_ops;
209         adapter->adapter.algo_data = &adapter->bit_lp_data;
210         adapter->bit_lp_data = type ? bit_lp_data2 : bit_lp_data;
211         adapter->bit_lp_data.data = port;
212
213         /* reset hardware to sane state */
214         parport_claim_or_block(adapter->pdev);
215         bit_lp_setsda(port, 1);
216         bit_lp_setscl(port, 1);
217         parport_release(adapter->pdev);
218
219         if (i2c_bit_add_bus(&adapter->adapter) < 0)
220         {
221                 printk("i2c-philips-par: Unable to register with I2C.\n");
222                 parport_unregister_device(adapter->pdev);
223                 kfree(adapter);
224                 return;         /* No good */
225         }
226
227         adapter->next = adapter_list;
228         adapter_list = adapter;
229 }
230
231 static void i2c_parport_detach (struct parport *port)
232 {
233         struct i2c_par *adapter, *prev = NULL;
234
235         for (adapter = adapter_list; adapter; adapter = adapter->next)
236         {
237                 if (adapter->pdev->port == port)
238                 {
239                         parport_unregister_device(adapter->pdev);
240                         i2c_bit_del_bus(&adapter->adapter);
241                         if (prev)
242                                 prev->next = adapter->next;
243                         else
244                                 adapter_list = adapter->next;
245                         kfree(adapter);
246                         return;
247                 }
248                 prev = adapter;
249         }
250 }
251
252
253 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,4)
254 static struct parport_driver i2c_driver = {
255         "i2c-philips-par",
256         i2c_parport_attach,
257         i2c_parport_detach,
258         NULL
259 };
260 #endif
261
262 int __init i2c_bitlp_init(void)
263 {
264 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,4)
265         struct parport *port;
266 #endif
267         printk("i2c-philips-par.o: i2c Philips parallel port adapter module\n");
268
269 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,4)
270         parport_register_driver(&i2c_driver);
271 #else
272         for (port = parport_enumerate(); port; port=port->next)
273                 i2c_parport_attach(port);
274 #endif
275         
276         return 0;
277 }
278
279 void __exit i2c_bitlp_exit(void)
280 {
281 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,4)
282         parport_unregister_driver(&i2c_driver);
283 #else
284         struct parport *port;
285         for (port = parport_enumerate(); port; port=port->next)
286                 i2c_parport_detach(port);
287 #endif
288 }
289
290 EXPORT_NO_SYMBOLS;
291
292 MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
293 MODULE_DESCRIPTION("I2C-Bus adapter routines for Philips parallel port adapter");
294 MODULE_LICENSE("GPL");
295
296 MODULE_PARM(type, "i");
297
298 #ifdef MODULE
299 int init_module(void)
300 {
301         return i2c_bitlp_init();
302 }
303
304 void cleanup_module(void)
305 {
306         i2c_bitlp_exit();
307 }
308 #endif