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/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);
60 /* Output value (IOF not supported) */
61 oval
= output_en
&& (port
^ out_xor
);
63 /* Pin both driven externally and internally */
64 if (output_en
&& in_mask
) {
65 qemu_log_mask(LOG_GUEST_ERROR
, "GPIO pin %zu short circuited\n", i
);
69 /* The pin is driven by external device */
71 } else if (output_en
) {
72 /* The pin is driven by internal circuit */
75 /* Floating? Apply pull-up resistor */
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
:
224 /* Write 1 to clear */
225 s
->rise_ip
&= ~value
;
228 case SIFIVE_GPIO_REG_FALL_IE
:
232 case SIFIVE_GPIO_REG_FALL_IP
:
233 /* Write 1 to clear */
234 s
->fall_ip
&= ~value
;
237 case SIFIVE_GPIO_REG_HIGH_IE
:
241 case SIFIVE_GPIO_REG_HIGH_IP
:
242 /* Write 1 to clear */
243 s
->high_ip
&= ~value
;
246 case SIFIVE_GPIO_REG_LOW_IE
:
250 case SIFIVE_GPIO_REG_LOW_IP
:
251 /* Write 1 to clear */
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 device_class_set_legacy_reset(dc
, 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
)