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