1 /* ------------------------------------------------------------------------- */
2 /* i2c-elektor.c i2c-hw access for PCF8584 style isa bus adaptes */
3 /* ------------------------------------------------------------------------- */
4 /* Copyright (C) 1995-97 Simon G. Vogl
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.
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.
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 /* ------------------------------------------------------------------------- */
22 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
23 Frodo Looijaard <frodol@dds.nl> */
25 /* Partialy rewriten by Oleg I. Vdovikin for mmapped support of
26 for Alpha Processor Inc. UP-2000(+) boards */
28 #include <linux/config.h>
29 #include <linux/kernel.h>
30 #include <linux/ioport.h>
31 #include <linux/module.h>
32 #include <linux/delay.h>
33 #include <linux/slab.h>
34 #include <linux/init.h>
35 #include <linux/interrupt.h>
36 #include <linux/pci.h>
37 #include <linux/wait.h>
39 #include <linux/i2c.h>
40 #include <linux/i2c-algo-pcf.h>
45 #include "../algos/i2c-algo-pcf.h"
47 #define DEFAULT_BASE 0x330
51 static int clock
= 0x1c;
52 static int own
= 0x55;
55 /* vdovikin: removed static struct i2c_pcf_isa gpi; code -
56 this module in real supports only one device, due to missing arguments
57 in some functions, called from the algo-pcf module. Sometimes it's
58 need to be rewriten - but for now just remove this for simpler reading */
60 static wait_queue_head_t pcf_wait
;
61 static int pcf_pending
;
63 /* ----- local functions ---------------------------------------------- */
65 static void pcf_isa_setbyte(void *data
, int ctl
, int val
)
67 int address
= ctl
? (base
+ 1) : base
;
69 /* enable irq if any specified for serial operation */
70 if (ctl
&& irq
&& (val
& I2C_PCF_ESO
)) {
74 pr_debug("i2c-elektor: Write 0x%X 0x%02X\n", address
, val
& 255);
77 case 0: /* regular I/O */
80 case 2: /* double mapped I/O needed for UP2000 board,
81 I don't know why this... */
84 case 1: /* memory mapped I/O */
90 static int pcf_isa_getbyte(void *data
, int ctl
)
92 int address
= ctl
? (base
+ 1) : base
;
93 int val
= mmapped
? readb(address
) : inb(address
);
95 pr_debug("i2c-elektor: Read 0x%X 0x%02X\n", address
, val
);
100 static int pcf_isa_getown(void *data
)
106 static int pcf_isa_getclock(void *data
)
111 static void pcf_isa_waitforpin(void) {
117 if (pcf_pending
== 0) {
118 interruptible_sleep_on_timeout(&pcf_wait
, timeout
*HZ
);
128 static irqreturn_t
pcf_isa_handler(int this_irq
, void *dev_id
, struct pt_regs
*regs
) {
130 wake_up_interruptible(&pcf_wait
);
135 static int pcf_isa_init(void)
138 if (!request_region(base
, 2, "i2c (isa bus adapter)")) {
140 "i2c-elektor: requested I/O region (0x%X:2) "
141 "is in use.\n", base
);
146 if (request_irq(irq
, pcf_isa_handler
, 0, "PCF8584", NULL
) < 0) {
147 printk(KERN_ERR
"i2c-elektor: Request irq%d failed\n", irq
);
155 /* ------------------------------------------------------------------------
156 * Encapsulate the above functions in the correct operations structure.
157 * This is only done when more than one hardware adapter is supported.
159 static struct i2c_algo_pcf_data pcf_isa_data
= {
160 .setpcf
= pcf_isa_setbyte
,
161 .getpcf
= pcf_isa_getbyte
,
162 .getown
= pcf_isa_getown
,
163 .getclock
= pcf_isa_getclock
,
164 .waitforpin
= pcf_isa_waitforpin
,
170 static struct i2c_adapter pcf_isa_ops
= {
171 .owner
= THIS_MODULE
,
173 .algo_data
= &pcf_isa_data
,
174 .name
= "PCF8584 ISA adapter",
177 static int __init
i2c_pcfisa_init(void)
180 /* check to see we have memory mapped PCF8584 connected to the
181 Cypress cy82c693 PCI-ISA bridge as on UP2000 board */
184 struct pci_dev
*cy693_dev
=
185 pci_find_device(PCI_VENDOR_ID_CONTAQ
,
186 PCI_DEVICE_ID_CONTAQ_82C693
, NULL
);
190 /* yeap, we've found cypress, let's check config */
191 if (!pci_read_config_byte(cy693_dev
, 0x47, &config
)) {
193 pr_debug("i2c-elektor: found cy82c693, config register 0x47 = 0x%02x.\n", config
);
195 /* UP2000 board has this register set to 0xe1,
196 but the most significant bit as seems can be
197 reset during the proper initialisation
198 sequence if guys from API decides to do that
199 (so, we can even enable Tsunami Pchip
200 window for the upper 1 Gb) */
202 /* so just check for ROMCS at 0xe0000,
203 ROMCS enabled for writes
204 and external XD Bus buffer in use. */
205 if ((config
& 0x7f) == 0x61) {
206 /* seems to be UP2000 like board */
208 /* I don't know why we need to
211 /* UP2000 drives ISA with
212 8.25 MHz (PCI/4) clock
213 (this can be read from cypress) */
214 clock
= I2C_PCF_CLK
| I2C_PCF_TRNS90
;
215 printk(KERN_INFO
"i2c-elektor: found API UP2000 like board, will probe PCF8584 later.\n");
222 /* sanity checks for mmapped I/O */
223 if (mmapped
&& base
< 0xc8000) {
224 printk(KERN_ERR
"i2c-elektor: incorrect base address (0x%0X) specified for mmapped I/O.\n", base
);
228 printk(KERN_INFO
"i2c-elektor: i2c pcf8584-isa adapter driver\n");
234 init_waitqueue_head(&pcf_wait
);
237 if (i2c_pcf_add_bus(&pcf_isa_ops
) < 0)
240 printk(KERN_ERR
"i2c-elektor: found device at %#x.\n", base
);
251 release_region(base
, 2);
255 static void i2c_pcfisa_exit(void)
257 i2c_pcf_del_bus(&pcf_isa_ops
);
265 release_region(base
, 2);
268 MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
269 MODULE_DESCRIPTION("I2C-Bus adapter routines for PCF8584 ISA bus adapter");
270 MODULE_LICENSE("GPL");
272 module_param(base
, int, 0);
273 module_param(irq
, int, 0);
274 module_param(clock
, int, 0);
275 module_param(own
, int, 0);
276 module_param(mmapped
, int, 0);
278 module_init(i2c_pcfisa_init
);
279 module_exit(i2c_pcfisa_exit
);