blob: de5f5aacf540f05df3ac320f5c904e4f78772271 [file] [log] [blame]
Andrzej Zaborowski3ead03b2009-08-23 15:38:50 +02001/*
2 * Bit-Bang i2c emulation extracted from
3 * Marvell MV88W8618 / Freecom MusicPal emulation.
4 *
5 * Copyright (c) 2008 Jan Kiszka
6 *
Matthew Fernandez8e31bf32011-06-26 12:21:35 +10007 * This code is licensed under the GNU GPL v2.
Paolo Bonzini6b620ca2012-01-13 17:44:23 +01008 *
9 * Contributions after 2012-01-13 are licensed under the terms of the
10 * GNU GPL, version 2 or (at your option) any later version.
Andrzej Zaborowski3ead03b2009-08-23 15:38:50 +020011 */
Markus Armbruster0b8fa322019-05-23 16:35:07 +020012
Peter Maydell04308912016-01-26 18:17:30 +000013#include "qemu/osdep.h"
Markus Armbruster64552b62019-08-12 07:23:42 +020014#include "hw/irq.h"
BALATON Zoltand718b742019-06-20 12:55:23 +020015#include "hw/i2c/bitbang_i2c.h"
Paolo Bonzini83c9f4c2013-02-04 15:40:22 +010016#include "hw/sysbus.h"
Markus Armbruster0b8fa322019-05-23 16:35:07 +020017#include "qemu/module.h"
Eduardo Habkostdb1015e2020-09-03 16:43:22 -040018#include "qom/object.h"
Philippe Mathieu-Daudé1e5b1892023-01-11 09:50:15 +010019#include "trace.h"
Andrzej Zaborowski3ead03b2009-08-23 15:38:50 +020020
Paul Brook3cd035d2009-11-20 23:37:15 +000021
Philippe Mathieu-Daudé1e5b1892023-01-11 09:50:15 +010022/* bitbang_i2c_state enum to name */
23static const char * const sname[] = {
24#define NAME(e) [e] = stringify(e)
25 NAME(STOPPED),
26 [SENDING_BIT7] = "SENDING_BIT7 (START)",
27 NAME(SENDING_BIT6),
28 NAME(SENDING_BIT5),
29 NAME(SENDING_BIT4),
30 NAME(SENDING_BIT3),
31 NAME(SENDING_BIT2),
32 NAME(SENDING_BIT1),
33 NAME(SENDING_BIT0),
34 NAME(WAITING_FOR_ACK),
35 [RECEIVING_BIT7] = "RECEIVING_BIT7 (ACK)",
36 NAME(RECEIVING_BIT6),
37 NAME(RECEIVING_BIT5),
38 NAME(RECEIVING_BIT4),
39 NAME(RECEIVING_BIT3),
40 NAME(RECEIVING_BIT2),
41 NAME(RECEIVING_BIT1),
42 NAME(RECEIVING_BIT0),
43 NAME(SENDING_ACK),
44 NAME(SENT_NACK)
45#undef NAME
46};
47
Philippe Mathieu-Daudédc575b52023-01-11 09:50:14 +010048static void bitbang_i2c_set_state(bitbang_i2c_interface *i2c,
49 bitbang_i2c_state state)
50{
Philippe Mathieu-Daudé1e5b1892023-01-11 09:50:15 +010051 trace_bitbang_i2c_state(sname[i2c->state], sname[state]);
Philippe Mathieu-Daudédc575b52023-01-11 09:50:14 +010052 i2c->state = state;
53}
54
Andrzej Zaborowski3ead03b2009-08-23 15:38:50 +020055static void bitbang_i2c_enter_stop(bitbang_i2c_interface *i2c)
56{
57 if (i2c->current_addr >= 0)
58 i2c_end_transfer(i2c->bus);
59 i2c->current_addr = -1;
Philippe Mathieu-Daudédc575b52023-01-11 09:50:14 +010060 bitbang_i2c_set_state(i2c, STOPPED);
Andrzej Zaborowski3ead03b2009-08-23 15:38:50 +020061}
62
Paul Brook3cd035d2009-11-20 23:37:15 +000063/* Set device data pin. */
64static int bitbang_i2c_ret(bitbang_i2c_interface *i2c, int level)
Andrzej Zaborowski3ead03b2009-08-23 15:38:50 +020065{
Philippe Mathieu-Daudéc166e592023-01-11 09:50:16 +010066 trace_bitbang_i2c_data(i2c->last_clock, i2c->last_data,
67 i2c->device_out, level);
Paul Brook3cd035d2009-11-20 23:37:15 +000068 i2c->device_out = level;
Philippe Mathieu-Daudéc166e592023-01-11 09:50:16 +010069
Paul Brook3cd035d2009-11-20 23:37:15 +000070 return level & i2c->last_data;
Andrzej Zaborowski3ead03b2009-08-23 15:38:50 +020071}
72
BALATON Zoltan8ada2142023-07-28 02:45:24 +020073/* Leave device data pin unmodified. */
Paul Brook3cd035d2009-11-20 23:37:15 +000074static int bitbang_i2c_nop(bitbang_i2c_interface *i2c)
Andrzej Zaborowski3ead03b2009-08-23 15:38:50 +020075{
Paul Brook3cd035d2009-11-20 23:37:15 +000076 return bitbang_i2c_ret(i2c, i2c->device_out);
77}
78
79/* Returns data line level. */
80int bitbang_i2c_set(bitbang_i2c_interface *i2c, int line, int level)
81{
82 int data;
83
84 if (level != 0 && level != 1) {
85 abort();
86 }
87
88 if (line == BITBANG_I2C_SDA) {
89 if (level == i2c->last_data) {
90 return bitbang_i2c_nop(i2c);
91 }
92 i2c->last_data = level;
93 if (i2c->last_clock == 0) {
94 return bitbang_i2c_nop(i2c);
95 }
96 if (level == 0) {
Paul Brook3cd035d2009-11-20 23:37:15 +000097 /* START condition. */
Philippe Mathieu-Daudédc575b52023-01-11 09:50:14 +010098 bitbang_i2c_set_state(i2c, SENDING_BIT7);
Paul Brook3cd035d2009-11-20 23:37:15 +000099 i2c->current_addr = -1;
100 } else {
101 /* STOP condition. */
102 bitbang_i2c_enter_stop(i2c);
103 }
104 return bitbang_i2c_ret(i2c, 1);
105 }
106
107 data = i2c->last_data;
108 if (i2c->last_clock == level) {
109 return bitbang_i2c_nop(i2c);
110 }
111 i2c->last_clock = level;
112 if (level == 0) {
113 /* State is set/read at the start of the clock pulse.
114 release the data line at the end. */
115 return bitbang_i2c_ret(i2c, 1);
116 }
117 switch (i2c->state) {
118 case STOPPED:
Marcus Comstedt2eb9f242011-05-28 16:55:52 +0200119 case SENT_NACK:
Paul Brook3cd035d2009-11-20 23:37:15 +0000120 return bitbang_i2c_ret(i2c, 1);
121
122 case SENDING_BIT7 ... SENDING_BIT0:
123 i2c->buffer = (i2c->buffer << 1) | data;
124 /* will end up in WAITING_FOR_ACK */
Philippe Mathieu-Daudédc575b52023-01-11 09:50:14 +0100125 bitbang_i2c_set_state(i2c, i2c->state + 1);
Paul Brook3cd035d2009-11-20 23:37:15 +0000126 return bitbang_i2c_ret(i2c, 1);
127
128 case WAITING_FOR_ACK:
Peter Maydell9706e012016-10-24 19:12:29 +0100129 {
130 int ret;
131
Paul Brook3cd035d2009-11-20 23:37:15 +0000132 if (i2c->current_addr < 0) {
133 i2c->current_addr = i2c->buffer;
Philippe Mathieu-Daudéc166e592023-01-11 09:50:16 +0100134 trace_bitbang_i2c_addr(i2c->current_addr);
Peter Maydell9706e012016-10-24 19:12:29 +0100135 ret = i2c_start_transfer(i2c->bus, i2c->current_addr >> 1,
136 i2c->current_addr & 1);
Paul Brook3cd035d2009-11-20 23:37:15 +0000137 } else {
Philippe Mathieu-Daudéc166e592023-01-11 09:50:16 +0100138 trace_bitbang_i2c_send(i2c->buffer);
Peter Maydell9706e012016-10-24 19:12:29 +0100139 ret = i2c_send(i2c->bus, i2c->buffer);
140 }
141 if (ret) {
142 /* NACK (either addressing a nonexistent device, or the
143 * device we were sending to decided to NACK us).
144 */
Philippe Mathieu-Daudédc575b52023-01-11 09:50:14 +0100145 bitbang_i2c_set_state(i2c, SENT_NACK);
Peter Maydell9706e012016-10-24 19:12:29 +0100146 bitbang_i2c_enter_stop(i2c);
147 return bitbang_i2c_ret(i2c, 1);
Paul Brook3cd035d2009-11-20 23:37:15 +0000148 }
149 if (i2c->current_addr & 1) {
Philippe Mathieu-Daudédc575b52023-01-11 09:50:14 +0100150 bitbang_i2c_set_state(i2c, RECEIVING_BIT7);
Paul Brook3cd035d2009-11-20 23:37:15 +0000151 } else {
Philippe Mathieu-Daudédc575b52023-01-11 09:50:14 +0100152 bitbang_i2c_set_state(i2c, SENDING_BIT7);
Paul Brook3cd035d2009-11-20 23:37:15 +0000153 }
154 return bitbang_i2c_ret(i2c, 0);
Peter Maydell9706e012016-10-24 19:12:29 +0100155 }
Paul Brook3cd035d2009-11-20 23:37:15 +0000156 case RECEIVING_BIT7:
157 i2c->buffer = i2c_recv(i2c->bus);
Philippe Mathieu-Daudéc166e592023-01-11 09:50:16 +0100158 trace_bitbang_i2c_recv(i2c->buffer);
Paul Brook3cd035d2009-11-20 23:37:15 +0000159 /* Fall through... */
160 case RECEIVING_BIT6 ... RECEIVING_BIT0:
161 data = i2c->buffer >> 7;
162 /* will end up in SENDING_ACK */
Philippe Mathieu-Daudédc575b52023-01-11 09:50:14 +0100163 bitbang_i2c_set_state(i2c, i2c->state + 1);
Paul Brook3cd035d2009-11-20 23:37:15 +0000164 i2c->buffer <<= 1;
165 return bitbang_i2c_ret(i2c, data);
166
167 case SENDING_ACK:
Paul Brook3cd035d2009-11-20 23:37:15 +0000168 if (data != 0) {
Philippe Mathieu-Daudédc575b52023-01-11 09:50:14 +0100169 bitbang_i2c_set_state(i2c, SENT_NACK);
Paul Brook3cd035d2009-11-20 23:37:15 +0000170 i2c_nack(i2c->bus);
171 } else {
Philippe Mathieu-Daudédc575b52023-01-11 09:50:14 +0100172 bitbang_i2c_set_state(i2c, RECEIVING_BIT7);
Paul Brook3cd035d2009-11-20 23:37:15 +0000173 }
174 return bitbang_i2c_ret(i2c, 1);
175 }
176 abort();
177}
178
Peter Maydell41742922019-07-02 17:38:44 +0100179void bitbang_i2c_init(bitbang_i2c_interface *s, I2CBus *bus)
Paul Brook3cd035d2009-11-20 23:37:15 +0000180{
Paul Brook3cd035d2009-11-20 23:37:15 +0000181 s->bus = bus;
182 s->last_data = 1;
183 s->last_clock = 1;
184 s->device_out = 1;
Paul Brook3cd035d2009-11-20 23:37:15 +0000185}
186
187/* GPIO interface. */
Andreas Färbercc3c3b82013-07-26 18:13:46 +0200188
Eduardo Habkost80633962020-09-16 14:25:19 -0400189OBJECT_DECLARE_SIMPLE_TYPE(GPIOI2CState, GPIO_I2C)
Andreas Färbercc3c3b82013-07-26 18:13:46 +0200190
Eduardo Habkostdb1015e2020-09-03 16:43:22 -0400191struct GPIOI2CState {
Philippe Mathieu-Daudé2b9339d2023-01-11 09:50:13 +0100192 /*< private >*/
Andreas Färbercc3c3b82013-07-26 18:13:46 +0200193 SysBusDevice parent_obj;
Philippe Mathieu-Daudé2b9339d2023-01-11 09:50:13 +0100194 /*< public >*/
Andreas Färbercc3c3b82013-07-26 18:13:46 +0200195
Peter Maydell41742922019-07-02 17:38:44 +0100196 bitbang_i2c_interface bitbang;
Paul Brook3cd035d2009-11-20 23:37:15 +0000197 int last_level;
198 qemu_irq out;
Eduardo Habkostdb1015e2020-09-03 16:43:22 -0400199};
Paul Brook3cd035d2009-11-20 23:37:15 +0000200
201static void bitbang_i2c_gpio_set(void *opaque, int irq, int level)
202{
203 GPIOI2CState *s = opaque;
204
Peter Maydell41742922019-07-02 17:38:44 +0100205 level = bitbang_i2c_set(&s->bitbang, irq, level);
Paul Brook3cd035d2009-11-20 23:37:15 +0000206 if (level != s->last_level) {
207 s->last_level = level;
208 qemu_set_irq(s->out, level);
209 }
210}
211
xiaoqiang zhao00b2f752016-06-14 15:59:13 +0100212static void gpio_i2c_init(Object *obj)
Paul Brook3cd035d2009-11-20 23:37:15 +0000213{
xiaoqiang zhao00b2f752016-06-14 15:59:13 +0100214 DeviceState *dev = DEVICE(obj);
215 GPIOI2CState *s = GPIO_I2C(obj);
Andreas Färbera5c82852013-08-03 00:18:51 +0200216 I2CBus *bus;
Andrzej Zaborowski3ead03b2009-08-23 15:38:50 +0200217
Andreas Färbercc3c3b82013-07-26 18:13:46 +0200218 bus = i2c_init_bus(dev, "i2c");
Peter Maydell41742922019-07-02 17:38:44 +0100219 bitbang_i2c_init(&s->bitbang, bus);
Andrzej Zaborowski3ead03b2009-08-23 15:38:50 +0200220
Andreas Färbercc3c3b82013-07-26 18:13:46 +0200221 qdev_init_gpio_in(dev, bitbang_i2c_gpio_set, 2);
222 qdev_init_gpio_out(dev, &s->out, 1);
Andrzej Zaborowski3ead03b2009-08-23 15:38:50 +0200223}
224
Anthony Liguori999e12b2012-01-24 13:12:29 -0600225static void gpio_i2c_class_init(ObjectClass *klass, void *data)
226{
Anthony Liguori39bffca2011-12-07 21:34:16 -0600227 DeviceClass *dc = DEVICE_CLASS(klass);
Anthony Liguori999e12b2012-01-24 13:12:29 -0600228
Marcel Apfelbaum125ee0e2013-07-29 17:17:45 +0300229 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
Anthony Liguori39bffca2011-12-07 21:34:16 -0600230 dc->desc = "Virtual GPIO to I2C bridge";
Anthony Liguori999e12b2012-01-24 13:12:29 -0600231}
232
Andreas Färber8c43a6f2013-01-10 16:19:07 +0100233static const TypeInfo gpio_i2c_info = {
Andreas Färbercc3c3b82013-07-26 18:13:46 +0200234 .name = TYPE_GPIO_I2C,
Anthony Liguori39bffca2011-12-07 21:34:16 -0600235 .parent = TYPE_SYS_BUS_DEVICE,
236 .instance_size = sizeof(GPIOI2CState),
xiaoqiang zhao00b2f752016-06-14 15:59:13 +0100237 .instance_init = gpio_i2c_init,
Anthony Liguori39bffca2011-12-07 21:34:16 -0600238 .class_init = gpio_i2c_class_init,
Paul Brook3cd035d2009-11-20 23:37:15 +0000239};
240
Andreas Färber83f7d432012-02-09 15:20:55 +0100241static void bitbang_i2c_register_types(void)
Andrzej Zaborowski3ead03b2009-08-23 15:38:50 +0200242{
Anthony Liguori39bffca2011-12-07 21:34:16 -0600243 type_register_static(&gpio_i2c_info);
Andrzej Zaborowski3ead03b2009-08-23 15:38:50 +0200244}
245
Andreas Färber83f7d432012-02-09 15:20:55 +0100246type_init(bitbang_i2c_register_types)