1 | The following changes since commit d0ac9a61474cf594d19082bc8976247e984ea9a3: | 1 | From: Alistair Francis <alistair.francis@wdc.com> |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/thuth-gitlab/tags/pull-request-2021-06-21' into staging (2021-06-24 09:31:26 +0100) | 3 | The following changes since commit c5fbdd60cf1fb52f01bdfe342b6fa65d5343e1b1: |
4 | |||
5 | Merge tag 'qemu-sparc-20211121' of git://github.com/mcayland/qemu into staging (2021-11-21 14:12:25 +0100) | ||
4 | 6 | ||
5 | are available in the Git repository at: | 7 | are available in the Git repository at: |
6 | 8 | ||
7 | git@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20210624-2 | 9 | git@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20211122 |
8 | 10 | ||
9 | for you to fetch changes up to 3ef6434409c575e11faf537ce50ca05426c78940: | 11 | for you to fetch changes up to 526e7443027c71fe7b04c29df529e1f9f425f9e3: |
10 | 12 | ||
11 | hw/riscv: OpenTitan: Connect the mtime and mtimecmp timer (2021-06-24 05:00:13 -0700) | 13 | hw/misc/sifive_u_otp: Do not reset OTP content on hardware reset (2021-11-22 10:46:22 +1000) |
12 | 14 | ||
13 | ---------------------------------------------------------------- | 15 | ---------------------------------------------------------------- |
14 | Third RISC-V PR for 6.1 release | 16 | Seventh RISC-V PR for QEMU 6.2 |
15 | 17 | ||
16 | - Fix MISA in the DisasContext | 18 | - Deprecate IF_NONE for SiFive OTP |
17 | - Fix GDB CSR XML generation | 19 | - Don't reset SiFive OTP content |
18 | - QOMify the SiFive UART | ||
19 | - Add support for the OpenTitan timer | ||
20 | 20 | ||
21 | ---------------------------------------------------------------- | 21 | ---------------------------------------------------------------- |
22 | Alistair Francis (4): | 22 | Philippe Mathieu-Daudé (1): |
23 | target/riscv: Use target_ulong for the DisasContext misa | 23 | hw/misc/sifive_u_otp: Do not reset OTP content on hardware reset |
24 | hw/char/ibex_uart: Make the register layout private | ||
25 | hw/timer: Initial commit of Ibex Timer | ||
26 | hw/riscv: OpenTitan: Connect the mtime and mtimecmp timer | ||
27 | 24 | ||
28 | Bin Meng (1): | 25 | Thomas Huth (1): |
29 | target/riscv: gdbstub: Fix dynamic CSR XML generation | 26 | hw/misc/sifive_u_otp: Use IF_PFLASH for the OTP device instead of IF_NONE |
30 | 27 | ||
31 | Lukas Jünger (2): | 28 | docs/about/deprecated.rst | 6 ++++++ |
32 | hw/char: Consistent function names for sifive_uart | 29 | hw/misc/sifive_u_otp.c | 22 +++++++++++++--------- |
33 | hw/char: QOMify sifive_uart | 30 | 2 files changed, 19 insertions(+), 9 deletions(-) |
34 | 31 | ||
35 | include/hw/char/ibex_uart.h | 37 ----- | ||
36 | include/hw/char/sifive_uart.h | 11 +- | ||
37 | include/hw/riscv/opentitan.h | 5 +- | ||
38 | include/hw/timer/ibex_timer.h | 52 +++++++ | ||
39 | hw/char/ibex_uart.c | 37 +++++ | ||
40 | hw/char/sifive_uart.c | 152 +++++++++++++++++---- | ||
41 | hw/riscv/opentitan.c | 14 +- | ||
42 | hw/timer/ibex_timer.c | 305 ++++++++++++++++++++++++++++++++++++++++++ | ||
43 | target/riscv/gdbstub.c | 2 +- | ||
44 | target/riscv/translate.c | 2 +- | ||
45 | MAINTAINERS | 6 +- | ||
46 | hw/timer/meson.build | 1 + | ||
47 | 12 files changed, 543 insertions(+), 81 deletions(-) | ||
48 | create mode 100644 include/hw/timer/ibex_timer.h | ||
49 | create mode 100644 hw/timer/ibex_timer.c | ||
50 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | The is_32bit() check in translate.c expects a 64-bit guest to have a | ||
2 | 64-bit misa value otherwise the macro check won't work. This patches | ||
3 | fixes that and fixes a Coverity issue at the same time. | ||
4 | 1 | ||
5 | Fixes: CID 1453107 | ||
6 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | ||
7 | Reviewed-by: Bin Meng <bmeng.cn@gmail.com> | ||
8 | Message-id: c00176c7518c2a7b4de3eec320b6a683ab56f705.1622435221.git.alistair.francis@wdc.com | ||
9 | --- | ||
10 | target/riscv/translate.c | 2 +- | ||
11 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
12 | |||
13 | diff --git a/target/riscv/translate.c b/target/riscv/translate.c | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/target/riscv/translate.c | ||
16 | +++ b/target/riscv/translate.c | ||
17 | @@ -XXX,XX +XXX,XX @@ typedef struct DisasContext { | ||
18 | bool virt_enabled; | ||
19 | uint32_t opcode; | ||
20 | uint32_t mstatus_fs; | ||
21 | - uint32_t misa; | ||
22 | + target_ulong misa; | ||
23 | uint32_t mem_idx; | ||
24 | /* Remember the rounding mode encoded in the previous fp instruction, | ||
25 | which we have already installed into env->fp_status. Or -1 for | ||
26 | -- | ||
27 | 2.31.1 | ||
28 | |||
29 | diff view generated by jsdifflib |
1 | From: Bin Meng <bin.meng@windriver.com> | 1 | From: Thomas Huth <thuth@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | Since commit 605def6eeee5 ("target/riscv: Use the RISCVException enum for CSR operations") | 3 | Configuring a drive with "if=none" is meant for creation of a backend |
4 | the CSR predicate() function was changed to return RISCV_EXCP_NONE | 4 | only, it should not get automatically assigned to a device frontend. |
5 | instead of 0 for a valid CSR, but it forgot to update the dynamic | 5 | Use "if=pflash" for the One-Time-Programmable device instead (like |
6 | CSR XML generation codes in gdbstub. | 6 | it is e.g. also done for the efuse device in hw/arm/xlnx-zcu102.c). |
7 | 7 | ||
8 | Fixes: 605def6eeee5 ("target/riscv: Use the RISCVException enum for CSR operations") | 8 | Since the old way of configuring the device has already been published |
9 | Reported-by: Xuzhou Cheng <xuzhou.cheng@windriver.com> | 9 | with the previous QEMU versions, we cannot remove this immediately, but |
10 | Signed-off-by: Bin Meng <bin.meng@windriver.com> | 10 | have to deprecate it and support it for at least two more releases. |
11 | Tested-by: Xuzhou Cheng <xuzhou.cheng@windriver.com> | 11 | |
12 | Signed-off-by: Thomas Huth <thuth@redhat.com> | ||
13 | Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
14 | Reviewed-by: Markus Armbruster <armbru@redhat.com> | ||
12 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | 15 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> |
13 | Message-id: 20210615085133.389887-1-bmeng.cn@gmail.com | 16 | Message-id: 20211119102549.217755-1-thuth@redhat.com |
14 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | 17 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> |
15 | --- | 18 | --- |
16 | target/riscv/gdbstub.c | 2 +- | 19 | docs/about/deprecated.rst | 6 ++++++ |
17 | 1 file changed, 1 insertion(+), 1 deletion(-) | 20 | hw/misc/sifive_u_otp.c | 9 ++++++++- |
21 | 2 files changed, 14 insertions(+), 1 deletion(-) | ||
18 | 22 | ||
19 | diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c | 23 | diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst |
20 | index XXXXXXX..XXXXXXX 100644 | 24 | index XXXXXXX..XXXXXXX 100644 |
21 | --- a/target/riscv/gdbstub.c | 25 | --- a/docs/about/deprecated.rst |
22 | +++ b/target/riscv/gdbstub.c | 26 | +++ b/docs/about/deprecated.rst |
23 | @@ -XXX,XX +XXX,XX @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg) | 27 | @@ -XXX,XX +XXX,XX @@ as short-form boolean values, and passed to plugins as ``arg_name=on``. |
24 | 28 | However, short-form booleans are deprecated and full explicit ``arg_name=on`` | |
25 | for (i = 0; i < CSR_TABLE_SIZE; i++) { | 29 | form is preferred. |
26 | predicate = csr_ops[i].predicate; | 30 | |
27 | - if (predicate && !predicate(env, i)) { | 31 | +``-drive if=none`` for the sifive_u OTP device (since 6.2) |
28 | + if (predicate && (predicate(env, i) == RISCV_EXCP_NONE)) { | 32 | +'''''''''''''''''''''''''''''''''''''''''''''''''''''''''' |
29 | if (csr_ops[i].name) { | 33 | + |
30 | g_string_append_printf(s, "<reg name=\"%s\"", csr_ops[i].name); | 34 | +Using ``-drive if=none`` to configure the OTP device of the sifive_u |
31 | } else { | 35 | +RISC-V machine is deprecated. Use ``-drive if=pflash`` instead. |
36 | + | ||
37 | |||
38 | QEMU Machine Protocol (QMP) commands | ||
39 | ------------------------------------ | ||
40 | diff --git a/hw/misc/sifive_u_otp.c b/hw/misc/sifive_u_otp.c | ||
41 | index XXXXXXX..XXXXXXX 100644 | ||
42 | --- a/hw/misc/sifive_u_otp.c | ||
43 | +++ b/hw/misc/sifive_u_otp.c | ||
44 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_realize(DeviceState *dev, Error **errp) | ||
45 | TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE); | ||
46 | sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); | ||
47 | |||
48 | - dinfo = drive_get_next(IF_NONE); | ||
49 | + dinfo = drive_get_next(IF_PFLASH); | ||
50 | + if (!dinfo) { | ||
51 | + dinfo = drive_get_next(IF_NONE); | ||
52 | + if (dinfo) { | ||
53 | + warn_report("using \"-drive if=none\" for the OTP is deprecated, " | ||
54 | + "use \"-drive if=pflash\" instead."); | ||
55 | + } | ||
56 | + } | ||
57 | if (dinfo) { | ||
58 | int ret; | ||
59 | uint64_t perm; | ||
32 | -- | 60 | -- |
33 | 2.31.1 | 61 | 2.31.1 |
34 | 62 | ||
35 | 63 | diff view generated by jsdifflib |
1 | From: Lukas Jünger <lukas.juenger@greensocs.com> | 1 | From: Philippe Mathieu-Daudé <f4bug@amsat.org> |
---|---|---|---|
2 | 2 | ||
3 | This cleans up function names in the SiFive UART model. | 3 | Once a "One Time Programmable" is programmed, it shouldn't be reset. |
4 | 4 | ||
5 | Signed-off-by: Lukas Jünger <lukas.juenger@greensocs.com> | 5 | Do not re-initialize the OTP content in the DeviceReset handler, |
6 | initialize it once in the DeviceRealize one. | ||
7 | |||
8 | Fixes: 9fb45c62ae8 ("riscv: sifive: Implement a model for SiFive FU540 OTP") | ||
9 | Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
6 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | 10 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> |
7 | Reviewed-by: Bin Meng <bmeng.cn@gmail.com> | 11 | Message-Id: <20211119104757.331579-1-f4bug@amsat.org> |
8 | Message-id: 20210616092326.59639-2-lukas.juenger@greensocs.com | ||
9 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | 12 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> |
10 | --- | 13 | --- |
11 | hw/char/sifive_uart.c | 46 ++++++++++++++++++++++--------------------- | 14 | hw/misc/sifive_u_otp.c | 13 +++++-------- |
12 | 1 file changed, 24 insertions(+), 22 deletions(-) | 15 | 1 file changed, 5 insertions(+), 8 deletions(-) |
13 | 16 | ||
14 | diff --git a/hw/char/sifive_uart.c b/hw/char/sifive_uart.c | 17 | diff --git a/hw/misc/sifive_u_otp.c b/hw/misc/sifive_u_otp.c |
15 | index XXXXXXX..XXXXXXX 100644 | 18 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/hw/char/sifive_uart.c | 19 | --- a/hw/misc/sifive_u_otp.c |
17 | +++ b/hw/char/sifive_uart.c | 20 | +++ b/hw/misc/sifive_u_otp.c |
18 | @@ -XXX,XX +XXX,XX @@ | 21 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_realize(DeviceState *dev, Error **errp) |
19 | */ | 22 | |
20 | 23 | if (blk_pread(s->blk, 0, s->fuse, filesize) != filesize) { | |
21 | /* Returns the state of the IP (interrupt pending) register */ | 24 | error_setg(errp, "failed to read the initial flash content"); |
22 | -static uint64_t uart_ip(SiFiveUARTState *s) | 25 | + return; |
23 | +static uint64_t sifive_uart_ip(SiFiveUARTState *s) | 26 | } |
24 | { | 27 | } |
25 | uint64_t ret = 0; | 28 | } |
26 | 29 | -} | |
27 | @@ -XXX,XX +XXX,XX @@ static uint64_t uart_ip(SiFiveUARTState *s) | 30 | - |
28 | return ret; | 31 | -static void sifive_u_otp_reset(DeviceState *dev) |
32 | -{ | ||
33 | - SiFiveUOTPState *s = SIFIVE_U_OTP(dev); | ||
34 | |||
35 | /* Initialize all fuses' initial value to 0xFFs */ | ||
36 | memset(s->fuse, 0xff, sizeof(s->fuse)); | ||
37 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_reset(DeviceState *dev) | ||
38 | serial_data = s->serial; | ||
39 | if (blk_pwrite(s->blk, index * SIFIVE_U_OTP_FUSE_WORD, | ||
40 | &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0) < 0) { | ||
41 | - error_report("write error index<%d>", index); | ||
42 | + error_setg(errp, "failed to write index<%d>", index); | ||
43 | + return; | ||
44 | } | ||
45 | |||
46 | serial_data = ~(s->serial); | ||
47 | if (blk_pwrite(s->blk, (index + 1) * SIFIVE_U_OTP_FUSE_WORD, | ||
48 | &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0) < 0) { | ||
49 | - error_report("write error index<%d>", index + 1); | ||
50 | + error_setg(errp, "failed to write index<%d>", index + 1); | ||
51 | + return; | ||
52 | } | ||
53 | } | ||
54 | |||
55 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_class_init(ObjectClass *klass, void *data) | ||
56 | |||
57 | device_class_set_props(dc, sifive_u_otp_properties); | ||
58 | dc->realize = sifive_u_otp_realize; | ||
59 | - dc->reset = sifive_u_otp_reset; | ||
29 | } | 60 | } |
30 | 61 | ||
31 | -static void update_irq(SiFiveUARTState *s) | 62 | static const TypeInfo sifive_u_otp_info = { |
32 | +static void sifive_uart_update_irq(SiFiveUARTState *s) | ||
33 | { | ||
34 | int cond = 0; | ||
35 | if ((s->ie & SIFIVE_UART_IE_TXWM) || | ||
36 | @@ -XXX,XX +XXX,XX @@ static void update_irq(SiFiveUARTState *s) | ||
37 | } | ||
38 | |||
39 | static uint64_t | ||
40 | -uart_read(void *opaque, hwaddr addr, unsigned int size) | ||
41 | +sifive_uart_read(void *opaque, hwaddr addr, unsigned int size) | ||
42 | { | ||
43 | SiFiveUARTState *s = opaque; | ||
44 | unsigned char r; | ||
45 | @@ -XXX,XX +XXX,XX @@ uart_read(void *opaque, hwaddr addr, unsigned int size) | ||
46 | memmove(s->rx_fifo, s->rx_fifo + 1, s->rx_fifo_len - 1); | ||
47 | s->rx_fifo_len--; | ||
48 | qemu_chr_fe_accept_input(&s->chr); | ||
49 | - update_irq(s); | ||
50 | + sifive_uart_update_irq(s); | ||
51 | return r; | ||
52 | } | ||
53 | return 0x80000000; | ||
54 | @@ -XXX,XX +XXX,XX @@ uart_read(void *opaque, hwaddr addr, unsigned int size) | ||
55 | case SIFIVE_UART_IE: | ||
56 | return s->ie; | ||
57 | case SIFIVE_UART_IP: | ||
58 | - return uart_ip(s); | ||
59 | + return sifive_uart_ip(s); | ||
60 | case SIFIVE_UART_TXCTRL: | ||
61 | return s->txctrl; | ||
62 | case SIFIVE_UART_RXCTRL: | ||
63 | @@ -XXX,XX +XXX,XX @@ uart_read(void *opaque, hwaddr addr, unsigned int size) | ||
64 | } | ||
65 | |||
66 | static void | ||
67 | -uart_write(void *opaque, hwaddr addr, | ||
68 | - uint64_t val64, unsigned int size) | ||
69 | +sifive_uart_write(void *opaque, hwaddr addr, | ||
70 | + uint64_t val64, unsigned int size) | ||
71 | { | ||
72 | SiFiveUARTState *s = opaque; | ||
73 | uint32_t value = val64; | ||
74 | @@ -XXX,XX +XXX,XX @@ uart_write(void *opaque, hwaddr addr, | ||
75 | switch (addr) { | ||
76 | case SIFIVE_UART_TXFIFO: | ||
77 | qemu_chr_fe_write(&s->chr, &ch, 1); | ||
78 | - update_irq(s); | ||
79 | + sifive_uart_update_irq(s); | ||
80 | return; | ||
81 | case SIFIVE_UART_IE: | ||
82 | s->ie = val64; | ||
83 | - update_irq(s); | ||
84 | + sifive_uart_update_irq(s); | ||
85 | return; | ||
86 | case SIFIVE_UART_TXCTRL: | ||
87 | s->txctrl = val64; | ||
88 | @@ -XXX,XX +XXX,XX @@ uart_write(void *opaque, hwaddr addr, | ||
89 | __func__, (int)addr, (int)value); | ||
90 | } | ||
91 | |||
92 | -static const MemoryRegionOps uart_ops = { | ||
93 | - .read = uart_read, | ||
94 | - .write = uart_write, | ||
95 | +static const MemoryRegionOps sifive_uart_ops = { | ||
96 | + .read = sifive_uart_read, | ||
97 | + .write = sifive_uart_write, | ||
98 | .endianness = DEVICE_NATIVE_ENDIAN, | ||
99 | .valid = { | ||
100 | .min_access_size = 4, | ||
101 | @@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps uart_ops = { | ||
102 | } | ||
103 | }; | ||
104 | |||
105 | -static void uart_rx(void *opaque, const uint8_t *buf, int size) | ||
106 | +static void sifive_uart_rx(void *opaque, const uint8_t *buf, int size) | ||
107 | { | ||
108 | SiFiveUARTState *s = opaque; | ||
109 | |||
110 | @@ -XXX,XX +XXX,XX @@ static void uart_rx(void *opaque, const uint8_t *buf, int size) | ||
111 | } | ||
112 | s->rx_fifo[s->rx_fifo_len++] = *buf; | ||
113 | |||
114 | - update_irq(s); | ||
115 | + sifive_uart_update_irq(s); | ||
116 | } | ||
117 | |||
118 | -static int uart_can_rx(void *opaque) | ||
119 | +static int sifive_uart_can_rx(void *opaque) | ||
120 | { | ||
121 | SiFiveUARTState *s = opaque; | ||
122 | |||
123 | return s->rx_fifo_len < sizeof(s->rx_fifo); | ||
124 | } | ||
125 | |||
126 | -static void uart_event(void *opaque, QEMUChrEvent event) | ||
127 | +static void sifive_uart_event(void *opaque, QEMUChrEvent event) | ||
128 | { | ||
129 | } | ||
130 | |||
131 | -static int uart_be_change(void *opaque) | ||
132 | +static int sifive_uart_be_change(void *opaque) | ||
133 | { | ||
134 | SiFiveUARTState *s = opaque; | ||
135 | |||
136 | - qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx, uart_event, | ||
137 | - uart_be_change, s, NULL, true); | ||
138 | + qemu_chr_fe_set_handlers(&s->chr, sifive_uart_can_rx, sifive_uart_rx, | ||
139 | + sifive_uart_event, sifive_uart_be_change, s, | ||
140 | + NULL, true); | ||
141 | |||
142 | return 0; | ||
143 | } | ||
144 | @@ -XXX,XX +XXX,XX @@ SiFiveUARTState *sifive_uart_create(MemoryRegion *address_space, hwaddr base, | ||
145 | SiFiveUARTState *s = g_malloc0(sizeof(SiFiveUARTState)); | ||
146 | s->irq = irq; | ||
147 | qemu_chr_fe_init(&s->chr, chr, &error_abort); | ||
148 | - qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx, uart_event, | ||
149 | - uart_be_change, s, NULL, true); | ||
150 | - memory_region_init_io(&s->mmio, NULL, &uart_ops, s, | ||
151 | + qemu_chr_fe_set_handlers(&s->chr, sifive_uart_can_rx, sifive_uart_rx, | ||
152 | + sifive_uart_event, sifive_uart_be_change, s, | ||
153 | + NULL, true); | ||
154 | + memory_region_init_io(&s->mmio, NULL, &sifive_uart_ops, s, | ||
155 | TYPE_SIFIVE_UART, SIFIVE_UART_MAX); | ||
156 | memory_region_add_subregion(address_space, base, &s->mmio); | ||
157 | return s; | ||
158 | -- | 63 | -- |
159 | 2.31.1 | 64 | 2.31.1 |
160 | 65 | ||
161 | 66 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Lukas Jünger <lukas.juenger@greensocs.com> | ||
2 | 1 | ||
3 | This QOMifies the SiFive UART model. Migration and reset have been | ||
4 | implemented. | ||
5 | |||
6 | Signed-off-by: Lukas Jünger <lukas.juenger@greensocs.com> | ||
7 | Reviewed-by: Bin Meng <bmeng.cn@gmail.com> | ||
8 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | ||
9 | Message-id: 20210616092326.59639-3-lukas.juenger@greensocs.com | ||
10 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | ||
11 | --- | ||
12 | include/hw/char/sifive_uart.h | 11 ++-- | ||
13 | hw/char/sifive_uart.c | 114 +++++++++++++++++++++++++++++++--- | ||
14 | 2 files changed, 109 insertions(+), 16 deletions(-) | ||
15 | |||
16 | diff --git a/include/hw/char/sifive_uart.h b/include/hw/char/sifive_uart.h | ||
17 | index XXXXXXX..XXXXXXX 100644 | ||
18 | --- a/include/hw/char/sifive_uart.h | ||
19 | +++ b/include/hw/char/sifive_uart.h | ||
20 | @@ -XXX,XX +XXX,XX @@ | ||
21 | #define HW_SIFIVE_UART_H | ||
22 | |||
23 | #include "chardev/char-fe.h" | ||
24 | +#include "hw/qdev-properties.h" | ||
25 | #include "hw/sysbus.h" | ||
26 | #include "qom/object.h" | ||
27 | |||
28 | @@ -XXX,XX +XXX,XX @@ enum { | ||
29 | |||
30 | #define SIFIVE_UART_GET_TXCNT(txctrl) ((txctrl >> 16) & 0x7) | ||
31 | #define SIFIVE_UART_GET_RXCNT(rxctrl) ((rxctrl >> 16) & 0x7) | ||
32 | +#define SIFIVE_UART_RX_FIFO_SIZE 8 | ||
33 | |||
34 | #define TYPE_SIFIVE_UART "riscv.sifive.uart" | ||
35 | - | ||
36 | -typedef struct SiFiveUARTState SiFiveUARTState; | ||
37 | -DECLARE_INSTANCE_CHECKER(SiFiveUARTState, SIFIVE_UART, | ||
38 | - TYPE_SIFIVE_UART) | ||
39 | +OBJECT_DECLARE_SIMPLE_TYPE(SiFiveUARTState, SIFIVE_UART) | ||
40 | |||
41 | struct SiFiveUARTState { | ||
42 | /*< private >*/ | ||
43 | @@ -XXX,XX +XXX,XX @@ struct SiFiveUARTState { | ||
44 | qemu_irq irq; | ||
45 | MemoryRegion mmio; | ||
46 | CharBackend chr; | ||
47 | - uint8_t rx_fifo[8]; | ||
48 | - unsigned int rx_fifo_len; | ||
49 | + uint8_t rx_fifo[SIFIVE_UART_RX_FIFO_SIZE]; | ||
50 | + uint8_t rx_fifo_len; | ||
51 | uint32_t ie; | ||
52 | uint32_t ip; | ||
53 | uint32_t txctrl; | ||
54 | diff --git a/hw/char/sifive_uart.c b/hw/char/sifive_uart.c | ||
55 | index XXXXXXX..XXXXXXX 100644 | ||
56 | --- a/hw/char/sifive_uart.c | ||
57 | +++ b/hw/char/sifive_uart.c | ||
58 | @@ -XXX,XX +XXX,XX @@ | ||
59 | #include "qemu/osdep.h" | ||
60 | #include "qapi/error.h" | ||
61 | #include "qemu/log.h" | ||
62 | +#include "migration/vmstate.h" | ||
63 | #include "chardev/char.h" | ||
64 | #include "chardev/char-fe.h" | ||
65 | #include "hw/irq.h" | ||
66 | #include "hw/char/sifive_uart.h" | ||
67 | +#include "hw/qdev-properties-system.h" | ||
68 | |||
69 | /* | ||
70 | * Not yet implemented: | ||
71 | @@ -XXX,XX +XXX,XX @@ static int sifive_uart_be_change(void *opaque) | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | +static Property sifive_uart_properties[] = { | ||
76 | + DEFINE_PROP_CHR("chardev", SiFiveUARTState, chr), | ||
77 | + DEFINE_PROP_END_OF_LIST(), | ||
78 | +}; | ||
79 | + | ||
80 | +static void sifive_uart_init(Object *obj) | ||
81 | +{ | ||
82 | + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); | ||
83 | + SiFiveUARTState *s = SIFIVE_UART(obj); | ||
84 | + | ||
85 | + memory_region_init_io(&s->mmio, OBJECT(s), &sifive_uart_ops, s, | ||
86 | + TYPE_SIFIVE_UART, SIFIVE_UART_MAX); | ||
87 | + sysbus_init_mmio(sbd, &s->mmio); | ||
88 | + sysbus_init_irq(sbd, &s->irq); | ||
89 | +} | ||
90 | + | ||
91 | +static void sifive_uart_realize(DeviceState *dev, Error **errp) | ||
92 | +{ | ||
93 | + SiFiveUARTState *s = SIFIVE_UART(dev); | ||
94 | + | ||
95 | + qemu_chr_fe_set_handlers(&s->chr, sifive_uart_can_rx, sifive_uart_rx, | ||
96 | + sifive_uart_event, sifive_uart_be_change, s, | ||
97 | + NULL, true); | ||
98 | + | ||
99 | +} | ||
100 | + | ||
101 | +static void sifive_uart_reset_enter(Object *obj, ResetType type) | ||
102 | +{ | ||
103 | + SiFiveUARTState *s = SIFIVE_UART(obj); | ||
104 | + s->ie = 0; | ||
105 | + s->ip = 0; | ||
106 | + s->txctrl = 0; | ||
107 | + s->rxctrl = 0; | ||
108 | + s->div = 0; | ||
109 | + s->rx_fifo_len = 0; | ||
110 | +} | ||
111 | + | ||
112 | +static void sifive_uart_reset_hold(Object *obj) | ||
113 | +{ | ||
114 | + SiFiveUARTState *s = SIFIVE_UART(obj); | ||
115 | + qemu_irq_lower(s->irq); | ||
116 | +} | ||
117 | + | ||
118 | +static const VMStateDescription vmstate_sifive_uart = { | ||
119 | + .name = TYPE_SIFIVE_UART, | ||
120 | + .version_id = 1, | ||
121 | + .minimum_version_id = 1, | ||
122 | + .fields = (VMStateField[]) { | ||
123 | + VMSTATE_UINT8_ARRAY(rx_fifo, SiFiveUARTState, | ||
124 | + SIFIVE_UART_RX_FIFO_SIZE), | ||
125 | + VMSTATE_UINT8(rx_fifo_len, SiFiveUARTState), | ||
126 | + VMSTATE_UINT32(ie, SiFiveUARTState), | ||
127 | + VMSTATE_UINT32(ip, SiFiveUARTState), | ||
128 | + VMSTATE_UINT32(txctrl, SiFiveUARTState), | ||
129 | + VMSTATE_UINT32(rxctrl, SiFiveUARTState), | ||
130 | + VMSTATE_UINT32(div, SiFiveUARTState), | ||
131 | + VMSTATE_END_OF_LIST() | ||
132 | + }, | ||
133 | +}; | ||
134 | + | ||
135 | + | ||
136 | +static void sifive_uart_class_init(ObjectClass *oc, void *data) | ||
137 | +{ | ||
138 | + DeviceClass *dc = DEVICE_CLASS(oc); | ||
139 | + ResettableClass *rc = RESETTABLE_CLASS(oc); | ||
140 | + | ||
141 | + dc->realize = sifive_uart_realize; | ||
142 | + dc->vmsd = &vmstate_sifive_uart; | ||
143 | + rc->phases.enter = sifive_uart_reset_enter; | ||
144 | + rc->phases.hold = sifive_uart_reset_hold; | ||
145 | + device_class_set_props(dc, sifive_uart_properties); | ||
146 | +} | ||
147 | + | ||
148 | +static const TypeInfo sifive_uart_info = { | ||
149 | + .name = TYPE_SIFIVE_UART, | ||
150 | + .parent = TYPE_SYS_BUS_DEVICE, | ||
151 | + .instance_size = sizeof(SiFiveUARTState), | ||
152 | + .instance_init = sifive_uart_init, | ||
153 | + .class_init = sifive_uart_class_init, | ||
154 | +}; | ||
155 | + | ||
156 | +static void sifive_uart_register_types(void) | ||
157 | +{ | ||
158 | + type_register_static(&sifive_uart_info); | ||
159 | +} | ||
160 | + | ||
161 | +type_init(sifive_uart_register_types) | ||
162 | + | ||
163 | /* | ||
164 | * Create UART device. | ||
165 | */ | ||
166 | SiFiveUARTState *sifive_uart_create(MemoryRegion *address_space, hwaddr base, | ||
167 | Chardev *chr, qemu_irq irq) | ||
168 | { | ||
169 | - SiFiveUARTState *s = g_malloc0(sizeof(SiFiveUARTState)); | ||
170 | - s->irq = irq; | ||
171 | - qemu_chr_fe_init(&s->chr, chr, &error_abort); | ||
172 | - qemu_chr_fe_set_handlers(&s->chr, sifive_uart_can_rx, sifive_uart_rx, | ||
173 | - sifive_uart_event, sifive_uart_be_change, s, | ||
174 | - NULL, true); | ||
175 | - memory_region_init_io(&s->mmio, NULL, &sifive_uart_ops, s, | ||
176 | - TYPE_SIFIVE_UART, SIFIVE_UART_MAX); | ||
177 | - memory_region_add_subregion(address_space, base, &s->mmio); | ||
178 | - return s; | ||
179 | + DeviceState *dev; | ||
180 | + SysBusDevice *s; | ||
181 | + SiFiveUARTState *r; | ||
182 | + | ||
183 | + dev = qdev_new("riscv.sifive.uart"); | ||
184 | + s = SYS_BUS_DEVICE(dev); | ||
185 | + qdev_prop_set_chr(dev, "chardev", chr); | ||
186 | + sysbus_realize_and_unref(s, &error_fatal); | ||
187 | + memory_region_add_subregion(address_space, base, | ||
188 | + sysbus_mmio_get_region(s, 0)); | ||
189 | + sysbus_connect_irq(s, 0, irq); | ||
190 | + | ||
191 | + r = SIFIVE_UART(dev); | ||
192 | + return r; | ||
193 | } | ||
194 | -- | ||
195 | 2.31.1 | ||
196 | |||
197 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | We don't need to expose the register layout in the public header, so | ||
2 | don't. | ||
3 | 1 | ||
4 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | ||
5 | Reviewed-by: Bin Meng <bmeng.cn@gmail.com> | ||
6 | Message-id: c437f570b2b30ab4170387a3ba2fad7d116a4986.1624001156.git.alistair.francis@wdc.com | ||
7 | --- | ||
8 | include/hw/char/ibex_uart.h | 37 ------------------------------------- | ||
9 | hw/char/ibex_uart.c | 37 +++++++++++++++++++++++++++++++++++++ | ||
10 | 2 files changed, 37 insertions(+), 37 deletions(-) | ||
11 | |||
12 | diff --git a/include/hw/char/ibex_uart.h b/include/hw/char/ibex_uart.h | ||
13 | index XXXXXXX..XXXXXXX 100644 | ||
14 | --- a/include/hw/char/ibex_uart.h | ||
15 | +++ b/include/hw/char/ibex_uart.h | ||
16 | @@ -XXX,XX +XXX,XX @@ | ||
17 | #include "qemu/timer.h" | ||
18 | #include "qom/object.h" | ||
19 | |||
20 | -REG32(INTR_STATE, 0x00) | ||
21 | - FIELD(INTR_STATE, TX_WATERMARK, 0, 1) | ||
22 | - FIELD(INTR_STATE, RX_WATERMARK, 1, 1) | ||
23 | - FIELD(INTR_STATE, TX_EMPTY, 2, 1) | ||
24 | - FIELD(INTR_STATE, RX_OVERFLOW, 3, 1) | ||
25 | -REG32(INTR_ENABLE, 0x04) | ||
26 | -REG32(INTR_TEST, 0x08) | ||
27 | -REG32(CTRL, 0x0C) | ||
28 | - FIELD(CTRL, TX_ENABLE, 0, 1) | ||
29 | - FIELD(CTRL, RX_ENABLE, 1, 1) | ||
30 | - FIELD(CTRL, NF, 2, 1) | ||
31 | - FIELD(CTRL, SLPBK, 4, 1) | ||
32 | - FIELD(CTRL, LLPBK, 5, 1) | ||
33 | - FIELD(CTRL, PARITY_EN, 6, 1) | ||
34 | - FIELD(CTRL, PARITY_ODD, 7, 1) | ||
35 | - FIELD(CTRL, RXBLVL, 8, 2) | ||
36 | - FIELD(CTRL, NCO, 16, 16) | ||
37 | -REG32(STATUS, 0x10) | ||
38 | - FIELD(STATUS, TXFULL, 0, 1) | ||
39 | - FIELD(STATUS, RXFULL, 1, 1) | ||
40 | - FIELD(STATUS, TXEMPTY, 2, 1) | ||
41 | - FIELD(STATUS, RXIDLE, 4, 1) | ||
42 | - FIELD(STATUS, RXEMPTY, 5, 1) | ||
43 | -REG32(RDATA, 0x14) | ||
44 | -REG32(WDATA, 0x18) | ||
45 | -REG32(FIFO_CTRL, 0x1c) | ||
46 | - FIELD(FIFO_CTRL, RXRST, 0, 1) | ||
47 | - FIELD(FIFO_CTRL, TXRST, 1, 1) | ||
48 | - FIELD(FIFO_CTRL, RXILVL, 2, 3) | ||
49 | - FIELD(FIFO_CTRL, TXILVL, 5, 2) | ||
50 | -REG32(FIFO_STATUS, 0x20) | ||
51 | - FIELD(FIFO_STATUS, TXLVL, 0, 5) | ||
52 | - FIELD(FIFO_STATUS, RXLVL, 16, 5) | ||
53 | -REG32(OVRD, 0x24) | ||
54 | -REG32(VAL, 0x28) | ||
55 | -REG32(TIMEOUT_CTRL, 0x2c) | ||
56 | - | ||
57 | #define IBEX_UART_TX_FIFO_SIZE 16 | ||
58 | #define IBEX_UART_CLOCK 50000000 /* 50MHz clock */ | ||
59 | |||
60 | diff --git a/hw/char/ibex_uart.c b/hw/char/ibex_uart.c | ||
61 | index XXXXXXX..XXXXXXX 100644 | ||
62 | --- a/hw/char/ibex_uart.c | ||
63 | +++ b/hw/char/ibex_uart.c | ||
64 | @@ -XXX,XX +XXX,XX @@ | ||
65 | #include "qemu/log.h" | ||
66 | #include "qemu/module.h" | ||
67 | |||
68 | +REG32(INTR_STATE, 0x00) | ||
69 | + FIELD(INTR_STATE, TX_WATERMARK, 0, 1) | ||
70 | + FIELD(INTR_STATE, RX_WATERMARK, 1, 1) | ||
71 | + FIELD(INTR_STATE, TX_EMPTY, 2, 1) | ||
72 | + FIELD(INTR_STATE, RX_OVERFLOW, 3, 1) | ||
73 | +REG32(INTR_ENABLE, 0x04) | ||
74 | +REG32(INTR_TEST, 0x08) | ||
75 | +REG32(CTRL, 0x0C) | ||
76 | + FIELD(CTRL, TX_ENABLE, 0, 1) | ||
77 | + FIELD(CTRL, RX_ENABLE, 1, 1) | ||
78 | + FIELD(CTRL, NF, 2, 1) | ||
79 | + FIELD(CTRL, SLPBK, 4, 1) | ||
80 | + FIELD(CTRL, LLPBK, 5, 1) | ||
81 | + FIELD(CTRL, PARITY_EN, 6, 1) | ||
82 | + FIELD(CTRL, PARITY_ODD, 7, 1) | ||
83 | + FIELD(CTRL, RXBLVL, 8, 2) | ||
84 | + FIELD(CTRL, NCO, 16, 16) | ||
85 | +REG32(STATUS, 0x10) | ||
86 | + FIELD(STATUS, TXFULL, 0, 1) | ||
87 | + FIELD(STATUS, RXFULL, 1, 1) | ||
88 | + FIELD(STATUS, TXEMPTY, 2, 1) | ||
89 | + FIELD(STATUS, RXIDLE, 4, 1) | ||
90 | + FIELD(STATUS, RXEMPTY, 5, 1) | ||
91 | +REG32(RDATA, 0x14) | ||
92 | +REG32(WDATA, 0x18) | ||
93 | +REG32(FIFO_CTRL, 0x1c) | ||
94 | + FIELD(FIFO_CTRL, RXRST, 0, 1) | ||
95 | + FIELD(FIFO_CTRL, TXRST, 1, 1) | ||
96 | + FIELD(FIFO_CTRL, RXILVL, 2, 3) | ||
97 | + FIELD(FIFO_CTRL, TXILVL, 5, 2) | ||
98 | +REG32(FIFO_STATUS, 0x20) | ||
99 | + FIELD(FIFO_STATUS, TXLVL, 0, 5) | ||
100 | + FIELD(FIFO_STATUS, RXLVL, 16, 5) | ||
101 | +REG32(OVRD, 0x24) | ||
102 | +REG32(VAL, 0x28) | ||
103 | +REG32(TIMEOUT_CTRL, 0x2c) | ||
104 | + | ||
105 | static void ibex_uart_update_irqs(IbexUartState *s) | ||
106 | { | ||
107 | if (s->uart_intr_state & s->uart_intr_enable & R_INTR_STATE_TX_WATERMARK_MASK) { | ||
108 | -- | ||
109 | 2.31.1 | ||
110 | |||
111 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Add support for the Ibex timer. This is used with the RISC-V | ||
2 | mtime/mtimecmp similar to the SiFive CLINT. | ||
3 | 1 | ||
4 | We currently don't support changing the prescale or the timervalue. | ||
5 | |||
6 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | ||
7 | Reviewed-by: Bin Meng <bmeng.cn@gmail.com> | ||
8 | Message-id: 716fdea2244515ce86a2c46fe69467d013c03147.1624001156.git.alistair.francis@wdc.com | ||
9 | --- | ||
10 | include/hw/timer/ibex_timer.h | 52 ++++++ | ||
11 | hw/timer/ibex_timer.c | 305 ++++++++++++++++++++++++++++++++++ | ||
12 | MAINTAINERS | 6 +- | ||
13 | hw/timer/meson.build | 1 + | ||
14 | 4 files changed, 360 insertions(+), 4 deletions(-) | ||
15 | create mode 100644 include/hw/timer/ibex_timer.h | ||
16 | create mode 100644 hw/timer/ibex_timer.c | ||
17 | |||
18 | diff --git a/include/hw/timer/ibex_timer.h b/include/hw/timer/ibex_timer.h | ||
19 | new file mode 100644 | ||
20 | index XXXXXXX..XXXXXXX | ||
21 | --- /dev/null | ||
22 | +++ b/include/hw/timer/ibex_timer.h | ||
23 | @@ -XXX,XX +XXX,XX @@ | ||
24 | +/* | ||
25 | + * QEMU lowRISC Ibex Timer device | ||
26 | + * | ||
27 | + * Copyright (c) 2021 Western Digital | ||
28 | + * | ||
29 | + * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
30 | + * of this software and associated documentation files (the "Software"), to deal | ||
31 | + * in the Software without restriction, including without limitation the rights | ||
32 | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
33 | + * copies of the Software, and to permit persons to whom the Software is | ||
34 | + * furnished to do so, subject to the following conditions: | ||
35 | + * | ||
36 | + * The above copyright notice and this permission notice shall be included in | ||
37 | + * all copies or substantial portions of the Software. | ||
38 | + * | ||
39 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
40 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
41 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
42 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
43 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
44 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
45 | + * THE SOFTWARE. | ||
46 | + */ | ||
47 | + | ||
48 | +#ifndef HW_IBEX_TIMER_H | ||
49 | +#define HW_IBEX_TIMER_H | ||
50 | + | ||
51 | +#include "hw/sysbus.h" | ||
52 | + | ||
53 | +#define TYPE_IBEX_TIMER "ibex-timer" | ||
54 | +OBJECT_DECLARE_SIMPLE_TYPE(IbexTimerState, IBEX_TIMER) | ||
55 | + | ||
56 | +struct IbexTimerState { | ||
57 | + /* <private> */ | ||
58 | + SysBusDevice parent_obj; | ||
59 | + | ||
60 | + /* <public> */ | ||
61 | + MemoryRegion mmio; | ||
62 | + | ||
63 | + uint32_t timer_ctrl; | ||
64 | + uint32_t timer_cfg0; | ||
65 | + uint32_t timer_compare_lower0; | ||
66 | + uint32_t timer_compare_upper0; | ||
67 | + uint32_t timer_intr_enable; | ||
68 | + uint32_t timer_intr_state; | ||
69 | + uint32_t timer_intr_test; | ||
70 | + | ||
71 | + uint32_t timebase_freq; | ||
72 | + | ||
73 | + qemu_irq irq; | ||
74 | +}; | ||
75 | +#endif /* HW_IBEX_TIMER_H */ | ||
76 | diff --git a/hw/timer/ibex_timer.c b/hw/timer/ibex_timer.c | ||
77 | new file mode 100644 | ||
78 | index XXXXXXX..XXXXXXX | ||
79 | --- /dev/null | ||
80 | +++ b/hw/timer/ibex_timer.c | ||
81 | @@ -XXX,XX +XXX,XX @@ | ||
82 | +/* | ||
83 | + * QEMU lowRISC Ibex Timer device | ||
84 | + * | ||
85 | + * Copyright (c) 2021 Western Digital | ||
86 | + * | ||
87 | + * For details check the documentation here: | ||
88 | + * https://docs.opentitan.org/hw/ip/rv_timer/doc/ | ||
89 | + * | ||
90 | + * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
91 | + * of this software and associated documentation files (the "Software"), to deal | ||
92 | + * in the Software without restriction, including without limitation the rights | ||
93 | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
94 | + * copies of the Software, and to permit persons to whom the Software is | ||
95 | + * furnished to do so, subject to the following conditions: | ||
96 | + * | ||
97 | + * The above copyright notice and this permission notice shall be included in | ||
98 | + * all copies or substantial portions of the Software. | ||
99 | + * | ||
100 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
101 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
102 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
103 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
104 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
105 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
106 | + * THE SOFTWARE. | ||
107 | + */ | ||
108 | + | ||
109 | +#include "qemu/osdep.h" | ||
110 | +#include "qemu/log.h" | ||
111 | +#include "qemu/timer.h" | ||
112 | +#include "hw/timer/ibex_timer.h" | ||
113 | +#include "hw/irq.h" | ||
114 | +#include "hw/qdev-properties.h" | ||
115 | +#include "target/riscv/cpu.h" | ||
116 | +#include "migration/vmstate.h" | ||
117 | + | ||
118 | +REG32(CTRL, 0x00) | ||
119 | + FIELD(CTRL, ACTIVE, 0, 1) | ||
120 | +REG32(CFG0, 0x100) | ||
121 | + FIELD(CFG0, PRESCALE, 0, 12) | ||
122 | + FIELD(CFG0, STEP, 16, 8) | ||
123 | +REG32(LOWER0, 0x104) | ||
124 | +REG32(UPPER0, 0x108) | ||
125 | +REG32(COMPARE_LOWER0, 0x10C) | ||
126 | +REG32(COMPARE_UPPER0, 0x110) | ||
127 | +REG32(INTR_ENABLE, 0x114) | ||
128 | + FIELD(INTR_ENABLE, IE_0, 0, 1) | ||
129 | +REG32(INTR_STATE, 0x118) | ||
130 | + FIELD(INTR_STATE, IS_0, 0, 1) | ||
131 | +REG32(INTR_TEST, 0x11C) | ||
132 | + FIELD(INTR_TEST, T_0, 0, 1) | ||
133 | + | ||
134 | +static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq) | ||
135 | +{ | ||
136 | + return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), | ||
137 | + timebase_freq, NANOSECONDS_PER_SECOND); | ||
138 | +} | ||
139 | + | ||
140 | +static void ibex_timer_update_irqs(IbexTimerState *s) | ||
141 | +{ | ||
142 | + CPUState *cs = qemu_get_cpu(0); | ||
143 | + RISCVCPU *cpu = RISCV_CPU(cs); | ||
144 | + uint64_t value = s->timer_compare_lower0 | | ||
145 | + ((uint64_t)s->timer_compare_upper0 << 32); | ||
146 | + uint64_t next, diff; | ||
147 | + uint64_t now = cpu_riscv_read_rtc(s->timebase_freq); | ||
148 | + | ||
149 | + if (!(s->timer_ctrl & R_CTRL_ACTIVE_MASK)) { | ||
150 | + /* Timer isn't active */ | ||
151 | + return; | ||
152 | + } | ||
153 | + | ||
154 | + /* Update the CPUs mtimecmp */ | ||
155 | + cpu->env.timecmp = value; | ||
156 | + | ||
157 | + if (cpu->env.timecmp <= now) { | ||
158 | + /* | ||
159 | + * If the mtimecmp was in the past raise the interrupt now. | ||
160 | + */ | ||
161 | + riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1)); | ||
162 | + if (s->timer_intr_enable & R_INTR_ENABLE_IE_0_MASK) { | ||
163 | + s->timer_intr_state |= R_INTR_STATE_IS_0_MASK; | ||
164 | + qemu_set_irq(s->irq, true); | ||
165 | + } | ||
166 | + return; | ||
167 | + } | ||
168 | + | ||
169 | + /* Setup a timer to trigger the interrupt in the future */ | ||
170 | + riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(0)); | ||
171 | + qemu_set_irq(s->irq, false); | ||
172 | + | ||
173 | + diff = cpu->env.timecmp - now; | ||
174 | + next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + | ||
175 | + muldiv64(diff, | ||
176 | + NANOSECONDS_PER_SECOND, | ||
177 | + s->timebase_freq); | ||
178 | + | ||
179 | + if (next < qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)) { | ||
180 | + /* We overflowed the timer, just set it as large as we can */ | ||
181 | + timer_mod(cpu->env.timer, 0x7FFFFFFFFFFFFFFF); | ||
182 | + } else { | ||
183 | + timer_mod(cpu->env.timer, next); | ||
184 | + } | ||
185 | +} | ||
186 | + | ||
187 | +static void ibex_timer_cb(void *opaque) | ||
188 | +{ | ||
189 | + IbexTimerState *s = opaque; | ||
190 | + CPUState *cs = qemu_get_cpu(0); | ||
191 | + RISCVCPU *cpu = RISCV_CPU(cs); | ||
192 | + | ||
193 | + riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1)); | ||
194 | + if (s->timer_intr_enable & R_INTR_ENABLE_IE_0_MASK) { | ||
195 | + s->timer_intr_state |= R_INTR_STATE_IS_0_MASK; | ||
196 | + qemu_set_irq(s->irq, true); | ||
197 | + } | ||
198 | +} | ||
199 | + | ||
200 | +static void ibex_timer_reset(DeviceState *dev) | ||
201 | +{ | ||
202 | + IbexTimerState *s = IBEX_TIMER(dev); | ||
203 | + | ||
204 | + CPUState *cpu = qemu_get_cpu(0); | ||
205 | + CPURISCVState *env = cpu->env_ptr; | ||
206 | + env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, | ||
207 | + &ibex_timer_cb, s); | ||
208 | + env->timecmp = 0; | ||
209 | + | ||
210 | + s->timer_ctrl = 0x00000000; | ||
211 | + s->timer_cfg0 = 0x00010000; | ||
212 | + s->timer_compare_lower0 = 0xFFFFFFFF; | ||
213 | + s->timer_compare_upper0 = 0xFFFFFFFF; | ||
214 | + s->timer_intr_enable = 0x00000000; | ||
215 | + s->timer_intr_state = 0x00000000; | ||
216 | + s->timer_intr_test = 0x00000000; | ||
217 | + | ||
218 | + ibex_timer_update_irqs(s); | ||
219 | +} | ||
220 | + | ||
221 | +static uint64_t ibex_timer_read(void *opaque, hwaddr addr, | ||
222 | + unsigned int size) | ||
223 | +{ | ||
224 | + IbexTimerState *s = opaque; | ||
225 | + uint64_t now = cpu_riscv_read_rtc(s->timebase_freq); | ||
226 | + uint64_t retvalue = 0; | ||
227 | + | ||
228 | + switch (addr >> 2) { | ||
229 | + case R_CTRL: | ||
230 | + retvalue = s->timer_ctrl; | ||
231 | + break; | ||
232 | + case R_CFG0: | ||
233 | + retvalue = s->timer_cfg0; | ||
234 | + break; | ||
235 | + case R_LOWER0: | ||
236 | + retvalue = now; | ||
237 | + break; | ||
238 | + case R_UPPER0: | ||
239 | + retvalue = now >> 32; | ||
240 | + break; | ||
241 | + case R_COMPARE_LOWER0: | ||
242 | + retvalue = s->timer_compare_lower0; | ||
243 | + break; | ||
244 | + case R_COMPARE_UPPER0: | ||
245 | + retvalue = s->timer_compare_upper0; | ||
246 | + break; | ||
247 | + case R_INTR_ENABLE: | ||
248 | + retvalue = s->timer_intr_enable; | ||
249 | + break; | ||
250 | + case R_INTR_STATE: | ||
251 | + retvalue = s->timer_intr_state; | ||
252 | + break; | ||
253 | + case R_INTR_TEST: | ||
254 | + retvalue = s->timer_intr_test; | ||
255 | + break; | ||
256 | + default: | ||
257 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
258 | + "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr); | ||
259 | + return 0; | ||
260 | + } | ||
261 | + | ||
262 | + return retvalue; | ||
263 | +} | ||
264 | + | ||
265 | +static void ibex_timer_write(void *opaque, hwaddr addr, | ||
266 | + uint64_t val64, unsigned int size) | ||
267 | +{ | ||
268 | + IbexTimerState *s = opaque; | ||
269 | + uint32_t val = val64; | ||
270 | + | ||
271 | + switch (addr >> 2) { | ||
272 | + case R_CTRL: | ||
273 | + s->timer_ctrl = val; | ||
274 | + break; | ||
275 | + case R_CFG0: | ||
276 | + qemu_log_mask(LOG_UNIMP, "Changing prescale or step not supported"); | ||
277 | + s->timer_cfg0 = val; | ||
278 | + break; | ||
279 | + case R_LOWER0: | ||
280 | + qemu_log_mask(LOG_UNIMP, "Changing timer value is not supported"); | ||
281 | + break; | ||
282 | + case R_UPPER0: | ||
283 | + qemu_log_mask(LOG_UNIMP, "Changing timer value is not supported"); | ||
284 | + break; | ||
285 | + case R_COMPARE_LOWER0: | ||
286 | + s->timer_compare_lower0 = val; | ||
287 | + ibex_timer_update_irqs(s); | ||
288 | + break; | ||
289 | + case R_COMPARE_UPPER0: | ||
290 | + s->timer_compare_upper0 = val; | ||
291 | + ibex_timer_update_irqs(s); | ||
292 | + break; | ||
293 | + case R_INTR_ENABLE: | ||
294 | + s->timer_intr_enable = val; | ||
295 | + break; | ||
296 | + case R_INTR_STATE: | ||
297 | + /* Write 1 to clear */ | ||
298 | + s->timer_intr_state &= ~val; | ||
299 | + break; | ||
300 | + case R_INTR_TEST: | ||
301 | + s->timer_intr_test = val; | ||
302 | + if (s->timer_intr_enable & | ||
303 | + s->timer_intr_test & | ||
304 | + R_INTR_ENABLE_IE_0_MASK) { | ||
305 | + s->timer_intr_state |= R_INTR_STATE_IS_0_MASK; | ||
306 | + qemu_set_irq(s->irq, true); | ||
307 | + } | ||
308 | + break; | ||
309 | + default: | ||
310 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
311 | + "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr); | ||
312 | + } | ||
313 | +} | ||
314 | + | ||
315 | +static const MemoryRegionOps ibex_timer_ops = { | ||
316 | + .read = ibex_timer_read, | ||
317 | + .write = ibex_timer_write, | ||
318 | + .endianness = DEVICE_NATIVE_ENDIAN, | ||
319 | + .impl.min_access_size = 4, | ||
320 | + .impl.max_access_size = 4, | ||
321 | +}; | ||
322 | + | ||
323 | +static int ibex_timer_post_load(void *opaque, int version_id) | ||
324 | +{ | ||
325 | + IbexTimerState *s = opaque; | ||
326 | + | ||
327 | + ibex_timer_update_irqs(s); | ||
328 | + return 0; | ||
329 | +} | ||
330 | + | ||
331 | +static const VMStateDescription vmstate_ibex_timer = { | ||
332 | + .name = TYPE_IBEX_TIMER, | ||
333 | + .version_id = 1, | ||
334 | + .minimum_version_id = 1, | ||
335 | + .post_load = ibex_timer_post_load, | ||
336 | + .fields = (VMStateField[]) { | ||
337 | + VMSTATE_UINT32(timer_ctrl, IbexTimerState), | ||
338 | + VMSTATE_UINT32(timer_cfg0, IbexTimerState), | ||
339 | + VMSTATE_UINT32(timer_compare_lower0, IbexTimerState), | ||
340 | + VMSTATE_UINT32(timer_compare_upper0, IbexTimerState), | ||
341 | + VMSTATE_UINT32(timer_intr_enable, IbexTimerState), | ||
342 | + VMSTATE_UINT32(timer_intr_state, IbexTimerState), | ||
343 | + VMSTATE_UINT32(timer_intr_test, IbexTimerState), | ||
344 | + VMSTATE_END_OF_LIST() | ||
345 | + } | ||
346 | +}; | ||
347 | + | ||
348 | +static Property ibex_timer_properties[] = { | ||
349 | + DEFINE_PROP_UINT32("timebase-freq", IbexTimerState, timebase_freq, 10000), | ||
350 | + DEFINE_PROP_END_OF_LIST(), | ||
351 | +}; | ||
352 | + | ||
353 | +static void ibex_timer_init(Object *obj) | ||
354 | +{ | ||
355 | + IbexTimerState *s = IBEX_TIMER(obj); | ||
356 | + | ||
357 | + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); | ||
358 | + | ||
359 | + memory_region_init_io(&s->mmio, obj, &ibex_timer_ops, s, | ||
360 | + TYPE_IBEX_TIMER, 0x400); | ||
361 | + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); | ||
362 | +} | ||
363 | + | ||
364 | +static void ibex_timer_class_init(ObjectClass *klass, void *data) | ||
365 | +{ | ||
366 | + DeviceClass *dc = DEVICE_CLASS(klass); | ||
367 | + | ||
368 | + dc->reset = ibex_timer_reset; | ||
369 | + dc->vmsd = &vmstate_ibex_timer; | ||
370 | + device_class_set_props(dc, ibex_timer_properties); | ||
371 | +} | ||
372 | + | ||
373 | +static const TypeInfo ibex_timer_info = { | ||
374 | + .name = TYPE_IBEX_TIMER, | ||
375 | + .parent = TYPE_SYS_BUS_DEVICE, | ||
376 | + .instance_size = sizeof(IbexTimerState), | ||
377 | + .instance_init = ibex_timer_init, | ||
378 | + .class_init = ibex_timer_class_init, | ||
379 | +}; | ||
380 | + | ||
381 | +static void ibex_timer_register_types(void) | ||
382 | +{ | ||
383 | + type_register_static(&ibex_timer_info); | ||
384 | +} | ||
385 | + | ||
386 | +type_init(ibex_timer_register_types) | ||
387 | diff --git a/MAINTAINERS b/MAINTAINERS | ||
388 | index XXXXXXX..XXXXXXX 100644 | ||
389 | --- a/MAINTAINERS | ||
390 | +++ b/MAINTAINERS | ||
391 | @@ -XXX,XX +XXX,XX @@ M: Alistair Francis <Alistair.Francis@wdc.com> | ||
392 | L: qemu-riscv@nongnu.org | ||
393 | S: Supported | ||
394 | F: hw/riscv/opentitan.c | ||
395 | -F: hw/char/ibex_uart.c | ||
396 | -F: hw/intc/ibex_plic.c | ||
397 | +F: hw/*/ibex_*.c | ||
398 | F: include/hw/riscv/opentitan.h | ||
399 | -F: include/hw/char/ibex_uart.h | ||
400 | -F: include/hw/intc/ibex_plic.h | ||
401 | +F: include/hw/*/ibex_*.h | ||
402 | |||
403 | Microchip PolarFire SoC Icicle Kit | ||
404 | M: Bin Meng <bin.meng@windriver.com> | ||
405 | diff --git a/hw/timer/meson.build b/hw/timer/meson.build | ||
406 | index XXXXXXX..XXXXXXX 100644 | ||
407 | --- a/hw/timer/meson.build | ||
408 | +++ b/hw/timer/meson.build | ||
409 | @@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_SSE_COUNTER', if_true: files('sse-counter.c')) | ||
410 | softmmu_ss.add(when: 'CONFIG_SSE_TIMER', if_true: files('sse-timer.c')) | ||
411 | softmmu_ss.add(when: 'CONFIG_STM32F2XX_TIMER', if_true: files('stm32f2xx_timer.c')) | ||
412 | softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_timer.c')) | ||
413 | +specific_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_timer.c')) | ||
414 | |||
415 | specific_ss.add(when: 'CONFIG_AVR_TIMER16', if_true: files('avr_timer16.c')) | ||
416 | -- | ||
417 | 2.31.1 | ||
418 | |||
419 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Connect the Ibex timer to the OpenTitan machine. The timer can trigger | ||
2 | the RISC-V MIE interrupt as well as a custom device interrupt. | ||
3 | 1 | ||
4 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | ||
5 | Reviewed-by: Bin Meng <bmeng.cn@gmail.com> | ||
6 | Message-id: 5e7f4e9b4537f863bcb8db1264b840b56ef2a929.1624001156.git.alistair.francis@wdc.com | ||
7 | --- | ||
8 | include/hw/riscv/opentitan.h | 5 ++++- | ||
9 | hw/riscv/opentitan.c | 14 +++++++++++--- | ||
10 | 2 files changed, 15 insertions(+), 4 deletions(-) | ||
11 | |||
12 | diff --git a/include/hw/riscv/opentitan.h b/include/hw/riscv/opentitan.h | ||
13 | index XXXXXXX..XXXXXXX 100644 | ||
14 | --- a/include/hw/riscv/opentitan.h | ||
15 | +++ b/include/hw/riscv/opentitan.h | ||
16 | @@ -XXX,XX +XXX,XX @@ | ||
17 | #include "hw/riscv/riscv_hart.h" | ||
18 | #include "hw/intc/ibex_plic.h" | ||
19 | #include "hw/char/ibex_uart.h" | ||
20 | +#include "hw/timer/ibex_timer.h" | ||
21 | #include "qom/object.h" | ||
22 | |||
23 | #define TYPE_RISCV_IBEX_SOC "riscv.lowrisc.ibex.soc" | ||
24 | @@ -XXX,XX +XXX,XX @@ struct LowRISCIbexSoCState { | ||
25 | RISCVHartArrayState cpus; | ||
26 | IbexPlicState plic; | ||
27 | IbexUartState uart; | ||
28 | + IbexTimerState timer; | ||
29 | |||
30 | MemoryRegion flash_mem; | ||
31 | MemoryRegion rom; | ||
32 | @@ -XXX,XX +XXX,XX @@ enum { | ||
33 | IBEX_DEV_SPI, | ||
34 | IBEX_DEV_I2C, | ||
35 | IBEX_DEV_PATTGEN, | ||
36 | - IBEX_DEV_RV_TIMER, | ||
37 | + IBEX_DEV_TIMER, | ||
38 | IBEX_DEV_SENSOR_CTRL, | ||
39 | IBEX_DEV_OTP_CTRL, | ||
40 | IBEX_DEV_PWRMGR, | ||
41 | @@ -XXX,XX +XXX,XX @@ enum { | ||
42 | }; | ||
43 | |||
44 | enum { | ||
45 | + IBEX_TIMER_TIMEREXPIRED0_0 = 125, | ||
46 | IBEX_UART0_RX_PARITY_ERR_IRQ = 8, | ||
47 | IBEX_UART0_RX_TIMEOUT_IRQ = 7, | ||
48 | IBEX_UART0_RX_BREAK_ERR_IRQ = 6, | ||
49 | diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c | ||
50 | index XXXXXXX..XXXXXXX 100644 | ||
51 | --- a/hw/riscv/opentitan.c | ||
52 | +++ b/hw/riscv/opentitan.c | ||
53 | @@ -XXX,XX +XXX,XX @@ static const MemMapEntry ibex_memmap[] = { | ||
54 | [IBEX_DEV_SPI] = { 0x40050000, 0x1000 }, | ||
55 | [IBEX_DEV_I2C] = { 0x40080000, 0x1000 }, | ||
56 | [IBEX_DEV_PATTGEN] = { 0x400e0000, 0x1000 }, | ||
57 | - [IBEX_DEV_RV_TIMER] = { 0x40100000, 0x1000 }, | ||
58 | + [IBEX_DEV_TIMER] = { 0x40100000, 0x1000 }, | ||
59 | [IBEX_DEV_SENSOR_CTRL] = { 0x40110000, 0x1000 }, | ||
60 | [IBEX_DEV_OTP_CTRL] = { 0x40130000, 0x4000 }, | ||
61 | [IBEX_DEV_PWRMGR] = { 0x40400000, 0x1000 }, | ||
62 | @@ -XXX,XX +XXX,XX @@ static void lowrisc_ibex_soc_init(Object *obj) | ||
63 | object_initialize_child(obj, "plic", &s->plic, TYPE_IBEX_PLIC); | ||
64 | |||
65 | object_initialize_child(obj, "uart", &s->uart, TYPE_IBEX_UART); | ||
66 | + | ||
67 | + object_initialize_child(obj, "timer", &s->timer, TYPE_IBEX_TIMER); | ||
68 | } | ||
69 | |||
70 | static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp) | ||
71 | @@ -XXX,XX +XXX,XX @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp) | ||
72 | 3, qdev_get_gpio_in(DEVICE(&s->plic), | ||
73 | IBEX_UART0_RX_OVERFLOW_IRQ)); | ||
74 | |||
75 | + if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer), errp)) { | ||
76 | + return; | ||
77 | + } | ||
78 | + sysbus_mmio_map(SYS_BUS_DEVICE(&s->timer), 0, memmap[IBEX_DEV_TIMER].base); | ||
79 | + sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer), | ||
80 | + 0, qdev_get_gpio_in(DEVICE(&s->plic), | ||
81 | + IBEX_TIMER_TIMEREXPIRED0_0)); | ||
82 | + | ||
83 | create_unimplemented_device("riscv.lowrisc.ibex.gpio", | ||
84 | memmap[IBEX_DEV_GPIO].base, memmap[IBEX_DEV_GPIO].size); | ||
85 | create_unimplemented_device("riscv.lowrisc.ibex.spi", | ||
86 | @@ -XXX,XX +XXX,XX @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp) | ||
87 | memmap[IBEX_DEV_I2C].base, memmap[IBEX_DEV_I2C].size); | ||
88 | create_unimplemented_device("riscv.lowrisc.ibex.pattgen", | ||
89 | memmap[IBEX_DEV_PATTGEN].base, memmap[IBEX_DEV_PATTGEN].size); | ||
90 | - create_unimplemented_device("riscv.lowrisc.ibex.rv_timer", | ||
91 | - memmap[IBEX_DEV_RV_TIMER].base, memmap[IBEX_DEV_RV_TIMER].size); | ||
92 | create_unimplemented_device("riscv.lowrisc.ibex.sensor_ctrl", | ||
93 | memmap[IBEX_DEV_SENSOR_CTRL].base, memmap[IBEX_DEV_SENSOR_CTRL].size); | ||
94 | create_unimplemented_device("riscv.lowrisc.ibex.otp_ctrl", | ||
95 | -- | ||
96 | 2.31.1 | ||
97 | |||
98 | diff view generated by jsdifflib |