1
Last pullreq before 6.0 softfreeze: a few minor feature patches,
1
Arm queue; not huge but I figured I might as well send it out since
2
some bugfixes, some cleanups.
2
I've been doing code review today and there's no queue of unprocessed
3
pullreqs...
3
4
5
thanks
4
-- PMM
6
-- PMM
5
7
6
The following changes since commit 6f34661b6c97a37a5efc27d31c037ddeda4547e2:
8
The following changes since commit b3f846c59d8405bb87c551187721fc92ff2f1b92:
7
9
8
Merge remote-tracking branch 'remotes/vivier2/tags/trivial-branch-for-6.0-pull-request' into staging (2021-03-11 18:55:27 +0000)
10
Merge remote-tracking branch 'remotes/huth-gitlab/tags/pull-request-2021-01-11v2' into staging (2021-01-11 15:15:35 +0000)
9
11
10
are available in the Git repository at:
12
are available in the Git repository at:
11
13
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210312-1
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210112
13
15
14
for you to fetch changes up to 41f09f2e9f09e4dd386d84174a6dcb5136af17ca:
16
for you to fetch changes up to 19d131395ccaf503db21dadd8257e6dc9fc1d7de:
15
17
16
hw/display/pxa2xx: Inline template header (2021-03-12 13:26:08 +0000)
18
ui/cocoa: Fix openFile: deprecation on Big Sur (2021-01-12 11:38:37 +0000)
17
19
18
----------------------------------------------------------------
20
----------------------------------------------------------------
19
target-arm queue:
21
target-arm queue:
20
* versal: Support XRAMs and XRAM controller
22
* arm: Support emulation of ARMv8.4-TTST extension
21
* smmu: Various minor bug fixes
23
* arm: Update cpu.h ID register field definitions
22
* SVE emulation: fix bugs handling odd vector lengths
24
* arm: Fix breakage of XScale instruction emulation
23
* allwinner-sun8i-emac: traverse transmit queue using TX_CUR_DESC register value
25
* hw/net/lan9118: Fix RX Status FIFO PEEK value
24
* tests/acceptance: fix orangepi-pc acceptance tests
26
* npcm7xx: Add ADC and PWM emulation
25
* hw/timer/sse-timer: Propagate eventual error in sse_timer_realize()
27
* ui/cocoa: Make "open docs" help menu entry work again when binary
26
* hw/arm/virt: KVM: The IPA lower bound is 32
28
is run from the build tree
27
* npcm7xx: support MFT module
29
* ui/cocoa: Fix openFile: deprecation on Big Sur
28
* pl110, pxa2xx_lcd: tidy up template headers
30
* docs: Add qemu-storage-daemon(1) manpage to meson.build
31
* docs: Build and install all the docs in a single manual
29
32
30
----------------------------------------------------------------
33
----------------------------------------------------------------
31
Andrew Jones (2):
34
Hao Wu (6):
32
accel: kvm: Fix kvm_type invocation
35
hw/misc: Add clock converter in NPCM7XX CLK module
33
hw/arm/virt: KVM: The IPA lower bound is 32
36
hw/timer: Refactor NPCM7XX Timer to use CLK clock
37
hw/adc: Add an ADC module for NPCM7XX
38
hw/misc: Add a PWM module for NPCM7XX
39
hw/misc: Add QTest for NPCM7XX PWM Module
40
hw/*: Use type casting for SysBusDevice in NPCM7XX
34
41
35
Edgar E. Iglesias (2):
42
Leif Lindholm (6):
36
hw/misc: versal: Add a model of the XRAM controller
43
target/arm: fix typo in cpu.h ID_AA64PFR1 field name
37
hw/arm: versal: Add support for the XRAMs
44
target/arm: make ARMCPU.clidr 64-bit
45
target/arm: make ARMCPU.ctr 64-bit
46
target/arm: add descriptions of CLIDR_EL1, CCSIDR_EL1, CTR_EL0 to cpu.h
47
target/arm: add aarch64 ID register fields to cpu.h
48
target/arm: add aarch32 ID register fields to cpu.h
38
49
39
Eric Auger (7):
50
Peter Maydell (5):
40
intel_iommu: Fix mask may be uninitialized in vtd_context_device_invalidate
51
docs: Add qemu-storage-daemon(1) manpage to meson.build
41
dma: Introduce dma_aligned_pow2_mask()
52
docs: Build and install all the docs in a single manual
42
virtio-iommu: Handle non power of 2 range invalidations
53
target/arm: Don't decode insns in the XScale/iWMMXt space as cp insns
43
hw/arm/smmu-common: Fix smmu_iotlb_inv_iova when asid is not set
54
hw/net/lan9118: Fix RX Status FIFO PEEK value
44
hw/arm/smmuv3: Enforce invalidation on a power of two range
55
hw/net/lan9118: Add symbolic constants for register offsets
45
hw/arm/smmuv3: Fix SMMU_CMD_CFGI_STE_RANGE handling
46
hw/arm/smmuv3: Uniformize sid traces
47
56
48
Hao Wu (5):
57
Roman Bolshakov (2):
49
hw/misc: Add GPIOs for duty in NPCM7xx PWM
58
ui/cocoa: Update path to docs in build tree
50
hw/misc: Add NPCM7XX MFT Module
59
ui/cocoa: Fix openFile: deprecation on Big Sur
51
hw/arm: Add MFT device to NPCM7xx Soc
52
hw/arm: Connect PWM fans in NPCM7XX boards
53
tests/qtest: Test PWM fan RPM using MFT in PWM test
54
60
55
Niek Linnenbank (5):
61
Rémi Denis-Courmont (2):
56
hw/net/allwinner-sun8i-emac: traverse transmit queue using TX_CUR_DESC register value
62
target/arm: ARMv8.4-TTST extension
57
tests/acceptance/boot_linux_console: remove Armbian 19.11.3 bionic test for orangepi-pc machine
63
target/arm: enable Small Translation tables in max CPU
58
tests/acceptance/boot_linux_console: change URL for test_arm_orangepi_bionic_20_08
59
tests/acceptance: update sunxi kernel from armbian to 5.10.16
60
tests/acceptance: drop ARMBIAN_ARTIFACTS_CACHED condition for orangepi-pc, cubieboard tests
61
64
62
Peter Maydell (9):
65
docs/conf.py | 46 ++-
63
hw/display/pl110: Remove dead code for non-32-bpp surfaces
66
docs/devel/conf.py | 15 -
64
hw/display/pl110: Pull included-once parts of template header into pl110.c
67
docs/index.html.in | 17 -
65
hw/display/pl110: Remove use of BITS from pl110_template.h
68
docs/interop/conf.py | 28 --
66
hw/display/pxa2xx_lcd: Remove dead code for non-32-bpp surfaces
69
docs/meson.build | 65 ++--
67
hw/display/pxa2xx_lcd: Remove dest_width state field
70
docs/specs/conf.py | 16 -
68
hw/display/pxa2xx: Remove use of BITS in pxa2xx_template.h
71
docs/system/arm/nuvoton.rst | 4 +-
69
hw/display/pxa2xx: Apply brace-related coding style fixes to template header
72
docs/system/conf.py | 28 --
70
hw/display/pxa2xx: Apply whitespace-only coding style fixes to template header
73
docs/tools/conf.py | 37 --
71
hw/display/pxa2xx: Inline template header
74
docs/user/conf.py | 15 -
75
meson.build | 1 +
76
hw/adc/trace.h | 1 +
77
include/hw/adc/npcm7xx_adc.h | 69 ++++
78
include/hw/arm/npcm7xx.h | 4 +
79
include/hw/misc/npcm7xx_clk.h | 146 ++++++-
80
include/hw/misc/npcm7xx_pwm.h | 105 +++++
81
include/hw/timer/npcm7xx_timer.h | 1 +
82
target/arm/cpu.h | 85 ++++-
83
hw/adc/npcm7xx_adc.c | 301 +++++++++++++++
84
hw/arm/npcm7xx.c | 55 ++-
85
hw/arm/npcm7xx_boards.c | 2 +-
86
hw/mem/npcm7xx_mc.c | 2 +-
87
hw/misc/npcm7xx_clk.c | 807 ++++++++++++++++++++++++++++++++++++++-
88
hw/misc/npcm7xx_gcr.c | 2 +-
89
hw/misc/npcm7xx_pwm.c | 550 ++++++++++++++++++++++++++
90
hw/misc/npcm7xx_rng.c | 2 +-
91
hw/net/lan9118.c | 26 +-
92
hw/nvram/npcm7xx_otp.c | 2 +-
93
hw/ssi/npcm7xx_fiu.c | 2 +-
94
hw/timer/npcm7xx_timer.c | 39 +-
95
target/arm/cpu64.c | 1 +
96
target/arm/helper.c | 15 +-
97
target/arm/translate.c | 7 +
98
tests/qtest/npcm7xx_adc-test.c | 377 ++++++++++++++++++
99
tests/qtest/npcm7xx_pwm-test.c | 490 ++++++++++++++++++++++++
100
hw/adc/meson.build | 1 +
101
hw/adc/trace-events | 5 +
102
hw/misc/meson.build | 1 +
103
hw/misc/trace-events | 6 +
104
tests/qtest/meson.build | 4 +-
105
ui/cocoa.m | 7 +-
106
41 files changed, 3124 insertions(+), 263 deletions(-)
107
delete mode 100644 docs/devel/conf.py
108
delete mode 100644 docs/index.html.in
109
delete mode 100644 docs/interop/conf.py
110
delete mode 100644 docs/specs/conf.py
111
delete mode 100644 docs/system/conf.py
112
delete mode 100644 docs/tools/conf.py
113
delete mode 100644 docs/user/conf.py
114
create mode 100644 hw/adc/trace.h
115
create mode 100644 include/hw/adc/npcm7xx_adc.h
116
create mode 100644 include/hw/misc/npcm7xx_pwm.h
117
create mode 100644 hw/adc/npcm7xx_adc.c
118
create mode 100644 hw/misc/npcm7xx_pwm.c
119
create mode 100644 tests/qtest/npcm7xx_adc-test.c
120
create mode 100644 tests/qtest/npcm7xx_pwm-test.c
121
create mode 100644 hw/adc/trace-events
72
122
73
Philippe Mathieu-Daudé (1):
74
hw/timer/sse-timer: Propagate eventual error in sse_timer_realize()
75
76
Richard Henderson (8):
77
target/arm: Fix sve_uzp_p vs odd vector lengths
78
target/arm: Fix sve_zip_p vs odd vector lengths
79
target/arm: Fix sve_punpk_p vs odd vector lengths
80
target/arm: Update find_last_active for PREDDESC
81
target/arm: Update BRKA, BRKB, BRKN for PREDDESC
82
target/arm: Update CNTP for PREDDESC
83
target/arm: Update WHILE for PREDDESC
84
target/arm: Update sve reduction vs simd_desc
85
86
docs/system/arm/nuvoton.rst | 2 +-
87
docs/system/arm/xlnx-versal-virt.rst | 1 +
88
hw/arm/smmu-internal.h | 5 +
89
hw/display/pl110_template.h | 120 +-------
90
hw/display/pxa2xx_template.h | 447 ---------------------------
91
include/hw/arm/npcm7xx.h | 13 +-
92
include/hw/arm/xlnx-versal.h | 13 +
93
include/hw/boards.h | 1 +
94
include/hw/misc/npcm7xx_mft.h | 70 +++++
95
include/hw/misc/npcm7xx_pwm.h | 4 +-
96
include/hw/misc/xlnx-versal-xramc.h | 97 ++++++
97
include/sysemu/dma.h | 12 +
98
target/arm/kvm_arm.h | 6 +-
99
accel/kvm/kvm-all.c | 2 +
100
hw/arm/npcm7xx.c | 45 ++-
101
hw/arm/npcm7xx_boards.c | 99 ++++++
102
hw/arm/smmu-common.c | 32 +-
103
hw/arm/smmuv3.c | 58 ++--
104
hw/arm/virt.c | 23 +-
105
hw/arm/xlnx-versal.c | 36 +++
106
hw/display/pl110.c | 123 +++++---
107
hw/display/pxa2xx_lcd.c | 520 ++++++++++++++++++++++++++-----
108
hw/i386/intel_iommu.c | 32 +-
109
hw/misc/npcm7xx_mft.c | 540 +++++++++++++++++++++++++++++++++
110
hw/misc/npcm7xx_pwm.c | 4 +
111
hw/misc/xlnx-versal-xramc.c | 253 +++++++++++++++
112
hw/net/allwinner-sun8i-emac.c | 62 ++--
113
hw/timer/sse-timer.c | 1 +
114
hw/virtio/virtio-iommu.c | 19 +-
115
softmmu/dma-helpers.c | 26 ++
116
target/arm/kvm.c | 4 +-
117
target/arm/sve_helper.c | 107 ++++---
118
target/arm/translate-sve.c | 26 +-
119
tests/qtest/npcm7xx_pwm-test.c | 205 ++++++++++++-
120
hw/arm/trace-events | 24 +-
121
hw/misc/meson.build | 2 +
122
hw/misc/trace-events | 8 +
123
tests/acceptance/boot_linux_console.py | 120 +++-----
124
tests/acceptance/replay_kernel.py | 10 +-
125
39 files changed, 2235 insertions(+), 937 deletions(-)
126
delete mode 100644 hw/display/pxa2xx_template.h
127
create mode 100644 include/hw/misc/npcm7xx_mft.h
128
create mode 100644 include/hw/misc/xlnx-versal-xramc.h
129
create mode 100644 hw/misc/npcm7xx_mft.c
130
create mode 100644 hw/misc/xlnx-versal-xramc.c
131
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
From: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
2
2
3
Connect the support for the Versal Accelerator RAMs (XRAMs).
3
This adds for the Small Translation tables extension in AArch64 state.
4
4
5
Reviewed-by: Luc Michel <luc@lmichel.fr>
5
Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
6
Acked-by: Alistair Francis <alistair.francis@wdc.com>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Message-id: 20210308224637.2949533-3-edgar.iglesias@gmail.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
8
---
11
docs/system/arm/xlnx-versal-virt.rst | 1 +
9
target/arm/cpu.h | 5 +++++
12
include/hw/arm/xlnx-versal.h | 13 ++++++++++
10
target/arm/helper.c | 15 +++++++++++++--
13
hw/arm/xlnx-versal.c | 36 ++++++++++++++++++++++++++++
11
2 files changed, 18 insertions(+), 2 deletions(-)
14
3 files changed, 50 insertions(+)
15
12
16
diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-versal-virt.rst
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
18
--- a/docs/system/arm/xlnx-versal-virt.rst
15
--- a/target/arm/cpu.h
19
+++ b/docs/system/arm/xlnx-versal-virt.rst
16
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ Implemented devices:
17
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_uao(const ARMISARegisters *id)
21
- 8 ADMA (Xilinx zDMA) channels
18
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0;
22
- 2 SD Controllers
23
- OCM (256KB of On Chip Memory)
24
+- XRAM (4MB of on chip Accelerator RAM)
25
- DDR memory
26
27
QEMU does not yet model any other devices, including the PL and the AI Engine.
28
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/include/hw/arm/xlnx-versal.h
31
+++ b/include/hw/arm/xlnx-versal.h
32
@@ -XXX,XX +XXX,XX @@
33
34
#include "hw/sysbus.h"
35
#include "hw/arm/boot.h"
36
+#include "hw/or-irq.h"
37
#include "hw/sd/sdhci.h"
38
#include "hw/intc/arm_gicv3.h"
39
#include "hw/char/pl011.h"
40
@@ -XXX,XX +XXX,XX @@
41
#include "hw/rtc/xlnx-zynqmp-rtc.h"
42
#include "qom/object.h"
43
#include "hw/usb/xlnx-usb-subsystem.h"
44
+#include "hw/misc/xlnx-versal-xramc.h"
45
46
#define TYPE_XLNX_VERSAL "xlnx-versal"
47
OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
48
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
49
#define XLNX_VERSAL_NR_GEMS 2
50
#define XLNX_VERSAL_NR_ADMAS 8
51
#define XLNX_VERSAL_NR_SDS 2
52
+#define XLNX_VERSAL_NR_XRAM 4
53
#define XLNX_VERSAL_NR_IRQS 192
54
55
struct Versal {
56
@@ -XXX,XX +XXX,XX @@ struct Versal {
57
XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS];
58
VersalUsb2 usb;
59
} iou;
60
+
61
+ struct {
62
+ qemu_or_irq irq_orgate;
63
+ XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM];
64
+ } xram;
65
} lpd;
66
67
/* The Platform Management Controller subsystem. */
68
@@ -XXX,XX +XXX,XX @@ struct Versal {
69
#define VERSAL_GEM1_IRQ_0 58
70
#define VERSAL_GEM1_WAKE_IRQ_0 59
71
#define VERSAL_ADMA_IRQ_0 60
72
+#define VERSAL_XRAM_IRQ_0 79
73
#define VERSAL_RTC_APB_ERR_IRQ 121
74
#define VERSAL_SD0_IRQ_0 126
75
#define VERSAL_RTC_ALARM_IRQ 142
76
@@ -XXX,XX +XXX,XX @@ struct Versal {
77
#define MM_OCM 0xfffc0000U
78
#define MM_OCM_SIZE 0x40000
79
80
+#define MM_XRAM 0xfe800000
81
+#define MM_XRAMC 0xff8e0000
82
+#define MM_XRAMC_SIZE 0x10000
83
+
84
#define MM_USB2_CTRL_REGS 0xFF9D0000
85
#define MM_USB2_CTRL_REGS_SIZE 0x10000
86
87
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/hw/arm/xlnx-versal.c
90
+++ b/hw/arm/xlnx-versal.c
91
@@ -XXX,XX +XXX,XX @@
92
*/
93
94
#include "qemu/osdep.h"
95
+#include "qemu/units.h"
96
#include "qapi/error.h"
97
#include "qemu/log.h"
98
#include "qemu/module.h"
99
@@ -XXX,XX +XXX,XX @@ static void versal_create_rtc(Versal *s, qemu_irq *pic)
100
sysbus_connect_irq(sbd, 1, pic[VERSAL_RTC_APB_ERR_IRQ]);
101
}
19
}
102
20
103
+static void versal_create_xrams(Versal *s, qemu_irq *pic)
21
+static inline bool isar_feature_aa64_st(const ARMISARegisters *id)
104
+{
22
+{
105
+ int nr_xrams = ARRAY_SIZE(s->lpd.xram.ctrl);
23
+ return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, ST) != 0;
106
+ DeviceState *orgate;
107
+ int i;
108
+
109
+ /* XRAM IRQs get ORed into a single line. */
110
+ object_initialize_child(OBJECT(s), "xram-irq-orgate",
111
+ &s->lpd.xram.irq_orgate, TYPE_OR_IRQ);
112
+ orgate = DEVICE(&s->lpd.xram.irq_orgate);
113
+ object_property_set_int(OBJECT(orgate),
114
+ "num-lines", nr_xrams, &error_fatal);
115
+ qdev_realize(orgate, NULL, &error_fatal);
116
+ qdev_connect_gpio_out(orgate, 0, pic[VERSAL_XRAM_IRQ_0]);
117
+
118
+ for (i = 0; i < ARRAY_SIZE(s->lpd.xram.ctrl); i++) {
119
+ SysBusDevice *sbd;
120
+ MemoryRegion *mr;
121
+
122
+ object_initialize_child(OBJECT(s), "xram[*]", &s->lpd.xram.ctrl[i],
123
+ TYPE_XLNX_XRAM_CTRL);
124
+ sbd = SYS_BUS_DEVICE(&s->lpd.xram.ctrl[i]);
125
+ sysbus_realize(sbd, &error_fatal);
126
+
127
+ mr = sysbus_mmio_get_region(sbd, 0);
128
+ memory_region_add_subregion(&s->mr_ps,
129
+ MM_XRAMC + i * MM_XRAMC_SIZE, mr);
130
+ mr = sysbus_mmio_get_region(sbd, 1);
131
+ memory_region_add_subregion(&s->mr_ps, MM_XRAM + i * MiB, mr);
132
+
133
+ sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(orgate, i));
134
+ }
135
+}
24
+}
136
+
25
+
137
/* This takes the board allocated linear DDR memory and creates aliases
26
static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
138
* for each split DDR range/aperture on the Versal address map.
27
{
139
*/
28
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
140
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
29
diff --git a/target/arm/helper.c b/target/arm/helper.c
141
versal_create_admas(s, pic);
30
index XXXXXXX..XXXXXXX 100644
142
versal_create_sds(s, pic);
31
--- a/target/arm/helper.c
143
versal_create_rtc(s, pic);
32
+++ b/target/arm/helper.c
144
+ versal_create_xrams(s, pic);
33
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
145
versal_map_ddr(s);
34
{
146
versal_unimp(s);
35
uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
147
36
bool epd, hpd, using16k, using64k;
37
- int select, tsz, tbi;
38
+ int select, tsz, tbi, max_tsz;
39
40
if (!regime_has_2_ranges(mmu_idx)) {
41
select = 0;
42
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
43
hpd = extract64(tcr, 42, 1);
44
}
45
}
46
- tsz = MIN(tsz, 39); /* TODO: ARMv8.4-TTST */
47
+
48
+ if (cpu_isar_feature(aa64_st, env_archcpu(env))) {
49
+ max_tsz = 48 - using64k;
50
+ } else {
51
+ max_tsz = 39;
52
+ }
53
+
54
+ tsz = MIN(tsz, max_tsz);
55
tsz = MAX(tsz, 16); /* TODO: ARMv8.2-LVA */
56
57
/* Present TBI as a composite with TBID. */
58
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
59
if (!aarch64 || stride == 9) {
60
/* AArch32 or 4KB pages */
61
startlevel = 2 - sl0;
62
+
63
+ if (cpu_isar_feature(aa64_st, cpu)) {
64
+ startlevel &= 3;
65
+ }
66
} else {
67
/* 16KB or 64KB pages */
68
startlevel = 3 - sl0;
148
--
69
--
149
2.20.1
70
2.20.1
150
71
151
72
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
2
2
3
If the SSECounter link is absent, we set an error message
3
Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
4
in sse_timer_realize() but forgot to propagate this error.
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Add the missing 'return'.
6
7
Fixes: CID 1450755 (Null pointer dereferences)
8
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20210312001845.1562670-1-f4bug@amsat.org
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
6
---
13
hw/timer/sse-timer.c | 1 +
7
target/arm/cpu64.c | 1 +
14
1 file changed, 1 insertion(+)
8
1 file changed, 1 insertion(+)
15
9
16
diff --git a/hw/timer/sse-timer.c b/hw/timer/sse-timer.c
10
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
17
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/timer/sse-timer.c
12
--- a/target/arm/cpu64.c
19
+++ b/hw/timer/sse-timer.c
13
+++ b/target/arm/cpu64.c
20
@@ -XXX,XX +XXX,XX @@ static void sse_timer_realize(DeviceState *dev, Error **errp)
14
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
21
15
t = cpu->isar.id_aa64mmfr2;
22
if (!s->counter) {
16
t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1);
23
error_setg(errp, "counter property was not set");
17
t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* TTCNP */
24
+ return;
18
+ t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1); /* TTST */
25
}
19
cpu->isar.id_aa64mmfr2 = t;
26
20
27
s->counter_notifier.notify = sse_timer_counter_callback;
21
/* Replicate the same data to the 32-bit id registers. */
28
--
22
--
29
2.20.1
23
2.20.1
30
24
31
25
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
The virt machine already checks KVM_CAP_ARM_VM_IPA_SIZE to get the
3
SBSS -> SSBS
4
upper bound of the IPA size. If that bound is lower than the highest
5
possible GPA for the machine, then QEMU will error out. However, the
6
IPA is set to 40 when the highest GPA is less than or equal to 40,
7
even when KVM may support an IPA limit as low as 32. This means KVM
8
may fail the VM creation unnecessarily. Additionally, 40 is selected
9
with the value 0, which means use the default, and that gets around
10
a check in some versions of KVM, causing a difficult to debug fail.
11
Always use the IPA size that corresponds to the highest possible GPA,
12
unless it's lower than 32, in which case use 32. Also, we must still
13
use 0 when KVM only supports the legacy fixed 40 bit IPA.
14
4
15
Suggested-by: Marc Zyngier <maz@kernel.org>
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
16
Signed-off-by: Andrew Jones <drjones@redhat.com>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Reviewed-by: Eric Auger <eric.auger@redhat.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Marc Zyngier <maz@kernel.org>
8
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
19
Message-id: 20210310135218.255205-3-drjones@redhat.com
9
Message-id: 20210108185154.8108-2-leif@nuviainc.com
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
11
---
22
target/arm/kvm_arm.h | 6 ++++--
12
target/arm/cpu.h | 2 +-
23
hw/arm/virt.c | 23 ++++++++++++++++-------
13
1 file changed, 1 insertion(+), 1 deletion(-)
24
target/arm/kvm.c | 4 +++-
25
3 files changed, 23 insertions(+), 10 deletions(-)
26
14
27
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
28
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/kvm_arm.h
17
--- a/target/arm/cpu.h
30
+++ b/target/arm/kvm_arm.h
18
+++ b/target/arm/cpu.h
31
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_sve_supported(void);
19
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64PFR0, RAS, 28, 4)
32
/**
20
FIELD(ID_AA64PFR0, SVE, 32, 4)
33
* kvm_arm_get_max_vm_ipa_size:
21
34
* @ms: Machine state handle
22
FIELD(ID_AA64PFR1, BT, 0, 4)
35
+ * @fixed_ipa: True when the IPA limit is fixed at 40. This is the case
23
-FIELD(ID_AA64PFR1, SBSS, 4, 4)
36
+ * for legacy KVM.
24
+FIELD(ID_AA64PFR1, SSBS, 4, 4)
37
*
25
FIELD(ID_AA64PFR1, MTE, 8, 4)
38
* Returns the number of bits in the IPA address space supported by KVM
26
FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
39
*/
40
-int kvm_arm_get_max_vm_ipa_size(MachineState *ms);
41
+int kvm_arm_get_max_vm_ipa_size(MachineState *ms, bool *fixed_ipa);
42
43
/**
44
* kvm_arm_sync_mpstate_to_kvm:
45
@@ -XXX,XX +XXX,XX @@ static inline void kvm_arm_add_vcpu_properties(Object *obj)
46
g_assert_not_reached();
47
}
48
49
-static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
50
+static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms, bool *fixed_ipa)
51
{
52
g_assert_not_reached();
53
}
54
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/hw/arm/virt.c
57
+++ b/hw/arm/virt.c
58
@@ -XXX,XX +XXX,XX @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
59
static int virt_kvm_type(MachineState *ms, const char *type_str)
60
{
61
VirtMachineState *vms = VIRT_MACHINE(ms);
62
- int max_vm_pa_size = kvm_arm_get_max_vm_ipa_size(ms);
63
- int requested_pa_size;
64
+ int max_vm_pa_size, requested_pa_size;
65
+ bool fixed_ipa;
66
+
67
+ max_vm_pa_size = kvm_arm_get_max_vm_ipa_size(ms, &fixed_ipa);
68
69
/* we freeze the memory map to compute the highest gpa */
70
virt_set_memmap(vms);
71
72
requested_pa_size = 64 - clz64(vms->highest_gpa);
73
74
+ /*
75
+ * KVM requires the IPA size to be at least 32 bits.
76
+ */
77
+ if (requested_pa_size < 32) {
78
+ requested_pa_size = 32;
79
+ }
80
+
81
if (requested_pa_size > max_vm_pa_size) {
82
error_report("-m and ,maxmem option values "
83
"require an IPA range (%d bits) larger than "
84
"the one supported by the host (%d bits)",
85
requested_pa_size, max_vm_pa_size);
86
- exit(1);
87
+ exit(1);
88
}
89
/*
90
- * By default we return 0 which corresponds to an implicit legacy
91
- * 40b IPA setting. Otherwise we return the actual requested PA
92
- * logsize
93
+ * We return the requested PA log size, unless KVM only supports
94
+ * the implicit legacy 40b IPA setting, in which case the kvm_type
95
+ * must be 0.
96
*/
97
- return requested_pa_size > 40 ? requested_pa_size : 0;
98
+ return fixed_ipa ? 0 : requested_pa_size;
99
}
100
101
static void virt_machine_class_init(ObjectClass *oc, void *data)
102
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
103
index XXXXXXX..XXXXXXX 100644
104
--- a/target/arm/kvm.c
105
+++ b/target/arm/kvm.c
106
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_pmu_supported(void)
107
return kvm_check_extension(kvm_state, KVM_CAP_ARM_PMU_V3);
108
}
109
110
-int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
111
+int kvm_arm_get_max_vm_ipa_size(MachineState *ms, bool *fixed_ipa)
112
{
113
KVMState *s = KVM_STATE(ms->accelerator);
114
int ret;
115
116
ret = kvm_check_extension(s, KVM_CAP_ARM_VM_IPA_SIZE);
117
+ *fixed_ipa = ret <= 0;
118
+
119
return ret > 0 ? ret : 40;
120
}
121
27
122
--
28
--
123
2.20.1
29
2.20.1
124
30
125
31
diff view generated by jsdifflib
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
Previously the ARMBIAN_ARTIFACTS_CACHED pre-condition was added to allow running
3
The AArch64 view of CLIDR_EL1 extends the ICB field to include also bit
4
tests that have already existing armbian.com artifacts stored in the local avocado cache,
4
32, as well as adding a Ttype<n> field when FEAT_MTE is implemented.
5
but do not have working URLs to download a fresh copy.
5
Extend the clidr field to be able to hold this context.
6
6
7
At this time of writing the URLs for artifacts on the armbian.com server are updated and working.
7
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
8
Any future broken URLs will result in a skipped acceptance test, for example:
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
(1/5) tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_arm_orangepi:
10
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
11
CANCEL: Missing asset https://apt.armbian.com/pool/main/l/linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb (0.53 s)
11
Message-id: 20210108185154.8108-3-leif@nuviainc.com
12
13
This commits removes the ARMBIAN_ARTIFACTS_CACHED pre-condition such that
14
the acceptance tests for the orangepi-pc and cubieboard machines can run.
15
16
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
17
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
18
Message-id: 20210310195820.21950-6-nieklinnenbank@gmail.com
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
13
---
21
tests/acceptance/boot_linux_console.py | 12 ------------
14
target/arm/cpu.h | 2 +-
22
tests/acceptance/replay_kernel.py | 2 --
15
1 file changed, 1 insertion(+), 1 deletion(-)
23
2 files changed, 14 deletions(-)
24
16
25
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
26
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
27
--- a/tests/acceptance/boot_linux_console.py
19
--- a/target/arm/cpu.h
28
+++ b/tests/acceptance/boot_linux_console.py
20
+++ b/target/arm/cpu.h
29
@@ -XXX,XX +XXX,XX @@ def test_arm_exynos4210_initrd(self):
21
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
30
self.wait_for_console_pattern('Boot successful.')
22
uint32_t id_afr0;
31
# TODO user command, for now the uart is stuck
23
uint64_t id_aa64afr0;
32
24
uint64_t id_aa64afr1;
33
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
25
- uint32_t clidr;
34
- 'Test artifacts fetched from unreliable apt.armbian.com')
26
+ uint64_t clidr;
35
def test_arm_cubieboard_initrd(self):
27
uint64_t mp_affinity; /* MP ID without feature bits */
36
"""
28
/* The elements of this array are the CCSIDR values for each cache,
37
:avocado: tags=arch:arm
29
* in the order L1DCache, L1ICache, L2DCache, L2ICache, etc.
38
@@ -XXX,XX +XXX,XX @@ def test_arm_cubieboard_initrd(self):
39
'system-control@1c00000')
40
# cubieboard's reboot is not functioning; omit reboot test.
41
42
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
43
- 'Test artifacts fetched from unreliable apt.armbian.com')
44
def test_arm_cubieboard_sata(self):
45
"""
46
:avocado: tags=arch:arm
47
@@ -XXX,XX +XXX,XX @@ def test_arm_quanta_gsj_initrd(self):
48
self.wait_for_console_pattern(
49
'Give root password for system maintenance')
50
51
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
52
- 'Test artifacts fetched from unreliable apt.armbian.com')
53
def test_arm_orangepi(self):
54
"""
55
:avocado: tags=arch:arm
56
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi(self):
57
console_pattern = 'Kernel command line: %s' % kernel_command_line
58
self.wait_for_console_pattern(console_pattern)
59
60
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
61
- 'Test artifacts fetched from unreliable apt.armbian.com')
62
def test_arm_orangepi_initrd(self):
63
"""
64
:avocado: tags=arch:arm
65
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_initrd(self):
66
# Wait for VM to shut down gracefully
67
self.vm.wait()
68
69
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
70
- 'Test artifacts fetched from unreliable apt.armbian.com')
71
def test_arm_orangepi_sd(self):
72
"""
73
:avocado: tags=arch:arm
74
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_sd(self):
75
# Wait for VM to shut down gracefully
76
self.vm.wait()
77
78
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
79
- 'Test artifacts fetched from unreliable apt.armbian.com')
80
@skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
81
def test_arm_orangepi_bionic_20_08(self):
82
"""
83
diff --git a/tests/acceptance/replay_kernel.py b/tests/acceptance/replay_kernel.py
84
index XXXXXXX..XXXXXXX 100644
85
--- a/tests/acceptance/replay_kernel.py
86
+++ b/tests/acceptance/replay_kernel.py
87
@@ -XXX,XX +XXX,XX @@ def test_arm_virt(self):
88
self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=1)
89
90
@skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab')
91
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
92
- 'Test artifacts fetched from unreliable apt.armbian.com')
93
def test_arm_cubieboard_initrd(self):
94
"""
95
:avocado: tags=arch:arm
96
--
30
--
97
2.20.1
31
2.20.1
98
32
99
33
diff view generated by jsdifflib
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
Update the download URL of the Armbian 20.08 Bionic image for
3
When FEAT_MTE is implemented, the AArch64 view of CTR_EL0 adds the
4
test_arm_orangepi_bionic_20_08 of the orangepi-pc machine.
4
TminLine field in bits [37:32].
5
Extend the ctr field to be able to hold this context.
5
6
6
The archive.armbian.com URL contains more images and should keep stable
7
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
7
for a longer period of time than dl.armbian.com.
8
Reviewed-by: Hao Wu <wuhaotsh@google.com>
8
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
10
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Message-id: 20210108185154.8108-4-leif@nuviainc.com
11
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
13
Message-id: 20210310195820.21950-4-nieklinnenbank@gmail.com
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
13
---
16
tests/acceptance/boot_linux_console.py | 2 +-
14
target/arm/cpu.h | 2 +-
17
1 file changed, 1 insertion(+), 1 deletion(-)
15
1 file changed, 1 insertion(+), 1 deletion(-)
18
16
19
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
21
--- a/tests/acceptance/boot_linux_console.py
19
--- a/target/arm/cpu.h
22
+++ b/tests/acceptance/boot_linux_console.py
20
+++ b/target/arm/cpu.h
23
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_bionic_20_08(self):
21
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
24
# to 1036 MiB, but the underlying filesystem is 1552 MiB...
22
uint64_t midr;
25
# As we expand it to 2 GiB we are safe.
23
uint32_t revidr;
26
24
uint32_t reset_fpsid;
27
- image_url = ('https://dl.armbian.com/orangepipc/archive/'
25
- uint32_t ctr;
28
+ image_url = ('https://archive.armbian.com/orangepipc/archive/'
26
+ uint64_t ctr;
29
'Armbian_20.08.1_Orangepipc_bionic_current_5.8.5.img.xz')
27
uint32_t reset_sctlr;
30
image_hash = ('b4d6775f5673486329e45a0586bf06b6'
28
uint64_t pmceid0;
31
'dbe792199fd182ac6b9c7bb6c7d3e6dd')
29
uint64_t pmceid1;
32
--
30
--
33
2.20.1
31
2.20.1
34
32
35
33
diff view generated by jsdifflib
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
The linux kernel 4.20.7 binary for sunxi has been removed from apt.armbian.com:
3
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
4
4
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
5
$ ARMBIAN_ARTIFACTS_CACHED=yes AVOCADO_ALLOW_LARGE_STORAGE=yes avocado --show=app,console run -t machine:orangepi-pc tests/acceptance/boot_linux_console.py
5
Message-id: 20210108185154.8108-5-leif@nuviainc.com
6
Fetching asset from tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_arm_orangepi
7
...
8
(1/6) tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_arm_orangepi:
9
CANCEL: Missing asset https://apt.armbian.com/pool/main/l/linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb (0.55 s)
10
11
This commit updates the sunxi kernel to 5.10.16 for the acceptance
12
tests of the orangepi-pc and cubieboard machines.
13
14
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
15
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
16
Message-id: 20210310195820.21950-5-nieklinnenbank@gmail.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
7
---
19
tests/acceptance/boot_linux_console.py | 40 +++++++++++++-------------
8
target/arm/cpu.h | 31 +++++++++++++++++++++++++++++++
20
tests/acceptance/replay_kernel.py | 8 +++---
9
1 file changed, 31 insertions(+)
21
2 files changed, 24 insertions(+), 24 deletions(-)
22
10
23
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
11
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
24
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
25
--- a/tests/acceptance/boot_linux_console.py
13
--- a/target/arm/cpu.h
26
+++ b/tests/acceptance/boot_linux_console.py
14
+++ b/target/arm/cpu.h
27
@@ -XXX,XX +XXX,XX @@ def test_arm_cubieboard_initrd(self):
15
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_FPCCR, ASPEN, 31, 1)
28
:avocado: tags=machine:cubieboard
16
/*
29
"""
17
* System register ID fields.
30
deb_url = ('https://apt.armbian.com/pool/main/l/'
18
*/
31
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
19
+FIELD(CLIDR_EL1, CTYPE1, 0, 3)
32
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
20
+FIELD(CLIDR_EL1, CTYPE2, 3, 3)
33
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
21
+FIELD(CLIDR_EL1, CTYPE3, 6, 3)
34
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
22
+FIELD(CLIDR_EL1, CTYPE4, 9, 3)
35
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
23
+FIELD(CLIDR_EL1, CTYPE5, 12, 3)
36
kernel_path = self.extract_from_deb(deb_path,
24
+FIELD(CLIDR_EL1, CTYPE6, 15, 3)
37
- '/boot/vmlinuz-4.20.7-sunxi')
25
+FIELD(CLIDR_EL1, CTYPE7, 18, 3)
38
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun4i-a10-cubieboard.dtb'
26
+FIELD(CLIDR_EL1, LOUIS, 21, 3)
39
+ '/boot/vmlinuz-5.10.16-sunxi')
27
+FIELD(CLIDR_EL1, LOC, 24, 3)
40
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
28
+FIELD(CLIDR_EL1, LOUU, 27, 3)
41
dtb_path = self.extract_from_deb(deb_path, dtb_path)
29
+FIELD(CLIDR_EL1, ICB, 30, 3)
42
initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
30
+
43
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
31
+/* When FEAT_CCIDX is implemented */
44
@@ -XXX,XX +XXX,XX @@ def test_arm_cubieboard_sata(self):
32
+FIELD(CCSIDR_EL1, CCIDX_LINESIZE, 0, 3)
45
:avocado: tags=machine:cubieboard
33
+FIELD(CCSIDR_EL1, CCIDX_ASSOCIATIVITY, 3, 21)
46
"""
34
+FIELD(CCSIDR_EL1, CCIDX_NUMSETS, 32, 24)
47
deb_url = ('https://apt.armbian.com/pool/main/l/'
35
+
48
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
36
+/* When FEAT_CCIDX is not implemented */
49
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
37
+FIELD(CCSIDR_EL1, LINESIZE, 0, 3)
50
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
38
+FIELD(CCSIDR_EL1, ASSOCIATIVITY, 3, 10)
51
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
39
+FIELD(CCSIDR_EL1, NUMSETS, 13, 15)
52
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
40
+
53
kernel_path = self.extract_from_deb(deb_path,
41
+FIELD(CTR_EL0, IMINLINE, 0, 4)
54
- '/boot/vmlinuz-4.20.7-sunxi')
42
+FIELD(CTR_EL0, L1IP, 14, 2)
55
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun4i-a10-cubieboard.dtb'
43
+FIELD(CTR_EL0, DMINLINE, 16, 4)
56
+ '/boot/vmlinuz-5.10.16-sunxi')
44
+FIELD(CTR_EL0, ERG, 20, 4)
57
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
45
+FIELD(CTR_EL0, CWG, 24, 4)
58
dtb_path = self.extract_from_deb(deb_path, dtb_path)
46
+FIELD(CTR_EL0, IDC, 28, 1)
59
rootfs_url = ('https://github.com/groeck/linux-build-test/raw/'
47
+FIELD(CTR_EL0, DIC, 29, 1)
60
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
48
+FIELD(CTR_EL0, TMINLINE, 32, 6)
61
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi(self):
49
+
62
:avocado: tags=machine:orangepi-pc
50
FIELD(MIDR_EL1, REVISION, 0, 4)
63
"""
51
FIELD(MIDR_EL1, PARTNUM, 4, 12)
64
deb_url = ('https://apt.armbian.com/pool/main/l/'
52
FIELD(MIDR_EL1, ARCHITECTURE, 16, 4)
65
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
66
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
67
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
68
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
69
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
70
kernel_path = self.extract_from_deb(deb_path,
71
- '/boot/vmlinuz-4.20.7-sunxi')
72
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb'
73
+ '/boot/vmlinuz-5.10.16-sunxi')
74
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb'
75
dtb_path = self.extract_from_deb(deb_path, dtb_path)
76
77
self.vm.set_console()
78
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_initrd(self):
79
:avocado: tags=machine:orangepi-pc
80
"""
81
deb_url = ('https://apt.armbian.com/pool/main/l/'
82
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
83
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
84
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
85
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
86
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
87
kernel_path = self.extract_from_deb(deb_path,
88
- '/boot/vmlinuz-4.20.7-sunxi')
89
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb'
90
+ '/boot/vmlinuz-5.10.16-sunxi')
91
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb'
92
dtb_path = self.extract_from_deb(deb_path, dtb_path)
93
initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
94
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
95
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_sd(self):
96
:avocado: tags=device:sd
97
"""
98
deb_url = ('https://apt.armbian.com/pool/main/l/'
99
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
100
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
101
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
102
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
103
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
104
kernel_path = self.extract_from_deb(deb_path,
105
- '/boot/vmlinuz-4.20.7-sunxi')
106
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb'
107
+ '/boot/vmlinuz-5.10.16-sunxi')
108
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb'
109
dtb_path = self.extract_from_deb(deb_path, dtb_path)
110
rootfs_url = ('http://storage.kernelci.org/images/rootfs/buildroot/'
111
'kci-2019.02/armel/base/rootfs.ext2.xz')
112
diff --git a/tests/acceptance/replay_kernel.py b/tests/acceptance/replay_kernel.py
113
index XXXXXXX..XXXXXXX 100644
114
--- a/tests/acceptance/replay_kernel.py
115
+++ b/tests/acceptance/replay_kernel.py
116
@@ -XXX,XX +XXX,XX @@ def test_arm_cubieboard_initrd(self):
117
:avocado: tags=machine:cubieboard
118
"""
119
deb_url = ('https://apt.armbian.com/pool/main/l/'
120
- 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
121
- deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
122
+ 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
123
+ deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
124
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
125
kernel_path = self.extract_from_deb(deb_path,
126
- '/boot/vmlinuz-4.20.7-sunxi')
127
- dtb_path = '/usr/lib/linux-image-dev-sunxi/sun4i-a10-cubieboard.dtb'
128
+ '/boot/vmlinuz-5.10.16-sunxi')
129
+ dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
130
dtb_path = self.extract_from_deb(deb_path, dtb_path)
131
initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
132
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
133
--
53
--
134
2.20.1
54
2.20.1
135
55
136
56
diff view generated by jsdifflib
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
The image for Armbian 19.11.3 bionic has been removed from the armbian server.
3
Add entries present in ARM DDI 0487F.c (August 2020).
4
Without the image as input the test arm_orangepi_bionic_19_11 cannot run.
5
4
6
This commit removes the test completely and merges the code of the generic function
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
7
do_test_arm_orangepi_uboot_armbian back with the 20.08 test.
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
7
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
9
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
8
Message-id: 20210108185154.8108-6-leif@nuviainc.com
10
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
11
Message-id: 20210310195820.21950-3-nieklinnenbank@gmail.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
10
---
14
tests/acceptance/boot_linux_console.py | 72 ++++++++------------------
11
target/arm/cpu.h | 15 +++++++++++++++
15
1 file changed, 23 insertions(+), 49 deletions(-)
12
1 file changed, 15 insertions(+)
16
13
17
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/acceptance/boot_linux_console.py
16
--- a/target/arm/cpu.h
20
+++ b/tests/acceptance/boot_linux_console.py
17
+++ b/target/arm/cpu.h
21
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_sd(self):
18
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64ISAR1, GPI, 28, 4)
22
# Wait for VM to shut down gracefully
19
FIELD(ID_AA64ISAR1, FRINTTS, 32, 4)
23
self.vm.wait()
20
FIELD(ID_AA64ISAR1, SB, 36, 4)
24
21
FIELD(ID_AA64ISAR1, SPECRES, 40, 4)
25
- def do_test_arm_orangepi_uboot_armbian(self, image_path):
22
+FIELD(ID_AA64ISAR1, BF16, 44, 4)
26
+ @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
23
+FIELD(ID_AA64ISAR1, DGH, 48, 4)
27
+ 'Test artifacts fetched from unreliable apt.armbian.com')
24
+FIELD(ID_AA64ISAR1, I8MM, 52, 4)
28
+ @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
25
29
+ def test_arm_orangepi_bionic_20_08(self):
26
FIELD(ID_AA64PFR0, EL0, 0, 4)
30
+ """
27
FIELD(ID_AA64PFR0, EL1, 4, 4)
31
+ :avocado: tags=arch:arm
28
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64PFR0, ADVSIMD, 20, 4)
32
+ :avocado: tags=machine:orangepi-pc
29
FIELD(ID_AA64PFR0, GIC, 24, 4)
33
+ :avocado: tags=device:sd
30
FIELD(ID_AA64PFR0, RAS, 28, 4)
34
+ """
31
FIELD(ID_AA64PFR0, SVE, 32, 4)
35
+
32
+FIELD(ID_AA64PFR0, SEL2, 36, 4)
36
+ # This test download a 275 MiB compressed image and expand it
33
+FIELD(ID_AA64PFR0, MPAM, 40, 4)
37
+ # to 1036 MiB, but the underlying filesystem is 1552 MiB...
34
+FIELD(ID_AA64PFR0, AMU, 44, 4)
38
+ # As we expand it to 2 GiB we are safe.
35
+FIELD(ID_AA64PFR0, DIT, 48, 4)
39
+
36
+FIELD(ID_AA64PFR0, CSV2, 56, 4)
40
+ image_url = ('https://dl.armbian.com/orangepipc/archive/'
37
+FIELD(ID_AA64PFR0, CSV3, 60, 4)
41
+ 'Armbian_20.08.1_Orangepipc_bionic_current_5.8.5.img.xz')
38
42
+ image_hash = ('b4d6775f5673486329e45a0586bf06b6'
39
FIELD(ID_AA64PFR1, BT, 0, 4)
43
+ 'dbe792199fd182ac6b9c7bb6c7d3e6dd')
40
FIELD(ID_AA64PFR1, SSBS, 4, 4)
44
+ image_path_xz = self.fetch_asset(image_url, asset_hash=image_hash,
41
FIELD(ID_AA64PFR1, MTE, 8, 4)
45
+ algorithm='sha256')
42
FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
46
+ image_path = archive.extract(image_path_xz, self.workdir)
43
+FIELD(ID_AA64PFR1, MPAM_FRAC, 16, 4)
47
+ image_pow2ceil_expand(image_path)
44
48
+
45
FIELD(ID_AA64MMFR0, PARANGE, 0, 4)
49
self.vm.set_console()
46
FIELD(ID_AA64MMFR0, ASIDBITS, 4, 4)
50
self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw',
47
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64MMFR0, TGRAN16_2, 32, 4)
51
'-nic', 'user',
48
FIELD(ID_AA64MMFR0, TGRAN64_2, 36, 4)
52
@@ -XXX,XX +XXX,XX @@ def do_test_arm_orangepi_uboot_armbian(self, image_path):
49
FIELD(ID_AA64MMFR0, TGRAN4_2, 40, 4)
53
'to <orangepipc>')
50
FIELD(ID_AA64MMFR0, EXS, 44, 4)
54
self.wait_for_console_pattern('Starting Load Kernel Modules...')
51
+FIELD(ID_AA64MMFR0, FGT, 56, 4)
55
52
+FIELD(ID_AA64MMFR0, ECV, 60, 4)
56
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
53
57
- 'Test artifacts fetched from unreliable apt.armbian.com')
54
FIELD(ID_AA64MMFR1, HAFDBS, 0, 4)
58
- @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
55
FIELD(ID_AA64MMFR1, VMIDBITS, 4, 4)
59
- @skipUnless(P7ZIP_AVAILABLE, '7z not installed')
56
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64MMFR1, LO, 16, 4)
60
- def test_arm_orangepi_bionic_19_11(self):
57
FIELD(ID_AA64MMFR1, PAN, 20, 4)
61
- """
58
FIELD(ID_AA64MMFR1, SPECSEI, 24, 4)
62
- :avocado: tags=arch:arm
59
FIELD(ID_AA64MMFR1, XNX, 28, 4)
63
- :avocado: tags=machine:orangepi-pc
60
+FIELD(ID_AA64MMFR1, TWED, 32, 4)
64
- :avocado: tags=device:sd
61
+FIELD(ID_AA64MMFR1, ETS, 36, 4)
65
- """
62
66
-
63
FIELD(ID_AA64MMFR2, CNP, 0, 4)
67
- # This test download a 196MB compressed image and expand it to 1GB
64
FIELD(ID_AA64MMFR2, UAO, 4, 4)
68
- image_url = ('https://dl.armbian.com/orangepipc/archive/'
65
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64DFR0, CTX_CMPS, 28, 4)
69
- 'Armbian_19.11.3_Orangepipc_bionic_current_5.3.9.7z')
66
FIELD(ID_AA64DFR0, PMSVER, 32, 4)
70
- image_hash = '196a8ffb72b0123d92cea4a070894813d305c71e'
67
FIELD(ID_AA64DFR0, DOUBLELOCK, 36, 4)
71
- image_path_7z = self.fetch_asset(image_url, asset_hash=image_hash)
68
FIELD(ID_AA64DFR0, TRACEFILT, 40, 4)
72
- image_name = 'Armbian_19.11.3_Orangepipc_bionic_current_5.3.9.img'
69
+FIELD(ID_AA64DFR0, MTPMU, 48, 4)
73
- image_path = os.path.join(self.workdir, image_name)
70
74
- process.run("7z e -o%s %s" % (self.workdir, image_path_7z))
71
FIELD(ID_DFR0, COPDBG, 0, 4)
75
- image_pow2ceil_expand(image_path)
72
FIELD(ID_DFR0, COPSDBG, 4, 4)
76
-
77
- self.do_test_arm_orangepi_uboot_armbian(image_path)
78
-
79
- @skipUnless(os.getenv('ARMBIAN_ARTIFACTS_CACHED'),
80
- 'Test artifacts fetched from unreliable apt.armbian.com')
81
- @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
82
- def test_arm_orangepi_bionic_20_08(self):
83
- """
84
- :avocado: tags=arch:arm
85
- :avocado: tags=machine:orangepi-pc
86
- :avocado: tags=device:sd
87
- """
88
-
89
- # This test download a 275 MiB compressed image and expand it
90
- # to 1036 MiB, but the underlying filesystem is 1552 MiB...
91
- # As we expand it to 2 GiB we are safe.
92
-
93
- image_url = ('https://dl.armbian.com/orangepipc/archive/'
94
- 'Armbian_20.08.1_Orangepipc_bionic_current_5.8.5.img.xz')
95
- image_hash = ('b4d6775f5673486329e45a0586bf06b6'
96
- 'dbe792199fd182ac6b9c7bb6c7d3e6dd')
97
- image_path_xz = self.fetch_asset(image_url, asset_hash=image_hash,
98
- algorithm='sha256')
99
- image_path = archive.extract(image_path_xz, self.workdir)
100
- image_pow2ceil_expand(image_path)
101
-
102
- self.do_test_arm_orangepi_uboot_armbian(image_path)
103
-
104
@skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
105
def test_arm_orangepi_uboot_netbsd9(self):
106
"""
107
--
73
--
108
2.20.1
74
2.20.1
109
75
110
76
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
Prior to commit f2ce39b4f067 a MachineClass kvm_type method
3
Add entries present in ARM DDI 0487F.c (August 2020).
4
only needed to be registered to ensure it would be executed.
5
With commit f2ce39b4f067 a kvm-type machine property must also
6
be specified. hw/arm/virt relies on the kvm_type method to pass
7
its selected IPA limit to KVM, but this is not exposed as a
8
machine property. Restore the previous functionality of invoking
9
kvm_type when it's present.
10
4
11
Fixes: f2ce39b4f067 ("vl: make qemu_get_machine_opts static")
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
12
Signed-off-by: Andrew Jones <drjones@redhat.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Eric Auger <eric.auger@redhat.com>
7
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
14
Message-id: 20210310135218.255205-2-drjones@redhat.com
8
Message-id: 20210108185154.8108-7-leif@nuviainc.com
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
10
---
17
include/hw/boards.h | 1 +
11
target/arm/cpu.h | 28 ++++++++++++++++++++++++++++
18
accel/kvm/kvm-all.c | 2 ++
12
1 file changed, 28 insertions(+)
19
2 files changed, 3 insertions(+)
20
13
21
diff --git a/include/hw/boards.h b/include/hw/boards.h
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
22
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/boards.h
16
--- a/target/arm/cpu.h
24
+++ b/include/hw/boards.h
17
+++ b/target/arm/cpu.h
25
@@ -XXX,XX +XXX,XX @@ typedef struct {
18
@@ -XXX,XX +XXX,XX @@ FIELD(ID_ISAR6, DP, 4, 4)
26
* @kvm_type:
19
FIELD(ID_ISAR6, FHM, 8, 4)
27
* Return the type of KVM corresponding to the kvm-type string option or
20
FIELD(ID_ISAR6, SB, 12, 4)
28
* computed based on other criteria such as the host kernel capabilities.
21
FIELD(ID_ISAR6, SPECRES, 16, 4)
29
+ * kvm-type may be NULL if it is not needed.
22
+FIELD(ID_ISAR6, BF16, 20, 4)
30
* @numa_mem_supported:
23
+FIELD(ID_ISAR6, I8MM, 24, 4)
31
* true if '--numa node.mem' option is supported and false otherwise
24
32
* @smp_parse:
25
FIELD(ID_MMFR0, VMSA, 0, 4)
33
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
26
FIELD(ID_MMFR0, PMSA, 4, 4)
34
index XXXXXXX..XXXXXXX 100644
27
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR0, AUXREG, 20, 4)
35
--- a/accel/kvm/kvm-all.c
28
FIELD(ID_MMFR0, FCSE, 24, 4)
36
+++ b/accel/kvm/kvm-all.c
29
FIELD(ID_MMFR0, INNERSHR, 28, 4)
37
@@ -XXX,XX +XXX,XX @@ static int kvm_init(MachineState *ms)
30
38
"kvm-type",
31
+FIELD(ID_MMFR1, L1HVDVA, 0, 4)
39
&error_abort);
32
+FIELD(ID_MMFR1, L1UNIVA, 4, 4)
40
type = mc->kvm_type(ms, kvm_type);
33
+FIELD(ID_MMFR1, L1HVDSW, 8, 4)
41
+ } else if (mc->kvm_type) {
34
+FIELD(ID_MMFR1, L1UNISW, 12, 4)
42
+ type = mc->kvm_type(ms, NULL);
35
+FIELD(ID_MMFR1, L1HVD, 16, 4)
43
}
36
+FIELD(ID_MMFR1, L1UNI, 20, 4)
44
37
+FIELD(ID_MMFR1, L1TSTCLN, 24, 4)
45
do {
38
+FIELD(ID_MMFR1, BPRED, 28, 4)
39
+
40
+FIELD(ID_MMFR2, L1HVDFG, 0, 4)
41
+FIELD(ID_MMFR2, L1HVDBG, 4, 4)
42
+FIELD(ID_MMFR2, L1HVDRNG, 8, 4)
43
+FIELD(ID_MMFR2, HVDTLB, 12, 4)
44
+FIELD(ID_MMFR2, UNITLB, 16, 4)
45
+FIELD(ID_MMFR2, MEMBARR, 20, 4)
46
+FIELD(ID_MMFR2, WFISTALL, 24, 4)
47
+FIELD(ID_MMFR2, HWACCFLG, 28, 4)
48
+
49
FIELD(ID_MMFR3, CMAINTVA, 0, 4)
50
FIELD(ID_MMFR3, CMAINTSW, 4, 4)
51
FIELD(ID_MMFR3, BPMAINT, 8, 4)
52
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR4, LSM, 20, 4)
53
FIELD(ID_MMFR4, CCIDX, 24, 4)
54
FIELD(ID_MMFR4, EVT, 28, 4)
55
56
+FIELD(ID_MMFR5, ETS, 0, 4)
57
+
58
FIELD(ID_PFR0, STATE0, 0, 4)
59
FIELD(ID_PFR0, STATE1, 4, 4)
60
FIELD(ID_PFR0, STATE2, 8, 4)
61
@@ -XXX,XX +XXX,XX @@ FIELD(ID_PFR1, SEC_FRAC, 20, 4)
62
FIELD(ID_PFR1, VIRT_FRAC, 24, 4)
63
FIELD(ID_PFR1, GIC, 28, 4)
64
65
+FIELD(ID_PFR2, CSV3, 0, 4)
66
+FIELD(ID_PFR2, SSBS, 4, 4)
67
+FIELD(ID_PFR2, RAS_FRAC, 8, 4)
68
+
69
FIELD(ID_AA64ISAR0, AES, 4, 4)
70
FIELD(ID_AA64ISAR0, SHA1, 8, 4)
71
FIELD(ID_AA64ISAR0, SHA2, 12, 4)
72
@@ -XXX,XX +XXX,XX @@ FIELD(ID_DFR0, MPROFDBG, 20, 4)
73
FIELD(ID_DFR0, PERFMON, 24, 4)
74
FIELD(ID_DFR0, TRACEFILT, 28, 4)
75
76
+FIELD(ID_DFR1, MTPMU, 0, 4)
77
+
78
FIELD(DBGDIDR, SE_IMP, 12, 1)
79
FIELD(DBGDIDR, NSUHD_IMP, 14, 1)
80
FIELD(DBGDIDR, VERSION, 16, 4)
46
--
81
--
47
2.20.1
82
2.20.1
48
83
49
84
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Roman Bolshakov <r.bolshakov@yadro.com>
2
2
3
If the asid is not set, do not attempt to locate the key directly
3
QEMU documentation can't be opened if QEMU is run from build tree
4
as all inserted keys have a valid asid.
4
because executables are placed in the top of build tree after conversion
5
to meson.
5
6
6
Use g_hash_table_foreach_remove instead.
7
Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com>
7
8
Reported-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Eric Auger <eric.auger@redhat.com>
9
Message-id: 20210108213815.64678-1-r.bolshakov@yadro.com
9
Message-id: 20210309102742.30442-5-eric.auger@redhat.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
12
---
13
hw/arm/smmu-common.c | 2 +-
13
ui/cocoa.m | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
15
16
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
16
diff --git a/ui/cocoa.m b/ui/cocoa.m
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/smmu-common.c
18
--- a/ui/cocoa.m
19
+++ b/hw/arm/smmu-common.c
19
+++ b/ui/cocoa.m
20
@@ -XXX,XX +XXX,XX @@ inline void
20
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
21
smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova,
21
- (void) openDocumentation: (NSString *) filename
22
uint8_t tg, uint64_t num_pages, uint8_t ttl)
23
{
22
{
24
- if (ttl && (num_pages == 1)) {
23
/* Where to look for local files */
25
+ if (ttl && (num_pages == 1) && (asid >= 0)) {
24
- NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"../docs/"};
26
SMMUIOTLBKey key = smmu_get_iotlb_key(asid, iova, tg, ttl);
25
+ NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"docs/"};
27
26
NSString *full_file_path;
28
g_hash_table_remove(s->iotlb, &key);
27
28
/* iterate thru the possible paths until the file is found */
29
--
29
--
30
2.20.1
30
2.20.1
31
31
32
32
diff view generated by jsdifflib
1
The template header is now included only once; just inline its contents
1
In commit 1982e1602d15 we added a new qemu-storage-daemon(1) manpage.
2
in hw/display/pxa2xx_lcd.c.
2
At the moment new manpages have to be listed both in the conf.py for
3
Sphinx and also in docs/meson.build for Meson. We forgot the second
4
of those -- correct the omission.
3
5
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Message-id: 20210211141515.8755-10-peter.maydell@linaro.org
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Message-id: 20210108161416.21129-2-peter.maydell@linaro.org
7
---
10
---
8
hw/display/pxa2xx_template.h | 434 -----------------------------------
11
docs/meson.build | 1 +
9
hw/display/pxa2xx_lcd.c | 427 +++++++++++++++++++++++++++++++++-
12
1 file changed, 1 insertion(+)
10
2 files changed, 425 insertions(+), 436 deletions(-)
11
delete mode 100644 hw/display/pxa2xx_template.h
12
13
13
diff --git a/hw/display/pxa2xx_template.h b/hw/display/pxa2xx_template.h
14
diff --git a/docs/meson.build b/docs/meson.build
14
deleted file mode 100644
15
index XXXXXXX..XXXXXXX
16
--- a/hw/display/pxa2xx_template.h
17
+++ /dev/null
18
@@ -XXX,XX +XXX,XX @@
19
-/*
20
- * Intel XScale PXA255/270 LCDC emulation.
21
- *
22
- * Copyright (c) 2006 Openedhand Ltd.
23
- * Written by Andrzej Zaborowski <balrog@zabor.org>
24
- *
25
- * This code is licensed under the GPLv2.
26
- *
27
- * Framebuffer format conversion routines.
28
- */
29
-
30
-# define SKIP_PIXEL(to) do { to += deststep; } while (0)
31
-# define COPY_PIXEL(to, from) \
32
- do { \
33
- *(uint32_t *) to = from; \
34
- SKIP_PIXEL(to); \
35
- } while (0)
36
-
37
-#ifdef HOST_WORDS_BIGENDIAN
38
-# define SWAP_WORDS 1
39
-#endif
40
-
41
-#define FN_2(x) FN(x + 1) FN(x)
42
-#define FN_4(x) FN_2(x + 2) FN_2(x)
43
-
44
-static void pxa2xx_draw_line2(void *opaque, uint8_t *dest, const uint8_t *src,
45
- int width, int deststep)
46
-{
47
- uint32_t *palette = opaque;
48
- uint32_t data;
49
- while (width > 0) {
50
- data = *(uint32_t *) src;
51
-#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 2)) & 3]);
52
-#ifdef SWAP_WORDS
53
- FN_4(12)
54
- FN_4(8)
55
- FN_4(4)
56
- FN_4(0)
57
-#else
58
- FN_4(0)
59
- FN_4(4)
60
- FN_4(8)
61
- FN_4(12)
62
-#endif
63
-#undef FN
64
- width -= 16;
65
- src += 4;
66
- }
67
-}
68
-
69
-static void pxa2xx_draw_line4(void *opaque, uint8_t *dest, const uint8_t *src,
70
- int width, int deststep)
71
-{
72
- uint32_t *palette = opaque;
73
- uint32_t data;
74
- while (width > 0) {
75
- data = *(uint32_t *) src;
76
-#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 4)) & 0xf]);
77
-#ifdef SWAP_WORDS
78
- FN_2(6)
79
- FN_2(4)
80
- FN_2(2)
81
- FN_2(0)
82
-#else
83
- FN_2(0)
84
- FN_2(2)
85
- FN_2(4)
86
- FN_2(6)
87
-#endif
88
-#undef FN
89
- width -= 8;
90
- src += 4;
91
- }
92
-}
93
-
94
-static void pxa2xx_draw_line8(void *opaque, uint8_t *dest, const uint8_t *src,
95
- int width, int deststep)
96
-{
97
- uint32_t *palette = opaque;
98
- uint32_t data;
99
- while (width > 0) {
100
- data = *(uint32_t *) src;
101
-#define FN(x) COPY_PIXEL(dest, palette[(data >> (x)) & 0xff]);
102
-#ifdef SWAP_WORDS
103
- FN(24)
104
- FN(16)
105
- FN(8)
106
- FN(0)
107
-#else
108
- FN(0)
109
- FN(8)
110
- FN(16)
111
- FN(24)
112
-#endif
113
-#undef FN
114
- width -= 4;
115
- src += 4;
116
- }
117
-}
118
-
119
-static void pxa2xx_draw_line16(void *opaque, uint8_t *dest, const uint8_t *src,
120
- int width, int deststep)
121
-{
122
- uint32_t data;
123
- unsigned int r, g, b;
124
- while (width > 0) {
125
- data = *(uint32_t *) src;
126
-#ifdef SWAP_WORDS
127
- data = bswap32(data);
128
-#endif
129
- b = (data & 0x1f) << 3;
130
- data >>= 5;
131
- g = (data & 0x3f) << 2;
132
- data >>= 6;
133
- r = (data & 0x1f) << 3;
134
- data >>= 5;
135
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
136
- b = (data & 0x1f) << 3;
137
- data >>= 5;
138
- g = (data & 0x3f) << 2;
139
- data >>= 6;
140
- r = (data & 0x1f) << 3;
141
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
142
- width -= 2;
143
- src += 4;
144
- }
145
-}
146
-
147
-static void pxa2xx_draw_line16t(void *opaque, uint8_t *dest, const uint8_t *src,
148
- int width, int deststep)
149
-{
150
- uint32_t data;
151
- unsigned int r, g, b;
152
- while (width > 0) {
153
- data = *(uint32_t *) src;
154
-#ifdef SWAP_WORDS
155
- data = bswap32(data);
156
-#endif
157
- b = (data & 0x1f) << 3;
158
- data >>= 5;
159
- g = (data & 0x1f) << 3;
160
- data >>= 5;
161
- r = (data & 0x1f) << 3;
162
- data >>= 5;
163
- if (data & 1) {
164
- SKIP_PIXEL(dest);
165
- } else {
166
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
167
- }
168
- data >>= 1;
169
- b = (data & 0x1f) << 3;
170
- data >>= 5;
171
- g = (data & 0x1f) << 3;
172
- data >>= 5;
173
- r = (data & 0x1f) << 3;
174
- data >>= 5;
175
- if (data & 1) {
176
- SKIP_PIXEL(dest);
177
- } else {
178
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
179
- }
180
- width -= 2;
181
- src += 4;
182
- }
183
-}
184
-
185
-static void pxa2xx_draw_line18(void *opaque, uint8_t *dest, const uint8_t *src,
186
- int width, int deststep)
187
-{
188
- uint32_t data;
189
- unsigned int r, g, b;
190
- while (width > 0) {
191
- data = *(uint32_t *) src;
192
-#ifdef SWAP_WORDS
193
- data = bswap32(data);
194
-#endif
195
- b = (data & 0x3f) << 2;
196
- data >>= 6;
197
- g = (data & 0x3f) << 2;
198
- data >>= 6;
199
- r = (data & 0x3f) << 2;
200
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
201
- width -= 1;
202
- src += 4;
203
- }
204
-}
205
-
206
-/* The wicked packed format */
207
-static void pxa2xx_draw_line18p(void *opaque, uint8_t *dest, const uint8_t *src,
208
- int width, int deststep)
209
-{
210
- uint32_t data[3];
211
- unsigned int r, g, b;
212
- while (width > 0) {
213
- data[0] = *(uint32_t *) src;
214
- src += 4;
215
- data[1] = *(uint32_t *) src;
216
- src += 4;
217
- data[2] = *(uint32_t *) src;
218
- src += 4;
219
-#ifdef SWAP_WORDS
220
- data[0] = bswap32(data[0]);
221
- data[1] = bswap32(data[1]);
222
- data[2] = bswap32(data[2]);
223
-#endif
224
- b = (data[0] & 0x3f) << 2;
225
- data[0] >>= 6;
226
- g = (data[0] & 0x3f) << 2;
227
- data[0] >>= 6;
228
- r = (data[0] & 0x3f) << 2;
229
- data[0] >>= 12;
230
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
231
- b = (data[0] & 0x3f) << 2;
232
- data[0] >>= 6;
233
- g = ((data[1] & 0xf) << 4) | (data[0] << 2);
234
- data[1] >>= 4;
235
- r = (data[1] & 0x3f) << 2;
236
- data[1] >>= 12;
237
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
238
- b = (data[1] & 0x3f) << 2;
239
- data[1] >>= 6;
240
- g = (data[1] & 0x3f) << 2;
241
- data[1] >>= 6;
242
- r = ((data[2] & 0x3) << 6) | (data[1] << 2);
243
- data[2] >>= 8;
244
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
245
- b = (data[2] & 0x3f) << 2;
246
- data[2] >>= 6;
247
- g = (data[2] & 0x3f) << 2;
248
- data[2] >>= 6;
249
- r = data[2] << 2;
250
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
251
- width -= 4;
252
- }
253
-}
254
-
255
-static void pxa2xx_draw_line19(void *opaque, uint8_t *dest, const uint8_t *src,
256
- int width, int deststep)
257
-{
258
- uint32_t data;
259
- unsigned int r, g, b;
260
- while (width > 0) {
261
- data = *(uint32_t *) src;
262
-#ifdef SWAP_WORDS
263
- data = bswap32(data);
264
-#endif
265
- b = (data & 0x3f) << 2;
266
- data >>= 6;
267
- g = (data & 0x3f) << 2;
268
- data >>= 6;
269
- r = (data & 0x3f) << 2;
270
- data >>= 6;
271
- if (data & 1) {
272
- SKIP_PIXEL(dest);
273
- } else {
274
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
275
- }
276
- width -= 1;
277
- src += 4;
278
- }
279
-}
280
-
281
-/* The wicked packed format */
282
-static void pxa2xx_draw_line19p(void *opaque, uint8_t *dest, const uint8_t *src,
283
- int width, int deststep)
284
-{
285
- uint32_t data[3];
286
- unsigned int r, g, b;
287
- while (width > 0) {
288
- data[0] = *(uint32_t *) src;
289
- src += 4;
290
- data[1] = *(uint32_t *) src;
291
- src += 4;
292
- data[2] = *(uint32_t *) src;
293
- src += 4;
294
-# ifdef SWAP_WORDS
295
- data[0] = bswap32(data[0]);
296
- data[1] = bswap32(data[1]);
297
- data[2] = bswap32(data[2]);
298
-# endif
299
- b = (data[0] & 0x3f) << 2;
300
- data[0] >>= 6;
301
- g = (data[0] & 0x3f) << 2;
302
- data[0] >>= 6;
303
- r = (data[0] & 0x3f) << 2;
304
- data[0] >>= 6;
305
- if (data[0] & 1) {
306
- SKIP_PIXEL(dest);
307
- } else {
308
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
309
- }
310
- data[0] >>= 6;
311
- b = (data[0] & 0x3f) << 2;
312
- data[0] >>= 6;
313
- g = ((data[1] & 0xf) << 4) | (data[0] << 2);
314
- data[1] >>= 4;
315
- r = (data[1] & 0x3f) << 2;
316
- data[1] >>= 6;
317
- if (data[1] & 1) {
318
- SKIP_PIXEL(dest);
319
- } else {
320
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
321
- }
322
- data[1] >>= 6;
323
- b = (data[1] & 0x3f) << 2;
324
- data[1] >>= 6;
325
- g = (data[1] & 0x3f) << 2;
326
- data[1] >>= 6;
327
- r = ((data[2] & 0x3) << 6) | (data[1] << 2);
328
- data[2] >>= 2;
329
- if (data[2] & 1) {
330
- SKIP_PIXEL(dest);
331
- } else {
332
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
333
- }
334
- data[2] >>= 6;
335
- b = (data[2] & 0x3f) << 2;
336
- data[2] >>= 6;
337
- g = (data[2] & 0x3f) << 2;
338
- data[2] >>= 6;
339
- r = data[2] << 2;
340
- data[2] >>= 6;
341
- if (data[2] & 1) {
342
- SKIP_PIXEL(dest);
343
- } else {
344
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
345
- }
346
- width -= 4;
347
- }
348
-}
349
-
350
-static void pxa2xx_draw_line24(void *opaque, uint8_t *dest, const uint8_t *src,
351
- int width, int deststep)
352
-{
353
- uint32_t data;
354
- unsigned int r, g, b;
355
- while (width > 0) {
356
- data = *(uint32_t *) src;
357
-#ifdef SWAP_WORDS
358
- data = bswap32(data);
359
-#endif
360
- b = data & 0xff;
361
- data >>= 8;
362
- g = data & 0xff;
363
- data >>= 8;
364
- r = data & 0xff;
365
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
366
- width -= 1;
367
- src += 4;
368
- }
369
-}
370
-
371
-static void pxa2xx_draw_line24t(void *opaque, uint8_t *dest, const uint8_t *src,
372
- int width, int deststep)
373
-{
374
- uint32_t data;
375
- unsigned int r, g, b;
376
- while (width > 0) {
377
- data = *(uint32_t *) src;
378
-#ifdef SWAP_WORDS
379
- data = bswap32(data);
380
-#endif
381
- b = (data & 0x7f) << 1;
382
- data >>= 7;
383
- g = data & 0xff;
384
- data >>= 8;
385
- r = data & 0xff;
386
- data >>= 8;
387
- if (data & 1) {
388
- SKIP_PIXEL(dest);
389
- } else {
390
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
391
- }
392
- width -= 1;
393
- src += 4;
394
- }
395
-}
396
-
397
-static void pxa2xx_draw_line25(void *opaque, uint8_t *dest, const uint8_t *src,
398
- int width, int deststep)
399
-{
400
- uint32_t data;
401
- unsigned int r, g, b;
402
- while (width > 0) {
403
- data = *(uint32_t *) src;
404
-#ifdef SWAP_WORDS
405
- data = bswap32(data);
406
-#endif
407
- b = data & 0xff;
408
- data >>= 8;
409
- g = data & 0xff;
410
- data >>= 8;
411
- r = data & 0xff;
412
- data >>= 8;
413
- if (data & 1) {
414
- SKIP_PIXEL(dest);
415
- } else {
416
- COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
417
- }
418
- width -= 1;
419
- src += 4;
420
- }
421
-}
422
-
423
-/* Overlay planes disabled, no transparency */
424
-static drawfn pxa2xx_draw_fn_32[16] = {
425
- [0 ... 0xf] = NULL,
426
- [pxa_lcdc_2bpp] = pxa2xx_draw_line2,
427
- [pxa_lcdc_4bpp] = pxa2xx_draw_line4,
428
- [pxa_lcdc_8bpp] = pxa2xx_draw_line8,
429
- [pxa_lcdc_16bpp] = pxa2xx_draw_line16,
430
- [pxa_lcdc_18bpp] = pxa2xx_draw_line18,
431
- [pxa_lcdc_18pbpp] = pxa2xx_draw_line18p,
432
- [pxa_lcdc_24bpp] = pxa2xx_draw_line24,
433
-};
434
-
435
-/* Overlay planes enabled, transparency used */
436
-static drawfn pxa2xx_draw_fn_32t[16] = {
437
- [0 ... 0xf] = NULL,
438
- [pxa_lcdc_4bpp] = pxa2xx_draw_line4,
439
- [pxa_lcdc_8bpp] = pxa2xx_draw_line8,
440
- [pxa_lcdc_16bpp] = pxa2xx_draw_line16t,
441
- [pxa_lcdc_19bpp] = pxa2xx_draw_line19,
442
- [pxa_lcdc_19pbpp] = pxa2xx_draw_line19p,
443
- [pxa_lcdc_24bpp] = pxa2xx_draw_line24t,
444
- [pxa_lcdc_25bpp] = pxa2xx_draw_line25,
445
-};
446
-
447
-#undef COPY_PIXEL
448
-#undef SKIP_PIXEL
449
-
450
-#ifdef SWAP_WORDS
451
-# undef SWAP_WORDS
452
-#endif
453
diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c
454
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
455
--- a/hw/display/pxa2xx_lcd.c
16
--- a/docs/meson.build
456
+++ b/hw/display/pxa2xx_lcd.c
17
+++ b/docs/meson.build
457
@@ -XXX,XX +XXX,XX @@ typedef struct QEMU_PACKED {
18
@@ -XXX,XX +XXX,XX @@ if build_docs
458
/* Size of a pixel in the QEMU UI output surface, in bytes */
19
'qemu-img.1': (have_tools ? 'man1' : ''),
459
#define DEST_PIXEL_WIDTH 4
20
'qemu-nbd.8': (have_tools ? 'man8' : ''),
460
21
'qemu-pr-helper.8': (have_tools ? 'man8' : ''),
461
-#define BITS 32
22
+ 'qemu-storage-daemon.1': (have_tools ? 'man1' : ''),
462
-#include "pxa2xx_template.h"
23
'qemu-trace-stap.1': (config_host.has_key('CONFIG_TRACE_SYSTEMTAP') ? 'man1' : ''),
463
+/* Line drawing code to handle the various possible guest pixel formats */
24
'virtfs-proxy-helper.1': (have_virtfs_proxy_helper ? 'man1' : ''),
464
+
25
'virtiofsd.1': (have_virtiofsd ? 'man1' : ''),
465
+# define SKIP_PIXEL(to) do { to += deststep; } while (0)
466
+# define COPY_PIXEL(to, from) \
467
+ do { \
468
+ *(uint32_t *) to = from; \
469
+ SKIP_PIXEL(to); \
470
+ } while (0)
471
+
472
+#ifdef HOST_WORDS_BIGENDIAN
473
+# define SWAP_WORDS 1
474
+#endif
475
+
476
+#define FN_2(x) FN(x + 1) FN(x)
477
+#define FN_4(x) FN_2(x + 2) FN_2(x)
478
+
479
+static void pxa2xx_draw_line2(void *opaque, uint8_t *dest, const uint8_t *src,
480
+ int width, int deststep)
481
+{
482
+ uint32_t *palette = opaque;
483
+ uint32_t data;
484
+ while (width > 0) {
485
+ data = *(uint32_t *) src;
486
+#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 2)) & 3]);
487
+#ifdef SWAP_WORDS
488
+ FN_4(12)
489
+ FN_4(8)
490
+ FN_4(4)
491
+ FN_4(0)
492
+#else
493
+ FN_4(0)
494
+ FN_4(4)
495
+ FN_4(8)
496
+ FN_4(12)
497
+#endif
498
+#undef FN
499
+ width -= 16;
500
+ src += 4;
501
+ }
502
+}
503
+
504
+static void pxa2xx_draw_line4(void *opaque, uint8_t *dest, const uint8_t *src,
505
+ int width, int deststep)
506
+{
507
+ uint32_t *palette = opaque;
508
+ uint32_t data;
509
+ while (width > 0) {
510
+ data = *(uint32_t *) src;
511
+#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 4)) & 0xf]);
512
+#ifdef SWAP_WORDS
513
+ FN_2(6)
514
+ FN_2(4)
515
+ FN_2(2)
516
+ FN_2(0)
517
+#else
518
+ FN_2(0)
519
+ FN_2(2)
520
+ FN_2(4)
521
+ FN_2(6)
522
+#endif
523
+#undef FN
524
+ width -= 8;
525
+ src += 4;
526
+ }
527
+}
528
+
529
+static void pxa2xx_draw_line8(void *opaque, uint8_t *dest, const uint8_t *src,
530
+ int width, int deststep)
531
+{
532
+ uint32_t *palette = opaque;
533
+ uint32_t data;
534
+ while (width > 0) {
535
+ data = *(uint32_t *) src;
536
+#define FN(x) COPY_PIXEL(dest, palette[(data >> (x)) & 0xff]);
537
+#ifdef SWAP_WORDS
538
+ FN(24)
539
+ FN(16)
540
+ FN(8)
541
+ FN(0)
542
+#else
543
+ FN(0)
544
+ FN(8)
545
+ FN(16)
546
+ FN(24)
547
+#endif
548
+#undef FN
549
+ width -= 4;
550
+ src += 4;
551
+ }
552
+}
553
+
554
+static void pxa2xx_draw_line16(void *opaque, uint8_t *dest, const uint8_t *src,
555
+ int width, int deststep)
556
+{
557
+ uint32_t data;
558
+ unsigned int r, g, b;
559
+ while (width > 0) {
560
+ data = *(uint32_t *) src;
561
+#ifdef SWAP_WORDS
562
+ data = bswap32(data);
563
+#endif
564
+ b = (data & 0x1f) << 3;
565
+ data >>= 5;
566
+ g = (data & 0x3f) << 2;
567
+ data >>= 6;
568
+ r = (data & 0x1f) << 3;
569
+ data >>= 5;
570
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
571
+ b = (data & 0x1f) << 3;
572
+ data >>= 5;
573
+ g = (data & 0x3f) << 2;
574
+ data >>= 6;
575
+ r = (data & 0x1f) << 3;
576
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
577
+ width -= 2;
578
+ src += 4;
579
+ }
580
+}
581
+
582
+static void pxa2xx_draw_line16t(void *opaque, uint8_t *dest, const uint8_t *src,
583
+ int width, int deststep)
584
+{
585
+ uint32_t data;
586
+ unsigned int r, g, b;
587
+ while (width > 0) {
588
+ data = *(uint32_t *) src;
589
+#ifdef SWAP_WORDS
590
+ data = bswap32(data);
591
+#endif
592
+ b = (data & 0x1f) << 3;
593
+ data >>= 5;
594
+ g = (data & 0x1f) << 3;
595
+ data >>= 5;
596
+ r = (data & 0x1f) << 3;
597
+ data >>= 5;
598
+ if (data & 1) {
599
+ SKIP_PIXEL(dest);
600
+ } else {
601
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
602
+ }
603
+ data >>= 1;
604
+ b = (data & 0x1f) << 3;
605
+ data >>= 5;
606
+ g = (data & 0x1f) << 3;
607
+ data >>= 5;
608
+ r = (data & 0x1f) << 3;
609
+ data >>= 5;
610
+ if (data & 1) {
611
+ SKIP_PIXEL(dest);
612
+ } else {
613
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
614
+ }
615
+ width -= 2;
616
+ src += 4;
617
+ }
618
+}
619
+
620
+static void pxa2xx_draw_line18(void *opaque, uint8_t *dest, const uint8_t *src,
621
+ int width, int deststep)
622
+{
623
+ uint32_t data;
624
+ unsigned int r, g, b;
625
+ while (width > 0) {
626
+ data = *(uint32_t *) src;
627
+#ifdef SWAP_WORDS
628
+ data = bswap32(data);
629
+#endif
630
+ b = (data & 0x3f) << 2;
631
+ data >>= 6;
632
+ g = (data & 0x3f) << 2;
633
+ data >>= 6;
634
+ r = (data & 0x3f) << 2;
635
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
636
+ width -= 1;
637
+ src += 4;
638
+ }
639
+}
640
+
641
+/* The wicked packed format */
642
+static void pxa2xx_draw_line18p(void *opaque, uint8_t *dest, const uint8_t *src,
643
+ int width, int deststep)
644
+{
645
+ uint32_t data[3];
646
+ unsigned int r, g, b;
647
+ while (width > 0) {
648
+ data[0] = *(uint32_t *) src;
649
+ src += 4;
650
+ data[1] = *(uint32_t *) src;
651
+ src += 4;
652
+ data[2] = *(uint32_t *) src;
653
+ src += 4;
654
+#ifdef SWAP_WORDS
655
+ data[0] = bswap32(data[0]);
656
+ data[1] = bswap32(data[1]);
657
+ data[2] = bswap32(data[2]);
658
+#endif
659
+ b = (data[0] & 0x3f) << 2;
660
+ data[0] >>= 6;
661
+ g = (data[0] & 0x3f) << 2;
662
+ data[0] >>= 6;
663
+ r = (data[0] & 0x3f) << 2;
664
+ data[0] >>= 12;
665
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
666
+ b = (data[0] & 0x3f) << 2;
667
+ data[0] >>= 6;
668
+ g = ((data[1] & 0xf) << 4) | (data[0] << 2);
669
+ data[1] >>= 4;
670
+ r = (data[1] & 0x3f) << 2;
671
+ data[1] >>= 12;
672
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
673
+ b = (data[1] & 0x3f) << 2;
674
+ data[1] >>= 6;
675
+ g = (data[1] & 0x3f) << 2;
676
+ data[1] >>= 6;
677
+ r = ((data[2] & 0x3) << 6) | (data[1] << 2);
678
+ data[2] >>= 8;
679
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
680
+ b = (data[2] & 0x3f) << 2;
681
+ data[2] >>= 6;
682
+ g = (data[2] & 0x3f) << 2;
683
+ data[2] >>= 6;
684
+ r = data[2] << 2;
685
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
686
+ width -= 4;
687
+ }
688
+}
689
+
690
+static void pxa2xx_draw_line19(void *opaque, uint8_t *dest, const uint8_t *src,
691
+ int width, int deststep)
692
+{
693
+ uint32_t data;
694
+ unsigned int r, g, b;
695
+ while (width > 0) {
696
+ data = *(uint32_t *) src;
697
+#ifdef SWAP_WORDS
698
+ data = bswap32(data);
699
+#endif
700
+ b = (data & 0x3f) << 2;
701
+ data >>= 6;
702
+ g = (data & 0x3f) << 2;
703
+ data >>= 6;
704
+ r = (data & 0x3f) << 2;
705
+ data >>= 6;
706
+ if (data & 1) {
707
+ SKIP_PIXEL(dest);
708
+ } else {
709
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
710
+ }
711
+ width -= 1;
712
+ src += 4;
713
+ }
714
+}
715
+
716
+/* The wicked packed format */
717
+static void pxa2xx_draw_line19p(void *opaque, uint8_t *dest, const uint8_t *src,
718
+ int width, int deststep)
719
+{
720
+ uint32_t data[3];
721
+ unsigned int r, g, b;
722
+ while (width > 0) {
723
+ data[0] = *(uint32_t *) src;
724
+ src += 4;
725
+ data[1] = *(uint32_t *) src;
726
+ src += 4;
727
+ data[2] = *(uint32_t *) src;
728
+ src += 4;
729
+# ifdef SWAP_WORDS
730
+ data[0] = bswap32(data[0]);
731
+ data[1] = bswap32(data[1]);
732
+ data[2] = bswap32(data[2]);
733
+# endif
734
+ b = (data[0] & 0x3f) << 2;
735
+ data[0] >>= 6;
736
+ g = (data[0] & 0x3f) << 2;
737
+ data[0] >>= 6;
738
+ r = (data[0] & 0x3f) << 2;
739
+ data[0] >>= 6;
740
+ if (data[0] & 1) {
741
+ SKIP_PIXEL(dest);
742
+ } else {
743
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
744
+ }
745
+ data[0] >>= 6;
746
+ b = (data[0] & 0x3f) << 2;
747
+ data[0] >>= 6;
748
+ g = ((data[1] & 0xf) << 4) | (data[0] << 2);
749
+ data[1] >>= 4;
750
+ r = (data[1] & 0x3f) << 2;
751
+ data[1] >>= 6;
752
+ if (data[1] & 1) {
753
+ SKIP_PIXEL(dest);
754
+ } else {
755
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
756
+ }
757
+ data[1] >>= 6;
758
+ b = (data[1] & 0x3f) << 2;
759
+ data[1] >>= 6;
760
+ g = (data[1] & 0x3f) << 2;
761
+ data[1] >>= 6;
762
+ r = ((data[2] & 0x3) << 6) | (data[1] << 2);
763
+ data[2] >>= 2;
764
+ if (data[2] & 1) {
765
+ SKIP_PIXEL(dest);
766
+ } else {
767
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
768
+ }
769
+ data[2] >>= 6;
770
+ b = (data[2] & 0x3f) << 2;
771
+ data[2] >>= 6;
772
+ g = (data[2] & 0x3f) << 2;
773
+ data[2] >>= 6;
774
+ r = data[2] << 2;
775
+ data[2] >>= 6;
776
+ if (data[2] & 1) {
777
+ SKIP_PIXEL(dest);
778
+ } else {
779
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
780
+ }
781
+ width -= 4;
782
+ }
783
+}
784
+
785
+static void pxa2xx_draw_line24(void *opaque, uint8_t *dest, const uint8_t *src,
786
+ int width, int deststep)
787
+{
788
+ uint32_t data;
789
+ unsigned int r, g, b;
790
+ while (width > 0) {
791
+ data = *(uint32_t *) src;
792
+#ifdef SWAP_WORDS
793
+ data = bswap32(data);
794
+#endif
795
+ b = data & 0xff;
796
+ data >>= 8;
797
+ g = data & 0xff;
798
+ data >>= 8;
799
+ r = data & 0xff;
800
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
801
+ width -= 1;
802
+ src += 4;
803
+ }
804
+}
805
+
806
+static void pxa2xx_draw_line24t(void *opaque, uint8_t *dest, const uint8_t *src,
807
+ int width, int deststep)
808
+{
809
+ uint32_t data;
810
+ unsigned int r, g, b;
811
+ while (width > 0) {
812
+ data = *(uint32_t *) src;
813
+#ifdef SWAP_WORDS
814
+ data = bswap32(data);
815
+#endif
816
+ b = (data & 0x7f) << 1;
817
+ data >>= 7;
818
+ g = data & 0xff;
819
+ data >>= 8;
820
+ r = data & 0xff;
821
+ data >>= 8;
822
+ if (data & 1) {
823
+ SKIP_PIXEL(dest);
824
+ } else {
825
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
826
+ }
827
+ width -= 1;
828
+ src += 4;
829
+ }
830
+}
831
+
832
+static void pxa2xx_draw_line25(void *opaque, uint8_t *dest, const uint8_t *src,
833
+ int width, int deststep)
834
+{
835
+ uint32_t data;
836
+ unsigned int r, g, b;
837
+ while (width > 0) {
838
+ data = *(uint32_t *) src;
839
+#ifdef SWAP_WORDS
840
+ data = bswap32(data);
841
+#endif
842
+ b = data & 0xff;
843
+ data >>= 8;
844
+ g = data & 0xff;
845
+ data >>= 8;
846
+ r = data & 0xff;
847
+ data >>= 8;
848
+ if (data & 1) {
849
+ SKIP_PIXEL(dest);
850
+ } else {
851
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
852
+ }
853
+ width -= 1;
854
+ src += 4;
855
+ }
856
+}
857
+
858
+/* Overlay planes disabled, no transparency */
859
+static drawfn pxa2xx_draw_fn_32[16] = {
860
+ [0 ... 0xf] = NULL,
861
+ [pxa_lcdc_2bpp] = pxa2xx_draw_line2,
862
+ [pxa_lcdc_4bpp] = pxa2xx_draw_line4,
863
+ [pxa_lcdc_8bpp] = pxa2xx_draw_line8,
864
+ [pxa_lcdc_16bpp] = pxa2xx_draw_line16,
865
+ [pxa_lcdc_18bpp] = pxa2xx_draw_line18,
866
+ [pxa_lcdc_18pbpp] = pxa2xx_draw_line18p,
867
+ [pxa_lcdc_24bpp] = pxa2xx_draw_line24,
868
+};
869
+
870
+/* Overlay planes enabled, transparency used */
871
+static drawfn pxa2xx_draw_fn_32t[16] = {
872
+ [0 ... 0xf] = NULL,
873
+ [pxa_lcdc_4bpp] = pxa2xx_draw_line4,
874
+ [pxa_lcdc_8bpp] = pxa2xx_draw_line8,
875
+ [pxa_lcdc_16bpp] = pxa2xx_draw_line16t,
876
+ [pxa_lcdc_19bpp] = pxa2xx_draw_line19,
877
+ [pxa_lcdc_19pbpp] = pxa2xx_draw_line19p,
878
+ [pxa_lcdc_24bpp] = pxa2xx_draw_line24t,
879
+ [pxa_lcdc_25bpp] = pxa2xx_draw_line25,
880
+};
881
+
882
+#undef COPY_PIXEL
883
+#undef SKIP_PIXEL
884
+
885
+#ifdef SWAP_WORDS
886
+# undef SWAP_WORDS
887
+#endif
888
889
/* Route internal interrupt lines to the global IC */
890
static void pxa2xx_lcdc_int_update(PXA2xxLCDState *s)
891
--
26
--
892
2.20.1
27
2.20.1
893
28
894
29
diff view generated by jsdifflib
1
We're about to move code from the template header into pxa2xx_lcd.c.
1
When we first converted our documentation to Sphinx, we split it into
2
Before doing that, make coding style fixes so checkpatch doesn't
2
multiple manuals (system, interop, tools, etc), which are all built
3
complain about the patch which moves the code. This commit is
3
separately. The primary driver for this was wanting to be able to
4
whitespace changes only:
4
avoid shipping the 'devel' manual to end-users. However, this is
5
* avoid hard-coded tabs
5
working against the grain of the way Sphinx wants to be used and
6
* fix ident on function prototypes
6
causes some annoyances:
7
* no newline before open brace on array definitions
7
* Cross-references between documents become much harder or
8
possibly impossible
9
* There is no single index to the whole documentation
10
* Within one manual there's no links or table-of-contents info
11
that lets you easily navigate to the others
12
* The devel manual doesn't get published on the QEMU website
13
(it would be nice to able to refer to it there)
14
15
Merely hiding our developer documentation from end users seems like
16
it's not enough benefit for these costs. Combine all the
17
documentation into a single manual (the same way that the readthedocs
18
site builds it) and install the whole thing. The previous manual
19
divisions remain as the new top level sections in the manual.
20
21
* The per-manual conf.py files are no longer needed
22
* The man_pages[] specifications previously in each per-manual
23
conf.py move to the top level conf.py
24
* docs/meson.build logic is simplified as we now only need to run
25
Sphinx once for the HTML and then once for the manpages5B
26
* The old index.html.in that produced the top-level page with
27
links to each manual is no longer needed
28
29
Unfortunately this means that we now have to build the HTML
30
documentation into docs/manual in the build tree rather than directly
31
into docs/; otherwise it is too awkward to ensure we install only the
32
built manual and not also the dependency info, stamp file, etc. The
33
manual still ends up in the same place in the final installed
34
directory, but anybody who was consulting documentation from within
35
the build tree will have to adjust where they're looking.
8
36
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
37
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
38
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
11
Message-id: 20210211141515.8755-9-peter.maydell@linaro.org
39
Message-id: 20210108161416.21129-3-peter.maydell@linaro.org
12
---
40
---
13
hw/display/pxa2xx_template.h | 66 +++++++++++++++++-------------------
41
docs/conf.py | 46 ++++++++++++++++++++++++++++++-
14
1 file changed, 32 insertions(+), 34 deletions(-)
42
docs/devel/conf.py | 15 -----------
15
43
docs/index.html.in | 17 ------------
16
diff --git a/hw/display/pxa2xx_template.h b/hw/display/pxa2xx_template.h
44
docs/interop/conf.py | 28 -------------------
45
docs/meson.build | 64 +++++++++++++++++---------------------------
46
docs/specs/conf.py | 16 -----------
47
docs/system/conf.py | 28 -------------------
48
docs/tools/conf.py | 37 -------------------------
49
docs/user/conf.py | 15 -----------
50
9 files changed, 70 insertions(+), 196 deletions(-)
51
delete mode 100644 docs/devel/conf.py
52
delete mode 100644 docs/index.html.in
53
delete mode 100644 docs/interop/conf.py
54
delete mode 100644 docs/specs/conf.py
55
delete mode 100644 docs/system/conf.py
56
delete mode 100644 docs/tools/conf.py
57
delete mode 100644 docs/user/conf.py
58
59
diff --git a/docs/conf.py b/docs/conf.py
17
index XXXXXXX..XXXXXXX 100644
60
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/display/pxa2xx_template.h
61
--- a/docs/conf.py
19
+++ b/hw/display/pxa2xx_template.h
62
+++ b/docs/conf.py
20
@@ -XXX,XX +XXX,XX @@
63
@@ -XXX,XX +XXX,XX @@ latex_documents = [
21
} while (0)
64
22
65
# -- Options for manual page output ---------------------------------------
23
#ifdef HOST_WORDS_BIGENDIAN
66
# Individual manual/conf.py can override this to create man pages
24
-# define SWAP_WORDS    1
67
-man_pages = []
25
+# define SWAP_WORDS 1
68
+man_pages = [
26
#endif
69
+ ('interop/qemu-ga', 'qemu-ga',
27
70
+ 'QEMU Guest Agent',
28
-#define FN_2(x)        FN(x + 1) FN(x)
71
+ ['Michael Roth <mdroth@linux.vnet.ibm.com>'], 8),
29
-#define FN_4(x)        FN_2(x + 2) FN_2(x)
72
+ ('interop/qemu-ga-ref', 'qemu-ga-ref',
30
+#define FN_2(x) FN(x + 1) FN(x)
73
+ 'QEMU Guest Agent Protocol Reference',
31
+#define FN_4(x) FN_2(x + 2) FN_2(x)
74
+ [], 7),
32
75
+ ('interop/qemu-qmp-ref', 'qemu-qmp-ref',
33
-static void pxa2xx_draw_line2(void *opaque,
76
+ 'QEMU QMP Reference Manual',
34
- uint8_t *dest, const uint8_t *src, int width, int deststep)
77
+ [], 7),
35
+static void pxa2xx_draw_line2(void *opaque, uint8_t *dest, const uint8_t *src,
78
+ ('interop/qemu-storage-daemon-qmp-ref', 'qemu-storage-daemon-qmp-ref',
36
+ int width, int deststep)
79
+ 'QEMU Storage Daemon QMP Reference Manual',
37
{
80
+ [], 7),
38
uint32_t *palette = opaque;
81
+ ('system/qemu-manpage', 'qemu',
39
uint32_t data;
82
+ 'QEMU User Documentation',
40
while (width > 0) {
83
+ ['Fabrice Bellard'], 1),
41
data = *(uint32_t *) src;
84
+ ('system/qemu-block-drivers', 'qemu-block-drivers',
42
-#define FN(x)        COPY_PIXEL(dest, palette[(data >> ((x) * 2)) & 3]);
85
+ 'QEMU block drivers reference',
43
+#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 2)) & 3]);
86
+ ['Fabrice Bellard and the QEMU Project developers'], 7),
44
#ifdef SWAP_WORDS
87
+ ('system/qemu-cpu-models', 'qemu-cpu-models',
45
FN_4(12)
88
+ 'QEMU CPU Models',
46
FN_4(8)
89
+ ['The QEMU Project developers'], 7),
47
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line2(void *opaque,
90
+ ('tools/qemu-img', 'qemu-img',
48
}
91
+ 'QEMU disk image utility',
49
}
92
+ ['Fabrice Bellard'], 1),
50
93
+ ('tools/qemu-nbd', 'qemu-nbd',
51
-static void pxa2xx_draw_line4(void *opaque,
94
+ 'QEMU Disk Network Block Device Server',
52
- uint8_t *dest, const uint8_t *src, int width, int deststep)
95
+ ['Anthony Liguori <anthony@codemonkey.ws>'], 8),
53
+static void pxa2xx_draw_line4(void *opaque, uint8_t *dest, const uint8_t *src,
96
+ ('tools/qemu-pr-helper', 'qemu-pr-helper',
54
+ int width, int deststep)
97
+ 'QEMU persistent reservation helper',
55
{
98
+ [], 8),
56
uint32_t *palette = opaque;
99
+ ('tools/qemu-storage-daemon', 'qemu-storage-daemon',
57
uint32_t data;
100
+ 'QEMU storage daemon',
58
while (width > 0) {
101
+ [], 1),
59
data = *(uint32_t *) src;
102
+ ('tools/qemu-trace-stap', 'qemu-trace-stap',
60
-#define FN(x)        COPY_PIXEL(dest, palette[(data >> ((x) * 4)) & 0xf]);
103
+ 'QEMU SystemTap trace tool',
61
+#define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 4)) & 0xf]);
104
+ [], 1),
62
#ifdef SWAP_WORDS
105
+ ('tools/virtfs-proxy-helper', 'virtfs-proxy-helper',
63
FN_2(6)
106
+ 'QEMU 9p virtfs proxy filesystem helper',
64
FN_2(4)
107
+ ['M. Mohan Kumar'], 1),
65
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line4(void *opaque,
108
+ ('tools/virtiofsd', 'virtiofsd',
66
}
109
+ 'QEMU virtio-fs shared file system daemon',
67
}
110
+ ['Stefan Hajnoczi <stefanha@redhat.com>',
68
111
+ 'Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>'], 1),
69
-static void pxa2xx_draw_line8(void *opaque,
112
+]
70
- uint8_t *dest, const uint8_t *src, int width, int deststep)
113
71
+static void pxa2xx_draw_line8(void *opaque, uint8_t *dest, const uint8_t *src,
114
# -- Options for Texinfo output -------------------------------------------
72
+ int width, int deststep)
115
73
{
116
diff --git a/docs/devel/conf.py b/docs/devel/conf.py
74
uint32_t *palette = opaque;
117
deleted file mode 100644
75
uint32_t data;
118
index XXXXXXX..XXXXXXX
76
while (width > 0) {
119
--- a/docs/devel/conf.py
77
data = *(uint32_t *) src;
120
+++ /dev/null
78
-#define FN(x)        COPY_PIXEL(dest, palette[(data >> (x)) & 0xff]);
121
@@ -XXX,XX +XXX,XX @@
79
+#define FN(x) COPY_PIXEL(dest, palette[(data >> (x)) & 0xff]);
122
-# -*- coding: utf-8 -*-
80
#ifdef SWAP_WORDS
123
-#
81
FN(24)
124
-# QEMU documentation build configuration file for the 'devel' manual.
82
FN(16)
125
-#
83
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line8(void *opaque,
126
-# This includes the top level conf file and then makes any necessary tweaks.
84
}
127
-import sys
85
}
128
-import os
86
129
-
87
-static void pxa2xx_draw_line16(void *opaque,
130
-qemu_docdir = os.path.abspath("..")
88
- uint8_t *dest, const uint8_t *src, int width, int deststep)
131
-parent_config = os.path.join(qemu_docdir, "conf.py")
89
+static void pxa2xx_draw_line16(void *opaque, uint8_t *dest, const uint8_t *src,
132
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
90
+ int width, int deststep)
133
-
91
{
134
-# This slightly misuses the 'description', but is the best way to get
92
uint32_t data;
135
-# the manual title to appear in the sidebar.
93
unsigned int r, g, b;
136
-html_theme_options['description'] = u'Developer''s Guide'
94
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line16(void *opaque,
137
diff --git a/docs/index.html.in b/docs/index.html.in
95
}
138
deleted file mode 100644
96
}
139
index XXXXXXX..XXXXXXX
97
140
--- a/docs/index.html.in
98
-static void pxa2xx_draw_line16t(void *opaque,
141
+++ /dev/null
99
- uint8_t *dest, const uint8_t *src, int width, int deststep)
142
@@ -XXX,XX +XXX,XX @@
100
+static void pxa2xx_draw_line16t(void *opaque, uint8_t *dest, const uint8_t *src,
143
-<!DOCTYPE html>
101
+ int width, int deststep)
144
-<html lang="en">
102
{
145
- <head>
103
uint32_t data;
146
- <meta charset="UTF-8">
104
unsigned int r, g, b;
147
- <title>QEMU @VERSION@ Documentation</title>
105
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line16t(void *opaque,
148
- </head>
106
}
149
- <body>
107
}
150
- <h1>QEMU @VERSION@ Documentation</h1>
108
151
- <ul>
109
-static void pxa2xx_draw_line18(void *opaque,
152
- <li><a href="system/index.html">System Emulation User's Guide</a></li>
110
- uint8_t *dest, const uint8_t *src, int width, int deststep)
153
- <li><a href="user/index.html">User Mode Emulation User's Guide</a></li>
111
+static void pxa2xx_draw_line18(void *opaque, uint8_t *dest, const uint8_t *src,
154
- <li><a href="tools/index.html">Tools Guide</a></li>
112
+ int width, int deststep)
155
- <li><a href="interop/index.html">System Emulation Management and Interoperability Guide</a></li>
113
{
156
- <li><a href="specs/index.html">System Emulation Guest Hardware Specifications</a></li>
114
uint32_t data;
157
- </ul>
115
unsigned int r, g, b;
158
- </body>
116
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line18(void *opaque,
159
-</html>
117
}
160
diff --git a/docs/interop/conf.py b/docs/interop/conf.py
118
161
deleted file mode 100644
119
/* The wicked packed format */
162
index XXXXXXX..XXXXXXX
120
-static void pxa2xx_draw_line18p(void *opaque,
163
--- a/docs/interop/conf.py
121
- uint8_t *dest, const uint8_t *src, int width, int deststep)
164
+++ /dev/null
122
+static void pxa2xx_draw_line18p(void *opaque, uint8_t *dest, const uint8_t *src,
165
@@ -XXX,XX +XXX,XX @@
123
+ int width, int deststep)
166
-# -*- coding: utf-8 -*-
124
{
167
-#
125
uint32_t data[3];
168
-# QEMU documentation build configuration file for the 'interop' manual.
126
unsigned int r, g, b;
169
-#
127
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line18p(void *opaque,
170
-# This includes the top level conf file and then makes any necessary tweaks.
128
}
171
-import sys
129
}
172
-import os
130
173
-
131
-static void pxa2xx_draw_line19(void *opaque,
174
-qemu_docdir = os.path.abspath("..")
132
- uint8_t *dest, const uint8_t *src, int width, int deststep)
175
-parent_config = os.path.join(qemu_docdir, "conf.py")
133
+static void pxa2xx_draw_line19(void *opaque, uint8_t *dest, const uint8_t *src,
176
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
134
+ int width, int deststep)
177
-
135
{
178
-# This slightly misuses the 'description', but is the best way to get
136
uint32_t data;
179
-# the manual title to appear in the sidebar.
137
unsigned int r, g, b;
180
-html_theme_options['description'] = u'System Emulation Management and Interoperability Guide'
138
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19(void *opaque,
181
-
139
}
182
-# One entry per manual page. List of tuples
140
183
-# (source start file, name, description, authors, manual section).
141
/* The wicked packed format */
184
-man_pages = [
142
-static void pxa2xx_draw_line19p(void *opaque,
185
- ('qemu-ga', 'qemu-ga', u'QEMU Guest Agent',
143
- uint8_t *dest, const uint8_t *src, int width, int deststep)
186
- ['Michael Roth <mdroth@linux.vnet.ibm.com>'], 8),
144
+static void pxa2xx_draw_line19p(void *opaque, uint8_t *dest, const uint8_t *src,
187
- ('qemu-ga-ref', 'qemu-ga-ref', 'QEMU Guest Agent Protocol Reference',
145
+ int width, int deststep)
188
- [], 7),
146
{
189
- ('qemu-qmp-ref', 'qemu-qmp-ref', 'QEMU QMP Reference Manual',
147
uint32_t data[3];
190
- [], 7),
148
unsigned int r, g, b;
191
- ('qemu-storage-daemon-qmp-ref', 'qemu-storage-daemon-qmp-ref',
149
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19p(void *opaque,
192
- 'QEMU Storage Daemon QMP Reference Manual', [], 7),
150
}
193
-]
151
}
194
diff --git a/docs/meson.build b/docs/meson.build
152
195
index XXXXXXX..XXXXXXX 100644
153
-static void pxa2xx_draw_line24(void *opaque,
196
--- a/docs/meson.build
154
- uint8_t *dest, const uint8_t *src, int width, int deststep)
197
+++ b/docs/meson.build
155
+static void pxa2xx_draw_line24(void *opaque, uint8_t *dest, const uint8_t *src,
198
@@ -XXX,XX +XXX,XX @@ if build_docs
156
+ int width, int deststep)
199
meson.source_root() / 'docs/sphinx/qmp_lexer.py',
157
{
200
qapi_gen_depends ]
158
uint32_t data;
201
159
unsigned int r, g, b;
202
- configure_file(output: 'index.html',
160
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line24(void *opaque,
203
- input: files('index.html.in'),
161
}
204
- configuration: {'VERSION': meson.project_version()},
162
}
205
- install_dir: qemu_docdir)
163
206
- manuals = [ 'devel', 'interop', 'tools', 'specs', 'system', 'user' ]
164
-static void pxa2xx_draw_line24t(void *opaque,
207
man_pages = {
165
- uint8_t *dest, const uint8_t *src, int width, int deststep)
208
- 'interop' : {
166
+static void pxa2xx_draw_line24t(void *opaque, uint8_t *dest, const uint8_t *src,
209
'qemu-ga.8': (have_tools ? 'man8' : ''),
167
+ int width, int deststep)
210
'qemu-ga-ref.7': 'man7',
168
{
211
'qemu-qmp-ref.7': 'man7',
169
uint32_t data;
212
'qemu-storage-daemon-qmp-ref.7': (have_tools ? 'man7' : ''),
170
unsigned int r, g, b;
213
- },
171
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line24t(void *opaque,
214
- 'tools': {
172
}
215
'qemu-img.1': (have_tools ? 'man1' : ''),
173
}
216
'qemu-nbd.8': (have_tools ? 'man8' : ''),
174
217
'qemu-pr-helper.8': (have_tools ? 'man8' : ''),
175
-static void pxa2xx_draw_line25(void *opaque,
218
@@ -XXX,XX +XXX,XX @@ if build_docs
176
- uint8_t *dest, const uint8_t *src, int width, int deststep)
219
'qemu-trace-stap.1': (config_host.has_key('CONFIG_TRACE_SYSTEMTAP') ? 'man1' : ''),
177
+static void pxa2xx_draw_line25(void *opaque, uint8_t *dest, const uint8_t *src,
220
'virtfs-proxy-helper.1': (have_virtfs_proxy_helper ? 'man1' : ''),
178
+ int width, int deststep)
221
'virtiofsd.1': (have_virtiofsd ? 'man1' : ''),
179
{
222
- },
180
uint32_t data;
223
- 'system': {
181
unsigned int r, g, b;
224
'qemu.1': 'man1',
182
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line25(void *opaque,
225
'qemu-block-drivers.7': 'man7',
183
}
226
'qemu-cpu-models.7': 'man7'
184
227
- },
185
/* Overlay planes disabled, no transparency */
228
}
186
-static drawfn pxa2xx_draw_fn_32[16] =
229
187
-{
230
sphinxdocs = []
188
+static drawfn pxa2xx_draw_fn_32[16] = {
231
sphinxmans = []
189
[0 ... 0xf] = NULL,
232
- foreach manual : manuals
190
[pxa_lcdc_2bpp] = pxa2xx_draw_line2,
233
- private_dir = meson.current_build_dir() / (manual + '.p')
191
[pxa_lcdc_4bpp] = pxa2xx_draw_line4,
234
- output_dir = meson.current_build_dir() / manual
192
@@ -XXX,XX +XXX,XX @@ static drawfn pxa2xx_draw_fn_32[16] =
235
- input_dir = meson.current_source_dir() / manual
193
};
236
194
237
- this_manual = custom_target(manual + ' manual',
195
/* Overlay planes enabled, transparency used */
238
+ private_dir = meson.current_build_dir() / 'manual.p'
196
-static drawfn pxa2xx_draw_fn_32t[16] =
239
+ output_dir = meson.current_build_dir() / 'manual'
197
-{
240
+ input_dir = meson.current_source_dir()
198
+static drawfn pxa2xx_draw_fn_32t[16] = {
241
+
199
[0 ... 0xf] = NULL,
242
+ this_manual = custom_target('QEMU manual',
200
[pxa_lcdc_4bpp] = pxa2xx_draw_line4,
243
build_by_default: build_docs,
201
[pxa_lcdc_8bpp] = pxa2xx_draw_line8,
244
- output: [manual + '.stamp'],
245
- input: [files('conf.py'), files(manual / 'conf.py')],
246
- depfile: manual + '.d',
247
+ output: 'docs.stamp',
248
+ input: files('conf.py'),
249
+ depfile: 'docs.d',
250
depend_files: sphinx_extn_depends,
251
command: [SPHINX_ARGS, '-Ddepfile=@DEPFILE@',
252
'-Ddepfile_stamp=@OUTPUT0@',
253
'-b', 'html', '-d', private_dir,
254
input_dir, output_dir])
255
- sphinxdocs += this_manual
256
- if build_docs and manual != 'devel'
257
- install_subdir(output_dir, install_dir: qemu_docdir)
258
- endif
259
+ sphinxdocs += this_manual
260
+ install_subdir(output_dir, install_dir: qemu_docdir, strip_directory: true)
261
262
- these_man_pages = []
263
- install_dirs = []
264
- foreach page, section : man_pages.get(manual, {})
265
- these_man_pages += page
266
- install_dirs += section == '' ? false : get_option('mandir') / section
267
- endforeach
268
- if these_man_pages.length() > 0
269
- sphinxmans += custom_target(manual + ' man pages',
270
- build_by_default: build_docs,
271
- output: these_man_pages,
272
- input: this_manual,
273
- install: build_docs,
274
- install_dir: install_dirs,
275
- command: [SPHINX_ARGS, '-b', 'man', '-d', private_dir,
276
- input_dir, meson.current_build_dir()])
277
- endif
278
+ these_man_pages = []
279
+ install_dirs = []
280
+ foreach page, section : man_pages
281
+ these_man_pages += page
282
+ install_dirs += section == '' ? false : get_option('mandir') / section
283
endforeach
284
+
285
+ sphinxmans += custom_target('QEMU man pages',
286
+ build_by_default: build_docs,
287
+ output: these_man_pages,
288
+ input: this_manual,
289
+ install: build_docs,
290
+ install_dir: install_dirs,
291
+ command: [SPHINX_ARGS, '-b', 'man', '-d', private_dir,
292
+ input_dir, meson.current_build_dir()])
293
+
294
alias_target('sphinxdocs', sphinxdocs)
295
alias_target('html', sphinxdocs)
296
alias_target('man', sphinxmans)
297
diff --git a/docs/specs/conf.py b/docs/specs/conf.py
298
deleted file mode 100644
299
index XXXXXXX..XXXXXXX
300
--- a/docs/specs/conf.py
301
+++ /dev/null
302
@@ -XXX,XX +XXX,XX @@
303
-# -*- coding: utf-8 -*-
304
-#
305
-# QEMU documentation build configuration file for the 'specs' manual.
306
-#
307
-# This includes the top level conf file and then makes any necessary tweaks.
308
-import sys
309
-import os
310
-
311
-qemu_docdir = os.path.abspath("..")
312
-parent_config = os.path.join(qemu_docdir, "conf.py")
313
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
314
-
315
-# This slightly misuses the 'description', but is the best way to get
316
-# the manual title to appear in the sidebar.
317
-html_theme_options['description'] = \
318
- u'System Emulation Guest Hardware Specifications'
319
diff --git a/docs/system/conf.py b/docs/system/conf.py
320
deleted file mode 100644
321
index XXXXXXX..XXXXXXX
322
--- a/docs/system/conf.py
323
+++ /dev/null
324
@@ -XXX,XX +XXX,XX @@
325
-# -*- coding: utf-8 -*-
326
-#
327
-# QEMU documentation build configuration file for the 'system' manual.
328
-#
329
-# This includes the top level conf file and then makes any necessary tweaks.
330
-import sys
331
-import os
332
-
333
-qemu_docdir = os.path.abspath("..")
334
-parent_config = os.path.join(qemu_docdir, "conf.py")
335
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
336
-
337
-# This slightly misuses the 'description', but is the best way to get
338
-# the manual title to appear in the sidebar.
339
-html_theme_options['description'] = u'System Emulation User''s Guide'
340
-
341
-# One entry per manual page. List of tuples
342
-# (source start file, name, description, authors, manual section).
343
-man_pages = [
344
- ('qemu-manpage', 'qemu', u'QEMU User Documentation',
345
- ['Fabrice Bellard'], 1),
346
- ('qemu-block-drivers', 'qemu-block-drivers',
347
- u'QEMU block drivers reference',
348
- ['Fabrice Bellard and the QEMU Project developers'], 7),
349
- ('qemu-cpu-models', 'qemu-cpu-models',
350
- u'QEMU CPU Models',
351
- ['The QEMU Project developers'], 7)
352
-]
353
diff --git a/docs/tools/conf.py b/docs/tools/conf.py
354
deleted file mode 100644
355
index XXXXXXX..XXXXXXX
356
--- a/docs/tools/conf.py
357
+++ /dev/null
358
@@ -XXX,XX +XXX,XX @@
359
-# -*- coding: utf-8 -*-
360
-#
361
-# QEMU documentation build configuration file for the 'tools' manual.
362
-#
363
-# This includes the top level conf file and then makes any necessary tweaks.
364
-import sys
365
-import os
366
-
367
-qemu_docdir = os.path.abspath("..")
368
-parent_config = os.path.join(qemu_docdir, "conf.py")
369
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
370
-
371
-# This slightly misuses the 'description', but is the best way to get
372
-# the manual title to appear in the sidebar.
373
-html_theme_options['description'] = \
374
- u'Tools Guide'
375
-
376
-# One entry per manual page. List of tuples
377
-# (source start file, name, description, authors, manual section).
378
-man_pages = [
379
- ('qemu-img', 'qemu-img', u'QEMU disk image utility',
380
- ['Fabrice Bellard'], 1),
381
- ('qemu-storage-daemon', 'qemu-storage-daemon', u'QEMU storage daemon',
382
- [], 1),
383
- ('qemu-nbd', 'qemu-nbd', u'QEMU Disk Network Block Device Server',
384
- ['Anthony Liguori <anthony@codemonkey.ws>'], 8),
385
- ('qemu-pr-helper', 'qemu-pr-helper', 'QEMU persistent reservation helper',
386
- [], 8),
387
- ('qemu-trace-stap', 'qemu-trace-stap', u'QEMU SystemTap trace tool',
388
- [], 1),
389
- ('virtfs-proxy-helper', 'virtfs-proxy-helper',
390
- u'QEMU 9p virtfs proxy filesystem helper',
391
- ['M. Mohan Kumar'], 1),
392
- ('virtiofsd', 'virtiofsd', u'QEMU virtio-fs shared file system daemon',
393
- ['Stefan Hajnoczi <stefanha@redhat.com>',
394
- 'Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>'], 1),
395
-]
396
diff --git a/docs/user/conf.py b/docs/user/conf.py
397
deleted file mode 100644
398
index XXXXXXX..XXXXXXX
399
--- a/docs/user/conf.py
400
+++ /dev/null
401
@@ -XXX,XX +XXX,XX @@
402
-# -*- coding: utf-8 -*-
403
-#
404
-# QEMU documentation build configuration file for the 'user' manual.
405
-#
406
-# This includes the top level conf file and then makes any necessary tweaks.
407
-import sys
408
-import os
409
-
410
-qemu_docdir = os.path.abspath("..")
411
-parent_config = os.path.join(qemu_docdir, "conf.py")
412
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
413
-
414
-# This slightly misuses the 'description', but is the best way to get
415
-# the manual title to appear in the sidebar.
416
-html_theme_options['description'] = u'User Mode Emulation User''s Guide'
202
--
417
--
203
2.20.1
418
2.20.1
204
419
205
420
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
In commit cd8be50e58f63413c0 we converted the A32 coprocessor
2
insns to decodetree. This accidentally broke XScale/iWMMXt insns,
3
because it moved the handling of "cp insns which are handled
4
by looking up the cp register in the hashtable" from after the
5
call to the legacy disas_xscale_insn() decode to before it,
6
with the result that all XScale/iWMMXt insns now UNDEF.
2
7
3
Unmap notifiers work with an address mask assuming an
8
Update valid_cp() so that it knows that on XScale cp 0 and 1
4
invalidation range of a power of 2. Nothing mandates this
9
are not standard coprocessor instructions; this will cause
5
in the VIRTIO-IOMMU spec.
10
the decodetree trans_ functions to ignore them, so that
11
execution will correctly get through to the legacy decode again.
6
12
7
So in case the range is not a power of 2, split it into
13
Cc: qemu-stable@nongnu.org
8
several invalidations.
14
Reported-by: Guenter Roeck <linux@roeck-us.net>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Tested-by: Guenter Roeck <linux@roeck-us.net>
18
Message-id: 20210108195157.32067-1-peter.maydell@linaro.org
19
---
20
target/arm/translate.c | 7 +++++++
21
1 file changed, 7 insertions(+)
9
22
10
Signed-off-by: Eric Auger <eric.auger@redhat.com>
23
diff --git a/target/arm/translate.c b/target/arm/translate.c
11
Reviewed-by: Peter Xu <peterx@redhat.com>
12
Message-id: 20210309102742.30442-4-eric.auger@redhat.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
hw/virtio/virtio-iommu.c | 19 ++++++++++++++++---
16
1 file changed, 16 insertions(+), 3 deletions(-)
17
18
diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
19
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/virtio/virtio-iommu.c
25
--- a/target/arm/translate.c
21
+++ b/hw/virtio/virtio-iommu.c
26
+++ b/target/arm/translate.c
22
@@ -XXX,XX +XXX,XX @@ static void virtio_iommu_notify_unmap(IOMMUMemoryRegion *mr, hwaddr virt_start,
27
@@ -XXX,XX +XXX,XX @@ static bool valid_cp(DisasContext *s, int cp)
23
hwaddr virt_end)
28
* only cp14 and cp15 are valid, and other values aren't considered
24
{
29
* to be in the coprocessor-instruction space at all. v8M still
25
IOMMUTLBEvent event;
30
* permits coprocessors 0..7.
26
+ uint64_t delta = virt_end - virt_start;
31
+ * For XScale, we must not decode the XScale cp0, cp1 space as
27
32
+ * a standard coprocessor insn, because we want to fall through to
28
if (!(mr->iommu_notify_flags & IOMMU_NOTIFIER_UNMAP)) {
33
+ * the legacy disas_xscale_insn() decoder after decodetree is done.
29
return;
34
*/
30
@@ -XXX,XX +XXX,XX @@ static void virtio_iommu_notify_unmap(IOMMUMemoryRegion *mr, hwaddr virt_start,
35
+ if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cp == 0 || cp == 1)) {
31
36
+ return false;
32
event.type = IOMMU_NOTIFIER_UNMAP;
33
event.entry.target_as = &address_space_memory;
34
- event.entry.addr_mask = virt_end - virt_start;
35
- event.entry.iova = virt_start;
36
event.entry.perm = IOMMU_NONE;
37
event.entry.translated_addr = 0;
38
+ event.entry.addr_mask = delta;
39
+ event.entry.iova = virt_start;
40
41
- memory_region_notify_iommu(mr, 0, event);
42
+ if (delta == UINT64_MAX) {
43
+ memory_region_notify_iommu(mr, 0, event);
44
+ }
37
+ }
45
+
38
+
46
+
39
if (arm_dc_feature(s, ARM_FEATURE_V8) &&
47
+ while (virt_start != virt_end + 1) {
40
!arm_dc_feature(s, ARM_FEATURE_M)) {
48
+ uint64_t mask = dma_aligned_pow2_mask(virt_start, virt_end, 64);
41
return cp >= 14;
49
+
50
+ event.entry.addr_mask = mask;
51
+ event.entry.iova = virt_start;
52
+ memory_region_notify_iommu(mr, 0, event);
53
+ virt_start += mask + 1;
54
+ }
55
}
56
57
static gboolean virtio_iommu_notify_unmap_cb(gpointer key, gpointer value,
58
--
42
--
59
2.20.1
43
2.20.1
60
44
61
45
diff view generated by jsdifflib
1
We're about to move code from the template header into pxa2xx_lcd.c.
1
A copy-and-paste error meant that the return value for register offset 0x44
2
Before doing that, make coding style fixes so checkpatch doesn't
2
(the RX Status FIFO PEEK register) returned a byte from a bogus offset in
3
complain about the patch which moves the code. This commit fixes
3
the rx status FIFO. Fix the typo.
4
missing braces in the SKIP_PIXEL() macro definition and in if()
5
statements.
6
4
5
Cc: qemu-stable@nongnu.org
6
Fixes: https://bugs.launchpad.net/qemu/+bug/1904954
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20210211141515.8755-8-peter.maydell@linaro.org
9
Message-id: 20210108180401.2263-2-peter.maydell@linaro.org
10
---
10
---
11
hw/display/pxa2xx_template.h | 47 +++++++++++++++++++++---------------
11
hw/net/lan9118.c | 2 +-
12
1 file changed, 28 insertions(+), 19 deletions(-)
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
13
14
diff --git a/hw/display/pxa2xx_template.h b/hw/display/pxa2xx_template.h
14
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/display/pxa2xx_template.h
16
--- a/hw/net/lan9118.c
17
+++ b/hw/display/pxa2xx_template.h
17
+++ b/hw/net/lan9118.c
18
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static uint64_t lan9118_readl(void *opaque, hwaddr offset,
19
* Framebuffer format conversion routines.
19
case 0x40:
20
*/
20
return rx_status_fifo_pop(s);
21
21
case 0x44:
22
-# define SKIP_PIXEL(to)        to += deststep
22
- return s->rx_status_fifo[s->tx_status_fifo_head];
23
+# define SKIP_PIXEL(to) do { to += deststep; } while (0)
23
+ return s->rx_status_fifo[s->rx_status_fifo_head];
24
# define COPY_PIXEL(to, from) \
24
case 0x48:
25
do { \
25
return tx_status_fifo_pop(s);
26
*(uint32_t *) to = from; \
26
case 0x4c:
27
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line16t(void *opaque,
28
data >>= 5;
29
r = (data & 0x1f) << 3;
30
data >>= 5;
31
- if (data & 1)
32
+ if (data & 1) {
33
SKIP_PIXEL(dest);
34
- else
35
+ } else {
36
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
37
+ }
38
data >>= 1;
39
b = (data & 0x1f) << 3;
40
data >>= 5;
41
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line16t(void *opaque,
42
data >>= 5;
43
r = (data & 0x1f) << 3;
44
data >>= 5;
45
- if (data & 1)
46
+ if (data & 1) {
47
SKIP_PIXEL(dest);
48
- else
49
+ } else {
50
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
51
+ }
52
width -= 2;
53
src += 4;
54
}
55
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19(void *opaque,
56
data >>= 6;
57
r = (data & 0x3f) << 2;
58
data >>= 6;
59
- if (data & 1)
60
+ if (data & 1) {
61
SKIP_PIXEL(dest);
62
- else
63
+ } else {
64
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
65
+ }
66
width -= 1;
67
src += 4;
68
}
69
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19p(void *opaque,
70
data[0] >>= 6;
71
r = (data[0] & 0x3f) << 2;
72
data[0] >>= 6;
73
- if (data[0] & 1)
74
+ if (data[0] & 1) {
75
SKIP_PIXEL(dest);
76
- else
77
+ } else {
78
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
79
+ }
80
data[0] >>= 6;
81
b = (data[0] & 0x3f) << 2;
82
data[0] >>= 6;
83
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19p(void *opaque,
84
data[1] >>= 4;
85
r = (data[1] & 0x3f) << 2;
86
data[1] >>= 6;
87
- if (data[1] & 1)
88
+ if (data[1] & 1) {
89
SKIP_PIXEL(dest);
90
- else
91
+ } else {
92
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
93
+ }
94
data[1] >>= 6;
95
b = (data[1] & 0x3f) << 2;
96
data[1] >>= 6;
97
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19p(void *opaque,
98
data[1] >>= 6;
99
r = ((data[2] & 0x3) << 6) | (data[1] << 2);
100
data[2] >>= 2;
101
- if (data[2] & 1)
102
+ if (data[2] & 1) {
103
SKIP_PIXEL(dest);
104
- else
105
+ } else {
106
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
107
+ }
108
data[2] >>= 6;
109
b = (data[2] & 0x3f) << 2;
110
data[2] >>= 6;
111
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line19p(void *opaque,
112
data[2] >>= 6;
113
r = data[2] << 2;
114
data[2] >>= 6;
115
- if (data[2] & 1)
116
+ if (data[2] & 1) {
117
SKIP_PIXEL(dest);
118
- else
119
+ } else {
120
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
121
+ }
122
width -= 4;
123
}
124
}
125
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line24t(void *opaque,
126
data >>= 8;
127
r = data & 0xff;
128
data >>= 8;
129
- if (data & 1)
130
+ if (data & 1) {
131
SKIP_PIXEL(dest);
132
- else
133
+ } else {
134
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
135
+ }
136
width -= 1;
137
src += 4;
138
}
139
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_draw_line25(void *opaque,
140
data >>= 8;
141
r = data & 0xff;
142
data >>= 8;
143
- if (data & 1)
144
+ if (data & 1) {
145
SKIP_PIXEL(dest);
146
- else
147
+ } else {
148
COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
149
+ }
150
width -= 1;
151
src += 4;
152
}
153
--
27
--
154
2.20.1
28
2.20.1
155
29
156
30
diff view generated by jsdifflib
1
BITS is always 32, so remove all uses of it from the template header,
1
The lan9118 code mostly uses symbolic constants for register offsets;
2
by dropping the trailing '32' from the draw function names and
2
the exceptions are those which the datasheet doesn't give an official
3
not constructing the name of rgb_to_pixel32() via the glue() macro.
3
symbolic name to.
4
5
Add some names for the registers which don't already have them, based
6
on the longer names they are given in the memory map.
4
7
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20210211141515.8755-4-peter.maydell@linaro.org
10
Message-id: 20210108180401.2263-3-peter.maydell@linaro.org
8
---
11
---
9
hw/display/pl110_template.h | 20 +++----
12
hw/net/lan9118.c | 24 ++++++++++++++++++------
10
hw/display/pl110.c | 113 ++++++++++++++++++------------------
13
1 file changed, 18 insertions(+), 6 deletions(-)
11
2 files changed, 65 insertions(+), 68 deletions(-)
12
14
13
diff --git a/hw/display/pl110_template.h b/hw/display/pl110_template.h
15
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/display/pl110_template.h
17
--- a/hw/net/lan9118.c
16
+++ b/hw/display/pl110_template.h
18
+++ b/hw/net/lan9118.c
17
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ do { hw_error("lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
20
do { fprintf(stderr, "lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
18
#endif
21
#endif
19
22
20
#if ORDER == 0
23
+/* The tx and rx fifo ports are a range of aliased 32-bit registers */
21
-#define NAME glue(glue(lblp_, BORDER), BITS)
24
+#define RX_DATA_FIFO_PORT_FIRST 0x00
22
+#define NAME glue(lblp_, BORDER)
25
+#define RX_DATA_FIFO_PORT_LAST 0x1f
23
#ifdef HOST_WORDS_BIGENDIAN
26
+#define TX_DATA_FIFO_PORT_FIRST 0x20
24
#define SWAP_WORDS 1
27
+#define TX_DATA_FIFO_PORT_LAST 0x3f
25
#endif
26
#elif ORDER == 1
27
-#define NAME glue(glue(bbbp_, BORDER), BITS)
28
+#define NAME glue(bbbp_, BORDER)
29
#ifndef HOST_WORDS_BIGENDIAN
30
#define SWAP_WORDS 1
31
#endif
32
#else
33
#define SWAP_PIXELS 1
34
-#define NAME glue(glue(lbbp_, BORDER), BITS)
35
+#define NAME glue(lbbp_, BORDER)
36
#ifdef HOST_WORDS_BIGENDIAN
37
#define SWAP_WORDS 1
38
#endif
39
@@ -XXX,XX +XXX,XX @@ static void glue(pl110_draw_line16_,NAME)(void *opaque, uint8_t *d, const uint8_
40
MSB = (data & 0x1f) << 3;
41
data >>= 5;
42
#endif
43
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
44
+ COPY_PIXEL(d, rgb_to_pixel32(r, g, b));
45
LSB = (data & 0x1f) << 3;
46
data >>= 5;
47
g = (data & 0x3f) << 2;
48
data >>= 6;
49
MSB = (data & 0x1f) << 3;
50
data >>= 5;
51
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
52
+ COPY_PIXEL(d, rgb_to_pixel32(r, g, b));
53
#undef MSB
54
#undef LSB
55
width -= 2;
56
@@ -XXX,XX +XXX,XX @@ static void glue(pl110_draw_line32_,NAME)(void *opaque, uint8_t *d, const uint8_
57
g = (data >> 16) & 0xff;
58
MSB = (data >> 8) & 0xff;
59
#endif
60
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
61
+ COPY_PIXEL(d, rgb_to_pixel32(r, g, b));
62
#undef MSB
63
#undef LSB
64
width--;
65
@@ -XXX,XX +XXX,XX @@ static void glue(pl110_draw_line16_555_,NAME)(void *opaque, uint8_t *d, const ui
66
data >>= 5;
67
MSB = (data & 0x1f) << 3;
68
data >>= 5;
69
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
70
+ COPY_PIXEL(d, rgb_to_pixel32(r, g, b));
71
LSB = (data & 0x1f) << 3;
72
data >>= 5;
73
g = (data & 0x1f) << 3;
74
data >>= 5;
75
MSB = (data & 0x1f) << 3;
76
data >>= 6;
77
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
78
+ COPY_PIXEL(d, rgb_to_pixel32(r, g, b));
79
#undef MSB
80
#undef LSB
81
width -= 2;
82
@@ -XXX,XX +XXX,XX @@ static void glue(pl110_draw_line12_,NAME)(void *opaque, uint8_t *d, const uint8_
83
data >>= 4;
84
MSB = (data & 0xf) << 4;
85
data >>= 8;
86
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
87
+ COPY_PIXEL(d, rgb_to_pixel32(r, g, b));
88
LSB = (data & 0xf) << 4;
89
data >>= 4;
90
g = (data & 0xf) << 4;
91
data >>= 4;
92
MSB = (data & 0xf) << 4;
93
data >>= 8;
94
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
95
+ COPY_PIXEL(d, rgb_to_pixel32(r, g, b));
96
#undef MSB
97
#undef LSB
98
width -= 2;
99
diff --git a/hw/display/pl110.c b/hw/display/pl110.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/hw/display/pl110.c
102
+++ b/hw/display/pl110.c
103
@@ -XXX,XX +XXX,XX @@ static const unsigned char *idregs[] = {
104
pl111_id
105
};
106
107
-#define BITS 32
108
#define COPY_PIXEL(to, from) do { *(uint32_t *)to = from; to += 4; } while (0)
109
110
#undef RGB
111
@@ -XXX,XX +XXX,XX @@ static const unsigned char *idregs[] = {
112
#include "pl110_template.h"
113
#undef BORDER
114
115
-static drawfn pl110_draw_fn_32[48] = {
116
- pl110_draw_line1_lblp_bgr32,
117
- pl110_draw_line2_lblp_bgr32,
118
- pl110_draw_line4_lblp_bgr32,
119
- pl110_draw_line8_lblp_bgr32,
120
- pl110_draw_line16_555_lblp_bgr32,
121
- pl110_draw_line32_lblp_bgr32,
122
- pl110_draw_line16_lblp_bgr32,
123
- pl110_draw_line12_lblp_bgr32,
124
-
125
- pl110_draw_line1_bbbp_bgr32,
126
- pl110_draw_line2_bbbp_bgr32,
127
- pl110_draw_line4_bbbp_bgr32,
128
- pl110_draw_line8_bbbp_bgr32,
129
- pl110_draw_line16_555_bbbp_bgr32,
130
- pl110_draw_line32_bbbp_bgr32,
131
- pl110_draw_line16_bbbp_bgr32,
132
- pl110_draw_line12_bbbp_bgr32,
133
-
134
- pl110_draw_line1_lbbp_bgr32,
135
- pl110_draw_line2_lbbp_bgr32,
136
- pl110_draw_line4_lbbp_bgr32,
137
- pl110_draw_line8_lbbp_bgr32,
138
- pl110_draw_line16_555_lbbp_bgr32,
139
- pl110_draw_line32_lbbp_bgr32,
140
- pl110_draw_line16_lbbp_bgr32,
141
- pl110_draw_line12_lbbp_bgr32,
142
-
143
- pl110_draw_line1_lblp_rgb32,
144
- pl110_draw_line2_lblp_rgb32,
145
- pl110_draw_line4_lblp_rgb32,
146
- pl110_draw_line8_lblp_rgb32,
147
- pl110_draw_line16_555_lblp_rgb32,
148
- pl110_draw_line32_lblp_rgb32,
149
- pl110_draw_line16_lblp_rgb32,
150
- pl110_draw_line12_lblp_rgb32,
151
-
152
- pl110_draw_line1_bbbp_rgb32,
153
- pl110_draw_line2_bbbp_rgb32,
154
- pl110_draw_line4_bbbp_rgb32,
155
- pl110_draw_line8_bbbp_rgb32,
156
- pl110_draw_line16_555_bbbp_rgb32,
157
- pl110_draw_line32_bbbp_rgb32,
158
- pl110_draw_line16_bbbp_rgb32,
159
- pl110_draw_line12_bbbp_rgb32,
160
-
161
- pl110_draw_line1_lbbp_rgb32,
162
- pl110_draw_line2_lbbp_rgb32,
163
- pl110_draw_line4_lbbp_rgb32,
164
- pl110_draw_line8_lbbp_rgb32,
165
- pl110_draw_line16_555_lbbp_rgb32,
166
- pl110_draw_line32_lbbp_rgb32,
167
- pl110_draw_line16_lbbp_rgb32,
168
- pl110_draw_line12_lbbp_rgb32,
169
-};
170
-
171
-#undef BITS
172
#undef COPY_PIXEL
173
174
+static drawfn pl110_draw_fn_32[48] = {
175
+ pl110_draw_line1_lblp_bgr,
176
+ pl110_draw_line2_lblp_bgr,
177
+ pl110_draw_line4_lblp_bgr,
178
+ pl110_draw_line8_lblp_bgr,
179
+ pl110_draw_line16_555_lblp_bgr,
180
+ pl110_draw_line32_lblp_bgr,
181
+ pl110_draw_line16_lblp_bgr,
182
+ pl110_draw_line12_lblp_bgr,
183
+
28
+
184
+ pl110_draw_line1_bbbp_bgr,
29
+#define RX_STATUS_FIFO_PORT 0x40
185
+ pl110_draw_line2_bbbp_bgr,
30
+#define RX_STATUS_FIFO_PEEK 0x44
186
+ pl110_draw_line4_bbbp_bgr,
31
+#define TX_STATUS_FIFO_PORT 0x48
187
+ pl110_draw_line8_bbbp_bgr,
32
+#define TX_STATUS_FIFO_PEEK 0x4c
188
+ pl110_draw_line16_555_bbbp_bgr,
189
+ pl110_draw_line32_bbbp_bgr,
190
+ pl110_draw_line16_bbbp_bgr,
191
+ pl110_draw_line12_bbbp_bgr,
192
+
33
+
193
+ pl110_draw_line1_lbbp_bgr,
34
#define CSR_ID_REV 0x50
194
+ pl110_draw_line2_lbbp_bgr,
35
#define CSR_IRQ_CFG 0x54
195
+ pl110_draw_line4_lbbp_bgr,
36
#define CSR_INT_STS 0x58
196
+ pl110_draw_line8_lbbp_bgr,
37
@@ -XXX,XX +XXX,XX @@ static void lan9118_writel(void *opaque, hwaddr offset,
197
+ pl110_draw_line16_555_lbbp_bgr,
38
offset &= 0xff;
198
+ pl110_draw_line32_lbbp_bgr,
39
199
+ pl110_draw_line16_lbbp_bgr,
40
//DPRINTF("Write reg 0x%02x = 0x%08x\n", (int)offset, val);
200
+ pl110_draw_line12_lbbp_bgr,
41
- if (offset >= 0x20 && offset < 0x40) {
201
+
42
+ if (offset >= TX_DATA_FIFO_PORT_FIRST &&
202
+ pl110_draw_line1_lblp_rgb,
43
+ offset <= TX_DATA_FIFO_PORT_LAST) {
203
+ pl110_draw_line2_lblp_rgb,
44
/* TX FIFO */
204
+ pl110_draw_line4_lblp_rgb,
45
tx_fifo_push(s, val);
205
+ pl110_draw_line8_lblp_rgb,
46
return;
206
+ pl110_draw_line16_555_lblp_rgb,
47
@@ -XXX,XX +XXX,XX @@ static uint64_t lan9118_readl(void *opaque, hwaddr offset,
207
+ pl110_draw_line32_lblp_rgb,
48
lan9118_state *s = (lan9118_state *)opaque;
208
+ pl110_draw_line16_lblp_rgb,
49
209
+ pl110_draw_line12_lblp_rgb,
50
//DPRINTF("Read reg 0x%02x\n", (int)offset);
210
+
51
- if (offset < 0x20) {
211
+ pl110_draw_line1_bbbp_rgb,
52
+ if (offset <= RX_DATA_FIFO_PORT_LAST) {
212
+ pl110_draw_line2_bbbp_rgb,
53
/* RX FIFO */
213
+ pl110_draw_line4_bbbp_rgb,
54
return rx_fifo_pop(s);
214
+ pl110_draw_line8_bbbp_rgb,
55
}
215
+ pl110_draw_line16_555_bbbp_rgb,
56
switch (offset) {
216
+ pl110_draw_line32_bbbp_rgb,
57
- case 0x40:
217
+ pl110_draw_line16_bbbp_rgb,
58
+ case RX_STATUS_FIFO_PORT:
218
+ pl110_draw_line12_bbbp_rgb,
59
return rx_status_fifo_pop(s);
219
+
60
- case 0x44:
220
+ pl110_draw_line1_lbbp_rgb,
61
+ case RX_STATUS_FIFO_PEEK:
221
+ pl110_draw_line2_lbbp_rgb,
62
return s->rx_status_fifo[s->rx_status_fifo_head];
222
+ pl110_draw_line4_lbbp_rgb,
63
- case 0x48:
223
+ pl110_draw_line8_lbbp_rgb,
64
+ case TX_STATUS_FIFO_PORT:
224
+ pl110_draw_line16_555_lbbp_rgb,
65
return tx_status_fifo_pop(s);
225
+ pl110_draw_line32_lbbp_rgb,
66
- case 0x4c:
226
+ pl110_draw_line16_lbbp_rgb,
67
+ case TX_STATUS_FIFO_PEEK:
227
+ pl110_draw_line12_lbbp_rgb,
68
return s->tx_status_fifo[s->tx_status_fifo_head];
228
+};
69
case CSR_ID_REV:
229
70
return 0x01180001;
230
static int pl110_enabled(PL110State *s)
231
{
232
--
71
--
233
2.20.1
72
2.20.1
234
73
235
74
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
Add a model of the Xilinx Versal Accelerator RAM (XRAM).
3
This patch allows NPCM7XX CLK module to compute clocks that are used by
4
This is mainly a stub to make firmware happy. The size of
4
other NPCM7XX modules.
5
the RAMs can be probed. The interrupt mask logic is
6
modelled but none of the interrups will ever be raised
7
unless injected.
8
5
9
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
6
Add a new struct NPCM7xxClockConverterState which represents a
10
Message-id: 20210308224637.2949533-2-edgar.iglesias@gmail.com
7
single converter. Each clock converter in CLK module represents one
8
converter in NPCM7XX CLK Module(PLL, SEL or Divider). Each converter
9
takes one or more input clocks and converts them into one output clock.
10
They form a clock hierarchy in the CLK module and are responsible for
11
outputing clocks for various other modules in an NPCM7XX SoC.
12
13
Each converter has a function pointer called "convert" which represents
14
the unique logic for that converter.
15
16
The clock contains two initialization information: ConverterInitInfo and
17
ConverterConnectionInfo. They represent the vertices and edges in the
18
clock diagram respectively.
19
20
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
21
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
22
Signed-off-by: Hao Wu <wuhaotsh@google.com>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
23
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
24
Message-id: 20210108190945.949196-2-wuhaotsh@google.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
26
---
14
include/hw/misc/xlnx-versal-xramc.h | 97 +++++++++++
27
include/hw/misc/npcm7xx_clk.h | 140 +++++-
15
hw/misc/xlnx-versal-xramc.c | 253 ++++++++++++++++++++++++++++
28
hw/misc/npcm7xx_clk.c | 805 +++++++++++++++++++++++++++++++++-
16
hw/misc/meson.build | 1 +
29
2 files changed, 932 insertions(+), 13 deletions(-)
17
3 files changed, 351 insertions(+)
18
create mode 100644 include/hw/misc/xlnx-versal-xramc.h
19
create mode 100644 hw/misc/xlnx-versal-xramc.c
20
30
21
diff --git a/include/hw/misc/xlnx-versal-xramc.h b/include/hw/misc/xlnx-versal-xramc.h
31
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
22
new file mode 100644
32
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX
33
--- a/include/hw/misc/npcm7xx_clk.h
24
--- /dev/null
34
+++ b/include/hw/misc/npcm7xx_clk.h
25
+++ b/include/hw/misc/xlnx-versal-xramc.h
26
@@ -XXX,XX +XXX,XX @@
35
@@ -XXX,XX +XXX,XX @@
36
#define NPCM7XX_CLK_H
37
38
#include "exec/memory.h"
39
+#include "hw/clock.h"
40
#include "hw/sysbus.h"
41
42
/*
43
@@ -XXX,XX +XXX,XX @@
44
45
#define NPCM7XX_WATCHDOG_RESET_GPIO_IN "npcm7xx-clk-watchdog-reset-gpio-in"
46
47
-typedef struct NPCM7xxCLKState {
48
+/* Maximum amount of clock inputs in a SEL module. */
49
+#define NPCM7XX_CLK_SEL_MAX_INPUT 5
50
+
51
+/* PLLs in CLK module. */
52
+typedef enum NPCM7xxClockPLL {
53
+ NPCM7XX_CLOCK_PLL0,
54
+ NPCM7XX_CLOCK_PLL1,
55
+ NPCM7XX_CLOCK_PLL2,
56
+ NPCM7XX_CLOCK_PLLG,
57
+ NPCM7XX_CLOCK_NR_PLLS,
58
+} NPCM7xxClockPLL;
59
+
60
+/* SEL/MUX in CLK module. */
61
+typedef enum NPCM7xxClockSEL {
62
+ NPCM7XX_CLOCK_PIXCKSEL,
63
+ NPCM7XX_CLOCK_MCCKSEL,
64
+ NPCM7XX_CLOCK_CPUCKSEL,
65
+ NPCM7XX_CLOCK_CLKOUTSEL,
66
+ NPCM7XX_CLOCK_UARTCKSEL,
67
+ NPCM7XX_CLOCK_TIMCKSEL,
68
+ NPCM7XX_CLOCK_SDCKSEL,
69
+ NPCM7XX_CLOCK_GFXMSEL,
70
+ NPCM7XX_CLOCK_SUCKSEL,
71
+ NPCM7XX_CLOCK_NR_SELS,
72
+} NPCM7xxClockSEL;
73
+
74
+/* Dividers in CLK module. */
75
+typedef enum NPCM7xxClockDivider {
76
+ NPCM7XX_CLOCK_PLL1D2, /* PLL1/2 */
77
+ NPCM7XX_CLOCK_PLL2D2, /* PLL2/2 */
78
+ NPCM7XX_CLOCK_MC_DIVIDER,
79
+ NPCM7XX_CLOCK_AXI_DIVIDER,
80
+ NPCM7XX_CLOCK_AHB_DIVIDER,
81
+ NPCM7XX_CLOCK_AHB3_DIVIDER,
82
+ NPCM7XX_CLOCK_SPI0_DIVIDER,
83
+ NPCM7XX_CLOCK_SPIX_DIVIDER,
84
+ NPCM7XX_CLOCK_APB1_DIVIDER,
85
+ NPCM7XX_CLOCK_APB2_DIVIDER,
86
+ NPCM7XX_CLOCK_APB3_DIVIDER,
87
+ NPCM7XX_CLOCK_APB4_DIVIDER,
88
+ NPCM7XX_CLOCK_APB5_DIVIDER,
89
+ NPCM7XX_CLOCK_CLKOUT_DIVIDER,
90
+ NPCM7XX_CLOCK_UART_DIVIDER,
91
+ NPCM7XX_CLOCK_TIMER_DIVIDER,
92
+ NPCM7XX_CLOCK_ADC_DIVIDER,
93
+ NPCM7XX_CLOCK_MMC_DIVIDER,
94
+ NPCM7XX_CLOCK_SDHC_DIVIDER,
95
+ NPCM7XX_CLOCK_GFXM_DIVIDER, /* divide by 3 */
96
+ NPCM7XX_CLOCK_UTMI_DIVIDER,
97
+ NPCM7XX_CLOCK_NR_DIVIDERS,
98
+} NPCM7xxClockConverter;
99
+
100
+typedef struct NPCM7xxCLKState NPCM7xxCLKState;
101
+
102
+/**
103
+ * struct NPCM7xxClockPLLState - A PLL module in CLK module.
104
+ * @name: The name of the module.
105
+ * @clk: The CLK module that owns this module.
106
+ * @clock_in: The input clock of this module.
107
+ * @clock_out: The output clock of this module.
108
+ * @reg: The control registers for this PLL module.
109
+ */
110
+typedef struct NPCM7xxClockPLLState {
111
+ DeviceState parent;
112
+
113
+ const char *name;
114
+ NPCM7xxCLKState *clk;
115
+ Clock *clock_in;
116
+ Clock *clock_out;
117
+
118
+ int reg;
119
+} NPCM7xxClockPLLState;
120
+
121
+/**
122
+ * struct NPCM7xxClockSELState - A SEL module in CLK module.
123
+ * @name: The name of the module.
124
+ * @clk: The CLK module that owns this module.
125
+ * @input_size: The size of inputs of this module.
126
+ * @clock_in: The input clocks of this module.
127
+ * @clock_out: The output clocks of this module.
128
+ * @offset: The offset of this module in the control register.
129
+ * @len: The length of this module in the control register.
130
+ */
131
+typedef struct NPCM7xxClockSELState {
132
+ DeviceState parent;
133
+
134
+ const char *name;
135
+ NPCM7xxCLKState *clk;
136
+ uint8_t input_size;
137
+ Clock *clock_in[NPCM7XX_CLK_SEL_MAX_INPUT];
138
+ Clock *clock_out;
139
+
140
+ int offset;
141
+ int len;
142
+} NPCM7xxClockSELState;
143
+
144
+/**
145
+ * struct NPCM7xxClockDividerState - A Divider module in CLK module.
146
+ * @name: The name of the module.
147
+ * @clk: The CLK module that owns this module.
148
+ * @clock_in: The input clock of this module.
149
+ * @clock_out: The output clock of this module.
150
+ * @divide: The function the divider uses to divide the input.
151
+ * @reg: The index of the control register that contains the divisor.
152
+ * @offset: The offset of the divisor in the control register.
153
+ * @len: The length of the divisor in the control register.
154
+ * @divisor: The divisor for a constant divisor
155
+ */
156
+typedef struct NPCM7xxClockDividerState {
157
+ DeviceState parent;
158
+
159
+ const char *name;
160
+ NPCM7xxCLKState *clk;
161
+ Clock *clock_in;
162
+ Clock *clock_out;
163
+
164
+ uint32_t (*divide)(struct NPCM7xxClockDividerState *s);
165
+ union {
166
+ struct {
167
+ int reg;
168
+ int offset;
169
+ int len;
170
+ };
171
+ int divisor;
172
+ };
173
+} NPCM7xxClockDividerState;
174
+
175
+struct NPCM7xxCLKState {
176
SysBusDevice parent;
177
178
MemoryRegion iomem;
179
180
+ /* Clock converters */
181
+ NPCM7xxClockPLLState plls[NPCM7XX_CLOCK_NR_PLLS];
182
+ NPCM7xxClockSELState sels[NPCM7XX_CLOCK_NR_SELS];
183
+ NPCM7xxClockDividerState dividers[NPCM7XX_CLOCK_NR_DIVIDERS];
184
+
185
uint32_t regs[NPCM7XX_CLK_NR_REGS];
186
187
/* Time reference for SECCNT and CNTR25M, initialized by power on reset */
188
int64_t ref_ns;
189
-} NPCM7xxCLKState;
190
+
191
+ /* The incoming reference clock. */
192
+ Clock *clkref;
193
+};
194
195
#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
196
#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK)
197
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
198
index XXXXXXX..XXXXXXX 100644
199
--- a/hw/misc/npcm7xx_clk.c
200
+++ b/hw/misc/npcm7xx_clk.c
201
@@ -XXX,XX +XXX,XX @@
202
203
#include "hw/misc/npcm7xx_clk.h"
204
#include "hw/timer/npcm7xx_timer.h"
205
+#include "hw/qdev-clock.h"
206
#include "migration/vmstate.h"
207
#include "qemu/error-report.h"
208
#include "qemu/log.h"
209
@@ -XXX,XX +XXX,XX @@
210
#include "trace.h"
211
#include "sysemu/watchdog.h"
212
27
+/*
213
+/*
28
+ * QEMU model of the Xilinx XRAM Controller.
214
+ * The reference clock hz, and the SECCNT and CNTR25M registers in this module,
29
+ *
215
+ * is always 25 MHz.
30
+ * Copyright (c) 2021 Xilinx Inc.
31
+ * SPDX-License-Identifier: GPL-2.0-or-later
32
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
33
+ */
216
+ */
34
+
217
+#define NPCM7XX_CLOCK_REF_HZ (25000000)
35
+#ifndef XLNX_VERSAL_XRAMC_H
218
+
36
+#define XLNX_VERSAL_XRAMC_H
219
+/* Register Field Definitions */
37
+
220
+#define NPCM7XX_CLK_WDRCR_CA9C BIT(0) /* Cortex A9 Cores */
38
+#include "hw/sysbus.h"
221
+
39
+#include "hw/register.h"
222
#define PLLCON_LOKI BIT(31)
40
+
223
#define PLLCON_LOKS BIT(30)
41
+#define TYPE_XLNX_XRAM_CTRL "xlnx.versal-xramc"
224
#define PLLCON_PWDEN BIT(12)
42
+
225
+#define PLLCON_FBDV(con) extract32((con), 16, 12)
43
+#define XLNX_XRAM_CTRL(obj) \
226
+#define PLLCON_OTDV2(con) extract32((con), 13, 3)
44
+ OBJECT_CHECK(XlnxXramCtrl, (obj), TYPE_XLNX_XRAM_CTRL)
227
+#define PLLCON_OTDV1(con) extract32((con), 8, 3)
45
+
228
+#define PLLCON_INDV(con) extract32((con), 0, 6)
46
+REG32(XRAM_ERR_CTRL, 0x0)
229
47
+ FIELD(XRAM_ERR_CTRL, UE_RES, 3, 1)
230
enum NPCM7xxCLKRegisters {
48
+ FIELD(XRAM_ERR_CTRL, PWR_ERR_RES, 2, 1)
231
NPCM7XX_CLK_CLKEN1,
49
+ FIELD(XRAM_ERR_CTRL, PZ_ERR_RES, 1, 1)
232
@@ -XXX,XX +XXX,XX @@ static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = {
50
+ FIELD(XRAM_ERR_CTRL, APB_ERR_RES, 0, 1)
233
[NPCM7XX_CLK_AHBCKFI] = 0x000000c8,
51
+REG32(XRAM_ISR, 0x4)
234
};
52
+ FIELD(XRAM_ISR, INV_APB, 0, 1)
235
53
+REG32(XRAM_IMR, 0x8)
236
-/* Register Field Definitions */
54
+ FIELD(XRAM_IMR, INV_APB, 0, 1)
237
-#define NPCM7XX_CLK_WDRCR_CA9C BIT(0) /* Cortex A9 Cores */
55
+REG32(XRAM_IEN, 0xc)
238
-
56
+ FIELD(XRAM_IEN, INV_APB, 0, 1)
239
/* The number of watchdogs that can trigger a reset. */
57
+REG32(XRAM_IDS, 0x10)
240
#define NPCM7XX_NR_WATCHDOGS (3)
58
+ FIELD(XRAM_IDS, INV_APB, 0, 1)
241
59
+REG32(XRAM_ECC_CNTL, 0x14)
242
+/* Clock converter functions */
60
+ FIELD(XRAM_ECC_CNTL, FI_MODE, 2, 1)
243
+
61
+ FIELD(XRAM_ECC_CNTL, DET_ONLY, 1, 1)
244
+#define TYPE_NPCM7XX_CLOCK_PLL "npcm7xx-clock-pll"
62
+ FIELD(XRAM_ECC_CNTL, ECC_ON_OFF, 0, 1)
245
+#define NPCM7XX_CLOCK_PLL(obj) OBJECT_CHECK(NPCM7xxClockPLLState, \
63
+REG32(XRAM_CLR_EXE, 0x18)
246
+ (obj), TYPE_NPCM7XX_CLOCK_PLL)
64
+ FIELD(XRAM_CLR_EXE, MON_7, 7, 1)
247
+#define TYPE_NPCM7XX_CLOCK_SEL "npcm7xx-clock-sel"
65
+ FIELD(XRAM_CLR_EXE, MON_6, 6, 1)
248
+#define NPCM7XX_CLOCK_SEL(obj) OBJECT_CHECK(NPCM7xxClockSELState, \
66
+ FIELD(XRAM_CLR_EXE, MON_5, 5, 1)
249
+ (obj), TYPE_NPCM7XX_CLOCK_SEL)
67
+ FIELD(XRAM_CLR_EXE, MON_4, 4, 1)
250
+#define TYPE_NPCM7XX_CLOCK_DIVIDER "npcm7xx-clock-divider"
68
+ FIELD(XRAM_CLR_EXE, MON_3, 3, 1)
251
+#define NPCM7XX_CLOCK_DIVIDER(obj) OBJECT_CHECK(NPCM7xxClockDividerState, \
69
+ FIELD(XRAM_CLR_EXE, MON_2, 2, 1)
252
+ (obj), TYPE_NPCM7XX_CLOCK_DIVIDER)
70
+ FIELD(XRAM_CLR_EXE, MON_1, 1, 1)
253
+
71
+ FIELD(XRAM_CLR_EXE, MON_0, 0, 1)
254
+static void npcm7xx_clk_update_pll(void *opaque)
72
+REG32(XRAM_CE_FFA, 0x1c)
255
+{
73
+ FIELD(XRAM_CE_FFA, ADDR, 0, 20)
256
+ NPCM7xxClockPLLState *s = opaque;
74
+REG32(XRAM_CE_FFD0, 0x20)
257
+ uint32_t con = s->clk->regs[s->reg];
75
+REG32(XRAM_CE_FFD1, 0x24)
258
+ uint64_t freq;
76
+REG32(XRAM_CE_FFD2, 0x28)
259
+
77
+REG32(XRAM_CE_FFD3, 0x2c)
260
+ /* The PLL is grounded if it is not locked yet. */
78
+REG32(XRAM_CE_FFE, 0x30)
261
+ if (con & PLLCON_LOKI) {
79
+ FIELD(XRAM_CE_FFE, SYNDROME, 0, 16)
262
+ freq = clock_get_hz(s->clock_in);
80
+REG32(XRAM_UE_FFA, 0x34)
263
+ freq *= PLLCON_FBDV(con);
81
+ FIELD(XRAM_UE_FFA, ADDR, 0, 20)
264
+ freq /= PLLCON_INDV(con) * PLLCON_OTDV1(con) * PLLCON_OTDV2(con);
82
+REG32(XRAM_UE_FFD0, 0x38)
265
+ } else {
83
+REG32(XRAM_UE_FFD1, 0x3c)
266
+ freq = 0;
84
+REG32(XRAM_UE_FFD2, 0x40)
267
+ }
85
+REG32(XRAM_UE_FFD3, 0x44)
268
+
86
+REG32(XRAM_UE_FFE, 0x48)
269
+ clock_update_hz(s->clock_out, freq);
87
+ FIELD(XRAM_UE_FFE, SYNDROME, 0, 16)
270
+}
88
+REG32(XRAM_FI_D0, 0x4c)
271
+
89
+REG32(XRAM_FI_D1, 0x50)
272
+static void npcm7xx_clk_update_sel(void *opaque)
90
+REG32(XRAM_FI_D2, 0x54)
273
+{
91
+REG32(XRAM_FI_D3, 0x58)
274
+ NPCM7xxClockSELState *s = opaque;
92
+REG32(XRAM_FI_SY, 0x5c)
275
+ uint32_t index = extract32(s->clk->regs[NPCM7XX_CLK_CLKSEL], s->offset,
93
+ FIELD(XRAM_FI_SY, DATA, 0, 16)
276
+ s->len);
94
+REG32(XRAM_RMW_UE_FFA, 0x70)
277
+
95
+ FIELD(XRAM_RMW_UE_FFA, ADDR, 0, 20)
278
+ if (index >= s->input_size) {
96
+REG32(XRAM_FI_CNTR, 0x74)
279
+ qemu_log_mask(LOG_GUEST_ERROR,
97
+ FIELD(XRAM_FI_CNTR, COUNT, 0, 24)
280
+ "%s: SEL index: %u out of range\n",
98
+REG32(XRAM_IMP, 0x80)
281
+ __func__, index);
99
+ FIELD(XRAM_IMP, SIZE, 0, 4)
282
+ index = 0;
100
+REG32(XRAM_PRDY_DBG, 0x84)
283
+ }
101
+ FIELD(XRAM_PRDY_DBG, ISLAND3, 12, 4)
284
+ clock_update_hz(s->clock_out, clock_get_hz(s->clock_in[index]));
102
+ FIELD(XRAM_PRDY_DBG, ISLAND2, 8, 4)
285
+}
103
+ FIELD(XRAM_PRDY_DBG, ISLAND1, 4, 4)
286
+
104
+ FIELD(XRAM_PRDY_DBG, ISLAND0, 0, 4)
287
+static void npcm7xx_clk_update_divider(void *opaque)
105
+REG32(XRAM_SAFETY_CHK, 0xff8)
288
+{
106
+
289
+ NPCM7xxClockDividerState *s = opaque;
107
+#define XRAM_CTRL_R_MAX (R_XRAM_SAFETY_CHK + 1)
290
+ uint32_t freq;
108
+
291
+
109
+typedef struct XlnxXramCtrl {
292
+ freq = s->divide(s);
110
+ SysBusDevice parent_obj;
293
+ clock_update_hz(s->clock_out, freq);
111
+ MemoryRegion ram;
294
+}
112
+ qemu_irq irq;
295
+
113
+
296
+static uint32_t divide_by_constant(NPCM7xxClockDividerState *s)
114
+ struct {
297
+{
115
+ uint64_t size;
298
+ return clock_get_hz(s->clock_in) / s->divisor;
116
+ unsigned int encoded_size;
299
+}
117
+ } cfg;
300
+
118
+
301
+static uint32_t divide_by_reg_divisor(NPCM7xxClockDividerState *s)
119
+ RegisterInfoArray *reg_array;
302
+{
120
+ uint32_t regs[XRAM_CTRL_R_MAX];
303
+ return clock_get_hz(s->clock_in) /
121
+ RegisterInfo regs_info[XRAM_CTRL_R_MAX];
304
+ (extract32(s->clk->regs[s->reg], s->offset, s->len) + 1);
122
+} XlnxXramCtrl;
305
+}
123
+#endif
306
+
124
diff --git a/hw/misc/xlnx-versal-xramc.c b/hw/misc/xlnx-versal-xramc.c
307
+static uint32_t divide_by_reg_divisor_times_2(NPCM7xxClockDividerState *s)
125
new file mode 100644
308
+{
126
index XXXXXXX..XXXXXXX
309
+ return divide_by_reg_divisor(s) / 2;
127
--- /dev/null
310
+}
128
+++ b/hw/misc/xlnx-versal-xramc.c
311
+
129
@@ -XXX,XX +XXX,XX @@
312
+static uint32_t shift_by_reg_divisor(NPCM7xxClockDividerState *s)
130
+/*
313
+{
131
+ * QEMU model of the Xilinx XRAM Controller.
314
+ return clock_get_hz(s->clock_in) >>
132
+ *
315
+ extract32(s->clk->regs[s->reg], s->offset, s->len);
133
+ * Copyright (c) 2021 Xilinx Inc.
316
+}
134
+ * SPDX-License-Identifier: GPL-2.0-or-later
317
+
135
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
318
+static NPCM7xxClockPLL find_pll_by_reg(enum NPCM7xxCLKRegisters reg)
136
+ */
319
+{
137
+
320
+ switch (reg) {
138
+#include "qemu/osdep.h"
321
+ case NPCM7XX_CLK_PLLCON0:
139
+#include "qemu/units.h"
322
+ return NPCM7XX_CLOCK_PLL0;
140
+#include "qapi/error.h"
323
+ case NPCM7XX_CLK_PLLCON1:
141
+#include "migration/vmstate.h"
324
+ return NPCM7XX_CLOCK_PLL1;
142
+#include "hw/sysbus.h"
325
+ case NPCM7XX_CLK_PLLCON2:
143
+#include "hw/register.h"
326
+ return NPCM7XX_CLOCK_PLL2;
144
+#include "hw/qdev-properties.h"
327
+ case NPCM7XX_CLK_PLLCONG:
145
+#include "hw/irq.h"
328
+ return NPCM7XX_CLOCK_PLLG;
146
+#include "hw/misc/xlnx-versal-xramc.h"
329
+ default:
147
+
330
+ g_assert_not_reached();
148
+#ifndef XLNX_XRAM_CTRL_ERR_DEBUG
331
+ }
149
+#define XLNX_XRAM_CTRL_ERR_DEBUG 0
332
+}
150
+#endif
333
+
151
+
334
+static void npcm7xx_clk_update_all_plls(NPCM7xxCLKState *clk)
152
+static void xram_update_irq(XlnxXramCtrl *s)
335
+{
153
+{
336
+ int i;
154
+ bool pending = s->regs[R_XRAM_ISR] & ~s->regs[R_XRAM_IMR];
337
+
155
+ qemu_set_irq(s->irq, pending);
338
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
156
+}
339
+ npcm7xx_clk_update_pll(&clk->plls[i]);
157
+
340
+ }
158
+static void xram_isr_postw(RegisterInfo *reg, uint64_t val64)
341
+}
159
+{
342
+
160
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(reg->opaque);
343
+static void npcm7xx_clk_update_all_sels(NPCM7xxCLKState *clk)
161
+ xram_update_irq(s);
344
+{
162
+}
345
+ int i;
163
+
346
+
164
+static uint64_t xram_ien_prew(RegisterInfo *reg, uint64_t val64)
347
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
165
+{
348
+ npcm7xx_clk_update_sel(&clk->sels[i]);
166
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(reg->opaque);
349
+ }
167
+ uint32_t val = val64;
350
+}
168
+
351
+
169
+ s->regs[R_XRAM_IMR] &= ~val;
352
+static void npcm7xx_clk_update_all_dividers(NPCM7xxCLKState *clk)
170
+ xram_update_irq(s);
353
+{
354
+ int i;
355
+
356
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
357
+ npcm7xx_clk_update_divider(&clk->dividers[i]);
358
+ }
359
+}
360
+
361
+static void npcm7xx_clk_update_all_clocks(NPCM7xxCLKState *clk)
362
+{
363
+ clock_update_hz(clk->clkref, NPCM7XX_CLOCK_REF_HZ);
364
+ npcm7xx_clk_update_all_plls(clk);
365
+ npcm7xx_clk_update_all_sels(clk);
366
+ npcm7xx_clk_update_all_dividers(clk);
367
+}
368
+
369
+/* Types of clock sources. */
370
+typedef enum ClockSrcType {
371
+ CLKSRC_REF,
372
+ CLKSRC_PLL,
373
+ CLKSRC_SEL,
374
+ CLKSRC_DIV,
375
+} ClockSrcType;
376
+
377
+typedef struct PLLInitInfo {
378
+ const char *name;
379
+ ClockSrcType src_type;
380
+ int src_index;
381
+ int reg;
382
+ const char *public_name;
383
+} PLLInitInfo;
384
+
385
+typedef struct SELInitInfo {
386
+ const char *name;
387
+ uint8_t input_size;
388
+ ClockSrcType src_type[NPCM7XX_CLK_SEL_MAX_INPUT];
389
+ int src_index[NPCM7XX_CLK_SEL_MAX_INPUT];
390
+ int offset;
391
+ int len;
392
+ const char *public_name;
393
+} SELInitInfo;
394
+
395
+typedef struct DividerInitInfo {
396
+ const char *name;
397
+ ClockSrcType src_type;
398
+ int src_index;
399
+ uint32_t (*divide)(NPCM7xxClockDividerState *s);
400
+ int reg; /* not used when type == CONSTANT */
401
+ int offset; /* not used when type == CONSTANT */
402
+ int len; /* not used when type == CONSTANT */
403
+ int divisor; /* used only when type == CONSTANT */
404
+ const char *public_name;
405
+} DividerInitInfo;
406
+
407
+static const PLLInitInfo pll_init_info_list[] = {
408
+ [NPCM7XX_CLOCK_PLL0] = {
409
+ .name = "pll0",
410
+ .src_type = CLKSRC_REF,
411
+ .reg = NPCM7XX_CLK_PLLCON0,
412
+ },
413
+ [NPCM7XX_CLOCK_PLL1] = {
414
+ .name = "pll1",
415
+ .src_type = CLKSRC_REF,
416
+ .reg = NPCM7XX_CLK_PLLCON1,
417
+ },
418
+ [NPCM7XX_CLOCK_PLL2] = {
419
+ .name = "pll2",
420
+ .src_type = CLKSRC_REF,
421
+ .reg = NPCM7XX_CLK_PLLCON2,
422
+ },
423
+ [NPCM7XX_CLOCK_PLLG] = {
424
+ .name = "pllg",
425
+ .src_type = CLKSRC_REF,
426
+ .reg = NPCM7XX_CLK_PLLCONG,
427
+ },
428
+};
429
+
430
+static const SELInitInfo sel_init_info_list[] = {
431
+ [NPCM7XX_CLOCK_PIXCKSEL] = {
432
+ .name = "pixcksel",
433
+ .input_size = 2,
434
+ .src_type = {CLKSRC_PLL, CLKSRC_REF},
435
+ .src_index = {NPCM7XX_CLOCK_PLLG, 0},
436
+ .offset = 5,
437
+ .len = 1,
438
+ .public_name = "pixel-clock",
439
+ },
440
+ [NPCM7XX_CLOCK_MCCKSEL] = {
441
+ .name = "mccksel",
442
+ .input_size = 4,
443
+ .src_type = {CLKSRC_DIV, CLKSRC_REF, CLKSRC_REF,
444
+ /*MCBPCK, shouldn't be used in normal operation*/
445
+ CLKSRC_REF},
446
+ .src_index = {NPCM7XX_CLOCK_PLL1D2, 0, 0, 0},
447
+ .offset = 12,
448
+ .len = 2,
449
+ .public_name = "mc-phy-clock",
450
+ },
451
+ [NPCM7XX_CLOCK_CPUCKSEL] = {
452
+ .name = "cpucksel",
453
+ .input_size = 4,
454
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF,
455
+ /*SYSBPCK, shouldn't be used in normal operation*/
456
+ CLKSRC_REF},
457
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0, 0},
458
+ .offset = 0,
459
+ .len = 2,
460
+ .public_name = "system-clock",
461
+ },
462
+ [NPCM7XX_CLOCK_CLKOUTSEL] = {
463
+ .name = "clkoutsel",
464
+ .input_size = 5,
465
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF,
466
+ CLKSRC_PLL, CLKSRC_DIV},
467
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
468
+ NPCM7XX_CLOCK_PLLG, NPCM7XX_CLOCK_PLL2D2},
469
+ .offset = 18,
470
+ .len = 3,
471
+ .public_name = "tock",
472
+ },
473
+ [NPCM7XX_CLOCK_UARTCKSEL] = {
474
+ .name = "uartcksel",
475
+ .input_size = 4,
476
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
477
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
478
+ NPCM7XX_CLOCK_PLL2D2},
479
+ .offset = 8,
480
+ .len = 2,
481
+ },
482
+ [NPCM7XX_CLOCK_TIMCKSEL] = {
483
+ .name = "timcksel",
484
+ .input_size = 4,
485
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
486
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
487
+ NPCM7XX_CLOCK_PLL2D2},
488
+ .offset = 14,
489
+ .len = 2,
490
+ },
491
+ [NPCM7XX_CLOCK_SDCKSEL] = {
492
+ .name = "sdcksel",
493
+ .input_size = 4,
494
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
495
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
496
+ NPCM7XX_CLOCK_PLL2D2},
497
+ .offset = 6,
498
+ .len = 2,
499
+ },
500
+ [NPCM7XX_CLOCK_GFXMSEL] = {
501
+ .name = "gfxmksel",
502
+ .input_size = 2,
503
+ .src_type = {CLKSRC_REF, CLKSRC_PLL},
504
+ .src_index = {0, NPCM7XX_CLOCK_PLL2},
505
+ .offset = 21,
506
+ .len = 1,
507
+ },
508
+ [NPCM7XX_CLOCK_SUCKSEL] = {
509
+ .name = "sucksel",
510
+ .input_size = 4,
511
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
512
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
513
+ NPCM7XX_CLOCK_PLL2D2},
514
+ .offset = 10,
515
+ .len = 2,
516
+ },
517
+};
518
+
519
+static const DividerInitInfo divider_init_info_list[] = {
520
+ [NPCM7XX_CLOCK_PLL1D2] = {
521
+ .name = "pll1d2",
522
+ .src_type = CLKSRC_PLL,
523
+ .src_index = NPCM7XX_CLOCK_PLL1,
524
+ .divide = divide_by_constant,
525
+ .divisor = 2,
526
+ },
527
+ [NPCM7XX_CLOCK_PLL2D2] = {
528
+ .name = "pll2d2",
529
+ .src_type = CLKSRC_PLL,
530
+ .src_index = NPCM7XX_CLOCK_PLL2,
531
+ .divide = divide_by_constant,
532
+ .divisor = 2,
533
+ },
534
+ [NPCM7XX_CLOCK_MC_DIVIDER] = {
535
+ .name = "mc-divider",
536
+ .src_type = CLKSRC_SEL,
537
+ .src_index = NPCM7XX_CLOCK_MCCKSEL,
538
+ .divide = divide_by_constant,
539
+ .divisor = 2,
540
+ .public_name = "mc-clock"
541
+ },
542
+ [NPCM7XX_CLOCK_AXI_DIVIDER] = {
543
+ .name = "axi-divider",
544
+ .src_type = CLKSRC_SEL,
545
+ .src_index = NPCM7XX_CLOCK_CPUCKSEL,
546
+ .divide = shift_by_reg_divisor,
547
+ .reg = NPCM7XX_CLK_CLKDIV1,
548
+ .offset = 0,
549
+ .len = 1,
550
+ .public_name = "clk2"
551
+ },
552
+ [NPCM7XX_CLOCK_AHB_DIVIDER] = {
553
+ .name = "ahb-divider",
554
+ .src_type = CLKSRC_DIV,
555
+ .src_index = NPCM7XX_CLOCK_AXI_DIVIDER,
556
+ .divide = divide_by_reg_divisor,
557
+ .reg = NPCM7XX_CLK_CLKDIV1,
558
+ .offset = 26,
559
+ .len = 2,
560
+ .public_name = "clk4"
561
+ },
562
+ [NPCM7XX_CLOCK_AHB3_DIVIDER] = {
563
+ .name = "ahb3-divider",
564
+ .src_type = CLKSRC_DIV,
565
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
566
+ .divide = divide_by_reg_divisor,
567
+ .reg = NPCM7XX_CLK_CLKDIV1,
568
+ .offset = 6,
569
+ .len = 5,
570
+ .public_name = "ahb3-spi3-clock"
571
+ },
572
+ [NPCM7XX_CLOCK_SPI0_DIVIDER] = {
573
+ .name = "spi0-divider",
574
+ .src_type = CLKSRC_DIV,
575
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
576
+ .divide = divide_by_reg_divisor,
577
+ .reg = NPCM7XX_CLK_CLKDIV3,
578
+ .offset = 6,
579
+ .len = 5,
580
+ .public_name = "spi0-clock",
581
+ },
582
+ [NPCM7XX_CLOCK_SPIX_DIVIDER] = {
583
+ .name = "spix-divider",
584
+ .src_type = CLKSRC_DIV,
585
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
586
+ .divide = divide_by_reg_divisor,
587
+ .reg = NPCM7XX_CLK_CLKDIV3,
588
+ .offset = 1,
589
+ .len = 5,
590
+ .public_name = "spix-clock",
591
+ },
592
+ [NPCM7XX_CLOCK_APB1_DIVIDER] = {
593
+ .name = "apb1-divider",
594
+ .src_type = CLKSRC_DIV,
595
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
596
+ .divide = shift_by_reg_divisor,
597
+ .reg = NPCM7XX_CLK_CLKDIV2,
598
+ .offset = 24,
599
+ .len = 2,
600
+ .public_name = "apb1-clock",
601
+ },
602
+ [NPCM7XX_CLOCK_APB2_DIVIDER] = {
603
+ .name = "apb2-divider",
604
+ .src_type = CLKSRC_DIV,
605
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
606
+ .divide = shift_by_reg_divisor,
607
+ .reg = NPCM7XX_CLK_CLKDIV2,
608
+ .offset = 26,
609
+ .len = 2,
610
+ .public_name = "apb2-clock",
611
+ },
612
+ [NPCM7XX_CLOCK_APB3_DIVIDER] = {
613
+ .name = "apb3-divider",
614
+ .src_type = CLKSRC_DIV,
615
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
616
+ .divide = shift_by_reg_divisor,
617
+ .reg = NPCM7XX_CLK_CLKDIV2,
618
+ .offset = 28,
619
+ .len = 2,
620
+ .public_name = "apb3-clock",
621
+ },
622
+ [NPCM7XX_CLOCK_APB4_DIVIDER] = {
623
+ .name = "apb4-divider",
624
+ .src_type = CLKSRC_DIV,
625
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
626
+ .divide = shift_by_reg_divisor,
627
+ .reg = NPCM7XX_CLK_CLKDIV2,
628
+ .offset = 30,
629
+ .len = 2,
630
+ .public_name = "apb4-clock",
631
+ },
632
+ [NPCM7XX_CLOCK_APB5_DIVIDER] = {
633
+ .name = "apb5-divider",
634
+ .src_type = CLKSRC_DIV,
635
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
636
+ .divide = shift_by_reg_divisor,
637
+ .reg = NPCM7XX_CLK_CLKDIV2,
638
+ .offset = 22,
639
+ .len = 2,
640
+ .public_name = "apb5-clock",
641
+ },
642
+ [NPCM7XX_CLOCK_CLKOUT_DIVIDER] = {
643
+ .name = "clkout-divider",
644
+ .src_type = CLKSRC_SEL,
645
+ .src_index = NPCM7XX_CLOCK_CLKOUTSEL,
646
+ .divide = divide_by_reg_divisor,
647
+ .reg = NPCM7XX_CLK_CLKDIV2,
648
+ .offset = 16,
649
+ .len = 5,
650
+ .public_name = "clkout",
651
+ },
652
+ [NPCM7XX_CLOCK_UART_DIVIDER] = {
653
+ .name = "uart-divider",
654
+ .src_type = CLKSRC_SEL,
655
+ .src_index = NPCM7XX_CLOCK_UARTCKSEL,
656
+ .divide = divide_by_reg_divisor,
657
+ .reg = NPCM7XX_CLK_CLKDIV1,
658
+ .offset = 16,
659
+ .len = 5,
660
+ .public_name = "uart-clock",
661
+ },
662
+ [NPCM7XX_CLOCK_TIMER_DIVIDER] = {
663
+ .name = "timer-divider",
664
+ .src_type = CLKSRC_SEL,
665
+ .src_index = NPCM7XX_CLOCK_TIMCKSEL,
666
+ .divide = divide_by_reg_divisor,
667
+ .reg = NPCM7XX_CLK_CLKDIV1,
668
+ .offset = 21,
669
+ .len = 5,
670
+ .public_name = "timer-clock",
671
+ },
672
+ [NPCM7XX_CLOCK_ADC_DIVIDER] = {
673
+ .name = "adc-divider",
674
+ .src_type = CLKSRC_DIV,
675
+ .src_index = NPCM7XX_CLOCK_TIMER_DIVIDER,
676
+ .divide = shift_by_reg_divisor,
677
+ .reg = NPCM7XX_CLK_CLKDIV1,
678
+ .offset = 28,
679
+ .len = 3,
680
+ .public_name = "adc-clock",
681
+ },
682
+ [NPCM7XX_CLOCK_MMC_DIVIDER] = {
683
+ .name = "mmc-divider",
684
+ .src_type = CLKSRC_SEL,
685
+ .src_index = NPCM7XX_CLOCK_SDCKSEL,
686
+ .divide = divide_by_reg_divisor,
687
+ .reg = NPCM7XX_CLK_CLKDIV1,
688
+ .offset = 11,
689
+ .len = 5,
690
+ .public_name = "mmc-clock",
691
+ },
692
+ [NPCM7XX_CLOCK_SDHC_DIVIDER] = {
693
+ .name = "sdhc-divider",
694
+ .src_type = CLKSRC_SEL,
695
+ .src_index = NPCM7XX_CLOCK_SDCKSEL,
696
+ .divide = divide_by_reg_divisor_times_2,
697
+ .reg = NPCM7XX_CLK_CLKDIV2,
698
+ .offset = 0,
699
+ .len = 4,
700
+ .public_name = "sdhc-clock",
701
+ },
702
+ [NPCM7XX_CLOCK_GFXM_DIVIDER] = {
703
+ .name = "gfxm-divider",
704
+ .src_type = CLKSRC_SEL,
705
+ .src_index = NPCM7XX_CLOCK_GFXMSEL,
706
+ .divide = divide_by_constant,
707
+ .divisor = 3,
708
+ .public_name = "gfxm-clock",
709
+ },
710
+ [NPCM7XX_CLOCK_UTMI_DIVIDER] = {
711
+ .name = "utmi-divider",
712
+ .src_type = CLKSRC_SEL,
713
+ .src_index = NPCM7XX_CLOCK_SUCKSEL,
714
+ .divide = divide_by_reg_divisor,
715
+ .reg = NPCM7XX_CLK_CLKDIV2,
716
+ .offset = 8,
717
+ .len = 5,
718
+ .public_name = "utmi-clock",
719
+ },
720
+};
721
+
722
+static void npcm7xx_clk_pll_init(Object *obj)
723
+{
724
+ NPCM7xxClockPLLState *pll = NPCM7XX_CLOCK_PLL(obj);
725
+
726
+ pll->clock_in = qdev_init_clock_in(DEVICE(pll), "clock-in",
727
+ npcm7xx_clk_update_pll, pll);
728
+ pll->clock_out = qdev_init_clock_out(DEVICE(pll), "clock-out");
729
+}
730
+
731
+static void npcm7xx_clk_sel_init(Object *obj)
732
+{
733
+ int i;
734
+ NPCM7xxClockSELState *sel = NPCM7XX_CLOCK_SEL(obj);
735
+
736
+ for (i = 0; i < NPCM7XX_CLK_SEL_MAX_INPUT; ++i) {
737
+ sel->clock_in[i] = qdev_init_clock_in(DEVICE(sel),
738
+ g_strdup_printf("clock-in[%d]", i),
739
+ npcm7xx_clk_update_sel, sel);
740
+ }
741
+ sel->clock_out = qdev_init_clock_out(DEVICE(sel), "clock-out");
742
+}
743
+static void npcm7xx_clk_divider_init(Object *obj)
744
+{
745
+ NPCM7xxClockDividerState *div = NPCM7XX_CLOCK_DIVIDER(obj);
746
+
747
+ div->clock_in = qdev_init_clock_in(DEVICE(div), "clock-in",
748
+ npcm7xx_clk_update_divider, div);
749
+ div->clock_out = qdev_init_clock_out(DEVICE(div), "clock-out");
750
+}
751
+
752
+static void npcm7xx_init_clock_pll(NPCM7xxClockPLLState *pll,
753
+ NPCM7xxCLKState *clk, const PLLInitInfo *init_info)
754
+{
755
+ pll->name = init_info->name;
756
+ pll->clk = clk;
757
+ pll->reg = init_info->reg;
758
+ if (init_info->public_name != NULL) {
759
+ qdev_alias_clock(DEVICE(pll), "clock-out", DEVICE(clk),
760
+ init_info->public_name);
761
+ }
762
+}
763
+
764
+static void npcm7xx_init_clock_sel(NPCM7xxClockSELState *sel,
765
+ NPCM7xxCLKState *clk, const SELInitInfo *init_info)
766
+{
767
+ int input_size = init_info->input_size;
768
+
769
+ sel->name = init_info->name;
770
+ sel->clk = clk;
771
+ sel->input_size = init_info->input_size;
772
+ g_assert(input_size <= NPCM7XX_CLK_SEL_MAX_INPUT);
773
+ sel->offset = init_info->offset;
774
+ sel->len = init_info->len;
775
+ if (init_info->public_name != NULL) {
776
+ qdev_alias_clock(DEVICE(sel), "clock-out", DEVICE(clk),
777
+ init_info->public_name);
778
+ }
779
+}
780
+
781
+static void npcm7xx_init_clock_divider(NPCM7xxClockDividerState *div,
782
+ NPCM7xxCLKState *clk, const DividerInitInfo *init_info)
783
+{
784
+ div->name = init_info->name;
785
+ div->clk = clk;
786
+
787
+ div->divide = init_info->divide;
788
+ if (div->divide == divide_by_constant) {
789
+ div->divisor = init_info->divisor;
790
+ } else {
791
+ div->reg = init_info->reg;
792
+ div->offset = init_info->offset;
793
+ div->len = init_info->len;
794
+ }
795
+ if (init_info->public_name != NULL) {
796
+ qdev_alias_clock(DEVICE(div), "clock-out", DEVICE(clk),
797
+ init_info->public_name);
798
+ }
799
+}
800
+
801
+static Clock *npcm7xx_get_clock(NPCM7xxCLKState *clk, ClockSrcType type,
802
+ int index)
803
+{
804
+ switch (type) {
805
+ case CLKSRC_REF:
806
+ return clk->clkref;
807
+ case CLKSRC_PLL:
808
+ return clk->plls[index].clock_out;
809
+ case CLKSRC_SEL:
810
+ return clk->sels[index].clock_out;
811
+ case CLKSRC_DIV:
812
+ return clk->dividers[index].clock_out;
813
+ default:
814
+ g_assert_not_reached();
815
+ }
816
+}
817
+
818
+static void npcm7xx_connect_clocks(NPCM7xxCLKState *clk)
819
+{
820
+ int i, j;
821
+ Clock *src;
822
+
823
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
824
+ src = npcm7xx_get_clock(clk, pll_init_info_list[i].src_type,
825
+ pll_init_info_list[i].src_index);
826
+ clock_set_source(clk->plls[i].clock_in, src);
827
+ }
828
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
829
+ for (j = 0; j < sel_init_info_list[i].input_size; ++j) {
830
+ src = npcm7xx_get_clock(clk, sel_init_info_list[i].src_type[j],
831
+ sel_init_info_list[i].src_index[j]);
832
+ clock_set_source(clk->sels[i].clock_in[j], src);
833
+ }
834
+ }
835
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
836
+ src = npcm7xx_get_clock(clk, divider_init_info_list[i].src_type,
837
+ divider_init_info_list[i].src_index);
838
+ clock_set_source(clk->dividers[i].clock_in, src);
839
+ }
840
+}
841
+
842
static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
843
{
844
uint32_t reg = offset / sizeof(uint32_t);
845
@@ -XXX,XX +XXX,XX @@ static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
846
*
847
* The 4 LSBs are always zero: (1e9 / 640) << 4 = 25000000.
848
*/
849
- value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_TIMER_REF_HZ;
850
+ value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_CLOCK_REF_HZ;
851
break;
852
853
default:
854
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_write(void *opaque, hwaddr offset,
855
value |= (value & PLLCON_LOKS);
856
}
857
}
858
+ /* Only update PLL when it is locked. */
859
+ if (value & PLLCON_LOKI) {
860
+ npcm7xx_clk_update_pll(&s->plls[find_pll_by_reg(reg)]);
861
+ }
862
+ break;
863
+
864
+ case NPCM7XX_CLK_CLKSEL:
865
+ npcm7xx_clk_update_all_sels(s);
866
+ break;
867
+
868
+ case NPCM7XX_CLK_CLKDIV1:
869
+ case NPCM7XX_CLK_CLKDIV2:
870
+ case NPCM7XX_CLK_CLKDIV3:
871
+ npcm7xx_clk_update_all_dividers(s);
872
break;
873
874
case NPCM7XX_CLK_CNTR25M:
875
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
876
case RESET_TYPE_COLD:
877
memcpy(s->regs, cold_reset_values, sizeof(cold_reset_values));
878
s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
879
+ npcm7xx_clk_update_all_clocks(s);
880
return;
881
}
882
883
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
884
__func__, type);
885
}
886
887
+static void npcm7xx_clk_init_clock_hierarchy(NPCM7xxCLKState *s)
888
+{
889
+ int i;
890
+
891
+ s->clkref = qdev_init_clock_in(DEVICE(s), "clkref", NULL, NULL);
892
+
893
+ /* First pass: init all converter modules */
894
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(pll_init_info_list) != NPCM7XX_CLOCK_NR_PLLS);
895
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(sel_init_info_list) != NPCM7XX_CLOCK_NR_SELS);
896
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(divider_init_info_list)
897
+ != NPCM7XX_CLOCK_NR_DIVIDERS);
898
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
899
+ object_initialize_child(OBJECT(s), pll_init_info_list[i].name,
900
+ &s->plls[i], TYPE_NPCM7XX_CLOCK_PLL);
901
+ npcm7xx_init_clock_pll(&s->plls[i], s,
902
+ &pll_init_info_list[i]);
903
+ }
904
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
905
+ object_initialize_child(OBJECT(s), sel_init_info_list[i].name,
906
+ &s->sels[i], TYPE_NPCM7XX_CLOCK_SEL);
907
+ npcm7xx_init_clock_sel(&s->sels[i], s,
908
+ &sel_init_info_list[i]);
909
+ }
910
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
911
+ object_initialize_child(OBJECT(s), divider_init_info_list[i].name,
912
+ &s->dividers[i], TYPE_NPCM7XX_CLOCK_DIVIDER);
913
+ npcm7xx_init_clock_divider(&s->dividers[i], s,
914
+ &divider_init_info_list[i]);
915
+ }
916
+
917
+ /* Second pass: connect converter modules */
918
+ npcm7xx_connect_clocks(s);
919
+
920
+ clock_update_hz(s->clkref, NPCM7XX_CLOCK_REF_HZ);
921
+}
922
+
923
static void npcm7xx_clk_init(Object *obj)
924
{
925
NPCM7xxCLKState *s = NPCM7XX_CLK(obj);
926
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_init(Object *obj)
927
memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
928
TYPE_NPCM7XX_CLK, 4 * KiB);
929
sysbus_init_mmio(&s->parent, &s->iomem);
930
- qdev_init_gpio_in_named(DEVICE(s), npcm7xx_clk_perform_watchdog_reset,
931
- NPCM7XX_WATCHDOG_RESET_GPIO_IN, NPCM7XX_NR_WATCHDOGS);
932
}
933
934
-static const VMStateDescription vmstate_npcm7xx_clk = {
935
- .name = "npcm7xx-clk",
936
+static int npcm7xx_clk_post_load(void *opaque, int version_id)
937
+{
938
+ if (version_id >= 1) {
939
+ NPCM7xxCLKState *clk = opaque;
940
+
941
+ npcm7xx_clk_update_all_clocks(clk);
942
+ }
943
+
171
+ return 0;
944
+ return 0;
172
+}
945
+}
173
+
946
+
174
+static uint64_t xram_ids_prew(RegisterInfo *reg, uint64_t val64)
947
+static void npcm7xx_clk_realize(DeviceState *dev, Error **errp)
175
+{
948
+{
176
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(reg->opaque);
949
+ int i;
177
+ uint32_t val = val64;
950
+ NPCM7xxCLKState *s = NPCM7XX_CLK(dev);
178
+
951
+
179
+ s->regs[R_XRAM_IMR] |= val;
952
+ qdev_init_gpio_in_named(DEVICE(s), npcm7xx_clk_perform_watchdog_reset,
180
+ xram_update_irq(s);
953
+ NPCM7XX_WATCHDOG_RESET_GPIO_IN, NPCM7XX_NR_WATCHDOGS);
181
+ return 0;
954
+ npcm7xx_clk_init_clock_hierarchy(s);
182
+}
955
+
183
+
956
+ /* Realize child devices */
184
+static const RegisterAccessInfo xram_ctrl_regs_info[] = {
957
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
185
+ { .name = "XRAM_ERR_CTRL", .addr = A_XRAM_ERR_CTRL,
958
+ if (!qdev_realize(DEVICE(&s->plls[i]), NULL, errp)) {
186
+ .reset = 0xf,
959
+ return;
187
+ .rsvd = 0xfffffff0,
960
+ }
188
+ },{ .name = "XRAM_ISR", .addr = A_XRAM_ISR,
961
+ }
189
+ .rsvd = 0xfffff800,
962
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
190
+ .w1c = 0x7ff,
963
+ if (!qdev_realize(DEVICE(&s->sels[i]), NULL, errp)) {
191
+ .post_write = xram_isr_postw,
964
+ return;
192
+ },{ .name = "XRAM_IMR", .addr = A_XRAM_IMR,
965
+ }
193
+ .reset = 0x7ff,
966
+ }
194
+ .rsvd = 0xfffff800,
967
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
195
+ .ro = 0x7ff,
968
+ if (!qdev_realize(DEVICE(&s->dividers[i]), NULL, errp)) {
196
+ },{ .name = "XRAM_IEN", .addr = A_XRAM_IEN,
969
+ return;
197
+ .rsvd = 0xfffff800,
970
+ }
198
+ .pre_write = xram_ien_prew,
971
+ }
199
+ },{ .name = "XRAM_IDS", .addr = A_XRAM_IDS,
972
+}
200
+ .rsvd = 0xfffff800,
973
+
201
+ .pre_write = xram_ids_prew,
974
+static const VMStateDescription vmstate_npcm7xx_clk_pll = {
202
+ },{ .name = "XRAM_ECC_CNTL", .addr = A_XRAM_ECC_CNTL,
975
+ .name = "npcm7xx-clock-pll",
203
+ .rsvd = 0xfffffff8,
976
.version_id = 0,
204
+ },{ .name = "XRAM_CLR_EXE", .addr = A_XRAM_CLR_EXE,
977
.minimum_version_id = 0,
205
+ .rsvd = 0xffffff00,
978
- .fields = (VMStateField[]) {
206
+ },{ .name = "XRAM_CE_FFA", .addr = A_XRAM_CE_FFA,
979
- VMSTATE_UINT32_ARRAY(regs, NPCM7xxCLKState, NPCM7XX_CLK_NR_REGS),
207
+ .rsvd = 0xfff00000,
980
- VMSTATE_INT64(ref_ns, NPCM7xxCLKState),
208
+ .ro = 0xfffff,
981
+ .fields = (VMStateField[]) {
209
+ },{ .name = "XRAM_CE_FFD0", .addr = A_XRAM_CE_FFD0,
982
+ VMSTATE_CLOCK(clock_in, NPCM7xxClockPLLState),
210
+ .ro = 0xffffffff,
983
VMSTATE_END_OF_LIST(),
211
+ },{ .name = "XRAM_CE_FFD1", .addr = A_XRAM_CE_FFD1,
984
},
212
+ .ro = 0xffffffff,
985
};
213
+ },{ .name = "XRAM_CE_FFD2", .addr = A_XRAM_CE_FFD2,
986
214
+ .ro = 0xffffffff,
987
+static const VMStateDescription vmstate_npcm7xx_clk_sel = {
215
+ },{ .name = "XRAM_CE_FFD3", .addr = A_XRAM_CE_FFD3,
988
+ .name = "npcm7xx-clock-sel",
216
+ .ro = 0xffffffff,
989
+ .version_id = 0,
217
+ },{ .name = "XRAM_CE_FFE", .addr = A_XRAM_CE_FFE,
990
+ .minimum_version_id = 0,
218
+ .rsvd = 0xffff0000,
991
+ .fields = (VMStateField[]) {
219
+ .ro = 0xffff,
992
+ VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(clock_in, NPCM7xxClockSELState,
220
+ },{ .name = "XRAM_UE_FFA", .addr = A_XRAM_UE_FFA,
993
+ NPCM7XX_CLK_SEL_MAX_INPUT, 0, vmstate_clock, Clock),
221
+ .rsvd = 0xfff00000,
994
+ VMSTATE_END_OF_LIST(),
222
+ .ro = 0xfffff,
995
+ },
223
+ },{ .name = "XRAM_UE_FFD0", .addr = A_XRAM_UE_FFD0,
224
+ .ro = 0xffffffff,
225
+ },{ .name = "XRAM_UE_FFD1", .addr = A_XRAM_UE_FFD1,
226
+ .ro = 0xffffffff,
227
+ },{ .name = "XRAM_UE_FFD2", .addr = A_XRAM_UE_FFD2,
228
+ .ro = 0xffffffff,
229
+ },{ .name = "XRAM_UE_FFD3", .addr = A_XRAM_UE_FFD3,
230
+ .ro = 0xffffffff,
231
+ },{ .name = "XRAM_UE_FFE", .addr = A_XRAM_UE_FFE,
232
+ .rsvd = 0xffff0000,
233
+ .ro = 0xffff,
234
+ },{ .name = "XRAM_FI_D0", .addr = A_XRAM_FI_D0,
235
+ },{ .name = "XRAM_FI_D1", .addr = A_XRAM_FI_D1,
236
+ },{ .name = "XRAM_FI_D2", .addr = A_XRAM_FI_D2,
237
+ },{ .name = "XRAM_FI_D3", .addr = A_XRAM_FI_D3,
238
+ },{ .name = "XRAM_FI_SY", .addr = A_XRAM_FI_SY,
239
+ .rsvd = 0xffff0000,
240
+ },{ .name = "XRAM_RMW_UE_FFA", .addr = A_XRAM_RMW_UE_FFA,
241
+ .rsvd = 0xfff00000,
242
+ .ro = 0xfffff,
243
+ },{ .name = "XRAM_FI_CNTR", .addr = A_XRAM_FI_CNTR,
244
+ .rsvd = 0xff000000,
245
+ },{ .name = "XRAM_IMP", .addr = A_XRAM_IMP,
246
+ .reset = 0x4,
247
+ .rsvd = 0xfffffff0,
248
+ .ro = 0xf,
249
+ },{ .name = "XRAM_PRDY_DBG", .addr = A_XRAM_PRDY_DBG,
250
+ .reset = 0xffff,
251
+ .rsvd = 0xffff0000,
252
+ .ro = 0xffff,
253
+ },{ .name = "XRAM_SAFETY_CHK", .addr = A_XRAM_SAFETY_CHK,
254
+ }
255
+};
996
+};
256
+
997
+
257
+static void xram_ctrl_reset_enter(Object *obj, ResetType type)
998
+static const VMStateDescription vmstate_npcm7xx_clk_divider = {
258
+{
999
+ .name = "npcm7xx-clock-divider",
259
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
1000
+ .version_id = 0,
260
+ unsigned int i;
1001
+ .minimum_version_id = 0,
261
+
1002
+ .fields = (VMStateField[]) {
262
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
1003
+ VMSTATE_CLOCK(clock_in, NPCM7xxClockDividerState),
263
+ register_reset(&s->regs_info[i]);
1004
+ VMSTATE_END_OF_LIST(),
264
+ }
265
+
266
+ ARRAY_FIELD_DP32(s->regs, XRAM_IMP, SIZE, s->cfg.encoded_size);
267
+}
268
+
269
+static void xram_ctrl_reset_hold(Object *obj)
270
+{
271
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
272
+
273
+ xram_update_irq(s);
274
+}
275
+
276
+static const MemoryRegionOps xram_ctrl_ops = {
277
+ .read = register_read_memory,
278
+ .write = register_write_memory,
279
+ .endianness = DEVICE_LITTLE_ENDIAN,
280
+ .valid = {
281
+ .min_access_size = 4,
282
+ .max_access_size = 4,
283
+ },
1005
+ },
284
+};
1006
+};
285
+
1007
+
286
+static void xram_ctrl_realize(DeviceState *dev, Error **errp)
1008
+static const VMStateDescription vmstate_npcm7xx_clk = {
287
+{
1009
+ .name = "npcm7xx-clk",
288
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
289
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(dev);
290
+
291
+ switch (s->cfg.size) {
292
+ case 64 * KiB:
293
+ s->cfg.encoded_size = 0;
294
+ break;
295
+ case 128 * KiB:
296
+ s->cfg.encoded_size = 1;
297
+ break;
298
+ case 256 * KiB:
299
+ s->cfg.encoded_size = 2;
300
+ break;
301
+ case 512 * KiB:
302
+ s->cfg.encoded_size = 3;
303
+ break;
304
+ case 1 * MiB:
305
+ s->cfg.encoded_size = 4;
306
+ break;
307
+ default:
308
+ error_setg(errp, "Unsupported XRAM size %" PRId64, s->cfg.size);
309
+ return;
310
+ }
311
+
312
+ memory_region_init_ram(&s->ram, OBJECT(s),
313
+ object_get_canonical_path_component(OBJECT(s)),
314
+ s->cfg.size, &error_fatal);
315
+ sysbus_init_mmio(sbd, &s->ram);
316
+}
317
+
318
+static void xram_ctrl_init(Object *obj)
319
+{
320
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
321
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
322
+
323
+ s->reg_array =
324
+ register_init_block32(DEVICE(obj), xram_ctrl_regs_info,
325
+ ARRAY_SIZE(xram_ctrl_regs_info),
326
+ s->regs_info, s->regs,
327
+ &xram_ctrl_ops,
328
+ XLNX_XRAM_CTRL_ERR_DEBUG,
329
+ XRAM_CTRL_R_MAX * 4);
330
+ sysbus_init_mmio(sbd, &s->reg_array->mem);
331
+ sysbus_init_irq(sbd, &s->irq);
332
+}
333
+
334
+static void xram_ctrl_finalize(Object *obj)
335
+{
336
+ XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
337
+ register_finalize_block(s->reg_array);
338
+}
339
+
340
+static const VMStateDescription vmstate_xram_ctrl = {
341
+ .name = TYPE_XLNX_XRAM_CTRL,
342
+ .version_id = 1,
1010
+ .version_id = 1,
343
+ .minimum_version_id = 1,
1011
+ .minimum_version_id = 1,
1012
+ .post_load = npcm7xx_clk_post_load,
344
+ .fields = (VMStateField[]) {
1013
+ .fields = (VMStateField[]) {
345
+ VMSTATE_UINT32_ARRAY(regs, XlnxXramCtrl, XRAM_CTRL_R_MAX),
1014
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxCLKState, NPCM7XX_CLK_NR_REGS),
1015
+ VMSTATE_INT64(ref_ns, NPCM7xxCLKState),
1016
+ VMSTATE_CLOCK(clkref, NPCM7xxCLKState),
346
+ VMSTATE_END_OF_LIST(),
1017
+ VMSTATE_END_OF_LIST(),
347
+ }
1018
+ },
348
+};
1019
+};
349
+
1020
+
350
+static Property xram_ctrl_properties[] = {
1021
+static void npcm7xx_clk_pll_class_init(ObjectClass *klass, void *data)
351
+ DEFINE_PROP_UINT64("size", XlnxXramCtrl, cfg.size, 1 * MiB),
1022
+{
352
+ DEFINE_PROP_END_OF_LIST(),
1023
+ DeviceClass *dc = DEVICE_CLASS(klass);
1024
+
1025
+ dc->desc = "NPCM7xx Clock PLL Module";
1026
+ dc->vmsd = &vmstate_npcm7xx_clk_pll;
1027
+}
1028
+
1029
+static void npcm7xx_clk_sel_class_init(ObjectClass *klass, void *data)
1030
+{
1031
+ DeviceClass *dc = DEVICE_CLASS(klass);
1032
+
1033
+ dc->desc = "NPCM7xx Clock SEL Module";
1034
+ dc->vmsd = &vmstate_npcm7xx_clk_sel;
1035
+}
1036
+
1037
+static void npcm7xx_clk_divider_class_init(ObjectClass *klass, void *data)
1038
+{
1039
+ DeviceClass *dc = DEVICE_CLASS(klass);
1040
+
1041
+ dc->desc = "NPCM7xx Clock Divider Module";
1042
+ dc->vmsd = &vmstate_npcm7xx_clk_divider;
1043
+}
1044
+
1045
static void npcm7xx_clk_class_init(ObjectClass *klass, void *data)
1046
{
1047
ResettableClass *rc = RESETTABLE_CLASS(klass);
1048
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_class_init(ObjectClass *klass, void *data)
1049
1050
dc->desc = "NPCM7xx Clock Control Registers";
1051
dc->vmsd = &vmstate_npcm7xx_clk;
1052
+ dc->realize = npcm7xx_clk_realize;
1053
rc->phases.enter = npcm7xx_clk_enter_reset;
1054
}
1055
1056
+static const TypeInfo npcm7xx_clk_pll_info = {
1057
+ .name = TYPE_NPCM7XX_CLOCK_PLL,
1058
+ .parent = TYPE_DEVICE,
1059
+ .instance_size = sizeof(NPCM7xxClockPLLState),
1060
+ .instance_init = npcm7xx_clk_pll_init,
1061
+ .class_init = npcm7xx_clk_pll_class_init,
353
+};
1062
+};
354
+
1063
+
355
+static void xram_ctrl_class_init(ObjectClass *klass, void *data)
1064
+static const TypeInfo npcm7xx_clk_sel_info = {
356
+{
1065
+ .name = TYPE_NPCM7XX_CLOCK_SEL,
357
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
1066
+ .parent = TYPE_DEVICE,
358
+ DeviceClass *dc = DEVICE_CLASS(klass);
1067
+ .instance_size = sizeof(NPCM7xxClockSELState),
359
+
1068
+ .instance_init = npcm7xx_clk_sel_init,
360
+ dc->realize = xram_ctrl_realize;
1069
+ .class_init = npcm7xx_clk_sel_class_init,
361
+ dc->vmsd = &vmstate_xram_ctrl;
362
+ device_class_set_props(dc, xram_ctrl_properties);
363
+
364
+ rc->phases.enter = xram_ctrl_reset_enter;
365
+ rc->phases.hold = xram_ctrl_reset_hold;
366
+}
367
+
368
+static const TypeInfo xram_ctrl_info = {
369
+ .name = TYPE_XLNX_XRAM_CTRL,
370
+ .parent = TYPE_SYS_BUS_DEVICE,
371
+ .instance_size = sizeof(XlnxXramCtrl),
372
+ .class_init = xram_ctrl_class_init,
373
+ .instance_init = xram_ctrl_init,
374
+ .instance_finalize = xram_ctrl_finalize,
375
+};
1070
+};
376
+
1071
+
377
+static void xram_ctrl_register_types(void)
1072
+static const TypeInfo npcm7xx_clk_divider_info = {
378
+{
1073
+ .name = TYPE_NPCM7XX_CLOCK_DIVIDER,
379
+ type_register_static(&xram_ctrl_info);
1074
+ .parent = TYPE_DEVICE,
380
+}
1075
+ .instance_size = sizeof(NPCM7xxClockDividerState),
381
+
1076
+ .instance_init = npcm7xx_clk_divider_init,
382
+type_init(xram_ctrl_register_types)
1077
+ .class_init = npcm7xx_clk_divider_class_init,
383
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
1078
+};
384
index XXXXXXX..XXXXXXX 100644
1079
+
385
--- a/hw/misc/meson.build
1080
static const TypeInfo npcm7xx_clk_info = {
386
+++ b/hw/misc/meson.build
1081
.name = TYPE_NPCM7XX_CLK,
387
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files(
1082
.parent = TYPE_SYS_BUS_DEVICE,
388
))
1083
@@ -XXX,XX +XXX,XX @@ static const TypeInfo npcm7xx_clk_info = {
389
softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c'))
1084
390
softmmu_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c', 'zynq-xadc.c'))
1085
static void npcm7xx_clk_register_type(void)
391
+softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-xramc.c'))
1086
{
392
softmmu_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.c'))
1087
+ type_register_static(&npcm7xx_clk_pll_info);
393
softmmu_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.c'))
1088
+ type_register_static(&npcm7xx_clk_sel_info);
394
softmmu_ss.add(when: 'CONFIG_STM32F4XX_EXTI', if_true: files('stm32f4xx_exti.c'))
1089
+ type_register_static(&npcm7xx_clk_divider_info);
1090
type_register_static(&npcm7xx_clk_info);
1091
}
1092
type_init(npcm7xx_clk_register_type);
395
--
1093
--
396
2.20.1
1094
2.20.1
397
1095
398
1096
diff view generated by jsdifflib
Deleted patch
1
From: Eric Auger <eric.auger@redhat.com>
2
1
3
With -Werror=maybe-uninitialized configuration we get
4
../hw/i386/intel_iommu.c: In function ‘vtd_context_device_invalidate’:
5
../hw/i386/intel_iommu.c:1888:10: error: ‘mask’ may be used
6
uninitialized in this function [-Werror=maybe-uninitialized]
7
1888 | mask = ~mask;
8
| ~~~~~^~~~~~~
9
10
Add a g_assert_not_reached() to avoid the error.
11
12
Signed-off-by: Eric Auger <eric.auger@redhat.com>
13
Reviewed-by: Peter Xu <peterx@redhat.com>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
15
Message-id: 20210309102742.30442-2-eric.auger@redhat.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
hw/i386/intel_iommu.c | 2 ++
19
1 file changed, 2 insertions(+)
20
21
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/i386/intel_iommu.c
24
+++ b/hw/i386/intel_iommu.c
25
@@ -XXX,XX +XXX,XX @@ static void vtd_context_device_invalidate(IntelIOMMUState *s,
26
case 3:
27
mask = 7; /* Mask bit 2:0 in the SID field */
28
break;
29
+ default:
30
+ g_assert_not_reached();
31
}
32
mask = ~mask;
33
34
--
35
2.20.1
36
37
diff view generated by jsdifflib
Deleted patch
1
From: Eric Auger <eric.auger@redhat.com>
2
1
3
Currently get_naturally_aligned_size() is used by the intel iommu
4
to compute the maximum invalidation range based on @size which is
5
a power of 2 while being aligned with the @start address and less
6
than the maximum range defined by @gaw.
7
8
This helper is also useful for other iommu devices (virtio-iommu,
9
SMMUv3) to make sure IOMMU UNMAP notifiers only are called with
10
power of 2 range sizes.
11
12
Let's move this latter into dma-helpers.c and rename it into
13
dma_aligned_pow2_mask(). Also rewrite the helper so that it
14
accomodates UINT64_MAX values for the size mask and max mask.
15
It now returns a mask instead of a size. Change the caller.
16
17
Signed-off-by: Eric Auger <eric.auger@redhat.com>
18
Reviewed-by: Peter Xu <peterx@redhat.com>
19
Message-id: 20210309102742.30442-3-eric.auger@redhat.com
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
22
include/sysemu/dma.h | 12 ++++++++++++
23
hw/i386/intel_iommu.c | 30 +++++++-----------------------
24
softmmu/dma-helpers.c | 26 ++++++++++++++++++++++++++
25
3 files changed, 45 insertions(+), 23 deletions(-)
26
27
diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/include/sysemu/dma.h
30
+++ b/include/sysemu/dma.h
31
@@ -XXX,XX +XXX,XX @@ uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg);
32
void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,
33
QEMUSGList *sg, enum BlockAcctType type);
34
35
+/**
36
+ * dma_aligned_pow2_mask: Return the address bit mask of the largest
37
+ * power of 2 size less or equal than @end - @start + 1, aligned with @start,
38
+ * and bounded by 1 << @max_addr_bits bits.
39
+ *
40
+ * @start: range start address
41
+ * @end: range end address (greater than @start)
42
+ * @max_addr_bits: max address bits (<= 64)
43
+ */
44
+uint64_t dma_aligned_pow2_mask(uint64_t start, uint64_t end,
45
+ int max_addr_bits);
46
+
47
#endif
48
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/i386/intel_iommu.c
51
+++ b/hw/i386/intel_iommu.c
52
@@ -XXX,XX +XXX,XX @@
53
#include "hw/i386/x86-iommu.h"
54
#include "hw/pci-host/q35.h"
55
#include "sysemu/kvm.h"
56
+#include "sysemu/dma.h"
57
#include "sysemu/sysemu.h"
58
#include "hw/i386/apic_internal.h"
59
#include "kvm/kvm_i386.h"
60
@@ -XXX,XX +XXX,XX @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
61
return vtd_dev_as;
62
}
63
64
-static uint64_t get_naturally_aligned_size(uint64_t start,
65
- uint64_t size, int gaw)
66
-{
67
- uint64_t max_mask = 1ULL << gaw;
68
- uint64_t alignment = start ? start & -start : max_mask;
69
-
70
- alignment = MIN(alignment, max_mask);
71
- size = MIN(size, max_mask);
72
-
73
- if (alignment <= size) {
74
- /* Increase the alignment of start */
75
- return alignment;
76
- } else {
77
- /* Find the largest page mask from size */
78
- return 1ULL << (63 - clz64(size));
79
- }
80
-}
81
-
82
/* Unmap the whole range in the notifier's scope. */
83
static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n)
84
{
85
@@ -XXX,XX +XXX,XX @@ static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n)
86
87
while (remain >= VTD_PAGE_SIZE) {
88
IOMMUTLBEvent event;
89
- uint64_t mask = get_naturally_aligned_size(start, remain, s->aw_bits);
90
+ uint64_t mask = dma_aligned_pow2_mask(start, end, s->aw_bits);
91
+ uint64_t size = mask + 1;
92
93
- assert(mask);
94
+ assert(size);
95
96
event.type = IOMMU_NOTIFIER_UNMAP;
97
event.entry.iova = start;
98
- event.entry.addr_mask = mask - 1;
99
+ event.entry.addr_mask = mask;
100
event.entry.target_as = &address_space_memory;
101
event.entry.perm = IOMMU_NONE;
102
/* This field is meaningless for unmap */
103
@@ -XXX,XX +XXX,XX @@ static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n)
104
105
memory_region_notify_iommu_one(n, &event);
106
107
- start += mask;
108
- remain -= mask;
109
+ start += size;
110
+ remain -= size;
111
}
112
113
assert(!remain);
114
diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c
115
index XXXXXXX..XXXXXXX 100644
116
--- a/softmmu/dma-helpers.c
117
+++ b/softmmu/dma-helpers.c
118
@@ -XXX,XX +XXX,XX @@ void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,
119
{
120
block_acct_start(blk_get_stats(blk), cookie, sg->size, type);
121
}
122
+
123
+uint64_t dma_aligned_pow2_mask(uint64_t start, uint64_t end, int max_addr_bits)
124
+{
125
+ uint64_t max_mask = UINT64_MAX, addr_mask = end - start;
126
+ uint64_t alignment_mask, size_mask;
127
+
128
+ if (max_addr_bits != 64) {
129
+ max_mask = (1ULL << max_addr_bits) - 1;
130
+ }
131
+
132
+ alignment_mask = start ? (start & -start) - 1 : max_mask;
133
+ alignment_mask = MIN(alignment_mask, max_mask);
134
+ size_mask = MIN(addr_mask, max_mask);
135
+
136
+ if (alignment_mask <= size_mask) {
137
+ /* Increase the alignment of start */
138
+ return alignment_mask;
139
+ } else {
140
+ /* Find the largest page mask from size */
141
+ if (addr_mask == UINT64_MAX) {
142
+ return UINT64_MAX;
143
+ }
144
+ return (1ULL << (63 - clz64(addr_mask + 1))) - 1;
145
+ }
146
+}
147
+
148
--
149
2.20.1
150
151
diff view generated by jsdifflib
Deleted patch
1
From: Eric Auger <eric.auger@redhat.com>
2
1
3
As of today, the driver can invalidate a number of pages that is
4
not a power of 2. However IOTLB unmap notifications and internal
5
IOTLB invalidations work with masks leading to erroneous
6
invalidations.
7
8
In case the range is not a power of 2, split invalidations into
9
power of 2 invalidations.
10
11
When looking for a single page entry in the vSMMU internal IOTLB,
12
let's make sure that if the entry is not found using a
13
g_hash_table_remove() we iterate over all the entries to find a
14
potential range that overlaps it.
15
16
Signed-off-by: Eric Auger <eric.auger@redhat.com>
17
Message-id: 20210309102742.30442-6-eric.auger@redhat.com
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
21
hw/arm/smmu-common.c | 30 ++++++++++++++++++------------
22
hw/arm/smmuv3.c | 24 ++++++++++++++++++++----
23
2 files changed, 38 insertions(+), 16 deletions(-)
24
25
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/smmu-common.c
28
+++ b/hw/arm/smmu-common.c
29
@@ -XXX,XX +XXX,XX @@ inline void
30
smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova,
31
uint8_t tg, uint64_t num_pages, uint8_t ttl)
32
{
33
+ /* if tg is not set we use 4KB range invalidation */
34
+ uint8_t granule = tg ? tg * 2 + 10 : 12;
35
+
36
if (ttl && (num_pages == 1) && (asid >= 0)) {
37
SMMUIOTLBKey key = smmu_get_iotlb_key(asid, iova, tg, ttl);
38
39
- g_hash_table_remove(s->iotlb, &key);
40
- } else {
41
- /* if tg is not set we use 4KB range invalidation */
42
- uint8_t granule = tg ? tg * 2 + 10 : 12;
43
-
44
- SMMUIOTLBPageInvInfo info = {
45
- .asid = asid, .iova = iova,
46
- .mask = (num_pages * 1 << granule) - 1};
47
-
48
- g_hash_table_foreach_remove(s->iotlb,
49
- smmu_hash_remove_by_asid_iova,
50
- &info);
51
+ if (g_hash_table_remove(s->iotlb, &key)) {
52
+ return;
53
+ }
54
+ /*
55
+ * if the entry is not found, let's see if it does not
56
+ * belong to a larger IOTLB entry
57
+ */
58
}
59
+
60
+ SMMUIOTLBPageInvInfo info = {
61
+ .asid = asid, .iova = iova,
62
+ .mask = (num_pages * 1 << granule) - 1};
63
+
64
+ g_hash_table_foreach_remove(s->iotlb,
65
+ smmu_hash_remove_by_asid_iova,
66
+ &info);
67
}
68
69
inline void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid)
70
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/hw/arm/smmuv3.c
73
+++ b/hw/arm/smmuv3.c
74
@@ -XXX,XX +XXX,XX @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
75
uint16_t vmid = CMD_VMID(cmd);
76
bool leaf = CMD_LEAF(cmd);
77
uint8_t tg = CMD_TG(cmd);
78
- hwaddr num_pages = 1;
79
+ uint64_t first_page = 0, last_page;
80
+ uint64_t num_pages = 1;
81
int asid = -1;
82
83
if (tg) {
84
@@ -XXX,XX +XXX,XX @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
85
if (type == SMMU_CMD_TLBI_NH_VA) {
86
asid = CMD_ASID(cmd);
87
}
88
- trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, num_pages, ttl, leaf);
89
- smmuv3_inv_notifiers_iova(s, asid, addr, tg, num_pages);
90
- smmu_iotlb_inv_iova(s, asid, addr, tg, num_pages, ttl);
91
+
92
+ /* Split invalidations into ^2 range invalidations */
93
+ last_page = num_pages - 1;
94
+ while (num_pages) {
95
+ uint8_t granule = tg * 2 + 10;
96
+ uint64_t mask, count;
97
+
98
+ mask = dma_aligned_pow2_mask(first_page, last_page, 64 - granule);
99
+ count = mask + 1;
100
+
101
+ trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, count, ttl, leaf);
102
+ smmuv3_inv_notifiers_iova(s, asid, addr, tg, count);
103
+ smmu_iotlb_inv_iova(s, asid, addr, tg, count, ttl);
104
+
105
+ num_pages -= count;
106
+ first_page += count;
107
+ addr += count * BIT_ULL(granule);
108
+ }
109
}
110
111
static int smmuv3_cmdq_consume(SMMUv3State *s)
112
--
113
2.20.1
114
115
diff view generated by jsdifflib
Deleted patch
1
From: Eric Auger <eric.auger@redhat.com>
2
1
3
If the whole SID range (32b) is invalidated (SMMU_CMD_CFGI_ALL),
4
@end overflows and we fail to handle the command properly.
5
6
Once this gets fixed, the current code really is awkward in the
7
sense it loops over the whole range instead of removing the
8
currently cached configs through a hash table lookup.
9
10
Fix both the overflow and the lookup.
11
12
Signed-off-by: Eric Auger <eric.auger@redhat.com>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20210309102742.30442-7-eric.auger@redhat.com
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
hw/arm/smmu-internal.h | 5 +++++
18
hw/arm/smmuv3.c | 34 ++++++++++++++++++++--------------
19
2 files changed, 25 insertions(+), 14 deletions(-)
20
21
diff --git a/hw/arm/smmu-internal.h b/hw/arm/smmu-internal.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/smmu-internal.h
24
+++ b/hw/arm/smmu-internal.h
25
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUIOTLBPageInvInfo {
26
uint64_t mask;
27
} SMMUIOTLBPageInvInfo;
28
29
+typedef struct SMMUSIDRange {
30
+ uint32_t start;
31
+ uint32_t end;
32
+} SMMUSIDRange;
33
+
34
#endif
35
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/arm/smmuv3.c
38
+++ b/hw/arm/smmuv3.c
39
@@ -XXX,XX +XXX,XX @@
40
41
#include "hw/arm/smmuv3.h"
42
#include "smmuv3-internal.h"
43
+#include "smmu-internal.h"
44
45
/**
46
* smmuv3_trigger_irq - pulse @irq if enabled and update
47
@@ -XXX,XX +XXX,XX @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
48
}
49
}
50
51
+static gboolean
52
+smmuv3_invalidate_ste(gpointer key, gpointer value, gpointer user_data)
53
+{
54
+ SMMUDevice *sdev = (SMMUDevice *)key;
55
+ uint32_t sid = smmu_get_sid(sdev);
56
+ SMMUSIDRange *sid_range = (SMMUSIDRange *)user_data;
57
+
58
+ if (sid < sid_range->start || sid > sid_range->end) {
59
+ return false;
60
+ }
61
+ trace_smmuv3_config_cache_inv(sid);
62
+ return true;
63
+}
64
+
65
static int smmuv3_cmdq_consume(SMMUv3State *s)
66
{
67
SMMUState *bs = ARM_SMMU(s);
68
@@ -XXX,XX +XXX,XX @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
69
}
70
case SMMU_CMD_CFGI_STE_RANGE: /* same as SMMU_CMD_CFGI_ALL */
71
{
72
- uint32_t start = CMD_SID(&cmd), end, i;
73
+ uint32_t start = CMD_SID(&cmd);
74
uint8_t range = CMD_STE_RANGE(&cmd);
75
+ uint64_t end = start + (1ULL << (range + 1)) - 1;
76
+ SMMUSIDRange sid_range = {start, end};
77
78
if (CMD_SSEC(&cmd)) {
79
cmd_error = SMMU_CERROR_ILL;
80
break;
81
}
82
-
83
- end = start + (1 << (range + 1)) - 1;
84
trace_smmuv3_cmdq_cfgi_ste_range(start, end);
85
-
86
- for (i = start; i <= end; i++) {
87
- IOMMUMemoryRegion *mr = smmu_iommu_mr(bs, i);
88
- SMMUDevice *sdev;
89
-
90
- if (!mr) {
91
- continue;
92
- }
93
- sdev = container_of(mr, SMMUDevice, iommu);
94
- smmuv3_flush_config(sdev);
95
- }
96
+ g_hash_table_foreach_remove(bs->configs, smmuv3_invalidate_ste,
97
+ &sid_range);
98
break;
99
}
100
case SMMU_CMD_CFGI_CD:
101
--
102
2.20.1
103
104
diff view generated by jsdifflib
Deleted patch
1
From: Eric Auger <eric.auger@redhat.com>
2
1
3
Convert all sid printouts to sid=0x%x.
4
5
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Message-id: 20210309102742.30442-8-eric.auger@redhat.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
hw/arm/trace-events | 24 ++++++++++++------------
11
1 file changed, 12 insertions(+), 12 deletions(-)
12
13
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/trace-events
16
+++ b/hw/arm/trace-events
17
@@ -XXX,XX +XXX,XX @@ smmuv3_cmdq_opcode(const char *opcode) "<--- %s"
18
smmuv3_cmdq_consume_out(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "prod:%d, cons:%d, prod_wrap:%d, cons_wrap:%d "
19
smmuv3_cmdq_consume_error(const char *cmd_name, uint8_t cmd_error) "Error on %s command execution: %d"
20
smmuv3_write_mmio(uint64_t addr, uint64_t val, unsigned size, uint32_t r) "addr: 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x(%d)"
21
-smmuv3_record_event(const char *type, uint32_t sid) "%s sid=%d"
22
-smmuv3_find_ste(uint16_t sid, uint32_t features, uint16_t sid_split) "SID:0x%x features:0x%x, sid_split:0x%x"
23
+smmuv3_record_event(const char *type, uint32_t sid) "%s sid=0x%x"
24
+smmuv3_find_ste(uint16_t sid, uint32_t features, uint16_t sid_split) "sid=0x%x features:0x%x, sid_split:0x%x"
25
smmuv3_find_ste_2lvl(uint64_t strtab_base, uint64_t l1ptr, int l1_ste_offset, uint64_t l2ptr, int l2_ste_offset, int max_l2_ste) "strtab_base:0x%"PRIx64" l1ptr:0x%"PRIx64" l1_off:0x%x, l2ptr:0x%"PRIx64" l2_off:0x%x max_l2_ste:%d"
26
smmuv3_get_ste(uint64_t addr) "STE addr: 0x%"PRIx64
27
-smmuv3_translate_disable(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=%d bypass (smmu disabled) iova:0x%"PRIx64" is_write=%d"
28
-smmuv3_translate_bypass(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=%d STE bypass iova:0x%"PRIx64" is_write=%d"
29
-smmuv3_translate_abort(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=%d abort on iova:0x%"PRIx64" is_write=%d"
30
-smmuv3_translate_success(const char *n, uint16_t sid, uint64_t iova, uint64_t translated, int perm) "%s sid=%d iova=0x%"PRIx64" translated=0x%"PRIx64" perm=0x%x"
31
+smmuv3_translate_disable(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=0x%x bypass (smmu disabled) iova:0x%"PRIx64" is_write=%d"
32
+smmuv3_translate_bypass(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=0x%x STE bypass iova:0x%"PRIx64" is_write=%d"
33
+smmuv3_translate_abort(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=0x%x abort on iova:0x%"PRIx64" is_write=%d"
34
+smmuv3_translate_success(const char *n, uint16_t sid, uint64_t iova, uint64_t translated, int perm) "%s sid=0x%x iova=0x%"PRIx64" translated=0x%"PRIx64" perm=0x%x"
35
smmuv3_get_cd(uint64_t addr) "CD addr: 0x%"PRIx64
36
smmuv3_decode_cd(uint32_t oas) "oas=%d"
37
smmuv3_decode_cd_tt(int i, uint32_t tsz, uint64_t ttb, uint32_t granule_sz, bool had) "TT[%d]:tsz:%d ttb:0x%"PRIx64" granule_sz:%d had:%d"
38
-smmuv3_cmdq_cfgi_ste(int streamid) "streamid =%d"
39
+smmuv3_cmdq_cfgi_ste(int streamid) "streamid= 0x%x"
40
smmuv3_cmdq_cfgi_ste_range(int start, int end) "start=0x%x - end=0x%x"
41
-smmuv3_cmdq_cfgi_cd(uint32_t sid) "streamid = %d"
42
-smmuv3_config_cache_hit(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache HIT for sid %d (hits=%d, misses=%d, hit rate=%d)"
43
-smmuv3_config_cache_miss(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache MISS for sid %d (hits=%d, misses=%d, hit rate=%d)"
44
-smmuv3_s1_range_inval(int vmid, int asid, uint64_t addr, uint8_t tg, uint64_t num_pages, uint8_t ttl, bool leaf) "vmid =%d asid =%d addr=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64" ttl=%d leaf=%d"
45
+smmuv3_cmdq_cfgi_cd(uint32_t sid) "sid=0x%x"
46
+smmuv3_config_cache_hit(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache HIT for sid=0x%x (hits=%d, misses=%d, hit rate=%d)"
47
+smmuv3_config_cache_miss(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache MISS for sid=0x%x (hits=%d, misses=%d, hit rate=%d)"
48
+smmuv3_s1_range_inval(int vmid, int asid, uint64_t addr, uint8_t tg, uint64_t num_pages, uint8_t ttl, bool leaf) "vmid=%d asid=%d addr=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64" ttl=%d leaf=%d"
49
smmuv3_cmdq_tlbi_nh(void) ""
50
smmuv3_cmdq_tlbi_nh_asid(uint16_t asid) "asid=%d"
51
-smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid %d"
52
+smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid=0x%x"
53
smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu mr=%s"
54
smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu mr=%s"
55
smmuv3_inv_notifiers_iova(const char *name, uint16_t asid, uint64_t iova, uint8_t tg, uint64_t num_pages) "iommu mr=%s asid=%d iova=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64
56
--
57
2.20.1
58
59
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
This patch adds fan_splitters (split IRQs) in NPCM7XX boards. Each fan
3
This patch makes NPCM7XX Timer to use a the timer clock generated by the
4
splitter corresponds to 1 PWM output and can connect to multiple fan
4
CLK module instead of the magic number TIMER_REF_HZ.
5
inputs (MFT devices).
6
In NPCM7XX boards(NPCM750 EVB and Quanta GSJ boards), we initializes
7
these splitters and connect them to their corresponding modules
8
according their specific device trees.
9
5
10
Reviewed-by: Doug Evans <dje@google.com>
6
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
11
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
12
Signed-off-by: Hao Wu <wuhaotsh@google.com>
8
Signed-off-by: Hao Wu <wuhaotsh@google.com>
9
Message-id: 20210108190945.949196-3-wuhaotsh@google.com
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20210311180855.149764-5-wuhaotsh@google.com
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
12
---
17
include/hw/arm/npcm7xx.h | 11 ++++-
13
include/hw/misc/npcm7xx_clk.h | 6 -----
18
hw/arm/npcm7xx_boards.c | 99 ++++++++++++++++++++++++++++++++++++++++
14
include/hw/timer/npcm7xx_timer.h | 1 +
19
2 files changed, 109 insertions(+), 1 deletion(-)
15
hw/arm/npcm7xx.c | 5 ++++
16
hw/timer/npcm7xx_timer.c | 39 +++++++++++++++-----------------
17
4 files changed, 24 insertions(+), 27 deletions(-)
20
18
21
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
19
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
22
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/arm/npcm7xx.h
21
--- a/include/hw/misc/npcm7xx_clk.h
24
+++ b/include/hw/arm/npcm7xx.h
22
+++ b/include/hw/misc/npcm7xx_clk.h
25
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
26
24
#include "hw/clock.h"
27
#include "hw/boards.h"
25
#include "hw/sysbus.h"
28
#include "hw/adc/npcm7xx_adc.h"
26
29
+#include "hw/core/split-irq.h"
27
-/*
30
#include "hw/cpu/a9mpcore.h"
28
- * The reference clock frequency for the timer modules, and the SECCNT and
31
#include "hw/gpio/npcm7xx_gpio.h"
29
- * CNTR25M registers in this module, is always 25 MHz.
32
#include "hw/i2c/npcm7xx_smbus.h"
30
- */
31
-#define NPCM7XX_TIMER_REF_HZ (25000000)
32
-
33
/*
34
* Number of registers in our device state structure. Don't change this without
35
* incrementing the version_id in the vmstate.
36
diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/timer/npcm7xx_timer.h
39
+++ b/include/hw/timer/npcm7xx_timer.h
40
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxTimerCtrlState {
41
42
uint32_t tisr;
43
44
+ Clock *clock;
45
NPCM7xxTimer timer[NPCM7XX_TIMERS_PER_CTRL];
46
NPCM7xxWatchdogTimer watchdog_timer;
47
};
48
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/arm/npcm7xx.c
51
+++ b/hw/arm/npcm7xx.c
33
@@ -XXX,XX +XXX,XX @@
52
@@ -XXX,XX +XXX,XX @@
34
#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100) /* GIC within A9 */
53
#include "hw/char/serial.h"
35
#define NPCM7XX_BOARD_SETUP_ADDR (0xffff1000) /* Boot ROM */
36
37
+#define NPCM7XX_NR_PWM_MODULES 2
38
+
39
typedef struct NPCM7xxMachine {
40
MachineState parent;
41
+ /*
42
+ * PWM fan splitter. each splitter connects to one PWM output and
43
+ * multiple MFT inputs.
44
+ */
45
+ SplitIRQ fan_splitter[NPCM7XX_NR_PWM_MODULES *
46
+ NPCM7XX_PWM_PER_MODULE];
47
} NPCM7xxMachine;
48
49
#define TYPE_NPCM7XX_MACHINE MACHINE_TYPE_NAME("npcm7xx")
50
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
51
NPCM7xxCLKState clk;
52
NPCM7xxTimerCtrlState tim[3];
53
NPCM7xxADCState adc;
54
- NPCM7xxPWMState pwm[2];
55
+ NPCM7xxPWMState pwm[NPCM7XX_NR_PWM_MODULES];
56
NPCM7xxMFTState mft[8];
57
NPCM7xxOTPState key_storage;
58
NPCM7xxOTPState fuse_array;
59
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/hw/arm/npcm7xx_boards.c
62
+++ b/hw/arm/npcm7xx_boards.c
63
@@ -XXX,XX +XXX,XX @@
64
#include "hw/core/cpu.h"
65
#include "hw/i2c/smbus_eeprom.h"
66
#include "hw/loader.h"
54
#include "hw/loader.h"
67
+#include "hw/qdev-core.h"
55
#include "hw/misc/unimp.h"
56
+#include "hw/qdev-clock.h"
68
#include "hw/qdev-properties.h"
57
#include "hw/qdev-properties.h"
69
#include "qapi/error.h"
58
#include "qapi/error.h"
70
#include "qemu-common.h"
59
#include "qemu/units.h"
71
@@ -XXX,XX +XXX,XX @@ static void at24c_eeprom_init(NPCM7xxState *soc, int bus, uint8_t addr,
60
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
72
i2c_slave_realize_and_unref(i2c_dev, i2c_bus, &error_abort);
61
int first_irq;
62
int j;
63
64
+ /* Connect the timer clock. */
65
+ qdev_connect_clock_in(DEVICE(&s->tim[i]), "clock", qdev_get_clock_out(
66
+ DEVICE(&s->clk), "timer-clock"));
67
+
68
sysbus_realize(sbd, &error_abort);
69
sysbus_mmio_map(sbd, 0, npcm7xx_tim_addr[i]);
70
71
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/hw/timer/npcm7xx_timer.c
74
+++ b/hw/timer/npcm7xx_timer.c
75
@@ -XXX,XX +XXX,XX @@
76
#include "qemu/osdep.h"
77
78
#include "hw/irq.h"
79
+#include "hw/qdev-clock.h"
80
#include "hw/qdev-properties.h"
81
-#include "hw/misc/npcm7xx_clk.h"
82
#include "hw/timer/npcm7xx_timer.h"
83
#include "migration/vmstate.h"
84
#include "qemu/bitops.h"
85
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_tcsr_prescaler(uint32_t tcsr)
86
/* Convert a timer cycle count to a time interval in nanoseconds. */
87
static int64_t npcm7xx_timer_count_to_ns(NPCM7xxTimer *t, uint32_t count)
88
{
89
- int64_t ns = count;
90
+ int64_t ticks = count;
91
92
- ns *= NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ;
93
- ns *= npcm7xx_tcsr_prescaler(t->tcsr);
94
+ ticks *= npcm7xx_tcsr_prescaler(t->tcsr);
95
96
- return ns;
97
+ return clock_ticks_to_ns(t->ctrl->clock, ticks);
73
}
98
}
74
99
75
+static void npcm7xx_init_pwm_splitter(NPCM7xxMachine *machine,
100
/* Convert a time interval in nanoseconds to a timer cycle count. */
76
+ NPCM7xxState *soc, const int *fan_counts)
101
static uint32_t npcm7xx_timer_ns_to_count(NPCM7xxTimer *t, int64_t ns)
77
+{
78
+ SplitIRQ *splitters = machine->fan_splitter;
79
+
80
+ /*
81
+ * PWM 0~3 belong to module 0 output 0~3.
82
+ * PWM 4~7 belong to module 1 output 0~3.
83
+ */
84
+ for (int i = 0; i < NPCM7XX_NR_PWM_MODULES; ++i) {
85
+ for (int j = 0; j < NPCM7XX_PWM_PER_MODULE; ++j) {
86
+ int splitter_no = i * NPCM7XX_PWM_PER_MODULE + j;
87
+ DeviceState *splitter;
88
+
89
+ if (fan_counts[splitter_no] < 1) {
90
+ continue;
91
+ }
92
+ object_initialize_child(OBJECT(machine), "fan-splitter[*]",
93
+ &splitters[splitter_no], TYPE_SPLIT_IRQ);
94
+ splitter = DEVICE(&splitters[splitter_no]);
95
+ qdev_prop_set_uint16(splitter, "num-lines",
96
+ fan_counts[splitter_no]);
97
+ qdev_realize(splitter, NULL, &error_abort);
98
+ qdev_connect_gpio_out_named(DEVICE(&soc->pwm[i]), "duty-gpio-out",
99
+ j, qdev_get_gpio_in(splitter, 0));
100
+ }
101
+ }
102
+}
103
+
104
+static void npcm7xx_connect_pwm_fan(NPCM7xxState *soc, SplitIRQ *splitter,
105
+ int fan_no, int output_no)
106
+{
107
+ DeviceState *fan;
108
+ int fan_input;
109
+ qemu_irq fan_duty_gpio;
110
+
111
+ g_assert(fan_no >= 0 && fan_no <= NPCM7XX_MFT_MAX_FAN_INPUT);
112
+ /*
113
+ * Fan 0~1 belong to module 0 input 0~1.
114
+ * Fan 2~3 belong to module 1 input 0~1.
115
+ * ...
116
+ * Fan 14~15 belong to module 7 input 0~1.
117
+ * Fan 16~17 belong to module 0 input 2~3.
118
+ * Fan 18~19 belong to module 1 input 2~3.
119
+ */
120
+ if (fan_no < 16) {
121
+ fan = DEVICE(&soc->mft[fan_no / 2]);
122
+ fan_input = fan_no % 2;
123
+ } else {
124
+ fan = DEVICE(&soc->mft[(fan_no - 16) / 2]);
125
+ fan_input = fan_no % 2 + 2;
126
+ }
127
+
128
+ /* Connect the Fan to PWM module */
129
+ fan_duty_gpio = qdev_get_gpio_in_named(fan, "duty", fan_input);
130
+ qdev_connect_gpio_out(DEVICE(splitter), output_no, fan_duty_gpio);
131
+}
132
+
133
static void npcm750_evb_i2c_init(NPCM7xxState *soc)
134
{
102
{
135
/* lm75 temperature sensor on SVB, tmp105 is compatible */
103
- int64_t count;
136
@@ -XXX,XX +XXX,XX @@ static void npcm750_evb_i2c_init(NPCM7xxState *soc)
104
-
137
i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 6), "tmp105", 0x48);
105
- count = ns / (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ);
106
- count /= npcm7xx_tcsr_prescaler(t->tcsr);
107
-
108
- return count;
109
+ return ns / clock_ticks_to_ns(t->ctrl->clock,
110
+ npcm7xx_tcsr_prescaler(t->tcsr));
138
}
111
}
139
112
140
+static void npcm750_evb_fan_init(NPCM7xxMachine *machine, NPCM7xxState *soc)
113
static uint32_t npcm7xx_watchdog_timer_prescaler(const NPCM7xxWatchdogTimer *t)
141
+{
114
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_watchdog_timer_prescaler(const NPCM7xxWatchdogTimer *t)
142
+ SplitIRQ *splitter = machine->fan_splitter;
115
static void npcm7xx_watchdog_timer_reset_cycles(NPCM7xxWatchdogTimer *t,
143
+ static const int fan_counts[] = {2, 2, 2, 2, 2, 2, 2, 2};
116
int64_t cycles)
144
+
145
+ npcm7xx_init_pwm_splitter(machine, soc, fan_counts);
146
+ npcm7xx_connect_pwm_fan(soc, &splitter[0], 0x00, 0);
147
+ npcm7xx_connect_pwm_fan(soc, &splitter[0], 0x01, 1);
148
+ npcm7xx_connect_pwm_fan(soc, &splitter[1], 0x02, 0);
149
+ npcm7xx_connect_pwm_fan(soc, &splitter[1], 0x03, 1);
150
+ npcm7xx_connect_pwm_fan(soc, &splitter[2], 0x04, 0);
151
+ npcm7xx_connect_pwm_fan(soc, &splitter[2], 0x05, 1);
152
+ npcm7xx_connect_pwm_fan(soc, &splitter[3], 0x06, 0);
153
+ npcm7xx_connect_pwm_fan(soc, &splitter[3], 0x07, 1);
154
+ npcm7xx_connect_pwm_fan(soc, &splitter[4], 0x08, 0);
155
+ npcm7xx_connect_pwm_fan(soc, &splitter[4], 0x09, 1);
156
+ npcm7xx_connect_pwm_fan(soc, &splitter[5], 0x0a, 0);
157
+ npcm7xx_connect_pwm_fan(soc, &splitter[5], 0x0b, 1);
158
+ npcm7xx_connect_pwm_fan(soc, &splitter[6], 0x0c, 0);
159
+ npcm7xx_connect_pwm_fan(soc, &splitter[6], 0x0d, 1);
160
+ npcm7xx_connect_pwm_fan(soc, &splitter[7], 0x0e, 0);
161
+ npcm7xx_connect_pwm_fan(soc, &splitter[7], 0x0f, 1);
162
+}
163
+
164
static void quanta_gsj_i2c_init(NPCM7xxState *soc)
165
{
117
{
166
/* GSJ machine have 4 max31725 temperature sensors, tmp105 is compatible. */
118
- uint32_t prescaler = npcm7xx_watchdog_timer_prescaler(t);
167
@@ -XXX,XX +XXX,XX @@ static void quanta_gsj_i2c_init(NPCM7xxState *soc)
119
- int64_t ns = (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ) * cycles;
168
/* TODO: Add additional i2c devices. */
120
+ int64_t ticks = cycles * npcm7xx_watchdog_timer_prescaler(t);
121
+ int64_t ns = clock_ticks_to_ns(t->ctrl->clock, ticks);
122
123
/*
124
* The reset function always clears the current timer. The caller of the
125
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_watchdog_timer_reset_cycles(NPCM7xxWatchdogTimer *t,
126
*/
127
npcm7xx_timer_clear(&t->base_timer);
128
129
- ns *= prescaler;
130
t->base_timer.remaining_ns = ns;
169
}
131
}
170
132
171
+static void quanta_gsj_fan_init(NPCM7xxMachine *machine, NPCM7xxState *soc)
133
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_hold_reset(Object *obj)
172
+{
134
qemu_irq_lower(s->watchdog_timer.irq);
173
+ SplitIRQ *splitter = machine->fan_splitter;
135
}
174
+ static const int fan_counts[] = {2, 2, 2, 0, 0, 0, 0, 0};
136
175
+
137
-static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
176
+ npcm7xx_init_pwm_splitter(machine, soc, fan_counts);
138
+static void npcm7xx_timer_init(Object *obj)
177
+ npcm7xx_connect_pwm_fan(soc, &splitter[0], 0x00, 0);
178
+ npcm7xx_connect_pwm_fan(soc, &splitter[0], 0x01, 1);
179
+ npcm7xx_connect_pwm_fan(soc, &splitter[1], 0x02, 0);
180
+ npcm7xx_connect_pwm_fan(soc, &splitter[1], 0x03, 1);
181
+ npcm7xx_connect_pwm_fan(soc, &splitter[2], 0x04, 0);
182
+ npcm7xx_connect_pwm_fan(soc, &splitter[2], 0x05, 1);
183
+}
184
+
185
static void npcm750_evb_init(MachineState *machine)
186
{
139
{
187
NPCM7xxState *soc;
140
- NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(dev);
188
@@ -XXX,XX +XXX,XX @@ static void npcm750_evb_init(MachineState *machine)
141
- SysBusDevice *sbd = &s->parent;
189
npcm7xx_load_bootrom(machine, soc);
142
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(obj);
190
npcm7xx_connect_flash(&soc->fiu[0], 0, "w25q256", drive_get(IF_MTD, 0, 0));
143
+ DeviceState *dev = DEVICE(obj);
191
npcm750_evb_i2c_init(soc);
144
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
192
+ npcm750_evb_fan_init(NPCM7XX_MACHINE(machine), soc);
145
int i;
193
npcm7xx_load_kernel(machine, soc);
146
NPCM7xxWatchdogTimer *w;
147
148
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
149
npcm7xx_watchdog_timer_expired, w);
150
sysbus_init_irq(sbd, &w->irq);
151
152
- memory_region_init_io(&s->iomem, OBJECT(s), &npcm7xx_timer_ops, s,
153
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_timer_ops, s,
154
TYPE_NPCM7XX_TIMER, 4 * KiB);
155
sysbus_init_mmio(sbd, &s->iomem);
156
qdev_init_gpio_out_named(dev, &w->reset_signal,
157
NPCM7XX_WATCHDOG_RESET_GPIO_OUT, 1);
158
+ s->clock = qdev_init_clock_in(dev, "clock", NULL, NULL);
194
}
159
}
195
160
196
@@ -XXX,XX +XXX,XX @@ static void quanta_gsj_init(MachineState *machine)
161
static const VMStateDescription vmstate_npcm7xx_base_timer = {
197
npcm7xx_connect_flash(&soc->fiu[0], 0, "mx25l25635e",
162
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_npcm7xx_watchdog_timer = {
198
drive_get(IF_MTD, 0, 0));
163
199
quanta_gsj_i2c_init(soc);
164
static const VMStateDescription vmstate_npcm7xx_timer_ctrl = {
200
+ quanta_gsj_fan_init(NPCM7XX_MACHINE(machine), soc);
165
.name = "npcm7xx-timer-ctrl",
201
npcm7xx_load_kernel(machine, soc);
166
- .version_id = 1,
202
}
167
- .minimum_version_id = 1,
203
168
+ .version_id = 2,
169
+ .minimum_version_id = 2,
170
.fields = (VMStateField[]) {
171
VMSTATE_UINT32(tisr, NPCM7xxTimerCtrlState),
172
+ VMSTATE_CLOCK(clock, NPCM7xxTimerCtrlState),
173
VMSTATE_STRUCT_ARRAY(timer, NPCM7xxTimerCtrlState,
174
NPCM7XX_TIMERS_PER_CTRL, 0, vmstate_npcm7xx_timer,
175
NPCM7xxTimer),
176
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_class_init(ObjectClass *klass, void *data)
177
QEMU_BUILD_BUG_ON(NPCM7XX_TIMER_REGS_END > NPCM7XX_TIMER_NR_REGS);
178
179
dc->desc = "NPCM7xx Timer Controller";
180
- dc->realize = npcm7xx_timer_realize;
181
dc->vmsd = &vmstate_npcm7xx_timer_ctrl;
182
rc->phases.enter = npcm7xx_timer_enter_reset;
183
rc->phases.hold = npcm7xx_timer_hold_reset;
184
@@ -XXX,XX +XXX,XX @@ static const TypeInfo npcm7xx_timer_info = {
185
.parent = TYPE_SYS_BUS_DEVICE,
186
.instance_size = sizeof(NPCM7xxTimerCtrlState),
187
.class_init = npcm7xx_timer_class_init,
188
+ .instance_init = npcm7xx_timer_init,
189
};
190
191
static void npcm7xx_timer_register_type(void)
204
--
192
--
205
2.20.1
193
2.20.1
206
194
207
195
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
This patch adds the recently implemented MFT device to the NPCM7XX
3
The ADC is part of NPCM7XX Module. Its behavior is controled by the
4
SoC file.
4
ADC_CON register. It converts one of the eight analog inputs into a
5
digital input and stores it in the ADC_DATA register when enabled.
5
6
6
Reviewed-by: Doug Evans <dje@google.com>
7
Users can alter input value by using qom-set QMP command.
8
9
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
8
Signed-off-by: Hao Wu <wuhaotsh@google.com>
11
Signed-off-by: Hao Wu <wuhaotsh@google.com>
9
Message-id: 20210311180855.149764-4-wuhaotsh@google.com
12
Message-id: 20210108190945.949196-4-wuhaotsh@google.com
13
[PMM: Added missing hw/adc/trace.h file]
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
16
---
13
docs/system/arm/nuvoton.rst | 2 +-
17
docs/system/arm/nuvoton.rst | 2 +-
14
include/hw/arm/npcm7xx.h | 2 ++
18
meson.build | 1 +
15
hw/arm/npcm7xx.c | 45 ++++++++++++++++++++++++++++++-------
19
hw/adc/trace.h | 1 +
16
3 files changed, 40 insertions(+), 9 deletions(-)
20
include/hw/adc/npcm7xx_adc.h | 69 ++++++
21
include/hw/arm/npcm7xx.h | 2 +
22
hw/adc/npcm7xx_adc.c | 301 ++++++++++++++++++++++++++
23
hw/arm/npcm7xx.c | 24 ++-
24
tests/qtest/npcm7xx_adc-test.c | 377 +++++++++++++++++++++++++++++++++
25
hw/adc/meson.build | 1 +
26
hw/adc/trace-events | 5 +
27
tests/qtest/meson.build | 3 +-
28
11 files changed, 783 insertions(+), 3 deletions(-)
29
create mode 100644 hw/adc/trace.h
30
create mode 100644 include/hw/adc/npcm7xx_adc.h
31
create mode 100644 hw/adc/npcm7xx_adc.c
32
create mode 100644 tests/qtest/npcm7xx_adc-test.c
33
create mode 100644 hw/adc/trace-events
17
34
18
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
35
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
19
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
20
--- a/docs/system/arm/nuvoton.rst
37
--- a/docs/system/arm/nuvoton.rst
21
+++ b/docs/system/arm/nuvoton.rst
38
+++ b/docs/system/arm/nuvoton.rst
22
@@ -XXX,XX +XXX,XX @@ Supported devices
39
@@ -XXX,XX +XXX,XX @@ Supported devices
23
* Pulse Width Modulation (PWM)
40
* Random Number Generator (RNG)
24
* SMBus controller (SMBF)
41
* USB host (USBH)
25
* Ethernet controller (EMC)
42
* GPIO controller
26
+ * Tachometer
43
+ * Analog to Digital Converter (ADC)
27
44
28
Missing devices
45
Missing devices
29
---------------
46
---------------
30
@@ -XXX,XX +XXX,XX @@ Missing devices
47
@@ -XXX,XX +XXX,XX @@ Missing devices
48
* USB device (USBD)
49
* SMBus controller (SMBF)
31
* Peripheral SPI controller (PSPI)
50
* Peripheral SPI controller (PSPI)
51
- * Analog to Digital Converter (ADC)
32
* SD/MMC host
52
* SD/MMC host
33
* PECI interface
53
* PECI interface
34
- * Tachometer
54
* Pulse Width Modulation (PWM)
35
* PCI and PCIe root complex and bridges
55
diff --git a/meson.build b/meson.build
36
* VDM and MCTP support
56
index XXXXXXX..XXXXXXX 100644
37
* Serial I/O expansion
57
--- a/meson.build
58
+++ b/meson.build
59
@@ -XXX,XX +XXX,XX @@ if have_system
60
'chardev',
61
'hw/9pfs',
62
'hw/acpi',
63
+ 'hw/adc',
64
'hw/alpha',
65
'hw/arm',
66
'hw/audio',
67
diff --git a/hw/adc/trace.h b/hw/adc/trace.h
68
new file mode 100644
69
index XXXXXXX..XXXXXXX
70
--- /dev/null
71
+++ b/hw/adc/trace.h
72
@@ -0,0 +1 @@
73
+#include "trace/trace-hw_adc.h"
74
diff --git a/include/hw/adc/npcm7xx_adc.h b/include/hw/adc/npcm7xx_adc.h
75
new file mode 100644
76
index XXXXXXX..XXXXXXX
77
--- /dev/null
78
+++ b/include/hw/adc/npcm7xx_adc.h
79
@@ -XXX,XX +XXX,XX @@
80
+/*
81
+ * Nuvoton NPCM7xx ADC Module
82
+ *
83
+ * Copyright 2020 Google LLC
84
+ *
85
+ * This program is free software; you can redistribute it and/or modify it
86
+ * under the terms of the GNU General Public License as published by the
87
+ * Free Software Foundation; either version 2 of the License, or
88
+ * (at your option) any later version.
89
+ *
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
91
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
92
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
93
+ * for more details.
94
+ */
95
+#ifndef NPCM7XX_ADC_H
96
+#define NPCM7XX_ADC_H
97
+
98
+#include "hw/clock.h"
99
+#include "hw/irq.h"
100
+#include "hw/sysbus.h"
101
+#include "qemu/timer.h"
102
+
103
+#define NPCM7XX_ADC_NUM_INPUTS 8
104
+/**
105
+ * This value should not be changed unless write_adc_calibration function in
106
+ * hw/arm/npcm7xx.c is also changed.
107
+ */
108
+#define NPCM7XX_ADC_NUM_CALIB 2
109
+
110
+/**
111
+ * struct NPCM7xxADCState - Analog to Digital Converter Module device state.
112
+ * @parent: System bus device.
113
+ * @iomem: Memory region through which registers are accessed.
114
+ * @conv_timer: The timer counts down remaining cycles for the conversion.
115
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
116
+ * @con: The Control Register.
117
+ * @data: The Data Buffer.
118
+ * @clock: The ADC Clock.
119
+ * @adci: The input voltage in units of uV. 1uv = 1e-6V.
120
+ * @vref: The external reference voltage.
121
+ * @iref: The internal reference voltage, initialized at launch time.
122
+ * @rv: The calibrated output values of 0.5V and 1.5V for the ADC.
123
+ */
124
+typedef struct {
125
+ SysBusDevice parent;
126
+
127
+ MemoryRegion iomem;
128
+
129
+ QEMUTimer conv_timer;
130
+
131
+ qemu_irq irq;
132
+ uint32_t con;
133
+ uint32_t data;
134
+ Clock *clock;
135
+
136
+ /* Voltages are in unit of uV. 1V = 1000000uV. */
137
+ uint32_t adci[NPCM7XX_ADC_NUM_INPUTS];
138
+ uint32_t vref;
139
+ uint32_t iref;
140
+
141
+ uint16_t calibration_r_values[NPCM7XX_ADC_NUM_CALIB];
142
+} NPCM7xxADCState;
143
+
144
+#define TYPE_NPCM7XX_ADC "npcm7xx-adc"
145
+#define NPCM7XX_ADC(obj) \
146
+ OBJECT_CHECK(NPCM7xxADCState, (obj), TYPE_NPCM7XX_ADC)
147
+
148
+#endif /* NPCM7XX_ADC_H */
38
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
149
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
39
index XXXXXXX..XXXXXXX 100644
150
index XXXXXXX..XXXXXXX 100644
40
--- a/include/hw/arm/npcm7xx.h
151
--- a/include/hw/arm/npcm7xx.h
41
+++ b/include/hw/arm/npcm7xx.h
152
+++ b/include/hw/arm/npcm7xx.h
42
@@ -XXX,XX +XXX,XX @@
153
@@ -XXX,XX +XXX,XX @@
154
#define NPCM7XX_H
155
156
#include "hw/boards.h"
157
+#include "hw/adc/npcm7xx_adc.h"
158
#include "hw/cpu/a9mpcore.h"
159
#include "hw/gpio/npcm7xx_gpio.h"
43
#include "hw/mem/npcm7xx_mc.h"
160
#include "hw/mem/npcm7xx_mc.h"
44
#include "hw/misc/npcm7xx_clk.h"
45
#include "hw/misc/npcm7xx_gcr.h"
46
+#include "hw/misc/npcm7xx_mft.h"
47
#include "hw/misc/npcm7xx_pwm.h"
48
#include "hw/misc/npcm7xx_rng.h"
49
#include "hw/net/npcm7xx_emc.h"
50
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
161
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
162
NPCM7xxGCRState gcr;
163
NPCM7xxCLKState clk;
51
NPCM7xxTimerCtrlState tim[3];
164
NPCM7xxTimerCtrlState tim[3];
52
NPCM7xxADCState adc;
165
+ NPCM7xxADCState adc;
53
NPCM7xxPWMState pwm[2];
54
+ NPCM7xxMFTState mft[8];
55
NPCM7xxOTPState key_storage;
166
NPCM7xxOTPState key_storage;
56
NPCM7xxOTPState fuse_array;
167
NPCM7xxOTPState fuse_array;
57
NPCM7xxMCState mc;
168
NPCM7xxMCState mc;
169
diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c
170
new file mode 100644
171
index XXXXXXX..XXXXXXX
172
--- /dev/null
173
+++ b/hw/adc/npcm7xx_adc.c
174
@@ -XXX,XX +XXX,XX @@
175
+/*
176
+ * Nuvoton NPCM7xx ADC Module
177
+ *
178
+ * Copyright 2020 Google LLC
179
+ *
180
+ * This program is free software; you can redistribute it and/or modify it
181
+ * under the terms of the GNU General Public License as published by the
182
+ * Free Software Foundation; either version 2 of the License, or
183
+ * (at your option) any later version.
184
+ *
185
+ * This program is distributed in the hope that it will be useful, but WITHOUT
186
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
187
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
188
+ * for more details.
189
+ */
190
+
191
+#include "qemu/osdep.h"
192
+#include "hw/adc/npcm7xx_adc.h"
193
+#include "hw/qdev-clock.h"
194
+#include "hw/qdev-properties.h"
195
+#include "hw/registerfields.h"
196
+#include "migration/vmstate.h"
197
+#include "qemu/log.h"
198
+#include "qemu/module.h"
199
+#include "qemu/timer.h"
200
+#include "qemu/units.h"
201
+#include "trace.h"
202
+
203
+REG32(NPCM7XX_ADC_CON, 0x0)
204
+REG32(NPCM7XX_ADC_DATA, 0x4)
205
+
206
+/* Register field definitions. */
207
+#define NPCM7XX_ADC_CON_MUX(rv) extract32(rv, 24, 4)
208
+#define NPCM7XX_ADC_CON_INT_EN BIT(21)
209
+#define NPCM7XX_ADC_CON_REFSEL BIT(19)
210
+#define NPCM7XX_ADC_CON_INT BIT(18)
211
+#define NPCM7XX_ADC_CON_EN BIT(17)
212
+#define NPCM7XX_ADC_CON_RST BIT(16)
213
+#define NPCM7XX_ADC_CON_CONV BIT(14)
214
+#define NPCM7XX_ADC_CON_DIV(rv) extract32(rv, 1, 8)
215
+
216
+#define NPCM7XX_ADC_MAX_RESULT 1023
217
+#define NPCM7XX_ADC_DEFAULT_IREF 2000000
218
+#define NPCM7XX_ADC_CONV_CYCLES 20
219
+#define NPCM7XX_ADC_RESET_CYCLES 10
220
+#define NPCM7XX_ADC_R0_INPUT 500000
221
+#define NPCM7XX_ADC_R1_INPUT 1500000
222
+
223
+static void npcm7xx_adc_reset(NPCM7xxADCState *s)
224
+{
225
+ timer_del(&s->conv_timer);
226
+ s->con = 0x000c0001;
227
+ s->data = 0x00000000;
228
+}
229
+
230
+static uint32_t npcm7xx_adc_convert(uint32_t input, uint32_t ref)
231
+{
232
+ uint32_t result;
233
+
234
+ result = input * (NPCM7XX_ADC_MAX_RESULT + 1) / ref;
235
+ if (result > NPCM7XX_ADC_MAX_RESULT) {
236
+ result = NPCM7XX_ADC_MAX_RESULT;
237
+ }
238
+
239
+ return result;
240
+}
241
+
242
+static uint32_t npcm7xx_adc_prescaler(NPCM7xxADCState *s)
243
+{
244
+ return 2 * (NPCM7XX_ADC_CON_DIV(s->con) + 1);
245
+}
246
+
247
+static void npcm7xx_adc_start_timer(Clock *clk, QEMUTimer *timer,
248
+ uint32_t cycles, uint32_t prescaler)
249
+{
250
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
251
+ int64_t ticks = cycles;
252
+ int64_t ns;
253
+
254
+ ticks *= prescaler;
255
+ ns = clock_ticks_to_ns(clk, ticks);
256
+ ns += now;
257
+ timer_mod(timer, ns);
258
+}
259
+
260
+static void npcm7xx_adc_start_convert(NPCM7xxADCState *s)
261
+{
262
+ uint32_t prescaler = npcm7xx_adc_prescaler(s);
263
+
264
+ npcm7xx_adc_start_timer(s->clock, &s->conv_timer, NPCM7XX_ADC_CONV_CYCLES,
265
+ prescaler);
266
+}
267
+
268
+static void npcm7xx_adc_convert_done(void *opaque)
269
+{
270
+ NPCM7xxADCState *s = opaque;
271
+ uint32_t input = NPCM7XX_ADC_CON_MUX(s->con);
272
+ uint32_t ref = (s->con & NPCM7XX_ADC_CON_REFSEL)
273
+ ? s->iref : s->vref;
274
+
275
+ if (input >= NPCM7XX_ADC_NUM_INPUTS) {
276
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid input: %u\n",
277
+ __func__, input);
278
+ return;
279
+ }
280
+ s->data = npcm7xx_adc_convert(s->adci[input], ref);
281
+ if (s->con & NPCM7XX_ADC_CON_INT_EN) {
282
+ s->con |= NPCM7XX_ADC_CON_INT;
283
+ qemu_irq_raise(s->irq);
284
+ }
285
+ s->con &= ~NPCM7XX_ADC_CON_CONV;
286
+}
287
+
288
+static void npcm7xx_adc_calibrate(NPCM7xxADCState *adc)
289
+{
290
+ adc->calibration_r_values[0] = npcm7xx_adc_convert(NPCM7XX_ADC_R0_INPUT,
291
+ adc->iref);
292
+ adc->calibration_r_values[1] = npcm7xx_adc_convert(NPCM7XX_ADC_R1_INPUT,
293
+ adc->iref);
294
+}
295
+
296
+static void npcm7xx_adc_write_con(NPCM7xxADCState *s, uint32_t new_con)
297
+{
298
+ uint32_t old_con = s->con;
299
+
300
+ /* Write ADC_INT to 1 to clear it */
301
+ if (new_con & NPCM7XX_ADC_CON_INT) {
302
+ new_con &= ~NPCM7XX_ADC_CON_INT;
303
+ qemu_irq_lower(s->irq);
304
+ } else if (old_con & NPCM7XX_ADC_CON_INT) {
305
+ new_con |= NPCM7XX_ADC_CON_INT;
306
+ }
307
+
308
+ s->con = new_con;
309
+
310
+ if (s->con & NPCM7XX_ADC_CON_RST) {
311
+ npcm7xx_adc_reset(s);
312
+ return;
313
+ }
314
+
315
+ if ((s->con & NPCM7XX_ADC_CON_EN)) {
316
+ if (s->con & NPCM7XX_ADC_CON_CONV) {
317
+ if (!(old_con & NPCM7XX_ADC_CON_CONV)) {
318
+ npcm7xx_adc_start_convert(s);
319
+ }
320
+ } else {
321
+ timer_del(&s->conv_timer);
322
+ }
323
+ }
324
+}
325
+
326
+static uint64_t npcm7xx_adc_read(void *opaque, hwaddr offset, unsigned size)
327
+{
328
+ uint64_t value = 0;
329
+ NPCM7xxADCState *s = opaque;
330
+
331
+ switch (offset) {
332
+ case A_NPCM7XX_ADC_CON:
333
+ value = s->con;
334
+ break;
335
+
336
+ case A_NPCM7XX_ADC_DATA:
337
+ value = s->data;
338
+ break;
339
+
340
+ default:
341
+ qemu_log_mask(LOG_GUEST_ERROR,
342
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
343
+ __func__, offset);
344
+ break;
345
+ }
346
+
347
+ trace_npcm7xx_adc_read(DEVICE(s)->canonical_path, offset, value);
348
+ return value;
349
+}
350
+
351
+static void npcm7xx_adc_write(void *opaque, hwaddr offset, uint64_t v,
352
+ unsigned size)
353
+{
354
+ NPCM7xxADCState *s = opaque;
355
+
356
+ trace_npcm7xx_adc_write(DEVICE(s)->canonical_path, offset, v);
357
+ switch (offset) {
358
+ case A_NPCM7XX_ADC_CON:
359
+ npcm7xx_adc_write_con(s, v);
360
+ break;
361
+
362
+ case A_NPCM7XX_ADC_DATA:
363
+ qemu_log_mask(LOG_GUEST_ERROR,
364
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
365
+ __func__, offset);
366
+ break;
367
+
368
+ default:
369
+ qemu_log_mask(LOG_GUEST_ERROR,
370
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
371
+ __func__, offset);
372
+ break;
373
+ }
374
+
375
+}
376
+
377
+static const struct MemoryRegionOps npcm7xx_adc_ops = {
378
+ .read = npcm7xx_adc_read,
379
+ .write = npcm7xx_adc_write,
380
+ .endianness = DEVICE_LITTLE_ENDIAN,
381
+ .valid = {
382
+ .min_access_size = 4,
383
+ .max_access_size = 4,
384
+ .unaligned = false,
385
+ },
386
+};
387
+
388
+static void npcm7xx_adc_enter_reset(Object *obj, ResetType type)
389
+{
390
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
391
+
392
+ npcm7xx_adc_reset(s);
393
+}
394
+
395
+static void npcm7xx_adc_hold_reset(Object *obj)
396
+{
397
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
398
+
399
+ qemu_irq_lower(s->irq);
400
+}
401
+
402
+static void npcm7xx_adc_init(Object *obj)
403
+{
404
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
405
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
406
+ int i;
407
+
408
+ sysbus_init_irq(sbd, &s->irq);
409
+
410
+ timer_init_ns(&s->conv_timer, QEMU_CLOCK_VIRTUAL,
411
+ npcm7xx_adc_convert_done, s);
412
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_adc_ops, s,
413
+ TYPE_NPCM7XX_ADC, 4 * KiB);
414
+ sysbus_init_mmio(sbd, &s->iomem);
415
+ s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL);
416
+
417
+ for (i = 0; i < NPCM7XX_ADC_NUM_INPUTS; ++i) {
418
+ object_property_add_uint32_ptr(obj, "adci[*]",
419
+ &s->adci[i], OBJ_PROP_FLAG_WRITE);
420
+ }
421
+ object_property_add_uint32_ptr(obj, "vref",
422
+ &s->vref, OBJ_PROP_FLAG_WRITE);
423
+ npcm7xx_adc_calibrate(s);
424
+}
425
+
426
+static const VMStateDescription vmstate_npcm7xx_adc = {
427
+ .name = "npcm7xx-adc",
428
+ .version_id = 0,
429
+ .minimum_version_id = 0,
430
+ .fields = (VMStateField[]) {
431
+ VMSTATE_TIMER(conv_timer, NPCM7xxADCState),
432
+ VMSTATE_UINT32(con, NPCM7xxADCState),
433
+ VMSTATE_UINT32(data, NPCM7xxADCState),
434
+ VMSTATE_CLOCK(clock, NPCM7xxADCState),
435
+ VMSTATE_UINT32_ARRAY(adci, NPCM7xxADCState, NPCM7XX_ADC_NUM_INPUTS),
436
+ VMSTATE_UINT32(vref, NPCM7xxADCState),
437
+ VMSTATE_UINT32(iref, NPCM7xxADCState),
438
+ VMSTATE_UINT16_ARRAY(calibration_r_values, NPCM7xxADCState,
439
+ NPCM7XX_ADC_NUM_CALIB),
440
+ VMSTATE_END_OF_LIST(),
441
+ },
442
+};
443
+
444
+static Property npcm7xx_timer_properties[] = {
445
+ DEFINE_PROP_UINT32("iref", NPCM7xxADCState, iref, NPCM7XX_ADC_DEFAULT_IREF),
446
+ DEFINE_PROP_END_OF_LIST(),
447
+};
448
+
449
+static void npcm7xx_adc_class_init(ObjectClass *klass, void *data)
450
+{
451
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
452
+ DeviceClass *dc = DEVICE_CLASS(klass);
453
+
454
+ dc->desc = "NPCM7xx ADC Module";
455
+ dc->vmsd = &vmstate_npcm7xx_adc;
456
+ rc->phases.enter = npcm7xx_adc_enter_reset;
457
+ rc->phases.hold = npcm7xx_adc_hold_reset;
458
+
459
+ device_class_set_props(dc, npcm7xx_timer_properties);
460
+}
461
+
462
+static const TypeInfo npcm7xx_adc_info = {
463
+ .name = TYPE_NPCM7XX_ADC,
464
+ .parent = TYPE_SYS_BUS_DEVICE,
465
+ .instance_size = sizeof(NPCM7xxADCState),
466
+ .class_init = npcm7xx_adc_class_init,
467
+ .instance_init = npcm7xx_adc_init,
468
+};
469
+
470
+static void npcm7xx_adc_register_types(void)
471
+{
472
+ type_register_static(&npcm7xx_adc_info);
473
+}
474
+
475
+type_init(npcm7xx_adc_register_types);
58
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
476
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
59
index XXXXXXX..XXXXXXX 100644
477
index XXXXXXX..XXXXXXX 100644
60
--- a/hw/arm/npcm7xx.c
478
--- a/hw/arm/npcm7xx.c
61
+++ b/hw/arm/npcm7xx.c
479
+++ b/hw/arm/npcm7xx.c
62
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
480
@@ -XXX,XX +XXX,XX @@
63
NPCM7XX_SMBUS15_IRQ,
481
#define NPCM7XX_EHCI_BA (0xf0806000)
64
NPCM7XX_PWM0_IRQ = 93, /* PWM module 0 */
482
#define NPCM7XX_OHCI_BA (0xf0807000)
65
NPCM7XX_PWM1_IRQ, /* PWM module 1 */
483
66
+ NPCM7XX_MFT0_IRQ = 96, /* MFT module 0 */
484
+/* ADC Module */
67
+ NPCM7XX_MFT1_IRQ, /* MFT module 1 */
485
+#define NPCM7XX_ADC_BA (0xf000c000)
68
+ NPCM7XX_MFT2_IRQ, /* MFT module 2 */
486
+
69
+ NPCM7XX_MFT3_IRQ, /* MFT module 3 */
487
/* Internal AHB SRAM */
70
+ NPCM7XX_MFT4_IRQ, /* MFT module 4 */
488
#define NPCM7XX_RAM3_BA (0xc0008000)
71
+ NPCM7XX_MFT5_IRQ, /* MFT module 5 */
489
#define NPCM7XX_RAM3_SZ (4 * KiB)
72
+ NPCM7XX_MFT6_IRQ, /* MFT module 6 */
490
@@ -XXX,XX +XXX,XX @@
73
+ NPCM7XX_MFT7_IRQ, /* MFT module 7 */
491
#define NPCM7XX_ROM_BA (0xffff0000)
74
NPCM7XX_EMC2RX_IRQ = 114,
492
#define NPCM7XX_ROM_SZ (64 * KiB)
75
NPCM7XX_EMC2TX_IRQ,
493
76
NPCM7XX_GPIO0_IRQ = 116,
494
+
77
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_pwm_addr[] = {
495
/* Clock configuration values to be fixed up when bypassing bootloader */
78
0xf0104000,
496
79
};
497
/* Run PLL1 at 1600 MHz */
80
498
@@ -XXX,XX +XXX,XX @@
81
+/* Register base address for each MFT Module */
499
* interrupts.
82
+static const hwaddr npcm7xx_mft_addr[] = {
500
*/
83
+ 0xf0180000,
501
enum NPCM7xxInterrupt {
84
+ 0xf0181000,
502
+ NPCM7XX_ADC_IRQ = 0,
85
+ 0xf0182000,
503
NPCM7XX_UART0_IRQ = 2,
86
+ 0xf0183000,
504
NPCM7XX_UART1_IRQ,
87
+ 0xf0184000,
505
NPCM7XX_UART2_IRQ,
88
+ 0xf0185000,
506
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init_fuses(NPCM7xxState *s)
89
+ 0xf0186000,
507
sizeof(value));
90
+ 0xf0187000,
508
}
509
510
+static void npcm7xx_write_adc_calibration(NPCM7xxState *s)
511
+{
512
+ /* Both ADC and the fuse array must have realized. */
513
+ QEMU_BUILD_BUG_ON(sizeof(s->adc.calibration_r_values) != 4);
514
+ npcm7xx_otp_array_write(&s->fuse_array, s->adc.calibration_r_values,
515
+ NPCM7XX_FUSE_ADC_CALIB, sizeof(s->adc.calibration_r_values));
516
+}
517
+
518
static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n)
519
{
520
return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
521
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
522
TYPE_NPCM7XX_FUSE_ARRAY);
523
object_initialize_child(obj, "mc", &s->mc, TYPE_NPCM7XX_MC);
524
object_initialize_child(obj, "rng", &s->rng, TYPE_NPCM7XX_RNG);
525
+ object_initialize_child(obj, "adc", &s->adc, TYPE_NPCM7XX_ADC);
526
527
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
528
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
529
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
530
sysbus_realize(SYS_BUS_DEVICE(&s->mc), &error_abort);
531
sysbus_mmio_map(SYS_BUS_DEVICE(&s->mc), 0, NPCM7XX_MC_BA);
532
533
+ /* ADC Modules. Cannot fail. */
534
+ qdev_connect_clock_in(DEVICE(&s->adc), "clock", qdev_get_clock_out(
535
+ DEVICE(&s->clk), "adc-clock"));
536
+ sysbus_realize(SYS_BUS_DEVICE(&s->adc), &error_abort);
537
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->adc), 0, NPCM7XX_ADC_BA);
538
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0,
539
+ npcm7xx_irq(s, NPCM7XX_ADC_IRQ));
540
+ npcm7xx_write_adc_calibration(s);
541
+
542
/* Timer Modules (TIM). Cannot fail. */
543
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
544
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
545
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
546
create_unimplemented_device("npcm7xx.vdmx", 0xe0800000, 4 * KiB);
547
create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB);
548
create_unimplemented_device("npcm7xx.kcs", 0xf0007000, 4 * KiB);
549
- create_unimplemented_device("npcm7xx.adc", 0xf000c000, 4 * KiB);
550
create_unimplemented_device("npcm7xx.gfxi", 0xf000e000, 4 * KiB);
551
create_unimplemented_device("npcm7xx.gpio[0]", 0xf0010000, 4 * KiB);
552
create_unimplemented_device("npcm7xx.gpio[1]", 0xf0011000, 4 * KiB);
553
diff --git a/tests/qtest/npcm7xx_adc-test.c b/tests/qtest/npcm7xx_adc-test.c
554
new file mode 100644
555
index XXXXXXX..XXXXXXX
556
--- /dev/null
557
+++ b/tests/qtest/npcm7xx_adc-test.c
558
@@ -XXX,XX +XXX,XX @@
559
+/*
560
+ * QTests for Nuvoton NPCM7xx ADCModules.
561
+ *
562
+ * Copyright 2020 Google LLC
563
+ *
564
+ * This program is free software; you can redistribute it and/or modify it
565
+ * under the terms of the GNU General Public License as published by the
566
+ * Free Software Foundation; either version 2 of the License, or
567
+ * (at your option) any later version.
568
+ *
569
+ * This program is distributed in the hope that it will be useful, but WITHOUT
570
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
571
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
572
+ * for more details.
573
+ */
574
+
575
+#include "qemu/osdep.h"
576
+#include "qemu/bitops.h"
577
+#include "qemu/timer.h"
578
+#include "libqos/libqtest.h"
579
+#include "qapi/qmp/qdict.h"
580
+
581
+#define REF_HZ (25000000)
582
+
583
+#define CON_OFFSET 0x0
584
+#define DATA_OFFSET 0x4
585
+
586
+#define NUM_INPUTS 8
587
+#define DEFAULT_IREF 2000000
588
+#define CONV_CYCLES 20
589
+#define RESET_CYCLES 10
590
+#define R0_INPUT 500000
591
+#define R1_INPUT 1500000
592
+#define MAX_RESULT 1023
593
+
594
+#define DEFAULT_CLKDIV 5
595
+
596
+#define FUSE_ARRAY_BA 0xf018a000
597
+#define FCTL_OFFSET 0x14
598
+#define FST_OFFSET 0x0
599
+#define FADDR_OFFSET 0x4
600
+#define FDATA_OFFSET 0x8
601
+#define ADC_CALIB_ADDR 24
602
+#define FUSE_READ 0x2
603
+
604
+/* Register field definitions. */
605
+#define CON_MUX(rv) ((rv) << 24)
606
+#define CON_INT_EN BIT(21)
607
+#define CON_REFSEL BIT(19)
608
+#define CON_INT BIT(18)
609
+#define CON_EN BIT(17)
610
+#define CON_RST BIT(16)
611
+#define CON_CONV BIT(14)
612
+#define CON_DIV(rv) extract32(rv, 1, 8)
613
+
614
+#define FST_RDST BIT(1)
615
+#define FDATA_MASK 0xff
616
+
617
+#define MAX_ERROR 10000
618
+#define MIN_CALIB_INPUT 100000
619
+#define MAX_CALIB_INPUT 1800000
620
+
621
+static const uint32_t input_list[] = {
622
+ 100000,
623
+ 500000,
624
+ 1000000,
625
+ 1500000,
626
+ 1800000,
627
+ 2000000,
91
+};
628
+};
92
+
629
+
93
/* Direct memory-mapped access to each SMBus Module. */
630
+static const uint32_t vref_list[] = {
94
static const hwaddr npcm7xx_smbus_addr[] = {
631
+ 2000000,
95
0xf0080000,
632
+ 2200000,
96
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
633
+ 2500000,
97
object_initialize_child(obj, "pwm[*]", &s->pwm[i], TYPE_NPCM7XX_PWM);
634
+};
98
}
635
+
99
636
+static const uint32_t iref_list[] = {
100
+ for (i = 0; i < ARRAY_SIZE(s->mft); i++) {
637
+ 1800000,
101
+ object_initialize_child(obj, "mft[*]", &s->mft[i], TYPE_NPCM7XX_MFT);
638
+ 1900000,
102
+ }
639
+ 2000000,
103
+
640
+ 2100000,
104
for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
641
+ 2200000,
105
object_initialize_child(obj, "emc[*]", &s->emc[i], TYPE_NPCM7XX_EMC);
642
+};
106
}
643
+
107
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
644
+static const uint32_t div_list[] = {0, 1, 3, 7, 15};
108
sysbus_connect_irq(sbd, i, npcm7xx_irq(s, NPCM7XX_PWM0_IRQ + i));
645
+
109
}
646
+typedef struct ADC {
110
647
+ int irq;
111
+ /* MFT Modules. Cannot fail. */
648
+ uint64_t base_addr;
112
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_mft_addr) != ARRAY_SIZE(s->mft));
649
+} ADC;
113
+ for (i = 0; i < ARRAY_SIZE(s->mft); i++) {
650
+
114
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->mft[i]);
651
+ADC adc = {
115
+
652
+ .irq = 0,
116
+ qdev_connect_clock_in(DEVICE(&s->mft[i]), "clock-in",
653
+ .base_addr = 0xf000c000
117
+ qdev_get_clock_out(DEVICE(&s->clk),
654
+};
118
+ "apb4-clock"));
655
+
119
+ sysbus_realize(sbd, &error_abort);
656
+static uint32_t adc_read_con(QTestState *qts, const ADC *adc)
120
+ sysbus_mmio_map(sbd, 0, npcm7xx_mft_addr[i]);
657
+{
121
+ sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, NPCM7XX_MFT0_IRQ + i));
658
+ return qtest_readl(qts, adc->base_addr + CON_OFFSET);
122
+ }
659
+}
123
+
660
+
124
/*
661
+static void adc_write_con(QTestState *qts, const ADC *adc, uint32_t value)
125
* EMC Modules. Cannot fail.
662
+{
126
* The mapping of the device to its netdev backend works as follows:
663
+ qtest_writel(qts, adc->base_addr + CON_OFFSET, value);
127
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
664
+}
128
create_unimplemented_device("npcm7xx.peci", 0xf0100000, 4 * KiB);
665
+
129
create_unimplemented_device("npcm7xx.siox[1]", 0xf0101000, 4 * KiB);
666
+static uint32_t adc_read_data(QTestState *qts, const ADC *adc)
130
create_unimplemented_device("npcm7xx.siox[2]", 0xf0102000, 4 * KiB);
667
+{
131
- create_unimplemented_device("npcm7xx.mft[0]", 0xf0180000, 4 * KiB);
668
+ return qtest_readl(qts, adc->base_addr + DATA_OFFSET);
132
- create_unimplemented_device("npcm7xx.mft[1]", 0xf0181000, 4 * KiB);
669
+}
133
- create_unimplemented_device("npcm7xx.mft[2]", 0xf0182000, 4 * KiB);
670
+
134
- create_unimplemented_device("npcm7xx.mft[3]", 0xf0183000, 4 * KiB);
671
+static uint32_t adc_calibrate(uint32_t measured, uint32_t *rv)
135
- create_unimplemented_device("npcm7xx.mft[4]", 0xf0184000, 4 * KiB);
672
+{
136
- create_unimplemented_device("npcm7xx.mft[5]", 0xf0185000, 4 * KiB);
673
+ return R0_INPUT + (R1_INPUT - R0_INPUT) * (int32_t)(measured - rv[0])
137
- create_unimplemented_device("npcm7xx.mft[6]", 0xf0186000, 4 * KiB);
674
+ / (int32_t)(rv[1] - rv[0]);
138
- create_unimplemented_device("npcm7xx.mft[7]", 0xf0187000, 4 * KiB);
675
+}
139
create_unimplemented_device("npcm7xx.pspi1", 0xf0200000, 4 * KiB);
676
+
140
create_unimplemented_device("npcm7xx.pspi2", 0xf0201000, 4 * KiB);
677
+static void adc_qom_set(QTestState *qts, const ADC *adc,
141
create_unimplemented_device("npcm7xx.ahbpci", 0xf0400000, 1 * MiB);
678
+ const char *name, uint32_t value)
679
+{
680
+ QDict *response;
681
+ const char *path = "/machine/soc/adc";
682
+
683
+ g_test_message("Setting properties %s of %s with value %u",
684
+ name, path, value);
685
+ response = qtest_qmp(qts, "{ 'execute': 'qom-set',"
686
+ " 'arguments': { 'path': %s, 'property': %s, 'value': %u}}",
687
+ path, name, value);
688
+ /* The qom set message returns successfully. */
689
+ g_assert_true(qdict_haskey(response, "return"));
690
+}
691
+
692
+static void adc_write_input(QTestState *qts, const ADC *adc,
693
+ uint32_t index, uint32_t value)
694
+{
695
+ char name[100];
696
+
697
+ sprintf(name, "adci[%u]", index);
698
+ adc_qom_set(qts, adc, name, value);
699
+}
700
+
701
+static void adc_write_vref(QTestState *qts, const ADC *adc, uint32_t value)
702
+{
703
+ adc_qom_set(qts, adc, "vref", value);
704
+}
705
+
706
+static uint32_t adc_calculate_output(uint32_t input, uint32_t ref)
707
+{
708
+ uint32_t output;
709
+
710
+ g_assert_cmpuint(input, <=, ref);
711
+ output = (input * (MAX_RESULT + 1)) / ref;
712
+ if (output > MAX_RESULT) {
713
+ output = MAX_RESULT;
714
+ }
715
+
716
+ return output;
717
+}
718
+
719
+static uint32_t adc_prescaler(QTestState *qts, const ADC *adc)
720
+{
721
+ uint32_t div = extract32(adc_read_con(qts, adc), 1, 8);
722
+
723
+ return 2 * (div + 1);
724
+}
725
+
726
+static int64_t adc_calculate_steps(uint32_t cycles, uint32_t prescale,
727
+ uint32_t clkdiv)
728
+{
729
+ return (NANOSECONDS_PER_SECOND / (REF_HZ >> clkdiv)) * cycles * prescale;
730
+}
731
+
732
+static void adc_wait_conv_finished(QTestState *qts, const ADC *adc,
733
+ uint32_t clkdiv)
734
+{
735
+ uint32_t prescaler = adc_prescaler(qts, adc);
736
+
737
+ /*
738
+ * ADC should takes roughly 20 cycles to convert one sample. So we assert it
739
+ * should take 10~30 cycles here.
740
+ */
741
+ qtest_clock_step(qts, adc_calculate_steps(CONV_CYCLES / 2, prescaler,
742
+ clkdiv));
743
+ /* ADC is still converting. */
744
+ g_assert_true(adc_read_con(qts, adc) & CON_CONV);
745
+ qtest_clock_step(qts, adc_calculate_steps(CONV_CYCLES, prescaler, clkdiv));
746
+ /* ADC has finished conversion. */
747
+ g_assert_false(adc_read_con(qts, adc) & CON_CONV);
748
+}
749
+
750
+/* Check ADC can be reset to default value. */
751
+static void test_init(gconstpointer adc_p)
752
+{
753
+ const ADC *adc = adc_p;
754
+
755
+ QTestState *qts = qtest_init("-machine quanta-gsj");
756
+ adc_write_con(qts, adc, CON_REFSEL | CON_INT);
757
+ g_assert_cmphex(adc_read_con(qts, adc), ==, CON_REFSEL);
758
+ qtest_quit(qts);
759
+}
760
+
761
+/* Check ADC can convert from an internal reference. */
762
+static void test_convert_internal(gconstpointer adc_p)
763
+{
764
+ const ADC *adc = adc_p;
765
+ uint32_t index, input, output, expected_output;
766
+ QTestState *qts = qtest_init("-machine quanta-gsj");
767
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
768
+
769
+ for (index = 0; index < NUM_INPUTS; ++index) {
770
+ for (size_t i = 0; i < ARRAY_SIZE(input_list); ++i) {
771
+ input = input_list[i];
772
+ expected_output = adc_calculate_output(input, DEFAULT_IREF);
773
+
774
+ adc_write_input(qts, adc, index, input);
775
+ adc_write_con(qts, adc, CON_MUX(index) | CON_REFSEL | CON_INT |
776
+ CON_EN | CON_CONV);
777
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
778
+ g_assert_cmphex(adc_read_con(qts, adc), ==, CON_MUX(index) |
779
+ CON_REFSEL | CON_EN);
780
+ g_assert_false(qtest_get_irq(qts, adc->irq));
781
+ output = adc_read_data(qts, adc);
782
+ g_assert_cmpuint(output, ==, expected_output);
783
+ }
784
+ }
785
+
786
+ qtest_quit(qts);
787
+}
788
+
789
+/* Check ADC can convert from an external reference. */
790
+static void test_convert_external(gconstpointer adc_p)
791
+{
792
+ const ADC *adc = adc_p;
793
+ uint32_t index, input, vref, output, expected_output;
794
+ QTestState *qts = qtest_init("-machine quanta-gsj");
795
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
796
+
797
+ for (index = 0; index < NUM_INPUTS; ++index) {
798
+ for (size_t i = 0; i < ARRAY_SIZE(input_list); ++i) {
799
+ for (size_t j = 0; j < ARRAY_SIZE(vref_list); ++j) {
800
+ input = input_list[i];
801
+ vref = vref_list[j];
802
+ expected_output = adc_calculate_output(input, vref);
803
+
804
+ adc_write_input(qts, adc, index, input);
805
+ adc_write_vref(qts, adc, vref);
806
+ adc_write_con(qts, adc, CON_MUX(index) | CON_INT | CON_EN |
807
+ CON_CONV);
808
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
809
+ g_assert_cmphex(adc_read_con(qts, adc), ==,
810
+ CON_MUX(index) | CON_EN);
811
+ g_assert_false(qtest_get_irq(qts, adc->irq));
812
+ output = adc_read_data(qts, adc);
813
+ g_assert_cmpuint(output, ==, expected_output);
814
+ }
815
+ }
816
+ }
817
+
818
+ qtest_quit(qts);
819
+}
820
+
821
+/* Check ADC interrupt files if and only if CON_INT_EN is set. */
822
+static void test_interrupt(gconstpointer adc_p)
823
+{
824
+ const ADC *adc = adc_p;
825
+ uint32_t index, input, output, expected_output;
826
+ QTestState *qts = qtest_init("-machine quanta-gsj");
827
+
828
+ index = 1;
829
+ input = input_list[1];
830
+ expected_output = adc_calculate_output(input, DEFAULT_IREF);
831
+
832
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
833
+ adc_write_input(qts, adc, index, input);
834
+ g_assert_false(qtest_get_irq(qts, adc->irq));
835
+ adc_write_con(qts, adc, CON_MUX(index) | CON_INT_EN | CON_REFSEL | CON_INT
836
+ | CON_EN | CON_CONV);
837
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
838
+ g_assert_cmphex(adc_read_con(qts, adc), ==, CON_MUX(index) | CON_INT_EN
839
+ | CON_REFSEL | CON_INT | CON_EN);
840
+ g_assert_true(qtest_get_irq(qts, adc->irq));
841
+ output = adc_read_data(qts, adc);
842
+ g_assert_cmpuint(output, ==, expected_output);
843
+
844
+ qtest_quit(qts);
845
+}
846
+
847
+/* Check ADC is reset after setting ADC_RST for 10 ADC cycles. */
848
+static void test_reset(gconstpointer adc_p)
849
+{
850
+ const ADC *adc = adc_p;
851
+ QTestState *qts = qtest_init("-machine quanta-gsj");
852
+
853
+ for (size_t i = 0; i < ARRAY_SIZE(div_list); ++i) {
854
+ uint32_t div = div_list[i];
855
+
856
+ adc_write_con(qts, adc, CON_INT | CON_EN | CON_RST | CON_DIV(div));
857
+ qtest_clock_step(qts, adc_calculate_steps(RESET_CYCLES,
858
+ adc_prescaler(qts, adc), DEFAULT_CLKDIV));
859
+ g_assert_false(adc_read_con(qts, adc) & CON_EN);
860
+ }
861
+ qtest_quit(qts);
862
+}
863
+
864
+/* Check ADC Calibration works as desired. */
865
+static void test_calibrate(gconstpointer adc_p)
866
+{
867
+ int i, j;
868
+ const ADC *adc = adc_p;
869
+
870
+ for (j = 0; j < ARRAY_SIZE(iref_list); ++j) {
871
+ uint32_t iref = iref_list[j];
872
+ uint32_t expected_rv[] = {
873
+ adc_calculate_output(R0_INPUT, iref),
874
+ adc_calculate_output(R1_INPUT, iref),
875
+ };
876
+ char buf[100];
877
+ QTestState *qts;
878
+
879
+ sprintf(buf, "-machine quanta-gsj -global npcm7xx-adc.iref=%u", iref);
880
+ qts = qtest_init(buf);
881
+
882
+ /* Check the converted value is correct using the calibration value. */
883
+ for (i = 0; i < ARRAY_SIZE(input_list); ++i) {
884
+ uint32_t input;
885
+ uint32_t output;
886
+ uint32_t expected_output;
887
+ uint32_t calibrated_voltage;
888
+ uint32_t index = 0;
889
+
890
+ input = input_list[i];
891
+ /* Calibration only works for input range 0.1V ~ 1.8V. */
892
+ if (input < MIN_CALIB_INPUT || input > MAX_CALIB_INPUT) {
893
+ continue;
894
+ }
895
+ expected_output = adc_calculate_output(input, iref);
896
+
897
+ adc_write_input(qts, adc, index, input);
898
+ adc_write_con(qts, adc, CON_MUX(index) | CON_REFSEL | CON_INT |
899
+ CON_EN | CON_CONV);
900
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
901
+ g_assert_cmphex(adc_read_con(qts, adc), ==,
902
+ CON_REFSEL | CON_MUX(index) | CON_EN);
903
+ output = adc_read_data(qts, adc);
904
+ g_assert_cmpuint(output, ==, expected_output);
905
+
906
+ calibrated_voltage = adc_calibrate(output, expected_rv);
907
+ g_assert_cmpuint(calibrated_voltage, >, input - MAX_ERROR);
908
+ g_assert_cmpuint(calibrated_voltage, <, input + MAX_ERROR);
909
+ }
910
+
911
+ qtest_quit(qts);
912
+ }
913
+}
914
+
915
+static void adc_add_test(const char *name, const ADC* wd,
916
+ GTestDataFunc fn)
917
+{
918
+ g_autofree char *full_name = g_strdup_printf("npcm7xx_adc/%s", name);
919
+ qtest_add_data_func(full_name, wd, fn);
920
+}
921
+#define add_test(name, td) adc_add_test(#name, td, test_##name)
922
+
923
+int main(int argc, char **argv)
924
+{
925
+ g_test_init(&argc, &argv, NULL);
926
+
927
+ add_test(init, &adc);
928
+ add_test(convert_internal, &adc);
929
+ add_test(convert_external, &adc);
930
+ add_test(interrupt, &adc);
931
+ add_test(reset, &adc);
932
+ add_test(calibrate, &adc);
933
+
934
+ return g_test_run();
935
+}
936
diff --git a/hw/adc/meson.build b/hw/adc/meson.build
937
index XXXXXXX..XXXXXXX 100644
938
--- a/hw/adc/meson.build
939
+++ b/hw/adc/meson.build
940
@@ -1 +1,2 @@
941
softmmu_ss.add(when: 'CONFIG_STM32F2XX_ADC', if_true: files('stm32f2xx_adc.c'))
942
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_adc.c'))
943
diff --git a/hw/adc/trace-events b/hw/adc/trace-events
944
new file mode 100644
945
index XXXXXXX..XXXXXXX
946
--- /dev/null
947
+++ b/hw/adc/trace-events
948
@@ -XXX,XX +XXX,XX @@
949
+# See docs/devel/tracing.txt for syntax documentation.
950
+
951
+# npcm7xx_adc.c
952
+npcm7xx_adc_read(const char *id, uint64_t offset, uint32_t value) " %s offset: 0x%04" PRIx64 " value 0x%04" PRIx32
953
+npcm7xx_adc_write(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value 0x%04" PRIx32
954
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
955
index XXXXXXX..XXXXXXX 100644
956
--- a/tests/qtest/meson.build
957
+++ b/tests/qtest/meson.build
958
@@ -XXX,XX +XXX,XX @@ qtests_sparc64 = \
959
['prom-env-test', 'boot-serial-test']
960
961
qtests_npcm7xx = \
962
- ['npcm7xx_gpio-test',
963
+ ['npcm7xx_adc-test',
964
+ 'npcm7xx_gpio-test',
965
'npcm7xx_rng-test',
966
'npcm7xx_timer-test',
967
'npcm7xx_watchdog_timer-test']
142
--
968
--
143
2.20.1
969
2.20.1
144
970
145
971
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
This patch implements Multi Function Timer (MFT) module for NPCM7XX.
3
The PWM module is part of NPCM7XX module. Each NPCM7XX module has two
4
This module is mainly used to configure PWM fans. It has just enough
4
identical PWM modules. Each module contains 4 PWM entries. Each PWM has
5
functionality to make the PWM fan kernel module work.
5
two outputs: frequency and duty_cycle. Both are computed using inputs
6
from software side.
6
7
7
The module takes two input, the max_rpm of a fan (modifiable via QMP)
8
This module does not model detail pulse signals since it is expensive.
8
and duty cycle (a GPIO from the PWM module.) The actual measured RPM
9
It also does not model interrupts and watchdogs that are dependant on
9
is equal to max_rpm * duty_cycle / NPCM7XX_PWM_MAX_DUTY. The RPM is
10
the detail models. The interfaces for these are left in the module so
10
measured as a counter compared to a prescaled input clock. The kernel
11
that anyone in need for these functionalities can implement on their
11
driver reads this counter and report to user space.
12
own.
12
13
13
Refs:
14
The user can read the duty cycle and frequency using qom-get command.
14
https://github.com/torvalds/linux/blob/master/drivers/hwmon/npcm750-pwm-fan.c
15
15
16
Reviewed-by: Doug Evans <dje@google.com>
16
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
17
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
17
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
18
Signed-off-by: Hao Wu <wuhaotsh@google.com>
18
Signed-off-by: Hao Wu <wuhaotsh@google.com>
19
Message-id: 20210311180855.149764-3-wuhaotsh@google.com
19
Message-id: 20210108190945.949196-5-wuhaotsh@google.com
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
22
---
23
include/hw/misc/npcm7xx_mft.h | 70 +++++
23
docs/system/arm/nuvoton.rst | 2 +-
24
hw/misc/npcm7xx_mft.c | 540 ++++++++++++++++++++++++++++++++++
24
include/hw/arm/npcm7xx.h | 2 +
25
include/hw/misc/npcm7xx_pwm.h | 105 +++++++
26
hw/arm/npcm7xx.c | 26 +-
27
hw/misc/npcm7xx_pwm.c | 550 ++++++++++++++++++++++++++++++++++
25
hw/misc/meson.build | 1 +
28
hw/misc/meson.build | 1 +
26
hw/misc/trace-events | 8 +
29
hw/misc/trace-events | 6 +
27
4 files changed, 619 insertions(+)
30
7 files changed, 689 insertions(+), 3 deletions(-)
28
create mode 100644 include/hw/misc/npcm7xx_mft.h
31
create mode 100644 include/hw/misc/npcm7xx_pwm.h
29
create mode 100644 hw/misc/npcm7xx_mft.c
32
create mode 100644 hw/misc/npcm7xx_pwm.c
30
33
31
diff --git a/include/hw/misc/npcm7xx_mft.h b/include/hw/misc/npcm7xx_mft.h
34
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
35
index XXXXXXX..XXXXXXX 100644
36
--- a/docs/system/arm/nuvoton.rst
37
+++ b/docs/system/arm/nuvoton.rst
38
@@ -XXX,XX +XXX,XX @@ Supported devices
39
* USB host (USBH)
40
* GPIO controller
41
* Analog to Digital Converter (ADC)
42
+ * Pulse Width Modulation (PWM)
43
44
Missing devices
45
---------------
46
@@ -XXX,XX +XXX,XX @@ Missing devices
47
* Peripheral SPI controller (PSPI)
48
* SD/MMC host
49
* PECI interface
50
- * Pulse Width Modulation (PWM)
51
* Tachometer
52
* PCI and PCIe root complex and bridges
53
* VDM and MCTP support
54
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
55
index XXXXXXX..XXXXXXX 100644
56
--- a/include/hw/arm/npcm7xx.h
57
+++ b/include/hw/arm/npcm7xx.h
58
@@ -XXX,XX +XXX,XX @@
59
#include "hw/mem/npcm7xx_mc.h"
60
#include "hw/misc/npcm7xx_clk.h"
61
#include "hw/misc/npcm7xx_gcr.h"
62
+#include "hw/misc/npcm7xx_pwm.h"
63
#include "hw/misc/npcm7xx_rng.h"
64
#include "hw/nvram/npcm7xx_otp.h"
65
#include "hw/timer/npcm7xx_timer.h"
66
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
67
NPCM7xxCLKState clk;
68
NPCM7xxTimerCtrlState tim[3];
69
NPCM7xxADCState adc;
70
+ NPCM7xxPWMState pwm[2];
71
NPCM7xxOTPState key_storage;
72
NPCM7xxOTPState fuse_array;
73
NPCM7xxMCState mc;
74
diff --git a/include/hw/misc/npcm7xx_pwm.h b/include/hw/misc/npcm7xx_pwm.h
32
new file mode 100644
75
new file mode 100644
33
index XXXXXXX..XXXXXXX
76
index XXXXXXX..XXXXXXX
34
--- /dev/null
77
--- /dev/null
35
+++ b/include/hw/misc/npcm7xx_mft.h
78
+++ b/include/hw/misc/npcm7xx_pwm.h
36
@@ -XXX,XX +XXX,XX @@
79
@@ -XXX,XX +XXX,XX @@
37
+/*
80
+/*
38
+ * Nuvoton NPCM7xx MFT Module
81
+ * Nuvoton NPCM7xx PWM Module
39
+ *
82
+ *
40
+ * Copyright 2021 Google LLC
83
+ * Copyright 2020 Google LLC
41
+ *
84
+ *
42
+ * This program is free software; you can redistribute it and/or modify it
85
+ * This program is free software; you can redistribute it and/or modify it
43
+ * under the terms of the GNU General Public License as published by the
86
+ * under the terms of the GNU General Public License as published by the
44
+ * Free Software Foundation; either version 2 of the License, or
87
+ * Free Software Foundation; either version 2 of the License, or
45
+ * (at your option) any later version.
88
+ * (at your option) any later version.
46
+ *
89
+ *
47
+ * This program is distributed in the hope that it will be useful, but WITHOUT
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
48
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
91
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
49
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
92
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
50
+ * for more details.
93
+ * for more details.
51
+ */
94
+ */
52
+#ifndef NPCM7XX_MFT_H
95
+#ifndef NPCM7XX_PWM_H
53
+#define NPCM7XX_MFT_H
96
+#define NPCM7XX_PWM_H
54
+
97
+
55
+#include "exec/memory.h"
56
+#include "hw/clock.h"
98
+#include "hw/clock.h"
99
+#include "hw/sysbus.h"
57
+#include "hw/irq.h"
100
+#include "hw/irq.h"
58
+#include "hw/sysbus.h"
101
+
59
+#include "qom/object.h"
102
+/* Each PWM module holds 4 PWM channels. */
60
+
103
+#define NPCM7XX_PWM_PER_MODULE 4
61
+/* Max Fan input number. */
62
+#define NPCM7XX_MFT_MAX_FAN_INPUT 19
63
+
104
+
64
+/*
105
+/*
65
+ * Number of registers in one MFT module. Don't change this without increasing
106
+ * Number of registers in one pwm module. Don't change this without increasing
66
+ * the version_id in vmstate.
107
+ * the version_id in vmstate.
67
+ */
108
+ */
68
+#define NPCM7XX_MFT_NR_REGS (0x20 / sizeof(uint16_t))
109
+#define NPCM7XX_PWM_NR_REGS (0x54 / sizeof(uint32_t))
69
+
110
+
70
+/*
111
+/*
71
+ * The MFT can take up to 4 inputs: A0, B0, A1, B1. It can measure one A and one
112
+ * The maximum duty values. Each duty unit represents 1/NPCM7XX_PWM_MAX_DUTY
72
+ * B simultaneously. NPCM7XX_MFT_INASEL and NPCM7XX_MFT_INBSEL are used to
113
+ * cycles. For example, if NPCM7XX_PWM_MAX_DUTY=1,000,000 and a PWM has a duty
73
+ * select which A or B input are used.
114
+ * value of 100,000 the duty cycle for that PWM is 10%.
74
+ */
115
+ */
75
+#define NPCM7XX_MFT_FANIN_COUNT 4
116
+#define NPCM7XX_PWM_MAX_DUTY 1000000
117
+
118
+typedef struct NPCM7xxPWMState NPCM7xxPWMState;
76
+
119
+
77
+/**
120
+/**
78
+ * struct NPCM7xxMFTState - Multi Functional Tachometer device state.
121
+ * struct NPCM7xxPWM - The state of a single PWM channel.
122
+ * @module: The PWM module that contains this channel.
123
+ * @irq: GIC interrupt line to fire on expiration if enabled.
124
+ * @running: Whether this PWM channel is generating output.
125
+ * @inverted: Whether this PWM channel is inverted.
126
+ * @index: The index of this PWM channel.
127
+ * @cnr: The counter register.
128
+ * @cmr: The comparator register.
129
+ * @pdr: The data register.
130
+ * @pwdr: The watchdog register.
131
+ * @freq: The frequency of this PWM channel.
132
+ * @duty: The duty cycle of this PWM channel. One unit represents
133
+ * 1/NPCM7XX_MAX_DUTY cycles.
134
+ */
135
+typedef struct NPCM7xxPWM {
136
+ NPCM7xxPWMState *module;
137
+
138
+ qemu_irq irq;
139
+
140
+ bool running;
141
+ bool inverted;
142
+
143
+ uint8_t index;
144
+ uint32_t cnr;
145
+ uint32_t cmr;
146
+ uint32_t pdr;
147
+ uint32_t pwdr;
148
+
149
+ uint32_t freq;
150
+ uint32_t duty;
151
+} NPCM7xxPWM;
152
+
153
+/**
154
+ * struct NPCM7xxPWMState - Pulse Width Modulation device state.
79
+ * @parent: System bus device.
155
+ * @parent: System bus device.
80
+ * @iomem: Memory region through which registers are accessed.
156
+ * @iomem: Memory region through which registers are accessed.
81
+ * @clock_in: The input clock for MFT from CLK module.
157
+ * @clock: The PWM clock.
82
+ * @clock_{1,2}: The counter clocks for NPCM7XX_MFT_CNT{1,2}
158
+ * @pwm: The PWM channels owned by this module.
83
+ * @irq: The IRQ for this MFT state.
159
+ * @ppr: The prescaler register.
84
+ * @regs: The MMIO registers.
160
+ * @csr: The clock selector register.
85
+ * @max_rpm: The maximum rpm for fans. Order: A0, B0, A1, B1.
161
+ * @pcr: The control register.
86
+ * @duty: The duty cycles for fans, relative to NPCM7XX_PWM_MAX_DUTY.
162
+ * @pier: The interrupt enable register.
163
+ * @piir: The interrupt indication register.
87
+ */
164
+ */
88
+typedef struct NPCM7xxMFTState {
165
+struct NPCM7xxPWMState {
89
+ SysBusDevice parent;
166
+ SysBusDevice parent;
90
+
167
+
91
+ MemoryRegion iomem;
168
+ MemoryRegion iomem;
92
+
169
+
93
+ Clock *clock_in;
170
+ Clock *clock;
94
+ Clock *clock_1, *clock_2;
171
+ NPCM7xxPWM pwm[NPCM7XX_PWM_PER_MODULE];
95
+ qemu_irq irq;
172
+
96
+ uint16_t regs[NPCM7XX_MFT_NR_REGS];
173
+ uint32_t ppr;
97
+
174
+ uint32_t csr;
98
+ uint32_t max_rpm[NPCM7XX_MFT_FANIN_COUNT];
175
+ uint32_t pcr;
99
+ uint32_t duty[NPCM7XX_MFT_FANIN_COUNT];
176
+ uint32_t pier;
100
+} NPCM7xxMFTState;
177
+ uint32_t piir;
101
+
178
+};
102
+#define TYPE_NPCM7XX_MFT "npcm7xx-mft"
179
+
103
+#define NPCM7XX_MFT(obj) \
180
+#define TYPE_NPCM7XX_PWM "npcm7xx-pwm"
104
+ OBJECT_CHECK(NPCM7xxMFTState, (obj), TYPE_NPCM7XX_MFT)
181
+#define NPCM7XX_PWM(obj) \
105
+
182
+ OBJECT_CHECK(NPCM7xxPWMState, (obj), TYPE_NPCM7XX_PWM)
106
+#endif /* NPCM7XX_MFT_H */
183
+
107
diff --git a/hw/misc/npcm7xx_mft.c b/hw/misc/npcm7xx_mft.c
184
+#endif /* NPCM7XX_PWM_H */
185
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
186
index XXXXXXX..XXXXXXX 100644
187
--- a/hw/arm/npcm7xx.c
188
+++ b/hw/arm/npcm7xx.c
189
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
190
NPCM7XX_WDG2_IRQ, /* Timer Module 2 Watchdog */
191
NPCM7XX_EHCI_IRQ = 61,
192
NPCM7XX_OHCI_IRQ = 62,
193
+ NPCM7XX_PWM0_IRQ = 93, /* PWM module 0 */
194
+ NPCM7XX_PWM1_IRQ, /* PWM module 1 */
195
NPCM7XX_GPIO0_IRQ = 116,
196
NPCM7XX_GPIO1_IRQ,
197
NPCM7XX_GPIO2_IRQ,
198
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_fiu3_flash_addr[] = {
199
0xb8000000, /* CS3 */
200
};
201
202
+/* Register base address for each PWM Module */
203
+static const hwaddr npcm7xx_pwm_addr[] = {
204
+ 0xf0103000,
205
+ 0xf0104000,
206
+};
207
+
208
static const struct {
209
hwaddr regs_addr;
210
uint32_t unconnected_pins;
211
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
212
object_initialize_child(obj, npcm7xx_fiu[i].name, &s->fiu[i],
213
TYPE_NPCM7XX_FIU);
214
}
215
+
216
+ for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
217
+ object_initialize_child(obj, "pwm[*]", &s->pwm[i], TYPE_NPCM7XX_PWM);
218
+ }
219
}
220
221
static void npcm7xx_realize(DeviceState *dev, Error **errp)
222
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
223
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ohci), 0,
224
npcm7xx_irq(s, NPCM7XX_OHCI_IRQ));
225
226
+ /* PWM Modules. Cannot fail. */
227
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_pwm_addr) != ARRAY_SIZE(s->pwm));
228
+ for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
229
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->pwm[i]);
230
+
231
+ qdev_connect_clock_in(DEVICE(&s->pwm[i]), "clock", qdev_get_clock_out(
232
+ DEVICE(&s->clk), "apb3-clock"));
233
+ sysbus_realize(sbd, &error_abort);
234
+ sysbus_mmio_map(sbd, 0, npcm7xx_pwm_addr[i]);
235
+ sysbus_connect_irq(sbd, i, npcm7xx_irq(s, NPCM7XX_PWM0_IRQ + i));
236
+ }
237
+
238
/*
239
* Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
240
* specified, but this is a programming error.
241
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
242
create_unimplemented_device("npcm7xx.peci", 0xf0100000, 4 * KiB);
243
create_unimplemented_device("npcm7xx.siox[1]", 0xf0101000, 4 * KiB);
244
create_unimplemented_device("npcm7xx.siox[2]", 0xf0102000, 4 * KiB);
245
- create_unimplemented_device("npcm7xx.pwm[0]", 0xf0103000, 4 * KiB);
246
- create_unimplemented_device("npcm7xx.pwm[1]", 0xf0104000, 4 * KiB);
247
create_unimplemented_device("npcm7xx.mft[0]", 0xf0180000, 4 * KiB);
248
create_unimplemented_device("npcm7xx.mft[1]", 0xf0181000, 4 * KiB);
249
create_unimplemented_device("npcm7xx.mft[2]", 0xf0182000, 4 * KiB);
250
diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
108
new file mode 100644
251
new file mode 100644
109
index XXXXXXX..XXXXXXX
252
index XXXXXXX..XXXXXXX
110
--- /dev/null
253
--- /dev/null
111
+++ b/hw/misc/npcm7xx_mft.c
254
+++ b/hw/misc/npcm7xx_pwm.c
112
@@ -XXX,XX +XXX,XX @@
255
@@ -XXX,XX +XXX,XX @@
113
+/*
256
+/*
114
+ * Nuvoton NPCM7xx MFT Module
257
+ * Nuvoton NPCM7xx PWM Module
115
+ *
258
+ *
116
+ * Copyright 2021 Google LLC
259
+ * Copyright 2020 Google LLC
117
+ *
260
+ *
118
+ * This program is free software; you can redistribute it and/or modify it
261
+ * This program is free software; you can redistribute it and/or modify it
119
+ * under the terms of the GNU General Public License as published by the
262
+ * under the terms of the GNU General Public License as published by the
120
+ * Free Software Foundation; either version 2 of the License, or
263
+ * Free Software Foundation; either version 2 of the License, or
121
+ * (at your option) any later version.
264
+ * (at your option) any later version.
...
...
128
+
271
+
129
+#include "qemu/osdep.h"
272
+#include "qemu/osdep.h"
130
+#include "hw/irq.h"
273
+#include "hw/irq.h"
131
+#include "hw/qdev-clock.h"
274
+#include "hw/qdev-clock.h"
132
+#include "hw/qdev-properties.h"
275
+#include "hw/qdev-properties.h"
133
+#include "hw/misc/npcm7xx_mft.h"
134
+#include "hw/misc/npcm7xx_pwm.h"
276
+#include "hw/misc/npcm7xx_pwm.h"
135
+#include "hw/registerfields.h"
277
+#include "hw/registerfields.h"
136
+#include "migration/vmstate.h"
278
+#include "migration/vmstate.h"
137
+#include "qapi/error.h"
138
+#include "qapi/visitor.h"
139
+#include "qemu/bitops.h"
279
+#include "qemu/bitops.h"
140
+#include "qemu/error-report.h"
280
+#include "qemu/error-report.h"
141
+#include "qemu/log.h"
281
+#include "qemu/log.h"
142
+#include "qemu/module.h"
282
+#include "qemu/module.h"
143
+#include "qemu/timer.h"
144
+#include "qemu/units.h"
283
+#include "qemu/units.h"
145
+#include "trace.h"
284
+#include "trace.h"
146
+
285
+
147
+/*
286
+REG32(NPCM7XX_PWM_PPR, 0x00);
148
+ * Some of the registers can only accessed via 16-bit ops and some can only
287
+REG32(NPCM7XX_PWM_CSR, 0x04);
149
+ * be accessed via 8-bit ops. However we mark all of them using REG16 to
288
+REG32(NPCM7XX_PWM_PCR, 0x08);
150
+ * simplify implementation. npcm7xx_mft_check_mem_op checks the access length
289
+REG32(NPCM7XX_PWM_CNR0, 0x0c);
151
+ * of memory operations.
290
+REG32(NPCM7XX_PWM_CMR0, 0x10);
152
+ */
291
+REG32(NPCM7XX_PWM_PDR0, 0x14);
153
+REG16(NPCM7XX_MFT_CNT1, 0x00);
292
+REG32(NPCM7XX_PWM_CNR1, 0x18);
154
+REG16(NPCM7XX_MFT_CRA, 0x02);
293
+REG32(NPCM7XX_PWM_CMR1, 0x1c);
155
+REG16(NPCM7XX_MFT_CRB, 0x04);
294
+REG32(NPCM7XX_PWM_PDR1, 0x20);
156
+REG16(NPCM7XX_MFT_CNT2, 0x06);
295
+REG32(NPCM7XX_PWM_CNR2, 0x24);
157
+REG16(NPCM7XX_MFT_PRSC, 0x08);
296
+REG32(NPCM7XX_PWM_CMR2, 0x28);
158
+REG16(NPCM7XX_MFT_CKC, 0x0a);
297
+REG32(NPCM7XX_PWM_PDR2, 0x2c);
159
+REG16(NPCM7XX_MFT_MCTRL, 0x0c);
298
+REG32(NPCM7XX_PWM_CNR3, 0x30);
160
+REG16(NPCM7XX_MFT_ICTRL, 0x0e);
299
+REG32(NPCM7XX_PWM_CMR3, 0x34);
161
+REG16(NPCM7XX_MFT_ICLR, 0x10);
300
+REG32(NPCM7XX_PWM_PDR3, 0x38);
162
+REG16(NPCM7XX_MFT_IEN, 0x12);
301
+REG32(NPCM7XX_PWM_PIER, 0x3c);
163
+REG16(NPCM7XX_MFT_CPA, 0x14);
302
+REG32(NPCM7XX_PWM_PIIR, 0x40);
164
+REG16(NPCM7XX_MFT_CPB, 0x16);
303
+REG32(NPCM7XX_PWM_PWDR0, 0x44);
165
+REG16(NPCM7XX_MFT_CPCFG, 0x18);
304
+REG32(NPCM7XX_PWM_PWDR1, 0x48);
166
+REG16(NPCM7XX_MFT_INASEL, 0x1a);
305
+REG32(NPCM7XX_PWM_PWDR2, 0x4c);
167
+REG16(NPCM7XX_MFT_INBSEL, 0x1c);
306
+REG32(NPCM7XX_PWM_PWDR3, 0x50);
168
+
307
+
169
+/* Register Fields */
308
+/* Register field definitions. */
170
+#define NPCM7XX_MFT_CKC_C2CSEL BIT(3)
309
+#define NPCM7XX_PPR(rv, index) extract32((rv), npcm7xx_ppr_base[index], 8)
171
+#define NPCM7XX_MFT_CKC_C1CSEL BIT(0)
310
+#define NPCM7XX_CSR(rv, index) extract32((rv), npcm7xx_csr_base[index], 3)
172
+
311
+#define NPCM7XX_CH(rv, index) extract32((rv), npcm7xx_ch_base[index], 4)
173
+#define NPCM7XX_MFT_MCTRL_TBEN BIT(6)
312
+#define NPCM7XX_CH_EN BIT(0)
174
+#define NPCM7XX_MFT_MCTRL_TAEN BIT(5)
313
+#define NPCM7XX_CH_INV BIT(2)
175
+#define NPCM7XX_MFT_MCTRL_TBEDG BIT(4)
314
+#define NPCM7XX_CH_MOD BIT(3)
176
+#define NPCM7XX_MFT_MCTRL_TAEDG BIT(3)
315
+
177
+#define NPCM7XX_MFT_MCTRL_MODE5 BIT(2)
316
+/* Offset of each PWM channel's prescaler in the PPR register. */
178
+
317
+static const int npcm7xx_ppr_base[] = { 0, 0, 8, 8 };
179
+#define NPCM7XX_MFT_ICTRL_TFPND BIT(5)
318
+/* Offset of each PWM channel's clock selector in the CSR register. */
180
+#define NPCM7XX_MFT_ICTRL_TEPND BIT(4)
319
+static const int npcm7xx_csr_base[] = { 0, 4, 8, 12 };
181
+#define NPCM7XX_MFT_ICTRL_TDPND BIT(3)
320
+/* Offset of each PWM channel's control variable in the PCR register. */
182
+#define NPCM7XX_MFT_ICTRL_TCPND BIT(2)
321
+static const int npcm7xx_ch_base[] = { 0, 8, 12, 16 };
183
+#define NPCM7XX_MFT_ICTRL_TBPND BIT(1)
322
+
184
+#define NPCM7XX_MFT_ICTRL_TAPND BIT(0)
323
+static uint32_t npcm7xx_pwm_calculate_freq(NPCM7xxPWM *p)
185
+
324
+{
186
+#define NPCM7XX_MFT_ICLR_TFCLR BIT(5)
325
+ uint32_t ppr;
187
+#define NPCM7XX_MFT_ICLR_TECLR BIT(4)
326
+ uint32_t csr;
188
+#define NPCM7XX_MFT_ICLR_TDCLR BIT(3)
327
+ uint32_t freq;
189
+#define NPCM7XX_MFT_ICLR_TCCLR BIT(2)
328
+
190
+#define NPCM7XX_MFT_ICLR_TBCLR BIT(1)
329
+ if (!p->running) {
191
+#define NPCM7XX_MFT_ICLR_TACLR BIT(0)
330
+ return 0;
192
+
331
+ }
193
+#define NPCM7XX_MFT_IEN_TFIEN BIT(5)
332
+
194
+#define NPCM7XX_MFT_IEN_TEIEN BIT(4)
333
+ csr = NPCM7XX_CSR(p->module->csr, p->index);
195
+#define NPCM7XX_MFT_IEN_TDIEN BIT(3)
334
+ ppr = NPCM7XX_PPR(p->module->ppr, p->index);
196
+#define NPCM7XX_MFT_IEN_TCIEN BIT(2)
335
+ freq = clock_get_hz(p->module->clock);
197
+#define NPCM7XX_MFT_IEN_TBIEN BIT(1)
336
+ freq /= ppr + 1;
198
+#define NPCM7XX_MFT_IEN_TAIEN BIT(0)
337
+ /* csr can only be 0~4 */
199
+
338
+ if (csr > 4) {
200
+#define NPCM7XX_MFT_CPCFG_GET_B(rv) extract8((rv), 4, 4)
339
+ qemu_log_mask(LOG_GUEST_ERROR,
201
+#define NPCM7XX_MFT_CPCFG_GET_A(rv) extract8((rv), 0, 4)
340
+ "%s: invalid csr value %u\n",
202
+#define NPCM7XX_MFT_CPCFG_HIEN BIT(3)
341
+ __func__, csr);
203
+#define NPCM7XX_MFT_CPCFG_EQEN BIT(2)
342
+ csr = 4;
204
+#define NPCM7XX_MFT_CPCFG_LOEN BIT(1)
343
+ }
205
+#define NPCM7XX_MFT_CPCFG_CPSEL BIT(0)
344
+ /* freq won't be changed if csr == 4. */
206
+
345
+ if (csr < 4) {
207
+#define NPCM7XX_MFT_INASEL_SELA BIT(0)
346
+ freq >>= csr + 1;
208
+#define NPCM7XX_MFT_INBSEL_SELB BIT(0)
347
+ }
209
+
348
+
210
+/* Max CNT values of the module. The CNT value is a countdown from it. */
349
+ return freq / (p->cnr + 1);
211
+#define NPCM7XX_MFT_MAX_CNT 0xFFFF
350
+}
212
+
351
+
213
+/* Each fan revolution should generated 2 pulses */
352
+static uint32_t npcm7xx_pwm_calculate_duty(NPCM7xxPWM *p)
214
+#define NPCM7XX_MFT_PULSE_PER_REVOLUTION 2
353
+{
215
+
354
+ uint64_t duty;
216
+typedef enum NPCM7xxMFTCaptureState {
355
+
217
+ /* capture succeeded with a valid CNT value. */
356
+ if (p->running) {
218
+ NPCM7XX_CAPTURE_SUCCEED,
357
+ if (p->cnr == 0) {
219
+ /* capture stopped prematurely due to reaching CPCFG condition. */
358
+ duty = 0;
220
+ NPCM7XX_CAPTURE_COMPARE_HIT,
359
+ } else if (p->cmr >= p->cnr) {
221
+ /* capture fails since it reaches underflow condition for CNT. */
360
+ duty = NPCM7XX_PWM_MAX_DUTY;
222
+ NPCM7XX_CAPTURE_UNDERFLOW,
223
+} NPCM7xxMFTCaptureState;
224
+
225
+static void npcm7xx_mft_reset(NPCM7xxMFTState *s)
226
+{
227
+ int i;
228
+
229
+ /* Only registers PRSC ~ INBSEL need to be reset. */
230
+ for (i = R_NPCM7XX_MFT_PRSC; i <= R_NPCM7XX_MFT_INBSEL; ++i) {
231
+ s->regs[i] = 0;
232
+ }
233
+}
234
+
235
+static void npcm7xx_mft_clear_interrupt(NPCM7xxMFTState *s, uint8_t iclr)
236
+{
237
+ /*
238
+ * Clear bits in ICTRL where corresponding bits in iclr is 1.
239
+ * Both iclr and ictrl are 8-bit regs. (See npcm7xx_mft_check_mem_op)
240
+ */
241
+ s->regs[R_NPCM7XX_MFT_ICTRL] &= ~iclr;
242
+}
243
+
244
+/*
245
+ * If the CPCFG's condition should be triggered during count down from
246
+ * NPCM7XX_MFT_MAX_CNT to src if compared to tgt, return the count when
247
+ * the condition is triggered.
248
+ * Otherwise return -1.
249
+ * Since tgt is uint16_t it must always <= NPCM7XX_MFT_MAX_CNT.
250
+ */
251
+static int npcm7xx_mft_compare(int32_t src, uint16_t tgt, uint8_t cpcfg)
252
+{
253
+ if (cpcfg & NPCM7XX_MFT_CPCFG_HIEN) {
254
+ return NPCM7XX_MFT_MAX_CNT;
255
+ }
256
+ if ((cpcfg & NPCM7XX_MFT_CPCFG_EQEN) && (src <= tgt)) {
257
+ return tgt;
258
+ }
259
+ if ((cpcfg & NPCM7XX_MFT_CPCFG_LOEN) && (tgt > 0) && (src < tgt)) {
260
+ return tgt - 1;
261
+ }
262
+
263
+ return -1;
264
+}
265
+
266
+/* Compute CNT according to corresponding fan's RPM. */
267
+static NPCM7xxMFTCaptureState npcm7xx_mft_compute_cnt(
268
+ Clock *clock, uint32_t max_rpm, uint32_t duty, uint16_t tgt,
269
+ uint8_t cpcfg, uint16_t *cnt)
270
+{
271
+ uint32_t rpm = (uint64_t)max_rpm * (uint64_t)duty / NPCM7XX_PWM_MAX_DUTY;
272
+ int32_t count;
273
+ int stopped;
274
+ NPCM7xxMFTCaptureState state;
275
+
276
+ if (rpm == 0) {
277
+ /*
278
+ * If RPM = 0, capture won't happen. CNT will continue count down.
279
+ * So it's effective equivalent to have a cnt > NPCM7XX_MFT_MAX_CNT
280
+ */
281
+ count = NPCM7XX_MFT_MAX_CNT + 1;
282
+ } else {
283
+ /*
284
+ * RPM = revolution/min. The time for one revlution (in ns) is
285
+ * MINUTE_TO_NANOSECOND / RPM.
286
+ */
287
+ count = clock_ns_to_ticks(clock, (60 * NANOSECONDS_PER_SECOND) /
288
+ (rpm * NPCM7XX_MFT_PULSE_PER_REVOLUTION));
289
+ }
290
+
291
+ if (count > NPCM7XX_MFT_MAX_CNT) {
292
+ count = -1;
293
+ } else {
294
+ /* The CNT is a countdown value from NPCM7XX_MFT_MAX_CNT. */
295
+ count = NPCM7XX_MFT_MAX_CNT - count;
296
+ }
297
+ stopped = npcm7xx_mft_compare(count, tgt, cpcfg);
298
+ if (stopped == -1) {
299
+ if (count == -1) {
300
+ /* Underflow */
301
+ state = NPCM7XX_CAPTURE_UNDERFLOW;
302
+ } else {
361
+ } else {
303
+ state = NPCM7XX_CAPTURE_SUCCEED;
362
+ duty = NPCM7XX_PWM_MAX_DUTY * (p->cmr + 1) / (p->cnr + 1);
304
+ }
363
+ }
305
+ } else {
364
+ } else {
306
+ count = stopped;
365
+ duty = 0;
307
+ state = NPCM7XX_CAPTURE_COMPARE_HIT;
366
+ }
308
+ }
367
+
309
+
368
+ if (p->inverted) {
310
+ if (count != -1) {
369
+ duty = NPCM7XX_PWM_MAX_DUTY - duty;
311
+ *cnt = count;
370
+ }
312
+ }
371
+
313
+ trace_npcm7xx_mft_rpm(clock->canonical_path, clock_get_hz(clock),
372
+ return duty;
314
+ state, count, rpm, duty);
373
+}
315
+ return state;
374
+
316
+}
375
+static void npcm7xx_pwm_update_freq(NPCM7xxPWM *p)
317
+
376
+{
318
+/*
377
+ uint32_t freq = npcm7xx_pwm_calculate_freq(p);
319
+ * Capture Fan RPM and update CNT and CR registers accordingly.
378
+
320
+ * Raise IRQ if certain contidions are met in IEN.
379
+ if (freq != p->freq) {
321
+ */
380
+ trace_npcm7xx_pwm_update_freq(DEVICE(p->module)->canonical_path,
322
+static void npcm7xx_mft_capture(NPCM7xxMFTState *s)
381
+ p->index, p->freq, freq);
323
+{
382
+ p->freq = freq;
324
+ int irq_level = 0;
383
+ }
325
+ NPCM7xxMFTCaptureState state;
384
+}
326
+ int sel;
385
+
327
+ uint8_t cpcfg;
386
+static void npcm7xx_pwm_update_duty(NPCM7xxPWM *p)
328
+
387
+{
329
+ /*
388
+ uint32_t duty = npcm7xx_pwm_calculate_duty(p);
330
+ * If not mode 5, the behavior is undefined. We just do nothing in this
389
+
331
+ * case.
390
+ if (duty != p->duty) {
332
+ */
391
+ trace_npcm7xx_pwm_update_duty(DEVICE(p->module)->canonical_path,
333
+ if (!(s->regs[R_NPCM7XX_MFT_MCTRL] & NPCM7XX_MFT_MCTRL_MODE5)) {
392
+ p->index, p->duty, duty);
334
+ return;
393
+ p->duty = duty;
335
+ }
394
+ }
336
+
395
+}
337
+ /* Capture input A. */
396
+
338
+ if (s->regs[R_NPCM7XX_MFT_MCTRL] & NPCM7XX_MFT_MCTRL_TAEN &&
397
+static void npcm7xx_pwm_update_output(NPCM7xxPWM *p)
339
+ s->regs[R_NPCM7XX_MFT_CKC] & NPCM7XX_MFT_CKC_C1CSEL) {
398
+{
340
+ sel = s->regs[R_NPCM7XX_MFT_INASEL] & NPCM7XX_MFT_INASEL_SELA;
399
+ npcm7xx_pwm_update_freq(p);
341
+ cpcfg = NPCM7XX_MFT_CPCFG_GET_A(s->regs[R_NPCM7XX_MFT_CPCFG]);
400
+ npcm7xx_pwm_update_duty(p);
342
+ state = npcm7xx_mft_compute_cnt(s->clock_1,
401
+}
343
+ sel ? s->max_rpm[2] : s->max_rpm[0],
402
+
344
+ sel ? s->duty[2] : s->duty[0],
403
+static void npcm7xx_pwm_write_ppr(NPCM7xxPWMState *s, uint32_t new_ppr)
345
+ s->regs[R_NPCM7XX_MFT_CPA],
404
+{
346
+ cpcfg,
405
+ int i;
347
+ &s->regs[R_NPCM7XX_MFT_CNT1]);
406
+ uint32_t old_ppr = s->ppr;
348
+ switch (state) {
407
+
349
+ case NPCM7XX_CAPTURE_SUCCEED:
408
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_ppr_base) != NPCM7XX_PWM_PER_MODULE);
350
+ /* Interrupt on input capture on TAn transition - TAPND */
409
+ s->ppr = new_ppr;
351
+ s->regs[R_NPCM7XX_MFT_CRA] = s->regs[R_NPCM7XX_MFT_CNT1];
410
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
352
+ s->regs[R_NPCM7XX_MFT_ICTRL] |= NPCM7XX_MFT_ICTRL_TAPND;
411
+ if (NPCM7XX_PPR(old_ppr, i) != NPCM7XX_PPR(new_ppr, i)) {
353
+ if (s->regs[R_NPCM7XX_MFT_IEN] & NPCM7XX_MFT_IEN_TAIEN) {
412
+ npcm7xx_pwm_update_freq(&s->pwm[i]);
354
+ irq_level = 1;
413
+ }
414
+ }
415
+}
416
+
417
+static void npcm7xx_pwm_write_csr(NPCM7xxPWMState *s, uint32_t new_csr)
418
+{
419
+ int i;
420
+ uint32_t old_csr = s->csr;
421
+
422
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_csr_base) != NPCM7XX_PWM_PER_MODULE);
423
+ s->csr = new_csr;
424
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
425
+ if (NPCM7XX_CSR(old_csr, i) != NPCM7XX_CSR(new_csr, i)) {
426
+ npcm7xx_pwm_update_freq(&s->pwm[i]);
427
+ }
428
+ }
429
+}
430
+
431
+static void npcm7xx_pwm_write_pcr(NPCM7xxPWMState *s, uint32_t new_pcr)
432
+{
433
+ int i;
434
+ bool inverted;
435
+ uint32_t pcr;
436
+ NPCM7xxPWM *p;
437
+
438
+ s->pcr = new_pcr;
439
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_ch_base) != NPCM7XX_PWM_PER_MODULE);
440
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
441
+ p = &s->pwm[i];
442
+ pcr = NPCM7XX_CH(new_pcr, i);
443
+ inverted = pcr & NPCM7XX_CH_INV;
444
+
445
+ /*
446
+ * We only run a PWM channel with toggle mode. Single-shot mode does not
447
+ * generate frequency and duty-cycle values.
448
+ */
449
+ if ((pcr & NPCM7XX_CH_EN) && (pcr & NPCM7XX_CH_MOD)) {
450
+ if (p->running) {
451
+ /* Re-run this PWM channel if inverted changed. */
452
+ if (p->inverted ^ inverted) {
453
+ p->inverted = inverted;
454
+ npcm7xx_pwm_update_duty(p);
455
+ }
456
+ } else {
457
+ /* Run this PWM channel. */
458
+ p->running = true;
459
+ p->inverted = inverted;
460
+ npcm7xx_pwm_update_output(p);
355
+ }
461
+ }
356
+ break;
462
+ } else {
357
+
463
+ /* Clear this PWM channel. */
358
+ case NPCM7XX_CAPTURE_COMPARE_HIT:
464
+ p->running = false;
359
+ /* Compare Hit - TEPND */
465
+ p->inverted = inverted;
360
+ s->regs[R_NPCM7XX_MFT_ICTRL] |= NPCM7XX_MFT_ICTRL_TEPND;
466
+ npcm7xx_pwm_update_output(p);
361
+ if (s->regs[R_NPCM7XX_MFT_IEN] & NPCM7XX_MFT_IEN_TEIEN) {
362
+ irq_level = 1;
363
+ }
364
+ break;
365
+
366
+ case NPCM7XX_CAPTURE_UNDERFLOW:
367
+ /* Underflow - TCPND */
368
+ s->regs[R_NPCM7XX_MFT_ICTRL] |= NPCM7XX_MFT_ICTRL_TCPND;
369
+ if (s->regs[R_NPCM7XX_MFT_IEN] & NPCM7XX_MFT_IEN_TCIEN) {
370
+ irq_level = 1;
371
+ }
372
+ break;
373
+
374
+ default:
375
+ g_assert_not_reached();
376
+ }
467
+ }
377
+ }
468
+ }
378
+
469
+
379
+ /* Capture input B. */
470
+}
380
+ if (s->regs[R_NPCM7XX_MFT_MCTRL] & NPCM7XX_MFT_MCTRL_TBEN &&
471
+
381
+ s->regs[R_NPCM7XX_MFT_CKC] & NPCM7XX_MFT_CKC_C2CSEL) {
472
+static hwaddr npcm7xx_cnr_index(hwaddr offset)
382
+ sel = s->regs[R_NPCM7XX_MFT_INBSEL] & NPCM7XX_MFT_INBSEL_SELB;
473
+{
383
+ cpcfg = NPCM7XX_MFT_CPCFG_GET_B(s->regs[R_NPCM7XX_MFT_CPCFG]);
384
+ state = npcm7xx_mft_compute_cnt(s->clock_2,
385
+ sel ? s->max_rpm[3] : s->max_rpm[1],
386
+ sel ? s->duty[3] : s->duty[1],
387
+ s->regs[R_NPCM7XX_MFT_CPB],
388
+ cpcfg,
389
+ &s->regs[R_NPCM7XX_MFT_CNT2]);
390
+ switch (state) {
391
+ case NPCM7XX_CAPTURE_SUCCEED:
392
+ /* Interrupt on input capture on TBn transition - TBPND */
393
+ s->regs[R_NPCM7XX_MFT_CRB] = s->regs[R_NPCM7XX_MFT_CNT2];
394
+ s->regs[R_NPCM7XX_MFT_ICTRL] |= NPCM7XX_MFT_ICTRL_TBPND;
395
+ if (s->regs[R_NPCM7XX_MFT_IEN] & NPCM7XX_MFT_IEN_TBIEN) {
396
+ irq_level = 1;
397
+ }
398
+ break;
399
+
400
+ case NPCM7XX_CAPTURE_COMPARE_HIT:
401
+ /* Compare Hit - TFPND */
402
+ s->regs[R_NPCM7XX_MFT_ICTRL] |= NPCM7XX_MFT_ICTRL_TFPND;
403
+ if (s->regs[R_NPCM7XX_MFT_IEN] & NPCM7XX_MFT_IEN_TFIEN) {
404
+ irq_level = 1;
405
+ }
406
+ break;
407
+
408
+ case NPCM7XX_CAPTURE_UNDERFLOW:
409
+ /* Underflow - TDPND */
410
+ s->regs[R_NPCM7XX_MFT_ICTRL] |= NPCM7XX_MFT_ICTRL_TDPND;
411
+ if (s->regs[R_NPCM7XX_MFT_IEN] & NPCM7XX_MFT_IEN_TDIEN) {
412
+ irq_level = 1;
413
+ }
414
+ break;
415
+
416
+ default:
417
+ g_assert_not_reached();
418
+ }
419
+ }
420
+
421
+ trace_npcm7xx_mft_capture(DEVICE(s)->canonical_path, irq_level);
422
+ qemu_set_irq(s->irq, irq_level);
423
+}
424
+
425
+/* Update clock for counters. */
426
+static void npcm7xx_mft_update_clock(void *opaque, ClockEvent event)
427
+{
428
+ NPCM7xxMFTState *s = NPCM7XX_MFT(opaque);
429
+ uint64_t prescaled_clock_period;
430
+
431
+ prescaled_clock_period = clock_get(s->clock_in) *
432
+ (s->regs[R_NPCM7XX_MFT_PRSC] + 1ULL);
433
+ trace_npcm7xx_mft_update_clock(s->clock_in->canonical_path,
434
+ s->regs[R_NPCM7XX_MFT_CKC],
435
+ clock_get(s->clock_in),
436
+ prescaled_clock_period);
437
+ /* Update clock 1 */
438
+ if (s->regs[R_NPCM7XX_MFT_CKC] & NPCM7XX_MFT_CKC_C1CSEL) {
439
+ /* Clock is prescaled. */
440
+ clock_update(s->clock_1, prescaled_clock_period);
441
+ } else {
442
+ /* Clock stopped. */
443
+ clock_update(s->clock_1, 0);
444
+ }
445
+ /* Update clock 2 */
446
+ if (s->regs[R_NPCM7XX_MFT_CKC] & NPCM7XX_MFT_CKC_C2CSEL) {
447
+ /* Clock is prescaled. */
448
+ clock_update(s->clock_2, prescaled_clock_period);
449
+ } else {
450
+ /* Clock stopped. */
451
+ clock_update(s->clock_2, 0);
452
+ }
453
+
454
+ npcm7xx_mft_capture(s);
455
+}
456
+
457
+static uint64_t npcm7xx_mft_read(void *opaque, hwaddr offset, unsigned size)
458
+{
459
+ NPCM7xxMFTState *s = NPCM7XX_MFT(opaque);
460
+ uint16_t value = 0;
461
+
462
+ switch (offset) {
474
+ switch (offset) {
463
+ case A_NPCM7XX_MFT_ICLR:
475
+ case A_NPCM7XX_PWM_CNR0:
476
+ return 0;
477
+ case A_NPCM7XX_PWM_CNR1:
478
+ return 1;
479
+ case A_NPCM7XX_PWM_CNR2:
480
+ return 2;
481
+ case A_NPCM7XX_PWM_CNR3:
482
+ return 3;
483
+ default:
484
+ g_assert_not_reached();
485
+ }
486
+}
487
+
488
+static hwaddr npcm7xx_cmr_index(hwaddr offset)
489
+{
490
+ switch (offset) {
491
+ case A_NPCM7XX_PWM_CMR0:
492
+ return 0;
493
+ case A_NPCM7XX_PWM_CMR1:
494
+ return 1;
495
+ case A_NPCM7XX_PWM_CMR2:
496
+ return 2;
497
+ case A_NPCM7XX_PWM_CMR3:
498
+ return 3;
499
+ default:
500
+ g_assert_not_reached();
501
+ }
502
+}
503
+
504
+static hwaddr npcm7xx_pdr_index(hwaddr offset)
505
+{
506
+ switch (offset) {
507
+ case A_NPCM7XX_PWM_PDR0:
508
+ return 0;
509
+ case A_NPCM7XX_PWM_PDR1:
510
+ return 1;
511
+ case A_NPCM7XX_PWM_PDR2:
512
+ return 2;
513
+ case A_NPCM7XX_PWM_PDR3:
514
+ return 3;
515
+ default:
516
+ g_assert_not_reached();
517
+ }
518
+}
519
+
520
+static hwaddr npcm7xx_pwdr_index(hwaddr offset)
521
+{
522
+ switch (offset) {
523
+ case A_NPCM7XX_PWM_PWDR0:
524
+ return 0;
525
+ case A_NPCM7XX_PWM_PWDR1:
526
+ return 1;
527
+ case A_NPCM7XX_PWM_PWDR2:
528
+ return 2;
529
+ case A_NPCM7XX_PWM_PWDR3:
530
+ return 3;
531
+ default:
532
+ g_assert_not_reached();
533
+ }
534
+}
535
+
536
+static uint64_t npcm7xx_pwm_read(void *opaque, hwaddr offset, unsigned size)
537
+{
538
+ NPCM7xxPWMState *s = opaque;
539
+ uint64_t value = 0;
540
+
541
+ switch (offset) {
542
+ case A_NPCM7XX_PWM_CNR0:
543
+ case A_NPCM7XX_PWM_CNR1:
544
+ case A_NPCM7XX_PWM_CNR2:
545
+ case A_NPCM7XX_PWM_CNR3:
546
+ value = s->pwm[npcm7xx_cnr_index(offset)].cnr;
547
+ break;
548
+
549
+ case A_NPCM7XX_PWM_CMR0:
550
+ case A_NPCM7XX_PWM_CMR1:
551
+ case A_NPCM7XX_PWM_CMR2:
552
+ case A_NPCM7XX_PWM_CMR3:
553
+ value = s->pwm[npcm7xx_cmr_index(offset)].cmr;
554
+ break;
555
+
556
+ case A_NPCM7XX_PWM_PDR0:
557
+ case A_NPCM7XX_PWM_PDR1:
558
+ case A_NPCM7XX_PWM_PDR2:
559
+ case A_NPCM7XX_PWM_PDR3:
560
+ value = s->pwm[npcm7xx_pdr_index(offset)].pdr;
561
+ break;
562
+
563
+ case A_NPCM7XX_PWM_PWDR0:
564
+ case A_NPCM7XX_PWM_PWDR1:
565
+ case A_NPCM7XX_PWM_PWDR2:
566
+ case A_NPCM7XX_PWM_PWDR3:
567
+ value = s->pwm[npcm7xx_pwdr_index(offset)].pwdr;
568
+ break;
569
+
570
+ case A_NPCM7XX_PWM_PPR:
571
+ value = s->ppr;
572
+ break;
573
+
574
+ case A_NPCM7XX_PWM_CSR:
575
+ value = s->csr;
576
+ break;
577
+
578
+ case A_NPCM7XX_PWM_PCR:
579
+ value = s->pcr;
580
+ break;
581
+
582
+ case A_NPCM7XX_PWM_PIER:
583
+ value = s->pier;
584
+ break;
585
+
586
+ case A_NPCM7XX_PWM_PIIR:
587
+ value = s->piir;
588
+ break;
589
+
590
+ default:
464
+ qemu_log_mask(LOG_GUEST_ERROR,
591
+ qemu_log_mask(LOG_GUEST_ERROR,
465
+ "%s: register @ 0x%04" HWADDR_PRIx " is write-only\n",
592
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
466
+ __func__, offset);
593
+ __func__, offset);
467
+ break;
594
+ break;
595
+ }
596
+
597
+ trace_npcm7xx_pwm_read(DEVICE(s)->canonical_path, offset, value);
598
+ return value;
599
+}
600
+
601
+static void npcm7xx_pwm_write(void *opaque, hwaddr offset,
602
+ uint64_t v, unsigned size)
603
+{
604
+ NPCM7xxPWMState *s = opaque;
605
+ NPCM7xxPWM *p;
606
+ uint32_t value = v;
607
+
608
+ trace_npcm7xx_pwm_write(DEVICE(s)->canonical_path, offset, value);
609
+ switch (offset) {
610
+ case A_NPCM7XX_PWM_CNR0:
611
+ case A_NPCM7XX_PWM_CNR1:
612
+ case A_NPCM7XX_PWM_CNR2:
613
+ case A_NPCM7XX_PWM_CNR3:
614
+ p = &s->pwm[npcm7xx_cnr_index(offset)];
615
+ p->cnr = value;
616
+ npcm7xx_pwm_update_output(p);
617
+ break;
618
+
619
+ case A_NPCM7XX_PWM_CMR0:
620
+ case A_NPCM7XX_PWM_CMR1:
621
+ case A_NPCM7XX_PWM_CMR2:
622
+ case A_NPCM7XX_PWM_CMR3:
623
+ p = &s->pwm[npcm7xx_cmr_index(offset)];
624
+ p->cmr = value;
625
+ npcm7xx_pwm_update_output(p);
626
+ break;
627
+
628
+ case A_NPCM7XX_PWM_PDR0:
629
+ case A_NPCM7XX_PWM_PDR1:
630
+ case A_NPCM7XX_PWM_PDR2:
631
+ case A_NPCM7XX_PWM_PDR3:
632
+ qemu_log_mask(LOG_GUEST_ERROR,
633
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
634
+ __func__, offset);
635
+ break;
636
+
637
+ case A_NPCM7XX_PWM_PWDR0:
638
+ case A_NPCM7XX_PWM_PWDR1:
639
+ case A_NPCM7XX_PWM_PWDR2:
640
+ case A_NPCM7XX_PWM_PWDR3:
641
+ qemu_log_mask(LOG_UNIMP,
642
+ "%s: register @ 0x%04" HWADDR_PRIx " is not implemented\n",
643
+ __func__, offset);
644
+ break;
645
+
646
+ case A_NPCM7XX_PWM_PPR:
647
+ npcm7xx_pwm_write_ppr(s, value);
648
+ break;
649
+
650
+ case A_NPCM7XX_PWM_CSR:
651
+ npcm7xx_pwm_write_csr(s, value);
652
+ break;
653
+
654
+ case A_NPCM7XX_PWM_PCR:
655
+ npcm7xx_pwm_write_pcr(s, value);
656
+ break;
657
+
658
+ case A_NPCM7XX_PWM_PIER:
659
+ qemu_log_mask(LOG_UNIMP,
660
+ "%s: register @ 0x%04" HWADDR_PRIx " is not implemented\n",
661
+ __func__, offset);
662
+ break;
663
+
664
+ case A_NPCM7XX_PWM_PIIR:
665
+ qemu_log_mask(LOG_UNIMP,
666
+ "%s: register @ 0x%04" HWADDR_PRIx " is not implemented\n",
667
+ __func__, offset);
668
+ break;
468
+
669
+
469
+ default:
670
+ default:
470
+ value = s->regs[offset / 2];
671
+ qemu_log_mask(LOG_GUEST_ERROR,
471
+ }
672
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
472
+
673
+ __func__, offset);
473
+ trace_npcm7xx_mft_read(DEVICE(s)->canonical_path, offset, value);
674
+ break;
474
+ return value;
675
+ }
475
+}
676
+}
476
+
677
+
477
+static void npcm7xx_mft_write(void *opaque, hwaddr offset,
678
+static const struct MemoryRegionOps npcm7xx_pwm_ops = {
478
+ uint64_t v, unsigned size)
679
+ .read = npcm7xx_pwm_read,
479
+{
680
+ .write = npcm7xx_pwm_write,
480
+ NPCM7xxMFTState *s = NPCM7XX_MFT(opaque);
481
+
482
+ trace_npcm7xx_mft_write(DEVICE(s)->canonical_path, offset, v);
483
+ switch (offset) {
484
+ case A_NPCM7XX_MFT_ICLR:
485
+ npcm7xx_mft_clear_interrupt(s, v);
486
+ break;
487
+
488
+ case A_NPCM7XX_MFT_CKC:
489
+ case A_NPCM7XX_MFT_PRSC:
490
+ s->regs[offset / 2] = v;
491
+ npcm7xx_mft_update_clock(s, ClockUpdate);
492
+ break;
493
+
494
+ default:
495
+ s->regs[offset / 2] = v;
496
+ npcm7xx_mft_capture(s);
497
+ break;
498
+ }
499
+}
500
+
501
+static bool npcm7xx_mft_check_mem_op(void *opaque, hwaddr offset,
502
+ unsigned size, bool is_write,
503
+ MemTxAttrs attrs)
504
+{
505
+ switch (offset) {
506
+ /* 16-bit registers. Must be accessed with 16-bit read/write.*/
507
+ case A_NPCM7XX_MFT_CNT1:
508
+ case A_NPCM7XX_MFT_CRA:
509
+ case A_NPCM7XX_MFT_CRB:
510
+ case A_NPCM7XX_MFT_CNT2:
511
+ case A_NPCM7XX_MFT_CPA:
512
+ case A_NPCM7XX_MFT_CPB:
513
+ return size == 2;
514
+
515
+ /* 8-bit registers. Must be accessed with 8-bit read/write.*/
516
+ case A_NPCM7XX_MFT_PRSC:
517
+ case A_NPCM7XX_MFT_CKC:
518
+ case A_NPCM7XX_MFT_MCTRL:
519
+ case A_NPCM7XX_MFT_ICTRL:
520
+ case A_NPCM7XX_MFT_ICLR:
521
+ case A_NPCM7XX_MFT_IEN:
522
+ case A_NPCM7XX_MFT_CPCFG:
523
+ case A_NPCM7XX_MFT_INASEL:
524
+ case A_NPCM7XX_MFT_INBSEL:
525
+ return size == 1;
526
+
527
+ default:
528
+ /* Invalid registers. */
529
+ return false;
530
+ }
531
+}
532
+
533
+static void npcm7xx_mft_get_max_rpm(Object *obj, Visitor *v, const char *name,
534
+ void *opaque, Error **errp)
535
+{
536
+ visit_type_uint32(v, name, (uint32_t *)opaque, errp);
537
+}
538
+
539
+static void npcm7xx_mft_set_max_rpm(Object *obj, Visitor *v, const char *name,
540
+ void *opaque, Error **errp)
541
+{
542
+ NPCM7xxMFTState *s = NPCM7XX_MFT(obj);
543
+ uint32_t *max_rpm = opaque;
544
+ uint32_t value;
545
+
546
+ if (!visit_type_uint32(v, name, &value, errp)) {
547
+ return;
548
+ }
549
+
550
+ *max_rpm = value;
551
+ npcm7xx_mft_capture(s);
552
+}
553
+
554
+static void npcm7xx_mft_duty_handler(void *opaque, int n, int value)
555
+{
556
+ NPCM7xxMFTState *s = NPCM7XX_MFT(opaque);
557
+
558
+ trace_npcm7xx_mft_set_duty(DEVICE(s)->canonical_path, n, value);
559
+ s->duty[n] = value;
560
+ npcm7xx_mft_capture(s);
561
+}
562
+
563
+static const struct MemoryRegionOps npcm7xx_mft_ops = {
564
+ .read = npcm7xx_mft_read,
565
+ .write = npcm7xx_mft_write,
566
+ .endianness = DEVICE_LITTLE_ENDIAN,
681
+ .endianness = DEVICE_LITTLE_ENDIAN,
567
+ .valid = {
682
+ .valid = {
568
+ .min_access_size = 1,
683
+ .min_access_size = 4,
569
+ .max_access_size = 2,
684
+ .max_access_size = 4,
570
+ .unaligned = false,
685
+ .unaligned = false,
571
+ .accepts = npcm7xx_mft_check_mem_op,
572
+ },
686
+ },
573
+};
687
+};
574
+
688
+
575
+static void npcm7xx_mft_enter_reset(Object *obj, ResetType type)
689
+static void npcm7xx_pwm_enter_reset(Object *obj, ResetType type)
576
+{
690
+{
577
+ NPCM7xxMFTState *s = NPCM7XX_MFT(obj);
691
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
578
+
692
+ int i;
579
+ npcm7xx_mft_reset(s);
693
+
580
+}
694
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
581
+
695
+ NPCM7xxPWM *p = &s->pwm[i];
582
+static void npcm7xx_mft_hold_reset(Object *obj)
696
+
583
+{
697
+ p->cnr = 0x00000000;
584
+ NPCM7xxMFTState *s = NPCM7XX_MFT(obj);
698
+ p->cmr = 0x00000000;
585
+
699
+ p->pdr = 0x00000000;
586
+ qemu_irq_lower(s->irq);
700
+ p->pwdr = 0x00000000;
587
+}
701
+ }
588
+
702
+
589
+static void npcm7xx_mft_init(Object *obj)
703
+ s->ppr = 0x00000000;
590
+{
704
+ s->csr = 0x00000000;
591
+ NPCM7xxMFTState *s = NPCM7XX_MFT(obj);
705
+ s->pcr = 0x00000000;
706
+ s->pier = 0x00000000;
707
+ s->piir = 0x00000000;
708
+}
709
+
710
+static void npcm7xx_pwm_hold_reset(Object *obj)
711
+{
712
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
713
+ int i;
714
+
715
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
716
+ qemu_irq_lower(s->pwm[i].irq);
717
+ }
718
+}
719
+
720
+static void npcm7xx_pwm_init(Object *obj)
721
+{
722
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
592
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
723
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
593
+ DeviceState *dev = DEVICE(obj);
724
+ int i;
594
+
725
+
595
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_mft_ops, s,
726
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
596
+ TYPE_NPCM7XX_MFT, 4 * KiB);
727
+ NPCM7xxPWM *p = &s->pwm[i];
728
+ p->module = s;
729
+ p->index = i;
730
+ sysbus_init_irq(sbd, &p->irq);
731
+ }
732
+
733
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_pwm_ops, s,
734
+ TYPE_NPCM7XX_PWM, 4 * KiB);
597
+ sysbus_init_mmio(sbd, &s->iomem);
735
+ sysbus_init_mmio(sbd, &s->iomem);
598
+ sysbus_init_irq(sbd, &s->irq);
736
+ s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL);
599
+ s->clock_in = qdev_init_clock_in(dev, "clock-in", npcm7xx_mft_update_clock,
737
+
600
+ s, ClockUpdate);
738
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
601
+ s->clock_1 = qdev_init_clock_out(dev, "clock1");
739
+ object_property_add_uint32_ptr(obj, "freq[*]",
602
+ s->clock_2 = qdev_init_clock_out(dev, "clock2");
740
+ &s->pwm[i].freq, OBJ_PROP_FLAG_READ);
603
+
741
+ object_property_add_uint32_ptr(obj, "duty[*]",
604
+ for (int i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
742
+ &s->pwm[i].duty, OBJ_PROP_FLAG_READ);
605
+ object_property_add(obj, "max_rpm[*]", "uint32",
743
+ }
606
+ npcm7xx_mft_get_max_rpm,
744
+}
607
+ npcm7xx_mft_set_max_rpm,
745
+
608
+ NULL, &s->max_rpm[i]);
746
+static const VMStateDescription vmstate_npcm7xx_pwm = {
609
+ }
747
+ .name = "npcm7xx-pwm",
610
+ qdev_init_gpio_in_named(dev, npcm7xx_mft_duty_handler, "duty",
611
+ NPCM7XX_MFT_FANIN_COUNT);
612
+}
613
+
614
+static const VMStateDescription vmstate_npcm7xx_mft = {
615
+ .name = "npcm7xx-mft-module",
616
+ .version_id = 0,
748
+ .version_id = 0,
617
+ .minimum_version_id = 0,
749
+ .minimum_version_id = 0,
618
+ .fields = (VMStateField[]) {
750
+ .fields = (VMStateField[]) {
619
+ VMSTATE_CLOCK(clock_in, NPCM7xxMFTState),
751
+ VMSTATE_BOOL(running, NPCM7xxPWM),
620
+ VMSTATE_CLOCK(clock_1, NPCM7xxMFTState),
752
+ VMSTATE_BOOL(inverted, NPCM7xxPWM),
621
+ VMSTATE_CLOCK(clock_2, NPCM7xxMFTState),
753
+ VMSTATE_UINT8(index, NPCM7xxPWM),
622
+ VMSTATE_UINT16_ARRAY(regs, NPCM7xxMFTState, NPCM7XX_MFT_NR_REGS),
754
+ VMSTATE_UINT32(cnr, NPCM7xxPWM),
623
+ VMSTATE_UINT32_ARRAY(max_rpm, NPCM7xxMFTState, NPCM7XX_MFT_FANIN_COUNT),
755
+ VMSTATE_UINT32(cmr, NPCM7xxPWM),
624
+ VMSTATE_UINT32_ARRAY(duty, NPCM7xxMFTState, NPCM7XX_MFT_FANIN_COUNT),
756
+ VMSTATE_UINT32(pdr, NPCM7xxPWM),
757
+ VMSTATE_UINT32(pwdr, NPCM7xxPWM),
758
+ VMSTATE_UINT32(freq, NPCM7xxPWM),
759
+ VMSTATE_UINT32(duty, NPCM7xxPWM),
625
+ VMSTATE_END_OF_LIST(),
760
+ VMSTATE_END_OF_LIST(),
626
+ },
761
+ },
627
+};
762
+};
628
+
763
+
629
+static void npcm7xx_mft_class_init(ObjectClass *klass, void *data)
764
+static const VMStateDescription vmstate_npcm7xx_pwm_module = {
765
+ .name = "npcm7xx-pwm-module",
766
+ .version_id = 0,
767
+ .minimum_version_id = 0,
768
+ .fields = (VMStateField[]) {
769
+ VMSTATE_CLOCK(clock, NPCM7xxPWMState),
770
+ VMSTATE_STRUCT_ARRAY(pwm, NPCM7xxPWMState,
771
+ NPCM7XX_PWM_PER_MODULE, 0, vmstate_npcm7xx_pwm,
772
+ NPCM7xxPWM),
773
+ VMSTATE_UINT32(ppr, NPCM7xxPWMState),
774
+ VMSTATE_UINT32(csr, NPCM7xxPWMState),
775
+ VMSTATE_UINT32(pcr, NPCM7xxPWMState),
776
+ VMSTATE_UINT32(pier, NPCM7xxPWMState),
777
+ VMSTATE_UINT32(piir, NPCM7xxPWMState),
778
+ VMSTATE_END_OF_LIST(),
779
+ },
780
+};
781
+
782
+static void npcm7xx_pwm_class_init(ObjectClass *klass, void *data)
630
+{
783
+{
631
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
784
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
632
+ DeviceClass *dc = DEVICE_CLASS(klass);
785
+ DeviceClass *dc = DEVICE_CLASS(klass);
633
+
786
+
634
+ dc->desc = "NPCM7xx MFT Controller";
787
+ dc->desc = "NPCM7xx PWM Controller";
635
+ dc->vmsd = &vmstate_npcm7xx_mft;
788
+ dc->vmsd = &vmstate_npcm7xx_pwm_module;
636
+ rc->phases.enter = npcm7xx_mft_enter_reset;
789
+ rc->phases.enter = npcm7xx_pwm_enter_reset;
637
+ rc->phases.hold = npcm7xx_mft_hold_reset;
790
+ rc->phases.hold = npcm7xx_pwm_hold_reset;
638
+}
791
+}
639
+
792
+
640
+static const TypeInfo npcm7xx_mft_info = {
793
+static const TypeInfo npcm7xx_pwm_info = {
641
+ .name = TYPE_NPCM7XX_MFT,
794
+ .name = TYPE_NPCM7XX_PWM,
642
+ .parent = TYPE_SYS_BUS_DEVICE,
795
+ .parent = TYPE_SYS_BUS_DEVICE,
643
+ .instance_size = sizeof(NPCM7xxMFTState),
796
+ .instance_size = sizeof(NPCM7xxPWMState),
644
+ .class_init = npcm7xx_mft_class_init,
797
+ .class_init = npcm7xx_pwm_class_init,
645
+ .instance_init = npcm7xx_mft_init,
798
+ .instance_init = npcm7xx_pwm_init,
646
+};
799
+};
647
+
800
+
648
+static void npcm7xx_mft_register_type(void)
801
+static void npcm7xx_pwm_register_type(void)
649
+{
802
+{
650
+ type_register_static(&npcm7xx_mft_info);
803
+ type_register_static(&npcm7xx_pwm_info);
651
+}
804
+}
652
+type_init(npcm7xx_mft_register_type);
805
+type_init(npcm7xx_pwm_register_type);
653
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
806
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
654
index XXXXXXX..XXXXXXX 100644
807
index XXXXXXX..XXXXXXX 100644
655
--- a/hw/misc/meson.build
808
--- a/hw/misc/meson.build
656
+++ b/hw/misc/meson.build
809
+++ b/hw/misc/meson.build
657
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
810
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
658
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
811
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
659
'npcm7xx_clk.c',
812
'npcm7xx_clk.c',
660
'npcm7xx_gcr.c',
813
'npcm7xx_gcr.c',
661
+ 'npcm7xx_mft.c',
814
+ 'npcm7xx_pwm.c',
662
'npcm7xx_pwm.c',
663
'npcm7xx_rng.c',
815
'npcm7xx_rng.c',
664
))
816
))
817
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files(
665
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
818
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
666
index XXXXXXX..XXXXXXX 100644
819
index XXXXXXX..XXXXXXX 100644
667
--- a/hw/misc/trace-events
820
--- a/hw/misc/trace-events
668
+++ b/hw/misc/trace-events
821
+++ b/hw/misc/trace-events
669
@@ -XXX,XX +XXX,XX @@ npcm7xx_clk_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " valu
822
@@ -XXX,XX +XXX,XX @@ npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " valu
670
npcm7xx_gcr_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
671
npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
672
673
+# npcm7xx_mft.c
674
+npcm7xx_mft_read(const char *name, uint64_t offset, uint16_t value) "%s: offset: 0x%04" PRIx64 " value: 0x%04" PRIx16
675
+npcm7xx_mft_write(const char *name, uint64_t offset, uint16_t value) "%s: offset: 0x%04" PRIx64 " value: 0x%04" PRIx16
676
+npcm7xx_mft_rpm(const char *clock, uint32_t clock_hz, int state, int32_t cnt, uint32_t rpm, uint32_t duty) " fan clk: %s clock_hz: %" PRIu32 ", state: %d, cnt: %" PRIi32 ", rpm: %" PRIu32 ", duty: %" PRIu32
677
+npcm7xx_mft_capture(const char *name, int irq_level) "%s: level: %d"
678
+npcm7xx_mft_update_clock(const char *name, uint16_t sel, uint64_t clock_period, uint64_t prescaled_clock_period) "%s: sel: 0x%02" PRIx16 ", period: %" PRIu64 ", prescaled: %" PRIu64
679
+npcm7xx_mft_set_duty(const char *name, int n, int value) "%s[%d]: %d"
680
+
681
# npcm7xx_rng.c
682
npcm7xx_rng_read(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
823
npcm7xx_rng_read(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
683
npcm7xx_rng_write(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
824
npcm7xx_rng_write(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
825
826
+# npcm7xx_pwm.c
827
+npcm7xx_pwm_read(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
828
+npcm7xx_pwm_write(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
829
+npcm7xx_pwm_update_freq(const char *id, uint8_t index, uint32_t old_value, uint32_t new_value) "%s pwm[%u] Update Freq: old_freq: %u, new_freq: %u"
830
+npcm7xx_pwm_update_duty(const char *id, uint8_t index, uint32_t old_value, uint32_t new_value) "%s pwm[%u] Update Duty: old_duty: %u, new_duty: %u"
831
+
832
# stm32f4xx_syscfg.c
833
stm32f4xx_syscfg_set_irq(int gpio, int line, int level) "Interupt: GPIO: %d, Line: %d; Level: %d"
834
stm32f4xx_pulse_exti(int irq) "Pulse EXTI: %d"
684
--
835
--
685
2.20.1
836
2.20.1
686
837
687
838
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
This patch adds testing of PWM fan RPMs in the existing npcm7xx pwm
3
We add a qtest for the PWM in the previous patch. It proves it works as
4
test. It tests whether the MFT module can measure correct fan values
4
expected.
5
for a PWM fan in NPCM7XX boards.
6
5
7
Reviewed-by: Doug Evans <dje@google.com>
6
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
8
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
9
Signed-off-by: Hao Wu <wuhaotsh@google.com>
8
Signed-off-by: Hao Wu <wuhaotsh@google.com>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20210311180855.149764-6-wuhaotsh@google.com
10
Message-id: 20210108190945.949196-6-wuhaotsh@google.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
12
---
14
tests/qtest/npcm7xx_pwm-test.c | 205 ++++++++++++++++++++++++++++++++-
13
tests/qtest/npcm7xx_pwm-test.c | 490 +++++++++++++++++++++++++++++++++
15
1 file changed, 199 insertions(+), 6 deletions(-)
14
tests/qtest/meson.build | 1 +
15
2 files changed, 491 insertions(+)
16
create mode 100644 tests/qtest/npcm7xx_pwm-test.c
16
17
17
diff --git a/tests/qtest/npcm7xx_pwm-test.c b/tests/qtest/npcm7xx_pwm-test.c
18
diff --git a/tests/qtest/npcm7xx_pwm-test.c b/tests/qtest/npcm7xx_pwm-test.c
18
index XXXXXXX..XXXXXXX 100644
19
new file mode 100644
19
--- a/tests/qtest/npcm7xx_pwm-test.c
20
index XXXXXXX..XXXXXXX
21
--- /dev/null
20
+++ b/tests/qtest/npcm7xx_pwm-test.c
22
+++ b/tests/qtest/npcm7xx_pwm-test.c
21
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
22
#define PLL_FBDV(rv) extract32((rv), 16, 12)
24
+/*
23
#define PLL_OTDV1(rv) extract32((rv), 8, 3)
25
+ * QTests for Nuvoton NPCM7xx PWM Modules.
24
#define PLL_OTDV2(rv) extract32((rv), 13, 3)
26
+ *
25
+#define APB4CKDIV(rv) extract32((rv), 30, 2)
27
+ * Copyright 2020 Google LLC
26
#define APB3CKDIV(rv) extract32((rv), 28, 2)
28
+ *
27
#define CLK2CKDIV(rv) extract32((rv), 0, 1)
29
+ * This program is free software; you can redistribute it and/or modify it
28
#define CLK4CKDIV(rv) extract32((rv), 26, 2)
30
+ * under the terms of the GNU General Public License as published by the
29
@@ -XXX,XX +XXX,XX @@
31
+ * Free Software Foundation; either version 2 of the License, or
30
32
+ * (at your option) any later version.
31
#define MAX_DUTY 1000000
33
+ *
32
34
+ * This program is distributed in the hope that it will be useful, but WITHOUT
33
+/* MFT (PWM fan) related */
35
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
34
+#define MFT_BA(n) (0xf0180000 + ((n) * 0x1000))
36
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
35
+#define MFT_IRQ(n) (96 + (n))
37
+ * for more details.
36
+#define MFT_CNT1 0x00
38
+ */
37
+#define MFT_CRA 0x02
39
+
38
+#define MFT_CRB 0x04
40
+#include "qemu/osdep.h"
39
+#define MFT_CNT2 0x06
41
+#include "qemu/bitops.h"
40
+#define MFT_PRSC 0x08
42
+#include "libqos/libqtest.h"
41
+#define MFT_CKC 0x0a
43
+#include "qapi/qmp/qdict.h"
42
+#define MFT_MCTRL 0x0c
44
+#include "qapi/qmp/qnum.h"
43
+#define MFT_ICTRL 0x0e
45
+
44
+#define MFT_ICLR 0x10
46
+#define REF_HZ 25000000
45
+#define MFT_IEN 0x12
47
+
46
+#define MFT_CPA 0x14
48
+/* Register field definitions. */
47
+#define MFT_CPB 0x16
49
+#define CH_EN BIT(0)
48
+#define MFT_CPCFG 0x18
50
+#define CH_INV BIT(2)
49
+#define MFT_INASEL 0x1a
51
+#define CH_MOD BIT(3)
50
+#define MFT_INBSEL 0x1c
52
+
51
+
53
+/* Registers shared between all PWMs in a module */
52
+#define MFT_MCTRL_ALL 0x64
54
+#define PPR 0x00
53
+#define MFT_ICLR_ALL 0x3f
55
+#define CSR 0x04
54
+#define MFT_IEN_ALL 0x3f
56
+#define PCR 0x08
55
+#define MFT_CPCFG_EQ_MODE 0x44
57
+#define PIER 0x3c
56
+
58
+#define PIIR 0x40
57
+#define MFT_CKC_C2CSEL BIT(3)
59
+
58
+#define MFT_CKC_C1CSEL BIT(0)
60
+/* CLK module related */
59
+
61
+#define CLK_BA 0xf0801000
60
+#define MFT_ICTRL_TFPND BIT(5)
62
+#define CLKSEL 0x04
61
+#define MFT_ICTRL_TEPND BIT(4)
63
+#define CLKDIV1 0x08
62
+#define MFT_ICTRL_TDPND BIT(3)
64
+#define CLKDIV2 0x2c
63
+#define MFT_ICTRL_TCPND BIT(2)
65
+#define PLLCON0 0x0c
64
+#define MFT_ICTRL_TBPND BIT(1)
66
+#define PLLCON1 0x10
65
+#define MFT_ICTRL_TAPND BIT(0)
67
+#define PLL_INDV(rv) extract32((rv), 0, 6)
66
+
68
+#define PLL_FBDV(rv) extract32((rv), 16, 12)
67
+#define MFT_MAX_CNT 0xffff
69
+#define PLL_OTDV1(rv) extract32((rv), 8, 3)
68
+#define MFT_TIMEOUT 0x5000
70
+#define PLL_OTDV2(rv) extract32((rv), 13, 3)
69
+
71
+#define APB3CKDIV(rv) extract32((rv), 28, 2)
70
+#define DEFAULT_RPM 19800
72
+#define CLK2CKDIV(rv) extract32((rv), 0, 1)
71
+#define DEFAULT_PRSC 255
73
+#define CLK4CKDIV(rv) extract32((rv), 26, 2)
72
+#define MFT_PULSE_PER_REVOLUTION 2
74
+#define CPUCKSEL(rv) extract32((rv), 0, 2)
73
+
75
+
74
+#define MAX_ERROR 1
76
+#define MAX_DUTY 1000000
75
+
77
+
76
typedef struct PWMModule {
78
+typedef struct PWMModule {
77
int irq;
79
+ int irq;
78
uint64_t base_addr;
80
+ uint64_t base_addr;
79
@@ -XXX,XX +XXX,XX @@ static uint64_t pwm_get_duty(QTestState *qts, int module_index, int pwm_index)
81
+} PWMModule;
80
return pwm_qom_get(qts, path, name);
82
+
81
}
83
+typedef struct PWM {
82
84
+ uint32_t cnr_offset;
83
+static void mft_qom_set(QTestState *qts, int index, const char *name,
85
+ uint32_t cmr_offset;
84
+ uint32_t value)
86
+ uint32_t pdr_offset;
87
+ uint32_t pwdr_offset;
88
+} PWM;
89
+
90
+typedef struct TestData {
91
+ const PWMModule *module;
92
+ const PWM *pwm;
93
+} TestData;
94
+
95
+static const PWMModule pwm_module_list[] = {
96
+ {
97
+ .irq = 93,
98
+ .base_addr = 0xf0103000
99
+ },
100
+ {
101
+ .irq = 94,
102
+ .base_addr = 0xf0104000
103
+ }
104
+};
105
+
106
+static const PWM pwm_list[] = {
107
+ {
108
+ .cnr_offset = 0x0c,
109
+ .cmr_offset = 0x10,
110
+ .pdr_offset = 0x14,
111
+ .pwdr_offset = 0x44,
112
+ },
113
+ {
114
+ .cnr_offset = 0x18,
115
+ .cmr_offset = 0x1c,
116
+ .pdr_offset = 0x20,
117
+ .pwdr_offset = 0x48,
118
+ },
119
+ {
120
+ .cnr_offset = 0x24,
121
+ .cmr_offset = 0x28,
122
+ .pdr_offset = 0x2c,
123
+ .pwdr_offset = 0x4c,
124
+ },
125
+ {
126
+ .cnr_offset = 0x30,
127
+ .cmr_offset = 0x34,
128
+ .pdr_offset = 0x38,
129
+ .pwdr_offset = 0x50,
130
+ },
131
+};
132
+
133
+static const int ppr_base[] = { 0, 0, 8, 8 };
134
+static const int csr_base[] = { 0, 4, 8, 12 };
135
+static const int pcr_base[] = { 0, 8, 12, 16 };
136
+
137
+static const uint32_t ppr_list[] = {
138
+ 0,
139
+ 1,
140
+ 10,
141
+ 100,
142
+ 255, /* Max possible value. */
143
+};
144
+
145
+static const uint32_t csr_list[] = {
146
+ 0,
147
+ 1,
148
+ 2,
149
+ 3,
150
+ 4, /* Max possible value. */
151
+};
152
+
153
+static const uint32_t cnr_list[] = {
154
+ 0,
155
+ 1,
156
+ 50,
157
+ 100,
158
+ 150,
159
+ 200,
160
+ 1000,
161
+ 10000,
162
+ 65535, /* Max possible value. */
163
+};
164
+
165
+static const uint32_t cmr_list[] = {
166
+ 0,
167
+ 1,
168
+ 10,
169
+ 50,
170
+ 100,
171
+ 150,
172
+ 200,
173
+ 1000,
174
+ 10000,
175
+ 65535, /* Max possible value. */
176
+};
177
+
178
+/* Returns the index of the PWM module. */
179
+static int pwm_module_index(const PWMModule *module)
180
+{
181
+ ptrdiff_t diff = module - pwm_module_list;
182
+
183
+ g_assert_true(diff >= 0 && diff < ARRAY_SIZE(pwm_module_list));
184
+
185
+ return diff;
186
+}
187
+
188
+/* Returns the index of the PWM entry. */
189
+static int pwm_index(const PWM *pwm)
190
+{
191
+ ptrdiff_t diff = pwm - pwm_list;
192
+
193
+ g_assert_true(diff >= 0 && diff < ARRAY_SIZE(pwm_list));
194
+
195
+ return diff;
196
+}
197
+
198
+static uint64_t pwm_qom_get(QTestState *qts, const char *path, const char *name)
85
+{
199
+{
86
+ QDict *response;
200
+ QDict *response;
87
+ char *path = g_strdup_printf("/machine/soc/mft[%d]", index);
201
+
88
+
202
+ g_test_message("Getting properties %s from %s", name, path);
89
+ g_test_message("Setting properties %s of mft[%d] with value %u",
203
+ response = qtest_qmp(qts, "{ 'execute': 'qom-get',"
90
+ name, index, value);
204
+ " 'arguments': { 'path': %s, 'property': %s}}",
91
+ response = qtest_qmp(qts, "{ 'execute': 'qom-set',"
205
+ path, name);
92
+ " 'arguments': { 'path': %s, "
93
+ " 'property': %s, 'value': %u}}",
94
+ path, name, value);
95
+ /* The qom set message returns successfully. */
206
+ /* The qom set message returns successfully. */
96
+ g_assert_true(qdict_haskey(response, "return"));
207
+ g_assert_true(qdict_haskey(response, "return"));
97
+}
208
+ return qnum_get_uint(qobject_to(QNum, qdict_get(response, "return")));
98
+
209
+}
99
static uint32_t get_pll(uint32_t con)
210
+
100
{
211
+static uint64_t pwm_get_freq(QTestState *qts, int module_index, int pwm_index)
101
return REF_HZ * PLL_FBDV(con) / (PLL_INDV(con) * PLL_OTDV1(con)
212
+{
102
* PLL_OTDV2(con));
213
+ char path[100];
103
}
214
+ char name[100];
104
215
+
105
-static uint64_t read_pclk(QTestState *qts)
216
+ sprintf(path, "/machine/soc/pwm[%d]", module_index);
106
+static uint64_t read_pclk(QTestState *qts, bool mft)
217
+ sprintf(name, "freq[%d]", pwm_index);
107
{
218
+
108
uint64_t freq = REF_HZ;
219
+ return pwm_qom_get(qts, path, name);
109
uint32_t clksel = qtest_readl(qts, CLK_BA + CLKSEL);
220
+}
110
uint32_t pllcon;
221
+
111
uint32_t clkdiv1 = qtest_readl(qts, CLK_BA + CLKDIV1);
222
+static uint64_t pwm_get_duty(QTestState *qts, int module_index, int pwm_index)
112
uint32_t clkdiv2 = qtest_readl(qts, CLK_BA + CLKDIV2);
223
+{
113
+ uint32_t apbdiv = mft ? APB4CKDIV(clkdiv2) : APB3CKDIV(clkdiv2);
224
+ char path[100];
114
225
+ char name[100];
115
switch (CPUCKSEL(clksel)) {
226
+
116
case 0:
227
+ sprintf(path, "/machine/soc/pwm[%d]", module_index);
117
@@ -XXX,XX +XXX,XX @@ static uint64_t read_pclk(QTestState *qts)
228
+ sprintf(name, "duty[%d]", pwm_index);
118
g_assert_not_reached();
229
+
119
}
230
+ return pwm_qom_get(qts, path, name);
120
231
+}
121
- freq >>= (CLK2CKDIV(clkdiv1) + CLK4CKDIV(clkdiv1) + APB3CKDIV(clkdiv2));
232
+
122
+ freq >>= (CLK2CKDIV(clkdiv1) + CLK4CKDIV(clkdiv1) + apbdiv);
233
+static uint32_t get_pll(uint32_t con)
123
234
+{
124
return freq;
235
+ return REF_HZ * PLL_FBDV(con) / (PLL_INDV(con) * PLL_OTDV1(con)
125
}
236
+ * PLL_OTDV2(con));
126
@@ -XXX,XX +XXX,XX @@ static uint32_t pwm_selector(uint32_t csr)
237
+}
127
static uint64_t pwm_compute_freq(QTestState *qts, uint32_t ppr, uint32_t csr,
238
+
128
uint32_t cnr)
239
+static uint64_t read_pclk(QTestState *qts)
129
{
240
+{
130
- return read_pclk(qts) / ((ppr + 1) * pwm_selector(csr) * (cnr + 1));
241
+ uint64_t freq = REF_HZ;
131
+ return read_pclk(qts, false) / ((ppr + 1) * pwm_selector(csr) * (cnr + 1));
242
+ uint32_t clksel = qtest_readl(qts, CLK_BA + CLKSEL);
132
}
243
+ uint32_t pllcon;
133
244
+ uint32_t clkdiv1 = qtest_readl(qts, CLK_BA + CLKDIV1);
134
static uint64_t pwm_compute_duty(uint32_t cnr, uint32_t cmr, bool inverted)
245
+ uint32_t clkdiv2 = qtest_readl(qts, CLK_BA + CLKDIV2);
135
@@ -XXX,XX +XXX,XX @@ static void pwm_write(QTestState *qts, const TestData *td, unsigned offset,
246
+
136
qtest_writel(qts, td->module->base_addr + offset, value);
247
+ switch (CPUCKSEL(clksel)) {
137
}
248
+ case 0:
138
249
+ pllcon = qtest_readl(qts, CLK_BA + PLLCON0);
139
+static uint8_t mft_readb(QTestState *qts, int index, unsigned offset)
250
+ freq = get_pll(pllcon);
140
+{
251
+ break;
141
+ return qtest_readb(qts, MFT_BA(index) + offset);
252
+ case 1:
142
+}
253
+ pllcon = qtest_readl(qts, CLK_BA + PLLCON1);
143
+
254
+ freq = get_pll(pllcon);
144
+static uint16_t mft_readw(QTestState *qts, int index, unsigned offset)
255
+ break;
145
+{
256
+ case 2:
146
+ return qtest_readw(qts, MFT_BA(index) + offset);
257
+ break;
147
+}
258
+ case 3:
148
+
259
+ break;
149
+static void mft_writeb(QTestState *qts, int index, unsigned offset,
260
+ default:
150
+ uint8_t value)
261
+ g_assert_not_reached();
151
+{
262
+ }
152
+ qtest_writeb(qts, MFT_BA(index) + offset, value);
263
+
153
+}
264
+ freq >>= (CLK2CKDIV(clkdiv1) + CLK4CKDIV(clkdiv1) + APB3CKDIV(clkdiv2));
154
+
265
+
155
+static void mft_writew(QTestState *qts, int index, unsigned offset,
266
+ return freq;
156
+ uint16_t value)
267
+}
157
+{
268
+
158
+ return qtest_writew(qts, MFT_BA(index) + offset, value);
269
+static uint32_t pwm_selector(uint32_t csr)
159
+}
270
+{
160
+
271
+ switch (csr) {
161
static uint32_t pwm_read_ppr(QTestState *qts, const TestData *td)
272
+ case 0:
162
{
273
+ return 2;
163
return extract32(pwm_read(qts, td, PPR), ppr_base[pwm_index(td->pwm)], 8);
274
+ case 1:
164
@@ -XXX,XX +XXX,XX @@ static void pwm_write_cmr(QTestState *qts, const TestData *td, uint32_t value)
275
+ return 4;
165
pwm_write(qts, td, td->pwm->cmr_offset, value);
276
+ case 2:
166
}
277
+ return 8;
167
278
+ case 3:
168
+static int mft_compute_index(const TestData *td)
279
+ return 16;
169
+{
280
+ case 4:
170
+ int index = pwm_module_index(td->module) * ARRAY_SIZE(pwm_list) +
281
+ return 1;
171
+ pwm_index(td->pwm);
282
+ default:
172
+
283
+ g_assert_not_reached();
173
+ g_assert_cmpint(index, <,
284
+ }
174
+ ARRAY_SIZE(pwm_module_list) * ARRAY_SIZE(pwm_list));
285
+}
175
+
286
+
176
+ return index;
287
+static uint64_t pwm_compute_freq(QTestState *qts, uint32_t ppr, uint32_t csr,
177
+}
288
+ uint32_t cnr)
178
+
289
+{
179
+static void mft_reset_counters(QTestState *qts, int index)
290
+ return read_pclk(qts) / ((ppr + 1) * pwm_selector(csr) * (cnr + 1));
180
+{
291
+}
181
+ mft_writew(qts, index, MFT_CNT1, MFT_MAX_CNT);
292
+
182
+ mft_writew(qts, index, MFT_CNT2, MFT_MAX_CNT);
293
+static uint64_t pwm_compute_duty(uint32_t cnr, uint32_t cmr, bool inverted)
183
+ mft_writew(qts, index, MFT_CRA, MFT_MAX_CNT);
294
+{
184
+ mft_writew(qts, index, MFT_CRB, MFT_MAX_CNT);
295
+ uint64_t duty;
185
+ mft_writew(qts, index, MFT_CPA, MFT_MAX_CNT - MFT_TIMEOUT);
296
+
186
+ mft_writew(qts, index, MFT_CPB, MFT_MAX_CNT - MFT_TIMEOUT);
297
+ if (cnr == 0) {
187
+}
298
+ /* PWM is stopped. */
188
+
299
+ duty = 0;
189
+static void mft_init(QTestState *qts, const TestData *td)
300
+ } else if (cmr >= cnr) {
190
+{
301
+ duty = MAX_DUTY;
191
+ int index = mft_compute_index(td);
192
+
193
+ /* Enable everything */
194
+ mft_writeb(qts, index, MFT_CKC, 0);
195
+ mft_writeb(qts, index, MFT_ICLR, MFT_ICLR_ALL);
196
+ mft_writeb(qts, index, MFT_MCTRL, MFT_MCTRL_ALL);
197
+ mft_writeb(qts, index, MFT_IEN, MFT_IEN_ALL);
198
+ mft_writeb(qts, index, MFT_INASEL, 0);
199
+ mft_writeb(qts, index, MFT_INBSEL, 0);
200
+
201
+ /* Set cpcfg to use EQ mode, same as kernel driver */
202
+ mft_writeb(qts, index, MFT_CPCFG, MFT_CPCFG_EQ_MODE);
203
+
204
+ /* Write default counters, timeout and prescaler */
205
+ mft_reset_counters(qts, index);
206
+ mft_writeb(qts, index, MFT_PRSC, DEFAULT_PRSC);
207
+
208
+ /* Write default max rpm via QMP */
209
+ mft_qom_set(qts, index, "max_rpm[0]", DEFAULT_RPM);
210
+ mft_qom_set(qts, index, "max_rpm[1]", DEFAULT_RPM);
211
+}
212
+
213
+static int32_t mft_compute_cnt(uint32_t rpm, uint64_t clk)
214
+{
215
+ uint64_t cnt;
216
+
217
+ if (rpm == 0) {
218
+ return -1;
219
+ }
220
+
221
+ cnt = clk * 60 / ((DEFAULT_PRSC + 1) * rpm * MFT_PULSE_PER_REVOLUTION);
222
+ if (cnt >= MFT_TIMEOUT) {
223
+ return -1;
224
+ }
225
+ return MFT_MAX_CNT - cnt;
226
+}
227
+
228
+static void mft_verify_rpm(QTestState *qts, const TestData *td, uint64_t duty)
229
+{
230
+ int index = mft_compute_index(td);
231
+ uint16_t cnt, cr;
232
+ uint32_t rpm = DEFAULT_RPM * duty / MAX_DUTY;
233
+ uint64_t clk = read_pclk(qts, true);
234
+ int32_t expected_cnt = mft_compute_cnt(rpm, clk);
235
+
236
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
237
+ g_test_message(
238
+ "verifying rpm for mft[%d]: clk: %lu, duty: %lu, rpm: %u, cnt: %d",
239
+ index, clk, duty, rpm, expected_cnt);
240
+
241
+ /* Verify rpm for fan A */
242
+ /* Stop capture */
243
+ mft_writeb(qts, index, MFT_CKC, 0);
244
+ mft_writeb(qts, index, MFT_ICLR, MFT_ICLR_ALL);
245
+ mft_reset_counters(qts, index);
246
+ g_assert_cmphex(mft_readw(qts, index, MFT_CNT1), ==, MFT_MAX_CNT);
247
+ g_assert_cmphex(mft_readw(qts, index, MFT_CRA), ==, MFT_MAX_CNT);
248
+ g_assert_cmphex(mft_readw(qts, index, MFT_CPA), ==,
249
+ MFT_MAX_CNT - MFT_TIMEOUT);
250
+ /* Start capture */
251
+ mft_writeb(qts, index, MFT_CKC, MFT_CKC_C1CSEL);
252
+ g_assert_true(qtest_get_irq(qts, MFT_IRQ(index)));
253
+ if (expected_cnt == -1) {
254
+ g_assert_cmphex(mft_readb(qts, index, MFT_ICTRL), ==, MFT_ICTRL_TEPND);
255
+ } else {
302
+ } else {
256
+ g_assert_cmphex(mft_readb(qts, index, MFT_ICTRL), ==, MFT_ICTRL_TAPND);
303
+ duty = MAX_DUTY * (cmr + 1) / (cnr + 1);
257
+ cnt = mft_readw(qts, index, MFT_CNT1);
304
+ }
258
+ /*
305
+
259
+ * Due to error in clock measurement and rounding, we might have a small
306
+ if (inverted) {
260
+ * error in measuring RPM.
307
+ duty = MAX_DUTY - duty;
261
+ */
308
+ }
262
+ g_assert_cmphex(cnt + MAX_ERROR, >=, expected_cnt);
309
+
263
+ g_assert_cmphex(cnt, <=, expected_cnt + MAX_ERROR);
310
+ return duty;
264
+ cr = mft_readw(qts, index, MFT_CRA);
311
+}
265
+ g_assert_cmphex(cnt, ==, cr);
312
+
266
+ }
313
+static uint32_t pwm_read(QTestState *qts, const TestData *td, unsigned offset)
267
+
314
+{
268
+ /* Verify rpm for fan B */
315
+ return qtest_readl(qts, td->module->base_addr + offset);
269
+
316
+}
270
+ qtest_irq_intercept_out(qts, "/machine/soc/a9mpcore/gic");
317
+
271
+}
318
+static void pwm_write(QTestState *qts, const TestData *td, unsigned offset,
272
+
319
+ uint32_t value)
273
/* Check pwm registers can be reset to default value */
320
+{
274
static void test_init(gconstpointer test_data)
321
+ qtest_writel(qts, td->module->base_addr + offset, value);
275
{
322
+}
276
const TestData *td = test_data;
323
+
277
- QTestState *qts = qtest_init("-machine quanta-gsj");
324
+static uint32_t pwm_read_ppr(QTestState *qts, const TestData *td)
278
+ QTestState *qts = qtest_init("-machine npcm750-evb");
325
+{
279
int module = pwm_module_index(td->module);
326
+ return extract32(pwm_read(qts, td, PPR), ppr_base[pwm_index(td->pwm)], 8);
280
int pwm = pwm_index(td->pwm);
327
+}
281
328
+
282
@@ -XXX,XX +XXX,XX @@ static void test_init(gconstpointer test_data)
329
+static void pwm_write_ppr(QTestState *qts, const TestData *td, uint32_t value)
283
static void test_oneshot(gconstpointer test_data)
330
+{
284
{
331
+ pwm_write(qts, td, PPR, value << ppr_base[pwm_index(td->pwm)]);
285
const TestData *td = test_data;
332
+}
286
- QTestState *qts = qtest_init("-machine quanta-gsj");
333
+
287
+ QTestState *qts = qtest_init("-machine npcm750-evb");
334
+static uint32_t pwm_read_csr(QTestState *qts, const TestData *td)
288
int module = pwm_module_index(td->module);
335
+{
289
int pwm = pwm_index(td->pwm);
336
+ return extract32(pwm_read(qts, td, CSR), csr_base[pwm_index(td->pwm)], 3);
290
uint32_t ppr, csr, pcr;
337
+}
291
@@ -XXX,XX +XXX,XX @@ static void test_oneshot(gconstpointer test_data)
338
+
292
static void test_toggle(gconstpointer test_data)
339
+static void pwm_write_csr(QTestState *qts, const TestData *td, uint32_t value)
293
{
340
+{
294
const TestData *td = test_data;
341
+ pwm_write(qts, td, CSR, value << csr_base[pwm_index(td->pwm)]);
295
- QTestState *qts = qtest_init("-machine quanta-gsj");
342
+}
296
+ QTestState *qts = qtest_init("-machine npcm750-evb");
343
+
297
int module = pwm_module_index(td->module);
344
+static uint32_t pwm_read_pcr(QTestState *qts, const TestData *td)
298
int pwm = pwm_index(td->pwm);
345
+{
299
uint32_t ppr, csr, pcr, cnr, cmr;
346
+ return extract32(pwm_read(qts, td, PCR), pcr_base[pwm_index(td->pwm)], 4);
300
int i, j, k, l;
347
+}
301
uint64_t expected_freq, expected_duty;
348
+
302
349
+static void pwm_write_pcr(QTestState *qts, const TestData *td, uint32_t value)
303
+ mft_init(qts, td);
350
+{
304
+
351
+ pwm_write(qts, td, PCR, value << pcr_base[pwm_index(td->pwm)]);
305
pcr = CH_EN | CH_MOD;
352
+}
306
for (i = 0; i < ARRAY_SIZE(ppr_list); ++i) {
353
+
307
ppr = ppr_list[i];
354
+static uint32_t pwm_read_cnr(QTestState *qts, const TestData *td)
308
@@ -XXX,XX +XXX,XX @@ static void test_toggle(gconstpointer test_data)
355
+{
309
==, expected_freq);
356
+ return pwm_read(qts, td, td->pwm->cnr_offset);
310
}
357
+}
311
358
+
312
+ /* Test MFT's RPM is correct. */
359
+static void pwm_write_cnr(QTestState *qts, const TestData *td, uint32_t value)
313
+ mft_verify_rpm(qts, td, expected_duty);
360
+{
314
+
361
+ pwm_write(qts, td, td->pwm->cnr_offset, value);
315
/* Test inverted mode */
362
+}
316
expected_duty = pwm_compute_duty(cnr, cmr, true);
363
+
317
pwm_write_pcr(qts, td, pcr | CH_INV);
364
+static uint32_t pwm_read_cmr(QTestState *qts, const TestData *td)
365
+{
366
+ return pwm_read(qts, td, td->pwm->cmr_offset);
367
+}
368
+
369
+static void pwm_write_cmr(QTestState *qts, const TestData *td, uint32_t value)
370
+{
371
+ pwm_write(qts, td, td->pwm->cmr_offset, value);
372
+}
373
+
374
+/* Check pwm registers can be reset to default value */
375
+static void test_init(gconstpointer test_data)
376
+{
377
+ const TestData *td = test_data;
378
+ QTestState *qts = qtest_init("-machine quanta-gsj");
379
+ int module = pwm_module_index(td->module);
380
+ int pwm = pwm_index(td->pwm);
381
+
382
+ g_assert_cmpuint(pwm_get_freq(qts, module, pwm), ==, 0);
383
+ g_assert_cmpuint(pwm_get_duty(qts, module, pwm), ==, 0);
384
+
385
+ qtest_quit(qts);
386
+}
387
+
388
+/* One-shot mode should not change frequency and duty cycle. */
389
+static void test_oneshot(gconstpointer test_data)
390
+{
391
+ const TestData *td = test_data;
392
+ QTestState *qts = qtest_init("-machine quanta-gsj");
393
+ int module = pwm_module_index(td->module);
394
+ int pwm = pwm_index(td->pwm);
395
+ uint32_t ppr, csr, pcr;
396
+ int i, j;
397
+
398
+ pcr = CH_EN;
399
+ for (i = 0; i < ARRAY_SIZE(ppr_list); ++i) {
400
+ ppr = ppr_list[i];
401
+ pwm_write_ppr(qts, td, ppr);
402
+
403
+ for (j = 0; j < ARRAY_SIZE(csr_list); ++j) {
404
+ csr = csr_list[j];
405
+ pwm_write_csr(qts, td, csr);
406
+ pwm_write_pcr(qts, td, pcr);
407
+
408
+ g_assert_cmpuint(pwm_read_ppr(qts, td), ==, ppr);
409
+ g_assert_cmpuint(pwm_read_csr(qts, td), ==, csr);
410
+ g_assert_cmpuint(pwm_read_pcr(qts, td), ==, pcr);
411
+ g_assert_cmpuint(pwm_get_freq(qts, module, pwm), ==, 0);
412
+ g_assert_cmpuint(pwm_get_duty(qts, module, pwm), ==, 0);
413
+ }
414
+ }
415
+
416
+ qtest_quit(qts);
417
+}
418
+
419
+/* In toggle mode, the PWM generates correct outputs. */
420
+static void test_toggle(gconstpointer test_data)
421
+{
422
+ const TestData *td = test_data;
423
+ QTestState *qts = qtest_init("-machine quanta-gsj");
424
+ int module = pwm_module_index(td->module);
425
+ int pwm = pwm_index(td->pwm);
426
+ uint32_t ppr, csr, pcr, cnr, cmr;
427
+ int i, j, k, l;
428
+ uint64_t expected_freq, expected_duty;
429
+
430
+ pcr = CH_EN | CH_MOD;
431
+ for (i = 0; i < ARRAY_SIZE(ppr_list); ++i) {
432
+ ppr = ppr_list[i];
433
+ pwm_write_ppr(qts, td, ppr);
434
+
435
+ for (j = 0; j < ARRAY_SIZE(csr_list); ++j) {
436
+ csr = csr_list[j];
437
+ pwm_write_csr(qts, td, csr);
438
+
439
+ for (k = 0; k < ARRAY_SIZE(cnr_list); ++k) {
440
+ cnr = cnr_list[k];
441
+ pwm_write_cnr(qts, td, cnr);
442
+
443
+ for (l = 0; l < ARRAY_SIZE(cmr_list); ++l) {
444
+ cmr = cmr_list[l];
445
+ pwm_write_cmr(qts, td, cmr);
446
+ expected_freq = pwm_compute_freq(qts, ppr, csr, cnr);
447
+ expected_duty = pwm_compute_duty(cnr, cmr, false);
448
+
449
+ pwm_write_pcr(qts, td, pcr);
450
+ g_assert_cmpuint(pwm_read_ppr(qts, td), ==, ppr);
451
+ g_assert_cmpuint(pwm_read_csr(qts, td), ==, csr);
452
+ g_assert_cmpuint(pwm_read_pcr(qts, td), ==, pcr);
453
+ g_assert_cmpuint(pwm_read_cnr(qts, td), ==, cnr);
454
+ g_assert_cmpuint(pwm_read_cmr(qts, td), ==, cmr);
455
+ g_assert_cmpuint(pwm_get_duty(qts, module, pwm),
456
+ ==, expected_duty);
457
+ if (expected_duty != 0 && expected_duty != 100) {
458
+ /* Duty cycle with 0 or 100 doesn't need frequency. */
459
+ g_assert_cmpuint(pwm_get_freq(qts, module, pwm),
460
+ ==, expected_freq);
461
+ }
462
+
463
+ /* Test inverted mode */
464
+ expected_duty = pwm_compute_duty(cnr, cmr, true);
465
+ pwm_write_pcr(qts, td, pcr | CH_INV);
466
+ g_assert_cmpuint(pwm_read_pcr(qts, td), ==, pcr | CH_INV);
467
+ g_assert_cmpuint(pwm_get_duty(qts, module, pwm),
468
+ ==, expected_duty);
469
+ if (expected_duty != 0 && expected_duty != 100) {
470
+ /* Duty cycle with 0 or 100 doesn't need frequency. */
471
+ g_assert_cmpuint(pwm_get_freq(qts, module, pwm),
472
+ ==, expected_freq);
473
+ }
474
+
475
+ }
476
+ }
477
+ }
478
+ }
479
+
480
+ qtest_quit(qts);
481
+}
482
+
483
+static void pwm_add_test(const char *name, const TestData* td,
484
+ GTestDataFunc fn)
485
+{
486
+ g_autofree char *full_name = g_strdup_printf(
487
+ "npcm7xx_pwm/module[%d]/pwm[%d]/%s", pwm_module_index(td->module),
488
+ pwm_index(td->pwm), name);
489
+ qtest_add_data_func(full_name, td, fn);
490
+}
491
+#define add_test(name, td) pwm_add_test(#name, td, test_##name)
492
+
493
+int main(int argc, char **argv)
494
+{
495
+ TestData test_data_list[ARRAY_SIZE(pwm_module_list) * ARRAY_SIZE(pwm_list)];
496
+
497
+ g_test_init(&argc, &argv, NULL);
498
+
499
+ for (int i = 0; i < ARRAY_SIZE(pwm_module_list); ++i) {
500
+ for (int j = 0; j < ARRAY_SIZE(pwm_list); ++j) {
501
+ TestData *td = &test_data_list[i * ARRAY_SIZE(pwm_list) + j];
502
+
503
+ td->module = &pwm_module_list[i];
504
+ td->pwm = &pwm_list[j];
505
+
506
+ add_test(init, td);
507
+ add_test(oneshot, td);
508
+ add_test(toggle, td);
509
+ }
510
+ }
511
+
512
+ return g_test_run();
513
+}
514
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
515
index XXXXXXX..XXXXXXX 100644
516
--- a/tests/qtest/meson.build
517
+++ b/tests/qtest/meson.build
518
@@ -XXX,XX +XXX,XX @@ qtests_sparc64 = \
519
qtests_npcm7xx = \
520
['npcm7xx_adc-test',
521
'npcm7xx_gpio-test',
522
+ 'npcm7xx_pwm-test',
523
'npcm7xx_rng-test',
524
'npcm7xx_timer-test',
525
'npcm7xx_watchdog_timer-test']
318
--
526
--
319
2.20.1
527
2.20.1
320
528
321
529
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
This patch adds GPIOs in NPCM7xx PWM module for its duty values.
3
A device shouldn't access its parent object which is QOM internal.
4
The purpose of this is to connect it to the MFT module to provide
4
Instead it should use type cast for this purporse. This patch fixes this
5
an input for measuring a PWM fan's RPM. Each PWM module has
5
issue for all NPCM7XX Devices.
6
NPCM7XX_PWM_PER_MODULE of GPIOs, each one corresponds to
7
one PWM instance and can connect to multiple fan instances in MFT.
8
6
9
Reviewed-by: Doug Evans <dje@google.com>
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
11
Signed-off-by: Hao Wu <wuhaotsh@google.com>
7
Signed-off-by: Hao Wu <wuhaotsh@google.com>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Message-id: 20210311180855.149764-2-wuhaotsh@google.com
9
Message-id: 20210108190945.949196-7-wuhaotsh@google.com
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
11
---
16
include/hw/misc/npcm7xx_pwm.h | 4 +++-
12
hw/arm/npcm7xx_boards.c | 2 +-
17
hw/misc/npcm7xx_pwm.c | 4 ++++
13
hw/mem/npcm7xx_mc.c | 2 +-
18
2 files changed, 7 insertions(+), 1 deletion(-)
14
hw/misc/npcm7xx_clk.c | 2 +-
15
hw/misc/npcm7xx_gcr.c | 2 +-
16
hw/misc/npcm7xx_rng.c | 2 +-
17
hw/nvram/npcm7xx_otp.c | 2 +-
18
hw/ssi/npcm7xx_fiu.c | 2 +-
19
7 files changed, 7 insertions(+), 7 deletions(-)
19
20
20
diff --git a/include/hw/misc/npcm7xx_pwm.h b/include/hw/misc/npcm7xx_pwm.h
21
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
21
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/misc/npcm7xx_pwm.h
23
--- a/hw/arm/npcm7xx_boards.c
23
+++ b/include/hw/misc/npcm7xx_pwm.h
24
+++ b/hw/arm/npcm7xx_boards.c
24
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxPWM {
25
@@ -XXX,XX +XXX,XX @@ static NPCM7xxState *npcm7xx_create_soc(MachineState *machine,
25
* @iomem: Memory region through which registers are accessed.
26
uint32_t hw_straps)
26
* @clock: The PWM clock.
27
{
27
* @pwm: The PWM channels owned by this module.
28
NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine);
28
+ * @duty_gpio_out: The duty cycle of each PWM channels as a output GPIO.
29
- MachineClass *mc = &nmc->parent;
29
* @ppr: The prescaler register.
30
+ MachineClass *mc = MACHINE_CLASS(nmc);
30
* @csr: The clock selector register.
31
Object *obj;
31
* @pcr: The control register.
32
32
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxPWMState {
33
if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
33
MemoryRegion iomem;
34
diff --git a/hw/mem/npcm7xx_mc.c b/hw/mem/npcm7xx_mc.c
34
35
Clock *clock;
36
- NPCM7xxPWM pwm[NPCM7XX_PWM_PER_MODULE];
37
+ NPCM7xxPWM pwm[NPCM7XX_PWM_PER_MODULE];
38
+ qemu_irq duty_gpio_out[NPCM7XX_PWM_PER_MODULE];
39
40
uint32_t ppr;
41
uint32_t csr;
42
diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
43
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/misc/npcm7xx_pwm.c
36
--- a/hw/mem/npcm7xx_mc.c
45
+++ b/hw/misc/npcm7xx_pwm.c
37
+++ b/hw/mem/npcm7xx_mc.c
46
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_pwm_update_duty(NPCM7xxPWM *p)
38
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_mc_realize(DeviceState *dev, Error **errp)
47
trace_npcm7xx_pwm_update_duty(DEVICE(p->module)->canonical_path,
39
48
p->index, p->duty, duty);
40
memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_mc_ops, s, "regs",
49
p->duty = duty;
41
NPCM7XX_MC_REGS_SIZE);
50
+ qemu_set_irq(p->module->duty_gpio_out[p->index], p->duty);
42
- sysbus_init_mmio(&s->parent, &s->mmio);
51
}
43
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio);
52
}
44
}
53
45
54
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_pwm_init(Object *obj)
46
static void npcm7xx_mc_class_init(ObjectClass *klass, void *data)
55
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
47
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/misc/npcm7xx_clk.c
50
+++ b/hw/misc/npcm7xx_clk.c
51
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_init(Object *obj)
52
53
memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
54
TYPE_NPCM7XX_CLK, 4 * KiB);
55
- sysbus_init_mmio(&s->parent, &s->iomem);
56
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
57
}
58
59
static int npcm7xx_clk_post_load(void *opaque, int version_id)
60
diff --git a/hw/misc/npcm7xx_gcr.c b/hw/misc/npcm7xx_gcr.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/hw/misc/npcm7xx_gcr.c
63
+++ b/hw/misc/npcm7xx_gcr.c
64
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_gcr_init(Object *obj)
65
66
memory_region_init_io(&s->iomem, obj, &npcm7xx_gcr_ops, s,
67
TYPE_NPCM7XX_GCR, 4 * KiB);
68
- sysbus_init_mmio(&s->parent, &s->iomem);
69
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
70
}
71
72
static const VMStateDescription vmstate_npcm7xx_gcr = {
73
diff --git a/hw/misc/npcm7xx_rng.c b/hw/misc/npcm7xx_rng.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/misc/npcm7xx_rng.c
76
+++ b/hw/misc/npcm7xx_rng.c
77
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_rng_init(Object *obj)
78
79
memory_region_init_io(&s->iomem, obj, &npcm7xx_rng_ops, s, "regs",
80
NPCM7XX_RNG_REGS_SIZE);
81
- sysbus_init_mmio(&s->parent, &s->iomem);
82
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
83
}
84
85
static const VMStateDescription vmstate_npcm7xx_rng = {
86
diff --git a/hw/nvram/npcm7xx_otp.c b/hw/nvram/npcm7xx_otp.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/hw/nvram/npcm7xx_otp.c
89
+++ b/hw/nvram/npcm7xx_otp.c
90
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_otp_realize(DeviceState *dev, Error **errp)
91
{
92
NPCM7xxOTPClass *oc = NPCM7XX_OTP_GET_CLASS(dev);
93
NPCM7xxOTPState *s = NPCM7XX_OTP(dev);
94
- SysBusDevice *sbd = &s->parent;
95
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
96
97
memset(s->array, 0, sizeof(s->array));
98
99
diff --git a/hw/ssi/npcm7xx_fiu.c b/hw/ssi/npcm7xx_fiu.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/hw/ssi/npcm7xx_fiu.c
102
+++ b/hw/ssi/npcm7xx_fiu.c
103
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_fiu_hold_reset(Object *obj)
104
static void npcm7xx_fiu_realize(DeviceState *dev, Error **errp)
105
{
106
NPCM7xxFIUState *s = NPCM7XX_FIU(dev);
107
- SysBusDevice *sbd = &s->parent;
108
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
56
int i;
109
int i;
57
110
58
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(s->pwm) != NPCM7XX_PWM_PER_MODULE);
111
if (s->cs_count <= 0) {
59
for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
60
NPCM7xxPWM *p = &s->pwm[i];
61
p->module = s;
62
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_pwm_init(Object *obj)
63
object_property_add_uint32_ptr(obj, "duty[*]",
64
&s->pwm[i].duty, OBJ_PROP_FLAG_READ);
65
}
66
+ qdev_init_gpio_out_named(DEVICE(s), s->duty_gpio_out,
67
+ "duty-gpio-out", NPCM7XX_PWM_PER_MODULE);
68
}
69
70
static const VMStateDescription vmstate_npcm7xx_pwm = {
71
--
112
--
72
2.20.1
113
2.20.1
73
114
74
115
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Roman Bolshakov <r.bolshakov@yadro.com>
2
2
3
Missed out on compressing the second half of a predicate
3
ui/cocoa.m:1188:44: warning: 'openFile:' is deprecated: first deprecated in macOS 11.0 - Use -[NSWorkspace openURL:] instead.
4
with length vl % 512 > 256.
4
[-Wdeprecated-declarations]
5
if ([[NSWorkspace sharedWorkspace] openFile: full_file_path] == YES) {
6
^
7
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSWorkspace.h:350:1: note:
8
'openFile:' has been explicitly marked deprecated here
9
- (BOOL)openFile:(NSString *)fullPath API_DEPRECATED("Use -[NSWorkspace openURL:] instead.", macos(10.0, 11.0));
10
^
5
11
6
Adjust all of the x + (y << s) to x | (y << s) as a
12
Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com>
7
general style fix. Drop the extract64 because the input
8
uint64_t are known to be already zero-extended from the
9
current size of the predicate.
10
11
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20210309155305.11301-2-richard.henderson@linaro.org
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20210102150718.47618-1-r.bolshakov@yadro.com
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
16
---
17
target/arm/sve_helper.c | 30 +++++++++++++++++++++---------
17
ui/cocoa.m | 5 ++++-
18
1 file changed, 21 insertions(+), 9 deletions(-)
18
1 file changed, 4 insertions(+), 1 deletion(-)
19
19
20
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
20
diff --git a/ui/cocoa.m b/ui/cocoa.m
21
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/sve_helper.c
22
--- a/ui/cocoa.m
23
+++ b/target/arm/sve_helper.c
23
+++ b/ui/cocoa.m
24
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_uzp_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
24
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
25
if (oprsz <= 8) {
25
/* Where to look for local files */
26
l = compress_bits(n[0] >> odd, esz);
26
NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"docs/"};
27
h = compress_bits(m[0] >> odd, esz);
27
NSString *full_file_path;
28
- d[0] = extract64(l + (h << (4 * oprsz)), 0, 8 * oprsz);
28
+ NSURL *full_file_url;
29
+ d[0] = l | (h << (4 * oprsz));
29
30
} else {
30
/* iterate thru the possible paths until the file is found */
31
ARMPredicateReg tmp_m;
31
int index;
32
intptr_t oprsz_16 = oprsz / 16;
32
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
33
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_uzp_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
33
full_file_path = [full_file_path stringByDeletingLastPathComponent];
34
h = n[2 * i + 1];
34
full_file_path = [NSString stringWithFormat: @"%@/%@%@", full_file_path,
35
l = compress_bits(l >> odd, esz);
35
path_array[index], filename];
36
h = compress_bits(h >> odd, esz);
36
- if ([[NSWorkspace sharedWorkspace] openFile: full_file_path] == YES) {
37
- d[i] = l + (h << 32);
37
+ full_file_url = [NSURL fileURLWithPath: full_file_path
38
+ d[i] = l | (h << 32);
38
+ isDirectory: false];
39
}
39
+ if ([[NSWorkspace sharedWorkspace] openURL: full_file_url] == YES) {
40
40
return;
41
- /* For VL which is not a power of 2, the results from M do not
42
- align nicely with the uint64_t for D. Put the aligned results
43
- from M into TMP_M and then copy it into place afterward. */
44
+ /*
45
+ * For VL which is not a multiple of 512, the results from M do not
46
+ * align nicely with the uint64_t for D. Put the aligned results
47
+ * from M into TMP_M and then copy it into place afterward.
48
+ */
49
if (oprsz & 15) {
50
- d[i] = compress_bits(n[2 * i] >> odd, esz);
51
+ int final_shift = (oprsz & 15) * 2;
52
+
53
+ l = n[2 * i + 0];
54
+ h = n[2 * i + 1];
55
+ l = compress_bits(l >> odd, esz);
56
+ h = compress_bits(h >> odd, esz);
57
+ d[i] = l | (h << final_shift);
58
59
for (i = 0; i < oprsz_16; i++) {
60
l = m[2 * i + 0];
61
h = m[2 * i + 1];
62
l = compress_bits(l >> odd, esz);
63
h = compress_bits(h >> odd, esz);
64
- tmp_m.p[i] = l + (h << 32);
65
+ tmp_m.p[i] = l | (h << 32);
66
}
67
- tmp_m.p[i] = compress_bits(m[2 * i] >> odd, esz);
68
+ l = m[2 * i + 0];
69
+ h = m[2 * i + 1];
70
+ l = compress_bits(l >> odd, esz);
71
+ h = compress_bits(h >> odd, esz);
72
+ tmp_m.p[i] = l | (h << final_shift);
73
74
swap_memmove(vd + oprsz / 2, &tmp_m, oprsz / 2);
75
} else {
76
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_uzp_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
77
h = m[2 * i + 1];
78
l = compress_bits(l >> odd, esz);
79
h = compress_bits(h >> odd, esz);
80
- d[oprsz_16 + i] = l + (h << 32);
81
+ d[oprsz_16 + i] = l | (h << 32);
82
}
83
}
41
}
84
}
42
}
85
--
43
--
86
2.20.1
44
2.20.1
87
45
88
46
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Wrote too much with low-half zip (zip1) with vl % 512 != 0.
4
5
Adjust all of the x + (y << s) to x | (y << s) as a style fix.
6
7
We only ever have exact overlap between D, M, and N. Therefore
8
we only need a single temporary, and we do not need to check for
9
partial overlap.
10
11
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20210309155305.11301-3-richard.henderson@linaro.org
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
target/arm/sve_helper.c | 25 ++++++++++++++-----------
18
1 file changed, 14 insertions(+), 11 deletions(-)
19
20
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/sve_helper.c
23
+++ b/target/arm/sve_helper.c
24
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_zip_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
25
intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
26
int esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
27
intptr_t high = FIELD_EX32(pred_desc, PREDDESC, DATA);
28
+ int esize = 1 << esz;
29
uint64_t *d = vd;
30
intptr_t i;
31
32
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_zip_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
33
mm = extract64(mm, high * half, half);
34
nn = expand_bits(nn, esz);
35
mm = expand_bits(mm, esz);
36
- d[0] = nn + (mm << (1 << esz));
37
+ d[0] = nn | (mm << esize);
38
} else {
39
- ARMPredicateReg tmp_n, tmp_m;
40
+ ARMPredicateReg tmp;
41
42
/* We produce output faster than we consume input.
43
Therefore we must be mindful of possible overlap. */
44
- if ((vn - vd) < (uintptr_t)oprsz) {
45
- vn = memcpy(&tmp_n, vn, oprsz);
46
- }
47
- if ((vm - vd) < (uintptr_t)oprsz) {
48
- vm = memcpy(&tmp_m, vm, oprsz);
49
+ if (vd == vn) {
50
+ vn = memcpy(&tmp, vn, oprsz);
51
+ if (vd == vm) {
52
+ vm = vn;
53
+ }
54
+ } else if (vd == vm) {
55
+ vm = memcpy(&tmp, vm, oprsz);
56
}
57
if (high) {
58
high = oprsz >> 1;
59
}
60
61
- if ((high & 3) == 0) {
62
+ if ((oprsz & 7) == 0) {
63
uint32_t *n = vn, *m = vm;
64
high >>= 2;
65
66
- for (i = 0; i < DIV_ROUND_UP(oprsz, 8); i++) {
67
+ for (i = 0; i < oprsz / 8; i++) {
68
uint64_t nn = n[H4(high + i)];
69
uint64_t mm = m[H4(high + i)];
70
71
nn = expand_bits(nn, esz);
72
mm = expand_bits(mm, esz);
73
- d[i] = nn + (mm << (1 << esz));
74
+ d[i] = nn | (mm << esize);
75
}
76
} else {
77
uint8_t *n = vn, *m = vm;
78
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_zip_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
79
80
nn = expand_bits(nn, esz);
81
mm = expand_bits(mm, esz);
82
- d16[H2(i)] = nn + (mm << (1 << esz));
83
+ d16[H2(i)] = nn | (mm << esize);
84
}
85
}
86
}
87
--
88
2.20.1
89
90
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Wrote too much with punpk1 with vl % 512 != 0.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210309155305.11301-4-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/sve_helper.c | 4 ++--
12
1 file changed, 2 insertions(+), 2 deletions(-)
13
14
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/sve_helper.c
17
+++ b/target/arm/sve_helper.c
18
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_punpk_p)(void *vd, void *vn, uint32_t pred_desc)
19
high = oprsz >> 1;
20
}
21
22
- if ((high & 3) == 0) {
23
+ if ((oprsz & 7) == 0) {
24
uint32_t *n = vn;
25
high >>= 2;
26
27
- for (i = 0; i < DIV_ROUND_UP(oprsz, 8); i++) {
28
+ for (i = 0; i < oprsz / 8; i++) {
29
uint64_t nn = n[H4(high + i)];
30
d[i] = expand_bits(nn, 0);
31
}
32
--
33
2.20.1
34
35
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Since b64ee454a4a0, all predicate operations should be
4
using these field macros for predicates.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210309155305.11301-5-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/sve_helper.c | 6 +++---
12
target/arm/translate-sve.c | 7 +++----
13
2 files changed, 6 insertions(+), 7 deletions(-)
14
15
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sve_helper.c
18
+++ b/target/arm/sve_helper.c
19
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_compact_d)(void *vd, void *vn, void *vg, uint32_t desc)
20
*/
21
int32_t HELPER(sve_last_active_element)(void *vg, uint32_t pred_desc)
22
{
23
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
24
- intptr_t esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2);
25
+ intptr_t words = DIV_ROUND_UP(FIELD_EX32(pred_desc, PREDDESC, OPRSZ), 8);
26
+ intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
27
28
- return last_active_element(vg, DIV_ROUND_UP(oprsz, 8), esz);
29
+ return last_active_element(vg, words, esz);
30
}
31
32
void HELPER(sve_splice)(void *vd, void *vn, void *vm, void *vg, uint32_t desc)
33
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/translate-sve.c
36
+++ b/target/arm/translate-sve.c
37
@@ -XXX,XX +XXX,XX @@ static void find_last_active(DisasContext *s, TCGv_i32 ret, int esz, int pg)
38
*/
39
TCGv_ptr t_p = tcg_temp_new_ptr();
40
TCGv_i32 t_desc;
41
- unsigned vsz = pred_full_reg_size(s);
42
- unsigned desc;
43
+ unsigned desc = 0;
44
45
- desc = vsz - 2;
46
- desc = deposit32(desc, SIMD_DATA_SHIFT, 2, esz);
47
+ desc = FIELD_DP32(desc, PREDDESC, OPRSZ, pred_full_reg_size(s));
48
+ desc = FIELD_DP32(desc, PREDDESC, ESZ, esz);
49
50
tcg_gen_addi_ptr(t_p, cpu_env, pred_full_reg_offset(s, pg));
51
t_desc = tcg_const_i32(desc);
52
--
53
2.20.1
54
55
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Since b64ee454a4a0, all predicate operations should be
4
using these field macros for predicates.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210309155305.11301-6-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/sve_helper.c | 30 ++++++++++++++----------------
12
target/arm/translate-sve.c | 4 ++--
13
2 files changed, 16 insertions(+), 18 deletions(-)
14
15
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sve_helper.c
18
+++ b/target/arm/sve_helper.c
19
@@ -XXX,XX +XXX,XX @@ static uint32_t do_zero(ARMPredicateReg *d, intptr_t oprsz)
20
void HELPER(sve_brkpa)(void *vd, void *vn, void *vm, void *vg,
21
uint32_t pred_desc)
22
{
23
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
24
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
25
if (last_active_pred(vn, vg, oprsz)) {
26
compute_brk_z(vd, vm, vg, oprsz, true);
27
} else {
28
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_brkpa)(void *vd, void *vn, void *vm, void *vg,
29
uint32_t HELPER(sve_brkpas)(void *vd, void *vn, void *vm, void *vg,
30
uint32_t pred_desc)
31
{
32
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
33
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
34
if (last_active_pred(vn, vg, oprsz)) {
35
return compute_brks_z(vd, vm, vg, oprsz, true);
36
} else {
37
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(sve_brkpas)(void *vd, void *vn, void *vm, void *vg,
38
void HELPER(sve_brkpb)(void *vd, void *vn, void *vm, void *vg,
39
uint32_t pred_desc)
40
{
41
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
42
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
43
if (last_active_pred(vn, vg, oprsz)) {
44
compute_brk_z(vd, vm, vg, oprsz, false);
45
} else {
46
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_brkpb)(void *vd, void *vn, void *vm, void *vg,
47
uint32_t HELPER(sve_brkpbs)(void *vd, void *vn, void *vm, void *vg,
48
uint32_t pred_desc)
49
{
50
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
51
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
52
if (last_active_pred(vn, vg, oprsz)) {
53
return compute_brks_z(vd, vm, vg, oprsz, false);
54
} else {
55
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(sve_brkpbs)(void *vd, void *vn, void *vm, void *vg,
56
57
void HELPER(sve_brka_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
58
{
59
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
60
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
61
compute_brk_z(vd, vn, vg, oprsz, true);
62
}
63
64
uint32_t HELPER(sve_brkas_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
65
{
66
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
67
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
68
return compute_brks_z(vd, vn, vg, oprsz, true);
69
}
70
71
void HELPER(sve_brkb_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
72
{
73
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
74
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
75
compute_brk_z(vd, vn, vg, oprsz, false);
76
}
77
78
uint32_t HELPER(sve_brkbs_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
79
{
80
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
81
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
82
return compute_brks_z(vd, vn, vg, oprsz, false);
83
}
84
85
void HELPER(sve_brka_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
86
{
87
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
88
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
89
compute_brk_m(vd, vn, vg, oprsz, true);
90
}
91
92
uint32_t HELPER(sve_brkas_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
93
{
94
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
95
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
96
return compute_brks_m(vd, vn, vg, oprsz, true);
97
}
98
99
void HELPER(sve_brkb_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
100
{
101
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
102
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
103
compute_brk_m(vd, vn, vg, oprsz, false);
104
}
105
106
uint32_t HELPER(sve_brkbs_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
107
{
108
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
109
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
110
return compute_brks_m(vd, vn, vg, oprsz, false);
111
}
112
113
void HELPER(sve_brkn)(void *vd, void *vn, void *vg, uint32_t pred_desc)
114
{
115
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
116
-
117
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
118
if (!last_active_pred(vn, vg, oprsz)) {
119
do_zero(vd, oprsz);
120
}
121
@@ -XXX,XX +XXX,XX @@ static uint32_t predtest_ones(ARMPredicateReg *d, intptr_t oprsz,
122
123
uint32_t HELPER(sve_brkns)(void *vd, void *vn, void *vg, uint32_t pred_desc)
124
{
125
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
126
-
127
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
128
if (last_active_pred(vn, vg, oprsz)) {
129
return predtest_ones(vd, oprsz, -1);
130
} else {
131
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
132
index XXXXXXX..XXXXXXX 100644
133
--- a/target/arm/translate-sve.c
134
+++ b/target/arm/translate-sve.c
135
@@ -XXX,XX +XXX,XX @@ static bool do_brk3(DisasContext *s, arg_rprr_s *a,
136
TCGv_ptr n = tcg_temp_new_ptr();
137
TCGv_ptr m = tcg_temp_new_ptr();
138
TCGv_ptr g = tcg_temp_new_ptr();
139
- TCGv_i32 t = tcg_const_i32(vsz - 2);
140
+ TCGv_i32 t = tcg_const_i32(FIELD_DP32(0, PREDDESC, OPRSZ, vsz));
141
142
tcg_gen_addi_ptr(d, cpu_env, pred_full_reg_offset(s, a->rd));
143
tcg_gen_addi_ptr(n, cpu_env, pred_full_reg_offset(s, a->rn));
144
@@ -XXX,XX +XXX,XX @@ static bool do_brk2(DisasContext *s, arg_rpr_s *a,
145
TCGv_ptr d = tcg_temp_new_ptr();
146
TCGv_ptr n = tcg_temp_new_ptr();
147
TCGv_ptr g = tcg_temp_new_ptr();
148
- TCGv_i32 t = tcg_const_i32(vsz - 2);
149
+ TCGv_i32 t = tcg_const_i32(FIELD_DP32(0, PREDDESC, OPRSZ, vsz));
150
151
tcg_gen_addi_ptr(d, cpu_env, pred_full_reg_offset(s, a->rd));
152
tcg_gen_addi_ptr(n, cpu_env, pred_full_reg_offset(s, a->rn));
153
--
154
2.20.1
155
156
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Since b64ee454a4a0, all predicate operations should be
4
using these field macros for predicates.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210309155305.11301-7-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/sve_helper.c | 6 +++---
12
target/arm/translate-sve.c | 6 +++---
13
2 files changed, 6 insertions(+), 6 deletions(-)
14
15
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sve_helper.c
18
+++ b/target/arm/sve_helper.c
19
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(sve_brkns)(void *vd, void *vn, void *vg, uint32_t pred_desc)
20
21
uint64_t HELPER(sve_cntp)(void *vn, void *vg, uint32_t pred_desc)
22
{
23
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
24
- intptr_t esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2);
25
+ intptr_t words = DIV_ROUND_UP(FIELD_EX32(pred_desc, PREDDESC, OPRSZ), 8);
26
+ intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
27
uint64_t *n = vn, *g = vg, sum = 0, mask = pred_esz_masks[esz];
28
intptr_t i;
29
30
- for (i = 0; i < DIV_ROUND_UP(oprsz, 8); ++i) {
31
+ for (i = 0; i < words; ++i) {
32
uint64_t t = n[i] & g[i] & mask;
33
sum += ctpop64(t);
34
}
35
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/translate-sve.c
38
+++ b/target/arm/translate-sve.c
39
@@ -XXX,XX +XXX,XX @@ static void do_cntp(DisasContext *s, TCGv_i64 val, int esz, int pn, int pg)
40
} else {
41
TCGv_ptr t_pn = tcg_temp_new_ptr();
42
TCGv_ptr t_pg = tcg_temp_new_ptr();
43
- unsigned desc;
44
+ unsigned desc = 0;
45
TCGv_i32 t_desc;
46
47
- desc = psz - 2;
48
- desc = deposit32(desc, SIMD_DATA_SHIFT, 2, esz);
49
+ desc = FIELD_DP32(desc, PREDDESC, OPRSZ, psz);
50
+ desc = FIELD_DP32(desc, PREDDESC, ESZ, esz);
51
52
tcg_gen_addi_ptr(t_pn, cpu_env, pred_full_reg_offset(s, pn));
53
tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, pg));
54
--
55
2.20.1
56
57
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Since b64ee454a4a0, all predicate operations should be
4
using these field macros for predicates.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210309155305.11301-8-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/sve_helper.c | 4 ++--
12
target/arm/translate-sve.c | 7 ++++---
13
2 files changed, 6 insertions(+), 5 deletions(-)
14
15
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sve_helper.c
18
+++ b/target/arm/sve_helper.c
19
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(sve_cntp)(void *vn, void *vg, uint32_t pred_desc)
20
21
uint32_t HELPER(sve_while)(void *vd, uint32_t count, uint32_t pred_desc)
22
{
23
- uintptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
24
- intptr_t esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2);
25
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
26
+ intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
27
uint64_t esz_mask = pred_esz_masks[esz];
28
ARMPredicateReg *d = vd;
29
uint32_t flags;
30
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/translate-sve.c
33
+++ b/target/arm/translate-sve.c
34
@@ -XXX,XX +XXX,XX @@ static bool trans_WHILE(DisasContext *s, arg_WHILE *a)
35
TCGv_i64 op0, op1, t0, t1, tmax;
36
TCGv_i32 t2, t3;
37
TCGv_ptr ptr;
38
- unsigned desc, vsz = vec_full_reg_size(s);
39
+ unsigned vsz = vec_full_reg_size(s);
40
+ unsigned desc = 0;
41
TCGCond cond;
42
43
if (!sve_access_check(s)) {
44
@@ -XXX,XX +XXX,XX @@ static bool trans_WHILE(DisasContext *s, arg_WHILE *a)
45
/* Scale elements to bits. */
46
tcg_gen_shli_i32(t2, t2, a->esz);
47
48
- desc = (vsz / 8) - 2;
49
- desc = deposit32(desc, SIMD_DATA_SHIFT, 2, a->esz);
50
+ desc = FIELD_DP32(desc, PREDDESC, OPRSZ, vsz / 8);
51
+ desc = FIELD_DP32(desc, PREDDESC, ESZ, a->esz);
52
t3 = tcg_const_i32(desc);
53
54
ptr = tcg_temp_new_ptr();
55
--
56
2.20.1
57
58
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
With the reduction operations, we intentionally increase maxsz to
4
the next power of 2, so as to fill out the reduction tree correctly.
5
Since e2e7168a214b, oprsz must equal maxsz, with exceptions for small
6
vectors, so this triggers an assertion for vector sizes > 32 that are
7
not themselves a power of 2.
8
9
Pass the power-of-two value in the simd_data field instead.
10
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210309155305.11301-9-richard.henderson@linaro.org
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
target/arm/sve_helper.c | 2 +-
17
target/arm/translate-sve.c | 2 +-
18
2 files changed, 2 insertions(+), 2 deletions(-)
19
20
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/sve_helper.c
23
+++ b/target/arm/sve_helper.c
24
@@ -XXX,XX +XXX,XX @@ static TYPE NAME##_reduce(TYPE *data, float_status *status, uintptr_t n) \
25
} \
26
uint64_t HELPER(NAME)(void *vn, void *vg, void *vs, uint32_t desc) \
27
{ \
28
- uintptr_t i, oprsz = simd_oprsz(desc), maxsz = simd_maxsz(desc); \
29
+ uintptr_t i, oprsz = simd_oprsz(desc), maxsz = simd_data(desc); \
30
TYPE data[sizeof(ARMVectorReg) / sizeof(TYPE)]; \
31
for (i = 0; i < oprsz; ) { \
32
uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
33
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/translate-sve.c
36
+++ b/target/arm/translate-sve.c
37
@@ -XXX,XX +XXX,XX @@ static void do_reduce(DisasContext *s, arg_rpr_esz *a,
38
{
39
unsigned vsz = vec_full_reg_size(s);
40
unsigned p2vsz = pow2ceil(vsz);
41
- TCGv_i32 t_desc = tcg_const_i32(simd_desc(vsz, p2vsz, 0));
42
+ TCGv_i32 t_desc = tcg_const_i32(simd_desc(vsz, vsz, p2vsz));
43
TCGv_ptr t_zn, t_pg, status;
44
TCGv_i64 temp;
45
46
--
47
2.20.1
48
49
diff view generated by jsdifflib
Deleted patch
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
1
3
Currently the emulated EMAC for sun8i always traverses the transmit queue
4
from the head when transferring packets. It searches for a list of consecutive
5
descriptors whichs are flagged as ready for processing and transmits their payloads
6
accordingly. The controller stops processing once it finds a descriptor that is not
7
marked ready.
8
9
While the above behaviour works in most situations, it is not the same as the actual
10
EMAC in hardware. Actual hardware uses the TX_CUR_DESC register value to keep track
11
of the last position in the transmit queue and continues processing from that position
12
when software triggers the start of DMA processing. The currently emulated behaviour can
13
lead to packet loss on transmit when software fills the transmit queue with ready
14
descriptors that overlap the tail of the circular list.
15
16
This commit modifies the emulated EMAC for sun8i such that it processes
17
the transmit queue using the TX_CUR_DESC register in the same way as hardware.
18
19
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
20
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
21
Message-id: 20210310195820.21950-2-nieklinnenbank@gmail.com
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
24
hw/net/allwinner-sun8i-emac.c | 62 +++++++++++++++++++----------------
25
1 file changed, 34 insertions(+), 28 deletions(-)
26
27
diff --git a/hw/net/allwinner-sun8i-emac.c b/hw/net/allwinner-sun8i-emac.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/net/allwinner-sun8i-emac.c
30
+++ b/hw/net/allwinner-sun8i-emac.c
31
@@ -XXX,XX +XXX,XX @@ static void allwinner_sun8i_emac_update_irq(AwSun8iEmacState *s)
32
qemu_set_irq(s->irq, (s->int_sta & s->int_en) != 0);
33
}
34
35
-static uint32_t allwinner_sun8i_emac_next_desc(AwSun8iEmacState *s,
36
- FrameDescriptor *desc,
37
- size_t min_size)
38
+static bool allwinner_sun8i_emac_desc_owned(FrameDescriptor *desc,
39
+ size_t min_buf_size)
40
{
41
- uint32_t paddr = desc->next;
42
-
43
- dma_memory_read(&s->dma_as, paddr, desc, sizeof(*desc));
44
-
45
- if ((desc->status & DESC_STATUS_CTL) &&
46
- (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_size) {
47
- return paddr;
48
- } else {
49
- return 0;
50
- }
51
+ return (desc->status & DESC_STATUS_CTL) && (min_buf_size == 0 ||
52
+ (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_buf_size);
53
}
54
55
-static uint32_t allwinner_sun8i_emac_get_desc(AwSun8iEmacState *s,
56
- FrameDescriptor *desc,
57
- uint32_t start_addr,
58
- size_t min_size)
59
+static void allwinner_sun8i_emac_get_desc(AwSun8iEmacState *s,
60
+ FrameDescriptor *desc,
61
+ uint32_t phys_addr)
62
+{
63
+ dma_memory_read(&s->dma_as, phys_addr, desc, sizeof(*desc));
64
+}
65
+
66
+static uint32_t allwinner_sun8i_emac_next_desc(AwSun8iEmacState *s,
67
+ FrameDescriptor *desc)
68
+{
69
+ const uint32_t nxt = desc->next;
70
+ allwinner_sun8i_emac_get_desc(s, desc, nxt);
71
+ return nxt;
72
+}
73
+
74
+static uint32_t allwinner_sun8i_emac_find_desc(AwSun8iEmacState *s,
75
+ FrameDescriptor *desc,
76
+ uint32_t start_addr,
77
+ size_t min_size)
78
{
79
uint32_t desc_addr = start_addr;
80
81
/* Note that the list is a cycle. Last entry points back to the head. */
82
while (desc_addr != 0) {
83
- dma_memory_read(&s->dma_as, desc_addr, desc, sizeof(*desc));
84
+ allwinner_sun8i_emac_get_desc(s, desc, desc_addr);
85
86
- if ((desc->status & DESC_STATUS_CTL) &&
87
- (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_size) {
88
+ if (allwinner_sun8i_emac_desc_owned(desc, min_size)) {
89
return desc_addr;
90
} else if (desc->next == start_addr) {
91
break;
92
@@ -XXX,XX +XXX,XX @@ static uint32_t allwinner_sun8i_emac_rx_desc(AwSun8iEmacState *s,
93
FrameDescriptor *desc,
94
size_t min_size)
95
{
96
- return allwinner_sun8i_emac_get_desc(s, desc, s->rx_desc_curr, min_size);
97
+ return allwinner_sun8i_emac_find_desc(s, desc, s->rx_desc_curr, min_size);
98
}
99
100
static uint32_t allwinner_sun8i_emac_tx_desc(AwSun8iEmacState *s,
101
- FrameDescriptor *desc,
102
- size_t min_size)
103
+ FrameDescriptor *desc)
104
{
105
- return allwinner_sun8i_emac_get_desc(s, desc, s->tx_desc_head, min_size);
106
+ allwinner_sun8i_emac_get_desc(s, desc, s->tx_desc_curr);
107
+ return s->tx_desc_curr;
108
}
109
110
static void allwinner_sun8i_emac_flush_desc(AwSun8iEmacState *s,
111
@@ -XXX,XX +XXX,XX @@ static ssize_t allwinner_sun8i_emac_receive(NetClientState *nc,
112
bytes_left -= desc_bytes;
113
114
/* Move to the next descriptor */
115
- s->rx_desc_curr = allwinner_sun8i_emac_next_desc(s, &desc, 64);
116
+ s->rx_desc_curr = allwinner_sun8i_emac_find_desc(s, &desc, desc.next,
117
+ AW_SUN8I_EMAC_MIN_PKT_SZ);
118
if (!s->rx_desc_curr) {
119
/* Not enough buffer space available */
120
s->int_sta |= INT_STA_RX_BUF_UA;
121
@@ -XXX,XX +XXX,XX @@ static void allwinner_sun8i_emac_transmit(AwSun8iEmacState *s)
122
size_t transmitted = 0;
123
static uint8_t packet_buf[2048];
124
125
- s->tx_desc_curr = allwinner_sun8i_emac_tx_desc(s, &desc, 0);
126
+ s->tx_desc_curr = allwinner_sun8i_emac_tx_desc(s, &desc);
127
128
/* Read all transmit descriptors */
129
- while (s->tx_desc_curr != 0) {
130
+ while (allwinner_sun8i_emac_desc_owned(&desc, 0)) {
131
132
/* Read from physical memory into packet buffer */
133
bytes = desc.status2 & DESC_STATUS2_BUF_SIZE_MASK;
134
@@ -XXX,XX +XXX,XX @@ static void allwinner_sun8i_emac_transmit(AwSun8iEmacState *s)
135
packet_bytes = 0;
136
transmitted++;
137
}
138
- s->tx_desc_curr = allwinner_sun8i_emac_next_desc(s, &desc, 0);
139
+ s->tx_desc_curr = allwinner_sun8i_emac_next_desc(s, &desc);
140
}
141
142
/* Raise transmit completed interrupt */
143
--
144
2.20.1
145
146
diff view generated by jsdifflib
Deleted patch
1
For a long time now the UI layer has guaranteed that the console
2
surface is always 32 bits per pixel. Remove the legacy dead
3
code from the pl110 display device which was handling the
4
possibility that the console surface was some other format.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
8
Message-id: 20210211141515.8755-2-peter.maydell@linaro.org
9
---
10
hw/display/pl110.c | 53 +++++++---------------------------------------
11
1 file changed, 8 insertions(+), 45 deletions(-)
12
13
diff --git a/hw/display/pl110.c b/hw/display/pl110.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/display/pl110.c
16
+++ b/hw/display/pl110.c
17
@@ -XXX,XX +XXX,XX @@ static const unsigned char *idregs[] = {
18
pl111_id
19
};
20
21
-#define BITS 8
22
-#include "pl110_template.h"
23
-#define BITS 15
24
-#include "pl110_template.h"
25
-#define BITS 16
26
-#include "pl110_template.h"
27
-#define BITS 24
28
-#include "pl110_template.h"
29
#define BITS 32
30
#include "pl110_template.h"
31
32
@@ -XXX,XX +XXX,XX @@ static void pl110_update_display(void *opaque)
33
PL110State *s = (PL110State *)opaque;
34
SysBusDevice *sbd;
35
DisplaySurface *surface = qemu_console_surface(s->con);
36
- drawfn* fntable;
37
drawfn fn;
38
- int dest_width;
39
int src_width;
40
int bpp_offset;
41
int first;
42
@@ -XXX,XX +XXX,XX @@ static void pl110_update_display(void *opaque)
43
44
sbd = SYS_BUS_DEVICE(s);
45
46
- switch (surface_bits_per_pixel(surface)) {
47
- case 0:
48
- return;
49
- case 8:
50
- fntable = pl110_draw_fn_8;
51
- dest_width = 1;
52
- break;
53
- case 15:
54
- fntable = pl110_draw_fn_15;
55
- dest_width = 2;
56
- break;
57
- case 16:
58
- fntable = pl110_draw_fn_16;
59
- dest_width = 2;
60
- break;
61
- case 24:
62
- fntable = pl110_draw_fn_24;
63
- dest_width = 3;
64
- break;
65
- case 32:
66
- fntable = pl110_draw_fn_32;
67
- dest_width = 4;
68
- break;
69
- default:
70
- fprintf(stderr, "pl110: Bad color depth\n");
71
- exit(1);
72
- }
73
if (s->cr & PL110_CR_BGR)
74
bpp_offset = 0;
75
else
76
@@ -XXX,XX +XXX,XX @@ static void pl110_update_display(void *opaque)
77
}
78
}
79
80
- if (s->cr & PL110_CR_BEBO)
81
- fn = fntable[s->bpp + 8 + bpp_offset];
82
- else if (s->cr & PL110_CR_BEPO)
83
- fn = fntable[s->bpp + 16 + bpp_offset];
84
- else
85
- fn = fntable[s->bpp + bpp_offset];
86
+ if (s->cr & PL110_CR_BEBO) {
87
+ fn = pl110_draw_fn_32[s->bpp + 8 + bpp_offset];
88
+ } else if (s->cr & PL110_CR_BEPO) {
89
+ fn = pl110_draw_fn_32[s->bpp + 16 + bpp_offset];
90
+ } else {
91
+ fn = pl110_draw_fn_32[s->bpp + bpp_offset];
92
+ }
93
94
src_width = s->cols;
95
switch (s->bpp) {
96
@@ -XXX,XX +XXX,XX @@ static void pl110_update_display(void *opaque)
97
src_width <<= 2;
98
break;
99
}
100
- dest_width *= s->cols;
101
first = 0;
102
if (s->invalidate) {
103
framebuffer_update_memory_section(&s->fbsection,
104
@@ -XXX,XX +XXX,XX @@ static void pl110_update_display(void *opaque)
105
106
framebuffer_update_display(surface, &s->fbsection,
107
s->cols, s->rows,
108
- src_width, dest_width, 0,
109
+ src_width, s->cols * 4, 0,
110
s->invalidate,
111
fn, s->palette,
112
&first, &last);
113
--
114
2.20.1
115
116
diff view generated by jsdifflib
Deleted patch
1
The pl110_template.h header has a doubly-nested multiple-include pattern:
2
* pl110.c includes it once for each host bit depth (now always 32)
3
* every time it is included, it includes itself 6 times, to account
4
for multiple guest device pixel and byte orders
5
1
6
Now we only have to deal with 32-bit host bit depths, we can move the
7
code corresponding to the outer layer of this double-nesting to be
8
directly in pl110.c and reduce the template header to a single layer
9
of nesting.
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
13
Message-id: 20210211141515.8755-3-peter.maydell@linaro.org
14
---
15
hw/display/pl110_template.h | 100 +-----------------------------------
16
hw/display/pl110.c | 79 ++++++++++++++++++++++++++++
17
2 files changed, 80 insertions(+), 99 deletions(-)
18
19
diff --git a/hw/display/pl110_template.h b/hw/display/pl110_template.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/display/pl110_template.h
22
+++ b/hw/display/pl110_template.h
23
@@ -XXX,XX +XXX,XX @@
24
*/
25
26
#ifndef ORDER
27
-
28
-#if BITS == 8
29
-#define COPY_PIXEL(to, from) *(to++) = from
30
-#elif BITS == 15 || BITS == 16
31
-#define COPY_PIXEL(to, from) do { *(uint16_t *)to = from; to += 2; } while (0)
32
-#elif BITS == 24
33
-#define COPY_PIXEL(to, from) \
34
- do { \
35
- *(to++) = from; \
36
- *(to++) = (from) >> 8; \
37
- *(to++) = (from) >> 16; \
38
- } while (0)
39
-#elif BITS == 32
40
-#define COPY_PIXEL(to, from) do { *(uint32_t *)to = from; to += 4; } while (0)
41
-#else
42
-#error unknown bit depth
43
+#error "pl110_template.h is only for inclusion by pl110.c"
44
#endif
45
46
-#undef RGB
47
-#define BORDER bgr
48
-#define ORDER 0
49
-#include "pl110_template.h"
50
-#define ORDER 1
51
-#include "pl110_template.h"
52
-#define ORDER 2
53
-#include "pl110_template.h"
54
-#undef BORDER
55
-#define RGB
56
-#define BORDER rgb
57
-#define ORDER 0
58
-#include "pl110_template.h"
59
-#define ORDER 1
60
-#include "pl110_template.h"
61
-#define ORDER 2
62
-#include "pl110_template.h"
63
-#undef BORDER
64
-
65
-static drawfn glue(pl110_draw_fn_,BITS)[48] =
66
-{
67
- glue(pl110_draw_line1_lblp_bgr,BITS),
68
- glue(pl110_draw_line2_lblp_bgr,BITS),
69
- glue(pl110_draw_line4_lblp_bgr,BITS),
70
- glue(pl110_draw_line8_lblp_bgr,BITS),
71
- glue(pl110_draw_line16_555_lblp_bgr,BITS),
72
- glue(pl110_draw_line32_lblp_bgr,BITS),
73
- glue(pl110_draw_line16_lblp_bgr,BITS),
74
- glue(pl110_draw_line12_lblp_bgr,BITS),
75
-
76
- glue(pl110_draw_line1_bbbp_bgr,BITS),
77
- glue(pl110_draw_line2_bbbp_bgr,BITS),
78
- glue(pl110_draw_line4_bbbp_bgr,BITS),
79
- glue(pl110_draw_line8_bbbp_bgr,BITS),
80
- glue(pl110_draw_line16_555_bbbp_bgr,BITS),
81
- glue(pl110_draw_line32_bbbp_bgr,BITS),
82
- glue(pl110_draw_line16_bbbp_bgr,BITS),
83
- glue(pl110_draw_line12_bbbp_bgr,BITS),
84
-
85
- glue(pl110_draw_line1_lbbp_bgr,BITS),
86
- glue(pl110_draw_line2_lbbp_bgr,BITS),
87
- glue(pl110_draw_line4_lbbp_bgr,BITS),
88
- glue(pl110_draw_line8_lbbp_bgr,BITS),
89
- glue(pl110_draw_line16_555_lbbp_bgr,BITS),
90
- glue(pl110_draw_line32_lbbp_bgr,BITS),
91
- glue(pl110_draw_line16_lbbp_bgr,BITS),
92
- glue(pl110_draw_line12_lbbp_bgr,BITS),
93
-
94
- glue(pl110_draw_line1_lblp_rgb,BITS),
95
- glue(pl110_draw_line2_lblp_rgb,BITS),
96
- glue(pl110_draw_line4_lblp_rgb,BITS),
97
- glue(pl110_draw_line8_lblp_rgb,BITS),
98
- glue(pl110_draw_line16_555_lblp_rgb,BITS),
99
- glue(pl110_draw_line32_lblp_rgb,BITS),
100
- glue(pl110_draw_line16_lblp_rgb,BITS),
101
- glue(pl110_draw_line12_lblp_rgb,BITS),
102
-
103
- glue(pl110_draw_line1_bbbp_rgb,BITS),
104
- glue(pl110_draw_line2_bbbp_rgb,BITS),
105
- glue(pl110_draw_line4_bbbp_rgb,BITS),
106
- glue(pl110_draw_line8_bbbp_rgb,BITS),
107
- glue(pl110_draw_line16_555_bbbp_rgb,BITS),
108
- glue(pl110_draw_line32_bbbp_rgb,BITS),
109
- glue(pl110_draw_line16_bbbp_rgb,BITS),
110
- glue(pl110_draw_line12_bbbp_rgb,BITS),
111
-
112
- glue(pl110_draw_line1_lbbp_rgb,BITS),
113
- glue(pl110_draw_line2_lbbp_rgb,BITS),
114
- glue(pl110_draw_line4_lbbp_rgb,BITS),
115
- glue(pl110_draw_line8_lbbp_rgb,BITS),
116
- glue(pl110_draw_line16_555_lbbp_rgb,BITS),
117
- glue(pl110_draw_line32_lbbp_rgb,BITS),
118
- glue(pl110_draw_line16_lbbp_rgb,BITS),
119
- glue(pl110_draw_line12_lbbp_rgb,BITS),
120
-};
121
-
122
-#undef BITS
123
-#undef COPY_PIXEL
124
-
125
-#else
126
-
127
#if ORDER == 0
128
#define NAME glue(glue(lblp_, BORDER), BITS)
129
#ifdef HOST_WORDS_BIGENDIAN
130
@@ -XXX,XX +XXX,XX @@ static void glue(pl110_draw_line12_,NAME)(void *opaque, uint8_t *d, const uint8_
131
#undef NAME
132
#undef SWAP_WORDS
133
#undef ORDER
134
-
135
-#endif
136
diff --git a/hw/display/pl110.c b/hw/display/pl110.c
137
index XXXXXXX..XXXXXXX 100644
138
--- a/hw/display/pl110.c
139
+++ b/hw/display/pl110.c
140
@@ -XXX,XX +XXX,XX @@ static const unsigned char *idregs[] = {
141
};
142
143
#define BITS 32
144
+#define COPY_PIXEL(to, from) do { *(uint32_t *)to = from; to += 4; } while (0)
145
+
146
+#undef RGB
147
+#define BORDER bgr
148
+#define ORDER 0
149
#include "pl110_template.h"
150
+#define ORDER 1
151
+#include "pl110_template.h"
152
+#define ORDER 2
153
+#include "pl110_template.h"
154
+#undef BORDER
155
+#define RGB
156
+#define BORDER rgb
157
+#define ORDER 0
158
+#include "pl110_template.h"
159
+#define ORDER 1
160
+#include "pl110_template.h"
161
+#define ORDER 2
162
+#include "pl110_template.h"
163
+#undef BORDER
164
+
165
+static drawfn pl110_draw_fn_32[48] = {
166
+ pl110_draw_line1_lblp_bgr32,
167
+ pl110_draw_line2_lblp_bgr32,
168
+ pl110_draw_line4_lblp_bgr32,
169
+ pl110_draw_line8_lblp_bgr32,
170
+ pl110_draw_line16_555_lblp_bgr32,
171
+ pl110_draw_line32_lblp_bgr32,
172
+ pl110_draw_line16_lblp_bgr32,
173
+ pl110_draw_line12_lblp_bgr32,
174
+
175
+ pl110_draw_line1_bbbp_bgr32,
176
+ pl110_draw_line2_bbbp_bgr32,
177
+ pl110_draw_line4_bbbp_bgr32,
178
+ pl110_draw_line8_bbbp_bgr32,
179
+ pl110_draw_line16_555_bbbp_bgr32,
180
+ pl110_draw_line32_bbbp_bgr32,
181
+ pl110_draw_line16_bbbp_bgr32,
182
+ pl110_draw_line12_bbbp_bgr32,
183
+
184
+ pl110_draw_line1_lbbp_bgr32,
185
+ pl110_draw_line2_lbbp_bgr32,
186
+ pl110_draw_line4_lbbp_bgr32,
187
+ pl110_draw_line8_lbbp_bgr32,
188
+ pl110_draw_line16_555_lbbp_bgr32,
189
+ pl110_draw_line32_lbbp_bgr32,
190
+ pl110_draw_line16_lbbp_bgr32,
191
+ pl110_draw_line12_lbbp_bgr32,
192
+
193
+ pl110_draw_line1_lblp_rgb32,
194
+ pl110_draw_line2_lblp_rgb32,
195
+ pl110_draw_line4_lblp_rgb32,
196
+ pl110_draw_line8_lblp_rgb32,
197
+ pl110_draw_line16_555_lblp_rgb32,
198
+ pl110_draw_line32_lblp_rgb32,
199
+ pl110_draw_line16_lblp_rgb32,
200
+ pl110_draw_line12_lblp_rgb32,
201
+
202
+ pl110_draw_line1_bbbp_rgb32,
203
+ pl110_draw_line2_bbbp_rgb32,
204
+ pl110_draw_line4_bbbp_rgb32,
205
+ pl110_draw_line8_bbbp_rgb32,
206
+ pl110_draw_line16_555_bbbp_rgb32,
207
+ pl110_draw_line32_bbbp_rgb32,
208
+ pl110_draw_line16_bbbp_rgb32,
209
+ pl110_draw_line12_bbbp_rgb32,
210
+
211
+ pl110_draw_line1_lbbp_rgb32,
212
+ pl110_draw_line2_lbbp_rgb32,
213
+ pl110_draw_line4_lbbp_rgb32,
214
+ pl110_draw_line8_lbbp_rgb32,
215
+ pl110_draw_line16_555_lbbp_rgb32,
216
+ pl110_draw_line32_lbbp_rgb32,
217
+ pl110_draw_line16_lbbp_rgb32,
218
+ pl110_draw_line12_lbbp_rgb32,
219
+};
220
+
221
+#undef BITS
222
+#undef COPY_PIXEL
223
+
224
225
static int pl110_enabled(PL110State *s)
226
{
227
--
228
2.20.1
229
230
diff view generated by jsdifflib
Deleted patch
1
For a long time now the UI layer has guaranteed that the console
2
surface is always 32 bits per pixel. Remove the legacy dead code
3
from the pxa2xx_lcd display device which was handling the possibility
4
that the console surface was some other format.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
8
Message-id: 20210211141515.8755-5-peter.maydell@linaro.org
9
---
10
hw/display/pxa2xx_lcd.c | 79 +++++++++--------------------------------
11
1 file changed, 17 insertions(+), 62 deletions(-)
12
13
diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/display/pxa2xx_lcd.c
16
+++ b/hw/display/pxa2xx_lcd.c
17
@@ -XXX,XX +XXX,XX @@ struct PXA2xxLCDState {
18
19
int invalidated;
20
QemuConsole *con;
21
- drawfn *line_fn[2];
22
int dest_width;
23
int xres, yres;
24
int pal_for;
25
@@ -XXX,XX +XXX,XX @@ typedef struct QEMU_PACKED {
26
#define LDCMD_SOFINT    (1 << 22)
27
#define LDCMD_PAL    (1 << 26)
28
29
+#define BITS 32
30
+#include "pxa2xx_template.h"
31
+
32
/* Route internal interrupt lines to the global IC */
33
static void pxa2xx_lcdc_int_update(PXA2xxLCDState *s)
34
{
35
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp)
36
}
37
}
38
39
+static inline drawfn pxa2xx_drawfn(PXA2xxLCDState *s)
40
+{
41
+ if (s->transp) {
42
+ return pxa2xx_draw_fn_32t[s->bpp];
43
+ } else {
44
+ return pxa2xx_draw_fn_32[s->bpp];
45
+ }
46
+}
47
+
48
static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
49
hwaddr addr, int *miny, int *maxy)
50
{
51
DisplaySurface *surface = qemu_console_surface(s->con);
52
int src_width, dest_width;
53
- drawfn fn = NULL;
54
- if (s->dest_width)
55
- fn = s->line_fn[s->transp][s->bpp];
56
+ drawfn fn = pxa2xx_drawfn(s);
57
if (!fn)
58
return;
59
60
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s,
61
{
62
DisplaySurface *surface = qemu_console_surface(s->con);
63
int src_width, dest_width;
64
- drawfn fn = NULL;
65
- if (s->dest_width)
66
- fn = s->line_fn[s->transp][s->bpp];
67
+ drawfn fn = pxa2xx_drawfn(s);
68
if (!fn)
69
return;
70
71
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s,
72
{
73
DisplaySurface *surface = qemu_console_surface(s->con);
74
int src_width, dest_width;
75
- drawfn fn = NULL;
76
- if (s->dest_width) {
77
- fn = s->line_fn[s->transp][s->bpp];
78
- }
79
+ drawfn fn = pxa2xx_drawfn(s);
80
if (!fn) {
81
return;
82
}
83
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s,
84
{
85
DisplaySurface *surface = qemu_console_surface(s->con);
86
int src_width, dest_width;
87
- drawfn fn = NULL;
88
- if (s->dest_width) {
89
- fn = s->line_fn[s->transp][s->bpp];
90
- }
91
+ drawfn fn = pxa2xx_drawfn(s);
92
if (!fn) {
93
return;
94
}
95
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pxa2xx_lcdc = {
96
}
97
};
98
99
-#define BITS 8
100
-#include "pxa2xx_template.h"
101
-#define BITS 15
102
-#include "pxa2xx_template.h"
103
-#define BITS 16
104
-#include "pxa2xx_template.h"
105
-#define BITS 24
106
-#include "pxa2xx_template.h"
107
-#define BITS 32
108
-#include "pxa2xx_template.h"
109
-
110
static const GraphicHwOps pxa2xx_ops = {
111
.invalidate = pxa2xx_invalidate_display,
112
.gfx_update = pxa2xx_update_display,
113
@@ -XXX,XX +XXX,XX @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
114
hwaddr base, qemu_irq irq)
115
{
116
PXA2xxLCDState *s;
117
- DisplaySurface *surface;
118
119
s = (PXA2xxLCDState *) g_malloc0(sizeof(PXA2xxLCDState));
120
s->invalidated = 1;
121
@@ -XXX,XX +XXX,XX @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
122
memory_region_add_subregion(sysmem, base, &s->iomem);
123
124
s->con = graphic_console_init(NULL, 0, &pxa2xx_ops, s);
125
- surface = qemu_console_surface(s->con);
126
-
127
- switch (surface_bits_per_pixel(surface)) {
128
- case 0:
129
- s->dest_width = 0;
130
- break;
131
- case 8:
132
- s->line_fn[0] = pxa2xx_draw_fn_8;
133
- s->line_fn[1] = pxa2xx_draw_fn_8t;
134
- s->dest_width = 1;
135
- break;
136
- case 15:
137
- s->line_fn[0] = pxa2xx_draw_fn_15;
138
- s->line_fn[1] = pxa2xx_draw_fn_15t;
139
- s->dest_width = 2;
140
- break;
141
- case 16:
142
- s->line_fn[0] = pxa2xx_draw_fn_16;
143
- s->line_fn[1] = pxa2xx_draw_fn_16t;
144
- s->dest_width = 2;
145
- break;
146
- case 24:
147
- s->line_fn[0] = pxa2xx_draw_fn_24;
148
- s->line_fn[1] = pxa2xx_draw_fn_24t;
149
- s->dest_width = 3;
150
- break;
151
- case 32:
152
- s->line_fn[0] = pxa2xx_draw_fn_32;
153
- s->line_fn[1] = pxa2xx_draw_fn_32t;
154
- s->dest_width = 4;
155
- break;
156
- default:
157
- fprintf(stderr, "%s: Bad color depth\n", __func__);
158
- exit(1);
159
- }
160
+ s->dest_width = 4;
161
162
vmstate_register(NULL, 0, &vmstate_pxa2xx_lcdc, s);
163
164
--
165
2.20.1
166
167
diff view generated by jsdifflib
Deleted patch
1
Since the dest_width is now always 4 because the output surface is
2
32bpp, we can replace the dest_width state field with a constant.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
6
Message-id: 20210211141515.8755-6-peter.maydell@linaro.org
7
---
8
hw/display/pxa2xx_lcd.c | 20 +++++++++++---------
9
1 file changed, 11 insertions(+), 9 deletions(-)
10
11
diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/display/pxa2xx_lcd.c
14
+++ b/hw/display/pxa2xx_lcd.c
15
@@ -XXX,XX +XXX,XX @@ typedef struct QEMU_PACKED {
16
#define LDCMD_SOFINT    (1 << 22)
17
#define LDCMD_PAL    (1 << 26)
18
19
+/* Size of a pixel in the QEMU UI output surface, in bytes */
20
+#define DEST_PIXEL_WIDTH 4
21
+
22
#define BITS 32
23
#include "pxa2xx_template.h"
24
25
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
26
else if (s->bpp > pxa_lcdc_8bpp)
27
src_width *= 2;
28
29
- dest_width = s->xres * s->dest_width;
30
+ dest_width = s->xres * DEST_PIXEL_WIDTH;
31
*miny = 0;
32
if (s->invalidated) {
33
framebuffer_update_memory_section(&s->fbsection, s->sysmem,
34
addr, s->yres, src_width);
35
}
36
framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
37
- src_width, dest_width, s->dest_width,
38
+ src_width, dest_width, DEST_PIXEL_WIDTH,
39
s->invalidated,
40
fn, s->dma_ch[0].palette, miny, maxy);
41
}
42
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s,
43
else if (s->bpp > pxa_lcdc_8bpp)
44
src_width *= 2;
45
46
- dest_width = s->yres * s->dest_width;
47
+ dest_width = s->yres * DEST_PIXEL_WIDTH;
48
*miny = 0;
49
if (s->invalidated) {
50
framebuffer_update_memory_section(&s->fbsection, s->sysmem,
51
addr, s->yres, src_width);
52
}
53
framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
54
- src_width, s->dest_width, -dest_width,
55
+ src_width, DEST_PIXEL_WIDTH, -dest_width,
56
s->invalidated,
57
fn, s->dma_ch[0].palette,
58
miny, maxy);
59
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s,
60
src_width *= 2;
61
}
62
63
- dest_width = s->xres * s->dest_width;
64
+ dest_width = s->xres * DEST_PIXEL_WIDTH;
65
*miny = 0;
66
if (s->invalidated) {
67
framebuffer_update_memory_section(&s->fbsection, s->sysmem,
68
addr, s->yres, src_width);
69
}
70
framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
71
- src_width, -dest_width, -s->dest_width,
72
+ src_width, -dest_width, -DEST_PIXEL_WIDTH,
73
s->invalidated,
74
fn, s->dma_ch[0].palette, miny, maxy);
75
}
76
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s,
77
src_width *= 2;
78
}
79
80
- dest_width = s->yres * s->dest_width;
81
+ dest_width = s->yres * DEST_PIXEL_WIDTH;
82
*miny = 0;
83
if (s->invalidated) {
84
framebuffer_update_memory_section(&s->fbsection, s->sysmem,
85
addr, s->yres, src_width);
86
}
87
framebuffer_update_display(surface, &s->fbsection, s->xres, s->yres,
88
- src_width, -s->dest_width, dest_width,
89
+ src_width, -DEST_PIXEL_WIDTH, dest_width,
90
s->invalidated,
91
fn, s->dma_ch[0].palette,
92
miny, maxy);
93
@@ -XXX,XX +XXX,XX @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
94
memory_region_add_subregion(sysmem, base, &s->iomem);
95
96
s->con = graphic_console_init(NULL, 0, &pxa2xx_ops, s);
97
- s->dest_width = 4;
98
99
vmstate_register(NULL, 0, &vmstate_pxa2xx_lcdc, s);
100
101
--
102
2.20.1
103
104
diff view generated by jsdifflib
Deleted patch
1
Now that BITS is always 32, expand out all its uses in the template
2
header, including removing now-useless uses of the glue() macro.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
6
Message-id: 20210211141515.8755-7-peter.maydell@linaro.org
7
---
8
hw/display/pxa2xx_template.h | 110 ++++++++++++++---------------------
9
1 file changed, 45 insertions(+), 65 deletions(-)
10
11
diff --git a/hw/display/pxa2xx_template.h b/hw/display/pxa2xx_template.h
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/display/pxa2xx_template.h
14
+++ b/hw/display/pxa2xx_template.h
15
@@ -XXX,XX +XXX,XX @@
16
*/
17
18
# define SKIP_PIXEL(to)        to += deststep
19
-#if BITS == 8
20
-# define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0)
21
-#elif BITS == 15 || BITS == 16
22
-# define COPY_PIXEL(to, from) \
23
- do { \
24
- *(uint16_t *) to = from; \
25
- SKIP_PIXEL(to); \
26
- } while (0)
27
-#elif BITS == 24
28
-# define COPY_PIXEL(to, from) \
29
- do { \
30
- *(uint16_t *) to = from; \
31
- *(to + 2) = (from) >> 16; \
32
- SKIP_PIXEL(to); \
33
- } while (0)
34
-#elif BITS == 32
35
# define COPY_PIXEL(to, from) \
36
do { \
37
*(uint32_t *) to = from; \
38
SKIP_PIXEL(to); \
39
} while (0)
40
-#else
41
-# error unknown bit depth
42
-#endif
43
44
#ifdef HOST_WORDS_BIGENDIAN
45
# define SWAP_WORDS    1
46
@@ -XXX,XX +XXX,XX @@
47
#define FN_2(x)        FN(x + 1) FN(x)
48
#define FN_4(x)        FN_2(x + 2) FN_2(x)
49
50
-static void glue(pxa2xx_draw_line2_, BITS)(void *opaque,
51
+static void pxa2xx_draw_line2(void *opaque,
52
uint8_t *dest, const uint8_t *src, int width, int deststep)
53
{
54
uint32_t *palette = opaque;
55
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line2_, BITS)(void *opaque,
56
}
57
}
58
59
-static void glue(pxa2xx_draw_line4_, BITS)(void *opaque,
60
+static void pxa2xx_draw_line4(void *opaque,
61
uint8_t *dest, const uint8_t *src, int width, int deststep)
62
{
63
uint32_t *palette = opaque;
64
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line4_, BITS)(void *opaque,
65
}
66
}
67
68
-static void glue(pxa2xx_draw_line8_, BITS)(void *opaque,
69
+static void pxa2xx_draw_line8(void *opaque,
70
uint8_t *dest, const uint8_t *src, int width, int deststep)
71
{
72
uint32_t *palette = opaque;
73
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line8_, BITS)(void *opaque,
74
}
75
}
76
77
-static void glue(pxa2xx_draw_line16_, BITS)(void *opaque,
78
+static void pxa2xx_draw_line16(void *opaque,
79
uint8_t *dest, const uint8_t *src, int width, int deststep)
80
{
81
uint32_t data;
82
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line16_, BITS)(void *opaque,
83
data >>= 6;
84
r = (data & 0x1f) << 3;
85
data >>= 5;
86
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
87
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
88
b = (data & 0x1f) << 3;
89
data >>= 5;
90
g = (data & 0x3f) << 2;
91
data >>= 6;
92
r = (data & 0x1f) << 3;
93
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
94
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
95
width -= 2;
96
src += 4;
97
}
98
}
99
100
-static void glue(pxa2xx_draw_line16t_, BITS)(void *opaque,
101
+static void pxa2xx_draw_line16t(void *opaque,
102
uint8_t *dest, const uint8_t *src, int width, int deststep)
103
{
104
uint32_t data;
105
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line16t_, BITS)(void *opaque,
106
if (data & 1)
107
SKIP_PIXEL(dest);
108
else
109
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
110
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
111
data >>= 1;
112
b = (data & 0x1f) << 3;
113
data >>= 5;
114
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line16t_, BITS)(void *opaque,
115
if (data & 1)
116
SKIP_PIXEL(dest);
117
else
118
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
119
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
120
width -= 2;
121
src += 4;
122
}
123
}
124
125
-static void glue(pxa2xx_draw_line18_, BITS)(void *opaque,
126
+static void pxa2xx_draw_line18(void *opaque,
127
uint8_t *dest, const uint8_t *src, int width, int deststep)
128
{
129
uint32_t data;
130
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line18_, BITS)(void *opaque,
131
g = (data & 0x3f) << 2;
132
data >>= 6;
133
r = (data & 0x3f) << 2;
134
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
135
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
136
width -= 1;
137
src += 4;
138
}
139
}
140
141
/* The wicked packed format */
142
-static void glue(pxa2xx_draw_line18p_, BITS)(void *opaque,
143
+static void pxa2xx_draw_line18p(void *opaque,
144
uint8_t *dest, const uint8_t *src, int width, int deststep)
145
{
146
uint32_t data[3];
147
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line18p_, BITS)(void *opaque,
148
data[0] >>= 6;
149
r = (data[0] & 0x3f) << 2;
150
data[0] >>= 12;
151
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
152
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
153
b = (data[0] & 0x3f) << 2;
154
data[0] >>= 6;
155
g = ((data[1] & 0xf) << 4) | (data[0] << 2);
156
data[1] >>= 4;
157
r = (data[1] & 0x3f) << 2;
158
data[1] >>= 12;
159
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
160
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
161
b = (data[1] & 0x3f) << 2;
162
data[1] >>= 6;
163
g = (data[1] & 0x3f) << 2;
164
data[1] >>= 6;
165
r = ((data[2] & 0x3) << 6) | (data[1] << 2);
166
data[2] >>= 8;
167
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
168
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
169
b = (data[2] & 0x3f) << 2;
170
data[2] >>= 6;
171
g = (data[2] & 0x3f) << 2;
172
data[2] >>= 6;
173
r = data[2] << 2;
174
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
175
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
176
width -= 4;
177
}
178
}
179
180
-static void glue(pxa2xx_draw_line19_, BITS)(void *opaque,
181
+static void pxa2xx_draw_line19(void *opaque,
182
uint8_t *dest, const uint8_t *src, int width, int deststep)
183
{
184
uint32_t data;
185
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line19_, BITS)(void *opaque,
186
if (data & 1)
187
SKIP_PIXEL(dest);
188
else
189
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
190
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
191
width -= 1;
192
src += 4;
193
}
194
}
195
196
/* The wicked packed format */
197
-static void glue(pxa2xx_draw_line19p_, BITS)(void *opaque,
198
+static void pxa2xx_draw_line19p(void *opaque,
199
uint8_t *dest, const uint8_t *src, int width, int deststep)
200
{
201
uint32_t data[3];
202
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line19p_, BITS)(void *opaque,
203
if (data[0] & 1)
204
SKIP_PIXEL(dest);
205
else
206
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
207
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
208
data[0] >>= 6;
209
b = (data[0] & 0x3f) << 2;
210
data[0] >>= 6;
211
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line19p_, BITS)(void *opaque,
212
if (data[1] & 1)
213
SKIP_PIXEL(dest);
214
else
215
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
216
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
217
data[1] >>= 6;
218
b = (data[1] & 0x3f) << 2;
219
data[1] >>= 6;
220
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line19p_, BITS)(void *opaque,
221
if (data[2] & 1)
222
SKIP_PIXEL(dest);
223
else
224
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
225
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
226
data[2] >>= 6;
227
b = (data[2] & 0x3f) << 2;
228
data[2] >>= 6;
229
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line19p_, BITS)(void *opaque,
230
if (data[2] & 1)
231
SKIP_PIXEL(dest);
232
else
233
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
234
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
235
width -= 4;
236
}
237
}
238
239
-static void glue(pxa2xx_draw_line24_, BITS)(void *opaque,
240
+static void pxa2xx_draw_line24(void *opaque,
241
uint8_t *dest, const uint8_t *src, int width, int deststep)
242
{
243
uint32_t data;
244
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line24_, BITS)(void *opaque,
245
g = data & 0xff;
246
data >>= 8;
247
r = data & 0xff;
248
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
249
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
250
width -= 1;
251
src += 4;
252
}
253
}
254
255
-static void glue(pxa2xx_draw_line24t_, BITS)(void *opaque,
256
+static void pxa2xx_draw_line24t(void *opaque,
257
uint8_t *dest, const uint8_t *src, int width, int deststep)
258
{
259
uint32_t data;
260
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line24t_, BITS)(void *opaque,
261
if (data & 1)
262
SKIP_PIXEL(dest);
263
else
264
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
265
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
266
width -= 1;
267
src += 4;
268
}
269
}
270
271
-static void glue(pxa2xx_draw_line25_, BITS)(void *opaque,
272
+static void pxa2xx_draw_line25(void *opaque,
273
uint8_t *dest, const uint8_t *src, int width, int deststep)
274
{
275
uint32_t data;
276
@@ -XXX,XX +XXX,XX @@ static void glue(pxa2xx_draw_line25_, BITS)(void *opaque,
277
if (data & 1)
278
SKIP_PIXEL(dest);
279
else
280
- COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b));
281
+ COPY_PIXEL(dest, rgb_to_pixel32(r, g, b));
282
width -= 1;
283
src += 4;
284
}
285
}
286
287
/* Overlay planes disabled, no transparency */
288
-static drawfn glue(pxa2xx_draw_fn_, BITS)[16] =
289
+static drawfn pxa2xx_draw_fn_32[16] =
290
{
291
[0 ... 0xf] = NULL,
292
- [pxa_lcdc_2bpp] = glue(pxa2xx_draw_line2_, BITS),
293
- [pxa_lcdc_4bpp] = glue(pxa2xx_draw_line4_, BITS),
294
- [pxa_lcdc_8bpp] = glue(pxa2xx_draw_line8_, BITS),
295
- [pxa_lcdc_16bpp] = glue(pxa2xx_draw_line16_, BITS),
296
- [pxa_lcdc_18bpp] = glue(pxa2xx_draw_line18_, BITS),
297
- [pxa_lcdc_18pbpp] = glue(pxa2xx_draw_line18p_, BITS),
298
- [pxa_lcdc_24bpp] = glue(pxa2xx_draw_line24_, BITS),
299
+ [pxa_lcdc_2bpp] = pxa2xx_draw_line2,
300
+ [pxa_lcdc_4bpp] = pxa2xx_draw_line4,
301
+ [pxa_lcdc_8bpp] = pxa2xx_draw_line8,
302
+ [pxa_lcdc_16bpp] = pxa2xx_draw_line16,
303
+ [pxa_lcdc_18bpp] = pxa2xx_draw_line18,
304
+ [pxa_lcdc_18pbpp] = pxa2xx_draw_line18p,
305
+ [pxa_lcdc_24bpp] = pxa2xx_draw_line24,
306
};
307
308
/* Overlay planes enabled, transparency used */
309
-static drawfn glue(glue(pxa2xx_draw_fn_, BITS), t)[16] =
310
+static drawfn pxa2xx_draw_fn_32t[16] =
311
{
312
[0 ... 0xf] = NULL,
313
- [pxa_lcdc_4bpp] = glue(pxa2xx_draw_line4_, BITS),
314
- [pxa_lcdc_8bpp] = glue(pxa2xx_draw_line8_, BITS),
315
- [pxa_lcdc_16bpp] = glue(pxa2xx_draw_line16t_, BITS),
316
- [pxa_lcdc_19bpp] = glue(pxa2xx_draw_line19_, BITS),
317
- [pxa_lcdc_19pbpp] = glue(pxa2xx_draw_line19p_, BITS),
318
- [pxa_lcdc_24bpp] = glue(pxa2xx_draw_line24t_, BITS),
319
- [pxa_lcdc_25bpp] = glue(pxa2xx_draw_line25_, BITS),
320
+ [pxa_lcdc_4bpp] = pxa2xx_draw_line4,
321
+ [pxa_lcdc_8bpp] = pxa2xx_draw_line8,
322
+ [pxa_lcdc_16bpp] = pxa2xx_draw_line16t,
323
+ [pxa_lcdc_19bpp] = pxa2xx_draw_line19,
324
+ [pxa_lcdc_19pbpp] = pxa2xx_draw_line19p,
325
+ [pxa_lcdc_24bpp] = pxa2xx_draw_line24t,
326
+ [pxa_lcdc_25bpp] = pxa2xx_draw_line25,
327
};
328
329
-#undef BITS
330
#undef COPY_PIXEL
331
#undef SKIP_PIXEL
332
333
--
334
2.20.1
335
336
diff view generated by jsdifflib