i2c: tegra: Factor out packet header setup from tegra_i2c_xfer_msg()

The code related to packet header setting up is a bit messy and makes
tegra_i2c_xfer_msg() more difficult to read than it could be. Let's
factor the packet header setup from tegra_i2c_xfer_msg() into separate
function in order to make code easier to read and follow.

Reviewed-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Acked-by: Thierry Reding <treding@nvidia.com>
Tested-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Wolfram Sang <wsa@kernel.org>
This commit is contained in:
Dmitry Osipenko 2020-09-30 01:19:06 +03:00 committed by Wolfram Sang
parent 4a8e0f8797
commit 4be62340f3

View file

@ -281,7 +281,7 @@ struct tegra_i2c_dev {
struct dma_chan *tx_dma_chan;
struct dma_chan *rx_dma_chan;
dma_addr_t dma_phys;
u32 *dma_buf;
void *dma_buf;
unsigned int dma_buf_size;
bool is_curr_dma_xfer;
struct completion dma_complete;
@ -1105,6 +1105,57 @@ static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap)
return -EAGAIN;
}
static void tegra_i2c_push_packet_header(struct tegra_i2c_dev *i2c_dev,
struct i2c_msg *msg,
enum msg_end_type end_state)
{
u32 *dma_buf = i2c_dev->dma_buf;
u32 packet_header;
packet_header = FIELD_PREP(PACKET_HEADER0_HEADER_SIZE, 0) |
FIELD_PREP(PACKET_HEADER0_PROTOCOL,
PACKET_HEADER0_PROTOCOL_I2C) |
FIELD_PREP(PACKET_HEADER0_CONT_ID, i2c_dev->cont_id) |
FIELD_PREP(PACKET_HEADER0_PACKET_ID, 1);
if (i2c_dev->is_curr_dma_xfer && !i2c_dev->msg_read)
*dma_buf++ = packet_header;
else
i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
packet_header = msg->len - 1;
if (i2c_dev->is_curr_dma_xfer && !i2c_dev->msg_read)
*dma_buf++ = packet_header;
else
i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
packet_header = I2C_HEADER_IE_ENABLE;
if (end_state == MSG_END_CONTINUE)
packet_header |= I2C_HEADER_CONTINUE_XFER;
else if (end_state == MSG_END_REPEAT_START)
packet_header |= I2C_HEADER_REPEAT_START;
if (msg->flags & I2C_M_TEN) {
packet_header |= msg->addr;
packet_header |= I2C_HEADER_10BIT_ADDR;
} else {
packet_header |= msg->addr << I2C_HEADER_SLAVE_ADDR_SHIFT;
}
if (msg->flags & I2C_M_IGNORE_NAK)
packet_header |= I2C_HEADER_CONT_ON_NAK;
if (msg->flags & I2C_M_RD)
packet_header |= I2C_HEADER_READ;
if (i2c_dev->is_curr_dma_xfer && !i2c_dev->msg_read)
*dma_buf++ = packet_header;
else
i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
}
static int tegra_i2c_error_recover(struct tegra_i2c_dev *i2c_dev,
struct i2c_msg *msg)
{
@ -1135,11 +1186,9 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
struct i2c_msg *msg,
enum msg_end_type end_state)
{
u32 packet_header;
u32 int_mask;
unsigned long time_left;
size_t xfer_size;
u32 *buffer = NULL;
int err = 0;
u16 xfer_time = 100;
@ -1192,49 +1241,15 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
i2c_dev->dma_phys,
xfer_size,
DMA_TO_DEVICE);
buffer = i2c_dev->dma_buf;
}
}
packet_header = FIELD_PREP(PACKET_HEADER0_HEADER_SIZE, 0) |
FIELD_PREP(PACKET_HEADER0_PROTOCOL,
PACKET_HEADER0_PROTOCOL_I2C) |
FIELD_PREP(PACKET_HEADER0_CONT_ID, i2c_dev->cont_id) |
FIELD_PREP(PACKET_HEADER0_PACKET_ID, 1);
if (i2c_dev->is_curr_dma_xfer && !i2c_dev->msg_read)
*buffer++ = packet_header;
else
i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
packet_header = msg->len - 1;
if (i2c_dev->is_curr_dma_xfer && !i2c_dev->msg_read)
*buffer++ = packet_header;
else
i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
packet_header = I2C_HEADER_IE_ENABLE;
if (end_state == MSG_END_CONTINUE)
packet_header |= I2C_HEADER_CONTINUE_XFER;
else if (end_state == MSG_END_REPEAT_START)
packet_header |= I2C_HEADER_REPEAT_START;
if (msg->flags & I2C_M_TEN) {
packet_header |= msg->addr;
packet_header |= I2C_HEADER_10BIT_ADDR;
} else {
packet_header |= msg->addr << I2C_HEADER_SLAVE_ADDR_SHIFT;
}
if (msg->flags & I2C_M_IGNORE_NAK)
packet_header |= I2C_HEADER_CONT_ON_NAK;
if (msg->flags & I2C_M_RD)
packet_header |= I2C_HEADER_READ;
if (i2c_dev->is_curr_dma_xfer && !i2c_dev->msg_read)
*buffer++ = packet_header;
else
i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
tegra_i2c_push_packet_header(i2c_dev, msg, end_state);
if (!i2c_dev->msg_read) {
if (i2c_dev->is_curr_dma_xfer) {
memcpy(buffer, msg->buf, msg->len);
memcpy(i2c_dev->dma_buf + I2C_PACKET_HEADER_SIZE,
msg->buf, msg->len);
dma_sync_single_for_device(i2c_dev->dev,
i2c_dev->dma_phys,
xfer_size,