Add i2c new register mode driver to support AST2600 i2c
new register mode. AST2600 i2c controller have legacy and
new register mode. The new register mode have global register
support 4 base clock for scl clock selection, and new clock
divider mode.
Signed-off-by: Ryan Chen
---
MAINTAINERS | 6 +
drivers/i2c/Kconfig | 10 ++
drivers/i2c/Makefile | 1 +
drivers/i2c/ast2600_i2c.c | 367 ++
drivers/i2c/ast2600_i2c.h | 120 +
5 files changed, 504 insertions(+)
create mode 100644 drivers/i2c/ast2600_i2c.c
create mode 100644 drivers/i2c/ast2600_i2c.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 3fc4cd0f12..1cf54f0b4e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -769,6 +769,12 @@ S: Maintained
F: drivers/pci/pcie_phytium.c
F: arch/arm/dts/phytium-durian.dts
+ASPEED AST2600 I2C DRIVER
+M: Ryan Chen
+R: Aspeed BMC SW team
+S: Maintained
+F: drivers/i2c/ast2600_i2c.c
+
ASPEED FMC SPI DRIVER
M: Chin-Ting Kuo
M: Cédric Le Goater
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 08b6c7bdcc..77e2a1c4c0 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -221,6 +221,16 @@ config SYS_I2C_DW
controller is used in various SoCs, e.g. the ST SPEAr, Altera
SoCFPGA, Synopsys ARC700 and some Intel x86 SoCs.
+config SYS_I2C_AST2600
+bool "AST2600 I2C Controller"
+depends on DM_I2C && ARCH_ASPEED
+help
+ Say yes here to select AST2600 I2C Host Controller. The driver
+ support AST2600 I2C new mode register. This I2C controller supports:
+ _Standard-mode (up to 100 kHz)
+ _Fast-mode (up to 400 kHz)
+ _Fast-mode Plus (up to 1 MHz)
+
config SYS_I2C_ASPEED
bool "Aspeed I2C Controller"
depends on DM_I2C && ARCH_ASPEED
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 920aafb91c..89db2d8e37 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_$(SPL_)I2C_CROS_EC_LDO) += cros_ec_ldo.o
obj-$(CONFIG_$(SPL_)SYS_I2C_LEGACY) += i2c_core.o
obj-$(CONFIG_SYS_I2C_ASPEED) += ast_i2c.o
+obj-$(CONFIG_SYS_I2C_AST2600) += ast2600_i2c.o
obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o
obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
obj-$(CONFIG_SYS_I2C_CA) += i2c-cortina.o
diff --git a/drivers/i2c/ast2600_i2c.c b/drivers/i2c/ast2600_i2c.c
new file mode 100644
index 00..f9d9ff09b3
--- /dev/null
+++ b/drivers/i2c/ast2600_i2c.c
@@ -0,0 +1,367 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright ASPEED Technology Inc.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "ast2600_i2c.h"
+
+/* Device private data */
+struct ast2600_i2c_priv {
+ struct clk clk;
+ struct ast2600_i2c_regs *regs;
+ void __iomem *global;
+};
+
+static int ast2600_i2c_read_data(struct ast2600_i2c_priv *priv, u8 chip_addr,
+u8 *buffer, size_t len, bool send_stop)
+{
+ int rx_cnt, ret = 0;
+ u32 cmd, isr;
+
+ for (rx_cnt = 0; rx_cnt < len; rx_cnt++, buffer++) {
+ cmd = I2CM_PKT_EN | I2CM_PKT_ADDR(chip_addr) |
+ I2CM_RX_CMD;
+ if (!rx_cnt)
+ cmd |= I2CM_START_CMD;
+
+ if ((len - 1) == rx_cnt)
+ cmd |= I2CM_RX_CMD_LAST;
+
+ if (send_stop && ((len - 1) == rx_cnt))
+ cmd |= I2CM_STOP_CMD;
+
+ writel(cmd, &priv->regs->cmd_sts);
+
+ ret = readl_poll_timeout(&priv->regs->isr, isr,
+isr & I2CM_PKT_DONE,
+I2C_TIMEOUT_US);
+ if (ret)
+ return -ETIMEDOUT;
+
+ *buffer =
+ I2CC_GET_RX_BUFF(readl(&priv->regs->trx_buff));
+
+ writel(I2CM_PKT_DONE, &priv->regs->isr);
+
+ if (isr & I2CM_TX_NAK)
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+static int ast2600_i2c_write_data(struct ast2600_i2c_priv *priv, u8 chip_addr,
+ u8 *buffer, size_t len, bool send_stop)
+{
+ int tx_cnt, ret = 0;
+ u32 cmd, isr;
+
+ if (!len) {
+ cmd = I2CM_PKT_EN | I2CM_PKT_ADDR(chip_addr) |
+ I2CM_START_CMD;
+ writel(cmd, &priv->regs->cmd_sts);
+ ret = readl_poll_timeout(&priv->regs->isr, isr,
+isr & I2CM_PKT_DONE,
+I2C_TIMEOUT_US);
+ if (ret)
+ return -ETIMEDOUT;
+
+ writel(I2CM_PKT_DONE, &priv->regs->isr);
+
+ if (isr & I2CM_TX_NAK)
+ return -EREMOTEIO;
+ }
+
+ for (tx_cnt = 0; tx_cnt < len; tx_cnt++, buffer++) {
+ cmd = I2C