1*f912f1bdSKlaus Jensen /* 2*f912f1bdSKlaus Jensen * Example I2C device using asynchronous I2C send. 3*f912f1bdSKlaus Jensen * 4*f912f1bdSKlaus Jensen * Copyright (C) 2023 Samsung Electronics Co., Ltd. All Rights Reserved. 5*f912f1bdSKlaus Jensen * 6*f912f1bdSKlaus Jensen * This work is licensed under the terms of the GNU GPL, version 2. See 7*f912f1bdSKlaus Jensen * the COPYING file in the top-level directory. 8*f912f1bdSKlaus Jensen * 9*f912f1bdSKlaus Jensen */ 10*f912f1bdSKlaus Jensen 11b14037f3SKlaus Jensen #include "qemu/osdep.h" 12b14037f3SKlaus Jensen #include "qemu/timer.h" 13b14037f3SKlaus Jensen #include "qemu/main-loop.h" 14b14037f3SKlaus Jensen #include "block/aio.h" 15b14037f3SKlaus Jensen #include "hw/i2c/i2c.h" 16b14037f3SKlaus Jensen 17b14037f3SKlaus Jensen #define TYPE_I2C_ECHO "i2c-echo" 18b14037f3SKlaus Jensen OBJECT_DECLARE_SIMPLE_TYPE(I2CEchoState, I2C_ECHO) 19b14037f3SKlaus Jensen 20b14037f3SKlaus Jensen enum i2c_echo_state { 21b14037f3SKlaus Jensen I2C_ECHO_STATE_IDLE, 22b14037f3SKlaus Jensen I2C_ECHO_STATE_START_SEND, 23b14037f3SKlaus Jensen I2C_ECHO_STATE_ACK, 24b14037f3SKlaus Jensen }; 25b14037f3SKlaus Jensen 26b14037f3SKlaus Jensen typedef struct I2CEchoState { 27b14037f3SKlaus Jensen I2CSlave parent_obj; 28b14037f3SKlaus Jensen 29b14037f3SKlaus Jensen I2CBus *bus; 30b14037f3SKlaus Jensen 31b14037f3SKlaus Jensen enum i2c_echo_state state; 32b14037f3SKlaus Jensen QEMUBH *bh; 33b14037f3SKlaus Jensen 34b14037f3SKlaus Jensen unsigned int pos; 35b14037f3SKlaus Jensen uint8_t data[3]; 36b14037f3SKlaus Jensen } I2CEchoState; 37b14037f3SKlaus Jensen 38b14037f3SKlaus Jensen static void i2c_echo_bh(void *opaque) 39b14037f3SKlaus Jensen { 40b14037f3SKlaus Jensen I2CEchoState *state = opaque; 41b14037f3SKlaus Jensen 42b14037f3SKlaus Jensen switch (state->state) { 43b14037f3SKlaus Jensen case I2C_ECHO_STATE_IDLE: 44b14037f3SKlaus Jensen return; 45b14037f3SKlaus Jensen 46b14037f3SKlaus Jensen case I2C_ECHO_STATE_START_SEND: 47b14037f3SKlaus Jensen if (i2c_start_send_async(state->bus, state->data[0])) { 48b14037f3SKlaus Jensen goto release_bus; 49b14037f3SKlaus Jensen } 50b14037f3SKlaus Jensen 51b14037f3SKlaus Jensen state->pos++; 52b14037f3SKlaus Jensen state->state = I2C_ECHO_STATE_ACK; 53b14037f3SKlaus Jensen return; 54b14037f3SKlaus Jensen 55b14037f3SKlaus Jensen case I2C_ECHO_STATE_ACK: 56b14037f3SKlaus Jensen if (state->pos > 2) { 57b14037f3SKlaus Jensen break; 58b14037f3SKlaus Jensen } 59b14037f3SKlaus Jensen 60b14037f3SKlaus Jensen if (i2c_send_async(state->bus, state->data[state->pos++])) { 61b14037f3SKlaus Jensen break; 62b14037f3SKlaus Jensen } 63b14037f3SKlaus Jensen 64b14037f3SKlaus Jensen return; 65b14037f3SKlaus Jensen } 66b14037f3SKlaus Jensen 67b14037f3SKlaus Jensen 68b14037f3SKlaus Jensen i2c_end_transfer(state->bus); 69b14037f3SKlaus Jensen release_bus: 70b14037f3SKlaus Jensen i2c_bus_release(state->bus); 71b14037f3SKlaus Jensen 72b14037f3SKlaus Jensen state->state = I2C_ECHO_STATE_IDLE; 73b14037f3SKlaus Jensen } 74b14037f3SKlaus Jensen 75b14037f3SKlaus Jensen static int i2c_echo_event(I2CSlave *s, enum i2c_event event) 76b14037f3SKlaus Jensen { 77b14037f3SKlaus Jensen I2CEchoState *state = I2C_ECHO(s); 78b14037f3SKlaus Jensen 79b14037f3SKlaus Jensen switch (event) { 80b14037f3SKlaus Jensen case I2C_START_RECV: 81b14037f3SKlaus Jensen state->pos = 0; 82b14037f3SKlaus Jensen 83b14037f3SKlaus Jensen break; 84b14037f3SKlaus Jensen 85b14037f3SKlaus Jensen case I2C_START_SEND: 86b14037f3SKlaus Jensen state->pos = 0; 87b14037f3SKlaus Jensen 88b14037f3SKlaus Jensen break; 89b14037f3SKlaus Jensen 90b14037f3SKlaus Jensen case I2C_FINISH: 91b14037f3SKlaus Jensen state->pos = 0; 92b14037f3SKlaus Jensen state->state = I2C_ECHO_STATE_START_SEND; 93b14037f3SKlaus Jensen i2c_bus_master(state->bus, state->bh); 94b14037f3SKlaus Jensen 95b14037f3SKlaus Jensen break; 96b14037f3SKlaus Jensen 97b14037f3SKlaus Jensen case I2C_NACK: 98b14037f3SKlaus Jensen break; 99b14037f3SKlaus Jensen 100b14037f3SKlaus Jensen default: 101b14037f3SKlaus Jensen return -1; 102b14037f3SKlaus Jensen } 103b14037f3SKlaus Jensen 104b14037f3SKlaus Jensen return 0; 105b14037f3SKlaus Jensen } 106b14037f3SKlaus Jensen 107b14037f3SKlaus Jensen static uint8_t i2c_echo_recv(I2CSlave *s) 108b14037f3SKlaus Jensen { 109b14037f3SKlaus Jensen I2CEchoState *state = I2C_ECHO(s); 110b14037f3SKlaus Jensen 111b14037f3SKlaus Jensen if (state->pos > 2) { 112b14037f3SKlaus Jensen return 0xff; 113b14037f3SKlaus Jensen } 114b14037f3SKlaus Jensen 115b14037f3SKlaus Jensen return state->data[state->pos++]; 116b14037f3SKlaus Jensen } 117b14037f3SKlaus Jensen 118b14037f3SKlaus Jensen static int i2c_echo_send(I2CSlave *s, uint8_t data) 119b14037f3SKlaus Jensen { 120b14037f3SKlaus Jensen I2CEchoState *state = I2C_ECHO(s); 121b14037f3SKlaus Jensen 122b14037f3SKlaus Jensen if (state->pos > 2) { 123b14037f3SKlaus Jensen return -1; 124b14037f3SKlaus Jensen } 125b14037f3SKlaus Jensen 126b14037f3SKlaus Jensen state->data[state->pos++] = data; 127b14037f3SKlaus Jensen 128b14037f3SKlaus Jensen return 0; 129b14037f3SKlaus Jensen } 130b14037f3SKlaus Jensen 131b14037f3SKlaus Jensen static void i2c_echo_realize(DeviceState *dev, Error **errp) 132b14037f3SKlaus Jensen { 133b14037f3SKlaus Jensen I2CEchoState *state = I2C_ECHO(dev); 134b14037f3SKlaus Jensen BusState *bus = qdev_get_parent_bus(dev); 135b14037f3SKlaus Jensen 136b14037f3SKlaus Jensen state->bus = I2C_BUS(bus); 137b14037f3SKlaus Jensen state->bh = qemu_bh_new(i2c_echo_bh, state); 138b14037f3SKlaus Jensen 139b14037f3SKlaus Jensen return; 140b14037f3SKlaus Jensen } 141b14037f3SKlaus Jensen 142b14037f3SKlaus Jensen static void i2c_echo_class_init(ObjectClass *oc, void *data) 143b14037f3SKlaus Jensen { 144b14037f3SKlaus Jensen I2CSlaveClass *sc = I2C_SLAVE_CLASS(oc); 145b14037f3SKlaus Jensen DeviceClass *dc = DEVICE_CLASS(oc); 146b14037f3SKlaus Jensen 147b14037f3SKlaus Jensen dc->realize = i2c_echo_realize; 148b14037f3SKlaus Jensen 149b14037f3SKlaus Jensen sc->event = i2c_echo_event; 150b14037f3SKlaus Jensen sc->recv = i2c_echo_recv; 151b14037f3SKlaus Jensen sc->send = i2c_echo_send; 152b14037f3SKlaus Jensen } 153b14037f3SKlaus Jensen 154b14037f3SKlaus Jensen static const TypeInfo i2c_echo = { 155b14037f3SKlaus Jensen .name = TYPE_I2C_ECHO, 156b14037f3SKlaus Jensen .parent = TYPE_I2C_SLAVE, 157b14037f3SKlaus Jensen .instance_size = sizeof(I2CEchoState), 158b14037f3SKlaus Jensen .class_init = i2c_echo_class_init, 159b14037f3SKlaus Jensen }; 160b14037f3SKlaus Jensen 161b14037f3SKlaus Jensen static void register_types(void) 162b14037f3SKlaus Jensen { 163b14037f3SKlaus Jensen type_register_static(&i2c_echo); 164b14037f3SKlaus Jensen } 165b14037f3SKlaus Jensen 166b14037f3SKlaus Jensen type_init(register_types); 167