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