1
target-arm queue. The big thing here is the landing of the 3-phase
1
arm queue; dunno if this will be the last before softfreeze
2
reset patches...
2
or not, but anyway probably the last large one. New orangepi-pc
3
board model is the big item here.
3
4
5
thanks
4
-- PMM
6
-- PMM
5
7
6
The following changes since commit 204aa60b37c23a89e690d418f49787d274303ca7:
8
The following changes since commit 67d9ef7d541c3d21a25796c51c26da096a433565:
7
9
8
Merge remote-tracking branch 'remotes/amarkovic/tags/mips-queue-jan-29-2020' into staging (2020-01-30 14:18:45 +0000)
10
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-docs-20200312' into staging (2020-03-12 15:20:52 +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-20200130
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200312
13
15
14
for you to fetch changes up to dea101a1ae9968c9fec6ab0291489dad7c49f36f:
16
for you to fetch changes up to aca53be34ac3e7cac5f39396a51a338860a5a837:
15
17
16
target/arm/cpu: Add the kvm-no-adjvtime CPU property (2020-01-30 16:02:06 +0000)
18
target/arm: kvm: Inject events at the last stage of sync (2020-03-12 16:31:10 +0000)
17
19
18
----------------------------------------------------------------
20
----------------------------------------------------------------
19
target-arm queue:
21
target-arm queue:
20
* hw/core/or-irq: Fix incorrect assert forbidding num-lines == MAX_OR_LINES
22
* Fix various bugs that might result in an assert() due to
21
* target/arm/arm-semi: Don't let the guest close stdin/stdout/stderr
23
incorrect hflags for M-profile CPUs
22
* aspeed: some minor bugfixes
24
* Fix Aspeed SMC Controller user-mode select handling
23
* aspeed: add eMMC controller model for AST2600 SoC
25
* Report correct (with-tag) address in fault address register
24
* hw/arm/raspi: Remove obsolete use of -smp to set the soc 'enabled-cpus'
26
when TBI is enabled
25
* New 3-phase reset API for device models
27
* cubieboard: make sure SOC object isn't leaked
26
* hw/intc/arm_gicv3_kvm: Stop wrongly programming GICR_PENDBASER.PTZ bit
28
* fsl-imx25: Wire up eSDHC controllers
27
* Arm KVM: stop/restart the guest counter when the VM is stopped and started
29
* fsl-imx25: Wire up USB controllers
30
* New board model: orangepi-pc (OrangePi PC)
31
* ARM/KVM: if user doesn't select GIC version and the
32
host kernel can only provide GICv3, use that, rather
33
than defaulting to "fail because GICv2 isn't possible"
34
* kvm: Only do KVM_SET_VCPU_EVENTS at the last stage of sync
28
35
29
----------------------------------------------------------------
36
----------------------------------------------------------------
30
Andrew Jeffery (2):
37
Beata Michalska (1):
31
hw/sd: Configure number of slots exposed by the ASPEED SDHCI model
38
target/arm: kvm: Inject events at the last stage of sync
32
hw/arm: ast2600: Wire up the eMMC controller
33
34
Andrew Jones (6):
35
target/arm/kvm: trivial: Clean up header documentation
36
hw/arm/virt: Add missing 5.0 options call to 4.2 options
37
target/arm/kvm64: kvm64 cpus have timer registers
38
tests/arm-cpu-features: Check feature default values
39
target/arm/kvm: Implement virtual time adjustment
40
target/arm/cpu: Add the kvm-no-adjvtime CPU property
41
39
42
Cédric Le Goater (2):
40
Cédric Le Goater (2):
43
ftgmac100: check RX and TX buffer alignment
41
aspeed/smc: Add some tracing
44
hw/arm/aspeed: add a 'execute-in-place' property to boot directly from CE0
42
aspeed/smc: Fix User mode select/unselect scheme
45
43
46
Damien Hedde (11):
44
Eric Auger (6):
47
add device_legacy_reset function to prepare for reset api change
45
hw/arm/virt: Document 'max' value in gic-version property description
48
hw/core/qdev: add trace events to help with resettable transition
46
hw/arm/virt: Introduce VirtGICType enum type
49
hw/core: create Resettable QOM interface
47
hw/arm/virt: Introduce finalize_gic_version()
50
hw/core: add Resettable support to BusClass and DeviceClass
48
target/arm/kvm: Let kvm_arm_vgic_probe() return a bitmap
51
hw/core/resettable: add support for changing parent
49
hw/arm/virt: kvm: Restructure finalize_gic_version()
52
hw/core/qdev: handle parent bus change regarding resettable
50
hw/arm/virt: kvm: allow gicv3 by default if v2 cannot work
53
hw/core/qdev: update hotplug reset regarding resettable
54
hw/core: deprecate old reset functions and introduce new ones
55
docs/devel/reset.rst: add doc about Resettable interface
56
vl: replace deprecated qbus_reset_all registration
57
hw/s390x/ipl: replace deprecated qdev_reset_all registration
58
51
59
Joel Stanley (1):
52
Guenter Roeck (2):
60
misc/pca9552: Add qom set and get
53
hw/arm/fsl-imx25: Wire up eSDHC controllers
54
hw/arm/fsl-imx25: Wire up USB controllers
61
55
62
Peter Maydell (2):
56
Igor Mammedov (1):
63
hw/core/or-irq: Fix incorrect assert forbidding num-lines == MAX_OR_LINES
57
hw/arm/cubieboard: make sure SOC object isn't leaked
64
target/arm/arm-semi: Don't let the guest close stdin/stdout/stderr
65
58
66
Philippe Mathieu-Daudé (1):
59
Niek Linnenbank (13):
67
hw/arm/raspi: Remove obsolete use of -smp to set the soc 'enabled-cpus'
60
hw/arm: add Allwinner H3 System-on-Chip
61
hw/arm: add Xunlong Orange Pi PC machine
62
hw/arm/allwinner-h3: add Clock Control Unit
63
hw/arm/allwinner-h3: add USB host controller
64
hw/arm/allwinner-h3: add System Control module
65
hw/arm/allwinner: add CPU Configuration module
66
hw/arm/allwinner: add Security Identifier device
67
hw/arm/allwinner: add SD/MMC host controller
68
hw/arm/allwinner-h3: add EMAC ethernet device
69
hw/arm/allwinner-h3: add Boot ROM support
70
hw/arm/allwinner-h3: add SDRAM controller device
71
hw/arm/allwinner: add RTC device support
72
docs: add Orange Pi PC document
68
73
69
Zenghui Yu (1):
74
Peter Maydell (4):
70
hw/intc/arm_gicv3_kvm: Stop wrongly programming GICR_PENDBASER.PTZ bit
75
hw/intc/armv7m_nvic: Rebuild hflags on reset
76
target/arm: Update hflags in trans_CPS_v7m()
77
target/arm: Recalculate hflags correctly after writes to CONTROL
78
target/arm: Fix some comment typos
71
79
72
hw/core/Makefile.objs | 1 +
80
Philippe Mathieu-Daudé (5):
73
tests/Makefile.include | 1 +
81
tests/boot_linux_console: Add a quick test for the OrangePi PC board
74
include/hw/arm/aspeed.h | 2 +
82
tests/boot_linux_console: Add initrd test for the Orange Pi PC board
75
include/hw/arm/aspeed_soc.h | 2 +
83
tests/boot_linux_console: Add a SD card test for the OrangePi PC board
76
include/hw/arm/virt.h | 1 +
84
tests/boot_linux_console: Add a SLOW test booting Ubuntu on OrangePi PC
77
include/hw/qdev-core.h | 58 +++++++-
85
tests/boot_linux_console: Test booting NetBSD via U-Boot on OrangePi PC
78
include/hw/resettable.h | 247 +++++++++++++++++++++++++++++++++
79
include/hw/sd/aspeed_sdhci.h | 1 +
80
target/arm/cpu.h | 7 +
81
target/arm/kvm_arm.h | 95 ++++++++++---
82
hw/arm/aspeed.c | 72 ++++++++--
83
hw/arm/aspeed_ast2600.c | 31 ++++-
84
hw/arm/aspeed_soc.c | 2 +
85
hw/arm/raspi.c | 2 -
86
hw/arm/virt.c | 9 ++
87
hw/audio/intel-hda.c | 2 +-
88
hw/core/bus.c | 102 ++++++++++++++
89
hw/core/or-irq.c | 2 +-
90
hw/core/qdev.c | 160 ++++++++++++++++++++--
91
hw/core/resettable.c | 301 +++++++++++++++++++++++++++++++++++++++++
92
hw/hyperv/hyperv.c | 2 +-
93
hw/i386/microvm.c | 2 +-
94
hw/i386/pc.c | 2 +-
95
hw/ide/microdrive.c | 8 +-
96
hw/intc/arm_gicv3_kvm.c | 11 +-
97
hw/intc/spapr_xive.c | 2 +-
98
hw/misc/pca9552.c | 90 ++++++++++++
99
hw/net/ftgmac100.c | 13 ++
100
hw/ppc/pnv_psi.c | 4 +-
101
hw/ppc/spapr_pci.c | 2 +-
102
hw/ppc/spapr_vio.c | 2 +-
103
hw/s390x/ipl.c | 10 +-
104
hw/s390x/s390-pci-inst.c | 2 +-
105
hw/scsi/vmw_pvscsi.c | 2 +-
106
hw/sd/aspeed_sdhci.c | 11 +-
107
hw/sd/omap_mmc.c | 2 +-
108
hw/sd/pl181.c | 2 +-
109
target/arm/arm-semi.c | 9 ++
110
target/arm/cpu.c | 2 +
111
target/arm/cpu64.c | 1 +
112
target/arm/kvm.c | 120 ++++++++++++++++
113
target/arm/kvm32.c | 3 +
114
target/arm/kvm64.c | 4 +
115
target/arm/machine.c | 7 +
116
target/arm/monitor.c | 1 +
117
tests/qtest/arm-cpu-features.c | 41 ++++--
118
vl.c | 10 +-
119
docs/arm-cpu-features.rst | 37 ++++-
120
docs/devel/index.rst | 1 +
121
docs/devel/reset.rst | 289 +++++++++++++++++++++++++++++++++++++++
122
hw/core/trace-events | 27 ++++
123
51 files changed, 1727 insertions(+), 90 deletions(-)
124
create mode 100644 include/hw/resettable.h
125
create mode 100644 hw/core/resettable.c
126
create mode 100644 docs/devel/reset.rst
127
86
87
Richard Henderson (2):
88
target/arm: Check addresses for disabled regimes
89
target/arm: Disable clean_data_tbi for system mode
90
91
Makefile.objs | 1 +
92
hw/arm/Makefile.objs | 1 +
93
hw/misc/Makefile.objs | 5 +
94
hw/net/Makefile.objs | 1 +
95
hw/rtc/Makefile.objs | 1 +
96
hw/sd/Makefile.objs | 1 +
97
hw/usb/hcd-ehci.h | 1 +
98
include/hw/arm/allwinner-a10.h | 4 +
99
include/hw/arm/allwinner-h3.h | 161 ++++++
100
include/hw/arm/fsl-imx25.h | 18 +
101
include/hw/arm/virt.h | 12 +-
102
include/hw/misc/allwinner-cpucfg.h | 52 ++
103
include/hw/misc/allwinner-h3-ccu.h | 66 +++
104
include/hw/misc/allwinner-h3-dramc.h | 106 ++++
105
include/hw/misc/allwinner-h3-sysctrl.h | 67 +++
106
include/hw/misc/allwinner-sid.h | 60 +++
107
include/hw/net/allwinner-sun8i-emac.h | 99 ++++
108
include/hw/rtc/allwinner-rtc.h | 134 +++++
109
include/hw/sd/allwinner-sdhost.h | 135 +++++
110
target/arm/helper.h | 1 +
111
target/arm/kvm_arm.h | 3 +
112
hw/arm/allwinner-a10.c | 19 +
113
hw/arm/allwinner-h3.c | 465 ++++++++++++++++++
114
hw/arm/cubieboard.c | 18 +
115
hw/arm/fsl-imx25.c | 56 +++
116
hw/arm/imx25_pdk.c | 16 +
117
hw/arm/orangepi.c | 130 +++++
118
hw/arm/virt.c | 145 ++++--
119
hw/intc/armv7m_nvic.c | 6 +
120
hw/misc/allwinner-cpucfg.c | 282 +++++++++++
121
hw/misc/allwinner-h3-ccu.c | 242 +++++++++
122
hw/misc/allwinner-h3-dramc.c | 358 ++++++++++++++
123
hw/misc/allwinner-h3-sysctrl.c | 140 ++++++
124
hw/misc/allwinner-sid.c | 168 +++++++
125
hw/net/allwinner-sun8i-emac.c | 871 +++++++++++++++++++++++++++++++++
126
hw/rtc/allwinner-rtc.c | 411 ++++++++++++++++
127
hw/sd/allwinner-sdhost.c | 854 ++++++++++++++++++++++++++++++++
128
hw/ssi/aspeed_smc.c | 56 ++-
129
hw/usb/hcd-ehci-sysbus.c | 17 +
130
target/arm/helper.c | 49 +-
131
target/arm/kvm.c | 14 +-
132
target/arm/kvm32.c | 15 +-
133
target/arm/kvm64.c | 15 +-
134
target/arm/translate-a64.c | 11 +
135
target/arm/translate.c | 14 +-
136
MAINTAINERS | 9 +
137
default-configs/arm-softmmu.mak | 1 +
138
docs/system/arm/orangepi.rst | 253 ++++++++++
139
docs/system/target-arm.rst | 2 +
140
hw/arm/Kconfig | 12 +
141
hw/misc/trace-events | 19 +
142
hw/net/Kconfig | 3 +
143
hw/net/trace-events | 10 +
144
hw/rtc/trace-events | 4 +
145
hw/sd/trace-events | 7 +
146
hw/ssi/trace-events | 10 +
147
tests/acceptance/boot_linux_console.py | 230 +++++++++
148
57 files changed, 5787 insertions(+), 74 deletions(-)
149
create mode 100644 include/hw/arm/allwinner-h3.h
150
create mode 100644 include/hw/misc/allwinner-cpucfg.h
151
create mode 100644 include/hw/misc/allwinner-h3-ccu.h
152
create mode 100644 include/hw/misc/allwinner-h3-dramc.h
153
create mode 100644 include/hw/misc/allwinner-h3-sysctrl.h
154
create mode 100644 include/hw/misc/allwinner-sid.h
155
create mode 100644 include/hw/net/allwinner-sun8i-emac.h
156
create mode 100644 include/hw/rtc/allwinner-rtc.h
157
create mode 100644 include/hw/sd/allwinner-sdhost.h
158
create mode 100644 hw/arm/allwinner-h3.c
159
create mode 100644 hw/arm/orangepi.c
160
create mode 100644 hw/misc/allwinner-cpucfg.c
161
create mode 100644 hw/misc/allwinner-h3-ccu.c
162
create mode 100644 hw/misc/allwinner-h3-dramc.c
163
create mode 100644 hw/misc/allwinner-h3-sysctrl.c
164
create mode 100644 hw/misc/allwinner-sid.c
165
create mode 100644 hw/net/allwinner-sun8i-emac.c
166
create mode 100644 hw/rtc/allwinner-rtc.c
167
create mode 100644 hw/sd/allwinner-sdhost.c
168
create mode 100644 docs/system/arm/orangepi.rst
169
create mode 100644 hw/ssi/trace-events
170
diff view generated by jsdifflib
New patch
1
Some of an M-profile CPU's cached hflags state depends on state that's
2
in our NVIC object. We already do an hflags rebuild when the NVIC
3
registers are written, but we also need to do this on NVIC reset,
4
because there's no guarantee that this will happen before the
5
CPU reset.
1
6
7
This fixes an assertion due to mismatched hflags which happens if
8
the CPU is reset from inside a HardFault handler.
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20200303174950.3298-2-peter.maydell@linaro.org
13
---
14
hw/intc/armv7m_nvic.c | 6 ++++++
15
1 file changed, 6 insertions(+)
16
17
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/intc/armv7m_nvic.c
20
+++ b/hw/intc/armv7m_nvic.c
21
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_reset(DeviceState *dev)
22
s->itns[i] = true;
23
}
24
}
25
+
26
+ /*
27
+ * We updated state that affects the CPU's MMUidx and thus its hflags;
28
+ * and we can't guarantee that we run before the CPU reset function.
29
+ */
30
+ arm_rebuild_hflags(&s->cpu->env);
31
}
32
33
static void nvic_systick_trigger(void *opaque, int n, int level)
34
--
35
2.20.1
36
37
diff view generated by jsdifflib
New patch
1
For M-profile CPUs, the FAULTMASK value affects the CPU's MMU index
2
(it changes the NegPri bit). We update the hflags after calls
3
to the v7m_msr helper in trans_MSR_v7m() but forgot to do so
4
in trans_CPS_v7m().
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200303174950.3298-3-peter.maydell@linaro.org
9
---
10
target/arm/translate.c | 5 ++++-
11
1 file changed, 4 insertions(+), 1 deletion(-)
12
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate.c
16
+++ b/target/arm/translate.c
17
@@ -XXX,XX +XXX,XX @@ static bool trans_CPS(DisasContext *s, arg_CPS *a)
18
19
static bool trans_CPS_v7m(DisasContext *s, arg_CPS_v7m *a)
20
{
21
- TCGv_i32 tmp, addr;
22
+ TCGv_i32 tmp, addr, el;
23
24
if (!arm_dc_feature(s, ARM_FEATURE_M)) {
25
return false;
26
@@ -XXX,XX +XXX,XX @@ static bool trans_CPS_v7m(DisasContext *s, arg_CPS_v7m *a)
27
gen_helper_v7m_msr(cpu_env, addr, tmp);
28
tcg_temp_free_i32(addr);
29
}
30
+ el = tcg_const_i32(s->current_el);
31
+ gen_helper_rebuild_hflags_m32(cpu_env, el);
32
+ tcg_temp_free_i32(el);
33
tcg_temp_free_i32(tmp);
34
gen_lookup_tb(s);
35
return true;
36
--
37
2.20.1
38
39
diff view generated by jsdifflib
1
The num-lines property of the TYPE_OR_GATE device sets the number
1
A write to the CONTROL register can change our current EL (by
2
of input lines it has. An assert() in or_irq_realize() restricts
2
writing to the nPRIV bit). That means that we can't assume
3
this to the maximum supported by the implementation. However we
3
that s->current_el is still valid in trans_MSR_v7m() when
4
got the condition in the assert wrong: it should be using <=,
4
we try to rebuild the hflags.
5
because num-lines == MAX_OR_LINES is permitted, and means that
6
all entries from 0 to MAX_OR_LINES-1 in the s->levels[] array
7
are used.
8
5
9
We didn't notice this previously because no user has so far
6
Add a new helper rebuild_hflags_m32_newel() which, like the
10
needed that many input lines.
7
existing rebuild_hflags_a32_newel(), recalculates the current
8
EL from scratch, and use it in trans_MSR_v7m().
11
9
12
Reported-by: Guenter Roeck <linux@roeck-us.net>
10
This fixes an assertion about an hflags mismatch when the
11
guest changes privilege by writing to CONTROL.
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
15
Message-id: 20200303174950.3298-4-peter.maydell@linaro.org
16
Message-id: 20200120142235.10432-1-peter.maydell@linaro.org
17
---
16
---
18
hw/core/or-irq.c | 2 +-
17
target/arm/helper.h | 1 +
19
1 file changed, 1 insertion(+), 1 deletion(-)
18
target/arm/helper.c | 12 ++++++++++++
19
target/arm/translate.c | 7 +++----
20
3 files changed, 16 insertions(+), 4 deletions(-)
20
21
21
diff --git a/hw/core/or-irq.c b/hw/core/or-irq.c
22
diff --git a/target/arm/helper.h b/target/arm/helper.h
22
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/core/or-irq.c
24
--- a/target/arm/helper.h
24
+++ b/hw/core/or-irq.c
25
+++ b/target/arm/helper.h
25
@@ -XXX,XX +XXX,XX @@ static void or_irq_realize(DeviceState *dev, Error **errp)
26
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_4(msr_banked, void, env, i32, i32, i32)
27
DEF_HELPER_2(get_user_reg, i32, env, i32)
28
DEF_HELPER_3(set_user_reg, void, env, i32, i32)
29
30
+DEF_HELPER_FLAGS_1(rebuild_hflags_m32_newel, TCG_CALL_NO_RWG, void, env)
31
DEF_HELPER_FLAGS_2(rebuild_hflags_m32, TCG_CALL_NO_RWG, void, env, int)
32
DEF_HELPER_FLAGS_1(rebuild_hflags_a32_newel, TCG_CALL_NO_RWG, void, env)
33
DEF_HELPER_FLAGS_2(rebuild_hflags_a32, TCG_CALL_NO_RWG, void, env, int)
34
diff --git a/target/arm/helper.c b/target/arm/helper.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/helper.c
37
+++ b/target/arm/helper.c
38
@@ -XXX,XX +XXX,XX @@ void arm_rebuild_hflags(CPUARMState *env)
39
env->hflags = rebuild_hflags_internal(env);
40
}
41
42
+/*
43
+ * If we have triggered a EL state change we can't rely on the
44
+ * translator having passed it to us, we need to recompute.
45
+ */
46
+void HELPER(rebuild_hflags_m32_newel)(CPUARMState *env)
47
+{
48
+ int el = arm_current_el(env);
49
+ int fp_el = fp_exception_el(env, el);
50
+ ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
51
+ env->hflags = rebuild_hflags_m32(env, fp_el, mmu_idx);
52
+}
53
+
54
void HELPER(rebuild_hflags_m32)(CPUARMState *env, int el)
26
{
55
{
27
qemu_or_irq *s = OR_IRQ(dev);
56
int fp_el = fp_exception_el(env, el);
28
57
diff --git a/target/arm/translate.c b/target/arm/translate.c
29
- assert(s->num_lines < MAX_OR_LINES);
58
index XXXXXXX..XXXXXXX 100644
30
+ assert(s->num_lines <= MAX_OR_LINES);
59
--- a/target/arm/translate.c
31
60
+++ b/target/arm/translate.c
32
qdev_init_gpio_in(dev, or_irq_handler, s->num_lines);
61
@@ -XXX,XX +XXX,XX @@ static bool trans_MRS_v7m(DisasContext *s, arg_MRS_v7m *a)
62
63
static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a)
64
{
65
- TCGv_i32 addr, reg, el;
66
+ TCGv_i32 addr, reg;
67
68
if (!arm_dc_feature(s, ARM_FEATURE_M)) {
69
return false;
70
@@ -XXX,XX +XXX,XX @@ static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a)
71
gen_helper_v7m_msr(cpu_env, addr, reg);
72
tcg_temp_free_i32(addr);
73
tcg_temp_free_i32(reg);
74
- el = tcg_const_i32(s->current_el);
75
- gen_helper_rebuild_hflags_m32(cpu_env, el);
76
- tcg_temp_free_i32(el);
77
+ /* If we wrote to CONTROL, the EL might have changed */
78
+ gen_helper_rebuild_hflags_m32_newel(cpu_env);
79
gen_lookup_tb(s);
80
return true;
33
}
81
}
34
--
82
--
35
2.20.1
83
2.20.1
36
84
37
85
diff view generated by jsdifflib
New patch
1
Fix a couple of comment typos.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20200303174950.3298-5-peter.maydell@linaro.org
6
---
7
target/arm/helper.c | 2 +-
8
target/arm/translate.c | 2 +-
9
2 files changed, 2 insertions(+), 2 deletions(-)
10
11
diff --git a/target/arm/helper.c b/target/arm/helper.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/helper.c
14
+++ b/target/arm/helper.c
15
@@ -XXX,XX +XXX,XX @@ void HELPER(rebuild_hflags_m32)(CPUARMState *env, int el)
16
17
/*
18
* If we have triggered a EL state change we can't rely on the
19
- * translator having passed it too us, we need to recompute.
20
+ * translator having passed it to us, we need to recompute.
21
*/
22
void HELPER(rebuild_hflags_a32_newel)(CPUARMState *env)
23
{
24
diff --git a/target/arm/translate.c b/target/arm/translate.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/translate.c
27
+++ b/target/arm/translate.c
28
@@ -XXX,XX +XXX,XX @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
29
30
if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
31
/*
32
- * A write to any coprocessor regiser that ends a TB
33
+ * A write to any coprocessor register that ends a TB
34
* must rebuild the hflags for the next TB.
35
*/
36
TCGv_i32 tcg_el = tcg_const_i32(s->current_el);
37
--
38
2.20.1
39
40
diff view generated by jsdifflib
1
From: Cédric Le Goater <clg@kaod.org>
1
From: Cédric Le Goater <clg@kaod.org>
2
2
3
The overhead for the OpenBMC firmware images using the a custom U-Boot
4
is around 2 seconds, which is fine, but with a U-Boot from mainline,
5
it takes an extra 50 seconds or so to reach Linux. A quick survey on
6
the number of reads performed on the flash memory region gives the
7
following figures :
8
9
OpenBMC U-Boot 922478 (~ 3.5 MBytes)
10
Mainline U-Boot 20569977 (~ 80 MBytes)
11
12
QEMU must be trashing the TCG TBs and reloading text very often. Some
13
addresses are read more than 250.000 times. Until we find a solution
14
to improve boot time, execution from MMIO is not activated by default.
15
16
Setting this option also breaks migration compatibility.
17
18
Signed-off-by: Cédric Le Goater <clg@kaod.org>
3
Signed-off-by: Cédric Le Goater <clg@kaod.org>
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
5
Reviewed-by: Joel Stanley <joel@jms.id.au>
20
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
21
Message-id: 20200114103433.30534-5-clg@kaod.org
7
Message-id: 20200206112645.21275-2-clg@kaod.org
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
9
---
24
include/hw/arm/aspeed.h | 2 ++
10
Makefile.objs | 1 +
25
hw/arm/aspeed.c | 44 ++++++++++++++++++++++++++++++++++++-----
11
hw/ssi/aspeed_smc.c | 17 +++++++++++++++++
26
2 files changed, 41 insertions(+), 5 deletions(-)
12
hw/ssi/trace-events | 9 +++++++++
13
3 files changed, 27 insertions(+)
14
create mode 100644 hw/ssi/trace-events
27
15
28
diff --git a/include/hw/arm/aspeed.h b/include/hw/arm/aspeed.h
16
diff --git a/Makefile.objs b/Makefile.objs
29
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
30
--- a/include/hw/arm/aspeed.h
18
--- a/Makefile.objs
31
+++ b/include/hw/arm/aspeed.h
19
+++ b/Makefile.objs
32
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedBoardState AspeedBoardState;
20
@@ -XXX,XX +XXX,XX @@ trace-events-subdirs += hw/scsi
33
21
trace-events-subdirs += hw/sd
34
typedef struct AspeedMachine {
22
trace-events-subdirs += hw/sparc
35
MachineState parent_obj;
23
trace-events-subdirs += hw/sparc64
24
+trace-events-subdirs += hw/ssi
25
trace-events-subdirs += hw/timer
26
trace-events-subdirs += hw/tpm
27
trace-events-subdirs += hw/usb
28
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/ssi/aspeed_smc.c
31
+++ b/hw/ssi/aspeed_smc.c
32
@@ -XXX,XX +XXX,XX @@
33
#include "qapi/error.h"
34
#include "exec/address-spaces.h"
35
#include "qemu/units.h"
36
+#include "trace.h"
37
38
#include "hw/irq.h"
39
#include "hw/qdev-properties.h"
40
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_flash_set_segment(AspeedSMCState *s, int cs,
41
42
s->ctrl->reg_to_segment(s, new, &seg);
43
44
+ trace_aspeed_smc_flash_set_segment(cs, new, seg.addr, seg.addr + seg.size);
36
+
45
+
37
+ bool mmio_exec;
46
/* The start address of CS0 is read-only */
38
} AspeedMachine;
47
if (cs == 0 && seg.addr != s->ctrl->flash_window_base) {
39
48
qemu_log_mask(LOG_GUEST_ERROR,
40
#define ASPEED_MACHINE_CLASS(klass) \
49
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_smc_flash_read(void *opaque, hwaddr addr, unsigned size)
41
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
50
__func__, aspeed_smc_flash_mode(fl));
42
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/arm/aspeed.c
44
+++ b/hw/arm/aspeed.c
45
@@ -XXX,XX +XXX,XX @@ static void aspeed_machine_init(MachineState *machine)
46
* SoC and 128MB for the AST2500 SoC, which is twice as big as
47
* needed by the flash modules of the Aspeed machines.
48
*/
49
- memory_region_init_rom(boot_rom, OBJECT(bmc), "aspeed.boot_rom",
50
- fl->size, &error_abort);
51
- memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR,
52
- boot_rom);
53
- write_boot_rom(drive0, FIRMWARE_ADDR, fl->size, &error_abort);
54
+ if (ASPEED_MACHINE(machine)->mmio_exec) {
55
+ memory_region_init_alias(boot_rom, OBJECT(bmc), "aspeed.boot_rom",
56
+ &fl->mmio, 0, fl->size);
57
+ memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR,
58
+ boot_rom);
59
+ } else {
60
+ memory_region_init_rom(boot_rom, OBJECT(bmc), "aspeed.boot_rom",
61
+ fl->size, &error_abort);
62
+ memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR,
63
+ boot_rom);
64
+ write_boot_rom(drive0, FIRMWARE_ADDR, fl->size, &error_abort);
65
+ }
66
}
51
}
67
52
68
aspeed_board_binfo.ram_size = ram_size;
53
+ trace_aspeed_smc_flash_read(fl->id, addr, size, ret,
69
@@ -XXX,XX +XXX,XX @@ static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
54
+ aspeed_smc_flash_mode(fl));
70
/* Bus 11: TODO ucd90160@64 */
55
return ret;
71
}
56
}
72
57
73
+static bool aspeed_get_mmio_exec(Object *obj, Error **errp)
58
@@ -XXX,XX +XXX,XX @@ static bool aspeed_smc_do_snoop(AspeedSMCFlash *fl, uint64_t data,
74
+{
59
AspeedSMCState *s = fl->controller;
75
+ return ASPEED_MACHINE(obj)->mmio_exec;
60
uint8_t addr_width = aspeed_smc_flash_is_4byte(fl) ? 4 : 3;
76
+}
61
62
+ trace_aspeed_smc_do_snoop(fl->id, s->snoop_index, s->snoop_dummies,
63
+ (uint8_t) data & 0xff);
77
+
64
+
78
+static void aspeed_set_mmio_exec(Object *obj, bool value, Error **errp)
65
if (s->snoop_index == SNOOP_OFF) {
79
+{
66
return false; /* Do nothing */
80
+ ASPEED_MACHINE(obj)->mmio_exec = value;
67
81
+}
68
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_flash_write(void *opaque, hwaddr addr, uint64_t data,
69
AspeedSMCState *s = fl->controller;
70
int i;
71
72
+ trace_aspeed_smc_flash_write(fl->id, addr, size, data,
73
+ aspeed_smc_flash_mode(fl));
82
+
74
+
83
+static void aspeed_machine_instance_init(Object *obj)
75
if (!aspeed_smc_is_writable(fl)) {
84
+{
76
qemu_log_mask(LOG_GUEST_ERROR, "%s: flash is not writable at 0x%"
85
+ ASPEED_MACHINE(obj)->mmio_exec = false;
77
HWADDR_PRIx "\n", __func__, addr);
86
+}
78
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
79
(s->ctrl->has_dma && addr == R_DMA_CHECKSUM) ||
80
(addr >= R_SEG_ADDR0 && addr < R_SEG_ADDR0 + s->ctrl->max_slaves) ||
81
(addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->ctrl->max_slaves)) {
87
+
82
+
88
+static void aspeed_machine_class_props_init(ObjectClass *oc)
83
+ trace_aspeed_smc_read(addr, size, s->regs[addr]);
89
+{
90
+ object_class_property_add_bool(oc, "execute-in-place",
91
+ aspeed_get_mmio_exec,
92
+ aspeed_set_mmio_exec, &error_abort);
93
+ object_class_property_set_description(oc, "execute-in-place",
94
+ "boot directly from CE0 flash device", &error_abort);
95
+}
96
+
84
+
97
static void aspeed_machine_class_init(ObjectClass *oc, void *data)
85
return s->regs[addr];
98
{
86
} else {
99
MachineClass *mc = MACHINE_CLASS(oc);
87
qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
100
@@ -XXX,XX +XXX,XX @@ static void aspeed_machine_class_init(ObjectClass *oc, void *data)
88
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
101
mc->no_floppy = 1;
89
__func__, s->regs[R_DMA_FLASH_ADDR]);
102
mc->no_cdrom = 1;
90
return;
103
mc->no_parallel = 1;
91
}
92
+ trace_aspeed_smc_dma_checksum(s->regs[R_DMA_FLASH_ADDR], data);
93
94
/*
95
* When the DMA is on-going, the DMA registers are updated
96
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
97
98
addr >>= 2;
99
100
+ trace_aspeed_smc_write(addr, size, data);
104
+
101
+
105
+ aspeed_machine_class_props_init(oc);
102
if (addr == s->r_conf ||
106
}
103
(addr >= s->r_timings &&
107
104
addr < s->r_timings + s->ctrl->nregs_timings) ||
108
static void aspeed_machine_palmetto_class_init(ObjectClass *oc, void *data)
105
diff --git a/hw/ssi/trace-events b/hw/ssi/trace-events
109
@@ -XXX,XX +XXX,XX @@ static const TypeInfo aspeed_machine_types[] = {
106
new file mode 100644
110
.name = TYPE_ASPEED_MACHINE,
107
index XXXXXXX..XXXXXXX
111
.parent = TYPE_MACHINE,
108
--- /dev/null
112
.instance_size = sizeof(AspeedMachine),
109
+++ b/hw/ssi/trace-events
113
+ .instance_init = aspeed_machine_instance_init,
110
@@ -XXX,XX +XXX,XX @@
114
.class_size = sizeof(AspeedMachineClass),
111
+# aspeed_smc.c
115
.class_init = aspeed_machine_class_init,
112
+
116
.abstract = true,
113
+aspeed_smc_flash_set_segment(int cs, uint64_t reg, uint64_t start, uint64_t end) "CS%d segreg=0x%"PRIx64" [ 0x%"PRIx64" - 0x%"PRIx64" ]"
114
+aspeed_smc_flash_read(int cs, uint64_t addr, uint32_t size, uint64_t data, int mode) "CS%d @0x%" PRIx64 " size %u: 0x%" PRIx64" mode:%d"
115
+aspeed_smc_do_snoop(int cs, int index, int dummies, int data) "CS%d index:0x%x dummies:%d data:0x%x"
116
+aspeed_smc_flash_write(int cs, uint64_t addr, uint32_t size, uint64_t data, int mode) "CS%d @0x%" PRIx64 " size %u: 0x%" PRIx64" mode:%d"
117
+aspeed_smc_read(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
118
+aspeed_smc_dma_checksum(uint32_t addr, uint32_t data) "0x%08x: 0x%08x"
119
+aspeed_smc_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
117
--
120
--
118
2.20.1
121
2.20.1
119
122
120
123
diff view generated by jsdifflib
1
From: Andrew Jeffery <andrew@aj.id.au>
1
From: Cédric Le Goater <clg@kaod.org>
2
2
3
The AST2600 includes a second cut-down version of the SD/MMC controller
3
The Aspeed SMC Controller can operate in different modes : Read, Fast
4
found in the AST2500, named the eMMC controller. It's cut down in the
4
Read, Write and User modes. When the User mode is configured, it
5
sense that it only supports one slot rather than two, but it brings the
5
selects automatically the SPI slave device until the CE_STOP_ACTIVE
6
total number of slots supported by the AST2600 to three.
6
bit is set to 1. When any other modes are configured the device is
7
unselected. The HW logic handles the chip select automatically when
8
the flash is accessed through its AHB window.
7
9
8
The existing code assumed that the SD controller always provided two
10
When configuring the CEx Control Register, the User mode logic to
9
slots. Rework the SDHCI object to expose the number of slots as a
11
select and unselect the slave is incorrect and data corruption can be
10
property to be set by the SoC configuration.
12
seen on machines using two chips, witherspoon and romulus.
11
13
12
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
14
Rework the handler setting the CEx Control Register to fix this issue.
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
15
14
Reviewed-by: Cédric Le Goater <clg@kaod.org>
16
Fixes: 7c1c69bca43c ("ast2400: add SMC controllers (FMC and SPI)")
15
Signed-off-by: Cédric Le Goater <clg@kaod.org>
17
Signed-off-by: Cédric Le Goater <clg@kaod.org>
16
Message-id: 20200114103433.30534-2-clg@kaod.org
18
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
17
[PMM: fixed up to use device_class_set_props()]
19
Message-id: 20200206112645.21275-3-clg@kaod.org
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
21
---
20
include/hw/sd/aspeed_sdhci.h | 1 +
22
hw/ssi/aspeed_smc.c | 39 +++++++++++++++++++++++----------------
21
hw/arm/aspeed.c | 2 +-
23
hw/ssi/trace-events | 1 +
22
hw/arm/aspeed_ast2600.c | 2 ++
24
2 files changed, 24 insertions(+), 16 deletions(-)
23
hw/arm/aspeed_soc.c | 2 ++
24
hw/sd/aspeed_sdhci.c | 11 +++++++++--
25
5 files changed, 15 insertions(+), 3 deletions(-)
26
25
27
diff --git a/include/hw/sd/aspeed_sdhci.h b/include/hw/sd/aspeed_sdhci.h
26
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
28
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
29
--- a/include/hw/sd/aspeed_sdhci.h
28
--- a/hw/ssi/aspeed_smc.c
30
+++ b/include/hw/sd/aspeed_sdhci.h
29
+++ b/hw/ssi/aspeed_smc.c
31
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSDHCIState {
30
@@ -XXX,XX +XXX,XX @@ static inline int aspeed_smc_flash_is_4byte(const AspeedSMCFlash *fl)
32
SysBusDevice parent;
33
34
SDHCIState slots[ASPEED_SDHCI_NUM_SLOTS];
35
+ uint8_t num_slots;
36
37
MemoryRegion iomem;
38
qemu_irq irq;
39
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/arm/aspeed.c
42
+++ b/hw/arm/aspeed.c
43
@@ -XXX,XX +XXX,XX @@ static void aspeed_machine_init(MachineState *machine)
44
amc->i2c_init(bmc);
45
}
31
}
46
32
}
47
- for (i = 0; i < ARRAY_SIZE(bmc->soc.sdhci.slots); i++) {
33
48
+ for (i = 0; i < bmc->soc.sdhci.num_slots; i++) {
34
-static inline bool aspeed_smc_is_ce_stop_active(const AspeedSMCFlash *fl)
49
SDHCIState *sdhci = &bmc->soc.sdhci.slots[i];
35
+static void aspeed_smc_flash_do_select(AspeedSMCFlash *fl, bool unselect)
50
DriveInfo *dinfo = drive_get_next(IF_SD);
36
{
51
BlockBackend *blk;
37
- const AspeedSMCState *s = fl->controller;
52
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
38
+ AspeedSMCState *s = fl->controller;
53
index XXXXXXX..XXXXXXX 100644
39
54
--- a/hw/arm/aspeed_ast2600.c
40
- return s->regs[s->r_ctrl0 + fl->id] & CTRL_CE_STOP_ACTIVE;
55
+++ b/hw/arm/aspeed_ast2600.c
41
+ trace_aspeed_smc_flash_select(fl->id, unselect ? "un" : "");
56
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2600_init(Object *obj)
57
sysbus_init_child_obj(obj, "sdc", OBJECT(&s->sdhci), sizeof(s->sdhci),
58
TYPE_ASPEED_SDHCI);
59
60
+ object_property_set_int(OBJECT(&s->sdhci), 2, "num-slots", &error_abort);
61
+
42
+
62
/* Init sd card slot class here so that they're under the correct parent */
43
+ qemu_set_irq(s->cs_lines[fl->id], unselect);
63
for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) {
44
}
64
sysbus_init_child_obj(obj, "sdhci[*]", OBJECT(&s->sdhci.slots[i]),
45
65
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
46
static void aspeed_smc_flash_select(AspeedSMCFlash *fl)
66
index XXXXXXX..XXXXXXX 100644
47
{
67
--- a/hw/arm/aspeed_soc.c
48
- AspeedSMCState *s = fl->controller;
68
+++ b/hw/arm/aspeed_soc.c
49
-
69
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
50
- s->regs[s->r_ctrl0 + fl->id] &= ~CTRL_CE_STOP_ACTIVE;
70
sysbus_init_child_obj(obj, "sdc", OBJECT(&s->sdhci), sizeof(s->sdhci),
51
- qemu_set_irq(s->cs_lines[fl->id], aspeed_smc_is_ce_stop_active(fl));
71
TYPE_ASPEED_SDHCI);
52
+ aspeed_smc_flash_do_select(fl, false);
72
53
}
73
+ object_property_set_int(OBJECT(&s->sdhci), 2, "num-slots", &error_abort);
54
74
+
55
static void aspeed_smc_flash_unselect(AspeedSMCFlash *fl)
75
/* Init sd card slot class here so that they're under the correct parent */
56
{
76
for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) {
57
- AspeedSMCState *s = fl->controller;
77
sysbus_init_child_obj(obj, "sdhci[*]", OBJECT(&s->sdhci.slots[i]),
58
-
78
diff --git a/hw/sd/aspeed_sdhci.c b/hw/sd/aspeed_sdhci.c
59
- s->regs[s->r_ctrl0 + fl->id] |= CTRL_CE_STOP_ACTIVE;
79
index XXXXXXX..XXXXXXX 100644
60
- qemu_set_irq(s->cs_lines[fl->id], aspeed_smc_is_ce_stop_active(fl));
80
--- a/hw/sd/aspeed_sdhci.c
61
+ aspeed_smc_flash_do_select(fl, true);
81
+++ b/hw/sd/aspeed_sdhci.c
62
}
82
@@ -XXX,XX +XXX,XX @@
63
83
#include "qapi/error.h"
64
static uint32_t aspeed_smc_check_segment_addr(const AspeedSMCFlash *fl,
84
#include "hw/irq.h"
65
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps aspeed_smc_flash_ops = {
85
#include "migration/vmstate.h"
86
+#include "hw/qdev-properties.h"
87
88
#define ASPEED_SDHCI_INFO 0x00
89
#define ASPEED_SDHCI_INFO_RESET 0x00030000
90
@@ -XXX,XX +XXX,XX @@ static void aspeed_sdhci_realize(DeviceState *dev, Error **errp)
91
92
/* Create input irqs for the slots */
93
qdev_init_gpio_in_named_with_opaque(DEVICE(sbd), aspeed_sdhci_set_irq,
94
- sdhci, NULL, ASPEED_SDHCI_NUM_SLOTS);
95
+ sdhci, NULL, sdhci->num_slots);
96
97
sysbus_init_irq(sbd, &sdhci->irq);
98
memory_region_init_io(&sdhci->iomem, OBJECT(sdhci), &aspeed_sdhci_ops,
99
sdhci, TYPE_ASPEED_SDHCI, 0x1000);
100
sysbus_init_mmio(sbd, &sdhci->iomem);
101
102
- for (int i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) {
103
+ for (int i = 0; i < sdhci->num_slots; ++i) {
104
Object *sdhci_slot = OBJECT(&sdhci->slots[i]);
105
SysBusDevice *sbd_slot = SYS_BUS_DEVICE(&sdhci->slots[i]);
106
107
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_aspeed_sdhci = {
108
},
66
},
109
};
67
};
110
68
111
+static Property aspeed_sdhci_properties[] = {
69
-static void aspeed_smc_flash_update_cs(AspeedSMCFlash *fl)
112
+ DEFINE_PROP_UINT8("num-slots", AspeedSDHCIState, num_slots, 0),
70
+static void aspeed_smc_flash_update_ctrl(AspeedSMCFlash *fl, uint32_t value)
113
+ DEFINE_PROP_END_OF_LIST(),
71
{
114
+};
72
AspeedSMCState *s = fl->controller;
73
+ bool unselect;
74
75
- s->snoop_index = aspeed_smc_is_ce_stop_active(fl) ? SNOOP_OFF : SNOOP_START;
76
+ /* User mode selects the CS, other modes unselect */
77
+ unselect = (value & CTRL_CMD_MODE_MASK) != CTRL_USERMODE;
78
79
- qemu_set_irq(s->cs_lines[fl->id], aspeed_smc_is_ce_stop_active(fl));
80
+ /* A change of CTRL_CE_STOP_ACTIVE from 0 to 1, unselects the CS */
81
+ if (!(s->regs[s->r_ctrl0 + fl->id] & CTRL_CE_STOP_ACTIVE) &&
82
+ value & CTRL_CE_STOP_ACTIVE) {
83
+ unselect = true;
84
+ }
115
+
85
+
116
static void aspeed_sdhci_class_init(ObjectClass *classp, void *data)
86
+ s->regs[s->r_ctrl0 + fl->id] = value;
117
{
87
+
118
DeviceClass *dc = DEVICE_CLASS(classp);
88
+ s->snoop_index = unselect ? SNOOP_OFF : SNOOP_START;
119
@@ -XXX,XX +XXX,XX @@ static void aspeed_sdhci_class_init(ObjectClass *classp, void *data)
89
+
120
dc->realize = aspeed_sdhci_realize;
90
+ aspeed_smc_flash_do_select(fl, unselect);
121
dc->reset = aspeed_sdhci_reset;
122
dc->vmsd = &vmstate_aspeed_sdhci;
123
+ device_class_set_props(dc, aspeed_sdhci_properties);
124
}
91
}
125
92
126
static TypeInfo aspeed_sdhci_info = {
93
static void aspeed_smc_reset(DeviceState *d)
94
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
95
s->regs[addr] = value;
96
} else if (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs) {
97
int cs = addr - s->r_ctrl0;
98
- s->regs[addr] = value;
99
- aspeed_smc_flash_update_cs(&s->flashes[cs]);
100
+ aspeed_smc_flash_update_ctrl(&s->flashes[cs], value);
101
} else if (addr >= R_SEG_ADDR0 &&
102
addr < R_SEG_ADDR0 + s->ctrl->max_slaves) {
103
int cs = addr - R_SEG_ADDR0;
104
diff --git a/hw/ssi/trace-events b/hw/ssi/trace-events
105
index XXXXXXX..XXXXXXX 100644
106
--- a/hw/ssi/trace-events
107
+++ b/hw/ssi/trace-events
108
@@ -XXX,XX +XXX,XX @@ aspeed_smc_flash_write(int cs, uint64_t addr, uint32_t size, uint64_t data, int
109
aspeed_smc_read(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
110
aspeed_smc_dma_checksum(uint32_t addr, uint32_t data) "0x%08x: 0x%08x"
111
aspeed_smc_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
112
+aspeed_smc_flash_select(int cs, const char *prefix) "CS%d %sselect"
127
--
113
--
128
2.20.1
114
2.20.1
129
115
130
116
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
We fail to validate the upper bits of a virtual address on a
4
translation disabled regime, as per AArch64.TranslateAddressS1Off.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200308012946.16303-2-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/helper.c | 35 ++++++++++++++++++++++++++++++++++-
12
1 file changed, 34 insertions(+), 1 deletion(-)
13
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
17
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
19
/* Definitely a real MMU, not an MPU */
20
21
if (regime_translation_disabled(env, mmu_idx)) {
22
- /* MMU disabled. */
23
+ /*
24
+ * MMU disabled. S1 addresses within aa64 translation regimes are
25
+ * still checked for bounds -- see AArch64.TranslateAddressS1Off.
26
+ */
27
+ if (mmu_idx != ARMMMUIdx_Stage2) {
28
+ int r_el = regime_el(env, mmu_idx);
29
+ if (arm_el_is_aa64(env, r_el)) {
30
+ int pamax = arm_pamax(env_archcpu(env));
31
+ uint64_t tcr = env->cp15.tcr_el[r_el].raw_tcr;
32
+ int addrtop, tbi;
33
+
34
+ tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
35
+ if (access_type == MMU_INST_FETCH) {
36
+ tbi &= ~aa64_va_parameter_tbid(tcr, mmu_idx);
37
+ }
38
+ tbi = (tbi >> extract64(address, 55, 1)) & 1;
39
+ addrtop = (tbi ? 55 : 63);
40
+
41
+ if (extract64(address, pamax, addrtop - pamax + 1) != 0) {
42
+ fi->type = ARMFault_AddressSize;
43
+ fi->level = 0;
44
+ fi->stage2 = false;
45
+ return 1;
46
+ }
47
+
48
+ /*
49
+ * When TBI is disabled, we've just validated that all of the
50
+ * bits above PAMax are zero, so logically we only need to
51
+ * clear the top byte for TBI. But it's clearer to follow
52
+ * the pseudocode set of addrdesc.paddress.
53
+ */
54
+ address = extract64(address, 0, 52);
55
+ }
56
+ }
57
*phys_ptr = address;
58
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
59
*page_size = TARGET_PAGE_SIZE;
60
--
61
2.20.1
62
63
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
We must include the tag in the FAR_ELx register when raising
4
an addressing exception. Which means that we should not clear
5
out the tag during translation.
6
7
We cannot at present comply with this for user mode, so we
8
retain the clean_data_tbi function for the moment, though it
9
no longer does what it says on the tin for system mode. This
10
function is to be replaced with MTE, so don't worry about the
11
slight misnaming.
12
13
Buglink: https://bugs.launchpad.net/qemu/+bug/1867072
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20200308012946.16303-3-richard.henderson@linaro.org
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
target/arm/translate-a64.c | 11 +++++++++++
20
1 file changed, 11 insertions(+)
21
22
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/translate-a64.c
25
+++ b/target/arm/translate-a64.c
26
@@ -XXX,XX +XXX,XX @@ static void gen_a64_set_pc(DisasContext *s, TCGv_i64 src)
27
static TCGv_i64 clean_data_tbi(DisasContext *s, TCGv_i64 addr)
28
{
29
TCGv_i64 clean = new_tmp_a64(s);
30
+ /*
31
+ * In order to get the correct value in the FAR_ELx register,
32
+ * we must present the memory subsystem with the "dirty" address
33
+ * including the TBI. In system mode we can make this work via
34
+ * the TLB, dropping the TBI during translation. But for user-only
35
+ * mode we don't have that option, and must remove the top byte now.
36
+ */
37
+#ifdef CONFIG_USER_ONLY
38
gen_top_byte_ignore(s, clean, addr, s->tbid);
39
+#else
40
+ tcg_gen_mov_i64(clean, addr);
41
+#endif
42
return clean;
43
}
44
45
--
46
2.20.1
47
48
diff view generated by jsdifflib
New patch
1
From: Igor Mammedov <imammedo@redhat.com>
1
2
3
SOC object returned by object_new() is leaked in current code.
4
Set SOC parent explicitly to board and then unref to SOC object
5
to make sure that refererence returned by object_new() is taken
6
care of.
7
8
The SOC object will be kept alive by its parent (machine) and
9
will be automatically freed when MachineState is destroyed.
10
11
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
12
Reported-by: Andrew Jones <drjones@redhat.com>
13
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
14
Message-id: 20200303091254.22373-1-imammedo@redhat.com
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
hw/arm/cubieboard.c | 3 +++
19
1 file changed, 3 insertions(+)
20
21
diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/cubieboard.c
24
+++ b/hw/arm/cubieboard.c
25
@@ -XXX,XX +XXX,XX @@ static void cubieboard_init(MachineState *machine)
26
}
27
28
a10 = AW_A10(object_new(TYPE_AW_A10));
29
+ object_property_add_child(OBJECT(machine), "soc", OBJECT(a10),
30
+ &error_abort);
31
+ object_unref(OBJECT(a10));
32
33
object_property_set_int(OBJECT(&a10->emac), 1, "phy-addr", &err);
34
if (err != NULL) {
35
--
36
2.20.1
37
38
diff view generated by jsdifflib
1
From: Cédric Le Goater <clg@kaod.org>
1
From: Guenter Roeck <linux@roeck-us.net>
2
2
3
These buffers should be aligned on 16 bytes.
3
Wire up eSDHC controllers in fsl-imx25. For imx25-pdk, connect drives
4
provided on the command line to available eSDHC controllers.
4
5
5
Ignore invalid RX and TX buffer addresses and log an error. All
6
This patch enables booting the imx25-pdk emulation from SD card.
6
incoming and outgoing traffic will be dropped because no valid RX or
7
TX descriptors will be available.
8
7
9
Signed-off-by: Cédric Le Goater <clg@kaod.org>
8
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
10
Message-id: 20200114103433.30534-4-clg@kaod.org
9
Message-id: 20200310215146.19688-2-linux@roeck-us.net
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
[PMM: made commit subject consistent with other patch]
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
13
---
14
hw/net/ftgmac100.c | 13 +++++++++++++
14
include/hw/arm/fsl-imx25.h | 9 +++++++++
15
1 file changed, 13 insertions(+)
15
hw/arm/fsl-imx25.c | 32 ++++++++++++++++++++++++++++++++
16
hw/arm/imx25_pdk.c | 16 ++++++++++++++++
17
3 files changed, 57 insertions(+)
16
18
17
diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c
19
diff --git a/include/hw/arm/fsl-imx25.h b/include/hw/arm/fsl-imx25.h
18
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/net/ftgmac100.c
21
--- a/include/hw/arm/fsl-imx25.h
20
+++ b/hw/net/ftgmac100.c
22
+++ b/include/hw/arm/fsl-imx25.h
21
@@ -XXX,XX +XXX,XX @@ typedef struct {
23
@@ -XXX,XX +XXX,XX @@
22
uint32_t des3;
24
#include "hw/misc/imx_rngc.h"
23
} FTGMAC100Desc;
25
#include "hw/i2c/imx_i2c.h"
24
26
#include "hw/gpio/imx_gpio.h"
25
+#define FTGMAC100_DESC_ALIGNMENT 16
27
+#include "hw/sd/sdhci.h"
28
#include "exec/memory.h"
29
#include "target/arm/cpu.h"
30
31
@@ -XXX,XX +XXX,XX @@
32
#define FSL_IMX25_NUM_EPITS 2
33
#define FSL_IMX25_NUM_I2CS 3
34
#define FSL_IMX25_NUM_GPIOS 4
35
+#define FSL_IMX25_NUM_ESDHCS 2
36
37
typedef struct FslIMX25State {
38
/*< private >*/
39
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX25State {
40
IMXRNGCState rngc;
41
IMXI2CState i2c[FSL_IMX25_NUM_I2CS];
42
IMXGPIOState gpio[FSL_IMX25_NUM_GPIOS];
43
+ SDHCIState esdhc[FSL_IMX25_NUM_ESDHCS];
44
MemoryRegion rom[2];
45
MemoryRegion iram;
46
MemoryRegion iram_alias;
47
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX25State {
48
#define FSL_IMX25_GPIO3_SIZE 0x4000
49
#define FSL_IMX25_RNGC_ADDR 0x53FB0000
50
#define FSL_IMX25_RNGC_SIZE 0x4000
51
+#define FSL_IMX25_ESDHC1_ADDR 0x53FB4000
52
+#define FSL_IMX25_ESDHC1_SIZE 0x4000
53
+#define FSL_IMX25_ESDHC2_ADDR 0x53FB8000
54
+#define FSL_IMX25_ESDHC2_SIZE 0x4000
55
#define FSL_IMX25_GPIO1_ADDR 0x53FCC000
56
#define FSL_IMX25_GPIO1_SIZE 0x4000
57
#define FSL_IMX25_GPIO2_ADDR 0x53FD0000
58
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX25State {
59
#define FSL_IMX25_GPIO2_IRQ 51
60
#define FSL_IMX25_GPIO3_IRQ 16
61
#define FSL_IMX25_GPIO4_IRQ 23
62
+#define FSL_IMX25_ESDHC1_IRQ 9
63
+#define FSL_IMX25_ESDHC2_IRQ 8
64
65
#endif /* FSL_IMX25_H */
66
diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/hw/arm/fsl-imx25.c
69
+++ b/hw/arm/fsl-imx25.c
70
@@ -XXX,XX +XXX,XX @@
71
#include "hw/qdev-properties.h"
72
#include "chardev/char.h"
73
74
+#define IMX25_ESDHC_CAPABILITIES 0x07e20000
26
+
75
+
27
/*
76
static void fsl_imx25_init(Object *obj)
28
* Specific RTL8211E MII Registers
77
{
29
*/
78
FslIMX25State *s = FSL_IMX25(obj);
30
@@ -XXX,XX +XXX,XX @@ static void ftgmac100_write(void *opaque, hwaddr addr,
79
@@ -XXX,XX +XXX,XX @@ static void fsl_imx25_init(Object *obj)
31
s->itc = value;
80
sysbus_init_child_obj(obj, "gpio[*]", &s->gpio[i], sizeof(s->gpio[i]),
32
break;
81
TYPE_IMX_GPIO);
33
case FTGMAC100_RXR_BADR: /* Ring buffer address */
82
}
34
+ if (!QEMU_IS_ALIGNED(value, FTGMAC100_DESC_ALIGNMENT)) {
83
+
35
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad RX buffer alignment 0x%"
84
+ for (i = 0; i < FSL_IMX25_NUM_ESDHCS; i++) {
36
+ HWADDR_PRIx "\n", __func__, value);
85
+ sysbus_init_child_obj(obj, "sdhc[*]", &s->esdhc[i], sizeof(s->esdhc[i]),
86
+ TYPE_IMX_USDHC);
87
+ }
88
}
89
90
static void fsl_imx25_realize(DeviceState *dev, Error **errp)
91
@@ -XXX,XX +XXX,XX @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
92
gpio_table[i].irq));
93
}
94
95
+ /* Initialize all SDHC */
96
+ for (i = 0; i < FSL_IMX25_NUM_ESDHCS; i++) {
97
+ static const struct {
98
+ hwaddr addr;
99
+ unsigned int irq;
100
+ } esdhc_table[FSL_IMX25_NUM_ESDHCS] = {
101
+ { FSL_IMX25_ESDHC1_ADDR, FSL_IMX25_ESDHC1_IRQ },
102
+ { FSL_IMX25_ESDHC2_ADDR, FSL_IMX25_ESDHC2_IRQ },
103
+ };
104
+
105
+ object_property_set_uint(OBJECT(&s->esdhc[i]), 2, "sd-spec-version",
106
+ &err);
107
+ object_property_set_uint(OBJECT(&s->esdhc[i]), IMX25_ESDHC_CAPABILITIES,
108
+ "capareg", &err);
109
+ object_property_set_bool(OBJECT(&s->esdhc[i]), true, "realized", &err);
110
+ if (err) {
111
+ error_propagate(errp, err);
37
+ return;
112
+ return;
38
+ }
113
+ }
114
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->esdhc[i]), 0, esdhc_table[i].addr);
115
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->esdhc[i]), 0,
116
+ qdev_get_gpio_in(DEVICE(&s->avic),
117
+ esdhc_table[i].irq));
118
+ }
39
+
119
+
40
s->rx_ring = value;
120
/* initialize 2 x 16 KB ROM */
41
s->rx_descriptor = s->rx_ring;
121
memory_region_init_rom(&s->rom[0], NULL,
42
break;
122
"imx25.rom0", FSL_IMX25_ROM0_SIZE, &err);
43
@@ -XXX,XX +XXX,XX @@ static void ftgmac100_write(void *opaque, hwaddr addr,
123
diff --git a/hw/arm/imx25_pdk.c b/hw/arm/imx25_pdk.c
44
break;
124
index XXXXXXX..XXXXXXX 100644
45
125
--- a/hw/arm/imx25_pdk.c
46
case FTGMAC100_NPTXR_BADR: /* Transmit buffer address */
126
+++ b/hw/arm/imx25_pdk.c
47
+ if (!QEMU_IS_ALIGNED(value, FTGMAC100_DESC_ALIGNMENT)) {
127
@@ -XXX,XX +XXX,XX @@
48
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad TX buffer alignment 0x%"
128
#include "qemu/osdep.h"
49
+ HWADDR_PRIx "\n", __func__, value);
129
#include "qapi/error.h"
50
+ return;
130
#include "cpu.h"
51
+ }
131
+#include "hw/qdev-properties.h"
52
s->tx_ring = value;
132
#include "hw/arm/fsl-imx25.h"
53
s->tx_descriptor = s->tx_ring;
133
#include "hw/boards.h"
54
break;
134
#include "qemu/error-report.h"
135
@@ -XXX,XX +XXX,XX @@ static void imx25_pdk_init(MachineState *machine)
136
imx25_pdk_binfo.board_id = 1771,
137
imx25_pdk_binfo.nb_cpus = 1;
138
139
+ for (i = 0; i < FSL_IMX25_NUM_ESDHCS; i++) {
140
+ BusState *bus;
141
+ DeviceState *carddev;
142
+ DriveInfo *di;
143
+ BlockBackend *blk;
144
+
145
+ di = drive_get_next(IF_SD);
146
+ blk = di ? blk_by_legacy_dinfo(di) : NULL;
147
+ bus = qdev_get_child_bus(DEVICE(&s->soc.esdhc[i]), "sd-bus");
148
+ carddev = qdev_create(bus, TYPE_SD_CARD);
149
+ qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
150
+ object_property_set_bool(OBJECT(carddev), true,
151
+ "realized", &error_fatal);
152
+ }
153
+
154
/*
155
* We test explicitly for qtest here as it is not done (yet?) in
156
* arm_load_kernel(). Without this the "make check" command would
55
--
157
--
56
2.20.1
158
2.20.1
57
159
58
160
diff view generated by jsdifflib
1
From: Zenghui Yu <yuzenghui@huawei.com>
1
From: Guenter Roeck <linux@roeck-us.net>
2
2
3
If LPIs are disabled, KVM will just ignore the GICR_PENDBASER.PTZ bit when
3
i.MX25 supports two USB controllers. Let's wire them up.
4
restoring GICR_CTLR. Setting PTZ here makes littlt sense in "reduce GIC
5
initialization time".
6
4
7
And what's worse, PTZ is generally programmed by guest to indicate to the
5
With this patch, imx25-pdk can boot from both USB ports.
8
Redistributor whether the LPI Pending table is zero when enabling LPIs.
9
If migration is triggered when the PTZ has just been cleared by guest (and
10
before enabling LPIs), we will see PTZ==1 on the destination side, which
11
is not as expected. Let's just drop this hackish userspace behavior.
12
6
13
Also take this chance to refine the comment a bit.
7
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
14
8
Message-id: 20200310215146.19688-3-linux@roeck-us.net
15
Fixes: 367b9f527bec ("hw/intc/arm_gicv3_kvm: Implement get/put functions")
16
Signed-off-by: Zenghui Yu <yuzenghui@huawei.com>
17
Message-id: 20200119133051.642-1-yuzenghui@huawei.com
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
11
---
21
hw/intc/arm_gicv3_kvm.c | 11 ++++-------
12
include/hw/arm/fsl-imx25.h | 9 +++++++++
22
1 file changed, 4 insertions(+), 7 deletions(-)
13
hw/arm/fsl-imx25.c | 24 ++++++++++++++++++++++++
14
2 files changed, 33 insertions(+)
23
15
24
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
16
diff --git a/include/hw/arm/fsl-imx25.h b/include/hw/arm/fsl-imx25.h
25
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/intc/arm_gicv3_kvm.c
18
--- a/include/hw/arm/fsl-imx25.h
27
+++ b/hw/intc/arm_gicv3_kvm.c
19
+++ b/include/hw/arm/fsl-imx25.h
28
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_put(GICv3State *s)
20
@@ -XXX,XX +XXX,XX @@
29
kvm_gicd_access(s, GICD_CTLR, &reg, true);
21
#include "hw/i2c/imx_i2c.h"
30
22
#include "hw/gpio/imx_gpio.h"
31
if (redist_typer & GICR_TYPER_PLPIS) {
23
#include "hw/sd/sdhci.h"
32
- /* Set base addresses before LPIs are enabled by GICR_CTLR write */
24
+#include "hw/usb/chipidea.h"
33
+ /*
25
#include "exec/memory.h"
34
+ * Restore base addresses before LPIs are potentially enabled by
26
#include "target/arm/cpu.h"
35
+ * GICR_CTLR write
27
36
+ */
28
@@ -XXX,XX +XXX,XX @@
37
for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {
29
#define FSL_IMX25_NUM_I2CS 3
38
GICv3CPUState *c = &s->cpu[ncpu];
30
#define FSL_IMX25_NUM_GPIOS 4
39
31
#define FSL_IMX25_NUM_ESDHCS 2
40
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_put(GICv3State *s)
32
+#define FSL_IMX25_NUM_USBS 2
41
kvm_gicr_access(s, GICR_PROPBASER + 4, ncpu, &regh, true);
33
42
34
typedef struct FslIMX25State {
43
reg64 = c->gicr_pendbaser;
35
/*< private >*/
44
- if (!(c->gicr_ctlr & GICR_CTLR_ENABLE_LPIS)) {
36
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX25State {
45
- /* Setting PTZ is advised if LPIs are disabled, to reduce
37
IMXI2CState i2c[FSL_IMX25_NUM_I2CS];
46
- * GIC initialization time.
38
IMXGPIOState gpio[FSL_IMX25_NUM_GPIOS];
47
- */
39
SDHCIState esdhc[FSL_IMX25_NUM_ESDHCS];
48
- reg64 |= GICR_PENDBASER_PTZ;
40
+ ChipideaState usb[FSL_IMX25_NUM_USBS];
49
- }
41
MemoryRegion rom[2];
50
regl = (uint32_t)reg64;
42
MemoryRegion iram;
51
kvm_gicr_access(s, GICR_PENDBASER, ncpu, &regl, true);
43
MemoryRegion iram_alias;
52
regh = (uint32_t)(reg64 >> 32);
44
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX25State {
45
#define FSL_IMX25_GPIO1_SIZE 0x4000
46
#define FSL_IMX25_GPIO2_ADDR 0x53FD0000
47
#define FSL_IMX25_GPIO2_SIZE 0x4000
48
+#define FSL_IMX25_USB1_ADDR 0x53FF4000
49
+#define FSL_IMX25_USB1_SIZE 0x0200
50
+#define FSL_IMX25_USB2_ADDR 0x53FF4400
51
+#define FSL_IMX25_USB2_SIZE 0x0200
52
#define FSL_IMX25_AVIC_ADDR 0x68000000
53
#define FSL_IMX25_AVIC_SIZE 0x4000
54
#define FSL_IMX25_IRAM_ADDR 0x78000000
55
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX25State {
56
#define FSL_IMX25_GPIO4_IRQ 23
57
#define FSL_IMX25_ESDHC1_IRQ 9
58
#define FSL_IMX25_ESDHC2_IRQ 8
59
+#define FSL_IMX25_USB1_IRQ 37
60
+#define FSL_IMX25_USB2_IRQ 35
61
62
#endif /* FSL_IMX25_H */
63
diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/arm/fsl-imx25.c
66
+++ b/hw/arm/fsl-imx25.c
67
@@ -XXX,XX +XXX,XX @@ static void fsl_imx25_init(Object *obj)
68
sysbus_init_child_obj(obj, "sdhc[*]", &s->esdhc[i], sizeof(s->esdhc[i]),
69
TYPE_IMX_USDHC);
70
}
71
+
72
+ for (i = 0; i < FSL_IMX25_NUM_USBS; i++) {
73
+ sysbus_init_child_obj(obj, "usb[*]", &s->usb[i], sizeof(s->usb[i]),
74
+ TYPE_CHIPIDEA);
75
+ }
76
+
77
}
78
79
static void fsl_imx25_realize(DeviceState *dev, Error **errp)
80
@@ -XXX,XX +XXX,XX @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
81
esdhc_table[i].irq));
82
}
83
84
+ /* USB */
85
+ for (i = 0; i < FSL_IMX25_NUM_USBS; i++) {
86
+ static const struct {
87
+ hwaddr addr;
88
+ unsigned int irq;
89
+ } usb_table[FSL_IMX25_NUM_USBS] = {
90
+ { FSL_IMX25_USB1_ADDR, FSL_IMX25_USB1_IRQ },
91
+ { FSL_IMX25_USB2_ADDR, FSL_IMX25_USB2_IRQ },
92
+ };
93
+
94
+ object_property_set_bool(OBJECT(&s->usb[i]), true, "realized",
95
+ &error_abort);
96
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0, usb_table[i].addr);
97
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i]), 0,
98
+ qdev_get_gpio_in(DEVICE(&s->avic),
99
+ usb_table[i].irq));
100
+ }
101
+
102
/* initialize 2 x 16 KB ROM */
103
memory_region_init_rom(&s->rom[0], NULL,
104
"imx25.rom0", FSL_IMX25_ROM0_SIZE, &err);
53
--
105
--
54
2.20.1
106
2.20.1
55
107
56
108
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Add a function resettable_change_parent() to do the required
3
The Allwinner H3 is a System on Chip containing four ARM Cortex A7
4
plumbing when changing the parent a of Resettable object.
4
processor cores. Features and specifications include DDR2/DDR3 memory,
5
SD/MMC storage cards, 10/100/1000Mbit Ethernet, USB 2.0, HDMI and
6
various I/O modules. This commit adds support for the Allwinner H3
7
System on Chip.
5
8
6
We need to make sure that the reset state of the object remains
9
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
7
coherent with the reset state of the new parent.
8
9
We make the 2 following hypothesis:
10
+ when an object is put in a parent under reset, the object goes in
11
reset.
12
+ when an object is removed from a parent under reset, the object
13
leaves reset.
14
15
The added function avoids any glitch if both old and new parent are
16
already in reset.
17
18
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
21
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
22
Message-id: 20200123132823.1117486-6-damien.hedde@greensocs.com
13
Message-id: 20200311221854.30370-2-nieklinnenbank@gmail.com
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
---
15
---
25
include/hw/resettable.h | 16 +++++++++++
16
hw/arm/Makefile.objs | 1 +
26
hw/core/resettable.c | 62 +++++++++++++++++++++++++++++++++++++++--
17
include/hw/arm/allwinner-h3.h | 106 +++++++++++
27
hw/core/trace-events | 1 +
18
hw/arm/allwinner-h3.c | 327 ++++++++++++++++++++++++++++++++
28
3 files changed, 77 insertions(+), 2 deletions(-)
19
MAINTAINERS | 7 +
20
default-configs/arm-softmmu.mak | 1 +
21
hw/arm/Kconfig | 8 +
22
6 files changed, 450 insertions(+)
23
create mode 100644 include/hw/arm/allwinner-h3.h
24
create mode 100644 hw/arm/allwinner-h3.c
29
25
30
diff --git a/include/hw/resettable.h b/include/hw/resettable.h
26
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
31
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
32
--- a/include/hw/resettable.h
28
--- a/hw/arm/Makefile.objs
33
+++ b/include/hw/resettable.h
29
+++ b/hw/arm/Makefile.objs
34
@@ -XXX,XX +XXX,XX @@ void resettable_release_reset(Object *obj, ResetType type);
30
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_DIGIC) += digic.o
35
*/
31
obj-$(CONFIG_OMAP) += omap1.o omap2.o
36
bool resettable_is_in_reset(Object *obj);
32
obj-$(CONFIG_STRONGARM) += strongarm.o
37
33
obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
34
+obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3.o
35
obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
36
obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
37
obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o
38
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
39
new file mode 100644
40
index XXXXXXX..XXXXXXX
41
--- /dev/null
42
+++ b/include/hw/arm/allwinner-h3.h
43
@@ -XXX,XX +XXX,XX @@
44
+/*
45
+ * Allwinner H3 System on Chip emulation
46
+ *
47
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
48
+ *
49
+ * This program is free software: you can redistribute it and/or modify
50
+ * it under the terms of the GNU General Public License as published by
51
+ * the Free Software Foundation, either version 2 of the License, or
52
+ * (at your option) any later version.
53
+ *
54
+ * This program is distributed in the hope that it will be useful,
55
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
56
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57
+ * GNU General Public License for more details.
58
+ *
59
+ * You should have received a copy of the GNU General Public License
60
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
61
+ */
62
+
63
+/*
64
+ * The Allwinner H3 is a System on Chip containing four ARM Cortex A7
65
+ * processor cores. Features and specifications include DDR2/DDR3 memory,
66
+ * SD/MMC storage cards, 10/100/1000Mbit Ethernet, USB 2.0, HDMI and
67
+ * various I/O modules.
68
+ *
69
+ * This implementation is based on the following datasheet:
70
+ *
71
+ * https://linux-sunxi.org/File:Allwinner_H3_Datasheet_V1.2.pdf
72
+ *
73
+ * The latest datasheet and more info can be found on the Linux Sunxi wiki:
74
+ *
75
+ * https://linux-sunxi.org/H3
76
+ */
77
+
78
+#ifndef HW_ARM_ALLWINNER_H3_H
79
+#define HW_ARM_ALLWINNER_H3_H
80
+
81
+#include "qom/object.h"
82
+#include "hw/arm/boot.h"
83
+#include "hw/timer/allwinner-a10-pit.h"
84
+#include "hw/intc/arm_gic.h"
85
+#include "target/arm/cpu.h"
86
+
38
+/**
87
+/**
39
+ * resettable_change_parent:
88
+ * Allwinner H3 device list
40
+ * Indicate that the parent of Ressettable @obj is changing from @oldp to @newp.
89
+ *
41
+ * All 3 objects must implement resettable interface. @oldp or @newp may be
90
+ * This enumeration is can be used refer to a particular device in the
42
+ * NULL.
91
+ * Allwinner H3 SoC. For example, the physical memory base address for
43
+ *
92
+ * each device can be found in the AwH3State object in the memmap member
44
+ * This function will adapt the reset state of @obj so that it is coherent
93
+ * using the device enum value as index.
45
+ * with the reset state of @newp. It may trigger @resettable_assert_reset()
94
+ *
46
+ * or @resettable_release_reset(). It will do such things only if the reset
95
+ * @see AwH3State
47
+ * state of @newp and @oldp are different.
48
+ *
49
+ * When using this function during reset, it must only be called during
50
+ * a hold phase method. Calling this during enter or exit phase is an error.
51
+ */
96
+ */
52
+void resettable_change_parent(Object *obj, Object *newp, Object *oldp);
97
+enum {
53
+
98
+ AW_H3_SRAM_A1,
54
/**
99
+ AW_H3_SRAM_A2,
55
* resettable_class_set_parent_phases:
100
+ AW_H3_SRAM_C,
56
*
101
+ AW_H3_PIT,
57
diff --git a/hw/core/resettable.c b/hw/core/resettable.c
102
+ AW_H3_UART0,
58
index XXXXXXX..XXXXXXX 100644
103
+ AW_H3_UART1,
59
--- a/hw/core/resettable.c
104
+ AW_H3_UART2,
60
+++ b/hw/core/resettable.c
105
+ AW_H3_UART3,
61
@@ -XXX,XX +XXX,XX @@ static void resettable_phase_exit(Object *obj, void *opaque, ResetType type);
106
+ AW_H3_GIC_DIST,
62
* enter_phase_in_progress:
107
+ AW_H3_GIC_CPU,
63
* True if we are currently in reset enter phase.
108
+ AW_H3_GIC_HYP,
64
*
109
+ AW_H3_GIC_VCPU,
65
- * Note: This flag is only used to guarantee (using asserts) that the reset
110
+ AW_H3_SDRAM
66
- * API is used correctly. We can use a global variable because we rely on the
111
+};
67
+ * exit_phase_in_progress:
112
+
68
+ * count the number of exit phase we are in.
113
+/** Total number of CPU cores in the H3 SoC */
69
+ *
114
+#define AW_H3_NUM_CPUS (4)
70
+ * Note: These flags are only used to guarantee (using asserts) that the reset
115
+
71
+ * API is used correctly. We can use global variables because we rely on the
116
+/**
72
* iothread mutex to ensure only one reset operation is in a progress at a
117
+ * Allwinner H3 object model
73
* given time.
118
+ * @{
74
*/
119
+ */
75
static bool enter_phase_in_progress;
120
+
76
+static unsigned exit_phase_in_progress;
121
+/** Object type for the Allwinner H3 SoC */
77
122
+#define TYPE_AW_H3 "allwinner-h3"
78
void resettable_reset(Object *obj, ResetType type)
123
+
79
{
124
+/** Convert input object to Allwinner H3 state object */
80
@@ -XXX,XX +XXX,XX @@ void resettable_release_reset(Object *obj, ResetType type)
125
+#define AW_H3(obj) OBJECT_CHECK(AwH3State, (obj), TYPE_AW_H3)
81
trace_resettable_reset_release_begin(obj, type);
126
+
82
assert(!enter_phase_in_progress);
127
+/** @} */
83
128
+
84
+ exit_phase_in_progress += 1;
129
+/**
85
resettable_phase_exit(obj, NULL, type);
130
+ * Allwinner H3 object
86
+ exit_phase_in_progress -= 1;
131
+ *
87
132
+ * This struct contains the state of all the devices
88
trace_resettable_reset_release_end(obj);
133
+ * which are currently emulated by the H3 SoC code.
89
}
134
+ */
90
@@ -XXX,XX +XXX,XX @@ static void resettable_phase_exit(Object *obj, void *opaque, ResetType type)
135
+typedef struct AwH3State {
91
trace_resettable_phase_exit_end(obj, obj_typename, s->count);
136
+ /*< private >*/
92
}
137
+ DeviceState parent_obj;
93
138
+ /*< public >*/
139
+
140
+ ARMCPU cpus[AW_H3_NUM_CPUS];
141
+ const hwaddr *memmap;
142
+ AwA10PITState timer;
143
+ GICState gic;
144
+ MemoryRegion sram_a1;
145
+ MemoryRegion sram_a2;
146
+ MemoryRegion sram_c;
147
+} AwH3State;
148
+
149
+#endif /* HW_ARM_ALLWINNER_H3_H */
150
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
151
new file mode 100644
152
index XXXXXXX..XXXXXXX
153
--- /dev/null
154
+++ b/hw/arm/allwinner-h3.c
155
@@ -XXX,XX +XXX,XX @@
94
+/*
156
+/*
95
+ * resettable_get_count:
157
+ * Allwinner H3 System on Chip emulation
96
+ * Get the count of the Resettable object @obj. Return 0 if @obj is NULL.
158
+ *
159
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
160
+ *
161
+ * This program is free software: you can redistribute it and/or modify
162
+ * it under the terms of the GNU General Public License as published by
163
+ * the Free Software Foundation, either version 2 of the License, or
164
+ * (at your option) any later version.
165
+ *
166
+ * This program is distributed in the hope that it will be useful,
167
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
168
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
169
+ * GNU General Public License for more details.
170
+ *
171
+ * You should have received a copy of the GNU General Public License
172
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
97
+ */
173
+ */
98
+static unsigned resettable_get_count(Object *obj)
174
+
175
+#include "qemu/osdep.h"
176
+#include "exec/address-spaces.h"
177
+#include "qapi/error.h"
178
+#include "qemu/error-report.h"
179
+#include "qemu/module.h"
180
+#include "qemu/units.h"
181
+#include "hw/qdev-core.h"
182
+#include "cpu.h"
183
+#include "hw/sysbus.h"
184
+#include "hw/char/serial.h"
185
+#include "hw/misc/unimp.h"
186
+#include "sysemu/sysemu.h"
187
+#include "hw/arm/allwinner-h3.h"
188
+
189
+/* Memory map */
190
+const hwaddr allwinner_h3_memmap[] = {
191
+ [AW_H3_SRAM_A1] = 0x00000000,
192
+ [AW_H3_SRAM_A2] = 0x00044000,
193
+ [AW_H3_SRAM_C] = 0x00010000,
194
+ [AW_H3_PIT] = 0x01c20c00,
195
+ [AW_H3_UART0] = 0x01c28000,
196
+ [AW_H3_UART1] = 0x01c28400,
197
+ [AW_H3_UART2] = 0x01c28800,
198
+ [AW_H3_UART3] = 0x01c28c00,
199
+ [AW_H3_GIC_DIST] = 0x01c81000,
200
+ [AW_H3_GIC_CPU] = 0x01c82000,
201
+ [AW_H3_GIC_HYP] = 0x01c84000,
202
+ [AW_H3_GIC_VCPU] = 0x01c86000,
203
+ [AW_H3_SDRAM] = 0x40000000
204
+};
205
+
206
+/* List of unimplemented devices */
207
+struct AwH3Unimplemented {
208
+ const char *device_name;
209
+ hwaddr base;
210
+ hwaddr size;
211
+} unimplemented[] = {
212
+ { "d-engine", 0x01000000, 4 * MiB },
213
+ { "d-inter", 0x01400000, 128 * KiB },
214
+ { "syscon", 0x01c00000, 4 * KiB },
215
+ { "dma", 0x01c02000, 4 * KiB },
216
+ { "nfdc", 0x01c03000, 4 * KiB },
217
+ { "ts", 0x01c06000, 4 * KiB },
218
+ { "keymem", 0x01c0b000, 4 * KiB },
219
+ { "lcd0", 0x01c0c000, 4 * KiB },
220
+ { "lcd1", 0x01c0d000, 4 * KiB },
221
+ { "ve", 0x01c0e000, 4 * KiB },
222
+ { "mmc0", 0x01c0f000, 4 * KiB },
223
+ { "mmc1", 0x01c10000, 4 * KiB },
224
+ { "mmc2", 0x01c11000, 4 * KiB },
225
+ { "sid", 0x01c14000, 1 * KiB },
226
+ { "crypto", 0x01c15000, 4 * KiB },
227
+ { "msgbox", 0x01c17000, 4 * KiB },
228
+ { "spinlock", 0x01c18000, 4 * KiB },
229
+ { "usb0-otg", 0x01c19000, 4 * KiB },
230
+ { "usb0-phy", 0x01c1a000, 4 * KiB },
231
+ { "usb1-phy", 0x01c1b000, 4 * KiB },
232
+ { "usb2-phy", 0x01c1c000, 4 * KiB },
233
+ { "usb3-phy", 0x01c1d000, 4 * KiB },
234
+ { "smc", 0x01c1e000, 4 * KiB },
235
+ { "ccu", 0x01c20000, 1 * KiB },
236
+ { "pio", 0x01c20800, 1 * KiB },
237
+ { "owa", 0x01c21000, 1 * KiB },
238
+ { "pwm", 0x01c21400, 1 * KiB },
239
+ { "keyadc", 0x01c21800, 1 * KiB },
240
+ { "pcm0", 0x01c22000, 1 * KiB },
241
+ { "pcm1", 0x01c22400, 1 * KiB },
242
+ { "pcm2", 0x01c22800, 1 * KiB },
243
+ { "audio", 0x01c22c00, 2 * KiB },
244
+ { "smta", 0x01c23400, 1 * KiB },
245
+ { "ths", 0x01c25000, 1 * KiB },
246
+ { "uart0", 0x01c28000, 1 * KiB },
247
+ { "uart1", 0x01c28400, 1 * KiB },
248
+ { "uart2", 0x01c28800, 1 * KiB },
249
+ { "uart3", 0x01c28c00, 1 * KiB },
250
+ { "twi0", 0x01c2ac00, 1 * KiB },
251
+ { "twi1", 0x01c2b000, 1 * KiB },
252
+ { "twi2", 0x01c2b400, 1 * KiB },
253
+ { "scr", 0x01c2c400, 1 * KiB },
254
+ { "emac", 0x01c30000, 64 * KiB },
255
+ { "gpu", 0x01c40000, 64 * KiB },
256
+ { "hstmr", 0x01c60000, 4 * KiB },
257
+ { "dramcom", 0x01c62000, 4 * KiB },
258
+ { "dramctl0", 0x01c63000, 4 * KiB },
259
+ { "dramphy0", 0x01c65000, 4 * KiB },
260
+ { "spi0", 0x01c68000, 4 * KiB },
261
+ { "spi1", 0x01c69000, 4 * KiB },
262
+ { "csi", 0x01cb0000, 320 * KiB },
263
+ { "tve", 0x01e00000, 64 * KiB },
264
+ { "hdmi", 0x01ee0000, 128 * KiB },
265
+ { "rtc", 0x01f00000, 1 * KiB },
266
+ { "r_timer", 0x01f00800, 1 * KiB },
267
+ { "r_intc", 0x01f00c00, 1 * KiB },
268
+ { "r_wdog", 0x01f01000, 1 * KiB },
269
+ { "r_prcm", 0x01f01400, 1 * KiB },
270
+ { "r_twd", 0x01f01800, 1 * KiB },
271
+ { "r_cpucfg", 0x01f01c00, 1 * KiB },
272
+ { "r_cir-rx", 0x01f02000, 1 * KiB },
273
+ { "r_twi", 0x01f02400, 1 * KiB },
274
+ { "r_uart", 0x01f02800, 1 * KiB },
275
+ { "r_pio", 0x01f02c00, 1 * KiB },
276
+ { "r_pwm", 0x01f03800, 1 * KiB },
277
+ { "core-dbg", 0x3f500000, 128 * KiB },
278
+ { "tsgen-ro", 0x3f506000, 4 * KiB },
279
+ { "tsgen-ctl", 0x3f507000, 4 * KiB },
280
+ { "ddr-mem", 0x40000000, 2 * GiB },
281
+ { "n-brom", 0xffff0000, 32 * KiB },
282
+ { "s-brom", 0xffff0000, 64 * KiB }
283
+};
284
+
285
+/* Per Processor Interrupts */
286
+enum {
287
+ AW_H3_GIC_PPI_MAINT = 9,
288
+ AW_H3_GIC_PPI_HYPTIMER = 10,
289
+ AW_H3_GIC_PPI_VIRTTIMER = 11,
290
+ AW_H3_GIC_PPI_SECTIMER = 13,
291
+ AW_H3_GIC_PPI_PHYSTIMER = 14
292
+};
293
+
294
+/* Shared Processor Interrupts */
295
+enum {
296
+ AW_H3_GIC_SPI_UART0 = 0,
297
+ AW_H3_GIC_SPI_UART1 = 1,
298
+ AW_H3_GIC_SPI_UART2 = 2,
299
+ AW_H3_GIC_SPI_UART3 = 3,
300
+ AW_H3_GIC_SPI_TIMER0 = 18,
301
+ AW_H3_GIC_SPI_TIMER1 = 19,
302
+};
303
+
304
+/* Allwinner H3 general constants */
305
+enum {
306
+ AW_H3_GIC_NUM_SPI = 128
307
+};
308
+
309
+static void allwinner_h3_init(Object *obj)
99
+{
310
+{
100
+ if (obj) {
311
+ AwH3State *s = AW_H3(obj);
101
+ ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
312
+
102
+ return rc->get_state(obj)->count;
313
+ s->memmap = allwinner_h3_memmap;
314
+
315
+ for (int i = 0; i < AW_H3_NUM_CPUS; i++) {
316
+ object_initialize_child(obj, "cpu[*]", &s->cpus[i], sizeof(s->cpus[i]),
317
+ ARM_CPU_TYPE_NAME("cortex-a7"),
318
+ &error_abort, NULL);
103
+ }
319
+ }
104
+ return 0;
320
+
321
+ sysbus_init_child_obj(obj, "gic", &s->gic, sizeof(s->gic),
322
+ TYPE_ARM_GIC);
323
+
324
+ sysbus_init_child_obj(obj, "timer", &s->timer, sizeof(s->timer),
325
+ TYPE_AW_A10_PIT);
326
+ object_property_add_alias(obj, "clk0-freq", OBJECT(&s->timer),
327
+ "clk0-freq", &error_abort);
328
+ object_property_add_alias(obj, "clk1-freq", OBJECT(&s->timer),
329
+ "clk1-freq", &error_abort);
105
+}
330
+}
106
+
331
+
107
+void resettable_change_parent(Object *obj, Object *newp, Object *oldp)
332
+static void allwinner_h3_realize(DeviceState *dev, Error **errp)
108
+{
333
+{
109
+ ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
334
+ AwH3State *s = AW_H3(dev);
110
+ ResettableState *s = rc->get_state(obj);
335
+ unsigned i;
111
+ unsigned newp_count = resettable_get_count(newp);
336
+
112
+ unsigned oldp_count = resettable_get_count(oldp);
337
+ /* CPUs */
338
+ for (i = 0; i < AW_H3_NUM_CPUS; i++) {
339
+
340
+ /* Provide Power State Coordination Interface */
341
+ qdev_prop_set_int32(DEVICE(&s->cpus[i]), "psci-conduit",
342
+ QEMU_PSCI_CONDUIT_HVC);
343
+
344
+ /* Disable secondary CPUs */
345
+ qdev_prop_set_bit(DEVICE(&s->cpus[i]), "start-powered-off",
346
+ i > 0);
347
+
348
+ /* All exception levels required */
349
+ qdev_prop_set_bit(DEVICE(&s->cpus[i]), "has_el3", true);
350
+ qdev_prop_set_bit(DEVICE(&s->cpus[i]), "has_el2", true);
351
+
352
+ /* Mark realized */
353
+ qdev_init_nofail(DEVICE(&s->cpus[i]));
354
+ }
355
+
356
+ /* Generic Interrupt Controller */
357
+ qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", AW_H3_GIC_NUM_SPI +
358
+ GIC_INTERNAL);
359
+ qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 2);
360
+ qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", AW_H3_NUM_CPUS);
361
+ qdev_prop_set_bit(DEVICE(&s->gic), "has-security-extensions", false);
362
+ qdev_prop_set_bit(DEVICE(&s->gic), "has-virtualization-extensions", true);
363
+ qdev_init_nofail(DEVICE(&s->gic));
364
+
365
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 0, s->memmap[AW_H3_GIC_DIST]);
366
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 1, s->memmap[AW_H3_GIC_CPU]);
367
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 2, s->memmap[AW_H3_GIC_HYP]);
368
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 3, s->memmap[AW_H3_GIC_VCPU]);
113
+
369
+
114
+ /*
370
+ /*
115
+ * Ensure we do not change parent when in enter or exit phase.
371
+ * Wire the outputs from each CPU's generic timer and the GICv3
116
+ * During these phases, the reset subtree being updated is partly in reset
372
+ * maintenance interrupt signal to the appropriate GIC PPI inputs,
117
+ * and partly not in reset (it depends on the actual position in
373
+ * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs.
118
+ * resettable_child_foreach()s). We are not able to tell in which part is a
119
+ * leaving or arriving device. Thus we cannot set the reset count of the
120
+ * moving device to the proper value.
121
+ */
374
+ */
122
+ assert(!enter_phase_in_progress && !exit_phase_in_progress);
375
+ for (i = 0; i < AW_H3_NUM_CPUS; i++) {
123
+ trace_resettable_change_parent(obj, oldp, oldp_count, newp, newp_count);
376
+ DeviceState *cpudev = DEVICE(&s->cpus[i]);
124
+
377
+ int ppibase = AW_H3_GIC_NUM_SPI + i * GIC_INTERNAL + GIC_NR_SGIS;
125
+ /*
378
+ int irq;
126
+ * At most one of the two 'for' loops will be executed below
379
+ /*
127
+ * in order to cope with the difference between the two counts.
380
+ * Mapping from the output timer irq lines from the CPU to the
128
+ */
381
+ * GIC PPI inputs used for this board.
129
+ /* if newp is more reset than oldp */
382
+ */
130
+ for (unsigned i = oldp_count; i < newp_count; i++) {
383
+ const int timer_irq[] = {
131
+ resettable_assert_reset(obj, RESET_TYPE_COLD);
384
+ [GTIMER_PHYS] = AW_H3_GIC_PPI_PHYSTIMER,
385
+ [GTIMER_VIRT] = AW_H3_GIC_PPI_VIRTTIMER,
386
+ [GTIMER_HYP] = AW_H3_GIC_PPI_HYPTIMER,
387
+ [GTIMER_SEC] = AW_H3_GIC_PPI_SECTIMER,
388
+ };
389
+
390
+ /* Connect CPU timer outputs to GIC PPI inputs */
391
+ for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
392
+ qdev_connect_gpio_out(cpudev, irq,
393
+ qdev_get_gpio_in(DEVICE(&s->gic),
394
+ ppibase + timer_irq[irq]));
395
+ }
396
+
397
+ /* Connect GIC outputs to CPU interrupt inputs */
398
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i,
399
+ qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
400
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + AW_H3_NUM_CPUS,
401
+ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
402
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + (2 * AW_H3_NUM_CPUS),
403
+ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
404
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + (3 * AW_H3_NUM_CPUS),
405
+ qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
406
+
407
+ /* GIC maintenance signal */
408
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i + (4 * AW_H3_NUM_CPUS),
409
+ qdev_get_gpio_in(DEVICE(&s->gic),
410
+ ppibase + AW_H3_GIC_PPI_MAINT));
132
+ }
411
+ }
133
+ /*
412
+
134
+ * if obj is leaving a bus under reset, we need to ensure
413
+ /* Timer */
135
+ * hold phase is not pending.
414
+ qdev_init_nofail(DEVICE(&s->timer));
136
+ */
415
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->timer), 0, s->memmap[AW_H3_PIT]);
137
+ if (oldp_count && s->hold_phase_pending) {
416
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer), 0,
138
+ resettable_phase_hold(obj, NULL, RESET_TYPE_COLD);
417
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_TIMER0));
139
+ }
418
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer), 1,
140
+ /* if oldp is more reset than newp */
419
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_TIMER1));
141
+ for (unsigned i = newp_count; i < oldp_count; i++) {
420
+
142
+ resettable_release_reset(obj, RESET_TYPE_COLD);
421
+ /* SRAM */
422
+ memory_region_init_ram(&s->sram_a1, OBJECT(dev), "sram A1",
423
+ 64 * KiB, &error_abort);
424
+ memory_region_init_ram(&s->sram_a2, OBJECT(dev), "sram A2",
425
+ 32 * KiB, &error_abort);
426
+ memory_region_init_ram(&s->sram_c, OBJECT(dev), "sram C",
427
+ 44 * KiB, &error_abort);
428
+ memory_region_add_subregion(get_system_memory(), s->memmap[AW_H3_SRAM_A1],
429
+ &s->sram_a1);
430
+ memory_region_add_subregion(get_system_memory(), s->memmap[AW_H3_SRAM_A2],
431
+ &s->sram_a2);
432
+ memory_region_add_subregion(get_system_memory(), s->memmap[AW_H3_SRAM_C],
433
+ &s->sram_c);
434
+
435
+ /* UART0. For future clocktree API: All UARTS are connected to APB2_CLK. */
436
+ serial_mm_init(get_system_memory(), s->memmap[AW_H3_UART0], 2,
437
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART0),
438
+ 115200, serial_hd(0), DEVICE_NATIVE_ENDIAN);
439
+ /* UART1 */
440
+ serial_mm_init(get_system_memory(), s->memmap[AW_H3_UART1], 2,
441
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART1),
442
+ 115200, serial_hd(1), DEVICE_NATIVE_ENDIAN);
443
+ /* UART2 */
444
+ serial_mm_init(get_system_memory(), s->memmap[AW_H3_UART2], 2,
445
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART2),
446
+ 115200, serial_hd(2), DEVICE_NATIVE_ENDIAN);
447
+ /* UART3 */
448
+ serial_mm_init(get_system_memory(), s->memmap[AW_H3_UART3], 2,
449
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART3),
450
+ 115200, serial_hd(3), DEVICE_NATIVE_ENDIAN);
451
+
452
+ /* Unimplemented devices */
453
+ for (i = 0; i < ARRAY_SIZE(unimplemented); i++) {
454
+ create_unimplemented_device(unimplemented[i].device_name,
455
+ unimplemented[i].base,
456
+ unimplemented[i].size);
143
+ }
457
+ }
144
+}
458
+}
145
+
459
+
146
void resettable_class_set_parent_phases(ResettableClass *rc,
460
+static void allwinner_h3_class_init(ObjectClass *oc, void *data)
147
ResettableEnterPhase enter,
461
+{
148
ResettableHoldPhase hold,
462
+ DeviceClass *dc = DEVICE_CLASS(oc);
149
diff --git a/hw/core/trace-events b/hw/core/trace-events
463
+
464
+ dc->realize = allwinner_h3_realize;
465
+ /* Reason: uses serial_hd() in realize function */
466
+ dc->user_creatable = false;
467
+}
468
+
469
+static const TypeInfo allwinner_h3_type_info = {
470
+ .name = TYPE_AW_H3,
471
+ .parent = TYPE_DEVICE,
472
+ .instance_size = sizeof(AwH3State),
473
+ .instance_init = allwinner_h3_init,
474
+ .class_init = allwinner_h3_class_init,
475
+};
476
+
477
+static void allwinner_h3_register_types(void)
478
+{
479
+ type_register_static(&allwinner_h3_type_info);
480
+}
481
+
482
+type_init(allwinner_h3_register_types)
483
diff --git a/MAINTAINERS b/MAINTAINERS
150
index XXXXXXX..XXXXXXX 100644
484
index XXXXXXX..XXXXXXX 100644
151
--- a/hw/core/trace-events
485
--- a/MAINTAINERS
152
+++ b/hw/core/trace-events
486
+++ b/MAINTAINERS
153
@@ -XXX,XX +XXX,XX @@ resettable_reset_assert_begin(void *obj, int cold) "obj=%p cold=%d"
487
@@ -XXX,XX +XXX,XX @@ F: hw/*/allwinner*
154
resettable_reset_assert_end(void *obj) "obj=%p"
488
F: include/hw/*/allwinner*
155
resettable_reset_release_begin(void *obj, int cold) "obj=%p cold=%d"
489
F: hw/arm/cubieboard.c
156
resettable_reset_release_end(void *obj) "obj=%p"
490
157
+resettable_change_parent(void *obj, void *o, unsigned oc, void *n, unsigned nc) "obj=%p from=%p(%d) to=%p(%d)"
491
+Allwinner-h3
158
resettable_phase_enter_begin(void *obj, const char *objtype, unsigned count, int type) "obj=%p(%s) count=%d type=%d"
492
+M: Niek Linnenbank <nieklinnenbank@gmail.com>
159
resettable_phase_enter_exec(void *obj, const char *objtype, int type, int has_method) "obj=%p(%s) type=%d method=%d"
493
+L: qemu-arm@nongnu.org
160
resettable_phase_enter_end(void *obj, const char *objtype, unsigned count) "obj=%p(%s) count=%d"
494
+S: Maintained
495
+F: hw/*/allwinner-h3*
496
+F: include/hw/*/allwinner-h3*
497
+
498
ARM PrimeCell and CMSDK devices
499
M: Peter Maydell <peter.maydell@linaro.org>
500
L: qemu-arm@nongnu.org
501
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
502
index XXXXXXX..XXXXXXX 100644
503
--- a/default-configs/arm-softmmu.mak
504
+++ b/default-configs/arm-softmmu.mak
505
@@ -XXX,XX +XXX,XX @@ CONFIG_FSL_IMX25=y
506
CONFIG_FSL_IMX7=y
507
CONFIG_FSL_IMX6UL=y
508
CONFIG_SEMIHOSTING=y
509
+CONFIG_ALLWINNER_H3=y
510
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
511
index XXXXXXX..XXXXXXX 100644
512
--- a/hw/arm/Kconfig
513
+++ b/hw/arm/Kconfig
514
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10
515
select SERIAL
516
select UNIMP
517
518
+config ALLWINNER_H3
519
+ bool
520
+ select ALLWINNER_A10_PIT
521
+ select SERIAL
522
+ select ARM_TIMER
523
+ select ARM_GIC
524
+ select UNIMP
525
+
526
config RASPI
527
bool
528
select FRAMEBUFFER
161
--
529
--
162
2.20.1
530
2.20.1
163
531
164
532
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
3
The Xunlong Orange Pi PC is an Allwinner H3 System on Chip
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
based embedded computer with mainline support in both U-Boot
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
and Linux. The board comes with a Quad Core Cortex A7 @ 1.3GHz,
6
Message-id: 20200123132823.1117486-10-damien.hedde@greensocs.com
6
1GiB RAM, 100Mbit ethernet, USB, SD/MMC, USB, HDMI and
7
various other I/O. This commit add support for the Xunlong
8
Orange Pi PC machine.
9
10
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
11
Tested-by: KONRAD Frederic <frederic.konrad@adacore.com>
12
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
15
Acked-by: Igor Mammedov <imammedo@redhat.com>
16
Message-id: 20200311221854.30370-3-nieklinnenbank@gmail.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
18
---
9
docs/devel/index.rst | 1 +
19
hw/arm/Makefile.objs | 2 +-
10
docs/devel/reset.rst | 289 +++++++++++++++++++++++++++++++++++++++++++
20
hw/arm/orangepi.c | 92 ++++++++++++++++++++++++++++++++++++++++++++
11
2 files changed, 290 insertions(+)
21
MAINTAINERS | 1 +
12
create mode 100644 docs/devel/reset.rst
22
3 files changed, 94 insertions(+), 1 deletion(-)
23
create mode 100644 hw/arm/orangepi.c
13
24
14
diff --git a/docs/devel/index.rst b/docs/devel/index.rst
25
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
15
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
16
--- a/docs/devel/index.rst
27
--- a/hw/arm/Makefile.objs
17
+++ b/docs/devel/index.rst
28
+++ b/hw/arm/Makefile.objs
18
@@ -XXX,XX +XXX,XX @@ Contents:
29
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_DIGIC) += digic.o
19
tcg
30
obj-$(CONFIG_OMAP) += omap1.o omap2.o
20
tcg-plugins
31
obj-$(CONFIG_STRONGARM) += strongarm.o
21
bitops
32
obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
22
+ reset
33
-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3.o
23
diff --git a/docs/devel/reset.rst b/docs/devel/reset.rst
34
+obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3.o orangepi.o
35
obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
36
obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
37
obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o
38
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
24
new file mode 100644
39
new file mode 100644
25
index XXXXXXX..XXXXXXX
40
index XXXXXXX..XXXXXXX
26
--- /dev/null
41
--- /dev/null
27
+++ b/docs/devel/reset.rst
42
+++ b/hw/arm/orangepi.c
28
@@ -XXX,XX +XXX,XX @@
43
@@ -XXX,XX +XXX,XX @@
44
+/*
45
+ * Orange Pi emulation
46
+ *
47
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
48
+ *
49
+ * This program is free software: you can redistribute it and/or modify
50
+ * it under the terms of the GNU General Public License as published by
51
+ * the Free Software Foundation, either version 2 of the License, or
52
+ * (at your option) any later version.
53
+ *
54
+ * This program is distributed in the hope that it will be useful,
55
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
56
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57
+ * GNU General Public License for more details.
58
+ *
59
+ * You should have received a copy of the GNU General Public License
60
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
61
+ */
29
+
62
+
30
+=======================================
63
+#include "qemu/osdep.h"
31
+Reset in QEMU: the Resettable interface
64
+#include "qemu/units.h"
32
+=======================================
65
+#include "exec/address-spaces.h"
66
+#include "qapi/error.h"
67
+#include "cpu.h"
68
+#include "hw/sysbus.h"
69
+#include "hw/boards.h"
70
+#include "hw/qdev-properties.h"
71
+#include "hw/arm/allwinner-h3.h"
72
+#include "sysemu/sysemu.h"
33
+
73
+
34
+The reset of qemu objects is handled using the resettable interface declared
74
+static struct arm_boot_info orangepi_binfo = {
35
+in ``include/hw/resettable.h``.
75
+ .nb_cpus = AW_H3_NUM_CPUS,
76
+};
36
+
77
+
37
+This interface allows objects to be grouped (on a tree basis); so that the
78
+static void orangepi_init(MachineState *machine)
38
+whole group can be reset consistently. Each individual member object does not
79
+{
39
+have to care about others; in particular, problems of order (which object is
80
+ AwH3State *h3;
40
+reset first) are addressed.
41
+
81
+
42
+As of now DeviceClass and BusClass implement this interface.
82
+ /* BIOS is not supported by this board */
43
+
83
+ if (bios_name) {
44
+
84
+ error_report("BIOS not supported for this machine");
45
+Triggering reset
85
+ exit(1);
46
+----------------
47
+
48
+This section documents the APIs which "users" of a resettable object should use
49
+to control it. All resettable control functions must be called while holding
50
+the iothread lock.
51
+
52
+You can apply a reset to an object using ``resettable_assert_reset()``. You need
53
+to call ``resettable_release_reset()`` to release the object from reset. To
54
+instantly reset an object, without keeping it in reset state, just call
55
+``resettable_reset()``. These functions take two parameters: a pointer to the
56
+object to reset and a reset type.
57
+
58
+Several types of reset will be supported. For now only cold reset is defined;
59
+others may be added later. The Resettable interface handles reset types with an
60
+enum:
61
+
62
+``RESET_TYPE_COLD``
63
+ Cold reset is supported by every resettable object. In QEMU, it means we reset
64
+ to the initial state corresponding to the start of QEMU; this might differ
65
+ from what is a real hardware cold reset. It differs from other resets (like
66
+ warm or bus resets) which may keep certain parts untouched.
67
+
68
+Calling ``resettable_reset()`` is equivalent to calling
69
+``resettable_assert_reset()`` then ``resettable_release_reset()``. It is
70
+possible to interleave multiple calls to these three functions. There may
71
+be several reset sources/controllers of a given object. The interface handles
72
+everything and the different reset controllers do not need to know anything
73
+about each others. The object will leave reset state only when each other
74
+controllers end their reset operation. This point is handled internally by
75
+maintaining a count of in-progress resets; it is crucial to call
76
+``resettable_release_reset()`` one time and only one time per
77
+``resettable_assert_reset()`` call.
78
+
79
+For now migration of a device or bus in reset is not supported. Care must be
80
+taken not to delay ``resettable_release_reset()`` after its
81
+``resettable_assert_reset()`` counterpart.
82
+
83
+Note that, since resettable is an interface, the API takes a simple Object as
84
+parameter. Still, it is a programming error to call a resettable function on a
85
+non-resettable object and it will trigger a run time assert error. Since most
86
+calls to resettable interface are done through base class functions, such an
87
+error is not likely to happen.
88
+
89
+For Devices and Buses, the following helper functions exist:
90
+
91
+- ``device_cold_reset()``
92
+- ``bus_cold_reset()``
93
+
94
+These are simple wrappers around resettable_reset() function; they only cast the
95
+Device or Bus into an Object and pass the cold reset type. When possible
96
+prefer to use these functions instead of ``resettable_reset()``.
97
+
98
+Device and bus functions co-exist because there can be semantic differences
99
+between resetting a bus and resetting the controller bridge which owns it.
100
+For example, consider a SCSI controller. Resetting the controller puts all
101
+its registers back to what reset state was as well as reset everything on the
102
+SCSI bus, whereas resetting just the SCSI bus only resets everything that's on
103
+it but not the controller.
104
+
105
+
106
+Multi-phase mechanism
107
+---------------------
108
+
109
+This section documents the internals of the resettable interface.
110
+
111
+The resettable interface uses a multi-phase system to relieve objects and
112
+machines from reset ordering problems. To address this, the reset operation
113
+of an object is split into three well defined phases.
114
+
115
+When resetting several objects (for example the whole machine at simulation
116
+startup), all first phases of all objects are executed, then all second phases
117
+and then all third phases.
118
+
119
+The three phases are:
120
+
121
+1. The **enter** phase is executed when the object enters reset. It resets only
122
+ local state of the object; it must not do anything that has a side-effect
123
+ on other objects, such as raising or lowering a qemu_irq line or reading or
124
+ writing guest memory.
125
+
126
+2. The **hold** phase is executed for entry into reset, once every object in the
127
+ group which is being reset has had its *enter* phase executed. At this point
128
+ devices can do actions that affect other objects.
129
+
130
+3. The **exit** phase is executed when the object leaves the reset state.
131
+ Actions affecting other objects are permitted.
132
+
133
+As said in previous section, the interface maintains a count of reset. This
134
+count is used to ensure phases are executed only when required. *enter* and
135
+*hold* phases are executed only when asserting reset for the first time
136
+(if an object is already in reset state when calling
137
+``resettable_assert_reset()`` or ``resettable_reset()``, they are not
138
+executed).
139
+The *exit* phase is executed only when the last reset operation ends. Therefore
140
+the object does not need to care how many of reset controllers it has and how
141
+many of them have started a reset.
142
+
143
+
144
+Handling reset in a resettable object
145
+-------------------------------------
146
+
147
+This section documents the APIs that an implementation of a resettable object
148
+must provide and what functions it has access to. It is intended for people
149
+who want to implement or convert a class which has the resettable interface;
150
+for example when specializing an existing device or bus.
151
+
152
+Methods to implement
153
+....................
154
+
155
+Three methods should be defined or left empty. Each method corresponds to a
156
+phase of the reset; they are name ``phases.enter()``, ``phases.hold()`` and
157
+``phases.exit()``. They all take the object as parameter. The *enter* method
158
+also take the reset type as second parameter.
159
+
160
+When extending an existing class, these methods may need to be extended too.
161
+The ``resettable_class_set_parent_phases()`` class function may be used to
162
+backup parent class methods.
163
+
164
+Here follows an example to implement reset for a Device which sets an IO while
165
+in reset.
166
+
167
+::
168
+
169
+ static void mydev_reset_enter(Object *obj, ResetType type)
170
+ {
171
+ MyDevClass *myclass = MYDEV_GET_CLASS(obj);
172
+ MyDevState *mydev = MYDEV(obj);
173
+ /* call parent class enter phase */
174
+ if (myclass->parent_phases.enter) {
175
+ myclass->parent_phases.enter(obj, type);
176
+ }
177
+ /* initialize local state only */
178
+ mydev->var = 0;
179
+ }
86
+ }
180
+
87
+
181
+ static void mydev_reset_hold(Object *obj)
88
+ /* This board has fixed size RAM */
182
+ {
89
+ if (machine->ram_size != 1 * GiB) {
183
+ MyDevClass *myclass = MYDEV_GET_CLASS(obj);
90
+ error_report("This machine can only be used with 1GiB of RAM");
184
+ MyDevState *mydev = MYDEV(obj);
91
+ exit(1);
185
+ /* call parent class hold phase */
186
+ if (myclass->parent_phases.hold) {
187
+ myclass->parent_phases.hold(obj);
188
+ }
189
+ /* set an IO */
190
+ qemu_set_irq(mydev->irq, 1);
191
+ }
92
+ }
192
+
93
+
193
+ static void mydev_reset_exit(Object *obj)
94
+ /* Only allow Cortex-A7 for this board */
194
+ {
95
+ if (strcmp(machine->cpu_type, ARM_CPU_TYPE_NAME("cortex-a7")) != 0) {
195
+ MyDevClass *myclass = MYDEV_GET_CLASS(obj);
96
+ error_report("This board can only be used with cortex-a7 CPU");
196
+ MyDevState *mydev = MYDEV(obj);
97
+ exit(1);
197
+ /* call parent class exit phase */
198
+ if (myclass->parent_phases.exit) {
199
+ myclass->parent_phases.exit(obj);
200
+ }
201
+ /* clear an IO */
202
+ qemu_set_irq(mydev->irq, 0);
203
+ }
98
+ }
204
+
99
+
205
+ typedef struct MyDevClass {
100
+ h3 = AW_H3(object_new(TYPE_AW_H3));
206
+ MyParentClass parent_class;
101
+ object_property_add_child(OBJECT(machine), "soc", OBJECT(h3),
207
+ /* to store eventual parent reset methods */
102
+ &error_abort);
208
+ ResettablePhases parent_phases;
103
+ object_unref(OBJECT(h3));
209
+ } MyDevClass;
210
+
104
+
211
+ static void mydev_class_init(ObjectClass *class, void *data)
105
+ /* Setup timer properties */
212
+ {
106
+ object_property_set_int(OBJECT(h3), 32768, "clk0-freq",
213
+ MyDevClass *myclass = MYDEV_CLASS(class);
107
+ &error_abort);
214
+ ResettableClass *rc = RESETTABLE_CLASS(class);
108
+ object_property_set_int(OBJECT(h3), 24 * 1000 * 1000, "clk1-freq",
215
+ resettable_class_set_parent_reset_phases(rc,
109
+ &error_abort);
216
+ mydev_reset_enter,
217
+ mydev_reset_hold,
218
+ mydev_reset_exit,
219
+ &myclass->parent_phases);
220
+ }
221
+
110
+
222
+In the above example, we override all three phases. It is possible to override
111
+ /* Mark H3 object realized */
223
+only some of them by passing NULL instead of a function pointer to
112
+ object_property_set_bool(OBJECT(h3), true, "realized", &error_abort);
224
+``resettable_class_set_parent_reset_phases()``. For example, the following will
225
+only override the *enter* phase and leave *hold* and *exit* untouched::
226
+
113
+
227
+ resettable_class_set_parent_reset_phases(rc, mydev_reset_enter,
114
+ /* SDRAM */
228
+ NULL, NULL,
115
+ memory_region_add_subregion(get_system_memory(), h3->memmap[AW_H3_SDRAM],
229
+ &myclass->parent_phases);
116
+ machine->ram);
230
+
117
+
231
+This is equivalent to providing a trivial implementation of the hold and exit
118
+ orangepi_binfo.loader_start = h3->memmap[AW_H3_SDRAM];
232
+phases which does nothing but call the parent class's implementation of the
119
+ orangepi_binfo.ram_size = machine->ram_size;
233
+phase.
120
+ arm_load_kernel(ARM_CPU(first_cpu), machine, &orangepi_binfo);
121
+}
234
+
122
+
235
+Polling the reset state
123
+static void orangepi_machine_init(MachineClass *mc)
236
+.......................
124
+{
125
+ mc->desc = "Orange Pi PC";
126
+ mc->init = orangepi_init;
127
+ mc->min_cpus = AW_H3_NUM_CPUS;
128
+ mc->max_cpus = AW_H3_NUM_CPUS;
129
+ mc->default_cpus = AW_H3_NUM_CPUS;
130
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a7");
131
+ mc->default_ram_size = 1 * GiB;
132
+ mc->default_ram_id = "orangepi.ram";
133
+}
237
+
134
+
238
+Resettable interface provides the ``resettable_is_in_reset()`` function.
135
+DEFINE_MACHINE("orangepi-pc", orangepi_machine_init)
239
+This function returns true if the object parameter is currently under reset.
136
diff --git a/MAINTAINERS b/MAINTAINERS
240
+
137
index XXXXXXX..XXXXXXX 100644
241
+An object is under reset from the beginning of the *init* phase to the end of
138
--- a/MAINTAINERS
242
+the *exit* phase. During all three phases, the function will return that the
139
+++ b/MAINTAINERS
243
+object is in reset.
140
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
244
+
141
S: Maintained
245
+This function may be used if the object behavior has to be adapted
142
F: hw/*/allwinner-h3*
246
+while in reset state. For example if a device has an irq input,
143
F: include/hw/*/allwinner-h3*
247
+it will probably need to ignore it while in reset; then it can for
144
+F: hw/arm/orangepi.c
248
+example check the reset state at the beginning of the irq callback.
145
249
+
146
ARM PrimeCell and CMSDK devices
250
+Note that until migration of the reset state is supported, an object
147
M: Peter Maydell <peter.maydell@linaro.org>
251
+should not be left in reset. So apart from being currently executing
252
+one of the reset phases, the only cases when this function will return
253
+true is if an external interaction (like changing an io) is made during
254
+*hold* or *exit* phase of another object in the same reset group.
255
+
256
+Helpers ``device_is_in_reset()`` and ``bus_is_in_reset()`` are also provided
257
+for devices and buses and should be preferred.
258
+
259
+
260
+Base class handling of reset
261
+----------------------------
262
+
263
+This section documents parts of the reset mechanism that you only need to know
264
+about if you are extending it to work with a new base class other than
265
+DeviceClass or BusClass, or maintaining the existing code in those classes. Most
266
+people can ignore it.
267
+
268
+Methods to implement
269
+....................
270
+
271
+There are two other methods that need to exist in a class implementing the
272
+interface: ``get_state()`` and ``child_foreach()``.
273
+
274
+``get_state()`` is simple. *resettable* is an interface and, as a consequence,
275
+does not have any class state structure. But in order to factorize the code, we
276
+need one. This method must return a pointer to ``ResettableState`` structure.
277
+The structure must be allocated by the base class; preferably it should be
278
+located inside the object instance structure.
279
+
280
+``child_foreach()`` is more complex. It should execute the given callback on
281
+every reset child of the given resettable object. All children must be
282
+resettable too. Additional parameters (a reset type and an opaque pointer) must
283
+be passed to the callback too.
284
+
285
+In ``DeviceClass`` and ``BusClass`` the ``ResettableState`` is located
286
+``DeviceState`` and ``BusState`` structure. ``child_foreach()`` is implemented
287
+to follow the bus hierarchy; for a bus, it calls the function on every child
288
+device; for a device, it calls the function on every bus child. When we reset
289
+the main system bus, we reset the whole machine bus tree.
290
+
291
+Changing a resettable parent
292
+............................
293
+
294
+One thing which should be taken care of by the base class is handling reset
295
+hierarchy changes.
296
+
297
+The reset hierarchy is supposed to be static and built during machine creation.
298
+But there are actually some exceptions. To cope with this, the resettable API
299
+provides ``resettable_change_parent()``. This function allows to set, update or
300
+remove the parent of a resettable object after machine creation is done. As
301
+parameters, it takes the object being moved, the old parent if any and the new
302
+parent if any.
303
+
304
+This function can be used at any time when not in a reset operation. During
305
+a reset operation it must be used only in *hold* phase. Using it in *enter* or
306
+*exit* phase is an error.
307
+Also it should not be used during machine creation, although it is harmless to
308
+do so: the function is a no-op as long as old and new parent are NULL or not
309
+in reset.
310
+
311
+There is currently 2 cases where this function is used:
312
+
313
+1. *device hotplug*; it means a new device is introduced on a live bus.
314
+
315
+2. *hot bus change*; it means an existing live device is added, moved or
316
+ removed in the bus hierarchy. At the moment, it occurs only in the raspi
317
+ machines for changing the sdbus used by sd card.
318
--
148
--
319
2.20.1
149
2.20.1
320
150
321
151
diff view generated by jsdifflib
New patch
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
1
2
3
The Clock Control Unit is responsible for clock signal generation,
4
configuration and distribution in the Allwinner H3 System on Chip.
5
This commit adds support for the Clock Control Unit which emulates
6
a simple read/write register interface.
7
8
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Message-id: 20200311221854.30370-4-nieklinnenbank@gmail.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
hw/misc/Makefile.objs | 1 +
16
include/hw/arm/allwinner-h3.h | 3 +
17
include/hw/misc/allwinner-h3-ccu.h | 66 ++++++++
18
hw/arm/allwinner-h3.c | 9 +-
19
hw/misc/allwinner-h3-ccu.c | 242 +++++++++++++++++++++++++++++
20
5 files changed, 320 insertions(+), 1 deletion(-)
21
create mode 100644 include/hw/misc/allwinner-h3-ccu.h
22
create mode 100644 hw/misc/allwinner-h3-ccu.c
23
24
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
25
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/misc/Makefile.objs
27
+++ b/hw/misc/Makefile.objs
28
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_MACIO) += macio/
29
30
common-obj-$(CONFIG_IVSHMEM_DEVICE) += ivshmem.o
31
32
+common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-ccu.o
33
common-obj-$(CONFIG_REALVIEW) += arm_sysctl.o
34
common-obj-$(CONFIG_NSERIES) += cbus.o
35
common-obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
36
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/arm/allwinner-h3.h
39
+++ b/include/hw/arm/allwinner-h3.h
40
@@ -XXX,XX +XXX,XX @@
41
#include "hw/arm/boot.h"
42
#include "hw/timer/allwinner-a10-pit.h"
43
#include "hw/intc/arm_gic.h"
44
+#include "hw/misc/allwinner-h3-ccu.h"
45
#include "target/arm/cpu.h"
46
47
/**
48
@@ -XXX,XX +XXX,XX @@ enum {
49
AW_H3_SRAM_A1,
50
AW_H3_SRAM_A2,
51
AW_H3_SRAM_C,
52
+ AW_H3_CCU,
53
AW_H3_PIT,
54
AW_H3_UART0,
55
AW_H3_UART1,
56
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
57
ARMCPU cpus[AW_H3_NUM_CPUS];
58
const hwaddr *memmap;
59
AwA10PITState timer;
60
+ AwH3ClockCtlState ccu;
61
GICState gic;
62
MemoryRegion sram_a1;
63
MemoryRegion sram_a2;
64
diff --git a/include/hw/misc/allwinner-h3-ccu.h b/include/hw/misc/allwinner-h3-ccu.h
65
new file mode 100644
66
index XXXXXXX..XXXXXXX
67
--- /dev/null
68
+++ b/include/hw/misc/allwinner-h3-ccu.h
69
@@ -XXX,XX +XXX,XX @@
70
+/*
71
+ * Allwinner H3 Clock Control Unit emulation
72
+ *
73
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
74
+ *
75
+ * This program is free software: you can redistribute it and/or modify
76
+ * it under the terms of the GNU General Public License as published by
77
+ * the Free Software Foundation, either version 2 of the License, or
78
+ * (at your option) any later version.
79
+ *
80
+ * This program is distributed in the hope that it will be useful,
81
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
82
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83
+ * GNU General Public License for more details.
84
+ *
85
+ * You should have received a copy of the GNU General Public License
86
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
87
+ */
88
+
89
+#ifndef HW_MISC_ALLWINNER_H3_CCU_H
90
+#define HW_MISC_ALLWINNER_H3_CCU_H
91
+
92
+#include "qom/object.h"
93
+#include "hw/sysbus.h"
94
+
95
+/**
96
+ * @name Constants
97
+ * @{
98
+ */
99
+
100
+/** Size of register I/O address space used by CCU device */
101
+#define AW_H3_CCU_IOSIZE (0x400)
102
+
103
+/** Total number of known registers */
104
+#define AW_H3_CCU_REGS_NUM (AW_H3_CCU_IOSIZE / sizeof(uint32_t))
105
+
106
+/** @} */
107
+
108
+/**
109
+ * @name Object model
110
+ * @{
111
+ */
112
+
113
+#define TYPE_AW_H3_CCU "allwinner-h3-ccu"
114
+#define AW_H3_CCU(obj) \
115
+ OBJECT_CHECK(AwH3ClockCtlState, (obj), TYPE_AW_H3_CCU)
116
+
117
+/** @} */
118
+
119
+/**
120
+ * Allwinner H3 CCU object instance state.
121
+ */
122
+typedef struct AwH3ClockCtlState {
123
+ /*< private >*/
124
+ SysBusDevice parent_obj;
125
+ /*< public >*/
126
+
127
+ /** Maps I/O registers in physical memory */
128
+ MemoryRegion iomem;
129
+
130
+ /** Array of hardware registers */
131
+ uint32_t regs[AW_H3_CCU_REGS_NUM];
132
+
133
+} AwH3ClockCtlState;
134
+
135
+#endif /* HW_MISC_ALLWINNER_H3_CCU_H */
136
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
137
index XXXXXXX..XXXXXXX 100644
138
--- a/hw/arm/allwinner-h3.c
139
+++ b/hw/arm/allwinner-h3.c
140
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
141
[AW_H3_SRAM_A1] = 0x00000000,
142
[AW_H3_SRAM_A2] = 0x00044000,
143
[AW_H3_SRAM_C] = 0x00010000,
144
+ [AW_H3_CCU] = 0x01c20000,
145
[AW_H3_PIT] = 0x01c20c00,
146
[AW_H3_UART0] = 0x01c28000,
147
[AW_H3_UART1] = 0x01c28400,
148
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
149
{ "usb2-phy", 0x01c1c000, 4 * KiB },
150
{ "usb3-phy", 0x01c1d000, 4 * KiB },
151
{ "smc", 0x01c1e000, 4 * KiB },
152
- { "ccu", 0x01c20000, 1 * KiB },
153
{ "pio", 0x01c20800, 1 * KiB },
154
{ "owa", 0x01c21000, 1 * KiB },
155
{ "pwm", 0x01c21400, 1 * KiB },
156
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
157
"clk0-freq", &error_abort);
158
object_property_add_alias(obj, "clk1-freq", OBJECT(&s->timer),
159
"clk1-freq", &error_abort);
160
+
161
+ sysbus_init_child_obj(obj, "ccu", &s->ccu, sizeof(s->ccu),
162
+ TYPE_AW_H3_CCU);
163
}
164
165
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
166
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
167
memory_region_add_subregion(get_system_memory(), s->memmap[AW_H3_SRAM_C],
168
&s->sram_c);
169
170
+ /* Clock Control Unit */
171
+ qdev_init_nofail(DEVICE(&s->ccu));
172
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccu), 0, s->memmap[AW_H3_CCU]);
173
+
174
/* UART0. For future clocktree API: All UARTS are connected to APB2_CLK. */
175
serial_mm_init(get_system_memory(), s->memmap[AW_H3_UART0], 2,
176
qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART0),
177
diff --git a/hw/misc/allwinner-h3-ccu.c b/hw/misc/allwinner-h3-ccu.c
178
new file mode 100644
179
index XXXXXXX..XXXXXXX
180
--- /dev/null
181
+++ b/hw/misc/allwinner-h3-ccu.c
182
@@ -XXX,XX +XXX,XX @@
183
+/*
184
+ * Allwinner H3 Clock Control Unit emulation
185
+ *
186
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
187
+ *
188
+ * This program is free software: you can redistribute it and/or modify
189
+ * it under the terms of the GNU General Public License as published by
190
+ * the Free Software Foundation, either version 2 of the License, or
191
+ * (at your option) any later version.
192
+ *
193
+ * This program is distributed in the hope that it will be useful,
194
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
195
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
196
+ * GNU General Public License for more details.
197
+ *
198
+ * You should have received a copy of the GNU General Public License
199
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
200
+ */
201
+
202
+#include "qemu/osdep.h"
203
+#include "qemu/units.h"
204
+#include "hw/sysbus.h"
205
+#include "migration/vmstate.h"
206
+#include "qemu/log.h"
207
+#include "qemu/module.h"
208
+#include "hw/misc/allwinner-h3-ccu.h"
209
+
210
+/* CCU register offsets */
211
+enum {
212
+ REG_PLL_CPUX = 0x0000, /* PLL CPUX Control */
213
+ REG_PLL_AUDIO = 0x0008, /* PLL Audio Control */
214
+ REG_PLL_VIDEO = 0x0010, /* PLL Video Control */
215
+ REG_PLL_VE = 0x0018, /* PLL VE Control */
216
+ REG_PLL_DDR = 0x0020, /* PLL DDR Control */
217
+ REG_PLL_PERIPH0 = 0x0028, /* PLL Peripherals 0 Control */
218
+ REG_PLL_GPU = 0x0038, /* PLL GPU Control */
219
+ REG_PLL_PERIPH1 = 0x0044, /* PLL Peripherals 1 Control */
220
+ REG_PLL_DE = 0x0048, /* PLL Display Engine Control */
221
+ REG_CPUX_AXI = 0x0050, /* CPUX/AXI Configuration */
222
+ REG_APB1 = 0x0054, /* ARM Peripheral Bus 1 Config */
223
+ REG_APB2 = 0x0058, /* ARM Peripheral Bus 2 Config */
224
+ REG_DRAM_CFG = 0x00F4, /* DRAM Configuration */
225
+ REG_MBUS = 0x00FC, /* MBUS Reset */
226
+ REG_PLL_TIME0 = 0x0200, /* PLL Stable Time 0 */
227
+ REG_PLL_TIME1 = 0x0204, /* PLL Stable Time 1 */
228
+ REG_PLL_CPUX_BIAS = 0x0220, /* PLL CPUX Bias */
229
+ REG_PLL_AUDIO_BIAS = 0x0224, /* PLL Audio Bias */
230
+ REG_PLL_VIDEO_BIAS = 0x0228, /* PLL Video Bias */
231
+ REG_PLL_VE_BIAS = 0x022C, /* PLL VE Bias */
232
+ REG_PLL_DDR_BIAS = 0x0230, /* PLL DDR Bias */
233
+ REG_PLL_PERIPH0_BIAS = 0x0234, /* PLL Peripherals 0 Bias */
234
+ REG_PLL_GPU_BIAS = 0x023C, /* PLL GPU Bias */
235
+ REG_PLL_PERIPH1_BIAS = 0x0244, /* PLL Peripherals 1 Bias */
236
+ REG_PLL_DE_BIAS = 0x0248, /* PLL Display Engine Bias */
237
+ REG_PLL_CPUX_TUNING = 0x0250, /* PLL CPUX Tuning */
238
+ REG_PLL_DDR_TUNING = 0x0260, /* PLL DDR Tuning */
239
+};
240
+
241
+#define REG_INDEX(offset) (offset / sizeof(uint32_t))
242
+
243
+/* CCU register flags */
244
+enum {
245
+ REG_DRAM_CFG_UPDATE = (1 << 16),
246
+};
247
+
248
+enum {
249
+ REG_PLL_ENABLE = (1 << 31),
250
+ REG_PLL_LOCK = (1 << 28),
251
+};
252
+
253
+
254
+/* CCU register reset values */
255
+enum {
256
+ REG_PLL_CPUX_RST = 0x00001000,
257
+ REG_PLL_AUDIO_RST = 0x00035514,
258
+ REG_PLL_VIDEO_RST = 0x03006207,
259
+ REG_PLL_VE_RST = 0x03006207,
260
+ REG_PLL_DDR_RST = 0x00001000,
261
+ REG_PLL_PERIPH0_RST = 0x00041811,
262
+ REG_PLL_GPU_RST = 0x03006207,
263
+ REG_PLL_PERIPH1_RST = 0x00041811,
264
+ REG_PLL_DE_RST = 0x03006207,
265
+ REG_CPUX_AXI_RST = 0x00010000,
266
+ REG_APB1_RST = 0x00001010,
267
+ REG_APB2_RST = 0x01000000,
268
+ REG_DRAM_CFG_RST = 0x00000000,
269
+ REG_MBUS_RST = 0x80000000,
270
+ REG_PLL_TIME0_RST = 0x000000FF,
271
+ REG_PLL_TIME1_RST = 0x000000FF,
272
+ REG_PLL_CPUX_BIAS_RST = 0x08100200,
273
+ REG_PLL_AUDIO_BIAS_RST = 0x10100000,
274
+ REG_PLL_VIDEO_BIAS_RST = 0x10100000,
275
+ REG_PLL_VE_BIAS_RST = 0x10100000,
276
+ REG_PLL_DDR_BIAS_RST = 0x81104000,
277
+ REG_PLL_PERIPH0_BIAS_RST = 0x10100010,
278
+ REG_PLL_GPU_BIAS_RST = 0x10100000,
279
+ REG_PLL_PERIPH1_BIAS_RST = 0x10100010,
280
+ REG_PLL_DE_BIAS_RST = 0x10100000,
281
+ REG_PLL_CPUX_TUNING_RST = 0x0A101000,
282
+ REG_PLL_DDR_TUNING_RST = 0x14880000,
283
+};
284
+
285
+static uint64_t allwinner_h3_ccu_read(void *opaque, hwaddr offset,
286
+ unsigned size)
287
+{
288
+ const AwH3ClockCtlState *s = AW_H3_CCU(opaque);
289
+ const uint32_t idx = REG_INDEX(offset);
290
+
291
+ switch (offset) {
292
+ case 0x308 ... AW_H3_CCU_IOSIZE:
293
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
294
+ __func__, (uint32_t)offset);
295
+ return 0;
296
+ }
297
+
298
+ return s->regs[idx];
299
+}
300
+
301
+static void allwinner_h3_ccu_write(void *opaque, hwaddr offset,
302
+ uint64_t val, unsigned size)
303
+{
304
+ AwH3ClockCtlState *s = AW_H3_CCU(opaque);
305
+ const uint32_t idx = REG_INDEX(offset);
306
+
307
+ switch (offset) {
308
+ case REG_DRAM_CFG: /* DRAM Configuration */
309
+ val &= ~REG_DRAM_CFG_UPDATE;
310
+ break;
311
+ case REG_PLL_CPUX: /* PLL CPUX Control */
312
+ case REG_PLL_AUDIO: /* PLL Audio Control */
313
+ case REG_PLL_VIDEO: /* PLL Video Control */
314
+ case REG_PLL_VE: /* PLL VE Control */
315
+ case REG_PLL_DDR: /* PLL DDR Control */
316
+ case REG_PLL_PERIPH0: /* PLL Peripherals 0 Control */
317
+ case REG_PLL_GPU: /* PLL GPU Control */
318
+ case REG_PLL_PERIPH1: /* PLL Peripherals 1 Control */
319
+ case REG_PLL_DE: /* PLL Display Engine Control */
320
+ if (val & REG_PLL_ENABLE) {
321
+ val |= REG_PLL_LOCK;
322
+ }
323
+ break;
324
+ case 0x308 ... AW_H3_CCU_IOSIZE:
325
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
326
+ __func__, (uint32_t)offset);
327
+ break;
328
+ default:
329
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented write offset 0x%04x\n",
330
+ __func__, (uint32_t)offset);
331
+ break;
332
+ }
333
+
334
+ s->regs[idx] = (uint32_t) val;
335
+}
336
+
337
+static const MemoryRegionOps allwinner_h3_ccu_ops = {
338
+ .read = allwinner_h3_ccu_read,
339
+ .write = allwinner_h3_ccu_write,
340
+ .endianness = DEVICE_NATIVE_ENDIAN,
341
+ .valid = {
342
+ .min_access_size = 4,
343
+ .max_access_size = 4,
344
+ },
345
+ .impl.min_access_size = 4,
346
+};
347
+
348
+static void allwinner_h3_ccu_reset(DeviceState *dev)
349
+{
350
+ AwH3ClockCtlState *s = AW_H3_CCU(dev);
351
+
352
+ /* Set default values for registers */
353
+ s->regs[REG_INDEX(REG_PLL_CPUX)] = REG_PLL_CPUX_RST;
354
+ s->regs[REG_INDEX(REG_PLL_AUDIO)] = REG_PLL_AUDIO_RST;
355
+ s->regs[REG_INDEX(REG_PLL_VIDEO)] = REG_PLL_VIDEO_RST;
356
+ s->regs[REG_INDEX(REG_PLL_VE)] = REG_PLL_VE_RST;
357
+ s->regs[REG_INDEX(REG_PLL_DDR)] = REG_PLL_DDR_RST;
358
+ s->regs[REG_INDEX(REG_PLL_PERIPH0)] = REG_PLL_PERIPH0_RST;
359
+ s->regs[REG_INDEX(REG_PLL_GPU)] = REG_PLL_GPU_RST;
360
+ s->regs[REG_INDEX(REG_PLL_PERIPH1)] = REG_PLL_PERIPH1_RST;
361
+ s->regs[REG_INDEX(REG_PLL_DE)] = REG_PLL_DE_RST;
362
+ s->regs[REG_INDEX(REG_CPUX_AXI)] = REG_CPUX_AXI_RST;
363
+ s->regs[REG_INDEX(REG_APB1)] = REG_APB1_RST;
364
+ s->regs[REG_INDEX(REG_APB2)] = REG_APB2_RST;
365
+ s->regs[REG_INDEX(REG_DRAM_CFG)] = REG_DRAM_CFG_RST;
366
+ s->regs[REG_INDEX(REG_MBUS)] = REG_MBUS_RST;
367
+ s->regs[REG_INDEX(REG_PLL_TIME0)] = REG_PLL_TIME0_RST;
368
+ s->regs[REG_INDEX(REG_PLL_TIME1)] = REG_PLL_TIME1_RST;
369
+ s->regs[REG_INDEX(REG_PLL_CPUX_BIAS)] = REG_PLL_CPUX_BIAS_RST;
370
+ s->regs[REG_INDEX(REG_PLL_AUDIO_BIAS)] = REG_PLL_AUDIO_BIAS_RST;
371
+ s->regs[REG_INDEX(REG_PLL_VIDEO_BIAS)] = REG_PLL_VIDEO_BIAS_RST;
372
+ s->regs[REG_INDEX(REG_PLL_VE_BIAS)] = REG_PLL_VE_BIAS_RST;
373
+ s->regs[REG_INDEX(REG_PLL_DDR_BIAS)] = REG_PLL_DDR_BIAS_RST;
374
+ s->regs[REG_INDEX(REG_PLL_PERIPH0_BIAS)] = REG_PLL_PERIPH0_BIAS_RST;
375
+ s->regs[REG_INDEX(REG_PLL_GPU_BIAS)] = REG_PLL_GPU_BIAS_RST;
376
+ s->regs[REG_INDEX(REG_PLL_PERIPH1_BIAS)] = REG_PLL_PERIPH1_BIAS_RST;
377
+ s->regs[REG_INDEX(REG_PLL_DE_BIAS)] = REG_PLL_DE_BIAS_RST;
378
+ s->regs[REG_INDEX(REG_PLL_CPUX_TUNING)] = REG_PLL_CPUX_TUNING_RST;
379
+ s->regs[REG_INDEX(REG_PLL_DDR_TUNING)] = REG_PLL_DDR_TUNING_RST;
380
+}
381
+
382
+static void allwinner_h3_ccu_init(Object *obj)
383
+{
384
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
385
+ AwH3ClockCtlState *s = AW_H3_CCU(obj);
386
+
387
+ /* Memory mapping */
388
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_h3_ccu_ops, s,
389
+ TYPE_AW_H3_CCU, AW_H3_CCU_IOSIZE);
390
+ sysbus_init_mmio(sbd, &s->iomem);
391
+}
392
+
393
+static const VMStateDescription allwinner_h3_ccu_vmstate = {
394
+ .name = "allwinner-h3-ccu",
395
+ .version_id = 1,
396
+ .minimum_version_id = 1,
397
+ .fields = (VMStateField[]) {
398
+ VMSTATE_UINT32_ARRAY(regs, AwH3ClockCtlState, AW_H3_CCU_REGS_NUM),
399
+ VMSTATE_END_OF_LIST()
400
+ }
401
+};
402
+
403
+static void allwinner_h3_ccu_class_init(ObjectClass *klass, void *data)
404
+{
405
+ DeviceClass *dc = DEVICE_CLASS(klass);
406
+
407
+ dc->reset = allwinner_h3_ccu_reset;
408
+ dc->vmsd = &allwinner_h3_ccu_vmstate;
409
+}
410
+
411
+static const TypeInfo allwinner_h3_ccu_info = {
412
+ .name = TYPE_AW_H3_CCU,
413
+ .parent = TYPE_SYS_BUS_DEVICE,
414
+ .instance_init = allwinner_h3_ccu_init,
415
+ .instance_size = sizeof(AwH3ClockCtlState),
416
+ .class_init = allwinner_h3_ccu_class_init,
417
+};
418
+
419
+static void allwinner_h3_ccu_register(void)
420
+{
421
+ type_register_static(&allwinner_h3_ccu_info);
422
+}
423
+
424
+type_init(allwinner_h3_ccu_register)
425
--
426
2.20.1
427
428
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
This commit adds support of Resettable interface to buses and devices:
3
The Allwinner H3 System on Chip contains multiple USB 2.0 bus
4
+ ResettableState structure is added in the Bus/Device state
4
connections which provide software access using the Enhanced
5
+ Resettable methods are implemented.
5
Host Controller Interface (EHCI) and Open Host Controller
6
+ device/bus_is_in_reset function defined
6
Interface (OHCI) interfaces. This commit adds support for
7
both interfaces in the Allwinner H3 System on Chip.
7
8
8
This commit allows to transition the objects to the new
9
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
9
multi-phase interface without changing the reset behavior at all.
10
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
10
Object single reset method can be split into the 3 different phases
11
but the 3 phases are still executed in a row for a given object.
12
From the qdev/qbus reset api point of view, nothing is changed.
13
qdev_reset_all() and qbus_reset_all() are not modified as well as
14
device_legacy_reset().
15
16
Transition of an object must be done from parent class to child class.
17
Care has been taken to allow the transition of a parent class
18
without requiring the child classes to be transitioned at the same
19
time. Note that SysBus and SysBusDevice class do not need any transition
20
because they do not override the legacy reset method.
21
22
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
25
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
26
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
27
Message-id: 20200123132823.1117486-5-damien.hedde@greensocs.com
14
Message-id: 20200311221854.30370-5-nieklinnenbank@gmail.com
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
---
16
---
30
tests/Makefile.include | 1 +
17
hw/usb/hcd-ehci.h | 1 +
31
include/hw/qdev-core.h | 27 ++++++++++++
18
include/hw/arm/allwinner-h3.h | 8 +++++++
32
hw/core/bus.c | 97 ++++++++++++++++++++++++++++++++++++++++++
19
hw/arm/allwinner-h3.c | 44 +++++++++++++++++++++++++++++++++++
33
hw/core/qdev.c | 93 ++++++++++++++++++++++++++++++++++++++++
20
hw/usb/hcd-ehci-sysbus.c | 17 ++++++++++++++
34
4 files changed, 218 insertions(+)
21
hw/arm/Kconfig | 2 ++
22
5 files changed, 72 insertions(+)
35
23
36
diff --git a/tests/Makefile.include b/tests/Makefile.include
24
diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
37
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
38
--- a/tests/Makefile.include
26
--- a/hw/usb/hcd-ehci.h
39
+++ b/tests/Makefile.include
27
+++ b/hw/usb/hcd-ehci.h
40
@@ -XXX,XX +XXX,XX @@ tests/fp/%:
28
@@ -XXX,XX +XXX,XX @@ typedef struct EHCIPCIState {
41
tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \
29
#define TYPE_SYS_BUS_EHCI "sysbus-ehci-usb"
42
    hw/core/qdev.o hw/core/qdev-properties.o hw/core/hotplug.o\
30
#define TYPE_PLATFORM_EHCI "platform-ehci-usb"
43
    hw/core/bus.o \
31
#define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb"
44
+    hw/core/resettable.o \
32
+#define TYPE_AW_H3_EHCI "aw-h3-ehci-usb"
45
    hw/core/irq.o \
33
#define TYPE_TEGRA2_EHCI "tegra2-ehci-usb"
46
    hw/core/fw-path-provider.o \
34
#define TYPE_PPC4xx_EHCI "ppc4xx-ehci-usb"
47
    hw/core/reset.o \
35
#define TYPE_FUSBH200_EHCI "fusbh200-ehci-usb"
48
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
36
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
49
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
50
--- a/include/hw/qdev-core.h
38
--- a/include/hw/arm/allwinner-h3.h
51
+++ b/include/hw/qdev-core.h
39
+++ b/include/hw/arm/allwinner-h3.h
40
@@ -XXX,XX +XXX,XX @@ enum {
41
AW_H3_SRAM_A1,
42
AW_H3_SRAM_A2,
43
AW_H3_SRAM_C,
44
+ AW_H3_EHCI0,
45
+ AW_H3_OHCI0,
46
+ AW_H3_EHCI1,
47
+ AW_H3_OHCI1,
48
+ AW_H3_EHCI2,
49
+ AW_H3_OHCI2,
50
+ AW_H3_EHCI3,
51
+ AW_H3_OHCI3,
52
AW_H3_CCU,
53
AW_H3_PIT,
54
AW_H3_UART0,
55
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/hw/arm/allwinner-h3.c
58
+++ b/hw/arm/allwinner-h3.c
52
@@ -XXX,XX +XXX,XX @@
59
@@ -XXX,XX +XXX,XX @@
53
#include "qemu/bitmap.h"
60
#include "hw/sysbus.h"
54
#include "qom/object.h"
61
#include "hw/char/serial.h"
55
#include "hw/hotplug.h"
62
#include "hw/misc/unimp.h"
56
+#include "hw/resettable.h"
63
+#include "hw/usb/hcd-ehci.h"
57
64
#include "sysemu/sysemu.h"
58
enum {
65
#include "hw/arm/allwinner-h3.h"
59
DEV_NVECTORS_UNSPECIFIED = -1,
66
60
@@ -XXX,XX +XXX,XX @@ typedef struct DeviceClass {
67
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
61
bool hotpluggable;
68
[AW_H3_SRAM_A1] = 0x00000000,
62
69
[AW_H3_SRAM_A2] = 0x00044000,
63
/* callbacks */
70
[AW_H3_SRAM_C] = 0x00010000,
64
+ /*
71
+ [AW_H3_EHCI0] = 0x01c1a000,
65
+ * Reset method here is deprecated and replaced by methods in the
72
+ [AW_H3_OHCI0] = 0x01c1a400,
66
+ * resettable class interface to implement a multi-phase reset.
73
+ [AW_H3_EHCI1] = 0x01c1b000,
67
+ * TODO: remove once every reset callback is unused
74
+ [AW_H3_OHCI1] = 0x01c1b400,
68
+ */
75
+ [AW_H3_EHCI2] = 0x01c1c000,
69
DeviceReset reset;
76
+ [AW_H3_OHCI2] = 0x01c1c400,
70
DeviceRealize realize;
77
+ [AW_H3_EHCI3] = 0x01c1d000,
71
DeviceUnrealize unrealize;
78
+ [AW_H3_OHCI3] = 0x01c1d400,
72
@@ -XXX,XX +XXX,XX @@ struct NamedGPIOList {
79
[AW_H3_CCU] = 0x01c20000,
73
/**
80
[AW_H3_PIT] = 0x01c20c00,
74
* DeviceState:
81
[AW_H3_UART0] = 0x01c28000,
75
* @realized: Indicates whether the device has been fully constructed.
82
@@ -XXX,XX +XXX,XX @@ enum {
76
+ * @reset: ResettableState for the device; handled by Resettable interface.
83
AW_H3_GIC_SPI_UART3 = 3,
77
*
84
AW_H3_GIC_SPI_TIMER0 = 18,
78
* This structure should not be accessed directly. We declare it here
85
AW_H3_GIC_SPI_TIMER1 = 19,
79
* so that it can be embedded in individual device state structures.
86
+ AW_H3_GIC_SPI_EHCI0 = 72,
80
@@ -XXX,XX +XXX,XX @@ struct DeviceState {
87
+ AW_H3_GIC_SPI_OHCI0 = 73,
81
int num_child_bus;
88
+ AW_H3_GIC_SPI_EHCI1 = 74,
82
int instance_id_alias;
89
+ AW_H3_GIC_SPI_OHCI1 = 75,
83
int alias_required_for_version;
90
+ AW_H3_GIC_SPI_EHCI2 = 76,
84
+ ResettableState reset;
91
+ AW_H3_GIC_SPI_OHCI2 = 77,
92
+ AW_H3_GIC_SPI_EHCI3 = 78,
93
+ AW_H3_GIC_SPI_OHCI3 = 79,
85
};
94
};
86
95
87
struct DeviceListener {
96
/* Allwinner H3 general constants */
88
@@ -XXX,XX +XXX,XX @@ typedef struct BusChild {
97
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
89
/**
98
qdev_init_nofail(DEVICE(&s->ccu));
90
* BusState:
99
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccu), 0, s->memmap[AW_H3_CCU]);
91
* @hotplug_handler: link to a hotplug handler associated with bus.
100
92
+ * @reset: ResettableState for the bus; handled by Resettable interface.
101
+ /* Universal Serial Bus */
93
*/
102
+ sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI0],
94
struct BusState {
103
+ qdev_get_gpio_in(DEVICE(&s->gic),
95
Object obj;
104
+ AW_H3_GIC_SPI_EHCI0));
96
@@ -XXX,XX +XXX,XX @@ struct BusState {
105
+ sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI1],
97
int num_children;
106
+ qdev_get_gpio_in(DEVICE(&s->gic),
98
QTAILQ_HEAD(, BusChild) children;
107
+ AW_H3_GIC_SPI_EHCI1));
99
QLIST_ENTRY(BusState) sibling;
108
+ sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI2],
100
+ ResettableState reset;
109
+ qdev_get_gpio_in(DEVICE(&s->gic),
110
+ AW_H3_GIC_SPI_EHCI2));
111
+ sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI3],
112
+ qdev_get_gpio_in(DEVICE(&s->gic),
113
+ AW_H3_GIC_SPI_EHCI3));
114
+
115
+ sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_OHCI0],
116
+ qdev_get_gpio_in(DEVICE(&s->gic),
117
+ AW_H3_GIC_SPI_OHCI0));
118
+ sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_OHCI1],
119
+ qdev_get_gpio_in(DEVICE(&s->gic),
120
+ AW_H3_GIC_SPI_OHCI1));
121
+ sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_OHCI2],
122
+ qdev_get_gpio_in(DEVICE(&s->gic),
123
+ AW_H3_GIC_SPI_OHCI2));
124
+ sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_OHCI3],
125
+ qdev_get_gpio_in(DEVICE(&s->gic),
126
+ AW_H3_GIC_SPI_OHCI3));
127
+
128
/* UART0. For future clocktree API: All UARTS are connected to APB2_CLK. */
129
serial_mm_init(get_system_memory(), s->memmap[AW_H3_UART0], 2,
130
qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART0),
131
diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c
132
index XXXXXXX..XXXXXXX 100644
133
--- a/hw/usb/hcd-ehci-sysbus.c
134
+++ b/hw/usb/hcd-ehci-sysbus.c
135
@@ -XXX,XX +XXX,XX @@ static const TypeInfo ehci_exynos4210_type_info = {
136
.class_init = ehci_exynos4210_class_init,
101
};
137
};
102
138
103
/**
139
+static void ehci_aw_h3_class_init(ObjectClass *oc, void *data)
104
@@ -XXX,XX +XXX,XX @@ void qdev_reset_all_fn(void *opaque);
140
+{
105
void qbus_reset_all(BusState *bus);
141
+ SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
106
void qbus_reset_all_fn(void *opaque);
142
+ DeviceClass *dc = DEVICE_CLASS(oc);
107
108
+/**
109
+ * device_is_in_reset:
110
+ * Return true if the device @dev is currently being reset.
111
+ */
112
+bool device_is_in_reset(DeviceState *dev);
113
+
143
+
114
+/**
144
+ sec->capsbase = 0x0;
115
+ * bus_is_in_reset:
145
+ sec->opregbase = 0x10;
116
+ * Return true if the bus @bus is currently being reset.
146
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
117
+ */
118
+bool bus_is_in_reset(BusState *bus);
119
+
120
/* This should go away once we get rid of the NULL bus hack */
121
BusState *sysbus_get_default(void);
122
123
@@ -XXX,XX +XXX,XX @@ void device_legacy_reset(DeviceState *dev);
124
125
void device_class_set_props(DeviceClass *dc, Property *props);
126
127
+/**
128
+ * device_class_set_parent_reset:
129
+ * TODO: remove the function when DeviceClass's reset method
130
+ * is not used anymore.
131
+ */
132
void device_class_set_parent_reset(DeviceClass *dc,
133
DeviceReset dev_reset,
134
DeviceReset *parent_reset);
135
diff --git a/hw/core/bus.c b/hw/core/bus.c
136
index XXXXXXX..XXXXXXX 100644
137
--- a/hw/core/bus.c
138
+++ b/hw/core/bus.c
139
@@ -XXX,XX +XXX,XX @@ int qbus_walk_children(BusState *bus,
140
return 0;
141
}
142
143
+bool bus_is_in_reset(BusState *bus)
144
+{
145
+ return resettable_is_in_reset(OBJECT(bus));
146
+}
147
+}
147
+
148
+
148
+static ResettableState *bus_get_reset_state(Object *obj)
149
+static const TypeInfo ehci_aw_h3_type_info = {
149
+{
150
+ .name = TYPE_AW_H3_EHCI,
150
+ BusState *bus = BUS(obj);
151
+ .parent = TYPE_SYS_BUS_EHCI,
151
+ return &bus->reset;
152
+ .class_init = ehci_aw_h3_class_init,
152
+}
153
+};
153
+
154
+
154
+static void bus_reset_child_foreach(Object *obj, ResettableChildCallback cb,
155
static void ehci_tegra2_class_init(ObjectClass *oc, void *data)
155
+ void *opaque, ResetType type)
156
+{
157
+ BusState *bus = BUS(obj);
158
+ BusChild *kid;
159
+
160
+ QTAILQ_FOREACH(kid, &bus->children, sibling) {
161
+ cb(OBJECT(kid->child), opaque, type);
162
+ }
163
+}
164
+
165
static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
166
{
156
{
167
const char *typename = object_get_typename(OBJECT(bus));
157
SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
168
@@ -XXX,XX +XXX,XX @@ static char *default_bus_get_fw_dev_path(DeviceState *dev)
158
@@ -XXX,XX +XXX,XX @@ static void ehci_sysbus_register_types(void)
169
return g_strdup(object_get_typename(OBJECT(dev)));
159
type_register_static(&ehci_type_info);
170
}
160
type_register_static(&ehci_platform_type_info);
171
161
type_register_static(&ehci_exynos4210_type_info);
172
+/**
162
+ type_register_static(&ehci_aw_h3_type_info);
173
+ * bus_phases_reset:
163
type_register_static(&ehci_tegra2_type_info);
174
+ * Transition reset method for buses to allow moving
164
type_register_static(&ehci_ppc4xx_type_info);
175
+ * smoothly from legacy reset method to multi-phases
165
type_register_static(&ehci_fusbh200_type_info);
176
+ */
166
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
177
+static void bus_phases_reset(BusState *bus)
178
+{
179
+ ResettableClass *rc = RESETTABLE_GET_CLASS(bus);
180
+
181
+ if (rc->phases.enter) {
182
+ rc->phases.enter(OBJECT(bus), RESET_TYPE_COLD);
183
+ }
184
+ if (rc->phases.hold) {
185
+ rc->phases.hold(OBJECT(bus));
186
+ }
187
+ if (rc->phases.exit) {
188
+ rc->phases.exit(OBJECT(bus));
189
+ }
190
+}
191
+
192
+static void bus_transitional_reset(Object *obj)
193
+{
194
+ BusClass *bc = BUS_GET_CLASS(obj);
195
+
196
+ /*
197
+ * This will call either @bus_phases_reset (for multi-phases transitioned
198
+ * buses) or a bus's specific method for not-yet transitioned buses.
199
+ * In both case, it does not reset children.
200
+ */
201
+ if (bc->reset) {
202
+ bc->reset(BUS(obj));
203
+ }
204
+}
205
+
206
+/**
207
+ * bus_get_transitional_reset:
208
+ * check if the bus's class is ready for multi-phase
209
+ */
210
+static ResettableTrFunction bus_get_transitional_reset(Object *obj)
211
+{
212
+ BusClass *dc = BUS_GET_CLASS(obj);
213
+ if (dc->reset != bus_phases_reset) {
214
+ /*
215
+ * dc->reset has been overridden by a subclass,
216
+ * the bus is not ready for multi phase yet.
217
+ */
218
+ return bus_transitional_reset;
219
+ }
220
+ return NULL;
221
+}
222
+
223
static void bus_class_init(ObjectClass *class, void *data)
224
{
225
BusClass *bc = BUS_CLASS(class);
226
+ ResettableClass *rc = RESETTABLE_CLASS(class);
227
228
class->unparent = bus_unparent;
229
bc->get_fw_dev_path = default_bus_get_fw_dev_path;
230
+
231
+ rc->get_state = bus_get_reset_state;
232
+ rc->child_foreach = bus_reset_child_foreach;
233
+
234
+ /*
235
+ * @bus_phases_reset is put as the default reset method below, allowing
236
+ * to do the multi-phase transition from base classes to leaf classes. It
237
+ * allows a legacy-reset Bus class to extend a multi-phases-reset
238
+ * Bus class for the following reason:
239
+ * + If a base class B has been moved to multi-phase, then it does not
240
+ * override this default reset method and may have defined phase methods.
241
+ * + A child class C (extending class B) which uses
242
+ * bus_class_set_parent_reset() (or similar means) to override the
243
+ * reset method will still work as expected. @bus_phases_reset function
244
+ * will be registered as the parent reset method and effectively call
245
+ * parent reset phases.
246
+ */
247
+ bc->reset = bus_phases_reset;
248
+ rc->get_transitional_function = bus_get_transitional_reset;
249
}
250
251
static void qbus_finalize(Object *obj)
252
@@ -XXX,XX +XXX,XX @@ static const TypeInfo bus_info = {
253
.instance_init = qbus_initfn,
254
.instance_finalize = qbus_finalize,
255
.class_init = bus_class_init,
256
+ .interfaces = (InterfaceInfo[]) {
257
+ { TYPE_RESETTABLE_INTERFACE },
258
+ { }
259
+ },
260
};
261
262
static void bus_register_types(void)
263
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
264
index XXXXXXX..XXXXXXX 100644
167
index XXXXXXX..XXXXXXX 100644
265
--- a/hw/core/qdev.c
168
--- a/hw/arm/Kconfig
266
+++ b/hw/core/qdev.c
169
+++ b/hw/arm/Kconfig
267
@@ -XXX,XX +XXX,XX @@ void qbus_reset_all_fn(void *opaque)
170
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_H3
268
qbus_reset_all(bus);
171
select ARM_TIMER
269
}
172
select ARM_GIC
270
173
select UNIMP
271
+bool device_is_in_reset(DeviceState *dev)
174
+ select USB_OHCI
272
+{
175
+ select USB_EHCI_SYSBUS
273
+ return resettable_is_in_reset(OBJECT(dev));
176
274
+}
177
config RASPI
275
+
178
bool
276
+static ResettableState *device_get_reset_state(Object *obj)
277
+{
278
+ DeviceState *dev = DEVICE(obj);
279
+ return &dev->reset;
280
+}
281
+
282
+static void device_reset_child_foreach(Object *obj, ResettableChildCallback cb,
283
+ void *opaque, ResetType type)
284
+{
285
+ DeviceState *dev = DEVICE(obj);
286
+ BusState *bus;
287
+
288
+ QLIST_FOREACH(bus, &dev->child_bus, sibling) {
289
+ cb(OBJECT(bus), opaque, type);
290
+ }
291
+}
292
+
293
/* can be used as ->unplug() callback for the simple cases */
294
void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev,
295
DeviceState *dev, Error **errp)
296
@@ -XXX,XX +XXX,XX @@ device_vmstate_if_get_id(VMStateIf *obj)
297
return qdev_get_dev_path(dev);
298
}
299
300
+/**
301
+ * device_phases_reset:
302
+ * Transition reset method for devices to allow moving
303
+ * smoothly from legacy reset method to multi-phases
304
+ */
305
+static void device_phases_reset(DeviceState *dev)
306
+{
307
+ ResettableClass *rc = RESETTABLE_GET_CLASS(dev);
308
+
309
+ if (rc->phases.enter) {
310
+ rc->phases.enter(OBJECT(dev), RESET_TYPE_COLD);
311
+ }
312
+ if (rc->phases.hold) {
313
+ rc->phases.hold(OBJECT(dev));
314
+ }
315
+ if (rc->phases.exit) {
316
+ rc->phases.exit(OBJECT(dev));
317
+ }
318
+}
319
+
320
+static void device_transitional_reset(Object *obj)
321
+{
322
+ DeviceClass *dc = DEVICE_GET_CLASS(obj);
323
+
324
+ /*
325
+ * This will call either @device_phases_reset (for multi-phases transitioned
326
+ * devices) or a device's specific method for not-yet transitioned devices.
327
+ * In both case, it does not reset children.
328
+ */
329
+ if (dc->reset) {
330
+ dc->reset(DEVICE(obj));
331
+ }
332
+}
333
+
334
+/**
335
+ * device_get_transitional_reset:
336
+ * check if the device's class is ready for multi-phase
337
+ */
338
+static ResettableTrFunction device_get_transitional_reset(Object *obj)
339
+{
340
+ DeviceClass *dc = DEVICE_GET_CLASS(obj);
341
+ if (dc->reset != device_phases_reset) {
342
+ /*
343
+ * dc->reset has been overridden by a subclass,
344
+ * the device is not ready for multi phase yet.
345
+ */
346
+ return device_transitional_reset;
347
+ }
348
+ return NULL;
349
+}
350
+
351
static void device_class_init(ObjectClass *class, void *data)
352
{
353
DeviceClass *dc = DEVICE_CLASS(class);
354
VMStateIfClass *vc = VMSTATE_IF_CLASS(class);
355
+ ResettableClass *rc = RESETTABLE_CLASS(class);
356
357
class->unparent = device_unparent;
358
359
@@ -XXX,XX +XXX,XX @@ static void device_class_init(ObjectClass *class, void *data)
360
dc->hotpluggable = true;
361
dc->user_creatable = true;
362
vc->get_id = device_vmstate_if_get_id;
363
+ rc->get_state = device_get_reset_state;
364
+ rc->child_foreach = device_reset_child_foreach;
365
+
366
+ /*
367
+ * @device_phases_reset is put as the default reset method below, allowing
368
+ * to do the multi-phase transition from base classes to leaf classes. It
369
+ * allows a legacy-reset Device class to extend a multi-phases-reset
370
+ * Device class for the following reason:
371
+ * + If a base class B has been moved to multi-phase, then it does not
372
+ * override this default reset method and may have defined phase methods.
373
+ * + A child class C (extending class B) which uses
374
+ * device_class_set_parent_reset() (or similar means) to override the
375
+ * reset method will still work as expected. @device_phases_reset function
376
+ * will be registered as the parent reset method and effectively call
377
+ * parent reset phases.
378
+ */
379
+ dc->reset = device_phases_reset;
380
+ rc->get_transitional_function = device_get_transitional_reset;
381
382
object_class_property_add_bool(class, "realized",
383
device_get_realized, device_set_realized,
384
@@ -XXX,XX +XXX,XX @@ static const TypeInfo device_type_info = {
385
.class_size = sizeof(DeviceClass),
386
.interfaces = (InterfaceInfo[]) {
387
{ TYPE_VMSTATE_IF },
388
+ { TYPE_RESETTABLE_INTERFACE },
389
{ }
390
}
391
};
392
--
179
--
393
2.20.1
180
2.20.1
394
181
395
182
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Deprecate device_legacy_reset(), qdev_reset_all() and
3
The Allwinner H3 System on Chip has an System Control
4
qbus_reset_all() to be replaced by new functions
4
module that provides system wide generic controls and
5
device_cold_reset() and bus_cold_reset() which uses resettable API.
5
device information. This commit adds support for the
6
6
Allwinner H3 System Control module.
7
Also introduce resettable_cold_reset_fn() which may be used as a
7
8
replacement for qdev_reset_all_fn and qbus_reset_all_fn().
8
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
9
10
Following patches will be needed to look at legacy reset call sites
11
and switch to resettable api. The legacy functions will be removed
12
when unused.
13
14
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
15
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
19
Message-id: 20200123132823.1117486-9-damien.hedde@greensocs.com
12
Message-id: 20200311221854.30370-6-nieklinnenbank@gmail.com
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
14
---
22
include/hw/qdev-core.h | 27 +++++++++++++++++++++++++++
15
hw/misc/Makefile.objs | 1 +
23
include/hw/resettable.h | 9 +++++++++
16
include/hw/arm/allwinner-h3.h | 3 +
24
hw/core/bus.c | 5 +++++
17
include/hw/misc/allwinner-h3-sysctrl.h | 67 ++++++++++++
25
hw/core/qdev.c | 5 +++++
18
hw/arm/allwinner-h3.c | 9 +-
26
hw/core/resettable.c | 5 +++++
19
hw/misc/allwinner-h3-sysctrl.c | 140 +++++++++++++++++++++++++
27
5 files changed, 51 insertions(+)
20
5 files changed, 219 insertions(+), 1 deletion(-)
28
21
create mode 100644 include/hw/misc/allwinner-h3-sysctrl.h
29
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
22
create mode 100644 hw/misc/allwinner-h3-sysctrl.c
23
24
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
30
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
31
--- a/include/hw/qdev-core.h
26
--- a/hw/misc/Makefile.objs
32
+++ b/include/hw/qdev-core.h
27
+++ b/hw/misc/Makefile.objs
33
@@ -XXX,XX +XXX,XX @@ int qdev_walk_children(DeviceState *dev,
28
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_MACIO) += macio/
34
qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
29
common-obj-$(CONFIG_IVSHMEM_DEVICE) += ivshmem.o
35
void *opaque);
30
36
31
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-ccu.o
32
+common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-sysctrl.o
33
common-obj-$(CONFIG_REALVIEW) += arm_sysctl.o
34
common-obj-$(CONFIG_NSERIES) += cbus.o
35
common-obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
36
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/arm/allwinner-h3.h
39
+++ b/include/hw/arm/allwinner-h3.h
40
@@ -XXX,XX +XXX,XX @@
41
#include "hw/timer/allwinner-a10-pit.h"
42
#include "hw/intc/arm_gic.h"
43
#include "hw/misc/allwinner-h3-ccu.h"
44
+#include "hw/misc/allwinner-h3-sysctrl.h"
45
#include "target/arm/cpu.h"
46
47
/**
48
@@ -XXX,XX +XXX,XX @@ enum {
49
AW_H3_SRAM_A1,
50
AW_H3_SRAM_A2,
51
AW_H3_SRAM_C,
52
+ AW_H3_SYSCTRL,
53
AW_H3_EHCI0,
54
AW_H3_OHCI0,
55
AW_H3_EHCI1,
56
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
57
const hwaddr *memmap;
58
AwA10PITState timer;
59
AwH3ClockCtlState ccu;
60
+ AwH3SysCtrlState sysctrl;
61
GICState gic;
62
MemoryRegion sram_a1;
63
MemoryRegion sram_a2;
64
diff --git a/include/hw/misc/allwinner-h3-sysctrl.h b/include/hw/misc/allwinner-h3-sysctrl.h
65
new file mode 100644
66
index XXXXXXX..XXXXXXX
67
--- /dev/null
68
+++ b/include/hw/misc/allwinner-h3-sysctrl.h
69
@@ -XXX,XX +XXX,XX @@
70
+/*
71
+ * Allwinner H3 System Control emulation
72
+ *
73
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
74
+ *
75
+ * This program is free software: you can redistribute it and/or modify
76
+ * it under the terms of the GNU General Public License as published by
77
+ * the Free Software Foundation, either version 2 of the License, or
78
+ * (at your option) any later version.
79
+ *
80
+ * This program is distributed in the hope that it will be useful,
81
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
82
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83
+ * GNU General Public License for more details.
84
+ *
85
+ * You should have received a copy of the GNU General Public License
86
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
87
+ */
88
+
89
+#ifndef HW_MISC_ALLWINNER_H3_SYSCTRL_H
90
+#define HW_MISC_ALLWINNER_H3_SYSCTRL_H
91
+
92
+#include "qom/object.h"
93
+#include "hw/sysbus.h"
94
+
37
+/**
95
+/**
38
+ * @qdev_reset_all:
96
+ * @name Constants
39
+ * Reset @dev. See @qbus_reset_all() for more details.
97
+ * @{
40
+ *
98
+ */
41
+ * Note: This function is deprecated and will be removed when it becomes unused.
99
+
42
+ * Please use device_cold_reset() now.
100
+/** Highest register address used by System Control device */
43
+ */
101
+#define AW_H3_SYSCTRL_REGS_MAXADDR (0x30)
44
void qdev_reset_all(DeviceState *dev);
102
+
45
void qdev_reset_all_fn(void *opaque);
103
+/** Total number of known registers */
46
104
+#define AW_H3_SYSCTRL_REGS_NUM ((AW_H3_SYSCTRL_REGS_MAXADDR / \
47
@@ -XXX,XX +XXX,XX @@ void qdev_reset_all_fn(void *opaque);
105
+ sizeof(uint32_t)) + 1)
48
* hard reset means that qbus_reset_all will reset all state of the device.
106
+
49
* For PCI devices, for example, this will include the base address registers
107
+/** @} */
50
* or configuration space.
108
+
51
+ *
52
+ * Note: This function is deprecated and will be removed when it becomes unused.
53
+ * Please use bus_cold_reset() now.
54
*/
55
void qbus_reset_all(BusState *bus);
56
void qbus_reset_all_fn(void *opaque);
57
58
+/**
109
+/**
59
+ * device_cold_reset:
110
+ * @name Object model
60
+ * Reset device @dev and perform a recursive processing using the resettable
111
+ * @{
61
+ * interface. It triggers a RESET_TYPE_COLD.
112
+ */
62
+ */
113
+
63
+void device_cold_reset(DeviceState *dev);
114
+#define TYPE_AW_H3_SYSCTRL "allwinner-h3-sysctrl"
115
+#define AW_H3_SYSCTRL(obj) \
116
+ OBJECT_CHECK(AwH3SysCtrlState, (obj), TYPE_AW_H3_SYSCTRL)
117
+
118
+/** @} */
64
+
119
+
65
+/**
120
+/**
66
+ * bus_cold_reset:
121
+ * Allwinner H3 System Control object instance state
67
+ *
122
+ */
68
+ * Reset bus @bus and perform a recursive processing using the resettable
123
+typedef struct AwH3SysCtrlState {
69
+ * interface. It triggers a RESET_TYPE_COLD.
124
+ /*< private >*/
70
+ */
125
+ SysBusDevice parent_obj;
71
+void bus_cold_reset(BusState *bus);
126
+ /*< public >*/
72
+
127
+
73
/**
128
+ /** Maps I/O registers in physical memory */
74
* device_is_in_reset:
129
+ MemoryRegion iomem;
75
* Return true if the device @dev is currently being reset.
130
+
76
@@ -XXX,XX +XXX,XX @@ void qdev_machine_init(void);
131
+ /** Array of hardware registers */
77
* device_legacy_reset:
132
+ uint32_t regs[AW_H3_SYSCTRL_REGS_NUM];
78
*
133
+
79
* Reset a single device (by calling the reset method).
134
+} AwH3SysCtrlState;
80
+ * Note: This function is deprecated and will be removed when it becomes unused.
135
+
81
+ * Please use device_cold_reset() now.
136
+#endif /* HW_MISC_ALLWINNER_H3_SYSCTRL_H */
82
*/
137
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
83
void device_legacy_reset(DeviceState *dev);
84
85
diff --git a/include/hw/resettable.h b/include/hw/resettable.h
86
index XXXXXXX..XXXXXXX 100644
138
index XXXXXXX..XXXXXXX 100644
87
--- a/include/hw/resettable.h
139
--- a/hw/arm/allwinner-h3.c
88
+++ b/include/hw/resettable.h
140
+++ b/hw/arm/allwinner-h3.c
89
@@ -XXX,XX +XXX,XX @@ bool resettable_is_in_reset(Object *obj);
141
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
90
*/
142
[AW_H3_SRAM_A1] = 0x00000000,
91
void resettable_change_parent(Object *obj, Object *newp, Object *oldp);
143
[AW_H3_SRAM_A2] = 0x00044000,
92
144
[AW_H3_SRAM_C] = 0x00010000,
93
+/**
145
+ [AW_H3_SYSCTRL] = 0x01c00000,
94
+ * resettable_cold_reset_fn:
146
[AW_H3_EHCI0] = 0x01c1a000,
95
+ * Helper to call resettable_reset((Object *) opaque, RESET_TYPE_COLD).
147
[AW_H3_OHCI0] = 0x01c1a400,
96
+ *
148
[AW_H3_EHCI1] = 0x01c1b000,
97
+ * This function is typically useful to register a reset handler with
149
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
98
+ * qemu_register_reset.
150
} unimplemented[] = {
99
+ */
151
{ "d-engine", 0x01000000, 4 * MiB },
100
+void resettable_cold_reset_fn(void *opaque);
152
{ "d-inter", 0x01400000, 128 * KiB },
101
+
153
- { "syscon", 0x01c00000, 4 * KiB },
102
/**
154
{ "dma", 0x01c02000, 4 * KiB },
103
* resettable_class_set_parent_phases:
155
{ "nfdc", 0x01c03000, 4 * KiB },
104
*
156
{ "ts", 0x01c06000, 4 * KiB },
105
diff --git a/hw/core/bus.c b/hw/core/bus.c
157
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
106
index XXXXXXX..XXXXXXX 100644
158
107
--- a/hw/core/bus.c
159
sysbus_init_child_obj(obj, "ccu", &s->ccu, sizeof(s->ccu),
108
+++ b/hw/core/bus.c
160
TYPE_AW_H3_CCU);
109
@@ -XXX,XX +XXX,XX @@ int qbus_walk_children(BusState *bus,
161
+
110
return 0;
162
+ sysbus_init_child_obj(obj, "sysctrl", &s->sysctrl, sizeof(s->sysctrl),
163
+ TYPE_AW_H3_SYSCTRL);
111
}
164
}
112
165
113
+void bus_cold_reset(BusState *bus)
166
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
114
+{
167
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
115
+ resettable_reset(OBJECT(bus), RESET_TYPE_COLD);
168
qdev_init_nofail(DEVICE(&s->ccu));
116
+}
169
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccu), 0, s->memmap[AW_H3_CCU]);
117
+
170
118
bool bus_is_in_reset(BusState *bus)
171
+ /* System Control */
119
{
172
+ qdev_init_nofail(DEVICE(&s->sysctrl));
120
return resettable_is_in_reset(OBJECT(bus));
173
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctrl), 0, s->memmap[AW_H3_SYSCTRL]);
121
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
174
+
122
index XXXXXXX..XXXXXXX 100644
175
/* Universal Serial Bus */
123
--- a/hw/core/qdev.c
176
sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI0],
124
+++ b/hw/core/qdev.c
177
qdev_get_gpio_in(DEVICE(&s->gic),
125
@@ -XXX,XX +XXX,XX @@ void qbus_reset_all_fn(void *opaque)
178
diff --git a/hw/misc/allwinner-h3-sysctrl.c b/hw/misc/allwinner-h3-sysctrl.c
126
qbus_reset_all(bus);
179
new file mode 100644
127
}
180
index XXXXXXX..XXXXXXX
128
181
--- /dev/null
129
+void device_cold_reset(DeviceState *dev)
182
+++ b/hw/misc/allwinner-h3-sysctrl.c
130
+{
183
@@ -XXX,XX +XXX,XX @@
131
+ resettable_reset(OBJECT(dev), RESET_TYPE_COLD);
184
+/*
132
+}
185
+ * Allwinner H3 System Control emulation
133
+
186
+ *
134
bool device_is_in_reset(DeviceState *dev)
187
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
135
{
188
+ *
136
return resettable_is_in_reset(OBJECT(dev));
189
+ * This program is free software: you can redistribute it and/or modify
137
diff --git a/hw/core/resettable.c b/hw/core/resettable.c
190
+ * it under the terms of the GNU General Public License as published by
138
index XXXXXXX..XXXXXXX 100644
191
+ * the Free Software Foundation, either version 2 of the License, or
139
--- a/hw/core/resettable.c
192
+ * (at your option) any later version.
140
+++ b/hw/core/resettable.c
193
+ *
141
@@ -XXX,XX +XXX,XX @@ void resettable_change_parent(Object *obj, Object *newp, Object *oldp)
194
+ * This program is distributed in the hope that it will be useful,
142
}
195
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
143
}
196
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
144
197
+ * GNU General Public License for more details.
145
+void resettable_cold_reset_fn(void *opaque)
198
+ *
146
+{
199
+ * You should have received a copy of the GNU General Public License
147
+ resettable_reset((Object *) opaque, RESET_TYPE_COLD);
200
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
148
+}
201
+ */
149
+
202
+
150
void resettable_class_set_parent_phases(ResettableClass *rc,
203
+#include "qemu/osdep.h"
151
ResettableEnterPhase enter,
204
+#include "qemu/units.h"
152
ResettableHoldPhase hold,
205
+#include "hw/sysbus.h"
206
+#include "migration/vmstate.h"
207
+#include "qemu/log.h"
208
+#include "qemu/module.h"
209
+#include "hw/misc/allwinner-h3-sysctrl.h"
210
+
211
+/* System Control register offsets */
212
+enum {
213
+ REG_VER = 0x24, /* Version */
214
+ REG_EMAC_PHY_CLK = 0x30, /* EMAC PHY Clock */
215
+};
216
+
217
+#define REG_INDEX(offset) (offset / sizeof(uint32_t))
218
+
219
+/* System Control register reset values */
220
+enum {
221
+ REG_VER_RST = 0x0,
222
+ REG_EMAC_PHY_CLK_RST = 0x58000,
223
+};
224
+
225
+static uint64_t allwinner_h3_sysctrl_read(void *opaque, hwaddr offset,
226
+ unsigned size)
227
+{
228
+ const AwH3SysCtrlState *s = AW_H3_SYSCTRL(opaque);
229
+ const uint32_t idx = REG_INDEX(offset);
230
+
231
+ if (idx >= AW_H3_SYSCTRL_REGS_NUM) {
232
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
233
+ __func__, (uint32_t)offset);
234
+ return 0;
235
+ }
236
+
237
+ return s->regs[idx];
238
+}
239
+
240
+static void allwinner_h3_sysctrl_write(void *opaque, hwaddr offset,
241
+ uint64_t val, unsigned size)
242
+{
243
+ AwH3SysCtrlState *s = AW_H3_SYSCTRL(opaque);
244
+ const uint32_t idx = REG_INDEX(offset);
245
+
246
+ if (idx >= AW_H3_SYSCTRL_REGS_NUM) {
247
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
248
+ __func__, (uint32_t)offset);
249
+ return;
250
+ }
251
+
252
+ switch (offset) {
253
+ case REG_VER: /* Version */
254
+ break;
255
+ default:
256
+ s->regs[idx] = (uint32_t) val;
257
+ break;
258
+ }
259
+}
260
+
261
+static const MemoryRegionOps allwinner_h3_sysctrl_ops = {
262
+ .read = allwinner_h3_sysctrl_read,
263
+ .write = allwinner_h3_sysctrl_write,
264
+ .endianness = DEVICE_NATIVE_ENDIAN,
265
+ .valid = {
266
+ .min_access_size = 4,
267
+ .max_access_size = 4,
268
+ },
269
+ .impl.min_access_size = 4,
270
+};
271
+
272
+static void allwinner_h3_sysctrl_reset(DeviceState *dev)
273
+{
274
+ AwH3SysCtrlState *s = AW_H3_SYSCTRL(dev);
275
+
276
+ /* Set default values for registers */
277
+ s->regs[REG_INDEX(REG_VER)] = REG_VER_RST;
278
+ s->regs[REG_INDEX(REG_EMAC_PHY_CLK)] = REG_EMAC_PHY_CLK_RST;
279
+}
280
+
281
+static void allwinner_h3_sysctrl_init(Object *obj)
282
+{
283
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
284
+ AwH3SysCtrlState *s = AW_H3_SYSCTRL(obj);
285
+
286
+ /* Memory mapping */
287
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_h3_sysctrl_ops, s,
288
+ TYPE_AW_H3_SYSCTRL, 4 * KiB);
289
+ sysbus_init_mmio(sbd, &s->iomem);
290
+}
291
+
292
+static const VMStateDescription allwinner_h3_sysctrl_vmstate = {
293
+ .name = "allwinner-h3-sysctrl",
294
+ .version_id = 1,
295
+ .minimum_version_id = 1,
296
+ .fields = (VMStateField[]) {
297
+ VMSTATE_UINT32_ARRAY(regs, AwH3SysCtrlState, AW_H3_SYSCTRL_REGS_NUM),
298
+ VMSTATE_END_OF_LIST()
299
+ }
300
+};
301
+
302
+static void allwinner_h3_sysctrl_class_init(ObjectClass *klass, void *data)
303
+{
304
+ DeviceClass *dc = DEVICE_CLASS(klass);
305
+
306
+ dc->reset = allwinner_h3_sysctrl_reset;
307
+ dc->vmsd = &allwinner_h3_sysctrl_vmstate;
308
+}
309
+
310
+static const TypeInfo allwinner_h3_sysctrl_info = {
311
+ .name = TYPE_AW_H3_SYSCTRL,
312
+ .parent = TYPE_SYS_BUS_DEVICE,
313
+ .instance_init = allwinner_h3_sysctrl_init,
314
+ .instance_size = sizeof(AwH3SysCtrlState),
315
+ .class_init = allwinner_h3_sysctrl_class_init,
316
+};
317
+
318
+static void allwinner_h3_sysctrl_register(void)
319
+{
320
+ type_register_static(&allwinner_h3_sysctrl_info);
321
+}
322
+
323
+type_init(allwinner_h3_sysctrl_register)
153
--
324
--
154
2.20.1
325
2.20.1
155
326
156
327
diff view generated by jsdifflib
1
From: Andrew Jeffery <andrew@aj.id.au>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Initialise another SDHCI model instance for the AST2600's eMMC
3
Various Allwinner System on Chip designs contain multiple processors
4
controller and use the SDHCI's num_slots value introduced previously to
4
that can be configured and reset using the generic CPU Configuration
5
determine whether we should create an SD card instance for the new slot.
5
module interface. This commit adds support for the Allwinner CPU
6
6
configuration interface which emulates the following features:
7
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
7
8
Reviewed-by: Cédric Le Goater <clg@kaod.org>
8
* CPU reset
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
* CPU status
10
Signed-off-by: Cédric Le Goater <clg@kaod.org>
10
11
Message-id: 20200114103433.30534-3-clg@kaod.org
11
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
12
[ clg : - removed ternary operator from sdhci_attach_drive()
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
- renamed SDHCI objects with a '-controller' prefix ]
13
Message-id: 20200311221854.30370-7-nieklinnenbank@gmail.com
14
Signed-off-by: Cédric Le Goater <clg@kaod.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
15
---
17
include/hw/arm/aspeed_soc.h | 2 ++
16
hw/misc/Makefile.objs | 1 +
18
hw/arm/aspeed.c | 26 +++++++++++++++++---------
17
include/hw/arm/allwinner-h3.h | 3 +
19
hw/arm/aspeed_ast2600.c | 29 ++++++++++++++++++++++++++---
18
include/hw/misc/allwinner-cpucfg.h | 52 ++++++
20
3 files changed, 45 insertions(+), 12 deletions(-)
19
hw/arm/allwinner-h3.c | 9 +-
21
20
hw/misc/allwinner-cpucfg.c | 282 +++++++++++++++++++++++++++++
22
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
21
hw/misc/trace-events | 5 +
22
6 files changed, 351 insertions(+), 1 deletion(-)
23
create mode 100644 include/hw/misc/allwinner-cpucfg.h
24
create mode 100644 hw/misc/allwinner-cpucfg.c
25
26
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
23
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/arm/aspeed_soc.h
28
--- a/hw/misc/Makefile.objs
25
+++ b/include/hw/arm/aspeed_soc.h
29
+++ b/hw/misc/Makefile.objs
26
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSoCState {
30
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_MACIO) += macio/
27
AspeedGPIOState gpio;
31
common-obj-$(CONFIG_IVSHMEM_DEVICE) += ivshmem.o
28
AspeedGPIOState gpio_1_8v;
32
29
AspeedSDHCIState sdhci;
33
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-ccu.o
30
+ AspeedSDHCIState emmc;
34
+obj-$(CONFIG_ALLWINNER_H3) += allwinner-cpucfg.o
31
} AspeedSoCState;
35
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-sysctrl.o
32
36
common-obj-$(CONFIG_REALVIEW) += arm_sysctl.o
33
#define TYPE_ASPEED_SOC "aspeed-soc"
37
common-obj-$(CONFIG_NSERIES) += cbus.o
38
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/include/hw/arm/allwinner-h3.h
41
+++ b/include/hw/arm/allwinner-h3.h
42
@@ -XXX,XX +XXX,XX @@
43
#include "hw/timer/allwinner-a10-pit.h"
44
#include "hw/intc/arm_gic.h"
45
#include "hw/misc/allwinner-h3-ccu.h"
46
+#include "hw/misc/allwinner-cpucfg.h"
47
#include "hw/misc/allwinner-h3-sysctrl.h"
48
#include "target/arm/cpu.h"
49
34
@@ -XXX,XX +XXX,XX @@ enum {
50
@@ -XXX,XX +XXX,XX @@ enum {
35
ASPEED_MII4,
51
AW_H3_GIC_CPU,
36
ASPEED_SDRAM,
52
AW_H3_GIC_HYP,
37
ASPEED_XDMA,
53
AW_H3_GIC_VCPU,
38
+ ASPEED_EMMC,
54
+ AW_H3_CPUCFG,
55
AW_H3_SDRAM
39
};
56
};
40
57
41
#endif /* ASPEED_SOC_H */
58
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
42
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
59
const hwaddr *memmap;
60
AwA10PITState timer;
61
AwH3ClockCtlState ccu;
62
+ AwCpuCfgState cpucfg;
63
AwH3SysCtrlState sysctrl;
64
GICState gic;
65
MemoryRegion sram_a1;
66
diff --git a/include/hw/misc/allwinner-cpucfg.h b/include/hw/misc/allwinner-cpucfg.h
67
new file mode 100644
68
index XXXXXXX..XXXXXXX
69
--- /dev/null
70
+++ b/include/hw/misc/allwinner-cpucfg.h
71
@@ -XXX,XX +XXX,XX @@
72
+/*
73
+ * Allwinner CPU Configuration Module emulation
74
+ *
75
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
76
+ *
77
+ * This program is free software: you can redistribute it and/or modify
78
+ * it under the terms of the GNU General Public License as published by
79
+ * the Free Software Foundation, either version 2 of the License, or
80
+ * (at your option) any later version.
81
+ *
82
+ * This program is distributed in the hope that it will be useful,
83
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
84
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
85
+ * GNU General Public License for more details.
86
+ *
87
+ * You should have received a copy of the GNU General Public License
88
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
89
+ */
90
+
91
+#ifndef HW_MISC_ALLWINNER_CPUCFG_H
92
+#define HW_MISC_ALLWINNER_CPUCFG_H
93
+
94
+#include "qom/object.h"
95
+#include "hw/sysbus.h"
96
+
97
+/**
98
+ * Object model
99
+ * @{
100
+ */
101
+
102
+#define TYPE_AW_CPUCFG "allwinner-cpucfg"
103
+#define AW_CPUCFG(obj) \
104
+ OBJECT_CHECK(AwCpuCfgState, (obj), TYPE_AW_CPUCFG)
105
+
106
+/** @} */
107
+
108
+/**
109
+ * Allwinner CPU Configuration Module instance state
110
+ */
111
+typedef struct AwCpuCfgState {
112
+ /*< private >*/
113
+ SysBusDevice parent_obj;
114
+ /*< public >*/
115
+
116
+ MemoryRegion iomem;
117
+ uint32_t gen_ctrl;
118
+ uint32_t super_standby;
119
+ uint32_t entry_addr;
120
+
121
+} AwCpuCfgState;
122
+
123
+#endif /* HW_MISC_ALLWINNER_CPUCFG_H */
124
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
43
index XXXXXXX..XXXXXXX 100644
125
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/arm/aspeed.c
126
--- a/hw/arm/allwinner-h3.c
45
+++ b/hw/arm/aspeed.c
127
+++ b/hw/arm/allwinner-h3.c
46
@@ -XXX,XX +XXX,XX @@ static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
128
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
47
}
129
[AW_H3_GIC_CPU] = 0x01c82000,
130
[AW_H3_GIC_HYP] = 0x01c84000,
131
[AW_H3_GIC_VCPU] = 0x01c86000,
132
+ [AW_H3_CPUCFG] = 0x01f01c00,
133
[AW_H3_SDRAM] = 0x40000000
134
};
135
136
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
137
{ "r_wdog", 0x01f01000, 1 * KiB },
138
{ "r_prcm", 0x01f01400, 1 * KiB },
139
{ "r_twd", 0x01f01800, 1 * KiB },
140
- { "r_cpucfg", 0x01f01c00, 1 * KiB },
141
{ "r_cir-rx", 0x01f02000, 1 * KiB },
142
{ "r_twi", 0x01f02400, 1 * KiB },
143
{ "r_uart", 0x01f02800, 1 * KiB },
144
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
145
146
sysbus_init_child_obj(obj, "sysctrl", &s->sysctrl, sizeof(s->sysctrl),
147
TYPE_AW_H3_SYSCTRL);
148
+
149
+ sysbus_init_child_obj(obj, "cpucfg", &s->cpucfg, sizeof(s->cpucfg),
150
+ TYPE_AW_CPUCFG);
48
}
151
}
49
152
50
+static void sdhci_attach_drive(SDHCIState *sdhci, DriveInfo *dinfo)
153
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
51
+{
154
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
52
+ DeviceState *card;
155
qdev_init_nofail(DEVICE(&s->sysctrl));
53
+
156
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctrl), 0, s->memmap[AW_H3_SYSCTRL]);
54
+ card = qdev_create(qdev_get_child_bus(DEVICE(sdhci), "sd-bus"),
157
55
+ TYPE_SD_CARD);
158
+ /* CPU Configuration */
56
+ if (dinfo) {
159
+ qdev_init_nofail(DEVICE(&s->cpucfg));
57
+ qdev_prop_set_drive(card, "drive", blk_by_legacy_dinfo(dinfo),
160
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->cpucfg), 0, s->memmap[AW_H3_CPUCFG]);
58
+ &error_fatal);
161
+
59
+ }
162
/* Universal Serial Bus */
60
+ object_property_set_bool(OBJECT(card), true, "realized", &error_fatal);
163
sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI0],
61
+}
164
qdev_get_gpio_in(DEVICE(&s->gic),
62
+
165
diff --git a/hw/misc/allwinner-cpucfg.c b/hw/misc/allwinner-cpucfg.c
63
static void aspeed_machine_init(MachineState *machine)
166
new file mode 100644
64
{
167
index XXXXXXX..XXXXXXX
65
AspeedBoardState *bmc;
168
--- /dev/null
66
@@ -XXX,XX +XXX,XX @@ static void aspeed_machine_init(MachineState *machine)
169
+++ b/hw/misc/allwinner-cpucfg.c
67
}
170
@@ -XXX,XX +XXX,XX @@
68
171
+/*
69
for (i = 0; i < bmc->soc.sdhci.num_slots; i++) {
172
+ * Allwinner CPU Configuration Module emulation
70
- SDHCIState *sdhci = &bmc->soc.sdhci.slots[i];
173
+ *
71
- DriveInfo *dinfo = drive_get_next(IF_SD);
174
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
72
- BlockBackend *blk;
175
+ *
73
- DeviceState *card;
176
+ * This program is free software: you can redistribute it and/or modify
74
+ sdhci_attach_drive(&bmc->soc.sdhci.slots[i], drive_get_next(IF_SD));
177
+ * it under the terms of the GNU General Public License as published by
75
+ }
178
+ * the Free Software Foundation, either version 2 of the License, or
76
179
+ * (at your option) any later version.
77
- blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
180
+ *
78
- card = qdev_create(qdev_get_child_bus(DEVICE(sdhci), "sd-bus"),
181
+ * This program is distributed in the hope that it will be useful,
79
- TYPE_SD_CARD);
182
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
80
- qdev_prop_set_drive(card, "drive", blk, &error_fatal);
183
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
81
- object_property_set_bool(OBJECT(card), true, "realized", &error_fatal);
184
+ * GNU General Public License for more details.
82
+ if (bmc->soc.emmc.num_slots) {
185
+ *
83
+ sdhci_attach_drive(&bmc->soc.emmc.slots[0], drive_get_next(IF_SD));
186
+ * You should have received a copy of the GNU General Public License
84
}
187
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
85
188
+ */
86
arm_load_kernel(ARM_CPU(first_cpu), machine, &aspeed_board_binfo);
189
+
87
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
190
+#include "qemu/osdep.h"
88
index XXXXXXX..XXXXXXX 100644
191
+#include "qemu/units.h"
89
--- a/hw/arm/aspeed_ast2600.c
192
+#include "hw/sysbus.h"
90
+++ b/hw/arm/aspeed_ast2600.c
193
+#include "migration/vmstate.h"
91
@@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_soc_ast2600_memmap[] = {
194
+#include "qemu/log.h"
92
[ASPEED_ADC] = 0x1E6E9000,
195
+#include "qemu/module.h"
93
[ASPEED_VIDEO] = 0x1E700000,
196
+#include "qemu/error-report.h"
94
[ASPEED_SDHCI] = 0x1E740000,
197
+#include "qemu/timer.h"
95
+ [ASPEED_EMMC] = 0x1E750000,
198
+#include "hw/core/cpu.h"
96
[ASPEED_GPIO] = 0x1E780000,
199
+#include "target/arm/arm-powerctl.h"
97
[ASPEED_GPIO_1_8V] = 0x1E780800,
200
+#include "target/arm/cpu.h"
98
[ASPEED_RTC] = 0x1E781000,
201
+#include "hw/misc/allwinner-cpucfg.h"
99
@@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_soc_ast2600_memmap[] = {
202
+#include "trace.h"
100
203
+
101
#define ASPEED_SOC_AST2600_MAX_IRQ 128
204
+/* CPUCFG register offsets */
102
205
+enum {
103
+/* Shared Peripheral Interrupt values below are offset by -32 from datasheet */
206
+ REG_CPUS_RST_CTRL = 0x0000, /* CPUs Reset Control */
104
static const int aspeed_soc_ast2600_irqmap[] = {
207
+ REG_CPU0_RST_CTRL = 0x0040, /* CPU#0 Reset Control */
105
[ASPEED_UART1] = 47,
208
+ REG_CPU0_CTRL = 0x0044, /* CPU#0 Control */
106
[ASPEED_UART2] = 48,
209
+ REG_CPU0_STATUS = 0x0048, /* CPU#0 Status */
107
@@ -XXX,XX +XXX,XX @@ static const int aspeed_soc_ast2600_irqmap[] = {
210
+ REG_CPU1_RST_CTRL = 0x0080, /* CPU#1 Reset Control */
108
[ASPEED_ADC] = 78,
211
+ REG_CPU1_CTRL = 0x0084, /* CPU#1 Control */
109
[ASPEED_XDMA] = 6,
212
+ REG_CPU1_STATUS = 0x0088, /* CPU#1 Status */
110
[ASPEED_SDHCI] = 43,
213
+ REG_CPU2_RST_CTRL = 0x00C0, /* CPU#2 Reset Control */
111
+ [ASPEED_EMMC] = 15,
214
+ REG_CPU2_CTRL = 0x00C4, /* CPU#2 Control */
112
[ASPEED_GPIO] = 40,
215
+ REG_CPU2_STATUS = 0x00C8, /* CPU#2 Status */
113
[ASPEED_GPIO_1_8V] = 11,
216
+ REG_CPU3_RST_CTRL = 0x0100, /* CPU#3 Reset Control */
114
[ASPEED_RTC] = 13,
217
+ REG_CPU3_CTRL = 0x0104, /* CPU#3 Control */
115
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2600_init(Object *obj)
218
+ REG_CPU3_STATUS = 0x0108, /* CPU#3 Status */
116
sysbus_init_child_obj(obj, "gpio_1_8v", OBJECT(&s->gpio_1_8v),
219
+ REG_CPU_SYS_RST = 0x0140, /* CPU System Reset */
117
sizeof(s->gpio_1_8v), typename);
220
+ REG_CLK_GATING = 0x0144, /* CPU Clock Gating */
118
221
+ REG_GEN_CTRL = 0x0184, /* General Control */
119
- sysbus_init_child_obj(obj, "sdc", OBJECT(&s->sdhci), sizeof(s->sdhci),
222
+ REG_SUPER_STANDBY = 0x01A0, /* Super Standby Flag */
120
- TYPE_ASPEED_SDHCI);
223
+ REG_ENTRY_ADDR = 0x01A4, /* Reset Entry Address */
121
+ sysbus_init_child_obj(obj, "sd-controller", OBJECT(&s->sdhci),
224
+ REG_DBG_EXTERN = 0x01E4, /* Debug External */
122
+ sizeof(s->sdhci), TYPE_ASPEED_SDHCI);
225
+ REG_CNT64_CTRL = 0x0280, /* 64-bit Counter Control */
123
226
+ REG_CNT64_LOW = 0x0284, /* 64-bit Counter Low */
124
object_property_set_int(OBJECT(&s->sdhci), 2, "num-slots", &error_abort);
227
+ REG_CNT64_HIGH = 0x0288, /* 64-bit Counter High */
125
228
+};
126
/* Init sd card slot class here so that they're under the correct parent */
229
+
127
for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) {
230
+/* CPUCFG register flags */
128
- sysbus_init_child_obj(obj, "sdhci[*]", OBJECT(&s->sdhci.slots[i]),
231
+enum {
129
+ sysbus_init_child_obj(obj, "sd-controller.sdhci[*]",
232
+ CPUX_RESET_RELEASED = ((1 << 1) | (1 << 0)),
130
+ OBJECT(&s->sdhci.slots[i]),
233
+ CPUX_STATUS_SMP = (1 << 0),
131
sizeof(s->sdhci.slots[i]), TYPE_SYSBUS_SDHCI);
234
+ CPU_SYS_RESET_RELEASED = (1 << 0),
132
}
235
+ CLK_GATING_ENABLE = ((1 << 8) | 0xF),
133
+
236
+};
134
+ sysbus_init_child_obj(obj, "emmc-controller", OBJECT(&s->emmc),
237
+
135
+ sizeof(s->emmc), TYPE_ASPEED_SDHCI);
238
+/* CPUCFG register reset values */
136
+
239
+enum {
137
+ object_property_set_int(OBJECT(&s->emmc), 1, "num-slots", &error_abort);
240
+ REG_CLK_GATING_RST = 0x0000010F,
138
+
241
+ REG_GEN_CTRL_RST = 0x00000020,
139
+ sysbus_init_child_obj(obj, "emmc-controller.sdhci",
242
+ REG_SUPER_STANDBY_RST = 0x0,
140
+ OBJECT(&s->emmc.slots[0]), sizeof(s->emmc.slots[0]),
243
+ REG_CNT64_CTRL_RST = 0x0,
141
+ TYPE_SYSBUS_SDHCI);
244
+};
142
}
245
+
143
246
+/* CPUCFG constants */
144
/*
247
+enum {
145
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
248
+ CPU_EXCEPTION_LEVEL_ON_RESET = 3, /* EL3 */
146
sc->memmap[ASPEED_SDHCI]);
249
+};
147
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0,
250
+
148
aspeed_soc_get_irq(s, ASPEED_SDHCI));
251
+static void allwinner_cpucfg_cpu_reset(AwCpuCfgState *s, uint8_t cpu_id)
149
+
252
+{
150
+ /* eMMC */
253
+ int ret;
151
+ object_property_set_bool(OBJECT(&s->emmc), true, "realized", &err);
254
+
152
+ if (err) {
255
+ trace_allwinner_cpucfg_cpu_reset(cpu_id, s->entry_addr);
153
+ error_propagate(errp, err);
256
+
257
+ ARMCPU *target_cpu = ARM_CPU(arm_get_cpu_by_id(cpu_id));
258
+ if (!target_cpu) {
259
+ /*
260
+ * Called with a bogus value for cpu_id. Guest error will
261
+ * already have been logged, we can simply return here.
262
+ */
154
+ return;
263
+ return;
155
+ }
264
+ }
156
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->emmc), 0, sc->memmap[ASPEED_EMMC]);
265
+ bool target_aa64 = arm_feature(&target_cpu->env, ARM_FEATURE_AARCH64);
157
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->emmc), 0,
266
+
158
+ aspeed_soc_get_irq(s, ASPEED_EMMC));
267
+ ret = arm_set_cpu_on(cpu_id, s->entry_addr, 0,
159
}
268
+ CPU_EXCEPTION_LEVEL_ON_RESET, target_aa64);
160
269
+ if (ret != QEMU_ARM_POWERCTL_RET_SUCCESS) {
161
static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data)
270
+ error_report("%s: failed to bring up CPU %d: err %d",
271
+ __func__, cpu_id, ret);
272
+ return;
273
+ }
274
+}
275
+
276
+static uint64_t allwinner_cpucfg_read(void *opaque, hwaddr offset,
277
+ unsigned size)
278
+{
279
+ const AwCpuCfgState *s = AW_CPUCFG(opaque);
280
+ uint64_t val = 0;
281
+
282
+ switch (offset) {
283
+ case REG_CPUS_RST_CTRL: /* CPUs Reset Control */
284
+ case REG_CPU_SYS_RST: /* CPU System Reset */
285
+ val = CPU_SYS_RESET_RELEASED;
286
+ break;
287
+ case REG_CPU0_RST_CTRL: /* CPU#0 Reset Control */
288
+ case REG_CPU1_RST_CTRL: /* CPU#1 Reset Control */
289
+ case REG_CPU2_RST_CTRL: /* CPU#2 Reset Control */
290
+ case REG_CPU3_RST_CTRL: /* CPU#3 Reset Control */
291
+ val = CPUX_RESET_RELEASED;
292
+ break;
293
+ case REG_CPU0_CTRL: /* CPU#0 Control */
294
+ case REG_CPU1_CTRL: /* CPU#1 Control */
295
+ case REG_CPU2_CTRL: /* CPU#2 Control */
296
+ case REG_CPU3_CTRL: /* CPU#3 Control */
297
+ val = 0;
298
+ break;
299
+ case REG_CPU0_STATUS: /* CPU#0 Status */
300
+ case REG_CPU1_STATUS: /* CPU#1 Status */
301
+ case REG_CPU2_STATUS: /* CPU#2 Status */
302
+ case REG_CPU3_STATUS: /* CPU#3 Status */
303
+ val = CPUX_STATUS_SMP;
304
+ break;
305
+ case REG_CLK_GATING: /* CPU Clock Gating */
306
+ val = CLK_GATING_ENABLE;
307
+ break;
308
+ case REG_GEN_CTRL: /* General Control */
309
+ val = s->gen_ctrl;
310
+ break;
311
+ case REG_SUPER_STANDBY: /* Super Standby Flag */
312
+ val = s->super_standby;
313
+ break;
314
+ case REG_ENTRY_ADDR: /* Reset Entry Address */
315
+ val = s->entry_addr;
316
+ break;
317
+ case REG_DBG_EXTERN: /* Debug External */
318
+ case REG_CNT64_CTRL: /* 64-bit Counter Control */
319
+ case REG_CNT64_LOW: /* 64-bit Counter Low */
320
+ case REG_CNT64_HIGH: /* 64-bit Counter High */
321
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented register at 0x%04x\n",
322
+ __func__, (uint32_t)offset);
323
+ break;
324
+ default:
325
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
326
+ __func__, (uint32_t)offset);
327
+ break;
328
+ }
329
+
330
+ trace_allwinner_cpucfg_read(offset, val, size);
331
+
332
+ return val;
333
+}
334
+
335
+static void allwinner_cpucfg_write(void *opaque, hwaddr offset,
336
+ uint64_t val, unsigned size)
337
+{
338
+ AwCpuCfgState *s = AW_CPUCFG(opaque);
339
+
340
+ trace_allwinner_cpucfg_write(offset, val, size);
341
+
342
+ switch (offset) {
343
+ case REG_CPUS_RST_CTRL: /* CPUs Reset Control */
344
+ case REG_CPU_SYS_RST: /* CPU System Reset */
345
+ break;
346
+ case REG_CPU0_RST_CTRL: /* CPU#0 Reset Control */
347
+ case REG_CPU1_RST_CTRL: /* CPU#1 Reset Control */
348
+ case REG_CPU2_RST_CTRL: /* CPU#2 Reset Control */
349
+ case REG_CPU3_RST_CTRL: /* CPU#3 Reset Control */
350
+ if (val) {
351
+ allwinner_cpucfg_cpu_reset(s, (offset - REG_CPU0_RST_CTRL) >> 6);
352
+ }
353
+ break;
354
+ case REG_CPU0_CTRL: /* CPU#0 Control */
355
+ case REG_CPU1_CTRL: /* CPU#1 Control */
356
+ case REG_CPU2_CTRL: /* CPU#2 Control */
357
+ case REG_CPU3_CTRL: /* CPU#3 Control */
358
+ case REG_CPU0_STATUS: /* CPU#0 Status */
359
+ case REG_CPU1_STATUS: /* CPU#1 Status */
360
+ case REG_CPU2_STATUS: /* CPU#2 Status */
361
+ case REG_CPU3_STATUS: /* CPU#3 Status */
362
+ case REG_CLK_GATING: /* CPU Clock Gating */
363
+ break;
364
+ case REG_GEN_CTRL: /* General Control */
365
+ s->gen_ctrl = val;
366
+ break;
367
+ case REG_SUPER_STANDBY: /* Super Standby Flag */
368
+ s->super_standby = val;
369
+ break;
370
+ case REG_ENTRY_ADDR: /* Reset Entry Address */
371
+ s->entry_addr = val;
372
+ break;
373
+ case REG_DBG_EXTERN: /* Debug External */
374
+ case REG_CNT64_CTRL: /* 64-bit Counter Control */
375
+ case REG_CNT64_LOW: /* 64-bit Counter Low */
376
+ case REG_CNT64_HIGH: /* 64-bit Counter High */
377
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented register at 0x%04x\n",
378
+ __func__, (uint32_t)offset);
379
+ break;
380
+ default:
381
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
382
+ __func__, (uint32_t)offset);
383
+ break;
384
+ }
385
+}
386
+
387
+static const MemoryRegionOps allwinner_cpucfg_ops = {
388
+ .read = allwinner_cpucfg_read,
389
+ .write = allwinner_cpucfg_write,
390
+ .endianness = DEVICE_NATIVE_ENDIAN,
391
+ .valid = {
392
+ .min_access_size = 4,
393
+ .max_access_size = 4,
394
+ },
395
+ .impl.min_access_size = 4,
396
+};
397
+
398
+static void allwinner_cpucfg_reset(DeviceState *dev)
399
+{
400
+ AwCpuCfgState *s = AW_CPUCFG(dev);
401
+
402
+ /* Set default values for registers */
403
+ s->gen_ctrl = REG_GEN_CTRL_RST;
404
+ s->super_standby = REG_SUPER_STANDBY_RST;
405
+ s->entry_addr = 0;
406
+}
407
+
408
+static void allwinner_cpucfg_init(Object *obj)
409
+{
410
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
411
+ AwCpuCfgState *s = AW_CPUCFG(obj);
412
+
413
+ /* Memory mapping */
414
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_cpucfg_ops, s,
415
+ TYPE_AW_CPUCFG, 1 * KiB);
416
+ sysbus_init_mmio(sbd, &s->iomem);
417
+}
418
+
419
+static const VMStateDescription allwinner_cpucfg_vmstate = {
420
+ .name = "allwinner-cpucfg",
421
+ .version_id = 1,
422
+ .minimum_version_id = 1,
423
+ .fields = (VMStateField[]) {
424
+ VMSTATE_UINT32(gen_ctrl, AwCpuCfgState),
425
+ VMSTATE_UINT32(super_standby, AwCpuCfgState),
426
+ VMSTATE_UINT32(entry_addr, AwCpuCfgState),
427
+ VMSTATE_END_OF_LIST()
428
+ }
429
+};
430
+
431
+static void allwinner_cpucfg_class_init(ObjectClass *klass, void *data)
432
+{
433
+ DeviceClass *dc = DEVICE_CLASS(klass);
434
+
435
+ dc->reset = allwinner_cpucfg_reset;
436
+ dc->vmsd = &allwinner_cpucfg_vmstate;
437
+}
438
+
439
+static const TypeInfo allwinner_cpucfg_info = {
440
+ .name = TYPE_AW_CPUCFG,
441
+ .parent = TYPE_SYS_BUS_DEVICE,
442
+ .instance_init = allwinner_cpucfg_init,
443
+ .instance_size = sizeof(AwCpuCfgState),
444
+ .class_init = allwinner_cpucfg_class_init,
445
+};
446
+
447
+static void allwinner_cpucfg_register(void)
448
+{
449
+ type_register_static(&allwinner_cpucfg_info);
450
+}
451
+
452
+type_init(allwinner_cpucfg_register)
453
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
454
index XXXXXXX..XXXXXXX 100644
455
--- a/hw/misc/trace-events
456
+++ b/hw/misc/trace-events
457
@@ -XXX,XX +XXX,XX @@
458
# See docs/devel/tracing.txt for syntax documentation.
459
460
+# allwinner-cpucfg.c
461
+allwinner_cpucfg_cpu_reset(uint8_t cpu_id, uint32_t reset_addr) "id %u, reset_addr 0x%" PRIu32
462
+allwinner_cpucfg_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
463
+allwinner_cpucfg_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
464
+
465
# eccmemctl.c
466
ecc_mem_writel_mer(uint32_t val) "Write memory enable 0x%08x"
467
ecc_mem_writel_mdr(uint32_t val) "Write memory delay 0x%08x"
162
--
468
--
163
2.20.1
469
2.20.1
164
470
165
471
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Signed-off-by: Andrew Jones <drjones@redhat.com>
3
The Security Identifier device found in various Allwinner System on Chip
4
Message-id: 20200120101023.16030-2-drjones@redhat.com
4
designs gives applications a per-board unique identifier. This commit
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
adds support for the Allwinner Security Identifier using a 128-bit
6
UUID value as input.
7
8
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Message-id: 20200311221854.30370-8-nieklinnenbank@gmail.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
12
---
8
target/arm/kvm_arm.h | 46 ++++++++++++++++++++++++++------------------
13
hw/misc/Makefile.objs | 1 +
9
1 file changed, 27 insertions(+), 19 deletions(-)
14
include/hw/arm/allwinner-h3.h | 3 +
10
15
include/hw/misc/allwinner-sid.h | 60 ++++++++++++
11
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
16
hw/arm/allwinner-h3.c | 11 ++-
12
index XXXXXXX..XXXXXXX 100644
17
hw/arm/orangepi.c | 8 ++
13
--- a/target/arm/kvm_arm.h
18
hw/misc/allwinner-sid.c | 168 ++++++++++++++++++++++++++++++++
14
+++ b/target/arm/kvm_arm.h
19
hw/misc/trace-events | 4 +
20
7 files changed, 254 insertions(+), 1 deletion(-)
21
create mode 100644 include/hw/misc/allwinner-sid.h
22
create mode 100644 hw/misc/allwinner-sid.c
23
24
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
25
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/misc/Makefile.objs
27
+++ b/hw/misc/Makefile.objs
28
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_IVSHMEM_DEVICE) += ivshmem.o
29
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-ccu.o
30
obj-$(CONFIG_ALLWINNER_H3) += allwinner-cpucfg.o
31
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-sysctrl.o
32
+common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-sid.o
33
common-obj-$(CONFIG_REALVIEW) += arm_sysctl.o
34
common-obj-$(CONFIG_NSERIES) += cbus.o
35
common-obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
36
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/arm/allwinner-h3.h
39
+++ b/include/hw/arm/allwinner-h3.h
15
@@ -XXX,XX +XXX,XX @@
40
@@ -XXX,XX +XXX,XX @@
16
int kvm_arm_vcpu_init(CPUState *cs);
41
#include "hw/misc/allwinner-h3-ccu.h"
42
#include "hw/misc/allwinner-cpucfg.h"
43
#include "hw/misc/allwinner-h3-sysctrl.h"
44
+#include "hw/misc/allwinner-sid.h"
45
#include "target/arm/cpu.h"
17
46
18
/**
47
/**
19
- * kvm_arm_vcpu_finalize
48
@@ -XXX,XX +XXX,XX @@ enum {
20
+ * kvm_arm_vcpu_finalize:
49
AW_H3_SRAM_A2,
21
* @cs: CPUState
50
AW_H3_SRAM_C,
22
- * @feature: int
51
AW_H3_SYSCTRL,
23
+ * @feature: feature to finalize
52
+ AW_H3_SID,
24
*
53
AW_H3_EHCI0,
25
* Finalizes the configuration of the specified VCPU feature by
54
AW_H3_OHCI0,
26
* invoking the KVM_ARM_VCPU_FINALIZE ioctl. Features requiring
55
AW_H3_EHCI1,
27
@@ -XXX,XX +XXX,XX @@ void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group,
56
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
28
int kvm_arm_init_cpreg_list(ARMCPU *cpu);
57
AwH3ClockCtlState ccu;
29
58
AwCpuCfgState cpucfg;
30
/**
59
AwH3SysCtrlState sysctrl;
31
- * kvm_arm_reg_syncs_via_cpreg_list
60
+ AwSidState sid;
32
- * regidx: KVM register index
61
GICState gic;
33
+ * kvm_arm_reg_syncs_via_cpreg_list:
62
MemoryRegion sram_a1;
34
+ * @regidx: KVM register index
63
MemoryRegion sram_a2;
35
*
64
diff --git a/include/hw/misc/allwinner-sid.h b/include/hw/misc/allwinner-sid.h
36
* Return true if this KVM register should be synchronized via the
65
new file mode 100644
37
* cpreg list of arbitrary system registers, false if it is synchronized
66
index XXXXXXX..XXXXXXX
38
@@ -XXX,XX +XXX,XX @@ int kvm_arm_init_cpreg_list(ARMCPU *cpu);
67
--- /dev/null
39
bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx);
68
+++ b/include/hw/misc/allwinner-sid.h
40
69
@@ -XXX,XX +XXX,XX @@
41
/**
70
+/*
42
- * kvm_arm_cpreg_level
71
+ * Allwinner Security ID emulation
43
- * regidx: KVM register index
72
+ *
44
+ * kvm_arm_cpreg_level:
73
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
45
+ * @regidx: KVM register index
74
+ *
46
*
75
+ * This program is free software: you can redistribute it and/or modify
47
* Return the level of this coprocessor/system register. Return value is
76
+ * it under the terms of the GNU General Public License as published by
48
* either KVM_PUT_RUNTIME_STATE, KVM_PUT_RESET_STATE, or KVM_PUT_FULL_STATE.
77
+ * the Free Software Foundation, either version 2 of the License, or
49
@@ -XXX,XX +XXX,XX @@ void kvm_arm_init_serror_injection(CPUState *cs);
78
+ * (at your option) any later version.
50
* @cpu: ARMCPU
79
+ *
51
*
80
+ * This program is distributed in the hope that it will be useful,
52
* Get VCPU related state from kvm.
81
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
53
+ *
82
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
54
+ * Returns: 0 if success else < 0 error code
83
+ * GNU General Public License for more details.
55
*/
84
+ *
56
int kvm_get_vcpu_events(ARMCPU *cpu);
85
+ * You should have received a copy of the GNU General Public License
57
86
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
58
@@ -XXX,XX +XXX,XX @@ int kvm_get_vcpu_events(ARMCPU *cpu);
87
+ */
59
* @cpu: ARMCPU
88
+
60
*
89
+#ifndef HW_MISC_ALLWINNER_SID_H
61
* Put VCPU related state to kvm.
90
+#define HW_MISC_ALLWINNER_SID_H
62
+ *
91
+
63
+ * Returns: 0 if success else < 0 error code
92
+#include "qom/object.h"
64
*/
93
+#include "hw/sysbus.h"
65
int kvm_put_vcpu_events(ARMCPU *cpu);
94
+#include "qemu/uuid.h"
66
95
+
67
@@ -XXX,XX +XXX,XX @@ typedef struct ARMHostCPUFeatures {
96
+/**
68
97
+ * Object model
69
/**
98
+ * @{
70
* kvm_arm_get_host_cpu_features:
99
+ */
71
- * @ahcc: ARMHostCPUClass to fill in
100
+
72
+ * @ahcf: ARMHostCPUClass to fill in
101
+#define TYPE_AW_SID "allwinner-sid"
73
*
102
+#define AW_SID(obj) \
74
* Probe the capabilities of the host kernel's preferred CPU and fill
103
+ OBJECT_CHECK(AwSidState, (obj), TYPE_AW_SID)
75
* in the ARMHostCPUClass struct accordingly.
104
+
76
+ *
105
+/** @} */
77
+ * Returns true on success and false otherwise.
106
+
78
*/
107
+/**
79
bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf);
108
+ * Allwinner Security ID object instance state
80
109
+ */
81
@@ -XXX,XX +XXX,XX @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
110
+typedef struct AwSidState {
82
bool kvm_arm_aarch32_supported(CPUState *cs);
111
+ /*< private >*/
83
112
+ SysBusDevice parent_obj;
84
/**
113
+ /*< public >*/
85
- * bool kvm_arm_pmu_supported:
114
+
86
+ * kvm_arm_pmu_supported:
115
+ /** Maps I/O registers in physical memory */
87
* @cs: CPUState
116
+ MemoryRegion iomem;
88
*
117
+
89
* Returns: true if the KVM VCPU can enable its PMU
118
+ /** Control register defines how and what to read */
90
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_aarch32_supported(CPUState *cs);
119
+ uint32_t control;
91
bool kvm_arm_pmu_supported(CPUState *cs);
120
+
92
121
+ /** RdKey register contains the data retrieved by the device */
93
/**
122
+ uint32_t rdkey;
94
- * bool kvm_arm_sve_supported:
123
+
95
+ * kvm_arm_sve_supported:
124
+ /** Stores the emulated device identifier */
96
* @cs: CPUState
125
+ QemuUUID identifier;
97
*
126
+
98
* Returns true if the KVM VCPU can enable SVE and false otherwise.
127
+} AwSidState;
99
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_pmu_supported(CPUState *cs);
128
+
100
bool kvm_arm_sve_supported(CPUState *cs);
129
+#endif /* HW_MISC_ALLWINNER_SID_H */
101
130
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
102
/**
131
index XXXXXXX..XXXXXXX 100644
103
- * kvm_arm_get_max_vm_ipa_size - Returns the number of bits in the
132
--- a/hw/arm/allwinner-h3.c
104
- * IPA address space supported by KVM
133
+++ b/hw/arm/allwinner-h3.c
105
- *
134
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
106
+ * kvm_arm_get_max_vm_ipa_size:
135
[AW_H3_SRAM_A2] = 0x00044000,
107
* @ms: Machine state handle
136
[AW_H3_SRAM_C] = 0x00010000,
108
+ *
137
[AW_H3_SYSCTRL] = 0x01c00000,
109
+ * Returns the number of bits in the IPA address space supported by KVM
138
+ [AW_H3_SID] = 0x01c14000,
110
*/
139
[AW_H3_EHCI0] = 0x01c1a000,
111
int kvm_arm_get_max_vm_ipa_size(MachineState *ms);
140
[AW_H3_OHCI0] = 0x01c1a400,
112
141
[AW_H3_EHCI1] = 0x01c1b000,
113
/**
142
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
114
- * kvm_arm_sync_mpstate_to_kvm
143
{ "mmc0", 0x01c0f000, 4 * KiB },
115
+ * kvm_arm_sync_mpstate_to_kvm:
144
{ "mmc1", 0x01c10000, 4 * KiB },
116
* @cpu: ARMCPU
145
{ "mmc2", 0x01c11000, 4 * KiB },
117
*
146
- { "sid", 0x01c14000, 1 * KiB },
118
* If supported set the KVM MP_STATE based on QEMU's model.
147
{ "crypto", 0x01c15000, 4 * KiB },
119
+ *
148
{ "msgbox", 0x01c17000, 4 * KiB },
120
+ * Returns 0 on success and -1 on failure.
149
{ "spinlock", 0x01c18000, 4 * KiB },
121
*/
150
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
122
int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu);
151
123
152
sysbus_init_child_obj(obj, "cpucfg", &s->cpucfg, sizeof(s->cpucfg),
124
/**
153
TYPE_AW_CPUCFG);
125
- * kvm_arm_sync_mpstate_to_qemu
154
+
126
+ * kvm_arm_sync_mpstate_to_qemu:
155
+ sysbus_init_child_obj(obj, "sid", &s->sid, sizeof(s->sid),
127
* @cpu: ARMCPU
156
+ TYPE_AW_SID);
128
*
157
+ object_property_add_alias(obj, "identifier", OBJECT(&s->sid),
129
* If supported get the MP_STATE from KVM and store in QEMU's model.
158
+ "identifier", &error_abort);
130
+ *
159
}
131
+ * Returns 0 on success and aborts on failure.
160
132
*/
161
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
133
int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu);
162
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
134
163
qdev_init_nofail(DEVICE(&s->cpucfg));
135
@@ -XXX,XX +XXX,XX @@ int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level);
164
sysbus_mmio_map(SYS_BUS_DEVICE(&s->cpucfg), 0, s->memmap[AW_H3_CPUCFG]);
136
165
137
static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
166
+ /* Security Identifier */
138
{
167
+ qdev_init_nofail(DEVICE(&s->sid));
139
- /* This should never actually be called in the "not KVM" case,
168
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->sid), 0, s->memmap[AW_H3_SID]);
140
+ /*
169
+
141
+ * This should never actually be called in the "not KVM" case,
170
/* Universal Serial Bus */
142
* but set up the fields to indicate an error anyway.
171
sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI0],
143
*/
172
qdev_get_gpio_in(DEVICE(&s->gic),
144
cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE;
173
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
145
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit);
174
index XXXXXXX..XXXXXXX 100644
146
*
175
--- a/hw/arm/orangepi.c
147
* Return: TRUE if any hardware breakpoints in use.
176
+++ b/hw/arm/orangepi.c
148
*/
177
@@ -XXX,XX +XXX,XX @@ static void orangepi_init(MachineState *machine)
149
-
178
object_property_set_int(OBJECT(h3), 24 * 1000 * 1000, "clk1-freq",
150
bool kvm_arm_hw_debug_active(CPUState *cs);
179
&error_abort);
151
180
152
/**
181
+ /* Setup SID properties. Currently using a default fixed SID identifier. */
153
* kvm_arm_copy_hw_debug_data:
182
+ if (qemu_uuid_is_null(&h3->sid.identifier)) {
154
- *
183
+ qdev_prop_set_string(DEVICE(h3), "identifier",
155
* @ptr: kvm_guest_debug_arch structure
184
+ "02c00081-1111-2222-3333-000044556677");
156
*
185
+ } else if (ldl_be_p(&h3->sid.identifier.data[0]) != 0x02c00081) {
157
* Copy the architecture specific debug registers into the
186
+ warn_report("Security Identifier value does not include H3 prefix");
158
* kvm_guest_debug ioctl structure.
187
+ }
159
*/
188
+
160
struct kvm_guest_debug_arch;
189
/* Mark H3 object realized */
161
-
190
object_property_set_bool(OBJECT(h3), true, "realized", &error_abort);
162
void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr);
191
163
192
diff --git a/hw/misc/allwinner-sid.c b/hw/misc/allwinner-sid.c
164
/**
193
new file mode 100644
165
- * its_class_name
194
index XXXXXXX..XXXXXXX
166
+ * its_class_name:
195
--- /dev/null
167
*
196
+++ b/hw/misc/allwinner-sid.c
168
* Return the ITS class name to use depending on whether KVM acceleration
197
@@ -XXX,XX +XXX,XX @@
169
* and KVM CAP_SIGNAL_MSI are supported
198
+/*
199
+ * Allwinner Security ID emulation
200
+ *
201
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
202
+ *
203
+ * This program is free software: you can redistribute it and/or modify
204
+ * it under the terms of the GNU General Public License as published by
205
+ * the Free Software Foundation, either version 2 of the License, or
206
+ * (at your option) any later version.
207
+ *
208
+ * This program is distributed in the hope that it will be useful,
209
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
210
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
211
+ * GNU General Public License for more details.
212
+ *
213
+ * You should have received a copy of the GNU General Public License
214
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
215
+ */
216
+
217
+#include "qemu/osdep.h"
218
+#include "qemu/units.h"
219
+#include "hw/sysbus.h"
220
+#include "migration/vmstate.h"
221
+#include "qemu/log.h"
222
+#include "qemu/module.h"
223
+#include "qemu/guest-random.h"
224
+#include "qapi/error.h"
225
+#include "hw/qdev-properties.h"
226
+#include "hw/misc/allwinner-sid.h"
227
+#include "trace.h"
228
+
229
+/* SID register offsets */
230
+enum {
231
+ REG_PRCTL = 0x40, /* Control */
232
+ REG_RDKEY = 0x60, /* Read Key */
233
+};
234
+
235
+/* SID register flags */
236
+enum {
237
+ REG_PRCTL_WRITE = 0x0002, /* Unknown write flag */
238
+ REG_PRCTL_OP_LOCK = 0xAC00, /* Lock operation */
239
+};
240
+
241
+static uint64_t allwinner_sid_read(void *opaque, hwaddr offset,
242
+ unsigned size)
243
+{
244
+ const AwSidState *s = AW_SID(opaque);
245
+ uint64_t val = 0;
246
+
247
+ switch (offset) {
248
+ case REG_PRCTL: /* Control */
249
+ val = s->control;
250
+ break;
251
+ case REG_RDKEY: /* Read Key */
252
+ val = s->rdkey;
253
+ break;
254
+ default:
255
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
256
+ __func__, (uint32_t)offset);
257
+ return 0;
258
+ }
259
+
260
+ trace_allwinner_sid_read(offset, val, size);
261
+
262
+ return val;
263
+}
264
+
265
+static void allwinner_sid_write(void *opaque, hwaddr offset,
266
+ uint64_t val, unsigned size)
267
+{
268
+ AwSidState *s = AW_SID(opaque);
269
+
270
+ trace_allwinner_sid_write(offset, val, size);
271
+
272
+ switch (offset) {
273
+ case REG_PRCTL: /* Control */
274
+ s->control = val;
275
+
276
+ if ((s->control & REG_PRCTL_OP_LOCK) &&
277
+ (s->control & REG_PRCTL_WRITE)) {
278
+ uint32_t id = s->control >> 16;
279
+
280
+ if (id <= sizeof(QemuUUID) - sizeof(s->rdkey)) {
281
+ s->rdkey = ldl_be_p(&s->identifier.data[id]);
282
+ }
283
+ }
284
+ s->control &= ~REG_PRCTL_WRITE;
285
+ break;
286
+ case REG_RDKEY: /* Read Key */
287
+ break;
288
+ default:
289
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
290
+ __func__, (uint32_t)offset);
291
+ break;
292
+ }
293
+}
294
+
295
+static const MemoryRegionOps allwinner_sid_ops = {
296
+ .read = allwinner_sid_read,
297
+ .write = allwinner_sid_write,
298
+ .endianness = DEVICE_NATIVE_ENDIAN,
299
+ .valid = {
300
+ .min_access_size = 4,
301
+ .max_access_size = 4,
302
+ },
303
+ .impl.min_access_size = 4,
304
+};
305
+
306
+static void allwinner_sid_reset(DeviceState *dev)
307
+{
308
+ AwSidState *s = AW_SID(dev);
309
+
310
+ /* Set default values for registers */
311
+ s->control = 0;
312
+ s->rdkey = 0;
313
+}
314
+
315
+static void allwinner_sid_init(Object *obj)
316
+{
317
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
318
+ AwSidState *s = AW_SID(obj);
319
+
320
+ /* Memory mapping */
321
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_sid_ops, s,
322
+ TYPE_AW_SID, 1 * KiB);
323
+ sysbus_init_mmio(sbd, &s->iomem);
324
+}
325
+
326
+static Property allwinner_sid_properties[] = {
327
+ DEFINE_PROP_UUID_NODEFAULT("identifier", AwSidState, identifier),
328
+ DEFINE_PROP_END_OF_LIST()
329
+};
330
+
331
+static const VMStateDescription allwinner_sid_vmstate = {
332
+ .name = "allwinner-sid",
333
+ .version_id = 1,
334
+ .minimum_version_id = 1,
335
+ .fields = (VMStateField[]) {
336
+ VMSTATE_UINT32(control, AwSidState),
337
+ VMSTATE_UINT32(rdkey, AwSidState),
338
+ VMSTATE_UINT8_ARRAY_V(identifier.data, AwSidState, sizeof(QemuUUID), 1),
339
+ VMSTATE_END_OF_LIST()
340
+ }
341
+};
342
+
343
+static void allwinner_sid_class_init(ObjectClass *klass, void *data)
344
+{
345
+ DeviceClass *dc = DEVICE_CLASS(klass);
346
+
347
+ dc->reset = allwinner_sid_reset;
348
+ dc->vmsd = &allwinner_sid_vmstate;
349
+ device_class_set_props(dc, allwinner_sid_properties);
350
+}
351
+
352
+static const TypeInfo allwinner_sid_info = {
353
+ .name = TYPE_AW_SID,
354
+ .parent = TYPE_SYS_BUS_DEVICE,
355
+ .instance_init = allwinner_sid_init,
356
+ .instance_size = sizeof(AwSidState),
357
+ .class_init = allwinner_sid_class_init,
358
+};
359
+
360
+static void allwinner_sid_register(void)
361
+{
362
+ type_register_static(&allwinner_sid_info);
363
+}
364
+
365
+type_init(allwinner_sid_register)
366
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
367
index XXXXXXX..XXXXXXX 100644
368
--- a/hw/misc/trace-events
369
+++ b/hw/misc/trace-events
370
@@ -XXX,XX +XXX,XX @@ allwinner_cpucfg_cpu_reset(uint8_t cpu_id, uint32_t reset_addr) "id %u, reset_ad
371
allwinner_cpucfg_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
372
allwinner_cpucfg_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
373
374
+# allwinner-sid.c
375
+allwinner_sid_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
376
+allwinner_sid_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
377
+
378
# eccmemctl.c
379
ecc_mem_writel_mer(uint32_t val) "Write memory enable 0x%08x"
380
ecc_mem_writel_mdr(uint32_t val) "Write memory delay 0x%08x"
170
--
381
--
171
2.20.1
382
2.20.1
172
383
173
384
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Provide a temporary device_legacy_reset function doing what
3
The Allwinner System on Chip families sun4i and above contain
4
device_reset does to prepare for the transition with Resettable
4
an integrated storage controller for Secure Digital (SD) and
5
API.
5
Multi Media Card (MMC) interfaces. This commit adds support
6
for the Allwinner SD/MMC storage controller with the following
7
emulated features:
6
8
7
All occurrence of device_reset in the code tree are also replaced
9
* DMA transfers
8
by device_legacy_reset.
10
* Direct FIFO I/O
11
* Short/Long format command responses
12
* Auto-Stop command (CMD12)
13
* Insert & remove card detection
9
14
10
The new resettable API has different prototype and semantics
15
The following boards are extended with the SD host controller:
11
(resetting child buses as well as the specified device). Subsequent
12
commits will make the changeover for each call site individually; once
13
that is complete device_legacy_reset() will be removed.
14
16
15
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
17
* Cubieboard (hw/arm/cubieboard.c)
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
* Orange Pi PC (hw/arm/orangepi.c)
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
18
Acked-by: David Gibson <david@gibson.dropbear.id.au>
20
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
19
Acked-by: Cornelia Huck <cohuck@redhat.com>
21
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
20
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
22
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
21
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
23
Message-id: 20200311221854.30370-9-nieklinnenbank@gmail.com
22
Message-id: 20200123132823.1117486-2-damien.hedde@greensocs.com
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
---
25
---
25
include/hw/qdev-core.h | 4 ++--
26
hw/sd/Makefile.objs | 1 +
26
hw/audio/intel-hda.c | 2 +-
27
include/hw/arm/allwinner-a10.h | 2 +
27
hw/core/qdev.c | 6 +++---
28
include/hw/arm/allwinner-h3.h | 3 +
28
hw/hyperv/hyperv.c | 2 +-
29
include/hw/sd/allwinner-sdhost.h | 135 +++++
29
hw/i386/microvm.c | 2 +-
30
hw/arm/allwinner-a10.c | 11 +
30
hw/i386/pc.c | 2 +-
31
hw/arm/allwinner-h3.c | 15 +-
31
hw/ide/microdrive.c | 8 ++++----
32
hw/arm/cubieboard.c | 15 +
32
hw/intc/spapr_xive.c | 2 +-
33
hw/arm/orangepi.c | 16 +
33
hw/ppc/pnv_psi.c | 4 ++--
34
hw/sd/allwinner-sdhost.c | 854 +++++++++++++++++++++++++++++++
34
hw/ppc/spapr_pci.c | 2 +-
35
hw/arm/Kconfig | 1 +
35
hw/ppc/spapr_vio.c | 2 +-
36
hw/sd/trace-events | 7 +
36
hw/s390x/s390-pci-inst.c | 2 +-
37
11 files changed, 1059 insertions(+), 1 deletion(-)
37
hw/scsi/vmw_pvscsi.c | 2 +-
38
create mode 100644 include/hw/sd/allwinner-sdhost.h
38
hw/sd/omap_mmc.c | 2 +-
39
create mode 100644 hw/sd/allwinner-sdhost.c
39
hw/sd/pl181.c | 2 +-
40
15 files changed, 22 insertions(+), 22 deletions(-)
41
40
42
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
41
diff --git a/hw/sd/Makefile.objs b/hw/sd/Makefile.objs
43
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
44
--- a/include/hw/qdev-core.h
43
--- a/hw/sd/Makefile.objs
45
+++ b/include/hw/qdev-core.h
44
+++ b/hw/sd/Makefile.objs
46
@@ -XXX,XX +XXX,XX @@ char *qdev_get_own_fw_dev_path_from_handler(BusState *bus, DeviceState *dev);
45
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_SD) += sd.o core.o sdmmc-internal.o
47
void qdev_machine_init(void);
46
common-obj-$(CONFIG_SDHCI) += sdhci.o
47
common-obj-$(CONFIG_SDHCI_PCI) += sdhci-pci.o
48
49
+common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-sdhost.o
50
common-obj-$(CONFIG_MILKYMIST) += milkymist-memcard.o
51
common-obj-$(CONFIG_OMAP) += omap_mmc.o
52
common-obj-$(CONFIG_PXA2XX) += pxa2xx_mmci.o
53
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
54
index XXXXXXX..XXXXXXX 100644
55
--- a/include/hw/arm/allwinner-a10.h
56
+++ b/include/hw/arm/allwinner-a10.h
57
@@ -XXX,XX +XXX,XX @@
58
#include "hw/timer/allwinner-a10-pit.h"
59
#include "hw/intc/allwinner-a10-pic.h"
60
#include "hw/net/allwinner_emac.h"
61
+#include "hw/sd/allwinner-sdhost.h"
62
#include "hw/ide/ahci.h"
63
#include "hw/usb/hcd-ohci.h"
64
#include "hw/usb/hcd-ehci.h"
65
@@ -XXX,XX +XXX,XX @@ typedef struct AwA10State {
66
AwA10PICState intc;
67
AwEmacState emac;
68
AllwinnerAHCIState sata;
69
+ AwSdHostState mmc0;
70
MemoryRegion sram_a;
71
EHCISysBusState ehci[AW_A10_NUM_USB];
72
OHCISysBusState ohci[AW_A10_NUM_USB];
73
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
74
index XXXXXXX..XXXXXXX 100644
75
--- a/include/hw/arm/allwinner-h3.h
76
+++ b/include/hw/arm/allwinner-h3.h
77
@@ -XXX,XX +XXX,XX @@
78
#include "hw/misc/allwinner-cpucfg.h"
79
#include "hw/misc/allwinner-h3-sysctrl.h"
80
#include "hw/misc/allwinner-sid.h"
81
+#include "hw/sd/allwinner-sdhost.h"
82
#include "target/arm/cpu.h"
48
83
49
/**
84
/**
50
- * @device_reset
85
@@ -XXX,XX +XXX,XX @@ enum {
51
+ * device_legacy_reset:
86
AW_H3_SRAM_A2,
52
*
87
AW_H3_SRAM_C,
53
* Reset a single device (by calling the reset method).
88
AW_H3_SYSCTRL,
54
*/
89
+ AW_H3_MMC0,
55
-void device_reset(DeviceState *dev);
90
AW_H3_SID,
56
+void device_legacy_reset(DeviceState *dev);
91
AW_H3_EHCI0,
57
92
AW_H3_OHCI0,
58
void device_class_set_props(DeviceClass *dc, Property *props);
93
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
59
94
AwCpuCfgState cpucfg;
60
diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
95
AwH3SysCtrlState sysctrl;
96
AwSidState sid;
97
+ AwSdHostState mmc0;
98
GICState gic;
99
MemoryRegion sram_a1;
100
MemoryRegion sram_a2;
101
diff --git a/include/hw/sd/allwinner-sdhost.h b/include/hw/sd/allwinner-sdhost.h
102
new file mode 100644
103
index XXXXXXX..XXXXXXX
104
--- /dev/null
105
+++ b/include/hw/sd/allwinner-sdhost.h
106
@@ -XXX,XX +XXX,XX @@
107
+/*
108
+ * Allwinner (sun4i and above) SD Host Controller emulation
109
+ *
110
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
111
+ *
112
+ * This program is free software: you can redistribute it and/or modify
113
+ * it under the terms of the GNU General Public License as published by
114
+ * the Free Software Foundation, either version 2 of the License, or
115
+ * (at your option) any later version.
116
+ *
117
+ * This program is distributed in the hope that it will be useful,
118
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
119
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
120
+ * GNU General Public License for more details.
121
+ *
122
+ * You should have received a copy of the GNU General Public License
123
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
124
+ */
125
+
126
+#ifndef HW_SD_ALLWINNER_SDHOST_H
127
+#define HW_SD_ALLWINNER_SDHOST_H
128
+
129
+#include "qom/object.h"
130
+#include "hw/sysbus.h"
131
+#include "hw/sd/sd.h"
132
+
133
+/**
134
+ * Object model types
135
+ * @{
136
+ */
137
+
138
+/** Generic Allwinner SD Host Controller (abstract) */
139
+#define TYPE_AW_SDHOST "allwinner-sdhost"
140
+
141
+/** Allwinner sun4i family (A10, A12) */
142
+#define TYPE_AW_SDHOST_SUN4I TYPE_AW_SDHOST "-sun4i"
143
+
144
+/** Allwinner sun5i family and newer (A13, H2+, H3, etc) */
145
+#define TYPE_AW_SDHOST_SUN5I TYPE_AW_SDHOST "-sun5i"
146
+
147
+/** @} */
148
+
149
+/**
150
+ * Object model macros
151
+ * @{
152
+ */
153
+
154
+#define AW_SDHOST(obj) \
155
+ OBJECT_CHECK(AwSdHostState, (obj), TYPE_AW_SDHOST)
156
+#define AW_SDHOST_CLASS(klass) \
157
+ OBJECT_CLASS_CHECK(AwSdHostClass, (klass), TYPE_AW_SDHOST)
158
+#define AW_SDHOST_GET_CLASS(obj) \
159
+ OBJECT_GET_CLASS(AwSdHostClass, (obj), TYPE_AW_SDHOST)
160
+
161
+/** @} */
162
+
163
+/**
164
+ * Allwinner SD Host Controller object instance state.
165
+ */
166
+typedef struct AwSdHostState {
167
+ /*< private >*/
168
+ SysBusDevice busdev;
169
+ /*< public >*/
170
+
171
+ /** Secure Digital (SD) bus, which connects to SD card (if present) */
172
+ SDBus sdbus;
173
+
174
+ /** Maps I/O registers in physical memory */
175
+ MemoryRegion iomem;
176
+
177
+ /** Interrupt output signal to notify CPU */
178
+ qemu_irq irq;
179
+
180
+ /** Number of bytes left in current DMA transfer */
181
+ uint32_t transfer_cnt;
182
+
183
+ /**
184
+ * @name Hardware Registers
185
+ * @{
186
+ */
187
+
188
+ uint32_t global_ctl; /**< Global Control */
189
+ uint32_t clock_ctl; /**< Clock Control */
190
+ uint32_t timeout; /**< Timeout */
191
+ uint32_t bus_width; /**< Bus Width */
192
+ uint32_t block_size; /**< Block Size */
193
+ uint32_t byte_count; /**< Byte Count */
194
+
195
+ uint32_t command; /**< Command */
196
+ uint32_t command_arg; /**< Command Argument */
197
+ uint32_t response[4]; /**< Command Response */
198
+
199
+ uint32_t irq_mask; /**< Interrupt Mask */
200
+ uint32_t irq_status; /**< Raw Interrupt Status */
201
+ uint32_t status; /**< Status */
202
+
203
+ uint32_t fifo_wlevel; /**< FIFO Water Level */
204
+ uint32_t fifo_func_sel; /**< FIFO Function Select */
205
+ uint32_t debug_enable; /**< Debug Enable */
206
+ uint32_t auto12_arg; /**< Auto Command 12 Argument */
207
+ uint32_t newtiming_set; /**< SD New Timing Set */
208
+ uint32_t newtiming_debug; /**< SD New Timing Debug */
209
+ uint32_t hardware_rst; /**< Hardware Reset */
210
+ uint32_t dmac; /**< Internal DMA Controller Control */
211
+ uint32_t desc_base; /**< Descriptor List Base Address */
212
+ uint32_t dmac_status; /**< Internal DMA Controller Status */
213
+ uint32_t dmac_irq; /**< Internal DMA Controller IRQ Enable */
214
+ uint32_t card_threshold; /**< Card Threshold Control */
215
+ uint32_t startbit_detect; /**< eMMC DDR Start Bit Detection Control */
216
+ uint32_t response_crc; /**< Response CRC */
217
+ uint32_t data_crc[8]; /**< Data CRC */
218
+ uint32_t status_crc; /**< Status CRC */
219
+
220
+ /** @} */
221
+
222
+} AwSdHostState;
223
+
224
+/**
225
+ * Allwinner SD Host Controller class-level struct.
226
+ *
227
+ * This struct is filled by each sunxi device specific code
228
+ * such that the generic code can use this struct to support
229
+ * all devices.
230
+ */
231
+typedef struct AwSdHostClass {
232
+ /*< private >*/
233
+ SysBusDeviceClass parent_class;
234
+ /*< public >*/
235
+
236
+ /** Maximum buffer size in bytes per DMA descriptor */
237
+ size_t max_desc_size;
238
+
239
+} AwSdHostClass;
240
+
241
+#endif /* HW_SD_ALLWINNER_SDHOST_H */
242
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
61
index XXXXXXX..XXXXXXX 100644
243
index XXXXXXX..XXXXXXX 100644
62
--- a/hw/audio/intel-hda.c
244
--- a/hw/arm/allwinner-a10.c
63
+++ b/hw/audio/intel-hda.c
245
+++ b/hw/arm/allwinner-a10.c
64
@@ -XXX,XX +XXX,XX @@ static void intel_hda_reset(DeviceState *dev)
246
@@ -XXX,XX +XXX,XX @@
65
QTAILQ_FOREACH(kid, &d->codecs.qbus.children, sibling) {
247
#include "hw/boards.h"
66
DeviceState *qdev = kid->child;
248
#include "hw/usb/hcd-ohci.h"
67
cdev = HDA_CODEC_DEVICE(qdev);
249
68
- device_reset(DEVICE(cdev));
250
+#define AW_A10_MMC0_BASE 0x01c0f000
69
+ device_legacy_reset(DEVICE(cdev));
251
#define AW_A10_PIC_REG_BASE 0x01c20400
70
d->state_sts |= (1 << cdev->cad);
252
#define AW_A10_PIT_REG_BASE 0x01c20c00
71
}
253
#define AW_A10_UART0_REG_BASE 0x01c28000
72
intel_hda_update_irq(d);
254
@@ -XXX,XX +XXX,XX @@ static void aw_a10_init(Object *obj)
73
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
255
sizeof(s->ohci[i]), TYPE_SYSBUS_OHCI);
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/core/qdev.c
76
+++ b/hw/core/qdev.c
77
@@ -XXX,XX +XXX,XX @@ HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
78
79
static int qdev_reset_one(DeviceState *dev, void *opaque)
80
{
81
- device_reset(dev);
82
+ device_legacy_reset(dev);
83
84
return 0;
85
}
86
@@ -XXX,XX +XXX,XX @@ static void device_set_realized(Object *obj, bool value, Error **errp)
87
}
88
}
89
if (dev->hotplugged) {
90
- device_reset(dev);
91
+ device_legacy_reset(dev);
92
}
93
dev->pending_deleted_event = false;
94
95
@@ -XXX,XX +XXX,XX @@ void device_class_set_parent_unrealize(DeviceClass *dc,
96
dc->unrealize = dev_unrealize;
97
}
98
99
-void device_reset(DeviceState *dev)
100
+void device_legacy_reset(DeviceState *dev)
101
{
102
DeviceClass *klass = DEVICE_GET_CLASS(dev);
103
104
diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c
105
index XXXXXXX..XXXXXXX 100644
106
--- a/hw/hyperv/hyperv.c
107
+++ b/hw/hyperv/hyperv.c
108
@@ -XXX,XX +XXX,XX @@ void hyperv_synic_reset(CPUState *cs)
109
SynICState *synic = get_synic(cs);
110
111
if (synic) {
112
- device_reset(DEVICE(synic));
113
+ device_legacy_reset(DEVICE(synic));
114
}
115
}
116
117
diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/hw/i386/microvm.c
120
+++ b/hw/i386/microvm.c
121
@@ -XXX,XX +XXX,XX @@ static void microvm_machine_reset(MachineState *machine)
122
cpu = X86_CPU(cs);
123
124
if (cpu->apic_state) {
125
- device_reset(cpu->apic_state);
126
+ device_legacy_reset(cpu->apic_state);
127
}
256
}
128
}
257
}
258
+
259
+ sysbus_init_child_obj(obj, "mmc0", &s->mmc0, sizeof(s->mmc0),
260
+ TYPE_AW_SDHOST_SUN4I);
129
}
261
}
130
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
262
131
index XXXXXXX..XXXXXXX 100644
263
static void aw_a10_realize(DeviceState *dev, Error **errp)
132
--- a/hw/i386/pc.c
264
@@ -XXX,XX +XXX,XX @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
133
+++ b/hw/i386/pc.c
265
qdev_get_gpio_in(dev, 64 + i));
134
@@ -XXX,XX +XXX,XX @@ static void pc_machine_reset(MachineState *machine)
135
cpu = X86_CPU(cs);
136
137
if (cpu->apic_state) {
138
- device_reset(cpu->apic_state);
139
+ device_legacy_reset(cpu->apic_state);
140
}
266
}
141
}
267
}
268
+
269
+ /* SD/MMC */
270
+ qdev_init_nofail(DEVICE(&s->mmc0));
271
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc0), 0, AW_A10_MMC0_BASE);
272
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc0), 0, qdev_get_gpio_in(dev, 32));
273
+ object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->mmc0),
274
+ "sd-bus", &error_abort);
142
}
275
}
143
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
276
277
static void aw_a10_class_init(ObjectClass *oc, void *data)
278
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
144
index XXXXXXX..XXXXXXX 100644
279
index XXXXXXX..XXXXXXX 100644
145
--- a/hw/ide/microdrive.c
280
--- a/hw/arm/allwinner-h3.c
146
+++ b/hw/ide/microdrive.c
281
+++ b/hw/arm/allwinner-h3.c
147
@@ -XXX,XX +XXX,XX @@ static void md_attr_write(PCMCIACardState *card, uint32_t at, uint8_t value)
282
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
148
case 0x00:    /* Configuration Option Register */
283
[AW_H3_SRAM_A2] = 0x00044000,
149
s->opt = value & 0xcf;
284
[AW_H3_SRAM_C] = 0x00010000,
150
if (value & OPT_SRESET) {
285
[AW_H3_SYSCTRL] = 0x01c00000,
151
- device_reset(DEVICE(s));
286
+ [AW_H3_MMC0] = 0x01c0f000,
152
+ device_legacy_reset(DEVICE(s));
287
[AW_H3_SID] = 0x01c14000,
153
}
288
[AW_H3_EHCI0] = 0x01c1a000,
154
md_interrupt_update(s);
289
[AW_H3_OHCI0] = 0x01c1a400,
155
break;
290
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
156
@@ -XXX,XX +XXX,XX @@ static void md_common_write(PCMCIACardState *card, uint32_t at, uint16_t value)
291
{ "lcd0", 0x01c0c000, 4 * KiB },
157
case 0xe:    /* Device Control */
292
{ "lcd1", 0x01c0d000, 4 * KiB },
158
s->ctrl = value;
293
{ "ve", 0x01c0e000, 4 * KiB },
159
if (value & CTRL_SRST) {
294
- { "mmc0", 0x01c0f000, 4 * KiB },
160
- device_reset(DEVICE(s));
295
{ "mmc1", 0x01c10000, 4 * KiB },
161
+ device_legacy_reset(DEVICE(s));
296
{ "mmc2", 0x01c11000, 4 * KiB },
162
}
297
{ "crypto", 0x01c15000, 4 * KiB },
163
md_interrupt_update(s);
298
@@ -XXX,XX +XXX,XX @@ enum {
164
break;
299
AW_H3_GIC_SPI_UART3 = 3,
165
@@ -XXX,XX +XXX,XX @@ static int dscm1xxxx_attach(PCMCIACardState *card)
300
AW_H3_GIC_SPI_TIMER0 = 18,
166
md->attr_base = pcc->cis[0x74] | (pcc->cis[0x76] << 8);
301
AW_H3_GIC_SPI_TIMER1 = 19,
167
md->io_base = 0x0;
302
+ AW_H3_GIC_SPI_MMC0 = 60,
168
303
AW_H3_GIC_SPI_EHCI0 = 72,
169
- device_reset(DEVICE(md));
304
AW_H3_GIC_SPI_OHCI0 = 73,
170
+ device_legacy_reset(DEVICE(md));
305
AW_H3_GIC_SPI_EHCI1 = 74,
171
md_interrupt_update(md);
306
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
172
307
TYPE_AW_SID);
173
return 0;
308
object_property_add_alias(obj, "identifier", OBJECT(&s->sid),
174
@@ -XXX,XX +XXX,XX @@ static int dscm1xxxx_detach(PCMCIACardState *card)
309
"identifier", &error_abort);
310
+
311
+ sysbus_init_child_obj(obj, "mmc0", &s->mmc0, sizeof(s->mmc0),
312
+ TYPE_AW_SDHOST_SUN5I);
313
}
314
315
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
316
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
317
qdev_init_nofail(DEVICE(&s->sid));
318
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sid), 0, s->memmap[AW_H3_SID]);
319
320
+ /* SD/MMC */
321
+ qdev_init_nofail(DEVICE(&s->mmc0));
322
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc0), 0, s->memmap[AW_H3_MMC0]);
323
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc0), 0,
324
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_MMC0));
325
+
326
+ object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->mmc0),
327
+ "sd-bus", &error_abort);
328
+
329
/* Universal Serial Bus */
330
sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI0],
331
qdev_get_gpio_in(DEVICE(&s->gic),
332
diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
333
index XXXXXXX..XXXXXXX 100644
334
--- a/hw/arm/cubieboard.c
335
+++ b/hw/arm/cubieboard.c
336
@@ -XXX,XX +XXX,XX @@
337
#include "sysemu/sysemu.h"
338
#include "hw/sysbus.h"
339
#include "hw/boards.h"
340
+#include "hw/qdev-properties.h"
341
#include "hw/arm/allwinner-a10.h"
342
343
static struct arm_boot_info cubieboard_binfo = {
344
@@ -XXX,XX +XXX,XX @@ static void cubieboard_init(MachineState *machine)
175
{
345
{
176
MicroDriveState *md = MICRODRIVE(card);
346
AwA10State *a10;
177
347
Error *err = NULL;
178
- device_reset(DEVICE(md));
348
+ DriveInfo *di;
179
+ device_legacy_reset(DEVICE(md));
349
+ BlockBackend *blk;
180
return 0;
350
+ BusState *bus;
181
}
351
+ DeviceState *carddev;
182
352
183
diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
353
/* BIOS is not supported by this board */
354
if (bios_name) {
355
@@ -XXX,XX +XXX,XX @@ static void cubieboard_init(MachineState *machine)
356
exit(1);
357
}
358
359
+ /* Retrieve SD bus */
360
+ di = drive_get_next(IF_SD);
361
+ blk = di ? blk_by_legacy_dinfo(di) : NULL;
362
+ bus = qdev_get_child_bus(DEVICE(a10), "sd-bus");
363
+
364
+ /* Plug in SD card */
365
+ carddev = qdev_create(bus, TYPE_SD_CARD);
366
+ qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
367
+ object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal);
368
+
369
memory_region_add_subregion(get_system_memory(), AW_A10_SDRAM_BASE,
370
machine->ram);
371
372
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
184
index XXXXXXX..XXXXXXX 100644
373
index XXXXXXX..XXXXXXX 100644
185
--- a/hw/intc/spapr_xive.c
374
--- a/hw/arm/orangepi.c
186
+++ b/hw/intc/spapr_xive.c
375
+++ b/hw/arm/orangepi.c
187
@@ -XXX,XX +XXX,XX @@ static target_ulong h_int_reset(PowerPCCPU *cpu,
376
@@ -XXX,XX +XXX,XX @@ static struct arm_boot_info orangepi_binfo = {
188
return H_PARAMETER;
377
static void orangepi_init(MachineState *machine)
189
}
378
{
190
379
AwH3State *h3;
191
- device_reset(DEVICE(xive));
380
+ DriveInfo *di;
192
+ device_legacy_reset(DEVICE(xive));
381
+ BlockBackend *blk;
193
382
+ BusState *bus;
194
if (kvm_irqchip_in_kernel()) {
383
+ DeviceState *carddev;
195
Error *local_err = NULL;
384
196
diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c
385
/* BIOS is not supported by this board */
386
if (bios_name) {
387
@@ -XXX,XX +XXX,XX @@ static void orangepi_init(MachineState *machine)
388
/* Mark H3 object realized */
389
object_property_set_bool(OBJECT(h3), true, "realized", &error_abort);
390
391
+ /* Retrieve SD bus */
392
+ di = drive_get_next(IF_SD);
393
+ blk = di ? blk_by_legacy_dinfo(di) : NULL;
394
+ bus = qdev_get_child_bus(DEVICE(h3), "sd-bus");
395
+
396
+ /* Plug in SD card */
397
+ carddev = qdev_create(bus, TYPE_SD_CARD);
398
+ qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
399
+ object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal);
400
+
401
/* SDRAM */
402
memory_region_add_subregion(get_system_memory(), h3->memmap[AW_H3_SDRAM],
403
machine->ram);
404
@@ -XXX,XX +XXX,XX @@ static void orangepi_machine_init(MachineClass *mc)
405
{
406
mc->desc = "Orange Pi PC";
407
mc->init = orangepi_init;
408
+ mc->block_default_type = IF_SD;
409
+ mc->units_per_default_bus = 1;
410
mc->min_cpus = AW_H3_NUM_CPUS;
411
mc->max_cpus = AW_H3_NUM_CPUS;
412
mc->default_cpus = AW_H3_NUM_CPUS;
413
diff --git a/hw/sd/allwinner-sdhost.c b/hw/sd/allwinner-sdhost.c
414
new file mode 100644
415
index XXXXXXX..XXXXXXX
416
--- /dev/null
417
+++ b/hw/sd/allwinner-sdhost.c
418
@@ -XXX,XX +XXX,XX @@
419
+/*
420
+ * Allwinner (sun4i and above) SD Host Controller emulation
421
+ *
422
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
423
+ *
424
+ * This program is free software: you can redistribute it and/or modify
425
+ * it under the terms of the GNU General Public License as published by
426
+ * the Free Software Foundation, either version 2 of the License, or
427
+ * (at your option) any later version.
428
+ *
429
+ * This program is distributed in the hope that it will be useful,
430
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
431
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
432
+ * GNU General Public License for more details.
433
+ *
434
+ * You should have received a copy of the GNU General Public License
435
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
436
+ */
437
+
438
+#include "qemu/osdep.h"
439
+#include "qemu/log.h"
440
+#include "qemu/module.h"
441
+#include "qemu/units.h"
442
+#include "sysemu/blockdev.h"
443
+#include "hw/irq.h"
444
+#include "hw/sd/allwinner-sdhost.h"
445
+#include "migration/vmstate.h"
446
+#include "trace.h"
447
+
448
+#define TYPE_AW_SDHOST_BUS "allwinner-sdhost-bus"
449
+#define AW_SDHOST_BUS(obj) \
450
+ OBJECT_CHECK(SDBus, (obj), TYPE_AW_SDHOST_BUS)
451
+
452
+/* SD Host register offsets */
453
+enum {
454
+ REG_SD_GCTL = 0x00, /* Global Control */
455
+ REG_SD_CKCR = 0x04, /* Clock Control */
456
+ REG_SD_TMOR = 0x08, /* Timeout */
457
+ REG_SD_BWDR = 0x0C, /* Bus Width */
458
+ REG_SD_BKSR = 0x10, /* Block Size */
459
+ REG_SD_BYCR = 0x14, /* Byte Count */
460
+ REG_SD_CMDR = 0x18, /* Command */
461
+ REG_SD_CAGR = 0x1C, /* Command Argument */
462
+ REG_SD_RESP0 = 0x20, /* Response Zero */
463
+ REG_SD_RESP1 = 0x24, /* Response One */
464
+ REG_SD_RESP2 = 0x28, /* Response Two */
465
+ REG_SD_RESP3 = 0x2C, /* Response Three */
466
+ REG_SD_IMKR = 0x30, /* Interrupt Mask */
467
+ REG_SD_MISR = 0x34, /* Masked Interrupt Status */
468
+ REG_SD_RISR = 0x38, /* Raw Interrupt Status */
469
+ REG_SD_STAR = 0x3C, /* Status */
470
+ REG_SD_FWLR = 0x40, /* FIFO Water Level */
471
+ REG_SD_FUNS = 0x44, /* FIFO Function Select */
472
+ REG_SD_DBGC = 0x50, /* Debug Enable */
473
+ REG_SD_A12A = 0x58, /* Auto command 12 argument */
474
+ REG_SD_NTSR = 0x5C, /* SD NewTiming Set */
475
+ REG_SD_SDBG = 0x60, /* SD newTiming Set Debug */
476
+ REG_SD_HWRST = 0x78, /* Hardware Reset Register */
477
+ REG_SD_DMAC = 0x80, /* Internal DMA Controller Control */
478
+ REG_SD_DLBA = 0x84, /* Descriptor List Base Address */
479
+ REG_SD_IDST = 0x88, /* Internal DMA Controller Status */
480
+ REG_SD_IDIE = 0x8C, /* Internal DMA Controller IRQ Enable */
481
+ REG_SD_THLDC = 0x100, /* Card Threshold Control */
482
+ REG_SD_DSBD = 0x10C, /* eMMC DDR Start Bit Detection Control */
483
+ REG_SD_RES_CRC = 0x110, /* Response CRC from card/eMMC */
484
+ REG_SD_DATA7_CRC = 0x114, /* CRC Data 7 from card/eMMC */
485
+ REG_SD_DATA6_CRC = 0x118, /* CRC Data 6 from card/eMMC */
486
+ REG_SD_DATA5_CRC = 0x11C, /* CRC Data 5 from card/eMMC */
487
+ REG_SD_DATA4_CRC = 0x120, /* CRC Data 4 from card/eMMC */
488
+ REG_SD_DATA3_CRC = 0x124, /* CRC Data 3 from card/eMMC */
489
+ REG_SD_DATA2_CRC = 0x128, /* CRC Data 2 from card/eMMC */
490
+ REG_SD_DATA1_CRC = 0x12C, /* CRC Data 1 from card/eMMC */
491
+ REG_SD_DATA0_CRC = 0x130, /* CRC Data 0 from card/eMMC */
492
+ REG_SD_CRC_STA = 0x134, /* CRC status from card/eMMC during write */
493
+ REG_SD_FIFO = 0x200, /* Read/Write FIFO */
494
+};
495
+
496
+/* SD Host register flags */
497
+enum {
498
+ SD_GCTL_FIFO_AC_MOD = (1 << 31),
499
+ SD_GCTL_DDR_MOD_SEL = (1 << 10),
500
+ SD_GCTL_CD_DBC_ENB = (1 << 8),
501
+ SD_GCTL_DMA_ENB = (1 << 5),
502
+ SD_GCTL_INT_ENB = (1 << 4),
503
+ SD_GCTL_DMA_RST = (1 << 2),
504
+ SD_GCTL_FIFO_RST = (1 << 1),
505
+ SD_GCTL_SOFT_RST = (1 << 0),
506
+};
507
+
508
+enum {
509
+ SD_CMDR_LOAD = (1 << 31),
510
+ SD_CMDR_CLKCHANGE = (1 << 21),
511
+ SD_CMDR_WRITE = (1 << 10),
512
+ SD_CMDR_AUTOSTOP = (1 << 12),
513
+ SD_CMDR_DATA = (1 << 9),
514
+ SD_CMDR_RESPONSE_LONG = (1 << 7),
515
+ SD_CMDR_RESPONSE = (1 << 6),
516
+ SD_CMDR_CMDID_MASK = (0x3f),
517
+};
518
+
519
+enum {
520
+ SD_RISR_CARD_REMOVE = (1 << 31),
521
+ SD_RISR_CARD_INSERT = (1 << 30),
522
+ SD_RISR_SDIO_INTR = (1 << 16),
523
+ SD_RISR_AUTOCMD_DONE = (1 << 14),
524
+ SD_RISR_DATA_COMPLETE = (1 << 3),
525
+ SD_RISR_CMD_COMPLETE = (1 << 2),
526
+ SD_RISR_NO_RESPONSE = (1 << 1),
527
+};
528
+
529
+enum {
530
+ SD_STAR_CARD_PRESENT = (1 << 8),
531
+};
532
+
533
+enum {
534
+ SD_IDST_INT_SUMMARY = (1 << 8),
535
+ SD_IDST_RECEIVE_IRQ = (1 << 1),
536
+ SD_IDST_TRANSMIT_IRQ = (1 << 0),
537
+ SD_IDST_IRQ_MASK = (1 << 1) | (1 << 0) | (1 << 8),
538
+ SD_IDST_WR_MASK = (0x3ff),
539
+};
540
+
541
+/* SD Host register reset values */
542
+enum {
543
+ REG_SD_GCTL_RST = 0x00000300,
544
+ REG_SD_CKCR_RST = 0x0,
545
+ REG_SD_TMOR_RST = 0xFFFFFF40,
546
+ REG_SD_BWDR_RST = 0x0,
547
+ REG_SD_BKSR_RST = 0x00000200,
548
+ REG_SD_BYCR_RST = 0x00000200,
549
+ REG_SD_CMDR_RST = 0x0,
550
+ REG_SD_CAGR_RST = 0x0,
551
+ REG_SD_RESP_RST = 0x0,
552
+ REG_SD_IMKR_RST = 0x0,
553
+ REG_SD_MISR_RST = 0x0,
554
+ REG_SD_RISR_RST = 0x0,
555
+ REG_SD_STAR_RST = 0x00000100,
556
+ REG_SD_FWLR_RST = 0x000F0000,
557
+ REG_SD_FUNS_RST = 0x0,
558
+ REG_SD_DBGC_RST = 0x0,
559
+ REG_SD_A12A_RST = 0x0000FFFF,
560
+ REG_SD_NTSR_RST = 0x00000001,
561
+ REG_SD_SDBG_RST = 0x0,
562
+ REG_SD_HWRST_RST = 0x00000001,
563
+ REG_SD_DMAC_RST = 0x0,
564
+ REG_SD_DLBA_RST = 0x0,
565
+ REG_SD_IDST_RST = 0x0,
566
+ REG_SD_IDIE_RST = 0x0,
567
+ REG_SD_THLDC_RST = 0x0,
568
+ REG_SD_DSBD_RST = 0x0,
569
+ REG_SD_RES_CRC_RST = 0x0,
570
+ REG_SD_DATA_CRC_RST = 0x0,
571
+ REG_SD_CRC_STA_RST = 0x0,
572
+ REG_SD_FIFO_RST = 0x0,
573
+};
574
+
575
+/* Data transfer descriptor for DMA */
576
+typedef struct TransferDescriptor {
577
+ uint32_t status; /* Status flags */
578
+ uint32_t size; /* Data buffer size */
579
+ uint32_t addr; /* Data buffer address */
580
+ uint32_t next; /* Physical address of next descriptor */
581
+} TransferDescriptor;
582
+
583
+/* Data transfer descriptor flags */
584
+enum {
585
+ DESC_STATUS_HOLD = (1 << 31), /* Set when descriptor is in use by DMA */
586
+ DESC_STATUS_ERROR = (1 << 30), /* Set when DMA transfer error occurred */
587
+ DESC_STATUS_CHAIN = (1 << 4), /* Indicates chained descriptor. */
588
+ DESC_STATUS_FIRST = (1 << 3), /* Set on the first descriptor */
589
+ DESC_STATUS_LAST = (1 << 2), /* Set on the last descriptor */
590
+ DESC_STATUS_NOIRQ = (1 << 1), /* Skip raising interrupt after transfer */
591
+ DESC_SIZE_MASK = (0xfffffffc)
592
+};
593
+
594
+static void allwinner_sdhost_update_irq(AwSdHostState *s)
595
+{
596
+ uint32_t irq;
597
+
598
+ if (s->global_ctl & SD_GCTL_INT_ENB) {
599
+ irq = s->irq_status & s->irq_mask;
600
+ } else {
601
+ irq = 0;
602
+ }
603
+
604
+ trace_allwinner_sdhost_update_irq(irq);
605
+ qemu_set_irq(s->irq, irq);
606
+}
607
+
608
+static void allwinner_sdhost_update_transfer_cnt(AwSdHostState *s,
609
+ uint32_t bytes)
610
+{
611
+ if (s->transfer_cnt > bytes) {
612
+ s->transfer_cnt -= bytes;
613
+ } else {
614
+ s->transfer_cnt = 0;
615
+ }
616
+
617
+ if (!s->transfer_cnt) {
618
+ s->irq_status |= SD_RISR_DATA_COMPLETE;
619
+ }
620
+}
621
+
622
+static void allwinner_sdhost_set_inserted(DeviceState *dev, bool inserted)
623
+{
624
+ AwSdHostState *s = AW_SDHOST(dev);
625
+
626
+ trace_allwinner_sdhost_set_inserted(inserted);
627
+
628
+ if (inserted) {
629
+ s->irq_status |= SD_RISR_CARD_INSERT;
630
+ s->irq_status &= ~SD_RISR_CARD_REMOVE;
631
+ s->status |= SD_STAR_CARD_PRESENT;
632
+ } else {
633
+ s->irq_status &= ~SD_RISR_CARD_INSERT;
634
+ s->irq_status |= SD_RISR_CARD_REMOVE;
635
+ s->status &= ~SD_STAR_CARD_PRESENT;
636
+ }
637
+
638
+ allwinner_sdhost_update_irq(s);
639
+}
640
+
641
+static void allwinner_sdhost_send_command(AwSdHostState *s)
642
+{
643
+ SDRequest request;
644
+ uint8_t resp[16];
645
+ int rlen;
646
+
647
+ /* Auto clear load flag */
648
+ s->command &= ~SD_CMDR_LOAD;
649
+
650
+ /* Clock change does not actually interact with the SD bus */
651
+ if (!(s->command & SD_CMDR_CLKCHANGE)) {
652
+
653
+ /* Prepare request */
654
+ request.cmd = s->command & SD_CMDR_CMDID_MASK;
655
+ request.arg = s->command_arg;
656
+
657
+ /* Send request to SD bus */
658
+ rlen = sdbus_do_command(&s->sdbus, &request, resp);
659
+ if (rlen < 0) {
660
+ goto error;
661
+ }
662
+
663
+ /* If the command has a response, store it in the response registers */
664
+ if ((s->command & SD_CMDR_RESPONSE)) {
665
+ if (rlen == 4 && !(s->command & SD_CMDR_RESPONSE_LONG)) {
666
+ s->response[0] = ldl_be_p(&resp[0]);
667
+ s->response[1] = s->response[2] = s->response[3] = 0;
668
+
669
+ } else if (rlen == 16 && (s->command & SD_CMDR_RESPONSE_LONG)) {
670
+ s->response[0] = ldl_be_p(&resp[12]);
671
+ s->response[1] = ldl_be_p(&resp[8]);
672
+ s->response[2] = ldl_be_p(&resp[4]);
673
+ s->response[3] = ldl_be_p(&resp[0]);
674
+ } else {
675
+ goto error;
676
+ }
677
+ }
678
+ }
679
+
680
+ /* Set interrupt status bits */
681
+ s->irq_status |= SD_RISR_CMD_COMPLETE;
682
+ return;
683
+
684
+error:
685
+ s->irq_status |= SD_RISR_NO_RESPONSE;
686
+}
687
+
688
+static void allwinner_sdhost_auto_stop(AwSdHostState *s)
689
+{
690
+ /*
691
+ * The stop command (CMD12) ensures the SD bus
692
+ * returns to the transfer state.
693
+ */
694
+ if ((s->command & SD_CMDR_AUTOSTOP) && (s->transfer_cnt == 0)) {
695
+ /* First save current command registers */
696
+ uint32_t saved_cmd = s->command;
697
+ uint32_t saved_arg = s->command_arg;
698
+
699
+ /* Prepare stop command (CMD12) */
700
+ s->command &= ~SD_CMDR_CMDID_MASK;
701
+ s->command |= 12; /* CMD12 */
702
+ s->command_arg = 0;
703
+
704
+ /* Put the command on SD bus */
705
+ allwinner_sdhost_send_command(s);
706
+
707
+ /* Restore command values */
708
+ s->command = saved_cmd;
709
+ s->command_arg = saved_arg;
710
+
711
+ /* Set IRQ status bit for automatic stop done */
712
+ s->irq_status |= SD_RISR_AUTOCMD_DONE;
713
+ }
714
+}
715
+
716
+static uint32_t allwinner_sdhost_process_desc(AwSdHostState *s,
717
+ hwaddr desc_addr,
718
+ TransferDescriptor *desc,
719
+ bool is_write, uint32_t max_bytes)
720
+{
721
+ AwSdHostClass *klass = AW_SDHOST_GET_CLASS(s);
722
+ uint32_t num_done = 0;
723
+ uint32_t num_bytes = max_bytes;
724
+ uint8_t buf[1024];
725
+
726
+ /* Read descriptor */
727
+ cpu_physical_memory_read(desc_addr, desc, sizeof(*desc));
728
+ if (desc->size == 0) {
729
+ desc->size = klass->max_desc_size;
730
+ } else if (desc->size > klass->max_desc_size) {
731
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA descriptor buffer size "
732
+ " is out-of-bounds: %" PRIu32 " > %zu",
733
+ __func__, desc->size, klass->max_desc_size);
734
+ desc->size = klass->max_desc_size;
735
+ }
736
+ if (desc->size < num_bytes) {
737
+ num_bytes = desc->size;
738
+ }
739
+
740
+ trace_allwinner_sdhost_process_desc(desc_addr, desc->size,
741
+ is_write, max_bytes);
742
+
743
+ while (num_done < num_bytes) {
744
+ /* Try to completely fill the local buffer */
745
+ uint32_t buf_bytes = num_bytes - num_done;
746
+ if (buf_bytes > sizeof(buf)) {
747
+ buf_bytes = sizeof(buf);
748
+ }
749
+
750
+ /* Write to SD bus */
751
+ if (is_write) {
752
+ cpu_physical_memory_read((desc->addr & DESC_SIZE_MASK) + num_done,
753
+ buf, buf_bytes);
754
+
755
+ for (uint32_t i = 0; i < buf_bytes; i++) {
756
+ sdbus_write_data(&s->sdbus, buf[i]);
757
+ }
758
+
759
+ /* Read from SD bus */
760
+ } else {
761
+ for (uint32_t i = 0; i < buf_bytes; i++) {
762
+ buf[i] = sdbus_read_data(&s->sdbus);
763
+ }
764
+ cpu_physical_memory_write((desc->addr & DESC_SIZE_MASK) + num_done,
765
+ buf, buf_bytes);
766
+ }
767
+ num_done += buf_bytes;
768
+ }
769
+
770
+ /* Clear hold flag and flush descriptor */
771
+ desc->status &= ~DESC_STATUS_HOLD;
772
+ cpu_physical_memory_write(desc_addr, desc, sizeof(*desc));
773
+
774
+ return num_done;
775
+}
776
+
777
+static void allwinner_sdhost_dma(AwSdHostState *s)
778
+{
779
+ TransferDescriptor desc;
780
+ hwaddr desc_addr = s->desc_base;
781
+ bool is_write = (s->command & SD_CMDR_WRITE);
782
+ uint32_t bytes_done = 0;
783
+
784
+ /* Check if DMA can be performed */
785
+ if (s->byte_count == 0 || s->block_size == 0 ||
786
+ !(s->global_ctl & SD_GCTL_DMA_ENB)) {
787
+ return;
788
+ }
789
+
790
+ /*
791
+ * For read operations, data must be available on the SD bus
792
+ * If not, it is an error and we should not act at all
793
+ */
794
+ if (!is_write && !sdbus_data_ready(&s->sdbus)) {
795
+ return;
796
+ }
797
+
798
+ /* Process the DMA descriptors until all data is copied */
799
+ while (s->byte_count > 0) {
800
+ bytes_done = allwinner_sdhost_process_desc(s, desc_addr, &desc,
801
+ is_write, s->byte_count);
802
+ allwinner_sdhost_update_transfer_cnt(s, bytes_done);
803
+
804
+ if (bytes_done <= s->byte_count) {
805
+ s->byte_count -= bytes_done;
806
+ } else {
807
+ s->byte_count = 0;
808
+ }
809
+
810
+ if (desc.status & DESC_STATUS_LAST) {
811
+ break;
812
+ } else {
813
+ desc_addr = desc.next;
814
+ }
815
+ }
816
+
817
+ /* Raise IRQ to signal DMA is completed */
818
+ s->irq_status |= SD_RISR_DATA_COMPLETE | SD_RISR_SDIO_INTR;
819
+
820
+ /* Update DMAC bits */
821
+ s->dmac_status |= SD_IDST_INT_SUMMARY;
822
+
823
+ if (is_write) {
824
+ s->dmac_status |= SD_IDST_TRANSMIT_IRQ;
825
+ } else {
826
+ s->dmac_status |= SD_IDST_RECEIVE_IRQ;
827
+ }
828
+}
829
+
830
+static uint64_t allwinner_sdhost_read(void *opaque, hwaddr offset,
831
+ unsigned size)
832
+{
833
+ AwSdHostState *s = AW_SDHOST(opaque);
834
+ uint32_t res = 0;
835
+
836
+ switch (offset) {
837
+ case REG_SD_GCTL: /* Global Control */
838
+ res = s->global_ctl;
839
+ break;
840
+ case REG_SD_CKCR: /* Clock Control */
841
+ res = s->clock_ctl;
842
+ break;
843
+ case REG_SD_TMOR: /* Timeout */
844
+ res = s->timeout;
845
+ break;
846
+ case REG_SD_BWDR: /* Bus Width */
847
+ res = s->bus_width;
848
+ break;
849
+ case REG_SD_BKSR: /* Block Size */
850
+ res = s->block_size;
851
+ break;
852
+ case REG_SD_BYCR: /* Byte Count */
853
+ res = s->byte_count;
854
+ break;
855
+ case REG_SD_CMDR: /* Command */
856
+ res = s->command;
857
+ break;
858
+ case REG_SD_CAGR: /* Command Argument */
859
+ res = s->command_arg;
860
+ break;
861
+ case REG_SD_RESP0: /* Response Zero */
862
+ res = s->response[0];
863
+ break;
864
+ case REG_SD_RESP1: /* Response One */
865
+ res = s->response[1];
866
+ break;
867
+ case REG_SD_RESP2: /* Response Two */
868
+ res = s->response[2];
869
+ break;
870
+ case REG_SD_RESP3: /* Response Three */
871
+ res = s->response[3];
872
+ break;
873
+ case REG_SD_IMKR: /* Interrupt Mask */
874
+ res = s->irq_mask;
875
+ break;
876
+ case REG_SD_MISR: /* Masked Interrupt Status */
877
+ res = s->irq_status & s->irq_mask;
878
+ break;
879
+ case REG_SD_RISR: /* Raw Interrupt Status */
880
+ res = s->irq_status;
881
+ break;
882
+ case REG_SD_STAR: /* Status */
883
+ res = s->status;
884
+ break;
885
+ case REG_SD_FWLR: /* FIFO Water Level */
886
+ res = s->fifo_wlevel;
887
+ break;
888
+ case REG_SD_FUNS: /* FIFO Function Select */
889
+ res = s->fifo_func_sel;
890
+ break;
891
+ case REG_SD_DBGC: /* Debug Enable */
892
+ res = s->debug_enable;
893
+ break;
894
+ case REG_SD_A12A: /* Auto command 12 argument */
895
+ res = s->auto12_arg;
896
+ break;
897
+ case REG_SD_NTSR: /* SD NewTiming Set */
898
+ res = s->newtiming_set;
899
+ break;
900
+ case REG_SD_SDBG: /* SD newTiming Set Debug */
901
+ res = s->newtiming_debug;
902
+ break;
903
+ case REG_SD_HWRST: /* Hardware Reset Register */
904
+ res = s->hardware_rst;
905
+ break;
906
+ case REG_SD_DMAC: /* Internal DMA Controller Control */
907
+ res = s->dmac;
908
+ break;
909
+ case REG_SD_DLBA: /* Descriptor List Base Address */
910
+ res = s->desc_base;
911
+ break;
912
+ case REG_SD_IDST: /* Internal DMA Controller Status */
913
+ res = s->dmac_status;
914
+ break;
915
+ case REG_SD_IDIE: /* Internal DMA Controller Interrupt Enable */
916
+ res = s->dmac_irq;
917
+ break;
918
+ case REG_SD_THLDC: /* Card Threshold Control */
919
+ res = s->card_threshold;
920
+ break;
921
+ case REG_SD_DSBD: /* eMMC DDR Start Bit Detection Control */
922
+ res = s->startbit_detect;
923
+ break;
924
+ case REG_SD_RES_CRC: /* Response CRC from card/eMMC */
925
+ res = s->response_crc;
926
+ break;
927
+ case REG_SD_DATA7_CRC: /* CRC Data 7 from card/eMMC */
928
+ case REG_SD_DATA6_CRC: /* CRC Data 6 from card/eMMC */
929
+ case REG_SD_DATA5_CRC: /* CRC Data 5 from card/eMMC */
930
+ case REG_SD_DATA4_CRC: /* CRC Data 4 from card/eMMC */
931
+ case REG_SD_DATA3_CRC: /* CRC Data 3 from card/eMMC */
932
+ case REG_SD_DATA2_CRC: /* CRC Data 2 from card/eMMC */
933
+ case REG_SD_DATA1_CRC: /* CRC Data 1 from card/eMMC */
934
+ case REG_SD_DATA0_CRC: /* CRC Data 0 from card/eMMC */
935
+ res = s->data_crc[((offset - REG_SD_DATA7_CRC) / sizeof(uint32_t))];
936
+ break;
937
+ case REG_SD_CRC_STA: /* CRC status from card/eMMC in write operation */
938
+ res = s->status_crc;
939
+ break;
940
+ case REG_SD_FIFO: /* Read/Write FIFO */
941
+ if (sdbus_data_ready(&s->sdbus)) {
942
+ res = sdbus_read_data(&s->sdbus);
943
+ res |= sdbus_read_data(&s->sdbus) << 8;
944
+ res |= sdbus_read_data(&s->sdbus) << 16;
945
+ res |= sdbus_read_data(&s->sdbus) << 24;
946
+ allwinner_sdhost_update_transfer_cnt(s, sizeof(uint32_t));
947
+ allwinner_sdhost_auto_stop(s);
948
+ allwinner_sdhost_update_irq(s);
949
+ } else {
950
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: no data ready on SD bus\n",
951
+ __func__);
952
+ }
953
+ break;
954
+ default:
955
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset %"
956
+ HWADDR_PRIx"\n", __func__, offset);
957
+ res = 0;
958
+ break;
959
+ }
960
+
961
+ trace_allwinner_sdhost_read(offset, res, size);
962
+ return res;
963
+}
964
+
965
+static void allwinner_sdhost_write(void *opaque, hwaddr offset,
966
+ uint64_t value, unsigned size)
967
+{
968
+ AwSdHostState *s = AW_SDHOST(opaque);
969
+
970
+ trace_allwinner_sdhost_write(offset, value, size);
971
+
972
+ switch (offset) {
973
+ case REG_SD_GCTL: /* Global Control */
974
+ s->global_ctl = value;
975
+ s->global_ctl &= ~(SD_GCTL_DMA_RST | SD_GCTL_FIFO_RST |
976
+ SD_GCTL_SOFT_RST);
977
+ allwinner_sdhost_update_irq(s);
978
+ break;
979
+ case REG_SD_CKCR: /* Clock Control */
980
+ s->clock_ctl = value;
981
+ break;
982
+ case REG_SD_TMOR: /* Timeout */
983
+ s->timeout = value;
984
+ break;
985
+ case REG_SD_BWDR: /* Bus Width */
986
+ s->bus_width = value;
987
+ break;
988
+ case REG_SD_BKSR: /* Block Size */
989
+ s->block_size = value;
990
+ break;
991
+ case REG_SD_BYCR: /* Byte Count */
992
+ s->byte_count = value;
993
+ s->transfer_cnt = value;
994
+ break;
995
+ case REG_SD_CMDR: /* Command */
996
+ s->command = value;
997
+ if (value & SD_CMDR_LOAD) {
998
+ allwinner_sdhost_send_command(s);
999
+ allwinner_sdhost_dma(s);
1000
+ allwinner_sdhost_auto_stop(s);
1001
+ }
1002
+ allwinner_sdhost_update_irq(s);
1003
+ break;
1004
+ case REG_SD_CAGR: /* Command Argument */
1005
+ s->command_arg = value;
1006
+ break;
1007
+ case REG_SD_RESP0: /* Response Zero */
1008
+ s->response[0] = value;
1009
+ break;
1010
+ case REG_SD_RESP1: /* Response One */
1011
+ s->response[1] = value;
1012
+ break;
1013
+ case REG_SD_RESP2: /* Response Two */
1014
+ s->response[2] = value;
1015
+ break;
1016
+ case REG_SD_RESP3: /* Response Three */
1017
+ s->response[3] = value;
1018
+ break;
1019
+ case REG_SD_IMKR: /* Interrupt Mask */
1020
+ s->irq_mask = value;
1021
+ allwinner_sdhost_update_irq(s);
1022
+ break;
1023
+ case REG_SD_MISR: /* Masked Interrupt Status */
1024
+ case REG_SD_RISR: /* Raw Interrupt Status */
1025
+ s->irq_status &= ~value;
1026
+ allwinner_sdhost_update_irq(s);
1027
+ break;
1028
+ case REG_SD_STAR: /* Status */
1029
+ s->status &= ~value;
1030
+ allwinner_sdhost_update_irq(s);
1031
+ break;
1032
+ case REG_SD_FWLR: /* FIFO Water Level */
1033
+ s->fifo_wlevel = value;
1034
+ break;
1035
+ case REG_SD_FUNS: /* FIFO Function Select */
1036
+ s->fifo_func_sel = value;
1037
+ break;
1038
+ case REG_SD_DBGC: /* Debug Enable */
1039
+ s->debug_enable = value;
1040
+ break;
1041
+ case REG_SD_A12A: /* Auto command 12 argument */
1042
+ s->auto12_arg = value;
1043
+ break;
1044
+ case REG_SD_NTSR: /* SD NewTiming Set */
1045
+ s->newtiming_set = value;
1046
+ break;
1047
+ case REG_SD_SDBG: /* SD newTiming Set Debug */
1048
+ s->newtiming_debug = value;
1049
+ break;
1050
+ case REG_SD_HWRST: /* Hardware Reset Register */
1051
+ s->hardware_rst = value;
1052
+ break;
1053
+ case REG_SD_DMAC: /* Internal DMA Controller Control */
1054
+ s->dmac = value;
1055
+ allwinner_sdhost_update_irq(s);
1056
+ break;
1057
+ case REG_SD_DLBA: /* Descriptor List Base Address */
1058
+ s->desc_base = value;
1059
+ break;
1060
+ case REG_SD_IDST: /* Internal DMA Controller Status */
1061
+ s->dmac_status &= (~SD_IDST_WR_MASK) | (~value & SD_IDST_WR_MASK);
1062
+ allwinner_sdhost_update_irq(s);
1063
+ break;
1064
+ case REG_SD_IDIE: /* Internal DMA Controller Interrupt Enable */
1065
+ s->dmac_irq = value;
1066
+ allwinner_sdhost_update_irq(s);
1067
+ break;
1068
+ case REG_SD_THLDC: /* Card Threshold Control */
1069
+ s->card_threshold = value;
1070
+ break;
1071
+ case REG_SD_DSBD: /* eMMC DDR Start Bit Detection Control */
1072
+ s->startbit_detect = value;
1073
+ break;
1074
+ case REG_SD_FIFO: /* Read/Write FIFO */
1075
+ sdbus_write_data(&s->sdbus, value & 0xff);
1076
+ sdbus_write_data(&s->sdbus, (value >> 8) & 0xff);
1077
+ sdbus_write_data(&s->sdbus, (value >> 16) & 0xff);
1078
+ sdbus_write_data(&s->sdbus, (value >> 24) & 0xff);
1079
+ allwinner_sdhost_update_transfer_cnt(s, sizeof(uint32_t));
1080
+ allwinner_sdhost_auto_stop(s);
1081
+ allwinner_sdhost_update_irq(s);
1082
+ break;
1083
+ case REG_SD_RES_CRC: /* Response CRC from card/eMMC */
1084
+ case REG_SD_DATA7_CRC: /* CRC Data 7 from card/eMMC */
1085
+ case REG_SD_DATA6_CRC: /* CRC Data 6 from card/eMMC */
1086
+ case REG_SD_DATA5_CRC: /* CRC Data 5 from card/eMMC */
1087
+ case REG_SD_DATA4_CRC: /* CRC Data 4 from card/eMMC */
1088
+ case REG_SD_DATA3_CRC: /* CRC Data 3 from card/eMMC */
1089
+ case REG_SD_DATA2_CRC: /* CRC Data 2 from card/eMMC */
1090
+ case REG_SD_DATA1_CRC: /* CRC Data 1 from card/eMMC */
1091
+ case REG_SD_DATA0_CRC: /* CRC Data 0 from card/eMMC */
1092
+ case REG_SD_CRC_STA: /* CRC status from card/eMMC in write operation */
1093
+ break;
1094
+ default:
1095
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset %"
1096
+ HWADDR_PRIx"\n", __func__, offset);
1097
+ break;
1098
+ }
1099
+}
1100
+
1101
+static const MemoryRegionOps allwinner_sdhost_ops = {
1102
+ .read = allwinner_sdhost_read,
1103
+ .write = allwinner_sdhost_write,
1104
+ .endianness = DEVICE_NATIVE_ENDIAN,
1105
+ .valid = {
1106
+ .min_access_size = 4,
1107
+ .max_access_size = 4,
1108
+ },
1109
+ .impl.min_access_size = 4,
1110
+};
1111
+
1112
+static const VMStateDescription vmstate_allwinner_sdhost = {
1113
+ .name = "allwinner-sdhost",
1114
+ .version_id = 1,
1115
+ .minimum_version_id = 1,
1116
+ .fields = (VMStateField[]) {
1117
+ VMSTATE_UINT32(global_ctl, AwSdHostState),
1118
+ VMSTATE_UINT32(clock_ctl, AwSdHostState),
1119
+ VMSTATE_UINT32(timeout, AwSdHostState),
1120
+ VMSTATE_UINT32(bus_width, AwSdHostState),
1121
+ VMSTATE_UINT32(block_size, AwSdHostState),
1122
+ VMSTATE_UINT32(byte_count, AwSdHostState),
1123
+ VMSTATE_UINT32(transfer_cnt, AwSdHostState),
1124
+ VMSTATE_UINT32(command, AwSdHostState),
1125
+ VMSTATE_UINT32(command_arg, AwSdHostState),
1126
+ VMSTATE_UINT32_ARRAY(response, AwSdHostState, 4),
1127
+ VMSTATE_UINT32(irq_mask, AwSdHostState),
1128
+ VMSTATE_UINT32(irq_status, AwSdHostState),
1129
+ VMSTATE_UINT32(status, AwSdHostState),
1130
+ VMSTATE_UINT32(fifo_wlevel, AwSdHostState),
1131
+ VMSTATE_UINT32(fifo_func_sel, AwSdHostState),
1132
+ VMSTATE_UINT32(debug_enable, AwSdHostState),
1133
+ VMSTATE_UINT32(auto12_arg, AwSdHostState),
1134
+ VMSTATE_UINT32(newtiming_set, AwSdHostState),
1135
+ VMSTATE_UINT32(newtiming_debug, AwSdHostState),
1136
+ VMSTATE_UINT32(hardware_rst, AwSdHostState),
1137
+ VMSTATE_UINT32(dmac, AwSdHostState),
1138
+ VMSTATE_UINT32(desc_base, AwSdHostState),
1139
+ VMSTATE_UINT32(dmac_status, AwSdHostState),
1140
+ VMSTATE_UINT32(dmac_irq, AwSdHostState),
1141
+ VMSTATE_UINT32(card_threshold, AwSdHostState),
1142
+ VMSTATE_UINT32(startbit_detect, AwSdHostState),
1143
+ VMSTATE_UINT32(response_crc, AwSdHostState),
1144
+ VMSTATE_UINT32_ARRAY(data_crc, AwSdHostState, 8),
1145
+ VMSTATE_UINT32(status_crc, AwSdHostState),
1146
+ VMSTATE_END_OF_LIST()
1147
+ }
1148
+};
1149
+
1150
+static void allwinner_sdhost_init(Object *obj)
1151
+{
1152
+ AwSdHostState *s = AW_SDHOST(obj);
1153
+
1154
+ qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
1155
+ TYPE_AW_SDHOST_BUS, DEVICE(s), "sd-bus");
1156
+
1157
+ memory_region_init_io(&s->iomem, obj, &allwinner_sdhost_ops, s,
1158
+ TYPE_AW_SDHOST, 4 * KiB);
1159
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
1160
+ sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
1161
+}
1162
+
1163
+static void allwinner_sdhost_reset(DeviceState *dev)
1164
+{
1165
+ AwSdHostState *s = AW_SDHOST(dev);
1166
+
1167
+ s->global_ctl = REG_SD_GCTL_RST;
1168
+ s->clock_ctl = REG_SD_CKCR_RST;
1169
+ s->timeout = REG_SD_TMOR_RST;
1170
+ s->bus_width = REG_SD_BWDR_RST;
1171
+ s->block_size = REG_SD_BKSR_RST;
1172
+ s->byte_count = REG_SD_BYCR_RST;
1173
+ s->transfer_cnt = 0;
1174
+
1175
+ s->command = REG_SD_CMDR_RST;
1176
+ s->command_arg = REG_SD_CAGR_RST;
1177
+
1178
+ for (int i = 0; i < ARRAY_SIZE(s->response); i++) {
1179
+ s->response[i] = REG_SD_RESP_RST;
1180
+ }
1181
+
1182
+ s->irq_mask = REG_SD_IMKR_RST;
1183
+ s->irq_status = REG_SD_RISR_RST;
1184
+ s->status = REG_SD_STAR_RST;
1185
+
1186
+ s->fifo_wlevel = REG_SD_FWLR_RST;
1187
+ s->fifo_func_sel = REG_SD_FUNS_RST;
1188
+ s->debug_enable = REG_SD_DBGC_RST;
1189
+ s->auto12_arg = REG_SD_A12A_RST;
1190
+ s->newtiming_set = REG_SD_NTSR_RST;
1191
+ s->newtiming_debug = REG_SD_SDBG_RST;
1192
+ s->hardware_rst = REG_SD_HWRST_RST;
1193
+ s->dmac = REG_SD_DMAC_RST;
1194
+ s->desc_base = REG_SD_DLBA_RST;
1195
+ s->dmac_status = REG_SD_IDST_RST;
1196
+ s->dmac_irq = REG_SD_IDIE_RST;
1197
+ s->card_threshold = REG_SD_THLDC_RST;
1198
+ s->startbit_detect = REG_SD_DSBD_RST;
1199
+ s->response_crc = REG_SD_RES_CRC_RST;
1200
+
1201
+ for (int i = 0; i < ARRAY_SIZE(s->data_crc); i++) {
1202
+ s->data_crc[i] = REG_SD_DATA_CRC_RST;
1203
+ }
1204
+
1205
+ s->status_crc = REG_SD_CRC_STA_RST;
1206
+}
1207
+
1208
+static void allwinner_sdhost_bus_class_init(ObjectClass *klass, void *data)
1209
+{
1210
+ SDBusClass *sbc = SD_BUS_CLASS(klass);
1211
+
1212
+ sbc->set_inserted = allwinner_sdhost_set_inserted;
1213
+}
1214
+
1215
+static void allwinner_sdhost_class_init(ObjectClass *klass, void *data)
1216
+{
1217
+ DeviceClass *dc = DEVICE_CLASS(klass);
1218
+
1219
+ dc->reset = allwinner_sdhost_reset;
1220
+ dc->vmsd = &vmstate_allwinner_sdhost;
1221
+}
1222
+
1223
+static void allwinner_sdhost_sun4i_class_init(ObjectClass *klass, void *data)
1224
+{
1225
+ AwSdHostClass *sc = AW_SDHOST_CLASS(klass);
1226
+ sc->max_desc_size = 8 * KiB;
1227
+}
1228
+
1229
+static void allwinner_sdhost_sun5i_class_init(ObjectClass *klass, void *data)
1230
+{
1231
+ AwSdHostClass *sc = AW_SDHOST_CLASS(klass);
1232
+ sc->max_desc_size = 64 * KiB;
1233
+}
1234
+
1235
+static TypeInfo allwinner_sdhost_info = {
1236
+ .name = TYPE_AW_SDHOST,
1237
+ .parent = TYPE_SYS_BUS_DEVICE,
1238
+ .instance_init = allwinner_sdhost_init,
1239
+ .instance_size = sizeof(AwSdHostState),
1240
+ .class_init = allwinner_sdhost_class_init,
1241
+ .class_size = sizeof(AwSdHostClass),
1242
+ .abstract = true,
1243
+};
1244
+
1245
+static const TypeInfo allwinner_sdhost_sun4i_info = {
1246
+ .name = TYPE_AW_SDHOST_SUN4I,
1247
+ .parent = TYPE_AW_SDHOST,
1248
+ .class_init = allwinner_sdhost_sun4i_class_init,
1249
+};
1250
+
1251
+static const TypeInfo allwinner_sdhost_sun5i_info = {
1252
+ .name = TYPE_AW_SDHOST_SUN5I,
1253
+ .parent = TYPE_AW_SDHOST,
1254
+ .class_init = allwinner_sdhost_sun5i_class_init,
1255
+};
1256
+
1257
+static const TypeInfo allwinner_sdhost_bus_info = {
1258
+ .name = TYPE_AW_SDHOST_BUS,
1259
+ .parent = TYPE_SD_BUS,
1260
+ .instance_size = sizeof(SDBus),
1261
+ .class_init = allwinner_sdhost_bus_class_init,
1262
+};
1263
+
1264
+static void allwinner_sdhost_register_types(void)
1265
+{
1266
+ type_register_static(&allwinner_sdhost_info);
1267
+ type_register_static(&allwinner_sdhost_sun4i_info);
1268
+ type_register_static(&allwinner_sdhost_sun5i_info);
1269
+ type_register_static(&allwinner_sdhost_bus_info);
1270
+}
1271
+
1272
+type_init(allwinner_sdhost_register_types)
1273
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
197
index XXXXXXX..XXXXXXX 100644
1274
index XXXXXXX..XXXXXXX 100644
198
--- a/hw/ppc/pnv_psi.c
1275
--- a/hw/arm/Kconfig
199
+++ b/hw/ppc/pnv_psi.c
1276
+++ b/hw/arm/Kconfig
200
@@ -XXX,XX +XXX,XX @@ static void pnv_psi_reset(DeviceState *dev)
1277
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_H3
201
1278
select UNIMP
202
static void pnv_psi_reset_handler(void *dev)
1279
select USB_OHCI
203
{
1280
select USB_EHCI_SYSBUS
204
- device_reset(DEVICE(dev));
1281
+ select SD
205
+ device_legacy_reset(DEVICE(dev));
1282
206
}
1283
config RASPI
207
1284
bool
208
static void pnv_psi_realize(DeviceState *dev, Error **errp)
1285
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
209
@@ -XXX,XX +XXX,XX @@ static void pnv_psi_p9_mmio_write(void *opaque, hwaddr addr,
210
break;
211
case PSIHB9_INTERRUPT_CONTROL:
212
if (val & PSIHB9_IRQ_RESET) {
213
- device_reset(DEVICE(&psi9->source));
214
+ device_legacy_reset(DEVICE(&psi9->source));
215
}
216
psi->regs[reg] = val;
217
break;
218
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
219
index XXXXXXX..XXXXXXX 100644
1286
index XXXXXXX..XXXXXXX 100644
220
--- a/hw/ppc/spapr_pci.c
1287
--- a/hw/sd/trace-events
221
+++ b/hw/ppc/spapr_pci.c
1288
+++ b/hw/sd/trace-events
222
@@ -XXX,XX +XXX,XX @@ static int spapr_phb_children_reset(Object *child, void *opaque)
1289
@@ -XXX,XX +XXX,XX @@
223
DeviceState *dev = (DeviceState *) object_dynamic_cast(child, TYPE_DEVICE);
1290
# See docs/devel/tracing.txt for syntax documentation.
224
1291
225
if (dev) {
1292
+# allwinner-sdhost.c
226
- device_reset(dev);
1293
+allwinner_sdhost_set_inserted(bool inserted) "inserted %u"
227
+ device_legacy_reset(dev);
1294
+allwinner_sdhost_process_desc(uint64_t desc_addr, uint32_t desc_size, bool is_write, uint32_t max_bytes) "desc_addr 0x%" PRIx64 " desc_size %" PRIu32 " is_write %u max_bytes %" PRIu32
228
}
1295
+allwinner_sdhost_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
229
1296
+allwinner_sdhost_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
230
return 0;
1297
+allwinner_sdhost_update_irq(uint32_t irq) "IRQ bits 0x%" PRIx32
231
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
1298
+
232
index XXXXXXX..XXXXXXX 100644
1299
# bcm2835_sdhost.c
233
--- a/hw/ppc/spapr_vio.c
1300
bcm2835_sdhost_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
234
+++ b/hw/ppc/spapr_vio.c
1301
bcm2835_sdhost_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
235
@@ -XXX,XX +XXX,XX @@ int spapr_vio_send_crq(SpaprVioDevice *dev, uint8_t *crq)
236
static void spapr_vio_quiesce_one(SpaprVioDevice *dev)
237
{
238
if (dev->tcet) {
239
- device_reset(DEVICE(dev->tcet));
240
+ device_legacy_reset(DEVICE(dev->tcet));
241
}
242
free_crq(dev);
243
}
244
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
245
index XXXXXXX..XXXXXXX 100644
246
--- a/hw/s390x/s390-pci-inst.c
247
+++ b/hw/s390x/s390-pci-inst.c
248
@@ -XXX,XX +XXX,XX @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra)
249
stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_FHOP);
250
goto out;
251
}
252
- device_reset(DEVICE(pbdev));
253
+ device_legacy_reset(DEVICE(pbdev));
254
pbdev->fh &= ~FH_MASK_ENABLE;
255
pbdev->state = ZPCI_FS_DISABLED;
256
stl_p(&ressetpci->fh, pbdev->fh);
257
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
258
index XXXXXXX..XXXXXXX 100644
259
--- a/hw/scsi/vmw_pvscsi.c
260
+++ b/hw/scsi/vmw_pvscsi.c
261
@@ -XXX,XX +XXX,XX @@ pvscsi_on_cmd_reset_device(PVSCSIState *s)
262
263
if (sdev != NULL) {
264
s->resetting++;
265
- device_reset(&sdev->qdev);
266
+ device_legacy_reset(&sdev->qdev);
267
s->resetting--;
268
return PVSCSI_COMMAND_PROCESSING_SUCCEEDED;
269
}
270
diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c
271
index XXXXXXX..XXXXXXX 100644
272
--- a/hw/sd/omap_mmc.c
273
+++ b/hw/sd/omap_mmc.c
274
@@ -XXX,XX +XXX,XX @@ void omap_mmc_reset(struct omap_mmc_s *host)
275
* into any bus, and we must reset it manually. When omap_mmc is
276
* QOMified this must move into the QOM reset function.
277
*/
278
- device_reset(DEVICE(host->card));
279
+ device_legacy_reset(DEVICE(host->card));
280
}
281
282
static uint64_t omap_mmc_read(void *opaque, hwaddr offset,
283
diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
284
index XXXXXXX..XXXXXXX 100644
285
--- a/hw/sd/pl181.c
286
+++ b/hw/sd/pl181.c
287
@@ -XXX,XX +XXX,XX @@ static void pl181_reset(DeviceState *d)
288
/* Since we're still using the legacy SD API the card is not plugged
289
* into any bus, and we must reset it manually.
290
*/
291
- device_reset(DEVICE(s->card));
292
+ device_legacy_reset(DEVICE(s->card));
293
}
294
295
static void pl181_init(Object *obj)
296
--
1302
--
297
2.20.1
1303
2.20.1
298
1304
299
1305
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Adds trace events to reset procedure and when updating the parent
3
The Allwinner Sun8i System on Chip family includes an Ethernet MAC (EMAC)
4
bus of a device.
4
which provides 10M/100M/1000M Ethernet connectivity. This commit
5
adds support for the Allwinner EMAC from the Sun8i family (H2+, H3, A33, etc),
6
including emulation for the following functionality:
5
7
6
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
8
* DMA transfers
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
* MII interface
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
* Transmit CRC calculation
9
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
11
10
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
11
Message-id: 20200123132823.1117486-3-damien.hedde@greensocs.com
13
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
14
Message-id: 20200311221854.30370-10-nieklinnenbank@gmail.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
16
---
14
hw/core/qdev.c | 29 ++++++++++++++++++++++++++---
17
hw/net/Makefile.objs | 1 +
15
hw/core/trace-events | 9 +++++++++
18
include/hw/arm/allwinner-h3.h | 3 +
16
2 files changed, 35 insertions(+), 3 deletions(-)
19
include/hw/net/allwinner-sun8i-emac.h | 99 +++
20
hw/arm/allwinner-h3.c | 16 +-
21
hw/arm/orangepi.c | 3 +
22
hw/net/allwinner-sun8i-emac.c | 871 ++++++++++++++++++++++++++
23
hw/arm/Kconfig | 1 +
24
hw/net/Kconfig | 3 +
25
hw/net/trace-events | 10 +
26
9 files changed, 1006 insertions(+), 1 deletion(-)
27
create mode 100644 include/hw/net/allwinner-sun8i-emac.h
28
create mode 100644 hw/net/allwinner-sun8i-emac.c
17
29
18
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
30
diff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs
19
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/core/qdev.c
32
--- a/hw/net/Makefile.objs
21
+++ b/hw/core/qdev.c
33
+++ b/hw/net/Makefile.objs
34
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_XGMAC) += xgmac.o
35
common-obj-$(CONFIG_MIPSNET) += mipsnet.o
36
common-obj-$(CONFIG_XILINX_AXI) += xilinx_axienet.o
37
common-obj-$(CONFIG_ALLWINNER_EMAC) += allwinner_emac.o
38
+common-obj-$(CONFIG_ALLWINNER_SUN8I_EMAC) += allwinner-sun8i-emac.o
39
common-obj-$(CONFIG_IMX_FEC) += imx_fec.o
40
41
common-obj-$(CONFIG_CADENCE) += cadence_gem.o
42
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
43
index XXXXXXX..XXXXXXX 100644
44
--- a/include/hw/arm/allwinner-h3.h
45
+++ b/include/hw/arm/allwinner-h3.h
22
@@ -XXX,XX +XXX,XX @@
46
@@ -XXX,XX +XXX,XX @@
23
#include "hw/boards.h"
47
#include "hw/misc/allwinner-h3-sysctrl.h"
24
#include "hw/sysbus.h"
48
#include "hw/misc/allwinner-sid.h"
25
#include "migration/vmstate.h"
49
#include "hw/sd/allwinner-sdhost.h"
50
+#include "hw/net/allwinner-sun8i-emac.h"
51
#include "target/arm/cpu.h"
52
53
/**
54
@@ -XXX,XX +XXX,XX @@ enum {
55
AW_H3_UART1,
56
AW_H3_UART2,
57
AW_H3_UART3,
58
+ AW_H3_EMAC,
59
AW_H3_GIC_DIST,
60
AW_H3_GIC_CPU,
61
AW_H3_GIC_HYP,
62
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
63
AwH3SysCtrlState sysctrl;
64
AwSidState sid;
65
AwSdHostState mmc0;
66
+ AwSun8iEmacState emac;
67
GICState gic;
68
MemoryRegion sram_a1;
69
MemoryRegion sram_a2;
70
diff --git a/include/hw/net/allwinner-sun8i-emac.h b/include/hw/net/allwinner-sun8i-emac.h
71
new file mode 100644
72
index XXXXXXX..XXXXXXX
73
--- /dev/null
74
+++ b/include/hw/net/allwinner-sun8i-emac.h
75
@@ -XXX,XX +XXX,XX @@
76
+/*
77
+ * Allwinner Sun8i Ethernet MAC emulation
78
+ *
79
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
80
+ *
81
+ * This program is free software: you can redistribute it and/or modify
82
+ * it under the terms of the GNU General Public License as published by
83
+ * the Free Software Foundation, either version 2 of the License, or
84
+ * (at your option) any later version.
85
+ *
86
+ * This program is distributed in the hope that it will be useful,
87
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
88
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
89
+ * GNU General Public License for more details.
90
+ *
91
+ * You should have received a copy of the GNU General Public License
92
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
93
+ */
94
+
95
+#ifndef HW_NET_ALLWINNER_SUN8I_EMAC_H
96
+#define HW_NET_ALLWINNER_SUN8I_EMAC_H
97
+
98
+#include "qom/object.h"
99
+#include "net/net.h"
100
+#include "hw/sysbus.h"
101
+
102
+/**
103
+ * Object model
104
+ * @{
105
+ */
106
+
107
+#define TYPE_AW_SUN8I_EMAC "allwinner-sun8i-emac"
108
+#define AW_SUN8I_EMAC(obj) \
109
+ OBJECT_CHECK(AwSun8iEmacState, (obj), TYPE_AW_SUN8I_EMAC)
110
+
111
+/** @} */
112
+
113
+/**
114
+ * Allwinner Sun8i EMAC object instance state
115
+ */
116
+typedef struct AwSun8iEmacState {
117
+ /*< private >*/
118
+ SysBusDevice parent_obj;
119
+ /*< public >*/
120
+
121
+ /** Maps I/O registers in physical memory */
122
+ MemoryRegion iomem;
123
+
124
+ /** Interrupt output signal to notify CPU */
125
+ qemu_irq irq;
126
+
127
+ /** Generic Network Interface Controller (NIC) for networking API */
128
+ NICState *nic;
129
+
130
+ /** Generic Network Interface Controller (NIC) configuration */
131
+ NICConf conf;
132
+
133
+ /**
134
+ * @name Media Independent Interface (MII)
135
+ * @{
136
+ */
137
+
138
+ uint8_t mii_phy_addr; /**< PHY address */
139
+ uint32_t mii_cr; /**< Control */
140
+ uint32_t mii_st; /**< Status */
141
+ uint32_t mii_adv; /**< Advertised Abilities */
142
+
143
+ /** @} */
144
+
145
+ /**
146
+ * @name Hardware Registers
147
+ * @{
148
+ */
149
+
150
+ uint32_t basic_ctl0; /**< Basic Control 0 */
151
+ uint32_t basic_ctl1; /**< Basic Control 1 */
152
+ uint32_t int_en; /**< Interrupt Enable */
153
+ uint32_t int_sta; /**< Interrupt Status */
154
+ uint32_t frm_flt; /**< Receive Frame Filter */
155
+
156
+ uint32_t rx_ctl0; /**< Receive Control 0 */
157
+ uint32_t rx_ctl1; /**< Receive Control 1 */
158
+ uint32_t rx_desc_head; /**< Receive Descriptor List Address */
159
+ uint32_t rx_desc_curr; /**< Current Receive Descriptor Address */
160
+
161
+ uint32_t tx_ctl0; /**< Transmit Control 0 */
162
+ uint32_t tx_ctl1; /**< Transmit Control 1 */
163
+ uint32_t tx_desc_head; /**< Transmit Descriptor List Address */
164
+ uint32_t tx_desc_curr; /**< Current Transmit Descriptor Address */
165
+ uint32_t tx_flowctl; /**< Transmit Flow Control */
166
+
167
+ uint32_t mii_cmd; /**< Management Interface Command */
168
+ uint32_t mii_data; /**< Management Interface Data */
169
+
170
+ /** @} */
171
+
172
+} AwSun8iEmacState;
173
+
174
+#endif /* HW_NET_ALLWINNER_SUN8I_H */
175
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
176
index XXXXXXX..XXXXXXX 100644
177
--- a/hw/arm/allwinner-h3.c
178
+++ b/hw/arm/allwinner-h3.c
179
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
180
[AW_H3_UART1] = 0x01c28400,
181
[AW_H3_UART2] = 0x01c28800,
182
[AW_H3_UART3] = 0x01c28c00,
183
+ [AW_H3_EMAC] = 0x01c30000,
184
[AW_H3_GIC_DIST] = 0x01c81000,
185
[AW_H3_GIC_CPU] = 0x01c82000,
186
[AW_H3_GIC_HYP] = 0x01c84000,
187
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
188
{ "twi1", 0x01c2b000, 1 * KiB },
189
{ "twi2", 0x01c2b400, 1 * KiB },
190
{ "scr", 0x01c2c400, 1 * KiB },
191
- { "emac", 0x01c30000, 64 * KiB },
192
{ "gpu", 0x01c40000, 64 * KiB },
193
{ "hstmr", 0x01c60000, 4 * KiB },
194
{ "dramcom", 0x01c62000, 4 * KiB },
195
@@ -XXX,XX +XXX,XX @@ enum {
196
AW_H3_GIC_SPI_OHCI2 = 77,
197
AW_H3_GIC_SPI_EHCI3 = 78,
198
AW_H3_GIC_SPI_OHCI3 = 79,
199
+ AW_H3_GIC_SPI_EMAC = 82
200
};
201
202
/* Allwinner H3 general constants */
203
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
204
205
sysbus_init_child_obj(obj, "mmc0", &s->mmc0, sizeof(s->mmc0),
206
TYPE_AW_SDHOST_SUN5I);
207
+
208
+ sysbus_init_child_obj(obj, "emac", &s->emac, sizeof(s->emac),
209
+ TYPE_AW_SUN8I_EMAC);
210
}
211
212
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
213
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
214
object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->mmc0),
215
"sd-bus", &error_abort);
216
217
+ /* EMAC */
218
+ if (nd_table[0].used) {
219
+ qemu_check_nic_model(&nd_table[0], TYPE_AW_SUN8I_EMAC);
220
+ qdev_set_nic_properties(DEVICE(&s->emac), &nd_table[0]);
221
+ }
222
+ qdev_init_nofail(DEVICE(&s->emac));
223
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->emac), 0, s->memmap[AW_H3_EMAC]);
224
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->emac), 0,
225
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_EMAC));
226
+
227
/* Universal Serial Bus */
228
sysbus_create_simple(TYPE_AW_H3_EHCI, s->memmap[AW_H3_EHCI0],
229
qdev_get_gpio_in(DEVICE(&s->gic),
230
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
231
index XXXXXXX..XXXXXXX 100644
232
--- a/hw/arm/orangepi.c
233
+++ b/hw/arm/orangepi.c
234
@@ -XXX,XX +XXX,XX @@ static void orangepi_init(MachineState *machine)
235
warn_report("Security Identifier value does not include H3 prefix");
236
}
237
238
+ /* Setup EMAC properties */
239
+ object_property_set_int(OBJECT(&h3->emac), 1, "phy-addr", &error_abort);
240
+
241
/* Mark H3 object realized */
242
object_property_set_bool(OBJECT(h3), true, "realized", &error_abort);
243
244
diff --git a/hw/net/allwinner-sun8i-emac.c b/hw/net/allwinner-sun8i-emac.c
245
new file mode 100644
246
index XXXXXXX..XXXXXXX
247
--- /dev/null
248
+++ b/hw/net/allwinner-sun8i-emac.c
249
@@ -XXX,XX +XXX,XX @@
250
+/*
251
+ * Allwinner Sun8i Ethernet MAC emulation
252
+ *
253
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
254
+ *
255
+ * This program is free software: you can redistribute it and/or modify
256
+ * it under the terms of the GNU General Public License as published by
257
+ * the Free Software Foundation, either version 2 of the License, or
258
+ * (at your option) any later version.
259
+ *
260
+ * This program is distributed in the hope that it will be useful,
261
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
262
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
263
+ * GNU General Public License for more details.
264
+ *
265
+ * You should have received a copy of the GNU General Public License
266
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
267
+ */
268
+
269
+#include "qemu/osdep.h"
270
+#include "qemu/units.h"
271
+#include "hw/sysbus.h"
272
+#include "migration/vmstate.h"
273
+#include "net/net.h"
274
+#include "hw/irq.h"
275
+#include "hw/qdev-properties.h"
276
+#include "qemu/log.h"
26
+#include "trace.h"
277
+#include "trace.h"
27
278
+#include "net/checksum.h"
28
bool qdev_hotplug = false;
279
+#include "qemu/module.h"
29
static bool qdev_hot_added = false;
280
+#include "exec/cpu-common.h"
30
@@ -XXX,XX +XXX,XX @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
281
+#include "hw/net/allwinner-sun8i-emac.h"
31
bool replugging = dev->parent_bus != NULL;
282
+
32
283
+/* EMAC register offsets */
33
if (replugging) {
284
+enum {
34
- /* Keep a reference to the device while it's not plugged into
285
+ REG_BASIC_CTL_0 = 0x0000, /* Basic Control 0 */
35
+ trace_qdev_update_parent_bus(dev, object_get_typename(OBJECT(dev)),
286
+ REG_BASIC_CTL_1 = 0x0004, /* Basic Control 1 */
36
+ dev->parent_bus, object_get_typename(OBJECT(dev->parent_bus)),
287
+ REG_INT_STA = 0x0008, /* Interrupt Status */
37
+ OBJECT(bus), object_get_typename(OBJECT(bus)));
288
+ REG_INT_EN = 0x000C, /* Interrupt Enable */
38
+ /*
289
+ REG_TX_CTL_0 = 0x0010, /* Transmit Control 0 */
39
+ * Keep a reference to the device while it's not plugged into
290
+ REG_TX_CTL_1 = 0x0014, /* Transmit Control 1 */
40
* any bus, to avoid it potentially evaporating when it is
291
+ REG_TX_FLOW_CTL = 0x001C, /* Transmit Flow Control */
41
* dereffed in bus_remove_child().
292
+ REG_TX_DMA_DESC_LIST = 0x0020, /* Transmit Descriptor List Address */
42
*/
293
+ REG_RX_CTL_0 = 0x0024, /* Receive Control 0 */
43
@@ -XXX,XX +XXX,XX @@ HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
294
+ REG_RX_CTL_1 = 0x0028, /* Receive Control 1 */
44
return hotplug_ctrl;
295
+ REG_RX_DMA_DESC_LIST = 0x0034, /* Receive Descriptor List Address */
45
}
296
+ REG_FRM_FLT = 0x0038, /* Receive Frame Filter */
46
297
+ REG_RX_HASH_0 = 0x0040, /* Receive Hash Table 0 */
47
+static int qdev_prereset(DeviceState *dev, void *opaque)
298
+ REG_RX_HASH_1 = 0x0044, /* Receive Hash Table 1 */
48
+{
299
+ REG_MII_CMD = 0x0048, /* Management Interface Command */
49
+ trace_qdev_reset_tree(dev, object_get_typename(OBJECT(dev)));
300
+ REG_MII_DATA = 0x004C, /* Management Interface Data */
301
+ REG_ADDR_HIGH = 0x0050, /* MAC Address High */
302
+ REG_ADDR_LOW = 0x0054, /* MAC Address Low */
303
+ REG_TX_DMA_STA = 0x00B0, /* Transmit DMA Status */
304
+ REG_TX_CUR_DESC = 0x00B4, /* Transmit Current Descriptor */
305
+ REG_TX_CUR_BUF = 0x00B8, /* Transmit Current Buffer */
306
+ REG_RX_DMA_STA = 0x00C0, /* Receive DMA Status */
307
+ REG_RX_CUR_DESC = 0x00C4, /* Receive Current Descriptor */
308
+ REG_RX_CUR_BUF = 0x00C8, /* Receive Current Buffer */
309
+ REG_RGMII_STA = 0x00D0, /* RGMII Status */
310
+};
311
+
312
+/* EMAC register flags */
313
+enum {
314
+ BASIC_CTL0_100Mbps = (0b11 << 2),
315
+ BASIC_CTL0_FD = (1 << 0),
316
+ BASIC_CTL1_SOFTRST = (1 << 0),
317
+};
318
+
319
+enum {
320
+ INT_STA_RGMII_LINK = (1 << 16),
321
+ INT_STA_RX_EARLY = (1 << 13),
322
+ INT_STA_RX_OVERFLOW = (1 << 12),
323
+ INT_STA_RX_TIMEOUT = (1 << 11),
324
+ INT_STA_RX_DMA_STOP = (1 << 10),
325
+ INT_STA_RX_BUF_UA = (1 << 9),
326
+ INT_STA_RX = (1 << 8),
327
+ INT_STA_TX_EARLY = (1 << 5),
328
+ INT_STA_TX_UNDERFLOW = (1 << 4),
329
+ INT_STA_TX_TIMEOUT = (1 << 3),
330
+ INT_STA_TX_BUF_UA = (1 << 2),
331
+ INT_STA_TX_DMA_STOP = (1 << 1),
332
+ INT_STA_TX = (1 << 0),
333
+};
334
+
335
+enum {
336
+ INT_EN_RX_EARLY = (1 << 13),
337
+ INT_EN_RX_OVERFLOW = (1 << 12),
338
+ INT_EN_RX_TIMEOUT = (1 << 11),
339
+ INT_EN_RX_DMA_STOP = (1 << 10),
340
+ INT_EN_RX_BUF_UA = (1 << 9),
341
+ INT_EN_RX = (1 << 8),
342
+ INT_EN_TX_EARLY = (1 << 5),
343
+ INT_EN_TX_UNDERFLOW = (1 << 4),
344
+ INT_EN_TX_TIMEOUT = (1 << 3),
345
+ INT_EN_TX_BUF_UA = (1 << 2),
346
+ INT_EN_TX_DMA_STOP = (1 << 1),
347
+ INT_EN_TX = (1 << 0),
348
+};
349
+
350
+enum {
351
+ TX_CTL0_TX_EN = (1 << 31),
352
+ TX_CTL1_TX_DMA_START = (1 << 31),
353
+ TX_CTL1_TX_DMA_EN = (1 << 30),
354
+ TX_CTL1_TX_FLUSH = (1 << 0),
355
+};
356
+
357
+enum {
358
+ RX_CTL0_RX_EN = (1 << 31),
359
+ RX_CTL0_STRIP_FCS = (1 << 28),
360
+ RX_CTL0_CRC_IPV4 = (1 << 27),
361
+};
362
+
363
+enum {
364
+ RX_CTL1_RX_DMA_START = (1 << 31),
365
+ RX_CTL1_RX_DMA_EN = (1 << 30),
366
+ RX_CTL1_RX_MD = (1 << 1),
367
+};
368
+
369
+enum {
370
+ RX_FRM_FLT_DIS_ADDR = (1 << 31),
371
+};
372
+
373
+enum {
374
+ MII_CMD_PHY_ADDR_SHIFT = (12),
375
+ MII_CMD_PHY_ADDR_MASK = (0xf000),
376
+ MII_CMD_PHY_REG_SHIFT = (4),
377
+ MII_CMD_PHY_REG_MASK = (0xf0),
378
+ MII_CMD_PHY_RW = (1 << 1),
379
+ MII_CMD_PHY_BUSY = (1 << 0),
380
+};
381
+
382
+enum {
383
+ TX_DMA_STA_STOP = (0b000),
384
+ TX_DMA_STA_RUN_FETCH = (0b001),
385
+ TX_DMA_STA_WAIT_STA = (0b010),
386
+};
387
+
388
+enum {
389
+ RX_DMA_STA_STOP = (0b000),
390
+ RX_DMA_STA_RUN_FETCH = (0b001),
391
+ RX_DMA_STA_WAIT_FRM = (0b011),
392
+};
393
+
394
+/* EMAC register reset values */
395
+enum {
396
+ REG_BASIC_CTL_1_RST = 0x08000000,
397
+};
398
+
399
+/* EMAC constants */
400
+enum {
401
+ AW_SUN8I_EMAC_MIN_PKT_SZ = 64
402
+};
403
+
404
+/* Transmit/receive frame descriptor */
405
+typedef struct FrameDescriptor {
406
+ uint32_t status;
407
+ uint32_t status2;
408
+ uint32_t addr;
409
+ uint32_t next;
410
+} FrameDescriptor;
411
+
412
+/* Frame descriptor flags */
413
+enum {
414
+ DESC_STATUS_CTL = (1 << 31),
415
+ DESC_STATUS2_BUF_SIZE_MASK = (0x7ff),
416
+};
417
+
418
+/* Transmit frame descriptor flags */
419
+enum {
420
+ TX_DESC_STATUS_LENGTH_ERR = (1 << 14),
421
+ TX_DESC_STATUS2_FIRST_DESC = (1 << 29),
422
+ TX_DESC_STATUS2_LAST_DESC = (1 << 30),
423
+ TX_DESC_STATUS2_CHECKSUM_MASK = (0x3 << 27),
424
+};
425
+
426
+/* Receive frame descriptor flags */
427
+enum {
428
+ RX_DESC_STATUS_FIRST_DESC = (1 << 9),
429
+ RX_DESC_STATUS_LAST_DESC = (1 << 8),
430
+ RX_DESC_STATUS_FRM_LEN_MASK = (0x3fff0000),
431
+ RX_DESC_STATUS_FRM_LEN_SHIFT = (16),
432
+ RX_DESC_STATUS_NO_BUF = (1 << 14),
433
+ RX_DESC_STATUS_HEADER_ERR = (1 << 7),
434
+ RX_DESC_STATUS_LENGTH_ERR = (1 << 4),
435
+ RX_DESC_STATUS_CRC_ERR = (1 << 1),
436
+ RX_DESC_STATUS_PAYLOAD_ERR = (1 << 0),
437
+ RX_DESC_STATUS2_RX_INT_CTL = (1 << 31),
438
+};
439
+
440
+/* MII register offsets */
441
+enum {
442
+ MII_REG_CR = (0x0), /* Control */
443
+ MII_REG_ST = (0x1), /* Status */
444
+ MII_REG_ID_HIGH = (0x2), /* Identifier High */
445
+ MII_REG_ID_LOW = (0x3), /* Identifier Low */
446
+ MII_REG_ADV = (0x4), /* Advertised abilities */
447
+ MII_REG_LPA = (0x5), /* Link partner abilities */
448
+};
449
+
450
+/* MII register flags */
451
+enum {
452
+ MII_REG_CR_RESET = (1 << 15),
453
+ MII_REG_CR_POWERDOWN = (1 << 11),
454
+ MII_REG_CR_10Mbit = (0),
455
+ MII_REG_CR_100Mbit = (1 << 13),
456
+ MII_REG_CR_1000Mbit = (1 << 6),
457
+ MII_REG_CR_AUTO_NEG = (1 << 12),
458
+ MII_REG_CR_AUTO_NEG_RESTART = (1 << 9),
459
+ MII_REG_CR_FULLDUPLEX = (1 << 8),
460
+};
461
+
462
+enum {
463
+ MII_REG_ST_100BASE_T4 = (1 << 15),
464
+ MII_REG_ST_100BASE_X_FD = (1 << 14),
465
+ MII_REG_ST_100BASE_X_HD = (1 << 13),
466
+ MII_REG_ST_10_FD = (1 << 12),
467
+ MII_REG_ST_10_HD = (1 << 11),
468
+ MII_REG_ST_100BASE_T2_FD = (1 << 10),
469
+ MII_REG_ST_100BASE_T2_HD = (1 << 9),
470
+ MII_REG_ST_AUTONEG_COMPLETE = (1 << 5),
471
+ MII_REG_ST_AUTONEG_AVAIL = (1 << 3),
472
+ MII_REG_ST_LINK_UP = (1 << 2),
473
+};
474
+
475
+enum {
476
+ MII_REG_LPA_10_HD = (1 << 5),
477
+ MII_REG_LPA_10_FD = (1 << 6),
478
+ MII_REG_LPA_100_HD = (1 << 7),
479
+ MII_REG_LPA_100_FD = (1 << 8),
480
+ MII_REG_LPA_PAUSE = (1 << 10),
481
+ MII_REG_LPA_ASYMPAUSE = (1 << 11),
482
+};
483
+
484
+/* MII constants */
485
+enum {
486
+ MII_PHY_ID_HIGH = 0x0044,
487
+ MII_PHY_ID_LOW = 0x1400,
488
+};
489
+
490
+static void allwinner_sun8i_emac_mii_set_link(AwSun8iEmacState *s,
491
+ bool link_active)
492
+{
493
+ if (link_active) {
494
+ s->mii_st |= MII_REG_ST_LINK_UP;
495
+ } else {
496
+ s->mii_st &= ~MII_REG_ST_LINK_UP;
497
+ }
498
+}
499
+
500
+static void allwinner_sun8i_emac_mii_reset(AwSun8iEmacState *s,
501
+ bool link_active)
502
+{
503
+ s->mii_cr = MII_REG_CR_100Mbit | MII_REG_CR_AUTO_NEG |
504
+ MII_REG_CR_FULLDUPLEX;
505
+ s->mii_st = MII_REG_ST_100BASE_T4 | MII_REG_ST_100BASE_X_FD |
506
+ MII_REG_ST_100BASE_X_HD | MII_REG_ST_10_FD | MII_REG_ST_10_HD |
507
+ MII_REG_ST_100BASE_T2_FD | MII_REG_ST_100BASE_T2_HD |
508
+ MII_REG_ST_AUTONEG_COMPLETE | MII_REG_ST_AUTONEG_AVAIL;
509
+ s->mii_adv = 0;
510
+
511
+ allwinner_sun8i_emac_mii_set_link(s, link_active);
512
+}
513
+
514
+static void allwinner_sun8i_emac_mii_cmd(AwSun8iEmacState *s)
515
+{
516
+ uint8_t addr, reg;
517
+
518
+ addr = (s->mii_cmd & MII_CMD_PHY_ADDR_MASK) >> MII_CMD_PHY_ADDR_SHIFT;
519
+ reg = (s->mii_cmd & MII_CMD_PHY_REG_MASK) >> MII_CMD_PHY_REG_SHIFT;
520
+
521
+ if (addr != s->mii_phy_addr) {
522
+ return;
523
+ }
524
+
525
+ /* Read or write a PHY register? */
526
+ if (s->mii_cmd & MII_CMD_PHY_RW) {
527
+ trace_allwinner_sun8i_emac_mii_write_reg(reg, s->mii_data);
528
+
529
+ switch (reg) {
530
+ case MII_REG_CR:
531
+ if (s->mii_data & MII_REG_CR_RESET) {
532
+ allwinner_sun8i_emac_mii_reset(s, s->mii_st &
533
+ MII_REG_ST_LINK_UP);
534
+ } else {
535
+ s->mii_cr = s->mii_data & ~(MII_REG_CR_RESET |
536
+ MII_REG_CR_AUTO_NEG_RESTART);
537
+ }
538
+ break;
539
+ case MII_REG_ADV:
540
+ s->mii_adv = s->mii_data;
541
+ break;
542
+ case MII_REG_ID_HIGH:
543
+ case MII_REG_ID_LOW:
544
+ case MII_REG_LPA:
545
+ break;
546
+ default:
547
+ qemu_log_mask(LOG_UNIMP, "allwinner-h3-emac: write access to "
548
+ "unknown MII register 0x%x\n", reg);
549
+ break;
550
+ }
551
+ } else {
552
+ switch (reg) {
553
+ case MII_REG_CR:
554
+ s->mii_data = s->mii_cr;
555
+ break;
556
+ case MII_REG_ST:
557
+ s->mii_data = s->mii_st;
558
+ break;
559
+ case MII_REG_ID_HIGH:
560
+ s->mii_data = MII_PHY_ID_HIGH;
561
+ break;
562
+ case MII_REG_ID_LOW:
563
+ s->mii_data = MII_PHY_ID_LOW;
564
+ break;
565
+ case MII_REG_ADV:
566
+ s->mii_data = s->mii_adv;
567
+ break;
568
+ case MII_REG_LPA:
569
+ s->mii_data = MII_REG_LPA_10_HD | MII_REG_LPA_10_FD |
570
+ MII_REG_LPA_100_HD | MII_REG_LPA_100_FD |
571
+ MII_REG_LPA_PAUSE | MII_REG_LPA_ASYMPAUSE;
572
+ break;
573
+ default:
574
+ qemu_log_mask(LOG_UNIMP, "allwinner-h3-emac: read access to "
575
+ "unknown MII register 0x%x\n", reg);
576
+ s->mii_data = 0;
577
+ break;
578
+ }
579
+
580
+ trace_allwinner_sun8i_emac_mii_read_reg(reg, s->mii_data);
581
+ }
582
+}
583
+
584
+static void allwinner_sun8i_emac_update_irq(AwSun8iEmacState *s)
585
+{
586
+ qemu_set_irq(s->irq, (s->int_sta & s->int_en) != 0);
587
+}
588
+
589
+static uint32_t allwinner_sun8i_emac_next_desc(FrameDescriptor *desc,
590
+ size_t min_size)
591
+{
592
+ uint32_t paddr = desc->next;
593
+
594
+ cpu_physical_memory_read(paddr, desc, sizeof(*desc));
595
+
596
+ if ((desc->status & DESC_STATUS_CTL) &&
597
+ (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_size) {
598
+ return paddr;
599
+ } else {
600
+ return 0;
601
+ }
602
+}
603
+
604
+static uint32_t allwinner_sun8i_emac_get_desc(FrameDescriptor *desc,
605
+ uint32_t start_addr,
606
+ size_t min_size)
607
+{
608
+ uint32_t desc_addr = start_addr;
609
+
610
+ /* Note that the list is a cycle. Last entry points back to the head. */
611
+ while (desc_addr != 0) {
612
+ cpu_physical_memory_read(desc_addr, desc, sizeof(*desc));
613
+
614
+ if ((desc->status & DESC_STATUS_CTL) &&
615
+ (desc->status2 & DESC_STATUS2_BUF_SIZE_MASK) >= min_size) {
616
+ return desc_addr;
617
+ } else if (desc->next == start_addr) {
618
+ break;
619
+ } else {
620
+ desc_addr = desc->next;
621
+ }
622
+ }
623
+
50
+ return 0;
624
+ return 0;
51
+}
625
+}
52
+
626
+
53
+static int qbus_prereset(BusState *bus, void *opaque)
627
+static uint32_t allwinner_sun8i_emac_rx_desc(AwSun8iEmacState *s,
54
+{
628
+ FrameDescriptor *desc,
55
+ trace_qbus_reset_tree(bus, object_get_typename(OBJECT(bus)));
629
+ size_t min_size)
630
+{
631
+ return allwinner_sun8i_emac_get_desc(desc, s->rx_desc_curr, min_size);
632
+}
633
+
634
+static uint32_t allwinner_sun8i_emac_tx_desc(AwSun8iEmacState *s,
635
+ FrameDescriptor *desc,
636
+ size_t min_size)
637
+{
638
+ return allwinner_sun8i_emac_get_desc(desc, s->tx_desc_head, min_size);
639
+}
640
+
641
+static void allwinner_sun8i_emac_flush_desc(FrameDescriptor *desc,
642
+ uint32_t phys_addr)
643
+{
644
+ cpu_physical_memory_write(phys_addr, desc, sizeof(*desc));
645
+}
646
+
647
+static int allwinner_sun8i_emac_can_receive(NetClientState *nc)
648
+{
649
+ AwSun8iEmacState *s = qemu_get_nic_opaque(nc);
650
+ FrameDescriptor desc;
651
+
652
+ return (s->rx_ctl0 & RX_CTL0_RX_EN) &&
653
+ (allwinner_sun8i_emac_rx_desc(s, &desc, 0) != 0);
654
+}
655
+
656
+static ssize_t allwinner_sun8i_emac_receive(NetClientState *nc,
657
+ const uint8_t *buf,
658
+ size_t size)
659
+{
660
+ AwSun8iEmacState *s = qemu_get_nic_opaque(nc);
661
+ FrameDescriptor desc;
662
+ size_t bytes_left = size;
663
+ size_t desc_bytes = 0;
664
+ size_t pad_fcs_size = 4;
665
+ size_t padding = 0;
666
+
667
+ if (!(s->rx_ctl0 & RX_CTL0_RX_EN)) {
668
+ return -1;
669
+ }
670
+
671
+ s->rx_desc_curr = allwinner_sun8i_emac_rx_desc(s, &desc,
672
+ AW_SUN8I_EMAC_MIN_PKT_SZ);
673
+ if (!s->rx_desc_curr) {
674
+ s->int_sta |= INT_STA_RX_BUF_UA;
675
+ }
676
+
677
+ /* Keep filling RX descriptors until the whole frame is written */
678
+ while (s->rx_desc_curr && bytes_left > 0) {
679
+ desc.status &= ~DESC_STATUS_CTL;
680
+ desc.status &= ~RX_DESC_STATUS_FRM_LEN_MASK;
681
+
682
+ if (bytes_left == size) {
683
+ desc.status |= RX_DESC_STATUS_FIRST_DESC;
684
+ }
685
+
686
+ if ((desc.status2 & DESC_STATUS2_BUF_SIZE_MASK) <
687
+ (bytes_left + pad_fcs_size)) {
688
+ desc_bytes = desc.status2 & DESC_STATUS2_BUF_SIZE_MASK;
689
+ desc.status |= desc_bytes << RX_DESC_STATUS_FRM_LEN_SHIFT;
690
+ } else {
691
+ padding = pad_fcs_size;
692
+ if (bytes_left < AW_SUN8I_EMAC_MIN_PKT_SZ) {
693
+ padding += (AW_SUN8I_EMAC_MIN_PKT_SZ - bytes_left);
694
+ }
695
+
696
+ desc_bytes = (bytes_left);
697
+ desc.status |= RX_DESC_STATUS_LAST_DESC;
698
+ desc.status |= (bytes_left + padding)
699
+ << RX_DESC_STATUS_FRM_LEN_SHIFT;
700
+ }
701
+
702
+ cpu_physical_memory_write(desc.addr, buf, desc_bytes);
703
+ allwinner_sun8i_emac_flush_desc(&desc, s->rx_desc_curr);
704
+ trace_allwinner_sun8i_emac_receive(s->rx_desc_curr, desc.addr,
705
+ desc_bytes);
706
+
707
+ /* Check if frame needs to raise the receive interrupt */
708
+ if (!(desc.status2 & RX_DESC_STATUS2_RX_INT_CTL)) {
709
+ s->int_sta |= INT_STA_RX;
710
+ }
711
+
712
+ /* Increment variables */
713
+ buf += desc_bytes;
714
+ bytes_left -= desc_bytes;
715
+
716
+ /* Move to the next descriptor */
717
+ s->rx_desc_curr = allwinner_sun8i_emac_next_desc(&desc, 64);
718
+ if (!s->rx_desc_curr) {
719
+ /* Not enough buffer space available */
720
+ s->int_sta |= INT_STA_RX_BUF_UA;
721
+ s->rx_desc_curr = s->rx_desc_head;
722
+ break;
723
+ }
724
+ }
725
+
726
+ /* Report receive DMA is finished */
727
+ s->rx_ctl1 &= ~RX_CTL1_RX_DMA_START;
728
+ allwinner_sun8i_emac_update_irq(s);
729
+
730
+ return size;
731
+}
732
+
733
+static void allwinner_sun8i_emac_transmit(AwSun8iEmacState *s)
734
+{
735
+ NetClientState *nc = qemu_get_queue(s->nic);
736
+ FrameDescriptor desc;
737
+ size_t bytes = 0;
738
+ size_t packet_bytes = 0;
739
+ size_t transmitted = 0;
740
+ static uint8_t packet_buf[2048];
741
+
742
+ s->tx_desc_curr = allwinner_sun8i_emac_tx_desc(s, &desc, 0);
743
+
744
+ /* Read all transmit descriptors */
745
+ while (s->tx_desc_curr != 0) {
746
+
747
+ /* Read from physical memory into packet buffer */
748
+ bytes = desc.status2 & DESC_STATUS2_BUF_SIZE_MASK;
749
+ if (bytes + packet_bytes > sizeof(packet_buf)) {
750
+ desc.status |= TX_DESC_STATUS_LENGTH_ERR;
751
+ break;
752
+ }
753
+ cpu_physical_memory_read(desc.addr, packet_buf + packet_bytes, bytes);
754
+ packet_bytes += bytes;
755
+ desc.status &= ~DESC_STATUS_CTL;
756
+ allwinner_sun8i_emac_flush_desc(&desc, s->tx_desc_curr);
757
+
758
+ /* After the last descriptor, send the packet */
759
+ if (desc.status2 & TX_DESC_STATUS2_LAST_DESC) {
760
+ if (desc.status2 & TX_DESC_STATUS2_CHECKSUM_MASK) {
761
+ net_checksum_calculate(packet_buf, packet_bytes);
762
+ }
763
+
764
+ qemu_send_packet(nc, packet_buf, packet_bytes);
765
+ trace_allwinner_sun8i_emac_transmit(s->tx_desc_curr, desc.addr,
766
+ bytes);
767
+
768
+ packet_bytes = 0;
769
+ transmitted++;
770
+ }
771
+ s->tx_desc_curr = allwinner_sun8i_emac_next_desc(&desc, 0);
772
+ }
773
+
774
+ /* Raise transmit completed interrupt */
775
+ if (transmitted > 0) {
776
+ s->int_sta |= INT_STA_TX;
777
+ s->tx_ctl1 &= ~TX_CTL1_TX_DMA_START;
778
+ allwinner_sun8i_emac_update_irq(s);
779
+ }
780
+}
781
+
782
+static void allwinner_sun8i_emac_reset(DeviceState *dev)
783
+{
784
+ AwSun8iEmacState *s = AW_SUN8I_EMAC(dev);
785
+ NetClientState *nc = qemu_get_queue(s->nic);
786
+
787
+ trace_allwinner_sun8i_emac_reset();
788
+
789
+ s->mii_cmd = 0;
790
+ s->mii_data = 0;
791
+ s->basic_ctl0 = 0;
792
+ s->basic_ctl1 = REG_BASIC_CTL_1_RST;
793
+ s->int_en = 0;
794
+ s->int_sta = 0;
795
+ s->frm_flt = 0;
796
+ s->rx_ctl0 = 0;
797
+ s->rx_ctl1 = RX_CTL1_RX_MD;
798
+ s->rx_desc_head = 0;
799
+ s->rx_desc_curr = 0;
800
+ s->tx_ctl0 = 0;
801
+ s->tx_ctl1 = 0;
802
+ s->tx_desc_head = 0;
803
+ s->tx_desc_curr = 0;
804
+ s->tx_flowctl = 0;
805
+
806
+ allwinner_sun8i_emac_mii_reset(s, !nc->link_down);
807
+}
808
+
809
+static uint64_t allwinner_sun8i_emac_read(void *opaque, hwaddr offset,
810
+ unsigned size)
811
+{
812
+ AwSun8iEmacState *s = AW_SUN8I_EMAC(opaque);
813
+ uint64_t value = 0;
814
+ FrameDescriptor desc;
815
+
816
+ switch (offset) {
817
+ case REG_BASIC_CTL_0: /* Basic Control 0 */
818
+ value = s->basic_ctl0;
819
+ break;
820
+ case REG_BASIC_CTL_1: /* Basic Control 1 */
821
+ value = s->basic_ctl1;
822
+ break;
823
+ case REG_INT_STA: /* Interrupt Status */
824
+ value = s->int_sta;
825
+ break;
826
+ case REG_INT_EN: /* Interupt Enable */
827
+ value = s->int_en;
828
+ break;
829
+ case REG_TX_CTL_0: /* Transmit Control 0 */
830
+ value = s->tx_ctl0;
831
+ break;
832
+ case REG_TX_CTL_1: /* Transmit Control 1 */
833
+ value = s->tx_ctl1;
834
+ break;
835
+ case REG_TX_FLOW_CTL: /* Transmit Flow Control */
836
+ value = s->tx_flowctl;
837
+ break;
838
+ case REG_TX_DMA_DESC_LIST: /* Transmit Descriptor List Address */
839
+ value = s->tx_desc_head;
840
+ break;
841
+ case REG_RX_CTL_0: /* Receive Control 0 */
842
+ value = s->rx_ctl0;
843
+ break;
844
+ case REG_RX_CTL_1: /* Receive Control 1 */
845
+ value = s->rx_ctl1;
846
+ break;
847
+ case REG_RX_DMA_DESC_LIST: /* Receive Descriptor List Address */
848
+ value = s->rx_desc_head;
849
+ break;
850
+ case REG_FRM_FLT: /* Receive Frame Filter */
851
+ value = s->frm_flt;
852
+ break;
853
+ case REG_RX_HASH_0: /* Receive Hash Table 0 */
854
+ case REG_RX_HASH_1: /* Receive Hash Table 1 */
855
+ break;
856
+ case REG_MII_CMD: /* Management Interface Command */
857
+ value = s->mii_cmd;
858
+ break;
859
+ case REG_MII_DATA: /* Management Interface Data */
860
+ value = s->mii_data;
861
+ break;
862
+ case REG_ADDR_HIGH: /* MAC Address High */
863
+ value = *(((uint32_t *) (s->conf.macaddr.a)) + 1);
864
+ break;
865
+ case REG_ADDR_LOW: /* MAC Address Low */
866
+ value = *(uint32_t *) (s->conf.macaddr.a);
867
+ break;
868
+ case REG_TX_DMA_STA: /* Transmit DMA Status */
869
+ break;
870
+ case REG_TX_CUR_DESC: /* Transmit Current Descriptor */
871
+ value = s->tx_desc_curr;
872
+ break;
873
+ case REG_TX_CUR_BUF: /* Transmit Current Buffer */
874
+ if (s->tx_desc_curr != 0) {
875
+ cpu_physical_memory_read(s->tx_desc_curr, &desc, sizeof(desc));
876
+ value = desc.addr;
877
+ } else {
878
+ value = 0;
879
+ }
880
+ break;
881
+ case REG_RX_DMA_STA: /* Receive DMA Status */
882
+ break;
883
+ case REG_RX_CUR_DESC: /* Receive Current Descriptor */
884
+ value = s->rx_desc_curr;
885
+ break;
886
+ case REG_RX_CUR_BUF: /* Receive Current Buffer */
887
+ if (s->rx_desc_curr != 0) {
888
+ cpu_physical_memory_read(s->rx_desc_curr, &desc, sizeof(desc));
889
+ value = desc.addr;
890
+ } else {
891
+ value = 0;
892
+ }
893
+ break;
894
+ case REG_RGMII_STA: /* RGMII Status */
895
+ break;
896
+ default:
897
+ qemu_log_mask(LOG_UNIMP, "allwinner-h3-emac: read access to unknown "
898
+ "EMAC register 0x" TARGET_FMT_plx "\n",
899
+ offset);
900
+ }
901
+
902
+ trace_allwinner_sun8i_emac_read(offset, value);
903
+ return value;
904
+}
905
+
906
+static void allwinner_sun8i_emac_write(void *opaque, hwaddr offset,
907
+ uint64_t value, unsigned size)
908
+{
909
+ AwSun8iEmacState *s = AW_SUN8I_EMAC(opaque);
910
+ NetClientState *nc = qemu_get_queue(s->nic);
911
+
912
+ trace_allwinner_sun8i_emac_write(offset, value);
913
+
914
+ switch (offset) {
915
+ case REG_BASIC_CTL_0: /* Basic Control 0 */
916
+ s->basic_ctl0 = value;
917
+ break;
918
+ case REG_BASIC_CTL_1: /* Basic Control 1 */
919
+ if (value & BASIC_CTL1_SOFTRST) {
920
+ allwinner_sun8i_emac_reset(DEVICE(s));
921
+ value &= ~BASIC_CTL1_SOFTRST;
922
+ }
923
+ s->basic_ctl1 = value;
924
+ if (allwinner_sun8i_emac_can_receive(nc)) {
925
+ qemu_flush_queued_packets(nc);
926
+ }
927
+ break;
928
+ case REG_INT_STA: /* Interrupt Status */
929
+ s->int_sta &= ~value;
930
+ allwinner_sun8i_emac_update_irq(s);
931
+ break;
932
+ case REG_INT_EN: /* Interrupt Enable */
933
+ s->int_en = value;
934
+ allwinner_sun8i_emac_update_irq(s);
935
+ break;
936
+ case REG_TX_CTL_0: /* Transmit Control 0 */
937
+ s->tx_ctl0 = value;
938
+ break;
939
+ case REG_TX_CTL_1: /* Transmit Control 1 */
940
+ s->tx_ctl1 = value;
941
+ if (value & TX_CTL1_TX_DMA_EN) {
942
+ allwinner_sun8i_emac_transmit(s);
943
+ }
944
+ break;
945
+ case REG_TX_FLOW_CTL: /* Transmit Flow Control */
946
+ s->tx_flowctl = value;
947
+ break;
948
+ case REG_TX_DMA_DESC_LIST: /* Transmit Descriptor List Address */
949
+ s->tx_desc_head = value;
950
+ s->tx_desc_curr = value;
951
+ break;
952
+ case REG_RX_CTL_0: /* Receive Control 0 */
953
+ s->rx_ctl0 = value;
954
+ break;
955
+ case REG_RX_CTL_1: /* Receive Control 1 */
956
+ s->rx_ctl1 = value | RX_CTL1_RX_MD;
957
+ if ((value & RX_CTL1_RX_DMA_EN) &&
958
+ allwinner_sun8i_emac_can_receive(nc)) {
959
+ qemu_flush_queued_packets(nc);
960
+ }
961
+ break;
962
+ case REG_RX_DMA_DESC_LIST: /* Receive Descriptor List Address */
963
+ s->rx_desc_head = value;
964
+ s->rx_desc_curr = value;
965
+ break;
966
+ case REG_FRM_FLT: /* Receive Frame Filter */
967
+ s->frm_flt = value;
968
+ break;
969
+ case REG_RX_HASH_0: /* Receive Hash Table 0 */
970
+ case REG_RX_HASH_1: /* Receive Hash Table 1 */
971
+ break;
972
+ case REG_MII_CMD: /* Management Interface Command */
973
+ s->mii_cmd = value & ~MII_CMD_PHY_BUSY;
974
+ allwinner_sun8i_emac_mii_cmd(s);
975
+ break;
976
+ case REG_MII_DATA: /* Management Interface Data */
977
+ s->mii_data = value;
978
+ break;
979
+ case REG_ADDR_HIGH: /* MAC Address High */
980
+ s->conf.macaddr.a[4] = (value & 0xff);
981
+ s->conf.macaddr.a[5] = (value & 0xff00) >> 8;
982
+ break;
983
+ case REG_ADDR_LOW: /* MAC Address Low */
984
+ s->conf.macaddr.a[0] = (value & 0xff);
985
+ s->conf.macaddr.a[1] = (value & 0xff00) >> 8;
986
+ s->conf.macaddr.a[2] = (value & 0xff0000) >> 16;
987
+ s->conf.macaddr.a[3] = (value & 0xff000000) >> 24;
988
+ break;
989
+ case REG_TX_DMA_STA: /* Transmit DMA Status */
990
+ case REG_TX_CUR_DESC: /* Transmit Current Descriptor */
991
+ case REG_TX_CUR_BUF: /* Transmit Current Buffer */
992
+ case REG_RX_DMA_STA: /* Receive DMA Status */
993
+ case REG_RX_CUR_DESC: /* Receive Current Descriptor */
994
+ case REG_RX_CUR_BUF: /* Receive Current Buffer */
995
+ case REG_RGMII_STA: /* RGMII Status */
996
+ break;
997
+ default:
998
+ qemu_log_mask(LOG_UNIMP, "allwinner-h3-emac: write access to unknown "
999
+ "EMAC register 0x" TARGET_FMT_plx "\n",
1000
+ offset);
1001
+ }
1002
+}
1003
+
1004
+static void allwinner_sun8i_emac_set_link(NetClientState *nc)
1005
+{
1006
+ AwSun8iEmacState *s = qemu_get_nic_opaque(nc);
1007
+
1008
+ trace_allwinner_sun8i_emac_set_link(!nc->link_down);
1009
+ allwinner_sun8i_emac_mii_set_link(s, !nc->link_down);
1010
+}
1011
+
1012
+static const MemoryRegionOps allwinner_sun8i_emac_mem_ops = {
1013
+ .read = allwinner_sun8i_emac_read,
1014
+ .write = allwinner_sun8i_emac_write,
1015
+ .endianness = DEVICE_NATIVE_ENDIAN,
1016
+ .valid = {
1017
+ .min_access_size = 4,
1018
+ .max_access_size = 4,
1019
+ },
1020
+ .impl.min_access_size = 4,
1021
+};
1022
+
1023
+static NetClientInfo net_allwinner_sun8i_emac_info = {
1024
+ .type = NET_CLIENT_DRIVER_NIC,
1025
+ .size = sizeof(NICState),
1026
+ .can_receive = allwinner_sun8i_emac_can_receive,
1027
+ .receive = allwinner_sun8i_emac_receive,
1028
+ .link_status_changed = allwinner_sun8i_emac_set_link,
1029
+};
1030
+
1031
+static void allwinner_sun8i_emac_init(Object *obj)
1032
+{
1033
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1034
+ AwSun8iEmacState *s = AW_SUN8I_EMAC(obj);
1035
+
1036
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_sun8i_emac_mem_ops,
1037
+ s, TYPE_AW_SUN8I_EMAC, 64 * KiB);
1038
+ sysbus_init_mmio(sbd, &s->iomem);
1039
+ sysbus_init_irq(sbd, &s->irq);
1040
+}
1041
+
1042
+static void allwinner_sun8i_emac_realize(DeviceState *dev, Error **errp)
1043
+{
1044
+ AwSun8iEmacState *s = AW_SUN8I_EMAC(dev);
1045
+
1046
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
1047
+ s->nic = qemu_new_nic(&net_allwinner_sun8i_emac_info, &s->conf,
1048
+ object_get_typename(OBJECT(dev)), dev->id, s);
1049
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
1050
+}
1051
+
1052
+static Property allwinner_sun8i_emac_properties[] = {
1053
+ DEFINE_NIC_PROPERTIES(AwSun8iEmacState, conf),
1054
+ DEFINE_PROP_UINT8("phy-addr", AwSun8iEmacState, mii_phy_addr, 0),
1055
+ DEFINE_PROP_END_OF_LIST(),
1056
+};
1057
+
1058
+static int allwinner_sun8i_emac_post_load(void *opaque, int version_id)
1059
+{
1060
+ AwSun8iEmacState *s = opaque;
1061
+
1062
+ allwinner_sun8i_emac_set_link(qemu_get_queue(s->nic));
1063
+
56
+ return 0;
1064
+ return 0;
57
+}
1065
+}
58
+
1066
+
59
static int qdev_reset_one(DeviceState *dev, void *opaque)
1067
+static const VMStateDescription vmstate_aw_emac = {
60
{
1068
+ .name = "allwinner-sun8i-emac",
61
device_legacy_reset(dev);
1069
+ .version_id = 1,
62
@@ -XXX,XX +XXX,XX @@ static int qdev_reset_one(DeviceState *dev, void *opaque)
1070
+ .minimum_version_id = 1,
63
static int qbus_reset_one(BusState *bus, void *opaque)
1071
+ .post_load = allwinner_sun8i_emac_post_load,
64
{
1072
+ .fields = (VMStateField[]) {
65
BusClass *bc = BUS_GET_CLASS(bus);
1073
+ VMSTATE_UINT8(mii_phy_addr, AwSun8iEmacState),
66
+ trace_qbus_reset(bus, object_get_typename(OBJECT(bus)));
1074
+ VMSTATE_UINT32(mii_cmd, AwSun8iEmacState),
67
if (bc->reset) {
1075
+ VMSTATE_UINT32(mii_data, AwSun8iEmacState),
68
bc->reset(bus);
1076
+ VMSTATE_UINT32(mii_cr, AwSun8iEmacState),
69
}
1077
+ VMSTATE_UINT32(mii_st, AwSun8iEmacState),
70
@@ -XXX,XX +XXX,XX @@ static int qbus_reset_one(BusState *bus, void *opaque)
1078
+ VMSTATE_UINT32(mii_adv, AwSun8iEmacState),
71
1079
+ VMSTATE_UINT32(basic_ctl0, AwSun8iEmacState),
72
void qdev_reset_all(DeviceState *dev)
1080
+ VMSTATE_UINT32(basic_ctl1, AwSun8iEmacState),
73
{
1081
+ VMSTATE_UINT32(int_en, AwSun8iEmacState),
74
- qdev_walk_children(dev, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
1082
+ VMSTATE_UINT32(int_sta, AwSun8iEmacState),
75
+ trace_qdev_reset_all(dev, object_get_typename(OBJECT(dev)));
1083
+ VMSTATE_UINT32(frm_flt, AwSun8iEmacState),
76
+ qdev_walk_children(dev, qdev_prereset, qbus_prereset,
1084
+ VMSTATE_UINT32(rx_ctl0, AwSun8iEmacState),
77
+ qdev_reset_one, qbus_reset_one, NULL);
1085
+ VMSTATE_UINT32(rx_ctl1, AwSun8iEmacState),
78
}
1086
+ VMSTATE_UINT32(rx_desc_head, AwSun8iEmacState),
79
1087
+ VMSTATE_UINT32(rx_desc_curr, AwSun8iEmacState),
80
void qdev_reset_all_fn(void *opaque)
1088
+ VMSTATE_UINT32(tx_ctl0, AwSun8iEmacState),
81
@@ -XXX,XX +XXX,XX @@ void qdev_reset_all_fn(void *opaque)
1089
+ VMSTATE_UINT32(tx_ctl1, AwSun8iEmacState),
82
1090
+ VMSTATE_UINT32(tx_desc_head, AwSun8iEmacState),
83
void qbus_reset_all(BusState *bus)
1091
+ VMSTATE_UINT32(tx_desc_curr, AwSun8iEmacState),
84
{
1092
+ VMSTATE_UINT32(tx_flowctl, AwSun8iEmacState),
85
- qbus_walk_children(bus, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
1093
+ VMSTATE_END_OF_LIST()
86
+ trace_qbus_reset_all(bus, object_get_typename(OBJECT(bus)));
1094
+ }
87
+ qbus_walk_children(bus, qdev_prereset, qbus_prereset,
1095
+};
88
+ qdev_reset_one, qbus_reset_one, NULL);
1096
+
89
}
1097
+static void allwinner_sun8i_emac_class_init(ObjectClass *klass, void *data)
90
1098
+{
91
void qbus_reset_all_fn(void *opaque)
1099
+ DeviceClass *dc = DEVICE_CLASS(klass);
92
@@ -XXX,XX +XXX,XX @@ void device_legacy_reset(DeviceState *dev)
1100
+
93
{
1101
+ dc->realize = allwinner_sun8i_emac_realize;
94
DeviceClass *klass = DEVICE_GET_CLASS(dev);
1102
+ dc->reset = allwinner_sun8i_emac_reset;
95
1103
+ dc->vmsd = &vmstate_aw_emac;
96
+ trace_qdev_reset(dev, object_get_typename(OBJECT(dev)));
1104
+ device_class_set_props(dc, allwinner_sun8i_emac_properties);
97
if (klass->reset) {
1105
+}
98
klass->reset(dev);
1106
+
99
}
1107
+static const TypeInfo allwinner_sun8i_emac_info = {
100
diff --git a/hw/core/trace-events b/hw/core/trace-events
1108
+ .name = TYPE_AW_SUN8I_EMAC,
1109
+ .parent = TYPE_SYS_BUS_DEVICE,
1110
+ .instance_size = sizeof(AwSun8iEmacState),
1111
+ .instance_init = allwinner_sun8i_emac_init,
1112
+ .class_init = allwinner_sun8i_emac_class_init,
1113
+};
1114
+
1115
+static void allwinner_sun8i_emac_register_types(void)
1116
+{
1117
+ type_register_static(&allwinner_sun8i_emac_info);
1118
+}
1119
+
1120
+type_init(allwinner_sun8i_emac_register_types)
1121
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
101
index XXXXXXX..XXXXXXX 100644
1122
index XXXXXXX..XXXXXXX 100644
102
--- a/hw/core/trace-events
1123
--- a/hw/arm/Kconfig
103
+++ b/hw/core/trace-events
1124
+++ b/hw/arm/Kconfig
1125
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10
1126
config ALLWINNER_H3
1127
bool
1128
select ALLWINNER_A10_PIT
1129
+ select ALLWINNER_SUN8I_EMAC
1130
select SERIAL
1131
select ARM_TIMER
1132
select ARM_GIC
1133
diff --git a/hw/net/Kconfig b/hw/net/Kconfig
1134
index XXXXXXX..XXXXXXX 100644
1135
--- a/hw/net/Kconfig
1136
+++ b/hw/net/Kconfig
1137
@@ -XXX,XX +XXX,XX @@ config MIPSNET
1138
config ALLWINNER_EMAC
1139
bool
1140
1141
+config ALLWINNER_SUN8I_EMAC
1142
+ bool
1143
+
1144
config IMX_FEC
1145
bool
1146
1147
diff --git a/hw/net/trace-events b/hw/net/trace-events
1148
index XXXXXXX..XXXXXXX 100644
1149
--- a/hw/net/trace-events
1150
+++ b/hw/net/trace-events
104
@@ -XXX,XX +XXX,XX @@
1151
@@ -XXX,XX +XXX,XX @@
105
# loader.c
1152
# See docs/devel/tracing.txt for syntax documentation.
106
loader_write_rom(const char *name, uint64_t gpa, uint64_t size, bool isrom) "%s: @0x%"PRIx64" size=0x%"PRIx64" ROM=%d"
1153
107
+
1154
+# allwinner-sun8i-emac.c
108
+# qdev.c
1155
+allwinner_sun8i_emac_mii_write_reg(uint32_t reg, uint32_t value) "MII write: reg=0x%" PRIx32 " value=0x%" PRIx32
109
+qdev_reset(void *obj, const char *objtype) "obj=%p(%s)"
1156
+allwinner_sun8i_emac_mii_read_reg(uint32_t reg, uint32_t value) "MII read: reg=0x%" PRIx32 " value=0x%" PRIx32
110
+qdev_reset_all(void *obj, const char *objtype) "obj=%p(%s)"
1157
+allwinner_sun8i_emac_receive(uint32_t desc, uint32_t paddr, uint32_t bytes) "RX packet: desc=0x%" PRIx32 " paddr=0x%" PRIx32 " bytes=%" PRIu32
111
+qdev_reset_tree(void *obj, const char *objtype) "obj=%p(%s)"
1158
+allwinner_sun8i_emac_transmit(uint32_t desc, uint32_t paddr, uint32_t bytes) "TX packet: desc=0x%" PRIx32 " paddr=0x%" PRIx32 " bytes=%" PRIu32
112
+qbus_reset(void *obj, const char *objtype) "obj=%p(%s)"
1159
+allwinner_sun8i_emac_reset(void) "HW reset"
113
+qbus_reset_all(void *obj, const char *objtype) "obj=%p(%s)"
1160
+allwinner_sun8i_emac_set_link(bool active) "Set link: active=%u"
114
+qbus_reset_tree(void *obj, const char *objtype) "obj=%p(%s)"
1161
+allwinner_sun8i_emac_read(uint64_t offset, uint64_t val) "MMIO read: offset=0x%" PRIx64 " value=0x%" PRIx64
115
+qdev_update_parent_bus(void *obj, const char *objtype, void *oldp, const char *oldptype, void *newp, const char *newptype) "obj=%p(%s) old_parent=%p(%s) new_parent=%p(%s)"
1162
+allwinner_sun8i_emac_write(uint64_t offset, uint64_t val) "MMIO write: offset=0x%" PRIx64 " value=0x%" PRIx64
1163
+
1164
# etraxfs_eth.c
1165
mdio_phy_read(int regnum, uint16_t value) "read phy_reg:%d value:0x%04x"
1166
mdio_phy_write(int regnum, uint16_t value) "write phy_reg:%d value:0x%04x"
116
--
1167
--
117
2.20.1
1168
2.20.1
118
1169
119
1170
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
This commit make use of the resettable API to reset the device being
3
A real Allwinner H3 SoC contains a Boot ROM which is the
4
hotplugged when it is realized. Also it ensures it is put in a reset
4
first code that runs right after the SoC is powered on.
5
state coherent with the parent it is plugged into.
5
The Boot ROM is responsible for loading user code (e.g. a bootloader)
6
from any of the supported external devices and writing the downloaded
7
code to internal SRAM. After loading the SoC begins executing the code
8
written to SRAM.
6
9
7
Note that there is a difference in the reset. Instead of resetting
10
This commits adds emulation of the Boot ROM firmware setup functionality
8
only the hotplugged device, we reset also its subtree (switch to
11
by loading user code from SD card in the A1 SRAM. While the A1 SRAM is
9
resettable API). This is not expected to be a problem because
12
64KiB, we limit the size to 32KiB because the real H3 Boot ROM also rejects
10
sub-buses are just realized too. If a hotplugged device has any
13
sizes larger than 32KiB. For reference, this behaviour is documented
11
sub-buses it is logical to reset them too at this point.
14
by the Linux Sunxi project wiki at:
12
15
13
The recently added should_be_hidden and PCI's partially_hotplugged
16
https://linux-sunxi.org/BROM#U-Boot_SPL_limitations
14
mechanisms do not interfere with realize operation:
15
+ In the should_be_hidden use case, device creation is
16
delayed.
17
+ The partially_hotplugged mechanism prevents a device to be
18
unplugged and unrealized from qdev POV and unrealized.
19
17
20
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
18
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
21
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
22
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
20
Message-id: 20200311221854.30370-11-nieklinnenbank@gmail.com
23
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
24
Message-id: 20200123132823.1117486-8-damien.hedde@greensocs.com
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
---
22
---
27
include/hw/resettable.h | 11 +++++++++++
23
include/hw/arm/allwinner-h3.h | 21 +++++++++++++++++++++
28
hw/core/qdev.c | 15 ++++++++++++++-
24
hw/arm/allwinner-h3.c | 17 +++++++++++++++++
29
2 files changed, 25 insertions(+), 1 deletion(-)
25
hw/arm/orangepi.c | 5 +++++
26
3 files changed, 43 insertions(+)
30
27
31
diff --git a/include/hw/resettable.h b/include/hw/resettable.h
28
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
32
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
33
--- a/include/hw/resettable.h
30
--- a/include/hw/arm/allwinner-h3.h
34
+++ b/include/hw/resettable.h
31
+++ b/include/hw/arm/allwinner-h3.h
35
@@ -XXX,XX +XXX,XX @@ struct ResettableState {
32
@@ -XXX,XX +XXX,XX @@
36
bool exit_phase_in_progress;
33
#include "hw/sd/allwinner-sdhost.h"
34
#include "hw/net/allwinner-sun8i-emac.h"
35
#include "target/arm/cpu.h"
36
+#include "sysemu/block-backend.h"
37
38
/**
39
* Allwinner H3 device list
40
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
41
MemoryRegion sram_c;
42
} AwH3State;
43
44
+/**
45
+ * Emulate Boot ROM firmware setup functionality.
46
+ *
47
+ * A real Allwinner H3 SoC contains a Boot ROM
48
+ * which is the first code that runs right after
49
+ * the SoC is powered on. The Boot ROM is responsible
50
+ * for loading user code (e.g. a bootloader) from any
51
+ * of the supported external devices and writing the
52
+ * downloaded code to internal SRAM. After loading the SoC
53
+ * begins executing the code written to SRAM.
54
+ *
55
+ * This function emulates the Boot ROM by copying 32 KiB
56
+ * of data from the given block device and writes it to
57
+ * the start of the first internal SRAM memory.
58
+ *
59
+ * @s: Allwinner H3 state object pointer
60
+ * @blk: Block backend device object pointer
61
+ */
62
+void allwinner_h3_bootrom_setup(AwH3State *s, BlockBackend *blk);
63
+
64
#endif /* HW_ARM_ALLWINNER_H3_H */
65
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/hw/arm/allwinner-h3.c
68
+++ b/hw/arm/allwinner-h3.c
69
@@ -XXX,XX +XXX,XX @@
70
#include "hw/char/serial.h"
71
#include "hw/misc/unimp.h"
72
#include "hw/usb/hcd-ehci.h"
73
+#include "hw/loader.h"
74
#include "sysemu/sysemu.h"
75
#include "hw/arm/allwinner-h3.h"
76
77
@@ -XXX,XX +XXX,XX @@ enum {
78
AW_H3_GIC_NUM_SPI = 128
37
};
79
};
38
80
39
+/**
81
+void allwinner_h3_bootrom_setup(AwH3State *s, BlockBackend *blk)
40
+ * resettable_state_clear:
41
+ * Clear the state. It puts the state to the initial (zeroed) state required
42
+ * to reuse an object. Typically used in realize step of base classes
43
+ * implementing the interface.
44
+ */
45
+static inline void resettable_state_clear(ResettableState *state)
46
+{
82
+{
47
+ memset(state, 0, sizeof(ResettableState));
83
+ const int64_t rom_size = 32 * KiB;
84
+ g_autofree uint8_t *buffer = g_new0(uint8_t, rom_size);
85
+
86
+ if (blk_pread(blk, 8 * KiB, buffer, rom_size) < 0) {
87
+ error_setg(&error_fatal, "%s: failed to read BlockBackend data",
88
+ __func__);
89
+ return;
90
+ }
91
+
92
+ rom_add_blob("allwinner-h3.bootrom", buffer, rom_size,
93
+ rom_size, s->memmap[AW_H3_SRAM_A1],
94
+ NULL, NULL, NULL, NULL, false);
48
+}
95
+}
49
+
96
+
50
/**
97
static void allwinner_h3_init(Object *obj)
51
* resettable_reset:
98
{
52
* Trigger a reset on an object @obj of type @type. @obj must implement
99
AwH3State *s = AW_H3(obj);
53
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
100
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
54
index XXXXXXX..XXXXXXX 100644
101
index XXXXXXX..XXXXXXX 100644
55
--- a/hw/core/qdev.c
102
--- a/hw/arm/orangepi.c
56
+++ b/hw/core/qdev.c
103
+++ b/hw/arm/orangepi.c
57
@@ -XXX,XX +XXX,XX @@ static void device_set_realized(Object *obj, bool value, Error **errp)
104
@@ -XXX,XX +XXX,XX @@ static void orangepi_init(MachineState *machine)
58
}
105
memory_region_add_subregion(get_system_memory(), h3->memmap[AW_H3_SDRAM],
59
}
106
machine->ram);
60
107
61
+ /*
108
+ /* Load target kernel or start using BootROM */
62
+ * Clear the reset state, in case the object was previously unrealized
109
+ if (!machine->kernel_filename && blk_is_available(blk)) {
63
+ * with a dirty state.
110
+ /* Use Boot ROM to copy data from SD card to SRAM */
64
+ */
111
+ allwinner_h3_bootrom_setup(h3, blk);
65
+ resettable_state_clear(&dev->reset);
112
+ }
66
+
113
orangepi_binfo.loader_start = h3->memmap[AW_H3_SDRAM];
67
QLIST_FOREACH(bus, &dev->child_bus, sibling) {
114
orangepi_binfo.ram_size = machine->ram_size;
68
object_property_set_bool(OBJECT(bus), true, "realized",
115
arm_load_kernel(ARM_CPU(first_cpu), machine, &orangepi_binfo);
69
&local_err);
70
@@ -XXX,XX +XXX,XX @@ static void device_set_realized(Object *obj, bool value, Error **errp)
71
}
72
}
73
if (dev->hotplugged) {
74
- device_legacy_reset(dev);
75
+ /*
76
+ * Reset the device, as well as its subtree which, at this point,
77
+ * should be realized too.
78
+ */
79
+ resettable_assert_reset(OBJECT(dev), RESET_TYPE_COLD);
80
+ resettable_change_parent(OBJECT(dev), OBJECT(dev->parent_bus),
81
+ NULL);
82
+ resettable_release_reset(OBJECT(dev), RESET_TYPE_COLD);
83
}
84
dev->pending_deleted_event = false;
85
86
--
116
--
87
2.20.1
117
2.20.1
88
118
89
119
diff view generated by jsdifflib
1
From: Joel Stanley <joel@jms.id.au>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Following the pattern of the work recently done with the ASPEED GPIO
3
In the Allwinner H3 SoC the SDRAM controller is responsible
4
model, this adds support for inspecting and modifying the PCA9552 LEDs
4
for interfacing with the external Synchronous Dynamic Random
5
from the monitor.
5
Access Memory (SDRAM). Types of memory that the SDRAM controller
6
supports are DDR2/DDR3 and capacities of up to 2GiB. This commit
7
adds emulation support of the Allwinner H3 SDRAM controller.
6
8
7
(qemu) qom-set /machine/unattached/device[17] led0 on
9
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
8
(qemu) qom-set /machine/unattached/device[17] led0 off
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
(qemu) qom-set /machine/unattached/device[17] led0 pwm0
11
Message-id: 20200311221854.30370-12-nieklinnenbank@gmail.com
10
(qemu) qom-set /machine/unattached/device[17] led0 pwm1
11
12
Signed-off-by: Joel Stanley <joel@jms.id.au>
13
Signed-off-by: Cédric Le Goater <clg@kaod.org>
14
Message-id: 20200114103433.30534-6-clg@kaod.org
15
[clg: - removed the "qom-get" examples from the commit log
16
- merged memory leak fixes from Joel ]
17
Signed-off-by: Cédric Le Goater <clg@kaod.org>
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
13
---
21
hw/misc/pca9552.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++
14
hw/misc/Makefile.objs | 1 +
22
1 file changed, 90 insertions(+)
15
include/hw/arm/allwinner-h3.h | 5 +
16
include/hw/misc/allwinner-h3-dramc.h | 106 ++++++++
17
hw/arm/allwinner-h3.c | 19 +-
18
hw/arm/orangepi.c | 6 +
19
hw/misc/allwinner-h3-dramc.c | 358 +++++++++++++++++++++++++++
20
hw/misc/trace-events | 10 +
21
7 files changed, 502 insertions(+), 3 deletions(-)
22
create mode 100644 include/hw/misc/allwinner-h3-dramc.h
23
create mode 100644 hw/misc/allwinner-h3-dramc.c
23
24
24
diff --git a/hw/misc/pca9552.c b/hw/misc/pca9552.c
25
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
25
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/misc/pca9552.c
27
--- a/hw/misc/Makefile.objs
27
+++ b/hw/misc/pca9552.c
28
+++ b/hw/misc/Makefile.objs
29
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_IVSHMEM_DEVICE) += ivshmem.o
30
31
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-ccu.o
32
obj-$(CONFIG_ALLWINNER_H3) += allwinner-cpucfg.o
33
+common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-dramc.o
34
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-h3-sysctrl.o
35
common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-sid.o
36
common-obj-$(CONFIG_REALVIEW) += arm_sysctl.o
37
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
38
index XXXXXXX..XXXXXXX 100644
39
--- a/include/hw/arm/allwinner-h3.h
40
+++ b/include/hw/arm/allwinner-h3.h
28
@@ -XXX,XX +XXX,XX @@
41
@@ -XXX,XX +XXX,XX @@
29
#include "hw/misc/pca9552.h"
42
#include "hw/intc/arm_gic.h"
30
#include "hw/misc/pca9552_regs.h"
43
#include "hw/misc/allwinner-h3-ccu.h"
31
#include "migration/vmstate.h"
44
#include "hw/misc/allwinner-cpucfg.h"
45
+#include "hw/misc/allwinner-h3-dramc.h"
46
#include "hw/misc/allwinner-h3-sysctrl.h"
47
#include "hw/misc/allwinner-sid.h"
48
#include "hw/sd/allwinner-sdhost.h"
49
@@ -XXX,XX +XXX,XX @@ enum {
50
AW_H3_UART2,
51
AW_H3_UART3,
52
AW_H3_EMAC,
53
+ AW_H3_DRAMCOM,
54
+ AW_H3_DRAMCTL,
55
+ AW_H3_DRAMPHY,
56
AW_H3_GIC_DIST,
57
AW_H3_GIC_CPU,
58
AW_H3_GIC_HYP,
59
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
60
AwA10PITState timer;
61
AwH3ClockCtlState ccu;
62
AwCpuCfgState cpucfg;
63
+ AwH3DramCtlState dramc;
64
AwH3SysCtrlState sysctrl;
65
AwSidState sid;
66
AwSdHostState mmc0;
67
diff --git a/include/hw/misc/allwinner-h3-dramc.h b/include/hw/misc/allwinner-h3-dramc.h
68
new file mode 100644
69
index XXXXXXX..XXXXXXX
70
--- /dev/null
71
+++ b/include/hw/misc/allwinner-h3-dramc.h
72
@@ -XXX,XX +XXX,XX @@
73
+/*
74
+ * Allwinner H3 SDRAM Controller emulation
75
+ *
76
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
77
+ *
78
+ * This program is free software: you can redistribute it and/or modify
79
+ * it under the terms of the GNU General Public License as published by
80
+ * the Free Software Foundation, either version 2 of the License, or
81
+ * (at your option) any later version.
82
+ *
83
+ * This program is distributed in the hope that it will be useful,
84
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
85
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
86
+ * GNU General Public License for more details.
87
+ *
88
+ * You should have received a copy of the GNU General Public License
89
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
90
+ */
91
+
92
+#ifndef HW_MISC_ALLWINNER_H3_DRAMC_H
93
+#define HW_MISC_ALLWINNER_H3_DRAMC_H
94
+
95
+#include "qom/object.h"
96
+#include "hw/sysbus.h"
97
+#include "exec/hwaddr.h"
98
+
99
+/**
100
+ * Constants
101
+ * @{
102
+ */
103
+
104
+/** Highest register address used by DRAMCOM module */
105
+#define AW_H3_DRAMCOM_REGS_MAXADDR (0x804)
106
+
107
+/** Total number of known DRAMCOM registers */
108
+#define AW_H3_DRAMCOM_REGS_NUM (AW_H3_DRAMCOM_REGS_MAXADDR / \
109
+ sizeof(uint32_t))
110
+
111
+/** Highest register address used by DRAMCTL module */
112
+#define AW_H3_DRAMCTL_REGS_MAXADDR (0x88c)
113
+
114
+/** Total number of known DRAMCTL registers */
115
+#define AW_H3_DRAMCTL_REGS_NUM (AW_H3_DRAMCTL_REGS_MAXADDR / \
116
+ sizeof(uint32_t))
117
+
118
+/** Highest register address used by DRAMPHY module */
119
+#define AW_H3_DRAMPHY_REGS_MAXADDR (0x4)
120
+
121
+/** Total number of known DRAMPHY registers */
122
+#define AW_H3_DRAMPHY_REGS_NUM (AW_H3_DRAMPHY_REGS_MAXADDR / \
123
+ sizeof(uint32_t))
124
+
125
+/** @} */
126
+
127
+/**
128
+ * Object model
129
+ * @{
130
+ */
131
+
132
+#define TYPE_AW_H3_DRAMC "allwinner-h3-dramc"
133
+#define AW_H3_DRAMC(obj) \
134
+ OBJECT_CHECK(AwH3DramCtlState, (obj), TYPE_AW_H3_DRAMC)
135
+
136
+/** @} */
137
+
138
+/**
139
+ * Allwinner H3 SDRAM Controller object instance state.
140
+ */
141
+typedef struct AwH3DramCtlState {
142
+ /*< private >*/
143
+ SysBusDevice parent_obj;
144
+ /*< public >*/
145
+
146
+ /** Physical base address for start of RAM */
147
+ hwaddr ram_addr;
148
+
149
+ /** Total RAM size in megabytes */
150
+ uint32_t ram_size;
151
+
152
+ /**
153
+ * @name Memory Regions
154
+ * @{
155
+ */
156
+
157
+ MemoryRegion row_mirror; /**< Simulates rows for RAM size detection */
158
+ MemoryRegion row_mirror_alias; /**< Alias of the row which is mirrored */
159
+ MemoryRegion dramcom_iomem; /**< DRAMCOM module I/O registers */
160
+ MemoryRegion dramctl_iomem; /**< DRAMCTL module I/O registers */
161
+ MemoryRegion dramphy_iomem; /**< DRAMPHY module I/O registers */
162
+
163
+ /** @} */
164
+
165
+ /**
166
+ * @name Hardware Registers
167
+ * @{
168
+ */
169
+
170
+ uint32_t dramcom[AW_H3_DRAMCOM_REGS_NUM]; /**< Array of DRAMCOM registers */
171
+ uint32_t dramctl[AW_H3_DRAMCTL_REGS_NUM]; /**< Array of DRAMCTL registers */
172
+ uint32_t dramphy[AW_H3_DRAMPHY_REGS_NUM] ;/**< Array of DRAMPHY registers */
173
+
174
+ /** @} */
175
+
176
+} AwH3DramCtlState;
177
+
178
+#endif /* HW_MISC_ALLWINNER_H3_DRAMC_H */
179
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
180
index XXXXXXX..XXXXXXX 100644
181
--- a/hw/arm/allwinner-h3.c
182
+++ b/hw/arm/allwinner-h3.c
183
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
184
[AW_H3_UART2] = 0x01c28800,
185
[AW_H3_UART3] = 0x01c28c00,
186
[AW_H3_EMAC] = 0x01c30000,
187
+ [AW_H3_DRAMCOM] = 0x01c62000,
188
+ [AW_H3_DRAMCTL] = 0x01c63000,
189
+ [AW_H3_DRAMPHY] = 0x01c65000,
190
[AW_H3_GIC_DIST] = 0x01c81000,
191
[AW_H3_GIC_CPU] = 0x01c82000,
192
[AW_H3_GIC_HYP] = 0x01c84000,
193
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
194
{ "scr", 0x01c2c400, 1 * KiB },
195
{ "gpu", 0x01c40000, 64 * KiB },
196
{ "hstmr", 0x01c60000, 4 * KiB },
197
- { "dramcom", 0x01c62000, 4 * KiB },
198
- { "dramctl0", 0x01c63000, 4 * KiB },
199
- { "dramphy0", 0x01c65000, 4 * KiB },
200
{ "spi0", 0x01c68000, 4 * KiB },
201
{ "spi1", 0x01c69000, 4 * KiB },
202
{ "csi", 0x01cb0000, 320 * KiB },
203
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
204
205
sysbus_init_child_obj(obj, "emac", &s->emac, sizeof(s->emac),
206
TYPE_AW_SUN8I_EMAC);
207
+
208
+ sysbus_init_child_obj(obj, "dramc", &s->dramc, sizeof(s->dramc),
209
+ TYPE_AW_H3_DRAMC);
210
+ object_property_add_alias(obj, "ram-addr", OBJECT(&s->dramc),
211
+ "ram-addr", &error_abort);
212
+ object_property_add_alias(obj, "ram-size", OBJECT(&s->dramc),
213
+ "ram-size", &error_abort);
214
}
215
216
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
217
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
218
qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_UART3),
219
115200, serial_hd(3), DEVICE_NATIVE_ENDIAN);
220
221
+ /* DRAMC */
222
+ qdev_init_nofail(DEVICE(&s->dramc));
223
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 0, s->memmap[AW_H3_DRAMCOM]);
224
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 1, s->memmap[AW_H3_DRAMCTL]);
225
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 2, s->memmap[AW_H3_DRAMPHY]);
226
+
227
/* Unimplemented devices */
228
for (i = 0; i < ARRAY_SIZE(unimplemented); i++) {
229
create_unimplemented_device(unimplemented[i].device_name,
230
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
231
index XXXXXXX..XXXXXXX 100644
232
--- a/hw/arm/orangepi.c
233
+++ b/hw/arm/orangepi.c
234
@@ -XXX,XX +XXX,XX @@ static void orangepi_init(MachineState *machine)
235
/* Setup EMAC properties */
236
object_property_set_int(OBJECT(&h3->emac), 1, "phy-addr", &error_abort);
237
238
+ /* DRAMC */
239
+ object_property_set_uint(OBJECT(h3), h3->memmap[AW_H3_SDRAM],
240
+ "ram-addr", &error_abort);
241
+ object_property_set_int(OBJECT(h3), machine->ram_size / MiB, "ram-size",
242
+ &error_abort);
243
+
244
/* Mark H3 object realized */
245
object_property_set_bool(OBJECT(h3), true, "realized", &error_abort);
246
247
diff --git a/hw/misc/allwinner-h3-dramc.c b/hw/misc/allwinner-h3-dramc.c
248
new file mode 100644
249
index XXXXXXX..XXXXXXX
250
--- /dev/null
251
+++ b/hw/misc/allwinner-h3-dramc.c
252
@@ -XXX,XX +XXX,XX @@
253
+/*
254
+ * Allwinner H3 SDRAM Controller emulation
255
+ *
256
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
257
+ *
258
+ * This program is free software: you can redistribute it and/or modify
259
+ * it under the terms of the GNU General Public License as published by
260
+ * the Free Software Foundation, either version 2 of the License, or
261
+ * (at your option) any later version.
262
+ *
263
+ * This program is distributed in the hope that it will be useful,
264
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
265
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
266
+ * GNU General Public License for more details.
267
+ *
268
+ * You should have received a copy of the GNU General Public License
269
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
270
+ */
271
+
272
+#include "qemu/osdep.h"
273
+#include "qemu/units.h"
274
+#include "qemu/error-report.h"
275
+#include "hw/sysbus.h"
276
+#include "migration/vmstate.h"
277
+#include "qemu/log.h"
278
+#include "qemu/module.h"
279
+#include "exec/address-spaces.h"
280
+#include "hw/qdev-properties.h"
32
+#include "qapi/error.h"
281
+#include "qapi/error.h"
33
+#include "qapi/visitor.h"
282
+#include "hw/misc/allwinner-h3-dramc.h"
34
283
+#include "trace.h"
35
#define PCA9552_LED_ON 0x0
284
+
36
#define PCA9552_LED_OFF 0x1
285
+#define REG_INDEX(offset) (offset / sizeof(uint32_t))
37
#define PCA9552_LED_PWM0 0x2
286
+
38
#define PCA9552_LED_PWM1 0x3
287
+/* DRAMCOM register offsets */
39
288
+enum {
40
+static const char *led_state[] = {"on", "off", "pwm0", "pwm1"};
289
+ REG_DRAMCOM_CR = 0x0000, /* Control Register */
41
+
290
+};
42
static uint8_t pca9552_pin_get_config(PCA9552State *s, int pin)
291
+
43
{
292
+/* DRAMCTL register offsets */
44
uint8_t reg = PCA9552_LS0 + (pin / 4);
293
+enum {
45
@@ -XXX,XX +XXX,XX @@ static int pca9552_event(I2CSlave *i2c, enum i2c_event event)
294
+ REG_DRAMCTL_PIR = 0x0000, /* PHY Initialization Register */
46
return 0;
295
+ REG_DRAMCTL_PGSR = 0x0010, /* PHY General Status Register */
47
}
296
+ REG_DRAMCTL_STATR = 0x0018, /* Status Register */
48
297
+};
49
+static void pca9552_get_led(Object *obj, Visitor *v, const char *name,
298
+
50
+ void *opaque, Error **errp)
299
+/* DRAMCTL register flags */
51
+{
300
+enum {
52
+ PCA9552State *s = PCA9552(obj);
301
+ REG_DRAMCTL_PGSR_INITDONE = (1 << 0),
53
+ int led, rc, reg;
302
+};
54
+ uint8_t state;
303
+
55
+
304
+enum {
56
+ rc = sscanf(name, "led%2d", &led);
305
+ REG_DRAMCTL_STATR_ACTIVE = (1 << 0),
57
+ if (rc != 1) {
306
+};
58
+ error_setg(errp, "%s: error reading %s", __func__, name);
307
+
59
+ return;
308
+static void allwinner_h3_dramc_map_rows(AwH3DramCtlState *s, uint8_t row_bits,
60
+ }
309
+ uint8_t bank_bits, uint16_t page_size)
61
+ if (led < 0 || led > s->nr_leds) {
310
+{
62
+ error_setg(errp, "%s invalid led %s", __func__, name);
63
+ return;
64
+ }
65
+ /*
311
+ /*
66
+ * Get the LSx register as the qom interface should expose the device
312
+ * This function simulates row addressing behavior when bootloader
67
+ * state, not the modeled 'input line' behaviour which would come from
313
+ * software attempts to detect the amount of available SDRAM. In U-Boot
68
+ * reading the INPUTx reg
314
+ * the controller is configured with the widest row addressing available.
315
+ * Then a pattern is written to RAM at an offset on the row boundary size.
316
+ * If the value read back equals the value read back from the
317
+ * start of RAM, the bootloader knows the amount of row bits.
318
+ *
319
+ * This function inserts a mirrored memory region when the configured row
320
+ * bits are not matching the actual emulated memory, to simulate the
321
+ * same behavior on hardware as expected by the bootloader.
69
+ */
322
+ */
70
+ reg = PCA9552_LS0 + led / 4;
323
+ uint8_t row_bits_actual = 0;
71
+ state = (pca9552_read(s, reg) >> (led % 8)) & 0x3;
324
+
72
+ visit_type_str(v, name, (char **)&led_state[state], errp);
325
+ /* Calculate the actual row bits using the ram_size property */
73
+}
326
+ for (uint8_t i = 8; i < 12; i++) {
74
+
327
+ if (1 << i == s->ram_size) {
75
+/*
328
+ row_bits_actual = i + 3;
76
+ * Return an LED selector register value based on an existing one, with
77
+ * the appropriate 2-bit state value set for the given LED number (0-3).
78
+ */
79
+static inline uint8_t pca955x_ledsel(uint8_t oldval, int led_num, int state)
80
+{
81
+ return (oldval & (~(0x3 << (led_num << 1)))) |
82
+ ((state & 0x3) << (led_num << 1));
83
+}
84
+
85
+static void pca9552_set_led(Object *obj, Visitor *v, const char *name,
86
+ void *opaque, Error **errp)
87
+{
88
+ PCA9552State *s = PCA9552(obj);
89
+ Error *local_err = NULL;
90
+ int led, rc, reg, val;
91
+ uint8_t state;
92
+ char *state_str;
93
+
94
+ visit_type_str(v, name, &state_str, &local_err);
95
+ if (local_err) {
96
+ error_propagate(errp, local_err);
97
+ return;
98
+ }
99
+ rc = sscanf(name, "led%2d", &led);
100
+ if (rc != 1) {
101
+ error_setg(errp, "%s: error reading %s", __func__, name);
102
+ return;
103
+ }
104
+ if (led < 0 || led > s->nr_leds) {
105
+ error_setg(errp, "%s invalid led %s", __func__, name);
106
+ return;
107
+ }
108
+
109
+ for (state = 0; state < ARRAY_SIZE(led_state); state++) {
110
+ if (!strcmp(state_str, led_state[state])) {
111
+ break;
329
+ break;
112
+ }
330
+ }
113
+ }
331
+ }
114
+ if (state >= ARRAY_SIZE(led_state)) {
332
+
115
+ error_setg(errp, "%s invalid led state %s", __func__, state_str);
333
+ if (s->ram_size == (1 << (row_bits - 3))) {
334
+ /* When row bits is the expected value, remove the mirror */
335
+ memory_region_set_enabled(&s->row_mirror_alias, false);
336
+ trace_allwinner_h3_dramc_rowmirror_disable();
337
+
338
+ } else if (row_bits_actual) {
339
+ /* Row bits not matching ram_size, install the rows mirror */
340
+ hwaddr row_mirror = s->ram_addr + ((1 << (row_bits_actual +
341
+ bank_bits)) * page_size);
342
+
343
+ memory_region_set_enabled(&s->row_mirror_alias, true);
344
+ memory_region_set_address(&s->row_mirror_alias, row_mirror);
345
+
346
+ trace_allwinner_h3_dramc_rowmirror_enable(row_mirror);
347
+ }
348
+}
349
+
350
+static uint64_t allwinner_h3_dramcom_read(void *opaque, hwaddr offset,
351
+ unsigned size)
352
+{
353
+ const AwH3DramCtlState *s = AW_H3_DRAMC(opaque);
354
+ const uint32_t idx = REG_INDEX(offset);
355
+
356
+ if (idx >= AW_H3_DRAMCOM_REGS_NUM) {
357
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
358
+ __func__, (uint32_t)offset);
359
+ return 0;
360
+ }
361
+
362
+ trace_allwinner_h3_dramcom_read(offset, s->dramcom[idx], size);
363
+
364
+ return s->dramcom[idx];
365
+}
366
+
367
+static void allwinner_h3_dramcom_write(void *opaque, hwaddr offset,
368
+ uint64_t val, unsigned size)
369
+{
370
+ AwH3DramCtlState *s = AW_H3_DRAMC(opaque);
371
+ const uint32_t idx = REG_INDEX(offset);
372
+
373
+ trace_allwinner_h3_dramcom_write(offset, val, size);
374
+
375
+ if (idx >= AW_H3_DRAMCOM_REGS_NUM) {
376
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
377
+ __func__, (uint32_t)offset);
116
+ return;
378
+ return;
117
+ }
379
+ }
118
+
380
+
119
+ reg = PCA9552_LS0 + led / 4;
381
+ switch (offset) {
120
+ val = pca9552_read(s, reg);
382
+ case REG_DRAMCOM_CR: /* Control Register */
121
+ val = pca955x_ledsel(val, led % 4, state);
383
+ allwinner_h3_dramc_map_rows(s, ((val >> 4) & 0xf) + 1,
122
+ pca9552_write(s, reg, val);
384
+ ((val >> 2) & 0x1) + 2,
123
+}
385
+ 1 << (((val >> 8) & 0xf) + 3));
124
+
386
+ break;
125
static const VMStateDescription pca9552_vmstate = {
387
+ default:
126
.name = "PCA9552",
388
+ break;
127
.version_id = 0,
389
+ };
128
@@ -XXX,XX +XXX,XX @@ static void pca9552_reset(DeviceState *dev)
390
+
129
static void pca9552_initfn(Object *obj)
391
+ s->dramcom[idx] = (uint32_t) val;
130
{
392
+}
131
PCA9552State *s = PCA9552(obj);
393
+
132
+ int led;
394
+static uint64_t allwinner_h3_dramctl_read(void *opaque, hwaddr offset,
133
395
+ unsigned size)
134
/* If support for the other PCA955X devices are implemented, these
396
+{
135
* constant values might be part of class structure describing the
397
+ const AwH3DramCtlState *s = AW_H3_DRAMC(opaque);
136
@@ -XXX,XX +XXX,XX @@ static void pca9552_initfn(Object *obj)
398
+ const uint32_t idx = REG_INDEX(offset);
137
*/
399
+
138
s->max_reg = PCA9552_LS3;
400
+ if (idx >= AW_H3_DRAMCTL_REGS_NUM) {
139
s->nr_leds = 16;
401
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
140
+
402
+ __func__, (uint32_t)offset);
141
+ for (led = 0; led < s->nr_leds; led++) {
403
+ return 0;
142
+ char *name;
404
+ }
143
+
405
+
144
+ name = g_strdup_printf("led%d", led);
406
+ trace_allwinner_h3_dramctl_read(offset, s->dramctl[idx], size);
145
+ object_property_add(obj, name, "bool", pca9552_get_led, pca9552_set_led,
407
+
146
+ NULL, NULL, NULL);
408
+ return s->dramctl[idx];
147
+ g_free(name);
409
+}
148
+ }
410
+
149
}
411
+static void allwinner_h3_dramctl_write(void *opaque, hwaddr offset,
150
412
+ uint64_t val, unsigned size)
151
static void pca9552_class_init(ObjectClass *klass, void *data)
413
+{
414
+ AwH3DramCtlState *s = AW_H3_DRAMC(opaque);
415
+ const uint32_t idx = REG_INDEX(offset);
416
+
417
+ trace_allwinner_h3_dramctl_write(offset, val, size);
418
+
419
+ if (idx >= AW_H3_DRAMCTL_REGS_NUM) {
420
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
421
+ __func__, (uint32_t)offset);
422
+ return;
423
+ }
424
+
425
+ switch (offset) {
426
+ case REG_DRAMCTL_PIR: /* PHY Initialization Register */
427
+ s->dramctl[REG_INDEX(REG_DRAMCTL_PGSR)] |= REG_DRAMCTL_PGSR_INITDONE;
428
+ s->dramctl[REG_INDEX(REG_DRAMCTL_STATR)] |= REG_DRAMCTL_STATR_ACTIVE;
429
+ break;
430
+ default:
431
+ break;
432
+ }
433
+
434
+ s->dramctl[idx] = (uint32_t) val;
435
+}
436
+
437
+static uint64_t allwinner_h3_dramphy_read(void *opaque, hwaddr offset,
438
+ unsigned size)
439
+{
440
+ const AwH3DramCtlState *s = AW_H3_DRAMC(opaque);
441
+ const uint32_t idx = REG_INDEX(offset);
442
+
443
+ if (idx >= AW_H3_DRAMPHY_REGS_NUM) {
444
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
445
+ __func__, (uint32_t)offset);
446
+ return 0;
447
+ }
448
+
449
+ trace_allwinner_h3_dramphy_read(offset, s->dramphy[idx], size);
450
+
451
+ return s->dramphy[idx];
452
+}
453
+
454
+static void allwinner_h3_dramphy_write(void *opaque, hwaddr offset,
455
+ uint64_t val, unsigned size)
456
+{
457
+ AwH3DramCtlState *s = AW_H3_DRAMC(opaque);
458
+ const uint32_t idx = REG_INDEX(offset);
459
+
460
+ trace_allwinner_h3_dramphy_write(offset, val, size);
461
+
462
+ if (idx >= AW_H3_DRAMPHY_REGS_NUM) {
463
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
464
+ __func__, (uint32_t)offset);
465
+ return;
466
+ }
467
+
468
+ s->dramphy[idx] = (uint32_t) val;
469
+}
470
+
471
+static const MemoryRegionOps allwinner_h3_dramcom_ops = {
472
+ .read = allwinner_h3_dramcom_read,
473
+ .write = allwinner_h3_dramcom_write,
474
+ .endianness = DEVICE_NATIVE_ENDIAN,
475
+ .valid = {
476
+ .min_access_size = 4,
477
+ .max_access_size = 4,
478
+ },
479
+ .impl.min_access_size = 4,
480
+};
481
+
482
+static const MemoryRegionOps allwinner_h3_dramctl_ops = {
483
+ .read = allwinner_h3_dramctl_read,
484
+ .write = allwinner_h3_dramctl_write,
485
+ .endianness = DEVICE_NATIVE_ENDIAN,
486
+ .valid = {
487
+ .min_access_size = 4,
488
+ .max_access_size = 4,
489
+ },
490
+ .impl.min_access_size = 4,
491
+};
492
+
493
+static const MemoryRegionOps allwinner_h3_dramphy_ops = {
494
+ .read = allwinner_h3_dramphy_read,
495
+ .write = allwinner_h3_dramphy_write,
496
+ .endianness = DEVICE_NATIVE_ENDIAN,
497
+ .valid = {
498
+ .min_access_size = 4,
499
+ .max_access_size = 4,
500
+ },
501
+ .impl.min_access_size = 4,
502
+};
503
+
504
+static void allwinner_h3_dramc_reset(DeviceState *dev)
505
+{
506
+ AwH3DramCtlState *s = AW_H3_DRAMC(dev);
507
+
508
+ /* Set default values for registers */
509
+ memset(&s->dramcom, 0, sizeof(s->dramcom));
510
+ memset(&s->dramctl, 0, sizeof(s->dramctl));
511
+ memset(&s->dramphy, 0, sizeof(s->dramphy));
512
+}
513
+
514
+static void allwinner_h3_dramc_realize(DeviceState *dev, Error **errp)
515
+{
516
+ AwH3DramCtlState *s = AW_H3_DRAMC(dev);
517
+
518
+ /* Only power of 2 RAM sizes from 256MiB up to 2048MiB are supported */
519
+ for (uint8_t i = 8; i < 13; i++) {
520
+ if (1 << i == s->ram_size) {
521
+ break;
522
+ } else if (i == 12) {
523
+ error_report("%s: ram-size %u MiB is not supported",
524
+ __func__, s->ram_size);
525
+ exit(1);
526
+ }
527
+ }
528
+
529
+ /* Setup row mirror mappings */
530
+ memory_region_init_ram(&s->row_mirror, OBJECT(s),
531
+ "allwinner-h3-dramc.row-mirror",
532
+ 4 * KiB, &error_abort);
533
+ memory_region_add_subregion_overlap(get_system_memory(), s->ram_addr,
534
+ &s->row_mirror, 10);
535
+
536
+ memory_region_init_alias(&s->row_mirror_alias, OBJECT(s),
537
+ "allwinner-h3-dramc.row-mirror-alias",
538
+ &s->row_mirror, 0, 4 * KiB);
539
+ memory_region_add_subregion_overlap(get_system_memory(),
540
+ s->ram_addr + 1 * MiB,
541
+ &s->row_mirror_alias, 10);
542
+ memory_region_set_enabled(&s->row_mirror_alias, false);
543
+}
544
+
545
+static void allwinner_h3_dramc_init(Object *obj)
546
+{
547
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
548
+ AwH3DramCtlState *s = AW_H3_DRAMC(obj);
549
+
550
+ /* DRAMCOM registers */
551
+ memory_region_init_io(&s->dramcom_iomem, OBJECT(s),
552
+ &allwinner_h3_dramcom_ops, s,
553
+ TYPE_AW_H3_DRAMC, 4 * KiB);
554
+ sysbus_init_mmio(sbd, &s->dramcom_iomem);
555
+
556
+ /* DRAMCTL registers */
557
+ memory_region_init_io(&s->dramctl_iomem, OBJECT(s),
558
+ &allwinner_h3_dramctl_ops, s,
559
+ TYPE_AW_H3_DRAMC, 4 * KiB);
560
+ sysbus_init_mmio(sbd, &s->dramctl_iomem);
561
+
562
+ /* DRAMPHY registers */
563
+ memory_region_init_io(&s->dramphy_iomem, OBJECT(s),
564
+ &allwinner_h3_dramphy_ops, s,
565
+ TYPE_AW_H3_DRAMC, 4 * KiB);
566
+ sysbus_init_mmio(sbd, &s->dramphy_iomem);
567
+}
568
+
569
+static Property allwinner_h3_dramc_properties[] = {
570
+ DEFINE_PROP_UINT64("ram-addr", AwH3DramCtlState, ram_addr, 0x0),
571
+ DEFINE_PROP_UINT32("ram-size", AwH3DramCtlState, ram_size, 256 * MiB),
572
+ DEFINE_PROP_END_OF_LIST()
573
+};
574
+
575
+static const VMStateDescription allwinner_h3_dramc_vmstate = {
576
+ .name = "allwinner-h3-dramc",
577
+ .version_id = 1,
578
+ .minimum_version_id = 1,
579
+ .fields = (VMStateField[]) {
580
+ VMSTATE_UINT32_ARRAY(dramcom, AwH3DramCtlState, AW_H3_DRAMCOM_REGS_NUM),
581
+ VMSTATE_UINT32_ARRAY(dramctl, AwH3DramCtlState, AW_H3_DRAMCTL_REGS_NUM),
582
+ VMSTATE_UINT32_ARRAY(dramphy, AwH3DramCtlState, AW_H3_DRAMPHY_REGS_NUM),
583
+ VMSTATE_END_OF_LIST()
584
+ }
585
+};
586
+
587
+static void allwinner_h3_dramc_class_init(ObjectClass *klass, void *data)
588
+{
589
+ DeviceClass *dc = DEVICE_CLASS(klass);
590
+
591
+ dc->reset = allwinner_h3_dramc_reset;
592
+ dc->vmsd = &allwinner_h3_dramc_vmstate;
593
+ dc->realize = allwinner_h3_dramc_realize;
594
+ device_class_set_props(dc, allwinner_h3_dramc_properties);
595
+}
596
+
597
+static const TypeInfo allwinner_h3_dramc_info = {
598
+ .name = TYPE_AW_H3_DRAMC,
599
+ .parent = TYPE_SYS_BUS_DEVICE,
600
+ .instance_init = allwinner_h3_dramc_init,
601
+ .instance_size = sizeof(AwH3DramCtlState),
602
+ .class_init = allwinner_h3_dramc_class_init,
603
+};
604
+
605
+static void allwinner_h3_dramc_register(void)
606
+{
607
+ type_register_static(&allwinner_h3_dramc_info);
608
+}
609
+
610
+type_init(allwinner_h3_dramc_register)
611
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
612
index XXXXXXX..XXXXXXX 100644
613
--- a/hw/misc/trace-events
614
+++ b/hw/misc/trace-events
615
@@ -XXX,XX +XXX,XX @@ allwinner_cpucfg_cpu_reset(uint8_t cpu_id, uint32_t reset_addr) "id %u, reset_ad
616
allwinner_cpucfg_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
617
allwinner_cpucfg_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
618
619
+# allwinner-h3-dramc.c
620
+allwinner_h3_dramc_rowmirror_disable(void) "Disable row mirror"
621
+allwinner_h3_dramc_rowmirror_enable(uint64_t addr) "Enable row mirror: addr 0x%" PRIx64
622
+allwinner_h3_dramcom_read(uint64_t offset, uint64_t data, unsigned size) "Read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
623
+allwinner_h3_dramcom_write(uint64_t offset, uint64_t data, unsigned size) "Write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
624
+allwinner_h3_dramctl_read(uint64_t offset, uint64_t data, unsigned size) "Read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
625
+allwinner_h3_dramctl_write(uint64_t offset, uint64_t data, unsigned size) "Write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
626
+allwinner_h3_dramphy_read(uint64_t offset, uint64_t data, unsigned size) "Read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
627
+allwinner_h3_dramphy_write(uint64_t offset, uint64_t data, unsigned size) "write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
628
+
629
# allwinner-sid.c
630
allwinner_sid_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
631
allwinner_sid_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
152
--
632
--
153
2.20.1
633
2.20.1
154
634
155
635
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
This commit defines an interface allowing multi-phase reset. This aims
3
Allwinner System-on-Chips usually contain a Real Time Clock (RTC)
4
to solve a problem of the actual single-phase reset (built in
4
for non-volatile system date and time keeping. This commit adds a generic
5
DeviceClass and BusClass): reset behavior is dependent on the order
5
Allwinner RTC device that supports the RTC devices found in Allwinner SoC
6
in which reset handlers are called. In particular doing external
6
family sun4i (A10), sun7i (A20) and sun6i and newer (A31, H2+, H3, etc).
7
side-effect (like setting an qemu_irq) is problematic because receiving
7
The following RTC functionality and features are implemented:
8
object may not be reset yet.
9
8
10
The Resettable interface divides the reset in 3 well defined phases.
9
* Year-Month-Day read/write
11
To reset an object tree, all 1st phases are executed then all 2nd then
10
* Hour-Minute-Second read/write
12
all 3rd. See the comments in include/hw/resettable.h for a more complete
11
* General Purpose storage
13
description. The interface defines 3 phases to let the future
14
possibility of holding an object into reset for some time.
15
12
16
The qdev/qbus reset in DeviceClass and BusClass will be modified in
13
The following boards are extended with the RTC device:
17
following commits to use this interface. A mechanism is provided
18
to allow executing a transitional reset handler in place of the 2nd
19
phase which is executed in children-then-parent order inside a tree.
20
This will allow to transition devices and buses smoothly while
21
keeping the exact current qdev/qbus reset behavior for now.
22
14
23
Documentation will be added in a following commit.
15
* Cubieboard (hw/arm/cubieboard.c)
16
* Orange Pi PC (hw/arm/orangepi.c)
24
17
25
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
18
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
27
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
20
Message-id: 20200311221854.30370-13-nieklinnenbank@gmail.com
28
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
29
Message-id: 20200123132823.1117486-4-damien.hedde@greensocs.com
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
---
22
---
32
hw/core/Makefile.objs | 1 +
23
hw/rtc/Makefile.objs | 1 +
33
include/hw/resettable.h | 211 +++++++++++++++++++++++++++++++++++
24
include/hw/arm/allwinner-a10.h | 2 +
34
hw/core/resettable.c | 238 ++++++++++++++++++++++++++++++++++++++++
25
include/hw/arm/allwinner-h3.h | 3 +
35
hw/core/trace-events | 17 +++
26
include/hw/rtc/allwinner-rtc.h | 134 +++++++++++
36
4 files changed, 467 insertions(+)
27
hw/arm/allwinner-a10.c | 8 +
37
create mode 100644 include/hw/resettable.h
28
hw/arm/allwinner-h3.c | 9 +-
38
create mode 100644 hw/core/resettable.c
29
hw/rtc/allwinner-rtc.c | 411 +++++++++++++++++++++++++++++++++
30
hw/rtc/trace-events | 4 +
31
8 files changed, 571 insertions(+), 1 deletion(-)
32
create mode 100644 include/hw/rtc/allwinner-rtc.h
33
create mode 100644 hw/rtc/allwinner-rtc.c
39
34
40
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
35
diff --git a/hw/rtc/Makefile.objs b/hw/rtc/Makefile.objs
41
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/core/Makefile.objs
37
--- a/hw/rtc/Makefile.objs
43
+++ b/hw/core/Makefile.objs
38
+++ b/hw/rtc/Makefile.objs
39
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MC146818RTC) += mc146818rtc.o
40
common-obj-$(CONFIG_SUN4V_RTC) += sun4v-rtc.o
41
common-obj-$(CONFIG_ASPEED_SOC) += aspeed_rtc.o
42
common-obj-$(CONFIG_GOLDFISH_RTC) += goldfish_rtc.o
43
+common-obj-$(CONFIG_ALLWINNER_H3) += allwinner-rtc.o
44
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/hw/arm/allwinner-a10.h
47
+++ b/include/hw/arm/allwinner-a10.h
44
@@ -XXX,XX +XXX,XX @@
48
@@ -XXX,XX +XXX,XX @@
45
common-obj-y += qdev.o qdev-properties.o
49
#include "hw/ide/ahci.h"
46
common-obj-y += bus.o
50
#include "hw/usb/hcd-ohci.h"
47
common-obj-y += cpu.o
51
#include "hw/usb/hcd-ehci.h"
48
+common-obj-y += resettable.o
52
+#include "hw/rtc/allwinner-rtc.h"
49
common-obj-y += hotplug.o
53
50
common-obj-y += vmstate-if.o
54
#include "target/arm/cpu.h"
51
# irq.o needed for qdev GPIO handling:
55
52
diff --git a/include/hw/resettable.h b/include/hw/resettable.h
56
@@ -XXX,XX +XXX,XX @@ typedef struct AwA10State {
57
AwEmacState emac;
58
AllwinnerAHCIState sata;
59
AwSdHostState mmc0;
60
+ AwRtcState rtc;
61
MemoryRegion sram_a;
62
EHCISysBusState ehci[AW_A10_NUM_USB];
63
OHCISysBusState ohci[AW_A10_NUM_USB];
64
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
65
index XXXXXXX..XXXXXXX 100644
66
--- a/include/hw/arm/allwinner-h3.h
67
+++ b/include/hw/arm/allwinner-h3.h
68
@@ -XXX,XX +XXX,XX @@
69
#include "hw/misc/allwinner-sid.h"
70
#include "hw/sd/allwinner-sdhost.h"
71
#include "hw/net/allwinner-sun8i-emac.h"
72
+#include "hw/rtc/allwinner-rtc.h"
73
#include "target/arm/cpu.h"
74
#include "sysemu/block-backend.h"
75
76
@@ -XXX,XX +XXX,XX @@ enum {
77
AW_H3_GIC_CPU,
78
AW_H3_GIC_HYP,
79
AW_H3_GIC_VCPU,
80
+ AW_H3_RTC,
81
AW_H3_CPUCFG,
82
AW_H3_SDRAM
83
};
84
@@ -XXX,XX +XXX,XX @@ typedef struct AwH3State {
85
AwSidState sid;
86
AwSdHostState mmc0;
87
AwSun8iEmacState emac;
88
+ AwRtcState rtc;
89
GICState gic;
90
MemoryRegion sram_a1;
91
MemoryRegion sram_a2;
92
diff --git a/include/hw/rtc/allwinner-rtc.h b/include/hw/rtc/allwinner-rtc.h
53
new file mode 100644
93
new file mode 100644
54
index XXXXXXX..XXXXXXX
94
index XXXXXXX..XXXXXXX
55
--- /dev/null
95
--- /dev/null
56
+++ b/include/hw/resettable.h
96
+++ b/include/hw/rtc/allwinner-rtc.h
57
@@ -XXX,XX +XXX,XX @@
97
@@ -XXX,XX +XXX,XX @@
58
+/*
98
+/*
59
+ * Resettable interface header.
99
+ * Allwinner Real Time Clock emulation
60
+ *
100
+ *
61
+ * Copyright (c) 2019 GreenSocs SAS
101
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
62
+ *
102
+ *
63
+ * Authors:
103
+ * This program is free software: you can redistribute it and/or modify
64
+ * Damien Hedde
104
+ * it under the terms of the GNU General Public License as published by
65
+ *
105
+ * the Free Software Foundation, either version 2 of the License, or
66
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
106
+ * (at your option) any later version.
67
+ * See the COPYING file in the top-level directory.
107
+ *
108
+ * This program is distributed in the hope that it will be useful,
109
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
110
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
111
+ * GNU General Public License for more details.
112
+ *
113
+ * You should have received a copy of the GNU General Public License
114
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
68
+ */
115
+ */
69
+
116
+
70
+#ifndef HW_RESETTABLE_H
117
+#ifndef HW_MISC_ALLWINNER_RTC_H
71
+#define HW_RESETTABLE_H
118
+#define HW_MISC_ALLWINNER_RTC_H
72
+
119
+
73
+#include "qom/object.h"
120
+#include "qom/object.h"
74
+
121
+#include "hw/sysbus.h"
75
+#define TYPE_RESETTABLE_INTERFACE "resettable"
76
+
77
+#define RESETTABLE_CLASS(class) \
78
+ OBJECT_CLASS_CHECK(ResettableClass, (class), TYPE_RESETTABLE_INTERFACE)
79
+
80
+#define RESETTABLE_GET_CLASS(obj) \
81
+ OBJECT_GET_CLASS(ResettableClass, (obj), TYPE_RESETTABLE_INTERFACE)
82
+
83
+typedef struct ResettableState ResettableState;
84
+
122
+
85
+/**
123
+/**
86
+ * ResetType:
124
+ * Constants
87
+ * Types of reset.
125
+ * @{
88
+ *
89
+ * + Cold: reset resulting from a power cycle of the object.
90
+ *
91
+ * TODO: Support has to be added to handle more types. In particular,
92
+ * ResettableState structure needs to be expanded.
93
+ */
126
+ */
94
+typedef enum ResetType {
127
+
95
+ RESET_TYPE_COLD,
128
+/** Highest register address used by RTC device */
96
+} ResetType;
129
+#define AW_RTC_REGS_MAXADDR (0x200)
97
+
130
+
98
+/*
131
+/** Total number of known registers */
99
+ * ResettableClass:
132
+#define AW_RTC_REGS_NUM (AW_RTC_REGS_MAXADDR / sizeof(uint32_t))
100
+ * Interface for resettable objects.
133
+
101
+ *
134
+/** @} */
102
+ * See docs/devel/reset.rst for more detailed information about how QEMU models
135
+
103
+ * reset. This whole API must only be used when holding the iothread mutex.
136
+/**
104
+ *
137
+ * Object model types
105
+ * All objects which can be reset must implement this interface;
138
+ * @{
106
+ * it is usually provided by a base class such as DeviceClass or BusClass.
107
+ * Every Resettable object must maintain some state tracking the
108
+ * progress of a reset operation by providing a ResettableState structure.
109
+ * The functions defined in this module take care of updating the
110
+ * state of the reset.
111
+ * The base class implementation of the interface provides this
112
+ * state and implements the associated method: get_state.
113
+ *
114
+ * Concrete object implementations (typically specific devices
115
+ * such as a UART model) should provide the functions
116
+ * for the phases.enter, phases.hold and phases.exit methods, which
117
+ * they can set in their class init function, either directly or
118
+ * by calling resettable_class_set_parent_phases().
119
+ * The phase methods are guaranteed to only only ever be called once
120
+ * for any reset event, in the order 'enter', 'hold', 'exit'.
121
+ * An object will always move quickly from 'enter' to 'hold'
122
+ * but might remain in 'hold' for an arbitrary period of time
123
+ * before eventually reset is deasserted and the 'exit' phase is called.
124
+ * Object implementations should be prepared for functions handling
125
+ * inbound connections from other devices (such as qemu_irq handler
126
+ * functions) to be called at any point during reset after their
127
+ * 'enter' method has been called.
128
+ *
129
+ * Users of a resettable object should not call these methods
130
+ * directly, but instead use the function resettable_reset().
131
+ *
132
+ * @phases.enter: This phase is called when the object enters reset. It
133
+ * should reset local state of the object, but it must not do anything that
134
+ * has a side-effect on other objects, such as raising or lowering a qemu_irq
135
+ * line or reading or writing guest memory. It takes the reset's type as
136
+ * argument.
137
+ *
138
+ * @phases.hold: This phase is called for entry into reset, once every object
139
+ * in the system which is being reset has had its @phases.enter method called.
140
+ * At this point devices can do actions that affect other objects.
141
+ *
142
+ * @phases.exit: This phase is called when the object leaves the reset state.
143
+ * Actions affecting other objects are permitted.
144
+ *
145
+ * @get_state: Mandatory method which must return a pointer to a
146
+ * ResettableState.
147
+ *
148
+ * @get_transitional_function: transitional method to handle Resettable objects
149
+ * not yet fully moved to this interface. It will be removed as soon as it is
150
+ * not needed anymore. This method is optional and may return a pointer to a
151
+ * function to be used instead of the phases. If the method exists and returns
152
+ * a non-NULL function pointer then that function is executed as a replacement
153
+ * of the 'hold' phase method taking the object as argument. The two other phase
154
+ * methods are not executed.
155
+ *
156
+ * @child_foreach: Executes a given callback on every Resettable child. Child
157
+ * in this context means a child in the qbus tree, so the children of a qbus
158
+ * are the devices on it, and the children of a device are all the buses it
159
+ * owns. This is not the same as the QOM object hierarchy. The function takes
160
+ * additional opaque and ResetType arguments which must be passed unmodified to
161
+ * the callback.
162
+ */
139
+ */
163
+typedef void (*ResettableEnterPhase)(Object *obj, ResetType type);
140
+
164
+typedef void (*ResettableHoldPhase)(Object *obj);
141
+/** Generic Allwinner RTC device (abstract) */
165
+typedef void (*ResettableExitPhase)(Object *obj);
142
+#define TYPE_AW_RTC "allwinner-rtc"
166
+typedef ResettableState * (*ResettableGetState)(Object *obj);
143
+
167
+typedef void (*ResettableTrFunction)(Object *obj);
144
+/** Allwinner RTC sun4i family (A10, A12) */
168
+typedef ResettableTrFunction (*ResettableGetTrFunction)(Object *obj);
145
+#define TYPE_AW_RTC_SUN4I TYPE_AW_RTC "-sun4i"
169
+typedef void (*ResettableChildCallback)(Object *, void *opaque,
146
+
170
+ ResetType type);
147
+/** Allwinner RTC sun6i family and newer (A31, H2+, H3, etc) */
171
+typedef void (*ResettableChildForeach)(Object *obj,
148
+#define TYPE_AW_RTC_SUN6I TYPE_AW_RTC "-sun6i"
172
+ ResettableChildCallback cb,
149
+
173
+ void *opaque, ResetType type);
150
+/** Allwinner RTC sun7i family (A20) */
174
+typedef struct ResettablePhases {
151
+#define TYPE_AW_RTC_SUN7I TYPE_AW_RTC "-sun7i"
175
+ ResettableEnterPhase enter;
152
+
176
+ ResettableHoldPhase hold;
153
+/** @} */
177
+ ResettableExitPhase exit;
178
+} ResettablePhases;
179
+typedef struct ResettableClass {
180
+ InterfaceClass parent_class;
181
+
182
+ /* Phase methods */
183
+ ResettablePhases phases;
184
+
185
+ /* State access method */
186
+ ResettableGetState get_state;
187
+
188
+ /* Transitional method for legacy reset compatibility */
189
+ ResettableGetTrFunction get_transitional_function;
190
+
191
+ /* Hierarchy handling method */
192
+ ResettableChildForeach child_foreach;
193
+} ResettableClass;
194
+
154
+
195
+/**
155
+/**
196
+ * ResettableState:
156
+ * Object model macros
197
+ * Structure holding reset related state. The fields should not be accessed
157
+ * @{
198
+ * directly; the definition is here to allow further inclusion into other
199
+ * objects.
200
+ *
201
+ * @count: Number of reset level the object is into. It is incremented when
202
+ * the reset operation starts and decremented when it finishes.
203
+ * @hold_phase_pending: flag which indicates that we need to invoke the 'hold'
204
+ * phase handler for this object.
205
+ * @exit_phase_in_progress: true if we are currently in the exit phase
206
+ */
158
+ */
207
+struct ResettableState {
159
+
208
+ unsigned count;
160
+#define AW_RTC(obj) \
209
+ bool hold_phase_pending;
161
+ OBJECT_CHECK(AwRtcState, (obj), TYPE_AW_RTC)
210
+ bool exit_phase_in_progress;
162
+#define AW_RTC_CLASS(klass) \
211
+};
163
+ OBJECT_CLASS_CHECK(AwRtcClass, (klass), TYPE_AW_RTC)
164
+#define AW_RTC_GET_CLASS(obj) \
165
+ OBJECT_GET_CLASS(AwRtcClass, (obj), TYPE_AW_RTC)
166
+
167
+/** @} */
212
+
168
+
213
+/**
169
+/**
214
+ * resettable_reset:
170
+ * Allwinner RTC per-object instance state.
215
+ * Trigger a reset on an object @obj of type @type. @obj must implement
216
+ * Resettable interface.
217
+ *
218
+ * Calling this function is equivalent to calling @resettable_assert_reset()
219
+ * then @resettable_release_reset().
220
+ */
171
+ */
221
+void resettable_reset(Object *obj, ResetType type);
172
+typedef struct AwRtcState {
173
+ /*< private >*/
174
+ SysBusDevice parent_obj;
175
+ /*< public >*/
176
+
177
+ /**
178
+ * Actual year represented by the device when year counter is zero
179
+ *
180
+ * Can be overridden by the user using the corresponding 'base-year'
181
+ * property. The base year used by the target OS driver can vary, for
182
+ * example the Linux driver for sun6i uses 1970 while NetBSD uses 2000.
183
+ */
184
+ int base_year;
185
+
186
+ /** Maps I/O registers in physical memory */
187
+ MemoryRegion iomem;
188
+
189
+ /** Array of hardware registers */
190
+ uint32_t regs[AW_RTC_REGS_NUM];
191
+
192
+} AwRtcState;
222
+
193
+
223
+/**
194
+/**
224
+ * resettable_assert_reset:
195
+ * Allwinner RTC class-level struct.
225
+ * Put an object @obj into reset. @obj must implement Resettable interface.
196
+ *
226
+ *
197
+ * This struct is filled by each sunxi device specific code
227
+ * @resettable_release_reset() must eventually be called after this call.
198
+ * such that the generic code can use this struct to support
228
+ * There must be one call to @resettable_release_reset() per call of
199
+ * all devices.
229
+ * @resettable_assert_reset(), with the same type argument.
230
+ *
231
+ * NOTE: Until support for migration is added, the @resettable_release_reset()
232
+ * must not be delayed. It must occur just after @resettable_assert_reset() so
233
+ * that migration cannot be triggered in between. Prefer using
234
+ * @resettable_reset() for now.
235
+ */
200
+ */
236
+void resettable_assert_reset(Object *obj, ResetType type);
201
+typedef struct AwRtcClass {
237
+
202
+ /*< private >*/
238
+/**
203
+ SysBusDeviceClass parent_class;
239
+ * resettable_release_reset:
204
+ /*< public >*/
240
+ * Release the object @obj from reset. @obj must implement Resettable interface.
205
+
241
+ *
206
+ /** Defines device specific register map */
242
+ * See @resettable_assert_reset() description for details.
207
+ const uint8_t *regmap;
243
+ */
208
+
244
+void resettable_release_reset(Object *obj, ResetType type);
209
+ /** Size of the regmap in bytes */
245
+
210
+ size_t regmap_size;
246
+/**
211
+
247
+ * resettable_is_in_reset:
212
+ /**
248
+ * Return true if @obj is under reset.
213
+ * Read device specific register
249
+ *
214
+ *
250
+ * @obj must implement Resettable interface.
215
+ * @offset: register offset to read
251
+ */
216
+ * @return true if register read successful, false otherwise
252
+bool resettable_is_in_reset(Object *obj);
217
+ */
253
+
218
+ bool (*read)(AwRtcState *s, uint32_t offset);
254
+/**
219
+
255
+ * resettable_class_set_parent_phases:
220
+ /**
256
+ *
221
+ * Write device specific register
257
+ * Save @rc current reset phases into @parent_phases and override @rc phases
222
+ *
258
+ * by the given new methods (@enter, @hold and @exit).
223
+ * @offset: register offset to write
259
+ * Each phase is overridden only if the new one is not NULL allowing to
224
+ * @data: value to set in register
260
+ * override a subset of phases.
225
+ * @return true if register write successful, false otherwise
261
+ */
226
+ */
262
+void resettable_class_set_parent_phases(ResettableClass *rc,
227
+ bool (*write)(AwRtcState *s, uint32_t offset, uint32_t data);
263
+ ResettableEnterPhase enter,
228
+
264
+ ResettableHoldPhase hold,
229
+} AwRtcClass;
265
+ ResettableExitPhase exit,
230
+
266
+ ResettablePhases *parent_phases);
231
+#endif /* HW_MISC_ALLWINNER_RTC_H */
267
+
232
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
268
+#endif
233
index XXXXXXX..XXXXXXX 100644
269
diff --git a/hw/core/resettable.c b/hw/core/resettable.c
234
--- a/hw/arm/allwinner-a10.c
235
+++ b/hw/arm/allwinner-a10.c
236
@@ -XXX,XX +XXX,XX @@
237
#define AW_A10_EHCI_BASE 0x01c14000
238
#define AW_A10_OHCI_BASE 0x01c14400
239
#define AW_A10_SATA_BASE 0x01c18000
240
+#define AW_A10_RTC_BASE 0x01c20d00
241
242
static void aw_a10_init(Object *obj)
243
{
244
@@ -XXX,XX +XXX,XX @@ static void aw_a10_init(Object *obj)
245
246
sysbus_init_child_obj(obj, "mmc0", &s->mmc0, sizeof(s->mmc0),
247
TYPE_AW_SDHOST_SUN4I);
248
+
249
+ sysbus_init_child_obj(obj, "rtc", &s->rtc, sizeof(s->rtc),
250
+ TYPE_AW_RTC_SUN4I);
251
}
252
253
static void aw_a10_realize(DeviceState *dev, Error **errp)
254
@@ -XXX,XX +XXX,XX @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
255
sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc0), 0, qdev_get_gpio_in(dev, 32));
256
object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->mmc0),
257
"sd-bus", &error_abort);
258
+
259
+ /* RTC */
260
+ qdev_init_nofail(DEVICE(&s->rtc));
261
+ sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->rtc), 0, AW_A10_RTC_BASE, 10);
262
}
263
264
static void aw_a10_class_init(ObjectClass *oc, void *data)
265
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
266
index XXXXXXX..XXXXXXX 100644
267
--- a/hw/arm/allwinner-h3.c
268
+++ b/hw/arm/allwinner-h3.c
269
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
270
[AW_H3_GIC_CPU] = 0x01c82000,
271
[AW_H3_GIC_HYP] = 0x01c84000,
272
[AW_H3_GIC_VCPU] = 0x01c86000,
273
+ [AW_H3_RTC] = 0x01f00000,
274
[AW_H3_CPUCFG] = 0x01f01c00,
275
[AW_H3_SDRAM] = 0x40000000
276
};
277
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
278
{ "csi", 0x01cb0000, 320 * KiB },
279
{ "tve", 0x01e00000, 64 * KiB },
280
{ "hdmi", 0x01ee0000, 128 * KiB },
281
- { "rtc", 0x01f00000, 1 * KiB },
282
{ "r_timer", 0x01f00800, 1 * KiB },
283
{ "r_intc", 0x01f00c00, 1 * KiB },
284
{ "r_wdog", 0x01f01000, 1 * KiB },
285
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
286
"ram-addr", &error_abort);
287
object_property_add_alias(obj, "ram-size", OBJECT(&s->dramc),
288
"ram-size", &error_abort);
289
+
290
+ sysbus_init_child_obj(obj, "rtc", &s->rtc, sizeof(s->rtc),
291
+ TYPE_AW_RTC_SUN6I);
292
}
293
294
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
295
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
296
sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 1, s->memmap[AW_H3_DRAMCTL]);
297
sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 2, s->memmap[AW_H3_DRAMPHY]);
298
299
+ /* RTC */
300
+ qdev_init_nofail(DEVICE(&s->rtc));
301
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, s->memmap[AW_H3_RTC]);
302
+
303
/* Unimplemented devices */
304
for (i = 0; i < ARRAY_SIZE(unimplemented); i++) {
305
create_unimplemented_device(unimplemented[i].device_name,
306
diff --git a/hw/rtc/allwinner-rtc.c b/hw/rtc/allwinner-rtc.c
270
new file mode 100644
307
new file mode 100644
271
index XXXXXXX..XXXXXXX
308
index XXXXXXX..XXXXXXX
272
--- /dev/null
309
--- /dev/null
273
+++ b/hw/core/resettable.c
310
+++ b/hw/rtc/allwinner-rtc.c
274
@@ -XXX,XX +XXX,XX @@
311
@@ -XXX,XX +XXX,XX @@
275
+/*
312
+/*
276
+ * Resettable interface.
313
+ * Allwinner Real Time Clock emulation
277
+ *
314
+ *
278
+ * Copyright (c) 2019 GreenSocs SAS
315
+ * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
279
+ *
316
+ *
280
+ * Authors:
317
+ * This program is free software: you can redistribute it and/or modify
281
+ * Damien Hedde
318
+ * it under the terms of the GNU General Public License as published by
282
+ *
319
+ * the Free Software Foundation, either version 2 of the License, or
283
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
320
+ * (at your option) any later version.
284
+ * See the COPYING file in the top-level directory.
321
+ *
322
+ * This program is distributed in the hope that it will be useful,
323
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
324
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
325
+ * GNU General Public License for more details.
326
+ *
327
+ * You should have received a copy of the GNU General Public License
328
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
285
+ */
329
+ */
286
+
330
+
287
+#include "qemu/osdep.h"
331
+#include "qemu/osdep.h"
332
+#include "qemu/units.h"
333
+#include "hw/sysbus.h"
334
+#include "migration/vmstate.h"
335
+#include "qemu/log.h"
288
+#include "qemu/module.h"
336
+#include "qemu/module.h"
289
+#include "hw/resettable.h"
337
+#include "qemu-common.h"
338
+#include "hw/qdev-properties.h"
339
+#include "hw/rtc/allwinner-rtc.h"
290
+#include "trace.h"
340
+#include "trace.h"
291
+
341
+
292
+/**
342
+/* RTC registers */
293
+ * resettable_phase_enter/hold/exit:
343
+enum {
294
+ * Function executing a phase recursively in a resettable object and its
344
+ REG_LOSC = 1, /* Low Oscillator Control */
295
+ * children.
345
+ REG_YYMMDD, /* RTC Year-Month-Day */
296
+ */
346
+ REG_HHMMSS, /* RTC Hour-Minute-Second */
297
+static void resettable_phase_enter(Object *obj, void *opaque, ResetType type);
347
+ REG_ALARM1_WKHHMMSS, /* Alarm1 Week Hour-Minute-Second */
298
+static void resettable_phase_hold(Object *obj, void *opaque, ResetType type);
348
+ REG_ALARM1_EN, /* Alarm1 Enable */
299
+static void resettable_phase_exit(Object *obj, void *opaque, ResetType type);
349
+ REG_ALARM1_IRQ_EN, /* Alarm1 IRQ Enable */
300
+
350
+ REG_ALARM1_IRQ_STA, /* Alarm1 IRQ Status */
301
+/**
351
+ REG_GP0, /* General Purpose Register 0 */
302
+ * enter_phase_in_progress:
352
+ REG_GP1, /* General Purpose Register 1 */
303
+ * True if we are currently in reset enter phase.
353
+ REG_GP2, /* General Purpose Register 2 */
304
+ *
354
+ REG_GP3, /* General Purpose Register 3 */
305
+ * Note: This flag is only used to guarantee (using asserts) that the reset
355
+
306
+ * API is used correctly. We can use a global variable because we rely on the
356
+ /* sun4i registers */
307
+ * iothread mutex to ensure only one reset operation is in a progress at a
357
+ REG_ALARM1_DDHHMMSS, /* Alarm1 Day Hour-Minute-Second */
308
+ * given time.
358
+ REG_CPUCFG, /* CPU Configuration Register */
309
+ */
359
+
310
+static bool enter_phase_in_progress;
360
+ /* sun6i registers */
311
+
361
+ REG_LOSC_AUTOSTA, /* LOSC Auto Switch Status */
312
+void resettable_reset(Object *obj, ResetType type)
362
+ REG_INT_OSC_PRE, /* Internal OSC Clock Prescaler */
313
+{
363
+ REG_ALARM0_COUNTER, /* Alarm0 Counter */
314
+ trace_resettable_reset(obj, type);
364
+ REG_ALARM0_CUR_VLU, /* Alarm0 Counter Current Value */
315
+ resettable_assert_reset(obj, type);
365
+ REG_ALARM0_ENABLE, /* Alarm0 Enable */
316
+ resettable_release_reset(obj, type);
366
+ REG_ALARM0_IRQ_EN, /* Alarm0 IRQ Enable */
317
+}
367
+ REG_ALARM0_IRQ_STA, /* Alarm0 IRQ Status */
318
+
368
+ REG_ALARM_CONFIG, /* Alarm Config */
319
+void resettable_assert_reset(Object *obj, ResetType type)
369
+ REG_LOSC_OUT_GATING, /* LOSC Output Gating Register */
320
+{
370
+ REG_GP4, /* General Purpose Register 4 */
321
+ /* TODO: change this assert when adding support for other reset types */
371
+ REG_GP5, /* General Purpose Register 5 */
322
+ assert(type == RESET_TYPE_COLD);
372
+ REG_GP6, /* General Purpose Register 6 */
323
+ trace_resettable_reset_assert_begin(obj, type);
373
+ REG_GP7, /* General Purpose Register 7 */
324
+ assert(!enter_phase_in_progress);
374
+ REG_RTC_DBG, /* RTC Debug Register */
325
+
375
+ REG_GPL_HOLD_OUT, /* GPL Hold Output Register */
326
+ enter_phase_in_progress = true;
376
+ REG_VDD_RTC, /* VDD RTC Regulate Register */
327
+ resettable_phase_enter(obj, NULL, type);
377
+ REG_IC_CHARA, /* IC Characteristics Register */
328
+ enter_phase_in_progress = false;
378
+};
329
+
379
+
330
+ resettable_phase_hold(obj, NULL, type);
380
+/* RTC register flags */
331
+
381
+enum {
332
+ trace_resettable_reset_assert_end(obj);
382
+ REG_LOSC_YMD = (1 << 7),
333
+}
383
+ REG_LOSC_HMS = (1 << 8),
334
+
384
+};
335
+void resettable_release_reset(Object *obj, ResetType type)
385
+
336
+{
386
+/* RTC sun4i register map (offset to name) */
337
+ /* TODO: change this assert when adding support for other reset types */
387
+const uint8_t allwinner_rtc_sun4i_regmap[] = {
338
+ assert(type == RESET_TYPE_COLD);
388
+ [0x0000] = REG_LOSC,
339
+ trace_resettable_reset_release_begin(obj, type);
389
+ [0x0004] = REG_YYMMDD,
340
+ assert(!enter_phase_in_progress);
390
+ [0x0008] = REG_HHMMSS,
341
+
391
+ [0x000C] = REG_ALARM1_DDHHMMSS,
342
+ resettable_phase_exit(obj, NULL, type);
392
+ [0x0010] = REG_ALARM1_WKHHMMSS,
343
+
393
+ [0x0014] = REG_ALARM1_EN,
344
+ trace_resettable_reset_release_end(obj);
394
+ [0x0018] = REG_ALARM1_IRQ_EN,
345
+}
395
+ [0x001C] = REG_ALARM1_IRQ_STA,
346
+
396
+ [0x0020] = REG_GP0,
347
+bool resettable_is_in_reset(Object *obj)
397
+ [0x0024] = REG_GP1,
348
+{
398
+ [0x0028] = REG_GP2,
349
+ ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
399
+ [0x002C] = REG_GP3,
350
+ ResettableState *s = rc->get_state(obj);
400
+ [0x003C] = REG_CPUCFG,
351
+
401
+};
352
+ return s->count > 0;
402
+
353
+}
403
+/* RTC sun6i register map (offset to name) */
354
+
404
+const uint8_t allwinner_rtc_sun6i_regmap[] = {
355
+/**
405
+ [0x0000] = REG_LOSC,
356
+ * resettable_child_foreach:
406
+ [0x0004] = REG_LOSC_AUTOSTA,
357
+ * helper to avoid checking the existence of the method.
407
+ [0x0008] = REG_INT_OSC_PRE,
358
+ */
408
+ [0x0010] = REG_YYMMDD,
359
+static void resettable_child_foreach(ResettableClass *rc, Object *obj,
409
+ [0x0014] = REG_HHMMSS,
360
+ ResettableChildCallback cb,
410
+ [0x0020] = REG_ALARM0_COUNTER,
361
+ void *opaque, ResetType type)
411
+ [0x0024] = REG_ALARM0_CUR_VLU,
362
+{
412
+ [0x0028] = REG_ALARM0_ENABLE,
363
+ if (rc->child_foreach) {
413
+ [0x002C] = REG_ALARM0_IRQ_EN,
364
+ rc->child_foreach(obj, cb, opaque, type);
414
+ [0x0030] = REG_ALARM0_IRQ_STA,
365
+ }
415
+ [0x0040] = REG_ALARM1_WKHHMMSS,
366
+}
416
+ [0x0044] = REG_ALARM1_EN,
367
+
417
+ [0x0048] = REG_ALARM1_IRQ_EN,
368
+/**
418
+ [0x004C] = REG_ALARM1_IRQ_STA,
369
+ * resettable_get_tr_func:
419
+ [0x0050] = REG_ALARM_CONFIG,
370
+ * helper to fetch transitional reset callback if any.
420
+ [0x0060] = REG_LOSC_OUT_GATING,
371
+ */
421
+ [0x0100] = REG_GP0,
372
+static ResettableTrFunction resettable_get_tr_func(ResettableClass *rc,
422
+ [0x0104] = REG_GP1,
373
+ Object *obj)
423
+ [0x0108] = REG_GP2,
374
+{
424
+ [0x010C] = REG_GP3,
375
+ ResettableTrFunction tr_func = NULL;
425
+ [0x0110] = REG_GP4,
376
+ if (rc->get_transitional_function) {
426
+ [0x0114] = REG_GP5,
377
+ tr_func = rc->get_transitional_function(obj);
427
+ [0x0118] = REG_GP6,
378
+ }
428
+ [0x011C] = REG_GP7,
379
+ return tr_func;
429
+ [0x0170] = REG_RTC_DBG,
380
+}
430
+ [0x0180] = REG_GPL_HOLD_OUT,
381
+
431
+ [0x0190] = REG_VDD_RTC,
382
+static void resettable_phase_enter(Object *obj, void *opaque, ResetType type)
432
+ [0x01F0] = REG_IC_CHARA,
383
+{
433
+};
384
+ ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
434
+
385
+ ResettableState *s = rc->get_state(obj);
435
+static bool allwinner_rtc_sun4i_read(AwRtcState *s, uint32_t offset)
386
+ const char *obj_typename = object_get_typename(obj);
436
+{
387
+ bool action_needed = false;
437
+ /* no sun4i specific registers currently implemented */
388
+
438
+ return false;
389
+ /* exit phase has to finish properly before entering back in reset */
439
+}
390
+ assert(!s->exit_phase_in_progress);
440
+
391
+
441
+static bool allwinner_rtc_sun4i_write(AwRtcState *s, uint32_t offset,
392
+ trace_resettable_phase_enter_begin(obj, obj_typename, s->count, type);
442
+ uint32_t data)
393
+
443
+{
394
+ /* Only take action if we really enter reset for the 1st time. */
444
+ /* no sun4i specific registers currently implemented */
395
+ /*
445
+ return false;
396
+ * TODO: if adding more ResetType support, some additional checks
446
+}
397
+ * are probably needed here.
447
+
398
+ */
448
+static bool allwinner_rtc_sun6i_read(AwRtcState *s, uint32_t offset)
399
+ if (s->count++ == 0) {
449
+{
400
+ action_needed = true;
450
+ const AwRtcClass *c = AW_RTC_GET_CLASS(s);
401
+ }
451
+
402
+ /*
452
+ switch (c->regmap[offset]) {
403
+ * We limit the count to an arbitrary "big" value. The value is big
453
+ case REG_GP4: /* General Purpose Register 4 */
404
+ * enough not to be triggered normally.
454
+ case REG_GP5: /* General Purpose Register 5 */
405
+ * The assert will stop an infinite loop if there is a cycle in the
455
+ case REG_GP6: /* General Purpose Register 6 */
406
+ * reset tree. The loop goes through resettable_foreach_child below
456
+ case REG_GP7: /* General Purpose Register 7 */
407
+ * which at some point will call us again.
457
+ return true;
408
+ */
458
+ default:
409
+ assert(s->count <= 50);
459
+ break;
410
+
460
+ }
411
+ /*
461
+ return false;
412
+ * handle the children even if action_needed is at false so that
462
+}
413
+ * child counts are incremented too
463
+
414
+ */
464
+static bool allwinner_rtc_sun6i_write(AwRtcState *s, uint32_t offset,
415
+ resettable_child_foreach(rc, obj, resettable_phase_enter, NULL, type);
465
+ uint32_t data)
416
+
466
+{
417
+ /* execute enter phase for the object if needed */
467
+ const AwRtcClass *c = AW_RTC_GET_CLASS(s);
418
+ if (action_needed) {
468
+
419
+ trace_resettable_phase_enter_exec(obj, obj_typename, type,
469
+ switch (c->regmap[offset]) {
420
+ !!rc->phases.enter);
470
+ case REG_GP4: /* General Purpose Register 4 */
421
+ if (rc->phases.enter && !resettable_get_tr_func(rc, obj)) {
471
+ case REG_GP5: /* General Purpose Register 5 */
422
+ rc->phases.enter(obj, type);
472
+ case REG_GP6: /* General Purpose Register 6 */
473
+ case REG_GP7: /* General Purpose Register 7 */
474
+ return true;
475
+ default:
476
+ break;
477
+ }
478
+ return false;
479
+}
480
+
481
+static uint64_t allwinner_rtc_read(void *opaque, hwaddr offset,
482
+ unsigned size)
483
+{
484
+ AwRtcState *s = AW_RTC(opaque);
485
+ const AwRtcClass *c = AW_RTC_GET_CLASS(s);
486
+ uint64_t val = 0;
487
+
488
+ if (offset >= c->regmap_size) {
489
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
490
+ __func__, (uint32_t)offset);
491
+ return 0;
492
+ }
493
+
494
+ if (!c->regmap[offset]) {
495
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid register 0x%04x\n",
496
+ __func__, (uint32_t)offset);
497
+ return 0;
498
+ }
499
+
500
+ switch (c->regmap[offset]) {
501
+ case REG_LOSC: /* Low Oscillator Control */
502
+ val = s->regs[REG_LOSC];
503
+ s->regs[REG_LOSC] &= ~(REG_LOSC_YMD | REG_LOSC_HMS);
504
+ break;
505
+ case REG_YYMMDD: /* RTC Year-Month-Day */
506
+ case REG_HHMMSS: /* RTC Hour-Minute-Second */
507
+ case REG_GP0: /* General Purpose Register 0 */
508
+ case REG_GP1: /* General Purpose Register 1 */
509
+ case REG_GP2: /* General Purpose Register 2 */
510
+ case REG_GP3: /* General Purpose Register 3 */
511
+ val = s->regs[c->regmap[offset]];
512
+ break;
513
+ default:
514
+ if (!c->read(s, offset)) {
515
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented register 0x%04x\n",
516
+ __func__, (uint32_t)offset);
423
+ }
517
+ }
424
+ s->hold_phase_pending = true;
518
+ val = s->regs[c->regmap[offset]];
425
+ }
519
+ break;
426
+ trace_resettable_phase_enter_end(obj, obj_typename, s->count);
520
+ }
427
+}
521
+
428
+
522
+ trace_allwinner_rtc_read(offset, val);
429
+static void resettable_phase_hold(Object *obj, void *opaque, ResetType type)
523
+ return val;
430
+{
524
+}
431
+ ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
525
+
432
+ ResettableState *s = rc->get_state(obj);
526
+static void allwinner_rtc_write(void *opaque, hwaddr offset,
433
+ const char *obj_typename = object_get_typename(obj);
527
+ uint64_t val, unsigned size)
434
+
528
+{
435
+ /* exit phase has to finish properly before entering back in reset */
529
+ AwRtcState *s = AW_RTC(opaque);
436
+ assert(!s->exit_phase_in_progress);
530
+ const AwRtcClass *c = AW_RTC_GET_CLASS(s);
437
+
531
+
438
+ trace_resettable_phase_hold_begin(obj, obj_typename, s->count, type);
532
+ if (offset >= c->regmap_size) {
439
+
533
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
440
+ /* handle children first */
534
+ __func__, (uint32_t)offset);
441
+ resettable_child_foreach(rc, obj, resettable_phase_hold, NULL, type);
535
+ return;
442
+
536
+ }
443
+ /* exec hold phase */
537
+
444
+ if (s->hold_phase_pending) {
538
+ if (!c->regmap[offset]) {
445
+ s->hold_phase_pending = false;
539
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid register 0x%04x\n",
446
+ ResettableTrFunction tr_func = resettable_get_tr_func(rc, obj);
540
+ __func__, (uint32_t)offset);
447
+ trace_resettable_phase_hold_exec(obj, obj_typename, !!rc->phases.hold);
541
+ return;
448
+ if (tr_func) {
542
+ }
449
+ trace_resettable_transitional_function(obj, obj_typename);
543
+
450
+ tr_func(obj);
544
+ trace_allwinner_rtc_write(offset, val);
451
+ } else if (rc->phases.hold) {
545
+
452
+ rc->phases.hold(obj);
546
+ switch (c->regmap[offset]) {
547
+ case REG_YYMMDD: /* RTC Year-Month-Day */
548
+ s->regs[REG_YYMMDD] = val;
549
+ s->regs[REG_LOSC] |= REG_LOSC_YMD;
550
+ break;
551
+ case REG_HHMMSS: /* RTC Hour-Minute-Second */
552
+ s->regs[REG_HHMMSS] = val;
553
+ s->regs[REG_LOSC] |= REG_LOSC_HMS;
554
+ break;
555
+ case REG_GP0: /* General Purpose Register 0 */
556
+ case REG_GP1: /* General Purpose Register 1 */
557
+ case REG_GP2: /* General Purpose Register 2 */
558
+ case REG_GP3: /* General Purpose Register 3 */
559
+ s->regs[c->regmap[offset]] = val;
560
+ break;
561
+ default:
562
+ if (!c->write(s, offset, val)) {
563
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented register 0x%04x\n",
564
+ __func__, (uint32_t)offset);
453
+ }
565
+ }
454
+ }
566
+ break;
455
+ trace_resettable_phase_hold_end(obj, obj_typename, s->count);
567
+ }
456
+}
568
+}
457
+
569
+
458
+static void resettable_phase_exit(Object *obj, void *opaque, ResetType type)
570
+static const MemoryRegionOps allwinner_rtc_ops = {
459
+{
571
+ .read = allwinner_rtc_read,
460
+ ResettableClass *rc = RESETTABLE_GET_CLASS(obj);
572
+ .write = allwinner_rtc_write,
461
+ ResettableState *s = rc->get_state(obj);
573
+ .endianness = DEVICE_NATIVE_ENDIAN,
462
+ const char *obj_typename = object_get_typename(obj);
574
+ .valid = {
463
+
575
+ .min_access_size = 4,
464
+ assert(!s->exit_phase_in_progress);
576
+ .max_access_size = 4,
465
+ trace_resettable_phase_exit_begin(obj, obj_typename, s->count, type);
577
+ },
466
+
578
+ .impl.min_access_size = 4,
467
+ /* exit_phase_in_progress ensures this phase is 'atomic' */
579
+};
468
+ s->exit_phase_in_progress = true;
580
+
469
+ resettable_child_foreach(rc, obj, resettable_phase_exit, NULL, type);
581
+static void allwinner_rtc_reset(DeviceState *dev)
470
+
582
+{
471
+ assert(s->count > 0);
583
+ AwRtcState *s = AW_RTC(dev);
472
+ if (s->count == 1) {
584
+ struct tm now;
473
+ trace_resettable_phase_exit_exec(obj, obj_typename, !!rc->phases.exit);
585
+
474
+ if (rc->phases.exit && !resettable_get_tr_func(rc, obj)) {
586
+ /* Clear registers */
475
+ rc->phases.exit(obj);
587
+ memset(s->regs, 0, sizeof(s->regs));
476
+ }
588
+
477
+ s->count = 0;
589
+ /* Get current datetime */
478
+ }
590
+ qemu_get_timedate(&now, 0);
479
+ s->exit_phase_in_progress = false;
591
+
480
+ trace_resettable_phase_exit_end(obj, obj_typename, s->count);
592
+ /* Set RTC with current datetime */
481
+}
593
+ if (s->base_year > 1900) {
482
+
594
+ s->regs[REG_YYMMDD] = ((now.tm_year + 1900 - s->base_year) << 16) |
483
+void resettable_class_set_parent_phases(ResettableClass *rc,
595
+ ((now.tm_mon + 1) << 8) |
484
+ ResettableEnterPhase enter,
596
+ now.tm_mday;
485
+ ResettableHoldPhase hold,
597
+ s->regs[REG_HHMMSS] = (((now.tm_wday + 6) % 7) << 29) |
486
+ ResettableExitPhase exit,
598
+ (now.tm_hour << 16) |
487
+ ResettablePhases *parent_phases)
599
+ (now.tm_min << 8) |
488
+{
600
+ now.tm_sec;
489
+ *parent_phases = rc->phases;
601
+ }
490
+ if (enter) {
602
+}
491
+ rc->phases.enter = enter;
603
+
492
+ }
604
+static void allwinner_rtc_init(Object *obj)
493
+ if (hold) {
605
+{
494
+ rc->phases.hold = hold;
606
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
495
+ }
607
+ AwRtcState *s = AW_RTC(obj);
496
+ if (exit) {
608
+
497
+ rc->phases.exit = exit;
609
+ /* Memory mapping */
498
+ }
610
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_rtc_ops, s,
499
+}
611
+ TYPE_AW_RTC, 1 * KiB);
500
+
612
+ sysbus_init_mmio(sbd, &s->iomem);
501
+static const TypeInfo resettable_interface_info = {
613
+}
502
+ .name = TYPE_RESETTABLE_INTERFACE,
614
+
503
+ .parent = TYPE_INTERFACE,
615
+static const VMStateDescription allwinner_rtc_vmstate = {
504
+ .class_size = sizeof(ResettableClass),
616
+ .name = "allwinner-rtc",
505
+};
617
+ .version_id = 1,
506
+
618
+ .minimum_version_id = 1,
507
+static void reset_register_types(void)
619
+ .fields = (VMStateField[]) {
508
+{
620
+ VMSTATE_UINT32_ARRAY(regs, AwRtcState, AW_RTC_REGS_NUM),
509
+ type_register_static(&resettable_interface_info);
621
+ VMSTATE_END_OF_LIST()
510
+}
622
+ }
511
+
623
+};
512
+type_init(reset_register_types)
624
+
513
diff --git a/hw/core/trace-events b/hw/core/trace-events
625
+static Property allwinner_rtc_properties[] = {
626
+ DEFINE_PROP_INT32("base-year", AwRtcState, base_year, 0),
627
+ DEFINE_PROP_END_OF_LIST(),
628
+};
629
+
630
+static void allwinner_rtc_class_init(ObjectClass *klass, void *data)
631
+{
632
+ DeviceClass *dc = DEVICE_CLASS(klass);
633
+
634
+ dc->reset = allwinner_rtc_reset;
635
+ dc->vmsd = &allwinner_rtc_vmstate;
636
+ device_class_set_props(dc, allwinner_rtc_properties);
637
+}
638
+
639
+static void allwinner_rtc_sun4i_init(Object *obj)
640
+{
641
+ AwRtcState *s = AW_RTC(obj);
642
+ s->base_year = 2010;
643
+}
644
+
645
+static void allwinner_rtc_sun4i_class_init(ObjectClass *klass, void *data)
646
+{
647
+ AwRtcClass *arc = AW_RTC_CLASS(klass);
648
+
649
+ arc->regmap = allwinner_rtc_sun4i_regmap;
650
+ arc->regmap_size = sizeof(allwinner_rtc_sun4i_regmap);
651
+ arc->read = allwinner_rtc_sun4i_read;
652
+ arc->write = allwinner_rtc_sun4i_write;
653
+}
654
+
655
+static void allwinner_rtc_sun6i_init(Object *obj)
656
+{
657
+ AwRtcState *s = AW_RTC(obj);
658
+ s->base_year = 1970;
659
+}
660
+
661
+static void allwinner_rtc_sun6i_class_init(ObjectClass *klass, void *data)
662
+{
663
+ AwRtcClass *arc = AW_RTC_CLASS(klass);
664
+
665
+ arc->regmap = allwinner_rtc_sun6i_regmap;
666
+ arc->regmap_size = sizeof(allwinner_rtc_sun6i_regmap);
667
+ arc->read = allwinner_rtc_sun6i_read;
668
+ arc->write = allwinner_rtc_sun6i_write;
669
+}
670
+
671
+static void allwinner_rtc_sun7i_init(Object *obj)
672
+{
673
+ AwRtcState *s = AW_RTC(obj);
674
+ s->base_year = 1970;
675
+}
676
+
677
+static void allwinner_rtc_sun7i_class_init(ObjectClass *klass, void *data)
678
+{
679
+ AwRtcClass *arc = AW_RTC_CLASS(klass);
680
+ allwinner_rtc_sun4i_class_init(klass, arc);
681
+}
682
+
683
+static const TypeInfo allwinner_rtc_info = {
684
+ .name = TYPE_AW_RTC,
685
+ .parent = TYPE_SYS_BUS_DEVICE,
686
+ .instance_init = allwinner_rtc_init,
687
+ .instance_size = sizeof(AwRtcState),
688
+ .class_init = allwinner_rtc_class_init,
689
+ .class_size = sizeof(AwRtcClass),
690
+ .abstract = true,
691
+};
692
+
693
+static const TypeInfo allwinner_rtc_sun4i_info = {
694
+ .name = TYPE_AW_RTC_SUN4I,
695
+ .parent = TYPE_AW_RTC,
696
+ .class_init = allwinner_rtc_sun4i_class_init,
697
+ .instance_init = allwinner_rtc_sun4i_init,
698
+};
699
+
700
+static const TypeInfo allwinner_rtc_sun6i_info = {
701
+ .name = TYPE_AW_RTC_SUN6I,
702
+ .parent = TYPE_AW_RTC,
703
+ .class_init = allwinner_rtc_sun6i_class_init,
704
+ .instance_init = allwinner_rtc_sun6i_init,
705
+};
706
+
707
+static const TypeInfo allwinner_rtc_sun7i_info = {
708
+ .name = TYPE_AW_RTC_SUN7I,
709
+ .parent = TYPE_AW_RTC,
710
+ .class_init = allwinner_rtc_sun7i_class_init,
711
+ .instance_init = allwinner_rtc_sun7i_init,
712
+};
713
+
714
+static void allwinner_rtc_register(void)
715
+{
716
+ type_register_static(&allwinner_rtc_info);
717
+ type_register_static(&allwinner_rtc_sun4i_info);
718
+ type_register_static(&allwinner_rtc_sun6i_info);
719
+ type_register_static(&allwinner_rtc_sun7i_info);
720
+}
721
+
722
+type_init(allwinner_rtc_register)
723
diff --git a/hw/rtc/trace-events b/hw/rtc/trace-events
514
index XXXXXXX..XXXXXXX 100644
724
index XXXXXXX..XXXXXXX 100644
515
--- a/hw/core/trace-events
725
--- a/hw/rtc/trace-events
516
+++ b/hw/core/trace-events
726
+++ b/hw/rtc/trace-events
517
@@ -XXX,XX +XXX,XX @@ qbus_reset(void *obj, const char *objtype) "obj=%p(%s)"
727
@@ -XXX,XX +XXX,XX @@
518
qbus_reset_all(void *obj, const char *objtype) "obj=%p(%s)"
728
# See docs/devel/tracing.txt for syntax documentation.
519
qbus_reset_tree(void *obj, const char *objtype) "obj=%p(%s)"
729
520
qdev_update_parent_bus(void *obj, const char *objtype, void *oldp, const char *oldptype, void *newp, const char *newptype) "obj=%p(%s) old_parent=%p(%s) new_parent=%p(%s)"
730
+# allwinner-rtc.c
521
+
731
+allwinner_rtc_read(uint64_t addr, uint64_t value) "addr 0x%" PRIx64 " value 0x%" PRIx64
522
+# resettable.c
732
+allwinner_rtc_write(uint64_t addr, uint64_t value) "addr 0x%" PRIx64 " value 0x%" PRIx64
523
+resettable_reset(void *obj, int cold) "obj=%p cold=%d"
733
+
524
+resettable_reset_assert_begin(void *obj, int cold) "obj=%p cold=%d"
734
# sun4v-rtc.c
525
+resettable_reset_assert_end(void *obj) "obj=%p"
735
sun4v_rtc_read(uint64_t addr, uint64_t value) "read: addr 0x%" PRIx64 " value 0x%" PRIx64
526
+resettable_reset_release_begin(void *obj, int cold) "obj=%p cold=%d"
736
sun4v_rtc_write(uint64_t addr, uint64_t value) "write: addr 0x%" PRIx64 " value 0x%" PRIx64
527
+resettable_reset_release_end(void *obj) "obj=%p"
528
+resettable_phase_enter_begin(void *obj, const char *objtype, unsigned count, int type) "obj=%p(%s) count=%d type=%d"
529
+resettable_phase_enter_exec(void *obj, const char *objtype, int type, int has_method) "obj=%p(%s) type=%d method=%d"
530
+resettable_phase_enter_end(void *obj, const char *objtype, unsigned count) "obj=%p(%s) count=%d"
531
+resettable_phase_hold_begin(void *obj, const char *objtype, unsigned count, int type) "obj=%p(%s) count=%d type=%d"
532
+resettable_phase_hold_exec(void *obj, const char *objtype, int has_method) "obj=%p(%s) method=%d"
533
+resettable_phase_hold_end(void *obj, const char *objtype, unsigned count) "obj=%p(%s) count=%d"
534
+resettable_phase_exit_begin(void *obj, const char *objtype, unsigned count, int type) "obj=%p(%s) count=%d type=%d"
535
+resettable_phase_exit_exec(void *obj, const char *objtype, int has_method) "obj=%p(%s) method=%d"
536
+resettable_phase_exit_end(void *obj, const char *objtype, unsigned count) "obj=%p(%s) count=%d"
537
+resettable_transitional_function(void *obj, const char *objtype) "obj=%p(%s)"
538
--
737
--
539
2.20.1
738
2.20.1
540
739
541
740
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
This test boots a Linux kernel on a OrangePi PC board and verify
4
the serial output is working.
5
6
The kernel image and DeviceTree blob are built by the Armbian
7
project (based on Debian):
8
https://www.armbian.com/orange-pi-pc/
9
10
If ARM is a target being built, "make check-acceptance" will
11
automatically include this test by the use of the "arch:arm" tags.
12
13
Alternatively, this test can be run using:
14
15
$ make check-venv
16
$ ./tests/venv/bin/avocado --show=console,app run -t machine:orangepi-pc tests/acceptance/boot_linux_console.py
17
JOB ID : 2e4d15eceb13c33672af406f08171e6e9de1414a
18
JOB LOG : ~/job-results/job-2019-12-17T05.46-2e4d15e/job.log
19
(1/1) tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_arm_orangepi:
20
console: Uncompressing Linux... done, booting the kernel.
21
console: Booting Linux on physical CPU 0x0
22
console: Linux version 4.20.7-sunxi (root@armbian.com) (gcc version 7.2.1 20171011 (Linaro GCC 7.2-2017.11)) #5.75 SMP Fri Feb 8 09:02:10 CET 2019
23
console: CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=50c5387d
24
console: CPU: div instructions available: patching division code
25
console: CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
26
console: OF: fdt: Machine model: Xunlong Orange Pi PC
27
console: Memory policy: Data cache writealloc
28
console: OF: reserved mem: failed to allocate memory for node 'cma@4a000000'
29
console: cma: Failed to reserve 128 MiB
30
console: psci: probing for conduit method from DT.
31
console: psci: PSCIv0.2 detected in firmware.
32
console: psci: Using standard PSCI v0.2 function IDs
33
console: psci: Trusted OS migration not required
34
console: random: get_random_bytes called from start_kernel+0x8d/0x3c2 with crng_init=0
35
console: percpu: Embedded 18 pages/cpu @(ptrval) s41228 r8192 d24308 u73728
36
console: Built 1 zonelists, mobility grouping on. Total pages: 32480
37
console: Kernel command line: printk.time=0 console=ttyS0,115200
38
PASS (8.59 s)
39
JOB TIME : 8.81 s
40
41
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
42
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
43
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
44
Tested-by: Alex Bennée <alex.bennee@linaro.org>
45
Message-id: 20200311221854.30370-14-nieklinnenbank@gmail.com
46
[NL: rename in commit message Raspbian to Armbian, remove vm.set_machine()]
47
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
48
---
49
tests/acceptance/boot_linux_console.py | 25 +++++++++++++++++++++++++
50
1 file changed, 25 insertions(+)
51
52
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
53
index XXXXXXX..XXXXXXX 100644
54
--- a/tests/acceptance/boot_linux_console.py
55
+++ b/tests/acceptance/boot_linux_console.py
56
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(Test):
57
exec_command_and_wait_for_pattern(self, 'reboot',
58
'reboot: Restarting system')
59
60
+ def test_arm_orangepi(self):
61
+ """
62
+ :avocado: tags=arch:arm
63
+ :avocado: tags=machine:orangepi-pc
64
+ """
65
+ deb_url = ('https://apt.armbian.com/pool/main/l/'
66
+ 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
67
+ deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
68
+ deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
69
+ kernel_path = self.extract_from_deb(deb_path,
70
+ '/boot/vmlinuz-4.20.7-sunxi')
71
+ dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb'
72
+ dtb_path = self.extract_from_deb(deb_path, dtb_path)
73
+
74
+ self.vm.set_console()
75
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
76
+ 'console=ttyS0,115200n8 '
77
+ 'earlycon=uart,mmio32,0x1c28000')
78
+ self.vm.add_args('-kernel', kernel_path,
79
+ '-dtb', dtb_path,
80
+ '-append', kernel_command_line)
81
+ self.vm.launch()
82
+ console_pattern = 'Kernel command line: %s' % kernel_command_line
83
+ self.wait_for_console_pattern(console_pattern)
84
+
85
def test_s390x_s390_ccw_virtio(self):
86
"""
87
:avocado: tags=arch:s390x
88
--
89
2.20.1
90
91
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
This test boots a Linux kernel on a OrangePi PC board and verify
4
the serial output is working.
5
6
The kernel image and DeviceTree blob are built by the Armbian
7
project (based on Debian):
8
https://www.armbian.com/orange-pi-pc/
9
10
The cpio image used comes from the linux-build-test project:
11
https://github.com/groeck/linux-build-test
12
13
If ARM is a target being built, "make check-acceptance" will
14
automatically include this test by the use of the "arch:arm" tags.
15
16
Alternatively, this test can be run using:
17
18
$ avocado --show=console run -t machine:orangepi-pc tests/acceptance/boot_linux_console.py
19
console: Uncompressing Linux... done, booting the kernel.
20
console: Booting Linux on physical CPU 0x0
21
console: Linux version 4.20.7-sunxi (root@armbian.com) (gcc version 7.2.1 20171011 (Linaro GCC 7.2-2017.11)) #5.75 SMP Fri Feb 8 09:02:10 CET 2019
22
console: CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=50c5387d
23
console: CPU: div instructions available: patching division code
24
console: CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
25
console: OF: fdt: Machine model: Xunlong Orange Pi PC
26
[...]
27
console: Trying to unpack rootfs image as initramfs...
28
console: Freeing initrd memory: 3256K
29
console: Freeing unused kernel memory: 1024K
30
console: Run /init as init process
31
console: mount: mounting devtmpfs on /dev failed: Device or resource busy
32
console: Starting logging: OK
33
console: Initializing random number generator... random: dd: uninitialized urandom read (512 bytes read)
34
console: done.
35
console: Starting network: OK
36
console: Found console ttyS0
37
console: Linux version 4.20.7-sunxi (root@armbian.com) (gcc version 7.2.1 20171011 (Linaro GCC 7.2-2017.11)) #5.75 SMP Fri Feb 8 09:02:10 CET 2019
38
console: Boot successful.
39
console: cat /proc/cpuinfo
40
console: / # cat /proc/cpuinfo
41
console: processor : 0
42
console: model name : ARMv7 Processor rev 5 (v7l)
43
console: BogoMIPS : 125.00
44
console: Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm
45
console: CPU implementer : 0x41
46
console: CPU architecture: 7
47
console: CPU variant : 0x0
48
console: CPU part : 0xc07
49
console: CPU revision : 5
50
[...]
51
console: processor : 3
52
console: model name : ARMv7 Processor rev 5 (v7l)
53
console: BogoMIPS : 125.00
54
console: Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm
55
console: CPU implementer : 0x41
56
console: CPU architecture: 7
57
console: CPU variant : 0x0
58
console: CPU part : 0xc07
59
console: CPU revision : 5
60
console: Hardware : Allwinner sun8i Family
61
console: Revision : 0000
62
console: Serial : 0000000000000000
63
console: cat /proc/iomem
64
console: / # cat /proc/iomem
65
console: 01000000-010fffff : clock@1000000
66
console: 01c00000-01c00fff : system-control@1c00000
67
console: 01c02000-01c02fff : dma-controller@1c02000
68
[...]
69
console: reboot
70
console: / # reboot
71
console: / # Found console ttyS0
72
console: Stopping network: OK
73
console: hrtimer: interrupt took 21852064 ns
74
console: Saving random seed... random: dd: uninitialized urandom read (512 bytes read)
75
console: done.
76
console: Stopping logging: OK
77
console: umount: devtmpfs busy - remounted read-only
78
console: umount: can't unmount /: Invalid argument
79
console: The system is going down NOW!
80
console: Sent SIGTERM to all processes
81
console: Sent SIGKILL to all processes
82
console: Requesting system reboot
83
console: reboot: Restarting system
84
PASS (48.32 s)
85
JOB TIME : 49.16 s
86
87
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
88
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
89
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
90
Tested-by: Alex Bennée <alex.bennee@linaro.org>
91
Message-id: 20200311221854.30370-15-nieklinnenbank@gmail.com
92
[NL: rename in commit message Raspbian to Armbian, remove vm.set_machine()]
93
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
94
---
95
tests/acceptance/boot_linux_console.py | 40 ++++++++++++++++++++++++++
96
1 file changed, 40 insertions(+)
97
98
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
99
index XXXXXXX..XXXXXXX 100644
100
--- a/tests/acceptance/boot_linux_console.py
101
+++ b/tests/acceptance/boot_linux_console.py
102
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(Test):
103
console_pattern = 'Kernel command line: %s' % kernel_command_line
104
self.wait_for_console_pattern(console_pattern)
105
106
+ def test_arm_orangepi_initrd(self):
107
+ """
108
+ :avocado: tags=arch:arm
109
+ :avocado: tags=machine:orangepi-pc
110
+ """
111
+ deb_url = ('https://apt.armbian.com/pool/main/l/'
112
+ 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
113
+ deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
114
+ deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
115
+ kernel_path = self.extract_from_deb(deb_path,
116
+ '/boot/vmlinuz-4.20.7-sunxi')
117
+ dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb'
118
+ dtb_path = self.extract_from_deb(deb_path, dtb_path)
119
+ initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
120
+ '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
121
+ 'arm/rootfs-armv7a.cpio.gz')
122
+ initrd_hash = '604b2e45cdf35045846b8bbfbf2129b1891bdc9c'
123
+ initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
124
+ initrd_path = os.path.join(self.workdir, 'rootfs.cpio')
125
+ archive.gzip_uncompress(initrd_path_gz, initrd_path)
126
+
127
+ self.vm.set_console()
128
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
129
+ 'console=ttyS0,115200 '
130
+ 'panic=-1 noreboot')
131
+ self.vm.add_args('-kernel', kernel_path,
132
+ '-dtb', dtb_path,
133
+ '-initrd', initrd_path,
134
+ '-append', kernel_command_line,
135
+ '-no-reboot')
136
+ self.vm.launch()
137
+ self.wait_for_console_pattern('Boot successful.')
138
+
139
+ exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
140
+ 'Allwinner sun8i Family')
141
+ exec_command_and_wait_for_pattern(self, 'cat /proc/iomem',
142
+ 'system-control@1c00000')
143
+ exec_command_and_wait_for_pattern(self, 'reboot',
144
+ 'reboot: Restarting system')
145
+
146
def test_s390x_s390_ccw_virtio(self):
147
"""
148
:avocado: tags=arch:s390x
149
--
150
2.20.1
151
152
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
The kernel image and DeviceTree blob are built by the Armbian
4
project (based on Debian):
5
https://www.armbian.com/orange-pi-pc/
6
7
The SD image is from the kernelci.org project:
8
https://kernelci.org/faq/#the-code
9
10
If ARM is a target being built, "make check-acceptance" will
11
automatically include this test by the use of the "arch:arm" tags.
12
13
Alternatively, this test can be run using:
14
15
$ avocado --show=console run -t machine:orangepi-pc tests/acceptance/boot_linux_console.py
16
console: Uncompressing Linux... done, booting the kernel.
17
console: Booting Linux on physical CPU 0x0
18
console: Linux version 4.20.7-sunxi (root@armbian.com) (gcc version 7.2.1 20171011 (Linaro GCC 7.2-2017.11)) #5.75 SMP Fri Feb 8 09:02:10 CET 2019
19
console: CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=50c5387d
20
[...]
21
console: sunxi-wdt 1c20ca0.watchdog: Watchdog enabled (timeout=16 sec, nowayout=0)
22
console: sunxi-mmc 1c0f000.mmc: Linked as a consumer to regulator.2
23
console: sunxi-mmc 1c0f000.mmc: Got CD GPIO
24
console: ledtrig-cpu: registered to indicate activity on CPUs
25
console: hidraw: raw HID events driver (C) Jiri Kosina
26
console: usbcore: registered new interface driver usbhid
27
console: usbhid: USB HID core driver
28
console: Initializing XFRM netlink socket
29
console: sunxi-mmc 1c0f000.mmc: initialized, max. request size: 16384 KB
30
console: NET: Registered protocol family 10
31
console: mmc0: host does not support reading read-only switch, assuming write-enable
32
console: mmc0: Problem switching card into high-speed mode!
33
console: mmc0: new SD card at address 4567
34
console: mmcblk0: mmc0:4567 QEMU! 60.0 MiB
35
[...]
36
console: EXT4-fs (mmcblk0): mounting ext2 file system using the ext4 subsystem
37
console: EXT4-fs (mmcblk0): mounted filesystem without journal. Opts: (null)
38
console: VFS: Mounted root (ext2 filesystem) on device 179:0.
39
console: Run /sbin/init as init process
40
console: EXT4-fs (mmcblk0): re-mounted. Opts: block_validity,barrier,user_xattr,acl
41
console: Starting syslogd: OK
42
console: Starting klogd: OK
43
console: Populating /dev using udev: udevd[203]: starting version 3.2.7
44
console: /bin/sh: can't access tty; job control turned off
45
console: cat /proc/partitions
46
console: / # cat /proc/partitions
47
console: major minor #blocks name
48
console: 1 0 4096 ram0
49
console: 1 1 4096 ram1
50
console: 1 2 4096 ram2
51
console: 1 3 4096 ram3
52
console: 179 0 61440 mmcblk0
53
console: reboot
54
console: / # reboot
55
console: umount: devtmpfs busy - remounted read-only
56
console: EXT4-fs (mmcblk0): re-mounted. Opts: (null)
57
console: The system is going down NOW!
58
console: Sent SIGTERM to all processes
59
console: Sent SIGKILL to all processes
60
console: Requesting system reboot
61
console: reboot: Restarting system
62
JOB TIME : 68.64 s
63
64
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
65
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
66
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
67
Tested-by: Alex Bennée <alex.bennee@linaro.org>
68
Message-id: 20200311221854.30370-16-nieklinnenbank@gmail.com
69
[NL: rename in commit message Raspbian to Armbian, remove vm.set_machine()]
70
[NL: extend test with ethernet device checks]
71
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
72
---
73
tests/acceptance/boot_linux_console.py | 47 ++++++++++++++++++++++++++
74
1 file changed, 47 insertions(+)
75
76
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
77
index XXXXXXX..XXXXXXX 100644
78
--- a/tests/acceptance/boot_linux_console.py
79
+++ b/tests/acceptance/boot_linux_console.py
80
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(Test):
81
exec_command_and_wait_for_pattern(self, 'reboot',
82
'reboot: Restarting system')
83
84
+ def test_arm_orangepi_sd(self):
85
+ """
86
+ :avocado: tags=arch:arm
87
+ :avocado: tags=machine:orangepi-pc
88
+ """
89
+ deb_url = ('https://apt.armbian.com/pool/main/l/'
90
+ 'linux-4.20.7-sunxi/linux-image-dev-sunxi_5.75_armhf.deb')
91
+ deb_hash = '1334c29c44d984ffa05ed10de8c3361f33d78315'
92
+ deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
93
+ kernel_path = self.extract_from_deb(deb_path,
94
+ '/boot/vmlinuz-4.20.7-sunxi')
95
+ dtb_path = '/usr/lib/linux-image-dev-sunxi/sun8i-h3-orangepi-pc.dtb'
96
+ dtb_path = self.extract_from_deb(deb_path, dtb_path)
97
+ rootfs_url = ('http://storage.kernelci.org/images/rootfs/buildroot/'
98
+ 'kci-2019.02/armel/base/rootfs.ext2.xz')
99
+ rootfs_hash = '692510cb625efda31640d1de0a8d60e26040f061'
100
+ rootfs_path_xz = self.fetch_asset(rootfs_url, asset_hash=rootfs_hash)
101
+ rootfs_path = os.path.join(self.workdir, 'rootfs.cpio')
102
+ archive.lzma_uncompress(rootfs_path_xz, rootfs_path)
103
+
104
+ self.vm.set_console()
105
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
106
+ 'console=ttyS0,115200 '
107
+ 'root=/dev/mmcblk0 rootwait rw '
108
+ 'panic=-1 noreboot')
109
+ self.vm.add_args('-kernel', kernel_path,
110
+ '-dtb', dtb_path,
111
+ '-drive', 'file=' + rootfs_path + ',if=sd,format=raw',
112
+ '-append', kernel_command_line,
113
+ '-no-reboot')
114
+ self.vm.launch()
115
+ shell_ready = "/bin/sh: can't access tty; job control turned off"
116
+ self.wait_for_console_pattern(shell_ready)
117
+
118
+ exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
119
+ 'Allwinner sun8i Family')
120
+ exec_command_and_wait_for_pattern(self, 'cat /proc/partitions',
121
+ 'mmcblk0')
122
+ exec_command_and_wait_for_pattern(self, 'ifconfig eth0 up',
123
+ 'eth0: Link is Up')
124
+ exec_command_and_wait_for_pattern(self, 'udhcpc eth0',
125
+ 'udhcpc: lease of 10.0.2.15 obtained')
126
+ exec_command_and_wait_for_pattern(self, 'ping -c 3 10.0.2.2',
127
+ '3 packets transmitted, 3 packets received, 0% packet loss')
128
+ exec_command_and_wait_for_pattern(self, 'reboot',
129
+ 'reboot: Restarting system')
130
+
131
def test_s390x_s390_ccw_virtio(self):
132
"""
133
:avocado: tags=arch:s390x
134
--
135
2.20.1
136
137
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
If we know what the default value should be then we can test for
3
This test boots Ubuntu Bionic on a OrangePi PC board.
4
that as well as the feature existence.
5
4
6
Signed-off-by: Andrew Jones <drjones@redhat.com>
5
As it requires 1GB of storage, and is slow, this test is disabled
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
on automatic CI testing.
8
Message-id: 20200120101023.16030-5-drjones@redhat.com
7
8
It is useful for workstation testing. Currently Avocado timeouts too
9
quickly, so we can't run userland commands.
10
11
The kernel image and DeviceTree blob are built by the Armbian
12
project (based on Debian):
13
https://www.armbian.com/orange-pi-pc/
14
15
The Ubuntu image is downloaded from:
16
https://dl.armbian.com/orangepipc/Bionic_current
17
18
This test can be run using:
19
20
$ AVOCADO_ALLOW_LARGE_STORAGE=yes \
21
avocado --show=app,console run -t machine:orangepi-pc \
22
tests/acceptance/boot_linux_console.py
23
console: U-Boot SPL 2019.04-armbian (Nov 18 2019 - 23:08:35 +0100)
24
console: DRAM: 1024 MiB
25
console: Failed to set core voltage! Can't set CPU frequency
26
console: Trying to boot from MMC1
27
console: U-Boot 2019.04-armbian (Nov 18 2019 - 23:08:35 +0100) Allwinner Technology
28
console: CPU: Allwinner H3 (SUN8I 0000)
29
console: Model: Xunlong Orange Pi PC
30
console: DRAM: 1 GiB
31
console: MMC: mmc@1c0f000: 0
32
[...]
33
console: Uncompressing Linux... done, booting the kernel.
34
console: Booting Linux on physical CPU 0x0
35
console: Linux version 5.3.9-sunxi (root@builder) (gcc version 8.3.0 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36))) #19.11.3 SMP Mon Nov 18 18:49:43 CET 2019
36
console: CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=50c5387d
37
console: CPU: div instructions available: patching division code
38
console: CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
39
console: OF: fdt: Machine model: Xunlong Orange Pi PC
40
[...]
41
console: EXT4-fs (mmcblk0p1): mounted filesystem with writeback data mode. Opts: (null)
42
console: done.
43
console: Begin: Running /scripts/local-bottom ... done.
44
console: Begin: Running /scripts/init-bottom ... done.
45
console: systemd[1]: systemd 237 running in system mode. (...)
46
console: systemd[1]: Detected architecture arm.
47
console: Welcome to Ubuntu 18.04.3 LTS!
48
console: systemd[1]: Set hostname to <orangepipc>.
49
50
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
51
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
52
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
53
Tested-by: Alex Bennée <alex.bennee@linaro.org>
54
Message-id: 20200311221854.30370-17-nieklinnenbank@gmail.com
55
[NL: rename in commit message Raspbian to Armbian, remove vm.set_machine()]
56
[NL: changed test to boot from SD card via BootROM, added check for 7z]
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
57
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
58
---
11
tests/qtest/arm-cpu-features.c | 37 +++++++++++++++++++++++++---------
59
tests/acceptance/boot_linux_console.py | 48 ++++++++++++++++++++++++++
12
1 file changed, 28 insertions(+), 9 deletions(-)
60
1 file changed, 48 insertions(+)
13
61
14
diff --git a/tests/qtest/arm-cpu-features.c b/tests/qtest/arm-cpu-features.c
62
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
15
index XXXXXXX..XXXXXXX 100644
63
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/qtest/arm-cpu-features.c
64
--- a/tests/acceptance/boot_linux_console.py
17
+++ b/tests/qtest/arm-cpu-features.c
65
+++ b/tests/acceptance/boot_linux_console.py
18
@@ -XXX,XX +XXX,XX @@ static bool resp_get_feature(QDict *resp, const char *feature)
66
@@ -XXX,XX +XXX,XX @@ from avocado_qemu import exec_command_and_wait_for_pattern
19
qobject_unref(_resp); \
67
from avocado_qemu import wait_for_console_pattern
20
})
68
from avocado.utils import process
21
69
from avocado.utils import archive
22
+#define assert_feature(qts, cpu_type, feature, expected_value) \
70
+from avocado.utils.path import find_command, CmdNotFoundError
23
+({ \
71
24
+ QDict *_resp, *_props; \
72
+P7ZIP_AVAILABLE = True
25
+ \
73
+try:
26
+ _resp = do_query_no_props(qts, cpu_type); \
74
+ find_command('7z')
27
+ g_assert(_resp); \
75
+except CmdNotFoundError:
28
+ g_assert(resp_has_props(_resp)); \
76
+ P7ZIP_AVAILABLE = False
29
+ _props = resp_get_props(_resp); \
77
30
+ g_assert(qdict_get(_props, feature)); \
78
class BootLinuxConsole(Test):
31
+ g_assert(qdict_get_bool(_props, feature) == (expected_value)); \
79
"""
32
+ qobject_unref(_resp); \
80
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(Test):
33
+})
81
exec_command_and_wait_for_pattern(self, 'reboot',
82
'reboot: Restarting system')
83
84
+ @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
85
+ @skipUnless(P7ZIP_AVAILABLE, '7z not installed')
86
+ def test_arm_orangepi_bionic(self):
87
+ """
88
+ :avocado: tags=arch:arm
89
+ :avocado: tags=machine:orangepi-pc
90
+ """
34
+
91
+
35
+#define assert_has_feature_enabled(qts, cpu_type, feature) \
92
+ # This test download a 196MB compressed image and expand it to 932MB...
36
+ assert_feature(qts, cpu_type, feature, true)
93
+ image_url = ('https://dl.armbian.com/orangepipc/archive/'
94
+ 'Armbian_19.11.3_Orangepipc_bionic_current_5.3.9.7z')
95
+ image_hash = '196a8ffb72b0123d92cea4a070894813d305c71e'
96
+ image_path_7z = self.fetch_asset(image_url, asset_hash=image_hash)
97
+ image_name = 'Armbian_19.11.3_Orangepipc_bionic_current_5.3.9.img'
98
+ image_path = os.path.join(self.workdir, image_name)
99
+ process.run("7z e -o%s %s" % (self.workdir, image_path_7z))
37
+
100
+
38
+#define assert_has_feature_disabled(qts, cpu_type, feature) \
101
+ self.vm.set_console()
39
+ assert_feature(qts, cpu_type, feature, false)
102
+ self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw',
103
+ '-nic', 'user',
104
+ '-no-reboot')
105
+ self.vm.launch()
40
+
106
+
41
static void assert_type_full(QTestState *qts)
107
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
42
{
108
+ 'console=ttyS0,115200 '
43
const char *error;
109
+ 'loglevel=7 '
44
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion(const void *data)
110
+ 'nosmp '
45
assert_error(qts, "host", "The CPU type 'host' requires KVM", NULL);
111
+ 'systemd.default_timeout_start_sec=9000 '
46
112
+ 'systemd.mask=armbian-zram-config.service '
47
/* Test expected feature presence/absence for some cpu types */
113
+ 'systemd.mask=armbian-ramlog.service')
48
- assert_has_feature(qts, "max", "pmu");
114
+
49
- assert_has_feature(qts, "cortex-a15", "pmu");
115
+ self.wait_for_console_pattern('U-Boot SPL')
50
+ assert_has_feature_enabled(qts, "max", "pmu");
116
+ self.wait_for_console_pattern('Autoboot in ')
51
+ assert_has_feature_enabled(qts, "cortex-a15", "pmu");
117
+ exec_command_and_wait_for_pattern(self, ' ', '=>')
52
assert_has_not_feature(qts, "cortex-a15", "aarch64");
118
+ exec_command_and_wait_for_pattern(self, "setenv extraargs '" +
53
119
+ kernel_command_line + "'", '=>')
54
if (g_str_equal(qtest_get_arch(), "aarch64")) {
120
+ exec_command_and_wait_for_pattern(self, 'boot', 'Starting kernel ...');
55
- assert_has_feature(qts, "max", "aarch64");
121
+
56
- assert_has_feature(qts, "max", "sve");
122
+ self.wait_for_console_pattern('systemd[1]: Set hostname ' +
57
- assert_has_feature(qts, "max", "sve128");
123
+ 'to <orangepipc>')
58
- assert_has_feature(qts, "cortex-a57", "pmu");
124
+ self.wait_for_console_pattern('Starting Load Kernel Modules...')
59
- assert_has_feature(qts, "cortex-a57", "aarch64");
125
+
60
+ assert_has_feature_enabled(qts, "max", "aarch64");
126
def test_s390x_s390_ccw_virtio(self):
61
+ assert_has_feature_enabled(qts, "max", "sve");
127
"""
62
+ assert_has_feature_enabled(qts, "max", "sve128");
128
:avocado: tags=arch:s390x
63
+ assert_has_feature_enabled(qts, "cortex-a57", "pmu");
64
+ assert_has_feature_enabled(qts, "cortex-a57", "aarch64");
65
66
sve_tests_default(qts, "max");
67
68
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion_kvm(const void *data)
69
QDict *resp;
70
char *error;
71
72
- assert_has_feature(qts, "host", "aarch64");
73
- assert_has_feature(qts, "host", "pmu");
74
+ assert_has_feature_enabled(qts, "host", "aarch64");
75
+ assert_has_feature_enabled(qts, "host", "pmu");
76
77
assert_error(qts, "cortex-a15",
78
"We cannot guarantee the CPU type 'cortex-a15' works "
79
--
129
--
80
2.20.1
130
2.20.1
81
131
82
132
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Since we enabled parallel TCG code generation for softmmu (see
3
This test boots U-Boot then NetBSD (stored on a SD card) on
4
commit 3468b59 "tcg: enable multiple TCG contexts in softmmu")
4
a OrangePi PC board.
5
and its subsequent fix (commit 72649619 "add .min_cpus and
6
.default_cpus fields to machine_class"), the raspi machines are
7
restricted to always use their 4 cores:
8
5
9
See in hw/arm/raspi2 (with BCM283X_NCPUS set to 4):
6
As it requires ~1.3GB of storage, it is disabled by default.
10
7
11
222 static void raspi2_machine_init(MachineClass *mc)
8
U-Boot is built by the Debian project [1], and the SD card image
12
223 {
9
is provided by the NetBSD organization [2].
13
224 mc->desc = "Raspberry Pi 2";
14
230 mc->max_cpus = BCM283X_NCPUS;
15
231 mc->min_cpus = BCM283X_NCPUS;
16
232 mc->default_cpus = BCM283X_NCPUS;
17
235 };
18
236 DEFINE_MACHINE("raspi2", raspi2_machine_init)
19
10
20
We can no longer use the -smp option, as we get:
11
Once the compressed SD card image is downloaded (304MB) and
12
extracted, this test is fast:
21
13
22
$ qemu-system-arm -M raspi2 -smp 1
14
$ AVOCADO_ALLOW_LARGE_STORAGE=yes \
23
qemu-system-arm: Invalid SMP CPUs 1. The min CPUs supported by machine 'raspi2' is 4
15
avocado --show=app,console run -t machine:orangepi-pc \
16
tests/acceptance/boot_linux_console.py
17
console: U-Boot SPL 2020.01+dfsg-1 (Jan 08 2020 - 08:19:44 +0000)
18
console: DRAM: 1024 MiB
19
console: U-Boot 2020.01+dfsg-1 (Jan 08 2020 - 08:19:44 +0000) Allwinner Technology
20
console: CPU: Allwinner H3 (SUN8I 0000)
21
console: scanning bus usb@1c1b000 for devices... 1 USB Device(s) found
22
console: scanning bus usb@1c1d000 for devices... 1 USB Device(s) found
23
console: scanning usb for storage devices... 0 Storage Device(s) found
24
console: Hit any key to stop autoboot: 0
25
console: => setenv bootargs root=ld0a
26
console: => setenv kernel netbsd-GENERIC.ub
27
console: => setenv fdtfile dtb/sun8i-h3-orangepi-pc.dtb
28
console: => boot
29
console: ## Booting kernel from Legacy Image at 42000000 ...
30
console: Image Name: NetBSD/earmv7hf 9.0_RC1
31
console: Image Type: ARM Linux Kernel Image (no loading done) (uncompressed)
32
console: XIP Kernel Image (no loading done)
33
console: Loading Device Tree to 49ff6000, end 49fffe01 ... OK
34
console: Starting kernel ...
35
console: [ 1.0000000] NetBSD/evbarm (fdt) booting ...
36
console: [ 1.0000000] NetBSD 9.0 (GENERIC) #0: Fri Feb 14 00:06:28 UTC 2020
37
console: [ 1.0000000] mkrepro@mkrepro.NetBSD.org:/usr/src/sys/arch/evbarm/compile/GENERIC
38
console: [ 1.0000000] total memory = 1024 MB
39
console: [ 1.0000000] avail memory = 1003 MB
40
console: [ 1.0000000] armfdt0 (root)
41
console: [ 1.0000000] simplebus0 at armfdt0: Xunlong Orange Pi PC
42
console: [ 1.0000000] cpu0 at cpus0: Cortex-A7 r0p5 (Cortex V7A core)
43
console: [ 1.0000000] cpu0: DC enabled IC enabled WB enabled LABT branch prediction enabled
44
console: [ 1.0000000] cpu0: 32KB/64B 2-way L1 VIPT Instruction cache
45
console: [ 1.0000000] cpu0: 32KB/64B 2-way write-back-locking-C L1 PIPT Data cache
46
console: [ 1.0000000] cpu0: 2304KB/64B 16-way write-through L2 PIPT Unified cache
47
console: [ 1.0000000] vfp0 at cpu0: NEON MPE (VFP 3.0+), rounding, NaN propagation, denormals
48
...
49
console: [ 2.3812082] sdmmc0: SD card status: 4-bit, C0
50
console: [ 2.3812082] ld0 at sdmmc0: <0xaa:0x5859:QEMU!:0x01:0xdeadbeef:0x062>
51
console: [ 2.4012856] ld0: 1226 MB, 622 cyl, 64 head, 63 sec, 512 bytes/sect x 2511872 sectors
52
console: [ 2.5321222] ld0: 4-bit width, High-Speed/SDR25, 50.000 MHz
53
console: [ 3.1068718] WARNING: 4 errors while detecting hardware; check system log.
54
console: [ 3.1179868] boot device: ld0
55
console: [ 3.1470623] root on ld0a dumps on ld0b
56
console: [ 3.2464436] root file system type: ffs
57
console: [ 3.2897123] kern.module.path=/stand/evbarm/9.0/modules
58
console: Mon Feb 17 20:33:35 UTC 2020
59
console: Starting root file system check:
60
PASS (35.96 s)
61
RESULTS : PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0
62
JOB TIME : 36.09 s
24
63
25
Since we can not set the TYPE_BCM283x SOC "enabled-cpus" with -smp,
64
Note, this test only took ~65 seconds to run on Travis-CI, see: [3].
26
remove the unuseful code.
27
65
28
We can achieve the same by using the '-global bcm2836.enabled-cpus=1'
66
This test is based on a description from Niek Linnenbank from [4].
29
option.
30
67
31
Reported-by: Laurent Bonnans <laurent.bonnans@here.com>
68
[1] https://wiki.debian.org/InstallingDebianOn/Allwinner#Creating_a_bootable_SD_Card_with_u-boot
69
[2] https://wiki.netbsd.org/ports/evbarm/allwinner/
70
[3] https://travis-ci.org/philmd/qemu/jobs/638823612#L3778
71
[4] https://www.mail-archive.com/qemu-devel@nongnu.org/msg669347.html
72
32
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
73
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
33
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
74
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
34
Message-id: 20200120235159.18510-2-f4bug@amsat.org
75
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
76
Tested-by: Alex Bennée <alex.bennee@linaro.org>
77
Message-id: 20200311221854.30370-18-nieklinnenbank@gmail.com
78
[NL: changed test to use NetBSD 9.0 final release and -global allwinner-rtc.base-year]
35
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
79
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
36
---
80
---
37
hw/arm/raspi.c | 2 --
81
tests/acceptance/boot_linux_console.py | 70 ++++++++++++++++++++++++++
38
1 file changed, 2 deletions(-)
82
1 file changed, 70 insertions(+)
39
83
40
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
84
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
41
index XXXXXXX..XXXXXXX 100644
85
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/arm/raspi.c
86
--- a/tests/acceptance/boot_linux_console.py
43
+++ b/hw/arm/raspi.c
87
+++ b/tests/acceptance/boot_linux_console.py
44
@@ -XXX,XX +XXX,XX @@ static void raspi_init(MachineState *machine, int version)
88
@@ -XXX,XX +XXX,XX @@ import shutil
45
/* Setup the SOC */
89
from avocado import skipUnless
46
object_property_add_const_link(OBJECT(&s->soc), "ram", OBJECT(&s->ram),
90
from avocado_qemu import Test
47
&error_abort);
91
from avocado_qemu import exec_command_and_wait_for_pattern
48
- object_property_set_int(OBJECT(&s->soc), machine->smp.cpus, "enabled-cpus",
92
+from avocado_qemu import interrupt_interactive_console_until_pattern
49
- &error_abort);
93
from avocado_qemu import wait_for_console_pattern
50
int board_rev = version == 3 ? 0xa02082 : 0xa21041;
94
from avocado.utils import process
51
object_property_set_int(OBJECT(&s->soc), board_rev, "board-rev",
95
from avocado.utils import archive
52
&error_abort);
96
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(Test):
97
'to <orangepipc>')
98
self.wait_for_console_pattern('Starting Load Kernel Modules...')
99
100
+ @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
101
+ def test_arm_orangepi_uboot_netbsd9(self):
102
+ """
103
+ :avocado: tags=arch:arm
104
+ :avocado: tags=machine:orangepi-pc
105
+ """
106
+ # This test download a 304MB compressed image and expand it to 1.3GB...
107
+ deb_url = ('http://snapshot.debian.org/archive/debian/'
108
+ '20200108T145233Z/pool/main/u/u-boot/'
109
+ 'u-boot-sunxi_2020.01%2Bdfsg-1_armhf.deb')
110
+ deb_hash = 'f67f404a80753ca3d1258f13e38f2b060e13db99'
111
+ deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
112
+ # We use the common OrangePi PC 'plus' build of U-Boot for our secondary
113
+ # program loader (SPL). We will then set the path to the more specific
114
+ # OrangePi "PC" device tree blob with 'setenv fdtfile' in U-Boot prompt,
115
+ # before to boot NetBSD.
116
+ uboot_path = '/usr/lib/u-boot/orangepi_plus/u-boot-sunxi-with-spl.bin'
117
+ uboot_path = self.extract_from_deb(deb_path, uboot_path)
118
+ image_url = ('https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.0/'
119
+ 'evbarm-earmv7hf/binary/gzimg/armv7.img.gz')
120
+ image_hash = '2babb29d36d8360adcb39c09e31060945259917a'
121
+ image_path_gz = self.fetch_asset(image_url, asset_hash=image_hash)
122
+ image_path = os.path.join(self.workdir, 'armv7.img')
123
+ image_drive_args = 'if=sd,format=raw,snapshot=on,file=' + image_path
124
+ archive.gzip_uncompress(image_path_gz, image_path)
125
+
126
+ # dd if=u-boot-sunxi-with-spl.bin of=armv7.img bs=1K seek=8 conv=notrunc
127
+ with open(uboot_path, 'rb') as f_in:
128
+ with open(image_path, 'r+b') as f_out:
129
+ f_out.seek(8 * 1024)
130
+ shutil.copyfileobj(f_in, f_out)
131
+
132
+ # Extend image, to avoid that NetBSD thinks the partition
133
+ # inside the image is larger than device size itself
134
+ f_out.seek(0, 2)
135
+ f_out.seek(64 * 1024 * 1024, 1)
136
+ f_out.write(bytearray([0x00]))
137
+
138
+ self.vm.set_console()
139
+ self.vm.add_args('-nic', 'user',
140
+ '-drive', image_drive_args,
141
+ '-global', 'allwinner-rtc.base-year=2000',
142
+ '-no-reboot')
143
+ self.vm.launch()
144
+ wait_for_console_pattern(self, 'U-Boot 2020.01+dfsg-1')
145
+ interrupt_interactive_console_until_pattern(self,
146
+ 'Hit any key to stop autoboot:',
147
+ 'switch to partitions #0, OK')
148
+
149
+ exec_command_and_wait_for_pattern(self, '', '=>')
150
+ cmd = 'setenv bootargs root=ld0a'
151
+ exec_command_and_wait_for_pattern(self, cmd, '=>')
152
+ cmd = 'setenv kernel netbsd-GENERIC.ub'
153
+ exec_command_and_wait_for_pattern(self, cmd, '=>')
154
+ cmd = 'setenv fdtfile dtb/sun8i-h3-orangepi-pc.dtb'
155
+ exec_command_and_wait_for_pattern(self, cmd, '=>')
156
+ cmd = ("setenv bootcmd 'fatload mmc 0:1 ${kernel_addr_r} ${kernel}; "
157
+ "fatload mmc 0:1 ${fdt_addr_r} ${fdtfile}; "
158
+ "fdt addr ${fdt_addr_r}; "
159
+ "bootm ${kernel_addr_r} - ${fdt_addr_r}'")
160
+ exec_command_and_wait_for_pattern(self, cmd, '=>')
161
+
162
+ exec_command_and_wait_for_pattern(self, 'boot',
163
+ 'Booting kernel from Legacy Image')
164
+ wait_for_console_pattern(self, 'Starting kernel ...')
165
+ wait_for_console_pattern(self, 'NetBSD 9.0 (GENERIC)')
166
+ # Wait for user-space
167
+ wait_for_console_pattern(self, 'Starting root file system check')
168
+
169
def test_s390x_s390_ccw_virtio(self):
170
"""
171
:avocado: tags=arch:s390x
53
--
172
--
54
2.20.1
173
2.20.1
55
174
56
175
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
Replace deprecated qdev_reset_all by resettable_cold_reset_fn for
3
The Xunlong Orange Pi PC machine is a functional ARM machine
4
the ipl registration in the main reset handlers.
4
based on the Allwinner H3 System-on-Chip. It supports mainline
5
5
Linux, U-Boot, NetBSD and is covered by acceptance tests.
6
This does not impact the behavior for the following reasons:
6
7
+ at this point resettable just call the old reset methods of devices
7
This commit adds a documentation text file with a description
8
and buses in the same order than qdev/qbus.
8
of the machine and instructions for the user.
9
+ resettable handlers registered with qemu_register_reset are
9
10
serialized; there is no interleaving.
10
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
11
+ eventual explicit calls to legacy reset API (device_reset or
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
qdev/qbus_reset) inside this reset handler will not be masked out
12
Message-id: 20200311221854.30370-19-nieklinnenbank@gmail.com
13
by resettable mechanism; they do not go through resettable api.
13
[PMM: moved file into docs/system/arm to match the reorg
14
14
of the arm target part of the docs; tweaked heading to
15
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
15
match other boards]
16
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Message-id: 20200123132823.1117486-12-damien.hedde@greensocs.com
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
17
---
23
hw/s390x/ipl.c | 10 +++++++++-
18
MAINTAINERS | 1 +
24
1 file changed, 9 insertions(+), 1 deletion(-)
19
docs/system/arm/orangepi.rst | 253 +++++++++++++++++++++++++++++++++++
25
20
docs/system/target-arm.rst | 2 +
26
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
21
3 files changed, 256 insertions(+)
22
create mode 100644 docs/system/arm/orangepi.rst
23
24
diff --git a/MAINTAINERS b/MAINTAINERS
27
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/s390x/ipl.c
26
--- a/MAINTAINERS
29
+++ b/hw/s390x/ipl.c
27
+++ b/MAINTAINERS
30
@@ -XXX,XX +XXX,XX @@ static void s390_ipl_realize(DeviceState *dev, Error **errp)
28
@@ -XXX,XX +XXX,XX @@ S: Maintained
31
*/
29
F: hw/*/allwinner-h3*
32
ipl->compat_start_addr = ipl->start_addr;
30
F: include/hw/*/allwinner-h3*
33
ipl->compat_bios_start_addr = ipl->bios_start_addr;
31
F: hw/arm/orangepi.c
34
- qemu_register_reset(qdev_reset_all_fn, dev);
32
+F: docs/system/orangepi.rst
35
+ /*
33
36
+ * Because this Device is not on any bus in the qbus tree (it is
34
ARM PrimeCell and CMSDK devices
37
+ * not a sysbus device and it's not on some other bus like a PCI
35
M: Peter Maydell <peter.maydell@linaro.org>
38
+ * bus) it will not be automatically reset by the 'reset the
36
diff --git a/docs/system/arm/orangepi.rst b/docs/system/arm/orangepi.rst
39
+ * sysbus' hook registered by vl.c like most devices. So we must
37
new file mode 100644
40
+ * manually register a reset hook for it.
38
index XXXXXXX..XXXXXXX
41
+ * TODO: there should be a better way to do this.
39
--- /dev/null
42
+ */
40
+++ b/docs/system/arm/orangepi.rst
43
+ qemu_register_reset(resettable_cold_reset_fn, dev);
41
@@ -XXX,XX +XXX,XX @@
44
error:
42
+Orange Pi PC (``orangepi-pc``)
45
error_propagate(errp, err);
43
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
46
}
44
+
45
+The Xunlong Orange Pi PC is an Allwinner H3 System on Chip
46
+based embedded computer with mainline support in both U-Boot
47
+and Linux. The board comes with a Quad Core Cortex-A7 @ 1.3GHz,
48
+1GiB RAM, 100Mbit ethernet, USB, SD/MMC, USB, HDMI and
49
+various other I/O.
50
+
51
+Supported devices
52
+"""""""""""""""""
53
+
54
+The Orange Pi PC machine supports the following devices:
55
+
56
+ * SMP (Quad Core Cortex-A7)
57
+ * Generic Interrupt Controller configuration
58
+ * SRAM mappings
59
+ * SDRAM controller
60
+ * Real Time Clock
61
+ * Timer device (re-used from Allwinner A10)
62
+ * UART
63
+ * SD/MMC storage controller
64
+ * EMAC ethernet
65
+ * USB 2.0 interfaces
66
+ * Clock Control Unit
67
+ * System Control module
68
+ * Security Identifier device
69
+
70
+Limitations
71
+"""""""""""
72
+
73
+Currently, Orange Pi PC does *not* support the following features:
74
+
75
+- Graphical output via HDMI, GPU and/or the Display Engine
76
+- Audio output
77
+- Hardware Watchdog
78
+
79
+Also see the 'unimplemented' array in the Allwinner H3 SoC module
80
+for a complete list of unimplemented I/O devices: ``./hw/arm/allwinner-h3.c``
81
+
82
+Boot options
83
+""""""""""""
84
+
85
+The Orange Pi PC machine can start using the standard -kernel functionality
86
+for loading a Linux kernel or ELF executable. Additionally, the Orange Pi PC
87
+machine can also emulate the BootROM which is present on an actual Allwinner H3
88
+based SoC, which loads the bootloader from a SD card, specified via the -sd argument
89
+to qemu-system-arm.
90
+
91
+Machine-specific options
92
+""""""""""""""""""""""""
93
+
94
+The following machine-specific options are supported:
95
+
96
+- allwinner-rtc.base-year=YYYY
97
+
98
+ The Allwinner RTC device is automatically created by the Orange Pi PC machine
99
+ and uses a default base year value which can be overridden using the 'base-year' property.
100
+ The base year is the actual represented year when the RTC year value is zero.
101
+ This option can be used in case the target operating system driver uses a different
102
+ base year value. The minimum value for the base year is 1900.
103
+
104
+- allwinner-sid.identifier=abcd1122-a000-b000-c000-12345678ffff
105
+
106
+ The Security Identifier value can be read by the guest.
107
+ For example, U-Boot uses it to determine a unique MAC address.
108
+
109
+The above machine-specific options can be specified in qemu-system-arm
110
+via the '-global' argument, for example:
111
+
112
+.. code-block:: bash
113
+
114
+ $ qemu-system-arm -M orangepi-pc -sd mycard.img \
115
+ -global allwinner-rtc.base-year=2000
116
+
117
+Running mainline Linux
118
+""""""""""""""""""""""
119
+
120
+Mainline Linux kernels from 4.19 up to latest master are known to work.
121
+To build a Linux mainline kernel that can be booted by the Orange Pi PC machine,
122
+simply configure the kernel using the sunxi_defconfig configuration:
123
+
124
+.. code-block:: bash
125
+
126
+ $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make mrproper
127
+ $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make sunxi_defconfig
128
+
129
+To be able to use USB storage, you need to manually enable the corresponding
130
+configuration item. Start the kconfig configuration tool:
131
+
132
+.. code-block:: bash
133
+
134
+ $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make menuconfig
135
+
136
+Navigate to the following item, enable it and save your configuration:
137
+
138
+ Device Drivers > USB support > USB Mass Storage support
139
+
140
+Build the Linux kernel with:
141
+
142
+.. code-block:: bash
143
+
144
+ $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make
145
+
146
+To boot the newly build linux kernel in QEMU with the Orange Pi PC machine, use:
147
+
148
+.. code-block:: bash
149
+
150
+ $ qemu-system-arm -M orangepi-pc -nic user -nographic \
151
+ -kernel /path/to/linux/arch/arm/boot/zImage \
152
+ -append 'console=ttyS0,115200' \
153
+ -dtb /path/to/linux/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dtb
154
+
155
+Orange Pi PC images
156
+"""""""""""""""""""
157
+
158
+Note that the mainline kernel does not have a root filesystem. You may provide it
159
+with an official Orange Pi PC image from the official website:
160
+
161
+ http://www.orangepi.org/downloadresources/
162
+
163
+Another possibility is to run an Armbian image for Orange Pi PC which
164
+can be downloaded from:
165
+
166
+ https://www.armbian.com/orange-pi-pc/
167
+
168
+Alternatively, you can also choose to build you own image with buildroot
169
+using the orangepi_pc_defconfig. Also see https://buildroot.org for more information.
170
+
171
+You can choose to attach the selected image either as an SD card or as USB mass storage.
172
+For example, to boot using the Orange Pi PC Debian image on SD card, simply add the -sd
173
+argument and provide the proper root= kernel parameter:
174
+
175
+.. code-block:: bash
176
+
177
+ $ qemu-system-arm -M orangepi-pc -nic user -nographic \
178
+ -kernel /path/to/linux/arch/arm/boot/zImage \
179
+ -append 'console=ttyS0,115200 root=/dev/mmcblk0p2' \
180
+ -dtb /path/to/linux/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dtb \
181
+ -sd OrangePi_pc_debian_stretch_server_linux5.3.5_v1.0.img
182
+
183
+To attach the image as an USB mass storage device to the machine,
184
+simply append to the command:
185
+
186
+.. code-block:: bash
187
+
188
+ -drive if=none,id=stick,file=myimage.img \
189
+ -device usb-storage,bus=usb-bus.0,drive=stick
190
+
191
+Instead of providing a custom Linux kernel via the -kernel command you may also
192
+choose to let the Orange Pi PC machine load the bootloader from SD card, just like
193
+a real board would do using the BootROM. Simply pass the selected image via the -sd
194
+argument and remove the -kernel, -append, -dbt and -initrd arguments:
195
+
196
+.. code-block:: bash
197
+
198
+ $ qemu-system-arm -M orangepi-pc -nic user -nographic \
199
+ -sd Armbian_19.11.3_Orangepipc_buster_current_5.3.9.img
200
+
201
+Note that both the official Orange Pi PC images and Armbian images start
202
+a lot of userland programs via systemd. Depending on the host hardware and OS,
203
+they may be slow to emulate, especially due to emulating the 4 cores.
204
+To help reduce the performance slow down due to emulating the 4 cores, you can
205
+give the following kernel parameters via U-Boot (or via -append):
206
+
207
+.. code-block:: bash
208
+
209
+ => setenv extraargs 'systemd.default_timeout_start_sec=9000 loglevel=7 nosmp console=ttyS0,115200'
210
+
211
+Running U-Boot
212
+""""""""""""""
213
+
214
+U-Boot mainline can be build and configured using the orangepi_pc_defconfig
215
+using similar commands as describe above for Linux. Note that it is recommended
216
+for development/testing to select the following configuration setting in U-Boot:
217
+
218
+ Device Tree Control > Provider for DTB for DT Control > Embedded DTB
219
+
220
+To start U-Boot using the Orange Pi PC machine, provide the
221
+u-boot binary to the -kernel argument:
222
+
223
+.. code-block:: bash
224
+
225
+ $ qemu-system-arm -M orangepi-pc -nic user -nographic \
226
+ -kernel /path/to/uboot/u-boot -sd disk.img
227
+
228
+Use the following U-boot commands to load and boot a Linux kernel from SD card:
229
+
230
+.. code-block:: bash
231
+
232
+ => setenv bootargs console=ttyS0,115200
233
+ => ext2load mmc 0 0x42000000 zImage
234
+ => ext2load mmc 0 0x43000000 sun8i-h3-orangepi-pc.dtb
235
+ => bootz 0x42000000 - 0x43000000
236
+
237
+Running NetBSD
238
+""""""""""""""
239
+
240
+The NetBSD operating system also includes support for Allwinner H3 based boards,
241
+including the Orange Pi PC. NetBSD 9.0 is known to work best for the Orange Pi PC
242
+board and provides a fully working system with serial console, networking and storage.
243
+For the Orange Pi PC machine, get the 'evbarm-earmv7hf' based image from:
244
+
245
+ https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.0/evbarm-earmv7hf/binary/gzimg/armv7.img.gz
246
+
247
+The image requires manually installing U-Boot in the image. Build U-Boot with
248
+the orangepi_pc_defconfig configuration as described in the previous section.
249
+Next, unzip the NetBSD image and write the U-Boot binary including SPL using:
250
+
251
+.. code-block:: bash
252
+
253
+ $ gunzip armv7.img.gz
254
+ $ dd if=/path/to/u-boot-sunxi-with-spl.bin of=armv7.img bs=1024 seek=8 conv=notrunc
255
+
256
+Finally, before starting the machine the SD image must be extended such
257
+that the NetBSD kernel will not conclude the NetBSD partition is larger than
258
+the emulated SD card:
259
+
260
+.. code-block:: bash
261
+
262
+ $ dd if=/dev/zero bs=1M count=64 >> armv7.img
263
+
264
+Start the machine using the following command:
265
+
266
+.. code-block:: bash
267
+
268
+ $ qemu-system-arm -M orangepi-pc -nic user -nographic \
269
+ -sd armv7.img -global allwinner-rtc.base-year=2000
270
+
271
+At the U-Boot stage, interrupt the automatic boot process by pressing a key
272
+and set the following environment variables before booting:
273
+
274
+.. code-block:: bash
275
+
276
+ => setenv bootargs root=ld0a
277
+ => setenv kernel netbsd-GENERIC.ub
278
+ => setenv fdtfile dtb/sun8i-h3-orangepi-pc.dtb
279
+ => setenv bootcmd 'fatload mmc 0:1 ${kernel_addr_r} ${kernel}; fatload mmc 0:1 ${fdt_addr_r} ${fdtfile}; fdt addr ${fdt_addr_r}; bootm ${kernel_addr_r} - ${fdt_addr_r}'
280
+
281
+Optionally you may save the environment variables to SD card with 'saveenv'.
282
+To continue booting simply give the 'boot' command and NetBSD boots.
283
+
284
+Orange Pi PC acceptance tests
285
+"""""""""""""""""""""""""""""
286
+
287
+The Orange Pi PC machine has several acceptance tests included.
288
+To run the whole set of tests, build QEMU from source and simply
289
+provide the following command:
290
+
291
+.. code-block:: bash
292
+
293
+ $ AVOCADO_ALLOW_LARGE_STORAGE=yes avocado --show=app,console run \
294
+ -t machine:orangepi-pc tests/acceptance/boot_linux_console.py
295
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
296
index XXXXXXX..XXXXXXX 100644
297
--- a/docs/system/target-arm.rst
298
+++ b/docs/system/target-arm.rst
299
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
300
``qemu-system-aarch64 --machine help``.
301
302
.. toctree::
303
+ :maxdepth: 1
304
305
arm/integratorcp
306
arm/versatile
307
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
308
arm/stellaris
309
arm/musicpal
310
arm/sx1
311
+ arm/orangepi
312
313
Arm CPU features
314
================
47
--
315
--
48
2.20.1
316
2.20.1
49
317
50
318
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
Add the missing GENERIC_TIMER feature to kvm64 cpus.
3
Mention 'max' value in the gic-version property description.
4
4
5
We don't currently use these registers when KVM is enabled, but it's
5
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
probably best we add the feature flag for consistency and potential
7
future use. There's also precedent, as we add the PMU feature flag to
8
KVM enabled guests, even though we don't use those registers either.
9
10
This change was originally posted as a hunk of a different, never
11
merged patch from Bijan Mottahedeh.
12
13
Signed-off-by: Andrew Jones <drjones@redhat.com>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20200120101023.16030-4-drjones@redhat.com
7
Reviewed-by: Andrew Jones <drjones@redhat.com>
8
Message-id: 20200311131618.7187-2-eric.auger@redhat.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
10
---
18
target/arm/kvm64.c | 1 +
11
hw/arm/virt.c | 3 ++-
19
1 file changed, 1 insertion(+)
12
1 file changed, 2 insertions(+), 1 deletion(-)
20
13
21
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
14
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
22
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/kvm64.c
16
--- a/hw/arm/virt.c
24
+++ b/target/arm/kvm64.c
17
+++ b/hw/arm/virt.c
25
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
18
@@ -XXX,XX +XXX,XX @@ static void virt_instance_init(Object *obj)
26
set_feature(&features, ARM_FEATURE_NEON);
19
virt_set_gic_version, NULL);
27
set_feature(&features, ARM_FEATURE_AARCH64);
20
object_property_set_description(obj, "gic-version",
28
set_feature(&features, ARM_FEATURE_PMU);
21
"Set GIC version. "
29
+ set_feature(&features, ARM_FEATURE_GENERIC_TIMER);
22
- "Valid values are 2, 3 and host", NULL);
30
23
+ "Valid values are 2, 3, host and max",
31
ahcf->features = features;
24
+ NULL);
25
26
vms->highmem_ecam = !vmc->no_highmem_ecam;
32
27
33
--
28
--
34
2.20.1
29
2.20.1
35
30
36
31
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
Replace deprecated qbus_reset_all by resettable_cold_reset_fn for
3
We plan to introduce yet another value for the gic version (nosel).
4
the sysbus reset registration.
4
As we already use exotic values such as 0 and -1, let's introduce
5
a dedicated enum type and let vms->gic_version take this
6
type.
5
7
6
Apart for the raspi machines, this does not impact the behavior
8
Signed-off-by: Eric Auger <eric.auger@redhat.com>
7
because:
8
+ at this point resettable just calls the old reset methods of devices
9
and buses in the same order as qdev/qbus.
10
+ resettable handlers registered with qemu_register_reset are
11
serialized; there is no interleaving.
12
+ eventual explicit calls to legacy reset API (device_reset or
13
qdev/qbus_reset) inside this reset handler will not be masked out
14
by resettable mechanism; they do not go through resettable api.
15
16
For the raspi machines, during the sysbus reset the sd-card is not
17
reset twice anymore but only once. This is a consequence of switching
18
both sysbus reset and changing parent to resettable; it detects the
19
second reset is not needed. This has no impact on the state after
20
reset; the sd-card reset method only reset local state and query
21
information from the block backend.
22
23
The raspi reset change can be observed by using the following command
24
(reset will occurs, then do Ctrl-C to end qemu; no firmware is
25
given here).
26
qemu-system-aarch64 -M raspi3 \
27
-trace resettable_phase_hold_exec \
28
-trace qdev_update_parent_bus \
29
-trace resettable_change_parent \
30
-trace qdev_reset -trace qbus_reset
31
32
Before the patch, the qdev/qbus_reset traces show when reset method are
33
called. After the patch, the resettable_phase_hold_exec show when reset
34
method are called.
35
36
The traced reset order of the raspi3 is listed below. I've added empty
37
lines and the tree structure.
38
39
+->bcm2835-peripherals reset
40
|
41
| +->sd-card reset
42
| +->sd-bus reset
43
+->bcm2835_gpio reset
44
| -> dev_update_parent_bus (move the sd-card on the sdhci-bus)
45
| -> resettable_change_parent
46
|
47
+->bcm2835-dma reset
48
|
49
| +->bcm2835-sdhost-bus reset
50
+->bcm2835-sdhost reset
51
|
52
| +->sd-card (reset ONLY BEFORE BEFORE THE PATCH)
53
| +->sdhci-bus reset
54
+->generic-sdhci reset
55
|
56
+->bcm2835-rng reset
57
+->bcm2835-property reset
58
+->bcm2835-fb reset
59
+->bcm2835-mbox reset
60
+->bcm2835-aux reset
61
+->pl011 reset
62
+->bcm2835-ic reset
63
+->bcm2836-control reset
64
System reset
65
66
In both case, the sd-card is reset (being on bcm2835_gpio/sd-bus) then moved
67
to generic-sdhci/sdhci-bus by the bcm2835_gpio reset method.
68
69
Before the patch, it is then reset again being part of generic-sdhci/sdhci-bus.
70
After the patch, it considered again for reset but its reset method is not
71
called because it is already flagged as reset.
72
73
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
74
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
75
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
76
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
77
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Reviewed-by: Andrew Jones <drjones@redhat.com>
78
Message-id: 20200123132823.1117486-11-damien.hedde@greensocs.com
12
Message-id: 20200311131618.7187-3-eric.auger@redhat.com
79
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
80
---
14
---
81
vl.c | 10 +++++++++-
15
include/hw/arm/virt.h | 11 +++++++++--
82
1 file changed, 9 insertions(+), 1 deletion(-)
16
hw/arm/virt.c | 30 +++++++++++++++---------------
17
2 files changed, 24 insertions(+), 17 deletions(-)
83
18
84
diff --git a/vl.c b/vl.c
19
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
85
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
86
--- a/vl.c
21
--- a/include/hw/arm/virt.h
87
+++ b/vl.c
22
+++ b/include/hw/arm/virt.h
88
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp)
23
@@ -XXX,XX +XXX,XX @@ typedef enum VirtIOMMUType {
89
24
VIRT_IOMMU_VIRTIO,
90
/* TODO: once all bus devices are qdevified, this should be done
25
} VirtIOMMUType;
91
* when bus is created by qdev.c */
26
92
- qemu_register_reset(qbus_reset_all_fn, sysbus_get_default());
27
+typedef enum VirtGICType {
93
+ /*
28
+ VIRT_GIC_VERSION_MAX,
94
+ * TODO: If we had a main 'reset container' that the whole system
29
+ VIRT_GIC_VERSION_HOST,
95
+ * lived in, we could reset that using the multi-phase reset
30
+ VIRT_GIC_VERSION_2,
96
+ * APIs. For the moment, we just reset the sysbus, which will cause
31
+ VIRT_GIC_VERSION_3,
97
+ * all devices hanging off it (and all their child buses, recursively)
32
+} VirtGICType;
98
+ * to be reset. Note that this will *not* reset any Device objects
33
+
99
+ * which are not attached to some part of the qbus tree!
34
typedef struct MemMapEntry {
100
+ */
35
hwaddr base;
101
+ qemu_register_reset(resettable_cold_reset_fn, sysbus_get_default());
36
hwaddr size;
102
qemu_run_machine_init_done_notifiers();
37
@@ -XXX,XX +XXX,XX @@ typedef struct {
103
38
bool highmem_ecam;
104
if (rom_check_and_register_reset() != 0) {
39
bool its;
40
bool virt;
41
- int32_t gic_version;
42
+ VirtGICType gic_version;
43
VirtIOMMUType iommu;
44
uint16_t virtio_iommu_bdf;
45
struct arm_boot_info bootinfo;
46
@@ -XXX,XX +XXX,XX @@ static inline int virt_gicv3_redist_region_count(VirtMachineState *vms)
47
uint32_t redist0_capacity =
48
vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
49
50
- assert(vms->gic_version == 3);
51
+ assert(vms->gic_version == VIRT_GIC_VERSION_3);
52
53
return vms->smp_cpus > redist0_capacity ? 2 : 1;
54
}
55
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/hw/arm/virt.c
58
+++ b/hw/arm/virt.c
59
@@ -XXX,XX +XXX,XX @@ static void fdt_add_timer_nodes(const VirtMachineState *vms)
60
irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI;
61
}
62
63
- if (vms->gic_version == 2) {
64
+ if (vms->gic_version == VIRT_GIC_VERSION_2) {
65
irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
66
GIC_FDT_IRQ_PPI_CPU_WIDTH,
67
(1 << vms->smp_cpus) - 1);
68
@@ -XXX,XX +XXX,XX @@ static void fdt_add_gic_node(VirtMachineState *vms)
69
qemu_fdt_setprop_cell(vms->fdt, nodename, "#address-cells", 0x2);
70
qemu_fdt_setprop_cell(vms->fdt, nodename, "#size-cells", 0x2);
71
qemu_fdt_setprop(vms->fdt, nodename, "ranges", NULL, 0);
72
- if (vms->gic_version == 3) {
73
+ if (vms->gic_version == VIRT_GIC_VERSION_3) {
74
int nb_redist_regions = virt_gicv3_redist_region_count(vms);
75
76
qemu_fdt_setprop_string(vms->fdt, nodename, "compatible",
77
@@ -XXX,XX +XXX,XX @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms)
78
}
79
}
80
81
- if (vms->gic_version == 2) {
82
+ if (vms->gic_version == VIRT_GIC_VERSION_2) {
83
irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
84
GIC_FDT_IRQ_PPI_CPU_WIDTH,
85
(1 << vms->smp_cpus) - 1);
86
@@ -XXX,XX +XXX,XX @@ static uint64_t virt_cpu_mp_affinity(VirtMachineState *vms, int idx)
87
* purposes are to make TCG consistent (with 64-bit KVM hosts)
88
* and to improve SGI efficiency.
89
*/
90
- if (vms->gic_version == 3) {
91
+ if (vms->gic_version == VIRT_GIC_VERSION_3) {
92
clustersz = GICV3_TARGETLIST_BITS;
93
} else {
94
clustersz = GIC_TARGETLIST_BITS;
95
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
96
/* We can probe only here because during property set
97
* KVM is not available yet
98
*/
99
- if (vms->gic_version <= 0) {
100
- /* "host" or "max" */
101
+ if (vms->gic_version == VIRT_GIC_VERSION_HOST ||
102
+ vms->gic_version == VIRT_GIC_VERSION_MAX) {
103
if (!kvm_enabled()) {
104
- if (vms->gic_version == 0) {
105
+ if (vms->gic_version == VIRT_GIC_VERSION_HOST) {
106
error_report("gic-version=host requires KVM");
107
exit(1);
108
} else {
109
/* "max": currently means 3 for TCG */
110
- vms->gic_version = 3;
111
+ vms->gic_version = VIRT_GIC_VERSION_3;
112
}
113
} else {
114
vms->gic_version = kvm_arm_vgic_probe();
115
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
116
/* The maximum number of CPUs depends on the GIC version, or on how
117
* many redistributors we can fit into the memory map.
118
*/
119
- if (vms->gic_version == 3) {
120
+ if (vms->gic_version == VIRT_GIC_VERSION_3) {
121
virt_max_cpus =
122
vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
123
virt_max_cpus +=
124
@@ -XXX,XX +XXX,XX @@ static void virt_set_its(Object *obj, bool value, Error **errp)
125
static char *virt_get_gic_version(Object *obj, Error **errp)
126
{
127
VirtMachineState *vms = VIRT_MACHINE(obj);
128
- const char *val = vms->gic_version == 3 ? "3" : "2";
129
+ const char *val = vms->gic_version == VIRT_GIC_VERSION_3 ? "3" : "2";
130
131
return g_strdup(val);
132
}
133
@@ -XXX,XX +XXX,XX @@ static void virt_set_gic_version(Object *obj, const char *value, Error **errp)
134
VirtMachineState *vms = VIRT_MACHINE(obj);
135
136
if (!strcmp(value, "3")) {
137
- vms->gic_version = 3;
138
+ vms->gic_version = VIRT_GIC_VERSION_3;
139
} else if (!strcmp(value, "2")) {
140
- vms->gic_version = 2;
141
+ vms->gic_version = VIRT_GIC_VERSION_2;
142
} else if (!strcmp(value, "host")) {
143
- vms->gic_version = 0; /* Will probe later */
144
+ vms->gic_version = VIRT_GIC_VERSION_HOST; /* Will probe later */
145
} else if (!strcmp(value, "max")) {
146
- vms->gic_version = -1; /* Will probe later */
147
+ vms->gic_version = VIRT_GIC_VERSION_MAX; /* Will probe later */
148
} else {
149
error_setg(errp, "Invalid gic-version value");
150
error_append_hint(errp, "Valid values are 3, 2, host, max.\n");
151
@@ -XXX,XX +XXX,XX @@ static void virt_instance_init(Object *obj)
152
"physical address space above 32 bits",
153
NULL);
154
/* Default GIC type is v2 */
155
- vms->gic_version = 2;
156
+ vms->gic_version = VIRT_GIC_VERSION_2;
157
object_property_add_str(obj, "gic-version", virt_get_gic_version,
158
virt_set_gic_version, NULL);
159
object_property_set_description(obj, "gic-version",
105
--
160
--
106
2.20.1
161
2.20.1
107
162
108
163
diff view generated by jsdifflib
1
From: Damien Hedde <damien.hedde@greensocs.com>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
In qdev_set_parent_bus(), when changing the parent bus of a
3
Let's move the code which freezes which gic-version to
4
realized device, if the source and destination buses are not in the
4
be applied in a dedicated function. We also now set by
5
same reset state, some adaptations are required. This patch adds
5
default the VIRT_GIC_VERSION_NO_SET. This eventually
6
needed call to resettable_change_parent() to make sure a device reset
6
turns into the legacy v2 choice in the finalize() function.
7
state stays coherent with its parent bus.
8
7
9
The addition is a no-op if:
8
Signed-off-by: Eric Auger <eric.auger@redhat.com>
10
1. the device being parented is not realized.
11
2. the device is realized, but both buses are not under reset.
12
13
Case 2 means that as long as qdev_set_parent_bus() is called
14
during the machine realization procedure (which is before the
15
machine reset so nothing is in reset), it is a no op.
16
17
There are 52 call sites of qdev_set_parent_bus(). All but one fall
18
into the no-op case:
19
+ 29 trivial calls related to virtio (in hw/{s390x,display,virtio}/
20
{vhost,virtio}-xxx.c) to set a vdev(or vgpu) composing device
21
parent bus just before realizing the same vdev(vgpu).
22
+ hw/core/qdev.c: when creating a device in qdev_try_create()
23
+ hw/core/sysbus.c: when initializing a device in the sysbus
24
+ hw/i386/amd_iommu.c: before realizing AMDVIState/pci
25
+ hw/isa/piix4.c: before realizing PIIX4State/rtc
26
+ hw/misc/auxbus.c: when creating an AUXBus
27
+ hw/misc/auxbus.c: when creating an AUXBus child
28
+ hw/misc/macio/macio.c: when initializing a MACIOState child
29
+ hw/misc/macio/macio.c: before realizing NewWorldMacIOState/pmu
30
+ hw/misc/macio/macio.c: before realizing NewWorldMacIOState/cuda
31
+ hw/net/virtio-net.c: Used for migration when using the failover
32
mechanism to migration a vfio-pci/net. It is
33
a no-op because at this point the device is
34
already on the bus.
35
+ hw/pci-host/designware.c: before realizing DesignwarePCIEHost/root
36
+ hw/pci-host/gpex.c: before realizing GPEXHost/root
37
+ hw/pci-host/prep.c: when initialiazing PREPPCIState/pci_dev
38
+ hw/pci-host/q35.c: before realizing Q35PCIHost/mch
39
+ hw/pci-host/versatile.c: when initializing PCIVPBState/pci_dev
40
+ hw/pci-host/xilinx-pcie.c: before realizing XilinxPCIEHost/root
41
+ hw/s390x/event-facility.c: when creating SCLPEventFacility/
42
TYPE_SCLP_QUIESCE
43
+ hw/s390x/event-facility.c: ditto with SCLPEventFacility/
44
TYPE_SCLP_CPU_HOTPLUG
45
+ hw/s390x/sclp.c: Not trivial because it is called on a SLCPDevice
46
just after realizing it. Ok because at this point the destination
47
bus (sysbus) is not in reset; the realize step is before the
48
machine reset.
49
+ hw/sd/core.c: Not OK. Used in sdbus_reparent_card(). See below.
50
+ hw/ssi/ssi.c: Used to put spi slave on spi bus and connect the cs
51
line in ssi_auto_connect_slave(). Ok because this function is only
52
used in realize step in hw/ssi/aspeed_smc.ci, hw/ssi/imx_spi.c,
53
hw/ssi/mss-spi.c, hw/ssi/xilinx_spi.c and hw/ssi/xilinx_spips.c.
54
+ hw/xen/xen-legacy-backend.c: when creating a XenLegacyDevice device
55
+ qdev-monitor.c: in device hotplug creation procedure before realize
56
57
Note that this commit alone will have no effect, right now there is no
58
use of resettable API to reset anything. So a bus will never be tagged
59
as in-reset by this same API.
60
61
The one place where side-effect will occurs is in hw/sd/core.c in
62
sdbus_reparent_card(). This function is only used in the raspi machines,
63
including during the sysbus reset procedure. This case will be
64
carrefully handled when doing the multiple phase reset transition.
65
66
Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
67
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
68
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
69
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Andrew Jones <drjones@redhat.com>
70
Message-id: 20200123132823.1117486-7-damien.hedde@greensocs.com
11
Message-id: 20200311131618.7187-4-eric.auger@redhat.com
71
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
72
---
13
---
73
hw/core/qdev.c | 16 +++++++++++-----
14
include/hw/arm/virt.h | 1 +
74
1 file changed, 11 insertions(+), 5 deletions(-)
15
hw/arm/virt.c | 54 ++++++++++++++++++++++++++-----------------
16
2 files changed, 34 insertions(+), 21 deletions(-)
75
17
76
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
18
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
77
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
78
--- a/hw/core/qdev.c
20
--- a/include/hw/arm/virt.h
79
+++ b/hw/core/qdev.c
21
+++ b/include/hw/arm/virt.h
80
@@ -XXX,XX +XXX,XX @@ static void bus_add_child(BusState *bus, DeviceState *child)
22
@@ -XXX,XX +XXX,XX @@ typedef enum VirtGICType {
81
23
VIRT_GIC_VERSION_HOST,
82
void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
24
VIRT_GIC_VERSION_2,
83
{
25
VIRT_GIC_VERSION_3,
84
- bool replugging = dev->parent_bus != NULL;
26
+ VIRT_GIC_VERSION_NOSEL,
85
+ BusState *old_parent_bus = dev->parent_bus;
27
} VirtGICType;
86
28
87
- if (replugging) {
29
typedef struct MemMapEntry {
88
+ if (old_parent_bus) {
30
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
89
trace_qdev_update_parent_bus(dev, object_get_typename(OBJECT(dev)),
31
index XXXXXXX..XXXXXXX 100644
90
- dev->parent_bus, object_get_typename(OBJECT(dev->parent_bus)),
32
--- a/hw/arm/virt.c
91
+ old_parent_bus, object_get_typename(OBJECT(old_parent_bus)),
33
+++ b/hw/arm/virt.c
92
OBJECT(bus), object_get_typename(OBJECT(bus)));
34
@@ -XXX,XX +XXX,XX @@ static void virt_set_memmap(VirtMachineState *vms)
93
/*
94
* Keep a reference to the device while it's not plugged into
95
* any bus, to avoid it potentially evaporating when it is
96
* dereffed in bus_remove_child().
97
+ * Also keep the ref of the parent bus until the end, so that
98
+ * we can safely call resettable_change_parent() below.
99
*/
100
object_ref(OBJECT(dev));
101
bus_remove_child(dev->parent_bus, dev);
102
- object_unref(OBJECT(dev->parent_bus));
103
}
104
dev->parent_bus = bus;
105
object_ref(OBJECT(bus));
106
bus_add_child(bus, dev);
107
- if (replugging) {
108
+ if (dev->realized) {
109
+ resettable_change_parent(OBJECT(dev), OBJECT(bus),
110
+ OBJECT(old_parent_bus));
111
+ }
112
+ if (old_parent_bus) {
113
+ object_unref(OBJECT(old_parent_bus));
114
object_unref(OBJECT(dev));
115
}
35
}
116
}
36
}
37
38
+/*
39
+ * finalize_gic_version - Determines the final gic_version
40
+ * according to the gic-version property
41
+ *
42
+ * Default GIC type is v2
43
+ */
44
+static void finalize_gic_version(VirtMachineState *vms)
45
+{
46
+ if (vms->gic_version == VIRT_GIC_VERSION_HOST ||
47
+ vms->gic_version == VIRT_GIC_VERSION_MAX) {
48
+ if (!kvm_enabled()) {
49
+ if (vms->gic_version == VIRT_GIC_VERSION_HOST) {
50
+ error_report("gic-version=host requires KVM");
51
+ exit(1);
52
+ } else {
53
+ /* "max": currently means 3 for TCG */
54
+ vms->gic_version = VIRT_GIC_VERSION_3;
55
+ }
56
+ } else {
57
+ vms->gic_version = kvm_arm_vgic_probe();
58
+ if (!vms->gic_version) {
59
+ error_report(
60
+ "Unable to determine GIC version supported by host");
61
+ exit(1);
62
+ }
63
+ }
64
+ } else if (vms->gic_version == VIRT_GIC_VERSION_NOSEL) {
65
+ vms->gic_version = VIRT_GIC_VERSION_2;
66
+ }
67
+}
68
+
69
static void machvirt_init(MachineState *machine)
70
{
71
VirtMachineState *vms = VIRT_MACHINE(machine);
72
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
73
/* We can probe only here because during property set
74
* KVM is not available yet
75
*/
76
- if (vms->gic_version == VIRT_GIC_VERSION_HOST ||
77
- vms->gic_version == VIRT_GIC_VERSION_MAX) {
78
- if (!kvm_enabled()) {
79
- if (vms->gic_version == VIRT_GIC_VERSION_HOST) {
80
- error_report("gic-version=host requires KVM");
81
- exit(1);
82
- } else {
83
- /* "max": currently means 3 for TCG */
84
- vms->gic_version = VIRT_GIC_VERSION_3;
85
- }
86
- } else {
87
- vms->gic_version = kvm_arm_vgic_probe();
88
- if (!vms->gic_version) {
89
- error_report(
90
- "Unable to determine GIC version supported by host");
91
- exit(1);
92
- }
93
- }
94
- }
95
+ finalize_gic_version(vms);
96
97
if (!cpu_type_valid(machine->cpu_type)) {
98
error_report("mach-virt: CPU type %s not supported", machine->cpu_type);
99
@@ -XXX,XX +XXX,XX @@ static void virt_instance_init(Object *obj)
100
"Set on/off to enable/disable using "
101
"physical address space above 32 bits",
102
NULL);
103
- /* Default GIC type is v2 */
104
- vms->gic_version = VIRT_GIC_VERSION_2;
105
+ vms->gic_version = VIRT_GIC_VERSION_NOSEL;
106
object_property_add_str(obj, "gic-version", virt_get_gic_version,
107
virt_set_gic_version, NULL);
108
object_property_set_description(obj, "gic-version",
117
--
109
--
118
2.20.1
110
2.20.1
119
111
120
112
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
kvm-no-adjvtime is a KVM specific CPU property and a first of its
3
Convert kvm_arm_vgic_probe() so that it returns a
4
kind. To accommodate it we also add kvm_arm_add_vcpu_properties()
4
bitmap of supported in-kernel emulation VGIC versions instead
5
and a KVM specific CPU properties description to the CPU features
5
of the max version: at the moment values can be v2 and v3.
6
document.
6
This allows to expose the case where the host GICv3 also
7
supports GICv2 emulation. This will be useful to choose the
8
default version in KVM accelerated mode.
7
9
8
Signed-off-by: Andrew Jones <drjones@redhat.com>
10
Signed-off-by: Eric Auger <eric.auger@redhat.com>
9
Message-id: 20200120101023.16030-7-drjones@redhat.com
11
Reviewed-by: Andrew Jones <drjones@redhat.com>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20200311131618.7187-5-eric.auger@redhat.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
15
---
13
include/hw/arm/virt.h | 1 +
16
target/arm/kvm_arm.h | 3 +++
14
target/arm/kvm_arm.h | 11 ++++++++++
17
hw/arm/virt.c | 11 +++++++++--
15
hw/arm/virt.c | 8 ++++++++
18
target/arm/kvm.c | 14 ++++++++------
16
target/arm/cpu.c | 2 ++
19
3 files changed, 20 insertions(+), 8 deletions(-)
17
target/arm/cpu64.c | 1 +
18
target/arm/kvm.c | 28 +++++++++++++++++++++++++
19
target/arm/monitor.c | 1 +
20
tests/qtest/arm-cpu-features.c | 4 ++++
21
docs/arm-cpu-features.rst | 37 +++++++++++++++++++++++++++++++++-
22
9 files changed, 92 insertions(+), 1 deletion(-)
23
20
24
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/include/hw/arm/virt.h
27
+++ b/include/hw/arm/virt.h
28
@@ -XXX,XX +XXX,XX @@ typedef struct {
29
bool smbios_old_sys_ver;
30
bool no_highmem_ecam;
31
bool no_ged; /* Machines < 4.2 has no support for ACPI GED device */
32
+ bool kvm_no_adjvtime;
33
} VirtMachineClass;
34
35
typedef struct {
36
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
21
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
37
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/kvm_arm.h
23
--- a/target/arm/kvm_arm.h
39
+++ b/target/arm/kvm_arm.h
24
+++ b/target/arm/kvm_arm.h
40
@@ -XXX,XX +XXX,XX @@ void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map);
25
@@ -XXX,XX +XXX,XX @@
41
*/
26
#include "exec/memory.h"
42
void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
27
#include "qemu/error-report.h"
43
28
44
+/**
29
+#define KVM_ARM_VGIC_V2 (1 << 0)
45
+ * kvm_arm_add_vcpu_properties:
30
+#define KVM_ARM_VGIC_V3 (1 << 1)
46
+ * @obj: The CPU object to add the properties to
47
+ *
48
+ * Add all KVM specific CPU properties to the CPU object. These
49
+ * are the CPU properties with "kvm-" prefixed names.
50
+ */
51
+void kvm_arm_add_vcpu_properties(Object *obj);
52
+
31
+
53
/**
32
/**
54
* kvm_arm_aarch32_supported:
33
* kvm_arm_vcpu_init:
55
* @cs: CPUState
34
* @cs: CPUState
56
@@ -XXX,XX +XXX,XX @@ static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
57
cpu->host_cpu_probe_failed = true;
58
}
59
60
+static inline void kvm_arm_add_vcpu_properties(Object *obj) {}
61
+
62
static inline bool kvm_arm_aarch32_supported(CPUState *cs)
63
{
64
return false;
65
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
35
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
66
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
67
--- a/hw/arm/virt.c
37
--- a/hw/arm/virt.c
68
+++ b/hw/arm/virt.c
38
+++ b/hw/arm/virt.c
69
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
39
@@ -XXX,XX +XXX,XX @@ static void finalize_gic_version(VirtMachineState *vms)
40
vms->gic_version = VIRT_GIC_VERSION_3;
41
}
42
} else {
43
- vms->gic_version = kvm_arm_vgic_probe();
44
- if (!vms->gic_version) {
45
+ int probe_bitmap = kvm_arm_vgic_probe();
46
+
47
+ if (!probe_bitmap) {
48
error_report(
49
"Unable to determine GIC version supported by host");
50
exit(1);
51
+ } else {
52
+ if (probe_bitmap & KVM_ARM_VGIC_V3) {
53
+ vms->gic_version = VIRT_GIC_VERSION_3;
54
+ } else {
55
+ vms->gic_version = VIRT_GIC_VERSION_2;
56
+ }
70
}
57
}
71
}
58
}
72
59
} else if (vms->gic_version == VIRT_GIC_VERSION_NOSEL) {
73
+ if (vmc->kvm_no_adjvtime &&
74
+ object_property_find(cpuobj, "kvm-no-adjvtime", NULL)) {
75
+ object_property_set_bool(cpuobj, true, "kvm-no-adjvtime", NULL);
76
+ }
77
+
78
if (vmc->no_pmu && object_property_find(cpuobj, "pmu", NULL)) {
79
object_property_set_bool(cpuobj, false, "pmu", NULL);
80
}
81
@@ -XXX,XX +XXX,XX @@ DEFINE_VIRT_MACHINE_AS_LATEST(5, 0)
82
83
static void virt_machine_4_2_options(MachineClass *mc)
84
{
85
+ VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
86
+
87
virt_machine_5_0_options(mc);
88
compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len);
89
+ vmc->kvm_no_adjvtime = true;
90
}
91
DEFINE_VIRT_MACHINE(4, 2)
92
93
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/target/arm/cpu.c
96
+++ b/target/arm/cpu.c
97
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
98
99
if (kvm_enabled()) {
100
kvm_arm_set_cpu_features_from_host(cpu);
101
+ kvm_arm_add_vcpu_properties(obj);
102
} else {
103
cortex_a15_initfn(obj);
104
105
@@ -XXX,XX +XXX,XX @@ static void arm_host_initfn(Object *obj)
106
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
107
aarch64_add_sve_properties(obj);
108
}
109
+ kvm_arm_add_vcpu_properties(obj);
110
arm_cpu_post_init(obj);
111
}
112
113
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
114
index XXXXXXX..XXXXXXX 100644
115
--- a/target/arm/cpu64.c
116
+++ b/target/arm/cpu64.c
117
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
118
119
if (kvm_enabled()) {
120
kvm_arm_set_cpu_features_from_host(cpu);
121
+ kvm_arm_add_vcpu_properties(obj);
122
} else {
123
uint64_t t;
124
uint32_t u;
125
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
60
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
126
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
127
--- a/target/arm/kvm.c
62
--- a/target/arm/kvm.c
128
+++ b/target/arm/kvm.c
63
+++ b/target/arm/kvm.c
129
@@ -XXX,XX +XXX,XX @@
64
@@ -XXX,XX +XXX,XX @@ int kvm_arch_irqchip_create(KVMState *s)
130
#include "qemu/timer.h"
65
131
#include "qemu/error-report.h"
66
int kvm_arm_vgic_probe(void)
132
#include "qemu/main-loop.h"
67
{
133
+#include "qom/object.h"
68
+ int val = 0;
134
+#include "qapi/error.h"
69
+
135
#include "sysemu/sysemu.h"
70
if (kvm_create_device(kvm_state,
136
#include "sysemu/kvm.h"
71
KVM_DEV_TYPE_ARM_VGIC_V3, true) == 0) {
137
#include "sysemu/kvm_int.h"
72
- return 3;
138
@@ -XXX,XX +XXX,XX @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
73
- } else if (kvm_create_device(kvm_state,
139
env->features = arm_host_cpu_features.features;
74
- KVM_DEV_TYPE_ARM_VGIC_V2, true) == 0) {
75
- return 2;
76
- } else {
77
- return 0;
78
+ val |= KVM_ARM_VGIC_V3;
79
}
80
+ if (kvm_create_device(kvm_state,
81
+ KVM_DEV_TYPE_ARM_VGIC_V2, true) == 0) {
82
+ val |= KVM_ARM_VGIC_V2;
83
+ }
84
+ return val;
140
}
85
}
141
86
142
+static bool kvm_no_adjvtime_get(Object *obj, Error **errp)
87
int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level)
143
+{
144
+ return !ARM_CPU(obj)->kvm_adjvtime;
145
+}
146
+
147
+static void kvm_no_adjvtime_set(Object *obj, bool value, Error **errp)
148
+{
149
+ ARM_CPU(obj)->kvm_adjvtime = !value;
150
+}
151
+
152
+/* KVM VCPU properties should be prefixed with "kvm-". */
153
+void kvm_arm_add_vcpu_properties(Object *obj)
154
+{
155
+ if (!kvm_enabled()) {
156
+ return;
157
+ }
158
+
159
+ ARM_CPU(obj)->kvm_adjvtime = true;
160
+ object_property_add_bool(obj, "kvm-no-adjvtime", kvm_no_adjvtime_get,
161
+ kvm_no_adjvtime_set, &error_abort);
162
+ object_property_set_description(obj, "kvm-no-adjvtime",
163
+ "Set on to disable the adjustment of "
164
+ "the virtual counter. VM stopped time "
165
+ "will be counted.", &error_abort);
166
+}
167
+
168
bool kvm_arm_pmu_supported(CPUState *cpu)
169
{
170
return kvm_check_extension(cpu->kvm_state, KVM_CAP_ARM_PMU_V3);
171
diff --git a/target/arm/monitor.c b/target/arm/monitor.c
172
index XXXXXXX..XXXXXXX 100644
173
--- a/target/arm/monitor.c
174
+++ b/target/arm/monitor.c
175
@@ -XXX,XX +XXX,XX @@ static const char *cpu_model_advertised_features[] = {
176
"sve128", "sve256", "sve384", "sve512",
177
"sve640", "sve768", "sve896", "sve1024", "sve1152", "sve1280",
178
"sve1408", "sve1536", "sve1664", "sve1792", "sve1920", "sve2048",
179
+ "kvm-no-adjvtime",
180
NULL
181
};
182
183
diff --git a/tests/qtest/arm-cpu-features.c b/tests/qtest/arm-cpu-features.c
184
index XXXXXXX..XXXXXXX 100644
185
--- a/tests/qtest/arm-cpu-features.c
186
+++ b/tests/qtest/arm-cpu-features.c
187
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion(const void *data)
188
assert_has_feature_enabled(qts, "cortex-a15", "pmu");
189
assert_has_not_feature(qts, "cortex-a15", "aarch64");
190
191
+ assert_has_not_feature(qts, "max", "kvm-no-adjvtime");
192
+
193
if (g_str_equal(qtest_get_arch(), "aarch64")) {
194
assert_has_feature_enabled(qts, "max", "aarch64");
195
assert_has_feature_enabled(qts, "max", "sve");
196
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion_kvm(const void *data)
197
return;
198
}
199
200
+ assert_has_feature_disabled(qts, "host", "kvm-no-adjvtime");
201
+
202
if (g_str_equal(qtest_get_arch(), "aarch64")) {
203
bool kvm_supports_sve;
204
char max_name[8], name[8];
205
diff --git a/docs/arm-cpu-features.rst b/docs/arm-cpu-features.rst
206
index XXXXXXX..XXXXXXX 100644
207
--- a/docs/arm-cpu-features.rst
208
+++ b/docs/arm-cpu-features.rst
209
@@ -XXX,XX +XXX,XX @@ supporting the feature or only supporting the feature under certain
210
configurations. For example, the `aarch64` CPU feature, which, when
211
disabled, enables the optional AArch32 CPU feature, is only supported
212
when using the KVM accelerator and when running on a host CPU type that
213
-supports the feature.
214
+supports the feature. While `aarch64` currently only works with KVM,
215
+it could work with TCG. CPU features that are specific to KVM are
216
+prefixed with "kvm-" and are described in "KVM VCPU Features".
217
218
CPU Feature Probing
219
===================
220
@@ -XXX,XX +XXX,XX @@ disabling many SVE vector lengths would be quite verbose, the `sve<N>` CPU
221
properties have special semantics (see "SVE CPU Property Parsing
222
Semantics").
223
224
+KVM VCPU Features
225
+=================
226
+
227
+KVM VCPU features are CPU features that are specific to KVM, such as
228
+paravirt features or features that enable CPU virtualization extensions.
229
+The features' CPU properties are only available when KVM is enabled and
230
+are named with the prefix "kvm-". KVM VCPU features may be probed,
231
+enabled, and disabled in the same way as other CPU features. Below is
232
+the list of KVM VCPU features and their descriptions.
233
+
234
+ kvm-no-adjvtime By default kvm-no-adjvtime is disabled. This
235
+ means that by default the virtual time
236
+ adjustment is enabled (vtime is *not not*
237
+ adjusted).
238
+
239
+ When virtual time adjustment is enabled each
240
+ time the VM transitions back to running state
241
+ the VCPU's virtual counter is updated to ensure
242
+ stopped time is not counted. This avoids time
243
+ jumps surprising guest OSes and applications,
244
+ as long as they use the virtual counter for
245
+ timekeeping. However it has the side effect of
246
+ the virtual and physical counters diverging.
247
+ All timekeeping based on the virtual counter
248
+ will appear to lag behind any timekeeping that
249
+ does not subtract VM stopped time. The guest
250
+ may resynchronize its virtual counter with
251
+ other time sources as needed.
252
+
253
+ Enable kvm-no-adjvtime to disable virtual time
254
+ adjustment, also restoring the legacy (pre-5.0)
255
+ behavior.
256
+
257
SVE CPU Properties
258
==================
259
260
--
88
--
261
2.20.1
89
2.20.1
262
90
263
91
diff view generated by jsdifflib
1
The guest can use the semihosting API to open a handle
1
From: Eric Auger <eric.auger@redhat.com>
2
corresponding to QEMU's own stdin, stdout, or stderr.
3
When the guest closes this handle, we should not
4
close the underlying host stdin/stdout/stderr
5
the way we would do if the handle corresponded to
6
a host fd we'd opened on behalf of the guest in SYS_OPEN.
7
2
3
Restructure the finalize_gic_version with switch cases and
4
clearly separate the following cases:
5
6
- KVM mode / in-kernel irqchip
7
- KVM mode / userspace irqchip
8
- TCG mode
9
10
In KVM mode / in-kernel irqchip , we explictly check whether
11
the chosen version is supported by the host. If the end-user
12
explicitly sets v2/v3 and this is not supported by the host,
13
then the user gets an explicit error message. Note that for
14
old kernels where the CREATE_DEVICE ioctl doesn't exist then
15
we will now fail if the user specifically asked for gicv2,
16
where previously we (probably) would have succeeded.
17
18
In KVM mode / userspace irqchip we immediatly output an error
19
in case the end-user explicitly selected v3. Also we warn the
20
end-user about the unexpected usage of gic-version=host in
21
that case as only userspace GICv2 is supported.
22
23
Signed-off-by: Eric Auger <eric.auger@redhat.com>
24
Reviewed-by: Andrew Jones <drjones@redhat.com>
25
Message-id: 20200311131618.7187-6-eric.auger@redhat.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Message-id: 20200124172954.28481-1-peter.maydell@linaro.org
12
---
27
---
13
target/arm/arm-semi.c | 9 +++++++++
28
hw/arm/virt.c | 88 +++++++++++++++++++++++++++++++++++++++------------
14
1 file changed, 9 insertions(+)
29
1 file changed, 67 insertions(+), 21 deletions(-)
15
30
16
diff --git a/target/arm/arm-semi.c b/target/arm/arm-semi.c
31
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
17
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/arm-semi.c
33
--- a/hw/arm/virt.c
19
+++ b/target/arm/arm-semi.c
34
+++ b/hw/arm/virt.c
20
@@ -XXX,XX +XXX,XX @@ static uint32_t host_closefn(ARMCPU *cpu, GuestFD *gf)
35
@@ -XXX,XX +XXX,XX @@ static void virt_set_memmap(VirtMachineState *vms)
36
*/
37
static void finalize_gic_version(VirtMachineState *vms)
21
{
38
{
22
CPUARMState *env = &cpu->env;
39
- if (vms->gic_version == VIRT_GIC_VERSION_HOST ||
23
40
- vms->gic_version == VIRT_GIC_VERSION_MAX) {
24
+ /*
41
- if (!kvm_enabled()) {
25
+ * Only close the underlying host fd if it's one we opened on behalf
42
- if (vms->gic_version == VIRT_GIC_VERSION_HOST) {
26
+ * of the guest in SYS_OPEN.
43
- error_report("gic-version=host requires KVM");
27
+ */
44
- exit(1);
28
+ if (gf->hostfd == STDIN_FILENO ||
45
- } else {
29
+ gf->hostfd == STDOUT_FILENO ||
46
- /* "max": currently means 3 for TCG */
30
+ gf->hostfd == STDERR_FILENO) {
47
- vms->gic_version = VIRT_GIC_VERSION_3;
31
+ return 0;
48
- }
49
- } else {
50
- int probe_bitmap = kvm_arm_vgic_probe();
51
+ if (kvm_enabled()) {
52
+ int probe_bitmap;
53
54
- if (!probe_bitmap) {
55
+ if (!kvm_irqchip_in_kernel()) {
56
+ switch (vms->gic_version) {
57
+ case VIRT_GIC_VERSION_HOST:
58
+ warn_report(
59
+ "gic-version=host not relevant with kernel-irqchip=off "
60
+ "as only userspace GICv2 is supported. Using v2 ...");
61
+ return;
62
+ case VIRT_GIC_VERSION_MAX:
63
+ case VIRT_GIC_VERSION_NOSEL:
64
+ vms->gic_version = VIRT_GIC_VERSION_2;
65
+ return;
66
+ case VIRT_GIC_VERSION_2:
67
+ return;
68
+ case VIRT_GIC_VERSION_3:
69
error_report(
70
- "Unable to determine GIC version supported by host");
71
+ "gic-version=3 is not supported with kernel-irqchip=off");
72
exit(1);
73
- } else {
74
- if (probe_bitmap & KVM_ARM_VGIC_V3) {
75
- vms->gic_version = VIRT_GIC_VERSION_3;
76
- } else {
77
- vms->gic_version = VIRT_GIC_VERSION_2;
78
- }
79
}
80
}
81
- } else if (vms->gic_version == VIRT_GIC_VERSION_NOSEL) {
82
+
83
+ probe_bitmap = kvm_arm_vgic_probe();
84
+ if (!probe_bitmap) {
85
+ error_report("Unable to determine GIC version supported by host");
86
+ exit(1);
87
+ }
88
+
89
+ switch (vms->gic_version) {
90
+ case VIRT_GIC_VERSION_HOST:
91
+ case VIRT_GIC_VERSION_MAX:
92
+ if (probe_bitmap & KVM_ARM_VGIC_V3) {
93
+ vms->gic_version = VIRT_GIC_VERSION_3;
94
+ } else {
95
+ vms->gic_version = VIRT_GIC_VERSION_2;
96
+ }
97
+ return;
98
+ case VIRT_GIC_VERSION_NOSEL:
99
+ vms->gic_version = VIRT_GIC_VERSION_2;
100
+ break;
101
+ case VIRT_GIC_VERSION_2:
102
+ case VIRT_GIC_VERSION_3:
103
+ break;
104
+ }
105
+
106
+ /* Check chosen version is effectively supported by the host */
107
+ if (vms->gic_version == VIRT_GIC_VERSION_2 &&
108
+ !(probe_bitmap & KVM_ARM_VGIC_V2)) {
109
+ error_report("host does not support in-kernel GICv2 emulation");
110
+ exit(1);
111
+ } else if (vms->gic_version == VIRT_GIC_VERSION_3 &&
112
+ !(probe_bitmap & KVM_ARM_VGIC_V3)) {
113
+ error_report("host does not support in-kernel GICv3 emulation");
114
+ exit(1);
115
+ }
116
+ return;
32
+ }
117
+ }
33
return set_swi_errno(env, close(gf->hostfd));
118
+
119
+ /* TCG mode */
120
+ switch (vms->gic_version) {
121
+ case VIRT_GIC_VERSION_NOSEL:
122
vms->gic_version = VIRT_GIC_VERSION_2;
123
+ break;
124
+ case VIRT_GIC_VERSION_MAX:
125
+ vms->gic_version = VIRT_GIC_VERSION_3;
126
+ break;
127
+ case VIRT_GIC_VERSION_HOST:
128
+ error_report("gic-version=host requires KVM");
129
+ exit(1);
130
+ case VIRT_GIC_VERSION_2:
131
+ case VIRT_GIC_VERSION_3:
132
+ break;
133
}
34
}
134
}
35
135
36
--
136
--
37
2.20.1
137
2.20.1
38
138
39
139
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
Signed-off-by: Andrew Jones <drjones@redhat.com>
3
At the moment if the end-user does not specify the gic-version along
4
Message-id: 20200120101023.16030-3-drjones@redhat.com
4
with KVM acceleration, v2 is set by default. However most of the
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
systems now have GICv3 and sometimes they do not support GICv2
6
compatibility.
7
8
This patch keeps the default v2 selection in all cases except
9
in the KVM accelerated mode when either
10
- the host does not support GICv2 in-kernel emulation or
11
- number of VCPUS exceeds 8.
12
13
Those cases did not work anyway so we do not break any compatibility.
14
Now we get v3 selected in such a case.
15
16
Signed-off-by: Eric Auger <eric.auger@redhat.com>
17
Reported-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
18
Reviewed-by: Andrew Jones <drjones@redhat.com>
19
Message-id: 20200311131618.7187-7-eric.auger@redhat.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
21
---
8
hw/arm/virt.c | 1 +
22
hw/arm/virt.c | 17 ++++++++++++++++-
9
1 file changed, 1 insertion(+)
23
1 file changed, 16 insertions(+), 1 deletion(-)
10
24
11
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
25
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
12
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/virt.c
27
--- a/hw/arm/virt.c
14
+++ b/hw/arm/virt.c
28
+++ b/hw/arm/virt.c
15
@@ -XXX,XX +XXX,XX @@ DEFINE_VIRT_MACHINE_AS_LATEST(5, 0)
29
@@ -XXX,XX +XXX,XX @@ static void virt_set_memmap(VirtMachineState *vms)
16
30
*/
17
static void virt_machine_4_2_options(MachineClass *mc)
31
static void finalize_gic_version(VirtMachineState *vms)
18
{
32
{
19
+ virt_machine_5_0_options(mc);
33
+ unsigned int max_cpus = MACHINE(vms)->smp.max_cpus;
20
compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len);
34
+
21
}
35
if (kvm_enabled()) {
22
DEFINE_VIRT_MACHINE(4, 2)
36
int probe_bitmap;
37
38
@@ -XXX,XX +XXX,XX @@ static void finalize_gic_version(VirtMachineState *vms)
39
}
40
return;
41
case VIRT_GIC_VERSION_NOSEL:
42
- vms->gic_version = VIRT_GIC_VERSION_2;
43
+ if ((probe_bitmap & KVM_ARM_VGIC_V2) && max_cpus <= GIC_NCPU) {
44
+ vms->gic_version = VIRT_GIC_VERSION_2;
45
+ } else if (probe_bitmap & KVM_ARM_VGIC_V3) {
46
+ /*
47
+ * in case the host does not support v2 in-kernel emulation or
48
+ * the end-user requested more than 8 VCPUs we now default
49
+ * to v3. In any case defaulting to v2 would be broken.
50
+ */
51
+ vms->gic_version = VIRT_GIC_VERSION_3;
52
+ } else if (max_cpus > GIC_NCPU) {
53
+ error_report("host only supports in-kernel GICv2 emulation "
54
+ "but more than 8 vcpus are requested");
55
+ exit(1);
56
+ }
57
break;
58
case VIRT_GIC_VERSION_2:
59
case VIRT_GIC_VERSION_3:
23
--
60
--
24
2.20.1
61
2.20.1
25
62
26
63
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Beata Michalska <beata.michalska@linaro.org>
2
2
3
When a VM is stopped (such as when it's paused) guest virtual time
3
KVM_SET_VCPU_EVENTS might actually lead to vcpu registers being modified.
4
should stop counting. Otherwise, when the VM is resumed it will
4
As such this should be the last step of sync to avoid potential overwriting
5
experience time jumps and its kernel may report soft lockups. Not
5
of whatever changes KVM might have done.
6
counting virtual time while the VM is stopped has the side effect
7
of making the guest's time appear to lag when compared with real
8
time, and even with time derived from the physical counter. For
9
this reason, this change, which is enabled by default, comes with
10
a KVM CPU feature allowing it to be disabled, restoring legacy
11
behavior.
12
6
13
This patch only provides the implementation of the virtual time
7
Signed-off-by: Beata Michalska <beata.michalska@linaro.org>
14
adjustment. A subsequent patch will provide the CPU property
8
Reviewed-by: Andrew Jones <drjones@redhat.com>
15
allowing the change to be enabled and disabled.
9
Message-id: 20200312003401.29017-2-beata.michalska@linaro.org
16
17
Reported-by: Bijan Mottahedeh <bijan.mottahedeh@oracle.com>
18
Signed-off-by: Andrew Jones <drjones@redhat.com>
19
Message-id: 20200120101023.16030-6-drjones@redhat.com
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
11
---
23
target/arm/cpu.h | 7 ++++
12
target/arm/kvm32.c | 15 ++++++++++-----
24
target/arm/kvm_arm.h | 38 ++++++++++++++++++
13
target/arm/kvm64.c | 15 ++++++++++-----
25
target/arm/kvm.c | 92 ++++++++++++++++++++++++++++++++++++++++++++
14
2 files changed, 20 insertions(+), 10 deletions(-)
26
target/arm/kvm32.c | 3 ++
27
target/arm/kvm64.c | 3 ++
28
target/arm/machine.c | 7 ++++
29
6 files changed, 150 insertions(+)
30
15
31
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/cpu.h
34
+++ b/target/arm/cpu.h
35
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
36
/* KVM init features for this CPU */
37
uint32_t kvm_init_features[7];
38
39
+ /* KVM CPU state */
40
+
41
+ /* KVM virtual time adjustment */
42
+ bool kvm_adjvtime;
43
+ bool kvm_vtime_dirty;
44
+ uint64_t kvm_vtime;
45
+
46
/* Uniprocessor system with MP extensions */
47
bool mp_is_up;
48
49
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
50
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/kvm_arm.h
52
+++ b/target/arm/kvm_arm.h
53
@@ -XXX,XX +XXX,XX @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level);
54
*/
55
bool write_kvmstate_to_list(ARMCPU *cpu);
56
57
+/**
58
+ * kvm_arm_cpu_pre_save:
59
+ * @cpu: ARMCPU
60
+ *
61
+ * Called after write_kvmstate_to_list() from cpu_pre_save() to update
62
+ * the cpreg list with KVM CPU state.
63
+ */
64
+void kvm_arm_cpu_pre_save(ARMCPU *cpu);
65
+
66
+/**
67
+ * kvm_arm_cpu_post_load:
68
+ * @cpu: ARMCPU
69
+ *
70
+ * Called from cpu_post_load() to update KVM CPU state from the cpreg list.
71
+ */
72
+void kvm_arm_cpu_post_load(ARMCPU *cpu);
73
+
74
/**
75
* kvm_arm_reset_vcpu:
76
* @cpu: ARMCPU
77
@@ -XXX,XX +XXX,XX @@ int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu);
78
*/
79
int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu);
80
81
+/**
82
+ * kvm_arm_get_virtual_time:
83
+ * @cs: CPUState
84
+ *
85
+ * Gets the VCPU's virtual counter and stores it in the KVM CPU state.
86
+ */
87
+void kvm_arm_get_virtual_time(CPUState *cs);
88
+
89
+/**
90
+ * kvm_arm_put_virtual_time:
91
+ * @cs: CPUState
92
+ *
93
+ * Sets the VCPU's virtual counter to the value stored in the KVM CPU state.
94
+ */
95
+void kvm_arm_put_virtual_time(CPUState *cs);
96
+
97
+void kvm_arm_vm_state_change(void *opaque, int running, RunState state);
98
+
99
int kvm_arm_vgic_probe(void);
100
101
void kvm_arm_pmu_set_irq(CPUState *cs, int irq);
102
@@ -XXX,XX +XXX,XX @@ static inline void kvm_arm_pmu_set_irq(CPUState *cs, int irq) {}
103
static inline void kvm_arm_pmu_init(CPUState *cs) {}
104
105
static inline void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map) {}
106
+
107
+static inline void kvm_arm_get_virtual_time(CPUState *cs) {}
108
+static inline void kvm_arm_put_virtual_time(CPUState *cs) {}
109
#endif
110
111
static inline const char *gic_class_name(void)
112
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
113
index XXXXXXX..XXXXXXX 100644
114
--- a/target/arm/kvm.c
115
+++ b/target/arm/kvm.c
116
@@ -XXX,XX +XXX,XX @@ static int compare_u64(const void *a, const void *b)
117
return 0;
118
}
119
120
+/*
121
+ * cpreg_values are sorted in ascending order by KVM register ID
122
+ * (see kvm_arm_init_cpreg_list). This allows us to cheaply find
123
+ * the storage for a KVM register by ID with a binary search.
124
+ */
125
+static uint64_t *kvm_arm_get_cpreg_ptr(ARMCPU *cpu, uint64_t regidx)
126
+{
127
+ uint64_t *res;
128
+
129
+ res = bsearch(&regidx, cpu->cpreg_indexes, cpu->cpreg_array_len,
130
+ sizeof(uint64_t), compare_u64);
131
+ assert(res);
132
+
133
+ return &cpu->cpreg_values[res - cpu->cpreg_indexes];
134
+}
135
+
136
/* Initialize the ARMCPU cpreg list according to the kernel's
137
* definition of what CPU registers it knows about (and throw away
138
* the previous TCG-created cpreg list).
139
@@ -XXX,XX +XXX,XX @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level)
140
return ok;
141
}
142
143
+void kvm_arm_cpu_pre_save(ARMCPU *cpu)
144
+{
145
+ /* KVM virtual time adjustment */
146
+ if (cpu->kvm_vtime_dirty) {
147
+ *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT) = cpu->kvm_vtime;
148
+ }
149
+}
150
+
151
+void kvm_arm_cpu_post_load(ARMCPU *cpu)
152
+{
153
+ /* KVM virtual time adjustment */
154
+ if (cpu->kvm_adjvtime) {
155
+ cpu->kvm_vtime = *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT);
156
+ cpu->kvm_vtime_dirty = true;
157
+ }
158
+}
159
+
160
void kvm_arm_reset_vcpu(ARMCPU *cpu)
161
{
162
int ret;
163
@@ -XXX,XX +XXX,XX @@ int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu)
164
return 0;
165
}
166
167
+void kvm_arm_get_virtual_time(CPUState *cs)
168
+{
169
+ ARMCPU *cpu = ARM_CPU(cs);
170
+ struct kvm_one_reg reg = {
171
+ .id = KVM_REG_ARM_TIMER_CNT,
172
+ .addr = (uintptr_t)&cpu->kvm_vtime,
173
+ };
174
+ int ret;
175
+
176
+ if (cpu->kvm_vtime_dirty) {
177
+ return;
178
+ }
179
+
180
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
181
+ if (ret) {
182
+ error_report("Failed to get KVM_REG_ARM_TIMER_CNT");
183
+ abort();
184
+ }
185
+
186
+ cpu->kvm_vtime_dirty = true;
187
+}
188
+
189
+void kvm_arm_put_virtual_time(CPUState *cs)
190
+{
191
+ ARMCPU *cpu = ARM_CPU(cs);
192
+ struct kvm_one_reg reg = {
193
+ .id = KVM_REG_ARM_TIMER_CNT,
194
+ .addr = (uintptr_t)&cpu->kvm_vtime,
195
+ };
196
+ int ret;
197
+
198
+ if (!cpu->kvm_vtime_dirty) {
199
+ return;
200
+ }
201
+
202
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
203
+ if (ret) {
204
+ error_report("Failed to set KVM_REG_ARM_TIMER_CNT");
205
+ abort();
206
+ }
207
+
208
+ cpu->kvm_vtime_dirty = false;
209
+}
210
+
211
int kvm_put_vcpu_events(ARMCPU *cpu)
212
{
213
CPUARMState *env = &cpu->env;
214
@@ -XXX,XX +XXX,XX @@ MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
215
return MEMTXATTRS_UNSPECIFIED;
216
}
217
218
+void kvm_arm_vm_state_change(void *opaque, int running, RunState state)
219
+{
220
+ CPUState *cs = opaque;
221
+ ARMCPU *cpu = ARM_CPU(cs);
222
+
223
+ if (running) {
224
+ if (cpu->kvm_adjvtime) {
225
+ kvm_arm_put_virtual_time(cs);
226
+ }
227
+ } else {
228
+ if (cpu->kvm_adjvtime) {
229
+ kvm_arm_get_virtual_time(cs);
230
+ }
231
+ }
232
+}
233
234
int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
235
{
236
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
16
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
237
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
238
--- a/target/arm/kvm32.c
18
--- a/target/arm/kvm32.c
239
+++ b/target/arm/kvm32.c
19
+++ b/target/arm/kvm32.c
240
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level)
241
#include "qemu-common.h"
21
return ret;
242
#include "cpu.h"
243
#include "qemu/timer.h"
244
+#include "sysemu/runstate.h"
245
#include "sysemu/kvm.h"
246
#include "kvm_arm.h"
247
#include "internals.h"
248
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs)
249
return -EINVAL;
250
}
22
}
251
23
252
+ qemu_add_vm_change_state_handler(kvm_arm_vm_state_change, cs);
24
- ret = kvm_put_vcpu_events(cpu);
25
- if (ret) {
26
- return ret;
27
- }
28
-
29
write_cpustate_to_list(cpu, true);
30
31
if (!write_list_to_kvmstate(cpu, level)) {
32
return EINVAL;
33
}
34
35
+ /*
36
+ * Setting VCPU events should be triggered after syncing the registers
37
+ * to avoid overwriting potential changes made by KVM upon calling
38
+ * KVM_SET_VCPU_EVENTS ioctl
39
+ */
40
+ ret = kvm_put_vcpu_events(cpu);
41
+ if (ret) {
42
+ return ret;
43
+ }
253
+
44
+
254
/* Determine init features for this CPU */
45
kvm_arm_sync_mpstate_to_kvm(cpu);
255
memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features));
46
256
if (cpu->start_powered_off) {
47
return ret;
257
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
48
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
258
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
259
--- a/target/arm/kvm64.c
50
--- a/target/arm/kvm64.c
260
+++ b/target/arm/kvm64.c
51
+++ b/target/arm/kvm64.c
261
@@ -XXX,XX +XXX,XX @@
52
@@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level)
262
#include "qemu/host-utils.h"
53
return ret;
263
#include "qemu/main-loop.h"
54
}
264
#include "exec/gdbstub.h"
55
265
+#include "sysemu/runstate.h"
56
- ret = kvm_put_vcpu_events(cpu);
266
#include "sysemu/kvm.h"
57
- if (ret) {
267
#include "sysemu/kvm_int.h"
58
- return ret;
268
#include "kvm_arm.h"
59
- }
269
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs)
60
-
61
write_cpustate_to_list(cpu, true);
62
63
if (!write_list_to_kvmstate(cpu, level)) {
270
return -EINVAL;
64
return -EINVAL;
271
}
65
}
272
66
273
+ qemu_add_vm_change_state_handler(kvm_arm_vm_state_change, cs);
67
+ /*
68
+ * Setting VCPU events should be triggered after syncing the registers
69
+ * to avoid overwriting potential changes made by KVM upon calling
70
+ * KVM_SET_VCPU_EVENTS ioctl
71
+ */
72
+ ret = kvm_put_vcpu_events(cpu);
73
+ if (ret) {
74
+ return ret;
75
+ }
274
+
76
+
275
/* Determine init features for this CPU */
77
kvm_arm_sync_mpstate_to_kvm(cpu);
276
memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features));
78
277
if (cpu->start_powered_off) {
79
return ret;
278
diff --git a/target/arm/machine.c b/target/arm/machine.c
279
index XXXXXXX..XXXXXXX 100644
280
--- a/target/arm/machine.c
281
+++ b/target/arm/machine.c
282
@@ -XXX,XX +XXX,XX @@ static int cpu_pre_save(void *opaque)
283
/* This should never fail */
284
abort();
285
}
286
+
287
+ /*
288
+ * kvm_arm_cpu_pre_save() must be called after
289
+ * write_kvmstate_to_list()
290
+ */
291
+ kvm_arm_cpu_pre_save(cpu);
292
} else {
293
if (!write_cpustate_to_list(cpu, false)) {
294
/* This should never fail. */
295
@@ -XXX,XX +XXX,XX @@ static int cpu_post_load(void *opaque, int version_id)
296
* we're using it.
297
*/
298
write_list_to_cpustate(cpu);
299
+ kvm_arm_cpu_post_load(cpu);
300
} else {
301
if (!write_list_to_cpustate(cpu)) {
302
return -1;
303
--
80
--
304
2.20.1
81
2.20.1
305
82
306
83
diff view generated by jsdifflib