linux/drivers/i2c/busses/i2c-acorn.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *  ARM IOC/IOMD i2c driver.
   4 *
   5 *  Copyright (C) 2000 Russell King
   6 *
   7 *  On Acorn machines, the following i2c devices are on the bus:
   8 *      - PCF8583 real time clock & static RAM
   9 */
  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      0xdc
  19#define SCL             0x02
  20#define SDA             0x01
  21
  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 and
  25 * SDA outputs as well (which may be different from the
  26 * 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        else
  38                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        else
  53                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