1 /* 2 * ARM IOC/IOMD i2c driver. 3 * 4 * Copyright (C) 2000 Russell King 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 version 2 as 8 * published by the Free Software Foundation. 9 * 10 * On Acorn machines, the following i2c devices are on the bus: 11 * - PCF8583 real time clock & static RAM 12 */ 13 #include <linux/module.h> 14 #include <linux/i2c.h> 15 #include <linux/i2c-algo-bit.h> 16 #include <linux/io.h> 17 18 #include <mach/hardware.h> 19 #include <asm/hardware/ioc.h> 20 21 #define FORCE_ONES 0xdc 22 #define SCL 0x02 23 #define SDA 0x01 24 25 /* 26 * We must preserve all non-i2c output bits in IOC_CONTROL. 27 * Note also that we need to preserve the value of SCL and 28 * SDA outputs as well (which may be different from the 29 * values read back from IOC_CONTROL). 30 */ 31 static u_int force_ones; 32 33 static void ioc_setscl(void *data, int state) 34 { 35 u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA); 36 u_int ones = force_ones; 37 38 if (state) 39 ones |= SCL; 40 else 41 ones &= ~SCL; 42 43 force_ones = ones; 44 45 ioc_writeb(ioc_control | ones, IOC_CONTROL); 46 } 47 48 static void ioc_setsda(void *data, int state) 49 { 50 u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA); 51 u_int ones = force_ones; 52 53 if (state) 54 ones |= SDA; 55 else 56 ones &= ~SDA; 57 58 force_ones = ones; 59 60 ioc_writeb(ioc_control | ones, IOC_CONTROL); 61 } 62 63 static int ioc_getscl(void *data) 64 { 65 return (ioc_readb(IOC_CONTROL) & SCL) != 0; 66 } 67 68 static int ioc_getsda(void *data) 69 { 70 return (ioc_readb(IOC_CONTROL) & SDA) != 0; 71 } 72 73 static struct i2c_algo_bit_data ioc_data = { 74 .setsda = ioc_setsda, 75 .setscl = ioc_setscl, 76 .getsda = ioc_getsda, 77 .getscl = ioc_getscl, 78 .udelay = 80, 79 .timeout = HZ, 80 }; 81 82 static struct i2c_adapter ioc_ops = { 83 .nr = 0, 84 .algo_data = &ioc_data, 85 }; 86 87 static int __init i2c_ioc_init(void) 88 { 89 force_ones = FORCE_ONES | SCL | SDA; 90 91 return i2c_bit_add_numbered_bus(&ioc_ops); 92 } 93 94 module_init(i2c_ioc_init); 95 96 MODULE_AUTHOR("Russell King <linux@armlinux.org.uk>"); 97 MODULE_DESCRIPTION("ARM IOC/IOMD i2c driver"); 98 MODULE_LICENSE("GPL v2"); 99