Skip to content
Snippets Groups Projects
Commit 491739bb authored by Armando Visconti's avatar Armando Visconti Committed by Tom Rini
Browse files

designware_i2c: Added s/w generation of stop bit


In the newer versions of designware i2c IP there is the possibility
of configuring it with IC_EMPTYFIFO_HOLD_MASTER_EN=1, which basically
requires the s/w to generate the stop bit condition directly, as
the h/w will not automatically generate it when TX_FIFO is empty.

To avoid generation of an extra 0x0 byte sent as data, the
IC_STOP command must be sent along with the last IC_CMD.

This patch always writes bit[9] of ic_data_cmd even in the
older versions, assuming that it is a noop there.

Signed-off-by: default avatarArmando Visconti <armando.visconti@st.com>
parent ac6e2fe6
No related branches found
No related tags found
No related merge requests found
...@@ -283,7 +283,10 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) ...@@ -283,7 +283,10 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
start_time_rx = get_timer(0); start_time_rx = get_timer(0);
while (len) { while (len) {
writel(IC_CMD, &i2c_regs_p->ic_cmd_data); if (len == 1)
writel(IC_CMD | IC_STOP, &i2c_regs_p->ic_cmd_data);
else
writel(IC_CMD, &i2c_regs_p->ic_cmd_data);
if (readl(&i2c_regs_p->ic_status) & IC_STATUS_RFNE) { if (readl(&i2c_regs_p->ic_status) & IC_STATUS_RFNE) {
*buffer++ = (uchar)readl(&i2c_regs_p->ic_cmd_data); *buffer++ = (uchar)readl(&i2c_regs_p->ic_cmd_data);
...@@ -322,9 +325,11 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) ...@@ -322,9 +325,11 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
start_time_tx = get_timer(0); start_time_tx = get_timer(0);
while (len) { while (len) {
if (readl(&i2c_regs_p->ic_status) & IC_STATUS_TFNF) { if (readl(&i2c_regs_p->ic_status) & IC_STATUS_TFNF) {
writel(*buffer, &i2c_regs_p->ic_cmd_data); if (--len == 0)
writel(*buffer | IC_STOP, &i2c_regs_p->ic_cmd_data);
else
writel(*buffer, &i2c_regs_p->ic_cmd_data);
buffer++; buffer++;
len--;
start_time_tx = get_timer(0); start_time_tx = get_timer(0);
} else if (get_timer(start_time_tx) > (nb * I2C_BYTE_TO)) { } else if (get_timer(start_time_tx) > (nb * I2C_BYTE_TO)) {
......
...@@ -95,6 +95,7 @@ struct i2c_regs { ...@@ -95,6 +95,7 @@ struct i2c_regs {
/* i2c data buffer and command register definitions */ /* i2c data buffer and command register definitions */
#define IC_CMD 0x0100 #define IC_CMD 0x0100
#define IC_STOP 0x0200
/* i2c interrupt status register definitions */ /* i2c interrupt status register definitions */
#define IC_GEN_CALL 0x0800 #define IC_GEN_CALL 0x0800
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment