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
)
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
< SIFIVE_GPIO_PINS
; 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
< SIFIVE_GPIO_PINS
; 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 */
79 qemu_set_irq(s
->output
[i
], actual_value
);
82 ival
= input_en
&& actual_value
;
85 high_ip
= high_ip
|| ival
;
86 s
->high_ip
= deposit32(s
->high_ip
, i
, 1, high_ip
);
88 low_ip
= low_ip
|| !ival
;
89 s
->low_ip
= deposit32(s
->low_ip
, i
, 1, low_ip
);
91 rise_ip
= rise_ip
|| (ival
&& !prev_ival
);
92 s
->rise_ip
= deposit32(s
->rise_ip
, i
, 1, rise_ip
);
94 fall_ip
= fall_ip
|| (!ival
&& prev_ival
);
95 s
->fall_ip
= deposit32(s
->fall_ip
, i
, 1, fall_ip
);
98 s
->value
= deposit32(s
->value
, i
, 1, ival
);
100 update_output_irq(s
);
103 static uint64_t sifive_gpio_read(void *opaque
, hwaddr offset
, unsigned int size
)
105 SIFIVEGPIOState
*s
= SIFIVE_GPIO(opaque
);
109 case SIFIVE_GPIO_REG_VALUE
:
113 case SIFIVE_GPIO_REG_INPUT_EN
:
117 case SIFIVE_GPIO_REG_OUTPUT_EN
:
121 case SIFIVE_GPIO_REG_PORT
:
125 case SIFIVE_GPIO_REG_PUE
:
129 case SIFIVE_GPIO_REG_DS
:
133 case SIFIVE_GPIO_REG_RISE_IE
:
137 case SIFIVE_GPIO_REG_RISE_IP
:
141 case SIFIVE_GPIO_REG_FALL_IE
:
145 case SIFIVE_GPIO_REG_FALL_IP
:
149 case SIFIVE_GPIO_REG_HIGH_IE
:
153 case SIFIVE_GPIO_REG_HIGH_IP
:
157 case SIFIVE_GPIO_REG_LOW_IE
:
161 case SIFIVE_GPIO_REG_LOW_IP
:
165 case SIFIVE_GPIO_REG_IOF_EN
:
169 case SIFIVE_GPIO_REG_IOF_SEL
:
173 case SIFIVE_GPIO_REG_OUT_XOR
:
178 qemu_log_mask(LOG_GUEST_ERROR
,
179 "%s: bad read offset 0x%" HWADDR_PRIx
"\n",
183 trace_sifive_gpio_read(offset
, r
);
188 static void sifive_gpio_write(void *opaque
, hwaddr offset
,
189 uint64_t value
, unsigned int size
)
191 SIFIVEGPIOState
*s
= SIFIVE_GPIO(opaque
);
193 trace_sifive_gpio_write(offset
, value
);
197 case SIFIVE_GPIO_REG_INPUT_EN
:
201 case SIFIVE_GPIO_REG_OUTPUT_EN
:
202 s
->output_en
= value
;
205 case SIFIVE_GPIO_REG_PORT
:
209 case SIFIVE_GPIO_REG_PUE
:
213 case SIFIVE_GPIO_REG_DS
:
217 case SIFIVE_GPIO_REG_RISE_IE
:
221 case SIFIVE_GPIO_REG_RISE_IP
:
222 /* Write 1 to clear */
223 s
->rise_ip
&= ~value
;
226 case SIFIVE_GPIO_REG_FALL_IE
:
230 case SIFIVE_GPIO_REG_FALL_IP
:
231 /* Write 1 to clear */
232 s
->fall_ip
&= ~value
;
235 case SIFIVE_GPIO_REG_HIGH_IE
:
239 case SIFIVE_GPIO_REG_HIGH_IP
:
240 /* Write 1 to clear */
241 s
->high_ip
&= ~value
;
244 case SIFIVE_GPIO_REG_LOW_IE
:
248 case SIFIVE_GPIO_REG_LOW_IP
:
249 /* Write 1 to clear */
253 case SIFIVE_GPIO_REG_IOF_EN
:
257 case SIFIVE_GPIO_REG_IOF_SEL
:
261 case SIFIVE_GPIO_REG_OUT_XOR
:
266 qemu_log_mask(LOG_GUEST_ERROR
,
267 "%s: bad write offset 0x%" HWADDR_PRIx
"\n",
274 static const MemoryRegionOps gpio_ops
= {
275 .read
= sifive_gpio_read
,
276 .write
= sifive_gpio_write
,
277 .endianness
= DEVICE_LITTLE_ENDIAN
,
278 .impl
.min_access_size
= 4,
279 .impl
.max_access_size
= 4,
282 static void sifive_gpio_set(void *opaque
, int line
, int value
)
284 SIFIVEGPIOState
*s
= SIFIVE_GPIO(opaque
);
286 trace_sifive_gpio_set(line
, value
);
288 assert(line
>= 0 && line
< SIFIVE_GPIO_PINS
);
290 s
->in_mask
= deposit32(s
->in_mask
, line
, 1, value
>= 0);
292 s
->in
= deposit32(s
->in
, line
, 1, value
!= 0);
298 static void sifive_gpio_reset(DeviceState
*dev
)
300 SIFIVEGPIOState
*s
= SIFIVE_GPIO(dev
);
324 static const VMStateDescription vmstate_sifive_gpio
= {
325 .name
= TYPE_SIFIVE_GPIO
,
327 .minimum_version_id
= 1,
328 .fields
= (VMStateField
[]) {
329 VMSTATE_UINT32(value
, SIFIVEGPIOState
),
330 VMSTATE_UINT32(input_en
, SIFIVEGPIOState
),
331 VMSTATE_UINT32(output_en
, SIFIVEGPIOState
),
332 VMSTATE_UINT32(port
, SIFIVEGPIOState
),
333 VMSTATE_UINT32(pue
, SIFIVEGPIOState
),
334 VMSTATE_UINT32(rise_ie
, SIFIVEGPIOState
),
335 VMSTATE_UINT32(rise_ip
, SIFIVEGPIOState
),
336 VMSTATE_UINT32(fall_ie
, SIFIVEGPIOState
),
337 VMSTATE_UINT32(fall_ip
, SIFIVEGPIOState
),
338 VMSTATE_UINT32(high_ie
, SIFIVEGPIOState
),
339 VMSTATE_UINT32(high_ip
, SIFIVEGPIOState
),
340 VMSTATE_UINT32(low_ie
, SIFIVEGPIOState
),
341 VMSTATE_UINT32(low_ip
, SIFIVEGPIOState
),
342 VMSTATE_UINT32(iof_en
, SIFIVEGPIOState
),
343 VMSTATE_UINT32(iof_sel
, SIFIVEGPIOState
),
344 VMSTATE_UINT32(out_xor
, SIFIVEGPIOState
),
345 VMSTATE_UINT32(in
, SIFIVEGPIOState
),
346 VMSTATE_UINT32(in_mask
, SIFIVEGPIOState
),
347 VMSTATE_END_OF_LIST()
351 static void sifive_gpio_init(Object
*obj
)
353 SIFIVEGPIOState
*s
= SIFIVE_GPIO(obj
);
355 memory_region_init_io(&s
->mmio
, obj
, &gpio_ops
, s
,
356 TYPE_SIFIVE_GPIO
, SIFIVE_GPIO_SIZE
);
357 sysbus_init_mmio(SYS_BUS_DEVICE(obj
), &s
->mmio
);
360 for (int i
= 0; i
< SIFIVE_GPIO_PINS
; i
++) {
361 sysbus_init_irq(SYS_BUS_DEVICE(obj
), &s
->irq
[i
]);
364 qdev_init_gpio_in(DEVICE(s
), sifive_gpio_set
, SIFIVE_GPIO_PINS
);
365 qdev_init_gpio_out(DEVICE(s
), s
->output
, SIFIVE_GPIO_PINS
);
368 static void sifive_gpio_class_init(ObjectClass
*klass
, void *data
)
370 DeviceClass
*dc
= DEVICE_CLASS(klass
);
372 dc
->vmsd
= &vmstate_sifive_gpio
;
373 dc
->reset
= sifive_gpio_reset
;
374 dc
->desc
= "sifive GPIO";
377 static const TypeInfo sifive_gpio_info
= {
378 .name
= TYPE_SIFIVE_GPIO
,
379 .parent
= TYPE_SYS_BUS_DEVICE
,
380 .instance_size
= sizeof(SIFIVEGPIOState
),
381 .instance_init
= sifive_gpio_init
,
382 .class_init
= sifive_gpio_class_init
385 static void sifive_gpio_register_types(void)
387 type_register_static(&sifive_gpio_info
);
390 type_init(sifive_gpio_register_types
)