1 | target-arm queue. This has the "plumb txattrs through various | 1 | The following changes since commit b367db48126d4ee14579af6cf5cdbffeb9496627: |
---|---|---|---|
2 | bits of exec.c" patches, and a collection of bug fixes from | ||
3 | various people. | ||
4 | 2 | ||
5 | v2: fix compile error on arm hosts... | 3 | Merge remote-tracking branch 'remotes/aperard/tags/pull-xen-20220127' into staging (2022-01-28 11:05:29 +0000) |
6 | |||
7 | thanks | ||
8 | -- PMM | ||
9 | |||
10 | |||
11 | The following changes since commit a3ac12fba028df90f7b3dbec924995c126c41022: | ||
12 | |||
13 | Merge remote-tracking branch 'remotes/ehabkost/tags/numa-next-pull-request' into staging (2018-05-31 11:12:36 +0100) | ||
14 | 4 | ||
15 | are available in the Git repository at: | 5 | are available in the Git repository at: |
16 | 6 | ||
17 | git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180531-1 | 7 | https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220128 |
18 | 8 | ||
19 | for you to fetch changes up to 2f15b79280cf71b7991dfd3f0312a1797630e376: | 9 | for you to fetch changes up to 2c023d3675a3ffb54fc30504dcd715bc6f6e234f: |
20 | 10 | ||
21 | KVM: GIC: Fix memory leak due to calling kvm_init_irq_routing twice (2018-05-31 16:32:35 +0100) | 11 | target/arm: Use correct entrypoint for SVC taken from Hyp to Hyp (2022-01-28 14:30:36 +0000) |
22 | 12 | ||
23 | ---------------------------------------------------------------- | 13 | ---------------------------------------------------------------- |
24 | target-arm queue: | 14 | target-arm queue: |
25 | * target/arm: Honour FPCR.FZ in FRECPX | 15 | * Update copyright dates to 2022 |
26 | * MAINTAINERS: Add entries for newer MPS2 boards and devices | 16 | * hw/armv7m: Fix broken VMStateDescription |
27 | * hw/intc/arm_gicv3: Fix APxR<n> register dispatching | 17 | * hw/char/exynos4210_uart: Fix crash on trying to load VM state |
28 | * arm_gicv3_kvm: fix bug in writing zero bits back to the in-kernel | 18 | * rtc: Move RTC function prototypes to their own header |
29 | GIC state | 19 | * xlnx-versal-virt: Support PMC SLCR |
30 | * tcg: Fix helper function vs host abi for float16 | 20 | * xlnx-versal-virt: Support OSPI flash memory controller |
31 | * arm: fix qemu crash on startup with -bios option | 21 | * scripts: Explain the difference between linux-headers and standard-headers |
32 | * arm: fix malloc type mismatch | 22 | * target/arm: Log CPU index in 'Taking exception' log |
33 | * xlnx-zdma: Correct mem leaks and memset to zero on desc unaligned errors | 23 | * arm_gicv3_its: Various bugfixes and cleanups |
34 | * Correct CPACR reset value for v7 cores | 24 | * arm_gicv3_its: Implement the missing MOVI and MOVALL commands |
35 | * memory.h: Improve IOMMU related documentation | 25 | * ast2600: Fix address mapping of second SPI controller |
36 | * exec: Plumb transaction attributes through various functions in | 26 | * target/arm: Use correct entrypoint for SVC taken from Hyp to Hyp |
37 | preparation for allowing IOMMUs to see them | ||
38 | * vmstate.h: Provide VMSTATE_BOOL_SUB_ARRAY | ||
39 | * ARM: ACPI: Fix use-after-free due to memory realloc | ||
40 | * KVM: GIC: Fix memory leak due to calling kvm_init_irq_routing twice | ||
41 | 27 | ||
42 | ---------------------------------------------------------------- | 28 | ---------------------------------------------------------------- |
43 | Francisco Iglesias (1): | 29 | Andrew Baumann (1): |
44 | xlnx-zdma: Correct mem leaks and memset to zero on desc unaligned errors | 30 | MAINTAINERS: Remove myself (for raspi). |
45 | 31 | ||
46 | Igor Mammedov (1): | 32 | Cédric Le Goater (1): |
47 | arm: fix qemu crash on startup with -bios option | 33 | hw/arm: ast2600: Fix address mapping of second SPI controller |
48 | 34 | ||
49 | Jan Kiszka (1): | 35 | Francisco Iglesias (10): |
50 | hw/intc/arm_gicv3: Fix APxR<n> register dispatching | 36 | hw/misc: Add a model of Versal's PMC SLCR |
37 | hw/arm/xlnx-versal: 'Or' the interrupts from the BBRAM and RTC models | ||
38 | hw/arm/xlnx-versal: Connect Versal's PMC SLCR | ||
39 | include/hw/dma/xlnx_csu_dma: Add in missing includes in the header | ||
40 | hw/dma/xlnx_csu_dma: Support starting a read transfer through a class method | ||
41 | hw/ssi: Add a model of Xilinx Versal's OSPI flash memory controller | ||
42 | hw/arm/xlnx-versal: Connect the OSPI flash memory controller model | ||
43 | hw/block/m25p80: Add support for Micron Xccela flash mt35xu01g | ||
44 | hw/arm/xlnx-versal-virt: Connect mt35xu01g flashes to the OSPI | ||
45 | MAINTAINERS: Add an entry for Xilinx Versal OSPI | ||
51 | 46 | ||
52 | Paolo Bonzini (1): | 47 | Peter Maydell (20): |
53 | arm: fix malloc type mismatch | 48 | Update copyright dates to 2022 |
49 | hw/armv7m: Fix broken VMStateDescription | ||
50 | hw/char/exynos4210_uart: Fix crash on trying to load VM state | ||
51 | rtc: Move RTC function prototypes to their own header | ||
52 | scripts: Explain the difference between linux-headers and standard-headers | ||
53 | target/arm: Log CPU index in 'Taking exception' log | ||
54 | hw/intc/arm_gicv3_its: Add tracepoints | ||
55 | hw/intc/arm_gicv3: Initialise dma_as in GIC, not ITS | ||
56 | hw/intc/arm_gicv3_its: Don't clear GITS_CREADR when GITS_CTLR.ENABLED is set | ||
57 | hw/intc/arm_gicv3_its: Don't clear GITS_CWRITER on writes to GITS_CBASER | ||
58 | hw/intc/arm_gicv3: Honour GICD_CTLR.EnableGrp1NS for LPIs | ||
59 | hw/intc/arm_gicv3_its: Sort ITS command list into numeric order | ||
60 | hw/intc/arm_gicv3_redist: Remove unnecessary zero checks | ||
61 | hw/intc/arm_gicv3: Set GICR_CTLR.CES if LPIs are supported | ||
62 | hw/intc/arm_gicv3_its: Provide read accessor for translation_ops | ||
63 | hw/intc/arm_gicv3_its: Make GITS_BASER<n> RAZ/WI for unimplemented registers | ||
64 | hw/intc/arm_gicv3_its: Check table bounds against correct limit | ||
65 | hw/intc/arm_gicv3_its: Implement MOVALL | ||
66 | hw/intc/arm_gicv3_its: Implement MOVI | ||
67 | target/arm: Use correct entrypoint for SVC taken from Hyp to Hyp | ||
54 | 68 | ||
55 | Peter Maydell (17): | 69 | docs/conf.py | 2 +- |
56 | target/arm: Honour FPCR.FZ in FRECPX | 70 | hw/intc/gicv3_internal.h | 43 +- |
57 | MAINTAINERS: Add entries for newer MPS2 boards and devices | 71 | include/hw/arm/xlnx-versal.h | 30 +- |
58 | Correct CPACR reset value for v7 cores | 72 | include/hw/dma/xlnx_csu_dma.h | 24 +- |
59 | memory.h: Improve IOMMU related documentation | 73 | include/hw/intc/arm_gicv3_its_common.h | 1 - |
60 | Make tb_invalidate_phys_addr() take a MemTxAttrs argument | 74 | include/hw/misc/xlnx-versal-pmc-iou-slcr.h | 78 ++ |
61 | Make address_space_translate{, _cached}() take a MemTxAttrs argument | 75 | include/hw/ssi/xlnx-versal-ospi.h | 111 ++ |
62 | Make address_space_map() take a MemTxAttrs argument | 76 | include/qemu-common.h | 5 +- |
63 | Make address_space_access_valid() take a MemTxAttrs argument | 77 | include/sysemu/rtc.h | 58 + |
64 | Make flatview_extend_translation() take a MemTxAttrs argument | 78 | target/arm/internals.h | 2 +- |
65 | Make memory_region_access_valid() take a MemTxAttrs argument | 79 | hw/arm/armv7m.c | 4 +- |
66 | Make MemoryRegion valid.accepts callback take a MemTxAttrs argument | 80 | hw/arm/aspeed_ast2600.c | 2 +- |
67 | Make flatview_access_valid() take a MemTxAttrs argument | 81 | hw/arm/omap1.c | 2 +- |
68 | Make flatview_translate() take a MemTxAttrs argument | 82 | hw/arm/pxa2xx.c | 2 +- |
69 | Make address_space_get_iotlb_entry() take a MemTxAttrs argument | 83 | hw/arm/strongarm.c | 2 +- |
70 | Make flatview_do_translate() take a MemTxAttrs argument | 84 | hw/arm/xlnx-versal-virt.c | 25 +- |
71 | Make address_space_translate_iommu take a MemTxAttrs argument | 85 | hw/arm/xlnx-versal.c | 190 ++- |
72 | vmstate.h: Provide VMSTATE_BOOL_SUB_ARRAY | 86 | hw/block/m25p80.c | 2 + |
87 | hw/char/exynos4210_uart.c | 2 +- | ||
88 | hw/dma/xlnx_csu_dma.c | 17 + | ||
89 | hw/intc/arm_gicv3.c | 1 + | ||
90 | hw/intc/arm_gicv3_common.c | 9 + | ||
91 | hw/intc/arm_gicv3_its.c | 258 +++- | ||
92 | hw/intc/arm_gicv3_redist.c | 115 +- | ||
93 | hw/misc/mac_via.c | 2 +- | ||
94 | hw/misc/macio/cuda.c | 2 +- | ||
95 | hw/misc/macio/pmu.c | 2 +- | ||
96 | hw/misc/xlnx-versal-pmc-iou-slcr.c | 1446 ++++++++++++++++++++++ | ||
97 | hw/ppc/spapr_rtc.c | 2 +- | ||
98 | hw/rtc/allwinner-rtc.c | 2 +- | ||
99 | hw/rtc/aspeed_rtc.c | 2 +- | ||
100 | hw/rtc/ds1338.c | 2 +- | ||
101 | hw/rtc/exynos4210_rtc.c | 2 +- | ||
102 | hw/rtc/goldfish_rtc.c | 2 +- | ||
103 | hw/rtc/m41t80.c | 2 +- | ||
104 | hw/rtc/m48t59.c | 2 +- | ||
105 | hw/rtc/mc146818rtc.c | 2 +- | ||
106 | hw/rtc/pl031.c | 2 +- | ||
107 | hw/rtc/twl92230.c | 2 +- | ||
108 | hw/rtc/xlnx-zynqmp-rtc.c | 2 +- | ||
109 | hw/s390x/tod-tcg.c | 2 +- | ||
110 | hw/scsi/megasas.c | 2 +- | ||
111 | hw/ssi/xlnx-versal-ospi.c | 1853 ++++++++++++++++++++++++++++ | ||
112 | net/dump.c | 2 +- | ||
113 | softmmu/rtc.c | 2 +- | ||
114 | target/arm/helper.c | 13 +- | ||
115 | target/arm/m_helper.c | 2 +- | ||
116 | MAINTAINERS | 7 +- | ||
117 | hw/intc/trace-events | 8 + | ||
118 | hw/misc/meson.build | 5 +- | ||
119 | hw/ssi/meson.build | 1 + | ||
120 | scripts/update-linux-headers.sh | 16 + | ||
121 | 52 files changed, 4300 insertions(+), 74 deletions(-) | ||
122 | create mode 100644 include/hw/misc/xlnx-versal-pmc-iou-slcr.h | ||
123 | create mode 100644 include/hw/ssi/xlnx-versal-ospi.h | ||
124 | create mode 100644 include/sysemu/rtc.h | ||
125 | create mode 100644 hw/misc/xlnx-versal-pmc-iou-slcr.c | ||
126 | create mode 100644 hw/ssi/xlnx-versal-ospi.c | ||
73 | 127 | ||
74 | Richard Henderson (1): | ||
75 | tcg: Fix helper function vs host abi for float16 | ||
76 | |||
77 | Shannon Zhao (3): | ||
78 | arm_gicv3_kvm: increase clroffset accordingly | ||
79 | ARM: ACPI: Fix use-after-free due to memory realloc | ||
80 | KVM: GIC: Fix memory leak due to calling kvm_init_irq_routing twice | ||
81 | |||
82 | include/exec/exec-all.h | 5 +- | ||
83 | include/exec/helper-head.h | 2 +- | ||
84 | include/exec/memory-internal.h | 3 +- | ||
85 | include/exec/memory.h | 128 +++++++++++++++++++++++++++++++++++------ | ||
86 | include/migration/vmstate.h | 3 + | ||
87 | include/sysemu/dma.h | 6 +- | ||
88 | accel/tcg/translate-all.c | 4 +- | ||
89 | exec.c | 95 ++++++++++++++++++------------ | ||
90 | hw/arm/boot.c | 18 +++--- | ||
91 | hw/arm/virt-acpi-build.c | 20 +++++-- | ||
92 | hw/dma/xlnx-zdma.c | 10 +++- | ||
93 | hw/hppa/dino.c | 3 +- | ||
94 | hw/intc/arm_gic_kvm.c | 1 - | ||
95 | hw/intc/arm_gicv3_cpuif.c | 12 ++-- | ||
96 | hw/intc/arm_gicv3_kvm.c | 2 +- | ||
97 | hw/nvram/fw_cfg.c | 12 ++-- | ||
98 | hw/s390x/s390-pci-inst.c | 3 +- | ||
99 | hw/scsi/esp.c | 3 +- | ||
100 | hw/vfio/common.c | 3 +- | ||
101 | hw/virtio/vhost.c | 3 +- | ||
102 | hw/xen/xen_pt_msi.c | 3 +- | ||
103 | memory.c | 12 ++-- | ||
104 | memory_ldst.inc.c | 18 +++--- | ||
105 | target/arm/gdbstub.c | 3 +- | ||
106 | target/arm/helper-a64.c | 41 +++++++------ | ||
107 | target/arm/helper.c | 90 ++++++++++++++++------------- | ||
108 | target/arm/kvm.c | 3 +- | ||
109 | target/ppc/mmu-hash64.c | 3 +- | ||
110 | target/riscv/helper.c | 2 +- | ||
111 | target/s390x/diag.c | 6 +- | ||
112 | target/s390x/excp_helper.c | 3 +- | ||
113 | target/s390x/mmu_helper.c | 3 +- | ||
114 | target/s390x/sigp.c | 3 +- | ||
115 | target/xtensa/op_helper.c | 3 +- | ||
116 | MAINTAINERS | 9 ++- | ||
117 | 35 files changed, 355 insertions(+), 183 deletions(-) | ||
118 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | It's a new year; update the copyright strings for our | ||
2 | help/version/about information and for our documentation. | ||
1 | 3 | ||
4 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
5 | Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> | ||
6 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
7 | Message-id: 20220120124713.288303-1-peter.maydell@linaro.org | ||
8 | --- | ||
9 | docs/conf.py | 2 +- | ||
10 | include/qemu-common.h | 2 +- | ||
11 | 2 files changed, 2 insertions(+), 2 deletions(-) | ||
12 | |||
13 | diff --git a/docs/conf.py b/docs/conf.py | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/docs/conf.py | ||
16 | +++ b/docs/conf.py | ||
17 | @@ -XXX,XX +XXX,XX @@ | ||
18 | |||
19 | # General information about the project. | ||
20 | project = u'QEMU' | ||
21 | -copyright = u'2021, The QEMU Project Developers' | ||
22 | +copyright = u'2022, The QEMU Project Developers' | ||
23 | author = u'The QEMU Project Developers' | ||
24 | |||
25 | # The version info for the project you're documenting, acts as replacement for | ||
26 | diff --git a/include/qemu-common.h b/include/qemu-common.h | ||
27 | index XXXXXXX..XXXXXXX 100644 | ||
28 | --- a/include/qemu-common.h | ||
29 | +++ b/include/qemu-common.h | ||
30 | @@ -XXX,XX +XXX,XX @@ | ||
31 | #define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR) | ||
32 | |||
33 | /* Copyright string for -version arguments, About dialogs, etc */ | ||
34 | -#define QEMU_COPYRIGHT "Copyright (c) 2003-2021 " \ | ||
35 | +#define QEMU_COPYRIGHT "Copyright (c) 2003-2022 " \ | ||
36 | "Fabrice Bellard and the QEMU Project developers" | ||
37 | |||
38 | /* Bug reporting information for --help arguments, About dialogs, etc */ | ||
39 | -- | ||
40 | 2.25.1 | ||
41 | |||
42 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | In commit d5093d961585f02 we added a VMStateDescription to | ||
2 | the TYPE_ARMV7M object, to handle migration of its Clocks. | ||
3 | However a cut-and-paste error meant we used the wrong struct | ||
4 | name in the VMSTATE_CLOCK() macro arguments. The result was | ||
5 | that attempting a 'savevm' might result in an assertion | ||
6 | failure. | ||
1 | 7 | ||
8 | Cc: qemu-stable@nongnu.org | ||
9 | Buglink: https://gitlab.com/qemu-project/qemu/-/issues/803 | ||
10 | Fixes: d5093d961585f02 | ||
11 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
12 | Reviewed-by: Ani Sinha <ani@anisinha.ca> | ||
13 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
14 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
15 | Message-id: 20220120151609.433555-1-peter.maydell@linaro.org | ||
16 | --- | ||
17 | hw/arm/armv7m.c | 4 ++-- | ||
18 | 1 file changed, 2 insertions(+), 2 deletions(-) | ||
19 | |||
20 | diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c | ||
21 | index XXXXXXX..XXXXXXX 100644 | ||
22 | --- a/hw/arm/armv7m.c | ||
23 | +++ b/hw/arm/armv7m.c | ||
24 | @@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_armv7m = { | ||
25 | .version_id = 1, | ||
26 | .minimum_version_id = 1, | ||
27 | .fields = (VMStateField[]) { | ||
28 | - VMSTATE_CLOCK(refclk, SysTickState), | ||
29 | - VMSTATE_CLOCK(cpuclk, SysTickState), | ||
30 | + VMSTATE_CLOCK(refclk, ARMv7MState), | ||
31 | + VMSTATE_CLOCK(cpuclk, ARMv7MState), | ||
32 | VMSTATE_END_OF_LIST() | ||
33 | } | ||
34 | }; | ||
35 | -- | ||
36 | 2.25.1 | ||
37 | |||
38 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | The exynos4210_uart_post_load() function assumes that it is passed | ||
2 | the Exynos4210UartState, but it has been attached to the | ||
3 | VMStateDescription for the Exynos4210UartFIFO type. The result is a | ||
4 | SIGSEGV when attempting to load VM state for any machine type | ||
5 | including this device. | ||
1 | 6 | ||
7 | Fix the bug by attaching the post-load function to the VMSD for the | ||
8 | Exynos4210UartState. This is the logical place for it, because the | ||
9 | actions it does relate to the entire UART state, not just the FIFO. | ||
10 | |||
11 | Thanks to the bug reporter @TrungNguyen1909 for the clear bug | ||
12 | description and the suggested fix. | ||
13 | |||
14 | Fixes: c9d3396d80fe7ece9b | ||
15 | ("hw/char/exynos4210_uart: Implement post_load function") | ||
16 | Resolves: https://gitlab.com/qemu-project/qemu/-/issues/638 | ||
17 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
18 | Reviewed-by: Guenter Roeck <linux@roeck-us.net> | ||
19 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
20 | Message-id: 20220120151648.433736-1-peter.maydell@linaro.org | ||
21 | --- | ||
22 | hw/char/exynos4210_uart.c | 2 +- | ||
23 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
24 | |||
25 | diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c | ||
26 | index XXXXXXX..XXXXXXX 100644 | ||
27 | --- a/hw/char/exynos4210_uart.c | ||
28 | +++ b/hw/char/exynos4210_uart.c | ||
29 | @@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_exynos4210_uart_fifo = { | ||
30 | .name = "exynos4210.uart.fifo", | ||
31 | .version_id = 1, | ||
32 | .minimum_version_id = 1, | ||
33 | - .post_load = exynos4210_uart_post_load, | ||
34 | .fields = (VMStateField[]) { | ||
35 | VMSTATE_UINT32(sp, Exynos4210UartFIFO), | ||
36 | VMSTATE_UINT32(rp, Exynos4210UartFIFO), | ||
37 | @@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_exynos4210_uart = { | ||
38 | .name = "exynos4210.uart", | ||
39 | .version_id = 1, | ||
40 | .minimum_version_id = 1, | ||
41 | + .post_load = exynos4210_uart_post_load, | ||
42 | .fields = (VMStateField[]) { | ||
43 | VMSTATE_STRUCT(rx, Exynos4210UartState, 1, | ||
44 | vmstate_exynos4210_uart_fifo, Exynos4210UartFIFO), | ||
45 | -- | ||
46 | 2.25.1 | ||
47 | |||
48 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | softmmu/rtc.c defines two public functions: qemu_get_timedate() and | ||
2 | qemu_timedate_diff(). Currently we keep the prototypes for these in | ||
3 | qemu-common.h, but most files don't need them. Move them to their | ||
4 | own header, a new include/sysemu/rtc.h. | ||
1 | 5 | ||
6 | Since the C files using these two functions did not need to include | ||
7 | qemu-common.h for any other reason, we can remove those include lines | ||
8 | when we add the include of the new rtc.h. | ||
9 | |||
10 | The license for the .h file follows that of the softmmu/rtc.c | ||
11 | where both the functions are defined. | ||
12 | |||
13 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
14 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
15 | --- | ||
16 | include/qemu-common.h | 3 --- | ||
17 | include/sysemu/rtc.h | 58 ++++++++++++++++++++++++++++++++++++++++ | ||
18 | hw/arm/omap1.c | 2 +- | ||
19 | hw/arm/pxa2xx.c | 2 +- | ||
20 | hw/arm/strongarm.c | 2 +- | ||
21 | hw/misc/mac_via.c | 2 +- | ||
22 | hw/misc/macio/cuda.c | 2 +- | ||
23 | hw/misc/macio/pmu.c | 2 +- | ||
24 | hw/ppc/spapr_rtc.c | 2 +- | ||
25 | hw/rtc/allwinner-rtc.c | 2 +- | ||
26 | hw/rtc/aspeed_rtc.c | 2 +- | ||
27 | hw/rtc/ds1338.c | 2 +- | ||
28 | hw/rtc/exynos4210_rtc.c | 2 +- | ||
29 | hw/rtc/goldfish_rtc.c | 2 +- | ||
30 | hw/rtc/m41t80.c | 2 +- | ||
31 | hw/rtc/m48t59.c | 2 +- | ||
32 | hw/rtc/mc146818rtc.c | 2 +- | ||
33 | hw/rtc/pl031.c | 2 +- | ||
34 | hw/rtc/twl92230.c | 2 +- | ||
35 | hw/rtc/xlnx-zynqmp-rtc.c | 2 +- | ||
36 | hw/s390x/tod-tcg.c | 2 +- | ||
37 | hw/scsi/megasas.c | 2 +- | ||
38 | net/dump.c | 2 +- | ||
39 | softmmu/rtc.c | 2 +- | ||
40 | 24 files changed, 80 insertions(+), 25 deletions(-) | ||
41 | create mode 100644 include/sysemu/rtc.h | ||
42 | |||
43 | diff --git a/include/qemu-common.h b/include/qemu-common.h | ||
44 | index XXXXXXX..XXXXXXX 100644 | ||
45 | --- a/include/qemu-common.h | ||
46 | +++ b/include/qemu-common.h | ||
47 | @@ -XXX,XX +XXX,XX @@ | ||
48 | int qemu_main(int argc, char **argv, char **envp); | ||
49 | #endif | ||
50 | |||
51 | -void qemu_get_timedate(struct tm *tm, int offset); | ||
52 | -int qemu_timedate_diff(struct tm *tm); | ||
53 | - | ||
54 | void *qemu_oom_check(void *ptr); | ||
55 | |||
56 | ssize_t qemu_write_full(int fd, const void *buf, size_t count) | ||
57 | diff --git a/include/sysemu/rtc.h b/include/sysemu/rtc.h | ||
58 | new file mode 100644 | ||
59 | index XXXXXXX..XXXXXXX | ||
60 | --- /dev/null | ||
61 | +++ b/include/sysemu/rtc.h | ||
62 | @@ -XXX,XX +XXX,XX @@ | ||
63 | +/* | ||
64 | + * RTC configuration and clock read | ||
65 | + * | ||
66 | + * Copyright (c) 2003-2021 QEMU contributors | ||
67 | + * | ||
68 | + * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
69 | + * of this software and associated documentation files (the "Software"), to deal | ||
70 | + * in the Software without restriction, including without limitation the rights | ||
71 | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
72 | + * copies of the Software, and to permit persons to whom the Software is | ||
73 | + * furnished to do so, subject to the following conditions: | ||
74 | + * | ||
75 | + * The above copyright notice and this permission notice shall be included in | ||
76 | + * all copies or substantial portions of the Software. | ||
77 | + * | ||
78 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
79 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
80 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
81 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
82 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
83 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
84 | + * THE SOFTWARE. | ||
85 | + */ | ||
86 | + | ||
87 | +#ifndef SYSEMU_RTC_H | ||
88 | +#define SYSEMU_RTC_H | ||
89 | + | ||
90 | +/** | ||
91 | + * qemu_get_timedate: Get the current RTC time | ||
92 | + * @tm: struct tm to fill in with RTC time | ||
93 | + * @offset: offset in seconds to adjust the RTC time by before | ||
94 | + * converting to struct tm format. | ||
95 | + * | ||
96 | + * This function fills in @tm with the current RTC time, as adjusted | ||
97 | + * by @offset (for example, if @offset is 3600 then the returned time/date | ||
98 | + * will be one hour further ahead than the current RTC time). | ||
99 | + * | ||
100 | + * The usual use is by RTC device models, which should call this function | ||
101 | + * to find the time/date value that they should return to the guest | ||
102 | + * when it reads the RTC registers. | ||
103 | + * | ||
104 | + * The behaviour of the clock whose value this function returns will | ||
105 | + * depend on the -rtc command line option passed by the user. | ||
106 | + */ | ||
107 | +void qemu_get_timedate(struct tm *tm, int offset); | ||
108 | + | ||
109 | +/** | ||
110 | + * qemu_timedate_diff: Return difference between a struct tm and the RTC | ||
111 | + * @tm: struct tm containing the date/time to compare against | ||
112 | + * | ||
113 | + * Returns the difference in seconds between the RTC clock time | ||
114 | + * and the date/time specified in @tm. For example, if @tm specifies | ||
115 | + * a timestamp one hour further ahead than the current RTC time | ||
116 | + * then this function will return 3600. | ||
117 | + */ | ||
118 | +int qemu_timedate_diff(struct tm *tm); | ||
119 | + | ||
120 | +#endif | ||
121 | diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c | ||
122 | index XXXXXXX..XXXXXXX 100644 | ||
123 | --- a/hw/arm/omap1.c | ||
124 | +++ b/hw/arm/omap1.c | ||
125 | @@ -XXX,XX +XXX,XX @@ | ||
126 | #include "qemu/error-report.h" | ||
127 | #include "qemu/main-loop.h" | ||
128 | #include "qapi/error.h" | ||
129 | -#include "qemu-common.h" | ||
130 | #include "cpu.h" | ||
131 | #include "exec/address-spaces.h" | ||
132 | #include "hw/hw.h" | ||
133 | @@ -XXX,XX +XXX,XX @@ | ||
134 | #include "sysemu/qtest.h" | ||
135 | #include "sysemu/reset.h" | ||
136 | #include "sysemu/runstate.h" | ||
137 | +#include "sysemu/rtc.h" | ||
138 | #include "qemu/range.h" | ||
139 | #include "hw/sysbus.h" | ||
140 | #include "qemu/cutils.h" | ||
141 | diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c | ||
142 | index XXXXXXX..XXXXXXX 100644 | ||
143 | --- a/hw/arm/pxa2xx.c | ||
144 | +++ b/hw/arm/pxa2xx.c | ||
145 | @@ -XXX,XX +XXX,XX @@ | ||
146 | */ | ||
147 | |||
148 | #include "qemu/osdep.h" | ||
149 | -#include "qemu-common.h" | ||
150 | #include "qemu/error-report.h" | ||
151 | #include "qemu/module.h" | ||
152 | #include "qapi/error.h" | ||
153 | @@ -XXX,XX +XXX,XX @@ | ||
154 | #include "chardev/char-fe.h" | ||
155 | #include "sysemu/blockdev.h" | ||
156 | #include "sysemu/qtest.h" | ||
157 | +#include "sysemu/rtc.h" | ||
158 | #include "qemu/cutils.h" | ||
159 | #include "qemu/log.h" | ||
160 | #include "qom/object.h" | ||
161 | diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c | ||
162 | index XXXXXXX..XXXXXXX 100644 | ||
163 | --- a/hw/arm/strongarm.c | ||
164 | +++ b/hw/arm/strongarm.c | ||
165 | @@ -XXX,XX +XXX,XX @@ | ||
166 | */ | ||
167 | |||
168 | #include "qemu/osdep.h" | ||
169 | -#include "qemu-common.h" | ||
170 | #include "cpu.h" | ||
171 | #include "hw/irq.h" | ||
172 | #include "hw/qdev-properties.h" | ||
173 | @@ -XXX,XX +XXX,XX @@ | ||
174 | #include "chardev/char-fe.h" | ||
175 | #include "chardev/char-serial.h" | ||
176 | #include "sysemu/sysemu.h" | ||
177 | +#include "sysemu/rtc.h" | ||
178 | #include "hw/ssi/ssi.h" | ||
179 | #include "qapi/error.h" | ||
180 | #include "qemu/cutils.h" | ||
181 | diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c | ||
182 | index XXXXXXX..XXXXXXX 100644 | ||
183 | --- a/hw/misc/mac_via.c | ||
184 | +++ b/hw/misc/mac_via.c | ||
185 | @@ -XXX,XX +XXX,XX @@ | ||
186 | */ | ||
187 | |||
188 | #include "qemu/osdep.h" | ||
189 | -#include "qemu-common.h" | ||
190 | #include "migration/vmstate.h" | ||
191 | #include "hw/sysbus.h" | ||
192 | #include "hw/irq.h" | ||
193 | @@ -XXX,XX +XXX,XX @@ | ||
194 | #include "hw/qdev-properties.h" | ||
195 | #include "hw/qdev-properties-system.h" | ||
196 | #include "sysemu/block-backend.h" | ||
197 | +#include "sysemu/rtc.h" | ||
198 | #include "trace.h" | ||
199 | #include "qemu/log.h" | ||
200 | |||
201 | diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c | ||
202 | index XXXXXXX..XXXXXXX 100644 | ||
203 | --- a/hw/misc/macio/cuda.c | ||
204 | +++ b/hw/misc/macio/cuda.c | ||
205 | @@ -XXX,XX +XXX,XX @@ | ||
206 | */ | ||
207 | |||
208 | #include "qemu/osdep.h" | ||
209 | -#include "qemu-common.h" | ||
210 | #include "hw/ppc/mac.h" | ||
211 | #include "hw/qdev-properties.h" | ||
212 | #include "migration/vmstate.h" | ||
213 | @@ -XXX,XX +XXX,XX @@ | ||
214 | #include "qapi/error.h" | ||
215 | #include "qemu/timer.h" | ||
216 | #include "sysemu/runstate.h" | ||
217 | +#include "sysemu/rtc.h" | ||
218 | #include "qapi/error.h" | ||
219 | #include "qemu/cutils.h" | ||
220 | #include "qemu/log.h" | ||
221 | diff --git a/hw/misc/macio/pmu.c b/hw/misc/macio/pmu.c | ||
222 | index XXXXXXX..XXXXXXX 100644 | ||
223 | --- a/hw/misc/macio/pmu.c | ||
224 | +++ b/hw/misc/macio/pmu.c | ||
225 | @@ -XXX,XX +XXX,XX @@ | ||
226 | */ | ||
227 | |||
228 | #include "qemu/osdep.h" | ||
229 | -#include "qemu-common.h" | ||
230 | #include "hw/ppc/mac.h" | ||
231 | #include "hw/qdev-properties.h" | ||
232 | #include "migration/vmstate.h" | ||
233 | @@ -XXX,XX +XXX,XX @@ | ||
234 | #include "qapi/error.h" | ||
235 | #include "qemu/timer.h" | ||
236 | #include "sysemu/runstate.h" | ||
237 | +#include "sysemu/rtc.h" | ||
238 | #include "qapi/error.h" | ||
239 | #include "qemu/cutils.h" | ||
240 | #include "qemu/log.h" | ||
241 | diff --git a/hw/ppc/spapr_rtc.c b/hw/ppc/spapr_rtc.c | ||
242 | index XXXXXXX..XXXXXXX 100644 | ||
243 | --- a/hw/ppc/spapr_rtc.c | ||
244 | +++ b/hw/ppc/spapr_rtc.c | ||
245 | @@ -XXX,XX +XXX,XX @@ | ||
246 | */ | ||
247 | |||
248 | #include "qemu/osdep.h" | ||
249 | -#include "qemu-common.h" | ||
250 | #include "qemu/timer.h" | ||
251 | #include "sysemu/sysemu.h" | ||
252 | +#include "sysemu/rtc.h" | ||
253 | #include "hw/ppc/spapr.h" | ||
254 | #include "migration/vmstate.h" | ||
255 | #include "qapi/error.h" | ||
256 | diff --git a/hw/rtc/allwinner-rtc.c b/hw/rtc/allwinner-rtc.c | ||
257 | index XXXXXXX..XXXXXXX 100644 | ||
258 | --- a/hw/rtc/allwinner-rtc.c | ||
259 | +++ b/hw/rtc/allwinner-rtc.c | ||
260 | @@ -XXX,XX +XXX,XX @@ | ||
261 | #include "migration/vmstate.h" | ||
262 | #include "qemu/log.h" | ||
263 | #include "qemu/module.h" | ||
264 | -#include "qemu-common.h" | ||
265 | #include "hw/qdev-properties.h" | ||
266 | #include "hw/rtc/allwinner-rtc.h" | ||
267 | +#include "sysemu/rtc.h" | ||
268 | #include "trace.h" | ||
269 | |||
270 | /* RTC registers */ | ||
271 | diff --git a/hw/rtc/aspeed_rtc.c b/hw/rtc/aspeed_rtc.c | ||
272 | index XXXXXXX..XXXXXXX 100644 | ||
273 | --- a/hw/rtc/aspeed_rtc.c | ||
274 | +++ b/hw/rtc/aspeed_rtc.c | ||
275 | @@ -XXX,XX +XXX,XX @@ | ||
276 | */ | ||
277 | |||
278 | #include "qemu/osdep.h" | ||
279 | -#include "qemu-common.h" | ||
280 | #include "hw/rtc/aspeed_rtc.h" | ||
281 | #include "migration/vmstate.h" | ||
282 | #include "qemu/log.h" | ||
283 | #include "qemu/timer.h" | ||
284 | +#include "sysemu/rtc.h" | ||
285 | |||
286 | #include "trace.h" | ||
287 | |||
288 | diff --git a/hw/rtc/ds1338.c b/hw/rtc/ds1338.c | ||
289 | index XXXXXXX..XXXXXXX 100644 | ||
290 | --- a/hw/rtc/ds1338.c | ||
291 | +++ b/hw/rtc/ds1338.c | ||
292 | @@ -XXX,XX +XXX,XX @@ | ||
293 | */ | ||
294 | |||
295 | #include "qemu/osdep.h" | ||
296 | -#include "qemu-common.h" | ||
297 | #include "hw/i2c/i2c.h" | ||
298 | #include "migration/vmstate.h" | ||
299 | #include "qemu/bcd.h" | ||
300 | #include "qemu/module.h" | ||
301 | #include "qom/object.h" | ||
302 | +#include "sysemu/rtc.h" | ||
303 | |||
304 | /* Size of NVRAM including both the user-accessible area and the | ||
305 | * secondary register area. | ||
306 | diff --git a/hw/rtc/exynos4210_rtc.c b/hw/rtc/exynos4210_rtc.c | ||
307 | index XXXXXXX..XXXXXXX 100644 | ||
308 | --- a/hw/rtc/exynos4210_rtc.c | ||
309 | +++ b/hw/rtc/exynos4210_rtc.c | ||
310 | @@ -XXX,XX +XXX,XX @@ | ||
311 | */ | ||
312 | |||
313 | #include "qemu/osdep.h" | ||
314 | -#include "qemu-common.h" | ||
315 | #include "qemu/log.h" | ||
316 | #include "qemu/module.h" | ||
317 | #include "hw/sysbus.h" | ||
318 | @@ -XXX,XX +XXX,XX @@ | ||
319 | |||
320 | #include "hw/arm/exynos4210.h" | ||
321 | #include "qom/object.h" | ||
322 | +#include "sysemu/rtc.h" | ||
323 | |||
324 | #define DEBUG_RTC 0 | ||
325 | |||
326 | diff --git a/hw/rtc/goldfish_rtc.c b/hw/rtc/goldfish_rtc.c | ||
327 | index XXXXXXX..XXXXXXX 100644 | ||
328 | --- a/hw/rtc/goldfish_rtc.c | ||
329 | +++ b/hw/rtc/goldfish_rtc.c | ||
330 | @@ -XXX,XX +XXX,XX @@ | ||
331 | */ | ||
332 | |||
333 | #include "qemu/osdep.h" | ||
334 | -#include "qemu-common.h" | ||
335 | #include "hw/rtc/goldfish_rtc.h" | ||
336 | #include "migration/vmstate.h" | ||
337 | #include "hw/irq.h" | ||
338 | @@ -XXX,XX +XXX,XX @@ | ||
339 | #include "qemu/bitops.h" | ||
340 | #include "qemu/timer.h" | ||
341 | #include "sysemu/sysemu.h" | ||
342 | +#include "sysemu/rtc.h" | ||
343 | #include "qemu/cutils.h" | ||
344 | #include "qemu/log.h" | ||
345 | |||
346 | diff --git a/hw/rtc/m41t80.c b/hw/rtc/m41t80.c | ||
347 | index XXXXXXX..XXXXXXX 100644 | ||
348 | --- a/hw/rtc/m41t80.c | ||
349 | +++ b/hw/rtc/m41t80.c | ||
350 | @@ -XXX,XX +XXX,XX @@ | ||
351 | */ | ||
352 | |||
353 | #include "qemu/osdep.h" | ||
354 | -#include "qemu-common.h" | ||
355 | #include "qemu/log.h" | ||
356 | #include "qemu/module.h" | ||
357 | #include "qemu/timer.h" | ||
358 | #include "qemu/bcd.h" | ||
359 | #include "hw/i2c/i2c.h" | ||
360 | #include "qom/object.h" | ||
361 | +#include "sysemu/rtc.h" | ||
362 | |||
363 | #define TYPE_M41T80 "m41t80" | ||
364 | OBJECT_DECLARE_SIMPLE_TYPE(M41t80State, M41T80) | ||
365 | diff --git a/hw/rtc/m48t59.c b/hw/rtc/m48t59.c | ||
366 | index XXXXXXX..XXXXXXX 100644 | ||
367 | --- a/hw/rtc/m48t59.c | ||
368 | +++ b/hw/rtc/m48t59.c | ||
369 | @@ -XXX,XX +XXX,XX @@ | ||
370 | */ | ||
371 | |||
372 | #include "qemu/osdep.h" | ||
373 | -#include "qemu-common.h" | ||
374 | #include "hw/irq.h" | ||
375 | #include "hw/qdev-properties.h" | ||
376 | #include "hw/rtc/m48t59.h" | ||
377 | #include "qemu/timer.h" | ||
378 | #include "sysemu/runstate.h" | ||
379 | +#include "sysemu/rtc.h" | ||
380 | #include "sysemu/sysemu.h" | ||
381 | #include "hw/sysbus.h" | ||
382 | #include "qapi/error.h" | ||
383 | diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c | ||
384 | index XXXXXXX..XXXXXXX 100644 | ||
385 | --- a/hw/rtc/mc146818rtc.c | ||
386 | +++ b/hw/rtc/mc146818rtc.c | ||
387 | @@ -XXX,XX +XXX,XX @@ | ||
388 | */ | ||
389 | |||
390 | #include "qemu/osdep.h" | ||
391 | -#include "qemu-common.h" | ||
392 | #include "qemu/cutils.h" | ||
393 | #include "qemu/module.h" | ||
394 | #include "qemu/bcd.h" | ||
395 | @@ -XXX,XX +XXX,XX @@ | ||
396 | #include "sysemu/replay.h" | ||
397 | #include "sysemu/reset.h" | ||
398 | #include "sysemu/runstate.h" | ||
399 | +#include "sysemu/rtc.h" | ||
400 | #include "hw/rtc/mc146818rtc.h" | ||
401 | #include "hw/rtc/mc146818rtc_regs.h" | ||
402 | #include "migration/vmstate.h" | ||
403 | diff --git a/hw/rtc/pl031.c b/hw/rtc/pl031.c | ||
404 | index XXXXXXX..XXXXXXX 100644 | ||
405 | --- a/hw/rtc/pl031.c | ||
406 | +++ b/hw/rtc/pl031.c | ||
407 | @@ -XXX,XX +XXX,XX @@ | ||
408 | */ | ||
409 | |||
410 | #include "qemu/osdep.h" | ||
411 | -#include "qemu-common.h" | ||
412 | #include "hw/rtc/pl031.h" | ||
413 | #include "migration/vmstate.h" | ||
414 | #include "hw/irq.h" | ||
415 | @@ -XXX,XX +XXX,XX @@ | ||
416 | #include "hw/sysbus.h" | ||
417 | #include "qemu/timer.h" | ||
418 | #include "sysemu/sysemu.h" | ||
419 | +#include "sysemu/rtc.h" | ||
420 | #include "qemu/cutils.h" | ||
421 | #include "qemu/log.h" | ||
422 | #include "qemu/module.h" | ||
423 | diff --git a/hw/rtc/twl92230.c b/hw/rtc/twl92230.c | ||
424 | index XXXXXXX..XXXXXXX 100644 | ||
425 | --- a/hw/rtc/twl92230.c | ||
426 | +++ b/hw/rtc/twl92230.c | ||
427 | @@ -XXX,XX +XXX,XX @@ | ||
428 | */ | ||
429 | |||
430 | #include "qemu/osdep.h" | ||
431 | -#include "qemu-common.h" | ||
432 | #include "qemu/timer.h" | ||
433 | #include "hw/i2c/i2c.h" | ||
434 | #include "hw/irq.h" | ||
435 | #include "migration/qemu-file-types.h" | ||
436 | #include "migration/vmstate.h" | ||
437 | #include "sysemu/sysemu.h" | ||
438 | +#include "sysemu/rtc.h" | ||
439 | #include "qemu/bcd.h" | ||
440 | #include "qemu/module.h" | ||
441 | #include "qom/object.h" | ||
442 | diff --git a/hw/rtc/xlnx-zynqmp-rtc.c b/hw/rtc/xlnx-zynqmp-rtc.c | ||
443 | index XXXXXXX..XXXXXXX 100644 | ||
444 | --- a/hw/rtc/xlnx-zynqmp-rtc.c | ||
445 | +++ b/hw/rtc/xlnx-zynqmp-rtc.c | ||
446 | @@ -XXX,XX +XXX,XX @@ | ||
447 | */ | ||
448 | |||
449 | #include "qemu/osdep.h" | ||
450 | -#include "qemu-common.h" | ||
451 | #include "hw/sysbus.h" | ||
452 | #include "hw/register.h" | ||
453 | #include "qemu/bitops.h" | ||
454 | @@ -XXX,XX +XXX,XX @@ | ||
455 | #include "hw/irq.h" | ||
456 | #include "qemu/cutils.h" | ||
457 | #include "sysemu/sysemu.h" | ||
458 | +#include "sysemu/rtc.h" | ||
459 | #include "trace.h" | ||
460 | #include "hw/rtc/xlnx-zynqmp-rtc.h" | ||
461 | #include "migration/vmstate.h" | ||
462 | diff --git a/hw/s390x/tod-tcg.c b/hw/s390x/tod-tcg.c | ||
463 | index XXXXXXX..XXXXXXX 100644 | ||
464 | --- a/hw/s390x/tod-tcg.c | ||
465 | +++ b/hw/s390x/tod-tcg.c | ||
466 | @@ -XXX,XX +XXX,XX @@ | ||
467 | */ | ||
468 | |||
469 | #include "qemu/osdep.h" | ||
470 | -#include "qemu-common.h" | ||
471 | #include "qapi/error.h" | ||
472 | #include "hw/s390x/tod.h" | ||
473 | #include "qemu/timer.h" | ||
474 | @@ -XXX,XX +XXX,XX @@ | ||
475 | #include "qemu/module.h" | ||
476 | #include "cpu.h" | ||
477 | #include "tcg/tcg_s390x.h" | ||
478 | +#include "sysemu/rtc.h" | ||
479 | |||
480 | static void qemu_s390_tod_get(const S390TODState *td, S390TOD *tod, | ||
481 | Error **errp) | ||
482 | diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c | ||
483 | index XXXXXXX..XXXXXXX 100644 | ||
484 | --- a/hw/scsi/megasas.c | ||
485 | +++ b/hw/scsi/megasas.c | ||
486 | @@ -XXX,XX +XXX,XX @@ | ||
487 | */ | ||
488 | |||
489 | #include "qemu/osdep.h" | ||
490 | -#include "qemu-common.h" | ||
491 | #include "hw/pci/pci.h" | ||
492 | #include "hw/qdev-properties.h" | ||
493 | #include "sysemu/dma.h" | ||
494 | #include "sysemu/block-backend.h" | ||
495 | +#include "sysemu/rtc.h" | ||
496 | #include "hw/pci/msi.h" | ||
497 | #include "hw/pci/msix.h" | ||
498 | #include "qemu/iov.h" | ||
499 | diff --git a/net/dump.c b/net/dump.c | ||
500 | index XXXXXXX..XXXXXXX 100644 | ||
501 | --- a/net/dump.c | ||
502 | +++ b/net/dump.c | ||
503 | @@ -XXX,XX +XXX,XX @@ | ||
504 | */ | ||
505 | |||
506 | #include "qemu/osdep.h" | ||
507 | -#include "qemu-common.h" | ||
508 | #include "clients.h" | ||
509 | #include "qapi/error.h" | ||
510 | #include "qemu/error-report.h" | ||
511 | @@ -XXX,XX +XXX,XX @@ | ||
512 | #include "qapi/visitor.h" | ||
513 | #include "net/filter.h" | ||
514 | #include "qom/object.h" | ||
515 | +#include "sysemu/rtc.h" | ||
516 | |||
517 | typedef struct DumpState { | ||
518 | int64_t start_ts; | ||
519 | diff --git a/softmmu/rtc.c b/softmmu/rtc.c | ||
520 | index XXXXXXX..XXXXXXX 100644 | ||
521 | --- a/softmmu/rtc.c | ||
522 | +++ b/softmmu/rtc.c | ||
523 | @@ -XXX,XX +XXX,XX @@ | ||
524 | */ | ||
525 | |||
526 | #include "qemu/osdep.h" | ||
527 | -#include "qemu-common.h" | ||
528 | #include "qemu/cutils.h" | ||
529 | #include "qapi/error.h" | ||
530 | #include "qapi/qmp/qerror.h" | ||
531 | @@ -XXX,XX +XXX,XX @@ | ||
532 | #include "qom/object.h" | ||
533 | #include "sysemu/replay.h" | ||
534 | #include "sysemu/sysemu.h" | ||
535 | +#include "sysemu/rtc.h" | ||
536 | |||
537 | static enum { | ||
538 | RTC_BASE_UTC, | ||
539 | -- | ||
540 | 2.25.1 | ||
541 | |||
542 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
1 | 2 | ||
3 | Add a model of Versal's PMC SLCR (system-level control registers). | ||
4 | |||
5 | Signed-off-by: Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
6 | Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
7 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
8 | Reviewed-by: Luc Michel <luc@lmichel.fr> | ||
9 | Message-id: 20220121161141.14389-2-francisco.iglesias@xilinx.com | ||
10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
11 | --- | ||
12 | include/hw/misc/xlnx-versal-pmc-iou-slcr.h | 78 ++ | ||
13 | hw/misc/xlnx-versal-pmc-iou-slcr.c | 1446 ++++++++++++++++++++ | ||
14 | hw/misc/meson.build | 5 +- | ||
15 | 3 files changed, 1528 insertions(+), 1 deletion(-) | ||
16 | create mode 100644 include/hw/misc/xlnx-versal-pmc-iou-slcr.h | ||
17 | create mode 100644 hw/misc/xlnx-versal-pmc-iou-slcr.c | ||
18 | |||
19 | diff --git a/include/hw/misc/xlnx-versal-pmc-iou-slcr.h b/include/hw/misc/xlnx-versal-pmc-iou-slcr.h | ||
20 | new file mode 100644 | ||
21 | index XXXXXXX..XXXXXXX | ||
22 | --- /dev/null | ||
23 | +++ b/include/hw/misc/xlnx-versal-pmc-iou-slcr.h | ||
24 | @@ -XXX,XX +XXX,XX @@ | ||
25 | +/* | ||
26 | + * Header file for the Xilinx Versal's PMC IOU SLCR | ||
27 | + * | ||
28 | + * Copyright (C) 2021 Xilinx Inc | ||
29 | + * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
30 | + * | ||
31 | + * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
32 | + * of this software and associated documentation files (the "Software"), to deal | ||
33 | + * in the Software without restriction, including without limitation the rights | ||
34 | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
35 | + * copies of the Software, and to permit persons to whom the Software is | ||
36 | + * furnished to do so, subject to the following conditions: | ||
37 | + * | ||
38 | + * The above copyright notice and this permission notice shall be included in | ||
39 | + * all copies or substantial portions of the Software. | ||
40 | + * | ||
41 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
42 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
43 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
44 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
45 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
46 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
47 | + * THE SOFTWARE. | ||
48 | + */ | ||
49 | + | ||
50 | +/* | ||
51 | + * This is a model of Xilinx Versal's PMC I/O Peripheral Control and Status | ||
52 | + * module documented in Versal's Technical Reference manual [1] and the Versal | ||
53 | + * ACAP Register reference [2]. | ||
54 | + * | ||
55 | + * References: | ||
56 | + * | ||
57 | + * [1] Versal ACAP Technical Reference Manual, | ||
58 | + * https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf | ||
59 | + * | ||
60 | + * [2] Versal ACAP Register Reference, | ||
61 | + * https://www.xilinx.com/html_docs/registers/am012/am012-versal-register-reference.html#mod___pmc_iop_slcr.html | ||
62 | + * | ||
63 | + * QEMU interface: | ||
64 | + * + sysbus MMIO region 0: MemoryRegion for the device's registers | ||
65 | + * + sysbus IRQ 0: PMC (AXI and APB) parity error interrupt detected by the PMC | ||
66 | + * I/O peripherals. | ||
67 | + * + sysbus IRQ 1: Device interrupt. | ||
68 | + * + Named GPIO output "sd-emmc-sel[0]": Enables 0: SD mode or 1: eMMC mode on | ||
69 | + * SD/eMMC controller 0. | ||
70 | + * + Named GPIO output "sd-emmc-sel[1]": Enables 0: SD mode or 1: eMMC mode on | ||
71 | + * SD/eMMC controller 1. | ||
72 | + * + Named GPIO output "qspi-ospi-mux-sel": Selects 0: QSPI linear region or 1: | ||
73 | + * OSPI linear region. | ||
74 | + * + Named GPIO output "ospi-mux-sel": Selects 0: OSPI Indirect access mode or | ||
75 | + * 1: OSPI direct access mode. | ||
76 | + */ | ||
77 | + | ||
78 | +#ifndef XILINX_VERSAL_PMC_IOU_SLCR_H | ||
79 | +#define XILINX_VERSAL_PMC_IOU_SLCR_H | ||
80 | + | ||
81 | +#include "hw/register.h" | ||
82 | + | ||
83 | +#define TYPE_XILINX_VERSAL_PMC_IOU_SLCR "xlnx.versal-pmc-iou-slcr" | ||
84 | + | ||
85 | +OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalPmcIouSlcr, XILINX_VERSAL_PMC_IOU_SLCR) | ||
86 | + | ||
87 | +#define XILINX_VERSAL_PMC_IOU_SLCR_R_MAX (0x828 / 4 + 1) | ||
88 | + | ||
89 | +struct XlnxVersalPmcIouSlcr { | ||
90 | + SysBusDevice parent_obj; | ||
91 | + MemoryRegion iomem; | ||
92 | + qemu_irq irq_parity_imr; | ||
93 | + qemu_irq irq_imr; | ||
94 | + qemu_irq sd_emmc_sel[2]; | ||
95 | + qemu_irq qspi_ospi_mux_sel; | ||
96 | + qemu_irq ospi_mux_sel; | ||
97 | + | ||
98 | + uint32_t regs[XILINX_VERSAL_PMC_IOU_SLCR_R_MAX]; | ||
99 | + RegisterInfo regs_info[XILINX_VERSAL_PMC_IOU_SLCR_R_MAX]; | ||
100 | +}; | ||
101 | + | ||
102 | +#endif /* XILINX_VERSAL_PMC_IOU_SLCR_H */ | ||
103 | diff --git a/hw/misc/xlnx-versal-pmc-iou-slcr.c b/hw/misc/xlnx-versal-pmc-iou-slcr.c | ||
104 | new file mode 100644 | ||
105 | index XXXXXXX..XXXXXXX | ||
106 | --- /dev/null | ||
107 | +++ b/hw/misc/xlnx-versal-pmc-iou-slcr.c | ||
108 | @@ -XXX,XX +XXX,XX @@ | ||
109 | +/* | ||
110 | + * QEMU model of Versal's PMC IOU SLCR (system level control registers) | ||
111 | + * | ||
112 | + * Copyright (c) 2021 Xilinx Inc. | ||
113 | + * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
114 | + * | ||
115 | + * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
116 | + * of this software and associated documentation files (the "Software"), to deal | ||
117 | + * in the Software without restriction, including without limitation the rights | ||
118 | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
119 | + * copies of the Software, and to permit persons to whom the Software is | ||
120 | + * furnished to do so, subject to the following conditions: | ||
121 | + * | ||
122 | + * The above copyright notice and this permission notice shall be included in | ||
123 | + * all copies or substantial portions of the Software. | ||
124 | + * | ||
125 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
126 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
127 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
128 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
129 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
130 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
131 | + * THE SOFTWARE. | ||
132 | + */ | ||
133 | + | ||
134 | +#include "qemu/osdep.h" | ||
135 | +#include "hw/sysbus.h" | ||
136 | +#include "hw/register.h" | ||
137 | +#include "hw/irq.h" | ||
138 | +#include "qemu/bitops.h" | ||
139 | +#include "qemu/log.h" | ||
140 | +#include "migration/vmstate.h" | ||
141 | +#include "hw/qdev-properties.h" | ||
142 | +#include "hw/misc/xlnx-versal-pmc-iou-slcr.h" | ||
143 | + | ||
144 | +#ifndef XILINX_VERSAL_PMC_IOU_SLCR_ERR_DEBUG | ||
145 | +#define XILINX_VERSAL_PMC_IOU_SLCR_ERR_DEBUG 0 | ||
146 | +#endif | ||
147 | + | ||
148 | +REG32(MIO_PIN_0, 0x0) | ||
149 | + FIELD(MIO_PIN_0, L3_SEL, 7, 3) | ||
150 | + FIELD(MIO_PIN_0, L2_SEL, 5, 2) | ||
151 | + FIELD(MIO_PIN_0, L1_SEL, 3, 2) | ||
152 | + FIELD(MIO_PIN_0, L0_SEL, 1, 2) | ||
153 | +REG32(MIO_PIN_1, 0x4) | ||
154 | + FIELD(MIO_PIN_1, L3_SEL, 7, 3) | ||
155 | + FIELD(MIO_PIN_1, L2_SEL, 5, 2) | ||
156 | + FIELD(MIO_PIN_1, L1_SEL, 3, 2) | ||
157 | + FIELD(MIO_PIN_1, L0_SEL, 1, 2) | ||
158 | +REG32(MIO_PIN_2, 0x8) | ||
159 | + FIELD(MIO_PIN_2, L3_SEL, 7, 3) | ||
160 | + FIELD(MIO_PIN_2, L2_SEL, 5, 2) | ||
161 | + FIELD(MIO_PIN_2, L1_SEL, 3, 2) | ||
162 | + FIELD(MIO_PIN_2, L0_SEL, 1, 2) | ||
163 | +REG32(MIO_PIN_3, 0xc) | ||
164 | + FIELD(MIO_PIN_3, L3_SEL, 7, 3) | ||
165 | + FIELD(MIO_PIN_3, L2_SEL, 5, 2) | ||
166 | + FIELD(MIO_PIN_3, L1_SEL, 3, 2) | ||
167 | + FIELD(MIO_PIN_3, L0_SEL, 1, 2) | ||
168 | +REG32(MIO_PIN_4, 0x10) | ||
169 | + FIELD(MIO_PIN_4, L3_SEL, 7, 3) | ||
170 | + FIELD(MIO_PIN_4, L2_SEL, 5, 2) | ||
171 | + FIELD(MIO_PIN_4, L1_SEL, 3, 2) | ||
172 | + FIELD(MIO_PIN_4, L0_SEL, 1, 2) | ||
173 | +REG32(MIO_PIN_5, 0x14) | ||
174 | + FIELD(MIO_PIN_5, L3_SEL, 7, 3) | ||
175 | + FIELD(MIO_PIN_5, L2_SEL, 5, 2) | ||
176 | + FIELD(MIO_PIN_5, L1_SEL, 3, 2) | ||
177 | + FIELD(MIO_PIN_5, L0_SEL, 1, 2) | ||
178 | +REG32(MIO_PIN_6, 0x18) | ||
179 | + FIELD(MIO_PIN_6, L3_SEL, 7, 3) | ||
180 | + FIELD(MIO_PIN_6, L2_SEL, 5, 2) | ||
181 | + FIELD(MIO_PIN_6, L1_SEL, 3, 2) | ||
182 | + FIELD(MIO_PIN_6, L0_SEL, 1, 2) | ||
183 | +REG32(MIO_PIN_7, 0x1c) | ||
184 | + FIELD(MIO_PIN_7, L3_SEL, 7, 3) | ||
185 | + FIELD(MIO_PIN_7, L2_SEL, 5, 2) | ||
186 | + FIELD(MIO_PIN_7, L1_SEL, 3, 2) | ||
187 | + FIELD(MIO_PIN_7, L0_SEL, 1, 2) | ||
188 | +REG32(MIO_PIN_8, 0x20) | ||
189 | + FIELD(MIO_PIN_8, L3_SEL, 7, 3) | ||
190 | + FIELD(MIO_PIN_8, L2_SEL, 5, 2) | ||
191 | + FIELD(MIO_PIN_8, L1_SEL, 3, 2) | ||
192 | + FIELD(MIO_PIN_8, L0_SEL, 1, 2) | ||
193 | +REG32(MIO_PIN_9, 0x24) | ||
194 | + FIELD(MIO_PIN_9, L3_SEL, 7, 3) | ||
195 | + FIELD(MIO_PIN_9, L2_SEL, 5, 2) | ||
196 | + FIELD(MIO_PIN_9, L1_SEL, 3, 2) | ||
197 | + FIELD(MIO_PIN_9, L0_SEL, 1, 2) | ||
198 | +REG32(MIO_PIN_10, 0x28) | ||
199 | + FIELD(MIO_PIN_10, L3_SEL, 7, 3) | ||
200 | + FIELD(MIO_PIN_10, L2_SEL, 5, 2) | ||
201 | + FIELD(MIO_PIN_10, L1_SEL, 3, 2) | ||
202 | + FIELD(MIO_PIN_10, L0_SEL, 1, 2) | ||
203 | +REG32(MIO_PIN_11, 0x2c) | ||
204 | + FIELD(MIO_PIN_11, L3_SEL, 7, 3) | ||
205 | + FIELD(MIO_PIN_11, L2_SEL, 5, 2) | ||
206 | + FIELD(MIO_PIN_11, L1_SEL, 3, 2) | ||
207 | + FIELD(MIO_PIN_11, L0_SEL, 1, 2) | ||
208 | +REG32(MIO_PIN_12, 0x30) | ||
209 | + FIELD(MIO_PIN_12, L3_SEL, 7, 3) | ||
210 | + FIELD(MIO_PIN_12, L2_SEL, 5, 2) | ||
211 | + FIELD(MIO_PIN_12, L1_SEL, 3, 2) | ||
212 | + FIELD(MIO_PIN_12, L0_SEL, 1, 2) | ||
213 | +REG32(MIO_PIN_13, 0x34) | ||
214 | + FIELD(MIO_PIN_13, L3_SEL, 7, 3) | ||
215 | + FIELD(MIO_PIN_13, L2_SEL, 5, 2) | ||
216 | + FIELD(MIO_PIN_13, L1_SEL, 3, 2) | ||
217 | + FIELD(MIO_PIN_13, L0_SEL, 1, 2) | ||
218 | +REG32(MIO_PIN_14, 0x38) | ||
219 | + FIELD(MIO_PIN_14, L3_SEL, 7, 3) | ||
220 | + FIELD(MIO_PIN_14, L2_SEL, 5, 2) | ||
221 | + FIELD(MIO_PIN_14, L1_SEL, 3, 2) | ||
222 | + FIELD(MIO_PIN_14, L0_SEL, 1, 2) | ||
223 | +REG32(MIO_PIN_15, 0x3c) | ||
224 | + FIELD(MIO_PIN_15, L3_SEL, 7, 3) | ||
225 | + FIELD(MIO_PIN_15, L2_SEL, 5, 2) | ||
226 | + FIELD(MIO_PIN_15, L1_SEL, 3, 2) | ||
227 | + FIELD(MIO_PIN_15, L0_SEL, 1, 2) | ||
228 | +REG32(MIO_PIN_16, 0x40) | ||
229 | + FIELD(MIO_PIN_16, L3_SEL, 7, 3) | ||
230 | + FIELD(MIO_PIN_16, L2_SEL, 5, 2) | ||
231 | + FIELD(MIO_PIN_16, L1_SEL, 3, 2) | ||
232 | + FIELD(MIO_PIN_16, L0_SEL, 1, 2) | ||
233 | +REG32(MIO_PIN_17, 0x44) | ||
234 | + FIELD(MIO_PIN_17, L3_SEL, 7, 3) | ||
235 | + FIELD(MIO_PIN_17, L2_SEL, 5, 2) | ||
236 | + FIELD(MIO_PIN_17, L1_SEL, 3, 2) | ||
237 | + FIELD(MIO_PIN_17, L0_SEL, 1, 2) | ||
238 | +REG32(MIO_PIN_18, 0x48) | ||
239 | + FIELD(MIO_PIN_18, L3_SEL, 7, 3) | ||
240 | + FIELD(MIO_PIN_18, L2_SEL, 5, 2) | ||
241 | + FIELD(MIO_PIN_18, L1_SEL, 3, 2) | ||
242 | + FIELD(MIO_PIN_18, L0_SEL, 1, 2) | ||
243 | +REG32(MIO_PIN_19, 0x4c) | ||
244 | + FIELD(MIO_PIN_19, L3_SEL, 7, 3) | ||
245 | + FIELD(MIO_PIN_19, L2_SEL, 5, 2) | ||
246 | + FIELD(MIO_PIN_19, L1_SEL, 3, 2) | ||
247 | + FIELD(MIO_PIN_19, L0_SEL, 1, 2) | ||
248 | +REG32(MIO_PIN_20, 0x50) | ||
249 | + FIELD(MIO_PIN_20, L3_SEL, 7, 3) | ||
250 | + FIELD(MIO_PIN_20, L2_SEL, 5, 2) | ||
251 | + FIELD(MIO_PIN_20, L1_SEL, 3, 2) | ||
252 | + FIELD(MIO_PIN_20, L0_SEL, 1, 2) | ||
253 | +REG32(MIO_PIN_21, 0x54) | ||
254 | + FIELD(MIO_PIN_21, L3_SEL, 7, 3) | ||
255 | + FIELD(MIO_PIN_21, L2_SEL, 5, 2) | ||
256 | + FIELD(MIO_PIN_21, L1_SEL, 3, 2) | ||
257 | + FIELD(MIO_PIN_21, L0_SEL, 1, 2) | ||
258 | +REG32(MIO_PIN_22, 0x58) | ||
259 | + FIELD(MIO_PIN_22, L3_SEL, 7, 3) | ||
260 | + FIELD(MIO_PIN_22, L2_SEL, 5, 2) | ||
261 | + FIELD(MIO_PIN_22, L1_SEL, 3, 2) | ||
262 | + FIELD(MIO_PIN_22, L0_SEL, 1, 2) | ||
263 | +REG32(MIO_PIN_23, 0x5c) | ||
264 | + FIELD(MIO_PIN_23, L3_SEL, 7, 3) | ||
265 | + FIELD(MIO_PIN_23, L2_SEL, 5, 2) | ||
266 | + FIELD(MIO_PIN_23, L1_SEL, 3, 2) | ||
267 | + FIELD(MIO_PIN_23, L0_SEL, 1, 2) | ||
268 | +REG32(MIO_PIN_24, 0x60) | ||
269 | + FIELD(MIO_PIN_24, L3_SEL, 7, 3) | ||
270 | + FIELD(MIO_PIN_24, L2_SEL, 5, 2) | ||
271 | + FIELD(MIO_PIN_24, L1_SEL, 3, 2) | ||
272 | + FIELD(MIO_PIN_24, L0_SEL, 1, 2) | ||
273 | +REG32(MIO_PIN_25, 0x64) | ||
274 | + FIELD(MIO_PIN_25, L3_SEL, 7, 3) | ||
275 | + FIELD(MIO_PIN_25, L2_SEL, 5, 2) | ||
276 | + FIELD(MIO_PIN_25, L1_SEL, 3, 2) | ||
277 | + FIELD(MIO_PIN_25, L0_SEL, 1, 2) | ||
278 | +REG32(MIO_PIN_26, 0x68) | ||
279 | + FIELD(MIO_PIN_26, L3_SEL, 7, 3) | ||
280 | + FIELD(MIO_PIN_26, L2_SEL, 5, 2) | ||
281 | + FIELD(MIO_PIN_26, L1_SEL, 3, 2) | ||
282 | + FIELD(MIO_PIN_26, L0_SEL, 1, 2) | ||
283 | +REG32(MIO_PIN_27, 0x6c) | ||
284 | + FIELD(MIO_PIN_27, L3_SEL, 7, 3) | ||
285 | + FIELD(MIO_PIN_27, L2_SEL, 5, 2) | ||
286 | + FIELD(MIO_PIN_27, L1_SEL, 3, 2) | ||
287 | + FIELD(MIO_PIN_27, L0_SEL, 1, 2) | ||
288 | +REG32(MIO_PIN_28, 0x70) | ||
289 | + FIELD(MIO_PIN_28, L3_SEL, 7, 3) | ||
290 | + FIELD(MIO_PIN_28, L2_SEL, 5, 2) | ||
291 | + FIELD(MIO_PIN_28, L1_SEL, 3, 2) | ||
292 | + FIELD(MIO_PIN_28, L0_SEL, 1, 2) | ||
293 | +REG32(MIO_PIN_29, 0x74) | ||
294 | + FIELD(MIO_PIN_29, L3_SEL, 7, 3) | ||
295 | + FIELD(MIO_PIN_29, L2_SEL, 5, 2) | ||
296 | + FIELD(MIO_PIN_29, L1_SEL, 3, 2) | ||
297 | + FIELD(MIO_PIN_29, L0_SEL, 1, 2) | ||
298 | +REG32(MIO_PIN_30, 0x78) | ||
299 | + FIELD(MIO_PIN_30, L3_SEL, 7, 3) | ||
300 | + FIELD(MIO_PIN_30, L2_SEL, 5, 2) | ||
301 | + FIELD(MIO_PIN_30, L1_SEL, 3, 2) | ||
302 | + FIELD(MIO_PIN_30, L0_SEL, 1, 2) | ||
303 | +REG32(MIO_PIN_31, 0x7c) | ||
304 | + FIELD(MIO_PIN_31, L3_SEL, 7, 3) | ||
305 | + FIELD(MIO_PIN_31, L2_SEL, 5, 2) | ||
306 | + FIELD(MIO_PIN_31, L1_SEL, 3, 2) | ||
307 | + FIELD(MIO_PIN_31, L0_SEL, 1, 2) | ||
308 | +REG32(MIO_PIN_32, 0x80) | ||
309 | + FIELD(MIO_PIN_32, L3_SEL, 7, 3) | ||
310 | + FIELD(MIO_PIN_32, L2_SEL, 5, 2) | ||
311 | + FIELD(MIO_PIN_32, L1_SEL, 3, 2) | ||
312 | + FIELD(MIO_PIN_32, L0_SEL, 1, 2) | ||
313 | +REG32(MIO_PIN_33, 0x84) | ||
314 | + FIELD(MIO_PIN_33, L3_SEL, 7, 3) | ||
315 | + FIELD(MIO_PIN_33, L2_SEL, 5, 2) | ||
316 | + FIELD(MIO_PIN_33, L1_SEL, 3, 2) | ||
317 | + FIELD(MIO_PIN_33, L0_SEL, 1, 2) | ||
318 | +REG32(MIO_PIN_34, 0x88) | ||
319 | + FIELD(MIO_PIN_34, L3_SEL, 7, 3) | ||
320 | + FIELD(MIO_PIN_34, L2_SEL, 5, 2) | ||
321 | + FIELD(MIO_PIN_34, L1_SEL, 3, 2) | ||
322 | + FIELD(MIO_PIN_34, L0_SEL, 1, 2) | ||
323 | +REG32(MIO_PIN_35, 0x8c) | ||
324 | + FIELD(MIO_PIN_35, L3_SEL, 7, 3) | ||
325 | + FIELD(MIO_PIN_35, L2_SEL, 5, 2) | ||
326 | + FIELD(MIO_PIN_35, L1_SEL, 3, 2) | ||
327 | + FIELD(MIO_PIN_35, L0_SEL, 1, 2) | ||
328 | +REG32(MIO_PIN_36, 0x90) | ||
329 | + FIELD(MIO_PIN_36, L3_SEL, 7, 3) | ||
330 | + FIELD(MIO_PIN_36, L2_SEL, 5, 2) | ||
331 | + FIELD(MIO_PIN_36, L1_SEL, 3, 2) | ||
332 | + FIELD(MIO_PIN_36, L0_SEL, 1, 2) | ||
333 | +REG32(MIO_PIN_37, 0x94) | ||
334 | + FIELD(MIO_PIN_37, L3_SEL, 7, 3) | ||
335 | + FIELD(MIO_PIN_37, L2_SEL, 5, 2) | ||
336 | + FIELD(MIO_PIN_37, L1_SEL, 3, 2) | ||
337 | + FIELD(MIO_PIN_37, L0_SEL, 1, 2) | ||
338 | +REG32(MIO_PIN_38, 0x98) | ||
339 | + FIELD(MIO_PIN_38, L3_SEL, 7, 3) | ||
340 | + FIELD(MIO_PIN_38, L2_SEL, 5, 2) | ||
341 | + FIELD(MIO_PIN_38, L1_SEL, 3, 2) | ||
342 | + FIELD(MIO_PIN_38, L0_SEL, 1, 2) | ||
343 | +REG32(MIO_PIN_39, 0x9c) | ||
344 | + FIELD(MIO_PIN_39, L3_SEL, 7, 3) | ||
345 | + FIELD(MIO_PIN_39, L2_SEL, 5, 2) | ||
346 | + FIELD(MIO_PIN_39, L1_SEL, 3, 2) | ||
347 | + FIELD(MIO_PIN_39, L0_SEL, 1, 2) | ||
348 | +REG32(MIO_PIN_40, 0xa0) | ||
349 | + FIELD(MIO_PIN_40, L3_SEL, 7, 3) | ||
350 | + FIELD(MIO_PIN_40, L2_SEL, 5, 2) | ||
351 | + FIELD(MIO_PIN_40, L1_SEL, 3, 2) | ||
352 | + FIELD(MIO_PIN_40, L0_SEL, 1, 2) | ||
353 | +REG32(MIO_PIN_41, 0xa4) | ||
354 | + FIELD(MIO_PIN_41, L3_SEL, 7, 3) | ||
355 | + FIELD(MIO_PIN_41, L2_SEL, 5, 2) | ||
356 | + FIELD(MIO_PIN_41, L1_SEL, 3, 2) | ||
357 | + FIELD(MIO_PIN_41, L0_SEL, 1, 2) | ||
358 | +REG32(MIO_PIN_42, 0xa8) | ||
359 | + FIELD(MIO_PIN_42, L3_SEL, 7, 3) | ||
360 | + FIELD(MIO_PIN_42, L2_SEL, 5, 2) | ||
361 | + FIELD(MIO_PIN_42, L1_SEL, 3, 2) | ||
362 | + FIELD(MIO_PIN_42, L0_SEL, 1, 2) | ||
363 | +REG32(MIO_PIN_43, 0xac) | ||
364 | + FIELD(MIO_PIN_43, L3_SEL, 7, 3) | ||
365 | + FIELD(MIO_PIN_43, L2_SEL, 5, 2) | ||
366 | + FIELD(MIO_PIN_43, L1_SEL, 3, 2) | ||
367 | + FIELD(MIO_PIN_43, L0_SEL, 1, 2) | ||
368 | +REG32(MIO_PIN_44, 0xb0) | ||
369 | + FIELD(MIO_PIN_44, L3_SEL, 7, 3) | ||
370 | + FIELD(MIO_PIN_44, L2_SEL, 5, 2) | ||
371 | + FIELD(MIO_PIN_44, L1_SEL, 3, 2) | ||
372 | + FIELD(MIO_PIN_44, L0_SEL, 1, 2) | ||
373 | +REG32(MIO_PIN_45, 0xb4) | ||
374 | + FIELD(MIO_PIN_45, L3_SEL, 7, 3) | ||
375 | + FIELD(MIO_PIN_45, L2_SEL, 5, 2) | ||
376 | + FIELD(MIO_PIN_45, L1_SEL, 3, 2) | ||
377 | + FIELD(MIO_PIN_45, L0_SEL, 1, 2) | ||
378 | +REG32(MIO_PIN_46, 0xb8) | ||
379 | + FIELD(MIO_PIN_46, L3_SEL, 7, 3) | ||
380 | + FIELD(MIO_PIN_46, L2_SEL, 5, 2) | ||
381 | + FIELD(MIO_PIN_46, L1_SEL, 3, 2) | ||
382 | + FIELD(MIO_PIN_46, L0_SEL, 1, 2) | ||
383 | +REG32(MIO_PIN_47, 0xbc) | ||
384 | + FIELD(MIO_PIN_47, L3_SEL, 7, 3) | ||
385 | + FIELD(MIO_PIN_47, L2_SEL, 5, 2) | ||
386 | + FIELD(MIO_PIN_47, L1_SEL, 3, 2) | ||
387 | + FIELD(MIO_PIN_47, L0_SEL, 1, 2) | ||
388 | +REG32(MIO_PIN_48, 0xc0) | ||
389 | + FIELD(MIO_PIN_48, L3_SEL, 7, 3) | ||
390 | + FIELD(MIO_PIN_48, L2_SEL, 5, 2) | ||
391 | + FIELD(MIO_PIN_48, L1_SEL, 3, 2) | ||
392 | + FIELD(MIO_PIN_48, L0_SEL, 1, 2) | ||
393 | +REG32(MIO_PIN_49, 0xc4) | ||
394 | + FIELD(MIO_PIN_49, L3_SEL, 7, 3) | ||
395 | + FIELD(MIO_PIN_49, L2_SEL, 5, 2) | ||
396 | + FIELD(MIO_PIN_49, L1_SEL, 3, 2) | ||
397 | + FIELD(MIO_PIN_49, L0_SEL, 1, 2) | ||
398 | +REG32(MIO_PIN_50, 0xc8) | ||
399 | + FIELD(MIO_PIN_50, L3_SEL, 7, 3) | ||
400 | + FIELD(MIO_PIN_50, L2_SEL, 5, 2) | ||
401 | + FIELD(MIO_PIN_50, L1_SEL, 3, 2) | ||
402 | + FIELD(MIO_PIN_50, L0_SEL, 1, 2) | ||
403 | +REG32(MIO_PIN_51, 0xcc) | ||
404 | + FIELD(MIO_PIN_51, L3_SEL, 7, 3) | ||
405 | + FIELD(MIO_PIN_51, L2_SEL, 5, 2) | ||
406 | + FIELD(MIO_PIN_51, L1_SEL, 3, 2) | ||
407 | + FIELD(MIO_PIN_51, L0_SEL, 1, 2) | ||
408 | +REG32(BNK0_EN_RX, 0x100) | ||
409 | + FIELD(BNK0_EN_RX, BNK0_EN_RX, 0, 26) | ||
410 | +REG32(BNK0_SEL_RX0, 0x104) | ||
411 | +REG32(BNK0_SEL_RX1, 0x108) | ||
412 | + FIELD(BNK0_SEL_RX1, BNK0_SEL_RX, 0, 20) | ||
413 | +REG32(BNK0_EN_RX_SCHMITT_HYST, 0x10c) | ||
414 | + FIELD(BNK0_EN_RX_SCHMITT_HYST, BNK0_EN_RX_SCHMITT_HYST, 0, 26) | ||
415 | +REG32(BNK0_EN_WK_PD, 0x110) | ||
416 | + FIELD(BNK0_EN_WK_PD, BNK0_EN_WK_PD, 0, 26) | ||
417 | +REG32(BNK0_EN_WK_PU, 0x114) | ||
418 | + FIELD(BNK0_EN_WK_PU, BNK0_EN_WK_PU, 0, 26) | ||
419 | +REG32(BNK0_SEL_DRV0, 0x118) | ||
420 | +REG32(BNK0_SEL_DRV1, 0x11c) | ||
421 | + FIELD(BNK0_SEL_DRV1, BNK0_SEL_DRV, 0, 20) | ||
422 | +REG32(BNK0_SEL_SLEW, 0x120) | ||
423 | + FIELD(BNK0_SEL_SLEW, BNK0_SEL_SLEW, 0, 26) | ||
424 | +REG32(BNK0_EN_DFT_OPT_INV, 0x124) | ||
425 | + FIELD(BNK0_EN_DFT_OPT_INV, BNK0_EN_DFT_OPT_INV, 0, 26) | ||
426 | +REG32(BNK0_EN_PAD2PAD_LOOPBACK, 0x128) | ||
427 | + FIELD(BNK0_EN_PAD2PAD_LOOPBACK, BNK0_EN_PAD2PAD_LOOPBACK, 0, 13) | ||
428 | +REG32(BNK0_RX_SPARE0, 0x12c) | ||
429 | +REG32(BNK0_RX_SPARE1, 0x130) | ||
430 | + FIELD(BNK0_RX_SPARE1, BNK0_RX_SPARE, 0, 20) | ||
431 | +REG32(BNK0_TX_SPARE0, 0x134) | ||
432 | +REG32(BNK0_TX_SPARE1, 0x138) | ||
433 | + FIELD(BNK0_TX_SPARE1, BNK0_TX_SPARE, 0, 20) | ||
434 | +REG32(BNK0_SEL_EN1P8, 0x13c) | ||
435 | + FIELD(BNK0_SEL_EN1P8, BNK0_SEL_EN1P8, 0, 1) | ||
436 | +REG32(BNK0_EN_B_POR_DETECT, 0x140) | ||
437 | + FIELD(BNK0_EN_B_POR_DETECT, BNK0_EN_B_POR_DETECT, 0, 1) | ||
438 | +REG32(BNK0_LPF_BYP_POR_DETECT, 0x144) | ||
439 | + FIELD(BNK0_LPF_BYP_POR_DETECT, BNK0_LPF_BYP_POR_DETECT, 0, 1) | ||
440 | +REG32(BNK0_EN_LATCH, 0x148) | ||
441 | + FIELD(BNK0_EN_LATCH, BNK0_EN_LATCH, 0, 1) | ||
442 | +REG32(BNK0_VBG_LPF_BYP_B, 0x14c) | ||
443 | + FIELD(BNK0_VBG_LPF_BYP_B, BNK0_VBG_LPF_BYP_B, 0, 1) | ||
444 | +REG32(BNK0_EN_AMP_B, 0x150) | ||
445 | + FIELD(BNK0_EN_AMP_B, BNK0_EN_AMP_B, 0, 2) | ||
446 | +REG32(BNK0_SPARE_BIAS, 0x154) | ||
447 | + FIELD(BNK0_SPARE_BIAS, BNK0_SPARE_BIAS, 0, 4) | ||
448 | +REG32(BNK0_DRIVER_BIAS, 0x158) | ||
449 | + FIELD(BNK0_DRIVER_BIAS, BNK0_DRIVER_BIAS, 0, 15) | ||
450 | +REG32(BNK0_VMODE, 0x15c) | ||
451 | + FIELD(BNK0_VMODE, BNK0_VMODE, 0, 1) | ||
452 | +REG32(BNK0_SEL_AUX_IO_RX, 0x160) | ||
453 | + FIELD(BNK0_SEL_AUX_IO_RX, BNK0_SEL_AUX_IO_RX, 0, 26) | ||
454 | +REG32(BNK0_EN_TX_HS_MODE, 0x164) | ||
455 | + FIELD(BNK0_EN_TX_HS_MODE, BNK0_EN_TX_HS_MODE, 0, 26) | ||
456 | +REG32(MIO_MST_TRI0, 0x200) | ||
457 | + FIELD(MIO_MST_TRI0, PIN_25_TRI, 25, 1) | ||
458 | + FIELD(MIO_MST_TRI0, PIN_24_TRI, 24, 1) | ||
459 | + FIELD(MIO_MST_TRI0, PIN_23_TRI, 23, 1) | ||
460 | + FIELD(MIO_MST_TRI0, PIN_22_TRI, 22, 1) | ||
461 | + FIELD(MIO_MST_TRI0, PIN_21_TRI, 21, 1) | ||
462 | + FIELD(MIO_MST_TRI0, PIN_20_TRI, 20, 1) | ||
463 | + FIELD(MIO_MST_TRI0, PIN_19_TRI, 19, 1) | ||
464 | + FIELD(MIO_MST_TRI0, PIN_18_TRI, 18, 1) | ||
465 | + FIELD(MIO_MST_TRI0, PIN_17_TRI, 17, 1) | ||
466 | + FIELD(MIO_MST_TRI0, PIN_16_TRI, 16, 1) | ||
467 | + FIELD(MIO_MST_TRI0, PIN_15_TRI, 15, 1) | ||
468 | + FIELD(MIO_MST_TRI0, PIN_14_TRI, 14, 1) | ||
469 | + FIELD(MIO_MST_TRI0, PIN_13_TRI, 13, 1) | ||
470 | + FIELD(MIO_MST_TRI0, PIN_12_TRI, 12, 1) | ||
471 | + FIELD(MIO_MST_TRI0, PIN_11_TRI, 11, 1) | ||
472 | + FIELD(MIO_MST_TRI0, PIN_10_TRI, 10, 1) | ||
473 | + FIELD(MIO_MST_TRI0, PIN_09_TRI, 9, 1) | ||
474 | + FIELD(MIO_MST_TRI0, PIN_08_TRI, 8, 1) | ||
475 | + FIELD(MIO_MST_TRI0, PIN_07_TRI, 7, 1) | ||
476 | + FIELD(MIO_MST_TRI0, PIN_06_TRI, 6, 1) | ||
477 | + FIELD(MIO_MST_TRI0, PIN_05_TRI, 5, 1) | ||
478 | + FIELD(MIO_MST_TRI0, PIN_04_TRI, 4, 1) | ||
479 | + FIELD(MIO_MST_TRI0, PIN_03_TRI, 3, 1) | ||
480 | + FIELD(MIO_MST_TRI0, PIN_02_TRI, 2, 1) | ||
481 | + FIELD(MIO_MST_TRI0, PIN_01_TRI, 1, 1) | ||
482 | + FIELD(MIO_MST_TRI0, PIN_00_TRI, 0, 1) | ||
483 | +REG32(MIO_MST_TRI1, 0x204) | ||
484 | + FIELD(MIO_MST_TRI1, PIN_51_TRI, 25, 1) | ||
485 | + FIELD(MIO_MST_TRI1, PIN_50_TRI, 24, 1) | ||
486 | + FIELD(MIO_MST_TRI1, PIN_49_TRI, 23, 1) | ||
487 | + FIELD(MIO_MST_TRI1, PIN_48_TRI, 22, 1) | ||
488 | + FIELD(MIO_MST_TRI1, PIN_47_TRI, 21, 1) | ||
489 | + FIELD(MIO_MST_TRI1, PIN_46_TRI, 20, 1) | ||
490 | + FIELD(MIO_MST_TRI1, PIN_45_TRI, 19, 1) | ||
491 | + FIELD(MIO_MST_TRI1, PIN_44_TRI, 18, 1) | ||
492 | + FIELD(MIO_MST_TRI1, PIN_43_TRI, 17, 1) | ||
493 | + FIELD(MIO_MST_TRI1, PIN_42_TRI, 16, 1) | ||
494 | + FIELD(MIO_MST_TRI1, PIN_41_TRI, 15, 1) | ||
495 | + FIELD(MIO_MST_TRI1, PIN_40_TRI, 14, 1) | ||
496 | + FIELD(MIO_MST_TRI1, PIN_39_TRI, 13, 1) | ||
497 | + FIELD(MIO_MST_TRI1, PIN_38_TRI, 12, 1) | ||
498 | + FIELD(MIO_MST_TRI1, PIN_37_TRI, 11, 1) | ||
499 | + FIELD(MIO_MST_TRI1, PIN_36_TRI, 10, 1) | ||
500 | + FIELD(MIO_MST_TRI1, PIN_35_TRI, 9, 1) | ||
501 | + FIELD(MIO_MST_TRI1, PIN_34_TRI, 8, 1) | ||
502 | + FIELD(MIO_MST_TRI1, PIN_33_TRI, 7, 1) | ||
503 | + FIELD(MIO_MST_TRI1, PIN_32_TRI, 6, 1) | ||
504 | + FIELD(MIO_MST_TRI1, PIN_31_TRI, 5, 1) | ||
505 | + FIELD(MIO_MST_TRI1, PIN_30_TRI, 4, 1) | ||
506 | + FIELD(MIO_MST_TRI1, PIN_29_TRI, 3, 1) | ||
507 | + FIELD(MIO_MST_TRI1, PIN_28_TRI, 2, 1) | ||
508 | + FIELD(MIO_MST_TRI1, PIN_27_TRI, 1, 1) | ||
509 | + FIELD(MIO_MST_TRI1, PIN_26_TRI, 0, 1) | ||
510 | +REG32(BNK1_EN_RX, 0x300) | ||
511 | + FIELD(BNK1_EN_RX, BNK1_EN_RX, 0, 26) | ||
512 | +REG32(BNK1_SEL_RX0, 0x304) | ||
513 | +REG32(BNK1_SEL_RX1, 0x308) | ||
514 | + FIELD(BNK1_SEL_RX1, BNK1_SEL_RX, 0, 20) | ||
515 | +REG32(BNK1_EN_RX_SCHMITT_HYST, 0x30c) | ||
516 | + FIELD(BNK1_EN_RX_SCHMITT_HYST, BNK1_EN_RX_SCHMITT_HYST, 0, 26) | ||
517 | +REG32(BNK1_EN_WK_PD, 0x310) | ||
518 | + FIELD(BNK1_EN_WK_PD, BNK1_EN_WK_PD, 0, 26) | ||
519 | +REG32(BNK1_EN_WK_PU, 0x314) | ||
520 | + FIELD(BNK1_EN_WK_PU, BNK1_EN_WK_PU, 0, 26) | ||
521 | +REG32(BNK1_SEL_DRV0, 0x318) | ||
522 | +REG32(BNK1_SEL_DRV1, 0x31c) | ||
523 | + FIELD(BNK1_SEL_DRV1, BNK1_SEL_DRV, 0, 20) | ||
524 | +REG32(BNK1_SEL_SLEW, 0x320) | ||
525 | + FIELD(BNK1_SEL_SLEW, BNK1_SEL_SLEW, 0, 26) | ||
526 | +REG32(BNK1_EN_DFT_OPT_INV, 0x324) | ||
527 | + FIELD(BNK1_EN_DFT_OPT_INV, BNK1_EN_DFT_OPT_INV, 0, 26) | ||
528 | +REG32(BNK1_EN_PAD2PAD_LOOPBACK, 0x328) | ||
529 | + FIELD(BNK1_EN_PAD2PAD_LOOPBACK, BNK1_EN_PAD2PAD_LOOPBACK, 0, 13) | ||
530 | +REG32(BNK1_RX_SPARE0, 0x32c) | ||
531 | +REG32(BNK1_RX_SPARE1, 0x330) | ||
532 | + FIELD(BNK1_RX_SPARE1, BNK1_RX_SPARE, 0, 20) | ||
533 | +REG32(BNK1_TX_SPARE0, 0x334) | ||
534 | +REG32(BNK1_TX_SPARE1, 0x338) | ||
535 | + FIELD(BNK1_TX_SPARE1, BNK1_TX_SPARE, 0, 20) | ||
536 | +REG32(BNK1_SEL_EN1P8, 0x33c) | ||
537 | + FIELD(BNK1_SEL_EN1P8, BNK1_SEL_EN1P8, 0, 1) | ||
538 | +REG32(BNK1_EN_B_POR_DETECT, 0x340) | ||
539 | + FIELD(BNK1_EN_B_POR_DETECT, BNK1_EN_B_POR_DETECT, 0, 1) | ||
540 | +REG32(BNK1_LPF_BYP_POR_DETECT, 0x344) | ||
541 | + FIELD(BNK1_LPF_BYP_POR_DETECT, BNK1_LPF_BYP_POR_DETECT, 0, 1) | ||
542 | +REG32(BNK1_EN_LATCH, 0x348) | ||
543 | + FIELD(BNK1_EN_LATCH, BNK1_EN_LATCH, 0, 1) | ||
544 | +REG32(BNK1_VBG_LPF_BYP_B, 0x34c) | ||
545 | + FIELD(BNK1_VBG_LPF_BYP_B, BNK1_VBG_LPF_BYP_B, 0, 1) | ||
546 | +REG32(BNK1_EN_AMP_B, 0x350) | ||
547 | + FIELD(BNK1_EN_AMP_B, BNK1_EN_AMP_B, 0, 2) | ||
548 | +REG32(BNK1_SPARE_BIAS, 0x354) | ||
549 | + FIELD(BNK1_SPARE_BIAS, BNK1_SPARE_BIAS, 0, 4) | ||
550 | +REG32(BNK1_DRIVER_BIAS, 0x358) | ||
551 | + FIELD(BNK1_DRIVER_BIAS, BNK1_DRIVER_BIAS, 0, 15) | ||
552 | +REG32(BNK1_VMODE, 0x35c) | ||
553 | + FIELD(BNK1_VMODE, BNK1_VMODE, 0, 1) | ||
554 | +REG32(BNK1_SEL_AUX_IO_RX, 0x360) | ||
555 | + FIELD(BNK1_SEL_AUX_IO_RX, BNK1_SEL_AUX_IO_RX, 0, 26) | ||
556 | +REG32(BNK1_EN_TX_HS_MODE, 0x364) | ||
557 | + FIELD(BNK1_EN_TX_HS_MODE, BNK1_EN_TX_HS_MODE, 0, 26) | ||
558 | +REG32(SD0_CLK_CTRL, 0x400) | ||
559 | + FIELD(SD0_CLK_CTRL, SDIO0_FBCLK_SEL, 2, 1) | ||
560 | + FIELD(SD0_CLK_CTRL, SDIO0_RX_SRC_SEL, 0, 2) | ||
561 | +REG32(SD0_CTRL_REG, 0x404) | ||
562 | + FIELD(SD0_CTRL_REG, SD0_EMMC_SEL, 0, 1) | ||
563 | +REG32(SD0_CONFIG_REG1, 0x410) | ||
564 | + FIELD(SD0_CONFIG_REG1, SD0_BASECLK, 7, 8) | ||
565 | + FIELD(SD0_CONFIG_REG1, SD0_TUNIGCOUNT, 1, 6) | ||
566 | + FIELD(SD0_CONFIG_REG1, SD0_ASYNCWKPENA, 0, 1) | ||
567 | +REG32(SD0_CONFIG_REG2, 0x414) | ||
568 | + FIELD(SD0_CONFIG_REG2, SD0_SLOTTYPE, 12, 2) | ||
569 | + FIELD(SD0_CONFIG_REG2, SD0_ASYCINTR, 11, 1) | ||
570 | + FIELD(SD0_CONFIG_REG2, SD0_64BIT, 10, 1) | ||
571 | + FIELD(SD0_CONFIG_REG2, SD0_1P8V, 9, 1) | ||
572 | + FIELD(SD0_CONFIG_REG2, SD0_3P0V, 8, 1) | ||
573 | + FIELD(SD0_CONFIG_REG2, SD0_3P3V, 7, 1) | ||
574 | + FIELD(SD0_CONFIG_REG2, SD0_SUSPRES, 6, 1) | ||
575 | + FIELD(SD0_CONFIG_REG2, SD0_SDMA, 5, 1) | ||
576 | + FIELD(SD0_CONFIG_REG2, SD0_HIGHSPEED, 4, 1) | ||
577 | + FIELD(SD0_CONFIG_REG2, SD0_ADMA2, 3, 1) | ||
578 | + FIELD(SD0_CONFIG_REG2, SD0_8BIT, 2, 1) | ||
579 | + FIELD(SD0_CONFIG_REG2, SD0_MAXBLK, 0, 2) | ||
580 | +REG32(SD0_CONFIG_REG3, 0x418) | ||
581 | + FIELD(SD0_CONFIG_REG3, SD0_TUNINGSDR50, 10, 1) | ||
582 | + FIELD(SD0_CONFIG_REG3, SD0_RETUNETMR, 6, 4) | ||
583 | + FIELD(SD0_CONFIG_REG3, SD0_DDRIVER, 5, 1) | ||
584 | + FIELD(SD0_CONFIG_REG3, SD0_CDRIVER, 4, 1) | ||
585 | + FIELD(SD0_CONFIG_REG3, SD0_ADRIVER, 3, 1) | ||
586 | + FIELD(SD0_CONFIG_REG3, SD0_DDR50, 2, 1) | ||
587 | + FIELD(SD0_CONFIG_REG3, SD0_SDR104, 1, 1) | ||
588 | + FIELD(SD0_CONFIG_REG3, SD0_SDR50, 0, 1) | ||
589 | +REG32(SD0_INITPRESET, 0x41c) | ||
590 | + FIELD(SD0_INITPRESET, SD0_INITPRESET, 0, 13) | ||
591 | +REG32(SD0_DSPPRESET, 0x420) | ||
592 | + FIELD(SD0_DSPPRESET, SD0_DSPPRESET, 0, 13) | ||
593 | +REG32(SD0_HSPDPRESET, 0x424) | ||
594 | + FIELD(SD0_HSPDPRESET, SD0_HSPDPRESET, 0, 13) | ||
595 | +REG32(SD0_SDR12PRESET, 0x428) | ||
596 | + FIELD(SD0_SDR12PRESET, SD0_SDR12PRESET, 0, 13) | ||
597 | +REG32(SD0_SDR25PRESET, 0x42c) | ||
598 | + FIELD(SD0_SDR25PRESET, SD0_SDR25PRESET, 0, 13) | ||
599 | +REG32(SD0_SDR50PRSET, 0x430) | ||
600 | + FIELD(SD0_SDR50PRSET, SD0_SDR50PRESET, 0, 13) | ||
601 | +REG32(SD0_SDR104PRST, 0x434) | ||
602 | + FIELD(SD0_SDR104PRST, SD0_SDR104PRESET, 0, 13) | ||
603 | +REG32(SD0_DDR50PRESET, 0x438) | ||
604 | + FIELD(SD0_DDR50PRESET, SD0_DDR50PRESET, 0, 13) | ||
605 | +REG32(SD0_MAXCUR1P8, 0x43c) | ||
606 | + FIELD(SD0_MAXCUR1P8, SD0_MAXCUR1P8, 0, 8) | ||
607 | +REG32(SD0_MAXCUR3P0, 0x440) | ||
608 | + FIELD(SD0_MAXCUR3P0, SD0_MAXCUR3P0, 0, 8) | ||
609 | +REG32(SD0_MAXCUR3P3, 0x444) | ||
610 | + FIELD(SD0_MAXCUR3P3, SD0_MAXCUR3P3, 0, 8) | ||
611 | +REG32(SD0_DLL_CTRL, 0x448) | ||
612 | + FIELD(SD0_DLL_CTRL, SD0_CLKSTABLE_CFG, 9, 1) | ||
613 | + FIELD(SD0_DLL_CTRL, SD0_DLL_CFG, 5, 4) | ||
614 | + FIELD(SD0_DLL_CTRL, SD0_DLL_PSDONE, 4, 1) | ||
615 | + FIELD(SD0_DLL_CTRL, SD0_DLL_OVF, 3, 1) | ||
616 | + FIELD(SD0_DLL_CTRL, SD0_DLL_RST, 2, 1) | ||
617 | + FIELD(SD0_DLL_CTRL, SD0_DLL_TESTMODE, 1, 1) | ||
618 | + FIELD(SD0_DLL_CTRL, SD0_DLL_LOCK, 0, 1) | ||
619 | +REG32(SD0_CDN_CTRL, 0x44c) | ||
620 | + FIELD(SD0_CDN_CTRL, SD0_CDN_CTRL, 0, 1) | ||
621 | +REG32(SD0_DLL_TEST, 0x450) | ||
622 | + FIELD(SD0_DLL_TEST, DLL_DIV, 16, 8) | ||
623 | + FIELD(SD0_DLL_TEST, DLL_TX_SEL, 9, 7) | ||
624 | + FIELD(SD0_DLL_TEST, DLL_RX_SEL, 0, 9) | ||
625 | +REG32(SD0_RX_TUNING_SEL, 0x454) | ||
626 | + FIELD(SD0_RX_TUNING_SEL, SD0_RX_SEL, 0, 9) | ||
627 | +REG32(SD0_DLL_DIV_MAP0, 0x458) | ||
628 | + FIELD(SD0_DLL_DIV_MAP0, DIV_3, 24, 8) | ||
629 | + FIELD(SD0_DLL_DIV_MAP0, DIV_2, 16, 8) | ||
630 | + FIELD(SD0_DLL_DIV_MAP0, DIV_1, 8, 8) | ||
631 | + FIELD(SD0_DLL_DIV_MAP0, DIV_0, 0, 8) | ||
632 | +REG32(SD0_DLL_DIV_MAP1, 0x45c) | ||
633 | + FIELD(SD0_DLL_DIV_MAP1, DIV_7, 24, 8) | ||
634 | + FIELD(SD0_DLL_DIV_MAP1, DIV_6, 16, 8) | ||
635 | + FIELD(SD0_DLL_DIV_MAP1, DIV_5, 8, 8) | ||
636 | + FIELD(SD0_DLL_DIV_MAP1, DIV_4, 0, 8) | ||
637 | +REG32(SD0_IOU_COHERENT_CTRL, 0x460) | ||
638 | + FIELD(SD0_IOU_COHERENT_CTRL, SD0_AXI_COH, 0, 4) | ||
639 | +REG32(SD0_IOU_INTERCONNECT_ROUTE, 0x464) | ||
640 | + FIELD(SD0_IOU_INTERCONNECT_ROUTE, SD0, 0, 1) | ||
641 | +REG32(SD0_IOU_RAM, 0x468) | ||
642 | + FIELD(SD0_IOU_RAM, EMASA0, 6, 1) | ||
643 | + FIELD(SD0_IOU_RAM, EMAB0, 3, 3) | ||
644 | + FIELD(SD0_IOU_RAM, EMAA0, 0, 3) | ||
645 | +REG32(SD0_IOU_INTERCONNECT_QOS, 0x46c) | ||
646 | + FIELD(SD0_IOU_INTERCONNECT_QOS, SD0_QOS, 0, 4) | ||
647 | +REG32(SD1_CLK_CTRL, 0x480) | ||
648 | + FIELD(SD1_CLK_CTRL, SDIO1_FBCLK_SEL, 1, 1) | ||
649 | + FIELD(SD1_CLK_CTRL, SDIO1_RX_SRC_SEL, 0, 1) | ||
650 | +REG32(SD1_CTRL_REG, 0x484) | ||
651 | + FIELD(SD1_CTRL_REG, SD1_EMMC_SEL, 0, 1) | ||
652 | +REG32(SD1_CONFIG_REG1, 0x490) | ||
653 | + FIELD(SD1_CONFIG_REG1, SD1_BASECLK, 7, 8) | ||
654 | + FIELD(SD1_CONFIG_REG1, SD1_TUNIGCOUNT, 1, 6) | ||
655 | + FIELD(SD1_CONFIG_REG1, SD1_ASYNCWKPENA, 0, 1) | ||
656 | +REG32(SD1_CONFIG_REG2, 0x494) | ||
657 | + FIELD(SD1_CONFIG_REG2, SD1_SLOTTYPE, 12, 2) | ||
658 | + FIELD(SD1_CONFIG_REG2, SD1_ASYCINTR, 11, 1) | ||
659 | + FIELD(SD1_CONFIG_REG2, SD1_64BIT, 10, 1) | ||
660 | + FIELD(SD1_CONFIG_REG2, SD1_1P8V, 9, 1) | ||
661 | + FIELD(SD1_CONFIG_REG2, SD1_3P0V, 8, 1) | ||
662 | + FIELD(SD1_CONFIG_REG2, SD1_3P3V, 7, 1) | ||
663 | + FIELD(SD1_CONFIG_REG2, SD1_SUSPRES, 6, 1) | ||
664 | + FIELD(SD1_CONFIG_REG2, SD1_SDMA, 5, 1) | ||
665 | + FIELD(SD1_CONFIG_REG2, SD1_HIGHSPEED, 4, 1) | ||
666 | + FIELD(SD1_CONFIG_REG2, SD1_ADMA2, 3, 1) | ||
667 | + FIELD(SD1_CONFIG_REG2, SD1_8BIT, 2, 1) | ||
668 | + FIELD(SD1_CONFIG_REG2, SD1_MAXBLK, 0, 2) | ||
669 | +REG32(SD1_CONFIG_REG3, 0x498) | ||
670 | + FIELD(SD1_CONFIG_REG3, SD1_TUNINGSDR50, 10, 1) | ||
671 | + FIELD(SD1_CONFIG_REG3, SD1_RETUNETMR, 6, 4) | ||
672 | + FIELD(SD1_CONFIG_REG3, SD1_DDRIVER, 5, 1) | ||
673 | + FIELD(SD1_CONFIG_REG3, SD1_CDRIVER, 4, 1) | ||
674 | + FIELD(SD1_CONFIG_REG3, SD1_ADRIVER, 3, 1) | ||
675 | + FIELD(SD1_CONFIG_REG3, SD1_DDR50, 2, 1) | ||
676 | + FIELD(SD1_CONFIG_REG3, SD1_SDR104, 1, 1) | ||
677 | + FIELD(SD1_CONFIG_REG3, SD1_SDR50, 0, 1) | ||
678 | +REG32(SD1_INITPRESET, 0x49c) | ||
679 | + FIELD(SD1_INITPRESET, SD1_INITPRESET, 0, 13) | ||
680 | +REG32(SD1_DSPPRESET, 0x4a0) | ||
681 | + FIELD(SD1_DSPPRESET, SD1_DSPPRESET, 0, 13) | ||
682 | +REG32(SD1_HSPDPRESET, 0x4a4) | ||
683 | + FIELD(SD1_HSPDPRESET, SD1_HSPDPRESET, 0, 13) | ||
684 | +REG32(SD1_SDR12PRESET, 0x4a8) | ||
685 | + FIELD(SD1_SDR12PRESET, SD1_SDR12PRESET, 0, 13) | ||
686 | +REG32(SD1_SDR25PRESET, 0x4ac) | ||
687 | + FIELD(SD1_SDR25PRESET, SD1_SDR25PRESET, 0, 13) | ||
688 | +REG32(SD1_SDR50PRSET, 0x4b0) | ||
689 | + FIELD(SD1_SDR50PRSET, SD1_SDR50PRESET, 0, 13) | ||
690 | +REG32(SD1_SDR104PRST, 0x4b4) | ||
691 | + FIELD(SD1_SDR104PRST, SD1_SDR104PRESET, 0, 13) | ||
692 | +REG32(SD1_DDR50PRESET, 0x4b8) | ||
693 | + FIELD(SD1_DDR50PRESET, SD1_DDR50PRESET, 0, 13) | ||
694 | +REG32(SD1_MAXCUR1P8, 0x4bc) | ||
695 | + FIELD(SD1_MAXCUR1P8, SD1_MAXCUR1P8, 0, 8) | ||
696 | +REG32(SD1_MAXCUR3P0, 0x4c0) | ||
697 | + FIELD(SD1_MAXCUR3P0, SD1_MAXCUR3P0, 0, 8) | ||
698 | +REG32(SD1_MAXCUR3P3, 0x4c4) | ||
699 | + FIELD(SD1_MAXCUR3P3, SD1_MAXCUR3P3, 0, 8) | ||
700 | +REG32(SD1_DLL_CTRL, 0x4c8) | ||
701 | + FIELD(SD1_DLL_CTRL, SD1_CLKSTABLE_CFG, 9, 1) | ||
702 | + FIELD(SD1_DLL_CTRL, SD1_DLL_CFG, 5, 4) | ||
703 | + FIELD(SD1_DLL_CTRL, SD1_DLL_PSDONE, 4, 1) | ||
704 | + FIELD(SD1_DLL_CTRL, SD1_DLL_OVF, 3, 1) | ||
705 | + FIELD(SD1_DLL_CTRL, SD1_DLL_RST, 2, 1) | ||
706 | + FIELD(SD1_DLL_CTRL, SD1_DLL_TESTMODE, 1, 1) | ||
707 | + FIELD(SD1_DLL_CTRL, SD1_DLL_LOCK, 0, 1) | ||
708 | +REG32(SD1_CDN_CTRL, 0x4cc) | ||
709 | + FIELD(SD1_CDN_CTRL, SD1_CDN_CTRL, 0, 1) | ||
710 | +REG32(SD1_DLL_TEST, 0x4d0) | ||
711 | + FIELD(SD1_DLL_TEST, DLL_DIV, 16, 8) | ||
712 | + FIELD(SD1_DLL_TEST, DLL_TX_SEL, 9, 7) | ||
713 | + FIELD(SD1_DLL_TEST, DLL_RX_SEL, 0, 9) | ||
714 | +REG32(SD1_RX_TUNING_SEL, 0x4d4) | ||
715 | + FIELD(SD1_RX_TUNING_SEL, SD1_RX_SEL, 0, 9) | ||
716 | +REG32(SD1_DLL_DIV_MAP0, 0x4d8) | ||
717 | + FIELD(SD1_DLL_DIV_MAP0, DIV_3, 24, 8) | ||
718 | + FIELD(SD1_DLL_DIV_MAP0, DIV_2, 16, 8) | ||
719 | + FIELD(SD1_DLL_DIV_MAP0, DIV_1, 8, 8) | ||
720 | + FIELD(SD1_DLL_DIV_MAP0, DIV_0, 0, 8) | ||
721 | +REG32(SD1_DLL_DIV_MAP1, 0x4dc) | ||
722 | + FIELD(SD1_DLL_DIV_MAP1, DIV_7, 24, 8) | ||
723 | + FIELD(SD1_DLL_DIV_MAP1, DIV_6, 16, 8) | ||
724 | + FIELD(SD1_DLL_DIV_MAP1, DIV_5, 8, 8) | ||
725 | + FIELD(SD1_DLL_DIV_MAP1, DIV_4, 0, 8) | ||
726 | +REG32(SD1_IOU_COHERENT_CTRL, 0x4e0) | ||
727 | + FIELD(SD1_IOU_COHERENT_CTRL, SD1_AXI_COH, 0, 4) | ||
728 | +REG32(SD1_IOU_INTERCONNECT_ROUTE, 0x4e4) | ||
729 | + FIELD(SD1_IOU_INTERCONNECT_ROUTE, SD1, 0, 1) | ||
730 | +REG32(SD1_IOU_RAM, 0x4e8) | ||
731 | + FIELD(SD1_IOU_RAM, EMASA0, 6, 1) | ||
732 | + FIELD(SD1_IOU_RAM, EMAB0, 3, 3) | ||
733 | + FIELD(SD1_IOU_RAM, EMAA0, 0, 3) | ||
734 | +REG32(SD1_IOU_INTERCONNECT_QOS, 0x4ec) | ||
735 | + FIELD(SD1_IOU_INTERCONNECT_QOS, SD1_QOS, 0, 4) | ||
736 | +REG32(OSPI_QSPI_IOU_AXI_MUX_SEL, 0x504) | ||
737 | + FIELD(OSPI_QSPI_IOU_AXI_MUX_SEL, OSPI_MUX_SEL, 1, 1) | ||
738 | + FIELD(OSPI_QSPI_IOU_AXI_MUX_SEL, QSPI_OSPI_MUX_SEL, 0, 1) | ||
739 | +REG32(QSPI_IOU_COHERENT_CTRL, 0x508) | ||
740 | + FIELD(QSPI_IOU_COHERENT_CTRL, QSPI_AXI_COH, 0, 4) | ||
741 | +REG32(QSPI_IOU_INTERCONNECT_ROUTE, 0x50c) | ||
742 | + FIELD(QSPI_IOU_INTERCONNECT_ROUTE, QSPI, 0, 1) | ||
743 | +REG32(QSPI_IOU_RAM, 0x510) | ||
744 | + FIELD(QSPI_IOU_RAM, EMASA1, 13, 1) | ||
745 | + FIELD(QSPI_IOU_RAM, EMAB1, 10, 3) | ||
746 | + FIELD(QSPI_IOU_RAM, EMAA1, 7, 3) | ||
747 | + FIELD(QSPI_IOU_RAM, EMASA0, 6, 1) | ||
748 | + FIELD(QSPI_IOU_RAM, EMAB0, 3, 3) | ||
749 | + FIELD(QSPI_IOU_RAM, EMAA0, 0, 3) | ||
750 | +REG32(QSPI_IOU_INTERCONNECT_QOS, 0x514) | ||
751 | + FIELD(QSPI_IOU_INTERCONNECT_QOS, QSPI_QOS, 0, 4) | ||
752 | +REG32(OSPI_IOU_COHERENT_CTRL, 0x530) | ||
753 | + FIELD(OSPI_IOU_COHERENT_CTRL, OSPI_AXI_COH, 0, 4) | ||
754 | +REG32(OSPI_IOU_INTERCONNECT_ROUTE, 0x534) | ||
755 | + FIELD(OSPI_IOU_INTERCONNECT_ROUTE, OSPI, 0, 1) | ||
756 | +REG32(OSPI_IOU_RAM, 0x538) | ||
757 | + FIELD(OSPI_IOU_RAM, EMAS0, 5, 1) | ||
758 | + FIELD(OSPI_IOU_RAM, EMAW0, 3, 2) | ||
759 | + FIELD(OSPI_IOU_RAM, EMA0, 0, 3) | ||
760 | +REG32(OSPI_IOU_INTERCONNECT_QOS, 0x53c) | ||
761 | + FIELD(OSPI_IOU_INTERCONNECT_QOS, OSPI_QOS, 0, 4) | ||
762 | +REG32(OSPI_REFCLK_DLY_CTRL, 0x540) | ||
763 | + FIELD(OSPI_REFCLK_DLY_CTRL, DLY1, 3, 2) | ||
764 | + FIELD(OSPI_REFCLK_DLY_CTRL, DLY0, 0, 3) | ||
765 | +REG32(CUR_PWR_ST, 0x600) | ||
766 | + FIELD(CUR_PWR_ST, U2PMU, 0, 2) | ||
767 | +REG32(CONNECT_ST, 0x604) | ||
768 | + FIELD(CONNECT_ST, U2PMU, 0, 1) | ||
769 | +REG32(PW_STATE_REQ, 0x608) | ||
770 | + FIELD(PW_STATE_REQ, BIT_1_0, 0, 2) | ||
771 | +REG32(HOST_U2_PORT_DISABLE, 0x60c) | ||
772 | + FIELD(HOST_U2_PORT_DISABLE, BIT_0, 0, 1) | ||
773 | +REG32(DBG_U2PMU, 0x610) | ||
774 | +REG32(DBG_U2PMU_EXT1, 0x614) | ||
775 | +REG32(DBG_U2PMU_EXT2, 0x618) | ||
776 | + FIELD(DBG_U2PMU_EXT2, BIT_67_64, 0, 4) | ||
777 | +REG32(PME_GEN_U2PMU, 0x61c) | ||
778 | + FIELD(PME_GEN_U2PMU, BIT_0, 0, 1) | ||
779 | +REG32(PWR_CONFIG_USB2, 0x620) | ||
780 | + FIELD(PWR_CONFIG_USB2, STRAP, 0, 30) | ||
781 | +REG32(PHY_HUB, 0x624) | ||
782 | + FIELD(PHY_HUB, VBUS_CTRL, 1, 1) | ||
783 | + FIELD(PHY_HUB, OVER_CURRENT, 0, 1) | ||
784 | +REG32(CTRL, 0x700) | ||
785 | + FIELD(CTRL, SLVERR_ENABLE, 0, 1) | ||
786 | +REG32(ISR, 0x800) | ||
787 | + FIELD(ISR, ADDR_DECODE_ERR, 0, 1) | ||
788 | +REG32(IMR, 0x804) | ||
789 | + FIELD(IMR, ADDR_DECODE_ERR, 0, 1) | ||
790 | +REG32(IER, 0x808) | ||
791 | + FIELD(IER, ADDR_DECODE_ERR, 0, 1) | ||
792 | +REG32(IDR, 0x80c) | ||
793 | + FIELD(IDR, ADDR_DECODE_ERR, 0, 1) | ||
794 | +REG32(ITR, 0x810) | ||
795 | + FIELD(ITR, ADDR_DECODE_ERR, 0, 1) | ||
796 | +REG32(PARITY_ISR, 0x814) | ||
797 | + FIELD(PARITY_ISR, PERR_AXI_SD1_IOU, 12, 1) | ||
798 | + FIELD(PARITY_ISR, PERR_AXI_SD0_IOU, 11, 1) | ||
799 | + FIELD(PARITY_ISR, PERR_AXI_QSPI_IOU, 10, 1) | ||
800 | + FIELD(PARITY_ISR, PERR_AXI_OSPI_IOU, 9, 1) | ||
801 | + FIELD(PARITY_ISR, PERR_IOU_SD1, 8, 1) | ||
802 | + FIELD(PARITY_ISR, PERR_IOU_SD0, 7, 1) | ||
803 | + FIELD(PARITY_ISR, PERR_IOU_QSPI1, 6, 1) | ||
804 | + FIELD(PARITY_ISR, PERR_IOUSLCR_SECURE_APB, 5, 1) | ||
805 | + FIELD(PARITY_ISR, PERR_IOUSLCR_APB, 4, 1) | ||
806 | + FIELD(PARITY_ISR, PERR_QSPI0_APB, 3, 1) | ||
807 | + FIELD(PARITY_ISR, PERR_OSPI_APB, 2, 1) | ||
808 | + FIELD(PARITY_ISR, PERR_I2C_APB, 1, 1) | ||
809 | + FIELD(PARITY_ISR, PERR_GPIO_APB, 0, 1) | ||
810 | +REG32(PARITY_IMR, 0x818) | ||
811 | + FIELD(PARITY_IMR, PERR_AXI_SD1_IOU, 12, 1) | ||
812 | + FIELD(PARITY_IMR, PERR_AXI_SD0_IOU, 11, 1) | ||
813 | + FIELD(PARITY_IMR, PERR_AXI_QSPI_IOU, 10, 1) | ||
814 | + FIELD(PARITY_IMR, PERR_AXI_OSPI_IOU, 9, 1) | ||
815 | + FIELD(PARITY_IMR, PERR_IOU_SD1, 8, 1) | ||
816 | + FIELD(PARITY_IMR, PERR_IOU_SD0, 7, 1) | ||
817 | + FIELD(PARITY_IMR, PERR_IOU_QSPI1, 6, 1) | ||
818 | + FIELD(PARITY_IMR, PERR_IOUSLCR_SECURE_APB, 5, 1) | ||
819 | + FIELD(PARITY_IMR, PERR_IOUSLCR_APB, 4, 1) | ||
820 | + FIELD(PARITY_IMR, PERR_QSPI0_APB, 3, 1) | ||
821 | + FIELD(PARITY_IMR, PERR_OSPI_APB, 2, 1) | ||
822 | + FIELD(PARITY_IMR, PERR_I2C_APB, 1, 1) | ||
823 | + FIELD(PARITY_IMR, PERR_GPIO_APB, 0, 1) | ||
824 | +REG32(PARITY_IER, 0x81c) | ||
825 | + FIELD(PARITY_IER, PERR_AXI_SD1_IOU, 12, 1) | ||
826 | + FIELD(PARITY_IER, PERR_AXI_SD0_IOU, 11, 1) | ||
827 | + FIELD(PARITY_IER, PERR_AXI_QSPI_IOU, 10, 1) | ||
828 | + FIELD(PARITY_IER, PERR_AXI_OSPI_IOU, 9, 1) | ||
829 | + FIELD(PARITY_IER, PERR_IOU_SD1, 8, 1) | ||
830 | + FIELD(PARITY_IER, PERR_IOU_SD0, 7, 1) | ||
831 | + FIELD(PARITY_IER, PERR_IOU_QSPI1, 6, 1) | ||
832 | + FIELD(PARITY_IER, PERR_IOUSLCR_SECURE_APB, 5, 1) | ||
833 | + FIELD(PARITY_IER, PERR_IOUSLCR_APB, 4, 1) | ||
834 | + FIELD(PARITY_IER, PERR_QSPI0_APB, 3, 1) | ||
835 | + FIELD(PARITY_IER, PERR_OSPI_APB, 2, 1) | ||
836 | + FIELD(PARITY_IER, PERR_I2C_APB, 1, 1) | ||
837 | + FIELD(PARITY_IER, PERR_GPIO_APB, 0, 1) | ||
838 | +REG32(PARITY_IDR, 0x820) | ||
839 | + FIELD(PARITY_IDR, PERR_AXI_SD1_IOU, 12, 1) | ||
840 | + FIELD(PARITY_IDR, PERR_AXI_SD0_IOU, 11, 1) | ||
841 | + FIELD(PARITY_IDR, PERR_AXI_QSPI_IOU, 10, 1) | ||
842 | + FIELD(PARITY_IDR, PERR_AXI_OSPI_IOU, 9, 1) | ||
843 | + FIELD(PARITY_IDR, PERR_IOU_SD1, 8, 1) | ||
844 | + FIELD(PARITY_IDR, PERR_IOU_SD0, 7, 1) | ||
845 | + FIELD(PARITY_IDR, PERR_IOU_QSPI1, 6, 1) | ||
846 | + FIELD(PARITY_IDR, PERR_IOUSLCR_SECURE_APB, 5, 1) | ||
847 | + FIELD(PARITY_IDR, PERR_IOUSLCR_APB, 4, 1) | ||
848 | + FIELD(PARITY_IDR, PERR_QSPI0_APB, 3, 1) | ||
849 | + FIELD(PARITY_IDR, PERR_OSPI_APB, 2, 1) | ||
850 | + FIELD(PARITY_IDR, PERR_I2C_APB, 1, 1) | ||
851 | + FIELD(PARITY_IDR, PERR_GPIO_APB, 0, 1) | ||
852 | +REG32(PARITY_ITR, 0x824) | ||
853 | + FIELD(PARITY_ITR, PERR_AXI_SD1_IOU, 12, 1) | ||
854 | + FIELD(PARITY_ITR, PERR_AXI_SD0_IOU, 11, 1) | ||
855 | + FIELD(PARITY_ITR, PERR_AXI_QSPI_IOU, 10, 1) | ||
856 | + FIELD(PARITY_ITR, PERR_AXI_OSPI_IOU, 9, 1) | ||
857 | + FIELD(PARITY_ITR, PERR_IOU_SD1, 8, 1) | ||
858 | + FIELD(PARITY_ITR, PERR_IOU_SD0, 7, 1) | ||
859 | + FIELD(PARITY_ITR, PERR_IOU_QSPI1, 6, 1) | ||
860 | + FIELD(PARITY_ITR, PERR_IOUSLCR_SECURE_APB, 5, 1) | ||
861 | + FIELD(PARITY_ITR, PERR_IOUSLCR_APB, 4, 1) | ||
862 | + FIELD(PARITY_ITR, PERR_QSPI0_APB, 3, 1) | ||
863 | + FIELD(PARITY_ITR, PERR_OSPI_APB, 2, 1) | ||
864 | + FIELD(PARITY_ITR, PERR_I2C_APB, 1, 1) | ||
865 | + FIELD(PARITY_ITR, PERR_GPIO_APB, 0, 1) | ||
866 | +REG32(WPROT0, 0x828) | ||
867 | + FIELD(WPROT0, ACTIVE, 0, 1) | ||
868 | + | ||
869 | +static void parity_imr_update_irq(XlnxVersalPmcIouSlcr *s) | ||
870 | +{ | ||
871 | + bool pending = s->regs[R_PARITY_ISR] & ~s->regs[R_PARITY_IMR]; | ||
872 | + qemu_set_irq(s->irq_parity_imr, pending); | ||
873 | +} | ||
874 | + | ||
875 | +static void parity_isr_postw(RegisterInfo *reg, uint64_t val64) | ||
876 | +{ | ||
877 | + XlnxVersalPmcIouSlcr *s = XILINX_VERSAL_PMC_IOU_SLCR(reg->opaque); | ||
878 | + parity_imr_update_irq(s); | ||
879 | +} | ||
880 | + | ||
881 | +static uint64_t parity_ier_prew(RegisterInfo *reg, uint64_t val64) | ||
882 | +{ | ||
883 | + XlnxVersalPmcIouSlcr *s = XILINX_VERSAL_PMC_IOU_SLCR(reg->opaque); | ||
884 | + uint32_t val = val64; | ||
885 | + | ||
886 | + s->regs[R_PARITY_IMR] &= ~val; | ||
887 | + parity_imr_update_irq(s); | ||
888 | + return 0; | ||
889 | +} | ||
890 | + | ||
891 | +static uint64_t parity_idr_prew(RegisterInfo *reg, uint64_t val64) | ||
892 | +{ | ||
893 | + XlnxVersalPmcIouSlcr *s = XILINX_VERSAL_PMC_IOU_SLCR(reg->opaque); | ||
894 | + uint32_t val = val64; | ||
895 | + | ||
896 | + s->regs[R_PARITY_IMR] |= val; | ||
897 | + parity_imr_update_irq(s); | ||
898 | + return 0; | ||
899 | +} | ||
900 | + | ||
901 | +static uint64_t parity_itr_prew(RegisterInfo *reg, uint64_t val64) | ||
902 | +{ | ||
903 | + XlnxVersalPmcIouSlcr *s = XILINX_VERSAL_PMC_IOU_SLCR(reg->opaque); | ||
904 | + uint32_t val = val64; | ||
905 | + | ||
906 | + s->regs[R_PARITY_ISR] |= val; | ||
907 | + parity_imr_update_irq(s); | ||
908 | + return 0; | ||
909 | +} | ||
910 | + | ||
911 | +static void imr_update_irq(XlnxVersalPmcIouSlcr *s) | ||
912 | +{ | ||
913 | + bool pending = s->regs[R_ISR] & ~s->regs[R_IMR]; | ||
914 | + qemu_set_irq(s->irq_imr, pending); | ||
915 | +} | ||
916 | + | ||
917 | +static void isr_postw(RegisterInfo *reg, uint64_t val64) | ||
918 | +{ | ||
919 | + XlnxVersalPmcIouSlcr *s = XILINX_VERSAL_PMC_IOU_SLCR(reg->opaque); | ||
920 | + imr_update_irq(s); | ||
921 | +} | ||
922 | + | ||
923 | +static uint64_t ier_prew(RegisterInfo *reg, uint64_t val64) | ||
924 | +{ | ||
925 | + XlnxVersalPmcIouSlcr *s = XILINX_VERSAL_PMC_IOU_SLCR(reg->opaque); | ||
926 | + uint32_t val = val64; | ||
927 | + | ||
928 | + s->regs[R_IMR] &= ~val; | ||
929 | + imr_update_irq(s); | ||
930 | + return 0; | ||
931 | +} | ||
932 | + | ||
933 | +static uint64_t idr_prew(RegisterInfo *reg, uint64_t val64) | ||
934 | +{ | ||
935 | + XlnxVersalPmcIouSlcr *s = XILINX_VERSAL_PMC_IOU_SLCR(reg->opaque); | ||
936 | + uint32_t val = val64; | ||
937 | + | ||
938 | + s->regs[R_IMR] |= val; | ||
939 | + imr_update_irq(s); | ||
940 | + return 0; | ||
941 | +} | ||
942 | + | ||
943 | +static uint64_t itr_prew(RegisterInfo *reg, uint64_t val64) | ||
944 | +{ | ||
945 | + XlnxVersalPmcIouSlcr *s = XILINX_VERSAL_PMC_IOU_SLCR(reg->opaque); | ||
946 | + uint32_t val = val64; | ||
947 | + | ||
948 | + s->regs[R_ISR] |= val; | ||
949 | + imr_update_irq(s); | ||
950 | + return 0; | ||
951 | +} | ||
952 | + | ||
953 | +static uint64_t sd0_ctrl_reg_prew(RegisterInfo *reg, uint64_t val64) | ||
954 | +{ | ||
955 | + XlnxVersalPmcIouSlcr *s = XILINX_VERSAL_PMC_IOU_SLCR(reg->opaque); | ||
956 | + uint32_t prev = ARRAY_FIELD_EX32(s->regs, SD0_CTRL_REG, SD0_EMMC_SEL); | ||
957 | + | ||
958 | + if (prev != (val64 & R_SD0_CTRL_REG_SD0_EMMC_SEL_MASK)) { | ||
959 | + qemu_set_irq(s->sd_emmc_sel[0], !!val64); | ||
960 | + } | ||
961 | + | ||
962 | + return val64; | ||
963 | +} | ||
964 | + | ||
965 | +static uint64_t sd1_ctrl_reg_prew(RegisterInfo *reg, uint64_t val64) | ||
966 | +{ | ||
967 | + XlnxVersalPmcIouSlcr *s = XILINX_VERSAL_PMC_IOU_SLCR(reg->opaque); | ||
968 | + uint32_t prev = ARRAY_FIELD_EX32(s->regs, SD1_CTRL_REG, SD1_EMMC_SEL); | ||
969 | + | ||
970 | + if (prev != (val64 & R_SD1_CTRL_REG_SD1_EMMC_SEL_MASK)) { | ||
971 | + qemu_set_irq(s->sd_emmc_sel[1], !!val64); | ||
972 | + } | ||
973 | + | ||
974 | + return val64; | ||
975 | +} | ||
976 | + | ||
977 | +static uint64_t ospi_qspi_iou_axi_mux_sel_prew(RegisterInfo *reg, | ||
978 | + uint64_t val64) | ||
979 | +{ | ||
980 | + XlnxVersalPmcIouSlcr *s = XILINX_VERSAL_PMC_IOU_SLCR(reg->opaque); | ||
981 | + uint32_t val32 = (uint32_t) val64; | ||
982 | + uint8_t ospi_mux_sel = FIELD_EX32(val32, OSPI_QSPI_IOU_AXI_MUX_SEL, | ||
983 | + OSPI_MUX_SEL); | ||
984 | + uint8_t qspi_ospi_mux_sel = FIELD_EX32(val32, OSPI_QSPI_IOU_AXI_MUX_SEL, | ||
985 | + QSPI_OSPI_MUX_SEL); | ||
986 | + | ||
987 | + if (ospi_mux_sel != | ||
988 | + ARRAY_FIELD_EX32(s->regs, OSPI_QSPI_IOU_AXI_MUX_SEL, OSPI_MUX_SEL)) { | ||
989 | + qemu_set_irq(s->ospi_mux_sel, !!ospi_mux_sel); | ||
990 | + } | ||
991 | + | ||
992 | + if (qspi_ospi_mux_sel != | ||
993 | + ARRAY_FIELD_EX32(s->regs, OSPI_QSPI_IOU_AXI_MUX_SEL, | ||
994 | + QSPI_OSPI_MUX_SEL)) { | ||
995 | + qemu_set_irq(s->qspi_ospi_mux_sel, !!qspi_ospi_mux_sel); | ||
996 | + } | ||
997 | + | ||
998 | + return val64; | ||
999 | +} | ||
1000 | + | ||
1001 | +static RegisterAccessInfo pmc_iou_slcr_regs_info[] = { | ||
1002 | + { .name = "MIO_PIN_0", .addr = A_MIO_PIN_0, | ||
1003 | + .rsvd = 0xfffffc01, | ||
1004 | + },{ .name = "MIO_PIN_1", .addr = A_MIO_PIN_1, | ||
1005 | + .rsvd = 0xfffffc01, | ||
1006 | + },{ .name = "MIO_PIN_2", .addr = A_MIO_PIN_2, | ||
1007 | + .rsvd = 0xfffffc01, | ||
1008 | + },{ .name = "MIO_PIN_3", .addr = A_MIO_PIN_3, | ||
1009 | + .rsvd = 0xfffffc01, | ||
1010 | + },{ .name = "MIO_PIN_4", .addr = A_MIO_PIN_4, | ||
1011 | + .rsvd = 0xfffffc01, | ||
1012 | + },{ .name = "MIO_PIN_5", .addr = A_MIO_PIN_5, | ||
1013 | + .rsvd = 0xfffffc01, | ||
1014 | + },{ .name = "MIO_PIN_6", .addr = A_MIO_PIN_6, | ||
1015 | + .rsvd = 0xfffffc01, | ||
1016 | + },{ .name = "MIO_PIN_7", .addr = A_MIO_PIN_7, | ||
1017 | + .rsvd = 0xfffffc01, | ||
1018 | + },{ .name = "MIO_PIN_8", .addr = A_MIO_PIN_8, | ||
1019 | + .rsvd = 0xfffffc01, | ||
1020 | + },{ .name = "MIO_PIN_9", .addr = A_MIO_PIN_9, | ||
1021 | + .rsvd = 0xfffffc01, | ||
1022 | + },{ .name = "MIO_PIN_10", .addr = A_MIO_PIN_10, | ||
1023 | + .rsvd = 0xfffffc01, | ||
1024 | + },{ .name = "MIO_PIN_11", .addr = A_MIO_PIN_11, | ||
1025 | + .rsvd = 0xfffffc01, | ||
1026 | + },{ .name = "MIO_PIN_12", .addr = A_MIO_PIN_12, | ||
1027 | + .rsvd = 0xfffffc01, | ||
1028 | + },{ .name = "MIO_PIN_13", .addr = A_MIO_PIN_13, | ||
1029 | + .rsvd = 0xfffffc01, | ||
1030 | + },{ .name = "MIO_PIN_14", .addr = A_MIO_PIN_14, | ||
1031 | + .rsvd = 0xfffffc01, | ||
1032 | + },{ .name = "MIO_PIN_15", .addr = A_MIO_PIN_15, | ||
1033 | + .rsvd = 0xfffffc01, | ||
1034 | + },{ .name = "MIO_PIN_16", .addr = A_MIO_PIN_16, | ||
1035 | + .rsvd = 0xfffffc01, | ||
1036 | + },{ .name = "MIO_PIN_17", .addr = A_MIO_PIN_17, | ||
1037 | + .rsvd = 0xfffffc01, | ||
1038 | + },{ .name = "MIO_PIN_18", .addr = A_MIO_PIN_18, | ||
1039 | + .rsvd = 0xfffffc01, | ||
1040 | + },{ .name = "MIO_PIN_19", .addr = A_MIO_PIN_19, | ||
1041 | + .rsvd = 0xfffffc01, | ||
1042 | + },{ .name = "MIO_PIN_20", .addr = A_MIO_PIN_20, | ||
1043 | + .rsvd = 0xfffffc01, | ||
1044 | + },{ .name = "MIO_PIN_21", .addr = A_MIO_PIN_21, | ||
1045 | + .rsvd = 0xfffffc01, | ||
1046 | + },{ .name = "MIO_PIN_22", .addr = A_MIO_PIN_22, | ||
1047 | + .rsvd = 0xfffffc01, | ||
1048 | + },{ .name = "MIO_PIN_23", .addr = A_MIO_PIN_23, | ||
1049 | + .rsvd = 0xfffffc01, | ||
1050 | + },{ .name = "MIO_PIN_24", .addr = A_MIO_PIN_24, | ||
1051 | + .rsvd = 0xfffffc01, | ||
1052 | + },{ .name = "MIO_PIN_25", .addr = A_MIO_PIN_25, | ||
1053 | + .rsvd = 0xfffffc01, | ||
1054 | + },{ .name = "MIO_PIN_26", .addr = A_MIO_PIN_26, | ||
1055 | + .rsvd = 0xfffffc01, | ||
1056 | + },{ .name = "MIO_PIN_27", .addr = A_MIO_PIN_27, | ||
1057 | + .rsvd = 0xfffffc01, | ||
1058 | + },{ .name = "MIO_PIN_28", .addr = A_MIO_PIN_28, | ||
1059 | + .rsvd = 0xfffffc01, | ||
1060 | + },{ .name = "MIO_PIN_29", .addr = A_MIO_PIN_29, | ||
1061 | + .rsvd = 0xfffffc01, | ||
1062 | + },{ .name = "MIO_PIN_30", .addr = A_MIO_PIN_30, | ||
1063 | + .rsvd = 0xfffffc01, | ||
1064 | + },{ .name = "MIO_PIN_31", .addr = A_MIO_PIN_31, | ||
1065 | + .rsvd = 0xfffffc01, | ||
1066 | + },{ .name = "MIO_PIN_32", .addr = A_MIO_PIN_32, | ||
1067 | + .rsvd = 0xfffffc01, | ||
1068 | + },{ .name = "MIO_PIN_33", .addr = A_MIO_PIN_33, | ||
1069 | + .rsvd = 0xfffffc01, | ||
1070 | + },{ .name = "MIO_PIN_34", .addr = A_MIO_PIN_34, | ||
1071 | + .rsvd = 0xfffffc01, | ||
1072 | + },{ .name = "MIO_PIN_35", .addr = A_MIO_PIN_35, | ||
1073 | + .rsvd = 0xfffffc01, | ||
1074 | + },{ .name = "MIO_PIN_36", .addr = A_MIO_PIN_36, | ||
1075 | + .rsvd = 0xfffffc01, | ||
1076 | + },{ .name = "MIO_PIN_37", .addr = A_MIO_PIN_37, | ||
1077 | + .rsvd = 0xfffffc01, | ||
1078 | + },{ .name = "MIO_PIN_38", .addr = A_MIO_PIN_38, | ||
1079 | + .rsvd = 0xfffffc01, | ||
1080 | + },{ .name = "MIO_PIN_39", .addr = A_MIO_PIN_39, | ||
1081 | + .rsvd = 0xfffffc01, | ||
1082 | + },{ .name = "MIO_PIN_40", .addr = A_MIO_PIN_40, | ||
1083 | + .rsvd = 0xfffffc01, | ||
1084 | + },{ .name = "MIO_PIN_41", .addr = A_MIO_PIN_41, | ||
1085 | + .rsvd = 0xfffffc01, | ||
1086 | + },{ .name = "MIO_PIN_42", .addr = A_MIO_PIN_42, | ||
1087 | + .rsvd = 0xfffffc01, | ||
1088 | + },{ .name = "MIO_PIN_43", .addr = A_MIO_PIN_43, | ||
1089 | + .rsvd = 0xfffffc01, | ||
1090 | + },{ .name = "MIO_PIN_44", .addr = A_MIO_PIN_44, | ||
1091 | + .rsvd = 0xfffffc01, | ||
1092 | + },{ .name = "MIO_PIN_45", .addr = A_MIO_PIN_45, | ||
1093 | + .rsvd = 0xfffffc01, | ||
1094 | + },{ .name = "MIO_PIN_46", .addr = A_MIO_PIN_46, | ||
1095 | + .rsvd = 0xfffffc01, | ||
1096 | + },{ .name = "MIO_PIN_47", .addr = A_MIO_PIN_47, | ||
1097 | + .rsvd = 0xfffffc01, | ||
1098 | + },{ .name = "MIO_PIN_48", .addr = A_MIO_PIN_48, | ||
1099 | + .rsvd = 0xfffffc01, | ||
1100 | + },{ .name = "MIO_PIN_49", .addr = A_MIO_PIN_49, | ||
1101 | + .rsvd = 0xfffffc01, | ||
1102 | + },{ .name = "MIO_PIN_50", .addr = A_MIO_PIN_50, | ||
1103 | + .rsvd = 0xfffffc01, | ||
1104 | + },{ .name = "MIO_PIN_51", .addr = A_MIO_PIN_51, | ||
1105 | + .rsvd = 0xfffffc01, | ||
1106 | + },{ .name = "BNK0_EN_RX", .addr = A_BNK0_EN_RX, | ||
1107 | + .reset = 0x3ffffff, | ||
1108 | + .rsvd = 0xfc000000, | ||
1109 | + },{ .name = "BNK0_SEL_RX0", .addr = A_BNK0_SEL_RX0, | ||
1110 | + .reset = 0xffffffff, | ||
1111 | + },{ .name = "BNK0_SEL_RX1", .addr = A_BNK0_SEL_RX1, | ||
1112 | + .reset = 0xfffff, | ||
1113 | + .rsvd = 0xfff00000, | ||
1114 | + },{ .name = "BNK0_EN_RX_SCHMITT_HYST", .addr = A_BNK0_EN_RX_SCHMITT_HYST, | ||
1115 | + .rsvd = 0xfc000000, | ||
1116 | + },{ .name = "BNK0_EN_WK_PD", .addr = A_BNK0_EN_WK_PD, | ||
1117 | + .rsvd = 0xfc000000, | ||
1118 | + },{ .name = "BNK0_EN_WK_PU", .addr = A_BNK0_EN_WK_PU, | ||
1119 | + .reset = 0x3ffffff, | ||
1120 | + .rsvd = 0xfc000000, | ||
1121 | + },{ .name = "BNK0_SEL_DRV0", .addr = A_BNK0_SEL_DRV0, | ||
1122 | + .reset = 0xffffffff, | ||
1123 | + },{ .name = "BNK0_SEL_DRV1", .addr = A_BNK0_SEL_DRV1, | ||
1124 | + .reset = 0xfffff, | ||
1125 | + .rsvd = 0xfff00000, | ||
1126 | + },{ .name = "BNK0_SEL_SLEW", .addr = A_BNK0_SEL_SLEW, | ||
1127 | + .rsvd = 0xfc000000, | ||
1128 | + },{ .name = "BNK0_EN_DFT_OPT_INV", .addr = A_BNK0_EN_DFT_OPT_INV, | ||
1129 | + .rsvd = 0xfc000000, | ||
1130 | + },{ .name = "BNK0_EN_PAD2PAD_LOOPBACK", | ||
1131 | + .addr = A_BNK0_EN_PAD2PAD_LOOPBACK, | ||
1132 | + .rsvd = 0xffffe000, | ||
1133 | + },{ .name = "BNK0_RX_SPARE0", .addr = A_BNK0_RX_SPARE0, | ||
1134 | + },{ .name = "BNK0_RX_SPARE1", .addr = A_BNK0_RX_SPARE1, | ||
1135 | + .rsvd = 0xfff00000, | ||
1136 | + },{ .name = "BNK0_TX_SPARE0", .addr = A_BNK0_TX_SPARE0, | ||
1137 | + },{ .name = "BNK0_TX_SPARE1", .addr = A_BNK0_TX_SPARE1, | ||
1138 | + .rsvd = 0xfff00000, | ||
1139 | + },{ .name = "BNK0_SEL_EN1P8", .addr = A_BNK0_SEL_EN1P8, | ||
1140 | + .rsvd = 0xfffffffe, | ||
1141 | + },{ .name = "BNK0_EN_B_POR_DETECT", .addr = A_BNK0_EN_B_POR_DETECT, | ||
1142 | + .rsvd = 0xfffffffe, | ||
1143 | + },{ .name = "BNK0_LPF_BYP_POR_DETECT", .addr = A_BNK0_LPF_BYP_POR_DETECT, | ||
1144 | + .reset = 0x1, | ||
1145 | + .rsvd = 0xfffffffe, | ||
1146 | + },{ .name = "BNK0_EN_LATCH", .addr = A_BNK0_EN_LATCH, | ||
1147 | + .rsvd = 0xfffffffe, | ||
1148 | + },{ .name = "BNK0_VBG_LPF_BYP_B", .addr = A_BNK0_VBG_LPF_BYP_B, | ||
1149 | + .reset = 0x1, | ||
1150 | + .rsvd = 0xfffffffe, | ||
1151 | + },{ .name = "BNK0_EN_AMP_B", .addr = A_BNK0_EN_AMP_B, | ||
1152 | + .rsvd = 0xfffffffc, | ||
1153 | + },{ .name = "BNK0_SPARE_BIAS", .addr = A_BNK0_SPARE_BIAS, | ||
1154 | + .rsvd = 0xfffffff0, | ||
1155 | + },{ .name = "BNK0_DRIVER_BIAS", .addr = A_BNK0_DRIVER_BIAS, | ||
1156 | + .rsvd = 0xffff8000, | ||
1157 | + },{ .name = "BNK0_VMODE", .addr = A_BNK0_VMODE, | ||
1158 | + .rsvd = 0xfffffffe, | ||
1159 | + .ro = 0x1, | ||
1160 | + },{ .name = "BNK0_SEL_AUX_IO_RX", .addr = A_BNK0_SEL_AUX_IO_RX, | ||
1161 | + .rsvd = 0xfc000000, | ||
1162 | + },{ .name = "BNK0_EN_TX_HS_MODE", .addr = A_BNK0_EN_TX_HS_MODE, | ||
1163 | + .rsvd = 0xfc000000, | ||
1164 | + },{ .name = "MIO_MST_TRI0", .addr = A_MIO_MST_TRI0, | ||
1165 | + .reset = 0x3ffffff, | ||
1166 | + .rsvd = 0xfc000000, | ||
1167 | + },{ .name = "MIO_MST_TRI1", .addr = A_MIO_MST_TRI1, | ||
1168 | + .reset = 0x3ffffff, | ||
1169 | + .rsvd = 0xfc000000, | ||
1170 | + },{ .name = "BNK1_EN_RX", .addr = A_BNK1_EN_RX, | ||
1171 | + .reset = 0x3ffffff, | ||
1172 | + .rsvd = 0xfc000000, | ||
1173 | + },{ .name = "BNK1_SEL_RX0", .addr = A_BNK1_SEL_RX0, | ||
1174 | + .reset = 0xffffffff, | ||
1175 | + },{ .name = "BNK1_SEL_RX1", .addr = A_BNK1_SEL_RX1, | ||
1176 | + .reset = 0xfffff, | ||
1177 | + .rsvd = 0xfff00000, | ||
1178 | + },{ .name = "BNK1_EN_RX_SCHMITT_HYST", .addr = A_BNK1_EN_RX_SCHMITT_HYST, | ||
1179 | + .rsvd = 0xfc000000, | ||
1180 | + },{ .name = "BNK1_EN_WK_PD", .addr = A_BNK1_EN_WK_PD, | ||
1181 | + .rsvd = 0xfc000000, | ||
1182 | + },{ .name = "BNK1_EN_WK_PU", .addr = A_BNK1_EN_WK_PU, | ||
1183 | + .reset = 0x3ffffff, | ||
1184 | + .rsvd = 0xfc000000, | ||
1185 | + },{ .name = "BNK1_SEL_DRV0", .addr = A_BNK1_SEL_DRV0, | ||
1186 | + .reset = 0xffffffff, | ||
1187 | + },{ .name = "BNK1_SEL_DRV1", .addr = A_BNK1_SEL_DRV1, | ||
1188 | + .reset = 0xfffff, | ||
1189 | + .rsvd = 0xfff00000, | ||
1190 | + },{ .name = "BNK1_SEL_SLEW", .addr = A_BNK1_SEL_SLEW, | ||
1191 | + .rsvd = 0xfc000000, | ||
1192 | + },{ .name = "BNK1_EN_DFT_OPT_INV", .addr = A_BNK1_EN_DFT_OPT_INV, | ||
1193 | + .rsvd = 0xfc000000, | ||
1194 | + },{ .name = "BNK1_EN_PAD2PAD_LOOPBACK", | ||
1195 | + .addr = A_BNK1_EN_PAD2PAD_LOOPBACK, | ||
1196 | + .rsvd = 0xffffe000, | ||
1197 | + },{ .name = "BNK1_RX_SPARE0", .addr = A_BNK1_RX_SPARE0, | ||
1198 | + },{ .name = "BNK1_RX_SPARE1", .addr = A_BNK1_RX_SPARE1, | ||
1199 | + .rsvd = 0xfff00000, | ||
1200 | + },{ .name = "BNK1_TX_SPARE0", .addr = A_BNK1_TX_SPARE0, | ||
1201 | + },{ .name = "BNK1_TX_SPARE1", .addr = A_BNK1_TX_SPARE1, | ||
1202 | + .rsvd = 0xfff00000, | ||
1203 | + },{ .name = "BNK1_SEL_EN1P8", .addr = A_BNK1_SEL_EN1P8, | ||
1204 | + .rsvd = 0xfffffffe, | ||
1205 | + },{ .name = "BNK1_EN_B_POR_DETECT", .addr = A_BNK1_EN_B_POR_DETECT, | ||
1206 | + .rsvd = 0xfffffffe, | ||
1207 | + },{ .name = "BNK1_LPF_BYP_POR_DETECT", .addr = A_BNK1_LPF_BYP_POR_DETECT, | ||
1208 | + .reset = 0x1, | ||
1209 | + .rsvd = 0xfffffffe, | ||
1210 | + },{ .name = "BNK1_EN_LATCH", .addr = A_BNK1_EN_LATCH, | ||
1211 | + .rsvd = 0xfffffffe, | ||
1212 | + },{ .name = "BNK1_VBG_LPF_BYP_B", .addr = A_BNK1_VBG_LPF_BYP_B, | ||
1213 | + .reset = 0x1, | ||
1214 | + .rsvd = 0xfffffffe, | ||
1215 | + },{ .name = "BNK1_EN_AMP_B", .addr = A_BNK1_EN_AMP_B, | ||
1216 | + .rsvd = 0xfffffffc, | ||
1217 | + },{ .name = "BNK1_SPARE_BIAS", .addr = A_BNK1_SPARE_BIAS, | ||
1218 | + .rsvd = 0xfffffff0, | ||
1219 | + },{ .name = "BNK1_DRIVER_BIAS", .addr = A_BNK1_DRIVER_BIAS, | ||
1220 | + .rsvd = 0xffff8000, | ||
1221 | + },{ .name = "BNK1_VMODE", .addr = A_BNK1_VMODE, | ||
1222 | + .rsvd = 0xfffffffe, | ||
1223 | + .ro = 0x1, | ||
1224 | + },{ .name = "BNK1_SEL_AUX_IO_RX", .addr = A_BNK1_SEL_AUX_IO_RX, | ||
1225 | + .rsvd = 0xfc000000, | ||
1226 | + },{ .name = "BNK1_EN_TX_HS_MODE", .addr = A_BNK1_EN_TX_HS_MODE, | ||
1227 | + .rsvd = 0xfc000000, | ||
1228 | + },{ .name = "SD0_CLK_CTRL", .addr = A_SD0_CLK_CTRL, | ||
1229 | + .rsvd = 0xfffffff8, | ||
1230 | + },{ .name = "SD0_CTRL_REG", .addr = A_SD0_CTRL_REG, | ||
1231 | + .rsvd = 0xfffffffe, | ||
1232 | + .pre_write = sd0_ctrl_reg_prew, | ||
1233 | + },{ .name = "SD0_CONFIG_REG1", .addr = A_SD0_CONFIG_REG1, | ||
1234 | + .reset = 0x3250, | ||
1235 | + .rsvd = 0xffff8000, | ||
1236 | + },{ .name = "SD0_CONFIG_REG2", .addr = A_SD0_CONFIG_REG2, | ||
1237 | + .reset = 0xffc, | ||
1238 | + .rsvd = 0xffffc000, | ||
1239 | + },{ .name = "SD0_CONFIG_REG3", .addr = A_SD0_CONFIG_REG3, | ||
1240 | + .reset = 0x407, | ||
1241 | + .rsvd = 0xfffff800, | ||
1242 | + },{ .name = "SD0_INITPRESET", .addr = A_SD0_INITPRESET, | ||
1243 | + .reset = 0x100, | ||
1244 | + .rsvd = 0xffffe000, | ||
1245 | + },{ .name = "SD0_DSPPRESET", .addr = A_SD0_DSPPRESET, | ||
1246 | + .reset = 0x4, | ||
1247 | + .rsvd = 0xffffe000, | ||
1248 | + },{ .name = "SD0_HSPDPRESET", .addr = A_SD0_HSPDPRESET, | ||
1249 | + .reset = 0x2, | ||
1250 | + .rsvd = 0xffffe000, | ||
1251 | + },{ .name = "SD0_SDR12PRESET", .addr = A_SD0_SDR12PRESET, | ||
1252 | + .reset = 0x4, | ||
1253 | + .rsvd = 0xffffe000, | ||
1254 | + },{ .name = "SD0_SDR25PRESET", .addr = A_SD0_SDR25PRESET, | ||
1255 | + .reset = 0x2, | ||
1256 | + .rsvd = 0xffffe000, | ||
1257 | + },{ .name = "SD0_SDR50PRSET", .addr = A_SD0_SDR50PRSET, | ||
1258 | + .reset = 0x1, | ||
1259 | + .rsvd = 0xffffe000, | ||
1260 | + },{ .name = "SD0_SDR104PRST", .addr = A_SD0_SDR104PRST, | ||
1261 | + .rsvd = 0xffffe000, | ||
1262 | + },{ .name = "SD0_DDR50PRESET", .addr = A_SD0_DDR50PRESET, | ||
1263 | + .reset = 0x2, | ||
1264 | + .rsvd = 0xffffe000, | ||
1265 | + },{ .name = "SD0_MAXCUR1P8", .addr = A_SD0_MAXCUR1P8, | ||
1266 | + .rsvd = 0xffffff00, | ||
1267 | + },{ .name = "SD0_MAXCUR3P0", .addr = A_SD0_MAXCUR3P0, | ||
1268 | + .rsvd = 0xffffff00, | ||
1269 | + },{ .name = "SD0_MAXCUR3P3", .addr = A_SD0_MAXCUR3P3, | ||
1270 | + .rsvd = 0xffffff00, | ||
1271 | + },{ .name = "SD0_DLL_CTRL", .addr = A_SD0_DLL_CTRL, | ||
1272 | + .reset = 0x1, | ||
1273 | + .rsvd = 0xfffffc00, | ||
1274 | + .ro = 0x19, | ||
1275 | + },{ .name = "SD0_CDN_CTRL", .addr = A_SD0_CDN_CTRL, | ||
1276 | + .rsvd = 0xfffffffe, | ||
1277 | + },{ .name = "SD0_DLL_TEST", .addr = A_SD0_DLL_TEST, | ||
1278 | + .rsvd = 0xff000000, | ||
1279 | + },{ .name = "SD0_RX_TUNING_SEL", .addr = A_SD0_RX_TUNING_SEL, | ||
1280 | + .rsvd = 0xfffffe00, | ||
1281 | + .ro = 0x1ff, | ||
1282 | + },{ .name = "SD0_DLL_DIV_MAP0", .addr = A_SD0_DLL_DIV_MAP0, | ||
1283 | + .reset = 0x50505050, | ||
1284 | + },{ .name = "SD0_DLL_DIV_MAP1", .addr = A_SD0_DLL_DIV_MAP1, | ||
1285 | + .reset = 0x50505050, | ||
1286 | + },{ .name = "SD0_IOU_COHERENT_CTRL", .addr = A_SD0_IOU_COHERENT_CTRL, | ||
1287 | + .rsvd = 0xfffffff0, | ||
1288 | + },{ .name = "SD0_IOU_INTERCONNECT_ROUTE", | ||
1289 | + .addr = A_SD0_IOU_INTERCONNECT_ROUTE, | ||
1290 | + .rsvd = 0xfffffffe, | ||
1291 | + },{ .name = "SD0_IOU_RAM", .addr = A_SD0_IOU_RAM, | ||
1292 | + .reset = 0x24, | ||
1293 | + .rsvd = 0xffffff80, | ||
1294 | + },{ .name = "SD0_IOU_INTERCONNECT_QOS", | ||
1295 | + .addr = A_SD0_IOU_INTERCONNECT_QOS, | ||
1296 | + .rsvd = 0xfffffff0, | ||
1297 | + },{ .name = "SD1_CLK_CTRL", .addr = A_SD1_CLK_CTRL, | ||
1298 | + .rsvd = 0xfffffffc, | ||
1299 | + },{ .name = "SD1_CTRL_REG", .addr = A_SD1_CTRL_REG, | ||
1300 | + .rsvd = 0xfffffffe, | ||
1301 | + .pre_write = sd1_ctrl_reg_prew, | ||
1302 | + },{ .name = "SD1_CONFIG_REG1", .addr = A_SD1_CONFIG_REG1, | ||
1303 | + .reset = 0x3250, | ||
1304 | + .rsvd = 0xffff8000, | ||
1305 | + },{ .name = "SD1_CONFIG_REG2", .addr = A_SD1_CONFIG_REG2, | ||
1306 | + .reset = 0xffc, | ||
1307 | + .rsvd = 0xffffc000, | ||
1308 | + },{ .name = "SD1_CONFIG_REG3", .addr = A_SD1_CONFIG_REG3, | ||
1309 | + .reset = 0x407, | ||
1310 | + .rsvd = 0xfffff800, | ||
1311 | + },{ .name = "SD1_INITPRESET", .addr = A_SD1_INITPRESET, | ||
1312 | + .reset = 0x100, | ||
1313 | + .rsvd = 0xffffe000, | ||
1314 | + },{ .name = "SD1_DSPPRESET", .addr = A_SD1_DSPPRESET, | ||
1315 | + .reset = 0x4, | ||
1316 | + .rsvd = 0xffffe000, | ||
1317 | + },{ .name = "SD1_HSPDPRESET", .addr = A_SD1_HSPDPRESET, | ||
1318 | + .reset = 0x2, | ||
1319 | + .rsvd = 0xffffe000, | ||
1320 | + },{ .name = "SD1_SDR12PRESET", .addr = A_SD1_SDR12PRESET, | ||
1321 | + .reset = 0x4, | ||
1322 | + .rsvd = 0xffffe000, | ||
1323 | + },{ .name = "SD1_SDR25PRESET", .addr = A_SD1_SDR25PRESET, | ||
1324 | + .reset = 0x2, | ||
1325 | + .rsvd = 0xffffe000, | ||
1326 | + },{ .name = "SD1_SDR50PRSET", .addr = A_SD1_SDR50PRSET, | ||
1327 | + .reset = 0x1, | ||
1328 | + .rsvd = 0xffffe000, | ||
1329 | + },{ .name = "SD1_SDR104PRST", .addr = A_SD1_SDR104PRST, | ||
1330 | + .rsvd = 0xffffe000, | ||
1331 | + },{ .name = "SD1_DDR50PRESET", .addr = A_SD1_DDR50PRESET, | ||
1332 | + .reset = 0x2, | ||
1333 | + .rsvd = 0xffffe000, | ||
1334 | + },{ .name = "SD1_MAXCUR1P8", .addr = A_SD1_MAXCUR1P8, | ||
1335 | + .rsvd = 0xffffff00, | ||
1336 | + },{ .name = "SD1_MAXCUR3P0", .addr = A_SD1_MAXCUR3P0, | ||
1337 | + .rsvd = 0xffffff00, | ||
1338 | + },{ .name = "SD1_MAXCUR3P3", .addr = A_SD1_MAXCUR3P3, | ||
1339 | + .rsvd = 0xffffff00, | ||
1340 | + },{ .name = "SD1_DLL_CTRL", .addr = A_SD1_DLL_CTRL, | ||
1341 | + .reset = 0x1, | ||
1342 | + .rsvd = 0xfffffc00, | ||
1343 | + .ro = 0x19, | ||
1344 | + },{ .name = "SD1_CDN_CTRL", .addr = A_SD1_CDN_CTRL, | ||
1345 | + .rsvd = 0xfffffffe, | ||
1346 | + },{ .name = "SD1_DLL_TEST", .addr = A_SD1_DLL_TEST, | ||
1347 | + .rsvd = 0xff000000, | ||
1348 | + },{ .name = "SD1_RX_TUNING_SEL", .addr = A_SD1_RX_TUNING_SEL, | ||
1349 | + .rsvd = 0xfffffe00, | ||
1350 | + .ro = 0x1ff, | ||
1351 | + },{ .name = "SD1_DLL_DIV_MAP0", .addr = A_SD1_DLL_DIV_MAP0, | ||
1352 | + .reset = 0x50505050, | ||
1353 | + },{ .name = "SD1_DLL_DIV_MAP1", .addr = A_SD1_DLL_DIV_MAP1, | ||
1354 | + .reset = 0x50505050, | ||
1355 | + },{ .name = "SD1_IOU_COHERENT_CTRL", .addr = A_SD1_IOU_COHERENT_CTRL, | ||
1356 | + .rsvd = 0xfffffff0, | ||
1357 | + },{ .name = "SD1_IOU_INTERCONNECT_ROUTE", | ||
1358 | + .addr = A_SD1_IOU_INTERCONNECT_ROUTE, | ||
1359 | + .rsvd = 0xfffffffe, | ||
1360 | + },{ .name = "SD1_IOU_RAM", .addr = A_SD1_IOU_RAM, | ||
1361 | + .reset = 0x24, | ||
1362 | + .rsvd = 0xffffff80, | ||
1363 | + },{ .name = "SD1_IOU_INTERCONNECT_QOS", | ||
1364 | + .addr = A_SD1_IOU_INTERCONNECT_QOS, | ||
1365 | + .rsvd = 0xfffffff0, | ||
1366 | + },{ .name = "OSPI_QSPI_IOU_AXI_MUX_SEL", | ||
1367 | + .addr = A_OSPI_QSPI_IOU_AXI_MUX_SEL, | ||
1368 | + .reset = 0x1, | ||
1369 | + .rsvd = 0xfffffffc, | ||
1370 | + .pre_write = ospi_qspi_iou_axi_mux_sel_prew, | ||
1371 | + },{ .name = "QSPI_IOU_COHERENT_CTRL", .addr = A_QSPI_IOU_COHERENT_CTRL, | ||
1372 | + .rsvd = 0xfffffff0, | ||
1373 | + },{ .name = "QSPI_IOU_INTERCONNECT_ROUTE", | ||
1374 | + .addr = A_QSPI_IOU_INTERCONNECT_ROUTE, | ||
1375 | + .rsvd = 0xfffffffe, | ||
1376 | + },{ .name = "QSPI_IOU_RAM", .addr = A_QSPI_IOU_RAM, | ||
1377 | + .reset = 0x1224, | ||
1378 | + .rsvd = 0xffffc000, | ||
1379 | + },{ .name = "QSPI_IOU_INTERCONNECT_QOS", | ||
1380 | + .addr = A_QSPI_IOU_INTERCONNECT_QOS, | ||
1381 | + .rsvd = 0xfffffff0, | ||
1382 | + },{ .name = "OSPI_IOU_COHERENT_CTRL", .addr = A_OSPI_IOU_COHERENT_CTRL, | ||
1383 | + .rsvd = 0xfffffff0, | ||
1384 | + },{ .name = "OSPI_IOU_INTERCONNECT_ROUTE", | ||
1385 | + .addr = A_OSPI_IOU_INTERCONNECT_ROUTE, | ||
1386 | + .rsvd = 0xfffffffe, | ||
1387 | + },{ .name = "OSPI_IOU_RAM", .addr = A_OSPI_IOU_RAM, | ||
1388 | + .reset = 0xa, | ||
1389 | + .rsvd = 0xffffffc0, | ||
1390 | + },{ .name = "OSPI_IOU_INTERCONNECT_QOS", | ||
1391 | + .addr = A_OSPI_IOU_INTERCONNECT_QOS, | ||
1392 | + .rsvd = 0xfffffff0, | ||
1393 | + },{ .name = "OSPI_REFCLK_DLY_CTRL", .addr = A_OSPI_REFCLK_DLY_CTRL, | ||
1394 | + .reset = 0x13, | ||
1395 | + .rsvd = 0xffffffe0, | ||
1396 | + },{ .name = "CUR_PWR_ST", .addr = A_CUR_PWR_ST, | ||
1397 | + .rsvd = 0xfffffffc, | ||
1398 | + .ro = 0x3, | ||
1399 | + },{ .name = "CONNECT_ST", .addr = A_CONNECT_ST, | ||
1400 | + .rsvd = 0xfffffffe, | ||
1401 | + .ro = 0x1, | ||
1402 | + },{ .name = "PW_STATE_REQ", .addr = A_PW_STATE_REQ, | ||
1403 | + .rsvd = 0xfffffffc, | ||
1404 | + },{ .name = "HOST_U2_PORT_DISABLE", .addr = A_HOST_U2_PORT_DISABLE, | ||
1405 | + .rsvd = 0xfffffffe, | ||
1406 | + },{ .name = "DBG_U2PMU", .addr = A_DBG_U2PMU, | ||
1407 | + .ro = 0xffffffff, | ||
1408 | + },{ .name = "DBG_U2PMU_EXT1", .addr = A_DBG_U2PMU_EXT1, | ||
1409 | + .ro = 0xffffffff, | ||
1410 | + },{ .name = "DBG_U2PMU_EXT2", .addr = A_DBG_U2PMU_EXT2, | ||
1411 | + .rsvd = 0xfffffff0, | ||
1412 | + .ro = 0xf, | ||
1413 | + },{ .name = "PME_GEN_U2PMU", .addr = A_PME_GEN_U2PMU, | ||
1414 | + .rsvd = 0xfffffffe, | ||
1415 | + .ro = 0x1, | ||
1416 | + },{ .name = "PWR_CONFIG_USB2", .addr = A_PWR_CONFIG_USB2, | ||
1417 | + .rsvd = 0xc0000000, | ||
1418 | + },{ .name = "PHY_HUB", .addr = A_PHY_HUB, | ||
1419 | + .rsvd = 0xfffffffc, | ||
1420 | + .ro = 0x2, | ||
1421 | + },{ .name = "CTRL", .addr = A_CTRL, | ||
1422 | + },{ .name = "ISR", .addr = A_ISR, | ||
1423 | + .w1c = 0x1, | ||
1424 | + .post_write = isr_postw, | ||
1425 | + },{ .name = "IMR", .addr = A_IMR, | ||
1426 | + .reset = 0x1, | ||
1427 | + .ro = 0x1, | ||
1428 | + },{ .name = "IER", .addr = A_IER, | ||
1429 | + .pre_write = ier_prew, | ||
1430 | + },{ .name = "IDR", .addr = A_IDR, | ||
1431 | + .pre_write = idr_prew, | ||
1432 | + },{ .name = "ITR", .addr = A_ITR, | ||
1433 | + .pre_write = itr_prew, | ||
1434 | + },{ .name = "PARITY_ISR", .addr = A_PARITY_ISR, | ||
1435 | + .w1c = 0x1fff, | ||
1436 | + .post_write = parity_isr_postw, | ||
1437 | + },{ .name = "PARITY_IMR", .addr = A_PARITY_IMR, | ||
1438 | + .reset = 0x1fff, | ||
1439 | + .ro = 0x1fff, | ||
1440 | + },{ .name = "PARITY_IER", .addr = A_PARITY_IER, | ||
1441 | + .pre_write = parity_ier_prew, | ||
1442 | + },{ .name = "PARITY_IDR", .addr = A_PARITY_IDR, | ||
1443 | + .pre_write = parity_idr_prew, | ||
1444 | + },{ .name = "PARITY_ITR", .addr = A_PARITY_ITR, | ||
1445 | + .pre_write = parity_itr_prew, | ||
1446 | + },{ .name = "WPROT0", .addr = A_WPROT0, | ||
1447 | + .reset = 0x1, | ||
1448 | + } | ||
1449 | +}; | ||
1450 | + | ||
1451 | +static void xlnx_versal_pmc_iou_slcr_reset_init(Object *obj, ResetType type) | ||
1452 | +{ | ||
1453 | + XlnxVersalPmcIouSlcr *s = XILINX_VERSAL_PMC_IOU_SLCR(obj); | ||
1454 | + unsigned int i; | ||
1455 | + | ||
1456 | + for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) { | ||
1457 | + register_reset(&s->regs_info[i]); | ||
1458 | + } | ||
1459 | +} | ||
1460 | + | ||
1461 | +static void xlnx_versal_pmc_iou_slcr_reset_hold(Object *obj) | ||
1462 | +{ | ||
1463 | + XlnxVersalPmcIouSlcr *s = XILINX_VERSAL_PMC_IOU_SLCR(obj); | ||
1464 | + | ||
1465 | + parity_imr_update_irq(s); | ||
1466 | + imr_update_irq(s); | ||
1467 | + | ||
1468 | + /* | ||
1469 | + * Setup OSPI_QSPI mux | ||
1470 | + * By default axi slave interface is enabled for ospi-dma | ||
1471 | + */ | ||
1472 | + qemu_set_irq(s->ospi_mux_sel, 0); | ||
1473 | + qemu_set_irq(s->qspi_ospi_mux_sel, 1); | ||
1474 | +} | ||
1475 | + | ||
1476 | +static const MemoryRegionOps pmc_iou_slcr_ops = { | ||
1477 | + .read = register_read_memory, | ||
1478 | + .write = register_write_memory, | ||
1479 | + .endianness = DEVICE_LITTLE_ENDIAN, | ||
1480 | + .valid = { | ||
1481 | + .min_access_size = 4, | ||
1482 | + .max_access_size = 4, | ||
1483 | + }, | ||
1484 | +}; | ||
1485 | + | ||
1486 | +static void xlnx_versal_pmc_iou_slcr_realize(DeviceState *dev, Error **errp) | ||
1487 | +{ | ||
1488 | + XlnxVersalPmcIouSlcr *s = XILINX_VERSAL_PMC_IOU_SLCR(dev); | ||
1489 | + | ||
1490 | + qdev_init_gpio_out_named(dev, s->sd_emmc_sel, "sd-emmc-sel", 2); | ||
1491 | + qdev_init_gpio_out_named(dev, &s->qspi_ospi_mux_sel, | ||
1492 | + "qspi-ospi-mux-sel", 1); | ||
1493 | + qdev_init_gpio_out_named(dev, &s->ospi_mux_sel, "ospi-mux-sel", 1); | ||
1494 | +} | ||
1495 | + | ||
1496 | +static void xlnx_versal_pmc_iou_slcr_init(Object *obj) | ||
1497 | +{ | ||
1498 | + XlnxVersalPmcIouSlcr *s = XILINX_VERSAL_PMC_IOU_SLCR(obj); | ||
1499 | + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); | ||
1500 | + RegisterInfoArray *reg_array; | ||
1501 | + | ||
1502 | + memory_region_init(&s->iomem, obj, TYPE_XILINX_VERSAL_PMC_IOU_SLCR, | ||
1503 | + XILINX_VERSAL_PMC_IOU_SLCR_R_MAX * 4); | ||
1504 | + reg_array = | ||
1505 | + register_init_block32(DEVICE(obj), pmc_iou_slcr_regs_info, | ||
1506 | + ARRAY_SIZE(pmc_iou_slcr_regs_info), | ||
1507 | + s->regs_info, s->regs, | ||
1508 | + &pmc_iou_slcr_ops, | ||
1509 | + XILINX_VERSAL_PMC_IOU_SLCR_ERR_DEBUG, | ||
1510 | + XILINX_VERSAL_PMC_IOU_SLCR_R_MAX * 4); | ||
1511 | + memory_region_add_subregion(&s->iomem, | ||
1512 | + 0x0, | ||
1513 | + ®_array->mem); | ||
1514 | + sysbus_init_mmio(sbd, &s->iomem); | ||
1515 | + sysbus_init_irq(sbd, &s->irq_parity_imr); | ||
1516 | + sysbus_init_irq(sbd, &s->irq_imr); | ||
1517 | +} | ||
1518 | + | ||
1519 | +static const VMStateDescription vmstate_pmc_iou_slcr = { | ||
1520 | + .name = TYPE_XILINX_VERSAL_PMC_IOU_SLCR, | ||
1521 | + .version_id = 1, | ||
1522 | + .minimum_version_id = 1, | ||
1523 | + .fields = (VMStateField[]) { | ||
1524 | + VMSTATE_UINT32_ARRAY(regs, XlnxVersalPmcIouSlcr, | ||
1525 | + XILINX_VERSAL_PMC_IOU_SLCR_R_MAX), | ||
1526 | + VMSTATE_END_OF_LIST(), | ||
1527 | + } | ||
1528 | +}; | ||
1529 | + | ||
1530 | +static void xlnx_versal_pmc_iou_slcr_class_init(ObjectClass *klass, void *data) | ||
1531 | +{ | ||
1532 | + DeviceClass *dc = DEVICE_CLASS(klass); | ||
1533 | + ResettableClass *rc = RESETTABLE_CLASS(klass); | ||
1534 | + | ||
1535 | + dc->realize = xlnx_versal_pmc_iou_slcr_realize; | ||
1536 | + dc->vmsd = &vmstate_pmc_iou_slcr; | ||
1537 | + rc->phases.enter = xlnx_versal_pmc_iou_slcr_reset_init; | ||
1538 | + rc->phases.hold = xlnx_versal_pmc_iou_slcr_reset_hold; | ||
1539 | +} | ||
1540 | + | ||
1541 | +static const TypeInfo xlnx_versal_pmc_iou_slcr_info = { | ||
1542 | + .name = TYPE_XILINX_VERSAL_PMC_IOU_SLCR, | ||
1543 | + .parent = TYPE_SYS_BUS_DEVICE, | ||
1544 | + .instance_size = sizeof(XlnxVersalPmcIouSlcr), | ||
1545 | + .class_init = xlnx_versal_pmc_iou_slcr_class_init, | ||
1546 | + .instance_init = xlnx_versal_pmc_iou_slcr_init, | ||
1547 | +}; | ||
1548 | + | ||
1549 | +static void xlnx_versal_pmc_iou_slcr_register_types(void) | ||
1550 | +{ | ||
1551 | + type_register_static(&xlnx_versal_pmc_iou_slcr_info); | ||
1552 | +} | ||
1553 | + | ||
1554 | +type_init(xlnx_versal_pmc_iou_slcr_register_types) | ||
1555 | diff --git a/hw/misc/meson.build b/hw/misc/meson.build | ||
1556 | index XXXXXXX..XXXXXXX 100644 | ||
1557 | --- a/hw/misc/meson.build | ||
1558 | +++ b/hw/misc/meson.build | ||
1559 | @@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files( | ||
1560 | )) | ||
1561 | softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c')) | ||
1562 | softmmu_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c')) | ||
1563 | -softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-xramc.c')) | ||
1564 | +softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files( | ||
1565 | + 'xlnx-versal-xramc.c', | ||
1566 | + 'xlnx-versal-pmc-iou-slcr.c', | ||
1567 | +)) | ||
1568 | softmmu_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.c')) | ||
1569 | softmmu_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.c')) | ||
1570 | softmmu_ss.add(when: 'CONFIG_STM32F4XX_EXTI', if_true: files('stm32f4xx_exti.c')) | ||
1571 | -- | ||
1572 | 2.25.1 | ||
1573 | |||
1574 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
1 | 2 | ||
3 | Add an orgate and 'or' the interrupts from the BBRAM and RTC models. | ||
4 | |||
5 | Signed-off-by: Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
6 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
7 | Reviewed-by: Luc Michel <luc@lmichel.fr> | ||
8 | Message-id: 20220121161141.14389-3-francisco.iglesias@xilinx.com | ||
9 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
10 | --- | ||
11 | include/hw/arm/xlnx-versal.h | 5 +++-- | ||
12 | hw/arm/xlnx-versal-virt.c | 2 +- | ||
13 | hw/arm/xlnx-versal.c | 28 ++++++++++++++++++++++++++-- | ||
14 | 3 files changed, 30 insertions(+), 5 deletions(-) | ||
15 | |||
16 | diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h | ||
17 | index XXXXXXX..XXXXXXX 100644 | ||
18 | --- a/include/hw/arm/xlnx-versal.h | ||
19 | +++ b/include/hw/arm/xlnx-versal.h | ||
20 | @@ -XXX,XX +XXX,XX @@ struct Versal { | ||
21 | XlnxEFuse efuse; | ||
22 | XlnxVersalEFuseCtrl efuse_ctrl; | ||
23 | XlnxVersalEFuseCache efuse_cache; | ||
24 | + | ||
25 | + qemu_or_irq apb_irq_orgate; | ||
26 | } pmc; | ||
27 | |||
28 | struct { | ||
29 | @@ -XXX,XX +XXX,XX @@ struct Versal { | ||
30 | #define VERSAL_GEM1_WAKE_IRQ_0 59 | ||
31 | #define VERSAL_ADMA_IRQ_0 60 | ||
32 | #define VERSAL_XRAM_IRQ_0 79 | ||
33 | -#define VERSAL_BBRAM_APB_IRQ_0 121 | ||
34 | -#define VERSAL_RTC_APB_ERR_IRQ 121 | ||
35 | +#define VERSAL_PMC_APB_IRQ 121 | ||
36 | #define VERSAL_SD0_IRQ_0 126 | ||
37 | #define VERSAL_EFUSE_IRQ 139 | ||
38 | #define VERSAL_RTC_ALARM_IRQ 142 | ||
39 | diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c | ||
40 | index XXXXXXX..XXXXXXX 100644 | ||
41 | --- a/hw/arm/xlnx-versal-virt.c | ||
42 | +++ b/hw/arm/xlnx-versal-virt.c | ||
43 | @@ -XXX,XX +XXX,XX @@ static void fdt_add_bbram_node(VersalVirt *s) | ||
44 | qemu_fdt_add_subnode(s->fdt, name); | ||
45 | |||
46 | qemu_fdt_setprop_cells(s->fdt, name, "interrupts", | ||
47 | - GIC_FDT_IRQ_TYPE_SPI, VERSAL_BBRAM_APB_IRQ_0, | ||
48 | + GIC_FDT_IRQ_TYPE_SPI, VERSAL_PMC_APB_IRQ, | ||
49 | GIC_FDT_IRQ_FLAGS_LEVEL_HI); | ||
50 | qemu_fdt_setprop(s->fdt, name, "interrupt-names", | ||
51 | interrupt_names, sizeof(interrupt_names)); | ||
52 | diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c | ||
53 | index XXXXXXX..XXXXXXX 100644 | ||
54 | --- a/hw/arm/xlnx-versal.c | ||
55 | +++ b/hw/arm/xlnx-versal.c | ||
56 | @@ -XXX,XX +XXX,XX @@ | ||
57 | #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72") | ||
58 | #define GEM_REVISION 0x40070106 | ||
59 | |||
60 | +#define VERSAL_NUM_PMC_APB_IRQS 2 | ||
61 | + | ||
62 | static void versal_create_apu_cpus(Versal *s) | ||
63 | { | ||
64 | int i; | ||
65 | @@ -XXX,XX +XXX,XX @@ static void versal_create_sds(Versal *s, qemu_irq *pic) | ||
66 | } | ||
67 | } | ||
68 | |||
69 | +static void versal_create_pmc_apb_irq_orgate(Versal *s, qemu_irq *pic) | ||
70 | +{ | ||
71 | + DeviceState *orgate; | ||
72 | + | ||
73 | + /* | ||
74 | + * The VERSAL_PMC_APB_IRQ is an 'or' of the interrupts from the following | ||
75 | + * models: | ||
76 | + * - RTC | ||
77 | + * - BBRAM | ||
78 | + */ | ||
79 | + object_initialize_child(OBJECT(s), "pmc-apb-irq-orgate", | ||
80 | + &s->pmc.apb_irq_orgate, TYPE_OR_IRQ); | ||
81 | + orgate = DEVICE(&s->pmc.apb_irq_orgate); | ||
82 | + object_property_set_int(OBJECT(orgate), | ||
83 | + "num-lines", VERSAL_NUM_PMC_APB_IRQS, &error_fatal); | ||
84 | + qdev_realize(orgate, NULL, &error_fatal); | ||
85 | + qdev_connect_gpio_out(orgate, 0, pic[VERSAL_PMC_APB_IRQ]); | ||
86 | +} | ||
87 | + | ||
88 | static void versal_create_rtc(Versal *s, qemu_irq *pic) | ||
89 | { | ||
90 | SysBusDevice *sbd; | ||
91 | @@ -XXX,XX +XXX,XX @@ static void versal_create_rtc(Versal *s, qemu_irq *pic) | ||
92 | * TODO: Connect the ALARM and SECONDS interrupts once our RTC model | ||
93 | * supports them. | ||
94 | */ | ||
95 | - sysbus_connect_irq(sbd, 1, pic[VERSAL_RTC_APB_ERR_IRQ]); | ||
96 | + sysbus_connect_irq(sbd, 1, | ||
97 | + qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 0)); | ||
98 | } | ||
99 | |||
100 | static void versal_create_xrams(Versal *s, qemu_irq *pic) | ||
101 | @@ -XXX,XX +XXX,XX @@ static void versal_create_bbram(Versal *s, qemu_irq *pic) | ||
102 | sysbus_realize(sbd, &error_fatal); | ||
103 | memory_region_add_subregion(&s->mr_ps, MM_PMC_BBRAM_CTRL, | ||
104 | sysbus_mmio_get_region(sbd, 0)); | ||
105 | - sysbus_connect_irq(sbd, 0, pic[VERSAL_BBRAM_APB_IRQ_0]); | ||
106 | + sysbus_connect_irq(sbd, 0, | ||
107 | + qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 1)); | ||
108 | } | ||
109 | |||
110 | static void versal_realize_efuse_part(Versal *s, Object *dev, hwaddr base) | ||
111 | @@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp) | ||
112 | versal_create_gems(s, pic); | ||
113 | versal_create_admas(s, pic); | ||
114 | versal_create_sds(s, pic); | ||
115 | + versal_create_pmc_apb_irq_orgate(s, pic); | ||
116 | versal_create_rtc(s, pic); | ||
117 | versal_create_xrams(s, pic); | ||
118 | versal_create_bbram(s, pic); | ||
119 | -- | ||
120 | 2.25.1 | ||
121 | |||
122 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
1 | 2 | ||
3 | Connect Versal's PMC SLCR (system-level control registers) model. | ||
4 | |||
5 | Signed-off-by: Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
6 | Reviewed-by: Luc Michel <luc@lmichel.fr> | ||
7 | Message-id: 20220121161141.14389-4-francisco.iglesias@xilinx.com | ||
8 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
9 | --- | ||
10 | include/hw/arm/xlnx-versal.h | 5 +++ | ||
11 | hw/arm/xlnx-versal.c | 71 +++++++++++++++++++++++++++++++++++- | ||
12 | 2 files changed, 75 insertions(+), 1 deletion(-) | ||
13 | |||
14 | diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/include/hw/arm/xlnx-versal.h | ||
17 | +++ b/include/hw/arm/xlnx-versal.h | ||
18 | @@ -XXX,XX +XXX,XX @@ | ||
19 | #include "hw/misc/xlnx-versal-xramc.h" | ||
20 | #include "hw/nvram/xlnx-bbram.h" | ||
21 | #include "hw/nvram/xlnx-versal-efuse.h" | ||
22 | +#include "hw/misc/xlnx-versal-pmc-iou-slcr.h" | ||
23 | |||
24 | #define TYPE_XLNX_VERSAL "xlnx-versal" | ||
25 | OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL) | ||
26 | @@ -XXX,XX +XXX,XX @@ struct Versal { | ||
27 | struct { | ||
28 | struct { | ||
29 | SDHCIState sd[XLNX_VERSAL_NR_SDS]; | ||
30 | + XlnxVersalPmcIouSlcr slcr; | ||
31 | } iou; | ||
32 | |||
33 | XlnxZynqMPRTC rtc; | ||
34 | @@ -XXX,XX +XXX,XX @@ struct Versal { | ||
35 | #define MM_FPD_FPD_APU 0xfd5c0000 | ||
36 | #define MM_FPD_FPD_APU_SIZE 0x100 | ||
37 | |||
38 | +#define MM_PMC_PMC_IOU_SLCR 0xf1060000 | ||
39 | +#define MM_PMC_PMC_IOU_SLCR_SIZE 0x10000 | ||
40 | + | ||
41 | #define MM_PMC_SD0 0xf1040000U | ||
42 | #define MM_PMC_SD0_SIZE 0x10000 | ||
43 | #define MM_PMC_BBRAM_CTRL 0xf11f0000 | ||
44 | diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c | ||
45 | index XXXXXXX..XXXXXXX 100644 | ||
46 | --- a/hw/arm/xlnx-versal.c | ||
47 | +++ b/hw/arm/xlnx-versal.c | ||
48 | @@ -XXX,XX +XXX,XX @@ | ||
49 | #include "kvm_arm.h" | ||
50 | #include "hw/misc/unimp.h" | ||
51 | #include "hw/arm/xlnx-versal.h" | ||
52 | +#include "qemu/log.h" | ||
53 | +#include "hw/sysbus.h" | ||
54 | |||
55 | #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72") | ||
56 | #define GEM_REVISION 0x40070106 | ||
57 | |||
58 | -#define VERSAL_NUM_PMC_APB_IRQS 2 | ||
59 | +#define VERSAL_NUM_PMC_APB_IRQS 3 | ||
60 | |||
61 | static void versal_create_apu_cpus(Versal *s) | ||
62 | { | ||
63 | @@ -XXX,XX +XXX,XX @@ static void versal_create_pmc_apb_irq_orgate(Versal *s, qemu_irq *pic) | ||
64 | * models: | ||
65 | * - RTC | ||
66 | * - BBRAM | ||
67 | + * - PMC SLCR | ||
68 | */ | ||
69 | object_initialize_child(OBJECT(s), "pmc-apb-irq-orgate", | ||
70 | &s->pmc.apb_irq_orgate, TYPE_OR_IRQ); | ||
71 | @@ -XXX,XX +XXX,XX @@ static void versal_create_efuse(Versal *s, qemu_irq *pic) | ||
72 | sysbus_connect_irq(SYS_BUS_DEVICE(ctrl), 0, pic[VERSAL_EFUSE_IRQ]); | ||
73 | } | ||
74 | |||
75 | +static void versal_create_pmc_iou_slcr(Versal *s, qemu_irq *pic) | ||
76 | +{ | ||
77 | + SysBusDevice *sbd; | ||
78 | + | ||
79 | + object_initialize_child(OBJECT(s), "versal-pmc-iou-slcr", &s->pmc.iou.slcr, | ||
80 | + TYPE_XILINX_VERSAL_PMC_IOU_SLCR); | ||
81 | + | ||
82 | + sbd = SYS_BUS_DEVICE(&s->pmc.iou.slcr); | ||
83 | + sysbus_realize(sbd, &error_fatal); | ||
84 | + | ||
85 | + memory_region_add_subregion(&s->mr_ps, MM_PMC_PMC_IOU_SLCR, | ||
86 | + sysbus_mmio_get_region(sbd, 0)); | ||
87 | + | ||
88 | + sysbus_connect_irq(sbd, 0, | ||
89 | + qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 2)); | ||
90 | +} | ||
91 | + | ||
92 | /* This takes the board allocated linear DDR memory and creates aliases | ||
93 | * for each split DDR range/aperture on the Versal address map. | ||
94 | */ | ||
95 | @@ -XXX,XX +XXX,XX @@ static void versal_unimp_area(Versal *s, const char *name, | ||
96 | memory_region_add_subregion(mr, base, mr_dev); | ||
97 | } | ||
98 | |||
99 | +static void versal_unimp_sd_emmc_sel(void *opaque, int n, int level) | ||
100 | +{ | ||
101 | + qemu_log_mask(LOG_UNIMP, | ||
102 | + "Selecting between enabling SD mode or eMMC mode on " | ||
103 | + "controller %d is not yet implemented\n", n); | ||
104 | +} | ||
105 | + | ||
106 | +static void versal_unimp_qspi_ospi_mux_sel(void *opaque, int n, int level) | ||
107 | +{ | ||
108 | + qemu_log_mask(LOG_UNIMP, | ||
109 | + "Selecting between enabling the QSPI or OSPI linear address " | ||
110 | + "region is not yet implemented\n"); | ||
111 | +} | ||
112 | + | ||
113 | +static void versal_unimp_irq_parity_imr(void *opaque, int n, int level) | ||
114 | +{ | ||
115 | + qemu_log_mask(LOG_UNIMP, | ||
116 | + "PMC SLCR parity interrupt behaviour " | ||
117 | + "is not yet implemented\n"); | ||
118 | +} | ||
119 | + | ||
120 | static void versal_unimp(Versal *s) | ||
121 | { | ||
122 | + qemu_irq gpio_in; | ||
123 | + | ||
124 | versal_unimp_area(s, "psm", &s->mr_ps, | ||
125 | MM_PSM_START, MM_PSM_END - MM_PSM_START); | ||
126 | versal_unimp_area(s, "crl", &s->mr_ps, | ||
127 | @@ -XXX,XX +XXX,XX @@ static void versal_unimp(Versal *s) | ||
128 | MM_IOU_SCNTR, MM_IOU_SCNTR_SIZE); | ||
129 | versal_unimp_area(s, "iou-scntr-seucre", &s->mr_ps, | ||
130 | MM_IOU_SCNTRS, MM_IOU_SCNTRS_SIZE); | ||
131 | + | ||
132 | + qdev_init_gpio_in_named(DEVICE(s), versal_unimp_sd_emmc_sel, | ||
133 | + "sd-emmc-sel-dummy", 2); | ||
134 | + qdev_init_gpio_in_named(DEVICE(s), versal_unimp_qspi_ospi_mux_sel, | ||
135 | + "qspi-ospi-mux-sel-dummy", 1); | ||
136 | + qdev_init_gpio_in_named(DEVICE(s), versal_unimp_irq_parity_imr, | ||
137 | + "irq-parity-imr-dummy", 1); | ||
138 | + | ||
139 | + gpio_in = qdev_get_gpio_in_named(DEVICE(s), "sd-emmc-sel-dummy", 0); | ||
140 | + qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), "sd-emmc-sel", 0, | ||
141 | + gpio_in); | ||
142 | + | ||
143 | + gpio_in = qdev_get_gpio_in_named(DEVICE(s), "sd-emmc-sel-dummy", 1); | ||
144 | + qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), "sd-emmc-sel", 1, | ||
145 | + gpio_in); | ||
146 | + | ||
147 | + gpio_in = qdev_get_gpio_in_named(DEVICE(s), "qspi-ospi-mux-sel-dummy", 0); | ||
148 | + qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), | ||
149 | + "qspi-ospi-mux-sel", 0, | ||
150 | + gpio_in); | ||
151 | + | ||
152 | + gpio_in = qdev_get_gpio_in_named(DEVICE(s), "irq-parity-imr-dummy", 0); | ||
153 | + qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), | ||
154 | + SYSBUS_DEVICE_GPIO_IRQ, 0, | ||
155 | + gpio_in); | ||
156 | } | ||
157 | |||
158 | static void versal_realize(DeviceState *dev, Error **errp) | ||
159 | @@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp) | ||
160 | versal_create_xrams(s, pic); | ||
161 | versal_create_bbram(s, pic); | ||
162 | versal_create_efuse(s, pic); | ||
163 | + versal_create_pmc_iou_slcr(s, pic); | ||
164 | versal_map_ddr(s); | ||
165 | versal_unimp(s); | ||
166 | |||
167 | -- | ||
168 | 2.25.1 | ||
169 | |||
170 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
1 | 2 | ||
3 | Add in the missing includes in the header for being able to build the DMA | ||
4 | model when reusing it. | ||
5 | |||
6 | Signed-off-by: Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
7 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
8 | Reviewed-by: Luc Michel <luc@lmichel.fr> | ||
9 | Message-id: 20220121161141.14389-5-francisco.iglesias@xilinx.com | ||
10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
11 | --- | ||
12 | include/hw/dma/xlnx_csu_dma.h | 5 +++++ | ||
13 | 1 file changed, 5 insertions(+) | ||
14 | |||
15 | diff --git a/include/hw/dma/xlnx_csu_dma.h b/include/hw/dma/xlnx_csu_dma.h | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/include/hw/dma/xlnx_csu_dma.h | ||
18 | +++ b/include/hw/dma/xlnx_csu_dma.h | ||
19 | @@ -XXX,XX +XXX,XX @@ | ||
20 | #ifndef XLNX_CSU_DMA_H | ||
21 | #define XLNX_CSU_DMA_H | ||
22 | |||
23 | +#include "hw/sysbus.h" | ||
24 | +#include "hw/register.h" | ||
25 | +#include "hw/ptimer.h" | ||
26 | +#include "hw/stream.h" | ||
27 | + | ||
28 | #define TYPE_XLNX_CSU_DMA "xlnx.csu_dma" | ||
29 | |||
30 | #define XLNX_CSU_DMA_R_MAX (0x2c / 4) | ||
31 | -- | ||
32 | 2.25.1 | ||
33 | |||
34 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
1 | 2 | ||
3 | An option on real hardware when embedding a DMA engine into a peripheral | ||
4 | is to make the peripheral control the engine through a custom DMA control | ||
5 | (hardware) interface between the two. Software drivers in this scenario | ||
6 | configure and trigger DMA operations through the controlling peripheral's | ||
7 | register API (for example, writing a specific bit in a register could | ||
8 | propagate down to a transfer start signal on the DMA control interface). | ||
9 | At the same time the status, results and interrupts for the transfer might | ||
10 | still be intended to be read and caught through the DMA engine's register | ||
11 | API (and signals). | ||
12 | |||
13 | This patch adds a class 'read' method for allowing to start read transfers | ||
14 | from peripherals embedding and controlling the Xilinx CSU DMA engine as in | ||
15 | above scenario. | ||
16 | |||
17 | Signed-off-by: Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
18 | Reviewed-by: Luc Michel <luc@lmichel.fr> | ||
19 | Message-id: 20220121161141.14389-6-francisco.iglesias@xilinx.com | ||
20 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
21 | --- | ||
22 | include/hw/dma/xlnx_csu_dma.h | 19 +++++++++++++++++-- | ||
23 | hw/dma/xlnx_csu_dma.c | 17 +++++++++++++++++ | ||
24 | 2 files changed, 34 insertions(+), 2 deletions(-) | ||
25 | |||
26 | diff --git a/include/hw/dma/xlnx_csu_dma.h b/include/hw/dma/xlnx_csu_dma.h | ||
27 | index XXXXXXX..XXXXXXX 100644 | ||
28 | --- a/include/hw/dma/xlnx_csu_dma.h | ||
29 | +++ b/include/hw/dma/xlnx_csu_dma.h | ||
30 | @@ -XXX,XX +XXX,XX @@ typedef struct XlnxCSUDMA { | ||
31 | RegisterInfo regs_info[XLNX_CSU_DMA_R_MAX]; | ||
32 | } XlnxCSUDMA; | ||
33 | |||
34 | -#define XLNX_CSU_DMA(obj) \ | ||
35 | - OBJECT_CHECK(XlnxCSUDMA, (obj), TYPE_XLNX_CSU_DMA) | ||
36 | +OBJECT_DECLARE_TYPE(XlnxCSUDMA, XlnxCSUDMAClass, XLNX_CSU_DMA) | ||
37 | + | ||
38 | +struct XlnxCSUDMAClass { | ||
39 | + SysBusDeviceClass parent_class; | ||
40 | + | ||
41 | + /* | ||
42 | + * read: Start a read transfer on a Xilinx CSU DMA engine | ||
43 | + * | ||
44 | + * @s: the Xilinx CSU DMA engine to start the transfer on | ||
45 | + * @addr: the address to read | ||
46 | + * @len: the number of bytes to read at 'addr' | ||
47 | + * | ||
48 | + * @return a MemTxResult indicating whether the operation succeeded ('len' | ||
49 | + * bytes were read) or failed. | ||
50 | + */ | ||
51 | + MemTxResult (*read)(XlnxCSUDMA *s, hwaddr addr, uint32_t len); | ||
52 | +}; | ||
53 | |||
54 | #endif | ||
55 | diff --git a/hw/dma/xlnx_csu_dma.c b/hw/dma/xlnx_csu_dma.c | ||
56 | index XXXXXXX..XXXXXXX 100644 | ||
57 | --- a/hw/dma/xlnx_csu_dma.c | ||
58 | +++ b/hw/dma/xlnx_csu_dma.c | ||
59 | @@ -XXX,XX +XXX,XX @@ static uint64_t addr_msb_pre_write(RegisterInfo *reg, uint64_t val) | ||
60 | return val & R_ADDR_MSB_ADDR_MSB_MASK; | ||
61 | } | ||
62 | |||
63 | +static MemTxResult xlnx_csu_dma_class_read(XlnxCSUDMA *s, hwaddr addr, | ||
64 | + uint32_t len) | ||
65 | +{ | ||
66 | + RegisterInfo *reg = &s->regs_info[R_SIZE]; | ||
67 | + uint64_t we = MAKE_64BIT_MASK(0, 4 * 8); | ||
68 | + | ||
69 | + s->regs[R_ADDR] = addr; | ||
70 | + s->regs[R_ADDR_MSB] = (uint64_t)addr >> 32; | ||
71 | + | ||
72 | + register_write(reg, len, we, object_get_typename(OBJECT(s)), false); | ||
73 | + | ||
74 | + return (s->regs[R_SIZE] == 0) ? MEMTX_OK : MEMTX_ERROR; | ||
75 | +} | ||
76 | + | ||
77 | static const RegisterAccessInfo *xlnx_csu_dma_regs_info[] = { | ||
78 | #define DMACH_REGINFO(NAME, snd) \ | ||
79 | (const RegisterAccessInfo []) { \ | ||
80 | @@ -XXX,XX +XXX,XX @@ static void xlnx_csu_dma_class_init(ObjectClass *klass, void *data) | ||
81 | { | ||
82 | DeviceClass *dc = DEVICE_CLASS(klass); | ||
83 | StreamSinkClass *ssc = STREAM_SINK_CLASS(klass); | ||
84 | + XlnxCSUDMAClass *xcdc = XLNX_CSU_DMA_CLASS(klass); | ||
85 | |||
86 | dc->reset = xlnx_csu_dma_reset; | ||
87 | dc->realize = xlnx_csu_dma_realize; | ||
88 | @@ -XXX,XX +XXX,XX @@ static void xlnx_csu_dma_class_init(ObjectClass *klass, void *data) | ||
89 | |||
90 | ssc->push = xlnx_csu_dma_stream_push; | ||
91 | ssc->can_push = xlnx_csu_dma_stream_can_push; | ||
92 | + | ||
93 | + xcdc->read = xlnx_csu_dma_class_read; | ||
94 | } | ||
95 | |||
96 | static void xlnx_csu_dma_init(Object *obj) | ||
97 | -- | ||
98 | 2.25.1 | ||
99 | |||
100 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
1 | 2 | ||
3 | Add a model of Xilinx Versal's OSPI flash memory controller. | ||
4 | |||
5 | Signed-off-by: Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
6 | Reviewed-by: Luc Michel <luc@lmichel.fr> | ||
7 | Message-id: 20220121161141.14389-7-francisco.iglesias@xilinx.com | ||
8 | [PMM: fixed indent] | ||
9 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
10 | --- | ||
11 | include/hw/ssi/xlnx-versal-ospi.h | 111 ++ | ||
12 | hw/ssi/xlnx-versal-ospi.c | 1853 +++++++++++++++++++++++++++++ | ||
13 | hw/ssi/meson.build | 1 + | ||
14 | 3 files changed, 1965 insertions(+) | ||
15 | create mode 100644 include/hw/ssi/xlnx-versal-ospi.h | ||
16 | create mode 100644 hw/ssi/xlnx-versal-ospi.c | ||
17 | |||
18 | diff --git a/include/hw/ssi/xlnx-versal-ospi.h b/include/hw/ssi/xlnx-versal-ospi.h | ||
19 | new file mode 100644 | ||
20 | index XXXXXXX..XXXXXXX | ||
21 | --- /dev/null | ||
22 | +++ b/include/hw/ssi/xlnx-versal-ospi.h | ||
23 | @@ -XXX,XX +XXX,XX @@ | ||
24 | +/* | ||
25 | + * Header file for the Xilinx Versal's OSPI controller | ||
26 | + * | ||
27 | + * Copyright (C) 2021 Xilinx Inc | ||
28 | + * Written by Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
29 | + * | ||
30 | + * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
31 | + * of this software and associated documentation files (the "Software"), to deal | ||
32 | + * in the Software without restriction, including without limitation the rights | ||
33 | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
34 | + * copies of the Software, and to permit persons to whom the Software is | ||
35 | + * furnished to do so, subject to the following conditions: | ||
36 | + * | ||
37 | + * The above copyright notice and this permission notice shall be included in | ||
38 | + * all copies or substantial portions of the Software. | ||
39 | + * | ||
40 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
41 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
42 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
43 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
44 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
45 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
46 | + * THE SOFTWARE. | ||
47 | + */ | ||
48 | + | ||
49 | +/* | ||
50 | + * This is a model of Xilinx Versal's Octal SPI flash memory controller | ||
51 | + * documented in Versal's Technical Reference manual [1] and the Versal ACAP | ||
52 | + * Register reference [2]. | ||
53 | + * | ||
54 | + * References: | ||
55 | + * | ||
56 | + * [1] Versal ACAP Technical Reference Manual, | ||
57 | + * https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf | ||
58 | + * | ||
59 | + * [2] Versal ACAP Register Reference, | ||
60 | + * https://www.xilinx.com/html_docs/registers/am012/am012-versal-register-reference.html#mod___ospi.html | ||
61 | + * | ||
62 | + * | ||
63 | + * QEMU interface: | ||
64 | + * + sysbus MMIO region 0: MemoryRegion for the device's registers | ||
65 | + * + sysbus MMIO region 1: MemoryRegion for flash memory linear address space | ||
66 | + * (data transfer). | ||
67 | + * + sysbus IRQ 0: Device interrupt. | ||
68 | + * + Named GPIO input "ospi-mux-sel": 0: enables indirect access mode | ||
69 | + * and 1: enables direct access mode. | ||
70 | + * + Property "dac-with-indac": Allow both direct accesses and indirect | ||
71 | + * accesses simultaneously. | ||
72 | + * + Property "indac-write-disabled": Disable indirect access writes. | ||
73 | + */ | ||
74 | + | ||
75 | +#ifndef XILINX_VERSAL_OSPI_H | ||
76 | +#define XILINX_VERSAL_OSPI_H | ||
77 | + | ||
78 | +#include "hw/register.h" | ||
79 | +#include "hw/ssi/ssi.h" | ||
80 | +#include "qemu/fifo8.h" | ||
81 | +#include "hw/dma/xlnx_csu_dma.h" | ||
82 | + | ||
83 | +#define TYPE_XILINX_VERSAL_OSPI "xlnx.versal-ospi" | ||
84 | + | ||
85 | +OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalOspi, XILINX_VERSAL_OSPI) | ||
86 | + | ||
87 | +#define XILINX_VERSAL_OSPI_R_MAX (0xfc / 4 + 1) | ||
88 | + | ||
89 | +/* | ||
90 | + * Indirect operations | ||
91 | + */ | ||
92 | +typedef struct IndOp { | ||
93 | + uint32_t flash_addr; | ||
94 | + uint32_t num_bytes; | ||
95 | + uint32_t done_bytes; | ||
96 | + bool completed; | ||
97 | +} IndOp; | ||
98 | + | ||
99 | +struct XlnxVersalOspi { | ||
100 | + SysBusDevice parent_obj; | ||
101 | + | ||
102 | + MemoryRegion iomem; | ||
103 | + MemoryRegion iomem_dac; | ||
104 | + | ||
105 | + uint8_t num_cs; | ||
106 | + qemu_irq *cs_lines; | ||
107 | + | ||
108 | + SSIBus *spi; | ||
109 | + | ||
110 | + Fifo8 rx_fifo; | ||
111 | + Fifo8 tx_fifo; | ||
112 | + | ||
113 | + Fifo8 rx_sram; | ||
114 | + Fifo8 tx_sram; | ||
115 | + | ||
116 | + qemu_irq irq; | ||
117 | + | ||
118 | + XlnxCSUDMA *dma_src; | ||
119 | + bool ind_write_disabled; | ||
120 | + bool dac_with_indac; | ||
121 | + bool dac_enable; | ||
122 | + bool src_dma_inprog; | ||
123 | + | ||
124 | + IndOp rd_ind_op[2]; | ||
125 | + IndOp wr_ind_op[2]; | ||
126 | + | ||
127 | + uint32_t regs[XILINX_VERSAL_OSPI_R_MAX]; | ||
128 | + RegisterInfo regs_info[XILINX_VERSAL_OSPI_R_MAX]; | ||
129 | + | ||
130 | + /* Maximum inferred membank size is 512 bytes */ | ||
131 | + uint8_t stig_membank[512]; | ||
132 | +}; | ||
133 | + | ||
134 | +#endif /* XILINX_VERSAL_OSPI_H */ | ||
135 | diff --git a/hw/ssi/xlnx-versal-ospi.c b/hw/ssi/xlnx-versal-ospi.c | ||
136 | new file mode 100644 | ||
137 | index XXXXXXX..XXXXXXX | ||
138 | --- /dev/null | ||
139 | +++ b/hw/ssi/xlnx-versal-ospi.c | ||
140 | @@ -XXX,XX +XXX,XX @@ | ||
141 | +/* | ||
142 | + * QEMU model of Xilinx Versal's OSPI controller. | ||
143 | + * | ||
144 | + * Copyright (c) 2021 Xilinx Inc. | ||
145 | + * Written by Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
146 | + * | ||
147 | + * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
148 | + * of this software and associated documentation files (the "Software"), to deal | ||
149 | + * in the Software without restriction, including without limitation the rights | ||
150 | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
151 | + * copies of the Software, and to permit persons to whom the Software is | ||
152 | + * furnished to do so, subject to the following conditions: | ||
153 | + * | ||
154 | + * The above copyright notice and this permission notice shall be included in | ||
155 | + * all copies or substantial portions of the Software. | ||
156 | + * | ||
157 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
158 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
159 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
160 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
161 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
162 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
163 | + * THE SOFTWARE. | ||
164 | + */ | ||
165 | +#include "qemu/osdep.h" | ||
166 | +#include "hw/sysbus.h" | ||
167 | +#include "migration/vmstate.h" | ||
168 | +#include "hw/qdev-properties.h" | ||
169 | +#include "qemu/bitops.h" | ||
170 | +#include "qemu/log.h" | ||
171 | +#include "hw/irq.h" | ||
172 | +#include "hw/ssi/xlnx-versal-ospi.h" | ||
173 | + | ||
174 | +#ifndef XILINX_VERSAL_OSPI_ERR_DEBUG | ||
175 | +#define XILINX_VERSAL_OSPI_ERR_DEBUG 0 | ||
176 | +#endif | ||
177 | + | ||
178 | +REG32(CONFIG_REG, 0x0) | ||
179 | + FIELD(CONFIG_REG, IDLE_FLD, 31, 1) | ||
180 | + FIELD(CONFIG_REG, DUAL_BYTE_OPCODE_EN_FLD, 30, 1) | ||
181 | + FIELD(CONFIG_REG, CRC_ENABLE_FLD, 29, 1) | ||
182 | + FIELD(CONFIG_REG, CONFIG_RESV2_FLD, 26, 3) | ||
183 | + FIELD(CONFIG_REG, PIPELINE_PHY_FLD, 25, 1) | ||
184 | + FIELD(CONFIG_REG, ENABLE_DTR_PROTOCOL_FLD, 24, 1) | ||
185 | + FIELD(CONFIG_REG, ENABLE_AHB_DECODER_FLD, 23, 1) | ||
186 | + FIELD(CONFIG_REG, MSTR_BAUD_DIV_FLD, 19, 4) | ||
187 | + FIELD(CONFIG_REG, ENTER_XIP_MODE_IMM_FLD, 18, 1) | ||
188 | + FIELD(CONFIG_REG, ENTER_XIP_MODE_FLD, 17, 1) | ||
189 | + FIELD(CONFIG_REG, ENB_AHB_ADDR_REMAP_FLD, 16, 1) | ||
190 | + FIELD(CONFIG_REG, ENB_DMA_IF_FLD, 15, 1) | ||
191 | + FIELD(CONFIG_REG, WR_PROT_FLASH_FLD, 14, 1) | ||
192 | + FIELD(CONFIG_REG, PERIPH_CS_LINES_FLD, 10, 4) | ||
193 | + FIELD(CONFIG_REG, PERIPH_SEL_DEC_FLD, 9, 1) | ||
194 | + FIELD(CONFIG_REG, ENB_LEGACY_IP_MODE_FLD, 8, 1) | ||
195 | + FIELD(CONFIG_REG, ENB_DIR_ACC_CTLR_FLD, 7, 1) | ||
196 | + FIELD(CONFIG_REG, RESET_CFG_FLD, 6, 1) | ||
197 | + FIELD(CONFIG_REG, RESET_PIN_FLD, 5, 1) | ||
198 | + FIELD(CONFIG_REG, HOLD_PIN_FLD, 4, 1) | ||
199 | + FIELD(CONFIG_REG, PHY_MODE_ENABLE_FLD, 3, 1) | ||
200 | + FIELD(CONFIG_REG, SEL_CLK_PHASE_FLD, 2, 1) | ||
201 | + FIELD(CONFIG_REG, SEL_CLK_POL_FLD, 1, 1) | ||
202 | + FIELD(CONFIG_REG, ENB_SPI_FLD, 0, 1) | ||
203 | +REG32(DEV_INSTR_RD_CONFIG_REG, 0x4) | ||
204 | + FIELD(DEV_INSTR_RD_CONFIG_REG, RD_INSTR_RESV5_FLD, 29, 3) | ||
205 | + FIELD(DEV_INSTR_RD_CONFIG_REG, DUMMY_RD_CLK_CYCLES_FLD, 24, 5) | ||
206 | + FIELD(DEV_INSTR_RD_CONFIG_REG, RD_INSTR_RESV4_FLD, 21, 3) | ||
207 | + FIELD(DEV_INSTR_RD_CONFIG_REG, MODE_BIT_ENABLE_FLD, 20, 1) | ||
208 | + FIELD(DEV_INSTR_RD_CONFIG_REG, RD_INSTR_RESV3_FLD, 18, 2) | ||
209 | + FIELD(DEV_INSTR_RD_CONFIG_REG, DATA_XFER_TYPE_EXT_MODE_FLD, 16, 2) | ||
210 | + FIELD(DEV_INSTR_RD_CONFIG_REG, RD_INSTR_RESV2_FLD, 14, 2) | ||
211 | + FIELD(DEV_INSTR_RD_CONFIG_REG, ADDR_XFER_TYPE_STD_MODE_FLD, 12, 2) | ||
212 | + FIELD(DEV_INSTR_RD_CONFIG_REG, PRED_DIS_FLD, 11, 1) | ||
213 | + FIELD(DEV_INSTR_RD_CONFIG_REG, DDR_EN_FLD, 10, 1) | ||
214 | + FIELD(DEV_INSTR_RD_CONFIG_REG, INSTR_TYPE_FLD, 8, 2) | ||
215 | + FIELD(DEV_INSTR_RD_CONFIG_REG, RD_OPCODE_NON_XIP_FLD, 0, 8) | ||
216 | +REG32(DEV_INSTR_WR_CONFIG_REG, 0x8) | ||
217 | + FIELD(DEV_INSTR_WR_CONFIG_REG, WR_INSTR_RESV4_FLD, 29, 3) | ||
218 | + FIELD(DEV_INSTR_WR_CONFIG_REG, DUMMY_WR_CLK_CYCLES_FLD, 24, 5) | ||
219 | + FIELD(DEV_INSTR_WR_CONFIG_REG, WR_INSTR_RESV3_FLD, 18, 6) | ||
220 | + FIELD(DEV_INSTR_WR_CONFIG_REG, DATA_XFER_TYPE_EXT_MODE_FLD, 16, 2) | ||
221 | + FIELD(DEV_INSTR_WR_CONFIG_REG, WR_INSTR_RESV2_FLD, 14, 2) | ||
222 | + FIELD(DEV_INSTR_WR_CONFIG_REG, ADDR_XFER_TYPE_STD_MODE_FLD, 12, 2) | ||
223 | + FIELD(DEV_INSTR_WR_CONFIG_REG, WR_INSTR_RESV1_FLD, 9, 3) | ||
224 | + FIELD(DEV_INSTR_WR_CONFIG_REG, WEL_DIS_FLD, 8, 1) | ||
225 | + FIELD(DEV_INSTR_WR_CONFIG_REG, WR_OPCODE_FLD, 0, 8) | ||
226 | +REG32(DEV_DELAY_REG, 0xc) | ||
227 | + FIELD(DEV_DELAY_REG, D_NSS_FLD, 24, 8) | ||
228 | + FIELD(DEV_DELAY_REG, D_BTWN_FLD, 16, 8) | ||
229 | + FIELD(DEV_DELAY_REG, D_AFTER_FLD, 8, 8) | ||
230 | + FIELD(DEV_DELAY_REG, D_INIT_FLD, 0, 8) | ||
231 | +REG32(RD_DATA_CAPTURE_REG, 0x10) | ||
232 | + FIELD(RD_DATA_CAPTURE_REG, RD_DATA_RESV3_FLD, 20, 12) | ||
233 | + FIELD(RD_DATA_CAPTURE_REG, DDR_READ_DELAY_FLD, 16, 4) | ||
234 | + FIELD(RD_DATA_CAPTURE_REG, RD_DATA_RESV2_FLD, 9, 7) | ||
235 | + FIELD(RD_DATA_CAPTURE_REG, DQS_ENABLE_FLD, 8, 1) | ||
236 | + FIELD(RD_DATA_CAPTURE_REG, RD_DATA_RESV1_FLD, 6, 2) | ||
237 | + FIELD(RD_DATA_CAPTURE_REG, SAMPLE_EDGE_SEL_FLD, 5, 1) | ||
238 | + FIELD(RD_DATA_CAPTURE_REG, DELAY_FLD, 1, 4) | ||
239 | + FIELD(RD_DATA_CAPTURE_REG, BYPASS_FLD, 0, 1) | ||
240 | +REG32(DEV_SIZE_CONFIG_REG, 0x14) | ||
241 | + FIELD(DEV_SIZE_CONFIG_REG, DEV_SIZE_RESV_FLD, 29, 3) | ||
242 | + FIELD(DEV_SIZE_CONFIG_REG, MEM_SIZE_ON_CS3_FLD, 27, 2) | ||
243 | + FIELD(DEV_SIZE_CONFIG_REG, MEM_SIZE_ON_CS2_FLD, 25, 2) | ||
244 | + FIELD(DEV_SIZE_CONFIG_REG, MEM_SIZE_ON_CS1_FLD, 23, 2) | ||
245 | + FIELD(DEV_SIZE_CONFIG_REG, MEM_SIZE_ON_CS0_FLD, 21, 2) | ||
246 | + FIELD(DEV_SIZE_CONFIG_REG, BYTES_PER_SUBSECTOR_FLD, 16, 5) | ||
247 | + FIELD(DEV_SIZE_CONFIG_REG, BYTES_PER_DEVICE_PAGE_FLD, 4, 12) | ||
248 | + FIELD(DEV_SIZE_CONFIG_REG, NUM_ADDR_BYTES_FLD, 0, 4) | ||
249 | +REG32(SRAM_PARTITION_CFG_REG, 0x18) | ||
250 | + FIELD(SRAM_PARTITION_CFG_REG, SRAM_PARTITION_RESV_FLD, 8, 24) | ||
251 | + FIELD(SRAM_PARTITION_CFG_REG, ADDR_FLD, 0, 8) | ||
252 | +REG32(IND_AHB_ADDR_TRIGGER_REG, 0x1c) | ||
253 | +REG32(DMA_PERIPH_CONFIG_REG, 0x20) | ||
254 | + FIELD(DMA_PERIPH_CONFIG_REG, DMA_PERIPH_RESV2_FLD, 12, 20) | ||
255 | + FIELD(DMA_PERIPH_CONFIG_REG, NUM_BURST_REQ_BYTES_FLD, 8, 4) | ||
256 | + FIELD(DMA_PERIPH_CONFIG_REG, DMA_PERIPH_RESV1_FLD, 4, 4) | ||
257 | + FIELD(DMA_PERIPH_CONFIG_REG, NUM_SINGLE_REQ_BYTES_FLD, 0, 4) | ||
258 | +REG32(REMAP_ADDR_REG, 0x24) | ||
259 | +REG32(MODE_BIT_CONFIG_REG, 0x28) | ||
260 | + FIELD(MODE_BIT_CONFIG_REG, RX_CRC_DATA_LOW_FLD, 24, 8) | ||
261 | + FIELD(MODE_BIT_CONFIG_REG, RX_CRC_DATA_UP_FLD, 16, 8) | ||
262 | + FIELD(MODE_BIT_CONFIG_REG, CRC_OUT_ENABLE_FLD, 15, 1) | ||
263 | + FIELD(MODE_BIT_CONFIG_REG, MODE_BIT_RESV1_FLD, 11, 4) | ||
264 | + FIELD(MODE_BIT_CONFIG_REG, CHUNK_SIZE_FLD, 8, 3) | ||
265 | + FIELD(MODE_BIT_CONFIG_REG, MODE_FLD, 0, 8) | ||
266 | +REG32(SRAM_FILL_REG, 0x2c) | ||
267 | + FIELD(SRAM_FILL_REG, SRAM_FILL_INDAC_WRITE_FLD, 16, 16) | ||
268 | + FIELD(SRAM_FILL_REG, SRAM_FILL_INDAC_READ_FLD, 0, 16) | ||
269 | +REG32(TX_THRESH_REG, 0x30) | ||
270 | + FIELD(TX_THRESH_REG, TX_THRESH_RESV_FLD, 5, 27) | ||
271 | + FIELD(TX_THRESH_REG, LEVEL_FLD, 0, 5) | ||
272 | +REG32(RX_THRESH_REG, 0x34) | ||
273 | + FIELD(RX_THRESH_REG, RX_THRESH_RESV_FLD, 5, 27) | ||
274 | + FIELD(RX_THRESH_REG, LEVEL_FLD, 0, 5) | ||
275 | +REG32(WRITE_COMPLETION_CTRL_REG, 0x38) | ||
276 | + FIELD(WRITE_COMPLETION_CTRL_REG, POLL_REP_DELAY_FLD, 24, 8) | ||
277 | + FIELD(WRITE_COMPLETION_CTRL_REG, POLL_COUNT_FLD, 16, 8) | ||
278 | + FIELD(WRITE_COMPLETION_CTRL_REG, ENABLE_POLLING_EXP_FLD, 15, 1) | ||
279 | + FIELD(WRITE_COMPLETION_CTRL_REG, DISABLE_POLLING_FLD, 14, 1) | ||
280 | + FIELD(WRITE_COMPLETION_CTRL_REG, POLLING_POLARITY_FLD, 13, 1) | ||
281 | + FIELD(WRITE_COMPLETION_CTRL_REG, WR_COMP_CTRL_RESV1_FLD, 12, 1) | ||
282 | + FIELD(WRITE_COMPLETION_CTRL_REG, POLLING_ADDR_EN_FLD, 11, 1) | ||
283 | + FIELD(WRITE_COMPLETION_CTRL_REG, POLLING_BIT_INDEX_FLD, 8, 3) | ||
284 | + FIELD(WRITE_COMPLETION_CTRL_REG, OPCODE_FLD, 0, 8) | ||
285 | +REG32(NO_OF_POLLS_BEF_EXP_REG, 0x3c) | ||
286 | +REG32(IRQ_STATUS_REG, 0x40) | ||
287 | + FIELD(IRQ_STATUS_REG, IRQ_STAT_RESV_FLD, 20, 12) | ||
288 | + FIELD(IRQ_STATUS_REG, ECC_FAIL_FLD, 19, 1) | ||
289 | + FIELD(IRQ_STATUS_REG, TX_CRC_CHUNK_BRK_FLD, 18, 1) | ||
290 | + FIELD(IRQ_STATUS_REG, RX_CRC_DATA_VAL_FLD, 17, 1) | ||
291 | + FIELD(IRQ_STATUS_REG, RX_CRC_DATA_ERR_FLD, 16, 1) | ||
292 | + FIELD(IRQ_STATUS_REG, IRQ_STAT_RESV1_FLD, 15, 1) | ||
293 | + FIELD(IRQ_STATUS_REG, STIG_REQ_INT_FLD, 14, 1) | ||
294 | + FIELD(IRQ_STATUS_REG, POLL_EXP_INT_FLD, 13, 1) | ||
295 | + FIELD(IRQ_STATUS_REG, INDRD_SRAM_FULL_FLD, 12, 1) | ||
296 | + FIELD(IRQ_STATUS_REG, RX_FIFO_FULL_FLD, 11, 1) | ||
297 | + FIELD(IRQ_STATUS_REG, RX_FIFO_NOT_EMPTY_FLD, 10, 1) | ||
298 | + FIELD(IRQ_STATUS_REG, TX_FIFO_FULL_FLD, 9, 1) | ||
299 | + FIELD(IRQ_STATUS_REG, TX_FIFO_NOT_FULL_FLD, 8, 1) | ||
300 | + FIELD(IRQ_STATUS_REG, RECV_OVERFLOW_FLD, 7, 1) | ||
301 | + FIELD(IRQ_STATUS_REG, INDIRECT_XFER_LEVEL_BREACH_FLD, 6, 1) | ||
302 | + FIELD(IRQ_STATUS_REG, ILLEGAL_ACCESS_DET_FLD, 5, 1) | ||
303 | + FIELD(IRQ_STATUS_REG, PROT_WR_ATTEMPT_FLD, 4, 1) | ||
304 | + FIELD(IRQ_STATUS_REG, INDIRECT_TRANSFER_REJECT_FLD, 3, 1) | ||
305 | + FIELD(IRQ_STATUS_REG, INDIRECT_OP_DONE_FLD, 2, 1) | ||
306 | + FIELD(IRQ_STATUS_REG, UNDERFLOW_DET_FLD, 1, 1) | ||
307 | + FIELD(IRQ_STATUS_REG, MODE_M_FAIL_FLD, 0, 1) | ||
308 | +REG32(IRQ_MASK_REG, 0x44) | ||
309 | + FIELD(IRQ_MASK_REG, IRQ_MASK_RESV_FLD, 20, 12) | ||
310 | + FIELD(IRQ_MASK_REG, ECC_FAIL_MASK_FLD, 19, 1) | ||
311 | + FIELD(IRQ_MASK_REG, TX_CRC_CHUNK_BRK_MASK_FLD, 18, 1) | ||
312 | + FIELD(IRQ_MASK_REG, RX_CRC_DATA_VAL_MASK_FLD, 17, 1) | ||
313 | + FIELD(IRQ_MASK_REG, RX_CRC_DATA_ERR_MASK_FLD, 16, 1) | ||
314 | + FIELD(IRQ_MASK_REG, IRQ_MASK_RESV1_FLD, 15, 1) | ||
315 | + FIELD(IRQ_MASK_REG, STIG_REQ_MASK_FLD, 14, 1) | ||
316 | + FIELD(IRQ_MASK_REG, POLL_EXP_INT_MASK_FLD, 13, 1) | ||
317 | + FIELD(IRQ_MASK_REG, INDRD_SRAM_FULL_MASK_FLD, 12, 1) | ||
318 | + FIELD(IRQ_MASK_REG, RX_FIFO_FULL_MASK_FLD, 11, 1) | ||
319 | + FIELD(IRQ_MASK_REG, RX_FIFO_NOT_EMPTY_MASK_FLD, 10, 1) | ||
320 | + FIELD(IRQ_MASK_REG, TX_FIFO_FULL_MASK_FLD, 9, 1) | ||
321 | + FIELD(IRQ_MASK_REG, TX_FIFO_NOT_FULL_MASK_FLD, 8, 1) | ||
322 | + FIELD(IRQ_MASK_REG, RECV_OVERFLOW_MASK_FLD, 7, 1) | ||
323 | + FIELD(IRQ_MASK_REG, INDIRECT_XFER_LEVEL_BREACH_MASK_FLD, 6, 1) | ||
324 | + FIELD(IRQ_MASK_REG, ILLEGAL_ACCESS_DET_MASK_FLD, 5, 1) | ||
325 | + FIELD(IRQ_MASK_REG, PROT_WR_ATTEMPT_MASK_FLD, 4, 1) | ||
326 | + FIELD(IRQ_MASK_REG, INDIRECT_TRANSFER_REJECT_MASK_FLD, 3, 1) | ||
327 | + FIELD(IRQ_MASK_REG, INDIRECT_OP_DONE_MASK_FLD, 2, 1) | ||
328 | + FIELD(IRQ_MASK_REG, UNDERFLOW_DET_MASK_FLD, 1, 1) | ||
329 | + FIELD(IRQ_MASK_REG, MODE_M_FAIL_MASK_FLD, 0, 1) | ||
330 | +REG32(LOWER_WR_PROT_REG, 0x50) | ||
331 | +REG32(UPPER_WR_PROT_REG, 0x54) | ||
332 | +REG32(WR_PROT_CTRL_REG, 0x58) | ||
333 | + FIELD(WR_PROT_CTRL_REG, WR_PROT_CTRL_RESV_FLD, 2, 30) | ||
334 | + FIELD(WR_PROT_CTRL_REG, ENB_FLD, 1, 1) | ||
335 | + FIELD(WR_PROT_CTRL_REG, INV_FLD, 0, 1) | ||
336 | +REG32(INDIRECT_READ_XFER_CTRL_REG, 0x60) | ||
337 | + FIELD(INDIRECT_READ_XFER_CTRL_REG, INDIR_RD_XFER_RESV_FLD, 8, 24) | ||
338 | + FIELD(INDIRECT_READ_XFER_CTRL_REG, NUM_IND_OPS_DONE_FLD, 6, 2) | ||
339 | + FIELD(INDIRECT_READ_XFER_CTRL_REG, IND_OPS_DONE_STATUS_FLD, 5, 1) | ||
340 | + FIELD(INDIRECT_READ_XFER_CTRL_REG, RD_QUEUED_FLD, 4, 1) | ||
341 | + FIELD(INDIRECT_READ_XFER_CTRL_REG, SRAM_FULL_FLD, 3, 1) | ||
342 | + FIELD(INDIRECT_READ_XFER_CTRL_REG, RD_STATUS_FLD, 2, 1) | ||
343 | + FIELD(INDIRECT_READ_XFER_CTRL_REG, CANCEL_FLD, 1, 1) | ||
344 | + FIELD(INDIRECT_READ_XFER_CTRL_REG, START_FLD, 0, 1) | ||
345 | +REG32(INDIRECT_READ_XFER_WATERMARK_REG, 0x64) | ||
346 | +REG32(INDIRECT_READ_XFER_START_REG, 0x68) | ||
347 | +REG32(INDIRECT_READ_XFER_NUM_BYTES_REG, 0x6c) | ||
348 | +REG32(INDIRECT_WRITE_XFER_CTRL_REG, 0x70) | ||
349 | + FIELD(INDIRECT_WRITE_XFER_CTRL_REG, INDIR_WR_XFER_RESV2_FLD, 8, 24) | ||
350 | + FIELD(INDIRECT_WRITE_XFER_CTRL_REG, NUM_IND_OPS_DONE_FLD, 6, 2) | ||
351 | + FIELD(INDIRECT_WRITE_XFER_CTRL_REG, IND_OPS_DONE_STATUS_FLD, 5, 1) | ||
352 | + FIELD(INDIRECT_WRITE_XFER_CTRL_REG, WR_QUEUED_FLD, 4, 1) | ||
353 | + FIELD(INDIRECT_WRITE_XFER_CTRL_REG, INDIR_WR_XFER_RESV1_FLD, 3, 1) | ||
354 | + FIELD(INDIRECT_WRITE_XFER_CTRL_REG, WR_STATUS_FLD, 2, 1) | ||
355 | + FIELD(INDIRECT_WRITE_XFER_CTRL_REG, CANCEL_FLD, 1, 1) | ||
356 | + FIELD(INDIRECT_WRITE_XFER_CTRL_REG, START_FLD, 0, 1) | ||
357 | +REG32(INDIRECT_WRITE_XFER_WATERMARK_REG, 0x74) | ||
358 | +REG32(INDIRECT_WRITE_XFER_START_REG, 0x78) | ||
359 | +REG32(INDIRECT_WRITE_XFER_NUM_BYTES_REG, 0x7c) | ||
360 | +REG32(INDIRECT_TRIGGER_ADDR_RANGE_REG, 0x80) | ||
361 | + FIELD(INDIRECT_TRIGGER_ADDR_RANGE_REG, IND_RANGE_RESV1_FLD, 4, 28) | ||
362 | + FIELD(INDIRECT_TRIGGER_ADDR_RANGE_REG, IND_RANGE_WIDTH_FLD, 0, 4) | ||
363 | +REG32(FLASH_COMMAND_CTRL_MEM_REG, 0x8c) | ||
364 | + FIELD(FLASH_COMMAND_CTRL_MEM_REG, FLASH_COMMAND_CTRL_MEM_RESV1_FLD, 29, 3) | ||
365 | + FIELD(FLASH_COMMAND_CTRL_MEM_REG, MEM_BANK_ADDR_FLD, 20, 9) | ||
366 | + FIELD(FLASH_COMMAND_CTRL_MEM_REG, FLASH_COMMAND_CTRL_MEM_RESV2_FLD, 19, 1) | ||
367 | + FIELD(FLASH_COMMAND_CTRL_MEM_REG, NB_OF_STIG_READ_BYTES_FLD, 16, 3) | ||
368 | + FIELD(FLASH_COMMAND_CTRL_MEM_REG, MEM_BANK_READ_DATA_FLD, 8, 8) | ||
369 | + FIELD(FLASH_COMMAND_CTRL_MEM_REG, FLASH_COMMAND_CTRL_MEM_RESV3_FLD, 2, 6) | ||
370 | + FIELD(FLASH_COMMAND_CTRL_MEM_REG, MEM_BANK_REQ_IN_PROGRESS_FLD, 1, 1) | ||
371 | + FIELD(FLASH_COMMAND_CTRL_MEM_REG, TRIGGER_MEM_BANK_REQ_FLD, 0, 1) | ||
372 | +REG32(FLASH_CMD_CTRL_REG, 0x90) | ||
373 | + FIELD(FLASH_CMD_CTRL_REG, CMD_OPCODE_FLD, 24, 8) | ||
374 | + FIELD(FLASH_CMD_CTRL_REG, ENB_READ_DATA_FLD, 23, 1) | ||
375 | + FIELD(FLASH_CMD_CTRL_REG, NUM_RD_DATA_BYTES_FLD, 20, 3) | ||
376 | + FIELD(FLASH_CMD_CTRL_REG, ENB_COMD_ADDR_FLD, 19, 1) | ||
377 | + FIELD(FLASH_CMD_CTRL_REG, ENB_MODE_BIT_FLD, 18, 1) | ||
378 | + FIELD(FLASH_CMD_CTRL_REG, NUM_ADDR_BYTES_FLD, 16, 2) | ||
379 | + FIELD(FLASH_CMD_CTRL_REG, ENB_WRITE_DATA_FLD, 15, 1) | ||
380 | + FIELD(FLASH_CMD_CTRL_REG, NUM_WR_DATA_BYTES_FLD, 12, 3) | ||
381 | + FIELD(FLASH_CMD_CTRL_REG, NUM_DUMMY_CYCLES_FLD, 7, 5) | ||
382 | + FIELD(FLASH_CMD_CTRL_REG, FLASH_CMD_CTRL_RESV1_FLD, 3, 4) | ||
383 | + FIELD(FLASH_CMD_CTRL_REG, STIG_MEM_BANK_EN_FLD, 2, 1) | ||
384 | + FIELD(FLASH_CMD_CTRL_REG, CMD_EXEC_STATUS_FLD, 1, 1) | ||
385 | + FIELD(FLASH_CMD_CTRL_REG, CMD_EXEC_FLD, 0, 1) | ||
386 | +REG32(FLASH_CMD_ADDR_REG, 0x94) | ||
387 | +REG32(FLASH_RD_DATA_LOWER_REG, 0xa0) | ||
388 | +REG32(FLASH_RD_DATA_UPPER_REG, 0xa4) | ||
389 | +REG32(FLASH_WR_DATA_LOWER_REG, 0xa8) | ||
390 | +REG32(FLASH_WR_DATA_UPPER_REG, 0xac) | ||
391 | +REG32(POLLING_FLASH_STATUS_REG, 0xb0) | ||
392 | + FIELD(POLLING_FLASH_STATUS_REG, DEVICE_STATUS_RSVD_FLD2, 21, 11) | ||
393 | + FIELD(POLLING_FLASH_STATUS_REG, DEVICE_STATUS_NB_DUMMY, 16, 5) | ||
394 | + FIELD(POLLING_FLASH_STATUS_REG, DEVICE_STATUS_RSVD_FLD1, 9, 7) | ||
395 | + FIELD(POLLING_FLASH_STATUS_REG, DEVICE_STATUS_VALID_FLD, 8, 1) | ||
396 | + FIELD(POLLING_FLASH_STATUS_REG, DEVICE_STATUS_FLD, 0, 8) | ||
397 | +REG32(PHY_CONFIGURATION_REG, 0xb4) | ||
398 | + FIELD(PHY_CONFIGURATION_REG, PHY_CONFIG_RESYNC_FLD, 31, 1) | ||
399 | + FIELD(PHY_CONFIGURATION_REG, PHY_CONFIG_RESET_FLD, 30, 1) | ||
400 | + FIELD(PHY_CONFIGURATION_REG, PHY_CONFIG_RX_DLL_BYPASS_FLD, 29, 1) | ||
401 | + FIELD(PHY_CONFIGURATION_REG, PHY_CONFIG_RESV2_FLD, 23, 6) | ||
402 | + FIELD(PHY_CONFIGURATION_REG, PHY_CONFIG_TX_DLL_DELAY_FLD, 16, 7) | ||
403 | + FIELD(PHY_CONFIGURATION_REG, PHY_CONFIG_RESV1_FLD, 7, 9) | ||
404 | + FIELD(PHY_CONFIGURATION_REG, PHY_CONFIG_RX_DLL_DELAY_FLD, 0, 7) | ||
405 | +REG32(PHY_MASTER_CONTROL_REG, 0xb8) | ||
406 | + FIELD(PHY_MASTER_CONTROL_REG, PHY_MASTER_CONTROL_RESV3_FLD, 25, 7) | ||
407 | + FIELD(PHY_MASTER_CONTROL_REG, PHY_MASTER_LOCK_MODE_FLD, 24, 1) | ||
408 | + FIELD(PHY_MASTER_CONTROL_REG, PHY_MASTER_BYPASS_MODE_FLD, 23, 1) | ||
409 | + FIELD(PHY_MASTER_CONTROL_REG, PHY_MASTER_PHASE_DETECT_SELECTOR_FLD, 20, 3) | ||
410 | + FIELD(PHY_MASTER_CONTROL_REG, PHY_MASTER_CONTROL_RESV2_FLD, 19, 1) | ||
411 | + FIELD(PHY_MASTER_CONTROL_REG, PHY_MASTER_NB_INDICATIONS_FLD, 16, 3) | ||
412 | + FIELD(PHY_MASTER_CONTROL_REG, PHY_MASTER_CONTROL_RESV1_FLD, 7, 9) | ||
413 | + FIELD(PHY_MASTER_CONTROL_REG, PHY_MASTER_INITIAL_DELAY_FLD, 0, 7) | ||
414 | +REG32(DLL_OBSERVABLE_LOWER_REG, 0xbc) | ||
415 | + FIELD(DLL_OBSERVABLE_LOWER_REG, | ||
416 | + DLL_OBSERVABLE_LOWER_DLL_LOCK_INC_FLD, 24, 8) | ||
417 | + FIELD(DLL_OBSERVABLE_LOWER_REG, | ||
418 | + DLL_OBSERVABLE_LOWER_DLL_LOCK_DEC_FLD, 16, 8) | ||
419 | + FIELD(DLL_OBSERVABLE_LOWER_REG, | ||
420 | + DLL_OBSERVABLE_LOWER_LOOPBACK_LOCK_FLD, 15, 1) | ||
421 | + FIELD(DLL_OBSERVABLE_LOWER_REG, | ||
422 | + DLL_OBSERVABLE_LOWER_LOCK_VALUE_FLD, 8, 7) | ||
423 | + FIELD(DLL_OBSERVABLE_LOWER_REG, | ||
424 | + DLL_OBSERVABLE_LOWER_UNLOCK_COUNTER_FLD, 3, 5) | ||
425 | + FIELD(DLL_OBSERVABLE_LOWER_REG, | ||
426 | + DLL_OBSERVABLE_LOWER_LOCK_MODE_FLD, 1, 2) | ||
427 | + FIELD(DLL_OBSERVABLE_LOWER_REG, | ||
428 | + DLL_OBSERVABLE_LOWER_DLL_LOCK_FLD, 0, 1) | ||
429 | +REG32(DLL_OBSERVABLE_UPPER_REG, 0xc0) | ||
430 | + FIELD(DLL_OBSERVABLE_UPPER_REG, | ||
431 | + DLL_OBSERVABLE_UPPER_RESV2_FLD, 23, 9) | ||
432 | + FIELD(DLL_OBSERVABLE_UPPER_REG, | ||
433 | + DLL_OBSERVABLE_UPPER_TX_DECODER_OUTPUT_FLD, 16, 7) | ||
434 | + FIELD(DLL_OBSERVABLE_UPPER_REG, | ||
435 | + DLL_OBSERVABLE_UPPER_RESV1_FLD, 7, 9) | ||
436 | + FIELD(DLL_OBSERVABLE_UPPER_REG, | ||
437 | + DLL_OBSERVABLE__UPPER_RX_DECODER_OUTPUT_FLD, 0, 7) | ||
438 | +REG32(OPCODE_EXT_LOWER_REG, 0xe0) | ||
439 | + FIELD(OPCODE_EXT_LOWER_REG, EXT_READ_OPCODE_FLD, 24, 8) | ||
440 | + FIELD(OPCODE_EXT_LOWER_REG, EXT_WRITE_OPCODE_FLD, 16, 8) | ||
441 | + FIELD(OPCODE_EXT_LOWER_REG, EXT_POLL_OPCODE_FLD, 8, 8) | ||
442 | + FIELD(OPCODE_EXT_LOWER_REG, EXT_STIG_OPCODE_FLD, 0, 8) | ||
443 | +REG32(OPCODE_EXT_UPPER_REG, 0xe4) | ||
444 | + FIELD(OPCODE_EXT_UPPER_REG, WEL_OPCODE_FLD, 24, 8) | ||
445 | + FIELD(OPCODE_EXT_UPPER_REG, EXT_WEL_OPCODE_FLD, 16, 8) | ||
446 | + FIELD(OPCODE_EXT_UPPER_REG, OPCODE_EXT_UPPER_RESV1_FLD, 0, 16) | ||
447 | +REG32(MODULE_ID_REG, 0xfc) | ||
448 | + FIELD(MODULE_ID_REG, FIX_PATCH_FLD, 24, 8) | ||
449 | + FIELD(MODULE_ID_REG, MODULE_ID_FLD, 8, 16) | ||
450 | + FIELD(MODULE_ID_REG, MODULE_ID_RESV_FLD, 2, 6) | ||
451 | + FIELD(MODULE_ID_REG, CONF_FLD, 0, 2) | ||
452 | + | ||
453 | +#define RXFF_SZ 1024 | ||
454 | +#define TXFF_SZ 1024 | ||
455 | + | ||
456 | +#define MAX_RX_DEC_OUT 8 | ||
457 | + | ||
458 | +#define SZ_512MBIT (512 * 1024 * 1024) | ||
459 | +#define SZ_1GBIT (1024 * 1024 * 1024) | ||
460 | +#define SZ_2GBIT (2ULL * SZ_1GBIT) | ||
461 | +#define SZ_4GBIT (4ULL * SZ_1GBIT) | ||
462 | + | ||
463 | +#define IS_IND_DMA_START(op) (op->done_bytes == 0) | ||
464 | +/* | ||
465 | + * Bit field size of R_INDIRECT_WRITE_XFER_CTRL_REG_NUM_IND_OPS_DONE_FLD | ||
466 | + * is 2 bits, which can record max of 3 indac operations. | ||
467 | + */ | ||
468 | +#define IND_OPS_DONE_MAX 3 | ||
469 | + | ||
470 | +typedef enum { | ||
471 | + WREN = 0x6, | ||
472 | +} FlashCMD; | ||
473 | + | ||
474 | +static unsigned int ospi_stig_addr_len(XlnxVersalOspi *s) | ||
475 | +{ | ||
476 | + /* Num address bytes is NUM_ADDR_BYTES_FLD + 1 */ | ||
477 | + return ARRAY_FIELD_EX32(s->regs, | ||
478 | + FLASH_CMD_CTRL_REG, NUM_ADDR_BYTES_FLD) + 1; | ||
479 | +} | ||
480 | + | ||
481 | +static unsigned int ospi_stig_wr_data_len(XlnxVersalOspi *s) | ||
482 | +{ | ||
483 | + /* Num write data bytes is NUM_WR_DATA_BYTES_FLD + 1 */ | ||
484 | + return ARRAY_FIELD_EX32(s->regs, | ||
485 | + FLASH_CMD_CTRL_REG, NUM_WR_DATA_BYTES_FLD) + 1; | ||
486 | +} | ||
487 | + | ||
488 | +static unsigned int ospi_stig_rd_data_len(XlnxVersalOspi *s) | ||
489 | +{ | ||
490 | + /* Num read data bytes is NUM_RD_DATA_BYTES_FLD + 1 */ | ||
491 | + return ARRAY_FIELD_EX32(s->regs, | ||
492 | + FLASH_CMD_CTRL_REG, NUM_RD_DATA_BYTES_FLD) + 1; | ||
493 | +} | ||
494 | + | ||
495 | +/* | ||
496 | + * Status bits in R_IRQ_STATUS_REG are set when the event occurs and the | ||
497 | + * interrupt is enabled in the mask register ([1] Section 2.3.17) | ||
498 | + */ | ||
499 | +static void set_irq(XlnxVersalOspi *s, uint32_t set_mask) | ||
500 | +{ | ||
501 | + s->regs[R_IRQ_STATUS_REG] |= s->regs[R_IRQ_MASK_REG] & set_mask; | ||
502 | +} | ||
503 | + | ||
504 | +static void ospi_update_irq_line(XlnxVersalOspi *s) | ||
505 | +{ | ||
506 | + qemu_set_irq(s->irq, !!(s->regs[R_IRQ_STATUS_REG] & | ||
507 | + s->regs[R_IRQ_MASK_REG])); | ||
508 | +} | ||
509 | + | ||
510 | +static uint8_t ospi_get_wr_opcode(XlnxVersalOspi *s) | ||
511 | +{ | ||
512 | + return ARRAY_FIELD_EX32(s->regs, | ||
513 | + DEV_INSTR_WR_CONFIG_REG, WR_OPCODE_FLD); | ||
514 | +} | ||
515 | + | ||
516 | +static uint8_t ospi_get_rd_opcode(XlnxVersalOspi *s) | ||
517 | +{ | ||
518 | + return ARRAY_FIELD_EX32(s->regs, | ||
519 | + DEV_INSTR_RD_CONFIG_REG, RD_OPCODE_NON_XIP_FLD); | ||
520 | +} | ||
521 | + | ||
522 | +static uint32_t ospi_get_num_addr_bytes(XlnxVersalOspi *s) | ||
523 | +{ | ||
524 | + /* Num address bytes is NUM_ADDR_BYTES_FLD + 1 */ | ||
525 | + return ARRAY_FIELD_EX32(s->regs, | ||
526 | + DEV_SIZE_CONFIG_REG, NUM_ADDR_BYTES_FLD) + 1; | ||
527 | +} | ||
528 | + | ||
529 | +static void ospi_stig_membank_req(XlnxVersalOspi *s) | ||
530 | +{ | ||
531 | + int idx = ARRAY_FIELD_EX32(s->regs, | ||
532 | + FLASH_COMMAND_CTRL_MEM_REG, MEM_BANK_ADDR_FLD); | ||
533 | + | ||
534 | + ARRAY_FIELD_DP32(s->regs, FLASH_COMMAND_CTRL_MEM_REG, | ||
535 | + MEM_BANK_READ_DATA_FLD, s->stig_membank[idx]); | ||
536 | +} | ||
537 | + | ||
538 | +static int ospi_stig_membank_rd_bytes(XlnxVersalOspi *s) | ||
539 | +{ | ||
540 | + int rd_data_fld = ARRAY_FIELD_EX32(s->regs, FLASH_COMMAND_CTRL_MEM_REG, | ||
541 | + NB_OF_STIG_READ_BYTES_FLD); | ||
542 | + static const int sizes[6] = { 16, 32, 64, 128, 256, 512 }; | ||
543 | + return (rd_data_fld < 6) ? sizes[rd_data_fld] : 0; | ||
544 | +} | ||
545 | + | ||
546 | +static uint32_t ospi_get_page_sz(XlnxVersalOspi *s) | ||
547 | +{ | ||
548 | + return ARRAY_FIELD_EX32(s->regs, | ||
549 | + DEV_SIZE_CONFIG_REG, BYTES_PER_DEVICE_PAGE_FLD); | ||
550 | +} | ||
551 | + | ||
552 | +static bool ospi_ind_rd_watermark_enabled(XlnxVersalOspi *s) | ||
553 | +{ | ||
554 | + return s->regs[R_INDIRECT_READ_XFER_WATERMARK_REG]; | ||
555 | +} | ||
556 | + | ||
557 | +static void ind_op_advance(IndOp *op, unsigned int len) | ||
558 | +{ | ||
559 | + op->done_bytes += len; | ||
560 | + assert(op->done_bytes <= op->num_bytes); | ||
561 | + if (op->done_bytes == op->num_bytes) { | ||
562 | + op->completed = true; | ||
563 | + } | ||
564 | +} | ||
565 | + | ||
566 | +static uint32_t ind_op_next_byte(IndOp *op) | ||
567 | +{ | ||
568 | + return op->flash_addr + op->done_bytes; | ||
569 | +} | ||
570 | + | ||
571 | +static uint32_t ind_op_end_byte(IndOp *op) | ||
572 | +{ | ||
573 | + return op->flash_addr + op->num_bytes; | ||
574 | +} | ||
575 | + | ||
576 | +static void ospi_ind_op_next(IndOp *op) | ||
577 | +{ | ||
578 | + op[0] = op[1]; | ||
579 | + op[1].completed = true; | ||
580 | +} | ||
581 | + | ||
582 | +static void ind_op_setup(IndOp *op, uint32_t flash_addr, uint32_t num_bytes) | ||
583 | +{ | ||
584 | + if (num_bytes & 0x3) { | ||
585 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
586 | + "OSPI indirect op num bytes not word aligned\n"); | ||
587 | + } | ||
588 | + op->flash_addr = flash_addr; | ||
589 | + op->num_bytes = num_bytes; | ||
590 | + op->done_bytes = 0; | ||
591 | + op->completed = false; | ||
592 | +} | ||
593 | + | ||
594 | +static bool ospi_ind_op_completed(IndOp *op) | ||
595 | +{ | ||
596 | + return op->completed; | ||
597 | +} | ||
598 | + | ||
599 | +static bool ospi_ind_op_all_completed(XlnxVersalOspi *s) | ||
600 | +{ | ||
601 | + return s->rd_ind_op[0].completed && s->wr_ind_op[0].completed; | ||
602 | +} | ||
603 | + | ||
604 | +static void ospi_ind_op_cancel(IndOp *op) | ||
605 | +{ | ||
606 | + op[0].completed = true; | ||
607 | + op[1].completed = true; | ||
608 | +} | ||
609 | + | ||
610 | +static bool ospi_ind_op_add(IndOp *op, Fifo8 *fifo, | ||
611 | + uint32_t flash_addr, uint32_t num_bytes) | ||
612 | +{ | ||
613 | + /* Check if first indirect op has been completed */ | ||
614 | + if (op->completed) { | ||
615 | + fifo8_reset(fifo); | ||
616 | + ind_op_setup(op, flash_addr, num_bytes); | ||
617 | + return false; | ||
618 | + } | ||
619 | + | ||
620 | + /* Check if second indirect op has been completed */ | ||
621 | + op++; | ||
622 | + if (op->completed) { | ||
623 | + ind_op_setup(op, flash_addr, num_bytes); | ||
624 | + return false; | ||
625 | + } | ||
626 | + return true; | ||
627 | +} | ||
628 | + | ||
629 | +static void ospi_ind_op_queue_up_rd(XlnxVersalOspi *s) | ||
630 | +{ | ||
631 | + uint32_t num_bytes = s->regs[R_INDIRECT_READ_XFER_NUM_BYTES_REG]; | ||
632 | + uint32_t flash_addr = s->regs[R_INDIRECT_READ_XFER_START_REG]; | ||
633 | + bool failed; | ||
634 | + | ||
635 | + failed = ospi_ind_op_add(s->rd_ind_op, &s->rx_sram, flash_addr, num_bytes); | ||
636 | + /* If two already queued set rd reject interrupt */ | ||
637 | + if (failed) { | ||
638 | + set_irq(s, R_IRQ_STATUS_REG_INDIRECT_TRANSFER_REJECT_FLD_MASK); | ||
639 | + } | ||
640 | +} | ||
641 | + | ||
642 | +static void ospi_ind_op_queue_up_wr(XlnxVersalOspi *s) | ||
643 | +{ | ||
644 | + uint32_t num_bytes = s->regs[R_INDIRECT_WRITE_XFER_NUM_BYTES_REG]; | ||
645 | + uint32_t flash_addr = s->regs[R_INDIRECT_WRITE_XFER_START_REG]; | ||
646 | + bool failed; | ||
647 | + | ||
648 | + failed = ospi_ind_op_add(s->wr_ind_op, &s->tx_sram, flash_addr, num_bytes); | ||
649 | + /* If two already queued set rd reject interrupt */ | ||
650 | + if (failed) { | ||
651 | + set_irq(s, R_IRQ_STATUS_REG_INDIRECT_TRANSFER_REJECT_FLD_MASK); | ||
652 | + } | ||
653 | +} | ||
654 | + | ||
655 | +static uint64_t flash_sz(XlnxVersalOspi *s, unsigned int cs) | ||
656 | +{ | ||
657 | + /* Flash sizes in MB */ | ||
658 | + static const uint64_t sizes[4] = { SZ_512MBIT / 8, SZ_1GBIT / 8, | ||
659 | + SZ_2GBIT / 8, SZ_4GBIT / 8 }; | ||
660 | + uint32_t v = s->regs[R_DEV_SIZE_CONFIG_REG]; | ||
661 | + | ||
662 | + v >>= cs * R_DEV_SIZE_CONFIG_REG_MEM_SIZE_ON_CS0_FLD_LENGTH; | ||
663 | + return sizes[FIELD_EX32(v, DEV_SIZE_CONFIG_REG, MEM_SIZE_ON_CS0_FLD)]; | ||
664 | +} | ||
665 | + | ||
666 | +static unsigned int ospi_get_block_sz(XlnxVersalOspi *s) | ||
667 | +{ | ||
668 | + unsigned int block_fld = ARRAY_FIELD_EX32(s->regs, | ||
669 | + DEV_SIZE_CONFIG_REG, | ||
670 | + BYTES_PER_SUBSECTOR_FLD); | ||
671 | + return 1 << block_fld; | ||
672 | +} | ||
673 | + | ||
674 | +static unsigned int flash_blocks(XlnxVersalOspi *s, unsigned int cs) | ||
675 | +{ | ||
676 | + unsigned int b_sz = ospi_get_block_sz(s); | ||
677 | + unsigned int f_sz = flash_sz(s, cs); | ||
678 | + | ||
679 | + return f_sz / b_sz; | ||
680 | +} | ||
681 | + | ||
682 | +static int ospi_ahb_decoder_cs(XlnxVersalOspi *s, hwaddr addr) | ||
683 | +{ | ||
684 | + uint64_t end_addr = 0; | ||
685 | + int cs; | ||
686 | + | ||
687 | + for (cs = 0; cs < s->num_cs; cs++) { | ||
688 | + end_addr += flash_sz(s, cs); | ||
689 | + if (addr < end_addr) { | ||
690 | + break; | ||
691 | + } | ||
692 | + } | ||
693 | + | ||
694 | + if (cs == s->num_cs) { | ||
695 | + /* Address is out of range */ | ||
696 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
697 | + "OSPI flash address does not fit in configuration\n"); | ||
698 | + return -1; | ||
699 | + } | ||
700 | + return cs; | ||
701 | +} | ||
702 | + | ||
703 | +static void ospi_ahb_decoder_enable_cs(XlnxVersalOspi *s, hwaddr addr) | ||
704 | +{ | ||
705 | + int cs = ospi_ahb_decoder_cs(s, addr); | ||
706 | + | ||
707 | + if (cs >= 0) { | ||
708 | + for (int i = 0; i < s->num_cs; i++) { | ||
709 | + qemu_set_irq(s->cs_lines[i], cs != i); | ||
710 | + } | ||
711 | + } | ||
712 | +} | ||
713 | + | ||
714 | +static unsigned int single_cs(XlnxVersalOspi *s) | ||
715 | +{ | ||
716 | + unsigned int field = ARRAY_FIELD_EX32(s->regs, | ||
717 | + CONFIG_REG, PERIPH_CS_LINES_FLD); | ||
718 | + | ||
719 | + /* | ||
720 | + * Below one liner is a trick that finds the rightmost zero and makes sure | ||
721 | + * all other bits are turned to 1. It is a variant of the 'Isolate the | ||
722 | + * rightmost 0-bit' trick found below at the time of writing: | ||
723 | + * | ||
724 | + * https://emre.me/computer-science/bit-manipulation-tricks/ | ||
725 | + * | ||
726 | + * 4'bXXX0 -> 4'b1110 | ||
727 | + * 4'bXX01 -> 4'b1101 | ||
728 | + * 4'bX011 -> 4'b1011 | ||
729 | + * 4'b0111 -> 4'b0111 | ||
730 | + * 4'b1111 -> 4'b1111 | ||
731 | + */ | ||
732 | + return (field | ~(field + 1)) & 0xf; | ||
733 | +} | ||
734 | + | ||
735 | +static void ospi_update_cs_lines(XlnxVersalOspi *s) | ||
736 | +{ | ||
737 | + unsigned int all_cs; | ||
738 | + int i; | ||
739 | + | ||
740 | + if (ARRAY_FIELD_EX32(s->regs, CONFIG_REG, PERIPH_SEL_DEC_FLD)) { | ||
741 | + all_cs = ARRAY_FIELD_EX32(s->regs, CONFIG_REG, PERIPH_CS_LINES_FLD); | ||
742 | + } else { | ||
743 | + all_cs = single_cs(s); | ||
744 | + } | ||
745 | + | ||
746 | + for (i = 0; i < s->num_cs; i++) { | ||
747 | + bool cs = (all_cs >> i) & 1; | ||
748 | + | ||
749 | + qemu_set_irq(s->cs_lines[i], cs); | ||
750 | + } | ||
751 | +} | ||
752 | + | ||
753 | +static void ospi_dac_cs(XlnxVersalOspi *s, hwaddr addr) | ||
754 | +{ | ||
755 | + if (ARRAY_FIELD_EX32(s->regs, CONFIG_REG, ENABLE_AHB_DECODER_FLD)) { | ||
756 | + ospi_ahb_decoder_enable_cs(s, addr); | ||
757 | + } else { | ||
758 | + ospi_update_cs_lines(s); | ||
759 | + } | ||
760 | +} | ||
761 | + | ||
762 | +static void ospi_disable_cs(XlnxVersalOspi *s) | ||
763 | +{ | ||
764 | + int i; | ||
765 | + | ||
766 | + for (i = 0; i < s->num_cs; i++) { | ||
767 | + qemu_set_irq(s->cs_lines[i], 1); | ||
768 | + } | ||
769 | +} | ||
770 | + | ||
771 | +static void ospi_flush_txfifo(XlnxVersalOspi *s) | ||
772 | +{ | ||
773 | + while (!fifo8_is_empty(&s->tx_fifo)) { | ||
774 | + uint32_t tx_rx = fifo8_pop(&s->tx_fifo); | ||
775 | + | ||
776 | + tx_rx = ssi_transfer(s->spi, tx_rx); | ||
777 | + fifo8_push(&s->rx_fifo, tx_rx); | ||
778 | + } | ||
779 | +} | ||
780 | + | ||
781 | +static void ospi_tx_fifo_push_address_raw(XlnxVersalOspi *s, | ||
782 | + uint32_t flash_addr, | ||
783 | + unsigned int addr_bytes) | ||
784 | +{ | ||
785 | + /* Push write address */ | ||
786 | + if (addr_bytes == 4) { | ||
787 | + fifo8_push(&s->tx_fifo, flash_addr >> 24); | ||
788 | + } | ||
789 | + if (addr_bytes >= 3) { | ||
790 | + fifo8_push(&s->tx_fifo, flash_addr >> 16); | ||
791 | + } | ||
792 | + if (addr_bytes >= 2) { | ||
793 | + fifo8_push(&s->tx_fifo, flash_addr >> 8); | ||
794 | + } | ||
795 | + fifo8_push(&s->tx_fifo, flash_addr); | ||
796 | +} | ||
797 | + | ||
798 | +static void ospi_tx_fifo_push_address(XlnxVersalOspi *s, uint32_t flash_addr) | ||
799 | +{ | ||
800 | + /* Push write address */ | ||
801 | + int addr_bytes = ospi_get_num_addr_bytes(s); | ||
802 | + | ||
803 | + ospi_tx_fifo_push_address_raw(s, flash_addr, addr_bytes); | ||
804 | +} | ||
805 | + | ||
806 | +static void ospi_tx_fifo_push_stig_addr(XlnxVersalOspi *s) | ||
807 | +{ | ||
808 | + uint32_t flash_addr = s->regs[R_FLASH_CMD_ADDR_REG]; | ||
809 | + unsigned int addr_bytes = ospi_stig_addr_len(s); | ||
810 | + | ||
811 | + ospi_tx_fifo_push_address_raw(s, flash_addr, addr_bytes); | ||
812 | +} | ||
813 | + | ||
814 | +static void ospi_tx_fifo_push_rd_op_addr(XlnxVersalOspi *s, uint32_t flash_addr) | ||
815 | +{ | ||
816 | + uint8_t inst_code = ospi_get_rd_opcode(s); | ||
817 | + | ||
818 | + fifo8_reset(&s->tx_fifo); | ||
819 | + | ||
820 | + /* Push read opcode */ | ||
821 | + fifo8_push(&s->tx_fifo, inst_code); | ||
822 | + | ||
823 | + /* Push read address */ | ||
824 | + ospi_tx_fifo_push_address(s, flash_addr); | ||
825 | +} | ||
826 | + | ||
827 | +static void ospi_tx_fifo_push_stig_wr_data(XlnxVersalOspi *s) | ||
828 | +{ | ||
829 | + uint64_t data = s->regs[R_FLASH_WR_DATA_LOWER_REG]; | ||
830 | + int wr_data_len = ospi_stig_wr_data_len(s); | ||
831 | + int i; | ||
832 | + | ||
833 | + data |= (uint64_t) s->regs[R_FLASH_WR_DATA_UPPER_REG] << 32; | ||
834 | + for (i = 0; i < wr_data_len; i++) { | ||
835 | + int shift = i * 8; | ||
836 | + fifo8_push(&s->tx_fifo, data >> shift); | ||
837 | + } | ||
838 | +} | ||
839 | + | ||
840 | +static void ospi_tx_fifo_push_stig_rd_data(XlnxVersalOspi *s) | ||
841 | +{ | ||
842 | + int rd_data_len; | ||
843 | + int i; | ||
844 | + | ||
845 | + if (ARRAY_FIELD_EX32(s->regs, FLASH_CMD_CTRL_REG, STIG_MEM_BANK_EN_FLD)) { | ||
846 | + rd_data_len = ospi_stig_membank_rd_bytes(s); | ||
847 | + } else { | ||
848 | + rd_data_len = ospi_stig_rd_data_len(s); | ||
849 | + } | ||
850 | + | ||
851 | + /* transmit second part (data) */ | ||
852 | + for (i = 0; i < rd_data_len; ++i) { | ||
853 | + fifo8_push(&s->tx_fifo, 0); | ||
854 | + } | ||
855 | +} | ||
856 | + | ||
857 | +static void ospi_rx_fifo_pop_stig_rd_data(XlnxVersalOspi *s) | ||
858 | +{ | ||
859 | + int size = ospi_stig_rd_data_len(s); | ||
860 | + uint8_t bytes[8] = {}; | ||
861 | + int i; | ||
862 | + | ||
863 | + size = MIN(fifo8_num_used(&s->rx_fifo), size); | ||
864 | + | ||
865 | + assert(size <= 8); | ||
866 | + | ||
867 | + for (i = 0; i < size; i++) { | ||
868 | + bytes[i] = fifo8_pop(&s->rx_fifo); | ||
869 | + } | ||
870 | + | ||
871 | + s->regs[R_FLASH_RD_DATA_LOWER_REG] = ldl_le_p(bytes); | ||
872 | + s->regs[R_FLASH_RD_DATA_UPPER_REG] = ldl_le_p(bytes + 4); | ||
873 | +} | ||
874 | + | ||
875 | +static void ospi_ind_read(XlnxVersalOspi *s, uint32_t flash_addr, uint32_t len) | ||
876 | +{ | ||
877 | + int i; | ||
878 | + | ||
879 | + /* Create first section of read cmd */ | ||
880 | + ospi_tx_fifo_push_rd_op_addr(s, flash_addr); | ||
881 | + | ||
882 | + /* transmit first part */ | ||
883 | + ospi_update_cs_lines(s); | ||
884 | + ospi_flush_txfifo(s); | ||
885 | + | ||
886 | + fifo8_reset(&s->rx_fifo); | ||
887 | + | ||
888 | + /* transmit second part (data) */ | ||
889 | + for (i = 0; i < len; ++i) { | ||
890 | + fifo8_push(&s->tx_fifo, 0); | ||
891 | + } | ||
892 | + ospi_flush_txfifo(s); | ||
893 | + | ||
894 | + for (i = 0; i < len; ++i) { | ||
895 | + fifo8_push(&s->rx_sram, fifo8_pop(&s->rx_fifo)); | ||
896 | + } | ||
897 | + | ||
898 | + /* done */ | ||
899 | + ospi_disable_cs(s); | ||
900 | +} | ||
901 | + | ||
902 | +static unsigned int ospi_dma_burst_size(XlnxVersalOspi *s) | ||
903 | +{ | ||
904 | + return 1 << ARRAY_FIELD_EX32(s->regs, | ||
905 | + DMA_PERIPH_CONFIG_REG, | ||
906 | + NUM_BURST_REQ_BYTES_FLD); | ||
907 | +} | ||
908 | + | ||
909 | +static unsigned int ospi_dma_single_size(XlnxVersalOspi *s) | ||
910 | +{ | ||
911 | + return 1 << ARRAY_FIELD_EX32(s->regs, | ||
912 | + DMA_PERIPH_CONFIG_REG, | ||
913 | + NUM_SINGLE_REQ_BYTES_FLD); | ||
914 | +} | ||
915 | + | ||
916 | +static void ind_rd_inc_num_done(XlnxVersalOspi *s) | ||
917 | +{ | ||
918 | + unsigned int done = ARRAY_FIELD_EX32(s->regs, | ||
919 | + INDIRECT_READ_XFER_CTRL_REG, | ||
920 | + NUM_IND_OPS_DONE_FLD); | ||
921 | + if (done < IND_OPS_DONE_MAX) { | ||
922 | + done++; | ||
923 | + } | ||
924 | + done &= 0x3; | ||
925 | + ARRAY_FIELD_DP32(s->regs, INDIRECT_READ_XFER_CTRL_REG, | ||
926 | + NUM_IND_OPS_DONE_FLD, done); | ||
927 | +} | ||
928 | + | ||
929 | +static void ospi_ind_rd_completed(XlnxVersalOspi *s) | ||
930 | +{ | ||
931 | + ARRAY_FIELD_DP32(s->regs, INDIRECT_READ_XFER_CTRL_REG, | ||
932 | + IND_OPS_DONE_STATUS_FLD, 1); | ||
933 | + | ||
934 | + ind_rd_inc_num_done(s); | ||
935 | + ospi_ind_op_next(s->rd_ind_op); | ||
936 | + if (ospi_ind_op_all_completed(s)) { | ||
937 | + set_irq(s, R_IRQ_STATUS_REG_INDIRECT_OP_DONE_FLD_MASK); | ||
938 | + } | ||
939 | +} | ||
940 | + | ||
941 | +static void ospi_dma_read(XlnxVersalOspi *s) | ||
942 | +{ | ||
943 | + IndOp *op = s->rd_ind_op; | ||
944 | + uint32_t dma_len = op->num_bytes; | ||
945 | + uint32_t burst_sz = ospi_dma_burst_size(s); | ||
946 | + uint32_t single_sz = ospi_dma_single_size(s); | ||
947 | + uint32_t ind_trig_range; | ||
948 | + uint32_t remainder; | ||
949 | + XlnxCSUDMAClass *xcdc = XLNX_CSU_DMA_GET_CLASS(s->dma_src); | ||
950 | + | ||
951 | + ind_trig_range = (1 << ARRAY_FIELD_EX32(s->regs, | ||
952 | + INDIRECT_TRIGGER_ADDR_RANGE_REG, | ||
953 | + IND_RANGE_WIDTH_FLD)); | ||
954 | + remainder = dma_len % burst_sz; | ||
955 | + remainder = remainder % single_sz; | ||
956 | + if (burst_sz > ind_trig_range || single_sz > ind_trig_range || | ||
957 | + remainder != 0) { | ||
958 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
959 | + "OSPI DMA burst size / single size config error\n"); | ||
960 | + } | ||
961 | + | ||
962 | + s->src_dma_inprog = true; | ||
963 | + if (xcdc->read(s->dma_src, 0, dma_len) != MEMTX_OK) { | ||
964 | + qemu_log_mask(LOG_GUEST_ERROR, "OSPI DMA configuration error\n"); | ||
965 | + } | ||
966 | + s->src_dma_inprog = false; | ||
967 | +} | ||
968 | + | ||
969 | +static void ospi_do_ind_read(XlnxVersalOspi *s) | ||
970 | +{ | ||
971 | + IndOp *op = s->rd_ind_op; | ||
972 | + uint32_t next_b; | ||
973 | + uint32_t end_b; | ||
974 | + uint32_t len; | ||
975 | + bool start_dma = IS_IND_DMA_START(op) && !s->src_dma_inprog; | ||
976 | + | ||
977 | + /* Continue to read flash until we run out of space in sram */ | ||
978 | + while (!ospi_ind_op_completed(op) && | ||
979 | + !fifo8_is_full(&s->rx_sram)) { | ||
980 | + /* Read reqested number of bytes, max bytes limited to size of sram */ | ||
981 | + next_b = ind_op_next_byte(op); | ||
982 | + end_b = next_b + fifo8_num_free(&s->rx_sram); | ||
983 | + end_b = MIN(end_b, ind_op_end_byte(op)); | ||
984 | + | ||
985 | + len = end_b - next_b; | ||
986 | + ospi_ind_read(s, next_b, len); | ||
987 | + ind_op_advance(op, len); | ||
988 | + | ||
989 | + if (ospi_ind_rd_watermark_enabled(s)) { | ||
990 | + ARRAY_FIELD_DP32(s->regs, IRQ_STATUS_REG, | ||
991 | + INDIRECT_XFER_LEVEL_BREACH_FLD, 1); | ||
992 | + set_irq(s, | ||
993 | + R_IRQ_STATUS_REG_INDIRECT_XFER_LEVEL_BREACH_FLD_MASK); | ||
994 | + } | ||
995 | + | ||
996 | + if (!s->src_dma_inprog && | ||
997 | + ARRAY_FIELD_EX32(s->regs, CONFIG_REG, ENB_DMA_IF_FLD)) { | ||
998 | + ospi_dma_read(s); | ||
999 | + } | ||
1000 | + } | ||
1001 | + | ||
1002 | + /* Set sram full */ | ||
1003 | + if (fifo8_num_used(&s->rx_sram) == RXFF_SZ) { | ||
1004 | + ARRAY_FIELD_DP32(s->regs, | ||
1005 | + INDIRECT_READ_XFER_CTRL_REG, SRAM_FULL_FLD, 1); | ||
1006 | + set_irq(s, R_IRQ_STATUS_REG_INDRD_SRAM_FULL_FLD_MASK); | ||
1007 | + } | ||
1008 | + | ||
1009 | + /* Signal completion if done, unless inside recursion via ospi_dma_read */ | ||
1010 | + if (!ARRAY_FIELD_EX32(s->regs, CONFIG_REG, ENB_DMA_IF_FLD) || start_dma) { | ||
1011 | + if (ospi_ind_op_completed(op)) { | ||
1012 | + ospi_ind_rd_completed(s); | ||
1013 | + } | ||
1014 | + } | ||
1015 | +} | ||
1016 | + | ||
1017 | +/* Transmit write enable instruction */ | ||
1018 | +static void ospi_transmit_wel(XlnxVersalOspi *s, bool ahb_decoder_cs, | ||
1019 | + hwaddr addr) | ||
1020 | +{ | ||
1021 | + fifo8_reset(&s->tx_fifo); | ||
1022 | + fifo8_push(&s->tx_fifo, WREN); | ||
1023 | + | ||
1024 | + if (ahb_decoder_cs) { | ||
1025 | + ospi_ahb_decoder_enable_cs(s, addr); | ||
1026 | + } else { | ||
1027 | + ospi_update_cs_lines(s); | ||
1028 | + } | ||
1029 | + | ||
1030 | + ospi_flush_txfifo(s); | ||
1031 | + ospi_disable_cs(s); | ||
1032 | + | ||
1033 | + fifo8_reset(&s->rx_fifo); | ||
1034 | +} | ||
1035 | + | ||
1036 | +static void ospi_ind_write(XlnxVersalOspi *s, uint32_t flash_addr, uint32_t len) | ||
1037 | +{ | ||
1038 | + bool ahb_decoder_cs = false; | ||
1039 | + uint8_t inst_code; | ||
1040 | + int i; | ||
1041 | + | ||
1042 | + assert(fifo8_num_used(&s->tx_sram) >= len); | ||
1043 | + | ||
1044 | + if (!ARRAY_FIELD_EX32(s->regs, DEV_INSTR_WR_CONFIG_REG, WEL_DIS_FLD)) { | ||
1045 | + ospi_transmit_wel(s, ahb_decoder_cs, 0); | ||
1046 | + } | ||
1047 | + | ||
1048 | + /* reset fifos */ | ||
1049 | + fifo8_reset(&s->tx_fifo); | ||
1050 | + fifo8_reset(&s->rx_fifo); | ||
1051 | + | ||
1052 | + /* Push write opcode */ | ||
1053 | + inst_code = ospi_get_wr_opcode(s); | ||
1054 | + fifo8_push(&s->tx_fifo, inst_code); | ||
1055 | + | ||
1056 | + /* Push write address */ | ||
1057 | + ospi_tx_fifo_push_address(s, flash_addr); | ||
1058 | + | ||
1059 | + /* data */ | ||
1060 | + for (i = 0; i < len; i++) { | ||
1061 | + fifo8_push(&s->tx_fifo, fifo8_pop(&s->tx_sram)); | ||
1062 | + } | ||
1063 | + | ||
1064 | + /* transmit */ | ||
1065 | + ospi_update_cs_lines(s); | ||
1066 | + ospi_flush_txfifo(s); | ||
1067 | + | ||
1068 | + /* done */ | ||
1069 | + ospi_disable_cs(s); | ||
1070 | + fifo8_reset(&s->rx_fifo); | ||
1071 | +} | ||
1072 | + | ||
1073 | +static void ind_wr_inc_num_done(XlnxVersalOspi *s) | ||
1074 | +{ | ||
1075 | + unsigned int done = ARRAY_FIELD_EX32(s->regs, INDIRECT_WRITE_XFER_CTRL_REG, | ||
1076 | + NUM_IND_OPS_DONE_FLD); | ||
1077 | + if (done < IND_OPS_DONE_MAX) { | ||
1078 | + done++; | ||
1079 | + } | ||
1080 | + done &= 0x3; | ||
1081 | + ARRAY_FIELD_DP32(s->regs, INDIRECT_WRITE_XFER_CTRL_REG, | ||
1082 | + NUM_IND_OPS_DONE_FLD, done); | ||
1083 | +} | ||
1084 | + | ||
1085 | +static void ospi_ind_wr_completed(XlnxVersalOspi *s) | ||
1086 | +{ | ||
1087 | + ARRAY_FIELD_DP32(s->regs, INDIRECT_WRITE_XFER_CTRL_REG, | ||
1088 | + IND_OPS_DONE_STATUS_FLD, 1); | ||
1089 | + ind_wr_inc_num_done(s); | ||
1090 | + ospi_ind_op_next(s->wr_ind_op); | ||
1091 | + /* Set indirect op done interrupt if enabled */ | ||
1092 | + if (ospi_ind_op_all_completed(s)) { | ||
1093 | + set_irq(s, R_IRQ_STATUS_REG_INDIRECT_OP_DONE_FLD_MASK); | ||
1094 | + } | ||
1095 | +} | ||
1096 | + | ||
1097 | +static void ospi_do_indirect_write(XlnxVersalOspi *s) | ||
1098 | +{ | ||
1099 | + uint32_t write_watermark = s->regs[R_INDIRECT_WRITE_XFER_WATERMARK_REG]; | ||
1100 | + uint32_t pagesz = ospi_get_page_sz(s); | ||
1101 | + uint32_t page_mask = ~(pagesz - 1); | ||
1102 | + IndOp *op = s->wr_ind_op; | ||
1103 | + uint32_t next_b; | ||
1104 | + uint32_t end_b; | ||
1105 | + uint32_t len; | ||
1106 | + | ||
1107 | + /* Write out tx_fifo in maximum page sz chunks */ | ||
1108 | + while (!ospi_ind_op_completed(op) && fifo8_num_used(&s->tx_sram) > 0) { | ||
1109 | + next_b = ind_op_next_byte(op); | ||
1110 | + end_b = next_b + MIN(fifo8_num_used(&s->tx_sram), pagesz); | ||
1111 | + | ||
1112 | + /* Dont cross page boundary */ | ||
1113 | + if ((end_b & page_mask) > next_b) { | ||
1114 | + end_b &= page_mask; | ||
1115 | + } | ||
1116 | + | ||
1117 | + len = end_b - next_b; | ||
1118 | + len = MIN(len, op->num_bytes - op->done_bytes); | ||
1119 | + ospi_ind_write(s, next_b, len); | ||
1120 | + ind_op_advance(op, len); | ||
1121 | + } | ||
1122 | + | ||
1123 | + /* | ||
1124 | + * Always set indirect transfer level breached interrupt if enabled | ||
1125 | + * (write watermark > 0) since the tx_sram always will be emptied | ||
1126 | + */ | ||
1127 | + if (write_watermark > 0) { | ||
1128 | + set_irq(s, R_IRQ_STATUS_REG_INDIRECT_XFER_LEVEL_BREACH_FLD_MASK); | ||
1129 | + } | ||
1130 | + | ||
1131 | + /* Signal completions if done */ | ||
1132 | + if (ospi_ind_op_completed(op)) { | ||
1133 | + ospi_ind_wr_completed(s); | ||
1134 | + } | ||
1135 | +} | ||
1136 | + | ||
1137 | +static void ospi_stig_fill_membank(XlnxVersalOspi *s) | ||
1138 | +{ | ||
1139 | + int num_rd_bytes = ospi_stig_membank_rd_bytes(s); | ||
1140 | + int idx = num_rd_bytes - 8; /* first of last 8 */ | ||
1141 | + int i; | ||
1142 | + | ||
1143 | + for (i = 0; i < num_rd_bytes; i++) { | ||
1144 | + s->stig_membank[i] = fifo8_pop(&s->rx_fifo); | ||
1145 | + } | ||
1146 | + | ||
1147 | + g_assert((idx + 4) < ARRAY_SIZE(s->stig_membank)); | ||
1148 | + | ||
1149 | + /* Fill in lower upper regs */ | ||
1150 | + s->regs[R_FLASH_RD_DATA_LOWER_REG] = ldl_le_p(&s->stig_membank[idx]); | ||
1151 | + s->regs[R_FLASH_RD_DATA_UPPER_REG] = ldl_le_p(&s->stig_membank[idx + 4]); | ||
1152 | +} | ||
1153 | + | ||
1154 | +static void ospi_stig_cmd_exec(XlnxVersalOspi *s) | ||
1155 | +{ | ||
1156 | + uint8_t inst_code; | ||
1157 | + | ||
1158 | + /* Reset fifos */ | ||
1159 | + fifo8_reset(&s->tx_fifo); | ||
1160 | + fifo8_reset(&s->rx_fifo); | ||
1161 | + | ||
1162 | + /* Push write opcode */ | ||
1163 | + inst_code = ARRAY_FIELD_EX32(s->regs, FLASH_CMD_CTRL_REG, CMD_OPCODE_FLD); | ||
1164 | + fifo8_push(&s->tx_fifo, inst_code); | ||
1165 | + | ||
1166 | + /* Push address if enabled */ | ||
1167 | + if (ARRAY_FIELD_EX32(s->regs, FLASH_CMD_CTRL_REG, ENB_COMD_ADDR_FLD)) { | ||
1168 | + ospi_tx_fifo_push_stig_addr(s); | ||
1169 | + } | ||
1170 | + | ||
1171 | + /* Enable cs */ | ||
1172 | + ospi_update_cs_lines(s); | ||
1173 | + | ||
1174 | + /* Data */ | ||
1175 | + if (ARRAY_FIELD_EX32(s->regs, FLASH_CMD_CTRL_REG, ENB_WRITE_DATA_FLD)) { | ||
1176 | + ospi_tx_fifo_push_stig_wr_data(s); | ||
1177 | + } else if (ARRAY_FIELD_EX32(s->regs, | ||
1178 | + FLASH_CMD_CTRL_REG, ENB_READ_DATA_FLD)) { | ||
1179 | + /* transmit first part */ | ||
1180 | + ospi_flush_txfifo(s); | ||
1181 | + fifo8_reset(&s->rx_fifo); | ||
1182 | + ospi_tx_fifo_push_stig_rd_data(s); | ||
1183 | + } | ||
1184 | + | ||
1185 | + /* Transmit */ | ||
1186 | + ospi_flush_txfifo(s); | ||
1187 | + ospi_disable_cs(s); | ||
1188 | + | ||
1189 | + if (ARRAY_FIELD_EX32(s->regs, FLASH_CMD_CTRL_REG, ENB_READ_DATA_FLD)) { | ||
1190 | + if (ARRAY_FIELD_EX32(s->regs, | ||
1191 | + FLASH_CMD_CTRL_REG, STIG_MEM_BANK_EN_FLD)) { | ||
1192 | + ospi_stig_fill_membank(s); | ||
1193 | + } else { | ||
1194 | + ospi_rx_fifo_pop_stig_rd_data(s); | ||
1195 | + } | ||
1196 | + } | ||
1197 | +} | ||
1198 | + | ||
1199 | +static uint32_t ospi_block_address(XlnxVersalOspi *s, unsigned int block) | ||
1200 | +{ | ||
1201 | + unsigned int block_sz = ospi_get_block_sz(s); | ||
1202 | + unsigned int cs = 0; | ||
1203 | + uint32_t addr = 0; | ||
1204 | + | ||
1205 | + while (cs < s->num_cs && block >= flash_blocks(s, cs)) { | ||
1206 | + block -= flash_blocks(s, 0); | ||
1207 | + addr += flash_sz(s, cs); | ||
1208 | + } | ||
1209 | + addr += block * block_sz; | ||
1210 | + return addr; | ||
1211 | +} | ||
1212 | + | ||
1213 | +static uint32_t ospi_get_wr_prot_addr_low(XlnxVersalOspi *s) | ||
1214 | +{ | ||
1215 | + unsigned int block = s->regs[R_LOWER_WR_PROT_REG]; | ||
1216 | + | ||
1217 | + return ospi_block_address(s, block); | ||
1218 | +} | ||
1219 | + | ||
1220 | +static uint32_t ospi_get_wr_prot_addr_upper(XlnxVersalOspi *s) | ||
1221 | +{ | ||
1222 | + unsigned int block = s->regs[R_UPPER_WR_PROT_REG]; | ||
1223 | + | ||
1224 | + /* Get address of first block out of defined range */ | ||
1225 | + return ospi_block_address(s, block + 1); | ||
1226 | +} | ||
1227 | + | ||
1228 | +static bool ospi_is_write_protected(XlnxVersalOspi *s, hwaddr addr) | ||
1229 | +{ | ||
1230 | + uint32_t wr_prot_addr_upper = ospi_get_wr_prot_addr_upper(s); | ||
1231 | + uint32_t wr_prot_addr_low = ospi_get_wr_prot_addr_low(s); | ||
1232 | + bool in_range = false; | ||
1233 | + | ||
1234 | + if (addr >= wr_prot_addr_low && addr < wr_prot_addr_upper) { | ||
1235 | + in_range = true; | ||
1236 | + } | ||
1237 | + | ||
1238 | + if (ARRAY_FIELD_EX32(s->regs, WR_PROT_CTRL_REG, INV_FLD)) { | ||
1239 | + in_range = !in_range; | ||
1240 | + } | ||
1241 | + return in_range; | ||
1242 | +} | ||
1243 | + | ||
1244 | +static uint64_t ospi_rx_sram_read(XlnxVersalOspi *s, unsigned int size) | ||
1245 | +{ | ||
1246 | + uint8_t bytes[8] = {}; | ||
1247 | + int i; | ||
1248 | + | ||
1249 | + if (size < 4 && fifo8_num_used(&s->rx_sram) >= 4) { | ||
1250 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
1251 | + "OSPI only last read of internal " | ||
1252 | + "sram is allowed to be < 32 bits\n"); | ||
1253 | + } | ||
1254 | + | ||
1255 | + size = MIN(fifo8_num_used(&s->rx_sram), size); | ||
1256 | + | ||
1257 | + assert(size <= 8); | ||
1258 | + | ||
1259 | + for (i = 0; i < size; i++) { | ||
1260 | + bytes[i] = fifo8_pop(&s->rx_sram); | ||
1261 | + } | ||
1262 | + | ||
1263 | + return ldq_le_p(bytes); | ||
1264 | +} | ||
1265 | + | ||
1266 | +static void ospi_tx_sram_write(XlnxVersalOspi *s, uint64_t value, | ||
1267 | + unsigned int size) | ||
1268 | +{ | ||
1269 | + int i; | ||
1270 | + for (i = 0; i < size && !fifo8_is_full(&s->tx_sram); i++) { | ||
1271 | + fifo8_push(&s->tx_sram, value >> 8 * i); | ||
1272 | + } | ||
1273 | +} | ||
1274 | + | ||
1275 | +static uint64_t ospi_do_dac_read(void *opaque, hwaddr addr, unsigned int size) | ||
1276 | +{ | ||
1277 | + XlnxVersalOspi *s = XILINX_VERSAL_OSPI(opaque); | ||
1278 | + uint8_t bytes[8] = {}; | ||
1279 | + int i; | ||
1280 | + | ||
1281 | + /* Create first section of read cmd */ | ||
1282 | + ospi_tx_fifo_push_rd_op_addr(s, (uint32_t) addr); | ||
1283 | + | ||
1284 | + /* Enable cs and transmit first part */ | ||
1285 | + ospi_dac_cs(s, addr); | ||
1286 | + ospi_flush_txfifo(s); | ||
1287 | + | ||
1288 | + fifo8_reset(&s->rx_fifo); | ||
1289 | + | ||
1290 | + /* transmit second part (data) */ | ||
1291 | + for (i = 0; i < size; ++i) { | ||
1292 | + fifo8_push(&s->tx_fifo, 0); | ||
1293 | + } | ||
1294 | + ospi_flush_txfifo(s); | ||
1295 | + | ||
1296 | + /* fill in result */ | ||
1297 | + size = MIN(fifo8_num_used(&s->rx_fifo), size); | ||
1298 | + | ||
1299 | + assert(size <= 8); | ||
1300 | + | ||
1301 | + for (i = 0; i < size; i++) { | ||
1302 | + bytes[i] = fifo8_pop(&s->rx_fifo); | ||
1303 | + } | ||
1304 | + | ||
1305 | + /* done */ | ||
1306 | + ospi_disable_cs(s); | ||
1307 | + | ||
1308 | + return ldq_le_p(bytes); | ||
1309 | +} | ||
1310 | + | ||
1311 | +static void ospi_do_dac_write(void *opaque, | ||
1312 | + hwaddr addr, | ||
1313 | + uint64_t value, | ||
1314 | + unsigned int size) | ||
1315 | +{ | ||
1316 | + XlnxVersalOspi *s = XILINX_VERSAL_OSPI(opaque); | ||
1317 | + bool ahb_decoder_cs = ARRAY_FIELD_EX32(s->regs, CONFIG_REG, | ||
1318 | + ENABLE_AHB_DECODER_FLD); | ||
1319 | + uint8_t inst_code; | ||
1320 | + unsigned int i; | ||
1321 | + | ||
1322 | + if (!ARRAY_FIELD_EX32(s->regs, DEV_INSTR_WR_CONFIG_REG, WEL_DIS_FLD)) { | ||
1323 | + ospi_transmit_wel(s, ahb_decoder_cs, addr); | ||
1324 | + } | ||
1325 | + | ||
1326 | + /* reset fifos */ | ||
1327 | + fifo8_reset(&s->tx_fifo); | ||
1328 | + fifo8_reset(&s->rx_fifo); | ||
1329 | + | ||
1330 | + /* Push write opcode */ | ||
1331 | + inst_code = ospi_get_wr_opcode(s); | ||
1332 | + fifo8_push(&s->tx_fifo, inst_code); | ||
1333 | + | ||
1334 | + /* Push write address */ | ||
1335 | + ospi_tx_fifo_push_address(s, addr); | ||
1336 | + | ||
1337 | + /* data */ | ||
1338 | + for (i = 0; i < size; i++) { | ||
1339 | + fifo8_push(&s->tx_fifo, value >> 8 * i); | ||
1340 | + } | ||
1341 | + | ||
1342 | + /* Enable cs and transmit */ | ||
1343 | + ospi_dac_cs(s, addr); | ||
1344 | + ospi_flush_txfifo(s); | ||
1345 | + ospi_disable_cs(s); | ||
1346 | + | ||
1347 | + fifo8_reset(&s->rx_fifo); | ||
1348 | +} | ||
1349 | + | ||
1350 | +static void flash_cmd_ctrl_mem_reg_post_write(RegisterInfo *reg, | ||
1351 | + uint64_t val) | ||
1352 | +{ | ||
1353 | + XlnxVersalOspi *s = XILINX_VERSAL_OSPI(reg->opaque); | ||
1354 | + if (ARRAY_FIELD_EX32(s->regs, CONFIG_REG, ENB_SPI_FLD)) { | ||
1355 | + if (ARRAY_FIELD_EX32(s->regs, | ||
1356 | + FLASH_COMMAND_CTRL_MEM_REG, | ||
1357 | + TRIGGER_MEM_BANK_REQ_FLD)) { | ||
1358 | + ospi_stig_membank_req(s); | ||
1359 | + ARRAY_FIELD_DP32(s->regs, FLASH_COMMAND_CTRL_MEM_REG, | ||
1360 | + TRIGGER_MEM_BANK_REQ_FLD, 0); | ||
1361 | + } | ||
1362 | + } | ||
1363 | +} | ||
1364 | + | ||
1365 | +static void flash_cmd_ctrl_reg_post_write(RegisterInfo *reg, uint64_t val) | ||
1366 | +{ | ||
1367 | + XlnxVersalOspi *s = XILINX_VERSAL_OSPI(reg->opaque); | ||
1368 | + | ||
1369 | + if (ARRAY_FIELD_EX32(s->regs, CONFIG_REG, ENB_SPI_FLD) && | ||
1370 | + ARRAY_FIELD_EX32(s->regs, FLASH_CMD_CTRL_REG, CMD_EXEC_FLD)) { | ||
1371 | + ospi_stig_cmd_exec(s); | ||
1372 | + set_irq(s, R_IRQ_STATUS_REG_STIG_REQ_INT_FLD_MASK); | ||
1373 | + ARRAY_FIELD_DP32(s->regs, FLASH_CMD_CTRL_REG, CMD_EXEC_FLD, 0); | ||
1374 | + } | ||
1375 | +} | ||
1376 | + | ||
1377 | +static uint64_t ind_wr_dec_num_done(XlnxVersalOspi *s, uint64_t val) | ||
1378 | +{ | ||
1379 | + unsigned int done = ARRAY_FIELD_EX32(s->regs, INDIRECT_WRITE_XFER_CTRL_REG, | ||
1380 | + NUM_IND_OPS_DONE_FLD); | ||
1381 | + done--; | ||
1382 | + done &= 0x3; | ||
1383 | + val = FIELD_DP32(val, INDIRECT_WRITE_XFER_CTRL_REG, | ||
1384 | + NUM_IND_OPS_DONE_FLD, done); | ||
1385 | + return val; | ||
1386 | +} | ||
1387 | + | ||
1388 | +static bool ind_wr_clearing_op_done(XlnxVersalOspi *s, uint64_t new_val) | ||
1389 | +{ | ||
1390 | + bool set_in_reg = ARRAY_FIELD_EX32(s->regs, INDIRECT_WRITE_XFER_CTRL_REG, | ||
1391 | + IND_OPS_DONE_STATUS_FLD); | ||
1392 | + bool set_in_new_val = FIELD_EX32(new_val, INDIRECT_WRITE_XFER_CTRL_REG, | ||
1393 | + IND_OPS_DONE_STATUS_FLD); | ||
1394 | + /* return true if clearing bit */ | ||
1395 | + return set_in_reg && !set_in_new_val; | ||
1396 | +} | ||
1397 | + | ||
1398 | +static uint64_t ind_wr_xfer_ctrl_reg_pre_write(RegisterInfo *reg, | ||
1399 | + uint64_t val) | ||
1400 | +{ | ||
1401 | + XlnxVersalOspi *s = XILINX_VERSAL_OSPI(reg->opaque); | ||
1402 | + | ||
1403 | + if (ind_wr_clearing_op_done(s, val)) { | ||
1404 | + val = ind_wr_dec_num_done(s, val); | ||
1405 | + } | ||
1406 | + return val; | ||
1407 | +} | ||
1408 | + | ||
1409 | +static void ind_wr_xfer_ctrl_reg_post_write(RegisterInfo *reg, uint64_t val) | ||
1410 | +{ | ||
1411 | + XlnxVersalOspi *s = XILINX_VERSAL_OSPI(reg->opaque); | ||
1412 | + | ||
1413 | + if (s->ind_write_disabled) { | ||
1414 | + return; | ||
1415 | + } | ||
1416 | + | ||
1417 | + if (ARRAY_FIELD_EX32(s->regs, INDIRECT_WRITE_XFER_CTRL_REG, START_FLD)) { | ||
1418 | + ospi_ind_op_queue_up_wr(s); | ||
1419 | + ospi_do_indirect_write(s); | ||
1420 | + ARRAY_FIELD_DP32(s->regs, INDIRECT_WRITE_XFER_CTRL_REG, START_FLD, 0); | ||
1421 | + } | ||
1422 | + | ||
1423 | + if (ARRAY_FIELD_EX32(s->regs, INDIRECT_WRITE_XFER_CTRL_REG, CANCEL_FLD)) { | ||
1424 | + ospi_ind_op_cancel(s->wr_ind_op); | ||
1425 | + fifo8_reset(&s->tx_sram); | ||
1426 | + ARRAY_FIELD_DP32(s->regs, INDIRECT_WRITE_XFER_CTRL_REG, CANCEL_FLD, 0); | ||
1427 | + } | ||
1428 | +} | ||
1429 | + | ||
1430 | +static uint64_t ind_wr_xfer_ctrl_reg_post_read(RegisterInfo *reg, | ||
1431 | + uint64_t val) | ||
1432 | +{ | ||
1433 | + XlnxVersalOspi *s = XILINX_VERSAL_OSPI(reg->opaque); | ||
1434 | + IndOp *op = s->wr_ind_op; | ||
1435 | + | ||
1436 | + /* Check if ind ops is ongoing */ | ||
1437 | + if (!ospi_ind_op_completed(&op[0])) { | ||
1438 | + /* Check if two ind ops are queued */ | ||
1439 | + if (!ospi_ind_op_completed(&op[1])) { | ||
1440 | + val = FIELD_DP32(val, INDIRECT_WRITE_XFER_CTRL_REG, | ||
1441 | + WR_QUEUED_FLD, 1); | ||
1442 | + } | ||
1443 | + val = FIELD_DP32(val, INDIRECT_WRITE_XFER_CTRL_REG, WR_STATUS_FLD, 1); | ||
1444 | + } | ||
1445 | + return val; | ||
1446 | +} | ||
1447 | + | ||
1448 | +static uint64_t ind_rd_dec_num_done(XlnxVersalOspi *s, uint64_t val) | ||
1449 | +{ | ||
1450 | + unsigned int done = ARRAY_FIELD_EX32(s->regs, INDIRECT_READ_XFER_CTRL_REG, | ||
1451 | + NUM_IND_OPS_DONE_FLD); | ||
1452 | + done--; | ||
1453 | + done &= 0x3; | ||
1454 | + val = FIELD_DP32(val, INDIRECT_READ_XFER_CTRL_REG, | ||
1455 | + NUM_IND_OPS_DONE_FLD, done); | ||
1456 | + return val; | ||
1457 | +} | ||
1458 | + | ||
1459 | +static uint64_t ind_rd_xfer_ctrl_reg_pre_write(RegisterInfo *reg, | ||
1460 | + uint64_t val) | ||
1461 | +{ | ||
1462 | + XlnxVersalOspi *s = XILINX_VERSAL_OSPI(reg->opaque); | ||
1463 | + | ||
1464 | + if (FIELD_EX32(val, INDIRECT_READ_XFER_CTRL_REG, | ||
1465 | + IND_OPS_DONE_STATUS_FLD)) { | ||
1466 | + val = ind_rd_dec_num_done(s, val); | ||
1467 | + val &= ~R_INDIRECT_READ_XFER_CTRL_REG_IND_OPS_DONE_STATUS_FLD_MASK; | ||
1468 | + } | ||
1469 | + return val; | ||
1470 | +} | ||
1471 | + | ||
1472 | +static void ind_rd_xfer_ctrl_reg_post_write(RegisterInfo *reg, uint64_t val) | ||
1473 | +{ | ||
1474 | + XlnxVersalOspi *s = XILINX_VERSAL_OSPI(reg->opaque); | ||
1475 | + | ||
1476 | + if (ARRAY_FIELD_EX32(s->regs, INDIRECT_READ_XFER_CTRL_REG, START_FLD)) { | ||
1477 | + ospi_ind_op_queue_up_rd(s); | ||
1478 | + ospi_do_ind_read(s); | ||
1479 | + ARRAY_FIELD_DP32(s->regs, INDIRECT_READ_XFER_CTRL_REG, START_FLD, 0); | ||
1480 | + } | ||
1481 | + | ||
1482 | + if (ARRAY_FIELD_EX32(s->regs, INDIRECT_READ_XFER_CTRL_REG, CANCEL_FLD)) { | ||
1483 | + ospi_ind_op_cancel(s->rd_ind_op); | ||
1484 | + fifo8_reset(&s->rx_sram); | ||
1485 | + ARRAY_FIELD_DP32(s->regs, INDIRECT_READ_XFER_CTRL_REG, CANCEL_FLD, 0); | ||
1486 | + } | ||
1487 | +} | ||
1488 | + | ||
1489 | +static uint64_t ind_rd_xfer_ctrl_reg_post_read(RegisterInfo *reg, | ||
1490 | + uint64_t val) | ||
1491 | +{ | ||
1492 | + XlnxVersalOspi *s = XILINX_VERSAL_OSPI(reg->opaque); | ||
1493 | + IndOp *op = s->rd_ind_op; | ||
1494 | + | ||
1495 | + /* Check if ind ops is ongoing */ | ||
1496 | + if (!ospi_ind_op_completed(&op[0])) { | ||
1497 | + /* Check if two ind ops are queued */ | ||
1498 | + if (!ospi_ind_op_completed(&op[1])) { | ||
1499 | + val = FIELD_DP32(val, INDIRECT_READ_XFER_CTRL_REG, | ||
1500 | + RD_QUEUED_FLD, 1); | ||
1501 | + } | ||
1502 | + val = FIELD_DP32(val, INDIRECT_READ_XFER_CTRL_REG, RD_STATUS_FLD, 1); | ||
1503 | + } | ||
1504 | + return val; | ||
1505 | +} | ||
1506 | + | ||
1507 | +static uint64_t sram_fill_reg_post_read(RegisterInfo *reg, uint64_t val) | ||
1508 | +{ | ||
1509 | + XlnxVersalOspi *s = XILINX_VERSAL_OSPI(reg->opaque); | ||
1510 | + val = ((fifo8_num_used(&s->tx_sram) & 0xFFFF) << 16) | | ||
1511 | + (fifo8_num_used(&s->rx_sram) & 0xFFFF); | ||
1512 | + return val; | ||
1513 | +} | ||
1514 | + | ||
1515 | +static uint64_t dll_obs_upper_reg_post_read(RegisterInfo *reg, uint64_t val) | ||
1516 | +{ | ||
1517 | + XlnxVersalOspi *s = XILINX_VERSAL_OSPI(reg->opaque); | ||
1518 | + uint32_t rx_dec_out; | ||
1519 | + | ||
1520 | + rx_dec_out = FIELD_EX32(val, DLL_OBSERVABLE_UPPER_REG, | ||
1521 | + DLL_OBSERVABLE__UPPER_RX_DECODER_OUTPUT_FLD); | ||
1522 | + | ||
1523 | + if (rx_dec_out < MAX_RX_DEC_OUT) { | ||
1524 | + ARRAY_FIELD_DP32(s->regs, DLL_OBSERVABLE_UPPER_REG, | ||
1525 | + DLL_OBSERVABLE__UPPER_RX_DECODER_OUTPUT_FLD, | ||
1526 | + rx_dec_out + 1); | ||
1527 | + } | ||
1528 | + | ||
1529 | + return val; | ||
1530 | +} | ||
1531 | + | ||
1532 | + | ||
1533 | +static void xlnx_versal_ospi_reset(DeviceState *dev) | ||
1534 | +{ | ||
1535 | + XlnxVersalOspi *s = XILINX_VERSAL_OSPI(dev); | ||
1536 | + unsigned int i; | ||
1537 | + | ||
1538 | + for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) { | ||
1539 | + register_reset(&s->regs_info[i]); | ||
1540 | + } | ||
1541 | + | ||
1542 | + fifo8_reset(&s->rx_fifo); | ||
1543 | + fifo8_reset(&s->tx_fifo); | ||
1544 | + fifo8_reset(&s->rx_sram); | ||
1545 | + fifo8_reset(&s->tx_sram); | ||
1546 | + | ||
1547 | + s->rd_ind_op[0].completed = true; | ||
1548 | + s->rd_ind_op[1].completed = true; | ||
1549 | + s->wr_ind_op[0].completed = true; | ||
1550 | + s->wr_ind_op[1].completed = true; | ||
1551 | + ARRAY_FIELD_DP32(s->regs, DLL_OBSERVABLE_LOWER_REG, | ||
1552 | + DLL_OBSERVABLE_LOWER_DLL_LOCK_FLD, 1); | ||
1553 | + ARRAY_FIELD_DP32(s->regs, DLL_OBSERVABLE_LOWER_REG, | ||
1554 | + DLL_OBSERVABLE_LOWER_LOOPBACK_LOCK_FLD, 1); | ||
1555 | +} | ||
1556 | + | ||
1557 | +static RegisterAccessInfo ospi_regs_info[] = { | ||
1558 | + { .name = "CONFIG_REG", | ||
1559 | + .addr = A_CONFIG_REG, | ||
1560 | + .reset = 0x80780081, | ||
1561 | + .ro = 0x9c000000, | ||
1562 | + },{ .name = "DEV_INSTR_RD_CONFIG_REG", | ||
1563 | + .addr = A_DEV_INSTR_RD_CONFIG_REG, | ||
1564 | + .reset = 0x3, | ||
1565 | + .ro = 0xe0ecc800, | ||
1566 | + },{ .name = "DEV_INSTR_WR_CONFIG_REG", | ||
1567 | + .addr = A_DEV_INSTR_WR_CONFIG_REG, | ||
1568 | + .reset = 0x2, | ||
1569 | + .ro = 0xe0fcce00, | ||
1570 | + },{ .name = "DEV_DELAY_REG", | ||
1571 | + .addr = A_DEV_DELAY_REG, | ||
1572 | + },{ .name = "RD_DATA_CAPTURE_REG", | ||
1573 | + .addr = A_RD_DATA_CAPTURE_REG, | ||
1574 | + .reset = 0x1, | ||
1575 | + .ro = 0xfff0fec0, | ||
1576 | + },{ .name = "DEV_SIZE_CONFIG_REG", | ||
1577 | + .addr = A_DEV_SIZE_CONFIG_REG, | ||
1578 | + .reset = 0x101002, | ||
1579 | + .ro = 0xe0000000, | ||
1580 | + },{ .name = "SRAM_PARTITION_CFG_REG", | ||
1581 | + .addr = A_SRAM_PARTITION_CFG_REG, | ||
1582 | + .reset = 0x80, | ||
1583 | + .ro = 0xffffff00, | ||
1584 | + },{ .name = "IND_AHB_ADDR_TRIGGER_REG", | ||
1585 | + .addr = A_IND_AHB_ADDR_TRIGGER_REG, | ||
1586 | + },{ .name = "DMA_PERIPH_CONFIG_REG", | ||
1587 | + .addr = A_DMA_PERIPH_CONFIG_REG, | ||
1588 | + .ro = 0xfffff0f0, | ||
1589 | + },{ .name = "REMAP_ADDR_REG", | ||
1590 | + .addr = A_REMAP_ADDR_REG, | ||
1591 | + },{ .name = "MODE_BIT_CONFIG_REG", | ||
1592 | + .addr = A_MODE_BIT_CONFIG_REG, | ||
1593 | + .reset = 0x200, | ||
1594 | + .ro = 0xffff7800, | ||
1595 | + },{ .name = "SRAM_FILL_REG", | ||
1596 | + .addr = A_SRAM_FILL_REG, | ||
1597 | + .ro = 0xffffffff, | ||
1598 | + .post_read = sram_fill_reg_post_read, | ||
1599 | + },{ .name = "TX_THRESH_REG", | ||
1600 | + .addr = A_TX_THRESH_REG, | ||
1601 | + .reset = 0x1, | ||
1602 | + .ro = 0xffffffe0, | ||
1603 | + },{ .name = "RX_THRESH_REG", | ||
1604 | + .addr = A_RX_THRESH_REG, | ||
1605 | + .reset = 0x1, | ||
1606 | + .ro = 0xffffffe0, | ||
1607 | + },{ .name = "WRITE_COMPLETION_CTRL_REG", | ||
1608 | + .addr = A_WRITE_COMPLETION_CTRL_REG, | ||
1609 | + .reset = 0x10005, | ||
1610 | + .ro = 0x1800, | ||
1611 | + },{ .name = "NO_OF_POLLS_BEF_EXP_REG", | ||
1612 | + .addr = A_NO_OF_POLLS_BEF_EXP_REG, | ||
1613 | + .reset = 0xffffffff, | ||
1614 | + },{ .name = "IRQ_STATUS_REG", | ||
1615 | + .addr = A_IRQ_STATUS_REG, | ||
1616 | + .ro = 0xfff08000, | ||
1617 | + .w1c = 0xf7fff, | ||
1618 | + },{ .name = "IRQ_MASK_REG", | ||
1619 | + .addr = A_IRQ_MASK_REG, | ||
1620 | + .ro = 0xfff08000, | ||
1621 | + },{ .name = "LOWER_WR_PROT_REG", | ||
1622 | + .addr = A_LOWER_WR_PROT_REG, | ||
1623 | + },{ .name = "UPPER_WR_PROT_REG", | ||
1624 | + .addr = A_UPPER_WR_PROT_REG, | ||
1625 | + },{ .name = "WR_PROT_CTRL_REG", | ||
1626 | + .addr = A_WR_PROT_CTRL_REG, | ||
1627 | + .ro = 0xfffffffc, | ||
1628 | + },{ .name = "INDIRECT_READ_XFER_CTRL_REG", | ||
1629 | + .addr = A_INDIRECT_READ_XFER_CTRL_REG, | ||
1630 | + .ro = 0xffffffd4, | ||
1631 | + .w1c = 0x08, | ||
1632 | + .pre_write = ind_rd_xfer_ctrl_reg_pre_write, | ||
1633 | + .post_write = ind_rd_xfer_ctrl_reg_post_write, | ||
1634 | + .post_read = ind_rd_xfer_ctrl_reg_post_read, | ||
1635 | + },{ .name = "INDIRECT_READ_XFER_WATERMARK_REG", | ||
1636 | + .addr = A_INDIRECT_READ_XFER_WATERMARK_REG, | ||
1637 | + },{ .name = "INDIRECT_READ_XFER_START_REG", | ||
1638 | + .addr = A_INDIRECT_READ_XFER_START_REG, | ||
1639 | + },{ .name = "INDIRECT_READ_XFER_NUM_BYTES_REG", | ||
1640 | + .addr = A_INDIRECT_READ_XFER_NUM_BYTES_REG, | ||
1641 | + },{ .name = "INDIRECT_WRITE_XFER_CTRL_REG", | ||
1642 | + .addr = A_INDIRECT_WRITE_XFER_CTRL_REG, | ||
1643 | + .ro = 0xffffffdc, | ||
1644 | + .w1c = 0x20, | ||
1645 | + .pre_write = ind_wr_xfer_ctrl_reg_pre_write, | ||
1646 | + .post_write = ind_wr_xfer_ctrl_reg_post_write, | ||
1647 | + .post_read = ind_wr_xfer_ctrl_reg_post_read, | ||
1648 | + },{ .name = "INDIRECT_WRITE_XFER_WATERMARK_REG", | ||
1649 | + .addr = A_INDIRECT_WRITE_XFER_WATERMARK_REG, | ||
1650 | + .reset = 0xffffffff, | ||
1651 | + },{ .name = "INDIRECT_WRITE_XFER_START_REG", | ||
1652 | + .addr = A_INDIRECT_WRITE_XFER_START_REG, | ||
1653 | + },{ .name = "INDIRECT_WRITE_XFER_NUM_BYTES_REG", | ||
1654 | + .addr = A_INDIRECT_WRITE_XFER_NUM_BYTES_REG, | ||
1655 | + },{ .name = "INDIRECT_TRIGGER_ADDR_RANGE_REG", | ||
1656 | + .addr = A_INDIRECT_TRIGGER_ADDR_RANGE_REG, | ||
1657 | + .reset = 0x4, | ||
1658 | + .ro = 0xfffffff0, | ||
1659 | + },{ .name = "FLASH_COMMAND_CTRL_MEM_REG", | ||
1660 | + .addr = A_FLASH_COMMAND_CTRL_MEM_REG, | ||
1661 | + .ro = 0xe008fffe, | ||
1662 | + .post_write = flash_cmd_ctrl_mem_reg_post_write, | ||
1663 | + },{ .name = "FLASH_CMD_CTRL_REG", | ||
1664 | + .addr = A_FLASH_CMD_CTRL_REG, | ||
1665 | + .ro = 0x7a, | ||
1666 | + .post_write = flash_cmd_ctrl_reg_post_write, | ||
1667 | + },{ .name = "FLASH_CMD_ADDR_REG", | ||
1668 | + .addr = A_FLASH_CMD_ADDR_REG, | ||
1669 | + },{ .name = "FLASH_RD_DATA_LOWER_REG", | ||
1670 | + .addr = A_FLASH_RD_DATA_LOWER_REG, | ||
1671 | + .ro = 0xffffffff, | ||
1672 | + },{ .name = "FLASH_RD_DATA_UPPER_REG", | ||
1673 | + .addr = A_FLASH_RD_DATA_UPPER_REG, | ||
1674 | + .ro = 0xffffffff, | ||
1675 | + },{ .name = "FLASH_WR_DATA_LOWER_REG", | ||
1676 | + .addr = A_FLASH_WR_DATA_LOWER_REG, | ||
1677 | + },{ .name = "FLASH_WR_DATA_UPPER_REG", | ||
1678 | + .addr = A_FLASH_WR_DATA_UPPER_REG, | ||
1679 | + },{ .name = "POLLING_FLASH_STATUS_REG", | ||
1680 | + .addr = A_POLLING_FLASH_STATUS_REG, | ||
1681 | + .ro = 0xfff0ffff, | ||
1682 | + },{ .name = "PHY_CONFIGURATION_REG", | ||
1683 | + .addr = A_PHY_CONFIGURATION_REG, | ||
1684 | + .reset = 0x40000000, | ||
1685 | + .ro = 0x1f80ff80, | ||
1686 | + },{ .name = "PHY_MASTER_CONTROL_REG", | ||
1687 | + .addr = A_PHY_MASTER_CONTROL_REG, | ||
1688 | + .reset = 0x800000, | ||
1689 | + .ro = 0xfe08ff80, | ||
1690 | + },{ .name = "DLL_OBSERVABLE_LOWER_REG", | ||
1691 | + .addr = A_DLL_OBSERVABLE_LOWER_REG, | ||
1692 | + .ro = 0xffffffff, | ||
1693 | + },{ .name = "DLL_OBSERVABLE_UPPER_REG", | ||
1694 | + .addr = A_DLL_OBSERVABLE_UPPER_REG, | ||
1695 | + .ro = 0xffffffff, | ||
1696 | + .post_read = dll_obs_upper_reg_post_read, | ||
1697 | + },{ .name = "OPCODE_EXT_LOWER_REG", | ||
1698 | + .addr = A_OPCODE_EXT_LOWER_REG, | ||
1699 | + .reset = 0x13edfa00, | ||
1700 | + },{ .name = "OPCODE_EXT_UPPER_REG", | ||
1701 | + .addr = A_OPCODE_EXT_UPPER_REG, | ||
1702 | + .reset = 0x6f90000, | ||
1703 | + .ro = 0xffff, | ||
1704 | + },{ .name = "MODULE_ID_REG", | ||
1705 | + .addr = A_MODULE_ID_REG, | ||
1706 | + .reset = 0x300, | ||
1707 | + .ro = 0xffffffff, | ||
1708 | + } | ||
1709 | +}; | ||
1710 | + | ||
1711 | +/* Return dev-obj from reg-region created by register_init_block32 */ | ||
1712 | +static XlnxVersalOspi *xilinx_ospi_of_mr(void *mr_accessor) | ||
1713 | +{ | ||
1714 | + RegisterInfoArray *reg_array = mr_accessor; | ||
1715 | + Object *dev; | ||
1716 | + | ||
1717 | + dev = reg_array->mem.owner; | ||
1718 | + assert(dev); | ||
1719 | + | ||
1720 | + return XILINX_VERSAL_OSPI(dev); | ||
1721 | +} | ||
1722 | + | ||
1723 | +static void ospi_write(void *opaque, hwaddr addr, uint64_t value, | ||
1724 | + unsigned int size) | ||
1725 | +{ | ||
1726 | + XlnxVersalOspi *s = xilinx_ospi_of_mr(opaque); | ||
1727 | + | ||
1728 | + register_write_memory(opaque, addr, value, size); | ||
1729 | + ospi_update_irq_line(s); | ||
1730 | +} | ||
1731 | + | ||
1732 | +static const MemoryRegionOps ospi_ops = { | ||
1733 | + .read = register_read_memory, | ||
1734 | + .write = ospi_write, | ||
1735 | + .endianness = DEVICE_LITTLE_ENDIAN, | ||
1736 | + .valid = { | ||
1737 | + .min_access_size = 4, | ||
1738 | + .max_access_size = 4, | ||
1739 | + }, | ||
1740 | +}; | ||
1741 | + | ||
1742 | +static uint64_t ospi_indac_read(void *opaque, unsigned int size) | ||
1743 | +{ | ||
1744 | + XlnxVersalOspi *s = XILINX_VERSAL_OSPI(opaque); | ||
1745 | + uint64_t ret = ospi_rx_sram_read(s, size); | ||
1746 | + | ||
1747 | + if (!ospi_ind_op_completed(s->rd_ind_op)) { | ||
1748 | + ospi_do_ind_read(s); | ||
1749 | + } | ||
1750 | + return ret; | ||
1751 | +} | ||
1752 | + | ||
1753 | +static void ospi_indac_write(void *opaque, uint64_t value, unsigned int size) | ||
1754 | +{ | ||
1755 | + XlnxVersalOspi *s = XILINX_VERSAL_OSPI(opaque); | ||
1756 | + | ||
1757 | + g_assert(!s->ind_write_disabled); | ||
1758 | + | ||
1759 | + if (!ospi_ind_op_completed(s->wr_ind_op)) { | ||
1760 | + ospi_tx_sram_write(s, value, size); | ||
1761 | + ospi_do_indirect_write(s); | ||
1762 | + } else { | ||
1763 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
1764 | + "OSPI wr into indac area while no ongoing indac wr\n"); | ||
1765 | + } | ||
1766 | +} | ||
1767 | + | ||
1768 | +static bool is_inside_indac_range(XlnxVersalOspi *s, hwaddr addr) | ||
1769 | +{ | ||
1770 | + uint32_t range_start; | ||
1771 | + uint32_t range_end; | ||
1772 | + | ||
1773 | + if (ARRAY_FIELD_EX32(s->regs, CONFIG_REG, ENB_DMA_IF_FLD)) { | ||
1774 | + return true; | ||
1775 | + } | ||
1776 | + | ||
1777 | + range_start = s->regs[R_IND_AHB_ADDR_TRIGGER_REG]; | ||
1778 | + range_end = range_start + | ||
1779 | + (1 << ARRAY_FIELD_EX32(s->regs, | ||
1780 | + INDIRECT_TRIGGER_ADDR_RANGE_REG, | ||
1781 | + IND_RANGE_WIDTH_FLD)); | ||
1782 | + | ||
1783 | + addr += s->regs[R_IND_AHB_ADDR_TRIGGER_REG] & 0xF0000000; | ||
1784 | + | ||
1785 | + return addr >= range_start && addr < range_end; | ||
1786 | +} | ||
1787 | + | ||
1788 | +static bool ospi_is_indac_active(XlnxVersalOspi *s) | ||
1789 | +{ | ||
1790 | + /* | ||
1791 | + * When dac and indac cannot be active at the same time, | ||
1792 | + * return true when dac is disabled. | ||
1793 | + */ | ||
1794 | + return s->dac_with_indac || !s->dac_enable; | ||
1795 | +} | ||
1796 | + | ||
1797 | +static uint64_t ospi_dac_read(void *opaque, hwaddr addr, unsigned int size) | ||
1798 | +{ | ||
1799 | + XlnxVersalOspi *s = XILINX_VERSAL_OSPI(opaque); | ||
1800 | + | ||
1801 | + if (ARRAY_FIELD_EX32(s->regs, CONFIG_REG, ENB_SPI_FLD)) { | ||
1802 | + if (ospi_is_indac_active(s) && | ||
1803 | + is_inside_indac_range(s, addr)) { | ||
1804 | + return ospi_indac_read(s, size); | ||
1805 | + } | ||
1806 | + if (ARRAY_FIELD_EX32(s->regs, CONFIG_REG, ENB_DIR_ACC_CTLR_FLD) | ||
1807 | + && s->dac_enable) { | ||
1808 | + if (ARRAY_FIELD_EX32(s->regs, | ||
1809 | + CONFIG_REG, ENB_AHB_ADDR_REMAP_FLD)) { | ||
1810 | + addr += s->regs[R_REMAP_ADDR_REG]; | ||
1811 | + } | ||
1812 | + return ospi_do_dac_read(opaque, addr, size); | ||
1813 | + } else { | ||
1814 | + qemu_log_mask(LOG_GUEST_ERROR, "OSPI AHB rd while DAC disabled\n"); | ||
1815 | + } | ||
1816 | + } else { | ||
1817 | + qemu_log_mask(LOG_GUEST_ERROR, "OSPI AHB rd while OSPI disabled\n"); | ||
1818 | + } | ||
1819 | + | ||
1820 | + return 0; | ||
1821 | +} | ||
1822 | + | ||
1823 | +static void ospi_dac_write(void *opaque, hwaddr addr, uint64_t value, | ||
1824 | + unsigned int size) | ||
1825 | +{ | ||
1826 | + XlnxVersalOspi *s = XILINX_VERSAL_OSPI(opaque); | ||
1827 | + | ||
1828 | + if (ARRAY_FIELD_EX32(s->regs, CONFIG_REG, ENB_SPI_FLD)) { | ||
1829 | + if (ospi_is_indac_active(s) && | ||
1830 | + !s->ind_write_disabled && | ||
1831 | + is_inside_indac_range(s, addr)) { | ||
1832 | + return ospi_indac_write(s, value, size); | ||
1833 | + } | ||
1834 | + if (ARRAY_FIELD_EX32(s->regs, CONFIG_REG, ENB_DIR_ACC_CTLR_FLD) && | ||
1835 | + s->dac_enable) { | ||
1836 | + if (ARRAY_FIELD_EX32(s->regs, | ||
1837 | + CONFIG_REG, ENB_AHB_ADDR_REMAP_FLD)) { | ||
1838 | + addr += s->regs[R_REMAP_ADDR_REG]; | ||
1839 | + } | ||
1840 | + /* Check if addr is write protected */ | ||
1841 | + if (ARRAY_FIELD_EX32(s->regs, WR_PROT_CTRL_REG, ENB_FLD) && | ||
1842 | + ospi_is_write_protected(s, addr)) { | ||
1843 | + set_irq(s, R_IRQ_STATUS_REG_PROT_WR_ATTEMPT_FLD_MASK); | ||
1844 | + ospi_update_irq_line(s); | ||
1845 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
1846 | + "OSPI writing into write protected area\n"); | ||
1847 | + return; | ||
1848 | + } | ||
1849 | + ospi_do_dac_write(opaque, addr, value, size); | ||
1850 | + } else { | ||
1851 | + qemu_log_mask(LOG_GUEST_ERROR, "OSPI AHB wr while DAC disabled\n"); | ||
1852 | + } | ||
1853 | + } else { | ||
1854 | + qemu_log_mask(LOG_GUEST_ERROR, "OSPI AHB wr while OSPI disabled\n"); | ||
1855 | + } | ||
1856 | +} | ||
1857 | + | ||
1858 | +static const MemoryRegionOps ospi_dac_ops = { | ||
1859 | + .read = ospi_dac_read, | ||
1860 | + .write = ospi_dac_write, | ||
1861 | + .endianness = DEVICE_LITTLE_ENDIAN, | ||
1862 | + .valid = { | ||
1863 | + .min_access_size = 4, | ||
1864 | + .max_access_size = 4, | ||
1865 | + }, | ||
1866 | +}; | ||
1867 | + | ||
1868 | +static void ospi_update_dac_status(void *opaque, int n, int level) | ||
1869 | +{ | ||
1870 | + XlnxVersalOspi *s = XILINX_VERSAL_OSPI(opaque); | ||
1871 | + | ||
1872 | + s->dac_enable = level; | ||
1873 | +} | ||
1874 | + | ||
1875 | +static void xlnx_versal_ospi_realize(DeviceState *dev, Error **errp) | ||
1876 | +{ | ||
1877 | + XlnxVersalOspi *s = XILINX_VERSAL_OSPI(dev); | ||
1878 | + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); | ||
1879 | + | ||
1880 | + s->num_cs = 4; | ||
1881 | + s->spi = ssi_create_bus(dev, "spi0"); | ||
1882 | + s->cs_lines = g_new0(qemu_irq, s->num_cs); | ||
1883 | + for (int i = 0; i < s->num_cs; ++i) { | ||
1884 | + sysbus_init_irq(sbd, &s->cs_lines[i]); | ||
1885 | + } | ||
1886 | + | ||
1887 | + fifo8_create(&s->rx_fifo, RXFF_SZ); | ||
1888 | + fifo8_create(&s->tx_fifo, TXFF_SZ); | ||
1889 | + fifo8_create(&s->rx_sram, RXFF_SZ); | ||
1890 | + fifo8_create(&s->tx_sram, TXFF_SZ); | ||
1891 | +} | ||
1892 | + | ||
1893 | +static void xlnx_versal_ospi_init(Object *obj) | ||
1894 | +{ | ||
1895 | + XlnxVersalOspi *s = XILINX_VERSAL_OSPI(obj); | ||
1896 | + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); | ||
1897 | + DeviceState *dev = DEVICE(obj); | ||
1898 | + RegisterInfoArray *reg_array; | ||
1899 | + | ||
1900 | + memory_region_init(&s->iomem, obj, TYPE_XILINX_VERSAL_OSPI, | ||
1901 | + XILINX_VERSAL_OSPI_R_MAX * 4); | ||
1902 | + reg_array = | ||
1903 | + register_init_block32(DEVICE(obj), ospi_regs_info, | ||
1904 | + ARRAY_SIZE(ospi_regs_info), | ||
1905 | + s->regs_info, s->regs, | ||
1906 | + &ospi_ops, | ||
1907 | + XILINX_VERSAL_OSPI_ERR_DEBUG, | ||
1908 | + XILINX_VERSAL_OSPI_R_MAX * 4); | ||
1909 | + memory_region_add_subregion(&s->iomem, 0x0, ®_array->mem); | ||
1910 | + sysbus_init_mmio(sbd, &s->iomem); | ||
1911 | + | ||
1912 | + memory_region_init_io(&s->iomem_dac, obj, &ospi_dac_ops, s, | ||
1913 | + TYPE_XILINX_VERSAL_OSPI "-dac", 0x20000000); | ||
1914 | + sysbus_init_mmio(sbd, &s->iomem_dac); | ||
1915 | + | ||
1916 | + sysbus_init_irq(sbd, &s->irq); | ||
1917 | + | ||
1918 | + object_property_add_link(obj, "dma-src", TYPE_XLNX_CSU_DMA, | ||
1919 | + (Object **)&s->dma_src, | ||
1920 | + object_property_allow_set_link, | ||
1921 | + OBJ_PROP_LINK_STRONG); | ||
1922 | + | ||
1923 | + qdev_init_gpio_in_named(dev, ospi_update_dac_status, "ospi-mux-sel", 1); | ||
1924 | +} | ||
1925 | + | ||
1926 | +static const VMStateDescription vmstate_ind_op = { | ||
1927 | + .name = "OSPIIndOp", | ||
1928 | + .version_id = 1, | ||
1929 | + .minimum_version_id = 1, | ||
1930 | + .fields = (VMStateField[]) { | ||
1931 | + VMSTATE_UINT32(flash_addr, IndOp), | ||
1932 | + VMSTATE_UINT32(num_bytes, IndOp), | ||
1933 | + VMSTATE_UINT32(done_bytes, IndOp), | ||
1934 | + VMSTATE_BOOL(completed, IndOp), | ||
1935 | + VMSTATE_END_OF_LIST() | ||
1936 | + } | ||
1937 | +}; | ||
1938 | + | ||
1939 | +static const VMStateDescription vmstate_xlnx_versal_ospi = { | ||
1940 | + .name = TYPE_XILINX_VERSAL_OSPI, | ||
1941 | + .version_id = 1, | ||
1942 | + .minimum_version_id = 1, | ||
1943 | + .minimum_version_id_old = 1, | ||
1944 | + .fields = (VMStateField[]) { | ||
1945 | + VMSTATE_FIFO8(rx_fifo, XlnxVersalOspi), | ||
1946 | + VMSTATE_FIFO8(tx_fifo, XlnxVersalOspi), | ||
1947 | + VMSTATE_FIFO8(rx_sram, XlnxVersalOspi), | ||
1948 | + VMSTATE_FIFO8(tx_sram, XlnxVersalOspi), | ||
1949 | + VMSTATE_BOOL(ind_write_disabled, XlnxVersalOspi), | ||
1950 | + VMSTATE_BOOL(dac_with_indac, XlnxVersalOspi), | ||
1951 | + VMSTATE_BOOL(dac_enable, XlnxVersalOspi), | ||
1952 | + VMSTATE_BOOL(src_dma_inprog, XlnxVersalOspi), | ||
1953 | + VMSTATE_STRUCT_ARRAY(rd_ind_op, XlnxVersalOspi, 2, 1, | ||
1954 | + vmstate_ind_op, IndOp), | ||
1955 | + VMSTATE_STRUCT_ARRAY(wr_ind_op, XlnxVersalOspi, 2, 1, | ||
1956 | + vmstate_ind_op, IndOp), | ||
1957 | + VMSTATE_UINT32_ARRAY(regs, XlnxVersalOspi, XILINX_VERSAL_OSPI_R_MAX), | ||
1958 | + VMSTATE_UINT8_ARRAY(stig_membank, XlnxVersalOspi, 512), | ||
1959 | + VMSTATE_END_OF_LIST(), | ||
1960 | + } | ||
1961 | +}; | ||
1962 | + | ||
1963 | +static Property xlnx_versal_ospi_properties[] = { | ||
1964 | + DEFINE_PROP_BOOL("dac-with-indac", XlnxVersalOspi, dac_with_indac, false), | ||
1965 | + DEFINE_PROP_BOOL("indac-write-disabled", XlnxVersalOspi, | ||
1966 | + ind_write_disabled, false), | ||
1967 | + DEFINE_PROP_END_OF_LIST(), | ||
1968 | +}; | ||
1969 | + | ||
1970 | +static void xlnx_versal_ospi_class_init(ObjectClass *klass, void *data) | ||
1971 | +{ | ||
1972 | + DeviceClass *dc = DEVICE_CLASS(klass); | ||
1973 | + | ||
1974 | + dc->reset = xlnx_versal_ospi_reset; | ||
1975 | + dc->realize = xlnx_versal_ospi_realize; | ||
1976 | + dc->vmsd = &vmstate_xlnx_versal_ospi; | ||
1977 | + device_class_set_props(dc, xlnx_versal_ospi_properties); | ||
1978 | +} | ||
1979 | + | ||
1980 | +static const TypeInfo xlnx_versal_ospi_info = { | ||
1981 | + .name = TYPE_XILINX_VERSAL_OSPI, | ||
1982 | + .parent = TYPE_SYS_BUS_DEVICE, | ||
1983 | + .instance_size = sizeof(XlnxVersalOspi), | ||
1984 | + .class_init = xlnx_versal_ospi_class_init, | ||
1985 | + .instance_init = xlnx_versal_ospi_init, | ||
1986 | +}; | ||
1987 | + | ||
1988 | +static void xlnx_versal_ospi_register_types(void) | ||
1989 | +{ | ||
1990 | + type_register_static(&xlnx_versal_ospi_info); | ||
1991 | +} | ||
1992 | + | ||
1993 | +type_init(xlnx_versal_ospi_register_types) | ||
1994 | diff --git a/hw/ssi/meson.build b/hw/ssi/meson.build | ||
1995 | index XXXXXXX..XXXXXXX 100644 | ||
1996 | --- a/hw/ssi/meson.build | ||
1997 | +++ b/hw/ssi/meson.build | ||
1998 | @@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_SSI', if_true: files('ssi.c')) | ||
1999 | softmmu_ss.add(when: 'CONFIG_STM32F2XX_SPI', if_true: files('stm32f2xx_spi.c')) | ||
2000 | softmmu_ss.add(when: 'CONFIG_XILINX_SPI', if_true: files('xilinx_spi.c')) | ||
2001 | softmmu_ss.add(when: 'CONFIG_XILINX_SPIPS', if_true: files('xilinx_spips.c')) | ||
2002 | +softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-ospi.c')) | ||
2003 | softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_spi.c')) | ||
2004 | softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_spi.c')) | ||
2005 | -- | ||
2006 | 2.25.1 | ||
2007 | |||
2008 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
1 | 2 | ||
3 | Connect the OSPI flash memory controller model (including the source and | ||
4 | destination DMA). | ||
5 | |||
6 | Signed-off-by: Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
7 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
8 | Message-id: 20220121161141.14389-8-francisco.iglesias@xilinx.com | ||
9 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
10 | --- | ||
11 | include/hw/arm/xlnx-versal.h | 20 ++++++++ | ||
12 | hw/arm/xlnx-versal.c | 93 ++++++++++++++++++++++++++++++++++++ | ||
13 | 2 files changed, 113 insertions(+) | ||
14 | |||
15 | diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/include/hw/arm/xlnx-versal.h | ||
18 | +++ b/include/hw/arm/xlnx-versal.h | ||
19 | @@ -XXX,XX +XXX,XX @@ | ||
20 | #include "hw/misc/xlnx-versal-xramc.h" | ||
21 | #include "hw/nvram/xlnx-bbram.h" | ||
22 | #include "hw/nvram/xlnx-versal-efuse.h" | ||
23 | +#include "hw/ssi/xlnx-versal-ospi.h" | ||
24 | +#include "hw/dma/xlnx_csu_dma.h" | ||
25 | #include "hw/misc/xlnx-versal-pmc-iou-slcr.h" | ||
26 | |||
27 | #define TYPE_XLNX_VERSAL "xlnx-versal" | ||
28 | @@ -XXX,XX +XXX,XX @@ struct Versal { | ||
29 | struct { | ||
30 | SDHCIState sd[XLNX_VERSAL_NR_SDS]; | ||
31 | XlnxVersalPmcIouSlcr slcr; | ||
32 | + | ||
33 | + struct { | ||
34 | + XlnxVersalOspi ospi; | ||
35 | + XlnxCSUDMA dma_src; | ||
36 | + XlnxCSUDMA dma_dst; | ||
37 | + MemoryRegion linear_mr; | ||
38 | + qemu_or_irq irq_orgate; | ||
39 | + } ospi; | ||
40 | } iou; | ||
41 | |||
42 | XlnxZynqMPRTC rtc; | ||
43 | @@ -XXX,XX +XXX,XX @@ struct Versal { | ||
44 | #define VERSAL_ADMA_IRQ_0 60 | ||
45 | #define VERSAL_XRAM_IRQ_0 79 | ||
46 | #define VERSAL_PMC_APB_IRQ 121 | ||
47 | +#define VERSAL_OSPI_IRQ 124 | ||
48 | #define VERSAL_SD0_IRQ_0 126 | ||
49 | #define VERSAL_EFUSE_IRQ 139 | ||
50 | #define VERSAL_RTC_ALARM_IRQ 142 | ||
51 | @@ -XXX,XX +XXX,XX @@ struct Versal { | ||
52 | #define MM_PMC_PMC_IOU_SLCR 0xf1060000 | ||
53 | #define MM_PMC_PMC_IOU_SLCR_SIZE 0x10000 | ||
54 | |||
55 | +#define MM_PMC_OSPI 0xf1010000 | ||
56 | +#define MM_PMC_OSPI_SIZE 0x10000 | ||
57 | + | ||
58 | +#define MM_PMC_OSPI_DAC 0xc0000000 | ||
59 | +#define MM_PMC_OSPI_DAC_SIZE 0x20000000 | ||
60 | + | ||
61 | +#define MM_PMC_OSPI_DMA_DST 0xf1011800 | ||
62 | +#define MM_PMC_OSPI_DMA_SRC 0xf1011000 | ||
63 | + | ||
64 | #define MM_PMC_SD0 0xf1040000U | ||
65 | #define MM_PMC_SD0_SIZE 0x10000 | ||
66 | #define MM_PMC_BBRAM_CTRL 0xf11f0000 | ||
67 | diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c | ||
68 | index XXXXXXX..XXXXXXX 100644 | ||
69 | --- a/hw/arm/xlnx-versal.c | ||
70 | +++ b/hw/arm/xlnx-versal.c | ||
71 | @@ -XXX,XX +XXX,XX @@ | ||
72 | #define GEM_REVISION 0x40070106 | ||
73 | |||
74 | #define VERSAL_NUM_PMC_APB_IRQS 3 | ||
75 | +#define NUM_OSPI_IRQ_LINES 3 | ||
76 | |||
77 | static void versal_create_apu_cpus(Versal *s) | ||
78 | { | ||
79 | @@ -XXX,XX +XXX,XX @@ static void versal_create_pmc_iou_slcr(Versal *s, qemu_irq *pic) | ||
80 | qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 2)); | ||
81 | } | ||
82 | |||
83 | +static void versal_create_ospi(Versal *s, qemu_irq *pic) | ||
84 | +{ | ||
85 | + SysBusDevice *sbd; | ||
86 | + MemoryRegion *mr_dac; | ||
87 | + qemu_irq ospi_mux_sel; | ||
88 | + DeviceState *orgate; | ||
89 | + | ||
90 | + memory_region_init(&s->pmc.iou.ospi.linear_mr, OBJECT(s), | ||
91 | + "versal-ospi-linear-mr" , MM_PMC_OSPI_DAC_SIZE); | ||
92 | + | ||
93 | + object_initialize_child(OBJECT(s), "versal-ospi", &s->pmc.iou.ospi.ospi, | ||
94 | + TYPE_XILINX_VERSAL_OSPI); | ||
95 | + | ||
96 | + mr_dac = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi), 1); | ||
97 | + memory_region_add_subregion(&s->pmc.iou.ospi.linear_mr, 0x0, mr_dac); | ||
98 | + | ||
99 | + /* Create the OSPI destination DMA */ | ||
100 | + object_initialize_child(OBJECT(s), "versal-ospi-dma-dst", | ||
101 | + &s->pmc.iou.ospi.dma_dst, | ||
102 | + TYPE_XLNX_CSU_DMA); | ||
103 | + | ||
104 | + object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_dst), | ||
105 | + "dma", OBJECT(get_system_memory()), | ||
106 | + &error_abort); | ||
107 | + | ||
108 | + sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_dst); | ||
109 | + sysbus_realize(sbd, &error_fatal); | ||
110 | + | ||
111 | + memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DMA_DST, | ||
112 | + sysbus_mmio_get_region(sbd, 0)); | ||
113 | + | ||
114 | + /* Create the OSPI source DMA */ | ||
115 | + object_initialize_child(OBJECT(s), "versal-ospi-dma-src", | ||
116 | + &s->pmc.iou.ospi.dma_src, | ||
117 | + TYPE_XLNX_CSU_DMA); | ||
118 | + | ||
119 | + object_property_set_bool(OBJECT(&s->pmc.iou.ospi.dma_src), "is-dst", | ||
120 | + false, &error_abort); | ||
121 | + | ||
122 | + object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_src), | ||
123 | + "dma", OBJECT(mr_dac), &error_abort); | ||
124 | + | ||
125 | + object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_src), | ||
126 | + "stream-connected-dma", | ||
127 | + OBJECT(&s->pmc.iou.ospi.dma_dst), | ||
128 | + &error_abort); | ||
129 | + | ||
130 | + sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_src); | ||
131 | + sysbus_realize(sbd, &error_fatal); | ||
132 | + | ||
133 | + memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DMA_SRC, | ||
134 | + sysbus_mmio_get_region(sbd, 0)); | ||
135 | + | ||
136 | + /* Realize the OSPI */ | ||
137 | + object_property_set_link(OBJECT(&s->pmc.iou.ospi.ospi), "dma-src", | ||
138 | + OBJECT(&s->pmc.iou.ospi.dma_src), &error_abort); | ||
139 | + | ||
140 | + sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi); | ||
141 | + sysbus_realize(sbd, &error_fatal); | ||
142 | + | ||
143 | + memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI, | ||
144 | + sysbus_mmio_get_region(sbd, 0)); | ||
145 | + | ||
146 | + memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DAC, | ||
147 | + &s->pmc.iou.ospi.linear_mr); | ||
148 | + | ||
149 | + /* ospi_mux_sel */ | ||
150 | + ospi_mux_sel = qdev_get_gpio_in_named(DEVICE(&s->pmc.iou.ospi.ospi), | ||
151 | + "ospi-mux-sel", 0); | ||
152 | + qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), "ospi-mux-sel", 0, | ||
153 | + ospi_mux_sel); | ||
154 | + | ||
155 | + /* OSPI irq */ | ||
156 | + object_initialize_child(OBJECT(s), "ospi-irq-orgate", | ||
157 | + &s->pmc.iou.ospi.irq_orgate, TYPE_OR_IRQ); | ||
158 | + object_property_set_int(OBJECT(&s->pmc.iou.ospi.irq_orgate), | ||
159 | + "num-lines", NUM_OSPI_IRQ_LINES, &error_fatal); | ||
160 | + | ||
161 | + orgate = DEVICE(&s->pmc.iou.ospi.irq_orgate); | ||
162 | + qdev_realize(orgate, NULL, &error_fatal); | ||
163 | + | ||
164 | + sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi), 0, | ||
165 | + qdev_get_gpio_in(orgate, 0)); | ||
166 | + sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_src), 0, | ||
167 | + qdev_get_gpio_in(orgate, 1)); | ||
168 | + sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_dst), 0, | ||
169 | + qdev_get_gpio_in(orgate, 2)); | ||
170 | + | ||
171 | + qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]); | ||
172 | +} | ||
173 | + | ||
174 | /* This takes the board allocated linear DDR memory and creates aliases | ||
175 | * for each split DDR range/aperture on the Versal address map. | ||
176 | */ | ||
177 | @@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp) | ||
178 | versal_create_bbram(s, pic); | ||
179 | versal_create_efuse(s, pic); | ||
180 | versal_create_pmc_iou_slcr(s, pic); | ||
181 | + versal_create_ospi(s, pic); | ||
182 | versal_map_ddr(s); | ||
183 | versal_unimp(s); | ||
184 | |||
185 | -- | ||
186 | 2.25.1 | ||
187 | |||
188 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
1 | 2 | ||
3 | Add support for Micron Xccela flash mt35xu01g. | ||
4 | |||
5 | Signed-off-by: Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
6 | Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
7 | Message-id: 20220121161141.14389-9-francisco.iglesias@xilinx.com | ||
8 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
9 | --- | ||
10 | hw/block/m25p80.c | 2 ++ | ||
11 | 1 file changed, 2 insertions(+) | ||
12 | |||
13 | diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/hw/block/m25p80.c | ||
16 | +++ b/hw/block/m25p80.c | ||
17 | @@ -XXX,XX +XXX,XX @@ static const FlashPartInfo known_devices[] = { | ||
18 | { INFO("n25q512a", 0x20ba20, 0, 64 << 10, 1024, ER_4K) }, | ||
19 | { INFO("n25q512ax3", 0x20ba20, 0x1000, 64 << 10, 1024, ER_4K) }, | ||
20 | { INFO("mt25ql512ab", 0x20ba20, 0x1044, 64 << 10, 1024, ER_4K | ER_32K) }, | ||
21 | + { INFO_STACKED("mt35xu01g", 0x2c5b1b, 0x104100, 128 << 10, 1024, | ||
22 | + ER_4K | ER_32K, 2) }, | ||
23 | { INFO_STACKED("n25q00", 0x20ba21, 0x1000, 64 << 10, 2048, ER_4K, 4) }, | ||
24 | { INFO_STACKED("n25q00a", 0x20bb21, 0x1000, 64 << 10, 2048, ER_4K, 4) }, | ||
25 | { INFO_STACKED("mt25ql01g", 0x20ba21, 0x1040, 64 << 10, 2048, ER_4K, 2) }, | ||
26 | -- | ||
27 | 2.25.1 | ||
28 | |||
29 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
1 | 2 | ||
3 | Connect Micron Xccela mt35xu01g flashes to the OSPI flash memory | ||
4 | controller. | ||
5 | |||
6 | Signed-off-by: Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
7 | Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
8 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
9 | Message-id: 20220121161141.14389-10-francisco.iglesias@xilinx.com | ||
10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
11 | --- | ||
12 | hw/arm/xlnx-versal-virt.c | 23 +++++++++++++++++++++++ | ||
13 | 1 file changed, 23 insertions(+) | ||
14 | |||
15 | diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/hw/arm/xlnx-versal-virt.c | ||
18 | +++ b/hw/arm/xlnx-versal-virt.c | ||
19 | @@ -XXX,XX +XXX,XX @@ | ||
20 | #define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("xlnx-versal-virt") | ||
21 | OBJECT_DECLARE_SIMPLE_TYPE(VersalVirt, XLNX_VERSAL_VIRT_MACHINE) | ||
22 | |||
23 | +#define XLNX_VERSAL_NUM_OSPI_FLASH 4 | ||
24 | + | ||
25 | struct VersalVirt { | ||
26 | MachineState parent_obj; | ||
27 | |||
28 | @@ -XXX,XX +XXX,XX @@ static void versal_virt_init(MachineState *machine) | ||
29 | exit(EXIT_FAILURE); | ||
30 | } | ||
31 | } | ||
32 | + | ||
33 | + for (i = 0; i < XLNX_VERSAL_NUM_OSPI_FLASH; i++) { | ||
34 | + BusState *spi_bus; | ||
35 | + DeviceState *flash_dev; | ||
36 | + qemu_irq cs_line; | ||
37 | + DriveInfo *dinfo = drive_get(IF_MTD, 0, i); | ||
38 | + | ||
39 | + spi_bus = qdev_get_child_bus(DEVICE(&s->soc.pmc.iou.ospi), "spi0"); | ||
40 | + | ||
41 | + flash_dev = qdev_new("mt35xu01g"); | ||
42 | + if (dinfo) { | ||
43 | + qdev_prop_set_drive_err(flash_dev, "drive", | ||
44 | + blk_by_legacy_dinfo(dinfo), &error_fatal); | ||
45 | + } | ||
46 | + qdev_realize_and_unref(flash_dev, spi_bus, &error_fatal); | ||
47 | + | ||
48 | + cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0); | ||
49 | + | ||
50 | + sysbus_connect_irq(SYS_BUS_DEVICE(&s->soc.pmc.iou.ospi), | ||
51 | + i + 1, cs_line); | ||
52 | + } | ||
53 | } | ||
54 | |||
55 | static void versal_virt_machine_instance_init(Object *obj) | ||
56 | -- | ||
57 | 2.25.1 | ||
58 | |||
59 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
1 | 2 | ||
3 | List myself as maintainer for the Xilinx Versal OSPI controller. | ||
4 | |||
5 | Signed-off-by: Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
6 | Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
7 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
8 | Message-id: 20220121161141.14389-11-francisco.iglesias@xilinx.com | ||
9 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
10 | --- | ||
11 | MAINTAINERS | 6 ++++++ | ||
12 | 1 file changed, 6 insertions(+) | ||
13 | |||
14 | diff --git a/MAINTAINERS b/MAINTAINERS | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/MAINTAINERS | ||
17 | +++ b/MAINTAINERS | ||
18 | @@ -XXX,XX +XXX,XX @@ F: hw/display/dpcd.c | ||
19 | F: include/hw/display/dpcd.h | ||
20 | F: docs/system/arm/xlnx-versal-virt.rst | ||
21 | |||
22 | +Xilinx Versal OSPI | ||
23 | +M: Francisco Iglesias <francisco.iglesias@xilinx.com> | ||
24 | +S: Maintained | ||
25 | +F: hw/ssi/xlnx-versal-ospi.c | ||
26 | +F: include/hw/ssi/xlnx-versal-ospi.h | ||
27 | + | ||
28 | ARM ACPI Subsystem | ||
29 | M: Shannon Zhao <shannon.zhaosl@gmail.com> | ||
30 | L: qemu-arm@nongnu.org | ||
31 | -- | ||
32 | 2.25.1 | ||
33 | |||
34 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Andrew Baumann <Andrew.Baumann@microsoft.com> | ||
1 | 2 | ||
3 | Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com> | ||
4 | Message-id: MW4PR21MB1940E8BB52F4053C943B1FCD9E219@MW4PR21MB1940.namprd21.prod.outlook.com | ||
5 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
6 | --- | ||
7 | MAINTAINERS | 1 - | ||
8 | 1 file changed, 1 deletion(-) | ||
9 | |||
10 | diff --git a/MAINTAINERS b/MAINTAINERS | ||
11 | index XXXXXXX..XXXXXXX 100644 | ||
12 | --- a/MAINTAINERS | ||
13 | +++ b/MAINTAINERS | ||
14 | @@ -XXX,XX +XXX,XX @@ F: docs/system/arm/palm.rst | ||
15 | |||
16 | Raspberry Pi | ||
17 | M: Peter Maydell <peter.maydell@linaro.org> | ||
18 | -R: Andrew Baumann <Andrew.Baumann@microsoft.com> | ||
19 | R: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
20 | L: qemu-arm@nongnu.org | ||
21 | S: Odd Fixes | ||
22 | -- | ||
23 | 2.25.1 | ||
24 | |||
25 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | If you don't know it, it's hard to figure out the difference between | ||
2 | the linux-headers folder and the include/standard-headers folder. | ||
3 | So let's add a short explanation to clarify the difference. | ||
1 | 4 | ||
5 | Suggested-by: Thomas Huth <thuth@redhat.com> | ||
6 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
7 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
8 | Reviewed-by: Cornelia Huck <cohuck@redhat.com> | ||
9 | Reviewed-by: Thomas Huth <thuth@redhat.com> | ||
10 | --- | ||
11 | scripts/update-linux-headers.sh | 16 ++++++++++++++++ | ||
12 | 1 file changed, 16 insertions(+) | ||
13 | |||
14 | diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh | ||
15 | index XXXXXXX..XXXXXXX 100755 | ||
16 | --- a/scripts/update-linux-headers.sh | ||
17 | +++ b/scripts/update-linux-headers.sh | ||
18 | @@ -XXX,XX +XXX,XX @@ | ||
19 | # | ||
20 | # This work is licensed under the terms of the GNU GPL version 2. | ||
21 | # See the COPYING file in the top-level directory. | ||
22 | +# | ||
23 | +# The script will copy the headers into two target folders: | ||
24 | +# | ||
25 | +# - linux-headers/ for files that are required for compiling for a | ||
26 | +# Linux host. Generally we have these so we can use kernel structs | ||
27 | +# and defines that are more recent than the headers that might be | ||
28 | +# installed on the host system. Usually this script can do simple | ||
29 | +# file copies for these headers. | ||
30 | +# | ||
31 | +# - include/standard-headers/ for files that are used for guest | ||
32 | +# device emulation and are required on all hosts. For instance, we | ||
33 | +# get our definitions of the virtio structures from the Linux | ||
34 | +# kernel headers, but we need those definitions regardless of which | ||
35 | +# host OS we are building for. This script has to be careful to | ||
36 | +# sanitize the headers to remove any use of Linux-specifics such as | ||
37 | +# types like "__u64". This work is done in the cp_portable function. | ||
38 | |||
39 | tmpdir=$(mktemp -d) | ||
40 | linux="$1" | ||
41 | -- | ||
42 | 2.25.1 | ||
43 | |||
44 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | In an SMP system it can be unclear which CPU is taking an exception; | ||
2 | add the CPU index (which is the same value used in the TCG 'Trace | ||
3 | %d:' logging) to the "Taking exception" log line to clarify it. | ||
1 | 4 | ||
5 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
6 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
7 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
8 | Message-id: 20220122182444.724087-2-peter.maydell@linaro.org | ||
9 | --- | ||
10 | target/arm/internals.h | 2 +- | ||
11 | target/arm/helper.c | 9 ++++++--- | ||
12 | target/arm/m_helper.c | 2 +- | ||
13 | 3 files changed, 8 insertions(+), 5 deletions(-) | ||
14 | |||
15 | diff --git a/target/arm/internals.h b/target/arm/internals.h | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/target/arm/internals.h | ||
18 | +++ b/target/arm/internals.h | ||
19 | @@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, target_ulong address, | ||
20 | ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs) | ||
21 | __attribute__((nonnull)); | ||
22 | |||
23 | -void arm_log_exception(int idx); | ||
24 | +void arm_log_exception(CPUState *cs); | ||
25 | |||
26 | #endif /* !CONFIG_USER_ONLY */ | ||
27 | |||
28 | diff --git a/target/arm/helper.c b/target/arm/helper.c | ||
29 | index XXXXXXX..XXXXXXX 100644 | ||
30 | --- a/target/arm/helper.c | ||
31 | +++ b/target/arm/helper.c | ||
32 | @@ -XXX,XX +XXX,XX @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx, | ||
33 | return target_el; | ||
34 | } | ||
35 | |||
36 | -void arm_log_exception(int idx) | ||
37 | +void arm_log_exception(CPUState *cs) | ||
38 | { | ||
39 | + int idx = cs->exception_index; | ||
40 | + | ||
41 | if (qemu_loglevel_mask(CPU_LOG_INT)) { | ||
42 | const char *exc = NULL; | ||
43 | static const char * const excnames[] = { | ||
44 | @@ -XXX,XX +XXX,XX @@ void arm_log_exception(int idx) | ||
45 | if (!exc) { | ||
46 | exc = "unknown"; | ||
47 | } | ||
48 | - qemu_log_mask(CPU_LOG_INT, "Taking exception %d [%s]\n", idx, exc); | ||
49 | + qemu_log_mask(CPU_LOG_INT, "Taking exception %d [%s] on CPU %d\n", | ||
50 | + idx, exc, cs->cpu_index); | ||
51 | } | ||
52 | } | ||
53 | |||
54 | @@ -XXX,XX +XXX,XX @@ void arm_cpu_do_interrupt(CPUState *cs) | ||
55 | |||
56 | assert(!arm_feature(env, ARM_FEATURE_M)); | ||
57 | |||
58 | - arm_log_exception(cs->exception_index); | ||
59 | + arm_log_exception(cs); | ||
60 | qemu_log_mask(CPU_LOG_INT, "...from EL%d to EL%d\n", arm_current_el(env), | ||
61 | new_el); | ||
62 | if (qemu_loglevel_mask(CPU_LOG_INT) | ||
63 | diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c | ||
64 | index XXXXXXX..XXXXXXX 100644 | ||
65 | --- a/target/arm/m_helper.c | ||
66 | +++ b/target/arm/m_helper.c | ||
67 | @@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) | ||
68 | uint32_t lr; | ||
69 | bool ignore_stackfaults; | ||
70 | |||
71 | - arm_log_exception(cs->exception_index); | ||
72 | + arm_log_exception(cs); | ||
73 | |||
74 | /* | ||
75 | * For exceptions we just mark as pending on the NVIC, and let that | ||
76 | -- | ||
77 | 2.25.1 | ||
78 | |||
79 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | The ITS currently has no tracepoints; add a minimal set | ||
2 | that allows basic monitoring of guest register accesses and | ||
3 | reading of commands from the command queue. | ||
1 | 4 | ||
5 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
6 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
7 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
8 | Message-id: 20220122182444.724087-3-peter.maydell@linaro.org | ||
9 | --- | ||
10 | hw/intc/arm_gicv3_its.c | 11 +++++++++++ | ||
11 | hw/intc/trace-events | 8 ++++++++ | ||
12 | 2 files changed, 19 insertions(+) | ||
13 | |||
14 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/hw/intc/arm_gicv3_its.c | ||
17 | +++ b/hw/intc/arm_gicv3_its.c | ||
18 | @@ -XXX,XX +XXX,XX @@ | ||
19 | |||
20 | #include "qemu/osdep.h" | ||
21 | #include "qemu/log.h" | ||
22 | +#include "trace.h" | ||
23 | #include "hw/qdev-properties.h" | ||
24 | #include "hw/intc/arm_gicv3_its_common.h" | ||
25 | #include "gicv3_internal.h" | ||
26 | @@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s) | ||
27 | |||
28 | cmd = (data & CMD_MASK); | ||
29 | |||
30 | + trace_gicv3_its_process_command(rd_offset, cmd); | ||
31 | + | ||
32 | switch (cmd) { | ||
33 | case GITS_CMD_INT: | ||
34 | result = process_its_cmd(s, data, cq_offset, INTERRUPT); | ||
35 | @@ -XXX,XX +XXX,XX @@ static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset, | ||
36 | bool result = true; | ||
37 | uint32_t devid = 0; | ||
38 | |||
39 | + trace_gicv3_its_translation_write(offset, data, size, attrs.requester_id); | ||
40 | + | ||
41 | switch (offset) { | ||
42 | case GITS_TRANSLATER: | ||
43 | if (s->ctlr & R_GITS_CTLR_ENABLED_MASK) { | ||
44 | @@ -XXX,XX +XXX,XX @@ static MemTxResult gicv3_its_read(void *opaque, hwaddr offset, uint64_t *data, | ||
45 | qemu_log_mask(LOG_GUEST_ERROR, | ||
46 | "%s: invalid guest read at offset " TARGET_FMT_plx | ||
47 | "size %u\n", __func__, offset, size); | ||
48 | + trace_gicv3_its_badread(offset, size); | ||
49 | /* | ||
50 | * The spec requires that reserved registers are RAZ/WI; | ||
51 | * so use false returns from leaf functions as a way to | ||
52 | @@ -XXX,XX +XXX,XX @@ static MemTxResult gicv3_its_read(void *opaque, hwaddr offset, uint64_t *data, | ||
53 | * the caller, or we'll cause a spurious guest data abort. | ||
54 | */ | ||
55 | *data = 0; | ||
56 | + } else { | ||
57 | + trace_gicv3_its_read(offset, *data, size); | ||
58 | } | ||
59 | return MEMTX_OK; | ||
60 | } | ||
61 | @@ -XXX,XX +XXX,XX @@ static MemTxResult gicv3_its_write(void *opaque, hwaddr offset, uint64_t data, | ||
62 | qemu_log_mask(LOG_GUEST_ERROR, | ||
63 | "%s: invalid guest write at offset " TARGET_FMT_plx | ||
64 | "size %u\n", __func__, offset, size); | ||
65 | + trace_gicv3_its_badwrite(offset, data, size); | ||
66 | /* | ||
67 | * The spec requires that reserved registers are RAZ/WI; | ||
68 | * so use false returns from leaf functions as a way to | ||
69 | * trigger the guest-error logging but don't return it to | ||
70 | * the caller, or we'll cause a spurious guest data abort. | ||
71 | */ | ||
72 | + } else { | ||
73 | + trace_gicv3_its_write(offset, data, size); | ||
74 | } | ||
75 | return MEMTX_OK; | ||
76 | } | ||
77 | diff --git a/hw/intc/trace-events b/hw/intc/trace-events | ||
78 | index XXXXXXX..XXXXXXX 100644 | ||
79 | --- a/hw/intc/trace-events | ||
80 | +++ b/hw/intc/trace-events | ||
81 | @@ -XXX,XX +XXX,XX @@ gicv3_redist_badwrite(uint32_t cpu, uint64_t offset, uint64_t data, unsigned siz | ||
82 | gicv3_redist_set_irq(uint32_t cpu, int irq, int level) "GICv3 redistributor 0x%x interrupt %d level changed to %d" | ||
83 | gicv3_redist_send_sgi(uint32_t cpu, int irq) "GICv3 redistributor 0x%x pending SGI %d" | ||
84 | |||
85 | +# arm_gicv3_its.c | ||
86 | +gicv3_its_read(uint64_t offset, uint64_t data, unsigned size) "GICv3 ITS read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" | ||
87 | +gicv3_its_badread(uint64_t offset, unsigned size) "GICv3 ITS read: offset 0x%" PRIx64 " size %u: error" | ||
88 | +gicv3_its_write(uint64_t offset, uint64_t data, unsigned size) "GICv3 ITS write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" | ||
89 | +gicv3_its_badwrite(uint64_t offset, uint64_t data, unsigned size) "GICv3 ITS write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u: error" | ||
90 | +gicv3_its_translation_write(uint64_t offset, uint64_t data, unsigned size, uint32_t requester_id) "GICv3 ITS TRANSLATER write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u requester_id 0x%x" | ||
91 | +gicv3_its_process_command(uint32_t rd_offset, uint8_t cmd) "GICv3 ITS: processing command at offset 0x%x: 0x%x" | ||
92 | + | ||
93 | # armv7m_nvic.c | ||
94 | nvic_recompute_state(int vectpending, int vectpending_prio, int exception_prio) "NVIC state recomputed: vectpending %d vectpending_prio %d exception_prio %d" | ||
95 | nvic_recompute_state_secure(int vectpending, bool vectpending_is_s_banked, int vectpending_prio, int exception_prio) "NVIC state recomputed: vectpending %d is_s_banked %d vectpending_prio %d exception_prio %d" | ||
96 | -- | ||
97 | 2.25.1 | ||
98 | |||
99 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | In our implementation, all ITSes connected to a GIC share a single | ||
2 | AddressSpace, which we keep in the GICv3State::dma_as field and | ||
3 | initialized based on the GIC's 'sysmem' property. The right place | ||
4 | to set it up by calling address_space_init() is therefore in the | ||
5 | GIC's realize method, not the ITS's realize. | ||
1 | 6 | ||
7 | This fixes a theoretical bug where QEMU hangs on startup if the board | ||
8 | model creates two ITSes connected to the same GIC -- we would call | ||
9 | address_space_init() twice on the same AddressSpace*, which creates | ||
10 | an infinite loop in the QTAILQ that softmmu/memory.c uses to store | ||
11 | its list of AddressSpaces and causes any subsequent attempt to | ||
12 | iterate through that list to loop forever. There aren't any board | ||
13 | models like that in the tree at the moment, though. | ||
14 | |||
15 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
16 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
17 | Message-id: 20220122182444.724087-4-peter.maydell@linaro.org | ||
18 | --- | ||
19 | hw/intc/arm_gicv3_common.c | 5 +++++ | ||
20 | hw/intc/arm_gicv3_its.c | 3 --- | ||
21 | 2 files changed, 5 insertions(+), 3 deletions(-) | ||
22 | |||
23 | diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c | ||
24 | index XXXXXXX..XXXXXXX 100644 | ||
25 | --- a/hw/intc/arm_gicv3_common.c | ||
26 | +++ b/hw/intc/arm_gicv3_common.c | ||
27 | @@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) | ||
28 | return; | ||
29 | } | ||
30 | |||
31 | + if (s->lpi_enable) { | ||
32 | + address_space_init(&s->dma_as, s->dma, | ||
33 | + "gicv3-its-sysmem"); | ||
34 | + } | ||
35 | + | ||
36 | s->cpu = g_new0(GICv3CPUState, s->num_cpu); | ||
37 | |||
38 | for (i = 0; i < s->num_cpu; i++) { | ||
39 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c | ||
40 | index XXXXXXX..XXXXXXX 100644 | ||
41 | --- a/hw/intc/arm_gicv3_its.c | ||
42 | +++ b/hw/intc/arm_gicv3_its.c | ||
43 | @@ -XXX,XX +XXX,XX @@ static void gicv3_arm_its_realize(DeviceState *dev, Error **errp) | ||
44 | |||
45 | gicv3_its_init_mmio(s, &gicv3_its_control_ops, &gicv3_its_translation_ops); | ||
46 | |||
47 | - address_space_init(&s->gicv3->dma_as, s->gicv3->dma, | ||
48 | - "gicv3-its-sysmem"); | ||
49 | - | ||
50 | /* set the ITS default features supported */ | ||
51 | s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL, 1); | ||
52 | s->typer = FIELD_DP64(s->typer, GITS_TYPER, ITT_ENTRY_SIZE, | ||
53 | -- | ||
54 | 2.25.1 | ||
55 | |||
56 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | The current ITS code clears GITS_CREADR when GITS_CTLR.ENABLED is set. | ||
2 | This is not correct -- guest code can validly clear ENABLED and then | ||
3 | set it again and expect the ITS to continue processing where it left | ||
4 | off. Remove the erroneous assignment. | ||
1 | 5 | ||
6 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
7 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
8 | Message-id: 20220122182444.724087-5-peter.maydell@linaro.org | ||
9 | --- | ||
10 | hw/intc/arm_gicv3_its.c | 1 - | ||
11 | 1 file changed, 1 deletion(-) | ||
12 | |||
13 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/hw/intc/arm_gicv3_its.c | ||
16 | +++ b/hw/intc/arm_gicv3_its.c | ||
17 | @@ -XXX,XX +XXX,XX @@ static bool its_writel(GICv3ITSState *s, hwaddr offset, | ||
18 | s->ctlr |= R_GITS_CTLR_ENABLED_MASK; | ||
19 | extract_table_params(s); | ||
20 | extract_cmdq_params(s); | ||
21 | - s->creadr = 0; | ||
22 | process_cmdq(s); | ||
23 | } else { | ||
24 | s->ctlr &= ~R_GITS_CTLR_ENABLED_MASK; | ||
25 | -- | ||
26 | 2.25.1 | ||
27 | |||
28 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | The ITS specification says that when the guest writes to GITS_CBASER | ||
2 | this causes GITS_CREADR to be cleared. However it does not have an | ||
3 | equivalent clause for GITS_CWRITER. (This is because GITS_CREADR is | ||
4 | read-only, but GITS_CWRITER is writable and the guest can initialize | ||
5 | it.) Remove the code that clears GITS_CWRITER on GITS_CBASER writes. | ||
1 | 6 | ||
7 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
8 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
9 | Message-id: 20220122182444.724087-6-peter.maydell@linaro.org | ||
10 | --- | ||
11 | hw/intc/arm_gicv3_its.c | 3 --- | ||
12 | 1 file changed, 3 deletions(-) | ||
13 | |||
14 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/hw/intc/arm_gicv3_its.c | ||
17 | +++ b/hw/intc/arm_gicv3_its.c | ||
18 | @@ -XXX,XX +XXX,XX @@ static bool its_writel(GICv3ITSState *s, hwaddr offset, | ||
19 | if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) { | ||
20 | s->cbaser = deposit64(s->cbaser, 0, 32, value); | ||
21 | s->creadr = 0; | ||
22 | - s->cwriter = s->creadr; | ||
23 | } | ||
24 | break; | ||
25 | case GITS_CBASER + 4: | ||
26 | @@ -XXX,XX +XXX,XX @@ static bool its_writel(GICv3ITSState *s, hwaddr offset, | ||
27 | if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) { | ||
28 | s->cbaser = deposit64(s->cbaser, 32, 32, value); | ||
29 | s->creadr = 0; | ||
30 | - s->cwriter = s->creadr; | ||
31 | } | ||
32 | break; | ||
33 | case GITS_CWRITER: | ||
34 | @@ -XXX,XX +XXX,XX @@ static bool its_writell(GICv3ITSState *s, hwaddr offset, | ||
35 | if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) { | ||
36 | s->cbaser = value; | ||
37 | s->creadr = 0; | ||
38 | - s->cwriter = s->creadr; | ||
39 | } | ||
40 | break; | ||
41 | case GITS_CWRITER: | ||
42 | -- | ||
43 | 2.25.1 | ||
44 | |||
45 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | The GICD_CTLR distributor register has enable bits which control | ||
2 | whether the different interrupt groups (Group 0, Non-secure Group 1 | ||
3 | and Secure Group 1) are forwarded to the CPU. We get this right for | ||
4 | traditional interrupts, but forgot to account for it when adding | ||
5 | LPIs. LPIs are always Group 1 NS and if the EnableGrp1NS bit is not | ||
6 | set we must not forward them to the CPU. | ||
1 | 7 | ||
8 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
9 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
10 | Message-id: 20220122182444.724087-7-peter.maydell@linaro.org | ||
11 | --- | ||
12 | hw/intc/arm_gicv3.c | 1 + | ||
13 | 1 file changed, 1 insertion(+) | ||
14 | |||
15 | diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/hw/intc/arm_gicv3.c | ||
18 | +++ b/hw/intc/arm_gicv3.c | ||
19 | @@ -XXX,XX +XXX,XX @@ static void gicv3_redist_update_noirqset(GICv3CPUState *cs) | ||
20 | } | ||
21 | |||
22 | if ((cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) && cs->gic->lpi_enable && | ||
23 | + (cs->gic->gicd_ctlr & GICD_CTLR_EN_GRP1NS) && | ||
24 | (cs->hpplpi.prio != 0xff)) { | ||
25 | if (irqbetter(cs, cs->hpplpi.irq, cs->hpplpi.prio)) { | ||
26 | cs->hppi.irq = cs->hpplpi.irq; | ||
27 | -- | ||
28 | 2.25.1 | ||
29 | |||
30 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | The list of #defines for the ITS command packet numbers is neither | ||
2 | in alphabetical nor numeric order. Sort it into numeric order. | ||
1 | 3 | ||
4 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
5 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
6 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
7 | Message-id: 20220122182444.724087-8-peter.maydell@linaro.org | ||
8 | --- | ||
9 | hw/intc/gicv3_internal.h | 10 +++++----- | ||
10 | 1 file changed, 5 insertions(+), 5 deletions(-) | ||
11 | |||
12 | diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h | ||
13 | index XXXXXXX..XXXXXXX 100644 | ||
14 | --- a/hw/intc/gicv3_internal.h | ||
15 | +++ b/hw/intc/gicv3_internal.h | ||
16 | @@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1) | ||
17 | #define CMD_MASK 0xff | ||
18 | |||
19 | /* ITS Commands */ | ||
20 | -#define GITS_CMD_CLEAR 0x04 | ||
21 | -#define GITS_CMD_DISCARD 0x0F | ||
22 | #define GITS_CMD_INT 0x03 | ||
23 | -#define GITS_CMD_MAPC 0x09 | ||
24 | +#define GITS_CMD_CLEAR 0x04 | ||
25 | +#define GITS_CMD_SYNC 0x05 | ||
26 | #define GITS_CMD_MAPD 0x08 | ||
27 | -#define GITS_CMD_MAPI 0x0B | ||
28 | +#define GITS_CMD_MAPC 0x09 | ||
29 | #define GITS_CMD_MAPTI 0x0A | ||
30 | +#define GITS_CMD_MAPI 0x0B | ||
31 | #define GITS_CMD_INV 0x0C | ||
32 | #define GITS_CMD_INVALL 0x0D | ||
33 | -#define GITS_CMD_SYNC 0x05 | ||
34 | +#define GITS_CMD_DISCARD 0x0F | ||
35 | |||
36 | /* MAPC command fields */ | ||
37 | #define ICID_LENGTH 16 | ||
38 | -- | ||
39 | 2.25.1 | ||
40 | |||
41 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | The ITS-related parts of the redistributor code make some checks for | ||
2 | whether registers like GICR_PROPBASER and GICR_PENDBASER are zero. | ||
3 | There is no requirement in the specification for treating zeroes in | ||
4 | these address registers specially -- they contain guest physical | ||
5 | addresses and it is entirely valid (if unusual) for the guest to | ||
6 | choose to put the tables they address at guest physical address zero. | ||
7 | We use these values only to calculate guest addresses, and attempts | ||
8 | by the guest to use a bad address will be handled by the | ||
9 | address_space_* functions which we use to do the loads and stores. | ||
1 | 10 | ||
11 | Remove the unnecessary checks. | ||
12 | |||
13 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
14 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
15 | Message-id: 20220122182444.724087-9-peter.maydell@linaro.org | ||
16 | --- | ||
17 | hw/intc/arm_gicv3_redist.c | 8 +++----- | ||
18 | 1 file changed, 3 insertions(+), 5 deletions(-) | ||
19 | |||
20 | diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c | ||
21 | index XXXXXXX..XXXXXXX 100644 | ||
22 | --- a/hw/intc/arm_gicv3_redist.c | ||
23 | +++ b/hw/intc/arm_gicv3_redist.c | ||
24 | @@ -XXX,XX +XXX,XX @@ void gicv3_redist_update_lpi_only(GICv3CPUState *cs) | ||
25 | idbits = MIN(FIELD_EX64(cs->gicr_propbaser, GICR_PROPBASER, IDBITS), | ||
26 | GICD_TYPER_IDBITS); | ||
27 | |||
28 | - if (!(cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) || !cs->gicr_propbaser || | ||
29 | - !cs->gicr_pendbaser) { | ||
30 | + if (!(cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS)) { | ||
31 | return; | ||
32 | } | ||
33 | |||
34 | @@ -XXX,XX +XXX,XX @@ void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level) | ||
35 | idbits = MIN(FIELD_EX64(cs->gicr_propbaser, GICR_PROPBASER, IDBITS), | ||
36 | GICD_TYPER_IDBITS); | ||
37 | |||
38 | - if (!(cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) || !cs->gicr_propbaser || | ||
39 | - !cs->gicr_pendbaser || (irq > (1ULL << (idbits + 1)) - 1) || | ||
40 | - irq < GICV3_LPI_INTID_START) { | ||
41 | + if (!(cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) || | ||
42 | + (irq > (1ULL << (idbits + 1)) - 1) || irq < GICV3_LPI_INTID_START) { | ||
43 | return; | ||
44 | } | ||
45 | |||
46 | -- | ||
47 | 2.25.1 | ||
48 | |||
49 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | The GICR_CTLR.CES bit is a read-only bit which is set to 1 to indicate | ||
2 | that the GICR_CTLR.EnableLPIs bit can be written to 0 to disable | ||
3 | LPIs (as opposed to allowing LPIs to be enabled but not subsequently | ||
4 | disabled). Our implementation permits this, so advertise it | ||
5 | by setting CES to 1. | ||
1 | 6 | ||
7 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
8 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
9 | Message-id: 20220122182444.724087-10-peter.maydell@linaro.org | ||
10 | --- | ||
11 | hw/intc/gicv3_internal.h | 1 + | ||
12 | hw/intc/arm_gicv3_common.c | 4 ++++ | ||
13 | 2 files changed, 5 insertions(+) | ||
14 | |||
15 | diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/hw/intc/gicv3_internal.h | ||
18 | +++ b/hw/intc/gicv3_internal.h | ||
19 | @@ -XXX,XX +XXX,XX @@ | ||
20 | #define GICR_NSACR (GICR_SGI_OFFSET + 0x0E00) | ||
21 | |||
22 | #define GICR_CTLR_ENABLE_LPIS (1U << 0) | ||
23 | +#define GICR_CTLR_CES (1U << 1) | ||
24 | #define GICR_CTLR_RWP (1U << 3) | ||
25 | #define GICR_CTLR_DPG0 (1U << 24) | ||
26 | #define GICR_CTLR_DPG1NS (1U << 25) | ||
27 | diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c | ||
28 | index XXXXXXX..XXXXXXX 100644 | ||
29 | --- a/hw/intc/arm_gicv3_common.c | ||
30 | +++ b/hw/intc/arm_gicv3_common.c | ||
31 | @@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_reset(DeviceState *dev) | ||
32 | |||
33 | cs->level = 0; | ||
34 | cs->gicr_ctlr = 0; | ||
35 | + if (s->lpi_enable) { | ||
36 | + /* Our implementation supports clearing GICR_CTLR.EnableLPIs */ | ||
37 | + cs->gicr_ctlr |= GICR_CTLR_CES; | ||
38 | + } | ||
39 | cs->gicr_statusr[GICV3_S] = 0; | ||
40 | cs->gicr_statusr[GICV3_NS] = 0; | ||
41 | cs->gicr_waker = GICR_WAKER_ProcessorSleep | GICR_WAKER_ChildrenAsleep; | ||
42 | -- | ||
43 | 2.25.1 | ||
44 | |||
45 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | The MemoryRegionOps gicv3_its_translation_ops currently provides only | ||
2 | a .write_with_attrs function, because the only register in this | ||
3 | region is the write-only GITS_TRANSLATER. However, if you don't | ||
4 | provide a read function and the guest tries reading from this memory | ||
5 | region, QEMU will crash because | ||
6 | memory_region_read_with_attrs_accessor() calls a NULL pointer. | ||
1 | 7 | ||
8 | Add a read function which always returns 0, to cover both bogus | ||
9 | attempts to read GITS_TRANSLATER and also reads from the rest of the | ||
10 | region, which is documented to be reserved, RES0. | ||
11 | |||
12 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
13 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
14 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
15 | Message-id: 20220122182444.724087-11-peter.maydell@linaro.org | ||
16 | --- | ||
17 | hw/intc/arm_gicv3_its.c | 13 +++++++++++++ | ||
18 | 1 file changed, 13 insertions(+) | ||
19 | |||
20 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c | ||
21 | index XXXXXXX..XXXXXXX 100644 | ||
22 | --- a/hw/intc/arm_gicv3_its.c | ||
23 | +++ b/hw/intc/arm_gicv3_its.c | ||
24 | @@ -XXX,XX +XXX,XX @@ static void extract_cmdq_params(GICv3ITSState *s) | ||
25 | } | ||
26 | } | ||
27 | |||
28 | +static MemTxResult gicv3_its_translation_read(void *opaque, hwaddr offset, | ||
29 | + uint64_t *data, unsigned size, | ||
30 | + MemTxAttrs attrs) | ||
31 | +{ | ||
32 | + /* | ||
33 | + * GITS_TRANSLATER is write-only, and all other addresses | ||
34 | + * in the interrupt translation space frame are RES0. | ||
35 | + */ | ||
36 | + *data = 0; | ||
37 | + return MEMTX_OK; | ||
38 | +} | ||
39 | + | ||
40 | static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset, | ||
41 | uint64_t data, unsigned size, | ||
42 | MemTxAttrs attrs) | ||
43 | @@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps gicv3_its_control_ops = { | ||
44 | }; | ||
45 | |||
46 | static const MemoryRegionOps gicv3_its_translation_ops = { | ||
47 | + .read_with_attrs = gicv3_its_translation_read, | ||
48 | .write_with_attrs = gicv3_its_translation_write, | ||
49 | .valid.min_access_size = 2, | ||
50 | .valid.max_access_size = 4, | ||
51 | -- | ||
52 | 2.25.1 | ||
53 | |||
54 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | The ITS has a bank of 8 GITS_BASER<n> registers, which allow the | ||
2 | guest to specify the base address of various data tables. Each | ||
3 | register has a read-only type field indicating which table it is for | ||
4 | and a read-write field where the guest can write in the base address | ||
5 | (among other things). We currently allow the guest to write the | ||
6 | writeable fields for all eight registers, even if the type field is 0 | ||
7 | indicating "Unimplemented". This means the guest can provoke QEMU | ||
8 | into asserting by writing an address into one of these unimplemented | ||
9 | base registers, which bypasses the "if (!value) continue" check in | ||
10 | extract_table_params() and lets us hit the assertion that the type | ||
11 | field is one of the permitted table types. | ||
1 | 12 | ||
13 | Prevent the assertion by not allowing the guest to write to the | ||
14 | unimplemented base registers. This means their value will remain 0 | ||
15 | and extract_table_params() will ignore them. | ||
16 | |||
17 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
18 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
19 | Message-id: 20220122182444.724087-12-peter.maydell@linaro.org | ||
20 | --- | ||
21 | hw/intc/arm_gicv3_its.c | 8 ++++++++ | ||
22 | 1 file changed, 8 insertions(+) | ||
23 | |||
24 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c | ||
25 | index XXXXXXX..XXXXXXX 100644 | ||
26 | --- a/hw/intc/arm_gicv3_its.c | ||
27 | +++ b/hw/intc/arm_gicv3_its.c | ||
28 | @@ -XXX,XX +XXX,XX @@ static bool its_writel(GICv3ITSState *s, hwaddr offset, | ||
29 | if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) { | ||
30 | index = (offset - GITS_BASER) / 8; | ||
31 | |||
32 | + if (s->baser[index] == 0) { | ||
33 | + /* Unimplemented GITS_BASERn: RAZ/WI */ | ||
34 | + break; | ||
35 | + } | ||
36 | if (offset & 7) { | ||
37 | value <<= 32; | ||
38 | value &= ~GITS_BASER_RO_MASK; | ||
39 | @@ -XXX,XX +XXX,XX @@ static bool its_writell(GICv3ITSState *s, hwaddr offset, | ||
40 | */ | ||
41 | if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) { | ||
42 | index = (offset - GITS_BASER) / 8; | ||
43 | + if (s->baser[index] == 0) { | ||
44 | + /* Unimplemented GITS_BASERn: RAZ/WI */ | ||
45 | + break; | ||
46 | + } | ||
47 | s->baser[index] &= GITS_BASER_RO_MASK; | ||
48 | s->baser[index] |= (value & ~GITS_BASER_RO_MASK); | ||
49 | } | ||
50 | -- | ||
51 | 2.25.1 | ||
52 | |||
53 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | Currently when we fill in a TableDesc based on the value the guest | ||
2 | has written to the GITS_BASER<n> register, we calculate both: | ||
3 | * num_entries : the number of entries in the table, constrained | ||
4 | by the amount of memory the guest has given it | ||
5 | * num_ids : the number of IDs we support for this table, | ||
6 | constrained by the implementation choices and the architecture | ||
7 | (eg DeviceIDs are 16 bits, so num_ids is 1 << 16) | ||
1 | 8 | ||
9 | When validating ITS commands, however, we check only num_ids, | ||
10 | thus allowing a broken guest to specify table entries that | ||
11 | index off the end of it. This will only corrupt guest memory, | ||
12 | but the ITS is supposed to reject such commands as invalid. | ||
13 | |||
14 | Instead of calculating both num_entries and num_ids, set | ||
15 | num_entries to the minimum of the two limits, and check that. | ||
16 | |||
17 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
18 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
19 | Message-id: 20220122182444.724087-13-peter.maydell@linaro.org | ||
20 | --- | ||
21 | include/hw/intc/arm_gicv3_its_common.h | 1 - | ||
22 | hw/intc/arm_gicv3_its.c | 18 +++++++++--------- | ||
23 | 2 files changed, 9 insertions(+), 10 deletions(-) | ||
24 | |||
25 | diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h | ||
26 | index XXXXXXX..XXXXXXX 100644 | ||
27 | --- a/include/hw/intc/arm_gicv3_its_common.h | ||
28 | +++ b/include/hw/intc/arm_gicv3_its_common.h | ||
29 | @@ -XXX,XX +XXX,XX @@ typedef struct { | ||
30 | uint16_t entry_sz; | ||
31 | uint32_t page_sz; | ||
32 | uint32_t num_entries; | ||
33 | - uint32_t num_ids; | ||
34 | uint64_t base_addr; | ||
35 | } TableDesc; | ||
36 | |||
37 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c | ||
38 | index XXXXXXX..XXXXXXX 100644 | ||
39 | --- a/hw/intc/arm_gicv3_its.c | ||
40 | +++ b/hw/intc/arm_gicv3_its.c | ||
41 | @@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value, | ||
42 | |||
43 | eventid = (value & EVENTID_MASK); | ||
44 | |||
45 | - if (devid >= s->dt.num_ids) { | ||
46 | + if (devid >= s->dt.num_entries) { | ||
47 | qemu_log_mask(LOG_GUEST_ERROR, | ||
48 | "%s: invalid command attributes: devid %d>=%d", | ||
49 | - __func__, devid, s->dt.num_ids); | ||
50 | + __func__, devid, s->dt.num_entries); | ||
51 | return CMD_CONTINUE; | ||
52 | } | ||
53 | |||
54 | @@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value, | ||
55 | return CMD_CONTINUE; | ||
56 | } | ||
57 | |||
58 | - if (icid >= s->ct.num_ids) { | ||
59 | + if (icid >= s->ct.num_entries) { | ||
60 | qemu_log_mask(LOG_GUEST_ERROR, | ||
61 | "%s: invalid ICID 0x%x in ITE (table corrupted?)\n", | ||
62 | __func__, icid); | ||
63 | @@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value, | ||
64 | |||
65 | icid = value & ICID_MASK; | ||
66 | |||
67 | - if (devid >= s->dt.num_ids) { | ||
68 | + if (devid >= s->dt.num_entries) { | ||
69 | qemu_log_mask(LOG_GUEST_ERROR, | ||
70 | "%s: invalid command attributes: devid %d>=%d", | ||
71 | - __func__, devid, s->dt.num_ids); | ||
72 | + __func__, devid, s->dt.num_entries); | ||
73 | return CMD_CONTINUE; | ||
74 | } | ||
75 | |||
76 | @@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value, | ||
77 | num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1); | ||
78 | num_intids = 1ULL << (GICD_TYPER_IDBITS + 1); | ||
79 | |||
80 | - if ((icid >= s->ct.num_ids) | ||
81 | + if ((icid >= s->ct.num_entries) | ||
82 | || !dte_valid || (eventid >= num_eventids) || | ||
83 | (((pIntid < GICV3_LPI_INTID_START) || (pIntid >= num_intids)) && | ||
84 | (pIntid != INTID_SPURIOUS))) { | ||
85 | @@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapc(GICv3ITSState *s, uint32_t offset) | ||
86 | |||
87 | valid = (value & CMD_FIELD_VALID_MASK); | ||
88 | |||
89 | - if ((icid >= s->ct.num_ids) || (rdbase >= s->gicv3->num_cpu)) { | ||
90 | + if ((icid >= s->ct.num_entries) || (rdbase >= s->gicv3->num_cpu)) { | ||
91 | qemu_log_mask(LOG_GUEST_ERROR, | ||
92 | "ITS MAPC: invalid collection table attributes " | ||
93 | "icid %d rdbase %" PRIu64 "\n", icid, rdbase); | ||
94 | @@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapd(GICv3ITSState *s, uint64_t value, | ||
95 | |||
96 | valid = (value & CMD_FIELD_VALID_MASK); | ||
97 | |||
98 | - if ((devid >= s->dt.num_ids) || | ||
99 | + if ((devid >= s->dt.num_entries) || | ||
100 | (size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) { | ||
101 | qemu_log_mask(LOG_GUEST_ERROR, | ||
102 | "ITS MAPD: invalid device table attributes " | ||
103 | @@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s) | ||
104 | L1TABLE_ENTRY_SIZE) * | ||
105 | (page_sz / td->entry_sz)); | ||
106 | } | ||
107 | - td->num_ids = 1ULL << idbits; | ||
108 | + td->num_entries = MIN(td->num_entries, 1ULL << idbits); | ||
109 | } | ||
110 | } | ||
111 | |||
112 | -- | ||
113 | 2.25.1 | ||
114 | |||
115 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | Implement the ITS MOVALL command, which takes all the pending | ||
2 | interrupts on a source redistributor and makes the not-pending on | ||
3 | that source redistributor and pending on a destination redistributor. | ||
1 | 4 | ||
5 | This is a GICv3 ITS command which we forgot to implement. (It is | ||
6 | not used by Linux guests.) | ||
7 | |||
8 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
9 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
10 | Message-id: 20220122182444.724087-14-peter.maydell@linaro.org | ||
11 | --- | ||
12 | hw/intc/gicv3_internal.h | 16 +++++++++++ | ||
13 | hw/intc/arm_gicv3_its.c | 55 ++++++++++++++++++++++++++++++++++++++ | ||
14 | hw/intc/arm_gicv3_redist.c | 54 +++++++++++++++++++++++++++++++++++++ | ||
15 | 3 files changed, 125 insertions(+) | ||
16 | |||
17 | diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h | ||
18 | index XXXXXXX..XXXXXXX 100644 | ||
19 | --- a/hw/intc/gicv3_internal.h | ||
20 | +++ b/hw/intc/gicv3_internal.h | ||
21 | @@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1) | ||
22 | #define GITS_CMD_MAPI 0x0B | ||
23 | #define GITS_CMD_INV 0x0C | ||
24 | #define GITS_CMD_INVALL 0x0D | ||
25 | +#define GITS_CMD_MOVALL 0x0E | ||
26 | #define GITS_CMD_DISCARD 0x0F | ||
27 | |||
28 | /* MAPC command fields */ | ||
29 | @@ -XXX,XX +XXX,XX @@ FIELD(MAPC, RDBASE, 16, 32) | ||
30 | #define L2_TABLE_VALID_MASK CMD_FIELD_VALID_MASK | ||
31 | #define TABLE_ENTRY_VALID_MASK (1ULL << 0) | ||
32 | |||
33 | +/* MOVALL command fields */ | ||
34 | +FIELD(MOVALL_2, RDBASE1, 16, 36) | ||
35 | +FIELD(MOVALL_3, RDBASE2, 16, 36) | ||
36 | + | ||
37 | /* | ||
38 | * 12 bytes Interrupt translation Table Entry size | ||
39 | * as per Table 5.3 in GICv3 spec | ||
40 | @@ -XXX,XX +XXX,XX @@ void gicv3_redist_update_lpi(GICv3CPUState *cs); | ||
41 | * an incoming migration has loaded new state. | ||
42 | */ | ||
43 | void gicv3_redist_update_lpi_only(GICv3CPUState *cs); | ||
44 | +/** | ||
45 | + * gicv3_redist_movall_lpis: | ||
46 | + * @src: source redistributor | ||
47 | + * @dest: destination redistributor | ||
48 | + * | ||
49 | + * Scan the LPI pending table for @src, and for each pending LPI there | ||
50 | + * mark it as not-pending for @src and pending for @dest, as required | ||
51 | + * by the ITS MOVALL command. | ||
52 | + */ | ||
53 | +void gicv3_redist_movall_lpis(GICv3CPUState *src, GICv3CPUState *dest); | ||
54 | + | ||
55 | void gicv3_redist_send_sgi(GICv3CPUState *cs, int grp, int irq, bool ns); | ||
56 | void gicv3_init_cpuif(GICv3State *s); | ||
57 | |||
58 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c | ||
59 | index XXXXXXX..XXXXXXX 100644 | ||
60 | --- a/hw/intc/arm_gicv3_its.c | ||
61 | +++ b/hw/intc/arm_gicv3_its.c | ||
62 | @@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_mapd(GICv3ITSState *s, uint64_t value, | ||
63 | return update_dte(s, devid, valid, size, itt_addr) ? CMD_CONTINUE : CMD_STALL; | ||
64 | } | ||
65 | |||
66 | +static ItsCmdResult process_movall(GICv3ITSState *s, uint64_t value, | ||
67 | + uint32_t offset) | ||
68 | +{ | ||
69 | + AddressSpace *as = &s->gicv3->dma_as; | ||
70 | + MemTxResult res = MEMTX_OK; | ||
71 | + uint64_t rd1, rd2; | ||
72 | + | ||
73 | + /* No fields in dwords 0 or 1 */ | ||
74 | + offset += NUM_BYTES_IN_DW; | ||
75 | + offset += NUM_BYTES_IN_DW; | ||
76 | + value = address_space_ldq_le(as, s->cq.base_addr + offset, | ||
77 | + MEMTXATTRS_UNSPECIFIED, &res); | ||
78 | + if (res != MEMTX_OK) { | ||
79 | + return CMD_STALL; | ||
80 | + } | ||
81 | + | ||
82 | + rd1 = FIELD_EX64(value, MOVALL_2, RDBASE1); | ||
83 | + if (rd1 >= s->gicv3->num_cpu) { | ||
84 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
85 | + "%s: RDBASE1 %" PRId64 | ||
86 | + " out of range (must be less than %d)\n", | ||
87 | + __func__, rd1, s->gicv3->num_cpu); | ||
88 | + return CMD_CONTINUE; | ||
89 | + } | ||
90 | + | ||
91 | + offset += NUM_BYTES_IN_DW; | ||
92 | + value = address_space_ldq_le(as, s->cq.base_addr + offset, | ||
93 | + MEMTXATTRS_UNSPECIFIED, &res); | ||
94 | + if (res != MEMTX_OK) { | ||
95 | + return CMD_STALL; | ||
96 | + } | ||
97 | + | ||
98 | + rd2 = FIELD_EX64(value, MOVALL_3, RDBASE2); | ||
99 | + if (rd2 >= s->gicv3->num_cpu) { | ||
100 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
101 | + "%s: RDBASE2 %" PRId64 | ||
102 | + " out of range (must be less than %d)\n", | ||
103 | + __func__, rd2, s->gicv3->num_cpu); | ||
104 | + return CMD_CONTINUE; | ||
105 | + } | ||
106 | + | ||
107 | + if (rd1 == rd2) { | ||
108 | + /* Move to same target must succeed as a no-op */ | ||
109 | + return CMD_CONTINUE; | ||
110 | + } | ||
111 | + | ||
112 | + /* Move all pending LPIs from redistributor 1 to redistributor 2 */ | ||
113 | + gicv3_redist_movall_lpis(&s->gicv3->cpu[rd1], &s->gicv3->cpu[rd2]); | ||
114 | + | ||
115 | + return CMD_CONTINUE; | ||
116 | +} | ||
117 | + | ||
118 | /* | ||
119 | * Current implementation blocks until all | ||
120 | * commands are processed | ||
121 | @@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s) | ||
122 | gicv3_redist_update_lpi(&s->gicv3->cpu[i]); | ||
123 | } | ||
124 | break; | ||
125 | + case GITS_CMD_MOVALL: | ||
126 | + result = process_movall(s, data, cq_offset); | ||
127 | + break; | ||
128 | default: | ||
129 | break; | ||
130 | } | ||
131 | diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c | ||
132 | index XXXXXXX..XXXXXXX 100644 | ||
133 | --- a/hw/intc/arm_gicv3_redist.c | ||
134 | +++ b/hw/intc/arm_gicv3_redist.c | ||
135 | @@ -XXX,XX +XXX,XX @@ void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level) | ||
136 | gicv3_redist_lpi_pending(cs, irq, level); | ||
137 | } | ||
138 | |||
139 | +void gicv3_redist_movall_lpis(GICv3CPUState *src, GICv3CPUState *dest) | ||
140 | +{ | ||
141 | + /* | ||
142 | + * We must move all pending LPIs from the source redistributor | ||
143 | + * to the destination. That is, for every pending LPI X on | ||
144 | + * src, we must set it not-pending on src and pending on dest. | ||
145 | + * LPIs that are already pending on dest are not cleared. | ||
146 | + * | ||
147 | + * If LPIs are disabled on dest this is CONSTRAINED UNPREDICTABLE: | ||
148 | + * we choose to NOP. If LPIs are disabled on source there's nothing | ||
149 | + * to be transferred anyway. | ||
150 | + */ | ||
151 | + AddressSpace *as = &src->gic->dma_as; | ||
152 | + uint64_t idbits; | ||
153 | + uint32_t pendt_size; | ||
154 | + uint64_t src_baddr, dest_baddr; | ||
155 | + int i; | ||
156 | + | ||
157 | + if (!(src->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) || | ||
158 | + !(dest->gicr_ctlr & GICR_CTLR_ENABLE_LPIS)) { | ||
159 | + return; | ||
160 | + } | ||
161 | + | ||
162 | + idbits = MIN(FIELD_EX64(src->gicr_propbaser, GICR_PROPBASER, IDBITS), | ||
163 | + GICD_TYPER_IDBITS); | ||
164 | + idbits = MIN(FIELD_EX64(dest->gicr_propbaser, GICR_PROPBASER, IDBITS), | ||
165 | + idbits); | ||
166 | + | ||
167 | + pendt_size = 1ULL << (idbits + 1); | ||
168 | + src_baddr = src->gicr_pendbaser & R_GICR_PENDBASER_PHYADDR_MASK; | ||
169 | + dest_baddr = dest->gicr_pendbaser & R_GICR_PENDBASER_PHYADDR_MASK; | ||
170 | + | ||
171 | + for (i = GICV3_LPI_INTID_START / 8; i < pendt_size / 8; i++) { | ||
172 | + uint8_t src_pend, dest_pend; | ||
173 | + | ||
174 | + address_space_read(as, src_baddr + i, MEMTXATTRS_UNSPECIFIED, | ||
175 | + &src_pend, sizeof(src_pend)); | ||
176 | + if (!src_pend) { | ||
177 | + continue; | ||
178 | + } | ||
179 | + address_space_read(as, dest_baddr + i, MEMTXATTRS_UNSPECIFIED, | ||
180 | + &dest_pend, sizeof(dest_pend)); | ||
181 | + dest_pend |= src_pend; | ||
182 | + src_pend = 0; | ||
183 | + address_space_write(as, src_baddr + i, MEMTXATTRS_UNSPECIFIED, | ||
184 | + &src_pend, sizeof(src_pend)); | ||
185 | + address_space_write(as, dest_baddr + i, MEMTXATTRS_UNSPECIFIED, | ||
186 | + &dest_pend, sizeof(dest_pend)); | ||
187 | + } | ||
188 | + | ||
189 | + gicv3_redist_update_lpi(src); | ||
190 | + gicv3_redist_update_lpi(dest); | ||
191 | +} | ||
192 | + | ||
193 | void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level) | ||
194 | { | ||
195 | /* Update redistributor state for a change in an external PPI input line */ | ||
196 | -- | ||
197 | 2.25.1 | ||
198 | |||
199 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | 1 | Implement the ITS MOVI command. This command specifies a (physical) LPI | |
2 | by DeviceID and EventID and provides a new ICID for it. The ITS must | ||
3 | find the interrupt translation table entry for the LPI, which will | ||
4 | tell it the old ICID. It then moves the pending state of the LPI from | ||
5 | the old redistributor to the new one and updates the ICID field in | ||
6 | the translation table entry. | ||
7 | |||
8 | This is another GICv3 ITS command that we forgot to implement. Linux | ||
9 | does use this one, but only if the guest powers off one of its CPUs. | ||
10 | |||
11 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
12 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
13 | Message-id: 20220122182444.724087-15-peter.maydell@linaro.org | ||
14 | --- | ||
15 | hw/intc/gicv3_internal.h | 16 ++++ | ||
16 | hw/intc/arm_gicv3_its.c | 146 +++++++++++++++++++++++++++++++++++++ | ||
17 | hw/intc/arm_gicv3_redist.c | 53 ++++++++++++++ | ||
18 | 3 files changed, 215 insertions(+) | ||
19 | |||
20 | diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h | ||
21 | index XXXXXXX..XXXXXXX 100644 | ||
22 | --- a/hw/intc/gicv3_internal.h | ||
23 | +++ b/hw/intc/gicv3_internal.h | ||
24 | @@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1) | ||
25 | #define CMD_MASK 0xff | ||
26 | |||
27 | /* ITS Commands */ | ||
28 | +#define GITS_CMD_MOVI 0x01 | ||
29 | #define GITS_CMD_INT 0x03 | ||
30 | #define GITS_CMD_CLEAR 0x04 | ||
31 | #define GITS_CMD_SYNC 0x05 | ||
32 | @@ -XXX,XX +XXX,XX @@ FIELD(MAPC, RDBASE, 16, 32) | ||
33 | FIELD(MOVALL_2, RDBASE1, 16, 36) | ||
34 | FIELD(MOVALL_3, RDBASE2, 16, 36) | ||
35 | |||
36 | +/* MOVI command fields */ | ||
37 | +FIELD(MOVI_0, DEVICEID, 32, 32) | ||
38 | +FIELD(MOVI_1, EVENTID, 0, 32) | ||
39 | +FIELD(MOVI_2, ICID, 0, 16) | ||
40 | + | ||
41 | /* | ||
42 | * 12 bytes Interrupt translation Table Entry size | ||
43 | * as per Table 5.3 in GICv3 spec | ||
44 | @@ -XXX,XX +XXX,XX @@ void gicv3_redist_update_lpi(GICv3CPUState *cs); | ||
45 | * an incoming migration has loaded new state. | ||
46 | */ | ||
47 | void gicv3_redist_update_lpi_only(GICv3CPUState *cs); | ||
48 | +/** | ||
49 | + * gicv3_redist_mov_lpi: | ||
50 | + * @src: source redistributor | ||
51 | + * @dest: destination redistributor | ||
52 | + * @irq: LPI to update | ||
53 | + * | ||
54 | + * Move the pending state of the specified LPI from @src to @dest, | ||
55 | + * as required by the ITS MOVI command. | ||
56 | + */ | ||
57 | +void gicv3_redist_mov_lpi(GICv3CPUState *src, GICv3CPUState *dest, int irq); | ||
58 | /** | ||
59 | * gicv3_redist_movall_lpis: | ||
60 | * @src: source redistributor | ||
61 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c | ||
62 | index XXXXXXX..XXXXXXX 100644 | ||
63 | --- a/hw/intc/arm_gicv3_its.c | ||
64 | +++ b/hw/intc/arm_gicv3_its.c | ||
65 | @@ -XXX,XX +XXX,XX @@ static ItsCmdResult process_movall(GICv3ITSState *s, uint64_t value, | ||
66 | return CMD_CONTINUE; | ||
67 | } | ||
68 | |||
69 | +static ItsCmdResult process_movi(GICv3ITSState *s, uint64_t value, | ||
70 | + uint32_t offset) | ||
71 | +{ | ||
72 | + AddressSpace *as = &s->gicv3->dma_as; | ||
73 | + MemTxResult res = MEMTX_OK; | ||
74 | + uint32_t devid, eventid, intid; | ||
75 | + uint16_t old_icid, new_icid; | ||
76 | + uint64_t old_cte, new_cte; | ||
77 | + uint64_t old_rdbase, new_rdbase; | ||
78 | + uint64_t dte; | ||
79 | + bool dte_valid, ite_valid, cte_valid; | ||
80 | + uint64_t num_eventids; | ||
81 | + IteEntry ite = {}; | ||
82 | + | ||
83 | + devid = FIELD_EX64(value, MOVI_0, DEVICEID); | ||
84 | + | ||
85 | + offset += NUM_BYTES_IN_DW; | ||
86 | + value = address_space_ldq_le(as, s->cq.base_addr + offset, | ||
87 | + MEMTXATTRS_UNSPECIFIED, &res); | ||
88 | + if (res != MEMTX_OK) { | ||
89 | + return CMD_STALL; | ||
90 | + } | ||
91 | + eventid = FIELD_EX64(value, MOVI_1, EVENTID); | ||
92 | + | ||
93 | + offset += NUM_BYTES_IN_DW; | ||
94 | + value = address_space_ldq_le(as, s->cq.base_addr + offset, | ||
95 | + MEMTXATTRS_UNSPECIFIED, &res); | ||
96 | + if (res != MEMTX_OK) { | ||
97 | + return CMD_STALL; | ||
98 | + } | ||
99 | + new_icid = FIELD_EX64(value, MOVI_2, ICID); | ||
100 | + | ||
101 | + if (devid >= s->dt.num_entries) { | ||
102 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
103 | + "%s: invalid command attributes: devid %d>=%d", | ||
104 | + __func__, devid, s->dt.num_entries); | ||
105 | + return CMD_CONTINUE; | ||
106 | + } | ||
107 | + dte = get_dte(s, devid, &res); | ||
108 | + if (res != MEMTX_OK) { | ||
109 | + return CMD_STALL; | ||
110 | + } | ||
111 | + | ||
112 | + dte_valid = FIELD_EX64(dte, DTE, VALID); | ||
113 | + if (!dte_valid) { | ||
114 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
115 | + "%s: invalid command attributes: " | ||
116 | + "invalid dte: %"PRIx64" for %d\n", | ||
117 | + __func__, dte, devid); | ||
118 | + return CMD_CONTINUE; | ||
119 | + } | ||
120 | + | ||
121 | + num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1); | ||
122 | + if (eventid >= num_eventids) { | ||
123 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
124 | + "%s: invalid command attributes: eventid %d >= %" | ||
125 | + PRId64 "\n", | ||
126 | + __func__, eventid, num_eventids); | ||
127 | + return CMD_CONTINUE; | ||
128 | + } | ||
129 | + | ||
130 | + ite_valid = get_ite(s, eventid, dte, &old_icid, &intid, &res); | ||
131 | + if (res != MEMTX_OK) { | ||
132 | + return CMD_STALL; | ||
133 | + } | ||
134 | + | ||
135 | + if (!ite_valid) { | ||
136 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
137 | + "%s: invalid command attributes: invalid ITE\n", | ||
138 | + __func__); | ||
139 | + return CMD_CONTINUE; | ||
140 | + } | ||
141 | + | ||
142 | + if (old_icid >= s->ct.num_entries) { | ||
143 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
144 | + "%s: invalid ICID 0x%x in ITE (table corrupted?)\n", | ||
145 | + __func__, old_icid); | ||
146 | + return CMD_CONTINUE; | ||
147 | + } | ||
148 | + | ||
149 | + if (new_icid >= s->ct.num_entries) { | ||
150 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
151 | + "%s: invalid command attributes: ICID 0x%x\n", | ||
152 | + __func__, new_icid); | ||
153 | + return CMD_CONTINUE; | ||
154 | + } | ||
155 | + | ||
156 | + cte_valid = get_cte(s, old_icid, &old_cte, &res); | ||
157 | + if (res != MEMTX_OK) { | ||
158 | + return CMD_STALL; | ||
159 | + } | ||
160 | + if (!cte_valid) { | ||
161 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
162 | + "%s: invalid command attributes: " | ||
163 | + "invalid cte: %"PRIx64"\n", | ||
164 | + __func__, old_cte); | ||
165 | + return CMD_CONTINUE; | ||
166 | + } | ||
167 | + | ||
168 | + cte_valid = get_cte(s, new_icid, &new_cte, &res); | ||
169 | + if (res != MEMTX_OK) { | ||
170 | + return CMD_STALL; | ||
171 | + } | ||
172 | + if (!cte_valid) { | ||
173 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
174 | + "%s: invalid command attributes: " | ||
175 | + "invalid cte: %"PRIx64"\n", | ||
176 | + __func__, new_cte); | ||
177 | + return CMD_CONTINUE; | ||
178 | + } | ||
179 | + | ||
180 | + old_rdbase = FIELD_EX64(old_cte, CTE, RDBASE); | ||
181 | + if (old_rdbase >= s->gicv3->num_cpu) { | ||
182 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
183 | + "%s: CTE has invalid rdbase 0x%"PRIx64"\n", | ||
184 | + __func__, old_rdbase); | ||
185 | + return CMD_CONTINUE; | ||
186 | + } | ||
187 | + | ||
188 | + new_rdbase = FIELD_EX64(new_cte, CTE, RDBASE); | ||
189 | + if (new_rdbase >= s->gicv3->num_cpu) { | ||
190 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
191 | + "%s: CTE has invalid rdbase 0x%"PRIx64"\n", | ||
192 | + __func__, new_rdbase); | ||
193 | + return CMD_CONTINUE; | ||
194 | + } | ||
195 | + | ||
196 | + if (old_rdbase != new_rdbase) { | ||
197 | + /* Move the LPI from the old redistributor to the new one */ | ||
198 | + gicv3_redist_mov_lpi(&s->gicv3->cpu[old_rdbase], | ||
199 | + &s->gicv3->cpu[new_rdbase], | ||
200 | + intid); | ||
201 | + } | ||
202 | + | ||
203 | + /* Update the ICID field in the interrupt translation table entry */ | ||
204 | + ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, 1); | ||
205 | + ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL); | ||
206 | + ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, intid); | ||
207 | + ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS); | ||
208 | + ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, new_icid); | ||
209 | + return update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL; | ||
210 | +} | ||
211 | + | ||
212 | /* | ||
213 | * Current implementation blocks until all | ||
214 | * commands are processed | ||
215 | @@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s) | ||
216 | gicv3_redist_update_lpi(&s->gicv3->cpu[i]); | ||
217 | } | ||
218 | break; | ||
219 | + case GITS_CMD_MOVI: | ||
220 | + result = process_movi(s, data, cq_offset); | ||
221 | + break; | ||
222 | case GITS_CMD_MOVALL: | ||
223 | result = process_movall(s, data, cq_offset); | ||
224 | break; | ||
225 | diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c | ||
226 | index XXXXXXX..XXXXXXX 100644 | ||
227 | --- a/hw/intc/arm_gicv3_redist.c | ||
228 | +++ b/hw/intc/arm_gicv3_redist.c | ||
229 | @@ -XXX,XX +XXX,XX @@ void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level) | ||
230 | gicv3_redist_lpi_pending(cs, irq, level); | ||
231 | } | ||
232 | |||
233 | +void gicv3_redist_mov_lpi(GICv3CPUState *src, GICv3CPUState *dest, int irq) | ||
234 | +{ | ||
235 | + /* | ||
236 | + * Move the specified LPI's pending state from the source redistributor | ||
237 | + * to the destination. | ||
238 | + * | ||
239 | + * If LPIs are disabled on dest this is CONSTRAINED UNPREDICTABLE: | ||
240 | + * we choose to NOP. If LPIs are disabled on source there's nothing | ||
241 | + * to be transferred anyway. | ||
242 | + */ | ||
243 | + AddressSpace *as = &src->gic->dma_as; | ||
244 | + uint64_t idbits; | ||
245 | + uint32_t pendt_size; | ||
246 | + uint64_t src_baddr; | ||
247 | + uint8_t src_pend; | ||
248 | + | ||
249 | + if (!(src->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) || | ||
250 | + !(dest->gicr_ctlr & GICR_CTLR_ENABLE_LPIS)) { | ||
251 | + return; | ||
252 | + } | ||
253 | + | ||
254 | + idbits = MIN(FIELD_EX64(src->gicr_propbaser, GICR_PROPBASER, IDBITS), | ||
255 | + GICD_TYPER_IDBITS); | ||
256 | + idbits = MIN(FIELD_EX64(dest->gicr_propbaser, GICR_PROPBASER, IDBITS), | ||
257 | + idbits); | ||
258 | + | ||
259 | + pendt_size = 1ULL << (idbits + 1); | ||
260 | + if ((irq / 8) >= pendt_size) { | ||
261 | + return; | ||
262 | + } | ||
263 | + | ||
264 | + src_baddr = src->gicr_pendbaser & R_GICR_PENDBASER_PHYADDR_MASK; | ||
265 | + | ||
266 | + address_space_read(as, src_baddr + (irq / 8), | ||
267 | + MEMTXATTRS_UNSPECIFIED, &src_pend, sizeof(src_pend)); | ||
268 | + if (!extract32(src_pend, irq % 8, 1)) { | ||
269 | + /* Not pending on source, nothing to do */ | ||
270 | + return; | ||
271 | + } | ||
272 | + src_pend &= ~(1 << (irq % 8)); | ||
273 | + address_space_write(as, src_baddr + (irq / 8), | ||
274 | + MEMTXATTRS_UNSPECIFIED, &src_pend, sizeof(src_pend)); | ||
275 | + if (irq == src->hpplpi.irq) { | ||
276 | + /* | ||
277 | + * We just made this LPI not-pending so only need to update | ||
278 | + * if it was previously the highest priority pending LPI | ||
279 | + */ | ||
280 | + gicv3_redist_update_lpi(src); | ||
281 | + } | ||
282 | + /* Mark it pending on the destination */ | ||
283 | + gicv3_redist_lpi_pending(dest, irq, 1); | ||
284 | +} | ||
285 | + | ||
286 | void gicv3_redist_movall_lpis(GICv3CPUState *src, GICv3CPUState *dest) | ||
287 | { | ||
288 | /* | ||
289 | -- | ||
290 | 2.25.1 | ||
291 | |||
292 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Cédric Le Goater <clg@kaod.org> | ||
1 | 2 | ||
3 | Address should be 0x1E631000 and not 0x1E641000 as initially introduced. | ||
4 | |||
5 | Resolves: https://gitlab.com/qemu-project/qemu/-/issues/838 | ||
6 | Fixes: f25c0ae1079d ("aspeed/soc: Add AST2600 support") | ||
7 | Suggested-by: Troy Lee <troy_lee@aspeedtech.com> | ||
8 | Signed-off-by: Cédric Le Goater <clg@kaod.org> | ||
9 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
10 | Message-id: 20220126083520.4135713-1-clg@kaod.org | ||
11 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
12 | --- | ||
13 | hw/arm/aspeed_ast2600.c | 2 +- | ||
14 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
15 | |||
16 | diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c | ||
17 | index XXXXXXX..XXXXXXX 100644 | ||
18 | --- a/hw/arm/aspeed_ast2600.c | ||
19 | +++ b/hw/arm/aspeed_ast2600.c | ||
20 | @@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_soc_ast2600_memmap[] = { | ||
21 | [ASPEED_DEV_PWM] = 0x1E610000, | ||
22 | [ASPEED_DEV_FMC] = 0x1E620000, | ||
23 | [ASPEED_DEV_SPI1] = 0x1E630000, | ||
24 | - [ASPEED_DEV_SPI2] = 0x1E641000, | ||
25 | + [ASPEED_DEV_SPI2] = 0x1E631000, | ||
26 | [ASPEED_DEV_EHCI1] = 0x1E6A1000, | ||
27 | [ASPEED_DEV_EHCI2] = 0x1E6A3000, | ||
28 | [ASPEED_DEV_MII1] = 0x1E650000, | ||
29 | -- | ||
30 | 2.25.1 | ||
31 | |||
32 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | The exception caused by an SVC instruction may be taken to AArch32 | ||
2 | Hyp mode for two reasons: | ||
3 | * HCR.TGE indicates that exceptions from EL0 should trap to EL2 | ||
4 | * we were already in Hyp mode | ||
1 | 5 | ||
6 | The entrypoint in the vector table to be used differs in these two | ||
7 | cases: for an exception routed to Hyp mode from EL0, we enter at the | ||
8 | common 0x14 "hyp trap" entrypoint. For SVC from Hyp mode to Hyp | ||
9 | mode, we enter at the 0x08 (svc/hvc trap) entrypoint. | ||
10 | In the v8A Arm ARM pseudocode this is done in AArch32.TakeSVCException. | ||
11 | |||
12 | QEMU incorrectly routed both of these exceptions to the 0x14 | ||
13 | entrypoint. Correct the entrypoint for SVC from Hyp to Hyp by making | ||
14 | use of the existing logic which handles "normal entrypoint for | ||
15 | Hyp-to-Hyp, otherwise 0x14" for traps like UNDEF and data/prefetch | ||
16 | aborts (reproduced here since it's outside the visible context | ||
17 | in the diff for this commit): | ||
18 | |||
19 | if (arm_current_el(env) != 2 && addr < 0x14) { | ||
20 | addr = 0x14; | ||
21 | } | ||
22 | |||
23 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
24 | Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> | ||
25 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
26 | Message-id: 20220117131953.3936137-1-peter.maydell@linaro.org | ||
27 | --- | ||
28 | target/arm/helper.c | 4 ++-- | ||
29 | 1 file changed, 2 insertions(+), 2 deletions(-) | ||
30 | |||
31 | diff --git a/target/arm/helper.c b/target/arm/helper.c | ||
32 | index XXXXXXX..XXXXXXX 100644 | ||
33 | --- a/target/arm/helper.c | ||
34 | +++ b/target/arm/helper.c | ||
35 | @@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch32_hyp(CPUState *cs) | ||
36 | * separately here. | ||
37 | * | ||
38 | * The vector table entry used is always the 0x14 Hyp mode entry point, | ||
39 | - * unless this is an UNDEF/HVC/abort taken from Hyp to Hyp. | ||
40 | + * unless this is an UNDEF/SVC/HVC/abort taken from Hyp to Hyp. | ||
41 | * The offset applied to the preferred return address is always zero | ||
42 | * (see DDI0487C.a section G1.12.3). | ||
43 | * PSTATE A/I/F masks are set based only on the SCR.EA/IRQ/FIQ values. | ||
44 | @@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch32_hyp(CPUState *cs) | ||
45 | addr = 0x04; | ||
46 | break; | ||
47 | case EXCP_SWI: | ||
48 | - addr = 0x14; | ||
49 | + addr = 0x08; | ||
50 | break; | ||
51 | case EXCP_BKPT: | ||
52 | /* Fall through to prefetch abort. */ | ||
53 | -- | ||
54 | 2.25.1 | ||
55 | |||
56 | diff view generated by jsdifflib |