2 * SiFive System-on-Chip general purpose input/output register definition
4 * Copyright 2019 AdaCore
6 * Base on nrf51_gpio.c:
8 * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
10 * This code is licensed under the GPL version 2 or later. See
11 * the COPYING file in the top-level directory.
14 #include "qemu/osdep.h"
17 #include "hw/riscv/sifive_gpio.h"
18 #include "migration/vmstate.h"
21 static void update_output_irq(SIFIVEGPIOState
*s
)
26 pending
= s
->high_ip
& s
->high_ie
;
27 pending
|= s
->low_ip
& s
->low_ie
;
28 pending
|= s
->rise_ip
& s
->rise_ie
;
29 pending
|= s
->fall_ip
& s
->fall_ie
;
31 for (int i
= 0; i
< SIFIVE_GPIO_PINS
; i
++) {
33 qemu_set_irq(s
->irq
[i
], (pending
& pin
) != 0);
34 trace_sifive_gpio_update_output_irq(i
, (pending
& pin
) != 0);
38 static void update_state(SIFIVEGPIOState
*s
)
41 bool prev_ival
, in
, in_mask
, port
, out_xor
, pull
, output_en
, input_en
,
42 rise_ip
, fall_ip
, low_ip
, high_ip
, oval
, actual_value
, ival
;
44 for (i
= 0; i
< SIFIVE_GPIO_PINS
; i
++) {
46 prev_ival
= extract32(s
->value
, i
, 1);
47 in
= extract32(s
->in
, i
, 1);
48 in_mask
= extract32(s
->in_mask
, i
, 1);
49 port
= extract32(s
->port
, i
, 1);
50 out_xor
= extract32(s
->out_xor
, i
, 1);
51 pull
= extract32(s
->pue
, i
, 1);
52 output_en
= extract32(s
->output_en
, i
, 1);
53 input_en
= extract32(s
->input_en
, i
, 1);
54 rise_ip
= extract32(s
->rise_ip
, i
, 1);
55 fall_ip
= extract32(s
->fall_ip
, i
, 1);
56 low_ip
= extract32(s
->low_ip
, i
, 1);
57 high_ip
= extract32(s
->high_ip
, i
, 1);
59 /* Output value (IOF not supported) */
60 oval
= output_en
&& (port
^ out_xor
);
62 /* Pin both driven externally and internally */
63 if (output_en
&& in_mask
) {
64 qemu_log_mask(LOG_GUEST_ERROR
, "GPIO pin %zu short circuited\n", i
);
68 /* The pin is driven by external device */
70 } else if (output_en
) {
71 /* The pin is driven by internal circuit */
74 /* Floating? Apply pull-up resistor */
78 qemu_set_irq(s
->output
[i
], actual_value
);
81 ival
= input_en
&& actual_value
;
84 high_ip
= high_ip
|| ival
;
85 s
->high_ip
= deposit32(s
->high_ip
, i
, 1, high_ip
);
87 low_ip
= low_ip
|| !ival
;
88 s
->low_ip
= deposit32(s
->low_ip
, i
, 1, low_ip
);
90 rise_ip
= rise_ip
|| (ival
&& !prev_ival
);
91 s
->rise_ip
= deposit32(s
->rise_ip
, i
, 1, rise_ip
);
93 fall_ip
= fall_ip
|| (!ival
&& prev_ival
);
94 s
->fall_ip
= deposit32(s
->fall_ip
, i
, 1, fall_ip
);
97 s
->value
= deposit32(s
->value
, i
, 1, ival
);
102 static uint64_t sifive_gpio_read(void *opaque
, hwaddr offset
, unsigned int size
)
104 SIFIVEGPIOState
*s
= SIFIVE_GPIO(opaque
);
108 case SIFIVE_GPIO_REG_VALUE
:
112 case SIFIVE_GPIO_REG_INPUT_EN
:
116 case SIFIVE_GPIO_REG_OUTPUT_EN
:
120 case SIFIVE_GPIO_REG_PORT
:
124 case SIFIVE_GPIO_REG_PUE
:
128 case SIFIVE_GPIO_REG_DS
:
132 case SIFIVE_GPIO_REG_RISE_IE
:
136 case SIFIVE_GPIO_REG_RISE_IP
:
140 case SIFIVE_GPIO_REG_FALL_IE
:
144 case SIFIVE_GPIO_REG_FALL_IP
:
148 case SIFIVE_GPIO_REG_HIGH_IE
:
152 case SIFIVE_GPIO_REG_HIGH_IP
:
156 case SIFIVE_GPIO_REG_LOW_IE
:
160 case SIFIVE_GPIO_REG_LOW_IP
:
164 case SIFIVE_GPIO_REG_IOF_EN
:
168 case SIFIVE_GPIO_REG_IOF_SEL
:
172 case SIFIVE_GPIO_REG_OUT_XOR
:
177 qemu_log_mask(LOG_GUEST_ERROR
,
178 "%s: bad read offset 0x%" HWADDR_PRIx
"\n",
182 trace_sifive_gpio_read(offset
, r
);
187 static void sifive_gpio_write(void *opaque
, hwaddr offset
,
188 uint64_t value
, unsigned int size
)
190 SIFIVEGPIOState
*s
= SIFIVE_GPIO(opaque
);
192 trace_sifive_gpio_write(offset
, value
);
196 case SIFIVE_GPIO_REG_INPUT_EN
:
200 case SIFIVE_GPIO_REG_OUTPUT_EN
:
201 s
->output_en
= value
;
204 case SIFIVE_GPIO_REG_PORT
:
208 case SIFIVE_GPIO_REG_PUE
:
212 case SIFIVE_GPIO_REG_DS
:
216 case SIFIVE_GPIO_REG_RISE_IE
:
220 case SIFIVE_GPIO_REG_RISE_IP
:
221 /* Write 1 to clear */
222 s
->rise_ip
&= ~value
;
225 case SIFIVE_GPIO_REG_FALL_IE
:
229 case SIFIVE_GPIO_REG_FALL_IP
:
230 /* Write 1 to clear */
231 s
->fall_ip
&= ~value
;
234 case SIFIVE_GPIO_REG_HIGH_IE
:
238 case SIFIVE_GPIO_REG_HIGH_IP
:
239 /* Write 1 to clear */
240 s
->high_ip
&= ~value
;
243 case SIFIVE_GPIO_REG_LOW_IE
:
247 case SIFIVE_GPIO_REG_LOW_IP
:
248 /* Write 1 to clear */
252 case SIFIVE_GPIO_REG_IOF_EN
:
256 case SIFIVE_GPIO_REG_IOF_SEL
:
260 case SIFIVE_GPIO_REG_OUT_XOR
:
265 qemu_log_mask(LOG_GUEST_ERROR
,
266 "%s: bad write offset 0x%" HWADDR_PRIx
"\n",
273 static const MemoryRegionOps gpio_ops
= {
274 .read
= sifive_gpio_read
,
275 .write
= sifive_gpio_write
,
276 .endianness
= DEVICE_LITTLE_ENDIAN
,
277 .impl
.min_access_size
= 4,
278 .impl
.max_access_size
= 4,
281 static void sifive_gpio_set(void *opaque
, int line
, int value
)
283 SIFIVEGPIOState
*s
= SIFIVE_GPIO(opaque
);
285 trace_sifive_gpio_set(line
, value
);
287 assert(line
>= 0 && line
< SIFIVE_GPIO_PINS
);
289 s
->in_mask
= deposit32(s
->in_mask
, line
, 1, value
>= 0);
291 s
->in
= deposit32(s
->in
, line
, 1, value
!= 0);
297 static void sifive_gpio_reset(DeviceState
*dev
)
299 SIFIVEGPIOState
*s
= SIFIVE_GPIO(dev
);
322 static const VMStateDescription vmstate_sifive_gpio
= {
323 .name
= TYPE_SIFIVE_GPIO
,
325 .minimum_version_id
= 1,
326 .fields
= (VMStateField
[]) {
327 VMSTATE_UINT32(value
, SIFIVEGPIOState
),
328 VMSTATE_UINT32(input_en
, SIFIVEGPIOState
),
329 VMSTATE_UINT32(output_en
, SIFIVEGPIOState
),
330 VMSTATE_UINT32(port
, SIFIVEGPIOState
),
331 VMSTATE_UINT32(pue
, SIFIVEGPIOState
),
332 VMSTATE_UINT32(rise_ie
, SIFIVEGPIOState
),
333 VMSTATE_UINT32(rise_ip
, SIFIVEGPIOState
),
334 VMSTATE_UINT32(fall_ie
, SIFIVEGPIOState
),
335 VMSTATE_UINT32(fall_ip
, SIFIVEGPIOState
),
336 VMSTATE_UINT32(high_ie
, SIFIVEGPIOState
),
337 VMSTATE_UINT32(high_ip
, SIFIVEGPIOState
),
338 VMSTATE_UINT32(low_ie
, SIFIVEGPIOState
),
339 VMSTATE_UINT32(low_ip
, SIFIVEGPIOState
),
340 VMSTATE_UINT32(iof_en
, SIFIVEGPIOState
),
341 VMSTATE_UINT32(iof_sel
, SIFIVEGPIOState
),
342 VMSTATE_UINT32(out_xor
, SIFIVEGPIOState
),
343 VMSTATE_UINT32(in
, SIFIVEGPIOState
),
344 VMSTATE_UINT32(in_mask
, SIFIVEGPIOState
),
345 VMSTATE_END_OF_LIST()
349 static void sifive_gpio_init(Object
*obj
)
351 SIFIVEGPIOState
*s
= SIFIVE_GPIO(obj
);
353 memory_region_init_io(&s
->mmio
, obj
, &gpio_ops
, s
,
354 TYPE_SIFIVE_GPIO
, SIFIVE_GPIO_SIZE
);
355 sysbus_init_mmio(SYS_BUS_DEVICE(obj
), &s
->mmio
);
357 for (int i
= 0; i
< SIFIVE_GPIO_PINS
; i
++) {
358 sysbus_init_irq(SYS_BUS_DEVICE(obj
), &s
->irq
[i
]);
361 qdev_init_gpio_in(DEVICE(s
), sifive_gpio_set
, SIFIVE_GPIO_PINS
);
362 qdev_init_gpio_out(DEVICE(s
), s
->output
, SIFIVE_GPIO_PINS
);
365 static void sifive_gpio_class_init(ObjectClass
*klass
, void *data
)
367 DeviceClass
*dc
= DEVICE_CLASS(klass
);
369 dc
->vmsd
= &vmstate_sifive_gpio
;
370 dc
->reset
= sifive_gpio_reset
;
371 dc
->desc
= "SiFive GPIO";
374 static const TypeInfo sifive_gpio_info
= {
375 .name
= TYPE_SIFIVE_GPIO
,
376 .parent
= TYPE_SYS_BUS_DEVICE
,
377 .instance_size
= sizeof(SIFIVEGPIOState
),
378 .instance_init
= sifive_gpio_init
,
379 .class_init
= sifive_gpio_class_init
382 static void sifive_gpio_register_types(void)
384 type_register_static(&sifive_gpio_info
);
387 type_init(sifive_gpio_register_types
)