aboutsummaryrefslogtreecommitdiff
path: root/hw/i2c/bitbang_i2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/i2c/bitbang_i2c.c')
-rw-r--r--hw/i2c/bitbang_i2c.c82
1 files changed, 51 insertions, 31 deletions
diff --git a/hw/i2c/bitbang_i2c.c b/hw/i2c/bitbang_i2c.c
index e9a0612a04..bb18954765 100644
--- a/hw/i2c/bitbang_i2c.c
+++ b/hw/i2c/bitbang_i2c.c
@@ -16,30 +16,57 @@
#include "hw/sysbus.h"
#include "qemu/module.h"
#include "qom/object.h"
+#include "trace.h"
+
+
+/* bitbang_i2c_state enum to name */
+static const char * const sname[] = {
+#define NAME(e) [e] = stringify(e)
+ NAME(STOPPED),
+ [SENDING_BIT7] = "SENDING_BIT7 (START)",
+ NAME(SENDING_BIT6),
+ NAME(SENDING_BIT5),
+ NAME(SENDING_BIT4),
+ NAME(SENDING_BIT3),
+ NAME(SENDING_BIT2),
+ NAME(SENDING_BIT1),
+ NAME(SENDING_BIT0),
+ NAME(WAITING_FOR_ACK),
+ [RECEIVING_BIT7] = "RECEIVING_BIT7 (ACK)",
+ NAME(RECEIVING_BIT6),
+ NAME(RECEIVING_BIT5),
+ NAME(RECEIVING_BIT4),
+ NAME(RECEIVING_BIT3),
+ NAME(RECEIVING_BIT2),
+ NAME(RECEIVING_BIT1),
+ NAME(RECEIVING_BIT0),
+ NAME(SENDING_ACK),
+ NAME(SENT_NACK)
+#undef NAME
+};
-//#define DEBUG_BITBANG_I2C
-
-#ifdef DEBUG_BITBANG_I2C
-#define DPRINTF(fmt, ...) \
-do { printf("bitbang_i2c: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#endif
+static void bitbang_i2c_set_state(bitbang_i2c_interface *i2c,
+ bitbang_i2c_state state)
+{
+ trace_bitbang_i2c_state(sname[i2c->state], sname[state]);
+ i2c->state = state;
+}
static void bitbang_i2c_enter_stop(bitbang_i2c_interface *i2c)
{
- DPRINTF("STOP\n");
if (i2c->current_addr >= 0)
i2c_end_transfer(i2c->bus);
i2c->current_addr = -1;
- i2c->state = STOPPED;
+ bitbang_i2c_set_state(i2c, STOPPED);
}
/* Set device data pin. */
static int bitbang_i2c_ret(bitbang_i2c_interface *i2c, int level)
{
+ trace_bitbang_i2c_data(i2c->last_clock, i2c->last_data,
+ i2c->device_out, level);
i2c->device_out = level;
- //DPRINTF("%d %d %d\n", i2c->last_clock, i2c->last_data, i2c->device_out);
+
return level & i2c->last_data;
}
@@ -67,9 +94,8 @@ int bitbang_i2c_set(bitbang_i2c_interface *i2c, int line, int level)
return bitbang_i2c_nop(i2c);
}
if (level == 0) {
- DPRINTF("START\n");
/* START condition. */
- i2c->state = SENDING_BIT7;
+ bitbang_i2c_set_state(i2c, SENDING_BIT7);
i2c->current_addr = -1;
} else {
/* STOP condition. */
@@ -96,7 +122,7 @@ int bitbang_i2c_set(bitbang_i2c_interface *i2c, int line, int level)
case SENDING_BIT7 ... SENDING_BIT0:
i2c->buffer = (i2c->buffer << 1) | data;
/* will end up in WAITING_FOR_ACK */
- i2c->state++;
+ bitbang_i2c_set_state(i2c, i2c->state + 1);
return bitbang_i2c_ret(i2c, 1);
case WAITING_FOR_ACK:
@@ -105,47 +131,45 @@ int bitbang_i2c_set(bitbang_i2c_interface *i2c, int line, int level)
if (i2c->current_addr < 0) {
i2c->current_addr = i2c->buffer;
- DPRINTF("Address 0x%02x\n", i2c->current_addr);
+ trace_bitbang_i2c_addr(i2c->current_addr);
ret = i2c_start_transfer(i2c->bus, i2c->current_addr >> 1,
i2c->current_addr & 1);
} else {
- DPRINTF("Sent 0x%02x\n", i2c->buffer);
+ trace_bitbang_i2c_send(i2c->buffer);
ret = i2c_send(i2c->bus, i2c->buffer);
}
if (ret) {
/* NACK (either addressing a nonexistent device, or the
* device we were sending to decided to NACK us).
*/
- DPRINTF("Got NACK\n");
+ bitbang_i2c_set_state(i2c, SENT_NACK);
bitbang_i2c_enter_stop(i2c);
return bitbang_i2c_ret(i2c, 1);
}
if (i2c->current_addr & 1) {
- i2c->state = RECEIVING_BIT7;
+ bitbang_i2c_set_state(i2c, RECEIVING_BIT7);
} else {
- i2c->state = SENDING_BIT7;
+ bitbang_i2c_set_state(i2c, SENDING_BIT7);
}
return bitbang_i2c_ret(i2c, 0);
}
case RECEIVING_BIT7:
i2c->buffer = i2c_recv(i2c->bus);
- DPRINTF("RX byte 0x%02x\n", i2c->buffer);
+ trace_bitbang_i2c_recv(i2c->buffer);
/* Fall through... */
case RECEIVING_BIT6 ... RECEIVING_BIT0:
data = i2c->buffer >> 7;
/* will end up in SENDING_ACK */
- i2c->state++;
+ bitbang_i2c_set_state(i2c, i2c->state + 1);
i2c->buffer <<= 1;
return bitbang_i2c_ret(i2c, data);
case SENDING_ACK:
- i2c->state = RECEIVING_BIT7;
if (data != 0) {
- DPRINTF("NACKED\n");
- i2c->state = SENT_NACK;
+ bitbang_i2c_set_state(i2c, SENT_NACK);
i2c_nack(i2c->bus);
} else {
- DPRINTF("ACKED\n");
+ bitbang_i2c_set_state(i2c, RECEIVING_BIT7);
}
return bitbang_i2c_ret(i2c, 1);
}
@@ -162,13 +186,13 @@ void bitbang_i2c_init(bitbang_i2c_interface *s, I2CBus *bus)
/* GPIO interface. */
-#define TYPE_GPIO_I2C "gpio_i2c"
OBJECT_DECLARE_SIMPLE_TYPE(GPIOI2CState, GPIO_I2C)
struct GPIOI2CState {
+ /*< private >*/
SysBusDevice parent_obj;
+ /*< public >*/
- MemoryRegion dummy_iomem;
bitbang_i2c_interface bitbang;
int last_level;
qemu_irq out;
@@ -189,12 +213,8 @@ static void gpio_i2c_init(Object *obj)
{
DeviceState *dev = DEVICE(obj);
GPIOI2CState *s = GPIO_I2C(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
I2CBus *bus;
- memory_region_init(&s->dummy_iomem, obj, "gpio_i2c", 0);
- sysbus_init_mmio(sbd, &s->dummy_iomem);
-
bus = i2c_init_bus(dev, "i2c");
bitbang_i2c_init(&s->bitbang, bus);