19
#include "qemu/osdep.h"
21
#include "hw/gpio/stm32l4x5_gpio.h"
24
#include "hw/qdev-clock.h"
25
#include "hw/qdev-properties.h"
26
#include "qapi/visitor.h"
27
#include "qapi/error.h"
28
#include "migration/vmstate.h"
31
#define GPIO_MODER 0x00
32
#define GPIO_OTYPER 0x04
33
#define GPIO_OSPEEDR 0x08
34
#define GPIO_PUPDR 0x0C
45
#define RESERVED_BITS_MASK 0xFFFF0000
47
static void update_gpio_idr(Stm32l4x5GpioState *s);
49
static bool is_pull_up(Stm32l4x5GpioState *s, unsigned pin)
51
return extract32(s->pupdr, 2 * pin, 2) == 1;
54
static bool is_pull_down(Stm32l4x5GpioState *s, unsigned pin)
56
return extract32(s->pupdr, 2 * pin, 2) == 2;
59
static bool is_output(Stm32l4x5GpioState *s, unsigned pin)
61
return extract32(s->moder, 2 * pin, 2) == 1;
64
static bool is_open_drain(Stm32l4x5GpioState *s, unsigned pin)
66
return extract32(s->otyper, pin, 1) == 1;
69
static bool is_push_pull(Stm32l4x5GpioState *s, unsigned pin)
71
return extract32(s->otyper, pin, 1) == 0;
74
static void stm32l4x5_gpio_reset_hold(Object *obj, ResetType type)
76
Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
78
s->moder = s->moder_reset;
79
s->otyper = 0x00000000;
80
s->ospeedr = s->ospeedr_reset;
81
s->pupdr = s->pupdr_reset;
89
s->disconnected_pins = 0xFFFF;
90
s->pins_connected_high = 0x0000;
94
static void stm32l4x5_gpio_set(void *opaque, int line, int level)
96
Stm32l4x5GpioState *s = opaque;
102
if (is_output(s, line) && !(is_open_drain(s, line) && (level == 0))) {
103
qemu_log_mask(LOG_GUEST_ERROR, "Line %d can't be driven externally\n",
108
s->disconnected_pins &= ~(1 << line);
110
s->pins_connected_high |= (1 << line);
112
s->pins_connected_high &= ~(1 << line);
114
trace_stm32l4x5_gpio_pins(s->name, s->disconnected_pins,
115
s->pins_connected_high);
120
static void update_gpio_idr(Stm32l4x5GpioState *s)
122
uint32_t new_idr_mask = 0;
123
uint32_t new_idr = s->odr;
124
uint32_t old_idr = s->idr;
125
int new_pin_state, old_pin_state;
127
for (int i = 0; i < GPIO_NUM_PINS; i++) {
128
if (is_output(s, i)) {
129
if (is_push_pull(s, i)) {
130
new_idr_mask |= (1 << i);
131
} else if (!(s->odr & (1 << i))) {
133
new_idr_mask |= (1 << i);
135
} else if (!(s->disconnected_pins & (1 << i)) &&
136
!(s->pins_connected_high & (1 << i))) {
138
new_idr_mask |= (1 << i);
139
new_idr &= ~(1 << i);
141
} else if (is_pull_up(s, i)) {
142
new_idr_mask |= (1 << i);
143
} else if (is_pull_down(s, i)) {
144
new_idr_mask |= (1 << i);
145
new_idr &= ~(1 << i);
153
} else if (!(s->disconnected_pins & (1 << i))) {
154
if (s->pins_connected_high & (1 << i)) {
156
new_idr_mask |= (1 << i);
160
new_idr_mask |= (1 << i);
161
new_idr &= ~(1 << i);
165
if (is_pull_up(s, i)) {
167
new_idr_mask |= (1 << i);
169
} else if (is_pull_down(s, i)) {
171
new_idr_mask |= (1 << i);
172
new_idr &= ~(1 << i);
182
s->idr = (old_idr & ~new_idr_mask) | (new_idr & new_idr_mask);
183
trace_stm32l4x5_gpio_update_idr(s->name, old_idr, s->idr);
185
for (int i = 0; i < GPIO_NUM_PINS; i++) {
186
if (new_idr_mask & (1 << i)) {
187
new_pin_state = (new_idr & (1 << i)) > 0;
188
old_pin_state = (old_idr & (1 << i)) > 0;
189
if (new_pin_state > old_pin_state) {
190
qemu_irq_raise(s->pin[i]);
191
} else if (new_pin_state < old_pin_state) {
192
qemu_irq_lower(s->pin[i]);
203
static uint32_t get_gpio_pinmask_to_disconnect(Stm32l4x5GpioState *s)
205
uint32_t pins_to_disconnect = 0;
206
for (int i = 0; i < GPIO_NUM_PINS; i++) {
208
if (!(s->disconnected_pins & (1 << i)) && is_output(s, i)) {
210
if (is_push_pull(s, i) || s->pins_connected_high & (1 << i)) {
211
pins_to_disconnect |= (1 << i);
212
qemu_log_mask(LOG_GUEST_ERROR,
213
"Line %d can't be driven externally\n",
218
return pins_to_disconnect;
224
static void disconnect_gpio_pins(Stm32l4x5GpioState *s, uint16_t lines)
226
s->disconnected_pins |= lines;
227
trace_stm32l4x5_gpio_pins(s->name, s->disconnected_pins,
228
s->pins_connected_high);
232
static void disconnected_pins_set(Object *obj, Visitor *v,
233
const char *name, void *opaque, Error **errp)
235
Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
237
if (!visit_type_uint16(v, name, &value, errp)) {
240
disconnect_gpio_pins(s, value);
243
static void disconnected_pins_get(Object *obj, Visitor *v,
244
const char *name, void *opaque, Error **errp)
246
visit_type_uint16(v, name, (uint16_t *)opaque, errp);
249
static void clock_freq_get(Object *obj, Visitor *v,
250
const char *name, void *opaque, Error **errp)
252
Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
253
uint32_t clock_freq_hz = clock_get_hz(s->clk);
254
visit_type_uint32(v, name, &clock_freq_hz, errp);
257
static void stm32l4x5_gpio_write(void *opaque, hwaddr addr,
258
uint64_t val64, unsigned int size)
260
Stm32l4x5GpioState *s = opaque;
262
uint32_t value = val64;
263
trace_stm32l4x5_gpio_write(s->name, addr, val64);
268
disconnect_gpio_pins(s, get_gpio_pinmask_to_disconnect(s));
269
qemu_log_mask(LOG_UNIMP,
270
"%s: Analog and AF modes aren't supported\n\
271
Analog and AF mode behave like input mode\n",
275
s->otyper = value & ~RESERVED_BITS_MASK;
276
disconnect_gpio_pins(s, get_gpio_pinmask_to_disconnect(s));
279
qemu_log_mask(LOG_UNIMP,
280
"%s: Changing I/O output speed isn't supported\n\
281
I/O speed is already maximal\n",
290
qemu_log_mask(LOG_UNIMP,
291
"%s: GPIO->IDR is read-only\n",
295
s->odr = value & ~RESERVED_BITS_MASK;
299
uint32_t bits_to_reset = (value & RESERVED_BITS_MASK) >> GPIO_NUM_PINS;
300
uint32_t bits_to_set = value & ~RESERVED_BITS_MASK;
302
s->odr &= ~bits_to_reset;
303
s->odr |= bits_to_set;
308
qemu_log_mask(LOG_UNIMP,
309
"%s: Locking port bits configuration isn't supported\n",
311
s->lckr = value & ~RESERVED_BITS_MASK;
314
qemu_log_mask(LOG_UNIMP,
315
"%s: Alternate functions aren't supported\n",
320
qemu_log_mask(LOG_UNIMP,
321
"%s: Alternate functions aren't supported\n",
326
uint32_t bits_to_reset = value & ~RESERVED_BITS_MASK;
327
s->odr &= ~bits_to_reset;
332
qemu_log_mask(LOG_UNIMP,
333
"%s: ADC function isn't supported\n",
335
s->ascr = value & ~RESERVED_BITS_MASK;
338
qemu_log_mask(LOG_GUEST_ERROR,
339
"%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
343
static uint64_t stm32l4x5_gpio_read(void *opaque, hwaddr addr,
346
Stm32l4x5GpioState *s = opaque;
348
trace_stm32l4x5_gpio_read(s->name, addr);
376
qemu_log_mask(LOG_GUEST_ERROR,
377
"%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
382
static const MemoryRegionOps stm32l4x5_gpio_ops = {
383
.read = stm32l4x5_gpio_read,
384
.write = stm32l4x5_gpio_write,
385
.endianness = DEVICE_NATIVE_ENDIAN,
387
.min_access_size = 4,
388
.max_access_size = 4,
392
.min_access_size = 4,
393
.max_access_size = 4,
398
static void stm32l4x5_gpio_init(Object *obj)
400
Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
402
memory_region_init_io(&s->mmio, obj, &stm32l4x5_gpio_ops, s,
403
TYPE_STM32L4X5_GPIO, 0x400);
405
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
407
qdev_init_gpio_out(DEVICE(obj), s->pin, GPIO_NUM_PINS);
408
qdev_init_gpio_in(DEVICE(obj), stm32l4x5_gpio_set, GPIO_NUM_PINS);
410
s->clk = qdev_init_clock_in(DEVICE(s), "clk", NULL, s, 0);
412
object_property_add(obj, "disconnected-pins", "uint16",
413
disconnected_pins_get, disconnected_pins_set,
414
NULL, &s->disconnected_pins);
415
object_property_add(obj, "clock-freq-hz", "uint32",
416
clock_freq_get, NULL, NULL, NULL);
419
static void stm32l4x5_gpio_realize(DeviceState *dev, Error **errp)
421
Stm32l4x5GpioState *s = STM32L4X5_GPIO(dev);
422
if (!clock_has_source(s->clk)) {
423
error_setg(errp, "GPIO: clk input must be connected");
428
static const VMStateDescription vmstate_stm32l4x5_gpio = {
429
.name = TYPE_STM32L4X5_GPIO,
431
.minimum_version_id = 2,
432
.fields = (VMStateField[]){
433
VMSTATE_UINT32(moder, Stm32l4x5GpioState),
434
VMSTATE_UINT32(otyper, Stm32l4x5GpioState),
435
VMSTATE_UINT32(ospeedr, Stm32l4x5GpioState),
436
VMSTATE_UINT32(pupdr, Stm32l4x5GpioState),
437
VMSTATE_UINT32(idr, Stm32l4x5GpioState),
438
VMSTATE_UINT32(odr, Stm32l4x5GpioState),
439
VMSTATE_UINT32(lckr, Stm32l4x5GpioState),
440
VMSTATE_UINT32(afrl, Stm32l4x5GpioState),
441
VMSTATE_UINT32(afrh, Stm32l4x5GpioState),
442
VMSTATE_UINT32(ascr, Stm32l4x5GpioState),
443
VMSTATE_UINT16(disconnected_pins, Stm32l4x5GpioState),
444
VMSTATE_UINT16(pins_connected_high, Stm32l4x5GpioState),
445
VMSTATE_CLOCK(clk, Stm32l4x5GpioState),
446
VMSTATE_END_OF_LIST()
450
static Property stm32l4x5_gpio_properties[] = {
451
DEFINE_PROP_STRING("name", Stm32l4x5GpioState, name),
452
DEFINE_PROP_UINT32("mode-reset", Stm32l4x5GpioState, moder_reset, 0),
453
DEFINE_PROP_UINT32("ospeed-reset", Stm32l4x5GpioState, ospeedr_reset, 0),
454
DEFINE_PROP_UINT32("pupd-reset", Stm32l4x5GpioState, pupdr_reset, 0),
455
DEFINE_PROP_END_OF_LIST(),
458
static void stm32l4x5_gpio_class_init(ObjectClass *klass, void *data)
460
DeviceClass *dc = DEVICE_CLASS(klass);
461
ResettableClass *rc = RESETTABLE_CLASS(klass);
463
device_class_set_props(dc, stm32l4x5_gpio_properties);
464
dc->vmsd = &vmstate_stm32l4x5_gpio;
465
dc->realize = stm32l4x5_gpio_realize;
466
rc->phases.hold = stm32l4x5_gpio_reset_hold;
469
static const TypeInfo stm32l4x5_gpio_types[] = {
471
.name = TYPE_STM32L4X5_GPIO,
472
.parent = TYPE_SYS_BUS_DEVICE,
473
.instance_size = sizeof(Stm32l4x5GpioState),
474
.instance_init = stm32l4x5_gpio_init,
475
.class_init = stm32l4x5_gpio_class_init,
479
DEFINE_TYPES(stm32l4x5_gpio_types)