Skip to content

Commit 434f14e

Browse files
Cyrille PitchenWolfram Sang
authored andcommitted
i2c: at91: fix support of the "alternative command" feature
The "alternative command" feature was introduced with sama5d2 SoCs. Its purpose is to let the hardware i2c controller automatically send the STOP condition on the i2c bus at the end of a data transfer. Without this feature, the i2c driver has to write the 'STOP' bit into the Control Register so the hardware i2c controller is triggered to send the STOP condition on the bus. Using the "alternative command" feature requires to set the transfer data length into the 8bit DATAL field of the Alternative Command Register. Hence only data transfers up to 255 bytes can take advantage of the "alternative command" feature. For greater data transfer sizes, the driver should use the previous implementation, when the "alternative command" support was not implemented yet. Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com> Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
1 parent 97ccd4a commit 434f14e

File tree

1 file changed

+14
-10
lines changed

1 file changed

+14
-10
lines changed

drivers/i2c/busses/i2c-at91.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#define AT91_I2C_TIMEOUT msecs_to_jiffies(100) /* transfer timeout */
3939
#define AT91_I2C_DMA_THRESHOLD 8 /* enable DMA if transfer size is bigger than this threshold */
4040
#define AUTOSUSPEND_TIMEOUT 2000
41+
#define AT91_I2C_MAX_ALT_CMD_DATA_SIZE 256
4142

4243
/* AT91 TWI register definitions */
4344
#define AT91_TWI_CR 0x0000 /* Control Register */
@@ -141,6 +142,7 @@ struct at91_twi_dev {
141142
unsigned twi_cwgr_reg;
142143
struct at91_twi_pdata *pdata;
143144
bool use_dma;
145+
bool use_alt_cmd;
144146
bool recv_len_abort;
145147
u32 fifo_size;
146148
struct at91_twi_dma dma;
@@ -269,7 +271,7 @@ static void at91_twi_write_next_byte(struct at91_twi_dev *dev)
269271

270272
/* send stop when last byte has been written */
271273
if (--dev->buf_len == 0)
272-
if (!dev->pdata->has_alt_cmd)
274+
if (!dev->use_alt_cmd)
273275
at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP);
274276

275277
dev_dbg(dev->dev, "wrote 0x%x, to go %d\n", *dev->buf, dev->buf_len);
@@ -292,7 +294,7 @@ static void at91_twi_write_data_dma_callback(void *data)
292294
* we just have to enable TXCOMP one.
293295
*/
294296
at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP);
295-
if (!dev->pdata->has_alt_cmd)
297+
if (!dev->use_alt_cmd)
296298
at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP);
297299
}
298300

@@ -410,7 +412,7 @@ static void at91_twi_read_next_byte(struct at91_twi_dev *dev)
410412
}
411413

412414
/* send stop if second but last byte has been read */
413-
if (!dev->pdata->has_alt_cmd && dev->buf_len == 1)
415+
if (!dev->use_alt_cmd && dev->buf_len == 1)
414416
at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP);
415417

416418
dev_dbg(dev->dev, "read 0x%x, to go %d\n", *dev->buf, dev->buf_len);
@@ -426,7 +428,7 @@ static void at91_twi_read_data_dma_callback(void *data)
426428
dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg[0]),
427429
dev->buf_len, DMA_FROM_DEVICE);
428430

429-
if (!dev->pdata->has_alt_cmd) {
431+
if (!dev->use_alt_cmd) {
430432
/* The last two bytes have to be read without using dma */
431433
dev->buf += dev->buf_len - 2;
432434
dev->buf_len = 2;
@@ -443,7 +445,7 @@ static void at91_twi_read_data_dma(struct at91_twi_dev *dev)
443445
struct dma_chan *chan_rx = dma->chan_rx;
444446
size_t buf_len;
445447

446-
buf_len = (dev->pdata->has_alt_cmd) ? dev->buf_len : dev->buf_len - 2;
448+
buf_len = (dev->use_alt_cmd) ? dev->buf_len : dev->buf_len - 2;
447449
dma->direction = DMA_FROM_DEVICE;
448450

449451
/* Keep in mind that we won't use dma to read the last two bytes */
@@ -651,7 +653,7 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
651653
unsigned start_flags = AT91_TWI_START;
652654

653655
/* if only one byte is to be read, immediately stop transfer */
654-
if (!has_alt_cmd && dev->buf_len <= 1 &&
656+
if (!dev->use_alt_cmd && dev->buf_len <= 1 &&
655657
!(dev->msg->flags & I2C_M_RECV_LEN))
656658
start_flags |= AT91_TWI_STOP;
657659
at91_twi_write(dev, AT91_TWI_CR, start_flags);
@@ -745,7 +747,7 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
745747
int ret;
746748
unsigned int_addr_flag = 0;
747749
struct i2c_msg *m_start = msg;
748-
bool is_read, use_alt_cmd = false;
750+
bool is_read;
749751

750752
dev_dbg(&adap->dev, "at91_xfer: processing %d messages:\n", num);
751753

@@ -768,14 +770,16 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
768770
at91_twi_write(dev, AT91_TWI_IADR, internal_address);
769771
}
770772

773+
dev->use_alt_cmd = false;
771774
is_read = (m_start->flags & I2C_M_RD);
772775
if (dev->pdata->has_alt_cmd) {
773-
if (m_start->len > 0) {
776+
if (m_start->len > 0 &&
777+
m_start->len < AT91_I2C_MAX_ALT_CMD_DATA_SIZE) {
774778
at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_ACMEN);
775779
at91_twi_write(dev, AT91_TWI_ACR,
776780
AT91_TWI_ACR_DATAL(m_start->len) |
777781
((is_read) ? AT91_TWI_ACR_DIR : 0));
778-
use_alt_cmd = true;
782+
dev->use_alt_cmd = true;
779783
} else {
780784
at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_ACMDIS);
781785
}
@@ -784,7 +788,7 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
784788
at91_twi_write(dev, AT91_TWI_MMR,
785789
(m_start->addr << 16) |
786790
int_addr_flag |
787-
((!use_alt_cmd && is_read) ? AT91_TWI_MREAD : 0));
791+
((!dev->use_alt_cmd && is_read) ? AT91_TWI_MREAD : 0));
788792

789793
dev->buf_len = m_start->len;
790794
dev->buf = m_start->buf;

0 commit comments

Comments
 (0)