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