Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / i2c / busses / i2c-acorn.c
diff --git a/kernel/drivers/i2c/busses/i2c-acorn.c b/kernel/drivers/i2c/busses/i2c-acorn.c
new file mode 100644 (file)
index 0000000..9d7be5a
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ *  linux/drivers/acorn/char/i2c.c
+ *
+ *  Copyright (C) 2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  ARM IOC/IOMD i2c driver.
+ *
+ *  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,
+       .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);