diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-mlxbf.c')
-rw-r--r-- | drivers/i2c/busses/i2c-mlxbf.c | 195 |
1 files changed, 78 insertions, 117 deletions
diff --git a/drivers/i2c/busses/i2c-mlxbf.c b/drivers/i2c/busses/i2c-mlxbf.c index b3a73921ab69..8345f7e6385d 100644 --- a/drivers/i2c/busses/i2c-mlxbf.c +++ b/drivers/i2c/busses/i2c-mlxbf.c @@ -12,12 +12,14 @@ #include <linux/interrupt.h> #include <linux/i2c.h> #include <linux/io.h> +#include <linux/iopoll.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/string.h> +#include <linux/string_choices.h> /* Defines what functionality is present. */ #define MLXBF_I2C_FUNC_SMBUS_BLOCK \ @@ -196,6 +198,7 @@ #define MLXBF_I2C_MASK_8 GENMASK(7, 0) #define MLXBF_I2C_MASK_16 GENMASK(15, 0) +#define MLXBF_I2C_MASK_32 GENMASK(31, 0) #define MLXBF_I2C_MST_ADDR_OFFSET 0x200 @@ -222,7 +225,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) @@ -336,6 +339,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. */ @@ -495,65 +499,6 @@ static u8 mlxbf_i2c_bus_count; static struct mutex mlxbf_i2c_bus_lock; -/* - * Function to poll a set of bits at a specific address; it checks whether - * the bits are equal to zero when eq_zero is set to 'true', and not equal - * to zero when eq_zero is set to 'false'. - * Note that the timeout is given in microseconds. - */ -static u32 mlxbf_i2c_poll(void __iomem *io, u32 addr, u32 mask, - bool eq_zero, u32 timeout) -{ - u32 bits; - - timeout = (timeout / MLXBF_I2C_POLL_FREQ_IN_USEC) + 1; - - do { - bits = readl(io + addr) & mask; - if (eq_zero ? bits == 0 : bits != 0) - return eq_zero ? 1 : bits; - udelay(MLXBF_I2C_POLL_FREQ_IN_USEC); - } while (timeout-- != 0); - - return 0; -} - -/* - * SW must make sure that the SMBus Master GW is idle before starting - * a transaction. Accordingly, this function polls the Master FSM stop - * bit; it returns false when the bit is asserted, true if not. - */ -static bool mlxbf_i2c_smbus_master_wait_for_idle(struct mlxbf_i2c_priv *priv) -{ - u32 mask = MLXBF_I2C_SMBUS_MASTER_FSM_STOP_MASK; - u32 addr = priv->chip->smbus_master_fsm_off; - u32 timeout = MLXBF_I2C_SMBUS_TIMEOUT; - - if (mlxbf_i2c_poll(priv->mst->io, addr, mask, true, timeout)) - return true; - - return false; -} - -/* - * wait for the lock to be released before acquiring it. - */ -static bool mlxbf_i2c_smbus_master_lock(struct mlxbf_i2c_priv *priv) -{ - if (mlxbf_i2c_poll(priv->mst->io, MLXBF_I2C_SMBUS_MASTER_GW, - MLXBF_I2C_MASTER_LOCK_BIT, true, - MLXBF_I2C_SMBUS_LOCK_POLL_TIMEOUT)) - return true; - - return false; -} - -static void mlxbf_i2c_smbus_master_unlock(struct mlxbf_i2c_priv *priv) -{ - /* Clear the gw to clear the lock */ - writel(0, priv->mst->io + MLXBF_I2C_SMBUS_MASTER_GW); -} - static bool mlxbf_i2c_smbus_transaction_success(u32 master_status, u32 cause_status) { @@ -583,6 +528,7 @@ static int mlxbf_i2c_smbus_check_status(struct mlxbf_i2c_priv *priv) { u32 master_status_bits; u32 cause_status_bits; + u32 bits; /* * GW busy bit is raised by the driver and cleared by the HW @@ -591,9 +537,9 @@ static int mlxbf_i2c_smbus_check_status(struct mlxbf_i2c_priv *priv) * then read the cause and master status bits to determine if * errors occurred during the transaction. */ - mlxbf_i2c_poll(priv->mst->io, MLXBF_I2C_SMBUS_MASTER_GW, - MLXBF_I2C_MASTER_BUSY_BIT, true, - MLXBF_I2C_SMBUS_TIMEOUT); + readl_poll_timeout_atomic(priv->mst->io + MLXBF_I2C_SMBUS_MASTER_GW, + bits, !(bits & MLXBF_I2C_MASTER_BUSY_BIT), + MLXBF_I2C_POLL_FREQ_IN_USEC, MLXBF_I2C_SMBUS_TIMEOUT); /* Read cause status bits. */ cause_status_bits = readl(priv->mst_cause->io + @@ -694,16 +640,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); @@ -738,9 +687,12 @@ 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; - int ret = 0; + u32 flags; + u32 bits; + int ret; if (request->operation_cnt > MLXBF_I2C_SMBUS_MAX_OP_CNT) return -EINVAL; @@ -760,11 +712,22 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv, * Try to acquire the smbus gw lock before any reads of the GW register since * a read sets the lock. */ - if (WARN_ON(!mlxbf_i2c_smbus_master_lock(priv))) + ret = readl_poll_timeout_atomic(priv->mst->io + MLXBF_I2C_SMBUS_MASTER_GW, + bits, !(bits & MLXBF_I2C_MASTER_LOCK_BIT), + MLXBF_I2C_POLL_FREQ_IN_USEC, + MLXBF_I2C_SMBUS_LOCK_POLL_TIMEOUT); + if (WARN_ON(ret)) return -EBUSY; - /* Check whether the HW is idle */ - if (WARN_ON(!mlxbf_i2c_smbus_master_wait_for_idle(priv))) { + /* + * SW must make sure that the SMBus Master GW is idle before starting + * a transaction. Accordingly, this call polls the Master FSM stop bit; + * it returns -ETIMEDOUT when the bit is asserted, 0 if not. + */ + ret = readl_poll_timeout_atomic(priv->mst->io + priv->chip->smbus_master_fsm_off, + bits, !(bits & MLXBF_I2C_SMBUS_MASTER_FSM_STOP_MASK), + MLXBF_I2C_POLL_FREQ_IN_USEC, MLXBF_I2C_SMBUS_TIMEOUT); + if (WARN_ON(ret)) { ret = -EBUSY; goto out_unlock; } @@ -799,7 +762,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 @@ -825,7 +797,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; } @@ -835,7 +807,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, @@ -855,7 +827,8 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv, } out_unlock: - mlxbf_i2c_smbus_master_unlock(priv); + /* Clear the gw to clear the lock */ + writel(0, priv->mst->io + MLXBF_I2C_SMBUS_MASTER_GW); return ret; } @@ -940,6 +913,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 @@ -1107,7 +1083,7 @@ static u32 mlxbf_i2c_get_ticks(struct mlxbf_i2c_priv *priv, u64 nanoseconds, * Frequency */ frequency = priv->frequency; - ticks = (nanoseconds * frequency) / MLXBF_I2C_FREQUENCY_1GHZ; + ticks = div_u64(nanoseconds * frequency, MLXBF_I2C_FREQUENCY_1GHZ); /* * The number of ticks is rounded down and if minimum is equal to 1 * then add one tick. @@ -1174,7 +1150,8 @@ static void mlxbf_i2c_set_timings(struct mlxbf_i2c_priv *priv, MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_16); writel(timer, priv->timer->io + MLXBF_I2C_SMBUS_THIGH_MAX_TBUF); - timer = timings->timeout; + timer = mlxbf_i2c_set_timer(priv, timings->timeout, false, + MLXBF_I2C_MASK_32, MLXBF_I2C_SHIFT_0); writel(timer, priv->timer->io + MLXBF_I2C_SMBUS_SCL_LOW_TIMEOUT); } @@ -1184,11 +1161,7 @@ enum mlxbf_i2c_timings_config { MLXBF_I2C_TIMING_CONFIG_1000KHZ, }; -/* - * Note that the mlxbf_i2c_timings->timeout value is not related to the - * bus frequency, it is impacted by the time it takes the driver to - * complete data transmission before transaction abort. - */ +/* Timing values are in nanoseconds */ static const struct mlxbf_i2c_timings mlxbf_i2c_timings[] = { [MLXBF_I2C_TIMING_CONFIG_100KHZ] = { .scl_high = 4810, @@ -1203,8 +1176,8 @@ static const struct mlxbf_i2c_timings mlxbf_i2c_timings[] = { .scl_fall = 50, .hold_data = 300, .buf = 20000, - .thigh_max = 5000, - .timeout = 106500 + .thigh_max = 50000, + .timeout = 35000000 }, [MLXBF_I2C_TIMING_CONFIG_400KHZ] = { .scl_high = 1011, @@ -1219,24 +1192,24 @@ static const struct mlxbf_i2c_timings mlxbf_i2c_timings[] = { .scl_fall = 50, .hold_data = 300, .buf = 20000, - .thigh_max = 5000, - .timeout = 106500 + .thigh_max = 50000, + .timeout = 35000000 }, [MLXBF_I2C_TIMING_CONFIG_1000KHZ] = { - .scl_high = 600, - .scl_low = 1300, + .scl_high = 383, + .scl_low = 460, .hold_start = 600, - .setup_start = 600, - .setup_stop = 600, - .setup_data = 100, + .setup_start = 260, + .setup_stop = 260, + .setup_data = 50, .sda_rise = 50, .sda_fall = 50, .scl_rise = 50, .scl_fall = 50, .hold_data = 300, - .buf = 20000, - .thigh_max = 5000, - .timeout = 106500 + .buf = 500, + .thigh_max = 50000, + .timeout = 35000000 } }; @@ -1487,9 +1460,8 @@ static u64 mlxbf_i2c_calculate_freq_from_tyu(struct mlxbf_i2c_resource *corepll_ * and PadFrequency, respectively. */ core_frequency = MLXBF_I2C_PLL_IN_FREQ * (++core_f); - core_frequency /= (++core_r) * (++core_od); - return core_frequency; + return div_u64(core_frequency, (++core_r) * (++core_od)); } static u64 mlxbf_i2c_calculate_freq_from_yu(struct mlxbf_i2c_resource *corepll_res) @@ -1518,9 +1490,8 @@ static u64 mlxbf_i2c_calculate_freq_from_yu(struct mlxbf_i2c_resource *corepll_r * and PadFrequency, respectively. */ corepll_frequency = (MLXBF_I2C_PLL_IN_FREQ * core_f) / MLNXBF_I2C_COREPLL_CONST; - corepll_frequency /= (++core_r) * (++core_od); - return corepll_frequency; + return div_u64(corepll_frequency, (++core_r) * (++core_od)); } static int mlxbf_i2c_calculate_corepll_freq(struct platform_device *pdev, @@ -1829,18 +1800,6 @@ static bool mlxbf_i2c_has_coalesce(struct mlxbf_i2c_priv *priv, bool *read, return true; } -static bool mlxbf_i2c_slave_wait_for_idle(struct mlxbf_i2c_priv *priv, - u32 timeout) -{ - u32 mask = MLXBF_I2C_CAUSE_S_GW_BUSY_FALL; - u32 addr = MLXBF_I2C_CAUSE_ARBITER; - - if (mlxbf_i2c_poll(priv->slv_cause->io, addr, mask, false, timeout)) - return true; - - return false; -} - static struct i2c_client *mlxbf_i2c_get_slave_from_addr( struct mlxbf_i2c_priv *priv, u8 addr) { @@ -1943,7 +1902,9 @@ static int mlxbf_i2c_irq_send(struct mlxbf_i2c_priv *priv, u8 recv_bytes) * Wait until the transfer is completed; the driver will wait * until the GW is idle, a cause will rise on fall of GW busy. */ - mlxbf_i2c_slave_wait_for_idle(priv, MLXBF_I2C_SMBUS_TIMEOUT); + readl_poll_timeout_atomic(priv->slv_cause->io + MLXBF_I2C_CAUSE_ARBITER, + data32, data32 & MLXBF_I2C_CAUSE_S_GW_BUSY_FALL, + MLXBF_I2C_POLL_FREQ_IN_USEC, MLXBF_I2C_SMBUS_TIMEOUT); clear_csr: /* Release the Slave GW. */ @@ -2092,21 +2053,21 @@ static s32 mlxbf_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr, read ? &data->byte : &command, read, pec); dev_dbg(&adap->dev, "smbus %s byte, slave 0x%02x.\n", - read ? "read" : "write", addr); + str_read_write(read), addr); break; case I2C_SMBUS_BYTE_DATA: mlxbf_i2c_smbus_data_byte_func(&request, &command, &data->byte, read, pec); dev_dbg(&adap->dev, "smbus %s byte data at 0x%02x, slave 0x%02x.\n", - read ? "read" : "write", command, addr); + str_read_write(read), command, addr); break; case I2C_SMBUS_WORD_DATA: mlxbf_i2c_smbus_data_word_func(&request, &command, (u8 *)&data->word, read, pec); dev_dbg(&adap->dev, "smbus %s word data at 0x%02x, slave 0x%02x.\n", - read ? "read" : "write", command, addr); + str_read_write(read), command, addr); break; case I2C_SMBUS_I2C_BLOCK_DATA: @@ -2114,7 +2075,7 @@ static s32 mlxbf_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr, mlxbf_i2c_smbus_i2c_block_func(&request, &command, data->block, &byte_cnt, read, pec); dev_dbg(&adap->dev, "i2c %s block data, %d bytes at 0x%02x, slave 0x%02x.\n", - read ? "read" : "write", byte_cnt, command, addr); + str_read_write(read), byte_cnt, command, addr); break; case I2C_SMBUS_BLOCK_DATA: @@ -2122,7 +2083,7 @@ static s32 mlxbf_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr, mlxbf_i2c_smbus_block_func(&request, &command, data->block, &byte_cnt, read, pec); dev_dbg(&adap->dev, "smbus %s block data, %d bytes at 0x%02x, slave 0x%02x.\n", - read ? "read" : "write", byte_cnt, command, addr); + str_read_write(read), byte_cnt, command, addr); break; case I2C_FUNC_SMBUS_PROC_CALL: @@ -2456,7 +2417,7 @@ static void mlxbf_i2c_remove(struct platform_device *pdev) static struct platform_driver mlxbf_i2c_driver = { .probe = mlxbf_i2c_probe, - .remove_new = mlxbf_i2c_remove, + .remove = mlxbf_i2c_remove, .driver = { .name = "i2c-mlxbf", .acpi_match_table = ACPI_PTR(mlxbf_i2c_acpi_ids), |