Skip to content

Commit

Permalink
i2c: Factor our send() and recv() common logic
Browse files Browse the repository at this point in the history
Most of the control flow logic between send and recv (error checking
etc) is the same. Factor this out into a common send_recv() API.
This is then usable by clients, where the control logic for send
and receive differs only by a boolean. E.g.

if (send)
   i2c_send(...):
else
   i2c_recv(...);

becomes:

i2c_send_recv(... , send);

Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
Message-id: 1465833014-21982-4-git-send-email-fred.konrad@greensocs.com
Changes from FK:
  * Rebased on master.
  * Rebased on my i2c broadcast patch.
Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pcrost authored and pm215 committed Jun 14, 2016
1 parent 2293c27 commit 056fca7
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 18 deletions.
52 changes: 34 additions & 18 deletions hw/i2c/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,36 +149,52 @@ void i2c_end_transfer(I2CBus *bus)
bus->broadcast = false;
}

int i2c_send(I2CBus *bus, uint8_t data)
int i2c_send_recv(I2CBus *bus, uint8_t *data, bool send)
{
I2CSlaveClass *sc;
I2CNode *node;
int ret = 0;

QLIST_FOREACH(node, &bus->current_devs, next) {
sc = I2C_SLAVE_GET_CLASS(node->elt);
if (sc->send) {
ret = ret || sc->send(node->elt, data);
} else {
ret = -1;
if (send) {
QLIST_FOREACH(node, &bus->current_devs, next) {
sc = I2C_SLAVE_GET_CLASS(node->elt);
if (sc->send) {
ret = ret || sc->send(node->elt, *data);
} else {
ret = -1;
}
}
return ret ? -1 : 0;
} else {
if ((QLIST_EMPTY(&bus->current_devs)) || (bus->broadcast)) {
return -1;
}

sc = I2C_SLAVE_GET_CLASS(QLIST_FIRST(&bus->current_devs)->elt);
if (sc->recv) {
ret = sc->recv(QLIST_FIRST(&bus->current_devs)->elt);
if (ret < 0) {
return ret;
} else {
*data = ret;
return 0;
}
}
return -1;
}
return ret ? -1 : 0;
}

int i2c_recv(I2CBus *bus)
int i2c_send(I2CBus *bus, uint8_t data)
{
I2CSlaveClass *sc;
return i2c_send_recv(bus, &data, true);
}

if ((QLIST_EMPTY(&bus->current_devs)) || (bus->broadcast)) {
return -1;
}
int i2c_recv(I2CBus *bus)
{
uint8_t data;
int ret = i2c_send_recv(bus, &data, false);

sc = I2C_SLAVE_GET_CLASS(QLIST_FIRST(&bus->current_devs)->elt);
if (sc->recv) {
return sc->recv(QLIST_FIRST(&bus->current_devs)->elt);
}
return -1;
return ret < 0 ? ret : data;
}

void i2c_nack(I2CBus *bus)
Expand Down
1 change: 1 addition & 0 deletions include/hw/i2c/i2c.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ int i2c_bus_busy(I2CBus *bus);
int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv);
void i2c_end_transfer(I2CBus *bus);
void i2c_nack(I2CBus *bus);
int i2c_send_recv(I2CBus *bus, uint8_t *data, bool send);
int i2c_send(I2CBus *bus, uint8_t data);
int i2c_recv(I2CBus *bus);

Expand Down

0 comments on commit 056fca7

Please sign in to comment.