14
#include "qemu/osdep.h"
17
#include "hw/qdev-properties.h"
18
#include "hw/gpio/sifive_gpio.h"
19
#include "migration/vmstate.h"
22
static void update_output_irq(SIFIVEGPIOState *s)
27
pending = s->high_ip & s->high_ie;
28
pending |= s->low_ip & s->low_ie;
29
pending |= s->rise_ip & s->rise_ie;
30
pending |= s->fall_ip & s->fall_ie;
32
for (int i = 0; i < s->ngpio; i++) {
34
qemu_set_irq(s->irq[i], (pending & pin) != 0);
35
trace_sifive_gpio_update_output_irq(i, (pending & pin) != 0);
39
static void update_state(SIFIVEGPIOState *s)
42
bool prev_ival, in, in_mask, port, out_xor, pull, output_en, input_en,
43
rise_ip, fall_ip, low_ip, high_ip, oval, actual_value, ival;
45
for (i = 0; i < s->ngpio; i++) {
47
prev_ival = extract32(s->value, i, 1);
48
in = extract32(s->in, i, 1);
49
in_mask = extract32(s->in_mask, i, 1);
50
port = extract32(s->port, i, 1);
51
out_xor = extract32(s->out_xor, i, 1);
52
pull = extract32(s->pue, i, 1);
53
output_en = extract32(s->output_en, i, 1);
54
input_en = extract32(s->input_en, i, 1);
55
rise_ip = extract32(s->rise_ip, i, 1);
56
fall_ip = extract32(s->fall_ip, i, 1);
57
low_ip = extract32(s->low_ip, i, 1);
58
high_ip = extract32(s->high_ip, i, 1);
61
oval = output_en && (port ^ out_xor);
64
if (output_en && in_mask) {
65
qemu_log_mask(LOG_GUEST_ERROR, "GPIO pin %zu short circuited\n", i);
71
} else if (output_en) {
80
qemu_set_irq(s->output[i], actual_value);
84
ival = input_en && actual_value;
87
high_ip = high_ip || ival;
88
s->high_ip = deposit32(s->high_ip, i, 1, high_ip);
90
low_ip = low_ip || !ival;
91
s->low_ip = deposit32(s->low_ip, i, 1, low_ip);
93
rise_ip = rise_ip || (ival && !prev_ival);
94
s->rise_ip = deposit32(s->rise_ip, i, 1, rise_ip);
96
fall_ip = fall_ip || (!ival && prev_ival);
97
s->fall_ip = deposit32(s->fall_ip, i, 1, fall_ip);
100
s->value = deposit32(s->value, i, 1, ival);
102
update_output_irq(s);
105
static uint64_t sifive_gpio_read(void *opaque, hwaddr offset, unsigned int size)
107
SIFIVEGPIOState *s = SIFIVE_GPIO(opaque);
111
case SIFIVE_GPIO_REG_VALUE:
115
case SIFIVE_GPIO_REG_INPUT_EN:
119
case SIFIVE_GPIO_REG_OUTPUT_EN:
123
case SIFIVE_GPIO_REG_PORT:
127
case SIFIVE_GPIO_REG_PUE:
131
case SIFIVE_GPIO_REG_DS:
135
case SIFIVE_GPIO_REG_RISE_IE:
139
case SIFIVE_GPIO_REG_RISE_IP:
143
case SIFIVE_GPIO_REG_FALL_IE:
147
case SIFIVE_GPIO_REG_FALL_IP:
151
case SIFIVE_GPIO_REG_HIGH_IE:
155
case SIFIVE_GPIO_REG_HIGH_IP:
159
case SIFIVE_GPIO_REG_LOW_IE:
163
case SIFIVE_GPIO_REG_LOW_IP:
167
case SIFIVE_GPIO_REG_IOF_EN:
171
case SIFIVE_GPIO_REG_IOF_SEL:
175
case SIFIVE_GPIO_REG_OUT_XOR:
180
qemu_log_mask(LOG_GUEST_ERROR,
181
"%s: bad read offset 0x%" HWADDR_PRIx "\n",
185
trace_sifive_gpio_read(offset, r);
190
static void sifive_gpio_write(void *opaque, hwaddr offset,
191
uint64_t value, unsigned int size)
193
SIFIVEGPIOState *s = SIFIVE_GPIO(opaque);
195
trace_sifive_gpio_write(offset, value);
199
case SIFIVE_GPIO_REG_INPUT_EN:
203
case SIFIVE_GPIO_REG_OUTPUT_EN:
204
s->output_en = value;
207
case SIFIVE_GPIO_REG_PORT:
211
case SIFIVE_GPIO_REG_PUE:
215
case SIFIVE_GPIO_REG_DS:
219
case SIFIVE_GPIO_REG_RISE_IE:
223
case SIFIVE_GPIO_REG_RISE_IP:
225
s->rise_ip &= ~value;
228
case SIFIVE_GPIO_REG_FALL_IE:
232
case SIFIVE_GPIO_REG_FALL_IP:
234
s->fall_ip &= ~value;
237
case SIFIVE_GPIO_REG_HIGH_IE:
241
case SIFIVE_GPIO_REG_HIGH_IP:
243
s->high_ip &= ~value;
246
case SIFIVE_GPIO_REG_LOW_IE:
250
case SIFIVE_GPIO_REG_LOW_IP:
255
case SIFIVE_GPIO_REG_IOF_EN:
259
case SIFIVE_GPIO_REG_IOF_SEL:
263
case SIFIVE_GPIO_REG_OUT_XOR:
268
qemu_log_mask(LOG_GUEST_ERROR,
269
"%s: bad write offset 0x%" HWADDR_PRIx "\n",
276
static const MemoryRegionOps gpio_ops = {
277
.read = sifive_gpio_read,
278
.write = sifive_gpio_write,
279
.endianness = DEVICE_LITTLE_ENDIAN,
280
.impl.min_access_size = 4,
281
.impl.max_access_size = 4,
284
static void sifive_gpio_set(void *opaque, int line, int value)
286
SIFIVEGPIOState *s = SIFIVE_GPIO(opaque);
288
trace_sifive_gpio_set(line, value);
290
assert(line >= 0 && line < SIFIVE_GPIO_PINS);
292
s->in_mask = deposit32(s->in_mask, line, 1, value >= 0);
294
s->in = deposit32(s->in, line, 1, value != 0);
300
static void sifive_gpio_reset(DeviceState *dev)
302
SIFIVEGPIOState *s = SIFIVE_GPIO(dev);
325
static const VMStateDescription vmstate_sifive_gpio = {
326
.name = TYPE_SIFIVE_GPIO,
328
.minimum_version_id = 1,
329
.fields = (const VMStateField[]) {
330
VMSTATE_UINT32(value, SIFIVEGPIOState),
331
VMSTATE_UINT32(input_en, SIFIVEGPIOState),
332
VMSTATE_UINT32(output_en, SIFIVEGPIOState),
333
VMSTATE_UINT32(port, SIFIVEGPIOState),
334
VMSTATE_UINT32(pue, SIFIVEGPIOState),
335
VMSTATE_UINT32(rise_ie, SIFIVEGPIOState),
336
VMSTATE_UINT32(rise_ip, SIFIVEGPIOState),
337
VMSTATE_UINT32(fall_ie, SIFIVEGPIOState),
338
VMSTATE_UINT32(fall_ip, SIFIVEGPIOState),
339
VMSTATE_UINT32(high_ie, SIFIVEGPIOState),
340
VMSTATE_UINT32(high_ip, SIFIVEGPIOState),
341
VMSTATE_UINT32(low_ie, SIFIVEGPIOState),
342
VMSTATE_UINT32(low_ip, SIFIVEGPIOState),
343
VMSTATE_UINT32(iof_en, SIFIVEGPIOState),
344
VMSTATE_UINT32(iof_sel, SIFIVEGPIOState),
345
VMSTATE_UINT32(out_xor, SIFIVEGPIOState),
346
VMSTATE_UINT32(in, SIFIVEGPIOState),
347
VMSTATE_UINT32(in_mask, SIFIVEGPIOState),
348
VMSTATE_END_OF_LIST()
352
static Property sifive_gpio_properties[] = {
353
DEFINE_PROP_UINT32("ngpio", SIFIVEGPIOState, ngpio, SIFIVE_GPIO_PINS),
354
DEFINE_PROP_END_OF_LIST(),
357
static void sifive_gpio_realize(DeviceState *dev, Error **errp)
359
SIFIVEGPIOState *s = SIFIVE_GPIO(dev);
361
memory_region_init_io(&s->mmio, OBJECT(dev), &gpio_ops, s,
362
TYPE_SIFIVE_GPIO, SIFIVE_GPIO_SIZE);
364
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
366
for (int i = 0; i < s->ngpio; i++) {
367
sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]);
370
qdev_init_gpio_in(DEVICE(s), sifive_gpio_set, s->ngpio);
371
qdev_init_gpio_out(DEVICE(s), s->output, s->ngpio);
374
static void sifive_gpio_class_init(ObjectClass *klass, void *data)
376
DeviceClass *dc = DEVICE_CLASS(klass);
378
device_class_set_props(dc, sifive_gpio_properties);
379
dc->vmsd = &vmstate_sifive_gpio;
380
dc->realize = sifive_gpio_realize;
381
dc->reset = sifive_gpio_reset;
382
dc->desc = "SiFive GPIO";
385
static const TypeInfo sifive_gpio_info = {
386
.name = TYPE_SIFIVE_GPIO,
387
.parent = TYPE_SYS_BUS_DEVICE,
388
.instance_size = sizeof(SIFIVEGPIOState),
389
.class_init = sifive_gpio_class_init
392
static void sifive_gpio_register_types(void)
394
type_register_static(&sifive_gpio_info);
397
type_init(sifive_gpio_register_types)