diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-07 21:36:18 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-07 21:36:18 +0200 |
commit | 0d5b1bd332e09acffa6569dd6458199b3894d496 (patch) | |
tree | 6c103cb045f0990ae4aae9a2ea4af1c26bfe6390 /drivers/i2c/busses/i2c-qup.c | |
parent | Merge tag 'powerpc-4.17-1' of git://git.kernel.org/pub/scm/linux/kernel/git/p... (diff) | |
parent | i2c: add support for Socionext SynQuacer I2C controller (diff) | |
download | linux-0d5b1bd332e09acffa6569dd6458199b3894d496.tar.xz linux-0d5b1bd332e09acffa6569dd6458199b3894d496.zip |
Merge branch 'i2c/for-4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang:
-I2C core now reports proper OF style module alias. I'd like to repeat
the note from the commit msg here (Thanks, Javier!):
NOTE: This patch may break out-of-tree drivers that were relying
on this behavior, and only had an I2C device ID table even
when the device was registered via OF.
There are no remaining drivers in mainline that do this, but
out-of-tree drivers have to be fixed and define a proper OF
device ID table to have module auto-loading working.
- new driver for the SynQuacer I2C controller
- major refactoring of the QUP driver
- the piix4 driver now uses request_muxed_region which should fix a
long standing resource conflict with the sp5100_tco watchdog
- a bunch of small core & driver improvements
* 'i2c/for-4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (53 commits)
i2c: add support for Socionext SynQuacer I2C controller
dt-bindings: i2c: add binding for Socionext SynQuacer I2C
i2c: Update i2c_trace_msg static key to modern api
i2c: fix parameter of trace_i2c_result
i2c: imx: avoid taking clk_prepare mutex in PM callbacks
i2c: imx: use clk notifier for rate changes
i2c: make i2c_check_addr_validity() static
i2c: rcar: fix mask value of prohibited bit
dt-bindings: i2c: document R8A77965 bindings
i2c: pca-platform: drop gpio from platform data
i2c: pca-platform: use device_property_read_u32
i2c: pca-platform: unconditionally use devm_gpiod_get_optional
sh: sh7785lcr: add GPIO lookup table for i2c controller reset
i2c: qup: reorganization of driver code to remove polling for qup v2
i2c: qup: reorganization of driver code to remove polling for qup v1
i2c: qup: send NACK for last read sub transfers
i2c: qup: fix buffer overflow for multiple msg of maximum xfer len
i2c: qup: change completion timeout according to transfer length
i2c: qup: use the complete transfer length to choose DMA mode
i2c: qup: proper error handling for i2c error in BAM mode
...
Diffstat (limited to 'drivers/i2c/busses/i2c-qup.c')
-rw-r--r-- | drivers/i2c/busses/i2c-qup.c | 1471 |
1 files changed, 862 insertions, 609 deletions
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index 08f8e0107642..904dfec7ab96 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2009-2013, 2016-2018, The Linux Foundation. All rights reserved. * Copyright (c) 2014, Sony Mobile Communications AB. * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #include <linux/acpi.h> @@ -73,8 +64,11 @@ #define QUP_IN_SVC_FLAG BIT(9) #define QUP_MX_OUTPUT_DONE BIT(10) #define QUP_MX_INPUT_DONE BIT(11) +#define OUT_BLOCK_WRITE_REQ BIT(12) +#define IN_BLOCK_READ_REQ BIT(13) /* I2C mini core related values */ +#define QUP_NO_INPUT BIT(7) #define QUP_CLOCK_AUTO_GATE BIT(13) #define I2C_MINI_CORE (2 << 8) #define I2C_N_VAL 15 @@ -113,6 +107,7 @@ #define QUP_TAG_V2_DATAWR 0x82 #define QUP_TAG_V2_DATAWR_STOP 0x83 #define QUP_TAG_V2_DATARD 0x85 +#define QUP_TAG_V2_DATARD_NACK 0x86 #define QUP_TAG_V2_DATARD_STOP 0x87 /* Status, Error flags */ @@ -127,23 +122,87 @@ #define ONE_BYTE 0x1 #define QUP_I2C_MX_CONFIG_DURING_RUN BIT(31) +/* Maximum transfer length for single DMA descriptor */ #define MX_TX_RX_LEN SZ_64K #define MX_BLOCKS (MX_TX_RX_LEN / QUP_READ_LIMIT) +/* Maximum transfer length for all DMA descriptors */ +#define MX_DMA_TX_RX_LEN (2 * MX_TX_RX_LEN) +#define MX_DMA_BLOCKS (MX_DMA_TX_RX_LEN / QUP_READ_LIMIT) -/* Max timeout in ms for 32k bytes */ -#define TOUT_MAX 300 +/* + * Minimum transfer timeout for i2c transfers in seconds. It will be added on + * the top of maximum transfer time calculated from i2c bus speed to compensate + * the overheads. + */ +#define TOUT_MIN 2 /* Default values. Use these if FW query fails */ #define DEFAULT_CLK_FREQ 100000 #define DEFAULT_SRC_CLK 20000000 +/* + * Max tags length (start, stop and maximum 2 bytes address) for each QUP + * data transfer + */ +#define QUP_MAX_TAGS_LEN 4 +/* Max data length for each DATARD tags */ +#define RECV_MAX_DATA_LEN 254 +/* TAG length for DATA READ in RX FIFO */ +#define READ_RX_TAGS_LEN 2 + +/* + * count: no of blocks + * pos: current block number + * tx_tag_len: tx tag length for current block + * rx_tag_len: rx tag length for current block + * data_len: remaining data length for current message + * cur_blk_len: data length for current block + * total_tx_len: total tx length including tag bytes for current QUP transfer + * total_rx_len: total rx length including tag bytes for current QUP transfer + * tx_fifo_data_pos: current byte number in TX FIFO word + * tx_fifo_free: number of free bytes in current QUP block write. + * rx_fifo_data_pos: current byte number in RX FIFO word + * fifo_available: number of available bytes in RX FIFO for current + * QUP block read + * tx_fifo_data: QUP TX FIFO write works on word basis (4 bytes). New byte write + * to TX FIFO will be appended in this data and will be written to + * TX FIFO when all the 4 bytes are available. + * rx_fifo_data: QUP RX FIFO read works on word basis (4 bytes). This will + * contains the 4 bytes of RX data. + * cur_data: pointer to tell cur data position for current message + * cur_tx_tags: pointer to tell cur position in tags + * tx_tags_sent: all tx tag bytes have been written in FIFO word + * send_last_word: for tx FIFO, last word send is pending in current block + * rx_bytes_read: if all the bytes have been read from rx FIFO. + * rx_tags_fetched: all the rx tag bytes have been fetched from rx fifo word + * is_tx_blk_mode: whether tx uses block or FIFO mode in case of non BAM xfer. + * is_rx_blk_mode: whether rx uses block or FIFO mode in case of non BAM xfer. + * tags: contains tx tag bytes for current QUP transfer + */ struct qup_i2c_block { - int count; - int pos; - int tx_tag_len; - int rx_tag_len; - int data_len; - u8 tags[6]; + int count; + int pos; + int tx_tag_len; + int rx_tag_len; + int data_len; + int cur_blk_len; + int total_tx_len; + int total_rx_len; + int tx_fifo_data_pos; + int tx_fifo_free; + int rx_fifo_data_pos; + int fifo_available; + u32 tx_fifo_data; + u32 rx_fifo_data; + u8 *cur_data; + u8 *cur_tx_tags; + bool tx_tags_sent; + bool send_last_word; + bool rx_tags_fetched; + bool rx_bytes_read; + bool is_tx_blk_mode; + bool is_rx_blk_mode; + u8 tags[6]; }; struct qup_i2c_tag { @@ -155,6 +214,7 @@ struct qup_i2c_bam { struct qup_i2c_tag tag; struct dma_chan *dma; struct scatterlist *sg; + unsigned int sg_cnt; }; struct qup_i2c_dev { @@ -171,7 +231,9 @@ struct qup_i2c_dev { int out_blk_sz; int in_blk_sz; + int blk_xfer_limit; unsigned long one_byte_t; + unsigned long xfer_timeout; struct qup_i2c_block blk; struct i2c_msg *msg; @@ -184,23 +246,37 @@ struct qup_i2c_dev { /* To check if this is the last msg */ bool is_last; + bool is_smbus_read; /* To configure when bus is in run state */ - int config_run; + u32 config_run; /* dma parameters */ bool is_dma; + /* To check if the current transfer is using DMA */ + bool use_dma; + unsigned int max_xfer_sg_len; + unsigned int tag_buf_pos; + /* The threshold length above which block mode will be used */ + unsigned int blk_mode_threshold; struct dma_pool *dpool; struct qup_i2c_tag start_tag; struct qup_i2c_bam brx; struct qup_i2c_bam btx; struct completion xfer; + /* function to write data in tx fifo */ + void (*write_tx_fifo)(struct qup_i2c_dev *qup); + /* function to read data from rx fifo */ + void (*read_rx_fifo)(struct qup_i2c_dev *qup); + /* function to write tags in tx fifo for i2c read transfer */ + void (*write_rx_tags)(struct qup_i2c_dev *qup); }; static irqreturn_t qup_i2c_interrupt(int irq, void *dev) { struct qup_i2c_dev *qup = dev; + struct qup_i2c_block *blk = &qup->blk; u32 bus_err; u32 qup_err; u32 opflags; @@ -226,17 +302,65 @@ static irqreturn_t qup_i2c_interrupt(int irq, void *dev) if (bus_err) writel(bus_err, qup->base + QUP_I2C_STATUS); + /* + * Check for BAM mode and returns if already error has come for current + * transfer. In Error case, sometimes, QUP generates more than one + * interrupt. + */ + if (qup->use_dma && (qup->qup_err || qup->bus_err)) + return IRQ_HANDLED; + /* Reset the QUP State in case of error */ if (qup_err || bus_err) { - writel(QUP_RESET_STATE, qup->base + QUP_STATE); + /* + * Don’t reset the QUP state in case of BAM mode. The BAM + * flush operation needs to be scheduled in transfer function + * which will clear the remaining schedule descriptors in BAM + * HW FIFO and generates the BAM interrupt. + */ + if (!qup->use_dma) + writel(QUP_RESET_STATE, qup->base + QUP_STATE); goto done; } - if (opflags & QUP_IN_SVC_FLAG) + if (opflags & QUP_OUT_SVC_FLAG) { + writel(QUP_OUT_SVC_FLAG, qup->base + QUP_OPERATIONAL); + + if (opflags & OUT_BLOCK_WRITE_REQ) { + blk->tx_fifo_free += qup->out_blk_sz; + if (qup->msg->flags & I2C_M_RD) + qup->write_rx_tags(qup); + else + qup->write_tx_fifo(qup); + } + } + + if (opflags & QUP_IN_SVC_FLAG) { writel(QUP_IN_SVC_FLAG, qup->base + QUP_OPERATIONAL); - if (opflags & QUP_OUT_SVC_FLAG) - writel(QUP_OUT_SVC_FLAG, qup->base + QUP_OPERATIONAL); + if (!blk->is_rx_blk_mode) { + blk->fifo_available += qup->in_fifo_sz; + qup->read_rx_fifo(qup); + } else if (opflags & IN_BLOCK_READ_REQ) { + blk->fifo_available += qup->in_blk_sz; + qup->read_rx_fifo(qup); + } + } + + if (qup->msg->flags & I2C_M_RD) { + if (!blk->rx_bytes_read) + return IRQ_HANDLED; + } else { + /* + * Ideally, QUP_MAX_OUTPUT_DONE_FLAG should be checked + * for FIFO mode also. But, QUP_MAX_OUTPUT_DONE_FLAG lags + * behind QUP_OUTPUT_SERVICE_FLAG sometimes. The only reason + * of interrupt for write message in FIFO mode is + * QUP_MAX_OUTPUT_DONE_FLAG condition. + */ + if (blk->is_tx_blk_mode && !(opflags & QUP_MX_OUTPUT_DONE)) + return IRQ_HANDLED; + } done: qup->qup_err = qup_err; @@ -303,147 +427,47 @@ static int qup_i2c_change_state(struct qup_i2c_dev *qup, u32 state) return 0; } -/** - * qup_i2c_wait_ready - wait for a give number of bytes in tx/rx path - * @qup: The qup_i2c_dev device - * @op: The bit/event to wait on - * @val: value of the bit to wait on, 0 or 1 - * @len: The length the bytes to be transferred - */ -static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val, - int len) +/* Check if I2C bus returns to IDLE state */ +static int qup_i2c_bus_active(struct qup_i2c_dev *qup, int len) { unsigned long timeout; - u32 opflags; u32 status; - u32 shift = __ffs(op); int ret = 0; - len *= qup->one_byte_t; - /* timeout after a wait of twice the max time */ timeout = jiffies + len * 4; - for (;;) { - opflags = readl(qup->base + QUP_OPERATIONAL); status = readl(qup->base + QUP_I2C_STATUS); + if (!(status & I2C_STATUS_BUS_ACTIVE)) + break; - if (((opflags & op) >> shift) == val) { - if ((op == QUP_OUT_NOT_EMPTY) && qup->is_last) { - if (!(status & I2C_STATUS_BUS_ACTIVE)) { - ret = 0; - goto done; - } - } else { - ret = 0; - goto done; - } - } - - if (time_after(jiffies, timeout)) { + if (time_after(jiffies, timeout)) ret = -ETIMEDOUT; - goto done; - } - usleep_range(len, len * 2); - } - -done: - if (qup->bus_err || qup->qup_err) - ret = (qup->bus_err & QUP_I2C_NACK_FLAG) ? -ENXIO : -EIO; - - return ret; -} - -static void qup_i2c_set_write_mode_v2(struct qup_i2c_dev *qup, - struct i2c_msg *msg) -{ - /* Number of entries to shift out, including the tags */ - int total = msg->len + qup->blk.tx_tag_len; - - total |= qup->config_run; - - if (total < qup->out_fifo_sz) { - /* FIFO mode */ - writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE); - writel(total, qup->base + QUP_MX_WRITE_CNT); - } else { - /* BLOCK mode (transfer data on chunks) */ - writel(QUP_OUTPUT_BLK_MODE | QUP_REPACK_EN, - qup->base + QUP_IO_MODE); - writel(total, qup->base + QUP_MX_OUTPUT_CNT); - } -} - -static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg) -{ - /* Number of entries to shift out, including the start */ - int total = msg->len + 1; - - if (total < qup->out_fifo_sz) { - /* FIFO mode */ - writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE); - writel(total, qup->base + QUP_MX_WRITE_CNT); - } else { - /* BLOCK mode (transfer data on chunks) */ - writel(QUP_OUTPUT_BLK_MODE | QUP_REPACK_EN, - qup->base + QUP_IO_MODE); - writel(total, qup->base + QUP_MX_OUTPUT_CNT); - } -} - -static int check_for_fifo_space(struct qup_i2c_dev *qup) -{ - int ret; - - ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE); - if (ret) - goto out; - - ret = qup_i2c_wait_ready(qup, QUP_OUT_FULL, - RESET_BIT, 4 * ONE_BYTE); - if (ret) { - /* Fifo is full. Drain out the fifo */ - ret = qup_i2c_change_state(qup, QUP_RUN_STATE); - if (ret) - goto out; - ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, - RESET_BIT, 256 * ONE_BYTE); - if (ret) { - dev_err(qup->dev, "timeout for fifo out full"); - goto out; - } - - ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE); - if (ret) - goto out; + usleep_range(len, len * 2); } -out: return ret; } -static int qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg *msg) +static void qup_i2c_write_tx_fifo_v1(struct qup_i2c_dev *qup) { + struct qup_i2c_block *blk = &qup->blk; + struct i2c_msg *msg = qup->msg; u32 addr = msg->addr << 1; u32 qup_tag; int idx; u32 val; - int ret = 0; if (qup->pos == 0) { val = QUP_TAG_START | addr; idx = 1; + blk->tx_fifo_free--; } else { val = 0; idx = 0; } - while (qup->pos < msg->len) { - /* Check that there's space in the FIFO for our pair */ - ret = check_for_fifo_space(qup); - if (ret) - return ret; - + while (blk->tx_fifo_free && qup->pos < msg->len) { if (qup->pos == msg->len - 1) qup_tag = QUP_TAG_STOP; else @@ -460,70 +484,24 @@ static int qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg *msg) qup->pos++; idx++; + blk->tx_fifo_free--; } - - ret = qup_i2c_change_state(qup, QUP_RUN_STATE); - - return ret; } static void qup_i2c_set_blk_data(struct qup_i2c_dev *qup, struct i2c_msg *msg) { - memset(&qup->blk, 0, sizeof(qup->blk)); - + qup->blk.pos = 0; qup->blk.data_len = msg->len; - qup->blk.count = (msg->len + QUP_READ_LIMIT - 1) / QUP_READ_LIMIT; - - /* 4 bytes for first block and 2 writes for rest */ - qup->blk.tx_tag_len = 4 + (qup->blk.count - 1) * 2; - - /* There are 2 tag bytes that are read in to fifo for every block */ - if (msg->flags & I2C_M_RD) - qup->blk.rx_tag_len = qup->blk.count * 2; -} - -static int qup_i2c_send_data(struct qup_i2c_dev *qup, int tlen, u8 *tbuf, - int dlen, u8 *dbuf) -{ - u32 val = 0, idx = 0, pos = 0, i = 0, t; - int len = tlen + dlen; - u8 *buf = tbuf; - int ret = 0; - - while (len > 0) { - ret = check_for_fifo_space(qup); - if (ret) - return ret; - - t = (len >= 4) ? 4 : len; - - while (idx < t) { - if (!i && (pos >= tlen)) { - buf = dbuf; - pos = 0; - i = 1; - } - val |= buf[pos++] << (idx++ * 8); - } - - writel(val, qup->base + QUP_OUT_FIFO_BASE); - idx = 0; - val = 0; - len -= 4; - } - - ret = qup_i2c_change_state(qup, QUP_RUN_STATE); - - return ret; + qup->blk.count = DIV_ROUND_UP(msg->len, qup->blk_xfer_limit); } static int qup_i2c_get_data_len(struct qup_i2c_dev *qup) { int data_len; - if (qup->blk.data_len > QUP_READ_LIMIT) - data_len = QUP_READ_LIMIT; + if (qup->blk.data_len > qup->blk_xfer_limit) + data_len = qup->blk_xfer_limit; else data_len = qup->blk.data_len; @@ -540,9 +518,9 @@ static int qup_i2c_set_tags_smb(u16 addr, u8 *tags, struct qup_i2c_dev *qup, { int len = 0; - if (msg->len > 1) { + if (qup->is_smbus_read) { tags[len++] = QUP_TAG_V2_DATARD_STOP; - tags[len++] = qup_i2c_get_data_len(qup) - 1; + tags[len++] = qup_i2c_get_data_len(qup); } else { tags[len++] = QUP_TAG_V2_START; tags[len++] = addr & 0xff; @@ -558,7 +536,7 @@ static int qup_i2c_set_tags_smb(u16 addr, u8 *tags, struct qup_i2c_dev *qup, } static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup, - struct i2c_msg *msg, int is_dma) + struct i2c_msg *msg) { u16 addr = i2c_8bit_addr_from_msg(msg); int len = 0; @@ -586,7 +564,9 @@ static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup, tags[len++] = QUP_TAG_V2_DATAWR_STOP; } else { if (msg->flags & I2C_M_RD) - tags[len++] = QUP_TAG_V2_DATARD; + tags[len++] = qup->blk.pos == (qup->blk.count - 1) ? + QUP_TAG_V2_DATARD_NACK : + QUP_TAG_V2_DATARD; else tags[len++] = QUP_TAG_V2_DATAWR; } @@ -599,32 +579,9 @@ static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup, else tags[len++] = data_len; - if ((msg->flags & I2C_M_RD) && last && is_dma) { - tags[len++] = QUP_BAM_INPUT_EOT; - tags[len++] = QUP_BAM_FLUSH_STOP; - } - return len; } -static int qup_i2c_issue_xfer_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg) -{ - int data_len = 0, tag_len, index; - int ret; - - tag_len = qup_i2c_set_tags(qup->blk.tags, qup, msg, 0); - index = msg->len - qup->blk.data_len; - - /* only tags are written for read */ - if (!(msg->flags & I2C_M_RD)) - data_len = qup_i2c_get_data_len(qup); - - ret = qup_i2c_send_data(qup, tag_len, qup->blk.tags, - data_len, &msg->buf[index]); - qup->blk.data_len -= data_len; - - return ret; -} static void qup_i2c_bam_cb(void *data) { @@ -684,115 +641,109 @@ static int qup_i2c_req_dma(struct qup_i2c_dev *qup) return 0; } -static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg, - int num) +static int qup_i2c_bam_make_desc(struct qup_i2c_dev *qup, struct i2c_msg *msg) { - struct dma_async_tx_descriptor *txd, *rxd = NULL; - int ret = 0, idx = 0, limit = QUP_READ_LIMIT; - dma_cookie_t cookie_rx, cookie_tx; - u32 rx_nents = 0, tx_nents = 0, len, blocks, rem; - u32 i, tlen, tx_len, tx_buf = 0, rx_buf = 0, off = 0; + int ret = 0, limit = QUP_READ_LIMIT; + u32 len = 0, blocks, rem; + u32 i = 0, tlen, tx_len = 0; u8 *tags; - while (idx < num) { - tx_len = 0, len = 0, i = 0; - - qup->is_last = (idx == (num - 1)); - - qup_i2c_set_blk_data(qup, msg); + qup->blk_xfer_limit = QUP_READ_LIMIT; + qup_i2c_set_blk_data(qup, msg); - blocks = qup->blk.count; - rem = msg->len - (blocks - 1) * limit; + blocks = qup->blk.count; + rem = msg->len - (blocks - 1) * limit; - if (msg->flags & I2C_M_RD) { - rx_nents += (blocks * 2) + 1; - tx_nents += 1; + if (msg->flags & I2C_M_RD) { + while (qup->blk.pos < blocks) { + tlen = (i == (blocks - 1)) ? rem : limit; + tags = &qup->start_tag.start[qup->tag_buf_pos + len]; + len += qup_i2c_set_tags(tags, qup, msg); + qup->blk.data_len -= tlen; - while (qup->blk.pos < blocks) { - tlen = (i == (blocks - 1)) ? rem : limit; - tags = &qup->start_tag.start[off + len]; - len += qup_i2c_set_tags(tags, qup, msg, 1); - qup->blk.data_len -= tlen; + /* scratch buf to read the start and len tags */ + ret = qup_sg_set_buf(&qup->brx.sg[qup->brx.sg_cnt++], + &qup->brx.tag.start[0], + 2, qup, DMA_FROM_DEVICE); - /* scratch buf to read the start and len tags */ - ret = qup_sg_set_buf(&qup->brx.sg[rx_buf++], - &qup->brx.tag.start[0], - 2, qup, DMA_FROM_DEVICE); + if (ret) + return ret; - if (ret) - return ret; + ret = qup_sg_set_buf(&qup->brx.sg[qup->brx.sg_cnt++], + &msg->buf[limit * i], + tlen, qup, + DMA_FROM_DEVICE); + if (ret) + return ret; - ret = qup_sg_set_buf(&qup->brx.sg[rx_buf++], - &msg->buf[limit * i], - tlen, qup, - DMA_FROM_DEVICE); - if (ret) - return ret; + i++; + qup->blk.pos = i; + } + ret = qup_sg_set_buf(&qup->btx.sg[qup->btx.sg_cnt++], + &qup->start_tag.start[qup->tag_buf_pos], + len, qup, DMA_TO_DEVICE); + if (ret) + return ret; - i++; - qup->blk.pos = i; - } - ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++], - &qup->start_tag.start[off], - len, qup, DMA_TO_DEVICE); + qup->tag_buf_pos += len; + } else { + while (qup->blk.pos < blocks) { + tlen = (i == (blocks - 1)) ? rem : limit; + tags = &qup->start_tag.start[qup->tag_buf_pos + tx_len]; + len = qup_i2c_set_tags(tags, qup, msg); + qup->blk.data_len -= tlen; + + ret = qup_sg_set_buf(&qup->btx.sg[qup->btx.sg_cnt++], + tags, len, + qup, DMA_TO_DEVICE); if (ret) return ret; - off += len; - /* scratch buf to read the BAM EOT and FLUSH tags */ - ret = qup_sg_set_buf(&qup->brx.sg[rx_buf++], - &qup->brx.tag.start[0], - 2, qup, DMA_FROM_DEVICE); + tx_len += len; + ret = qup_sg_set_buf(&qup->btx.sg[qup->btx.sg_cnt++], + &msg->buf[limit * i], + tlen, qup, DMA_TO_DEVICE); if (ret) return ret; - } else { - tx_nents += (blocks * 2); - - while (qup->blk.pos < blocks) { - tlen = (i == (blocks - 1)) ? rem : limit; - tags = &qup->start_tag.start[off + tx_len]; - len = qup_i2c_set_tags(tags, qup, msg, 1); - qup->blk.data_len -= tlen; - - ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++], - tags, len, - qup, DMA_TO_DEVICE); - if (ret) - return ret; - - tx_len += len; - ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++], - &msg->buf[limit * i], - tlen, qup, DMA_TO_DEVICE); - if (ret) - return ret; - i++; - qup->blk.pos = i; - } - off += tx_len; - - if (idx == (num - 1)) { - len = 1; - if (rx_nents) { - qup->btx.tag.start[0] = - QUP_BAM_INPUT_EOT; - len++; - } - qup->btx.tag.start[len - 1] = - QUP_BAM_FLUSH_STOP; - ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++], - &qup->btx.tag.start[0], - len, qup, DMA_TO_DEVICE); - if (ret) - return ret; - tx_nents += 1; - } + i++; + qup->blk.pos = i; } - idx++; - msg++; + + qup->tag_buf_pos += tx_len; } - txd = dmaengine_prep_slave_sg(qup->btx.dma, qup->btx.sg, tx_nents, + return 0; +} + +static int qup_i2c_bam_schedule_desc(struct qup_i2c_dev *qup) +{ + struct dma_async_tx_descriptor *txd, *rxd = NULL; + int ret = 0; + dma_cookie_t cookie_rx, cookie_tx; + u32 len = 0; + u32 tx_cnt = qup->btx.sg_cnt, rx_cnt = qup->brx.sg_cnt; + + /* schedule the EOT and FLUSH I2C tags */ + len = 1; + if (rx_cnt) { + qup->btx.tag.start[0] = QUP_BAM_INPUT_EOT; + len++; + + /* scratch buf to read the BAM EOT FLUSH tags */ + ret = qup_sg_set_buf(&qup->brx.sg[rx_cnt++], + &qup->brx.tag.start[0], + 1, qup, DMA_FROM_DEVICE); + if (ret) + return ret; + } + + qup->btx.tag.start[len - 1] = QUP_BAM_FLUSH_STOP; + ret = qup_sg_set_buf(&qup->btx.sg[tx_cnt++], &qup->btx.tag.start[0], + len, qup, DMA_TO_DEVICE); + if (ret) + return ret; + + txd = dmaengine_prep_slave_sg(qup->btx.dma, qup->btx.sg, tx_cnt, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_PREP_FENCE); if (!txd) { @@ -801,7 +752,7 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg, goto desc_err; } - if (!rx_nents) { + if (!rx_cnt) { txd->callback = qup_i2c_bam_cb; txd->callback_param = qup; } @@ -814,9 +765,9 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg, dma_async_issue_pending(qup->btx.dma); - if (rx_nents) { + if (rx_cnt) { rxd = dmaengine_prep_slave_sg(qup->brx.dma, qup->brx.sg, - rx_nents, DMA_DEV_TO_MEM, + rx_cnt, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); if (!rxd) { dev_err(qup->dev, "failed to get rx desc\n"); @@ -838,49 +789,51 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg, dma_async_issue_pending(qup->brx.dma); } - if (!wait_for_completion_timeout(&qup->xfer, TOUT_MAX * HZ)) { + if (!wait_for_completion_timeout(&qup->xfer, qup->xfer_timeout)) { dev_err(qup->dev, "normal trans timed out\n"); ret = -ETIMEDOUT; } if (ret || qup->bus_err || qup->qup_err) { + reinit_completion(&qup->xfer); + if (qup_i2c_change_state(qup, QUP_RUN_STATE)) { dev_err(qup->dev, "change to run state timed out"); goto desc_err; } - if (rx_nents) - writel(QUP_BAM_INPUT_EOT, - qup->base + QUP_OUT_FIFO_BASE); - - writel(QUP_BAM_FLUSH_STOP, qup->base + QUP_OUT_FIFO_BASE); - qup_i2c_flush(qup); /* wait for remaining interrupts to occur */ if (!wait_for_completion_timeout(&qup->xfer, HZ)) dev_err(qup->dev, "flush timed out\n"); - qup_i2c_rel_dma(qup); - ret = (qup->bus_err & QUP_I2C_NACK_FLAG) ? -ENXIO : -EIO; } desc_err: - dma_unmap_sg(qup->dev, qup->btx.sg, tx_nents, DMA_TO_DEVICE); + dma_unmap_sg(qup->dev, qup->btx.sg, tx_cnt, DMA_TO_DEVICE); - if (rx_nents) - dma_unmap_sg(qup->dev, qup->brx.sg, rx_nents, + if (rx_cnt) + dma_unmap_sg(qup->dev, qup->brx.sg, rx_cnt, DMA_FROM_DEVICE); return ret; } +static void qup_i2c_bam_clear_tag_buffers(struct qup_i2c_dev *qup) +{ + qup->btx.sg_cnt = 0; + qup->brx.sg_cnt = 0; + qup->tag_buf_pos = 0; +} + static int qup_i2c_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num) { struct qup_i2c_dev *qup = i2c_get_adapdata(adap); int ret = 0; + int idx = 0; enable_irq(qup->irq); ret = qup_i2c_req_dma(qup); @@ -903,9 +856,34 @@ static int qup_i2c_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, goto out; writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL); + qup_i2c_bam_clear_tag_buffers(qup); + + for (idx = 0; idx < num; idx++) { + qup->msg = msg + idx; + qup->is_last = idx == (num - 1); + + ret = qup_i2c_bam_make_desc(qup, qup->msg); + if (ret) + break; + + /* + * Make DMA descriptor and schedule the BAM transfer if its + * already crossed the maximum length. Since the memory for all + * tags buffers have been taken for 2 maximum possible + * transfers length so it will never cross the buffer actual + * length. + */ + if (qup->btx.sg_cnt > qup->max_xfer_sg_len || + qup->brx.sg_cnt > qup->max_xfer_sg_len || + qup->is_last) { + ret = qup_i2c_bam_schedule_desc(qup); + if (ret) + break; + + qup_i2c_bam_clear_tag_buffers(qup); + } + } - qup->msg = msg; - ret = qup_i2c_bam_do_xfer(qup, qup->msg, num); out: disable_irq(qup->irq); @@ -919,7 +897,7 @@ static int qup_i2c_wait_for_complete(struct qup_i2c_dev *qup, unsigned long left; int ret = 0; - left = wait_for_completion_timeout(&qup->xfer, HZ); + left = wait_for_completion_timeout(&qup->xfer, qup->xfer_timeout); if (!left) { writel(1, qup->base + QUP_SW_RESET); ret = -ETIMEDOUT; @@ -931,363 +909,635 @@ static int qup_i2c_wait_for_complete(struct qup_i2c_dev *qup, return ret; } -static int qup_i2c_write_one_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg) +static void qup_i2c_read_rx_fifo_v1(struct qup_i2c_dev *qup) { - int ret = 0; + struct qup_i2c_block *blk = &qup->blk; + struct i2c_msg *msg = qup->msg; + u32 val = 0; + int idx = 0; - qup->msg = msg; - qup->pos = 0; - enable_irq(qup->irq); - qup_i2c_set_blk_data(qup, msg); - qup_i2c_set_write_mode_v2(qup, msg); + while (blk->fifo_available && qup->pos < msg->len) { + if ((idx & 1) == 0) { + /* Reading 2 words at time */ + val = readl(qup->base + QUP_IN_FIFO_BASE); + msg->buf[qup->pos++] = val & 0xFF; + } else { + msg->buf[qup->pos++] = val >> QUP_MSW_SHIFT; + } + idx++; + blk->fifo_available--; + } + if (qup->pos == msg->len) + blk->rx_bytes_read = true; +} + +static void qup_i2c_write_rx_tags_v1(struct qup_i2c_dev *qup) +{ + struct i2c_msg *msg = qup->msg; + u32 addr, len, val; + + addr = i2c_8bit_addr_from_msg(msg); + + /* 0 is used to specify a length 256 (QUP_READ_LIMIT) */ + len = (msg->len == QUP_READ_LIMIT) ? 0 : msg->len; + + val = ((QUP_TAG_REC | len) << QUP_MSW_SHIFT) | QUP_TAG_START | addr; + writel(val, qup->base + QUP_OUT_FIFO_BASE); +} + +static void qup_i2c_conf_v1(struct qup_i2c_dev *qup) +{ + struct qup_i2c_block *blk = &qup->blk; + u32 qup_config = I2C_MINI_CORE | I2C_N_VAL; + u32 io_mode = QUP_REPACK_EN; + + blk->is_tx_blk_mode = + blk->total_tx_len > qup->out_fifo_sz ? true : false; + blk->is_rx_blk_mode = + blk->total_rx_len > qup->in_fifo_sz ? true : false; + + if (blk->is_tx_blk_mode) { + io_mode |= QUP_OUTPUT_BLK_MODE; + writel(0, qup->base + QUP_MX_WRITE_CNT); + writel(blk->total_tx_len, qup->base + QUP_MX_OUTPUT_CNT); + } else { + writel(0, qup->base + QUP_MX_OUTPUT_CNT); + writel(blk->total_tx_len, qup->base + QUP_MX_WRITE_CNT); + } + + if (blk->total_rx_len) { + if (blk->is_rx_blk_mode) { + io_mode |= QUP_INPUT_BLK_MODE; + writel(0, qup->base + QUP_MX_READ_CNT); + writel(blk->total_rx_len, qup->base + QUP_MX_INPUT_CNT); + } else { + writel(0, qup->base + QUP_MX_INPUT_CNT); + writel(blk->total_rx_len, qup->base + QUP_MX_READ_CNT); + } + } else { + qup_config |= QUP_NO_INPUT; + } + + writel(qup_config, qup->base + QUP_CONFIG); + writel(io_mode, qup->base + QUP_IO_MODE); +} + +static void qup_i2c_clear_blk_v1(struct qup_i2c_block *blk) +{ + blk->tx_fifo_free = 0; + blk->fifo_available = 0; + blk->rx_bytes_read = false; +} + +static int qup_i2c_conf_xfer_v1(struct qup_i2c_dev *qup, bool is_rx) +{ + struct qup_i2c_block *blk = &qup->blk; + int ret; + + qup_i2c_clear_blk_v1(blk); + qup_i2c_conf_v1(qup); ret = qup_i2c_change_state(qup, QUP_RUN_STATE); if (ret) - goto err; + return ret; writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL); - do { - ret = qup_i2c_issue_xfer_v2(qup, msg); - if (ret) - goto err; + ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE); + if (ret) + return ret; - ret = qup_i2c_wait_for_complete(qup, msg); - if (ret) - goto err; + reinit_completion(&qup->xfer); + enable_irq(qup->irq); + if (!blk->is_tx_blk_mode) { + blk->tx_fifo_free = qup->out_fifo_sz; + + if (is_rx) + qup_i2c_write_rx_tags_v1(qup); + else + qup_i2c_write_tx_fifo_v1(qup); + } + + ret = qup_i2c_change_state(qup, QUP_RUN_STATE); + if (ret) + goto err; - qup->blk.pos++; - } while (qup->blk.pos < qup->blk.count); + ret = qup_i2c_wait_for_complete(qup, qup->msg); + if (ret) + goto err; - ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT, ONE_BYTE); + ret = qup_i2c_bus_active(qup, ONE_BYTE); err: disable_irq(qup->irq); - qup->msg = NULL; - return ret; } -static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg) +static int qup_i2c_write_one(struct qup_i2c_dev *qup) { - int ret; + struct i2c_msg *msg = qup->msg; + struct qup_i2c_block *blk = &qup->blk; - qup->msg = msg; qup->pos = 0; + blk->total_tx_len = msg->len + 1; + blk->total_rx_len = 0; - enable_irq(qup->irq); + return qup_i2c_conf_xfer_v1(qup, false); +} - qup_i2c_set_write_mode(qup, msg); +static int qup_i2c_read_one(struct qup_i2c_dev *qup) +{ + struct qup_i2c_block *blk = &qup->blk; - ret = qup_i2c_change_state(qup, QUP_RUN_STATE); + qup->pos = 0; + blk->total_tx_len = 2; + blk->total_rx_len = qup->msg->len; + + return qup_i2c_conf_xfer_v1(qup, true); +} + +static int qup_i2c_xfer(struct i2c_adapter *adap, + struct i2c_msg msgs[], + int num) +{ + struct qup_i2c_dev *qup = i2c_get_adapdata(adap); + int ret, idx; + + ret = pm_runtime_get_sync(qup->dev); + if (ret < 0) + goto out; + + qup->bus_err = 0; + qup->qup_err = 0; + + writel(1, qup->base + QUP_SW_RESET); + ret = qup_i2c_poll_state(qup, QUP_RESET_STATE); if (ret) - goto err; + goto out; - writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL); + /* Configure QUP as I2C mini core */ + writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG); - do { - ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE); - if (ret) - goto err; + for (idx = 0; idx < num; idx++) { + if (msgs[idx].len == 0) { + ret = -EINVAL; + goto out; + } - ret = qup_i2c_issue_write(qup, msg); - if (ret) - goto err; + if (qup_i2c_poll_state_i2c_master(qup)) { + ret = -EIO; + goto out; + } + + if (qup_i2c_check_msg_len(&msgs[idx])) { + ret = -EINVAL; + goto out; + } + + qup->msg = &msgs[idx]; + if (msgs[idx].flags & I2C_M_RD) + ret = qup_i2c_read_one(qup); + else + ret = qup_i2c_write_one(qup); - ret = qup_i2c_change_state(qup, QUP_RUN_STATE); if (ret) - goto err; + break; - ret = qup_i2c_wait_for_complete(qup, msg); + ret = qup_i2c_change_state(qup, QUP_RESET_STATE); if (ret) - goto err; - } while (qup->pos < msg->len); + break; + } - /* Wait for the outstanding data in the fifo to drain */ - ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT, ONE_BYTE); -err: - disable_irq(qup->irq); - qup->msg = NULL; + if (ret == 0) + ret = num; +out: + + pm_runtime_mark_last_busy(qup->dev); + pm_runtime_put_autosuspend(qup->dev); return ret; } -static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len) +/* + * Configure registers related with reconfiguration during run and call it + * before each i2c sub transfer. + */ +static void qup_i2c_conf_count_v2(struct qup_i2c_dev *qup) { - if (len < qup->in_fifo_sz) { - /* FIFO mode */ - writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE); - writel(len, qup->base + QUP_MX_READ_CNT); + struct qup_i2c_block *blk = &qup->blk; + u32 qup_config = I2C_MINI_CORE | I2C_N_VAL_V2; + + if (blk->is_tx_blk_mode) + writel(qup->config_run | blk->total_tx_len, + qup->base + QUP_MX_OUTPUT_CNT); + else + writel(qup->config_run | blk->total_tx_len, + qup->base + QUP_MX_WRITE_CNT); + + if (blk->total_rx_len) { + if (blk->is_rx_blk_mode) + writel(qup->config_run | blk->total_rx_len, + qup->base + QUP_MX_INPUT_CNT); + else + writel(qup->config_run | blk->total_rx_len, + qup->base + QUP_MX_READ_CNT); } else { - /* BLOCK mode (transfer data on chunks) */ - writel(QUP_INPUT_BLK_MODE | QUP_REPACK_EN, - qup->base + QUP_IO_MODE); - writel(len, qup->base + QUP_MX_INPUT_CNT); + qup_config |= QUP_NO_INPUT; } + + writel(qup_config, qup->base + QUP_CONFIG); } -static void qup_i2c_set_read_mode_v2(struct qup_i2c_dev *qup, int len) +/* + * Configure registers related with transfer mode (FIFO/Block) + * before starting of i2c transfer. It will be called only once in + * QUP RESET state. + */ +static void qup_i2c_conf_mode_v2(struct qup_i2c_dev *qup) { - int tx_len = qup->blk.tx_tag_len; + struct qup_i2c_block *blk = &qup->blk; + u32 io_mode = QUP_REPACK_EN; - len += qup->blk.rx_tag_len; - len |= qup->config_run; - tx_len |= qup->config_run; + if (blk->is_tx_blk_mode) { + io_mode |= QUP_OUTPUT_BLK_MODE; + writel(0, qup->base + QUP_MX_WRITE_CNT); + } else { + writel(0, qup->base + QUP_MX_OUTPUT_CNT); + } - if (len < qup->in_fifo_sz) { - /* FIFO mode */ - writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE); - writel(tx_len, qup->base + QUP_MX_WRITE_CNT); - writel(len, qup->base + QUP_MX_READ_CNT); + if (blk->is_rx_blk_mode) { + io_mode |= QUP_INPUT_BLK_MODE; + writel(0, qup->base + QUP_MX_READ_CNT); } else { - /* BLOCK mode (transfer data on chunks) */ - writel(QUP_INPUT_BLK_MODE | QUP_REPACK_EN, - qup->base + QUP_IO_MODE); - writel(tx_len, qup->base + QUP_MX_OUTPUT_CNT); - writel(len, qup->base + QUP_MX_INPUT_CNT); + writel(0, qup->base + QUP_MX_INPUT_CNT); } + + writel(io_mode, qup->base + QUP_IO_MODE); } -static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg *msg) +/* Clear required variables before starting of any QUP v2 sub transfer. */ +static void qup_i2c_clear_blk_v2(struct qup_i2c_block *blk) { - u32 addr, len, val; - - addr = i2c_8bit_addr_from_msg(msg); - - /* 0 is used to specify a length 256 (QUP_READ_LIMIT) */ - len = (msg->len == QUP_READ_LIMIT) ? 0 : msg->len; - - val = ((QUP_TAG_REC | len) << QUP_MSW_SHIFT) | QUP_TAG_START | addr; - writel(val, qup->base + QUP_OUT_FIFO_BASE); + blk->send_last_word = false; + blk->tx_tags_sent = false; + blk->tx_fifo_data = 0; + blk->tx_fifo_data_pos = 0; + blk->tx_fifo_free = 0; + + blk->rx_tags_fetched = false; + blk->rx_bytes_read = false; + blk->rx_fifo_data = 0; + blk->rx_fifo_data_pos = 0; + blk->fifo_available = 0; } - -static int qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg) +/* Receive data from RX FIFO for read message in QUP v2 i2c transfer. */ +static void qup_i2c_recv_data(struct qup_i2c_dev *qup) { - u32 val = 0; - int idx; - int ret = 0; + struct qup_i2c_block *blk = &qup->blk; + int j; - for (idx = 0; qup->pos < msg->len; idx++) { - if ((idx & 1) == 0) { - /* Check that FIFO have data */ - ret = qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, - SET_BIT, 4 * ONE_BYTE); - if (ret) - return ret; + for (j = blk->rx_fifo_data_pos; + blk->cur_blk_len && blk->fifo_available; + blk->cur_blk_len--, blk->fifo_available--) { + if (j == 0) + blk->rx_fifo_data = readl(qup->base + QUP_IN_FIFO_BASE); - /* Reading 2 words at time */ - val = readl(qup->base + QUP_IN_FIFO_BASE); + *(blk->cur_data++) = blk->rx_fifo_data; + blk->rx_fifo_data >>= 8; - msg->buf[qup->pos++] = val & 0xFF; - } else { - msg->buf[qup->pos++] = val >> QUP_MSW_SHIFT; - } + if (j == 3) + j = 0; + else + j++; } - return ret; + blk->rx_fifo_data_pos = j; } -static int qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup, - struct i2c_msg *msg) +/* Receive tags for read message in QUP v2 i2c transfer. */ +static void qup_i2c_recv_tags(struct qup_i2c_dev *qup) { - u32 val; - int idx, pos = 0, ret = 0, total, msg_offset = 0; + struct qup_i2c_block *blk = &qup->blk; - /* - * If the message length is already read in - * the first byte of the buffer, account for - * that by setting the offset - */ - if (qup_i2c_check_msg_len(msg) && (msg->len > 1)) - msg_offset = 1; - total = qup_i2c_get_data_len(qup); - total -= msg_offset; - - /* 2 extra bytes for read tags */ - while (pos < (total + 2)) { - /* Check that FIFO have data */ - ret = qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, - SET_BIT, 4 * ONE_BYTE); - if (ret) { - dev_err(qup->dev, "timeout for fifo not empty"); - return ret; - } - val = readl(qup->base + QUP_IN_FIFO_BASE); + blk->rx_fifo_data = readl(qup->base + QUP_IN_FIFO_BASE); + blk->rx_fifo_data >>= blk->rx_tag_len * 8; + blk->rx_fifo_data_pos = blk->rx_tag_len; + blk->fifo_available -= blk->rx_tag_len; +} - for (idx = 0; idx < 4; idx++, val >>= 8, pos++) { - /* first 2 bytes are tag bytes */ - if (pos < 2) - continue; +/* + * Read the data and tags from RX FIFO. Since in read case, the tags will be + * preceded by received data bytes so + * 1. Check if rx_tags_fetched is false i.e. the start of QUP block so receive + * all tag bytes and discard that. + * 2. Read the data from RX FIFO. When all the data bytes have been read then + * set rx_bytes_read to true. + */ +static void qup_i2c_read_rx_fifo_v2(struct qup_i2c_dev *qup) +{ + struct qup_i2c_block *blk = &qup->blk; - if (pos >= (total + 2)) - goto out; - msg->buf[qup->pos + msg_offset] = val & 0xff; - qup->pos++; - } + if (!blk->rx_tags_fetched) { + qup_i2c_recv_tags(qup); + blk->rx_tags_fetched = true; } -out: - qup->blk.data_len -= total; - - return ret; + qup_i2c_recv_data(qup); + if (!blk->cur_blk_len) + blk->rx_bytes_read = true; } -static int qup_i2c_read_one_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg) +/* + * Write bytes in TX FIFO for write message in QUP v2 i2c transfer. QUP TX FIFO + * write works on word basis (4 bytes). Append new data byte write for TX FIFO + * in tx_fifo_data and write to TX FIFO when all the 4 bytes are present. + */ +static void +qup_i2c_write_blk_data(struct qup_i2c_dev *qup, u8 **data, unsigned int *len) { - int ret = 0; + struct qup_i2c_block *blk = &qup->blk; + unsigned int j; + + for (j = blk->tx_fifo_data_pos; *len && blk->tx_fifo_free; + (*len)--, blk->tx_fifo_free--) { + blk->tx_fifo_data |= *(*data)++ << (j * 8); + if (j == 3) { + writel(blk->tx_fifo_data, + qup->base + QUP_OUT_FIFO_BASE); + blk->tx_fifo_data = 0x0; + j = 0; + } else { + j++; + } + } - qup->msg = msg; - qup->pos = 0; - enable_irq(qup->irq); - qup_i2c_set_blk_data(qup, msg); - qup_i2c_set_read_mode_v2(qup, msg->len); + blk->tx_fifo_data_pos = j; +} - ret = qup_i2c_change_state(qup, QUP_RUN_STATE); - if (ret) - goto err; +/* Transfer tags for read message in QUP v2 i2c transfer. */ +static void qup_i2c_write_rx_tags_v2(struct qup_i2c_dev *qup) +{ + struct qup_i2c_block *blk = &qup->blk; - writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL); + qup_i2c_write_blk_data(qup, &blk->cur_tx_tags, &blk->tx_tag_len); + if (blk->tx_fifo_data_pos) + writel(blk->tx_fifo_data, qup->base + QUP_OUT_FIFO_BASE); +} - do { - ret = qup_i2c_issue_xfer_v2(qup, msg); - if (ret) - goto err; +/* + * Write the data and tags in TX FIFO. Since in write case, both tags and data + * need to be written and QUP write tags can have maximum 256 data length, so + * + * 1. Check if tx_tags_sent is false i.e. the start of QUP block so write the + * tags to TX FIFO and set tx_tags_sent to true. + * 2. Check if send_last_word is true. It will be set when last few data bytes + * (less than 4 bytes) are reamining to be written in FIFO because of no FIFO + * space. All this data bytes are available in tx_fifo_data so write this + * in FIFO. + * 3. Write the data to TX FIFO and check for cur_blk_len. If it is non zero + * then more data is pending otherwise following 3 cases can be possible + * a. if tx_fifo_data_pos is zero i.e. all the data bytes in this block + * have been written in TX FIFO so nothing else is required. + * b. tx_fifo_free is non zero i.e tx FIFO is free so copy the remaining data + * from tx_fifo_data to tx FIFO. Since, qup_i2c_write_blk_data do write + * in 4 bytes and FIFO space is in multiple of 4 bytes so tx_fifo_free + * will be always greater than or equal to 4 bytes. + * c. tx_fifo_free is zero. In this case, last few bytes (less than 4 + * bytes) are copied to tx_fifo_data but couldn't be sent because of + * FIFO full so make send_last_word true. + */ +static void qup_i2c_write_tx_fifo_v2(struct qup_i2c_dev *qup) +{ + struct qup_i2c_block *blk = &qup->blk; - ret = qup_i2c_wait_for_complete(qup, msg); - if (ret) - goto err; + if (!blk->tx_tags_sent) { + qup_i2c_write_blk_data(qup, &blk->cur_tx_tags, + &blk->tx_tag_len); + blk->tx_tags_sent = true; + } - ret = qup_i2c_read_fifo_v2(qup, msg); - if (ret) - goto err; + if (blk->send_last_word) + goto send_last_word; - qup->blk.pos++; + qup_i2c_write_blk_data(qup, &blk->cur_data, &blk->cur_blk_len); + if (!blk->cur_blk_len) { + if (!blk->tx_fifo_data_pos) + return; - /* Handle SMBus block read length */ - if (qup_i2c_check_msg_len(msg) && (msg->len == 1)) { - if (msg->buf[0] > I2C_SMBUS_BLOCK_MAX) { - ret = -EPROTO; - goto err; - } - msg->len += msg->buf[0]; - qup->pos = 0; - qup_i2c_set_blk_data(qup, msg); - /* set tag length for block read */ - qup->blk.tx_tag_len = 2; - qup_i2c_set_read_mode_v2(qup, msg->buf[0]); - } - } while (qup->blk.pos < qup->blk.count); + if (blk->tx_fifo_free) + goto send_last_word; -err: - disable_irq(qup->irq); - qup->msg = NULL; + blk->send_last_word = true; + } - return ret; + return; + +send_last_word: + writel(blk->tx_fifo_data, qup->base + QUP_OUT_FIFO_BASE); } -static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg) +/* + * Main transfer function which read or write i2c data. + * The QUP v2 supports reconfiguration during run in which multiple i2c sub + * transfers can be scheduled. + */ +static int +qup_i2c_conf_xfer_v2(struct qup_i2c_dev *qup, bool is_rx, bool is_first, + bool change_pause_state) { + struct qup_i2c_block *blk = &qup->blk; + struct i2c_msg *msg = qup->msg; int ret; - qup->msg = msg; - qup->pos = 0; + /* + * Check if its SMBus Block read for which the top level read will be + * done into 2 QUP reads. One with message length 1 while other one is + * with actual length. + */ + if (qup_i2c_check_msg_len(msg)) { + if (qup->is_smbus_read) { + /* + * If the message length is already read in + * the first byte of the buffer, account for + * that by setting the offset + */ + blk->cur_data += 1; + is_first = false; + } else { + change_pause_state = false; + } + } - enable_irq(qup->irq); - qup_i2c_set_read_mode(qup, msg->len); + qup->config_run = is_first ? 0 : QUP_I2C_MX_CONFIG_DURING_RUN; - ret = qup_i2c_change_state(qup, QUP_RUN_STATE); - if (ret) - goto err; + qup_i2c_clear_blk_v2(blk); + qup_i2c_conf_count_v2(qup); - writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL); + /* If it is first sub transfer, then configure i2c bus clocks */ + if (is_first) { + ret = qup_i2c_change_state(qup, QUP_RUN_STATE); + if (ret) + return ret; - ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE); - if (ret) - goto err; + writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL); - qup_i2c_issue_read(qup, msg); + ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE); + if (ret) + return ret; + } + + reinit_completion(&qup->xfer); + enable_irq(qup->irq); + /* + * In FIFO mode, tx FIFO can be written directly while in block mode the + * it will be written after getting OUT_BLOCK_WRITE_REQ interrupt + */ + if (!blk->is_tx_blk_mode) { + blk->tx_fifo_free = qup->out_fifo_sz; + + if (is_rx) + qup_i2c_write_rx_tags_v2(qup); + else + qup_i2c_write_tx_fifo_v2(qup); + } ret = qup_i2c_change_state(qup, QUP_RUN_STATE); if (ret) goto err; - do { - ret = qup_i2c_wait_for_complete(qup, msg); - if (ret) - goto err; + ret = qup_i2c_wait_for_complete(qup, msg); + if (ret) + goto err; - ret = qup_i2c_read_fifo(qup, msg); + /* Move to pause state for all the transfers, except last one */ + if (change_pause_state) { + ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE); if (ret) goto err; - } while (qup->pos < msg->len); + } err: disable_irq(qup->irq); - qup->msg = NULL; - return ret; } -static int qup_i2c_xfer(struct i2c_adapter *adap, - struct i2c_msg msgs[], - int num) +/* + * Transfer one read/write message in i2c transfer. It splits the message into + * multiple of blk_xfer_limit data length blocks and schedule each + * QUP block individually. + */ +static int qup_i2c_xfer_v2_msg(struct qup_i2c_dev *qup, int msg_id, bool is_rx) { - struct qup_i2c_dev *qup = i2c_get_adapdata(adap); - int ret, idx; + int ret = 0; + unsigned int data_len, i; + struct i2c_msg *msg = qup->msg; + struct qup_i2c_block *blk = &qup->blk; + u8 *msg_buf = msg->buf; - ret = pm_runtime_get_sync(qup->dev); - if (ret < 0) - goto out; + qup->blk_xfer_limit = is_rx ? RECV_MAX_DATA_LEN : QUP_READ_LIMIT; + qup_i2c_set_blk_data(qup, msg); - qup->bus_err = 0; - qup->qup_err = 0; + for (i = 0; i < blk->count; i++) { + data_len = qup_i2c_get_data_len(qup); + blk->pos = i; + blk->cur_tx_tags = blk->tags; + blk->cur_blk_len = data_len; + blk->tx_tag_len = + qup_i2c_set_tags(blk->cur_tx_tags, qup, qup->msg); - writel(1, qup->base + QUP_SW_RESET); - ret = qup_i2c_poll_state(qup, QUP_RESET_STATE); - if (ret) - goto out; + blk->cur_data = msg_buf; - /* Configure QUP as I2C mini core */ - writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG); - - for (idx = 0; idx < num; idx++) { - if (msgs[idx].len == 0) { - ret = -EINVAL; - goto out; + if (is_rx) { + blk->total_tx_len = blk->tx_tag_len; + blk->rx_tag_len = 2; + blk->total_rx_len = blk->rx_tag_len + data_len; + } else { + blk->total_tx_len = blk->tx_tag_len + data_len; + blk->total_rx_len = 0; } - if (qup_i2c_poll_state_i2c_master(qup)) { - ret = -EIO; - goto out; - } + ret = qup_i2c_conf_xfer_v2(qup, is_rx, !msg_id && !i, + !qup->is_last || i < blk->count - 1); + if (ret) + return ret; - if (qup_i2c_check_msg_len(&msgs[idx])) { - ret = -EINVAL; - goto out; + /* Handle SMBus block read length */ + if (qup_i2c_check_msg_len(msg) && msg->len == 1 && + !qup->is_smbus_read) { + if (msg->buf[0] > I2C_SMBUS_BLOCK_MAX) + return -EPROTO; + + msg->len = msg->buf[0]; + qup->is_smbus_read = true; + ret = qup_i2c_xfer_v2_msg(qup, msg_id, true); + qup->is_smbus_read = false; + if (ret) + return ret; + + msg->len += 1; } + msg_buf += data_len; + blk->data_len -= qup->blk_xfer_limit; + } + + return ret; +} + +/* + * QUP v2 supports 3 modes + * Programmed IO using FIFO mode : Less than FIFO size + * Programmed IO using Block mode : Greater than FIFO size + * DMA using BAM : Appropriate for any transaction size but the address should + * be DMA applicable + * + * This function determines the mode which will be used for this transfer. An + * i2c transfer contains multiple message. Following are the rules to determine + * the mode used. + * 1. Determine complete length, maximum tx and rx length for complete transfer. + * 2. If complete transfer length is greater than fifo size then use the DMA + * mode. + * 3. In FIFO or block mode, tx and rx can operate in different mode so check + * for maximum tx and rx length to determine mode. + */ +static int +qup_i2c_determine_mode_v2(struct qup_i2c_dev *qup, + struct i2c_msg msgs[], int num) +{ + int idx; + bool no_dma = false; + unsigned int max_tx_len = 0, max_rx_len = 0, total_len = 0; + + /* All i2c_msgs should be transferred using either dma or cpu */ + for (idx = 0; idx < num; idx++) { + if (msgs[idx].len == 0) + return -EINVAL; + if (msgs[idx].flags & I2C_M_RD) - ret = qup_i2c_read_one(qup, &msgs[idx]); + max_rx_len = max_t(unsigned int, max_rx_len, + msgs[idx].len); else - ret = qup_i2c_write_one(qup, &msgs[idx]); + max_tx_len = max_t(unsigned int, max_tx_len, + msgs[idx].len); - if (ret) - break; + if (is_vmalloc_addr(msgs[idx].buf)) + no_dma = true; - ret = qup_i2c_change_state(qup, QUP_RESET_STATE); - if (ret) - break; + total_len += msgs[idx].len; } - if (ret == 0) - ret = num; -out: - - pm_runtime_mark_last_busy(qup->dev); - pm_runtime_put_autosuspend(qup->dev); + if (!no_dma && qup->is_dma && + (total_len > qup->out_fifo_sz || total_len > qup->in_fifo_sz)) { + qup->use_dma = true; + } else { + qup->blk.is_tx_blk_mode = max_tx_len > qup->out_fifo_sz - + QUP_MAX_TAGS_LEN ? true : false; + qup->blk.is_rx_blk_mode = max_rx_len > qup->in_fifo_sz - + READ_RX_TAGS_LEN ? true : false; + } - return ret; + return 0; } static int qup_i2c_xfer_v2(struct i2c_adapter *adap, @@ -1295,7 +1545,7 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap, int num) { struct qup_i2c_dev *qup = i2c_get_adapdata(adap); - int ret, len, idx = 0, use_dma = 0; + int ret, idx = 0; qup->bus_err = 0; qup->qup_err = 0; @@ -1304,6 +1554,10 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap, if (ret < 0) goto out; + ret = qup_i2c_determine_mode_v2(qup, msgs, num); + if (ret) + goto out; + writel(1, qup->base + QUP_SW_RESET); ret = qup_i2c_poll_state(qup, QUP_RESET_STATE); if (ret) @@ -1313,59 +1567,35 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap, writel(I2C_MINI_CORE | I2C_N_VAL_V2, qup->base + QUP_CONFIG); writel(QUP_V2_TAGS_EN, qup->base + QUP_I2C_MASTER_GEN); - if ((qup->is_dma)) { - /* All i2c_msgs should be transferred using either dma or cpu */ - for (idx = 0; idx < num; idx++) { - if (msgs[idx].len == 0) { - ret = -EINVAL; - goto out; - } - - len = (msgs[idx].len > qup->out_fifo_sz) || - (msgs[idx].len > qup->in_fifo_sz); - - if ((!is_vmalloc_addr(msgs[idx].buf)) && len) { - use_dma = 1; - } else { - use_dma = 0; - break; - } - } + if (qup_i2c_poll_state_i2c_master(qup)) { + ret = -EIO; + goto out; } - idx = 0; + if (qup->use_dma) { + reinit_completion(&qup->xfer); + ret = qup_i2c_bam_xfer(adap, &msgs[0], num); + qup->use_dma = false; + } else { + qup_i2c_conf_mode_v2(qup); - do { - if (msgs[idx].len == 0) { - ret = -EINVAL; - goto out; - } + for (idx = 0; idx < num; idx++) { + qup->msg = &msgs[idx]; + qup->is_last = idx == (num - 1); - if (qup_i2c_poll_state_i2c_master(qup)) { - ret = -EIO; - goto out; + ret = qup_i2c_xfer_v2_msg(qup, idx, + !!(msgs[idx].flags & I2C_M_RD)); + if (ret) + break; } + qup->msg = NULL; + } - qup->is_last = (idx == (num - 1)); - if (idx) - qup->config_run = QUP_I2C_MX_CONFIG_DURING_RUN; - else - qup->config_run = 0; - - reinit_completion(&qup->xfer); - - if (use_dma) { - ret = qup_i2c_bam_xfer(adap, &msgs[idx], num); - } else { - if (msgs[idx].flags & I2C_M_RD) - ret = qup_i2c_read_one_v2(qup, &msgs[idx]); - else - ret = qup_i2c_write_one_v2(qup, &msgs[idx]); - } - } while ((idx++ < (num - 1)) && !use_dma && !ret); + if (!ret) + ret = qup_i2c_bus_active(qup, ONE_BYTE); if (!ret) - ret = qup_i2c_change_state(qup, QUP_RESET_STATE); + qup_i2c_change_state(qup, QUP_RESET_STATE); if (ret == 0) ret = num; @@ -1429,6 +1659,7 @@ static int qup_i2c_probe(struct platform_device *pdev) u32 src_clk_freq = DEFAULT_SRC_CLK; u32 clk_freq = DEFAULT_CLK_FREQ; int blocks; + bool is_qup_v1; qup = devm_kzalloc(&pdev->dev, sizeof(*qup), GFP_KERNEL); if (!qup) @@ -1447,8 +1678,10 @@ static int qup_i2c_probe(struct platform_device *pdev) if (of_device_is_compatible(pdev->dev.of_node, "qcom,i2c-qup-v1.1.1")) { qup->adap.algo = &qup_i2c_algo; qup->adap.quirks = &qup_i2c_quirks; + is_qup_v1 = true; } else { qup->adap.algo = &qup_i2c_algo_v2; + is_qup_v1 = false; ret = qup_i2c_req_dma(qup); if (ret == -EPROBE_DEFER) @@ -1456,7 +1689,8 @@ static int qup_i2c_probe(struct platform_device *pdev) else if (ret != 0) goto nodma; - blocks = (MX_BLOCKS << 1) + 1; + qup->max_xfer_sg_len = (MX_BLOCKS << 1); + blocks = (MX_DMA_BLOCKS << 1) + 1; qup->btx.sg = devm_kzalloc(&pdev->dev, sizeof(*qup->btx.sg) * blocks, GFP_KERNEL); @@ -1573,14 +1807,31 @@ nodma: ret = -EIO; goto fail; } - qup->out_blk_sz = blk_sizes[size] / 2; + qup->out_blk_sz = blk_sizes[size]; size = QUP_INPUT_BLOCK_SIZE(io_mode); if (size >= ARRAY_SIZE(blk_sizes)) { ret = -EIO; goto fail; } - qup->in_blk_sz = blk_sizes[size] / 2; + qup->in_blk_sz = blk_sizes[size]; + + if (is_qup_v1) { + /* + * in QUP v1, QUP_CONFIG uses N as 15 i.e 16 bits constitutes a + * single transfer but the block size is in bytes so divide the + * in_blk_sz and out_blk_sz by 2 + */ + qup->in_blk_sz /= 2; + qup->out_blk_sz /= 2; + qup->write_tx_fifo = qup_i2c_write_tx_fifo_v1; + qup->read_rx_fifo = qup_i2c_read_rx_fifo_v1; + qup->write_rx_tags = qup_i2c_write_rx_tags_v1; + } else { + qup->write_tx_fifo = qup_i2c_write_tx_fifo_v2; + qup->read_rx_fifo = qup_i2c_read_rx_fifo_v2; + qup->write_rx_tags = qup_i2c_write_rx_tags_v2; + } size = QUP_OUTPUT_FIFO_SIZE(io_mode); qup->out_fifo_sz = qup->out_blk_sz * (2 << size); @@ -1598,6 +1849,8 @@ nodma: */ one_bit_t = (USEC_PER_SEC / clk_freq) + 1; qup->one_byte_t = one_bit_t * 9; + qup->xfer_timeout = TOUT_MIN * HZ + + usecs_to_jiffies(MX_DMA_TX_RX_LEN * qup->one_byte_t); dev_dbg(qup->dev, "IN:block:%d, fifo:%d, OUT:block:%d, fifo:%d\n", qup->in_blk_sz, qup->in_fifo_sz, |