diff options
Diffstat (limited to 'hw/i2c')
| -rw-r--r-- | hw/i2c/Kconfig | 2 | ||||
| -rw-r--r-- | hw/i2c/arm_sbcon_i2c.c (renamed from hw/i2c/versatile_i2c.c) | 39 | ||||
| -rw-r--r-- | hw/i2c/bitbang_i2c.c | 82 | ||||
| -rw-r--r-- | hw/i2c/meson.build | 2 | ||||
| -rw-r--r-- | hw/i2c/trace-events | 7 |
5 files changed, 77 insertions, 55 deletions
diff --git a/hw/i2c/Kconfig b/hw/i2c/Kconfig index f8ec461be3..14886b35da 100644 --- a/hw/i2c/Kconfig +++ b/hw/i2c/Kconfig @@ -14,7 +14,7 @@ config SMBUS_EEPROM bool select SMBUS -config VERSATILE_I2C +config ARM_SBCON_I2C bool select BITBANG_I2C diff --git a/hw/i2c/versatile_i2c.c b/hw/i2c/arm_sbcon_i2c.c index 3a04ba3969..979ccbe0ed 100644 --- a/hw/i2c/versatile_i2c.c +++ b/hw/i2c/arm_sbcon_i2c.c @@ -29,11 +29,6 @@ #include "qemu/module.h" #include "qom/object.h" -typedef ArmSbconI2CState VersatileI2CState; -DECLARE_INSTANCE_CHECKER(VersatileI2CState, VERSATILE_I2C, - TYPE_VERSATILE_I2C) - - REG32(CONTROL_GET, 0) REG32(CONTROL_SET, 0) @@ -42,10 +37,10 @@ REG32(CONTROL_CLR, 4) #define SCL BIT(0) #define SDA BIT(1) -static uint64_t versatile_i2c_read(void *opaque, hwaddr offset, +static uint64_t arm_sbcon_i2c_read(void *opaque, hwaddr offset, unsigned size) { - VersatileI2CState *s = (VersatileI2CState *)opaque; + ArmSbconI2CState *s = opaque; switch (offset) { case A_CONTROL_SET: @@ -57,10 +52,10 @@ static uint64_t versatile_i2c_read(void *opaque, hwaddr offset, } } -static void versatile_i2c_write(void *opaque, hwaddr offset, +static void arm_sbcon_i2c_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { - VersatileI2CState *s = (VersatileI2CState *)opaque; + ArmSbconI2CState *s = opaque; switch (offset) { case A_CONTROL_SET: @@ -77,36 +72,36 @@ static void versatile_i2c_write(void *opaque, hwaddr offset, s->in = bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SDA, (s->out & SDA) != 0); } -static const MemoryRegionOps versatile_i2c_ops = { - .read = versatile_i2c_read, - .write = versatile_i2c_write, +static const MemoryRegionOps arm_sbcon_i2c_ops = { + .read = arm_sbcon_i2c_read, + .write = arm_sbcon_i2c_write, .endianness = DEVICE_NATIVE_ENDIAN, }; -static void versatile_i2c_init(Object *obj) +static void arm_sbcon_i2c_init(Object *obj) { DeviceState *dev = DEVICE(obj); - VersatileI2CState *s = VERSATILE_I2C(obj); + ArmSbconI2CState *s = ARM_SBCON_I2C(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj); I2CBus *bus; bus = i2c_init_bus(dev, "i2c"); bitbang_i2c_init(&s->bitbang, bus); - memory_region_init_io(&s->iomem, obj, &versatile_i2c_ops, s, + memory_region_init_io(&s->iomem, obj, &arm_sbcon_i2c_ops, s, "arm_sbcon_i2c", 0x1000); sysbus_init_mmio(sbd, &s->iomem); } -static const TypeInfo versatile_i2c_info = { - .name = TYPE_VERSATILE_I2C, +static const TypeInfo arm_sbcon_i2c_info = { + .name = TYPE_ARM_SBCON_I2C, .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(VersatileI2CState), - .instance_init = versatile_i2c_init, + .instance_size = sizeof(ArmSbconI2CState), + .instance_init = arm_sbcon_i2c_init, }; -static void versatile_i2c_register_types(void) +static void arm_sbcon_i2c_register_types(void) { - type_register_static(&versatile_i2c_info); + type_register_static(&arm_sbcon_i2c_info); } -type_init(versatile_i2c_register_types) +type_init(arm_sbcon_i2c_register_types) 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); diff --git a/hw/i2c/meson.build b/hw/i2c/meson.build index e4c8e14a52..3996564c25 100644 --- a/hw/i2c/meson.build +++ b/hw/i2c/meson.build @@ -12,7 +12,7 @@ i2c_ss.add(when: 'CONFIG_ALLWINNER_I2C', if_true: files('allwinner-i2c.c')) i2c_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('microbit_i2c.c')) i2c_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_smbus.c')) i2c_ss.add(when: 'CONFIG_SMBUS_EEPROM', if_true: files('smbus_eeprom.c')) -i2c_ss.add(when: 'CONFIG_VERSATILE_I2C', if_true: files('versatile_i2c.c')) +i2c_ss.add(when: 'CONFIG_ARM_SBCON_I2C', if_true: files('arm_sbcon_i2c.c')) i2c_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_i2c.c')) i2c_ss.add(when: 'CONFIG_PPC4XX', if_true: files('ppc4xx_i2c.c')) i2c_ss.add(when: 'CONFIG_PCA954X', if_true: files('i2c_mux_pca954x.c')) diff --git a/hw/i2c/trace-events b/hw/i2c/trace-events index 52dbd53a23..8e88aa24c1 100644 --- a/hw/i2c/trace-events +++ b/hw/i2c/trace-events @@ -1,5 +1,12 @@ # See docs/devel/tracing.rst for syntax documentation. +# bitbang_i2c.c +bitbang_i2c_state(const char *old_state, const char *new_state) "state %s -> %s" +bitbang_i2c_addr(uint8_t addr) "Address 0x%02x" +bitbang_i2c_send(uint8_t byte) "TX byte 0x%02x" +bitbang_i2c_recv(uint8_t byte) "RX byte 0x%02x" +bitbang_i2c_data(unsigned dat, unsigned clk, unsigned old_out, unsigned new_out) "dat %u clk %u out %u -> %u" + # core.c i2c_event(const char *event, uint8_t address) "%s(addr:0x%02x)" |