2 * Microbit stub for Nordic Semiconductor nRF51 SoC Two-Wire Interface
3 * http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.1.pdf
5 * This is a microbit-specific stub for the TWI controller on the nRF51 SoC.
6 * We don't emulate I2C devices but the firmware probes the
7 * accelerometer/magnetometer on startup and panics if they are not found.
8 * Therefore we stub out the probing.
10 * In the future this file could evolve into a full nRF51 TWI controller
13 * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
14 * Copyright 2019 Red Hat, Inc.
16 * This code is licensed under the GPL version 2 or later. See
17 * the COPYING file in the top-level directory.
20 #include "qemu/osdep.h"
22 #include "qemu/module.h"
23 #include "hw/i2c/microbit_i2c.h"
24 #include "migration/vmstate.h"
26 static const uint32_t twi_read_sequence
[] = {0x5A, 0x5A, 0x40};
28 static uint64_t microbit_i2c_read(void *opaque
, hwaddr addr
, unsigned int size
)
30 MicrobitI2CState
*s
= opaque
;
34 case NRF51_TWI_EVENT_STOPPED
:
37 case NRF51_TWI_EVENT_RXDREADY
:
40 case NRF51_TWI_EVENT_TXDSENT
:
43 case NRF51_TWI_REG_RXD
:
44 data
= twi_read_sequence
[s
->read_idx
];
45 if (s
->read_idx
< G_N_ELEMENTS(twi_read_sequence
)) {
50 data
= s
->regs
[addr
/ sizeof(s
->regs
[0])];
54 qemu_log_mask(LOG_UNIMP
, "%s: 0x%" HWADDR_PRIx
" [%u] = %" PRIx32
"\n",
55 __func__
, addr
, size
, (uint32_t)data
);
61 static void microbit_i2c_write(void *opaque
, hwaddr addr
, uint64_t data
,
64 MicrobitI2CState
*s
= opaque
;
66 qemu_log_mask(LOG_UNIMP
, "%s: 0x%" HWADDR_PRIx
" <- 0x%" PRIx64
" [%u]\n",
67 __func__
, addr
, data
, size
);
68 s
->regs
[addr
/ sizeof(s
->regs
[0])] = data
;
71 static const MemoryRegionOps microbit_i2c_ops
= {
72 .read
= microbit_i2c_read
,
73 .write
= microbit_i2c_write
,
74 .endianness
= DEVICE_LITTLE_ENDIAN
,
75 .impl
.min_access_size
= 4,
76 .impl
.max_access_size
= 4,
79 static const VMStateDescription microbit_i2c_vmstate
= {
80 .name
= TYPE_MICROBIT_I2C
,
82 .minimum_version_id
= 1,
83 .fields
= (VMStateField
[]) {
84 VMSTATE_UINT32_ARRAY(regs
, MicrobitI2CState
, MICROBIT_I2C_NREGS
),
85 VMSTATE_UINT32(read_idx
, MicrobitI2CState
),
89 static void microbit_i2c_reset(DeviceState
*dev
)
91 MicrobitI2CState
*s
= MICROBIT_I2C(dev
);
93 memset(s
->regs
, 0, sizeof(s
->regs
));
97 static void microbit_i2c_realize(DeviceState
*dev
, Error
**errp
)
99 SysBusDevice
*sbd
= SYS_BUS_DEVICE(dev
);
100 MicrobitI2CState
*s
= MICROBIT_I2C(dev
);
102 memory_region_init_io(&s
->iomem
, OBJECT(s
), µbit_i2c_ops
, s
,
103 "microbit.twi", NRF51_PERIPHERAL_SIZE
);
104 sysbus_init_mmio(sbd
, &s
->iomem
);
107 static void microbit_i2c_class_init(ObjectClass
*klass
, void *data
)
109 DeviceClass
*dc
= DEVICE_CLASS(klass
);
111 dc
->vmsd
= µbit_i2c_vmstate
;
112 dc
->reset
= microbit_i2c_reset
;
113 dc
->realize
= microbit_i2c_realize
;
114 dc
->desc
= "Microbit I2C controller";
117 static const TypeInfo microbit_i2c_info
= {
118 .name
= TYPE_MICROBIT_I2C
,
119 .parent
= TYPE_SYS_BUS_DEVICE
,
120 .instance_size
= sizeof(MicrobitI2CState
),
121 .class_init
= microbit_i2c_class_init
,
124 static void microbit_i2c_register_types(void)
126 type_register_static(µbit_i2c_info
);
129 type_init(microbit_i2c_register_types
)