brute-forced more changes from MontaVista's tree. SCSI partition table read still...
[linux-2.4.git] / drivers / i2c / i2c-elektor.c
1 /* ------------------------------------------------------------------------- */
2 /* i2c-elektor.c i2c-hw access for PCF8584 style isa bus adaptes             */
3 /* ------------------------------------------------------------------------- */
4 /*   Copyright (C) 1995-97 Simon G. Vogl
5                    1998-99 Hans Berglund
6
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, or
10     (at your option) any later version.
11
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
20 /* ------------------------------------------------------------------------- */
21
22 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
23    Frodo Looijaard <frodol@dds.nl> */
24
25 /* Partialy rewriten by Oleg I. Vdovikin for mmapped support of 
26    for Alpha Processor Inc. UP-2000(+) boards */
27
28 #include <linux/kernel.h>
29 #include <linux/ioport.h>
30 #include <linux/module.h>
31 #include <linux/delay.h>
32 #include <linux/slab.h>
33 #include <linux/init.h>
34 #include <linux/pci.h>
35 #include <asm/irq.h>
36 #include <asm/io.h>
37
38 #include <linux/i2c.h>
39 #include <linux/i2c-algo-pcf.h>
40 #include <linux/i2c-elektor.h>
41 #include "i2c-pcf8584.h"
42
43 #define DEFAULT_BASE 0x330
44
45 static int base   = 0;
46 static int irq    = 0;
47 static int clock  = 0x1c;
48 static int own    = 0x55;
49 static int mmapped = 0;
50 static int i2c_debug = 0;
51
52 /* vdovikin: removed static struct i2c_pcf_isa gpi; code - 
53   this module in real supports only one device, due to missing arguments
54   in some functions, called from the algo-pcf module. Sometimes it's
55   need to be rewriten - but for now just remove this for simpler reading */
56
57 static wait_queue_head_t pcf_wait;
58 static int pcf_pending;
59
60 /* ----- global defines ----------------------------------------------- */
61 #define DEB(x)  if (i2c_debug>=1) x
62 #define DEB2(x) if (i2c_debug>=2) x
63 #define DEB3(x) if (i2c_debug>=3) x
64 #define DEBE(x) x       /* error messages                               */
65
66 /* ----- local functions ---------------------------------------------- */
67
68 static void pcf_isa_setbyte(void *data, int ctl, int val)
69 {
70         int address = ctl ? (base + 1) : base;
71
72         if (ctl && irq) {
73                 val |= I2C_PCF_ENI;
74         }
75
76         DEB3(printk(KERN_DEBUG "i2c-elektor.o: Write 0x%X 0x%02X\n", address, val & 255));
77
78         switch (mmapped) {
79         case 0: /* regular I/O */
80                 outb(val, address);
81                 break;
82         case 2: /* double mapped I/O needed for UP2000 board,
83                    I don't know why this... */
84                 writeb(val, address);
85                 /* fall */
86         case 1: /* memory mapped I/O */
87                 writeb(val, address);
88                 break;
89         }
90 }
91
92 static int pcf_isa_getbyte(void *data, int ctl)
93 {
94         int address = ctl ? (base + 1) : base;
95         int val = mmapped ? readb(address) : inb(address);
96
97         DEB3(printk(KERN_DEBUG "i2c-elektor.o: Read 0x%X 0x%02X\n", address, val));
98
99         return (val);
100 }
101
102 static int pcf_isa_getown(void *data)
103 {
104         return (own);
105 }
106
107
108 static int pcf_isa_getclock(void *data)
109 {
110         return (clock);
111 }
112
113 static void pcf_isa_waitforpin(void) {
114
115         int timeout = 2;
116
117         if (irq > 0) {
118                 cli();
119                 if (pcf_pending == 0) {
120                         interruptible_sleep_on_timeout(&pcf_wait, timeout*HZ );
121                 } else
122                         pcf_pending = 0;
123                 sti();
124         } else {
125                 udelay(100);
126         }
127 }
128
129
130 static void pcf_isa_handler(int this_irq, void *dev_id, struct pt_regs *regs) {
131         pcf_pending = 1;
132         wake_up_interruptible(&pcf_wait);
133 }
134
135
136 static int pcf_isa_init(void)
137 {
138         if (!mmapped) {
139                 if (check_region(base, 2) < 0 ) {
140                         printk(KERN_ERR
141                                "i2c-elektor.o: requested I/O region (0x%X:2) "
142                                "is in use.\n", base);
143                         return -ENODEV;
144                 } else {
145                         request_region(base, 2, "i2c (isa bus adapter)");
146                 }
147         }
148         if (irq > 0) {
149                 if (request_irq(irq, pcf_isa_handler, 0, "PCF8584", 0) < 0) {
150                         printk(KERN_ERR "i2c-elektor.o: Request irq%d failed\n", irq);
151                         irq = 0;
152                 } else
153                         enable_irq(irq);
154         }
155         return 0;
156 }
157
158
159 static void __exit pcf_isa_exit(void)
160 {
161         if (irq > 0) {
162                 disable_irq(irq);
163                 free_irq(irq, 0);
164         }
165         if (!mmapped) {
166                 release_region(base , 2);
167         }
168 }
169
170
171 static int pcf_isa_reg(struct i2c_client *client)
172 {
173         return 0;
174 }
175
176
177 static int pcf_isa_unreg(struct i2c_client *client)
178 {
179         return 0;
180 }
181
182 static void pcf_isa_inc_use(struct i2c_adapter *adap)
183 {
184 #ifdef MODULE
185         MOD_INC_USE_COUNT;
186 #endif
187 }
188
189 static void pcf_isa_dec_use(struct i2c_adapter *adap)
190 {
191 #ifdef MODULE
192         MOD_DEC_USE_COUNT;
193 #endif
194 }
195
196
197 /* ------------------------------------------------------------------------
198  * Encapsulate the above functions in the correct operations structure.
199  * This is only done when more than one hardware adapter is supported.
200  */
201 static struct i2c_algo_pcf_data pcf_isa_data = {
202         .setpcf         = pcf_isa_setbyte,
203         .getpcf         = pcf_isa_getbyte,
204         .getown         = pcf_isa_getown,
205         .getclock       = pcf_isa_getclock,
206         .waitforpin     = pcf_isa_waitforpin,
207         .udelay         = 10,
208         .mdelay         = 10,
209         .timeout        = HZ,
210 };
211
212 static struct i2c_adapter pcf_isa_ops = {
213         .name              = "PCF8584 ISA adapter",
214         .id                = I2C_HW_P_ELEK,
215         .algo_data         = &pcf_isa_data,
216         .inc_use           = pcf_isa_inc_use,
217         .dec_use           = pcf_isa_dec_use,
218         .client_register   = pcf_isa_reg,
219         .client_unregister = pcf_isa_unreg,
220 };
221
222 int __init i2c_pcfisa_init(void) 
223 {
224 #ifdef __alpha__
225         /* check to see we have memory mapped PCF8584 connected to the 
226         Cypress cy82c693 PCI-ISA bridge as on UP2000 board */
227         if ((base == 0) && pci_present()) {
228                 
229                 struct pci_dev *cy693_dev =
230                     pci_find_device(PCI_VENDOR_ID_CONTAQ, 
231                                     PCI_DEVICE_ID_CONTAQ_82C693, NULL);
232
233                 if (cy693_dev) {
234                         char config;
235                         /* yeap, we've found cypress, let's check config */
236                         if (!pci_read_config_byte(cy693_dev, 0x47, &config)) {
237                                 
238                                 DEB3(printk(KERN_DEBUG "i2c-elektor.o: found cy82c693, config register 0x47 = 0x%02x.\n", config));
239
240                                 /* UP2000 board has this register set to 0xe1,
241                                    but the most significant bit as seems can be 
242                                    reset during the proper initialisation
243                                    sequence if guys from API decides to do that
244                                    (so, we can even enable Tsunami Pchip
245                                    window for the upper 1 Gb) */
246
247                                 /* so just check for ROMCS at 0xe0000,
248                                    ROMCS enabled for writes
249                                    and external XD Bus buffer in use. */
250                                 if ((config & 0x7f) == 0x61) {
251                                         /* seems to be UP2000 like board */
252                                         base = 0xe0000;
253                                         /* I don't know why we need to
254                                            write twice */
255                                         mmapped = 2;
256                                         /* UP2000 drives ISA with
257                                            8.25 MHz (PCI/4) clock
258                                            (this can be read from cypress) */
259                                         clock = I2C_PCF_CLK | I2C_PCF_TRNS90;
260                                         printk(KERN_INFO "i2c-elektor.o: found API UP2000 like board, will probe PCF8584 later.\n");
261                                 }
262                         }
263                 }
264         }
265 #endif
266
267         /* sanity checks for mmapped I/O */
268         if (mmapped && base < 0xc8000) {
269                 printk(KERN_ERR "i2c-elektor.o: incorrect base address (0x%0X) specified for mmapped I/O.\n", base);
270                 return -ENODEV;
271         }
272
273         printk(KERN_INFO "i2c-elektor.o: i2c pcf8584-isa adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE);
274
275         if (base == 0) {
276                 base = DEFAULT_BASE;
277         }
278
279         init_waitqueue_head(&pcf_wait);
280         if (pcf_isa_init() == 0) {
281                 if (i2c_pcf_add_bus(&pcf_isa_ops) < 0)
282                         return -ENODEV;
283         } else {
284                 return -ENODEV;
285         }
286         
287         printk(KERN_DEBUG "i2c-elektor.o: found device at %#x.\n", base);
288
289         return 0;
290 }
291
292
293 EXPORT_NO_SYMBOLS;
294
295 #ifdef MODULE
296 MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
297 MODULE_DESCRIPTION("I2C-Bus adapter routines for PCF8584 ISA bus adapter");
298 MODULE_LICENSE("GPL");
299
300 MODULE_PARM(base, "i");
301 MODULE_PARM(irq, "i");
302 MODULE_PARM(clock, "i");
303 MODULE_PARM(own, "i");
304 MODULE_PARM(mmapped, "i");
305 MODULE_PARM(i2c_debug, "i");
306
307 int init_module(void) 
308 {
309         return i2c_pcfisa_init();
310 }
311
312 void cleanup_module(void) 
313 {
314         i2c_pcf_del_bus(&pcf_isa_ops);
315         pcf_isa_exit();
316 }
317
318 #endif