mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 20:14:06 +02:00
i2c-mlxbf: Add repeated start condition support
Add support for SMBus repeated start conditions to the Mellanox I2C driver. This support is specifically enabled for the I2C_FUNC_SMBUS_WRITE_I2C_BLOCK implementation which is required for communication with a specific I2C device on BlueField 3. Signed-off-by: Chris Babroski <cbabroski@nvidia.com> Reviewed-by: Asmaa Mnebhi <asmaa@nvidia.com> Reviewed-by: Khalil Blaiech <kblaiech@nvidia.com> Link: https://lore.kernel.org/r/20250506193059.321345-1-cbabroski@nvidia.com Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
This commit is contained in:
parent
24d9f60505
commit
6bdc662c05
|
|
@ -224,7 +224,7 @@
|
|||
|
||||
#define MLXBF_I2C_MASTER_ENABLE \
|
||||
(MLXBF_I2C_MASTER_LOCK_BIT | MLXBF_I2C_MASTER_BUSY_BIT | \
|
||||
MLXBF_I2C_MASTER_START_BIT | MLXBF_I2C_MASTER_STOP_BIT)
|
||||
MLXBF_I2C_MASTER_START_BIT)
|
||||
|
||||
#define MLXBF_I2C_MASTER_ENABLE_WRITE \
|
||||
(MLXBF_I2C_MASTER_ENABLE | MLXBF_I2C_MASTER_CTL_WRITE_BIT)
|
||||
|
|
@ -338,6 +338,7 @@ enum {
|
|||
MLXBF_I2C_F_SMBUS_BLOCK = BIT(5),
|
||||
MLXBF_I2C_F_SMBUS_PEC = BIT(6),
|
||||
MLXBF_I2C_F_SMBUS_PROCESS_CALL = BIT(7),
|
||||
MLXBF_I2C_F_WRITE_WITHOUT_STOP = BIT(8),
|
||||
};
|
||||
|
||||
/* Mellanox BlueField chip type. */
|
||||
|
|
@ -638,16 +639,19 @@ static void mlxbf_i2c_smbus_read_data(struct mlxbf_i2c_priv *priv,
|
|||
}
|
||||
|
||||
static int mlxbf_i2c_smbus_enable(struct mlxbf_i2c_priv *priv, u8 slave,
|
||||
u8 len, u8 block_en, u8 pec_en, bool read)
|
||||
u8 len, u8 block_en, u8 pec_en, bool read,
|
||||
bool stop)
|
||||
{
|
||||
u32 command;
|
||||
u32 command = 0;
|
||||
|
||||
/* Set Master GW control word. */
|
||||
if (stop)
|
||||
command |= MLXBF_I2C_MASTER_STOP_BIT;
|
||||
if (read) {
|
||||
command = MLXBF_I2C_MASTER_ENABLE_READ;
|
||||
command |= MLXBF_I2C_MASTER_ENABLE_READ;
|
||||
command |= rol32(len, MLXBF_I2C_MASTER_READ_SHIFT);
|
||||
} else {
|
||||
command = MLXBF_I2C_MASTER_ENABLE_WRITE;
|
||||
command |= MLXBF_I2C_MASTER_ENABLE_WRITE;
|
||||
command |= rol32(len, MLXBF_I2C_MASTER_WRITE_SHIFT);
|
||||
}
|
||||
command |= rol32(slave, MLXBF_I2C_MASTER_SLV_ADDR_SHIFT);
|
||||
|
|
@ -682,8 +686,10 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv,
|
|||
u8 op_idx, data_idx, data_len, write_len, read_len;
|
||||
struct mlxbf_i2c_smbus_operation *operation;
|
||||
u8 read_en, write_en, block_en, pec_en;
|
||||
u8 slave, flags, addr;
|
||||
bool stop_after_write = true;
|
||||
u8 slave, addr;
|
||||
u8 *read_buf;
|
||||
u32 flags;
|
||||
u32 bits;
|
||||
int ret;
|
||||
|
||||
|
|
@ -755,7 +761,16 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv,
|
|||
memcpy(data_desc + data_idx,
|
||||
operation->buffer, operation->length);
|
||||
data_idx += operation->length;
|
||||
|
||||
/*
|
||||
* The stop condition can be skipped when writing on the bus
|
||||
* to implement a repeated start condition on the next read
|
||||
* as required for several SMBus and I2C operations.
|
||||
*/
|
||||
if (flags & MLXBF_I2C_F_WRITE_WITHOUT_STOP)
|
||||
stop_after_write = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* We assume that read operations are performed only once per
|
||||
* SMBus transaction. *TBD* protect this statement so it won't
|
||||
|
|
@ -781,7 +796,7 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv,
|
|||
|
||||
if (write_en) {
|
||||
ret = mlxbf_i2c_smbus_enable(priv, slave, write_len, block_en,
|
||||
pec_en, 0);
|
||||
pec_en, 0, stop_after_write);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
|
@ -791,7 +806,7 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv,
|
|||
mlxbf_i2c_smbus_write_data(priv, (const u8 *)&addr, 1,
|
||||
MLXBF_I2C_MASTER_DATA_DESC_ADDR, true);
|
||||
ret = mlxbf_i2c_smbus_enable(priv, slave, read_len, block_en,
|
||||
pec_en, 1);
|
||||
pec_en, 1, true);
|
||||
if (!ret) {
|
||||
/* Get Master GW data descriptor. */
|
||||
mlxbf_i2c_smbus_read_data(priv, data_desc, read_len + 1,
|
||||
|
|
@ -897,6 +912,9 @@ mlxbf_i2c_smbus_i2c_block_func(struct mlxbf_i2c_smbus_request *request,
|
|||
request->operation[0].flags |= pec_check ? MLXBF_I2C_F_SMBUS_PEC : 0;
|
||||
request->operation[0].buffer = command;
|
||||
|
||||
if (read)
|
||||
request->operation[0].flags |= MLXBF_I2C_F_WRITE_WITHOUT_STOP;
|
||||
|
||||
/*
|
||||
* As specified in the standard, the max number of bytes to read/write
|
||||
* per block operation is 32 bytes. In Golan code, the controller can
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user