From 292700faccff983b60a6bf210af36d9bf7a0ac1a Mon Sep 17 00:00:00 2001 From: Jan Sowinski Date: Fri, 15 Oct 2021 23:34:10 +0200 Subject: [PATCH] Enable I2C clock stretching and multi-master support for AST2600 Enabled I2C clock stretching by default to improve general compatibility with various devices. Added support for multi-master mode enabled with "multi-master" property set in DTS for every i2c node. Signed-off-by: Jan Sowinski --- arch/arm/dts/ast2600-intel.dts | 8 ++++++++ drivers/i2c/ast_i2c.c | 19 ++++++++++++------- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/arch/arm/dts/ast2600-intel.dts b/arch/arm/dts/ast2600-intel.dts index a76193716d..dba62fd254 100644 --- a/arch/arm/dts/ast2600-intel.dts +++ b/arch/arm/dts/ast2600-intel.dts @@ -168,6 +168,7 @@ &i2c4 { status = "okay"; + multi-master; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c5_default>; @@ -175,6 +176,7 @@ &i2c5 { status = "okay"; + multi-master; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c6_default>; @@ -182,6 +184,7 @@ &i2c6 { status = "okay"; + multi-master; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c7_default>; @@ -189,6 +192,7 @@ &i2c7 { status = "okay"; + multi-master; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c8_default>; @@ -196,6 +200,7 @@ &i2c8 { status = "okay"; + multi-master; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c9_default>; @@ -203,6 +208,7 @@ &i2c9 { status = "okay"; + multi-master; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c10_default>; @@ -210,6 +216,7 @@ &i2c12 { status = "okay"; + multi-master; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c13_default>; @@ -217,6 +224,7 @@ &i2c13 { status = "okay"; + multi-master; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c14_default>; diff --git a/drivers/i2c/ast_i2c.c b/drivers/i2c/ast_i2c.c index bbc32d6cdb..974641220b 100644 --- a/drivers/i2c/ast_i2c.c +++ b/drivers/i2c/ast_i2c.c @@ -31,6 +31,8 @@ struct ast_i2c_priv { struct ast_i2c_regs *regs; /* I2C speed in Hz */ int speed; + /* Multi-master mode */ + bool multi_master; }; /* @@ -67,14 +69,14 @@ static void ast_i2c_clear_interrupts(struct udevice *dev) static void ast_i2c_init_bus(struct udevice *dev) { struct ast_i2c_priv *priv = dev_get_priv(dev); + u32 fun_ctrl_reg = I2CD_MASTER_EN; /* Reset device */ writel(0, &priv->regs->fcr); - /* Enable Master Mode. Assuming single-master */ - writel(I2CD_MASTER_EN - | I2CD_M_SDA_LOCK_EN - | I2CD_MULTI_MASTER_DIS | I2CD_M_SCL_DRIVE_EN, - &priv->regs->fcr); + /* Enable Single-Master or Multi-Master Mode. */ + if (!priv->multi_master) + fun_ctrl_reg |= I2CD_MULTI_MASTER_DIS; + writel(fun_ctrl_reg, &priv->regs->fcr); /* Enable Interrupts */ writel(I2CD_INTR_TX_ACK | I2CD_INTR_TX_NAK @@ -100,6 +102,9 @@ static int ast_i2c_ofdata_to_platdata(struct udevice *dev) return ret; } + if (dev_read_bool(dev, "multi-master")) + priv->multi_master = true; + return 0; } @@ -246,8 +251,8 @@ static int ast_i2c_deblock(struct udevice *dev) bool scl_high = csr & I2CD_SCL_LINE_STS; int ret = 0; - if (sda_high && scl_high) { - /* Bus is idle, no deblocking needed. */ + if ((sda_high && scl_high) || priv->multi_master) { + /* Bus is idle or multi-master mode enabled, no deblocking needed. */ return 0; } else if (sda_high) { /* Send stop command */ -- 2.25.1