1 /* 2 * i2c-pca-isa.c driver for PCA9564 on ISA boards 3 * Copyright (C) 2004 Arcom Control Systems 4 * Copyright (C) 2008 Pengutronix 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 21 #include <linux/kernel.h> 22 #include <linux/ioport.h> 23 #include <linux/module.h> 24 #include <linux/moduleparam.h> 25 #include <linux/delay.h> 26 #include <linux/jiffies.h> 27 #include <linux/init.h> 28 #include <linux/interrupt.h> 29 #include <linux/wait.h> 30 #include <linux/isa.h> 31 #include <linux/i2c.h> 32 #include <linux/i2c-algo-pca.h> 33 #include <linux/io.h> 34 35 #include <asm/irq.h> 36 37 #define DRIVER "i2c-pca-isa" 38 #define IO_SIZE 4 39 40 static unsigned long base; 41 static int irq = -1; 42 43 /* Data sheet recommends 59kHz for 100kHz operation due to variation 44 * in the actual clock rate */ 45 static int clock = 59000; 46 47 static struct i2c_adapter pca_isa_ops; 48 static wait_queue_head_t pca_wait; 49 50 static void pca_isa_writebyte(void *pd, int reg, int val) 51 { 52 #ifdef DEBUG_IO 53 static char *names[] = { "T/O", "DAT", "ADR", "CON" }; 54 printk(KERN_DEBUG "*** write %s at %#lx <= %#04x\n", names[reg], 55 base+reg, val); 56 #endif 57 outb(val, base+reg); 58 } 59 60 static int pca_isa_readbyte(void *pd, int reg) 61 { 62 int res = inb(base+reg); 63 #ifdef DEBUG_IO 64 { 65 static char *names[] = { "STA", "DAT", "ADR", "CON" }; 66 printk(KERN_DEBUG "*** read %s => %#04x\n", names[reg], res); 67 } 68 #endif 69 return res; 70 } 71 72 static int pca_isa_waitforcompletion(void *pd) 73 { 74 unsigned long timeout; 75 long ret; 76 77 if (irq > -1) { 78 ret = wait_event_timeout(pca_wait, 79 pca_isa_readbyte(pd, I2C_PCA_CON) 80 & I2C_PCA_CON_SI, pca_isa_ops.timeout); 81 } else { 82 /* Do polling */ 83 timeout = jiffies + pca_isa_ops.timeout; 84 do { 85 ret = time_before(jiffies, timeout); 86 if (pca_isa_readbyte(pd, I2C_PCA_CON) 87 & I2C_PCA_CON_SI) 88 break; 89 udelay(100); 90 } while (ret); 91 } 92 93 return ret > 0; 94 } 95 96 static void pca_isa_resetchip(void *pd) 97 { 98 /* apparently only an external reset will do it. not a lot can be done */ 99 printk(KERN_WARNING DRIVER ": Haven't figured out how to do a reset yet\n"); 100 } 101 102 static irqreturn_t pca_handler(int this_irq, void *dev_id) { 103 wake_up(&pca_wait); 104 return IRQ_HANDLED; 105 } 106 107 static struct i2c_algo_pca_data pca_isa_data = { 108 /* .data intentionally left NULL, not needed with ISA */ 109 .write_byte = pca_isa_writebyte, 110 .read_byte = pca_isa_readbyte, 111 .wait_for_completion = pca_isa_waitforcompletion, 112 .reset_chip = pca_isa_resetchip, 113 }; 114 115 static struct i2c_adapter pca_isa_ops = { 116 .owner = THIS_MODULE, 117 .algo_data = &pca_isa_data, 118 .name = "PCA9564/PCA9665 ISA Adapter", 119 .timeout = HZ, 120 }; 121 122 static int __devinit pca_isa_match(struct device *dev, unsigned int id) 123 { 124 int match = base != 0; 125 126 if (match) { 127 if (irq <= -1) 128 dev_warn(dev, "Using polling mode (specify irq)\n"); 129 } else 130 dev_err(dev, "Please specify I/O base\n"); 131 132 return match; 133 } 134 135 static int __devinit pca_isa_probe(struct device *dev, unsigned int id) 136 { 137 init_waitqueue_head(&pca_wait); 138 139 dev_info(dev, "i/o base %#08lx. irq %d\n", base, irq); 140 141 #ifdef CONFIG_PPC 142 if (check_legacy_ioport(base)) { 143 dev_err(dev, "I/O address %#08lx is not available\n", base); 144 goto out; 145 } 146 #endif 147 148 if (!request_region(base, IO_SIZE, "i2c-pca-isa")) { 149 dev_err(dev, "I/O address %#08lx is in use\n", base); 150 goto out; 151 } 152 153 if (irq > -1) { 154 if (request_irq(irq, pca_handler, 0, "i2c-pca-isa", &pca_isa_ops) < 0) { 155 dev_err(dev, "Request irq%d failed\n", irq); 156 goto out_region; 157 } 158 } 159 160 pca_isa_data.i2c_clock = clock; 161 if (i2c_pca_add_bus(&pca_isa_ops) < 0) { 162 dev_err(dev, "Failed to add i2c bus\n"); 163 goto out_irq; 164 } 165 166 return 0; 167 168 out_irq: 169 if (irq > -1) 170 free_irq(irq, &pca_isa_ops); 171 out_region: 172 release_region(base, IO_SIZE); 173 out: 174 return -ENODEV; 175 } 176 177 static int __devexit pca_isa_remove(struct device *dev, unsigned int id) 178 { 179 i2c_del_adapter(&pca_isa_ops); 180 181 if (irq > -1) { 182 disable_irq(irq); 183 free_irq(irq, &pca_isa_ops); 184 } 185 release_region(base, IO_SIZE); 186 187 return 0; 188 } 189 190 static struct isa_driver pca_isa_driver = { 191 .match = pca_isa_match, 192 .probe = pca_isa_probe, 193 .remove = __devexit_p(pca_isa_remove), 194 .driver = { 195 .owner = THIS_MODULE, 196 .name = DRIVER, 197 } 198 }; 199 200 static int __init pca_isa_init(void) 201 { 202 return isa_register_driver(&pca_isa_driver, 1); 203 } 204 205 static void __exit pca_isa_exit(void) 206 { 207 isa_unregister_driver(&pca_isa_driver); 208 } 209 210 MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>"); 211 MODULE_DESCRIPTION("ISA base PCA9564/PCA9665 driver"); 212 MODULE_LICENSE("GPL"); 213 214 module_param(base, ulong, 0); 215 MODULE_PARM_DESC(base, "I/O base address"); 216 217 module_param(irq, int, 0); 218 MODULE_PARM_DESC(irq, "IRQ"); 219 module_param(clock, int, 0); 220 MODULE_PARM_DESC(clock, "Clock rate in hertz.\n\t\t" 221 "For PCA9564: 330000,288000,217000,146000," 222 "88000,59000,44000,36000\n" 223 "\t\tFor PCA9665:\tStandard: 60300 - 100099\n" 224 "\t\t\t\tFast: 100100 - 400099\n" 225 "\t\t\t\tFast+: 400100 - 10000099\n" 226 "\t\t\t\tTurbo: Up to 1265800"); 227 228 module_init(pca_isa_init); 229 module_exit(pca_isa_exit); 230