diff mbox series

[SRU,F:linux-bluefield,v1,1/1] UBUNTU: SAUCE: i2c-mlxbf.c: support lock mechanism

Message ID 20220708193217.22920-2-asmaa@nvidia.com
State New
Headers show
Series UBUNTU: SAUCE: i2c-mlxbf.c: support lock mechanism | expand

Commit Message

Asmaa Mnebhi July 8, 2022, 7:32 p.m. UTC
Buglink: https://bugs.launchpad.net/bugs/1981105

Support the I2C lock mechanism, otherwise there could be
unexpected behavior when an i2c bus is accessed by
several entities like the linux driver, ATF driver and UEFI driver.
Replace ioremap_cache with ioremap since it is deprecated
in later kernels.

Signed-off-by: Asmaa Mnebhi <asmaa@nvidia.com>
---
 drivers/i2c/busses/i2c-mlxbf.c | 40 +++++++++++++++++++++++++++++-----
 1 file changed, 34 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/drivers/i2c/busses/i2c-mlxbf.c b/drivers/i2c/busses/i2c-mlxbf.c
index 0ac9e70244a7..7ce289d4efa8 100644
--- a/drivers/i2c/busses/i2c-mlxbf.c
+++ b/drivers/i2c/busses/i2c-mlxbf.c
@@ -340,7 +340,8 @@  enum {
  * Timeout is given in microsends. Note also that timeout handling is not
  * exact.
  */
-#define SMBUS_TIMEOUT   (300 * 1000) /* 300ms */
+#define SMBUS_TIMEOUT               (300 * 1000) /* 300ms */
+#define SMBUS_LOCK_POLL_TIMEOUT           (300 * 1000) /* 300ms */
 
 /* Encapsulates timing parameters */
 struct mlx_i2c_timings {
@@ -573,6 +574,25 @@  static bool mlx_smbus_master_wait_for_idle(struct mlx_i2c_priv *priv)
 	return false;
 }
 
+/*
+ * wait for the lock to be released before acquiring it.
+ */
+static bool mlx_smbus_master_lock(struct mlx_i2c_priv *priv)
+{
+	if (mlx_smbus_poll(priv->smbus->io, SMBUS_MASTER_GW,
+			   1 << MASTER_LOCK_BIT_OFF, true,
+			   SMBUS_LOCK_POLL_TIMEOUT))
+		return true;
+
+	return false;
+}
+
+static void mlx_smbus_master_unlock(struct mlx_i2c_priv *priv)
+{
+	/* Clear the gw to clear the lock */
+	writel(0, priv->smbus->io + SMBUS_MASTER_GW);
+}
+
 /*
  * Poll SMBus master status and return transaction status,
  * i.e. whether succeeded or failed. I2C and SMBus fault codes
@@ -704,7 +724,7 @@  static int mlx_smbus_enable(struct mlx_i2c_priv *priv, u8 slave,
 	/* Clear status bits  */
 	smbus_write(priv->smbus->io, SMBUS_MASTER_STATUS, 0x0);
 	/* Set the cause data */
-	smbus_write(priv->smbus->io, I2C_CAUSE_OR_CLEAR_BITS, ~0x0);
+	smbus_write(priv->mst_cause->io, I2C_CAUSE_OR_CLEAR_BITS, ~0x0);
 	/* Zero PEC byte */
 	smbus_write(priv->smbus->io, SMBUS_MASTER_PEC, 0x0);
 	/* Zero byte count    */
@@ -748,6 +768,10 @@  static int mlx_smbus_start_transaction(struct mlx_i2c_priv *priv,
 	if (WARN_ON(!mlx_smbus_master_wait_for_idle(priv)))
 		return -EBUSY;
 
+	/* Try to acquire the smbus gw lock */
+	if (WARN_ON(!mlx_smbus_master_lock(priv)))
+		return -EBUSY;
+
 	/* Set first byte */
 	data_desc[data_idx++] = addr;
 
@@ -802,8 +826,10 @@  static int mlx_smbus_start_transaction(struct mlx_i2c_priv *priv,
 	if (write_en) {
 		ret = mlx_smbus_enable(priv, slave, write_len, block_en,
 				       pec_en, 0);
-		if (ret != 0)
+		if (ret) {
+			mlx_smbus_master_unlock(priv);
 			return ret;
+		}
 	}
 
 	if (read_en) {
@@ -830,6 +856,8 @@  static int mlx_smbus_start_transaction(struct mlx_i2c_priv *priv,
 			    SMBUS_MASTER_FSM_PS_STATE_MASK);
 	}
 
+	mlx_smbus_master_unlock(priv);
+
 	return ret;
 }
 
@@ -1396,7 +1424,7 @@  static int mlx_i2c_get_gpio(struct platform_device *pdev,
 	if (!devm_request_mem_region(dev, params->start, size, params->name))
 		return -EFAULT;
 
-	gpio_res->io = devm_ioremap_nocache(dev, params->start, size);
+	gpio_res->io = devm_ioremap(dev, params->start, size);
 	if (IS_ERR(gpio_res->io)) {
 		devm_release_mem_region(dev, params->start, size);
 		return PTR_ERR(gpio_res->io);
@@ -1460,7 +1488,7 @@  static int mlx_i2c_get_corepll(struct platform_device *pdev,
 	if (!devm_request_mem_region(dev, params->start, size, params->name))
 		return -EFAULT;
 
-	corepll_res->io = devm_ioremap_nocache(dev, params->start, size);
+	corepll_res->io = devm_ioremap(dev, params->start, size);
 	if (IS_ERR(corepll_res->io)) {
 		devm_release_mem_region(dev, params->start, size);
 		return PTR_ERR(corepll_res->io);
@@ -1813,7 +1841,7 @@  static int mlx_i2c_init_coalesce(struct platform_device *pdev,
 		if (!request_mem_region(params->start, size, params->name))
 			return -EFAULT;
 
-		coalesce_res->io = ioremap_nocache(params->start, size);
+		coalesce_res->io = ioremap(params->start, size);
 		if (IS_ERR(coalesce_res->io)) {
 			release_mem_region(params->start, size);
 			return PTR_ERR(coalesce_res->io);