root/i2c/trunk/kernel/i2c-elektor.c @ 3872

Revision 3872, 7.9 KB (checked in by khali, 10 years ago)

Pointless printk changes (part of the Linux 2.4 merge process).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
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/interrupt.h>
35#include <linux/pci.h>
36#include <linux/wait.h>
37#include "i2c.h"
38#include "i2c-algo-pcf.h"
39#include <asm/io.h>
40#include <asm/irq.h>
41
42#define DEFAULT_BASE 0x330
43
44static int base;
45static int irq;
46static int clock  = 0x1c;
47static int own    = 0x55;
48static int mmapped;
49static int i2c_debug;
50
51/* vdovikin: removed static struct i2c_pcf_isa gpi; code -
52  this module in real supports only one device, due to missing arguments
53  in some functions, called from the algo-pcf module. Sometimes it's
54  need to be rewriten - but for now just remove this for simpler reading */
55
56static wait_queue_head_t pcf_wait;
57static int pcf_pending;
58static spinlock_t irq_driver_lock = SPIN_LOCK_UNLOCKED;
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
67/* compatibility */
68#ifndef isa_readb
69#define isa_readb readb
70#endif
71
72#ifndef isa_writeb
73#define isa_writeb writeb
74#endif
75
76/* ----- local functions ---------------------------------------------- */
77
78static void pcf_isa_setbyte(void *data, int ctl, int val)
79{
80        int address = ctl ? (base + 1) : base;
81
82        /* enable irq if any specified for serial operation */
83        if (ctl && irq && (val & I2C_PCF_ESO)) {
84                val |= I2C_PCF_ENI;
85        }
86
87        DEB3(printk(KERN_DEBUG "i2c-elektor.o: Write 0x%X 0x%02X\n", address, val & 255));
88
89        switch (mmapped) {
90        case 0: /* regular I/O */
91                outb(val, address);
92                break;
93        case 2: /* double mapped I/O needed for UP2000 board,
94                   I don't know why this... */
95                isa_writeb(val, address);
96                /* fall */
97        case 1: /* memory mapped I/O */
98                isa_writeb(val, address);
99                break;
100        }
101}
102
103static int pcf_isa_getbyte(void *data, int ctl)
104{
105        int address = ctl ? (base + 1) : base;
106        int val = mmapped ? isa_readb(address) : inb(address);
107
108        DEB3(printk(KERN_DEBUG "i2c-elektor.o: Read 0x%X 0x%02X\n", address, val));
109
110        return (val);
111}
112
113static int pcf_isa_getown(void *data)
114{
115        return (own);
116}
117
118
119static int pcf_isa_getclock(void *data)
120{
121        return (clock);
122}
123
124static void pcf_isa_waitforpin(void) {
125
126        int timeout = 2;
127
128        if (irq > 0) {
129                spin_lock_irq(&irq_driver_lock);
130                if (pcf_pending == 0) {
131                        interruptible_sleep_on_timeout(&pcf_wait, timeout*HZ );
132                } else
133                        pcf_pending = 0;
134                spin_unlock_irq(&irq_driver_lock);
135        } else {
136                udelay(100);
137        }
138}
139
140
141static void pcf_isa_handler(int this_irq, void *dev_id, struct pt_regs *regs) {
142        pcf_pending = 1;
143        wake_up_interruptible(&pcf_wait);
144}
145
146
147static int pcf_isa_init(void)
148{
149        if (!mmapped) {
150                if (!request_region(base, 2, "i2c (isa bus adapter)")) {
151                        printk(KERN_ERR
152                               "i2c-elektor.o: requested I/O region (0x%X:2) "
153                               "is in use.\n", base);
154                        return -ENODEV;
155                }
156        }
157        if (irq > 0) {
158                if (request_irq(irq, pcf_isa_handler, 0, "PCF8584", 0) < 0) {
159                        printk(KERN_ERR "i2c-elektor.o: Request irq%d failed\n", irq);
160                        irq = 0;
161                } else
162                        enable_irq(irq);
163        }
164        return 0;
165}
166
167
168/* ------------------------------------------------------------------------
169 * Encapsulate the above functions in the correct operations structure.
170 * This is only done when more than one hardware adapter is supported.
171 */
172static struct i2c_algo_pcf_data pcf_isa_data = {
173        .setpcf     = pcf_isa_setbyte,
174        .getpcf     = pcf_isa_getbyte,
175        .getown     = pcf_isa_getown,
176        .getclock   = pcf_isa_getclock,
177        .waitforpin = pcf_isa_waitforpin,
178        .udelay     = 10,
179        .mdelay     = 10,
180        .timeout    = HZ,
181};
182
183static struct i2c_adapter pcf_isa_ops = {
184        .owner             = THIS_MODULE,
185        .name              = "PCF8584 ISA adapter",
186        .id                = I2C_HW_P_ELEK,
187        .algo_data         = &pcf_isa_data,
188};
189
190static int __init i2c_pcfisa_init(void) 
191{
192#ifdef __alpha__
193        /* check to see we have memory mapped PCF8584 connected to the
194        Cypress cy82c693 PCI-ISA bridge as on UP2000 board */
195        if ((base == 0) && pci_present()) {
196               
197                struct pci_dev *cy693_dev =
198                    pci_find_device(PCI_VENDOR_ID_CONTAQ, 
199                                    PCI_DEVICE_ID_CONTAQ_82C693, NULL);
200
201                if (cy693_dev) {
202                        char config;
203                        /* yeap, we've found cypress, let's check config */
204                        if (!pci_read_config_byte(cy693_dev, 0x47, &config)) {
205                               
206                                DEB3(printk(KERN_DEBUG "i2c-elektor.o: found cy82c693, config register 0x47 = 0x%02x.\n", config));
207
208                                /* UP2000 board has this register set to 0xe1,
209                                   but the most significant bit as seems can be
210                                   reset during the proper initialisation
211                                   sequence if guys from API decides to do that
212                                   (so, we can even enable Tsunami Pchip
213                                   window for the upper 1 Gb) */
214
215                                /* so just check for ROMCS at 0xe0000,
216                                   ROMCS enabled for writes
217                                   and external XD Bus buffer in use. */
218                                if ((config & 0x7f) == 0x61) {
219                                        /* seems to be UP2000 like board */
220                                        base = 0xe0000;
221                                        /* I don't know why we need to
222                                           write twice */
223                                        mmapped = 2;
224                                        /* UP2000 drives ISA with
225                                           8.25 MHz (PCI/4) clock
226                                           (this can be read from cypress) */
227                                        clock = I2C_PCF_CLK | I2C_PCF_TRNS90;
228                                        printk(KERN_INFO "i2c-elektor.o: found API UP2000 like board, will probe PCF8584 later.\n");
229                                }
230                        }
231                }
232        }
233#endif
234
235        /* sanity checks for mmapped I/O */
236        if (mmapped && base < 0xc8000) {
237                printk(KERN_ERR "i2c-elektor.o: incorrect base address (0x%0X) specified for mmapped I/O.\n", base);
238                return -ENODEV;
239        }
240
241        printk(KERN_INFO "i2c-elektor.o: i2c pcf8584-isa adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE);
242
243        if (base == 0) {
244                base = DEFAULT_BASE;
245        }
246
247        init_waitqueue_head(&pcf_wait);
248        if (pcf_isa_init())
249                return -ENODEV;
250        if (i2c_pcf_add_bus(&pcf_isa_ops) < 0)
251                goto fail;
252       
253        printk(KERN_DEBUG "i2c-elektor.o: found device at %#x.\n", base);
254
255        return 0;
256
257 fail:
258        if (irq > 0) {
259                disable_irq(irq);
260                free_irq(irq, 0);
261        }
262
263        if (!mmapped)
264                release_region(base , 2);
265        return -ENODEV;
266}
267
268
269static void __exit i2c_pcfisa_exit(void)
270{
271        i2c_pcf_del_bus(&pcf_isa_ops);
272
273        if (irq > 0) {
274                disable_irq(irq);
275                free_irq(irq, 0);
276        }
277
278        if (!mmapped)
279                release_region(base , 2);
280}
281
282MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
283MODULE_DESCRIPTION("I2C-Bus adapter routines for PCF8584 ISA bus adapter");
284MODULE_LICENSE("GPL");
285
286MODULE_PARM(base, "i");
287MODULE_PARM(irq, "i");
288MODULE_PARM(clock, "i");
289MODULE_PARM(own, "i");
290MODULE_PARM(mmapped, "i");
291MODULE_PARM(i2c_debug, "i");
292
293module_init(i2c_pcfisa_init);
294module_exit(i2c_pcfisa_exit);
Note: See TracBrowser for help on using the browser.