aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-elektor.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses/i2c-elektor.c')
-rw-r--r--drivers/i2c/busses/i2c-elektor.c138
1 files changed, 84 insertions, 54 deletions
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index 6930b660e508..59f8308c2356 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -22,7 +22,7 @@
22/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even 22/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
23 Frodo Looijaard <frodol@dds.nl> */ 23 Frodo Looijaard <frodol@dds.nl> */
24 24
25/* Partialy rewriten by Oleg I. Vdovikin for mmapped support of 25/* Partialy rewriten by Oleg I. Vdovikin for mmapped support of
26 for Alpha Processor Inc. UP-2000(+) boards */ 26 for Alpha Processor Inc. UP-2000(+) boards */
27 27
28#include <linux/kernel.h> 28#include <linux/kernel.h>
@@ -46,12 +46,14 @@
46#define DEFAULT_BASE 0x330 46#define DEFAULT_BASE 0x330
47 47
48static int base; 48static int base;
49static u8 __iomem *base_iomem;
50
49static int irq; 51static int irq;
50static int clock = 0x1c; 52static int clock = 0x1c;
51static int own = 0x55; 53static int own = 0x55;
52static int mmapped; 54static int mmapped;
53 55
54/* vdovikin: removed static struct i2c_pcf_isa gpi; code - 56/* vdovikin: removed static struct i2c_pcf_isa gpi; code -
55 this module in real supports only one device, due to missing arguments 57 this module in real supports only one device, due to missing arguments
56 in some functions, called from the algo-pcf module. Sometimes it's 58 in some functions, called from the algo-pcf module. Sometimes it's
57 need to be rewriten - but for now just remove this for simpler reading */ 59 need to be rewriten - but for now just remove this for simpler reading */
@@ -60,40 +62,33 @@ static wait_queue_head_t pcf_wait;
60static int pcf_pending; 62static int pcf_pending;
61static spinlock_t lock; 63static spinlock_t lock;
62 64
65static struct i2c_adapter pcf_isa_ops;
66
63/* ----- local functions ---------------------------------------------- */ 67/* ----- local functions ---------------------------------------------- */
64 68
65static void pcf_isa_setbyte(void *data, int ctl, int val) 69static void pcf_isa_setbyte(void *data, int ctl, int val)
66{ 70{
67 int address = ctl ? (base + 1) : base; 71 u8 __iomem *address = ctl ? (base_iomem + 1) : base_iomem;
68 72
69 /* enable irq if any specified for serial operation */ 73 /* enable irq if any specified for serial operation */
70 if (ctl && irq && (val & I2C_PCF_ESO)) { 74 if (ctl && irq && (val & I2C_PCF_ESO)) {
71 val |= I2C_PCF_ENI; 75 val |= I2C_PCF_ENI;
72 } 76 }
73 77
74 pr_debug("i2c-elektor: Write 0x%X 0x%02X\n", address, val & 255); 78 pr_debug("%s: Write %p 0x%02X\n", pcf_isa_ops.name, address, val);
75 79 iowrite8(val, address);
76 switch (mmapped) { 80#ifdef __alpha__
77 case 0: /* regular I/O */ 81 /* API UP2000 needs some hardware fudging to make the write stick */
78 outb(val, address); 82 iowrite8(val, address);
79 break; 83#endif
80 case 2: /* double mapped I/O needed for UP2000 board,
81 I don't know why this... */
82 writeb(val, (void *)address);
83 /* fall */
84 case 1: /* memory mapped I/O */
85 writeb(val, (void *)address);
86 break;
87 }
88} 84}
89 85
90static int pcf_isa_getbyte(void *data, int ctl) 86static int pcf_isa_getbyte(void *data, int ctl)
91{ 87{
92 int address = ctl ? (base + 1) : base; 88 u8 __iomem *address = ctl ? (base_iomem + 1) : base_iomem;
93 int val = mmapped ? readb((void *)address) : inb(address); 89 int val = ioread8(address);
94
95 pr_debug("i2c-elektor: Read 0x%X 0x%02X\n", address, val);
96 90
91 pr_debug("%s: Read %p 0x%02X\n", pcf_isa_ops.name, address, val);
97 return (val); 92 return (val);
98} 93}
99 94
@@ -149,16 +144,40 @@ static int pcf_isa_init(void)
149{ 144{
150 spin_lock_init(&lock); 145 spin_lock_init(&lock);
151 if (!mmapped) { 146 if (!mmapped) {
152 if (!request_region(base, 2, "i2c (isa bus adapter)")) { 147 if (!request_region(base, 2, pcf_isa_ops.name)) {
153 printk(KERN_ERR 148 printk(KERN_ERR "%s: requested I/O region (%#x:2) is "
154 "i2c-elektor: requested I/O region (0x%X:2) " 149 "in use\n", pcf_isa_ops.name, base);
155 "is in use.\n", base); 150 return -ENODEV;
151 }
152 base_iomem = ioport_map(base, 2);
153 if (!base_iomem) {
154 printk(KERN_ERR "%s: remap of I/O region %#x failed\n",
155 pcf_isa_ops.name, base);
156 release_region(base, 2);
157 return -ENODEV;
158 }
159 } else {
160 if (!request_mem_region(base, 2, pcf_isa_ops.name)) {
161 printk(KERN_ERR "%s: requested memory region (%#x:2) "
162 "is in use\n", pcf_isa_ops.name, base);
163 return -ENODEV;
164 }
165 base_iomem = ioremap(base, 2);
166 if (base_iomem == NULL) {
167 printk(KERN_ERR "%s: remap of memory region %#x "
168 "failed\n", pcf_isa_ops.name, base);
169 release_mem_region(base, 2);
156 return -ENODEV; 170 return -ENODEV;
157 } 171 }
158 } 172 }
173 pr_debug("%s: registers %#x remapped to %p\n", pcf_isa_ops.name, base,
174 base_iomem);
175
159 if (irq > 0) { 176 if (irq > 0) {
160 if (request_irq(irq, pcf_isa_handler, 0, "PCF8584", NULL) < 0) { 177 if (request_irq(irq, pcf_isa_handler, 0, pcf_isa_ops.name,
161 printk(KERN_ERR "i2c-elektor: Request irq%d failed\n", irq); 178 NULL) < 0) {
179 printk(KERN_ERR "%s: Request irq%d failed\n",
180 pcf_isa_ops.name, irq);
162 irq = 0; 181 irq = 0;
163 } else 182 } else
164 enable_irq(irq); 183 enable_irq(irq);
@@ -186,47 +205,49 @@ static struct i2c_adapter pcf_isa_ops = {
186 .class = I2C_CLASS_HWMON, 205 .class = I2C_CLASS_HWMON,
187 .id = I2C_HW_P_ELEK, 206 .id = I2C_HW_P_ELEK,
188 .algo_data = &pcf_isa_data, 207 .algo_data = &pcf_isa_data,
189 .name = "PCF8584 ISA adapter", 208 .name = "i2c-elektor",
190}; 209};
191 210
192static int __init i2c_pcfisa_init(void) 211static int __init i2c_pcfisa_init(void)
193{ 212{
194#ifdef __alpha__ 213#ifdef __alpha__
195 /* check to see we have memory mapped PCF8584 connected to the 214 /* check to see we have memory mapped PCF8584 connected to the
196 Cypress cy82c693 PCI-ISA bridge as on UP2000 board */ 215 Cypress cy82c693 PCI-ISA bridge as on UP2000 board */
197 if (base == 0) { 216 if (base == 0) {
198 struct pci_dev *cy693_dev; 217 struct pci_dev *cy693_dev;
199 218
200 cy693_dev = pci_get_device(PCI_VENDOR_ID_CONTAQ, 219 cy693_dev = pci_get_device(PCI_VENDOR_ID_CONTAQ,
201 PCI_DEVICE_ID_CONTAQ_82C693, NULL); 220 PCI_DEVICE_ID_CONTAQ_82C693, NULL);
202 if (cy693_dev) { 221 if (cy693_dev) {
203 char config; 222 unsigned char config;
204 /* yeap, we've found cypress, let's check config */ 223 /* yeap, we've found cypress, let's check config */
205 if (!pci_read_config_byte(cy693_dev, 0x47, &config)) { 224 if (!pci_read_config_byte(cy693_dev, 0x47, &config)) {
206 225
207 pr_debug("i2c-elektor: found cy82c693, config register 0x47 = 0x%02x.\n", config); 226 pr_debug("%s: found cy82c693, config "
227 "register 0x47 = 0x%02x\n",
228 pcf_isa_ops.name, config);
208 229
209 /* UP2000 board has this register set to 0xe1, 230 /* UP2000 board has this register set to 0xe1,
210 but the most significant bit as seems can be 231 but the most significant bit as seems can be
211 reset during the proper initialisation 232 reset during the proper initialisation
212 sequence if guys from API decides to do that 233 sequence if guys from API decides to do that
213 (so, we can even enable Tsunami Pchip 234 (so, we can even enable Tsunami Pchip
214 window for the upper 1 Gb) */ 235 window for the upper 1 Gb) */
215 236
216 /* so just check for ROMCS at 0xe0000, 237 /* so just check for ROMCS at 0xe0000,
217 ROMCS enabled for writes 238 ROMCS enabled for writes
218 and external XD Bus buffer in use. */ 239 and external XD Bus buffer in use. */
219 if ((config & 0x7f) == 0x61) { 240 if ((config & 0x7f) == 0x61) {
220 /* seems to be UP2000 like board */ 241 /* seems to be UP2000 like board */
221 base = 0xe0000; 242 base = 0xe0000;
222 /* I don't know why we need to 243 mmapped = 1;
223 write twice */ 244 /* UP2000 drives ISA with
224 mmapped = 2;
225 /* UP2000 drives ISA with
226 8.25 MHz (PCI/4) clock 245 8.25 MHz (PCI/4) clock
227 (this can be read from cypress) */ 246 (this can be read from cypress) */
228 clock = I2C_PCF_CLK | I2C_PCF_TRNS90; 247 clock = I2C_PCF_CLK | I2C_PCF_TRNS90;
229 printk(KERN_INFO "i2c-elektor: found API UP2000 like board, will probe PCF8584 later.\n"); 248 pr_info("%s: found API UP2000 like "
249 "board, will probe PCF8584 "
250 "later\n", pcf_isa_ops.name);
230 } 251 }
231 } 252 }
232 pci_dev_put(cy693_dev); 253 pci_dev_put(cy693_dev);
@@ -236,12 +257,11 @@ static int __init i2c_pcfisa_init(void)
236 257
237 /* sanity checks for mmapped I/O */ 258 /* sanity checks for mmapped I/O */
238 if (mmapped && base < 0xc8000) { 259 if (mmapped && base < 0xc8000) {
239 printk(KERN_ERR "i2c-elektor: incorrect base address (0x%0X) specified for mmapped I/O.\n", base); 260 printk(KERN_ERR "%s: incorrect base address (%#x) specified "
261 "for mmapped I/O\n", pcf_isa_ops.name, base);
240 return -ENODEV; 262 return -ENODEV;
241 } 263 }
242 264
243 printk(KERN_INFO "i2c-elektor: i2c pcf8584-isa adapter driver\n");
244
245 if (base == 0) { 265 if (base == 0) {
246 base = DEFAULT_BASE; 266 base = DEFAULT_BASE;
247 } 267 }
@@ -251,8 +271,8 @@ static int __init i2c_pcfisa_init(void)
251 return -ENODEV; 271 return -ENODEV;
252 if (i2c_pcf_add_bus(&pcf_isa_ops) < 0) 272 if (i2c_pcf_add_bus(&pcf_isa_ops) < 0)
253 goto fail; 273 goto fail;
254 274
255 printk(KERN_ERR "i2c-elektor: found device at %#x.\n", base); 275 dev_info(&pcf_isa_ops.dev, "found device at %#x\n", base);
256 276
257 return 0; 277 return 0;
258 278
@@ -262,8 +282,13 @@ static int __init i2c_pcfisa_init(void)
262 free_irq(irq, NULL); 282 free_irq(irq, NULL);
263 } 283 }
264 284
265 if (!mmapped) 285 if (!mmapped) {
266 release_region(base , 2); 286 ioport_unmap(base_iomem);
287 release_region(base, 2);
288 } else {
289 iounmap(base_iomem);
290 release_mem_region(base, 2);
291 }
267 return -ENODEV; 292 return -ENODEV;
268} 293}
269 294
@@ -276,8 +301,13 @@ static void i2c_pcfisa_exit(void)
276 free_irq(irq, NULL); 301 free_irq(irq, NULL);
277 } 302 }
278 303
279 if (!mmapped) 304 if (!mmapped) {
280 release_region(base , 2); 305 ioport_unmap(base_iomem);
306 release_region(base, 2);
307 } else {
308 iounmap(base_iomem);
309 release_mem_region(base, 2);
310 }
281} 311}
282 312
283MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>"); 313MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");