hw/arm/smmuv3: Refactor stage-1 PTW
[qemu/ar7.git] / hw / misc / i2c-echo.c
blob5705ab5d7349dbecbb4123afca9d0a0b95c52e8f
1 #include "qemu/osdep.h"
2 #include "qemu/timer.h"
3 #include "qemu/main-loop.h"
4 #include "block/aio.h"
5 #include "hw/i2c/i2c.h"
7 #define TYPE_I2C_ECHO "i2c-echo"
8 OBJECT_DECLARE_SIMPLE_TYPE(I2CEchoState, I2C_ECHO)
10 enum i2c_echo_state {
11 I2C_ECHO_STATE_IDLE,
12 I2C_ECHO_STATE_START_SEND,
13 I2C_ECHO_STATE_ACK,
16 typedef struct I2CEchoState {
17 I2CSlave parent_obj;
19 I2CBus *bus;
21 enum i2c_echo_state state;
22 QEMUBH *bh;
24 unsigned int pos;
25 uint8_t data[3];
26 } I2CEchoState;
28 static void i2c_echo_bh(void *opaque)
30 I2CEchoState *state = opaque;
32 switch (state->state) {
33 case I2C_ECHO_STATE_IDLE:
34 return;
36 case I2C_ECHO_STATE_START_SEND:
37 if (i2c_start_send_async(state->bus, state->data[0])) {
38 goto release_bus;
41 state->pos++;
42 state->state = I2C_ECHO_STATE_ACK;
43 return;
45 case I2C_ECHO_STATE_ACK:
46 if (state->pos > 2) {
47 break;
50 if (i2c_send_async(state->bus, state->data[state->pos++])) {
51 break;
54 return;
58 i2c_end_transfer(state->bus);
59 release_bus:
60 i2c_bus_release(state->bus);
62 state->state = I2C_ECHO_STATE_IDLE;
65 static int i2c_echo_event(I2CSlave *s, enum i2c_event event)
67 I2CEchoState *state = I2C_ECHO(s);
69 switch (event) {
70 case I2C_START_RECV:
71 state->pos = 0;
73 break;
75 case I2C_START_SEND:
76 state->pos = 0;
78 break;
80 case I2C_FINISH:
81 state->pos = 0;
82 state->state = I2C_ECHO_STATE_START_SEND;
83 i2c_bus_master(state->bus, state->bh);
85 break;
87 case I2C_NACK:
88 break;
90 default:
91 return -1;
94 return 0;
97 static uint8_t i2c_echo_recv(I2CSlave *s)
99 I2CEchoState *state = I2C_ECHO(s);
101 if (state->pos > 2) {
102 return 0xff;
105 return state->data[state->pos++];
108 static int i2c_echo_send(I2CSlave *s, uint8_t data)
110 I2CEchoState *state = I2C_ECHO(s);
112 if (state->pos > 2) {
113 return -1;
116 state->data[state->pos++] = data;
118 return 0;
121 static void i2c_echo_realize(DeviceState *dev, Error **errp)
123 I2CEchoState *state = I2C_ECHO(dev);
124 BusState *bus = qdev_get_parent_bus(dev);
126 state->bus = I2C_BUS(bus);
127 state->bh = qemu_bh_new(i2c_echo_bh, state);
129 return;
132 static void i2c_echo_class_init(ObjectClass *oc, void *data)
134 I2CSlaveClass *sc = I2C_SLAVE_CLASS(oc);
135 DeviceClass *dc = DEVICE_CLASS(oc);
137 dc->realize = i2c_echo_realize;
139 sc->event = i2c_echo_event;
140 sc->recv = i2c_echo_recv;
141 sc->send = i2c_echo_send;
144 static const TypeInfo i2c_echo = {
145 .name = TYPE_I2C_ECHO,
146 .parent = TYPE_I2C_SLAVE,
147 .instance_size = sizeof(I2CEchoState),
148 .class_init = i2c_echo_class_init,
151 static void register_types(void)
153 type_register_static(&i2c_echo);
156 type_init(register_types);