cleanup
[linux-2.4.21-pre4.git] / drivers / i2c / i2c-elv.c
1 /* ------------------------------------------------------------------------- */
2 /* i2c-elv.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-elv.c,v 1.1.1.1 2005/04/11 02:50:21 jack Exp $ */
25
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/delay.h>
29 #include <linux/slab.h>
30 #include <linux/version.h>
31 #include <linux/init.h>
32
33 #include <asm/uaccess.h>
34
35 #include <linux/ioport.h>
36 #include <asm/io.h>
37 #include <linux/errno.h>
38 #include <linux/i2c.h>
39 #include <linux/i2c-algo-bit.h>
40
41 #define DEFAULT_BASE 0x378
42 static int base=0;
43 static unsigned char PortData = 0;
44
45 /* ----- global defines ----------------------------------------------- */
46 #define DEB(x)          /* should be reasonable open, close &c.         */
47 #define DEB2(x)         /* low level debugging - very slow              */
48 #define DEBE(x) x       /* error messages                               */
49 #define DEBINIT(x) x    /* detection status messages                    */
50
51 /* --- Convenience defines for the parallel port:                       */
52 #define BASE    (unsigned int)(data)
53 #define DATA    BASE                    /* Centronics data port         */
54 #define STAT    (BASE+1)                /* Centronics status port       */
55 #define CTRL    (BASE+2)                /* Centronics control port      */
56
57
58 /* ----- local functions ---------------------------------------------- */
59
60
61 static void bit_elv_setscl(void *data, int state)
62 {
63         if (state) {
64                 PortData &= 0xfe;
65         } else {
66                 PortData |=1;
67         }
68         outb(PortData, DATA);
69 }
70
71 static void bit_elv_setsda(void *data, int state)
72 {
73         if (state) {
74                 PortData &=0xfd;
75         } else {
76                 PortData |=2;
77         }
78         outb(PortData, DATA);
79
80
81 static int bit_elv_getscl(void *data)
82 {
83         return ( 0 == ( (inb_p(STAT)) & 0x08 ) );
84 }
85
86 static int bit_elv_getsda(void *data)
87 {
88         return ( 0 == ( (inb_p(STAT)) & 0x40 ) );
89 }
90
91 static int bit_elv_init(void)
92 {
93         if (check_region(base,(base == 0x3bc)? 3 : 8) < 0 ) {
94                 return -ENODEV; 
95         } else {
96                                                 /* test for ELV adap.   */
97                 if (inb(base+1) & 0x80) {       /* BUSY should be high  */
98                         DEBINIT(printk("i2c-elv.o: Busy was low.\n"));
99                         return -ENODEV;
100                 } else {
101                         outb(0x0c,base+2);      /* SLCT auf low         */
102                         udelay(400);
103                         if ( !(inb(base+1) && 0x10) ) {
104                                 outb(0x04,base+2);
105                                 DEBINIT(printk("i2c-elv.o: Select was high.\n"));
106                                 return -ENODEV;
107                         }
108                 }
109                 request_region(base,(base == 0x3bc)? 3 : 8,
110                         "i2c (ELV adapter)");
111                 PortData = 0;
112                 bit_elv_setsda((void*)base,1);
113                 bit_elv_setscl((void*)base,1);
114         }
115         return 0;
116 }
117
118 static void __exit bit_elv_exit(void)
119 {
120         release_region( base , (base == 0x3bc)? 3 : 8 );
121 }
122
123 static int bit_elv_reg(struct i2c_client *client)
124 {
125         return 0;
126 }
127
128 static int bit_elv_unreg(struct i2c_client *client)
129 {
130         return 0;
131 }
132
133 static void bit_elv_inc_use(struct i2c_adapter *adap)
134 {
135 #ifdef MODULE
136         MOD_INC_USE_COUNT;
137 #endif
138 }
139
140 static void bit_elv_dec_use(struct i2c_adapter *adap)
141 {
142 #ifdef MODULE
143         MOD_DEC_USE_COUNT;
144 #endif
145 }
146
147 /* ------------------------------------------------------------------------
148  * Encapsulate the above functions in the correct operations structure.
149  * This is only done when more than one hardware adapter is supported.
150  */
151 static struct i2c_algo_bit_data bit_elv_data = {
152         NULL,
153         bit_elv_setsda,
154         bit_elv_setscl,
155         bit_elv_getsda,
156         bit_elv_getscl,
157         80, 80, 100,            /*      waits, timeout */
158 };
159
160 static struct i2c_adapter bit_elv_ops = {
161         "ELV Parallel port adaptor",
162         I2C_HW_B_ELV,
163         NULL,
164         &bit_elv_data,
165         bit_elv_inc_use,
166         bit_elv_dec_use,
167         bit_elv_reg,
168         bit_elv_unreg,  
169 };
170
171 int __init i2c_bitelv_init(void)
172 {
173         printk("i2c-elv.o: i2c ELV parallel port adapter module\n");
174         if (base==0) {
175                 /* probe some values */
176                 base=DEFAULT_BASE;
177                 bit_elv_data.data=(void*)DEFAULT_BASE;
178                 if (bit_elv_init()==0) {
179                         if(i2c_bit_add_bus(&bit_elv_ops) < 0)
180                                 return -ENODEV;
181                 } else {
182                         return -ENODEV;
183                 }
184         } else {
185                 bit_elv_ops.data=(void*)base;
186                 if (bit_elv_init()==0) {
187                         if(i2c_bit_add_bus(&bit_elv_ops) < 0)
188                                 return -ENODEV;
189                 } else {
190                         return -ENODEV;
191                 }
192         }
193         printk("i2c-elv.o: found device at %#x.\n",base);
194         return 0;
195 }
196
197
198 EXPORT_NO_SYMBOLS;
199
200 #ifdef MODULE
201 MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
202 MODULE_DESCRIPTION("I2C-Bus adapter routines for ELV parallel port adapter");
203 MODULE_LICENSE("GPL");
204
205
206 MODULE_PARM(base, "i");
207
208 int init_module(void)
209 {
210         return i2c_bitelv_init();
211 }
212
213 void cleanup_module(void)
214 {
215         i2c_bit_del_bus(&bit_elv_ops);
216         bit_elv_exit();
217 }
218
219 #endif