23
#include "qemu/osdep.h"
24
#include "qemu/module.h"
25
#include "qemu/timer.h"
27
#include "migration/vmstate.h"
28
#include "hw/i2c/i2c.h"
30
#include "qom/object.h"
32
#ifndef EXYNOS4_I2C_DEBUG
33
#define EXYNOS4_I2C_DEBUG 0
36
#define TYPE_EXYNOS4_I2C "exynos4210.i2c"
37
OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210I2CState, EXYNOS4_I2C)
40
#define EXYNOS4_I2C_MEM_SIZE 0x14
41
#define I2CCON_ADDR 0x00
42
#define I2CSTAT_ADDR 0x04
43
#define I2CADD_ADDR 0x08
44
#define I2CDS_ADDR 0x0c
45
#define I2CLC_ADDR 0x10
47
#define I2CCON_ACK_GEN (1 << 7)
48
#define I2CCON_INTRS_EN (1 << 5)
49
#define I2CCON_INT_PEND (1 << 4)
51
#define EXYNOS4_I2C_MODE(reg) (((reg) >> 6) & 3)
52
#define I2C_IN_MASTER_MODE(reg) (((reg) >> 6) & 2)
53
#define I2CMODE_MASTER_Rx 0x2
54
#define I2CMODE_MASTER_Tx 0x3
55
#define I2CSTAT_LAST_BIT (1 << 0)
56
#define I2CSTAT_OUTPUT_EN (1 << 4)
57
#define I2CSTAT_START_BUSY (1 << 5)
61
#define DPRINT(fmt, args...) \
62
do { fprintf(stderr, "QEMU I2C: "fmt, ## args); } while (0)
64
static const char *exynos4_i2c_get_regname(unsigned offset)
83
#define DPRINT(fmt, args...) do { } while (0)
86
struct Exynos4210I2CState {
87
SysBusDevice parent_obj;
101
static inline void exynos4210_i2c_raise_interrupt(Exynos4210I2CState *s)
103
if (s->i2ccon & I2CCON_INTRS_EN) {
104
s->i2ccon |= I2CCON_INT_PEND;
105
qemu_irq_raise(s->irq);
109
static void exynos4210_i2c_data_receive(void *opaque)
111
Exynos4210I2CState *s = (Exynos4210I2CState *)opaque;
113
s->i2cstat &= ~I2CSTAT_LAST_BIT;
115
s->i2cds = i2c_recv(s->bus);
116
exynos4210_i2c_raise_interrupt(s);
119
static void exynos4210_i2c_data_send(void *opaque)
121
Exynos4210I2CState *s = (Exynos4210I2CState *)opaque;
123
s->i2cstat &= ~I2CSTAT_LAST_BIT;
125
if (i2c_send(s->bus, s->i2cds) < 0 && (s->i2ccon & I2CCON_ACK_GEN)) {
126
s->i2cstat |= I2CSTAT_LAST_BIT;
128
exynos4210_i2c_raise_interrupt(s);
131
static uint64_t exynos4210_i2c_read(void *opaque, hwaddr offset,
134
Exynos4210I2CState *s = (Exynos4210I2CState *)opaque;
150
if (EXYNOS4_I2C_MODE(s->i2cstat) == I2CMODE_MASTER_Rx &&
151
(s->i2cstat & I2CSTAT_START_BUSY) &&
152
!(s->i2ccon & I2CCON_INT_PEND)) {
153
exynos4210_i2c_data_receive(s);
161
DPRINT("ERROR: Bad read offset 0x%x\n", (unsigned int)offset);
165
DPRINT("read %s [0x%02x] -> 0x%02x\n", exynos4_i2c_get_regname(offset),
166
(unsigned int)offset, value);
170
static void exynos4210_i2c_write(void *opaque, hwaddr offset,
171
uint64_t value, unsigned size)
173
Exynos4210I2CState *s = (Exynos4210I2CState *)opaque;
174
uint8_t v = value & 0xff;
176
DPRINT("write %s [0x%02x] <- 0x%02x\n", exynos4_i2c_get_regname(offset),
177
(unsigned int)offset, v);
181
s->i2ccon = (v & ~I2CCON_INT_PEND) | (s->i2ccon & I2CCON_INT_PEND);
182
if ((s->i2ccon & I2CCON_INT_PEND) && !(v & I2CCON_INT_PEND)) {
183
s->i2ccon &= ~I2CCON_INT_PEND;
184
qemu_irq_lower(s->irq);
185
if (!(s->i2ccon & I2CCON_INTRS_EN)) {
186
s->i2cstat &= ~I2CSTAT_START_BUSY;
189
if (s->i2cstat & I2CSTAT_START_BUSY) {
191
if (EXYNOS4_I2C_MODE(s->i2cstat) == I2CMODE_MASTER_Tx) {
192
exynos4210_i2c_data_send(s);
193
} else if (EXYNOS4_I2C_MODE(s->i2cstat) ==
195
exynos4210_i2c_data_receive(s);
198
s->i2ccon |= I2CCON_INT_PEND;
199
qemu_irq_raise(s->irq);
206
(s->i2cstat & I2CSTAT_START_BUSY) | (v & ~I2CSTAT_START_BUSY);
208
if (!(s->i2cstat & I2CSTAT_OUTPUT_EN)) {
209
s->i2cstat &= ~I2CSTAT_START_BUSY;
211
qemu_irq_lower(s->irq);
216
if (!I2C_IN_MASTER_MODE(s->i2cstat)) {
220
if (v & I2CSTAT_START_BUSY) {
221
s->i2cstat &= ~I2CSTAT_LAST_BIT;
222
s->i2cstat |= I2CSTAT_START_BUSY;
226
if (i2c_start_transfer(s->bus, s->i2cds >> 1, s->i2cds & 0x1) &&
227
(s->i2ccon & I2CCON_ACK_GEN)) {
228
s->i2cstat |= I2CSTAT_LAST_BIT;
229
} else if (EXYNOS4_I2C_MODE(s->i2cstat) == I2CMODE_MASTER_Rx) {
230
exynos4210_i2c_data_receive(s);
232
exynos4210_i2c_raise_interrupt(s);
234
i2c_end_transfer(s->bus);
235
if (!(s->i2ccon & I2CCON_INT_PEND)) {
236
s->i2cstat &= ~I2CSTAT_START_BUSY;
242
if ((s->i2cstat & I2CSTAT_OUTPUT_EN) == 0) {
247
if (s->i2cstat & I2CSTAT_OUTPUT_EN) {
250
if (EXYNOS4_I2C_MODE(s->i2cstat) == I2CMODE_MASTER_Tx &&
251
(s->i2cstat & I2CSTAT_START_BUSY) &&
252
!(s->i2ccon & I2CCON_INT_PEND)) {
253
exynos4210_i2c_data_send(s);
261
DPRINT("ERROR: Bad write offset 0x%x\n", (unsigned int)offset);
266
static const MemoryRegionOps exynos4210_i2c_ops = {
267
.read = exynos4210_i2c_read,
268
.write = exynos4210_i2c_write,
269
.endianness = DEVICE_NATIVE_ENDIAN,
272
static const VMStateDescription exynos4210_i2c_vmstate = {
273
.name = "exynos4210.i2c",
275
.minimum_version_id = 1,
276
.fields = (const VMStateField[]) {
277
VMSTATE_UINT8(i2ccon, Exynos4210I2CState),
278
VMSTATE_UINT8(i2cstat, Exynos4210I2CState),
279
VMSTATE_UINT8(i2cds, Exynos4210I2CState),
280
VMSTATE_UINT8(i2cadd, Exynos4210I2CState),
281
VMSTATE_UINT8(i2clc, Exynos4210I2CState),
282
VMSTATE_BOOL(scl_free, Exynos4210I2CState),
283
VMSTATE_END_OF_LIST()
287
static void exynos4210_i2c_reset(DeviceState *d)
289
Exynos4210I2CState *s = EXYNOS4_I2C(d);
299
static void exynos4210_i2c_init(Object *obj)
301
DeviceState *dev = DEVICE(obj);
302
Exynos4210I2CState *s = EXYNOS4_I2C(obj);
303
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
305
memory_region_init_io(&s->iomem, obj, &exynos4210_i2c_ops, s,
306
TYPE_EXYNOS4_I2C, EXYNOS4_I2C_MEM_SIZE);
307
sysbus_init_mmio(sbd, &s->iomem);
308
sysbus_init_irq(sbd, &s->irq);
309
s->bus = i2c_init_bus(dev, "i2c");
312
static void exynos4210_i2c_class_init(ObjectClass *klass, void *data)
314
DeviceClass *dc = DEVICE_CLASS(klass);
316
dc->vmsd = &exynos4210_i2c_vmstate;
317
dc->reset = exynos4210_i2c_reset;
320
static const TypeInfo exynos4210_i2c_type_info = {
321
.name = TYPE_EXYNOS4_I2C,
322
.parent = TYPE_SYS_BUS_DEVICE,
323
.instance_size = sizeof(Exynos4210I2CState),
324
.instance_init = exynos4210_i2c_init,
325
.class_init = exynos4210_i2c_class_init,
328
static void exynos4210_i2c_register_types(void)
330
type_register_static(&exynos4210_i2c_type_info);
333
type_init(exynos4210_i2c_register_types)