From: Bin Meng Date: Thu, 3 Sep 2020 10:40:15 +0000 (+0800) Subject: hw/riscv: Move sifive_gpio model to hw/gpio X-Git-Tag: pull-xen-20201020~76^2~8 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=4921a0ce86cecd03e6918832673db79de62e6fe1;p=people%2Faperard%2Fqemu-dm.git hw/riscv: Move sifive_gpio model to hw/gpio This is an effort to clean up the hw/riscv directory. Ideally it should only contain the RISC-V SoC / machine codes plus generic codes. Let's move sifive_gpio model to hw/gpio directory. Note this also removes the trace-events in the hw/riscv directory, since gpio is the only supported trace target in that directory. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Message-Id: <1599129623-68957-5-git-send-email-bmeng.cn@gmail.com> Signed-off-by: Alistair Francis --- diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig index 9227cb5598..b6fdaa2586 100644 --- a/hw/gpio/Kconfig +++ b/hw/gpio/Kconfig @@ -7,3 +7,6 @@ config PL061 config GPIO_KEY bool + +config SIFIVE_GPIO + bool diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build index 6bcdfa6b1d..86cae9a0f3 100644 --- a/hw/gpio/meson.build +++ b/hw/gpio/meson.build @@ -10,3 +10,4 @@ softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_gpio.c')) softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_gpio.c')) softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_gpio.c')) softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c')) +softmmu_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c')) diff --git a/hw/gpio/sifive_gpio.c b/hw/gpio/sifive_gpio.c new file mode 100644 index 0000000000..78bf29e996 --- /dev/null +++ b/hw/gpio/sifive_gpio.c @@ -0,0 +1,397 @@ +/* + * SiFive System-on-Chip general purpose input/output register definition + * + * Copyright 2019 AdaCore + * + * Base on nrf51_gpio.c: + * + * Copyright 2018 Steffen Görtz + * + * This code is licensed under the GPL version 2 or later. See + * the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/gpio/sifive_gpio.h" +#include "migration/vmstate.h" +#include "trace.h" + +static void update_output_irq(SIFIVEGPIOState *s) +{ + uint32_t pending; + uint32_t pin; + + pending = s->high_ip & s->high_ie; + pending |= s->low_ip & s->low_ie; + pending |= s->rise_ip & s->rise_ie; + pending |= s->fall_ip & s->fall_ie; + + for (int i = 0; i < s->ngpio; i++) { + pin = 1 << i; + qemu_set_irq(s->irq[i], (pending & pin) != 0); + trace_sifive_gpio_update_output_irq(i, (pending & pin) != 0); + } +} + +static void update_state(SIFIVEGPIOState *s) +{ + size_t i; + bool prev_ival, in, in_mask, port, out_xor, pull, output_en, input_en, + rise_ip, fall_ip, low_ip, high_ip, oval, actual_value, ival; + + for (i = 0; i < s->ngpio; i++) { + + prev_ival = extract32(s->value, i, 1); + in = extract32(s->in, i, 1); + in_mask = extract32(s->in_mask, i, 1); + port = extract32(s->port, i, 1); + out_xor = extract32(s->out_xor, i, 1); + pull = extract32(s->pue, i, 1); + output_en = extract32(s->output_en, i, 1); + input_en = extract32(s->input_en, i, 1); + rise_ip = extract32(s->rise_ip, i, 1); + fall_ip = extract32(s->fall_ip, i, 1); + low_ip = extract32(s->low_ip, i, 1); + high_ip = extract32(s->high_ip, i, 1); + + /* Output value (IOF not supported) */ + oval = output_en && (port ^ out_xor); + + /* Pin both driven externally and internally */ + if (output_en && in_mask) { + qemu_log_mask(LOG_GUEST_ERROR, "GPIO pin %zu short circuited\n", i); + } + + if (in_mask) { + /* The pin is driven by external device */ + actual_value = in; + } else if (output_en) { + /* The pin is driven by internal circuit */ + actual_value = oval; + } else { + /* Floating? Apply pull-up resistor */ + actual_value = pull; + } + + if (output_en) { + qemu_set_irq(s->output[i], actual_value); + } + + /* Input value */ + ival = input_en && actual_value; + + /* Interrupts */ + high_ip = high_ip || ival; + s->high_ip = deposit32(s->high_ip, i, 1, high_ip); + + low_ip = low_ip || !ival; + s->low_ip = deposit32(s->low_ip, i, 1, low_ip); + + rise_ip = rise_ip || (ival && !prev_ival); + s->rise_ip = deposit32(s->rise_ip, i, 1, rise_ip); + + fall_ip = fall_ip || (!ival && prev_ival); + s->fall_ip = deposit32(s->fall_ip, i, 1, fall_ip); + + /* Update value */ + s->value = deposit32(s->value, i, 1, ival); + } + update_output_irq(s); +} + +static uint64_t sifive_gpio_read(void *opaque, hwaddr offset, unsigned int size) +{ + SIFIVEGPIOState *s = SIFIVE_GPIO(opaque); + uint64_t r = 0; + + switch (offset) { + case SIFIVE_GPIO_REG_VALUE: + r = s->value; + break; + + case SIFIVE_GPIO_REG_INPUT_EN: + r = s->input_en; + break; + + case SIFIVE_GPIO_REG_OUTPUT_EN: + r = s->output_en; + break; + + case SIFIVE_GPIO_REG_PORT: + r = s->port; + break; + + case SIFIVE_GPIO_REG_PUE: + r = s->pue; + break; + + case SIFIVE_GPIO_REG_DS: + r = s->ds; + break; + + case SIFIVE_GPIO_REG_RISE_IE: + r = s->rise_ie; + break; + + case SIFIVE_GPIO_REG_RISE_IP: + r = s->rise_ip; + break; + + case SIFIVE_GPIO_REG_FALL_IE: + r = s->fall_ie; + break; + + case SIFIVE_GPIO_REG_FALL_IP: + r = s->fall_ip; + break; + + case SIFIVE_GPIO_REG_HIGH_IE: + r = s->high_ie; + break; + + case SIFIVE_GPIO_REG_HIGH_IP: + r = s->high_ip; + break; + + case SIFIVE_GPIO_REG_LOW_IE: + r = s->low_ie; + break; + + case SIFIVE_GPIO_REG_LOW_IP: + r = s->low_ip; + break; + + case SIFIVE_GPIO_REG_IOF_EN: + r = s->iof_en; + break; + + case SIFIVE_GPIO_REG_IOF_SEL: + r = s->iof_sel; + break; + + case SIFIVE_GPIO_REG_OUT_XOR: + r = s->out_xor; + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: bad read offset 0x%" HWADDR_PRIx "\n", + __func__, offset); + } + + trace_sifive_gpio_read(offset, r); + + return r; +} + +static void sifive_gpio_write(void *opaque, hwaddr offset, + uint64_t value, unsigned int size) +{ + SIFIVEGPIOState *s = SIFIVE_GPIO(opaque); + + trace_sifive_gpio_write(offset, value); + + switch (offset) { + + case SIFIVE_GPIO_REG_INPUT_EN: + s->input_en = value; + break; + + case SIFIVE_GPIO_REG_OUTPUT_EN: + s->output_en = value; + break; + + case SIFIVE_GPIO_REG_PORT: + s->port = value; + break; + + case SIFIVE_GPIO_REG_PUE: + s->pue = value; + break; + + case SIFIVE_GPIO_REG_DS: + s->ds = value; + break; + + case SIFIVE_GPIO_REG_RISE_IE: + s->rise_ie = value; + break; + + case SIFIVE_GPIO_REG_RISE_IP: + /* Write 1 to clear */ + s->rise_ip &= ~value; + break; + + case SIFIVE_GPIO_REG_FALL_IE: + s->fall_ie = value; + break; + + case SIFIVE_GPIO_REG_FALL_IP: + /* Write 1 to clear */ + s->fall_ip &= ~value; + break; + + case SIFIVE_GPIO_REG_HIGH_IE: + s->high_ie = value; + break; + + case SIFIVE_GPIO_REG_HIGH_IP: + /* Write 1 to clear */ + s->high_ip &= ~value; + break; + + case SIFIVE_GPIO_REG_LOW_IE: + s->low_ie = value; + break; + + case SIFIVE_GPIO_REG_LOW_IP: + /* Write 1 to clear */ + s->low_ip &= ~value; + break; + + case SIFIVE_GPIO_REG_IOF_EN: + s->iof_en = value; + break; + + case SIFIVE_GPIO_REG_IOF_SEL: + s->iof_sel = value; + break; + + case SIFIVE_GPIO_REG_OUT_XOR: + s->out_xor = value; + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: bad write offset 0x%" HWADDR_PRIx "\n", + __func__, offset); + } + + update_state(s); +} + +static const MemoryRegionOps gpio_ops = { + .read = sifive_gpio_read, + .write = sifive_gpio_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl.min_access_size = 4, + .impl.max_access_size = 4, +}; + +static void sifive_gpio_set(void *opaque, int line, int value) +{ + SIFIVEGPIOState *s = SIFIVE_GPIO(opaque); + + trace_sifive_gpio_set(line, value); + + assert(line >= 0 && line < SIFIVE_GPIO_PINS); + + s->in_mask = deposit32(s->in_mask, line, 1, value >= 0); + if (value >= 0) { + s->in = deposit32(s->in, line, 1, value != 0); + } + + update_state(s); +} + +static void sifive_gpio_reset(DeviceState *dev) +{ + SIFIVEGPIOState *s = SIFIVE_GPIO(dev); + + s->value = 0; + s->input_en = 0; + s->output_en = 0; + s->port = 0; + s->pue = 0; + s->ds = 0; + s->rise_ie = 0; + s->rise_ip = 0; + s->fall_ie = 0; + s->fall_ip = 0; + s->high_ie = 0; + s->high_ip = 0; + s->low_ie = 0; + s->low_ip = 0; + s->iof_en = 0; + s->iof_sel = 0; + s->out_xor = 0; + s->in = 0; + s->in_mask = 0; +} + +static const VMStateDescription vmstate_sifive_gpio = { + .name = TYPE_SIFIVE_GPIO, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(value, SIFIVEGPIOState), + VMSTATE_UINT32(input_en, SIFIVEGPIOState), + VMSTATE_UINT32(output_en, SIFIVEGPIOState), + VMSTATE_UINT32(port, SIFIVEGPIOState), + VMSTATE_UINT32(pue, SIFIVEGPIOState), + VMSTATE_UINT32(rise_ie, SIFIVEGPIOState), + VMSTATE_UINT32(rise_ip, SIFIVEGPIOState), + VMSTATE_UINT32(fall_ie, SIFIVEGPIOState), + VMSTATE_UINT32(fall_ip, SIFIVEGPIOState), + VMSTATE_UINT32(high_ie, SIFIVEGPIOState), + VMSTATE_UINT32(high_ip, SIFIVEGPIOState), + VMSTATE_UINT32(low_ie, SIFIVEGPIOState), + VMSTATE_UINT32(low_ip, SIFIVEGPIOState), + VMSTATE_UINT32(iof_en, SIFIVEGPIOState), + VMSTATE_UINT32(iof_sel, SIFIVEGPIOState), + VMSTATE_UINT32(out_xor, SIFIVEGPIOState), + VMSTATE_UINT32(in, SIFIVEGPIOState), + VMSTATE_UINT32(in_mask, SIFIVEGPIOState), + VMSTATE_END_OF_LIST() + } +}; + +static Property sifive_gpio_properties[] = { + DEFINE_PROP_UINT32("ngpio", SIFIVEGPIOState, ngpio, SIFIVE_GPIO_PINS), + DEFINE_PROP_END_OF_LIST(), +}; + +static void sifive_gpio_realize(DeviceState *dev, Error **errp) +{ + SIFIVEGPIOState *s = SIFIVE_GPIO(dev); + + memory_region_init_io(&s->mmio, OBJECT(dev), &gpio_ops, s, + TYPE_SIFIVE_GPIO, SIFIVE_GPIO_SIZE); + + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); + + for (int i = 0; i < s->ngpio; i++) { + sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]); + } + + qdev_init_gpio_in(DEVICE(s), sifive_gpio_set, s->ngpio); + qdev_init_gpio_out(DEVICE(s), s->output, s->ngpio); +} + +static void sifive_gpio_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + device_class_set_props(dc, sifive_gpio_properties); + dc->vmsd = &vmstate_sifive_gpio; + dc->realize = sifive_gpio_realize; + dc->reset = sifive_gpio_reset; + dc->desc = "SiFive GPIO"; +} + +static const TypeInfo sifive_gpio_info = { + .name = TYPE_SIFIVE_GPIO, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(SIFIVEGPIOState), + .class_init = sifive_gpio_class_init +}; + +static void sifive_gpio_register_types(void) +{ + type_register_static(&sifive_gpio_info); +} + +type_init(sifive_gpio_register_types) diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events index c1271fdfb2..6e3f048745 100644 --- a/hw/gpio/trace-events +++ b/hw/gpio/trace-events @@ -5,3 +5,9 @@ nrf51_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" PR nrf51_gpio_write(uint64_t offset, uint64_t value) "offset 0x%" PRIx64 " value 0x%" PRIx64 nrf51_gpio_set(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64 nrf51_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64 + +# sifive_gpio.c +sifive_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" PRIx64 +sifive_gpio_write(uint64_t offset, uint64_t value) "offset 0x%" PRIx64 " value 0x%" PRIx64 +sifive_gpio_set(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64 +sifive_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64 diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index 76eaf77a80..5a8335bfec 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -15,6 +15,7 @@ config SIFIVE_E bool select HART select SIFIVE + select SIFIVE_GPIO select SIFIVE_E_PRCI select UNIMP @@ -23,6 +24,7 @@ config SIFIVE_U select CADENCE select HART select SIFIVE + select SIFIVE_GPIO select SIFIVE_PDMA select SIFIVE_U_OTP select SIFIVE_U_PRCI diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build index 74a73b2a44..90003793d4 100644 --- a/hw/riscv/meson.build +++ b/hw/riscv/meson.build @@ -5,7 +5,6 @@ riscv_ss.add(when: 'CONFIG_HART', if_true: files('riscv_hart.c')) riscv_ss.add(when: 'CONFIG_OPENTITAN', if_true: files('opentitan.c')) riscv_ss.add(when: 'CONFIG_RISCV_VIRT', if_true: files('virt.c')) riscv_ss.add(when: 'CONFIG_SIFIVE', if_true: files('sifive_clint.c')) -riscv_ss.add(when: 'CONFIG_SIFIVE', if_true: files('sifive_gpio.c')) riscv_ss.add(when: 'CONFIG_SIFIVE', if_true: files('sifive_plic.c')) riscv_ss.add(when: 'CONFIG_SIFIVE', if_true: files('sifive_test.c')) riscv_ss.add(when: 'CONFIG_SIFIVE', if_true: files('sifive_uart.c')) diff --git a/hw/riscv/sifive_gpio.c b/hw/riscv/sifive_gpio.c deleted file mode 100644 index aac6b44cac..0000000000 --- a/hw/riscv/sifive_gpio.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - * SiFive System-on-Chip general purpose input/output register definition - * - * Copyright 2019 AdaCore - * - * Base on nrf51_gpio.c: - * - * Copyright 2018 Steffen Görtz - * - * This code is licensed under the GPL version 2 or later. See - * the COPYING file in the top-level directory. - */ - -#include "qemu/osdep.h" -#include "qemu/log.h" -#include "hw/irq.h" -#include "hw/qdev-properties.h" -#include "hw/riscv/sifive_gpio.h" -#include "migration/vmstate.h" -#include "trace.h" - -static void update_output_irq(SIFIVEGPIOState *s) -{ - uint32_t pending; - uint32_t pin; - - pending = s->high_ip & s->high_ie; - pending |= s->low_ip & s->low_ie; - pending |= s->rise_ip & s->rise_ie; - pending |= s->fall_ip & s->fall_ie; - - for (int i = 0; i < s->ngpio; i++) { - pin = 1 << i; - qemu_set_irq(s->irq[i], (pending & pin) != 0); - trace_sifive_gpio_update_output_irq(i, (pending & pin) != 0); - } -} - -static void update_state(SIFIVEGPIOState *s) -{ - size_t i; - bool prev_ival, in, in_mask, port, out_xor, pull, output_en, input_en, - rise_ip, fall_ip, low_ip, high_ip, oval, actual_value, ival; - - for (i = 0; i < s->ngpio; i++) { - - prev_ival = extract32(s->value, i, 1); - in = extract32(s->in, i, 1); - in_mask = extract32(s->in_mask, i, 1); - port = extract32(s->port, i, 1); - out_xor = extract32(s->out_xor, i, 1); - pull = extract32(s->pue, i, 1); - output_en = extract32(s->output_en, i, 1); - input_en = extract32(s->input_en, i, 1); - rise_ip = extract32(s->rise_ip, i, 1); - fall_ip = extract32(s->fall_ip, i, 1); - low_ip = extract32(s->low_ip, i, 1); - high_ip = extract32(s->high_ip, i, 1); - - /* Output value (IOF not supported) */ - oval = output_en && (port ^ out_xor); - - /* Pin both driven externally and internally */ - if (output_en && in_mask) { - qemu_log_mask(LOG_GUEST_ERROR, "GPIO pin %zu short circuited\n", i); - } - - if (in_mask) { - /* The pin is driven by external device */ - actual_value = in; - } else if (output_en) { - /* The pin is driven by internal circuit */ - actual_value = oval; - } else { - /* Floating? Apply pull-up resistor */ - actual_value = pull; - } - - if (output_en) { - qemu_set_irq(s->output[i], actual_value); - } - - /* Input value */ - ival = input_en && actual_value; - - /* Interrupts */ - high_ip = high_ip || ival; - s->high_ip = deposit32(s->high_ip, i, 1, high_ip); - - low_ip = low_ip || !ival; - s->low_ip = deposit32(s->low_ip, i, 1, low_ip); - - rise_ip = rise_ip || (ival && !prev_ival); - s->rise_ip = deposit32(s->rise_ip, i, 1, rise_ip); - - fall_ip = fall_ip || (!ival && prev_ival); - s->fall_ip = deposit32(s->fall_ip, i, 1, fall_ip); - - /* Update value */ - s->value = deposit32(s->value, i, 1, ival); - } - update_output_irq(s); -} - -static uint64_t sifive_gpio_read(void *opaque, hwaddr offset, unsigned int size) -{ - SIFIVEGPIOState *s = SIFIVE_GPIO(opaque); - uint64_t r = 0; - - switch (offset) { - case SIFIVE_GPIO_REG_VALUE: - r = s->value; - break; - - case SIFIVE_GPIO_REG_INPUT_EN: - r = s->input_en; - break; - - case SIFIVE_GPIO_REG_OUTPUT_EN: - r = s->output_en; - break; - - case SIFIVE_GPIO_REG_PORT: - r = s->port; - break; - - case SIFIVE_GPIO_REG_PUE: - r = s->pue; - break; - - case SIFIVE_GPIO_REG_DS: - r = s->ds; - break; - - case SIFIVE_GPIO_REG_RISE_IE: - r = s->rise_ie; - break; - - case SIFIVE_GPIO_REG_RISE_IP: - r = s->rise_ip; - break; - - case SIFIVE_GPIO_REG_FALL_IE: - r = s->fall_ie; - break; - - case SIFIVE_GPIO_REG_FALL_IP: - r = s->fall_ip; - break; - - case SIFIVE_GPIO_REG_HIGH_IE: - r = s->high_ie; - break; - - case SIFIVE_GPIO_REG_HIGH_IP: - r = s->high_ip; - break; - - case SIFIVE_GPIO_REG_LOW_IE: - r = s->low_ie; - break; - - case SIFIVE_GPIO_REG_LOW_IP: - r = s->low_ip; - break; - - case SIFIVE_GPIO_REG_IOF_EN: - r = s->iof_en; - break; - - case SIFIVE_GPIO_REG_IOF_SEL: - r = s->iof_sel; - break; - - case SIFIVE_GPIO_REG_OUT_XOR: - r = s->out_xor; - break; - - default: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: bad read offset 0x%" HWADDR_PRIx "\n", - __func__, offset); - } - - trace_sifive_gpio_read(offset, r); - - return r; -} - -static void sifive_gpio_write(void *opaque, hwaddr offset, - uint64_t value, unsigned int size) -{ - SIFIVEGPIOState *s = SIFIVE_GPIO(opaque); - - trace_sifive_gpio_write(offset, value); - - switch (offset) { - - case SIFIVE_GPIO_REG_INPUT_EN: - s->input_en = value; - break; - - case SIFIVE_GPIO_REG_OUTPUT_EN: - s->output_en = value; - break; - - case SIFIVE_GPIO_REG_PORT: - s->port = value; - break; - - case SIFIVE_GPIO_REG_PUE: - s->pue = value; - break; - - case SIFIVE_GPIO_REG_DS: - s->ds = value; - break; - - case SIFIVE_GPIO_REG_RISE_IE: - s->rise_ie = value; - break; - - case SIFIVE_GPIO_REG_RISE_IP: - /* Write 1 to clear */ - s->rise_ip &= ~value; - break; - - case SIFIVE_GPIO_REG_FALL_IE: - s->fall_ie = value; - break; - - case SIFIVE_GPIO_REG_FALL_IP: - /* Write 1 to clear */ - s->fall_ip &= ~value; - break; - - case SIFIVE_GPIO_REG_HIGH_IE: - s->high_ie = value; - break; - - case SIFIVE_GPIO_REG_HIGH_IP: - /* Write 1 to clear */ - s->high_ip &= ~value; - break; - - case SIFIVE_GPIO_REG_LOW_IE: - s->low_ie = value; - break; - - case SIFIVE_GPIO_REG_LOW_IP: - /* Write 1 to clear */ - s->low_ip &= ~value; - break; - - case SIFIVE_GPIO_REG_IOF_EN: - s->iof_en = value; - break; - - case SIFIVE_GPIO_REG_IOF_SEL: - s->iof_sel = value; - break; - - case SIFIVE_GPIO_REG_OUT_XOR: - s->out_xor = value; - break; - - default: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: bad write offset 0x%" HWADDR_PRIx "\n", - __func__, offset); - } - - update_state(s); -} - -static const MemoryRegionOps gpio_ops = { - .read = sifive_gpio_read, - .write = sifive_gpio_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .impl.min_access_size = 4, - .impl.max_access_size = 4, -}; - -static void sifive_gpio_set(void *opaque, int line, int value) -{ - SIFIVEGPIOState *s = SIFIVE_GPIO(opaque); - - trace_sifive_gpio_set(line, value); - - assert(line >= 0 && line < SIFIVE_GPIO_PINS); - - s->in_mask = deposit32(s->in_mask, line, 1, value >= 0); - if (value >= 0) { - s->in = deposit32(s->in, line, 1, value != 0); - } - - update_state(s); -} - -static void sifive_gpio_reset(DeviceState *dev) -{ - SIFIVEGPIOState *s = SIFIVE_GPIO(dev); - - s->value = 0; - s->input_en = 0; - s->output_en = 0; - s->port = 0; - s->pue = 0; - s->ds = 0; - s->rise_ie = 0; - s->rise_ip = 0; - s->fall_ie = 0; - s->fall_ip = 0; - s->high_ie = 0; - s->high_ip = 0; - s->low_ie = 0; - s->low_ip = 0; - s->iof_en = 0; - s->iof_sel = 0; - s->out_xor = 0; - s->in = 0; - s->in_mask = 0; -} - -static const VMStateDescription vmstate_sifive_gpio = { - .name = TYPE_SIFIVE_GPIO, - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32(value, SIFIVEGPIOState), - VMSTATE_UINT32(input_en, SIFIVEGPIOState), - VMSTATE_UINT32(output_en, SIFIVEGPIOState), - VMSTATE_UINT32(port, SIFIVEGPIOState), - VMSTATE_UINT32(pue, SIFIVEGPIOState), - VMSTATE_UINT32(rise_ie, SIFIVEGPIOState), - VMSTATE_UINT32(rise_ip, SIFIVEGPIOState), - VMSTATE_UINT32(fall_ie, SIFIVEGPIOState), - VMSTATE_UINT32(fall_ip, SIFIVEGPIOState), - VMSTATE_UINT32(high_ie, SIFIVEGPIOState), - VMSTATE_UINT32(high_ip, SIFIVEGPIOState), - VMSTATE_UINT32(low_ie, SIFIVEGPIOState), - VMSTATE_UINT32(low_ip, SIFIVEGPIOState), - VMSTATE_UINT32(iof_en, SIFIVEGPIOState), - VMSTATE_UINT32(iof_sel, SIFIVEGPIOState), - VMSTATE_UINT32(out_xor, SIFIVEGPIOState), - VMSTATE_UINT32(in, SIFIVEGPIOState), - VMSTATE_UINT32(in_mask, SIFIVEGPIOState), - VMSTATE_END_OF_LIST() - } -}; - -static Property sifive_gpio_properties[] = { - DEFINE_PROP_UINT32("ngpio", SIFIVEGPIOState, ngpio, SIFIVE_GPIO_PINS), - DEFINE_PROP_END_OF_LIST(), -}; - -static void sifive_gpio_realize(DeviceState *dev, Error **errp) -{ - SIFIVEGPIOState *s = SIFIVE_GPIO(dev); - - memory_region_init_io(&s->mmio, OBJECT(dev), &gpio_ops, s, - TYPE_SIFIVE_GPIO, SIFIVE_GPIO_SIZE); - - sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); - - for (int i = 0; i < s->ngpio; i++) { - sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]); - } - - qdev_init_gpio_in(DEVICE(s), sifive_gpio_set, s->ngpio); - qdev_init_gpio_out(DEVICE(s), s->output, s->ngpio); -} - -static void sifive_gpio_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - device_class_set_props(dc, sifive_gpio_properties); - dc->vmsd = &vmstate_sifive_gpio; - dc->realize = sifive_gpio_realize; - dc->reset = sifive_gpio_reset; - dc->desc = "SiFive GPIO"; -} - -static const TypeInfo sifive_gpio_info = { - .name = TYPE_SIFIVE_GPIO, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(SIFIVEGPIOState), - .class_init = sifive_gpio_class_init -}; - -static void sifive_gpio_register_types(void) -{ - type_register_static(&sifive_gpio_info); -} - -type_init(sifive_gpio_register_types) diff --git a/hw/riscv/trace-events b/hw/riscv/trace-events deleted file mode 100644 index 6d59233e23..0000000000 --- a/hw/riscv/trace-events +++ /dev/null @@ -1,7 +0,0 @@ -# See docs/devel/tracing.txt for syntax documentation. - -# hw/gpio/sifive_gpio.c -sifive_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" PRIx64 -sifive_gpio_write(uint64_t offset, uint64_t value) "offset 0x%" PRIx64 " value 0x%" PRIx64 -sifive_gpio_set(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64 -sifive_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64 diff --git a/hw/riscv/trace.h b/hw/riscv/trace.h deleted file mode 100644 index 8c0e3ca1f3..0000000000 --- a/hw/riscv/trace.h +++ /dev/null @@ -1 +0,0 @@ -#include "trace/trace-hw_riscv.h" diff --git a/include/hw/gpio/sifive_gpio.h b/include/hw/gpio/sifive_gpio.h new file mode 100644 index 0000000000..cf12fcfd62 --- /dev/null +++ b/include/hw/gpio/sifive_gpio.h @@ -0,0 +1,76 @@ +/* + * SiFive System-on-Chip general purpose input/output register definition + * + * Copyright 2019 AdaCore + * + * Base on nrf51_gpio.c: + * + * Copyright 2018 Steffen Görtz + * + * This code is licensed under the GPL version 2 or later. See + * the COPYING file in the top-level directory. + */ + +#ifndef SIFIVE_GPIO_H +#define SIFIVE_GPIO_H + +#include "hw/sysbus.h" + +#define TYPE_SIFIVE_GPIO "sifive_soc.gpio" +#define SIFIVE_GPIO(obj) OBJECT_CHECK(SIFIVEGPIOState, (obj), TYPE_SIFIVE_GPIO) + +#define SIFIVE_GPIO_PINS 32 + +#define SIFIVE_GPIO_SIZE 0x100 + +#define SIFIVE_GPIO_REG_VALUE 0x000 +#define SIFIVE_GPIO_REG_INPUT_EN 0x004 +#define SIFIVE_GPIO_REG_OUTPUT_EN 0x008 +#define SIFIVE_GPIO_REG_PORT 0x00C +#define SIFIVE_GPIO_REG_PUE 0x010 +#define SIFIVE_GPIO_REG_DS 0x014 +#define SIFIVE_GPIO_REG_RISE_IE 0x018 +#define SIFIVE_GPIO_REG_RISE_IP 0x01C +#define SIFIVE_GPIO_REG_FALL_IE 0x020 +#define SIFIVE_GPIO_REG_FALL_IP 0x024 +#define SIFIVE_GPIO_REG_HIGH_IE 0x028 +#define SIFIVE_GPIO_REG_HIGH_IP 0x02C +#define SIFIVE_GPIO_REG_LOW_IE 0x030 +#define SIFIVE_GPIO_REG_LOW_IP 0x034 +#define SIFIVE_GPIO_REG_IOF_EN 0x038 +#define SIFIVE_GPIO_REG_IOF_SEL 0x03C +#define SIFIVE_GPIO_REG_OUT_XOR 0x040 + +typedef struct SIFIVEGPIOState { + SysBusDevice parent_obj; + + MemoryRegion mmio; + + qemu_irq irq[SIFIVE_GPIO_PINS]; + qemu_irq output[SIFIVE_GPIO_PINS]; + + uint32_t value; /* Actual value of the pin */ + uint32_t input_en; + uint32_t output_en; + uint32_t port; /* Pin value requested by the user */ + uint32_t pue; + uint32_t ds; + uint32_t rise_ie; + uint32_t rise_ip; + uint32_t fall_ie; + uint32_t fall_ip; + uint32_t high_ie; + uint32_t high_ip; + uint32_t low_ie; + uint32_t low_ip; + uint32_t iof_en; + uint32_t iof_sel; + uint32_t out_xor; + uint32_t in; + uint32_t in_mask; + + /* config */ + uint32_t ngpio; +} SIFIVEGPIOState; + +#endif /* SIFIVE_GPIO_H */ diff --git a/include/hw/riscv/sifive_e.h b/include/hw/riscv/sifive_e.h index 637414130b..b1400843c2 100644 --- a/include/hw/riscv/sifive_e.h +++ b/include/hw/riscv/sifive_e.h @@ -21,7 +21,7 @@ #include "hw/riscv/riscv_hart.h" #include "hw/riscv/sifive_cpu.h" -#include "hw/riscv/sifive_gpio.h" +#include "hw/gpio/sifive_gpio.h" #define TYPE_RISCV_E_SOC "riscv.sifive.e.soc" #define RISCV_E_SOC(obj) \ diff --git a/include/hw/riscv/sifive_gpio.h b/include/hw/riscv/sifive_gpio.h deleted file mode 100644 index cf12fcfd62..0000000000 --- a/include/hw/riscv/sifive_gpio.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * SiFive System-on-Chip general purpose input/output register definition - * - * Copyright 2019 AdaCore - * - * Base on nrf51_gpio.c: - * - * Copyright 2018 Steffen Görtz - * - * This code is licensed under the GPL version 2 or later. See - * the COPYING file in the top-level directory. - */ - -#ifndef SIFIVE_GPIO_H -#define SIFIVE_GPIO_H - -#include "hw/sysbus.h" - -#define TYPE_SIFIVE_GPIO "sifive_soc.gpio" -#define SIFIVE_GPIO(obj) OBJECT_CHECK(SIFIVEGPIOState, (obj), TYPE_SIFIVE_GPIO) - -#define SIFIVE_GPIO_PINS 32 - -#define SIFIVE_GPIO_SIZE 0x100 - -#define SIFIVE_GPIO_REG_VALUE 0x000 -#define SIFIVE_GPIO_REG_INPUT_EN 0x004 -#define SIFIVE_GPIO_REG_OUTPUT_EN 0x008 -#define SIFIVE_GPIO_REG_PORT 0x00C -#define SIFIVE_GPIO_REG_PUE 0x010 -#define SIFIVE_GPIO_REG_DS 0x014 -#define SIFIVE_GPIO_REG_RISE_IE 0x018 -#define SIFIVE_GPIO_REG_RISE_IP 0x01C -#define SIFIVE_GPIO_REG_FALL_IE 0x020 -#define SIFIVE_GPIO_REG_FALL_IP 0x024 -#define SIFIVE_GPIO_REG_HIGH_IE 0x028 -#define SIFIVE_GPIO_REG_HIGH_IP 0x02C -#define SIFIVE_GPIO_REG_LOW_IE 0x030 -#define SIFIVE_GPIO_REG_LOW_IP 0x034 -#define SIFIVE_GPIO_REG_IOF_EN 0x038 -#define SIFIVE_GPIO_REG_IOF_SEL 0x03C -#define SIFIVE_GPIO_REG_OUT_XOR 0x040 - -typedef struct SIFIVEGPIOState { - SysBusDevice parent_obj; - - MemoryRegion mmio; - - qemu_irq irq[SIFIVE_GPIO_PINS]; - qemu_irq output[SIFIVE_GPIO_PINS]; - - uint32_t value; /* Actual value of the pin */ - uint32_t input_en; - uint32_t output_en; - uint32_t port; /* Pin value requested by the user */ - uint32_t pue; - uint32_t ds; - uint32_t rise_ie; - uint32_t rise_ip; - uint32_t fall_ie; - uint32_t fall_ip; - uint32_t high_ie; - uint32_t high_ip; - uint32_t low_ie; - uint32_t low_ip; - uint32_t iof_en; - uint32_t iof_sel; - uint32_t out_xor; - uint32_t in; - uint32_t in_mask; - - /* config */ - uint32_t ngpio; -} SIFIVEGPIOState; - -#endif /* SIFIVE_GPIO_H */ diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h index 936a3bd0b1..fe5c580845 100644 --- a/include/hw/riscv/sifive_u.h +++ b/include/hw/riscv/sifive_u.h @@ -23,7 +23,7 @@ #include "hw/net/cadence_gem.h" #include "hw/riscv/riscv_hart.h" #include "hw/riscv/sifive_cpu.h" -#include "hw/riscv/sifive_gpio.h" +#include "hw/gpio/sifive_gpio.h" #include "hw/misc/sifive_u_otp.h" #include "hw/misc/sifive_u_prci.h" diff --git a/meson.build b/meson.build index 5421eca66a..bc869c676a 100644 --- a/meson.build +++ b/meson.build @@ -773,7 +773,6 @@ if have_system 'hw/watchdog', 'hw/xen', 'hw/gpio', - 'hw/riscv', 'migration', 'net', 'ui',