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