Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  ARM IOC/IOMD i2c driver.
0004  *
0005  *  Copyright (C) 2000 Russell King
0006  *
0007  *  On Acorn machines, the following i2c devices are on the bus:
0008  *  - PCF8583 real time clock & static RAM
0009  */
0010 #include <linux/module.h>
0011 #include <linux/i2c.h>
0012 #include <linux/i2c-algo-bit.h>
0013 #include <linux/io.h>
0014 
0015 #include <mach/hardware.h>
0016 #include <asm/hardware/ioc.h>
0017 
0018 #define FORCE_ONES  0xdc
0019 #define SCL     0x02
0020 #define SDA     0x01
0021 
0022 /*
0023  * We must preserve all non-i2c output bits in IOC_CONTROL.
0024  * Note also that we need to preserve the value of SCL and
0025  * SDA outputs as well (which may be different from the
0026  * values read back from IOC_CONTROL).
0027  */
0028 static u_int force_ones;
0029 
0030 static void ioc_setscl(void *data, int state)
0031 {
0032     u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA);
0033     u_int ones = force_ones;
0034 
0035     if (state)
0036         ones |= SCL;
0037     else
0038         ones &= ~SCL;
0039 
0040     force_ones = ones;
0041 
0042     ioc_writeb(ioc_control | ones, IOC_CONTROL);
0043 }
0044 
0045 static void ioc_setsda(void *data, int state)
0046 {
0047     u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA);
0048     u_int ones = force_ones;
0049 
0050     if (state)
0051         ones |= SDA;
0052     else
0053         ones &= ~SDA;
0054 
0055     force_ones = ones;
0056 
0057     ioc_writeb(ioc_control | ones, IOC_CONTROL);
0058 }
0059 
0060 static int ioc_getscl(void *data)
0061 {
0062     return (ioc_readb(IOC_CONTROL) & SCL) != 0;
0063 }
0064 
0065 static int ioc_getsda(void *data)
0066 {
0067     return (ioc_readb(IOC_CONTROL) & SDA) != 0;
0068 }
0069 
0070 static struct i2c_algo_bit_data ioc_data = {
0071     .setsda     = ioc_setsda,
0072     .setscl     = ioc_setscl,
0073     .getsda     = ioc_getsda,
0074     .getscl     = ioc_getscl,
0075     .udelay     = 80,
0076     .timeout    = HZ,
0077 };
0078 
0079 static struct i2c_adapter ioc_ops = {
0080     .nr         = 0,
0081     .name           = "ioc",
0082     .algo_data      = &ioc_data,
0083 };
0084 
0085 static int __init i2c_ioc_init(void)
0086 {
0087     force_ones = FORCE_ONES | SCL | SDA;
0088 
0089     return i2c_bit_add_numbered_bus(&ioc_ops);
0090 }
0091 
0092 module_init(i2c_ioc_init);
0093 
0094 MODULE_AUTHOR("Russell King <linux@armlinux.org.uk>");
0095 MODULE_DESCRIPTION("ARM IOC/IOMD i2c driver");
0096 MODULE_LICENSE("GPL v2");