Add support for on-chip I2C controller used on old UniPhier SoCs
such as PH1-LD4, PH1-sLD8, etc.. This adapter is so simple that
it has no FIFO in it.
Signed-off-by: Masahiro Yamada yamada.masah...@socionext.com
---
drivers/i2c/busses/Kconfig| 8 +
drivers/i2c/busses/Makefile | 1 +
drivers/i2c/busses/i2c-uniphier.c | 446 ++
3 files changed, 455 insertions(+)
create mode 100644 drivers/i2c/busses/i2c-uniphier.c
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 577d58d..7073a19 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -885,6 +885,14 @@ config I2C_TEGRA
If you say yes to this option, support will be included for the
I2C controller embedded in NVIDIA Tegra SOCs
+config I2C_UNIPHIER
+ tristate UniPhier FIFO-less I2C controller
+ depends on ARCH_UNIPHIER
+ help
+ If you say yes to this option, support will be included for
+ the UniPhier FIFO-less I2C interface embedded in PH1-LD4, PH1-sLD8,
+ or older UniPhier SoCs.
+
config I2C_VERSATILE
tristate ARM Versatile/Realview I2C bus support
depends on ARCH_VERSATILE || ARCH_REALVIEW || ARCH_VEXPRESS
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index e5f537c..e89969c 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -85,6 +85,7 @@ obj-$(CONFIG_I2C_ST) += i2c-st.o
obj-$(CONFIG_I2C_STU300) += i2c-stu300.o
obj-$(CONFIG_I2C_SUN6I_P2WI) += i2c-sun6i-p2wi.o
obj-$(CONFIG_I2C_TEGRA)+= i2c-tegra.o
+obj-$(CONFIG_I2C_UNIPHIER) += i2c-uniphier.o
obj-$(CONFIG_I2C_VERSATILE)+= i2c-versatile.o
obj-$(CONFIG_I2C_WMT) += i2c-wmt.o
obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o
diff --git a/drivers/i2c/busses/i2c-uniphier.c
b/drivers/i2c/busses/i2c-uniphier.c
new file mode 100644
index 000..bd9877f
--- /dev/null
+++ b/drivers/i2c/busses/i2c-uniphier.c
@@ -0,0 +1,446 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada yamada.masah...@socionext.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include linux/clk.h
+#include linux/i2c.h
+#include linux/interrupt.h
+#include linux/io.h
+#include linux/module.h
+#include linux/platform_device.h
+
+#define UNIPHIER_I2C_DTRM 0x00/* TX register */
+#define UNIPHIER_I2C_DTRM_IRQENBIT(11) /* enable interrupt */
+#define UNIPHIER_I2C_DTRM_STA BIT(10) /* start condition */
+#define UNIPHIER_I2C_DTRM_STO BIT(9) /* stop condition */
+#define UNIPHIER_I2C_DTRM_NACK BIT(8) /* do not return ACK */
+#define UNIPHIER_I2C_DTRM_RD BIT(0) /* read transaction */
+#define UNIPHIER_I2C_DREC 0x04/* RX register */
+#define UNIPHIER_I2C_DREC_MST BIT(14) /* 1 = master, 0 = slave */
+#define UNIPHIER_I2C_DREC_TX BIT(13) /* 1 = transmit, 0 = receive */
+#define UNIPHIER_I2C_DREC_STS BIT(12) /* stop condition detected */
+#define UNIPHIER_I2C_DREC_LRB BIT(11) /* no ACK */
+#define UNIPHIER_I2C_DREC_LAB BIT(9) /* arbitration lost */
+#define UNIPHIER_I2C_DREC_BBN BIT(8) /* bus not busy */
+#define UNIPHIER_I2C_MYAD 0x08/* slave address */
+#define UNIPHIER_I2C_CLK 0x0c/* clock frequency control */
+#define UNIPHIER_I2C_BRST 0x10/* bus reset */
+#define UNIPHIER_I2C_BRST_FOEN BIT(1) /* normal operation */
+#define UNIPHIER_I2C_BRST_RSCL BIT(0) /* release SCL */
+#define UNIPHIER_I2C_HOLD 0x14/* hold time control */
+#define UNIPHIER_I2C_BSTS 0x18/* bus status monitor */
+#define UNIPHIER_I2C_BSTS_SDA BIT(1) /* readback of SDA line */
+#define UNIPHIER_I2C_BSTS_SCL BIT(0) /* readback of SCL line */
+#define UNIPHIER_I2C_NOISE 0x1c/* noise filter control */
+#define UNIPHIER_I2C_SETUP 0x20/* setup time control */
+
+#define UNIPHIER_I2C_DEFAULT_SPEED 10
+#define UNIPHIER_I2C_MAX_SPEED 40
+
+struct uniphier_i2c_priv {
+ struct completion comp;
+ struct i2c_adapter adap;
+ void __iomem *membase;
+ struct clk *clk;
+ unsigned int busy_cnt;
+};
+
+static irqreturn_t uniphier_i2c_interrupt(int irq, void *dev_id)
+{
+ struct uniphier_i2c_priv *priv = dev_id;
+
+ /*
+* This hardware uses edge triggered interrupt. Do not touch the
+* hardware registers in this handler to make sure to catch the next
+*