1
target-arm queue: I have a lot more still in my to-review
1
Last pullreq before 6.0 softfreeze: a few minor feature patches,
2
queue, but my rule of thumb is when I get to 50 patches or
2
some bugfixes, some cleanups.
3
so to send out what I have.
4
3
5
thanks
6
-- PMM
4
-- PMM
7
5
8
The following changes since commit 9a7beaad3dbba982f7a461d676b55a5c3851d312:
6
The following changes since commit 6f34661b6c97a37a5efc27d31c037ddeda4547e2:
9
7
10
Merge remote-tracking branch 'remotes/alistair/tags/pull-riscv-to-apply-20210304' into staging (2021-03-05 10:47:46 +0000)
8
Merge remote-tracking branch 'remotes/vivier2/tags/trivial-branch-for-6.0-pull-request' into staging (2021-03-11 18:55:27 +0000)
11
9
12
are available in the Git repository at:
10
are available in the Git repository at:
13
11
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210305
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210312-1
15
13
16
for you to fetch changes up to 2c669ff88ec6733420a000103a2b8b9e93df4945:
14
for you to fetch changes up to 41f09f2e9f09e4dd386d84174a6dcb5136af17ca:
17
15
18
hw/arm/mps2: Update old infocenter.arm.com URLs (2021-03-05 15:17:38 +0000)
16
hw/display/pxa2xx: Inline template header (2021-03-12 13:26:08 +0000)
19
17
20
----------------------------------------------------------------
18
----------------------------------------------------------------
21
* sbsa-ref: remove cortex-a53 from list of supported cpus
19
target-arm queue:
22
* sbsa-ref: add 'max' to list of allowed cpus
20
* versal: Support XRAMs and XRAM controller
23
* target/arm: Add support for FEAT_SSBS, Speculative Store Bypass Safe
21
* smmu: Various minor bug fixes
24
* npcm7xx: add EMC model
22
* SVE emulation: fix bugs handling odd vector lengths
25
* xlnx-zynqmp: Remove obsolete 'has_rpu' property
23
* allwinner-sun8i-emac: traverse transmit queue using TX_CUR_DESC register value
26
* target/arm: Speed up aarch64 TBL/TBX
24
* tests/acceptance: fix orangepi-pc acceptance tests
27
* virtio-mmio: improve virtio-mmio get_dev_path alog
25
* hw/timer/sse-timer: Propagate eventual error in sse_timer_realize()
28
* target/arm: Use TCF0 and TFSRE0 for unprivileged tag checks
26
* hw/arm/virt: KVM: The IPA lower bound is 32
29
* target/arm: Restrict v8M IDAU to TCG
27
* npcm7xx: support MFT module
30
* target/arm/cpu: Update coding style to make checkpatch.pl happy
28
* pl110, pxa2xx_lcd: tidy up template headers
31
* musicpal, tc6393xb, omap_lcdc, tcx: drop dead code for non-32-bit-RGB surfaces
32
* Add new board: mps3-an524
33
29
34
----------------------------------------------------------------
30
----------------------------------------------------------------
35
Doug Evans (3):
31
Andrew Jones (2):
36
hw/net: Add npcm7xx emc model
32
accel: kvm: Fix kvm_type invocation
37
hw/arm: Add npcm7xx emc model
33
hw/arm/virt: KVM: The IPA lower bound is 32
38
tests/qtests: Add npcm7xx emc model test
39
34
40
Marcin Juszkiewicz (2):
35
Edgar E. Iglesias (2):
41
sbsa-ref: remove cortex-a53 from list of supported cpus
36
hw/misc: versal: Add a model of the XRAM controller
42
sbsa-ref: add 'max' to list of allowed cpus
37
hw/arm: versal: Add support for the XRAMs
43
38
44
Peter Collingbourne (1):
39
Eric Auger (7):
45
target/arm: Use TCF0 and TFSRE0 for unprivileged tag checks
40
intel_iommu: Fix mask may be uninitialized in vtd_context_device_invalidate
41
dma: Introduce dma_aligned_pow2_mask()
42
virtio-iommu: Handle non power of 2 range invalidations
43
hw/arm/smmu-common: Fix smmu_iotlb_inv_iova when asid is not set
44
hw/arm/smmuv3: Enforce invalidation on a power of two range
45
hw/arm/smmuv3: Fix SMMU_CMD_CFGI_STE_RANGE handling
46
hw/arm/smmuv3: Uniformize sid traces
46
47
47
Peter Maydell (34):
48
Hao Wu (5):
48
hw/arm/musicpal: Remove dead code for non-32-bit-RGB surfaces
49
hw/misc: Add GPIOs for duty in NPCM7xx PWM
49
hw/display/tc6393xb: Remove dead code for handling non-32bpp surfaces
50
hw/misc: Add NPCM7XX MFT Module
50
hw/display/tc6393xb: Expand out macros in template header
51
hw/arm: Add MFT device to NPCM7xx Soc
51
hw/display/tc6393xb: Inline tc6393xb_draw_graphic32() at its callsite
52
hw/arm: Connect PWM fans in NPCM7XX boards
52
hw/display/omap_lcdc: Expand out macros in template header
53
tests/qtest: Test PWM fan RPM using MFT in PWM test
53
hw/display/omap_lcdc: Drop broken bigendian ifdef
54
hw/display/omap_lcdc: Fix coding style issues in template header
55
hw/display/omap_lcdc: Inline template header into C file
56
hw/display/omap_lcdc: Delete unnecessary macro
57
hw/display/tcx: Drop unnecessary code for handling BGR format outputs
58
hw/arm/mps2-tz: Make SYSCLK frequency board-specific
59
hw/misc/mps2-scc: Support configurable number of OSCCLK values
60
hw/arm/mps2-tz: Correct the OSCCLK settings for mps2-an505 and mps2-an511
61
hw/arm/mps2-tz: Make the OSCCLK settings be configurable per-board
62
hw/misc/mps2-fpgaio: Make number of LEDs configurable by board
63
hw/misc/mps2-fpgaio: Support SWITCH register
64
hw/arm/mps2-tz: Make FPGAIO switch and LED config per-board
65
hw/arm/mps2-tz: Condition IRQ splitting on number of CPUs, not board type
66
hw/arm/mps2-tz: Make number of IRQs board-specific
67
hw/misc/mps2-scc: Implement CFG_REG5 and CFG_REG6 for MPS3 AN524
68
hw/arm/mps2-tz: Correct wrong interrupt numbers for DMA and SPI
69
hw/arm/mps2-tz: Allow PPCPortInfo structures to specify device interrupts
70
hw/arm/mps2-tz: Move device IRQ info to data structures
71
hw/arm/mps2-tz: Size the uart-irq-orgate based on the number of UARTs
72
hw/arm/mps2-tz: Allow boards to have different PPCInfo data
73
hw/arm/mps2-tz: Make RAM arrangement board-specific
74
hw/arm/mps2-tz: Set MachineClass default_ram info from RAMInfo data
75
hw/arm/mps2-tz: Support ROMs as well as RAMs
76
hw/arm/mps2-tz: Get armv7m_load_kernel() size argument from RAMInfo
77
hw/arm/mps2-tz: Add new mps3-an524 board
78
hw/arm/mps2-tz: Stub out USB controller for mps3-an524
79
hw/arm/mps2-tz: Provide PL031 RTC on mps3-an524
80
docs/system/arm/mps2.rst: Document the new mps3-an524 board
81
hw/arm/mps2: Update old infocenter.arm.com URLs
82
54
83
Philippe Mathieu-Daudé (4):
55
Niek Linnenbank (5):
84
hw/arm/xlnx-zynqmp: Remove obsolete 'has_rpu' property
56
hw/net/allwinner-sun8i-emac: traverse transmit queue using TX_CUR_DESC register value
85
hw/i2c/npcm7xx_smbus: Simplify npcm7xx_smbus_init()
57
tests/acceptance/boot_linux_console: remove Armbian 19.11.3 bionic test for orangepi-pc machine
86
target/arm: Restrict v8M IDAU to TCG
58
tests/acceptance/boot_linux_console: change URL for test_arm_orangepi_bionic_20_08
87
target/arm/cpu: Update coding style to make checkpatch.pl happy
59
tests/acceptance: update sunxi kernel from armbian to 5.10.16
60
tests/acceptance: drop ARMBIAN_ARTIFACTS_CACHED condition for orangepi-pc, cubieboard tests
88
61
89
Rebecca Cran (3):
62
Peter Maydell (9):
90
target/arm: Add support for FEAT_SSBS, Speculative Store Bypass Safe
63
hw/display/pl110: Remove dead code for non-32-bpp surfaces
91
target/arm: Enable FEAT_SSBS for "max" AARCH64 CPU
64
hw/display/pl110: Pull included-once parts of template header into pl110.c
92
target/arm: Set ID_PFR2.SSBS to 1 for "max" 32-bit CPU
65
hw/display/pl110: Remove use of BITS from pl110_template.h
66
hw/display/pxa2xx_lcd: Remove dead code for non-32-bpp surfaces
67
hw/display/pxa2xx_lcd: Remove dest_width state field
68
hw/display/pxa2xx: Remove use of BITS in pxa2xx_template.h
69
hw/display/pxa2xx: Apply brace-related coding style fixes to template header
70
hw/display/pxa2xx: Apply whitespace-only coding style fixes to template header
71
hw/display/pxa2xx: Inline template header
93
72
94
Richard Henderson (1):
73
Philippe Mathieu-Daudé (1):
95
target/arm: Speed up aarch64 TBL/TBX
74
hw/timer/sse-timer: Propagate eventual error in sse_timer_realize()
96
75
97
schspa (1):
76
Richard Henderson (8):
98
virtio-mmio: improve virtio-mmio get_dev_path alog
77
target/arm: Fix sve_uzp_p vs odd vector lengths
78
target/arm: Fix sve_zip_p vs odd vector lengths
79
target/arm: Fix sve_punpk_p vs odd vector lengths
80
target/arm: Update find_last_active for PREDDESC
81
target/arm: Update BRKA, BRKB, BRKN for PREDDESC
82
target/arm: Update CNTP for PREDDESC
83
target/arm: Update WHILE for PREDDESC
84
target/arm: Update sve reduction vs simd_desc
99
85
100
docs/system/arm/mps2.rst | 24 +-
86
docs/system/arm/nuvoton.rst | 2 +-
101
docs/system/arm/nuvoton.rst | 3 +-
87
docs/system/arm/xlnx-versal-virt.rst | 1 +
102
hw/display/omap_lcd_template.h | 169 --------
88
hw/arm/smmu-internal.h | 5 +
103
hw/display/tc6393xb_template.h | 72 ----
89
hw/display/pl110_template.h | 120 +-------
104
include/hw/arm/armsse.h | 4 +-
90
hw/display/pxa2xx_template.h | 447 ---------------------------
105
include/hw/arm/npcm7xx.h | 2 +
91
include/hw/arm/npcm7xx.h | 13 +-
106
include/hw/arm/xlnx-zynqmp.h | 2 -
92
include/hw/arm/xlnx-versal.h | 13 +
107
include/hw/misc/armsse-cpuid.h | 2 +-
93
include/hw/boards.h | 1 +
108
include/hw/misc/armsse-mhu.h | 2 +-
94
include/hw/misc/npcm7xx_mft.h | 70 +++++
109
include/hw/misc/iotkit-secctl.h | 2 +-
95
include/hw/misc/npcm7xx_pwm.h | 4 +-
110
include/hw/misc/iotkit-sysctl.h | 2 +-
96
include/hw/misc/xlnx-versal-xramc.h | 97 ++++++
111
include/hw/misc/iotkit-sysinfo.h | 2 +-
97
include/sysemu/dma.h | 12 +
112
include/hw/misc/mps2-fpgaio.h | 8 +-
98
target/arm/kvm_arm.h | 6 +-
113
include/hw/misc/mps2-scc.h | 10 +-
99
accel/kvm/kvm-all.c | 2 +
114
include/hw/net/npcm7xx_emc.h | 286 +++++++++++++
100
hw/arm/npcm7xx.c | 45 ++-
115
include/ui/console.h | 10 -
101
hw/arm/npcm7xx_boards.c | 99 ++++++
116
target/arm/cpu.h | 15 +-
102
hw/arm/smmu-common.c | 32 +-
117
target/arm/helper-a64.h | 2 +-
103
hw/arm/smmuv3.c | 58 ++--
118
target/arm/internals.h | 6 +
104
hw/arm/virt.c | 23 +-
119
hw/arm/mps2-tz.c | 632 +++++++++++++++++++++++-----
105
hw/arm/xlnx-versal.c | 36 +++
120
hw/arm/mps2.c | 5 +
106
hw/display/pl110.c | 123 +++++---
121
hw/arm/musicpal.c | 64 ++-
107
hw/display/pxa2xx_lcd.c | 520 ++++++++++++++++++++++++++-----
122
hw/arm/npcm7xx.c | 50 ++-
108
hw/i386/intel_iommu.c | 32 +-
123
hw/arm/sbsa-ref.c | 2 +-
109
hw/misc/npcm7xx_mft.c | 540 +++++++++++++++++++++++++++++++++
124
hw/arm/xlnx-zynqmp.c | 6 -
110
hw/misc/npcm7xx_pwm.c | 4 +
125
hw/display/omap_lcdc.c | 129 +++++-
111
hw/misc/xlnx-versal-xramc.c | 253 +++++++++++++++
126
hw/display/tc6393xb.c | 48 +--
112
hw/net/allwinner-sun8i-emac.c | 62 ++--
127
hw/display/tcx.c | 31 +-
113
hw/timer/sse-timer.c | 1 +
128
hw/i2c/npcm7xx_smbus.c | 1 -
114
hw/virtio/virtio-iommu.c | 19 +-
129
hw/misc/armsse-cpuid.c | 2 +-
115
softmmu/dma-helpers.c | 26 ++
130
hw/misc/armsse-mhu.c | 2 +-
116
target/arm/kvm.c | 4 +-
131
hw/misc/iotkit-sysctl.c | 2 +-
117
target/arm/sve_helper.c | 107 ++++---
132
hw/misc/iotkit-sysinfo.c | 2 +-
118
target/arm/translate-sve.c | 26 +-
133
hw/misc/mps2-fpgaio.c | 43 +-
119
tests/qtest/npcm7xx_pwm-test.c | 205 ++++++++++++-
134
hw/misc/mps2-scc.c | 93 ++++-
120
hw/arm/trace-events | 24 +-
135
hw/net/npcm7xx_emc.c | 857 ++++++++++++++++++++++++++++++++++++++
121
hw/misc/meson.build | 2 +
136
hw/virtio/virtio-mmio.c | 13 +-
122
hw/misc/trace-events | 8 +
137
target/arm/cpu.c | 23 +-
123
tests/acceptance/boot_linux_console.py | 120 +++-----
138
target/arm/cpu64.c | 5 +
124
tests/acceptance/replay_kernel.py | 10 +-
139
target/arm/cpu_tcg.c | 8 +
125
39 files changed, 2235 insertions(+), 937 deletions(-)
140
target/arm/helper-a64.c | 32 --
126
delete mode 100644 hw/display/pxa2xx_template.h
141
target/arm/helper.c | 39 +-
127
create mode 100644 include/hw/misc/npcm7xx_mft.h
142
target/arm/mte_helper.c | 13 +-
128
create mode 100644 include/hw/misc/xlnx-versal-xramc.h
143
target/arm/translate-a64.c | 70 +---
129
create mode 100644 hw/misc/npcm7xx_mft.c
144
target/arm/vec_helper.c | 48 +++
130
create mode 100644 hw/misc/xlnx-versal-xramc.c
145
tests/qtest/npcm7xx_emc-test.c | 862 +++++++++++++++++++++++++++++++++++++++
146
hw/net/meson.build | 1 +
147
hw/net/trace-events | 17 +
148
tests/qtest/meson.build | 3 +-
149
49 files changed, 3098 insertions(+), 628 deletions(-)
150
delete mode 100644 hw/display/omap_lcd_template.h
151
delete mode 100644 hw/display/tc6393xb_template.h
152
create mode 100644 include/hw/net/npcm7xx_emc.h
153
create mode 100644 hw/net/npcm7xx_emc.c
154
create mode 100644 tests/qtest/npcm7xx_emc-test.c
155
131
diff view generated by jsdifflib
1
From: Doug Evans <dje@google.com>
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
2
3
Reviewed-by: Hao Wu <wuhaotsh@google.com>
3
Add a model of the Xilinx Versal Accelerator RAM (XRAM).
4
Reviewed-by: Avi Fishman <avi.fishman@nuvoton.com>
4
This is mainly a stub to make firmware happy. The size of
5
the RAMs can be probed. The interrupt mask logic is
6
modelled but none of the interrups will ever be raised
7
unless injected.
8
9
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
Message-id: 20210308224637.2949533-2-edgar.iglesias@gmail.com
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Doug Evans <dje@google.com>
7
Message-id: 20210218212453.831406-4-dje@google.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
13
---
10
tests/qtest/npcm7xx_emc-test.c | 862 +++++++++++++++++++++++++++++++++
14
include/hw/misc/xlnx-versal-xramc.h | 97 +++++++++++
11
tests/qtest/meson.build | 3 +-
15
hw/misc/xlnx-versal-xramc.c | 253 ++++++++++++++++++++++++++++
12
2 files changed, 864 insertions(+), 1 deletion(-)
16
hw/misc/meson.build | 1 +
13
create mode 100644 tests/qtest/npcm7xx_emc-test.c
17
3 files changed, 351 insertions(+)
14
18
create mode 100644 include/hw/misc/xlnx-versal-xramc.h
15
diff --git a/tests/qtest/npcm7xx_emc-test.c b/tests/qtest/npcm7xx_emc-test.c
19
create mode 100644 hw/misc/xlnx-versal-xramc.c
20
21
diff --git a/include/hw/misc/xlnx-versal-xramc.h b/include/hw/misc/xlnx-versal-xramc.h
16
new file mode 100644
22
new file mode 100644
17
index XXXXXXX..XXXXXXX
23
index XXXXXXX..XXXXXXX
18
--- /dev/null
24
--- /dev/null
19
+++ b/tests/qtest/npcm7xx_emc-test.c
25
+++ b/include/hw/misc/xlnx-versal-xramc.h
20
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@
21
+/*
27
+/*
22
+ * QTests for Nuvoton NPCM7xx EMC Modules.
28
+ * QEMU model of the Xilinx XRAM Controller.
23
+ *
29
+ *
24
+ * Copyright 2020 Google LLC
30
+ * Copyright (c) 2021 Xilinx Inc.
31
+ * SPDX-License-Identifier: GPL-2.0-or-later
32
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
33
+ */
34
+
35
+#ifndef XLNX_VERSAL_XRAMC_H
36
+#define XLNX_VERSAL_XRAMC_H
37
+
38
+#include "hw/sysbus.h"
39
+#include "hw/register.h"
40
+
41
+#define TYPE_XLNX_XRAM_CTRL "xlnx.versal-xramc"
42
+
43
+#define XLNX_XRAM_CTRL(obj) \
44
+ OBJECT_CHECK(XlnxXramCtrl, (obj), TYPE_XLNX_XRAM_CTRL)
45
+
46
+REG32(XRAM_ERR_CTRL, 0x0)
47
+ FIELD(XRAM_ERR_CTRL, UE_RES, 3, 1)
48
+ FIELD(XRAM_ERR_CTRL, PWR_ERR_RES, 2, 1)
49
+ FIELD(XRAM_ERR_CTRL, PZ_ERR_RES, 1, 1)
50
+ FIELD(XRAM_ERR_CTRL, APB_ERR_RES, 0, 1)
51
+REG32(XRAM_ISR, 0x4)
52
+ FIELD(XRAM_ISR, INV_APB, 0, 1)
53
+REG32(XRAM_IMR, 0x8)
54
+ FIELD(XRAM_IMR, INV_APB, 0, 1)
55
+REG32(XRAM_IEN, 0xc)
56
+ FIELD(XRAM_IEN, INV_APB, 0, 1)
57
+REG32(XRAM_IDS, 0x10)
58
+ FIELD(XRAM_IDS, INV_APB, 0, 1)
59
+REG32(XRAM_ECC_CNTL, 0x14)
60
+ FIELD(XRAM_ECC_CNTL, FI_MODE, 2, 1)
61
+ FIELD(XRAM_ECC_CNTL, DET_ONLY, 1, 1)
62
+ FIELD(XRAM_ECC_CNTL, ECC_ON_OFF, 0, 1)
63
+REG32(XRAM_CLR_EXE, 0x18)
64
+ FIELD(XRAM_CLR_EXE, MON_7, 7, 1)
65
+ FIELD(XRAM_CLR_EXE, MON_6, 6, 1)
66
+ FIELD(XRAM_CLR_EXE, MON_5, 5, 1)
67
+ FIELD(XRAM_CLR_EXE, MON_4, 4, 1)
68
+ FIELD(XRAM_CLR_EXE, MON_3, 3, 1)
69
+ FIELD(XRAM_CLR_EXE, MON_2, 2, 1)
70
+ FIELD(XRAM_CLR_EXE, MON_1, 1, 1)
71
+ FIELD(XRAM_CLR_EXE, MON_0, 0, 1)
72
+REG32(XRAM_CE_FFA, 0x1c)
73
+ FIELD(XRAM_CE_FFA, ADDR, 0, 20)
74
+REG32(XRAM_CE_FFD0, 0x20)
75
+REG32(XRAM_CE_FFD1, 0x24)
76
+REG32(XRAM_CE_FFD2, 0x28)
77
+REG32(XRAM_CE_FFD3, 0x2c)
78
+REG32(XRAM_CE_FFE, 0x30)
79
+ FIELD(XRAM_CE_FFE, SYNDROME, 0, 16)
80
+REG32(XRAM_UE_FFA, 0x34)
81
+ FIELD(XRAM_UE_FFA, ADDR, 0, 20)
82
+REG32(XRAM_UE_FFD0, 0x38)
83
+REG32(XRAM_UE_FFD1, 0x3c)
84
+REG32(XRAM_UE_FFD2, 0x40)
85
+REG32(XRAM_UE_FFD3, 0x44)
86
+REG32(XRAM_UE_FFE, 0x48)
87
+ FIELD(XRAM_UE_FFE, SYNDROME, 0, 16)
88
+REG32(XRAM_FI_D0, 0x4c)
89
+REG32(XRAM_FI_D1, 0x50)
90
+REG32(XRAM_FI_D2, 0x54)
91
+REG32(XRAM_FI_D3, 0x58)
92
+REG32(XRAM_FI_SY, 0x5c)
93
+ FIELD(XRAM_FI_SY, DATA, 0, 16)
94
+REG32(XRAM_RMW_UE_FFA, 0x70)
95
+ FIELD(XRAM_RMW_UE_FFA, ADDR, 0, 20)
96
+REG32(XRAM_FI_CNTR, 0x74)
97
+ FIELD(XRAM_FI_CNTR, COUNT, 0, 24)
98
+REG32(XRAM_IMP, 0x80)
99
+ FIELD(XRAM_IMP, SIZE, 0, 4)
100
+REG32(XRAM_PRDY_DBG, 0x84)
101
+ FIELD(XRAM_PRDY_DBG, ISLAND3, 12, 4)
102
+ FIELD(XRAM_PRDY_DBG, ISLAND2, 8, 4)
103
+ FIELD(XRAM_PRDY_DBG, ISLAND1, 4, 4)
104
+ FIELD(XRAM_PRDY_DBG, ISLAND0, 0, 4)
105
+REG32(XRAM_SAFETY_CHK, 0xff8)
106
+
107
+#define XRAM_CTRL_R_MAX (R_XRAM_SAFETY_CHK + 1)
108
+
109
+typedef struct XlnxXramCtrl {
110
+ SysBusDevice parent_obj;
111
+ MemoryRegion ram;
112
+ qemu_irq irq;
113
+
114
+ struct {
115
+ uint64_t size;
116
+ unsigned int encoded_size;
117
+ } cfg;
118
+
119
+ RegisterInfoArray *reg_array;
120
+ uint32_t regs[XRAM_CTRL_R_MAX];
121
+ RegisterInfo regs_info[XRAM_CTRL_R_MAX];
122
+} XlnxXramCtrl;
123
+#endif
124
diff --git a/hw/misc/xlnx-versal-xramc.c b/hw/misc/xlnx-versal-xramc.c
125
new file mode 100644
126
index XXXXXXX..XXXXXXX
127
--- /dev/null
128
+++ b/hw/misc/xlnx-versal-xramc.c
129
@@ -XXX,XX +XXX,XX @@
130
+/*
131
+ * QEMU model of the Xilinx XRAM Controller.
25
+ *
132
+ *
26
+ * This program is free software; you can redistribute it and/or modify it
133
+ * Copyright (c) 2021 Xilinx Inc.
27
+ * under the terms of the GNU General Public License as published by the
134
+ * SPDX-License-Identifier: GPL-2.0-or-later
28
+ * Free Software Foundation; either version 2 of the License, or
135
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
29
+ * (at your option) any later version.
30
+ *
31
+ * This program is distributed in the hope that it will be useful, but WITHOUT
32
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
33
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
34
+ * for more details.
35
+ */
136
+ */
36
+
137
+
37
+#include "qemu/osdep.h"
138
+#include "qemu/osdep.h"
38
+#include "qemu-common.h"
139
+#include "qemu/units.h"
39
+#include "libqos/libqos.h"
140
+#include "qapi/error.h"
40
+#include "qapi/qmp/qdict.h"
141
+#include "migration/vmstate.h"
41
+#include "qapi/qmp/qnum.h"
142
+#include "hw/sysbus.h"
42
+#include "qemu/bitops.h"
143
+#include "hw/register.h"
43
+#include "qemu/iov.h"
144
+#include "hw/qdev-properties.h"
44
+
145
+#include "hw/irq.h"
45
+/* Name of the emc device. */
146
+#include "hw/misc/xlnx-versal-xramc.h"
46
+#define TYPE_NPCM7XX_EMC "npcm7xx-emc"
147
+
47
+
148
+#ifndef XLNX_XRAM_CTRL_ERR_DEBUG
48
+/* Timeout for various operations, in seconds. */
149
+#define XLNX_XRAM_CTRL_ERR_DEBUG 0
49
+#define TIMEOUT_SECONDS 10
150
+#endif
50
+
151
+
51
+/* Address in memory of the descriptor. */
152
+static void xram_update_irq(XlnxXramCtrl *s)
52
+#define DESC_ADDR (1 << 20) /* 1 MiB */
153
+{
53
+
154
+ bool pending = s->regs[R_XRAM_ISR] & ~s->regs[R_XRAM_IMR];
54
+/* Address in memory of the data packet. */
155
+ qemu_set_irq(s->irq, pending);
55
+#define DATA_ADDR (DESC_ADDR + 4096)
156
+}
56
+
157
+
57
+#define CRC_LENGTH 4
158
+static void xram_isr_postw(RegisterInfo *reg, uint64_t val64)
58
+
159
+{
59
+#define NUM_TX_DESCRIPTORS 3
160
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(reg->opaque);
60
+#define NUM_RX_DESCRIPTORS 2
161
+ xram_update_irq(s);
61
+
162
+}
62
+/* Size of tx,rx test buffers. */
163
+
63
+#define TX_DATA_LEN 64
164
+static uint64_t xram_ien_prew(RegisterInfo *reg, uint64_t val64)
64
+#define RX_DATA_LEN 64
165
+{
65
+
166
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(reg->opaque);
66
+#define TX_STEP_COUNT 10000
167
+ uint32_t val = val64;
67
+#define RX_STEP_COUNT 10000
168
+
68
+
169
+ s->regs[R_XRAM_IMR] &= ~val;
69
+/* 32-bit register indices. */
170
+ xram_update_irq(s);
70
+typedef enum NPCM7xxPWMRegister {
171
+ return 0;
71
+ /* Control registers. */
172
+}
72
+ REG_CAMCMR,
173
+
73
+ REG_CAMEN,
174
+static uint64_t xram_ids_prew(RegisterInfo *reg, uint64_t val64)
74
+
175
+{
75
+ /* There are 16 CAMn[ML] registers. */
176
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(reg->opaque);
76
+ REG_CAMM_BASE,
177
+ uint32_t val = val64;
77
+ REG_CAML_BASE,
178
+
78
+
179
+ s->regs[R_XRAM_IMR] |= val;
79
+ REG_TXDLSA = 0x22,
180
+ xram_update_irq(s);
80
+ REG_RXDLSA,
181
+ return 0;
81
+ REG_MCMDR,
182
+}
82
+ REG_MIID,
183
+
83
+ REG_MIIDA,
184
+static const RegisterAccessInfo xram_ctrl_regs_info[] = {
84
+ REG_FFTCR,
185
+ { .name = "XRAM_ERR_CTRL", .addr = A_XRAM_ERR_CTRL,
85
+ REG_TSDR,
186
+ .reset = 0xf,
86
+ REG_RSDR,
187
+ .rsvd = 0xfffffff0,
87
+ REG_DMARFC,
188
+ },{ .name = "XRAM_ISR", .addr = A_XRAM_ISR,
88
+ REG_MIEN,
189
+ .rsvd = 0xfffff800,
89
+
190
+ .w1c = 0x7ff,
90
+ /* Status registers. */
191
+ .post_write = xram_isr_postw,
91
+ REG_MISTA,
192
+ },{ .name = "XRAM_IMR", .addr = A_XRAM_IMR,
92
+ REG_MGSTA,
193
+ .reset = 0x7ff,
93
+ REG_MPCNT,
194
+ .rsvd = 0xfffff800,
94
+ REG_MRPC,
195
+ .ro = 0x7ff,
95
+ REG_MRPCC,
196
+ },{ .name = "XRAM_IEN", .addr = A_XRAM_IEN,
96
+ REG_MREPC,
197
+ .rsvd = 0xfffff800,
97
+ REG_DMARFS,
198
+ .pre_write = xram_ien_prew,
98
+ REG_CTXDSA,
199
+ },{ .name = "XRAM_IDS", .addr = A_XRAM_IDS,
99
+ REG_CTXBSA,
200
+ .rsvd = 0xfffff800,
100
+ REG_CRXDSA,
201
+ .pre_write = xram_ids_prew,
101
+ REG_CRXBSA,
202
+ },{ .name = "XRAM_ECC_CNTL", .addr = A_XRAM_ECC_CNTL,
102
+
203
+ .rsvd = 0xfffffff8,
103
+ NPCM7XX_NUM_EMC_REGS,
204
+ },{ .name = "XRAM_CLR_EXE", .addr = A_XRAM_CLR_EXE,
104
+} NPCM7xxPWMRegister;
205
+ .rsvd = 0xffffff00,
105
+
206
+ },{ .name = "XRAM_CE_FFA", .addr = A_XRAM_CE_FFA,
106
+enum { NUM_CAMML_REGS = 16 };
207
+ .rsvd = 0xfff00000,
107
+
208
+ .ro = 0xfffff,
108
+/* REG_CAMCMR fields */
209
+ },{ .name = "XRAM_CE_FFD0", .addr = A_XRAM_CE_FFD0,
109
+/* Enable CAM Compare */
210
+ .ro = 0xffffffff,
110
+#define REG_CAMCMR_ECMP (1 << 4)
211
+ },{ .name = "XRAM_CE_FFD1", .addr = A_XRAM_CE_FFD1,
111
+/* Accept Unicast Packet */
212
+ .ro = 0xffffffff,
112
+#define REG_CAMCMR_AUP (1 << 0)
213
+ },{ .name = "XRAM_CE_FFD2", .addr = A_XRAM_CE_FFD2,
113
+
214
+ .ro = 0xffffffff,
114
+/* REG_MCMDR fields */
215
+ },{ .name = "XRAM_CE_FFD3", .addr = A_XRAM_CE_FFD3,
115
+/* Software Reset */
216
+ .ro = 0xffffffff,
116
+#define REG_MCMDR_SWR (1 << 24)
217
+ },{ .name = "XRAM_CE_FFE", .addr = A_XRAM_CE_FFE,
117
+/* Frame Transmission On */
218
+ .rsvd = 0xffff0000,
118
+#define REG_MCMDR_TXON (1 << 8)
219
+ .ro = 0xffff,
119
+/* Accept Long Packet */
220
+ },{ .name = "XRAM_UE_FFA", .addr = A_XRAM_UE_FFA,
120
+#define REG_MCMDR_ALP (1 << 1)
221
+ .rsvd = 0xfff00000,
121
+/* Frame Reception On */
222
+ .ro = 0xfffff,
122
+#define REG_MCMDR_RXON (1 << 0)
223
+ },{ .name = "XRAM_UE_FFD0", .addr = A_XRAM_UE_FFD0,
123
+
224
+ .ro = 0xffffffff,
124
+/* REG_MIEN fields */
225
+ },{ .name = "XRAM_UE_FFD1", .addr = A_XRAM_UE_FFD1,
125
+/* Enable Transmit Completion Interrupt */
226
+ .ro = 0xffffffff,
126
+#define REG_MIEN_ENTXCP (1 << 18)
227
+ },{ .name = "XRAM_UE_FFD2", .addr = A_XRAM_UE_FFD2,
127
+/* Enable Transmit Interrupt */
228
+ .ro = 0xffffffff,
128
+#define REG_MIEN_ENTXINTR (1 << 16)
229
+ },{ .name = "XRAM_UE_FFD3", .addr = A_XRAM_UE_FFD3,
129
+/* Enable Receive Good Interrupt */
230
+ .ro = 0xffffffff,
130
+#define REG_MIEN_ENRXGD (1 << 4)
231
+ },{ .name = "XRAM_UE_FFE", .addr = A_XRAM_UE_FFE,
131
+/* ENable Receive Interrupt */
232
+ .rsvd = 0xffff0000,
132
+#define REG_MIEN_ENRXINTR (1 << 0)
233
+ .ro = 0xffff,
133
+
234
+ },{ .name = "XRAM_FI_D0", .addr = A_XRAM_FI_D0,
134
+/* REG_MISTA fields */
235
+ },{ .name = "XRAM_FI_D1", .addr = A_XRAM_FI_D1,
135
+/* Transmit Bus Error Interrupt */
236
+ },{ .name = "XRAM_FI_D2", .addr = A_XRAM_FI_D2,
136
+#define REG_MISTA_TXBERR (1 << 24)
237
+ },{ .name = "XRAM_FI_D3", .addr = A_XRAM_FI_D3,
137
+/* Transmit Descriptor Unavailable Interrupt */
238
+ },{ .name = "XRAM_FI_SY", .addr = A_XRAM_FI_SY,
138
+#define REG_MISTA_TDU (1 << 23)
239
+ .rsvd = 0xffff0000,
139
+/* Transmit Completion Interrupt */
240
+ },{ .name = "XRAM_RMW_UE_FFA", .addr = A_XRAM_RMW_UE_FFA,
140
+#define REG_MISTA_TXCP (1 << 18)
241
+ .rsvd = 0xfff00000,
141
+/* Transmit Interrupt */
242
+ .ro = 0xfffff,
142
+#define REG_MISTA_TXINTR (1 << 16)
243
+ },{ .name = "XRAM_FI_CNTR", .addr = A_XRAM_FI_CNTR,
143
+/* Receive Bus Error Interrupt */
244
+ .rsvd = 0xff000000,
144
+#define REG_MISTA_RXBERR (1 << 11)
245
+ },{ .name = "XRAM_IMP", .addr = A_XRAM_IMP,
145
+/* Receive Descriptor Unavailable Interrupt */
246
+ .reset = 0x4,
146
+#define REG_MISTA_RDU (1 << 10)
247
+ .rsvd = 0xfffffff0,
147
+/* DMA Early Notification Interrupt */
248
+ .ro = 0xf,
148
+#define REG_MISTA_DENI (1 << 9)
249
+ },{ .name = "XRAM_PRDY_DBG", .addr = A_XRAM_PRDY_DBG,
149
+/* Maximum Frame Length Interrupt */
250
+ .reset = 0xffff,
150
+#define REG_MISTA_DFOI (1 << 8)
251
+ .rsvd = 0xffff0000,
151
+/* Receive Good Interrupt */
252
+ .ro = 0xffff,
152
+#define REG_MISTA_RXGD (1 << 4)
253
+ },{ .name = "XRAM_SAFETY_CHK", .addr = A_XRAM_SAFETY_CHK,
153
+/* Packet Too Long Interrupt */
254
+ }
154
+#define REG_MISTA_PTLE (1 << 3)
255
+};
155
+/* Receive Interrupt */
256
+
156
+#define REG_MISTA_RXINTR (1 << 0)
257
+static void xram_ctrl_reset_enter(Object *obj, ResetType type)
157
+
258
+{
158
+typedef struct NPCM7xxEMCTxDesc NPCM7xxEMCTxDesc;
259
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
159
+typedef struct NPCM7xxEMCRxDesc NPCM7xxEMCRxDesc;
260
+ unsigned int i;
160
+
261
+
161
+struct NPCM7xxEMCTxDesc {
262
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
162
+ uint32_t flags;
263
+ register_reset(&s->regs_info[i]);
163
+ uint32_t txbsa;
264
+ }
164
+ uint32_t status_and_length;
265
+
165
+ uint32_t ntxdsa;
266
+ ARRAY_FIELD_DP32(s->regs, XRAM_IMP, SIZE, s->cfg.encoded_size);
166
+};
267
+}
167
+
268
+
168
+struct NPCM7xxEMCRxDesc {
269
+static void xram_ctrl_reset_hold(Object *obj)
169
+ uint32_t status_and_length;
270
+{
170
+ uint32_t rxbsa;
271
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
171
+ uint32_t reserved;
272
+
172
+ uint32_t nrxdsa;
273
+ xram_update_irq(s);
173
+};
274
+}
174
+
275
+
175
+/* NPCM7xxEMCTxDesc.flags values */
276
+static const MemoryRegionOps xram_ctrl_ops = {
176
+/* Owner: 0 = cpu, 1 = emc */
277
+ .read = register_read_memory,
177
+#define TX_DESC_FLAG_OWNER_MASK (1 << 31)
278
+ .write = register_write_memory,
178
+/* Transmit interrupt enable */
279
+ .endianness = DEVICE_LITTLE_ENDIAN,
179
+#define TX_DESC_FLAG_INTEN (1 << 2)
280
+ .valid = {
180
+
281
+ .min_access_size = 4,
181
+/* NPCM7xxEMCTxDesc.status_and_length values */
282
+ .max_access_size = 4,
182
+/* Transmission complete */
183
+#define TX_DESC_STATUS_TXCP (1 << 19)
184
+/* Transmit interrupt */
185
+#define TX_DESC_STATUS_TXINTR (1 << 16)
186
+
187
+/* NPCM7xxEMCRxDesc.status_and_length values */
188
+/* Owner: 0b00 = cpu, 0b10 = emc */
189
+#define RX_DESC_STATUS_OWNER_SHIFT 30
190
+#define RX_DESC_STATUS_OWNER_MASK 0xc0000000
191
+/* Frame Reception Complete */
192
+#define RX_DESC_STATUS_RXGD (1 << 20)
193
+/* Packet too long */
194
+#define RX_DESC_STATUS_PTLE (1 << 19)
195
+/* Receive Interrupt */
196
+#define RX_DESC_STATUS_RXINTR (1 << 16)
197
+
198
+#define RX_DESC_PKT_LEN(word) ((uint32_t) (word) & 0xffff)
199
+
200
+typedef struct EMCModule {
201
+ int rx_irq;
202
+ int tx_irq;
203
+ uint64_t base_addr;
204
+} EMCModule;
205
+
206
+typedef struct TestData {
207
+ const EMCModule *module;
208
+} TestData;
209
+
210
+static const EMCModule emc_module_list[] = {
211
+ {
212
+ .rx_irq = 15,
213
+ .tx_irq = 16,
214
+ .base_addr = 0xf0825000
215
+ },
283
+ },
216
+ {
284
+};
217
+ .rx_irq = 114,
285
+
218
+ .tx_irq = 115,
286
+static void xram_ctrl_realize(DeviceState *dev, Error **errp)
219
+ .base_addr = 0xf0826000
287
+{
288
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
289
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(dev);
290
+
291
+ switch (s->cfg.size) {
292
+ case 64 * KiB:
293
+ s->cfg.encoded_size = 0;
294
+ break;
295
+ case 128 * KiB:
296
+ s->cfg.encoded_size = 1;
297
+ break;
298
+ case 256 * KiB:
299
+ s->cfg.encoded_size = 2;
300
+ break;
301
+ case 512 * KiB:
302
+ s->cfg.encoded_size = 3;
303
+ break;
304
+ case 1 * MiB:
305
+ s->cfg.encoded_size = 4;
306
+ break;
307
+ default:
308
+ error_setg(errp, "Unsupported XRAM size %" PRId64, s->cfg.size);
309
+ return;
220
+ }
310
+ }
221
+};
311
+
222
+
312
+ memory_region_init_ram(&s->ram, OBJECT(s),
223
+/* Returns the index of the EMC module. */
313
+ object_get_canonical_path_component(OBJECT(s)),
224
+static int emc_module_index(const EMCModule *mod)
314
+ s->cfg.size, &error_fatal);
225
+{
315
+ sysbus_init_mmio(sbd, &s->ram);
226
+ ptrdiff_t diff = mod - emc_module_list;
316
+}
227
+
317
+
228
+ g_assert_true(diff >= 0 && diff < ARRAY_SIZE(emc_module_list));
318
+static void xram_ctrl_init(Object *obj)
229
+
319
+{
230
+ return diff;
320
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
231
+}
321
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
232
+
322
+
233
+static void packet_test_clear(void *sockets)
323
+ s->reg_array =
234
+{
324
+ register_init_block32(DEVICE(obj), xram_ctrl_regs_info,
235
+ int *test_sockets = sockets;
325
+ ARRAY_SIZE(xram_ctrl_regs_info),
236
+
326
+ s->regs_info, s->regs,
237
+ close(test_sockets[0]);
327
+ &xram_ctrl_ops,
238
+ g_free(test_sockets);
328
+ XLNX_XRAM_CTRL_ERR_DEBUG,
239
+}
329
+ XRAM_CTRL_R_MAX * 4);
240
+
330
+ sysbus_init_mmio(sbd, &s->reg_array->mem);
241
+static int *packet_test_init(int module_num, GString *cmd_line)
331
+ sysbus_init_irq(sbd, &s->irq);
242
+{
332
+}
243
+ int *test_sockets = g_new(int, 2);
333
+
244
+ int ret = socketpair(PF_UNIX, SOCK_STREAM, 0, test_sockets);
334
+static void xram_ctrl_finalize(Object *obj)
245
+ g_assert_cmpint(ret, != , -1);
335
+{
246
+
336
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
247
+ /*
337
+ register_finalize_block(s->reg_array);
248
+ * KISS and use -nic. We specify two nics (both emc{0,1}) because there's
338
+}
249
+ * currently no way to specify only emc1: The driver implicitly relies on
339
+
250
+ * emc[i] == nd_table[i].
340
+static const VMStateDescription vmstate_xram_ctrl = {
251
+ */
341
+ .name = TYPE_XLNX_XRAM_CTRL,
252
+ if (module_num == 0) {
342
+ .version_id = 1,
253
+ g_string_append_printf(cmd_line,
343
+ .minimum_version_id = 1,
254
+ " -nic socket,fd=%d,model=" TYPE_NPCM7XX_EMC " "
344
+ .fields = (VMStateField[]) {
255
+ " -nic user,model=" TYPE_NPCM7XX_EMC " ",
345
+ VMSTATE_UINT32_ARRAY(regs, XlnxXramCtrl, XRAM_CTRL_R_MAX),
256
+ test_sockets[1]);
346
+ VMSTATE_END_OF_LIST(),
257
+ } else {
258
+ g_string_append_printf(cmd_line,
259
+ " -nic user,model=" TYPE_NPCM7XX_EMC " "
260
+ " -nic socket,fd=%d,model=" TYPE_NPCM7XX_EMC " ",
261
+ test_sockets[1]);
262
+ }
347
+ }
263
+
348
+};
264
+ g_test_queue_destroy(packet_test_clear, test_sockets);
349
+
265
+ return test_sockets;
350
+static Property xram_ctrl_properties[] = {
266
+}
351
+ DEFINE_PROP_UINT64("size", XlnxXramCtrl, cfg.size, 1 * MiB),
267
+
352
+ DEFINE_PROP_END_OF_LIST(),
268
+static uint32_t emc_read(QTestState *qts, const EMCModule *mod,
353
+};
269
+ NPCM7xxPWMRegister regno)
354
+
270
+{
355
+static void xram_ctrl_class_init(ObjectClass *klass, void *data)
271
+ return qtest_readl(qts, mod->base_addr + regno * sizeof(uint32_t));
356
+{
272
+}
357
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
273
+
358
+ DeviceClass *dc = DEVICE_CLASS(klass);
274
+static void emc_write(QTestState *qts, const EMCModule *mod,
359
+
275
+ NPCM7xxPWMRegister regno, uint32_t value)
360
+ dc->realize = xram_ctrl_realize;
276
+{
361
+ dc->vmsd = &vmstate_xram_ctrl;
277
+ qtest_writel(qts, mod->base_addr + regno * sizeof(uint32_t), value);
362
+ device_class_set_props(dc, xram_ctrl_properties);
278
+}
363
+
279
+
364
+ rc->phases.enter = xram_ctrl_reset_enter;
280
+static void emc_read_tx_desc(QTestState *qts, uint32_t addr,
365
+ rc->phases.hold = xram_ctrl_reset_hold;
281
+ NPCM7xxEMCTxDesc *desc)
366
+}
282
+{
367
+
283
+ qtest_memread(qts, addr, desc, sizeof(*desc));
368
+static const TypeInfo xram_ctrl_info = {
284
+ desc->flags = le32_to_cpu(desc->flags);
369
+ .name = TYPE_XLNX_XRAM_CTRL,
285
+ desc->txbsa = le32_to_cpu(desc->txbsa);
370
+ .parent = TYPE_SYS_BUS_DEVICE,
286
+ desc->status_and_length = le32_to_cpu(desc->status_and_length);
371
+ .instance_size = sizeof(XlnxXramCtrl),
287
+ desc->ntxdsa = le32_to_cpu(desc->ntxdsa);
372
+ .class_init = xram_ctrl_class_init,
288
+}
373
+ .instance_init = xram_ctrl_init,
289
+
374
+ .instance_finalize = xram_ctrl_finalize,
290
+static void emc_write_tx_desc(QTestState *qts, const NPCM7xxEMCTxDesc *desc,
375
+};
291
+ uint32_t addr)
376
+
292
+{
377
+static void xram_ctrl_register_types(void)
293
+ NPCM7xxEMCTxDesc le_desc;
378
+{
294
+
379
+ type_register_static(&xram_ctrl_info);
295
+ le_desc.flags = cpu_to_le32(desc->flags);
380
+}
296
+ le_desc.txbsa = cpu_to_le32(desc->txbsa);
381
+
297
+ le_desc.status_and_length = cpu_to_le32(desc->status_and_length);
382
+type_init(xram_ctrl_register_types)
298
+ le_desc.ntxdsa = cpu_to_le32(desc->ntxdsa);
383
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
299
+ qtest_memwrite(qts, addr, &le_desc, sizeof(le_desc));
300
+}
301
+
302
+static void emc_read_rx_desc(QTestState *qts, uint32_t addr,
303
+ NPCM7xxEMCRxDesc *desc)
304
+{
305
+ qtest_memread(qts, addr, desc, sizeof(*desc));
306
+ desc->status_and_length = le32_to_cpu(desc->status_and_length);
307
+ desc->rxbsa = le32_to_cpu(desc->rxbsa);
308
+ desc->reserved = le32_to_cpu(desc->reserved);
309
+ desc->nrxdsa = le32_to_cpu(desc->nrxdsa);
310
+}
311
+
312
+static void emc_write_rx_desc(QTestState *qts, const NPCM7xxEMCRxDesc *desc,
313
+ uint32_t addr)
314
+{
315
+ NPCM7xxEMCRxDesc le_desc;
316
+
317
+ le_desc.status_and_length = cpu_to_le32(desc->status_and_length);
318
+ le_desc.rxbsa = cpu_to_le32(desc->rxbsa);
319
+ le_desc.reserved = cpu_to_le32(desc->reserved);
320
+ le_desc.nrxdsa = cpu_to_le32(desc->nrxdsa);
321
+ qtest_memwrite(qts, addr, &le_desc, sizeof(le_desc));
322
+}
323
+
324
+/*
325
+ * Reset the EMC module.
326
+ * The module must be reset before, e.g., TXDLSA,RXDLSA are changed.
327
+ */
328
+static bool emc_soft_reset(QTestState *qts, const EMCModule *mod)
329
+{
330
+ uint32_t val;
331
+ uint64_t end_time;
332
+
333
+ emc_write(qts, mod, REG_MCMDR, REG_MCMDR_SWR);
334
+
335
+ /*
336
+ * Wait for device to reset as the linux driver does.
337
+ * During reset the AHB reads 0 for all registers. So first wait for
338
+ * something that resets to non-zero, and then wait for SWR becoming 0.
339
+ */
340
+ end_time = g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
341
+
342
+ do {
343
+ qtest_clock_step(qts, 100);
344
+ val = emc_read(qts, mod, REG_FFTCR);
345
+ } while (val == 0 && g_get_monotonic_time() < end_time);
346
+ if (val != 0) {
347
+ do {
348
+ qtest_clock_step(qts, 100);
349
+ val = emc_read(qts, mod, REG_MCMDR);
350
+ if ((val & REG_MCMDR_SWR) == 0) {
351
+ /*
352
+ * N.B. The CAMs have been reset here, so macaddr matching of
353
+ * incoming packets will not work.
354
+ */
355
+ return true;
356
+ }
357
+ } while (g_get_monotonic_time() < end_time);
358
+ }
359
+
360
+ g_message("%s: Timeout expired", __func__);
361
+ return false;
362
+}
363
+
364
+/* Check emc registers are reset to default value. */
365
+static void test_init(gconstpointer test_data)
366
+{
367
+ const TestData *td = test_data;
368
+ const EMCModule *mod = td->module;
369
+ QTestState *qts = qtest_init("-machine quanta-gsj");
370
+ int i;
371
+
372
+#define CHECK_REG(regno, value) \
373
+ do { \
374
+ g_assert_cmphex(emc_read(qts, mod, (regno)), ==, (value)); \
375
+ } while (0)
376
+
377
+ CHECK_REG(REG_CAMCMR, 0);
378
+ CHECK_REG(REG_CAMEN, 0);
379
+ CHECK_REG(REG_TXDLSA, 0xfffffffc);
380
+ CHECK_REG(REG_RXDLSA, 0xfffffffc);
381
+ CHECK_REG(REG_MCMDR, 0);
382
+ CHECK_REG(REG_MIID, 0);
383
+ CHECK_REG(REG_MIIDA, 0x00900000);
384
+ CHECK_REG(REG_FFTCR, 0x0101);
385
+ CHECK_REG(REG_DMARFC, 0x0800);
386
+ CHECK_REG(REG_MIEN, 0);
387
+ CHECK_REG(REG_MISTA, 0);
388
+ CHECK_REG(REG_MGSTA, 0);
389
+ CHECK_REG(REG_MPCNT, 0x7fff);
390
+ CHECK_REG(REG_MRPC, 0);
391
+ CHECK_REG(REG_MRPCC, 0);
392
+ CHECK_REG(REG_MREPC, 0);
393
+ CHECK_REG(REG_DMARFS, 0);
394
+ CHECK_REG(REG_CTXDSA, 0);
395
+ CHECK_REG(REG_CTXBSA, 0);
396
+ CHECK_REG(REG_CRXDSA, 0);
397
+ CHECK_REG(REG_CRXBSA, 0);
398
+
399
+#undef CHECK_REG
400
+
401
+ for (i = 0; i < NUM_CAMML_REGS; ++i) {
402
+ g_assert_cmpuint(emc_read(qts, mod, REG_CAMM_BASE + i * 2), ==,
403
+ 0);
404
+ g_assert_cmpuint(emc_read(qts, mod, REG_CAML_BASE + i * 2), ==,
405
+ 0);
406
+ }
407
+
408
+ qtest_quit(qts);
409
+}
410
+
411
+static bool emc_wait_irq(QTestState *qts, const EMCModule *mod, int step,
412
+ bool is_tx)
413
+{
414
+ uint64_t end_time =
415
+ g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
416
+
417
+ do {
418
+ if (qtest_get_irq(qts, is_tx ? mod->tx_irq : mod->rx_irq)) {
419
+ return true;
420
+ }
421
+ qtest_clock_step(qts, step);
422
+ } while (g_get_monotonic_time() < end_time);
423
+
424
+ g_message("%s: Timeout expired", __func__);
425
+ return false;
426
+}
427
+
428
+static bool emc_wait_mista(QTestState *qts, const EMCModule *mod, int step,
429
+ uint32_t flag)
430
+{
431
+ uint64_t end_time =
432
+ g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
433
+
434
+ do {
435
+ uint32_t mista = emc_read(qts, mod, REG_MISTA);
436
+ if (mista & flag) {
437
+ return true;
438
+ }
439
+ qtest_clock_step(qts, step);
440
+ } while (g_get_monotonic_time() < end_time);
441
+
442
+ g_message("%s: Timeout expired", __func__);
443
+ return false;
444
+}
445
+
446
+static bool wait_socket_readable(int fd)
447
+{
448
+ fd_set read_fds;
449
+ struct timeval tv;
450
+ int rv;
451
+
452
+ FD_ZERO(&read_fds);
453
+ FD_SET(fd, &read_fds);
454
+ tv.tv_sec = TIMEOUT_SECONDS;
455
+ tv.tv_usec = 0;
456
+ rv = select(fd + 1, &read_fds, NULL, NULL, &tv);
457
+ if (rv == -1) {
458
+ perror("select");
459
+ } else if (rv == 0) {
460
+ g_message("%s: Timeout expired", __func__);
461
+ }
462
+ return rv == 1;
463
+}
464
+
465
+/* Initialize *desc (in host endian format). */
466
+static void init_tx_desc(NPCM7xxEMCTxDesc *desc, size_t count,
467
+ uint32_t desc_addr)
468
+{
469
+ g_assert(count >= 2);
470
+ memset(&desc[0], 0, sizeof(*desc) * count);
471
+ /* Leave the last one alone, owned by the cpu -> stops transmission. */
472
+ for (size_t i = 0; i < count - 1; ++i) {
473
+ desc[i].flags =
474
+ (TX_DESC_FLAG_OWNER_MASK | /* owner = 1: emc */
475
+ TX_DESC_FLAG_INTEN |
476
+ 0 | /* crc append = 0 */
477
+ 0 /* padding enable = 0 */);
478
+ desc[i].status_and_length =
479
+ (0 | /* collision count = 0 */
480
+ 0 | /* SQE = 0 */
481
+ 0 | /* PAU = 0 */
482
+ 0 | /* TXHA = 0 */
483
+ 0 | /* LC = 0 */
484
+ 0 | /* TXABT = 0 */
485
+ 0 | /* NCS = 0 */
486
+ 0 | /* EXDEF = 0 */
487
+ 0 | /* TXCP = 0 */
488
+ 0 | /* DEF = 0 */
489
+ 0 | /* TXINTR = 0 */
490
+ 0 /* length filled in later */);
491
+ desc[i].ntxdsa = desc_addr + (i + 1) * sizeof(*desc);
492
+ }
493
+}
494
+
495
+static void enable_tx(QTestState *qts, const EMCModule *mod,
496
+ const NPCM7xxEMCTxDesc *desc, size_t count,
497
+ uint32_t desc_addr, uint32_t mien_flags)
498
+{
499
+ /* Write the descriptors to guest memory. */
500
+ for (size_t i = 0; i < count; ++i) {
501
+ emc_write_tx_desc(qts, desc + i, desc_addr + i * sizeof(*desc));
502
+ }
503
+
504
+ /* Trigger sending the packet. */
505
+ /* The module must be reset before changing TXDLSA. */
506
+ g_assert(emc_soft_reset(qts, mod));
507
+ emc_write(qts, mod, REG_TXDLSA, desc_addr);
508
+ emc_write(qts, mod, REG_CTXDSA, ~0);
509
+ emc_write(qts, mod, REG_MIEN, REG_MIEN_ENTXCP | mien_flags);
510
+ {
511
+ uint32_t mcmdr = emc_read(qts, mod, REG_MCMDR);
512
+ mcmdr |= REG_MCMDR_TXON;
513
+ emc_write(qts, mod, REG_MCMDR, mcmdr);
514
+ }
515
+
516
+ /* Prod the device to send the packet. */
517
+ emc_write(qts, mod, REG_TSDR, 1);
518
+}
519
+
520
+static void emc_send_verify1(QTestState *qts, const EMCModule *mod, int fd,
521
+ bool with_irq, uint32_t desc_addr,
522
+ uint32_t next_desc_addr,
523
+ const char *test_data, int test_size)
524
+{
525
+ NPCM7xxEMCTxDesc result_desc;
526
+ uint32_t expected_mask, expected_value, recv_len;
527
+ int ret;
528
+ char buffer[TX_DATA_LEN];
529
+
530
+ g_assert(wait_socket_readable(fd));
531
+
532
+ /* Read the descriptor back. */
533
+ emc_read_tx_desc(qts, desc_addr, &result_desc);
534
+ /* Descriptor should be owned by cpu now. */
535
+ g_assert((result_desc.flags & TX_DESC_FLAG_OWNER_MASK) == 0);
536
+ /* Test the status bits, ignoring the length field. */
537
+ expected_mask = 0xffff << 16;
538
+ expected_value = TX_DESC_STATUS_TXCP;
539
+ if (with_irq) {
540
+ expected_value |= TX_DESC_STATUS_TXINTR;
541
+ }
542
+ g_assert_cmphex((result_desc.status_and_length & expected_mask), ==,
543
+ expected_value);
544
+
545
+ /* Check data sent to the backend. */
546
+ recv_len = ~0;
547
+ ret = qemu_recv(fd, &recv_len, sizeof(recv_len), MSG_DONTWAIT);
548
+ g_assert_cmpint(ret, == , sizeof(recv_len));
549
+
550
+ g_assert(wait_socket_readable(fd));
551
+ memset(buffer, 0xff, sizeof(buffer));
552
+ ret = qemu_recv(fd, buffer, test_size, MSG_DONTWAIT);
553
+ g_assert_cmpmem(buffer, ret, test_data, test_size);
554
+}
555
+
556
+static void emc_send_verify(QTestState *qts, const EMCModule *mod, int fd,
557
+ bool with_irq)
558
+{
559
+ NPCM7xxEMCTxDesc desc[NUM_TX_DESCRIPTORS];
560
+ uint32_t desc_addr = DESC_ADDR;
561
+ static const char test1_data[] = "TEST1";
562
+ static const char test2_data[] = "Testing 1 2 3 ...";
563
+ uint32_t data1_addr = DATA_ADDR;
564
+ uint32_t data2_addr = data1_addr + sizeof(test1_data);
565
+ bool got_tdu;
566
+ uint32_t end_desc_addr;
567
+
568
+ /* Prepare test data buffer. */
569
+ qtest_memwrite(qts, data1_addr, test1_data, sizeof(test1_data));
570
+ qtest_memwrite(qts, data2_addr, test2_data, sizeof(test2_data));
571
+
572
+ init_tx_desc(&desc[0], NUM_TX_DESCRIPTORS, desc_addr);
573
+ desc[0].txbsa = data1_addr;
574
+ desc[0].status_and_length |= sizeof(test1_data);
575
+ desc[1].txbsa = data2_addr;
576
+ desc[1].status_and_length |= sizeof(test2_data);
577
+
578
+ enable_tx(qts, mod, &desc[0], NUM_TX_DESCRIPTORS, desc_addr,
579
+ with_irq ? REG_MIEN_ENTXINTR : 0);
580
+
581
+ /*
582
+ * It's problematic to observe the interrupt for each packet.
583
+ * Instead just wait until all the packets go out.
584
+ */
585
+ got_tdu = false;
586
+ while (!got_tdu) {
587
+ if (with_irq) {
588
+ g_assert_true(emc_wait_irq(qts, mod, TX_STEP_COUNT,
589
+ /*is_tx=*/true));
590
+ } else {
591
+ g_assert_true(emc_wait_mista(qts, mod, TX_STEP_COUNT,
592
+ REG_MISTA_TXINTR));
593
+ }
594
+ got_tdu = !!(emc_read(qts, mod, REG_MISTA) & REG_MISTA_TDU);
595
+ /* If we don't have TDU yet, reset the interrupt. */
596
+ if (!got_tdu) {
597
+ emc_write(qts, mod, REG_MISTA,
598
+ emc_read(qts, mod, REG_MISTA) & 0xffff0000);
599
+ }
600
+ }
601
+
602
+ end_desc_addr = desc_addr + 2 * sizeof(desc[0]);
603
+ g_assert_cmphex(emc_read(qts, mod, REG_CTXDSA), ==, end_desc_addr);
604
+ g_assert_cmphex(emc_read(qts, mod, REG_MISTA), ==,
605
+ REG_MISTA_TXCP | REG_MISTA_TXINTR | REG_MISTA_TDU);
606
+
607
+ emc_send_verify1(qts, mod, fd, with_irq,
608
+ desc_addr, end_desc_addr,
609
+ test1_data, sizeof(test1_data));
610
+ emc_send_verify1(qts, mod, fd, with_irq,
611
+ desc_addr + sizeof(desc[0]), end_desc_addr,
612
+ test2_data, sizeof(test2_data));
613
+}
614
+
615
+/* Initialize *desc (in host endian format). */
616
+static void init_rx_desc(NPCM7xxEMCRxDesc *desc, size_t count,
617
+ uint32_t desc_addr, uint32_t data_addr)
618
+{
619
+ g_assert_true(count >= 2);
620
+ memset(desc, 0, sizeof(*desc) * count);
621
+ desc[0].rxbsa = data_addr;
622
+ desc[0].status_and_length =
623
+ (0b10 << RX_DESC_STATUS_OWNER_SHIFT | /* owner = 10: emc */
624
+ 0 | /* RP = 0 */
625
+ 0 | /* ALIE = 0 */
626
+ 0 | /* RXGD = 0 */
627
+ 0 | /* PTLE = 0 */
628
+ 0 | /* CRCE = 0 */
629
+ 0 | /* RXINTR = 0 */
630
+ 0 /* length (filled in later) */);
631
+ /* Leave the last one alone, owned by the cpu -> stops transmission. */
632
+ desc[0].nrxdsa = desc_addr + sizeof(*desc);
633
+}
634
+
635
+static void enable_rx(QTestState *qts, const EMCModule *mod,
636
+ const NPCM7xxEMCRxDesc *desc, size_t count,
637
+ uint32_t desc_addr, uint32_t mien_flags,
638
+ uint32_t mcmdr_flags)
639
+{
640
+ /*
641
+ * Write the descriptor to guest memory.
642
+ * FWIW, IWBN if the docs said the buffer needs to be at least DMARFC
643
+ * bytes.
644
+ */
645
+ for (size_t i = 0; i < count; ++i) {
646
+ emc_write_rx_desc(qts, desc + i, desc_addr + i * sizeof(*desc));
647
+ }
648
+
649
+ /* Trigger receiving the packet. */
650
+ /* The module must be reset before changing RXDLSA. */
651
+ g_assert(emc_soft_reset(qts, mod));
652
+ emc_write(qts, mod, REG_RXDLSA, desc_addr);
653
+ emc_write(qts, mod, REG_MIEN, REG_MIEN_ENRXGD | mien_flags);
654
+
655
+ /*
656
+ * We don't know what the device's macaddr is, so just accept all
657
+ * unicast packets (AUP).
658
+ */
659
+ emc_write(qts, mod, REG_CAMCMR, REG_CAMCMR_AUP);
660
+ emc_write(qts, mod, REG_CAMEN, 1 << 0);
661
+ {
662
+ uint32_t mcmdr = emc_read(qts, mod, REG_MCMDR);
663
+ mcmdr |= REG_MCMDR_RXON | mcmdr_flags;
664
+ emc_write(qts, mod, REG_MCMDR, mcmdr);
665
+ }
666
+
667
+ /* Prod the device to accept a packet. */
668
+ emc_write(qts, mod, REG_RSDR, 1);
669
+}
670
+
671
+static void emc_recv_verify(QTestState *qts, const EMCModule *mod, int fd,
672
+ bool with_irq)
673
+{
674
+ NPCM7xxEMCRxDesc desc[NUM_RX_DESCRIPTORS];
675
+ uint32_t desc_addr = DESC_ADDR;
676
+ uint32_t data_addr = DATA_ADDR;
677
+ int ret;
678
+ uint32_t expected_mask, expected_value;
679
+ NPCM7xxEMCRxDesc result_desc;
680
+
681
+ /* Prepare test data buffer. */
682
+ const char test[RX_DATA_LEN] = "TEST";
683
+ int len = htonl(sizeof(test));
684
+ const struct iovec iov[] = {
685
+ {
686
+ .iov_base = &len,
687
+ .iov_len = sizeof(len),
688
+ },{
689
+ .iov_base = (char *) test,
690
+ .iov_len = sizeof(test),
691
+ },
692
+ };
693
+
694
+ /*
695
+ * Reset the device BEFORE sending a test packet, otherwise the packet
696
+ * may get swallowed by an active device of an earlier test.
697
+ */
698
+ init_rx_desc(&desc[0], NUM_RX_DESCRIPTORS, desc_addr, data_addr);
699
+ enable_rx(qts, mod, &desc[0], NUM_RX_DESCRIPTORS, desc_addr,
700
+ with_irq ? REG_MIEN_ENRXINTR : 0, 0);
701
+
702
+ /* Send test packet to device's socket. */
703
+ ret = iov_send(fd, iov, 2, 0, sizeof(len) + sizeof(test));
704
+ g_assert_cmpint(ret, == , sizeof(test) + sizeof(len));
705
+
706
+ /* Wait for RX interrupt. */
707
+ if (with_irq) {
708
+ g_assert_true(emc_wait_irq(qts, mod, RX_STEP_COUNT, /*is_tx=*/false));
709
+ } else {
710
+ g_assert_true(emc_wait_mista(qts, mod, RX_STEP_COUNT, REG_MISTA_RXGD));
711
+ }
712
+
713
+ g_assert_cmphex(emc_read(qts, mod, REG_CRXDSA), ==,
714
+ desc_addr + sizeof(desc[0]));
715
+
716
+ expected_mask = 0xffff;
717
+ expected_value = (REG_MISTA_DENI |
718
+ REG_MISTA_RXGD |
719
+ REG_MISTA_RXINTR);
720
+ g_assert_cmphex((emc_read(qts, mod, REG_MISTA) & expected_mask),
721
+ ==, expected_value);
722
+
723
+ /* Read the descriptor back. */
724
+ emc_read_rx_desc(qts, desc_addr, &result_desc);
725
+ /* Descriptor should be owned by cpu now. */
726
+ g_assert((result_desc.status_and_length & RX_DESC_STATUS_OWNER_MASK) == 0);
727
+ /* Test the status bits, ignoring the length field. */
728
+ expected_mask = 0xffff << 16;
729
+ expected_value = RX_DESC_STATUS_RXGD;
730
+ if (with_irq) {
731
+ expected_value |= RX_DESC_STATUS_RXINTR;
732
+ }
733
+ g_assert_cmphex((result_desc.status_and_length & expected_mask), ==,
734
+ expected_value);
735
+ g_assert_cmpint(RX_DESC_PKT_LEN(result_desc.status_and_length), ==,
736
+ RX_DATA_LEN + CRC_LENGTH);
737
+
738
+ {
739
+ char buffer[RX_DATA_LEN];
740
+ qtest_memread(qts, data_addr, buffer, sizeof(buffer));
741
+ g_assert_cmpstr(buffer, == , "TEST");
742
+ }
743
+}
744
+
745
+static void emc_test_ptle(QTestState *qts, const EMCModule *mod, int fd)
746
+{
747
+ NPCM7xxEMCRxDesc desc[NUM_RX_DESCRIPTORS];
748
+ uint32_t desc_addr = DESC_ADDR;
749
+ uint32_t data_addr = DATA_ADDR;
750
+ int ret;
751
+ NPCM7xxEMCRxDesc result_desc;
752
+ uint32_t expected_mask, expected_value;
753
+
754
+ /* Prepare test data buffer. */
755
+#define PTLE_DATA_LEN 1600
756
+ char test_data[PTLE_DATA_LEN];
757
+ int len = htonl(sizeof(test_data));
758
+ const struct iovec iov[] = {
759
+ {
760
+ .iov_base = &len,
761
+ .iov_len = sizeof(len),
762
+ },{
763
+ .iov_base = (char *) test_data,
764
+ .iov_len = sizeof(test_data),
765
+ },
766
+ };
767
+ memset(test_data, 42, sizeof(test_data));
768
+
769
+ /*
770
+ * Reset the device BEFORE sending a test packet, otherwise the packet
771
+ * may get swallowed by an active device of an earlier test.
772
+ */
773
+ init_rx_desc(&desc[0], NUM_RX_DESCRIPTORS, desc_addr, data_addr);
774
+ enable_rx(qts, mod, &desc[0], NUM_RX_DESCRIPTORS, desc_addr,
775
+ REG_MIEN_ENRXINTR, REG_MCMDR_ALP);
776
+
777
+ /* Send test packet to device's socket. */
778
+ ret = iov_send(fd, iov, 2, 0, sizeof(len) + sizeof(test_data));
779
+ g_assert_cmpint(ret, == , sizeof(test_data) + sizeof(len));
780
+
781
+ /* Wait for RX interrupt. */
782
+ g_assert_true(emc_wait_irq(qts, mod, RX_STEP_COUNT, /*is_tx=*/false));
783
+
784
+ /* Read the descriptor back. */
785
+ emc_read_rx_desc(qts, desc_addr, &result_desc);
786
+ /* Descriptor should be owned by cpu now. */
787
+ g_assert((result_desc.status_and_length & RX_DESC_STATUS_OWNER_MASK) == 0);
788
+ /* Test the status bits, ignoring the length field. */
789
+ expected_mask = 0xffff << 16;
790
+ expected_value = (RX_DESC_STATUS_RXGD |
791
+ RX_DESC_STATUS_PTLE |
792
+ RX_DESC_STATUS_RXINTR);
793
+ g_assert_cmphex((result_desc.status_and_length & expected_mask), ==,
794
+ expected_value);
795
+ g_assert_cmpint(RX_DESC_PKT_LEN(result_desc.status_and_length), ==,
796
+ PTLE_DATA_LEN + CRC_LENGTH);
797
+
798
+ {
799
+ char buffer[PTLE_DATA_LEN];
800
+ qtest_memread(qts, data_addr, buffer, sizeof(buffer));
801
+ g_assert(memcmp(buffer, test_data, PTLE_DATA_LEN) == 0);
802
+ }
803
+}
804
+
805
+static void test_tx(gconstpointer test_data)
806
+{
807
+ const TestData *td = test_data;
808
+ GString *cmd_line = g_string_new("-machine quanta-gsj");
809
+ int *test_sockets = packet_test_init(emc_module_index(td->module),
810
+ cmd_line);
811
+ QTestState *qts = qtest_init(cmd_line->str);
812
+
813
+ /*
814
+ * TODO: For pedantic correctness test_sockets[0] should be closed after
815
+ * the fork and before the exec, but that will require some harness
816
+ * improvements.
817
+ */
818
+ close(test_sockets[1]);
819
+ /* Defensive programming */
820
+ test_sockets[1] = -1;
821
+
822
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
823
+
824
+ emc_send_verify(qts, td->module, test_sockets[0], /*with_irq=*/false);
825
+ emc_send_verify(qts, td->module, test_sockets[0], /*with_irq=*/true);
826
+
827
+ qtest_quit(qts);
828
+}
829
+
830
+static void test_rx(gconstpointer test_data)
831
+{
832
+ const TestData *td = test_data;
833
+ GString *cmd_line = g_string_new("-machine quanta-gsj");
834
+ int *test_sockets = packet_test_init(emc_module_index(td->module),
835
+ cmd_line);
836
+ QTestState *qts = qtest_init(cmd_line->str);
837
+
838
+ /*
839
+ * TODO: For pedantic correctness test_sockets[0] should be closed after
840
+ * the fork and before the exec, but that will require some harness
841
+ * improvements.
842
+ */
843
+ close(test_sockets[1]);
844
+ /* Defensive programming */
845
+ test_sockets[1] = -1;
846
+
847
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
848
+
849
+ emc_recv_verify(qts, td->module, test_sockets[0], /*with_irq=*/false);
850
+ emc_recv_verify(qts, td->module, test_sockets[0], /*with_irq=*/true);
851
+ emc_test_ptle(qts, td->module, test_sockets[0]);
852
+
853
+ qtest_quit(qts);
854
+}
855
+
856
+static void emc_add_test(const char *name, const TestData* td,
857
+ GTestDataFunc fn)
858
+{
859
+ g_autofree char *full_name = g_strdup_printf(
860
+ "npcm7xx_emc/emc[%d]/%s", emc_module_index(td->module), name);
861
+ qtest_add_data_func(full_name, td, fn);
862
+}
863
+#define add_test(name, td) emc_add_test(#name, td, test_##name)
864
+
865
+int main(int argc, char **argv)
866
+{
867
+ TestData test_data_list[ARRAY_SIZE(emc_module_list)];
868
+
869
+ g_test_init(&argc, &argv, NULL);
870
+
871
+ for (int i = 0; i < ARRAY_SIZE(emc_module_list); ++i) {
872
+ TestData *td = &test_data_list[i];
873
+
874
+ td->module = &emc_module_list[i];
875
+
876
+ add_test(init, td);
877
+ add_test(tx, td);
878
+ add_test(rx, td);
879
+ }
880
+
881
+ return g_test_run();
882
+}
883
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
884
index XXXXXXX..XXXXXXX 100644
384
index XXXXXXX..XXXXXXX 100644
885
--- a/tests/qtest/meson.build
385
--- a/hw/misc/meson.build
886
+++ b/tests/qtest/meson.build
386
+++ b/hw/misc/meson.build
887
@@ -XXX,XX +XXX,XX @@ qtests_npcm7xx = \
387
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files(
888
'npcm7xx_rng-test',
388
))
889
'npcm7xx_smbus-test',
389
softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c'))
890
'npcm7xx_timer-test',
390
softmmu_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c', 'zynq-xadc.c'))
891
- 'npcm7xx_watchdog_timer-test']
391
+softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-xramc.c'))
892
+ 'npcm7xx_watchdog_timer-test'] + \
392
softmmu_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.c'))
893
+ (slirp.found() ? ['npcm7xx_emc-test'] : [])
393
softmmu_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.c'))
894
qtests_arm = \
394
softmmu_ss.add(when: 'CONFIG_STM32F4XX_EXTI', if_true: files('stm32f4xx_exti.c'))
895
(config_all_devices.has_key('CONFIG_CMSDK_APB_DUALTIMER') ? ['cmsdk-apb-dualtimer-test'] : []) + \
896
(config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-timer-test'] : []) + \
897
--
395
--
898
2.20.1
396
2.20.1
899
397
900
398
diff view generated by jsdifflib
1
Update old infocenter.arm.com URLs to the equivalent developer.arm.com
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
ones (the old URLs should redirect, but we might as well avoid the
3
redirection notice, and the new URLs are pleasantly shorter).
4
2
5
This commit covers the links to the MPS2 board TRM, the various
3
Connect the support for the Versal Accelerator RAMs (XRAMs).
6
Application Notes, the IoTKit and SSE-200 documents.
7
4
5
Reviewed-by: Luc Michel <luc@lmichel.fr>
6
Acked-by: Alistair Francis <alistair.francis@wdc.com>
7
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Message-id: 20210308224637.2949533-3-edgar.iglesias@gmail.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210215115138.20465-25-peter.maydell@linaro.org
11
---
10
---
12
include/hw/arm/armsse.h | 4 ++--
11
docs/system/arm/xlnx-versal-virt.rst | 1 +
13
include/hw/misc/armsse-cpuid.h | 2 +-
12
include/hw/arm/xlnx-versal.h | 13 ++++++++++
14
include/hw/misc/armsse-mhu.h | 2 +-
13
hw/arm/xlnx-versal.c | 36 ++++++++++++++++++++++++++++
15
include/hw/misc/iotkit-secctl.h | 2 +-
14
3 files changed, 50 insertions(+)
16
include/hw/misc/iotkit-sysctl.h | 2 +-
17
include/hw/misc/iotkit-sysinfo.h | 2 +-
18
include/hw/misc/mps2-fpgaio.h | 2 +-
19
hw/arm/mps2-tz.c | 11 +++++------
20
hw/misc/armsse-cpuid.c | 2 +-
21
hw/misc/armsse-mhu.c | 2 +-
22
hw/misc/iotkit-sysctl.c | 2 +-
23
hw/misc/iotkit-sysinfo.c | 2 +-
24
hw/misc/mps2-fpgaio.c | 2 +-
25
hw/misc/mps2-scc.c | 2 +-
26
14 files changed, 19 insertions(+), 20 deletions(-)
27
15
28
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
16
diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-versal-virt.rst
29
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
30
--- a/include/hw/arm/armsse.h
18
--- a/docs/system/arm/xlnx-versal-virt.rst
31
+++ b/include/hw/arm/armsse.h
19
+++ b/docs/system/arm/xlnx-versal-virt.rst
20
@@ -XXX,XX +XXX,XX @@ Implemented devices:
21
- 8 ADMA (Xilinx zDMA) channels
22
- 2 SD Controllers
23
- OCM (256KB of On Chip Memory)
24
+- XRAM (4MB of on chip Accelerator RAM)
25
- DDR memory
26
27
QEMU does not yet model any other devices, including the PL and the AI Engine.
28
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/include/hw/arm/xlnx-versal.h
31
+++ b/include/hw/arm/xlnx-versal.h
32
@@ -XXX,XX +XXX,XX @@
32
@@ -XXX,XX +XXX,XX @@
33
* hardware, which include the IoT Kit and the SSE-050, SSE-100 and
33
34
* SSE-200. Currently we model:
34
#include "hw/sysbus.h"
35
* - the Arm IoT Kit which is documented in
35
#include "hw/arm/boot.h"
36
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
36
+#include "hw/or-irq.h"
37
+ * https://developer.arm.com/documentation/ecm0601256/latest
37
#include "hw/sd/sdhci.h"
38
* - the SSE-200 which is documented in
38
#include "hw/intc/arm_gicv3.h"
39
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
39
#include "hw/char/pl011.h"
40
+ * https://developer.arm.com/documentation/101104/latest/
40
@@ -XXX,XX +XXX,XX @@
41
*
41
#include "hw/rtc/xlnx-zynqmp-rtc.h"
42
* The IoTKit contains:
42
#include "qom/object.h"
43
* a Cortex-M33
43
#include "hw/usb/xlnx-usb-subsystem.h"
44
diff --git a/include/hw/misc/armsse-cpuid.h b/include/hw/misc/armsse-cpuid.h
44
+#include "hw/misc/xlnx-versal-xramc.h"
45
46
#define TYPE_XLNX_VERSAL "xlnx-versal"
47
OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
48
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
49
#define XLNX_VERSAL_NR_GEMS 2
50
#define XLNX_VERSAL_NR_ADMAS 8
51
#define XLNX_VERSAL_NR_SDS 2
52
+#define XLNX_VERSAL_NR_XRAM 4
53
#define XLNX_VERSAL_NR_IRQS 192
54
55
struct Versal {
56
@@ -XXX,XX +XXX,XX @@ struct Versal {
57
XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS];
58
VersalUsb2 usb;
59
} iou;
60
+
61
+ struct {
62
+ qemu_or_irq irq_orgate;
63
+ XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM];
64
+ } xram;
65
} lpd;
66
67
/* The Platform Management Controller subsystem. */
68
@@ -XXX,XX +XXX,XX @@ struct Versal {
69
#define VERSAL_GEM1_IRQ_0 58
70
#define VERSAL_GEM1_WAKE_IRQ_0 59
71
#define VERSAL_ADMA_IRQ_0 60
72
+#define VERSAL_XRAM_IRQ_0 79
73
#define VERSAL_RTC_APB_ERR_IRQ 121
74
#define VERSAL_SD0_IRQ_0 126
75
#define VERSAL_RTC_ALARM_IRQ 142
76
@@ -XXX,XX +XXX,XX @@ struct Versal {
77
#define MM_OCM 0xfffc0000U
78
#define MM_OCM_SIZE 0x40000
79
80
+#define MM_XRAM 0xfe800000
81
+#define MM_XRAMC 0xff8e0000
82
+#define MM_XRAMC_SIZE 0x10000
83
+
84
#define MM_USB2_CTRL_REGS 0xFF9D0000
85
#define MM_USB2_CTRL_REGS_SIZE 0x10000
86
87
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
45
index XXXXXXX..XXXXXXX 100644
88
index XXXXXXX..XXXXXXX 100644
46
--- a/include/hw/misc/armsse-cpuid.h
89
--- a/hw/arm/xlnx-versal.c
47
+++ b/include/hw/misc/armsse-cpuid.h
90
+++ b/hw/arm/xlnx-versal.c
48
@@ -XXX,XX +XXX,XX @@
91
@@ -XXX,XX +XXX,XX @@
49
/*
50
* This is a model of the "CPU_IDENTITY" register block which is part of the
51
* Arm SSE-200 and documented in
52
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
53
+ * https://developer.arm.com/documentation/101104/latest/
54
*
55
* QEMU interface:
56
* + QOM property "CPUID": the value to use for the CPUID register
57
diff --git a/include/hw/misc/armsse-mhu.h b/include/hw/misc/armsse-mhu.h
58
index XXXXXXX..XXXXXXX 100644
59
--- a/include/hw/misc/armsse-mhu.h
60
+++ b/include/hw/misc/armsse-mhu.h
61
@@ -XXX,XX +XXX,XX @@
62
/*
63
* This is a model of the Message Handling Unit (MHU) which is part of the
64
* Arm SSE-200 and documented in
65
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
66
+ * https://developer.arm.com/documentation/101104/latest/
67
*
68
* QEMU interface:
69
* + sysbus MMIO region 0: the system information register bank
70
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
71
index XXXXXXX..XXXXXXX 100644
72
--- a/include/hw/misc/iotkit-secctl.h
73
+++ b/include/hw/misc/iotkit-secctl.h
74
@@ -XXX,XX +XXX,XX @@
75
76
/* This is a model of the security controller which is part of the
77
* Arm IoT Kit and documented in
78
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
79
+ * https://developer.arm.com/documentation/ecm0601256/latest
80
*
81
* QEMU interface:
82
* + sysbus MMIO region 0 is the "secure privilege control block" registers
83
diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
84
index XXXXXXX..XXXXXXX 100644
85
--- a/include/hw/misc/iotkit-sysctl.h
86
+++ b/include/hw/misc/iotkit-sysctl.h
87
@@ -XXX,XX +XXX,XX @@
88
/*
89
* This is a model of the "system control element" which is part of the
90
* Arm IoTKit and documented in
91
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
92
+ * https://developer.arm.com/documentation/ecm0601256/latest
93
* Specifically, it implements the "system information block" and
94
* "system control register" blocks.
95
*
96
diff --git a/include/hw/misc/iotkit-sysinfo.h b/include/hw/misc/iotkit-sysinfo.h
97
index XXXXXXX..XXXXXXX 100644
98
--- a/include/hw/misc/iotkit-sysinfo.h
99
+++ b/include/hw/misc/iotkit-sysinfo.h
100
@@ -XXX,XX +XXX,XX @@
101
/*
102
* This is a model of the "system information block" which is part of the
103
* Arm IoTKit and documented in
104
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
105
+ * https://developer.arm.com/documentation/ecm0601256/latest
106
* QEMU interface:
107
* + QOM property "SYS_VERSION": value to use for SYS_VERSION register
108
* + QOM property "SYS_CONFIG": value to use for SYS_CONFIG register
109
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
110
index XXXXXXX..XXXXXXX 100644
111
--- a/include/hw/misc/mps2-fpgaio.h
112
+++ b/include/hw/misc/mps2-fpgaio.h
113
@@ -XXX,XX +XXX,XX @@
114
/* This is a model of the FPGAIO register block in the AN505
115
* FPGA image for the MPS2 dev board; it is documented in the
116
* application note:
117
- * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
118
+ * https://developer.arm.com/documentation/dai0505/latest/
119
*
120
* QEMU interface:
121
* + sysbus MMIO region 0: the register bank
122
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
123
index XXXXXXX..XXXXXXX 100644
124
--- a/hw/arm/mps2-tz.c
125
+++ b/hw/arm/mps2-tz.c
126
@@ -XXX,XX +XXX,XX @@
127
* https://developer.arm.com/products/system-design/development-boards/fpga-prototyping-boards/mps2
128
*
129
* Board TRM:
130
- * http://infocenter.arm.com/help/topic/com.arm.doc.100112_0200_06_en/versatile_express_cortex_m_prototyping_systems_v2m_mps2_and_v2m_mps2plus_technical_reference_100112_0200_06_en.pdf
131
+ * https://developer.arm.com/documentation/100112/latest/
132
* Application Note AN505:
133
- * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
134
+ * https://developer.arm.com/documentation/dai0505/latest/
135
* Application Note AN521:
136
- * http://infocenter.arm.com/help/topic/com.arm.doc.dai0521c/index.html
137
+ * https://developer.arm.com/documentation/dai0521/latest/
138
* Application Note AN524:
139
* https://developer.arm.com/documentation/dai0524/latest/
140
*
141
* The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
142
* (ARM ECM0601256) for the details of some of the device layout:
143
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
144
+ * https://developer.arm.com/documentation/ecm0601256/latest
145
* Similarly, the AN521 and AN524 use the SSE-200, and the SSE-200 TRM defines
146
* most of the device layout:
147
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
148
- *
149
+ * https://developer.arm.com/documentation/101104/latest/
150
*/
92
*/
151
93
152
#include "qemu/osdep.h"
94
#include "qemu/osdep.h"
153
diff --git a/hw/misc/armsse-cpuid.c b/hw/misc/armsse-cpuid.c
95
+#include "qemu/units.h"
154
index XXXXXXX..XXXXXXX 100644
96
#include "qapi/error.h"
155
--- a/hw/misc/armsse-cpuid.c
97
#include "qemu/log.h"
156
+++ b/hw/misc/armsse-cpuid.c
98
#include "qemu/module.h"
157
@@ -XXX,XX +XXX,XX @@
99
@@ -XXX,XX +XXX,XX @@ static void versal_create_rtc(Versal *s, qemu_irq *pic)
158
/*
100
sysbus_connect_irq(sbd, 1, pic[VERSAL_RTC_APB_ERR_IRQ]);
159
* This is a model of the "CPU_IDENTITY" register block which is part of the
101
}
160
* Arm SSE-200 and documented in
102
161
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
103
+static void versal_create_xrams(Versal *s, qemu_irq *pic)
162
+ * https://developer.arm.com/documentation/101104/latest/
104
+{
163
*
105
+ int nr_xrams = ARRAY_SIZE(s->lpd.xram.ctrl);
164
* It consists of one read-only CPUID register (set by QOM property), plus the
106
+ DeviceState *orgate;
165
* usual ID registers.
107
+ int i;
166
diff --git a/hw/misc/armsse-mhu.c b/hw/misc/armsse-mhu.c
108
+
167
index XXXXXXX..XXXXXXX 100644
109
+ /* XRAM IRQs get ORed into a single line. */
168
--- a/hw/misc/armsse-mhu.c
110
+ object_initialize_child(OBJECT(s), "xram-irq-orgate",
169
+++ b/hw/misc/armsse-mhu.c
111
+ &s->lpd.xram.irq_orgate, TYPE_OR_IRQ);
170
@@ -XXX,XX +XXX,XX @@
112
+ orgate = DEVICE(&s->lpd.xram.irq_orgate);
171
/*
113
+ object_property_set_int(OBJECT(orgate),
172
* This is a model of the Message Handling Unit (MHU) which is part of the
114
+ "num-lines", nr_xrams, &error_fatal);
173
* Arm SSE-200 and documented in
115
+ qdev_realize(orgate, NULL, &error_fatal);
174
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
116
+ qdev_connect_gpio_out(orgate, 0, pic[VERSAL_XRAM_IRQ_0]);
175
+ * https://developer.arm.com/documentation/101104/latest/
117
+
118
+ for (i = 0; i < ARRAY_SIZE(s->lpd.xram.ctrl); i++) {
119
+ SysBusDevice *sbd;
120
+ MemoryRegion *mr;
121
+
122
+ object_initialize_child(OBJECT(s), "xram[*]", &s->lpd.xram.ctrl[i],
123
+ TYPE_XLNX_XRAM_CTRL);
124
+ sbd = SYS_BUS_DEVICE(&s->lpd.xram.ctrl[i]);
125
+ sysbus_realize(sbd, &error_fatal);
126
+
127
+ mr = sysbus_mmio_get_region(sbd, 0);
128
+ memory_region_add_subregion(&s->mr_ps,
129
+ MM_XRAMC + i * MM_XRAMC_SIZE, mr);
130
+ mr = sysbus_mmio_get_region(sbd, 1);
131
+ memory_region_add_subregion(&s->mr_ps, MM_XRAM + i * MiB, mr);
132
+
133
+ sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(orgate, i));
134
+ }
135
+}
136
+
137
/* This takes the board allocated linear DDR memory and creates aliases
138
* for each split DDR range/aperture on the Versal address map.
176
*/
139
*/
177
140
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
178
#include "qemu/osdep.h"
141
versal_create_admas(s, pic);
179
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
142
versal_create_sds(s, pic);
180
index XXXXXXX..XXXXXXX 100644
143
versal_create_rtc(s, pic);
181
--- a/hw/misc/iotkit-sysctl.c
144
+ versal_create_xrams(s, pic);
182
+++ b/hw/misc/iotkit-sysctl.c
145
versal_map_ddr(s);
183
@@ -XXX,XX +XXX,XX @@
146
versal_unimp(s);
184
/*
185
* This is a model of the "system control element" which is part of the
186
* Arm IoTKit and documented in
187
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
188
+ * https://developer.arm.com/documentation/ecm0601256/latest
189
* Specifically, it implements the "system control register" blocks.
190
*/
191
192
diff --git a/hw/misc/iotkit-sysinfo.c b/hw/misc/iotkit-sysinfo.c
193
index XXXXXXX..XXXXXXX 100644
194
--- a/hw/misc/iotkit-sysinfo.c
195
+++ b/hw/misc/iotkit-sysinfo.c
196
@@ -XXX,XX +XXX,XX @@
197
/*
198
* This is a model of the "system information block" which is part of the
199
* Arm IoTKit and documented in
200
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
201
+ * https://developer.arm.com/documentation/ecm0601256/latest
202
* It consists of 2 read-only version/config registers, plus the
203
* usual ID registers.
204
*/
205
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
206
index XXXXXXX..XXXXXXX 100644
207
--- a/hw/misc/mps2-fpgaio.c
208
+++ b/hw/misc/mps2-fpgaio.c
209
@@ -XXX,XX +XXX,XX @@
210
/* This is a model of the "FPGA system control and I/O" block found
211
* in the AN505 FPGA image for the MPS2 devboard.
212
* It is documented in AN505:
213
- * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
214
+ * https://developer.arm.com/documentation/dai0505/latest/
215
*/
216
217
#include "qemu/osdep.h"
218
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
219
index XXXXXXX..XXXXXXX 100644
220
--- a/hw/misc/mps2-scc.c
221
+++ b/hw/misc/mps2-scc.c
222
@@ -XXX,XX +XXX,XX @@
223
* found in the FPGA images of MPS2 development boards.
224
*
225
* Documentation of it can be found in the MPS2 TRM:
226
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.100112_0100_03_en/index.html
227
+ * https://developer.arm.com/documentation/100112/latest/
228
* and also in the Application Notes documenting individual FPGA images.
229
*/
230
147
231
--
148
--
232
2.20.1
149
2.20.1
233
150
234
151
diff view generated by jsdifflib
1
Currently the MPS2 SCC device implements a fixed number of OSCCLK
1
From: Eric Auger <eric.auger@redhat.com>
2
values (3). The variant of this device in the MPS3 AN524 board has 6
3
OSCCLK values. Switch to using a PROP_ARRAY, which allows board code
4
to specify how large the OSCCLK array should be as well as its
5
values.
6
2
7
With a variable-length property array, the SCC no longer specifies
3
With -Werror=maybe-uninitialized configuration we get
8
default values for the OSCCLKs, so we must set them explicitly in the
4
../hw/i386/intel_iommu.c: In function ‘vtd_context_device_invalidate’:
9
board code. This defaults are actually incorrect for the an521 and
5
../hw/i386/intel_iommu.c:1888:10: error: ‘mask’ may be used
10
an505; we will correct this bug in a following patch.
6
uninitialized in this function [-Werror=maybe-uninitialized]
7
1888 | mask = ~mask;
8
| ~~~~~^~~~~~~
11
9
12
This is a migration compatibility break for all the mps boards.
10
Add a g_assert_not_reached() to avoid the error.
13
11
12
Signed-off-by: Eric Auger <eric.auger@redhat.com>
13
Reviewed-by: Peter Xu <peterx@redhat.com>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
15
Message-id: 20210309102742.30442-2-eric.auger@redhat.com
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20210215115138.20465-3-peter.maydell@linaro.org
18
---
17
---
19
include/hw/misc/mps2-scc.h | 7 +++----
18
hw/i386/intel_iommu.c | 2 ++
20
hw/arm/mps2-tz.c | 5 +++++
19
1 file changed, 2 insertions(+)
21
hw/arm/mps2.c | 5 +++++
22
hw/misc/mps2-scc.c | 24 +++++++++++++-----------
23
4 files changed, 26 insertions(+), 15 deletions(-)
24
20
25
diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h
21
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
26
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
27
--- a/include/hw/misc/mps2-scc.h
23
--- a/hw/i386/intel_iommu.c
28
+++ b/include/hw/misc/mps2-scc.h
24
+++ b/hw/i386/intel_iommu.c
29
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ static void vtd_context_device_invalidate(IntelIOMMUState *s,
30
#define TYPE_MPS2_SCC "mps2-scc"
26
case 3:
31
OBJECT_DECLARE_SIMPLE_TYPE(MPS2SCC, MPS2_SCC)
27
mask = 7; /* Mask bit 2:0 in the SID field */
32
28
break;
33
-#define NUM_OSCCLK 3
29
+ default:
34
-
30
+ g_assert_not_reached();
35
struct MPS2SCC {
36
/*< private >*/
37
SysBusDevice parent_obj;
38
@@ -XXX,XX +XXX,XX @@ struct MPS2SCC {
39
uint32_t dll;
40
uint32_t aid;
41
uint32_t id;
42
- uint32_t oscclk[NUM_OSCCLK];
43
- uint32_t oscclk_reset[NUM_OSCCLK];
44
+ uint32_t num_oscclk;
45
+ uint32_t *oscclk;
46
+ uint32_t *oscclk_reset;
47
};
48
49
#endif
50
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/hw/arm/mps2-tz.c
53
+++ b/hw/arm/mps2-tz.c
54
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
55
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
56
qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
57
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
58
+ /* This will need to be per-FPGA image eventually */
59
+ qdev_prop_set_uint32(sccdev, "len-oscclk", 3);
60
+ qdev_prop_set_uint32(sccdev, "oscclk[0]", 50000000);
61
+ qdev_prop_set_uint32(sccdev, "oscclk[1]", 24576000);
62
+ qdev_prop_set_uint32(sccdev, "oscclk[2]", 25000000);
63
sysbus_realize(SYS_BUS_DEVICE(scc), &error_fatal);
64
return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
65
}
66
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/hw/arm/mps2.c
69
+++ b/hw/arm/mps2.c
70
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
71
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
72
qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
73
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
74
+ /* All these FPGA images have the same OSCCLK configuration */
75
+ qdev_prop_set_uint32(sccdev, "len-oscclk", 3);
76
+ qdev_prop_set_uint32(sccdev, "oscclk[0]", 50000000);
77
+ qdev_prop_set_uint32(sccdev, "oscclk[1]", 24576000);
78
+ qdev_prop_set_uint32(sccdev, "oscclk[2]", 25000000);
79
sysbus_realize(SYS_BUS_DEVICE(&mms->scc), &error_fatal);
80
sysbus_mmio_map(SYS_BUS_DEVICE(sccdev), 0, 0x4002f000);
81
object_initialize_child(OBJECT(mms), "fpgaio",
82
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
83
index XXXXXXX..XXXXXXX 100644
84
--- a/hw/misc/mps2-scc.c
85
+++ b/hw/misc/mps2-scc.c
86
@@ -XXX,XX +XXX,XX @@ static bool scc_cfg_write(MPS2SCC *s, unsigned function,
87
{
88
trace_mps2_scc_cfg_write(function, device, value);
89
90
- if (function != 1 || device >= NUM_OSCCLK) {
91
+ if (function != 1 || device >= s->num_oscclk) {
92
qemu_log_mask(LOG_GUEST_ERROR,
93
"MPS2 SCC config write: bad function %d device %d\n",
94
function, device);
95
@@ -XXX,XX +XXX,XX @@ static bool scc_cfg_write(MPS2SCC *s, unsigned function,
96
static bool scc_cfg_read(MPS2SCC *s, unsigned function,
97
unsigned device, uint32_t *value)
98
{
99
- if (function != 1 || device >= NUM_OSCCLK) {
100
+ if (function != 1 || device >= s->num_oscclk) {
101
qemu_log_mask(LOG_GUEST_ERROR,
102
"MPS2 SCC config read: bad function %d device %d\n",
103
function, device);
104
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_reset(DeviceState *dev)
105
s->cfgctrl = 0x100000;
106
s->cfgstat = 0;
107
s->dll = 0xffff0001;
108
- for (i = 0; i < NUM_OSCCLK; i++) {
109
+ for (i = 0; i < s->num_oscclk; i++) {
110
s->oscclk[i] = s->oscclk_reset[i];
111
}
31
}
112
for (i = 0; i < ARRAY_SIZE(s->led); i++) {
32
mask = ~mask;
113
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_realize(DeviceState *dev, Error **errp)
114
LED_COLOR_GREEN, name);
115
g_free(name);
116
}
117
+
118
+ s->oscclk = g_new0(uint32_t, s->num_oscclk);
119
}
120
121
static const VMStateDescription mps2_scc_vmstate = {
122
.name = "mps2-scc",
123
- .version_id = 1,
124
- .minimum_version_id = 1,
125
+ .version_id = 2,
126
+ .minimum_version_id = 2,
127
.fields = (VMStateField[]) {
128
VMSTATE_UINT32(cfg0, MPS2SCC),
129
VMSTATE_UINT32(cfg1, MPS2SCC),
130
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription mps2_scc_vmstate = {
131
VMSTATE_UINT32(cfgctrl, MPS2SCC),
132
VMSTATE_UINT32(cfgstat, MPS2SCC),
133
VMSTATE_UINT32(dll, MPS2SCC),
134
- VMSTATE_UINT32_ARRAY(oscclk, MPS2SCC, NUM_OSCCLK),
135
+ VMSTATE_VARRAY_UINT32(oscclk, MPS2SCC, num_oscclk,
136
+ 0, vmstate_info_uint32, uint32_t),
137
VMSTATE_END_OF_LIST()
138
}
139
};
140
@@ -XXX,XX +XXX,XX @@ static Property mps2_scc_properties[] = {
141
DEFINE_PROP_UINT32("scc-cfg4", MPS2SCC, cfg4, 0),
142
DEFINE_PROP_UINT32("scc-aid", MPS2SCC, aid, 0),
143
DEFINE_PROP_UINT32("scc-id", MPS2SCC, id, 0),
144
- /* These are the initial settings for the source clocks on the board.
145
+ /*
146
+ * These are the initial settings for the source clocks on the board.
147
* In hardware they can be configured via a config file read by the
148
* motherboard configuration controller to suit the FPGA image.
149
- * These default values are used by most of the standard FPGA images.
150
*/
151
- DEFINE_PROP_UINT32("oscclk0", MPS2SCC, oscclk_reset[0], 50000000),
152
- DEFINE_PROP_UINT32("oscclk1", MPS2SCC, oscclk_reset[1], 24576000),
153
- DEFINE_PROP_UINT32("oscclk2", MPS2SCC, oscclk_reset[2], 25000000),
154
+ DEFINE_PROP_ARRAY("oscclk", MPS2SCC, num_oscclk, oscclk_reset,
155
+ qdev_prop_uint32, uint32_t),
156
DEFINE_PROP_END_OF_LIST(),
157
};
158
33
159
--
34
--
160
2.20.1
35
2.20.1
161
36
162
37
diff view generated by jsdifflib
1
The AN524 has a PL031 RTC, which we have a model of; provide it
1
From: Eric Auger <eric.auger@redhat.com>
2
rather than an unimplemented-device stub.
3
2
3
Currently get_naturally_aligned_size() is used by the intel iommu
4
to compute the maximum invalidation range based on @size which is
5
a power of 2 while being aligned with the @start address and less
6
than the maximum range defined by @gaw.
7
8
This helper is also useful for other iommu devices (virtio-iommu,
9
SMMUv3) to make sure IOMMU UNMAP notifiers only are called with
10
power of 2 range sizes.
11
12
Let's move this latter into dma-helpers.c and rename it into
13
dma_aligned_pow2_mask(). Also rewrite the helper so that it
14
accomodates UINT64_MAX values for the size mask and max mask.
15
It now returns a mask instead of a size. Change the caller.
16
17
Signed-off-by: Eric Auger <eric.auger@redhat.com>
18
Reviewed-by: Peter Xu <peterx@redhat.com>
19
Message-id: 20210309102742.30442-3-eric.auger@redhat.com
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
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: 20210215115138.20465-23-peter.maydell@linaro.org
8
---
21
---
9
hw/arm/mps2-tz.c | 22 ++++++++++++++++++++--
22
include/sysemu/dma.h | 12 ++++++++++++
10
1 file changed, 20 insertions(+), 2 deletions(-)
23
hw/i386/intel_iommu.c | 30 +++++++-----------------------
24
softmmu/dma-helpers.c | 26 ++++++++++++++++++++++++++
25
3 files changed, 45 insertions(+), 23 deletions(-)
11
26
12
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
27
diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h
13
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/mps2-tz.c
29
--- a/include/sysemu/dma.h
15
+++ b/hw/arm/mps2-tz.c
30
+++ b/include/sysemu/dma.h
31
@@ -XXX,XX +XXX,XX @@ uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg);
32
void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,
33
QEMUSGList *sg, enum BlockAcctType type);
34
35
+/**
36
+ * dma_aligned_pow2_mask: Return the address bit mask of the largest
37
+ * power of 2 size less or equal than @end - @start + 1, aligned with @start,
38
+ * and bounded by 1 << @max_addr_bits bits.
39
+ *
40
+ * @start: range start address
41
+ * @end: range end address (greater than @start)
42
+ * @max_addr_bits: max address bits (<= 64)
43
+ */
44
+uint64_t dma_aligned_pow2_mask(uint64_t start, uint64_t end,
45
+ int max_addr_bits);
46
+
47
#endif
48
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/i386/intel_iommu.c
51
+++ b/hw/i386/intel_iommu.c
16
@@ -XXX,XX +XXX,XX @@
52
@@ -XXX,XX +XXX,XX @@
17
#include "hw/misc/tz-msc.h"
53
#include "hw/i386/x86-iommu.h"
18
#include "hw/arm/armsse.h"
54
#include "hw/pci-host/q35.h"
19
#include "hw/dma/pl080.h"
55
#include "sysemu/kvm.h"
20
+#include "hw/rtc/pl031.h"
56
+#include "sysemu/dma.h"
21
#include "hw/ssi/pl022.h"
57
#include "sysemu/sysemu.h"
22
#include "hw/i2c/arm_sbcon_i2c.h"
58
#include "hw/i386/apic_internal.h"
23
#include "hw/net/lan9118.h"
59
#include "kvm/kvm_i386.h"
24
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
60
@@ -XXX,XX +XXX,XX @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
25
UnimplementedDeviceState gpio[4];
61
return vtd_dev_as;
26
UnimplementedDeviceState gfx;
27
UnimplementedDeviceState cldc;
28
- UnimplementedDeviceState rtc;
29
UnimplementedDeviceState usb;
30
+ PL031State rtc;
31
PL080State dma[4];
32
TZMSC msc[4];
33
CMSDKAPBUART uart[6];
34
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
35
return sysbus_mmio_get_region(s, 0);
36
}
62
}
37
63
38
+static MemoryRegion *make_rtc(MPS2TZMachineState *mms, void *opaque,
64
-static uint64_t get_naturally_aligned_size(uint64_t start,
39
+ const char *name, hwaddr size,
65
- uint64_t size, int gaw)
40
+ const int *irqs)
66
-{
67
- uint64_t max_mask = 1ULL << gaw;
68
- uint64_t alignment = start ? start & -start : max_mask;
69
-
70
- alignment = MIN(alignment, max_mask);
71
- size = MIN(size, max_mask);
72
-
73
- if (alignment <= size) {
74
- /* Increase the alignment of start */
75
- return alignment;
76
- } else {
77
- /* Find the largest page mask from size */
78
- return 1ULL << (63 - clz64(size));
79
- }
80
-}
81
-
82
/* Unmap the whole range in the notifier's scope. */
83
static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n)
84
{
85
@@ -XXX,XX +XXX,XX @@ static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n)
86
87
while (remain >= VTD_PAGE_SIZE) {
88
IOMMUTLBEvent event;
89
- uint64_t mask = get_naturally_aligned_size(start, remain, s->aw_bits);
90
+ uint64_t mask = dma_aligned_pow2_mask(start, end, s->aw_bits);
91
+ uint64_t size = mask + 1;
92
93
- assert(mask);
94
+ assert(size);
95
96
event.type = IOMMU_NOTIFIER_UNMAP;
97
event.entry.iova = start;
98
- event.entry.addr_mask = mask - 1;
99
+ event.entry.addr_mask = mask;
100
event.entry.target_as = &address_space_memory;
101
event.entry.perm = IOMMU_NONE;
102
/* This field is meaningless for unmap */
103
@@ -XXX,XX +XXX,XX @@ static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n)
104
105
memory_region_notify_iommu_one(n, &event);
106
107
- start += mask;
108
- remain -= mask;
109
+ start += size;
110
+ remain -= size;
111
}
112
113
assert(!remain);
114
diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c
115
index XXXXXXX..XXXXXXX 100644
116
--- a/softmmu/dma-helpers.c
117
+++ b/softmmu/dma-helpers.c
118
@@ -XXX,XX +XXX,XX @@ void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,
119
{
120
block_acct_start(blk_get_stats(blk), cookie, sg->size, type);
121
}
122
+
123
+uint64_t dma_aligned_pow2_mask(uint64_t start, uint64_t end, int max_addr_bits)
41
+{
124
+{
42
+ PL031State *pl031 = opaque;
125
+ uint64_t max_mask = UINT64_MAX, addr_mask = end - start;
43
+ SysBusDevice *s;
126
+ uint64_t alignment_mask, size_mask;
44
+
127
+
45
+ object_initialize_child(OBJECT(mms), name, pl031, TYPE_PL031);
128
+ if (max_addr_bits != 64) {
46
+ s = SYS_BUS_DEVICE(pl031);
129
+ max_mask = (1ULL << max_addr_bits) - 1;
47
+ sysbus_realize(s, &error_fatal);
130
+ }
48
+ /*
131
+
49
+ * The board docs don't give an IRQ number for the PL031, so
132
+ alignment_mask = start ? (start & -start) - 1 : max_mask;
50
+ * presumably it is not connected.
133
+ alignment_mask = MIN(alignment_mask, max_mask);
51
+ */
134
+ size_mask = MIN(addr_mask, max_mask);
52
+ return sysbus_mmio_get_region(s, 0);
135
+
136
+ if (alignment_mask <= size_mask) {
137
+ /* Increase the alignment of start */
138
+ return alignment_mask;
139
+ } else {
140
+ /* Find the largest page mask from size */
141
+ if (addr_mask == UINT64_MAX) {
142
+ return UINT64_MAX;
143
+ }
144
+ return (1ULL << (63 - clz64(addr_mask + 1))) - 1;
145
+ }
53
+}
146
+}
54
+
147
+
55
static void create_non_mpc_ram(MPS2TZMachineState *mms)
56
{
57
/*
58
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
59
60
{ /* port 9 reserved */ },
61
{ "clcd", make_unimp_dev, &mms->cldc, 0x4130a000, 0x1000 },
62
- { "rtc", make_unimp_dev, &mms->rtc, 0x4130b000, 0x1000 },
63
+ { "rtc", make_rtc, &mms->rtc, 0x4130b000, 0x1000 },
64
},
65
}, {
66
.name = "ahb_ppcexp0",
67
--
148
--
68
2.20.1
149
2.20.1
69
150
70
151
diff view generated by jsdifflib
1
The MPS2 board has 2 LEDs, but the MPS3 board has 10 LEDs. The
1
From: Eric Auger <eric.auger@redhat.com>
2
FPGAIO device is similar on both sets of boards, but the LED0
3
register has correspondingly more bits that have an effect. Add a
4
device property for number of LEDs.
5
2
3
Unmap notifiers work with an address mask assuming an
4
invalidation range of a power of 2. Nothing mandates this
5
in the VIRTIO-IOMMU spec.
6
7
So in case the range is not a power of 2, split it into
8
several invalidations.
9
10
Signed-off-by: Eric Auger <eric.auger@redhat.com>
11
Reviewed-by: Peter Xu <peterx@redhat.com>
12
Message-id: 20210309102742.30442-4-eric.auger@redhat.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210215115138.20465-6-peter.maydell@linaro.org
10
---
14
---
11
include/hw/misc/mps2-fpgaio.h | 5 ++++-
15
hw/virtio/virtio-iommu.c | 19 ++++++++++++++++---
12
hw/misc/mps2-fpgaio.c | 31 +++++++++++++++++++++++--------
16
1 file changed, 16 insertions(+), 3 deletions(-)
13
2 files changed, 27 insertions(+), 9 deletions(-)
14
17
15
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
18
diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/misc/mps2-fpgaio.h
20
--- a/hw/virtio/virtio-iommu.c
18
+++ b/include/hw/misc/mps2-fpgaio.h
21
+++ b/hw/virtio/virtio-iommu.c
19
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ static void virtio_iommu_notify_unmap(IOMMUMemoryRegion *mr, hwaddr virt_start,
20
#define TYPE_MPS2_FPGAIO "mps2-fpgaio"
23
hwaddr virt_end)
21
OBJECT_DECLARE_SIMPLE_TYPE(MPS2FPGAIO, MPS2_FPGAIO)
22
23
+#define MPS2FPGAIO_MAX_LEDS 32
24
+
25
struct MPS2FPGAIO {
26
/*< private >*/
27
SysBusDevice parent_obj;
28
29
/*< public >*/
30
MemoryRegion iomem;
31
- LEDState *led[2];
32
+ LEDState *led[MPS2FPGAIO_MAX_LEDS];
33
+ uint32_t num_leds;
34
35
uint32_t led0;
36
uint32_t prescale;
37
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/misc/mps2-fpgaio.c
40
+++ b/hw/misc/mps2-fpgaio.c
41
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
42
43
switch (offset) {
44
case A_LED0:
45
- s->led0 = value & 0x3;
46
- led_set_state(s->led[0], value & 0x01);
47
- led_set_state(s->led[1], value & 0x02);
48
+ if (s->num_leds != 0) {
49
+ uint32_t i;
50
+
51
+ s->led0 = value & MAKE_64BIT_MASK(0, s->num_leds);
52
+ for (i = 0; i < s->num_leds; i++) {
53
+ led_set_state(s->led[i], value & (1 << i));
54
+ }
55
+ }
56
break;
57
case A_PRESCALE:
58
resync_counter(s);
59
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_reset(DeviceState *dev)
60
s->pscntr = 0;
61
s->pscntr_sync_ticks = now;
62
63
- for (size_t i = 0; i < ARRAY_SIZE(s->led); i++) {
64
+ for (size_t i = 0; i < s->num_leds; i++) {
65
device_cold_reset(DEVICE(s->led[i]));
66
}
67
}
68
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_init(Object *obj)
69
static void mps2_fpgaio_realize(DeviceState *dev, Error **errp)
70
{
24
{
71
MPS2FPGAIO *s = MPS2_FPGAIO(dev);
25
IOMMUTLBEvent event;
72
+ uint32_t i;
26
+ uint64_t delta = virt_end - virt_start;
73
27
74
- s->led[0] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH,
28
if (!(mr->iommu_notify_flags & IOMMU_NOTIFIER_UNMAP)) {
75
- LED_COLOR_GREEN, "USERLED0");
29
return;
76
- s->led[1] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH,
30
@@ -XXX,XX +XXX,XX @@ static void virtio_iommu_notify_unmap(IOMMUMemoryRegion *mr, hwaddr virt_start,
77
- LED_COLOR_GREEN, "USERLED1");
31
78
+ if (s->num_leds > MPS2FPGAIO_MAX_LEDS) {
32
event.type = IOMMU_NOTIFIER_UNMAP;
79
+ error_setg(errp, "num-leds cannot be greater than %d",
33
event.entry.target_as = &address_space_memory;
80
+ MPS2FPGAIO_MAX_LEDS);
34
- event.entry.addr_mask = virt_end - virt_start;
81
+ return;
35
- event.entry.iova = virt_start;
36
event.entry.perm = IOMMU_NONE;
37
event.entry.translated_addr = 0;
38
+ event.entry.addr_mask = delta;
39
+ event.entry.iova = virt_start;
40
41
- memory_region_notify_iommu(mr, 0, event);
42
+ if (delta == UINT64_MAX) {
43
+ memory_region_notify_iommu(mr, 0, event);
82
+ }
44
+ }
83
+
45
+
84
+ for (i = 0; i < s->num_leds; i++) {
46
+
85
+ g_autofree char *ledname = g_strdup_printf("USERLED%d", i);
47
+ while (virt_start != virt_end + 1) {
86
+ s->led[i] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH,
48
+ uint64_t mask = dma_aligned_pow2_mask(virt_start, virt_end, 64);
87
+ LED_COLOR_GREEN, ledname);
49
+
50
+ event.entry.addr_mask = mask;
51
+ event.entry.iova = virt_start;
52
+ memory_region_notify_iommu(mr, 0, event);
53
+ virt_start += mask + 1;
88
+ }
54
+ }
89
}
55
}
90
56
91
static bool mps2_fpgaio_counters_needed(void *opaque)
57
static gboolean virtio_iommu_notify_unmap_cb(gpointer key, gpointer value,
92
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription mps2_fpgaio_vmstate = {
93
static Property mps2_fpgaio_properties[] = {
94
/* Frequency of the prescale counter */
95
DEFINE_PROP_UINT32("prescale-clk", MPS2FPGAIO, prescale_clk, 20000000),
96
+ /* Number of LEDs controlled by LED0 register */
97
+ DEFINE_PROP_UINT32("num-leds", MPS2FPGAIO, num_leds, 2),
98
DEFINE_PROP_END_OF_LIST(),
99
};
100
101
--
58
--
102
2.20.1
59
2.20.1
103
60
104
61
diff view generated by jsdifflib
1
Add brief documentation of the new mps3-an524 board.
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
If the asid is not set, do not attempt to locate the key directly
4
as all inserted keys have a valid asid.
5
6
Use g_hash_table_foreach_remove instead.
7
8
Signed-off-by: Eric Auger <eric.auger@redhat.com>
9
Message-id: 20210309102742.30442-5-eric.auger@redhat.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210215115138.20465-24-peter.maydell@linaro.org
7
---
12
---
8
docs/system/arm/mps2.rst | 24 ++++++++++++++++++------
13
hw/arm/smmu-common.c | 2 +-
9
1 file changed, 18 insertions(+), 6 deletions(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
10
15
11
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
16
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
12
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
13
--- a/docs/system/arm/mps2.rst
18
--- a/hw/arm/smmu-common.c
14
+++ b/docs/system/arm/mps2.rst
19
+++ b/hw/arm/smmu-common.c
15
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ inline void
16
-Arm MPS2 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
21
smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova,
17
-================================================================================================================
22
uint8_t tg, uint64_t num_pages, uint8_t ttl)
18
+Arm MPS2 and MPS3 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``, ``mps3-an524``)
23
{
19
+=========================================================================================================================================
24
- if (ttl && (num_pages == 1)) {
20
25
+ if (ttl && (num_pages == 1) && (asid >= 0)) {
21
These board models all use Arm M-profile CPUs.
26
SMMUIOTLBKey key = smmu_get_iotlb_key(asid, iova, tg, ttl);
22
27
23
-The Arm MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger
28
g_hash_table_remove(s->iotlb, &key);
24
-FPGA but is otherwise the same as the 2). Since the CPU itself
25
-and most of the devices are in the FPGA, the details of the board
26
-as seen by the guest depend significantly on the FPGA image.
27
+The Arm MPS2, MPS2+ and MPS3 dev boards are FPGA based (the 2+ has a
28
+bigger FPGA but is otherwise the same as the 2; the 3 has a bigger
29
+FPGA again, can handle 4GB of RAM and has a USB controller and QSPI flash).
30
+
31
+Since the CPU itself and most of the devices are in the FPGA, the
32
+details of the board as seen by the guest depend significantly on the
33
+FPGA image.
34
35
QEMU models the following FPGA images:
36
37
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
38
Cortex-M3 'DesignStart' as documented in Arm Application Note AN511
39
``mps2-an521``
40
Dual Cortex-M33 as documented in Arm Application Note AN521
41
+``mps3-an524``
42
+ Dual Cortex-M33 on an MPS3, as documented in Arm Application Note AN524
43
44
Differences between QEMU and real hardware:
45
46
- AN385/AN386 remapping of low 16K of memory to either ZBT SSRAM1 or to
47
block RAM is unimplemented (QEMU always maps this to ZBT SSRAM1, as
48
if zbt_boot_ctrl is always zero)
49
+- AN524 remapping of low memory to either BRAM or to QSPI flash is
50
+ unimplemented (QEMU always maps this to BRAM, ignoring the
51
+ SCC CFG_REG0 memory-remap bit)
52
- QEMU provides a LAN9118 ethernet rather than LAN9220; the only guest
53
visible difference is that the LAN9118 doesn't support checksum
54
offloading
55
+- QEMU does not model the QSPI flash in MPS3 boards as real QSPI
56
+ flash, but only as simple ROM, so attempting to rewrite the flash
57
+ from the guest will fail
58
+- QEMU does not model the USB controller in MPS3 boards
59
--
29
--
60
2.20.1
30
2.20.1
61
31
62
32
diff view generated by jsdifflib
1
From: Rebecca Cran <rebecca@nuviainc.com>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
Add support for FEAT_SSBS. SSBS (Speculative Store Bypass Safe) is an
3
As of today, the driver can invalidate a number of pages that is
4
optional feature in ARMv8.0, and mandatory in ARMv8.5.
4
not a power of 2. However IOTLB unmap notifications and internal
5
IOTLB invalidations work with masks leading to erroneous
6
invalidations.
5
7
6
Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
8
In case the range is not a power of 2, split invalidations into
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
power of 2 invalidations.
8
Message-id: 20210216224543.16142-2-rebecca@nuviainc.com
10
11
When looking for a single page entry in the vSMMU internal IOTLB,
12
let's make sure that if the entry is not found using a
13
g_hash_table_remove() we iterate over all the entries to find a
14
potential range that overlaps it.
15
16
Signed-off-by: Eric Auger <eric.auger@redhat.com>
17
Message-id: 20210309102742.30442-6-eric.auger@redhat.com
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
20
---
11
target/arm/cpu.h | 15 ++++++++++++++-
21
hw/arm/smmu-common.c | 30 ++++++++++++++++++------------
12
target/arm/internals.h | 6 ++++++
22
hw/arm/smmuv3.c | 24 ++++++++++++++++++++----
13
target/arm/helper.c | 37 +++++++++++++++++++++++++++++++++++++
23
2 files changed, 38 insertions(+), 16 deletions(-)
14
target/arm/translate-a64.c | 12 ++++++++++++
15
4 files changed, 69 insertions(+), 1 deletion(-)
16
24
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
25
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
18
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
27
--- a/hw/arm/smmu-common.c
20
+++ b/target/arm/cpu.h
28
+++ b/hw/arm/smmu-common.c
21
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
29
@@ -XXX,XX +XXX,XX @@ inline void
22
#define SCTLR_TE (1U << 30) /* AArch32 only */
30
smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova,
23
#define SCTLR_EnIB (1U << 30) /* v8.3, AArch64 only */
31
uint8_t tg, uint64_t num_pages, uint8_t ttl)
24
#define SCTLR_EnIA (1U << 31) /* v8.3, AArch64 only */
32
{
25
+#define SCTLR_DSSBS_32 (1U << 31) /* v8.5, AArch32 only */
33
+ /* if tg is not set we use 4KB range invalidation */
26
#define SCTLR_BT0 (1ULL << 35) /* v8.5-BTI */
34
+ uint8_t granule = tg ? tg * 2 + 10 : 12;
27
#define SCTLR_BT1 (1ULL << 36) /* v8.5-BTI */
35
+
28
#define SCTLR_ITFSB (1ULL << 37) /* v8.5-MemTag */
36
if (ttl && (num_pages == 1) && (asid >= 0)) {
29
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
37
SMMUIOTLBKey key = smmu_get_iotlb_key(asid, iova, tg, ttl);
30
#define SCTLR_TCF (3ULL << 40) /* v8.5-MemTag */
38
31
#define SCTLR_ATA0 (1ULL << 42) /* v8.5-MemTag */
39
- g_hash_table_remove(s->iotlb, &key);
32
#define SCTLR_ATA (1ULL << 43) /* v8.5-MemTag */
40
- } else {
33
-#define SCTLR_DSSBS (1ULL << 44) /* v8.5 */
41
- /* if tg is not set we use 4KB range invalidation */
34
+#define SCTLR_DSSBS_64 (1ULL << 44) /* v8.5, AArch64 only */
42
- uint8_t granule = tg ? tg * 2 + 10 : 12;
35
43
-
36
#define CPTR_TCPAC (1U << 31)
44
- SMMUIOTLBPageInvInfo info = {
37
#define CPTR_TTA (1U << 20)
45
- .asid = asid, .iova = iova,
38
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
46
- .mask = (num_pages * 1 << granule) - 1};
39
#define CPSR_IL (1U << 20)
47
-
40
#define CPSR_DIT (1U << 21)
48
- g_hash_table_foreach_remove(s->iotlb,
41
#define CPSR_PAN (1U << 22)
49
- smmu_hash_remove_by_asid_iova,
42
+#define CPSR_SSBS (1U << 23)
50
- &info);
43
#define CPSR_J (1U << 24)
51
+ if (g_hash_table_remove(s->iotlb, &key)) {
44
#define CPSR_IT_0_1 (3U << 25)
52
+ return;
45
#define CPSR_Q (1U << 27)
53
+ }
46
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
54
+ /*
47
#define PSTATE_A (1U << 8)
55
+ * if the entry is not found, let's see if it does not
48
#define PSTATE_D (1U << 9)
56
+ * belong to a larger IOTLB entry
49
#define PSTATE_BTYPE (3U << 10)
57
+ */
50
+#define PSTATE_SSBS (1U << 12)
58
}
51
#define PSTATE_IL (1U << 20)
59
+
52
#define PSTATE_SS (1U << 21)
60
+ SMMUIOTLBPageInvInfo info = {
53
#define PSTATE_PAN (1U << 22)
61
+ .asid = asid, .iova = iova,
54
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_dit(const ARMISARegisters *id)
62
+ .mask = (num_pages * 1 << granule) - 1};
55
return FIELD_EX32(id->id_pfr0, ID_PFR0, DIT) != 0;
63
+
64
+ g_hash_table_foreach_remove(s->iotlb,
65
+ smmu_hash_remove_by_asid_iova,
66
+ &info);
56
}
67
}
57
68
58
+static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id)
69
inline void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid)
59
+{
70
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
60
+ return FIELD_EX32(id->id_pfr2, ID_PFR2, SSBS) != 0;
71
index XXXXXXX..XXXXXXX 100644
61
+}
72
--- a/hw/arm/smmuv3.c
73
+++ b/hw/arm/smmuv3.c
74
@@ -XXX,XX +XXX,XX @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
75
uint16_t vmid = CMD_VMID(cmd);
76
bool leaf = CMD_LEAF(cmd);
77
uint8_t tg = CMD_TG(cmd);
78
- hwaddr num_pages = 1;
79
+ uint64_t first_page = 0, last_page;
80
+ uint64_t num_pages = 1;
81
int asid = -1;
82
83
if (tg) {
84
@@ -XXX,XX +XXX,XX @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
85
if (type == SMMU_CMD_TLBI_NH_VA) {
86
asid = CMD_ASID(cmd);
87
}
88
- trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, num_pages, ttl, leaf);
89
- smmuv3_inv_notifiers_iova(s, asid, addr, tg, num_pages);
90
- smmu_iotlb_inv_iova(s, asid, addr, tg, num_pages, ttl);
62
+
91
+
63
/*
92
+ /* Split invalidations into ^2 range invalidations */
64
* 64-bit feature tests via id registers.
93
+ last_page = num_pages - 1;
65
*/
94
+ while (num_pages) {
66
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_dit(const ARMISARegisters *id)
95
+ uint8_t granule = tg * 2 + 10;
67
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0;
96
+ uint64_t mask, count;
97
+
98
+ mask = dma_aligned_pow2_mask(first_page, last_page, 64 - granule);
99
+ count = mask + 1;
100
+
101
+ trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, count, ttl, leaf);
102
+ smmuv3_inv_notifiers_iova(s, asid, addr, tg, count);
103
+ smmu_iotlb_inv_iova(s, asid, addr, tg, count, ttl);
104
+
105
+ num_pages -= count;
106
+ first_page += count;
107
+ addr += count * BIT_ULL(granule);
108
+ }
68
}
109
}
69
110
70
+static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id)
111
static int smmuv3_cmdq_consume(SMMUv3State *s)
71
+{
72
+ return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0;
73
+}
74
+
75
/*
76
* Feature tests for "does this exist in either 32-bit or 64-bit?"
77
*/
78
diff --git a/target/arm/internals.h b/target/arm/internals.h
79
index XXXXXXX..XXXXXXX 100644
80
--- a/target/arm/internals.h
81
+++ b/target/arm/internals.h
82
@@ -XXX,XX +XXX,XX @@ static inline uint32_t aarch32_cpsr_valid_mask(uint64_t features,
83
if (isar_feature_aa32_dit(id)) {
84
valid |= CPSR_DIT;
85
}
86
+ if (isar_feature_aa32_ssbs(id)) {
87
+ valid |= CPSR_SSBS;
88
+ }
89
90
return valid;
91
}
92
@@ -XXX,XX +XXX,XX @@ static inline uint32_t aarch64_pstate_valid_mask(const ARMISARegisters *id)
93
if (isar_feature_aa64_dit(id)) {
94
valid |= PSTATE_DIT;
95
}
96
+ if (isar_feature_aa64_ssbs(id)) {
97
+ valid |= PSTATE_SSBS;
98
+ }
99
if (isar_feature_aa64_mte(id)) {
100
valid |= PSTATE_TCO;
101
}
102
diff --git a/target/arm/helper.c b/target/arm/helper.c
103
index XXXXXXX..XXXXXXX 100644
104
--- a/target/arm/helper.c
105
+++ b/target/arm/helper.c
106
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo dit_reginfo = {
107
.readfn = aa64_dit_read, .writefn = aa64_dit_write
108
};
109
110
+static uint64_t aa64_ssbs_read(CPUARMState *env, const ARMCPRegInfo *ri)
111
+{
112
+ return env->pstate & PSTATE_SSBS;
113
+}
114
+
115
+static void aa64_ssbs_write(CPUARMState *env, const ARMCPRegInfo *ri,
116
+ uint64_t value)
117
+{
118
+ env->pstate = (env->pstate & ~PSTATE_SSBS) | (value & PSTATE_SSBS);
119
+}
120
+
121
+static const ARMCPRegInfo ssbs_reginfo = {
122
+ .name = "SSBS", .state = ARM_CP_STATE_AA64,
123
+ .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 6,
124
+ .type = ARM_CP_NO_RAW, .access = PL0_RW,
125
+ .readfn = aa64_ssbs_read, .writefn = aa64_ssbs_write
126
+};
127
+
128
static CPAccessResult aa64_cacheop_poc_access(CPUARMState *env,
129
const ARMCPRegInfo *ri,
130
bool isread)
131
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
132
if (cpu_isar_feature(aa64_dit, cpu)) {
133
define_one_arm_cp_reg(cpu, &dit_reginfo);
134
}
135
+ if (cpu_isar_feature(aa64_ssbs, cpu)) {
136
+ define_one_arm_cp_reg(cpu, &ssbs_reginfo);
137
+ }
138
139
if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
140
define_arm_cp_regs(cpu, vhe_reginfo);
141
@@ -XXX,XX +XXX,XX @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
142
env->uncached_cpsr &= ~(CPSR_IL | CPSR_J);
143
env->daif |= mask;
144
145
+ if (cpu_isar_feature(aa32_ssbs, env_archcpu(env))) {
146
+ if (env->cp15.sctlr_el[new_el] & SCTLR_DSSBS_32) {
147
+ env->uncached_cpsr |= CPSR_SSBS;
148
+ } else {
149
+ env->uncached_cpsr &= ~CPSR_SSBS;
150
+ }
151
+ }
152
+
153
if (new_mode == ARM_CPU_MODE_HYP) {
154
env->thumb = (env->cp15.sctlr_el[2] & SCTLR_TE) != 0;
155
env->elr_el[2] = env->regs[15];
156
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
157
new_mode |= PSTATE_TCO;
158
}
159
160
+ if (cpu_isar_feature(aa64_ssbs, cpu)) {
161
+ if (env->cp15.sctlr_el[new_el] & SCTLR_DSSBS_64) {
162
+ new_mode |= PSTATE_SSBS;
163
+ } else {
164
+ new_mode &= ~PSTATE_SSBS;
165
+ }
166
+ }
167
+
168
pstate_write(env, PSTATE_DAIF | new_mode);
169
env->aarch64 = 1;
170
aarch64_restore_sp(env, new_el);
171
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
172
index XXXXXXX..XXXXXXX 100644
173
--- a/target/arm/translate-a64.c
174
+++ b/target/arm/translate-a64.c
175
@@ -XXX,XX +XXX,XX @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
176
tcg_temp_free_i32(t1);
177
break;
178
179
+ case 0x19: /* SSBS */
180
+ if (!dc_isar_feature(aa64_ssbs, s)) {
181
+ goto do_unallocated;
182
+ }
183
+ if (crm & 1) {
184
+ set_pstate_bits(PSTATE_SSBS);
185
+ } else {
186
+ clear_pstate_bits(PSTATE_SSBS);
187
+ }
188
+ /* Don't need to rebuild hflags since SSBS is a nop */
189
+ break;
190
+
191
case 0x1a: /* DIT */
192
if (!dc_isar_feature(aa64_dit, s)) {
193
goto do_unallocated;
194
--
112
--
195
2.20.1
113
2.20.1
196
114
197
115
diff view generated by jsdifflib
1
The AN524 has a USB controller (an ISP1763); we don't have a model of
1
From: Eric Auger <eric.auger@redhat.com>
2
it but we should provide a stub "unimplemented-device" for it. This
3
is slightly complicated because the USB controller shares a PPC port
4
with the ethernet controller.
5
2
6
Implement a make_* function which provides creates a container
3
If the whole SID range (32b) is invalidated (SMMU_CMD_CFGI_ALL),
7
MemoryRegion with both the ethernet controller and an
4
@end overflows and we fail to handle the command properly.
8
unimplemented-device stub for the USB controller.
9
5
6
Once this gets fixed, the current code really is awkward in the
7
sense it loops over the whole range instead of removing the
8
currently cached configs through a hash table lookup.
9
10
Fix both the overflow and the lookup.
11
12
Signed-off-by: Eric Auger <eric.auger@redhat.com>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20210309102742.30442-7-eric.auger@redhat.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20210215115138.20465-22-peter.maydell@linaro.org
14
---
16
---
15
hw/arm/mps2-tz.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
17
hw/arm/smmu-internal.h | 5 +++++
16
1 file changed, 47 insertions(+), 1 deletion(-)
18
hw/arm/smmuv3.c | 34 ++++++++++++++++++++--------------
19
2 files changed, 25 insertions(+), 14 deletions(-)
17
20
18
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
21
diff --git a/hw/arm/smmu-internal.h b/hw/arm/smmu-internal.h
19
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/mps2-tz.c
23
--- a/hw/arm/smmu-internal.h
21
+++ b/hw/arm/mps2-tz.c
24
+++ b/hw/arm/smmu-internal.h
22
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
25
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUIOTLBPageInvInfo {
23
26
uint64_t mask;
24
ARMSSE iotkit;
27
} SMMUIOTLBPageInvInfo;
25
MemoryRegion ram[MPS2TZ_RAM_MAX];
28
26
+ MemoryRegion eth_usb_container;
29
+typedef struct SMMUSIDRange {
30
+ uint32_t start;
31
+ uint32_t end;
32
+} SMMUSIDRange;
27
+
33
+
28
MPS2SCC scc;
34
#endif
29
MPS2FPGAIO fpgaio;
35
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
30
TZPPC ppc[5];
36
index XXXXXXX..XXXXXXX 100644
31
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
37
--- a/hw/arm/smmuv3.c
32
UnimplementedDeviceState gfx;
38
+++ b/hw/arm/smmuv3.c
33
UnimplementedDeviceState cldc;
39
@@ -XXX,XX +XXX,XX @@
34
UnimplementedDeviceState rtc;
40
35
+ UnimplementedDeviceState usb;
41
#include "hw/arm/smmuv3.h"
36
PL080State dma[4];
42
#include "smmuv3-internal.h"
37
TZMSC msc[4];
43
+#include "smmu-internal.h"
38
CMSDKAPBUART uart[6];
44
39
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
45
/**
40
return sysbus_mmio_get_region(s, 0);
46
* smmuv3_trigger_irq - pulse @irq if enabled and update
47
@@ -XXX,XX +XXX,XX @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
48
}
41
}
49
}
42
50
43
+static MemoryRegion *make_eth_usb(MPS2TZMachineState *mms, void *opaque,
51
+static gboolean
44
+ const char *name, hwaddr size,
52
+smmuv3_invalidate_ste(gpointer key, gpointer value, gpointer user_data)
45
+ const int *irqs)
46
+{
53
+{
47
+ /*
54
+ SMMUDevice *sdev = (SMMUDevice *)key;
48
+ * The AN524 makes the ethernet and USB share a PPC port.
55
+ uint32_t sid = smmu_get_sid(sdev);
49
+ * irqs[] is the ethernet IRQ.
56
+ SMMUSIDRange *sid_range = (SMMUSIDRange *)user_data;
50
+ */
51
+ SysBusDevice *s;
52
+ NICInfo *nd = &nd_table[0];
53
+
57
+
54
+ memory_region_init(&mms->eth_usb_container, OBJECT(mms),
58
+ if (sid < sid_range->start || sid > sid_range->end) {
55
+ "mps2-tz-eth-usb-container", 0x200000);
59
+ return false;
56
+
60
+ }
57
+ /*
61
+ trace_smmuv3_config_cache_inv(sid);
58
+ * In hardware this is a LAN9220; the LAN9118 is software compatible
62
+ return true;
59
+ * except that it doesn't support the checksum-offload feature.
60
+ */
61
+ qemu_check_nic_model(nd, "lan9118");
62
+ mms->lan9118 = qdev_new(TYPE_LAN9118);
63
+ qdev_set_nic_properties(mms->lan9118, nd);
64
+
65
+ s = SYS_BUS_DEVICE(mms->lan9118);
66
+ sysbus_realize_and_unref(s, &error_fatal);
67
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
68
+
69
+ memory_region_add_subregion(&mms->eth_usb_container,
70
+ 0, sysbus_mmio_get_region(s, 0));
71
+
72
+ /* The USB OTG controller is an ISP1763; we don't have a model of it. */
73
+ object_initialize_child(OBJECT(mms), "usb-otg",
74
+ &mms->usb, TYPE_UNIMPLEMENTED_DEVICE);
75
+ qdev_prop_set_string(DEVICE(&mms->usb), "name", "usb-otg");
76
+ qdev_prop_set_uint64(DEVICE(&mms->usb), "size", 0x100000);
77
+ s = SYS_BUS_DEVICE(&mms->usb);
78
+ sysbus_realize(s, &error_fatal);
79
+
80
+ memory_region_add_subregion(&mms->eth_usb_container,
81
+ 0x100000, sysbus_mmio_get_region(s, 0));
82
+
83
+ return &mms->eth_usb_container;
84
+}
63
+}
85
+
64
+
86
static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
65
static int smmuv3_cmdq_consume(SMMUv3State *s)
87
const char *name, hwaddr size,
66
{
88
const int *irqs)
67
SMMUState *bs = ARM_SMMU(s);
89
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
68
@@ -XXX,XX +XXX,XX @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
90
{ "gpio1", make_unimp_dev, &mms->gpio[1], 0x41101000, 0x1000 },
69
}
91
{ "gpio2", make_unimp_dev, &mms->gpio[2], 0x41102000, 0x1000 },
70
case SMMU_CMD_CFGI_STE_RANGE: /* same as SMMU_CMD_CFGI_ALL */
92
{ "gpio3", make_unimp_dev, &mms->gpio[3], 0x41103000, 0x1000 },
71
{
93
- { "eth", make_eth_dev, NULL, 0x41400000, 0x100000, { 48 } },
72
- uint32_t start = CMD_SID(&cmd), end, i;
94
+ { "eth-usb", make_eth_usb, NULL, 0x41400000, 0x200000, { 48 } },
73
+ uint32_t start = CMD_SID(&cmd);
95
},
74
uint8_t range = CMD_STE_RANGE(&cmd);
96
},
75
+ uint64_t end = start + (1ULL << (range + 1)) - 1;
97
};
76
+ SMMUSIDRange sid_range = {start, end};
77
78
if (CMD_SSEC(&cmd)) {
79
cmd_error = SMMU_CERROR_ILL;
80
break;
81
}
82
-
83
- end = start + (1 << (range + 1)) - 1;
84
trace_smmuv3_cmdq_cfgi_ste_range(start, end);
85
-
86
- for (i = start; i <= end; i++) {
87
- IOMMUMemoryRegion *mr = smmu_iommu_mr(bs, i);
88
- SMMUDevice *sdev;
89
-
90
- if (!mr) {
91
- continue;
92
- }
93
- sdev = container_of(mr, SMMUDevice, iommu);
94
- smmuv3_flush_config(sdev);
95
- }
96
+ g_hash_table_foreach_remove(bs->configs, smmuv3_invalidate_ste,
97
+ &sid_range);
98
break;
99
}
100
case SMMU_CMD_CFGI_CD:
98
--
101
--
99
2.20.1
102
2.20.1
100
103
101
104
diff view generated by jsdifflib
1
We create an OR gate to wire together the overflow IRQs for all the
1
From: Eric Auger <eric.auger@redhat.com>
2
UARTs on the board; this has to have twice the number of inputs as
3
there are UARTs, since each UART feeds it a TX overflow and an RX
4
overflow interrupt line. Replace the hardcoded '10' with a
5
calculation based on the size of the uart[] array in the
6
MPS2TZMachineState. (We rely on OR gate inputs that are never wired
7
up or asserted being treated as always-zero.)
8
2
3
Convert all sid printouts to sid=0x%x.
4
5
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Message-id: 20210309102742.30442-8-eric.auger@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20210215115138.20465-15-peter.maydell@linaro.org
12
---
9
---
13
hw/arm/mps2-tz.c | 11 ++++++++---
10
hw/arm/trace-events | 24 ++++++++++++------------
14
1 file changed, 8 insertions(+), 3 deletions(-)
11
1 file changed, 12 insertions(+), 12 deletions(-)
15
12
16
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
13
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
17
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/mps2-tz.c
15
--- a/hw/arm/trace-events
19
+++ b/hw/arm/mps2-tz.c
16
+++ b/hw/arm/trace-events
20
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
17
@@ -XXX,XX +XXX,XX @@ smmuv3_cmdq_opcode(const char *opcode) "<--- %s"
21
*/
18
smmuv3_cmdq_consume_out(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "prod:%d, cons:%d, prod_wrap:%d, cons_wrap:%d "
22
memory_region_add_subregion(system_memory, 0x80000000, machine->ram);
19
smmuv3_cmdq_consume_error(const char *cmd_name, uint8_t cmd_error) "Error on %s command execution: %d"
23
20
smmuv3_write_mmio(uint64_t addr, uint64_t val, unsigned size, uint32_t r) "addr: 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x(%d)"
24
- /* The overflow IRQs for all UARTs are ORed together.
21
-smmuv3_record_event(const char *type, uint32_t sid) "%s sid=%d"
25
+ /*
22
-smmuv3_find_ste(uint16_t sid, uint32_t features, uint16_t sid_split) "SID:0x%x features:0x%x, sid_split:0x%x"
26
+ * The overflow IRQs for all UARTs are ORed together.
23
+smmuv3_record_event(const char *type, uint32_t sid) "%s sid=0x%x"
27
* Tx, Rx and "combined" IRQs are sent to the NVIC separately.
24
+smmuv3_find_ste(uint16_t sid, uint32_t features, uint16_t sid_split) "sid=0x%x features:0x%x, sid_split:0x%x"
28
- * Create the OR gate for this.
25
smmuv3_find_ste_2lvl(uint64_t strtab_base, uint64_t l1ptr, int l1_ste_offset, uint64_t l2ptr, int l2_ste_offset, int max_l2_ste) "strtab_base:0x%"PRIx64" l1ptr:0x%"PRIx64" l1_off:0x%x, l2ptr:0x%"PRIx64" l2_off:0x%x max_l2_ste:%d"
29
+ * Create the OR gate for this: it has one input for the TX overflow
26
smmuv3_get_ste(uint64_t addr) "STE addr: 0x%"PRIx64
30
+ * and one for the RX overflow for each UART we might have.
27
-smmuv3_translate_disable(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=%d bypass (smmu disabled) iova:0x%"PRIx64" is_write=%d"
31
+ * (If the board has fewer than the maximum possible number of UARTs
28
-smmuv3_translate_bypass(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=%d STE bypass iova:0x%"PRIx64" is_write=%d"
32
+ * those inputs are never wired up and are treated as always-zero.)
29
-smmuv3_translate_abort(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=%d abort on iova:0x%"PRIx64" is_write=%d"
33
*/
30
-smmuv3_translate_success(const char *n, uint16_t sid, uint64_t iova, uint64_t translated, int perm) "%s sid=%d iova=0x%"PRIx64" translated=0x%"PRIx64" perm=0x%x"
34
object_initialize_child(OBJECT(mms), "uart-irq-orgate",
31
+smmuv3_translate_disable(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=0x%x bypass (smmu disabled) iova:0x%"PRIx64" is_write=%d"
35
&mms->uart_irq_orgate, TYPE_OR_IRQ);
32
+smmuv3_translate_bypass(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=0x%x STE bypass iova:0x%"PRIx64" is_write=%d"
36
- object_property_set_int(OBJECT(&mms->uart_irq_orgate), "num-lines", 10,
33
+smmuv3_translate_abort(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=0x%x abort on iova:0x%"PRIx64" is_write=%d"
37
+ object_property_set_int(OBJECT(&mms->uart_irq_orgate), "num-lines",
34
+smmuv3_translate_success(const char *n, uint16_t sid, uint64_t iova, uint64_t translated, int perm) "%s sid=0x%x iova=0x%"PRIx64" translated=0x%"PRIx64" perm=0x%x"
38
+ 2 * ARRAY_SIZE(mms->uart),
35
smmuv3_get_cd(uint64_t addr) "CD addr: 0x%"PRIx64
39
&error_fatal);
36
smmuv3_decode_cd(uint32_t oas) "oas=%d"
40
qdev_realize(DEVICE(&mms->uart_irq_orgate), NULL, &error_fatal);
37
smmuv3_decode_cd_tt(int i, uint32_t tsz, uint64_t ttb, uint32_t granule_sz, bool had) "TT[%d]:tsz:%d ttb:0x%"PRIx64" granule_sz:%d had:%d"
41
qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
38
-smmuv3_cmdq_cfgi_ste(int streamid) "streamid =%d"
39
+smmuv3_cmdq_cfgi_ste(int streamid) "streamid= 0x%x"
40
smmuv3_cmdq_cfgi_ste_range(int start, int end) "start=0x%x - end=0x%x"
41
-smmuv3_cmdq_cfgi_cd(uint32_t sid) "streamid = %d"
42
-smmuv3_config_cache_hit(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache HIT for sid %d (hits=%d, misses=%d, hit rate=%d)"
43
-smmuv3_config_cache_miss(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache MISS for sid %d (hits=%d, misses=%d, hit rate=%d)"
44
-smmuv3_s1_range_inval(int vmid, int asid, uint64_t addr, uint8_t tg, uint64_t num_pages, uint8_t ttl, bool leaf) "vmid =%d asid =%d addr=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64" ttl=%d leaf=%d"
45
+smmuv3_cmdq_cfgi_cd(uint32_t sid) "sid=0x%x"
46
+smmuv3_config_cache_hit(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache HIT for sid=0x%x (hits=%d, misses=%d, hit rate=%d)"
47
+smmuv3_config_cache_miss(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache MISS for sid=0x%x (hits=%d, misses=%d, hit rate=%d)"
48
+smmuv3_s1_range_inval(int vmid, int asid, uint64_t addr, uint8_t tg, uint64_t num_pages, uint8_t ttl, bool leaf) "vmid=%d asid=%d addr=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64" ttl=%d leaf=%d"
49
smmuv3_cmdq_tlbi_nh(void) ""
50
smmuv3_cmdq_tlbi_nh_asid(uint16_t asid) "asid=%d"
51
-smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid %d"
52
+smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid=0x%x"
53
smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu mr=%s"
54
smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu mr=%s"
55
smmuv3_inv_notifiers_iova(const char *name, uint16_t asid, uint64_t iova, uint8_t tg, uint64_t num_pages) "iommu mr=%s asid=%d iova=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64
42
--
56
--
43
2.20.1
57
2.20.1
44
58
45
59
diff view generated by jsdifflib
1
From: schspa <schspa@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
At the moment the following QEMU command line triggers an assertion
3
Missed out on compressing the second half of a predicate
4
failure On xlnx-versal SOC:
4
with length vl % 512 > 256.
5
qemu-system-aarch64 \
6
-machine xlnx-versal-virt -nographic -smp 2 -m 128 \
7
-fsdev local,id=shareid,path=${HOME}/work,security_model=none \
8
-device virtio-9p-device,fsdev=shareid,mount_tag=share \
9
-fsdev local,id=shareid1,path=${HOME}/Music,security_model=none \
10
-device virtio-9p-device,fsdev=shareid1,mount_tag=share1
11
5
12
qemu-system-aarch64: ../migration/savevm.c:860:
6
Adjust all of the x + (y << s) to x | (y << s) as a
13
vmstate_register_with_alias_id:
7
general style fix. Drop the extract64 because the input
14
Assertion `!se->compat || se->instance_id == 0' failed.
8
uint64_t are known to be already zero-extended from the
9
current size of the predicate.
15
10
16
This problem was fixed on arm virt platform in commit f58b39d2d5b
11
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
17
("virtio-mmio: format transport base address in BusClass.get_dev_path")
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
18
13
Message-id: 20210309155305.11301-2-richard.henderson@linaro.org
19
It works perfectly on arm virt platform. but there is still there on
20
xlnx-versal SOC.
21
22
The main difference between arm virt and xlnx-versal is they use
23
different way to create virtio-mmio qdev. on arm virt, it calls
24
sysbus_create_simple("virtio-mmio", base, pic[irq]); which will call
25
sysbus_mmio_map internally and assign base address to subsys device
26
mmio correctly. but xlnx-versal's implements won't do this.
27
28
However, xlnx-versal can't switch to sysbus_create_simple() to create
29
virtio-mmio device. It's because xlnx-versal's cpu use
30
VersalVirt.soc.fpd.apu.mr as it's memory. which is subregion of
31
system_memory. sysbus_create_simple will add virtio to system_memory,
32
which can't be accessed by cpu.
33
34
Besides, xlnx-versal can't add sysbus_mmio_map api call too, because
35
this will add memory region to system_memory, and it can't be added
36
to VersalVirt.soc.fpd.apu.mr again.
37
38
We can solve this by assign correct base address offset on dev_path.
39
40
This path was test on aarch64 virt & xlnx-versal platform.
41
42
Signed-off-by: schspa <schspa@gmail.com>
43
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
44
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
45
---
16
---
46
hw/virtio/virtio-mmio.c | 13 +++++++------
17
target/arm/sve_helper.c | 30 +++++++++++++++++++++---------
47
1 file changed, 7 insertions(+), 6 deletions(-)
18
1 file changed, 21 insertions(+), 9 deletions(-)
48
19
49
diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
20
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
50
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/virtio/virtio-mmio.c
22
--- a/target/arm/sve_helper.c
52
+++ b/hw/virtio/virtio-mmio.c
23
+++ b/target/arm/sve_helper.c
53
@@ -XXX,XX +XXX,XX @@ static char *virtio_mmio_bus_get_dev_path(DeviceState *dev)
24
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_uzp_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
54
BusState *virtio_mmio_bus;
25
if (oprsz <= 8) {
55
VirtIOMMIOProxy *virtio_mmio_proxy;
26
l = compress_bits(n[0] >> odd, esz);
56
char *proxy_path;
27
h = compress_bits(m[0] >> odd, esz);
57
- SysBusDevice *proxy_sbd;
28
- d[0] = extract64(l + (h << (4 * oprsz)), 0, 8 * oprsz);
58
char *path;
29
+ d[0] = l | (h << (4 * oprsz));
59
+ MemoryRegionSection section;
30
} else {
60
31
ARMPredicateReg tmp_m;
61
virtio_mmio_bus = qdev_get_parent_bus(dev);
32
intptr_t oprsz_16 = oprsz / 16;
62
virtio_mmio_proxy = VIRTIO_MMIO(virtio_mmio_bus->parent);
33
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_uzp_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
63
@@ -XXX,XX +XXX,XX @@ static char *virtio_mmio_bus_get_dev_path(DeviceState *dev)
34
h = n[2 * i + 1];
35
l = compress_bits(l >> odd, esz);
36
h = compress_bits(h >> odd, esz);
37
- d[i] = l + (h << 32);
38
+ d[i] = l | (h << 32);
39
}
40
41
- /* For VL which is not a power of 2, the results from M do not
42
- align nicely with the uint64_t for D. Put the aligned results
43
- from M into TMP_M and then copy it into place afterward. */
44
+ /*
45
+ * For VL which is not a multiple of 512, the results from M do not
46
+ * align nicely with the uint64_t for D. Put the aligned results
47
+ * from M into TMP_M and then copy it into place afterward.
48
+ */
49
if (oprsz & 15) {
50
- d[i] = compress_bits(n[2 * i] >> odd, esz);
51
+ int final_shift = (oprsz & 15) * 2;
52
+
53
+ l = n[2 * i + 0];
54
+ h = n[2 * i + 1];
55
+ l = compress_bits(l >> odd, esz);
56
+ h = compress_bits(h >> odd, esz);
57
+ d[i] = l | (h << final_shift);
58
59
for (i = 0; i < oprsz_16; i++) {
60
l = m[2 * i + 0];
61
h = m[2 * i + 1];
62
l = compress_bits(l >> odd, esz);
63
h = compress_bits(h >> odd, esz);
64
- tmp_m.p[i] = l + (h << 32);
65
+ tmp_m.p[i] = l | (h << 32);
66
}
67
- tmp_m.p[i] = compress_bits(m[2 * i] >> odd, esz);
68
+ l = m[2 * i + 0];
69
+ h = m[2 * i + 1];
70
+ l = compress_bits(l >> odd, esz);
71
+ h = compress_bits(h >> odd, esz);
72
+ tmp_m.p[i] = l | (h << final_shift);
73
74
swap_memmove(vd + oprsz / 2, &tmp_m, oprsz / 2);
75
} else {
76
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_uzp_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
77
h = m[2 * i + 1];
78
l = compress_bits(l >> odd, esz);
79
h = compress_bits(h >> odd, esz);
80
- d[oprsz_16 + i] = l + (h << 32);
81
+ d[oprsz_16 + i] = l | (h << 32);
82
}
83
}
64
}
84
}
65
66
/* Otherwise, we append the base address of the transport. */
67
- proxy_sbd = SYS_BUS_DEVICE(virtio_mmio_proxy);
68
- assert(proxy_sbd->num_mmio == 1);
69
- assert(proxy_sbd->mmio[0].memory == &virtio_mmio_proxy->iomem);
70
+ section = memory_region_find(&virtio_mmio_proxy->iomem, 0, 0x200);
71
+ assert(section.mr);
72
73
if (proxy_path) {
74
path = g_strdup_printf("%s/virtio-mmio@" TARGET_FMT_plx, proxy_path,
75
- proxy_sbd->mmio[0].addr);
76
+ section.offset_within_address_space);
77
} else {
78
path = g_strdup_printf("virtio-mmio@" TARGET_FMT_plx,
79
- proxy_sbd->mmio[0].addr);
80
+ section.offset_within_address_space);
81
}
82
+ memory_region_unref(section.mr);
83
+
84
g_free(proxy_path);
85
return path;
86
}
87
--
85
--
88
2.20.1
86
2.20.1
89
87
90
88
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
IDAU is specific to M-profile. KVM only supports A-profile.
3
Wrote too much with low-half zip (zip1) with vl % 512 != 0.
4
Restrict this interface to TCG, as it is pointless (and
5
confusing) on a KVM-only build.
6
4
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Adjust all of the x + (y << s) to x | (y << s) as a style fix.
6
7
We only ever have exact overlap between D, M, and N. Therefore
8
we only need a single temporary, and we do not need to check for
9
partial overlap.
10
11
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20210309155305.11301-3-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20210221222617.2579610-2-f4bug@amsat.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
16
---
13
target/arm/cpu.c | 7 -------
17
target/arm/sve_helper.c | 25 ++++++++++++++-----------
14
target/arm/cpu_tcg.c | 8 ++++++++
18
1 file changed, 14 insertions(+), 11 deletions(-)
15
2 files changed, 8 insertions(+), 7 deletions(-)
16
19
17
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
20
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
18
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.c
22
--- a/target/arm/sve_helper.c
20
+++ b/target/arm/cpu.c
23
+++ b/target/arm/sve_helper.c
21
@@ -XXX,XX +XXX,XX @@ static const TypeInfo arm_cpu_type_info = {
24
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_zip_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
22
.class_init = arm_cpu_class_init,
25
intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
23
};
26
int esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
24
27
intptr_t high = FIELD_EX32(pred_desc, PREDDESC, DATA);
25
-static const TypeInfo idau_interface_type_info = {
28
+ int esize = 1 << esz;
26
- .name = TYPE_IDAU_INTERFACE,
29
uint64_t *d = vd;
27
- .parent = TYPE_INTERFACE,
30
intptr_t i;
28
- .class_size = sizeof(IDAUInterfaceClass),
31
29
-};
32
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_zip_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
30
-
33
mm = extract64(mm, high * half, half);
31
static void arm_cpu_register_types(void)
34
nn = expand_bits(nn, esz);
32
{
35
mm = expand_bits(mm, esz);
33
const size_t cpu_count = ARRAY_SIZE(arm_cpus);
36
- d[0] = nn + (mm << (1 << esz));
34
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_register_types(void)
37
+ d[0] = nn | (mm << esize);
35
if (cpu_count) {
38
} else {
36
size_t i;
39
- ARMPredicateReg tmp_n, tmp_m;
37
40
+ ARMPredicateReg tmp;
38
- type_register_static(&idau_interface_type_info);
41
39
for (i = 0; i < cpu_count; ++i) {
42
/* We produce output faster than we consume input.
40
arm_cpu_register(&arm_cpus[i]);
43
Therefore we must be mindful of possible overlap. */
44
- if ((vn - vd) < (uintptr_t)oprsz) {
45
- vn = memcpy(&tmp_n, vn, oprsz);
46
- }
47
- if ((vm - vd) < (uintptr_t)oprsz) {
48
- vm = memcpy(&tmp_m, vm, oprsz);
49
+ if (vd == vn) {
50
+ vn = memcpy(&tmp, vn, oprsz);
51
+ if (vd == vm) {
52
+ vm = vn;
53
+ }
54
+ } else if (vd == vm) {
55
+ vm = memcpy(&tmp, vm, oprsz);
41
}
56
}
42
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
57
if (high) {
43
index XXXXXXX..XXXXXXX 100644
58
high = oprsz >> 1;
44
--- a/target/arm/cpu_tcg.c
59
}
45
+++ b/target/arm/cpu_tcg.c
60
46
@@ -XXX,XX +XXX,XX @@
61
- if ((high & 3) == 0) {
47
#include "hw/core/tcg-cpu-ops.h"
62
+ if ((oprsz & 7) == 0) {
48
#endif /* CONFIG_TCG */
63
uint32_t *n = vn, *m = vm;
49
#include "internals.h"
64
high >>= 2;
50
+#include "target/arm/idau.h"
65
51
66
- for (i = 0; i < DIV_ROUND_UP(oprsz, 8); i++) {
52
/* CPU models. These are not needed for the AArch64 linux-user build. */
67
+ for (i = 0; i < oprsz / 8; i++) {
53
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
68
uint64_t nn = n[H4(high + i)];
54
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_tcg_cpus[] = {
69
uint64_t mm = m[H4(high + i)];
55
{ .name = "pxa270-c5", .initfn = pxa270c5_initfn },
70
56
};
71
nn = expand_bits(nn, esz);
57
72
mm = expand_bits(mm, esz);
58
+static const TypeInfo idau_interface_type_info = {
73
- d[i] = nn + (mm << (1 << esz));
59
+ .name = TYPE_IDAU_INTERFACE,
74
+ d[i] = nn | (mm << esize);
60
+ .parent = TYPE_INTERFACE,
75
}
61
+ .class_size = sizeof(IDAUInterfaceClass),
76
} else {
62
+};
77
uint8_t *n = vn, *m = vm;
63
+
78
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_zip_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
64
static void arm_tcg_cpu_register_types(void)
79
65
{
80
nn = expand_bits(nn, esz);
66
size_t i;
81
mm = expand_bits(mm, esz);
67
82
- d16[H2(i)] = nn + (mm << (1 << esz));
68
+ type_register_static(&idau_interface_type_info);
83
+ d16[H2(i)] = nn | (mm << esize);
69
for (i = 0; i < ARRAY_SIZE(arm_tcg_cpus); ++i) {
84
}
70
arm_cpu_register(&arm_tcg_cpus[i]);
85
}
71
}
86
}
72
--
87
--
73
2.20.1
88
2.20.1
74
89
75
90
diff view generated by jsdifflib
1
We were previously using the default OSCCLK settings, which are
1
From: Richard Henderson <richard.henderson@linaro.org>
2
correct for the older MPS2 boards (mps2-an385, mps2-an386,
3
mps2-an500, mps2-an511), but wrong for the mps2-an505 and mps2-511
4
implemented in mps2-tz.c. Now we're setting the values explicitly we
5
can fix them to be correct.
6
2
3
Wrote too much with punpk1 with vl % 512 != 0.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210309155305.11301-4-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210215115138.20465-4-peter.maydell@linaro.org
11
---
10
---
12
hw/arm/mps2-tz.c | 4 ++--
11
target/arm/sve_helper.c | 4 ++--
13
1 file changed, 2 insertions(+), 2 deletions(-)
12
1 file changed, 2 insertions(+), 2 deletions(-)
14
13
15
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
14
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/mps2-tz.c
16
--- a/target/arm/sve_helper.c
18
+++ b/hw/arm/mps2-tz.c
17
+++ b/target/arm/sve_helper.c
19
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
18
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_punpk_p)(void *vd, void *vn, uint32_t pred_desc)
20
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
19
high = oprsz >> 1;
21
/* This will need to be per-FPGA image eventually */
20
}
22
qdev_prop_set_uint32(sccdev, "len-oscclk", 3);
21
23
- qdev_prop_set_uint32(sccdev, "oscclk[0]", 50000000);
22
- if ((high & 3) == 0) {
24
- qdev_prop_set_uint32(sccdev, "oscclk[1]", 24576000);
23
+ if ((oprsz & 7) == 0) {
25
+ qdev_prop_set_uint32(sccdev, "oscclk[0]", 40000000);
24
uint32_t *n = vn;
26
+ qdev_prop_set_uint32(sccdev, "oscclk[1]", 24580000);
25
high >>= 2;
27
qdev_prop_set_uint32(sccdev, "oscclk[2]", 25000000);
26
28
sysbus_realize(SYS_BUS_DEVICE(scc), &error_fatal);
27
- for (i = 0; i < DIV_ROUND_UP(oprsz, 8); i++) {
29
return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
28
+ for (i = 0; i < oprsz / 8; i++) {
29
uint64_t nn = n[H4(high + i)];
30
d[i] = expand_bits(nn, 0);
31
}
30
--
32
--
31
2.20.1
33
2.20.1
32
34
33
35
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We will move this code in the next commit. Clean it up
3
Since b64ee454a4a0, all predicate operations should be
4
first to avoid checkpatch.pl errors.
4
using these field macros for predicates.
5
5
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210221222617.2579610-3-f4bug@amsat.org
7
Message-id: 20210309155305.11301-5-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
target/arm/cpu.c | 12 ++++++++----
11
target/arm/sve_helper.c | 6 +++---
12
1 file changed, 8 insertions(+), 4 deletions(-)
12
target/arm/translate-sve.c | 7 +++----
13
2 files changed, 6 insertions(+), 7 deletions(-)
13
14
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
15
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.c
17
--- a/target/arm/sve_helper.c
17
+++ b/target/arm/cpu.c
18
+++ b/target/arm/sve_helper.c
18
@@ -XXX,XX +XXX,XX @@ static void cortex_a8_initfn(Object *obj)
19
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_compact_d)(void *vd, void *vn, void *vg, uint32_t desc)
20
*/
21
int32_t HELPER(sve_last_active_element)(void *vg, uint32_t pred_desc)
22
{
23
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
24
- intptr_t esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2);
25
+ intptr_t words = DIV_ROUND_UP(FIELD_EX32(pred_desc, PREDDESC, OPRSZ), 8);
26
+ intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
27
28
- return last_active_element(vg, DIV_ROUND_UP(oprsz, 8), esz);
29
+ return last_active_element(vg, words, esz);
19
}
30
}
20
31
21
static const ARMCPRegInfo cortexa9_cp_reginfo[] = {
32
void HELPER(sve_splice)(void *vd, void *vn, void *vm, void *vg, uint32_t desc)
22
- /* power_control should be set to maximum latency. Again,
33
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
23
+ /*
34
index XXXXXXX..XXXXXXX 100644
24
+ * power_control should be set to maximum latency. Again,
35
--- a/target/arm/translate-sve.c
25
* default to 0 and set by private hook
36
+++ b/target/arm/translate-sve.c
37
@@ -XXX,XX +XXX,XX @@ static void find_last_active(DisasContext *s, TCGv_i32 ret, int esz, int pg)
26
*/
38
*/
27
{ .name = "A9_PWRCTL", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0,
39
TCGv_ptr t_p = tcg_temp_new_ptr();
28
@@ -XXX,XX +XXX,XX @@ static void cortex_a9_initfn(Object *obj)
40
TCGv_i32 t_desc;
29
set_feature(&cpu->env, ARM_FEATURE_NEON);
41
- unsigned vsz = pred_full_reg_size(s);
30
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
42
- unsigned desc;
31
set_feature(&cpu->env, ARM_FEATURE_EL3);
43
+ unsigned desc = 0;
32
- /* Note that A9 supports the MP extensions even for
44
33
+ /*
45
- desc = vsz - 2;
34
+ * Note that A9 supports the MP extensions even for
46
- desc = deposit32(desc, SIMD_DATA_SHIFT, 2, esz);
35
* A9UP and single-core A9MP (which are both different
47
+ desc = FIELD_DP32(desc, PREDDESC, OPRSZ, pred_full_reg_size(s));
36
* and valid configurations; we don't model A9UP).
48
+ desc = FIELD_DP32(desc, PREDDESC, ESZ, esz);
37
*/
49
38
@@ -XXX,XX +XXX,XX @@ static uint64_t a15_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
50
tcg_gen_addi_ptr(t_p, cpu_env, pred_full_reg_offset(s, pg));
39
{
51
t_desc = tcg_const_i32(desc);
40
MachineState *ms = MACHINE(qdev_get_machine());
41
42
- /* Linux wants the number of processors from here.
43
+ /*
44
+ * Linux wants the number of processors from here.
45
* Might as well set the interrupt-controller bit too.
46
*/
47
return ((ms->smp.cpus - 1) << 24) | (1 << 23);
48
@@ -XXX,XX +XXX,XX @@ static void cortex_a7_initfn(Object *obj)
49
cpu->isar.id_mmfr1 = 0x40000000;
50
cpu->isar.id_mmfr2 = 0x01240000;
51
cpu->isar.id_mmfr3 = 0x02102211;
52
- /* a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but
53
+ /*
54
+ * a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but
55
* table 4-41 gives 0x02101110, which includes the arm div insns.
56
*/
57
cpu->isar.id_isar0 = 0x02101110;
58
--
52
--
59
2.20.1
53
2.20.1
60
54
61
55
diff view generated by jsdifflib
1
The mps2-tz code uses PPCPortInfo data structures to define what
1
From: Richard Henderson <richard.henderson@linaro.org>
2
devices are present and how they are wired up. Currently we use
3
these to specify device types and addresses, but hard-code the
4
interrupt line wiring in each make_* helper function. This works for
5
the two boards we have at the moment, but the AN524 has some devices
6
with different interrupt assignments.
7
2
8
This commit adds the framework to allow PPCPortInfo structures to
3
Since b64ee454a4a0, all predicate operations should be
9
specify interrupt numbers. We add an array of interrupt numbers to
4
using these field macros for predicates.
10
the PPCPortInfo struct, and pass it through to the make_* helpers.
11
The following commit will change the make_* helpers over to using the
12
framework.
13
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210309155305.11301-6-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20210215115138.20465-13-peter.maydell@linaro.org
17
---
10
---
18
hw/arm/mps2-tz.c | 36 ++++++++++++++++++++++++------------
11
target/arm/sve_helper.c | 30 ++++++++++++++----------------
19
1 file changed, 24 insertions(+), 12 deletions(-)
12
target/arm/translate-sve.c | 4 ++--
13
2 files changed, 16 insertions(+), 18 deletions(-)
20
14
21
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
15
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
22
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/mps2-tz.c
17
--- a/target/arm/sve_helper.c
24
+++ b/hw/arm/mps2-tz.c
18
+++ b/target/arm/sve_helper.c
25
@@ -XXX,XX +XXX,XX @@ static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
19
@@ -XXX,XX +XXX,XX @@ static uint32_t do_zero(ARMPredicateReg *d, intptr_t oprsz)
26
* needs to be plugged into the downstream end of the PPC port.
20
void HELPER(sve_brkpa)(void *vd, void *vn, void *vm, void *vg,
27
*/
21
uint32_t pred_desc)
28
typedef MemoryRegion *MakeDevFn(MPS2TZMachineState *mms, void *opaque,
29
- const char *name, hwaddr size);
30
+ const char *name, hwaddr size,
31
+ const int *irqs);
32
33
typedef struct PPCPortInfo {
34
const char *name;
35
@@ -XXX,XX +XXX,XX @@ typedef struct PPCPortInfo {
36
void *opaque;
37
hwaddr addr;
38
hwaddr size;
39
+ int irqs[3]; /* currently no device needs more IRQ lines than this */
40
} PPCPortInfo;
41
42
typedef struct PPCInfo {
43
@@ -XXX,XX +XXX,XX @@ typedef struct PPCInfo {
44
} PPCInfo;
45
46
static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
47
- void *opaque,
48
- const char *name, hwaddr size)
49
+ void *opaque,
50
+ const char *name, hwaddr size,
51
+ const int *irqs)
52
{
22
{
53
/* Initialize, configure and realize a TYPE_UNIMPLEMENTED_DEVICE,
23
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
54
* and return a pointer to its MemoryRegion.
24
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
55
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
25
if (last_active_pred(vn, vg, oprsz)) {
26
compute_brk_z(vd, vm, vg, oprsz, true);
27
} else {
28
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_brkpa)(void *vd, void *vn, void *vm, void *vg,
29
uint32_t HELPER(sve_brkpas)(void *vd, void *vn, void *vm, void *vg,
30
uint32_t pred_desc)
31
{
32
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
33
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
34
if (last_active_pred(vn, vg, oprsz)) {
35
return compute_brks_z(vd, vm, vg, oprsz, true);
36
} else {
37
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(sve_brkpas)(void *vd, void *vn, void *vm, void *vg,
38
void HELPER(sve_brkpb)(void *vd, void *vn, void *vm, void *vg,
39
uint32_t pred_desc)
40
{
41
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
42
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
43
if (last_active_pred(vn, vg, oprsz)) {
44
compute_brk_z(vd, vm, vg, oprsz, false);
45
} else {
46
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_brkpb)(void *vd, void *vn, void *vm, void *vg,
47
uint32_t HELPER(sve_brkpbs)(void *vd, void *vn, void *vm, void *vg,
48
uint32_t pred_desc)
49
{
50
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
51
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
52
if (last_active_pred(vn, vg, oprsz)) {
53
return compute_brks_z(vd, vm, vg, oprsz, false);
54
} else {
55
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(sve_brkpbs)(void *vd, void *vn, void *vm, void *vg,
56
57
void HELPER(sve_brka_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
58
{
59
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
60
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
61
compute_brk_z(vd, vn, vg, oprsz, true);
56
}
62
}
57
63
58
static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
64
uint32_t HELPER(sve_brkas_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
59
- const char *name, hwaddr size)
60
+ const char *name, hwaddr size,
61
+ const int *irqs)
62
{
65
{
63
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
66
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
64
CMSDKAPBUART *uart = opaque;
67
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
65
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
68
return compute_brks_z(vd, vn, vg, oprsz, true);
66
}
69
}
67
70
68
static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
71
void HELPER(sve_brkb_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
69
- const char *name, hwaddr size)
70
+ const char *name, hwaddr size,
71
+ const int *irqs)
72
{
72
{
73
MPS2SCC *scc = opaque;
73
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
74
DeviceState *sccdev;
74
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
75
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
75
compute_brk_z(vd, vn, vg, oprsz, false);
76
}
76
}
77
77
78
static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
78
uint32_t HELPER(sve_brkbs_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
79
- const char *name, hwaddr size)
80
+ const char *name, hwaddr size,
81
+ const int *irqs)
82
{
79
{
83
MPS2FPGAIO *fpgaio = opaque;
80
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
84
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
81
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
85
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
82
return compute_brks_z(vd, vn, vg, oprsz, false);
86
}
83
}
87
84
88
static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
85
void HELPER(sve_brka_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
89
- const char *name, hwaddr size)
90
+ const char *name, hwaddr size,
91
+ const int *irqs)
92
{
86
{
93
SysBusDevice *s;
87
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
94
NICInfo *nd = &nd_table[0];
88
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
95
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
89
compute_brk_m(vd, vn, vg, oprsz, true);
96
}
90
}
97
91
98
static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
92
uint32_t HELPER(sve_brkas_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
99
- const char *name, hwaddr size)
100
+ const char *name, hwaddr size,
101
+ const int *irqs)
102
{
93
{
103
TZMPC *mpc = opaque;
94
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
104
int i = mpc - &mms->ssram_mpc[0];
95
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
105
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
96
return compute_brks_m(vd, vn, vg, oprsz, true);
106
}
97
}
107
98
108
static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
99
void HELPER(sve_brkb_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
109
- const char *name, hwaddr size)
110
+ const char *name, hwaddr size,
111
+ const int *irqs)
112
{
100
{
113
PL080State *dma = opaque;
101
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
114
int i = dma - &mms->dma[0];
102
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
115
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
103
compute_brk_m(vd, vn, vg, oprsz, false);
116
}
104
}
117
105
118
static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
106
uint32_t HELPER(sve_brkbs_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
119
- const char *name, hwaddr size)
120
+ const char *name, hwaddr size,
121
+ const int *irqs)
122
{
107
{
123
/*
108
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
124
* The AN505 has five PL022 SPI controllers.
109
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
125
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
110
return compute_brks_m(vd, vn, vg, oprsz, false);
126
}
111
}
127
112
128
static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
113
void HELPER(sve_brkn)(void *vd, void *vn, void *vg, uint32_t pred_desc)
129
- const char *name, hwaddr size)
130
+ const char *name, hwaddr size,
131
+ const int *irqs)
132
{
114
{
133
ArmSbconI2CState *i2c = opaque;
115
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
134
SysBusDevice *s;
116
-
135
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
117
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
136
continue;
118
if (!last_active_pred(vn, vg, oprsz)) {
137
}
119
do_zero(vd, oprsz);
138
120
}
139
- mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size);
121
@@ -XXX,XX +XXX,XX @@ static uint32_t predtest_ones(ARMPredicateReg *d, intptr_t oprsz,
140
+ mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size,
122
141
+ pinfo->irqs);
123
uint32_t HELPER(sve_brkns)(void *vd, void *vn, void *vg, uint32_t pred_desc)
142
portname = g_strdup_printf("port[%d]", port);
124
{
143
object_property_set_link(OBJECT(ppc), portname, OBJECT(mr),
125
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
144
&error_fatal);
126
-
127
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
128
if (last_active_pred(vn, vg, oprsz)) {
129
return predtest_ones(vd, oprsz, -1);
130
} else {
131
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
132
index XXXXXXX..XXXXXXX 100644
133
--- a/target/arm/translate-sve.c
134
+++ b/target/arm/translate-sve.c
135
@@ -XXX,XX +XXX,XX @@ static bool do_brk3(DisasContext *s, arg_rprr_s *a,
136
TCGv_ptr n = tcg_temp_new_ptr();
137
TCGv_ptr m = tcg_temp_new_ptr();
138
TCGv_ptr g = tcg_temp_new_ptr();
139
- TCGv_i32 t = tcg_const_i32(vsz - 2);
140
+ TCGv_i32 t = tcg_const_i32(FIELD_DP32(0, PREDDESC, OPRSZ, vsz));
141
142
tcg_gen_addi_ptr(d, cpu_env, pred_full_reg_offset(s, a->rd));
143
tcg_gen_addi_ptr(n, cpu_env, pred_full_reg_offset(s, a->rn));
144
@@ -XXX,XX +XXX,XX @@ static bool do_brk2(DisasContext *s, arg_rpr_s *a,
145
TCGv_ptr d = tcg_temp_new_ptr();
146
TCGv_ptr n = tcg_temp_new_ptr();
147
TCGv_ptr g = tcg_temp_new_ptr();
148
- TCGv_i32 t = tcg_const_i32(vsz - 2);
149
+ TCGv_i32 t = tcg_const_i32(FIELD_DP32(0, PREDDESC, OPRSZ, vsz));
150
151
tcg_gen_addi_ptr(d, cpu_env, pred_full_reg_offset(s, a->rd));
152
tcg_gen_addi_ptr(n, cpu_env, pred_full_reg_offset(s, a->rn));
145
--
153
--
146
2.20.1
154
2.20.1
147
155
148
156
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The STATUS register will be reset to IDLE in
3
Since b64ee454a4a0, all predicate operations should be
4
cnpcm7xx_smbus_enter_reset(), no need to preset
4
using these field macros for predicates.
5
it in instance_init().
6
5
7
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Hao Wu <wuhaotsh@google.com>
7
Message-id: 20210309155305.11301-7-richard.henderson@linaro.org
9
Message-id: 20210228224813.312532-1-f4bug@amsat.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
hw/i2c/npcm7xx_smbus.c | 1 -
11
target/arm/sve_helper.c | 6 +++---
13
1 file changed, 1 deletion(-)
12
target/arm/translate-sve.c | 6 +++---
13
2 files changed, 6 insertions(+), 6 deletions(-)
14
14
15
diff --git a/hw/i2c/npcm7xx_smbus.c b/hw/i2c/npcm7xx_smbus.c
15
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/i2c/npcm7xx_smbus.c
17
--- a/target/arm/sve_helper.c
18
+++ b/hw/i2c/npcm7xx_smbus.c
18
+++ b/target/arm/sve_helper.c
19
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_smbus_init(Object *obj)
19
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(sve_brkns)(void *vd, void *vn, void *vg, uint32_t pred_desc)
20
sysbus_init_mmio(sbd, &s->iomem);
20
21
21
uint64_t HELPER(sve_cntp)(void *vn, void *vg, uint32_t pred_desc)
22
s->bus = i2c_init_bus(DEVICE(s), "i2c-bus");
22
{
23
- s->status = NPCM7XX_SMBUS_STATUS_IDLE;
23
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
24
}
24
- intptr_t esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2);
25
25
+ intptr_t words = DIV_ROUND_UP(FIELD_EX32(pred_desc, PREDDESC, OPRSZ), 8);
26
static const VMStateDescription vmstate_npcm7xx_smbus = {
26
+ intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
27
uint64_t *n = vn, *g = vg, sum = 0, mask = pred_esz_masks[esz];
28
intptr_t i;
29
30
- for (i = 0; i < DIV_ROUND_UP(oprsz, 8); ++i) {
31
+ for (i = 0; i < words; ++i) {
32
uint64_t t = n[i] & g[i] & mask;
33
sum += ctpop64(t);
34
}
35
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/translate-sve.c
38
+++ b/target/arm/translate-sve.c
39
@@ -XXX,XX +XXX,XX @@ static void do_cntp(DisasContext *s, TCGv_i64 val, int esz, int pn, int pg)
40
} else {
41
TCGv_ptr t_pn = tcg_temp_new_ptr();
42
TCGv_ptr t_pg = tcg_temp_new_ptr();
43
- unsigned desc;
44
+ unsigned desc = 0;
45
TCGv_i32 t_desc;
46
47
- desc = psz - 2;
48
- desc = deposit32(desc, SIMD_DATA_SHIFT, 2, esz);
49
+ desc = FIELD_DP32(desc, PREDDESC, OPRSZ, psz);
50
+ desc = FIELD_DP32(desc, PREDDESC, ESZ, esz);
51
52
tcg_gen_addi_ptr(t_pn, cpu_env, pred_full_reg_offset(s, pn));
53
tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, pg));
27
--
54
--
28
2.20.1
55
2.20.1
29
56
30
57
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Always perform one call instead of two for 16-byte operands.
3
Since b64ee454a4a0, all predicate operations should be
4
Use byte loads/stores directly into the vector register file
4
using these field macros for predicates.
5
instead of extractions and deposits to a 64-bit local variable.
6
7
In order to easily receive pointers into the vector register file,
8
convert the helper to the gvec out-of-line signature. Move the
9
helper into vec_helper.c, where it can make use of H1 and clear_tail.
10
5
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Message-id: 20210309155305.11301-8-richard.henderson@linaro.org
13
Tested-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20210224230532.276878-1-richard.henderson@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
10
---
17
target/arm/helper-a64.h | 2 +-
11
target/arm/sve_helper.c | 4 ++--
18
target/arm/helper-a64.c | 32 ---------------------
12
target/arm/translate-sve.c | 7 ++++---
19
target/arm/translate-a64.c | 58 +++++---------------------------------
13
2 files changed, 6 insertions(+), 5 deletions(-)
20
target/arm/vec_helper.c | 48 +++++++++++++++++++++++++++++++
21
4 files changed, 56 insertions(+), 84 deletions(-)
22
14
23
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
15
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
24
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/helper-a64.h
17
--- a/target/arm/sve_helper.c
26
+++ b/target/arm/helper-a64.h
18
+++ b/target/arm/sve_helper.c
27
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_cmps_a64, i64, f32, f32, ptr)
19
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(sve_cntp)(void *vn, void *vg, uint32_t pred_desc)
28
DEF_HELPER_3(vfp_cmpes_a64, i64, f32, f32, ptr)
20
29
DEF_HELPER_3(vfp_cmpd_a64, i64, f64, f64, ptr)
21
uint32_t HELPER(sve_while)(void *vd, uint32_t count, uint32_t pred_desc)
30
DEF_HELPER_3(vfp_cmped_a64, i64, f64, f64, ptr)
22
{
31
-DEF_HELPER_FLAGS_5(simd_tbl, TCG_CALL_NO_RWG_SE, i64, env, i64, i64, i32, i32)
23
- uintptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
32
+DEF_HELPER_FLAGS_4(simd_tblx, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
- intptr_t esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2);
33
DEF_HELPER_FLAGS_3(vfp_mulxs, TCG_CALL_NO_RWG, f32, f32, f32, ptr)
25
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
34
DEF_HELPER_FLAGS_3(vfp_mulxd, TCG_CALL_NO_RWG, f64, f64, f64, ptr)
26
+ intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
35
DEF_HELPER_FLAGS_3(neon_ceq_f64, TCG_CALL_NO_RWG, i64, i64, i64, ptr)
27
uint64_t esz_mask = pred_esz_masks[esz];
36
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
28
ARMPredicateReg *d = vd;
29
uint32_t flags;
30
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
37
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/helper-a64.c
32
--- a/target/arm/translate-sve.c
39
+++ b/target/arm/helper-a64.c
33
+++ b/target/arm/translate-sve.c
40
@@ -XXX,XX +XXX,XX @@ float64 HELPER(vfp_mulxd)(float64 a, float64 b, void *fpstp)
34
@@ -XXX,XX +XXX,XX @@ static bool trans_WHILE(DisasContext *s, arg_WHILE *a)
41
return float64_mul(a, b, fpst);
35
TCGv_i64 op0, op1, t0, t1, tmax;
42
}
36
TCGv_i32 t2, t3;
43
37
TCGv_ptr ptr;
44
-uint64_t HELPER(simd_tbl)(CPUARMState *env, uint64_t result, uint64_t indices,
38
- unsigned desc, vsz = vec_full_reg_size(s);
45
- uint32_t rn, uint32_t numregs)
39
+ unsigned vsz = vec_full_reg_size(s);
46
-{
40
+ unsigned desc = 0;
47
- /* Helper function for SIMD TBL and TBX. We have to do the table
41
TCGCond cond;
48
- * lookup part for the 64 bits worth of indices we're passed in.
42
49
- * result is the initial results vector (either zeroes for TBL
43
if (!sve_access_check(s)) {
50
- * or some guest values for TBX), rn the register number where
44
@@ -XXX,XX +XXX,XX @@ static bool trans_WHILE(DisasContext *s, arg_WHILE *a)
51
- * the table starts, and numregs the number of registers in the table.
45
/* Scale elements to bits. */
52
- * We return the results of the lookups.
46
tcg_gen_shli_i32(t2, t2, a->esz);
53
- */
47
54
- int shift;
48
- desc = (vsz / 8) - 2;
55
-
49
- desc = deposit32(desc, SIMD_DATA_SHIFT, 2, a->esz);
56
- for (shift = 0; shift < 64; shift += 8) {
50
+ desc = FIELD_DP32(desc, PREDDESC, OPRSZ, vsz / 8);
57
- int index = extract64(indices, shift, 8);
51
+ desc = FIELD_DP32(desc, PREDDESC, ESZ, a->esz);
58
- if (index < 16 * numregs) {
52
t3 = tcg_const_i32(desc);
59
- /* Convert index (a byte offset into the virtual table
53
60
- * which is a series of 128-bit vectors concatenated)
54
ptr = tcg_temp_new_ptr();
61
- * into the correct register element plus a bit offset
62
- * into that element, bearing in mind that the table
63
- * can wrap around from V31 to V0.
64
- */
65
- int elt = (rn * 2 + (index >> 3)) % 64;
66
- int bitidx = (index & 7) * 8;
67
- uint64_t *q = aa64_vfp_qreg(env, elt >> 1);
68
- uint64_t val = extract64(q[elt & 1], bitidx, 8);
69
-
70
- result = deposit64(result, shift, 8, val);
71
- }
72
- }
73
- return result;
74
-}
75
-
76
/* 64bit/double versions of the neon float compare functions */
77
uint64_t HELPER(neon_ceq_f64)(float64 a, float64 b, void *fpstp)
78
{
79
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/target/arm/translate-a64.c
82
+++ b/target/arm/translate-a64.c
83
@@ -XXX,XX +XXX,XX @@ static void disas_simd_tb(DisasContext *s, uint32_t insn)
84
int rm = extract32(insn, 16, 5);
85
int rn = extract32(insn, 5, 5);
86
int rd = extract32(insn, 0, 5);
87
- int is_tblx = extract32(insn, 12, 1);
88
- int len = extract32(insn, 13, 2);
89
- TCGv_i64 tcg_resl, tcg_resh, tcg_idx;
90
- TCGv_i32 tcg_regno, tcg_numregs;
91
+ int is_tbx = extract32(insn, 12, 1);
92
+ int len = (extract32(insn, 13, 2) + 1) * 16;
93
94
if (op2 != 0) {
95
unallocated_encoding(s);
96
@@ -XXX,XX +XXX,XX @@ static void disas_simd_tb(DisasContext *s, uint32_t insn)
97
return;
98
}
99
100
- /* This does a table lookup: for every byte element in the input
101
- * we index into a table formed from up to four vector registers,
102
- * and then the output is the result of the lookups. Our helper
103
- * function does the lookup operation for a single 64 bit part of
104
- * the input.
105
- */
106
- tcg_resl = tcg_temp_new_i64();
107
- tcg_resh = NULL;
108
-
109
- if (is_tblx) {
110
- read_vec_element(s, tcg_resl, rd, 0, MO_64);
111
- } else {
112
- tcg_gen_movi_i64(tcg_resl, 0);
113
- }
114
-
115
- if (is_q) {
116
- tcg_resh = tcg_temp_new_i64();
117
- if (is_tblx) {
118
- read_vec_element(s, tcg_resh, rd, 1, MO_64);
119
- } else {
120
- tcg_gen_movi_i64(tcg_resh, 0);
121
- }
122
- }
123
-
124
- tcg_idx = tcg_temp_new_i64();
125
- tcg_regno = tcg_const_i32(rn);
126
- tcg_numregs = tcg_const_i32(len + 1);
127
- read_vec_element(s, tcg_idx, rm, 0, MO_64);
128
- gen_helper_simd_tbl(tcg_resl, cpu_env, tcg_resl, tcg_idx,
129
- tcg_regno, tcg_numregs);
130
- if (is_q) {
131
- read_vec_element(s, tcg_idx, rm, 1, MO_64);
132
- gen_helper_simd_tbl(tcg_resh, cpu_env, tcg_resh, tcg_idx,
133
- tcg_regno, tcg_numregs);
134
- }
135
- tcg_temp_free_i64(tcg_idx);
136
- tcg_temp_free_i32(tcg_regno);
137
- tcg_temp_free_i32(tcg_numregs);
138
-
139
- write_vec_element(s, tcg_resl, rd, 0, MO_64);
140
- tcg_temp_free_i64(tcg_resl);
141
-
142
- if (is_q) {
143
- write_vec_element(s, tcg_resh, rd, 1, MO_64);
144
- tcg_temp_free_i64(tcg_resh);
145
- }
146
- clear_vec_high(s, is_q, rd);
147
+ tcg_gen_gvec_2_ptr(vec_full_reg_offset(s, rd),
148
+ vec_full_reg_offset(s, rm), cpu_env,
149
+ is_q ? 16 : 8, vec_full_reg_size(s),
150
+ (len << 6) | (is_tbx << 5) | rn,
151
+ gen_helper_simd_tblx);
152
}
153
154
/* ZIP/UZP/TRN
155
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
156
index XXXXXXX..XXXXXXX 100644
157
--- a/target/arm/vec_helper.c
158
+++ b/target/arm/vec_helper.c
159
@@ -XXX,XX +XXX,XX @@ DO_VRINT_RMODE(gvec_vrint_rm_h, helper_rinth, uint16_t)
160
DO_VRINT_RMODE(gvec_vrint_rm_s, helper_rints, uint32_t)
161
162
#undef DO_VRINT_RMODE
163
+
164
+#ifdef TARGET_AARCH64
165
+void HELPER(simd_tblx)(void *vd, void *vm, void *venv, uint32_t desc)
166
+{
167
+ const uint8_t *indices = vm;
168
+ CPUARMState *env = venv;
169
+ size_t oprsz = simd_oprsz(desc);
170
+ uint32_t rn = extract32(desc, SIMD_DATA_SHIFT, 5);
171
+ bool is_tbx = extract32(desc, SIMD_DATA_SHIFT + 5, 1);
172
+ uint32_t table_len = desc >> (SIMD_DATA_SHIFT + 6);
173
+ union {
174
+ uint8_t b[16];
175
+ uint64_t d[2];
176
+ } result;
177
+
178
+ /*
179
+ * We must construct the final result in a temp, lest the output
180
+ * overlaps the input table. For TBL, begin with zero; for TBX,
181
+ * begin with the original register contents. Note that we always
182
+ * copy 16 bytes here to avoid an extra branch; clearing the high
183
+ * bits of the register for oprsz == 8 is handled below.
184
+ */
185
+ if (is_tbx) {
186
+ memcpy(&result, vd, 16);
187
+ } else {
188
+ memset(&result, 0, 16);
189
+ }
190
+
191
+ for (size_t i = 0; i < oprsz; ++i) {
192
+ uint32_t index = indices[H1(i)];
193
+
194
+ if (index < table_len) {
195
+ /*
196
+ * Convert index (a byte offset into the virtual table
197
+ * which is a series of 128-bit vectors concatenated)
198
+ * into the correct register element, bearing in mind
199
+ * that the table can wrap around from V31 to V0.
200
+ */
201
+ const uint8_t *table = (const uint8_t *)
202
+ aa64_vfp_qreg(env, (rn + (index >> 4)) % 32);
203
+ result.b[H1(i)] = table[H1(index % 16)];
204
+ }
205
+ }
206
+
207
+ memcpy(vd, &result, 16);
208
+ clear_tail(vd, oprsz, simd_maxsz(desc));
209
+}
210
+#endif
211
--
55
--
212
2.20.1
56
2.20.1
213
57
214
58
diff view generated by jsdifflib
1
From: Peter Collingbourne <pcc@google.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Section D6.7 of the ARM ARM states:
3
With the reduction operations, we intentionally increase maxsz to
4
the next power of 2, so as to fill out the reduction tree correctly.
5
Since e2e7168a214b, oprsz must equal maxsz, with exceptions for small
6
vectors, so this triggers an assertion for vector sizes > 32 that are
7
not themselves a power of 2.
4
8
5
For the purpose of determining Tag Check Fault handling, unprivileged
9
Pass the power-of-two value in the simd_data field instead.
6
load and store instructions are treated as if executed at EL0 when
7
executed at either:
8
- EL1, when the Effective value of PSTATE.UAO is 0.
9
- EL2, when both the Effective value of HCR_EL2.{E2H, TGE} is {1, 1}
10
and the Effective value of PSTATE.UAO is 0.
11
10
12
ARM has confirmed a defect in the pseudocode function
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
AArch64.TagCheckFault that makes it inconsistent with the above
12
Message-id: 20210309155305.11301-9-richard.henderson@linaro.org
14
wording. The remedy is to adjust references to PSTATE.EL in that
15
function to instead refer to AArch64.AccessUsesEL(acctype), so
16
that unprivileged instructions use SCTLR_EL1.TCF0 and TFSRE0_EL1.
17
The exception type for synchronous tag check faults remains unchanged.
18
19
This patch implements the described change by partially reverting
20
commits 50244cc76abc and cc97b0019bb5.
21
22
Signed-off-by: Peter Collingbourne <pcc@google.com>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Message-id: 20210219201820.2672077-1-pcc@google.com
25
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
---
15
---
28
target/arm/helper.c | 2 +-
16
target/arm/sve_helper.c | 2 +-
29
target/arm/mte_helper.c | 13 +++++++++----
17
target/arm/translate-sve.c | 2 +-
30
2 files changed, 10 insertions(+), 5 deletions(-)
18
2 files changed, 2 insertions(+), 2 deletions(-)
31
19
32
diff --git a/target/arm/helper.c b/target/arm/helper.c
20
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
33
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/helper.c
22
--- a/target/arm/sve_helper.c
35
+++ b/target/arm/helper.c
23
+++ b/target/arm/sve_helper.c
36
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
24
@@ -XXX,XX +XXX,XX @@ static TYPE NAME##_reduce(TYPE *data, float_status *status, uintptr_t n) \
37
if (FIELD_EX32(flags, TBFLAG_A64, UNPRIV)
25
} \
38
&& tbid
26
uint64_t HELPER(NAME)(void *vn, void *vg, void *vs, uint32_t desc) \
39
&& !(env->pstate & PSTATE_TCO)
27
{ \
40
- && (sctlr & SCTLR_TCF)
28
- uintptr_t i, oprsz = simd_oprsz(desc), maxsz = simd_maxsz(desc); \
41
+ && (sctlr & SCTLR_TCF0)
29
+ uintptr_t i, oprsz = simd_oprsz(desc), maxsz = simd_data(desc); \
42
&& allocation_tag_access_enabled(env, 0, sctlr)) {
30
TYPE data[sizeof(ARMVectorReg) / sizeof(TYPE)]; \
43
flags = FIELD_DP32(flags, TBFLAG_A64, MTE0_ACTIVE, 1);
31
for (i = 0; i < oprsz; ) { \
44
}
32
uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
45
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
33
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
46
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/mte_helper.c
35
--- a/target/arm/translate-sve.c
48
+++ b/target/arm/mte_helper.c
36
+++ b/target/arm/translate-sve.c
49
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
37
@@ -XXX,XX +XXX,XX @@ static void do_reduce(DisasContext *s, arg_rpr_esz *a,
50
reg_el = regime_el(env, arm_mmu_idx);
38
{
51
sctlr = env->cp15.sctlr_el[reg_el];
39
unsigned vsz = vec_full_reg_size(s);
52
40
unsigned p2vsz = pow2ceil(vsz);
53
- el = arm_current_el(env);
41
- TCGv_i32 t_desc = tcg_const_i32(simd_desc(vsz, p2vsz, 0));
54
- if (el == 0) {
42
+ TCGv_i32 t_desc = tcg_const_i32(simd_desc(vsz, vsz, p2vsz));
55
+ switch (arm_mmu_idx) {
43
TCGv_ptr t_zn, t_pg, status;
56
+ case ARMMMUIdx_E10_0:
44
TCGv_i64 temp;
57
+ case ARMMMUIdx_E20_0:
58
+ el = 0;
59
tcf = extract64(sctlr, 38, 2);
60
- } else {
61
+ break;
62
+ default:
63
+ el = reg_el;
64
tcf = extract64(sctlr, 40, 2);
65
}
66
67
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
68
env->exception.vaddress = dirty_ptr;
69
70
is_write = FIELD_EX32(desc, MTEDESC, WRITE);
71
- syn = syn_data_abort_no_iss(el != 0, 0, 0, 0, 0, is_write, 0x11);
72
+ syn = syn_data_abort_no_iss(arm_current_el(env) != 0, 0, 0, 0, 0,
73
+ is_write, 0x11);
74
raise_exception(env, EXCP_DATA_ABORT, syn, exception_target_el(env));
75
/* noreturn, but fall through to the assert anyway */
76
45
77
--
46
--
78
2.20.1
47
2.20.1
79
48
80
49
diff view generated by jsdifflib
1
For a long time now the UI layer has guaranteed that the console
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
surface is always 32 bits per pixel RGB. Remove the legacy dead
3
code from the tc6393xb display device which was handling the
4
possibility that the console surface was some other format.
5
2
3
Currently the emulated EMAC for sun8i always traverses the transmit queue
4
from the head when transferring packets. It searches for a list of consecutive
5
descriptors whichs are flagged as ready for processing and transmits their payloads
6
accordingly. The controller stops processing once it finds a descriptor that is not
7
marked ready.
8
9
While the above behaviour works in most situations, it is not the same as the actual
10
EMAC in hardware. Actual hardware uses the TX_CUR_DESC register value to keep track
11
of the last position in the transmit queue and continues processing from that position
12
when software triggers the start of DMA processing. The currently emulated behaviour can
13
lead to packet loss on transmit when software fills the transmit queue with ready
14
descriptors that overlap the tail of the circular list.
15
16
This commit modifies the emulated EMAC for sun8i such that it processes
17
the transmit queue using the TX_CUR_DESC register in the same way as hardware.
18
19
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
20
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
21
Message-id: 20210310195820.21950-2-nieklinnenbank@gmail.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215103215.4944-3-peter.maydell@linaro.org
9
---
23
---
10
include/ui/console.h | 10 ----------
24
hw/net/allwinner-sun8i-emac.c | 62 +++++++++++++++++++----------------
11
hw/display/tc6393xb.c | 33 +--------------------------------
25
1 file changed, 34 insertions(+), 28 deletions(-)
12
2 files changed, 1 insertion(+), 42 deletions(-)
13
26
14
diff --git a/include/ui/console.h b/include/ui/console.h
27
diff --git a/hw/net/allwinner-sun8i-emac.c b/hw/net/allwinner-sun8i-emac.c
15
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
16
--- a/include/ui/console.h
29
--- a/hw/net/allwinner-sun8i-emac.c
17
+++ b/include/ui/console.h
30
+++ b/hw/net/allwinner-sun8i-emac.c
18
@@ -XXX,XX +XXX,XX @@ PixelFormat qemu_default_pixelformat(int bpp);
31
@@ -XXX,XX +XXX,XX @@ static void allwinner_sun8i_emac_update_irq(AwSun8iEmacState *s)
19
DisplaySurface *qemu_create_displaysurface(int width, int height);
32
qemu_set_irq(s->irq, (s->int_sta & s->int_en) != 0);
20
void qemu_free_displaysurface(DisplaySurface *surface);
33
}
21
34
22
-static inline int is_surface_bgr(DisplaySurface *surface)
35
-static uint32_t allwinner_sun8i_emac_next_desc(AwSun8iEmacState *s,
23
-{
36
- FrameDescriptor *desc,
24
- if (PIXMAN_FORMAT_BPP(surface->format) == 32 &&
37
- size_t min_size)
25
- PIXMAN_FORMAT_TYPE(surface->format) == PIXMAN_TYPE_ABGR) {
38
+static bool allwinner_sun8i_emac_desc_owned(FrameDescriptor *desc,
26
- return 1;
39
+ size_t min_buf_size)
40
{
41
- uint32_t paddr = desc->next;
42
-
43
- dma_memory_read(&s->dma_as, paddr, desc, sizeof(*desc));
44
-
45
- if ((desc->status & DESC_STATUS_CTL) &&
46
- (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_size) {
47
- return paddr;
27
- } else {
48
- } else {
28
- return 0;
49
- return 0;
29
- }
50
- }
30
-}
51
+ return (desc->status & DESC_STATUS_CTL) && (min_buf_size == 0 ||
31
-
52
+ (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_buf_size);
32
static inline int is_buffer_shared(DisplaySurface *surface)
53
}
54
55
-static uint32_t allwinner_sun8i_emac_get_desc(AwSun8iEmacState *s,
56
- FrameDescriptor *desc,
57
- uint32_t start_addr,
58
- size_t min_size)
59
+static void allwinner_sun8i_emac_get_desc(AwSun8iEmacState *s,
60
+ FrameDescriptor *desc,
61
+ uint32_t phys_addr)
62
+{
63
+ dma_memory_read(&s->dma_as, phys_addr, desc, sizeof(*desc));
64
+}
65
+
66
+static uint32_t allwinner_sun8i_emac_next_desc(AwSun8iEmacState *s,
67
+ FrameDescriptor *desc)
68
+{
69
+ const uint32_t nxt = desc->next;
70
+ allwinner_sun8i_emac_get_desc(s, desc, nxt);
71
+ return nxt;
72
+}
73
+
74
+static uint32_t allwinner_sun8i_emac_find_desc(AwSun8iEmacState *s,
75
+ FrameDescriptor *desc,
76
+ uint32_t start_addr,
77
+ size_t min_size)
33
{
78
{
34
return !(surface->flags & QEMU_ALLOCATED_FLAG);
79
uint32_t desc_addr = start_addr;
35
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
80
36
index XXXXXXX..XXXXXXX 100644
81
/* Note that the list is a cycle. Last entry points back to the head. */
37
--- a/hw/display/tc6393xb.c
82
while (desc_addr != 0) {
38
+++ b/hw/display/tc6393xb.c
83
- dma_memory_read(&s->dma_as, desc_addr, desc, sizeof(*desc));
39
@@ -XXX,XX +XXX,XX @@ static void tc6393xb_nand_writeb(TC6393xbState *s, hwaddr addr, uint32_t value)
84
+ allwinner_sun8i_emac_get_desc(s, desc, desc_addr);
40
(uint32_t) addr, value & 0xff);
85
86
- if ((desc->status & DESC_STATUS_CTL) &&
87
- (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_size) {
88
+ if (allwinner_sun8i_emac_desc_owned(desc, min_size)) {
89
return desc_addr;
90
} else if (desc->next == start_addr) {
91
break;
92
@@ -XXX,XX +XXX,XX @@ static uint32_t allwinner_sun8i_emac_rx_desc(AwSun8iEmacState *s,
93
FrameDescriptor *desc,
94
size_t min_size)
95
{
96
- return allwinner_sun8i_emac_get_desc(s, desc, s->rx_desc_curr, min_size);
97
+ return allwinner_sun8i_emac_find_desc(s, desc, s->rx_desc_curr, min_size);
41
}
98
}
42
99
43
-#define BITS 8
100
static uint32_t allwinner_sun8i_emac_tx_desc(AwSun8iEmacState *s,
44
-#include "tc6393xb_template.h"
101
- FrameDescriptor *desc,
45
-#define BITS 15
102
- size_t min_size)
46
-#include "tc6393xb_template.h"
103
+ FrameDescriptor *desc)
47
-#define BITS 16
48
-#include "tc6393xb_template.h"
49
-#define BITS 24
50
-#include "tc6393xb_template.h"
51
#define BITS 32
52
#include "tc6393xb_template.h"
53
54
static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update)
55
{
104
{
56
- DisplaySurface *surface = qemu_console_surface(s->con);
105
- return allwinner_sun8i_emac_get_desc(s, desc, s->tx_desc_head, min_size);
57
-
106
+ allwinner_sun8i_emac_get_desc(s, desc, s->tx_desc_curr);
58
- switch (surface_bits_per_pixel(surface)) {
107
+ return s->tx_desc_curr;
59
- case 8:
60
- tc6393xb_draw_graphic8(s);
61
- break;
62
- case 15:
63
- tc6393xb_draw_graphic15(s);
64
- break;
65
- case 16:
66
- tc6393xb_draw_graphic16(s);
67
- break;
68
- case 24:
69
- tc6393xb_draw_graphic24(s);
70
- break;
71
- case 32:
72
- tc6393xb_draw_graphic32(s);
73
- break;
74
- default:
75
- printf("tc6393xb: unknown depth %d\n",
76
- surface_bits_per_pixel(surface));
77
- return;
78
- }
79
-
80
+ tc6393xb_draw_graphic32(s);
81
dpy_gfx_update_full(s->con);
82
}
108
}
83
109
110
static void allwinner_sun8i_emac_flush_desc(AwSun8iEmacState *s,
111
@@ -XXX,XX +XXX,XX @@ static ssize_t allwinner_sun8i_emac_receive(NetClientState *nc,
112
bytes_left -= desc_bytes;
113
114
/* Move to the next descriptor */
115
- s->rx_desc_curr = allwinner_sun8i_emac_next_desc(s, &desc, 64);
116
+ s->rx_desc_curr = allwinner_sun8i_emac_find_desc(s, &desc, desc.next,
117
+ AW_SUN8I_EMAC_MIN_PKT_SZ);
118
if (!s->rx_desc_curr) {
119
/* Not enough buffer space available */
120
s->int_sta |= INT_STA_RX_BUF_UA;
121
@@ -XXX,XX +XXX,XX @@ static void allwinner_sun8i_emac_transmit(AwSun8iEmacState *s)
122
size_t transmitted = 0;
123
static uint8_t packet_buf[2048];
124
125
- s->tx_desc_curr = allwinner_sun8i_emac_tx_desc(s, &desc, 0);
126
+ s->tx_desc_curr = allwinner_sun8i_emac_tx_desc(s, &desc);
127
128
/* Read all transmit descriptors */
129
- while (s->tx_desc_curr != 0) {
130
+ while (allwinner_sun8i_emac_desc_owned(&desc, 0)) {
131
132
/* Read from physical memory into packet buffer */
133
bytes = desc.status2 & DESC_STATUS2_BUF_SIZE_MASK;
134
@@ -XXX,XX +XXX,XX @@ static void allwinner_sun8i_emac_transmit(AwSun8iEmacState *s)
135
packet_bytes = 0;
136
transmitted++;
137
}
138
- s->tx_desc_curr = allwinner_sun8i_emac_next_desc(s, &desc, 0);
139
+ s->tx_desc_curr = allwinner_sun8i_emac_next_desc(s, &desc);
140
}
141
142
/* Raise transmit completed interrupt */
84
--
143
--
85
2.20.1
144
2.20.1
86
145
87
146
diff view generated by jsdifflib
1
From: Rebecca Cran <rebecca@nuviainc.com>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Enable FEAT_SSBS for the "max" 32-bit CPU.
3
The image for Armbian 19.11.3 bionic has been removed from the armbian server.
4
Without the image as input the test arm_orangepi_bionic_19_11 cannot run.
4
5
5
Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
6
This commit removes the test completely and merges the code of the generic function
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
do_test_arm_orangepi_uboot_armbian back with the 20.08 test.
7
Message-id: 20210216224543.16142-4-rebecca@nuviainc.com
8
8
[PMM: fix typo causing compilation failure]
9
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
10
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
11
Message-id: 20210310195820.21950-3-nieklinnenbank@gmail.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
13
---
11
target/arm/cpu.c | 4 ++++
14
tests/acceptance/boot_linux_console.py | 72 ++++++++------------------
12
1 file changed, 4 insertions(+)
15
1 file changed, 23 insertions(+), 49 deletions(-)
13
16
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
17
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.c
19
--- a/tests/acceptance/boot_linux_console.py
17
+++ b/target/arm/cpu.c
20
+++ b/tests/acceptance/boot_linux_console.py
18
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
21
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_sd(self):
19
t = cpu->isar.id_pfr0;
22
# Wait for VM to shut down gracefully
20
t = FIELD_DP32(t, ID_PFR0, DIT, 1);
23
self.vm.wait()
21
cpu->isar.id_pfr0 = t;
24
25
- def do_test_arm_orangepi_uboot_armbian(self, image_path):
26
+ @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
27
+ 'Test artifacts fetched from unreliable apt.armbian.com')
28
+ @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
29
+ def test_arm_orangepi_bionic_20_08(self):
30
+ """
31
+ :avocado: tags=arch:arm
32
+ :avocado: tags=machine:orangepi-pc
33
+ :avocado: tags=device:sd
34
+ """
22
+
35
+
23
+ t = cpu->isar.id_pfr2;
36
+ # This test download a 275 MiB compressed image and expand it
24
+ t = FIELD_DP32(t, ID_PFR2, SSBS, 1);
37
+ # to 1036 MiB, but the underlying filesystem is 1552 MiB...
25
+ cpu->isar.id_pfr2 = t;
38
+ # As we expand it to 2 GiB we are safe.
26
}
39
+
27
#endif
40
+ image_url = ('https://dl.armbian.com/orangepipc/archive/'
28
}
41
+ 'Armbian_20.08.1_Orangepipc_bionic_current_5.8.5.img.xz')
42
+ image_hash = ('b4d6775f5673486329e45a0586bf06b6'
43
+ 'dbe792199fd182ac6b9c7bb6c7d3e6dd')
44
+ image_path_xz = self.fetch_asset(image_url, asset_hash=image_hash,
45
+ algorithm='sha256')
46
+ image_path = archive.extract(image_path_xz, self.workdir)
47
+ image_pow2ceil_expand(image_path)
48
+
49
self.vm.set_console()
50
self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw',
51
'-nic', 'user',
52
@@ -XXX,XX +XXX,XX @@ def do_test_arm_orangepi_uboot_armbian(self, image_path):
53
'to <orangepipc>')
54
self.wait_for_console_pattern('Starting Load Kernel Modules...')
55
56
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
57
- 'Test artifacts fetched from unreliable apt.armbian.com')
58
- @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
59
- @skipUnless(P7ZIP_AVAILABLE, '7z not installed')
60
- def test_arm_orangepi_bionic_19_11(self):
61
- """
62
- :avocado: tags=arch:arm
63
- :avocado: tags=machine:orangepi-pc
64
- :avocado: tags=device:sd
65
- """
66
-
67
- # This test download a 196MB compressed image and expand it to 1GB
68
- image_url = ('https://dl.armbian.com/orangepipc/archive/'
69
- 'Armbian_19.11.3_Orangepipc_bionic_current_5.3.9.7z')
70
- image_hash = '196a8ffb72b0123d92cea4a070894813d305c71e'
71
- image_path_7z = self.fetch_asset(image_url, asset_hash=image_hash)
72
- image_name = 'Armbian_19.11.3_Orangepipc_bionic_current_5.3.9.img'
73
- image_path = os.path.join(self.workdir, image_name)
74
- process.run("7z e -o%s %s" % (self.workdir, image_path_7z))
75
- image_pow2ceil_expand(image_path)
76
-
77
- self.do_test_arm_orangepi_uboot_armbian(image_path)
78
-
79
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
80
- 'Test artifacts fetched from unreliable apt.armbian.com')
81
- @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
82
- def test_arm_orangepi_bionic_20_08(self):
83
- """
84
- :avocado: tags=arch:arm
85
- :avocado: tags=machine:orangepi-pc
86
- :avocado: tags=device:sd
87
- """
88
-
89
- # This test download a 275 MiB compressed image and expand it
90
- # to 1036 MiB, but the underlying filesystem is 1552 MiB...
91
- # As we expand it to 2 GiB we are safe.
92
-
93
- image_url = ('https://dl.armbian.com/orangepipc/archive/'
94
- 'Armbian_20.08.1_Orangepipc_bionic_current_5.8.5.img.xz')
95
- image_hash = ('b4d6775f5673486329e45a0586bf06b6'
96
- 'dbe792199fd182ac6b9c7bb6c7d3e6dd')
97
- image_path_xz = self.fetch_asset(image_url, asset_hash=image_hash,
98
- algorithm='sha256')
99
- image_path = archive.extract(image_path_xz, self.workdir)
100
- image_pow2ceil_expand(image_path)
101
-
102
- self.do_test_arm_orangepi_uboot_armbian(image_path)
103
-
104
@skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
105
def test_arm_orangepi_uboot_netbsd9(self):
106
"""
29
--
107
--
30
2.20.1
108
2.20.1
31
109
32
110
diff view generated by jsdifflib
1
From: Rebecca Cran <rebecca@nuviainc.com>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Set ID_AA64PFR1_EL1.SSBS to 2 and ID_PFR2.SSBS to 1.
3
Update the download URL of the Armbian 20.08 Bionic image for
4
test_arm_orangepi_bionic_20_08 of the orangepi-pc machine.
4
5
5
Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
6
The archive.armbian.com URL contains more images and should keep stable
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
for a longer period of time than dl.armbian.com.
7
Message-id: 20210216224543.16142-3-rebecca@nuviainc.com
8
9
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
13
Message-id: 20210310195820.21950-4-nieklinnenbank@gmail.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
15
---
10
target/arm/cpu64.c | 5 +++++
16
tests/acceptance/boot_linux_console.py | 2 +-
11
1 file changed, 5 insertions(+)
17
1 file changed, 1 insertion(+), 1 deletion(-)
12
18
13
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
19
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
14
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu64.c
21
--- a/tests/acceptance/boot_linux_console.py
16
+++ b/target/arm/cpu64.c
22
+++ b/tests/acceptance/boot_linux_console.py
17
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
23
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_bionic_20_08(self):
18
24
# to 1036 MiB, but the underlying filesystem is 1552 MiB...
19
t = cpu->isar.id_aa64pfr1;
25
# As we expand it to 2 GiB we are safe.
20
t = FIELD_DP64(t, ID_AA64PFR1, BT, 1);
26
21
+ t = FIELD_DP64(t, ID_AA64PFR1, SSBS, 2);
27
- image_url = ('https://dl.armbian.com/orangepipc/archive/'
22
/*
28
+ image_url = ('https://archive.armbian.com/orangepipc/archive/'
23
* Begin with full support for MTE. This will be downgraded to MTE=0
29
'Armbian_20.08.1_Orangepipc_bionic_current_5.8.5.img.xz')
24
* during realize if the board provides no tag memory, much like
30
image_hash = ('b4d6775f5673486329e45a0586bf06b6'
25
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
31
'dbe792199fd182ac6b9c7bb6c7d3e6dd')
26
u = FIELD_DP32(u, ID_PFR0, DIT, 1);
27
cpu->isar.id_pfr0 = u;
28
29
+ u = cpu->isar.id_pfr2;
30
+ u = FIELD_DP32(u, ID_PFR2, SSBS, 1);
31
+ cpu->isar.id_pfr2 = u;
32
+
33
u = cpu->isar.id_mmfr3;
34
u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */
35
cpu->isar.id_mmfr3 = u;
36
--
32
--
37
2.20.1
33
2.20.1
38
34
39
35
diff view generated by jsdifflib
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Let add 'max' cpu while work goes on adding newer CPU types than
3
The linux kernel 4.20.7 binary for sunxi has been removed from apt.armbian.com:
4
Cortex-A72. This allows us to check SVE etc support.
5
4
6
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
5
$ ARMBIAN_ARTIFACTS_CACHED=yes AVOCADO_ALLOW_LARGE_STORAGE=yes avocado --show=app,console run -t machine:orangepi-pc tests/acceptance/boot_linux_console.py
7
Acked-by: Leif Lindholm <leif@nuviainc.com>
6
Fetching asset from tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_arm_orangepi
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
...
9
Message-id: 20210216150122.3830863-3-marcin.juszkiewicz@linaro.org
8
(1/6) tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_arm_orangepi:
9
CANCEL: Missing asset https://apt.armbian.com/pool/main/l/linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb (0.55 s)
10
11
This commit updates the sunxi kernel to 5.10.16 for the acceptance
12
tests of the orangepi-pc and cubieboard machines.
13
14
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
15
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
16
Message-id: 20210310195820.21950-5-nieklinnenbank@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
18
---
12
hw/arm/sbsa-ref.c | 1 +
19
tests/acceptance/boot_linux_console.py | 40 +++++++++++++-------------
13
1 file changed, 1 insertion(+)
20
tests/acceptance/replay_kernel.py | 8 +++---
21
2 files changed, 24 insertions(+), 24 deletions(-)
14
22
15
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
23
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
16
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/sbsa-ref.c
25
--- a/tests/acceptance/boot_linux_console.py
18
+++ b/hw/arm/sbsa-ref.c
26
+++ b/tests/acceptance/boot_linux_console.py
19
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
27
@@ -XXX,XX +XXX,XX @@ def test_arm_cubieboard_initrd(self):
20
static const char * const valid_cpus[] = {
28
:avocado: tags=machine:cubieboard
21
ARM_CPU_TYPE_NAME("cortex-a57"),
29
"""
22
ARM_CPU_TYPE_NAME("cortex-a72"),
30
deb_url = ('https://apt.armbian.com/pool/main/l/'
23
+ ARM_CPU_TYPE_NAME("max"),
31
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
24
};
32
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
25
33
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
26
static bool cpu_type_valid(const char *cpu)
34
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
35
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
36
kernel_path = self.extract_from_deb(deb_path,
37
- '/boot/vmlinuz-4.20.7-sunxi')
38
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun4i-a10-cubieboard.dtb'
39
+ '/boot/vmlinuz-5.10.16-sunxi')
40
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
41
dtb_path = self.extract_from_deb(deb_path, dtb_path)
42
initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
43
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
44
@@ -XXX,XX +XXX,XX @@ def test_arm_cubieboard_sata(self):
45
:avocado: tags=machine:cubieboard
46
"""
47
deb_url = ('https://apt.armbian.com/pool/main/l/'
48
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
49
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
50
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
51
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
52
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
53
kernel_path = self.extract_from_deb(deb_path,
54
- '/boot/vmlinuz-4.20.7-sunxi')
55
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun4i-a10-cubieboard.dtb'
56
+ '/boot/vmlinuz-5.10.16-sunxi')
57
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
58
dtb_path = self.extract_from_deb(deb_path, dtb_path)
59
rootfs_url = ('https://github.com/groeck/linux-build-test/raw/'
60
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
61
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi(self):
62
:avocado: tags=machine:orangepi-pc
63
"""
64
deb_url = ('https://apt.armbian.com/pool/main/l/'
65
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
66
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
67
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
68
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
69
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
70
kernel_path = self.extract_from_deb(deb_path,
71
- '/boot/vmlinuz-4.20.7-sunxi')
72
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb'
73
+ '/boot/vmlinuz-5.10.16-sunxi')
74
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb'
75
dtb_path = self.extract_from_deb(deb_path, dtb_path)
76
77
self.vm.set_console()
78
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_initrd(self):
79
:avocado: tags=machine:orangepi-pc
80
"""
81
deb_url = ('https://apt.armbian.com/pool/main/l/'
82
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
83
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
84
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
85
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
86
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
87
kernel_path = self.extract_from_deb(deb_path,
88
- '/boot/vmlinuz-4.20.7-sunxi')
89
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb'
90
+ '/boot/vmlinuz-5.10.16-sunxi')
91
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb'
92
dtb_path = self.extract_from_deb(deb_path, dtb_path)
93
initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
94
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
95
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_sd(self):
96
:avocado: tags=device:sd
97
"""
98
deb_url = ('https://apt.armbian.com/pool/main/l/'
99
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
100
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
101
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
102
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
103
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
104
kernel_path = self.extract_from_deb(deb_path,
105
- '/boot/vmlinuz-4.20.7-sunxi')
106
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb'
107
+ '/boot/vmlinuz-5.10.16-sunxi')
108
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb'
109
dtb_path = self.extract_from_deb(deb_path, dtb_path)
110
rootfs_url = ('http://storage.kernelci.org/images/rootfs/buildroot/'
111
'kci-2019.02/armel/base/rootfs.ext2.xz')
112
diff --git a/tests/acceptance/replay_kernel.py b/tests/acceptance/replay_kernel.py
113
index XXXXXXX..XXXXXXX 100644
114
--- a/tests/acceptance/replay_kernel.py
115
+++ b/tests/acceptance/replay_kernel.py
116
@@ -XXX,XX +XXX,XX @@ def test_arm_cubieboard_initrd(self):
117
:avocado: tags=machine:cubieboard
118
"""
119
deb_url = ('https://apt.armbian.com/pool/main/l/'
120
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
121
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
122
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
123
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
124
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
125
kernel_path = self.extract_from_deb(deb_path,
126
- '/boot/vmlinuz-4.20.7-sunxi')
127
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun4i-a10-cubieboard.dtb'
128
+ '/boot/vmlinuz-5.10.16-sunxi')
129
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
130
dtb_path = self.extract_from_deb(deb_path, dtb_path)
131
initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
132
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
27
--
133
--
28
2.20.1
134
2.20.1
29
135
30
136
diff view generated by jsdifflib
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Cortex-A53 supports 40bits of address space. sbsa-ref's memory starts
3
Previously the ARMBIAN_ARTIFACTS_CACHED pre-condition was added to allow running
4
above this limit.
4
tests that have already existing armbian.com artifacts stored in the local avocado cache,
5
but do not have working URLs to download a fresh copy.
5
6
6
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
7
At this time of writing the URLs for artifacts on the armbian.com server are updated and working.
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Any future broken URLs will result in a skipped acceptance test, for example:
8
Acked-by: Leif Lindholm <leif@nuviainc.com>
9
9
Message-id: 20210216150122.3830863-2-marcin.juszkiewicz@linaro.org
10
(1/5) tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_arm_orangepi:
11
CANCEL: Missing asset https://apt.armbian.com/pool/main/l/linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb (0.53 s)
12
13
This commits removes the ARMBIAN_ARTIFACTS_CACHED pre-condition such that
14
the acceptance tests for the orangepi-pc and cubieboard machines can run.
15
16
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
17
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
18
Message-id: 20210310195820.21950-6-nieklinnenbank@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
20
---
12
hw/arm/sbsa-ref.c | 1 -
21
tests/acceptance/boot_linux_console.py | 12 ------------
13
1 file changed, 1 deletion(-)
22
tests/acceptance/replay_kernel.py | 2 --
23
2 files changed, 14 deletions(-)
14
24
15
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
25
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
16
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/sbsa-ref.c
27
--- a/tests/acceptance/boot_linux_console.py
18
+++ b/hw/arm/sbsa-ref.c
28
+++ b/tests/acceptance/boot_linux_console.py
19
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
29
@@ -XXX,XX +XXX,XX @@ def test_arm_exynos4210_initrd(self):
20
};
30
self.wait_for_console_pattern('Boot successful.')
21
31
# TODO user command, for now the uart is stuck
22
static const char * const valid_cpus[] = {
32
23
- ARM_CPU_TYPE_NAME("cortex-a53"),
33
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
24
ARM_CPU_TYPE_NAME("cortex-a57"),
34
- 'Test artifacts fetched from unreliable apt.armbian.com')
25
ARM_CPU_TYPE_NAME("cortex-a72"),
35
def test_arm_cubieboard_initrd(self):
26
};
36
"""
37
:avocado: tags=arch:arm
38
@@ -XXX,XX +XXX,XX @@ def test_arm_cubieboard_initrd(self):
39
'system-control@1c00000')
40
# cubieboard's reboot is not functioning; omit reboot test.
41
42
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
43
- 'Test artifacts fetched from unreliable apt.armbian.com')
44
def test_arm_cubieboard_sata(self):
45
"""
46
:avocado: tags=arch:arm
47
@@ -XXX,XX +XXX,XX @@ def test_arm_quanta_gsj_initrd(self):
48
self.wait_for_console_pattern(
49
'Give root password for system maintenance')
50
51
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
52
- 'Test artifacts fetched from unreliable apt.armbian.com')
53
def test_arm_orangepi(self):
54
"""
55
:avocado: tags=arch:arm
56
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi(self):
57
console_pattern = 'Kernel command line: %s' % kernel_command_line
58
self.wait_for_console_pattern(console_pattern)
59
60
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
61
- 'Test artifacts fetched from unreliable apt.armbian.com')
62
def test_arm_orangepi_initrd(self):
63
"""
64
:avocado: tags=arch:arm
65
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_initrd(self):
66
# Wait for VM to shut down gracefully
67
self.vm.wait()
68
69
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
70
- 'Test artifacts fetched from unreliable apt.armbian.com')
71
def test_arm_orangepi_sd(self):
72
"""
73
:avocado: tags=arch:arm
74
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_sd(self):
75
# Wait for VM to shut down gracefully
76
self.vm.wait()
77
78
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
79
- 'Test artifacts fetched from unreliable apt.armbian.com')
80
@skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
81
def test_arm_orangepi_bionic_20_08(self):
82
"""
83
diff --git a/tests/acceptance/replay_kernel.py b/tests/acceptance/replay_kernel.py
84
index XXXXXXX..XXXXXXX 100644
85
--- a/tests/acceptance/replay_kernel.py
86
+++ b/tests/acceptance/replay_kernel.py
87
@@ -XXX,XX +XXX,XX @@ def test_arm_virt(self):
88
self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=1)
89
90
@skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab')
91
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
92
- 'Test artifacts fetched from unreliable apt.armbian.com')
93
def test_arm_cubieboard_initrd(self):
94
"""
95
:avocado: tags=arch:arm
27
--
96
--
28
2.20.1
97
2.20.1
29
98
30
99
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
We hint the 'has_rpu' property is no longer required since commit
3
If the SSECounter link is absent, we set an error message
4
6908ec448b4 ("xlnx-zynqmp: Properly support the smp command line
4
in sse_timer_realize() but forgot to propagate this error.
5
option") which was released in QEMU v2.11.0.
5
Add the missing 'return'.
6
6
7
Beside, this device is marked 'user_creatable = false', so the
7
Fixes: CID 1450755 (Null pointer dereferences)
8
only thing that could be setting the property is the board code
8
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
that creates the device.
9
Message-id: 20210312001845.1562670-1-f4bug@amsat.org
10
11
Since the property is not user-facing, we can remove it without
12
going through the deprecation process.
13
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Message-id: 20210219144350.1979905-1-f4bug@amsat.org
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
12
---
19
include/hw/arm/xlnx-zynqmp.h | 2 --
13
hw/timer/sse-timer.c | 1 +
20
hw/arm/xlnx-zynqmp.c | 6 ------
14
1 file changed, 1 insertion(+)
21
2 files changed, 8 deletions(-)
22
15
23
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
16
diff --git a/hw/timer/sse-timer.c b/hw/timer/sse-timer.c
24
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/xlnx-zynqmp.h
18
--- a/hw/timer/sse-timer.c
26
+++ b/include/hw/arm/xlnx-zynqmp.h
19
+++ b/hw/timer/sse-timer.c
27
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
20
@@ -XXX,XX +XXX,XX @@ static void sse_timer_realize(DeviceState *dev, Error **errp)
28
bool secure;
21
29
/* Has the ARM Virtualization extensions? */
22
if (!s->counter) {
30
bool virt;
23
error_setg(errp, "counter property was not set");
31
- /* Has the RPU subsystem? */
24
+ return;
32
- bool has_rpu;
33
34
/* CAN bus. */
35
CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
36
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/arm/xlnx-zynqmp.c
39
+++ b/hw/arm/xlnx-zynqmp.c
40
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
41
}
42
}
25
}
43
26
44
- if (s->has_rpu) {
27
s->counter_notifier.notify = sse_timer_counter_callback;
45
- info_report("The 'has_rpu' property is no longer required, to use the "
46
- "RPUs just use -smp 6.");
47
- }
48
-
49
xlnx_zynqmp_create_rpu(ms, s, boot_cpu, &err);
50
if (err) {
51
error_propagate(errp, err);
52
@@ -XXX,XX +XXX,XX @@ static Property xlnx_zynqmp_props[] = {
53
DEFINE_PROP_STRING("boot-cpu", XlnxZynqMPState, boot_cpu),
54
DEFINE_PROP_BOOL("secure", XlnxZynqMPState, secure, false),
55
DEFINE_PROP_BOOL("virtualization", XlnxZynqMPState, virt, false),
56
- DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false),
57
DEFINE_PROP_LINK("ddr-ram", XlnxZynqMPState, ddr_ram, TYPE_MEMORY_REGION,
58
MemoryRegion *),
59
DEFINE_PROP_LINK("canbus0", XlnxZynqMPState, canbus[0], TYPE_CAN_BUS,
60
--
28
--
61
2.20.1
29
2.20.1
62
30
63
31
diff view generated by jsdifflib
1
The AN505 and AN521 don't have any read-only memory, but the AN524
1
From: Andrew Jones <drjones@redhat.com>
2
does; add a flag to ROMInfo to mark a region as ROM.
3
2
3
Prior to commit f2ce39b4f067 a MachineClass kvm_type method
4
only needed to be registered to ensure it would be executed.
5
With commit f2ce39b4f067 a kvm-type machine property must also
6
be specified. hw/arm/virt relies on the kvm_type method to pass
7
its selected IPA limit to KVM, but this is not exposed as a
8
machine property. Restore the previous functionality of invoking
9
kvm_type when it's present.
10
11
Fixes: f2ce39b4f067 ("vl: make qemu_get_machine_opts static")
12
Signed-off-by: Andrew Jones <drjones@redhat.com>
13
Reviewed-by: Eric Auger <eric.auger@redhat.com>
14
Message-id: 20210310135218.255205-2-drjones@redhat.com
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210215115138.20465-19-peter.maydell@linaro.org
7
---
16
---
8
hw/arm/mps2-tz.c | 6 ++++++
17
include/hw/boards.h | 1 +
9
1 file changed, 6 insertions(+)
18
accel/kvm/kvm-all.c | 2 ++
19
2 files changed, 3 insertions(+)
10
20
11
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
21
diff --git a/include/hw/boards.h b/include/hw/boards.h
12
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/mps2-tz.c
23
--- a/include/hw/boards.h
14
+++ b/hw/arm/mps2-tz.c
24
+++ b/include/hw/boards.h
15
@@ -XXX,XX +XXX,XX @@ typedef struct RAMInfo {
25
@@ -XXX,XX +XXX,XX @@ typedef struct {
16
* Flag values:
26
* @kvm_type:
17
* IS_ALIAS: this RAM area is an alias to the upstream end of the
27
* Return the type of KVM corresponding to the kvm-type string option or
18
* MPC specified by its .mpc value
28
* computed based on other criteria such as the host kernel capabilities.
19
+ * IS_ROM: this RAM area is read-only
29
+ * kvm-type may be NULL if it is not needed.
20
*/
30
* @numa_mem_supported:
21
#define IS_ALIAS 1
31
* true if '--numa node.mem' option is supported and false otherwise
22
+#define IS_ROM 2
32
* @smp_parse:
23
33
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
24
struct MPS2TZMachineClass {
34
index XXXXXXX..XXXXXXX 100644
25
MachineClass parent;
35
--- a/accel/kvm/kvm-all.c
26
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *mr_for_raminfo(MPS2TZMachineState *mms,
36
+++ b/accel/kvm/kvm-all.c
27
if (raminfo->mrindex < 0) {
37
@@ -XXX,XX +XXX,XX @@ static int kvm_init(MachineState *ms)
28
/* Means this RAMInfo is for QEMU's "system memory" */
38
"kvm-type",
29
MachineState *machine = MACHINE(mms);
39
&error_abort);
30
+ assert(!(raminfo->flags & IS_ROM));
40
type = mc->kvm_type(ms, kvm_type);
31
return machine->ram;
41
+ } else if (mc->kvm_type) {
42
+ type = mc->kvm_type(ms, NULL);
32
}
43
}
33
44
34
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *mr_for_raminfo(MPS2TZMachineState *mms,
45
do {
35
36
memory_region_init_ram(ram, NULL, raminfo->name,
37
raminfo->size, &error_fatal);
38
+ if (raminfo->flags & IS_ROM) {
39
+ memory_region_set_readonly(ram, true);
40
+ }
41
return ram;
42
}
43
44
--
46
--
45
2.20.1
47
2.20.1
46
48
47
49
diff view generated by jsdifflib
1
Instead of hardcoding the MachineClass default_ram_size and
1
From: Andrew Jones <drjones@redhat.com>
2
default_ram_id fields, set them on class creation by finding the
3
entry in the RAMInfo array which is marked as being the QEMU system
4
RAM.
5
2
3
The virt machine already checks KVM_CAP_ARM_VM_IPA_SIZE to get the
4
upper bound of the IPA size. If that bound is lower than the highest
5
possible GPA for the machine, then QEMU will error out. However, the
6
IPA is set to 40 when the highest GPA is less than or equal to 40,
7
even when KVM may support an IPA limit as low as 32. This means KVM
8
may fail the VM creation unnecessarily. Additionally, 40 is selected
9
with the value 0, which means use the default, and that gets around
10
a check in some versions of KVM, causing a difficult to debug fail.
11
Always use the IPA size that corresponds to the highest possible GPA,
12
unless it's lower than 32, in which case use 32. Also, we must still
13
use 0 when KVM only supports the legacy fixed 40 bit IPA.
14
15
Suggested-by: Marc Zyngier <maz@kernel.org>
16
Signed-off-by: Andrew Jones <drjones@redhat.com>
17
Reviewed-by: Eric Auger <eric.auger@redhat.com>
18
Reviewed-by: Marc Zyngier <maz@kernel.org>
19
Message-id: 20210310135218.255205-3-drjones@redhat.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215115138.20465-18-peter.maydell@linaro.org
9
---
21
---
10
hw/arm/mps2-tz.c | 24 ++++++++++++++++++++++--
22
target/arm/kvm_arm.h | 6 ++++--
11
1 file changed, 22 insertions(+), 2 deletions(-)
23
hw/arm/virt.c | 23 ++++++++++++++++-------
24
target/arm/kvm.c | 4 +++-
25
3 files changed, 23 insertions(+), 10 deletions(-)
12
26
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
27
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
14
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/mps2-tz.c
29
--- a/target/arm/kvm_arm.h
16
+++ b/hw/arm/mps2-tz.c
30
+++ b/target/arm/kvm_arm.h
17
@@ -XXX,XX +XXX,XX @@ static void mps2tz_class_init(ObjectClass *oc, void *data)
31
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_sve_supported(void);
18
32
/**
19
mc->init = mps2tz_common_init;
33
* kvm_arm_get_max_vm_ipa_size:
20
iic->check = mps2_tz_idau_check;
34
* @ms: Machine state handle
21
- mc->default_ram_size = 16 * MiB;
35
+ * @fixed_ipa: True when the IPA limit is fixed at 40. This is the case
22
- mc->default_ram_id = "mps.ram";
36
+ * for legacy KVM.
23
+}
37
*
38
* Returns the number of bits in the IPA address space supported by KVM
39
*/
40
-int kvm_arm_get_max_vm_ipa_size(MachineState *ms);
41
+int kvm_arm_get_max_vm_ipa_size(MachineState *ms, bool *fixed_ipa);
42
43
/**
44
* kvm_arm_sync_mpstate_to_kvm:
45
@@ -XXX,XX +XXX,XX @@ static inline void kvm_arm_add_vcpu_properties(Object *obj)
46
g_assert_not_reached();
47
}
48
49
-static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
50
+static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms, bool *fixed_ipa)
51
{
52
g_assert_not_reached();
53
}
54
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/hw/arm/virt.c
57
+++ b/hw/arm/virt.c
58
@@ -XXX,XX +XXX,XX @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
59
static int virt_kvm_type(MachineState *ms, const char *type_str)
60
{
61
VirtMachineState *vms = VIRT_MACHINE(ms);
62
- int max_vm_pa_size = kvm_arm_get_max_vm_ipa_size(ms);
63
- int requested_pa_size;
64
+ int max_vm_pa_size, requested_pa_size;
65
+ bool fixed_ipa;
24
+
66
+
25
+static void mps2tz_set_default_ram_info(MPS2TZMachineClass *mmc)
67
+ max_vm_pa_size = kvm_arm_get_max_vm_ipa_size(ms, &fixed_ipa);
26
+{
68
69
/* we freeze the memory map to compute the highest gpa */
70
virt_set_memmap(vms);
71
72
requested_pa_size = 64 - clz64(vms->highest_gpa);
73
27
+ /*
74
+ /*
28
+ * Set mc->default_ram_size and default_ram_id from the
75
+ * KVM requires the IPA size to be at least 32 bits.
29
+ * information in mmc->raminfo.
30
+ */
76
+ */
31
+ MachineClass *mc = MACHINE_CLASS(mmc);
77
+ if (requested_pa_size < 32) {
32
+ const RAMInfo *p;
78
+ requested_pa_size = 32;
79
+ }
33
+
80
+
34
+ for (p = mmc->raminfo; p->name; p++) {
81
if (requested_pa_size > max_vm_pa_size) {
35
+ if (p->mrindex < 0) {
82
error_report("-m and ,maxmem option values "
36
+ /* Found the entry for "system memory" */
83
"require an IPA range (%d bits) larger than "
37
+ mc->default_ram_size = p->size;
84
"the one supported by the host (%d bits)",
38
+ mc->default_ram_id = p->name;
85
requested_pa_size, max_vm_pa_size);
39
+ return;
86
- exit(1);
40
+ }
87
+ exit(1);
41
+ }
88
}
42
+ g_assert_not_reached();
89
/*
90
- * By default we return 0 which corresponds to an implicit legacy
91
- * 40b IPA setting. Otherwise we return the actual requested PA
92
- * logsize
93
+ * We return the requested PA log size, unless KVM only supports
94
+ * the implicit legacy 40b IPA setting, in which case the kvm_type
95
+ * must be 0.
96
*/
97
- return requested_pa_size > 40 ? requested_pa_size : 0;
98
+ return fixed_ipa ? 0 : requested_pa_size;
43
}
99
}
44
100
45
static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
101
static void virt_machine_class_init(ObjectClass *oc, void *data)
46
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
102
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
47
mmc->numirq = 92;
103
index XXXXXXX..XXXXXXX 100644
48
mmc->raminfo = an505_raminfo;
104
--- a/target/arm/kvm.c
49
mmc->armsse_type = TYPE_IOTKIT;
105
+++ b/target/arm/kvm.c
50
+ mps2tz_set_default_ram_info(mmc);
106
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_pmu_supported(void)
107
return kvm_check_extension(kvm_state, KVM_CAP_ARM_PMU_V3);
51
}
108
}
52
109
53
static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
110
-int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
54
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
111
+int kvm_arm_get_max_vm_ipa_size(MachineState *ms, bool *fixed_ipa)
55
mmc->numirq = 92;
112
{
56
mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
113
KVMState *s = KVM_STATE(ms->accelerator);
57
mmc->armsse_type = TYPE_SSE200;
114
int ret;
58
+ mps2tz_set_default_ram_info(mmc);
115
116
ret = kvm_check_extension(s, KVM_CAP_ARM_VM_IPA_SIZE);
117
+ *fixed_ipa = ret <= 0;
118
+
119
return ret > 0 ? ret : 40;
59
}
120
}
60
121
61
static const TypeInfo mps2tz_info = {
62
--
122
--
63
2.20.1
123
2.20.1
64
124
65
125
diff view generated by jsdifflib
1
The armv7m_load_kernel() function takes a mem_size argument which it
1
From: Hao Wu <wuhaotsh@google.com>
2
expects to be the size of the memory region at guest address 0. (It
3
uses this argument only as a limit on how large a raw image file it
4
can load at address zero).
5
2
6
Instead of hardcoding this value, find the RAMInfo corresponding to
3
This patch adds GPIOs in NPCM7xx PWM module for its duty values.
7
the 0 address and extract its size.
4
The purpose of this is to connect it to the MFT module to provide
5
an input for measuring a PWM fan's RPM. Each PWM module has
6
NPCM7XX_PWM_PER_MODULE of GPIOs, each one corresponds to
7
one PWM instance and can connect to multiple fan instances in MFT.
8
8
9
Reviewed-by: Doug Evans <dje@google.com>
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
11
Signed-off-by: Hao Wu <wuhaotsh@google.com>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Message-id: 20210311180855.149764-2-wuhaotsh@google.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210215115138.20465-20-peter.maydell@linaro.org
13
---
15
---
14
hw/arm/mps2-tz.c | 17 ++++++++++++++++-
16
include/hw/misc/npcm7xx_pwm.h | 4 +++-
15
1 file changed, 16 insertions(+), 1 deletion(-)
17
hw/misc/npcm7xx_pwm.c | 4 ++++
18
2 files changed, 7 insertions(+), 1 deletion(-)
16
19
17
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
20
diff --git a/include/hw/misc/npcm7xx_pwm.h b/include/hw/misc/npcm7xx_pwm.h
18
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/mps2-tz.c
22
--- a/include/hw/misc/npcm7xx_pwm.h
20
+++ b/hw/arm/mps2-tz.c
23
+++ b/include/hw/misc/npcm7xx_pwm.h
21
@@ -XXX,XX +XXX,XX @@ static void create_non_mpc_ram(MPS2TZMachineState *mms)
24
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxPWM {
25
* @iomem: Memory region through which registers are accessed.
26
* @clock: The PWM clock.
27
* @pwm: The PWM channels owned by this module.
28
+ * @duty_gpio_out: The duty cycle of each PWM channels as a output GPIO.
29
* @ppr: The prescaler register.
30
* @csr: The clock selector register.
31
* @pcr: The control register.
32
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxPWMState {
33
MemoryRegion iomem;
34
35
Clock *clock;
36
- NPCM7xxPWM pwm[NPCM7XX_PWM_PER_MODULE];
37
+ NPCM7xxPWM pwm[NPCM7XX_PWM_PER_MODULE];
38
+ qemu_irq duty_gpio_out[NPCM7XX_PWM_PER_MODULE];
39
40
uint32_t ppr;
41
uint32_t csr;
42
diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/misc/npcm7xx_pwm.c
45
+++ b/hw/misc/npcm7xx_pwm.c
46
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_pwm_update_duty(NPCM7xxPWM *p)
47
trace_npcm7xx_pwm_update_duty(DEVICE(p->module)->canonical_path,
48
p->index, p->duty, duty);
49
p->duty = duty;
50
+ qemu_set_irq(p->module->duty_gpio_out[p->index], p->duty);
22
}
51
}
23
}
52
}
24
53
25
+static uint32_t boot_ram_size(MPS2TZMachineState *mms)
54
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_pwm_init(Object *obj)
26
+{
55
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
27
+ /* Return the size of the RAM block at guest address zero */
56
int i;
28
+ const RAMInfo *p;
57
29
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
58
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(s->pwm) != NPCM7XX_PWM_PER_MODULE);
30
+
59
for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
31
+ for (p = mmc->raminfo; p->name; p++) {
60
NPCM7xxPWM *p = &s->pwm[i];
32
+ if (p->base == 0) {
61
p->module = s;
33
+ return p->size;
62
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_pwm_init(Object *obj)
34
+ }
63
object_property_add_uint32_ptr(obj, "duty[*]",
35
+ }
64
&s->pwm[i].duty, OBJ_PROP_FLAG_READ);
36
+ g_assert_not_reached();
65
}
37
+}
66
+ qdev_init_gpio_out_named(DEVICE(s), s->duty_gpio_out,
38
+
67
+ "duty-gpio-out", NPCM7XX_PWM_PER_MODULE);
39
static void mps2tz_common_init(MachineState *machine)
40
{
41
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
42
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
43
44
create_non_mpc_ram(mms);
45
46
- armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
47
+ armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
48
+ boot_ram_size(mms));
49
}
68
}
50
69
51
static void mps2_tz_idau_check(IDAUInterface *ii, uint32_t address,
70
static const VMStateDescription vmstate_npcm7xx_pwm = {
52
--
71
--
53
2.20.1
72
2.20.1
54
73
55
74
diff view generated by jsdifflib
1
From: Doug Evans <dje@google.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
This is a 10/100 ethernet device that has several features.
3
This patch implements Multi Function Timer (MFT) module for NPCM7XX.
4
Only the ones needed by the Linux driver have been implemented.
4
This module is mainly used to configure PWM fans. It has just enough
5
See npcm7xx_emc.c for a list of unimplemented features.
5
functionality to make the PWM fan kernel module work.
6
6
7
Reviewed-by: Hao Wu <wuhaotsh@google.com>
7
The module takes two input, the max_rpm of a fan (modifiable via QMP)
8
Reviewed-by: Avi Fishman <avi.fishman@nuvoton.com>
8
and duty cycle (a GPIO from the PWM module.) The actual measured RPM
9
Signed-off-by: Doug Evans <dje@google.com>
9
is equal to max_rpm * duty_cycle / NPCM7XX_PWM_MAX_DUTY. The RPM is
10
Message-id: 20210218212453.831406-2-dje@google.com
10
measured as a counter compared to a prescaled input clock. The kernel
11
driver reads this counter and report to user space.
12
13
Refs:
14
https://github.com/torvalds/linux/blob/master/drivers/hwmon/npcm750-pwm-fan.c
15
16
Reviewed-by: Doug Evans <dje@google.com>
17
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
18
Signed-off-by: Hao Wu <wuhaotsh@google.com>
19
Message-id: 20210311180855.149764-3-wuhaotsh@google.com
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
22
---
13
include/hw/net/npcm7xx_emc.h | 286 ++++++++++++
23
include/hw/misc/npcm7xx_mft.h | 70 +++++
14
hw/net/npcm7xx_emc.c | 857 +++++++++++++++++++++++++++++++++++
24
hw/misc/npcm7xx_mft.c | 540 ++++++++++++++++++++++++++++++++++
15
hw/net/meson.build | 1 +
25
hw/misc/meson.build | 1 +
16
hw/net/trace-events | 17 +
26
hw/misc/trace-events | 8 +
17
4 files changed, 1161 insertions(+)
27
4 files changed, 619 insertions(+)
18
create mode 100644 include/hw/net/npcm7xx_emc.h
28
create mode 100644 include/hw/misc/npcm7xx_mft.h
19
create mode 100644 hw/net/npcm7xx_emc.c
29
create mode 100644 hw/misc/npcm7xx_mft.c
20
30
21
diff --git a/include/hw/net/npcm7xx_emc.h b/include/hw/net/npcm7xx_emc.h
31
diff --git a/include/hw/misc/npcm7xx_mft.h b/include/hw/misc/npcm7xx_mft.h
22
new file mode 100644
32
new file mode 100644
23
index XXXXXXX..XXXXXXX
33
index XXXXXXX..XXXXXXX
24
--- /dev/null
34
--- /dev/null
25
+++ b/include/hw/net/npcm7xx_emc.h
35
+++ b/include/hw/misc/npcm7xx_mft.h
26
@@ -XXX,XX +XXX,XX @@
36
@@ -XXX,XX +XXX,XX @@
27
+/*
37
+/*
28
+ * Nuvoton NPCM7xx EMC Module
38
+ * Nuvoton NPCM7xx MFT Module
29
+ *
39
+ *
30
+ * Copyright 2020 Google LLC
40
+ * Copyright 2021 Google LLC
31
+ *
41
+ *
32
+ * This program is free software; you can redistribute it and/or modify it
42
+ * This program is free software; you can redistribute it and/or modify it
33
+ * under the terms of the GNU General Public License as published by the
43
+ * under the terms of the GNU General Public License as published by the
34
+ * Free Software Foundation; either version 2 of the License, or
44
+ * Free Software Foundation; either version 2 of the License, or
35
+ * (at your option) any later version.
45
+ * (at your option) any later version.
36
+ *
46
+ *
37
+ * This program is distributed in the hope that it will be useful, but WITHOUT
47
+ * This program is distributed in the hope that it will be useful, but WITHOUT
38
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
48
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
39
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
49
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
40
+ * for more details.
50
+ * for more details.
41
+ */
51
+ */
42
+
52
+#ifndef NPCM7XX_MFT_H
43
+#ifndef NPCM7XX_EMC_H
53
+#define NPCM7XX_MFT_H
44
+#define NPCM7XX_EMC_H
54
+
45
+
55
+#include "exec/memory.h"
56
+#include "hw/clock.h"
46
+#include "hw/irq.h"
57
+#include "hw/irq.h"
47
+#include "hw/sysbus.h"
58
+#include "hw/sysbus.h"
48
+#include "net/net.h"
59
+#include "qom/object.h"
49
+
60
+
50
+/* 32-bit register indices. */
61
+/* Max Fan input number. */
51
+enum NPCM7xxPWMRegister {
62
+#define NPCM7XX_MFT_MAX_FAN_INPUT 19
52
+ /* Control registers. */
63
+
53
+ REG_CAMCMR,
64
+/*
54
+ REG_CAMEN,
65
+ * Number of registers in one MFT module. Don't change this without increasing
55
+
66
+ * the version_id in vmstate.
56
+ /* There are 16 CAMn[ML] registers. */
67
+ */
57
+ REG_CAMM_BASE,
68
+#define NPCM7XX_MFT_NR_REGS (0x20 / sizeof(uint16_t))
58
+ REG_CAML_BASE,
69
+
59
+ REG_CAMML_LAST = 0x21,
70
+/*
60
+
71
+ * The MFT can take up to 4 inputs: A0, B0, A1, B1. It can measure one A and one
61
+ REG_TXDLSA = 0x22,
72
+ * B simultaneously. NPCM7XX_MFT_INASEL and NPCM7XX_MFT_INBSEL are used to
62
+ REG_RXDLSA,
73
+ * select which A or B input are used.
63
+ REG_MCMDR,
74
+ */
64
+ REG_MIID,
75
+#define NPCM7XX_MFT_FANIN_COUNT 4
65
+ REG_MIIDA,
76
+
66
+ REG_FFTCR,
77
+/**
67
+ REG_TSDR,
78
+ * struct NPCM7xxMFTState - Multi Functional Tachometer device state.
68
+ REG_RSDR,
79
+ * @parent: System bus device.
69
+ REG_DMARFC,
80
+ * @iomem: Memory region through which registers are accessed.
70
+ REG_MIEN,
81
+ * @clock_in: The input clock for MFT from CLK module.
71
+
82
+ * @clock_{1,2}: The counter clocks for NPCM7XX_MFT_CNT{1,2}
72
+ /* Status registers. */
83
+ * @irq: The IRQ for this MFT state.
73
+ REG_MISTA,
84
+ * @regs: The MMIO registers.
74
+ REG_MGSTA,
85
+ * @max_rpm: The maximum rpm for fans. Order: A0, B0, A1, B1.
75
+ REG_MPCNT,
86
+ * @duty: The duty cycles for fans, relative to NPCM7XX_PWM_MAX_DUTY.
76
+ REG_MRPC,
87
+ */
77
+ REG_MRPCC,
88
+typedef struct NPCM7xxMFTState {
78
+ REG_MREPC,
79
+ REG_DMARFS,
80
+ REG_CTXDSA,
81
+ REG_CTXBSA,
82
+ REG_CRXDSA,
83
+ REG_CRXBSA,
84
+
85
+ NPCM7XX_NUM_EMC_REGS,
86
+};
87
+
88
+/* REG_CAMCMR fields */
89
+/* Enable CAM Compare */
90
+#define REG_CAMCMR_ECMP (1 << 4)
91
+/* Complement CAM Compare */
92
+#define REG_CAMCMR_CCAM (1 << 3)
93
+/* Accept Broadcast Packet */
94
+#define REG_CAMCMR_ABP (1 << 2)
95
+/* Accept Multicast Packet */
96
+#define REG_CAMCMR_AMP (1 << 1)
97
+/* Accept Unicast Packet */
98
+#define REG_CAMCMR_AUP (1 << 0)
99
+
100
+/* REG_MCMDR fields */
101
+/* Software Reset */
102
+#define REG_MCMDR_SWR (1 << 24)
103
+/* Internal Loopback Select */
104
+#define REG_MCMDR_LBK (1 << 21)
105
+/* Operation Mode Select */
106
+#define REG_MCMDR_OPMOD (1 << 20)
107
+/* Enable MDC Clock Generation */
108
+#define REG_MCMDR_ENMDC (1 << 19)
109
+/* Full-Duplex Mode Select */
110
+#define REG_MCMDR_FDUP (1 << 18)
111
+/* Enable SQE Checking */
112
+#define REG_MCMDR_ENSEQ (1 << 17)
113
+/* Send PAUSE Frame */
114
+#define REG_MCMDR_SDPZ (1 << 16)
115
+/* No Defer */
116
+#define REG_MCMDR_NDEF (1 << 9)
117
+/* Frame Transmission On */
118
+#define REG_MCMDR_TXON (1 << 8)
119
+/* Strip CRC Checksum */
120
+#define REG_MCMDR_SPCRC (1 << 5)
121
+/* Accept CRC Error Packet */
122
+#define REG_MCMDR_AEP (1 << 4)
123
+/* Accept Control Packet */
124
+#define REG_MCMDR_ACP (1 << 3)
125
+/* Accept Runt Packet */
126
+#define REG_MCMDR_ARP (1 << 2)
127
+/* Accept Long Packet */
128
+#define REG_MCMDR_ALP (1 << 1)
129
+/* Frame Reception On */
130
+#define REG_MCMDR_RXON (1 << 0)
131
+
132
+/* REG_MIEN fields */
133
+/* Enable Transmit Descriptor Unavailable Interrupt */
134
+#define REG_MIEN_ENTDU (1 << 23)
135
+/* Enable Transmit Completion Interrupt */
136
+#define REG_MIEN_ENTXCP (1 << 18)
137
+/* Enable Transmit Interrupt */
138
+#define REG_MIEN_ENTXINTR (1 << 16)
139
+/* Enable Receive Descriptor Unavailable Interrupt */
140
+#define REG_MIEN_ENRDU (1 << 10)
141
+/* Enable Receive Good Interrupt */
142
+#define REG_MIEN_ENRXGD (1 << 4)
143
+/* Enable Receive Interrupt */
144
+#define REG_MIEN_ENRXINTR (1 << 0)
145
+
146
+/* REG_MISTA fields */
147
+/* TODO: Add error fields and support simulated errors? */
148
+/* Transmit Bus Error Interrupt */
149
+#define REG_MISTA_TXBERR (1 << 24)
150
+/* Transmit Descriptor Unavailable Interrupt */
151
+#define REG_MISTA_TDU (1 << 23)
152
+/* Transmit Completion Interrupt */
153
+#define REG_MISTA_TXCP (1 << 18)
154
+/* Transmit Interrupt */
155
+#define REG_MISTA_TXINTR (1 << 16)
156
+/* Receive Bus Error Interrupt */
157
+#define REG_MISTA_RXBERR (1 << 11)
158
+/* Receive Descriptor Unavailable Interrupt */
159
+#define REG_MISTA_RDU (1 << 10)
160
+/* DMA Early Notification Interrupt */
161
+#define REG_MISTA_DENI (1 << 9)
162
+/* Maximum Frame Length Interrupt */
163
+#define REG_MISTA_DFOI (1 << 8)
164
+/* Receive Good Interrupt */
165
+#define REG_MISTA_RXGD (1 << 4)
166
+/* Packet Too Long Interrupt */
167
+#define REG_MISTA_PTLE (1 << 3)
168
+/* Receive Interrupt */
169
+#define REG_MISTA_RXINTR (1 << 0)
170
+
171
+/* REG_MGSTA fields */
172
+/* Transmission Halted */
173
+#define REG_MGSTA_TXHA (1 << 11)
174
+/* Receive Halted */
175
+#define REG_MGSTA_RXHA (1 << 11)
176
+
177
+/* REG_DMARFC fields */
178
+/* Maximum Receive Frame Length */
179
+#define REG_DMARFC_RXMS(word) extract32((word), 0, 16)
180
+
181
+/* REG MIIDA fields */
182
+/* Busy Bit */
183
+#define REG_MIIDA_BUSY (1 << 17)
184
+
185
+/* Transmit and receive descriptors */
186
+typedef struct NPCM7xxEMCTxDesc NPCM7xxEMCTxDesc;
187
+typedef struct NPCM7xxEMCRxDesc NPCM7xxEMCRxDesc;
188
+
189
+struct NPCM7xxEMCTxDesc {
190
+ uint32_t flags;
191
+ uint32_t txbsa;
192
+ uint32_t status_and_length;
193
+ uint32_t ntxdsa;
194
+};
195
+
196
+struct NPCM7xxEMCRxDesc {
197
+ uint32_t status_and_length;
198
+ uint32_t rxbsa;
199
+ uint32_t reserved;
200
+ uint32_t nrxdsa;
201
+};
202
+
203
+/* NPCM7xxEMCTxDesc.flags values */
204
+/* Owner: 0 = cpu, 1 = emc */
205
+#define TX_DESC_FLAG_OWNER_MASK (1 << 31)
206
+/* Transmit interrupt enable */
207
+#define TX_DESC_FLAG_INTEN (1 << 2)
208
+/* CRC append */
209
+#define TX_DESC_FLAG_CRCAPP (1 << 1)
210
+/* Padding enable */
211
+#define TX_DESC_FLAG_PADEN (1 << 0)
212
+
213
+/* NPCM7xxEMCTxDesc.status_and_length values */
214
+/* Collision count */
215
+#define TX_DESC_STATUS_CCNT_SHIFT 28
216
+#define TX_DESC_STATUS_CCNT_BITSIZE 4
217
+/* SQE error */
218
+#define TX_DESC_STATUS_SQE (1 << 26)
219
+/* Transmission paused */
220
+#define TX_DESC_STATUS_PAU (1 << 25)
221
+/* P transmission halted */
222
+#define TX_DESC_STATUS_TXHA (1 << 24)
223
+/* Late collision */
224
+#define TX_DESC_STATUS_LC (1 << 23)
225
+/* Transmission abort */
226
+#define TX_DESC_STATUS_TXABT (1 << 22)
227
+/* No carrier sense */
228
+#define TX_DESC_STATUS_NCS (1 << 21)
229
+/* Defer exceed */
230
+#define TX_DESC_STATUS_EXDEF (1 << 20)
231
+/* Transmission complete */
232
+#define TX_DESC_STATUS_TXCP (1 << 19)
233
+/* Transmission deferred */
234
+#define TX_DESC_STATUS_DEF (1 << 17)
235
+/* Transmit interrupt */
236
+#define TX_DESC_STATUS_TXINTR (1 << 16)
237
+
238
+#define TX_DESC_PKT_LEN(word) extract32((word), 0, 16)
239
+
240
+/* Transmit buffer start address */
241
+#define TX_DESC_TXBSA(word) ((uint32_t) (word) & ~3u)
242
+
243
+/* Next transmit descriptor start address */
244
+#define TX_DESC_NTXDSA(word) ((uint32_t) (word) & ~3u)
245
+
246
+/* NPCM7xxEMCRxDesc.status_and_length values */
247
+/* Owner: 0b00 = cpu, 0b01 = undefined, 0b10 = emc, 0b11 = undefined */
248
+#define RX_DESC_STATUS_OWNER_SHIFT 30
249
+#define RX_DESC_STATUS_OWNER_BITSIZE 2
250
+#define RX_DESC_STATUS_OWNER_MASK (3 << RX_DESC_STATUS_OWNER_SHIFT)
251
+/* Runt packet */
252
+#define RX_DESC_STATUS_RP (1 << 22)
253
+/* Alignment error */
254
+#define RX_DESC_STATUS_ALIE (1 << 21)
255
+/* Frame reception complete */
256
+#define RX_DESC_STATUS_RXGD (1 << 20)
257
+/* Packet too long */
258
+#define RX_DESC_STATUS_PTLE (1 << 19)
259
+/* CRC error */
260
+#define RX_DESC_STATUS_CRCE (1 << 17)
261
+/* Receive interrupt */
262
+#define RX_DESC_STATUS_RXINTR (1 << 16)
263
+
264
+#define RX_DESC_PKT_LEN(word) extract32((word), 0, 16)
265
+
266
+/* Receive buffer start address */
267
+#define RX_DESC_RXBSA(word) ((uint32_t) (word) & ~3u)
268
+
269
+/* Next receive descriptor start address */
270
+#define RX_DESC_NRXDSA(word) ((uint32_t) (word) & ~3u)
271
+
272
+/* Minimum packet length, when TX_DESC_FLAG_PADEN is set. */
273
+#define MIN_PACKET_LENGTH 64
274
+
275
+struct NPCM7xxEMCState {
276
+ /*< private >*/
277
+ SysBusDevice parent;
89
+ SysBusDevice parent;
278
+ /*< public >*/
279
+
90
+
280
+ MemoryRegion iomem;
91
+ MemoryRegion iomem;
281
+
92
+
282
+ qemu_irq tx_irq;
93
+ Clock *clock_in;
283
+ qemu_irq rx_irq;
94
+ Clock *clock_1, *clock_2;
284
+
95
+ qemu_irq irq;
285
+ NICState *nic;
96
+ uint16_t regs[NPCM7XX_MFT_NR_REGS];
286
+ NICConf conf;
97
+
287
+
98
+ uint32_t max_rpm[NPCM7XX_MFT_FANIN_COUNT];
288
+ /* 0 or 1, for log messages */
99
+ uint32_t duty[NPCM7XX_MFT_FANIN_COUNT];
289
+ uint8_t emc_num;
100
+} NPCM7xxMFTState;
290
+
101
+
291
+ uint32_t regs[NPCM7XX_NUM_EMC_REGS];
102
+#define TYPE_NPCM7XX_MFT "npcm7xx-mft"
292
+
103
+#define NPCM7XX_MFT(obj) \
293
+ /*
104
+ OBJECT_CHECK(NPCM7xxMFTState, (obj), TYPE_NPCM7XX_MFT)
294
+ * tx is active. Set to true by TSDR and then switches off when out of
105
+
295
+ * descriptors. If the TXON bit in REG_MCMDR is off then this is off.
106
+#endif /* NPCM7XX_MFT_H */
296
+ */
107
diff --git a/hw/misc/npcm7xx_mft.c b/hw/misc/npcm7xx_mft.c
297
+ bool tx_active;
298
+
299
+ /*
300
+ * rx is active. Set to true by RSDR and then switches off when out of
301
+ * descriptors. If the RXON bit in REG_MCMDR is off then this is off.
302
+ */
303
+ bool rx_active;
304
+};
305
+
306
+typedef struct NPCM7xxEMCState NPCM7xxEMCState;
307
+
308
+#define TYPE_NPCM7XX_EMC "npcm7xx-emc"
309
+#define NPCM7XX_EMC(obj) \
310
+ OBJECT_CHECK(NPCM7xxEMCState, (obj), TYPE_NPCM7XX_EMC)
311
+
312
+#endif /* NPCM7XX_EMC_H */
313
diff --git a/hw/net/npcm7xx_emc.c b/hw/net/npcm7xx_emc.c
314
new file mode 100644
108
new file mode 100644
315
index XXXXXXX..XXXXXXX
109
index XXXXXXX..XXXXXXX
316
--- /dev/null
110
--- /dev/null
317
+++ b/hw/net/npcm7xx_emc.c
111
+++ b/hw/misc/npcm7xx_mft.c
318
@@ -XXX,XX +XXX,XX @@
112
@@ -XXX,XX +XXX,XX @@
319
+/*
113
+/*
320
+ * Nuvoton NPCM7xx EMC Module
114
+ * Nuvoton NPCM7xx MFT Module
321
+ *
115
+ *
322
+ * Copyright 2020 Google LLC
116
+ * Copyright 2021 Google LLC
323
+ *
117
+ *
324
+ * This program is free software; you can redistribute it and/or modify it
118
+ * This program is free software; you can redistribute it and/or modify it
325
+ * under the terms of the GNU General Public License as published by the
119
+ * under the terms of the GNU General Public License as published by the
326
+ * Free Software Foundation; either version 2 of the License, or
120
+ * Free Software Foundation; either version 2 of the License, or
327
+ * (at your option) any later version.
121
+ * (at your option) any later version.
328
+ *
122
+ *
329
+ * This program is distributed in the hope that it will be useful, but WITHOUT
123
+ * This program is distributed in the hope that it will be useful, but WITHOUT
330
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
124
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
331
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
125
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
332
+ * for more details.
126
+ * for more details.
333
+ *
334
+ * Unsupported/unimplemented features:
335
+ * - MCMDR.FDUP (full duplex) is ignored, half duplex is not supported
336
+ * - Only CAM0 is supported, CAM[1-15] are not
337
+ * - writes to CAMEN.[1-15] are ignored, these bits always read as zeroes
338
+ * - MII is not implemented, MIIDA.BUSY and MIID always return zero
339
+ * - MCMDR.LBK is not implemented
340
+ * - MCMDR.{OPMOD,ENSQE,AEP,ARP} are not supported
341
+ * - H/W FIFOs are not supported, MCMDR.FFTCR is ignored
342
+ * - MGSTA.SQE is not supported
343
+ * - pause and control frames are not implemented
344
+ * - MGSTA.CCNT is not supported
345
+ * - MPCNT, DMARFS are not implemented
346
+ */
127
+ */
347
+
128
+
348
+#include "qemu/osdep.h"
129
+#include "qemu/osdep.h"
349
+
350
+/* For crc32 */
351
+#include <zlib.h>
352
+
353
+#include "qemu-common.h"
354
+#include "hw/irq.h"
130
+#include "hw/irq.h"
355
+#include "hw/qdev-clock.h"
131
+#include "hw/qdev-clock.h"
356
+#include "hw/qdev-properties.h"
132
+#include "hw/qdev-properties.h"
357
+#include "hw/net/npcm7xx_emc.h"
133
+#include "hw/misc/npcm7xx_mft.h"
358
+#include "net/eth.h"
134
+#include "hw/misc/npcm7xx_pwm.h"
135
+#include "hw/registerfields.h"
359
+#include "migration/vmstate.h"
136
+#include "migration/vmstate.h"
137
+#include "qapi/error.h"
138
+#include "qapi/visitor.h"
360
+#include "qemu/bitops.h"
139
+#include "qemu/bitops.h"
361
+#include "qemu/error-report.h"
140
+#include "qemu/error-report.h"
362
+#include "qemu/log.h"
141
+#include "qemu/log.h"
363
+#include "qemu/module.h"
142
+#include "qemu/module.h"
143
+#include "qemu/timer.h"
364
+#include "qemu/units.h"
144
+#include "qemu/units.h"
365
+#include "sysemu/dma.h"
366
+#include "trace.h"
145
+#include "trace.h"
367
+
146
+
368
+#define CRC_LENGTH 4
369
+
370
+/*
147
+/*
371
+ * The maximum size of a (layer 2) ethernet frame as defined by 802.3.
148
+ * Some of the registers can only accessed via 16-bit ops and some can only
372
+ * 1518 = 6(dest macaddr) + 6(src macaddr) + 2(proto) + 4(crc) + 1500(payload)
149
+ * be accessed via 8-bit ops. However we mark all of them using REG16 to
373
+ * This does not include an additional 4 for the vlan field (802.1q).
150
+ * simplify implementation. npcm7xx_mft_check_mem_op checks the access length
374
+ */
151
+ * of memory operations.
375
+#define MAX_ETH_FRAME_SIZE 1518
152
+ */
376
+
153
+REG16(NPCM7XX_MFT_CNT1, 0x00);
377
+static const char *emc_reg_name(int regno)
154
+REG16(NPCM7XX_MFT_CRA, 0x02);
378
+{
155
+REG16(NPCM7XX_MFT_CRB, 0x04);
379
+#define REG(name) case REG_ ## name: return #name;
156
+REG16(NPCM7XX_MFT_CNT2, 0x06);
380
+ switch (regno) {
157
+REG16(NPCM7XX_MFT_PRSC, 0x08);
381
+ REG(CAMCMR)
158
+REG16(NPCM7XX_MFT_CKC, 0x0a);
382
+ REG(CAMEN)
159
+REG16(NPCM7XX_MFT_MCTRL, 0x0c);
383
+ REG(TXDLSA)
160
+REG16(NPCM7XX_MFT_ICTRL, 0x0e);
384
+ REG(RXDLSA)
161
+REG16(NPCM7XX_MFT_ICLR, 0x10);
385
+ REG(MCMDR)
162
+REG16(NPCM7XX_MFT_IEN, 0x12);
386
+ REG(MIID)
163
+REG16(NPCM7XX_MFT_CPA, 0x14);
387
+ REG(MIIDA)
164
+REG16(NPCM7XX_MFT_CPB, 0x16);
388
+ REG(FFTCR)
165
+REG16(NPCM7XX_MFT_CPCFG, 0x18);
389
+ REG(TSDR)
166
+REG16(NPCM7XX_MFT_INASEL, 0x1a);
390
+ REG(RSDR)
167
+REG16(NPCM7XX_MFT_INBSEL, 0x1c);
391
+ REG(DMARFC)
168
+
392
+ REG(MIEN)
169
+/* Register Fields */
393
+ REG(MISTA)
170
+#define NPCM7XX_MFT_CKC_C2CSEL BIT(3)
394
+ REG(MGSTA)
171
+#define NPCM7XX_MFT_CKC_C1CSEL BIT(0)
395
+ REG(MPCNT)
172
+
396
+ REG(MRPC)
173
+#define NPCM7XX_MFT_MCTRL_TBEN BIT(6)
397
+ REG(MRPCC)
174
+#define NPCM7XX_MFT_MCTRL_TAEN BIT(5)
398
+ REG(MREPC)
175
+#define NPCM7XX_MFT_MCTRL_TBEDG BIT(4)
399
+ REG(DMARFS)
176
+#define NPCM7XX_MFT_MCTRL_TAEDG BIT(3)
400
+ REG(CTXDSA)
177
+#define NPCM7XX_MFT_MCTRL_MODE5 BIT(2)
401
+ REG(CTXBSA)
178
+
402
+ REG(CRXDSA)
179
+#define NPCM7XX_MFT_ICTRL_TFPND BIT(5)
403
+ REG(CRXBSA)
180
+#define NPCM7XX_MFT_ICTRL_TEPND BIT(4)
404
+ case REG_CAMM_BASE + 0: return "CAM0M";
181
+#define NPCM7XX_MFT_ICTRL_TDPND BIT(3)
405
+ case REG_CAML_BASE + 0: return "CAM0L";
182
+#define NPCM7XX_MFT_ICTRL_TCPND BIT(2)
406
+ case REG_CAMM_BASE + 2 ... REG_CAMML_LAST:
183
+#define NPCM7XX_MFT_ICTRL_TBPND BIT(1)
407
+ /* Only CAM0 is supported, fold the others into something simple. */
184
+#define NPCM7XX_MFT_ICTRL_TAPND BIT(0)
408
+ if (regno & 1) {
185
+
409
+ return "CAM<n>L";
186
+#define NPCM7XX_MFT_ICLR_TFCLR BIT(5)
187
+#define NPCM7XX_MFT_ICLR_TECLR BIT(4)
188
+#define NPCM7XX_MFT_ICLR_TDCLR BIT(3)
189
+#define NPCM7XX_MFT_ICLR_TCCLR BIT(2)
190
+#define NPCM7XX_MFT_ICLR_TBCLR BIT(1)
191
+#define NPCM7XX_MFT_ICLR_TACLR BIT(0)
192
+
193
+#define NPCM7XX_MFT_IEN_TFIEN BIT(5)
194
+#define NPCM7XX_MFT_IEN_TEIEN BIT(4)
195
+#define NPCM7XX_MFT_IEN_TDIEN BIT(3)
196
+#define NPCM7XX_MFT_IEN_TCIEN BIT(2)
197
+#define NPCM7XX_MFT_IEN_TBIEN BIT(1)
198
+#define NPCM7XX_MFT_IEN_TAIEN BIT(0)
199
+
200
+#define NPCM7XX_MFT_CPCFG_GET_B(rv) extract8((rv), 4, 4)
201
+#define NPCM7XX_MFT_CPCFG_GET_A(rv) extract8((rv), 0, 4)
202
+#define NPCM7XX_MFT_CPCFG_HIEN BIT(3)
203
+#define NPCM7XX_MFT_CPCFG_EQEN BIT(2)
204
+#define NPCM7XX_MFT_CPCFG_LOEN BIT(1)
205
+#define NPCM7XX_MFT_CPCFG_CPSEL BIT(0)
206
+
207
+#define NPCM7XX_MFT_INASEL_SELA BIT(0)
208
+#define NPCM7XX_MFT_INBSEL_SELB BIT(0)
209
+
210
+/* Max CNT values of the module. The CNT value is a countdown from it. */
211
+#define NPCM7XX_MFT_MAX_CNT 0xFFFF
212
+
213
+/* Each fan revolution should generated 2 pulses */
214
+#define NPCM7XX_MFT_PULSE_PER_REVOLUTION 2
215
+
216
+typedef enum NPCM7xxMFTCaptureState {
217
+ /* capture succeeded with a valid CNT value. */
218
+ NPCM7XX_CAPTURE_SUCCEED,
219
+ /* capture stopped prematurely due to reaching CPCFG condition. */
220
+ NPCM7XX_CAPTURE_COMPARE_HIT,
221
+ /* capture fails since it reaches underflow condition for CNT. */
222
+ NPCM7XX_CAPTURE_UNDERFLOW,
223
+} NPCM7xxMFTCaptureState;
224
+
225
+static void npcm7xx_mft_reset(NPCM7xxMFTState *s)
226
+{
227
+ int i;
228
+
229
+ /* Only registers PRSC ~ INBSEL need to be reset. */
230
+ for (i = R_NPCM7XX_MFT_PRSC; i <= R_NPCM7XX_MFT_INBSEL; ++i) {
231
+ s->regs[i] = 0;
232
+ }
233
+}
234
+
235
+static void npcm7xx_mft_clear_interrupt(NPCM7xxMFTState *s, uint8_t iclr)
236
+{
237
+ /*
238
+ * Clear bits in ICTRL where corresponding bits in iclr is 1.
239
+ * Both iclr and ictrl are 8-bit regs. (See npcm7xx_mft_check_mem_op)
240
+ */
241
+ s->regs[R_NPCM7XX_MFT_ICTRL] &= ~iclr;
242
+}
243
+
244
+/*
245
+ * If the CPCFG's condition should be triggered during count down from
246
+ * NPCM7XX_MFT_MAX_CNT to src if compared to tgt, return the count when
247
+ * the condition is triggered.
248
+ * Otherwise return -1.
249
+ * Since tgt is uint16_t it must always <= NPCM7XX_MFT_MAX_CNT.
250
+ */
251
+static int npcm7xx_mft_compare(int32_t src, uint16_t tgt, uint8_t cpcfg)
252
+{
253
+ if (cpcfg & NPCM7XX_MFT_CPCFG_HIEN) {
254
+ return NPCM7XX_MFT_MAX_CNT;
255
+ }
256
+ if ((cpcfg & NPCM7XX_MFT_CPCFG_EQEN) && (src <= tgt)) {
257
+ return tgt;
258
+ }
259
+ if ((cpcfg & NPCM7XX_MFT_CPCFG_LOEN) && (tgt > 0) && (src < tgt)) {
260
+ return tgt - 1;
261
+ }
262
+
263
+ return -1;
264
+}
265
+
266
+/* Compute CNT according to corresponding fan's RPM. */
267
+static NPCM7xxMFTCaptureState npcm7xx_mft_compute_cnt(
268
+ Clock *clock, uint32_t max_rpm, uint32_t duty, uint16_t tgt,
269
+ uint8_t cpcfg, uint16_t *cnt)
270
+{
271
+ uint32_t rpm = (uint64_t)max_rpm * (uint64_t)duty / NPCM7XX_PWM_MAX_DUTY;
272
+ int32_t count;
273
+ int stopped;
274
+ NPCM7xxMFTCaptureState state;
275
+
276
+ if (rpm == 0) {
277
+ /*
278
+ * If RPM = 0, capture won't happen. CNT will continue count down.
279
+ * So it's effective equivalent to have a cnt > NPCM7XX_MFT_MAX_CNT
280
+ */
281
+ count = NPCM7XX_MFT_MAX_CNT + 1;
282
+ } else {
283
+ /*
284
+ * RPM = revolution/min. The time for one revlution (in ns) is
285
+ * MINUTE_TO_NANOSECOND / RPM.
286
+ */
287
+ count = clock_ns_to_ticks(clock, (60 * NANOSECONDS_PER_SECOND) /
288
+ (rpm * NPCM7XX_MFT_PULSE_PER_REVOLUTION));
289
+ }
290
+
291
+ if (count > NPCM7XX_MFT_MAX_CNT) {
292
+ count = -1;
293
+ } else {
294
+ /* The CNT is a countdown value from NPCM7XX_MFT_MAX_CNT. */
295
+ count = NPCM7XX_MFT_MAX_CNT - count;
296
+ }
297
+ stopped = npcm7xx_mft_compare(count, tgt, cpcfg);
298
+ if (stopped == -1) {
299
+ if (count == -1) {
300
+ /* Underflow */
301
+ state = NPCM7XX_CAPTURE_UNDERFLOW;
410
+ } else {
302
+ } else {
411
+ return "CAM<n>M";
303
+ state = NPCM7XX_CAPTURE_SUCCEED;
412
+ }
304
+ }
413
+ default: return "UNKNOWN";
305
+ } else {
414
+ }
306
+ count = stopped;
415
+#undef REG
307
+ state = NPCM7XX_CAPTURE_COMPARE_HIT;
416
+}
308
+ }
417
+
309
+
418
+static void emc_reset(NPCM7xxEMCState *emc)
310
+ if (count != -1) {
419
+{
311
+ *cnt = count;
420
+ trace_npcm7xx_emc_reset(emc->emc_num);
312
+ }
421
+
313
+ trace_npcm7xx_mft_rpm(clock->canonical_path, clock_get_hz(clock),
422
+ memset(&emc->regs[0], 0, sizeof(emc->regs));
314
+ state, count, rpm, duty);
423
+
315
+ return state;
424
+ /* These regs have non-zero reset values. */
316
+}
425
+ emc->regs[REG_TXDLSA] = 0xfffffffc;
317
+
426
+ emc->regs[REG_RXDLSA] = 0xfffffffc;
318
+/*
427
+ emc->regs[REG_MIIDA] = 0x00900000;
319
+ * Capture Fan RPM and update CNT and CR registers accordingly.
428
+ emc->regs[REG_FFTCR] = 0x0101;
320
+ * Raise IRQ if certain contidions are met in IEN.
429
+ emc->regs[REG_DMARFC] = 0x0800;
321
+ */
430
+ emc->regs[REG_MPCNT] = 0x7fff;
322
+static void npcm7xx_mft_capture(NPCM7xxMFTState *s)
431
+
323
+{
432
+ emc->tx_active = false;
324
+ int irq_level = 0;
433
+ emc->rx_active = false;
325
+ NPCM7xxMFTCaptureState state;
434
+}
326
+ int sel;
435
+
327
+ uint8_t cpcfg;
436
+static void npcm7xx_emc_reset(DeviceState *dev)
328
+
437
+{
438
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(dev);
439
+ emc_reset(emc);
440
+}
441
+
442
+static void emc_soft_reset(NPCM7xxEMCState *emc)
443
+{
444
+ /*
329
+ /*
445
+ * The docs say at least MCMDR.{LBK,OPMOD} bits are not changed during a
330
+ * If not mode 5, the behavior is undefined. We just do nothing in this
446
+ * soft reset, but does not go into further detail. For now, KISS.
331
+ * case.
447
+ */
332
+ */
448
+ uint32_t mcmdr = emc->regs[REG_MCMDR];
333
+ if (!(s->regs[R_NPCM7XX_MFT_MCTRL] & NPCM7XX_MFT_MCTRL_MODE5)) {
449
+ emc_reset(emc);
334
+ return;
450
+ emc->regs[REG_MCMDR] = mcmdr & (REG_MCMDR_LBK | REG_MCMDR_OPMOD);
335
+ }
451
+
336
+
452
+ qemu_set_irq(emc->tx_irq, 0);
337
+ /* Capture input A. */
453
+ qemu_set_irq(emc->rx_irq, 0);
338
+ if (s->regs[R_NPCM7XX_MFT_MCTRL] & NPCM7XX_MFT_MCTRL_TAEN &&
454
+}
339
+ s->regs[R_NPCM7XX_MFT_CKC] & NPCM7XX_MFT_CKC_C1CSEL) {
455
+
340
+ sel = s->regs[R_NPCM7XX_MFT_INASEL] & NPCM7XX_MFT_INASEL_SELA;
456
+static void emc_set_link(NetClientState *nc)
341
+ cpcfg = NPCM7XX_MFT_CPCFG_GET_A(s->regs[R_NPCM7XX_MFT_CPCFG]);
457
+{
342
+ state = npcm7xx_mft_compute_cnt(s->clock_1,
458
+ /* Nothing to do yet. */
343
+ sel ? s->max_rpm[2] : s->max_rpm[0],
459
+}
344
+ sel ? s->duty[2] : s->duty[0],
460
+
345
+ s->regs[R_NPCM7XX_MFT_CPA],
461
+/* MISTA.TXINTR is the union of the individual bits with their enables. */
346
+ cpcfg,
462
+static void emc_update_mista_txintr(NPCM7xxEMCState *emc)
347
+ &s->regs[R_NPCM7XX_MFT_CNT1]);
463
+{
348
+ switch (state) {
464
+ /* Only look at the bits we support. */
349
+ case NPCM7XX_CAPTURE_SUCCEED:
465
+ uint32_t mask = (REG_MISTA_TXBERR |
350
+ /* Interrupt on input capture on TAn transition - TAPND */
466
+ REG_MISTA_TDU |
351
+ s->regs[R_NPCM7XX_MFT_CRA] = s->regs[R_NPCM7XX_MFT_CNT1];
467
+ REG_MISTA_TXCP);
352
+ s->regs[R_NPCM7XX_MFT_ICTRL] |= NPCM7XX_MFT_ICTRL_TAPND;
468
+ if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & mask) {
353
+ if (s->regs[R_NPCM7XX_MFT_IEN] & NPCM7XX_MFT_IEN_TAIEN) {
469
+ emc->regs[REG_MISTA] |= REG_MISTA_TXINTR;
354
+ irq_level = 1;
355
+ }
356
+ break;
357
+
358
+ case NPCM7XX_CAPTURE_COMPARE_HIT:
359
+ /* Compare Hit - TEPND */
360
+ s->regs[R_NPCM7XX_MFT_ICTRL] |= NPCM7XX_MFT_ICTRL_TEPND;
361
+ if (s->regs[R_NPCM7XX_MFT_IEN] & NPCM7XX_MFT_IEN_TEIEN) {
362
+ irq_level = 1;
363
+ }
364
+ break;
365
+
366
+ case NPCM7XX_CAPTURE_UNDERFLOW:
367
+ /* Underflow - TCPND */
368
+ s->regs[R_NPCM7XX_MFT_ICTRL] |= NPCM7XX_MFT_ICTRL_TCPND;
369
+ if (s->regs[R_NPCM7XX_MFT_IEN] & NPCM7XX_MFT_IEN_TCIEN) {
370
+ irq_level = 1;
371
+ }
372
+ break;
373
+
374
+ default:
375
+ g_assert_not_reached();
376
+ }
377
+ }
378
+
379
+ /* Capture input B. */
380
+ if (s->regs[R_NPCM7XX_MFT_MCTRL] & NPCM7XX_MFT_MCTRL_TBEN &&
381
+ s->regs[R_NPCM7XX_MFT_CKC] & NPCM7XX_MFT_CKC_C2CSEL) {
382
+ sel = s->regs[R_NPCM7XX_MFT_INBSEL] & NPCM7XX_MFT_INBSEL_SELB;
383
+ cpcfg = NPCM7XX_MFT_CPCFG_GET_B(s->regs[R_NPCM7XX_MFT_CPCFG]);
384
+ state = npcm7xx_mft_compute_cnt(s->clock_2,
385
+ sel ? s->max_rpm[3] : s->max_rpm[1],
386
+ sel ? s->duty[3] : s->duty[1],
387
+ s->regs[R_NPCM7XX_MFT_CPB],
388
+ cpcfg,
389
+ &s->regs[R_NPCM7XX_MFT_CNT2]);
390
+ switch (state) {
391
+ case NPCM7XX_CAPTURE_SUCCEED:
392
+ /* Interrupt on input capture on TBn transition - TBPND */
393
+ s->regs[R_NPCM7XX_MFT_CRB] = s->regs[R_NPCM7XX_MFT_CNT2];
394
+ s->regs[R_NPCM7XX_MFT_ICTRL] |= NPCM7XX_MFT_ICTRL_TBPND;
395
+ if (s->regs[R_NPCM7XX_MFT_IEN] & NPCM7XX_MFT_IEN_TBIEN) {
396
+ irq_level = 1;
397
+ }
398
+ break;
399
+
400
+ case NPCM7XX_CAPTURE_COMPARE_HIT:
401
+ /* Compare Hit - TFPND */
402
+ s->regs[R_NPCM7XX_MFT_ICTRL] |= NPCM7XX_MFT_ICTRL_TFPND;
403
+ if (s->regs[R_NPCM7XX_MFT_IEN] & NPCM7XX_MFT_IEN_TFIEN) {
404
+ irq_level = 1;
405
+ }
406
+ break;
407
+
408
+ case NPCM7XX_CAPTURE_UNDERFLOW:
409
+ /* Underflow - TDPND */
410
+ s->regs[R_NPCM7XX_MFT_ICTRL] |= NPCM7XX_MFT_ICTRL_TDPND;
411
+ if (s->regs[R_NPCM7XX_MFT_IEN] & NPCM7XX_MFT_IEN_TDIEN) {
412
+ irq_level = 1;
413
+ }
414
+ break;
415
+
416
+ default:
417
+ g_assert_not_reached();
418
+ }
419
+ }
420
+
421
+ trace_npcm7xx_mft_capture(DEVICE(s)->canonical_path, irq_level);
422
+ qemu_set_irq(s->irq, irq_level);
423
+}
424
+
425
+/* Update clock for counters. */
426
+static void npcm7xx_mft_update_clock(void *opaque, ClockEvent event)
427
+{
428
+ NPCM7xxMFTState *s = NPCM7XX_MFT(opaque);
429
+ uint64_t prescaled_clock_period;
430
+
431
+ prescaled_clock_period = clock_get(s->clock_in) *
432
+ (s->regs[R_NPCM7XX_MFT_PRSC] + 1ULL);
433
+ trace_npcm7xx_mft_update_clock(s->clock_in->canonical_path,
434
+ s->regs[R_NPCM7XX_MFT_CKC],
435
+ clock_get(s->clock_in),
436
+ prescaled_clock_period);
437
+ /* Update clock 1 */
438
+ if (s->regs[R_NPCM7XX_MFT_CKC] & NPCM7XX_MFT_CKC_C1CSEL) {
439
+ /* Clock is prescaled. */
440
+ clock_update(s->clock_1, prescaled_clock_period);
470
+ } else {
441
+ } else {
471
+ emc->regs[REG_MISTA] &= ~REG_MISTA_TXINTR;
442
+ /* Clock stopped. */
472
+ }
443
+ clock_update(s->clock_1, 0);
473
+}
444
+ }
474
+
445
+ /* Update clock 2 */
475
+/* MISTA.RXINTR is the union of the individual bits with their enables. */
446
+ if (s->regs[R_NPCM7XX_MFT_CKC] & NPCM7XX_MFT_CKC_C2CSEL) {
476
+static void emc_update_mista_rxintr(NPCM7xxEMCState *emc)
447
+ /* Clock is prescaled. */
477
+{
448
+ clock_update(s->clock_2, prescaled_clock_period);
478
+ /* Only look at the bits we support. */
479
+ uint32_t mask = (REG_MISTA_RXBERR |
480
+ REG_MISTA_RDU |
481
+ REG_MISTA_RXGD);
482
+ if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & mask) {
483
+ emc->regs[REG_MISTA] |= REG_MISTA_RXINTR;
484
+ } else {
449
+ } else {
485
+ emc->regs[REG_MISTA] &= ~REG_MISTA_RXINTR;
450
+ /* Clock stopped. */
486
+ }
451
+ clock_update(s->clock_2, 0);
487
+}
452
+ }
488
+
453
+
489
+/* N.B. emc_update_mista_txintr must have already been called. */
454
+ npcm7xx_mft_capture(s);
490
+static void emc_update_tx_irq(NPCM7xxEMCState *emc)
455
+}
491
+{
456
+
492
+ int level = !!(emc->regs[REG_MISTA] &
457
+static uint64_t npcm7xx_mft_read(void *opaque, hwaddr offset, unsigned size)
493
+ emc->regs[REG_MIEN] &
458
+{
494
+ REG_MISTA_TXINTR);
459
+ NPCM7xxMFTState *s = NPCM7XX_MFT(opaque);
495
+ trace_npcm7xx_emc_update_tx_irq(level);
460
+ uint16_t value = 0;
496
+ qemu_set_irq(emc->tx_irq, level);
461
+
497
+}
462
+ switch (offset) {
498
+
463
+ case A_NPCM7XX_MFT_ICLR:
499
+/* N.B. emc_update_mista_rxintr must have already been called. */
464
+ qemu_log_mask(LOG_GUEST_ERROR,
500
+static void emc_update_rx_irq(NPCM7xxEMCState *emc)
465
+ "%s: register @ 0x%04" HWADDR_PRIx " is write-only\n",
501
+{
466
+ __func__, offset);
502
+ int level = !!(emc->regs[REG_MISTA] &
467
+ break;
503
+ emc->regs[REG_MIEN] &
468
+
504
+ REG_MISTA_RXINTR);
469
+ default:
505
+ trace_npcm7xx_emc_update_rx_irq(level);
470
+ value = s->regs[offset / 2];
506
+ qemu_set_irq(emc->rx_irq, level);
471
+ }
507
+}
472
+
508
+
473
+ trace_npcm7xx_mft_read(DEVICE(s)->canonical_path, offset, value);
509
+/* Update IRQ states due to changes in MIEN,MISTA. */
474
+ return value;
510
+static void emc_update_irq_from_reg_change(NPCM7xxEMCState *emc)
475
+}
511
+{
476
+
512
+ emc_update_mista_txintr(emc);
477
+static void npcm7xx_mft_write(void *opaque, hwaddr offset,
513
+ emc_update_tx_irq(emc);
478
+ uint64_t v, unsigned size)
514
+
479
+{
515
+ emc_update_mista_rxintr(emc);
480
+ NPCM7xxMFTState *s = NPCM7XX_MFT(opaque);
516
+ emc_update_rx_irq(emc);
481
+
517
+}
482
+ trace_npcm7xx_mft_write(DEVICE(s)->canonical_path, offset, v);
518
+
483
+ switch (offset) {
519
+static int emc_read_tx_desc(dma_addr_t addr, NPCM7xxEMCTxDesc *desc)
484
+ case A_NPCM7XX_MFT_ICLR:
520
+{
485
+ npcm7xx_mft_clear_interrupt(s, v);
521
+ if (dma_memory_read(&address_space_memory, addr, desc, sizeof(*desc))) {
486
+ break;
522
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read descriptor @ 0x%"
487
+
523
+ HWADDR_PRIx "\n", __func__, addr);
488
+ case A_NPCM7XX_MFT_CKC:
524
+ return -1;
489
+ case A_NPCM7XX_MFT_PRSC:
525
+ }
490
+ s->regs[offset / 2] = v;
526
+ desc->flags = le32_to_cpu(desc->flags);
491
+ npcm7xx_mft_update_clock(s, ClockUpdate);
527
+ desc->txbsa = le32_to_cpu(desc->txbsa);
492
+ break;
528
+ desc->status_and_length = le32_to_cpu(desc->status_and_length);
493
+
529
+ desc->ntxdsa = le32_to_cpu(desc->ntxdsa);
494
+ default:
530
+ return 0;
495
+ s->regs[offset / 2] = v;
531
+}
496
+ npcm7xx_mft_capture(s);
532
+
497
+ break;
533
+static int emc_write_tx_desc(const NPCM7xxEMCTxDesc *desc, dma_addr_t addr)
498
+ }
534
+{
499
+}
535
+ NPCM7xxEMCTxDesc le_desc;
500
+
536
+
501
+static bool npcm7xx_mft_check_mem_op(void *opaque, hwaddr offset,
537
+ le_desc.flags = cpu_to_le32(desc->flags);
502
+ unsigned size, bool is_write,
538
+ le_desc.txbsa = cpu_to_le32(desc->txbsa);
503
+ MemTxAttrs attrs)
539
+ le_desc.status_and_length = cpu_to_le32(desc->status_and_length);
504
+{
540
+ le_desc.ntxdsa = cpu_to_le32(desc->ntxdsa);
505
+ switch (offset) {
541
+ if (dma_memory_write(&address_space_memory, addr, &le_desc,
506
+ /* 16-bit registers. Must be accessed with 16-bit read/write.*/
542
+ sizeof(le_desc))) {
507
+ case A_NPCM7XX_MFT_CNT1:
543
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to write descriptor @ 0x%"
508
+ case A_NPCM7XX_MFT_CRA:
544
+ HWADDR_PRIx "\n", __func__, addr);
509
+ case A_NPCM7XX_MFT_CRB:
545
+ return -1;
510
+ case A_NPCM7XX_MFT_CNT2:
546
+ }
511
+ case A_NPCM7XX_MFT_CPA:
547
+ return 0;
512
+ case A_NPCM7XX_MFT_CPB:
548
+}
513
+ return size == 2;
549
+
514
+
550
+static int emc_read_rx_desc(dma_addr_t addr, NPCM7xxEMCRxDesc *desc)
515
+ /* 8-bit registers. Must be accessed with 8-bit read/write.*/
551
+{
516
+ case A_NPCM7XX_MFT_PRSC:
552
+ if (dma_memory_read(&address_space_memory, addr, desc, sizeof(*desc))) {
517
+ case A_NPCM7XX_MFT_CKC:
553
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read descriptor @ 0x%"
518
+ case A_NPCM7XX_MFT_MCTRL:
554
+ HWADDR_PRIx "\n", __func__, addr);
519
+ case A_NPCM7XX_MFT_ICTRL:
555
+ return -1;
520
+ case A_NPCM7XX_MFT_ICLR:
556
+ }
521
+ case A_NPCM7XX_MFT_IEN:
557
+ desc->status_and_length = le32_to_cpu(desc->status_and_length);
522
+ case A_NPCM7XX_MFT_CPCFG:
558
+ desc->rxbsa = le32_to_cpu(desc->rxbsa);
523
+ case A_NPCM7XX_MFT_INASEL:
559
+ desc->reserved = le32_to_cpu(desc->reserved);
524
+ case A_NPCM7XX_MFT_INBSEL:
560
+ desc->nrxdsa = le32_to_cpu(desc->nrxdsa);
525
+ return size == 1;
561
+ return 0;
526
+
562
+}
527
+ default:
563
+
528
+ /* Invalid registers. */
564
+static int emc_write_rx_desc(const NPCM7xxEMCRxDesc *desc, dma_addr_t addr)
529
+ return false;
565
+{
530
+ }
566
+ NPCM7xxEMCRxDesc le_desc;
531
+}
567
+
532
+
568
+ le_desc.status_and_length = cpu_to_le32(desc->status_and_length);
533
+static void npcm7xx_mft_get_max_rpm(Object *obj, Visitor *v, const char *name,
569
+ le_desc.rxbsa = cpu_to_le32(desc->rxbsa);
534
+ void *opaque, Error **errp)
570
+ le_desc.reserved = cpu_to_le32(desc->reserved);
535
+{
571
+ le_desc.nrxdsa = cpu_to_le32(desc->nrxdsa);
536
+ visit_type_uint32(v, name, (uint32_t *)opaque, errp);
572
+ if (dma_memory_write(&address_space_memory, addr, &le_desc,
537
+}
573
+ sizeof(le_desc))) {
538
+
574
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to write descriptor @ 0x%"
539
+static void npcm7xx_mft_set_max_rpm(Object *obj, Visitor *v, const char *name,
575
+ HWADDR_PRIx "\n", __func__, addr);
540
+ void *opaque, Error **errp)
576
+ return -1;
541
+{
577
+ }
542
+ NPCM7xxMFTState *s = NPCM7XX_MFT(obj);
578
+ return 0;
543
+ uint32_t *max_rpm = opaque;
579
+}
544
+ uint32_t value;
580
+
545
+
581
+static void emc_set_mista(NPCM7xxEMCState *emc, uint32_t flags)
546
+ if (!visit_type_uint32(v, name, &value, errp)) {
582
+{
583
+ trace_npcm7xx_emc_set_mista(flags);
584
+ emc->regs[REG_MISTA] |= flags;
585
+ if (extract32(flags, 16, 16)) {
586
+ emc_update_mista_txintr(emc);
587
+ }
588
+ if (extract32(flags, 0, 16)) {
589
+ emc_update_mista_rxintr(emc);
590
+ }
591
+}
592
+
593
+static void emc_halt_tx(NPCM7xxEMCState *emc, uint32_t mista_flag)
594
+{
595
+ emc->tx_active = false;
596
+ emc_set_mista(emc, mista_flag);
597
+}
598
+
599
+static void emc_halt_rx(NPCM7xxEMCState *emc, uint32_t mista_flag)
600
+{
601
+ emc->rx_active = false;
602
+ emc_set_mista(emc, mista_flag);
603
+}
604
+
605
+static void emc_set_next_tx_descriptor(NPCM7xxEMCState *emc,
606
+ const NPCM7xxEMCTxDesc *tx_desc,
607
+ uint32_t desc_addr)
608
+{
609
+ /* Update the current descriptor, if only to reset the owner flag. */
610
+ if (emc_write_tx_desc(tx_desc, desc_addr)) {
611
+ /*
612
+ * We just read it so this shouldn't generally happen.
613
+ * Error already reported.
614
+ */
615
+ emc_set_mista(emc, REG_MISTA_TXBERR);
616
+ }
617
+ emc->regs[REG_CTXDSA] = TX_DESC_NTXDSA(tx_desc->ntxdsa);
618
+}
619
+
620
+static void emc_set_next_rx_descriptor(NPCM7xxEMCState *emc,
621
+ const NPCM7xxEMCRxDesc *rx_desc,
622
+ uint32_t desc_addr)
623
+{
624
+ /* Update the current descriptor, if only to reset the owner flag. */
625
+ if (emc_write_rx_desc(rx_desc, desc_addr)) {
626
+ /*
627
+ * We just read it so this shouldn't generally happen.
628
+ * Error already reported.
629
+ */
630
+ emc_set_mista(emc, REG_MISTA_RXBERR);
631
+ }
632
+ emc->regs[REG_CRXDSA] = RX_DESC_NRXDSA(rx_desc->nrxdsa);
633
+}
634
+
635
+static void emc_try_send_next_packet(NPCM7xxEMCState *emc)
636
+{
637
+ /* Working buffer for sending out packets. Most packets fit in this. */
638
+#define TX_BUFFER_SIZE 2048
639
+ uint8_t tx_send_buffer[TX_BUFFER_SIZE];
640
+ uint32_t desc_addr = TX_DESC_NTXDSA(emc->regs[REG_CTXDSA]);
641
+ NPCM7xxEMCTxDesc tx_desc;
642
+ uint32_t next_buf_addr, length;
643
+ uint8_t *buf;
644
+ g_autofree uint8_t *malloced_buf = NULL;
645
+
646
+ if (emc_read_tx_desc(desc_addr, &tx_desc)) {
647
+ /* Error reading descriptor, already reported. */
648
+ emc_halt_tx(emc, REG_MISTA_TXBERR);
649
+ emc_update_tx_irq(emc);
650
+ return;
547
+ return;
651
+ }
548
+ }
652
+
549
+
653
+ /* Nothing we can do if we don't own the descriptor. */
550
+ *max_rpm = value;
654
+ if (!(tx_desc.flags & TX_DESC_FLAG_OWNER_MASK)) {
551
+ npcm7xx_mft_capture(s);
655
+ trace_npcm7xx_emc_cpu_owned_desc(desc_addr);
552
+}
656
+ emc_halt_tx(emc, REG_MISTA_TDU);
553
+
657
+ emc_update_tx_irq(emc);
554
+static void npcm7xx_mft_duty_handler(void *opaque, int n, int value)
658
+ return;
555
+{
659
+ }
556
+ NPCM7xxMFTState *s = NPCM7XX_MFT(opaque);
660
+
557
+
661
+ /* Give the descriptor back regardless of what happens. */
558
+ trace_npcm7xx_mft_set_duty(DEVICE(s)->canonical_path, n, value);
662
+ tx_desc.flags &= ~TX_DESC_FLAG_OWNER_MASK;
559
+ s->duty[n] = value;
663
+ tx_desc.status_and_length &= 0xffff;
560
+ npcm7xx_mft_capture(s);
664
+
561
+}
665
+ /*
562
+
666
+ * Despite the h/w documentation saying the tx buffer is word aligned,
563
+static const struct MemoryRegionOps npcm7xx_mft_ops = {
667
+ * the linux driver does not word align the buffer. There is value in not
564
+ .read = npcm7xx_mft_read,
668
+ * aligning the buffer: See the description of NET_IP_ALIGN in linux
565
+ .write = npcm7xx_mft_write,
669
+ * kernel sources.
670
+ */
671
+ next_buf_addr = tx_desc.txbsa;
672
+ emc->regs[REG_CTXBSA] = next_buf_addr;
673
+ length = TX_DESC_PKT_LEN(tx_desc.status_and_length);
674
+ buf = &tx_send_buffer[0];
675
+
676
+ if (length > sizeof(tx_send_buffer)) {
677
+ malloced_buf = g_malloc(length);
678
+ buf = malloced_buf;
679
+ }
680
+
681
+ if (dma_memory_read(&address_space_memory, next_buf_addr, buf, length)) {
682
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read packet @ 0x%x\n",
683
+ __func__, next_buf_addr);
684
+ emc_set_mista(emc, REG_MISTA_TXBERR);
685
+ emc_set_next_tx_descriptor(emc, &tx_desc, desc_addr);
686
+ emc_update_tx_irq(emc);
687
+ trace_npcm7xx_emc_tx_done(emc->regs[REG_CTXDSA]);
688
+ return;
689
+ }
690
+
691
+ if ((tx_desc.flags & TX_DESC_FLAG_PADEN) && (length < MIN_PACKET_LENGTH)) {
692
+ memset(buf + length, 0, MIN_PACKET_LENGTH - length);
693
+ length = MIN_PACKET_LENGTH;
694
+ }
695
+
696
+ /* N.B. emc_receive can get called here. */
697
+ qemu_send_packet(qemu_get_queue(emc->nic), buf, length);
698
+ trace_npcm7xx_emc_sent_packet(length);
699
+
700
+ tx_desc.status_and_length |= TX_DESC_STATUS_TXCP;
701
+ if (tx_desc.flags & TX_DESC_FLAG_INTEN) {
702
+ emc_set_mista(emc, REG_MISTA_TXCP);
703
+ }
704
+ if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & REG_MISTA_TXINTR) {
705
+ tx_desc.status_and_length |= TX_DESC_STATUS_TXINTR;
706
+ }
707
+
708
+ emc_set_next_tx_descriptor(emc, &tx_desc, desc_addr);
709
+ emc_update_tx_irq(emc);
710
+ trace_npcm7xx_emc_tx_done(emc->regs[REG_CTXDSA]);
711
+}
712
+
713
+static bool emc_can_receive(NetClientState *nc)
714
+{
715
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(qemu_get_nic_opaque(nc));
716
+
717
+ bool can_receive = emc->rx_active;
718
+ trace_npcm7xx_emc_can_receive(can_receive);
719
+ return can_receive;
720
+}
721
+
722
+/* If result is false then *fail_reason contains the reason. */
723
+static bool emc_receive_filter1(NPCM7xxEMCState *emc, const uint8_t *buf,
724
+ size_t len, const char **fail_reason)
725
+{
726
+ eth_pkt_types_e pkt_type = get_eth_packet_type(PKT_GET_ETH_HDR(buf));
727
+
728
+ switch (pkt_type) {
729
+ case ETH_PKT_BCAST:
730
+ if (emc->regs[REG_CAMCMR] & REG_CAMCMR_CCAM) {
731
+ return true;
732
+ } else {
733
+ *fail_reason = "Broadcast packet disabled";
734
+ return !!(emc->regs[REG_CAMCMR] & REG_CAMCMR_ABP);
735
+ }
736
+ case ETH_PKT_MCAST:
737
+ if (emc->regs[REG_CAMCMR] & REG_CAMCMR_CCAM) {
738
+ return true;
739
+ } else {
740
+ *fail_reason = "Multicast packet disabled";
741
+ return !!(emc->regs[REG_CAMCMR] & REG_CAMCMR_AMP);
742
+ }
743
+ case ETH_PKT_UCAST: {
744
+ bool matches;
745
+ if (emc->regs[REG_CAMCMR] & REG_CAMCMR_AUP) {
746
+ return true;
747
+ }
748
+ matches = ((emc->regs[REG_CAMCMR] & REG_CAMCMR_ECMP) &&
749
+ /* We only support one CAM register, CAM0. */
750
+ (emc->regs[REG_CAMEN] & (1 << 0)) &&
751
+ memcmp(buf, emc->conf.macaddr.a, ETH_ALEN) == 0);
752
+ if (emc->regs[REG_CAMCMR] & REG_CAMCMR_CCAM) {
753
+ *fail_reason = "MACADDR matched, comparison complemented";
754
+ return !matches;
755
+ } else {
756
+ *fail_reason = "MACADDR didn't match";
757
+ return matches;
758
+ }
759
+ }
760
+ default:
761
+ g_assert_not_reached();
762
+ }
763
+}
764
+
765
+static bool emc_receive_filter(NPCM7xxEMCState *emc, const uint8_t *buf,
766
+ size_t len)
767
+{
768
+ const char *fail_reason = NULL;
769
+ bool ok = emc_receive_filter1(emc, buf, len, &fail_reason);
770
+ if (!ok) {
771
+ trace_npcm7xx_emc_packet_filtered_out(fail_reason);
772
+ }
773
+ return ok;
774
+}
775
+
776
+static ssize_t emc_receive(NetClientState *nc, const uint8_t *buf, size_t len1)
777
+{
778
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(qemu_get_nic_opaque(nc));
779
+ const uint32_t len = len1;
780
+ size_t max_frame_len;
781
+ bool long_frame;
782
+ uint32_t desc_addr;
783
+ NPCM7xxEMCRxDesc rx_desc;
784
+ uint32_t crc;
785
+ uint8_t *crc_ptr;
786
+ uint32_t buf_addr;
787
+
788
+ trace_npcm7xx_emc_receiving_packet(len);
789
+
790
+ if (!emc_can_receive(nc)) {
791
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Unexpected packet\n", __func__);
792
+ return -1;
793
+ }
794
+
795
+ if (len < ETH_HLEN ||
796
+ /* Defensive programming: drop unsupportable large packets. */
797
+ len > 0xffff - CRC_LENGTH) {
798
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Dropped frame of %u bytes\n",
799
+ __func__, len);
800
+ return len;
801
+ }
802
+
803
+ /*
804
+ * DENI is set if EMC received the Length/Type field of the incoming
805
+ * packet, so it will be set regardless of what happens next.
806
+ */
807
+ emc_set_mista(emc, REG_MISTA_DENI);
808
+
809
+ if (!emc_receive_filter(emc, buf, len)) {
810
+ emc_update_rx_irq(emc);
811
+ return len;
812
+ }
813
+
814
+ /* Huge frames (> DMARFC) are dropped. */
815
+ max_frame_len = REG_DMARFC_RXMS(emc->regs[REG_DMARFC]);
816
+ if (len + CRC_LENGTH > max_frame_len) {
817
+ trace_npcm7xx_emc_packet_dropped(len);
818
+ emc_set_mista(emc, REG_MISTA_DFOI);
819
+ emc_update_rx_irq(emc);
820
+ return len;
821
+ }
822
+
823
+ /*
824
+ * Long Frames (> MAX_ETH_FRAME_SIZE) are also dropped, unless MCMDR.ALP
825
+ * is set.
826
+ */
827
+ long_frame = false;
828
+ if (len + CRC_LENGTH > MAX_ETH_FRAME_SIZE) {
829
+ if (emc->regs[REG_MCMDR] & REG_MCMDR_ALP) {
830
+ long_frame = true;
831
+ } else {
832
+ trace_npcm7xx_emc_packet_dropped(len);
833
+ emc_set_mista(emc, REG_MISTA_PTLE);
834
+ emc_update_rx_irq(emc);
835
+ return len;
836
+ }
837
+ }
838
+
839
+ desc_addr = RX_DESC_NRXDSA(emc->regs[REG_CRXDSA]);
840
+ if (emc_read_rx_desc(desc_addr, &rx_desc)) {
841
+ /* Error reading descriptor, already reported. */
842
+ emc_halt_rx(emc, REG_MISTA_RXBERR);
843
+ emc_update_rx_irq(emc);
844
+ return len;
845
+ }
846
+
847
+ /* Nothing we can do if we don't own the descriptor. */
848
+ if (!(rx_desc.status_and_length & RX_DESC_STATUS_OWNER_MASK)) {
849
+ trace_npcm7xx_emc_cpu_owned_desc(desc_addr);
850
+ emc_halt_rx(emc, REG_MISTA_RDU);
851
+ emc_update_rx_irq(emc);
852
+ return len;
853
+ }
854
+
855
+ crc = 0;
856
+ crc_ptr = (uint8_t *) &crc;
857
+ if (!(emc->regs[REG_MCMDR] & REG_MCMDR_SPCRC)) {
858
+ crc = cpu_to_be32(crc32(~0, buf, len));
859
+ }
860
+
861
+ /* Give the descriptor back regardless of what happens. */
862
+ rx_desc.status_and_length &= ~RX_DESC_STATUS_OWNER_MASK;
863
+
864
+ buf_addr = rx_desc.rxbsa;
865
+ emc->regs[REG_CRXBSA] = buf_addr;
866
+ if (dma_memory_write(&address_space_memory, buf_addr, buf, len) ||
867
+ (!(emc->regs[REG_MCMDR] & REG_MCMDR_SPCRC) &&
868
+ dma_memory_write(&address_space_memory, buf_addr + len, crc_ptr,
869
+ 4))) {
870
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bus error writing packet\n",
871
+ __func__);
872
+ emc_set_mista(emc, REG_MISTA_RXBERR);
873
+ emc_set_next_rx_descriptor(emc, &rx_desc, desc_addr);
874
+ emc_update_rx_irq(emc);
875
+ trace_npcm7xx_emc_rx_done(emc->regs[REG_CRXDSA]);
876
+ return len;
877
+ }
878
+
879
+ trace_npcm7xx_emc_received_packet(len);
880
+
881
+ /* Note: We've already verified len+4 <= 0xffff. */
882
+ rx_desc.status_and_length = len;
883
+ if (!(emc->regs[REG_MCMDR] & REG_MCMDR_SPCRC)) {
884
+ rx_desc.status_and_length += 4;
885
+ }
886
+ rx_desc.status_and_length |= RX_DESC_STATUS_RXGD;
887
+ emc_set_mista(emc, REG_MISTA_RXGD);
888
+
889
+ if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & REG_MISTA_RXINTR) {
890
+ rx_desc.status_and_length |= RX_DESC_STATUS_RXINTR;
891
+ }
892
+ if (long_frame) {
893
+ rx_desc.status_and_length |= RX_DESC_STATUS_PTLE;
894
+ }
895
+
896
+ emc_set_next_rx_descriptor(emc, &rx_desc, desc_addr);
897
+ emc_update_rx_irq(emc);
898
+ trace_npcm7xx_emc_rx_done(emc->regs[REG_CRXDSA]);
899
+ return len;
900
+}
901
+
902
+static void emc_try_receive_next_packet(NPCM7xxEMCState *emc)
903
+{
904
+ if (emc_can_receive(qemu_get_queue(emc->nic))) {
905
+ qemu_flush_queued_packets(qemu_get_queue(emc->nic));
906
+ }
907
+}
908
+
909
+static uint64_t npcm7xx_emc_read(void *opaque, hwaddr offset, unsigned size)
910
+{
911
+ NPCM7xxEMCState *emc = opaque;
912
+ uint32_t reg = offset / sizeof(uint32_t);
913
+ uint32_t result;
914
+
915
+ if (reg >= NPCM7XX_NUM_EMC_REGS) {
916
+ qemu_log_mask(LOG_GUEST_ERROR,
917
+ "%s: Invalid offset 0x%04" HWADDR_PRIx "\n",
918
+ __func__, offset);
919
+ return 0;
920
+ }
921
+
922
+ switch (reg) {
923
+ case REG_MIID:
924
+ /*
925
+ * We don't implement MII. For determinism, always return zero as
926
+ * writes record the last value written for debugging purposes.
927
+ */
928
+ qemu_log_mask(LOG_UNIMP, "%s: Read of MIID, returning 0\n", __func__);
929
+ result = 0;
930
+ break;
931
+ case REG_TSDR:
932
+ case REG_RSDR:
933
+ qemu_log_mask(LOG_GUEST_ERROR,
934
+ "%s: Read of write-only reg, %s/%d\n",
935
+ __func__, emc_reg_name(reg), reg);
936
+ return 0;
937
+ default:
938
+ result = emc->regs[reg];
939
+ break;
940
+ }
941
+
942
+ trace_npcm7xx_emc_reg_read(emc->emc_num, result, emc_reg_name(reg), reg);
943
+ return result;
944
+}
945
+
946
+static void npcm7xx_emc_write(void *opaque, hwaddr offset,
947
+ uint64_t v, unsigned size)
948
+{
949
+ NPCM7xxEMCState *emc = opaque;
950
+ uint32_t reg = offset / sizeof(uint32_t);
951
+ uint32_t value = v;
952
+
953
+ g_assert(size == sizeof(uint32_t));
954
+
955
+ if (reg >= NPCM7XX_NUM_EMC_REGS) {
956
+ qemu_log_mask(LOG_GUEST_ERROR,
957
+ "%s: Invalid offset 0x%04" HWADDR_PRIx "\n",
958
+ __func__, offset);
959
+ return;
960
+ }
961
+
962
+ trace_npcm7xx_emc_reg_write(emc->emc_num, emc_reg_name(reg), reg, value);
963
+
964
+ switch (reg) {
965
+ case REG_CAMCMR:
966
+ emc->regs[reg] = value;
967
+ break;
968
+ case REG_CAMEN:
969
+ /* Only CAM0 is supported, don't pretend otherwise. */
970
+ if (value & ~1) {
971
+ qemu_log_mask(LOG_GUEST_ERROR,
972
+ "%s: Only CAM0 is supported, cannot enable others"
973
+ ": 0x%x\n",
974
+ __func__, value);
975
+ }
976
+ emc->regs[reg] = value & 1;
977
+ break;
978
+ case REG_CAMM_BASE + 0:
979
+ emc->regs[reg] = value;
980
+ emc->conf.macaddr.a[0] = value >> 24;
981
+ emc->conf.macaddr.a[1] = value >> 16;
982
+ emc->conf.macaddr.a[2] = value >> 8;
983
+ emc->conf.macaddr.a[3] = value >> 0;
984
+ break;
985
+ case REG_CAML_BASE + 0:
986
+ emc->regs[reg] = value;
987
+ emc->conf.macaddr.a[4] = value >> 24;
988
+ emc->conf.macaddr.a[5] = value >> 16;
989
+ break;
990
+ case REG_MCMDR: {
991
+ uint32_t prev;
992
+ if (value & REG_MCMDR_SWR) {
993
+ emc_soft_reset(emc);
994
+ /* On h/w the reset happens over multiple cycles. For now KISS. */
995
+ break;
996
+ }
997
+ prev = emc->regs[reg];
998
+ emc->regs[reg] = value;
999
+ /* Update tx state. */
1000
+ if (!(prev & REG_MCMDR_TXON) &&
1001
+ (value & REG_MCMDR_TXON)) {
1002
+ emc->regs[REG_CTXDSA] = emc->regs[REG_TXDLSA];
1003
+ /*
1004
+ * Linux kernel turns TX on with CPU still holding descriptor,
1005
+ * which suggests we should wait for a write to TSDR before trying
1006
+ * to send a packet: so we don't send one here.
1007
+ */
1008
+ } else if ((prev & REG_MCMDR_TXON) &&
1009
+ !(value & REG_MCMDR_TXON)) {
1010
+ emc->regs[REG_MGSTA] |= REG_MGSTA_TXHA;
1011
+ }
1012
+ if (!(value & REG_MCMDR_TXON)) {
1013
+ emc_halt_tx(emc, 0);
1014
+ }
1015
+ /* Update rx state. */
1016
+ if (!(prev & REG_MCMDR_RXON) &&
1017
+ (value & REG_MCMDR_RXON)) {
1018
+ emc->regs[REG_CRXDSA] = emc->regs[REG_RXDLSA];
1019
+ } else if ((prev & REG_MCMDR_RXON) &&
1020
+ !(value & REG_MCMDR_RXON)) {
1021
+ emc->regs[REG_MGSTA] |= REG_MGSTA_RXHA;
1022
+ }
1023
+ if (!(value & REG_MCMDR_RXON)) {
1024
+ emc_halt_rx(emc, 0);
1025
+ }
1026
+ break;
1027
+ }
1028
+ case REG_TXDLSA:
1029
+ case REG_RXDLSA:
1030
+ case REG_DMARFC:
1031
+ case REG_MIID:
1032
+ emc->regs[reg] = value;
1033
+ break;
1034
+ case REG_MIEN:
1035
+ emc->regs[reg] = value;
1036
+ emc_update_irq_from_reg_change(emc);
1037
+ break;
1038
+ case REG_MISTA:
1039
+ /* Clear the bits that have 1 in "value". */
1040
+ emc->regs[reg] &= ~value;
1041
+ emc_update_irq_from_reg_change(emc);
1042
+ break;
1043
+ case REG_MGSTA:
1044
+ /* Clear the bits that have 1 in "value". */
1045
+ emc->regs[reg] &= ~value;
1046
+ break;
1047
+ case REG_TSDR:
1048
+ if (emc->regs[REG_MCMDR] & REG_MCMDR_TXON) {
1049
+ emc->tx_active = true;
1050
+ /* Keep trying to send packets until we run out. */
1051
+ while (emc->tx_active) {
1052
+ emc_try_send_next_packet(emc);
1053
+ }
1054
+ }
1055
+ break;
1056
+ case REG_RSDR:
1057
+ if (emc->regs[REG_MCMDR] & REG_MCMDR_RXON) {
1058
+ emc->rx_active = true;
1059
+ emc_try_receive_next_packet(emc);
1060
+ }
1061
+ break;
1062
+ case REG_MIIDA:
1063
+ emc->regs[reg] = value & ~REG_MIIDA_BUSY;
1064
+ break;
1065
+ case REG_MRPC:
1066
+ case REG_MRPCC:
1067
+ case REG_MREPC:
1068
+ case REG_CTXDSA:
1069
+ case REG_CTXBSA:
1070
+ case REG_CRXDSA:
1071
+ case REG_CRXBSA:
1072
+ qemu_log_mask(LOG_GUEST_ERROR,
1073
+ "%s: Write to read-only reg %s/%d\n",
1074
+ __func__, emc_reg_name(reg), reg);
1075
+ break;
1076
+ default:
1077
+ qemu_log_mask(LOG_UNIMP, "%s: Write to unimplemented reg %s/%d\n",
1078
+ __func__, emc_reg_name(reg), reg);
1079
+ break;
1080
+ }
1081
+}
1082
+
1083
+static const struct MemoryRegionOps npcm7xx_emc_ops = {
1084
+ .read = npcm7xx_emc_read,
1085
+ .write = npcm7xx_emc_write,
1086
+ .endianness = DEVICE_LITTLE_ENDIAN,
566
+ .endianness = DEVICE_LITTLE_ENDIAN,
1087
+ .valid = {
567
+ .valid = {
1088
+ .min_access_size = 4,
568
+ .min_access_size = 1,
1089
+ .max_access_size = 4,
569
+ .max_access_size = 2,
1090
+ .unaligned = false,
570
+ .unaligned = false,
571
+ .accepts = npcm7xx_mft_check_mem_op,
1091
+ },
572
+ },
1092
+};
573
+};
1093
+
574
+
1094
+static void emc_cleanup(NetClientState *nc)
575
+static void npcm7xx_mft_enter_reset(Object *obj, ResetType type)
1095
+{
576
+{
1096
+ /* Nothing to do yet. */
577
+ NPCM7xxMFTState *s = NPCM7XX_MFT(obj);
1097
+}
578
+
1098
+
579
+ npcm7xx_mft_reset(s);
1099
+static NetClientInfo net_npcm7xx_emc_info = {
580
+}
1100
+ .type = NET_CLIENT_DRIVER_NIC,
581
+
1101
+ .size = sizeof(NICState),
582
+static void npcm7xx_mft_hold_reset(Object *obj)
1102
+ .can_receive = emc_can_receive,
583
+{
1103
+ .receive = emc_receive,
584
+ NPCM7xxMFTState *s = NPCM7XX_MFT(obj);
1104
+ .cleanup = emc_cleanup,
585
+
1105
+ .link_status_changed = emc_set_link,
586
+ qemu_irq_lower(s->irq);
1106
+};
587
+}
1107
+
588
+
1108
+static void npcm7xx_emc_realize(DeviceState *dev, Error **errp)
589
+static void npcm7xx_mft_init(Object *obj)
1109
+{
590
+{
1110
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(dev);
591
+ NPCM7xxMFTState *s = NPCM7XX_MFT(obj);
1111
+ SysBusDevice *sbd = SYS_BUS_DEVICE(emc);
592
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1112
+
593
+ DeviceState *dev = DEVICE(obj);
1113
+ memory_region_init_io(&emc->iomem, OBJECT(emc), &npcm7xx_emc_ops, emc,
594
+
1114
+ TYPE_NPCM7XX_EMC, 4 * KiB);
595
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_mft_ops, s,
1115
+ sysbus_init_mmio(sbd, &emc->iomem);
596
+ TYPE_NPCM7XX_MFT, 4 * KiB);
1116
+ sysbus_init_irq(sbd, &emc->tx_irq);
597
+ sysbus_init_mmio(sbd, &s->iomem);
1117
+ sysbus_init_irq(sbd, &emc->rx_irq);
598
+ sysbus_init_irq(sbd, &s->irq);
1118
+
599
+ s->clock_in = qdev_init_clock_in(dev, "clock-in", npcm7xx_mft_update_clock,
1119
+ qemu_macaddr_default_if_unset(&emc->conf.macaddr);
600
+ s, ClockUpdate);
1120
+ emc->nic = qemu_new_nic(&net_npcm7xx_emc_info, &emc->conf,
601
+ s->clock_1 = qdev_init_clock_out(dev, "clock1");
1121
+ object_get_typename(OBJECT(dev)), dev->id, emc);
602
+ s->clock_2 = qdev_init_clock_out(dev, "clock2");
1122
+ qemu_format_nic_info_str(qemu_get_queue(emc->nic), emc->conf.macaddr.a);
603
+
1123
+}
604
+ for (int i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
1124
+
605
+ object_property_add(obj, "max_rpm[*]", "uint32",
1125
+static void npcm7xx_emc_unrealize(DeviceState *dev)
606
+ npcm7xx_mft_get_max_rpm,
1126
+{
607
+ npcm7xx_mft_set_max_rpm,
1127
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(dev);
608
+ NULL, &s->max_rpm[i]);
1128
+
609
+ }
1129
+ qemu_del_nic(emc->nic);
610
+ qdev_init_gpio_in_named(dev, npcm7xx_mft_duty_handler, "duty",
1130
+}
611
+ NPCM7XX_MFT_FANIN_COUNT);
1131
+
612
+}
1132
+static const VMStateDescription vmstate_npcm7xx_emc = {
613
+
1133
+ .name = TYPE_NPCM7XX_EMC,
614
+static const VMStateDescription vmstate_npcm7xx_mft = {
615
+ .name = "npcm7xx-mft-module",
1134
+ .version_id = 0,
616
+ .version_id = 0,
1135
+ .minimum_version_id = 0,
617
+ .minimum_version_id = 0,
1136
+ .fields = (VMStateField[]) {
618
+ .fields = (VMStateField[]) {
1137
+ VMSTATE_UINT8(emc_num, NPCM7xxEMCState),
619
+ VMSTATE_CLOCK(clock_in, NPCM7xxMFTState),
1138
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxEMCState, NPCM7XX_NUM_EMC_REGS),
620
+ VMSTATE_CLOCK(clock_1, NPCM7xxMFTState),
1139
+ VMSTATE_BOOL(tx_active, NPCM7xxEMCState),
621
+ VMSTATE_CLOCK(clock_2, NPCM7xxMFTState),
1140
+ VMSTATE_BOOL(rx_active, NPCM7xxEMCState),
622
+ VMSTATE_UINT16_ARRAY(regs, NPCM7xxMFTState, NPCM7XX_MFT_NR_REGS),
623
+ VMSTATE_UINT32_ARRAY(max_rpm, NPCM7xxMFTState, NPCM7XX_MFT_FANIN_COUNT),
624
+ VMSTATE_UINT32_ARRAY(duty, NPCM7xxMFTState, NPCM7XX_MFT_FANIN_COUNT),
1141
+ VMSTATE_END_OF_LIST(),
625
+ VMSTATE_END_OF_LIST(),
1142
+ },
626
+ },
1143
+};
627
+};
1144
+
628
+
1145
+static Property npcm7xx_emc_properties[] = {
629
+static void npcm7xx_mft_class_init(ObjectClass *klass, void *data)
1146
+ DEFINE_NIC_PROPERTIES(NPCM7xxEMCState, conf),
630
+{
1147
+ DEFINE_PROP_END_OF_LIST(),
631
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
632
+ DeviceClass *dc = DEVICE_CLASS(klass);
633
+
634
+ dc->desc = "NPCM7xx MFT Controller";
635
+ dc->vmsd = &vmstate_npcm7xx_mft;
636
+ rc->phases.enter = npcm7xx_mft_enter_reset;
637
+ rc->phases.hold = npcm7xx_mft_hold_reset;
638
+}
639
+
640
+static const TypeInfo npcm7xx_mft_info = {
641
+ .name = TYPE_NPCM7XX_MFT,
642
+ .parent = TYPE_SYS_BUS_DEVICE,
643
+ .instance_size = sizeof(NPCM7xxMFTState),
644
+ .class_init = npcm7xx_mft_class_init,
645
+ .instance_init = npcm7xx_mft_init,
1148
+};
646
+};
1149
+
647
+
1150
+static void npcm7xx_emc_class_init(ObjectClass *klass, void *data)
648
+static void npcm7xx_mft_register_type(void)
1151
+{
649
+{
1152
+ DeviceClass *dc = DEVICE_CLASS(klass);
650
+ type_register_static(&npcm7xx_mft_info);
1153
+
651
+}
1154
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
652
+type_init(npcm7xx_mft_register_type);
1155
+ dc->desc = "NPCM7xx EMC Controller";
653
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
1156
+ dc->realize = npcm7xx_emc_realize;
1157
+ dc->unrealize = npcm7xx_emc_unrealize;
1158
+ dc->reset = npcm7xx_emc_reset;
1159
+ dc->vmsd = &vmstate_npcm7xx_emc;
1160
+ device_class_set_props(dc, npcm7xx_emc_properties);
1161
+}
1162
+
1163
+static const TypeInfo npcm7xx_emc_info = {
1164
+ .name = TYPE_NPCM7XX_EMC,
1165
+ .parent = TYPE_SYS_BUS_DEVICE,
1166
+ .instance_size = sizeof(NPCM7xxEMCState),
1167
+ .class_init = npcm7xx_emc_class_init,
1168
+};
1169
+
1170
+static void npcm7xx_emc_register_type(void)
1171
+{
1172
+ type_register_static(&npcm7xx_emc_info);
1173
+}
1174
+
1175
+type_init(npcm7xx_emc_register_type)
1176
diff --git a/hw/net/meson.build b/hw/net/meson.build
1177
index XXXXXXX..XXXXXXX 100644
654
index XXXXXXX..XXXXXXX 100644
1178
--- a/hw/net/meson.build
655
--- a/hw/misc/meson.build
1179
+++ b/hw/net/meson.build
656
+++ b/hw/misc/meson.build
1180
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_I82596_COMMON', if_true: files('i82596.c'))
657
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
1181
softmmu_ss.add(when: 'CONFIG_SUNHME', if_true: files('sunhme.c'))
658
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
1182
softmmu_ss.add(when: 'CONFIG_FTGMAC100', if_true: files('ftgmac100.c'))
659
'npcm7xx_clk.c',
1183
softmmu_ss.add(when: 'CONFIG_SUNGEM', if_true: files('sungem.c'))
660
'npcm7xx_gcr.c',
1184
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_emc.c'))
661
+ 'npcm7xx_mft.c',
1185
662
'npcm7xx_pwm.c',
1186
softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_eth.c'))
663
'npcm7xx_rng.c',
1187
softmmu_ss.add(when: 'CONFIG_COLDFIRE', if_true: files('mcf_fec.c'))
664
))
1188
diff --git a/hw/net/trace-events b/hw/net/trace-events
665
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
1189
index XXXXXXX..XXXXXXX 100644
666
index XXXXXXX..XXXXXXX 100644
1190
--- a/hw/net/trace-events
667
--- a/hw/misc/trace-events
1191
+++ b/hw/net/trace-events
668
+++ b/hw/misc/trace-events
1192
@@ -XXX,XX +XXX,XX @@ imx_fec_receive_last(int last) "rx frame flags 0x%04x"
669
@@ -XXX,XX +XXX,XX @@ npcm7xx_clk_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " valu
1193
imx_enet_receive(size_t size) "len %zu"
670
npcm7xx_gcr_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
1194
imx_enet_receive_len(uint64_t addr, int len) "rx_bd 0x%"PRIx64" length %d"
671
npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
1195
imx_enet_receive_last(int last) "rx frame flags 0x%04x"
672
1196
+
673
+# npcm7xx_mft.c
1197
+# npcm7xx_emc.c
674
+npcm7xx_mft_read(const char *name, uint64_t offset, uint16_t value) "%s: offset: 0x%04" PRIx64 " value: 0x%04" PRIx16
1198
+npcm7xx_emc_reset(int emc_num) "Resetting emc%d"
675
+npcm7xx_mft_write(const char *name, uint64_t offset, uint16_t value) "%s: offset: 0x%04" PRIx64 " value: 0x%04" PRIx16
1199
+npcm7xx_emc_update_tx_irq(int level) "Setting tx irq to %d"
676
+npcm7xx_mft_rpm(const char *clock, uint32_t clock_hz, int state, int32_t cnt, uint32_t rpm, uint32_t duty) " fan clk: %s clock_hz: %" PRIu32 ", state: %d, cnt: %" PRIi32 ", rpm: %" PRIu32 ", duty: %" PRIu32
1200
+npcm7xx_emc_update_rx_irq(int level) "Setting rx irq to %d"
677
+npcm7xx_mft_capture(const char *name, int irq_level) "%s: level: %d"
1201
+npcm7xx_emc_set_mista(uint32_t flags) "ORing 0x%x into MISTA"
678
+npcm7xx_mft_update_clock(const char *name, uint16_t sel, uint64_t clock_period, uint64_t prescaled_clock_period) "%s: sel: 0x%02" PRIx16 ", period: %" PRIu64 ", prescaled: %" PRIu64
1202
+npcm7xx_emc_cpu_owned_desc(uint32_t addr) "Can't process cpu-owned descriptor @0x%x"
679
+npcm7xx_mft_set_duty(const char *name, int n, int value) "%s[%d]: %d"
1203
+npcm7xx_emc_sent_packet(uint32_t len) "Sent %u byte packet"
680
+
1204
+npcm7xx_emc_tx_done(uint32_t ctxdsa) "TX done, CTXDSA=0x%x"
681
# npcm7xx_rng.c
1205
+npcm7xx_emc_can_receive(int can_receive) "Can receive: %d"
682
npcm7xx_rng_read(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
1206
+npcm7xx_emc_packet_filtered_out(const char* fail_reason) "Packet filtered out: %s"
683
npcm7xx_rng_write(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
1207
+npcm7xx_emc_packet_dropped(uint32_t len) "%u byte packet dropped"
1208
+npcm7xx_emc_receiving_packet(uint32_t len) "Receiving %u byte packet"
1209
+npcm7xx_emc_received_packet(uint32_t len) "Received %u byte packet"
1210
+npcm7xx_emc_rx_done(uint32_t crxdsa) "RX done, CRXDSA=0x%x"
1211
+npcm7xx_emc_reg_read(int emc_num, uint32_t result, const char *name, int regno) "emc%d: 0x%x = reg[%s/%d]"
1212
+npcm7xx_emc_reg_write(int emc_num, const char *name, int regno, uint32_t value) "emc%d: reg[%s/%d] = 0x%x"
1213
--
684
--
1214
2.20.1
685
2.20.1
1215
686
1216
687
diff view generated by jsdifflib
1
From: Doug Evans <dje@google.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
This is a 10/100 ethernet device that has several features.
3
This patch adds the recently implemented MFT device to the NPCM7XX
4
Only the ones needed by the Linux driver have been implemented.
4
SoC file.
5
See npcm7xx_emc.c for a list of unimplemented features.
6
5
7
Reviewed-by: Hao Wu <wuhaotsh@google.com>
6
Reviewed-by: Doug Evans <dje@google.com>
8
Reviewed-by: Avi Fishman <avi.fishman@nuvoton.com>
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
8
Signed-off-by: Hao Wu <wuhaotsh@google.com>
9
Message-id: 20210311180855.149764-4-wuhaotsh@google.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Doug Evans <dje@google.com>
11
Message-id: 20210218212453.831406-3-dje@google.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
12
---
14
docs/system/arm/nuvoton.rst | 3 ++-
13
docs/system/arm/nuvoton.rst | 2 +-
15
include/hw/arm/npcm7xx.h | 2 ++
14
include/hw/arm/npcm7xx.h | 2 ++
16
hw/arm/npcm7xx.c | 50 +++++++++++++++++++++++++++++++++++--
15
hw/arm/npcm7xx.c | 45 ++++++++++++++++++++++++++++++-------
17
3 files changed, 52 insertions(+), 3 deletions(-)
16
3 files changed, 40 insertions(+), 9 deletions(-)
18
17
19
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
18
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
20
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
21
--- a/docs/system/arm/nuvoton.rst
20
--- a/docs/system/arm/nuvoton.rst
22
+++ b/docs/system/arm/nuvoton.rst
21
+++ b/docs/system/arm/nuvoton.rst
23
@@ -XXX,XX +XXX,XX @@ Supported devices
22
@@ -XXX,XX +XXX,XX @@ Supported devices
24
* Analog to Digital Converter (ADC)
25
* Pulse Width Modulation (PWM)
23
* Pulse Width Modulation (PWM)
26
* SMBus controller (SMBF)
24
* SMBus controller (SMBF)
27
+ * Ethernet controller (EMC)
25
* Ethernet controller (EMC)
26
+ * Tachometer
28
27
29
Missing devices
28
Missing devices
30
---------------
29
---------------
31
@@ -XXX,XX +XXX,XX @@ Missing devices
30
@@ -XXX,XX +XXX,XX @@ Missing devices
32
* Shared memory (SHM)
33
* eSPI slave interface
34
35
- * Ethernet controllers (GMAC and EMC)
36
+ * Ethernet controller (GMAC)
37
* USB device (USBD)
38
* Peripheral SPI controller (PSPI)
31
* Peripheral SPI controller (PSPI)
39
* SD/MMC host
32
* SD/MMC host
33
* PECI interface
34
- * Tachometer
35
* PCI and PCIe root complex and bridges
36
* VDM and MCTP support
37
* Serial I/O expansion
40
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
38
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
41
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
42
--- a/include/hw/arm/npcm7xx.h
40
--- a/include/hw/arm/npcm7xx.h
43
+++ b/include/hw/arm/npcm7xx.h
41
+++ b/include/hw/arm/npcm7xx.h
44
@@ -XXX,XX +XXX,XX @@
42
@@ -XXX,XX +XXX,XX @@
43
#include "hw/mem/npcm7xx_mc.h"
44
#include "hw/misc/npcm7xx_clk.h"
45
#include "hw/misc/npcm7xx_gcr.h"
45
#include "hw/misc/npcm7xx_gcr.h"
46
+#include "hw/misc/npcm7xx_mft.h"
46
#include "hw/misc/npcm7xx_pwm.h"
47
#include "hw/misc/npcm7xx_pwm.h"
47
#include "hw/misc/npcm7xx_rng.h"
48
#include "hw/misc/npcm7xx_rng.h"
48
+#include "hw/net/npcm7xx_emc.h"
49
#include "hw/net/npcm7xx_emc.h"
49
#include "hw/nvram/npcm7xx_otp.h"
50
#include "hw/timer/npcm7xx_timer.h"
51
#include "hw/ssi/npcm7xx_fiu.h"
52
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
50
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
53
EHCISysBusState ehci;
51
NPCM7xxTimerCtrlState tim[3];
54
OHCISysBusState ohci;
52
NPCM7xxADCState adc;
55
NPCM7xxFIUState fiu[2];
53
NPCM7xxPWMState pwm[2];
56
+ NPCM7xxEMCState emc[2];
54
+ NPCM7xxMFTState mft[8];
57
} NPCM7xxState;
55
NPCM7xxOTPState key_storage;
58
56
NPCM7xxOTPState fuse_array;
59
#define TYPE_NPCM7XX "npcm7xx"
57
NPCM7xxMCState mc;
60
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
58
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
61
index XXXXXXX..XXXXXXX 100644
59
index XXXXXXX..XXXXXXX 100644
62
--- a/hw/arm/npcm7xx.c
60
--- a/hw/arm/npcm7xx.c
63
+++ b/hw/arm/npcm7xx.c
61
+++ b/hw/arm/npcm7xx.c
64
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
62
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
65
NPCM7XX_UART1_IRQ,
66
NPCM7XX_UART2_IRQ,
67
NPCM7XX_UART3_IRQ,
68
+ NPCM7XX_EMC1RX_IRQ = 15,
69
+ NPCM7XX_EMC1TX_IRQ,
70
NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */
71
NPCM7XX_TIMER1_IRQ,
72
NPCM7XX_TIMER2_IRQ,
73
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
74
NPCM7XX_SMBUS15_IRQ,
63
NPCM7XX_SMBUS15_IRQ,
75
NPCM7XX_PWM0_IRQ = 93, /* PWM module 0 */
64
NPCM7XX_PWM0_IRQ = 93, /* PWM module 0 */
76
NPCM7XX_PWM1_IRQ, /* PWM module 1 */
65
NPCM7XX_PWM1_IRQ, /* PWM module 1 */
77
+ NPCM7XX_EMC2RX_IRQ = 114,
66
+ NPCM7XX_MFT0_IRQ = 96, /* MFT module 0 */
78
+ NPCM7XX_EMC2TX_IRQ,
67
+ NPCM7XX_MFT1_IRQ, /* MFT module 1 */
68
+ NPCM7XX_MFT2_IRQ, /* MFT module 2 */
69
+ NPCM7XX_MFT3_IRQ, /* MFT module 3 */
70
+ NPCM7XX_MFT4_IRQ, /* MFT module 4 */
71
+ NPCM7XX_MFT5_IRQ, /* MFT module 5 */
72
+ NPCM7XX_MFT6_IRQ, /* MFT module 6 */
73
+ NPCM7XX_MFT7_IRQ, /* MFT module 7 */
74
NPCM7XX_EMC2RX_IRQ = 114,
75
NPCM7XX_EMC2TX_IRQ,
79
NPCM7XX_GPIO0_IRQ = 116,
76
NPCM7XX_GPIO0_IRQ = 116,
80
NPCM7XX_GPIO1_IRQ,
77
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_pwm_addr[] = {
81
NPCM7XX_GPIO2_IRQ,
78
0xf0104000,
82
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_smbus_addr[] = {
83
0xf008f000,
84
};
79
};
85
80
86
+/* Register base address for each EMC Module */
81
+/* Register base address for each MFT Module */
87
+static const hwaddr npcm7xx_emc_addr[] = {
82
+static const hwaddr npcm7xx_mft_addr[] = {
88
+ 0xf0825000,
83
+ 0xf0180000,
89
+ 0xf0826000,
84
+ 0xf0181000,
85
+ 0xf0182000,
86
+ 0xf0183000,
87
+ 0xf0184000,
88
+ 0xf0185000,
89
+ 0xf0186000,
90
+ 0xf0187000,
90
+};
91
+};
91
+
92
+
92
static const struct {
93
/* Direct memory-mapped access to each SMBus Module. */
93
hwaddr regs_addr;
94
static const hwaddr npcm7xx_smbus_addr[] = {
94
uint32_t unconnected_pins;
95
0xf0080000,
95
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
96
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
96
for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
97
object_initialize_child(obj, "pwm[*]", &s->pwm[i], TYPE_NPCM7XX_PWM);
97
object_initialize_child(obj, "pwm[*]", &s->pwm[i], TYPE_NPCM7XX_PWM);
98
}
98
}
99
100
+ for (i = 0; i < ARRAY_SIZE(s->mft); i++) {
101
+ object_initialize_child(obj, "mft[*]", &s->mft[i], TYPE_NPCM7XX_MFT);
102
+ }
99
+
103
+
100
+ for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
104
for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
101
+ object_initialize_child(obj, "emc[*]", &s->emc[i], TYPE_NPCM7XX_EMC);
105
object_initialize_child(obj, "emc[*]", &s->emc[i], TYPE_NPCM7XX_EMC);
102
+ }
106
}
103
}
104
105
static void npcm7xx_realize(DeviceState *dev, Error **errp)
106
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
107
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
107
sysbus_connect_irq(sbd, i, npcm7xx_irq(s, NPCM7XX_PWM0_IRQ + i));
108
sysbus_connect_irq(sbd, i, npcm7xx_irq(s, NPCM7XX_PWM0_IRQ + i));
108
}
109
}
109
110
110
+ /*
111
+ /* MFT Modules. Cannot fail. */
111
+ * EMC Modules. Cannot fail.
112
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_mft_addr) != ARRAY_SIZE(s->mft));
112
+ * The mapping of the device to its netdev backend works as follows:
113
+ for (i = 0; i < ARRAY_SIZE(s->mft); i++) {
113
+ * emc[i] = nd_table[i]
114
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->mft[i]);
114
+ * This works around the inability to specify the netdev property for the
115
+
115
+ * emc device: it's not pluggable and thus the -device option can't be
116
+ qdev_connect_clock_in(DEVICE(&s->mft[i]), "clock-in",
116
+ * used.
117
+ qdev_get_clock_out(DEVICE(&s->clk),
117
+ */
118
+ "apb4-clock"));
118
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_emc_addr) != ARRAY_SIZE(s->emc));
119
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(s->emc) != 2);
120
+ for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
121
+ s->emc[i].emc_num = i;
122
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->emc[i]);
123
+ if (nd_table[i].used) {
124
+ qemu_check_nic_model(&nd_table[i], TYPE_NPCM7XX_EMC);
125
+ qdev_set_nic_properties(DEVICE(sbd), &nd_table[i]);
126
+ }
127
+ /*
128
+ * The device exists regardless of whether it's connected to a QEMU
129
+ * netdev backend. So always instantiate it even if there is no
130
+ * backend.
131
+ */
132
+ sysbus_realize(sbd, &error_abort);
119
+ sysbus_realize(sbd, &error_abort);
133
+ sysbus_mmio_map(sbd, 0, npcm7xx_emc_addr[i]);
120
+ sysbus_mmio_map(sbd, 0, npcm7xx_mft_addr[i]);
134
+ int tx_irq = i == 0 ? NPCM7XX_EMC1TX_IRQ : NPCM7XX_EMC2TX_IRQ;
121
+ sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, NPCM7XX_MFT0_IRQ + i));
135
+ int rx_irq = i == 0 ? NPCM7XX_EMC1RX_IRQ : NPCM7XX_EMC2RX_IRQ;
136
+ /*
137
+ * N.B. The values for the second argument sysbus_connect_irq are
138
+ * chosen to match the registration order in npcm7xx_emc_realize.
139
+ */
140
+ sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, tx_irq));
141
+ sysbus_connect_irq(sbd, 1, npcm7xx_irq(s, rx_irq));
142
+ }
122
+ }
143
+
123
+
144
/*
124
/*
145
* Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
125
* EMC Modules. Cannot fail.
146
* specified, but this is a programming error.
126
* The mapping of the device to its netdev backend works as follows:
147
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
127
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
148
create_unimplemented_device("npcm7xx.vcd", 0xf0810000, 64 * KiB);
128
create_unimplemented_device("npcm7xx.peci", 0xf0100000, 4 * KiB);
149
create_unimplemented_device("npcm7xx.ece", 0xf0820000, 8 * KiB);
129
create_unimplemented_device("npcm7xx.siox[1]", 0xf0101000, 4 * KiB);
150
create_unimplemented_device("npcm7xx.vdma", 0xf0822000, 8 * KiB);
130
create_unimplemented_device("npcm7xx.siox[2]", 0xf0102000, 4 * KiB);
151
- create_unimplemented_device("npcm7xx.emc1", 0xf0825000, 4 * KiB);
131
- create_unimplemented_device("npcm7xx.mft[0]", 0xf0180000, 4 * KiB);
152
- create_unimplemented_device("npcm7xx.emc2", 0xf0826000, 4 * KiB);
132
- create_unimplemented_device("npcm7xx.mft[1]", 0xf0181000, 4 * KiB);
153
create_unimplemented_device("npcm7xx.usbd[0]", 0xf0830000, 4 * KiB);
133
- create_unimplemented_device("npcm7xx.mft[2]", 0xf0182000, 4 * KiB);
154
create_unimplemented_device("npcm7xx.usbd[1]", 0xf0831000, 4 * KiB);
134
- create_unimplemented_device("npcm7xx.mft[3]", 0xf0183000, 4 * KiB);
155
create_unimplemented_device("npcm7xx.usbd[2]", 0xf0832000, 4 * KiB);
135
- create_unimplemented_device("npcm7xx.mft[4]", 0xf0184000, 4 * KiB);
136
- create_unimplemented_device("npcm7xx.mft[5]", 0xf0185000, 4 * KiB);
137
- create_unimplemented_device("npcm7xx.mft[6]", 0xf0186000, 4 * KiB);
138
- create_unimplemented_device("npcm7xx.mft[7]", 0xf0187000, 4 * KiB);
139
create_unimplemented_device("npcm7xx.pspi1", 0xf0200000, 4 * KiB);
140
create_unimplemented_device("npcm7xx.pspi2", 0xf0201000, 4 * KiB);
141
create_unimplemented_device("npcm7xx.ahbpci", 0xf0400000, 1 * MiB);
156
--
142
--
157
2.20.1
143
2.20.1
158
144
159
145
diff view generated by jsdifflib
1
The AN505 and AN521 have the same layout of RAM; the AN524 does not.
1
From: Hao Wu <wuhaotsh@google.com>
2
Replace the current hard-coding of where the RAM is and which parts
2
3
of it are behind which MPCs with a data-driven approach.
3
This patch adds fan_splitters (split IRQs) in NPCM7XX boards. Each fan
4
4
splitter corresponds to 1 PWM output and can connect to multiple fan
5
inputs (MFT devices).
6
In NPCM7XX boards(NPCM750 EVB and Quanta GSJ boards), we initializes
7
these splitters and connect them to their corresponding modules
8
according their specific device trees.
9
10
Reviewed-by: Doug Evans <dje@google.com>
11
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
12
Signed-off-by: Hao Wu <wuhaotsh@google.com>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20210311180855.149764-5-wuhaotsh@google.com
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210215115138.20465-17-peter.maydell@linaro.org
8
---
16
---
9
hw/arm/mps2-tz.c | 175 +++++++++++++++++++++++++++++++++++++----------
17
include/hw/arm/npcm7xx.h | 11 ++++-
10
1 file changed, 138 insertions(+), 37 deletions(-)
18
hw/arm/npcm7xx_boards.c | 99 ++++++++++++++++++++++++++++++++++++++++
11
19
2 files changed, 109 insertions(+), 1 deletion(-)
12
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
20
21
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
13
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/mps2-tz.c
23
--- a/include/hw/arm/npcm7xx.h
15
+++ b/hw/arm/mps2-tz.c
24
+++ b/include/hw/arm/npcm7xx.h
16
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@
17
#include "qom/object.h"
26
18
27
#include "hw/boards.h"
19
#define MPS2TZ_NUMIRQ_MAX 92
28
#include "hw/adc/npcm7xx_adc.h"
20
+#define MPS2TZ_RAM_MAX 4
29
+#include "hw/core/split-irq.h"
21
30
#include "hw/cpu/a9mpcore.h"
22
typedef enum MPS2TZFPGAType {
31
#include "hw/gpio/npcm7xx_gpio.h"
23
FPGA_AN505,
32
#include "hw/i2c/npcm7xx_smbus.h"
24
FPGA_AN521,
33
@@ -XXX,XX +XXX,XX @@
25
} MPS2TZFPGAType;
34
#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100) /* GIC within A9 */
26
35
#define NPCM7XX_BOARD_SETUP_ADDR (0xffff1000) /* Boot ROM */
27
+/*
36
28
+ * Define the layout of RAM in a board, including which parts are
37
+#define NPCM7XX_NR_PWM_MODULES 2
29
+ * behind which MPCs.
38
+
30
+ * mrindex specifies the index into mms->ram[] to use for the backing RAM;
39
typedef struct NPCM7xxMachine {
31
+ * -1 means "use the system RAM".
40
MachineState parent;
32
+ */
41
+ /*
33
+typedef struct RAMInfo {
42
+ * PWM fan splitter. each splitter connects to one PWM output and
34
+ const char *name;
43
+ * multiple MFT inputs.
35
+ uint32_t base;
44
+ */
36
+ uint32_t size;
45
+ SplitIRQ fan_splitter[NPCM7XX_NR_PWM_MODULES *
37
+ int mpc; /* MPC number, -1 for "not behind an MPC" */
46
+ NPCM7XX_PWM_PER_MODULE];
38
+ int mrindex;
47
} NPCM7xxMachine;
39
+ int flags;
48
40
+} RAMInfo;
49
#define TYPE_NPCM7XX_MACHINE MACHINE_TYPE_NAME("npcm7xx")
41
+
50
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
42
+/*
51
NPCM7xxCLKState clk;
43
+ * Flag values:
52
NPCM7xxTimerCtrlState tim[3];
44
+ * IS_ALIAS: this RAM area is an alias to the upstream end of the
53
NPCM7xxADCState adc;
45
+ * MPC specified by its .mpc value
54
- NPCM7xxPWMState pwm[2];
46
+ */
55
+ NPCM7xxPWMState pwm[NPCM7XX_NR_PWM_MODULES];
47
+#define IS_ALIAS 1
56
NPCM7xxMFTState mft[8];
48
+
57
NPCM7xxOTPState key_storage;
49
struct MPS2TZMachineClass {
58
NPCM7xxOTPState fuse_array;
50
MachineClass parent;
59
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
51
MPS2TZFPGAType fpga_type;
60
index XXXXXXX..XXXXXXX 100644
52
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
61
--- a/hw/arm/npcm7xx_boards.c
53
uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
62
+++ b/hw/arm/npcm7xx_boards.c
54
bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
63
@@ -XXX,XX +XXX,XX @@
55
int numirq; /* Number of external interrupts */
64
#include "hw/core/cpu.h"
56
+ const RAMInfo *raminfo;
65
#include "hw/i2c/smbus_eeprom.h"
57
const char *armsse_type;
66
#include "hw/loader.h"
58
};
67
+#include "hw/qdev-core.h"
59
68
#include "hw/qdev-properties.h"
60
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
69
#include "qapi/error.h"
61
MachineState parent;
70
#include "qemu-common.h"
62
71
@@ -XXX,XX +XXX,XX @@ static void at24c_eeprom_init(NPCM7xxState *soc, int bus, uint8_t addr,
63
ARMSSE iotkit;
72
i2c_slave_realize_and_unref(i2c_dev, i2c_bus, &error_abort);
64
- MemoryRegion ssram[3];
73
}
65
- MemoryRegion ssram1_m;
74
66
+ MemoryRegion ram[MPS2TZ_RAM_MAX];
75
+static void npcm7xx_init_pwm_splitter(NPCM7xxMachine *machine,
67
MPS2SCC scc;
76
+ NPCM7xxState *soc, const int *fan_counts)
68
MPS2FPGAIO fpgaio;
77
+{
69
TZPPC ppc[5];
78
+ SplitIRQ *splitters = machine->fan_splitter;
70
- TZMPC ssram_mpc[3];
79
+
71
+ TZMPC mpc[3];
80
+ /*
72
PL022State spi[5];
81
+ * PWM 0~3 belong to module 0 output 0~3.
73
ArmSbconI2CState i2c[4];
82
+ * PWM 4~7 belong to module 1 output 0~3.
74
UnimplementedDeviceState i2s_audio;
83
+ */
75
@@ -XXX,XX +XXX,XX @@ static const uint32_t an505_oscclk[] = {
84
+ for (int i = 0; i < NPCM7XX_NR_PWM_MODULES; ++i) {
76
25000000,
85
+ for (int j = 0; j < NPCM7XX_PWM_PER_MODULE; ++j) {
77
};
86
+ int splitter_no = i * NPCM7XX_PWM_PER_MODULE + j;
78
87
+ DeviceState *splitter;
79
+static const RAMInfo an505_raminfo[] = { {
88
+
80
+ .name = "ssram-0",
89
+ if (fan_counts[splitter_no] < 1) {
81
+ .base = 0x00000000,
90
+ continue;
82
+ .size = 0x00400000,
91
+ }
83
+ .mpc = 0,
92
+ object_initialize_child(OBJECT(machine), "fan-splitter[*]",
84
+ .mrindex = 0,
93
+ &splitters[splitter_no], TYPE_SPLIT_IRQ);
85
+ }, {
94
+ splitter = DEVICE(&splitters[splitter_no]);
86
+ .name = "ssram-1",
95
+ qdev_prop_set_uint16(splitter, "num-lines",
87
+ .base = 0x28000000,
96
+ fan_counts[splitter_no]);
88
+ .size = 0x00200000,
97
+ qdev_realize(splitter, NULL, &error_abort);
89
+ .mpc = 1,
98
+ qdev_connect_gpio_out_named(DEVICE(&soc->pwm[i]), "duty-gpio-out",
90
+ .mrindex = 1,
99
+ j, qdev_get_gpio_in(splitter, 0));
91
+ }, {
92
+ .name = "ssram-2",
93
+ .base = 0x28200000,
94
+ .size = 0x00200000,
95
+ .mpc = 2,
96
+ .mrindex = 2,
97
+ }, {
98
+ .name = "ssram-0-alias",
99
+ .base = 0x00400000,
100
+ .size = 0x00400000,
101
+ .mpc = 0,
102
+ .mrindex = 3,
103
+ .flags = IS_ALIAS,
104
+ }, {
105
+ /* Use the largest bit of contiguous RAM as our "system memory" */
106
+ .name = "mps.ram",
107
+ .base = 0x80000000,
108
+ .size = 16 * MiB,
109
+ .mpc = -1,
110
+ .mrindex = -1,
111
+ }, {
112
+ .name = NULL,
113
+ },
114
+};
115
+
116
+static const RAMInfo *find_raminfo_for_mpc(MPS2TZMachineState *mms, int mpc)
117
+{
118
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
119
+ const RAMInfo *p;
120
+
121
+ for (p = mmc->raminfo; p->name; p++) {
122
+ if (p->mpc == mpc && !(p->flags & IS_ALIAS)) {
123
+ return p;
124
+ }
100
+ }
125
+ }
101
+ }
126
+ /* if raminfo array doesn't have an entry for each MPC this is a bug */
102
+}
127
+ g_assert_not_reached();
103
+
128
+}
104
+static void npcm7xx_connect_pwm_fan(NPCM7xxState *soc, SplitIRQ *splitter,
129
+
105
+ int fan_no, int output_no)
130
+static MemoryRegion *mr_for_raminfo(MPS2TZMachineState *mms,
106
+{
131
+ const RAMInfo *raminfo)
107
+ DeviceState *fan;
132
+{
108
+ int fan_input;
133
+ /* Return an initialized MemoryRegion for the RAMInfo. */
109
+ qemu_irq fan_duty_gpio;
134
+ MemoryRegion *ram;
110
+
135
+
111
+ g_assert(fan_no >= 0 && fan_no <= NPCM7XX_MFT_MAX_FAN_INPUT);
136
+ if (raminfo->mrindex < 0) {
112
+ /*
137
+ /* Means this RAMInfo is for QEMU's "system memory" */
113
+ * Fan 0~1 belong to module 0 input 0~1.
138
+ MachineState *machine = MACHINE(mms);
114
+ * Fan 2~3 belong to module 1 input 0~1.
139
+ return machine->ram;
115
+ * ...
116
+ * Fan 14~15 belong to module 7 input 0~1.
117
+ * Fan 16~17 belong to module 0 input 2~3.
118
+ * Fan 18~19 belong to module 1 input 2~3.
119
+ */
120
+ if (fan_no < 16) {
121
+ fan = DEVICE(&soc->mft[fan_no / 2]);
122
+ fan_input = fan_no % 2;
123
+ } else {
124
+ fan = DEVICE(&soc->mft[(fan_no - 16) / 2]);
125
+ fan_input = fan_no % 2 + 2;
140
+ }
126
+ }
141
+
127
+
142
+ assert(raminfo->mrindex < MPS2TZ_RAM_MAX);
128
+ /* Connect the Fan to PWM module */
143
+ ram = &mms->ram[raminfo->mrindex];
129
+ fan_duty_gpio = qdev_get_gpio_in_named(fan, "duty", fan_input);
144
+
130
+ qdev_connect_gpio_out(DEVICE(splitter), output_no, fan_duty_gpio);
145
+ memory_region_init_ram(ram, NULL, raminfo->name,
131
+}
146
+ raminfo->size, &error_fatal);
132
+
147
+ return ram;
133
static void npcm750_evb_i2c_init(NPCM7xxState *soc)
148
+}
149
+
150
/* Create an alias of an entire original MemoryRegion @orig
151
* located at @base in the memory map.
152
*/
153
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
154
const int *irqs)
155
{
134
{
156
TZMPC *mpc = opaque;
135
/* lm75 temperature sensor on SVB, tmp105 is compatible */
157
- int i = mpc - &mms->ssram_mpc[0];
136
@@ -XXX,XX +XXX,XX @@ static void npcm750_evb_i2c_init(NPCM7xxState *soc)
158
- MemoryRegion *ssram = &mms->ssram[i];
137
i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 6), "tmp105", 0x48);
159
+ int i = mpc - &mms->mpc[0];
138
}
160
MemoryRegion *upstream;
139
161
- char *mpcname = g_strdup_printf("%s-mpc", name);
140
+static void npcm750_evb_fan_init(NPCM7xxMachine *machine, NPCM7xxState *soc)
162
- static uint32_t ramsize[] = { 0x00400000, 0x00200000, 0x00200000 };
141
+{
163
- static uint32_t rambase[] = { 0x00000000, 0x28000000, 0x28200000 };
142
+ SplitIRQ *splitter = machine->fan_splitter;
164
+ const RAMInfo *raminfo = find_raminfo_for_mpc(mms, i);
143
+ static const int fan_counts[] = {2, 2, 2, 2, 2, 2, 2, 2};
165
+ MemoryRegion *ram = mr_for_raminfo(mms, raminfo);
144
+
166
145
+ npcm7xx_init_pwm_splitter(machine, soc, fan_counts);
167
- memory_region_init_ram(ssram, NULL, name, ramsize[i], &error_fatal);
146
+ npcm7xx_connect_pwm_fan(soc, &splitter[0], 0x00, 0);
168
-
147
+ npcm7xx_connect_pwm_fan(soc, &splitter[0], 0x01, 1);
169
- object_initialize_child(OBJECT(mms), mpcname, mpc, TYPE_TZ_MPC);
148
+ npcm7xx_connect_pwm_fan(soc, &splitter[1], 0x02, 0);
170
- object_property_set_link(OBJECT(mpc), "downstream", OBJECT(ssram),
149
+ npcm7xx_connect_pwm_fan(soc, &splitter[1], 0x03, 1);
171
+ object_initialize_child(OBJECT(mms), name, mpc, TYPE_TZ_MPC);
150
+ npcm7xx_connect_pwm_fan(soc, &splitter[2], 0x04, 0);
172
+ object_property_set_link(OBJECT(mpc), "downstream", OBJECT(ram),
151
+ npcm7xx_connect_pwm_fan(soc, &splitter[2], 0x05, 1);
173
&error_fatal);
152
+ npcm7xx_connect_pwm_fan(soc, &splitter[3], 0x06, 0);
174
sysbus_realize(SYS_BUS_DEVICE(mpc), &error_fatal);
153
+ npcm7xx_connect_pwm_fan(soc, &splitter[3], 0x07, 1);
175
/* Map the upstream end of the MPC into system memory */
154
+ npcm7xx_connect_pwm_fan(soc, &splitter[4], 0x08, 0);
176
upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1);
155
+ npcm7xx_connect_pwm_fan(soc, &splitter[4], 0x09, 1);
177
- memory_region_add_subregion(get_system_memory(), rambase[i], upstream);
156
+ npcm7xx_connect_pwm_fan(soc, &splitter[5], 0x0a, 0);
178
+ memory_region_add_subregion(get_system_memory(), raminfo->base, upstream);
157
+ npcm7xx_connect_pwm_fan(soc, &splitter[5], 0x0b, 1);
179
/* and connect its interrupt to the IoTKit */
158
+ npcm7xx_connect_pwm_fan(soc, &splitter[6], 0x0c, 0);
180
qdev_connect_gpio_out_named(DEVICE(mpc), "irq", 0,
159
+ npcm7xx_connect_pwm_fan(soc, &splitter[6], 0x0d, 1);
181
qdev_get_gpio_in_named(DEVICE(&mms->iotkit),
160
+ npcm7xx_connect_pwm_fan(soc, &splitter[7], 0x0e, 0);
182
"mpcexp_status", i));
161
+ npcm7xx_connect_pwm_fan(soc, &splitter[7], 0x0f, 1);
183
162
+}
184
- /* The first SSRAM is a special case as it has an alias; accesses to
163
+
185
- * the alias region at 0x00400000 must also go to the MPC upstream.
164
static void quanta_gsj_i2c_init(NPCM7xxState *soc)
186
- */
187
- if (i == 0) {
188
- make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", upstream, 0x00400000);
189
- }
190
-
191
- g_free(mpcname);
192
/* Return the register interface MR for our caller to map behind the PPC */
193
return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0);
194
}
195
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
196
return sysbus_mmio_get_region(s, 0);
197
}
198
199
+static void create_non_mpc_ram(MPS2TZMachineState *mms)
200
+{
201
+ /*
202
+ * Handle the RAMs which are either not behind MPCs or which are
203
+ * aliases to another MPC.
204
+ */
205
+ const RAMInfo *p;
206
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
207
+
208
+ for (p = mmc->raminfo; p->name; p++) {
209
+ if (p->flags & IS_ALIAS) {
210
+ SysBusDevice *mpc_sbd = SYS_BUS_DEVICE(&mms->mpc[p->mpc]);
211
+ MemoryRegion *upstream = sysbus_mmio_get_region(mpc_sbd, 1);
212
+ make_ram_alias(&mms->ram[p->mrindex], p->name, upstream, p->base);
213
+ } else if (p->mpc == -1) {
214
+ /* RAM not behind an MPC */
215
+ MemoryRegion *mr = mr_for_raminfo(mms, p);
216
+ memory_region_add_subregion(get_system_memory(), p->base, mr);
217
+ }
218
+ }
219
+}
220
+
221
static void mps2tz_common_init(MachineState *machine)
222
{
165
{
223
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
166
/* GSJ machine have 4 max31725 temperature sensors, tmp105 is compatible. */
224
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
167
@@ -XXX,XX +XXX,XX @@ static void quanta_gsj_i2c_init(NPCM7xxState *soc)
225
qdev_connect_gpio_out_named(iotkitdev, "sec_resp_cfg", 0,
168
/* TODO: Add additional i2c devices. */
226
qdev_get_gpio_in(dev_splitter, 0));
169
}
227
170
228
- /* The IoTKit sets up much of the memory layout, including
171
+static void quanta_gsj_fan_init(NPCM7xxMachine *machine, NPCM7xxState *soc)
229
+ /*
172
+{
230
+ * The IoTKit sets up much of the memory layout, including
173
+ SplitIRQ *splitter = machine->fan_splitter;
231
* the aliases between secure and non-secure regions in the
174
+ static const int fan_counts[] = {2, 2, 2, 0, 0, 0, 0, 0};
232
- * address space. The FPGA itself contains:
175
+
233
- *
176
+ npcm7xx_init_pwm_splitter(machine, soc, fan_counts);
234
- * 0x00000000..0x003fffff SSRAM1
177
+ npcm7xx_connect_pwm_fan(soc, &splitter[0], 0x00, 0);
235
- * 0x00400000..0x007fffff alias of SSRAM1
178
+ npcm7xx_connect_pwm_fan(soc, &splitter[0], 0x01, 1);
236
- * 0x28000000..0x283fffff 4MB SSRAM2 + SSRAM3
179
+ npcm7xx_connect_pwm_fan(soc, &splitter[1], 0x02, 0);
237
- * 0x40100000..0x4fffffff AHB Master Expansion 1 interface devices
180
+ npcm7xx_connect_pwm_fan(soc, &splitter[1], 0x03, 1);
238
- * 0x80000000..0x80ffffff 16MB PSRAM
181
+ npcm7xx_connect_pwm_fan(soc, &splitter[2], 0x04, 0);
239
- */
182
+ npcm7xx_connect_pwm_fan(soc, &splitter[2], 0x05, 1);
240
-
183
+}
241
- /* The FPGA images have an odd combination of different RAMs,
184
+
242
+ * address space, and also most of the devices in the system.
185
static void npcm750_evb_init(MachineState *machine)
243
+ * The FPGA itself contains various RAMs and some additional devices.
186
{
244
+ * The FPGA images have an odd combination of different RAMs,
187
NPCM7xxState *soc;
245
* because in hardware they are different implementations and
188
@@ -XXX,XX +XXX,XX @@ static void npcm750_evb_init(MachineState *machine)
246
* connected to different buses, giving varying performance/size
189
npcm7xx_load_bootrom(machine, soc);
247
* tradeoffs. For QEMU they're all just RAM, though. We arbitrarily
190
npcm7xx_connect_flash(&soc->fiu[0], 0, "w25q256", drive_get(IF_MTD, 0, 0));
248
- * call the 16MB our "system memory", as it's the largest lump.
191
npcm750_evb_i2c_init(soc);
249
+ * call the largest lump our "system memory".
192
+ npcm750_evb_fan_init(NPCM7XX_MACHINE(machine), soc);
250
*/
193
npcm7xx_load_kernel(machine, soc);
251
- memory_region_add_subregion(system_memory, 0x80000000, machine->ram);
194
}
252
195
253
/*
196
@@ -XXX,XX +XXX,XX @@ static void quanta_gsj_init(MachineState *machine)
254
* The overflow IRQs for all UARTs are ORed together.
197
npcm7xx_connect_flash(&soc->fiu[0], 0, "mx25l25635e",
255
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
198
drive_get(IF_MTD, 0, 0));
256
const PPCInfo an505_ppcs[] = { {
199
quanta_gsj_i2c_init(soc);
257
.name = "apb_ppcexp0",
200
+ quanta_gsj_fan_init(NPCM7XX_MACHINE(machine), soc);
258
.ports = {
201
npcm7xx_load_kernel(machine, soc);
259
- { "ssram-0", make_mpc, &mms->ssram_mpc[0], 0x58007000, 0x1000 },
202
}
260
- { "ssram-1", make_mpc, &mms->ssram_mpc[1], 0x58008000, 0x1000 },
261
- { "ssram-2", make_mpc, &mms->ssram_mpc[2], 0x58009000, 0x1000 },
262
+ { "ssram-0-mpc", make_mpc, &mms->mpc[0], 0x58007000, 0x1000 },
263
+ { "ssram-1-mpc", make_mpc, &mms->mpc[1], 0x58008000, 0x1000 },
264
+ { "ssram-2-mpc", make_mpc, &mms->mpc[2], 0x58009000, 0x1000 },
265
},
266
}, {
267
.name = "apb_ppcexp1",
268
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
269
270
create_unimplemented_device("FPGA NS PC", 0x48007000, 0x1000);
271
272
+ create_non_mpc_ram(mms);
273
+
274
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
275
}
276
277
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
278
mmc->fpgaio_num_leds = 2;
279
mmc->fpgaio_has_switches = false;
280
mmc->numirq = 92;
281
+ mmc->raminfo = an505_raminfo;
282
mmc->armsse_type = TYPE_IOTKIT;
283
}
284
285
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
286
mmc->fpgaio_num_leds = 2;
287
mmc->fpgaio_has_switches = false;
288
mmc->numirq = 92;
289
+ mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
290
mmc->armsse_type = TYPE_SSE200;
291
}
292
203
293
--
204
--
294
2.20.1
205
2.20.1
295
206
296
207
diff view generated by jsdifflib
1
The AN505 and AN521 have the same device layout, but the AN524 is
1
From: Hao Wu <wuhaotsh@google.com>
2
somewhat different. Allow for more than one PPCInfo array, which can
2
3
be selected based on the board type.
3
This patch adds testing of PWM fan RPMs in the existing npcm7xx pwm
4
4
test. It tests whether the MFT module can measure correct fan values
5
for a PWM fan in NPCM7XX boards.
6
7
Reviewed-by: Doug Evans <dje@google.com>
8
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
9
Signed-off-by: Hao Wu <wuhaotsh@google.com>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20210311180855.149764-6-wuhaotsh@google.com
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210215115138.20465-16-peter.maydell@linaro.org
8
---
13
---
9
hw/arm/mps2-tz.c | 16 ++++++++++++++--
14
tests/qtest/npcm7xx_pwm-test.c | 205 ++++++++++++++++++++++++++++++++-
10
1 file changed, 14 insertions(+), 2 deletions(-)
15
1 file changed, 199 insertions(+), 6 deletions(-)
11
16
12
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
17
diff --git a/tests/qtest/npcm7xx_pwm-test.c b/tests/qtest/npcm7xx_pwm-test.c
13
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/mps2-tz.c
19
--- a/tests/qtest/npcm7xx_pwm-test.c
15
+++ b/hw/arm/mps2-tz.c
20
+++ b/tests/qtest/npcm7xx_pwm-test.c
16
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
21
@@ -XXX,XX +XXX,XX @@
17
MemoryRegion *system_memory = get_system_memory();
22
#define PLL_FBDV(rv) extract32((rv), 16, 12)
18
DeviceState *iotkitdev;
23
#define PLL_OTDV1(rv) extract32((rv), 8, 3)
19
DeviceState *dev_splitter;
24
#define PLL_OTDV2(rv) extract32((rv), 13, 3)
20
+ const PPCInfo *ppcs;
25
+#define APB4CKDIV(rv) extract32((rv), 30, 2)
21
+ int num_ppcs;
26
#define APB3CKDIV(rv) extract32((rv), 28, 2)
22
int i;
27
#define CLK2CKDIV(rv) extract32((rv), 0, 1)
23
28
#define CLK4CKDIV(rv) extract32((rv), 26, 2)
24
if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
29
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
30
26
* + wire up the PPC's control lines to the IoTKit object
31
#define MAX_DUTY 1000000
27
*/
32
28
33
+/* MFT (PWM fan) related */
29
- const PPCInfo ppcs[] = { {
34
+#define MFT_BA(n) (0xf0180000 + ((n) * 0x1000))
30
+ const PPCInfo an505_ppcs[] = { {
35
+#define MFT_IRQ(n) (96 + (n))
31
.name = "apb_ppcexp0",
36
+#define MFT_CNT1 0x00
32
.ports = {
37
+#define MFT_CRA 0x02
33
{ "ssram-0", make_mpc, &mms->ssram_mpc[0], 0x58007000, 0x1000 },
38
+#define MFT_CRB 0x04
34
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
39
+#define MFT_CNT2 0x06
35
},
40
+#define MFT_PRSC 0x08
36
};
41
+#define MFT_CKC 0x0a
37
42
+#define MFT_MCTRL 0x0c
38
- for (i = 0; i < ARRAY_SIZE(ppcs); i++) {
43
+#define MFT_ICTRL 0x0e
39
+ switch (mmc->fpga_type) {
44
+#define MFT_ICLR 0x10
40
+ case FPGA_AN505:
45
+#define MFT_IEN 0x12
41
+ case FPGA_AN521:
46
+#define MFT_CPA 0x14
42
+ ppcs = an505_ppcs;
47
+#define MFT_CPB 0x16
43
+ num_ppcs = ARRAY_SIZE(an505_ppcs);
48
+#define MFT_CPCFG 0x18
44
+ break;
49
+#define MFT_INASEL 0x1a
45
+ default:
50
+#define MFT_INBSEL 0x1c
46
+ g_assert_not_reached();
51
+
52
+#define MFT_MCTRL_ALL 0x64
53
+#define MFT_ICLR_ALL 0x3f
54
+#define MFT_IEN_ALL 0x3f
55
+#define MFT_CPCFG_EQ_MODE 0x44
56
+
57
+#define MFT_CKC_C2CSEL BIT(3)
58
+#define MFT_CKC_C1CSEL BIT(0)
59
+
60
+#define MFT_ICTRL_TFPND BIT(5)
61
+#define MFT_ICTRL_TEPND BIT(4)
62
+#define MFT_ICTRL_TDPND BIT(3)
63
+#define MFT_ICTRL_TCPND BIT(2)
64
+#define MFT_ICTRL_TBPND BIT(1)
65
+#define MFT_ICTRL_TAPND BIT(0)
66
+
67
+#define MFT_MAX_CNT 0xffff
68
+#define MFT_TIMEOUT 0x5000
69
+
70
+#define DEFAULT_RPM 19800
71
+#define DEFAULT_PRSC 255
72
+#define MFT_PULSE_PER_REVOLUTION 2
73
+
74
+#define MAX_ERROR 1
75
+
76
typedef struct PWMModule {
77
int irq;
78
uint64_t base_addr;
79
@@ -XXX,XX +XXX,XX @@ static uint64_t pwm_get_duty(QTestState *qts, int module_index, int pwm_index)
80
return pwm_qom_get(qts, path, name);
81
}
82
83
+static void mft_qom_set(QTestState *qts, int index, const char *name,
84
+ uint32_t value)
85
+{
86
+ QDict *response;
87
+ char *path = g_strdup_printf("/machine/soc/mft[%d]", index);
88
+
89
+ g_test_message("Setting properties %s of mft[%d] with value %u",
90
+ name, index, value);
91
+ response = qtest_qmp(qts, "{ 'execute': 'qom-set',"
92
+ " 'arguments': { 'path': %s, "
93
+ " 'property': %s, 'value': %u}}",
94
+ path, name, value);
95
+ /* The qom set message returns successfully. */
96
+ g_assert_true(qdict_haskey(response, "return"));
97
+}
98
+
99
static uint32_t get_pll(uint32_t con)
100
{
101
return REF_HZ * PLL_FBDV(con) / (PLL_INDV(con) * PLL_OTDV1(con)
102
* PLL_OTDV2(con));
103
}
104
105
-static uint64_t read_pclk(QTestState *qts)
106
+static uint64_t read_pclk(QTestState *qts, bool mft)
107
{
108
uint64_t freq = REF_HZ;
109
uint32_t clksel = qtest_readl(qts, CLK_BA + CLKSEL);
110
uint32_t pllcon;
111
uint32_t clkdiv1 = qtest_readl(qts, CLK_BA + CLKDIV1);
112
uint32_t clkdiv2 = qtest_readl(qts, CLK_BA + CLKDIV2);
113
+ uint32_t apbdiv = mft ? APB4CKDIV(clkdiv2) : APB3CKDIV(clkdiv2);
114
115
switch (CPUCKSEL(clksel)) {
116
case 0:
117
@@ -XXX,XX +XXX,XX @@ static uint64_t read_pclk(QTestState *qts)
118
g_assert_not_reached();
119
}
120
121
- freq >>= (CLK2CKDIV(clkdiv1) + CLK4CKDIV(clkdiv1) + APB3CKDIV(clkdiv2));
122
+ freq >>= (CLK2CKDIV(clkdiv1) + CLK4CKDIV(clkdiv1) + apbdiv);
123
124
return freq;
125
}
126
@@ -XXX,XX +XXX,XX @@ static uint32_t pwm_selector(uint32_t csr)
127
static uint64_t pwm_compute_freq(QTestState *qts, uint32_t ppr, uint32_t csr,
128
uint32_t cnr)
129
{
130
- return read_pclk(qts) / ((ppr + 1) * pwm_selector(csr) * (cnr + 1));
131
+ return read_pclk(qts, false) / ((ppr + 1) * pwm_selector(csr) * (cnr + 1));
132
}
133
134
static uint64_t pwm_compute_duty(uint32_t cnr, uint32_t cmr, bool inverted)
135
@@ -XXX,XX +XXX,XX @@ static void pwm_write(QTestState *qts, const TestData *td, unsigned offset,
136
qtest_writel(qts, td->module->base_addr + offset, value);
137
}
138
139
+static uint8_t mft_readb(QTestState *qts, int index, unsigned offset)
140
+{
141
+ return qtest_readb(qts, MFT_BA(index) + offset);
142
+}
143
+
144
+static uint16_t mft_readw(QTestState *qts, int index, unsigned offset)
145
+{
146
+ return qtest_readw(qts, MFT_BA(index) + offset);
147
+}
148
+
149
+static void mft_writeb(QTestState *qts, int index, unsigned offset,
150
+ uint8_t value)
151
+{
152
+ qtest_writeb(qts, MFT_BA(index) + offset, value);
153
+}
154
+
155
+static void mft_writew(QTestState *qts, int index, unsigned offset,
156
+ uint16_t value)
157
+{
158
+ return qtest_writew(qts, MFT_BA(index) + offset, value);
159
+}
160
+
161
static uint32_t pwm_read_ppr(QTestState *qts, const TestData *td)
162
{
163
return extract32(pwm_read(qts, td, PPR), ppr_base[pwm_index(td->pwm)], 8);
164
@@ -XXX,XX +XXX,XX @@ static void pwm_write_cmr(QTestState *qts, const TestData *td, uint32_t value)
165
pwm_write(qts, td, td->pwm->cmr_offset, value);
166
}
167
168
+static int mft_compute_index(const TestData *td)
169
+{
170
+ int index = pwm_module_index(td->module) * ARRAY_SIZE(pwm_list) +
171
+ pwm_index(td->pwm);
172
+
173
+ g_assert_cmpint(index, <,
174
+ ARRAY_SIZE(pwm_module_list) * ARRAY_SIZE(pwm_list));
175
+
176
+ return index;
177
+}
178
+
179
+static void mft_reset_counters(QTestState *qts, int index)
180
+{
181
+ mft_writew(qts, index, MFT_CNT1, MFT_MAX_CNT);
182
+ mft_writew(qts, index, MFT_CNT2, MFT_MAX_CNT);
183
+ mft_writew(qts, index, MFT_CRA, MFT_MAX_CNT);
184
+ mft_writew(qts, index, MFT_CRB, MFT_MAX_CNT);
185
+ mft_writew(qts, index, MFT_CPA, MFT_MAX_CNT - MFT_TIMEOUT);
186
+ mft_writew(qts, index, MFT_CPB, MFT_MAX_CNT - MFT_TIMEOUT);
187
+}
188
+
189
+static void mft_init(QTestState *qts, const TestData *td)
190
+{
191
+ int index = mft_compute_index(td);
192
+
193
+ /* Enable everything */
194
+ mft_writeb(qts, index, MFT_CKC, 0);
195
+ mft_writeb(qts, index, MFT_ICLR, MFT_ICLR_ALL);
196
+ mft_writeb(qts, index, MFT_MCTRL, MFT_MCTRL_ALL);
197
+ mft_writeb(qts, index, MFT_IEN, MFT_IEN_ALL);
198
+ mft_writeb(qts, index, MFT_INASEL, 0);
199
+ mft_writeb(qts, index, MFT_INBSEL, 0);
200
+
201
+ /* Set cpcfg to use EQ mode, same as kernel driver */
202
+ mft_writeb(qts, index, MFT_CPCFG, MFT_CPCFG_EQ_MODE);
203
+
204
+ /* Write default counters, timeout and prescaler */
205
+ mft_reset_counters(qts, index);
206
+ mft_writeb(qts, index, MFT_PRSC, DEFAULT_PRSC);
207
+
208
+ /* Write default max rpm via QMP */
209
+ mft_qom_set(qts, index, "max_rpm[0]", DEFAULT_RPM);
210
+ mft_qom_set(qts, index, "max_rpm[1]", DEFAULT_RPM);
211
+}
212
+
213
+static int32_t mft_compute_cnt(uint32_t rpm, uint64_t clk)
214
+{
215
+ uint64_t cnt;
216
+
217
+ if (rpm == 0) {
218
+ return -1;
47
+ }
219
+ }
48
+
220
+
49
+ for (i = 0; i < num_ppcs; i++) {
221
+ cnt = clk * 60 / ((DEFAULT_PRSC + 1) * rpm * MFT_PULSE_PER_REVOLUTION);
50
const PPCInfo *ppcinfo = &ppcs[i];
222
+ if (cnt >= MFT_TIMEOUT) {
51
TZPPC *ppc = &mms->ppc[i];
223
+ return -1;
52
DeviceState *ppcdev;
224
+ }
225
+ return MFT_MAX_CNT - cnt;
226
+}
227
+
228
+static void mft_verify_rpm(QTestState *qts, const TestData *td, uint64_t duty)
229
+{
230
+ int index = mft_compute_index(td);
231
+ uint16_t cnt, cr;
232
+ uint32_t rpm = DEFAULT_RPM * duty / MAX_DUTY;
233
+ uint64_t clk = read_pclk(qts, true);
234
+ int32_t expected_cnt = mft_compute_cnt(rpm, clk);
235
+
236
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
237
+ g_test_message(
238
+ "verifying rpm for mft[%d]: clk: %lu, duty: %lu, rpm: %u, cnt: %d",
239
+ index, clk, duty, rpm, expected_cnt);
240
+
241
+ /* Verify rpm for fan A */
242
+ /* Stop capture */
243
+ mft_writeb(qts, index, MFT_CKC, 0);
244
+ mft_writeb(qts, index, MFT_ICLR, MFT_ICLR_ALL);
245
+ mft_reset_counters(qts, index);
246
+ g_assert_cmphex(mft_readw(qts, index, MFT_CNT1), ==, MFT_MAX_CNT);
247
+ g_assert_cmphex(mft_readw(qts, index, MFT_CRA), ==, MFT_MAX_CNT);
248
+ g_assert_cmphex(mft_readw(qts, index, MFT_CPA), ==,
249
+ MFT_MAX_CNT - MFT_TIMEOUT);
250
+ /* Start capture */
251
+ mft_writeb(qts, index, MFT_CKC, MFT_CKC_C1CSEL);
252
+ g_assert_true(qtest_get_irq(qts, MFT_IRQ(index)));
253
+ if (expected_cnt == -1) {
254
+ g_assert_cmphex(mft_readb(qts, index, MFT_ICTRL), ==, MFT_ICTRL_TEPND);
255
+ } else {
256
+ g_assert_cmphex(mft_readb(qts, index, MFT_ICTRL), ==, MFT_ICTRL_TAPND);
257
+ cnt = mft_readw(qts, index, MFT_CNT1);
258
+ /*
259
+ * Due to error in clock measurement and rounding, we might have a small
260
+ * error in measuring RPM.
261
+ */
262
+ g_assert_cmphex(cnt + MAX_ERROR, >=, expected_cnt);
263
+ g_assert_cmphex(cnt, <=, expected_cnt + MAX_ERROR);
264
+ cr = mft_readw(qts, index, MFT_CRA);
265
+ g_assert_cmphex(cnt, ==, cr);
266
+ }
267
+
268
+ /* Verify rpm for fan B */
269
+
270
+ qtest_irq_intercept_out(qts, "/machine/soc/a9mpcore/gic");
271
+}
272
+
273
/* Check pwm registers can be reset to default value */
274
static void test_init(gconstpointer test_data)
275
{
276
const TestData *td = test_data;
277
- QTestState *qts = qtest_init("-machine quanta-gsj");
278
+ QTestState *qts = qtest_init("-machine npcm750-evb");
279
int module = pwm_module_index(td->module);
280
int pwm = pwm_index(td->pwm);
281
282
@@ -XXX,XX +XXX,XX @@ static void test_init(gconstpointer test_data)
283
static void test_oneshot(gconstpointer test_data)
284
{
285
const TestData *td = test_data;
286
- QTestState *qts = qtest_init("-machine quanta-gsj");
287
+ QTestState *qts = qtest_init("-machine npcm750-evb");
288
int module = pwm_module_index(td->module);
289
int pwm = pwm_index(td->pwm);
290
uint32_t ppr, csr, pcr;
291
@@ -XXX,XX +XXX,XX @@ static void test_oneshot(gconstpointer test_data)
292
static void test_toggle(gconstpointer test_data)
293
{
294
const TestData *td = test_data;
295
- QTestState *qts = qtest_init("-machine quanta-gsj");
296
+ QTestState *qts = qtest_init("-machine npcm750-evb");
297
int module = pwm_module_index(td->module);
298
int pwm = pwm_index(td->pwm);
299
uint32_t ppr, csr, pcr, cnr, cmr;
300
int i, j, k, l;
301
uint64_t expected_freq, expected_duty;
302
303
+ mft_init(qts, td);
304
+
305
pcr = CH_EN | CH_MOD;
306
for (i = 0; i < ARRAY_SIZE(ppr_list); ++i) {
307
ppr = ppr_list[i];
308
@@ -XXX,XX +XXX,XX @@ static void test_toggle(gconstpointer test_data)
309
==, expected_freq);
310
}
311
312
+ /* Test MFT's RPM is correct. */
313
+ mft_verify_rpm(qts, td, expected_duty);
314
+
315
/* Test inverted mode */
316
expected_duty = pwm_compute_duty(cnr, cmr, true);
317
pwm_write_pcr(qts, td, pcr | CH_INV);
53
--
318
--
54
2.20.1
319
2.20.1
55
320
56
321
diff view generated by jsdifflib
1
For a long time now the UI layer has guaranteed that the console
1
For a long time now the UI layer has guaranteed that the console
2
surface is always 32 bits per pixel RGB. Remove the legacy dead
2
surface is always 32 bits per pixel. Remove the legacy dead
3
code from the milkymist display device which was handling the
3
code from the pl110 display device which was handling the
4
possibility that the console surface was some other format.
4
possibility that the console surface was some other format.
5
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
8
Message-id: 20210215103215.4944-2-peter.maydell@linaro.org
8
Message-id: 20210211141515.8755-2-peter.maydell@linaro.org
9
---
9
---
10
hw/arm/musicpal.c | 64 ++++++++++++++++++-----------------------------
10
hw/display/pl110.c | 53 +++++++---------------------------------------
11
1 file changed, 24 insertions(+), 40 deletions(-)
11
1 file changed, 8 insertions(+), 45 deletions(-)
12
12
13
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
13
diff --git a/hw/display/pl110.c b/hw/display/pl110.c
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/musicpal.c
15
--- a/hw/display/pl110.c
16
+++ b/hw/arm/musicpal.c
16
+++ b/hw/display/pl110.c
17
@@ -XXX,XX +XXX,XX @@ static uint8_t scale_lcd_color(musicpal_lcd_state *s, uint8_t col)
17
@@ -XXX,XX +XXX,XX @@ static const unsigned char *idregs[] = {
18
}
18
pl111_id
19
}
19
};
20
20
21
-#define SET_LCD_PIXEL(depth, type) \
21
-#define BITS 8
22
-static inline void glue(set_lcd_pixel, depth) \
22
-#include "pl110_template.h"
23
- (musicpal_lcd_state *s, int x, int y, type col) \
23
-#define BITS 15
24
-{ \
24
-#include "pl110_template.h"
25
- int dx, dy; \
25
-#define BITS 16
26
- DisplaySurface *surface = qemu_console_surface(s->con); \
26
-#include "pl110_template.h"
27
- type *pixel = &((type *) surface_data(surface))[(y * 128 * 3 + x) * 3]; \
27
-#define BITS 24
28
-\
28
-#include "pl110_template.h"
29
- for (dy = 0; dy < 3; dy++, pixel += 127 * 3) \
29
#define BITS 32
30
- for (dx = 0; dx < 3; dx++, pixel++) \
30
#include "pl110_template.h"
31
- *pixel = col; \
31
32
+static inline void set_lcd_pixel32(musicpal_lcd_state *s,
32
@@ -XXX,XX +XXX,XX @@ static void pl110_update_display(void *opaque)
33
+ int x, int y, uint32_t col)
33
PL110State *s = (PL110State *)opaque;
34
+{
34
SysBusDevice *sbd;
35
+ int dx, dy;
35
DisplaySurface *surface = qemu_console_surface(s->con);
36
+ DisplaySurface *surface = qemu_console_surface(s->con);
36
- drawfn* fntable;
37
+ uint32_t *pixel =
37
drawfn fn;
38
+ &((uint32_t *) surface_data(surface))[(y * 128 * 3 + x) * 3];
38
- int dest_width;
39
+
39
int src_width;
40
+ for (dy = 0; dy < 3; dy++, pixel += 127 * 3) {
40
int bpp_offset;
41
+ for (dx = 0; dx < 3; dx++, pixel++) {
41
int first;
42
+ *pixel = col;
42
@@ -XXX,XX +XXX,XX @@ static void pl110_update_display(void *opaque)
43
+ }
43
44
+ }
44
sbd = SYS_BUS_DEVICE(s);
45
}
46
-SET_LCD_PIXEL(8, uint8_t)
47
-SET_LCD_PIXEL(16, uint16_t)
48
-SET_LCD_PIXEL(32, uint32_t)
49
50
static void lcd_refresh(void *opaque)
51
{
52
musicpal_lcd_state *s = opaque;
53
- DisplaySurface *surface = qemu_console_surface(s->con);
54
int x, y, col;
55
45
56
- switch (surface_bits_per_pixel(surface)) {
46
- switch (surface_bits_per_pixel(surface)) {
57
- case 0:
47
- case 0:
58
- return;
48
- return;
59
-#define LCD_REFRESH(depth, func) \
49
- case 8:
60
- case depth: \
50
- fntable = pl110_draw_fn_8;
61
- col = func(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff), \
51
- dest_width = 1;
62
- scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff), \
63
- scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff)); \
64
- for (x = 0; x < 128; x++) { \
65
- for (y = 0; y < 64; y++) { \
66
- if (s->video_ram[x + (y/8)*128] & (1 << (y % 8))) { \
67
- glue(set_lcd_pixel, depth)(s, x, y, col); \
68
- } else { \
69
- glue(set_lcd_pixel, depth)(s, x, y, 0); \
70
- } \
71
- } \
72
- } \
73
- break;
52
- break;
74
- LCD_REFRESH(8, rgb_to_pixel8)
53
- case 15:
75
- LCD_REFRESH(16, rgb_to_pixel16)
54
- fntable = pl110_draw_fn_15;
76
- LCD_REFRESH(32, (is_surface_bgr(surface) ?
55
- dest_width = 2;
77
- rgb_to_pixel32bgr : rgb_to_pixel32))
56
- break;
57
- case 16:
58
- fntable = pl110_draw_fn_16;
59
- dest_width = 2;
60
- break;
61
- case 24:
62
- fntable = pl110_draw_fn_24;
63
- dest_width = 3;
64
- break;
65
- case 32:
66
- fntable = pl110_draw_fn_32;
67
- dest_width = 4;
68
- break;
78
- default:
69
- default:
79
- hw_error("unsupported colour depth %i\n",
70
- fprintf(stderr, "pl110: Bad color depth\n");
80
- surface_bits_per_pixel(surface));
71
- exit(1);
81
+ col = rgb_to_pixel32(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff),
72
- }
82
+ scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff),
73
if (s->cr & PL110_CR_BGR)
83
+ scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff));
74
bpp_offset = 0;
84
+ for (x = 0; x < 128; x++) {
75
else
85
+ for (y = 0; y < 64; y++) {
76
@@ -XXX,XX +XXX,XX @@ static void pl110_update_display(void *opaque)
86
+ if (s->video_ram[x + (y / 8) * 128] & (1 << (y % 8))) {
77
}
87
+ set_lcd_pixel32(s, x, y, col);
88
+ } else {
89
+ set_lcd_pixel32(s, x, y, 0);
90
+ }
91
+ }
92
}
78
}
93
79
94
dpy_gfx_update(s->con, 0, 0, 128*3, 64*3);
80
- if (s->cr & PL110_CR_BEBO)
81
- fn = fntable[s->bpp + 8 + bpp_offset];
82
- else if (s->cr & PL110_CR_BEPO)
83
- fn = fntable[s->bpp + 16 + bpp_offset];
84
- else
85
- fn = fntable[s->bpp + bpp_offset];
86
+ if (s->cr & PL110_CR_BEBO) {
87
+ fn = pl110_draw_fn_32[s->bpp + 8 + bpp_offset];
88
+ } else if (s->cr & PL110_CR_BEPO) {
89
+ fn = pl110_draw_fn_32[s->bpp + 16 + bpp_offset];
90
+ } else {
91
+ fn = pl110_draw_fn_32[s->bpp + bpp_offset];
92
+ }
93
94
src_width = s->cols;
95
switch (s->bpp) {
96
@@ -XXX,XX +XXX,XX @@ static void pl110_update_display(void *opaque)
97
src_width <<= 2;
98
break;
99
}
100
- dest_width *= s->cols;
101
first = 0;
102
if (s->invalidate) {
103
framebuffer_update_memory_section(&s->fbsection,
104
@@ -XXX,XX +XXX,XX @@ static void pl110_update_display(void *opaque)
105
106
framebuffer_update_display(surface, &s->fbsection,
107
s->cols, s->rows,
108
- src_width, dest_width, 0,
109
+ src_width, s->cols * 4, 0,
110
s->invalidate,
111
fn, s->palette,
112
&first, &last);
95
--
113
--
96
2.20.1
114
2.20.1
97
115
98
116
diff view generated by jsdifflib
1
The AN505 and AN511 happen to share the same OSCCLK values, but the
1
The pl110_template.h header has a doubly-nested multiple-include pattern:
2
AN524 will have a different set (and more of them), so split the
2
* pl110.c includes it once for each host bit depth (now always 32)
3
settings out to be per-board.
3
* every time it is included, it includes itself 6 times, to account
4
for multiple guest device pixel and byte orders
5
6
Now we only have to deal with 32-bit host bit depths, we can move the
7
code corresponding to the outer layer of this double-nesting to be
8
directly in pl110.c and reduce the template header to a single layer
9
of nesting.
4
10
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20210211141515.8755-3-peter.maydell@linaro.org
8
Message-id: 20210215115138.20465-5-peter.maydell@linaro.org
9
---
14
---
10
hw/arm/mps2-tz.c | 23 ++++++++++++++++++-----
15
hw/display/pl110_template.h | 100 +-----------------------------------
11
1 file changed, 18 insertions(+), 5 deletions(-)
16
hw/display/pl110.c | 79 ++++++++++++++++++++++++++++
12
17
2 files changed, 80 insertions(+), 99 deletions(-)
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
18
19
diff --git a/hw/display/pl110_template.h b/hw/display/pl110_template.h
14
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/mps2-tz.c
21
--- a/hw/display/pl110_template.h
16
+++ b/hw/arm/mps2-tz.c
22
+++ b/hw/display/pl110_template.h
17
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
23
@@ -XXX,XX +XXX,XX @@
18
MPS2TZFPGAType fpga_type;
24
*/
19
uint32_t scc_id;
25
20
uint32_t sysclk_frq; /* Main SYSCLK frequency in Hz */
26
#ifndef ORDER
21
+ uint32_t len_oscclk;
27
-
22
+ const uint32_t *oscclk;
28
-#if BITS == 8
23
const char *armsse_type;
29
-#define COPY_PIXEL(to, from) *(to++) = from
30
-#elif BITS == 15 || BITS == 16
31
-#define COPY_PIXEL(to, from) do { *(uint16_t *)to = from; to += 2; } while (0)
32
-#elif BITS == 24
33
-#define COPY_PIXEL(to, from) \
34
- do { \
35
- *(to++) = from; \
36
- *(to++) = (from) >> 8; \
37
- *(to++) = (from) >> 16; \
38
- } while (0)
39
-#elif BITS == 32
40
-#define COPY_PIXEL(to, from) do { *(uint32_t *)to = from; to += 4; } while (0)
41
-#else
42
-#error unknown bit depth
43
+#error "pl110_template.h is only for inclusion by pl110.c"
44
#endif
45
46
-#undef RGB
47
-#define BORDER bgr
48
-#define ORDER 0
49
-#include "pl110_template.h"
50
-#define ORDER 1
51
-#include "pl110_template.h"
52
-#define ORDER 2
53
-#include "pl110_template.h"
54
-#undef BORDER
55
-#define RGB
56
-#define BORDER rgb
57
-#define ORDER 0
58
-#include "pl110_template.h"
59
-#define ORDER 1
60
-#include "pl110_template.h"
61
-#define ORDER 2
62
-#include "pl110_template.h"
63
-#undef BORDER
64
-
65
-static drawfn glue(pl110_draw_fn_,BITS)[48] =
66
-{
67
- glue(pl110_draw_line1_lblp_bgr,BITS),
68
- glue(pl110_draw_line2_lblp_bgr,BITS),
69
- glue(pl110_draw_line4_lblp_bgr,BITS),
70
- glue(pl110_draw_line8_lblp_bgr,BITS),
71
- glue(pl110_draw_line16_555_lblp_bgr,BITS),
72
- glue(pl110_draw_line32_lblp_bgr,BITS),
73
- glue(pl110_draw_line16_lblp_bgr,BITS),
74
- glue(pl110_draw_line12_lblp_bgr,BITS),
75
-
76
- glue(pl110_draw_line1_bbbp_bgr,BITS),
77
- glue(pl110_draw_line2_bbbp_bgr,BITS),
78
- glue(pl110_draw_line4_bbbp_bgr,BITS),
79
- glue(pl110_draw_line8_bbbp_bgr,BITS),
80
- glue(pl110_draw_line16_555_bbbp_bgr,BITS),
81
- glue(pl110_draw_line32_bbbp_bgr,BITS),
82
- glue(pl110_draw_line16_bbbp_bgr,BITS),
83
- glue(pl110_draw_line12_bbbp_bgr,BITS),
84
-
85
- glue(pl110_draw_line1_lbbp_bgr,BITS),
86
- glue(pl110_draw_line2_lbbp_bgr,BITS),
87
- glue(pl110_draw_line4_lbbp_bgr,BITS),
88
- glue(pl110_draw_line8_lbbp_bgr,BITS),
89
- glue(pl110_draw_line16_555_lbbp_bgr,BITS),
90
- glue(pl110_draw_line32_lbbp_bgr,BITS),
91
- glue(pl110_draw_line16_lbbp_bgr,BITS),
92
- glue(pl110_draw_line12_lbbp_bgr,BITS),
93
-
94
- glue(pl110_draw_line1_lblp_rgb,BITS),
95
- glue(pl110_draw_line2_lblp_rgb,BITS),
96
- glue(pl110_draw_line4_lblp_rgb,BITS),
97
- glue(pl110_draw_line8_lblp_rgb,BITS),
98
- glue(pl110_draw_line16_555_lblp_rgb,BITS),
99
- glue(pl110_draw_line32_lblp_rgb,BITS),
100
- glue(pl110_draw_line16_lblp_rgb,BITS),
101
- glue(pl110_draw_line12_lblp_rgb,BITS),
102
-
103
- glue(pl110_draw_line1_bbbp_rgb,BITS),
104
- glue(pl110_draw_line2_bbbp_rgb,BITS),
105
- glue(pl110_draw_line4_bbbp_rgb,BITS),
106
- glue(pl110_draw_line8_bbbp_rgb,BITS),
107
- glue(pl110_draw_line16_555_bbbp_rgb,BITS),
108
- glue(pl110_draw_line32_bbbp_rgb,BITS),
109
- glue(pl110_draw_line16_bbbp_rgb,BITS),
110
- glue(pl110_draw_line12_bbbp_rgb,BITS),
111
-
112
- glue(pl110_draw_line1_lbbp_rgb,BITS),
113
- glue(pl110_draw_line2_lbbp_rgb,BITS),
114
- glue(pl110_draw_line4_lbbp_rgb,BITS),
115
- glue(pl110_draw_line8_lbbp_rgb,BITS),
116
- glue(pl110_draw_line16_555_lbbp_rgb,BITS),
117
- glue(pl110_draw_line32_lbbp_rgb,BITS),
118
- glue(pl110_draw_line16_lbbp_rgb,BITS),
119
- glue(pl110_draw_line12_lbbp_rgb,BITS),
120
-};
121
-
122
-#undef BITS
123
-#undef COPY_PIXEL
124
-
125
-#else
126
-
127
#if ORDER == 0
128
#define NAME glue(glue(lblp_, BORDER), BITS)
129
#ifdef HOST_WORDS_BIGENDIAN
130
@@ -XXX,XX +XXX,XX @@ static void glue(pl110_draw_line12_,NAME)(void *opaque, uint8_t *d, const uint8_
131
#undef NAME
132
#undef SWAP_WORDS
133
#undef ORDER
134
-
135
-#endif
136
diff --git a/hw/display/pl110.c b/hw/display/pl110.c
137
index XXXXXXX..XXXXXXX 100644
138
--- a/hw/display/pl110.c
139
+++ b/hw/display/pl110.c
140
@@ -XXX,XX +XXX,XX @@ static const unsigned char *idregs[] = {
24
};
141
};
25
142
26
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
143
#define BITS 32
27
/* Slow 32Khz S32KCLK frequency in Hz */
144
+#define COPY_PIXEL(to, from) do { *(uint32_t *)to = from; to += 4; } while (0)
28
#define S32KCLK_FRQ (32 * 1000)
145
+
29
146
+#undef RGB
30
+static const uint32_t an505_oscclk[] = {
147
+#define BORDER bgr
31
+ 40000000,
148
+#define ORDER 0
32
+ 24580000,
149
#include "pl110_template.h"
33
+ 25000000,
150
+#define ORDER 1
151
+#include "pl110_template.h"
152
+#define ORDER 2
153
+#include "pl110_template.h"
154
+#undef BORDER
155
+#define RGB
156
+#define BORDER rgb
157
+#define ORDER 0
158
+#include "pl110_template.h"
159
+#define ORDER 1
160
+#include "pl110_template.h"
161
+#define ORDER 2
162
+#include "pl110_template.h"
163
+#undef BORDER
164
+
165
+static drawfn pl110_draw_fn_32[48] = {
166
+ pl110_draw_line1_lblp_bgr32,
167
+ pl110_draw_line2_lblp_bgr32,
168
+ pl110_draw_line4_lblp_bgr32,
169
+ pl110_draw_line8_lblp_bgr32,
170
+ pl110_draw_line16_555_lblp_bgr32,
171
+ pl110_draw_line32_lblp_bgr32,
172
+ pl110_draw_line16_lblp_bgr32,
173
+ pl110_draw_line12_lblp_bgr32,
174
+
175
+ pl110_draw_line1_bbbp_bgr32,
176
+ pl110_draw_line2_bbbp_bgr32,
177
+ pl110_draw_line4_bbbp_bgr32,
178
+ pl110_draw_line8_bbbp_bgr32,
179
+ pl110_draw_line16_555_bbbp_bgr32,
180
+ pl110_draw_line32_bbbp_bgr32,
181
+ pl110_draw_line16_bbbp_bgr32,
182
+ pl110_draw_line12_bbbp_bgr32,
183
+
184
+ pl110_draw_line1_lbbp_bgr32,
185
+ pl110_draw_line2_lbbp_bgr32,
186
+ pl110_draw_line4_lbbp_bgr32,
187
+ pl110_draw_line8_lbbp_bgr32,
188
+ pl110_draw_line16_555_lbbp_bgr32,
189
+ pl110_draw_line32_lbbp_bgr32,
190
+ pl110_draw_line16_lbbp_bgr32,
191
+ pl110_draw_line12_lbbp_bgr32,
192
+
193
+ pl110_draw_line1_lblp_rgb32,
194
+ pl110_draw_line2_lblp_rgb32,
195
+ pl110_draw_line4_lblp_rgb32,
196
+ pl110_draw_line8_lblp_rgb32,
197
+ pl110_draw_line16_555_lblp_rgb32,
198
+ pl110_draw_line32_lblp_rgb32,
199
+ pl110_draw_line16_lblp_rgb32,
200
+ pl110_draw_line12_lblp_rgb32,
201
+
202
+ pl110_draw_line1_bbbp_rgb32,
203
+ pl110_draw_line2_bbbp_rgb32,
204
+ pl110_draw_line4_bbbp_rgb32,
205
+ pl110_draw_line8_bbbp_rgb32,
206
+ pl110_draw_line16_555_bbbp_rgb32,
207
+ pl110_draw_line32_bbbp_rgb32,
208
+ pl110_draw_line16_bbbp_rgb32,
209
+ pl110_draw_line12_bbbp_rgb32,
210
+
211
+ pl110_draw_line1_lbbp_rgb32,
212
+ pl110_draw_line2_lbbp_rgb32,
213
+ pl110_draw_line4_lbbp_rgb32,
214
+ pl110_draw_line8_lbbp_rgb32,
215
+ pl110_draw_line16_555_lbbp_rgb32,
216
+ pl110_draw_line32_lbbp_rgb32,
217
+ pl110_draw_line16_lbbp_rgb32,
218
+ pl110_draw_line12_lbbp_rgb32,
34
+};
219
+};
35
+
220
+
36
/* Create an alias of an entire original MemoryRegion @orig
221
+#undef BITS
37
* located at @base in the memory map.
222
+#undef COPY_PIXEL
38
*/
223
+
39
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
224
40
MPS2SCC *scc = opaque;
225
static int pl110_enabled(PL110State *s)
41
DeviceState *sccdev;
226
{
42
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
43
+ uint32_t i;
44
45
object_initialize_child(OBJECT(mms), "scc", scc, TYPE_MPS2_SCC);
46
sccdev = DEVICE(scc);
47
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
48
qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
49
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
50
- /* This will need to be per-FPGA image eventually */
51
- qdev_prop_set_uint32(sccdev, "len-oscclk", 3);
52
- qdev_prop_set_uint32(sccdev, "oscclk[0]", 40000000);
53
- qdev_prop_set_uint32(sccdev, "oscclk[1]", 24580000);
54
- qdev_prop_set_uint32(sccdev, "oscclk[2]", 25000000);
55
+ qdev_prop_set_uint32(sccdev, "len-oscclk", mmc->len_oscclk);
56
+ for (i = 0; i < mmc->len_oscclk; i++) {
57
+ g_autofree char *propname = g_strdup_printf("oscclk[%u]", i);
58
+ qdev_prop_set_uint32(sccdev, propname, mmc->oscclk[i]);
59
+ }
60
sysbus_realize(SYS_BUS_DEVICE(scc), &error_fatal);
61
return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
62
}
63
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
64
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
65
mmc->scc_id = 0x41045050;
66
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
67
+ mmc->oscclk = an505_oscclk;
68
+ mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
69
mmc->armsse_type = TYPE_IOTKIT;
70
}
71
72
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
73
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
74
mmc->scc_id = 0x41045210;
75
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
76
+ mmc->oscclk = an505_oscclk; /* AN521 is the same as AN505 here */
77
+ mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
78
mmc->armsse_type = TYPE_SSE200;
79
}
80
81
--
227
--
82
2.20.1
228
2.20.1
83
229
84
230
diff view generated by jsdifflib
1
The AN524 has more interrupt lines than the AN505 and AN521; make
1
BITS is always 32, so remove all uses of it from the template header,
2
numirq board-specific rather than a compile-time constant.
2
by dropping the trailing '32' from the draw function names and
3
3
not constructing the name of rgb_to_pixel32() via the glue() macro.
4
Since the difference is small (92 on the current boards and 95 on the
5
new one) we don't dynamically allocate the cpu_irq_splitter[] array
6
but leave it as a fixed length array whose size is the maximum needed
7
for any of the boards.
8
4
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210211141515.8755-4-peter.maydell@linaro.org
12
Message-id: 20210215115138.20465-10-peter.maydell@linaro.org
13
---
8
---
14
hw/arm/mps2-tz.c | 15 ++++++++++-----
9
hw/display/pl110_template.h | 20 +++----
15
1 file changed, 10 insertions(+), 5 deletions(-)
10
hw/display/pl110.c | 113 ++++++++++++++++++------------------
16
11
2 files changed, 65 insertions(+), 68 deletions(-)
17
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
12
13
diff --git a/hw/display/pl110_template.h b/hw/display/pl110_template.h
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/mps2-tz.c
15
--- a/hw/display/pl110_template.h
20
+++ b/hw/arm/mps2-tz.c
16
+++ b/hw/display/pl110_template.h
21
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@
22
#include "hw/qdev-clock.h"
18
#endif
23
#include "qom/object.h"
19
24
20
#if ORDER == 0
25
-#define MPS2TZ_NUMIRQ 92
21
-#define NAME glue(glue(lblp_, BORDER), BITS)
26
+#define MPS2TZ_NUMIRQ_MAX 92
22
+#define NAME glue(lblp_, BORDER)
27
23
#ifdef HOST_WORDS_BIGENDIAN
28
typedef enum MPS2TZFPGAType {
24
#define SWAP_WORDS 1
29
FPGA_AN505,
25
#endif
30
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
26
#elif ORDER == 1
31
const uint32_t *oscclk;
27
-#define NAME glue(glue(bbbp_, BORDER), BITS)
32
uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
28
+#define NAME glue(bbbp_, BORDER)
33
bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
29
#ifndef HOST_WORDS_BIGENDIAN
34
+ int numirq; /* Number of external interrupts */
30
#define SWAP_WORDS 1
35
const char *armsse_type;
31
#endif
32
#else
33
#define SWAP_PIXELS 1
34
-#define NAME glue(glue(lbbp_, BORDER), BITS)
35
+#define NAME glue(lbbp_, BORDER)
36
#ifdef HOST_WORDS_BIGENDIAN
37
#define SWAP_WORDS 1
38
#endif
39
@@ -XXX,XX +XXX,XX @@ static void glue(pl110_draw_line16_,NAME)(void *opaque, uint8_t *d, const uint8_
40
MSB = (data & 0x1f) << 3;
41
data >>= 5;
42
#endif
43
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
44
+ COPY_PIXEL(d, rgb_to_pixel32(r, g, b));
45
LSB = (data & 0x1f) << 3;
46
data >>= 5;
47
g = (data & 0x3f) << 2;
48
data >>= 6;
49
MSB = (data & 0x1f) << 3;
50
data >>= 5;
51
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
52
+ COPY_PIXEL(d, rgb_to_pixel32(r, g, b));
53
#undef MSB
54
#undef LSB
55
width -= 2;
56
@@ -XXX,XX +XXX,XX @@ static void glue(pl110_draw_line32_,NAME)(void *opaque, uint8_t *d, const uint8_
57
g = (data >> 16) & 0xff;
58
MSB = (data >> 8) & 0xff;
59
#endif
60
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
61
+ COPY_PIXEL(d, rgb_to_pixel32(r, g, b));
62
#undef MSB
63
#undef LSB
64
width--;
65
@@ -XXX,XX +XXX,XX @@ static void glue(pl110_draw_line16_555_,NAME)(void *opaque, uint8_t *d, const ui
66
data >>= 5;
67
MSB = (data & 0x1f) << 3;
68
data >>= 5;
69
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
70
+ COPY_PIXEL(d, rgb_to_pixel32(r, g, b));
71
LSB = (data & 0x1f) << 3;
72
data >>= 5;
73
g = (data & 0x1f) << 3;
74
data >>= 5;
75
MSB = (data & 0x1f) << 3;
76
data >>= 6;
77
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
78
+ COPY_PIXEL(d, rgb_to_pixel32(r, g, b));
79
#undef MSB
80
#undef LSB
81
width -= 2;
82
@@ -XXX,XX +XXX,XX @@ static void glue(pl110_draw_line12_,NAME)(void *opaque, uint8_t *d, const uint8_
83
data >>= 4;
84
MSB = (data & 0xf) << 4;
85
data >>= 8;
86
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
87
+ COPY_PIXEL(d, rgb_to_pixel32(r, g, b));
88
LSB = (data & 0xf) << 4;
89
data >>= 4;
90
g = (data & 0xf) << 4;
91
data >>= 4;
92
MSB = (data & 0xf) << 4;
93
data >>= 8;
94
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
95
+ COPY_PIXEL(d, rgb_to_pixel32(r, g, b));
96
#undef MSB
97
#undef LSB
98
width -= 2;
99
diff --git a/hw/display/pl110.c b/hw/display/pl110.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/hw/display/pl110.c
102
+++ b/hw/display/pl110.c
103
@@ -XXX,XX +XXX,XX @@ static const unsigned char *idregs[] = {
104
pl111_id
36
};
105
};
37
106
38
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
107
-#define BITS 32
39
SplitIRQ sec_resp_splitter;
108
#define COPY_PIXEL(to, from) do { *(uint32_t *)to = from; to += 4; } while (0)
40
qemu_or_irq uart_irq_orgate;
109
41
DeviceState *lan9118;
110
#undef RGB
42
- SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ];
111
@@ -XXX,XX +XXX,XX @@ static const unsigned char *idregs[] = {
43
+ SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ_MAX];
112
#include "pl110_template.h"
44
Clock *sysclk;
113
#undef BORDER
45
Clock *s32kclk;
114
46
};
115
-static drawfn pl110_draw_fn_32[48] = {
47
@@ -XXX,XX +XXX,XX @@ static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
116
- pl110_draw_line1_lblp_bgr32,
117
- pl110_draw_line2_lblp_bgr32,
118
- pl110_draw_line4_lblp_bgr32,
119
- pl110_draw_line8_lblp_bgr32,
120
- pl110_draw_line16_555_lblp_bgr32,
121
- pl110_draw_line32_lblp_bgr32,
122
- pl110_draw_line16_lblp_bgr32,
123
- pl110_draw_line12_lblp_bgr32,
124
-
125
- pl110_draw_line1_bbbp_bgr32,
126
- pl110_draw_line2_bbbp_bgr32,
127
- pl110_draw_line4_bbbp_bgr32,
128
- pl110_draw_line8_bbbp_bgr32,
129
- pl110_draw_line16_555_bbbp_bgr32,
130
- pl110_draw_line32_bbbp_bgr32,
131
- pl110_draw_line16_bbbp_bgr32,
132
- pl110_draw_line12_bbbp_bgr32,
133
-
134
- pl110_draw_line1_lbbp_bgr32,
135
- pl110_draw_line2_lbbp_bgr32,
136
- pl110_draw_line4_lbbp_bgr32,
137
- pl110_draw_line8_lbbp_bgr32,
138
- pl110_draw_line16_555_lbbp_bgr32,
139
- pl110_draw_line32_lbbp_bgr32,
140
- pl110_draw_line16_lbbp_bgr32,
141
- pl110_draw_line12_lbbp_bgr32,
142
-
143
- pl110_draw_line1_lblp_rgb32,
144
- pl110_draw_line2_lblp_rgb32,
145
- pl110_draw_line4_lblp_rgb32,
146
- pl110_draw_line8_lblp_rgb32,
147
- pl110_draw_line16_555_lblp_rgb32,
148
- pl110_draw_line32_lblp_rgb32,
149
- pl110_draw_line16_lblp_rgb32,
150
- pl110_draw_line12_lblp_rgb32,
151
-
152
- pl110_draw_line1_bbbp_rgb32,
153
- pl110_draw_line2_bbbp_rgb32,
154
- pl110_draw_line4_bbbp_rgb32,
155
- pl110_draw_line8_bbbp_rgb32,
156
- pl110_draw_line16_555_bbbp_rgb32,
157
- pl110_draw_line32_bbbp_rgb32,
158
- pl110_draw_line16_bbbp_rgb32,
159
- pl110_draw_line12_bbbp_rgb32,
160
-
161
- pl110_draw_line1_lbbp_rgb32,
162
- pl110_draw_line2_lbbp_rgb32,
163
- pl110_draw_line4_lbbp_rgb32,
164
- pl110_draw_line8_lbbp_rgb32,
165
- pl110_draw_line16_555_lbbp_rgb32,
166
- pl110_draw_line32_lbbp_rgb32,
167
- pl110_draw_line16_lbbp_rgb32,
168
- pl110_draw_line12_lbbp_rgb32,
169
-};
170
-
171
-#undef BITS
172
#undef COPY_PIXEL
173
174
+static drawfn pl110_draw_fn_32[48] = {
175
+ pl110_draw_line1_lblp_bgr,
176
+ pl110_draw_line2_lblp_bgr,
177
+ pl110_draw_line4_lblp_bgr,
178
+ pl110_draw_line8_lblp_bgr,
179
+ pl110_draw_line16_555_lblp_bgr,
180
+ pl110_draw_line32_lblp_bgr,
181
+ pl110_draw_line16_lblp_bgr,
182
+ pl110_draw_line12_lblp_bgr,
183
+
184
+ pl110_draw_line1_bbbp_bgr,
185
+ pl110_draw_line2_bbbp_bgr,
186
+ pl110_draw_line4_bbbp_bgr,
187
+ pl110_draw_line8_bbbp_bgr,
188
+ pl110_draw_line16_555_bbbp_bgr,
189
+ pl110_draw_line32_bbbp_bgr,
190
+ pl110_draw_line16_bbbp_bgr,
191
+ pl110_draw_line12_bbbp_bgr,
192
+
193
+ pl110_draw_line1_lbbp_bgr,
194
+ pl110_draw_line2_lbbp_bgr,
195
+ pl110_draw_line4_lbbp_bgr,
196
+ pl110_draw_line8_lbbp_bgr,
197
+ pl110_draw_line16_555_lbbp_bgr,
198
+ pl110_draw_line32_lbbp_bgr,
199
+ pl110_draw_line16_lbbp_bgr,
200
+ pl110_draw_line12_lbbp_bgr,
201
+
202
+ pl110_draw_line1_lblp_rgb,
203
+ pl110_draw_line2_lblp_rgb,
204
+ pl110_draw_line4_lblp_rgb,
205
+ pl110_draw_line8_lblp_rgb,
206
+ pl110_draw_line16_555_lblp_rgb,
207
+ pl110_draw_line32_lblp_rgb,
208
+ pl110_draw_line16_lblp_rgb,
209
+ pl110_draw_line12_lblp_rgb,
210
+
211
+ pl110_draw_line1_bbbp_rgb,
212
+ pl110_draw_line2_bbbp_rgb,
213
+ pl110_draw_line4_bbbp_rgb,
214
+ pl110_draw_line8_bbbp_rgb,
215
+ pl110_draw_line16_555_bbbp_rgb,
216
+ pl110_draw_line32_bbbp_rgb,
217
+ pl110_draw_line16_bbbp_rgb,
218
+ pl110_draw_line12_bbbp_rgb,
219
+
220
+ pl110_draw_line1_lbbp_rgb,
221
+ pl110_draw_line2_lbbp_rgb,
222
+ pl110_draw_line4_lbbp_rgb,
223
+ pl110_draw_line8_lbbp_rgb,
224
+ pl110_draw_line16_555_lbbp_rgb,
225
+ pl110_draw_line32_lbbp_rgb,
226
+ pl110_draw_line16_lbbp_rgb,
227
+ pl110_draw_line12_lbbp_rgb,
228
+};
229
230
static int pl110_enabled(PL110State *s)
48
{
231
{
49
/* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
50
MachineClass *mc = MACHINE_GET_CLASS(mms);
51
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
52
53
- assert(irqno < MPS2TZ_NUMIRQ);
54
+ assert(irqno < mmc->numirq);
55
56
if (mc->max_cpus > 1) {
57
return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
58
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
59
iotkitdev = DEVICE(&mms->iotkit);
60
object_property_set_link(OBJECT(&mms->iotkit), "memory",
61
OBJECT(system_memory), &error_abort);
62
- qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", MPS2TZ_NUMIRQ);
63
+ qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", mmc->numirq);
64
qdev_connect_clock_in(iotkitdev, "MAINCLK", mms->sysclk);
65
qdev_connect_clock_in(iotkitdev, "S32KCLK", mms->s32kclk);
66
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
67
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
68
* board. If there is only one CPU, we can just wire the device IRQ
69
* directly to the SSE's IRQ input.
70
*/
71
+ assert(mmc->numirq <= MPS2TZ_NUMIRQ_MAX);
72
if (mc->max_cpus > 1) {
73
- for (i = 0; i < MPS2TZ_NUMIRQ; i++) {
74
+ for (i = 0; i < mmc->numirq; i++) {
75
char *name = g_strdup_printf("mps2-irq-splitter%d", i);
76
SplitIRQ *splitter = &mms->cpu_irq_splitter[i];
77
78
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
79
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
80
mmc->fpgaio_num_leds = 2;
81
mmc->fpgaio_has_switches = false;
82
+ mmc->numirq = 92;
83
mmc->armsse_type = TYPE_IOTKIT;
84
}
85
86
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
87
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
88
mmc->fpgaio_num_leds = 2;
89
mmc->fpgaio_has_switches = false;
90
+ mmc->numirq = 92;
91
mmc->armsse_type = TYPE_SSE200;
92
}
93
94
--
232
--
95
2.20.1
233
2.20.1
96
234
97
235
diff view generated by jsdifflib
1
Add support for the mps3-an524 board; this is an SSE-200 based FPGA
1
For a long time now the UI layer has guaranteed that the console
2
image, like the existing mps2-an521. It has a usefully larger amount
2
surface is always 32 bits per pixel. Remove the legacy dead code
3
of RAM, and a PL031 RTC, as well as some more minor differences.
3
from the pxa2xx_lcd display device which was handling the possibility
4
4
that the console surface was some other format.
5
In real hardware this image runs on a newer generation of the FPGA
6
board, the MPS3 rather than the older MPS2. Architecturally the two
7
boards are similar, so we implement the MPS3 boards in the mps2-tz.c
8
file as variations of the existing MPS2 boards.
9
5
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
12
Message-id: 20210215115138.20465-21-peter.maydell@linaro.org
8
Message-id: 20210211141515.8755-5-peter.maydell@linaro.org
13
---
9
---
14
hw/arm/mps2-tz.c | 139 +++++++++++++++++++++++++++++++++++++++++++++--
10
hw/display/pxa2xx_lcd.c | 79 +++++++++--------------------------------
15
1 file changed, 135 insertions(+), 4 deletions(-)
11
1 file changed, 17 insertions(+), 62 deletions(-)
16
12
17
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
13
diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/mps2-tz.c
15
--- a/hw/display/pxa2xx_lcd.c
20
+++ b/hw/arm/mps2-tz.c
16
+++ b/hw/display/pxa2xx_lcd.c
21
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ struct PXA2xxLCDState {
22
* This source file covers the following FPGA images, for TrustZone cores:
18
23
* "mps2-an505" -- Cortex-M33 as documented in ARM Application Note AN505
19
int invalidated;
24
* "mps2-an521" -- Dual Cortex-M33 as documented in Application Note AN521
20
QemuConsole *con;
25
+ * "mps2-an524" -- Dual Cortex-M33 as documented in Application Note AN524
21
- drawfn *line_fn[2];
26
*
22
int dest_width;
27
* Links to the TRM for the board itself and to the various Application
23
int xres, yres;
28
* Notes which document the FPGA images can be found here:
24
int pal_for;
29
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ typedef struct QEMU_PACKED {
30
* http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
26
#define LDCMD_SOFINT    (1 << 22)
31
* Application Note AN521:
27
#define LDCMD_PAL    (1 << 26)
32
* http://infocenter.arm.com/help/topic/com.arm.doc.dai0521c/index.html
28
33
+ * Application Note AN524:
29
+#define BITS 32
34
+ * https://developer.arm.com/documentation/dai0524/latest/
30
+#include "pxa2xx_template.h"
35
*
36
* The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
37
* (ARM ECM0601256) for the details of some of the device layout:
38
* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
39
- * Similarly, the AN521 uses the SSE-200, and the SSE-200 TRM defines
40
+ * Similarly, the AN521 and AN524 use the SSE-200, and the SSE-200 TRM defines
41
* most of the device layout:
42
* http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
43
*
44
@@ -XXX,XX +XXX,XX @@
45
#include "hw/qdev-clock.h"
46
#include "qom/object.h"
47
48
-#define MPS2TZ_NUMIRQ_MAX 92
49
+#define MPS2TZ_NUMIRQ_MAX 95
50
#define MPS2TZ_RAM_MAX 4
51
52
typedef enum MPS2TZFPGAType {
53
FPGA_AN505,
54
FPGA_AN521,
55
+ FPGA_AN524,
56
} MPS2TZFPGAType;
57
58
/*
59
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
60
TZPPC ppc[5];
61
TZMPC mpc[3];
62
PL022State spi[5];
63
- ArmSbconI2CState i2c[4];
64
+ ArmSbconI2CState i2c[5];
65
UnimplementedDeviceState i2s_audio;
66
UnimplementedDeviceState gpio[4];
67
UnimplementedDeviceState gfx;
68
+ UnimplementedDeviceState cldc;
69
+ UnimplementedDeviceState rtc;
70
PL080State dma[4];
71
TZMSC msc[4];
72
- CMSDKAPBUART uart[5];
73
+ CMSDKAPBUART uart[6];
74
SplitIRQ sec_resp_splitter;
75
qemu_or_irq uart_irq_orgate;
76
DeviceState *lan9118;
77
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
78
#define TYPE_MPS2TZ_MACHINE "mps2tz"
79
#define TYPE_MPS2TZ_AN505_MACHINE MACHINE_TYPE_NAME("mps2-an505")
80
#define TYPE_MPS2TZ_AN521_MACHINE MACHINE_TYPE_NAME("mps2-an521")
81
+#define TYPE_MPS3TZ_AN524_MACHINE MACHINE_TYPE_NAME("mps3-an524")
82
83
OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
84
85
@@ -XXX,XX +XXX,XX @@ static const uint32_t an505_oscclk[] = {
86
25000000,
87
};
88
89
+static const uint32_t an524_oscclk[] = {
90
+ 24000000,
91
+ 32000000,
92
+ 50000000,
93
+ 50000000,
94
+ 24576000,
95
+ 23750000,
96
+};
97
+
31
+
98
static const RAMInfo an505_raminfo[] = { {
32
/* Route internal interrupt lines to the global IC */
99
.name = "ssram-0",
33
static void pxa2xx_lcdc_int_update(PXA2xxLCDState *s)
100
.base = 0x00000000,
101
@@ -XXX,XX +XXX,XX @@ static const RAMInfo an505_raminfo[] = { {
102
},
103
};
104
105
+static const RAMInfo an524_raminfo[] = { {
106
+ .name = "bram",
107
+ .base = 0x00000000,
108
+ .size = 512 * KiB,
109
+ .mpc = 0,
110
+ .mrindex = 0,
111
+ }, {
112
+ .name = "sram",
113
+ .base = 0x20000000,
114
+ .size = 32 * 4 * KiB,
115
+ .mpc = 1,
116
+ .mrindex = 1,
117
+ }, {
118
+ /* We don't model QSPI flash yet; for now expose it as simple ROM */
119
+ .name = "QSPI",
120
+ .base = 0x28000000,
121
+ .size = 8 * MiB,
122
+ .mpc = 1,
123
+ .mrindex = 2,
124
+ .flags = IS_ROM,
125
+ }, {
126
+ .name = "DDR",
127
+ .base = 0x60000000,
128
+ .size = 2 * GiB,
129
+ .mpc = 2,
130
+ .mrindex = -1,
131
+ }, {
132
+ .name = NULL,
133
+ },
134
+};
135
+
136
static const RAMInfo *find_raminfo_for_mpc(MPS2TZMachineState *mms, int mpc)
137
{
34
{
138
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
35
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp)
139
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
140
},
141
};
142
143
+ const PPCInfo an524_ppcs[] = { {
144
+ .name = "apb_ppcexp0",
145
+ .ports = {
146
+ { "bram-mpc", make_mpc, &mms->mpc[0], 0x58007000, 0x1000 },
147
+ { "qspi-mpc", make_mpc, &mms->mpc[1], 0x58008000, 0x1000 },
148
+ { "ddr-mpc", make_mpc, &mms->mpc[2], 0x58009000, 0x1000 },
149
+ },
150
+ }, {
151
+ .name = "apb_ppcexp1",
152
+ .ports = {
153
+ { "i2c0", make_i2c, &mms->i2c[0], 0x41200000, 0x1000 },
154
+ { "i2c1", make_i2c, &mms->i2c[1], 0x41201000, 0x1000 },
155
+ { "spi0", make_spi, &mms->spi[0], 0x41202000, 0x1000, { 52 } },
156
+ { "spi1", make_spi, &mms->spi[1], 0x41203000, 0x1000, { 53 } },
157
+ { "spi2", make_spi, &mms->spi[2], 0x41204000, 0x1000, { 54 } },
158
+ { "i2c2", make_i2c, &mms->i2c[2], 0x41205000, 0x1000 },
159
+ { "i2c3", make_i2c, &mms->i2c[3], 0x41206000, 0x1000 },
160
+ { /* port 7 reserved */ },
161
+ { "i2c4", make_i2c, &mms->i2c[4], 0x41208000, 0x1000 },
162
+ },
163
+ }, {
164
+ .name = "apb_ppcexp2",
165
+ .ports = {
166
+ { "scc", make_scc, &mms->scc, 0x41300000, 0x1000 },
167
+ { "i2s-audio", make_unimp_dev, &mms->i2s_audio,
168
+ 0x41301000, 0x1000 },
169
+ { "fpgaio", make_fpgaio, &mms->fpgaio, 0x41302000, 0x1000 },
170
+ { "uart0", make_uart, &mms->uart[0], 0x41303000, 0x1000, { 32, 33, 42 } },
171
+ { "uart1", make_uart, &mms->uart[1], 0x41304000, 0x1000, { 34, 35, 43 } },
172
+ { "uart2", make_uart, &mms->uart[2], 0x41305000, 0x1000, { 36, 37, 44 } },
173
+ { "uart3", make_uart, &mms->uart[3], 0x41306000, 0x1000, { 38, 39, 45 } },
174
+ { "uart4", make_uart, &mms->uart[4], 0x41307000, 0x1000, { 40, 41, 46 } },
175
+ { "uart5", make_uart, &mms->uart[5], 0x41308000, 0x1000, { 124, 125, 126 } },
176
+
177
+ { /* port 9 reserved */ },
178
+ { "clcd", make_unimp_dev, &mms->cldc, 0x4130a000, 0x1000 },
179
+ { "rtc", make_unimp_dev, &mms->rtc, 0x4130b000, 0x1000 },
180
+ },
181
+ }, {
182
+ .name = "ahb_ppcexp0",
183
+ .ports = {
184
+ { "gpio0", make_unimp_dev, &mms->gpio[0], 0x41100000, 0x1000 },
185
+ { "gpio1", make_unimp_dev, &mms->gpio[1], 0x41101000, 0x1000 },
186
+ { "gpio2", make_unimp_dev, &mms->gpio[2], 0x41102000, 0x1000 },
187
+ { "gpio3", make_unimp_dev, &mms->gpio[3], 0x41103000, 0x1000 },
188
+ { "eth", make_eth_dev, NULL, 0x41400000, 0x100000, { 48 } },
189
+ },
190
+ },
191
+ };
192
+
193
switch (mmc->fpga_type) {
194
case FPGA_AN505:
195
case FPGA_AN521:
196
ppcs = an505_ppcs;
197
num_ppcs = ARRAY_SIZE(an505_ppcs);
198
break;
199
+ case FPGA_AN524:
200
+ ppcs = an524_ppcs;
201
+ num_ppcs = ARRAY_SIZE(an524_ppcs);
202
+ break;
203
default:
204
g_assert_not_reached();
205
}
36
}
206
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
207
mps2tz_set_default_ram_info(mmc);
208
}
37
}
209
38
210
+static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
39
+static inline drawfn pxa2xx_drawfn(PXA2xxLCDState *s)
211
+{
40
+{
212
+ MachineClass *mc = MACHINE_CLASS(oc);
41
+ if (s->transp) {
213
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
42
+ return pxa2xx_draw_fn_32t[s->bpp];
214
+
43
+ } else {
215
+ mc->desc = "ARM MPS3 with AN524 FPGA image for dual Cortex-M33";
44
+ return pxa2xx_draw_fn_32[s->bpp];
216
+ mc->default_cpus = 2;
45
+ }
217
+ mc->min_cpus = mc->default_cpus;
218
+ mc->max_cpus = mc->default_cpus;
219
+ mmc->fpga_type = FPGA_AN524;
220
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
221
+ mmc->scc_id = 0x41045240;
222
+ mmc->sysclk_frq = 32 * 1000 * 1000; /* 32MHz */
223
+ mmc->oscclk = an524_oscclk;
224
+ mmc->len_oscclk = ARRAY_SIZE(an524_oscclk);
225
+ mmc->fpgaio_num_leds = 10;
226
+ mmc->fpgaio_has_switches = true;
227
+ mmc->numirq = 95;
228
+ mmc->raminfo = an524_raminfo;
229
+ mmc->armsse_type = TYPE_SSE200;
230
+ mps2tz_set_default_ram_info(mmc);
231
+}
46
+}
232
+
47
+
233
static const TypeInfo mps2tz_info = {
48
static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
234
.name = TYPE_MPS2TZ_MACHINE,
49
hwaddr addr, int *miny, int *maxy)
235
.parent = TYPE_MACHINE,
50
{
236
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mps2tz_an521_info = {
51
DisplaySurface *surface = qemu_console_surface(s->con);
237
.class_init = mps2tz_an521_class_init,
52
int src_width, dest_width;
53
- drawfn fn = NULL;
54
- if (s->dest_width)
55
- fn = s->line_fn[s->transp][s->bpp];
56
+ drawfn fn = pxa2xx_drawfn(s);
57
if (!fn)
58
return;
59
60
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s,
61
{
62
DisplaySurface *surface = qemu_console_surface(s->con);
63
int src_width, dest_width;
64
- drawfn fn = NULL;
65
- if (s->dest_width)
66
- fn = s->line_fn[s->transp][s->bpp];
67
+ drawfn fn = pxa2xx_drawfn(s);
68
if (!fn)
69
return;
70
71
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s,
72
{
73
DisplaySurface *surface = qemu_console_surface(s->con);
74
int src_width, dest_width;
75
- drawfn fn = NULL;
76
- if (s->dest_width) {
77
- fn = s->line_fn[s->transp][s->bpp];
78
- }
79
+ drawfn fn = pxa2xx_drawfn(s);
80
if (!fn) {
81
return;
82
}
83
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s,
84
{
85
DisplaySurface *surface = qemu_console_surface(s->con);
86
int src_width, dest_width;
87
- drawfn fn = NULL;
88
- if (s->dest_width) {
89
- fn = s->line_fn[s->transp][s->bpp];
90
- }
91
+ drawfn fn = pxa2xx_drawfn(s);
92
if (!fn) {
93
return;
94
}
95
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pxa2xx_lcdc = {
96
}
238
};
97
};
239
98
240
+static const TypeInfo mps3tz_an524_info = {
99
-#define BITS 8
241
+ .name = TYPE_MPS3TZ_AN524_MACHINE,
100
-#include "pxa2xx_template.h"
242
+ .parent = TYPE_MPS2TZ_MACHINE,
101
-#define BITS 15
243
+ .class_init = mps3tz_an524_class_init,
102
-#include "pxa2xx_template.h"
244
+};
103
-#define BITS 16
245
+
104
-#include "pxa2xx_template.h"
246
static void mps2tz_machine_init(void)
105
-#define BITS 24
106
-#include "pxa2xx_template.h"
107
-#define BITS 32
108
-#include "pxa2xx_template.h"
109
-
110
static const GraphicHwOps pxa2xx_ops = {
111
.invalidate = pxa2xx_invalidate_display,
112
.gfx_update = pxa2xx_update_display,
113
@@ -XXX,XX +XXX,XX @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
114
hwaddr base, qemu_irq irq)
247
{
115
{
248
type_register_static(&mps2tz_info);
116
PXA2xxLCDState *s;
249
type_register_static(&mps2tz_an505_info);
117
- DisplaySurface *surface;
250
type_register_static(&mps2tz_an521_info);
118
251
+ type_register_static(&mps3tz_an524_info);
119
s = (PXA2xxLCDState *) g_malloc0(sizeof(PXA2xxLCDState));
252
}
120
s->invalidated = 1;
253
121
@@ -XXX,XX +XXX,XX @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
254
type_init(mps2tz_machine_init);
122
memory_region_add_subregion(sysmem, base, &s->iomem);
123
124
s->con = graphic_console_init(NULL, 0, &pxa2xx_ops, s);
125
- surface = qemu_console_surface(s->con);
126
-
127
- switch (surface_bits_per_pixel(surface)) {
128
- case 0:
129
- s->dest_width = 0;
130
- break;
131
- case 8:
132
- s->line_fn[0] = pxa2xx_draw_fn_8;
133
- s->line_fn[1] = pxa2xx_draw_fn_8t;
134
- s->dest_width = 1;
135
- break;
136
- case 15:
137
- s->line_fn[0] = pxa2xx_draw_fn_15;
138
- s->line_fn[1] = pxa2xx_draw_fn_15t;
139
- s->dest_width = 2;
140
- break;
141
- case 16:
142
- s->line_fn[0] = pxa2xx_draw_fn_16;
143
- s->line_fn[1] = pxa2xx_draw_fn_16t;
144
- s->dest_width = 2;
145
- break;
146
- case 24:
147
- s->line_fn[0] = pxa2xx_draw_fn_24;
148
- s->line_fn[1] = pxa2xx_draw_fn_24t;
149
- s->dest_width = 3;
150
- break;
151
- case 32:
152
- s->line_fn[0] = pxa2xx_draw_fn_32;
153
- s->line_fn[1] = pxa2xx_draw_fn_32t;
154
- s->dest_width = 4;
155
- break;
156
- default:
157
- fprintf(stderr, "%s: Bad color depth\n", __func__);
158
- exit(1);
159
- }
160
+ s->dest_width = 4;
161
162
vmstate_register(NULL, 0, &vmstate_pxa2xx_lcdc, s);
163
255
--
164
--
256
2.20.1
165
2.20.1
257
166
258
167
diff view generated by jsdifflib
1
Set the FPGAIO num-leds and have-switches properties explicitly
1
Since the dest_width is now always 4 because the output surface is
2
per-board, rather than relying on the defaults. The AN505 and AN521
2
32bpp, we can replace the dest_width state field with a constant.
3
both have the same settings as the default values, but the AN524 will
4
be different.
5
3
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210211141515.8755-6-peter.maydell@linaro.org
9
Message-id: 20210215115138.20465-8-peter.maydell@linaro.org
10
---
7
---
11
hw/arm/mps2-tz.c | 9 +++++++++
8
hw/display/pxa2xx_lcd.c | 20 +++++++++++---------
12
1 file changed, 9 insertions(+)
9
1 file changed, 11 insertions(+), 9 deletions(-)
13
10
14
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
11
diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c
15
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/mps2-tz.c
13
--- a/hw/display/pxa2xx_lcd.c
17
+++ b/hw/arm/mps2-tz.c
14
+++ b/hw/display/pxa2xx_lcd.c
18
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
15
@@ -XXX,XX +XXX,XX @@ typedef struct QEMU_PACKED {
19
uint32_t sysclk_frq; /* Main SYSCLK frequency in Hz */
16
#define LDCMD_SOFINT    (1 << 22)
20
uint32_t len_oscclk;
17
#define LDCMD_PAL    (1 << 26)
21
const uint32_t *oscclk;
18
22
+ uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
19
+/* Size of a pixel in the QEMU UI output surface, in bytes */
23
+ bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
20
+#define DEST_PIXEL_WIDTH 4
24
const char *armsse_type;
21
+
25
};
22
#define BITS 32
26
23
#include "pxa2xx_template.h"
27
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
24
28
const char *name, hwaddr size)
25
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
29
{
26
else if (s->bpp > pxa_lcdc_8bpp)
30
MPS2FPGAIO *fpgaio = opaque;
27
src_width *= 2;
31
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
28
32
29
- dest_width = s->xres * s->dest_width;
33
object_initialize_child(OBJECT(mms), "fpgaio", fpgaio, TYPE_MPS2_FPGAIO);
30
+ dest_width = s->xres * DEST_PIXEL_WIDTH;
34
+ qdev_prop_set_uint32(DEVICE(fpgaio), "num-leds", mmc->fpgaio_num_leds);
31
*miny = 0;
35
+ qdev_prop_set_bit(DEVICE(fpgaio), "has-switches", mmc->fpgaio_has_switches);
32
if (s->invalidated) {
36
sysbus_realize(SYS_BUS_DEVICE(fpgaio), &error_fatal);
33
framebuffer_update_memory_section(&s->fbsection, s->sysmem,
37
return sysbus_mmio_get_region(SYS_BUS_DEVICE(fpgaio), 0);
34
addr, s->yres, src_width);
35
}
36
framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
37
- src_width, dest_width, s->dest_width,
38
+ src_width, dest_width, DEST_PIXEL_WIDTH,
39
s->invalidated,
40
fn, s->dma_ch[0].palette, miny, maxy);
38
}
41
}
39
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
42
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s,
40
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
43
else if (s->bpp > pxa_lcdc_8bpp)
41
mmc->oscclk = an505_oscclk;
44
src_width *= 2;
42
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
45
43
+ mmc->fpgaio_num_leds = 2;
46
- dest_width = s->yres * s->dest_width;
44
+ mmc->fpgaio_has_switches = false;
47
+ dest_width = s->yres * DEST_PIXEL_WIDTH;
45
mmc->armsse_type = TYPE_IOTKIT;
48
*miny = 0;
49
if (s->invalidated) {
50
framebuffer_update_memory_section(&s->fbsection, s->sysmem,
51
addr, s->yres, src_width);
52
}
53
framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
54
- src_width, s->dest_width, -dest_width,
55
+ src_width, DEST_PIXEL_WIDTH, -dest_width,
56
s->invalidated,
57
fn, s->dma_ch[0].palette,
58
miny, maxy);
59
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s,
60
src_width *= 2;
61
}
62
63
- dest_width = s->xres * s->dest_width;
64
+ dest_width = s->xres * DEST_PIXEL_WIDTH;
65
*miny = 0;
66
if (s->invalidated) {
67
framebuffer_update_memory_section(&s->fbsection, s->sysmem,
68
addr, s->yres, src_width);
69
}
70
framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
71
- src_width, -dest_width, -s->dest_width,
72
+ src_width, -dest_width, -DEST_PIXEL_WIDTH,
73
s->invalidated,
74
fn, s->dma_ch[0].palette, miny, maxy);
46
}
75
}
47
76
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s,
48
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
77
src_width *= 2;
49
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
78
}
50
mmc->oscclk = an505_oscclk; /* AN521 is the same as AN505 here */
79
51
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
80
- dest_width = s->yres * s->dest_width;
52
+ mmc->fpgaio_num_leds = 2;
81
+ dest_width = s->yres * DEST_PIXEL_WIDTH;
53
+ mmc->fpgaio_has_switches = false;
82
*miny = 0;
54
mmc->armsse_type = TYPE_SSE200;
83
if (s->invalidated) {
55
}
84
framebuffer_update_memory_section(&s->fbsection, s->sysmem,
85
addr, s->yres, src_width);
86
}
87
framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
88
- src_width, -s->dest_width, dest_width,
89
+ src_width, -DEST_PIXEL_WIDTH, dest_width,
90
s->invalidated,
91
fn, s->dma_ch[0].palette,
92
miny, maxy);
93
@@ -XXX,XX +XXX,XX @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
94
memory_region_add_subregion(sysmem, base, &s->iomem);
95
96
s->con = graphic_console_init(NULL, 0, &pxa2xx_ops, s);
97
- s->dest_width = 4;
98
99
vmstate_register(NULL, 0, &vmstate_pxa2xx_lcdc, s);
56
100
57
--
101
--
58
2.20.1
102
2.20.1
59
103
60
104
diff view generated by jsdifflib
1
Now the template header is included only for BITS==32, expand
1
Now that BITS is always 32, expand out all its uses in the template
2
out all the macros that depended on the BITS setting.
2
header, including removing now-useless uses of the glue() macro.
3
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
6
Message-id: 20210215103215.4944-4-peter.maydell@linaro.org
6
Message-id: 20210211141515.8755-7-peter.maydell@linaro.org
7
---
7
---
8
hw/display/tc6393xb_template.h | 35 ++++------------------------------
8
hw/display/pxa2xx_template.h | 110 ++++++++++++++---------------------
9
1 file changed, 4 insertions(+), 31 deletions(-)
9
1 file changed, 45 insertions(+), 65 deletions(-)
10
10
11
diff --git a/hw/display/tc6393xb_template.h b/hw/display/tc6393xb_template.h
11
diff --git a/hw/display/pxa2xx_template.h b/hw/display/pxa2xx_template.h
12
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/display/tc6393xb_template.h
13
--- a/hw/display/pxa2xx_template.h
14
+++ b/hw/display/tc6393xb_template.h
14
+++ b/hw/display/pxa2xx_template.h
15
@@ -XXX,XX +XXX,XX @@
15
@@ -XXX,XX +XXX,XX @@
16
* with this program; if not, see <http://www.gnu.org/licenses/>.
17
*/
16
*/
18
17
18
# define SKIP_PIXEL(to)        to += deststep
19
-#if BITS == 8
19
-#if BITS == 8
20
-# define SET_PIXEL(addr, color) (*(uint8_t *)addr = color)
20
-# define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0)
21
-#elif BITS == 15 || BITS == 16
21
-#elif BITS == 15 || BITS == 16
22
-# define SET_PIXEL(addr, color) (*(uint16_t *)addr = color)
22
-# define COPY_PIXEL(to, from) \
23
- do { \
24
- *(uint16_t *) to = from; \
25
- SKIP_PIXEL(to); \
26
- } while (0)
23
-#elif BITS == 24
27
-#elif BITS == 24
24
-# define SET_PIXEL(addr, color) \
28
-# define COPY_PIXEL(to, from) \
25
- do { \
29
- do { \
26
- addr[0] = color; \
30
- *(uint16_t *) to = from; \
27
- addr[1] = (color) >> 8; \
31
- *(to + 2) = (from) >> 16; \
28
- addr[2] = (color) >> 16; \
32
- SKIP_PIXEL(to); \
29
- } while (0)
33
- } while (0)
30
-#elif BITS == 32
34
-#elif BITS == 32
31
-# define SET_PIXEL(addr, color) (*(uint32_t *)addr = color)
35
# define COPY_PIXEL(to, from) \
36
do { \
37
*(uint32_t *) to = from; \
38
SKIP_PIXEL(to); \
39
} while (0)
32
-#else
40
-#else
33
-# error unknown bit depth
41
-# error unknown bit depth
34
-#endif
42
-#endif
35
-
43
36
-
44
#ifdef HOST_WORDS_BIGENDIAN
37
-static void glue(tc6393xb_draw_graphic, BITS)(TC6393xbState *s)
45
# define SWAP_WORDS    1
38
+static void tc6393xb_draw_graphic32(TC6393xbState *s)
46
@@ -XXX,XX +XXX,XX @@
39
{
47
#define FN_2(x)        FN(x + 1) FN(x)
40
DisplaySurface *surface = qemu_console_surface(s->con);
48
#define FN_4(x)        FN_2(x + 2) FN_2(x)
41
int i;
49
42
@@ -XXX,XX +XXX,XX @@ static void glue(tc6393xb_draw_graphic, BITS)(TC6393xbState *s)
50
-static void glue(pxa2xx_draw_line2_, BITS)(void *opaque,
43
data_buffer = s->vram_ptr;
51
+static void pxa2xx_draw_line2(void *opaque,
44
data_display = surface_data(surface);
52
uint8_t *dest, const uint8_t *src, int width, int deststep)
45
for(i = 0; i < s->scr_height; i++) {
53
{
46
-#if (BITS == 16)
54
uint32_t *palette = opaque;
47
- memcpy(data_display, data_buffer, s->scr_width * 2);
55
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line2_, BITS)(void *opaque,
48
- data_buffer += s->scr_width;
56
}
49
- data_display += surface_stride(surface);
57
}
50
-#else
58
51
int j;
59
-static void glue(pxa2xx_draw_line4_, BITS)(void *opaque,
52
- for (j = 0; j < s->scr_width; j++, data_display += BITS / 8, data_buffer++) {
60
+static void pxa2xx_draw_line4(void *opaque,
53
+ for (j = 0; j < s->scr_width; j++, data_display += 4, data_buffer++) {
61
uint8_t *dest, const uint8_t *src, int width, int deststep)
54
uint16_t color = *data_buffer;
62
{
55
- uint32_t dest_color = glue(rgb_to_pixel, BITS)(
63
uint32_t *palette = opaque;
56
+ uint32_t dest_color = rgb_to_pixel32(
64
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line4_, BITS)(void *opaque,
57
((color & 0xf800) * 0x108) >> 11,
65
}
58
((color & 0x7e0) * 0x41) >> 9,
66
}
59
((color & 0x1f) * 0x21) >> 2
67
60
);
68
-static void glue(pxa2xx_draw_line8_, BITS)(void *opaque,
61
- SET_PIXEL(data_display, dest_color);
69
+static void pxa2xx_draw_line8(void *opaque,
62
+ *(uint32_t *)data_display = dest_color;
70
uint8_t *dest, const uint8_t *src, int width, int deststep)
63
}
71
{
64
-#endif
72
uint32_t *palette = opaque;
65
}
73
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line8_, BITS)(void *opaque,
66
}
74
}
67
-
75
}
76
77
-static void glue(pxa2xx_draw_line16_, BITS)(void *opaque,
78
+static void pxa2xx_draw_line16(void *opaque,
79
uint8_t *dest, const uint8_t *src, int width, int deststep)
80
{
81
uint32_t data;
82
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line16_, BITS)(void *opaque,
83
data >>= 6;
84
r = (data & 0x1f) << 3;
85
data >>= 5;
86
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
87
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
88
b = (data & 0x1f) << 3;
89
data >>= 5;
90
g = (data & 0x3f) << 2;
91
data >>= 6;
92
r = (data & 0x1f) << 3;
93
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
94
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
95
width -= 2;
96
src += 4;
97
}
98
}
99
100
-static void glue(pxa2xx_draw_line16t_, BITS)(void *opaque,
101
+static void pxa2xx_draw_line16t(void *opaque,
102
uint8_t *dest, const uint8_t *src, int width, int deststep)
103
{
104
uint32_t data;
105
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line16t_, BITS)(void *opaque,
106
if (data & 1)
107
SKIP_PIXEL(dest);
108
else
109
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
110
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
111
data >>= 1;
112
b = (data & 0x1f) << 3;
113
data >>= 5;
114
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line16t_, BITS)(void *opaque,
115
if (data & 1)
116
SKIP_PIXEL(dest);
117
else
118
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
119
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
120
width -= 2;
121
src += 4;
122
}
123
}
124
125
-static void glue(pxa2xx_draw_line18_, BITS)(void *opaque,
126
+static void pxa2xx_draw_line18(void *opaque,
127
uint8_t *dest, const uint8_t *src, int width, int deststep)
128
{
129
uint32_t data;
130
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line18_, BITS)(void *opaque,
131
g = (data & 0x3f) << 2;
132
data >>= 6;
133
r = (data & 0x3f) << 2;
134
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
135
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
136
width -= 1;
137
src += 4;
138
}
139
}
140
141
/* The wicked packed format */
142
-static void glue(pxa2xx_draw_line18p_, BITS)(void *opaque,
143
+static void pxa2xx_draw_line18p(void *opaque,
144
uint8_t *dest, const uint8_t *src, int width, int deststep)
145
{
146
uint32_t data[3];
147
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line18p_, BITS)(void *opaque,
148
data[0] >>= 6;
149
r = (data[0] & 0x3f) << 2;
150
data[0] >>= 12;
151
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
152
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
153
b = (data[0] & 0x3f) << 2;
154
data[0] >>= 6;
155
g = ((data[1] & 0xf) << 4) | (data[0] << 2);
156
data[1] >>= 4;
157
r = (data[1] & 0x3f) << 2;
158
data[1] >>= 12;
159
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
160
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
161
b = (data[1] & 0x3f) << 2;
162
data[1] >>= 6;
163
g = (data[1] & 0x3f) << 2;
164
data[1] >>= 6;
165
r = ((data[2] & 0x3) << 6) | (data[1] << 2);
166
data[2] >>= 8;
167
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
168
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
169
b = (data[2] & 0x3f) << 2;
170
data[2] >>= 6;
171
g = (data[2] & 0x3f) << 2;
172
data[2] >>= 6;
173
r = data[2] << 2;
174
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
175
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
176
width -= 4;
177
}
178
}
179
180
-static void glue(pxa2xx_draw_line19_, BITS)(void *opaque,
181
+static void pxa2xx_draw_line19(void *opaque,
182
uint8_t *dest, const uint8_t *src, int width, int deststep)
183
{
184
uint32_t data;
185
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line19_, BITS)(void *opaque,
186
if (data & 1)
187
SKIP_PIXEL(dest);
188
else
189
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
190
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
191
width -= 1;
192
src += 4;
193
}
194
}
195
196
/* The wicked packed format */
197
-static void glue(pxa2xx_draw_line19p_, BITS)(void *opaque,
198
+static void pxa2xx_draw_line19p(void *opaque,
199
uint8_t *dest, const uint8_t *src, int width, int deststep)
200
{
201
uint32_t data[3];
202
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line19p_, BITS)(void *opaque,
203
if (data[0] & 1)
204
SKIP_PIXEL(dest);
205
else
206
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
207
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
208
data[0] >>= 6;
209
b = (data[0] & 0x3f) << 2;
210
data[0] >>= 6;
211
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line19p_, BITS)(void *opaque,
212
if (data[1] & 1)
213
SKIP_PIXEL(dest);
214
else
215
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
216
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
217
data[1] >>= 6;
218
b = (data[1] & 0x3f) << 2;
219
data[1] >>= 6;
220
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line19p_, BITS)(void *opaque,
221
if (data[2] & 1)
222
SKIP_PIXEL(dest);
223
else
224
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
225
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
226
data[2] >>= 6;
227
b = (data[2] & 0x3f) << 2;
228
data[2] >>= 6;
229
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line19p_, BITS)(void *opaque,
230
if (data[2] & 1)
231
SKIP_PIXEL(dest);
232
else
233
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
234
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
235
width -= 4;
236
}
237
}
238
239
-static void glue(pxa2xx_draw_line24_, BITS)(void *opaque,
240
+static void pxa2xx_draw_line24(void *opaque,
241
uint8_t *dest, const uint8_t *src, int width, int deststep)
242
{
243
uint32_t data;
244
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line24_, BITS)(void *opaque,
245
g = data & 0xff;
246
data >>= 8;
247
r = data & 0xff;
248
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
249
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
250
width -= 1;
251
src += 4;
252
}
253
}
254
255
-static void glue(pxa2xx_draw_line24t_, BITS)(void *opaque,
256
+static void pxa2xx_draw_line24t(void *opaque,
257
uint8_t *dest, const uint8_t *src, int width, int deststep)
258
{
259
uint32_t data;
260
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line24t_, BITS)(void *opaque,
261
if (data & 1)
262
SKIP_PIXEL(dest);
263
else
264
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
265
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
266
width -= 1;
267
src += 4;
268
}
269
}
270
271
-static void glue(pxa2xx_draw_line25_, BITS)(void *opaque,
272
+static void pxa2xx_draw_line25(void *opaque,
273
uint8_t *dest, const uint8_t *src, int width, int deststep)
274
{
275
uint32_t data;
276
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line25_, BITS)(void *opaque,
277
if (data & 1)
278
SKIP_PIXEL(dest);
279
else
280
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
281
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
282
width -= 1;
283
src += 4;
284
}
285
}
286
287
/* Overlay planes disabled, no transparency */
288
-static drawfn glue(pxa2xx_draw_fn_, BITS)[16] =
289
+static drawfn pxa2xx_draw_fn_32[16] =
290
{
291
[0 ... 0xf] = NULL,
292
- [pxa_lcdc_2bpp] = glue(pxa2xx_draw_line2_, BITS),
293
- [pxa_lcdc_4bpp] = glue(pxa2xx_draw_line4_, BITS),
294
- [pxa_lcdc_8bpp] = glue(pxa2xx_draw_line8_, BITS),
295
- [pxa_lcdc_16bpp] = glue(pxa2xx_draw_line16_, BITS),
296
- [pxa_lcdc_18bpp] = glue(pxa2xx_draw_line18_, BITS),
297
- [pxa_lcdc_18pbpp] = glue(pxa2xx_draw_line18p_, BITS),
298
- [pxa_lcdc_24bpp] = glue(pxa2xx_draw_line24_, BITS),
299
+ [pxa_lcdc_2bpp] = pxa2xx_draw_line2,
300
+ [pxa_lcdc_4bpp] = pxa2xx_draw_line4,
301
+ [pxa_lcdc_8bpp] = pxa2xx_draw_line8,
302
+ [pxa_lcdc_16bpp] = pxa2xx_draw_line16,
303
+ [pxa_lcdc_18bpp] = pxa2xx_draw_line18,
304
+ [pxa_lcdc_18pbpp] = pxa2xx_draw_line18p,
305
+ [pxa_lcdc_24bpp] = pxa2xx_draw_line24,
306
};
307
308
/* Overlay planes enabled, transparency used */
309
-static drawfn glue(glue(pxa2xx_draw_fn_, BITS), t)[16] =
310
+static drawfn pxa2xx_draw_fn_32t[16] =
311
{
312
[0 ... 0xf] = NULL,
313
- [pxa_lcdc_4bpp] = glue(pxa2xx_draw_line4_, BITS),
314
- [pxa_lcdc_8bpp] = glue(pxa2xx_draw_line8_, BITS),
315
- [pxa_lcdc_16bpp] = glue(pxa2xx_draw_line16t_, BITS),
316
- [pxa_lcdc_19bpp] = glue(pxa2xx_draw_line19_, BITS),
317
- [pxa_lcdc_19pbpp] = glue(pxa2xx_draw_line19p_, BITS),
318
- [pxa_lcdc_24bpp] = glue(pxa2xx_draw_line24t_, BITS),
319
- [pxa_lcdc_25bpp] = glue(pxa2xx_draw_line25_, BITS),
320
+ [pxa_lcdc_4bpp] = pxa2xx_draw_line4,
321
+ [pxa_lcdc_8bpp] = pxa2xx_draw_line8,
322
+ [pxa_lcdc_16bpp] = pxa2xx_draw_line16t,
323
+ [pxa_lcdc_19bpp] = pxa2xx_draw_line19,
324
+ [pxa_lcdc_19pbpp] = pxa2xx_draw_line19p,
325
+ [pxa_lcdc_24bpp] = pxa2xx_draw_line24t,
326
+ [pxa_lcdc_25bpp] = pxa2xx_draw_line25,
327
};
328
68
-#undef BITS
329
-#undef BITS
69
-#undef SET_PIXEL
330
#undef COPY_PIXEL
331
#undef SKIP_PIXEL
332
70
--
333
--
71
2.20.1
334
2.20.1
72
335
73
336
diff view generated by jsdifflib
1
In the mps2-tz board code, we handle devices whose interrupt lines
1
We're about to move code from the template header into pxa2xx_lcd.c.
2
must be wired to all CPUs by creating IRQ splitter devices for the
2
Before doing that, make coding style fixes so checkpatch doesn't
3
AN521, because it has 2 CPUs, but wiring the device IRQ directly to
3
complain about the patch which moves the code. This commit fixes
4
the SSE/IoTKit input for the AN505, which has only 1 CPU.
4
missing braces in the SKIP_PIXEL() macro definition and in if()
5
5
statements.
6
We can avoid making an explicit check on the board type constant by
7
instead creating and using the IRQ splitters for any board with more
8
than 1 CPU. This avoids having to add extra cases to the
9
conditionals every time we add new boards.
10
6
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210211141515.8755-8-peter.maydell@linaro.org
14
Message-id: 20210215115138.20465-9-peter.maydell@linaro.org
15
---
10
---
16
hw/arm/mps2-tz.c | 19 +++++++++----------
11
hw/display/pxa2xx_template.h | 47 +++++++++++++++++++++---------------
17
1 file changed, 9 insertions(+), 10 deletions(-)
12
1 file changed, 28 insertions(+), 19 deletions(-)
18
13
19
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
14
diff --git a/hw/display/pxa2xx_template.h b/hw/display/pxa2xx_template.h
20
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/arm/mps2-tz.c
16
--- a/hw/display/pxa2xx_template.h
22
+++ b/hw/arm/mps2-tz.c
17
+++ b/hw/display/pxa2xx_template.h
23
@@ -XXX,XX +XXX,XX @@ static void make_ram_alias(MemoryRegion *mr, const char *name,
18
@@ -XXX,XX +XXX,XX @@
24
static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
19
* Framebuffer format conversion routines.
25
{
20
*/
26
/* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
21
27
- MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
22
-# define SKIP_PIXEL(to)        to += deststep
28
+ MachineClass *mc = MACHINE_GET_CLASS(mms);
23
+# define SKIP_PIXEL(to) do { to += deststep; } while (0)
29
24
# define COPY_PIXEL(to, from) \
30
assert(irqno < MPS2TZ_NUMIRQ);
25
do { \
31
26
*(uint32_t *) to = from; \
32
- switch (mmc->fpga_type) {
27
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line16t(void *opaque,
33
- case FPGA_AN505:
28
data >>= 5;
34
- return qdev_get_gpio_in_named(DEVICE(&mms->iotkit), "EXP_IRQ", irqno);
29
r = (data & 0x1f) << 3;
35
- case FPGA_AN521:
30
data >>= 5;
36
+ if (mc->max_cpus > 1) {
31
- if (data & 1)
37
return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
32
+ if (data & 1) {
38
- default:
33
SKIP_PIXEL(dest);
39
- g_assert_not_reached();
34
- else
40
+ } else {
35
+ } else {
41
+ return qdev_get_gpio_in_named(DEVICE(&mms->iotkit), "EXP_IRQ", irqno);
36
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
37
+ }
38
data >>= 1;
39
b = (data & 0x1f) << 3;
40
data >>= 5;
41
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line16t(void *opaque,
42
data >>= 5;
43
r = (data & 0x1f) << 3;
44
data >>= 5;
45
- if (data & 1)
46
+ if (data & 1) {
47
SKIP_PIXEL(dest);
48
- else
49
+ } else {
50
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
51
+ }
52
width -= 2;
53
src += 4;
54
}
55
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19(void *opaque,
56
data >>= 6;
57
r = (data & 0x3f) << 2;
58
data >>= 6;
59
- if (data & 1)
60
+ if (data & 1) {
61
SKIP_PIXEL(dest);
62
- else
63
+ } else {
64
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
65
+ }
66
width -= 1;
67
src += 4;
68
}
69
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19p(void *opaque,
70
data[0] >>= 6;
71
r = (data[0] & 0x3f) << 2;
72
data[0] >>= 6;
73
- if (data[0] & 1)
74
+ if (data[0] & 1) {
75
SKIP_PIXEL(dest);
76
- else
77
+ } else {
78
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
79
+ }
80
data[0] >>= 6;
81
b = (data[0] & 0x3f) << 2;
82
data[0] >>= 6;
83
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19p(void *opaque,
84
data[1] >>= 4;
85
r = (data[1] & 0x3f) << 2;
86
data[1] >>= 6;
87
- if (data[1] & 1)
88
+ if (data[1] & 1) {
89
SKIP_PIXEL(dest);
90
- else
91
+ } else {
92
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
93
+ }
94
data[1] >>= 6;
95
b = (data[1] & 0x3f) << 2;
96
data[1] >>= 6;
97
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19p(void *opaque,
98
data[1] >>= 6;
99
r = ((data[2] & 0x3) << 6) | (data[1] << 2);
100
data[2] >>= 2;
101
- if (data[2] & 1)
102
+ if (data[2] & 1) {
103
SKIP_PIXEL(dest);
104
- else
105
+ } else {
106
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
107
+ }
108
data[2] >>= 6;
109
b = (data[2] & 0x3f) << 2;
110
data[2] >>= 6;
111
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19p(void *opaque,
112
data[2] >>= 6;
113
r = data[2] << 2;
114
data[2] >>= 6;
115
- if (data[2] & 1)
116
+ if (data[2] & 1) {
117
SKIP_PIXEL(dest);
118
- else
119
+ } else {
120
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
121
+ }
122
width -= 4;
42
}
123
}
43
}
124
}
44
125
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line24t(void *opaque,
45
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
126
data >>= 8;
46
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
127
r = data & 0xff;
47
128
data >>= 8;
48
/*
129
- if (data & 1)
49
- * The AN521 needs us to create splitters to feed the IRQ inputs
130
+ if (data & 1) {
50
- * for each CPU in the SSE-200 from each device in the board.
131
SKIP_PIXEL(dest);
51
+ * If this board has more than one CPU, then we need to create splitters
132
- else
52
+ * to feed the IRQ inputs for each CPU in the SSE from each device in the
133
+ } else {
53
+ * board. If there is only one CPU, we can just wire the device IRQ
134
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
54
+ * directly to the SSE's IRQ input.
135
+ }
55
*/
136
width -= 1;
56
- if (mmc->fpga_type == FPGA_AN521) {
137
src += 4;
57
+ if (mc->max_cpus > 1) {
138
}
58
for (i = 0; i < MPS2TZ_NUMIRQ; i++) {
139
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line25(void *opaque,
59
char *name = g_strdup_printf("mps2-irq-splitter%d", i);
140
data >>= 8;
60
SplitIRQ *splitter = &mms->cpu_irq_splitter[i];
141
r = data & 0xff;
142
data >>= 8;
143
- if (data & 1)
144
+ if (data & 1) {
145
SKIP_PIXEL(dest);
146
- else
147
+ } else {
148
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
149
+ }
150
width -= 1;
151
src += 4;
152
}
61
--
153
--
62
2.20.1
154
2.20.1
63
155
64
156
diff view generated by jsdifflib
1
MPS3 boards have an extra SWITCH register in the FPGAIO block which
1
We're about to move code from the template header into pxa2xx_lcd.c.
2
reports the value of some switches. Implement this, governed by a
2
Before doing that, make coding style fixes so checkpatch doesn't
3
property the board code can use to specify whether whether it exists.
3
complain about the patch which moves the code. This commit is
4
whitespace changes only:
5
* avoid hard-coded tabs
6
* fix ident on function prototypes
7
* no newline before open brace on array definitions
4
8
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20210211141515.8755-9-peter.maydell@linaro.org
8
Message-id: 20210215115138.20465-7-peter.maydell@linaro.org
9
---
12
---
10
include/hw/misc/mps2-fpgaio.h | 1 +
13
hw/display/pxa2xx_template.h | 66 +++++++++++++++++-------------------
11
hw/misc/mps2-fpgaio.c | 10 ++++++++++
14
1 file changed, 32 insertions(+), 34 deletions(-)
12
2 files changed, 11 insertions(+)
15
13
16
diff --git a/hw/display/pxa2xx_template.h b/hw/display/pxa2xx_template.h
14
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/misc/mps2-fpgaio.h
18
--- a/hw/display/pxa2xx_template.h
17
+++ b/include/hw/misc/mps2-fpgaio.h
19
+++ b/hw/display/pxa2xx_template.h
18
@@ -XXX,XX +XXX,XX @@ struct MPS2FPGAIO {
20
@@ -XXX,XX +XXX,XX @@
19
MemoryRegion iomem;
21
} while (0)
20
LEDState *led[MPS2FPGAIO_MAX_LEDS];
22
21
uint32_t num_leds;
23
#ifdef HOST_WORDS_BIGENDIAN
22
+ bool has_switches;
24
-# define SWAP_WORDS    1
23
25
+# define SWAP_WORDS 1
24
uint32_t led0;
26
#endif
25
uint32_t prescale;
27
26
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
28
-#define FN_2(x)        FN(x + 1) FN(x)
27
index XXXXXXX..XXXXXXX 100644
29
-#define FN_4(x)        FN_2(x + 2) FN_2(x)
28
--- a/hw/misc/mps2-fpgaio.c
30
+#define FN_2(x) FN(x + 1) FN(x)
29
+++ b/hw/misc/mps2-fpgaio.c
31
+#define FN_4(x) FN_2(x + 2) FN_2(x)
30
@@ -XXX,XX +XXX,XX @@ REG32(CLK100HZ, 0x14)
32
31
REG32(COUNTER, 0x18)
33
-static void pxa2xx_draw_line2(void *opaque,
32
REG32(PRESCALE, 0x1c)
34
- uint8_t *dest, const uint8_t *src, int width, int deststep)
33
REG32(PSCNTR, 0x20)
35
+static void pxa2xx_draw_line2(void *opaque, uint8_t *dest, const uint8_t *src,
34
+REG32(SWITCH, 0x28)
36
+ int width, int deststep)
35
REG32(MISC, 0x4c)
37
{
36
38
uint32_t *palette = opaque;
37
static uint32_t counter_from_tickoff(int64_t now, int64_t tick_offset, int frq)
39
uint32_t data;
38
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
40
while (width > 0) {
39
resync_counter(s);
41
data = *(uint32_t *) src;
40
r = s->pscntr;
42
-#define FN(x)        COPY_PIXEL(dest, palette[(data >> ((x) * 2)) & 3]);
41
break;
43
+#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 2)) & 3]);
42
+ case A_SWITCH:
44
#ifdef SWAP_WORDS
43
+ if (!s->has_switches) {
45
FN_4(12)
44
+ goto bad_offset;
46
FN_4(8)
45
+ }
47
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line2(void *opaque,
46
+ /* User-togglable board switches. We don't model that, so report 0. */
48
}
47
+ r = 0;
49
}
48
+ break;
50
49
default:
51
-static void pxa2xx_draw_line4(void *opaque,
50
+ bad_offset:
52
- uint8_t *dest, const uint8_t *src, int width, int deststep)
51
qemu_log_mask(LOG_GUEST_ERROR,
53
+static void pxa2xx_draw_line4(void *opaque, uint8_t *dest, const uint8_t *src,
52
"MPS2 FPGAIO read: bad offset %x\n", (int) offset);
54
+ int width, int deststep)
53
r = 0;
55
{
54
@@ -XXX,XX +XXX,XX @@ static Property mps2_fpgaio_properties[] = {
56
uint32_t *palette = opaque;
55
DEFINE_PROP_UINT32("prescale-clk", MPS2FPGAIO, prescale_clk, 20000000),
57
uint32_t data;
56
/* Number of LEDs controlled by LED0 register */
58
while (width > 0) {
57
DEFINE_PROP_UINT32("num-leds", MPS2FPGAIO, num_leds, 2),
59
data = *(uint32_t *) src;
58
+ DEFINE_PROP_BOOL("has-switches", MPS2FPGAIO, has_switches, false),
60
-#define FN(x)        COPY_PIXEL(dest, palette[(data >> ((x) * 4)) & 0xf]);
59
DEFINE_PROP_END_OF_LIST(),
61
+#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 4)) & 0xf]);
62
#ifdef SWAP_WORDS
63
FN_2(6)
64
FN_2(4)
65
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line4(void *opaque,
66
}
67
}
68
69
-static void pxa2xx_draw_line8(void *opaque,
70
- uint8_t *dest, const uint8_t *src, int width, int deststep)
71
+static void pxa2xx_draw_line8(void *opaque, uint8_t *dest, const uint8_t *src,
72
+ int width, int deststep)
73
{
74
uint32_t *palette = opaque;
75
uint32_t data;
76
while (width > 0) {
77
data = *(uint32_t *) src;
78
-#define FN(x)        COPY_PIXEL(dest, palette[(data >> (x)) & 0xff]);
79
+#define FN(x) COPY_PIXEL(dest, palette[(data >> (x)) & 0xff]);
80
#ifdef SWAP_WORDS
81
FN(24)
82
FN(16)
83
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line8(void *opaque,
84
}
85
}
86
87
-static void pxa2xx_draw_line16(void *opaque,
88
- uint8_t *dest, const uint8_t *src, int width, int deststep)
89
+static void pxa2xx_draw_line16(void *opaque, uint8_t *dest, const uint8_t *src,
90
+ int width, int deststep)
91
{
92
uint32_t data;
93
unsigned int r, g, b;
94
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line16(void *opaque,
95
}
96
}
97
98
-static void pxa2xx_draw_line16t(void *opaque,
99
- uint8_t *dest, const uint8_t *src, int width, int deststep)
100
+static void pxa2xx_draw_line16t(void *opaque, uint8_t *dest, const uint8_t *src,
101
+ int width, int deststep)
102
{
103
uint32_t data;
104
unsigned int r, g, b;
105
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line16t(void *opaque,
106
}
107
}
108
109
-static void pxa2xx_draw_line18(void *opaque,
110
- uint8_t *dest, const uint8_t *src, int width, int deststep)
111
+static void pxa2xx_draw_line18(void *opaque, uint8_t *dest, const uint8_t *src,
112
+ int width, int deststep)
113
{
114
uint32_t data;
115
unsigned int r, g, b;
116
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line18(void *opaque,
117
}
118
119
/* The wicked packed format */
120
-static void pxa2xx_draw_line18p(void *opaque,
121
- uint8_t *dest, const uint8_t *src, int width, int deststep)
122
+static void pxa2xx_draw_line18p(void *opaque, uint8_t *dest, const uint8_t *src,
123
+ int width, int deststep)
124
{
125
uint32_t data[3];
126
unsigned int r, g, b;
127
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line18p(void *opaque,
128
}
129
}
130
131
-static void pxa2xx_draw_line19(void *opaque,
132
- uint8_t *dest, const uint8_t *src, int width, int deststep)
133
+static void pxa2xx_draw_line19(void *opaque, uint8_t *dest, const uint8_t *src,
134
+ int width, int deststep)
135
{
136
uint32_t data;
137
unsigned int r, g, b;
138
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19(void *opaque,
139
}
140
141
/* The wicked packed format */
142
-static void pxa2xx_draw_line19p(void *opaque,
143
- uint8_t *dest, const uint8_t *src, int width, int deststep)
144
+static void pxa2xx_draw_line19p(void *opaque, uint8_t *dest, const uint8_t *src,
145
+ int width, int deststep)
146
{
147
uint32_t data[3];
148
unsigned int r, g, b;
149
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19p(void *opaque,
150
}
151
}
152
153
-static void pxa2xx_draw_line24(void *opaque,
154
- uint8_t *dest, const uint8_t *src, int width, int deststep)
155
+static void pxa2xx_draw_line24(void *opaque, uint8_t *dest, const uint8_t *src,
156
+ int width, int deststep)
157
{
158
uint32_t data;
159
unsigned int r, g, b;
160
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line24(void *opaque,
161
}
162
}
163
164
-static void pxa2xx_draw_line24t(void *opaque,
165
- uint8_t *dest, const uint8_t *src, int width, int deststep)
166
+static void pxa2xx_draw_line24t(void *opaque, uint8_t *dest, const uint8_t *src,
167
+ int width, int deststep)
168
{
169
uint32_t data;
170
unsigned int r, g, b;
171
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line24t(void *opaque,
172
}
173
}
174
175
-static void pxa2xx_draw_line25(void *opaque,
176
- uint8_t *dest, const uint8_t *src, int width, int deststep)
177
+static void pxa2xx_draw_line25(void *opaque, uint8_t *dest, const uint8_t *src,
178
+ int width, int deststep)
179
{
180
uint32_t data;
181
unsigned int r, g, b;
182
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line25(void *opaque,
183
}
184
185
/* Overlay planes disabled, no transparency */
186
-static drawfn pxa2xx_draw_fn_32[16] =
187
-{
188
+static drawfn pxa2xx_draw_fn_32[16] = {
189
[0 ... 0xf] = NULL,
190
[pxa_lcdc_2bpp] = pxa2xx_draw_line2,
191
[pxa_lcdc_4bpp] = pxa2xx_draw_line4,
192
@@ -XXX,XX +XXX,XX @@ static drawfn pxa2xx_draw_fn_32[16] =
60
};
193
};
61
194
195
/* Overlay planes enabled, transparency used */
196
-static drawfn pxa2xx_draw_fn_32t[16] =
197
-{
198
+static drawfn pxa2xx_draw_fn_32t[16] = {
199
[0 ... 0xf] = NULL,
200
[pxa_lcdc_4bpp] = pxa2xx_draw_line4,
201
[pxa_lcdc_8bpp] = pxa2xx_draw_line8,
62
--
202
--
63
2.20.1
203
2.20.1
64
204
65
205
diff view generated by jsdifflib
1
The function tc6393xb_draw_graphic32() is called in exactly one place,
1
The template header is now included only once; just inline its contents
2
so just inline the function body at its callsite. This allows us to
2
in hw/display/pxa2xx_lcd.c.
3
drop the template header entirely.
4
5
The code move includes a single added space after 'for' to fix
6
the coding style.
7
3
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20210211141515.8755-10-peter.maydell@linaro.org
11
Message-id: 20210215103215.4944-5-peter.maydell@linaro.org
12
---
7
---
13
hw/display/tc6393xb_template.h | 45 ----------------------------------
8
hw/display/pxa2xx_template.h | 434 -----------------------------------
14
hw/display/tc6393xb.c | 23 ++++++++++++++---
9
hw/display/pxa2xx_lcd.c | 427 +++++++++++++++++++++++++++++++++-
15
2 files changed, 19 insertions(+), 49 deletions(-)
10
2 files changed, 425 insertions(+), 436 deletions(-)
16
delete mode 100644 hw/display/tc6393xb_template.h
11
delete mode 100644 hw/display/pxa2xx_template.h
17
12
18
diff --git a/hw/display/tc6393xb_template.h b/hw/display/tc6393xb_template.h
13
diff --git a/hw/display/pxa2xx_template.h b/hw/display/pxa2xx_template.h
19
deleted file mode 100644
14
deleted file mode 100644
20
index XXXXXXX..XXXXXXX
15
index XXXXXXX..XXXXXXX
21
--- a/hw/display/tc6393xb_template.h
16
--- a/hw/display/pxa2xx_template.h
22
+++ /dev/null
17
+++ /dev/null
23
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@
24
-/*
19
-/*
25
- * Toshiba TC6393XB I/O Controller.
20
- * Intel XScale PXA255/270 LCDC emulation.
26
- * Found in Sharp Zaurus SL-6000 (tosa) or some
27
- * Toshiba e-Series PDAs.
28
- *
21
- *
29
- * FB support code. Based on G364 fb emulator
22
- * Copyright (c) 2006 Openedhand Ltd.
23
- * Written by Andrzej Zaborowski <balrog@zabor.org>
30
- *
24
- *
31
- * Copyright (c) 2007 Hervé Poussineau
25
- * This code is licensed under the GPLv2.
32
- *
26
- *
33
- * This program is free software; you can redistribute it and/or
27
- * Framebuffer format conversion routines.
34
- * modify it under the terms of the GNU General Public License as
35
- * published by the Free Software Foundation; either version 2 of
36
- * the License, or (at your option) any later version.
37
- *
38
- * This program is distributed in the hope that it will be useful,
39
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
40
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41
- * GNU General Public License for more details.
42
- *
43
- * You should have received a copy of the GNU General Public License along
44
- * with this program; if not, see <http://www.gnu.org/licenses/>.
45
- */
28
- */
46
-
29
-
47
-static void tc6393xb_draw_graphic32(TC6393xbState *s)
30
-# define SKIP_PIXEL(to) do { to += deststep; } while (0)
48
-{
31
-# define COPY_PIXEL(to, from) \
49
- DisplaySurface *surface = qemu_console_surface(s->con);
32
- do { \
50
- int i;
33
- *(uint32_t *) to = from; \
51
- uint16_t *data_buffer;
34
- SKIP_PIXEL(to); \
52
- uint8_t *data_display;
35
- } while (0)
53
-
36
-
54
- data_buffer = s->vram_ptr;
37
-#ifdef HOST_WORDS_BIGENDIAN
55
- data_display = surface_data(surface);
38
-# define SWAP_WORDS 1
56
- for(i = 0; i < s->scr_height; i++) {
39
-#endif
57
- int j;
40
-
58
- for (j = 0; j < s->scr_width; j++, data_display += 4, data_buffer++) {
41
-#define FN_2(x) FN(x + 1) FN(x)
59
- uint16_t color = *data_buffer;
42
-#define FN_4(x) FN_2(x + 2) FN_2(x)
60
- uint32_t dest_color = rgb_to_pixel32(
43
-
61
- ((color & 0xf800) * 0x108) >> 11,
44
-static void pxa2xx_draw_line2(void *opaque, uint8_t *dest, const uint8_t *src,
62
- ((color & 0x7e0) * 0x41) >> 9,
45
- int width, int deststep)
63
- ((color & 0x1f) * 0x21) >> 2
46
-{
64
- );
47
- uint32_t *palette = opaque;
65
- *(uint32_t *)data_display = dest_color;
48
- uint32_t data;
49
- while (width > 0) {
50
- data = *(uint32_t *) src;
51
-#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 2)) & 3]);
52
-#ifdef SWAP_WORDS
53
- FN_4(12)
54
- FN_4(8)
55
- FN_4(4)
56
- FN_4(0)
57
-#else
58
- FN_4(0)
59
- FN_4(4)
60
- FN_4(8)
61
- FN_4(12)
62
-#endif
63
-#undef FN
64
- width -= 16;
65
- src += 4;
66
- }
67
-}
68
-
69
-static void pxa2xx_draw_line4(void *opaque, uint8_t *dest, const uint8_t *src,
70
- int width, int deststep)
71
-{
72
- uint32_t *palette = opaque;
73
- uint32_t data;
74
- while (width > 0) {
75
- data = *(uint32_t *) src;
76
-#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 4)) & 0xf]);
77
-#ifdef SWAP_WORDS
78
- FN_2(6)
79
- FN_2(4)
80
- FN_2(2)
81
- FN_2(0)
82
-#else
83
- FN_2(0)
84
- FN_2(2)
85
- FN_2(4)
86
- FN_2(6)
87
-#endif
88
-#undef FN
89
- width -= 8;
90
- src += 4;
91
- }
92
-}
93
-
94
-static void pxa2xx_draw_line8(void *opaque, uint8_t *dest, const uint8_t *src,
95
- int width, int deststep)
96
-{
97
- uint32_t *palette = opaque;
98
- uint32_t data;
99
- while (width > 0) {
100
- data = *(uint32_t *) src;
101
-#define FN(x) COPY_PIXEL(dest, palette[(data >> (x)) & 0xff]);
102
-#ifdef SWAP_WORDS
103
- FN(24)
104
- FN(16)
105
- FN(8)
106
- FN(0)
107
-#else
108
- FN(0)
109
- FN(8)
110
- FN(16)
111
- FN(24)
112
-#endif
113
-#undef FN
114
- width -= 4;
115
- src += 4;
116
- }
117
-}
118
-
119
-static void pxa2xx_draw_line16(void *opaque, uint8_t *dest, const uint8_t *src,
120
- int width, int deststep)
121
-{
122
- uint32_t data;
123
- unsigned int r, g, b;
124
- while (width > 0) {
125
- data = *(uint32_t *) src;
126
-#ifdef SWAP_WORDS
127
- data = bswap32(data);
128
-#endif
129
- b = (data & 0x1f) << 3;
130
- data >>= 5;
131
- g = (data & 0x3f) << 2;
132
- data >>= 6;
133
- r = (data & 0x1f) << 3;
134
- data >>= 5;
135
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
136
- b = (data & 0x1f) << 3;
137
- data >>= 5;
138
- g = (data & 0x3f) << 2;
139
- data >>= 6;
140
- r = (data & 0x1f) << 3;
141
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
142
- width -= 2;
143
- src += 4;
144
- }
145
-}
146
-
147
-static void pxa2xx_draw_line16t(void *opaque, uint8_t *dest, const uint8_t *src,
148
- int width, int deststep)
149
-{
150
- uint32_t data;
151
- unsigned int r, g, b;
152
- while (width > 0) {
153
- data = *(uint32_t *) src;
154
-#ifdef SWAP_WORDS
155
- data = bswap32(data);
156
-#endif
157
- b = (data & 0x1f) << 3;
158
- data >>= 5;
159
- g = (data & 0x1f) << 3;
160
- data >>= 5;
161
- r = (data & 0x1f) << 3;
162
- data >>= 5;
163
- if (data & 1) {
164
- SKIP_PIXEL(dest);
165
- } else {
166
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
66
- }
167
- }
67
- }
168
- data >>= 1;
68
-}
169
- b = (data & 0x1f) << 3;
69
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
170
- data >>= 5;
171
- g = (data & 0x1f) << 3;
172
- data >>= 5;
173
- r = (data & 0x1f) << 3;
174
- data >>= 5;
175
- if (data & 1) {
176
- SKIP_PIXEL(dest);
177
- } else {
178
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
179
- }
180
- width -= 2;
181
- src += 4;
182
- }
183
-}
184
-
185
-static void pxa2xx_draw_line18(void *opaque, uint8_t *dest, const uint8_t *src,
186
- int width, int deststep)
187
-{
188
- uint32_t data;
189
- unsigned int r, g, b;
190
- while (width > 0) {
191
- data = *(uint32_t *) src;
192
-#ifdef SWAP_WORDS
193
- data = bswap32(data);
194
-#endif
195
- b = (data & 0x3f) << 2;
196
- data >>= 6;
197
- g = (data & 0x3f) << 2;
198
- data >>= 6;
199
- r = (data & 0x3f) << 2;
200
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
201
- width -= 1;
202
- src += 4;
203
- }
204
-}
205
-
206
-/* The wicked packed format */
207
-static void pxa2xx_draw_line18p(void *opaque, uint8_t *dest, const uint8_t *src,
208
- int width, int deststep)
209
-{
210
- uint32_t data[3];
211
- unsigned int r, g, b;
212
- while (width > 0) {
213
- data[0] = *(uint32_t *) src;
214
- src += 4;
215
- data[1] = *(uint32_t *) src;
216
- src += 4;
217
- data[2] = *(uint32_t *) src;
218
- src += 4;
219
-#ifdef SWAP_WORDS
220
- data[0] = bswap32(data[0]);
221
- data[1] = bswap32(data[1]);
222
- data[2] = bswap32(data[2]);
223
-#endif
224
- b = (data[0] & 0x3f) << 2;
225
- data[0] >>= 6;
226
- g = (data[0] & 0x3f) << 2;
227
- data[0] >>= 6;
228
- r = (data[0] & 0x3f) << 2;
229
- data[0] >>= 12;
230
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
231
- b = (data[0] & 0x3f) << 2;
232
- data[0] >>= 6;
233
- g = ((data[1] & 0xf) << 4) | (data[0] << 2);
234
- data[1] >>= 4;
235
- r = (data[1] & 0x3f) << 2;
236
- data[1] >>= 12;
237
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
238
- b = (data[1] & 0x3f) << 2;
239
- data[1] >>= 6;
240
- g = (data[1] & 0x3f) << 2;
241
- data[1] >>= 6;
242
- r = ((data[2] & 0x3) << 6) | (data[1] << 2);
243
- data[2] >>= 8;
244
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
245
- b = (data[2] & 0x3f) << 2;
246
- data[2] >>= 6;
247
- g = (data[2] & 0x3f) << 2;
248
- data[2] >>= 6;
249
- r = data[2] << 2;
250
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
251
- width -= 4;
252
- }
253
-}
254
-
255
-static void pxa2xx_draw_line19(void *opaque, uint8_t *dest, const uint8_t *src,
256
- int width, int deststep)
257
-{
258
- uint32_t data;
259
- unsigned int r, g, b;
260
- while (width > 0) {
261
- data = *(uint32_t *) src;
262
-#ifdef SWAP_WORDS
263
- data = bswap32(data);
264
-#endif
265
- b = (data & 0x3f) << 2;
266
- data >>= 6;
267
- g = (data & 0x3f) << 2;
268
- data >>= 6;
269
- r = (data & 0x3f) << 2;
270
- data >>= 6;
271
- if (data & 1) {
272
- SKIP_PIXEL(dest);
273
- } else {
274
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
275
- }
276
- width -= 1;
277
- src += 4;
278
- }
279
-}
280
-
281
-/* The wicked packed format */
282
-static void pxa2xx_draw_line19p(void *opaque, uint8_t *dest, const uint8_t *src,
283
- int width, int deststep)
284
-{
285
- uint32_t data[3];
286
- unsigned int r, g, b;
287
- while (width > 0) {
288
- data[0] = *(uint32_t *) src;
289
- src += 4;
290
- data[1] = *(uint32_t *) src;
291
- src += 4;
292
- data[2] = *(uint32_t *) src;
293
- src += 4;
294
-# ifdef SWAP_WORDS
295
- data[0] = bswap32(data[0]);
296
- data[1] = bswap32(data[1]);
297
- data[2] = bswap32(data[2]);
298
-# endif
299
- b = (data[0] & 0x3f) << 2;
300
- data[0] >>= 6;
301
- g = (data[0] & 0x3f) << 2;
302
- data[0] >>= 6;
303
- r = (data[0] & 0x3f) << 2;
304
- data[0] >>= 6;
305
- if (data[0] & 1) {
306
- SKIP_PIXEL(dest);
307
- } else {
308
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
309
- }
310
- data[0] >>= 6;
311
- b = (data[0] & 0x3f) << 2;
312
- data[0] >>= 6;
313
- g = ((data[1] & 0xf) << 4) | (data[0] << 2);
314
- data[1] >>= 4;
315
- r = (data[1] & 0x3f) << 2;
316
- data[1] >>= 6;
317
- if (data[1] & 1) {
318
- SKIP_PIXEL(dest);
319
- } else {
320
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
321
- }
322
- data[1] >>= 6;
323
- b = (data[1] & 0x3f) << 2;
324
- data[1] >>= 6;
325
- g = (data[1] & 0x3f) << 2;
326
- data[1] >>= 6;
327
- r = ((data[2] & 0x3) << 6) | (data[1] << 2);
328
- data[2] >>= 2;
329
- if (data[2] & 1) {
330
- SKIP_PIXEL(dest);
331
- } else {
332
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
333
- }
334
- data[2] >>= 6;
335
- b = (data[2] & 0x3f) << 2;
336
- data[2] >>= 6;
337
- g = (data[2] & 0x3f) << 2;
338
- data[2] >>= 6;
339
- r = data[2] << 2;
340
- data[2] >>= 6;
341
- if (data[2] & 1) {
342
- SKIP_PIXEL(dest);
343
- } else {
344
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
345
- }
346
- width -= 4;
347
- }
348
-}
349
-
350
-static void pxa2xx_draw_line24(void *opaque, uint8_t *dest, const uint8_t *src,
351
- int width, int deststep)
352
-{
353
- uint32_t data;
354
- unsigned int r, g, b;
355
- while (width > 0) {
356
- data = *(uint32_t *) src;
357
-#ifdef SWAP_WORDS
358
- data = bswap32(data);
359
-#endif
360
- b = data & 0xff;
361
- data >>= 8;
362
- g = data & 0xff;
363
- data >>= 8;
364
- r = data & 0xff;
365
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
366
- width -= 1;
367
- src += 4;
368
- }
369
-}
370
-
371
-static void pxa2xx_draw_line24t(void *opaque, uint8_t *dest, const uint8_t *src,
372
- int width, int deststep)
373
-{
374
- uint32_t data;
375
- unsigned int r, g, b;
376
- while (width > 0) {
377
- data = *(uint32_t *) src;
378
-#ifdef SWAP_WORDS
379
- data = bswap32(data);
380
-#endif
381
- b = (data & 0x7f) << 1;
382
- data >>= 7;
383
- g = data & 0xff;
384
- data >>= 8;
385
- r = data & 0xff;
386
- data >>= 8;
387
- if (data & 1) {
388
- SKIP_PIXEL(dest);
389
- } else {
390
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
391
- }
392
- width -= 1;
393
- src += 4;
394
- }
395
-}
396
-
397
-static void pxa2xx_draw_line25(void *opaque, uint8_t *dest, const uint8_t *src,
398
- int width, int deststep)
399
-{
400
- uint32_t data;
401
- unsigned int r, g, b;
402
- while (width > 0) {
403
- data = *(uint32_t *) src;
404
-#ifdef SWAP_WORDS
405
- data = bswap32(data);
406
-#endif
407
- b = data & 0xff;
408
- data >>= 8;
409
- g = data & 0xff;
410
- data >>= 8;
411
- r = data & 0xff;
412
- data >>= 8;
413
- if (data & 1) {
414
- SKIP_PIXEL(dest);
415
- } else {
416
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
417
- }
418
- width -= 1;
419
- src += 4;
420
- }
421
-}
422
-
423
-/* Overlay planes disabled, no transparency */
424
-static drawfn pxa2xx_draw_fn_32[16] = {
425
- [0 ... 0xf] = NULL,
426
- [pxa_lcdc_2bpp] = pxa2xx_draw_line2,
427
- [pxa_lcdc_4bpp] = pxa2xx_draw_line4,
428
- [pxa_lcdc_8bpp] = pxa2xx_draw_line8,
429
- [pxa_lcdc_16bpp] = pxa2xx_draw_line16,
430
- [pxa_lcdc_18bpp] = pxa2xx_draw_line18,
431
- [pxa_lcdc_18pbpp] = pxa2xx_draw_line18p,
432
- [pxa_lcdc_24bpp] = pxa2xx_draw_line24,
433
-};
434
-
435
-/* Overlay planes enabled, transparency used */
436
-static drawfn pxa2xx_draw_fn_32t[16] = {
437
- [0 ... 0xf] = NULL,
438
- [pxa_lcdc_4bpp] = pxa2xx_draw_line4,
439
- [pxa_lcdc_8bpp] = pxa2xx_draw_line8,
440
- [pxa_lcdc_16bpp] = pxa2xx_draw_line16t,
441
- [pxa_lcdc_19bpp] = pxa2xx_draw_line19,
442
- [pxa_lcdc_19pbpp] = pxa2xx_draw_line19p,
443
- [pxa_lcdc_24bpp] = pxa2xx_draw_line24t,
444
- [pxa_lcdc_25bpp] = pxa2xx_draw_line25,
445
-};
446
-
447
-#undef COPY_PIXEL
448
-#undef SKIP_PIXEL
449
-
450
-#ifdef SWAP_WORDS
451
-# undef SWAP_WORDS
452
-#endif
453
diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c
70
index XXXXXXX..XXXXXXX 100644
454
index XXXXXXX..XXXXXXX 100644
71
--- a/hw/display/tc6393xb.c
455
--- a/hw/display/pxa2xx_lcd.c
72
+++ b/hw/display/tc6393xb.c
456
+++ b/hw/display/pxa2xx_lcd.c
73
@@ -XXX,XX +XXX,XX @@ static void tc6393xb_nand_writeb(TC6393xbState *s, hwaddr addr, uint32_t value)
457
@@ -XXX,XX +XXX,XX @@ typedef struct QEMU_PACKED {
74
(uint32_t) addr, value & 0xff);
458
/* Size of a pixel in the QEMU UI output surface, in bytes */
75
}
459
#define DEST_PIXEL_WIDTH 4
76
460
77
-#define BITS 32
461
-#define BITS 32
78
-#include "tc6393xb_template.h"
462
-#include "pxa2xx_template.h"
79
-
463
+/* Line drawing code to handle the various possible guest pixel formats */
80
static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update)
464
+
81
{
465
+# define SKIP_PIXEL(to) do { to += deststep; } while (0)
82
- tc6393xb_draw_graphic32(s);
466
+# define COPY_PIXEL(to, from) \
83
+ DisplaySurface *surface = qemu_console_surface(s->con);
467
+ do { \
84
+ int i;
468
+ *(uint32_t *) to = from; \
85
+ uint16_t *data_buffer;
469
+ SKIP_PIXEL(to); \
86
+ uint8_t *data_display;
470
+ } while (0)
87
+
471
+
88
+ data_buffer = s->vram_ptr;
472
+#ifdef HOST_WORDS_BIGENDIAN
89
+ data_display = surface_data(surface);
473
+# define SWAP_WORDS 1
90
+ for (i = 0; i < s->scr_height; i++) {
474
+#endif
91
+ int j;
475
+
92
+ for (j = 0; j < s->scr_width; j++, data_display += 4, data_buffer++) {
476
+#define FN_2(x) FN(x + 1) FN(x)
93
+ uint16_t color = *data_buffer;
477
+#define FN_4(x) FN_2(x + 2) FN_2(x)
94
+ uint32_t dest_color = rgb_to_pixel32(
478
+
95
+ ((color & 0xf800) * 0x108) >> 11,
479
+static void pxa2xx_draw_line2(void *opaque, uint8_t *dest, const uint8_t *src,
96
+ ((color & 0x7e0) * 0x41) >> 9,
480
+ int width, int deststep)
97
+ ((color & 0x1f) * 0x21) >> 2
481
+{
98
+ );
482
+ uint32_t *palette = opaque;
99
+ *(uint32_t *)data_display = dest_color;
483
+ uint32_t data;
484
+ while (width > 0) {
485
+ data = *(uint32_t *) src;
486
+#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 2)) & 3]);
487
+#ifdef SWAP_WORDS
488
+ FN_4(12)
489
+ FN_4(8)
490
+ FN_4(4)
491
+ FN_4(0)
492
+#else
493
+ FN_4(0)
494
+ FN_4(4)
495
+ FN_4(8)
496
+ FN_4(12)
497
+#endif
498
+#undef FN
499
+ width -= 16;
500
+ src += 4;
501
+ }
502
+}
503
+
504
+static void pxa2xx_draw_line4(void *opaque, uint8_t *dest, const uint8_t *src,
505
+ int width, int deststep)
506
+{
507
+ uint32_t *palette = opaque;
508
+ uint32_t data;
509
+ while (width > 0) {
510
+ data = *(uint32_t *) src;
511
+#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 4)) & 0xf]);
512
+#ifdef SWAP_WORDS
513
+ FN_2(6)
514
+ FN_2(4)
515
+ FN_2(2)
516
+ FN_2(0)
517
+#else
518
+ FN_2(0)
519
+ FN_2(2)
520
+ FN_2(4)
521
+ FN_2(6)
522
+#endif
523
+#undef FN
524
+ width -= 8;
525
+ src += 4;
526
+ }
527
+}
528
+
529
+static void pxa2xx_draw_line8(void *opaque, uint8_t *dest, const uint8_t *src,
530
+ int width, int deststep)
531
+{
532
+ uint32_t *palette = opaque;
533
+ uint32_t data;
534
+ while (width > 0) {
535
+ data = *(uint32_t *) src;
536
+#define FN(x) COPY_PIXEL(dest, palette[(data >> (x)) & 0xff]);
537
+#ifdef SWAP_WORDS
538
+ FN(24)
539
+ FN(16)
540
+ FN(8)
541
+ FN(0)
542
+#else
543
+ FN(0)
544
+ FN(8)
545
+ FN(16)
546
+ FN(24)
547
+#endif
548
+#undef FN
549
+ width -= 4;
550
+ src += 4;
551
+ }
552
+}
553
+
554
+static void pxa2xx_draw_line16(void *opaque, uint8_t *dest, const uint8_t *src,
555
+ int width, int deststep)
556
+{
557
+ uint32_t data;
558
+ unsigned int r, g, b;
559
+ while (width > 0) {
560
+ data = *(uint32_t *) src;
561
+#ifdef SWAP_WORDS
562
+ data = bswap32(data);
563
+#endif
564
+ b = (data & 0x1f) << 3;
565
+ data >>= 5;
566
+ g = (data & 0x3f) << 2;
567
+ data >>= 6;
568
+ r = (data & 0x1f) << 3;
569
+ data >>= 5;
570
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
571
+ b = (data & 0x1f) << 3;
572
+ data >>= 5;
573
+ g = (data & 0x3f) << 2;
574
+ data >>= 6;
575
+ r = (data & 0x1f) << 3;
576
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
577
+ width -= 2;
578
+ src += 4;
579
+ }
580
+}
581
+
582
+static void pxa2xx_draw_line16t(void *opaque, uint8_t *dest, const uint8_t *src,
583
+ int width, int deststep)
584
+{
585
+ uint32_t data;
586
+ unsigned int r, g, b;
587
+ while (width > 0) {
588
+ data = *(uint32_t *) src;
589
+#ifdef SWAP_WORDS
590
+ data = bswap32(data);
591
+#endif
592
+ b = (data & 0x1f) << 3;
593
+ data >>= 5;
594
+ g = (data & 0x1f) << 3;
595
+ data >>= 5;
596
+ r = (data & 0x1f) << 3;
597
+ data >>= 5;
598
+ if (data & 1) {
599
+ SKIP_PIXEL(dest);
600
+ } else {
601
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
100
+ }
602
+ }
101
+ }
603
+ data >>= 1;
102
dpy_gfx_update_full(s->con);
604
+ b = (data & 0x1f) << 3;
103
}
605
+ data >>= 5;
104
606
+ g = (data & 0x1f) << 3;
607
+ data >>= 5;
608
+ r = (data & 0x1f) << 3;
609
+ data >>= 5;
610
+ if (data & 1) {
611
+ SKIP_PIXEL(dest);
612
+ } else {
613
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
614
+ }
615
+ width -= 2;
616
+ src += 4;
617
+ }
618
+}
619
+
620
+static void pxa2xx_draw_line18(void *opaque, uint8_t *dest, const uint8_t *src,
621
+ int width, int deststep)
622
+{
623
+ uint32_t data;
624
+ unsigned int r, g, b;
625
+ while (width > 0) {
626
+ data = *(uint32_t *) src;
627
+#ifdef SWAP_WORDS
628
+ data = bswap32(data);
629
+#endif
630
+ b = (data & 0x3f) << 2;
631
+ data >>= 6;
632
+ g = (data & 0x3f) << 2;
633
+ data >>= 6;
634
+ r = (data & 0x3f) << 2;
635
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
636
+ width -= 1;
637
+ src += 4;
638
+ }
639
+}
640
+
641
+/* The wicked packed format */
642
+static void pxa2xx_draw_line18p(void *opaque, uint8_t *dest, const uint8_t *src,
643
+ int width, int deststep)
644
+{
645
+ uint32_t data[3];
646
+ unsigned int r, g, b;
647
+ while (width > 0) {
648
+ data[0] = *(uint32_t *) src;
649
+ src += 4;
650
+ data[1] = *(uint32_t *) src;
651
+ src += 4;
652
+ data[2] = *(uint32_t *) src;
653
+ src += 4;
654
+#ifdef SWAP_WORDS
655
+ data[0] = bswap32(data[0]);
656
+ data[1] = bswap32(data[1]);
657
+ data[2] = bswap32(data[2]);
658
+#endif
659
+ b = (data[0] & 0x3f) << 2;
660
+ data[0] >>= 6;
661
+ g = (data[0] & 0x3f) << 2;
662
+ data[0] >>= 6;
663
+ r = (data[0] & 0x3f) << 2;
664
+ data[0] >>= 12;
665
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
666
+ b = (data[0] & 0x3f) << 2;
667
+ data[0] >>= 6;
668
+ g = ((data[1] & 0xf) << 4) | (data[0] << 2);
669
+ data[1] >>= 4;
670
+ r = (data[1] & 0x3f) << 2;
671
+ data[1] >>= 12;
672
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
673
+ b = (data[1] & 0x3f) << 2;
674
+ data[1] >>= 6;
675
+ g = (data[1] & 0x3f) << 2;
676
+ data[1] >>= 6;
677
+ r = ((data[2] & 0x3) << 6) | (data[1] << 2);
678
+ data[2] >>= 8;
679
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
680
+ b = (data[2] & 0x3f) << 2;
681
+ data[2] >>= 6;
682
+ g = (data[2] & 0x3f) << 2;
683
+ data[2] >>= 6;
684
+ r = data[2] << 2;
685
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
686
+ width -= 4;
687
+ }
688
+}
689
+
690
+static void pxa2xx_draw_line19(void *opaque, uint8_t *dest, const uint8_t *src,
691
+ int width, int deststep)
692
+{
693
+ uint32_t data;
694
+ unsigned int r, g, b;
695
+ while (width > 0) {
696
+ data = *(uint32_t *) src;
697
+#ifdef SWAP_WORDS
698
+ data = bswap32(data);
699
+#endif
700
+ b = (data & 0x3f) << 2;
701
+ data >>= 6;
702
+ g = (data & 0x3f) << 2;
703
+ data >>= 6;
704
+ r = (data & 0x3f) << 2;
705
+ data >>= 6;
706
+ if (data & 1) {
707
+ SKIP_PIXEL(dest);
708
+ } else {
709
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
710
+ }
711
+ width -= 1;
712
+ src += 4;
713
+ }
714
+}
715
+
716
+/* The wicked packed format */
717
+static void pxa2xx_draw_line19p(void *opaque, uint8_t *dest, const uint8_t *src,
718
+ int width, int deststep)
719
+{
720
+ uint32_t data[3];
721
+ unsigned int r, g, b;
722
+ while (width > 0) {
723
+ data[0] = *(uint32_t *) src;
724
+ src += 4;
725
+ data[1] = *(uint32_t *) src;
726
+ src += 4;
727
+ data[2] = *(uint32_t *) src;
728
+ src += 4;
729
+# ifdef SWAP_WORDS
730
+ data[0] = bswap32(data[0]);
731
+ data[1] = bswap32(data[1]);
732
+ data[2] = bswap32(data[2]);
733
+# endif
734
+ b = (data[0] & 0x3f) << 2;
735
+ data[0] >>= 6;
736
+ g = (data[0] & 0x3f) << 2;
737
+ data[0] >>= 6;
738
+ r = (data[0] & 0x3f) << 2;
739
+ data[0] >>= 6;
740
+ if (data[0] & 1) {
741
+ SKIP_PIXEL(dest);
742
+ } else {
743
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
744
+ }
745
+ data[0] >>= 6;
746
+ b = (data[0] & 0x3f) << 2;
747
+ data[0] >>= 6;
748
+ g = ((data[1] & 0xf) << 4) | (data[0] << 2);
749
+ data[1] >>= 4;
750
+ r = (data[1] & 0x3f) << 2;
751
+ data[1] >>= 6;
752
+ if (data[1] & 1) {
753
+ SKIP_PIXEL(dest);
754
+ } else {
755
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
756
+ }
757
+ data[1] >>= 6;
758
+ b = (data[1] & 0x3f) << 2;
759
+ data[1] >>= 6;
760
+ g = (data[1] & 0x3f) << 2;
761
+ data[1] >>= 6;
762
+ r = ((data[2] & 0x3) << 6) | (data[1] << 2);
763
+ data[2] >>= 2;
764
+ if (data[2] & 1) {
765
+ SKIP_PIXEL(dest);
766
+ } else {
767
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
768
+ }
769
+ data[2] >>= 6;
770
+ b = (data[2] & 0x3f) << 2;
771
+ data[2] >>= 6;
772
+ g = (data[2] & 0x3f) << 2;
773
+ data[2] >>= 6;
774
+ r = data[2] << 2;
775
+ data[2] >>= 6;
776
+ if (data[2] & 1) {
777
+ SKIP_PIXEL(dest);
778
+ } else {
779
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
780
+ }
781
+ width -= 4;
782
+ }
783
+}
784
+
785
+static void pxa2xx_draw_line24(void *opaque, uint8_t *dest, const uint8_t *src,
786
+ int width, int deststep)
787
+{
788
+ uint32_t data;
789
+ unsigned int r, g, b;
790
+ while (width > 0) {
791
+ data = *(uint32_t *) src;
792
+#ifdef SWAP_WORDS
793
+ data = bswap32(data);
794
+#endif
795
+ b = data & 0xff;
796
+ data >>= 8;
797
+ g = data & 0xff;
798
+ data >>= 8;
799
+ r = data & 0xff;
800
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
801
+ width -= 1;
802
+ src += 4;
803
+ }
804
+}
805
+
806
+static void pxa2xx_draw_line24t(void *opaque, uint8_t *dest, const uint8_t *src,
807
+ int width, int deststep)
808
+{
809
+ uint32_t data;
810
+ unsigned int r, g, b;
811
+ while (width > 0) {
812
+ data = *(uint32_t *) src;
813
+#ifdef SWAP_WORDS
814
+ data = bswap32(data);
815
+#endif
816
+ b = (data & 0x7f) << 1;
817
+ data >>= 7;
818
+ g = data & 0xff;
819
+ data >>= 8;
820
+ r = data & 0xff;
821
+ data >>= 8;
822
+ if (data & 1) {
823
+ SKIP_PIXEL(dest);
824
+ } else {
825
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
826
+ }
827
+ width -= 1;
828
+ src += 4;
829
+ }
830
+}
831
+
832
+static void pxa2xx_draw_line25(void *opaque, uint8_t *dest, const uint8_t *src,
833
+ int width, int deststep)
834
+{
835
+ uint32_t data;
836
+ unsigned int r, g, b;
837
+ while (width > 0) {
838
+ data = *(uint32_t *) src;
839
+#ifdef SWAP_WORDS
840
+ data = bswap32(data);
841
+#endif
842
+ b = data & 0xff;
843
+ data >>= 8;
844
+ g = data & 0xff;
845
+ data >>= 8;
846
+ r = data & 0xff;
847
+ data >>= 8;
848
+ if (data & 1) {
849
+ SKIP_PIXEL(dest);
850
+ } else {
851
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
852
+ }
853
+ width -= 1;
854
+ src += 4;
855
+ }
856
+}
857
+
858
+/* Overlay planes disabled, no transparency */
859
+static drawfn pxa2xx_draw_fn_32[16] = {
860
+ [0 ... 0xf] = NULL,
861
+ [pxa_lcdc_2bpp] = pxa2xx_draw_line2,
862
+ [pxa_lcdc_4bpp] = pxa2xx_draw_line4,
863
+ [pxa_lcdc_8bpp] = pxa2xx_draw_line8,
864
+ [pxa_lcdc_16bpp] = pxa2xx_draw_line16,
865
+ [pxa_lcdc_18bpp] = pxa2xx_draw_line18,
866
+ [pxa_lcdc_18pbpp] = pxa2xx_draw_line18p,
867
+ [pxa_lcdc_24bpp] = pxa2xx_draw_line24,
868
+};
869
+
870
+/* Overlay planes enabled, transparency used */
871
+static drawfn pxa2xx_draw_fn_32t[16] = {
872
+ [0 ... 0xf] = NULL,
873
+ [pxa_lcdc_4bpp] = pxa2xx_draw_line4,
874
+ [pxa_lcdc_8bpp] = pxa2xx_draw_line8,
875
+ [pxa_lcdc_16bpp] = pxa2xx_draw_line16t,
876
+ [pxa_lcdc_19bpp] = pxa2xx_draw_line19,
877
+ [pxa_lcdc_19pbpp] = pxa2xx_draw_line19p,
878
+ [pxa_lcdc_24bpp] = pxa2xx_draw_line24t,
879
+ [pxa_lcdc_25bpp] = pxa2xx_draw_line25,
880
+};
881
+
882
+#undef COPY_PIXEL
883
+#undef SKIP_PIXEL
884
+
885
+#ifdef SWAP_WORDS
886
+# undef SWAP_WORDS
887
+#endif
888
889
/* Route internal interrupt lines to the global IC */
890
static void pxa2xx_lcdc_int_update(PXA2xxLCDState *s)
105
--
891
--
106
2.20.1
892
2.20.1
107
893
108
894
diff view generated by jsdifflib
Deleted patch
1
The omap_lcdc template header is already only included once, for
2
DEPTH==32, but it still has all the macro-driven parameterization
3
for other depths. Expand out all the macros in the header.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210215103215.4944-6-peter.maydell@linaro.org
9
---
10
hw/display/omap_lcd_template.h | 67 ++++++++++++++--------------------
11
1 file changed, 28 insertions(+), 39 deletions(-)
12
13
diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/display/omap_lcd_template.h
16
+++ b/hw/display/omap_lcd_template.h
17
@@ -XXX,XX +XXX,XX @@
18
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19
*/
20
21
-#if DEPTH == 32
22
-# define BPP 4
23
-# define PIXEL_TYPE uint32_t
24
-#else
25
-# error unsupport depth
26
-#endif
27
-
28
/*
29
* 2-bit colour
30
*/
31
-static void glue(draw_line2_, DEPTH)(void *opaque,
32
- uint8_t *d, const uint8_t *s, int width, int deststep)
33
+static void draw_line2_32(void *opaque, uint8_t *d, const uint8_t *s,
34
+ int width, int deststep)
35
{
36
uint16_t *pal = opaque;
37
uint8_t v, r, g, b;
38
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line2_, DEPTH)(void *opaque,
39
r = (pal[v & 3] >> 4) & 0xf0;
40
g = pal[v & 3] & 0xf0;
41
b = (pal[v & 3] << 4) & 0xf0;
42
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
43
- d += BPP;
44
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
45
+ d += 4;
46
v >>= 2;
47
r = (pal[v & 3] >> 4) & 0xf0;
48
g = pal[v & 3] & 0xf0;
49
b = (pal[v & 3] << 4) & 0xf0;
50
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
51
- d += BPP;
52
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
53
+ d += 4;
54
v >>= 2;
55
r = (pal[v & 3] >> 4) & 0xf0;
56
g = pal[v & 3] & 0xf0;
57
b = (pal[v & 3] << 4) & 0xf0;
58
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
59
- d += BPP;
60
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
61
+ d += 4;
62
v >>= 2;
63
r = (pal[v & 3] >> 4) & 0xf0;
64
g = pal[v & 3] & 0xf0;
65
b = (pal[v & 3] << 4) & 0xf0;
66
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
67
- d += BPP;
68
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
69
+ d += 4;
70
s ++;
71
width -= 4;
72
} while (width > 0);
73
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line2_, DEPTH)(void *opaque,
74
/*
75
* 4-bit colour
76
*/
77
-static void glue(draw_line4_, DEPTH)(void *opaque,
78
- uint8_t *d, const uint8_t *s, int width, int deststep)
79
+static void draw_line4_32(void *opaque, uint8_t *d, const uint8_t *s,
80
+ int width, int deststep)
81
{
82
uint16_t *pal = opaque;
83
uint8_t v, r, g, b;
84
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line4_, DEPTH)(void *opaque,
85
r = (pal[v & 0xf] >> 4) & 0xf0;
86
g = pal[v & 0xf] & 0xf0;
87
b = (pal[v & 0xf] << 4) & 0xf0;
88
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
89
- d += BPP;
90
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
91
+ d += 4;
92
v >>= 4;
93
r = (pal[v & 0xf] >> 4) & 0xf0;
94
g = pal[v & 0xf] & 0xf0;
95
b = (pal[v & 0xf] << 4) & 0xf0;
96
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
97
- d += BPP;
98
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
99
+ d += 4;
100
s ++;
101
width -= 2;
102
} while (width > 0);
103
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line4_, DEPTH)(void *opaque,
104
/*
105
* 8-bit colour
106
*/
107
-static void glue(draw_line8_, DEPTH)(void *opaque,
108
- uint8_t *d, const uint8_t *s, int width, int deststep)
109
+static void draw_line8_32(void *opaque, uint8_t *d, const uint8_t *s,
110
+ int width, int deststep)
111
{
112
uint16_t *pal = opaque;
113
uint8_t v, r, g, b;
114
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line8_, DEPTH)(void *opaque,
115
r = (pal[v] >> 4) & 0xf0;
116
g = pal[v] & 0xf0;
117
b = (pal[v] << 4) & 0xf0;
118
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
119
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
120
s ++;
121
- d += BPP;
122
+ d += 4;
123
} while (-- width != 0);
124
}
125
126
/*
127
* 12-bit colour
128
*/
129
-static void glue(draw_line12_, DEPTH)(void *opaque,
130
- uint8_t *d, const uint8_t *s, int width, int deststep)
131
+static void draw_line12_32(void *opaque, uint8_t *d, const uint8_t *s,
132
+ int width, int deststep)
133
{
134
uint16_t v;
135
uint8_t r, g, b;
136
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line12_, DEPTH)(void *opaque,
137
r = (v >> 4) & 0xf0;
138
g = v & 0xf0;
139
b = (v << 4) & 0xf0;
140
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
141
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
142
s += 2;
143
- d += BPP;
144
+ d += 4;
145
} while (-- width != 0);
146
}
147
148
/*
149
* 16-bit colour
150
*/
151
-static void glue(draw_line16_, DEPTH)(void *opaque,
152
- uint8_t *d, const uint8_t *s, int width, int deststep)
153
+static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
154
+ int width, int deststep)
155
{
156
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
157
memcpy(d, s, width * 2);
158
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line16_, DEPTH)(void *opaque,
159
r = (v >> 8) & 0xf8;
160
g = (v >> 3) & 0xfc;
161
b = (v << 3) & 0xf8;
162
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
163
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
164
s += 2;
165
- d += BPP;
166
+ d += 4;
167
} while (-- width != 0);
168
#endif
169
}
170
-
171
-#undef DEPTH
172
-#undef BPP
173
-#undef PIXEL_TYPE
174
--
175
2.20.1
176
177
diff view generated by jsdifflib
Deleted patch
1
The draw_line16_32() function in the omap_lcdc template header
2
includes an ifdef for the case where HOST_WORDS_BIGENDIAN matches
3
TARGET_WORDS_BIGENDIAN. This is trying to optimise for "source
4
bitmap and destination bitmap format match", but it is broken,
5
because in this function the formats don't match: the source is
6
16-bit colour and the destination is 32-bit colour, so a memcpy()
7
will produce corrupted graphics output. Drop the bogus ifdef.
8
1
9
This bug was introduced in commit ea644cf343129, when we dropped
10
support for DEPTH values other than 32 from the template header.
11
The old #if line was
12
#if DEPTH == 16 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
13
and this was mistakenly changed to
14
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
15
rather than deleting the #if as now having an always-false condition.
16
17
Fixes: ea644cf343129
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
21
Message-id: 20210215103215.4944-7-peter.maydell@linaro.org
22
---
23
hw/display/omap_lcd_template.h | 4 ----
24
1 file changed, 4 deletions(-)
25
26
diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/display/omap_lcd_template.h
29
+++ b/hw/display/omap_lcd_template.h
30
@@ -XXX,XX +XXX,XX @@ static void draw_line12_32(void *opaque, uint8_t *d, const uint8_t *s,
31
static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
32
int width, int deststep)
33
{
34
-#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
35
- memcpy(d, s, width * 2);
36
-#else
37
uint16_t v;
38
uint8_t r, g, b;
39
40
@@ -XXX,XX +XXX,XX @@ static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
41
s += 2;
42
d += 4;
43
} while (-- width != 0);
44
-#endif
45
}
46
--
47
2.20.1
48
49
diff view generated by jsdifflib
Deleted patch
1
Fix some minor coding style issues in the template header,
2
so checkpatch doesn't complain when we move the code.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20210215103215.4944-8-peter.maydell@linaro.org
8
---
9
hw/display/omap_lcd_template.h | 6 +++---
10
1 file changed, 3 insertions(+), 3 deletions(-)
11
12
diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/display/omap_lcd_template.h
15
+++ b/hw/display/omap_lcd_template.h
16
@@ -XXX,XX +XXX,XX @@ static void draw_line2_32(void *opaque, uint8_t *d, const uint8_t *s,
17
b = (pal[v & 3] << 4) & 0xf0;
18
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
19
d += 4;
20
- s ++;
21
+ s++;
22
width -= 4;
23
} while (width > 0);
24
}
25
@@ -XXX,XX +XXX,XX @@ static void draw_line4_32(void *opaque, uint8_t *d, const uint8_t *s,
26
b = (pal[v & 0xf] << 4) & 0xf0;
27
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
28
d += 4;
29
- s ++;
30
+ s++;
31
width -= 2;
32
} while (width > 0);
33
}
34
@@ -XXX,XX +XXX,XX @@ static void draw_line8_32(void *opaque, uint8_t *d, const uint8_t *s,
35
g = pal[v] & 0xf0;
36
b = (pal[v] << 4) & 0xf0;
37
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
38
- s ++;
39
+ s++;
40
d += 4;
41
} while (-- width != 0);
42
}
43
--
44
2.20.1
45
46
diff view generated by jsdifflib
Deleted patch
1
We only include the template header once, so just inline it into the
2
source file for the device.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20210215103215.4944-9-peter.maydell@linaro.org
8
---
9
hw/display/omap_lcd_template.h | 154 ---------------------------------
10
hw/display/omap_lcdc.c | 127 ++++++++++++++++++++++++++-
11
2 files changed, 125 insertions(+), 156 deletions(-)
12
delete mode 100644 hw/display/omap_lcd_template.h
13
14
diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h
15
deleted file mode 100644
16
index XXXXXXX..XXXXXXX
17
--- a/hw/display/omap_lcd_template.h
18
+++ /dev/null
19
@@ -XXX,XX +XXX,XX @@
20
-/*
21
- * QEMU OMAP LCD Emulator templates
22
- *
23
- * Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org>
24
- *
25
- * Redistribution and use in source and binary forms, with or without
26
- * modification, are permitted provided that the following conditions
27
- * are met:
28
- *
29
- * 1. Redistributions of source code must retain the above copyright
30
- * notice, this list of conditions and the following disclaimer.
31
- * 2. Redistributions in binary form must reproduce the above copyright
32
- * notice, this list of conditions and the following disclaimer in
33
- * the documentation and/or other materials provided with the
34
- * distribution.
35
- *
36
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
37
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
38
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
39
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
40
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
41
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
42
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
43
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
44
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
46
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47
- */
48
-
49
-/*
50
- * 2-bit colour
51
- */
52
-static void draw_line2_32(void *opaque, uint8_t *d, const uint8_t *s,
53
- int width, int deststep)
54
-{
55
- uint16_t *pal = opaque;
56
- uint8_t v, r, g, b;
57
-
58
- do {
59
- v = ldub_p((void *) s);
60
- r = (pal[v & 3] >> 4) & 0xf0;
61
- g = pal[v & 3] & 0xf0;
62
- b = (pal[v & 3] << 4) & 0xf0;
63
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
64
- d += 4;
65
- v >>= 2;
66
- r = (pal[v & 3] >> 4) & 0xf0;
67
- g = pal[v & 3] & 0xf0;
68
- b = (pal[v & 3] << 4) & 0xf0;
69
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
70
- d += 4;
71
- v >>= 2;
72
- r = (pal[v & 3] >> 4) & 0xf0;
73
- g = pal[v & 3] & 0xf0;
74
- b = (pal[v & 3] << 4) & 0xf0;
75
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
76
- d += 4;
77
- v >>= 2;
78
- r = (pal[v & 3] >> 4) & 0xf0;
79
- g = pal[v & 3] & 0xf0;
80
- b = (pal[v & 3] << 4) & 0xf0;
81
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
82
- d += 4;
83
- s++;
84
- width -= 4;
85
- } while (width > 0);
86
-}
87
-
88
-/*
89
- * 4-bit colour
90
- */
91
-static void draw_line4_32(void *opaque, uint8_t *d, const uint8_t *s,
92
- int width, int deststep)
93
-{
94
- uint16_t *pal = opaque;
95
- uint8_t v, r, g, b;
96
-
97
- do {
98
- v = ldub_p((void *) s);
99
- r = (pal[v & 0xf] >> 4) & 0xf0;
100
- g = pal[v & 0xf] & 0xf0;
101
- b = (pal[v & 0xf] << 4) & 0xf0;
102
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
103
- d += 4;
104
- v >>= 4;
105
- r = (pal[v & 0xf] >> 4) & 0xf0;
106
- g = pal[v & 0xf] & 0xf0;
107
- b = (pal[v & 0xf] << 4) & 0xf0;
108
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
109
- d += 4;
110
- s++;
111
- width -= 2;
112
- } while (width > 0);
113
-}
114
-
115
-/*
116
- * 8-bit colour
117
- */
118
-static void draw_line8_32(void *opaque, uint8_t *d, const uint8_t *s,
119
- int width, int deststep)
120
-{
121
- uint16_t *pal = opaque;
122
- uint8_t v, r, g, b;
123
-
124
- do {
125
- v = ldub_p((void *) s);
126
- r = (pal[v] >> 4) & 0xf0;
127
- g = pal[v] & 0xf0;
128
- b = (pal[v] << 4) & 0xf0;
129
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
130
- s++;
131
- d += 4;
132
- } while (-- width != 0);
133
-}
134
-
135
-/*
136
- * 12-bit colour
137
- */
138
-static void draw_line12_32(void *opaque, uint8_t *d, const uint8_t *s,
139
- int width, int deststep)
140
-{
141
- uint16_t v;
142
- uint8_t r, g, b;
143
-
144
- do {
145
- v = lduw_le_p((void *) s);
146
- r = (v >> 4) & 0xf0;
147
- g = v & 0xf0;
148
- b = (v << 4) & 0xf0;
149
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
150
- s += 2;
151
- d += 4;
152
- } while (-- width != 0);
153
-}
154
-
155
-/*
156
- * 16-bit colour
157
- */
158
-static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
159
- int width, int deststep)
160
-{
161
- uint16_t v;
162
- uint8_t r, g, b;
163
-
164
- do {
165
- v = lduw_le_p((void *) s);
166
- r = (v >> 8) & 0xf8;
167
- g = (v >> 3) & 0xfc;
168
- b = (v << 3) & 0xf8;
169
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
170
- s += 2;
171
- d += 4;
172
- } while (-- width != 0);
173
-}
174
diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c
175
index XXXXXXX..XXXXXXX 100644
176
--- a/hw/display/omap_lcdc.c
177
+++ b/hw/display/omap_lcdc.c
178
@@ -XXX,XX +XXX,XX @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s)
179
180
#define draw_line_func drawfn
181
182
-#define DEPTH 32
183
-#include "omap_lcd_template.h"
184
+/*
185
+ * 2-bit colour
186
+ */
187
+static void draw_line2_32(void *opaque, uint8_t *d, const uint8_t *s,
188
+ int width, int deststep)
189
+{
190
+ uint16_t *pal = opaque;
191
+ uint8_t v, r, g, b;
192
+
193
+ do {
194
+ v = ldub_p((void *) s);
195
+ r = (pal[v & 3] >> 4) & 0xf0;
196
+ g = pal[v & 3] & 0xf0;
197
+ b = (pal[v & 3] << 4) & 0xf0;
198
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
199
+ d += 4;
200
+ v >>= 2;
201
+ r = (pal[v & 3] >> 4) & 0xf0;
202
+ g = pal[v & 3] & 0xf0;
203
+ b = (pal[v & 3] << 4) & 0xf0;
204
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
205
+ d += 4;
206
+ v >>= 2;
207
+ r = (pal[v & 3] >> 4) & 0xf0;
208
+ g = pal[v & 3] & 0xf0;
209
+ b = (pal[v & 3] << 4) & 0xf0;
210
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
211
+ d += 4;
212
+ v >>= 2;
213
+ r = (pal[v & 3] >> 4) & 0xf0;
214
+ g = pal[v & 3] & 0xf0;
215
+ b = (pal[v & 3] << 4) & 0xf0;
216
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
217
+ d += 4;
218
+ s++;
219
+ width -= 4;
220
+ } while (width > 0);
221
+}
222
+
223
+/*
224
+ * 4-bit colour
225
+ */
226
+static void draw_line4_32(void *opaque, uint8_t *d, const uint8_t *s,
227
+ int width, int deststep)
228
+{
229
+ uint16_t *pal = opaque;
230
+ uint8_t v, r, g, b;
231
+
232
+ do {
233
+ v = ldub_p((void *) s);
234
+ r = (pal[v & 0xf] >> 4) & 0xf0;
235
+ g = pal[v & 0xf] & 0xf0;
236
+ b = (pal[v & 0xf] << 4) & 0xf0;
237
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
238
+ d += 4;
239
+ v >>= 4;
240
+ r = (pal[v & 0xf] >> 4) & 0xf0;
241
+ g = pal[v & 0xf] & 0xf0;
242
+ b = (pal[v & 0xf] << 4) & 0xf0;
243
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
244
+ d += 4;
245
+ s++;
246
+ width -= 2;
247
+ } while (width > 0);
248
+}
249
+
250
+/*
251
+ * 8-bit colour
252
+ */
253
+static void draw_line8_32(void *opaque, uint8_t *d, const uint8_t *s,
254
+ int width, int deststep)
255
+{
256
+ uint16_t *pal = opaque;
257
+ uint8_t v, r, g, b;
258
+
259
+ do {
260
+ v = ldub_p((void *) s);
261
+ r = (pal[v] >> 4) & 0xf0;
262
+ g = pal[v] & 0xf0;
263
+ b = (pal[v] << 4) & 0xf0;
264
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
265
+ s++;
266
+ d += 4;
267
+ } while (-- width != 0);
268
+}
269
+
270
+/*
271
+ * 12-bit colour
272
+ */
273
+static void draw_line12_32(void *opaque, uint8_t *d, const uint8_t *s,
274
+ int width, int deststep)
275
+{
276
+ uint16_t v;
277
+ uint8_t r, g, b;
278
+
279
+ do {
280
+ v = lduw_le_p((void *) s);
281
+ r = (v >> 4) & 0xf0;
282
+ g = v & 0xf0;
283
+ b = (v << 4) & 0xf0;
284
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
285
+ s += 2;
286
+ d += 4;
287
+ } while (-- width != 0);
288
+}
289
+
290
+/*
291
+ * 16-bit colour
292
+ */
293
+static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
294
+ int width, int deststep)
295
+{
296
+ uint16_t v;
297
+ uint8_t r, g, b;
298
+
299
+ do {
300
+ v = lduw_le_p((void *) s);
301
+ r = (v >> 8) & 0xf8;
302
+ g = (v >> 3) & 0xfc;
303
+ b = (v << 3) & 0xf8;
304
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
305
+ s += 2;
306
+ d += 4;
307
+ } while (-- width != 0);
308
+}
309
310
static void omap_update_display(void *opaque)
311
{
312
--
313
2.20.1
314
315
diff view generated by jsdifflib
Deleted patch
1
The macro draw_line_func is used only once; just expand it.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20210215103215.4944-10-peter.maydell@linaro.org
7
---
8
hw/display/omap_lcdc.c | 4 +---
9
1 file changed, 1 insertion(+), 3 deletions(-)
10
11
diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/display/omap_lcdc.c
14
+++ b/hw/display/omap_lcdc.c
15
@@ -XXX,XX +XXX,XX @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s)
16
qemu_irq_lower(s->irq);
17
}
18
19
-#define draw_line_func drawfn
20
-
21
/*
22
* 2-bit colour
23
*/
24
@@ -XXX,XX +XXX,XX @@ static void omap_update_display(void *opaque)
25
{
26
struct omap_lcd_panel_s *omap_lcd = (struct omap_lcd_panel_s *) opaque;
27
DisplaySurface *surface;
28
- draw_line_func draw_line;
29
+ drawfn draw_line;
30
int size, height, first, last;
31
int width, linesize, step, bpp, frame_offset;
32
hwaddr frame_base;
33
--
34
2.20.1
35
36
diff view generated by jsdifflib
Deleted patch
1
For a long time now the UI layer has guaranteed that the console
2
surface is always 32 bits per pixel, RGB. The TCX code already
3
assumes 32bpp, but it still has some checks of is_surface_bgr()
4
in an attempt to support 32bpp BGR. is_surface_bgr() will always
5
return false for the qemu_console_surface(), unless the display
6
device itself has deliberately created an alternate-format
7
surface via a function like qemu_create_displaysurface_from().
8
1
9
Drop the never-used BGR-handling code, and assert that we have
10
a 32-bit surface rather than just doing nothing if it isn't.
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20210215102149.20513-1-peter.maydell@linaro.org
16
---
17
hw/display/tcx.c | 31 ++++++++-----------------------
18
1 file changed, 8 insertions(+), 23 deletions(-)
19
20
diff --git a/hw/display/tcx.c b/hw/display/tcx.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/display/tcx.c
23
+++ b/hw/display/tcx.c
24
@@ -XXX,XX +XXX,XX @@ static int tcx_check_dirty(TCXState *s, DirtyBitmapSnapshot *snap,
25
26
static void update_palette_entries(TCXState *s, int start, int end)
27
{
28
- DisplaySurface *surface = qemu_console_surface(s->con);
29
int i;
30
31
for (i = start; i < end; i++) {
32
- if (is_surface_bgr(surface)) {
33
- s->palette[i] = rgb_to_pixel32bgr(s->r[i], s->g[i], s->b[i]);
34
- } else {
35
- s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
36
- }
37
+ s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
38
}
39
tcx_set_dirty(s, 0, memory_region_size(&s->vram_mem));
40
}
41
@@ -XXX,XX +XXX,XX @@ static void tcx_draw_cursor32(TCXState *s1, uint8_t *d,
42
}
43
44
/*
45
- XXX Could be much more optimal:
46
- * detect if line/page/whole screen is in 24 bit mode
47
- * if destination is also BGR, use memcpy
48
- */
49
+ * XXX Could be much more optimal:
50
+ * detect if line/page/whole screen is in 24 bit mode
51
+ */
52
static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
53
const uint8_t *s, int width,
54
const uint32_t *cplane,
55
const uint32_t *s24)
56
{
57
- DisplaySurface *surface = qemu_console_surface(s1->con);
58
- int x, bgr, r, g, b;
59
+ int x, r, g, b;
60
uint8_t val, *p8;
61
uint32_t *p = (uint32_t *)d;
62
uint32_t dval;
63
- bgr = is_surface_bgr(surface);
64
for(x = 0; x < width; x++, s++, s24++) {
65
if (be32_to_cpu(*cplane) & 0x03000000) {
66
/* 24-bit direct, BGR order */
67
@@ -XXX,XX +XXX,XX @@ static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
68
b = *p8++;
69
g = *p8++;
70
r = *p8;
71
- if (bgr)
72
- dval = rgb_to_pixel32bgr(r, g, b);
73
- else
74
- dval = rgb_to_pixel32(r, g, b);
75
+ dval = rgb_to_pixel32(r, g, b);
76
} else {
77
/* 8-bit pseudocolor */
78
val = *s;
79
@@ -XXX,XX +XXX,XX @@ static void tcx_update_display(void *opaque)
80
int y, y_start, dd, ds;
81
uint8_t *d, *s;
82
83
- if (surface_bits_per_pixel(surface) != 32) {
84
- return;
85
- }
86
+ assert(surface_bits_per_pixel(surface) == 32);
87
88
page = 0;
89
y_start = -1;
90
@@ -XXX,XX +XXX,XX @@ static void tcx24_update_display(void *opaque)
91
uint8_t *d, *s;
92
uint32_t *cptr, *s24;
93
94
- if (surface_bits_per_pixel(surface) != 32) {
95
- return;
96
- }
97
+ assert(surface_bits_per_pixel(surface) == 32);
98
99
page = 0;
100
y_start = -1;
101
--
102
2.20.1
103
104
diff view generated by jsdifflib
Deleted patch
1
The AN524 has a different SYSCLK frequency from the AN505 and AN521;
2
make the SYSCLK frequency a field in the MPS2TZMachineClass rather
3
than a compile-time constant so we can support the AN524.
4
1
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: 20210215115138.20465-2-peter.maydell@linaro.org
9
---
10
hw/arm/mps2-tz.c | 10 ++++++----
11
1 file changed, 6 insertions(+), 4 deletions(-)
12
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/mps2-tz.c
16
+++ b/hw/arm/mps2-tz.c
17
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
18
MachineClass parent;
19
MPS2TZFPGAType fpga_type;
20
uint32_t scc_id;
21
+ uint32_t sysclk_frq; /* Main SYSCLK frequency in Hz */
22
const char *armsse_type;
23
};
24
25
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
26
27
OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
28
29
-/* Main SYSCLK frequency in Hz */
30
-#define SYSCLK_FRQ 20000000
31
/* Slow 32Khz S32KCLK frequency in Hz */
32
#define S32KCLK_FRQ (32 * 1000)
33
34
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
35
static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
36
const char *name, hwaddr size)
37
{
38
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
39
CMSDKAPBUART *uart = opaque;
40
int i = uart - &mms->uart[0];
41
int rxirqno = i * 2;
42
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
43
44
object_initialize_child(OBJECT(mms), name, uart, TYPE_CMSDK_APB_UART);
45
qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i));
46
- qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", SYSCLK_FRQ);
47
+ qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", mmc->sysclk_frq);
48
sysbus_realize(SYS_BUS_DEVICE(uart), &error_fatal);
49
s = SYS_BUS_DEVICE(uart);
50
sysbus_connect_irq(s, 0, get_sse_irq_in(mms, txirqno));
51
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
52
53
/* These clocks don't need migration because they are fixed-frequency */
54
mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
55
- clock_set_hz(mms->sysclk, SYSCLK_FRQ);
56
+ clock_set_hz(mms->sysclk, mmc->sysclk_frq);
57
mms->s32kclk = clock_new(OBJECT(machine), "S32KCLK");
58
clock_set_hz(mms->s32kclk, S32KCLK_FRQ);
59
60
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
61
mmc->fpga_type = FPGA_AN505;
62
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
63
mmc->scc_id = 0x41045050;
64
+ mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
65
mmc->armsse_type = TYPE_IOTKIT;
66
}
67
68
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
69
mmc->fpga_type = FPGA_AN521;
70
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
71
mmc->scc_id = 0x41045210;
72
+ mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
73
mmc->armsse_type = TYPE_SSE200;
74
}
75
76
--
77
2.20.1
78
79
diff view generated by jsdifflib
Deleted patch
1
The AN524 version of the SCC interface has different behaviour for
2
some of the CFG registers; implement it.
3
1
4
Each board in this family can have minor differences in the meaning
5
of the CFG registers, so rather than trying to specify all the
6
possible semantics via individual device properties, we make the
7
behaviour conditional on the part-number field of the SCC_ID register
8
which the board code already passes us.
9
10
For the AN524, the differences are:
11
* CFG3 is reserved rather than being board switches
12
* CFG5 is a new register ("ACLK Frequency in Hz")
13
* CFG6 is a new register ("Clock divider for BRAM")
14
15
We implement both of the new registers as reads-as-written.
16
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Message-id: 20210215115138.20465-11-peter.maydell@linaro.org
20
---
21
include/hw/misc/mps2-scc.h | 3 ++
22
hw/misc/mps2-scc.c | 71 ++++++++++++++++++++++++++++++++++++--
23
2 files changed, 72 insertions(+), 2 deletions(-)
24
25
diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/include/hw/misc/mps2-scc.h
28
+++ b/include/hw/misc/mps2-scc.h
29
@@ -XXX,XX +XXX,XX @@ struct MPS2SCC {
30
31
uint32_t cfg0;
32
uint32_t cfg1;
33
+ uint32_t cfg2;
34
uint32_t cfg4;
35
+ uint32_t cfg5;
36
+ uint32_t cfg6;
37
uint32_t cfgdata_rtn;
38
uint32_t cfgdata_out;
39
uint32_t cfgctrl;
40
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/misc/mps2-scc.c
43
+++ b/hw/misc/mps2-scc.c
44
@@ -XXX,XX +XXX,XX @@
45
46
REG32(CFG0, 0)
47
REG32(CFG1, 4)
48
+REG32(CFG2, 8)
49
REG32(CFG3, 0xc)
50
REG32(CFG4, 0x10)
51
+REG32(CFG5, 0x14)
52
+REG32(CFG6, 0x18)
53
REG32(CFGDATA_RTN, 0xa0)
54
REG32(CFGDATA_OUT, 0xa4)
55
REG32(CFGCTRL, 0xa8)
56
@@ -XXX,XX +XXX,XX @@ REG32(DLL, 0x100)
57
REG32(AID, 0xFF8)
58
REG32(ID, 0xFFC)
59
60
+static int scc_partno(MPS2SCC *s)
61
+{
62
+ /* Return the partno field of the SCC_ID (0x524, 0x511, etc) */
63
+ return extract32(s->id, 4, 8);
64
+}
65
+
66
/* Handle a write via the SYS_CFG channel to the specified function/device.
67
* Return false on error (reported to guest via SYS_CFGCTRL ERROR bit).
68
*/
69
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
70
case A_CFG1:
71
r = s->cfg1;
72
break;
73
+ case A_CFG2:
74
+ if (scc_partno(s) != 0x524) {
75
+ /* CFG2 reserved on other boards */
76
+ goto bad_offset;
77
+ }
78
+ r = s->cfg2;
79
+ break;
80
case A_CFG3:
81
+ if (scc_partno(s) == 0x524) {
82
+ /* CFG3 reserved on AN524 */
83
+ goto bad_offset;
84
+ }
85
/* These are user-settable DIP switches on the board. We don't
86
* model that, so just return zeroes.
87
*/
88
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
89
case A_CFG4:
90
r = s->cfg4;
91
break;
92
+ case A_CFG5:
93
+ if (scc_partno(s) != 0x524) {
94
+ /* CFG5 reserved on other boards */
95
+ goto bad_offset;
96
+ }
97
+ r = s->cfg5;
98
+ break;
99
+ case A_CFG6:
100
+ if (scc_partno(s) != 0x524) {
101
+ /* CFG6 reserved on other boards */
102
+ goto bad_offset;
103
+ }
104
+ r = s->cfg6;
105
+ break;
106
case A_CFGDATA_RTN:
107
r = s->cfgdata_rtn;
108
break;
109
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
110
r = s->id;
111
break;
112
default:
113
+ bad_offset:
114
qemu_log_mask(LOG_GUEST_ERROR,
115
"MPS2 SCC read: bad offset %x\n", (int) offset);
116
r = 0;
117
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
118
led_set_state(s->led[i], extract32(value, i, 1));
119
}
120
break;
121
+ case A_CFG2:
122
+ if (scc_partno(s) != 0x524) {
123
+ /* CFG2 reserved on other boards */
124
+ goto bad_offset;
125
+ }
126
+ /* AN524: QSPI Select signal */
127
+ s->cfg2 = value;
128
+ break;
129
+ case A_CFG5:
130
+ if (scc_partno(s) != 0x524) {
131
+ /* CFG5 reserved on other boards */
132
+ goto bad_offset;
133
+ }
134
+ /* AN524: ACLK frequency in Hz */
135
+ s->cfg5 = value;
136
+ break;
137
+ case A_CFG6:
138
+ if (scc_partno(s) != 0x524) {
139
+ /* CFG6 reserved on other boards */
140
+ goto bad_offset;
141
+ }
142
+ /* AN524: Clock divider for BRAM */
143
+ s->cfg6 = value;
144
+ break;
145
case A_CFGDATA_OUT:
146
s->cfgdata_out = value;
147
break;
148
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
149
s->dll = deposit32(s->dll, 24, 8, extract32(value, 24, 8));
150
break;
151
default:
152
+ bad_offset:
153
qemu_log_mask(LOG_GUEST_ERROR,
154
"MPS2 SCC write: bad offset 0x%x\n", (int) offset);
155
break;
156
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_reset(DeviceState *dev)
157
trace_mps2_scc_reset();
158
s->cfg0 = 0;
159
s->cfg1 = 0;
160
+ s->cfg2 = 0;
161
+ s->cfg5 = 0;
162
+ s->cfg6 = 0;
163
s->cfgdata_rtn = 0;
164
s->cfgdata_out = 0;
165
s->cfgctrl = 0x100000;
166
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_realize(DeviceState *dev, Error **errp)
167
168
static const VMStateDescription mps2_scc_vmstate = {
169
.name = "mps2-scc",
170
- .version_id = 2,
171
- .minimum_version_id = 2,
172
+ .version_id = 3,
173
+ .minimum_version_id = 3,
174
.fields = (VMStateField[]) {
175
VMSTATE_UINT32(cfg0, MPS2SCC),
176
VMSTATE_UINT32(cfg1, MPS2SCC),
177
+ VMSTATE_UINT32(cfg2, MPS2SCC),
178
+ /* cfg3, cfg4 are read-only so need not be migrated */
179
+ VMSTATE_UINT32(cfg5, MPS2SCC),
180
+ VMSTATE_UINT32(cfg6, MPS2SCC),
181
VMSTATE_UINT32(cfgdata_rtn, MPS2SCC),
182
VMSTATE_UINT32(cfgdata_out, MPS2SCC),
183
VMSTATE_UINT32(cfgctrl, MPS2SCC),
184
--
185
2.20.1
186
187
diff view generated by jsdifflib
Deleted patch
1
On the MPS2 boards, the first 32 interrupt lines are entirely
2
internal to the SSE; interrupt lines for devices outside the SSE
3
start at 32. In the application notes that document each FPGA image,
4
the interrupt wiring is documented from the point of view of the CPU,
5
so '0' is the first of the SSE's interrupts and the devices in the
6
FPGA image itself are '32' and up: so the UART 0 Receive interrupt is
7
32, the SPI #0 interrupt is 51, and so on.
8
1
9
Within our implementation, because the external interrupts must be
10
connected to the EXP_IRQ[0...n] lines of the SSE object, we made the
11
get_sse_irq_in() function take an irqno whose values start at 0 for
12
the first FPGA device interrupt. In this numbering scheme the UART 0
13
Receive interrupt is 0, the SPI #0 interrupt is 19, and so on.
14
15
The result of these two different numbering schemes has been that
16
half of the devices were wired up to the wrong IRQs: the UART IRQs
17
are wired up correctly, but the DMA and SPI devices were passing
18
start-at-32 values to get_sse_irq_in() and so being mis-connected.
19
20
Fix the bug by making get_sse_irq_in() take values specified with the
21
same scheme that the hardware manuals use, to avoid confusion.
22
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Message-id: 20210215115138.20465-12-peter.maydell@linaro.org
26
---
27
hw/arm/mps2-tz.c | 24 +++++++++++++++++-------
28
1 file changed, 17 insertions(+), 7 deletions(-)
29
30
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/arm/mps2-tz.c
33
+++ b/hw/arm/mps2-tz.c
34
@@ -XXX,XX +XXX,XX @@ static void make_ram_alias(MemoryRegion *mr, const char *name,
35
36
static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
37
{
38
- /* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
39
+ /*
40
+ * Return a qemu_irq which will signal IRQ n to all CPUs in the
41
+ * SSE. The irqno should be as the CPU sees it, so the first
42
+ * external-to-the-SSE interrupt is 32.
43
+ */
44
MachineClass *mc = MACHINE_GET_CLASS(mms);
45
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
46
47
- assert(irqno < mmc->numirq);
48
+ assert(irqno >= 32 && irqno < (mmc->numirq + 32));
49
+
50
+ /*
51
+ * Convert from "CPU irq number" (as listed in the FPGA image
52
+ * documentation) to the SSE external-interrupt number.
53
+ */
54
+ irqno -= 32;
55
56
if (mc->max_cpus > 1) {
57
return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
58
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
59
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
60
CMSDKAPBUART *uart = opaque;
61
int i = uart - &mms->uart[0];
62
- int rxirqno = i * 2;
63
- int txirqno = i * 2 + 1;
64
- int combirqno = i + 10;
65
+ int rxirqno = i * 2 + 32;
66
+ int txirqno = i * 2 + 33;
67
+ int combirqno = i + 42;
68
SysBusDevice *s;
69
DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
70
71
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
72
73
s = SYS_BUS_DEVICE(mms->lan9118);
74
sysbus_realize_and_unref(s, &error_fatal);
75
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 16));
76
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 48));
77
return sysbus_mmio_get_region(s, 0);
78
}
79
80
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
81
&error_fatal);
82
qdev_realize(DEVICE(&mms->uart_irq_orgate), NULL, &error_fatal);
83
qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
84
- get_sse_irq_in(mms, 15));
85
+ get_sse_irq_in(mms, 47));
86
87
/* Most of the devices in the FPGA are behind Peripheral Protection
88
* Controllers. The required order for initializing things is:
89
--
90
2.20.1
91
92
diff view generated by jsdifflib
Deleted patch
1
Move the specification of the IRQ information for the uart, ethernet,
2
dma and spi devices to the data structures. (The other devices
3
handled by the PPCPortInfo structures don't have any interrupt lines
4
we need to wire up.)
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215115138.20465-14-peter.maydell@linaro.org
9
---
10
hw/arm/mps2-tz.c | 52 +++++++++++++++++++++++-------------------------
11
1 file changed, 25 insertions(+), 27 deletions(-)
12
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/mps2-tz.c
16
+++ b/hw/arm/mps2-tz.c
17
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
18
const char *name, hwaddr size,
19
const int *irqs)
20
{
21
+ /* The irq[] array is tx, rx, combined, in that order */
22
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
23
CMSDKAPBUART *uart = opaque;
24
int i = uart - &mms->uart[0];
25
- int rxirqno = i * 2 + 32;
26
- int txirqno = i * 2 + 33;
27
- int combirqno = i + 42;
28
SysBusDevice *s;
29
DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
30
31
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
32
qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", mmc->sysclk_frq);
33
sysbus_realize(SYS_BUS_DEVICE(uart), &error_fatal);
34
s = SYS_BUS_DEVICE(uart);
35
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, txirqno));
36
- sysbus_connect_irq(s, 1, get_sse_irq_in(mms, rxirqno));
37
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
38
+ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqs[1]));
39
sysbus_connect_irq(s, 2, qdev_get_gpio_in(orgate_dev, i * 2));
40
sysbus_connect_irq(s, 3, qdev_get_gpio_in(orgate_dev, i * 2 + 1));
41
- sysbus_connect_irq(s, 4, get_sse_irq_in(mms, combirqno));
42
+ sysbus_connect_irq(s, 4, get_sse_irq_in(mms, irqs[2]));
43
return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0);
44
}
45
46
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
47
48
s = SYS_BUS_DEVICE(mms->lan9118);
49
sysbus_realize_and_unref(s, &error_fatal);
50
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 48));
51
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
52
return sysbus_mmio_get_region(s, 0);
53
}
54
55
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
56
const char *name, hwaddr size,
57
const int *irqs)
58
{
59
+ /* The irq[] array is DMACINTR, DMACINTERR, DMACINTTC, in that order */
60
PL080State *dma = opaque;
61
int i = dma - &mms->dma[0];
62
SysBusDevice *s;
63
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
64
65
s = SYS_BUS_DEVICE(dma);
66
/* Wire up DMACINTR, DMACINTERR, DMACINTTC */
67
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 58 + i * 3));
68
- sysbus_connect_irq(s, 1, get_sse_irq_in(mms, 56 + i * 3));
69
- sysbus_connect_irq(s, 2, get_sse_irq_in(mms, 57 + i * 3));
70
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
71
+ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqs[1]));
72
+ sysbus_connect_irq(s, 2, get_sse_irq_in(mms, irqs[2]));
73
74
g_free(mscname);
75
return sysbus_mmio_get_region(s, 0);
76
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
77
* lines are set via the "MISC" register in the MPS2 FPGAIO device.
78
*/
79
PL022State *spi = opaque;
80
- int i = spi - &mms->spi[0];
81
SysBusDevice *s;
82
83
object_initialize_child(OBJECT(mms), name, spi, TYPE_PL022);
84
sysbus_realize(SYS_BUS_DEVICE(spi), &error_fatal);
85
s = SYS_BUS_DEVICE(spi);
86
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 51 + i));
87
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
88
return sysbus_mmio_get_region(s, 0);
89
}
90
91
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
92
}, {
93
.name = "apb_ppcexp1",
94
.ports = {
95
- { "spi0", make_spi, &mms->spi[0], 0x40205000, 0x1000 },
96
- { "spi1", make_spi, &mms->spi[1], 0x40206000, 0x1000 },
97
- { "spi2", make_spi, &mms->spi[2], 0x40209000, 0x1000 },
98
- { "spi3", make_spi, &mms->spi[3], 0x4020a000, 0x1000 },
99
- { "spi4", make_spi, &mms->spi[4], 0x4020b000, 0x1000 },
100
- { "uart0", make_uart, &mms->uart[0], 0x40200000, 0x1000 },
101
- { "uart1", make_uart, &mms->uart[1], 0x40201000, 0x1000 },
102
- { "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000 },
103
- { "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000 },
104
- { "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000 },
105
+ { "spi0", make_spi, &mms->spi[0], 0x40205000, 0x1000, { 51 } },
106
+ { "spi1", make_spi, &mms->spi[1], 0x40206000, 0x1000, { 52 } },
107
+ { "spi2", make_spi, &mms->spi[2], 0x40209000, 0x1000, { 53 } },
108
+ { "spi3", make_spi, &mms->spi[3], 0x4020a000, 0x1000, { 54 } },
109
+ { "spi4", make_spi, &mms->spi[4], 0x4020b000, 0x1000, { 55 } },
110
+ { "uart0", make_uart, &mms->uart[0], 0x40200000, 0x1000, { 32, 33, 42 } },
111
+ { "uart1", make_uart, &mms->uart[1], 0x40201000, 0x1000, { 34, 35, 43 } },
112
+ { "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000, { 36, 37, 44 } },
113
+ { "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000, { 38, 39, 45 } },
114
+ { "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000, { 40, 41, 46 } },
115
{ "i2c0", make_i2c, &mms->i2c[0], 0x40207000, 0x1000 },
116
{ "i2c1", make_i2c, &mms->i2c[1], 0x40208000, 0x1000 },
117
{ "i2c2", make_i2c, &mms->i2c[2], 0x4020c000, 0x1000 },
118
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
119
{ "gpio1", make_unimp_dev, &mms->gpio[1], 0x40101000, 0x1000 },
120
{ "gpio2", make_unimp_dev, &mms->gpio[2], 0x40102000, 0x1000 },
121
{ "gpio3", make_unimp_dev, &mms->gpio[3], 0x40103000, 0x1000 },
122
- { "eth", make_eth_dev, NULL, 0x42000000, 0x100000 },
123
+ { "eth", make_eth_dev, NULL, 0x42000000, 0x100000, { 48 } },
124
},
125
}, {
126
.name = "ahb_ppcexp1",
127
.ports = {
128
- { "dma0", make_dma, &mms->dma[0], 0x40110000, 0x1000 },
129
- { "dma1", make_dma, &mms->dma[1], 0x40111000, 0x1000 },
130
- { "dma2", make_dma, &mms->dma[2], 0x40112000, 0x1000 },
131
- { "dma3", make_dma, &mms->dma[3], 0x40113000, 0x1000 },
132
+ { "dma0", make_dma, &mms->dma[0], 0x40110000, 0x1000, { 58, 56, 57 } },
133
+ { "dma1", make_dma, &mms->dma[1], 0x40111000, 0x1000, { 61, 59, 60 } },
134
+ { "dma2", make_dma, &mms->dma[2], 0x40112000, 0x1000, { 64, 62, 63 } },
135
+ { "dma3", make_dma, &mms->dma[3], 0x40113000, 0x1000, { 67, 65, 66 } },
136
},
137
},
138
};
139
--
140
2.20.1
141
142
diff view generated by jsdifflib