// SPDX-License-Identifier: GPL-2.0-only /* * ARM IOC/IOMD i2c driver. * * Copyright (C) 2000 Russell King * * On Acorn machines, the following i2c devices are on the bus: * - PCF8583 real time clock & static RAM */ #include <linux/module.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> #include <linux/io.h> #include <mach/hardware.h> #include <asm/hardware/ioc.h> #define FORCE_ONES 0xdc #define SCL 0x02 #define SDA 0x01 /* * We must preserve all non-i2c output bits in IOC_CONTROL. * Note also that we need to preserve the value of SCL and * SDA outputs as well (which may be different from the * values read back from IOC_CONTROL). */ static u_int force_ones; static void ioc_setscl(void *data, int state) { u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA); u_int ones = force_ones; if (state) ones |= SCL; else ones &= ~SCL; force_ones = ones; ioc_writeb(ioc_control | ones, IOC_CONTROL); } static void ioc_setsda(void *data, int state) { u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA); u_int ones = force_ones; if (state) ones |= SDA; else ones &= ~SDA; force_ones = ones; ioc_writeb(ioc_control | ones, IOC_CONTROL); } static int ioc_getscl(void *data) { return (ioc_readb(IOC_CONTROL) & SCL) != 0; } static int ioc_getsda(void *data) { return (ioc_readb(IOC_CONTROL) & SDA) != 0; } static struct i2c_algo_bit_data ioc_data = { .setsda = ioc_setsda, .setscl = ioc_setscl, .getsda = ioc_getsda, .getscl = ioc_getscl, .udelay = 80, .timeout = HZ, }; static struct i2c_adapter ioc_ops = { .nr = 0, .name = "ioc", .algo_data = &ioc_data, }; static int __init i2c_ioc_init(void) { force_ones = FORCE_ONES | SCL | SDA; return i2c_bit_add_numbered_bus(&ioc_ops); } module_init(i2c_ioc_init); MODULE_AUTHOR("Russell King <linux@armlinux.org.uk>"); MODULE_DESCRIPTION("ARM IOC/IOMD i2c driver"); MODULE_LICENSE("GPL v2");