1
Nuvoton new board models, and some more minor stuff. I also put
1
The following changes since commit 3db29dcac23da85486704ef9e7a8e7217f7829cd:
2
in the deprecation patches for unicore32 and lm32.
3
2
4
thanks
3
Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging (2023-01-12 13:51:36 +0000)
5
-- PMM
6
7
The following changes since commit a68694cd1f3e5448cca814ff39b871f9ebd71ed5:
8
9
Merge remote-tracking branch 'remotes/philmd-gitlab/tags/edk2-next-20200914' into staging (2020-09-14 12:18:58 +0100)
10
4
11
are available in the Git repository at:
5
are available in the Git repository at:
12
6
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200914
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20230113
14
8
15
for you to fetch changes up to dd44ae00fc5342ed99acb68ec3508f76a71d523a:
9
for you to fetch changes up to 08899b5c68a55a3780d707e2464073c8f2670d31:
16
10
17
MAINTAINERS: Add maintainer entry for Xilinx ZynqMP CAN controller (2020-09-14 14:27:08 +0100)
11
target/arm: allow writes to SCR_EL3.HXEn bit when FEAT_HCX is enabled (2023-01-13 13:19:36 +0000)
18
12
19
----------------------------------------------------------------
13
----------------------------------------------------------------
20
target-arm queue:
14
target-arm queue:
21
* hw/misc/a9scu: Do not allow invalid CPU count
15
hw/arm/stm32f405: correctly describe the memory layout
22
* hw/misc/a9scu: Minor cleanups
16
hw/arm: Add Olimex H405 board
23
* hw/timer/armv7m_systick: assert that board code set system_clock_scale
17
cubieboard: Support booting from an SD card image with u-boot on it
24
* decodetree: Improve identifier matching
18
target/arm: Fix sve_probe_page
25
* target/arm: Clean up neon fp insn size field decode
19
target/arm: allow writes to SCR_EL3.HXEn bit when FEAT_HCX is enabled
26
* target/arm: Remove KVM support for 32-bit Arm hosts
20
various code cleanups
27
* hw/arm/mps2: New board models mps2-an386, mps2-an500
28
* Deprecate Unicore32 port
29
* Deprecate lm32 port
30
* target/arm: Count PMU events when MDCR.SPME is set
31
* hw/arm: versal-virt: Correct the tx/rx GEM clocks
32
* New Nuvoton iBMC board models npcm750-evb, quanta-gsj
33
* xlnx-zynqmp: implement ZynqMP CAN controllers
34
21
35
----------------------------------------------------------------
22
----------------------------------------------------------------
36
Aaron Lindsay (1):
23
Evgeny Iakovlev (1):
37
target/arm: Count PMU events when MDCR.SPME is set
24
target/arm: allow writes to SCR_EL3.HXEn bit when FEAT_HCX is enabled
38
25
39
Edgar E. Iglesias (1):
26
Felipe Balbi (2):
40
hw/arm: versal-virt: Correct the tx/rx GEM clocks
27
hw/arm/stm32f405: correctly describe the memory layout
28
hw/arm: Add Olimex H405
41
29
42
Havard Skinnemoen (14):
30
Philippe Mathieu-Daudé (27):
43
hw/misc: Add NPCM7xx System Global Control Registers device model
31
hw/arm/pxa2xx: Simplify pxa255_init()
44
hw/misc: Add NPCM7xx Clock Controller device model
32
hw/arm/pxa2xx: Simplify pxa270_init()
45
hw/timer: Add NPCM7xx Timer device model
33
hw/arm/collie: Use the IEC binary prefix definitions
46
hw/arm: Add NPCM730 and NPCM750 SoC models
34
hw/arm/collie: Simplify flash creation using for() loop
47
hw/arm: Add two NPCM7xx-based machines
35
hw/arm/gumstix: Improve documentation
48
roms: Add virtual Boot ROM for NPCM7xx SoCs
36
hw/arm/gumstix: Use the IEC binary prefix definitions
49
hw/arm: Load -bios image as a boot ROM for npcm7xx
37
hw/arm/mainstone: Use the IEC binary prefix definitions
50
hw/nvram: NPCM7xx OTP device model
38
hw/arm/musicpal: Use the IEC binary prefix definitions
51
hw/mem: Stubbed out NPCM7xx Memory Controller model
39
hw/arm/omap_sx1: Remove unused 'total_ram' definitions
52
hw/ssi: NPCM7xx Flash Interface Unit device model
40
hw/arm/omap_sx1: Use the IEC binary prefix definitions
53
hw/arm: Wire up BMC boot flash for npcm750-evb and quanta-gsj
41
hw/arm/z2: Use the IEC binary prefix definitions
54
hw/arm/npcm7xx: add board setup stub for CPU and UART clocks
42
hw/arm/vexpress: Remove dead code in vexpress_common_init()
55
docs/system: Add Nuvoton machine documentation
43
hw/arm: Remove unreachable code calling pflash_cfi01_register()
56
tests/acceptance: console boot tests for quanta-gsj
44
hw/arm/pxa: Avoid forward-declaring PXA2xxI2CState
57
45
hw/gpio/omap_gpio: Add local variable to avoid embedded cast
58
Peter Maydell (11):
46
hw/arm/omap: Drop useless casts from void * to pointer
59
hw/timer/armv7m_systick: assert that board code set system_clock_scale
47
hw/gpio/omap_gpio: Use CamelCase for TYPE_OMAP1_GPIO type name
60
target/arm: Convert Neon 3-same-fp size field to MO_* in decode
48
hw/gpio/omap_gpio: Use CamelCase for TYPE_OMAP2_GPIO type name
61
target/arm: Convert Neon VCVT fp size field to MO_* in decode
49
hw/intc/omap_intc: Use CamelCase for TYPE_OMAP_INTC type name
62
target/arm: Convert VCMLA, VCADD size field to MO_* in decode
50
hw/arm/stellaris: Drop useless casts from void * to pointer
63
target/arm: Remove KVM support for 32-bit Arm hosts
51
hw/arm/stellaris: Use CamelCase for STELLARIS_ADC type name
64
target/arm: Remove no-longer-reachable 32-bit KVM code
52
hw/arm/bcm2836: Remove definitions generated by OBJECT_DECLARE_TYPE()
65
hw/arm/mps2: New board model mps2-an386
53
hw/arm/npcm7xx: Declare QOM macros using OBJECT_DECLARE_SIMPLE_TYPE()
66
hw/arm/mps2: New board model mps2-an500
54
hw/misc/sbsa_ec: Rename TYPE_SBSA_EC -> TYPE_SBSA_SECURE_EC
67
docs/system/arm/mps2.rst: Make board list consistent
55
hw/misc/sbsa_ec: Declare QOM macros using OBJECT_DECLARE_SIMPLE_TYPE()
68
Deprecate Unicore32 port
56
hw/intc/xilinx_intc: Use 'XpsIntc' typedef instead of 'struct xlx_pic'
69
Deprecate lm32 port
57
hw/timer/xilinx_timer: Use XpsTimerState instead of 'struct timerblock'
70
71
Philippe Mathieu-Daudé (4):
72
hw/misc/a9scu: Do not allow invalid CPU count
73
hw/misc/a9scu: Simplify setting MemoryRegionOps::valid fields
74
hw/misc/a9scu: Simplify setting MemoryRegionOps::impl fields
75
hw/misc/a9scu: Report unimplemented accesses with qemu_log_mask(UNIMP)
76
58
77
Richard Henderson (1):
59
Richard Henderson (1):
78
decodetree: Improve identifier matching
60
target/arm: Fix sve_probe_page
79
61
80
Vikram Garhwal (4):
62
Strahinja Jankovic (7):
81
hw/net/can: Introduce Xilinx ZynqMP CAN controller
63
hw/misc: Allwinner-A10 Clock Controller Module Emulation
82
xlnx-zynqmp: Connect Xilinx ZynqMP CAN controllers
64
hw/misc: Allwinner A10 DRAM Controller Emulation
83
tests/qtest: Introduce tests for Xilinx ZynqMP CAN controller
65
{hw/i2c,docs/system/arm}: Allwinner TWI/I2C Emulation
84
MAINTAINERS: Add maintainer entry for Xilinx ZynqMP CAN controller
66
hw/misc: AXP209 PMU Emulation
67
hw/arm: Add AXP209 to Cubieboard
68
hw/arm: Allwinner A10 enable SPL load from MMC
69
tests/avocado: Add SD boot test to Cubieboard
85
70
86
docs/system/arm/mps2.rst | 20 +-
71
docs/system/arm/cubieboard.rst | 1 +
87
docs/system/arm/nuvoton.rst | 92 +++
72
docs/system/arm/orangepi.rst | 1 +
88
docs/system/deprecated.rst | 32 +-
73
docs/system/arm/stm32.rst | 1 +
89
docs/system/target-arm.rst | 1 +
74
configs/devices/arm-softmmu/default.mak | 1 +
90
configure | 2 +-
75
include/hw/adc/npcm7xx_adc.h | 7 +-
91
default-configs/arm-softmmu.mak | 1 +
76
include/hw/arm/allwinner-a10.h | 27 ++
92
include/hw/arm/npcm7xx.h | 112 +++
77
include/hw/arm/allwinner-h3.h | 3 +
93
include/hw/arm/xlnx-zynqmp.h | 8 +
78
include/hw/arm/npcm7xx.h | 18 +-
94
include/hw/mem/npcm7xx_mc.h | 36 +
79
include/hw/arm/omap.h | 24 +-
95
include/hw/misc/npcm7xx_clk.h | 48 ++
80
include/hw/arm/pxa.h | 11 +-
96
include/hw/misc/npcm7xx_gcr.h | 43 ++
81
include/hw/arm/stm32f405_soc.h | 5 +-
97
include/hw/net/xlnx-zynqmp-can.h | 78 +++
82
include/hw/i2c/allwinner-i2c.h | 55 ++++
98
include/hw/nvram/npcm7xx_otp.h | 79 +++
83
include/hw/i2c/npcm7xx_smbus.h | 7 +-
99
include/hw/ssi/npcm7xx_fiu.h | 73 ++
84
include/hw/misc/allwinner-a10-ccm.h | 67 +++++
100
include/hw/timer/npcm7xx_timer.h | 78 +++
85
include/hw/misc/allwinner-a10-dramc.h | 68 +++++
101
target/arm/kvm-consts.h | 7 -
86
include/hw/misc/npcm7xx_clk.h | 2 +-
102
target/arm/kvm_arm.h | 6 -
87
include/hw/misc/npcm7xx_gcr.h | 6 +-
103
target/arm/neon-dp.decode | 18 +-
88
include/hw/misc/npcm7xx_mft.h | 7 +-
104
target/arm/neon-shared.decode | 18 +-
89
include/hw/misc/npcm7xx_pwm.h | 3 +-
105
tests/decode/succ_ident1.decode | 7 +
90
include/hw/misc/npcm7xx_rng.h | 6 +-
106
hw/arm/mps2.c | 97 ++-
91
include/hw/net/npcm7xx_emc.h | 5 +-
107
hw/arm/npcm7xx.c | 532 +++++++++++++++
92
include/hw/sd/npcm7xx_sdhci.h | 4 +-
108
hw/arm/npcm7xx_boards.c | 197 ++++++
93
hw/arm/allwinner-a10.c | 40 +++
109
hw/arm/xlnx-versal-virt.c | 2 +-
94
hw/arm/allwinner-h3.c | 11 +-
110
hw/arm/xlnx-zcu102.c | 20 +
95
hw/arm/bcm2836.c | 9 +-
111
hw/arm/xlnx-zynqmp.c | 34 +
96
hw/arm/collie.c | 25 +-
112
hw/mem/npcm7xx_mc.c | 84 +++
97
hw/arm/cubieboard.c | 11 +
113
hw/misc/a9scu.c | 59 +-
98
hw/arm/gumstix.c | 45 ++--
114
hw/misc/npcm7xx_clk.c | 266 ++++++++
99
hw/arm/mainstone.c | 37 ++-
115
hw/misc/npcm7xx_gcr.c | 269 ++++++++
100
hw/arm/musicpal.c | 9 +-
116
hw/net/can/xlnx-zynqmp-can.c | 1165 ++++++++++++++++++++++++++++++++
101
hw/arm/olimex-stm32-h405.c | 69 +++++
117
hw/nvram/npcm7xx_otp.c | 440 ++++++++++++
102
hw/arm/omap1.c | 115 ++++----
118
hw/ssi/npcm7xx_fiu.c | 572 ++++++++++++++++
103
hw/arm/omap2.c | 40 ++-
119
hw/timer/armv7m_systick.c | 8 +
104
hw/arm/omap_sx1.c | 53 ++--
120
hw/timer/npcm7xx_timer.c | 543 +++++++++++++++
105
hw/arm/palm.c | 2 +-
121
target/arm/cpu.c | 101 ++-
106
hw/arm/pxa2xx.c | 8 +-
122
target/arm/helper.c | 2 +-
107
hw/arm/spitz.c | 6 +-
123
target/arm/kvm.c | 7 -
108
hw/arm/stellaris.c | 73 +++--
124
target/arm/kvm32.c | 595 ----------------
109
hw/arm/stm32f405_soc.c | 8 +
125
tests/qtest/xlnx-can-test.c | 359 ++++++++++
110
hw/arm/tosa.c | 2 +-
126
.gitmodules | 3 +
111
hw/arm/versatilepb.c | 6 +-
127
MAINTAINERS | 18 +
112
hw/arm/vexpress.c | 10 +-
128
hw/arm/Kconfig | 9 +
113
hw/arm/z2.c | 16 +-
129
hw/arm/meson.build | 1 +
114
hw/char/omap_uart.c | 7 +-
130
hw/mem/meson.build | 1 +
115
hw/display/omap_dss.c | 15 +-
131
hw/misc/meson.build | 4 +
116
hw/display/omap_lcdc.c | 9 +-
132
hw/misc/trace-events | 8 +
117
hw/dma/omap_dma.c | 15 +-
133
hw/net/can/meson.build | 1 +
118
hw/gpio/omap_gpio.c | 48 ++--
134
hw/nvram/meson.build | 1 +
119
hw/i2c/allwinner-i2c.c | 459 ++++++++++++++++++++++++++++++++
135
hw/ssi/meson.build | 1 +
120
hw/intc/omap_intc.c | 38 +--
136
hw/ssi/trace-events | 11 +
121
hw/intc/xilinx_intc.c | 28 +-
137
hw/timer/meson.build | 1 +
122
hw/misc/allwinner-a10-ccm.c | 224 ++++++++++++++++
138
hw/timer/trace-events | 5 +
123
hw/misc/allwinner-a10-dramc.c | 179 +++++++++++++
139
pc-bios/README | 6 +
124
hw/misc/axp209.c | 238 +++++++++++++++++
140
pc-bios/meson.build | 1 +
125
hw/misc/omap_gpmc.c | 12 +-
141
pc-bios/npcm7xx_bootrom.bin | Bin 0 -> 768 bytes
126
hw/misc/omap_l4.c | 7 +-
142
roms/Makefile | 7 +
127
hw/misc/omap_sdrc.c | 7 +-
143
roms/vbootrom | 1 +
128
hw/misc/omap_tap.c | 5 +-
144
scripts/decodetree.py | 46 +-
129
hw/misc/sbsa_ec.c | 12 +-
145
target/arm/meson.build | 5 +-
130
hw/sd/omap_mmc.c | 9 +-
146
target/arm/translate-neon.c.inc | 42 +-
131
hw/ssi/omap_spi.c | 7 +-
147
tests/acceptance/boot_linux_console.py | 83 +++
132
hw/timer/omap_gptimer.c | 22 +-
148
tests/qtest/meson.build | 1 +
133
hw/timer/omap_synctimer.c | 4 +-
149
63 files changed, 5584 insertions(+), 783 deletions(-)
134
hw/timer/xilinx_timer.c | 27 +-
150
create mode 100644 docs/system/arm/nuvoton.rst
135
target/arm/helper.c | 3 +
151
create mode 100644 include/hw/arm/npcm7xx.h
136
target/arm/sve_helper.c | 14 +-
152
create mode 100644 include/hw/mem/npcm7xx_mc.h
137
MAINTAINERS | 8 +
153
create mode 100644 include/hw/misc/npcm7xx_clk.h
138
hw/arm/Kconfig | 9 +
154
create mode 100644 include/hw/misc/npcm7xx_gcr.h
139
hw/arm/meson.build | 1 +
155
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
140
hw/i2c/Kconfig | 4 +
156
create mode 100644 include/hw/nvram/npcm7xx_otp.h
141
hw/i2c/meson.build | 1 +
157
create mode 100644 include/hw/ssi/npcm7xx_fiu.h
142
hw/i2c/trace-events | 5 +
158
create mode 100644 include/hw/timer/npcm7xx_timer.h
143
hw/misc/Kconfig | 10 +
159
create mode 100644 tests/decode/succ_ident1.decode
144
hw/misc/meson.build | 3 +
160
create mode 100644 hw/arm/npcm7xx.c
145
hw/misc/trace-events | 5 +
161
create mode 100644 hw/arm/npcm7xx_boards.c
146
tests/avocado/boot_linux_console.py | 47 ++++
162
create mode 100644 hw/mem/npcm7xx_mc.c
147
76 files changed, 1951 insertions(+), 455 deletions(-)
163
create mode 100644 hw/misc/npcm7xx_clk.c
148
create mode 100644 include/hw/i2c/allwinner-i2c.h
164
create mode 100644 hw/misc/npcm7xx_gcr.c
149
create mode 100644 include/hw/misc/allwinner-a10-ccm.h
165
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
150
create mode 100644 include/hw/misc/allwinner-a10-dramc.h
166
create mode 100644 hw/nvram/npcm7xx_otp.c
151
create mode 100644 hw/arm/olimex-stm32-h405.c
167
create mode 100644 hw/ssi/npcm7xx_fiu.c
152
create mode 100644 hw/i2c/allwinner-i2c.c
168
create mode 100644 hw/timer/npcm7xx_timer.c
153
create mode 100644 hw/misc/allwinner-a10-ccm.c
169
delete mode 100644 target/arm/kvm32.c
154
create mode 100644 hw/misc/allwinner-a10-dramc.c
170
create mode 100644 tests/qtest/xlnx-can-test.c
155
create mode 100644 hw/misc/axp209.c
171
create mode 100644 pc-bios/npcm7xx_bootrom.bin
172
create mode 160000 roms/vbootrom
173
156
diff view generated by jsdifflib
New patch
1
From: Felipe Balbi <balbi@kernel.org>
1
2
3
STM32F405 has 128K of SRAM and another 64K of CCM (Core-coupled
4
Memory) at a different base address. Correctly describe the memory
5
layout to give existing FW images a chance to run unmodified.
6
7
Reviewed-by: Alistair Francis <alistair@alistair23.me>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Signed-off-by: Felipe Balbi <balbi@kernel.org>
10
Message-id: 20221230145733.200496-2-balbi@kernel.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
include/hw/arm/stm32f405_soc.h | 5 ++++-
14
hw/arm/stm32f405_soc.c | 8 ++++++++
15
2 files changed, 12 insertions(+), 1 deletion(-)
16
17
diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/stm32f405_soc.h
20
+++ b/include/hw/arm/stm32f405_soc.h
21
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(STM32F405State, STM32F405_SOC)
22
#define FLASH_BASE_ADDRESS 0x08000000
23
#define FLASH_SIZE (1024 * 1024)
24
#define SRAM_BASE_ADDRESS 0x20000000
25
-#define SRAM_SIZE (192 * 1024)
26
+#define SRAM_SIZE (128 * 1024)
27
+#define CCM_BASE_ADDRESS 0x10000000
28
+#define CCM_SIZE (64 * 1024)
29
30
struct STM32F405State {
31
/*< private >*/
32
@@ -XXX,XX +XXX,XX @@ struct STM32F405State {
33
STM32F2XXADCState adc[STM_NUM_ADCS];
34
STM32F2XXSPIState spi[STM_NUM_SPIS];
35
36
+ MemoryRegion ccm;
37
MemoryRegion sram;
38
MemoryRegion flash;
39
MemoryRegion flash_alias;
40
diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/arm/stm32f405_soc.c
43
+++ b/hw/arm/stm32f405_soc.c
44
@@ -XXX,XX +XXX,XX @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
45
}
46
memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, &s->sram);
47
48
+ memory_region_init_ram(&s->ccm, NULL, "STM32F405.ccm", CCM_SIZE,
49
+ &err);
50
+ if (err != NULL) {
51
+ error_propagate(errp, err);
52
+ return;
53
+ }
54
+ memory_region_add_subregion(system_memory, CCM_BASE_ADDRESS, &s->ccm);
55
+
56
armv7m = DEVICE(&s->armv7m);
57
qdev_prop_set_uint32(armv7m, "num-irq", 96);
58
qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
59
--
60
2.34.1
61
62
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Felipe Balbi <balbi@kernel.org>
2
2
3
The QTests perform five tests on the Xilinx ZynqMP CAN controller:
3
Olimex makes a series of low-cost STM32 boards. This commit introduces
4
Tests the CAN controller in loopback, sleep and snoop mode.
4
the minimum setup to support SMT32-H405. See [1] for details
5
Tests filtering of incoming CAN messages.
6
5
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
6
[1] https://www.olimex.com/Products/ARM/ST/STM32-H405/
8
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
7
9
Message-id: 1597278668-339715-4-git-send-email-fnu.vikram@xilinx.com
8
Signed-off-by: Felipe Balbi <balbi@kernel.org>
10
[PMM: updated to meson build system]
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Message-id: 20221230145733.200496-3-balbi@kernel.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
---
13
tests/qtest/xlnx-can-test.c | 359 ++++++++++++++++++++++++++++++++++++
14
docs/system/arm/stm32.rst | 1 +
14
tests/qtest/meson.build | 1 +
15
configs/devices/arm-softmmu/default.mak | 1 +
15
2 files changed, 360 insertions(+)
16
hw/arm/olimex-stm32-h405.c | 69 +++++++++++++++++++++++++
16
create mode 100644 tests/qtest/xlnx-can-test.c
17
MAINTAINERS | 6 +++
18
hw/arm/Kconfig | 4 ++
19
hw/arm/meson.build | 1 +
20
6 files changed, 82 insertions(+)
21
create mode 100644 hw/arm/olimex-stm32-h405.c
17
22
18
diff --git a/tests/qtest/xlnx-can-test.c b/tests/qtest/xlnx-can-test.c
23
diff --git a/docs/system/arm/stm32.rst b/docs/system/arm/stm32.rst
24
index XXXXXXX..XXXXXXX 100644
25
--- a/docs/system/arm/stm32.rst
26
+++ b/docs/system/arm/stm32.rst
27
@@ -XXX,XX +XXX,XX @@ The STM32F4 series is based on ARM Cortex-M4F core. This series is pin-to-pin
28
compatible with STM32F2 series. The following machines are based on this chip :
29
30
- ``netduinoplus2`` Netduino Plus 2 board with STM32F405RGT6 microcontroller
31
+- ``olimex-stm32-h405`` Olimex STM32 H405 board with STM32F405RGT6 microcontroller
32
33
There are many other STM32 series that are currently not supported by QEMU.
34
35
diff --git a/configs/devices/arm-softmmu/default.mak b/configs/devices/arm-softmmu/default.mak
36
index XXXXXXX..XXXXXXX 100644
37
--- a/configs/devices/arm-softmmu/default.mak
38
+++ b/configs/devices/arm-softmmu/default.mak
39
@@ -XXX,XX +XXX,XX @@ CONFIG_COLLIE=y
40
CONFIG_ASPEED_SOC=y
41
CONFIG_NETDUINO2=y
42
CONFIG_NETDUINOPLUS2=y
43
+CONFIG_OLIMEX_STM32_H405=y
44
CONFIG_MPS2=y
45
CONFIG_RASPI=y
46
CONFIG_DIGIC=y
47
diff --git a/hw/arm/olimex-stm32-h405.c b/hw/arm/olimex-stm32-h405.c
19
new file mode 100644
48
new file mode 100644
20
index XXXXXXX..XXXXXXX
49
index XXXXXXX..XXXXXXX
21
--- /dev/null
50
--- /dev/null
22
+++ b/tests/qtest/xlnx-can-test.c
51
+++ b/hw/arm/olimex-stm32-h405.c
23
@@ -XXX,XX +XXX,XX @@
52
@@ -XXX,XX +XXX,XX @@
24
+/*
53
+/*
25
+ * QTests for the Xilinx ZynqMP CAN controller.
54
+ * ST STM32VLDISCOVERY machine
55
+ * Olimex STM32-H405 machine
26
+ *
56
+ *
27
+ * Copyright (c) 2020 Xilinx Inc.
57
+ * Copyright (c) 2022 Felipe Balbi <balbi@kernel.org>
28
+ *
29
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
30
+ *
58
+ *
31
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
59
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
32
+ * of this software and associated documentation files (the "Software"), to deal
60
+ * of this software and associated documentation files (the "Software"), to deal
33
+ * in the Software without restriction, including without limitation the rights
61
+ * in the Software without restriction, including without limitation the rights
34
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
62
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
...
...
46
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
74
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
47
+ * THE SOFTWARE.
75
+ * THE SOFTWARE.
48
+ */
76
+ */
49
+
77
+
50
+#include "qemu/osdep.h"
78
+#include "qemu/osdep.h"
51
+#include "libqos/libqtest.h"
79
+#include "qapi/error.h"
80
+#include "hw/boards.h"
81
+#include "hw/qdev-properties.h"
82
+#include "hw/qdev-clock.h"
83
+#include "qemu/error-report.h"
84
+#include "hw/arm/stm32f405_soc.h"
85
+#include "hw/arm/boot.h"
52
+
86
+
53
+/* Base address. */
87
+/* olimex-stm32-h405 implementation is derived from netduinoplus2 */
54
+#define CAN0_BASE_ADDR 0xFF060000
55
+#define CAN1_BASE_ADDR 0xFF070000
56
+
88
+
57
+/* Register addresses. */
89
+/* Main SYSCLK frequency in Hz (168MHz) */
58
+#define R_SRR_OFFSET 0x00
90
+#define SYSCLK_FRQ 168000000ULL
59
+#define R_MSR_OFFSET 0x04
60
+#define R_SR_OFFSET 0x18
61
+#define R_ISR_OFFSET 0x1C
62
+#define R_ICR_OFFSET 0x24
63
+#define R_TXID_OFFSET 0x30
64
+#define R_TXDLC_OFFSET 0x34
65
+#define R_TXDATA1_OFFSET 0x38
66
+#define R_TXDATA2_OFFSET 0x3C
67
+#define R_RXID_OFFSET 0x50
68
+#define R_RXDLC_OFFSET 0x54
69
+#define R_RXDATA1_OFFSET 0x58
70
+#define R_RXDATA2_OFFSET 0x5C
71
+#define R_AFR 0x60
72
+#define R_AFMR1 0x64
73
+#define R_AFIR1 0x68
74
+#define R_AFMR2 0x6C
75
+#define R_AFIR2 0x70
76
+#define R_AFMR3 0x74
77
+#define R_AFIR3 0x78
78
+#define R_AFMR4 0x7C
79
+#define R_AFIR4 0x80
80
+
91
+
81
+/* CAN modes. */
92
+static void olimex_stm32_h405_init(MachineState *machine)
82
+#define CONFIG_MODE 0x00
93
+{
83
+#define NORMAL_MODE 0x00
94
+ DeviceState *dev;
84
+#define LOOPBACK_MODE 0x02
95
+ Clock *sysclk;
85
+#define SNOOP_MODE 0x04
86
+#define SLEEP_MODE 0x01
87
+#define ENABLE_CAN (1 << 1)
88
+#define STATUS_NORMAL_MODE (1 << 3)
89
+#define STATUS_LOOPBACK_MODE (1 << 1)
90
+#define STATUS_SNOOP_MODE (1 << 12)
91
+#define STATUS_SLEEP_MODE (1 << 2)
92
+#define ISR_TXOK (1 << 1)
93
+#define ISR_RXOK (1 << 4)
94
+
96
+
95
+static void match_rx_tx_data(uint32_t *buf_tx, uint32_t *buf_rx,
97
+ /* This clock doesn't need migration because it is fixed-frequency */
96
+ uint8_t can_timestamp)
98
+ sysclk = clock_new(OBJECT(machine), "SYSCLK");
97
+{
99
+ clock_set_hz(sysclk, SYSCLK_FRQ);
98
+ uint16_t size = 0;
99
+ uint8_t len = 4;
100
+
100
+
101
+ while (size < len) {
101
+ dev = qdev_new(TYPE_STM32F405_SOC);
102
+ if (R_RXID_OFFSET + 4 * size == R_RXDLC_OFFSET) {
102
+ qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4"));
103
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size] + can_timestamp);
103
+ qdev_connect_clock_in(dev, "sysclk", sysclk);
104
+ } else {
104
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
105
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size]);
106
+ }
107
+
105
+
108
+ size++;
106
+ armv7m_load_kernel(ARM_CPU(first_cpu),
109
+ }
107
+ machine->kernel_filename,
108
+ 0, FLASH_SIZE);
110
+}
109
+}
111
+
110
+
112
+static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_rx)
111
+static void olimex_stm32_h405_machine_init(MachineClass *mc)
113
+{
112
+{
114
+ uint32_t int_status;
113
+ mc->desc = "Olimex STM32-H405 (Cortex-M4)";
114
+ mc->init = olimex_stm32_h405_init;
115
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m4");
115
+
116
+
116
+ /* Read the interrupt on CAN rx. */
117
+ /* SRAM pre-allocated as part of the SoC instantiation */
117
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_RXOK;
118
+ mc->default_ram_size = 0;
118
+
119
+ g_assert_cmpint(int_status, ==, ISR_RXOK);
120
+
121
+ /* Read the RX register data for CAN. */
122
+ buf_rx[0] = qtest_readl(qts, can_base_addr + R_RXID_OFFSET);
123
+ buf_rx[1] = qtest_readl(qts, can_base_addr + R_RXDLC_OFFSET);
124
+ buf_rx[2] = qtest_readl(qts, can_base_addr + R_RXDATA1_OFFSET);
125
+ buf_rx[3] = qtest_readl(qts, can_base_addr + R_RXDATA2_OFFSET);
126
+
127
+ /* Clear the RX interrupt. */
128
+ qtest_writel(qts, CAN1_BASE_ADDR + R_ICR_OFFSET, ISR_RXOK);
129
+}
119
+}
130
+
120
+
131
+static void send_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_tx)
121
+DEFINE_MACHINE("olimex-stm32-h405", olimex_stm32_h405_machine_init)
132
+{
122
diff --git a/MAINTAINERS b/MAINTAINERS
133
+ uint32_t int_status;
123
index XXXXXXX..XXXXXXX 100644
124
--- a/MAINTAINERS
125
+++ b/MAINTAINERS
126
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
127
S: Maintained
128
F: hw/arm/netduinoplus2.c
129
130
+Olimex STM32 H405
131
+M: Felipe Balbi <balbi@kernel.org>
132
+L: qemu-arm@nongnu.org
133
+S: Maintained
134
+F: hw/arm/olimex-stm32-h405.c
134
+
135
+
135
+ /* Write the TX register data for CAN. */
136
SmartFusion2
136
+ qtest_writel(qts, can_base_addr + R_TXID_OFFSET, buf_tx[0]);
137
M: Subbaraya Sundeep <sundeep.lkml@gmail.com>
137
+ qtest_writel(qts, can_base_addr + R_TXDLC_OFFSET, buf_tx[1]);
138
M: Peter Maydell <peter.maydell@linaro.org>
138
+ qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET, buf_tx[2]);
139
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
139
+ qtest_writel(qts, can_base_addr + R_TXDATA2_OFFSET, buf_tx[3]);
140
index XXXXXXX..XXXXXXX 100644
141
--- a/hw/arm/Kconfig
142
+++ b/hw/arm/Kconfig
143
@@ -XXX,XX +XXX,XX @@ config NETDUINOPLUS2
144
bool
145
select STM32F405_SOC
146
147
+config OLIMEX_STM32_H405
148
+ bool
149
+ select STM32F405_SOC
140
+
150
+
141
+ /* Read the interrupt on CAN for tx. */
151
config NSERIES
142
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_TXOK;
152
bool
143
+
153
select OMAP
144
+ g_assert_cmpint(int_status, ==, ISR_TXOK);
154
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
145
+
146
+ /* Clear the interrupt for tx. */
147
+ qtest_writel(qts, CAN0_BASE_ADDR + R_ICR_OFFSET, ISR_TXOK);
148
+}
149
+
150
+/*
151
+ * This test will be transferring data from CAN0 and CAN1 through canbus. CAN0
152
+ * initiate the data transfer to can-bus, CAN1 receives the data. Test compares
153
+ * the data sent from CAN0 with received on CAN1.
154
+ */
155
+static void test_can_bus(void)
156
+{
157
+ uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
158
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
159
+ uint32_t status = 0;
160
+ uint8_t can_timestamp = 1;
161
+
162
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
163
+ " -object can-bus,id=canbus0"
164
+ " -machine xlnx-zcu102.canbus0=canbus0"
165
+ " -machine xlnx-zcu102.canbus1=canbus0"
166
+ );
167
+
168
+ /* Configure the CAN0 and CAN1. */
169
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
170
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
171
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
172
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
173
+
174
+ /* Check here if CAN0 and CAN1 are in normal mode. */
175
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
176
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
177
+
178
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
179
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
180
+
181
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
182
+
183
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
184
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
185
+
186
+ qtest_quit(qts);
187
+}
188
+
189
+/*
190
+ * This test is performing loopback mode on CAN0 and CAN1. Data sent from TX of
191
+ * each CAN0 and CAN1 are compared with RX register data for respective CAN.
192
+ */
193
+static void test_can_loopback(void)
194
+{
195
+ uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
196
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
197
+ uint32_t status = 0;
198
+
199
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
200
+ " -object can-bus,id=canbus0"
201
+ " -machine xlnx-zcu102.canbus0=canbus0"
202
+ " -machine xlnx-zcu102.canbus1=canbus0"
203
+ );
204
+
205
+ /* Configure the CAN0 in loopback mode. */
206
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
207
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
208
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
209
+
210
+ /* Check here if CAN0 is set in loopback mode. */
211
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
212
+
213
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
214
+
215
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
216
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
217
+ match_rx_tx_data(buf_tx, buf_rx, 0);
218
+
219
+ /* Configure the CAN1 in loopback mode. */
220
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
221
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
222
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
223
+
224
+ /* Check here if CAN1 is set in loopback mode. */
225
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
226
+
227
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
228
+
229
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
230
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
231
+ match_rx_tx_data(buf_tx, buf_rx, 0);
232
+
233
+ qtest_quit(qts);
234
+}
235
+
236
+/*
237
+ * Enable filters for CAN1. This will filter incoming messages with ID. In this
238
+ * test message will pass through filter 2.
239
+ */
240
+static void test_can_filter(void)
241
+{
242
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
243
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
244
+ uint32_t status = 0;
245
+ uint8_t can_timestamp = 1;
246
+
247
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
248
+ " -object can-bus,id=canbus0"
249
+ " -machine xlnx-zcu102.canbus0=canbus0"
250
+ " -machine xlnx-zcu102.canbus1=canbus0"
251
+ );
252
+
253
+ /* Configure the CAN0 and CAN1. */
254
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
255
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
256
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
257
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
258
+
259
+ /* Check here if CAN0 and CAN1 are in normal mode. */
260
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
261
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
262
+
263
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
264
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
265
+
266
+ /* Set filter for CAN1 for incoming messages. */
267
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0x0);
268
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR1, 0xF7);
269
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR1, 0x121F);
270
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR2, 0x5431);
271
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR2, 0x14);
272
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR3, 0x1234);
273
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR3, 0x5431);
274
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR4, 0xFFF);
275
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR4, 0x1234);
276
+
277
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0xF);
278
+
279
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
280
+
281
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
282
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
283
+
284
+ qtest_quit(qts);
285
+}
286
+
287
+/* Testing sleep mode on CAN0 while CAN1 is in normal mode. */
288
+static void test_can_sleepmode(void)
289
+{
290
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
291
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
292
+ uint32_t status = 0;
293
+ uint8_t can_timestamp = 1;
294
+
295
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
296
+ " -object can-bus,id=canbus0"
297
+ " -machine xlnx-zcu102.canbus0=canbus0"
298
+ " -machine xlnx-zcu102.canbus1=canbus0"
299
+ );
300
+
301
+ /* Configure the CAN0. */
302
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
303
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SLEEP_MODE);
304
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
305
+
306
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
307
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
308
+
309
+ /* Check here if CAN0 is in SLEEP mode and CAN1 in normal mode. */
310
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
311
+ g_assert_cmpint(status, ==, STATUS_SLEEP_MODE);
312
+
313
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
314
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
315
+
316
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
317
+
318
+ /*
319
+ * Once CAN1 sends data on can-bus. CAN0 should exit sleep mode.
320
+ * Check the CAN0 status now. It should exit the sleep mode and receive the
321
+ * incoming data.
322
+ */
323
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
324
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
325
+
326
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
327
+
328
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
329
+
330
+ qtest_quit(qts);
331
+}
332
+
333
+/* Testing Snoop mode on CAN0 while CAN1 is in normal mode. */
334
+static void test_can_snoopmode(void)
335
+{
336
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
337
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
338
+ uint32_t status = 0;
339
+ uint8_t can_timestamp = 1;
340
+
341
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
342
+ " -object can-bus,id=canbus0"
343
+ " -machine xlnx-zcu102.canbus0=canbus0"
344
+ " -machine xlnx-zcu102.canbus1=canbus0"
345
+ );
346
+
347
+ /* Configure the CAN0. */
348
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
349
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SNOOP_MODE);
350
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
351
+
352
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
353
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
354
+
355
+ /* Check here if CAN0 is in SNOOP mode and CAN1 in normal mode. */
356
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
357
+ g_assert_cmpint(status, ==, STATUS_SNOOP_MODE);
358
+
359
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
360
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
361
+
362
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
363
+
364
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
365
+
366
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
367
+
368
+ qtest_quit(qts);
369
+}
370
+
371
+int main(int argc, char **argv)
372
+{
373
+ g_test_init(&argc, &argv, NULL);
374
+
375
+ qtest_add_func("/net/can/can_bus", test_can_bus);
376
+ qtest_add_func("/net/can/can_loopback", test_can_loopback);
377
+ qtest_add_func("/net/can/can_filter", test_can_filter);
378
+ qtest_add_func("/net/can/can_test_snoopmode", test_can_snoopmode);
379
+ qtest_add_func("/net/can/can_test_sleepmode", test_can_sleepmode);
380
+
381
+ return g_test_run();
382
+}
383
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
384
index XXXXXXX..XXXXXXX 100644
155
index XXXXXXX..XXXXXXX 100644
385
--- a/tests/qtest/meson.build
156
--- a/hw/arm/meson.build
386
+++ b/tests/qtest/meson.build
157
+++ b/hw/arm/meson.build
387
@@ -XXX,XX +XXX,XX @@ qtests_aarch64 = \
158
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'CONFIG_MICROBIT', if_true: files('microbit.c'))
388
(config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ? ['tpm-tis-device-swtpm-test'] : []) + \
159
arm_ss.add(when: 'CONFIG_MUSICPAL', if_true: files('musicpal.c'))
389
['numa-test',
160
arm_ss.add(when: 'CONFIG_NETDUINO2', if_true: files('netduino2.c'))
390
'boot-serial-test',
161
arm_ss.add(when: 'CONFIG_NETDUINOPLUS2', if_true: files('netduinoplus2.c'))
391
+ 'xlnx-can-test',
162
+arm_ss.add(when: 'CONFIG_OLIMEX_STM32_H405', if_true: files('olimex-stm32-h405.c'))
392
'migration-test']
163
arm_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx.c', 'npcm7xx_boards.c'))
393
164
arm_ss.add(when: 'CONFIG_NSERIES', if_true: files('nseries.c'))
394
qtests_s390x = \
165
arm_ss.add(when: 'CONFIG_SX1', if_true: files('omap_sx1.c'))
395
--
166
--
396
2.20.1
167
2.34.1
397
168
398
169
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
2
2
3
Enough functionality to boot the Linux kernel has been implemented. This
3
During SPL boot several Clock Controller Module (CCM) registers are
4
includes:
4
read, most important are PLL and Tuning, as well as divisor registers.
5
5
6
- Correct power-on reset values so the various clock rates can be
6
This patch adds these registers and initializes reset values from user's
7
accurately calculated.
7
guide.
8
- Clock enables stick around when written.
9
8
10
In addition, a best effort attempt to implement SECCNT and CNTR25M was
9
Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
11
made even though I don't think the kernel needs them.
12
10
13
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
11
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
14
Reviewed-by: Joel Stanley <joel@jms.id.au>
12
Message-id: 20221226220303.14420-2-strahinja.p.jankovic@gmail.com
15
Reviewed-by: Cédric Le Goater <clg@kaod.org>
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Tested-by: Alexander Bulekov <alxndr@bu.edu>
19
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
20
Message-id: 20200911052101.2602693-3-hskinnemoen@google.com
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
14
---
23
include/hw/misc/npcm7xx_clk.h | 48 ++++++
15
include/hw/arm/allwinner-a10.h | 2 +
24
hw/misc/npcm7xx_clk.c | 266 ++++++++++++++++++++++++++++++++++
16
include/hw/misc/allwinner-a10-ccm.h | 67 +++++++++
25
hw/misc/meson.build | 1 +
17
hw/arm/allwinner-a10.c | 7 +
26
hw/misc/trace-events | 4 +
18
hw/misc/allwinner-a10-ccm.c | 224 ++++++++++++++++++++++++++++
27
4 files changed, 319 insertions(+)
19
hw/arm/Kconfig | 1 +
28
create mode 100644 include/hw/misc/npcm7xx_clk.h
20
hw/misc/Kconfig | 3 +
29
create mode 100644 hw/misc/npcm7xx_clk.c
21
hw/misc/meson.build | 1 +
22
7 files changed, 305 insertions(+)
23
create mode 100644 include/hw/misc/allwinner-a10-ccm.h
24
create mode 100644 hw/misc/allwinner-a10-ccm.c
30
25
31
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
26
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/include/hw/arm/allwinner-a10.h
29
+++ b/include/hw/arm/allwinner-a10.h
30
@@ -XXX,XX +XXX,XX @@
31
#include "hw/usb/hcd-ohci.h"
32
#include "hw/usb/hcd-ehci.h"
33
#include "hw/rtc/allwinner-rtc.h"
34
+#include "hw/misc/allwinner-a10-ccm.h"
35
36
#include "target/arm/cpu.h"
37
#include "qom/object.h"
38
@@ -XXX,XX +XXX,XX @@ struct AwA10State {
39
/*< public >*/
40
41
ARMCPU cpu;
42
+ AwA10ClockCtlState ccm;
43
AwA10PITState timer;
44
AwA10PICState intc;
45
AwEmacState emac;
46
diff --git a/include/hw/misc/allwinner-a10-ccm.h b/include/hw/misc/allwinner-a10-ccm.h
32
new file mode 100644
47
new file mode 100644
33
index XXXXXXX..XXXXXXX
48
index XXXXXXX..XXXXXXX
34
--- /dev/null
49
--- /dev/null
35
+++ b/include/hw/misc/npcm7xx_clk.h
50
+++ b/include/hw/misc/allwinner-a10-ccm.h
36
@@ -XXX,XX +XXX,XX @@
51
@@ -XXX,XX +XXX,XX @@
37
+/*
52
+/*
38
+ * Nuvoton NPCM7xx Clock Control Registers.
53
+ * Allwinner A10 Clock Control Module emulation
39
+ *
54
+ *
40
+ * Copyright 2020 Google LLC
55
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
41
+ *
56
+ *
42
+ * This program is free software; you can redistribute it and/or modify it
57
+ * This file is derived from Allwinner H3 CCU,
43
+ * under the terms of the GNU General Public License as published by the
58
+ * by Niek Linnenbank.
44
+ * Free Software Foundation; either version 2 of the License, or
59
+ *
60
+ * This program is free software: you can redistribute it and/or modify
61
+ * it under the terms of the GNU General Public License as published by
62
+ * the Free Software Foundation, either version 2 of the License, or
45
+ * (at your option) any later version.
63
+ * (at your option) any later version.
46
+ *
64
+ *
47
+ * This program is distributed in the hope that it will be useful, but WITHOUT
65
+ * This program is distributed in the hope that it will be useful,
48
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
66
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
49
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
67
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
50
+ * for more details.
68
+ * GNU General Public License for more details.
69
+ *
70
+ * You should have received a copy of the GNU General Public License
71
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
51
+ */
72
+ */
52
+#ifndef NPCM7XX_CLK_H
73
+
53
+#define NPCM7XX_CLK_H
74
+#ifndef HW_MISC_ALLWINNER_A10_CCM_H
54
+
75
+#define HW_MISC_ALLWINNER_A10_CCM_H
55
+#include "exec/memory.h"
76
+
77
+#include "qom/object.h"
56
+#include "hw/sysbus.h"
78
+#include "hw/sysbus.h"
57
+
79
+
58
+/*
80
+/**
59
+ * The reference clock frequency for the timer modules, and the SECCNT and
81
+ * @name Constants
60
+ * CNTR25M registers in this module, is always 25 MHz.
82
+ * @{
61
+ */
83
+ */
62
+#define NPCM7XX_TIMER_REF_HZ (25000000)
84
+
63
+
85
+/** Size of register I/O address space used by CCM device */
64
+/*
86
+#define AW_A10_CCM_IOSIZE (0x400)
65
+ * Number of registers in our device state structure. Don't change this without
87
+
66
+ * incrementing the version_id in the vmstate.
88
+/** Total number of known registers */
89
+#define AW_A10_CCM_REGS_NUM (AW_A10_CCM_IOSIZE / sizeof(uint32_t))
90
+
91
+/** @} */
92
+
93
+/**
94
+ * @name Object model
95
+ * @{
67
+ */
96
+ */
68
+#define NPCM7XX_CLK_NR_REGS (0x70 / sizeof(uint32_t))
97
+
69
+
98
+#define TYPE_AW_A10_CCM "allwinner-a10-ccm"
70
+typedef struct NPCM7xxCLKState {
99
+OBJECT_DECLARE_SIMPLE_TYPE(AwA10ClockCtlState, AW_A10_CCM)
71
+ SysBusDevice parent;
100
+
72
+
101
+/** @} */
102
+
103
+/**
104
+ * Allwinner A10 CCM object instance state.
105
+ */
106
+struct AwA10ClockCtlState {
107
+ /*< private >*/
108
+ SysBusDevice parent_obj;
109
+ /*< public >*/
110
+
111
+ /** Maps I/O registers in physical memory */
73
+ MemoryRegion iomem;
112
+ MemoryRegion iomem;
74
+
113
+
75
+ uint32_t regs[NPCM7XX_CLK_NR_REGS];
114
+ /** Array of hardware registers */
76
+
115
+ uint32_t regs[AW_A10_CCM_REGS_NUM];
77
+ /* Time reference for SECCNT and CNTR25M, initialized by power on reset */
116
+};
78
+ int64_t ref_ns;
117
+
79
+} NPCM7xxCLKState;
118
+#endif /* HW_MISC_ALLWINNER_H3_CCU_H */
80
+
119
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
81
+#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
120
index XXXXXXX..XXXXXXX 100644
82
+#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK)
121
--- a/hw/arm/allwinner-a10.c
83
+
122
+++ b/hw/arm/allwinner-a10.c
84
+#endif /* NPCM7XX_CLK_H */
123
@@ -XXX,XX +XXX,XX @@
85
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
124
#include "hw/usb/hcd-ohci.h"
125
126
#define AW_A10_MMC0_BASE 0x01c0f000
127
+#define AW_A10_CCM_BASE 0x01c20000
128
#define AW_A10_PIC_REG_BASE 0x01c20400
129
#define AW_A10_PIT_REG_BASE 0x01c20c00
130
#define AW_A10_UART0_REG_BASE 0x01c28000
131
@@ -XXX,XX +XXX,XX @@ static void aw_a10_init(Object *obj)
132
133
object_initialize_child(obj, "timer", &s->timer, TYPE_AW_A10_PIT);
134
135
+ object_initialize_child(obj, "ccm", &s->ccm, TYPE_AW_A10_CCM);
136
+
137
object_initialize_child(obj, "emac", &s->emac, TYPE_AW_EMAC);
138
139
object_initialize_child(obj, "sata", &s->sata, TYPE_ALLWINNER_AHCI);
140
@@ -XXX,XX +XXX,XX @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
141
memory_region_add_subregion(get_system_memory(), 0x00000000, &s->sram_a);
142
create_unimplemented_device("a10-sram-ctrl", 0x01c00000, 4 * KiB);
143
144
+ /* Clock Control Module */
145
+ sysbus_realize(SYS_BUS_DEVICE(&s->ccm), &error_fatal);
146
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, AW_A10_CCM_BASE);
147
+
148
/* FIXME use qdev NIC properties instead of nd_table[] */
149
if (nd_table[0].used) {
150
qemu_check_nic_model(&nd_table[0], TYPE_AW_EMAC);
151
diff --git a/hw/misc/allwinner-a10-ccm.c b/hw/misc/allwinner-a10-ccm.c
86
new file mode 100644
152
new file mode 100644
87
index XXXXXXX..XXXXXXX
153
index XXXXXXX..XXXXXXX
88
--- /dev/null
154
--- /dev/null
89
+++ b/hw/misc/npcm7xx_clk.c
155
+++ b/hw/misc/allwinner-a10-ccm.c
90
@@ -XXX,XX +XXX,XX @@
156
@@ -XXX,XX +XXX,XX @@
91
+/*
157
+/*
92
+ * Nuvoton NPCM7xx Clock Control Registers.
158
+ * Allwinner A10 Clock Control Module emulation
93
+ *
159
+ *
94
+ * Copyright 2020 Google LLC
160
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
95
+ *
161
+ *
96
+ * This program is free software; you can redistribute it and/or modify it
162
+ * This file is derived from Allwinner H3 CCU,
97
+ * under the terms of the GNU General Public License as published by the
163
+ * by Niek Linnenbank.
98
+ * Free Software Foundation; either version 2 of the License, or
164
+ *
165
+ * This program is free software: you can redistribute it and/or modify
166
+ * it under the terms of the GNU General Public License as published by
167
+ * the Free Software Foundation, either version 2 of the License, or
99
+ * (at your option) any later version.
168
+ * (at your option) any later version.
100
+ *
169
+ *
101
+ * This program is distributed in the hope that it will be useful, but WITHOUT
170
+ * This program is distributed in the hope that it will be useful,
102
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
171
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
103
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
172
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
104
+ * for more details.
173
+ * GNU General Public License for more details.
174
+ *
175
+ * You should have received a copy of the GNU General Public License
176
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
105
+ */
177
+ */
106
+
178
+
107
+#include "qemu/osdep.h"
179
+#include "qemu/osdep.h"
108
+
180
+#include "qemu/units.h"
109
+#include "hw/misc/npcm7xx_clk.h"
181
+#include "hw/sysbus.h"
110
+#include "migration/vmstate.h"
182
+#include "migration/vmstate.h"
111
+#include "qemu/error-report.h"
112
+#include "qemu/log.h"
183
+#include "qemu/log.h"
113
+#include "qemu/module.h"
184
+#include "qemu/module.h"
114
+#include "qemu/timer.h"
185
+#include "hw/misc/allwinner-a10-ccm.h"
115
+#include "qemu/units.h"
186
+
116
+#include "trace.h"
187
+/* CCM register offsets */
117
+
188
+enum {
118
+#define PLLCON_LOKI BIT(31)
189
+ REG_PLL1_CFG = 0x0000, /* PLL1 Control */
119
+#define PLLCON_LOKS BIT(30)
190
+ REG_PLL1_TUN = 0x0004, /* PLL1 Tuning */
120
+#define PLLCON_PWDEN BIT(12)
191
+ REG_PLL2_CFG = 0x0008, /* PLL2 Control */
121
+
192
+ REG_PLL2_TUN = 0x000C, /* PLL2 Tuning */
122
+enum NPCM7xxCLKRegisters {
193
+ REG_PLL3_CFG = 0x0010, /* PLL3 Control */
123
+ NPCM7XX_CLK_CLKEN1,
194
+ REG_PLL4_CFG = 0x0018, /* PLL4 Control */
124
+ NPCM7XX_CLK_CLKSEL,
195
+ REG_PLL5_CFG = 0x0020, /* PLL5 Control */
125
+ NPCM7XX_CLK_CLKDIV1,
196
+ REG_PLL5_TUN = 0x0024, /* PLL5 Tuning */
126
+ NPCM7XX_CLK_PLLCON0,
197
+ REG_PLL6_CFG = 0x0028, /* PLL6 Control */
127
+ NPCM7XX_CLK_PLLCON1,
198
+ REG_PLL6_TUN = 0x002C, /* PLL6 Tuning */
128
+ NPCM7XX_CLK_SWRSTR,
199
+ REG_PLL7_CFG = 0x0030, /* PLL7 Control */
129
+ NPCM7XX_CLK_IPSRST1 = 0x20 / sizeof(uint32_t),
200
+ REG_PLL1_TUN2 = 0x0038, /* PLL1 Tuning2 */
130
+ NPCM7XX_CLK_IPSRST2,
201
+ REG_PLL5_TUN2 = 0x003C, /* PLL5 Tuning2 */
131
+ NPCM7XX_CLK_CLKEN2,
202
+ REG_PLL8_CFG = 0x0040, /* PLL8 Control */
132
+ NPCM7XX_CLK_CLKDIV2,
203
+ REG_OSC24M_CFG = 0x0050, /* OSC24M Control */
133
+ NPCM7XX_CLK_CLKEN3,
204
+ REG_CPU_AHB_APB0_CFG = 0x0054, /* CPU, AHB and APB0 Divide Ratio */
134
+ NPCM7XX_CLK_IPSRST3,
205
+};
135
+ NPCM7XX_CLK_WD0RCR,
206
+
136
+ NPCM7XX_CLK_WD1RCR,
207
+#define REG_INDEX(offset) (offset / sizeof(uint32_t))
137
+ NPCM7XX_CLK_WD2RCR,
208
+
138
+ NPCM7XX_CLK_SWRSTC1,
209
+/* CCM register reset values */
139
+ NPCM7XX_CLK_SWRSTC2,
210
+enum {
140
+ NPCM7XX_CLK_SWRSTC3,
211
+ REG_PLL1_CFG_RST = 0x21005000,
141
+ NPCM7XX_CLK_SWRSTC4,
212
+ REG_PLL1_TUN_RST = 0x0A101000,
142
+ NPCM7XX_CLK_PLLCON2,
213
+ REG_PLL2_CFG_RST = 0x08100010,
143
+ NPCM7XX_CLK_CLKDIV3,
214
+ REG_PLL2_TUN_RST = 0x00000000,
144
+ NPCM7XX_CLK_CORSTC,
215
+ REG_PLL3_CFG_RST = 0x0010D063,
145
+ NPCM7XX_CLK_PLLCONG,
216
+ REG_PLL4_CFG_RST = 0x21009911,
146
+ NPCM7XX_CLK_AHBCKFI,
217
+ REG_PLL5_CFG_RST = 0x11049280,
147
+ NPCM7XX_CLK_SECCNT,
218
+ REG_PLL5_TUN_RST = 0x14888000,
148
+ NPCM7XX_CLK_CNTR25M,
219
+ REG_PLL6_CFG_RST = 0x21009911,
149
+ NPCM7XX_CLK_REGS_END,
220
+ REG_PLL6_TUN_RST = 0x00000000,
150
+};
221
+ REG_PLL7_CFG_RST = 0x0010D063,
151
+
222
+ REG_PLL1_TUN2_RST = 0x00000000,
152
+/*
223
+ REG_PLL5_TUN2_RST = 0x00000000,
153
+ * These reset values were taken from version 0.91 of the NPCM750R data sheet.
224
+ REG_PLL8_CFG_RST = 0x21009911,
154
+ *
225
+ REG_OSC24M_CFG_RST = 0x00138013,
155
+ * All are loaded on power-up reset. CLKENx and SWRSTR should also be loaded on
226
+ REG_CPU_AHB_APB0_CFG_RST = 0x00010010,
156
+ * core domain reset, but this reset type is not yet supported by QEMU.
227
+};
157
+ */
228
+
158
+static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = {
229
+static uint64_t allwinner_a10_ccm_read(void *opaque, hwaddr offset,
159
+ [NPCM7XX_CLK_CLKEN1] = 0xffffffff,
230
+ unsigned size)
160
+ [NPCM7XX_CLK_CLKSEL] = 0x004aaaaa,
231
+{
161
+ [NPCM7XX_CLK_CLKDIV1] = 0x5413f855,
232
+ const AwA10ClockCtlState *s = AW_A10_CCM(opaque);
162
+ [NPCM7XX_CLK_PLLCON0] = 0x00222101 | PLLCON_LOKI,
233
+ const uint32_t idx = REG_INDEX(offset);
163
+ [NPCM7XX_CLK_PLLCON1] = 0x00202101 | PLLCON_LOKI,
234
+
164
+ [NPCM7XX_CLK_IPSRST1] = 0x00001000,
235
+ switch (offset) {
165
+ [NPCM7XX_CLK_IPSRST2] = 0x80000000,
236
+ case REG_PLL1_CFG:
166
+ [NPCM7XX_CLK_CLKEN2] = 0xffffffff,
237
+ case REG_PLL1_TUN:
167
+ [NPCM7XX_CLK_CLKDIV2] = 0xaa4f8f9f,
238
+ case REG_PLL2_CFG:
168
+ [NPCM7XX_CLK_CLKEN3] = 0xffffffff,
239
+ case REG_PLL2_TUN:
169
+ [NPCM7XX_CLK_IPSRST3] = 0x03000000,
240
+ case REG_PLL3_CFG:
170
+ [NPCM7XX_CLK_WD0RCR] = 0xffffffff,
241
+ case REG_PLL4_CFG:
171
+ [NPCM7XX_CLK_WD1RCR] = 0xffffffff,
242
+ case REG_PLL5_CFG:
172
+ [NPCM7XX_CLK_WD2RCR] = 0xffffffff,
243
+ case REG_PLL5_TUN:
173
+ [NPCM7XX_CLK_SWRSTC1] = 0x00000003,
244
+ case REG_PLL6_CFG:
174
+ [NPCM7XX_CLK_PLLCON2] = 0x00c02105 | PLLCON_LOKI,
245
+ case REG_PLL6_TUN:
175
+ [NPCM7XX_CLK_CORSTC] = 0x04000003,
246
+ case REG_PLL7_CFG:
176
+ [NPCM7XX_CLK_PLLCONG] = 0x01228606 | PLLCON_LOKI,
247
+ case REG_PLL1_TUN2:
177
+ [NPCM7XX_CLK_AHBCKFI] = 0x000000c8,
248
+ case REG_PLL5_TUN2:
178
+};
249
+ case REG_PLL8_CFG:
179
+
250
+ case REG_OSC24M_CFG:
180
+static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
251
+ case REG_CPU_AHB_APB0_CFG:
181
+{
252
+ break;
182
+ uint32_t reg = offset / sizeof(uint32_t);
253
+ case 0x158 ... AW_A10_CCM_IOSIZE:
183
+ NPCM7xxCLKState *s = opaque;
254
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
184
+ int64_t now_ns;
255
+ __func__, (uint32_t)offset);
185
+ uint32_t value = 0;
256
+ return 0;
186
+
257
+ default:
187
+ if (reg >= NPCM7XX_CLK_NR_REGS) {
258
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented read offset 0x%04x\n",
188
+ qemu_log_mask(LOG_GUEST_ERROR,
259
+ __func__, (uint32_t)offset);
189
+ "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
190
+ __func__, offset);
191
+ return 0;
260
+ return 0;
192
+ }
261
+ }
193
+
262
+
194
+ switch (reg) {
263
+ return s->regs[idx];
195
+ case NPCM7XX_CLK_SWRSTR:
264
+}
196
+ qemu_log_mask(LOG_GUEST_ERROR,
265
+
197
+ "%s: register @ 0x%04" HWADDR_PRIx " is write-only\n",
266
+static void allwinner_a10_ccm_write(void *opaque, hwaddr offset,
198
+ __func__, offset);
267
+ uint64_t val, unsigned size)
268
+{
269
+ AwA10ClockCtlState *s = AW_A10_CCM(opaque);
270
+ const uint32_t idx = REG_INDEX(offset);
271
+
272
+ switch (offset) {
273
+ case REG_PLL1_CFG:
274
+ case REG_PLL1_TUN:
275
+ case REG_PLL2_CFG:
276
+ case REG_PLL2_TUN:
277
+ case REG_PLL3_CFG:
278
+ case REG_PLL4_CFG:
279
+ case REG_PLL5_CFG:
280
+ case REG_PLL5_TUN:
281
+ case REG_PLL6_CFG:
282
+ case REG_PLL6_TUN:
283
+ case REG_PLL7_CFG:
284
+ case REG_PLL1_TUN2:
285
+ case REG_PLL5_TUN2:
286
+ case REG_PLL8_CFG:
287
+ case REG_OSC24M_CFG:
288
+ case REG_CPU_AHB_APB0_CFG:
199
+ break;
289
+ break;
200
+
290
+ case 0x158 ... AW_A10_CCM_IOSIZE:
201
+ case NPCM7XX_CLK_SECCNT:
291
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
202
+ now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
292
+ __func__, (uint32_t)offset);
203
+ value = (now_ns - s->ref_ns) / NANOSECONDS_PER_SECOND;
204
+ break;
293
+ break;
205
+
294
+ default:
206
+ case NPCM7XX_CLK_CNTR25M:
295
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented write offset 0x%04x\n",
207
+ now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
296
+ __func__, (uint32_t)offset);
208
+ /*
209
+ * This register counts 25 MHz cycles, updating every 640 ns. It rolls
210
+ * over to zero every second.
211
+ *
212
+ * The 4 LSBs are always zero: (1e9 / 640) << 4 = 25000000.
213
+ */
214
+ value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_TIMER_REF_HZ;
215
+ break;
297
+ break;
216
+
217
+ default:
218
+ value = s->regs[reg];
219
+ break;
220
+ };
221
+
222
+ trace_npcm7xx_clk_read(offset, value);
223
+
224
+ return value;
225
+}
226
+
227
+static void npcm7xx_clk_write(void *opaque, hwaddr offset,
228
+ uint64_t v, unsigned size)
229
+{
230
+ uint32_t reg = offset / sizeof(uint32_t);
231
+ NPCM7xxCLKState *s = opaque;
232
+ uint32_t value = v;
233
+
234
+ trace_npcm7xx_clk_write(offset, value);
235
+
236
+ if (reg >= NPCM7XX_CLK_NR_REGS) {
237
+ qemu_log_mask(LOG_GUEST_ERROR,
238
+ "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
239
+ __func__, offset);
240
+ return;
241
+ }
298
+ }
242
+
299
+
243
+ switch (reg) {
300
+ s->regs[idx] = (uint32_t) val;
244
+ case NPCM7XX_CLK_SWRSTR:
301
+}
245
+ qemu_log_mask(LOG_UNIMP, "%s: SW reset not implemented: 0x%02x\n",
302
+
246
+ __func__, value);
303
+static const MemoryRegionOps allwinner_a10_ccm_ops = {
247
+ value = 0;
304
+ .read = allwinner_a10_ccm_read,
248
+ break;
305
+ .write = allwinner_a10_ccm_write,
249
+
306
+ .endianness = DEVICE_NATIVE_ENDIAN,
250
+ case NPCM7XX_CLK_PLLCON0:
307
+ .valid = {
251
+ case NPCM7XX_CLK_PLLCON1:
308
+ .min_access_size = 4,
252
+ case NPCM7XX_CLK_PLLCON2:
309
+ .max_access_size = 4,
253
+ case NPCM7XX_CLK_PLLCONG:
310
+ },
254
+ if (value & PLLCON_PWDEN) {
311
+ .impl.min_access_size = 4,
255
+ /* Power down -- clear lock and indicate loss of lock */
312
+};
256
+ value &= ~PLLCON_LOKI;
313
+
257
+ value |= PLLCON_LOKS;
314
+static void allwinner_a10_ccm_reset_enter(Object *obj, ResetType type)
258
+ } else {
315
+{
259
+ /* Normal mode -- assume always locked */
316
+ AwA10ClockCtlState *s = AW_A10_CCM(obj);
260
+ value |= PLLCON_LOKI;
317
+
261
+ /* Keep LOKS unchanged unless cleared by writing 1 */
318
+ /* Set default values for registers */
262
+ if (value & PLLCON_LOKS) {
319
+ s->regs[REG_INDEX(REG_PLL1_CFG)] = REG_PLL1_CFG_RST;
263
+ value &= ~PLLCON_LOKS;
320
+ s->regs[REG_INDEX(REG_PLL1_TUN)] = REG_PLL1_TUN_RST;
264
+ } else {
321
+ s->regs[REG_INDEX(REG_PLL2_CFG)] = REG_PLL2_CFG_RST;
265
+ value |= (value & PLLCON_LOKS);
322
+ s->regs[REG_INDEX(REG_PLL2_TUN)] = REG_PLL2_TUN_RST;
266
+ }
323
+ s->regs[REG_INDEX(REG_PLL3_CFG)] = REG_PLL3_CFG_RST;
267
+ }
324
+ s->regs[REG_INDEX(REG_PLL4_CFG)] = REG_PLL4_CFG_RST;
268
+ break;
325
+ s->regs[REG_INDEX(REG_PLL5_CFG)] = REG_PLL5_CFG_RST;
269
+
326
+ s->regs[REG_INDEX(REG_PLL5_TUN)] = REG_PLL5_TUN_RST;
270
+ case NPCM7XX_CLK_CNTR25M:
327
+ s->regs[REG_INDEX(REG_PLL6_CFG)] = REG_PLL6_CFG_RST;
271
+ qemu_log_mask(LOG_GUEST_ERROR,
328
+ s->regs[REG_INDEX(REG_PLL6_TUN)] = REG_PLL6_TUN_RST;
272
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
329
+ s->regs[REG_INDEX(REG_PLL7_CFG)] = REG_PLL7_CFG_RST;
273
+ __func__, offset);
330
+ s->regs[REG_INDEX(REG_PLL1_TUN2)] = REG_PLL1_TUN2_RST;
274
+ return;
331
+ s->regs[REG_INDEX(REG_PLL5_TUN2)] = REG_PLL5_TUN2_RST;
332
+ s->regs[REG_INDEX(REG_PLL8_CFG)] = REG_PLL8_CFG_RST;
333
+ s->regs[REG_INDEX(REG_OSC24M_CFG)] = REG_OSC24M_CFG_RST;
334
+ s->regs[REG_INDEX(REG_CPU_AHB_APB0_CFG)] = REG_CPU_AHB_APB0_CFG_RST;
335
+}
336
+
337
+static void allwinner_a10_ccm_init(Object *obj)
338
+{
339
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
340
+ AwA10ClockCtlState *s = AW_A10_CCM(obj);
341
+
342
+ /* Memory mapping */
343
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_a10_ccm_ops, s,
344
+ TYPE_AW_A10_CCM, AW_A10_CCM_IOSIZE);
345
+ sysbus_init_mmio(sbd, &s->iomem);
346
+}
347
+
348
+static const VMStateDescription allwinner_a10_ccm_vmstate = {
349
+ .name = "allwinner-a10-ccm",
350
+ .version_id = 1,
351
+ .minimum_version_id = 1,
352
+ .fields = (VMStateField[]) {
353
+ VMSTATE_UINT32_ARRAY(regs, AwA10ClockCtlState, AW_A10_CCM_REGS_NUM),
354
+ VMSTATE_END_OF_LIST()
275
+ }
355
+ }
276
+
356
+};
277
+ s->regs[reg] = value;
357
+
278
+}
358
+static void allwinner_a10_ccm_class_init(ObjectClass *klass, void *data)
279
+
359
+{
280
+static const struct MemoryRegionOps npcm7xx_clk_ops = {
360
+ DeviceClass *dc = DEVICE_CLASS(klass);
281
+ .read = npcm7xx_clk_read,
282
+ .write = npcm7xx_clk_write,
283
+ .endianness = DEVICE_LITTLE_ENDIAN,
284
+ .valid = {
285
+ .min_access_size = 4,
286
+ .max_access_size = 4,
287
+ .unaligned = false,
288
+ },
289
+};
290
+
291
+static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
292
+{
293
+ NPCM7xxCLKState *s = NPCM7XX_CLK(obj);
294
+
295
+ QEMU_BUILD_BUG_ON(sizeof(s->regs) != sizeof(cold_reset_values));
296
+
297
+ switch (type) {
298
+ case RESET_TYPE_COLD:
299
+ memcpy(s->regs, cold_reset_values, sizeof(cold_reset_values));
300
+ s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
301
+ return;
302
+ }
303
+
304
+ /*
305
+ * A small number of registers need to be reset on a core domain reset,
306
+ * but no such reset type exists yet.
307
+ */
308
+ qemu_log_mask(LOG_UNIMP, "%s: reset type %d not implemented.",
309
+ __func__, type);
310
+}
311
+
312
+static void npcm7xx_clk_init(Object *obj)
313
+{
314
+ NPCM7xxCLKState *s = NPCM7XX_CLK(obj);
315
+
316
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
317
+ TYPE_NPCM7XX_CLK, 4 * KiB);
318
+ sysbus_init_mmio(&s->parent, &s->iomem);
319
+}
320
+
321
+static const VMStateDescription vmstate_npcm7xx_clk = {
322
+ .name = "npcm7xx-clk",
323
+ .version_id = 0,
324
+ .minimum_version_id = 0,
325
+ .fields = (VMStateField[]) {
326
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxCLKState, NPCM7XX_CLK_NR_REGS),
327
+ VMSTATE_INT64(ref_ns, NPCM7xxCLKState),
328
+ VMSTATE_END_OF_LIST(),
329
+ },
330
+};
331
+
332
+static void npcm7xx_clk_class_init(ObjectClass *klass, void *data)
333
+{
334
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
361
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
335
+ DeviceClass *dc = DEVICE_CLASS(klass);
362
+
336
+
363
+ rc->phases.enter = allwinner_a10_ccm_reset_enter;
337
+ QEMU_BUILD_BUG_ON(NPCM7XX_CLK_REGS_END > NPCM7XX_CLK_NR_REGS);
364
+ dc->vmsd = &allwinner_a10_ccm_vmstate;
338
+
365
+}
339
+ dc->desc = "NPCM7xx Clock Control Registers";
366
+
340
+ dc->vmsd = &vmstate_npcm7xx_clk;
367
+static const TypeInfo allwinner_a10_ccm_info = {
341
+ rc->phases.enter = npcm7xx_clk_enter_reset;
368
+ .name = TYPE_AW_A10_CCM,
342
+}
369
+ .parent = TYPE_SYS_BUS_DEVICE,
343
+
370
+ .instance_init = allwinner_a10_ccm_init,
344
+static const TypeInfo npcm7xx_clk_info = {
371
+ .instance_size = sizeof(AwA10ClockCtlState),
345
+ .name = TYPE_NPCM7XX_CLK,
372
+ .class_init = allwinner_a10_ccm_class_init,
346
+ .parent = TYPE_SYS_BUS_DEVICE,
373
+};
347
+ .instance_size = sizeof(NPCM7xxCLKState),
374
+
348
+ .instance_init = npcm7xx_clk_init,
375
+static void allwinner_a10_ccm_register(void)
349
+ .class_init = npcm7xx_clk_class_init,
376
+{
350
+};
377
+ type_register_static(&allwinner_a10_ccm_info);
351
+
378
+}
352
+static void npcm7xx_clk_register_type(void)
379
+
353
+{
380
+type_init(allwinner_a10_ccm_register)
354
+ type_register_static(&npcm7xx_clk_info);
381
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
355
+}
382
index XXXXXXX..XXXXXXX 100644
356
+type_init(npcm7xx_clk_register_type);
383
--- a/hw/arm/Kconfig
384
+++ b/hw/arm/Kconfig
385
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10
386
select AHCI
387
select ALLWINNER_A10_PIT
388
select ALLWINNER_A10_PIC
389
+ select ALLWINNER_A10_CCM
390
select ALLWINNER_EMAC
391
select SERIAL
392
select UNIMP
393
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
394
index XXXXXXX..XXXXXXX 100644
395
--- a/hw/misc/Kconfig
396
+++ b/hw/misc/Kconfig
397
@@ -XXX,XX +XXX,XX @@ config VIRT_CTRL
398
config LASI
399
bool
400
401
+config ALLWINNER_A10_CCM
402
+ bool
403
+
404
source macio/Kconfig
357
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
405
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
358
index XXXXXXX..XXXXXXX 100644
406
index XXXXXXX..XXXXXXX 100644
359
--- a/hw/misc/meson.build
407
--- a/hw/misc/meson.build
360
+++ b/hw/misc/meson.build
408
+++ b/hw/misc/meson.build
361
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_IMX', if_true: files(
409
@@ -XXX,XX +XXX,XX @@ subdir('macio')
362
softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-hpdmc.c', 'milkymist-pfpu.c'))
410
363
softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
411
softmmu_ss.add(when: 'CONFIG_IVSHMEM_DEVICE', if_true: files('ivshmem.c'))
364
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
412
365
+ 'npcm7xx_clk.c',
413
+softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_CCM', if_true: files('allwinner-a10-ccm.c'))
366
'npcm7xx_gcr.c',
414
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-ccu.c'))
367
))
415
specific_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-cpucfg.c'))
368
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files(
416
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-dramc.c'))
369
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
370
index XXXXXXX..XXXXXXX 100644
371
--- a/hw/misc/trace-events
372
+++ b/hw/misc/trace-events
373
@@ -XXX,XX +XXX,XX @@ mos6522_set_sr_int(void) "set sr_int"
374
mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64
375
mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x"
376
377
+# npcm7xx_clk.c
378
+npcm7xx_clk_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
379
+npcm7xx_clk_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
380
+
381
# npcm7xx_gcr.c
382
npcm7xx_gcr_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
383
npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
384
--
417
--
385
2.20.1
418
2.34.1
386
387
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
2
2
3
Implement a device model for the System Global Control Registers in the
3
During SPL boot several DRAM Controller registers are used. Most
4
NPCM730 and NPCM750 BMC SoCs.
4
important registers are those related to DRAM initialization and
5
5
calibration, where SPL initiates process and waits until certain bit is
6
This is primarily used to enable SMP boot (the boot ROM spins reading
6
set/cleared.
7
the SCRPAD register) and DDR memory initialization; other registers are
7
8
best effort for now.
8
This patch adds these registers, initializes reset values from user's
9
9
guide and updates state of registers as SPL expects it.
10
The reset values of the MDLR and PWRON registers are determined by the
10
11
SoC variant (730 vs 750) and board straps respectively.
11
Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
12
12
13
Reviewed-by: Joel Stanley <joel@jms.id.au>
13
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
14
Reviewed-by: Cédric Le Goater <clg@kaod.org>
14
Message-id: 20221226220303.14420-3-strahinja.p.jankovic@gmail.com
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Tested-by: Alexander Bulekov <alxndr@bu.edu>
18
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
19
Message-id: 20200911052101.2602693-2-hskinnemoen@google.com
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
16
---
22
include/hw/misc/npcm7xx_gcr.h | 43 ++++++
17
include/hw/arm/allwinner-a10.h | 2 +
23
hw/misc/npcm7xx_gcr.c | 269 ++++++++++++++++++++++++++++++++++
18
include/hw/misc/allwinner-a10-dramc.h | 68 ++++++++++
24
MAINTAINERS | 8 +
19
hw/arm/allwinner-a10.c | 7 +
25
hw/arm/Kconfig | 3 +
20
hw/misc/allwinner-a10-dramc.c | 179 ++++++++++++++++++++++++++
26
hw/misc/meson.build | 3 +
21
hw/arm/Kconfig | 1 +
27
hw/misc/trace-events | 4 +
22
hw/misc/Kconfig | 3 +
28
6 files changed, 330 insertions(+)
23
hw/misc/meson.build | 1 +
29
create mode 100644 include/hw/misc/npcm7xx_gcr.h
24
7 files changed, 261 insertions(+)
30
create mode 100644 hw/misc/npcm7xx_gcr.c
25
create mode 100644 include/hw/misc/allwinner-a10-dramc.h
31
26
create mode 100644 hw/misc/allwinner-a10-dramc.c
32
diff --git a/include/hw/misc/npcm7xx_gcr.h b/include/hw/misc/npcm7xx_gcr.h
27
28
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/include/hw/arm/allwinner-a10.h
31
+++ b/include/hw/arm/allwinner-a10.h
32
@@ -XXX,XX +XXX,XX @@
33
#include "hw/usb/hcd-ehci.h"
34
#include "hw/rtc/allwinner-rtc.h"
35
#include "hw/misc/allwinner-a10-ccm.h"
36
+#include "hw/misc/allwinner-a10-dramc.h"
37
38
#include "target/arm/cpu.h"
39
#include "qom/object.h"
40
@@ -XXX,XX +XXX,XX @@ struct AwA10State {
41
42
ARMCPU cpu;
43
AwA10ClockCtlState ccm;
44
+ AwA10DramControllerState dramc;
45
AwA10PITState timer;
46
AwA10PICState intc;
47
AwEmacState emac;
48
diff --git a/include/hw/misc/allwinner-a10-dramc.h b/include/hw/misc/allwinner-a10-dramc.h
33
new file mode 100644
49
new file mode 100644
34
index XXXXXXX..XXXXXXX
50
index XXXXXXX..XXXXXXX
35
--- /dev/null
51
--- /dev/null
36
+++ b/include/hw/misc/npcm7xx_gcr.h
52
+++ b/include/hw/misc/allwinner-a10-dramc.h
37
@@ -XXX,XX +XXX,XX @@
53
@@ -XXX,XX +XXX,XX @@
38
+/*
54
+/*
39
+ * Nuvoton NPCM7xx System Global Control Registers.
55
+ * Allwinner A10 DRAM Controller emulation
40
+ *
56
+ *
41
+ * Copyright 2020 Google LLC
57
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
42
+ *
58
+ *
43
+ * This program is free software; you can redistribute it and/or modify it
59
+ * This file is derived from Allwinner H3 DRAMC,
44
+ * under the terms of the GNU General Public License as published by the
60
+ * by Niek Linnenbank.
45
+ * Free Software Foundation; either version 2 of the License, or
61
+ *
62
+ * This program is free software: you can redistribute it and/or modify
63
+ * it under the terms of the GNU General Public License as published by
64
+ * the Free Software Foundation, either version 2 of the License, or
46
+ * (at your option) any later version.
65
+ * (at your option) any later version.
47
+ *
66
+ *
48
+ * This program is distributed in the hope that it will be useful, but WITHOUT
67
+ * This program is distributed in the hope that it will be useful,
49
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
68
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
50
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
69
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51
+ * for more details.
70
+ * GNU General Public License for more details.
52
+ */
71
+ *
53
+#ifndef NPCM7XX_GCR_H
72
+ * You should have received a copy of the GNU General Public License
54
+#define NPCM7XX_GCR_H
73
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
55
+
74
+ */
56
+#include "exec/memory.h"
75
+
76
+#ifndef HW_MISC_ALLWINNER_A10_DRAMC_H
77
+#define HW_MISC_ALLWINNER_A10_DRAMC_H
78
+
79
+#include "qom/object.h"
57
+#include "hw/sysbus.h"
80
+#include "hw/sysbus.h"
58
+
81
+#include "hw/register.h"
59
+/*
82
+
60
+ * Number of registers in our device state structure. Don't change this without
83
+/**
61
+ * incrementing the version_id in the vmstate.
84
+ * @name Constants
62
+ */
85
+ * @{
63
+#define NPCM7XX_GCR_NR_REGS (0x148 / sizeof(uint32_t))
86
+ */
64
+
87
+
65
+typedef struct NPCM7xxGCRState {
88
+/** Size of register I/O address space used by DRAMC device */
66
+ SysBusDevice parent;
89
+#define AW_A10_DRAMC_IOSIZE (0x1000)
67
+
90
+
91
+/** Total number of known registers */
92
+#define AW_A10_DRAMC_REGS_NUM (AW_A10_DRAMC_IOSIZE / sizeof(uint32_t))
93
+
94
+/** @} */
95
+
96
+/**
97
+ * @name Object model
98
+ * @{
99
+ */
100
+
101
+#define TYPE_AW_A10_DRAMC "allwinner-a10-dramc"
102
+OBJECT_DECLARE_SIMPLE_TYPE(AwA10DramControllerState, AW_A10_DRAMC)
103
+
104
+/** @} */
105
+
106
+/**
107
+ * Allwinner A10 DRAMC object instance state.
108
+ */
109
+struct AwA10DramControllerState {
110
+ /*< private >*/
111
+ SysBusDevice parent_obj;
112
+ /*< public >*/
113
+
114
+ /** Maps I/O registers in physical memory */
68
+ MemoryRegion iomem;
115
+ MemoryRegion iomem;
69
+
116
+
70
+ uint32_t regs[NPCM7XX_GCR_NR_REGS];
117
+ /** Array of hardware registers */
71
+
118
+ uint32_t regs[AW_A10_DRAMC_REGS_NUM];
72
+ uint32_t reset_pwron;
119
+};
73
+ uint32_t reset_mdlr;
120
+
74
+ uint32_t reset_intcr3;
121
+#endif /* HW_MISC_ALLWINNER_A10_DRAMC_H */
75
+} NPCM7xxGCRState;
122
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
76
+
123
index XXXXXXX..XXXXXXX 100644
77
+#define TYPE_NPCM7XX_GCR "npcm7xx-gcr"
124
--- a/hw/arm/allwinner-a10.c
78
+#define NPCM7XX_GCR(obj) OBJECT_CHECK(NPCM7xxGCRState, (obj), TYPE_NPCM7XX_GCR)
125
+++ b/hw/arm/allwinner-a10.c
79
+
126
@@ -XXX,XX +XXX,XX @@
80
+#endif /* NPCM7XX_GCR_H */
127
#include "hw/boards.h"
81
diff --git a/hw/misc/npcm7xx_gcr.c b/hw/misc/npcm7xx_gcr.c
128
#include "hw/usb/hcd-ohci.h"
129
130
+#define AW_A10_DRAMC_BASE 0x01c01000
131
#define AW_A10_MMC0_BASE 0x01c0f000
132
#define AW_A10_CCM_BASE 0x01c20000
133
#define AW_A10_PIC_REG_BASE 0x01c20400
134
@@ -XXX,XX +XXX,XX @@ static void aw_a10_init(Object *obj)
135
136
object_initialize_child(obj, "ccm", &s->ccm, TYPE_AW_A10_CCM);
137
138
+ object_initialize_child(obj, "dramc", &s->dramc, TYPE_AW_A10_DRAMC);
139
+
140
object_initialize_child(obj, "emac", &s->emac, TYPE_AW_EMAC);
141
142
object_initialize_child(obj, "sata", &s->sata, TYPE_ALLWINNER_AHCI);
143
@@ -XXX,XX +XXX,XX @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
144
sysbus_realize(SYS_BUS_DEVICE(&s->ccm), &error_fatal);
145
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, AW_A10_CCM_BASE);
146
147
+ /* DRAM Control Module */
148
+ sysbus_realize(SYS_BUS_DEVICE(&s->dramc), &error_fatal);
149
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 0, AW_A10_DRAMC_BASE);
150
+
151
/* FIXME use qdev NIC properties instead of nd_table[] */
152
if (nd_table[0].used) {
153
qemu_check_nic_model(&nd_table[0], TYPE_AW_EMAC);
154
diff --git a/hw/misc/allwinner-a10-dramc.c b/hw/misc/allwinner-a10-dramc.c
82
new file mode 100644
155
new file mode 100644
83
index XXXXXXX..XXXXXXX
156
index XXXXXXX..XXXXXXX
84
--- /dev/null
157
--- /dev/null
85
+++ b/hw/misc/npcm7xx_gcr.c
158
+++ b/hw/misc/allwinner-a10-dramc.c
86
@@ -XXX,XX +XXX,XX @@
159
@@ -XXX,XX +XXX,XX @@
87
+/*
160
+/*
88
+ * Nuvoton NPCM7xx System Global Control Registers.
161
+ * Allwinner A10 DRAM Controller emulation
89
+ *
162
+ *
90
+ * Copyright 2020 Google LLC
163
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
91
+ *
164
+ *
92
+ * This program is free software; you can redistribute it and/or modify it
165
+ * This file is derived from Allwinner H3 DRAMC,
93
+ * under the terms of the GNU General Public License as published by the
166
+ * by Niek Linnenbank.
94
+ * Free Software Foundation; either version 2 of the License, or
167
+ *
168
+ * This program is free software: you can redistribute it and/or modify
169
+ * it under the terms of the GNU General Public License as published by
170
+ * the Free Software Foundation, either version 2 of the License, or
95
+ * (at your option) any later version.
171
+ * (at your option) any later version.
96
+ *
172
+ *
97
+ * This program is distributed in the hope that it will be useful, but WITHOUT
173
+ * This program is distributed in the hope that it will be useful,
98
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
174
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
99
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
175
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
100
+ * for more details.
176
+ * GNU General Public License for more details.
177
+ *
178
+ * You should have received a copy of the GNU General Public License
179
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
101
+ */
180
+ */
102
+
181
+
103
+#include "qemu/osdep.h"
182
+#include "qemu/osdep.h"
104
+
183
+#include "qemu/units.h"
105
+#include "hw/misc/npcm7xx_gcr.h"
184
+#include "hw/sysbus.h"
106
+#include "hw/qdev-properties.h"
107
+#include "migration/vmstate.h"
185
+#include "migration/vmstate.h"
108
+#include "qapi/error.h"
109
+#include "qemu/cutils.h"
110
+#include "qemu/log.h"
186
+#include "qemu/log.h"
111
+#include "qemu/module.h"
187
+#include "qemu/module.h"
112
+#include "qemu/units.h"
188
+#include "hw/misc/allwinner-a10-dramc.h"
113
+
189
+
114
+#include "trace.h"
190
+/* DRAMC register offsets */
115
+
191
+enum {
116
+#define NPCM7XX_GCR_MIN_DRAM_SIZE (128 * MiB)
192
+ REG_SDR_CCR = 0x0000,
117
+#define NPCM7XX_GCR_MAX_DRAM_SIZE (2 * GiB)
193
+ REG_SDR_ZQCR0 = 0x00a8,
118
+
194
+ REG_SDR_ZQSR = 0x00b0
119
+enum NPCM7xxGCRRegisters {
195
+};
120
+ NPCM7XX_GCR_PDID,
196
+
121
+ NPCM7XX_GCR_PWRON,
197
+#define REG_INDEX(offset) (offset / sizeof(uint32_t))
122
+ NPCM7XX_GCR_MFSEL1 = 0x0c / sizeof(uint32_t),
198
+
123
+ NPCM7XX_GCR_MFSEL2,
199
+/* DRAMC register flags */
124
+ NPCM7XX_GCR_MISCPE,
200
+enum {
125
+ NPCM7XX_GCR_SPSWC = 0x038 / sizeof(uint32_t),
201
+ REG_SDR_CCR_DATA_TRAINING = (1 << 30),
126
+ NPCM7XX_GCR_INTCR,
202
+ REG_SDR_CCR_DRAM_INIT = (1 << 31),
127
+ NPCM7XX_GCR_INTSR,
203
+};
128
+ NPCM7XX_GCR_HIFCR = 0x050 / sizeof(uint32_t),
204
+enum {
129
+ NPCM7XX_GCR_INTCR2 = 0x060 / sizeof(uint32_t),
205
+ REG_SDR_ZQSR_ZCAL = (1 << 31),
130
+ NPCM7XX_GCR_MFSEL3,
206
+};
131
+ NPCM7XX_GCR_SRCNT,
207
+
132
+ NPCM7XX_GCR_RESSR,
208
+/* DRAMC register reset values */
133
+ NPCM7XX_GCR_RLOCKR1,
209
+enum {
134
+ NPCM7XX_GCR_FLOCKR1,
210
+ REG_SDR_CCR_RESET = 0x80020000,
135
+ NPCM7XX_GCR_DSCNT,
211
+ REG_SDR_ZQCR0_RESET = 0x07b00000,
136
+ NPCM7XX_GCR_MDLR,
212
+ REG_SDR_ZQSR_RESET = 0x80000000
137
+ NPCM7XX_GCR_SCRPAD3,
213
+};
138
+ NPCM7XX_GCR_SCRPAD2,
214
+
139
+ NPCM7XX_GCR_DAVCLVLR = 0x098 / sizeof(uint32_t),
215
+static uint64_t allwinner_a10_dramc_read(void *opaque, hwaddr offset,
140
+ NPCM7XX_GCR_INTCR3,
216
+ unsigned size)
141
+ NPCM7XX_GCR_VSINTR = 0x0ac / sizeof(uint32_t),
217
+{
142
+ NPCM7XX_GCR_MFSEL4,
218
+ const AwA10DramControllerState *s = AW_A10_DRAMC(opaque);
143
+ NPCM7XX_GCR_CPBPNTR = 0x0c4 / sizeof(uint32_t),
219
+ const uint32_t idx = REG_INDEX(offset);
144
+ NPCM7XX_GCR_CPCTL = 0x0d0 / sizeof(uint32_t),
220
+
145
+ NPCM7XX_GCR_CP2BST,
221
+ switch (offset) {
146
+ NPCM7XX_GCR_B2CPNT,
222
+ case REG_SDR_CCR:
147
+ NPCM7XX_GCR_CPPCTL,
223
+ case REG_SDR_ZQCR0:
148
+ NPCM7XX_GCR_I2CSEGSEL,
224
+ case REG_SDR_ZQSR:
149
+ NPCM7XX_GCR_I2CSEGCTL,
225
+ break;
150
+ NPCM7XX_GCR_VSRCR,
226
+ case 0x2e4 ... AW_A10_DRAMC_IOSIZE:
151
+ NPCM7XX_GCR_MLOCKR,
227
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
152
+ NPCM7XX_GCR_SCRPAD = 0x013c / sizeof(uint32_t),
228
+ __func__, (uint32_t)offset);
153
+ NPCM7XX_GCR_USB1PHYCTL,
229
+ return 0;
154
+ NPCM7XX_GCR_USB2PHYCTL,
230
+ default:
155
+ NPCM7XX_GCR_REGS_END,
231
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented read offset 0x%04x\n",
156
+};
232
+ __func__, (uint32_t)offset);
157
+
158
+static const uint32_t cold_reset_values[NPCM7XX_GCR_NR_REGS] = {
159
+ [NPCM7XX_GCR_PDID] = 0x04a92750, /* Poleg A1 */
160
+ [NPCM7XX_GCR_MISCPE] = 0x0000ffff,
161
+ [NPCM7XX_GCR_SPSWC] = 0x00000003,
162
+ [NPCM7XX_GCR_INTCR] = 0x0000035e,
163
+ [NPCM7XX_GCR_HIFCR] = 0x0000004e,
164
+ [NPCM7XX_GCR_INTCR2] = (1U << 19), /* DDR initialized */
165
+ [NPCM7XX_GCR_RESSR] = 0x80000000,
166
+ [NPCM7XX_GCR_DSCNT] = 0x000000c0,
167
+ [NPCM7XX_GCR_DAVCLVLR] = 0x5a00f3cf,
168
+ [NPCM7XX_GCR_SCRPAD] = 0x00000008,
169
+ [NPCM7XX_GCR_USB1PHYCTL] = 0x034730e4,
170
+ [NPCM7XX_GCR_USB2PHYCTL] = 0x034730e4,
171
+};
172
+
173
+static uint64_t npcm7xx_gcr_read(void *opaque, hwaddr offset, unsigned size)
174
+{
175
+ uint32_t reg = offset / sizeof(uint32_t);
176
+ NPCM7xxGCRState *s = opaque;
177
+
178
+ if (reg >= NPCM7XX_GCR_NR_REGS) {
179
+ qemu_log_mask(LOG_GUEST_ERROR,
180
+ "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
181
+ __func__, offset);
182
+ return 0;
233
+ return 0;
183
+ }
234
+ }
184
+
235
+
185
+ trace_npcm7xx_gcr_read(offset, s->regs[reg]);
236
+ return s->regs[idx];
186
+
237
+}
187
+ return s->regs[reg];
238
+
188
+}
239
+static void allwinner_a10_dramc_write(void *opaque, hwaddr offset,
189
+
240
+ uint64_t val, unsigned size)
190
+static void npcm7xx_gcr_write(void *opaque, hwaddr offset,
241
+{
191
+ uint64_t v, unsigned size)
242
+ AwA10DramControllerState *s = AW_A10_DRAMC(opaque);
192
+{
243
+ const uint32_t idx = REG_INDEX(offset);
193
+ uint32_t reg = offset / sizeof(uint32_t);
244
+
194
+ NPCM7xxGCRState *s = opaque;
245
+ switch (offset) {
195
+ uint32_t value = v;
246
+ case REG_SDR_CCR:
196
+
247
+ if (val & REG_SDR_CCR_DRAM_INIT) {
197
+ trace_npcm7xx_gcr_write(offset, value);
248
+ /* Clear DRAM_INIT to indicate process is done. */
198
+
249
+ val &= ~REG_SDR_CCR_DRAM_INIT;
199
+ if (reg >= NPCM7XX_GCR_NR_REGS) {
250
+ }
200
+ qemu_log_mask(LOG_GUEST_ERROR,
251
+ if (val & REG_SDR_CCR_DATA_TRAINING) {
201
+ "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
252
+ /* Clear DATA_TRAINING to indicate process is done. */
202
+ __func__, offset);
253
+ val &= ~REG_SDR_CCR_DATA_TRAINING;
203
+ return;
254
+ }
255
+ break;
256
+ case REG_SDR_ZQCR0:
257
+ /* Set ZCAL in ZQSR to indicate calibration is done. */
258
+ s->regs[REG_INDEX(REG_SDR_ZQSR)] |= REG_SDR_ZQSR_ZCAL;
259
+ break;
260
+ case 0x2e4 ... AW_A10_DRAMC_IOSIZE:
261
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
262
+ __func__, (uint32_t)offset);
263
+ break;
264
+ default:
265
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented write offset 0x%04x\n",
266
+ __func__, (uint32_t)offset);
267
+ break;
204
+ }
268
+ }
205
+
269
+
206
+ switch (reg) {
270
+ s->regs[idx] = (uint32_t) val;
207
+ case NPCM7XX_GCR_PDID:
271
+}
208
+ case NPCM7XX_GCR_PWRON:
272
+
209
+ case NPCM7XX_GCR_INTSR:
273
+static const MemoryRegionOps allwinner_a10_dramc_ops = {
210
+ qemu_log_mask(LOG_GUEST_ERROR,
274
+ .read = allwinner_a10_dramc_read,
211
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
275
+ .write = allwinner_a10_dramc_write,
212
+ __func__, offset);
276
+ .endianness = DEVICE_NATIVE_ENDIAN,
213
+ return;
277
+ .valid = {
214
+
278
+ .min_access_size = 4,
215
+ case NPCM7XX_GCR_RESSR:
279
+ .max_access_size = 4,
216
+ case NPCM7XX_GCR_CP2BST:
217
+ /* Write 1 to clear */
218
+ value = s->regs[reg] & ~value;
219
+ break;
220
+
221
+ case NPCM7XX_GCR_RLOCKR1:
222
+ case NPCM7XX_GCR_MDLR:
223
+ /* Write 1 to set */
224
+ value |= s->regs[reg];
225
+ break;
226
+ };
227
+
228
+ s->regs[reg] = value;
229
+}
230
+
231
+static const struct MemoryRegionOps npcm7xx_gcr_ops = {
232
+ .read = npcm7xx_gcr_read,
233
+ .write = npcm7xx_gcr_write,
234
+ .endianness = DEVICE_LITTLE_ENDIAN,
235
+ .valid = {
236
+ .min_access_size = 4,
237
+ .max_access_size = 4,
238
+ .unaligned = false,
239
+ },
280
+ },
240
+};
281
+ .impl.min_access_size = 4,
241
+
282
+};
242
+static void npcm7xx_gcr_enter_reset(Object *obj, ResetType type)
283
+
243
+{
284
+static void allwinner_a10_dramc_reset_enter(Object *obj, ResetType type)
244
+ NPCM7xxGCRState *s = NPCM7XX_GCR(obj);
285
+{
245
+
286
+ AwA10DramControllerState *s = AW_A10_DRAMC(obj);
246
+ QEMU_BUILD_BUG_ON(sizeof(s->regs) != sizeof(cold_reset_values));
287
+
247
+
288
+ /* Set default values for registers */
248
+ switch (type) {
289
+ s->regs[REG_INDEX(REG_SDR_CCR)] = REG_SDR_CCR_RESET;
249
+ case RESET_TYPE_COLD:
290
+ s->regs[REG_INDEX(REG_SDR_ZQCR0)] = REG_SDR_ZQCR0_RESET;
250
+ memcpy(s->regs, cold_reset_values, sizeof(s->regs));
291
+ s->regs[REG_INDEX(REG_SDR_ZQSR)] = REG_SDR_ZQSR_RESET;
251
+ s->regs[NPCM7XX_GCR_PWRON] = s->reset_pwron;
292
+}
252
+ s->regs[NPCM7XX_GCR_MDLR] = s->reset_mdlr;
293
+
253
+ s->regs[NPCM7XX_GCR_INTCR3] = s->reset_intcr3;
294
+static void allwinner_a10_dramc_init(Object *obj)
254
+ break;
295
+{
296
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
297
+ AwA10DramControllerState *s = AW_A10_DRAMC(obj);
298
+
299
+ /* Memory mapping */
300
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_a10_dramc_ops, s,
301
+ TYPE_AW_A10_DRAMC, AW_A10_DRAMC_IOSIZE);
302
+ sysbus_init_mmio(sbd, &s->iomem);
303
+}
304
+
305
+static const VMStateDescription allwinner_a10_dramc_vmstate = {
306
+ .name = "allwinner-a10-dramc",
307
+ .version_id = 1,
308
+ .minimum_version_id = 1,
309
+ .fields = (VMStateField[]) {
310
+ VMSTATE_UINT32_ARRAY(regs, AwA10DramControllerState,
311
+ AW_A10_DRAMC_REGS_NUM),
312
+ VMSTATE_END_OF_LIST()
255
+ }
313
+ }
256
+}
314
+};
257
+
315
+
258
+static void npcm7xx_gcr_realize(DeviceState *dev, Error **errp)
316
+static void allwinner_a10_dramc_class_init(ObjectClass *klass, void *data)
259
+{
317
+{
260
+ ERRP_GUARD();
318
+ DeviceClass *dc = DEVICE_CLASS(klass);
261
+ NPCM7xxGCRState *s = NPCM7XX_GCR(dev);
262
+ uint64_t dram_size;
263
+ Object *obj;
264
+
265
+ obj = object_property_get_link(OBJECT(dev), "dram-mr", errp);
266
+ if (!obj) {
267
+ error_prepend(errp, "%s: required dram-mr link not found: ", __func__);
268
+ return;
269
+ }
270
+ dram_size = memory_region_size(MEMORY_REGION(obj));
271
+ if (!is_power_of_2(dram_size) ||
272
+ dram_size < NPCM7XX_GCR_MIN_DRAM_SIZE ||
273
+ dram_size > NPCM7XX_GCR_MAX_DRAM_SIZE) {
274
+ g_autofree char *sz = size_to_str(dram_size);
275
+ g_autofree char *min_sz = size_to_str(NPCM7XX_GCR_MIN_DRAM_SIZE);
276
+ g_autofree char *max_sz = size_to_str(NPCM7XX_GCR_MAX_DRAM_SIZE);
277
+ error_setg(errp, "%s: unsupported DRAM size %s", __func__, sz);
278
+ error_append_hint(errp,
279
+ "DRAM size must be a power of two between %s and %s,"
280
+ " inclusive.\n", min_sz, max_sz);
281
+ return;
282
+ }
283
+
284
+ /* Power-on reset value */
285
+ s->reset_intcr3 = 0x00001002;
286
+
287
+ /*
288
+ * The GMMAP (Graphics Memory Map) field is used by u-boot to detect the
289
+ * DRAM size, and is normally initialized by the boot block as part of DRAM
290
+ * training. However, since we don't have a complete emulation of the
291
+ * memory controller and try to make it look like it has already been
292
+ * initialized, the boot block will skip this initialization, and we need
293
+ * to make sure this field is set correctly up front.
294
+ *
295
+ * WARNING: some versions of u-boot only looks at bits 8 and 9, so 2 GiB of
296
+ * DRAM will be interpreted as 128 MiB.
297
+ *
298
+ * https://github.com/Nuvoton-Israel/u-boot/blob/2aef993bd2aafeb5408dbaad0f3ce099ee40c4aa/board/nuvoton/poleg/poleg.c#L244
299
+ */
300
+ s->reset_intcr3 |= ctz64(dram_size / NPCM7XX_GCR_MIN_DRAM_SIZE) << 8;
301
+}
302
+
303
+static void npcm7xx_gcr_init(Object *obj)
304
+{
305
+ NPCM7xxGCRState *s = NPCM7XX_GCR(obj);
306
+
307
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_gcr_ops, s,
308
+ TYPE_NPCM7XX_GCR, 4 * KiB);
309
+ sysbus_init_mmio(&s->parent, &s->iomem);
310
+}
311
+
312
+static const VMStateDescription vmstate_npcm7xx_gcr = {
313
+ .name = "npcm7xx-gcr",
314
+ .version_id = 0,
315
+ .minimum_version_id = 0,
316
+ .fields = (VMStateField[]) {
317
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxGCRState, NPCM7XX_GCR_NR_REGS),
318
+ VMSTATE_END_OF_LIST(),
319
+ },
320
+};
321
+
322
+static Property npcm7xx_gcr_properties[] = {
323
+ DEFINE_PROP_UINT32("disabled-modules", NPCM7xxGCRState, reset_mdlr, 0),
324
+ DEFINE_PROP_UINT32("power-on-straps", NPCM7xxGCRState, reset_pwron, 0),
325
+ DEFINE_PROP_END_OF_LIST(),
326
+};
327
+
328
+static void npcm7xx_gcr_class_init(ObjectClass *klass, void *data)
329
+{
330
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
319
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
331
+ DeviceClass *dc = DEVICE_CLASS(klass);
320
+
332
+
321
+ rc->phases.enter = allwinner_a10_dramc_reset_enter;
333
+ QEMU_BUILD_BUG_ON(NPCM7XX_GCR_REGS_END > NPCM7XX_GCR_NR_REGS);
322
+ dc->vmsd = &allwinner_a10_dramc_vmstate;
334
+
323
+}
335
+ dc->desc = "NPCM7xx System Global Control Registers";
324
+
336
+ dc->realize = npcm7xx_gcr_realize;
325
+static const TypeInfo allwinner_a10_dramc_info = {
337
+ dc->vmsd = &vmstate_npcm7xx_gcr;
326
+ .name = TYPE_AW_A10_DRAMC,
338
+ rc->phases.enter = npcm7xx_gcr_enter_reset;
327
+ .parent = TYPE_SYS_BUS_DEVICE,
339
+
328
+ .instance_init = allwinner_a10_dramc_init,
340
+ device_class_set_props(dc, npcm7xx_gcr_properties);
329
+ .instance_size = sizeof(AwA10DramControllerState),
341
+}
330
+ .class_init = allwinner_a10_dramc_class_init,
342
+
331
+};
343
+static const TypeInfo npcm7xx_gcr_info = {
332
+
344
+ .name = TYPE_NPCM7XX_GCR,
333
+static void allwinner_a10_dramc_register(void)
345
+ .parent = TYPE_SYS_BUS_DEVICE,
334
+{
346
+ .instance_size = sizeof(NPCM7xxGCRState),
335
+ type_register_static(&allwinner_a10_dramc_info);
347
+ .instance_init = npcm7xx_gcr_init,
336
+}
348
+ .class_init = npcm7xx_gcr_class_init,
337
+
349
+};
338
+type_init(allwinner_a10_dramc_register)
350
+
351
+static void npcm7xx_gcr_register_type(void)
352
+{
353
+ type_register_static(&npcm7xx_gcr_info);
354
+}
355
+type_init(npcm7xx_gcr_register_type);
356
diff --git a/MAINTAINERS b/MAINTAINERS
357
index XXXXXXX..XXXXXXX 100644
358
--- a/MAINTAINERS
359
+++ b/MAINTAINERS
360
@@ -XXX,XX +XXX,XX @@ S: Odd Fixes
361
F: hw/arm/musicpal.c
362
F: docs/system/arm/musicpal.rst
363
364
+Nuvoton NPCM7xx
365
+M: Havard Skinnemoen <hskinnemoen@google.com>
366
+M: Tyrone Ting <kfting@nuvoton.com>
367
+L: qemu-arm@nongnu.org
368
+S: Supported
369
+F: hw/*/npcm7xx*
370
+F: include/hw/*/npcm7xx*
371
+
372
nSeries
373
M: Andrzej Zaborowski <balrogg@gmail.com>
374
M: Peter Maydell <peter.maydell@linaro.org>
375
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
339
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
376
index XXXXXXX..XXXXXXX 100644
340
index XXXXXXX..XXXXXXX 100644
377
--- a/hw/arm/Kconfig
341
--- a/hw/arm/Kconfig
378
+++ b/hw/arm/Kconfig
342
+++ b/hw/arm/Kconfig
379
@@ -XXX,XX +XXX,XX @@ config XLNX_VERSAL
343
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10
380
select VIRTIO_MMIO
344
select ALLWINNER_A10_PIT
345
select ALLWINNER_A10_PIC
346
select ALLWINNER_A10_CCM
347
+ select ALLWINNER_A10_DRAMC
348
select ALLWINNER_EMAC
349
select SERIAL
381
select UNIMP
350
select UNIMP
382
351
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
383
+config NPCM7XX
352
index XXXXXXX..XXXXXXX 100644
353
--- a/hw/misc/Kconfig
354
+++ b/hw/misc/Kconfig
355
@@ -XXX,XX +XXX,XX @@ config LASI
356
config ALLWINNER_A10_CCM
357
bool
358
359
+config ALLWINNER_A10_DRAMC
384
+ bool
360
+ bool
385
+
361
+
386
config FSL_IMX25
362
source macio/Kconfig
387
bool
388
select IMX
389
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
363
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
390
index XXXXXXX..XXXXXXX 100644
364
index XXXXXXX..XXXXXXX 100644
391
--- a/hw/misc/meson.build
365
--- a/hw/misc/meson.build
392
+++ b/hw/misc/meson.build
366
+++ b/hw/misc/meson.build
393
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_IMX', if_true: files(
367
@@ -XXX,XX +XXX,XX @@ subdir('macio')
394
))
368
softmmu_ss.add(when: 'CONFIG_IVSHMEM_DEVICE', if_true: files('ivshmem.c'))
395
softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-hpdmc.c', 'milkymist-pfpu.c'))
369
396
softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
370
softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_CCM', if_true: files('allwinner-a10-ccm.c'))
397
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
371
+softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_DRAMC', if_true: files('allwinner-a10-dramc.c'))
398
+ 'npcm7xx_gcr.c',
372
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-ccu.c'))
399
+))
373
specific_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-cpucfg.c'))
400
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files(
374
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-dramc.c'))
401
'omap_clk.c',
402
'omap_gpmc.c',
403
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
404
index XXXXXXX..XXXXXXX 100644
405
--- a/hw/misc/trace-events
406
+++ b/hw/misc/trace-events
407
@@ -XXX,XX +XXX,XX @@ mos6522_set_sr_int(void) "set sr_int"
408
mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64
409
mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x"
410
411
+# npcm7xx_gcr.c
412
+npcm7xx_gcr_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
413
+npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
414
+
415
# stm32f4xx_syscfg.c
416
stm32f4xx_syscfg_set_irq(int gpio, int line, int level) "Interupt: GPIO: %d, Line: %d; Level: %d"
417
stm32f4xx_pulse_exti(int irq) "Pulse EXTI: %d"
418
--
375
--
419
2.20.1
376
2.34.1
420
421
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
2
2
3
This implements a device model for the NPCM7xx SPI flash controller.
3
This patch implements Allwinner TWI/I2C controller emulation. Only
4
master-mode functionality is implemented.
4
5
5
Direct reads and writes, and user-mode transactions have been tested in
6
The SPL boot for Cubieboard expects AXP209 PMIC on TWI0/I2C0 bus, so this is
6
various modes. Protection features are not implemented yet.
7
first part enabling the TWI/I2C bus operation.
7
8
8
All the FIU instances are available in the SoC's address space,
9
Since both Allwinner A10 and H3 use the same module, it is added for
9
regardless of whether or not they're connected to actual flash chips.
10
both boards.
10
11
11
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
12
Docs are also updated for Cubieboard and Orangepi-PC board to indicate
12
Reviewed-by: Cédric Le Goater <clg@kaod.org>
13
I2C availability.
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
15
Tested-by: Alexander Bulekov <alxndr@bu.edu>
16
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
16
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
17
Message-id: 20221226220303.14420-4-strahinja.p.jankovic@gmail.com
17
Message-id: 20200911052101.2602693-11-hskinnemoen@google.com
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
19
---
20
include/hw/arm/npcm7xx.h | 2 +
20
docs/system/arm/cubieboard.rst | 1 +
21
include/hw/ssi/npcm7xx_fiu.h | 73 +++++
21
docs/system/arm/orangepi.rst | 1 +
22
hw/arm/npcm7xx.c | 58 ++++
22
include/hw/arm/allwinner-a10.h | 2 +
23
hw/ssi/npcm7xx_fiu.c | 572 +++++++++++++++++++++++++++++++++++
23
include/hw/arm/allwinner-h3.h | 3 +
24
hw/arm/Kconfig | 1 +
24
include/hw/i2c/allwinner-i2c.h | 55 ++++
25
hw/ssi/meson.build | 1 +
25
hw/arm/allwinner-a10.c | 8 +
26
hw/ssi/trace-events | 11 +
26
hw/arm/allwinner-h3.c | 11 +-
27
7 files changed, 718 insertions(+)
27
hw/i2c/allwinner-i2c.c | 459 +++++++++++++++++++++++++++++++++
28
create mode 100644 include/hw/ssi/npcm7xx_fiu.h
28
hw/arm/Kconfig | 2 +
29
create mode 100644 hw/ssi/npcm7xx_fiu.c
29
hw/i2c/Kconfig | 4 +
30
hw/i2c/meson.build | 1 +
31
hw/i2c/trace-events | 5 +
32
12 files changed, 551 insertions(+), 1 deletion(-)
33
create mode 100644 include/hw/i2c/allwinner-i2c.h
34
create mode 100644 hw/i2c/allwinner-i2c.c
30
35
31
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
36
diff --git a/docs/system/arm/cubieboard.rst b/docs/system/arm/cubieboard.rst
32
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
33
--- a/include/hw/arm/npcm7xx.h
38
--- a/docs/system/arm/cubieboard.rst
34
+++ b/include/hw/arm/npcm7xx.h
39
+++ b/docs/system/arm/cubieboard.rst
40
@@ -XXX,XX +XXX,XX @@ Emulated devices:
41
- SDHCI
42
- USB controller
43
- SATA controller
44
+- TWI (I2C) controller
45
diff --git a/docs/system/arm/orangepi.rst b/docs/system/arm/orangepi.rst
46
index XXXXXXX..XXXXXXX 100644
47
--- a/docs/system/arm/orangepi.rst
48
+++ b/docs/system/arm/orangepi.rst
49
@@ -XXX,XX +XXX,XX @@ The Orange Pi PC machine supports the following devices:
50
* Clock Control Unit
51
* System Control module
52
* Security Identifier device
53
+ * TWI (I2C)
54
55
Limitations
56
"""""""""""
57
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
58
index XXXXXXX..XXXXXXX 100644
59
--- a/include/hw/arm/allwinner-a10.h
60
+++ b/include/hw/arm/allwinner-a10.h
35
@@ -XXX,XX +XXX,XX @@
61
@@ -XXX,XX +XXX,XX @@
36
#include "hw/misc/npcm7xx_gcr.h"
62
#include "hw/rtc/allwinner-rtc.h"
37
#include "hw/nvram/npcm7xx_otp.h"
63
#include "hw/misc/allwinner-a10-ccm.h"
38
#include "hw/timer/npcm7xx_timer.h"
64
#include "hw/misc/allwinner-a10-dramc.h"
39
+#include "hw/ssi/npcm7xx_fiu.h"
65
+#include "hw/i2c/allwinner-i2c.h"
66
40
#include "target/arm/cpu.h"
67
#include "target/arm/cpu.h"
41
68
#include "qom/object.h"
42
#define NPCM7XX_MAX_NUM_CPUS (2)
69
@@ -XXX,XX +XXX,XX @@ struct AwA10State {
43
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
70
AwEmacState emac;
44
NPCM7xxOTPState key_storage;
71
AllwinnerAHCIState sata;
45
NPCM7xxOTPState fuse_array;
72
AwSdHostState mmc0;
46
NPCM7xxMCState mc;
73
+ AWI2CState i2c0;
47
+ NPCM7xxFIUState fiu[2];
74
AwRtcState rtc;
48
} NPCM7xxState;
75
MemoryRegion sram_a;
49
76
EHCISysBusState ehci[AW_A10_NUM_USB];
50
#define TYPE_NPCM7XX "npcm7xx"
77
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
51
diff --git a/include/hw/ssi/npcm7xx_fiu.h b/include/hw/ssi/npcm7xx_fiu.h
78
index XXXXXXX..XXXXXXX 100644
79
--- a/include/hw/arm/allwinner-h3.h
80
+++ b/include/hw/arm/allwinner-h3.h
81
@@ -XXX,XX +XXX,XX @@
82
#include "hw/sd/allwinner-sdhost.h"
83
#include "hw/net/allwinner-sun8i-emac.h"
84
#include "hw/rtc/allwinner-rtc.h"
85
+#include "hw/i2c/allwinner-i2c.h"
86
#include "target/arm/cpu.h"
87
#include "sysemu/block-backend.h"
88
89
@@ -XXX,XX +XXX,XX @@ enum {
90
AW_H3_DEV_UART2,
91
AW_H3_DEV_UART3,
92
AW_H3_DEV_EMAC,
93
+ AW_H3_DEV_TWI0,
94
AW_H3_DEV_DRAMCOM,
95
AW_H3_DEV_DRAMCTL,
96
AW_H3_DEV_DRAMPHY,
97
@@ -XXX,XX +XXX,XX @@ struct AwH3State {
98
AwH3SysCtrlState sysctrl;
99
AwSidState sid;
100
AwSdHostState mmc0;
101
+ AWI2CState i2c0;
102
AwSun8iEmacState emac;
103
AwRtcState rtc;
104
GICState gic;
105
diff --git a/include/hw/i2c/allwinner-i2c.h b/include/hw/i2c/allwinner-i2c.h
52
new file mode 100644
106
new file mode 100644
53
index XXXXXXX..XXXXXXX
107
index XXXXXXX..XXXXXXX
54
--- /dev/null
108
--- /dev/null
55
+++ b/include/hw/ssi/npcm7xx_fiu.h
109
+++ b/include/hw/i2c/allwinner-i2c.h
56
@@ -XXX,XX +XXX,XX @@
110
@@ -XXX,XX +XXX,XX @@
57
+/*
111
+/*
58
+ * Nuvoton NPCM7xx Flash Interface Unit (FIU)
112
+ * Allwinner I2C Bus Serial Interface registers definition
59
+ *
113
+ *
60
+ * Copyright 2020 Google LLC
114
+ * Copyright (C) 2022 Strahinja Jankovic. <strahinja.p.jankovic@gmail.com>
61
+ *
115
+ *
62
+ * This program is free software; you can redistribute it and/or modify it
116
+ * This file is derived from IMX I2C controller,
63
+ * under the terms of the GNU General Public License as published by the
117
+ * by Jean-Christophe DUBOIS .
64
+ * Free Software Foundation; either version 2 of the License, or
118
+ *
65
+ * (at your option) any later version.
119
+ * This program is free software; you can redistribute it and/or modify it
66
+ *
120
+ * under the terms of the GNU General Public License as published by the
67
+ * This program is distributed in the hope that it will be useful, but WITHOUT
121
+ * Free Software Foundation; either version 2 of the License, or
68
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
122
+ * (at your option) any later version.
69
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
123
+ *
70
+ * for more details.
124
+ * This program is distributed in the hope that it will be useful, but WITHOUT
125
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
126
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
127
+ * for more details.
128
+ *
129
+ * You should have received a copy of the GNU General Public License along
130
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
131
+ *
71
+ */
132
+ */
72
+#ifndef NPCM7XX_FIU_H
133
+
73
+#define NPCM7XX_FIU_H
134
+#ifndef ALLWINNER_I2C_H
74
+
135
+#define ALLWINNER_I2C_H
75
+#include "hw/ssi/ssi.h"
136
+
76
+#include "hw/sysbus.h"
137
+#include "hw/sysbus.h"
77
+
138
+#include "qom/object.h"
78
+/*
139
+
79
+ * Number of registers in our device state structure. Don't change this without
140
+#define TYPE_AW_I2C "allwinner.i2c"
80
+ * incrementing the version_id in the vmstate.
141
+OBJECT_DECLARE_SIMPLE_TYPE(AWI2CState, AW_I2C)
81
+ */
142
+
82
+#define NPCM7XX_FIU_NR_REGS (0x7c / sizeof(uint32_t))
143
+#define AW_I2C_MEM_SIZE 0x24
83
+
144
+
84
+typedef struct NPCM7xxFIUState NPCM7xxFIUState;
145
+struct AWI2CState {
85
+
146
+ /*< private >*/
86
+/**
147
+ SysBusDevice parent_obj;
87
+ * struct NPCM7xxFIUFlash - Per-chipselect flash controller state.
148
+
88
+ * @direct_access: Memory region for direct flash access.
149
+ /*< public >*/
89
+ * @fiu: Pointer to flash controller shared state.
150
+ MemoryRegion iomem;
90
+ */
151
+ I2CBus *bus;
91
+typedef struct NPCM7xxFIUFlash {
152
+ qemu_irq irq;
92
+ MemoryRegion direct_access;
153
+
93
+ NPCM7xxFIUState *fiu;
154
+ uint8_t addr;
94
+} NPCM7xxFIUFlash;
155
+ uint8_t xaddr;
95
+
156
+ uint8_t data;
96
+/**
157
+ uint8_t cntr;
97
+ * NPCM7xxFIUState - Device state for one Flash Interface Unit.
158
+ uint8_t stat;
98
+ * @parent: System bus device.
159
+ uint8_t ccr;
99
+ * @mmio: Memory region for register access.
160
+ uint8_t srst;
100
+ * @cs_count: Number of flash chips that may be connected to this module.
161
+ uint8_t efr;
101
+ * @active_cs: Currently active chip select, or -1 if no chip is selected.
162
+ uint8_t lcr;
102
+ * @cs_lines: GPIO lines that may be wired to flash chips.
103
+ * @flash: Array of @cs_count per-flash-chip state objects.
104
+ * @spi: The SPI bus mastered by this controller.
105
+ * @regs: Register contents.
106
+ *
107
+ * Each FIU has a shared bank of registers, and controls up to four chip
108
+ * selects. Each chip select has a dedicated memory region which may be used to
109
+ * read and write the flash connected to that chip select as if it were memory.
110
+ */
111
+struct NPCM7xxFIUState {
112
+ SysBusDevice parent;
113
+
114
+ MemoryRegion mmio;
115
+
116
+ int32_t cs_count;
117
+ int32_t active_cs;
118
+ qemu_irq *cs_lines;
119
+ NPCM7xxFIUFlash *flash;
120
+
121
+ SSIBus *spi;
122
+
123
+ uint32_t regs[NPCM7XX_FIU_NR_REGS];
124
+};
163
+};
125
+
164
+
126
+#define TYPE_NPCM7XX_FIU "npcm7xx-fiu"
165
+#endif /* ALLWINNER_I2C_H */
127
+#define NPCM7XX_FIU(obj) OBJECT_CHECK(NPCM7xxFIUState, (obj), TYPE_NPCM7XX_FIU)
166
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
128
+
167
index XXXXXXX..XXXXXXX 100644
129
+#endif /* NPCM7XX_FIU_H */
168
--- a/hw/arm/allwinner-a10.c
130
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
169
+++ b/hw/arm/allwinner-a10.c
131
index XXXXXXX..XXXXXXX 100644
170
@@ -XXX,XX +XXX,XX @@
132
--- a/hw/arm/npcm7xx.c
171
#define AW_A10_OHCI_BASE 0x01c14400
133
+++ b/hw/arm/npcm7xx.c
172
#define AW_A10_SATA_BASE 0x01c18000
134
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_uart_addr[] = {
173
#define AW_A10_RTC_BASE 0x01c20d00
135
0xf0004000,
174
+#define AW_A10_I2C0_BASE 0x01c2ac00
136
};
175
137
176
static void aw_a10_init(Object *obj)
138
+/* Direct memory-mapped access to SPI0 CS0-1. */
139
+static const hwaddr npcm7xx_fiu0_flash_addr[] = {
140
+ 0x80000000, /* CS0 */
141
+ 0x88000000, /* CS1 */
142
+};
143
+
144
+/* Direct memory-mapped access to SPI3 CS0-3. */
145
+static const hwaddr npcm7xx_fiu3_flash_addr[] = {
146
+ 0xa0000000, /* CS0 */
147
+ 0xa8000000, /* CS1 */
148
+ 0xb0000000, /* CS2 */
149
+ 0xb8000000, /* CS3 */
150
+};
151
+
152
+static const struct {
153
+ const char *name;
154
+ hwaddr regs_addr;
155
+ int cs_count;
156
+ const hwaddr *flash_addr;
157
+} npcm7xx_fiu[] = {
158
+ {
159
+ .name = "fiu0",
160
+ .regs_addr = 0xfb000000,
161
+ .cs_count = ARRAY_SIZE(npcm7xx_fiu0_flash_addr),
162
+ .flash_addr = npcm7xx_fiu0_flash_addr,
163
+ }, {
164
+ .name = "fiu3",
165
+ .regs_addr = 0xc0000000,
166
+ .cs_count = ARRAY_SIZE(npcm7xx_fiu3_flash_addr),
167
+ .flash_addr = npcm7xx_fiu3_flash_addr,
168
+ },
169
+};
170
+
171
static void npcm7xx_write_secondary_boot(ARMCPU *cpu,
172
const struct arm_boot_info *info)
173
{
177
{
174
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
178
@@ -XXX,XX +XXX,XX @@ static void aw_a10_init(Object *obj)
175
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
179
176
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
180
object_initialize_child(obj, "sata", &s->sata, TYPE_ALLWINNER_AHCI);
177
}
181
178
+
182
+ object_initialize_child(obj, "i2c0", &s->i2c0, TYPE_AW_I2C);
179
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
183
+
180
+ for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
184
if (machine_usb(current_machine)) {
181
+ object_initialize_child(obj, npcm7xx_fiu[i].name, &s->fiu[i],
185
int i;
182
+ TYPE_NPCM7XX_FIU);
186
183
+ }
187
@@ -XXX,XX +XXX,XX @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
188
/* RTC */
189
sysbus_realize(SYS_BUS_DEVICE(&s->rtc), &error_fatal);
190
sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->rtc), 0, AW_A10_RTC_BASE, 10);
191
+
192
+ /* I2C */
193
+ sysbus_realize(SYS_BUS_DEVICE(&s->i2c0), &error_fatal);
194
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c0), 0, AW_A10_I2C0_BASE);
195
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c0), 0, qdev_get_gpio_in(dev, 7));
184
}
196
}
185
197
186
static void npcm7xx_realize(DeviceState *dev, Error **errp)
198
static void aw_a10_class_init(ObjectClass *oc, void *data)
187
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
199
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
188
serial_hd(i), DEVICE_LITTLE_ENDIAN);
200
index XXXXXXX..XXXXXXX 100644
189
}
201
--- a/hw/arm/allwinner-h3.c
190
202
+++ b/hw/arm/allwinner-h3.c
191
+ /*
203
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
192
+ * Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
204
[AW_H3_DEV_UART1] = 0x01c28400,
193
+ * specified, but this is a programming error.
205
[AW_H3_DEV_UART2] = 0x01c28800,
194
+ */
206
[AW_H3_DEV_UART3] = 0x01c28c00,
195
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
207
+ [AW_H3_DEV_TWI0] = 0x01c2ac00,
196
+ for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
208
[AW_H3_DEV_EMAC] = 0x01c30000,
197
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->fiu[i]);
209
[AW_H3_DEV_DRAMCOM] = 0x01c62000,
198
+ int j;
210
[AW_H3_DEV_DRAMCTL] = 0x01c63000,
199
+
211
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
200
+ object_property_set_int(OBJECT(sbd), "cs-count",
212
{ "uart1", 0x01c28400, 1 * KiB },
201
+ npcm7xx_fiu[i].cs_count, &error_abort);
213
{ "uart2", 0x01c28800, 1 * KiB },
202
+ sysbus_realize(sbd, &error_abort);
214
{ "uart3", 0x01c28c00, 1 * KiB },
203
+
215
- { "twi0", 0x01c2ac00, 1 * KiB },
204
+ sysbus_mmio_map(sbd, 0, npcm7xx_fiu[i].regs_addr);
216
{ "twi1", 0x01c2b000, 1 * KiB },
205
+ for (j = 0; j < npcm7xx_fiu[i].cs_count; j++) {
217
{ "twi2", 0x01c2b400, 1 * KiB },
206
+ sysbus_mmio_map(sbd, j + 1, npcm7xx_fiu[i].flash_addr[j]);
218
{ "scr", 0x01c2c400, 1 * KiB },
207
+ }
219
@@ -XXX,XX +XXX,XX @@ enum {
208
+ }
220
AW_H3_GIC_SPI_UART1 = 1,
209
+
221
AW_H3_GIC_SPI_UART2 = 2,
210
/* RAM2 (SRAM) */
222
AW_H3_GIC_SPI_UART3 = 3,
211
memory_region_init_ram(&s->sram, OBJECT(dev), "ram2",
223
+ AW_H3_GIC_SPI_TWI0 = 6,
212
NPCM7XX_RAM2_SZ, &error_abort);
224
AW_H3_GIC_SPI_TIMER0 = 18,
213
diff --git a/hw/ssi/npcm7xx_fiu.c b/hw/ssi/npcm7xx_fiu.c
225
AW_H3_GIC_SPI_TIMER1 = 19,
226
AW_H3_GIC_SPI_MMC0 = 60,
227
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
228
"ram-size");
229
230
object_initialize_child(obj, "rtc", &s->rtc, TYPE_AW_RTC_SUN6I);
231
+
232
+ object_initialize_child(obj, "twi0", &s->i2c0, TYPE_AW_I2C);
233
}
234
235
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
236
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
237
sysbus_realize(SYS_BUS_DEVICE(&s->rtc), &error_fatal);
238
sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, s->memmap[AW_H3_DEV_RTC]);
239
240
+ /* I2C */
241
+ sysbus_realize(SYS_BUS_DEVICE(&s->i2c0), &error_fatal);
242
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c0), 0, s->memmap[AW_H3_DEV_TWI0]);
243
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c0), 0,
244
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_TWI0));
245
+
246
/* Unimplemented devices */
247
for (i = 0; i < ARRAY_SIZE(unimplemented); i++) {
248
create_unimplemented_device(unimplemented[i].device_name,
249
diff --git a/hw/i2c/allwinner-i2c.c b/hw/i2c/allwinner-i2c.c
214
new file mode 100644
250
new file mode 100644
215
index XXXXXXX..XXXXXXX
251
index XXXXXXX..XXXXXXX
216
--- /dev/null
252
--- /dev/null
217
+++ b/hw/ssi/npcm7xx_fiu.c
253
+++ b/hw/i2c/allwinner-i2c.c
218
@@ -XXX,XX +XXX,XX @@
254
@@ -XXX,XX +XXX,XX @@
219
+/*
255
+/*
220
+ * Nuvoton NPCM7xx Flash Interface Unit (FIU)
256
+ * Allwinner I2C Bus Serial Interface Emulation
221
+ *
257
+ *
222
+ * Copyright 2020 Google LLC
258
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
223
+ *
259
+ *
224
+ * This program is free software; you can redistribute it and/or modify it
260
+ * This file is derived from IMX I2C controller,
225
+ * under the terms of the GNU General Public License as published by the
261
+ * by Jean-Christophe DUBOIS .
226
+ * Free Software Foundation; either version 2 of the License, or
262
+ *
227
+ * (at your option) any later version.
263
+ * This program is free software; you can redistribute it and/or modify it
228
+ *
264
+ * under the terms of the GNU General Public License as published by the
229
+ * This program is distributed in the hope that it will be useful, but WITHOUT
265
+ * Free Software Foundation; either version 2 of the License, or
230
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
266
+ * (at your option) any later version.
231
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
267
+ *
232
+ * for more details.
268
+ * This program is distributed in the hope that it will be useful, but WITHOUT
269
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
270
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
271
+ * for more details.
272
+ *
273
+ * You should have received a copy of the GNU General Public License along
274
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
275
+ *
276
+ * SPDX-License-Identifier: MIT
233
+ */
277
+ */
234
+
278
+
235
+#include "qemu/osdep.h"
279
+#include "qemu/osdep.h"
236
+
280
+#include "hw/i2c/allwinner-i2c.h"
237
+#include "hw/irq.h"
281
+#include "hw/irq.h"
238
+#include "hw/qdev-properties.h"
239
+#include "hw/ssi/npcm7xx_fiu.h"
240
+#include "migration/vmstate.h"
282
+#include "migration/vmstate.h"
241
+#include "qapi/error.h"
283
+#include "hw/i2c/i2c.h"
242
+#include "qemu/error-report.h"
243
+#include "qemu/log.h"
284
+#include "qemu/log.h"
285
+#include "trace.h"
244
+#include "qemu/module.h"
286
+#include "qemu/module.h"
245
+#include "qemu/units.h"
287
+
246
+
288
+/* Allwinner I2C memory map */
247
+#include "trace.h"
289
+#define TWI_ADDR_REG 0x00 /* slave address register */
248
+
290
+#define TWI_XADDR_REG 0x04 /* extended slave address register */
249
+/* Up to 128 MiB of flash may be accessed directly as memory. */
291
+#define TWI_DATA_REG 0x08 /* data register */
250
+#define NPCM7XX_FIU_FLASH_WINDOW_SIZE (128 * MiB)
292
+#define TWI_CNTR_REG 0x0c /* control register */
251
+
293
+#define TWI_STAT_REG 0x10 /* status register */
252
+/* Each module has 4 KiB of register space. Only a fraction of it is used. */
294
+#define TWI_CCR_REG 0x14 /* clock control register */
253
+#define NPCM7XX_FIU_CTRL_REGS_SIZE (4 * KiB)
295
+#define TWI_SRST_REG 0x18 /* software reset register */
254
+
296
+#define TWI_EFR_REG 0x1c /* enhance feature register */
255
+/* 32-bit FIU register indices. */
297
+#define TWI_LCR_REG 0x20 /* line control register */
256
+enum NPCM7xxFIURegister {
298
+
257
+ NPCM7XX_FIU_DRD_CFG,
299
+/* Used only in slave mode, do not set */
258
+ NPCM7XX_FIU_DWR_CFG,
300
+#define TWI_ADDR_RESET 0
259
+ NPCM7XX_FIU_UMA_CFG,
301
+#define TWI_XADDR_RESET 0
260
+ NPCM7XX_FIU_UMA_CTS,
302
+
261
+ NPCM7XX_FIU_UMA_CMD,
303
+/* Data register */
262
+ NPCM7XX_FIU_UMA_ADDR,
304
+#define TWI_DATA_MASK 0xFF
263
+ NPCM7XX_FIU_PRT_CFG,
305
+#define TWI_DATA_RESET 0
264
+ NPCM7XX_FIU_UMA_DW0 = 0x0020 / sizeof(uint32_t),
306
+
265
+ NPCM7XX_FIU_UMA_DW1,
307
+/* Control register */
266
+ NPCM7XX_FIU_UMA_DW2,
308
+#define TWI_CNTR_INT_EN (1 << 7)
267
+ NPCM7XX_FIU_UMA_DW3,
309
+#define TWI_CNTR_BUS_EN (1 << 6)
268
+ NPCM7XX_FIU_UMA_DR0,
310
+#define TWI_CNTR_M_STA (1 << 5)
269
+ NPCM7XX_FIU_UMA_DR1,
311
+#define TWI_CNTR_M_STP (1 << 4)
270
+ NPCM7XX_FIU_UMA_DR2,
312
+#define TWI_CNTR_INT_FLAG (1 << 3)
271
+ NPCM7XX_FIU_UMA_DR3,
313
+#define TWI_CNTR_A_ACK (1 << 2)
272
+ NPCM7XX_FIU_PRT_CMD0,
314
+#define TWI_CNTR_MASK 0xFC
273
+ NPCM7XX_FIU_PRT_CMD1,
315
+#define TWI_CNTR_RESET 0
274
+ NPCM7XX_FIU_PRT_CMD2,
316
+
275
+ NPCM7XX_FIU_PRT_CMD3,
317
+/* Status register */
276
+ NPCM7XX_FIU_PRT_CMD4,
318
+#define TWI_STAT_MASK 0xF8
277
+ NPCM7XX_FIU_PRT_CMD5,
319
+#define TWI_STAT_RESET 0xF8
278
+ NPCM7XX_FIU_PRT_CMD6,
320
+
279
+ NPCM7XX_FIU_PRT_CMD7,
321
+/* Clock register */
280
+ NPCM7XX_FIU_PRT_CMD8,
322
+#define TWI_CCR_CLK_M_MASK 0x78
281
+ NPCM7XX_FIU_PRT_CMD9,
323
+#define TWI_CCR_CLK_N_MASK 0x07
282
+ NPCM7XX_FIU_CFG = 0x78 / sizeof(uint32_t),
324
+#define TWI_CCR_MASK 0x7F
283
+ NPCM7XX_FIU_REGS_END,
325
+#define TWI_CCR_RESET 0
284
+};
326
+
285
+
327
+/* Soft reset */
286
+/* FIU_{DRD,DWR,UMA,PTR}_CFG cannot be written when this bit is set. */
328
+#define TWI_SRST_MASK 0x01
287
+#define NPCM7XX_FIU_CFG_LCK BIT(31)
329
+#define TWI_SRST_RESET 0
288
+
330
+
289
+/* Direct Read configuration register fields. */
331
+/* Enhance feature */
290
+#define FIU_DRD_CFG_ADDSIZ(rv) extract32(rv, 16, 2)
332
+#define TWI_EFR_MASK 0x03
291
+#define FIU_ADDSIZ_3BYTES 0
333
+#define TWI_EFR_RESET 0
292
+#define FIU_ADDSIZ_4BYTES 1
334
+
293
+#define FIU_DRD_CFG_DBW(rv) extract32(rv, 12, 2)
335
+/* Line control */
294
+#define FIU_DRD_CFG_ACCTYPE(rv) extract32(rv, 8, 2)
336
+#define TWI_LCR_SCL_STATE (1 << 5)
295
+#define FIU_DRD_CFG_RDCMD(rv) extract32(rv, 0, 8)
337
+#define TWI_LCR_SDA_STATE (1 << 4)
296
+
338
+#define TWI_LCR_SCL_CTL (1 << 3)
297
+/* Direct Write configuration register fields. */
339
+#define TWI_LCR_SCL_CTL_EN (1 << 2)
298
+#define FIU_DWR_CFG_ADDSIZ(rv) extract32(rv, 16, 2)
340
+#define TWI_LCR_SDA_CTL (1 << 1)
299
+#define FIU_DWR_CFG_WRCMD(rv) extract32(rv, 0, 8)
341
+#define TWI_LCR_SDA_CTL_EN (1 << 0)
300
+
342
+#define TWI_LCR_MASK 0x3F
301
+/* User-Mode Access register fields. */
343
+#define TWI_LCR_RESET 0x3A
302
+
344
+
303
+/* Command Mode Lock and the bits protected by it. */
345
+/* Status value in STAT register is shifted by 3 bits */
304
+#define FIU_UMA_CFG_CMMLCK BIT(30)
346
+#define TWI_STAT_SHIFT 3
305
+#define FIU_UMA_CFG_CMMLCK_MASK 0x00000403
347
+#define STAT_FROM_STA(x) ((x) << TWI_STAT_SHIFT)
306
+
348
+#define STAT_TO_STA(x) ((x) >> TWI_STAT_SHIFT)
307
+#define FIU_UMA_CFG_RDATSIZ(rv) extract32(rv, 24, 5)
349
+
308
+#define FIU_UMA_CFG_DBSIZ(rv) extract32(rv, 21, 3)
350
+enum {
309
+#define FIU_UMA_CFG_WDATSIZ(rv) extract32(rv, 16, 5)
351
+ STAT_BUS_ERROR = 0,
310
+#define FIU_UMA_CFG_ADDSIZ(rv) extract32(rv, 11, 3)
352
+ /* Master mode */
311
+#define FIU_UMA_CFG_CMDSIZ(rv) extract32(rv, 10, 1)
353
+ STAT_M_STA_TX,
312
+#define FIU_UMA_CFG_DBPCK(rv) extract32(rv, 6, 2)
354
+ STAT_M_RSTA_TX,
313
+
355
+ STAT_M_ADDR_WR_ACK,
314
+#define FIU_UMA_CTS_RDYIE BIT(25)
356
+ STAT_M_ADDR_WR_NACK,
315
+#define FIU_UMA_CTS_RDYST BIT(24)
357
+ STAT_M_DATA_TX_ACK,
316
+#define FIU_UMA_CTS_SW_CS BIT(16)
358
+ STAT_M_DATA_TX_NACK,
317
+#define FIU_UMA_CTS_DEV_NUM(rv) extract32(rv, 8, 2)
359
+ STAT_M_ARB_LOST,
318
+#define FIU_UMA_CTS_EXEC_DONE BIT(0)
360
+ STAT_M_ADDR_RD_ACK,
319
+
361
+ STAT_M_ADDR_RD_NACK,
320
+/*
362
+ STAT_M_DATA_RX_ACK,
321
+ * Returns the index of flash in the fiu->flash array. This corresponds to the
363
+ STAT_M_DATA_RX_NACK,
322
+ * chip select ID of the flash.
364
+ /* Slave mode */
323
+ */
365
+ STAT_S_ADDR_WR_ACK,
324
+static int npcm7xx_fiu_cs_index(NPCM7xxFIUState *fiu, NPCM7xxFIUFlash *flash)
366
+ STAT_S_ARB_LOST_AW_ACK,
325
+{
367
+ STAT_S_GCA_ACK,
326
+ int index = flash - fiu->flash;
368
+ STAT_S_ARB_LOST_GCA_ACK,
327
+
369
+ STAT_S_DATA_RX_SA_ACK,
328
+ g_assert(index >= 0 && index < fiu->cs_count);
370
+ STAT_S_DATA_RX_SA_NACK,
329
+
371
+ STAT_S_DATA_RX_GCA_ACK,
330
+ return index;
372
+ STAT_S_DATA_RX_GCA_NACK,
331
+}
373
+ STAT_S_STP_RSTA,
332
+
374
+ STAT_S_ADDR_RD_ACK,
333
+/* Assert the chip select specified in the UMA Control/Status Register. */
375
+ STAT_S_ARB_LOST_AR_ACK,
334
+static void npcm7xx_fiu_select(NPCM7xxFIUState *s, int cs_id)
376
+ STAT_S_DATA_TX_ACK,
335
+{
377
+ STAT_S_DATA_TX_NACK,
336
+ trace_npcm7xx_fiu_select(DEVICE(s)->canonical_path, cs_id);
378
+ STAT_S_LB_TX_ACK,
337
+
379
+ /* Master mode, 10-bit */
338
+ if (cs_id < s->cs_count) {
380
+ STAT_M_2ND_ADDR_WR_ACK,
339
+ qemu_irq_lower(s->cs_lines[cs_id]);
381
+ STAT_M_2ND_ADDR_WR_NACK,
340
+ } else {
382
+ /* Idle */
341
+ qemu_log_mask(LOG_GUEST_ERROR,
383
+ STAT_IDLE = 0x1f
342
+ "%s: UMA to CS%d; this module has only %d chip selects",
384
+} TWI_STAT_STA;
343
+ DEVICE(s)->canonical_path, cs_id, s->cs_count);
385
+
344
+ cs_id = -1;
386
+static const char *allwinner_i2c_get_regname(unsigned offset)
387
+{
388
+ switch (offset) {
389
+ case TWI_ADDR_REG:
390
+ return "ADDR";
391
+ case TWI_XADDR_REG:
392
+ return "XADDR";
393
+ case TWI_DATA_REG:
394
+ return "DATA";
395
+ case TWI_CNTR_REG:
396
+ return "CNTR";
397
+ case TWI_STAT_REG:
398
+ return "STAT";
399
+ case TWI_CCR_REG:
400
+ return "CCR";
401
+ case TWI_SRST_REG:
402
+ return "SRST";
403
+ case TWI_EFR_REG:
404
+ return "EFR";
405
+ case TWI_LCR_REG:
406
+ return "LCR";
407
+ default:
408
+ return "[?]";
345
+ }
409
+ }
346
+
410
+}
347
+ s->active_cs = cs_id;
411
+
348
+}
412
+static inline bool allwinner_i2c_is_reset(AWI2CState *s)
349
+
413
+{
350
+/* Deassert the currently active chip select. */
414
+ return s->srst & TWI_SRST_MASK;
351
+static void npcm7xx_fiu_deselect(NPCM7xxFIUState *s)
415
+}
352
+{
416
+
353
+ if (s->active_cs < 0) {
417
+static inline bool allwinner_i2c_bus_is_enabled(AWI2CState *s)
354
+ return;
418
+{
419
+ return s->cntr & TWI_CNTR_BUS_EN;
420
+}
421
+
422
+static inline bool allwinner_i2c_interrupt_is_enabled(AWI2CState *s)
423
+{
424
+ return s->cntr & TWI_CNTR_INT_EN;
425
+}
426
+
427
+static void allwinner_i2c_reset_hold(Object *obj)
428
+{
429
+ AWI2CState *s = AW_I2C(obj);
430
+
431
+ if (STAT_TO_STA(s->stat) != STAT_IDLE) {
432
+ i2c_end_transfer(s->bus);
355
+ }
433
+ }
356
+
434
+
357
+ trace_npcm7xx_fiu_deselect(DEVICE(s)->canonical_path, s->active_cs);
435
+ s->addr = TWI_ADDR_RESET;
358
+
436
+ s->xaddr = TWI_XADDR_RESET;
359
+ qemu_irq_raise(s->cs_lines[s->active_cs]);
437
+ s->data = TWI_DATA_RESET;
360
+ s->active_cs = -1;
438
+ s->cntr = TWI_CNTR_RESET;
361
+}
439
+ s->stat = TWI_STAT_RESET;
362
+
440
+ s->ccr = TWI_CCR_RESET;
363
+/* Direct flash memory read handler. */
441
+ s->srst = TWI_SRST_RESET;
364
+static uint64_t npcm7xx_fiu_flash_read(void *opaque, hwaddr addr,
442
+ s->efr = TWI_EFR_RESET;
365
+ unsigned int size)
443
+ s->lcr = TWI_LCR_RESET;
366
+{
444
+}
367
+ NPCM7xxFIUFlash *f = opaque;
445
+
368
+ NPCM7xxFIUState *fiu = f->fiu;
446
+static inline void allwinner_i2c_raise_interrupt(AWI2CState *s)
369
+ uint64_t value = 0;
447
+{
370
+ uint32_t drd_cfg;
448
+ /*
371
+ int dummy_cycles;
449
+ * Raise an interrupt if the device is not reset and it is configured
372
+ int i;
450
+ * to generate some interrupts.
373
+
451
+ */
374
+ if (fiu->active_cs != -1) {
452
+ if (!allwinner_i2c_is_reset(s) && allwinner_i2c_bus_is_enabled(s)) {
375
+ qemu_log_mask(LOG_GUEST_ERROR,
453
+ if (STAT_TO_STA(s->stat) != STAT_IDLE) {
376
+ "%s: direct flash read with CS%d already active",
454
+ s->cntr |= TWI_CNTR_INT_FLAG;
377
+ DEVICE(fiu)->canonical_path, fiu->active_cs);
455
+ if (allwinner_i2c_interrupt_is_enabled(s)) {
378
+ }
456
+ qemu_irq_raise(s->irq);
379
+
457
+ }
380
+ npcm7xx_fiu_select(fiu, npcm7xx_fiu_cs_index(fiu, f));
381
+
382
+ drd_cfg = fiu->regs[NPCM7XX_FIU_DRD_CFG];
383
+ ssi_transfer(fiu->spi, FIU_DRD_CFG_RDCMD(drd_cfg));
384
+
385
+ switch (FIU_DRD_CFG_ADDSIZ(drd_cfg)) {
386
+ case FIU_ADDSIZ_4BYTES:
387
+ ssi_transfer(fiu->spi, extract32(addr, 24, 8));
388
+ /* fall through */
389
+ case FIU_ADDSIZ_3BYTES:
390
+ ssi_transfer(fiu->spi, extract32(addr, 16, 8));
391
+ ssi_transfer(fiu->spi, extract32(addr, 8, 8));
392
+ ssi_transfer(fiu->spi, extract32(addr, 0, 8));
393
+ break;
394
+
395
+ default:
396
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad address size %d\n",
397
+ DEVICE(fiu)->canonical_path, FIU_DRD_CFG_ADDSIZ(drd_cfg));
398
+ break;
399
+ }
400
+
401
+ /* Flash chip model expects one transfer per dummy bit, not byte */
402
+ dummy_cycles =
403
+ (FIU_DRD_CFG_DBW(drd_cfg) * 8) >> FIU_DRD_CFG_ACCTYPE(drd_cfg);
404
+ for (i = 0; i < dummy_cycles; i++) {
405
+ ssi_transfer(fiu->spi, 0);
406
+ }
407
+
408
+ for (i = 0; i < size; i++) {
409
+ value = deposit64(value, 8 * i, 8, ssi_transfer(fiu->spi, 0));
410
+ }
411
+
412
+ trace_npcm7xx_fiu_flash_read(DEVICE(fiu)->canonical_path, fiu->active_cs,
413
+ addr, size, value);
414
+
415
+ npcm7xx_fiu_deselect(fiu);
416
+
417
+ return value;
418
+}
419
+
420
+/* Direct flash memory write handler. */
421
+static void npcm7xx_fiu_flash_write(void *opaque, hwaddr addr, uint64_t v,
422
+ unsigned int size)
423
+{
424
+ NPCM7xxFIUFlash *f = opaque;
425
+ NPCM7xxFIUState *fiu = f->fiu;
426
+ uint32_t dwr_cfg;
427
+ int cs_id;
428
+ int i;
429
+
430
+ if (fiu->active_cs != -1) {
431
+ qemu_log_mask(LOG_GUEST_ERROR,
432
+ "%s: direct flash write with CS%d already active",
433
+ DEVICE(fiu)->canonical_path, fiu->active_cs);
434
+ }
435
+
436
+ cs_id = npcm7xx_fiu_cs_index(fiu, f);
437
+ trace_npcm7xx_fiu_flash_write(DEVICE(fiu)->canonical_path, cs_id, addr,
438
+ size, v);
439
+ npcm7xx_fiu_select(fiu, cs_id);
440
+
441
+ dwr_cfg = fiu->regs[NPCM7XX_FIU_DWR_CFG];
442
+ ssi_transfer(fiu->spi, FIU_DWR_CFG_WRCMD(dwr_cfg));
443
+
444
+ switch (FIU_DWR_CFG_ADDSIZ(dwr_cfg)) {
445
+ case FIU_ADDSIZ_4BYTES:
446
+ ssi_transfer(fiu->spi, extract32(addr, 24, 8));
447
+ /* fall through */
448
+ case FIU_ADDSIZ_3BYTES:
449
+ ssi_transfer(fiu->spi, extract32(addr, 16, 8));
450
+ ssi_transfer(fiu->spi, extract32(addr, 8, 8));
451
+ ssi_transfer(fiu->spi, extract32(addr, 0, 8));
452
+ break;
453
+
454
+ default:
455
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad address size %d\n",
456
+ DEVICE(fiu)->canonical_path, FIU_DWR_CFG_ADDSIZ(dwr_cfg));
457
+ break;
458
+ }
459
+
460
+ for (i = 0; i < size; i++) {
461
+ ssi_transfer(fiu->spi, extract64(v, i * 8, 8));
462
+ }
463
+
464
+ npcm7xx_fiu_deselect(fiu);
465
+}
466
+
467
+static const MemoryRegionOps npcm7xx_fiu_flash_ops = {
468
+ .read = npcm7xx_fiu_flash_read,
469
+ .write = npcm7xx_fiu_flash_write,
470
+ .endianness = DEVICE_LITTLE_ENDIAN,
471
+ .valid = {
472
+ .min_access_size = 1,
473
+ .max_access_size = 8,
474
+ .unaligned = true,
475
+ },
476
+};
477
+
478
+/* Control register read handler. */
479
+static uint64_t npcm7xx_fiu_ctrl_read(void *opaque, hwaddr addr,
480
+ unsigned int size)
481
+{
482
+ hwaddr reg = addr / sizeof(uint32_t);
483
+ NPCM7xxFIUState *s = opaque;
484
+ uint32_t value;
485
+
486
+ if (reg < NPCM7XX_FIU_NR_REGS) {
487
+ value = s->regs[reg];
488
+ } else {
489
+ qemu_log_mask(LOG_GUEST_ERROR,
490
+ "%s: read from invalid offset 0x%" PRIx64 "\n",
491
+ DEVICE(s)->canonical_path, addr);
492
+ value = 0;
493
+ }
494
+
495
+ trace_npcm7xx_fiu_ctrl_read(DEVICE(s)->canonical_path, addr, value);
496
+
497
+ return value;
498
+}
499
+
500
+/* Send the specified number of address bytes from the UMA address register. */
501
+static void send_address(SSIBus *spi, unsigned int addsiz, uint32_t addr)
502
+{
503
+ switch (addsiz) {
504
+ case 4:
505
+ ssi_transfer(spi, extract32(addr, 24, 8));
506
+ /* fall through */
507
+ case 3:
508
+ ssi_transfer(spi, extract32(addr, 16, 8));
509
+ /* fall through */
510
+ case 2:
511
+ ssi_transfer(spi, extract32(addr, 8, 8));
512
+ /* fall through */
513
+ case 1:
514
+ ssi_transfer(spi, extract32(addr, 0, 8));
515
+ /* fall through */
516
+ case 0:
517
+ break;
518
+ }
519
+}
520
+
521
+/* Send the number of dummy bits specified in the UMA config register. */
522
+static void send_dummy_bits(SSIBus *spi, uint32_t uma_cfg, uint32_t uma_cmd)
523
+{
524
+ unsigned int bits_per_clock = 1U << FIU_UMA_CFG_DBPCK(uma_cfg);
525
+ unsigned int i;
526
+
527
+ for (i = 0; i < FIU_UMA_CFG_DBSIZ(uma_cfg); i++) {
528
+ /* Use bytes 0 and 1 first, then keep repeating byte 2 */
529
+ unsigned int field = (i < 2) ? ((i + 1) * 8) : 24;
530
+ unsigned int j;
531
+
532
+ for (j = 0; j < 8; j += bits_per_clock) {
533
+ ssi_transfer(spi, extract32(uma_cmd, field + j, bits_per_clock));
534
+ }
458
+ }
535
+ }
459
+ }
536
+}
460
+}
537
+
461
+
538
+/* Perform a User-Mode Access transaction. */
462
+static uint64_t allwinner_i2c_read(void *opaque, hwaddr offset,
539
+static void npcm7xx_fiu_uma_transaction(NPCM7xxFIUState *s)
463
+ unsigned size)
540
+{
464
+{
541
+ uint32_t uma_cts = s->regs[NPCM7XX_FIU_UMA_CTS];
465
+ uint16_t value;
542
+ uint32_t uma_cfg;
466
+ AWI2CState *s = AW_I2C(opaque);
543
+ unsigned int i;
467
+
544
+
468
+ switch (offset) {
545
+ /* SW_CS means the CS is already forced low, so don't touch it. */
469
+ case TWI_ADDR_REG:
546
+ if (uma_cts & FIU_UMA_CTS_SW_CS) {
470
+ value = s->addr;
547
+ int cs_id = FIU_UMA_CTS_DEV_NUM(s->regs[NPCM7XX_FIU_UMA_CTS]);
471
+ break;
548
+ npcm7xx_fiu_select(s, cs_id);
472
+ case TWI_XADDR_REG:
473
+ value = s->xaddr;
474
+ break;
475
+ case TWI_DATA_REG:
476
+ if ((STAT_TO_STA(s->stat) == STAT_M_ADDR_RD_ACK) ||
477
+ (STAT_TO_STA(s->stat) == STAT_M_DATA_RX_ACK) ||
478
+ (STAT_TO_STA(s->stat) == STAT_M_DATA_RX_NACK)) {
479
+ /* Get the next byte */
480
+ s->data = i2c_recv(s->bus);
481
+
482
+ if (s->cntr & TWI_CNTR_A_ACK) {
483
+ s->stat = STAT_FROM_STA(STAT_M_DATA_RX_ACK);
484
+ } else {
485
+ s->stat = STAT_FROM_STA(STAT_M_DATA_RX_NACK);
486
+ }
487
+ allwinner_i2c_raise_interrupt(s);
488
+ }
489
+ value = s->data;
490
+ break;
491
+ case TWI_CNTR_REG:
492
+ value = s->cntr;
493
+ break;
494
+ case TWI_STAT_REG:
495
+ value = s->stat;
496
+ /*
497
+ * If polling when reading then change state to indicate data
498
+ * is available
499
+ */
500
+ if (STAT_TO_STA(s->stat) == STAT_M_ADDR_RD_ACK) {
501
+ if (s->cntr & TWI_CNTR_A_ACK) {
502
+ s->stat = STAT_FROM_STA(STAT_M_DATA_RX_ACK);
503
+ } else {
504
+ s->stat = STAT_FROM_STA(STAT_M_DATA_RX_NACK);
505
+ }
506
+ allwinner_i2c_raise_interrupt(s);
507
+ }
508
+ break;
509
+ case TWI_CCR_REG:
510
+ value = s->ccr;
511
+ break;
512
+ case TWI_SRST_REG:
513
+ value = s->srst;
514
+ break;
515
+ case TWI_EFR_REG:
516
+ value = s->efr;
517
+ break;
518
+ case TWI_LCR_REG:
519
+ value = s->lcr;
520
+ break;
521
+ default:
522
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
523
+ HWADDR_PRIx "\n", TYPE_AW_I2C, __func__, offset);
524
+ value = 0;
525
+ break;
549
+ }
526
+ }
550
+
527
+
551
+ /* Send command, if present. */
528
+ trace_allwinner_i2c_read(allwinner_i2c_get_regname(offset), offset, value);
552
+ uma_cfg = s->regs[NPCM7XX_FIU_UMA_CFG];
529
+
553
+ if (FIU_UMA_CFG_CMDSIZ(uma_cfg) > 0) {
530
+ return (uint64_t)value;
554
+ ssi_transfer(s->spi, extract32(s->regs[NPCM7XX_FIU_UMA_CMD], 0, 8));
531
+}
555
+ }
532
+
556
+
533
+static void allwinner_i2c_write(void *opaque, hwaddr offset,
557
+ /* Send address, if present. */
534
+ uint64_t value, unsigned size)
558
+ send_address(s->spi, FIU_UMA_CFG_ADDSIZ(uma_cfg),
535
+{
559
+ s->regs[NPCM7XX_FIU_UMA_ADDR]);
536
+ AWI2CState *s = AW_I2C(opaque);
560
+
537
+
561
+ /* Write data, if present. */
538
+ value &= 0xff;
562
+ for (i = 0; i < FIU_UMA_CFG_WDATSIZ(uma_cfg); i++) {
539
+
563
+ unsigned int reg =
540
+ trace_allwinner_i2c_write(allwinner_i2c_get_regname(offset), offset, value);
564
+ (i < 16) ? (NPCM7XX_FIU_UMA_DW0 + i / 4) : NPCM7XX_FIU_UMA_DW3;
541
+
565
+ unsigned int field = (i % 4) * 8;
542
+ switch (offset) {
566
+
543
+ case TWI_ADDR_REG:
567
+ ssi_transfer(s->spi, extract32(s->regs[reg], field, 8));
544
+ s->addr = (uint8_t)value;
568
+ }
545
+ break;
569
+
546
+ case TWI_XADDR_REG:
570
+ /* Send dummy bits, if present. */
547
+ s->xaddr = (uint8_t)value;
571
+ send_dummy_bits(s->spi, uma_cfg, s->regs[NPCM7XX_FIU_UMA_CMD]);
548
+ break;
572
+
549
+ case TWI_DATA_REG:
573
+ /* Read data, if present. */
550
+ /* If the device is in reset or not enabled, nothing to do */
574
+ for (i = 0; i < FIU_UMA_CFG_RDATSIZ(uma_cfg); i++) {
551
+ if (allwinner_i2c_is_reset(s) || (!allwinner_i2c_bus_is_enabled(s))) {
575
+ unsigned int reg = NPCM7XX_FIU_UMA_DR0 + i / 4;
552
+ break;
576
+ unsigned int field = (i % 4) * 8;
577
+ uint8_t c;
578
+
579
+ c = ssi_transfer(s->spi, 0);
580
+ if (reg <= NPCM7XX_FIU_UMA_DR3) {
581
+ s->regs[reg] = deposit32(s->regs[reg], field, 8, c);
582
+ }
553
+ }
583
+ }
554
+
584
+
555
+ s->data = value & TWI_DATA_MASK;
585
+ /* Again, don't touch CS if the user is forcing it low. */
556
+
586
+ if (uma_cts & FIU_UMA_CTS_SW_CS) {
557
+ switch (STAT_TO_STA(s->stat)) {
587
+ npcm7xx_fiu_deselect(s);
558
+ case STAT_M_STA_TX:
588
+ }
559
+ case STAT_M_RSTA_TX:
589
+
560
+ /* Send address */
590
+ /* RDYST means a command has completed since it was cleared. */
561
+ if (i2c_start_transfer(s->bus, extract32(s->data, 1, 7),
591
+ s->regs[NPCM7XX_FIU_UMA_CTS] |= FIU_UMA_CTS_RDYST;
562
+ extract32(s->data, 0, 1))) {
592
+ /* EXEC_DONE means Execute Command / Not Done, so clear it here. */
563
+ /* If non zero is returned, the address is not valid */
593
+ s->regs[NPCM7XX_FIU_UMA_CTS] &= ~FIU_UMA_CTS_EXEC_DONE;
564
+ s->stat = STAT_FROM_STA(STAT_M_ADDR_WR_NACK);
594
+}
565
+ } else {
595
+
566
+ /* Determine if read of write */
596
+/* Control register write handler. */
567
+ if (extract32(s->data, 0, 1)) {
597
+static void npcm7xx_fiu_ctrl_write(void *opaque, hwaddr addr, uint64_t v,
568
+ s->stat = STAT_FROM_STA(STAT_M_ADDR_RD_ACK);
598
+ unsigned int size)
569
+ } else {
599
+{
570
+ s->stat = STAT_FROM_STA(STAT_M_ADDR_WR_ACK);
600
+ hwaddr reg = addr / sizeof(uint32_t);
571
+ }
601
+ NPCM7xxFIUState *s = opaque;
572
+ allwinner_i2c_raise_interrupt(s);
602
+ uint32_t value = v;
573
+ }
603
+
574
+ break;
604
+ trace_npcm7xx_fiu_ctrl_write(DEVICE(s)->canonical_path, addr, value);
575
+ case STAT_M_ADDR_WR_ACK:
605
+
576
+ case STAT_M_DATA_TX_ACK:
606
+ switch (reg) {
577
+ if (i2c_send(s->bus, s->data)) {
607
+ case NPCM7XX_FIU_UMA_CFG:
578
+ /* If the target return non zero then end the transfer */
608
+ if (s->regs[reg] & FIU_UMA_CFG_CMMLCK) {
579
+ s->stat = STAT_FROM_STA(STAT_M_DATA_TX_NACK);
609
+ value &= ~FIU_UMA_CFG_CMMLCK_MASK;
580
+ i2c_end_transfer(s->bus);
610
+ value |= (s->regs[reg] & FIU_UMA_CFG_CMMLCK_MASK);
581
+ } else {
582
+ s->stat = STAT_FROM_STA(STAT_M_DATA_TX_ACK);
583
+ allwinner_i2c_raise_interrupt(s);
584
+ }
585
+ break;
586
+ default:
587
+ break;
611
+ }
588
+ }
612
+ /* fall through */
589
+ break;
613
+ case NPCM7XX_FIU_DRD_CFG:
590
+ case TWI_CNTR_REG:
614
+ case NPCM7XX_FIU_DWR_CFG:
591
+ if (!allwinner_i2c_is_reset(s)) {
615
+ if (s->regs[reg] & NPCM7XX_FIU_CFG_LCK) {
592
+ /* Do something only if not in software reset */
616
+ qemu_log_mask(LOG_GUEST_ERROR,
593
+ s->cntr = value & TWI_CNTR_MASK;
617
+ "%s: write to locked register @ 0x%" PRIx64 "\n",
594
+
618
+ DEVICE(s)->canonical_path, addr);
595
+ /* Check if start condition should be sent */
619
+ return;
596
+ if (s->cntr & TWI_CNTR_M_STA) {
620
+ }
597
+ /* Update status */
621
+ s->regs[reg] = value;
598
+ if (STAT_TO_STA(s->stat) == STAT_IDLE) {
622
+ break;
599
+ /* Send start condition */
623
+
600
+ s->stat = STAT_FROM_STA(STAT_M_STA_TX);
624
+ case NPCM7XX_FIU_UMA_CTS:
601
+ } else {
625
+ if (value & FIU_UMA_CTS_RDYST) {
602
+ /* Send repeated start condition */
626
+ value &= ~FIU_UMA_CTS_RDYST;
603
+ s->stat = STAT_FROM_STA(STAT_M_RSTA_TX);
627
+ } else {
604
+ }
628
+ value |= s->regs[reg] & FIU_UMA_CTS_RDYST;
605
+ /* Clear start condition */
629
+ }
606
+ s->cntr &= ~TWI_CNTR_M_STA;
630
+ if ((s->regs[reg] ^ value) & FIU_UMA_CTS_SW_CS) {
607
+ }
631
+ if (value & FIU_UMA_CTS_SW_CS) {
608
+ if (s->cntr & TWI_CNTR_M_STP) {
632
+ /*
609
+ /* Update status */
633
+ * Don't drop CS if there's a transfer in progress, or we're
610
+ i2c_end_transfer(s->bus);
634
+ * about to start one.
611
+ s->stat = STAT_FROM_STA(STAT_IDLE);
635
+ */
612
+ s->cntr &= ~TWI_CNTR_M_STP;
636
+ if (!((value | s->regs[reg]) & FIU_UMA_CTS_EXEC_DONE)) {
613
+ }
637
+ npcm7xx_fiu_deselect(s);
614
+ if ((s->cntr & TWI_CNTR_INT_FLAG) == 0) {
615
+ /* Interrupt flag cleared */
616
+ qemu_irq_lower(s->irq);
617
+ }
618
+ if ((s->cntr & TWI_CNTR_A_ACK) == 0) {
619
+ if (STAT_TO_STA(s->stat) == STAT_M_DATA_RX_ACK) {
620
+ s->stat = STAT_FROM_STA(STAT_M_DATA_RX_NACK);
638
+ }
621
+ }
639
+ } else {
622
+ } else {
640
+ int cs_id = FIU_UMA_CTS_DEV_NUM(s->regs[NPCM7XX_FIU_UMA_CTS]);
623
+ if (STAT_TO_STA(s->stat) == STAT_M_DATA_RX_NACK) {
641
+ npcm7xx_fiu_select(s, cs_id);
624
+ s->stat = STAT_FROM_STA(STAT_M_DATA_RX_ACK);
642
+ }
625
+ }
626
+ }
627
+ allwinner_i2c_raise_interrupt(s);
628
+
643
+ }
629
+ }
644
+ s->regs[reg] = value | (s->regs[reg] & FIU_UMA_CTS_EXEC_DONE);
630
+ break;
645
+ if (value & FIU_UMA_CTS_EXEC_DONE) {
631
+ case TWI_CCR_REG:
646
+ npcm7xx_fiu_uma_transaction(s);
632
+ s->ccr = value & TWI_CCR_MASK;
633
+ break;
634
+ case TWI_SRST_REG:
635
+ if (((value & TWI_SRST_MASK) == 0) && (s->srst & TWI_SRST_MASK)) {
636
+ /* Perform reset */
637
+ allwinner_i2c_reset_hold(OBJECT(s));
647
+ }
638
+ }
648
+ break;
639
+ s->srst = value & TWI_SRST_MASK;
649
+
640
+ break;
650
+ case NPCM7XX_FIU_UMA_DR0 ... NPCM7XX_FIU_UMA_DR3:
641
+ case TWI_EFR_REG:
651
+ qemu_log_mask(LOG_GUEST_ERROR,
642
+ s->efr = value & TWI_EFR_MASK;
652
+ "%s: write to read-only register @ 0x%" PRIx64 "\n",
643
+ break;
653
+ DEVICE(s)->canonical_path, addr);
644
+ case TWI_LCR_REG:
654
+ return;
645
+ s->lcr = value & TWI_LCR_MASK;
655
+
646
+ break;
656
+ case NPCM7XX_FIU_PRT_CFG:
657
+ case NPCM7XX_FIU_PRT_CMD0 ... NPCM7XX_FIU_PRT_CMD9:
658
+ qemu_log_mask(LOG_UNIMP, "%s: PRT is not implemented\n", __func__);
659
+ break;
660
+
661
+ case NPCM7XX_FIU_UMA_CMD:
662
+ case NPCM7XX_FIU_UMA_ADDR:
663
+ case NPCM7XX_FIU_UMA_DW0 ... NPCM7XX_FIU_UMA_DW3:
664
+ case NPCM7XX_FIU_CFG:
665
+ s->regs[reg] = value;
666
+ break;
667
+
668
+ default:
647
+ default:
669
+ qemu_log_mask(LOG_GUEST_ERROR,
648
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
670
+ "%s: write to invalid offset 0x%" PRIx64 "\n",
649
+ HWADDR_PRIx "\n", TYPE_AW_I2C, __func__, offset);
671
+ DEVICE(s)->canonical_path, addr);
650
+ break;
672
+ return;
673
+ }
651
+ }
674
+}
652
+}
675
+
653
+
676
+static const MemoryRegionOps npcm7xx_fiu_ctrl_ops = {
654
+static const MemoryRegionOps allwinner_i2c_ops = {
677
+ .read = npcm7xx_fiu_ctrl_read,
655
+ .read = allwinner_i2c_read,
678
+ .write = npcm7xx_fiu_ctrl_write,
656
+ .write = allwinner_i2c_write,
679
+ .endianness = DEVICE_LITTLE_ENDIAN,
657
+ .valid.min_access_size = 1,
680
+ .valid = {
658
+ .valid.max_access_size = 4,
681
+ .min_access_size = 4,
659
+ .endianness = DEVICE_NATIVE_ENDIAN,
682
+ .max_access_size = 4,
683
+ .unaligned = false,
684
+ },
685
+};
660
+};
686
+
661
+
687
+static void npcm7xx_fiu_enter_reset(Object *obj, ResetType type)
662
+static const VMStateDescription allwinner_i2c_vmstate = {
688
+{
663
+ .name = TYPE_AW_I2C,
689
+ NPCM7xxFIUState *s = NPCM7XX_FIU(obj);
664
+ .version_id = 1,
690
+
665
+ .minimum_version_id = 1,
691
+ trace_npcm7xx_fiu_enter_reset(DEVICE(obj)->canonical_path, type);
666
+ .fields = (VMStateField[]) {
692
+
667
+ VMSTATE_UINT8(addr, AWI2CState),
693
+ memset(s->regs, 0, sizeof(s->regs));
668
+ VMSTATE_UINT8(xaddr, AWI2CState),
694
+
669
+ VMSTATE_UINT8(data, AWI2CState),
695
+ s->regs[NPCM7XX_FIU_DRD_CFG] = 0x0300100b;
670
+ VMSTATE_UINT8(cntr, AWI2CState),
696
+ s->regs[NPCM7XX_FIU_DWR_CFG] = 0x03000002;
671
+ VMSTATE_UINT8(ccr, AWI2CState),
697
+ s->regs[NPCM7XX_FIU_UMA_CFG] = 0x00000400;
672
+ VMSTATE_UINT8(srst, AWI2CState),
698
+ s->regs[NPCM7XX_FIU_UMA_CTS] = 0x00010000;
673
+ VMSTATE_UINT8(efr, AWI2CState),
699
+ s->regs[NPCM7XX_FIU_UMA_CMD] = 0x0000000b;
674
+ VMSTATE_UINT8(lcr, AWI2CState),
700
+ s->regs[NPCM7XX_FIU_PRT_CFG] = 0x00000400;
675
+ VMSTATE_END_OF_LIST()
701
+ s->regs[NPCM7XX_FIU_CFG] = 0x0000000b;
702
+}
703
+
704
+static void npcm7xx_fiu_hold_reset(Object *obj)
705
+{
706
+ NPCM7xxFIUState *s = NPCM7XX_FIU(obj);
707
+ int i;
708
+
709
+ trace_npcm7xx_fiu_hold_reset(DEVICE(obj)->canonical_path);
710
+
711
+ for (i = 0; i < s->cs_count; i++) {
712
+ qemu_irq_raise(s->cs_lines[i]);
713
+ }
676
+ }
714
+}
715
+
716
+static void npcm7xx_fiu_realize(DeviceState *dev, Error **errp)
717
+{
718
+ NPCM7xxFIUState *s = NPCM7XX_FIU(dev);
719
+ SysBusDevice *sbd = &s->parent;
720
+ int i;
721
+
722
+ if (s->cs_count <= 0) {
723
+ error_setg(errp, "%s: %d chip selects specified, need at least one",
724
+ dev->canonical_path, s->cs_count);
725
+ return;
726
+ }
727
+
728
+ s->spi = ssi_create_bus(dev, "spi");
729
+ s->cs_lines = g_new0(qemu_irq, s->cs_count);
730
+ qdev_init_gpio_out_named(DEVICE(s), s->cs_lines, "cs", s->cs_count);
731
+ s->flash = g_new0(NPCM7xxFIUFlash, s->cs_count);
732
+
733
+ /*
734
+ * Register the control registers region first. It may be followed by one
735
+ * or more direct flash access regions.
736
+ */
737
+ memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_fiu_ctrl_ops, s, "ctrl",
738
+ NPCM7XX_FIU_CTRL_REGS_SIZE);
739
+ sysbus_init_mmio(sbd, &s->mmio);
740
+
741
+ for (i = 0; i < s->cs_count; i++) {
742
+ NPCM7xxFIUFlash *flash = &s->flash[i];
743
+ flash->fiu = s;
744
+ memory_region_init_io(&flash->direct_access, OBJECT(s),
745
+ &npcm7xx_fiu_flash_ops, &s->flash[i], "flash",
746
+ NPCM7XX_FIU_FLASH_WINDOW_SIZE);
747
+ sysbus_init_mmio(sbd, &flash->direct_access);
748
+ }
749
+}
750
+
751
+static const VMStateDescription vmstate_npcm7xx_fiu = {
752
+ .name = "npcm7xx-fiu",
753
+ .version_id = 0,
754
+ .minimum_version_id = 0,
755
+ .fields = (VMStateField[]) {
756
+ VMSTATE_INT32(active_cs, NPCM7xxFIUState),
757
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxFIUState, NPCM7XX_FIU_NR_REGS),
758
+ VMSTATE_END_OF_LIST(),
759
+ },
760
+};
677
+};
761
+
678
+
762
+static Property npcm7xx_fiu_properties[] = {
679
+static void allwinner_i2c_realize(DeviceState *dev, Error **errp)
763
+ DEFINE_PROP_INT32("cs-count", NPCM7xxFIUState, cs_count, 0),
680
+{
764
+ DEFINE_PROP_END_OF_LIST(),
681
+ AWI2CState *s = AW_I2C(dev);
682
+
683
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_i2c_ops, s,
684
+ TYPE_AW_I2C, AW_I2C_MEM_SIZE);
685
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
686
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
687
+ s->bus = i2c_init_bus(dev, "i2c");
688
+}
689
+
690
+static void allwinner_i2c_class_init(ObjectClass *klass, void *data)
691
+{
692
+ DeviceClass *dc = DEVICE_CLASS(klass);
693
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
694
+
695
+ rc->phases.hold = allwinner_i2c_reset_hold;
696
+ dc->vmsd = &allwinner_i2c_vmstate;
697
+ dc->realize = allwinner_i2c_realize;
698
+ dc->desc = "Allwinner I2C Controller";
699
+}
700
+
701
+static const TypeInfo allwinner_i2c_type_info = {
702
+ .name = TYPE_AW_I2C,
703
+ .parent = TYPE_SYS_BUS_DEVICE,
704
+ .instance_size = sizeof(AWI2CState),
705
+ .class_init = allwinner_i2c_class_init,
765
+};
706
+};
766
+
707
+
767
+static void npcm7xx_fiu_class_init(ObjectClass *klass, void *data)
708
+static void allwinner_i2c_register_types(void)
768
+{
709
+{
769
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
710
+ type_register_static(&allwinner_i2c_type_info);
770
+ DeviceClass *dc = DEVICE_CLASS(klass);
711
+}
771
+
712
+
772
+ QEMU_BUILD_BUG_ON(NPCM7XX_FIU_REGS_END > NPCM7XX_FIU_NR_REGS);
713
+type_init(allwinner_i2c_register_types)
773
+
774
+ dc->desc = "NPCM7xx Flash Interface Unit";
775
+ dc->realize = npcm7xx_fiu_realize;
776
+ dc->vmsd = &vmstate_npcm7xx_fiu;
777
+ rc->phases.enter = npcm7xx_fiu_enter_reset;
778
+ rc->phases.hold = npcm7xx_fiu_hold_reset;
779
+ device_class_set_props(dc, npcm7xx_fiu_properties);
780
+}
781
+
782
+static const TypeInfo npcm7xx_fiu_types[] = {
783
+ {
784
+ .name = TYPE_NPCM7XX_FIU,
785
+ .parent = TYPE_SYS_BUS_DEVICE,
786
+ .instance_size = sizeof(NPCM7xxFIUState),
787
+ .class_init = npcm7xx_fiu_class_init,
788
+ },
789
+};
790
+DEFINE_TYPES(npcm7xx_fiu_types);
791
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
714
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
792
index XXXXXXX..XXXXXXX 100644
715
index XXXXXXX..XXXXXXX 100644
793
--- a/hw/arm/Kconfig
716
--- a/hw/arm/Kconfig
794
+++ b/hw/arm/Kconfig
717
+++ b/hw/arm/Kconfig
795
@@ -XXX,XX +XXX,XX @@ config NPCM7XX
718
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10
719
select ALLWINNER_A10_CCM
720
select ALLWINNER_A10_DRAMC
721
select ALLWINNER_EMAC
722
+ select ALLWINNER_I2C
723
select SERIAL
724
select UNIMP
725
726
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_H3
727
bool
728
select ALLWINNER_A10_PIT
729
select ALLWINNER_SUN8I_EMAC
730
+ select ALLWINNER_I2C
731
select SERIAL
732
select ARM_TIMER
796
select ARM_GIC
733
select ARM_GIC
797
select PL310 # cache controller
734
diff --git a/hw/i2c/Kconfig b/hw/i2c/Kconfig
798
select SERIAL
735
index XXXXXXX..XXXXXXX 100644
799
+ select SSI
736
--- a/hw/i2c/Kconfig
800
select UNIMP
737
+++ b/hw/i2c/Kconfig
801
738
@@ -XXX,XX +XXX,XX @@ config MPC_I2C
802
config FSL_IMX25
739
bool
803
diff --git a/hw/ssi/meson.build b/hw/ssi/meson.build
740
select I2C
804
index XXXXXXX..XXXXXXX 100644
741
805
--- a/hw/ssi/meson.build
742
+config ALLWINNER_I2C
806
+++ b/hw/ssi/meson.build
743
+ bool
807
@@ -XXX,XX +XXX,XX @@
744
+ select I2C
808
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_smc.c'))
745
+
809
softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('mss-spi.c'))
746
config PCA954X
810
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_fiu.c'))
747
bool
811
softmmu_ss.add(when: 'CONFIG_PL022', if_true: files('pl022.c'))
748
select I2C
812
softmmu_ss.add(when: 'CONFIG_SSI', if_true: files('ssi.c'))
749
diff --git a/hw/i2c/meson.build b/hw/i2c/meson.build
813
softmmu_ss.add(when: 'CONFIG_STM32F2XX_SPI', if_true: files('stm32f2xx_spi.c'))
750
index XXXXXXX..XXXXXXX 100644
814
diff --git a/hw/ssi/trace-events b/hw/ssi/trace-events
751
--- a/hw/i2c/meson.build
815
index XXXXXXX..XXXXXXX 100644
752
+++ b/hw/i2c/meson.build
816
--- a/hw/ssi/trace-events
753
@@ -XXX,XX +XXX,XX @@ i2c_ss.add(when: 'CONFIG_BITBANG_I2C', if_true: files('bitbang_i2c.c'))
817
+++ b/hw/ssi/trace-events
754
i2c_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_i2c.c'))
818
@@ -XXX,XX +XXX,XX @@ aspeed_smc_dma_checksum(uint32_t addr, uint32_t data) "0x%08x: 0x%08x"
755
i2c_ss.add(when: 'CONFIG_IMX_I2C', if_true: files('imx_i2c.c'))
819
aspeed_smc_dma_rw(const char *dir, uint32_t flash_addr, uint32_t dram_addr, uint32_t size) "%s flash:@0x%08x dram:@0x%08x size:0x%08x"
756
i2c_ss.add(when: 'CONFIG_MPC_I2C', if_true: files('mpc_i2c.c'))
820
aspeed_smc_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
757
+i2c_ss.add(when: 'CONFIG_ALLWINNER_I2C', if_true: files('allwinner-i2c.c'))
821
aspeed_smc_flash_select(int cs, const char *prefix) "CS%d %sselect"
758
i2c_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('microbit_i2c.c'))
822
+
759
i2c_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_smbus.c'))
823
+# npcm7xx_fiu.c
760
i2c_ss.add(when: 'CONFIG_SMBUS_EEPROM', if_true: files('smbus_eeprom.c'))
824
+
761
diff --git a/hw/i2c/trace-events b/hw/i2c/trace-events
825
+npcm7xx_fiu_enter_reset(const char *id, int reset_type) "%s reset type: %d"
762
index XXXXXXX..XXXXXXX 100644
826
+npcm7xx_fiu_hold_reset(const char *id) "%s"
763
--- a/hw/i2c/trace-events
827
+npcm7xx_fiu_select(const char *id, int cs) "%s select CS%d"
764
+++ b/hw/i2c/trace-events
828
+npcm7xx_fiu_deselect(const char *id, int cs) "%s deselect CS%d"
765
@@ -XXX,XX +XXX,XX @@ i2c_send_async(uint8_t address, uint8_t data) "send_async(addr:0x%02x) data:0x%0
829
+npcm7xx_fiu_ctrl_read(const char *id, uint64_t addr, uint32_t data) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
766
i2c_recv(uint8_t address, uint8_t data) "recv(addr:0x%02x) data:0x%02x"
830
+npcm7xx_fiu_ctrl_write(const char *id, uint64_t addr, uint32_t data) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
767
i2c_ack(void) ""
831
+npcm7xx_fiu_flash_read(const char *id, int cs, uint64_t addr, unsigned int size, uint64_t value) "%s[%d] offset: 0x%08" PRIx64 " size: %u value: 0x%" PRIx64
768
832
+npcm7xx_fiu_flash_write(const char *id, int cs, uint64_t addr, unsigned int size, uint64_t value) "%s[%d] offset: 0x%08" PRIx64 " size: %u value: 0x%" PRIx64
769
+# allwinner_i2c.c
770
+
771
+allwinner_i2c_read(const char* reg_name, uint64_t offset, uint64_t value) "read %s [0x%" PRIx64 "]: -> 0x%" PRIx64
772
+allwinner_i2c_write(const char* reg_name, uint64_t offset, uint64_t value) "write %s [0x%" PRIx64 "]: <- 0x%" PRIx64
773
+
774
# aspeed_i2c.c
775
776
aspeed_i2c_bus_cmd(uint32_t cmd, const char *cmd_flags, uint32_t count, uint32_t intr_status) "handling cmd=0x%x %s count=%d intr=0x%x"
833
--
777
--
834
2.20.1
778
2.34.1
835
836
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
2
2
3
The Xilinx ZynqMP CAN controller is developed based on SocketCAN, QEMU CAN bus
3
This patch adds minimal support for AXP-209 PMU.
4
implementation. Bus connection and socketCAN connection for each CAN module
4
Most important is chip ID since U-Boot SPL expects version 0x1. Besides
5
can be set through command lines.
5
the chip ID register, reset values for two more registers used by A10
6
U-Boot SPL are covered.
6
7
7
Example for using single CAN:
8
Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
8
-object can-bus,id=canbus0 \
9
Message-id: 20221226220303.14420-5-strahinja.p.jankovic@gmail.com
9
-machine xlnx-zcu102.canbus0=canbus0 \
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0
11
12
Example for connecting both CAN to same virtual CAN on host machine:
13
-object can-bus,id=canbus0 -object can-bus,id=canbus1 \
14
-machine xlnx-zcu102.canbus0=canbus0 \
15
-machine xlnx-zcu102.canbus1=canbus1 \
16
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0 \
17
-object can-host-socketcan,id=socketcan1,if=vcan0,canbus=canbus1
18
19
To create virtual CAN on the host machine, please check the QEMU CAN docs:
20
https://github.com/qemu/qemu/blob/master/docs/can.txt
21
22
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
23
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
24
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
25
Message-id: 1597278668-339715-2-git-send-email-fnu.vikram@xilinx.com
26
[PMM: updated to meson build system]
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
---
12
---
29
include/hw/net/xlnx-zynqmp-can.h | 78 ++
13
hw/misc/axp209.c | 238 +++++++++++++++++++++++++++++++++++++++++++
30
hw/net/can/xlnx-zynqmp-can.c | 1165 ++++++++++++++++++++++++++++++
14
MAINTAINERS | 2 +
31
hw/net/can/meson.build | 1 +
15
hw/misc/Kconfig | 4 +
32
3 files changed, 1244 insertions(+)
16
hw/misc/meson.build | 1 +
33
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
17
hw/misc/trace-events | 5 +
34
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
18
5 files changed, 250 insertions(+)
19
create mode 100644 hw/misc/axp209.c
35
20
36
diff --git a/include/hw/net/xlnx-zynqmp-can.h b/include/hw/net/xlnx-zynqmp-can.h
21
diff --git a/hw/misc/axp209.c b/hw/misc/axp209.c
37
new file mode 100644
22
new file mode 100644
38
index XXXXXXX..XXXXXXX
23
index XXXXXXX..XXXXXXX
39
--- /dev/null
24
--- /dev/null
40
+++ b/include/hw/net/xlnx-zynqmp-can.h
25
+++ b/hw/misc/axp209.c
41
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@
42
+/*
27
+/*
43
+ * QEMU model of the Xilinx ZynqMP CAN controller.
28
+ * AXP-209 PMU Emulation
44
+ *
29
+ *
45
+ * Copyright (c) 2020 Xilinx Inc.
30
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
46
+ *
31
+ *
47
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
32
+ * Permission is hereby granted, free of charge, to any person obtaining a
48
+ *
33
+ * copy of this software and associated documentation files (the "Software"),
49
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
34
+ * to deal in the Software without restriction, including without limitation
50
+ * Pavel Pisa.
35
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
51
+ *
36
+ * and/or sell copies of the Software, and to permit persons to whom the
52
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
37
+ * Software is furnished to do so, subject to the following conditions:
53
+ * of this software and associated documentation files (the "Software"), to deal
54
+ * in the Software without restriction, including without limitation the rights
55
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
56
+ * copies of the Software, and to permit persons to whom the Software is
57
+ * furnished to do so, subject to the following conditions:
58
+ *
38
+ *
59
+ * The above copyright notice and this permission notice shall be included in
39
+ * The above copyright notice and this permission notice shall be included in
60
+ * all copies or substantial portions of the Software.
40
+ * all copies or substantial portions of the Software.
61
+ *
41
+ *
62
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
64
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
44
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
65
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
66
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
67
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
47
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
68
+ * THE SOFTWARE.
48
+ * DEALINGS IN THE SOFTWARE.
49
+ *
50
+ * SPDX-License-Identifier: MIT
69
+ */
51
+ */
70
+
52
+
71
+#ifndef XLNX_ZYNQMP_CAN_H
53
+#include "qemu/osdep.h"
72
+#define XLNX_ZYNQMP_CAN_H
54
+#include "qemu/log.h"
73
+
55
+#include "trace.h"
74
+#include "hw/register.h"
56
+#include "hw/i2c/i2c.h"
75
+#include "net/can_emu.h"
57
+#include "migration/vmstate.h"
76
+#include "net/can_host.h"
58
+
77
+#include "qemu/fifo32.h"
59
+#define TYPE_AXP209_PMU "axp209_pmu"
78
+#include "hw/ptimer.h"
60
+
79
+#include "hw/qdev-clock.h"
61
+#define AXP209(obj) \
80
+
62
+ OBJECT_CHECK(AXP209I2CState, (obj), TYPE_AXP209_PMU)
81
+#define TYPE_XLNX_ZYNQMP_CAN "xlnx.zynqmp-can"
63
+
82
+
64
+/* registers */
83
+#define XLNX_ZYNQMP_CAN(obj) \
65
+enum {
84
+ OBJECT_CHECK(XlnxZynqMPCANState, (obj), TYPE_XLNX_ZYNQMP_CAN)
66
+ REG_POWER_STATUS = 0x0u,
85
+
67
+ REG_OPERATING_MODE,
86
+#define MAX_CAN_CTRLS 2
68
+ REG_OTG_VBUS_STATUS,
87
+#define XLNX_ZYNQMP_CAN_R_MAX (0x84 / 4)
69
+ REG_CHIP_VERSION,
88
+#define MAILBOX_CAPACITY 64
70
+ REG_DATA_CACHE_0,
89
+#define CAN_TIMER_MAX 0XFFFFUL
71
+ REG_DATA_CACHE_1,
90
+#define CAN_DEFAULT_CLOCK (24 * 1000 * 1000)
72
+ REG_DATA_CACHE_2,
91
+
73
+ REG_DATA_CACHE_3,
92
+/* Each CAN_FRAME will have 4 * 32bit size. */
74
+ REG_DATA_CACHE_4,
93
+#define CAN_FRAME_SIZE 4
75
+ REG_DATA_CACHE_5,
94
+#define RXFIFO_SIZE (MAILBOX_CAPACITY * CAN_FRAME_SIZE)
76
+ REG_DATA_CACHE_6,
95
+
77
+ REG_DATA_CACHE_7,
96
+typedef struct XlnxZynqMPCANState {
78
+ REG_DATA_CACHE_8,
97
+ SysBusDevice parent_obj;
79
+ REG_DATA_CACHE_9,
98
+ MemoryRegion iomem;
80
+ REG_DATA_CACHE_A,
99
+
81
+ REG_DATA_CACHE_B,
100
+ qemu_irq irq;
82
+ REG_POWER_OUTPUT_CTRL = 0x12u,
101
+
83
+ REG_DC_DC2_OUT_V_CTRL = 0x23u,
102
+ CanBusClientState bus_client;
84
+ REG_DC_DC2_DVS_CTRL = 0x25u,
103
+ CanBusState *canbus;
85
+ REG_DC_DC3_OUT_V_CTRL = 0x27u,
104
+
86
+ REG_LDO2_4_OUT_V_CTRL,
105
+ struct {
87
+ REG_LDO3_OUT_V_CTRL,
106
+ uint32_t ext_clk_freq;
88
+ REG_VBUS_CH_MGMT = 0x30u,
107
+ } cfg;
89
+ REG_SHUTDOWN_V_CTRL,
108
+
90
+ REG_SHUTDOWN_CTRL,
109
+ RegisterInfo reg_info[XLNX_ZYNQMP_CAN_R_MAX];
91
+ REG_CHARGE_CTRL_1,
110
+ uint32_t regs[XLNX_ZYNQMP_CAN_R_MAX];
92
+ REG_CHARGE_CTRL_2,
111
+
93
+ REG_SPARE_CHARGE_CTRL,
112
+ Fifo32 rx_fifo;
94
+ REG_PEK_KEY_CTRL,
113
+ Fifo32 tx_fifo;
95
+ REG_DC_DC_FREQ_SET,
114
+ Fifo32 txhpb_fifo;
96
+ REG_CHR_TEMP_TH_SET,
115
+
97
+ REG_CHR_HIGH_TEMP_TH_CTRL,
116
+ ptimer_state *can_timer;
98
+ REG_IPSOUT_WARN_L1,
117
+} XlnxZynqMPCANState;
99
+ REG_IPSOUT_WARN_L2,
118
+
100
+ REG_DISCHR_TEMP_TH_SET,
119
+#endif
101
+ REG_DISCHR_HIGH_TEMP_TH_CTRL,
120
diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
102
+ REG_IRQ_BANK_1_CTRL = 0x40u,
121
new file mode 100644
103
+ REG_IRQ_BANK_2_CTRL,
122
index XXXXXXX..XXXXXXX
104
+ REG_IRQ_BANK_3_CTRL,
123
--- /dev/null
105
+ REG_IRQ_BANK_4_CTRL,
124
+++ b/hw/net/can/xlnx-zynqmp-can.c
106
+ REG_IRQ_BANK_5_CTRL,
125
@@ -XXX,XX +XXX,XX @@
107
+ REG_IRQ_BANK_1_STAT = 0x48u,
108
+ REG_IRQ_BANK_2_STAT,
109
+ REG_IRQ_BANK_3_STAT,
110
+ REG_IRQ_BANK_4_STAT,
111
+ REG_IRQ_BANK_5_STAT,
112
+ REG_ADC_ACIN_V_H = 0x56u,
113
+ REG_ADC_ACIN_V_L,
114
+ REG_ADC_ACIN_CURR_H,
115
+ REG_ADC_ACIN_CURR_L,
116
+ REG_ADC_VBUS_V_H,
117
+ REG_ADC_VBUS_V_L,
118
+ REG_ADC_VBUS_CURR_H,
119
+ REG_ADC_VBUS_CURR_L,
120
+ REG_ADC_INT_TEMP_H,
121
+ REG_ADC_INT_TEMP_L,
122
+ REG_ADC_TEMP_SENS_V_H = 0x62u,
123
+ REG_ADC_TEMP_SENS_V_L,
124
+ REG_ADC_BAT_V_H = 0x78u,
125
+ REG_ADC_BAT_V_L,
126
+ REG_ADC_BAT_DISCHR_CURR_H,
127
+ REG_ADC_BAT_DISCHR_CURR_L,
128
+ REG_ADC_BAT_CHR_CURR_H,
129
+ REG_ADC_BAT_CHR_CURR_L,
130
+ REG_ADC_IPSOUT_V_H,
131
+ REG_ADC_IPSOUT_V_L,
132
+ REG_DC_DC_MOD_SEL = 0x80u,
133
+ REG_ADC_EN_1,
134
+ REG_ADC_EN_2,
135
+ REG_ADC_SR_CTRL,
136
+ REG_ADC_IN_RANGE,
137
+ REG_GPIO1_ADC_IRQ_RISING_TH,
138
+ REG_GPIO1_ADC_IRQ_FALLING_TH,
139
+ REG_TIMER_CTRL = 0x8au,
140
+ REG_VBUS_CTRL_MON_SRP,
141
+ REG_OVER_TEMP_SHUTDOWN = 0x8fu,
142
+ REG_GPIO0_FEAT_SET,
143
+ REG_GPIO_OUT_HIGH_SET,
144
+ REG_GPIO1_FEAT_SET,
145
+ REG_GPIO2_FEAT_SET,
146
+ REG_GPIO_SIG_STATE_SET_MON,
147
+ REG_GPIO3_SET,
148
+ REG_COULOMB_CNTR_CTRL = 0xb8u,
149
+ REG_POWER_MEAS_RES,
150
+ NR_REGS
151
+};
152
+
153
+#define AXP209_CHIP_VERSION_ID (0x01)
154
+#define AXP209_DC_DC2_OUT_V_CTRL_RESET (0x16)
155
+#define AXP209_IRQ_BANK_1_CTRL_RESET (0xd8)
156
+
157
+/* A simple I2C slave which returns values of ID or CNT register. */
158
+typedef struct AXP209I2CState {
159
+ /*< private >*/
160
+ I2CSlave i2c;
161
+ /*< public >*/
162
+ uint8_t regs[NR_REGS]; /* peripheral registers */
163
+ uint8_t ptr; /* current register index */
164
+ uint8_t count; /* counter used for tx/rx */
165
+} AXP209I2CState;
166
+
167
+/* Reset all counters and load ID register */
168
+static void axp209_reset_enter(Object *obj, ResetType type)
169
+{
170
+ AXP209I2CState *s = AXP209(obj);
171
+
172
+ memset(s->regs, 0, NR_REGS);
173
+ s->ptr = 0;
174
+ s->count = 0;
175
+ s->regs[REG_CHIP_VERSION] = AXP209_CHIP_VERSION_ID;
176
+ s->regs[REG_DC_DC2_OUT_V_CTRL] = AXP209_DC_DC2_OUT_V_CTRL_RESET;
177
+ s->regs[REG_IRQ_BANK_1_CTRL] = AXP209_IRQ_BANK_1_CTRL_RESET;
178
+}
179
+
180
+/* Handle events from master. */
181
+static int axp209_event(I2CSlave *i2c, enum i2c_event event)
182
+{
183
+ AXP209I2CState *s = AXP209(i2c);
184
+
185
+ s->count = 0;
186
+
187
+ return 0;
188
+}
189
+
190
+/* Called when master requests read */
191
+static uint8_t axp209_rx(I2CSlave *i2c)
192
+{
193
+ AXP209I2CState *s = AXP209(i2c);
194
+ uint8_t ret = 0xff;
195
+
196
+ if (s->ptr < NR_REGS) {
197
+ ret = s->regs[s->ptr++];
198
+ }
199
+
200
+ trace_axp209_rx(s->ptr - 1, ret);
201
+
202
+ return ret;
203
+}
204
+
126
+/*
205
+/*
127
+ * QEMU model of the Xilinx ZynqMP CAN controller.
206
+ * Called when master sends write.
128
+ * This implementation is based on the following datasheet:
207
+ * Update ptr with byte 0, then perform write with second byte.
129
+ * https://www.xilinx.com/support/documentation/user_guides/ug1085-zynq-ultrascale-trm.pdf
130
+ *
131
+ * Copyright (c) 2020 Xilinx Inc.
132
+ *
133
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
134
+ *
135
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
136
+ * Pavel Pisa
137
+ *
138
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
139
+ * of this software and associated documentation files (the "Software"), to deal
140
+ * in the Software without restriction, including without limitation the rights
141
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
142
+ * copies of the Software, and to permit persons to whom the Software is
143
+ * furnished to do so, subject to the following conditions:
144
+ *
145
+ * The above copyright notice and this permission notice shall be included in
146
+ * all copies or substantial portions of the Software.
147
+ *
148
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
149
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
150
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
151
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
152
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
153
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
154
+ * THE SOFTWARE.
155
+ */
208
+ */
156
+
209
+static int axp209_tx(I2CSlave *i2c, uint8_t data)
157
+#include "qemu/osdep.h"
210
+{
158
+#include "hw/sysbus.h"
211
+ AXP209I2CState *s = AXP209(i2c);
159
+#include "hw/register.h"
212
+
160
+#include "hw/irq.h"
213
+ if (s->count == 0) {
161
+#include "qapi/error.h"
214
+ /* Store register address */
162
+#include "qemu/bitops.h"
215
+ s->ptr = data;
163
+#include "qemu/log.h"
216
+ s->count++;
164
+#include "qemu/cutils.h"
217
+ trace_axp209_select(data);
165
+#include "sysemu/sysemu.h"
166
+#include "migration/vmstate.h"
167
+#include "hw/qdev-properties.h"
168
+#include "net/can_emu.h"
169
+#include "net/can_host.h"
170
+#include "qemu/event_notifier.h"
171
+#include "qom/object_interfaces.h"
172
+#include "hw/net/xlnx-zynqmp-can.h"
173
+
174
+#ifndef XLNX_ZYNQMP_CAN_ERR_DEBUG
175
+#define XLNX_ZYNQMP_CAN_ERR_DEBUG 0
176
+#endif
177
+
178
+#define DB_PRINT(dev, ...) do { \
179
+ if (XLNX_ZYNQMP_CAN_ERR_DEBUG) { \
180
+ g_autofree char *path = object_get_canonical_path(OBJECT(dev)); \
181
+ qemu_log("%s: %s", path, ## __VA_ARGS__); \
182
+ } \
183
+} while (0)
184
+
185
+#define MAX_DLC 8
186
+#undef ERROR
187
+
188
+REG32(SOFTWARE_RESET_REGISTER, 0x0)
189
+ FIELD(SOFTWARE_RESET_REGISTER, CEN, 1, 1)
190
+ FIELD(SOFTWARE_RESET_REGISTER, SRST, 0, 1)
191
+REG32(MODE_SELECT_REGISTER, 0x4)
192
+ FIELD(MODE_SELECT_REGISTER, SNOOP, 2, 1)
193
+ FIELD(MODE_SELECT_REGISTER, LBACK, 1, 1)
194
+ FIELD(MODE_SELECT_REGISTER, SLEEP, 0, 1)
195
+REG32(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, 0x8)
196
+ FIELD(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, BRP, 0, 8)
197
+REG32(ARBITRATION_PHASE_BIT_TIMING_REGISTER, 0xc)
198
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, SJW, 7, 2)
199
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS2, 4, 3)
200
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS1, 0, 4)
201
+REG32(ERROR_COUNTER_REGISTER, 0x10)
202
+ FIELD(ERROR_COUNTER_REGISTER, REC, 8, 8)
203
+ FIELD(ERROR_COUNTER_REGISTER, TEC, 0, 8)
204
+REG32(ERROR_STATUS_REGISTER, 0x14)
205
+ FIELD(ERROR_STATUS_REGISTER, ACKER, 4, 1)
206
+ FIELD(ERROR_STATUS_REGISTER, BERR, 3, 1)
207
+ FIELD(ERROR_STATUS_REGISTER, STER, 2, 1)
208
+ FIELD(ERROR_STATUS_REGISTER, FMER, 1, 1)
209
+ FIELD(ERROR_STATUS_REGISTER, CRCER, 0, 1)
210
+REG32(STATUS_REGISTER, 0x18)
211
+ FIELD(STATUS_REGISTER, SNOOP, 12, 1)
212
+ FIELD(STATUS_REGISTER, ACFBSY, 11, 1)
213
+ FIELD(STATUS_REGISTER, TXFLL, 10, 1)
214
+ FIELD(STATUS_REGISTER, TXBFLL, 9, 1)
215
+ FIELD(STATUS_REGISTER, ESTAT, 7, 2)
216
+ FIELD(STATUS_REGISTER, ERRWRN, 6, 1)
217
+ FIELD(STATUS_REGISTER, BBSY, 5, 1)
218
+ FIELD(STATUS_REGISTER, BIDLE, 4, 1)
219
+ FIELD(STATUS_REGISTER, NORMAL, 3, 1)
220
+ FIELD(STATUS_REGISTER, SLEEP, 2, 1)
221
+ FIELD(STATUS_REGISTER, LBACK, 1, 1)
222
+ FIELD(STATUS_REGISTER, CONFIG, 0, 1)
223
+REG32(INTERRUPT_STATUS_REGISTER, 0x1c)
224
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFEMP, 14, 1)
225
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFWMEMP, 13, 1)
226
+ FIELD(INTERRUPT_STATUS_REGISTER, RXFWMFLL, 12, 1)
227
+ FIELD(INTERRUPT_STATUS_REGISTER, WKUP, 11, 1)
228
+ FIELD(INTERRUPT_STATUS_REGISTER, SLP, 10, 1)
229
+ FIELD(INTERRUPT_STATUS_REGISTER, BSOFF, 9, 1)
230
+ FIELD(INTERRUPT_STATUS_REGISTER, ERROR, 8, 1)
231
+ FIELD(INTERRUPT_STATUS_REGISTER, RXNEMP, 7, 1)
232
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOFLW, 6, 1)
233
+ FIELD(INTERRUPT_STATUS_REGISTER, RXUFLW, 5, 1)
234
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOK, 4, 1)
235
+ FIELD(INTERRUPT_STATUS_REGISTER, TXBFLL, 3, 1)
236
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFLL, 2, 1)
237
+ FIELD(INTERRUPT_STATUS_REGISTER, TXOK, 1, 1)
238
+ FIELD(INTERRUPT_STATUS_REGISTER, ARBLST, 0, 1)
239
+REG32(INTERRUPT_ENABLE_REGISTER, 0x20)
240
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFEMP, 14, 1)
241
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFWMEMP, 13, 1)
242
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXFWMFLL, 12, 1)
243
+ FIELD(INTERRUPT_ENABLE_REGISTER, EWKUP, 11, 1)
244
+ FIELD(INTERRUPT_ENABLE_REGISTER, ESLP, 10, 1)
245
+ FIELD(INTERRUPT_ENABLE_REGISTER, EBSOFF, 9, 1)
246
+ FIELD(INTERRUPT_ENABLE_REGISTER, EERROR, 8, 1)
247
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXNEMP, 7, 1)
248
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOFLW, 6, 1)
249
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXUFLW, 5, 1)
250
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOK, 4, 1)
251
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXBFLL, 3, 1)
252
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFLL, 2, 1)
253
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXOK, 1, 1)
254
+ FIELD(INTERRUPT_ENABLE_REGISTER, EARBLST, 0, 1)
255
+REG32(INTERRUPT_CLEAR_REGISTER, 0x24)
256
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFEMP, 14, 1)
257
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFWMEMP, 13, 1)
258
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXFWMFLL, 12, 1)
259
+ FIELD(INTERRUPT_CLEAR_REGISTER, CWKUP, 11, 1)
260
+ FIELD(INTERRUPT_CLEAR_REGISTER, CSLP, 10, 1)
261
+ FIELD(INTERRUPT_CLEAR_REGISTER, CBSOFF, 9, 1)
262
+ FIELD(INTERRUPT_CLEAR_REGISTER, CERROR, 8, 1)
263
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXNEMP, 7, 1)
264
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOFLW, 6, 1)
265
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXUFLW, 5, 1)
266
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOK, 4, 1)
267
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXBFLL, 3, 1)
268
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFLL, 2, 1)
269
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXOK, 1, 1)
270
+ FIELD(INTERRUPT_CLEAR_REGISTER, CARBLST, 0, 1)
271
+REG32(TIMESTAMP_REGISTER, 0x28)
272
+ FIELD(TIMESTAMP_REGISTER, CTS, 0, 1)
273
+REG32(WIR, 0x2c)
274
+ FIELD(WIR, EW, 8, 8)
275
+ FIELD(WIR, FW, 0, 8)
276
+REG32(TXFIFO_ID, 0x30)
277
+ FIELD(TXFIFO_ID, IDH, 21, 11)
278
+ FIELD(TXFIFO_ID, SRRRTR, 20, 1)
279
+ FIELD(TXFIFO_ID, IDE, 19, 1)
280
+ FIELD(TXFIFO_ID, IDL, 1, 18)
281
+ FIELD(TXFIFO_ID, RTR, 0, 1)
282
+REG32(TXFIFO_DLC, 0x34)
283
+ FIELD(TXFIFO_DLC, DLC, 28, 4)
284
+REG32(TXFIFO_DATA1, 0x38)
285
+ FIELD(TXFIFO_DATA1, DB0, 24, 8)
286
+ FIELD(TXFIFO_DATA1, DB1, 16, 8)
287
+ FIELD(TXFIFO_DATA1, DB2, 8, 8)
288
+ FIELD(TXFIFO_DATA1, DB3, 0, 8)
289
+REG32(TXFIFO_DATA2, 0x3c)
290
+ FIELD(TXFIFO_DATA2, DB4, 24, 8)
291
+ FIELD(TXFIFO_DATA2, DB5, 16, 8)
292
+ FIELD(TXFIFO_DATA2, DB6, 8, 8)
293
+ FIELD(TXFIFO_DATA2, DB7, 0, 8)
294
+REG32(TXHPB_ID, 0x40)
295
+ FIELD(TXHPB_ID, IDH, 21, 11)
296
+ FIELD(TXHPB_ID, SRRRTR, 20, 1)
297
+ FIELD(TXHPB_ID, IDE, 19, 1)
298
+ FIELD(TXHPB_ID, IDL, 1, 18)
299
+ FIELD(TXHPB_ID, RTR, 0, 1)
300
+REG32(TXHPB_DLC, 0x44)
301
+ FIELD(TXHPB_DLC, DLC, 28, 4)
302
+REG32(TXHPB_DATA1, 0x48)
303
+ FIELD(TXHPB_DATA1, DB0, 24, 8)
304
+ FIELD(TXHPB_DATA1, DB1, 16, 8)
305
+ FIELD(TXHPB_DATA1, DB2, 8, 8)
306
+ FIELD(TXHPB_DATA1, DB3, 0, 8)
307
+REG32(TXHPB_DATA2, 0x4c)
308
+ FIELD(TXHPB_DATA2, DB4, 24, 8)
309
+ FIELD(TXHPB_DATA2, DB5, 16, 8)
310
+ FIELD(TXHPB_DATA2, DB6, 8, 8)
311
+ FIELD(TXHPB_DATA2, DB7, 0, 8)
312
+REG32(RXFIFO_ID, 0x50)
313
+ FIELD(RXFIFO_ID, IDH, 21, 11)
314
+ FIELD(RXFIFO_ID, SRRRTR, 20, 1)
315
+ FIELD(RXFIFO_ID, IDE, 19, 1)
316
+ FIELD(RXFIFO_ID, IDL, 1, 18)
317
+ FIELD(RXFIFO_ID, RTR, 0, 1)
318
+REG32(RXFIFO_DLC, 0x54)
319
+ FIELD(RXFIFO_DLC, DLC, 28, 4)
320
+ FIELD(RXFIFO_DLC, RXT, 0, 16)
321
+REG32(RXFIFO_DATA1, 0x58)
322
+ FIELD(RXFIFO_DATA1, DB0, 24, 8)
323
+ FIELD(RXFIFO_DATA1, DB1, 16, 8)
324
+ FIELD(RXFIFO_DATA1, DB2, 8, 8)
325
+ FIELD(RXFIFO_DATA1, DB3, 0, 8)
326
+REG32(RXFIFO_DATA2, 0x5c)
327
+ FIELD(RXFIFO_DATA2, DB4, 24, 8)
328
+ FIELD(RXFIFO_DATA2, DB5, 16, 8)
329
+ FIELD(RXFIFO_DATA2, DB6, 8, 8)
330
+ FIELD(RXFIFO_DATA2, DB7, 0, 8)
331
+REG32(AFR, 0x60)
332
+ FIELD(AFR, UAF4, 3, 1)
333
+ FIELD(AFR, UAF3, 2, 1)
334
+ FIELD(AFR, UAF2, 1, 1)
335
+ FIELD(AFR, UAF1, 0, 1)
336
+REG32(AFMR1, 0x64)
337
+ FIELD(AFMR1, AMIDH, 21, 11)
338
+ FIELD(AFMR1, AMSRR, 20, 1)
339
+ FIELD(AFMR1, AMIDE, 19, 1)
340
+ FIELD(AFMR1, AMIDL, 1, 18)
341
+ FIELD(AFMR1, AMRTR, 0, 1)
342
+REG32(AFIR1, 0x68)
343
+ FIELD(AFIR1, AIIDH, 21, 11)
344
+ FIELD(AFIR1, AISRR, 20, 1)
345
+ FIELD(AFIR1, AIIDE, 19, 1)
346
+ FIELD(AFIR1, AIIDL, 1, 18)
347
+ FIELD(AFIR1, AIRTR, 0, 1)
348
+REG32(AFMR2, 0x6c)
349
+ FIELD(AFMR2, AMIDH, 21, 11)
350
+ FIELD(AFMR2, AMSRR, 20, 1)
351
+ FIELD(AFMR2, AMIDE, 19, 1)
352
+ FIELD(AFMR2, AMIDL, 1, 18)
353
+ FIELD(AFMR2, AMRTR, 0, 1)
354
+REG32(AFIR2, 0x70)
355
+ FIELD(AFIR2, AIIDH, 21, 11)
356
+ FIELD(AFIR2, AISRR, 20, 1)
357
+ FIELD(AFIR2, AIIDE, 19, 1)
358
+ FIELD(AFIR2, AIIDL, 1, 18)
359
+ FIELD(AFIR2, AIRTR, 0, 1)
360
+REG32(AFMR3, 0x74)
361
+ FIELD(AFMR3, AMIDH, 21, 11)
362
+ FIELD(AFMR3, AMSRR, 20, 1)
363
+ FIELD(AFMR3, AMIDE, 19, 1)
364
+ FIELD(AFMR3, AMIDL, 1, 18)
365
+ FIELD(AFMR3, AMRTR, 0, 1)
366
+REG32(AFIR3, 0x78)
367
+ FIELD(AFIR3, AIIDH, 21, 11)
368
+ FIELD(AFIR3, AISRR, 20, 1)
369
+ FIELD(AFIR3, AIIDE, 19, 1)
370
+ FIELD(AFIR3, AIIDL, 1, 18)
371
+ FIELD(AFIR3, AIRTR, 0, 1)
372
+REG32(AFMR4, 0x7c)
373
+ FIELD(AFMR4, AMIDH, 21, 11)
374
+ FIELD(AFMR4, AMSRR, 20, 1)
375
+ FIELD(AFMR4, AMIDE, 19, 1)
376
+ FIELD(AFMR4, AMIDL, 1, 18)
377
+ FIELD(AFMR4, AMRTR, 0, 1)
378
+REG32(AFIR4, 0x80)
379
+ FIELD(AFIR4, AIIDH, 21, 11)
380
+ FIELD(AFIR4, AISRR, 20, 1)
381
+ FIELD(AFIR4, AIIDE, 19, 1)
382
+ FIELD(AFIR4, AIIDL, 1, 18)
383
+ FIELD(AFIR4, AIRTR, 0, 1)
384
+
385
+static void can_update_irq(XlnxZynqMPCANState *s)
386
+{
387
+ uint32_t irq;
388
+
389
+ /* Watermark register interrupts. */
390
+ if ((fifo32_num_free(&s->tx_fifo) / CAN_FRAME_SIZE) >
391
+ ARRAY_FIELD_EX32(s->regs, WIR, EW)) {
392
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFWMEMP, 1);
393
+ }
394
+
395
+ if ((fifo32_num_used(&s->rx_fifo) / CAN_FRAME_SIZE) >
396
+ ARRAY_FIELD_EX32(s->regs, WIR, FW)) {
397
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL, 1);
398
+ }
399
+
400
+ /* RX Interrupts. */
401
+ if (fifo32_num_used(&s->rx_fifo) >= CAN_FRAME_SIZE) {
402
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXNEMP, 1);
403
+ }
404
+
405
+ /* TX interrupts. */
406
+ if (fifo32_is_empty(&s->tx_fifo)) {
407
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFEMP, 1);
408
+ }
409
+
410
+ if (fifo32_is_full(&s->tx_fifo)) {
411
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFLL, 1);
412
+ }
413
+
414
+ if (fifo32_is_full(&s->txhpb_fifo)) {
415
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXBFLL, 1);
416
+ }
417
+
418
+ irq = s->regs[R_INTERRUPT_STATUS_REGISTER];
419
+ irq &= s->regs[R_INTERRUPT_ENABLE_REGISTER];
420
+
421
+ qemu_set_irq(s->irq, irq);
422
+}
423
+
424
+static void can_ier_post_write(RegisterInfo *reg, uint64_t val64)
425
+{
426
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
427
+
428
+ can_update_irq(s);
429
+}
430
+
431
+static uint64_t can_icr_pre_write(RegisterInfo *reg, uint64_t val64)
432
+{
433
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
434
+ uint32_t val = val64;
435
+
436
+ s->regs[R_INTERRUPT_STATUS_REGISTER] &= ~val;
437
+ can_update_irq(s);
438
+
439
+ return 0;
440
+}
441
+
442
+static void can_config_reset(XlnxZynqMPCANState *s)
443
+{
444
+ /* Reset all the configuration registers. */
445
+ register_reset(&s->reg_info[R_SOFTWARE_RESET_REGISTER]);
446
+ register_reset(&s->reg_info[R_MODE_SELECT_REGISTER]);
447
+ register_reset(
448
+ &s->reg_info[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER]);
449
+ register_reset(&s->reg_info[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER]);
450
+ register_reset(&s->reg_info[R_STATUS_REGISTER]);
451
+ register_reset(&s->reg_info[R_INTERRUPT_STATUS_REGISTER]);
452
+ register_reset(&s->reg_info[R_INTERRUPT_ENABLE_REGISTER]);
453
+ register_reset(&s->reg_info[R_INTERRUPT_CLEAR_REGISTER]);
454
+ register_reset(&s->reg_info[R_WIR]);
455
+}
456
+
457
+static void can_config_mode(XlnxZynqMPCANState *s)
458
+{
459
+ register_reset(&s->reg_info[R_ERROR_COUNTER_REGISTER]);
460
+ register_reset(&s->reg_info[R_ERROR_STATUS_REGISTER]);
461
+
462
+ /* Put XlnxZynqMPCAN in configuration mode. */
463
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 1);
464
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP, 0);
465
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP, 0);
466
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, BSOFF, 0);
467
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ERROR, 0);
468
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 0);
469
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 0);
470
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 0);
471
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ARBLST, 0);
472
+
473
+ can_update_irq(s);
474
+}
475
+
476
+static void update_status_register_mode_bits(XlnxZynqMPCANState *s)
477
+{
478
+ bool sleep_status = ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP);
479
+ bool sleep_mode = ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP);
480
+ /* Wake up interrupt bit. */
481
+ bool wakeup_irq_val = sleep_status && (sleep_mode == 0);
482
+ /* Sleep interrupt bit. */
483
+ bool sleep_irq_val = sleep_mode && (sleep_status == 0);
484
+
485
+ /* Clear previous core mode status bits. */
486
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 0);
487
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 0);
488
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 0);
489
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 0);
490
+
491
+ /* set current mode bit and generate irqs accordingly. */
492
+ if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, LBACK)) {
493
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 1);
494
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP)) {
495
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 1);
496
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP,
497
+ sleep_irq_val);
498
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SNOOP)) {
499
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 1);
500
+ } else {
218
+ } else {
501
+ /*
219
+ trace_axp209_tx(s->ptr, data);
502
+ * If all bits are zero then XlnxZynqMPCAN is set in normal mode.
220
+ if (s->ptr == REG_DC_DC2_OUT_V_CTRL) {
503
+ */
221
+ s->regs[s->ptr++] = data;
504
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 1);
505
+ /* Set wakeup interrupt bit. */
506
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP,
507
+ wakeup_irq_val);
508
+ }
509
+
510
+ can_update_irq(s);
511
+}
512
+
513
+static void can_exit_sleep_mode(XlnxZynqMPCANState *s)
514
+{
515
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, 0);
516
+ update_status_register_mode_bits(s);
517
+}
518
+
519
+static void generate_frame(qemu_can_frame *frame, uint32_t *data)
520
+{
521
+ frame->can_id = data[0];
522
+ frame->can_dlc = FIELD_EX32(data[1], TXFIFO_DLC, DLC);
523
+
524
+ frame->data[0] = FIELD_EX32(data[2], TXFIFO_DATA1, DB3);
525
+ frame->data[1] = FIELD_EX32(data[2], TXFIFO_DATA1, DB2);
526
+ frame->data[2] = FIELD_EX32(data[2], TXFIFO_DATA1, DB1);
527
+ frame->data[3] = FIELD_EX32(data[2], TXFIFO_DATA1, DB0);
528
+
529
+ frame->data[4] = FIELD_EX32(data[3], TXFIFO_DATA2, DB7);
530
+ frame->data[5] = FIELD_EX32(data[3], TXFIFO_DATA2, DB6);
531
+ frame->data[6] = FIELD_EX32(data[3], TXFIFO_DATA2, DB5);
532
+ frame->data[7] = FIELD_EX32(data[3], TXFIFO_DATA2, DB4);
533
+}
534
+
535
+static bool tx_ready_check(XlnxZynqMPCANState *s)
536
+{
537
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
538
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
539
+
540
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data while"
541
+ " data while controller is in reset mode.\n",
542
+ path);
543
+ return false;
544
+ }
545
+
546
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
547
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
548
+
549
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
550
+ " data while controller is in configuration mode. Reset"
551
+ " the core so operations can start fresh.\n",
552
+ path);
553
+ return false;
554
+ }
555
+
556
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
557
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
558
+
559
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
560
+ " data while controller is in SNOOP MODE.\n",
561
+ path);
562
+ return false;
563
+ }
564
+
565
+ return true;
566
+}
567
+
568
+static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
569
+{
570
+ qemu_can_frame frame;
571
+ uint32_t data[CAN_FRAME_SIZE];
572
+ int i;
573
+ bool can_tx = tx_ready_check(s);
574
+
575
+ if (can_tx) {
576
+ while (!fifo32_is_empty(fifo)) {
577
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
578
+ data[i] = fifo32_pop(fifo);
579
+ }
580
+
581
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
582
+ /*
583
+ * Controller is in loopback. In Loopback mode, the CAN core
584
+ * transmits a recessive bitstream on to the XlnxZynqMPCAN Bus.
585
+ * Any message transmitted is looped back to the RX line and
586
+ * acknowledged. The XlnxZynqMPCAN core receives any message
587
+ * that it transmits.
588
+ */
589
+ if (fifo32_is_full(&s->rx_fifo)) {
590
+ DB_PRINT(s, "Loopback: RX FIFO is full."
591
+ " TX FIFO will be flushed.\n");
592
+
593
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER,
594
+ RXOFLW, 1);
595
+ } else {
596
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
597
+ fifo32_push(&s->rx_fifo, data[i]);
598
+ }
599
+
600
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER,
601
+ RXOK, 1);
602
+ }
603
+ } else {
604
+ /* Normal mode Tx. */
605
+ generate_frame(&frame, data);
606
+
607
+ can_bus_client_send(&s->bus_client, &frame, 1);
608
+ }
609
+ }
610
+
611
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 1);
612
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, TXBFLL, 0);
613
+
614
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) {
615
+ can_exit_sleep_mode(s);
616
+ }
617
+ } else {
618
+ DB_PRINT(s, "Not enabled for data transfer.\n");
619
+ }
620
+
621
+ can_update_irq(s);
622
+}
623
+
624
+static uint64_t can_srr_pre_write(RegisterInfo *reg, uint64_t val64)
625
+{
626
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
627
+ uint32_t val = val64;
628
+
629
+ ARRAY_FIELD_DP32(s->regs, SOFTWARE_RESET_REGISTER, CEN,
630
+ FIELD_EX32(val, SOFTWARE_RESET_REGISTER, CEN));
631
+
632
+ if (FIELD_EX32(val, SOFTWARE_RESET_REGISTER, SRST)) {
633
+ DB_PRINT(s, "Resetting controller.\n");
634
+
635
+ /* First, core will do software reset then will enter in config mode. */
636
+ can_config_reset(s);
637
+ }
638
+
639
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
640
+ can_config_mode(s);
641
+ } else {
642
+ /*
643
+ * Leave config mode. Now XlnxZynqMPCAN core will enter normal,
644
+ * sleep, snoop or loopback mode depending upon LBACK, SLEEP, SNOOP
645
+ * register states.
646
+ */
647
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 0);
648
+
649
+ ptimer_transaction_begin(s->can_timer);
650
+ ptimer_set_count(s->can_timer, 0);
651
+ ptimer_transaction_commit(s->can_timer);
652
+
653
+ /* XlnxZynqMPCAN is out of config mode. It will send pending data. */
654
+ transfer_fifo(s, &s->txhpb_fifo);
655
+ transfer_fifo(s, &s->tx_fifo);
656
+ }
657
+
658
+ update_status_register_mode_bits(s);
659
+
660
+ return s->regs[R_SOFTWARE_RESET_REGISTER];
661
+}
662
+
663
+static uint64_t can_msr_pre_write(RegisterInfo *reg, uint64_t val64)
664
+{
665
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
666
+ uint32_t val = val64;
667
+ uint8_t multi_mode;
668
+
669
+ /*
670
+ * Multiple mode set check. This is done to make sure user doesn't set
671
+ * multiple modes.
672
+ */
673
+ multi_mode = FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK) +
674
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP) +
675
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP);
676
+
677
+ if (multi_mode > 1) {
678
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
679
+
680
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to config"
681
+ " several modes simultaneously. One mode will be selected"
682
+ " according to their priority: LBACK > SLEEP > SNOOP.\n",
683
+ path);
684
+ }
685
+
686
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
687
+ /* We are in configuration mode, any mode can be selected. */
688
+ s->regs[R_MODE_SELECT_REGISTER] = val;
689
+ } else {
690
+ bool sleep_mode_bit = FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP);
691
+
692
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, sleep_mode_bit);
693
+
694
+ if (FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK)) {
695
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
696
+
697
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
698
+ " LBACK mode without setting CEN bit as 0.\n",
699
+ path);
700
+ } else if (FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP)) {
701
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
702
+
703
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
704
+ " SNOOP mode without setting CEN bit as 0.\n",
705
+ path);
706
+ }
707
+
708
+ update_status_register_mode_bits(s);
709
+ }
710
+
711
+ return s->regs[R_MODE_SELECT_REGISTER];
712
+}
713
+
714
+static uint64_t can_brpr_pre_write(RegisterInfo *reg, uint64_t val64)
715
+{
716
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
717
+ uint32_t val = val64;
718
+
719
+ /* Only allow writes when in config mode. */
720
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
721
+ val = s->regs[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER];
722
+ }
723
+
724
+ return val;
725
+}
726
+
727
+static uint64_t can_btr_pre_write(RegisterInfo *reg, uint64_t val64)
728
+{
729
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
730
+ uint32_t val = val64;
731
+
732
+ /* Only allow writes when in config mode. */
733
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
734
+ val = s->regs[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER];
735
+ }
736
+
737
+ return val;
738
+}
739
+
740
+static uint64_t can_tcr_pre_write(RegisterInfo *reg, uint64_t val64)
741
+{
742
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
743
+ uint32_t val = val64;
744
+
745
+ if (FIELD_EX32(val, TIMESTAMP_REGISTER, CTS)) {
746
+ ptimer_transaction_begin(s->can_timer);
747
+ ptimer_set_count(s->can_timer, 0);
748
+ ptimer_transaction_commit(s->can_timer);
749
+ }
750
+
751
+ return 0;
752
+}
753
+
754
+static void update_rx_fifo(XlnxZynqMPCANState *s, const qemu_can_frame *frame)
755
+{
756
+ bool filter_pass = false;
757
+ uint16_t timestamp = 0;
758
+
759
+ /* If no filter is enabled. Message will be stored in FIFO. */
760
+ if (!((ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) |
761
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) |
762
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) |
763
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)))) {
764
+ filter_pass = true;
765
+ }
766
+
767
+ /*
768
+ * Messages that pass any of the acceptance filters will be stored in
769
+ * the RX FIFO.
770
+ */
771
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) {
772
+ uint32_t id_masked = s->regs[R_AFMR1] & frame->can_id;
773
+ uint32_t filter_id_masked = s->regs[R_AFMR1] & s->regs[R_AFIR1];
774
+
775
+ if (filter_id_masked == id_masked) {
776
+ filter_pass = true;
777
+ }
222
+ }
778
+ }
223
+ }
779
+
224
+
780
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) {
225
+ return 0;
781
+ uint32_t id_masked = s->regs[R_AFMR2] & frame->can_id;
226
+}
782
+ uint32_t filter_id_masked = s->regs[R_AFMR2] & s->regs[R_AFIR2];
227
+
783
+
228
+static const VMStateDescription vmstate_axp209 = {
784
+ if (filter_id_masked == id_masked) {
229
+ .name = TYPE_AXP209_PMU,
785
+ filter_pass = true;
230
+ .version_id = 1,
786
+ }
231
+ .fields = (VMStateField[]) {
787
+ }
232
+ VMSTATE_UINT8_ARRAY(regs, AXP209I2CState, NR_REGS),
788
+
233
+ VMSTATE_UINT8(count, AXP209I2CState),
789
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) {
234
+ VMSTATE_UINT8(ptr, AXP209I2CState),
790
+ uint32_t id_masked = s->regs[R_AFMR3] & frame->can_id;
235
+ VMSTATE_END_OF_LIST()
791
+ uint32_t filter_id_masked = s->regs[R_AFMR3] & s->regs[R_AFIR3];
792
+
793
+ if (filter_id_masked == id_masked) {
794
+ filter_pass = true;
795
+ }
796
+ }
797
+
798
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
799
+ uint32_t id_masked = s->regs[R_AFMR4] & frame->can_id;
800
+ uint32_t filter_id_masked = s->regs[R_AFMR4] & s->regs[R_AFIR4];
801
+
802
+ if (filter_id_masked == id_masked) {
803
+ filter_pass = true;
804
+ }
805
+ }
806
+
807
+ /* Store the message in fifo if it passed through any of the filters. */
808
+ if (filter_pass && frame->can_dlc <= MAX_DLC) {
809
+
810
+ if (fifo32_is_full(&s->rx_fifo)) {
811
+ DB_PRINT(s, "RX FIFO is full.\n");
812
+
813
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
814
+ } else {
815
+ timestamp = CAN_TIMER_MAX - ptimer_get_count(s->can_timer);
816
+
817
+ fifo32_push(&s->rx_fifo, frame->can_id);
818
+
819
+ fifo32_push(&s->rx_fifo, deposit32(0, R_RXFIFO_DLC_DLC_SHIFT,
820
+ R_RXFIFO_DLC_DLC_LENGTH,
821
+ frame->can_dlc) |
822
+ deposit32(0, R_RXFIFO_DLC_RXT_SHIFT,
823
+ R_RXFIFO_DLC_RXT_LENGTH,
824
+ timestamp));
825
+
826
+ /* First 32 bit of the data. */
827
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA1_DB3_SHIFT,
828
+ R_TXFIFO_DATA1_DB3_LENGTH,
829
+ frame->data[0]) |
830
+ deposit32(0, R_TXFIFO_DATA1_DB2_SHIFT,
831
+ R_TXFIFO_DATA1_DB2_LENGTH,
832
+ frame->data[1]) |
833
+ deposit32(0, R_TXFIFO_DATA1_DB1_SHIFT,
834
+ R_TXFIFO_DATA1_DB1_LENGTH,
835
+ frame->data[2]) |
836
+ deposit32(0, R_TXFIFO_DATA1_DB0_SHIFT,
837
+ R_TXFIFO_DATA1_DB0_LENGTH,
838
+ frame->data[3]));
839
+ /* Last 32 bit of the data. */
840
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA2_DB7_SHIFT,
841
+ R_TXFIFO_DATA2_DB7_LENGTH,
842
+ frame->data[4]) |
843
+ deposit32(0, R_TXFIFO_DATA2_DB6_SHIFT,
844
+ R_TXFIFO_DATA2_DB6_LENGTH,
845
+ frame->data[5]) |
846
+ deposit32(0, R_TXFIFO_DATA2_DB5_SHIFT,
847
+ R_TXFIFO_DATA2_DB5_LENGTH,
848
+ frame->data[6]) |
849
+ deposit32(0, R_TXFIFO_DATA2_DB4_SHIFT,
850
+ R_TXFIFO_DATA2_DB4_LENGTH,
851
+ frame->data[7]));
852
+
853
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
854
+ }
855
+
856
+ can_update_irq(s);
857
+ } else {
858
+ DB_PRINT(s, "Message didn't pass through any filter or dlc"
859
+ " is not in range.\n");
860
+ }
861
+}
862
+
863
+static uint64_t can_rxfifo_pre_read(RegisterInfo *reg, uint64_t val64)
864
+{
865
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
866
+ uint32_t r = 0;
867
+
868
+ if (!fifo32_is_empty(&s->rx_fifo)) {
869
+ r = fifo32_pop(&s->rx_fifo);
870
+ } else {
871
+ DB_PRINT(s, "No message in RXFIFO.\n");
872
+
873
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXUFLW, 1);
874
+ }
875
+
876
+ can_update_irq(s);
877
+ return r;
878
+}
879
+
880
+static void can_filter_enable_post_write(RegisterInfo *reg, uint64_t val64)
881
+{
882
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
883
+
884
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1) &&
885
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF2) &&
886
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF3) &&
887
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
888
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 1);
889
+ } else {
890
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 0);
891
+ }
892
+}
893
+
894
+static uint64_t can_filter_mask_pre_write(RegisterInfo *reg, uint64_t val64)
895
+{
896
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
897
+ uint32_t reg_idx = (reg->access->addr) / 4;
898
+ uint32_t val = val64;
899
+ uint32_t filter_number = (reg_idx - R_AFMR1) / 2;
900
+
901
+ /* modify an acceptance filter, the corresponding UAF bit should be '0.' */
902
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
903
+ s->regs[reg_idx] = val;
904
+ } else {
905
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
906
+
907
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
908
+ " mask is not set as corresponding UAF bit is not 0.\n",
909
+ path, filter_number + 1);
910
+ }
911
+
912
+ return s->regs[reg_idx];
913
+}
914
+
915
+static uint64_t can_filter_id_pre_write(RegisterInfo *reg, uint64_t val64)
916
+{
917
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
918
+ uint32_t reg_idx = (reg->access->addr) / 4;
919
+ uint32_t val = val64;
920
+ uint32_t filter_number = (reg_idx - R_AFIR1) / 2;
921
+
922
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
923
+ s->regs[reg_idx] = val;
924
+ } else {
925
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
926
+
927
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
928
+ " id is not set as corresponding UAF bit is not 0.\n",
929
+ path, filter_number + 1);
930
+ }
931
+
932
+ return s->regs[reg_idx];
933
+}
934
+
935
+static void can_tx_post_write(RegisterInfo *reg, uint64_t val64)
936
+{
937
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
938
+ uint32_t val = val64;
939
+
940
+ bool is_txhpb = reg->access->addr > A_TXFIFO_DATA2;
941
+
942
+ bool initiate_transfer = (reg->access->addr == A_TXFIFO_DATA2) ||
943
+ (reg->access->addr == A_TXHPB_DATA2);
944
+
945
+ Fifo32 *f = is_txhpb ? &s->txhpb_fifo : &s->tx_fifo;
946
+
947
+ DB_PRINT(s, "TX FIFO write.\n");
948
+
949
+ if (!fifo32_is_full(f)) {
950
+ fifo32_push(f, val);
951
+ } else {
952
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
953
+
954
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: TX FIFO is full.\n", path);
955
+ }
956
+
957
+ /* Initiate the message send if TX register is written. */
958
+ if (initiate_transfer &&
959
+ ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
960
+ transfer_fifo(s, f);
961
+ }
962
+
963
+ can_update_irq(s);
964
+}
965
+
966
+static const RegisterAccessInfo can_regs_info[] = {
967
+ { .name = "SOFTWARE_RESET_REGISTER",
968
+ .addr = A_SOFTWARE_RESET_REGISTER,
969
+ .rsvd = 0xfffffffc,
970
+ .pre_write = can_srr_pre_write,
971
+ },{ .name = "MODE_SELECT_REGISTER",
972
+ .addr = A_MODE_SELECT_REGISTER,
973
+ .rsvd = 0xfffffff8,
974
+ .pre_write = can_msr_pre_write,
975
+ },{ .name = "ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER",
976
+ .addr = A_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER,
977
+ .rsvd = 0xffffff00,
978
+ .pre_write = can_brpr_pre_write,
979
+ },{ .name = "ARBITRATION_PHASE_BIT_TIMING_REGISTER",
980
+ .addr = A_ARBITRATION_PHASE_BIT_TIMING_REGISTER,
981
+ .rsvd = 0xfffffe00,
982
+ .pre_write = can_btr_pre_write,
983
+ },{ .name = "ERROR_COUNTER_REGISTER",
984
+ .addr = A_ERROR_COUNTER_REGISTER,
985
+ .rsvd = 0xffff0000,
986
+ .ro = 0xffffffff,
987
+ },{ .name = "ERROR_STATUS_REGISTER",
988
+ .addr = A_ERROR_STATUS_REGISTER,
989
+ .rsvd = 0xffffffe0,
990
+ .w1c = 0x1f,
991
+ },{ .name = "STATUS_REGISTER", .addr = A_STATUS_REGISTER,
992
+ .reset = 0x1,
993
+ .rsvd = 0xffffe000,
994
+ .ro = 0x1fff,
995
+ },{ .name = "INTERRUPT_STATUS_REGISTER",
996
+ .addr = A_INTERRUPT_STATUS_REGISTER,
997
+ .reset = 0x6000,
998
+ .rsvd = 0xffff8000,
999
+ .ro = 0x7fff,
1000
+ },{ .name = "INTERRUPT_ENABLE_REGISTER",
1001
+ .addr = A_INTERRUPT_ENABLE_REGISTER,
1002
+ .rsvd = 0xffff8000,
1003
+ .post_write = can_ier_post_write,
1004
+ },{ .name = "INTERRUPT_CLEAR_REGISTER",
1005
+ .addr = A_INTERRUPT_CLEAR_REGISTER,
1006
+ .rsvd = 0xffff8000,
1007
+ .pre_write = can_icr_pre_write,
1008
+ },{ .name = "TIMESTAMP_REGISTER",
1009
+ .addr = A_TIMESTAMP_REGISTER,
1010
+ .rsvd = 0xfffffffe,
1011
+ .pre_write = can_tcr_pre_write,
1012
+ },{ .name = "WIR", .addr = A_WIR,
1013
+ .reset = 0x3f3f,
1014
+ .rsvd = 0xffff0000,
1015
+ },{ .name = "TXFIFO_ID", .addr = A_TXFIFO_ID,
1016
+ .post_write = can_tx_post_write,
1017
+ },{ .name = "TXFIFO_DLC", .addr = A_TXFIFO_DLC,
1018
+ .rsvd = 0xfffffff,
1019
+ .post_write = can_tx_post_write,
1020
+ },{ .name = "TXFIFO_DATA1", .addr = A_TXFIFO_DATA1,
1021
+ .post_write = can_tx_post_write,
1022
+ },{ .name = "TXFIFO_DATA2", .addr = A_TXFIFO_DATA2,
1023
+ .post_write = can_tx_post_write,
1024
+ },{ .name = "TXHPB_ID", .addr = A_TXHPB_ID,
1025
+ .post_write = can_tx_post_write,
1026
+ },{ .name = "TXHPB_DLC", .addr = A_TXHPB_DLC,
1027
+ .rsvd = 0xfffffff,
1028
+ .post_write = can_tx_post_write,
1029
+ },{ .name = "TXHPB_DATA1", .addr = A_TXHPB_DATA1,
1030
+ .post_write = can_tx_post_write,
1031
+ },{ .name = "TXHPB_DATA2", .addr = A_TXHPB_DATA2,
1032
+ .post_write = can_tx_post_write,
1033
+ },{ .name = "RXFIFO_ID", .addr = A_RXFIFO_ID,
1034
+ .ro = 0xffffffff,
1035
+ .post_read = can_rxfifo_pre_read,
1036
+ },{ .name = "RXFIFO_DLC", .addr = A_RXFIFO_DLC,
1037
+ .rsvd = 0xfff0000,
1038
+ .post_read = can_rxfifo_pre_read,
1039
+ },{ .name = "RXFIFO_DATA1", .addr = A_RXFIFO_DATA1,
1040
+ .post_read = can_rxfifo_pre_read,
1041
+ },{ .name = "RXFIFO_DATA2", .addr = A_RXFIFO_DATA2,
1042
+ .post_read = can_rxfifo_pre_read,
1043
+ },{ .name = "AFR", .addr = A_AFR,
1044
+ .rsvd = 0xfffffff0,
1045
+ .post_write = can_filter_enable_post_write,
1046
+ },{ .name = "AFMR1", .addr = A_AFMR1,
1047
+ .pre_write = can_filter_mask_pre_write,
1048
+ },{ .name = "AFIR1", .addr = A_AFIR1,
1049
+ .pre_write = can_filter_id_pre_write,
1050
+ },{ .name = "AFMR2", .addr = A_AFMR2,
1051
+ .pre_write = can_filter_mask_pre_write,
1052
+ },{ .name = "AFIR2", .addr = A_AFIR2,
1053
+ .pre_write = can_filter_id_pre_write,
1054
+ },{ .name = "AFMR3", .addr = A_AFMR3,
1055
+ .pre_write = can_filter_mask_pre_write,
1056
+ },{ .name = "AFIR3", .addr = A_AFIR3,
1057
+ .pre_write = can_filter_id_pre_write,
1058
+ },{ .name = "AFMR4", .addr = A_AFMR4,
1059
+ .pre_write = can_filter_mask_pre_write,
1060
+ },{ .name = "AFIR4", .addr = A_AFIR4,
1061
+ .pre_write = can_filter_id_pre_write,
1062
+ }
236
+ }
1063
+};
237
+};
1064
+
238
+
1065
+static void xlnx_zynqmp_can_ptimer_cb(void *opaque)
239
+static void axp209_class_init(ObjectClass *oc, void *data)
1066
+{
240
+{
1067
+ /* No action required on the timer rollover. */
241
+ DeviceClass *dc = DEVICE_CLASS(oc);
1068
+}
242
+ I2CSlaveClass *isc = I2C_SLAVE_CLASS(oc);
1069
+
243
+ ResettableClass *rc = RESETTABLE_CLASS(oc);
1070
+static const MemoryRegionOps can_ops = {
244
+
1071
+ .read = register_read_memory,
245
+ rc->phases.enter = axp209_reset_enter;
1072
+ .write = register_write_memory,
246
+ dc->vmsd = &vmstate_axp209;
1073
+ .endianness = DEVICE_LITTLE_ENDIAN,
247
+ isc->event = axp209_event;
1074
+ .valid = {
248
+ isc->recv = axp209_rx;
1075
+ .min_access_size = 4,
249
+ isc->send = axp209_tx;
1076
+ .max_access_size = 4,
250
+}
1077
+ },
251
+
252
+static const TypeInfo axp209_info = {
253
+ .name = TYPE_AXP209_PMU,
254
+ .parent = TYPE_I2C_SLAVE,
255
+ .instance_size = sizeof(AXP209I2CState),
256
+ .class_init = axp209_class_init
1078
+};
257
+};
1079
+
258
+
1080
+static void xlnx_zynqmp_can_reset_init(Object *obj, ResetType type)
259
+static void axp209_register_devices(void)
1081
+{
260
+{
1082
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
261
+ type_register_static(&axp209_info);
1083
+ unsigned int i;
262
+}
1084
+
263
+
1085
+ for (i = R_RXFIFO_ID; i < ARRAY_SIZE(s->reg_info); ++i) {
264
+type_init(axp209_register_devices);
1086
+ register_reset(&s->reg_info[i]);
265
diff --git a/MAINTAINERS b/MAINTAINERS
1087
+ }
1088
+
1089
+ ptimer_transaction_begin(s->can_timer);
1090
+ ptimer_set_count(s->can_timer, 0);
1091
+ ptimer_transaction_commit(s->can_timer);
1092
+}
1093
+
1094
+static void xlnx_zynqmp_can_reset_hold(Object *obj)
1095
+{
1096
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1097
+ unsigned int i;
1098
+
1099
+ for (i = 0; i < R_RXFIFO_ID; ++i) {
1100
+ register_reset(&s->reg_info[i]);
1101
+ }
1102
+
1103
+ /*
1104
+ * Reset FIFOs when CAN model is reset. This will clear the fifo writes
1105
+ * done by post_write which gets called from register_reset function,
1106
+ * post_write handle will not be able to trigger tx because CAN will be
1107
+ * disabled when software_reset_register is cleared first.
1108
+ */
1109
+ fifo32_reset(&s->rx_fifo);
1110
+ fifo32_reset(&s->tx_fifo);
1111
+ fifo32_reset(&s->txhpb_fifo);
1112
+}
1113
+
1114
+static bool xlnx_zynqmp_can_can_receive(CanBusClientState *client)
1115
+{
1116
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1117
+ bus_client);
1118
+
1119
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
1120
+ DB_PRINT(s, "Controller is in reset.\n");
1121
+ return false;
1122
+ } else if ((ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) == 0) {
1123
+ DB_PRINT(s, "Controller is disabled. Incoming messages"
1124
+ " will be discarded.\n");
1125
+ return false;
1126
+ } else {
1127
+ return true;
1128
+ }
1129
+}
1130
+
1131
+static ssize_t xlnx_zynqmp_can_receive(CanBusClientState *client,
1132
+ const qemu_can_frame *buf, size_t buf_size) {
1133
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1134
+ bus_client);
1135
+ const qemu_can_frame *frame = buf;
1136
+
1137
+ DB_PRINT(s, "Incoming data.\n");
1138
+
1139
+ if (buf_size <= 0) {
1140
+ DB_PRINT(s, "Junk data received.\n");
1141
+ return 0;
1142
+ }
1143
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
1144
+ /*
1145
+ * XlnxZynqMPCAN will not participate in normal bus communication
1146
+ * and will not receive any messages transmitted by other CAN nodes.
1147
+ */
1148
+ DB_PRINT(s, "Controller is in loopback mode. It will not"
1149
+ " receive data.\n");
1150
+
1151
+ } else if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
1152
+ /* Snoop Mode: Just keep the data. no response back. */
1153
+ update_rx_fifo(s, frame);
1154
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP))) {
1155
+ /*
1156
+ * XlnxZynqMPCAN is in sleep mode. Any data on bus will bring it to wake
1157
+ * up state.
1158
+ */
1159
+ can_exit_sleep_mode(s);
1160
+ update_rx_fifo(s, frame);
1161
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) == 0) {
1162
+ update_rx_fifo(s, frame);
1163
+ } else {
1164
+ DB_PRINT(s, "Cannot receive data as controller is not configured"
1165
+ " correctly.\n");
1166
+ }
1167
+
1168
+ return 1;
1169
+}
1170
+
1171
+static CanBusClientInfo can_xilinx_bus_client_info = {
1172
+ .can_receive = xlnx_zynqmp_can_can_receive,
1173
+ .receive = xlnx_zynqmp_can_receive,
1174
+};
1175
+
1176
+static int xlnx_zynqmp_can_connect_to_bus(XlnxZynqMPCANState *s,
1177
+ CanBusState *bus)
1178
+{
1179
+ s->bus_client.info = &can_xilinx_bus_client_info;
1180
+
1181
+ if (can_bus_insert_client(bus, &s->bus_client) < 0) {
1182
+ return -1;
1183
+ }
1184
+ return 0;
1185
+}
1186
+
1187
+static void xlnx_zynqmp_can_realize(DeviceState *dev, Error **errp)
1188
+{
1189
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(dev);
1190
+
1191
+ if (s->canbus) {
1192
+ if (xlnx_zynqmp_can_connect_to_bus(s, s->canbus) < 0) {
1193
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1194
+
1195
+ error_setg(errp, "%s: xlnx_zynqmp_can_connect_to_bus"
1196
+ " failed.", path);
1197
+ return;
1198
+ }
1199
+
1200
+ } else {
1201
+ /* If no bus is set. */
1202
+ DB_PRINT(s, "Canbus property is not set.\n");
1203
+ }
1204
+
1205
+ /* Create RX FIFO, TXFIFO, TXHPB storage. */
1206
+ fifo32_create(&s->rx_fifo, RXFIFO_SIZE);
1207
+ fifo32_create(&s->tx_fifo, RXFIFO_SIZE);
1208
+ fifo32_create(&s->txhpb_fifo, CAN_FRAME_SIZE);
1209
+
1210
+ /* Allocate a new timer. */
1211
+ s->can_timer = ptimer_init(xlnx_zynqmp_can_ptimer_cb, s,
1212
+ PTIMER_POLICY_DEFAULT);
1213
+
1214
+ ptimer_transaction_begin(s->can_timer);
1215
+
1216
+ ptimer_set_freq(s->can_timer, s->cfg.ext_clk_freq);
1217
+ ptimer_set_limit(s->can_timer, CAN_TIMER_MAX, 1);
1218
+ ptimer_run(s->can_timer, 0);
1219
+ ptimer_transaction_commit(s->can_timer);
1220
+}
1221
+
1222
+static void xlnx_zynqmp_can_init(Object *obj)
1223
+{
1224
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1225
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1226
+
1227
+ RegisterInfoArray *reg_array;
1228
+
1229
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_CAN,
1230
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
1231
+ reg_array = register_init_block32(DEVICE(obj), can_regs_info,
1232
+ ARRAY_SIZE(can_regs_info),
1233
+ s->reg_info, s->regs,
1234
+ &can_ops,
1235
+ XLNX_ZYNQMP_CAN_ERR_DEBUG,
1236
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
1237
+
1238
+ memory_region_add_subregion(&s->iomem, 0x00, &reg_array->mem);
1239
+ sysbus_init_mmio(sbd, &s->iomem);
1240
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
1241
+}
1242
+
1243
+static const VMStateDescription vmstate_can = {
1244
+ .name = TYPE_XLNX_ZYNQMP_CAN,
1245
+ .version_id = 1,
1246
+ .minimum_version_id = 1,
1247
+ .fields = (VMStateField[]) {
1248
+ VMSTATE_FIFO32(rx_fifo, XlnxZynqMPCANState),
1249
+ VMSTATE_FIFO32(tx_fifo, XlnxZynqMPCANState),
1250
+ VMSTATE_FIFO32(txhpb_fifo, XlnxZynqMPCANState),
1251
+ VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPCANState, XLNX_ZYNQMP_CAN_R_MAX),
1252
+ VMSTATE_PTIMER(can_timer, XlnxZynqMPCANState),
1253
+ VMSTATE_END_OF_LIST(),
1254
+ }
1255
+};
1256
+
1257
+static Property xlnx_zynqmp_can_properties[] = {
1258
+ DEFINE_PROP_UINT32("ext_clk_freq", XlnxZynqMPCANState, cfg.ext_clk_freq,
1259
+ CAN_DEFAULT_CLOCK),
1260
+ DEFINE_PROP_LINK("canbus", XlnxZynqMPCANState, canbus, TYPE_CAN_BUS,
1261
+ CanBusState *),
1262
+ DEFINE_PROP_END_OF_LIST(),
1263
+};
1264
+
1265
+static void xlnx_zynqmp_can_class_init(ObjectClass *klass, void *data)
1266
+{
1267
+ DeviceClass *dc = DEVICE_CLASS(klass);
1268
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
1269
+
1270
+ rc->phases.enter = xlnx_zynqmp_can_reset_init;
1271
+ rc->phases.hold = xlnx_zynqmp_can_reset_hold;
1272
+ dc->realize = xlnx_zynqmp_can_realize;
1273
+ device_class_set_props(dc, xlnx_zynqmp_can_properties);
1274
+ dc->vmsd = &vmstate_can;
1275
+}
1276
+
1277
+static const TypeInfo can_info = {
1278
+ .name = TYPE_XLNX_ZYNQMP_CAN,
1279
+ .parent = TYPE_SYS_BUS_DEVICE,
1280
+ .instance_size = sizeof(XlnxZynqMPCANState),
1281
+ .class_init = xlnx_zynqmp_can_class_init,
1282
+ .instance_init = xlnx_zynqmp_can_init,
1283
+};
1284
+
1285
+static void can_register_types(void)
1286
+{
1287
+ type_register_static(&can_info);
1288
+}
1289
+
1290
+type_init(can_register_types)
1291
diff --git a/hw/net/can/meson.build b/hw/net/can/meson.build
1292
index XXXXXXX..XXXXXXX 100644
266
index XXXXXXX..XXXXXXX 100644
1293
--- a/hw/net/can/meson.build
267
--- a/MAINTAINERS
1294
+++ b/hw/net/can/meson.build
268
+++ b/MAINTAINERS
1295
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_CAN_SJA1000', if_true: files('can_sja1000.c'))
269
@@ -XXX,XX +XXX,XX @@ ARM Machines
1296
softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_kvaser_pci.c'))
270
Allwinner-a10
1297
softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_pcm3680_pci.c'))
271
M: Beniamino Galvani <b.galvani@gmail.com>
1298
softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_mioe3680_pci.c'))
272
M: Peter Maydell <peter.maydell@linaro.org>
1299
+softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-can.c'))
273
+R: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
274
L: qemu-arm@nongnu.org
275
S: Odd Fixes
276
F: hw/*/allwinner*
277
F: include/hw/*/allwinner*
278
F: hw/arm/cubieboard.c
279
F: docs/system/arm/cubieboard.rst
280
+F: hw/misc/axp209.c
281
282
Allwinner-h3
283
M: Niek Linnenbank <nieklinnenbank@gmail.com>
284
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
285
index XXXXXXX..XXXXXXX 100644
286
--- a/hw/misc/Kconfig
287
+++ b/hw/misc/Kconfig
288
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10_CCM
289
config ALLWINNER_A10_DRAMC
290
bool
291
292
+config AXP209_PMU
293
+ bool
294
+ depends on I2C
295
+
296
source macio/Kconfig
297
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
298
index XXXXXXX..XXXXXXX 100644
299
--- a/hw/misc/meson.build
300
+++ b/hw/misc/meson.build
301
@@ -XXX,XX +XXX,XX @@ specific_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-cpucfg.c'
302
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-dramc.c'))
303
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-sysctrl.c'))
304
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-sid.c'))
305
+softmmu_ss.add(when: 'CONFIG_AXP209_PMU', if_true: files('axp209.c'))
306
softmmu_ss.add(when: 'CONFIG_REALVIEW', if_true: files('arm_sysctl.c'))
307
softmmu_ss.add(when: 'CONFIG_NSERIES', if_true: files('cbus.c'))
308
softmmu_ss.add(when: 'CONFIG_ECCMEMCTL', if_true: files('eccmemctl.c'))
309
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
310
index XXXXXXX..XXXXXXX 100644
311
--- a/hw/misc/trace-events
312
+++ b/hw/misc/trace-events
313
@@ -XXX,XX +XXX,XX @@ allwinner_sid_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%"
314
avr_power_read(uint8_t value) "power_reduc read value:%u"
315
avr_power_write(uint8_t value) "power_reduc write value:%u"
316
317
+# axp209.c
318
+axp209_rx(uint8_t reg, uint8_t data) "Read reg 0x%" PRIx8 " : 0x%" PRIx8
319
+axp209_select(uint8_t reg) "Accessing reg 0x%" PRIx8
320
+axp209_tx(uint8_t reg, uint8_t data) "Write reg 0x%" PRIx8 " : 0x%" PRIx8
321
+
322
# eccmemctl.c
323
ecc_mem_writel_mer(uint32_t val) "Write memory enable 0x%08x"
324
ecc_mem_writel_mdr(uint32_t val) "Write memory delay 0x%08x"
1300
--
325
--
1301
2.20.1
326
2.34.1
1302
1303
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
2
2
3
The Nuvoton NPCM7xx SoC family are used to implement Baseboard
3
SPL Boot for Cubieboard expects AXP209 connected to I2C0 bus.
4
Management Controllers in servers. While the family includes four SoCs,
5
this patch implements limited support for two of them: NPCM730 (targeted
6
for Data Center applications) and NPCM750 (targeted for Enterprise
7
applications).
8
4
9
This patch includes little more than the bare minimum needed to boot a
5
Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
10
Linux kernel built with NPCM7xx support in direct-kernel mode:
11
6
12
- Two Cortex-A9 CPU cores with built-in periperhals.
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
13
- Global Configuration Registers.
8
Message-id: 20221226220303.14420-6-strahinja.p.jankovic@gmail.com
14
- Clock Management.
15
- 3 Timer Modules with 5 timers each.
16
- 4 serial ports.
17
18
The chips themselves have a lot more features, some of which will be
19
added to the model at a later stage.
20
21
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
22
Reviewed-by: Joel Stanley <joel@jms.id.au>
23
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
24
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
25
Tested-by: Alexander Bulekov <alxndr@bu.edu>
26
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
27
Message-id: 20200911052101.2602693-5-hskinnemoen@google.com
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
---
10
---
30
include/hw/arm/npcm7xx.h | 85 ++++++++
11
hw/arm/cubieboard.c | 6 ++++++
31
hw/arm/npcm7xx.c | 407 +++++++++++++++++++++++++++++++++++++++
12
hw/arm/Kconfig | 1 +
32
hw/arm/Kconfig | 5 +
13
2 files changed, 7 insertions(+)
33
hw/arm/meson.build | 1 +
34
4 files changed, 498 insertions(+)
35
create mode 100644 include/hw/arm/npcm7xx.h
36
create mode 100644 hw/arm/npcm7xx.c
37
14
38
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
15
diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
39
new file mode 100644
16
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX
17
--- a/hw/arm/cubieboard.c
41
--- /dev/null
18
+++ b/hw/arm/cubieboard.c
42
+++ b/include/hw/arm/npcm7xx.h
43
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
44
+/*
20
#include "hw/boards.h"
45
+ * Nuvoton NPCM7xx SoC family.
21
#include "hw/qdev-properties.h"
46
+ *
22
#include "hw/arm/allwinner-a10.h"
47
+ * Copyright 2020 Google LLC
23
+#include "hw/i2c/i2c.h"
48
+ *
24
49
+ * This program is free software; you can redistribute it and/or modify it
25
static struct arm_boot_info cubieboard_binfo = {
50
+ * under the terms of the GNU General Public License as published by the
26
.loader_start = AW_A10_SDRAM_BASE,
51
+ * Free Software Foundation; either version 2 of the License, or
27
@@ -XXX,XX +XXX,XX @@ static void cubieboard_init(MachineState *machine)
52
+ * (at your option) any later version.
28
BlockBackend *blk;
53
+ *
29
BusState *bus;
54
+ * This program is distributed in the hope that it will be useful, but WITHOUT
30
DeviceState *carddev;
55
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
31
+ I2CBus *i2c;
56
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
32
57
+ * for more details.
33
/* BIOS is not supported by this board */
58
+ */
34
if (machine->firmware) {
59
+#ifndef NPCM7XX_H
35
@@ -XXX,XX +XXX,XX @@ static void cubieboard_init(MachineState *machine)
60
+#define NPCM7XX_H
36
exit(1);
37
}
38
39
+ /* Connect AXP 209 */
40
+ i2c = I2C_BUS(qdev_get_child_bus(DEVICE(&a10->i2c0), "i2c"));
41
+ i2c_slave_create_simple(i2c, "axp209_pmu", 0x34);
61
+
42
+
62
+#include "hw/boards.h"
43
/* Retrieve SD bus */
63
+#include "hw/cpu/a9mpcore.h"
44
di = drive_get(IF_SD, 0, 0);
64
+#include "hw/misc/npcm7xx_clk.h"
45
blk = di ? blk_by_legacy_dinfo(di) : NULL;
65
+#include "hw/misc/npcm7xx_gcr.h"
66
+#include "hw/timer/npcm7xx_timer.h"
67
+#include "target/arm/cpu.h"
68
+
69
+#define NPCM7XX_MAX_NUM_CPUS (2)
70
+
71
+/* The first half of the address space is reserved for DDR4 DRAM. */
72
+#define NPCM7XX_DRAM_BA (0x00000000)
73
+#define NPCM7XX_DRAM_SZ (2 * GiB)
74
+
75
+/* Magic addresses for setting up direct kernel booting and SMP boot stubs. */
76
+#define NPCM7XX_LOADER_START (0x00000000) /* Start of SDRAM */
77
+#define NPCM7XX_SMP_LOADER_START (0xffff0000) /* Boot ROM */
78
+#define NPCM7XX_SMP_BOOTREG_ADDR (0xf080013c) /* GCR.SCRPAD */
79
+#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100) /* GIC within A9 */
80
+
81
+typedef struct NPCM7xxState {
82
+ DeviceState parent;
83
+
84
+ ARMCPU cpu[NPCM7XX_MAX_NUM_CPUS];
85
+ A9MPPrivState a9mpcore;
86
+
87
+ MemoryRegion sram;
88
+ MemoryRegion irom;
89
+ MemoryRegion ram3;
90
+ MemoryRegion *dram;
91
+
92
+ NPCM7xxGCRState gcr;
93
+ NPCM7xxCLKState clk;
94
+ NPCM7xxTimerCtrlState tim[3];
95
+} NPCM7xxState;
96
+
97
+#define TYPE_NPCM7XX "npcm7xx"
98
+#define NPCM7XX(obj) OBJECT_CHECK(NPCM7xxState, (obj), TYPE_NPCM7XX)
99
+
100
+#define TYPE_NPCM730 "npcm730"
101
+#define TYPE_NPCM750 "npcm750"
102
+
103
+typedef struct NPCM7xxClass {
104
+ DeviceClass parent;
105
+
106
+ /* Bitmask of modules that are permanently disabled on this chip. */
107
+ uint32_t disabled_modules;
108
+ /* Number of CPU cores enabled in this SoC class (may be 1 or 2). */
109
+ uint32_t num_cpus;
110
+} NPCM7xxClass;
111
+
112
+#define NPCM7XX_CLASS(klass) \
113
+ OBJECT_CLASS_CHECK(NPCM7xxClass, (klass), TYPE_NPCM7XX)
114
+#define NPCM7XX_GET_CLASS(obj) \
115
+ OBJECT_GET_CLASS(NPCM7xxClass, (obj), TYPE_NPCM7XX)
116
+
117
+/**
118
+ * npcm7xx_load_kernel - Loads memory with everything needed to boot
119
+ * @machine - The machine containing the SoC to be booted.
120
+ * @soc - The SoC containing the CPU to be booted.
121
+ *
122
+ * This will set up the ARM boot info structure for the specific NPCM7xx
123
+ * derivative and call arm_load_kernel() to set up loading of the kernel, etc.
124
+ * into memory, if requested by the user.
125
+ */
126
+void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc);
127
+
128
+#endif /* NPCM7XX_H */
129
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
130
new file mode 100644
131
index XXXXXXX..XXXXXXX
132
--- /dev/null
133
+++ b/hw/arm/npcm7xx.c
134
@@ -XXX,XX +XXX,XX @@
135
+/*
136
+ * Nuvoton NPCM7xx SoC family.
137
+ *
138
+ * Copyright 2020 Google LLC
139
+ *
140
+ * This program is free software; you can redistribute it and/or modify it
141
+ * under the terms of the GNU General Public License as published by the
142
+ * Free Software Foundation; either version 2 of the License, or
143
+ * (at your option) any later version.
144
+ *
145
+ * This program is distributed in the hope that it will be useful, but WITHOUT
146
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
147
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
148
+ * for more details.
149
+ */
150
+
151
+#include "qemu/osdep.h"
152
+
153
+#include "exec/address-spaces.h"
154
+#include "hw/arm/boot.h"
155
+#include "hw/arm/npcm7xx.h"
156
+#include "hw/char/serial.h"
157
+#include "hw/loader.h"
158
+#include "hw/misc/unimp.h"
159
+#include "hw/qdev-properties.h"
160
+#include "qapi/error.h"
161
+#include "qemu/units.h"
162
+#include "sysemu/sysemu.h"
163
+
164
+/*
165
+ * This covers the whole MMIO space. We'll use this to catch any MMIO accesses
166
+ * that aren't handled by any device.
167
+ */
168
+#define NPCM7XX_MMIO_BA (0x80000000)
169
+#define NPCM7XX_MMIO_SZ (0x7ffd0000)
170
+
171
+/* Core system modules. */
172
+#define NPCM7XX_L2C_BA (0xf03fc000)
173
+#define NPCM7XX_CPUP_BA (0xf03fe000)
174
+#define NPCM7XX_GCR_BA (0xf0800000)
175
+#define NPCM7XX_CLK_BA (0xf0801000)
176
+
177
+/* Internal AHB SRAM */
178
+#define NPCM7XX_RAM3_BA (0xc0008000)
179
+#define NPCM7XX_RAM3_SZ (4 * KiB)
180
+
181
+/* Memory blocks at the end of the address space */
182
+#define NPCM7XX_RAM2_BA (0xfffd0000)
183
+#define NPCM7XX_RAM2_SZ (128 * KiB)
184
+#define NPCM7XX_ROM_BA (0xffff0000)
185
+#define NPCM7XX_ROM_SZ (64 * KiB)
186
+
187
+/*
188
+ * Interrupt lines going into the GIC. This does not include internal Cortex-A9
189
+ * interrupts.
190
+ */
191
+enum NPCM7xxInterrupt {
192
+ NPCM7XX_UART0_IRQ = 2,
193
+ NPCM7XX_UART1_IRQ,
194
+ NPCM7XX_UART2_IRQ,
195
+ NPCM7XX_UART3_IRQ,
196
+ NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */
197
+ NPCM7XX_TIMER1_IRQ,
198
+ NPCM7XX_TIMER2_IRQ,
199
+ NPCM7XX_TIMER3_IRQ,
200
+ NPCM7XX_TIMER4_IRQ,
201
+ NPCM7XX_TIMER5_IRQ, /* Timer Module 1 */
202
+ NPCM7XX_TIMER6_IRQ,
203
+ NPCM7XX_TIMER7_IRQ,
204
+ NPCM7XX_TIMER8_IRQ,
205
+ NPCM7XX_TIMER9_IRQ,
206
+ NPCM7XX_TIMER10_IRQ, /* Timer Module 2 */
207
+ NPCM7XX_TIMER11_IRQ,
208
+ NPCM7XX_TIMER12_IRQ,
209
+ NPCM7XX_TIMER13_IRQ,
210
+ NPCM7XX_TIMER14_IRQ,
211
+};
212
+
213
+/* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
214
+#define NPCM7XX_NUM_IRQ (160)
215
+
216
+/* Register base address for each Timer Module */
217
+static const hwaddr npcm7xx_tim_addr[] = {
218
+ 0xf0008000,
219
+ 0xf0009000,
220
+ 0xf000a000,
221
+};
222
+
223
+/* Register base address for each 16550 UART */
224
+static const hwaddr npcm7xx_uart_addr[] = {
225
+ 0xf0001000,
226
+ 0xf0002000,
227
+ 0xf0003000,
228
+ 0xf0004000,
229
+};
230
+
231
+static void npcm7xx_write_secondary_boot(ARMCPU *cpu,
232
+ const struct arm_boot_info *info)
233
+{
234
+ /*
235
+ * The default smpboot stub halts the secondary CPU with a 'wfi'
236
+ * instruction, but the arch/arm/mach-npcm/platsmp.c in the Linux kernel
237
+ * does not send an IPI to wake it up, so the second CPU fails to boot. So
238
+ * we need to provide our own smpboot stub that can not use 'wfi', it has
239
+ * to spin the secondary CPU until the first CPU writes to the SCRPAD reg.
240
+ */
241
+ uint32_t smpboot[] = {
242
+ 0xe59f2018, /* ldr r2, bootreg_addr */
243
+ 0xe3a00000, /* mov r0, #0 */
244
+ 0xe5820000, /* str r0, [r2] */
245
+ 0xe320f002, /* wfe */
246
+ 0xe5921000, /* ldr r1, [r2] */
247
+ 0xe1110001, /* tst r1, r1 */
248
+ 0x0afffffb, /* beq <wfe> */
249
+ 0xe12fff11, /* bx r1 */
250
+ NPCM7XX_SMP_BOOTREG_ADDR,
251
+ };
252
+ int i;
253
+
254
+ for (i = 0; i < ARRAY_SIZE(smpboot); i++) {
255
+ smpboot[i] = tswap32(smpboot[i]);
256
+ }
257
+
258
+ rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
259
+ NPCM7XX_SMP_LOADER_START);
260
+}
261
+
262
+static struct arm_boot_info npcm7xx_binfo = {
263
+ .loader_start = NPCM7XX_LOADER_START,
264
+ .smp_loader_start = NPCM7XX_SMP_LOADER_START,
265
+ .smp_bootreg_addr = NPCM7XX_SMP_BOOTREG_ADDR,
266
+ .gic_cpu_if_addr = NPCM7XX_GIC_CPU_IF_ADDR,
267
+ .write_secondary_boot = npcm7xx_write_secondary_boot,
268
+ .board_id = -1,
269
+};
270
+
271
+void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
272
+{
273
+ NPCM7xxClass *sc = NPCM7XX_GET_CLASS(soc);
274
+
275
+ npcm7xx_binfo.ram_size = machine->ram_size;
276
+ npcm7xx_binfo.nb_cpus = sc->num_cpus;
277
+
278
+ arm_load_kernel(&soc->cpu[0], machine, &npcm7xx_binfo);
279
+}
280
+
281
+static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n)
282
+{
283
+ return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
284
+}
285
+
286
+static void npcm7xx_init(Object *obj)
287
+{
288
+ NPCM7xxState *s = NPCM7XX(obj);
289
+ int i;
290
+
291
+ for (i = 0; i < NPCM7XX_MAX_NUM_CPUS; i++) {
292
+ object_initialize_child(obj, "cpu[*]", &s->cpu[i],
293
+ ARM_CPU_TYPE_NAME("cortex-a9"));
294
+ }
295
+
296
+ object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
297
+ object_initialize_child(obj, "gcr", &s->gcr, TYPE_NPCM7XX_GCR);
298
+ object_property_add_alias(obj, "power-on-straps", OBJECT(&s->gcr),
299
+ "power-on-straps");
300
+ object_initialize_child(obj, "clk", &s->clk, TYPE_NPCM7XX_CLK);
301
+
302
+ for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
303
+ object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
304
+ }
305
+}
306
+
307
+static void npcm7xx_realize(DeviceState *dev, Error **errp)
308
+{
309
+ NPCM7xxState *s = NPCM7XX(dev);
310
+ NPCM7xxClass *nc = NPCM7XX_GET_CLASS(s);
311
+ int i;
312
+
313
+ if (memory_region_size(s->dram) > NPCM7XX_DRAM_SZ) {
314
+ error_setg(errp, "%s: NPCM7xx cannot address more than %" PRIu64
315
+ " MiB of DRAM", __func__, NPCM7XX_DRAM_SZ / MiB);
316
+ return;
317
+ }
318
+
319
+ /* CPUs */
320
+ for (i = 0; i < nc->num_cpus; i++) {
321
+ object_property_set_int(OBJECT(&s->cpu[i]), "mp-affinity",
322
+ arm_cpu_mp_affinity(i, NPCM7XX_MAX_NUM_CPUS),
323
+ &error_abort);
324
+ object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
325
+ NPCM7XX_GIC_CPU_IF_ADDR, &error_abort);
326
+ object_property_set_bool(OBJECT(&s->cpu[i]), "reset-hivecs", true,
327
+ &error_abort);
328
+
329
+ /* Disable security extensions. */
330
+ object_property_set_bool(OBJECT(&s->cpu[i]), "has_el3", false,
331
+ &error_abort);
332
+
333
+ if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) {
334
+ return;
335
+ }
336
+ }
337
+
338
+ /* A9MPCORE peripherals. Can only fail if we pass bad parameters here. */
339
+ object_property_set_int(OBJECT(&s->a9mpcore), "num-cpu", nc->num_cpus,
340
+ &error_abort);
341
+ object_property_set_int(OBJECT(&s->a9mpcore), "num-irq", NPCM7XX_NUM_IRQ,
342
+ &error_abort);
343
+ sysbus_realize(SYS_BUS_DEVICE(&s->a9mpcore), &error_abort);
344
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->a9mpcore), 0, NPCM7XX_CPUP_BA);
345
+
346
+ for (i = 0; i < nc->num_cpus; i++) {
347
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i,
348
+ qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_IRQ));
349
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i + nc->num_cpus,
350
+ qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_FIQ));
351
+ }
352
+
353
+ /* L2 cache controller */
354
+ sysbus_create_simple("l2x0", NPCM7XX_L2C_BA, NULL);
355
+
356
+ /* System Global Control Registers (GCR). Can fail due to user input. */
357
+ object_property_set_int(OBJECT(&s->gcr), "disabled-modules",
358
+ nc->disabled_modules, &error_abort);
359
+ object_property_add_const_link(OBJECT(&s->gcr), "dram-mr", OBJECT(s->dram));
360
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->gcr), errp)) {
361
+ return;
362
+ }
363
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gcr), 0, NPCM7XX_GCR_BA);
364
+
365
+ /* Clock Control Registers (CLK). Cannot fail. */
366
+ sysbus_realize(SYS_BUS_DEVICE(&s->clk), &error_abort);
367
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->clk), 0, NPCM7XX_CLK_BA);
368
+
369
+ /* Timer Modules (TIM). Cannot fail. */
370
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
371
+ for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
372
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->tim[i]);
373
+ int first_irq;
374
+ int j;
375
+
376
+ sysbus_realize(sbd, &error_abort);
377
+ sysbus_mmio_map(sbd, 0, npcm7xx_tim_addr[i]);
378
+
379
+ first_irq = NPCM7XX_TIMER0_IRQ + i * NPCM7XX_TIMERS_PER_CTRL;
380
+ for (j = 0; j < NPCM7XX_TIMERS_PER_CTRL; j++) {
381
+ qemu_irq irq = npcm7xx_irq(s, first_irq + j);
382
+ sysbus_connect_irq(sbd, j, irq);
383
+ }
384
+ }
385
+
386
+ /* UART0..3 (16550 compatible) */
387
+ for (i = 0; i < ARRAY_SIZE(npcm7xx_uart_addr); i++) {
388
+ serial_mm_init(get_system_memory(), npcm7xx_uart_addr[i], 2,
389
+ npcm7xx_irq(s, NPCM7XX_UART0_IRQ + i), 115200,
390
+ serial_hd(i), DEVICE_LITTLE_ENDIAN);
391
+ }
392
+
393
+ /* RAM2 (SRAM) */
394
+ memory_region_init_ram(&s->sram, OBJECT(dev), "ram2",
395
+ NPCM7XX_RAM2_SZ, &error_abort);
396
+ memory_region_add_subregion(get_system_memory(), NPCM7XX_RAM2_BA, &s->sram);
397
+
398
+ /* RAM3 (SRAM) */
399
+ memory_region_init_ram(&s->ram3, OBJECT(dev), "ram3",
400
+ NPCM7XX_RAM3_SZ, &error_abort);
401
+ memory_region_add_subregion(get_system_memory(), NPCM7XX_RAM3_BA, &s->ram3);
402
+
403
+ /* Internal ROM */
404
+ memory_region_init_rom(&s->irom, OBJECT(dev), "irom", NPCM7XX_ROM_SZ,
405
+ &error_abort);
406
+ memory_region_add_subregion(get_system_memory(), NPCM7XX_ROM_BA, &s->irom);
407
+
408
+ create_unimplemented_device("npcm7xx.shm", 0xc0001000, 4 * KiB);
409
+ create_unimplemented_device("npcm7xx.vdmx", 0xe0800000, 4 * KiB);
410
+ create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB);
411
+ create_unimplemented_device("npcm7xx.kcs", 0xf0007000, 4 * KiB);
412
+ create_unimplemented_device("npcm7xx.rng", 0xf000b000, 4 * KiB);
413
+ create_unimplemented_device("npcm7xx.adc", 0xf000c000, 4 * KiB);
414
+ create_unimplemented_device("npcm7xx.gfxi", 0xf000e000, 4 * KiB);
415
+ create_unimplemented_device("npcm7xx.gpio[0]", 0xf0010000, 4 * KiB);
416
+ create_unimplemented_device("npcm7xx.gpio[1]", 0xf0011000, 4 * KiB);
417
+ create_unimplemented_device("npcm7xx.gpio[2]", 0xf0012000, 4 * KiB);
418
+ create_unimplemented_device("npcm7xx.gpio[3]", 0xf0013000, 4 * KiB);
419
+ create_unimplemented_device("npcm7xx.gpio[4]", 0xf0014000, 4 * KiB);
420
+ create_unimplemented_device("npcm7xx.gpio[5]", 0xf0015000, 4 * KiB);
421
+ create_unimplemented_device("npcm7xx.gpio[6]", 0xf0016000, 4 * KiB);
422
+ create_unimplemented_device("npcm7xx.gpio[7]", 0xf0017000, 4 * KiB);
423
+ create_unimplemented_device("npcm7xx.smbus[0]", 0xf0080000, 4 * KiB);
424
+ create_unimplemented_device("npcm7xx.smbus[1]", 0xf0081000, 4 * KiB);
425
+ create_unimplemented_device("npcm7xx.smbus[2]", 0xf0082000, 4 * KiB);
426
+ create_unimplemented_device("npcm7xx.smbus[3]", 0xf0083000, 4 * KiB);
427
+ create_unimplemented_device("npcm7xx.smbus[4]", 0xf0084000, 4 * KiB);
428
+ create_unimplemented_device("npcm7xx.smbus[5]", 0xf0085000, 4 * KiB);
429
+ create_unimplemented_device("npcm7xx.smbus[6]", 0xf0086000, 4 * KiB);
430
+ create_unimplemented_device("npcm7xx.smbus[7]", 0xf0087000, 4 * KiB);
431
+ create_unimplemented_device("npcm7xx.smbus[8]", 0xf0088000, 4 * KiB);
432
+ create_unimplemented_device("npcm7xx.smbus[9]", 0xf0089000, 4 * KiB);
433
+ create_unimplemented_device("npcm7xx.smbus[10]", 0xf008a000, 4 * KiB);
434
+ create_unimplemented_device("npcm7xx.smbus[11]", 0xf008b000, 4 * KiB);
435
+ create_unimplemented_device("npcm7xx.smbus[12]", 0xf008c000, 4 * KiB);
436
+ create_unimplemented_device("npcm7xx.smbus[13]", 0xf008d000, 4 * KiB);
437
+ create_unimplemented_device("npcm7xx.smbus[14]", 0xf008e000, 4 * KiB);
438
+ create_unimplemented_device("npcm7xx.smbus[15]", 0xf008f000, 4 * KiB);
439
+ create_unimplemented_device("npcm7xx.espi", 0xf009f000, 4 * KiB);
440
+ create_unimplemented_device("npcm7xx.peci", 0xf0100000, 4 * KiB);
441
+ create_unimplemented_device("npcm7xx.siox[1]", 0xf0101000, 4 * KiB);
442
+ create_unimplemented_device("npcm7xx.siox[2]", 0xf0102000, 4 * KiB);
443
+ create_unimplemented_device("npcm7xx.pwm[0]", 0xf0103000, 4 * KiB);
444
+ create_unimplemented_device("npcm7xx.pwm[1]", 0xf0104000, 4 * KiB);
445
+ create_unimplemented_device("npcm7xx.mft[0]", 0xf0180000, 4 * KiB);
446
+ create_unimplemented_device("npcm7xx.mft[1]", 0xf0181000, 4 * KiB);
447
+ create_unimplemented_device("npcm7xx.mft[2]", 0xf0182000, 4 * KiB);
448
+ create_unimplemented_device("npcm7xx.mft[3]", 0xf0183000, 4 * KiB);
449
+ create_unimplemented_device("npcm7xx.mft[4]", 0xf0184000, 4 * KiB);
450
+ create_unimplemented_device("npcm7xx.mft[5]", 0xf0185000, 4 * KiB);
451
+ create_unimplemented_device("npcm7xx.mft[6]", 0xf0186000, 4 * KiB);
452
+ create_unimplemented_device("npcm7xx.mft[7]", 0xf0187000, 4 * KiB);
453
+ create_unimplemented_device("npcm7xx.pspi1", 0xf0200000, 4 * KiB);
454
+ create_unimplemented_device("npcm7xx.pspi2", 0xf0201000, 4 * KiB);
455
+ create_unimplemented_device("npcm7xx.ahbpci", 0xf0400000, 1 * MiB);
456
+ create_unimplemented_device("npcm7xx.mcphy", 0xf05f0000, 64 * KiB);
457
+ create_unimplemented_device("npcm7xx.gmac1", 0xf0802000, 8 * KiB);
458
+ create_unimplemented_device("npcm7xx.gmac2", 0xf0804000, 8 * KiB);
459
+ create_unimplemented_device("npcm7xx.ehci", 0xf0806000, 4 * KiB);
460
+ create_unimplemented_device("npcm7xx.ohci", 0xf0807000, 4 * KiB);
461
+ create_unimplemented_device("npcm7xx.vcd", 0xf0810000, 64 * KiB);
462
+ create_unimplemented_device("npcm7xx.ece", 0xf0820000, 8 * KiB);
463
+ create_unimplemented_device("npcm7xx.vdma", 0xf0822000, 8 * KiB);
464
+ create_unimplemented_device("npcm7xx.emc1", 0xf0825000, 4 * KiB);
465
+ create_unimplemented_device("npcm7xx.emc2", 0xf0826000, 4 * KiB);
466
+ create_unimplemented_device("npcm7xx.usbd[0]", 0xf0830000, 4 * KiB);
467
+ create_unimplemented_device("npcm7xx.usbd[1]", 0xf0831000, 4 * KiB);
468
+ create_unimplemented_device("npcm7xx.usbd[2]", 0xf0832000, 4 * KiB);
469
+ create_unimplemented_device("npcm7xx.usbd[3]", 0xf0833000, 4 * KiB);
470
+ create_unimplemented_device("npcm7xx.usbd[4]", 0xf0834000, 4 * KiB);
471
+ create_unimplemented_device("npcm7xx.usbd[5]", 0xf0835000, 4 * KiB);
472
+ create_unimplemented_device("npcm7xx.usbd[6]", 0xf0836000, 4 * KiB);
473
+ create_unimplemented_device("npcm7xx.usbd[7]", 0xf0837000, 4 * KiB);
474
+ create_unimplemented_device("npcm7xx.usbd[8]", 0xf0838000, 4 * KiB);
475
+ create_unimplemented_device("npcm7xx.usbd[9]", 0xf0839000, 4 * KiB);
476
+ create_unimplemented_device("npcm7xx.sd", 0xf0840000, 8 * KiB);
477
+ create_unimplemented_device("npcm7xx.mmc", 0xf0842000, 8 * KiB);
478
+ create_unimplemented_device("npcm7xx.pcimbx", 0xf0848000, 512 * KiB);
479
+ create_unimplemented_device("npcm7xx.aes", 0xf0858000, 4 * KiB);
480
+ create_unimplemented_device("npcm7xx.des", 0xf0859000, 4 * KiB);
481
+ create_unimplemented_device("npcm7xx.sha", 0xf085a000, 4 * KiB);
482
+ create_unimplemented_device("npcm7xx.secacc", 0xf085b000, 4 * KiB);
483
+ create_unimplemented_device("npcm7xx.spixcs0", 0xf8000000, 16 * MiB);
484
+ create_unimplemented_device("npcm7xx.spixcs1", 0xf9000000, 16 * MiB);
485
+ create_unimplemented_device("npcm7xx.spix", 0xfb001000, 4 * KiB);
486
+}
487
+
488
+static Property npcm7xx_properties[] = {
489
+ DEFINE_PROP_LINK("dram-mr", NPCM7xxState, dram, TYPE_MEMORY_REGION,
490
+ MemoryRegion *),
491
+ DEFINE_PROP_END_OF_LIST(),
492
+};
493
+
494
+static void npcm7xx_class_init(ObjectClass *oc, void *data)
495
+{
496
+ DeviceClass *dc = DEVICE_CLASS(oc);
497
+
498
+ dc->realize = npcm7xx_realize;
499
+ dc->user_creatable = false;
500
+ device_class_set_props(dc, npcm7xx_properties);
501
+}
502
+
503
+static void npcm730_class_init(ObjectClass *oc, void *data)
504
+{
505
+ NPCM7xxClass *nc = NPCM7XX_CLASS(oc);
506
+
507
+ /* NPCM730 is optimized for data center use, so no graphics, etc. */
508
+ nc->disabled_modules = 0x00300395;
509
+ nc->num_cpus = 2;
510
+}
511
+
512
+static void npcm750_class_init(ObjectClass *oc, void *data)
513
+{
514
+ NPCM7xxClass *nc = NPCM7XX_CLASS(oc);
515
+
516
+ /* NPCM750 has 2 cores and a full set of peripherals */
517
+ nc->disabled_modules = 0x00000000;
518
+ nc->num_cpus = 2;
519
+}
520
+
521
+static const TypeInfo npcm7xx_soc_types[] = {
522
+ {
523
+ .name = TYPE_NPCM7XX,
524
+ .parent = TYPE_DEVICE,
525
+ .instance_size = sizeof(NPCM7xxState),
526
+ .instance_init = npcm7xx_init,
527
+ .class_size = sizeof(NPCM7xxClass),
528
+ .class_init = npcm7xx_class_init,
529
+ .abstract = true,
530
+ }, {
531
+ .name = TYPE_NPCM730,
532
+ .parent = TYPE_NPCM7XX,
533
+ .class_init = npcm730_class_init,
534
+ }, {
535
+ .name = TYPE_NPCM750,
536
+ .parent = TYPE_NPCM7XX,
537
+ .class_init = npcm750_class_init,
538
+ },
539
+};
540
+
541
+DEFINE_TYPES(npcm7xx_soc_types);
542
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
46
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
543
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
544
--- a/hw/arm/Kconfig
48
--- a/hw/arm/Kconfig
545
+++ b/hw/arm/Kconfig
49
+++ b/hw/arm/Kconfig
546
@@ -XXX,XX +XXX,XX @@ config XLNX_VERSAL
50
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10
547
51
select ALLWINNER_A10_DRAMC
548
config NPCM7XX
52
select ALLWINNER_EMAC
549
bool
53
select ALLWINNER_I2C
550
+ select A9MPCORE
54
+ select AXP209_PMU
551
+ select ARM_GIC
55
select SERIAL
552
+ select PL310 # cache controller
56
select UNIMP
553
+ select SERIAL
57
554
+ select UNIMP
555
556
config FSL_IMX25
557
bool
558
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
559
index XXXXXXX..XXXXXXX 100644
560
--- a/hw/arm/meson.build
561
+++ b/hw/arm/meson.build
562
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'CONFIG_MICROBIT', if_true: files('microbit.c'))
563
arm_ss.add(when: 'CONFIG_MUSICPAL', if_true: files('musicpal.c'))
564
arm_ss.add(when: 'CONFIG_NETDUINO2', if_true: files('netduino2.c'))
565
arm_ss.add(when: 'CONFIG_NETDUINOPLUS2', if_true: files('netduinoplus2.c'))
566
+arm_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx.c'))
567
arm_ss.add(when: 'CONFIG_NSERIES', if_true: files('nseries.c'))
568
arm_ss.add(when: 'CONFIG_SX1', if_true: files('omap_sx1.c'))
569
arm_ss.add(when: 'CONFIG_CHEETAH', if_true: files('palm.c'))
570
--
58
--
571
2.20.1
59
2.34.1
572
60
573
61
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
2
2
3
The NPCM730 and NPCM750 SoCs have three timer modules each holding five
3
This patch enables copying of SPL from MMC if `-kernel` parameter is not
4
timers and some shared registers (e.g. interrupt status).
4
passed when starting QEMU. SPL is copied to SRAM_A.
5
5
6
Each timer runs at 25 MHz divided by a prescaler, and counts down from a
6
The approach is reused from Allwinner H3 implementation.
7
configurable initial value to zero. When zero is reached, the interrupt
8
flag for the timer is set, and the timer is disabled (one-shot mode) or
9
reloaded from its initial value (periodic mode).
10
7
11
This implementation is sufficient to boot a Linux kernel configured for
8
Tested with Armbian and custom Yocto image.
12
NPCM750. Note that the kernel does not seem to actually turn on the
13
interrupts.
14
9
15
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
10
Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
16
Reviewed-by: Joel Stanley <joel@jms.id.au>
11
17
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
18
Tested-by: Alexander Bulekov <alxndr@bu.edu>
13
Message-id: 20221226220303.14420-7-strahinja.p.jankovic@gmail.com
19
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
21
Message-id: 20200911052101.2602693-4-hskinnemoen@google.com
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
15
---
24
include/hw/timer/npcm7xx_timer.h | 78 +++++
16
include/hw/arm/allwinner-a10.h | 21 +++++++++++++++++++++
25
hw/timer/npcm7xx_timer.c | 543 +++++++++++++++++++++++++++++++
17
hw/arm/allwinner-a10.c | 18 ++++++++++++++++++
26
hw/timer/meson.build | 1 +
18
hw/arm/cubieboard.c | 5 +++++
27
hw/timer/trace-events | 5 +
19
3 files changed, 44 insertions(+)
28
4 files changed, 627 insertions(+)
29
create mode 100644 include/hw/timer/npcm7xx_timer.h
30
create mode 100644 hw/timer/npcm7xx_timer.c
31
20
32
diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h
21
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
33
new file mode 100644
22
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX
23
--- a/include/hw/arm/allwinner-a10.h
35
--- /dev/null
24
+++ b/include/hw/arm/allwinner-a10.h
36
+++ b/include/hw/timer/npcm7xx_timer.h
37
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@
38
+/*
26
#include "hw/misc/allwinner-a10-ccm.h"
39
+ * Nuvoton NPCM7xx Timer Controller
27
#include "hw/misc/allwinner-a10-dramc.h"
28
#include "hw/i2c/allwinner-i2c.h"
29
+#include "sysemu/block-backend.h"
30
31
#include "target/arm/cpu.h"
32
#include "qom/object.h"
33
@@ -XXX,XX +XXX,XX @@ struct AwA10State {
34
OHCISysBusState ohci[AW_A10_NUM_USB];
35
};
36
37
+/**
38
+ * Emulate Boot ROM firmware setup functionality.
40
+ *
39
+ *
41
+ * Copyright 2020 Google LLC
40
+ * A real Allwinner A10 SoC contains a Boot ROM
41
+ * which is the first code that runs right after
42
+ * the SoC is powered on. The Boot ROM is responsible
43
+ * for loading user code (e.g. a bootloader) from any
44
+ * of the supported external devices and writing the
45
+ * downloaded code to internal SRAM. After loading the SoC
46
+ * begins executing the code written to SRAM.
42
+ *
47
+ *
43
+ * This program is free software; you can redistribute it and/or modify it
48
+ * This function emulates the Boot ROM by copying 32 KiB
44
+ * under the terms of the GNU General Public License as published by the
49
+ * of data at offset 8 KiB from the given block device and writes it to
45
+ * Free Software Foundation; either version 2 of the License, or
50
+ * the start of the first internal SRAM memory.
46
+ * (at your option) any later version.
47
+ *
51
+ *
48
+ * This program is distributed in the hope that it will be useful, but WITHOUT
52
+ * @s: Allwinner A10 state object pointer
49
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
53
+ * @blk: Block backend device object pointer
50
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
51
+ * for more details.
52
+ */
54
+ */
53
+#ifndef NPCM7XX_TIMER_H
55
+void allwinner_a10_bootrom_setup(AwA10State *s, BlockBackend *blk);
54
+#define NPCM7XX_TIMER_H
55
+
56
+
56
+#include "exec/memory.h"
57
#endif
57
+#include "hw/sysbus.h"
58
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
58
+#include "qemu/timer.h"
59
index XXXXXXX..XXXXXXX 100644
60
--- a/hw/arm/allwinner-a10.c
61
+++ b/hw/arm/allwinner-a10.c
62
@@ -XXX,XX +XXX,XX @@
63
#include "sysemu/sysemu.h"
64
#include "hw/boards.h"
65
#include "hw/usb/hcd-ohci.h"
66
+#include "hw/loader.h"
67
68
+#define AW_A10_SRAM_A_BASE 0x00000000
69
#define AW_A10_DRAMC_BASE 0x01c01000
70
#define AW_A10_MMC0_BASE 0x01c0f000
71
#define AW_A10_CCM_BASE 0x01c20000
72
@@ -XXX,XX +XXX,XX @@
73
#define AW_A10_RTC_BASE 0x01c20d00
74
#define AW_A10_I2C0_BASE 0x01c2ac00
75
76
+void allwinner_a10_bootrom_setup(AwA10State *s, BlockBackend *blk)
77
+{
78
+ const int64_t rom_size = 32 * KiB;
79
+ g_autofree uint8_t *buffer = g_new0(uint8_t, rom_size);
59
+
80
+
60
+/* Each Timer Module (TIM) instance holds five 25 MHz timers. */
81
+ if (blk_pread(blk, 8 * KiB, rom_size, buffer, 0) < 0) {
61
+#define NPCM7XX_TIMERS_PER_CTRL (5)
82
+ error_setg(&error_fatal, "%s: failed to read BlockBackend data",
62
+
83
+ __func__);
63
+/*
64
+ * Number of registers in our device state structure. Don't change this without
65
+ * incrementing the version_id in the vmstate.
66
+ */
67
+#define NPCM7XX_TIMER_NR_REGS (0x54 / sizeof(uint32_t))
68
+
69
+typedef struct NPCM7xxTimerCtrlState NPCM7xxTimerCtrlState;
70
+
71
+/**
72
+ * struct NPCM7xxTimer - Individual timer state.
73
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
74
+ * @qtimer: QEMU timer that notifies us on expiration.
75
+ * @expires_ns: Absolute virtual expiration time.
76
+ * @remaining_ns: Remaining time until expiration if timer is paused.
77
+ * @tcsr: The Timer Control and Status Register.
78
+ * @ticr: The Timer Initial Count Register.
79
+ */
80
+typedef struct NPCM7xxTimer {
81
+ NPCM7xxTimerCtrlState *ctrl;
82
+
83
+ qemu_irq irq;
84
+ QEMUTimer qtimer;
85
+ int64_t expires_ns;
86
+ int64_t remaining_ns;
87
+
88
+ uint32_t tcsr;
89
+ uint32_t ticr;
90
+} NPCM7xxTimer;
91
+
92
+/**
93
+ * struct NPCM7xxTimerCtrlState - Timer Module device state.
94
+ * @parent: System bus device.
95
+ * @iomem: Memory region through which registers are accessed.
96
+ * @tisr: The Timer Interrupt Status Register.
97
+ * @wtcr: The Watchdog Timer Control Register.
98
+ * @timer: The five individual timers managed by this module.
99
+ */
100
+struct NPCM7xxTimerCtrlState {
101
+ SysBusDevice parent;
102
+
103
+ MemoryRegion iomem;
104
+
105
+ uint32_t tisr;
106
+ uint32_t wtcr;
107
+
108
+ NPCM7xxTimer timer[NPCM7XX_TIMERS_PER_CTRL];
109
+};
110
+
111
+#define TYPE_NPCM7XX_TIMER "npcm7xx-timer"
112
+#define NPCM7XX_TIMER(obj) \
113
+ OBJECT_CHECK(NPCM7xxTimerCtrlState, (obj), TYPE_NPCM7XX_TIMER)
114
+
115
+#endif /* NPCM7XX_TIMER_H */
116
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
117
new file mode 100644
118
index XXXXXXX..XXXXXXX
119
--- /dev/null
120
+++ b/hw/timer/npcm7xx_timer.c
121
@@ -XXX,XX +XXX,XX @@
122
+/*
123
+ * Nuvoton NPCM7xx Timer Controller
124
+ *
125
+ * Copyright 2020 Google LLC
126
+ *
127
+ * This program is free software; you can redistribute it and/or modify it
128
+ * under the terms of the GNU General Public License as published by the
129
+ * Free Software Foundation; either version 2 of the License, or
130
+ * (at your option) any later version.
131
+ *
132
+ * This program is distributed in the hope that it will be useful, but WITHOUT
133
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
134
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
135
+ * for more details.
136
+ */
137
+
138
+#include "qemu/osdep.h"
139
+
140
+#include "hw/irq.h"
141
+#include "hw/misc/npcm7xx_clk.h"
142
+#include "hw/timer/npcm7xx_timer.h"
143
+#include "migration/vmstate.h"
144
+#include "qemu/bitops.h"
145
+#include "qemu/error-report.h"
146
+#include "qemu/log.h"
147
+#include "qemu/module.h"
148
+#include "qemu/timer.h"
149
+#include "qemu/units.h"
150
+#include "trace.h"
151
+
152
+/* 32-bit register indices. */
153
+enum NPCM7xxTimerRegisters {
154
+ NPCM7XX_TIMER_TCSR0,
155
+ NPCM7XX_TIMER_TCSR1,
156
+ NPCM7XX_TIMER_TICR0,
157
+ NPCM7XX_TIMER_TICR1,
158
+ NPCM7XX_TIMER_TDR0,
159
+ NPCM7XX_TIMER_TDR1,
160
+ NPCM7XX_TIMER_TISR,
161
+ NPCM7XX_TIMER_WTCR,
162
+ NPCM7XX_TIMER_TCSR2,
163
+ NPCM7XX_TIMER_TCSR3,
164
+ NPCM7XX_TIMER_TICR2,
165
+ NPCM7XX_TIMER_TICR3,
166
+ NPCM7XX_TIMER_TDR2,
167
+ NPCM7XX_TIMER_TDR3,
168
+ NPCM7XX_TIMER_TCSR4 = 0x0040 / sizeof(uint32_t),
169
+ NPCM7XX_TIMER_TICR4 = 0x0048 / sizeof(uint32_t),
170
+ NPCM7XX_TIMER_TDR4 = 0x0050 / sizeof(uint32_t),
171
+ NPCM7XX_TIMER_REGS_END,
172
+};
173
+
174
+/* Register field definitions. */
175
+#define NPCM7XX_TCSR_CEN BIT(30)
176
+#define NPCM7XX_TCSR_IE BIT(29)
177
+#define NPCM7XX_TCSR_PERIODIC BIT(27)
178
+#define NPCM7XX_TCSR_CRST BIT(26)
179
+#define NPCM7XX_TCSR_CACT BIT(25)
180
+#define NPCM7XX_TCSR_RSVD 0x01ffff00
181
+#define NPCM7XX_TCSR_PRESCALE_START 0
182
+#define NPCM7XX_TCSR_PRESCALE_LEN 8
183
+
184
+/*
185
+ * Returns the index of timer in the tc->timer array. This can be used to
186
+ * locate the registers that belong to this timer.
187
+ */
188
+static int npcm7xx_timer_index(NPCM7xxTimerCtrlState *tc, NPCM7xxTimer *timer)
189
+{
190
+ int index = timer - tc->timer;
191
+
192
+ g_assert(index >= 0 && index < NPCM7XX_TIMERS_PER_CTRL);
193
+
194
+ return index;
195
+}
196
+
197
+/* Return the value by which to divide the reference clock rate. */
198
+static uint32_t npcm7xx_tcsr_prescaler(uint32_t tcsr)
199
+{
200
+ return extract32(tcsr, NPCM7XX_TCSR_PRESCALE_START,
201
+ NPCM7XX_TCSR_PRESCALE_LEN) + 1;
202
+}
203
+
204
+/* Convert a timer cycle count to a time interval in nanoseconds. */
205
+static int64_t npcm7xx_timer_count_to_ns(NPCM7xxTimer *t, uint32_t count)
206
+{
207
+ int64_t ns = count;
208
+
209
+ ns *= NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ;
210
+ ns *= npcm7xx_tcsr_prescaler(t->tcsr);
211
+
212
+ return ns;
213
+}
214
+
215
+/* Convert a time interval in nanoseconds to a timer cycle count. */
216
+static uint32_t npcm7xx_timer_ns_to_count(NPCM7xxTimer *t, int64_t ns)
217
+{
218
+ int64_t count;
219
+
220
+ count = ns / (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ);
221
+ count /= npcm7xx_tcsr_prescaler(t->tcsr);
222
+
223
+ return count;
224
+}
225
+
226
+/*
227
+ * Raise the interrupt line if there's a pending interrupt and interrupts are
228
+ * enabled for this timer. If not, lower it.
229
+ */
230
+static void npcm7xx_timer_check_interrupt(NPCM7xxTimer *t)
231
+{
232
+ NPCM7xxTimerCtrlState *tc = t->ctrl;
233
+ int index = npcm7xx_timer_index(tc, t);
234
+ bool pending = (t->tcsr & NPCM7XX_TCSR_IE) && (tc->tisr & BIT(index));
235
+
236
+ qemu_set_irq(t->irq, pending);
237
+ trace_npcm7xx_timer_irq(DEVICE(tc)->canonical_path, index, pending);
238
+}
239
+
240
+/* Start or resume the timer. */
241
+static void npcm7xx_timer_start(NPCM7xxTimer *t)
242
+{
243
+ int64_t now;
244
+
245
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
246
+ t->expires_ns = now + t->remaining_ns;
247
+ timer_mod(&t->qtimer, t->expires_ns);
248
+}
249
+
250
+/*
251
+ * Called when the counter reaches zero. Sets the interrupt flag, and either
252
+ * restarts or disables the timer.
253
+ */
254
+static void npcm7xx_timer_reached_zero(NPCM7xxTimer *t)
255
+{
256
+ NPCM7xxTimerCtrlState *tc = t->ctrl;
257
+ int index = npcm7xx_timer_index(tc, t);
258
+
259
+ tc->tisr |= BIT(index);
260
+
261
+ if (t->tcsr & NPCM7XX_TCSR_PERIODIC) {
262
+ t->remaining_ns = npcm7xx_timer_count_to_ns(t, t->ticr);
263
+ if (t->tcsr & NPCM7XX_TCSR_CEN) {
264
+ npcm7xx_timer_start(t);
265
+ }
266
+ } else {
267
+ t->tcsr &= ~(NPCM7XX_TCSR_CEN | NPCM7XX_TCSR_CACT);
268
+ }
269
+
270
+ npcm7xx_timer_check_interrupt(t);
271
+}
272
+
273
+/* Stop counting. Record the time remaining so we can continue later. */
274
+static void npcm7xx_timer_pause(NPCM7xxTimer *t)
275
+{
276
+ int64_t now;
277
+
278
+ timer_del(&t->qtimer);
279
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
280
+ t->remaining_ns = t->expires_ns - now;
281
+ if (t->remaining_ns <= 0) {
282
+ npcm7xx_timer_reached_zero(t);
283
+ }
284
+}
285
+
286
+/*
287
+ * Restart the timer from its initial value. If the timer was enabled and stays
288
+ * enabled, adjust the QEMU timer according to the new count. If the timer is
289
+ * transitioning from disabled to enabled, the caller is expected to start the
290
+ * timer later.
291
+ */
292
+static void npcm7xx_timer_restart(NPCM7xxTimer *t, uint32_t old_tcsr)
293
+{
294
+ t->remaining_ns = npcm7xx_timer_count_to_ns(t, t->ticr);
295
+
296
+ if (old_tcsr & t->tcsr & NPCM7XX_TCSR_CEN) {
297
+ npcm7xx_timer_start(t);
298
+ }
299
+}
300
+
301
+/* Register read and write handlers */
302
+
303
+static uint32_t npcm7xx_timer_read_tdr(NPCM7xxTimer *t)
304
+{
305
+ if (t->tcsr & NPCM7XX_TCSR_CEN) {
306
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
307
+
308
+ return npcm7xx_timer_ns_to_count(t, t->expires_ns - now);
309
+ }
310
+
311
+ return npcm7xx_timer_ns_to_count(t, t->remaining_ns);
312
+}
313
+
314
+static void npcm7xx_timer_write_tcsr(NPCM7xxTimer *t, uint32_t new_tcsr)
315
+{
316
+ uint32_t old_tcsr = t->tcsr;
317
+ uint32_t tdr;
318
+
319
+ if (new_tcsr & NPCM7XX_TCSR_RSVD) {
320
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: reserved bits in 0x%08x ignored\n",
321
+ __func__, new_tcsr);
322
+ new_tcsr &= ~NPCM7XX_TCSR_RSVD;
323
+ }
324
+ if (new_tcsr & NPCM7XX_TCSR_CACT) {
325
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: read-only bits in 0x%08x ignored\n",
326
+ __func__, new_tcsr);
327
+ new_tcsr &= ~NPCM7XX_TCSR_CACT;
328
+ }
329
+ if ((new_tcsr & NPCM7XX_TCSR_CRST) && (new_tcsr & NPCM7XX_TCSR_CEN)) {
330
+ qemu_log_mask(LOG_GUEST_ERROR,
331
+ "%s: both CRST and CEN set; ignoring CEN.\n",
332
+ __func__);
333
+ new_tcsr &= ~NPCM7XX_TCSR_CEN;
334
+ }
335
+
336
+ /* Calculate the value of TDR before potentially changing the prescaler. */
337
+ tdr = npcm7xx_timer_read_tdr(t);
338
+
339
+ t->tcsr = (t->tcsr & NPCM7XX_TCSR_CACT) | new_tcsr;
340
+
341
+ if (npcm7xx_tcsr_prescaler(old_tcsr) != npcm7xx_tcsr_prescaler(new_tcsr)) {
342
+ /* Recalculate time remaining based on the current TDR value. */
343
+ t->remaining_ns = npcm7xx_timer_count_to_ns(t, tdr);
344
+ if (old_tcsr & t->tcsr & NPCM7XX_TCSR_CEN) {
345
+ npcm7xx_timer_start(t);
346
+ }
347
+ }
348
+
349
+ if ((old_tcsr ^ new_tcsr) & NPCM7XX_TCSR_IE) {
350
+ npcm7xx_timer_check_interrupt(t);
351
+ }
352
+ if (new_tcsr & NPCM7XX_TCSR_CRST) {
353
+ npcm7xx_timer_restart(t, old_tcsr);
354
+ t->tcsr &= ~NPCM7XX_TCSR_CRST;
355
+ }
356
+ if ((old_tcsr ^ new_tcsr) & NPCM7XX_TCSR_CEN) {
357
+ if (new_tcsr & NPCM7XX_TCSR_CEN) {
358
+ t->tcsr |= NPCM7XX_TCSR_CACT;
359
+ npcm7xx_timer_start(t);
360
+ } else {
361
+ t->tcsr &= ~NPCM7XX_TCSR_CACT;
362
+ npcm7xx_timer_pause(t);
363
+ }
364
+ }
365
+}
366
+
367
+static void npcm7xx_timer_write_ticr(NPCM7xxTimer *t, uint32_t new_ticr)
368
+{
369
+ t->ticr = new_ticr;
370
+
371
+ npcm7xx_timer_restart(t, t->tcsr);
372
+}
373
+
374
+static void npcm7xx_timer_write_tisr(NPCM7xxTimerCtrlState *s, uint32_t value)
375
+{
376
+ int i;
377
+
378
+ s->tisr &= ~value;
379
+ for (i = 0; i < ARRAY_SIZE(s->timer); i++) {
380
+ if (value & (1U << i)) {
381
+ npcm7xx_timer_check_interrupt(&s->timer[i]);
382
+ }
383
+ }
384
+}
385
+
386
+static hwaddr npcm7xx_tcsr_index(hwaddr reg)
387
+{
388
+ switch (reg) {
389
+ case NPCM7XX_TIMER_TCSR0:
390
+ return 0;
391
+ case NPCM7XX_TIMER_TCSR1:
392
+ return 1;
393
+ case NPCM7XX_TIMER_TCSR2:
394
+ return 2;
395
+ case NPCM7XX_TIMER_TCSR3:
396
+ return 3;
397
+ case NPCM7XX_TIMER_TCSR4:
398
+ return 4;
399
+ default:
400
+ g_assert_not_reached();
401
+ }
402
+}
403
+
404
+static hwaddr npcm7xx_ticr_index(hwaddr reg)
405
+{
406
+ switch (reg) {
407
+ case NPCM7XX_TIMER_TICR0:
408
+ return 0;
409
+ case NPCM7XX_TIMER_TICR1:
410
+ return 1;
411
+ case NPCM7XX_TIMER_TICR2:
412
+ return 2;
413
+ case NPCM7XX_TIMER_TICR3:
414
+ return 3;
415
+ case NPCM7XX_TIMER_TICR4:
416
+ return 4;
417
+ default:
418
+ g_assert_not_reached();
419
+ }
420
+}
421
+
422
+static hwaddr npcm7xx_tdr_index(hwaddr reg)
423
+{
424
+ switch (reg) {
425
+ case NPCM7XX_TIMER_TDR0:
426
+ return 0;
427
+ case NPCM7XX_TIMER_TDR1:
428
+ return 1;
429
+ case NPCM7XX_TIMER_TDR2:
430
+ return 2;
431
+ case NPCM7XX_TIMER_TDR3:
432
+ return 3;
433
+ case NPCM7XX_TIMER_TDR4:
434
+ return 4;
435
+ default:
436
+ g_assert_not_reached();
437
+ }
438
+}
439
+
440
+static uint64_t npcm7xx_timer_read(void *opaque, hwaddr offset, unsigned size)
441
+{
442
+ NPCM7xxTimerCtrlState *s = opaque;
443
+ uint64_t value = 0;
444
+ hwaddr reg;
445
+
446
+ reg = offset / sizeof(uint32_t);
447
+ switch (reg) {
448
+ case NPCM7XX_TIMER_TCSR0:
449
+ case NPCM7XX_TIMER_TCSR1:
450
+ case NPCM7XX_TIMER_TCSR2:
451
+ case NPCM7XX_TIMER_TCSR3:
452
+ case NPCM7XX_TIMER_TCSR4:
453
+ value = s->timer[npcm7xx_tcsr_index(reg)].tcsr;
454
+ break;
455
+
456
+ case NPCM7XX_TIMER_TICR0:
457
+ case NPCM7XX_TIMER_TICR1:
458
+ case NPCM7XX_TIMER_TICR2:
459
+ case NPCM7XX_TIMER_TICR3:
460
+ case NPCM7XX_TIMER_TICR4:
461
+ value = s->timer[npcm7xx_ticr_index(reg)].ticr;
462
+ break;
463
+
464
+ case NPCM7XX_TIMER_TDR0:
465
+ case NPCM7XX_TIMER_TDR1:
466
+ case NPCM7XX_TIMER_TDR2:
467
+ case NPCM7XX_TIMER_TDR3:
468
+ case NPCM7XX_TIMER_TDR4:
469
+ value = npcm7xx_timer_read_tdr(&s->timer[npcm7xx_tdr_index(reg)]);
470
+ break;
471
+
472
+ case NPCM7XX_TIMER_TISR:
473
+ value = s->tisr;
474
+ break;
475
+
476
+ case NPCM7XX_TIMER_WTCR:
477
+ value = s->wtcr;
478
+ break;
479
+
480
+ default:
481
+ qemu_log_mask(LOG_GUEST_ERROR,
482
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
483
+ __func__, offset);
484
+ break;
485
+ }
486
+
487
+ trace_npcm7xx_timer_read(DEVICE(s)->canonical_path, offset, value);
488
+
489
+ return value;
490
+}
491
+
492
+static void npcm7xx_timer_write(void *opaque, hwaddr offset,
493
+ uint64_t v, unsigned size)
494
+{
495
+ uint32_t reg = offset / sizeof(uint32_t);
496
+ NPCM7xxTimerCtrlState *s = opaque;
497
+ uint32_t value = v;
498
+
499
+ trace_npcm7xx_timer_write(DEVICE(s)->canonical_path, offset, value);
500
+
501
+ switch (reg) {
502
+ case NPCM7XX_TIMER_TCSR0:
503
+ case NPCM7XX_TIMER_TCSR1:
504
+ case NPCM7XX_TIMER_TCSR2:
505
+ case NPCM7XX_TIMER_TCSR3:
506
+ case NPCM7XX_TIMER_TCSR4:
507
+ npcm7xx_timer_write_tcsr(&s->timer[npcm7xx_tcsr_index(reg)], value);
508
+ return;
509
+
510
+ case NPCM7XX_TIMER_TICR0:
511
+ case NPCM7XX_TIMER_TICR1:
512
+ case NPCM7XX_TIMER_TICR2:
513
+ case NPCM7XX_TIMER_TICR3:
514
+ case NPCM7XX_TIMER_TICR4:
515
+ npcm7xx_timer_write_ticr(&s->timer[npcm7xx_ticr_index(reg)], value);
516
+ return;
517
+
518
+ case NPCM7XX_TIMER_TDR0:
519
+ case NPCM7XX_TIMER_TDR1:
520
+ case NPCM7XX_TIMER_TDR2:
521
+ case NPCM7XX_TIMER_TDR3:
522
+ case NPCM7XX_TIMER_TDR4:
523
+ qemu_log_mask(LOG_GUEST_ERROR,
524
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
525
+ __func__, offset);
526
+ return;
527
+
528
+ case NPCM7XX_TIMER_TISR:
529
+ npcm7xx_timer_write_tisr(s, value);
530
+ return;
531
+
532
+ case NPCM7XX_TIMER_WTCR:
533
+ qemu_log_mask(LOG_UNIMP, "%s: WTCR write not implemented: 0x%08x\n",
534
+ __func__, value);
535
+ return;
84
+ return;
536
+ }
85
+ }
537
+
86
+
538
+ qemu_log_mask(LOG_GUEST_ERROR,
87
+ rom_add_blob("allwinner-a10.bootrom", buffer, rom_size,
539
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
88
+ rom_size, AW_A10_SRAM_A_BASE,
540
+ __func__, offset);
89
+ NULL, NULL, NULL, NULL, false);
541
+}
90
+}
542
+
91
+
543
+static const struct MemoryRegionOps npcm7xx_timer_ops = {
92
static void aw_a10_init(Object *obj)
544
+ .read = npcm7xx_timer_read,
93
{
545
+ .write = npcm7xx_timer_write,
94
AwA10State *s = AW_A10(obj);
546
+ .endianness = DEVICE_LITTLE_ENDIAN,
95
diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
547
+ .valid = {
96
index XXXXXXX..XXXXXXX 100644
548
+ .min_access_size = 4,
97
--- a/hw/arm/cubieboard.c
549
+ .max_access_size = 4,
98
+++ b/hw/arm/cubieboard.c
550
+ .unaligned = false,
99
@@ -XXX,XX +XXX,XX @@ static void cubieboard_init(MachineState *machine)
551
+ },
100
memory_region_add_subregion(get_system_memory(), AW_A10_SDRAM_BASE,
552
+};
101
machine->ram);
553
+
102
554
+/* Called when the QEMU timer expires. */
103
+ /* Load target kernel or start using BootROM */
555
+static void npcm7xx_timer_expired(void *opaque)
104
+ if (!machine->kernel_filename && blk && blk_is_available(blk)) {
556
+{
105
+ /* Use Boot ROM to copy data from SD card to SRAM */
557
+ NPCM7xxTimer *t = opaque;
106
+ allwinner_a10_bootrom_setup(a10, blk);
558
+
559
+ if (t->tcsr & NPCM7XX_TCSR_CEN) {
560
+ npcm7xx_timer_reached_zero(t);
561
+ }
107
+ }
562
+}
108
/* TODO create and connect IDE devices for ide_drive_get() */
563
+
109
564
+static void npcm7xx_timer_enter_reset(Object *obj, ResetType type)
110
cubieboard_binfo.ram_size = machine->ram_size;
565
+{
566
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(obj);
567
+ int i;
568
+
569
+ for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) {
570
+ NPCM7xxTimer *t = &s->timer[i];
571
+
572
+ timer_del(&t->qtimer);
573
+ t->expires_ns = 0;
574
+ t->remaining_ns = 0;
575
+ t->tcsr = 0x00000005;
576
+ t->ticr = 0x00000000;
577
+ }
578
+
579
+ s->tisr = 0x00000000;
580
+ s->wtcr = 0x00000400;
581
+}
582
+
583
+static void npcm7xx_timer_hold_reset(Object *obj)
584
+{
585
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(obj);
586
+ int i;
587
+
588
+ for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) {
589
+ qemu_irq_lower(s->timer[i].irq);
590
+ }
591
+}
592
+
593
+static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
594
+{
595
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(dev);
596
+ SysBusDevice *sbd = &s->parent;
597
+ int i;
598
+
599
+ for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) {
600
+ NPCM7xxTimer *t = &s->timer[i];
601
+ t->ctrl = s;
602
+ timer_init_ns(&t->qtimer, QEMU_CLOCK_VIRTUAL, npcm7xx_timer_expired, t);
603
+ sysbus_init_irq(sbd, &t->irq);
604
+ }
605
+
606
+ memory_region_init_io(&s->iomem, OBJECT(s), &npcm7xx_timer_ops, s,
607
+ TYPE_NPCM7XX_TIMER, 4 * KiB);
608
+ sysbus_init_mmio(sbd, &s->iomem);
609
+}
610
+
611
+static const VMStateDescription vmstate_npcm7xx_timer = {
612
+ .name = "npcm7xx-timer",
613
+ .version_id = 0,
614
+ .minimum_version_id = 0,
615
+ .fields = (VMStateField[]) {
616
+ VMSTATE_TIMER(qtimer, NPCM7xxTimer),
617
+ VMSTATE_INT64(expires_ns, NPCM7xxTimer),
618
+ VMSTATE_INT64(remaining_ns, NPCM7xxTimer),
619
+ VMSTATE_UINT32(tcsr, NPCM7xxTimer),
620
+ VMSTATE_UINT32(ticr, NPCM7xxTimer),
621
+ VMSTATE_END_OF_LIST(),
622
+ },
623
+};
624
+
625
+static const VMStateDescription vmstate_npcm7xx_timer_ctrl = {
626
+ .name = "npcm7xx-timer-ctrl",
627
+ .version_id = 0,
628
+ .minimum_version_id = 0,
629
+ .fields = (VMStateField[]) {
630
+ VMSTATE_UINT32(tisr, NPCM7xxTimerCtrlState),
631
+ VMSTATE_UINT32(wtcr, NPCM7xxTimerCtrlState),
632
+ VMSTATE_STRUCT_ARRAY(timer, NPCM7xxTimerCtrlState,
633
+ NPCM7XX_TIMERS_PER_CTRL, 0, vmstate_npcm7xx_timer,
634
+ NPCM7xxTimer),
635
+ VMSTATE_END_OF_LIST(),
636
+ },
637
+};
638
+
639
+static void npcm7xx_timer_class_init(ObjectClass *klass, void *data)
640
+{
641
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
642
+ DeviceClass *dc = DEVICE_CLASS(klass);
643
+
644
+ QEMU_BUILD_BUG_ON(NPCM7XX_TIMER_REGS_END > NPCM7XX_TIMER_NR_REGS);
645
+
646
+ dc->desc = "NPCM7xx Timer Controller";
647
+ dc->realize = npcm7xx_timer_realize;
648
+ dc->vmsd = &vmstate_npcm7xx_timer_ctrl;
649
+ rc->phases.enter = npcm7xx_timer_enter_reset;
650
+ rc->phases.hold = npcm7xx_timer_hold_reset;
651
+}
652
+
653
+static const TypeInfo npcm7xx_timer_info = {
654
+ .name = TYPE_NPCM7XX_TIMER,
655
+ .parent = TYPE_SYS_BUS_DEVICE,
656
+ .instance_size = sizeof(NPCM7xxTimerCtrlState),
657
+ .class_init = npcm7xx_timer_class_init,
658
+};
659
+
660
+static void npcm7xx_timer_register_type(void)
661
+{
662
+ type_register_static(&npcm7xx_timer_info);
663
+}
664
+type_init(npcm7xx_timer_register_type);
665
diff --git a/hw/timer/meson.build b/hw/timer/meson.build
666
index XXXXXXX..XXXXXXX 100644
667
--- a/hw/timer/meson.build
668
+++ b/hw/timer/meson.build
669
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_LM32', if_true: files('lm32_timer.c'))
670
softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-sysctl.c'))
671
softmmu_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_gictimer.c'))
672
softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('mss-timer.c'))
673
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_timer.c'))
674
softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_timer.c'))
675
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_gptimer.c'))
676
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_synctimer.c'))
677
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
678
index XXXXXXX..XXXXXXX 100644
679
--- a/hw/timer/trace-events
680
+++ b/hw/timer/trace-events
681
@@ -XXX,XX +XXX,XX @@ cmsdk_apb_dualtimer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK A
682
cmsdk_apb_dualtimer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB dualtimer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
683
cmsdk_apb_dualtimer_reset(void) "CMSDK APB dualtimer: reset"
684
685
+# npcm7xx_timer.c
686
+npcm7xx_timer_read(const char *id, uint64_t offset, uint64_t value) " %s offset: 0x%04" PRIx64 " value 0x%08" PRIx64
687
+npcm7xx_timer_write(const char *id, uint64_t offset, uint64_t value) "%s offset: 0x%04" PRIx64 " value 0x%08" PRIx64
688
+npcm7xx_timer_irq(const char *id, int timer, int state) "%s timer %d state %d"
689
+
690
# nrf51_timer.c
691
nrf51_timer_read(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size) "timer %u read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
692
nrf51_timer_write(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size) "timer %u write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
693
--
111
--
694
2.20.1
112
2.34.1
695
696
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
2
2
3
This adds two acceptance tests for the quanta-gsj machine.
3
Cubieboard now can boot directly from SD card, without the need to pass
4
`-kernel` parameter. Update Avocado tests to cover this functionality.
4
5
5
One test downloads a lightly patched openbmc flash image from github and
6
Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
6
verifies that it boots all the way to the login prompt.
7
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
7
8
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
8
The other test downloads a kernel, initrd and dtb built from the same
9
Message-id: 20221226220303.14420-8-strahinja.p.jankovic@gmail.com
9
openbmc source and verifies that the kernel detects all CPUs and boots
10
to the point where it can't find the root filesystem (because we have no
11
flash image in this case).
12
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
16
Message-id: 20200911052101.2602693-15-hskinnemoen@google.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
11
---
19
tests/acceptance/boot_linux_console.py | 83 ++++++++++++++++++++++++++
12
tests/avocado/boot_linux_console.py | 47 +++++++++++++++++++++++++++++
20
1 file changed, 83 insertions(+)
13
1 file changed, 47 insertions(+)
21
14
22
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
15
diff --git a/tests/avocado/boot_linux_console.py b/tests/avocado/boot_linux_console.py
23
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
24
--- a/tests/acceptance/boot_linux_console.py
17
--- a/tests/avocado/boot_linux_console.py
25
+++ b/tests/acceptance/boot_linux_console.py
18
+++ b/tests/avocado/boot_linux_console.py
26
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(LinuxKernelTest):
19
@@ -XXX,XX +XXX,XX @@ def test_arm_cubieboard_sata(self):
27
'sda')
20
'sda')
28
# cubieboard's reboot is not functioning; omit reboot test.
21
# cubieboard's reboot is not functioning; omit reboot test.
29
22
30
+ def test_arm_quanta_gsj(self):
23
+ @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
24
+ def test_arm_cubieboard_openwrt_22_03_2(self):
31
+ """
25
+ """
32
+ :avocado: tags=arch:arm
26
+ :avocado: tags=arch:arm
33
+ :avocado: tags=machine:quanta-gsj
27
+ :avocado: tags=machine:cubieboard
28
+ :avocado: tags=device:sd
34
+ """
29
+ """
35
+ # 25 MiB compressed, 32 MiB uncompressed.
30
+
36
+ image_url = (
31
+ # This test download a 7.5 MiB compressed image and expand it
37
+ 'https://github.com/hskinnemoen/openbmc/releases/download/'
32
+ # to 126 MiB.
38
+ '20200711-gsj-qemu-0/obmc-phosphor-image-gsj.static.mtd.gz')
33
+ image_url = ('https://downloads.openwrt.org/releases/22.03.2/targets/'
39
+ image_hash = '14895e634923345cb5c8776037ff7876df96f6b1'
34
+ 'sunxi/cortexa8/openwrt-22.03.2-sunxi-cortexa8-'
40
+ image_path_gz = self.fetch_asset(image_url, asset_hash=image_hash)
35
+ 'cubietech_a10-cubieboard-ext4-sdcard.img.gz')
41
+ image_name = 'obmc.mtd'
36
+ image_hash = ('94b5ecbfbc0b3b56276e5146b899eafa'
42
+ image_path = os.path.join(self.workdir, image_name)
37
+ '2ac5dc2d08733d6705af9f144f39f554')
43
+ archive.gzip_uncompress(image_path_gz, image_path)
38
+ image_path_gz = self.fetch_asset(image_url, asset_hash=image_hash,
39
+ algorithm='sha256')
40
+ image_path = archive.extract(image_path_gz, self.workdir)
41
+ image_pow2ceil_expand(image_path)
44
+
42
+
45
+ self.vm.set_console()
43
+ self.vm.set_console()
46
+ drive_args = 'file=' + image_path + ',if=mtd,bus=0,unit=0'
44
+ self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw',
47
+ self.vm.add_args('-drive', drive_args)
45
+ '-nic', 'user',
46
+ '-no-reboot')
48
+ self.vm.launch()
47
+ self.vm.launch()
49
+
48
+
50
+ # Disable drivers and services that stall for a long time during boot,
49
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
51
+ # to avoid running past the 90-second timeout. These may be removed
50
+ 'usbcore.nousb '
52
+ # as the corresponding device support is added.
51
+ 'noreboot')
53
+ kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + (
54
+ 'console=${console} '
55
+ 'mem=${mem} '
56
+ 'initcall_blacklist=npcm_i2c_bus_driver_init '
57
+ 'systemd.mask=systemd-random-seed.service '
58
+ 'systemd.mask=dropbearkey.service '
59
+ )
60
+
52
+
61
+ self.wait_for_console_pattern('> BootBlock by Nuvoton')
53
+ self.wait_for_console_pattern('U-Boot SPL')
62
+ self.wait_for_console_pattern('>Device: Poleg BMC NPCM730')
54
+
63
+ self.wait_for_console_pattern('>Skip DDR init.')
64
+ self.wait_for_console_pattern('U-Boot ')
65
+ interrupt_interactive_console_until_pattern(
55
+ interrupt_interactive_console_until_pattern(
66
+ self, 'Hit any key to stop autoboot:', 'U-Boot>')
56
+ self, 'Hit any key to stop autoboot:', '=>')
67
+ exec_command_and_wait_for_pattern(
57
+ exec_command_and_wait_for_pattern(self, "setenv extraargs '" +
68
+ self, "setenv bootargs ${bootargs} " + kernel_command_line,
58
+ kernel_command_line + "'", '=>')
69
+ 'U-Boot>')
59
+ exec_command_and_wait_for_pattern(self, 'boot', 'Starting kernel ...');
70
+ exec_command_and_wait_for_pattern(
71
+ self, 'run romboot', 'Booting Kernel from flash')
72
+ self.wait_for_console_pattern('Booting Linux on physical CPU 0x0')
73
+ self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0')
74
+ self.wait_for_console_pattern('OpenBMC Project Reference Distro')
75
+ self.wait_for_console_pattern('gsj login:')
76
+
60
+
77
+ def test_arm_quanta_gsj_initrd(self):
61
+ self.wait_for_console_pattern(
78
+ """
62
+ 'Please press Enter to activate this console.')
79
+ :avocado: tags=arch:arm
80
+ :avocado: tags=machine:quanta-gsj
81
+ """
82
+ initrd_url = (
83
+ 'https://github.com/hskinnemoen/openbmc/releases/download/'
84
+ '20200711-gsj-qemu-0/obmc-phosphor-initramfs-gsj.cpio.xz')
85
+ initrd_hash = '98fefe5d7e56727b1eb17d5c00311b1b5c945300'
86
+ initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
87
+ kernel_url = (
88
+ 'https://github.com/hskinnemoen/openbmc/releases/download/'
89
+ '20200711-gsj-qemu-0/uImage-gsj.bin')
90
+ kernel_hash = 'fa67b2f141d56d39b3c54305c0e8a899c99eb2c7'
91
+ kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
92
+ dtb_url = (
93
+ 'https://github.com/hskinnemoen/openbmc/releases/download/'
94
+ '20200711-gsj-qemu-0/nuvoton-npcm730-gsj.dtb')
95
+ dtb_hash = '18315f7006d7b688d8312d5c727eecd819aa36a4'
96
+ dtb_path = self.fetch_asset(dtb_url, asset_hash=dtb_hash)
97
+
63
+
98
+ self.vm.set_console()
64
+ exec_command_and_wait_for_pattern(self, ' ', 'root@')
99
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
100
+ 'console=ttyS0,115200n8 '
101
+ 'earlycon=uart8250,mmio32,0xf0001000')
102
+ self.vm.add_args('-kernel', kernel_path,
103
+ '-initrd', initrd_path,
104
+ '-dtb', dtb_path,
105
+ '-append', kernel_command_line)
106
+ self.vm.launch()
107
+
65
+
108
+ self.wait_for_console_pattern('Booting Linux on physical CPU 0x0')
66
+ exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
109
+ self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0')
67
+ 'Allwinner sun4i/sun5i')
110
+ self.wait_for_console_pattern(
68
+ # cubieboard's reboot is not functioning; omit reboot test.
111
+ 'Give root password for system maintenance')
112
+
69
+
113
def test_arm_orangepi(self):
70
@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout')
71
def test_arm_quanta_gsj(self):
114
"""
72
"""
115
:avocado: tags=arch:arm
116
--
73
--
117
2.20.1
74
2.34.1
118
119
diff view generated by jsdifflib
1
Convert the insns using the 2reg_vcvt and 2reg_vcvt_f16 formats
1
From: Richard Henderson <richard.henderson@linaro.org>
2
to pass the size through to the trans function as a MO_* value
3
rather than the '0==f32, 1==f16' used in the fp 3-same encodings.
4
2
3
Don't dereference CPUTLBEntryFull until we verify that
4
the page is valid. Move the other user-only info field
5
updates after the valid check to match.
6
7
Cc: qemu-stable@nongnu.org
8
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1412
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Message-id: 20230104190056.305143-1-richard.henderson@linaro.org
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: 20200903133209.5141-3-peter.maydell@linaro.org
8
---
13
---
9
target/arm/neon-dp.decode | 3 +--
14
target/arm/sve_helper.c | 14 +++++++++-----
10
target/arm/translate-neon.c.inc | 4 ++--
15
1 file changed, 9 insertions(+), 5 deletions(-)
11
2 files changed, 3 insertions(+), 4 deletions(-)
12
16
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
17
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
19
--- a/target/arm/sve_helper.c
16
+++ b/target/arm/neon-dp.decode
20
+++ b/target/arm/sve_helper.c
17
@@ -XXX,XX +XXX,XX @@ VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
21
@@ -XXX,XX +XXX,XX @@ bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env,
18
@2reg_shll_b .... ... . . . 001 shift:3 .... .... 0 . . . .... \
22
#ifdef CONFIG_USER_ONLY
19
&2reg_shift vm=%vm_dp vd=%vd_dp size=0 q=0
23
flags = probe_access_flags(env, addr, access_type, mmu_idx, nofault,
20
24
&info->host, retaddr);
21
-# We use size=0 for fp32 and size=1 for fp16 to match the 3-same encodings.
25
- memset(&info->attrs, 0, sizeof(info->attrs));
22
@2reg_vcvt .... ... . . . 1 ..... .... .... . q:1 . . .... \
26
- /* Require both ANON and MTE; see allocation_tag_mem(). */
23
- &2reg_shift vm=%vm_dp vd=%vd_dp size=0 shift=%neon_rshift_i5
27
- info->tagged = (flags & PAGE_ANON) && (flags & PAGE_MTE);
24
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=2 shift=%neon_rshift_i5
28
#else
25
@2reg_vcvt_f16 .... ... . . . 11 .... .... .... . q:1 . . .... \
29
CPUTLBEntryFull *full;
26
&2reg_shift vm=%vm_dp vd=%vd_dp size=1 shift=%neon_rshift_i4
30
flags = probe_access_full(env, addr, access_type, mmu_idx, nofault,
27
31
&info->host, &full, retaddr);
28
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
32
- info->attrs = full->attrs;
29
index XXXXXXX..XXXXXXX 100644
33
- info->tagged = full->pte_attrs == 0xf0;
30
--- a/target/arm/translate-neon.c.inc
34
#endif
31
+++ b/target/arm/translate-neon.c.inc
35
info->flags = flags;
32
@@ -XXX,XX +XXX,XX @@ static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
36
37
@@ -XXX,XX +XXX,XX @@ bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env,
33
return false;
38
return false;
34
}
39
}
35
40
36
- if (a->size != 0) {
41
+#ifdef CONFIG_USER_ONLY
37
+ if (a->size == MO_16) {
42
+ memset(&info->attrs, 0, sizeof(info->attrs));
38
if (!dc_isar_feature(aa32_fp16_arith, s)) {
43
+ /* Require both ANON and MTE; see allocation_tag_mem(). */
39
return false;
44
+ info->tagged = (flags & PAGE_ANON) && (flags & PAGE_MTE);
40
}
45
+#else
41
@@ -XXX,XX +XXX,XX @@ static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
46
+ info->attrs = full->attrs;
42
return true;
47
+ info->tagged = full->pte_attrs == 0xf0;
43
}
48
+#endif
44
49
+
45
- fpst = fpstatus_ptr(a->size ? FPST_STD_F16 : FPST_STD);
50
/* Ensure that info->host[] is relative to addr, not addr + mem_off. */
46
+ fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
51
info->host -= mem_off;
47
tcg_gen_gvec_2_ptr(rd_ofs, rm_ofs, fpst, vec_size, vec_size, a->shift, fn);
48
tcg_temp_free_ptr(fpst);
49
return true;
52
return true;
50
--
53
--
51
2.20.1
54
2.34.1
52
55
53
56
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
3
Since pxa255_init() must map the device in the system memory,
4
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
4
there is no point in passing get_system_memory() by argument.
5
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
5
6
Message-id: 1597278668-339715-5-git-send-email-fnu.vikram@xilinx.com
6
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230109115316.2235-2-philmd@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
10
---
9
MAINTAINERS | 8 ++++++++
11
include/hw/arm/pxa.h | 2 +-
10
1 file changed, 8 insertions(+)
12
hw/arm/gumstix.c | 3 +--
13
hw/arm/pxa2xx.c | 4 +++-
14
hw/arm/tosa.c | 2 +-
15
4 files changed, 6 insertions(+), 5 deletions(-)
11
16
12
diff --git a/MAINTAINERS b/MAINTAINERS
17
diff --git a/include/hw/arm/pxa.h b/include/hw/arm/pxa.h
13
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
14
--- a/MAINTAINERS
19
--- a/include/hw/arm/pxa.h
15
+++ b/MAINTAINERS
20
+++ b/include/hw/arm/pxa.h
16
@@ -XXX,XX +XXX,XX @@ F: hw/net/opencores_eth.c
21
@@ -XXX,XX +XXX,XX @@ struct PXA2xxI2SState {
17
22
18
Devices
23
PXA2xxState *pxa270_init(MemoryRegion *address_space, unsigned int sdram_size,
19
-------
24
const char *revision);
20
+Xilinx CAN
25
-PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size);
21
+M: Vikram Garhwal <fnu.vikram@xilinx.com>
26
+PXA2xxState *pxa255_init(unsigned int sdram_size);
22
+M: Francisco Iglesias <francisco.iglesias@xilinx.com>
27
23
+S: Maintained
28
#endif /* PXA_H */
24
+F: hw/net/can/xlnx-*
29
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
25
+F: include/hw/net/xlnx-*
30
index XXXXXXX..XXXXXXX 100644
26
+F: tests/qtest/xlnx-can-test*
31
--- a/hw/arm/gumstix.c
27
+
32
+++ b/hw/arm/gumstix.c
28
EDU
33
@@ -XXX,XX +XXX,XX @@ static void connex_init(MachineState *machine)
29
M: Jiri Slaby <jslaby@suse.cz>
34
{
30
S: Maintained
35
PXA2xxState *cpu;
36
DriveInfo *dinfo;
37
- MemoryRegion *address_space_mem = get_system_memory();
38
39
uint32_t connex_rom = 0x01000000;
40
uint32_t connex_ram = 0x04000000;
41
42
- cpu = pxa255_init(address_space_mem, connex_ram);
43
+ cpu = pxa255_init(connex_ram);
44
45
dinfo = drive_get(IF_PFLASH, 0, 0);
46
if (!dinfo && !qtest_enabled()) {
47
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/arm/pxa2xx.c
50
+++ b/hw/arm/pxa2xx.c
51
@@ -XXX,XX +XXX,XX @@
52
#include "qemu/error-report.h"
53
#include "qemu/module.h"
54
#include "qapi/error.h"
55
+#include "exec/address-spaces.h"
56
#include "cpu.h"
57
#include "hw/sysbus.h"
58
#include "migration/vmstate.h"
59
@@ -XXX,XX +XXX,XX @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
60
}
61
62
/* Initialise a PXA255 integrated chip (ARM based core). */
63
-PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
64
+PXA2xxState *pxa255_init(unsigned int sdram_size)
65
{
66
+ MemoryRegion *address_space = get_system_memory();
67
PXA2xxState *s;
68
int i;
69
DriveInfo *dinfo;
70
diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/hw/arm/tosa.c
73
+++ b/hw/arm/tosa.c
74
@@ -XXX,XX +XXX,XX @@ static void tosa_init(MachineState *machine)
75
TC6393xbState *tmio;
76
DeviceState *scp0, *scp1;
77
78
- mpu = pxa255_init(address_space_mem, tosa_binfo.ram_size);
79
+ mpu = pxa255_init(tosa_binfo.ram_size);
80
81
memory_region_init_rom(rom, NULL, "tosa.rom", TOSA_ROM, &error_fatal);
82
memory_region_add_subregion(address_space_mem, 0, rom);
31
--
83
--
32
2.20.1
84
2.34.1
33
85
34
86
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
This supports reading and writing OTP fuses and keys. Only fuse reading
3
Since pxa270_init() must map the device in the system memory,
4
has been tested. Protection is not implemented.
4
there is no point in passing get_system_memory() by argument.
5
5
6
Reviewed-by: Avi Fishman <avi.fishman@nuvoton.com>
6
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20230109115316.2235-3-philmd@linaro.org
9
Tested-by: Alexander Bulekov <alxndr@bu.edu>
10
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
11
Message-id: 20200911052101.2602693-9-hskinnemoen@google.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
10
---
14
include/hw/arm/npcm7xx.h | 3 +
11
include/hw/arm/pxa.h | 3 +--
15
include/hw/nvram/npcm7xx_otp.h | 79 ++++++
12
hw/arm/gumstix.c | 3 +--
16
hw/arm/npcm7xx.c | 29 +++
13
hw/arm/mainstone.c | 10 ++++------
17
hw/nvram/npcm7xx_otp.c | 440 +++++++++++++++++++++++++++++++++
14
hw/arm/pxa2xx.c | 4 ++--
18
hw/nvram/meson.build | 1 +
15
hw/arm/spitz.c | 6 ++----
19
5 files changed, 552 insertions(+)
16
hw/arm/z2.c | 3 +--
20
create mode 100644 include/hw/nvram/npcm7xx_otp.h
17
6 files changed, 11 insertions(+), 18 deletions(-)
21
create mode 100644 hw/nvram/npcm7xx_otp.c
22
18
23
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
19
diff --git a/include/hw/arm/pxa.h b/include/hw/arm/pxa.h
24
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/npcm7xx.h
21
--- a/include/hw/arm/pxa.h
26
+++ b/include/hw/arm/npcm7xx.h
22
+++ b/include/hw/arm/pxa.h
27
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ struct PXA2xxI2SState {
28
#include "hw/cpu/a9mpcore.h"
24
29
#include "hw/misc/npcm7xx_clk.h"
25
# define PA_FMT            "0x%08lx"
30
#include "hw/misc/npcm7xx_gcr.h"
26
31
+#include "hw/nvram/npcm7xx_otp.h"
27
-PXA2xxState *pxa270_init(MemoryRegion *address_space, unsigned int sdram_size,
32
#include "hw/timer/npcm7xx_timer.h"
28
- const char *revision);
33
#include "target/arm/cpu.h"
29
+PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision);
34
30
PXA2xxState *pxa255_init(unsigned int sdram_size);
35
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
31
36
NPCM7xxGCRState gcr;
32
#endif /* PXA_H */
37
NPCM7xxCLKState clk;
33
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
38
NPCM7xxTimerCtrlState tim[3];
39
+ NPCM7xxOTPState key_storage;
40
+ NPCM7xxOTPState fuse_array;
41
} NPCM7xxState;
42
43
#define TYPE_NPCM7XX "npcm7xx"
44
diff --git a/include/hw/nvram/npcm7xx_otp.h b/include/hw/nvram/npcm7xx_otp.h
45
new file mode 100644
46
index XXXXXXX..XXXXXXX
47
--- /dev/null
48
+++ b/include/hw/nvram/npcm7xx_otp.h
49
@@ -XXX,XX +XXX,XX @@
50
+/*
51
+ * Nuvoton NPCM7xx OTP (Fuse Array) Interface
52
+ *
53
+ * Copyright 2020 Google LLC
54
+ *
55
+ * This program is free software; you can redistribute it and/or modify it
56
+ * under the terms of the GNU General Public License as published by the
57
+ * Free Software Foundation; either version 2 of the License, or
58
+ * (at your option) any later version.
59
+ *
60
+ * This program is distributed in the hope that it will be useful, but WITHOUT
61
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
62
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
63
+ * for more details.
64
+ */
65
+#ifndef NPCM7XX_OTP_H
66
+#define NPCM7XX_OTP_H
67
+
68
+#include "exec/memory.h"
69
+#include "hw/sysbus.h"
70
+
71
+/* Each OTP module holds 8192 bits of one-time programmable storage */
72
+#define NPCM7XX_OTP_ARRAY_BITS (8192)
73
+#define NPCM7XX_OTP_ARRAY_BYTES (NPCM7XX_OTP_ARRAY_BITS / BITS_PER_BYTE)
74
+
75
+/* Fuse array offsets */
76
+#define NPCM7XX_FUSE_FUSTRAP (0)
77
+#define NPCM7XX_FUSE_CP_FUSTRAP (12)
78
+#define NPCM7XX_FUSE_DAC_CALIB (16)
79
+#define NPCM7XX_FUSE_ADC_CALIB (24)
80
+#define NPCM7XX_FUSE_DERIVATIVE (64)
81
+#define NPCM7XX_FUSE_TEST_SIG (72)
82
+#define NPCM7XX_FUSE_DIE_LOCATION (74)
83
+#define NPCM7XX_FUSE_GP1 (80)
84
+#define NPCM7XX_FUSE_GP2 (128)
85
+
86
+/*
87
+ * Number of registers in our device state structure. Don't change this without
88
+ * incrementing the version_id in the vmstate.
89
+ */
90
+#define NPCM7XX_OTP_NR_REGS (0x18 / sizeof(uint32_t))
91
+
92
+/**
93
+ * struct NPCM7xxOTPState - Device state for one OTP module.
94
+ * @parent: System bus device.
95
+ * @mmio: Memory region through which registers are accessed.
96
+ * @regs: Register contents.
97
+ * @array: OTP storage array.
98
+ */
99
+typedef struct NPCM7xxOTPState {
100
+ SysBusDevice parent;
101
+
102
+ MemoryRegion mmio;
103
+ uint32_t regs[NPCM7XX_OTP_NR_REGS];
104
+ uint8_t array[NPCM7XX_OTP_ARRAY_BYTES];
105
+} NPCM7xxOTPState;
106
+
107
+#define TYPE_NPCM7XX_OTP "npcm7xx-otp"
108
+#define NPCM7XX_OTP(obj) OBJECT_CHECK(NPCM7xxOTPState, (obj), TYPE_NPCM7XX_OTP)
109
+
110
+#define TYPE_NPCM7XX_KEY_STORAGE "npcm7xx-key-storage"
111
+#define TYPE_NPCM7XX_FUSE_ARRAY "npcm7xx-fuse-array"
112
+
113
+typedef struct NPCM7xxOTPClass NPCM7xxOTPClass;
114
+
115
+/**
116
+ * npcm7xx_otp_array_write - ECC encode and write data to OTP array.
117
+ * @s: OTP module.
118
+ * @data: Data to be encoded and written.
119
+ * @offset: Offset of first byte to be written in the OTP array.
120
+ * @len: Number of bytes before ECC encoding.
121
+ *
122
+ * Each nibble of data is encoded into a byte, so the number of bytes written
123
+ * to the array will be @len * 2.
124
+ */
125
+extern void npcm7xx_otp_array_write(NPCM7xxOTPState *s, const void *data,
126
+ unsigned int offset, unsigned int len);
127
+
128
+#endif /* NPCM7XX_OTP_H */
129
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
130
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
131
--- a/hw/arm/npcm7xx.c
35
--- a/hw/arm/gumstix.c
132
+++ b/hw/arm/npcm7xx.c
36
+++ b/hw/arm/gumstix.c
133
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@ static void verdex_init(MachineState *machine)
134
#define NPCM7XX_MMIO_BA (0x80000000)
38
{
135
#define NPCM7XX_MMIO_SZ (0x7ffd0000)
39
PXA2xxState *cpu;
136
40
DriveInfo *dinfo;
137
+/* OTP key storage and fuse strap array */
41
- MemoryRegion *address_space_mem = get_system_memory();
138
+#define NPCM7XX_OTP1_BA (0xf0189000)
42
139
+#define NPCM7XX_OTP2_BA (0xf018a000)
43
uint32_t verdex_rom = 0x02000000;
140
+
44
uint32_t verdex_ram = 0x10000000;
141
/* Core system modules. */
45
142
#define NPCM7XX_L2C_BA (0xf03fc000)
46
- cpu = pxa270_init(address_space_mem, verdex_ram, machine->cpu_type);
143
#define NPCM7XX_CPUP_BA (0xf03fe000)
47
+ cpu = pxa270_init(verdex_ram, machine->cpu_type);
144
@@ -XXX,XX +XXX,XX @@ void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
48
145
arm_load_kernel(&soc->cpu[0], machine, &npcm7xx_binfo);
49
dinfo = drive_get(IF_PFLASH, 0, 0);
50
if (!dinfo && !qtest_enabled()) {
51
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/hw/arm/mainstone.c
54
+++ b/hw/arm/mainstone.c
55
@@ -XXX,XX +XXX,XX @@ static struct arm_boot_info mainstone_binfo = {
56
.ram_size = 0x04000000,
57
};
58
59
-static void mainstone_common_init(MemoryRegion *address_space_mem,
60
- MachineState *machine,
61
+static void mainstone_common_init(MachineState *machine,
62
enum mainstone_model_e model, int arm_id)
63
{
64
uint32_t sector_len = 256 * 1024;
65
@@ -XXX,XX +XXX,XX @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
66
MemoryRegion *rom = g_new(MemoryRegion, 1);
67
68
/* Setup CPU & memory */
69
- mpu = pxa270_init(address_space_mem, mainstone_binfo.ram_size,
70
- machine->cpu_type);
71
+ mpu = pxa270_init(mainstone_binfo.ram_size, machine->cpu_type);
72
memory_region_init_rom(rom, NULL, "mainstone.rom", MAINSTONE_ROM,
73
&error_fatal);
74
- memory_region_add_subregion(address_space_mem, 0, rom);
75
+ memory_region_add_subregion(get_system_memory(), 0x00000000, rom);
76
77
/* There are two 32MiB flash devices on the board */
78
for (i = 0; i < 2; i ++) {
79
@@ -XXX,XX +XXX,XX @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
80
81
static void mainstone_init(MachineState *machine)
82
{
83
- mainstone_common_init(get_system_memory(), machine, mainstone, 0x196);
84
+ mainstone_common_init(machine, mainstone, 0x196);
146
}
85
}
147
86
148
+static void npcm7xx_init_fuses(NPCM7xxState *s)
87
static void mainstone2_machine_init(MachineClass *mc)
149
+{
88
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
150
+ NPCM7xxClass *nc = NPCM7XX_GET_CLASS(s);
89
index XXXXXXX..XXXXXXX 100644
151
+ uint32_t value;
90
--- a/hw/arm/pxa2xx.c
152
+
91
+++ b/hw/arm/pxa2xx.c
153
+ /*
92
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_reset(void *opaque, int line, int level)
154
+ * The initial mask of disabled modules indicates the chip derivative (e.g.
93
}
155
+ * NPCM750 or NPCM730).
94
156
+ */
95
/* Initialise a PXA270 integrated chip (ARM based core). */
157
+ value = tswap32(nc->disabled_modules);
96
-PXA2xxState *pxa270_init(MemoryRegion *address_space,
158
+ npcm7xx_otp_array_write(&s->fuse_array, &value, NPCM7XX_FUSE_DERIVATIVE,
97
- unsigned int sdram_size, const char *cpu_type)
159
+ sizeof(value));
98
+PXA2xxState *pxa270_init(unsigned int sdram_size, const char *cpu_type)
160
+}
161
+
162
static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n)
163
{
99
{
164
return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
100
+ MemoryRegion *address_space = get_system_memory();
165
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
101
PXA2xxState *s;
166
object_property_add_alias(obj, "power-on-straps", OBJECT(&s->gcr),
102
int i;
167
"power-on-straps");
103
DriveInfo *dinfo;
168
object_initialize_child(obj, "clk", &s->clk, TYPE_NPCM7XX_CLK);
104
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
169
+ object_initialize_child(obj, "otp1", &s->key_storage,
170
+ TYPE_NPCM7XX_KEY_STORAGE);
171
+ object_initialize_child(obj, "otp2", &s->fuse_array,
172
+ TYPE_NPCM7XX_FUSE_ARRAY);
173
174
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
175
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
176
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
177
sysbus_realize(SYS_BUS_DEVICE(&s->clk), &error_abort);
178
sysbus_mmio_map(SYS_BUS_DEVICE(&s->clk), 0, NPCM7XX_CLK_BA);
179
180
+ /* OTP key storage and fuse strap array. Cannot fail. */
181
+ sysbus_realize(SYS_BUS_DEVICE(&s->key_storage), &error_abort);
182
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->key_storage), 0, NPCM7XX_OTP1_BA);
183
+ sysbus_realize(SYS_BUS_DEVICE(&s->fuse_array), &error_abort);
184
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->fuse_array), 0, NPCM7XX_OTP2_BA);
185
+ npcm7xx_init_fuses(s);
186
+
187
/* Timer Modules (TIM). Cannot fail. */
188
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
189
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
190
diff --git a/hw/nvram/npcm7xx_otp.c b/hw/nvram/npcm7xx_otp.c
191
new file mode 100644
192
index XXXXXXX..XXXXXXX
193
--- /dev/null
194
+++ b/hw/nvram/npcm7xx_otp.c
195
@@ -XXX,XX +XXX,XX @@
196
+/*
197
+ * Nuvoton NPCM7xx OTP (Fuse Array) Interface
198
+ *
199
+ * Copyright 2020 Google LLC
200
+ *
201
+ * This program is free software; you can redistribute it and/or modify it
202
+ * under the terms of the GNU General Public License as published by the
203
+ * Free Software Foundation; either version 2 of the License, or
204
+ * (at your option) any later version.
205
+ *
206
+ * This program is distributed in the hope that it will be useful, but WITHOUT
207
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
208
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
209
+ * for more details.
210
+ */
211
+
212
+#include "qemu/osdep.h"
213
+
214
+#include "hw/nvram/npcm7xx_otp.h"
215
+#include "migration/vmstate.h"
216
+#include "qapi/error.h"
217
+#include "qemu/bitops.h"
218
+#include "qemu/log.h"
219
+#include "qemu/module.h"
220
+#include "qemu/units.h"
221
+
222
+/* Each module has 4 KiB of register space. Only a fraction of it is used. */
223
+#define NPCM7XX_OTP_REGS_SIZE (4 * KiB)
224
+
225
+/* 32-bit register indices. */
226
+typedef enum NPCM7xxOTPRegister {
227
+ NPCM7XX_OTP_FST,
228
+ NPCM7XX_OTP_FADDR,
229
+ NPCM7XX_OTP_FDATA,
230
+ NPCM7XX_OTP_FCFG,
231
+ /* Offset 0x10 is FKEYIND in OTP1, FUSTRAP in OTP2 */
232
+ NPCM7XX_OTP_FKEYIND = 0x0010 / sizeof(uint32_t),
233
+ NPCM7XX_OTP_FUSTRAP = 0x0010 / sizeof(uint32_t),
234
+ NPCM7XX_OTP_FCTL,
235
+ NPCM7XX_OTP_REGS_END,
236
+} NPCM7xxOTPRegister;
237
+
238
+/* Register field definitions. */
239
+#define FST_RIEN BIT(2)
240
+#define FST_RDST BIT(1)
241
+#define FST_RDY BIT(0)
242
+#define FST_RO_MASK (FST_RDST | FST_RDY)
243
+
244
+#define FADDR_BYTEADDR(rv) extract32((rv), 0, 10)
245
+#define FADDR_BITPOS(rv) extract32((rv), 10, 3)
246
+
247
+#define FDATA_CLEAR 0x00000001
248
+
249
+#define FCFG_FDIS BIT(31)
250
+#define FCFG_FCFGLK_MASK 0x00ff0000
251
+
252
+#define FCTL_PROG_CMD1 0x00000001
253
+#define FCTL_PROG_CMD2 0xbf79e5d0
254
+#define FCTL_READ_CMD 0x00000002
255
+
256
+/**
257
+ * struct NPCM7xxOTPClass - OTP module class.
258
+ * @parent: System bus device class.
259
+ * @mmio_ops: MMIO register operations for this type of module.
260
+ *
261
+ * The two OTP modules (key-storage and fuse-array) have slightly different
262
+ * behavior, so we give them different MMIO register operations.
263
+ */
264
+struct NPCM7xxOTPClass {
265
+ SysBusDeviceClass parent;
266
+
267
+ const MemoryRegionOps *mmio_ops;
268
+};
269
+
270
+#define NPCM7XX_OTP_CLASS(klass) \
271
+ OBJECT_CLASS_CHECK(NPCM7xxOTPClass, (klass), TYPE_NPCM7XX_OTP)
272
+#define NPCM7XX_OTP_GET_CLASS(obj) \
273
+ OBJECT_GET_CLASS(NPCM7xxOTPClass, (obj), TYPE_NPCM7XX_OTP)
274
+
275
+static uint8_t ecc_encode_nibble(uint8_t n)
276
+{
277
+ uint8_t result = n;
278
+
279
+ result |= (((n >> 0) & 1) ^ ((n >> 1) & 1)) << 4;
280
+ result |= (((n >> 2) & 1) ^ ((n >> 3) & 1)) << 5;
281
+ result |= (((n >> 0) & 1) ^ ((n >> 2) & 1)) << 6;
282
+ result |= (((n >> 1) & 1) ^ ((n >> 3) & 1)) << 7;
283
+
284
+ return result;
285
+}
286
+
287
+void npcm7xx_otp_array_write(NPCM7xxOTPState *s, const void *data,
288
+ unsigned int offset, unsigned int len)
289
+{
290
+ const uint8_t *src = data;
291
+ uint8_t *dst = &s->array[offset];
292
+
293
+ while (len-- > 0) {
294
+ uint8_t c = *src++;
295
+
296
+ *dst++ = ecc_encode_nibble(extract8(c, 0, 4));
297
+ *dst++ = ecc_encode_nibble(extract8(c, 4, 4));
298
+ }
299
+}
300
+
301
+/* Common register read handler for both OTP classes. */
302
+static uint64_t npcm7xx_otp_read(NPCM7xxOTPState *s, NPCM7xxOTPRegister reg)
303
+{
304
+ uint32_t value = 0;
305
+
306
+ switch (reg) {
307
+ case NPCM7XX_OTP_FST:
308
+ case NPCM7XX_OTP_FADDR:
309
+ case NPCM7XX_OTP_FDATA:
310
+ case NPCM7XX_OTP_FCFG:
311
+ value = s->regs[reg];
312
+ break;
313
+
314
+ case NPCM7XX_OTP_FCTL:
315
+ qemu_log_mask(LOG_GUEST_ERROR,
316
+ "%s: read from write-only FCTL register\n",
317
+ DEVICE(s)->canonical_path);
318
+ break;
319
+
320
+ default:
321
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: read from invalid offset 0x%zx\n",
322
+ DEVICE(s)->canonical_path, reg * sizeof(uint32_t));
323
+ break;
324
+ }
325
+
326
+ return value;
327
+}
328
+
329
+/* Read a byte from the OTP array into the data register. */
330
+static void npcm7xx_otp_read_array(NPCM7xxOTPState *s)
331
+{
332
+ uint32_t faddr = s->regs[NPCM7XX_OTP_FADDR];
333
+
334
+ s->regs[NPCM7XX_OTP_FDATA] = s->array[FADDR_BYTEADDR(faddr)];
335
+ s->regs[NPCM7XX_OTP_FST] |= FST_RDST | FST_RDY;
336
+}
337
+
338
+/* Program a byte from the data register into the OTP array. */
339
+static void npcm7xx_otp_program_array(NPCM7xxOTPState *s)
340
+{
341
+ uint32_t faddr = s->regs[NPCM7XX_OTP_FADDR];
342
+
343
+ /* Bits can only go 0->1, never 1->0. */
344
+ s->array[FADDR_BYTEADDR(faddr)] |= (1U << FADDR_BITPOS(faddr));
345
+ s->regs[NPCM7XX_OTP_FST] |= FST_RDST | FST_RDY;
346
+}
347
+
348
+/* Compute the next value of the FCFG register. */
349
+static uint32_t npcm7xx_otp_compute_fcfg(uint32_t cur_value, uint32_t new_value)
350
+{
351
+ uint32_t lock_mask;
352
+ uint32_t value;
353
+
354
+ /*
355
+ * FCFGLK holds sticky bits 16..23, indicating which bits in FPRGLK (8..15)
356
+ * and FRDLK (0..7) that are read-only.
357
+ */
358
+ lock_mask = (cur_value & FCFG_FCFGLK_MASK) >> 8;
359
+ lock_mask |= lock_mask >> 8;
360
+ /* FDIS and FCFGLK bits are sticky (write 1 to set; can't clear). */
361
+ value = cur_value & (FCFG_FDIS | FCFG_FCFGLK_MASK);
362
+ /* Preserve read-only bits in FPRGLK and FRDLK */
363
+ value |= cur_value & lock_mask;
364
+ /* Set all bits that aren't read-only. */
365
+ value |= new_value & ~lock_mask;
366
+
367
+ return value;
368
+}
369
+
370
+/* Common register write handler for both OTP classes. */
371
+static void npcm7xx_otp_write(NPCM7xxOTPState *s, NPCM7xxOTPRegister reg,
372
+ uint32_t value)
373
+{
374
+ switch (reg) {
375
+ case NPCM7XX_OTP_FST:
376
+ /* RDST is cleared by writing 1 to it. */
377
+ if (value & FST_RDST) {
378
+ s->regs[NPCM7XX_OTP_FST] &= ~FST_RDST;
379
+ }
380
+ /* Preserve read-only and write-one-to-clear bits */
381
+ value &= ~FST_RO_MASK;
382
+ value |= s->regs[NPCM7XX_OTP_FST] & FST_RO_MASK;
383
+ break;
384
+
385
+ case NPCM7XX_OTP_FADDR:
386
+ break;
387
+
388
+ case NPCM7XX_OTP_FDATA:
389
+ /*
390
+ * This register is cleared by writing a magic value to it; no other
391
+ * values can be written.
392
+ */
393
+ if (value == FDATA_CLEAR) {
394
+ value = 0;
395
+ } else {
396
+ value = s->regs[NPCM7XX_OTP_FDATA];
397
+ }
398
+ break;
399
+
400
+ case NPCM7XX_OTP_FCFG:
401
+ value = npcm7xx_otp_compute_fcfg(s->regs[NPCM7XX_OTP_FCFG], value);
402
+ break;
403
+
404
+ case NPCM7XX_OTP_FCTL:
405
+ switch (value) {
406
+ case FCTL_READ_CMD:
407
+ npcm7xx_otp_read_array(s);
408
+ break;
409
+
410
+ case FCTL_PROG_CMD1:
411
+ /*
412
+ * Programming requires writing two separate magic values to this
413
+ * register; this is the first one. Just store it so it can be
414
+ * verified later when the second magic value is received.
415
+ */
416
+ break;
417
+
418
+ case FCTL_PROG_CMD2:
419
+ /*
420
+ * Only initiate programming if we received the first half of the
421
+ * command immediately before this one.
422
+ */
423
+ if (s->regs[NPCM7XX_OTP_FCTL] == FCTL_PROG_CMD1) {
424
+ npcm7xx_otp_program_array(s);
425
+ }
426
+ break;
427
+
428
+ default:
429
+ qemu_log_mask(LOG_GUEST_ERROR,
430
+ "%s: unrecognized FCNTL value 0x%" PRIx32 "\n",
431
+ DEVICE(s)->canonical_path, value);
432
+ break;
433
+ }
434
+ if (value != FCTL_PROG_CMD1) {
435
+ value = 0;
436
+ }
437
+ break;
438
+
439
+ default:
440
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: write to invalid offset 0x%zx\n",
441
+ DEVICE(s)->canonical_path, reg * sizeof(uint32_t));
442
+ return;
443
+ }
444
+
445
+ s->regs[reg] = value;
446
+}
447
+
448
+/* Register read handler specific to the fuse array OTP module. */
449
+static uint64_t npcm7xx_fuse_array_read(void *opaque, hwaddr addr,
450
+ unsigned int size)
451
+{
452
+ NPCM7xxOTPRegister reg = addr / sizeof(uint32_t);
453
+ NPCM7xxOTPState *s = opaque;
454
+ uint32_t value;
455
+
456
+ /*
457
+ * Only the Fuse Strap register needs special handling; all other registers
458
+ * work the same way for both kinds of OTP modules.
459
+ */
460
+ if (reg != NPCM7XX_OTP_FUSTRAP) {
461
+ value = npcm7xx_otp_read(s, reg);
462
+ } else {
463
+ /* FUSTRAP is stored as three copies in the OTP array. */
464
+ uint32_t fustrap[3];
465
+
466
+ memcpy(fustrap, &s->array[0], sizeof(fustrap));
467
+
468
+ /* Determine value by a majority vote on each bit. */
469
+ value = (fustrap[0] & fustrap[1]) | (fustrap[0] & fustrap[2]) |
470
+ (fustrap[1] & fustrap[2]);
471
+ }
472
+
473
+ return value;
474
+}
475
+
476
+/* Register write handler specific to the fuse array OTP module. */
477
+static void npcm7xx_fuse_array_write(void *opaque, hwaddr addr, uint64_t v,
478
+ unsigned int size)
479
+{
480
+ NPCM7xxOTPRegister reg = addr / sizeof(uint32_t);
481
+ NPCM7xxOTPState *s = opaque;
482
+
483
+ /*
484
+ * The Fuse Strap register is read-only. Other registers are handled by
485
+ * common code.
486
+ */
487
+ if (reg != NPCM7XX_OTP_FUSTRAP) {
488
+ npcm7xx_otp_write(s, reg, v);
489
+ }
490
+}
491
+
492
+static const MemoryRegionOps npcm7xx_fuse_array_ops = {
493
+ .read = npcm7xx_fuse_array_read,
494
+ .write = npcm7xx_fuse_array_write,
495
+ .endianness = DEVICE_LITTLE_ENDIAN,
496
+ .valid = {
497
+ .min_access_size = 4,
498
+ .max_access_size = 4,
499
+ .unaligned = false,
500
+ },
501
+};
502
+
503
+/* Register read handler specific to the key storage OTP module. */
504
+static uint64_t npcm7xx_key_storage_read(void *opaque, hwaddr addr,
505
+ unsigned int size)
506
+{
507
+ NPCM7xxOTPRegister reg = addr / sizeof(uint32_t);
508
+ NPCM7xxOTPState *s = opaque;
509
+
510
+ /*
511
+ * Only the Fuse Key Index register needs special handling; all other
512
+ * registers work the same way for both kinds of OTP modules.
513
+ */
514
+ if (reg != NPCM7XX_OTP_FKEYIND) {
515
+ return npcm7xx_otp_read(s, reg);
516
+ }
517
+
518
+ qemu_log_mask(LOG_UNIMP, "%s: FKEYIND is not implemented\n", __func__);
519
+
520
+ return s->regs[NPCM7XX_OTP_FKEYIND];
521
+}
522
+
523
+/* Register write handler specific to the key storage OTP module. */
524
+static void npcm7xx_key_storage_write(void *opaque, hwaddr addr, uint64_t v,
525
+ unsigned int size)
526
+{
527
+ NPCM7xxOTPRegister reg = addr / sizeof(uint32_t);
528
+ NPCM7xxOTPState *s = opaque;
529
+
530
+ /*
531
+ * Only the Fuse Key Index register needs special handling; all other
532
+ * registers work the same way for both kinds of OTP modules.
533
+ */
534
+ if (reg != NPCM7XX_OTP_FKEYIND) {
535
+ npcm7xx_otp_write(s, reg, v);
536
+ return;
537
+ }
538
+
539
+ qemu_log_mask(LOG_UNIMP, "%s: FKEYIND is not implemented\n", __func__);
540
+
541
+ s->regs[NPCM7XX_OTP_FKEYIND] = v;
542
+}
543
+
544
+static const MemoryRegionOps npcm7xx_key_storage_ops = {
545
+ .read = npcm7xx_key_storage_read,
546
+ .write = npcm7xx_key_storage_write,
547
+ .endianness = DEVICE_LITTLE_ENDIAN,
548
+ .valid = {
549
+ .min_access_size = 4,
550
+ .max_access_size = 4,
551
+ .unaligned = false,
552
+ },
553
+};
554
+
555
+static void npcm7xx_otp_enter_reset(Object *obj, ResetType type)
556
+{
557
+ NPCM7xxOTPState *s = NPCM7XX_OTP(obj);
558
+
559
+ memset(s->regs, 0, sizeof(s->regs));
560
+
561
+ s->regs[NPCM7XX_OTP_FST] = 0x00000001;
562
+ s->regs[NPCM7XX_OTP_FCFG] = 0x20000000;
563
+}
564
+
565
+static void npcm7xx_otp_realize(DeviceState *dev, Error **errp)
566
+{
567
+ NPCM7xxOTPClass *oc = NPCM7XX_OTP_GET_CLASS(dev);
568
+ NPCM7xxOTPState *s = NPCM7XX_OTP(dev);
569
+ SysBusDevice *sbd = &s->parent;
570
+
571
+ memset(s->array, 0, sizeof(s->array));
572
+
573
+ memory_region_init_io(&s->mmio, OBJECT(s), oc->mmio_ops, s, "regs",
574
+ NPCM7XX_OTP_REGS_SIZE);
575
+ sysbus_init_mmio(sbd, &s->mmio);
576
+}
577
+
578
+static const VMStateDescription vmstate_npcm7xx_otp = {
579
+ .name = "npcm7xx-otp",
580
+ .version_id = 0,
581
+ .minimum_version_id = 0,
582
+ .fields = (VMStateField[]) {
583
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxOTPState, NPCM7XX_OTP_NR_REGS),
584
+ VMSTATE_UINT8_ARRAY(array, NPCM7xxOTPState, NPCM7XX_OTP_ARRAY_BYTES),
585
+ VMSTATE_END_OF_LIST(),
586
+ },
587
+};
588
+
589
+static void npcm7xx_otp_class_init(ObjectClass *klass, void *data)
590
+{
591
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
592
+ DeviceClass *dc = DEVICE_CLASS(klass);
593
+
594
+ QEMU_BUILD_BUG_ON(NPCM7XX_OTP_REGS_END > NPCM7XX_OTP_NR_REGS);
595
+
596
+ dc->realize = npcm7xx_otp_realize;
597
+ dc->vmsd = &vmstate_npcm7xx_otp;
598
+ rc->phases.enter = npcm7xx_otp_enter_reset;
599
+}
600
+
601
+static void npcm7xx_key_storage_class_init(ObjectClass *klass, void *data)
602
+{
603
+ NPCM7xxOTPClass *oc = NPCM7XX_OTP_CLASS(klass);
604
+
605
+ oc->mmio_ops = &npcm7xx_key_storage_ops;
606
+}
607
+
608
+static void npcm7xx_fuse_array_class_init(ObjectClass *klass, void *data)
609
+{
610
+ NPCM7xxOTPClass *oc = NPCM7XX_OTP_CLASS(klass);
611
+
612
+ oc->mmio_ops = &npcm7xx_fuse_array_ops;
613
+}
614
+
615
+static const TypeInfo npcm7xx_otp_types[] = {
616
+ {
617
+ .name = TYPE_NPCM7XX_OTP,
618
+ .parent = TYPE_SYS_BUS_DEVICE,
619
+ .instance_size = sizeof(NPCM7xxOTPState),
620
+ .class_size = sizeof(NPCM7xxOTPClass),
621
+ .class_init = npcm7xx_otp_class_init,
622
+ .abstract = true,
623
+ },
624
+ {
625
+ .name = TYPE_NPCM7XX_KEY_STORAGE,
626
+ .parent = TYPE_NPCM7XX_OTP,
627
+ .class_init = npcm7xx_key_storage_class_init,
628
+ },
629
+ {
630
+ .name = TYPE_NPCM7XX_FUSE_ARRAY,
631
+ .parent = TYPE_NPCM7XX_OTP,
632
+ .class_init = npcm7xx_fuse_array_class_init,
633
+ },
634
+};
635
+DEFINE_TYPES(npcm7xx_otp_types);
636
diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build
637
index XXXXXXX..XXXXXXX 100644
105
index XXXXXXX..XXXXXXX 100644
638
--- a/hw/nvram/meson.build
106
--- a/hw/arm/spitz.c
639
+++ b/hw/nvram/meson.build
107
+++ b/hw/arm/spitz.c
640
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_DS1225Y', if_true: files('ds1225y.c'))
108
@@ -XXX,XX +XXX,XX @@ static void spitz_common_init(MachineState *machine)
641
softmmu_ss.add(when: 'CONFIG_NMC93XX_EEPROM', if_true: files('eeprom93xx.c'))
109
SpitzMachineState *sms = SPITZ_MACHINE(machine);
642
softmmu_ss.add(when: 'CONFIG_AT24C', if_true: files('eeprom_at24c.c'))
110
enum spitz_model_e model = smc->model;
643
softmmu_ss.add(when: 'CONFIG_MAC_NVRAM', if_true: files('mac_nvram.c'))
111
PXA2xxState *mpu;
644
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_otp.c'))
112
- MemoryRegion *address_space_mem = get_system_memory();
645
softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_nvm.c'))
113
MemoryRegion *rom = g_new(MemoryRegion, 1);
646
114
647
specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_nvram.c'))
115
/* Setup CPU & memory */
116
- mpu = pxa270_init(address_space_mem, spitz_binfo.ram_size,
117
- machine->cpu_type);
118
+ mpu = pxa270_init(spitz_binfo.ram_size, machine->cpu_type);
119
sms->mpu = mpu;
120
121
sl_flash_register(mpu, (model == spitz) ? FLASH_128M : FLASH_1024M);
122
123
memory_region_init_rom(rom, NULL, "spitz.rom", SPITZ_ROM, &error_fatal);
124
- memory_region_add_subregion(address_space_mem, 0, rom);
125
+ memory_region_add_subregion(get_system_memory(), 0, rom);
126
127
/* Setup peripherals */
128
spitz_keyboard_register(mpu);
129
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/hw/arm/z2.c
132
+++ b/hw/arm/z2.c
133
@@ -XXX,XX +XXX,XX @@ static const TypeInfo aer915_info = {
134
135
static void z2_init(MachineState *machine)
136
{
137
- MemoryRegion *address_space_mem = get_system_memory();
138
uint32_t sector_len = 0x10000;
139
PXA2xxState *mpu;
140
DriveInfo *dinfo;
141
@@ -XXX,XX +XXX,XX @@ static void z2_init(MachineState *machine)
142
DeviceState *wm;
143
144
/* Setup CPU & memory */
145
- mpu = pxa270_init(address_space_mem, z2_binfo.ram_size, machine->cpu_type);
146
+ mpu = pxa270_init(z2_binfo.ram_size, machine->cpu_type);
147
148
dinfo = drive_get(IF_PFLASH, 0, 0);
149
if (!pflash_cfi01_register(Z2_FLASH_BASE, "z2.flash0", Z2_FLASH_SIZE,
648
--
150
--
649
2.20.1
151
2.34.1
650
152
651
153
diff view generated by jsdifflib
1
Deprecate our Unicore32 target support:
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
* the Linux kernel dropped support for unicore32 in commit
3
05119217a9bd199c for its 5.9 release (with rationale in the
4
cover letter: https://lkml.org/lkml/2020/8/3/232 )
5
* there is apparently no upstream toolchain that can create unicore32
6
binaries
7
* the maintainer doesn't seem to have made any contributions to
8
QEMU since the port first landed in 2012
9
* nobody else seems to have made changes to the unicore code except
10
for generic cleanups either
11
2
3
IEC binary prefixes ease code review: the unit is explicit.
4
5
Add definitions for RAM / Flash / Flash blocksize.
6
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230109115316.2235-4-philmd@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
14
Message-id: 20200825172719.19422-1-peter.maydell@linaro.org
15
---
11
---
16
docs/system/deprecated.rst | 8 ++++++++
12
hw/arm/collie.c | 16 ++++++++++------
17
1 file changed, 8 insertions(+)
13
1 file changed, 10 insertions(+), 6 deletions(-)
18
14
19
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
15
diff --git a/hw/arm/collie.c b/hw/arm/collie.c
20
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
21
--- a/docs/system/deprecated.rst
17
--- a/hw/arm/collie.c
22
+++ b/docs/system/deprecated.rst
18
+++ b/hw/arm/collie.c
23
@@ -XXX,XX +XXX,XX @@ The above, converted to the current supported format::
19
@@ -XXX,XX +XXX,XX @@
24
linux-user mode CPUs
20
#include "cpu.h"
25
--------------------
21
#include "qom/object.h"
26
22
27
+``unicore32`` CPUs (since 5.2.0)
23
+#define RAM_SIZE (512 * MiB)
28
+''''''''''''''''''''''''''''''''
24
+#define FLASH_SIZE (32 * MiB)
25
+#define FLASH_SECTOR_SIZE (64 * KiB)
29
+
26
+
30
+The ``unicore32`` guest CPU support is deprecated and will be removed in
27
struct CollieMachineState {
31
+a future version of QEMU. Support for this CPU was removed from the
28
MachineState parent;
32
+upstream Linux kernel, and there is no available upstream toolchain
29
33
+to build binaries for it.
30
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(CollieMachineState, COLLIE_MACHINE)
34
+
31
35
``tilegx`` CPUs (since 5.1.0)
32
static struct arm_boot_info collie_binfo = {
36
'''''''''''''''''''''''''''''
33
.loader_start = SA_SDCS0,
34
- .ram_size = 0x20000000,
35
+ .ram_size = RAM_SIZE,
36
};
37
38
static void collie_init(MachineState *machine)
39
@@ -XXX,XX +XXX,XX @@ static void collie_init(MachineState *machine)
40
memory_region_add_subregion(get_system_memory(), SA_SDCS0, machine->ram);
41
42
dinfo = drive_get(IF_PFLASH, 0, 0);
43
- pflash_cfi01_register(SA_CS0, "collie.fl1", 0x02000000,
44
+ pflash_cfi01_register(SA_CS0, "collie.fl1", FLASH_SIZE,
45
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
46
- 64 * KiB, 4, 0x00, 0x00, 0x00, 0x00, 0);
47
+ FLASH_SECTOR_SIZE, 4, 0x00, 0x00, 0x00, 0x00, 0);
48
49
dinfo = drive_get(IF_PFLASH, 0, 1);
50
- pflash_cfi01_register(SA_CS1, "collie.fl2", 0x02000000,
51
+ pflash_cfi01_register(SA_CS1, "collie.fl2", FLASH_SIZE,
52
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
53
- 64 * KiB, 4, 0x00, 0x00, 0x00, 0x00, 0);
54
+ FLASH_SECTOR_SIZE, 4, 0x00, 0x00, 0x00, 0x00, 0);
55
56
sysbus_create_simple("scoop", 0x40800000, NULL);
57
58
@@ -XXX,XX +XXX,XX @@ static void collie_machine_class_init(ObjectClass *oc, void *data)
59
mc->init = collie_init;
60
mc->ignore_memory_transaction_failures = true;
61
mc->default_cpu_type = ARM_CPU_TYPE_NAME("sa1110");
62
- mc->default_ram_size = 0x20000000;
63
+ mc->default_ram_size = RAM_SIZE;
64
mc->default_ram_id = "strongarm.sdram";
65
}
37
66
38
--
67
--
39
2.20.1
68
2.34.1
40
69
41
70
diff view generated by jsdifflib
1
Deprecate our lm32 target support. Michael Walle (former lm32 maintainer)
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
suggested that we do this in 2019:
3
https://www.mail-archive.com/qemu-devel@nongnu.org/msg605024.html
4
because the only public user of the architecture is the many-years-dead
5
milkymist project. (The Linux port to lm32 was never merged upstream.)
6
2
7
In commit 4b4d96c776f552e (March 2020) we marked it as 'orphan' in
3
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
the MAINTAINERS file, but didn't officially deprecate it. Mark it
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
deprecated now, with the intention of removing it from QEMU in
5
Message-id: 20230109115316.2235-5-philmd@linaro.org
10
mid-2021 before the 6.1 release.
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
hw/arm/collie.c | 17 +++++++----------
9
1 file changed, 7 insertions(+), 10 deletions(-)
11
10
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
diff --git a/hw/arm/collie.c b/hw/arm/collie.c
13
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Reviewed-by: Thomas Huth <thuth@redhat.com>
16
Acked-by: Michael Walle <michael@walle.cc>
17
Message-id: 20200827113259.25064-1-peter.maydell@linaro.org
18
---
19
docs/system/deprecated.rst | 8 ++++++++
20
1 file changed, 8 insertions(+)
21
22
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
23
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
24
--- a/docs/system/deprecated.rst
13
--- a/hw/arm/collie.c
25
+++ b/docs/system/deprecated.rst
14
+++ b/hw/arm/collie.c
26
@@ -XXX,XX +XXX,XX @@ The above, converted to the current supported format::
15
@@ -XXX,XX +XXX,XX @@ static struct arm_boot_info collie_binfo = {
27
linux-user mode CPUs
16
28
--------------------
17
static void collie_init(MachineState *machine)
29
18
{
30
+``lm32`` CPUs (since 5.2.0)
19
- DriveInfo *dinfo;
31
+'''''''''''''''''''''''''''
20
MachineClass *mc = MACHINE_GET_CLASS(machine);
32
+
21
CollieMachineState *cms = COLLIE_MACHINE(machine);
33
+The ``lm32`` guest CPU support is deprecated and will be removed in
22
34
+a future version of QEMU. The only public user of this architecture
23
@@ -XXX,XX +XXX,XX @@ static void collie_init(MachineState *machine)
35
+was the milkymist project, which has been dead for years; there was
24
36
+never an upstream Linux port.
25
memory_region_add_subregion(get_system_memory(), SA_SDCS0, machine->ram);
37
+
26
38
``unicore32`` CPUs (since 5.2.0)
27
- dinfo = drive_get(IF_PFLASH, 0, 0);
39
''''''''''''''''''''''''''''''''
28
- pflash_cfi01_register(SA_CS0, "collie.fl1", FLASH_SIZE,
29
- dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
30
- FLASH_SECTOR_SIZE, 4, 0x00, 0x00, 0x00, 0x00, 0);
31
-
32
- dinfo = drive_get(IF_PFLASH, 0, 1);
33
- pflash_cfi01_register(SA_CS1, "collie.fl2", FLASH_SIZE,
34
- dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
35
- FLASH_SECTOR_SIZE, 4, 0x00, 0x00, 0x00, 0x00, 0);
36
+ for (unsigned i = 0; i < 2; i++) {
37
+ DriveInfo *dinfo = drive_get(IF_PFLASH, 0, i);
38
+ pflash_cfi01_register(i ? SA_CS1 : SA_CS0,
39
+ i ? "collie.fl2" : "collie.fl1", FLASH_SIZE,
40
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
41
+ FLASH_SECTOR_SIZE, 4, 0x00, 0x00, 0x00, 0x00, 0);
42
+ }
43
44
sysbus_create_simple("scoop", 0x40800000, NULL);
40
45
41
--
46
--
42
2.20.1
47
2.34.1
43
48
44
49
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Report unimplemented register accesses using qemu_log_mask(UNIMP).
3
Add a comment describing the Connex uses a Numonyx RC28F128J3F75
4
flash, and the Verdex uses a Micron RC28F256P30TFA.
5
6
Correct the Verdex machine description (we model the 'Pro' board).
4
7
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200901144100.116742-5-f4bug@amsat.org
10
Message-id: 20230109115316.2235-6-philmd@linaro.org
11
Message-Id: <20200223231044.8003-3-philmd@redhat.com>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
13
---
10
hw/misc/a9scu.c | 6 ++++++
14
hw/arm/gumstix.c | 6 ++++--
11
1 file changed, 6 insertions(+)
15
1 file changed, 4 insertions(+), 2 deletions(-)
12
16
13
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
17
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/misc/a9scu.c
19
--- a/hw/arm/gumstix.c
16
+++ b/hw/misc/a9scu.c
20
+++ b/hw/arm/gumstix.c
17
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@
18
#include "hw/qdev-properties.h"
22
* Contributions after 2012-01-13 are licensed under the terms of the
19
#include "migration/vmstate.h"
23
* GNU GPL, version 2 or (at your option) any later version.
20
#include "qapi/error.h"
24
*/
21
+#include "qemu/log.h"
25
-
22
#include "qemu/module.h"
26
+
23
27
/*
24
#define A9_SCU_CPU_MAX 4
28
* Example usage:
25
@@ -XXX,XX +XXX,XX @@ static uint64_t a9_scu_read(void *opaque, hwaddr offset,
29
*
26
case 0x54: /* SCU Non-secure Access Control Register */
30
@@ -XXX,XX +XXX,XX @@ static void connex_init(MachineState *machine)
27
/* unimplemented, fall through */
31
exit(1);
28
default:
29
+ qemu_log_mask(LOG_UNIMP, "%s: Unsupported offset 0x%"HWADDR_PRIx"\n",
30
+ __func__, offset);
31
return 0;
32
}
32
}
33
}
33
34
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
34
+ /* Numonyx RC28F128J3F75 */
35
case 0x54: /* SCU Non-secure Access Control Register */
35
if (!pflash_cfi01_register(0x00000000, "connext.rom", connex_rom,
36
/* unimplemented, fall through */
36
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
37
default:
37
sector_len, 2, 0, 0, 0, 0, 0)) {
38
+ qemu_log_mask(LOG_UNIMP, "%s: Unsupported offset 0x%"HWADDR_PRIx
38
@@ -XXX,XX +XXX,XX @@ static void verdex_init(MachineState *machine)
39
+ " value 0x%"PRIx64"\n",
39
exit(1);
40
+ __func__, offset, value);
41
break;
42
}
40
}
43
}
41
42
+ /* Micron RC28F256P30TFA */
43
if (!pflash_cfi01_register(0x00000000, "verdex.rom", verdex_rom,
44
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
45
sector_len, 2, 0, 0, 0, 0, 0)) {
46
@@ -XXX,XX +XXX,XX @@ static void verdex_class_init(ObjectClass *oc, void *data)
47
{
48
MachineClass *mc = MACHINE_CLASS(oc);
49
50
- mc->desc = "Gumstix Verdex (PXA270)";
51
+ mc->desc = "Gumstix Verdex Pro XL6P COMs (PXA270)";
52
mc->init = verdex_init;
53
mc->ignore_memory_transaction_failures = true;
54
mc->default_cpu_type = ARM_CPU_TYPE_NAME("pxa270-c0");
44
--
55
--
45
2.20.1
56
2.34.1
46
57
47
58
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
This model implementation is designed for 32-bit accesses.
3
IEC binary prefixes ease code review: the unit is explicit.
4
We can simplify setting the MemoryRegionOps::impl min/max
4
5
fields to 32-bit (memory::access_with_adjusted_size() will
5
Add definitions for RAM / Flash / Flash blocksize.
6
take care of the 8/16-bit accesses).
7
6
8
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200901144100.116742-4-f4bug@amsat.org
9
Message-id: 20230109115316.2235-7-philmd@linaro.org
10
Message-Id: <20200223231044.8003-3-philmd@redhat.com>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
12
---
13
hw/misc/a9scu.c | 16 +++++-----------
13
hw/arm/gumstix.c | 27 ++++++++++++++-------------
14
1 file changed, 5 insertions(+), 11 deletions(-)
14
1 file changed, 14 insertions(+), 13 deletions(-)
15
15
16
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
16
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/misc/a9scu.c
18
--- a/hw/arm/gumstix.c
19
+++ b/hw/misc/a9scu.c
19
+++ b/hw/arm/gumstix.c
20
@@ -XXX,XX +XXX,XX @@ static uint64_t a9_scu_read(void *opaque, hwaddr offset,
20
@@ -XXX,XX +XXX,XX @@
21
return (((1 << s->num_cpu) - 1) << 4) | (s->num_cpu - 1);
21
*/
22
case 0x08: /* CPU Power Status */
22
23
return s->status;
23
#include "qemu/osdep.h"
24
- case 0x09: /* CPU status. */
24
+#include "qemu/units.h"
25
- return s->status >> 8;
25
#include "qemu/error-report.h"
26
- case 0x0a: /* CPU status. */
26
#include "hw/arm/pxa.h"
27
- return s->status >> 16;
27
#include "net/net.h"
28
- case 0x0b: /* CPU status. */
28
@@ -XXX,XX +XXX,XX @@
29
- return s->status >> 24;
29
#include "sysemu/qtest.h"
30
case 0x0c: /* Invalidate All Registers In Secure State */
30
#include "cpu.h"
31
return 0;
31
32
case 0x40: /* Filtering Start Address Register */
32
-static const int sector_len = 128 * 1024;
33
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
33
+#define CONNEX_FLASH_SIZE (16 * MiB)
34
uint64_t value, unsigned size)
34
+#define CONNEX_RAM_SIZE (64 * MiB)
35
+
36
+#define VERDEX_FLASH_SIZE (32 * MiB)
37
+#define VERDEX_RAM_SIZE (256 * MiB)
38
+
39
+#define FLASH_SECTOR_SIZE (128 * KiB)
40
41
static void connex_init(MachineState *machine)
35
{
42
{
36
A9SCUState *s = (A9SCUState *)opaque;
43
PXA2xxState *cpu;
37
- uint32_t mask = MAKE_64BIT_MASK(0, size * 8);
44
DriveInfo *dinfo;
38
- uint32_t shift;
45
39
46
- uint32_t connex_rom = 0x01000000;
40
switch (offset) {
47
- uint32_t connex_ram = 0x04000000;
41
case 0x00: /* Control */
48
-
42
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
49
- cpu = pxa255_init(connex_ram);
43
case 0x4: /* Configuration: RO */
50
+ cpu = pxa255_init(CONNEX_RAM_SIZE);
44
break;
51
45
case 0x08: case 0x09: case 0x0A: case 0x0B: /* Power Control */
52
dinfo = drive_get(IF_PFLASH, 0, 0);
46
- shift = (offset - 0x8) * 8;
53
if (!dinfo && !qtest_enabled()) {
47
- s->status &= ~(mask << shift);
54
@@ -XXX,XX +XXX,XX @@ static void connex_init(MachineState *machine)
48
- s->status |= ((value & mask) << shift);
55
}
49
+ s->status = value;
56
50
break;
57
/* Numonyx RC28F128J3F75 */
51
case 0x0c: /* Invalidate All Registers In Secure State */
58
- if (!pflash_cfi01_register(0x00000000, "connext.rom", connex_rom,
52
/* no-op as we do not implement caches */
59
+ if (!pflash_cfi01_register(0x00000000, "connext.rom", CONNEX_FLASH_SIZE,
53
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
60
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
54
static const MemoryRegionOps a9_scu_ops = {
61
- sector_len, 2, 0, 0, 0, 0, 0)) {
55
.read = a9_scu_read,
62
+ FLASH_SECTOR_SIZE, 2, 0, 0, 0, 0, 0)) {
56
.write = a9_scu_write,
63
error_report("Error registering flash memory");
57
+ .impl = {
64
exit(1);
58
+ .min_access_size = 4,
65
}
59
+ .max_access_size = 4,
66
@@ -XXX,XX +XXX,XX @@ static void verdex_init(MachineState *machine)
60
+ },
67
PXA2xxState *cpu;
61
.valid = {
68
DriveInfo *dinfo;
62
.min_access_size = 1,
69
63
.max_access_size = 4,
70
- uint32_t verdex_rom = 0x02000000;
71
- uint32_t verdex_ram = 0x10000000;
72
-
73
- cpu = pxa270_init(verdex_ram, machine->cpu_type);
74
+ cpu = pxa270_init(VERDEX_RAM_SIZE, machine->cpu_type);
75
76
dinfo = drive_get(IF_PFLASH, 0, 0);
77
if (!dinfo && !qtest_enabled()) {
78
@@ -XXX,XX +XXX,XX @@ static void verdex_init(MachineState *machine)
79
}
80
81
/* Micron RC28F256P30TFA */
82
- if (!pflash_cfi01_register(0x00000000, "verdex.rom", verdex_rom,
83
+ if (!pflash_cfi01_register(0x00000000, "verdex.rom", VERDEX_FLASH_SIZE,
84
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
85
- sector_len, 2, 0, 0, 0, 0, 0)) {
86
+ FLASH_SECTOR_SIZE, 2, 0, 0, 0, 0, 0)) {
87
error_report("Error registering flash memory");
88
exit(1);
89
}
64
--
90
--
65
2.20.1
91
2.34.1
66
92
67
93
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
Reviewed-by: Cédric Le Goater <clg@kaod.org>
3
IEC binary prefixes ease code review: the unit is explicit.
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
5
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
5
Add the FLASH_SECTOR_SIZE definition.
6
Message-id: 20200911052101.2602693-14-hskinnemoen@google.com
6
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230109115316.2235-8-philmd@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
11
---
9
docs/system/arm/nuvoton.rst | 92 +++++++++++++++++++++++++++++++++++++
12
hw/arm/mainstone.c | 18 ++++++++++--------
10
docs/system/target-arm.rst | 1 +
13
1 file changed, 10 insertions(+), 8 deletions(-)
11
2 files changed, 93 insertions(+)
12
create mode 100644 docs/system/arm/nuvoton.rst
13
14
14
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
15
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
15
new file mode 100644
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX
17
--- a/hw/arm/mainstone.c
17
--- /dev/null
18
+++ b/hw/arm/mainstone.c
18
+++ b/docs/system/arm/nuvoton.rst
19
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
20
+Nuvoton iBMC boards (``npcm750-evb``, ``quanta-gsj``)
20
* GNU GPL, version 2 or (at your option) any later version.
21
+=====================================================
21
*/
22
#include "qemu/osdep.h"
23
+#include "qemu/units.h"
24
#include "qemu/error-report.h"
25
#include "qapi/error.h"
26
#include "hw/arm/pxa.h"
27
@@ -XXX,XX +XXX,XX @@ static const struct keymap map[0xE0] = {
28
29
enum mainstone_model_e { mainstone };
30
31
-#define MAINSTONE_RAM    0x04000000
32
-#define MAINSTONE_ROM    0x00800000
33
-#define MAINSTONE_FLASH    0x02000000
34
+#define MAINSTONE_RAM_SIZE (64 * MiB)
35
+#define MAINSTONE_ROM_SIZE (8 * MiB)
36
+#define MAINSTONE_FLASH_SIZE (32 * MiB)
37
38
static struct arm_boot_info mainstone_binfo = {
39
.loader_start = PXA2XX_SDRAM_BASE,
40
- .ram_size = 0x04000000,
41
+ .ram_size = MAINSTONE_RAM_SIZE,
42
};
43
44
+#define FLASH_SECTOR_SIZE (256 * KiB)
22
+
45
+
23
+The `Nuvoton iBMC`_ chips (NPCM7xx) are a family of ARM-based SoCs that are
46
static void mainstone_common_init(MachineState *machine,
24
+designed to be used as Baseboard Management Controllers (BMCs) in various
47
enum mainstone_model_e model, int arm_id)
25
+servers. They all feature one or two ARM Cortex A9 CPU cores, as well as an
48
{
26
+assortment of peripherals targeted for either Enterprise or Data Center /
49
- uint32_t sector_len = 256 * 1024;
27
+Hyperscale applications. The former is a superset of the latter, so NPCM750 has
50
hwaddr mainstone_flash_base[] = { MST_FLASH_0, MST_FLASH_1 };
28
+all the peripherals of NPCM730 and more.
51
PXA2xxState *mpu;
29
+
52
DeviceState *mst_irq;
30
+.. _Nuvoton iBMC: https://www.nuvoton.com/products/cloud-computing/ibmc/
53
@@ -XXX,XX +XXX,XX @@ static void mainstone_common_init(MachineState *machine,
31
+
54
32
+The NPCM750 SoC has two Cortex A9 cores and is targeted for the Enterprise
55
/* Setup CPU & memory */
33
+segment. The following machines are based on this chip :
56
mpu = pxa270_init(mainstone_binfo.ram_size, machine->cpu_type);
34
+
57
- memory_region_init_rom(rom, NULL, "mainstone.rom", MAINSTONE_ROM,
35
+- ``npcm750-evb`` Nuvoton NPCM750 Evaluation board
58
+ memory_region_init_rom(rom, NULL, "mainstone.rom", MAINSTONE_ROM_SIZE,
36
+
59
&error_fatal);
37
+The NPCM730 SoC has two Cortex A9 cores and is targeted for Data Center and
60
memory_region_add_subregion(get_system_memory(), 0x00000000, rom);
38
+Hyperscale applications. The following machines are based on this chip :
61
39
+
62
@@ -XXX,XX +XXX,XX @@ static void mainstone_common_init(MachineState *machine,
40
+- ``quanta-gsj`` Quanta GSJ server BMC
63
dinfo = drive_get(IF_PFLASH, 0, i);
41
+
64
if (!pflash_cfi01_register(mainstone_flash_base[i],
42
+There are also two more SoCs, NPCM710 and NPCM705, which are single-core
65
i ? "mainstone.flash1" : "mainstone.flash0",
43
+variants of NPCM750 and NPCM730, respectively. These are currently not
66
- MAINSTONE_FLASH,
44
+supported by QEMU.
67
+ MAINSTONE_FLASH_SIZE,
45
+
68
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
46
+Supported devices
69
- sector_len, 4, 0, 0, 0, 0, 0)) {
47
+-----------------
70
+ FLASH_SECTOR_SIZE, 4, 0, 0, 0, 0, 0)) {
48
+
71
error_report("Error registering flash memory");
49
+ * SMP (Dual Core Cortex-A9)
72
exit(1);
50
+ * Cortex-A9MPCore built-in peripherals: SCU, GIC, Global Timer, Private Timer
73
}
51
+ and Watchdog.
52
+ * SRAM, ROM and DRAM mappings
53
+ * System Global Control Registers (GCR)
54
+ * Clock and reset controller (CLK)
55
+ * Timer controller (TIM)
56
+ * Serial ports (16550-based)
57
+ * DDR4 memory controller (dummy interface indicating memory training is done)
58
+ * OTP controllers (no protection features)
59
+ * Flash Interface Unit (FIU; no protection features)
60
+
61
+Missing devices
62
+---------------
63
+
64
+ * GPIO controller
65
+ * LPC/eSPI host-to-BMC interface, including
66
+
67
+ * Keyboard and mouse controller interface (KBCI)
68
+ * Keyboard Controller Style (KCS) channels
69
+ * BIOS POST code FIFO
70
+ * System Wake-up Control (SWC)
71
+ * Shared memory (SHM)
72
+ * eSPI slave interface
73
+
74
+ * Ethernet controllers (GMAC and EMC)
75
+ * USB host (USBH)
76
+ * USB device (USBD)
77
+ * SMBus controller (SMBF)
78
+ * Peripheral SPI controller (PSPI)
79
+ * Analog to Digital Converter (ADC)
80
+ * SD/MMC host
81
+ * Random Number Generator (RNG)
82
+ * PECI interface
83
+ * Pulse Width Modulation (PWM)
84
+ * Tachometer
85
+ * PCI and PCIe root complex and bridges
86
+ * VDM and MCTP support
87
+ * Serial I/O expansion
88
+ * LPC/eSPI host
89
+ * Coprocessor
90
+ * Graphics
91
+ * Video capture
92
+ * Encoding compression engine
93
+ * Security features
94
+
95
+Boot options
96
+------------
97
+
98
+The Nuvoton machines can boot from an OpenBMC firmware image, or directly into
99
+a kernel using the ``-kernel`` option. OpenBMC images for `quanta-gsj` and
100
+possibly others can be downloaded from the OpenPOWER jenkins :
101
+
102
+ https://openpower.xyz/
103
+
104
+The firmware image should be attached as an MTD drive. Example :
105
+
106
+.. code-block:: bash
107
+
108
+ $ qemu-system-arm -machine quanta-gsj -nographic \
109
+ -drive file=image-bmc,if=mtd,bus=0,unit=0,format=raw
110
+
111
+The default root password for test images is usually ``0penBmc``.
112
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
113
index XXXXXXX..XXXXXXX 100644
114
--- a/docs/system/target-arm.rst
115
+++ b/docs/system/target-arm.rst
116
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
117
arm/musicpal
118
arm/gumstix
119
arm/nseries
120
+ arm/nuvoton
121
arm/orangepi
122
arm/palm
123
arm/xscale
124
--
74
--
125
2.20.1
75
2.34.1
126
76
127
77
diff view generated by jsdifflib
1
Now that 32-bit KVM host support is gone, KVM can never
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
be enabled unless CONFIG_AARCH64 is true, and some code
3
paths are no longer reachable and can be deleted.
4
2
3
IEC binary prefixes ease code review: the unit is explicit.
4
5
Add the FLASH_SECTOR_SIZE definition.
6
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230109115316.2235-9-philmd@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Message-id: 20200904154156.31943-3-peter.maydell@linaro.org
9
---
11
---
10
target/arm/kvm-consts.h | 7 ---
12
hw/arm/musicpal.c | 9 ++++++---
11
target/arm/kvm_arm.h | 6 ---
13
1 file changed, 6 insertions(+), 3 deletions(-)
12
target/arm/cpu.c | 101 +++++++++++++++++++---------------------
13
target/arm/kvm.c | 7 ---
14
4 files changed, 47 insertions(+), 74 deletions(-)
15
14
16
diff --git a/target/arm/kvm-consts.h b/target/arm/kvm-consts.h
15
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/kvm-consts.h
17
--- a/hw/arm/musicpal.c
19
+++ b/target/arm/kvm-consts.h
18
+++ b/hw/arm/musicpal.c
20
@@ -XXX,XX +XXX,XX @@ MISMATCH_CHECK(QEMU_PSCI_RET_DISABLED, PSCI_RET_DISABLED);
19
@@ -XXX,XX +XXX,XX @@
21
*/
20
*/
22
#define QEMU_KVM_ARM_TARGET_NONE UINT_MAX
21
23
22
#include "qemu/osdep.h"
24
-#ifdef TARGET_AARCH64
23
+#include "qemu/units.h"
25
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_AEM_V8, KVM_ARM_TARGET_AEM_V8);
24
#include "qapi/error.h"
26
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_FOUNDATION_V8, KVM_ARM_TARGET_FOUNDATION_V8);
25
#include "cpu.h"
27
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A57, KVM_ARM_TARGET_CORTEX_A57);
26
#include "hw/sysbus.h"
28
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_XGENE_POTENZA, KVM_ARM_TARGET_XGENE_POTENZA);
27
@@ -XXX,XX +XXX,XX @@ static const TypeInfo musicpal_key_info = {
29
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A53, KVM_ARM_TARGET_CORTEX_A53);
28
.class_init = musicpal_key_class_init,
30
-#else
31
-MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A15, KVM_ARM_TARGET_CORTEX_A15);
32
-MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A7, KVM_ARM_TARGET_CORTEX_A7);
33
-#endif
34
35
#define CP_REG_ARM64 0x6000000000000000ULL
36
#define CP_REG_ARM_COPROC_MASK 0x000000000FFF0000
37
@@ -XXX,XX +XXX,XX @@ MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A7, KVM_ARM_TARGET_CORTEX_A7);
38
/* No kernel define but it's useful to QEMU */
39
#define CP_REG_ARM64_SYSREG_CP (CP_REG_ARM64_SYSREG >> CP_REG_ARM_COPROC_SHIFT)
40
41
-#ifdef TARGET_AARCH64
42
MISMATCH_CHECK(CP_REG_ARM64, KVM_REG_ARM64);
43
MISMATCH_CHECK(CP_REG_ARM_COPROC_MASK, KVM_REG_ARM_COPROC_MASK);
44
MISMATCH_CHECK(CP_REG_ARM_COPROC_SHIFT, KVM_REG_ARM_COPROC_SHIFT);
45
@@ -XXX,XX +XXX,XX @@ MISMATCH_CHECK(CP_REG_ARM64_SYSREG_CRM_MASK, KVM_REG_ARM64_SYSREG_CRM_MASK);
46
MISMATCH_CHECK(CP_REG_ARM64_SYSREG_CRM_SHIFT, KVM_REG_ARM64_SYSREG_CRM_SHIFT);
47
MISMATCH_CHECK(CP_REG_ARM64_SYSREG_OP2_MASK, KVM_REG_ARM64_SYSREG_OP2_MASK);
48
MISMATCH_CHECK(CP_REG_ARM64_SYSREG_OP2_SHIFT, KVM_REG_ARM64_SYSREG_OP2_SHIFT);
49
-#endif
50
51
#undef MISMATCH_CHECK
52
53
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/kvm_arm.h
56
+++ b/target/arm/kvm_arm.h
57
@@ -XXX,XX +XXX,XX @@ static inline const char *gic_class_name(void)
58
static inline const char *gicv3_class_name(void)
59
{
60
if (kvm_irqchip_in_kernel()) {
61
-#ifdef TARGET_AARCH64
62
return "kvm-arm-gicv3";
63
-#else
64
- error_report("KVM GICv3 acceleration is not supported on this "
65
- "platform");
66
- exit(1);
67
-#endif
68
} else {
69
if (kvm_enabled()) {
70
error_report("Userspace GICv3 is not supported with KVM");
71
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/target/arm/cpu.c
74
+++ b/target/arm/cpu.c
75
@@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj)
76
}
77
78
#ifndef TARGET_AARCH64
79
-/* -cpu max: if KVM is enabled, like -cpu host (best possible with this host);
80
- * otherwise, a CPU with as many features enabled as our emulation supports.
81
+/*
82
+ * -cpu max: a CPU with as many features enabled as our emulation supports.
83
* The version of '-cpu max' for qemu-system-aarch64 is defined in cpu64.c;
84
- * this only needs to handle 32 bits.
85
+ * this only needs to handle 32 bits, and need not care about KVM.
86
*/
87
static void arm_max_initfn(Object *obj)
88
{
89
ARMCPU *cpu = ARM_CPU(obj);
90
91
- if (kvm_enabled()) {
92
- kvm_arm_set_cpu_features_from_host(cpu);
93
- } else {
94
- cortex_a15_initfn(obj);
95
+ cortex_a15_initfn(obj);
96
97
- /* old-style VFP short-vector support */
98
- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
99
+ /* old-style VFP short-vector support */
100
+ cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
101
102
#ifdef CONFIG_USER_ONLY
103
- /* We don't set these in system emulation mode for the moment,
104
- * since we don't correctly set (all of) the ID registers to
105
- * advertise them.
106
- */
107
- set_feature(&cpu->env, ARM_FEATURE_V8);
108
- {
109
- uint32_t t;
110
+ /*
111
+ * We don't set these in system emulation mode for the moment,
112
+ * since we don't correctly set (all of) the ID registers to
113
+ * advertise them.
114
+ */
115
+ set_feature(&cpu->env, ARM_FEATURE_V8);
116
+ {
117
+ uint32_t t;
118
119
- t = cpu->isar.id_isar5;
120
- t = FIELD_DP32(t, ID_ISAR5, AES, 2);
121
- t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
122
- t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
123
- t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
124
- t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
125
- t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
126
- cpu->isar.id_isar5 = t;
127
+ t = cpu->isar.id_isar5;
128
+ t = FIELD_DP32(t, ID_ISAR5, AES, 2);
129
+ t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
130
+ t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
131
+ t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
132
+ t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
133
+ t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
134
+ cpu->isar.id_isar5 = t;
135
136
- t = cpu->isar.id_isar6;
137
- t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
138
- t = FIELD_DP32(t, ID_ISAR6, DP, 1);
139
- t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
140
- t = FIELD_DP32(t, ID_ISAR6, SB, 1);
141
- t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
142
- cpu->isar.id_isar6 = t;
143
+ t = cpu->isar.id_isar6;
144
+ t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
145
+ t = FIELD_DP32(t, ID_ISAR6, DP, 1);
146
+ t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
147
+ t = FIELD_DP32(t, ID_ISAR6, SB, 1);
148
+ t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
149
+ cpu->isar.id_isar6 = t;
150
151
- t = cpu->isar.mvfr1;
152
- t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */
153
- t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
154
- cpu->isar.mvfr1 = t;
155
+ t = cpu->isar.mvfr1;
156
+ t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */
157
+ t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
158
+ cpu->isar.mvfr1 = t;
159
160
- t = cpu->isar.mvfr2;
161
- t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
162
- t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
163
- cpu->isar.mvfr2 = t;
164
+ t = cpu->isar.mvfr2;
165
+ t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
166
+ t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
167
+ cpu->isar.mvfr2 = t;
168
169
- t = cpu->isar.id_mmfr3;
170
- t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
171
- cpu->isar.id_mmfr3 = t;
172
+ t = cpu->isar.id_mmfr3;
173
+ t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
174
+ cpu->isar.id_mmfr3 = t;
175
176
- t = cpu->isar.id_mmfr4;
177
- t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
178
- t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
179
- t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
180
- t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
181
- cpu->isar.id_mmfr4 = t;
182
- }
183
-#endif
184
+ t = cpu->isar.id_mmfr4;
185
+ t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
186
+ t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
187
+ t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
188
+ t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
189
+ cpu->isar.id_mmfr4 = t;
190
}
191
+#endif
192
}
193
#endif
194
195
@@ -XXX,XX +XXX,XX @@ static void arm_host_initfn(Object *obj)
196
197
static const TypeInfo host_arm_cpu_type_info = {
198
.name = TYPE_ARM_HOST_CPU,
199
-#ifdef TARGET_AARCH64
200
.parent = TYPE_AARCH64_CPU,
201
-#else
202
- .parent = TYPE_ARM_CPU,
203
-#endif
204
.instance_init = arm_host_initfn,
205
};
29
};
206
30
207
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
31
+#define FLASH_SECTOR_SIZE (64 * KiB)
208
index XXXXXXX..XXXXXXX 100644
32
+
209
--- a/target/arm/kvm.c
33
static struct arm_boot_info musicpal_binfo = {
210
+++ b/target/arm/kvm.c
34
.loader_start = 0x0,
211
@@ -XXX,XX +XXX,XX @@ int kvm_arch_process_async_events(CPUState *cs)
35
.board_id = 0x20e,
212
return 0;
36
@@ -XXX,XX +XXX,XX @@ static void musicpal_init(MachineState *machine)
213
}
37
BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
214
38
215
-/* The #ifdef protections are until 32bit headers are imported and can
39
flash_size = blk_getlength(blk);
216
- * be removed once both 32 and 64 bit reach feature parity.
40
- if (flash_size != 8*1024*1024 && flash_size != 16*1024*1024 &&
217
- */
41
- flash_size != 32*1024*1024) {
218
void kvm_arch_update_guest_debug(CPUState *cs, struct kvm_guest_debug *dbg)
42
+ if (flash_size != 8 * MiB && flash_size != 16 * MiB &&
219
{
43
+ flash_size != 32 * MiB) {
220
-#ifdef KVM_GUESTDBG_USE_SW_BP
44
error_report("Invalid flash image size");
221
if (kvm_sw_breakpoints_active(cs)) {
45
exit(1);
222
dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP;
46
}
223
}
47
@@ -XXX,XX +XXX,XX @@ static void musicpal_init(MachineState *machine)
224
-#endif
48
*/
225
-#ifdef KVM_GUESTDBG_USE_HW
49
pflash_cfi02_register(0x100000000ULL - MP_FLASH_SIZE_MAX,
226
if (kvm_arm_hw_debug_active(cs)) {
50
"musicpal.flash", flash_size,
227
dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW;
51
- blk, 0x10000,
228
kvm_arm_copy_hw_debug_data(&dbg->arch);
52
+ blk, FLASH_SECTOR_SIZE,
229
}
53
MP_FLASH_SIZE_MAX / flash_size,
230
-#endif
54
2, 0x00BF, 0x236D, 0x0000, 0x0000,
231
}
55
0x5555, 0x2AAA, 0);
232
233
void kvm_arch_init_irq_routing(KVMState *s)
234
--
56
--
235
2.20.1
57
2.34.1
236
58
237
59
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
This is a minimalistic boot ROM written specifically for use with QEMU.
3
The total_ram_v1/total_ram_v2 definitions were never used.
4
It supports loading the second-stage loader from SPI flash into RAM, SMP
5
boot, and not much else.
6
4
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
7
Message-id: 20230109115316.2235-10-philmd@linaro.org
10
Message-id: 20200911052101.2602693-7-hskinnemoen@google.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
9
---
13
.gitmodules | 3 +++
10
hw/arm/omap_sx1.c | 2 --
14
MAINTAINERS | 2 ++
11
1 file changed, 2 deletions(-)
15
pc-bios/README | 6 ++++++
16
pc-bios/meson.build | 1 +
17
pc-bios/npcm7xx_bootrom.bin | Bin 0 -> 768 bytes
18
roms/Makefile | 7 +++++++
19
roms/vbootrom | 1 +
20
7 files changed, 20 insertions(+)
21
create mode 100644 pc-bios/npcm7xx_bootrom.bin
22
create mode 160000 roms/vbootrom
23
12
24
diff --git a/.gitmodules b/.gitmodules
13
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
25
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
26
--- a/.gitmodules
15
--- a/hw/arm/omap_sx1.c
27
+++ b/.gitmodules
16
+++ b/hw/arm/omap_sx1.c
28
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps static_ops = {
29
[submodule "meson"]
18
#define flash0_size    (16 * 1024 * 1024)
30
    path = meson
19
#define flash1_size    ( 8 * 1024 * 1024)
31
    url = https://github.com/mesonbuild/meson/
20
#define flash2_size    (32 * 1024 * 1024)
32
+[submodule "roms/vbootrom"]
21
-#define total_ram_v1    (sdram_size + flash0_size + flash1_size + OMAP15XX_SRAM_SIZE)
33
+    path = roms/vbootrom
22
-#define total_ram_v2    (sdram_size + flash2_size + OMAP15XX_SRAM_SIZE)
34
+    url = https://github.com/google/vbootrom.git
23
35
diff --git a/MAINTAINERS b/MAINTAINERS
24
static struct arm_boot_info sx1_binfo = {
36
index XXXXXXX..XXXXXXX 100644
25
.loader_start = OMAP_EMIFF_BASE,
37
--- a/MAINTAINERS
38
+++ b/MAINTAINERS
39
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
40
S: Supported
41
F: hw/*/npcm7xx*
42
F: include/hw/*/npcm7xx*
43
+F: pc-bios/npcm7xx_bootrom.bin
44
+F: roms/vbootrom
45
46
nSeries
47
M: Andrzej Zaborowski <balrogg@gmail.com>
48
diff --git a/pc-bios/README b/pc-bios/README
49
index XXXXXXX..XXXXXXX 100644
50
--- a/pc-bios/README
51
+++ b/pc-bios/README
52
@@ -XXX,XX +XXX,XX @@
53
("Simplified BSD License" or "FreeBSD License", SPDX: BSD-2-Clause). OpenSBI
54
source code also contains code reused from other projects desribed here:
55
https://github.com/riscv/opensbi/blob/master/ThirdPartyNotices.md.
56
+
57
+- npcm7xx_bootrom.bin is a simplified, free (Apache 2.0) boot ROM for Nuvoton
58
+ NPCM7xx BMC devices. It currently implements the bare minimum to load, parse,
59
+ initialize and run boot images stored in SPI flash, but may grow more
60
+ features over time as needed. The source code is available at:
61
+ https://github.com/google/vbootrom
62
diff --git a/pc-bios/meson.build b/pc-bios/meson.build
63
index XXXXXXX..XXXXXXX 100644
64
--- a/pc-bios/meson.build
65
+++ b/pc-bios/meson.build
66
@@ -XXX,XX +XXX,XX @@ blobs = files(
67
'opensbi-riscv64-generic-fw_dynamic.bin',
68
'opensbi-riscv32-generic-fw_dynamic.elf',
69
'opensbi-riscv64-generic-fw_dynamic.elf',
70
+ 'npcm7xx_bootrom.bin',
71
)
72
73
if install_blobs
74
diff --git a/pc-bios/npcm7xx_bootrom.bin b/pc-bios/npcm7xx_bootrom.bin
75
new file mode 100644
76
index XXXXXXX..XXXXXXX
77
GIT binary patch
78
literal 768
79
zcmd5)JxClu6n-<aczPbVhZYusb8wKx;7TklHfmuZdYT9pDRLwd1p_t-DFpWpyA+8(
80
zwKtZg3J4a0aCM3_X(ZL&4g;46VVk5e$K;z;L99|b@aE%v^S$rQ8)h(Vm@cB9IYc+2
81
z2SHd4^NwTIGE%w>9S05p1#kf90Sj5Z(jG8}+)IZIp~iXK=T&)dL`%d-q*8aR#mq{7
82
z9`=6;Dr(H0ACe72R5x?!)^86Qj-X%{+!K9iZNA@*wkBAV&iZ(l^I9?!Gz=S2I_*1d
83
zr+tTQDHjvyzKnw(hu00yX`u!Fv<!~XVcX?@kr#<B0(gGU?$W{gSsQa}CF^8Cfzp2X
84
z@P}yDV-bci(K9XL$FU!som2C`c)?Uc&294s^}Wzumap{hg1X^jN|V25M5tQZ=<9lN
85
z%(zKz#t-qCwHKb;HygOCpvCNL_4@1tXV1YGf^XUE_$zr{g8zWh-6gz-teI(eibtxo
86
z?0OZI4%rU0741PgUD`2xq@H|*4=+Rs?%N)Ox5G+q>C;DilBe_YlkeSUVHA-crNk+k
87
jtiF_MudA<CB(}8|fqYwCf3re&=&@_s761P#-ID$TwgmBa
88
89
literal 0
90
HcmV?d00001
91
92
diff --git a/roms/Makefile b/roms/Makefile
93
index XXXXXXX..XXXXXXX 100644
94
--- a/roms/Makefile
95
+++ b/roms/Makefile
96
@@ -XXX,XX +XXX,XX @@ find-cross-gcc = $(firstword $(wildcard $(patsubst %ld,%gcc,$(call find-cross-ld
97
# finally strip off path + toolname so we get the prefix
98
find-cross-prefix = $(subst gcc,,$(notdir $(call find-cross-gcc,$(1))))
99
100
+arm_cross_prefix := $(call find-cross-prefix,arm)
101
powerpc64_cross_prefix := $(call find-cross-prefix,powerpc64)
102
powerpc_cross_prefix := $(call find-cross-prefix,powerpc)
103
x86_64_cross_prefix := $(call find-cross-prefix,x86_64)
104
@@ -XXX,XX +XXX,XX @@ default help:
105
    @echo " skiboot -- update skiboot.lid"
106
    @echo " u-boot.e500 -- update u-boot.e500"
107
    @echo " u-boot.sam460 -- update u-boot.sam460"
108
+    @echo " npcm7xx_bootrom -- update vbootrom for npcm7xx"
109
    @echo " efi -- update UEFI (edk2) platform firmware"
110
    @echo " opensbi32-generic -- update OpenSBI for 32-bit generic machine"
111
    @echo " opensbi64-generic -- update OpenSBI for 64-bit generic machine"
112
@@ -XXX,XX +XXX,XX @@ bios-microvm:
113
    $(MAKE) -C qboot
114
    cp qboot/bios.bin ../pc-bios/bios-microvm.bin
115
116
+npcm7xx_bootrom:
117
+    $(MAKE) -C vbootrom CROSS_COMPILE=$(arm_cross_prefix)
118
+    cp vbootrom/npcm7xx_bootrom.bin ../pc-bios/npcm7xx_bootrom.bin
119
+
120
clean:
121
    rm -rf seabios/.config seabios/out seabios/builds
122
    $(MAKE) -C sgabios clean
123
@@ -XXX,XX +XXX,XX @@ clean:
124
    $(MAKE) -f Makefile.edk2 clean
125
    $(MAKE) -C opensbi clean
126
    $(MAKE) -C qboot clean
127
+    $(MAKE) -C vbootrom clean
128
diff --git a/roms/vbootrom b/roms/vbootrom
129
new file mode 160000
130
index XXXXXXX..XXXXXXX
131
--- /dev/null
132
+++ b/roms/vbootrom
133
@@ -0,0 +1 @@
134
+Subproject commit 0c37a43527f0ee2b9584e7fb2fdc805e902635ac
135
--
26
--
136
2.20.1
27
2.34.1
137
28
138
29
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
If a -bios option is specified on the command line, load the image into
3
IEC binary prefixes ease code review: the unit is explicit.
4
the internal ROM memory region, which contains the first instructions
5
run by the CPU after reset.
6
4
7
If -bios is not specified, the vbootrom included with qemu is loaded by
5
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
default.
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
7
Message-id: 20230109115316.2235-11-philmd@linaro.org
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
11
Reviewed-by: Cédric Le Goater <clg@kaod.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
15
Message-id: 20200911052101.2602693-8-hskinnemoen@google.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
9
---
18
hw/arm/npcm7xx_boards.c | 32 ++++++++++++++++++++++++++++++++
10
hw/arm/omap_sx1.c | 33 +++++++++++++++++----------------
19
1 file changed, 32 insertions(+)
11
1 file changed, 17 insertions(+), 16 deletions(-)
20
12
21
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
13
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
22
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/npcm7xx_boards.c
15
--- a/hw/arm/omap_sx1.c
24
+++ b/hw/arm/npcm7xx_boards.c
16
+++ b/hw/arm/omap_sx1.c
25
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@
26
#include "exec/address-spaces.h"
18
* with this program; if not, see <http://www.gnu.org/licenses/>.
27
#include "hw/arm/npcm7xx.h"
19
*/
28
#include "hw/core/cpu.h"
20
#include "qemu/osdep.h"
29
+#include "hw/loader.h"
21
+#include "qemu/units.h"
30
#include "qapi/error.h"
22
#include "qapi/error.h"
31
+#include "qemu-common.h"
23
#include "ui/console.h"
32
#include "qemu/units.h"
24
#include "hw/arm/omap.h"
33
+#include "sysemu/sysemu.h"
25
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps static_ops = {
34
26
.endianness = DEVICE_NATIVE_ENDIAN,
35
#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
27
};
36
#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
28
37
29
-#define sdram_size    0x02000000
38
+static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin";
30
-#define sector_size    (128 * 1024)
39
+
31
-#define flash0_size    (16 * 1024 * 1024)
40
+static void npcm7xx_load_bootrom(MachineState *machine, NPCM7xxState *soc)
32
-#define flash1_size    ( 8 * 1024 * 1024)
41
+{
33
-#define flash2_size    (32 * 1024 * 1024)
42
+ g_autofree char *filename = NULL;
34
+#define SDRAM_SIZE (32 * MiB)
43
+ int ret;
35
+#define SECTOR_SIZE (128 * KiB)
44
+
36
+#define FLASH0_SIZE (16 * MiB)
45
+ if (!bios_name) {
37
+#define FLASH1_SIZE (8 * MiB)
46
+ bios_name = npcm7xx_default_bootrom;
38
+#define FLASH2_SIZE (32 * MiB)
47
+ }
39
48
+
40
static struct arm_boot_info sx1_binfo = {
49
+ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
41
.loader_start = OMAP_EMIFF_BASE,
50
+ if (!filename) {
42
- .ram_size = sdram_size,
51
+ error_report("Could not find ROM image '%s'", bios_name);
43
+ .ram_size = SDRAM_SIZE,
52
+ if (!machine->kernel_filename) {
44
.board_id = 0x265,
53
+ /* We can't boot without a bootrom or a kernel image. */
45
};
54
+ exit(1);
46
55
+ }
47
@@ -XXX,XX +XXX,XX @@ static void sx1_init(MachineState *machine, const int version)
56
+ return;
48
static uint32_t cs3val = 0x00001139;
57
+ }
49
DriveInfo *dinfo;
58
+ ret = load_image_mr(filename, &soc->irom);
50
int fl_idx;
59
+ if (ret < 0) {
51
- uint32_t flash_size = flash0_size;
60
+ error_report("Failed to load ROM image '%s'", filename);
52
+ uint32_t flash_size = FLASH0_SIZE;
61
+ exit(1);
53
62
+ }
54
if (machine->ram_size != mc->default_ram_size) {
63
+}
55
char *sz = size_to_str(mc->default_ram_size);
64
+
56
@@ -XXX,XX +XXX,XX @@ static void sx1_init(MachineState *machine, const int version)
65
static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
57
}
66
{
58
67
memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
59
if (version == 2) {
68
@@ -XXX,XX +XXX,XX @@ static void npcm750_evb_init(MachineState *machine)
60
- flash_size = flash2_size;
69
npcm7xx_connect_dram(soc, machine->ram);
61
+ flash_size = FLASH2_SIZE;
70
qdev_realize(DEVICE(soc), NULL, &error_fatal);
62
}
71
63
72
+ npcm7xx_load_bootrom(machine, soc);
64
memory_region_add_subregion(address_space, OMAP_EMIFF_BASE, machine->ram);
73
npcm7xx_load_kernel(machine, soc);
65
@@ -XXX,XX +XXX,XX @@ static void sx1_init(MachineState *machine, const int version)
66
if (!pflash_cfi01_register(OMAP_CS0_BASE,
67
"omap_sx1.flash0-1", flash_size,
68
blk_by_legacy_dinfo(dinfo),
69
- sector_size, 4, 0, 0, 0, 0, 0)) {
70
+ SECTOR_SIZE, 4, 0, 0, 0, 0, 0)) {
71
fprintf(stderr, "qemu: Error registering flash memory %d.\n",
72
fl_idx);
73
}
74
@@ -XXX,XX +XXX,XX @@ static void sx1_init(MachineState *machine, const int version)
75
(dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
76
MemoryRegion *flash_1 = g_new(MemoryRegion, 1);
77
memory_region_init_rom(flash_1, NULL, "omap_sx1.flash1-0",
78
- flash1_size, &error_fatal);
79
+ FLASH1_SIZE, &error_fatal);
80
memory_region_add_subregion(address_space, OMAP_CS1_BASE, flash_1);
81
82
memory_region_init_io(&cs[1], NULL, &static_ops, &cs1val,
83
- "sx1.cs1", OMAP_CS1_SIZE - flash1_size);
84
+ "sx1.cs1", OMAP_CS1_SIZE - FLASH1_SIZE);
85
memory_region_add_subregion(address_space,
86
- OMAP_CS1_BASE + flash1_size, &cs[1]);
87
+ OMAP_CS1_BASE + FLASH1_SIZE, &cs[1]);
88
89
if (!pflash_cfi01_register(OMAP_CS1_BASE,
90
- "omap_sx1.flash1-1", flash1_size,
91
+ "omap_sx1.flash1-1", FLASH1_SIZE,
92
blk_by_legacy_dinfo(dinfo),
93
- sector_size, 4, 0, 0, 0, 0, 0)) {
94
+ SECTOR_SIZE, 4, 0, 0, 0, 0, 0)) {
95
fprintf(stderr, "qemu: Error registering flash memory %d.\n",
96
fl_idx);
97
}
98
@@ -XXX,XX +XXX,XX @@ static void sx1_machine_v2_class_init(ObjectClass *oc, void *data)
99
mc->init = sx1_init_v2;
100
mc->ignore_memory_transaction_failures = true;
101
mc->default_cpu_type = ARM_CPU_TYPE_NAME("ti925t");
102
- mc->default_ram_size = sdram_size;
103
+ mc->default_ram_size = SDRAM_SIZE;
104
mc->default_ram_id = "omap1.dram";
74
}
105
}
75
106
76
@@ -XXX,XX +XXX,XX @@ static void quanta_gsj_init(MachineState *machine)
107
@@ -XXX,XX +XXX,XX @@ static void sx1_machine_v1_class_init(ObjectClass *oc, void *data)
77
npcm7xx_connect_dram(soc, machine->ram);
108
mc->init = sx1_init_v1;
78
qdev_realize(DEVICE(soc), NULL, &error_fatal);
109
mc->ignore_memory_transaction_failures = true;
79
110
mc->default_cpu_type = ARM_CPU_TYPE_NAME("ti925t");
80
+ npcm7xx_load_bootrom(machine, soc);
111
- mc->default_ram_size = sdram_size;
81
npcm7xx_load_kernel(machine, soc);
112
+ mc->default_ram_size = SDRAM_SIZE;
113
mc->default_ram_id = "omap1.dram";
82
}
114
}
83
115
84
--
116
--
85
2.20.1
117
2.34.1
86
118
87
119
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
This adds two new machines, both supported by OpenBMC:
3
IEC binary prefixes ease code review: the unit is explicit.
4
4
5
- npcm750-evb: Nuvoton NPCM750 Evaluation Board.
5
Add the FLASH_SECTOR_SIZE definition.
6
- quanta-gsj: A board with a NPCM730 chip.
7
6
8
They rely on the NPCM7xx SoC device to do the heavy lifting. They are
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
almost completely identical at the moment, apart from the SoC type,
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
which currently only changes the reset contents of one register
9
Message-id: 20230109115316.2235-12-philmd@linaro.org
11
(GCR.MDLR), but they might grow apart a bit more as more functionality
12
is added.
13
14
Both machines can boot the Linux kernel into /bin/sh.
15
16
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
17
Reviewed-by: Joel Stanley <joel@jms.id.au>
18
Reviewed-by: Cédric Le Goater <clg@kaod.org>
19
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
21
Tested-by: Alexander Bulekov <alxndr@bu.edu>
22
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
23
Message-id: 20200911052101.2602693-6-hskinnemoen@google.com
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
---
11
---
26
default-configs/arm-softmmu.mak | 1 +
12
hw/arm/z2.c | 6 ++++--
27
include/hw/arm/npcm7xx.h | 19 +++++
13
1 file changed, 4 insertions(+), 2 deletions(-)
28
hw/arm/npcm7xx_boards.c | 145 ++++++++++++++++++++++++++++++++
29
hw/arm/meson.build | 2 +-
30
4 files changed, 166 insertions(+), 1 deletion(-)
31
create mode 100644 hw/arm/npcm7xx_boards.c
32
14
33
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
15
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
34
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
35
--- a/default-configs/arm-softmmu.mak
17
--- a/hw/arm/z2.c
36
+++ b/default-configs/arm-softmmu.mak
18
+++ b/hw/arm/z2.c
37
@@ -XXX,XX +XXX,XX @@ CONFIG_GUMSTIX=y
38
CONFIG_SPITZ=y
39
CONFIG_TOSA=y
40
CONFIG_Z2=y
41
+CONFIG_NPCM7XX=y
42
CONFIG_COLLIE=y
43
CONFIG_ASPEED_SOC=y
44
CONFIG_NETDUINO2=y
45
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/include/hw/arm/npcm7xx.h
48
+++ b/include/hw/arm/npcm7xx.h
49
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
50
#define NPCM7XX_SMP_BOOTREG_ADDR (0xf080013c) /* GCR.SCRPAD */
20
*/
51
#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100) /* GIC within A9 */
21
52
22
#include "qemu/osdep.h"
53
+typedef struct NPCM7xxMachine {
23
+#include "qemu/units.h"
54
+ MachineState parent;
24
#include "hw/arm/pxa.h"
55
+} NPCM7xxMachine;
25
#include "hw/arm/boot.h"
26
#include "hw/i2c/i2c.h"
27
@@ -XXX,XX +XXX,XX @@ static const TypeInfo aer915_info = {
28
.class_init = aer915_class_init,
29
};
30
31
+#define FLASH_SECTOR_SIZE (64 * KiB)
56
+
32
+
57
+#define TYPE_NPCM7XX_MACHINE MACHINE_TYPE_NAME("npcm7xx")
33
static void z2_init(MachineState *machine)
58
+#define NPCM7XX_MACHINE(obj) \
34
{
59
+ OBJECT_CHECK(NPCM7xxMachine, (obj), TYPE_NPCM7XX_MACHINE)
35
- uint32_t sector_len = 0x10000;
60
+
36
PXA2xxState *mpu;
61
+typedef struct NPCM7xxMachineClass {
37
DriveInfo *dinfo;
62
+ MachineClass parent;
38
void *z2_lcd;
63
+
39
@@ -XXX,XX +XXX,XX @@ static void z2_init(MachineState *machine)
64
+ const char *soc_type;
40
dinfo = drive_get(IF_PFLASH, 0, 0);
65
+} NPCM7xxMachineClass;
41
if (!pflash_cfi01_register(Z2_FLASH_BASE, "z2.flash0", Z2_FLASH_SIZE,
66
+
42
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
67
+#define NPCM7XX_MACHINE_CLASS(klass) \
43
- sector_len, 4, 0, 0, 0, 0, 0)) {
68
+ OBJECT_CLASS_CHECK(NPCM7xxMachineClass, (klass), TYPE_NPCM7XX_MACHINE)
44
+ FLASH_SECTOR_SIZE, 4, 0, 0, 0, 0, 0)) {
69
+#define NPCM7XX_MACHINE_GET_CLASS(obj) \
45
error_report("Error registering flash memory");
70
+ OBJECT_GET_CLASS(NPCM7xxMachineClass, (obj), TYPE_NPCM7XX_MACHINE)
46
exit(1);
71
+
47
}
72
typedef struct NPCM7xxState {
73
DeviceState parent;
74
75
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
76
new file mode 100644
77
index XXXXXXX..XXXXXXX
78
--- /dev/null
79
+++ b/hw/arm/npcm7xx_boards.c
80
@@ -XXX,XX +XXX,XX @@
81
+/*
82
+ * Machine definitions for boards featuring an NPCM7xx SoC.
83
+ *
84
+ * Copyright 2020 Google LLC
85
+ *
86
+ * This program is free software; you can redistribute it and/or modify it
87
+ * under the terms of the GNU General Public License as published by the
88
+ * Free Software Foundation; either version 2 of the License, or
89
+ * (at your option) any later version.
90
+ *
91
+ * This program is distributed in the hope that it will be useful, but WITHOUT
92
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
93
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
94
+ * for more details.
95
+ */
96
+
97
+#include "qemu/osdep.h"
98
+
99
+#include "exec/address-spaces.h"
100
+#include "hw/arm/npcm7xx.h"
101
+#include "hw/core/cpu.h"
102
+#include "qapi/error.h"
103
+#include "qemu/units.h"
104
+
105
+#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
106
+#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
107
+
108
+static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
109
+{
110
+ memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
111
+
112
+ object_property_set_link(OBJECT(soc), "dram-mr", OBJECT(dram),
113
+ &error_abort);
114
+}
115
+
116
+static NPCM7xxState *npcm7xx_create_soc(MachineState *machine,
117
+ uint32_t hw_straps)
118
+{
119
+ NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine);
120
+ MachineClass *mc = &nmc->parent;
121
+ Object *obj;
122
+
123
+ if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
124
+ error_report("This board can only be used with %s",
125
+ mc->default_cpu_type);
126
+ exit(1);
127
+ }
128
+
129
+ obj = object_new_with_props(nmc->soc_type, OBJECT(machine), "soc",
130
+ &error_abort, NULL);
131
+ object_property_set_uint(obj, "power-on-straps", hw_straps, &error_abort);
132
+
133
+ return NPCM7XX(obj);
134
+}
135
+
136
+static void npcm750_evb_init(MachineState *machine)
137
+{
138
+ NPCM7xxState *soc;
139
+
140
+ soc = npcm7xx_create_soc(machine, NPCM750_EVB_POWER_ON_STRAPS);
141
+ npcm7xx_connect_dram(soc, machine->ram);
142
+ qdev_realize(DEVICE(soc), NULL, &error_fatal);
143
+
144
+ npcm7xx_load_kernel(machine, soc);
145
+}
146
+
147
+static void quanta_gsj_init(MachineState *machine)
148
+{
149
+ NPCM7xxState *soc;
150
+
151
+ soc = npcm7xx_create_soc(machine, QUANTA_GSJ_POWER_ON_STRAPS);
152
+ npcm7xx_connect_dram(soc, machine->ram);
153
+ qdev_realize(DEVICE(soc), NULL, &error_fatal);
154
+
155
+ npcm7xx_load_kernel(machine, soc);
156
+}
157
+
158
+static void npcm7xx_set_soc_type(NPCM7xxMachineClass *nmc, const char *type)
159
+{
160
+ NPCM7xxClass *sc = NPCM7XX_CLASS(object_class_by_name(type));
161
+ MachineClass *mc = MACHINE_CLASS(nmc);
162
+
163
+ nmc->soc_type = type;
164
+ mc->default_cpus = mc->min_cpus = mc->max_cpus = sc->num_cpus;
165
+}
166
+
167
+static void npcm7xx_machine_class_init(ObjectClass *oc, void *data)
168
+{
169
+ MachineClass *mc = MACHINE_CLASS(oc);
170
+
171
+ mc->no_floppy = 1;
172
+ mc->no_cdrom = 1;
173
+ mc->no_parallel = 1;
174
+ mc->default_ram_id = "ram";
175
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a9");
176
+}
177
+
178
+/*
179
+ * Schematics:
180
+ * https://github.com/Nuvoton-Israel/nuvoton-info/blob/master/npcm7xx-poleg/evaluation-board/board_deliverables/NPCM750x_EB_ver.A1.1_COMPLETE.pdf
181
+ */
182
+static void npcm750_evb_machine_class_init(ObjectClass *oc, void *data)
183
+{
184
+ NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_CLASS(oc);
185
+ MachineClass *mc = MACHINE_CLASS(oc);
186
+
187
+ npcm7xx_set_soc_type(nmc, TYPE_NPCM750);
188
+
189
+ mc->desc = "Nuvoton NPCM750 Evaluation Board (Cortex A9)";
190
+ mc->init = npcm750_evb_init;
191
+ mc->default_ram_size = 512 * MiB;
192
+};
193
+
194
+static void gsj_machine_class_init(ObjectClass *oc, void *data)
195
+{
196
+ NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_CLASS(oc);
197
+ MachineClass *mc = MACHINE_CLASS(oc);
198
+
199
+ npcm7xx_set_soc_type(nmc, TYPE_NPCM730);
200
+
201
+ mc->desc = "Quanta GSJ (Cortex A9)";
202
+ mc->init = quanta_gsj_init;
203
+ mc->default_ram_size = 512 * MiB;
204
+};
205
+
206
+static const TypeInfo npcm7xx_machine_types[] = {
207
+ {
208
+ .name = TYPE_NPCM7XX_MACHINE,
209
+ .parent = TYPE_MACHINE,
210
+ .instance_size = sizeof(NPCM7xxMachine),
211
+ .class_size = sizeof(NPCM7xxMachineClass),
212
+ .class_init = npcm7xx_machine_class_init,
213
+ .abstract = true,
214
+ }, {
215
+ .name = MACHINE_TYPE_NAME("npcm750-evb"),
216
+ .parent = TYPE_NPCM7XX_MACHINE,
217
+ .class_init = npcm750_evb_machine_class_init,
218
+ }, {
219
+ .name = MACHINE_TYPE_NAME("quanta-gsj"),
220
+ .parent = TYPE_NPCM7XX_MACHINE,
221
+ .class_init = gsj_machine_class_init,
222
+ },
223
+};
224
+
225
+DEFINE_TYPES(npcm7xx_machine_types)
226
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
227
index XXXXXXX..XXXXXXX 100644
228
--- a/hw/arm/meson.build
229
+++ b/hw/arm/meson.build
230
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'CONFIG_MICROBIT', if_true: files('microbit.c'))
231
arm_ss.add(when: 'CONFIG_MUSICPAL', if_true: files('musicpal.c'))
232
arm_ss.add(when: 'CONFIG_NETDUINO2', if_true: files('netduino2.c'))
233
arm_ss.add(when: 'CONFIG_NETDUINOPLUS2', if_true: files('netduinoplus2.c'))
234
-arm_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx.c'))
235
+arm_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx.c', 'npcm7xx_boards.c'))
236
arm_ss.add(when: 'CONFIG_NSERIES', if_true: files('nseries.c'))
237
arm_ss.add(when: 'CONFIG_SX1', if_true: files('omap_sx1.c'))
238
arm_ss.add(when: 'CONFIG_CHEETAH', if_true: files('palm.c'))
239
--
48
--
240
2.20.1
49
2.34.1
241
50
242
51
diff view generated by jsdifflib
1
The VCMLA and VCADD insns have a size field which is 0 for fp16
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
and 1 for fp32 (note that this is the reverse of the Neon 3-same
3
encoding!). Convert it to MO_* values in decode for consistency.
4
2
3
Upon introduction in commit b8433303fb ("Set proper device-width
4
for vexpress flash"), ve_pflash_cfi01_register() was calling
5
qdev_init_nofail() which can not fail. This call was later
6
converted with a script to use &error_fatal, still unable to
7
fail. Remove the unreachable code.
8
9
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20230109115316.2235-13-philmd@linaro.org
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: 20200903133209.5141-4-peter.maydell@linaro.org
8
---
13
---
9
target/arm/neon-shared.decode | 18 ++++++++++++------
14
hw/arm/vexpress.c | 10 +---------
10
target/arm/translate-neon.c.inc | 22 ++++++++++++----------
15
1 file changed, 1 insertion(+), 9 deletions(-)
11
2 files changed, 24 insertions(+), 16 deletions(-)
12
16
13
diff --git a/target/arm/neon-shared.decode b/target/arm/neon-shared.decode
17
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-shared.decode
19
--- a/hw/arm/vexpress.c
16
+++ b/target/arm/neon-shared.decode
20
+++ b/hw/arm/vexpress.c
17
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ static void vexpress_common_init(MachineState *machine)
18
%vd_dp 22:1 12:4
22
dinfo = drive_get(IF_PFLASH, 0, 0);
19
%vd_sp 12:4 22:1
23
pflash0 = ve_pflash_cfi01_register(map[VE_NORFLASH0], "vexpress.flash0",
20
24
dinfo);
21
-VCMLA 1111 110 rot:2 . 1 size:1 .... .... 1000 . q:1 . 0 .... \
25
- if (!pflash0) {
22
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
26
- error_report("vexpress: error registering flash 0");
23
+# For VCMLA/VCADD insns, convert the single-bit size field
27
- exit(1);
24
+# which is 0 for fp16 and 1 for fp32 into a MO_* constant.
28
- }
25
+# (Note that this is the reverse of the sense of the 1-bit size
29
26
+# field in the 3same_fp Neon insns.)
30
if (map[VE_NORFLASHALIAS] != -1) {
27
+%vcadd_size 20:1 !function=plus1
31
/* Map flash 0 as an alias into low memory */
28
32
@@ -XXX,XX +XXX,XX @@ static void vexpress_common_init(MachineState *machine)
29
-VCADD 1111 110 rot:1 1 . 0 size:1 .... .... 1000 . q:1 . 0 .... \
30
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
31
+VCMLA 1111 110 rot:2 . 1 . .... .... 1000 . q:1 . 0 .... \
32
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp size=%vcadd_size
33
+
34
+VCADD 1111 110 rot:1 1 . 0 . .... .... 1000 . q:1 . 0 .... \
35
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp size=%vcadd_size
36
37
# VUDOT and VSDOT
38
VDOT 1111 110 00 . 10 .... .... 1101 . q:1 . u:1 .... \
39
@@ -XXX,XX +XXX,XX @@ VFML 1111 110 0 s:1 . 10 .... .... 1000 . 1 . 1 .... \
40
vm=%vm_dp vn=%vn_dp vd=%vd_dp q=1
41
42
VCMLA_scalar 1111 1110 0 . rot:2 .... .... 1000 . q:1 index:1 0 vm:4 \
43
- vn=%vn_dp vd=%vd_dp size=0
44
+ vn=%vn_dp vd=%vd_dp size=1
45
VCMLA_scalar 1111 1110 1 . rot:2 .... .... 1000 . q:1 . 0 .... \
46
- vm=%vm_dp vn=%vn_dp vd=%vd_dp size=1 index=0
47
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp size=2 index=0
48
49
VDOT_scalar 1111 1110 0 . 10 .... .... 1101 . q:1 index:1 u:1 rm:4 \
50
vm=%vm_dp vn=%vn_dp vd=%vd_dp
51
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/translate-neon.c.inc
54
+++ b/target/arm/translate-neon.c.inc
55
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA(DisasContext *s, arg_VCMLA *a)
56
gen_helper_gvec_3_ptr *fn_gvec_ptr;
57
58
if (!dc_isar_feature(aa32_vcma, s)
59
- || (!a->size && !dc_isar_feature(aa32_fp16_arith, s))) {
60
+ || (a->size == MO_16 && !dc_isar_feature(aa32_fp16_arith, s))) {
61
return false;
62
}
33
}
63
34
64
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA(DisasContext *s, arg_VCMLA *a)
35
dinfo = drive_get(IF_PFLASH, 0, 1);
65
}
36
- if (!ve_pflash_cfi01_register(map[VE_NORFLASH1], "vexpress.flash1",
66
37
- dinfo)) {
67
opr_sz = (1 + a->q) * 8;
38
- error_report("vexpress: error registering flash 1");
68
- fpst = fpstatus_ptr(a->size == 0 ? FPST_STD_F16 : FPST_STD);
39
- exit(1);
69
- fn_gvec_ptr = a->size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
40
- }
70
+ fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
41
+ ve_pflash_cfi01_register(map[VE_NORFLASH1], "vexpress.flash1", dinfo);
71
+ fn_gvec_ptr = (a->size == MO_16) ?
42
72
+ gen_helper_gvec_fcmlah : gen_helper_gvec_fcmlas;
43
sram_size = 0x2000000;
73
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
44
memory_region_init_ram(sram, NULL, "vexpress.sram", sram_size,
74
vfp_reg_offset(1, a->vn),
75
vfp_reg_offset(1, a->vm),
76
@@ -XXX,XX +XXX,XX @@ static bool trans_VCADD(DisasContext *s, arg_VCADD *a)
77
gen_helper_gvec_3_ptr *fn_gvec_ptr;
78
79
if (!dc_isar_feature(aa32_vcma, s)
80
- || (!a->size && !dc_isar_feature(aa32_fp16_arith, s))) {
81
+ || (a->size == MO_16 && !dc_isar_feature(aa32_fp16_arith, s))) {
82
return false;
83
}
84
85
@@ -XXX,XX +XXX,XX @@ static bool trans_VCADD(DisasContext *s, arg_VCADD *a)
86
}
87
88
opr_sz = (1 + a->q) * 8;
89
- fpst = fpstatus_ptr(a->size == 0 ? FPST_STD_F16 : FPST_STD);
90
- fn_gvec_ptr = a->size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
91
+ fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
92
+ fn_gvec_ptr = (a->size == MO_16) ?
93
+ gen_helper_gvec_fcaddh : gen_helper_gvec_fcadds;
94
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
95
vfp_reg_offset(1, a->vn),
96
vfp_reg_offset(1, a->vm),
97
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA_scalar(DisasContext *s, arg_VCMLA_scalar *a)
98
if (!dc_isar_feature(aa32_vcma, s)) {
99
return false;
100
}
101
- if (a->size == 0 && !dc_isar_feature(aa32_fp16_arith, s)) {
102
+ if (a->size == MO_16 && !dc_isar_feature(aa32_fp16_arith, s)) {
103
return false;
104
}
105
106
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA_scalar(DisasContext *s, arg_VCMLA_scalar *a)
107
return true;
108
}
109
110
- fn_gvec_ptr = (a->size ? gen_helper_gvec_fcmlas_idx
111
- : gen_helper_gvec_fcmlah_idx);
112
+ fn_gvec_ptr = (a->size == MO_16) ?
113
+ gen_helper_gvec_fcmlah_idx : gen_helper_gvec_fcmlas_idx;
114
opr_sz = (1 + a->q) * 8;
115
- fpst = fpstatus_ptr(a->size == 0 ? FPST_STD_F16 : FPST_STD);
116
+ fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
117
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
118
vfp_reg_offset(1, a->vn),
119
vfp_reg_offset(1, a->vm),
120
--
45
--
121
2.20.1
46
2.34.1
122
47
123
48
diff view generated by jsdifflib
1
In the Neon instructions, some instruction formats have a 2-bit size
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
field which corresponds exactly to QEMU's MO_8/16/32/64. However the
3
floating-point insns in the 3-same group have a 1-bit size field
4
which is "0 for 32-bit float and 1 for 16-bit float". Currently we
5
pass these values directly through to trans_ functions, which means
6
that when reading a particular trans_ function you need to know if
7
that insn uses a 2-bit size or a 1-bit size.
8
2
9
Move the handling of the 1-bit size to the decodetree file, so that
3
Since its QOM'ification in commit 368a354f02 ("pflash_cfi0x:
10
all these insns consistently pass a size to the trans_ function which
4
QOMified") the pflash_cfi01_register() function does not fail.
11
is an MO_8/16/32/64 value.
12
5
13
In this commit we switch over the insns using the 3same_fp and
6
This call was later converted with a script to use &error_fatal,
14
3same_fp_q0 formats.
7
still unable to fail. Remove the unreachable code.
15
8
9
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20230109115316.2235-14-philmd@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 20200903133209.5141-2-peter.maydell@linaro.org
19
---
13
---
20
target/arm/neon-dp.decode | 15 ++++++++++-----
14
hw/arm/gumstix.c | 18 ++++++------------
21
target/arm/translate-neon.c.inc | 16 +++++++++++-----
15
hw/arm/mainstone.c | 13 +++++--------
22
2 files changed, 21 insertions(+), 10 deletions(-)
16
hw/arm/omap_sx1.c | 22 ++++++++--------------
17
hw/arm/versatilepb.c | 6 ++----
18
hw/arm/z2.c | 9 +++------
19
5 files changed, 24 insertions(+), 44 deletions(-)
23
20
24
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
21
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
25
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/neon-dp.decode
23
--- a/hw/arm/gumstix.c
27
+++ b/target/arm/neon-dp.decode
24
+++ b/hw/arm/gumstix.c
28
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ static void connex_init(MachineState *machine)
29
@3same_q0 .... ... . . . size:2 .... .... .... . 0 . . .... \
26
}
30
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
27
31
28
/* Numonyx RC28F128J3F75 */
32
-# For FP insns the high bit of 'size' is used as part of opcode decode
29
- if (!pflash_cfi01_register(0x00000000, "connext.rom", CONNEX_FLASH_SIZE,
33
-@3same_fp .... ... . . . . size:1 .... .... .... . q:1 . . .... \
30
- dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
34
- &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
31
- FLASH_SECTOR_SIZE, 2, 0, 0, 0, 0, 0)) {
35
-@3same_fp_q0 .... ... . . . . size:1 .... .... .... . 0 . . .... \
32
- error_report("Error registering flash memory");
36
- &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
33
- exit(1);
37
+# For FP insns the high bit of 'size' is used as part of opcode decode,
34
- }
38
+# and the 'size' bit is 0 for 32-bit float and 1 for 16-bit float.
35
+ pflash_cfi01_register(0x00000000, "connext.rom", CONNEX_FLASH_SIZE,
39
+# This converts this encoding to the same MO_8/16/32/64 values that the
36
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
40
+# integer neon insns use.
37
+ FLASH_SECTOR_SIZE, 2, 0, 0, 0, 0, 0);
41
+%3same_fp_size 20:1 !function=neon_3same_fp_size
38
42
+
39
/* Interrupt line of NIC is connected to GPIO line 36 */
43
+@3same_fp .... ... . . . . . .... .... .... . q:1 . . .... \
40
smc91c111_init(&nd_table[0], 0x04000300,
44
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp size=%3same_fp_size
41
@@ -XXX,XX +XXX,XX @@ static void verdex_init(MachineState *machine)
45
+@3same_fp_q0 .... ... . . . . . .... .... .... . 0 . . .... \
42
}
46
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0 size=%3same_fp_size
43
47
44
/* Micron RC28F256P30TFA */
48
VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same
45
- if (!pflash_cfi01_register(0x00000000, "verdex.rom", VERDEX_FLASH_SIZE,
49
VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same
46
- dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
50
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
47
- FLASH_SECTOR_SIZE, 2, 0, 0, 0, 0, 0)) {
48
- error_report("Error registering flash memory");
49
- exit(1);
50
- }
51
+ pflash_cfi01_register(0x00000000, "verdex.rom", VERDEX_FLASH_SIZE,
52
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
53
+ FLASH_SECTOR_SIZE, 2, 0, 0, 0, 0, 0);
54
55
/* Interrupt line of NIC is connected to GPIO line 99 */
56
smc91c111_init(&nd_table[0], 0x04000300,
57
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
51
index XXXXXXX..XXXXXXX 100644
58
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/translate-neon.c.inc
59
--- a/hw/arm/mainstone.c
53
+++ b/target/arm/translate-neon.c.inc
60
+++ b/hw/arm/mainstone.c
54
@@ -XXX,XX +XXX,XX @@ static inline int rsub_8(DisasContext *s, int x)
61
@@ -XXX,XX +XXX,XX @@ static void mainstone_common_init(MachineState *machine,
55
return 8 - x;
62
/* There are two 32MiB flash devices on the board */
56
}
63
for (i = 0; i < 2; i ++) {
57
64
dinfo = drive_get(IF_PFLASH, 0, i);
58
+static inline int neon_3same_fp_size(DisasContext *s, int x)
65
- if (!pflash_cfi01_register(mainstone_flash_base[i],
59
+{
66
- i ? "mainstone.flash1" : "mainstone.flash0",
60
+ /* Convert 0==fp32, 1==fp16 into a MO_* value */
67
- MAINSTONE_FLASH_SIZE,
61
+ return MO_32 - x;
68
- dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
62
+}
69
- FLASH_SECTOR_SIZE, 4, 0, 0, 0, 0, 0)) {
63
+
70
- error_report("Error registering flash memory");
64
/* Include the generated Neon decoder */
71
- exit(1);
65
#include "decode-neon-dp.c.inc"
72
- }
66
#include "decode-neon-ls.c.inc"
73
+ pflash_cfi01_register(mainstone_flash_base[i],
67
@@ -XXX,XX +XXX,XX @@ DO_3SAME_VQDMULH(VQRDMULH, qrdmulh)
74
+ i ? "mainstone.flash1" : "mainstone.flash0",
68
WRAP_FP_GVEC(gen_##INSN##_fp16_3s, FPST_STD_F16, HFUNC) \
75
+ MAINSTONE_FLASH_SIZE,
69
static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
76
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
70
{ \
77
+ FLASH_SECTOR_SIZE, 4, 0, 0, 0, 0, 0);
71
- if (a->size != 0) { \
72
+ if (a->size == MO_16) { \
73
if (!dc_isar_feature(aa32_fp16_arith, s)) { \
74
return false; \
75
} \
76
@@ -XXX,XX +XXX,XX @@ static bool trans_VMAXNM_fp_3s(DisasContext *s, arg_3same *a)
77
return false;
78
}
78
}
79
79
80
- if (a->size != 0) {
80
mst_irq = sysbus_create_simple("mainstone-fpga", MST_FPGA_PHYS,
81
+ if (a->size == MO_16) {
81
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
82
if (!dc_isar_feature(aa32_fp16_arith, s)) {
82
index XXXXXXX..XXXXXXX 100644
83
return false;
83
--- a/hw/arm/omap_sx1.c
84
}
84
+++ b/hw/arm/omap_sx1.c
85
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINNM_fp_3s(DisasContext *s, arg_3same *a)
85
@@ -XXX,XX +XXX,XX @@ static void sx1_init(MachineState *machine, const int version)
86
return false;
86
87
fl_idx = 0;
88
if ((dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
89
- if (!pflash_cfi01_register(OMAP_CS0_BASE,
90
- "omap_sx1.flash0-1", flash_size,
91
- blk_by_legacy_dinfo(dinfo),
92
- SECTOR_SIZE, 4, 0, 0, 0, 0, 0)) {
93
- fprintf(stderr, "qemu: Error registering flash memory %d.\n",
94
- fl_idx);
95
- }
96
+ pflash_cfi01_register(OMAP_CS0_BASE,
97
+ "omap_sx1.flash0-1", flash_size,
98
+ blk_by_legacy_dinfo(dinfo),
99
+ SECTOR_SIZE, 4, 0, 0, 0, 0, 0);
100
fl_idx++;
87
}
101
}
88
102
89
- if (a->size != 0) {
103
@@ -XXX,XX +XXX,XX @@ static void sx1_init(MachineState *machine, const int version)
90
+ if (a->size == MO_16) {
104
memory_region_add_subregion(address_space,
91
if (!dc_isar_feature(aa32_fp16_arith, s)) {
105
OMAP_CS1_BASE + FLASH1_SIZE, &cs[1]);
92
return false;
106
93
}
107
- if (!pflash_cfi01_register(OMAP_CS1_BASE,
94
@@ -XXX,XX +XXX,XX @@ static bool do_3same_fp_pair(DisasContext *s, arg_3same *a,
108
- "omap_sx1.flash1-1", FLASH1_SIZE,
95
assert(a->q == 0); /* enforced by decode patterns */
109
- blk_by_legacy_dinfo(dinfo),
96
110
- SECTOR_SIZE, 4, 0, 0, 0, 0, 0)) {
97
111
- fprintf(stderr, "qemu: Error registering flash memory %d.\n",
98
- fpstatus = fpstatus_ptr(a->size != 0 ? FPST_STD_F16 : FPST_STD);
112
- fl_idx);
99
+ fpstatus = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
113
- }
100
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
114
+ pflash_cfi01_register(OMAP_CS1_BASE,
101
vfp_reg_offset(1, a->vn),
115
+ "omap_sx1.flash1-1", FLASH1_SIZE,
102
vfp_reg_offset(1, a->vm),
116
+ blk_by_legacy_dinfo(dinfo),
103
@@ -XXX,XX +XXX,XX @@ static bool do_3same_fp_pair(DisasContext *s, arg_3same *a,
117
+ SECTOR_SIZE, 4, 0, 0, 0, 0, 0);
104
#define DO_3S_FP_PAIR(INSN,FUNC) \
118
fl_idx++;
105
static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
119
} else {
106
{ \
120
memory_region_init_io(&cs[1], NULL, &static_ops, &cs1val,
107
- if (a->size != 0) { \
121
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
108
+ if (a->size == MO_16) { \
122
index XXXXXXX..XXXXXXX 100644
109
if (!dc_isar_feature(aa32_fp16_arith, s)) { \
123
--- a/hw/arm/versatilepb.c
110
return false; \
124
+++ b/hw/arm/versatilepb.c
111
} \
125
@@ -XXX,XX +XXX,XX @@ static void versatile_init(MachineState *machine, int board_id)
126
/* 0x34000000 NOR Flash */
127
128
dinfo = drive_get(IF_PFLASH, 0, 0);
129
- if (!pflash_cfi01_register(VERSATILE_FLASH_ADDR, "versatile.flash",
130
+ pflash_cfi01_register(VERSATILE_FLASH_ADDR, "versatile.flash",
131
VERSATILE_FLASH_SIZE,
132
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
133
VERSATILE_FLASH_SECT_SIZE,
134
- 4, 0x0089, 0x0018, 0x0000, 0x0, 0)) {
135
- fprintf(stderr, "qemu: Error registering flash memory.\n");
136
- }
137
+ 4, 0x0089, 0x0018, 0x0000, 0x0, 0);
138
139
versatile_binfo.ram_size = machine->ram_size;
140
versatile_binfo.board_id = board_id;
141
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
142
index XXXXXXX..XXXXXXX 100644
143
--- a/hw/arm/z2.c
144
+++ b/hw/arm/z2.c
145
@@ -XXX,XX +XXX,XX @@ static void z2_init(MachineState *machine)
146
mpu = pxa270_init(z2_binfo.ram_size, machine->cpu_type);
147
148
dinfo = drive_get(IF_PFLASH, 0, 0);
149
- if (!pflash_cfi01_register(Z2_FLASH_BASE, "z2.flash0", Z2_FLASH_SIZE,
150
- dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
151
- FLASH_SECTOR_SIZE, 4, 0, 0, 0, 0, 0)) {
152
- error_report("Error registering flash memory");
153
- exit(1);
154
- }
155
+ pflash_cfi01_register(Z2_FLASH_BASE, "z2.flash0", Z2_FLASH_SIZE,
156
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
157
+ FLASH_SECTOR_SIZE, 4, 0, 0, 0, 0, 0);
158
159
/* setup keypad */
160
pxa27x_register_keypad(mpu->kp, map, 0x100);
112
--
161
--
113
2.20.1
162
2.34.1
114
163
115
164
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
Correct the GEMs tx/rx clocks to use the 125Mhz fixed-clock.
3
To avoid forward-declaring PXA2xxI2CState, declare
4
This matches the setup with the fixed-link 100Mbit PHY.
4
PXA2XX_I2C before its use in pxa2xx_i2c_init() prototype.
5
It also avoids the following warnings from the Linux kernel
6
driver:
7
5
8
eth0: unable to generate target frequency: 125000000 Hz
6
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20230109140306.23161-2-philmd@linaro.org
11
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
12
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
13
Message-id: 20200909174647.662864-2-edgar.iglesias@gmail.com
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
10
---
16
hw/arm/xlnx-versal-virt.c | 2 +-
11
include/hw/arm/pxa.h | 6 +++---
17
1 file changed, 1 insertion(+), 1 deletion(-)
12
1 file changed, 3 insertions(+), 3 deletions(-)
18
13
19
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
14
diff --git a/include/hw/arm/pxa.h b/include/hw/arm/pxa.h
20
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/arm/xlnx-versal-virt.c
16
--- a/include/hw/arm/pxa.h
22
+++ b/hw/arm/xlnx-versal-virt.c
17
+++ b/include/hw/arm/pxa.h
23
@@ -XXX,XX +XXX,XX @@ static void fdt_add_gem_nodes(VersalVirt *s)
18
@@ -XXX,XX +XXX,XX @@ void pxa27x_register_keypad(PXA2xxKeyPadState *kp,
24
s->phandle.ethernet_phy[i]);
19
const struct keymap *map, int size);
25
qemu_fdt_setprop_cells(s->fdt, name, "clocks",
20
26
s->phandle.clk_25Mhz, s->phandle.clk_25Mhz,
21
/* pxa2xx.c */
27
- s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
22
-typedef struct PXA2xxI2CState PXA2xxI2CState;
28
+ s->phandle.clk_125Mhz, s->phandle.clk_125Mhz);
23
+#define TYPE_PXA2XX_I2C "pxa2xx_i2c"
29
qemu_fdt_setprop(s->fdt, name, "clock-names",
24
+OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxI2CState, PXA2XX_I2C)
30
clocknames, sizeof(clocknames));
25
+
31
qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
26
PXA2xxI2CState *pxa2xx_i2c_init(hwaddr base,
27
qemu_irq irq, uint32_t page_size);
28
I2CBus *pxa2xx_i2c_bus(PXA2xxI2CState *s);
29
30
-#define TYPE_PXA2XX_I2C "pxa2xx_i2c"
31
typedef struct PXA2xxI2SState PXA2xxI2SState;
32
-OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxI2CState, PXA2XX_I2C)
33
34
#define TYPE_PXA2XX_FIR "pxa2xx-fir"
35
OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxFIrState, PXA2XX_FIR)
32
--
36
--
33
2.20.1
37
2.34.1
34
38
35
39
diff view generated by jsdifflib
1
Make the list of MPS2 boards consistent in the phrasing of each
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
entry, use the correct casing of "Arm", and move the mps2-an511
3
entry so the list is in numeric order.
4
2
3
Add a local 'struct omap_gpif_s *' variable to improve readability.
4
(This also eases next commit conversion).
5
6
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230109140306.23161-3-philmd@linaro.org
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>
7
Message-id: 20200903202048.15370-4-peter.maydell@linaro.org
8
---
10
---
9
docs/system/arm/mps2.rst | 14 +++++++-------
11
hw/gpio/omap_gpio.c | 3 ++-
10
1 file changed, 7 insertions(+), 7 deletions(-)
12
1 file changed, 2 insertions(+), 1 deletion(-)
11
13
12
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
14
diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/docs/system/arm/mps2.rst
16
--- a/hw/gpio/omap_gpio.c
15
+++ b/docs/system/arm/mps2.rst
17
+++ b/hw/gpio/omap_gpio.c
16
@@ -XXX,XX +XXX,XX @@ as seen by the guest depend significantly on the FPGA image.
18
@@ -XXX,XX +XXX,XX @@ struct omap_gpif_s {
17
QEMU models the following FPGA images:
19
/* General-Purpose I/O of OMAP1 */
18
20
static void omap_gpio_set(void *opaque, int line, int level)
19
``mps2-an385``
21
{
20
- Cortex-M3 as documented in ARM Application Note AN385
22
- struct omap_gpio_s *s = &((struct omap_gpif_s *) opaque)->omap1;
21
+ Cortex-M3 as documented in Arm Application Note AN385
23
+ struct omap_gpif_s *p = opaque;
22
``mps2-an386``
24
+ struct omap_gpio_s *s = &p->omap1;
23
- Cortex-M4 as documented in ARM Application Note AN386
25
uint16_t prev = s->inputs;
24
+ Cortex-M4 as documented in Arm Application Note AN386
26
25
``mps2-an500``
27
if (level)
26
- Cortex-M7 as documented in ARM Application Note AN500
27
-``mps2-an511``
28
- Cortex-M3 'DesignStart' as documented in AN511
29
+ Cortex-M7 as documented in Arm Application Note AN500
30
``mps2-an505``
31
- Cortex-M33 as documented in ARM Application Note AN505
32
+ Cortex-M33 as documented in Arm Application Note AN505
33
+``mps2-an511``
34
+ Cortex-M3 'DesignStart' as documented in Arm Application Note AN511
35
``mps2-an521``
36
- Dual Cortex-M33 as documented in Application Note AN521
37
+ Dual Cortex-M33 as documented in Arm Application Note AN521
38
39
Differences between QEMU and real hardware:
40
41
--
28
--
42
2.20.1
29
2.34.1
43
30
44
31
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
Per the datasheet (DDI0407 r2p0):
3
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
5
"All SCU registers are byte accessible" and are 32-bit aligned.
6
7
Set MemoryRegionOps::valid min/max fields and simplify the write()
8
handler.
9
10
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20200901144100.116742-3-f4bug@amsat.org
5
Message-id: 20230109140306.23161-4-philmd@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
7
---
15
hw/misc/a9scu.c | 21 +++++----------------
8
hw/arm/omap1.c | 115 ++++++++++++++++++--------------------
16
1 file changed, 5 insertions(+), 16 deletions(-)
9
hw/arm/omap2.c | 40 ++++++-------
10
hw/arm/omap_sx1.c | 2 +-
11
hw/arm/palm.c | 2 +-
12
hw/char/omap_uart.c | 7 +--
13
hw/display/omap_dss.c | 15 +++--
14
hw/display/omap_lcdc.c | 9 ++-
15
hw/dma/omap_dma.c | 15 +++--
16
hw/gpio/omap_gpio.c | 15 +++--
17
hw/intc/omap_intc.c | 12 ++--
18
hw/misc/omap_gpmc.c | 12 ++--
19
hw/misc/omap_l4.c | 7 +--
20
hw/misc/omap_sdrc.c | 7 +--
21
hw/misc/omap_tap.c | 5 +-
22
hw/sd/omap_mmc.c | 9 ++-
23
hw/ssi/omap_spi.c | 7 +--
24
hw/timer/omap_gptimer.c | 22 ++++----
25
hw/timer/omap_synctimer.c | 4 +-
26
18 files changed, 142 insertions(+), 163 deletions(-)
17
27
18
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
28
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
19
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/misc/a9scu.c
30
--- a/hw/arm/omap1.c
21
+++ b/hw/misc/a9scu.c
31
+++ b/hw/arm/omap1.c
22
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
32
@@ -XXX,XX +XXX,XX @@ static void omap_timer_fire(void *opaque)
23
uint64_t value, unsigned size)
33
24
{
34
static void omap_timer_tick(void *opaque)
25
A9SCUState *s = (A9SCUState *)opaque;
35
{
26
- uint32_t mask;
36
- struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
27
+ uint32_t mask = MAKE_64BIT_MASK(0, size * 8);
37
+ struct omap_mpu_timer_s *timer = opaque;
28
uint32_t shift;
38
29
- switch (size) {
39
omap_timer_sync(timer);
30
- case 1:
40
omap_timer_fire(timer);
31
- mask = 0xff;
41
@@ -XXX,XX +XXX,XX @@ static void omap_timer_tick(void *opaque)
32
- break;
42
33
- case 2:
43
static void omap_timer_clk_update(void *opaque, int line, int on)
34
- mask = 0xffff;
44
{
35
- break;
45
- struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
36
- case 4:
46
+ struct omap_mpu_timer_s *timer = opaque;
37
- mask = 0xffffffff;
47
38
- break;
48
omap_timer_sync(timer);
39
- default:
49
timer->rate = on ? omap_clk_getrate(timer->clk) : 0;
40
- fprintf(stderr, "Invalid size %u in write to a9 scu register %x\n",
50
@@ -XXX,XX +XXX,XX @@ static void omap_timer_clk_setup(struct omap_mpu_timer_s *timer)
41
- size, (unsigned)offset);
51
static uint64_t omap_mpu_timer_read(void *opaque, hwaddr addr,
42
- return;
52
unsigned size)
43
- }
53
{
54
- struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
55
+ struct omap_mpu_timer_s *s = opaque;
56
57
if (size != 4) {
58
return omap_badwidth_read32(opaque, addr);
59
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_mpu_timer_read(void *opaque, hwaddr addr,
60
static void omap_mpu_timer_write(void *opaque, hwaddr addr,
61
uint64_t value, unsigned size)
62
{
63
- struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
64
+ struct omap_mpu_timer_s *s = opaque;
65
66
if (size != 4) {
67
omap_badwidth_write32(opaque, addr, value);
68
@@ -XXX,XX +XXX,XX @@ struct omap_watchdog_timer_s {
69
static uint64_t omap_wd_timer_read(void *opaque, hwaddr addr,
70
unsigned size)
71
{
72
- struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
73
+ struct omap_watchdog_timer_s *s = opaque;
74
75
if (size != 2) {
76
return omap_badwidth_read16(opaque, addr);
77
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_wd_timer_read(void *opaque, hwaddr addr,
78
static void omap_wd_timer_write(void *opaque, hwaddr addr,
79
uint64_t value, unsigned size)
80
{
81
- struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
82
+ struct omap_watchdog_timer_s *s = opaque;
83
84
if (size != 2) {
85
omap_badwidth_write16(opaque, addr, value);
86
@@ -XXX,XX +XXX,XX @@ struct omap_32khz_timer_s {
87
static uint64_t omap_os_timer_read(void *opaque, hwaddr addr,
88
unsigned size)
89
{
90
- struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
91
+ struct omap_32khz_timer_s *s = opaque;
92
int offset = addr & OMAP_MPUI_REG_MASK;
93
94
if (size != 4) {
95
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_os_timer_read(void *opaque, hwaddr addr,
96
static void omap_os_timer_write(void *opaque, hwaddr addr,
97
uint64_t value, unsigned size)
98
{
99
- struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
100
+ struct omap_32khz_timer_s *s = opaque;
101
int offset = addr & OMAP_MPUI_REG_MASK;
102
103
if (size != 4) {
104
@@ -XXX,XX +XXX,XX @@ static struct omap_32khz_timer_s *omap_os_timer_init(MemoryRegion *memory,
105
static uint64_t omap_ulpd_pm_read(void *opaque, hwaddr addr,
106
unsigned size)
107
{
108
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
109
+ struct omap_mpu_state_s *s = opaque;
110
uint16_t ret;
111
112
if (size != 2) {
113
@@ -XXX,XX +XXX,XX @@ static inline void omap_ulpd_req_update(struct omap_mpu_state_s *s,
114
static void omap_ulpd_pm_write(void *opaque, hwaddr addr,
115
uint64_t value, unsigned size)
116
{
117
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
118
+ struct omap_mpu_state_s *s = opaque;
119
int64_t now, ticks;
120
int div, mult;
121
static const int bypass_div[4] = { 1, 2, 4, 4 };
122
@@ -XXX,XX +XXX,XX @@ static void omap_ulpd_pm_init(MemoryRegion *system_memory,
123
static uint64_t omap_pin_cfg_read(void *opaque, hwaddr addr,
124
unsigned size)
125
{
126
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
127
+ struct omap_mpu_state_s *s = opaque;
128
129
if (size != 4) {
130
return omap_badwidth_read32(opaque, addr);
131
@@ -XXX,XX +XXX,XX @@ static inline void omap_pin_modconf1_update(struct omap_mpu_state_s *s,
132
static void omap_pin_cfg_write(void *opaque, hwaddr addr,
133
uint64_t value, unsigned size)
134
{
135
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
136
+ struct omap_mpu_state_s *s = opaque;
137
uint32_t diff;
138
139
if (size != 4) {
140
@@ -XXX,XX +XXX,XX @@ static void omap_pin_cfg_init(MemoryRegion *system_memory,
141
static uint64_t omap_id_read(void *opaque, hwaddr addr,
142
unsigned size)
143
{
144
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
145
+ struct omap_mpu_state_s *s = opaque;
146
147
if (size != 4) {
148
return omap_badwidth_read32(opaque, addr);
149
@@ -XXX,XX +XXX,XX @@ static void omap_id_init(MemoryRegion *memory, struct omap_mpu_state_s *mpu)
150
static uint64_t omap_mpui_read(void *opaque, hwaddr addr,
151
unsigned size)
152
{
153
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
154
+ struct omap_mpu_state_s *s = opaque;
155
156
if (size != 4) {
157
return omap_badwidth_read32(opaque, addr);
158
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_mpui_read(void *opaque, hwaddr addr,
159
static void omap_mpui_write(void *opaque, hwaddr addr,
160
uint64_t value, unsigned size)
161
{
162
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
163
+ struct omap_mpu_state_s *s = opaque;
164
165
if (size != 4) {
166
omap_badwidth_write32(opaque, addr, value);
167
@@ -XXX,XX +XXX,XX @@ struct omap_tipb_bridge_s {
168
static uint64_t omap_tipb_bridge_read(void *opaque, hwaddr addr,
169
unsigned size)
170
{
171
- struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque;
172
+ struct omap_tipb_bridge_s *s = opaque;
173
174
if (size < 2) {
175
return omap_badwidth_read16(opaque, addr);
176
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_tipb_bridge_read(void *opaque, hwaddr addr,
177
static void omap_tipb_bridge_write(void *opaque, hwaddr addr,
178
uint64_t value, unsigned size)
179
{
180
- struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque;
181
+ struct omap_tipb_bridge_s *s = opaque;
182
183
if (size < 2) {
184
omap_badwidth_write16(opaque, addr, value);
185
@@ -XXX,XX +XXX,XX @@ static struct omap_tipb_bridge_s *omap_tipb_bridge_init(
186
static uint64_t omap_tcmi_read(void *opaque, hwaddr addr,
187
unsigned size)
188
{
189
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
190
+ struct omap_mpu_state_s *s = opaque;
191
uint32_t ret;
192
193
if (size != 4) {
194
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_tcmi_read(void *opaque, hwaddr addr,
195
static void omap_tcmi_write(void *opaque, hwaddr addr,
196
uint64_t value, unsigned size)
197
{
198
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
199
+ struct omap_mpu_state_s *s = opaque;
200
201
if (size != 4) {
202
omap_badwidth_write32(opaque, addr, value);
203
@@ -XXX,XX +XXX,XX @@ struct dpll_ctl_s {
204
static uint64_t omap_dpll_read(void *opaque, hwaddr addr,
205
unsigned size)
206
{
207
- struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque;
208
+ struct dpll_ctl_s *s = opaque;
209
210
if (size != 2) {
211
return omap_badwidth_read16(opaque, addr);
212
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_dpll_read(void *opaque, hwaddr addr,
213
static void omap_dpll_write(void *opaque, hwaddr addr,
214
uint64_t value, unsigned size)
215
{
216
- struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque;
217
+ struct dpll_ctl_s *s = opaque;
218
uint16_t diff;
219
static const int bypass_div[4] = { 1, 2, 4, 4 };
220
int div, mult;
221
@@ -XXX,XX +XXX,XX @@ static struct dpll_ctl_s *omap_dpll_init(MemoryRegion *memory,
222
static uint64_t omap_clkm_read(void *opaque, hwaddr addr,
223
unsigned size)
224
{
225
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
226
+ struct omap_mpu_state_s *s = opaque;
227
228
if (size != 2) {
229
return omap_badwidth_read16(opaque, addr);
230
@@ -XXX,XX +XXX,XX @@ static inline void omap_clkm_ckout1_update(struct omap_mpu_state_s *s,
231
static void omap_clkm_write(void *opaque, hwaddr addr,
232
uint64_t value, unsigned size)
233
{
234
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
235
+ struct omap_mpu_state_s *s = opaque;
236
uint16_t diff;
237
omap_clk clk;
238
static const char *clkschemename[8] = {
239
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps omap_clkm_ops = {
240
static uint64_t omap_clkdsp_read(void *opaque, hwaddr addr,
241
unsigned size)
242
{
243
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
244
+ struct omap_mpu_state_s *s = opaque;
245
CPUState *cpu = CPU(s->cpu);
246
247
if (size != 2) {
248
@@ -XXX,XX +XXX,XX @@ static inline void omap_clkdsp_idlect2_update(struct omap_mpu_state_s *s,
249
static void omap_clkdsp_write(void *opaque, hwaddr addr,
250
uint64_t value, unsigned size)
251
{
252
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
253
+ struct omap_mpu_state_s *s = opaque;
254
uint16_t diff;
255
256
if (size != 2) {
257
@@ -XXX,XX +XXX,XX @@ struct omap_mpuio_s {
258
259
static void omap_mpuio_set(void *opaque, int line, int level)
260
{
261
- struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
262
+ struct omap_mpuio_s *s = opaque;
263
uint16_t prev = s->inputs;
264
265
if (level)
266
@@ -XXX,XX +XXX,XX @@ static void omap_mpuio_kbd_update(struct omap_mpuio_s *s)
267
static uint64_t omap_mpuio_read(void *opaque, hwaddr addr,
268
unsigned size)
269
{
270
- struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
271
+ struct omap_mpuio_s *s = opaque;
272
int offset = addr & OMAP_MPUI_REG_MASK;
273
uint16_t ret;
274
275
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_mpuio_read(void *opaque, hwaddr addr,
276
static void omap_mpuio_write(void *opaque, hwaddr addr,
277
uint64_t value, unsigned size)
278
{
279
- struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
280
+ struct omap_mpuio_s *s = opaque;
281
int offset = addr & OMAP_MPUI_REG_MASK;
282
uint16_t diff;
283
int ln;
284
@@ -XXX,XX +XXX,XX @@ static void omap_mpuio_reset(struct omap_mpuio_s *s)
285
286
static void omap_mpuio_onoff(void *opaque, int line, int on)
287
{
288
- struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
289
+ struct omap_mpuio_s *s = opaque;
290
291
s->clk = on;
292
if (on)
293
@@ -XXX,XX +XXX,XX @@ static void omap_uwire_transfer_start(struct omap_uwire_s *s)
294
}
295
}
296
297
-static uint64_t omap_uwire_read(void *opaque, hwaddr addr,
298
- unsigned size)
299
+static uint64_t omap_uwire_read(void *opaque, hwaddr addr, unsigned size)
300
{
301
- struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
302
+ struct omap_uwire_s *s = opaque;
303
int offset = addr & OMAP_MPUI_REG_MASK;
304
305
if (size != 2) {
306
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_uwire_read(void *opaque, hwaddr addr,
307
static void omap_uwire_write(void *opaque, hwaddr addr,
308
uint64_t value, unsigned size)
309
{
310
- struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
311
+ struct omap_uwire_s *s = opaque;
312
int offset = addr & OMAP_MPUI_REG_MASK;
313
314
if (size != 2) {
315
@@ -XXX,XX +XXX,XX @@ static void omap_pwl_update(struct omap_pwl_s *s)
316
}
317
}
318
319
-static uint64_t omap_pwl_read(void *opaque, hwaddr addr,
320
- unsigned size)
321
+static uint64_t omap_pwl_read(void *opaque, hwaddr addr, unsigned size)
322
{
323
- struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
324
+ struct omap_pwl_s *s = opaque;
325
int offset = addr & OMAP_MPUI_REG_MASK;
326
327
if (size != 1) {
328
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_pwl_read(void *opaque, hwaddr addr,
329
static void omap_pwl_write(void *opaque, hwaddr addr,
330
uint64_t value, unsigned size)
331
{
332
- struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
333
+ struct omap_pwl_s *s = opaque;
334
int offset = addr & OMAP_MPUI_REG_MASK;
335
336
if (size != 1) {
337
@@ -XXX,XX +XXX,XX @@ static void omap_pwl_reset(struct omap_pwl_s *s)
338
339
static void omap_pwl_clk_update(void *opaque, int line, int on)
340
{
341
- struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
342
+ struct omap_pwl_s *s = opaque;
343
344
s->clk = on;
345
omap_pwl_update(s);
346
@@ -XXX,XX +XXX,XX @@ struct omap_pwt_s {
347
omap_clk clk;
348
};
349
350
-static uint64_t omap_pwt_read(void *opaque, hwaddr addr,
351
- unsigned size)
352
+static uint64_t omap_pwt_read(void *opaque, hwaddr addr, unsigned size)
353
{
354
- struct omap_pwt_s *s = (struct omap_pwt_s *) opaque;
355
+ struct omap_pwt_s *s = opaque;
356
int offset = addr & OMAP_MPUI_REG_MASK;
357
358
if (size != 1) {
359
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_pwt_read(void *opaque, hwaddr addr,
360
static void omap_pwt_write(void *opaque, hwaddr addr,
361
uint64_t value, unsigned size)
362
{
363
- struct omap_pwt_s *s = (struct omap_pwt_s *) opaque;
364
+ struct omap_pwt_s *s = opaque;
365
int offset = addr & OMAP_MPUI_REG_MASK;
366
367
if (size != 1) {
368
@@ -XXX,XX +XXX,XX @@ static void omap_rtc_alarm_update(struct omap_rtc_s *s)
369
printf("%s: conversion failed\n", __func__);
370
}
371
372
-static uint64_t omap_rtc_read(void *opaque, hwaddr addr,
373
- unsigned size)
374
+static uint64_t omap_rtc_read(void *opaque, hwaddr addr, unsigned size)
375
{
376
- struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
377
+ struct omap_rtc_s *s = opaque;
378
int offset = addr & OMAP_MPUI_REG_MASK;
379
uint8_t i;
380
381
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_rtc_read(void *opaque, hwaddr addr,
382
static void omap_rtc_write(void *opaque, hwaddr addr,
383
uint64_t value, unsigned size)
384
{
385
- struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
386
+ struct omap_rtc_s *s = opaque;
387
int offset = addr & OMAP_MPUI_REG_MASK;
388
struct tm new_tm;
389
time_t ti[2];
390
@@ -XXX,XX +XXX,XX @@ static void omap_mcbsp_rx_newdata(struct omap_mcbsp_s *s)
391
392
static void omap_mcbsp_source_tick(void *opaque)
393
{
394
- struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
395
+ struct omap_mcbsp_s *s = opaque;
396
static const int bps[8] = { 0, 1, 1, 2, 2, 2, -255, -255 };
397
398
if (!s->rx_rate)
399
@@ -XXX,XX +XXX,XX @@ static void omap_mcbsp_tx_newdata(struct omap_mcbsp_s *s)
400
401
static void omap_mcbsp_sink_tick(void *opaque)
402
{
403
- struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
404
+ struct omap_mcbsp_s *s = opaque;
405
static const int bps[8] = { 0, 1, 1, 2, 2, 2, -255, -255 };
406
407
if (!s->tx_rate)
408
@@ -XXX,XX +XXX,XX @@ static void omap_mcbsp_req_update(struct omap_mcbsp_s *s)
409
static uint64_t omap_mcbsp_read(void *opaque, hwaddr addr,
410
unsigned size)
411
{
412
- struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
413
+ struct omap_mcbsp_s *s = opaque;
414
int offset = addr & OMAP_MPUI_REG_MASK;
415
uint16_t ret;
416
417
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_mcbsp_read(void *opaque, hwaddr addr,
418
static void omap_mcbsp_writeh(void *opaque, hwaddr addr,
419
uint32_t value)
420
{
421
- struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
422
+ struct omap_mcbsp_s *s = opaque;
423
int offset = addr & OMAP_MPUI_REG_MASK;
44
424
45
switch (offset) {
425
switch (offset) {
46
case 0x00: /* Control */
426
@@ -XXX,XX +XXX,XX @@ static void omap_mcbsp_writeh(void *opaque, hwaddr addr,
47
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
427
static void omap_mcbsp_writew(void *opaque, hwaddr addr,
48
static const MemoryRegionOps a9_scu_ops = {
428
uint32_t value)
49
.read = a9_scu_read,
429
{
50
.write = a9_scu_write,
430
- struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
51
+ .valid = {
431
+ struct omap_mcbsp_s *s = opaque;
52
+ .min_access_size = 1,
432
int offset = addr & OMAP_MPUI_REG_MASK;
53
+ .max_access_size = 4,
433
54
+ },
434
if (offset == 0x04) {                /* DXR */
435
@@ -XXX,XX +XXX,XX @@ static struct omap_mcbsp_s *omap_mcbsp_init(MemoryRegion *system_memory,
436
437
static void omap_mcbsp_i2s_swallow(void *opaque, int line, int level)
438
{
439
- struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
440
+ struct omap_mcbsp_s *s = opaque;
441
442
if (s->rx_rate) {
443
s->rx_req = s->codec->in.len;
444
@@ -XXX,XX +XXX,XX @@ static void omap_mcbsp_i2s_swallow(void *opaque, int line, int level)
445
446
static void omap_mcbsp_i2s_start(void *opaque, int line, int level)
447
{
448
- struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
449
+ struct omap_mcbsp_s *s = opaque;
450
451
if (s->tx_rate) {
452
s->tx_req = s->codec->out.size;
453
@@ -XXX,XX +XXX,XX @@ static void omap_lpg_reset(struct omap_lpg_s *s)
454
omap_lpg_update(s);
455
}
456
457
-static uint64_t omap_lpg_read(void *opaque, hwaddr addr,
458
- unsigned size)
459
+static uint64_t omap_lpg_read(void *opaque, hwaddr addr, unsigned size)
460
{
461
- struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
462
+ struct omap_lpg_s *s = opaque;
463
int offset = addr & OMAP_MPUI_REG_MASK;
464
465
if (size != 1) {
466
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_lpg_read(void *opaque, hwaddr addr,
467
static void omap_lpg_write(void *opaque, hwaddr addr,
468
uint64_t value, unsigned size)
469
{
470
- struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
471
+ struct omap_lpg_s *s = opaque;
472
int offset = addr & OMAP_MPUI_REG_MASK;
473
474
if (size != 1) {
475
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps omap_lpg_ops = {
476
477
static void omap_lpg_clk_update(void *opaque, int line, int on)
478
{
479
- struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
480
+ struct omap_lpg_s *s = opaque;
481
482
s->clk = on;
483
omap_lpg_update(s);
484
@@ -XXX,XX +XXX,XX @@ static void omap_setup_mpui_io(MemoryRegion *system_memory,
485
/* General chip reset */
486
static void omap1_mpu_reset(void *opaque)
487
{
488
- struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
489
+ struct omap_mpu_state_s *mpu = opaque;
490
491
omap_dma_reset(mpu->dma);
492
omap_mpu_timer_reset(mpu->timer[0]);
493
@@ -XXX,XX +XXX,XX @@ static void omap_setup_dsp_mapping(MemoryRegion *system_memory,
494
495
void omap_mpu_wakeup(void *opaque, int irq, int req)
496
{
497
- struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
498
+ struct omap_mpu_state_s *mpu = opaque;
499
CPUState *cpu = CPU(mpu->cpu);
500
501
if (cpu->halted) {
502
diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c
503
index XXXXXXX..XXXXXXX 100644
504
--- a/hw/arm/omap2.c
505
+++ b/hw/arm/omap2.c
506
@@ -XXX,XX +XXX,XX @@ static inline void omap_eac_out_empty(struct omap_eac_s *s)
507
508
static void omap_eac_in_cb(void *opaque, int avail_b)
509
{
510
- struct omap_eac_s *s = (struct omap_eac_s *) opaque;
511
+ struct omap_eac_s *s = opaque;
512
513
s->codec.rxavail = avail_b >> 2;
514
omap_eac_in_refill(s);
515
@@ -XXX,XX +XXX,XX @@ static void omap_eac_in_cb(void *opaque, int avail_b)
516
517
static void omap_eac_out_cb(void *opaque, int free_b)
518
{
519
- struct omap_eac_s *s = (struct omap_eac_s *) opaque;
520
+ struct omap_eac_s *s = opaque;
521
522
s->codec.txavail = free_b >> 2;
523
if (s->codec.txlen)
524
@@ -XXX,XX +XXX,XX @@ static void omap_eac_reset(struct omap_eac_s *s)
525
omap_eac_interrupt_update(s);
526
}
527
528
-static uint64_t omap_eac_read(void *opaque, hwaddr addr,
529
- unsigned size)
530
+static uint64_t omap_eac_read(void *opaque, hwaddr addr, unsigned size)
531
{
532
- struct omap_eac_s *s = (struct omap_eac_s *) opaque;
533
+ struct omap_eac_s *s = opaque;
534
uint32_t ret;
535
536
if (size != 2) {
537
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_eac_read(void *opaque, hwaddr addr,
538
static void omap_eac_write(void *opaque, hwaddr addr,
539
uint64_t value, unsigned size)
540
{
541
- struct omap_eac_s *s = (struct omap_eac_s *) opaque;
542
+ struct omap_eac_s *s = opaque;
543
544
if (size != 2) {
545
omap_badwidth_write16(opaque, addr, value);
546
@@ -XXX,XX +XXX,XX @@ static void omap_sti_reset(struct omap_sti_s *s)
547
static uint64_t omap_sti_read(void *opaque, hwaddr addr,
548
unsigned size)
549
{
550
- struct omap_sti_s *s = (struct omap_sti_s *) opaque;
551
+ struct omap_sti_s *s = opaque;
552
553
if (size != 4) {
554
return omap_badwidth_read32(opaque, addr);
555
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_sti_read(void *opaque, hwaddr addr,
556
static void omap_sti_write(void *opaque, hwaddr addr,
557
uint64_t value, unsigned size)
558
{
559
- struct omap_sti_s *s = (struct omap_sti_s *) opaque;
560
+ struct omap_sti_s *s = opaque;
561
562
if (size != 4) {
563
omap_badwidth_write32(opaque, addr, value);
564
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps omap_sti_ops = {
55
.endianness = DEVICE_NATIVE_ENDIAN,
565
.endianness = DEVICE_NATIVE_ENDIAN,
56
};
566
};
57
567
568
-static uint64_t omap_sti_fifo_read(void *opaque, hwaddr addr,
569
- unsigned size)
570
+static uint64_t omap_sti_fifo_read(void *opaque, hwaddr addr, unsigned size)
571
{
572
OMAP_BAD_REG(addr);
573
return 0;
574
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_sti_fifo_read(void *opaque, hwaddr addr,
575
static void omap_sti_fifo_write(void *opaque, hwaddr addr,
576
uint64_t value, unsigned size)
577
{
578
- struct omap_sti_s *s = (struct omap_sti_s *) opaque;
579
+ struct omap_sti_s *s = opaque;
580
int ch = addr >> 6;
581
uint8_t byte = value;
582
583
@@ -XXX,XX +XXX,XX @@ static void omap_prcm_int_update(struct omap_prcm_s *s, int dom)
584
static uint64_t omap_prcm_read(void *opaque, hwaddr addr,
585
unsigned size)
586
{
587
- struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
588
+ struct omap_prcm_s *s = opaque;
589
uint32_t ret;
590
591
if (size != 4) {
592
@@ -XXX,XX +XXX,XX @@ static void omap_prcm_dpll_update(struct omap_prcm_s *s)
593
static void omap_prcm_write(void *opaque, hwaddr addr,
594
uint64_t value, unsigned size)
595
{
596
- struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
597
+ struct omap_prcm_s *s = opaque;
598
599
if (size != 4) {
600
omap_badwidth_write32(opaque, addr, value);
601
@@ -XXX,XX +XXX,XX @@ struct omap_sysctl_s {
602
static uint32_t omap_sysctl_read8(void *opaque, hwaddr addr)
603
{
604
605
- struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
606
+ struct omap_sysctl_s *s = opaque;
607
int pad_offset, byte_offset;
608
int value;
609
610
@@ -XXX,XX +XXX,XX @@ static uint32_t omap_sysctl_read8(void *opaque, hwaddr addr)
611
612
static uint32_t omap_sysctl_read(void *opaque, hwaddr addr)
613
{
614
- struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
615
+ struct omap_sysctl_s *s = opaque;
616
617
switch (addr) {
618
case 0x000:    /* CONTROL_REVISION */
619
@@ -XXX,XX +XXX,XX @@ static uint32_t omap_sysctl_read(void *opaque, hwaddr addr)
620
return 0;
621
}
622
623
-static void omap_sysctl_write8(void *opaque, hwaddr addr,
624
- uint32_t value)
625
+static void omap_sysctl_write8(void *opaque, hwaddr addr, uint32_t value)
626
{
627
- struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
628
+ struct omap_sysctl_s *s = opaque;
629
int pad_offset, byte_offset;
630
int prev_value;
631
632
@@ -XXX,XX +XXX,XX @@ static void omap_sysctl_write8(void *opaque, hwaddr addr,
633
}
634
}
635
636
-static void omap_sysctl_write(void *opaque, hwaddr addr,
637
- uint32_t value)
638
+static void omap_sysctl_write(void *opaque, hwaddr addr, uint32_t value)
639
{
640
- struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
641
+ struct omap_sysctl_s *s = opaque;
642
643
switch (addr) {
644
case 0x000:    /* CONTROL_REVISION */
645
@@ -XXX,XX +XXX,XX @@ static struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
646
/* General chip reset */
647
static void omap2_mpu_reset(void *opaque)
648
{
649
- struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
650
+ struct omap_mpu_state_s *mpu = opaque;
651
652
omap_dma_reset(mpu->dma);
653
omap_prcm_reset(mpu->prcm);
654
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
655
index XXXXXXX..XXXXXXX 100644
656
--- a/hw/arm/omap_sx1.c
657
+++ b/hw/arm/omap_sx1.c
658
@@ -XXX,XX +XXX,XX @@
659
static uint64_t static_read(void *opaque, hwaddr offset,
660
unsigned size)
661
{
662
- uint32_t *val = (uint32_t *) opaque;
663
+ uint32_t *val = opaque;
664
uint32_t mask = (4 / size) - 1;
665
666
return *val >> ((offset & mask) << 3);
667
diff --git a/hw/arm/palm.c b/hw/arm/palm.c
668
index XXXXXXX..XXXXXXX 100644
669
--- a/hw/arm/palm.c
670
+++ b/hw/arm/palm.c
671
@@ -XXX,XX +XXX,XX @@ static struct {
672
673
static void palmte_button_event(void *opaque, int keycode)
674
{
675
- struct omap_mpu_state_s *cpu = (struct omap_mpu_state_s *) opaque;
676
+ struct omap_mpu_state_s *cpu = opaque;
677
678
if (palmte_keymap[keycode & 0x7f].row != -1)
679
omap_mpuio_key(cpu->mpuio,
680
diff --git a/hw/char/omap_uart.c b/hw/char/omap_uart.c
681
index XXXXXXX..XXXXXXX 100644
682
--- a/hw/char/omap_uart.c
683
+++ b/hw/char/omap_uart.c
684
@@ -XXX,XX +XXX,XX @@ struct omap_uart_s *omap_uart_init(hwaddr base,
685
return s;
686
}
687
688
-static uint64_t omap_uart_read(void *opaque, hwaddr addr,
689
- unsigned size)
690
+static uint64_t omap_uart_read(void *opaque, hwaddr addr, unsigned size)
691
{
692
- struct omap_uart_s *s = (struct omap_uart_s *) opaque;
693
+ struct omap_uart_s *s = opaque;
694
695
if (size == 4) {
696
return omap_badwidth_read8(opaque, addr);
697
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_uart_read(void *opaque, hwaddr addr,
698
static void omap_uart_write(void *opaque, hwaddr addr,
699
uint64_t value, unsigned size)
700
{
701
- struct omap_uart_s *s = (struct omap_uart_s *) opaque;
702
+ struct omap_uart_s *s = opaque;
703
704
if (size == 4) {
705
omap_badwidth_write8(opaque, addr, value);
706
diff --git a/hw/display/omap_dss.c b/hw/display/omap_dss.c
707
index XXXXXXX..XXXXXXX 100644
708
--- a/hw/display/omap_dss.c
709
+++ b/hw/display/omap_dss.c
710
@@ -XXX,XX +XXX,XX @@ void omap_dss_reset(struct omap_dss_s *s)
711
static uint64_t omap_diss_read(void *opaque, hwaddr addr,
712
unsigned size)
713
{
714
- struct omap_dss_s *s = (struct omap_dss_s *) opaque;
715
+ struct omap_dss_s *s = opaque;
716
717
if (size != 4) {
718
return omap_badwidth_read32(opaque, addr);
719
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_diss_read(void *opaque, hwaddr addr,
720
static void omap_diss_write(void *opaque, hwaddr addr,
721
uint64_t value, unsigned size)
722
{
723
- struct omap_dss_s *s = (struct omap_dss_s *) opaque;
724
+ struct omap_dss_s *s = opaque;
725
726
if (size != 4) {
727
omap_badwidth_write32(opaque, addr, value);
728
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps omap_diss_ops = {
729
static uint64_t omap_disc_read(void *opaque, hwaddr addr,
730
unsigned size)
731
{
732
- struct omap_dss_s *s = (struct omap_dss_s *) opaque;
733
+ struct omap_dss_s *s = opaque;
734
735
if (size != 4) {
736
return omap_badwidth_read32(opaque, addr);
737
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_disc_read(void *opaque, hwaddr addr,
738
static void omap_disc_write(void *opaque, hwaddr addr,
739
uint64_t value, unsigned size)
740
{
741
- struct omap_dss_s *s = (struct omap_dss_s *) opaque;
742
+ struct omap_dss_s *s = opaque;
743
744
if (size != 4) {
745
omap_badwidth_write32(opaque, addr, value);
746
@@ -XXX,XX +XXX,XX @@ static void omap_rfbi_transfer_start(struct omap_dss_s *s)
747
omap_dispc_interrupt_update(s);
748
}
749
750
-static uint64_t omap_rfbi_read(void *opaque, hwaddr addr,
751
- unsigned size)
752
+static uint64_t omap_rfbi_read(void *opaque, hwaddr addr, unsigned size)
753
{
754
- struct omap_dss_s *s = (struct omap_dss_s *) opaque;
755
+ struct omap_dss_s *s = opaque;
756
757
if (size != 4) {
758
return omap_badwidth_read32(opaque, addr);
759
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_rfbi_read(void *opaque, hwaddr addr,
760
static void omap_rfbi_write(void *opaque, hwaddr addr,
761
uint64_t value, unsigned size)
762
{
763
- struct omap_dss_s *s = (struct omap_dss_s *) opaque;
764
+ struct omap_dss_s *s = opaque;
765
766
if (size != 4) {
767
omap_badwidth_write32(opaque, addr, value);
768
diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c
769
index XXXXXXX..XXXXXXX 100644
770
--- a/hw/display/omap_lcdc.c
771
+++ b/hw/display/omap_lcdc.c
772
@@ -XXX,XX +XXX,XX @@ static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
773
774
static void omap_update_display(void *opaque)
775
{
776
- struct omap_lcd_panel_s *omap_lcd = (struct omap_lcd_panel_s *) opaque;
777
+ struct omap_lcd_panel_s *omap_lcd = opaque;
778
DisplaySurface *surface;
779
drawfn draw_line;
780
int size, height, first, last;
781
@@ -XXX,XX +XXX,XX @@ static void omap_lcd_update(struct omap_lcd_panel_s *s) {
782
}
783
}
784
785
-static uint64_t omap_lcdc_read(void *opaque, hwaddr addr,
786
- unsigned size)
787
+static uint64_t omap_lcdc_read(void *opaque, hwaddr addr, unsigned size)
788
{
789
- struct omap_lcd_panel_s *s = (struct omap_lcd_panel_s *) opaque;
790
+ struct omap_lcd_panel_s *s = opaque;
791
792
switch (addr) {
793
case 0x00:    /* LCD_CONTROL */
794
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_lcdc_read(void *opaque, hwaddr addr,
795
static void omap_lcdc_write(void *opaque, hwaddr addr,
796
uint64_t value, unsigned size)
797
{
798
- struct omap_lcd_panel_s *s = (struct omap_lcd_panel_s *) opaque;
799
+ struct omap_lcd_panel_s *s = opaque;
800
801
switch (addr) {
802
case 0x00:    /* LCD_CONTROL */
803
diff --git a/hw/dma/omap_dma.c b/hw/dma/omap_dma.c
804
index XXXXXXX..XXXXXXX 100644
805
--- a/hw/dma/omap_dma.c
806
+++ b/hw/dma/omap_dma.c
807
@@ -XXX,XX +XXX,XX @@ static int omap_dma_sys_read(struct omap_dma_s *s, int offset,
808
return 0;
809
}
810
811
-static uint64_t omap_dma_read(void *opaque, hwaddr addr,
812
- unsigned size)
813
+static uint64_t omap_dma_read(void *opaque, hwaddr addr, unsigned size)
814
{
815
- struct omap_dma_s *s = (struct omap_dma_s *) opaque;
816
+ struct omap_dma_s *s = opaque;
817
int reg, ch;
818
uint16_t ret;
819
820
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_dma_read(void *opaque, hwaddr addr,
821
static void omap_dma_write(void *opaque, hwaddr addr,
822
uint64_t value, unsigned size)
823
{
824
- struct omap_dma_s *s = (struct omap_dma_s *) opaque;
825
+ struct omap_dma_s *s = opaque;
826
int reg, ch;
827
828
if (size != 2) {
829
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps omap_dma_ops = {
830
831
static void omap_dma_request(void *opaque, int drq, int req)
832
{
833
- struct omap_dma_s *s = (struct omap_dma_s *) opaque;
834
+ struct omap_dma_s *s = opaque;
835
/* The request pins are level triggered in QEMU. */
836
if (req) {
837
if (~s->dma->drqbmp & (1ULL << drq)) {
838
@@ -XXX,XX +XXX,XX @@ static void omap_dma_request(void *opaque, int drq, int req)
839
/* XXX: this won't be needed once soc_dma knows about clocks. */
840
static void omap_dma_clk_update(void *opaque, int line, int on)
841
{
842
- struct omap_dma_s *s = (struct omap_dma_s *) opaque;
843
+ struct omap_dma_s *s = opaque;
844
int i;
845
846
s->dma->freq = omap_clk_getrate(s->clk);
847
@@ -XXX,XX +XXX,XX @@ static void omap_dma_interrupts_4_update(struct omap_dma_s *s)
848
static uint64_t omap_dma4_read(void *opaque, hwaddr addr,
849
unsigned size)
850
{
851
- struct omap_dma_s *s = (struct omap_dma_s *) opaque;
852
+ struct omap_dma_s *s = opaque;
853
int irqn = 0, chnum;
854
struct omap_dma_channel_s *ch;
855
856
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_dma4_read(void *opaque, hwaddr addr,
857
static void omap_dma4_write(void *opaque, hwaddr addr,
858
uint64_t value, unsigned size)
859
{
860
- struct omap_dma_s *s = (struct omap_dma_s *) opaque;
861
+ struct omap_dma_s *s = opaque;
862
int chnum, irqn = 0;
863
struct omap_dma_channel_s *ch;
864
865
diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c
866
index XXXXXXX..XXXXXXX 100644
867
--- a/hw/gpio/omap_gpio.c
868
+++ b/hw/gpio/omap_gpio.c
869
@@ -XXX,XX +XXX,XX @@ static void omap_gpio_set(void *opaque, int line, int level)
870
static uint64_t omap_gpio_read(void *opaque, hwaddr addr,
871
unsigned size)
872
{
873
- struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
874
+ struct omap_gpio_s *s = opaque;
875
int offset = addr & OMAP_MPUI_REG_MASK;
876
877
if (size != 2) {
878
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_gpio_read(void *opaque, hwaddr addr,
879
static void omap_gpio_write(void *opaque, hwaddr addr,
880
uint64_t value, unsigned size)
881
{
882
- struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
883
+ struct omap_gpio_s *s = opaque;
884
int offset = addr & OMAP_MPUI_REG_MASK;
885
uint16_t diff;
886
int ln;
887
@@ -XXX,XX +XXX,XX @@ static void omap2_gpio_module_reset(struct omap2_gpio_s *s)
888
889
static uint32_t omap2_gpio_module_read(void *opaque, hwaddr addr)
890
{
891
- struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
892
+ struct omap2_gpio_s *s = opaque;
893
894
switch (addr) {
895
case 0x00:    /* GPIO_REVISION */
896
@@ -XXX,XX +XXX,XX @@ static uint32_t omap2_gpio_module_read(void *opaque, hwaddr addr)
897
static void omap2_gpio_module_write(void *opaque, hwaddr addr,
898
uint32_t value)
899
{
900
- struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
901
+ struct omap2_gpio_s *s = opaque;
902
uint32_t diff;
903
int ln;
904
905
@@ -XXX,XX +XXX,XX @@ static void omap2_gpif_reset(DeviceState *dev)
906
s->gpo = 0;
907
}
908
909
-static uint64_t omap2_gpif_top_read(void *opaque, hwaddr addr,
910
- unsigned size)
911
+static uint64_t omap2_gpif_top_read(void *opaque, hwaddr addr, unsigned size)
912
{
913
- struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
914
+ struct omap2_gpif_s *s = opaque;
915
916
switch (addr) {
917
case 0x00:    /* IPGENERICOCPSPL_REVISION */
918
@@ -XXX,XX +XXX,XX @@ static uint64_t omap2_gpif_top_read(void *opaque, hwaddr addr,
919
static void omap2_gpif_top_write(void *opaque, hwaddr addr,
920
uint64_t value, unsigned size)
921
{
922
- struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
923
+ struct omap2_gpif_s *s = opaque;
924
925
switch (addr) {
926
case 0x00:    /* IPGENERICOCPSPL_REVISION */
927
diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c
928
index XXXXXXX..XXXXXXX 100644
929
--- a/hw/intc/omap_intc.c
930
+++ b/hw/intc/omap_intc.c
931
@@ -XXX,XX +XXX,XX @@ static inline void omap_inth_update(struct omap_intr_handler_s *s, int is_fiq)
932
933
static void omap_set_intr(void *opaque, int irq, int req)
934
{
935
- struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
936
+ struct omap_intr_handler_s *ih = opaque;
937
uint32_t rise;
938
939
struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
940
@@ -XXX,XX +XXX,XX @@ static void omap_set_intr(void *opaque, int irq, int req)
941
/* Simplified version with no edge detection */
942
static void omap_set_intr_noedge(void *opaque, int irq, int req)
943
{
944
- struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
945
+ struct omap_intr_handler_s *ih = opaque;
946
uint32_t rise;
947
948
struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
949
@@ -XXX,XX +XXX,XX @@ static void omap_set_intr_noedge(void *opaque, int irq, int req)
950
static uint64_t omap_inth_read(void *opaque, hwaddr addr,
951
unsigned size)
952
{
953
- struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
954
+ struct omap_intr_handler_s *s = opaque;
955
int i, offset = addr;
956
int bank_no = offset >> 8;
957
int line_no;
958
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_inth_read(void *opaque, hwaddr addr,
959
static void omap_inth_write(void *opaque, hwaddr addr,
960
uint64_t value, unsigned size)
961
{
962
- struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
963
+ struct omap_intr_handler_s *s = opaque;
964
int i, offset = addr;
965
int bank_no = offset >> 8;
966
struct omap_intr_handler_bank_s *bank = &s->bank[bank_no];
967
@@ -XXX,XX +XXX,XX @@ static const TypeInfo omap_intc_info = {
968
static uint64_t omap2_inth_read(void *opaque, hwaddr addr,
969
unsigned size)
970
{
971
- struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
972
+ struct omap_intr_handler_s *s = opaque;
973
int offset = addr;
974
int bank_no, line_no;
975
struct omap_intr_handler_bank_s *bank = NULL;
976
@@ -XXX,XX +XXX,XX @@ static uint64_t omap2_inth_read(void *opaque, hwaddr addr,
977
static void omap2_inth_write(void *opaque, hwaddr addr,
978
uint64_t value, unsigned size)
979
{
980
- struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
981
+ struct omap_intr_handler_s *s = opaque;
982
int offset = addr;
983
int bank_no, line_no;
984
struct omap_intr_handler_bank_s *bank = NULL;
985
diff --git a/hw/misc/omap_gpmc.c b/hw/misc/omap_gpmc.c
986
index XXXXXXX..XXXXXXX 100644
987
--- a/hw/misc/omap_gpmc.c
988
+++ b/hw/misc/omap_gpmc.c
989
@@ -XXX,XX +XXX,XX @@ static void omap_gpmc_dma_update(struct omap_gpmc_s *s, int value)
990
static uint64_t omap_nand_read(void *opaque, hwaddr addr,
991
unsigned size)
992
{
993
- struct omap_gpmc_cs_file_s *f = (struct omap_gpmc_cs_file_s *)opaque;
994
+ struct omap_gpmc_cs_file_s *f = opaque;
995
uint64_t v;
996
nand_setpins(f->dev, 0, 0, 0, 1, 0);
997
switch (omap_gpmc_devsize(f)) {
998
@@ -XXX,XX +XXX,XX @@ static void omap_nand_setio(DeviceState *dev, uint64_t value,
999
static void omap_nand_write(void *opaque, hwaddr addr,
1000
uint64_t value, unsigned size)
1001
{
1002
- struct omap_gpmc_cs_file_s *f = (struct omap_gpmc_cs_file_s *)opaque;
1003
+ struct omap_gpmc_cs_file_s *f = opaque;
1004
nand_setpins(f->dev, 0, 0, 0, 1, 0);
1005
omap_nand_setio(f->dev, value, omap_gpmc_devsize(f), size);
1006
}
1007
@@ -XXX,XX +XXX,XX @@ static void fill_prefetch_fifo(struct omap_gpmc_s *s)
1008
static uint64_t omap_gpmc_prefetch_read(void *opaque, hwaddr addr,
1009
unsigned size)
1010
{
1011
- struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
1012
+ struct omap_gpmc_s *s = opaque;
1013
uint32_t data;
1014
if (s->prefetch.config1 & 1) {
1015
/* The TRM doesn't define the behaviour if you read from the
1016
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_gpmc_prefetch_read(void *opaque, hwaddr addr,
1017
static void omap_gpmc_prefetch_write(void *opaque, hwaddr addr,
1018
uint64_t value, unsigned size)
1019
{
1020
- struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
1021
+ struct omap_gpmc_s *s = opaque;
1022
int cs = prefetch_cs(s->prefetch.config1);
1023
if ((s->prefetch.config1 & 1) == 0) {
1024
/* The TRM doesn't define the behaviour of writing to the
1025
@@ -XXX,XX +XXX,XX @@ static int gpmc_wordaccess_only(hwaddr addr)
1026
static uint64_t omap_gpmc_read(void *opaque, hwaddr addr,
1027
unsigned size)
1028
{
1029
- struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
1030
+ struct omap_gpmc_s *s = opaque;
1031
int cs;
1032
struct omap_gpmc_cs_file_s *f;
1033
1034
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_gpmc_read(void *opaque, hwaddr addr,
1035
static void omap_gpmc_write(void *opaque, hwaddr addr,
1036
uint64_t value, unsigned size)
1037
{
1038
- struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
1039
+ struct omap_gpmc_s *s = opaque;
1040
int cs;
1041
struct omap_gpmc_cs_file_s *f;
1042
1043
diff --git a/hw/misc/omap_l4.c b/hw/misc/omap_l4.c
1044
index XXXXXXX..XXXXXXX 100644
1045
--- a/hw/misc/omap_l4.c
1046
+++ b/hw/misc/omap_l4.c
1047
@@ -XXX,XX +XXX,XX @@ hwaddr omap_l4_region_size(struct omap_target_agent_s *ta,
1048
return ta->start[region].size;
1049
}
1050
1051
-static uint64_t omap_l4ta_read(void *opaque, hwaddr addr,
1052
- unsigned size)
1053
+static uint64_t omap_l4ta_read(void *opaque, hwaddr addr, unsigned size)
1054
{
1055
- struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
1056
+ struct omap_target_agent_s *s = opaque;
1057
1058
if (size != 2) {
1059
return omap_badwidth_read16(opaque, addr);
1060
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_l4ta_read(void *opaque, hwaddr addr,
1061
static void omap_l4ta_write(void *opaque, hwaddr addr,
1062
uint64_t value, unsigned size)
1063
{
1064
- struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
1065
+ struct omap_target_agent_s *s = opaque;
1066
1067
if (size != 4) {
1068
omap_badwidth_write32(opaque, addr, value);
1069
diff --git a/hw/misc/omap_sdrc.c b/hw/misc/omap_sdrc.c
1070
index XXXXXXX..XXXXXXX 100644
1071
--- a/hw/misc/omap_sdrc.c
1072
+++ b/hw/misc/omap_sdrc.c
1073
@@ -XXX,XX +XXX,XX @@ void omap_sdrc_reset(struct omap_sdrc_s *s)
1074
s->config = 0x10;
1075
}
1076
1077
-static uint64_t omap_sdrc_read(void *opaque, hwaddr addr,
1078
- unsigned size)
1079
+static uint64_t omap_sdrc_read(void *opaque, hwaddr addr, unsigned size)
1080
{
1081
- struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
1082
+ struct omap_sdrc_s *s = opaque;
1083
1084
if (size != 4) {
1085
return omap_badwidth_read32(opaque, addr);
1086
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_sdrc_read(void *opaque, hwaddr addr,
1087
static void omap_sdrc_write(void *opaque, hwaddr addr,
1088
uint64_t value, unsigned size)
1089
{
1090
- struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
1091
+ struct omap_sdrc_s *s = opaque;
1092
1093
if (size != 4) {
1094
omap_badwidth_write32(opaque, addr, value);
1095
diff --git a/hw/misc/omap_tap.c b/hw/misc/omap_tap.c
1096
index XXXXXXX..XXXXXXX 100644
1097
--- a/hw/misc/omap_tap.c
1098
+++ b/hw/misc/omap_tap.c
1099
@@ -XXX,XX +XXX,XX @@
1100
#include "hw/arm/omap.h"
1101
1102
/* TEST-Chip-level TAP */
1103
-static uint64_t omap_tap_read(void *opaque, hwaddr addr,
1104
- unsigned size)
1105
+static uint64_t omap_tap_read(void *opaque, hwaddr addr, unsigned size)
1106
{
1107
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1108
+ struct omap_mpu_state_s *s = opaque;
1109
1110
if (size != 4) {
1111
return omap_badwidth_read32(opaque, addr);
1112
diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c
1113
index XXXXXXX..XXXXXXX 100644
1114
--- a/hw/sd/omap_mmc.c
1115
+++ b/hw/sd/omap_mmc.c
1116
@@ -XXX,XX +XXX,XX @@ void omap_mmc_reset(struct omap_mmc_s *host)
1117
device_cold_reset(DEVICE(host->card));
1118
}
1119
1120
-static uint64_t omap_mmc_read(void *opaque, hwaddr offset,
1121
- unsigned size)
1122
+static uint64_t omap_mmc_read(void *opaque, hwaddr offset, unsigned size)
1123
{
1124
uint16_t i;
1125
- struct omap_mmc_s *s = (struct omap_mmc_s *) opaque;
1126
+ struct omap_mmc_s *s = opaque;
1127
1128
if (size != 2) {
1129
return omap_badwidth_read16(opaque, offset);
1130
@@ -XXX,XX +XXX,XX @@ static void omap_mmc_write(void *opaque, hwaddr offset,
1131
uint64_t value, unsigned size)
1132
{
1133
int i;
1134
- struct omap_mmc_s *s = (struct omap_mmc_s *) opaque;
1135
+ struct omap_mmc_s *s = opaque;
1136
1137
if (size != 2) {
1138
omap_badwidth_write16(opaque, offset, value);
1139
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps omap_mmc_ops = {
1140
1141
static void omap_mmc_cover_cb(void *opaque, int line, int level)
1142
{
1143
- struct omap_mmc_s *host = (struct omap_mmc_s *) opaque;
1144
+ struct omap_mmc_s *host = opaque;
1145
1146
if (!host->cdet_state && level) {
1147
host->status |= 0x0002;
1148
diff --git a/hw/ssi/omap_spi.c b/hw/ssi/omap_spi.c
1149
index XXXXXXX..XXXXXXX 100644
1150
--- a/hw/ssi/omap_spi.c
1151
+++ b/hw/ssi/omap_spi.c
1152
@@ -XXX,XX +XXX,XX @@ void omap_mcspi_reset(struct omap_mcspi_s *s)
1153
omap_mcspi_interrupt_update(s);
1154
}
1155
1156
-static uint64_t omap_mcspi_read(void *opaque, hwaddr addr,
1157
- unsigned size)
1158
+static uint64_t omap_mcspi_read(void *opaque, hwaddr addr, unsigned size)
1159
{
1160
- struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;
1161
+ struct omap_mcspi_s *s = opaque;
1162
int ch = 0;
1163
uint32_t ret;
1164
1165
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_mcspi_read(void *opaque, hwaddr addr,
1166
static void omap_mcspi_write(void *opaque, hwaddr addr,
1167
uint64_t value, unsigned size)
1168
{
1169
- struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;
1170
+ struct omap_mcspi_s *s = opaque;
1171
int ch = 0;
1172
1173
if (size != 4) {
1174
diff --git a/hw/timer/omap_gptimer.c b/hw/timer/omap_gptimer.c
1175
index XXXXXXX..XXXXXXX 100644
1176
--- a/hw/timer/omap_gptimer.c
1177
+++ b/hw/timer/omap_gptimer.c
1178
@@ -XXX,XX +XXX,XX @@ static inline void omap_gp_timer_trigger(struct omap_gp_timer_s *timer)
1179
1180
static void omap_gp_timer_tick(void *opaque)
1181
{
1182
- struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
1183
+ struct omap_gp_timer_s *timer = opaque;
1184
1185
if (!timer->ar) {
1186
timer->st = 0;
1187
@@ -XXX,XX +XXX,XX @@ static void omap_gp_timer_tick(void *opaque)
1188
1189
static void omap_gp_timer_match(void *opaque)
1190
{
1191
- struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
1192
+ struct omap_gp_timer_s *timer = opaque;
1193
1194
if (timer->trigger == gpt_trigger_both)
1195
omap_gp_timer_trigger(timer);
1196
@@ -XXX,XX +XXX,XX @@ static void omap_gp_timer_match(void *opaque)
1197
1198
static void omap_gp_timer_input(void *opaque, int line, int on)
1199
{
1200
- struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
1201
+ struct omap_gp_timer_s *s = opaque;
1202
int trigger;
1203
1204
switch (s->capture) {
1205
@@ -XXX,XX +XXX,XX @@ static void omap_gp_timer_input(void *opaque, int line, int on)
1206
1207
static void omap_gp_timer_clk_update(void *opaque, int line, int on)
1208
{
1209
- struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
1210
+ struct omap_gp_timer_s *timer = opaque;
1211
1212
omap_gp_timer_sync(timer);
1213
timer->rate = on ? omap_clk_getrate(timer->clk) : 0;
1214
@@ -XXX,XX +XXX,XX @@ void omap_gp_timer_reset(struct omap_gp_timer_s *s)
1215
1216
static uint32_t omap_gp_timer_readw(void *opaque, hwaddr addr)
1217
{
1218
- struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
1219
+ struct omap_gp_timer_s *s = opaque;
1220
1221
switch (addr) {
1222
case 0x00:    /* TIDR */
1223
@@ -XXX,XX +XXX,XX @@ static uint32_t omap_gp_timer_readw(void *opaque, hwaddr addr)
1224
1225
static uint32_t omap_gp_timer_readh(void *opaque, hwaddr addr)
1226
{
1227
- struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
1228
+ struct omap_gp_timer_s *s = opaque;
1229
uint32_t ret;
1230
1231
if (addr & 2)
1232
@@ -XXX,XX +XXX,XX @@ static uint32_t omap_gp_timer_readh(void *opaque, hwaddr addr)
1233
}
1234
}
1235
1236
-static void omap_gp_timer_write(void *opaque, hwaddr addr,
1237
- uint32_t value)
1238
+static void omap_gp_timer_write(void *opaque, hwaddr addr, uint32_t value)
1239
{
1240
- struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
1241
+ struct omap_gp_timer_s *s = opaque;
1242
1243
switch (addr) {
1244
case 0x00:    /* TIDR */
1245
@@ -XXX,XX +XXX,XX @@ static void omap_gp_timer_write(void *opaque, hwaddr addr,
1246
}
1247
}
1248
1249
-static void omap_gp_timer_writeh(void *opaque, hwaddr addr,
1250
- uint32_t value)
1251
+static void omap_gp_timer_writeh(void *opaque, hwaddr addr, uint32_t value)
1252
{
1253
- struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
1254
+ struct omap_gp_timer_s *s = opaque;
1255
1256
if (addr & 2)
1257
omap_gp_timer_write(opaque, addr, (value << 16) | s->writeh);
1258
diff --git a/hw/timer/omap_synctimer.c b/hw/timer/omap_synctimer.c
1259
index XXXXXXX..XXXXXXX 100644
1260
--- a/hw/timer/omap_synctimer.c
1261
+++ b/hw/timer/omap_synctimer.c
1262
@@ -XXX,XX +XXX,XX @@ void omap_synctimer_reset(struct omap_synctimer_s *s)
1263
1264
static uint32_t omap_synctimer_readw(void *opaque, hwaddr addr)
1265
{
1266
- struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
1267
+ struct omap_synctimer_s *s = opaque;
1268
1269
switch (addr) {
1270
case 0x00:    /* 32KSYNCNT_REV */
1271
@@ -XXX,XX +XXX,XX @@ static uint32_t omap_synctimer_readw(void *opaque, hwaddr addr)
1272
1273
static uint32_t omap_synctimer_readh(void *opaque, hwaddr addr)
1274
{
1275
- struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
1276
+ struct omap_synctimer_s *s = opaque;
1277
uint32_t ret;
1278
1279
if (addr & 2)
58
--
1280
--
59
2.20.1
1281
2.34.1
60
1282
61
1283
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
This allows these NPCM7xx-based boards to boot from a flash image, e.g.
3
Following docs/devel/style.rst guidelines, rename omap_gpif_s ->
4
one built with OpenBMC. For example like this:
4
Omap1GpioState. This also remove a use of 'struct' in the
5
DECLARE_INSTANCE_CHECKER() macro call.
5
6
6
IMAGE=${OPENBMC}/build/tmp/deploy/images/gsj/image-bmc
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
qemu-system-arm -machine quanta-gsj -nographic \
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
    -drive file=${IMAGE},if=mtd,bus=0,unit=0,format=raw,snapshot=on
9
Message-id: 20230109140306.23161-5-philmd@linaro.org
9
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
11
Reviewed-by: Cédric Le Goater <clg@kaod.org>
12
Tested-by: Cédric Le Goater <clg@kaod.org>
13
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Message-id: 20200911052101.2602693-12-hskinnemoen@google.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
11
---
19
hw/arm/npcm7xx_boards.c | 20 ++++++++++++++++++++
12
include/hw/arm/omap.h | 6 +++---
20
1 file changed, 20 insertions(+)
13
hw/gpio/omap_gpio.c | 16 ++++++++--------
14
2 files changed, 11 insertions(+), 11 deletions(-)
21
15
22
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
16
diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h
23
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/arm/npcm7xx_boards.c
18
--- a/include/hw/arm/omap.h
25
+++ b/hw/arm/npcm7xx_boards.c
19
+++ b/include/hw/arm/omap.h
26
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ void omap_i2c_set_fclk(OMAPI2CState *i2c, omap_clk clk);
27
#include "hw/arm/npcm7xx.h"
21
28
#include "hw/core/cpu.h"
22
/* omap_gpio.c */
29
#include "hw/loader.h"
23
#define TYPE_OMAP1_GPIO "omap-gpio"
30
+#include "hw/qdev-properties.h"
24
-DECLARE_INSTANCE_CHECKER(struct omap_gpif_s, OMAP1_GPIO,
31
#include "qapi/error.h"
25
+typedef struct Omap1GpioState Omap1GpioState;
32
#include "qemu-common.h"
26
+DECLARE_INSTANCE_CHECKER(Omap1GpioState, OMAP1_GPIO,
33
#include "qemu/units.h"
27
TYPE_OMAP1_GPIO)
34
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_load_bootrom(MachineState *machine, NPCM7xxState *soc)
28
29
#define TYPE_OMAP2_GPIO "omap2-gpio"
30
DECLARE_INSTANCE_CHECKER(struct omap2_gpif_s, OMAP2_GPIO,
31
TYPE_OMAP2_GPIO)
32
33
-typedef struct omap_gpif_s omap_gpif;
34
typedef struct omap2_gpif_s omap2_gpif;
35
36
/* TODO: clock framework (see above) */
37
-void omap_gpio_set_clk(omap_gpif *gpio, omap_clk clk);
38
+void omap_gpio_set_clk(Omap1GpioState *gpio, omap_clk clk);
39
40
void omap2_gpio_set_iclk(omap2_gpif *gpio, omap_clk clk);
41
void omap2_gpio_set_fclk(omap2_gpif *gpio, uint8_t i, omap_clk clk);
42
diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/gpio/omap_gpio.c
45
+++ b/hw/gpio/omap_gpio.c
46
@@ -XXX,XX +XXX,XX @@ struct omap_gpio_s {
47
uint16_t pins;
48
};
49
50
-struct omap_gpif_s {
51
+struct Omap1GpioState {
52
SysBusDevice parent_obj;
53
54
MemoryRegion iomem;
55
@@ -XXX,XX +XXX,XX @@ struct omap_gpif_s {
56
/* General-Purpose I/O of OMAP1 */
57
static void omap_gpio_set(void *opaque, int line, int level)
58
{
59
- struct omap_gpif_s *p = opaque;
60
+ Omap1GpioState *p = opaque;
61
struct omap_gpio_s *s = &p->omap1;
62
uint16_t prev = s->inputs;
63
64
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps omap2_gpio_module_ops = {
65
66
static void omap_gpif_reset(DeviceState *dev)
67
{
68
- struct omap_gpif_s *s = OMAP1_GPIO(dev);
69
+ Omap1GpioState *s = OMAP1_GPIO(dev);
70
71
omap_gpio_reset(&s->omap1);
72
}
73
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps omap2_gpif_top_ops = {
74
static void omap_gpio_init(Object *obj)
75
{
76
DeviceState *dev = DEVICE(obj);
77
- struct omap_gpif_s *s = OMAP1_GPIO(obj);
78
+ Omap1GpioState *s = OMAP1_GPIO(obj);
79
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
80
81
qdev_init_gpio_in(dev, omap_gpio_set, 16);
82
@@ -XXX,XX +XXX,XX @@ static void omap_gpio_init(Object *obj)
83
84
static void omap_gpio_realize(DeviceState *dev, Error **errp)
85
{
86
- struct omap_gpif_s *s = OMAP1_GPIO(dev);
87
+ Omap1GpioState *s = OMAP1_GPIO(dev);
88
89
if (!s->clk) {
90
error_setg(errp, "omap-gpio: clk not connected");
91
@@ -XXX,XX +XXX,XX @@ static void omap2_gpio_realize(DeviceState *dev, Error **errp)
35
}
92
}
36
}
93
}
37
94
38
+static void npcm7xx_connect_flash(NPCM7xxFIUState *fiu, int cs_no,
95
-void omap_gpio_set_clk(omap_gpif *gpio, omap_clk clk)
39
+ const char *flash_type, DriveInfo *dinfo)
96
+void omap_gpio_set_clk(Omap1GpioState *gpio, omap_clk clk)
40
+{
41
+ DeviceState *flash;
42
+ qemu_irq flash_cs;
43
+
44
+ flash = qdev_new(flash_type);
45
+ if (dinfo) {
46
+ qdev_prop_set_drive(flash, "drive", blk_by_legacy_dinfo(dinfo));
47
+ }
48
+ qdev_realize_and_unref(flash, BUS(fiu->spi), &error_fatal);
49
+
50
+ flash_cs = qdev_get_gpio_in_named(flash, SSI_GPIO_CS, 0);
51
+ qdev_connect_gpio_out_named(DEVICE(fiu), "cs", cs_no, flash_cs);
52
+}
53
+
54
static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
55
{
97
{
56
memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
98
gpio->clk = clk;
57
@@ -XXX,XX +XXX,XX @@ static void npcm750_evb_init(MachineState *machine)
58
qdev_realize(DEVICE(soc), NULL, &error_fatal);
59
60
npcm7xx_load_bootrom(machine, soc);
61
+ npcm7xx_connect_flash(&soc->fiu[0], 0, "w25q256", drive_get(IF_MTD, 0, 0));
62
npcm7xx_load_kernel(machine, soc);
63
}
99
}
64
100
65
@@ -XXX,XX +XXX,XX @@ static void quanta_gsj_init(MachineState *machine)
101
static Property omap_gpio_properties[] = {
66
qdev_realize(DEVICE(soc), NULL, &error_fatal);
102
- DEFINE_PROP_INT32("mpu_model", struct omap_gpif_s, mpu_model, 0),
67
103
+ DEFINE_PROP_INT32("mpu_model", Omap1GpioState, mpu_model, 0),
68
npcm7xx_load_bootrom(machine, soc);
104
DEFINE_PROP_END_OF_LIST(),
69
+ npcm7xx_connect_flash(&soc->fiu[0], 0, "mx25l25635e",
105
};
70
+ drive_get(IF_MTD, 0, 0));
106
71
npcm7xx_load_kernel(machine, soc);
107
@@ -XXX,XX +XXX,XX @@ static void omap_gpio_class_init(ObjectClass *klass, void *data)
72
}
108
static const TypeInfo omap_gpio_info = {
73
109
.name = TYPE_OMAP1_GPIO,
110
.parent = TYPE_SYS_BUS_DEVICE,
111
- .instance_size = sizeof(struct omap_gpif_s),
112
+ .instance_size = sizeof(Omap1GpioState),
113
.instance_init = omap_gpio_init,
114
.class_init = omap_gpio_class_init,
115
};
74
--
116
--
75
2.20.1
117
2.34.1
76
118
77
119
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
Connect CAN0 and CAN1 on the ZynqMP.
3
Following docs/devel/style.rst guidelines, rename omap2_gpif_s ->
4
Omap2GpioState. This also remove a use of 'struct' in the
5
DECLARE_INSTANCE_CHECKER() macro call.
4
6
5
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
9
Message-id: 20230109140306.23161-6-philmd@linaro.org
8
Message-id: 1597278668-339715-3-git-send-email-fnu.vikram@xilinx.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
---
11
include/hw/arm/xlnx-zynqmp.h | 8 ++++++++
12
include/hw/arm/omap.h | 9 ++++-----
12
hw/arm/xlnx-zcu102.c | 20 ++++++++++++++++++++
13
hw/gpio/omap_gpio.c | 20 ++++++++++----------
13
hw/arm/xlnx-zynqmp.c | 34 ++++++++++++++++++++++++++++++++++
14
2 files changed, 14 insertions(+), 15 deletions(-)
14
3 files changed, 62 insertions(+)
15
15
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
16
diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/xlnx-zynqmp.h
18
--- a/include/hw/arm/omap.h
19
+++ b/include/hw/arm/xlnx-zynqmp.h
19
+++ b/include/hw/arm/omap.h
20
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ DECLARE_INSTANCE_CHECKER(Omap1GpioState, OMAP1_GPIO,
21
#include "hw/intc/arm_gic.h"
21
TYPE_OMAP1_GPIO)
22
#include "hw/net/cadence_gem.h"
22
23
#include "hw/char/cadence_uart.h"
23
#define TYPE_OMAP2_GPIO "omap2-gpio"
24
+#include "hw/net/xlnx-zynqmp-can.h"
24
-DECLARE_INSTANCE_CHECKER(struct omap2_gpif_s, OMAP2_GPIO,
25
#include "hw/ide/ahci.h"
25
+typedef struct Omap2GpioState Omap2GpioState;
26
#include "hw/sd/sdhci.h"
26
+DECLARE_INSTANCE_CHECKER(Omap2GpioState, OMAP2_GPIO,
27
#include "hw/ssi/xilinx_spips.h"
27
TYPE_OMAP2_GPIO)
28
@@ -XXX,XX +XXX,XX @@
28
29
#include "hw/cpu/cluster.h"
29
-typedef struct omap2_gpif_s omap2_gpif;
30
#include "target/arm/cpu.h"
30
-
31
#include "qom/object.h"
31
/* TODO: clock framework (see above) */
32
+#include "net/can_emu.h"
32
void omap_gpio_set_clk(Omap1GpioState *gpio, omap_clk clk);
33
33
34
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
34
-void omap2_gpio_set_iclk(omap2_gpif *gpio, omap_clk clk);
35
typedef struct XlnxZynqMPState XlnxZynqMPState;
35
-void omap2_gpio_set_fclk(omap2_gpif *gpio, uint8_t i, omap_clk clk);
36
@@ -XXX,XX +XXX,XX @@ DECLARE_INSTANCE_CHECKER(XlnxZynqMPState, XLNX_ZYNQMP,
36
+void omap2_gpio_set_iclk(Omap2GpioState *gpio, omap_clk clk);
37
#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
37
+void omap2_gpio_set_fclk(Omap2GpioState *gpio, uint8_t i, omap_clk clk);
38
#define XLNX_ZYNQMP_NUM_GEMS 4
38
39
#define XLNX_ZYNQMP_NUM_UARTS 2
39
/* OMAP2 l4 Interconnect */
40
+#define XLNX_ZYNQMP_NUM_CAN 2
40
struct omap_l4_s;
41
+#define XLNX_ZYNQMP_CAN_REF_CLK (24 * 1000 * 1000)
41
diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c
42
#define XLNX_ZYNQMP_NUM_SDHCI 2
42
index XXXXXXX..XXXXXXX 100644
43
#define XLNX_ZYNQMP_NUM_SPIS 2
43
--- a/hw/gpio/omap_gpio.c
44
#define XLNX_ZYNQMP_NUM_GDMA_CH 8
44
+++ b/hw/gpio/omap_gpio.c
45
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
45
@@ -XXX,XX +XXX,XX @@ struct omap2_gpio_s {
46
46
uint8_t delay;
47
CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
48
CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS];
49
+ XlnxZynqMPCANState can[XLNX_ZYNQMP_NUM_CAN];
50
SysbusAHCIState sata;
51
SDHCIState sdhci[XLNX_ZYNQMP_NUM_SDHCI];
52
XilinxSPIPS spi[XLNX_ZYNQMP_NUM_SPIS];
53
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
54
bool virt;
55
/* Has the RPU subsystem? */
56
bool has_rpu;
57
+
58
+ /* CAN bus. */
59
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
60
};
47
};
61
48
62
#endif
49
-struct omap2_gpif_s {
63
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
50
+struct Omap2GpioState {
64
index XXXXXXX..XXXXXXX 100644
51
SysBusDevice parent_obj;
65
--- a/hw/arm/xlnx-zcu102.c
52
66
+++ b/hw/arm/xlnx-zcu102.c
53
MemoryRegion iomem;
67
@@ -XXX,XX +XXX,XX @@
54
@@ -XXX,XX +XXX,XX @@ static inline void omap2_gpio_module_int(struct omap2_gpio_s *s, int line)
68
#include "sysemu/qtest.h"
55
69
#include "sysemu/device_tree.h"
56
static void omap2_gpio_set(void *opaque, int line, int level)
70
#include "qom/object.h"
57
{
71
+#include "net/can_emu.h"
58
- struct omap2_gpif_s *p = opaque;
72
59
+ Omap2GpioState *p = opaque;
73
struct XlnxZCU102 {
60
struct omap2_gpio_s *s = &p->modules[line >> 5];
74
MachineState parent_obj;
61
75
@@ -XXX,XX +XXX,XX @@ struct XlnxZCU102 {
62
line &= 31;
76
bool secure;
63
@@ -XXX,XX +XXX,XX @@ static void omap_gpif_reset(DeviceState *dev)
77
bool virt;
64
78
65
static void omap2_gpif_reset(DeviceState *dev)
79
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
66
{
80
+
67
- struct omap2_gpif_s *s = OMAP2_GPIO(dev);
81
struct arm_boot_info binfo;
68
+ Omap2GpioState *s = OMAP2_GPIO(dev);
69
int i;
70
71
for (i = 0; i < s->modulecount; i++) {
72
@@ -XXX,XX +XXX,XX @@ static void omap2_gpif_reset(DeviceState *dev)
73
74
static uint64_t omap2_gpif_top_read(void *opaque, hwaddr addr, unsigned size)
75
{
76
- struct omap2_gpif_s *s = opaque;
77
+ Omap2GpioState *s = opaque;
78
79
switch (addr) {
80
case 0x00:    /* IPGENERICOCPSPL_REVISION */
81
@@ -XXX,XX +XXX,XX @@ static uint64_t omap2_gpif_top_read(void *opaque, hwaddr addr, unsigned size)
82
static void omap2_gpif_top_write(void *opaque, hwaddr addr,
83
uint64_t value, unsigned size)
84
{
85
- struct omap2_gpif_s *s = opaque;
86
+ Omap2GpioState *s = opaque;
87
88
switch (addr) {
89
case 0x00:    /* IPGENERICOCPSPL_REVISION */
90
@@ -XXX,XX +XXX,XX @@ static void omap_gpio_realize(DeviceState *dev, Error **errp)
91
92
static void omap2_gpio_realize(DeviceState *dev, Error **errp)
93
{
94
- struct omap2_gpif_s *s = OMAP2_GPIO(dev);
95
+ Omap2GpioState *s = OMAP2_GPIO(dev);
96
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
97
int i;
98
99
@@ -XXX,XX +XXX,XX @@ static const TypeInfo omap_gpio_info = {
100
.class_init = omap_gpio_class_init,
82
};
101
};
83
typedef struct XlnxZCU102 XlnxZCU102;
102
84
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_init(MachineState *machine)
103
-void omap2_gpio_set_iclk(omap2_gpif *gpio, omap_clk clk)
85
object_property_set_bool(OBJECT(&s->soc), "virtualization", s->virt,
104
+void omap2_gpio_set_iclk(Omap2GpioState *gpio, omap_clk clk)
86
&error_fatal);
105
{
87
106
gpio->iclk = clk;
88
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
89
+ gchar *bus_name = g_strdup_printf("canbus%d", i);
90
+
91
+ object_property_set_link(OBJECT(&s->soc), bus_name,
92
+ OBJECT(s->canbus[i]), &error_fatal);
93
+ g_free(bus_name);
94
+ }
95
+
96
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
97
98
/* Create and plug in the SD cards */
99
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_instance_init(Object *obj)
100
"Set on/off to enable/disable emulating a "
101
"guest CPU which implements the ARM "
102
"Virtualization Extensions");
103
+ object_property_add_link(obj, "xlnx-zcu102.canbus0", TYPE_CAN_BUS,
104
+ (Object **)&s->canbus[0],
105
+ object_property_allow_set_link,
106
+ 0);
107
+
108
+ object_property_add_link(obj, "xlnx-zcu102.canbus1", TYPE_CAN_BUS,
109
+ (Object **)&s->canbus[1],
110
+ object_property_allow_set_link,
111
+ 0);
112
}
107
}
113
108
114
static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data)
109
-void omap2_gpio_set_fclk(omap2_gpif *gpio, uint8_t i, omap_clk clk)
115
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
110
+void omap2_gpio_set_fclk(Omap2GpioState *gpio, uint8_t i, omap_clk clk)
116
index XXXXXXX..XXXXXXX 100644
111
{
117
--- a/hw/arm/xlnx-zynqmp.c
112
assert(i <= 5);
118
+++ b/hw/arm/xlnx-zynqmp.c
113
gpio->fclk[i] = clk;
119
@@ -XXX,XX +XXX,XX @@ static const int uart_intr[XLNX_ZYNQMP_NUM_UARTS] = {
114
}
120
21, 22,
115
116
static Property omap2_gpio_properties[] = {
117
- DEFINE_PROP_INT32("mpu_model", struct omap2_gpif_s, mpu_model, 0),
118
+ DEFINE_PROP_INT32("mpu_model", Omap2GpioState, mpu_model, 0),
119
DEFINE_PROP_END_OF_LIST(),
121
};
120
};
122
121
123
+static const uint64_t can_addr[XLNX_ZYNQMP_NUM_CAN] = {
122
@@ -XXX,XX +XXX,XX @@ static void omap2_gpio_class_init(ObjectClass *klass, void *data)
124
+ 0xFF060000, 0xFF070000,
123
static const TypeInfo omap2_gpio_info = {
125
+};
124
.name = TYPE_OMAP2_GPIO,
126
+
125
.parent = TYPE_SYS_BUS_DEVICE,
127
+static const int can_intr[XLNX_ZYNQMP_NUM_CAN] = {
126
- .instance_size = sizeof(struct omap2_gpif_s),
128
+ 23, 24,
127
+ .instance_size = sizeof(Omap2GpioState),
129
+};
128
.class_init = omap2_gpio_class_init,
130
+
131
static const uint64_t sdhci_addr[XLNX_ZYNQMP_NUM_SDHCI] = {
132
0xFF160000, 0xFF170000,
133
};
129
};
134
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
135
TYPE_CADENCE_UART);
136
}
137
138
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
139
+ object_initialize_child(obj, "can[*]", &s->can[i],
140
+ TYPE_XLNX_ZYNQMP_CAN);
141
+ }
142
+
143
object_initialize_child(obj, "sata", &s->sata, TYPE_SYSBUS_AHCI);
144
145
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
146
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
147
gic_spi[uart_intr[i]]);
148
}
149
150
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
151
+ object_property_set_int(OBJECT(&s->can[i]), "ext_clk_freq",
152
+ XLNX_ZYNQMP_CAN_REF_CLK, &error_abort);
153
+
154
+ object_property_set_link(OBJECT(&s->can[i]), "canbus",
155
+ OBJECT(s->canbus[i]), &error_fatal);
156
+
157
+ sysbus_realize(SYS_BUS_DEVICE(&s->can[i]), &err);
158
+ if (err) {
159
+ error_propagate(errp, err);
160
+ return;
161
+ }
162
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->can[i]), 0, can_addr[i]);
163
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->can[i]), 0,
164
+ gic_spi[can_intr[i]]);
165
+ }
166
+
167
object_property_set_int(OBJECT(&s->sata), "num-ports", SATA_NUM_PORTS,
168
&error_abort);
169
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sata), errp)) {
170
@@ -XXX,XX +XXX,XX @@ static Property xlnx_zynqmp_props[] = {
171
DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false),
172
DEFINE_PROP_LINK("ddr-ram", XlnxZynqMPState, ddr_ram, TYPE_MEMORY_REGION,
173
MemoryRegion *),
174
+ DEFINE_PROP_LINK("canbus0", XlnxZynqMPState, canbus[0], TYPE_CAN_BUS,
175
+ CanBusState *),
176
+ DEFINE_PROP_LINK("canbus1", XlnxZynqMPState, canbus[1], TYPE_CAN_BUS,
177
+ CanBusState *),
178
DEFINE_PROP_END_OF_LIST()
179
};
180
130
181
--
131
--
182
2.20.1
132
2.34.1
183
133
184
134
diff view generated by jsdifflib
New patch
1
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
3
Following docs/devel/style.rst guidelines, rename
4
omap_intr_handler_s -> OMAPIntcState. This also remove a
5
use of 'struct' in the DECLARE_INSTANCE_CHECKER() macro call.
6
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230109140306.23161-7-philmd@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/arm/omap.h | 9 ++++-----
13
hw/intc/omap_intc.c | 38 +++++++++++++++++++-------------------
14
2 files changed, 23 insertions(+), 24 deletions(-)
15
16
diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/omap.h
19
+++ b/include/hw/arm/omap.h
20
@@ -XXX,XX +XXX,XX @@ void omap_clk_reparent(omap_clk clk, omap_clk parent);
21
22
/* omap_intc.c */
23
#define TYPE_OMAP_INTC "common-omap-intc"
24
-typedef struct omap_intr_handler_s omap_intr_handler;
25
-DECLARE_INSTANCE_CHECKER(omap_intr_handler, OMAP_INTC,
26
- TYPE_OMAP_INTC)
27
+typedef struct OMAPIntcState OMAPIntcState;
28
+DECLARE_INSTANCE_CHECKER(OMAPIntcState, OMAP_INTC, TYPE_OMAP_INTC)
29
30
31
/*
32
@@ -XXX,XX +XXX,XX @@ DECLARE_INSTANCE_CHECKER(omap_intr_handler, OMAP_INTC,
33
* (ie the struct omap_mpu_state_s*) to do the clockname to pointer
34
* translation.)
35
*/
36
-void omap_intc_set_iclk(omap_intr_handler *intc, omap_clk clk);
37
-void omap_intc_set_fclk(omap_intr_handler *intc, omap_clk clk);
38
+void omap_intc_set_iclk(OMAPIntcState *intc, omap_clk clk);
39
+void omap_intc_set_fclk(OMAPIntcState *intc, omap_clk clk);
40
41
/* omap_i2c.c */
42
#define TYPE_OMAP_I2C "omap_i2c"
43
diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/intc/omap_intc.c
46
+++ b/hw/intc/omap_intc.c
47
@@ -XXX,XX +XXX,XX @@ struct omap_intr_handler_bank_s {
48
unsigned char priority[32];
49
};
50
51
-struct omap_intr_handler_s {
52
+struct OMAPIntcState {
53
SysBusDevice parent_obj;
54
55
qemu_irq *pins;
56
@@ -XXX,XX +XXX,XX @@ struct omap_intr_handler_s {
57
struct omap_intr_handler_bank_s bank[3];
58
};
59
60
-static void omap_inth_sir_update(struct omap_intr_handler_s *s, int is_fiq)
61
+static void omap_inth_sir_update(OMAPIntcState *s, int is_fiq)
62
{
63
int i, j, sir_intr, p_intr, p;
64
uint32_t level;
65
@@ -XXX,XX +XXX,XX @@ static void omap_inth_sir_update(struct omap_intr_handler_s *s, int is_fiq)
66
s->sir_intr[is_fiq] = sir_intr;
67
}
68
69
-static inline void omap_inth_update(struct omap_intr_handler_s *s, int is_fiq)
70
+static inline void omap_inth_update(OMAPIntcState *s, int is_fiq)
71
{
72
int i;
73
uint32_t has_intr = 0;
74
@@ -XXX,XX +XXX,XX @@ static inline void omap_inth_update(struct omap_intr_handler_s *s, int is_fiq)
75
76
static void omap_set_intr(void *opaque, int irq, int req)
77
{
78
- struct omap_intr_handler_s *ih = opaque;
79
+ OMAPIntcState *ih = opaque;
80
uint32_t rise;
81
82
struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
83
@@ -XXX,XX +XXX,XX @@ static void omap_set_intr(void *opaque, int irq, int req)
84
/* Simplified version with no edge detection */
85
static void omap_set_intr_noedge(void *opaque, int irq, int req)
86
{
87
- struct omap_intr_handler_s *ih = opaque;
88
+ OMAPIntcState *ih = opaque;
89
uint32_t rise;
90
91
struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
92
@@ -XXX,XX +XXX,XX @@ static void omap_set_intr_noedge(void *opaque, int irq, int req)
93
static uint64_t omap_inth_read(void *opaque, hwaddr addr,
94
unsigned size)
95
{
96
- struct omap_intr_handler_s *s = opaque;
97
+ OMAPIntcState *s = opaque;
98
int i, offset = addr;
99
int bank_no = offset >> 8;
100
int line_no;
101
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_inth_read(void *opaque, hwaddr addr,
102
static void omap_inth_write(void *opaque, hwaddr addr,
103
uint64_t value, unsigned size)
104
{
105
- struct omap_intr_handler_s *s = opaque;
106
+ OMAPIntcState *s = opaque;
107
int i, offset = addr;
108
int bank_no = offset >> 8;
109
struct omap_intr_handler_bank_s *bank = &s->bank[bank_no];
110
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps omap_inth_mem_ops = {
111
112
static void omap_inth_reset(DeviceState *dev)
113
{
114
- struct omap_intr_handler_s *s = OMAP_INTC(dev);
115
+ OMAPIntcState *s = OMAP_INTC(dev);
116
int i;
117
118
for (i = 0; i < s->nbanks; ++i){
119
@@ -XXX,XX +XXX,XX @@ static void omap_inth_reset(DeviceState *dev)
120
static void omap_intc_init(Object *obj)
121
{
122
DeviceState *dev = DEVICE(obj);
123
- struct omap_intr_handler_s *s = OMAP_INTC(obj);
124
+ OMAPIntcState *s = OMAP_INTC(obj);
125
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
126
127
s->nbanks = 1;
128
@@ -XXX,XX +XXX,XX @@ static void omap_intc_init(Object *obj)
129
130
static void omap_intc_realize(DeviceState *dev, Error **errp)
131
{
132
- struct omap_intr_handler_s *s = OMAP_INTC(dev);
133
+ OMAPIntcState *s = OMAP_INTC(dev);
134
135
if (!s->iclk) {
136
error_setg(errp, "omap-intc: clk not connected");
137
}
138
}
139
140
-void omap_intc_set_iclk(omap_intr_handler *intc, omap_clk clk)
141
+void omap_intc_set_iclk(OMAPIntcState *intc, omap_clk clk)
142
{
143
intc->iclk = clk;
144
}
145
146
-void omap_intc_set_fclk(omap_intr_handler *intc, omap_clk clk)
147
+void omap_intc_set_fclk(OMAPIntcState *intc, omap_clk clk)
148
{
149
intc->fclk = clk;
150
}
151
152
static Property omap_intc_properties[] = {
153
- DEFINE_PROP_UINT32("size", struct omap_intr_handler_s, size, 0x100),
154
+ DEFINE_PROP_UINT32("size", OMAPIntcState, size, 0x100),
155
DEFINE_PROP_END_OF_LIST(),
156
};
157
158
@@ -XXX,XX +XXX,XX @@ static const TypeInfo omap_intc_info = {
159
static uint64_t omap2_inth_read(void *opaque, hwaddr addr,
160
unsigned size)
161
{
162
- struct omap_intr_handler_s *s = opaque;
163
+ OMAPIntcState *s = opaque;
164
int offset = addr;
165
int bank_no, line_no;
166
struct omap_intr_handler_bank_s *bank = NULL;
167
@@ -XXX,XX +XXX,XX @@ static uint64_t omap2_inth_read(void *opaque, hwaddr addr,
168
static void omap2_inth_write(void *opaque, hwaddr addr,
169
uint64_t value, unsigned size)
170
{
171
- struct omap_intr_handler_s *s = opaque;
172
+ OMAPIntcState *s = opaque;
173
int offset = addr;
174
int bank_no, line_no;
175
struct omap_intr_handler_bank_s *bank = NULL;
176
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps omap2_inth_mem_ops = {
177
static void omap2_intc_init(Object *obj)
178
{
179
DeviceState *dev = DEVICE(obj);
180
- struct omap_intr_handler_s *s = OMAP_INTC(obj);
181
+ OMAPIntcState *s = OMAP_INTC(obj);
182
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
183
184
s->level_only = 1;
185
@@ -XXX,XX +XXX,XX @@ static void omap2_intc_init(Object *obj)
186
187
static void omap2_intc_realize(DeviceState *dev, Error **errp)
188
{
189
- struct omap_intr_handler_s *s = OMAP_INTC(dev);
190
+ OMAPIntcState *s = OMAP_INTC(dev);
191
192
if (!s->iclk) {
193
error_setg(errp, "omap2-intc: iclk not connected");
194
@@ -XXX,XX +XXX,XX @@ static void omap2_intc_realize(DeviceState *dev, Error **errp)
195
}
196
197
static Property omap2_intc_properties[] = {
198
- DEFINE_PROP_UINT8("revision", struct omap_intr_handler_s,
199
+ DEFINE_PROP_UINT8("revision", OMAPIntcState,
200
revision, 0x21),
201
DEFINE_PROP_END_OF_LIST(),
202
};
203
@@ -XXX,XX +XXX,XX @@ static const TypeInfo omap2_intc_info = {
204
static const TypeInfo omap_intc_type_info = {
205
.name = TYPE_OMAP_INTC,
206
.parent = TYPE_SYS_BUS_DEVICE,
207
- .instance_size = sizeof(omap_intr_handler),
208
+ .instance_size = sizeof(OMAPIntcState),
209
.abstract = true,
210
};
211
212
--
213
2.34.1
214
215
diff view generated by jsdifflib
1
We deprecated the support for KVM on 32-bit Arm hosts in time
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
for release 5.0, which means that our deprecation policy allows
3
us to drop it in release 5.2. Remove the code.
4
2
5
To repeat the rationale from the deprecation note: the Linux
3
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
kernel dropped support for 32-bit Arm KVM hosts in 5.7.
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20230109140306.23161-8-philmd@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
hw/arm/stellaris.c | 6 +++---
9
1 file changed, 3 insertions(+), 3 deletions(-)
7
10
8
Running 32-bit guests on a 64-bit Arm host remains supported.
11
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Message-id: 20200904154156.31943-2-peter.maydell@linaro.org
14
---
15
docs/system/deprecated.rst | 16 +-
16
configure | 2 +-
17
target/arm/kvm32.c | 595 -------------------------------------
18
target/arm/meson.build | 5 +-
19
4 files changed, 10 insertions(+), 608 deletions(-)
20
delete mode 100644 target/arm/kvm32.c
21
22
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
23
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
24
--- a/docs/system/deprecated.rst
13
--- a/hw/arm/stellaris.c
25
+++ b/docs/system/deprecated.rst
14
+++ b/hw/arm/stellaris.c
26
@@ -XXX,XX +XXX,XX @@ The ``compat`` property used to set backwards compatibility modes for
15
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_update(stellaris_adc_state *s)
27
the processor has been deprecated. The ``max-cpu-compat`` property of
16
28
the ``pseries`` machine type should be used instead.
17
static void stellaris_adc_trigger(void *opaque, int irq, int level)
29
18
{
30
-KVM guest support on 32-bit Arm hosts (since 5.0)
19
- stellaris_adc_state *s = (stellaris_adc_state *)opaque;
31
-'''''''''''''''''''''''''''''''''''''''''''''''''
20
+ stellaris_adc_state *s = opaque;
32
-
21
int n;
33
-The Linux kernel has dropped support for allowing 32-bit Arm systems
22
34
-to host KVM guests as of the 5.7 kernel. Accordingly, QEMU is deprecating
23
for (n = 0; n < 4; n++) {
35
-its support for this configuration and will remove it in a future version.
24
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_reset(stellaris_adc_state *s)
36
-Running 32-bit guests on a 64-bit Arm host remains supported.
25
static uint64_t stellaris_adc_read(void *opaque, hwaddr offset,
37
-
26
unsigned size)
38
System emulator devices
27
{
39
-----------------------
28
- stellaris_adc_state *s = (stellaris_adc_state *)opaque;
40
29
+ stellaris_adc_state *s = opaque;
41
@@ -XXX,XX +XXX,XX @@ should be used instead of the 1.09.1 version.
30
42
System emulator CPUS
31
/* TODO: Implement this. */
43
--------------------
32
if (offset >= 0x40 && offset < 0xc0) {
44
33
@@ -XXX,XX +XXX,XX @@ static uint64_t stellaris_adc_read(void *opaque, hwaddr offset,
45
+KVM guest support on 32-bit Arm hosts (removed in 5.2)
34
static void stellaris_adc_write(void *opaque, hwaddr offset,
46
+''''''''''''''''''''''''''''''''''''''''''''''''''''''
35
uint64_t value, unsigned size)
47
+
36
{
48
+The Linux kernel has dropped support for allowing 32-bit Arm systems
37
- stellaris_adc_state *s = (stellaris_adc_state *)opaque;
49
+to host KVM guests as of the 5.7 kernel. Accordingly, QEMU is deprecating
38
+ stellaris_adc_state *s = opaque;
50
+its support for this configuration and will remove it in a future version.
39
51
+Running 32-bit guests on a 64-bit Arm host remains supported.
40
/* TODO: Implement this. */
52
+
41
if (offset >= 0x40 && offset < 0xc0) {
53
RISC-V ISA Specific CPUs (removed in 5.1)
54
'''''''''''''''''''''''''''''''''''''''''
55
56
diff --git a/configure b/configure
57
index XXXXXXX..XXXXXXX 100755
58
--- a/configure
59
+++ b/configure
60
@@ -XXX,XX +XXX,XX @@ supported_kvm_target() {
61
test "$kvm" = "yes" || return 1
62
glob "$1" "*-softmmu" || return 1
63
case "${1%-softmmu}:$cpu" in
64
- arm:arm | aarch64:aarch64 | \
65
+ aarch64:aarch64 | \
66
i386:i386 | i386:x86_64 | i386:x32 | \
67
x86_64:i386 | x86_64:x86_64 | x86_64:x32 | \
68
mips:mips | mipsel:mips | mips64:mips | mips64el:mips | \
69
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
70
deleted file mode 100644
71
index XXXXXXX..XXXXXXX
72
--- a/target/arm/kvm32.c
73
+++ /dev/null
74
@@ -XXX,XX +XXX,XX @@
75
-/*
76
- * ARM implementation of KVM hooks, 32 bit specific code.
77
- *
78
- * Copyright Christoffer Dall 2009-2010
79
- *
80
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
81
- * See the COPYING file in the top-level directory.
82
- *
83
- */
84
-
85
-#include "qemu/osdep.h"
86
-#include <sys/ioctl.h>
87
-
88
-#include <linux/kvm.h>
89
-
90
-#include "qemu-common.h"
91
-#include "cpu.h"
92
-#include "qemu/timer.h"
93
-#include "sysemu/runstate.h"
94
-#include "sysemu/kvm.h"
95
-#include "kvm_arm.h"
96
-#include "internals.h"
97
-#include "qemu/log.h"
98
-
99
-static int read_sys_reg32(int fd, uint32_t *pret, uint64_t id)
100
-{
101
- struct kvm_one_reg idreg = { .id = id, .addr = (uintptr_t)pret };
102
-
103
- assert((id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U32);
104
- return ioctl(fd, KVM_GET_ONE_REG, &idreg);
105
-}
106
-
107
-bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
108
-{
109
- /* Identify the feature bits corresponding to the host CPU, and
110
- * fill out the ARMHostCPUClass fields accordingly. To do this
111
- * we have to create a scratch VM, create a single CPU inside it,
112
- * and then query that CPU for the relevant ID registers.
113
- */
114
- int err = 0, fdarray[3];
115
- uint32_t midr, id_pfr0;
116
- uint64_t features = 0;
117
-
118
- /* Old kernels may not know about the PREFERRED_TARGET ioctl: however
119
- * we know these will only support creating one kind of guest CPU,
120
- * which is its preferred CPU type.
121
- */
122
- static const uint32_t cpus_to_try[] = {
123
- QEMU_KVM_ARM_TARGET_CORTEX_A15,
124
- QEMU_KVM_ARM_TARGET_NONE
125
- };
126
- /*
127
- * target = -1 informs kvm_arm_create_scratch_host_vcpu()
128
- * to use the preferred target
129
- */
130
- struct kvm_vcpu_init init = { .target = -1, };
131
-
132
- if (!kvm_arm_create_scratch_host_vcpu(cpus_to_try, fdarray, &init)) {
133
- return false;
134
- }
135
-
136
- ahcf->target = init.target;
137
-
138
- /* This is not strictly blessed by the device tree binding docs yet,
139
- * but in practice the kernel does not care about this string so
140
- * there is no point maintaining an KVM_ARM_TARGET_* -> string table.
141
- */
142
- ahcf->dtb_compatible = "arm,arm-v7";
143
-
144
- err |= read_sys_reg32(fdarray[2], &midr, ARM_CP15_REG32(0, 0, 0, 0));
145
- err |= read_sys_reg32(fdarray[2], &id_pfr0, ARM_CP15_REG32(0, 0, 1, 0));
146
-
147
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar0,
148
- ARM_CP15_REG32(0, 0, 2, 0));
149
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar1,
150
- ARM_CP15_REG32(0, 0, 2, 1));
151
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar2,
152
- ARM_CP15_REG32(0, 0, 2, 2));
153
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar3,
154
- ARM_CP15_REG32(0, 0, 2, 3));
155
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar4,
156
- ARM_CP15_REG32(0, 0, 2, 4));
157
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar5,
158
- ARM_CP15_REG32(0, 0, 2, 5));
159
- if (read_sys_reg32(fdarray[2], &ahcf->isar.id_isar6,
160
- ARM_CP15_REG32(0, 0, 2, 7))) {
161
- /*
162
- * Older kernels don't support reading ID_ISAR6. This register was
163
- * only introduced in ARMv8, so we can assume that it is zero on a
164
- * CPU that a kernel this old is running on.
165
- */
166
- ahcf->isar.id_isar6 = 0;
167
- }
168
-
169
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0,
170
- ARM_CP15_REG32(0, 0, 1, 2));
171
-
172
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr0,
173
- KVM_REG_ARM | KVM_REG_SIZE_U32 |
174
- KVM_REG_ARM_VFP | KVM_REG_ARM_VFP_MVFR0);
175
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr1,
176
- KVM_REG_ARM | KVM_REG_SIZE_U32 |
177
- KVM_REG_ARM_VFP | KVM_REG_ARM_VFP_MVFR1);
178
- /*
179
- * FIXME: There is not yet a way to read MVFR2.
180
- * Fortunately there is not yet anything in there that affects migration.
181
- */
182
-
183
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0,
184
- ARM_CP15_REG32(0, 0, 1, 4));
185
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1,
186
- ARM_CP15_REG32(0, 0, 1, 5));
187
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr2,
188
- ARM_CP15_REG32(0, 0, 1, 6));
189
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3,
190
- ARM_CP15_REG32(0, 0, 1, 7));
191
- if (read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4,
192
- ARM_CP15_REG32(0, 0, 2, 6))) {
193
- /*
194
- * Older kernels don't support reading ID_MMFR4 (a new in v8
195
- * register); assume it's zero.
196
- */
197
- ahcf->isar.id_mmfr4 = 0;
198
- }
199
-
200
- /*
201
- * There is no way to read DBGDIDR, because currently 32-bit KVM
202
- * doesn't implement debug at all. Leave it at zero.
203
- */
204
-
205
- kvm_arm_destroy_scratch_host_vcpu(fdarray);
206
-
207
- if (err < 0) {
208
- return false;
209
- }
210
-
211
- /* Now we've retrieved all the register information we can
212
- * set the feature bits based on the ID register fields.
213
- * We can assume any KVM supporting CPU is at least a v7
214
- * with VFPv3, virtualization extensions, and the generic
215
- * timers; this in turn implies most of the other feature
216
- * bits, but a few must be tested.
217
- */
218
- features |= 1ULL << ARM_FEATURE_V7VE;
219
- features |= 1ULL << ARM_FEATURE_GENERIC_TIMER;
220
-
221
- if (extract32(id_pfr0, 12, 4) == 1) {
222
- features |= 1ULL << ARM_FEATURE_THUMB2EE;
223
- }
224
- if (extract32(ahcf->isar.mvfr1, 12, 4) == 1) {
225
- features |= 1ULL << ARM_FEATURE_NEON;
226
- }
227
-
228
- ahcf->features = features;
229
-
230
- return true;
231
-}
232
-
233
-bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx)
234
-{
235
- /* Return true if the regidx is a register we should synchronize
236
- * via the cpreg_tuples array (ie is not a core reg we sync by
237
- * hand in kvm_arch_get/put_registers())
238
- */
239
- switch (regidx & KVM_REG_ARM_COPROC_MASK) {
240
- case KVM_REG_ARM_CORE:
241
- case KVM_REG_ARM_VFP:
242
- return false;
243
- default:
244
- return true;
245
- }
246
-}
247
-
248
-typedef struct CPRegStateLevel {
249
- uint64_t regidx;
250
- int level;
251
-} CPRegStateLevel;
252
-
253
-/* All coprocessor registers not listed in the following table are assumed to
254
- * be of the level KVM_PUT_RUNTIME_STATE. If a register should be written less
255
- * often, you must add it to this table with a state of either
256
- * KVM_PUT_RESET_STATE or KVM_PUT_FULL_STATE.
257
- */
258
-static const CPRegStateLevel non_runtime_cpregs[] = {
259
- { KVM_REG_ARM_TIMER_CNT, KVM_PUT_FULL_STATE },
260
-};
261
-
262
-int kvm_arm_cpreg_level(uint64_t regidx)
263
-{
264
- int i;
265
-
266
- for (i = 0; i < ARRAY_SIZE(non_runtime_cpregs); i++) {
267
- const CPRegStateLevel *l = &non_runtime_cpregs[i];
268
- if (l->regidx == regidx) {
269
- return l->level;
270
- }
271
- }
272
-
273
- return KVM_PUT_RUNTIME_STATE;
274
-}
275
-
276
-#define ARM_CPU_ID_MPIDR 0, 0, 0, 5
277
-
278
-int kvm_arch_init_vcpu(CPUState *cs)
279
-{
280
- int ret;
281
- uint64_t v;
282
- uint32_t mpidr;
283
- struct kvm_one_reg r;
284
- ARMCPU *cpu = ARM_CPU(cs);
285
-
286
- if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE) {
287
- fprintf(stderr, "KVM is not supported for this guest CPU type\n");
288
- return -EINVAL;
289
- }
290
-
291
- qemu_add_vm_change_state_handler(kvm_arm_vm_state_change, cs);
292
-
293
- /* Determine init features for this CPU */
294
- memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features));
295
- if (cs->start_powered_off) {
296
- cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_POWER_OFF;
297
- }
298
- if (kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_PSCI_0_2)) {
299
- cpu->psci_version = 2;
300
- cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_PSCI_0_2;
301
- }
302
-
303
- /* Do KVM_ARM_VCPU_INIT ioctl */
304
- ret = kvm_arm_vcpu_init(cs);
305
- if (ret) {
306
- return ret;
307
- }
308
-
309
- /* Query the kernel to make sure it supports 32 VFP
310
- * registers: QEMU's "cortex-a15" CPU is always a
311
- * VFP-D32 core. The simplest way to do this is just
312
- * to attempt to read register d31.
313
- */
314
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP | 31;
315
- r.addr = (uintptr_t)(&v);
316
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
317
- if (ret == -ENOENT) {
318
- return -EINVAL;
319
- }
320
-
321
- /*
322
- * When KVM is in use, PSCI is emulated in-kernel and not by qemu.
323
- * Currently KVM has its own idea about MPIDR assignment, so we
324
- * override our defaults with what we get from KVM.
325
- */
326
- ret = kvm_get_one_reg(cs, ARM_CP15_REG32(ARM_CPU_ID_MPIDR), &mpidr);
327
- if (ret) {
328
- return ret;
329
- }
330
- cpu->mp_affinity = mpidr & ARM32_AFFINITY_MASK;
331
-
332
- /* Check whether userspace can specify guest syndrome value */
333
- kvm_arm_init_serror_injection(cs);
334
-
335
- return kvm_arm_init_cpreg_list(cpu);
336
-}
337
-
338
-int kvm_arch_destroy_vcpu(CPUState *cs)
339
-{
340
-    return 0;
341
-}
342
-
343
-typedef struct Reg {
344
- uint64_t id;
345
- int offset;
346
-} Reg;
347
-
348
-#define COREREG(KERNELNAME, QEMUFIELD) \
349
- { \
350
- KVM_REG_ARM | KVM_REG_SIZE_U32 | \
351
- KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(KERNELNAME), \
352
- offsetof(CPUARMState, QEMUFIELD) \
353
- }
354
-
355
-#define VFPSYSREG(R) \
356
- { \
357
- KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP | \
358
- KVM_REG_ARM_VFP_##R, \
359
- offsetof(CPUARMState, vfp.xregs[ARM_VFP_##R]) \
360
- }
361
-
362
-/* Like COREREG, but handle fields which are in a uint64_t in CPUARMState. */
363
-#define COREREG64(KERNELNAME, QEMUFIELD) \
364
- { \
365
- KVM_REG_ARM | KVM_REG_SIZE_U32 | \
366
- KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(KERNELNAME), \
367
- offsetoflow32(CPUARMState, QEMUFIELD) \
368
- }
369
-
370
-static const Reg regs[] = {
371
- /* R0_usr .. R14_usr */
372
- COREREG(usr_regs.uregs[0], regs[0]),
373
- COREREG(usr_regs.uregs[1], regs[1]),
374
- COREREG(usr_regs.uregs[2], regs[2]),
375
- COREREG(usr_regs.uregs[3], regs[3]),
376
- COREREG(usr_regs.uregs[4], regs[4]),
377
- COREREG(usr_regs.uregs[5], regs[5]),
378
- COREREG(usr_regs.uregs[6], regs[6]),
379
- COREREG(usr_regs.uregs[7], regs[7]),
380
- COREREG(usr_regs.uregs[8], usr_regs[0]),
381
- COREREG(usr_regs.uregs[9], usr_regs[1]),
382
- COREREG(usr_regs.uregs[10], usr_regs[2]),
383
- COREREG(usr_regs.uregs[11], usr_regs[3]),
384
- COREREG(usr_regs.uregs[12], usr_regs[4]),
385
- COREREG(usr_regs.uregs[13], banked_r13[BANK_USRSYS]),
386
- COREREG(usr_regs.uregs[14], banked_r14[BANK_USRSYS]),
387
- /* R13, R14, SPSR for SVC, ABT, UND, IRQ banks */
388
- COREREG(svc_regs[0], banked_r13[BANK_SVC]),
389
- COREREG(svc_regs[1], banked_r14[BANK_SVC]),
390
- COREREG64(svc_regs[2], banked_spsr[BANK_SVC]),
391
- COREREG(abt_regs[0], banked_r13[BANK_ABT]),
392
- COREREG(abt_regs[1], banked_r14[BANK_ABT]),
393
- COREREG64(abt_regs[2], banked_spsr[BANK_ABT]),
394
- COREREG(und_regs[0], banked_r13[BANK_UND]),
395
- COREREG(und_regs[1], banked_r14[BANK_UND]),
396
- COREREG64(und_regs[2], banked_spsr[BANK_UND]),
397
- COREREG(irq_regs[0], banked_r13[BANK_IRQ]),
398
- COREREG(irq_regs[1], banked_r14[BANK_IRQ]),
399
- COREREG64(irq_regs[2], banked_spsr[BANK_IRQ]),
400
- /* R8_fiq .. R14_fiq and SPSR_fiq */
401
- COREREG(fiq_regs[0], fiq_regs[0]),
402
- COREREG(fiq_regs[1], fiq_regs[1]),
403
- COREREG(fiq_regs[2], fiq_regs[2]),
404
- COREREG(fiq_regs[3], fiq_regs[3]),
405
- COREREG(fiq_regs[4], fiq_regs[4]),
406
- COREREG(fiq_regs[5], banked_r13[BANK_FIQ]),
407
- COREREG(fiq_regs[6], banked_r14[BANK_FIQ]),
408
- COREREG64(fiq_regs[7], banked_spsr[BANK_FIQ]),
409
- /* R15 */
410
- COREREG(usr_regs.uregs[15], regs[15]),
411
- /* VFP system registers */
412
- VFPSYSREG(FPSID),
413
- VFPSYSREG(MVFR1),
414
- VFPSYSREG(MVFR0),
415
- VFPSYSREG(FPEXC),
416
- VFPSYSREG(FPINST),
417
- VFPSYSREG(FPINST2),
418
-};
419
-
420
-int kvm_arch_put_registers(CPUState *cs, int level)
421
-{
422
- ARMCPU *cpu = ARM_CPU(cs);
423
- CPUARMState *env = &cpu->env;
424
- struct kvm_one_reg r;
425
- int mode, bn;
426
- int ret, i;
427
- uint32_t cpsr, fpscr;
428
-
429
- /* Make sure the banked regs are properly set */
430
- mode = env->uncached_cpsr & CPSR_M;
431
- bn = bank_number(mode);
432
- if (mode == ARM_CPU_MODE_FIQ) {
433
- memcpy(env->fiq_regs, env->regs + 8, 5 * sizeof(uint32_t));
434
- } else {
435
- memcpy(env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t));
436
- }
437
- env->banked_r13[bn] = env->regs[13];
438
- env->banked_spsr[bn] = env->spsr;
439
- env->banked_r14[r14_bank_number(mode)] = env->regs[14];
440
-
441
- /* Now we can safely copy stuff down to the kernel */
442
- for (i = 0; i < ARRAY_SIZE(regs); i++) {
443
- r.id = regs[i].id;
444
- r.addr = (uintptr_t)(env) + regs[i].offset;
445
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
446
- if (ret) {
447
- return ret;
448
- }
449
- }
450
-
451
- /* Special cases which aren't a single CPUARMState field */
452
- cpsr = cpsr_read(env);
453
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 |
454
- KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr);
455
- r.addr = (uintptr_t)(&cpsr);
456
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
457
- if (ret) {
458
- return ret;
459
- }
460
-
461
- /* VFP registers */
462
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
463
- for (i = 0; i < 32; i++) {
464
- r.addr = (uintptr_t)aa32_vfp_dreg(env, i);
465
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
466
- if (ret) {
467
- return ret;
468
- }
469
- r.id++;
470
- }
471
-
472
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP |
473
- KVM_REG_ARM_VFP_FPSCR;
474
- fpscr = vfp_get_fpscr(env);
475
- r.addr = (uintptr_t)&fpscr;
476
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
477
- if (ret) {
478
- return ret;
479
- }
480
-
481
- write_cpustate_to_list(cpu, true);
482
-
483
- if (!write_list_to_kvmstate(cpu, level)) {
484
- return EINVAL;
485
- }
486
-
487
- /*
488
- * Setting VCPU events should be triggered after syncing the registers
489
- * to avoid overwriting potential changes made by KVM upon calling
490
- * KVM_SET_VCPU_EVENTS ioctl
491
- */
492
- ret = kvm_put_vcpu_events(cpu);
493
- if (ret) {
494
- return ret;
495
- }
496
-
497
- kvm_arm_sync_mpstate_to_kvm(cpu);
498
-
499
- return ret;
500
-}
501
-
502
-int kvm_arch_get_registers(CPUState *cs)
503
-{
504
- ARMCPU *cpu = ARM_CPU(cs);
505
- CPUARMState *env = &cpu->env;
506
- struct kvm_one_reg r;
507
- int mode, bn;
508
- int ret, i;
509
- uint32_t cpsr, fpscr;
510
-
511
- for (i = 0; i < ARRAY_SIZE(regs); i++) {
512
- r.id = regs[i].id;
513
- r.addr = (uintptr_t)(env) + regs[i].offset;
514
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
515
- if (ret) {
516
- return ret;
517
- }
518
- }
519
-
520
- /* Special cases which aren't a single CPUARMState field */
521
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 |
522
- KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr);
523
- r.addr = (uintptr_t)(&cpsr);
524
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
525
- if (ret) {
526
- return ret;
527
- }
528
- cpsr_write(env, cpsr, 0xffffffff, CPSRWriteRaw);
529
-
530
- /* Make sure the current mode regs are properly set */
531
- mode = env->uncached_cpsr & CPSR_M;
532
- bn = bank_number(mode);
533
- if (mode == ARM_CPU_MODE_FIQ) {
534
- memcpy(env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));
535
- } else {
536
- memcpy(env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t));
537
- }
538
- env->regs[13] = env->banked_r13[bn];
539
- env->spsr = env->banked_spsr[bn];
540
- env->regs[14] = env->banked_r14[r14_bank_number(mode)];
541
-
542
- /* VFP registers */
543
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
544
- for (i = 0; i < 32; i++) {
545
- r.addr = (uintptr_t)aa32_vfp_dreg(env, i);
546
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
547
- if (ret) {
548
- return ret;
549
- }
550
- r.id++;
551
- }
552
-
553
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP |
554
- KVM_REG_ARM_VFP_FPSCR;
555
- r.addr = (uintptr_t)&fpscr;
556
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
557
- if (ret) {
558
- return ret;
559
- }
560
- vfp_set_fpscr(env, fpscr);
561
-
562
- ret = kvm_get_vcpu_events(cpu);
563
- if (ret) {
564
- return ret;
565
- }
566
-
567
- if (!write_kvmstate_to_list(cpu)) {
568
- return EINVAL;
569
- }
570
- /* Note that it's OK to have registers which aren't in CPUState,
571
- * so we can ignore a failure return here.
572
- */
573
- write_list_to_cpustate(cpu);
574
-
575
- kvm_arm_sync_mpstate_to_qemu(cpu);
576
-
577
- return 0;
578
-}
579
-
580
-int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
581
-{
582
- qemu_log_mask(LOG_UNIMP, "%s: guest debug not yet implemented\n", __func__);
583
- return -EINVAL;
584
-}
585
-
586
-int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
587
-{
588
- qemu_log_mask(LOG_UNIMP, "%s: guest debug not yet implemented\n", __func__);
589
- return -EINVAL;
590
-}
591
-
592
-bool kvm_arm_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit)
593
-{
594
- qemu_log_mask(LOG_UNIMP, "%s: guest debug not yet implemented\n", __func__);
595
- return false;
596
-}
597
-
598
-int kvm_arch_insert_hw_breakpoint(target_ulong addr,
599
- target_ulong len, int type)
600
-{
601
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
602
- return -EINVAL;
603
-}
604
-
605
-int kvm_arch_remove_hw_breakpoint(target_ulong addr,
606
- target_ulong len, int type)
607
-{
608
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
609
- return -EINVAL;
610
-}
611
-
612
-void kvm_arch_remove_all_hw_breakpoints(void)
613
-{
614
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
615
-}
616
-
617
-void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr)
618
-{
619
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
620
-}
621
-
622
-bool kvm_arm_hw_debug_active(CPUState *cs)
623
-{
624
- return false;
625
-}
626
-
627
-void kvm_arm_pmu_set_irq(CPUState *cs, int irq)
628
-{
629
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
630
-}
631
-
632
-void kvm_arm_pmu_init(CPUState *cs)
633
-{
634
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
635
-}
636
-
637
-#define ARM_REG_DFSR ARM_CP15_REG32(0, 5, 0, 0)
638
-#define ARM_REG_TTBCR ARM_CP15_REG32(0, 2, 0, 2)
639
-/*
640
- *DFSR:
641
- * TTBCR.EAE == 0
642
- * FS[4] - DFSR[10]
643
- * FS[3:0] - DFSR[3:0]
644
- * TTBCR.EAE == 1
645
- * FS, bits [5:0]
646
- */
647
-#define DFSR_FSC(lpae, v) \
648
- ((lpae) ? ((v) & 0x3F) : (((v) >> 6) | ((v) & 0x1F)))
649
-
650
-#define DFSC_EXTABT(lpae) ((lpae) ? 0x10 : 0x08)
651
-
652
-bool kvm_arm_verify_ext_dabt_pending(CPUState *cs)
653
-{
654
- uint32_t dfsr_val;
655
-
656
- if (!kvm_get_one_reg(cs, ARM_REG_DFSR, &dfsr_val)) {
657
- ARMCPU *cpu = ARM_CPU(cs);
658
- CPUARMState *env = &cpu->env;
659
- uint32_t ttbcr;
660
- int lpae = 0;
661
-
662
- if (!kvm_get_one_reg(cs, ARM_REG_TTBCR, &ttbcr)) {
663
- lpae = arm_feature(env, ARM_FEATURE_LPAE) && (ttbcr & TTBCR_EAE);
664
- }
665
- /* The verification is based on FS filed of the DFSR reg only*/
666
- return (DFSR_FSC(lpae, dfsr_val) == DFSC_EXTABT(lpae));
667
- }
668
- return false;
669
-}
670
diff --git a/target/arm/meson.build b/target/arm/meson.build
671
index XXXXXXX..XXXXXXX 100644
672
--- a/target/arm/meson.build
673
+++ b/target/arm/meson.build
674
@@ -XXX,XX +XXX,XX @@ arm_ss.add(zlib)
675
676
arm_ss.add(when: 'CONFIG_TCG', if_true: files('arm-semi.c'))
677
678
-kvm_ss = ss.source_set()
679
-kvm_ss.add(when: 'TARGET_AARCH64', if_true: files('kvm64.c'), if_false: files('kvm32.c'))
680
-arm_ss.add_all(when: 'CONFIG_KVM', if_true: kvm_ss)
681
-arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: files('kvm-stub.c'))
682
+arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c', 'kvm64.c'), if_false: files('kvm-stub.c'))
683
684
arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
685
'cpu64.c',
686
--
42
--
687
2.20.1
43
2.34.1
688
44
689
45
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
Per the datasheet (DDI0407 r2p0):
3
Following docs/devel/style.rst guidelines, rename
4
stellaris_adc_state -> StellarisADCState. This also remove a
5
use of 'struct' in the DECLARE_INSTANCE_CHECKER() macro call.
4
6
5
"The SCU connects one to four Cortex-A9 processors to
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
the memory system through the AXI interfaces."
7
8
Change the instance_init() handler to a device_realize()
9
one so we can verify the property is in range, and return
10
an error to the caller if not.
11
12
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20200901144100.116742-2-f4bug@amsat.org
9
Message-id: 20230109140306.23161-9-philmd@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
11
---
17
hw/misc/a9scu.c | 18 +++++++++++++-----
12
hw/arm/stellaris.c | 73 +++++++++++++++++++++++-----------------------
18
1 file changed, 13 insertions(+), 5 deletions(-)
13
1 file changed, 36 insertions(+), 37 deletions(-)
19
14
20
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
15
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
21
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/a9scu.c
17
--- a/hw/arm/stellaris.c
23
+++ b/hw/misc/a9scu.c
18
+++ b/hw/arm/stellaris.c
24
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static void stellaris_i2c_init(Object *obj)
25
#include "hw/misc/a9scu.h"
20
#define STELLARIS_ADC_FIFO_FULL 0x1000
26
#include "hw/qdev-properties.h"
21
27
#include "migration/vmstate.h"
22
#define TYPE_STELLARIS_ADC "stellaris-adc"
28
+#include "qapi/error.h"
23
-typedef struct StellarisADCState stellaris_adc_state;
29
#include "qemu/module.h"
24
-DECLARE_INSTANCE_CHECKER(stellaris_adc_state, STELLARIS_ADC,
30
25
- TYPE_STELLARIS_ADC)
31
+#define A9_SCU_CPU_MAX 4
26
+typedef struct StellarisADCState StellarisADCState;
32
+
27
+DECLARE_INSTANCE_CHECKER(StellarisADCState, STELLARIS_ADC, TYPE_STELLARIS_ADC)
33
static uint64_t a9_scu_read(void *opaque, hwaddr offset,
28
34
unsigned size)
29
struct StellarisADCState {
30
SysBusDevice parent_obj;
31
@@ -XXX,XX +XXX,XX @@ struct StellarisADCState {
32
qemu_irq irq[4];
33
};
34
35
-static uint32_t stellaris_adc_fifo_read(stellaris_adc_state *s, int n)
36
+static uint32_t stellaris_adc_fifo_read(StellarisADCState *s, int n)
35
{
37
{
36
@@ -XXX,XX +XXX,XX @@ static void a9_scu_reset(DeviceState *dev)
38
int tail;
37
s->control = 0;
39
40
@@ -XXX,XX +XXX,XX @@ static uint32_t stellaris_adc_fifo_read(stellaris_adc_state *s, int n)
41
return s->fifo[n].data[tail];
38
}
42
}
39
43
40
-static void a9_scu_init(Object *obj)
44
-static void stellaris_adc_fifo_write(stellaris_adc_state *s, int n,
41
+static void a9_scu_realize(DeviceState *dev, Error **errp)
45
+static void stellaris_adc_fifo_write(StellarisADCState *s, int n,
46
uint32_t value)
42
{
47
{
43
- A9SCUState *s = A9_SCU(obj);
48
int head;
44
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
49
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_fifo_write(stellaris_adc_state *s, int n,
45
+ A9SCUState *s = A9_SCU(dev);
50
s->fifo[n].state |= STELLARIS_ADC_FIFO_FULL;
46
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
47
48
- memory_region_init_io(&s->iomem, obj, &a9_scu_ops, s,
49
+ if (!s->num_cpu || s->num_cpu > A9_SCU_CPU_MAX) {
50
+ error_setg(errp, "Illegal CPU count: %u", s->num_cpu);
51
+ return;
52
+ }
53
+
54
+ memory_region_init_io(&s->iomem, OBJECT(s), &a9_scu_ops, s,
55
"a9-scu", 0x100);
56
sysbus_init_mmio(sbd, &s->iomem);
57
}
51
}
58
@@ -XXX,XX +XXX,XX @@ static void a9_scu_class_init(ObjectClass *klass, void *data)
52
59
device_class_set_props(dc, a9_scu_properties);
53
-static void stellaris_adc_update(stellaris_adc_state *s)
60
dc->vmsd = &vmstate_a9_scu;
54
+static void stellaris_adc_update(StellarisADCState *s)
61
dc->reset = a9_scu_reset;
55
{
62
+ dc->realize = a9_scu_realize;
56
int level;
57
int n;
58
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_update(stellaris_adc_state *s)
59
60
static void stellaris_adc_trigger(void *opaque, int irq, int level)
61
{
62
- stellaris_adc_state *s = opaque;
63
+ StellarisADCState *s = opaque;
64
int n;
65
66
for (n = 0; n < 4; n++) {
67
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_trigger(void *opaque, int irq, int level)
68
}
63
}
69
}
64
70
65
static const TypeInfo a9_scu_info = {
71
-static void stellaris_adc_reset(stellaris_adc_state *s)
66
.name = TYPE_A9_SCU,
72
+static void stellaris_adc_reset(StellarisADCState *s)
73
{
74
int n;
75
76
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_reset(stellaris_adc_state *s)
77
static uint64_t stellaris_adc_read(void *opaque, hwaddr offset,
78
unsigned size)
79
{
80
- stellaris_adc_state *s = opaque;
81
+ StellarisADCState *s = opaque;
82
83
/* TODO: Implement this. */
84
if (offset >= 0x40 && offset < 0xc0) {
85
@@ -XXX,XX +XXX,XX @@ static uint64_t stellaris_adc_read(void *opaque, hwaddr offset,
86
static void stellaris_adc_write(void *opaque, hwaddr offset,
87
uint64_t value, unsigned size)
88
{
89
- stellaris_adc_state *s = opaque;
90
+ StellarisADCState *s = opaque;
91
92
/* TODO: Implement this. */
93
if (offset >= 0x40 && offset < 0xc0) {
94
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_stellaris_adc = {
95
.version_id = 1,
96
.minimum_version_id = 1,
97
.fields = (VMStateField[]) {
98
- VMSTATE_UINT32(actss, stellaris_adc_state),
99
- VMSTATE_UINT32(ris, stellaris_adc_state),
100
- VMSTATE_UINT32(im, stellaris_adc_state),
101
- VMSTATE_UINT32(emux, stellaris_adc_state),
102
- VMSTATE_UINT32(ostat, stellaris_adc_state),
103
- VMSTATE_UINT32(ustat, stellaris_adc_state),
104
- VMSTATE_UINT32(sspri, stellaris_adc_state),
105
- VMSTATE_UINT32(sac, stellaris_adc_state),
106
- VMSTATE_UINT32(fifo[0].state, stellaris_adc_state),
107
- VMSTATE_UINT32_ARRAY(fifo[0].data, stellaris_adc_state, 16),
108
- VMSTATE_UINT32(ssmux[0], stellaris_adc_state),
109
- VMSTATE_UINT32(ssctl[0], stellaris_adc_state),
110
- VMSTATE_UINT32(fifo[1].state, stellaris_adc_state),
111
- VMSTATE_UINT32_ARRAY(fifo[1].data, stellaris_adc_state, 16),
112
- VMSTATE_UINT32(ssmux[1], stellaris_adc_state),
113
- VMSTATE_UINT32(ssctl[1], stellaris_adc_state),
114
- VMSTATE_UINT32(fifo[2].state, stellaris_adc_state),
115
- VMSTATE_UINT32_ARRAY(fifo[2].data, stellaris_adc_state, 16),
116
- VMSTATE_UINT32(ssmux[2], stellaris_adc_state),
117
- VMSTATE_UINT32(ssctl[2], stellaris_adc_state),
118
- VMSTATE_UINT32(fifo[3].state, stellaris_adc_state),
119
- VMSTATE_UINT32_ARRAY(fifo[3].data, stellaris_adc_state, 16),
120
- VMSTATE_UINT32(ssmux[3], stellaris_adc_state),
121
- VMSTATE_UINT32(ssctl[3], stellaris_adc_state),
122
- VMSTATE_UINT32(noise, stellaris_adc_state),
123
+ VMSTATE_UINT32(actss, StellarisADCState),
124
+ VMSTATE_UINT32(ris, StellarisADCState),
125
+ VMSTATE_UINT32(im, StellarisADCState),
126
+ VMSTATE_UINT32(emux, StellarisADCState),
127
+ VMSTATE_UINT32(ostat, StellarisADCState),
128
+ VMSTATE_UINT32(ustat, StellarisADCState),
129
+ VMSTATE_UINT32(sspri, StellarisADCState),
130
+ VMSTATE_UINT32(sac, StellarisADCState),
131
+ VMSTATE_UINT32(fifo[0].state, StellarisADCState),
132
+ VMSTATE_UINT32_ARRAY(fifo[0].data, StellarisADCState, 16),
133
+ VMSTATE_UINT32(ssmux[0], StellarisADCState),
134
+ VMSTATE_UINT32(ssctl[0], StellarisADCState),
135
+ VMSTATE_UINT32(fifo[1].state, StellarisADCState),
136
+ VMSTATE_UINT32_ARRAY(fifo[1].data, StellarisADCState, 16),
137
+ VMSTATE_UINT32(ssmux[1], StellarisADCState),
138
+ VMSTATE_UINT32(ssctl[1], StellarisADCState),
139
+ VMSTATE_UINT32(fifo[2].state, StellarisADCState),
140
+ VMSTATE_UINT32_ARRAY(fifo[2].data, StellarisADCState, 16),
141
+ VMSTATE_UINT32(ssmux[2], StellarisADCState),
142
+ VMSTATE_UINT32(ssctl[2], StellarisADCState),
143
+ VMSTATE_UINT32(fifo[3].state, StellarisADCState),
144
+ VMSTATE_UINT32_ARRAY(fifo[3].data, StellarisADCState, 16),
145
+ VMSTATE_UINT32(ssmux[3], StellarisADCState),
146
+ VMSTATE_UINT32(ssctl[3], StellarisADCState),
147
+ VMSTATE_UINT32(noise, StellarisADCState),
148
VMSTATE_END_OF_LIST()
149
}
150
};
151
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_stellaris_adc = {
152
static void stellaris_adc_init(Object *obj)
153
{
154
DeviceState *dev = DEVICE(obj);
155
- stellaris_adc_state *s = STELLARIS_ADC(obj);
156
+ StellarisADCState *s = STELLARIS_ADC(obj);
157
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
158
int n;
159
160
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_class_init(ObjectClass *klass, void *data)
161
static const TypeInfo stellaris_adc_info = {
162
.name = TYPE_STELLARIS_ADC,
67
.parent = TYPE_SYS_BUS_DEVICE,
163
.parent = TYPE_SYS_BUS_DEVICE,
68
.instance_size = sizeof(A9SCUState),
164
- .instance_size = sizeof(stellaris_adc_state),
69
- .instance_init = a9_scu_init,
165
+ .instance_size = sizeof(StellarisADCState),
70
.class_init = a9_scu_class_init,
166
.instance_init = stellaris_adc_init,
167
.class_init = stellaris_adc_class_init,
71
};
168
};
72
73
--
169
--
74
2.20.1
170
2.34.1
75
171
76
172
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
Only argument set members have to be C identifiers, everything
3
The typedef and definitions are generated by the OBJECT_DECLARE_TYPE
4
else gets prefixed during conversion to C. Some places just
4
macro in "hw/arm/bcm2836.h":
5
checked the leading character, and some places matched a leading
6
character plus a C identifier.
7
5
8
Convert everything to match full identifiers, including the
6
20 #define TYPE_BCM283X "bcm283x"
9
[&%@&] prefix, and drop the full C identifier requirement.
7
21 OBJECT_DECLARE_TYPE(BCM283XState, BCM283XClass, BCM283X)
10
8
11
Reported-by: Peter Maydell <peter.maydell@linaro.org>
9
The script ran in commit a489d1951c ("Use OBJECT_DECLARE_TYPE when
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
possible") missed them because they are declared in a different
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
file unit. Remove them.
14
Message-id: 20200903192334.1603773-1-richard.henderson@linaro.org
12
13
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20230109140306.23161-10-philmd@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
---
17
tests/decode/succ_ident1.decode | 7 +++++
18
hw/arm/bcm2836.c | 9 ++-------
18
scripts/decodetree.py | 46 +++++++++++++++++++++------------
19
1 file changed, 2 insertions(+), 7 deletions(-)
19
2 files changed, 37 insertions(+), 16 deletions(-)
20
create mode 100644 tests/decode/succ_ident1.decode
21
20
22
diff --git a/tests/decode/succ_ident1.decode b/tests/decode/succ_ident1.decode
21
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
23
new file mode 100644
22
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX
23
--- a/hw/arm/bcm2836.c
25
--- /dev/null
24
+++ b/hw/arm/bcm2836.c
26
+++ b/tests/decode/succ_ident1.decode
27
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@
28
+%1f 0:8
26
#include "hw/arm/raspi_platform.h"
29
+%2f 8:8
27
#include "hw/sysbus.h"
30
+%3f 16:8
28
31
+
29
-typedef struct BCM283XClass {
32
+&3arg a b c
30
+struct BCM283XClass {
33
+@3arg ........ ........ ........ ........ &3arg a=%1f b=%2f c=%3f
31
/*< private >*/
34
+3insn 00000000 ........ ........ ........ @3arg
32
DeviceClass parent_class;
35
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
33
/*< public >*/
36
index XXXXXXX..XXXXXXX 100644
34
@@ -XXX,XX +XXX,XX @@ typedef struct BCM283XClass {
37
--- a/scripts/decodetree.py
35
hwaddr peri_base; /* Peripheral base address seen by the CPU */
38
+++ b/scripts/decodetree.py
36
hwaddr ctrl_base; /* Interrupt controller and mailboxes etc. */
39
@@ -XXX,XX +XXX,XX @@ output_fd = None
37
int clusterid;
40
insntype = 'uint32_t'
38
-} BCM283XClass;
41
decode_function = 'decode'
39
-
42
40
-#define BCM283X_CLASS(klass) \
43
-re_ident = '[a-zA-Z][a-zA-Z0-9_]*'
41
- OBJECT_CLASS_CHECK(BCM283XClass, (klass), TYPE_BCM283X)
44
+# An identifier for C.
42
-#define BCM283X_GET_CLASS(obj) \
45
+re_C_ident = '[a-zA-Z][a-zA-Z0-9_]*'
43
- OBJECT_GET_CLASS(BCM283XClass, (obj), TYPE_BCM283X)
46
44
+};
47
+# Identifiers for Arguments, Fields, Formats and Patterns.
45
48
+re_arg_ident = '&[a-zA-Z0-9_]*'
46
static Property bcm2836_enabled_cores_property =
49
+re_fld_ident = '%[a-zA-Z0-9_]*'
47
DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus, 0);
50
+re_fmt_ident = '@[a-zA-Z0-9_]*'
51
+re_pat_ident = '[a-zA-Z0-9_]*'
52
53
def error_with_file(file, lineno, *args):
54
"""Print an error message from file:line and args and exit."""
55
@@ -XXX,XX +XXX,XX @@ class ExcMultiPattern(MultiPattern):
56
def parse_field(lineno, name, toks):
57
"""Parse one instruction field from TOKS at LINENO"""
58
global fields
59
- global re_ident
60
global insnwidth
61
62
# A "simple" field will have only one entry;
63
@@ -XXX,XX +XXX,XX @@ def parse_field(lineno, name, toks):
64
width = 0
65
func = None
66
for t in toks:
67
- if re.fullmatch('!function=' + re_ident, t):
68
+ if re.match('^!function=', t):
69
if func:
70
error(lineno, 'duplicate function')
71
func = t.split('=')
72
@@ -XXX,XX +XXX,XX @@ def parse_field(lineno, name, toks):
73
def parse_arguments(lineno, name, toks):
74
"""Parse one argument set from TOKS at LINENO"""
75
global arguments
76
- global re_ident
77
+ global re_C_ident
78
global anyextern
79
80
flds = []
81
@@ -XXX,XX +XXX,XX @@ def parse_arguments(lineno, name, toks):
82
extern = True
83
anyextern = True
84
continue
85
- if not re.fullmatch(re_ident, t):
86
+ if not re.fullmatch(re_C_ident, t):
87
error(lineno, 'invalid argument set token "{0}"'.format(t))
88
if t in flds:
89
error(lineno, 'duplicate argument "{0}"'.format(t))
90
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
91
global arguments
92
global formats
93
global allpatterns
94
- global re_ident
95
+ global re_arg_ident
96
+ global re_fld_ident
97
+ global re_fmt_ident
98
+ global re_C_ident
99
global insnwidth
100
global insnmask
101
global variablewidth
102
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
103
fmt = None
104
for t in toks:
105
# '&Foo' gives a format an explcit argument set.
106
- if t[0] == '&':
107
+ if re.fullmatch(re_arg_ident, t):
108
tt = t[1:]
109
if arg:
110
error(lineno, 'multiple argument sets')
111
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
112
continue
113
114
# '@Foo' gives a pattern an explicit format.
115
- if t[0] == '@':
116
+ if re.fullmatch(re_fmt_ident, t):
117
tt = t[1:]
118
if fmt:
119
error(lineno, 'multiple formats')
120
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
121
continue
122
123
# '%Foo' imports a field.
124
- if t[0] == '%':
125
+ if re.fullmatch(re_fld_ident, t):
126
tt = t[1:]
127
flds = add_field_byname(lineno, flds, tt, tt)
128
continue
129
130
# 'Foo=%Bar' imports a field with a different name.
131
- if re.fullmatch(re_ident + '=%' + re_ident, t):
132
+ if re.fullmatch(re_C_ident + '=' + re_fld_ident, t):
133
(fname, iname) = t.split('=%')
134
flds = add_field_byname(lineno, flds, fname, iname)
135
continue
136
137
# 'Foo=number' sets an argument field to a constant value
138
- if re.fullmatch(re_ident + '=[+-]?[0-9]+', t):
139
+ if re.fullmatch(re_C_ident + '=[+-]?[0-9]+', t):
140
(fname, value) = t.split('=')
141
value = int(value)
142
flds = add_field(lineno, flds, fname, ConstField(value))
143
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
144
fixedmask = (fixedmask << shift) | fms
145
undefmask = (undefmask << shift) | ubm
146
# Otherwise, fieldname:fieldwidth
147
- elif re.fullmatch(re_ident + ':s?[0-9]+', t):
148
+ elif re.fullmatch(re_C_ident + ':s?[0-9]+', t):
149
(fname, flen) = t.split(':')
150
sign = False
151
if flen[0] == 's':
152
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
153
154
def parse_file(f, parent_pat):
155
"""Parse all of the patterns within a file"""
156
+ global re_arg_ident
157
+ global re_fld_ident
158
+ global re_fmt_ident
159
+ global re_pat_ident
160
161
# Read all of the lines of the file. Concatenate lines
162
# ending in backslash; discard empty lines and comments.
163
@@ -XXX,XX +XXX,XX @@ def parse_file(f, parent_pat):
164
continue
165
166
# Determine the type of object needing to be parsed.
167
- if name[0] == '%':
168
+ if re.fullmatch(re_fld_ident, name):
169
parse_field(start_lineno, name[1:], toks)
170
- elif name[0] == '&':
171
+ elif re.fullmatch(re_arg_ident, name):
172
parse_arguments(start_lineno, name[1:], toks)
173
- elif name[0] == '@':
174
+ elif re.fullmatch(re_fmt_ident, name):
175
parse_generic(start_lineno, None, name[1:], toks)
176
- else:
177
+ elif re.fullmatch(re_pat_ident, name):
178
parse_generic(start_lineno, parent_pat, name, toks)
179
+ else:
180
+ error(lineno, 'invalid token "{0}"'.format(name))
181
toks = []
182
183
if nesting != 0:
184
--
48
--
185
2.20.1
49
2.34.1
186
50
187
51
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
This just implements the bare minimum to cause the boot block to skip
3
NPCM7XX models have been commited after the conversion from
4
memory initialization.
4
commit 8063396bf3 ("Use OBJECT_DECLARE_SIMPLE_TYPE when possible").
5
5
Manually convert them.
6
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
6
7
Reviewed-by: Cédric Le Goater <clg@kaod.org>
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20230109140306.23161-11-philmd@linaro.org
10
Tested-by: Alexander Bulekov <alxndr@bu.edu>
11
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
12
Message-id: 20200911052101.2602693-10-hskinnemoen@google.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
11
---
15
include/hw/arm/npcm7xx.h | 2 +
12
include/hw/adc/npcm7xx_adc.h | 7 +++----
16
include/hw/mem/npcm7xx_mc.h | 36 ++++++++++++++++
13
include/hw/arm/npcm7xx.h | 18 ++++++------------
17
hw/arm/npcm7xx.c | 6 +++
14
include/hw/i2c/npcm7xx_smbus.h | 7 +++----
18
hw/mem/npcm7xx_mc.c | 84 +++++++++++++++++++++++++++++++++++++
15
include/hw/misc/npcm7xx_clk.h | 2 +-
19
hw/mem/meson.build | 1 +
16
include/hw/misc/npcm7xx_gcr.h | 6 +++---
20
5 files changed, 129 insertions(+)
17
include/hw/misc/npcm7xx_mft.h | 7 +++----
21
create mode 100644 include/hw/mem/npcm7xx_mc.h
18
include/hw/misc/npcm7xx_pwm.h | 3 +--
22
create mode 100644 hw/mem/npcm7xx_mc.c
19
include/hw/misc/npcm7xx_rng.h | 6 +++---
23
20
include/hw/net/npcm7xx_emc.h | 5 +----
21
include/hw/sd/npcm7xx_sdhci.h | 4 ++--
22
10 files changed, 26 insertions(+), 39 deletions(-)
23
24
diff --git a/include/hw/adc/npcm7xx_adc.h b/include/hw/adc/npcm7xx_adc.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/include/hw/adc/npcm7xx_adc.h
27
+++ b/include/hw/adc/npcm7xx_adc.h
28
@@ -XXX,XX +XXX,XX @@
29
* @iref: The internal reference voltage, initialized at launch time.
30
* @rv: The calibrated output values of 0.5V and 1.5V for the ADC.
31
*/
32
-typedef struct {
33
+struct NPCM7xxADCState {
34
SysBusDevice parent;
35
36
MemoryRegion iomem;
37
@@ -XXX,XX +XXX,XX @@ typedef struct {
38
uint32_t iref;
39
40
uint16_t calibration_r_values[NPCM7XX_ADC_NUM_CALIB];
41
-} NPCM7xxADCState;
42
+};
43
44
#define TYPE_NPCM7XX_ADC "npcm7xx-adc"
45
-#define NPCM7XX_ADC(obj) \
46
- OBJECT_CHECK(NPCM7xxADCState, (obj), TYPE_NPCM7XX_ADC)
47
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxADCState, NPCM7XX_ADC)
48
49
#endif /* NPCM7XX_ADC_H */
24
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
50
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
25
index XXXXXXX..XXXXXXX 100644
51
index XXXXXXX..XXXXXXX 100644
26
--- a/include/hw/arm/npcm7xx.h
52
--- a/include/hw/arm/npcm7xx.h
27
+++ b/include/hw/arm/npcm7xx.h
53
+++ b/include/hw/arm/npcm7xx.h
28
@@ -XXX,XX +XXX,XX @@
54
@@ -XXX,XX +XXX,XX @@
29
55
30
#include "hw/boards.h"
56
#define NPCM7XX_NR_PWM_MODULES 2
31
#include "hw/cpu/a9mpcore.h"
57
32
+#include "hw/mem/npcm7xx_mc.h"
58
-typedef struct NPCM7xxMachine {
33
#include "hw/misc/npcm7xx_clk.h"
59
+struct NPCM7xxMachine {
34
#include "hw/misc/npcm7xx_gcr.h"
60
MachineState parent;
35
#include "hw/nvram/npcm7xx_otp.h"
61
/*
62
* PWM fan splitter. each splitter connects to one PWM output and
63
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxMachine {
64
*/
65
SplitIRQ fan_splitter[NPCM7XX_NR_PWM_MODULES *
66
NPCM7XX_PWM_PER_MODULE];
67
-} NPCM7xxMachine;
68
+};
69
70
#define TYPE_NPCM7XX_MACHINE MACHINE_TYPE_NAME("npcm7xx")
71
-#define NPCM7XX_MACHINE(obj) \
72
- OBJECT_CHECK(NPCM7xxMachine, (obj), TYPE_NPCM7XX_MACHINE)
73
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxMachine, NPCM7XX_MACHINE)
74
75
typedef struct NPCM7xxMachineClass {
76
MachineClass parent;
77
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxMachineClass {
78
#define NPCM7XX_MACHINE_GET_CLASS(obj) \
79
OBJECT_GET_CLASS(NPCM7xxMachineClass, (obj), TYPE_NPCM7XX_MACHINE)
80
81
-typedef struct NPCM7xxState {
82
+struct NPCM7xxState {
83
DeviceState parent;
84
85
ARMCPU cpu[NPCM7XX_MAX_NUM_CPUS];
36
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
86
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
37
NPCM7xxTimerCtrlState tim[3];
87
NPCM7xxFIUState fiu[2];
38
NPCM7xxOTPState key_storage;
88
NPCM7xxEMCState emc[2];
39
NPCM7xxOTPState fuse_array;
89
NPCM7xxSDHCIState mmc;
40
+ NPCM7xxMCState mc;
90
-} NPCM7xxState;
41
} NPCM7xxState;
91
+};
42
92
43
#define TYPE_NPCM7XX "npcm7xx"
93
#define TYPE_NPCM7XX "npcm7xx"
44
diff --git a/include/hw/mem/npcm7xx_mc.h b/include/hw/mem/npcm7xx_mc.h
94
-#define NPCM7XX(obj) OBJECT_CHECK(NPCM7xxState, (obj), TYPE_NPCM7XX)
45
new file mode 100644
95
+OBJECT_DECLARE_TYPE(NPCM7xxState, NPCM7xxClass, NPCM7XX)
46
index XXXXXXX..XXXXXXX
96
47
--- /dev/null
97
#define TYPE_NPCM730 "npcm730"
48
+++ b/include/hw/mem/npcm7xx_mc.h
98
#define TYPE_NPCM750 "npcm750"
49
@@ -XXX,XX +XXX,XX @@
99
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxClass {
50
+/*
100
uint32_t num_cpus;
51
+ * Nuvoton NPCM7xx Memory Controller stub
101
} NPCM7xxClass;
52
+ *
102
53
+ * Copyright 2020 Google LLC
103
-#define NPCM7XX_CLASS(klass) \
54
+ *
104
- OBJECT_CLASS_CHECK(NPCM7xxClass, (klass), TYPE_NPCM7XX)
55
+ * This program is free software; you can redistribute it and/or modify it
105
-#define NPCM7XX_GET_CLASS(obj) \
56
+ * under the terms of the GNU General Public License as published by the
106
- OBJECT_GET_CLASS(NPCM7xxClass, (obj), TYPE_NPCM7XX)
57
+ * Free Software Foundation; either version 2 of the License, or
107
-
58
+ * (at your option) any later version.
108
/**
59
+ *
109
* npcm7xx_load_kernel - Loads memory with everything needed to boot
60
+ * This program is distributed in the hope that it will be useful, but WITHOUT
110
* @machine - The machine containing the SoC to be booted.
61
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
111
diff --git a/include/hw/i2c/npcm7xx_smbus.h b/include/hw/i2c/npcm7xx_smbus.h
62
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
112
index XXXXXXX..XXXXXXX 100644
63
+ * for more details.
113
--- a/include/hw/i2c/npcm7xx_smbus.h
64
+ */
114
+++ b/include/hw/i2c/npcm7xx_smbus.h
65
+#ifndef NPCM7XX_MC_H
115
@@ -XXX,XX +XXX,XX @@ typedef enum NPCM7xxSMBusStatus {
66
+#define NPCM7XX_MC_H
116
* @rx_cur: The current position of rx_fifo.
67
+
117
* @status: The current status of the SMBus.
68
+#include "exec/memory.h"
118
*/
69
+#include "hw/sysbus.h"
119
-typedef struct NPCM7xxSMBusState {
70
+
120
+struct NPCM7xxSMBusState {
71
+/**
121
SysBusDevice parent;
72
+ * struct NPCM7xxMCState - Device state for the memory controller.
122
73
+ * @parent: System bus device.
123
MemoryRegion iomem;
74
+ * @mmio: Memory region through which registers are accessed.
124
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxSMBusState {
75
+ */
125
uint8_t rx_cur;
76
+typedef struct NPCM7xxMCState {
126
77
+ SysBusDevice parent;
127
NPCM7xxSMBusStatus status;
78
+
128
-} NPCM7xxSMBusState;
79
+ MemoryRegion mmio;
129
+};
80
+} NPCM7xxMCState;
130
81
+
131
#define TYPE_NPCM7XX_SMBUS "npcm7xx-smbus"
82
+#define TYPE_NPCM7XX_MC "npcm7xx-mc"
132
-#define NPCM7XX_SMBUS(obj) OBJECT_CHECK(NPCM7xxSMBusState, (obj), \
83
+#define NPCM7XX_MC(obj) OBJECT_CHECK(NPCM7xxMCState, (obj), TYPE_NPCM7XX_MC)
133
- TYPE_NPCM7XX_SMBUS)
84
+
134
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxSMBusState, NPCM7XX_SMBUS)
85
+#endif /* NPCM7XX_MC_H */
135
86
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
136
#endif /* NPCM7XX_SMBUS_H */
87
index XXXXXXX..XXXXXXX 100644
137
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
88
--- a/hw/arm/npcm7xx.c
138
index XXXXXXX..XXXXXXX 100644
89
+++ b/hw/arm/npcm7xx.c
139
--- a/include/hw/misc/npcm7xx_clk.h
90
@@ -XXX,XX +XXX,XX @@
140
+++ b/include/hw/misc/npcm7xx_clk.h
91
#define NPCM7XX_CPUP_BA (0xf03fe000)
141
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxCLKState {
92
#define NPCM7XX_GCR_BA (0xf0800000)
142
};
93
#define NPCM7XX_CLK_BA (0xf0801000)
143
94
+#define NPCM7XX_MC_BA (0xf0824000)
144
#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
95
145
-#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK)
96
/* Internal AHB SRAM */
146
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxCLKState, NPCM7XX_CLK)
97
#define NPCM7XX_RAM3_BA (0xc0008000)
147
98
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
148
#endif /* NPCM7XX_CLK_H */
99
TYPE_NPCM7XX_KEY_STORAGE);
149
diff --git a/include/hw/misc/npcm7xx_gcr.h b/include/hw/misc/npcm7xx_gcr.h
100
object_initialize_child(obj, "otp2", &s->fuse_array,
150
index XXXXXXX..XXXXXXX 100644
101
TYPE_NPCM7XX_FUSE_ARRAY);
151
--- a/include/hw/misc/npcm7xx_gcr.h
102
+ object_initialize_child(obj, "mc", &s->mc, TYPE_NPCM7XX_MC);
152
+++ b/include/hw/misc/npcm7xx_gcr.h
103
153
@@ -XXX,XX +XXX,XX @@
104
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
154
*/
105
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
155
#define NPCM7XX_GCR_NR_REGS (0x148 / sizeof(uint32_t))
106
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
156
107
sysbus_mmio_map(SYS_BUS_DEVICE(&s->fuse_array), 0, NPCM7XX_OTP2_BA);
157
-typedef struct NPCM7xxGCRState {
108
npcm7xx_init_fuses(s);
158
+struct NPCM7xxGCRState {
109
159
SysBusDevice parent;
110
+ /* Fake Memory Controller (MC). Cannot fail. */
160
111
+ sysbus_realize(SYS_BUS_DEVICE(&s->mc), &error_abort);
161
MemoryRegion iomem;
112
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->mc), 0, NPCM7XX_MC_BA);
162
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxGCRState {
113
+
163
uint32_t reset_pwron;
114
/* Timer Modules (TIM). Cannot fail. */
164
uint32_t reset_mdlr;
115
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
165
uint32_t reset_intcr3;
116
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
166
-} NPCM7xxGCRState;
117
diff --git a/hw/mem/npcm7xx_mc.c b/hw/mem/npcm7xx_mc.c
167
+};
118
new file mode 100644
168
119
index XXXXXXX..XXXXXXX
169
#define TYPE_NPCM7XX_GCR "npcm7xx-gcr"
120
--- /dev/null
170
-#define NPCM7XX_GCR(obj) OBJECT_CHECK(NPCM7xxGCRState, (obj), TYPE_NPCM7XX_GCR)
121
+++ b/hw/mem/npcm7xx_mc.c
171
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxGCRState, NPCM7XX_GCR)
122
@@ -XXX,XX +XXX,XX @@
172
123
+/*
173
#endif /* NPCM7XX_GCR_H */
124
+ * Nuvoton NPCM7xx Memory Controller stub
174
diff --git a/include/hw/misc/npcm7xx_mft.h b/include/hw/misc/npcm7xx_mft.h
125
+ *
175
index XXXXXXX..XXXXXXX 100644
126
+ * Copyright 2020 Google LLC
176
--- a/include/hw/misc/npcm7xx_mft.h
127
+ *
177
+++ b/include/hw/misc/npcm7xx_mft.h
128
+ * This program is free software; you can redistribute it and/or modify it
178
@@ -XXX,XX +XXX,XX @@
129
+ * under the terms of the GNU General Public License as published by the
179
* @max_rpm: The maximum rpm for fans. Order: A0, B0, A1, B1.
130
+ * Free Software Foundation; either version 2 of the License, or
180
* @duty: The duty cycles for fans, relative to NPCM7XX_PWM_MAX_DUTY.
131
+ * (at your option) any later version.
181
*/
132
+ *
182
-typedef struct NPCM7xxMFTState {
133
+ * This program is distributed in the hope that it will be useful, but WITHOUT
183
+struct NPCM7xxMFTState {
134
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
184
SysBusDevice parent;
135
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
185
136
+ * for more details.
186
MemoryRegion iomem;
137
+ */
187
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxMFTState {
138
+
188
139
+#include "qemu/osdep.h"
189
uint32_t max_rpm[NPCM7XX_MFT_FANIN_COUNT];
140
+
190
uint32_t duty[NPCM7XX_MFT_FANIN_COUNT];
141
+#include "hw/mem/npcm7xx_mc.h"
191
-} NPCM7xxMFTState;
142
+#include "qapi/error.h"
192
+};
143
+#include "qemu/log.h"
193
144
+#include "qemu/module.h"
194
#define TYPE_NPCM7XX_MFT "npcm7xx-mft"
145
+#include "qemu/units.h"
195
-#define NPCM7XX_MFT(obj) \
146
+
196
- OBJECT_CHECK(NPCM7xxMFTState, (obj), TYPE_NPCM7XX_MFT)
147
+#define NPCM7XX_MC_REGS_SIZE (4 * KiB)
197
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxMFTState, NPCM7XX_MFT)
148
+
198
149
+static uint64_t npcm7xx_mc_read(void *opaque, hwaddr addr, unsigned int size)
199
#endif /* NPCM7XX_MFT_H */
150
+{
200
diff --git a/include/hw/misc/npcm7xx_pwm.h b/include/hw/misc/npcm7xx_pwm.h
151
+ /*
201
index XXXXXXX..XXXXXXX 100644
152
+ * If bits 8..11 @ offset 0 are not zero, the boot block thinks the memory
202
--- a/include/hw/misc/npcm7xx_pwm.h
153
+ * controller has already been initialized and will skip DDR training.
203
+++ b/include/hw/misc/npcm7xx_pwm.h
154
+ */
204
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxPWMState {
155
+ if (addr == 0) {
205
};
156
+ return 0x100;
206
157
+ }
207
#define TYPE_NPCM7XX_PWM "npcm7xx-pwm"
158
+
208
-#define NPCM7XX_PWM(obj) \
159
+ qemu_log_mask(LOG_UNIMP, "%s: mostly unimplemented\n", __func__);
209
- OBJECT_CHECK(NPCM7xxPWMState, (obj), TYPE_NPCM7XX_PWM)
160
+
210
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxPWMState, NPCM7XX_PWM)
161
+ return 0;
211
162
+}
212
#endif /* NPCM7XX_PWM_H */
163
+
213
diff --git a/include/hw/misc/npcm7xx_rng.h b/include/hw/misc/npcm7xx_rng.h
164
+static void npcm7xx_mc_write(void *opaque, hwaddr addr, uint64_t v,
214
index XXXXXXX..XXXXXXX 100644
165
+ unsigned int size)
215
--- a/include/hw/misc/npcm7xx_rng.h
166
+{
216
+++ b/include/hw/misc/npcm7xx_rng.h
167
+ qemu_log_mask(LOG_UNIMP, "%s: mostly unimplemented\n", __func__);
217
@@ -XXX,XX +XXX,XX @@
168
+}
218
169
+
219
#include "hw/sysbus.h"
170
+static const MemoryRegionOps npcm7xx_mc_ops = {
220
171
+ .read = npcm7xx_mc_read,
221
-typedef struct NPCM7xxRNGState {
172
+ .write = npcm7xx_mc_write,
222
+struct NPCM7xxRNGState {
173
+ .endianness = DEVICE_LITTLE_ENDIAN,
223
SysBusDevice parent;
174
+ .valid = {
224
175
+ .min_access_size = 4,
225
MemoryRegion iomem;
176
+ .max_access_size = 4,
226
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxRNGState {
177
+ .unaligned = false,
227
uint8_t rngcs;
178
+ },
228
uint8_t rngd;
179
+};
229
uint8_t rngmode;
180
+
230
-} NPCM7xxRNGState;
181
+static void npcm7xx_mc_realize(DeviceState *dev, Error **errp)
231
+};
182
+{
232
183
+ NPCM7xxMCState *s = NPCM7XX_MC(dev);
233
#define TYPE_NPCM7XX_RNG "npcm7xx-rng"
184
+
234
-#define NPCM7XX_RNG(obj) OBJECT_CHECK(NPCM7xxRNGState, (obj), TYPE_NPCM7XX_RNG)
185
+ memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_mc_ops, s, "regs",
235
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxRNGState, NPCM7XX_RNG)
186
+ NPCM7XX_MC_REGS_SIZE);
236
187
+ sysbus_init_mmio(&s->parent, &s->mmio);
237
#endif /* NPCM7XX_RNG_H */
188
+}
238
diff --git a/include/hw/net/npcm7xx_emc.h b/include/hw/net/npcm7xx_emc.h
189
+
239
index XXXXXXX..XXXXXXX 100644
190
+static void npcm7xx_mc_class_init(ObjectClass *klass, void *data)
240
--- a/include/hw/net/npcm7xx_emc.h
191
+{
241
+++ b/include/hw/net/npcm7xx_emc.h
192
+ DeviceClass *dc = DEVICE_CLASS(klass);
242
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxEMCState {
193
+
243
bool rx_active;
194
+ dc->desc = "NPCM7xx Memory Controller stub";
244
};
195
+ dc->realize = npcm7xx_mc_realize;
245
196
+}
246
-typedef struct NPCM7xxEMCState NPCM7xxEMCState;
197
+
247
-
198
+static const TypeInfo npcm7xx_mc_types[] = {
248
#define TYPE_NPCM7XX_EMC "npcm7xx-emc"
199
+ {
249
-#define NPCM7XX_EMC(obj) \
200
+ .name = TYPE_NPCM7XX_MC,
250
- OBJECT_CHECK(NPCM7xxEMCState, (obj), TYPE_NPCM7XX_EMC)
201
+ .parent = TYPE_SYS_BUS_DEVICE,
251
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxEMCState, NPCM7XX_EMC)
202
+ .instance_size = sizeof(NPCM7xxMCState),
252
203
+ .class_init = npcm7xx_mc_class_init,
253
#endif /* NPCM7XX_EMC_H */
204
+ },
254
diff --git a/include/hw/sd/npcm7xx_sdhci.h b/include/hw/sd/npcm7xx_sdhci.h
205
+};
255
index XXXXXXX..XXXXXXX 100644
206
+DEFINE_TYPES(npcm7xx_mc_types);
256
--- a/include/hw/sd/npcm7xx_sdhci.h
207
diff --git a/hw/mem/meson.build b/hw/mem/meson.build
257
+++ b/include/hw/sd/npcm7xx_sdhci.h
208
index XXXXXXX..XXXXXXX 100644
258
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxRegs {
209
--- a/hw/mem/meson.build
259
uint32_t boottoctrl;
210
+++ b/hw/mem/meson.build
260
} NPCM7xxRegisters;
211
@@ -XXX,XX +XXX,XX @@
261
212
mem_ss = ss.source_set()
262
-typedef struct NPCM7xxSDHCIState {
213
mem_ss.add(files('memory-device.c'))
263
+struct NPCM7xxSDHCIState {
214
mem_ss.add(when: 'CONFIG_DIMM', if_true: files('pc-dimm.c'))
264
SysBusDevice parent;
215
+mem_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_mc.c'))
265
216
mem_ss.add(when: 'CONFIG_NVDIMM', if_true: files('nvdimm.c'))
266
MemoryRegion container;
217
267
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxSDHCIState {
218
softmmu_ss.add_all(when: 'CONFIG_MEM_DEVICE', if_true: mem_ss)
268
NPCM7xxRegisters regs;
269
270
SDHCIState sdhci;
271
-} NPCM7xxSDHCIState;
272
+};
273
274
#endif /* NPCM7XX_SDHCI_H */
219
--
275
--
220
2.20.1
276
2.34.1
221
277
222
278
diff view generated by jsdifflib
1
Implement a model of the MPS2 with the AN386 firmware. This is
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
essentially identical to the AN385 firmware, but it has a
3
Cortex-M4 rather than a Cortex-M3.
4
2
3
The structure is named SECUREECState. Rename the type accordingly.
4
5
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20230109140306.23161-12-philmd@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
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: 20200903202048.15370-2-peter.maydell@linaro.org
9
---
9
---
10
docs/system/arm/mps2.rst | 8 +++++---
10
hw/misc/sbsa_ec.c | 13 +++++++------
11
hw/arm/mps2.c | 34 +++++++++++++++++++++++++++++-----
11
1 file changed, 7 insertions(+), 6 deletions(-)
12
2 files changed, 34 insertions(+), 8 deletions(-)
13
12
14
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
13
diff --git a/hw/misc/sbsa_ec.c b/hw/misc/sbsa_ec.c
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/docs/system/arm/mps2.rst
15
--- a/hw/misc/sbsa_ec.c
17
+++ b/docs/system/arm/mps2.rst
16
+++ b/hw/misc/sbsa_ec.c
18
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@
19
-Arm MPS2 boards (``mps2-an385``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
18
#include "hw/sysbus.h"
20
-================================================================================
19
#include "sysemu/runstate.h"
21
+Arm MPS2 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
20
22
+================================================================================================
21
-typedef struct {
23
22
+typedef struct SECUREECState {
24
These board models all use Arm M-profile CPUs.
23
SysBusDevice parent_obj;
25
24
MemoryRegion iomem;
26
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
25
} SECUREECState;
27
26
28
``mps2-an385``
27
-#define TYPE_SBSA_EC "sbsa-ec"
29
Cortex-M3 as documented in ARM Application Note AN385
28
-#define SECURE_EC(obj) OBJECT_CHECK(SECUREECState, (obj), TYPE_SBSA_EC)
30
+``mps2-an386``
29
+#define TYPE_SBSA_SECURE_EC "sbsa-ec"
31
+ Cortex-M4 as documented in ARM Application Note AN386
30
+#define SBSA_SECURE_EC(obj) \
32
``mps2-an511``
31
+ OBJECT_CHECK(SECUREECState, (obj), TYPE_SBSA_SECURE_EC)
33
Cortex-M3 'DesignStart' as documented in AN511
32
34
``mps2-an505``
33
enum sbsa_ec_powerstates {
35
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
34
SBSA_EC_CMD_POWEROFF = 0x01,
36
35
@@ -XXX,XX +XXX,XX @@ static uint64_t sbsa_ec_read(void *opaque, hwaddr offset, unsigned size)
37
Differences between QEMU and real hardware:
38
39
-- AN385 remapping of low 16K of memory to either ZBT SSRAM1 or to
40
+- AN385/AN386 remapping of low 16K of memory to either ZBT SSRAM1 or to
41
block RAM is unimplemented (QEMU always maps this to ZBT SSRAM1, as
42
if zbt_boot_ctrl is always zero)
43
- QEMU provides a LAN9118 ethernet rather than LAN9220; the only guest
44
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/arm/mps2.c
47
+++ b/hw/arm/mps2.c
48
@@ -XXX,XX +XXX,XX @@
49
* as seen by the guest depend significantly on the FPGA image.
50
* We model the following FPGA images:
51
* "mps2-an385" -- Cortex-M3 as documented in ARM Application Note AN385
52
+ * "mps2-an386" -- Cortex-M4 as documented in ARM Application Note AN386
53
* "mps2-an511" -- Cortex-M3 'DesignStart' as documented in AN511
54
*
55
* Links to the TRM for the board itself and to the various Application
56
@@ -XXX,XX +XXX,XX @@
57
58
typedef enum MPS2FPGAType {
59
FPGA_AN385,
60
+ FPGA_AN386,
61
FPGA_AN511,
62
} MPS2FPGAType;
63
64
@@ -XXX,XX +XXX,XX @@ typedef struct MPS2MachineState MPS2MachineState;
65
66
#define TYPE_MPS2_MACHINE "mps2"
67
#define TYPE_MPS2_AN385_MACHINE MACHINE_TYPE_NAME("mps2-an385")
68
+#define TYPE_MPS2_AN386_MACHINE MACHINE_TYPE_NAME("mps2-an386")
69
#define TYPE_MPS2_AN511_MACHINE MACHINE_TYPE_NAME("mps2-an511")
70
71
DECLARE_OBJ_CHECKERS(MPS2MachineState, MPS2MachineClass,
72
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
73
* tradeoffs. For QEMU they're all just RAM, though. We arbitrarily
74
* call the 16MB our "system memory", as it's the largest lump.
75
*
76
- * Common to both boards:
77
- * 0x21000000..0x21ffffff : PSRAM (16MB)
78
- * AN385 only:
79
+ * AN385/AN386/AN511:
80
+ * 0x21000000 .. 0x21ffffff : PSRAM (16MB)
81
+ * AN385/AN386 only:
82
* 0x00000000 .. 0x003fffff : ZBT SSRAM1
83
* 0x00400000 .. 0x007fffff : mirror of ZBT SSRAM1
84
* 0x20000000 .. 0x203fffff : ZBT SSRAM 2&3
85
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
86
* 0x20000000 .. 0x2001ffff : SRAM
87
* 0x20400000 .. 0x207fffff : ZBT SSRAM 2&3
88
*
89
- * The AN385 has a feature where the lowest 16K can be mapped
90
+ * The AN385/AN386 has a feature where the lowest 16K can be mapped
91
* either to the bottom of the ZBT SSRAM1 or to the block RAM.
92
* This is of no use for QEMU so we don't implement it (as if
93
* zbt_boot_ctrl is always zero).
94
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
95
96
switch (mmc->fpga_type) {
97
case FPGA_AN385:
98
+ case FPGA_AN386:
99
make_ram(&mms->ssram1, "mps.ssram1", 0x0, 0x400000);
100
make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x400000);
101
make_ram(&mms->ssram23, "mps.ssram23", 0x20000000, 0x400000);
102
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
103
armv7m = DEVICE(&mms->armv7m);
104
switch (mmc->fpga_type) {
105
case FPGA_AN385:
106
+ case FPGA_AN386:
107
qdev_prop_set_uint32(armv7m, "num-irq", 32);
108
break;
109
case FPGA_AN511:
110
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
111
112
switch (mmc->fpga_type) {
113
case FPGA_AN385:
114
+ case FPGA_AN386:
115
{
116
/* The overflow IRQs for UARTs 0, 1 and 2 are ORed together.
117
* Overflow for UARTs 4 and 5 doesn't trigger any interrupt.
118
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
119
*/
120
lan9118_init(&nd_table[0], 0x40200000,
121
qdev_get_gpio_in(armv7m,
122
- mmc->fpga_type == FPGA_AN385 ? 13 : 47));
123
+ mmc->fpga_type == FPGA_AN511 ? 47 : 13));
124
125
system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
126
127
@@ -XXX,XX +XXX,XX @@ static void mps2_an385_class_init(ObjectClass *oc, void *data)
128
mmc->scc_id = 0x41043850;
129
}
36
}
130
37
131
+static void mps2_an386_class_init(ObjectClass *oc, void *data)
38
static void sbsa_ec_write(void *opaque, hwaddr offset,
132
+{
39
- uint64_t value, unsigned size)
133
+ MachineClass *mc = MACHINE_CLASS(oc);
40
+ uint64_t value, unsigned size)
134
+ MPS2MachineClass *mmc = MPS2_MACHINE_CLASS(oc);
135
+
136
+ mc->desc = "ARM MPS2 with AN386 FPGA image for Cortex-M4";
137
+ mmc->fpga_type = FPGA_AN386;
138
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m4");
139
+ mmc->scc_id = 0x41043860;
140
+}
141
+
142
static void mps2_an511_class_init(ObjectClass *oc, void *data)
143
{
41
{
144
MachineClass *mc = MACHINE_CLASS(oc);
42
if (offset == 0) { /* PSCI machine power command register */
145
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mps2_an385_info = {
43
switch (value) {
146
.class_init = mps2_an385_class_init,
44
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps sbsa_ec_ops = {
147
};
45
148
46
static void sbsa_ec_init(Object *obj)
149
+static const TypeInfo mps2_an386_info = {
150
+ .name = TYPE_MPS2_AN386_MACHINE,
151
+ .parent = TYPE_MPS2_MACHINE,
152
+ .class_init = mps2_an386_class_init,
153
+};
154
+
155
static const TypeInfo mps2_an511_info = {
156
.name = TYPE_MPS2_AN511_MACHINE,
157
.parent = TYPE_MPS2_MACHINE,
158
@@ -XXX,XX +XXX,XX @@ static void mps2_machine_init(void)
159
{
47
{
160
type_register_static(&mps2_info);
48
- SECUREECState *s = SECURE_EC(obj);
161
type_register_static(&mps2_an385_info);
49
+ SECUREECState *s = SBSA_SECURE_EC(obj);
162
+ type_register_static(&mps2_an386_info);
50
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
163
type_register_static(&mps2_an511_info);
51
52
memory_region_init_io(&s->iomem, obj, &sbsa_ec_ops, s, "sbsa-ec",
53
@@ -XXX,XX +XXX,XX @@ static void sbsa_ec_class_init(ObjectClass *klass, void *data)
164
}
54
}
165
55
56
static const TypeInfo sbsa_ec_info = {
57
- .name = TYPE_SBSA_EC,
58
+ .name = TYPE_SBSA_SECURE_EC,
59
.parent = TYPE_SYS_BUS_DEVICE,
60
.instance_size = sizeof(SECUREECState),
61
.instance_init = sbsa_ec_init,
166
--
62
--
167
2.20.1
63
2.34.1
168
64
169
65
diff view generated by jsdifflib
1
It is the responsibility of board code for an armv7m system to set
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
system_clock_scale appropriately for the CPU speed of the core.
3
If it forgets to do this, then QEMU will hang if the guest tries
4
to use the systick timer in the "tick at the CPU clock frequency" mode.
5
2
6
We forgot that in a couple of our boards (see commits ce4f70e81ed23c93f,
3
This model was merged few days before the QOM cleanup from
7
e7e5a9595ab1136). Add an assertion in the systick reset method so
4
commit 8063396bf3 ("Use OBJECT_DECLARE_SIMPLE_TYPE when possible")
8
we don't let any new boards in with the same bug.
5
was pulled and merged. Manually adapt.
9
6
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230109140306.23161-13-philmd@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Message-id: 20200825160847.18091-1-peter.maydell@linaro.org
13
---
11
---
14
hw/timer/armv7m_systick.c | 8 ++++++++
12
hw/misc/sbsa_ec.c | 3 +--
15
1 file changed, 8 insertions(+)
13
1 file changed, 1 insertion(+), 2 deletions(-)
16
14
17
diff --git a/hw/timer/armv7m_systick.c b/hw/timer/armv7m_systick.c
15
diff --git a/hw/misc/sbsa_ec.c b/hw/misc/sbsa_ec.c
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/timer/armv7m_systick.c
17
--- a/hw/misc/sbsa_ec.c
20
+++ b/hw/timer/armv7m_systick.c
18
+++ b/hw/misc/sbsa_ec.c
21
@@ -XXX,XX +XXX,XX @@ static void systick_reset(DeviceState *dev)
19
@@ -XXX,XX +XXX,XX @@ typedef struct SECUREECState {
22
{
20
} SECUREECState;
23
SysTickState *s = SYSTICK(dev);
21
24
22
#define TYPE_SBSA_SECURE_EC "sbsa-ec"
25
+ /*
23
-#define SBSA_SECURE_EC(obj) \
26
+ * Forgetting to set system_clock_scale is always a board code
24
- OBJECT_CHECK(SECUREECState, (obj), TYPE_SBSA_SECURE_EC)
27
+ * bug. We can't check this earlier because for some boards
25
+OBJECT_DECLARE_SIMPLE_TYPE(SECUREECState, SBSA_SECURE_EC)
28
+ * (like stellaris) it is not yet configured at the point where
26
29
+ * the systick device is realized.
27
enum sbsa_ec_powerstates {
30
+ */
28
SBSA_EC_CMD_POWEROFF = 0x01,
31
+ assert(system_clock_scale != 0);
32
+
33
s->control = 0;
34
s->reload = 0;
35
s->tick = 0;
36
--
29
--
37
2.20.1
30
2.34.1
38
31
39
32
diff view generated by jsdifflib
1
Implement a model of the MPS2 with the AN500 firmware. This is
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
similar to the AN385, with the following differences:
3
* Cortex-M7 CPU
4
* PSRAM is at 0x6000_0000
5
* Ethernet is at 0xa000_0000
6
* No zbt_boot_ctrl remapping of the low 16K
7
(but QEMU doesn't implement this anyway)
8
* no "block RAM" at 0x01000000
9
2
3
This remove a use of 'struct' in the DECLARE_INSTANCE_CHECKER()
4
macro call, to avoid after a QOM refactor:
5
6
hw/intc/xilinx_intc.c:45:1: error: declaration of anonymous struct must be a definition
7
DECLARE_INSTANCE_CHECKER(struct xlx_pic, XILINX_INTC,
8
^
9
10
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Edgar E. Iglesias <edgar@zeroasic.com>
13
Message-id: 20230109140306.23161-14-philmd@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Message-id: 20200903202048.15370-3-peter.maydell@linaro.org
13
---
15
---
14
docs/system/arm/mps2.rst | 6 ++--
16
hw/intc/xilinx_intc.c | 28 +++++++++++++---------------
15
hw/arm/mps2.c | 67 +++++++++++++++++++++++++++++++++-------
17
1 file changed, 13 insertions(+), 15 deletions(-)
16
2 files changed, 60 insertions(+), 13 deletions(-)
17
18
18
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
19
diff --git a/hw/intc/xilinx_intc.c b/hw/intc/xilinx_intc.c
19
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
20
--- a/docs/system/arm/mps2.rst
21
--- a/hw/intc/xilinx_intc.c
21
+++ b/docs/system/arm/mps2.rst
22
+++ b/hw/intc/xilinx_intc.c
22
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
23
-Arm MPS2 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
24
#define R_MAX 8
24
-================================================================================================
25
25
+Arm MPS2 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
26
#define TYPE_XILINX_INTC "xlnx.xps-intc"
26
+================================================================================================================
27
-DECLARE_INSTANCE_CHECKER(struct xlx_pic, XILINX_INTC,
27
28
- TYPE_XILINX_INTC)
28
These board models all use Arm M-profile CPUs.
29
+typedef struct XpsIntc XpsIntc;
29
30
+DECLARE_INSTANCE_CHECKER(XpsIntc, XILINX_INTC, TYPE_XILINX_INTC)
30
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
31
31
Cortex-M3 as documented in ARM Application Note AN385
32
-struct xlx_pic
32
``mps2-an386``
33
+struct XpsIntc
33
Cortex-M4 as documented in ARM Application Note AN386
34
{
34
+``mps2-an500``
35
SysBusDevice parent_obj;
35
+ Cortex-M7 as documented in ARM Application Note AN500
36
36
``mps2-an511``
37
@@ -XXX,XX +XXX,XX @@ struct xlx_pic
37
Cortex-M3 'DesignStart' as documented in AN511
38
uint32_t irq_pin_state;
38
``mps2-an505``
39
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/arm/mps2.c
42
+++ b/hw/arm/mps2.c
43
@@ -XXX,XX +XXX,XX @@
44
* We model the following FPGA images:
45
* "mps2-an385" -- Cortex-M3 as documented in ARM Application Note AN385
46
* "mps2-an386" -- Cortex-M4 as documented in ARM Application Note AN386
47
+ * "mps2-an500" -- Cortex-M7 as documented in ARM Application Note AN500
48
* "mps2-an511" -- Cortex-M3 'DesignStart' as documented in AN511
49
*
50
* Links to the TRM for the board itself and to the various Application
51
@@ -XXX,XX +XXX,XX @@
52
typedef enum MPS2FPGAType {
53
FPGA_AN385,
54
FPGA_AN386,
55
+ FPGA_AN500,
56
FPGA_AN511,
57
} MPS2FPGAType;
58
59
@@ -XXX,XX +XXX,XX @@ struct MPS2MachineClass {
60
MachineClass parent;
61
MPS2FPGAType fpga_type;
62
uint32_t scc_id;
63
+ bool has_block_ram;
64
+ hwaddr ethernet_base;
65
+ hwaddr psram_base;
66
};
39
};
67
typedef struct MPS2MachineClass MPS2MachineClass;
40
68
41
-static void update_irq(struct xlx_pic *p)
69
@@ -XXX,XX +XXX,XX @@ typedef struct MPS2MachineState MPS2MachineState;
42
+static void update_irq(XpsIntc *p)
70
#define TYPE_MPS2_MACHINE "mps2"
43
{
71
#define TYPE_MPS2_AN385_MACHINE MACHINE_TYPE_NAME("mps2-an385")
44
uint32_t i;
72
#define TYPE_MPS2_AN386_MACHINE MACHINE_TYPE_NAME("mps2-an386")
45
73
+#define TYPE_MPS2_AN500_MACHINE MACHINE_TYPE_NAME("mps2-an500")
46
@@ -XXX,XX +XXX,XX @@ static void update_irq(struct xlx_pic *p)
74
#define TYPE_MPS2_AN511_MACHINE MACHINE_TYPE_NAME("mps2-an511")
47
qemu_set_irq(p->parent_irq, (p->regs[R_MER] & 1) && p->regs[R_IPR]);
75
76
DECLARE_OBJ_CHECKERS(MPS2MachineState, MPS2MachineClass,
77
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
78
*
79
* AN385/AN386/AN511:
80
* 0x21000000 .. 0x21ffffff : PSRAM (16MB)
81
- * AN385/AN386 only:
82
+ * AN385/AN386/AN500:
83
* 0x00000000 .. 0x003fffff : ZBT SSRAM1
84
* 0x00400000 .. 0x007fffff : mirror of ZBT SSRAM1
85
* 0x20000000 .. 0x203fffff : ZBT SSRAM 2&3
86
* 0x20400000 .. 0x207fffff : mirror of ZBT SSRAM 2&3
87
+ * AN385/AN386 only:
88
* 0x01000000 .. 0x01003fff : block RAM (16K)
89
* 0x01004000 .. 0x01007fff : mirror of above
90
* 0x01008000 .. 0x0100bfff : mirror of above
91
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
92
* 0x00400000 .. 0x007fffff : ZBT SSRAM1
93
* 0x20000000 .. 0x2001ffff : SRAM
94
* 0x20400000 .. 0x207fffff : ZBT SSRAM 2&3
95
+ * AN500 only:
96
+ * 0x60000000 .. 0x60ffffff : PSRAM (16MB)
97
*
98
* The AN385/AN386 has a feature where the lowest 16K can be mapped
99
* either to the bottom of the ZBT SSRAM1 or to the block RAM.
100
* This is of no use for QEMU so we don't implement it (as if
101
* zbt_boot_ctrl is always zero).
102
*/
103
- memory_region_add_subregion(system_memory, 0x21000000, machine->ram);
104
+ memory_region_add_subregion(system_memory, mmc->psram_base, machine->ram);
105
106
- switch (mmc->fpga_type) {
107
- case FPGA_AN385:
108
- case FPGA_AN386:
109
- make_ram(&mms->ssram1, "mps.ssram1", 0x0, 0x400000);
110
- make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x400000);
111
- make_ram(&mms->ssram23, "mps.ssram23", 0x20000000, 0x400000);
112
- make_ram_alias(&mms->ssram23_m, "mps.ssram23_m",
113
- &mms->ssram23, 0x20400000);
114
+ if (mmc->has_block_ram) {
115
make_ram(&mms->blockram, "mps.blockram", 0x01000000, 0x4000);
116
make_ram_alias(&mms->blockram_m1, "mps.blockram_m1",
117
&mms->blockram, 0x01004000);
118
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
119
&mms->blockram, 0x01008000);
120
make_ram_alias(&mms->blockram_m3, "mps.blockram_m3",
121
&mms->blockram, 0x0100c000);
122
+ }
123
+
124
+ switch (mmc->fpga_type) {
125
+ case FPGA_AN385:
126
+ case FPGA_AN386:
127
+ case FPGA_AN500:
128
+ make_ram(&mms->ssram1, "mps.ssram1", 0x0, 0x400000);
129
+ make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x400000);
130
+ make_ram(&mms->ssram23, "mps.ssram23", 0x20000000, 0x400000);
131
+ make_ram_alias(&mms->ssram23_m, "mps.ssram23_m",
132
+ &mms->ssram23, 0x20400000);
133
break;
134
case FPGA_AN511:
135
make_ram(&mms->blockram, "mps.blockram", 0x0, 0x40000);
136
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
137
switch (mmc->fpga_type) {
138
case FPGA_AN385:
139
case FPGA_AN386:
140
+ case FPGA_AN500:
141
qdev_prop_set_uint32(armv7m, "num-irq", 32);
142
break;
143
case FPGA_AN511:
144
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
145
switch (mmc->fpga_type) {
146
case FPGA_AN385:
147
case FPGA_AN386:
148
+ case FPGA_AN500:
149
{
150
/* The overflow IRQs for UARTs 0, 1 and 2 are ORed together.
151
* Overflow for UARTs 4 and 5 doesn't trigger any interrupt.
152
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
153
/* In hardware this is a LAN9220; the LAN9118 is software compatible
154
* except that it doesn't support the checksum-offload feature.
155
*/
156
- lan9118_init(&nd_table[0], 0x40200000,
157
+ lan9118_init(&nd_table[0], mmc->ethernet_base,
158
qdev_get_gpio_in(armv7m,
159
mmc->fpga_type == FPGA_AN511 ? 47 : 13));
160
161
@@ -XXX,XX +XXX,XX @@ static void mps2_an385_class_init(ObjectClass *oc, void *data)
162
mmc->fpga_type = FPGA_AN385;
163
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m3");
164
mmc->scc_id = 0x41043850;
165
+ mmc->psram_base = 0x21000000;
166
+ mmc->ethernet_base = 0x40200000;
167
+ mmc->has_block_ram = true;
168
}
48
}
169
49
170
static void mps2_an386_class_init(ObjectClass *oc, void *data)
50
-static uint64_t
171
@@ -XXX,XX +XXX,XX @@ static void mps2_an386_class_init(ObjectClass *oc, void *data)
51
-pic_read(void *opaque, hwaddr addr, unsigned int size)
172
mmc->fpga_type = FPGA_AN386;
52
+static uint64_t pic_read(void *opaque, hwaddr addr, unsigned int size)
173
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m4");
53
{
174
mmc->scc_id = 0x41043860;
54
- struct xlx_pic *p = opaque;
175
+ mmc->psram_base = 0x21000000;
55
+ XpsIntc *p = opaque;
176
+ mmc->ethernet_base = 0x40200000;
56
uint32_t r = 0;
177
+ mmc->has_block_ram = true;
57
178
+}
58
addr >>= 2;
179
+
59
@@ -XXX,XX +XXX,XX @@ pic_read(void *opaque, hwaddr addr, unsigned int size)
180
+static void mps2_an500_class_init(ObjectClass *oc, void *data)
60
return r;
181
+{
182
+ MachineClass *mc = MACHINE_CLASS(oc);
183
+ MPS2MachineClass *mmc = MPS2_MACHINE_CLASS(oc);
184
+
185
+ mc->desc = "ARM MPS2 with AN500 FPGA image for Cortex-M7";
186
+ mmc->fpga_type = FPGA_AN500;
187
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m7");
188
+ mmc->scc_id = 0x41045000;
189
+ mmc->psram_base = 0x60000000;
190
+ mmc->ethernet_base = 0xa0000000;
191
+ mmc->has_block_ram = false;
192
}
61
}
193
62
194
static void mps2_an511_class_init(ObjectClass *oc, void *data)
63
-static void
195
@@ -XXX,XX +XXX,XX @@ static void mps2_an511_class_init(ObjectClass *oc, void *data)
64
-pic_write(void *opaque, hwaddr addr,
196
mmc->fpga_type = FPGA_AN511;
65
- uint64_t val64, unsigned int size)
197
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m3");
66
+static void pic_write(void *opaque, hwaddr addr,
198
mmc->scc_id = 0x41045110;
67
+ uint64_t val64, unsigned int size)
199
+ mmc->psram_base = 0x21000000;
68
{
200
+ mmc->ethernet_base = 0x40200000;
69
- struct xlx_pic *p = opaque;
201
+ mmc->has_block_ram = false;
70
+ XpsIntc *p = opaque;
71
uint32_t value = val64;
72
73
addr >>= 2;
74
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps pic_ops = {
75
76
static void irq_handler(void *opaque, int irq, int level)
77
{
78
- struct xlx_pic *p = opaque;
79
+ XpsIntc *p = opaque;
80
81
/* edge triggered interrupt */
82
if (p->c_kind_of_intr & (1 << irq) && p->regs[R_MER] & 2) {
83
@@ -XXX,XX +XXX,XX @@ static void irq_handler(void *opaque, int irq, int level)
84
85
static void xilinx_intc_init(Object *obj)
86
{
87
- struct xlx_pic *p = XILINX_INTC(obj);
88
+ XpsIntc *p = XILINX_INTC(obj);
89
90
qdev_init_gpio_in(DEVICE(obj), irq_handler, 32);
91
sysbus_init_irq(SYS_BUS_DEVICE(obj), &p->parent_irq);
92
@@ -XXX,XX +XXX,XX @@ static void xilinx_intc_init(Object *obj)
202
}
93
}
203
94
204
static const TypeInfo mps2_info = {
95
static Property xilinx_intc_properties[] = {
205
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mps2_an386_info = {
96
- DEFINE_PROP_UINT32("kind-of-intr", struct xlx_pic, c_kind_of_intr, 0),
206
.class_init = mps2_an386_class_init,
97
+ DEFINE_PROP_UINT32("kind-of-intr", XpsIntc, c_kind_of_intr, 0),
98
DEFINE_PROP_END_OF_LIST(),
207
};
99
};
208
100
209
+static const TypeInfo mps2_an500_info = {
101
@@ -XXX,XX +XXX,XX @@ static void xilinx_intc_class_init(ObjectClass *klass, void *data)
210
+ .name = TYPE_MPS2_AN500_MACHINE,
102
static const TypeInfo xilinx_intc_info = {
211
+ .parent = TYPE_MPS2_MACHINE,
103
.name = TYPE_XILINX_INTC,
212
+ .class_init = mps2_an500_class_init,
104
.parent = TYPE_SYS_BUS_DEVICE,
213
+};
105
- .instance_size = sizeof(struct xlx_pic),
214
+
106
+ .instance_size = sizeof(XpsIntc),
215
static const TypeInfo mps2_an511_info = {
107
.instance_init = xilinx_intc_init,
216
.name = TYPE_MPS2_AN511_MACHINE,
108
.class_init = xilinx_intc_class_init,
217
.parent = TYPE_MPS2_MACHINE,
109
};
218
@@ -XXX,XX +XXX,XX @@ static void mps2_machine_init(void)
219
type_register_static(&mps2_info);
220
type_register_static(&mps2_an385_info);
221
type_register_static(&mps2_an386_info);
222
+ type_register_static(&mps2_an500_info);
223
type_register_static(&mps2_an511_info);
224
}
225
226
--
110
--
227
2.20.1
111
2.34.1
228
112
229
113
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
When booting directly into a kernel, bypassing the boot loader, the CPU and
3
This remove a use of 'struct' in the DECLARE_INSTANCE_CHECKER()
4
UART clocks are not set up correctly. This makes the system appear very
4
macro call, to avoid after a QOM refactor:
5
slow, and causes the initrd boot test to fail when optimization is off.
6
5
7
The UART clock must run at 24 MHz. The default 25 MHz reference clock
6
hw/timer/xilinx_timer.c:65:1: error: declaration of anonymous struct must be a definition
8
cannot achieve this, so switch to PLL2/2 @ 480 MHz, which works
7
DECLARE_INSTANCE_CHECKER(struct timerblock, XILINX_TIMER,
9
perfectly with the default /20 divider.
8
^
10
9
11
The CPU clock should run at 800 MHz, so switch it to PLL1/2. PLL1 runs
10
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
at 800 MHz by default, so we need to double the feedback divider as well
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
to make it run at 1600 MHz (so PLL1/2 runs at 800 MHz).
12
Reviewed-by: Edgar E. Iglesias <edgar@zeroasic.com>
14
13
Message-id: 20230109140306.23161-15-philmd@linaro.org
15
We don't bother checking for PLL lock because we know our emulated PLLs
16
lock instantly.
17
18
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
21
Message-id: 20200911052101.2602693-13-hskinnemoen@google.com
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
15
---
24
include/hw/arm/npcm7xx.h | 1 +
16
hw/timer/xilinx_timer.c | 27 +++++++++++++--------------
25
hw/arm/npcm7xx.c | 32 ++++++++++++++++++++++++++++++++
17
1 file changed, 13 insertions(+), 14 deletions(-)
26
2 files changed, 33 insertions(+)
27
18
28
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
19
diff --git a/hw/timer/xilinx_timer.c b/hw/timer/xilinx_timer.c
29
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
30
--- a/include/hw/arm/npcm7xx.h
21
--- a/hw/timer/xilinx_timer.c
31
+++ b/include/hw/arm/npcm7xx.h
22
+++ b/hw/timer/xilinx_timer.c
32
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ struct xlx_timer
33
#define NPCM7XX_SMP_LOADER_START (0xffff0000) /* Boot ROM */
34
#define NPCM7XX_SMP_BOOTREG_ADDR (0xf080013c) /* GCR.SCRPAD */
35
#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100) /* GIC within A9 */
36
+#define NPCM7XX_BOARD_SETUP_ADDR (0xffff1000) /* Boot ROM */
37
38
typedef struct NPCM7xxMachine {
39
MachineState parent;
40
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/arm/npcm7xx.c
43
+++ b/hw/arm/npcm7xx.c
44
@@ -XXX,XX +XXX,XX @@
45
#define NPCM7XX_ROM_BA (0xffff0000)
46
#define NPCM7XX_ROM_SZ (64 * KiB)
47
48
+/* Clock configuration values to be fixed up when bypassing bootloader */
49
+
50
+/* Run PLL1 at 1600 MHz */
51
+#define NPCM7XX_PLLCON1_FIXUP_VAL (0x00402101)
52
+/* Run the CPU from PLL1 and UART from PLL2 */
53
+#define NPCM7XX_CLKSEL_FIXUP_VAL (0x004aaba9)
54
+
55
/*
56
* Interrupt lines going into the GIC. This does not include internal Cortex-A9
57
* interrupts.
58
@@ -XXX,XX +XXX,XX @@ static const struct {
59
},
60
};
24
};
61
25
62
+static void npcm7xx_write_board_setup(ARMCPU *cpu,
26
#define TYPE_XILINX_TIMER "xlnx.xps-timer"
63
+ const struct arm_boot_info *info)
27
-DECLARE_INSTANCE_CHECKER(struct timerblock, XILINX_TIMER,
64
+{
28
- TYPE_XILINX_TIMER)
65
+ uint32_t board_setup[] = {
29
+typedef struct XpsTimerState XpsTimerState;
66
+ 0xe59f0010, /* ldr r0, clk_base_addr */
30
+DECLARE_INSTANCE_CHECKER(XpsTimerState, XILINX_TIMER, TYPE_XILINX_TIMER)
67
+ 0xe59f1010, /* ldr r1, pllcon1_value */
31
68
+ 0xe5801010, /* str r1, [r0, #16] */
32
-struct timerblock
69
+ 0xe59f100c, /* ldr r1, clksel_value */
33
+struct XpsTimerState
70
+ 0xe5801004, /* str r1, [r0, #4] */
71
+ 0xe12fff1e, /* bx lr */
72
+ NPCM7XX_CLK_BA,
73
+ NPCM7XX_PLLCON1_FIXUP_VAL,
74
+ NPCM7XX_CLKSEL_FIXUP_VAL,
75
+ };
76
+ int i;
77
+
78
+ for (i = 0; i < ARRAY_SIZE(board_setup); i++) {
79
+ board_setup[i] = tswap32(board_setup[i]);
80
+ }
81
+ rom_add_blob_fixed("board-setup", board_setup, sizeof(board_setup),
82
+ info->board_setup_addr);
83
+}
84
+
85
static void npcm7xx_write_secondary_boot(ARMCPU *cpu,
86
const struct arm_boot_info *info)
87
{
34
{
88
@@ -XXX,XX +XXX,XX @@ static struct arm_boot_info npcm7xx_binfo = {
35
SysBusDevice parent_obj;
89
.gic_cpu_if_addr = NPCM7XX_GIC_CPU_IF_ADDR,
36
90
.write_secondary_boot = npcm7xx_write_secondary_boot,
37
@@ -XXX,XX +XXX,XX @@ struct timerblock
91
.board_id = -1,
38
struct xlx_timer *timers;
92
+ .board_setup_addr = NPCM7XX_BOARD_SETUP_ADDR,
93
+ .write_board_setup = npcm7xx_write_board_setup,
94
};
39
};
95
40
96
void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
41
-static inline unsigned int num_timers(struct timerblock *t)
42
+static inline unsigned int num_timers(XpsTimerState *t)
43
{
44
return 2 - t->one_timer_only;
45
}
46
@@ -XXX,XX +XXX,XX @@ static inline unsigned int timer_from_addr(hwaddr addr)
47
return addr >> 2;
48
}
49
50
-static void timer_update_irq(struct timerblock *t)
51
+static void timer_update_irq(XpsTimerState *t)
52
{
53
unsigned int i, irq = 0;
54
uint32_t csr;
55
@@ -XXX,XX +XXX,XX @@ static void timer_update_irq(struct timerblock *t)
56
static uint64_t
57
timer_read(void *opaque, hwaddr addr, unsigned int size)
58
{
59
- struct timerblock *t = opaque;
60
+ XpsTimerState *t = opaque;
61
struct xlx_timer *xt;
62
uint32_t r = 0;
63
unsigned int timer;
64
@@ -XXX,XX +XXX,XX @@ static void
65
timer_write(void *opaque, hwaddr addr,
66
uint64_t val64, unsigned int size)
67
{
68
- struct timerblock *t = opaque;
69
+ XpsTimerState *t = opaque;
70
struct xlx_timer *xt;
71
unsigned int timer;
72
uint32_t value = val64;
73
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps timer_ops = {
74
static void timer_hit(void *opaque)
75
{
76
struct xlx_timer *xt = opaque;
77
- struct timerblock *t = xt->parent;
78
+ XpsTimerState *t = xt->parent;
79
D(fprintf(stderr, "%s %d\n", __func__, xt->nr));
80
xt->regs[R_TCSR] |= TCSR_TINT;
81
82
@@ -XXX,XX +XXX,XX @@ static void timer_hit(void *opaque)
83
84
static void xilinx_timer_realize(DeviceState *dev, Error **errp)
85
{
86
- struct timerblock *t = XILINX_TIMER(dev);
87
+ XpsTimerState *t = XILINX_TIMER(dev);
88
unsigned int i;
89
90
/* Init all the ptimers. */
91
@@ -XXX,XX +XXX,XX @@ static void xilinx_timer_realize(DeviceState *dev, Error **errp)
92
93
static void xilinx_timer_init(Object *obj)
94
{
95
- struct timerblock *t = XILINX_TIMER(obj);
96
+ XpsTimerState *t = XILINX_TIMER(obj);
97
98
/* All timers share a single irq line. */
99
sysbus_init_irq(SYS_BUS_DEVICE(obj), &t->irq);
100
}
101
102
static Property xilinx_timer_properties[] = {
103
- DEFINE_PROP_UINT32("clock-frequency", struct timerblock, freq_hz,
104
- 62 * 1000000),
105
- DEFINE_PROP_UINT8("one-timer-only", struct timerblock, one_timer_only, 0),
106
+ DEFINE_PROP_UINT32("clock-frequency", XpsTimerState, freq_hz, 62 * 1000000),
107
+ DEFINE_PROP_UINT8("one-timer-only", XpsTimerState, one_timer_only, 0),
108
DEFINE_PROP_END_OF_LIST(),
109
};
110
111
@@ -XXX,XX +XXX,XX @@ static void xilinx_timer_class_init(ObjectClass *klass, void *data)
112
static const TypeInfo xilinx_timer_info = {
113
.name = TYPE_XILINX_TIMER,
114
.parent = TYPE_SYS_BUS_DEVICE,
115
- .instance_size = sizeof(struct timerblock),
116
+ .instance_size = sizeof(XpsTimerState),
117
.instance_init = xilinx_timer_init,
118
.class_init = xilinx_timer_class_init,
119
};
97
--
120
--
98
2.20.1
121
2.34.1
99
122
100
123
diff view generated by jsdifflib
1
From: Aaron Lindsay <aaron@os.amperecomputing.com>
1
From: Evgeny Iakovlev <eiakovlev@linux.microsoft.com>
2
2
3
This check was backwards when introduced in commit
3
ARM trusted firmware, when built with FEAT_HCX support, sets SCR_EL3.HXEn bit
4
033614c47de78409ad3fb39bb7bd1483b71c6789:
4
to allow EL2 to modify HCRX_EL2 register without trapping it in EL3. Qemu
5
5
uses a valid mask to clear unsupported SCR_EL3 bits when emulating SCR_EL3
6
target/arm: Filter cycle counter based on PMCCFILTR_EL0
6
write, and that mask doesn't include SCR_EL3.HXEn bit even if FEAT_HCX is
7
enabled and exposed to the guest. As a result EL3 writes of that bit are
8
ignored.
7
9
8
Cc: qemu-stable@nongnu.org
10
Cc: qemu-stable@nongnu.org
9
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
11
Signed-off-by: Evgeny Iakovlev <eiakovlev@linux.microsoft.com>
12
Message-id: 20230105221251.17896-4-eiakovlev@linux.microsoft.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
15
---
13
target/arm/helper.c | 2 +-
16
target/arm/helper.c | 3 +++
14
1 file changed, 1 insertion(+), 1 deletion(-)
17
1 file changed, 3 insertions(+)
15
18
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.c
21
--- a/target/arm/helper.c
19
+++ b/target/arm/helper.c
22
+++ b/target/arm/helper.c
20
@@ -XXX,XX +XXX,XX @@ static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter)
23
@@ -XXX,XX +XXX,XX @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
24
if (cpu_isar_feature(aa64_sme, cpu)) {
25
valid_mask |= SCR_ENTP2;
21
}
26
}
27
+ if (cpu_isar_feature(aa64_hcx, cpu)) {
28
+ valid_mask |= SCR_HXEN;
29
+ }
22
} else {
30
} else {
23
prohibited = arm_feature(env, ARM_FEATURE_EL3) &&
31
valid_mask &= ~(SCR_RW | SCR_ST);
24
- (env->cp15.mdcr_el3 & MDCR_SPME);
32
if (cpu_isar_feature(aa32_ras, cpu)) {
25
+ !(env->cp15.mdcr_el3 & MDCR_SPME);
26
}
27
28
if (prohibited && counter == 31) {
29
--
33
--
30
2.20.1
34
2.34.1
31
32
diff view generated by jsdifflib