include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[linux-2.6-block.git] / drivers / i2c / busses / i2c-elektor.c
CommitLineData
1da177e4
LT
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
96de0e25 22/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
1da177e4
LT
23 Frodo Looijaard <frodol@dds.nl> */
24
fe3d6a99 25/* Partialy rewriten by Oleg I. Vdovikin for mmapped support of
1da177e4
LT
26 for Alpha Processor Inc. UP-2000(+) boards */
27
1da177e4
LT
28#include <linux/kernel.h>
29#include <linux/ioport.h>
30#include <linux/module.h>
31#include <linux/delay.h>
1da177e4
LT
32#include <linux/init.h>
33#include <linux/interrupt.h>
34#include <linux/pci.h>
35#include <linux/wait.h>
36
4a5d3030 37#include <linux/isa.h>
1da177e4
LT
38#include <linux/i2c.h>
39#include <linux/i2c-algo-pcf.h>
40
41#include <asm/io.h>
42#include <asm/irq.h>
43
44#include "../algos/i2c-algo-pcf.h"
45
46#define DEFAULT_BASE 0x330
47
48static int base;
3634ff6a
ST
49static u8 __iomem *base_iomem;
50
1da177e4
LT
51static int irq;
52static int clock = 0x1c;
53static int own = 0x55;
54static int mmapped;
55
fe3d6a99 56/* vdovikin: removed static struct i2c_pcf_isa gpi; code -
1da177e4
LT
57 this module in real supports only one device, due to missing arguments
58 in some functions, called from the algo-pcf module. Sometimes it's
59 need to be rewriten - but for now just remove this for simpler reading */
60
61static wait_queue_head_t pcf_wait;
62static int pcf_pending;
63static spinlock_t lock;
64
fe3d6a99
ST
65static struct i2c_adapter pcf_isa_ops;
66
1da177e4
LT
67/* ----- local functions ---------------------------------------------- */
68
69static void pcf_isa_setbyte(void *data, int ctl, int val)
70{
3634ff6a 71 u8 __iomem *address = ctl ? (base_iomem + 1) : base_iomem;
1da177e4
LT
72
73 /* enable irq if any specified for serial operation */
74 if (ctl && irq && (val & I2C_PCF_ESO)) {
75 val |= I2C_PCF_ENI;
76 }
77
fe3d6a99 78 pr_debug("%s: Write %p 0x%02X\n", pcf_isa_ops.name, address, val);
3634ff6a
ST
79 iowrite8(val, address);
80#ifdef __alpha__
81 /* API UP2000 needs some hardware fudging to make the write stick */
82 iowrite8(val, address);
83#endif
1da177e4
LT
84}
85
86static int pcf_isa_getbyte(void *data, int ctl)
87{
3634ff6a
ST
88 u8 __iomem *address = ctl ? (base_iomem + 1) : base_iomem;
89 int val = ioread8(address);
1da177e4 90
fe3d6a99 91 pr_debug("%s: Read %p 0x%02X\n", pcf_isa_ops.name, address, val);
1da177e4
LT
92 return (val);
93}
94
95static int pcf_isa_getown(void *data)
96{
97 return (own);
98}
99
100
101static int pcf_isa_getclock(void *data)
102{
103 return (clock);
104}
105
08e5338d
DM
106static void pcf_isa_waitforpin(void *data)
107{
1da177e4
LT
108 DEFINE_WAIT(wait);
109 int timeout = 2;
110 unsigned long flags;
111
112 if (irq > 0) {
113 spin_lock_irqsave(&lock, flags);
114 if (pcf_pending == 0) {
115 spin_unlock_irqrestore(&lock, flags);
116 prepare_to_wait(&pcf_wait, &wait, TASK_INTERRUPTIBLE);
117 if (schedule_timeout(timeout*HZ)) {
118 spin_lock_irqsave(&lock, flags);
119 if (pcf_pending == 1) {
120 pcf_pending = 0;
121 }
122 spin_unlock_irqrestore(&lock, flags);
123 }
124 finish_wait(&pcf_wait, &wait);
125 } else {
126 pcf_pending = 0;
127 spin_unlock_irqrestore(&lock, flags);
128 }
129 } else {
130 udelay(100);
131 }
132}
133
134
7d12e780 135static irqreturn_t pcf_isa_handler(int this_irq, void *dev_id) {
1da177e4
LT
136 spin_lock(&lock);
137 pcf_pending = 1;
138 spin_unlock(&lock);
139 wake_up_interruptible(&pcf_wait);
140 return IRQ_HANDLED;
141}
142
143
144static int pcf_isa_init(void)
145{
146 spin_lock_init(&lock);
147 if (!mmapped) {
fe3d6a99
ST
148 if (!request_region(base, 2, pcf_isa_ops.name)) {
149 printk(KERN_ERR "%s: requested I/O region (%#x:2) is "
150 "in use\n", pcf_isa_ops.name, base);
1da177e4
LT
151 return -ENODEV;
152 }
3634ff6a
ST
153 base_iomem = ioport_map(base, 2);
154 if (!base_iomem) {
fe3d6a99
ST
155 printk(KERN_ERR "%s: remap of I/O region %#x failed\n",
156 pcf_isa_ops.name, base);
3634ff6a
ST
157 release_region(base, 2);
158 return -ENODEV;
159 }
160 } else {
fe3d6a99
ST
161 if (!request_mem_region(base, 2, pcf_isa_ops.name)) {
162 printk(KERN_ERR "%s: requested memory region (%#x:2) "
163 "is in use\n", pcf_isa_ops.name, base);
3634ff6a
ST
164 return -ENODEV;
165 }
166 base_iomem = ioremap(base, 2);
167 if (base_iomem == NULL) {
fe3d6a99
ST
168 printk(KERN_ERR "%s: remap of memory region %#x "
169 "failed\n", pcf_isa_ops.name, base);
3634ff6a
ST
170 release_mem_region(base, 2);
171 return -ENODEV;
172 }
1da177e4 173 }
fe3d6a99 174 pr_debug("%s: registers %#x remapped to %p\n", pcf_isa_ops.name, base,
3634ff6a
ST
175 base_iomem);
176
1da177e4 177 if (irq > 0) {
fe3d6a99
ST
178 if (request_irq(irq, pcf_isa_handler, 0, pcf_isa_ops.name,
179 NULL) < 0) {
180 printk(KERN_ERR "%s: Request irq%d failed\n",
181 pcf_isa_ops.name, irq);
1da177e4
LT
182 irq = 0;
183 } else
184 enable_irq(irq);
185 }
186 return 0;
187}
188
189/* ------------------------------------------------------------------------
190 * Encapsulate the above functions in the correct operations structure.
191 * This is only done when more than one hardware adapter is supported.
192 */
193static struct i2c_algo_pcf_data pcf_isa_data = {
194 .setpcf = pcf_isa_setbyte,
195 .getpcf = pcf_isa_getbyte,
196 .getown = pcf_isa_getown,
197 .getclock = pcf_isa_getclock,
198 .waitforpin = pcf_isa_waitforpin,
1da177e4
LT
199};
200
201static struct i2c_adapter pcf_isa_ops = {
202 .owner = THIS_MODULE,
3401b2ff 203 .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
1da177e4 204 .algo_data = &pcf_isa_data,
fe3d6a99 205 .name = "i2c-elektor",
1da177e4
LT
206};
207
4a5d3030 208static int __devinit elektor_match(struct device *dev, unsigned int id)
1da177e4
LT
209{
210#ifdef __alpha__
fe3d6a99 211 /* check to see we have memory mapped PCF8584 connected to the
1da177e4
LT
212 Cypress cy82c693 PCI-ISA bridge as on UP2000 board */
213 if (base == 0) {
214 struct pci_dev *cy693_dev;
fe3d6a99
ST
215
216 cy693_dev = pci_get_device(PCI_VENDOR_ID_CONTAQ,
1da177e4
LT
217 PCI_DEVICE_ID_CONTAQ_82C693, NULL);
218 if (cy693_dev) {
3634ff6a 219 unsigned char config;
1da177e4
LT
220 /* yeap, we've found cypress, let's check config */
221 if (!pci_read_config_byte(cy693_dev, 0x47, &config)) {
fe3d6a99 222
4a5d3030
JD
223 dev_dbg(dev, "found cy82c693, config "
224 "register 0x47 = 0x%02x\n", config);
1da177e4
LT
225
226 /* UP2000 board has this register set to 0xe1,
fe3d6a99 227 but the most significant bit as seems can be
1da177e4 228 reset during the proper initialisation
fe3d6a99
ST
229 sequence if guys from API decides to do that
230 (so, we can even enable Tsunami Pchip
231 window for the upper 1 Gb) */
1da177e4
LT
232
233 /* so just check for ROMCS at 0xe0000,
fe3d6a99 234 ROMCS enabled for writes
1da177e4
LT
235 and external XD Bus buffer in use. */
236 if ((config & 0x7f) == 0x61) {
237 /* seems to be UP2000 like board */
238 base = 0xe0000;
3634ff6a 239 mmapped = 1;
fe3d6a99 240 /* UP2000 drives ISA with
1da177e4
LT
241 8.25 MHz (PCI/4) clock
242 (this can be read from cypress) */
243 clock = I2C_PCF_CLK | I2C_PCF_TRNS90;
4a5d3030
JD
244 dev_info(dev, "found API UP2000 like "
245 "board, will probe PCF8584 "
246 "later\n");
1da177e4
LT
247 }
248 }
249 pci_dev_put(cy693_dev);
250 }
251 }
252#endif
253
254 /* sanity checks for mmapped I/O */
255 if (mmapped && base < 0xc8000) {
4a5d3030
JD
256 dev_err(dev, "incorrect base address (%#x) specified "
257 "for mmapped I/O\n", base);
258 return 0;
1da177e4
LT
259 }
260
1da177e4
LT
261 if (base == 0) {
262 base = DEFAULT_BASE;
263 }
4a5d3030
JD
264 return 1;
265}
1da177e4 266
4a5d3030
JD
267static int __devinit elektor_probe(struct device *dev, unsigned int id)
268{
1da177e4
LT
269 init_waitqueue_head(&pcf_wait);
270 if (pcf_isa_init())
271 return -ENODEV;
4a5d3030 272 pcf_isa_ops.dev.parent = dev;
1da177e4
LT
273 if (i2c_pcf_add_bus(&pcf_isa_ops) < 0)
274 goto fail;
fe3d6a99 275
4a5d3030 276 dev_info(dev, "found device at %#x\n", base);
1da177e4
LT
277
278 return 0;
279
280 fail:
281 if (irq > 0) {
282 disable_irq(irq);
283 free_irq(irq, NULL);
284 }
285
3634ff6a
ST
286 if (!mmapped) {
287 ioport_unmap(base_iomem);
fe3d6a99 288 release_region(base, 2);
3634ff6a
ST
289 } else {
290 iounmap(base_iomem);
291 release_mem_region(base, 2);
292 }
1da177e4
LT
293 return -ENODEV;
294}
295
4a5d3030 296static int __devexit elektor_remove(struct device *dev, unsigned int id)
1da177e4 297{
3269711b 298 i2c_del_adapter(&pcf_isa_ops);
1da177e4
LT
299
300 if (irq > 0) {
301 disable_irq(irq);
302 free_irq(irq, NULL);
303 }
304
3634ff6a
ST
305 if (!mmapped) {
306 ioport_unmap(base_iomem);
fe3d6a99 307 release_region(base, 2);
3634ff6a
ST
308 } else {
309 iounmap(base_iomem);
310 release_mem_region(base, 2);
311 }
4a5d3030
JD
312
313 return 0;
314}
315
316static struct isa_driver i2c_elektor_driver = {
317 .match = elektor_match,
318 .probe = elektor_probe,
319 .remove = __devexit_p(elektor_remove),
320 .driver = {
321 .owner = THIS_MODULE,
322 .name = "i2c-elektor",
323 },
324};
325
326static int __init i2c_pcfisa_init(void)
327{
328 return isa_register_driver(&i2c_elektor_driver, 1);
329}
330
331static void __exit i2c_pcfisa_exit(void)
332{
333 isa_unregister_driver(&i2c_elektor_driver);
1da177e4
LT
334}
335
336MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
337MODULE_DESCRIPTION("I2C-Bus adapter routines for PCF8584 ISA bus adapter");
338MODULE_LICENSE("GPL");
339
340module_param(base, int, 0);
341module_param(irq, int, 0);
342module_param(clock, int, 0);
343module_param(own, int, 0);
344module_param(mmapped, int, 0);
345
346module_init(i2c_pcfisa_init);
347module_exit(i2c_pcfisa_exit);