From 6c1caca70063aa707ba809a6b4695d0f0c5646f1 Mon Sep 17 00:00:00 2001 From: "Jason M. Bills" Date: Thu, 27 Feb 2020 15:57:13 -0800 Subject: Update to internal 2020-02-27 Signed-off-by: Jason M. Bills --- ...-i2c-aspeed-add-DMA-mode-transfer-support.patch | 457 ++++++++++++--------- 1 file changed, 253 insertions(+), 204 deletions(-) (limited to 'meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0062-i2c-aspeed-add-DMA-mode-transfer-support.patch') diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0062-i2c-aspeed-add-DMA-mode-transfer-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0062-i2c-aspeed-add-DMA-mode-transfer-support.patch index a66e759e7..994c20b18 100644 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0062-i2c-aspeed-add-DMA-mode-transfer-support.patch +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0062-i2c-aspeed-add-DMA-mode-transfer-support.patch @@ -1,4 +1,4 @@ -From 0d237f4b5111aa192a1ae9aaee6e6779761906bc Mon Sep 17 00:00:00 2001 +From 5bf7a202eb0af455675a85a4f1bdad863fd8805d Mon Sep 17 00:00:00 2001 From: Jae Hyun Yoo Date: Tue, 18 Jun 2019 08:47:50 -0700 Subject: [PATCH] i2c: aspeed: add DMA mode transfer support @@ -15,9 +15,9 @@ use DMA mode. Signed-off-by: Jae Hyun Yoo --- - .../devicetree/bindings/i2c/i2c-aspeed.txt | 25 +++ - drivers/i2c/busses/i2c-aspeed.c | 231 +++++++++++++++++++-- - 2 files changed, 241 insertions(+), 15 deletions(-) + .../devicetree/bindings/i2c/i2c-aspeed.txt | 25 ++ + drivers/i2c/busses/i2c-aspeed.c | 253 +++++++++++++++++---- + 2 files changed, 234 insertions(+), 44 deletions(-) diff --git a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt index 0ff3539cee95..d3f4a39f7ba6 100644 @@ -61,7 +61,7 @@ index 0ff3539cee95..d3f4a39f7ba6 100644 + }; }; diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c -index 1b338492c68a..8dc6723bfaaf 100644 +index bf72e151d11f..3c9e491cbe4e 100644 --- a/drivers/i2c/busses/i2c-aspeed.c +++ b/drivers/i2c/busses/i2c-aspeed.c @@ -10,6 +10,8 @@ @@ -106,242 +106,291 @@ index 1b338492c68a..8dc6723bfaaf 100644 enum aspeed_i2c_master_state { ASPEED_I2C_MASTER_INACTIVE, ASPEED_I2C_MASTER_PENDING, -@@ -185,6 +199,12 @@ struct aspeed_i2c_bus { - size_t buf_size; +@@ -184,6 +198,12 @@ struct aspeed_i2c_bus { + void __iomem *buf_base; u8 buf_offset; u8 buf_page; + /* DMA mode */ + struct dma_pool *dma_pool; + dma_addr_t dma_handle; + u8 *dma_buf; -+ size_t dma_buf_size; + size_t dma_len; ++ /* Buffer/DMA mode */ + size_t buf_size; #if IS_ENABLED(CONFIG_I2C_SLAVE) struct i2c_client *slave; - enum aspeed_i2c_slave_state slave_state; -@@ -304,9 +324,13 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) - - /* Slave was sent something. */ - if (irq_status & ASPEED_I2CD_INTR_RX_DONE) { -- if (bus->buf_base && -+ if (bus->dma_buf && - bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED && - !(irq_status & ASPEED_I2CD_INTR_NORMAL_STOP)) -+ value = bus->dma_buf[0]; -+ else if (bus->buf_base && -+ bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED && -+ !(irq_status & ASPEED_I2CD_INTR_NORMAL_STOP)) - value = readb(bus->buf_base); - else - value = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8; -@@ -326,7 +350,18 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) - if (irq_status & ASPEED_I2CD_INTR_NORMAL_STOP) { - if (bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED && - irq_status & ASPEED_I2CD_INTR_RX_DONE) { -- if (bus->buf_base) { -+ if (bus->dma_buf) { -+ len = bus->dma_buf_size - -+ FIELD_GET(ASPEED_I2CD_DMA_LEN_MASK, -+ readl(bus->base + -+ ASPEED_I2C_DMA_LEN_REG)); -+ for (i = 0; i < len; i++) { -+ value = bus->dma_buf[i]; -+ i2c_slave_event(slave, -+ I2C_SLAVE_WRITE_RECEIVED, -+ &value); -+ } -+ } else if (bus->buf_base) { - len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK, - readl(bus->base + - ASPEED_I2C_BUF_CTRL_REG)); -@@ -370,7 +405,15 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) - case ASPEED_I2C_SLAVE_WRITE_REQUESTED: - bus->slave_state = ASPEED_I2C_SLAVE_WRITE_RECEIVED; - i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value); -- if (bus->buf_base) { -+ if (bus->dma_buf) { -+ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK, -+ bus->base + ASPEED_I2C_DMA_ADDR_REG); -+ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, -+ bus->dma_buf_size), -+ bus->base + ASPEED_I2C_DMA_LEN_REG); -+ writel(ASPEED_I2CD_RX_DMA_ENABLE, -+ bus->base + ASPEED_I2C_CMD_REG); -+ } else if (bus->buf_base) { - writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK, - bus->buf_size - 1) | - FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, -@@ -382,7 +425,25 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) - break; - case ASPEED_I2C_SLAVE_WRITE_RECEIVED: - i2c_slave_event(slave, I2C_SLAVE_WRITE_RECEIVED, &value); +@@ -281,7 +301,11 @@ static inline void + aspeed_i2c_slave_handle_rx_done(struct aspeed_i2c_bus *bus, u32 irq_status, + u8 *value) + { +- if (bus->buf_base && ++ if (bus->dma_buf && ++ bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED && ++ !(irq_status & ASPEED_I2CD_INTR_NORMAL_STOP)) ++ *value = bus->dma_buf[0]; ++ else if (bus->buf_base && + bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED && + !(irq_status & ASPEED_I2CD_INTR_NORMAL_STOP)) + *value = readb(bus->buf_base); +@@ -297,7 +321,18 @@ aspeed_i2c_slave_handle_normal_stop(struct aspeed_i2c_bus *bus, u32 irq_status, + + if (bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED && + irq_status & ASPEED_I2CD_INTR_RX_DONE) { - if (bus->buf_base) { + if (bus->dma_buf) { -+ len = bus->dma_buf_size - ++ len = bus->buf_size - + FIELD_GET(ASPEED_I2CD_DMA_LEN_MASK, + readl(bus->base + + ASPEED_I2C_DMA_LEN_REG)); -+ for (i = 1; i < len; i++) { -+ value = bus->dma_buf[i]; -+ i2c_slave_event(slave, ++ for (i = 0; i < len; i++) { ++ *value = bus->dma_buf[i]; ++ i2c_slave_event(bus->slave, + I2C_SLAVE_WRITE_RECEIVED, -+ &value); ++ value); + } -+ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK, -+ bus->base + ASPEED_I2C_DMA_ADDR_REG); -+ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, -+ bus->dma_buf_size), -+ bus->base + ASPEED_I2C_DMA_LEN_REG); -+ writel(ASPEED_I2CD_RX_DMA_ENABLE, -+ bus->base + ASPEED_I2C_CMD_REG); + } else if (bus->buf_base) { len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK, readl(bus->base + ASPEED_I2C_BUF_CTRL_REG)); -@@ -446,7 +507,23 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus) - if (msg->flags & I2C_M_RD) { - command |= ASPEED_I2CD_M_RX_CMD; +@@ -314,7 +349,14 @@ aspeed_i2c_slave_handle_normal_stop(struct aspeed_i2c_bus *bus, u32 irq_status, + static inline void + aspeed_i2c_slave_handle_write_requested(struct aspeed_i2c_bus *bus, u8 *value) + { +- if (bus->buf_base) { ++ if (bus->dma_buf) { ++ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK, ++ bus->base + ASPEED_I2C_DMA_ADDR_REG); ++ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, bus->buf_size), ++ bus->base + ASPEED_I2C_DMA_LEN_REG); ++ writel(ASPEED_I2CD_RX_DMA_ENABLE, ++ bus->base + ASPEED_I2C_CMD_REG); ++ } else if (bus->buf_base) { + writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK, + bus->buf_size - 1) | + FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, +@@ -330,7 +372,23 @@ aspeed_i2c_slave_handle_write_received(struct aspeed_i2c_bus *bus, u8 *value) + { + int i, len; -- if (bus->buf_base && !(msg->flags & I2C_M_RECV_LEN)) { -+ if (bus->dma_buf && !(msg->flags & I2C_M_RECV_LEN)) { -+ command |= ASPEED_I2CD_RX_DMA_ENABLE; -+ -+ if (msg->len > bus->dma_buf_size) { -+ len = bus->dma_buf_size; -+ } else { -+ len = msg->len; -+ command |= ASPEED_I2CD_M_S_RX_CMD_LAST; -+ } -+ -+ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK, -+ bus->base + ASPEED_I2C_DMA_ADDR_REG); -+ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, -+ len), -+ bus->base + ASPEED_I2C_DMA_LEN_REG); -+ bus->dma_len = len; -+ } else if (bus->buf_base && !(msg->flags & I2C_M_RECV_LEN)) { - command |= ASPEED_I2CD_RX_BUFF_ENABLE; +- if (bus->buf_base) { ++ if (bus->dma_buf) { ++ len = bus->buf_size - ++ FIELD_GET(ASPEED_I2CD_DMA_LEN_MASK, ++ readl(bus->base + ++ ASPEED_I2C_DMA_LEN_REG)); ++ for (i = 1; i < len; i++) { ++ *value = bus->dma_buf[i]; ++ i2c_slave_event(bus->slave, I2C_SLAVE_WRITE_RECEIVED, ++ value); ++ } ++ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK, ++ bus->base + ASPEED_I2C_DMA_ADDR_REG); ++ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, bus->buf_size), ++ bus->base + ASPEED_I2C_DMA_LEN_REG); ++ writel(ASPEED_I2CD_RX_DMA_ENABLE, ++ bus->base + ASPEED_I2C_CMD_REG); ++ } else if (bus->buf_base) { + len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK, + readl(bus->base + + ASPEED_I2C_BUF_CTRL_REG)); +@@ -460,7 +518,15 @@ aspeed_i2c_prepare_rx_buf(struct aspeed_i2c_bus *bus, struct i2c_msg *msg) + command |= ASPEED_I2CD_M_S_RX_CMD_LAST; + } - if (msg->len > bus->buf_size) { -@@ -467,7 +544,26 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus) - command |= ASPEED_I2CD_M_S_RX_CMD_LAST; - } - } else { -- if (bus->buf_base) { -+ if (bus->dma_buf) { -+ command |= ASPEED_I2CD_TX_DMA_ENABLE; -+ -+ if (msg->len + 1 > bus->dma_buf_size) -+ len = bus->dma_buf_size; -+ else -+ len = msg->len + 1; +- if (bus->buf_base) { ++ if (bus->dma_buf) { ++ command |= ASPEED_I2CD_RX_DMA_ENABLE; + -+ bus->dma_buf[0] = slave_addr; -+ memcpy(bus->dma_buf + 1, msg->buf, len); ++ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK, ++ bus->base + ASPEED_I2C_DMA_ADDR_REG); ++ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, len), ++ bus->base + ASPEED_I2C_DMA_LEN_REG); ++ bus->dma_len = len; ++ } else { + command |= ASPEED_I2CD_RX_BUFF_ENABLE; + + writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK, len - 1) | +@@ -483,7 +549,18 @@ aspeed_i2c_prepare_tx_buf(struct aspeed_i2c_bus *bus, struct i2c_msg *msg) + else + len = msg->len + 1; + +- if (bus->buf_base) { ++ if (bus->dma_buf) { ++ command |= ASPEED_I2CD_TX_DMA_ENABLE; + -+ bus->buf_index = len - 1; ++ bus->dma_buf[0] = slave_addr; ++ memcpy(bus->dma_buf + 1, msg->buf, len); + -+ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK, -+ bus->base + ASPEED_I2C_DMA_ADDR_REG); -+ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, -+ len), -+ bus->base + ASPEED_I2C_DMA_LEN_REG); -+ bus->dma_len = len; -+ } else if (bus->buf_base) { - int i; ++ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK, ++ bus->base + ASPEED_I2C_DMA_ADDR_REG); ++ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, len), ++ bus->base + ASPEED_I2C_DMA_LEN_REG); ++ bus->dma_len = len; ++ } else { + u8 wbuf[4]; + int i; + +@@ -536,18 +613,19 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus) + if (msg->flags & I2C_M_RD) { + command |= ASPEED_I2CD_M_RX_CMD; + if (!(msg->flags & I2C_M_RECV_LEN)) { +- if (msg->len && bus->buf_base) ++ if (msg->len && (bus->dma_buf || bus->buf_base)) + command |= aspeed_i2c_prepare_rx_buf(bus, msg); - command |= ASPEED_I2CD_TX_BUFF_ENABLE; -@@ -503,7 +599,8 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus) + /* Need to let the hardware know to NACK after RX. */ + if (msg->len <= 1) + command |= ASPEED_I2CD_M_S_RX_CMD_LAST; } +- } else if (msg->len && bus->buf_base) { ++ } else if (msg->len && (bus->dma_buf || bus->buf_base)) { + command |= aspeed_i2c_prepare_tx_buf(bus, msg); } - if (!(command & ASPEED_I2CD_TX_BUFF_ENABLE)) + if (!(command & (ASPEED_I2CD_TX_BUFF_ENABLE | + ASPEED_I2CD_TX_DMA_ENABLE))) - writel(slave_addr, bus->base + ASPEED_I2C_BYTE_BUF_REG); + writel(i2c_8bit_addr_from_msg(msg), + bus->base + ASPEED_I2C_BYTE_BUF_REG); writel(command, bus->base + ASPEED_I2C_CMD_REG); - } -@@ -649,7 +746,28 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status) - if (bus->buf_index < msg->len) { - command = ASPEED_I2CD_M_TX_CMD; +@@ -590,39 +668,52 @@ aspeed_i2c_master_handle_tx_first(struct aspeed_i2c_bus *bus, + { + u32 command = 0; + +- if (bus->buf_base) { +- u8 wbuf[4]; ++ if (bus->dma_buf || bus->buf_base) { + int len; +- int i; -- if (bus->buf_base) { -+ if (bus->dma_buf) { -+ command |= ASPEED_I2CD_TX_DMA_ENABLE; + if (msg->len - bus->buf_index > bus->buf_size) + len = bus->buf_size; + else + len = msg->len - bus->buf_index; + ++ if (bus->dma_buf) { ++ command |= ASPEED_I2CD_TX_DMA_ENABLE; + +- command |= ASPEED_I2CD_TX_BUFF_ENABLE; ++ memcpy(bus->dma_buf, msg->buf + bus->buf_index, len); + +- if (msg->len - bus->buf_index > bus->buf_size) +- len = bus->buf_size; +- else +- len = msg->len - bus->buf_index; + +- for (i = 0; i < len; i++) { +- wbuf[i % 4] = msg->buf[bus->buf_index + i]; +- if (i % 4 == 3) ++ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK, ++ bus->base + ASPEED_I2C_DMA_ADDR_REG); ++ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, len), ++ bus->base + ASPEED_I2C_DMA_LEN_REG); ++ bus->dma_len = len; ++ } else { ++ u8 wbuf[4]; ++ int i; + -+ if (msg->len - bus->buf_index > -+ bus->dma_buf_size) -+ len = bus->dma_buf_size; -+ else -+ len = msg->len - bus->buf_index; ++ command |= ASPEED_I2CD_TX_BUFF_ENABLE; + -+ memcpy(bus->dma_buf, msg->buf + bus->buf_index, -+ len); ++ if (msg->len - bus->buf_index > bus->buf_size) ++ len = bus->buf_size; ++ else ++ len = msg->len - bus->buf_index; + -+ bus->buf_index += len; ++ for (i = 0; i < len; i++) { ++ wbuf[i % 4] = msg->buf[bus->buf_index + i]; ++ if (i % 4 == 3) ++ writel(*(u32 *)wbuf, ++ bus->buf_base + i - 3); ++ } ++ if (--i % 4 != 3) + writel(*(u32 *)wbuf, +- bus->buf_base + i - 3); +- } +- if (--i % 4 != 3) +- writel(*(u32 *)wbuf, +- bus->buf_base + i - (i % 4)); ++ bus->buf_base + i - (i % 4)); + +- writel(FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK, +- len - 1) | +- FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, +- bus->buf_offset), +- bus->base + ASPEED_I2C_BUF_CTRL_REG); ++ writel(FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK, ++ len - 1) | ++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, ++ bus->buf_offset), ++ bus->base + ASPEED_I2C_BUF_CTRL_REG); ++ } + + bus->buf_index += len; + } else { +@@ -639,7 +730,14 @@ aspeed_i2c_master_handle_rx(struct aspeed_i2c_bus *bus, struct i2c_msg *msg) + u8 recv_byte; + int len; + +- if (bus->buf_base) { ++ if (bus->dma_buf) { ++ len = bus->dma_len - ++ FIELD_GET(ASPEED_I2CD_DMA_LEN_MASK, ++ readl(bus->base + ASPEED_I2C_DMA_LEN_REG)); + -+ writel(bus->dma_handle & -+ ASPEED_I2CD_DMA_ADDR_MASK, -+ bus->base + ASPEED_I2C_DMA_ADDR_REG); -+ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, -+ len), -+ bus->base + ASPEED_I2C_DMA_LEN_REG); -+ bus->dma_len = len; -+ } else if (bus->buf_base) { - u8 wbuf[4]; - int i; - -@@ -700,7 +818,15 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status) ++ memcpy(msg->buf + bus->buf_index, bus->dma_buf, len); ++ bus->buf_index += len; ++ } else if (bus->buf_base) { + len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK, + readl(bus->base + ASPEED_I2C_BUF_CTRL_REG)); + memcpy_fromio(msg->buf + bus->buf_index, bus->buf_base, len); +@@ -656,7 +754,7 @@ aspeed_i2c_master_handle_rx_next(struct aspeed_i2c_bus *bus, + { + u32 command = 0; + +- if (bus->buf_base) { ++ if (bus->dma_buf || bus->buf_base) { + int len; + + if (msg->len - bus->buf_index > bus->buf_size) { +@@ -666,14 +764,24 @@ aspeed_i2c_master_handle_rx_next(struct aspeed_i2c_bus *bus, + command |= ASPEED_I2CD_M_S_RX_CMD_LAST; } - irq_handled |= ASPEED_I2CD_INTR_RX_DONE; -- if (bus->buf_base && !(msg->flags & I2C_M_RECV_LEN)) { -+ if (bus->dma_buf && !(msg->flags & I2C_M_RECV_LEN)) { -+ len = bus->dma_len - -+ FIELD_GET(ASPEED_I2CD_DMA_LEN_MASK, -+ readl(bus->base + -+ ASPEED_I2C_DMA_LEN_REG)); -+ -+ memcpy(msg->buf + bus->buf_index, bus->dma_buf, len); -+ bus->buf_index += len; -+ } else if (bus->buf_base && !(msg->flags & I2C_M_RECV_LEN)) { - len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK, - readl(bus->base + - ASPEED_I2C_BUF_CTRL_REG)); -@@ -728,7 +854,25 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status) - if (bus->buf_index < msg->len) { - command = ASPEED_I2CD_M_RX_CMD; - bus->master_state = ASPEED_I2C_MASTER_RX; -- if (bus->buf_base) { -+ if (bus->dma_buf) { -+ command |= ASPEED_I2CD_RX_DMA_ENABLE; -+ -+ if (msg->len - bus->buf_index > -+ bus->dma_buf_size) { -+ len = bus->dma_buf_size; -+ } else { -+ len = msg->len - bus->buf_index; -+ command |= ASPEED_I2CD_M_S_RX_CMD_LAST; -+ } +- command |= ASPEED_I2CD_RX_BUFF_ENABLE; ++ if (bus->dma_buf) { ++ command |= ASPEED_I2CD_RX_DMA_ENABLE; + +- writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK, +- len - 1) | +- FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK, 0) | +- FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, +- bus->buf_offset), +- bus->base + ASPEED_I2C_BUF_CTRL_REG); ++ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK, ++ bus->base + ASPEED_I2C_DMA_ADDR_REG); ++ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, len), ++ bus->base + ASPEED_I2C_DMA_LEN_REG); ++ bus->dma_len = len; ++ } else { ++ command |= ASPEED_I2CD_RX_BUFF_ENABLE; + -+ writel(bus->dma_handle & -+ ASPEED_I2CD_DMA_ADDR_MASK, -+ bus->base + ASPEED_I2C_DMA_ADDR_REG); -+ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, -+ len), -+ bus->base + ASPEED_I2C_DMA_LEN_REG); -+ bus->dma_len = len; -+ } else if (bus->buf_base) { - command |= ASPEED_I2CD_RX_BUFF_ENABLE; - - if (msg->len - bus->buf_index > -@@ -1235,7 +1379,51 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) ++ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK, ++ len - 1) | ++ FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK, 0) | ++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, ++ bus->buf_offset), ++ bus->base + ASPEED_I2C_BUF_CTRL_REG); ++ } + } else { + if (bus->buf_index + 1 == msg->len) + command |= ASPEED_I2CD_M_S_RX_CMD_LAST; +@@ -1260,7 +1368,51 @@ static void aspeed_i2c_set_xfer_mode(struct aspeed_i2c_bus *bus) sram_enabled = false; } - if (sram_enabled) { + /* -+ * Only AST2500 supports DMA mode under some limitations: ++ * Only AST2500 and AST2600 support DMA mode under some limitations: + * I2C is sharing the DMA H/W with UHCI host controller and MCTP + * controller. Since those controllers operate with DMA mode only, I2C + * has to use buffer mode or byte mode instead if one of those @@ -350,25 +399,25 @@ index 1b338492c68a..8dc6723bfaaf 100644 + * use DMA mode. + */ + if (sram_enabled && !IS_ENABLED(CONFIG_USB_UHCI_ASPEED) && -+ of_device_is_compatible(pdev->dev.of_node, -+ "aspeed,ast2500-i2c-bus")) { ++ !of_device_is_compatible(pdev->dev.of_node, ++ "aspeed,ast2400-i2c-bus")) { + u32 dma_len_max = ASPEED_I2CD_DMA_LEN_MASK >> + ASPEED_I2CD_DMA_LEN_SHIFT; + + ret = device_property_read_u32(&pdev->dev, + "aspeed,dma-buf-size", -+ &bus->dma_buf_size); -+ if (!ret && bus->dma_buf_size > dma_len_max) -+ bus->dma_buf_size = dma_len_max; ++ &bus->buf_size); ++ if (!ret && bus->buf_size > dma_len_max) ++ bus->buf_size = dma_len_max; + } + -+ if (bus->dma_buf_size) { ++ if (bus->buf_size) { + if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) { + dev_warn(&pdev->dev, "No suitable DMA available\n"); + } else { + bus->dma_pool = dma_pool_create("i2c-aspeed", + &pdev->dev, -+ bus->dma_buf_size, ++ bus->buf_size, + ASPEED_I2CD_DMA_ALIGN, + 0); + if (bus->dma_pool) @@ -388,7 +437,7 @@ index 1b338492c68a..8dc6723bfaaf 100644 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 1); -@@ -1275,24 +1463,33 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) +@@ -1365,24 +1517,33 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) */ ret = aspeed_i2c_init(bus, pdev); if (ret < 0) @@ -426,7 +475,7 @@ index 1b338492c68a..8dc6723bfaaf 100644 } static int aspeed_i2c_remove_bus(struct platform_device *pdev) -@@ -1310,6 +1507,10 @@ static int aspeed_i2c_remove_bus(struct platform_device *pdev) +@@ -1400,6 +1561,10 @@ static int aspeed_i2c_remove_bus(struct platform_device *pdev) reset_control_assert(bus->rst); -- cgit v1.2.3