1
ARM queu; includes all the NVIC rewrite patches.
1
Less than a day of post-3.0 code review and already enough
2
The QOMify-armv7m patchset hasn't got enough review just
2
patches for another pullreq :-)
3
yet but I may be able to sneak it in before freeze
4
tomorrow if it gets review. Didn't want to hold this lot
5
up waiting, anyway.
6
3
7
thanks
4
thanks
8
-- PMM
5
-- PMM
9
6
7
The following changes since commit c542a9f9794ec8e0bc3fcf5956d3cc8bce667789:
10
8
11
The following changes since commit 8f2d7c341184a95d05476ea3c45dbae2b9ddbe51:
9
Merge remote-tracking branch 'remotes/armbru/tags/pull-tests-2018-08-16' into staging (2018-08-16 09:50:54 +0100)
12
10
13
Merge remote-tracking branch 'remotes/berrange/tags/pull-qcrypto-2017-02-27-1' into staging (2017-02-27 15:33:21 +0000)
11
are available in the Git repository at:
14
12
15
are available in the git repository at:
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180816
16
14
17
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20170227
15
for you to fetch changes up to fcf13ca556f462b52956059bf8fa622bc8575edb:
18
16
19
for you to fetch changes up to 94d5bcf5a7f3799660b62098a5183f161aad0601:
17
hw/arm/mps2-tz: Replace init_sysbus_child() with sysbus_init_child_obj() (2018-08-16 14:29:58 +0100)
20
21
hw/arm/exynos: Fix proper mapping of CPUs by providing real cluster ID (2017-02-27 17:23:16 +0000)
22
18
23
----------------------------------------------------------------
19
----------------------------------------------------------------
24
target-arm queue:
20
target-arm queue:
25
* raspi2: implement RNG module, GPIO and new SD card controller
21
* Fixes for various bugs in SVE instructions
26
(sufficient to boot new raspbian kernels)
22
* Add model of Freescale i.MX6 UltraLite 14x14 EVK Board
27
* sdhci: bugfixes for block transfers
23
* hw/arm: make bitbanded IO optional on ARMv7-M
28
* virt: fix cpu object reference leak
24
* Add model of Cortex-M0 CPU
29
* Add missing fp_access_check() to aarch64 crypto instructions
25
* Add support for loading Intel HEX files to the generic loader
30
* cputlb: Don't assume do_unassigned_access() never returns
26
* imx_spi: Unset XCH when TX FIFO becomes empty
31
* virt: Add a user option to disallow ITS instantiation
27
* aspeed_sdmc: fix various bugs
32
* i.MX timers: fix reset handling
28
* Fix bugs in Arm FP16 instruction support
33
* ARMv7M NVIC: rewrite to fix broken priority handling and masking
29
* Fix aa64 FCADD and FCMLA decode
34
* exynos: Fix proper mapping of CPUs by providing real cluster ID
30
* softfloat: Fix missing inexact for floating-point add
35
* exynos: Fix Linux kernel division by zero for PLLs
31
* hw/arm/mps2-tz: Replace init_sysbus_child() with sysbus_init_child_obj()
36
32
37
----------------------------------------------------------------
33
----------------------------------------------------------------
38
Clement Deschamps (4):
34
Cédric Le Goater (1):
39
bcm2835_sdhost: add bcm2835 sdhost controller
35
aspeed: add a max_ram_size property to the memory controller
40
hw/sd: add card-reparenting function
41
bcm2835_gpio: add bcm2835 gpio controller
42
bcm2835: add sdhost and gpio controllers
43
36
44
Eric Auger (1):
37
Jean-Christophe Dubois (3):
45
hw/arm/virt: Add a user option to disallow ITS instantiation
38
i.MX6UL: Add i.MX6UL specific CCM device
39
i.MX6UL: Add i.MX6UL SOC
40
i.MX6UL: Add Freescale i.MX6 UltraLite 14x14 EVK Board
46
41
47
Igor Mammedov (1):
42
Joel Stanley (5):
48
hw/arm/virt: fix cpu object reference leak
43
aspeed_sdmc: Extend number of valid registers
44
aspeed_sdmc: Fix saved values
45
aspeed_sdmc: Set 'cache initial sequence' always true
46
aspeed_sdmc: Init status always idle
47
aspeed_sdmc: Handle ECC training
49
48
50
Krzysztof Kozlowski (2):
49
Richard Henderson (13):
51
hw/arm/exynos: Fix Linux kernel division by zero for PLLs
50
target/arm: Fix typo in helper_sve_ld1hss_r
52
hw/arm/exynos: Fix proper mapping of CPUs by providing real cluster ID
51
target/arm: Fix sign-extension in sve do_ldr/do_str
52
target/arm: Fix offset for LD1R instructions
53
target/arm: Fix offset scaling for LD_zprr and ST_zprr
54
target/arm: Reformat integer register dump
55
target/arm: Dump SVE state if enabled
56
target/arm: Add sve-max-vq cpu property to -cpu max
57
target/arm: Adjust FPCR_MASK for FZ16
58
target/arm: Ignore float_flag_input_denormal from fp_status_f16
59
target/arm: Use fp_status_fp16 for do_fmpa_zpzzz_h
60
target/arm: Use FZ not FZ16 for SVE FCVT single-half and double-half
61
target/arm: Fix aa64 FCADD and FCMLA decode
62
softfloat: Fix missing inexact for floating-point add
53
63
54
Kurban Mallachiev (1):
64
Stefan Hajnoczi (4):
55
ARM i.MX timers: fix reset handling
65
hw/arm: make bitbanded IO optional on ARMv7-M
66
target/arm: add "cortex-m0" CPU model
67
loader: extract rom_free() function
68
loader: add rom transaction API
56
69
57
Marcin Chojnacki (1):
70
Su Hang (2):
58
target-arm: Implement BCM2835 hardware RNG
71
loader: Implement .hex file loader
72
Add QTest testcase for the Intel Hexadecimal
59
73
60
Michael Davidsaver (5):
74
Thomas Huth (1):
61
armv7m: Rewrite NVIC to not use any GIC code
75
hw/arm/mps2-tz: Replace init_sysbus_child() with sysbus_init_child_obj()
62
arm: gic: Remove references to NVIC
63
armv7m: Escalate exceptions to HardFault if necessary
64
armv7m: Simpler and faster exception start
65
armv7m: VECTCLRACTIVE and VECTRESET are UNPREDICTABLE
66
76
67
Nick Reilly (1):
77
Trent Piepho (1):
68
Add missing fp_access_check() to aarch64 crypto instructions
78
imx_spi: Unset XCH when TX FIFO becomes empty
69
79
70
Peter Maydell (10):
80
configure | 4 +
71
bcm2835_rng: Use qcrypto_random_bytes() rather than rand()
81
hw/arm/Makefile.objs | 1 +
72
cputlb: Don't assume do_unassigned_access() never returns
82
hw/misc/Makefile.objs | 1 +
73
armv7m: Rename nvic_state to NVICState
83
tests/Makefile.include | 2 +
74
armv7m: Implement reading and writing of PRIGROUP
84
include/hw/arm/armv7m.h | 2 +
75
armv7m: Fix condition check for taking exceptions
85
include/hw/arm/fsl-imx6ul.h | 339 ++++++++++++++
76
armv7m: Remove unused armv7m_nvic_acknowledge_irq() return value
86
include/hw/loader.h | 31 ++
77
armv7m: Extract "exception taken" code into functions
87
include/hw/misc/aspeed_sdmc.h | 4 +-
78
armv7m: Check exception return consistency
88
include/hw/misc/imx6ul_ccm.h | 226 +++++++++
79
armv7m: Raise correct kind of UsageFault for attempts to execute ARM code
89
target/arm/cpu.h | 5 +-
80
armv7m: Allow SHCSR writes to change pending and active bits
90
fpu/softfloat.c | 2 +-
91
hw/arm/armv7m.c | 37 +-
92
hw/arm/aspeed.c | 31 ++
93
hw/arm/aspeed_soc.c | 2 +
94
hw/arm/fsl-imx6ul.c | 617 ++++++++++++++++++++++++
95
hw/arm/mcimx6ul-evk.c | 85 ++++
96
hw/arm/mps2-tz.c | 32 +-
97
hw/arm/mps2.c | 1 +
98
hw/arm/msf2-soc.c | 1 +
99
hw/arm/stellaris.c | 1 +
100
hw/arm/stm32f205_soc.c | 1 +
101
hw/core/generic-loader.c | 4 +
102
hw/core/loader.c | 302 +++++++++++-
103
hw/misc/aspeed_sdmc.c | 55 ++-
104
hw/misc/imx6ul_ccm.c | 886 +++++++++++++++++++++++++++++++++++
105
hw/ssi/imx_spi.c | 3 +-
106
linux-user/syscall.c | 19 +-
107
target/arm/cpu.c | 17 +-
108
target/arm/cpu64.c | 29 ++
109
target/arm/helper.c | 18 +-
110
target/arm/sve_helper.c | 4 +-
111
target/arm/translate-a64.c | 120 ++++-
112
target/arm/translate-sve.c | 30 +-
113
tests/hexloader-test.c | 45 ++
114
MAINTAINERS | 6 +
115
default-configs/arm-softmmu.mak | 1 +
116
hw/misc/trace-events | 7 +
117
tests/hex-loader-check-data/test.hex | 18 +
118
38 files changed, 2863 insertions(+), 126 deletions(-)
119
create mode 100644 include/hw/arm/fsl-imx6ul.h
120
create mode 100644 include/hw/misc/imx6ul_ccm.h
121
create mode 100644 hw/arm/fsl-imx6ul.c
122
create mode 100644 hw/arm/mcimx6ul-evk.c
123
create mode 100644 hw/misc/imx6ul_ccm.c
124
create mode 100644 tests/hexloader-test.c
125
create mode 100644 tests/hex-loader-check-data/test.hex
81
126
82
Prasad J Pandit (4):
83
sd: sdhci: mask transfer mode register value
84
sd: sdhci: check transfer mode register in multi block transfer
85
sd: sdhci: conditionally invoke multi block transfer
86
sd: sdhci: Remove block count enable check in single block transfers
87
88
hw/gpio/Makefile.objs | 1 +
89
hw/misc/Makefile.objs | 3 +-
90
hw/sd/Makefile.objs | 1 +
91
hw/intc/gic_internal.h | 7 +-
92
include/hw/arm/bcm2835_peripherals.h | 6 +
93
include/hw/arm/virt.h | 1 +
94
include/hw/gpio/bcm2835_gpio.h | 39 ++
95
include/hw/misc/bcm2835_rng.h | 27 ++
96
include/hw/sd/bcm2835_sdhost.h | 48 ++
97
include/hw/sd/sd.h | 11 +
98
target/arm/cpu.h | 23 +-
99
cputlb.c | 15 +-
100
hw/arm/bcm2835_peripherals.c | 58 ++-
101
hw/arm/exynos4210.c | 18 +
102
hw/arm/virt.c | 32 +-
103
hw/gpio/bcm2835_gpio.c | 353 ++++++++++++++
104
hw/intc/arm_gic.c | 31 +-
105
hw/intc/arm_gic_common.c | 23 +-
106
hw/intc/armv7m_nvic.c | 885 ++++++++++++++++++++++++++++-------
107
hw/misc/bcm2835_rng.c | 149 ++++++
108
hw/misc/exynos4210_clk.c | 164 +++++++
109
hw/sd/bcm2835_sdhost.c | 429 +++++++++++++++++
110
hw/sd/core.c | 30 ++
111
hw/sd/sdhci.c | 25 +-
112
hw/timer/imx_gpt.c | 33 +-
113
linux-user/main.c | 1 +
114
target/arm/cpu.c | 16 +-
115
target/arm/helper.c | 245 +++++++---
116
target/arm/translate-a64.c | 12 +
117
target/arm/translate.c | 8 +-
118
hw/intc/trace-events | 15 +
119
31 files changed, 2376 insertions(+), 333 deletions(-)
120
create mode 100644 include/hw/gpio/bcm2835_gpio.h
121
create mode 100644 include/hw/misc/bcm2835_rng.h
122
create mode 100644 include/hw/sd/bcm2835_sdhost.h
123
create mode 100644 hw/gpio/bcm2835_gpio.c
124
create mode 100644 hw/misc/bcm2835_rng.c
125
create mode 100644 hw/misc/exynos4210_clk.c
126
create mode 100644 hw/sd/bcm2835_sdhost.c
127
diff view generated by jsdifflib
1
Implement the NVIC SHCSR write behaviour which allows pending and
1
From: Richard Henderson <richard.henderson@linaro.org>
2
active status of some exceptions to be changed.
3
2
3
Cc: qemu-stable@nongnu.org (3.0.1)
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
---
7
---
7
hw/intc/armv7m_nvic.c | 13 +++++++++++--
8
target/arm/sve_helper.c | 2 +-
8
1 file changed, 11 insertions(+), 2 deletions(-)
9
1 file changed, 1 insertion(+), 1 deletion(-)
9
10
10
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
11
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
11
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
12
--- a/hw/intc/armv7m_nvic.c
13
--- a/target/arm/sve_helper.c
13
+++ b/hw/intc/armv7m_nvic.c
14
+++ b/target/arm/sve_helper.c
14
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
15
@@ -XXX,XX +XXX,XX @@ DO_LD1(sve_ld1bdu_r, cpu_ldub_data_ra, uint64_t, uint8_t, )
15
cpu->env.v7m.ccr = value;
16
DO_LD1(sve_ld1bds_r, cpu_ldsb_data_ra, uint64_t, int8_t, )
16
break;
17
17
case 0xd24: /* System Handler Control. */
18
DO_LD1(sve_ld1hsu_r, cpu_lduw_data_ra, uint32_t, uint16_t, H1_4)
18
- /* TODO: Real hardware allows you to set/clear the active bits
19
-DO_LD1(sve_ld1hss_r, cpu_ldsw_data_ra, uint32_t, int8_t, H1_4)
19
- under some circumstances. We don't implement this. */
20
+DO_LD1(sve_ld1hss_r, cpu_ldsw_data_ra, uint32_t, int16_t, H1_4)
20
+ s->vectors[ARMV7M_EXCP_MEM].active = (value & (1 << 0)) != 0;
21
DO_LD1(sve_ld1hdu_r, cpu_lduw_data_ra, uint64_t, uint16_t, )
21
+ s->vectors[ARMV7M_EXCP_BUS].active = (value & (1 << 1)) != 0;
22
DO_LD1(sve_ld1hds_r, cpu_ldsw_data_ra, uint64_t, int16_t, )
22
+ s->vectors[ARMV7M_EXCP_USAGE].active = (value & (1 << 3)) != 0;
23
23
+ s->vectors[ARMV7M_EXCP_SVC].active = (value & (1 << 7)) != 0;
24
+ s->vectors[ARMV7M_EXCP_DEBUG].active = (value & (1 << 8)) != 0;
25
+ s->vectors[ARMV7M_EXCP_PENDSV].active = (value & (1 << 10)) != 0;
26
+ s->vectors[ARMV7M_EXCP_SYSTICK].active = (value & (1 << 11)) != 0;
27
+ s->vectors[ARMV7M_EXCP_USAGE].pending = (value & (1 << 12)) != 0;
28
+ s->vectors[ARMV7M_EXCP_MEM].pending = (value & (1 << 13)) != 0;
29
+ s->vectors[ARMV7M_EXCP_BUS].pending = (value & (1 << 14)) != 0;
30
+ s->vectors[ARMV7M_EXCP_SVC].pending = (value & (1 << 15)) != 0;
31
s->vectors[ARMV7M_EXCP_MEM].enabled = (value & (1 << 16)) != 0;
32
s->vectors[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0;
33
s->vectors[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0;
34
--
24
--
35
2.7.4
25
2.18.0
36
26
37
27
diff view generated by jsdifflib
1
M profile doesn't implement ARM, and the architecturally required
1
From: Richard Henderson <richard.henderson@linaro.org>
2
behaviour for attempts to execute with the Thumb bit clear is to
3
generate a UsageFault with the CFSR INVSTATE bit set. We were
4
incorrectly implementing this as generating an UNDEFINSTR UsageFault;
5
fix this.
6
2
3
The expression (int) imm + (uint32_t) len_align turns into uint32_t
4
and thus with negative imm produces a memory operation at the wrong
5
offset. None of the numbers involved are particularly large, so
6
change everything to use int.
7
8
Cc: qemu-stable@nongnu.org (3.0.1)
9
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
---
13
---
10
target/arm/cpu.h | 1 +
14
target/arm/translate-sve.c | 18 ++++++++----------
11
linux-user/main.c | 1 +
15
1 file changed, 8 insertions(+), 10 deletions(-)
12
target/arm/helper.c | 4 ++++
13
target/arm/translate.c | 8 ++++++--
14
4 files changed, 12 insertions(+), 2 deletions(-)
15
16
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
19
--- a/target/arm/translate-sve.c
19
+++ b/target/arm/cpu.h
20
+++ b/target/arm/translate-sve.c
20
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ static bool trans_UCVTF_dd(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
21
#define EXCP_VFIQ 15
22
* The load should begin at the address Rn + IMM.
22
#define EXCP_SEMIHOST 16 /* semihosting call */
23
*/
23
#define EXCP_NOCP 17 /* v7M NOCP UsageFault */
24
24
+#define EXCP_INVSTATE 18 /* v7M INVSTATE UsageFault */
25
-static void do_ldr(DisasContext *s, uint32_t vofs, uint32_t len,
25
26
- int rn, int imm)
26
#define ARMV7M_EXCP_RESET 1
27
+static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
27
#define ARMV7M_EXCP_NMI 2
28
{
28
diff --git a/linux-user/main.c b/linux-user/main.c
29
- uint32_t len_align = QEMU_ALIGN_DOWN(len, 8);
29
index XXXXXXX..XXXXXXX 100644
30
- uint32_t len_remain = len % 8;
30
--- a/linux-user/main.c
31
- uint32_t nparts = len / 8 + ctpop8(len_remain);
31
+++ b/linux-user/main.c
32
+ int len_align = QEMU_ALIGN_DOWN(len, 8);
32
@@ -XXX,XX +XXX,XX @@ void cpu_loop(CPUARMState *env)
33
+ int len_remain = len % 8;
33
switch(trapnr) {
34
+ int nparts = len / 8 + ctpop8(len_remain);
34
case EXCP_UDEF:
35
int midx = get_mem_index(s);
35
case EXCP_NOCP:
36
TCGv_i64 addr, t0, t1;
36
+ case EXCP_INVSTATE:
37
37
{
38
@@ -XXX,XX +XXX,XX @@ static void do_ldr(DisasContext *s, uint32_t vofs, uint32_t len,
38
TaskState *ts = cs->opaque;
39
}
39
uint32_t opcode;
40
40
diff --git a/target/arm/helper.c b/target/arm/helper.c
41
/* Similarly for stores. */
41
index XXXXXXX..XXXXXXX 100644
42
-static void do_str(DisasContext *s, uint32_t vofs, uint32_t len,
42
--- a/target/arm/helper.c
43
- int rn, int imm)
43
+++ b/target/arm/helper.c
44
+static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
44
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
45
{
45
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
46
- uint32_t len_align = QEMU_ALIGN_DOWN(len, 8);
46
env->v7m.cfsr |= R_V7M_CFSR_NOCP_MASK;
47
- uint32_t len_remain = len % 8;
47
break;
48
- uint32_t nparts = len / 8 + ctpop8(len_remain);
48
+ case EXCP_INVSTATE:
49
+ int len_align = QEMU_ALIGN_DOWN(len, 8);
49
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
50
+ int len_remain = len % 8;
50
+ env->v7m.cfsr |= R_V7M_CFSR_INVSTATE_MASK;
51
+ int nparts = len / 8 + ctpop8(len_remain);
51
+ break;
52
int midx = get_mem_index(s);
52
case EXCP_SWI:
53
TCGv_i64 addr, t0;
53
/* The PC already points to the next instruction. */
54
54
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC);
55
diff --git a/target/arm/translate.c b/target/arm/translate.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/translate.c
58
+++ b/target/arm/translate.c
59
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
60
TCGv_i32 addr;
61
TCGv_i64 tmp64;
62
63
- /* M variants do not implement ARM mode. */
64
+ /* M variants do not implement ARM mode; this must raise the INVSTATE
65
+ * UsageFault exception.
66
+ */
67
if (arm_dc_feature(s, ARM_FEATURE_M)) {
68
- goto illegal_op;
69
+ gen_exception_insn(s, 4, EXCP_INVSTATE, syn_uncategorized(),
70
+ default_exception_el(s));
71
+ return;
72
}
73
cond = insn >> 28;
74
if (cond == 0xf){
75
--
55
--
76
2.7.4
56
2.18.0
77
57
78
58
diff view generated by jsdifflib
1
From: Prasad J Pandit <pjp@fedoraproject.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
In SDHCI protocol, the transfer mode register is defined
3
The immediate should be scaled by the size of the memory reference,
4
to be of 6 bits. Mask its value with '0x0037' so that an
4
not the size of the elements into which it is loaded.
5
invalid value could not be assigned.
6
5
7
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
6
Cc: qemu-stable@nongnu.org (3.0.1)
8
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
7
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
9
Message-id: 20170214185225.7994-2-ppandit@redhat.com
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
10
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
hw/sd/sdhci.c | 3 ++-
13
target/arm/translate-sve.c | 3 ++-
13
1 file changed, 2 insertions(+), 1 deletion(-)
14
1 file changed, 2 insertions(+), 1 deletion(-)
14
15
15
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
16
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/sd/sdhci.c
18
--- a/target/arm/translate-sve.c
18
+++ b/hw/sd/sdhci.c
19
+++ b/target/arm/translate-sve.c
19
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1R_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn)
20
(SDHC_CAPAB_BASECLKFREQ << 8) | (SDHC_CAPAB_TOUNIT << 7) | \
21
unsigned vsz = vec_full_reg_size(s);
21
(SDHC_CAPAB_TOCLKFREQ))
22
unsigned psz = pred_full_reg_size(s);
22
23
unsigned esz = dtype_esz[a->dtype];
23
+#define MASK_TRNMOD 0x0037
24
+ unsigned msz = dtype_msz(a->dtype);
24
#define MASKED_WRITE(reg, mask, val) (reg = (reg & (mask)) | (val))
25
TCGLabel *over = gen_new_label();
25
26
TCGv_i64 temp;
26
static uint8_t sdhci_slotint(SDHCIState *s)
27
27
@@ -XXX,XX +XXX,XX @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
28
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1R_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn)
28
if (!(s->capareg & SDHC_CAN_DO_DMA)) {
29
29
value &= ~SDHC_TRNS_DMA;
30
/* Load the data. */
30
}
31
temp = tcg_temp_new_i64();
31
- MASKED_WRITE(s->trnmod, mask, value);
32
- tcg_gen_addi_i64(temp, cpu_reg_sp(s, a->rn), a->imm << esz);
32
+ MASKED_WRITE(s->trnmod, mask, value & MASK_TRNMOD);
33
+ tcg_gen_addi_i64(temp, cpu_reg_sp(s, a->rn), a->imm << msz);
33
MASKED_WRITE(s->cmdreg, mask >> 16, value >> 16);
34
tcg_gen_qemu_ld_i64(temp, temp, get_mem_index(s),
34
35
s->be_data | dtype_mop[a->dtype]);
35
/* Writing to the upper byte of CMDREG triggers SD command generation */
36
36
--
37
--
37
2.7.4
38
2.18.0
38
39
39
40
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The VECTCLRACTIVE and VECTRESET bits in the AIRCR are both
3
The scaling should be solely on the memory operation size; the number
4
documented as UNPREDICTABLE if you write a 1 to them when
4
of registers being loaded does not come in to the initial computation.
5
the processor is not halted in Debug state (ie stopped
6
and under the control of an external JTAG debugger).
7
Since we don't implement Debug state or emulated JTAG
8
these bits are always UNPREDICTABLE for us. Instead of
9
logging them as unimplemented we can simply log writes
10
as guest errors and ignore them.
11
5
12
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
6
Cc: qemu-stable@nongnu.org (3.0.1)
13
[PMM: change extracted from another patch; commit message
7
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
14
constructed from scratch]
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
10
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
18
---
12
---
19
hw/intc/armv7m_nvic.c | 8 ++++++--
13
target/arm/translate-sve.c | 5 ++---
20
1 file changed, 6 insertions(+), 2 deletions(-)
14
1 file changed, 2 insertions(+), 3 deletions(-)
21
15
22
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
16
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
23
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/intc/armv7m_nvic.c
18
--- a/target/arm/translate-sve.c
25
+++ b/hw/intc/armv7m_nvic.c
19
+++ b/target/arm/translate-sve.c
26
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
20
@@ -XXX,XX +XXX,XX @@ static bool trans_LD_zprr(DisasContext *s, arg_rprr_load *a, uint32_t insn)
27
qemu_irq_pulse(s->sysresetreq);
21
}
28
}
22
if (sve_access_check(s)) {
29
if (value & 2) {
23
TCGv_i64 addr = new_tmp_a64(s);
30
- qemu_log_mask(LOG_UNIMP, "VECTCLRACTIVE unimplemented\n");
24
- tcg_gen_muli_i64(addr, cpu_reg(s, a->rm),
31
+ qemu_log_mask(LOG_GUEST_ERROR,
25
- (a->nreg + 1) << dtype_msz(a->dtype));
32
+ "Setting VECTCLRACTIVE when not in DEBUG mode "
26
+ tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), dtype_msz(a->dtype));
33
+ "is UNPREDICTABLE\n");
27
tcg_gen_add_i64(addr, addr, cpu_reg_sp(s, a->rn));
34
}
28
do_ld_zpa(s, a->rd, a->pg, addr, a->dtype, a->nreg);
35
if (value & 1) {
29
}
36
- qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
30
@@ -XXX,XX +XXX,XX @@ static bool trans_ST_zprr(DisasContext *s, arg_rprr_store *a, uint32_t insn)
37
+ qemu_log_mask(LOG_GUEST_ERROR,
31
}
38
+ "Setting VECTRESET when not in DEBUG mode "
32
if (sve_access_check(s)) {
39
+ "is UNPREDICTABLE\n");
33
TCGv_i64 addr = new_tmp_a64(s);
40
}
34
- tcg_gen_muli_i64(addr, cpu_reg(s, a->rm), (a->nreg + 1) << a->msz);
41
s->prigroup = extract32(value, 8, 3);
35
+ tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), a->msz);
42
nvic_irq_update(s);
36
tcg_gen_add_i64(addr, addr, cpu_reg_sp(s, a->rn));
37
do_st_zpa(s, a->rd, a->pg, addr, a->msz, a->esz, a->nreg);
38
}
43
--
39
--
44
2.7.4
40
2.18.0
45
41
46
42
diff view generated by jsdifflib
1
From: Nick Reilly <nreilly@blackberry.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The aarch64 crypto instructions for AES and SHA are missing the
3
With PC, there are 33 registers. Three per line lines up nicely
4
check for if the FPU is enabled.
4
without overflowing 80 columns.
5
5
6
Signed-off-by: Nick Reilly <nreilly@blackberry.com>
6
Cc: qemu-stable@nongnu.org (3.0.1)
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
target/arm/translate-a64.c | 12 ++++++++++++
11
target/arm/translate-a64.c | 13 ++++++-------
11
1 file changed, 12 insertions(+)
12
1 file changed, 6 insertions(+), 7 deletions(-)
12
13
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a64.c
16
--- a/target/arm/translate-a64.c
16
+++ b/target/arm/translate-a64.c
17
+++ b/target/arm/translate-a64.c
17
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
18
return;
19
int el = arm_current_el(env);
20
const char *ns_status;
21
22
- cpu_fprintf(f, "PC=%016"PRIx64" SP=%016"PRIx64"\n",
23
- env->pc, env->xregs[31]);
24
- for (i = 0; i < 31; i++) {
25
- cpu_fprintf(f, "X%02d=%016"PRIx64, i, env->xregs[i]);
26
- if ((i % 4) == 3) {
27
- cpu_fprintf(f, "\n");
28
+ cpu_fprintf(f, " PC=%016" PRIx64 " ", env->pc);
29
+ for (i = 0; i < 32; i++) {
30
+ if (i == 31) {
31
+ cpu_fprintf(f, " SP=%016" PRIx64 "\n", env->xregs[i]);
32
} else {
33
- cpu_fprintf(f, " ");
34
+ cpu_fprintf(f, "X%02d=%016" PRIx64 "%s", i, env->xregs[i],
35
+ (i + 2) % 3 ? " " : "\n");
36
}
19
}
37
}
20
38
21
+ if (!fp_access_check(s)) {
22
+ return;
23
+ }
24
+
25
/* Note that we convert the Vx register indexes into the
26
* index within the vfp.regs[] array, so we can share the
27
* helper with the AArch32 instructions.
28
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
29
return;
30
}
31
32
+ if (!fp_access_check(s)) {
33
+ return;
34
+ }
35
+
36
tcg_rd_regno = tcg_const_i32(rd << 1);
37
tcg_rn_regno = tcg_const_i32(rn << 1);
38
tcg_rm_regno = tcg_const_i32(rm << 1);
39
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
40
return;
41
}
42
43
+ if (!fp_access_check(s)) {
44
+ return;
45
+ }
46
+
47
tcg_rd_regno = tcg_const_i32(rd << 1);
48
tcg_rn_regno = tcg_const_i32(rn << 1);
49
50
--
39
--
51
2.7.4
40
2.18.0
52
41
53
42
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Provide a new function sdbus_reparent_card() in sd core for reparenting
3
Also fold the FPCR/FPSR state onto the same line as PSTATE,
4
a card from a SDBus to another one.
4
and mention but do not dump disabled FPU state.
5
5
6
This function is required by the raspi platform, where the two SD
6
Cc: qemu-stable@nongnu.org (3.0.1)
7
controllers can be dynamically switched.
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
9
Tested-by: Alex Bennée <alex.bennee@linaro.org>
10
Message-id: 20170224164021.9066-3-clement.deschamps@antfield.fr
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
[PMM: added a doc comment to the header file]
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
11
---
15
include/hw/sd/sd.h | 11 +++++++++++
12
target/arm/translate-a64.c | 95 +++++++++++++++++++++++++++++++++-----
16
hw/sd/core.c | 30 ++++++++++++++++++++++++++++++
13
1 file changed, 83 insertions(+), 12 deletions(-)
17
2 files changed, 41 insertions(+)
18
14
19
diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
20
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/sd/sd.h
17
--- a/target/arm/translate-a64.c
22
+++ b/include/hw/sd/sd.h
18
+++ b/target/arm/translate-a64.c
23
@@ -XXX,XX +XXX,XX @@ uint8_t sdbus_read_data(SDBus *sd);
19
@@ -XXX,XX +XXX,XX @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
24
bool sdbus_data_ready(SDBus *sd);
20
} else {
25
bool sdbus_get_inserted(SDBus *sd);
21
ns_status = "";
26
bool sdbus_get_readonly(SDBus *sd);
22
}
27
+/**
23
-
28
+ * sdbus_reparent_card: Reparent an SD card from one controller to another
24
- cpu_fprintf(f, "\nPSTATE=%08x %c%c%c%c %sEL%d%c\n",
29
+ * @from: controller bus to remove card from
25
+ cpu_fprintf(f, "PSTATE=%08x %c%c%c%c %sEL%d%c",
30
+ * @to: controller bus to move card to
26
psr,
31
+ *
27
psr & PSTATE_N ? 'N' : '-',
32
+ * Reparent an SD card, effectively unplugging it from one controller
28
psr & PSTATE_Z ? 'Z' : '-',
33
+ * and inserting it into another. This is useful for SoCs like the
29
@@ -XXX,XX +XXX,XX @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
34
+ * bcm2835 which have two SD controllers and connect a single SD card
30
el,
35
+ * to them, selected by the guest reprogramming GPIO line routing.
31
psr & PSTATE_SP ? 'h' : 't');
36
+ */
32
37
+void sdbus_reparent_card(SDBus *from, SDBus *to);
33
- if (flags & CPU_DUMP_FPU) {
38
34
- int numvfpregs = 32;
39
/* Functions to be used by SD devices to report back to qdevified controllers */
35
- for (i = 0; i < numvfpregs; i++) {
40
void sdbus_set_inserted(SDBus *sd, bool inserted);
36
- uint64_t *q = aa64_vfp_qreg(env, i);
41
diff --git a/hw/sd/core.c b/hw/sd/core.c
37
- uint64_t vlo = q[0];
42
index XXXXXXX..XXXXXXX 100644
38
- uint64_t vhi = q[1];
43
--- a/hw/sd/core.c
39
- cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 "%c",
44
+++ b/hw/sd/core.c
40
- i, vhi, vlo, (i & 1 ? '\n' : ' '));
45
@@ -XXX,XX +XXX,XX @@ void sdbus_set_readonly(SDBus *sdbus, bool readonly)
41
+ if (!(flags & CPU_DUMP_FPU)) {
42
+ cpu_fprintf(f, "\n");
43
+ return;
44
+ }
45
+ cpu_fprintf(f, " FPCR=%08x FPSR=%08x\n",
46
+ vfp_get_fpcr(env), vfp_get_fpsr(env));
47
+
48
+ if (arm_feature(env, ARM_FEATURE_SVE)) {
49
+ int j, zcr_len = env->vfp.zcr_el[1] & 0xf; /* fix for system mode */
50
+
51
+ for (i = 0; i <= FFR_PRED_NUM; i++) {
52
+ bool eol;
53
+ if (i == FFR_PRED_NUM) {
54
+ cpu_fprintf(f, "FFR=");
55
+ /* It's last, so end the line. */
56
+ eol = true;
57
+ } else {
58
+ cpu_fprintf(f, "P%02d=", i);
59
+ switch (zcr_len) {
60
+ case 0:
61
+ eol = i % 8 == 7;
62
+ break;
63
+ case 1:
64
+ eol = i % 6 == 5;
65
+ break;
66
+ case 2:
67
+ case 3:
68
+ eol = i % 3 == 2;
69
+ break;
70
+ default:
71
+ /* More than one quadword per predicate. */
72
+ eol = true;
73
+ break;
74
+ }
75
+ }
76
+ for (j = zcr_len / 4; j >= 0; j--) {
77
+ int digits;
78
+ if (j * 4 + 4 <= zcr_len + 1) {
79
+ digits = 16;
80
+ } else {
81
+ digits = (zcr_len % 4 + 1) * 4;
82
+ }
83
+ cpu_fprintf(f, "%0*" PRIx64 "%s", digits,
84
+ env->vfp.pregs[i].p[j],
85
+ j ? ":" : eol ? "\n" : " ");
86
+ }
87
+ }
88
+
89
+ for (i = 0; i < 32; i++) {
90
+ if (zcr_len == 0) {
91
+ cpu_fprintf(f, "Z%02d=%016" PRIx64 ":%016" PRIx64 "%s",
92
+ i, env->vfp.zregs[i].d[1],
93
+ env->vfp.zregs[i].d[0], i & 1 ? "\n" : " ");
94
+ } else if (zcr_len == 1) {
95
+ cpu_fprintf(f, "Z%02d=%016" PRIx64 ":%016" PRIx64
96
+ ":%016" PRIx64 ":%016" PRIx64 "\n",
97
+ i, env->vfp.zregs[i].d[3], env->vfp.zregs[i].d[2],
98
+ env->vfp.zregs[i].d[1], env->vfp.zregs[i].d[0]);
99
+ } else {
100
+ for (j = zcr_len; j >= 0; j--) {
101
+ bool odd = (zcr_len - j) % 2 != 0;
102
+ if (j == zcr_len) {
103
+ cpu_fprintf(f, "Z%02d[%x-%x]=", i, j, j - 1);
104
+ } else if (!odd) {
105
+ if (j > 0) {
106
+ cpu_fprintf(f, " [%x-%x]=", j, j - 1);
107
+ } else {
108
+ cpu_fprintf(f, " [%x]=", j);
109
+ }
110
+ }
111
+ cpu_fprintf(f, "%016" PRIx64 ":%016" PRIx64 "%s",
112
+ env->vfp.zregs[i].d[j * 2 + 1],
113
+ env->vfp.zregs[i].d[j * 2],
114
+ odd || j == 0 ? "\n" : ":");
115
+ }
116
+ }
117
+ }
118
+ } else {
119
+ for (i = 0; i < 32; i++) {
120
+ uint64_t *q = aa64_vfp_qreg(env, i);
121
+ cpu_fprintf(f, "Q%02d=%016" PRIx64 ":%016" PRIx64 "%s",
122
+ i, q[1], q[0], (i & 1 ? "\n" : " "));
123
}
124
- cpu_fprintf(f, "FPCR: %08x FPSR: %08x\n",
125
- vfp_get_fpcr(env), vfp_get_fpsr(env));
46
}
126
}
47
}
127
}
48
128
49
+void sdbus_reparent_card(SDBus *from, SDBus *to)
50
+{
51
+ BusChild *kid = QTAILQ_FIRST(&from->qbus.children);
52
+ SDState *card;
53
+ SDCardClass *sc;
54
+ bool readonly;
55
+
56
+ /* We directly reparent the card object rather than implementing this
57
+ * as a hotpluggable connection because we don't want to expose SD cards
58
+ * to users as being hotpluggable, and we can get away with it in this
59
+ * limited use case. This could perhaps be implemented more cleanly in
60
+ * future by adding support to the hotplug infrastructure for "device
61
+ * can be hotplugged only via code, not by user".
62
+ */
63
+
64
+ if (!kid) {
65
+ return;
66
+ }
67
+
68
+ card = SD_CARD(kid->child);
69
+ sc = SD_CARD_GET_CLASS(card);
70
+ readonly = sc->get_readonly(card);
71
+
72
+ sdbus_set_inserted(from, false);
73
+ object_unparent(OBJECT(kid));
74
+ qdev_set_parent_bus(DEVICE(card), &to->qbus);
75
+ sdbus_set_inserted(to, true);
76
+ sdbus_set_readonly(to, readonly);
77
+}
78
+
79
static const TypeInfo sd_bus_info = {
80
.name = TYPE_SD_BUS,
81
.parent = TYPE_BUS,
82
--
129
--
83
2.7.4
130
2.18.0
84
131
85
132
diff view generated by jsdifflib
1
Having armv7m_nvic_acknowledge_irq() return the new value of
1
From: Richard Henderson <richard.henderson@linaro.org>
2
env->v7m.exception and its one caller assign the return value
3
back to env->v7m.exception is pointless. Just make the return
4
type void instead.
5
2
3
This allows the default (and maximum) vector length to be set
4
from the command-line. Which is extraordinarily helpful in
5
debugging problems depending on vector length without having to
6
bake knowledge of PR_SET_SVE_VL into every guest binary.
7
8
Cc: qemu-stable@nongnu.org (3.0.1)
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Tested-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
---
13
---
9
target/arm/cpu.h | 2 +-
14
target/arm/cpu.h | 3 +++
10
hw/intc/armv7m_nvic.c | 4 +---
15
linux-user/syscall.c | 19 +++++++++++++------
11
target/arm/helper.c | 2 +-
16
target/arm/cpu.c | 6 +++---
12
3 files changed, 3 insertions(+), 5 deletions(-)
17
target/arm/cpu64.c | 29 +++++++++++++++++++++++++++++
18
target/arm/helper.c | 7 +++++--
19
5 files changed, 53 insertions(+), 11 deletions(-)
13
20
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
23
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
24
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
25
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
26
27
/* Used to synchronize KVM and QEMU in-kernel device levels */
28
uint8_t device_irq_level;
29
+
30
+ /* Used to set the maximum vector length the cpu will support. */
31
+ uint32_t sve_max_vq;
32
};
33
34
static inline ARMCPU *arm_env_get_cpu(CPUARMState *env)
35
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/linux-user/syscall.c
38
+++ b/linux-user/syscall.c
39
@@ -XXX,XX +XXX,XX @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
40
#endif
41
#ifdef TARGET_AARCH64
42
case TARGET_PR_SVE_SET_VL:
43
- /* We cannot support either PR_SVE_SET_VL_ONEXEC
44
- or PR_SVE_VL_INHERIT. Therefore, anything above
45
- ARM_MAX_VQ results in EINVAL. */
46
+ /*
47
+ * We cannot support either PR_SVE_SET_VL_ONEXEC or
48
+ * PR_SVE_VL_INHERIT. Note the kernel definition
49
+ * of sve_vl_valid allows for VQ=512, i.e. VL=8192,
50
+ * even though the current architectural maximum is VQ=16.
51
+ */
52
ret = -TARGET_EINVAL;
53
if (arm_feature(cpu_env, ARM_FEATURE_SVE)
54
- && arg2 >= 0 && arg2 <= ARM_MAX_VQ * 16 && !(arg2 & 15)) {
55
+ && arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
56
CPUARMState *env = cpu_env;
57
- int old_vq = (env->vfp.zcr_el[1] & 0xf) + 1;
58
- int vq = MAX(arg2 / 16, 1);
59
+ ARMCPU *cpu = arm_env_get_cpu(env);
60
+ uint32_t vq, old_vq;
61
+
62
+ old_vq = (env->vfp.zcr_el[1] & 0xf) + 1;
63
+ vq = MAX(arg2 / 16, 1);
64
+ vq = MIN(vq, cpu->sve_max_vq);
65
66
if (vq < old_vq) {
67
aarch64_sve_narrow_vq(env, vq);
68
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/target/arm/cpu.c
71
+++ b/target/arm/cpu.c
72
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
73
env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 16, 2, 3);
74
env->cp15.cptr_el[3] |= CPTR_EZ;
75
/* with maximum vector length */
76
- env->vfp.zcr_el[1] = ARM_MAX_VQ - 1;
77
- env->vfp.zcr_el[2] = ARM_MAX_VQ - 1;
78
- env->vfp.zcr_el[3] = ARM_MAX_VQ - 1;
79
+ env->vfp.zcr_el[1] = cpu->sve_max_vq - 1;
80
+ env->vfp.zcr_el[2] = env->vfp.zcr_el[1];
81
+ env->vfp.zcr_el[3] = env->vfp.zcr_el[1];
82
#else
83
/* Reset into the highest available EL */
84
if (arm_feature(env, ARM_FEATURE_EL3)) {
85
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/target/arm/cpu64.c
88
+++ b/target/arm/cpu64.c
89
@@ -XXX,XX +XXX,XX @@
90
#include "sysemu/sysemu.h"
91
#include "sysemu/kvm.h"
92
#include "kvm_arm.h"
93
+#include "qapi/visitor.h"
94
95
static inline void set_feature(CPUARMState *env, int feature)
96
{
97
@@ -XXX,XX +XXX,XX @@ static void aarch64_a53_initfn(Object *obj)
98
define_arm_cp_regs(cpu, cortex_a57_a53_cp_reginfo);
19
}
99
}
100
101
+static void cpu_max_get_sve_vq(Object *obj, Visitor *v, const char *name,
102
+ void *opaque, Error **errp)
103
+{
104
+ ARMCPU *cpu = ARM_CPU(obj);
105
+ visit_type_uint32(v, name, &cpu->sve_max_vq, errp);
106
+}
107
+
108
+static void cpu_max_set_sve_vq(Object *obj, Visitor *v, const char *name,
109
+ void *opaque, Error **errp)
110
+{
111
+ ARMCPU *cpu = ARM_CPU(obj);
112
+ Error *err = NULL;
113
+
114
+ visit_type_uint32(v, name, &cpu->sve_max_vq, &err);
115
+
116
+ if (!err && (cpu->sve_max_vq == 0 || cpu->sve_max_vq > ARM_MAX_VQ)) {
117
+ error_setg(&err, "unsupported SVE vector length");
118
+ error_append_hint(&err, "Valid sve-max-vq in range [1-%d]\n",
119
+ ARM_MAX_VQ);
120
+ }
121
+ error_propagate(errp, err);
122
+}
123
+
124
/* -cpu max: if KVM is enabled, like -cpu host (best possible with this host);
125
* otherwise, a CPU with as many features enabled as our emulation supports.
126
* The version of '-cpu max' for qemu-system-arm is defined in cpu.c;
127
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
128
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
129
cpu->dcz_blocksize = 7; /* 512 bytes */
20
#endif
130
#endif
21
void armv7m_nvic_set_pending(void *opaque, int irq);
131
+
22
-int armv7m_nvic_acknowledge_irq(void *opaque);
132
+ cpu->sve_max_vq = ARM_MAX_VQ;
23
+void armv7m_nvic_acknowledge_irq(void *opaque);
133
+ object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_vq,
24
void armv7m_nvic_complete_irq(void *opaque, int irq);
134
+ cpu_max_set_sve_vq, NULL, NULL, &error_fatal);
25
135
}
26
/* Interface for defining coprocessor registers.
27
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/intc/armv7m_nvic.c
30
+++ b/hw/intc/armv7m_nvic.c
31
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq)
32
}
136
}
33
137
34
/* Make pending IRQ active. */
138
@@ -XXX,XX +XXX,XX @@ void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq)
35
-int armv7m_nvic_acknowledge_irq(void *opaque)
139
uint64_t pmask;
36
+void armv7m_nvic_acknowledge_irq(void *opaque)
140
37
{
141
assert(vq >= 1 && vq <= ARM_MAX_VQ);
38
NVICState *s = (NVICState *)opaque;
142
+ assert(vq <= arm_env_get_cpu(env)->sve_max_vq);
39
CPUARMState *env = &s->cpu->env;
143
40
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_acknowledge_irq(void *opaque)
144
/* Zap the high bits of the zregs. */
41
env->v7m.exception = s->vectpending;
145
for (i = 0; i < 32; i++) {
42
43
nvic_irq_update(s);
44
-
45
- return env->v7m.exception;
46
}
47
48
void armv7m_nvic_complete_irq(void *opaque, int irq)
49
diff --git a/target/arm/helper.c b/target/arm/helper.c
146
diff --git a/target/arm/helper.c b/target/arm/helper.c
50
index XXXXXXX..XXXXXXX 100644
147
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/helper.c
148
--- a/target/arm/helper.c
52
+++ b/target/arm/helper.c
149
+++ b/target/arm/helper.c
53
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
150
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
54
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG);
151
zcr_len = 0;
55
return;
152
} else {
56
case EXCP_IRQ:
153
int current_el = arm_current_el(env);
57
- env->v7m.exception = armv7m_nvic_acknowledge_irq(env->nvic);
154
+ ARMCPU *cpu = arm_env_get_cpu(env);
58
+ armv7m_nvic_acknowledge_irq(env->nvic);
155
59
break;
156
- zcr_len = env->vfp.zcr_el[current_el <= 1 ? 1 : current_el];
60
case EXCP_EXCEPTION_EXIT:
157
- zcr_len &= 0xf;
61
do_v7m_exception_exit(env);
158
+ zcr_len = cpu->sve_max_vq - 1;
159
+ if (current_el <= 1) {
160
+ zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[1]);
161
+ }
162
if (current_el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
163
zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[2]);
164
}
62
--
165
--
63
2.7.4
166
2.18.0
64
167
65
168
diff view generated by jsdifflib
1
From: Marcin Chojnacki <marcinch7@gmail.com>
1
From: Jean-Christophe Dubois <jcd@tribudubois.net>
2
2
3
Recent vanilla Raspberry Pi kernels started to make use of
3
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
4
the hardware random number generator in BCM2835 SoC. As a
4
Message-id: 34b6704ceb81b49e35ce1ad162bf758e5141ff87.1532984236.git.jcd@tribudubois.net
5
result, those kernels wouldn't work anymore under QEMU
5
[PMM: fixed some comment typos etc]
6
but rather just freeze during the boot process.
7
8
This patch implements a trivial BCM2835 compatible RNG,
9
and adds it as a peripheral to BCM2835 platform, which
10
allows to boot a vanilla Raspberry Pi kernel under Qemu.
11
12
Changes since v1:
13
* Prevented guest from writing [31..20] bits in rng_status
14
* Removed redundant minimum_version_id_old
15
* Added field entries for the state
16
* Changed realize function to reset
17
18
Signed-off-by: Marcin Chojnacki <marcinch7@gmail.com>
19
Message-id: 20170210210857.47893-1-marcinch7@gmail.com
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
8
---
23
hw/misc/Makefile.objs | 1 +
9
hw/misc/Makefile.objs | 1 +
24
include/hw/arm/bcm2835_peripherals.h | 2 +
10
include/hw/misc/imx6ul_ccm.h | 226 +++++++++
25
include/hw/misc/bcm2835_rng.h | 27 ++++++++
11
hw/misc/imx6ul_ccm.c | 886 +++++++++++++++++++++++++++++++++++
26
hw/arm/bcm2835_peripherals.c | 15 +++++
12
hw/misc/trace-events | 7 +
27
hw/misc/bcm2835_rng.c | 124 +++++++++++++++++++++++++++++++++++
13
4 files changed, 1120 insertions(+)
28
5 files changed, 169 insertions(+)
14
create mode 100644 include/hw/misc/imx6ul_ccm.h
29
create mode 100644 include/hw/misc/bcm2835_rng.h
15
create mode 100644 hw/misc/imx6ul_ccm.c
30
create mode 100644 hw/misc/bcm2835_rng.c
31
16
32
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
17
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
33
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/misc/Makefile.objs
19
--- a/hw/misc/Makefile.objs
35
+++ b/hw/misc/Makefile.objs
20
+++ b/hw/misc/Makefile.objs
36
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_OMAP) += omap_sdrc.o
21
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_IMX) += imx_ccm.o
37
obj-$(CONFIG_OMAP) += omap_tap.o
22
obj-$(CONFIG_IMX) += imx31_ccm.o
38
obj-$(CONFIG_RASPI) += bcm2835_mbox.o
23
obj-$(CONFIG_IMX) += imx25_ccm.o
39
obj-$(CONFIG_RASPI) += bcm2835_property.o
24
obj-$(CONFIG_IMX) += imx6_ccm.o
40
+obj-$(CONFIG_RASPI) += bcm2835_rng.o
25
+obj-$(CONFIG_IMX) += imx6ul_ccm.o
41
obj-$(CONFIG_SLAVIO) += slavio_misc.o
26
obj-$(CONFIG_IMX) += imx6_src.o
42
obj-$(CONFIG_ZYNQ) += zynq_slcr.o
27
obj-$(CONFIG_IMX) += imx7_ccm.o
43
obj-$(CONFIG_ZYNQ) += zynq-xadc.o
28
obj-$(CONFIG_IMX) += imx2_wdt.o
44
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
29
diff --git a/include/hw/misc/imx6ul_ccm.h b/include/hw/misc/imx6ul_ccm.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/hw/arm/bcm2835_peripherals.h
47
+++ b/include/hw/arm/bcm2835_peripherals.h
48
@@ -XXX,XX +XXX,XX @@
49
#include "hw/dma/bcm2835_dma.h"
50
#include "hw/intc/bcm2835_ic.h"
51
#include "hw/misc/bcm2835_property.h"
52
+#include "hw/misc/bcm2835_rng.h"
53
#include "hw/misc/bcm2835_mbox.h"
54
#include "hw/sd/sdhci.h"
55
56
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2835PeripheralState {
57
BCM2835DMAState dma;
58
BCM2835ICState ic;
59
BCM2835PropertyState property;
60
+ BCM2835RngState rng;
61
BCM2835MboxState mboxes;
62
SDHCIState sdhci;
63
} BCM2835PeripheralState;
64
diff --git a/include/hw/misc/bcm2835_rng.h b/include/hw/misc/bcm2835_rng.h
65
new file mode 100644
30
new file mode 100644
66
index XXXXXXX..XXXXXXX
31
index XXXXXXX..XXXXXXX
67
--- /dev/null
32
--- /dev/null
68
+++ b/include/hw/misc/bcm2835_rng.h
33
+++ b/include/hw/misc/imx6ul_ccm.h
69
@@ -XXX,XX +XXX,XX @@
34
@@ -XXX,XX +XXX,XX @@
70
+/*
35
+/*
71
+ * BCM2835 Random Number Generator emulation
36
+ * IMX6UL Clock Control Module
72
+ *
37
+ *
73
+ * Copyright (C) 2017 Marcin Chojnacki <marcinch7@gmail.com>
38
+ * Copyright (C) 2018 by Jean-Christophe Dubois <jcd@tribudubois.net>
74
+ *
39
+ *
75
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
40
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
76
+ * See the COPYING file in the top-level directory.
41
+ * See the COPYING file in the top-level directory.
77
+ */
42
+ */
78
+
43
+
79
+#ifndef BCM2835_RNG_H
44
+#ifndef IMX6UL_CCM_H
80
+#define BCM2835_RNG_H
45
+#define IMX6UL_CCM_H
81
+
46
+
82
+#include "hw/sysbus.h"
47
+#include "hw/misc/imx_ccm.h"
83
+
48
+#include "qemu/bitops.h"
84
+#define TYPE_BCM2835_RNG "bcm2835-rng"
49
+
85
+#define BCM2835_RNG(obj) \
50
+#define CCM_CCR 0
86
+ OBJECT_CHECK(BCM2835RngState, (obj), TYPE_BCM2835_RNG)
51
+#define CCM_CCDR 1
87
+
52
+#define CCM_CSR 2
88
+typedef struct {
53
+#define CCM_CCSR 3
89
+ SysBusDevice busdev;
54
+#define CCM_CACRR 4
90
+ MemoryRegion iomem;
55
+#define CCM_CBCDR 5
91
+
56
+#define CCM_CBCMR 6
92
+ uint32_t rng_ctrl;
57
+#define CCM_CSCMR1 7
93
+ uint32_t rng_status;
58
+#define CCM_CSCMR2 8
94
+} BCM2835RngState;
59
+#define CCM_CSCDR1 9
95
+
60
+#define CCM_CS1CDR 10
96
+#endif
61
+#define CCM_CS2CDR 11
97
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
62
+#define CCM_CDCDR 12
98
index XXXXXXX..XXXXXXX 100644
63
+#define CCM_CHSCCDR 13
99
--- a/hw/arm/bcm2835_peripherals.c
64
+#define CCM_CSCDR2 14
100
+++ b/hw/arm/bcm2835_peripherals.c
65
+#define CCM_CSCDR3 15
101
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
66
+#define CCM_CDHIPR 18
102
object_property_add_const_link(OBJECT(&s->property), "dma-mr",
67
+#define CCM_CTOR 20
103
OBJECT(&s->gpu_bus_mr), &error_abort);
68
+#define CCM_CLPCR 21
104
69
+#define CCM_CISR 22
105
+ /* Random Number Generator */
70
+#define CCM_CIMR 23
106
+ object_initialize(&s->rng, sizeof(s->rng), TYPE_BCM2835_RNG);
71
+#define CCM_CCOSR 24
107
+ object_property_add_child(obj, "rng", OBJECT(&s->rng), NULL);
72
+#define CCM_CGPR 25
108
+ qdev_set_parent_bus(DEVICE(&s->rng), sysbus_get_default());
73
+#define CCM_CCGR0 26
109
+
74
+#define CCM_CCGR1 27
110
/* Extended Mass Media Controller */
75
+#define CCM_CCGR2 28
111
object_initialize(&s->sdhci, sizeof(s->sdhci), TYPE_SYSBUS_SDHCI);
76
+#define CCM_CCGR3 29
112
object_property_add_child(obj, "sdhci", OBJECT(&s->sdhci), NULL);
77
+#define CCM_CCGR4 30
113
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
78
+#define CCM_CCGR5 31
114
sysbus_connect_irq(SYS_BUS_DEVICE(&s->property), 0,
79
+#define CCM_CCGR6 32
115
qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_PROPERTY));
80
+#define CCM_CMEOR 34
116
81
+#define CCM_MAX 35
117
+ /* Random Number Generator */
82
+
118
+ object_property_set_bool(OBJECT(&s->rng), true, "realized", &err);
83
+#define CCM_ANALOG_PLL_ARM 0
119
+ if (err) {
84
+#define CCM_ANALOG_PLL_ARM_SET 1
120
+ error_propagate(errp, err);
85
+#define CCM_ANALOG_PLL_ARM_CLR 2
121
+ return;
86
+#define CCM_ANALOG_PLL_ARM_TOG 3
122
+ }
87
+#define CCM_ANALOG_PLL_USB1 4
123
+
88
+#define CCM_ANALOG_PLL_USB1_SET 5
124
+ memory_region_add_subregion(&s->peri_mr, RNG_OFFSET,
89
+#define CCM_ANALOG_PLL_USB1_CLR 6
125
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->rng), 0));
90
+#define CCM_ANALOG_PLL_USB1_TOG 7
126
+
91
+#define CCM_ANALOG_PLL_USB2 8
127
/* Extended Mass Media Controller */
92
+#define CCM_ANALOG_PLL_USB2_SET 9
128
object_property_set_int(OBJECT(&s->sdhci), BCM2835_SDHC_CAPAREG, "capareg",
93
+#define CCM_ANALOG_PLL_USB2_CLR 10
129
&err);
94
+#define CCM_ANALOG_PLL_USB2_TOG 11
130
diff --git a/hw/misc/bcm2835_rng.c b/hw/misc/bcm2835_rng.c
95
+#define CCM_ANALOG_PLL_SYS 12
96
+#define CCM_ANALOG_PLL_SYS_SET 13
97
+#define CCM_ANALOG_PLL_SYS_CLR 14
98
+#define CCM_ANALOG_PLL_SYS_TOG 15
99
+#define CCM_ANALOG_PLL_SYS_SS 16
100
+#define CCM_ANALOG_PLL_SYS_NUM 20
101
+#define CCM_ANALOG_PLL_SYS_DENOM 24
102
+#define CCM_ANALOG_PLL_AUDIO 28
103
+#define CCM_ANALOG_PLL_AUDIO_SET 29
104
+#define CCM_ANALOG_PLL_AUDIO_CLR 30
105
+#define CCM_ANALOG_PLL_AUDIO_TOG 31
106
+#define CCM_ANALOG_PLL_AUDIO_NUM 32
107
+#define CCM_ANALOG_PLL_AUDIO_DENOM 36
108
+#define CCM_ANALOG_PLL_VIDEO 40
109
+#define CCM_ANALOG_PLL_VIDEO_SET 41
110
+#define CCM_ANALOG_PLL_VIDEO_CLR 42
111
+#define CCM_ANALOG_PLL_VIDEO_TOG 44
112
+#define CCM_ANALOG_PLL_VIDEO_NUM 46
113
+#define CCM_ANALOG_PLL_VIDEO_DENOM 48
114
+#define CCM_ANALOG_PLL_ENET 56
115
+#define CCM_ANALOG_PLL_ENET_SET 57
116
+#define CCM_ANALOG_PLL_ENET_CLR 58
117
+#define CCM_ANALOG_PLL_ENET_TOG 59
118
+#define CCM_ANALOG_PFD_480 60
119
+#define CCM_ANALOG_PFD_480_SET 61
120
+#define CCM_ANALOG_PFD_480_CLR 62
121
+#define CCM_ANALOG_PFD_480_TOG 63
122
+#define CCM_ANALOG_PFD_528 64
123
+#define CCM_ANALOG_PFD_528_SET 65
124
+#define CCM_ANALOG_PFD_528_CLR 66
125
+#define CCM_ANALOG_PFD_528_TOG 67
126
+
127
+/* PMU registers */
128
+#define PMU_REG_1P1 68
129
+#define PMU_REG_3P0 72
130
+#define PMU_REG_2P5 76
131
+#define PMU_REG_CORE 80
132
+
133
+#define CCM_ANALOG_MISC0 84
134
+#define PMU_MISC0 CCM_ANALOG_MISC0
135
+#define CCM_ANALOG_MISC0_SET 85
136
+#define PMU_MISC0_SET CCM_ANALOG_MISC0_SET
137
+#define CCM_ANALOG_MISC0_CLR 86
138
+#define PMU_MISC0_CLR CCM_ANALOG_MISC0_CLR
139
+#define CCM_ANALOG_MISC0_TOG 87
140
+#define PMU_MISC0_TOG CCM_ANALOG_MISC0_TOG
141
+
142
+#define CCM_ANALOG_MISC1 88
143
+#define PMU_MISC1 CCM_ANALOG_MISC1
144
+#define CCM_ANALOG_MISC1_SET 89
145
+#define PMU_MISC1_SET CCM_ANALOG_MISC1_SET
146
+#define CCM_ANALOG_MISC1_CLR 90
147
+#define PMU_MISC1_CLR CCM_ANALOG_MISC1_CLR
148
+#define CCM_ANALOG_MISC1_TOG 91
149
+#define PMU_MISC1_TOG CCM_ANALOG_MISC1_TOG
150
+
151
+#define CCM_ANALOG_MISC2 92
152
+#define PMU_MISC2 CCM_ANALOG_MISC2
153
+#define CCM_ANALOG_MISC2_SET 93
154
+#define PMU_MISC2_SET CCM_ANALOG_MISC2_SET
155
+#define CCM_ANALOG_MISC2_CLR 94
156
+#define PMU_MISC2_CLR CCM_ANALOG_MISC2_CLR
157
+#define CCM_ANALOG_MISC2_TOG 95
158
+#define PMU_MISC2_TOG CCM_ANALOG_MISC2_TOG
159
+
160
+#define TEMPMON_TEMPSENSE0 96
161
+#define TEMPMON_TEMPSENSE0_SET 97
162
+#define TEMPMON_TEMPSENSE0_CLR 98
163
+#define TEMPMON_TEMPSENSE0_TOG 99
164
+#define TEMPMON_TEMPSENSE1 100
165
+#define TEMPMON_TEMPSENSE1_SET 101
166
+#define TEMPMON_TEMPSENSE1_CLR 102
167
+#define TEMPMON_TEMPSENSE1_TOG 103
168
+#define TEMPMON_TEMPSENSE2 164
169
+#define TEMPMON_TEMPSENSE2_SET 165
170
+#define TEMPMON_TEMPSENSE2_CLR 166
171
+#define TEMPMON_TEMPSENSE2_TOG 167
172
+
173
+#define PMU_LOWPWR_CTRL 155
174
+#define PMU_LOWPWR_CTRL_SET 156
175
+#define PMU_LOWPWR_CTRL_CLR 157
176
+#define PMU_LOWPWR_CTRL_TOG 158
177
+
178
+#define USB_ANALOG_USB1_VBUS_DETECT 104
179
+#define USB_ANALOG_USB1_VBUS_DETECT_SET 105
180
+#define USB_ANALOG_USB1_VBUS_DETECT_CLR 106
181
+#define USB_ANALOG_USB1_VBUS_DETECT_TOG 107
182
+#define USB_ANALOG_USB1_CHRG_DETECT 108
183
+#define USB_ANALOG_USB1_CHRG_DETECT_SET 109
184
+#define USB_ANALOG_USB1_CHRG_DETECT_CLR 110
185
+#define USB_ANALOG_USB1_CHRG_DETECT_TOG 111
186
+#define USB_ANALOG_USB1_VBUS_DETECT_STAT 112
187
+#define USB_ANALOG_USB1_CHRG_DETECT_STAT 116
188
+#define USB_ANALOG_USB1_MISC 124
189
+#define USB_ANALOG_USB1_MISC_SET 125
190
+#define USB_ANALOG_USB1_MISC_CLR 126
191
+#define USB_ANALOG_USB1_MISC_TOG 127
192
+#define USB_ANALOG_USB2_VBUS_DETECT 128
193
+#define USB_ANALOG_USB2_VBUS_DETECT_SET 129
194
+#define USB_ANALOG_USB2_VBUS_DETECT_CLR 130
195
+#define USB_ANALOG_USB2_VBUS_DETECT_TOG 131
196
+#define USB_ANALOG_USB2_CHRG_DETECT 132
197
+#define USB_ANALOG_USB2_CHRG_DETECT_SET 133
198
+#define USB_ANALOG_USB2_CHRG_DETECT_CLR 134
199
+#define USB_ANALOG_USB2_CHRG_DETECT_TOG 135
200
+#define USB_ANALOG_USB2_VBUS_DETECT_STAT 136
201
+#define USB_ANALOG_USB2_CHRG_DETECT_STAT 140
202
+#define USB_ANALOG_USB2_MISC 148
203
+#define USB_ANALOG_USB2_MISC_SET 149
204
+#define USB_ANALOG_USB2_MISC_CLR 150
205
+#define USB_ANALOG_USB2_MISC_TOG 151
206
+#define USB_ANALOG_DIGPROG 152
207
+#define CCM_ANALOG_MAX 4096
208
+
209
+/* CCM_CBCMR */
210
+#define R_CBCMR_PRE_PERIPH_CLK_SEL_SHIFT (18)
211
+#define R_CBCMR_PRE_PERIPH_CLK_SEL_LENGTH (2)
212
+#define R_CBCMR_PERIPH_CLK2_SEL_SHIFT (12)
213
+#define R_CBCMR_PERIPH_CLK2_SEL_LENGTH (2)
214
+
215
+/* CCM_CBCDR */
216
+#define R_CBCDR_AHB_PODF_SHIFT (10)
217
+#define R_CBCDR_AHB_PODF_LENGTH (3)
218
+#define R_CBCDR_IPG_PODF_SHIFT (8)
219
+#define R_CBCDR_IPG_PODF_LENGTH (2)
220
+#define R_CBCDR_PERIPH_CLK_SEL_SHIFT (25)
221
+#define R_CBCDR_PERIPH_CLK_SEL_LENGTH (1)
222
+#define R_CBCDR_PERIPH_CLK2_PODF_SHIFT (27)
223
+#define R_CBCDR_PERIPH_CLK2_PODF_LENGTH (3)
224
+
225
+/* CCM_CSCMR1 */
226
+#define R_CSCMR1_PERCLK_PODF_SHIFT (0)
227
+#define R_CSCMR1_PERCLK_PODF_LENGTH (6)
228
+#define R_CSCMR1_PERCLK_CLK_SEL_SHIFT (6)
229
+#define R_CSCMR1_PERCLK_CLK_SEL_LENGTH (1)
230
+
231
+/* CCM_ANALOG_PFD_528 */
232
+#define R_ANALOG_PFD_528_PFD0_FRAC_SHIFT (0)
233
+#define R_ANALOG_PFD_528_PFD0_FRAC_LENGTH (6)
234
+#define R_ANALOG_PFD_528_PFD2_FRAC_SHIFT (16)
235
+#define R_ANALOG_PFD_528_PFD2_FRAC_LENGTH (6)
236
+
237
+/* CCM_ANALOG_PLL_SYS */
238
+#define R_ANALOG_PLL_SYS_DIV_SELECT_SHIFT (0)
239
+#define R_ANALOG_PLL_SYS_DIV_SELECT_LENGTH (1)
240
+
241
+#define CCM_ANALOG_PLL_LOCK (1 << 31);
242
+
243
+#define TYPE_IMX6UL_CCM "imx6ul.ccm"
244
+#define IMX6UL_CCM(obj) OBJECT_CHECK(IMX6ULCCMState, (obj), TYPE_IMX6UL_CCM)
245
+
246
+typedef struct IMX6ULCCMState {
247
+ /* <private> */
248
+ IMXCCMState parent_obj;
249
+
250
+ /* <public> */
251
+ MemoryRegion container;
252
+ MemoryRegion ioccm;
253
+ MemoryRegion ioanalog;
254
+
255
+ uint32_t ccm[CCM_MAX];
256
+ uint32_t analog[CCM_ANALOG_MAX];
257
+
258
+} IMX6ULCCMState;
259
+
260
+#endif /* IMX6UL_CCM_H */
261
diff --git a/hw/misc/imx6ul_ccm.c b/hw/misc/imx6ul_ccm.c
131
new file mode 100644
262
new file mode 100644
132
index XXXXXXX..XXXXXXX
263
index XXXXXXX..XXXXXXX
133
--- /dev/null
264
--- /dev/null
134
+++ b/hw/misc/bcm2835_rng.c
265
+++ b/hw/misc/imx6ul_ccm.c
135
@@ -XXX,XX +XXX,XX @@
266
@@ -XXX,XX +XXX,XX @@
136
+/*
267
+/*
137
+ * BCM2835 Random Number Generator emulation
268
+ * IMX6UL Clock Control Module
138
+ *
269
+ *
139
+ * Copyright (C) 2017 Marcin Chojnacki <marcinch7@gmail.com>
270
+ * Copyright (c) 2018 Jean-Christophe Dubois <jcd@tribudubois.net>
140
+ *
271
+ *
141
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
272
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
142
+ * See the COPYING file in the top-level directory.
273
+ * See the COPYING file in the top-level directory.
274
+ *
275
+ * To get the timer frequencies right, we need to emulate at least part of
276
+ * the CCM.
143
+ */
277
+ */
144
+
278
+
145
+#include "qemu/osdep.h"
279
+#include "qemu/osdep.h"
280
+#include "hw/registerfields.h"
281
+#include "hw/misc/imx6ul_ccm.h"
146
+#include "qemu/log.h"
282
+#include "qemu/log.h"
147
+#include "hw/misc/bcm2835_rng.h"
283
+
148
+
284
+#include "trace.h"
149
+static uint64_t bcm2835_rng_read(void *opaque, hwaddr offset,
285
+
150
+ unsigned size)
286
+static const char *imx6ul_ccm_reg_name(uint32_t reg)
151
+{
287
+{
152
+ BCM2835RngState *s = (BCM2835RngState *)opaque;
288
+ static char unknown[20];
153
+ uint32_t res = 0;
289
+
154
+
290
+ switch (reg) {
155
+ assert(size == 4);
291
+ case CCM_CCR:
156
+
292
+ return "CCR";
157
+ switch (offset) {
293
+ case CCM_CCDR:
158
+ case 0x0: /* rng_ctrl */
294
+ return "CCDR";
159
+ res = s->rng_ctrl;
295
+ case CCM_CSR:
160
+ break;
296
+ return "CSR";
161
+ case 0x4: /* rng_status */
297
+ case CCM_CCSR:
162
+ res = s->rng_status | (1 << 24);
298
+ return "CCSR";
163
+ break;
299
+ case CCM_CACRR:
164
+ case 0x8: /* rng_data */
300
+ return "CACRR";
165
+ res = rand();
301
+ case CCM_CBCDR:
166
+ break;
302
+ return "CBCDR";
167
+
303
+ case CCM_CBCMR:
304
+ return "CBCMR";
305
+ case CCM_CSCMR1:
306
+ return "CSCMR1";
307
+ case CCM_CSCMR2:
308
+ return "CSCMR2";
309
+ case CCM_CSCDR1:
310
+ return "CSCDR1";
311
+ case CCM_CS1CDR:
312
+ return "CS1CDR";
313
+ case CCM_CS2CDR:
314
+ return "CS2CDR";
315
+ case CCM_CDCDR:
316
+ return "CDCDR";
317
+ case CCM_CHSCCDR:
318
+ return "CHSCCDR";
319
+ case CCM_CSCDR2:
320
+ return "CSCDR2";
321
+ case CCM_CSCDR3:
322
+ return "CSCDR3";
323
+ case CCM_CDHIPR:
324
+ return "CDHIPR";
325
+ case CCM_CTOR:
326
+ return "CTOR";
327
+ case CCM_CLPCR:
328
+ return "CLPCR";
329
+ case CCM_CISR:
330
+ return "CISR";
331
+ case CCM_CIMR:
332
+ return "CIMR";
333
+ case CCM_CCOSR:
334
+ return "CCOSR";
335
+ case CCM_CGPR:
336
+ return "CGPR";
337
+ case CCM_CCGR0:
338
+ return "CCGR0";
339
+ case CCM_CCGR1:
340
+ return "CCGR1";
341
+ case CCM_CCGR2:
342
+ return "CCGR2";
343
+ case CCM_CCGR3:
344
+ return "CCGR3";
345
+ case CCM_CCGR4:
346
+ return "CCGR4";
347
+ case CCM_CCGR5:
348
+ return "CCGR5";
349
+ case CCM_CCGR6:
350
+ return "CCGR6";
351
+ case CCM_CMEOR:
352
+ return "CMEOR";
168
+ default:
353
+ default:
169
+ qemu_log_mask(LOG_GUEST_ERROR,
354
+ sprintf(unknown, "%d ?", reg);
170
+ "bcm2835_rng_read: Bad offset %x\n",
355
+ return unknown;
171
+ (int)offset);
172
+ res = 0;
173
+ break;
174
+ }
356
+ }
175
+
357
+}
176
+ return res;
358
+
177
+}
359
+static const char *imx6ul_analog_reg_name(uint32_t reg)
178
+
360
+{
179
+static void bcm2835_rng_write(void *opaque, hwaddr offset,
361
+ static char unknown[20];
180
+ uint64_t value, unsigned size)
362
+
181
+{
363
+ switch (reg) {
182
+ BCM2835RngState *s = (BCM2835RngState *)opaque;
364
+ case CCM_ANALOG_PLL_ARM:
183
+
365
+ return "PLL_ARM";
184
+ assert(size == 4);
366
+ case CCM_ANALOG_PLL_ARM_SET:
185
+
367
+ return "PLL_ARM_SET";
186
+ switch (offset) {
368
+ case CCM_ANALOG_PLL_ARM_CLR:
187
+ case 0x0: /* rng_ctrl */
369
+ return "PLL_ARM_CLR";
188
+ s->rng_ctrl = value;
370
+ case CCM_ANALOG_PLL_ARM_TOG:
189
+ break;
371
+ return "PLL_ARM_TOG";
190
+ case 0x4: /* rng_status */
372
+ case CCM_ANALOG_PLL_USB1:
191
+ /* we shouldn't let the guest write to bits [31..20] */
373
+ return "PLL_USB1";
192
+ s->rng_status &= ~0xFFFFF; /* clear 20 lower bits */
374
+ case CCM_ANALOG_PLL_USB1_SET:
193
+ s->rng_status |= value & 0xFFFFF; /* set them to new value */
375
+ return "PLL_USB1_SET";
194
+ break;
376
+ case CCM_ANALOG_PLL_USB1_CLR:
195
+
377
+ return "PLL_USB1_CLR";
378
+ case CCM_ANALOG_PLL_USB1_TOG:
379
+ return "PLL_USB1_TOG";
380
+ case CCM_ANALOG_PLL_USB2:
381
+ return "PLL_USB2";
382
+ case CCM_ANALOG_PLL_USB2_SET:
383
+ return "PLL_USB2_SET";
384
+ case CCM_ANALOG_PLL_USB2_CLR:
385
+ return "PLL_USB2_CLR";
386
+ case CCM_ANALOG_PLL_USB2_TOG:
387
+ return "PLL_USB2_TOG";
388
+ case CCM_ANALOG_PLL_SYS:
389
+ return "PLL_SYS";
390
+ case CCM_ANALOG_PLL_SYS_SET:
391
+ return "PLL_SYS_SET";
392
+ case CCM_ANALOG_PLL_SYS_CLR:
393
+ return "PLL_SYS_CLR";
394
+ case CCM_ANALOG_PLL_SYS_TOG:
395
+ return "PLL_SYS_TOG";
396
+ case CCM_ANALOG_PLL_SYS_SS:
397
+ return "PLL_SYS_SS";
398
+ case CCM_ANALOG_PLL_SYS_NUM:
399
+ return "PLL_SYS_NUM";
400
+ case CCM_ANALOG_PLL_SYS_DENOM:
401
+ return "PLL_SYS_DENOM";
402
+ case CCM_ANALOG_PLL_AUDIO:
403
+ return "PLL_AUDIO";
404
+ case CCM_ANALOG_PLL_AUDIO_SET:
405
+ return "PLL_AUDIO_SET";
406
+ case CCM_ANALOG_PLL_AUDIO_CLR:
407
+ return "PLL_AUDIO_CLR";
408
+ case CCM_ANALOG_PLL_AUDIO_TOG:
409
+ return "PLL_AUDIO_TOG";
410
+ case CCM_ANALOG_PLL_AUDIO_NUM:
411
+ return "PLL_AUDIO_NUM";
412
+ case CCM_ANALOG_PLL_AUDIO_DENOM:
413
+ return "PLL_AUDIO_DENOM";
414
+ case CCM_ANALOG_PLL_VIDEO:
415
+ return "PLL_VIDEO";
416
+ case CCM_ANALOG_PLL_VIDEO_SET:
417
+ return "PLL_VIDEO_SET";
418
+ case CCM_ANALOG_PLL_VIDEO_CLR:
419
+ return "PLL_VIDEO_CLR";
420
+ case CCM_ANALOG_PLL_VIDEO_TOG:
421
+ return "PLL_VIDEO_TOG";
422
+ case CCM_ANALOG_PLL_VIDEO_NUM:
423
+ return "PLL_VIDEO_NUM";
424
+ case CCM_ANALOG_PLL_VIDEO_DENOM:
425
+ return "PLL_VIDEO_DENOM";
426
+ case CCM_ANALOG_PLL_ENET:
427
+ return "PLL_ENET";
428
+ case CCM_ANALOG_PLL_ENET_SET:
429
+ return "PLL_ENET_SET";
430
+ case CCM_ANALOG_PLL_ENET_CLR:
431
+ return "PLL_ENET_CLR";
432
+ case CCM_ANALOG_PLL_ENET_TOG:
433
+ return "PLL_ENET_TOG";
434
+ case CCM_ANALOG_PFD_480:
435
+ return "PFD_480";
436
+ case CCM_ANALOG_PFD_480_SET:
437
+ return "PFD_480_SET";
438
+ case CCM_ANALOG_PFD_480_CLR:
439
+ return "PFD_480_CLR";
440
+ case CCM_ANALOG_PFD_480_TOG:
441
+ return "PFD_480_TOG";
442
+ case CCM_ANALOG_PFD_528:
443
+ return "PFD_528";
444
+ case CCM_ANALOG_PFD_528_SET:
445
+ return "PFD_528_SET";
446
+ case CCM_ANALOG_PFD_528_CLR:
447
+ return "PFD_528_CLR";
448
+ case CCM_ANALOG_PFD_528_TOG:
449
+ return "PFD_528_TOG";
450
+ case CCM_ANALOG_MISC0:
451
+ return "MISC0";
452
+ case CCM_ANALOG_MISC0_SET:
453
+ return "MISC0_SET";
454
+ case CCM_ANALOG_MISC0_CLR:
455
+ return "MISC0_CLR";
456
+ case CCM_ANALOG_MISC0_TOG:
457
+ return "MISC0_TOG";
458
+ case CCM_ANALOG_MISC2:
459
+ return "MISC2";
460
+ case CCM_ANALOG_MISC2_SET:
461
+ return "MISC2_SET";
462
+ case CCM_ANALOG_MISC2_CLR:
463
+ return "MISC2_CLR";
464
+ case CCM_ANALOG_MISC2_TOG:
465
+ return "MISC2_TOG";
466
+ case PMU_REG_1P1:
467
+ return "PMU_REG_1P1";
468
+ case PMU_REG_3P0:
469
+ return "PMU_REG_3P0";
470
+ case PMU_REG_2P5:
471
+ return "PMU_REG_2P5";
472
+ case PMU_REG_CORE:
473
+ return "PMU_REG_CORE";
474
+ case PMU_MISC1:
475
+ return "PMU_MISC1";
476
+ case PMU_MISC1_SET:
477
+ return "PMU_MISC1_SET";
478
+ case PMU_MISC1_CLR:
479
+ return "PMU_MISC1_CLR";
480
+ case PMU_MISC1_TOG:
481
+ return "PMU_MISC1_TOG";
482
+ case USB_ANALOG_DIGPROG:
483
+ return "USB_ANALOG_DIGPROG";
196
+ default:
484
+ default:
197
+ qemu_log_mask(LOG_GUEST_ERROR,
485
+ sprintf(unknown, "%d ?", reg);
198
+ "bcm2835_rng_write: Bad offset %x\n",
486
+ return unknown;
199
+ (int)offset);
200
+ break;
201
+ }
487
+ }
202
+}
488
+}
203
+
489
+
204
+static const MemoryRegionOps bcm2835_rng_ops = {
490
+#define CKIH_FREQ 24000000 /* 24MHz crystal input */
205
+ .read = bcm2835_rng_read,
491
+
206
+ .write = bcm2835_rng_write,
492
+static const VMStateDescription vmstate_imx6ul_ccm = {
207
+ .endianness = DEVICE_NATIVE_ENDIAN,
493
+ .name = TYPE_IMX6UL_CCM,
208
+};
209
+
210
+static const VMStateDescription vmstate_bcm2835_rng = {
211
+ .name = TYPE_BCM2835_RNG,
212
+ .version_id = 1,
494
+ .version_id = 1,
213
+ .minimum_version_id = 1,
495
+ .minimum_version_id = 1,
214
+ .fields = (VMStateField[]) {
496
+ .fields = (VMStateField[]) {
215
+ VMSTATE_UINT32(rng_ctrl, BCM2835RngState),
497
+ VMSTATE_UINT32_ARRAY(ccm, IMX6ULCCMState, CCM_MAX),
216
+ VMSTATE_UINT32(rng_status, BCM2835RngState),
498
+ VMSTATE_UINT32_ARRAY(analog, IMX6ULCCMState, CCM_ANALOG_MAX),
217
+ VMSTATE_END_OF_LIST()
499
+ VMSTATE_END_OF_LIST()
500
+ },
501
+};
502
+
503
+static uint64_t imx6ul_analog_get_osc_clk(IMX6ULCCMState *dev)
504
+{
505
+ uint64_t freq = CKIH_FREQ;
506
+
507
+ trace_ccm_freq((uint32_t)freq);
508
+
509
+ return freq;
510
+}
511
+
512
+static uint64_t imx6ul_analog_get_pll2_clk(IMX6ULCCMState *dev)
513
+{
514
+ uint64_t freq = imx6ul_analog_get_osc_clk(dev);
515
+
516
+ if (FIELD_EX32(dev->analog[CCM_ANALOG_PLL_SYS],
517
+ ANALOG_PLL_SYS, DIV_SELECT)) {
518
+ freq *= 22;
519
+ } else {
520
+ freq *= 20;
218
+ }
521
+ }
522
+
523
+ trace_ccm_freq((uint32_t)freq);
524
+
525
+ return freq;
526
+}
527
+
528
+static uint64_t imx6ul_analog_get_pll3_clk(IMX6ULCCMState *dev)
529
+{
530
+ uint64_t freq = imx6ul_analog_get_osc_clk(dev) * 20;
531
+
532
+ trace_ccm_freq((uint32_t)freq);
533
+
534
+ return freq;
535
+}
536
+
537
+static uint64_t imx6ul_analog_get_pll2_pfd0_clk(IMX6ULCCMState *dev)
538
+{
539
+ uint64_t freq = 0;
540
+
541
+ freq = imx6ul_analog_get_pll2_clk(dev) * 18
542
+ / FIELD_EX32(dev->analog[CCM_ANALOG_PFD_528],
543
+ ANALOG_PFD_528, PFD0_FRAC);
544
+
545
+ trace_ccm_freq((uint32_t)freq);
546
+
547
+ return freq;
548
+}
549
+
550
+static uint64_t imx6ul_analog_get_pll2_pfd2_clk(IMX6ULCCMState *dev)
551
+{
552
+ uint64_t freq = 0;
553
+
554
+ freq = imx6ul_analog_get_pll2_clk(dev) * 18
555
+ / FIELD_EX32(dev->analog[CCM_ANALOG_PFD_528],
556
+ ANALOG_PFD_528, PFD2_FRAC);
557
+
558
+ trace_ccm_freq((uint32_t)freq);
559
+
560
+ return freq;
561
+}
562
+
563
+static uint64_t imx6ul_analog_pll2_bypass_clk(IMX6ULCCMState *dev)
564
+{
565
+ uint64_t freq = 0;
566
+
567
+ trace_ccm_freq((uint32_t)freq);
568
+
569
+ return freq;
570
+}
571
+
572
+static uint64_t imx6ul_ccm_get_periph_clk2_sel_clk(IMX6ULCCMState *dev)
573
+{
574
+ uint64_t freq = 0;
575
+
576
+ switch (FIELD_EX32(dev->ccm[CCM_CBCMR], CBCMR, PERIPH_CLK2_SEL)) {
577
+ case 0:
578
+ freq = imx6ul_analog_get_pll3_clk(dev);
579
+ break;
580
+ case 1:
581
+ freq = imx6ul_analog_get_osc_clk(dev);
582
+ break;
583
+ case 2:
584
+ freq = imx6ul_analog_pll2_bypass_clk(dev);
585
+ break;
586
+ case 3:
587
+ /* We should never get there as 3 is a reserved value */
588
+ qemu_log_mask(LOG_GUEST_ERROR,
589
+ "[%s]%s: unsupported PERIPH_CLK2_SEL value 3\n",
590
+ TYPE_IMX6UL_CCM, __func__);
591
+ /* freq is set to 0 as we don't know what it should be */
592
+ break;
593
+ default:
594
+ g_assert_not_reached();
595
+ }
596
+
597
+ trace_ccm_freq((uint32_t)freq);
598
+
599
+ return freq;
600
+}
601
+
602
+static uint64_t imx6ul_ccm_get_periph_clk_sel_clk(IMX6ULCCMState *dev)
603
+{
604
+ uint64_t freq = 0;
605
+
606
+ switch (FIELD_EX32(dev->ccm[CCM_CBCMR], CBCMR, PRE_PERIPH_CLK_SEL)) {
607
+ case 0:
608
+ freq = imx6ul_analog_get_pll2_clk(dev);
609
+ break;
610
+ case 1:
611
+ freq = imx6ul_analog_get_pll2_pfd2_clk(dev);
612
+ break;
613
+ case 2:
614
+ freq = imx6ul_analog_get_pll2_pfd0_clk(dev);
615
+ break;
616
+ case 3:
617
+ freq = imx6ul_analog_get_pll2_pfd2_clk(dev) / 2;
618
+ break;
619
+ default:
620
+ g_assert_not_reached();
621
+ }
622
+
623
+ trace_ccm_freq((uint32_t)freq);
624
+
625
+ return freq;
626
+}
627
+
628
+static uint64_t imx6ul_ccm_get_periph_clk2_clk(IMX6ULCCMState *dev)
629
+{
630
+ uint64_t freq = 0;
631
+
632
+ freq = imx6ul_ccm_get_periph_clk2_sel_clk(dev)
633
+ / (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, PERIPH_CLK2_PODF));
634
+
635
+ trace_ccm_freq((uint32_t)freq);
636
+
637
+ return freq;
638
+}
639
+
640
+static uint64_t imx6ul_ccm_get_periph_sel_clk(IMX6ULCCMState *dev)
641
+{
642
+ uint64_t freq = 0;
643
+
644
+ switch (FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, PERIPH_CLK_SEL)) {
645
+ case 0:
646
+ freq = imx6ul_ccm_get_periph_clk_sel_clk(dev);
647
+ break;
648
+ case 1:
649
+ freq = imx6ul_ccm_get_periph_clk2_clk(dev);
650
+ break;
651
+ default:
652
+ g_assert_not_reached();
653
+ }
654
+
655
+ trace_ccm_freq((uint32_t)freq);
656
+
657
+ return freq;
658
+}
659
+
660
+static uint64_t imx6ul_ccm_get_ahb_clk(IMX6ULCCMState *dev)
661
+{
662
+ uint64_t freq = 0;
663
+
664
+ freq = imx6ul_ccm_get_periph_sel_clk(dev)
665
+ / (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, AHB_PODF));
666
+
667
+ trace_ccm_freq((uint32_t)freq);
668
+
669
+ return freq;
670
+}
671
+
672
+static uint64_t imx6ul_ccm_get_ipg_clk(IMX6ULCCMState *dev)
673
+{
674
+ uint64_t freq = 0;
675
+
676
+ freq = imx6ul_ccm_get_ahb_clk(dev)
677
+ / (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, IPG_PODF));
678
+
679
+ trace_ccm_freq((uint32_t)freq);
680
+
681
+ return freq;
682
+}
683
+
684
+static uint64_t imx6ul_ccm_get_per_sel_clk(IMX6ULCCMState *dev)
685
+{
686
+ uint64_t freq = 0;
687
+
688
+ switch (FIELD_EX32(dev->ccm[CCM_CSCMR1], CSCMR1, PERCLK_CLK_SEL)) {
689
+ case 0:
690
+ freq = imx6ul_ccm_get_ipg_clk(dev);
691
+ break;
692
+ case 1:
693
+ freq = imx6ul_analog_get_osc_clk(dev);
694
+ break;
695
+ default:
696
+ g_assert_not_reached();
697
+ }
698
+
699
+ trace_ccm_freq((uint32_t)freq);
700
+
701
+ return freq;
702
+}
703
+
704
+static uint64_t imx6ul_ccm_get_per_clk(IMX6ULCCMState *dev)
705
+{
706
+ uint64_t freq = 0;
707
+
708
+ freq = imx6ul_ccm_get_per_sel_clk(dev)
709
+ / (1 + FIELD_EX32(dev->ccm[CCM_CSCMR1], CSCMR1, PERCLK_PODF));
710
+
711
+ trace_ccm_freq((uint32_t)freq);
712
+
713
+ return freq;
714
+}
715
+
716
+static uint32_t imx6ul_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
717
+{
718
+ uint32_t freq = 0;
719
+ IMX6ULCCMState *s = IMX6UL_CCM(dev);
720
+
721
+ switch (clock) {
722
+ case CLK_NONE:
723
+ break;
724
+ case CLK_IPG:
725
+ freq = imx6ul_ccm_get_ipg_clk(s);
726
+ break;
727
+ case CLK_IPG_HIGH:
728
+ freq = imx6ul_ccm_get_per_clk(s);
729
+ break;
730
+ case CLK_32k:
731
+ freq = CKIL_FREQ;
732
+ break;
733
+ case CLK_HIGH:
734
+ freq = CKIH_FREQ;
735
+ break;
736
+ case CLK_HIGH_DIV:
737
+ freq = CKIH_FREQ / 8;
738
+ break;
739
+ default:
740
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n",
741
+ TYPE_IMX6UL_CCM, __func__, clock);
742
+ break;
743
+ }
744
+
745
+ trace_ccm_clock_freq(clock, freq);
746
+
747
+ return freq;
748
+}
749
+
750
+static void imx6ul_ccm_reset(DeviceState *dev)
751
+{
752
+ IMX6ULCCMState *s = IMX6UL_CCM(dev);
753
+
754
+ trace_ccm_entry();
755
+
756
+ s->ccm[CCM_CCR] = 0x0401167F;
757
+ s->ccm[CCM_CCDR] = 0x00000000;
758
+ s->ccm[CCM_CSR] = 0x00000010;
759
+ s->ccm[CCM_CCSR] = 0x00000100;
760
+ s->ccm[CCM_CACRR] = 0x00000000;
761
+ s->ccm[CCM_CBCDR] = 0x00018D00;
762
+ s->ccm[CCM_CBCMR] = 0x24860324;
763
+ s->ccm[CCM_CSCMR1] = 0x04900080;
764
+ s->ccm[CCM_CSCMR2] = 0x03192F06;
765
+ s->ccm[CCM_CSCDR1] = 0x00490B00;
766
+ s->ccm[CCM_CS1CDR] = 0x0EC102C1;
767
+ s->ccm[CCM_CS2CDR] = 0x000336C1;
768
+ s->ccm[CCM_CDCDR] = 0x33F71F92;
769
+ s->ccm[CCM_CHSCCDR] = 0x000248A4;
770
+ s->ccm[CCM_CSCDR2] = 0x00029B48;
771
+ s->ccm[CCM_CSCDR3] = 0x00014841;
772
+ s->ccm[CCM_CDHIPR] = 0x00000000;
773
+ s->ccm[CCM_CTOR] = 0x00000000;
774
+ s->ccm[CCM_CLPCR] = 0x00000079;
775
+ s->ccm[CCM_CISR] = 0x00000000;
776
+ s->ccm[CCM_CIMR] = 0xFFFFFFFF;
777
+ s->ccm[CCM_CCOSR] = 0x000A0001;
778
+ s->ccm[CCM_CGPR] = 0x0000FE62;
779
+ s->ccm[CCM_CCGR0] = 0xFFFFFFFF;
780
+ s->ccm[CCM_CCGR1] = 0xFFFFFFFF;
781
+ s->ccm[CCM_CCGR2] = 0xFC3FFFFF;
782
+ s->ccm[CCM_CCGR3] = 0xFFFFFFFF;
783
+ s->ccm[CCM_CCGR4] = 0xFFFFFFFF;
784
+ s->ccm[CCM_CCGR5] = 0xFFFFFFFF;
785
+ s->ccm[CCM_CCGR6] = 0xFFFFFFFF;
786
+ s->ccm[CCM_CMEOR] = 0xFFFFFFFF;
787
+
788
+ s->analog[CCM_ANALOG_PLL_ARM] = 0x00013063;
789
+ s->analog[CCM_ANALOG_PLL_USB1] = 0x00012000;
790
+ s->analog[CCM_ANALOG_PLL_USB2] = 0x00012000;
791
+ s->analog[CCM_ANALOG_PLL_SYS] = 0x00013001;
792
+ s->analog[CCM_ANALOG_PLL_SYS_SS] = 0x00000000;
793
+ s->analog[CCM_ANALOG_PLL_SYS_NUM] = 0x00000000;
794
+ s->analog[CCM_ANALOG_PLL_SYS_DENOM] = 0x00000012;
795
+ s->analog[CCM_ANALOG_PLL_AUDIO] = 0x00011006;
796
+ s->analog[CCM_ANALOG_PLL_AUDIO_NUM] = 0x05F5E100;
797
+ s->analog[CCM_ANALOG_PLL_AUDIO_DENOM] = 0x2964619C;
798
+ s->analog[CCM_ANALOG_PLL_VIDEO] = 0x0001100C;
799
+ s->analog[CCM_ANALOG_PLL_VIDEO_NUM] = 0x05F5E100;
800
+ s->analog[CCM_ANALOG_PLL_VIDEO_DENOM] = 0x10A24447;
801
+ s->analog[CCM_ANALOG_PLL_ENET] = 0x00011001;
802
+ s->analog[CCM_ANALOG_PFD_480] = 0x1311100C;
803
+ s->analog[CCM_ANALOG_PFD_528] = 0x1018101B;
804
+
805
+ s->analog[PMU_REG_1P1] = 0x00001073;
806
+ s->analog[PMU_REG_3P0] = 0x00000F74;
807
+ s->analog[PMU_REG_2P5] = 0x00001073;
808
+ s->analog[PMU_REG_CORE] = 0x00482012;
809
+ s->analog[PMU_MISC0] = 0x04000000;
810
+ s->analog[PMU_MISC1] = 0x00000000;
811
+ s->analog[PMU_MISC2] = 0x00272727;
812
+ s->analog[PMU_LOWPWR_CTRL] = 0x00004009;
813
+
814
+ s->analog[USB_ANALOG_USB1_VBUS_DETECT] = 0x01000004;
815
+ s->analog[USB_ANALOG_USB1_CHRG_DETECT] = 0x00000000;
816
+ s->analog[USB_ANALOG_USB1_VBUS_DETECT_STAT] = 0x00000000;
817
+ s->analog[USB_ANALOG_USB1_CHRG_DETECT_STAT] = 0x00000000;
818
+ s->analog[USB_ANALOG_USB1_MISC] = 0x00000002;
819
+ s->analog[USB_ANALOG_USB2_VBUS_DETECT] = 0x01000004;
820
+ s->analog[USB_ANALOG_USB2_CHRG_DETECT] = 0x00000000;
821
+ s->analog[USB_ANALOG_USB2_MISC] = 0x00000002;
822
+ s->analog[USB_ANALOG_DIGPROG] = 0x00640000;
823
+
824
+ /* all PLLs need to be locked */
825
+ s->analog[CCM_ANALOG_PLL_ARM] |= CCM_ANALOG_PLL_LOCK;
826
+ s->analog[CCM_ANALOG_PLL_USB1] |= CCM_ANALOG_PLL_LOCK;
827
+ s->analog[CCM_ANALOG_PLL_USB2] |= CCM_ANALOG_PLL_LOCK;
828
+ s->analog[CCM_ANALOG_PLL_SYS] |= CCM_ANALOG_PLL_LOCK;
829
+ s->analog[CCM_ANALOG_PLL_AUDIO] |= CCM_ANALOG_PLL_LOCK;
830
+ s->analog[CCM_ANALOG_PLL_VIDEO] |= CCM_ANALOG_PLL_LOCK;
831
+ s->analog[CCM_ANALOG_PLL_ENET] |= CCM_ANALOG_PLL_LOCK;
832
+
833
+ s->analog[TEMPMON_TEMPSENSE0] = 0x00000001;
834
+ s->analog[TEMPMON_TEMPSENSE1] = 0x00000001;
835
+ s->analog[TEMPMON_TEMPSENSE2] = 0x00000000;
836
+}
837
+
838
+static uint64_t imx6ul_ccm_read(void *opaque, hwaddr offset, unsigned size)
839
+{
840
+ uint32_t value = 0;
841
+ uint32_t index = offset >> 2;
842
+ IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
843
+
844
+ assert(index < CCM_MAX);
845
+
846
+ value = s->ccm[index];
847
+
848
+ trace_ccm_read_reg(imx6ul_ccm_reg_name(index), (uint32_t)value);
849
+
850
+ return (uint64_t)value;
851
+}
852
+
853
+static void imx6ul_ccm_write(void *opaque, hwaddr offset, uint64_t value,
854
+ unsigned size)
855
+{
856
+ uint32_t index = offset >> 2;
857
+ IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
858
+
859
+ assert(index < CCM_MAX);
860
+
861
+ trace_ccm_write_reg(imx6ul_ccm_reg_name(index), (uint32_t)value);
862
+
863
+ /*
864
+ * We will do a better implementation later. In particular some bits
865
+ * cannot be written to.
866
+ */
867
+ s->ccm[index] = (uint32_t)value;
868
+}
869
+
870
+static uint64_t imx6ul_analog_read(void *opaque, hwaddr offset, unsigned size)
871
+{
872
+ uint32_t value;
873
+ uint32_t index = offset >> 2;
874
+ IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
875
+
876
+ assert(index < CCM_ANALOG_MAX);
877
+
878
+ switch (index) {
879
+ case CCM_ANALOG_PLL_ARM_SET:
880
+ case CCM_ANALOG_PLL_USB1_SET:
881
+ case CCM_ANALOG_PLL_USB2_SET:
882
+ case CCM_ANALOG_PLL_SYS_SET:
883
+ case CCM_ANALOG_PLL_AUDIO_SET:
884
+ case CCM_ANALOG_PLL_VIDEO_SET:
885
+ case CCM_ANALOG_PLL_ENET_SET:
886
+ case CCM_ANALOG_PFD_480_SET:
887
+ case CCM_ANALOG_PFD_528_SET:
888
+ case CCM_ANALOG_MISC0_SET:
889
+ case PMU_MISC1_SET:
890
+ case CCM_ANALOG_MISC2_SET:
891
+ case USB_ANALOG_USB1_VBUS_DETECT_SET:
892
+ case USB_ANALOG_USB1_CHRG_DETECT_SET:
893
+ case USB_ANALOG_USB1_MISC_SET:
894
+ case USB_ANALOG_USB2_VBUS_DETECT_SET:
895
+ case USB_ANALOG_USB2_CHRG_DETECT_SET:
896
+ case USB_ANALOG_USB2_MISC_SET:
897
+ case TEMPMON_TEMPSENSE0_SET:
898
+ case TEMPMON_TEMPSENSE1_SET:
899
+ case TEMPMON_TEMPSENSE2_SET:
900
+ /*
901
+ * All REG_NAME_SET register access are in fact targeting
902
+ * the REG_NAME register.
903
+ */
904
+ value = s->analog[index - 1];
905
+ break;
906
+ case CCM_ANALOG_PLL_ARM_CLR:
907
+ case CCM_ANALOG_PLL_USB1_CLR:
908
+ case CCM_ANALOG_PLL_USB2_CLR:
909
+ case CCM_ANALOG_PLL_SYS_CLR:
910
+ case CCM_ANALOG_PLL_AUDIO_CLR:
911
+ case CCM_ANALOG_PLL_VIDEO_CLR:
912
+ case CCM_ANALOG_PLL_ENET_CLR:
913
+ case CCM_ANALOG_PFD_480_CLR:
914
+ case CCM_ANALOG_PFD_528_CLR:
915
+ case CCM_ANALOG_MISC0_CLR:
916
+ case PMU_MISC1_CLR:
917
+ case CCM_ANALOG_MISC2_CLR:
918
+ case USB_ANALOG_USB1_VBUS_DETECT_CLR:
919
+ case USB_ANALOG_USB1_CHRG_DETECT_CLR:
920
+ case USB_ANALOG_USB1_MISC_CLR:
921
+ case USB_ANALOG_USB2_VBUS_DETECT_CLR:
922
+ case USB_ANALOG_USB2_CHRG_DETECT_CLR:
923
+ case USB_ANALOG_USB2_MISC_CLR:
924
+ case TEMPMON_TEMPSENSE0_CLR:
925
+ case TEMPMON_TEMPSENSE1_CLR:
926
+ case TEMPMON_TEMPSENSE2_CLR:
927
+ /*
928
+ * All REG_NAME_CLR register access are in fact targeting
929
+ * the REG_NAME register.
930
+ */
931
+ value = s->analog[index - 2];
932
+ break;
933
+ case CCM_ANALOG_PLL_ARM_TOG:
934
+ case CCM_ANALOG_PLL_USB1_TOG:
935
+ case CCM_ANALOG_PLL_USB2_TOG:
936
+ case CCM_ANALOG_PLL_SYS_TOG:
937
+ case CCM_ANALOG_PLL_AUDIO_TOG:
938
+ case CCM_ANALOG_PLL_VIDEO_TOG:
939
+ case CCM_ANALOG_PLL_ENET_TOG:
940
+ case CCM_ANALOG_PFD_480_TOG:
941
+ case CCM_ANALOG_PFD_528_TOG:
942
+ case CCM_ANALOG_MISC0_TOG:
943
+ case PMU_MISC1_TOG:
944
+ case CCM_ANALOG_MISC2_TOG:
945
+ case USB_ANALOG_USB1_VBUS_DETECT_TOG:
946
+ case USB_ANALOG_USB1_CHRG_DETECT_TOG:
947
+ case USB_ANALOG_USB1_MISC_TOG:
948
+ case USB_ANALOG_USB2_VBUS_DETECT_TOG:
949
+ case USB_ANALOG_USB2_CHRG_DETECT_TOG:
950
+ case USB_ANALOG_USB2_MISC_TOG:
951
+ case TEMPMON_TEMPSENSE0_TOG:
952
+ case TEMPMON_TEMPSENSE1_TOG:
953
+ case TEMPMON_TEMPSENSE2_TOG:
954
+ /*
955
+ * All REG_NAME_TOG register access are in fact targeting
956
+ * the REG_NAME register.
957
+ */
958
+ value = s->analog[index - 3];
959
+ break;
960
+ default:
961
+ value = s->analog[index];
962
+ break;
963
+ }
964
+
965
+ trace_ccm_read_reg(imx6ul_analog_reg_name(index), (uint32_t)value);
966
+
967
+ return (uint64_t)value;
968
+}
969
+
970
+static void imx6ul_analog_write(void *opaque, hwaddr offset, uint64_t value,
971
+ unsigned size)
972
+{
973
+ uint32_t index = offset >> 2;
974
+ IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
975
+
976
+ assert(index < CCM_ANALOG_MAX);
977
+
978
+ trace_ccm_write_reg(imx6ul_analog_reg_name(index), (uint32_t)value);
979
+
980
+ switch (index) {
981
+ case CCM_ANALOG_PLL_ARM_SET:
982
+ case CCM_ANALOG_PLL_USB1_SET:
983
+ case CCM_ANALOG_PLL_USB2_SET:
984
+ case CCM_ANALOG_PLL_SYS_SET:
985
+ case CCM_ANALOG_PLL_AUDIO_SET:
986
+ case CCM_ANALOG_PLL_VIDEO_SET:
987
+ case CCM_ANALOG_PLL_ENET_SET:
988
+ case CCM_ANALOG_PFD_480_SET:
989
+ case CCM_ANALOG_PFD_528_SET:
990
+ case CCM_ANALOG_MISC0_SET:
991
+ case PMU_MISC1_SET:
992
+ case CCM_ANALOG_MISC2_SET:
993
+ case USB_ANALOG_USB1_VBUS_DETECT_SET:
994
+ case USB_ANALOG_USB1_CHRG_DETECT_SET:
995
+ case USB_ANALOG_USB1_MISC_SET:
996
+ case USB_ANALOG_USB2_VBUS_DETECT_SET:
997
+ case USB_ANALOG_USB2_CHRG_DETECT_SET:
998
+ case USB_ANALOG_USB2_MISC_SET:
999
+ /*
1000
+ * All REG_NAME_SET register access are in fact targeting
1001
+ * the REG_NAME register. So we change the value of the
1002
+ * REG_NAME register, setting bits passed in the value.
1003
+ */
1004
+ s->analog[index - 1] |= value;
1005
+ break;
1006
+ case CCM_ANALOG_PLL_ARM_CLR:
1007
+ case CCM_ANALOG_PLL_USB1_CLR:
1008
+ case CCM_ANALOG_PLL_USB2_CLR:
1009
+ case CCM_ANALOG_PLL_SYS_CLR:
1010
+ case CCM_ANALOG_PLL_AUDIO_CLR:
1011
+ case CCM_ANALOG_PLL_VIDEO_CLR:
1012
+ case CCM_ANALOG_PLL_ENET_CLR:
1013
+ case CCM_ANALOG_PFD_480_CLR:
1014
+ case CCM_ANALOG_PFD_528_CLR:
1015
+ case CCM_ANALOG_MISC0_CLR:
1016
+ case PMU_MISC1_CLR:
1017
+ case CCM_ANALOG_MISC2_CLR:
1018
+ case USB_ANALOG_USB1_VBUS_DETECT_CLR:
1019
+ case USB_ANALOG_USB1_CHRG_DETECT_CLR:
1020
+ case USB_ANALOG_USB1_MISC_CLR:
1021
+ case USB_ANALOG_USB2_VBUS_DETECT_CLR:
1022
+ case USB_ANALOG_USB2_CHRG_DETECT_CLR:
1023
+ case USB_ANALOG_USB2_MISC_CLR:
1024
+ /*
1025
+ * All REG_NAME_CLR register access are in fact targeting
1026
+ * the REG_NAME register. So we change the value of the
1027
+ * REG_NAME register, unsetting bits passed in the value.
1028
+ */
1029
+ s->analog[index - 2] &= ~value;
1030
+ break;
1031
+ case CCM_ANALOG_PLL_ARM_TOG:
1032
+ case CCM_ANALOG_PLL_USB1_TOG:
1033
+ case CCM_ANALOG_PLL_USB2_TOG:
1034
+ case CCM_ANALOG_PLL_SYS_TOG:
1035
+ case CCM_ANALOG_PLL_AUDIO_TOG:
1036
+ case CCM_ANALOG_PLL_VIDEO_TOG:
1037
+ case CCM_ANALOG_PLL_ENET_TOG:
1038
+ case CCM_ANALOG_PFD_480_TOG:
1039
+ case CCM_ANALOG_PFD_528_TOG:
1040
+ case CCM_ANALOG_MISC0_TOG:
1041
+ case PMU_MISC1_TOG:
1042
+ case CCM_ANALOG_MISC2_TOG:
1043
+ case USB_ANALOG_USB1_VBUS_DETECT_TOG:
1044
+ case USB_ANALOG_USB1_CHRG_DETECT_TOG:
1045
+ case USB_ANALOG_USB1_MISC_TOG:
1046
+ case USB_ANALOG_USB2_VBUS_DETECT_TOG:
1047
+ case USB_ANALOG_USB2_CHRG_DETECT_TOG:
1048
+ case USB_ANALOG_USB2_MISC_TOG:
1049
+ /*
1050
+ * All REG_NAME_TOG register access are in fact targeting
1051
+ * the REG_NAME register. So we change the value of the
1052
+ * REG_NAME register, toggling bits passed in the value.
1053
+ */
1054
+ s->analog[index - 3] ^= value;
1055
+ break;
1056
+ default:
1057
+ /*
1058
+ * We will do a better implementation later. In particular some bits
1059
+ * cannot be written to.
1060
+ */
1061
+ s->analog[index] = value;
1062
+ break;
1063
+ }
1064
+}
1065
+
1066
+static const struct MemoryRegionOps imx6ul_ccm_ops = {
1067
+ .read = imx6ul_ccm_read,
1068
+ .write = imx6ul_ccm_write,
1069
+ .endianness = DEVICE_NATIVE_ENDIAN,
1070
+ .valid = {
1071
+ /*
1072
+ * Our device would not work correctly if the guest was doing
1073
+ * unaligned access. This might not be a limitation on the real
1074
+ * device but in practice there is no reason for a guest to access
1075
+ * this device unaligned.
1076
+ */
1077
+ .min_access_size = 4,
1078
+ .max_access_size = 4,
1079
+ .unaligned = false,
1080
+ },
219
+};
1081
+};
220
+
1082
+
221
+static void bcm2835_rng_init(Object *obj)
1083
+static const struct MemoryRegionOps imx6ul_analog_ops = {
222
+{
1084
+ .read = imx6ul_analog_read,
223
+ BCM2835RngState *s = BCM2835_RNG(obj);
1085
+ .write = imx6ul_analog_write,
224
+
1086
+ .endianness = DEVICE_NATIVE_ENDIAN,
225
+ memory_region_init_io(&s->iomem, obj, &bcm2835_rng_ops, s,
1087
+ .valid = {
226
+ TYPE_BCM2835_RNG, 0x10);
1088
+ /*
227
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
1089
+ * Our device would not work correctly if the guest was doing
228
+}
1090
+ * unaligned access. This might not be a limitation on the real
229
+
1091
+ * device but in practice there is no reason for a guest to access
230
+static void bcm2835_rng_reset(DeviceState *dev)
1092
+ * this device unaligned.
231
+{
1093
+ */
232
+ BCM2835RngState *s = BCM2835_RNG(dev);
1094
+ .min_access_size = 4,
233
+
1095
+ .max_access_size = 4,
234
+ s->rng_ctrl = 0;
1096
+ .unaligned = false,
235
+ s->rng_status = 0;
1097
+ },
236
+}
1098
+};
237
+
1099
+
238
+static void bcm2835_rng_class_init(ObjectClass *klass, void *data)
1100
+static void imx6ul_ccm_init(Object *obj)
1101
+{
1102
+ DeviceState *dev = DEVICE(obj);
1103
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
1104
+ IMX6ULCCMState *s = IMX6UL_CCM(obj);
1105
+
1106
+ /* initialize a container for the all memory range */
1107
+ memory_region_init(&s->container, OBJECT(dev), TYPE_IMX6UL_CCM, 0x8000);
1108
+
1109
+ /* We initialize an IO memory region for the CCM part */
1110
+ memory_region_init_io(&s->ioccm, OBJECT(dev), &imx6ul_ccm_ops, s,
1111
+ TYPE_IMX6UL_CCM ".ccm", CCM_MAX * sizeof(uint32_t));
1112
+
1113
+ /* Add the CCM as a subregion at offset 0 */
1114
+ memory_region_add_subregion(&s->container, 0, &s->ioccm);
1115
+
1116
+ /* We initialize an IO memory region for the ANALOG part */
1117
+ memory_region_init_io(&s->ioanalog, OBJECT(dev), &imx6ul_analog_ops, s,
1118
+ TYPE_IMX6UL_CCM ".analog",
1119
+ CCM_ANALOG_MAX * sizeof(uint32_t));
1120
+
1121
+ /* Add the ANALOG as a subregion at offset 0x4000 */
1122
+ memory_region_add_subregion(&s->container, 0x4000, &s->ioanalog);
1123
+
1124
+ sysbus_init_mmio(sd, &s->container);
1125
+}
1126
+
1127
+static void imx6ul_ccm_class_init(ObjectClass *klass, void *data)
239
+{
1128
+{
240
+ DeviceClass *dc = DEVICE_CLASS(klass);
1129
+ DeviceClass *dc = DEVICE_CLASS(klass);
241
+
1130
+ IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
242
+ dc->reset = bcm2835_rng_reset;
1131
+
243
+ dc->vmsd = &vmstate_bcm2835_rng;
1132
+ dc->reset = imx6ul_ccm_reset;
244
+}
1133
+ dc->vmsd = &vmstate_imx6ul_ccm;
245
+
1134
+ dc->desc = "i.MX6UL Clock Control Module";
246
+static TypeInfo bcm2835_rng_info = {
1135
+
247
+ .name = TYPE_BCM2835_RNG,
1136
+ ccm->get_clock_frequency = imx6ul_ccm_get_clock_frequency;
248
+ .parent = TYPE_SYS_BUS_DEVICE,
1137
+}
249
+ .instance_size = sizeof(BCM2835RngState),
1138
+
250
+ .class_init = bcm2835_rng_class_init,
1139
+static const TypeInfo imx6ul_ccm_info = {
251
+ .instance_init = bcm2835_rng_init,
1140
+ .name = TYPE_IMX6UL_CCM,
1141
+ .parent = TYPE_IMX_CCM,
1142
+ .instance_size = sizeof(IMX6ULCCMState),
1143
+ .instance_init = imx6ul_ccm_init,
1144
+ .class_init = imx6ul_ccm_class_init,
252
+};
1145
+};
253
+
1146
+
254
+static void bcm2835_rng_register_types(void)
1147
+static void imx6ul_ccm_register_types(void)
255
+{
1148
+{
256
+ type_register_static(&bcm2835_rng_info);
1149
+ type_register_static(&imx6ul_ccm_info);
257
+}
1150
+}
258
+
1151
+
259
+type_init(bcm2835_rng_register_types)
1152
+type_init(imx6ul_ccm_register_types)
1153
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
1154
index XXXXXXX..XXXXXXX 100644
1155
--- a/hw/misc/trace-events
1156
+++ b/hw/misc/trace-events
1157
@@ -XXX,XX +XXX,XX @@ iotkit_secctl_s_write(uint32_t offset, uint64_t data, unsigned size) "IoTKit Sec
1158
iotkit_secctl_ns_read(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl NS regs read: offset 0x%x data 0x%" PRIx64 " size %u"
1159
iotkit_secctl_ns_write(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl NS regs write: offset 0x%x data 0x%" PRIx64 " size %u"
1160
iotkit_secctl_reset(void) "IoTKit SecCtl: reset"
1161
+
1162
+# hw/misc/imx6ul_ccm.c
1163
+ccm_entry(void) "\n"
1164
+ccm_freq(uint32_t freq) "freq = %d\n"
1165
+ccm_clock_freq(uint32_t clock, uint32_t freq) "(Clock = %d) = %d\n"
1166
+ccm_read_reg(const char *reg_name, uint32_t value) "reg[%s] <= 0x%" PRIx32 "\n"
1167
+ccm_write_reg(const char *reg_name, uint32_t value) "reg[%s] => 0x%" PRIx32 "\n"
260
--
1168
--
261
2.7.4
1169
2.18.0
262
1170
263
1171
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
From: Jean-Christophe Dubois <jcd@tribudubois.net>
2
2
3
This adds the BCM2835 SDHost controller from Arasan.
3
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
4
4
Message-id: 3853ec555d68e7e25d726170833b775796151a07.1532984236.git.jcd@tribudubois.net
5
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
6
Message-id: 20170224164021.9066-2-clement.deschamps@antfield.fr
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
7
---
10
hw/sd/Makefile.objs | 1 +
8
hw/arm/Makefile.objs | 1 +
11
include/hw/sd/bcm2835_sdhost.h | 48 +++++
9
include/hw/arm/fsl-imx6ul.h | 339 ++++++++++++++++++
12
hw/sd/bcm2835_sdhost.c | 429 +++++++++++++++++++++++++++++++++++++++++
10
hw/arm/fsl-imx6ul.c | 617 ++++++++++++++++++++++++++++++++
13
3 files changed, 478 insertions(+)
11
default-configs/arm-softmmu.mak | 1 +
14
create mode 100644 include/hw/sd/bcm2835_sdhost.h
12
4 files changed, 958 insertions(+)
15
create mode 100644 hw/sd/bcm2835_sdhost.c
13
create mode 100644 include/hw/arm/fsl-imx6ul.h
14
create mode 100644 hw/arm/fsl-imx6ul.c
16
15
17
diff --git a/hw/sd/Makefile.objs b/hw/sd/Makefile.objs
16
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/sd/Makefile.objs
18
--- a/hw/arm/Makefile.objs
20
+++ b/hw/sd/Makefile.objs
19
+++ b/hw/arm/Makefile.objs
21
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_SDHCI) += sdhci.o
20
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
22
obj-$(CONFIG_MILKYMIST) += milkymist-memcard.o
21
obj-$(CONFIG_IOTKIT) += iotkit.o
23
obj-$(CONFIG_OMAP) += omap_mmc.o
22
obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
24
obj-$(CONFIG_PXA2XX) += pxa2xx_mmci.o
23
obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmuv3.o
25
+obj-$(CONFIG_RASPI) += bcm2835_sdhost.o
24
+obj-$(CONFIG_FSL_IMX6UL) += fsl-imx6ul.o
26
diff --git a/include/hw/sd/bcm2835_sdhost.h b/include/hw/sd/bcm2835_sdhost.h
25
diff --git a/include/hw/arm/fsl-imx6ul.h b/include/hw/arm/fsl-imx6ul.h
27
new file mode 100644
26
new file mode 100644
28
index XXXXXXX..XXXXXXX
27
index XXXXXXX..XXXXXXX
29
--- /dev/null
28
--- /dev/null
30
+++ b/include/hw/sd/bcm2835_sdhost.h
29
+++ b/include/hw/arm/fsl-imx6ul.h
31
@@ -XXX,XX +XXX,XX @@
30
@@ -XXX,XX +XXX,XX @@
32
+/*
31
+/*
33
+ * Raspberry Pi (BCM2835) SD Host Controller
32
+ * Copyright (c) 2018 Jean-Christophe Dubois <jcd@tribudubois.net>
34
+ *
33
+ *
35
+ * Copyright (c) 2017 Antfield SAS
34
+ * i.MX6ul SoC definitions
36
+ *
35
+ *
37
+ * Authors:
36
+ * This program is free software; you can redistribute it and/or modify
38
+ * Clement Deschamps <clement.deschamps@antfield.fr>
37
+ * it under the terms of the GNU General Public License as published by
39
+ * Luc Michel <luc.michel@antfield.fr>
38
+ * the Free Software Foundation; either version 2 of the License, or
39
+ * (at your option) any later version.
40
+ *
40
+ *
41
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
41
+ * This program is distributed in the hope that it will be useful,
42
+ * See the COPYING file in the top-level directory.
42
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
43
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44
+ * GNU General Public License for more details.
43
+ */
45
+ */
44
+
46
+
45
+#ifndef BCM2835_SDHOST_H
47
+#ifndef FSL_IMX6UL_H
46
+#define BCM2835_SDHOST_H
48
+#define FSL_IMX6UL_H
47
+
49
+
48
+#include "hw/sysbus.h"
50
+#include "hw/arm/arm.h"
49
+#include "hw/sd/sd.h"
51
+#include "hw/cpu/a15mpcore.h"
50
+
52
+#include "hw/misc/imx6ul_ccm.h"
51
+#define TYPE_BCM2835_SDHOST "bcm2835-sdhost"
53
+#include "hw/misc/imx6_src.h"
52
+#define BCM2835_SDHOST(obj) \
54
+#include "hw/misc/imx7_snvs.h"
53
+ OBJECT_CHECK(BCM2835SDHostState, (obj), TYPE_BCM2835_SDHOST)
55
+#include "hw/misc/imx7_gpr.h"
54
+
56
+#include "hw/intc/imx_gpcv2.h"
55
+#define BCM2835_SDHOST_FIFO_LEN 16
57
+#include "hw/misc/imx2_wdt.h"
56
+
58
+#include "hw/gpio/imx_gpio.h"
57
+typedef struct {
59
+#include "hw/char/imx_serial.h"
58
+ SysBusDevice busdev;
60
+#include "hw/timer/imx_gpt.h"
59
+ SDBus sdbus;
61
+#include "hw/timer/imx_epit.h"
60
+ MemoryRegion iomem;
62
+#include "hw/i2c/imx_i2c.h"
61
+
63
+#include "hw/gpio/imx_gpio.h"
62
+ uint32_t cmd;
64
+#include "hw/sd/sdhci.h"
63
+ uint32_t cmdarg;
65
+#include "hw/ssi/imx_spi.h"
64
+ uint32_t status;
66
+#include "hw/net/imx_fec.h"
65
+ uint32_t rsp[4];
67
+#include "exec/memory.h"
66
+ uint32_t config;
68
+#include "cpu.h"
67
+ uint32_t edm;
69
+
68
+ uint32_t vdd;
70
+#define TYPE_FSL_IMX6UL "fsl,imx6ul"
69
+ uint32_t hbct;
71
+#define FSL_IMX6UL(obj) OBJECT_CHECK(FslIMX6ULState, (obj), TYPE_FSL_IMX6UL)
70
+ uint32_t hblc;
72
+
71
+ int32_t fifo_pos;
73
+enum FslIMX6ULConfiguration {
72
+ int32_t fifo_len;
74
+ FSL_IMX6UL_NUM_CPUS = 1,
73
+ uint32_t fifo[BCM2835_SDHOST_FIFO_LEN];
75
+ FSL_IMX6UL_NUM_UARTS = 8,
74
+ uint32_t datacnt;
76
+ FSL_IMX6UL_NUM_ETHS = 2,
75
+
77
+ FSL_IMX6UL_ETH_NUM_TX_RINGS = 2,
76
+ qemu_irq irq;
78
+ FSL_IMX6UL_NUM_USDHCS = 2,
77
+} BCM2835SDHostState;
79
+ FSL_IMX6UL_NUM_WDTS = 3,
78
+
80
+ FSL_IMX6UL_NUM_GPTS = 2,
79
+#endif
81
+ FSL_IMX6UL_NUM_EPITS = 2,
80
diff --git a/hw/sd/bcm2835_sdhost.c b/hw/sd/bcm2835_sdhost.c
82
+ FSL_IMX6UL_NUM_IOMUXCS = 2,
83
+ FSL_IMX6UL_NUM_GPIOS = 5,
84
+ FSL_IMX6UL_NUM_I2CS = 4,
85
+ FSL_IMX6UL_NUM_ECSPIS = 4,
86
+ FSL_IMX6UL_NUM_ADCS = 2,
87
+};
88
+
89
+typedef struct FslIMX6ULState {
90
+ /*< private >*/
91
+ DeviceState parent_obj;
92
+
93
+ /*< public >*/
94
+ ARMCPU cpu[FSL_IMX6UL_NUM_CPUS];
95
+ A15MPPrivState a7mpcore;
96
+ IMXGPTState gpt[FSL_IMX6UL_NUM_GPTS];
97
+ IMXEPITState epit[FSL_IMX6UL_NUM_EPITS];
98
+ IMXGPIOState gpio[FSL_IMX6UL_NUM_GPIOS];
99
+ IMX6ULCCMState ccm;
100
+ IMX6SRCState src;
101
+ IMX7SNVSState snvs;
102
+ IMXGPCv2State gpcv2;
103
+ IMX7GPRState gpr;
104
+ IMXSPIState spi[FSL_IMX6UL_NUM_ECSPIS];
105
+ IMXI2CState i2c[FSL_IMX6UL_NUM_I2CS];
106
+ IMXSerialState uart[FSL_IMX6UL_NUM_UARTS];
107
+ IMXFECState eth[FSL_IMX6UL_NUM_ETHS];
108
+ SDHCIState usdhc[FSL_IMX6UL_NUM_USDHCS];
109
+ IMX2WdtState wdt[FSL_IMX6UL_NUM_WDTS];
110
+ MemoryRegion rom;
111
+ MemoryRegion caam;
112
+ MemoryRegion ocram;
113
+ MemoryRegion ocram_alias;
114
+} FslIMX6ULState;
115
+
116
+enum FslIMX6ULMemoryMap {
117
+ FSL_IMX6UL_MMDC_ADDR = 0x80000000,
118
+ FSL_IMX6UL_MMDC_SIZE = 2 * 1024 * 1024 * 1024UL,
119
+
120
+ FSL_IMX6UL_QSPI1_MEM_ADDR = 0x60000000,
121
+ FSL_IMX6UL_EIM_ALIAS_ADDR = 0x58000000,
122
+ FSL_IMX6UL_EIM_CS_ADDR = 0x50000000,
123
+ FSL_IMX6UL_AES_ENCRYPT_ADDR = 0x10000000,
124
+ FSL_IMX6UL_QSPI1_RX_ADDR = 0x0C000000,
125
+
126
+ /* AIPS-2 */
127
+ FSL_IMX6UL_UART6_ADDR = 0x021FC000,
128
+ FSL_IMX6UL_I2C4_ADDR = 0x021F8000,
129
+ FSL_IMX6UL_UART5_ADDR = 0x021F4000,
130
+ FSL_IMX6UL_UART4_ADDR = 0x021F0000,
131
+ FSL_IMX6UL_UART3_ADDR = 0x021EC000,
132
+ FSL_IMX6UL_UART2_ADDR = 0x021E8000,
133
+ FSL_IMX6UL_WDOG3_ADDR = 0x021E4000,
134
+ FSL_IMX6UL_QSPI_ADDR = 0x021E0000,
135
+ FSL_IMX6UL_SYS_CNT_CTRL_ADDR = 0x021DC000,
136
+ FSL_IMX6UL_SYS_CNT_CMP_ADDR = 0x021D8000,
137
+ FSL_IMX6UL_SYS_CNT_RD_ADDR = 0x021D4000,
138
+ FSL_IMX6UL_TZASC_ADDR = 0x021D0000,
139
+ FSL_IMX6UL_PXP_ADDR = 0x021CC000,
140
+ FSL_IMX6UL_LCDIF_ADDR = 0x021C8000,
141
+ FSL_IMX6UL_CSI_ADDR = 0x021C4000,
142
+ FSL_IMX6UL_CSU_ADDR = 0x021C0000,
143
+ FSL_IMX6UL_OCOTP_CTRL_ADDR = 0x021BC000,
144
+ FSL_IMX6UL_EIM_ADDR = 0x021B8000,
145
+ FSL_IMX6UL_SIM2_ADDR = 0x021B4000,
146
+ FSL_IMX6UL_MMDC_CFG_ADDR = 0x021B0000,
147
+ FSL_IMX6UL_ROMCP_ADDR = 0x021AC000,
148
+ FSL_IMX6UL_I2C3_ADDR = 0x021A8000,
149
+ FSL_IMX6UL_I2C2_ADDR = 0x021A4000,
150
+ FSL_IMX6UL_I2C1_ADDR = 0x021A0000,
151
+ FSL_IMX6UL_ADC2_ADDR = 0x0219C000,
152
+ FSL_IMX6UL_ADC1_ADDR = 0x02198000,
153
+ FSL_IMX6UL_USDHC2_ADDR = 0x02194000,
154
+ FSL_IMX6UL_USDHC1_ADDR = 0x02190000,
155
+ FSL_IMX6UL_SIM1_ADDR = 0x0218C000,
156
+ FSL_IMX6UL_ENET1_ADDR = 0x02188000,
157
+ FSL_IMX6UL_USBO2_USBMISC_ADDR = 0x02184800,
158
+ FSL_IMX6UL_USBO2_USB_ADDR = 0x02184000,
159
+ FSL_IMX6UL_USBO2_PL301_ADDR = 0x02180000,
160
+ FSL_IMX6UL_AIPS2_CFG_ADDR = 0x0217C000,
161
+ FSL_IMX6UL_CAAM_ADDR = 0x02140000,
162
+ FSL_IMX6UL_A7MPCORE_DAP_ADDR = 0x02100000,
163
+
164
+ /* AIPS-1 */
165
+ FSL_IMX6UL_PWM8_ADDR = 0x020FC000,
166
+ FSL_IMX6UL_PWM7_ADDR = 0x020F8000,
167
+ FSL_IMX6UL_PWM6_ADDR = 0x020F4000,
168
+ FSL_IMX6UL_PWM5_ADDR = 0x020F0000,
169
+ FSL_IMX6UL_SDMA_ADDR = 0x020EC000,
170
+ FSL_IMX6UL_GPT2_ADDR = 0x020E8000,
171
+ FSL_IMX6UL_IOMUXC_GPR_ADDR = 0x020E4000,
172
+ FSL_IMX6UL_IOMUXC_ADDR = 0x020E0000,
173
+ FSL_IMX6UL_GPC_ADDR = 0x020DC000,
174
+ FSL_IMX6UL_SRC_ADDR = 0x020D8000,
175
+ FSL_IMX6UL_EPIT2_ADDR = 0x020D4000,
176
+ FSL_IMX6UL_EPIT1_ADDR = 0x020D0000,
177
+ FSL_IMX6UL_SNVS_HP_ADDR = 0x020CC000,
178
+ FSL_IMX6UL_ANALOG_ADDR = 0x020C8000,
179
+ FSL_IMX6UL_CCM_ADDR = 0x020C4000,
180
+ FSL_IMX6UL_WDOG2_ADDR = 0x020C0000,
181
+ FSL_IMX6UL_WDOG1_ADDR = 0x020BC000,
182
+ FSL_IMX6UL_KPP_ADDR = 0x020B8000,
183
+ FSL_IMX6UL_ENET2_ADDR = 0x020B4000,
184
+ FSL_IMX6UL_SNVS_LP_ADDR = 0x020B0000,
185
+ FSL_IMX6UL_GPIO5_ADDR = 0x020AC000,
186
+ FSL_IMX6UL_GPIO4_ADDR = 0x020A8000,
187
+ FSL_IMX6UL_GPIO3_ADDR = 0x020A4000,
188
+ FSL_IMX6UL_GPIO2_ADDR = 0x020A0000,
189
+ FSL_IMX6UL_GPIO1_ADDR = 0x0209C000,
190
+ FSL_IMX6UL_GPT1_ADDR = 0x02098000,
191
+ FSL_IMX6UL_CAN2_ADDR = 0x02094000,
192
+ FSL_IMX6UL_CAN1_ADDR = 0x02090000,
193
+ FSL_IMX6UL_PWM4_ADDR = 0x0208C000,
194
+ FSL_IMX6UL_PWM3_ADDR = 0x02088000,
195
+ FSL_IMX6UL_PWM2_ADDR = 0x02084000,
196
+ FSL_IMX6UL_PWM1_ADDR = 0x02080000,
197
+ FSL_IMX6UL_AIPS1_CFG_ADDR = 0x0207C000,
198
+ FSL_IMX6UL_BEE_ADDR = 0x02044000,
199
+ FSL_IMX6UL_TOUCH_CTRL_ADDR = 0x02040000,
200
+ FSL_IMX6UL_SPBA_ADDR = 0x0203C000,
201
+ FSL_IMX6UL_ASRC_ADDR = 0x02034000,
202
+ FSL_IMX6UL_SAI3_ADDR = 0x02030000,
203
+ FSL_IMX6UL_SAI2_ADDR = 0x0202C000,
204
+ FSL_IMX6UL_SAI1_ADDR = 0x02028000,
205
+ FSL_IMX6UL_UART8_ADDR = 0x02024000,
206
+ FSL_IMX6UL_UART1_ADDR = 0x02020000,
207
+ FSL_IMX6UL_UART7_ADDR = 0x02018000,
208
+ FSL_IMX6UL_ECSPI4_ADDR = 0x02014000,
209
+ FSL_IMX6UL_ECSPI3_ADDR = 0x02010000,
210
+ FSL_IMX6UL_ECSPI2_ADDR = 0x0200C000,
211
+ FSL_IMX6UL_ECSPI1_ADDR = 0x02008000,
212
+ FSL_IMX6UL_SPDIF_ADDR = 0x02004000,
213
+
214
+ FSL_IMX6UL_APBH_DMA_ADDR = 0x01804000,
215
+ FSL_IMX6UL_APBH_DMA_SIZE = (32 * 1024),
216
+
217
+ FSL_IMX6UL_A7MPCORE_ADDR = 0x00A00000,
218
+
219
+ FSL_IMX6UL_OCRAM_ALIAS_ADDR = 0x00920000,
220
+ FSL_IMX6UL_OCRAM_ALIAS_SIZE = 0x00060000,
221
+ FSL_IMX6UL_OCRAM_MEM_ADDR = 0x00900000,
222
+ FSL_IMX6UL_OCRAM_MEM_SIZE = 0x00020000,
223
+ FSL_IMX6UL_CAAM_MEM_ADDR = 0x00100000,
224
+ FSL_IMX6UL_CAAM_MEM_SIZE = 0x00008000,
225
+ FSL_IMX6UL_ROM_ADDR = 0x00000000,
226
+ FSL_IMX6UL_ROM_SIZE = 0x00018000,
227
+};
228
+
229
+enum FslIMX6ULIRQs {
230
+ FSL_IMX6UL_IOMUXC_IRQ = 0,
231
+ FSL_IMX6UL_DAP_IRQ = 1,
232
+ FSL_IMX6UL_SDMA_IRQ = 2,
233
+ FSL_IMX6UL_TSC_IRQ = 3,
234
+ FSL_IMX6UL_SNVS_IRQ = 4,
235
+ FSL_IMX6UL_LCDIF_IRQ = 5,
236
+ FSL_IMX6UL_BEE_IRQ = 6,
237
+ FSL_IMX6UL_CSI_IRQ = 7,
238
+ FSL_IMX6UL_PXP_IRQ = 8,
239
+ FSL_IMX6UL_SCTR1_IRQ = 9,
240
+ FSL_IMX6UL_SCTR2_IRQ = 10,
241
+ FSL_IMX6UL_WDOG3_IRQ = 11,
242
+ FSL_IMX6UL_APBH_DMA_IRQ = 13,
243
+ FSL_IMX6UL_WEIM_IRQ = 14,
244
+ FSL_IMX6UL_RAWNAND1_IRQ = 15,
245
+ FSL_IMX6UL_RAWNAND2_IRQ = 16,
246
+ FSL_IMX6UL_UART6_IRQ = 17,
247
+ FSL_IMX6UL_SRTC_IRQ = 19,
248
+ FSL_IMX6UL_SRTC_SEC_IRQ = 20,
249
+ FSL_IMX6UL_CSU_IRQ = 21,
250
+ FSL_IMX6UL_USDHC1_IRQ = 22,
251
+ FSL_IMX6UL_USDHC2_IRQ = 23,
252
+ FSL_IMX6UL_SAI3_IRQ = 24,
253
+ FSL_IMX6UL_SAI32_IRQ = 25,
254
+
255
+ FSL_IMX6UL_UART1_IRQ = 26,
256
+ FSL_IMX6UL_UART2_IRQ = 27,
257
+ FSL_IMX6UL_UART3_IRQ = 28,
258
+ FSL_IMX6UL_UART4_IRQ = 29,
259
+ FSL_IMX6UL_UART5_IRQ = 30,
260
+
261
+ FSL_IMX6UL_ECSPI1_IRQ = 31,
262
+ FSL_IMX6UL_ECSPI2_IRQ = 32,
263
+ FSL_IMX6UL_ECSPI3_IRQ = 33,
264
+ FSL_IMX6UL_ECSPI4_IRQ = 34,
265
+
266
+ FSL_IMX6UL_I2C4_IRQ = 35,
267
+ FSL_IMX6UL_I2C1_IRQ = 36,
268
+ FSL_IMX6UL_I2C2_IRQ = 37,
269
+ FSL_IMX6UL_I2C3_IRQ = 38,
270
+
271
+ FSL_IMX6UL_UART7_IRQ = 39,
272
+ FSL_IMX6UL_UART8_IRQ = 40,
273
+
274
+ FSL_IMX6UL_USB1_IRQ = 42,
275
+ FSL_IMX6UL_USB2_IRQ = 43,
276
+ FSL_IMX6UL_USB_PHY1_IRQ = 44,
277
+ FSL_IMX6UL_USB_PHY2_IRQ = 44,
278
+
279
+ FSL_IMX6UL_CAAM_JQ2_IRQ = 46,
280
+ FSL_IMX6UL_CAAM_ERR_IRQ = 47,
281
+ FSL_IMX6UL_CAAM_RTIC_IRQ = 48,
282
+ FSL_IMX6UL_TEMP_IRQ = 49,
283
+ FSL_IMX6UL_ASRC_IRQ = 50,
284
+ FSL_IMX6UL_SPDIF_IRQ = 52,
285
+ FSL_IMX6UL_PMU_REG_IRQ = 54,
286
+ FSL_IMX6UL_GPT1_IRQ = 55,
287
+
288
+ FSL_IMX6UL_EPIT1_IRQ = 56,
289
+ FSL_IMX6UL_EPIT2_IRQ = 57,
290
+
291
+ FSL_IMX6UL_GPIO1_INT7_IRQ = 58,
292
+ FSL_IMX6UL_GPIO1_INT6_IRQ = 59,
293
+ FSL_IMX6UL_GPIO1_INT5_IRQ = 60,
294
+ FSL_IMX6UL_GPIO1_INT4_IRQ = 61,
295
+ FSL_IMX6UL_GPIO1_INT3_IRQ = 62,
296
+ FSL_IMX6UL_GPIO1_INT2_IRQ = 63,
297
+ FSL_IMX6UL_GPIO1_INT1_IRQ = 64,
298
+ FSL_IMX6UL_GPIO1_INT0_IRQ = 65,
299
+ FSL_IMX6UL_GPIO1_LOW_IRQ = 66,
300
+ FSL_IMX6UL_GPIO1_HIGH_IRQ = 67,
301
+ FSL_IMX6UL_GPIO2_LOW_IRQ = 68,
302
+ FSL_IMX6UL_GPIO2_HIGH_IRQ = 69,
303
+ FSL_IMX6UL_GPIO3_LOW_IRQ = 70,
304
+ FSL_IMX6UL_GPIO3_HIGH_IRQ = 71,
305
+ FSL_IMX6UL_GPIO4_LOW_IRQ = 72,
306
+ FSL_IMX6UL_GPIO4_HIGH_IRQ = 73,
307
+ FSL_IMX6UL_GPIO5_LOW_IRQ = 74,
308
+ FSL_IMX6UL_GPIO5_HIGH_IRQ = 75,
309
+
310
+ FSL_IMX6UL_WDOG1_IRQ = 80,
311
+ FSL_IMX6UL_WDOG2_IRQ = 81,
312
+
313
+ FSL_IMX6UL_KPP_IRQ = 82,
314
+
315
+ FSL_IMX6UL_PWM1_IRQ = 83,
316
+ FSL_IMX6UL_PWM2_IRQ = 84,
317
+ FSL_IMX6UL_PWM3_IRQ = 85,
318
+ FSL_IMX6UL_PWM4_IRQ = 86,
319
+
320
+ FSL_IMX6UL_CCM1_IRQ = 87,
321
+ FSL_IMX6UL_CCM2_IRQ = 88,
322
+
323
+ FSL_IMX6UL_GPC_IRQ = 89,
324
+
325
+ FSL_IMX6UL_SRC_IRQ = 91,
326
+
327
+ FSL_IMX6UL_CPU_PERF_IRQ = 94,
328
+ FSL_IMX6UL_CPU_CTI_IRQ = 95,
329
+
330
+ FSL_IMX6UL_SRC_WDOG_IRQ = 96,
331
+
332
+ FSL_IMX6UL_SAI1_IRQ = 97,
333
+ FSL_IMX6UL_SAI2_IRQ = 98,
334
+
335
+ FSL_IMX6UL_ADC1_IRQ = 100,
336
+ FSL_IMX6UL_ADC2_IRQ = 101,
337
+
338
+ FSL_IMX6UL_SJC_IRQ = 104,
339
+
340
+ FSL_IMX6UL_CAAM_RING0_IRQ = 105,
341
+ FSL_IMX6UL_CAAM_RING1_IRQ = 106,
342
+
343
+ FSL_IMX6UL_QSPI_IRQ = 107,
344
+
345
+ FSL_IMX6UL_TZASC_IRQ = 108,
346
+
347
+ FSL_IMX6UL_GPT2_IRQ = 109,
348
+
349
+ FSL_IMX6UL_CAN1_IRQ = 110,
350
+ FSL_IMX6UL_CAN2_IRQ = 111,
351
+
352
+ FSL_IMX6UL_SIM1_IRQ = 112,
353
+ FSL_IMX6UL_SIM2_IRQ = 113,
354
+
355
+ FSL_IMX6UL_PWM5_IRQ = 114,
356
+ FSL_IMX6UL_PWM6_IRQ = 115,
357
+ FSL_IMX6UL_PWM7_IRQ = 116,
358
+ FSL_IMX6UL_PWM8_IRQ = 117,
359
+
360
+ FSL_IMX6UL_ENET1_IRQ = 118,
361
+ FSL_IMX6UL_ENET1_TIMER_IRQ = 119,
362
+ FSL_IMX6UL_ENET2_IRQ = 120,
363
+ FSL_IMX6UL_ENET2_TIMER_IRQ = 121,
364
+
365
+ FSL_IMX6UL_PMU_CORE_IRQ = 127,
366
+ FSL_IMX6UL_MAX_IRQ = 128,
367
+};
368
+
369
+#endif /* FSL_IMX6UL_H */
370
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
81
new file mode 100644
371
new file mode 100644
82
index XXXXXXX..XXXXXXX
372
index XXXXXXX..XXXXXXX
83
--- /dev/null
373
--- /dev/null
84
+++ b/hw/sd/bcm2835_sdhost.c
374
+++ b/hw/arm/fsl-imx6ul.c
85
@@ -XXX,XX +XXX,XX @@
375
@@ -XXX,XX +XXX,XX @@
86
+/*
376
+/*
87
+ * Raspberry Pi (BCM2835) SD Host Controller
377
+ * Copyright (c) 2018 Jean-Christophe Dubois <jcd@tribudubois.net>
88
+ *
378
+ *
89
+ * Copyright (c) 2017 Antfield SAS
379
+ * i.MX6UL SOC emulation.
90
+ *
380
+ *
91
+ * Authors:
381
+ * Based on hw/arm/fsl-imx7.c
92
+ * Clement Deschamps <clement.deschamps@antfield.fr>
93
+ * Luc Michel <luc.michel@antfield.fr>
94
+ *
382
+ *
95
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
383
+ * This program is free software; you can redistribute it and/or modify
96
+ * See the COPYING file in the top-level directory.
384
+ * it under the terms of the GNU General Public License as published by
385
+ * the Free Software Foundation; either version 2 of the License, or
386
+ * (at your option) any later version.
387
+ *
388
+ * This program is distributed in the hope that it will be useful,
389
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
390
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
391
+ * GNU General Public License for more details.
97
+ */
392
+ */
98
+
393
+
99
+#include "qemu/osdep.h"
394
+#include "qemu/osdep.h"
100
+#include "qemu/log.h"
395
+#include "qapi/error.h"
101
+#include "sysemu/blockdev.h"
396
+#include "qemu-common.h"
102
+#include "hw/sd/bcm2835_sdhost.h"
397
+#include "hw/arm/fsl-imx6ul.h"
103
+
398
+#include "hw/misc/unimp.h"
104
+#define TYPE_BCM2835_SDHOST_BUS "bcm2835-sdhost-bus"
399
+#include "sysemu/sysemu.h"
105
+#define BCM2835_SDHOST_BUS(obj) \
400
+#include "qemu/error-report.h"
106
+ OBJECT_CHECK(SDBus, (obj), TYPE_BCM2835_SDHOST_BUS)
401
+
107
+
402
+#define NAME_SIZE 20
108
+#define SDCMD 0x00 /* Command to SD card - 16 R/W */
403
+
109
+#define SDARG 0x04 /* Argument to SD card - 32 R/W */
404
+static void fsl_imx6ul_init(Object *obj)
110
+#define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */
111
+#define SDCDIV 0x0c /* Start value for clock divider - 11 R/W */
112
+#define SDRSP0 0x10 /* SD card rsp (31:0) - 32 R */
113
+#define SDRSP1 0x14 /* SD card rsp (63:32) - 32 R */
114
+#define SDRSP2 0x18 /* SD card rsp (95:64) - 32 R */
115
+#define SDRSP3 0x1c /* SD card rsp (127:96) - 32 R */
116
+#define SDHSTS 0x20 /* SD host status - 11 R */
117
+#define SDVDD 0x30 /* SD card power control - 1 R/W */
118
+#define SDEDM 0x34 /* Emergency Debug Mode - 13 R/W */
119
+#define SDHCFG 0x38 /* Host configuration - 2 R/W */
120
+#define SDHBCT 0x3c /* Host byte count (debug) - 32 R/W */
121
+#define SDDATA 0x40 /* Data to/from SD card - 32 R/W */
122
+#define SDHBLC 0x50 /* Host block count (SDIO/SDHC) - 9 R/W */
123
+
124
+#define SDCMD_NEW_FLAG 0x8000
125
+#define SDCMD_FAIL_FLAG 0x4000
126
+#define SDCMD_BUSYWAIT 0x800
127
+#define SDCMD_NO_RESPONSE 0x400
128
+#define SDCMD_LONG_RESPONSE 0x200
129
+#define SDCMD_WRITE_CMD 0x80
130
+#define SDCMD_READ_CMD 0x40
131
+#define SDCMD_CMD_MASK 0x3f
132
+
133
+#define SDCDIV_MAX_CDIV 0x7ff
134
+
135
+#define SDHSTS_BUSY_IRPT 0x400
136
+#define SDHSTS_BLOCK_IRPT 0x200
137
+#define SDHSTS_SDIO_IRPT 0x100
138
+#define SDHSTS_REW_TIME_OUT 0x80
139
+#define SDHSTS_CMD_TIME_OUT 0x40
140
+#define SDHSTS_CRC16_ERROR 0x20
141
+#define SDHSTS_CRC7_ERROR 0x10
142
+#define SDHSTS_FIFO_ERROR 0x08
143
+/* Reserved */
144
+/* Reserved */
145
+#define SDHSTS_DATA_FLAG 0x01
146
+
147
+#define SDHCFG_BUSY_IRPT_EN (1 << 10)
148
+#define SDHCFG_BLOCK_IRPT_EN (1 << 8)
149
+#define SDHCFG_SDIO_IRPT_EN (1 << 5)
150
+#define SDHCFG_DATA_IRPT_EN (1 << 4)
151
+#define SDHCFG_SLOW_CARD (1 << 3)
152
+#define SDHCFG_WIDE_EXT_BUS (1 << 2)
153
+#define SDHCFG_WIDE_INT_BUS (1 << 1)
154
+#define SDHCFG_REL_CMD_LINE (1 << 0)
155
+
156
+#define SDEDM_FORCE_DATA_MODE (1 << 19)
157
+#define SDEDM_CLOCK_PULSE (1 << 20)
158
+#define SDEDM_BYPASS (1 << 21)
159
+
160
+#define SDEDM_WRITE_THRESHOLD_SHIFT 9
161
+#define SDEDM_READ_THRESHOLD_SHIFT 14
162
+#define SDEDM_THRESHOLD_MASK 0x1f
163
+
164
+#define SDEDM_FSM_MASK 0xf
165
+#define SDEDM_FSM_IDENTMODE 0x0
166
+#define SDEDM_FSM_DATAMODE 0x1
167
+#define SDEDM_FSM_READDATA 0x2
168
+#define SDEDM_FSM_WRITEDATA 0x3
169
+#define SDEDM_FSM_READWAIT 0x4
170
+#define SDEDM_FSM_READCRC 0x5
171
+#define SDEDM_FSM_WRITECRC 0x6
172
+#define SDEDM_FSM_WRITEWAIT1 0x7
173
+#define SDEDM_FSM_POWERDOWN 0x8
174
+#define SDEDM_FSM_POWERUP 0x9
175
+#define SDEDM_FSM_WRITESTART1 0xa
176
+#define SDEDM_FSM_WRITESTART2 0xb
177
+#define SDEDM_FSM_GENPULSES 0xc
178
+#define SDEDM_FSM_WRITEWAIT2 0xd
179
+#define SDEDM_FSM_STARTPOWDOWN 0xf
180
+
181
+#define SDDATA_FIFO_WORDS 16
182
+
183
+static void bcm2835_sdhost_update_irq(BCM2835SDHostState *s)
184
+{
405
+{
185
+ uint32_t irq = s->status &
406
+ FslIMX6ULState *s = FSL_IMX6UL(obj);
186
+ (SDHSTS_BUSY_IRPT | SDHSTS_BLOCK_IRPT | SDHSTS_SDIO_IRPT);
407
+ char name[NAME_SIZE];
187
+ qemu_set_irq(s->irq, !!irq);
408
+ int i;
409
+
410
+ for (i = 0; i < MIN(smp_cpus, FSL_IMX6UL_NUM_CPUS); i++) {
411
+ snprintf(name, NAME_SIZE, "cpu%d", i);
412
+ object_initialize_child(obj, name, &s->cpu[i], sizeof(s->cpu[i]),
413
+ "cortex-a7-" TYPE_ARM_CPU, &error_abort, NULL);
414
+ }
415
+
416
+ /*
417
+ * A7MPCORE
418
+ */
419
+ sysbus_init_child_obj(obj, "a7mpcore", &s->a7mpcore, sizeof(s->a7mpcore),
420
+ TYPE_A15MPCORE_PRIV);
421
+
422
+ /*
423
+ * CCM
424
+ */
425
+ sysbus_init_child_obj(obj, "ccm", &s->ccm, sizeof(s->ccm), TYPE_IMX6UL_CCM);
426
+
427
+ /*
428
+ * SRC
429
+ */
430
+ sysbus_init_child_obj(obj, "src", &s->src, sizeof(s->src), TYPE_IMX6_SRC);
431
+
432
+ /*
433
+ * GPCv2
434
+ */
435
+ sysbus_init_child_obj(obj, "gpcv2", &s->gpcv2, sizeof(s->gpcv2),
436
+ TYPE_IMX_GPCV2);
437
+
438
+ /*
439
+ * SNVS
440
+ */
441
+ sysbus_init_child_obj(obj, "snvs", &s->snvs, sizeof(s->snvs),
442
+ TYPE_IMX7_SNVS);
443
+
444
+ /*
445
+ * GPR
446
+ */
447
+ sysbus_init_child_obj(obj, "gpr", &s->gpr, sizeof(s->gpr),
448
+ TYPE_IMX7_GPR);
449
+
450
+ /*
451
+ * GPIOs 1 to 5
452
+ */
453
+ for (i = 0; i < FSL_IMX6UL_NUM_GPIOS; i++) {
454
+ snprintf(name, NAME_SIZE, "gpio%d", i);
455
+ sysbus_init_child_obj(obj, name, &s->gpio[i], sizeof(s->gpio[i]),
456
+ TYPE_IMX_GPIO);
457
+ }
458
+
459
+ /*
460
+ * GPT 1, 2
461
+ */
462
+ for (i = 0; i < FSL_IMX6UL_NUM_GPTS; i++) {
463
+ snprintf(name, NAME_SIZE, "gpt%d", i);
464
+ sysbus_init_child_obj(obj, name, &s->gpt[i], sizeof(s->gpt[i]),
465
+ TYPE_IMX7_GPT);
466
+ }
467
+
468
+ /*
469
+ * EPIT 1, 2
470
+ */
471
+ for (i = 0; i < FSL_IMX6UL_NUM_EPITS; i++) {
472
+ snprintf(name, NAME_SIZE, "epit%d", i + 1);
473
+ sysbus_init_child_obj(obj, name, &s->epit[i], sizeof(s->epit[i]),
474
+ TYPE_IMX_EPIT);
475
+ }
476
+
477
+ /*
478
+ * eCSPI
479
+ */
480
+ for (i = 0; i < FSL_IMX6UL_NUM_ECSPIS; i++) {
481
+ snprintf(name, NAME_SIZE, "spi%d", i + 1);
482
+ sysbus_init_child_obj(obj, name, &s->spi[i], sizeof(s->spi[i]),
483
+ TYPE_IMX_SPI);
484
+ }
485
+
486
+ /*
487
+ * I2C
488
+ */
489
+ for (i = 0; i < FSL_IMX6UL_NUM_I2CS; i++) {
490
+ snprintf(name, NAME_SIZE, "i2c%d", i + 1);
491
+ sysbus_init_child_obj(obj, name, &s->i2c[i], sizeof(s->i2c[i]),
492
+ TYPE_IMX_I2C);
493
+ }
494
+
495
+ /*
496
+ * UART
497
+ */
498
+ for (i = 0; i < FSL_IMX6UL_NUM_UARTS; i++) {
499
+ snprintf(name, NAME_SIZE, "uart%d", i);
500
+ sysbus_init_child_obj(obj, name, &s->uart[i], sizeof(s->uart[i]),
501
+ TYPE_IMX_SERIAL);
502
+ }
503
+
504
+ /*
505
+ * Ethernet
506
+ */
507
+ for (i = 0; i < FSL_IMX6UL_NUM_ETHS; i++) {
508
+ snprintf(name, NAME_SIZE, "eth%d", i);
509
+ sysbus_init_child_obj(obj, name, &s->eth[i], sizeof(s->eth[i]),
510
+ TYPE_IMX_ENET);
511
+ }
512
+
513
+ /*
514
+ * SDHCI
515
+ */
516
+ for (i = 0; i < FSL_IMX6UL_NUM_USDHCS; i++) {
517
+ snprintf(name, NAME_SIZE, "usdhc%d", i);
518
+ sysbus_init_child_obj(obj, name, &s->usdhc[i], sizeof(s->usdhc[i]),
519
+ TYPE_IMX_USDHC);
520
+ }
521
+
522
+ /*
523
+ * Watchdog
524
+ */
525
+ for (i = 0; i < FSL_IMX6UL_NUM_WDTS; i++) {
526
+ snprintf(name, NAME_SIZE, "wdt%d", i);
527
+ sysbus_init_child_obj(obj, name, &s->wdt[i], sizeof(s->wdt[i]),
528
+ TYPE_IMX2_WDT);
529
+ }
188
+}
530
+}
189
+
531
+
190
+static void bcm2835_sdhost_send_command(BCM2835SDHostState *s)
532
+static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
191
+{
533
+{
192
+ SDRequest request;
534
+ FslIMX6ULState *s = FSL_IMX6UL(dev);
193
+ uint8_t rsp[16];
535
+ int i;
194
+ int rlen;
536
+ qemu_irq irq;
195
+
537
+ char name[NAME_SIZE];
196
+ request.cmd = s->cmd & SDCMD_CMD_MASK;
538
+
197
+ request.arg = s->cmdarg;
539
+ if (smp_cpus > FSL_IMX6UL_NUM_CPUS) {
198
+
540
+ error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
199
+ rlen = sdbus_do_command(&s->sdbus, &request, rsp);
541
+ TYPE_FSL_IMX6UL, FSL_IMX6UL_NUM_CPUS, smp_cpus);
200
+ if (rlen < 0) {
542
+ return;
201
+ goto error;
543
+ }
202
+ }
544
+
203
+ if (!(s->cmd & SDCMD_NO_RESPONSE)) {
545
+ for (i = 0; i < smp_cpus; i++) {
204
+#define RWORD(n) (((uint32_t)rsp[n] << 24) | (rsp[n + 1] << 16) \
546
+ Object *o = OBJECT(&s->cpu[i]);
205
+ | (rsp[n + 2] << 8) | rsp[n + 3])
547
+
206
+ if (rlen == 0 || (rlen == 4 && (s->cmd & SDCMD_LONG_RESPONSE))) {
548
+ object_property_set_int(o, QEMU_PSCI_CONDUIT_SMC,
207
+ goto error;
549
+ "psci-conduit", &error_abort);
550
+
551
+ /* On uniprocessor, the CBAR is set to 0 */
552
+ if (smp_cpus > 1) {
553
+ object_property_set_int(o, FSL_IMX6UL_A7MPCORE_ADDR,
554
+ "reset-cbar", &error_abort);
208
+ }
555
+ }
209
+ if (rlen != 4 && rlen != 16) {
556
+
210
+ goto error;
557
+ if (i) {
558
+ /* Secondary CPUs start in PSCI powered-down state */
559
+ object_property_set_bool(o, true,
560
+ "start-powered-off", &error_abort);
211
+ }
561
+ }
212
+ if (rlen == 4) {
562
+
213
+ s->rsp[0] = RWORD(0);
563
+ object_property_set_bool(o, true, "realized", &error_abort);
214
+ s->rsp[1] = s->rsp[2] = s->rsp[3] = 0;
564
+ }
215
+ } else {
565
+
216
+ s->rsp[0] = RWORD(12);
566
+ /*
217
+ s->rsp[1] = RWORD(8);
567
+ * A7MPCORE
218
+ s->rsp[2] = RWORD(4);
568
+ */
219
+ s->rsp[3] = RWORD(0);
569
+ object_property_set_int(OBJECT(&s->a7mpcore), smp_cpus, "num-cpu",
220
+ }
570
+ &error_abort);
221
+#undef RWORD
571
+ object_property_set_int(OBJECT(&s->a7mpcore),
222
+ }
572
+ FSL_IMX6UL_MAX_IRQ + GIC_INTERNAL,
223
+ return;
573
+ "num-irq", &error_abort);
224
+
574
+ object_property_set_bool(OBJECT(&s->a7mpcore), true, "realized",
225
+error:
575
+ &error_abort);
226
+ s->cmd |= SDCMD_FAIL_FLAG;
576
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->a7mpcore), 0, FSL_IMX6UL_A7MPCORE_ADDR);
227
+ s->status |= SDHSTS_CMD_TIME_OUT;
577
+
578
+ for (i = 0; i < smp_cpus; i++) {
579
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->a7mpcore);
580
+ DeviceState *d = DEVICE(qemu_get_cpu(i));
581
+
582
+ irq = qdev_get_gpio_in(d, ARM_CPU_IRQ);
583
+ sysbus_connect_irq(sbd, i, irq);
584
+ sysbus_connect_irq(sbd, i + smp_cpus, qdev_get_gpio_in(d, ARM_CPU_FIQ));
585
+ }
586
+
587
+ /*
588
+ * A7MPCORE DAP
589
+ */
590
+ create_unimplemented_device("a7mpcore-dap", FSL_IMX6UL_A7MPCORE_DAP_ADDR,
591
+ 0x100000);
592
+
593
+ /*
594
+ * GPT 1, 2
595
+ */
596
+ for (i = 0; i < FSL_IMX6UL_NUM_GPTS; i++) {
597
+ static const hwaddr FSL_IMX6UL_GPTn_ADDR[FSL_IMX6UL_NUM_GPTS] = {
598
+ FSL_IMX6UL_GPT1_ADDR,
599
+ FSL_IMX6UL_GPT2_ADDR,
600
+ };
601
+
602
+ static const int FSL_IMX6UL_GPTn_IRQ[FSL_IMX6UL_NUM_GPTS] = {
603
+ FSL_IMX6UL_GPT1_IRQ,
604
+ FSL_IMX6UL_GPT2_IRQ,
605
+ };
606
+
607
+ s->gpt[i].ccm = IMX_CCM(&s->ccm);
608
+ object_property_set_bool(OBJECT(&s->gpt[i]), true, "realized",
609
+ &error_abort);
610
+
611
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0,
612
+ FSL_IMX6UL_GPTn_ADDR[i]);
613
+
614
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0,
615
+ qdev_get_gpio_in(DEVICE(&s->a7mpcore),
616
+ FSL_IMX6UL_GPTn_IRQ[i]));
617
+ }
618
+
619
+ /*
620
+ * EPIT 1, 2
621
+ */
622
+ for (i = 0; i < FSL_IMX6UL_NUM_EPITS; i++) {
623
+ static const hwaddr FSL_IMX6UL_EPITn_ADDR[FSL_IMX6UL_NUM_EPITS] = {
624
+ FSL_IMX6UL_EPIT1_ADDR,
625
+ FSL_IMX6UL_EPIT2_ADDR,
626
+ };
627
+
628
+ static const int FSL_IMX6UL_EPITn_IRQ[FSL_IMX6UL_NUM_EPITS] = {
629
+ FSL_IMX6UL_EPIT1_IRQ,
630
+ FSL_IMX6UL_EPIT2_IRQ,
631
+ };
632
+
633
+ s->epit[i].ccm = IMX_CCM(&s->ccm);
634
+ object_property_set_bool(OBJECT(&s->epit[i]), true, "realized",
635
+ &error_abort);
636
+
637
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->epit[i]), 0,
638
+ FSL_IMX6UL_EPITn_ADDR[i]);
639
+
640
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->epit[i]), 0,
641
+ qdev_get_gpio_in(DEVICE(&s->a7mpcore),
642
+ FSL_IMX6UL_EPITn_IRQ[i]));
643
+ }
644
+
645
+ /*
646
+ * GPIO
647
+ */
648
+ for (i = 0; i < FSL_IMX6UL_NUM_GPIOS; i++) {
649
+ static const hwaddr FSL_IMX6UL_GPIOn_ADDR[FSL_IMX6UL_NUM_GPIOS] = {
650
+ FSL_IMX6UL_GPIO1_ADDR,
651
+ FSL_IMX6UL_GPIO2_ADDR,
652
+ FSL_IMX6UL_GPIO3_ADDR,
653
+ FSL_IMX6UL_GPIO4_ADDR,
654
+ FSL_IMX6UL_GPIO5_ADDR,
655
+ };
656
+
657
+ static const int FSL_IMX6UL_GPIOn_LOW_IRQ[FSL_IMX6UL_NUM_GPIOS] = {
658
+ FSL_IMX6UL_GPIO1_LOW_IRQ,
659
+ FSL_IMX6UL_GPIO2_LOW_IRQ,
660
+ FSL_IMX6UL_GPIO3_LOW_IRQ,
661
+ FSL_IMX6UL_GPIO4_LOW_IRQ,
662
+ FSL_IMX6UL_GPIO5_LOW_IRQ,
663
+ };
664
+
665
+ static const int FSL_IMX6UL_GPIOn_HIGH_IRQ[FSL_IMX6UL_NUM_GPIOS] = {
666
+ FSL_IMX6UL_GPIO1_HIGH_IRQ,
667
+ FSL_IMX6UL_GPIO2_HIGH_IRQ,
668
+ FSL_IMX6UL_GPIO3_HIGH_IRQ,
669
+ FSL_IMX6UL_GPIO4_HIGH_IRQ,
670
+ FSL_IMX6UL_GPIO5_HIGH_IRQ,
671
+ };
672
+
673
+ object_property_set_bool(OBJECT(&s->gpio[i]), true, "realized",
674
+ &error_abort);
675
+
676
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0,
677
+ FSL_IMX6UL_GPIOn_ADDR[i]);
678
+
679
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 0,
680
+ qdev_get_gpio_in(DEVICE(&s->a7mpcore),
681
+ FSL_IMX6UL_GPIOn_LOW_IRQ[i]));
682
+
683
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 1,
684
+ qdev_get_gpio_in(DEVICE(&s->a7mpcore),
685
+ FSL_IMX6UL_GPIOn_HIGH_IRQ[i]));
686
+ }
687
+
688
+ /*
689
+ * IOMUXC and IOMUXC_GPR
690
+ */
691
+ for (i = 0; i < 1; i++) {
692
+ static const hwaddr FSL_IMX6UL_IOMUXCn_ADDR[FSL_IMX6UL_NUM_IOMUXCS] = {
693
+ FSL_IMX6UL_IOMUXC_ADDR,
694
+ FSL_IMX6UL_IOMUXC_GPR_ADDR,
695
+ };
696
+
697
+ snprintf(name, NAME_SIZE, "iomuxc%d", i);
698
+ create_unimplemented_device(name, FSL_IMX6UL_IOMUXCn_ADDR[i], 0x4000);
699
+ }
700
+
701
+ /*
702
+ * CCM
703
+ */
704
+ object_property_set_bool(OBJECT(&s->ccm), true, "realized", &error_abort);
705
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, FSL_IMX6UL_CCM_ADDR);
706
+
707
+ /*
708
+ * SRC
709
+ */
710
+ object_property_set_bool(OBJECT(&s->src), true, "realized", &error_abort);
711
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->src), 0, FSL_IMX6UL_SRC_ADDR);
712
+
713
+ /*
714
+ * GPCv2
715
+ */
716
+ object_property_set_bool(OBJECT(&s->gpcv2), true,
717
+ "realized", &error_abort);
718
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpcv2), 0, FSL_IMX6UL_GPC_ADDR);
719
+
720
+ /* Initialize all ECSPI */
721
+ for (i = 0; i < FSL_IMX6UL_NUM_ECSPIS; i++) {
722
+ static const hwaddr FSL_IMX6UL_SPIn_ADDR[FSL_IMX6UL_NUM_ECSPIS] = {
723
+ FSL_IMX6UL_ECSPI1_ADDR,
724
+ FSL_IMX6UL_ECSPI2_ADDR,
725
+ FSL_IMX6UL_ECSPI3_ADDR,
726
+ FSL_IMX6UL_ECSPI4_ADDR,
727
+ };
728
+
729
+ static const int FSL_IMX6UL_SPIn_IRQ[FSL_IMX6UL_NUM_ECSPIS] = {
730
+ FSL_IMX6UL_ECSPI1_IRQ,
731
+ FSL_IMX6UL_ECSPI2_IRQ,
732
+ FSL_IMX6UL_ECSPI3_IRQ,
733
+ FSL_IMX6UL_ECSPI4_IRQ,
734
+ };
735
+
736
+ /* Initialize the SPI */
737
+ object_property_set_bool(OBJECT(&s->spi[i]), true, "realized",
738
+ &error_abort);
739
+
740
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0,
741
+ FSL_IMX6UL_SPIn_ADDR[i]);
742
+
743
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0,
744
+ qdev_get_gpio_in(DEVICE(&s->a7mpcore),
745
+ FSL_IMX6UL_SPIn_IRQ[i]));
746
+ }
747
+
748
+ /*
749
+ * I2C
750
+ */
751
+ for (i = 0; i < FSL_IMX6UL_NUM_I2CS; i++) {
752
+ static const hwaddr FSL_IMX6UL_I2Cn_ADDR[FSL_IMX6UL_NUM_I2CS] = {
753
+ FSL_IMX6UL_I2C1_ADDR,
754
+ FSL_IMX6UL_I2C2_ADDR,
755
+ FSL_IMX6UL_I2C3_ADDR,
756
+ FSL_IMX6UL_I2C4_ADDR,
757
+ };
758
+
759
+ static const int FSL_IMX6UL_I2Cn_IRQ[FSL_IMX6UL_NUM_I2CS] = {
760
+ FSL_IMX6UL_I2C1_IRQ,
761
+ FSL_IMX6UL_I2C2_IRQ,
762
+ FSL_IMX6UL_I2C3_IRQ,
763
+ FSL_IMX6UL_I2C4_IRQ,
764
+ };
765
+
766
+ object_property_set_bool(OBJECT(&s->i2c[i]), true, "realized",
767
+ &error_abort);
768
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, FSL_IMX6UL_I2Cn_ADDR[i]);
769
+
770
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0,
771
+ qdev_get_gpio_in(DEVICE(&s->a7mpcore),
772
+ FSL_IMX6UL_I2Cn_IRQ[i]));
773
+ }
774
+
775
+ /*
776
+ * UART
777
+ */
778
+ for (i = 0; i < FSL_IMX6UL_NUM_UARTS; i++) {
779
+ static const hwaddr FSL_IMX6UL_UARTn_ADDR[FSL_IMX6UL_NUM_UARTS] = {
780
+ FSL_IMX6UL_UART1_ADDR,
781
+ FSL_IMX6UL_UART2_ADDR,
782
+ FSL_IMX6UL_UART3_ADDR,
783
+ FSL_IMX6UL_UART4_ADDR,
784
+ FSL_IMX6UL_UART5_ADDR,
785
+ FSL_IMX6UL_UART6_ADDR,
786
+ FSL_IMX6UL_UART7_ADDR,
787
+ FSL_IMX6UL_UART8_ADDR,
788
+ };
789
+
790
+ static const int FSL_IMX6UL_UARTn_IRQ[FSL_IMX6UL_NUM_UARTS] = {
791
+ FSL_IMX6UL_UART1_IRQ,
792
+ FSL_IMX6UL_UART2_IRQ,
793
+ FSL_IMX6UL_UART3_IRQ,
794
+ FSL_IMX6UL_UART4_IRQ,
795
+ FSL_IMX6UL_UART5_IRQ,
796
+ FSL_IMX6UL_UART6_IRQ,
797
+ FSL_IMX6UL_UART7_IRQ,
798
+ FSL_IMX6UL_UART8_IRQ,
799
+ };
800
+
801
+ qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i));
802
+
803
+ object_property_set_bool(OBJECT(&s->uart[i]), true, "realized",
804
+ &error_abort);
805
+
806
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0,
807
+ FSL_IMX6UL_UARTn_ADDR[i]);
808
+
809
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
810
+ qdev_get_gpio_in(DEVICE(&s->a7mpcore),
811
+ FSL_IMX6UL_UARTn_IRQ[i]));
812
+ }
813
+
814
+ /*
815
+ * Ethernet
816
+ */
817
+ for (i = 0; i < FSL_IMX6UL_NUM_ETHS; i++) {
818
+ static const hwaddr FSL_IMX6UL_ENETn_ADDR[FSL_IMX6UL_NUM_ETHS] = {
819
+ FSL_IMX6UL_ENET1_ADDR,
820
+ FSL_IMX6UL_ENET2_ADDR,
821
+ };
822
+
823
+ static const int FSL_IMX6UL_ENETn_IRQ[FSL_IMX6UL_NUM_ETHS] = {
824
+ FSL_IMX6UL_ENET1_IRQ,
825
+ FSL_IMX6UL_ENET2_IRQ,
826
+ };
827
+
828
+ static const int FSL_IMX6UL_ENETn_TIMER_IRQ[FSL_IMX6UL_NUM_ETHS] = {
829
+ FSL_IMX6UL_ENET1_TIMER_IRQ,
830
+ FSL_IMX6UL_ENET2_TIMER_IRQ,
831
+ };
832
+
833
+ object_property_set_uint(OBJECT(&s->eth[i]),
834
+ FSL_IMX6UL_ETH_NUM_TX_RINGS,
835
+ "tx-ring-num", &error_abort);
836
+ qdev_set_nic_properties(DEVICE(&s->eth[i]), &nd_table[i]);
837
+ object_property_set_bool(OBJECT(&s->eth[i]), true, "realized",
838
+ &error_abort);
839
+
840
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->eth[i]), 0,
841
+ FSL_IMX6UL_ENETn_ADDR[i]);
842
+
843
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->eth[i]), 0,
844
+ qdev_get_gpio_in(DEVICE(&s->a7mpcore),
845
+ FSL_IMX6UL_ENETn_IRQ[i]));
846
+
847
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->eth[i]), 1,
848
+ qdev_get_gpio_in(DEVICE(&s->a7mpcore),
849
+ FSL_IMX6UL_ENETn_TIMER_IRQ[i]));
850
+ }
851
+
852
+ /*
853
+ * USDHC
854
+ */
855
+ for (i = 0; i < FSL_IMX6UL_NUM_USDHCS; i++) {
856
+ static const hwaddr FSL_IMX6UL_USDHCn_ADDR[FSL_IMX6UL_NUM_USDHCS] = {
857
+ FSL_IMX6UL_USDHC1_ADDR,
858
+ FSL_IMX6UL_USDHC2_ADDR,
859
+ };
860
+
861
+ static const int FSL_IMX6UL_USDHCn_IRQ[FSL_IMX6UL_NUM_USDHCS] = {
862
+ FSL_IMX6UL_USDHC1_IRQ,
863
+ FSL_IMX6UL_USDHC2_IRQ,
864
+ };
865
+
866
+ object_property_set_bool(OBJECT(&s->usdhc[i]), true, "realized",
867
+ &error_abort);
868
+
869
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->usdhc[i]), 0,
870
+ FSL_IMX6UL_USDHCn_ADDR[i]);
871
+
872
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->usdhc[i]), 0,
873
+ qdev_get_gpio_in(DEVICE(&s->a7mpcore),
874
+ FSL_IMX6UL_USDHCn_IRQ[i]));
875
+ }
876
+
877
+ /*
878
+ * SNVS
879
+ */
880
+ object_property_set_bool(OBJECT(&s->snvs), true, "realized", &error_abort);
881
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0, FSL_IMX6UL_SNVS_HP_ADDR);
882
+
883
+ /*
884
+ * Watchdog
885
+ */
886
+ for (i = 0; i < FSL_IMX6UL_NUM_WDTS; i++) {
887
+ static const hwaddr FSL_IMX6UL_WDOGn_ADDR[FSL_IMX6UL_NUM_WDTS] = {
888
+ FSL_IMX6UL_WDOG1_ADDR,
889
+ FSL_IMX6UL_WDOG2_ADDR,
890
+ FSL_IMX6UL_WDOG3_ADDR,
891
+ };
892
+
893
+ object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized",
894
+ &error_abort);
895
+
896
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0,
897
+ FSL_IMX6UL_WDOGn_ADDR[i]);
898
+ }
899
+
900
+ /*
901
+ * GPR
902
+ */
903
+ object_property_set_bool(OBJECT(&s->gpr), true, "realized",
904
+ &error_abort);
905
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpr), 0, FSL_IMX6UL_IOMUXC_GPR_ADDR);
906
+
907
+ /*
908
+ * SDMA
909
+ */
910
+ create_unimplemented_device("sdma", FSL_IMX6UL_SDMA_ADDR, 0x4000);
911
+
912
+ /*
913
+ * APHB_DMA
914
+ */
915
+ create_unimplemented_device("aphb_dma", FSL_IMX6UL_APBH_DMA_ADDR,
916
+ FSL_IMX6UL_APBH_DMA_SIZE);
917
+
918
+ /*
919
+ * ADCs
920
+ */
921
+ for (i = 0; i < FSL_IMX6UL_NUM_ADCS; i++) {
922
+ static const hwaddr FSL_IMX6UL_ADCn_ADDR[FSL_IMX6UL_NUM_ADCS] = {
923
+ FSL_IMX6UL_ADC1_ADDR,
924
+ FSL_IMX6UL_ADC2_ADDR,
925
+ };
926
+
927
+ snprintf(name, NAME_SIZE, "adc%d", i);
928
+ create_unimplemented_device(name, FSL_IMX6UL_ADCn_ADDR[i], 0x4000);
929
+ }
930
+
931
+ /*
932
+ * LCD
933
+ */
934
+ create_unimplemented_device("lcdif", FSL_IMX6UL_LCDIF_ADDR, 0x4000);
935
+
936
+ /*
937
+ * ROM memory
938
+ */
939
+ memory_region_init_rom(&s->rom, NULL, "imx6ul.rom",
940
+ FSL_IMX6UL_ROM_SIZE, &error_abort);
941
+ memory_region_add_subregion(get_system_memory(), FSL_IMX6UL_ROM_ADDR,
942
+ &s->rom);
943
+
944
+ /*
945
+ * CAAM memory
946
+ */
947
+ memory_region_init_rom(&s->caam, NULL, "imx6ul.caam",
948
+ FSL_IMX6UL_CAAM_MEM_SIZE, &error_abort);
949
+ memory_region_add_subregion(get_system_memory(), FSL_IMX6UL_CAAM_MEM_ADDR,
950
+ &s->caam);
951
+
952
+ /*
953
+ * OCRAM memory
954
+ */
955
+ memory_region_init_ram(&s->ocram, NULL, "imx6ul.ocram",
956
+ FSL_IMX6UL_OCRAM_MEM_SIZE,
957
+ &error_abort);
958
+ memory_region_add_subregion(get_system_memory(), FSL_IMX6UL_OCRAM_MEM_ADDR,
959
+ &s->ocram);
960
+
961
+ /*
962
+ * internal OCRAM (128 KB) is aliased over 512 KB
963
+ */
964
+ memory_region_init_alias(&s->ocram_alias, NULL, "imx6ul.ocram_alias",
965
+ &s->ocram, 0, FSL_IMX6UL_OCRAM_ALIAS_SIZE);
966
+ memory_region_add_subregion(get_system_memory(),
967
+ FSL_IMX6UL_OCRAM_ALIAS_ADDR, &s->ocram_alias);
228
+}
968
+}
229
+
969
+
230
+static void bcm2835_sdhost_fifo_push(BCM2835SDHostState *s, uint32_t value)
970
+static void fsl_imx6ul_class_init(ObjectClass *oc, void *data)
231
+{
971
+{
232
+ int n;
972
+ DeviceClass *dc = DEVICE_CLASS(oc);
233
+
973
+
234
+ if (s->fifo_len == BCM2835_SDHOST_FIFO_LEN) {
974
+ dc->realize = fsl_imx6ul_realize;
235
+ /* FIFO overflow */
975
+ dc->desc = "i.MX6UL SOC";
236
+ return;
976
+ /* Reason: Uses serial_hds and nd_table in realize() directly */
237
+ }
977
+ dc->user_creatable = false;
238
+ n = (s->fifo_pos + s->fifo_len) & (BCM2835_SDHOST_FIFO_LEN - 1);
239
+ s->fifo_len++;
240
+ s->fifo[n] = value;
241
+}
978
+}
242
+
979
+
243
+static uint32_t bcm2835_sdhost_fifo_pop(BCM2835SDHostState *s)
980
+static const TypeInfo fsl_imx6ul_type_info = {
981
+ .name = TYPE_FSL_IMX6UL,
982
+ .parent = TYPE_DEVICE,
983
+ .instance_size = sizeof(FslIMX6ULState),
984
+ .instance_init = fsl_imx6ul_init,
985
+ .class_init = fsl_imx6ul_class_init,
986
+};
987
+
988
+static void fsl_imx6ul_register_types(void)
244
+{
989
+{
245
+ uint32_t value;
990
+ type_register_static(&fsl_imx6ul_type_info);
246
+
247
+ if (s->fifo_len == 0) {
248
+ /* FIFO underflow */
249
+ return 0;
250
+ }
251
+ value = s->fifo[s->fifo_pos];
252
+ s->fifo_len--;
253
+ s->fifo_pos = (s->fifo_pos + 1) & (BCM2835_SDHOST_FIFO_LEN - 1);
254
+ return value;
255
+}
991
+}
256
+
992
+type_init(fsl_imx6ul_register_types)
257
+static void bcm2835_sdhost_fifo_run(BCM2835SDHostState *s)
993
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
258
+{
994
index XXXXXXX..XXXXXXX 100644
259
+ uint32_t value = 0;
995
--- a/default-configs/arm-softmmu.mak
260
+ int n;
996
+++ b/default-configs/arm-softmmu.mak
261
+ int is_read;
997
@@ -XXX,XX +XXX,XX @@ CONFIG_FSL_IMX6=y
262
+
998
CONFIG_FSL_IMX31=y
263
+ is_read = (s->cmd & SDCMD_READ_CMD) != 0;
999
CONFIG_FSL_IMX25=y
264
+ if (s->datacnt != 0 && (!is_read || sdbus_data_ready(&s->sdbus))) {
1000
CONFIG_FSL_IMX7=y
265
+ if (is_read) {
1001
+CONFIG_FSL_IMX6UL=y
266
+ n = 0;
1002
267
+ while (s->datacnt && s->fifo_len < BCM2835_SDHOST_FIFO_LEN) {
1003
CONFIG_IMX_I2C=y
268
+ value |= (uint32_t)sdbus_read_data(&s->sdbus) << (n * 8);
1004
269
+ s->datacnt--;
270
+ n++;
271
+ if (n == 4) {
272
+ bcm2835_sdhost_fifo_push(s, value);
273
+ n = 0;
274
+ value = 0;
275
+ }
276
+ }
277
+ if (n != 0) {
278
+ bcm2835_sdhost_fifo_push(s, value);
279
+ }
280
+ } else { /* write */
281
+ n = 0;
282
+ while (s->datacnt > 0 && (s->fifo_len > 0 || n > 0)) {
283
+ if (n == 0) {
284
+ value = bcm2835_sdhost_fifo_pop(s);
285
+ n = 4;
286
+ }
287
+ n--;
288
+ s->datacnt--;
289
+ sdbus_write_data(&s->sdbus, value & 0xff);
290
+ value >>= 8;
291
+ }
292
+ }
293
+ }
294
+ if (s->datacnt == 0) {
295
+ s->status |= SDHSTS_DATA_FLAG;
296
+
297
+ s->edm &= ~0xf;
298
+ s->edm |= SDEDM_FSM_DATAMODE;
299
+
300
+ if (s->config & SDHCFG_DATA_IRPT_EN) {
301
+ s->status |= SDHSTS_SDIO_IRPT;
302
+ }
303
+
304
+ if ((s->cmd & SDCMD_BUSYWAIT) && (s->config & SDHCFG_BUSY_IRPT_EN)) {
305
+ s->status |= SDHSTS_BUSY_IRPT;
306
+ }
307
+
308
+ if ((s->cmd & SDCMD_WRITE_CMD) && (s->config & SDHCFG_BLOCK_IRPT_EN)) {
309
+ s->status |= SDHSTS_BLOCK_IRPT;
310
+ }
311
+
312
+ bcm2835_sdhost_update_irq(s);
313
+ }
314
+
315
+ s->edm &= ~(0x1f << 4);
316
+ s->edm |= ((s->fifo_len & 0x1f) << 4);
317
+}
318
+
319
+static uint64_t bcm2835_sdhost_read(void *opaque, hwaddr offset,
320
+ unsigned size)
321
+{
322
+ BCM2835SDHostState *s = (BCM2835SDHostState *)opaque;
323
+ uint32_t res = 0;
324
+
325
+ switch (offset) {
326
+ case SDCMD:
327
+ res = s->cmd;
328
+ break;
329
+ case SDHSTS:
330
+ res = s->status;
331
+ break;
332
+ case SDRSP0:
333
+ res = s->rsp[0];
334
+ break;
335
+ case SDRSP1:
336
+ res = s->rsp[1];
337
+ break;
338
+ case SDRSP2:
339
+ res = s->rsp[2];
340
+ break;
341
+ case SDRSP3:
342
+ res = s->rsp[3];
343
+ break;
344
+ case SDEDM:
345
+ res = s->edm;
346
+ break;
347
+ case SDVDD:
348
+ res = s->vdd;
349
+ break;
350
+ case SDDATA:
351
+ res = bcm2835_sdhost_fifo_pop(s);
352
+ bcm2835_sdhost_fifo_run(s);
353
+ break;
354
+ case SDHBCT:
355
+ res = s->hbct;
356
+ break;
357
+ case SDHBLC:
358
+ res = s->hblc;
359
+ break;
360
+
361
+ default:
362
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
363
+ __func__, offset);
364
+ res = 0;
365
+ break;
366
+ }
367
+
368
+ return res;
369
+}
370
+
371
+static void bcm2835_sdhost_write(void *opaque, hwaddr offset,
372
+ uint64_t value, unsigned size)
373
+{
374
+ BCM2835SDHostState *s = (BCM2835SDHostState *)opaque;
375
+
376
+ switch (offset) {
377
+ case SDCMD:
378
+ s->cmd = value;
379
+ if (value & SDCMD_NEW_FLAG) {
380
+ bcm2835_sdhost_send_command(s);
381
+ bcm2835_sdhost_fifo_run(s);
382
+ s->cmd &= ~SDCMD_NEW_FLAG;
383
+ }
384
+ break;
385
+ case SDTOUT:
386
+ break;
387
+ case SDCDIV:
388
+ break;
389
+ case SDHSTS:
390
+ s->status &= ~value;
391
+ bcm2835_sdhost_update_irq(s);
392
+ break;
393
+ case SDARG:
394
+ s->cmdarg = value;
395
+ break;
396
+ case SDEDM:
397
+ if ((value & 0xf) == 0xf) {
398
+ /* power down */
399
+ value &= ~0xf;
400
+ }
401
+ s->edm = value;
402
+ break;
403
+ case SDHCFG:
404
+ s->config = value;
405
+ bcm2835_sdhost_fifo_run(s);
406
+ break;
407
+ case SDVDD:
408
+ s->vdd = value;
409
+ break;
410
+ case SDDATA:
411
+ bcm2835_sdhost_fifo_push(s, value);
412
+ bcm2835_sdhost_fifo_run(s);
413
+ break;
414
+ case SDHBCT:
415
+ s->hbct = value;
416
+ break;
417
+ case SDHBLC:
418
+ s->hblc = value;
419
+ s->datacnt = s->hblc * s->hbct;
420
+ bcm2835_sdhost_fifo_run(s);
421
+ break;
422
+
423
+ default:
424
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
425
+ __func__, offset);
426
+ break;
427
+ }
428
+}
429
+
430
+static const MemoryRegionOps bcm2835_sdhost_ops = {
431
+ .read = bcm2835_sdhost_read,
432
+ .write = bcm2835_sdhost_write,
433
+ .endianness = DEVICE_NATIVE_ENDIAN,
434
+};
435
+
436
+static const VMStateDescription vmstate_bcm2835_sdhost = {
437
+ .name = TYPE_BCM2835_SDHOST,
438
+ .version_id = 1,
439
+ .minimum_version_id = 1,
440
+ .fields = (VMStateField[]) {
441
+ VMSTATE_UINT32(cmd, BCM2835SDHostState),
442
+ VMSTATE_UINT32(cmdarg, BCM2835SDHostState),
443
+ VMSTATE_UINT32(status, BCM2835SDHostState),
444
+ VMSTATE_UINT32_ARRAY(rsp, BCM2835SDHostState, 4),
445
+ VMSTATE_UINT32(config, BCM2835SDHostState),
446
+ VMSTATE_UINT32(edm, BCM2835SDHostState),
447
+ VMSTATE_UINT32(vdd, BCM2835SDHostState),
448
+ VMSTATE_UINT32(hbct, BCM2835SDHostState),
449
+ VMSTATE_UINT32(hblc, BCM2835SDHostState),
450
+ VMSTATE_INT32(fifo_pos, BCM2835SDHostState),
451
+ VMSTATE_INT32(fifo_len, BCM2835SDHostState),
452
+ VMSTATE_UINT32_ARRAY(fifo, BCM2835SDHostState, BCM2835_SDHOST_FIFO_LEN),
453
+ VMSTATE_UINT32(datacnt, BCM2835SDHostState),
454
+ VMSTATE_END_OF_LIST()
455
+ }
456
+};
457
+
458
+static void bcm2835_sdhost_init(Object *obj)
459
+{
460
+ BCM2835SDHostState *s = BCM2835_SDHOST(obj);
461
+
462
+ qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
463
+ TYPE_BCM2835_SDHOST_BUS, DEVICE(s), "sd-bus");
464
+
465
+ memory_region_init_io(&s->iomem, obj, &bcm2835_sdhost_ops, s,
466
+ TYPE_BCM2835_SDHOST, 0x1000);
467
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
468
+ sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
469
+}
470
+
471
+static void bcm2835_sdhost_reset(DeviceState *dev)
472
+{
473
+ BCM2835SDHostState *s = BCM2835_SDHOST(dev);
474
+
475
+ s->cmd = 0;
476
+ s->cmdarg = 0;
477
+ s->edm = 0x0000c60f;
478
+ s->config = 0;
479
+ s->hbct = 0;
480
+ s->hblc = 0;
481
+ s->datacnt = 0;
482
+ s->fifo_pos = 0;
483
+ s->fifo_len = 0;
484
+}
485
+
486
+static void bcm2835_sdhost_class_init(ObjectClass *klass, void *data)
487
+{
488
+ DeviceClass *dc = DEVICE_CLASS(klass);
489
+
490
+ dc->reset = bcm2835_sdhost_reset;
491
+ dc->vmsd = &vmstate_bcm2835_sdhost;
492
+}
493
+
494
+static TypeInfo bcm2835_sdhost_info = {
495
+ .name = TYPE_BCM2835_SDHOST,
496
+ .parent = TYPE_SYS_BUS_DEVICE,
497
+ .instance_size = sizeof(BCM2835SDHostState),
498
+ .class_init = bcm2835_sdhost_class_init,
499
+ .instance_init = bcm2835_sdhost_init,
500
+};
501
+
502
+static const TypeInfo bcm2835_sdhost_bus_info = {
503
+ .name = TYPE_BCM2835_SDHOST_BUS,
504
+ .parent = TYPE_SD_BUS,
505
+ .instance_size = sizeof(SDBus),
506
+};
507
+
508
+static void bcm2835_sdhost_register_types(void)
509
+{
510
+ type_register_static(&bcm2835_sdhost_info);
511
+ type_register_static(&bcm2835_sdhost_bus_info);
512
+}
513
+
514
+type_init(bcm2835_sdhost_register_types)
515
--
1005
--
516
2.7.4
1006
2.18.0
517
1007
518
1008
diff view generated by jsdifflib
1
From: Krzysztof Kozlowski <krzk@kernel.org>
1
From: Jean-Christophe Dubois <jcd@tribudubois.net>
2
2
3
Without any clock controller, the Linux kernel was hitting division by
3
Tested by booting linux 4.18 (built using imx_v6_v7_defconfig) on the
4
zero during boot or with clk_summary:
4
emulated board.
5
[ 0.000000] [<c031054c>] (unwind_backtrace) from [<c030ba6c>] (show_stack+0x10/0x14)
6
[ 0.000000] [<c030ba6c>] (show_stack) from [<c05b2660>] (dump_stack+0x88/0x9c)
7
[ 0.000000] [<c05b2660>] (dump_stack) from [<c05b11a4>] (Ldiv0+0x8/0x10)
8
[ 0.000000] [<c05b11a4>] (Ldiv0) from [<c06ad1e0>] (samsung_pll45xx_recalc_rate+0x58/0x74)
9
[ 0.000000] [<c06ad1e0>] (samsung_pll45xx_recalc_rate) from [<c0692ec0>] (clk_register+0x39c/0x63c)
10
[ 0.000000] [<c0692ec0>] (clk_register) from [<c125d360>] (samsung_clk_register_pll+0x2e0/0x3d4)
11
[ 0.000000] [<c125d360>] (samsung_clk_register_pll) from [<c125d7e8>] (exynos4_clk_init+0x1b0/0x5e4)
12
[ 0.000000] [<c125d7e8>] (exynos4_clk_init) from [<c12335f4>] (of_clk_init+0x17c/0x210)
13
[ 0.000000] [<c12335f4>] (of_clk_init) from [<c1204700>] (time_init+0x24/0x2c)
14
[ 0.000000] [<c1204700>] (time_init) from [<c1200b2c>] (start_kernel+0x24c/0x38c)
15
[ 0.000000] [<c1200b2c>] (start_kernel) from [<4020807c>] (0x4020807c)
16
5
17
Provide stub for clock controller returning reset values for PLLs.
6
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
18
7
Message-id: 3f8eb4300206634dc01e04b12f65b73c0ad2f955.1532984236.git.jcd@tribudubois.net
19
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
20
Message-id: 20170226200142.31169-1-krzk@kernel.org
21
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
10
---
24
hw/misc/Makefile.objs | 2 +-
11
hw/arm/Makefile.objs | 2 +-
25
hw/arm/exynos4210.c | 6 ++
12
hw/arm/mcimx6ul-evk.c | 85 +++++++++++++++++++++++++++++++++++++++++++
26
hw/misc/exynos4210_clk.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++
13
2 files changed, 86 insertions(+), 1 deletion(-)
27
3 files changed, 171 insertions(+), 1 deletion(-)
14
create mode 100644 hw/arm/mcimx6ul-evk.c
28
create mode 100644 hw/misc/exynos4210_clk.c
29
15
30
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
16
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
31
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/misc/Makefile.objs
18
--- a/hw/arm/Makefile.objs
33
+++ b/hw/misc/Makefile.objs
19
+++ b/hw/arm/Makefile.objs
34
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_IVSHMEM) += ivshmem.o
20
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
35
obj-$(CONFIG_REALVIEW) += arm_sysctl.o
21
obj-$(CONFIG_IOTKIT) += iotkit.o
36
obj-$(CONFIG_NSERIES) += cbus.o
22
obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
37
obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
23
obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmuv3.o
38
-obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o
24
-obj-$(CONFIG_FSL_IMX6UL) += fsl-imx6ul.o
39
+obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o exynos4210_clk.o
25
+obj-$(CONFIG_FSL_IMX6UL) += fsl-imx6ul.o mcimx6ul-evk.o
40
obj-$(CONFIG_IMX) += imx_ccm.o
26
diff --git a/hw/arm/mcimx6ul-evk.c b/hw/arm/mcimx6ul-evk.c
41
obj-$(CONFIG_IMX) += imx31_ccm.o
42
obj-$(CONFIG_IMX) += imx25_ccm.o
43
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/arm/exynos4210.c
46
+++ b/hw/arm/exynos4210.c
47
@@ -XXX,XX +XXX,XX @@
48
#include "qemu/osdep.h"
49
#include "qapi/error.h"
50
#include "qemu-common.h"
51
+#include "qemu/log.h"
52
#include "cpu.h"
53
#include "hw/boards.h"
54
#include "sysemu/sysemu.h"
55
@@ -XXX,XX +XXX,XX @@
56
/* PMU SFR base address */
57
#define EXYNOS4210_PMU_BASE_ADDR 0x10020000
58
59
+/* Clock controller SFR base address */
60
+#define EXYNOS4210_CLK_BASE_ADDR 0x10030000
61
+
62
/* Display controllers (FIMD) */
63
#define EXYNOS4210_FIMD0_BASE_ADDR 0x11C00000
64
65
@@ -XXX,XX +XXX,XX @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
66
*/
67
sysbus_create_simple("exynos4210.pmu", EXYNOS4210_PMU_BASE_ADDR, NULL);
68
69
+ sysbus_create_simple("exynos4210.clk", EXYNOS4210_CLK_BASE_ADDR, NULL);
70
+
71
/* PWM */
72
sysbus_create_varargs("exynos4210.pwm", EXYNOS4210_PWM_BASE_ADDR,
73
s->irq_table[exynos4210_get_irq(22, 0)],
74
diff --git a/hw/misc/exynos4210_clk.c b/hw/misc/exynos4210_clk.c
75
new file mode 100644
27
new file mode 100644
76
index XXXXXXX..XXXXXXX
28
index XXXXXXX..XXXXXXX
77
--- /dev/null
29
--- /dev/null
78
+++ b/hw/misc/exynos4210_clk.c
30
+++ b/hw/arm/mcimx6ul-evk.c
79
@@ -XXX,XX +XXX,XX @@
31
@@ -XXX,XX +XXX,XX @@
80
+/*
32
+/*
81
+ * Exynos4210 Clock Controller Emulation
33
+ * Copyright (c) 2018 Jean-Christophe Dubois <jcd@tribudubois.net>
82
+ *
34
+ *
83
+ * Copyright (c) 2017 Krzysztof Kozlowski <krzk@kernel.org>
35
+ * MCIMX6UL_EVK Board System emulation.
84
+ *
36
+ *
85
+ * This program is free software; you can redistribute it and/or modify it
37
+ * This code is licensed under the GPL, version 2 or later.
86
+ * under the terms of the GNU General Public License as published by the
38
+ * See the file `COPYING' in the top level directory.
87
+ * Free Software Foundation; either version 2 of the License, or
88
+ * (at your option) any later version.
89
+ *
39
+ *
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
40
+ * It (partially) emulates a mcimx6ul_evk board, with a Freescale
91
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
41
+ * i.MX6ul SoC
92
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
93
+ * for more details.
94
+ *
95
+ * You should have received a copy of the GNU General Public License along
96
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
97
+ */
42
+ */
98
+
43
+
99
+#include "qemu/osdep.h"
44
+#include "qemu/osdep.h"
100
+#include "hw/sysbus.h"
45
+#include "qapi/error.h"
101
+#include "qemu/log.h"
46
+#include "qemu-common.h"
47
+#include "hw/arm/fsl-imx6ul.h"
48
+#include "hw/boards.h"
49
+#include "sysemu/sysemu.h"
50
+#include "qemu/error-report.h"
51
+#include "sysemu/qtest.h"
102
+
52
+
103
+#define TYPE_EXYNOS4210_CLK "exynos4210.clk"
53
+typedef struct {
104
+#define EXYNOS4210_CLK(obj) \
54
+ FslIMX6ULState soc;
105
+ OBJECT_CHECK(Exynos4210ClkState, (obj), TYPE_EXYNOS4210_CLK)
55
+ MemoryRegion ram;
56
+} MCIMX6ULEVK;
106
+
57
+
107
+#define CLK_PLL_LOCKED BIT(29)
58
+static void mcimx6ul_evk_init(MachineState *machine)
59
+{
60
+ static struct arm_boot_info boot_info;
61
+ MCIMX6ULEVK *s = g_new0(MCIMX6ULEVK, 1);
62
+ int i;
108
+
63
+
109
+#define EXYNOS4210_CLK_REGS_MEM_SIZE 0x15104
64
+ if (machine->ram_size > FSL_IMX6UL_MMDC_SIZE) {
65
+ error_report("RAM size " RAM_ADDR_FMT " above max supported (%08x)",
66
+ machine->ram_size, FSL_IMX6UL_MMDC_SIZE);
67
+ exit(1);
68
+ }
110
+
69
+
111
+typedef struct Exynos4210Reg {
70
+ boot_info = (struct arm_boot_info) {
112
+ const char *name; /* for debug only */
71
+ .loader_start = FSL_IMX6UL_MMDC_ADDR,
113
+ uint32_t offset;
72
+ .board_id = -1,
114
+ uint32_t reset_value;
73
+ .ram_size = machine->ram_size,
115
+} Exynos4210Reg;
74
+ .kernel_filename = machine->kernel_filename,
75
+ .kernel_cmdline = machine->kernel_cmdline,
76
+ .initrd_filename = machine->initrd_filename,
77
+ .nb_cpus = smp_cpus,
78
+ };
116
+
79
+
117
+/* Clock controller register base: 0x10030000 */
80
+ object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc),
118
+static const Exynos4210Reg exynos4210_clk_regs[] = {
81
+ TYPE_FSL_IMX6UL, &error_fatal, NULL);
119
+ {"EPLL_LOCK", 0xc010, 0x00000fff},
120
+ {"VPLL_LOCK", 0xc020, 0x00000fff},
121
+ {"EPLL_CON0", 0xc110, 0x00300301 | CLK_PLL_LOCKED},
122
+ {"EPLL_CON1", 0xc114, 0x00000000},
123
+ {"VPLL_CON0", 0xc120, 0x00240201 | CLK_PLL_LOCKED},
124
+ {"VPLL_CON1", 0xc124, 0x66010464},
125
+ {"APLL_LOCK", 0x14000, 0x00000fff},
126
+ {"MPLL_LOCK", 0x14004, 0x00000fff},
127
+ {"APLL_CON0", 0x14100, 0x00c80601 | CLK_PLL_LOCKED},
128
+ {"APLL_CON1", 0x14104, 0x0000001c},
129
+ {"MPLL_CON0", 0x14108, 0x00c80601 | CLK_PLL_LOCKED},
130
+ {"MPLL_CON1", 0x1410c, 0x0000001c},
131
+};
132
+
82
+
133
+#define EXYNOS4210_REGS_NUM ARRAY_SIZE(exynos4210_clk_regs)
83
+ object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_fatal);
134
+
84
+
135
+typedef struct Exynos4210ClkState {
85
+ memory_region_allocate_system_memory(&s->ram, NULL, "mcimx6ul-evk.ram",
136
+ SysBusDevice parent_obj;
86
+ machine->ram_size);
87
+ memory_region_add_subregion(get_system_memory(),
88
+ FSL_IMX6UL_MMDC_ADDR, &s->ram);
137
+
89
+
138
+ MemoryRegion iomem;
90
+ for (i = 0; i < FSL_IMX6UL_NUM_USDHCS; i++) {
139
+ uint32_t reg[EXYNOS4210_REGS_NUM];
91
+ BusState *bus;
140
+} Exynos4210ClkState;
92
+ DeviceState *carddev;
93
+ DriveInfo *di;
94
+ BlockBackend *blk;
141
+
95
+
142
+static uint64_t exynos4210_clk_read(void *opaque, hwaddr offset,
96
+ di = drive_get_next(IF_SD);
143
+ unsigned size)
97
+ blk = di ? blk_by_legacy_dinfo(di) : NULL;
144
+{
98
+ bus = qdev_get_child_bus(DEVICE(&s->soc.usdhc[i]), "sd-bus");
145
+ const Exynos4210ClkState *s = (Exynos4210ClkState *)opaque;
99
+ carddev = qdev_create(bus, TYPE_SD_CARD);
146
+ const Exynos4210Reg *regs = exynos4210_clk_regs;
100
+ qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
147
+ unsigned int i;
101
+ object_property_set_bool(OBJECT(carddev), true,
102
+ "realized", &error_fatal);
103
+ }
148
+
104
+
149
+ for (i = 0; i < EXYNOS4210_REGS_NUM; i++) {
105
+ if (!qtest_enabled()) {
150
+ if (regs->offset == offset) {
106
+ arm_load_kernel(&s->soc.cpu[0], &boot_info);
151
+ return s->reg[i];
152
+ }
153
+ regs++;
154
+ }
155
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad read offset 0x%04x\n",
156
+ __func__, (uint32_t)offset);
157
+ return 0;
158
+}
159
+
160
+static void exynos4210_clk_write(void *opaque, hwaddr offset,
161
+ uint64_t val, unsigned size)
162
+{
163
+ Exynos4210ClkState *s = (Exynos4210ClkState *)opaque;
164
+ const Exynos4210Reg *regs = exynos4210_clk_regs;
165
+ unsigned int i;
166
+
167
+ for (i = 0; i < EXYNOS4210_REGS_NUM; i++) {
168
+ if (regs->offset == offset) {
169
+ s->reg[i] = val;
170
+ return;
171
+ }
172
+ regs++;
173
+ }
174
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write offset 0x%04x\n",
175
+ __func__, (uint32_t)offset);
176
+}
177
+
178
+static const MemoryRegionOps exynos4210_clk_ops = {
179
+ .read = exynos4210_clk_read,
180
+ .write = exynos4210_clk_write,
181
+ .endianness = DEVICE_NATIVE_ENDIAN,
182
+ .valid = {
183
+ .min_access_size = 4,
184
+ .max_access_size = 4,
185
+ .unaligned = false
186
+ }
187
+};
188
+
189
+static void exynos4210_clk_reset(DeviceState *dev)
190
+{
191
+ Exynos4210ClkState *s = EXYNOS4210_CLK(dev);
192
+ unsigned int i;
193
+
194
+ /* Set default values for registers */
195
+ for (i = 0; i < EXYNOS4210_REGS_NUM; i++) {
196
+ s->reg[i] = exynos4210_clk_regs[i].reset_value;
197
+ }
107
+ }
198
+}
108
+}
199
+
109
+
200
+static void exynos4210_clk_init(Object *obj)
110
+static void mcimx6ul_evk_machine_init(MachineClass *mc)
201
+{
111
+{
202
+ Exynos4210ClkState *s = EXYNOS4210_CLK(obj);
112
+ mc->desc = "Freescale i.MX6UL Evaluation Kit (Cortex A7)";
203
+ SysBusDevice *dev = SYS_BUS_DEVICE(obj);
113
+ mc->init = mcimx6ul_evk_init;
204
+
114
+ mc->max_cpus = FSL_IMX6UL_NUM_CPUS;
205
+ /* memory mapping */
206
+ memory_region_init_io(&s->iomem, obj, &exynos4210_clk_ops, s,
207
+ TYPE_EXYNOS4210_CLK, EXYNOS4210_CLK_REGS_MEM_SIZE);
208
+ sysbus_init_mmio(dev, &s->iomem);
209
+}
115
+}
210
+
116
+DEFINE_MACHINE("mcimx6ul-evk", mcimx6ul_evk_machine_init)
211
+static const VMStateDescription exynos4210_clk_vmstate = {
212
+ .name = TYPE_EXYNOS4210_CLK,
213
+ .version_id = 1,
214
+ .minimum_version_id = 1,
215
+ .fields = (VMStateField[]) {
216
+ VMSTATE_UINT32_ARRAY(reg, Exynos4210ClkState, EXYNOS4210_REGS_NUM),
217
+ VMSTATE_END_OF_LIST()
218
+ }
219
+};
220
+
221
+static void exynos4210_clk_class_init(ObjectClass *klass, void *data)
222
+{
223
+ DeviceClass *dc = DEVICE_CLASS(klass);
224
+
225
+ dc->reset = exynos4210_clk_reset;
226
+ dc->vmsd = &exynos4210_clk_vmstate;
227
+}
228
+
229
+static const TypeInfo exynos4210_clk_info = {
230
+ .name = TYPE_EXYNOS4210_CLK,
231
+ .parent = TYPE_SYS_BUS_DEVICE,
232
+ .instance_size = sizeof(Exynos4210ClkState),
233
+ .instance_init = exynos4210_clk_init,
234
+ .class_init = exynos4210_clk_class_init,
235
+};
236
+
237
+static void exynos4210_clk_register(void)
238
+{
239
+ qemu_log_mask(LOG_GUEST_ERROR, "Clock init\n");
240
+ type_register_static(&exynos4210_clk_info);
241
+}
242
+
243
+type_init(exynos4210_clk_register)
244
--
117
--
245
2.7.4
118
2.18.0
246
119
247
120
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
2
3
Now that the NVIC is its own separate implementation, we can
3
Some ARM CPUs have bitbanded IO, a memory region that allows convenient
4
clean up the GIC code by removing REV_NVIC and conditionals
4
bit access via 32-bit memory loads/stores. This eliminates the need for
5
which use it.
5
read-modify-update instruction sequences.
6
6
7
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
7
This patch makes this optional feature an ARMv7MState qdev property,
8
allowing boards to choose whether they want bitbanding or not.
9
10
Status of boards:
11
* iotkit (Cortex M33), no bitband
12
* mps2 (Cortex M3), bitband
13
* msf2 (Cortex M3), bitband
14
* stellaris (Cortex M3), bitband
15
* stm32f205 (Cortex M3), bitband
16
17
As a side-effect of this patch, Peter Maydell noted that the Ethernet
18
controller on mps2 board is now accessible. Previously they were hidden
19
by the bitband region (which does not exist on the real board).
20
21
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
22
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
23
Message-id: 20180814162739.11814-2-stefanha@redhat.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
---
25
---
11
hw/intc/gic_internal.h | 7 ++-----
26
include/hw/arm/armv7m.h | 2 ++
12
hw/intc/arm_gic.c | 31 +++++--------------------------
27
hw/arm/armv7m.c | 37 ++++++++++++++++++++-----------------
13
hw/intc/arm_gic_common.c | 23 ++++++++---------------
28
hw/arm/mps2.c | 1 +
14
3 files changed, 15 insertions(+), 46 deletions(-)
29
hw/arm/msf2-soc.c | 1 +
30
hw/arm/stellaris.c | 1 +
31
hw/arm/stm32f205_soc.c | 1 +
32
6 files changed, 26 insertions(+), 17 deletions(-)
15
33
16
diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h
34
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
17
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/intc/gic_internal.h
36
--- a/include/hw/arm/armv7m.h
19
+++ b/hw/intc/gic_internal.h
37
+++ b/include/hw/arm/armv7m.h
20
@@ -XXX,XX +XXX,XX @@
38
@@ -XXX,XX +XXX,XX @@ typedef struct {
21
39
* devices will be automatically layered on top of this view.)
22
#define ALL_CPU_MASK ((unsigned)(((1 << GIC_NCPU) - 1)))
40
* + Property "idau": IDAU interface (forwarded to CPU object)
23
41
* + Property "init-svtor": secure VTOR reset value (forwarded to CPU object)
24
-/* The NVIC has 16 internal vectors. However these are not exposed
42
+ * + Property "enable-bitband": expose bitbanded IO
25
- through the normal GIC interface. */
43
*/
26
-#define GIC_BASE_IRQ ((s->revision == REV_NVIC) ? 32 : 0)
44
typedef struct ARMv7MState {
27
+#define GIC_BASE_IRQ 0
45
/*< private >*/
28
46
@@ -XXX,XX +XXX,XX @@ typedef struct ARMv7MState {
29
#define GIC_SET_ENABLED(irq, cm) s->irq_state[irq].enabled |= (cm)
47
MemoryRegion *board_memory;
30
#define GIC_CLEAR_ENABLED(irq, cm) s->irq_state[irq].enabled &= ~(cm)
48
Object *idau;
31
@@ -XXX,XX +XXX,XX @@
49
uint32_t init_svtor;
32
50
+ bool enable_bitband;
33
/* The special cases for the revision property: */
51
} ARMv7MState;
34
#define REV_11MPCORE 0
52
35
-#define REV_NVIC 0xffffffff
53
#endif
36
54
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
37
void gic_set_pending_private(GICState *s, int cpu, int irq);
38
uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs);
39
@@ -XXX,XX +XXX,XX @@ void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val,
40
41
static inline bool gic_test_pending(GICState *s, int irq, int cm)
42
{
43
- if (s->revision == REV_NVIC || s->revision == REV_11MPCORE) {
44
+ if (s->revision == REV_11MPCORE) {
45
return s->irq_state[irq].pending & cm;
46
} else {
47
/* Edge-triggered interrupts are marked pending on a rising edge, but
48
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
49
index XXXXXXX..XXXXXXX 100644
55
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/intc/arm_gic.c
56
--- a/hw/arm/armv7m.c
51
+++ b/hw/intc/arm_gic.c
57
+++ b/hw/arm/armv7m.c
52
@@ -XXX,XX +XXX,XX @@ static void gic_set_irq_11mpcore(GICState *s, int irq, int level,
58
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
59
memory_region_add_subregion(&s->container, 0xe000e000,
60
sysbus_mmio_get_region(sbd, 0));
61
62
- for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
63
- Object *obj = OBJECT(&s->bitband[i]);
64
- SysBusDevice *sbd = SYS_BUS_DEVICE(&s->bitband[i]);
65
+ if (s->enable_bitband) {
66
+ for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
67
+ Object *obj = OBJECT(&s->bitband[i]);
68
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->bitband[i]);
69
70
- object_property_set_int(obj, bitband_input_addr[i], "base", &err);
71
- if (err != NULL) {
72
- error_propagate(errp, err);
73
- return;
74
- }
75
- object_property_set_link(obj, OBJECT(s->board_memory),
76
- "source-memory", &error_abort);
77
- object_property_set_bool(obj, true, "realized", &err);
78
- if (err != NULL) {
79
- error_propagate(errp, err);
80
- return;
81
- }
82
+ object_property_set_int(obj, bitband_input_addr[i], "base", &err);
83
+ if (err != NULL) {
84
+ error_propagate(errp, err);
85
+ return;
86
+ }
87
+ object_property_set_link(obj, OBJECT(s->board_memory),
88
+ "source-memory", &error_abort);
89
+ object_property_set_bool(obj, true, "realized", &err);
90
+ if (err != NULL) {
91
+ error_propagate(errp, err);
92
+ return;
93
+ }
94
95
- memory_region_add_subregion(&s->container, bitband_output_addr[i],
96
- sysbus_mmio_get_region(sbd, 0));
97
+ memory_region_add_subregion(&s->container, bitband_output_addr[i],
98
+ sysbus_mmio_get_region(sbd, 0));
99
+ }
53
}
100
}
54
}
101
}
55
102
56
-static void gic_set_irq_nvic(GICState *s, int irq, int level,
103
@@ -XXX,XX +XXX,XX @@ static Property armv7m_properties[] = {
57
- int cm, int target)
104
MemoryRegion *),
58
-{
105
DEFINE_PROP_LINK("idau", ARMv7MState, idau, TYPE_IDAU_INTERFACE, Object *),
59
- if (level) {
106
DEFINE_PROP_UINT32("init-svtor", ARMv7MState, init_svtor, 0),
60
- GIC_SET_LEVEL(irq, cm);
107
+ DEFINE_PROP_BOOL("enable-bitband", ARMv7MState, enable_bitband, false),
61
- GIC_SET_PENDING(irq, target);
108
DEFINE_PROP_END_OF_LIST(),
62
- } else {
109
};
63
- GIC_CLEAR_LEVEL(irq, cm);
110
64
- }
111
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
65
-}
112
index XXXXXXX..XXXXXXX 100644
66
-
113
--- a/hw/arm/mps2.c
67
static void gic_set_irq_generic(GICState *s, int irq, int level,
114
+++ b/hw/arm/mps2.c
68
int cm, int target)
115
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
69
{
116
g_assert_not_reached();
70
@@ -XXX,XX +XXX,XX @@ static void gic_set_irq(void *opaque, int irq, int level)
71
72
if (s->revision == REV_11MPCORE) {
73
gic_set_irq_11mpcore(s, irq, level, cm, target);
74
- } else if (s->revision == REV_NVIC) {
75
- gic_set_irq_nvic(s, irq, level, cm, target);
76
} else {
77
gic_set_irq_generic(s, irq, level, cm, target);
78
}
117
}
79
@@ -XXX,XX +XXX,XX @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs)
118
qdev_prop_set_string(armv7m, "cpu-type", machine->cpu_type);
80
return 1023;
119
+ qdev_prop_set_bit(armv7m, "enable-bitband", true);
81
}
120
object_property_set_link(OBJECT(&mms->armv7m), OBJECT(system_memory),
82
121
"memory", &error_abort);
83
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
122
object_property_set_bool(OBJECT(&mms->armv7m), true, "realized",
84
+ if (s->revision == REV_11MPCORE) {
123
diff --git a/hw/arm/msf2-soc.c b/hw/arm/msf2-soc.c
85
/* Clear pending flags for both level and edge triggered interrupts.
86
* Level triggered IRQs will be reasserted once they become inactive.
87
*/
88
@@ -XXX,XX +XXX,XX @@ void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
89
DPRINTF("Set %d pending mask %x\n", irq, cm);
90
GIC_SET_PENDING(irq, cm);
91
}
92
- } else if (s->revision == REV_NVIC) {
93
- if (GIC_TEST_LEVEL(irq, cm)) {
94
- DPRINTF("Set nvic %d pending mask %x\n", irq, cm);
95
- GIC_SET_PENDING(irq, cm);
96
- }
97
}
98
99
group = gic_has_groups(s) && GIC_TEST_GROUP(irq, cm);
100
@@ -XXX,XX +XXX,XX @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
101
} else if (offset < 0xf10) {
102
goto bad_reg;
103
} else if (offset < 0xf30) {
104
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
105
+ if (s->revision == REV_11MPCORE) {
106
goto bad_reg;
107
}
108
109
@@ -XXX,XX +XXX,XX @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
110
case 2:
111
res = gic_id_gicv2[(offset - 0xfd0) >> 2];
112
break;
113
- case REV_NVIC:
114
- /* Shouldn't be able to get here */
115
- abort();
116
default:
117
res = 0;
118
}
119
@@ -XXX,XX +XXX,XX @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
120
continue; /* Ignore Non-secure access of Group0 IRQ */
121
}
122
123
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
124
+ if (s->revision == REV_11MPCORE) {
125
if (value & (1 << (i * 2))) {
126
GIC_SET_MODEL(irq + i);
127
} else {
128
@@ -XXX,XX +XXX,XX @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
129
goto bad_reg;
130
} else if (offset < 0xf20) {
131
/* GICD_CPENDSGIRn */
132
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
133
+ if (s->revision == REV_11MPCORE) {
134
goto bad_reg;
135
}
136
irq = (offset - 0xf10);
137
@@ -XXX,XX +XXX,XX @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
138
}
139
} else if (offset < 0xf30) {
140
/* GICD_SPENDSGIRn */
141
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
142
+ if (s->revision == REV_11MPCORE) {
143
goto bad_reg;
144
}
145
irq = (offset - 0xf20);
146
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
147
index XXXXXXX..XXXXXXX 100644
124
index XXXXXXX..XXXXXXX 100644
148
--- a/hw/intc/arm_gic_common.c
125
--- a/hw/arm/msf2-soc.c
149
+++ b/hw/intc/arm_gic_common.c
126
+++ b/hw/arm/msf2-soc.c
150
@@ -XXX,XX +XXX,XX @@ void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
127
@@ -XXX,XX +XXX,XX @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
151
* [N+32..N+63] PPIs for CPU 1
128
armv7m = DEVICE(&s->armv7m);
152
* ...
129
qdev_prop_set_uint32(armv7m, "num-irq", 81);
153
*/
130
qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
154
- if (s->revision != REV_NVIC) {
131
+ qdev_prop_set_bit(armv7m, "enable-bitband", true);
155
- i += (GIC_INTERNAL * s->num_cpu);
132
object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),
156
- }
133
"memory", &error_abort);
157
+ i += (GIC_INTERNAL * s->num_cpu);
134
object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
158
qdev_init_gpio_in(DEVICE(s), handler, i);
135
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
159
136
index XXXXXXX..XXXXXXX 100644
160
for (i = 0; i < s->num_cpu; i++) {
137
--- a/hw/arm/stellaris.c
161
@@ -XXX,XX +XXX,XX @@ void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
138
+++ b/hw/arm/stellaris.c
162
memory_region_init_io(&s->iomem, OBJECT(s), ops, s, "gic_dist", 0x1000);
139
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
163
sysbus_init_mmio(sbd, &s->iomem);
140
nvic = qdev_create(NULL, TYPE_ARMV7M);
164
141
qdev_prop_set_uint32(nvic, "num-irq", NUM_IRQ_LINES);
165
- if (s->revision != REV_NVIC) {
142
qdev_prop_set_string(nvic, "cpu-type", ms->cpu_type);
166
- /* This is the main CPU interface "for this core". It is always
143
+ qdev_prop_set_bit(nvic, "enable-bitband", true);
167
- * present because it is required by both software emulation and KVM.
144
object_property_set_link(OBJECT(nvic), OBJECT(get_system_memory()),
168
- * NVIC is not handled here because its CPU interface is different,
145
"memory", &error_abort);
169
- * neither it can use KVM.
146
/* This will exit with an error if the user passed us a bad cpu_type */
170
- */
147
diff --git a/hw/arm/stm32f205_soc.c b/hw/arm/stm32f205_soc.c
171
- memory_region_init_io(&s->cpuiomem[0], OBJECT(s), ops ? &ops[1] : NULL,
148
index XXXXXXX..XXXXXXX 100644
172
- s, "gic_cpu", s->revision == 2 ? 0x2000 : 0x100);
149
--- a/hw/arm/stm32f205_soc.c
173
- sysbus_init_mmio(sbd, &s->cpuiomem[0]);
150
+++ b/hw/arm/stm32f205_soc.c
174
- }
151
@@ -XXX,XX +XXX,XX @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
175
+ /* This is the main CPU interface "for this core". It is always
152
armv7m = DEVICE(&s->armv7m);
176
+ * present because it is required by both software emulation and KVM.
153
qdev_prop_set_uint32(armv7m, "num-irq", 96);
177
+ */
154
qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
178
+ memory_region_init_io(&s->cpuiomem[0], OBJECT(s), ops ? &ops[1] : NULL,
155
+ qdev_prop_set_bit(armv7m, "enable-bitband", true);
179
+ s, "gic_cpu", s->revision == 2 ? 0x2000 : 0x100);
156
object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),
180
+ sysbus_init_mmio(sbd, &s->cpuiomem[0]);
157
"memory", &error_abort);
181
}
158
object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
182
183
static void arm_gic_common_realize(DeviceState *dev, Error **errp)
184
@@ -XXX,XX +XXX,XX @@ static void arm_gic_common_realize(DeviceState *dev, Error **errp)
185
}
186
187
if (s->security_extn &&
188
- (s->revision == REV_11MPCORE || s->revision == REV_NVIC)) {
189
+ (s->revision == REV_11MPCORE)) {
190
error_setg(errp, "this GIC revision does not implement "
191
"the security extensions");
192
return;
193
@@ -XXX,XX +XXX,XX @@ static Property arm_gic_common_properties[] = {
194
DEFINE_PROP_UINT32("num-irq", GICState, num_irq, 32),
195
/* Revision can be 1 or 2 for GIC architecture specification
196
* versions 1 or 2, or 0 to indicate the legacy 11MPCore GIC.
197
- * (Internally, 0xffffffff also indicates "not a GIC but an NVIC".)
198
*/
199
DEFINE_PROP_UINT32("revision", GICState, revision, 1),
200
/* True if the GIC should implement the security extensions */
201
--
159
--
202
2.7.4
160
2.18.0
203
161
204
162
diff view generated by jsdifflib
1
The M profile condition for when we can take a pending exception or
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
interrupt is not the same as that for A/R profile. The code
3
originally copied from the A/R profile version of the
4
cpu_exec_interrupt function only worked by chance for the
5
very simple case of exceptions being masked by PRIMASK.
6
Replace it with a call to a function in the NVIC code that
7
correctly compares the priority of the pending exception
8
against the current execution priority of the CPU.
9
2
10
[Michael Davidsaver's patchset had a patch to do something
3
Define a "cortex-m0" ARMv6-M CPU model.
11
similar but the implementation ended up being a rewrite.]
12
4
5
Most of the register reset values set by other CPU models are not
6
relevant for the cut-down ARMv6-M architecture.
7
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20180814162739.11814-3-stefanha@redhat.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
15
---
13
---
16
target/arm/cpu.h | 8 ++++++++
14
target/arm/cpu.c | 11 +++++++++++
17
hw/intc/armv7m_nvic.c | 7 +++++++
15
1 file changed, 11 insertions(+)
18
target/arm/cpu.c | 16 ++++++++--------
19
3 files changed, 23 insertions(+), 8 deletions(-)
20
16
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/cpu.h
24
+++ b/target/arm/cpu.h
25
@@ -XXX,XX +XXX,XX @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
26
uint32_t cur_el, bool secure);
27
28
/* Interface between CPU and Interrupt controller. */
29
+#ifndef CONFIG_USER_ONLY
30
+bool armv7m_nvic_can_take_pending_exception(void *opaque);
31
+#else
32
+static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
33
+{
34
+ return true;
35
+}
36
+#endif
37
void armv7m_nvic_set_pending(void *opaque, int irq);
38
int armv7m_nvic_acknowledge_irq(void *opaque);
39
void armv7m_nvic_complete_irq(void *opaque, int irq);
40
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/intc/armv7m_nvic.c
43
+++ b/hw/intc/armv7m_nvic.c
44
@@ -XXX,XX +XXX,XX @@ static inline int nvic_exec_prio(NVICState *s)
45
return MIN(running, s->exception_prio);
46
}
47
48
+bool armv7m_nvic_can_take_pending_exception(void *opaque)
49
+{
50
+ NVICState *s = opaque;
51
+
52
+ return nvic_exec_prio(s) > nvic_pending_prio(s);
53
+}
54
+
55
/* caller must call nvic_irq_update() after this */
56
static void set_prio(NVICState *s, unsigned irq, uint8_t prio)
57
{
58
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
17
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
59
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/cpu.c
19
--- a/target/arm/cpu.c
61
+++ b/target/arm/cpu.c
20
+++ b/target/arm/cpu.c
62
@@ -XXX,XX +XXX,XX @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
21
@@ -XXX,XX +XXX,XX @@ static void arm11mpcore_initfn(Object *obj)
63
CPUARMState *env = &cpu->env;
22
cpu->reset_auxcr = 1;
64
bool ret = false;
23
}
65
24
66
-
25
+static void cortex_m0_initfn(Object *obj)
67
- if (interrupt_request & CPU_INTERRUPT_FIQ
26
+{
68
- && !(env->daif & PSTATE_F)) {
27
+ ARMCPU *cpu = ARM_CPU(obj);
69
- cs->exception_index = EXCP_FIQ;
28
+ set_feature(&cpu->env, ARM_FEATURE_V6);
70
- cc->do_interrupt(cs);
29
+ set_feature(&cpu->env, ARM_FEATURE_M);
71
- ret = true;
30
+
72
- }
31
+ cpu->midr = 0x410cc200;
73
/* ARMv7-M interrupt return works by loading a magic value
32
+}
74
* into the PC. On real hardware the load causes the
33
+
75
* return to occur. The qemu implementation performs the
34
static void cortex_m3_initfn(Object *obj)
76
@@ -XXX,XX +XXX,XX @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
35
{
77
* the stack if an interrupt occurred at the wrong time.
36
ARMCPU *cpu = ARM_CPU(obj);
78
* We avoid this by disabling interrupts when
37
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_cpus[] = {
79
* pc contains a magic address.
38
{ .name = "arm1136", .initfn = arm1136_initfn },
80
+ *
39
{ .name = "arm1176", .initfn = arm1176_initfn },
81
+ * ARMv7-M interrupt masking works differently than -A or -R.
40
{ .name = "arm11mpcore", .initfn = arm11mpcore_initfn },
82
+ * There is no FIQ/IRQ distinction. Instead of I and F bits
41
+ { .name = "cortex-m0", .initfn = cortex_m0_initfn,
83
+ * masking FIQ and IRQ interrupts, an exception is taken only
42
+ .class_init = arm_v7m_class_init },
84
+ * if it is higher priority than the current execution priority
43
{ .name = "cortex-m3", .initfn = cortex_m3_initfn,
85
+ * (which depends on state like BASEPRI, FAULTMASK and the
44
.class_init = arm_v7m_class_init },
86
+ * currently active exception).
45
{ .name = "cortex-m4", .initfn = cortex_m4_initfn,
87
*/
88
if (interrupt_request & CPU_INTERRUPT_HARD
89
- && !(env->daif & PSTATE_I)
90
+ && (armv7m_nvic_can_take_pending_exception(env->nvic))
91
&& (env->regs[15] < 0xfffffff0)) {
92
cs->exception_index = EXCP_IRQ;
93
cc->do_interrupt(cs);
94
--
46
--
95
2.7.4
47
2.18.0
96
48
97
49
diff view generated by jsdifflib
1
From: Krzysztof Kozlowski <krzk@kernel.org>
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
2
3
The Exynos4210 has cluster ID 0x9 in its MPIDR register (raw value
3
The next patch will need to free a rom. There is already code to do
4
0x8000090x). If this cluster ID is not provided, then Linux kernel
4
this in rom_add_file().
5
cannot map DeviceTree nodes to MPIDR values resulting in kernel
6
warning and lack of any secondary CPUs:
7
5
8
DT missing boot CPU MPIDR[23:0], fall back to default cpu_logical_map
6
Note that rom_add_file() uses:
9
...
10
smp: Bringing up secondary CPUs ...
11
smp: Brought up 1 node, 1 CPU
12
SMP: Total of 1 processors activated (24.00 BogoMIPS).
13
7
14
Provide a cluster ID so Linux will see proper MPIDR and will try to
8
rom = g_malloc0(sizeof(*rom));
15
bring the secondary CPU online.
9
...
10
if (rom->fw_dir) {
11
g_free(rom->fw_dir);
12
g_free(rom->fw_file);
13
}
16
14
17
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
15
The conditional is unnecessary since g_free(NULL) is a no-op.
18
Message-id: 20170226200142.31169-2-krzk@kernel.org
16
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
18
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
19
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Message-id: 20180814162739.11814-4-stefanha@redhat.com
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
22
---
22
hw/arm/exynos4210.c | 12 ++++++++++++
23
hw/core/loader.c | 21 ++++++++++++---------
23
1 file changed, 12 insertions(+)
24
1 file changed, 12 insertions(+), 9 deletions(-)
24
25
25
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
26
diff --git a/hw/core/loader.c b/hw/core/loader.c
26
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/exynos4210.c
28
--- a/hw/core/loader.c
28
+++ b/hw/arm/exynos4210.c
29
+++ b/hw/core/loader.c
29
@@ -XXX,XX +XXX,XX @@ void exynos4210_write_secondary(ARMCPU *cpu,
30
@@ -XXX,XX +XXX,XX @@ struct Rom {
30
info->smp_loader_start);
31
static FWCfgState *fw_cfg;
31
}
32
static QTAILQ_HEAD(, Rom) roms = QTAILQ_HEAD_INITIALIZER(roms);
32
33
33
+static uint64_t exynos4210_calc_affinity(int cpu)
34
+/* rom->data must be heap-allocated (do not use with rom_add_elf_program()) */
35
+static void rom_free(Rom *rom)
34
+{
36
+{
35
+ uint64_t mp_affinity;
37
+ g_free(rom->data);
36
+
38
+ g_free(rom->path);
37
+ /* Exynos4210 has 0x9 as cluster ID */
39
+ g_free(rom->name);
38
+ mp_affinity = (0x9 << ARM_AFF1_SHIFT) | cpu;
40
+ g_free(rom->fw_dir);
39
+
41
+ g_free(rom->fw_file);
40
+ return mp_affinity;
42
+ g_free(rom);
41
+}
43
+}
42
+
44
+
43
Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
45
static inline bool rom_order_compare(Rom *rom, Rom *item)
44
unsigned long ram_size)
45
{
46
{
46
@@ -XXX,XX +XXX,XX @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
47
return ((uintptr_t)(void *)rom->as > (uintptr_t)(void *)item->as) ||
47
}
48
@@ -XXX,XX +XXX,XX @@ err:
48
49
if (fd != -1)
49
s->cpu[n] = ARM_CPU(cpuobj);
50
close(fd);
50
+ object_property_set_int(cpuobj, exynos4210_calc_affinity(n),
51
51
+ "mp-affinity", &error_abort);
52
- g_free(rom->data);
52
object_property_set_int(cpuobj, EXYNOS4210_SMP_PRIVATE_BASE_ADDR,
53
- g_free(rom->path);
53
"reset-cbar", &error_abort);
54
- g_free(rom->name);
54
object_property_set_bool(cpuobj, true, "realized", &error_fatal);
55
- if (fw_dir) {
56
- g_free(rom->fw_dir);
57
- g_free(rom->fw_file);
58
- }
59
- g_free(rom);
60
-
61
+ rom_free(rom);
62
return -1;
63
}
64
55
--
65
--
56
2.7.4
66
2.18.0
57
67
58
68
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
2
3
In 2.9 ITS will block save/restore and migration use cases. As such,
3
Image file loaders may add a series of roms. If an error occurs partway
4
let's introduce a user option that allows to turn its instantiation
4
through loading there is no easy way to drop previously added roms.
5
off, along with GICv3. With the "its" option turned false, migration
6
will be possible, obviously at the expense of MSI support (with GICv3).
7
5
8
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
This patch adds a transaction mechanism that works like this:
9
Message-id: 1487681108-14452-1-git-send-email-eric.auger@redhat.com
7
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
rom_transaction_begin();
9
...call rom_add_*()...
10
rom_transaction_end(ok);
11
12
If ok is false then roms added in this transaction are dropped.
13
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
15
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
16
Message-id: 20180814162739.11814-5-stefanha@redhat.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
18
---
13
include/hw/arm/virt.h | 1 +
19
include/hw/loader.h | 19 +++++++++++++++++++
14
hw/arm/virt.c | 31 +++++++++++++++++++++++++++++--
20
hw/core/loader.c | 32 ++++++++++++++++++++++++++++++++
15
2 files changed, 30 insertions(+), 2 deletions(-)
21
2 files changed, 51 insertions(+)
16
22
17
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
23
diff --git a/include/hw/loader.h b/include/hw/loader.h
18
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/virt.h
25
--- a/include/hw/loader.h
20
+++ b/include/hw/arm/virt.h
26
+++ b/include/hw/loader.h
21
@@ -XXX,XX +XXX,XX @@ typedef struct {
27
@@ -XXX,XX +XXX,XX @@ int rom_check_and_register_reset(void);
22
FWCfgState *fw_cfg;
28
void rom_set_fw(FWCfgState *f);
23
bool secure;
29
void rom_set_order_override(int order);
24
bool highmem;
30
void rom_reset_order_override(void);
25
+ bool its;
31
+
26
bool virt;
32
+/**
27
int32_t gic_version;
33
+ * rom_transaction_begin:
28
struct arm_boot_info bootinfo;
34
+ *
29
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
35
+ * Call this before of a series of rom_add_*() calls. Call
36
+ * rom_transaction_end() afterwards to commit or abort. These functions are
37
+ * useful for undoing a series of rom_add_*() calls if image file loading fails
38
+ * partway through.
39
+ */
40
+void rom_transaction_begin(void);
41
+
42
+/**
43
+ * rom_transaction_end:
44
+ * @commit: true to commit added roms, false to drop added roms
45
+ *
46
+ * Call this after a series of rom_add_*() calls. See rom_transaction_begin().
47
+ */
48
+void rom_transaction_end(bool commit);
49
+
50
int rom_copy(uint8_t *dest, hwaddr addr, size_t size);
51
void *rom_ptr(hwaddr addr, size_t size);
52
void hmp_info_roms(Monitor *mon, const QDict *qdict);
53
diff --git a/hw/core/loader.c b/hw/core/loader.c
30
index XXXXXXX..XXXXXXX 100644
54
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/virt.c
55
--- a/hw/core/loader.c
32
+++ b/hw/arm/virt.c
56
+++ b/hw/core/loader.c
33
@@ -XXX,XX +XXX,XX @@ static void create_v2m(VirtMachineState *vms, qemu_irq *pic)
57
@@ -XXX,XX +XXX,XX @@ struct Rom {
34
static void create_gic(VirtMachineState *vms, qemu_irq *pic)
58
char *fw_dir;
35
{
59
char *fw_file;
36
/* We create a standalone GIC */
60
37
- VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
61
+ bool committed;
38
DeviceState *gicdev;
62
+
39
SysBusDevice *gicbusdev;
63
hwaddr addr;
40
const char *gictype;
64
QTAILQ_ENTRY(Rom) next;
41
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
65
};
42
66
@@ -XXX,XX +XXX,XX @@ static void rom_insert(Rom *rom)
43
fdt_add_gic_node(vms);
67
rom->as = &address_space_memory;
44
68
}
45
- if (type == 3 && !vmc->no_its) {
69
46
+ if (type == 3 && vms->its) {
70
+ rom->committed = false;
47
create_its(vms, gicdev);
71
+
48
} else if (type == 2) {
72
/* List is ordered by load address in the same address space */
49
create_v2m(vms, pic);
73
QTAILQ_FOREACH(item, &roms, next) {
50
@@ -XXX,XX +XXX,XX @@ static void virt_set_highmem(Object *obj, bool value, Error **errp)
74
if (rom_order_compare(rom, item)) {
51
vms->highmem = value;
75
@@ -XXX,XX +XXX,XX @@ void rom_reset_order_override(void)
76
fw_cfg_reset_order_override(fw_cfg);
52
}
77
}
53
78
54
+static bool virt_get_its(Object *obj, Error **errp)
79
+void rom_transaction_begin(void)
55
+{
80
+{
56
+ VirtMachineState *vms = VIRT_MACHINE(obj);
81
+ Rom *rom;
57
+
82
+
58
+ return vms->its;
83
+ /* Ignore ROMs added without the transaction API */
84
+ QTAILQ_FOREACH(rom, &roms, next) {
85
+ rom->committed = true;
86
+ }
59
+}
87
+}
60
+
88
+
61
+static void virt_set_its(Object *obj, bool value, Error **errp)
89
+void rom_transaction_end(bool commit)
62
+{
90
+{
63
+ VirtMachineState *vms = VIRT_MACHINE(obj);
91
+ Rom *rom;
92
+ Rom *tmp;
64
+
93
+
65
+ vms->its = value;
94
+ QTAILQ_FOREACH_SAFE(rom, &roms, next, tmp) {
95
+ if (rom->committed) {
96
+ continue;
97
+ }
98
+ if (commit) {
99
+ rom->committed = true;
100
+ } else {
101
+ QTAILQ_REMOVE(&roms, rom, next);
102
+ rom_free(rom);
103
+ }
104
+ }
66
+}
105
+}
67
+
106
+
68
static char *virt_get_gic_version(Object *obj, Error **errp)
107
static Rom *find_rom(hwaddr addr, size_t size)
69
{
108
{
70
VirtMachineState *vms = VIRT_MACHINE(obj);
109
Rom *rom;
71
@@ -XXX,XX +XXX,XX @@ type_init(machvirt_machine_init);
72
static void virt_2_9_instance_init(Object *obj)
73
{
74
VirtMachineState *vms = VIRT_MACHINE(obj);
75
+ VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
76
77
/* EL3 is disabled by default on virt: this makes us consistent
78
* between KVM and TCG for this board, and it also allows us to
79
@@ -XXX,XX +XXX,XX @@ static void virt_2_9_instance_init(Object *obj)
80
"Set GIC version. "
81
"Valid values are 2, 3 and host", NULL);
82
83
+ if (vmc->no_its) {
84
+ vms->its = false;
85
+ } else {
86
+ /* Default allows ITS instantiation */
87
+ vms->its = true;
88
+ object_property_add_bool(obj, "its", virt_get_its,
89
+ virt_set_its, NULL);
90
+ object_property_set_description(obj, "its",
91
+ "Set on/off to enable/disable "
92
+ "ITS instantiation",
93
+ NULL);
94
+ }
95
+
96
vms->memmap = a15memmap;
97
vms->irqmap = a15irqmap;
98
}
99
--
110
--
100
2.7.4
111
2.18.0
101
112
102
113
diff view generated by jsdifflib
1
Extract the code from the tail end of arm_v7m_do_interrupt() which
1
From: Su Hang <suhang16@mails.ucas.ac.cn>
2
enters the exception handler into a pair of utility functions
2
3
v7m_exception_taken() and v7m_push_stack(), which correspond roughly
3
This patch adds Intel Hexadecimal Object File format support to the
4
to the pseudocode PushStack() and ExceptionTaken().
4
generic loader device. The file format specification is available here:
5
5
http://www.piclist.com/techref/fileext/hex/intel.htm
6
This also requires us to move the arm_v7m_load_vector() utility
6
7
routine up so we can call it.
7
This file format is often used with microcontrollers such as the
8
8
micro:bit, Arduino, STM32, etc. Users expect to be able to run .hex
9
Handling illegal exception returns has some cases where we want to
9
files directly with without first converting them to ELF. Most
10
take a UsageFault either on an existing stack frame or with a new
10
micro:bit code is developed in web-based IDEs without direct user access
11
stack frame but with a specific LR value, so we want to be able to
11
to binutils so it is important for QEMU to handle this file format
12
call these without having to go via arm_v7m_cpu_do_interrupt().
12
natively.
13
13
14
Signed-off-by: Su Hang <suhang16@mails.ucas.ac.cn>
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
16
Acked-by: Alistair Francis <alistair.francis@wdc.com>
17
Message-id: 20180814162739.11814-6-stefanha@redhat.com
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
16
---
19
---
17
target/arm/helper.c | 118 ++++++++++++++++++++++++++++++----------------------
20
include/hw/loader.h | 12 ++
18
1 file changed, 68 insertions(+), 50 deletions(-)
21
hw/core/generic-loader.c | 4 +
19
22
hw/core/loader.c | 249 +++++++++++++++++++++++++++++++++++++++
20
diff --git a/target/arm/helper.c b/target/arm/helper.c
23
3 files changed, 265 insertions(+)
24
25
diff --git a/include/hw/loader.h b/include/hw/loader.h
21
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/helper.c
27
--- a/include/hw/loader.h
23
+++ b/target/arm/helper.c
28
+++ b/include/hw/loader.h
24
@@ -XXX,XX +XXX,XX @@ static void switch_v7m_sp(CPUARMState *env, bool new_spsel)
29
@@ -XXX,XX +XXX,XX @@ ssize_t load_image_size(const char *filename, void *addr, size_t size);
30
int load_image_targphys_as(const char *filename,
31
hwaddr addr, uint64_t max_sz, AddressSpace *as);
32
33
+/**load_targphys_hex_as:
34
+ * @filename: Path to the .hex file
35
+ * @entry: Store the entry point given by the .hex file
36
+ * @as: The AddressSpace to load the .hex file to. The value of
37
+ * address_space_memory is used if nothing is supplied here.
38
+ *
39
+ * Load a fixed .hex file into memory.
40
+ *
41
+ * Returns the size of the loaded .hex file on success, -1 otherwise.
42
+ */
43
+int load_targphys_hex_as(const char *filename, hwaddr *entry, AddressSpace *as);
44
+
45
/** load_image_targphys:
46
* Same as load_image_targphys_as(), but doesn't allow the caller to specify
47
* an AddressSpace.
48
diff --git a/hw/core/generic-loader.c b/hw/core/generic-loader.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/core/generic-loader.c
51
+++ b/hw/core/generic-loader.c
52
@@ -XXX,XX +XXX,XX @@ static void generic_loader_realize(DeviceState *dev, Error **errp)
53
size = load_uimage_as(s->file, &entry, NULL, NULL, NULL, NULL,
54
as);
55
}
56
+
57
+ if (size < 0) {
58
+ size = load_targphys_hex_as(s->file, &entry, as);
59
+ }
60
}
61
62
if (size < 0 || s->force_raw) {
63
diff --git a/hw/core/loader.c b/hw/core/loader.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/core/loader.c
66
+++ b/hw/core/loader.c
67
@@ -XXX,XX +XXX,XX @@ void hmp_info_roms(Monitor *mon, const QDict *qdict)
68
}
25
}
69
}
26
}
70
}
27
71
+
28
+static uint32_t arm_v7m_load_vector(ARMCPU *cpu)
72
+typedef enum HexRecord HexRecord;
73
+enum HexRecord {
74
+ DATA_RECORD = 0,
75
+ EOF_RECORD,
76
+ EXT_SEG_ADDR_RECORD,
77
+ START_SEG_ADDR_RECORD,
78
+ EXT_LINEAR_ADDR_RECORD,
79
+ START_LINEAR_ADDR_RECORD,
80
+};
81
+
82
+/* Each record contains a 16-bit address which is combined with the upper 16
83
+ * bits of the implicit "next address" to form a 32-bit address.
84
+ */
85
+#define NEXT_ADDR_MASK 0xffff0000
86
+
87
+#define DATA_FIELD_MAX_LEN 0xff
88
+#define LEN_EXCEPT_DATA 0x5
89
+/* 0x5 = sizeof(byte_count) + sizeof(address) + sizeof(record_type) +
90
+ * sizeof(checksum) */
91
+typedef struct {
92
+ uint8_t byte_count;
93
+ uint16_t address;
94
+ uint8_t record_type;
95
+ uint8_t data[DATA_FIELD_MAX_LEN];
96
+ uint8_t checksum;
97
+} HexLine;
98
+
99
+/* return 0 or -1 if error */
100
+static bool parse_record(HexLine *line, uint8_t *our_checksum, const uint8_t c,
101
+ uint32_t *index, const bool in_process)
29
+{
102
+{
30
+ CPUState *cs = CPU(cpu);
103
+ /* +-------+---------------+-------+---------------------+--------+
31
+ CPUARMState *env = &cpu->env;
104
+ * | byte | |record | | |
32
+ MemTxResult result;
105
+ * | count | address | type | data |checksum|
33
+ hwaddr vec = env->v7m.vecbase + env->v7m.exception * 4;
106
+ * +-------+---------------+-------+---------------------+--------+
34
+ uint32_t addr;
107
+ * ^ ^ ^ ^ ^ ^
35
+
108
+ * |1 byte | 2 bytes |1 byte | 0-255 bytes | 1 byte |
36
+ addr = address_space_ldl(cs->as, vec,
109
+ */
37
+ MEMTXATTRS_UNSPECIFIED, &result);
110
+ uint8_t value = 0;
38
+ if (result != MEMTX_OK) {
111
+ uint32_t idx = *index;
39
+ /* Architecturally this should cause a HardFault setting HSFR.VECTTBL,
112
+ /* ignore space */
40
+ * which would then be immediately followed by our failing to load
113
+ if (g_ascii_isspace(c)) {
41
+ * the entry vector for that HardFault, which is a Lockup case.
114
+ return true;
42
+ * Since we don't model Lockup, we just report this guest error
115
+ }
43
+ * via cpu_abort().
116
+ if (!g_ascii_isxdigit(c) || !in_process) {
44
+ */
117
+ return false;
45
+ cpu_abort(cs, "Failed to read from exception vector table "
118
+ }
46
+ "entry %08x\n", (unsigned)vec);
119
+ value = g_ascii_xdigit_value(c);
47
+ }
120
+ value = (idx & 0x1) ? (value & 0xf) : (value << 4);
48
+ return addr;
121
+ if (idx < 2) {
122
+ line->byte_count |= value;
123
+ } else if (2 <= idx && idx < 6) {
124
+ line->address <<= 4;
125
+ line->address += g_ascii_xdigit_value(c);
126
+ } else if (6 <= idx && idx < 8) {
127
+ line->record_type |= value;
128
+ } else if (8 <= idx && idx < 8 + 2 * line->byte_count) {
129
+ line->data[(idx - 8) >> 1] |= value;
130
+ } else if (8 + 2 * line->byte_count <= idx &&
131
+ idx < 10 + 2 * line->byte_count) {
132
+ line->checksum |= value;
133
+ } else {
134
+ return false;
135
+ }
136
+ *our_checksum += value;
137
+ ++(*index);
138
+ return true;
49
+}
139
+}
50
+
140
+
51
+static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr)
141
+typedef struct {
142
+ const char *filename;
143
+ HexLine line;
144
+ uint8_t *bin_buf;
145
+ hwaddr *start_addr;
146
+ int total_size;
147
+ uint32_t next_address_to_write;
148
+ uint32_t current_address;
149
+ uint32_t current_rom_index;
150
+ uint32_t rom_start_address;
151
+ AddressSpace *as;
152
+} HexParser;
153
+
154
+/* return size or -1 if error */
155
+static int handle_record_type(HexParser *parser)
52
+{
156
+{
53
+ /* Do the "take the exception" parts of exception entry,
157
+ HexLine *line = &(parser->line);
54
+ * but not the pushing of state to the stack. This is
158
+ switch (line->record_type) {
55
+ * similar to the pseudocode ExceptionTaken() function.
159
+ case DATA_RECORD:
56
+ */
160
+ parser->current_address =
57
+ CPUARMState *env = &cpu->env;
161
+ (parser->next_address_to_write & NEXT_ADDR_MASK) | line->address;
58
+ uint32_t addr;
162
+ /* verify this is a contiguous block of memory */
59
+
163
+ if (parser->current_address != parser->next_address_to_write) {
60
+ armv7m_nvic_acknowledge_irq(env->nvic);
164
+ if (parser->current_rom_index != 0) {
61
+ switch_v7m_sp(env, 0);
165
+ rom_add_blob_fixed_as(parser->filename, parser->bin_buf,
62
+ /* Clear IT bits */
166
+ parser->current_rom_index,
63
+ env->condexec_bits = 0;
167
+ parser->rom_start_address, parser->as);
64
+ env->regs[14] = lr;
168
+ }
65
+ addr = arm_v7m_load_vector(cpu);
169
+ parser->rom_start_address = parser->current_address;
66
+ env->regs[15] = addr & 0xfffffffe;
170
+ parser->current_rom_index = 0;
67
+ env->thumb = addr & 1;
171
+ }
172
+
173
+ /* copy from line buffer to output bin_buf */
174
+ memcpy(parser->bin_buf + parser->current_rom_index, line->data,
175
+ line->byte_count);
176
+ parser->current_rom_index += line->byte_count;
177
+ parser->total_size += line->byte_count;
178
+ /* save next address to write */
179
+ parser->next_address_to_write =
180
+ parser->current_address + line->byte_count;
181
+ break;
182
+
183
+ case EOF_RECORD:
184
+ if (parser->current_rom_index != 0) {
185
+ rom_add_blob_fixed_as(parser->filename, parser->bin_buf,
186
+ parser->current_rom_index,
187
+ parser->rom_start_address, parser->as);
188
+ }
189
+ return parser->total_size;
190
+ case EXT_SEG_ADDR_RECORD:
191
+ case EXT_LINEAR_ADDR_RECORD:
192
+ if (line->byte_count != 2 && line->address != 0) {
193
+ return -1;
194
+ }
195
+
196
+ if (parser->current_rom_index != 0) {
197
+ rom_add_blob_fixed_as(parser->filename, parser->bin_buf,
198
+ parser->current_rom_index,
199
+ parser->rom_start_address, parser->as);
200
+ }
201
+
202
+ /* save next address to write,
203
+ * in case of non-contiguous block of memory */
204
+ parser->next_address_to_write = (line->data[0] << 12) |
205
+ (line->data[1] << 4);
206
+ if (line->record_type == EXT_LINEAR_ADDR_RECORD) {
207
+ parser->next_address_to_write <<= 12;
208
+ }
209
+
210
+ parser->rom_start_address = parser->next_address_to_write;
211
+ parser->current_rom_index = 0;
212
+ break;
213
+
214
+ case START_SEG_ADDR_RECORD:
215
+ if (line->byte_count != 4 && line->address != 0) {
216
+ return -1;
217
+ }
218
+
219
+ /* x86 16-bit CS:IP segmented addressing */
220
+ *(parser->start_addr) = (((line->data[0] << 8) | line->data[1]) << 4) +
221
+ ((line->data[2] << 8) | line->data[3]);
222
+ break;
223
+
224
+ case START_LINEAR_ADDR_RECORD:
225
+ if (line->byte_count != 4 && line->address != 0) {
226
+ return -1;
227
+ }
228
+
229
+ *(parser->start_addr) = ldl_be_p(line->data);
230
+ break;
231
+
232
+ default:
233
+ return -1;
234
+ }
235
+
236
+ return parser->total_size;
68
+}
237
+}
69
+
238
+
70
+static void v7m_push_stack(ARMCPU *cpu)
239
+/* return size or -1 if error */
240
+static int parse_hex_blob(const char *filename, hwaddr *addr, uint8_t *hex_blob,
241
+ size_t hex_blob_size, AddressSpace *as)
71
+{
242
+{
72
+ /* Do the "set up stack frame" part of exception entry,
243
+ bool in_process = false; /* avoid re-enter and
73
+ * similar to pseudocode PushStack().
244
+ * check whether record begin with ':' */
74
+ */
245
+ uint8_t *end = hex_blob + hex_blob_size;
75
+ CPUARMState *env = &cpu->env;
246
+ uint8_t our_checksum = 0;
76
+ uint32_t xpsr = xpsr_read(env);
247
+ uint32_t record_index = 0;
77
+
248
+ HexParser parser = {
78
+ /* Align stack pointer if the guest wants that */
249
+ .filename = filename,
79
+ if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) {
250
+ .bin_buf = g_malloc(hex_blob_size),
80
+ env->regs[13] -= 4;
251
+ .start_addr = addr,
81
+ xpsr |= 0x200;
252
+ .as = as,
82
+ }
253
+ };
83
+ /* Switch to the handler mode. */
254
+
84
+ v7m_push(env, xpsr);
255
+ rom_transaction_begin();
85
+ v7m_push(env, env->regs[15]);
256
+
86
+ v7m_push(env, env->regs[14]);
257
+ for (; hex_blob < end; ++hex_blob) {
87
+ v7m_push(env, env->regs[12]);
258
+ switch (*hex_blob) {
88
+ v7m_push(env, env->regs[3]);
259
+ case '\r':
89
+ v7m_push(env, env->regs[2]);
260
+ case '\n':
90
+ v7m_push(env, env->regs[1]);
261
+ if (!in_process) {
91
+ v7m_push(env, env->regs[0]);
262
+ break;
263
+ }
264
+
265
+ in_process = false;
266
+ if ((LEN_EXCEPT_DATA + parser.line.byte_count) * 2 !=
267
+ record_index ||
268
+ our_checksum != 0) {
269
+ parser.total_size = -1;
270
+ goto out;
271
+ }
272
+
273
+ if (handle_record_type(&parser) == -1) {
274
+ parser.total_size = -1;
275
+ goto out;
276
+ }
277
+ break;
278
+
279
+ /* start of a new record. */
280
+ case ':':
281
+ memset(&parser.line, 0, sizeof(HexLine));
282
+ in_process = true;
283
+ record_index = 0;
284
+ break;
285
+
286
+ /* decoding lines */
287
+ default:
288
+ if (!parse_record(&parser.line, &our_checksum, *hex_blob,
289
+ &record_index, in_process)) {
290
+ parser.total_size = -1;
291
+ goto out;
292
+ }
293
+ break;
294
+ }
295
+ }
296
+
297
+out:
298
+ g_free(parser.bin_buf);
299
+ rom_transaction_end(parser.total_size != -1);
300
+ return parser.total_size;
92
+}
301
+}
93
+
302
+
94
static void do_v7m_exception_exit(CPUARMState *env)
303
+/* return size or -1 if error */
95
{
304
+int load_targphys_hex_as(const char *filename, hwaddr *entry, AddressSpace *as)
96
uint32_t type;
305
+{
97
@@ -XXX,XX +XXX,XX @@ static void arm_log_exception(int idx)
306
+ gsize hex_blob_size;
98
}
307
+ gchar *hex_blob;
99
}
308
+ int total_size = 0;
100
309
+
101
-static uint32_t arm_v7m_load_vector(ARMCPU *cpu)
310
+ if (!g_file_get_contents(filename, &hex_blob, &hex_blob_size, NULL)) {
102
-
311
+ return -1;
103
-{
312
+ }
104
- CPUState *cs = CPU(cpu);
313
+
105
- CPUARMState *env = &cpu->env;
314
+ total_size = parse_hex_blob(filename, entry, (uint8_t *)hex_blob,
106
- MemTxResult result;
315
+ hex_blob_size, as);
107
- hwaddr vec = env->v7m.vecbase + env->v7m.exception * 4;
316
+
108
- uint32_t addr;
317
+ g_free(hex_blob);
109
-
318
+ return total_size;
110
- addr = address_space_ldl(cs->as, vec,
319
+}
111
- MEMTXATTRS_UNSPECIFIED, &result);
112
- if (result != MEMTX_OK) {
113
- /* Architecturally this should cause a HardFault setting HSFR.VECTTBL,
114
- * which would then be immediately followed by our failing to load
115
- * the entry vector for that HardFault, which is a Lockup case.
116
- * Since we don't model Lockup, we just report this guest error
117
- * via cpu_abort().
118
- */
119
- cpu_abort(cs, "Failed to read from exception vector table "
120
- "entry %08x\n", (unsigned)vec);
121
- }
122
- return addr;
123
-}
124
-
125
void arm_v7m_cpu_do_interrupt(CPUState *cs)
126
{
127
ARMCPU *cpu = ARM_CPU(cs);
128
CPUARMState *env = &cpu->env;
129
- uint32_t xpsr = xpsr_read(env);
130
uint32_t lr;
131
- uint32_t addr;
132
133
arm_log_exception(cs->exception_index);
134
135
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
136
return; /* Never happens. Keep compiler happy. */
137
}
138
139
- armv7m_nvic_acknowledge_irq(env->nvic);
140
-
141
+ v7m_push_stack(cpu);
142
+ v7m_exception_taken(cpu, lr);
143
qemu_log_mask(CPU_LOG_INT, "... as %d\n", env->v7m.exception);
144
-
145
- /* Align stack pointer if the guest wants that */
146
- if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) {
147
- env->regs[13] -= 4;
148
- xpsr |= 0x200;
149
- }
150
- /* Switch to the handler mode. */
151
- v7m_push(env, xpsr);
152
- v7m_push(env, env->regs[15]);
153
- v7m_push(env, env->regs[14]);
154
- v7m_push(env, env->regs[12]);
155
- v7m_push(env, env->regs[3]);
156
- v7m_push(env, env->regs[2]);
157
- v7m_push(env, env->regs[1]);
158
- v7m_push(env, env->regs[0]);
159
- switch_v7m_sp(env, 0);
160
- /* Clear IT bits */
161
- env->condexec_bits = 0;
162
- env->regs[14] = lr;
163
- addr = arm_v7m_load_vector(cpu);
164
- env->regs[15] = addr & 0xfffffffe;
165
- env->thumb = addr & 1;
166
}
167
168
/* Function used to synchronize QEMU's AArch64 register set with AArch32
169
--
320
--
170
2.7.4
321
2.18.0
171
322
172
323
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
From: Su Hang <suhang16@mails.ucas.ac.cn>
2
2
3
This adds the BCM2835 GPIO controller.
3
'test.hex' file is a memory test pattern stored in Hexadecimal Object
4
Format. It loads at 0x10000 in RAM and contains values from 0 through
5
255.
4
6
5
It currently implements:
7
The test case verifies that the expected memory test pattern was loaded.
6
- The 54 GPIOs as outputs (qemu_irq)
7
- The SD controller selection via alternate function of GPIOs 48-53
8
8
9
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Message-id: 20170224164021.9066-4-clement.deschamps@antfield.fr
10
Suggested-by: Steffen Gortz <qemu.ml@steffen-goertz.de>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Suggested-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Signed-off-by: Su Hang <suhang16@mails.ucas.ac.cn>
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
[PMM: changed qtest_startf() to qtest_initf() to work with
16
current master after the refactoring in commit 88b988c895e3c2]
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
18
---
14
hw/gpio/Makefile.objs | 1 +
19
configure | 4 +++
15
include/hw/gpio/bcm2835_gpio.h | 39 +++++
20
tests/Makefile.include | 2 ++
16
hw/gpio/bcm2835_gpio.c | 353 +++++++++++++++++++++++++++++++++++++++++
21
tests/hexloader-test.c | 45 ++++++++++++++++++++++++++++
17
3 files changed, 393 insertions(+)
22
MAINTAINERS | 6 ++++
18
create mode 100644 include/hw/gpio/bcm2835_gpio.h
23
tests/hex-loader-check-data/test.hex | 18 +++++++++++
19
create mode 100644 hw/gpio/bcm2835_gpio.c
24
5 files changed, 75 insertions(+)
25
create mode 100644 tests/hexloader-test.c
26
create mode 100644 tests/hex-loader-check-data/test.hex
20
27
21
diff --git a/hw/gpio/Makefile.objs b/hw/gpio/Makefile.objs
28
diff --git a/configure b/configure
29
index XXXXXXX..XXXXXXX 100755
30
--- a/configure
31
+++ b/configure
32
@@ -XXX,XX +XXX,XX @@ for test_file in $(find $source_path/tests/acpi-test-data -type f)
33
do
34
FILES="$FILES tests/acpi-test-data$(echo $test_file | sed -e 's/.*acpi-test-data//')"
35
done
36
+for test_file in $(find $source_path/tests/hex-loader-check-data -type f)
37
+do
38
+ FILES="$FILES tests/hex-loader-check-data$(echo $test_file | sed -e 's/.*hex-loader-check-data//')"
39
+done
40
mkdir -p $DIRS
41
for f in $FILES ; do
42
if [ -e "$source_path/$f" ] && [ "$pwd_is_source_path" != "y" ]; then
43
diff --git a/tests/Makefile.include b/tests/Makefile.include
22
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/gpio/Makefile.objs
45
--- a/tests/Makefile.include
24
+++ b/hw/gpio/Makefile.objs
46
+++ b/tests/Makefile.include
25
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_GPIO_KEY) += gpio_key.o
47
@@ -XXX,XX +XXX,XX @@ check-qtest-arm-y += tests/test-arm-mptimer$(EXESUF)
26
48
gcov-files-arm-y += hw/timer/arm_mptimer.c
27
obj-$(CONFIG_OMAP) += omap_gpio.o
49
check-qtest-arm-y += tests/boot-serial-test$(EXESUF)
28
obj-$(CONFIG_IMX) += imx_gpio.o
50
check-qtest-arm-y += tests/sdhci-test$(EXESUF)
29
+obj-$(CONFIG_RASPI) += bcm2835_gpio.o
51
+check-qtest-arm-y += tests/hexloader-test$(EXESUF)
30
diff --git a/include/hw/gpio/bcm2835_gpio.h b/include/hw/gpio/bcm2835_gpio.h
52
53
check-qtest-aarch64-y = tests/numa-test$(EXESUF)
54
check-qtest-aarch64-y += tests/sdhci-test$(EXESUF)
55
@@ -XXX,XX +XXX,XX @@ tests/qmp-test$(EXESUF): tests/qmp-test.o
56
tests/device-introspect-test$(EXESUF): tests/device-introspect-test.o
57
tests/rtc-test$(EXESUF): tests/rtc-test.o
58
tests/m48t59-test$(EXESUF): tests/m48t59-test.o
59
+tests/hexloader-test$(EXESUF): tests/hexloader-test.o
60
tests/endianness-test$(EXESUF): tests/endianness-test.o
61
tests/spapr-phb-test$(EXESUF): tests/spapr-phb-test.o $(libqos-obj-y)
62
tests/prom-env-test$(EXESUF): tests/prom-env-test.o $(libqos-obj-y)
63
diff --git a/tests/hexloader-test.c b/tests/hexloader-test.c
31
new file mode 100644
64
new file mode 100644
32
index XXXXXXX..XXXXXXX
65
index XXXXXXX..XXXXXXX
33
--- /dev/null
66
--- /dev/null
34
+++ b/include/hw/gpio/bcm2835_gpio.h
67
+++ b/tests/hexloader-test.c
35
@@ -XXX,XX +XXX,XX @@
68
@@ -XXX,XX +XXX,XX @@
36
+/*
69
+/*
37
+ * Raspberry Pi (BCM2835) GPIO Controller
70
+ * QTest testcase for the Intel Hexadecimal Object File Loader
38
+ *
39
+ * Copyright (c) 2017 Antfield SAS
40
+ *
71
+ *
41
+ * Authors:
72
+ * Authors:
42
+ * Clement Deschamps <clement.deschamps@antfield.fr>
73
+ * Su Hang <suhang16@mails.ucas.ac.cn> 2018
43
+ * Luc Michel <luc.michel@antfield.fr>
44
+ *
74
+ *
45
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
75
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
46
+ * See the COPYING file in the top-level directory.
76
+ * See the COPYING file in the top-level directory.
77
+ *
47
+ */
78
+ */
48
+
79
+
49
+#ifndef BCM2835_GPIO_H
80
+#include "qemu/osdep.h"
50
+#define BCM2835_GPIO_H
81
+#include "libqtest.h"
51
+
82
+
52
+#include "hw/sd/sd.h"
83
+/* Load 'test.hex' and verify that the in-memory contents are as expected.
84
+ * 'test.hex' is a memory test pattern stored in Hexadecimal Object
85
+ * format. It loads at 0x10000 in RAM and contains values from 0 through
86
+ * 255.
87
+ */
88
+static void hex_loader_test(void)
89
+{
90
+ unsigned int i;
91
+ const unsigned int base_addr = 0x00010000;
53
+
92
+
54
+typedef struct BCM2835GpioState {
93
+ QTestState *s = qtest_initf(
55
+ SysBusDevice parent_obj;
94
+ "-M vexpress-a9 -nographic -device loader,file=tests/hex-loader-check-data/test.hex");
56
+
95
+
57
+ MemoryRegion iomem;
96
+ for (i = 0; i < 256; ++i) {
97
+ uint8_t val = qtest_readb(s, base_addr + i);
98
+ g_assert_cmpuint(i, ==, val);
99
+ }
100
+ qtest_quit(s);
101
+}
58
+
102
+
59
+ /* SDBus selector */
103
+int main(int argc, char **argv)
60
+ SDBus sdbus;
104
+{
61
+ SDBus *sdbus_sdhci;
105
+ int ret;
62
+ SDBus *sdbus_sdhost;
63
+
106
+
64
+ uint8_t fsel[54];
107
+ g_test_init(&argc, &argv, NULL);
65
+ uint32_t lev0, lev1;
66
+ uint8_t sd_fsel;
67
+ qemu_irq out[54];
68
+} BCM2835GpioState;
69
+
108
+
70
+#define TYPE_BCM2835_GPIO "bcm2835_gpio"
109
+ qtest_add_func("/tmp/hex_loader", hex_loader_test);
71
+#define BCM2835_GPIO(obj) \
110
+ ret = g_test_run();
72
+ OBJECT_CHECK(BCM2835GpioState, (obj), TYPE_BCM2835_GPIO)
73
+
111
+
74
+#endif
112
+ return ret;
75
diff --git a/hw/gpio/bcm2835_gpio.c b/hw/gpio/bcm2835_gpio.c
113
+}
114
diff --git a/MAINTAINERS b/MAINTAINERS
115
index XXXXXXX..XXXXXXX 100644
116
--- a/MAINTAINERS
117
+++ b/MAINTAINERS
118
@@ -XXX,XX +XXX,XX @@ F: hw/core/generic-loader.c
119
F: include/hw/core/generic-loader.h
120
F: docs/generic-loader.txt
121
122
+Intel Hexadecimal Object File Loader
123
+M: Su Hang <suhang16@mails.ucas.ac.cn>
124
+S: Maintained
125
+F: tests/hexloader-test.c
126
+F: tests/hex-loader-check-data/test.hex
127
+
128
CHRP NVRAM
129
M: Thomas Huth <thuth@redhat.com>
130
S: Maintained
131
diff --git a/tests/hex-loader-check-data/test.hex b/tests/hex-loader-check-data/test.hex
76
new file mode 100644
132
new file mode 100644
77
index XXXXXXX..XXXXXXX
133
index XXXXXXX..XXXXXXX
78
--- /dev/null
134
--- /dev/null
79
+++ b/hw/gpio/bcm2835_gpio.c
135
+++ b/tests/hex-loader-check-data/test.hex
80
@@ -XXX,XX +XXX,XX @@
136
@@ -XXX,XX +XXX,XX @@
81
+/*
137
+:020000040001F9
82
+ * Raspberry Pi (BCM2835) GPIO Controller
138
+:10000000000102030405060708090a0b0c0d0e0f78
83
+ *
139
+:10001000101112131415161718191a1b1c1d1e1f68
84
+ * Copyright (c) 2017 Antfield SAS
140
+:10002000202122232425262728292a2b2c2d2e2f58
85
+ *
141
+:10003000303132333435363738393a3b3c3d3e3f48
86
+ * Authors:
142
+:10004000404142434445464748494a4b4c4d4e4f38
87
+ * Clement Deschamps <clement.deschamps@antfield.fr>
143
+:10005000505152535455565758595a5b5c5d5e5f28
88
+ * Luc Michel <luc.michel@antfield.fr>
144
+:10006000606162636465666768696a6b6c6d6e6f18
89
+ *
145
+:10007000707172737475767778797a7b7c7d7e7f08
90
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
146
+:10008000808182838485868788898a8b8c8d8e8ff8
91
+ * See the COPYING file in the top-level directory.
147
+:10009000909192939495969798999a9b9c9d9e9fe8
92
+ */
148
+:1000a000a0a1a2a3a4a5a6a7a8a9aaabacadaeafd8
93
+
149
+:1000b000b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc8
94
+#include "qemu/osdep.h"
150
+:1000c000c0c1c2c3c4c5c6c7c8c9cacbcccdcecfb8
95
+#include "qemu/log.h"
151
+:1000d000d0d1d2d3d4d5d6d7d8d9dadbdcdddedfa8
96
+#include "qemu/timer.h"
152
+:1000e000e0e1e2e3e4e5e6e7e8e9eaebecedeeef98
97
+#include "qapi/error.h"
153
+:1000f000f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff88
98
+#include "hw/sysbus.h"
154
+:00000001FF
99
+#include "hw/sd/sd.h"
100
+#include "hw/gpio/bcm2835_gpio.h"
101
+
102
+#define GPFSEL0 0x00
103
+#define GPFSEL1 0x04
104
+#define GPFSEL2 0x08
105
+#define GPFSEL3 0x0C
106
+#define GPFSEL4 0x10
107
+#define GPFSEL5 0x14
108
+#define GPSET0 0x1C
109
+#define GPSET1 0x20
110
+#define GPCLR0 0x28
111
+#define GPCLR1 0x2C
112
+#define GPLEV0 0x34
113
+#define GPLEV1 0x38
114
+#define GPEDS0 0x40
115
+#define GPEDS1 0x44
116
+#define GPREN0 0x4C
117
+#define GPREN1 0x50
118
+#define GPFEN0 0x58
119
+#define GPFEN1 0x5C
120
+#define GPHEN0 0x64
121
+#define GPHEN1 0x68
122
+#define GPLEN0 0x70
123
+#define GPLEN1 0x74
124
+#define GPAREN0 0x7C
125
+#define GPAREN1 0x80
126
+#define GPAFEN0 0x88
127
+#define GPAFEN1 0x8C
128
+#define GPPUD 0x94
129
+#define GPPUDCLK0 0x98
130
+#define GPPUDCLK1 0x9C
131
+
132
+static uint32_t gpfsel_get(BCM2835GpioState *s, uint8_t reg)
133
+{
134
+ int i;
135
+ uint32_t value = 0;
136
+ for (i = 0; i < 10; i++) {
137
+ uint32_t index = 10 * reg + i;
138
+ if (index < sizeof(s->fsel)) {
139
+ value |= (s->fsel[index] & 0x7) << (3 * i);
140
+ }
141
+ }
142
+ return value;
143
+}
144
+
145
+static void gpfsel_set(BCM2835GpioState *s, uint8_t reg, uint32_t value)
146
+{
147
+ int i;
148
+ for (i = 0; i < 10; i++) {
149
+ uint32_t index = 10 * reg + i;
150
+ if (index < sizeof(s->fsel)) {
151
+ int fsel = (value >> (3 * i)) & 0x7;
152
+ s->fsel[index] = fsel;
153
+ }
154
+ }
155
+
156
+ /* SD controller selection (48-53) */
157
+ if (s->sd_fsel != 0
158
+ && (s->fsel[48] == 0) /* SD_CLK_R */
159
+ && (s->fsel[49] == 0) /* SD_CMD_R */
160
+ && (s->fsel[50] == 0) /* SD_DATA0_R */
161
+ && (s->fsel[51] == 0) /* SD_DATA1_R */
162
+ && (s->fsel[52] == 0) /* SD_DATA2_R */
163
+ && (s->fsel[53] == 0) /* SD_DATA3_R */
164
+ ) {
165
+ /* SDHCI controller selected */
166
+ sdbus_reparent_card(s->sdbus_sdhost, s->sdbus_sdhci);
167
+ s->sd_fsel = 0;
168
+ } else if (s->sd_fsel != 4
169
+ && (s->fsel[48] == 4) /* SD_CLK_R */
170
+ && (s->fsel[49] == 4) /* SD_CMD_R */
171
+ && (s->fsel[50] == 4) /* SD_DATA0_R */
172
+ && (s->fsel[51] == 4) /* SD_DATA1_R */
173
+ && (s->fsel[52] == 4) /* SD_DATA2_R */
174
+ && (s->fsel[53] == 4) /* SD_DATA3_R */
175
+ ) {
176
+ /* SDHost controller selected */
177
+ sdbus_reparent_card(s->sdbus_sdhci, s->sdbus_sdhost);
178
+ s->sd_fsel = 4;
179
+ }
180
+}
181
+
182
+static int gpfsel_is_out(BCM2835GpioState *s, int index)
183
+{
184
+ if (index >= 0 && index < 54) {
185
+ return s->fsel[index] == 1;
186
+ }
187
+ return 0;
188
+}
189
+
190
+static void gpset(BCM2835GpioState *s,
191
+ uint32_t val, uint8_t start, uint8_t count, uint32_t *lev)
192
+{
193
+ uint32_t changes = val & ~*lev;
194
+ uint32_t cur = 1;
195
+
196
+ int i;
197
+ for (i = 0; i < count; i++) {
198
+ if ((changes & cur) && (gpfsel_is_out(s, start + i))) {
199
+ qemu_set_irq(s->out[start + i], 1);
200
+ }
201
+ cur <<= 1;
202
+ }
203
+
204
+ *lev |= val;
205
+}
206
+
207
+static void gpclr(BCM2835GpioState *s,
208
+ uint32_t val, uint8_t start, uint8_t count, uint32_t *lev)
209
+{
210
+ uint32_t changes = val & *lev;
211
+ uint32_t cur = 1;
212
+
213
+ int i;
214
+ for (i = 0; i < count; i++) {
215
+ if ((changes & cur) && (gpfsel_is_out(s, start + i))) {
216
+ qemu_set_irq(s->out[start + i], 0);
217
+ }
218
+ cur <<= 1;
219
+ }
220
+
221
+ *lev &= ~val;
222
+}
223
+
224
+static uint64_t bcm2835_gpio_read(void *opaque, hwaddr offset,
225
+ unsigned size)
226
+{
227
+ BCM2835GpioState *s = (BCM2835GpioState *)opaque;
228
+
229
+ switch (offset) {
230
+ case GPFSEL0:
231
+ case GPFSEL1:
232
+ case GPFSEL2:
233
+ case GPFSEL3:
234
+ case GPFSEL4:
235
+ case GPFSEL5:
236
+ return gpfsel_get(s, offset / 4);
237
+ case GPSET0:
238
+ case GPSET1:
239
+ /* Write Only */
240
+ return 0;
241
+ case GPCLR0:
242
+ case GPCLR1:
243
+ /* Write Only */
244
+ return 0;
245
+ case GPLEV0:
246
+ return s->lev0;
247
+ case GPLEV1:
248
+ return s->lev1;
249
+ case GPEDS0:
250
+ case GPEDS1:
251
+ case GPREN0:
252
+ case GPREN1:
253
+ case GPFEN0:
254
+ case GPFEN1:
255
+ case GPHEN0:
256
+ case GPHEN1:
257
+ case GPLEN0:
258
+ case GPLEN1:
259
+ case GPAREN0:
260
+ case GPAREN1:
261
+ case GPAFEN0:
262
+ case GPAFEN1:
263
+ case GPPUD:
264
+ case GPPUDCLK0:
265
+ case GPPUDCLK1:
266
+ /* Not implemented */
267
+ return 0;
268
+ default:
269
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
270
+ __func__, offset);
271
+ break;
272
+ }
273
+
274
+ return 0;
275
+}
276
+
277
+static void bcm2835_gpio_write(void *opaque, hwaddr offset,
278
+ uint64_t value, unsigned size)
279
+{
280
+ BCM2835GpioState *s = (BCM2835GpioState *)opaque;
281
+
282
+ switch (offset) {
283
+ case GPFSEL0:
284
+ case GPFSEL1:
285
+ case GPFSEL2:
286
+ case GPFSEL3:
287
+ case GPFSEL4:
288
+ case GPFSEL5:
289
+ gpfsel_set(s, offset / 4, value);
290
+ break;
291
+ case GPSET0:
292
+ gpset(s, value, 0, 32, &s->lev0);
293
+ break;
294
+ case GPSET1:
295
+ gpset(s, value, 32, 22, &s->lev1);
296
+ break;
297
+ case GPCLR0:
298
+ gpclr(s, value, 0, 32, &s->lev0);
299
+ break;
300
+ case GPCLR1:
301
+ gpclr(s, value, 32, 22, &s->lev1);
302
+ break;
303
+ case GPLEV0:
304
+ case GPLEV1:
305
+ /* Read Only */
306
+ break;
307
+ case GPEDS0:
308
+ case GPEDS1:
309
+ case GPREN0:
310
+ case GPREN1:
311
+ case GPFEN0:
312
+ case GPFEN1:
313
+ case GPHEN0:
314
+ case GPHEN1:
315
+ case GPLEN0:
316
+ case GPLEN1:
317
+ case GPAREN0:
318
+ case GPAREN1:
319
+ case GPAFEN0:
320
+ case GPAFEN1:
321
+ case GPPUD:
322
+ case GPPUDCLK0:
323
+ case GPPUDCLK1:
324
+ /* Not implemented */
325
+ break;
326
+ default:
327
+ goto err_out;
328
+ }
329
+ return;
330
+
331
+err_out:
332
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
333
+ __func__, offset);
334
+}
335
+
336
+static void bcm2835_gpio_reset(DeviceState *dev)
337
+{
338
+ BCM2835GpioState *s = BCM2835_GPIO(dev);
339
+
340
+ int i;
341
+ for (i = 0; i < 6; i++) {
342
+ gpfsel_set(s, i, 0);
343
+ }
344
+
345
+ s->sd_fsel = 0;
346
+
347
+ /* SDHCI is selected by default */
348
+ sdbus_reparent_card(&s->sdbus, s->sdbus_sdhci);
349
+
350
+ s->lev0 = 0;
351
+ s->lev1 = 0;
352
+}
353
+
354
+static const MemoryRegionOps bcm2835_gpio_ops = {
355
+ .read = bcm2835_gpio_read,
356
+ .write = bcm2835_gpio_write,
357
+ .endianness = DEVICE_NATIVE_ENDIAN,
358
+};
359
+
360
+static const VMStateDescription vmstate_bcm2835_gpio = {
361
+ .name = "bcm2835_gpio",
362
+ .version_id = 1,
363
+ .minimum_version_id = 1,
364
+ .fields = (VMStateField[]) {
365
+ VMSTATE_UINT8_ARRAY(fsel, BCM2835GpioState, 54),
366
+ VMSTATE_UINT32(lev0, BCM2835GpioState),
367
+ VMSTATE_UINT32(lev1, BCM2835GpioState),
368
+ VMSTATE_UINT8(sd_fsel, BCM2835GpioState),
369
+ VMSTATE_END_OF_LIST()
370
+ }
371
+};
372
+
373
+static void bcm2835_gpio_init(Object *obj)
374
+{
375
+ BCM2835GpioState *s = BCM2835_GPIO(obj);
376
+ DeviceState *dev = DEVICE(obj);
377
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
378
+
379
+ qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
380
+ TYPE_SD_BUS, DEVICE(s), "sd-bus");
381
+
382
+ memory_region_init_io(&s->iomem, obj,
383
+ &bcm2835_gpio_ops, s, "bcm2835_gpio", 0x1000);
384
+ sysbus_init_mmio(sbd, &s->iomem);
385
+ qdev_init_gpio_out(dev, s->out, 54);
386
+}
387
+
388
+static void bcm2835_gpio_realize(DeviceState *dev, Error **errp)
389
+{
390
+ BCM2835GpioState *s = BCM2835_GPIO(dev);
391
+ Object *obj;
392
+ Error *err = NULL;
393
+
394
+ obj = object_property_get_link(OBJECT(dev), "sdbus-sdhci", &err);
395
+ if (obj == NULL) {
396
+ error_setg(errp, "%s: required sdhci link not found: %s",
397
+ __func__, error_get_pretty(err));
398
+ return;
399
+ }
400
+ s->sdbus_sdhci = SD_BUS(obj);
401
+
402
+ obj = object_property_get_link(OBJECT(dev), "sdbus-sdhost", &err);
403
+ if (obj == NULL) {
404
+ error_setg(errp, "%s: required sdhost link not found: %s",
405
+ __func__, error_get_pretty(err));
406
+ return;
407
+ }
408
+ s->sdbus_sdhost = SD_BUS(obj);
409
+}
410
+
411
+static void bcm2835_gpio_class_init(ObjectClass *klass, void *data)
412
+{
413
+ DeviceClass *dc = DEVICE_CLASS(klass);
414
+
415
+ dc->vmsd = &vmstate_bcm2835_gpio;
416
+ dc->realize = &bcm2835_gpio_realize;
417
+ dc->reset = &bcm2835_gpio_reset;
418
+}
419
+
420
+static const TypeInfo bcm2835_gpio_info = {
421
+ .name = TYPE_BCM2835_GPIO,
422
+ .parent = TYPE_SYS_BUS_DEVICE,
423
+ .instance_size = sizeof(BCM2835GpioState),
424
+ .instance_init = bcm2835_gpio_init,
425
+ .class_init = bcm2835_gpio_class_init,
426
+};
427
+
428
+static void bcm2835_gpio_register_types(void)
429
+{
430
+ type_register_static(&bcm2835_gpio_info);
431
+}
432
+
433
+type_init(bcm2835_gpio_register_types)
434
--
155
--
435
2.7.4
156
2.18.0
436
157
437
158
diff view generated by jsdifflib
1
From: Igor Mammedov <imammedo@redhat.com>
1
From: Trent Piepho <tpiepho@impinj.com>
2
2
3
object_new(FOO) returns an object with ref_cnt == 1
3
The current emulation will clear the XCH bit when a burst finishes.
4
and following
4
This is not quite correct. According to the i.MX7d referemce manual,
5
object_property_set_bool(cpuobj, true, "realized", NULL)
5
Rev 0.1, §10.1.7.3:
6
set parent of cpuobj to '/machine/unattached' which makes
7
ref_cnt == 2.
8
6
9
Since machvirt_init() doesn't take ownership of cpuobj
7
This bit [XCH] is cleared automatically when all data in the TXFIFO
10
returned by object_new() it should explicitly drop
8
and the shift register has been shifted out.
11
reference to cpuobj when dangling pointer is about to
12
go out of scope like it's done pc_new_cpu() to avoid
13
object leak.
14
9
15
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
10
So XCH should be cleared when the FIFO empties, not on completion of a
16
Message-id: 1487253461-269218-1-git-send-email-imammedo@redhat.com
11
burst. The FIFO is 64 x 32 bits = 2048 bits, while the max burst size
12
is larger at 4096 bits. So it's possible that the burst is not finished
13
after the TXFIFO empties.
14
15
Sending a large block (> 2048 bits) with the Linux driver will use a
16
burst that is larger than the TXFIFO. After the TXFIFO has emptied XCH
17
does not become unset, as the burst is not yet finished.
18
19
What should happen after the TXFIFO empties is the driver will refill it
20
and set XCH. The rising edge of XCH will trigger another transfer to
21
begin. However, since the emulation does not set XCH to 0, there is no
22
rising edge and the next trasfer never begins.
23
24
Signed-off-by: Trent Piepho <tpiepho@impinj.com>
25
Message-id: 20180731201056.29257-1-tpiepho@impinj.com
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
26
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
28
---
20
hw/arm/virt.c | 1 +
29
hw/ssi/imx_spi.c | 3 +--
21
1 file changed, 1 insertion(+)
30
1 file changed, 1 insertion(+), 2 deletions(-)
22
31
23
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
32
diff --git a/hw/ssi/imx_spi.c b/hw/ssi/imx_spi.c
24
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/arm/virt.c
34
--- a/hw/ssi/imx_spi.c
26
+++ b/hw/arm/virt.c
35
+++ b/hw/ssi/imx_spi.c
27
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
36
@@ -XXX,XX +XXX,XX @@ static void imx_spi_flush_txfifo(IMXSPIState *s)
28
}
37
}
29
38
30
object_property_set_bool(cpuobj, true, "realized", NULL);
39
if (s->burst_length <= 0) {
31
+ object_unref(cpuobj);
40
- s->regs[ECSPI_CONREG] &= ~ECSPI_CONREG_XCH;
41
-
42
if (!imx_spi_is_multiple_master_burst(s)) {
43
s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TC;
44
break;
45
@@ -XXX,XX +XXX,XX @@ static void imx_spi_flush_txfifo(IMXSPIState *s)
46
47
if (fifo32_is_empty(&s->tx_fifo)) {
48
s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TC;
49
+ s->regs[ECSPI_CONREG] &= ~ECSPI_CONREG_XCH;
32
}
50
}
33
fdt_add_timer_nodes(vms);
51
34
fdt_add_cpu_nodes(vms);
52
/* TODO: We should also use TDR and RDR bits */
35
--
53
--
36
2.7.4
54
2.18.0
37
55
38
56
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
From: Joel Stanley <joel@jms.id.au>
2
2
3
The v7M exception architecture requires that if a synchronous
3
The SDMC on the ast2500 has 170 registers.
4
exception cannot be taken immediately (because it is disabled
5
or at too low a priority) then it should be escalated to
6
HardFault (and the HardFault exception is then taken).
7
Implement this escalation logic.
8
4
9
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
5
Signed-off-by: Joel Stanley <joel@jms.id.au>
10
[PMM: extracted from another patch]
6
Reviewed-by: Cédric Le Goater <clg@kaod.org>
7
Tested-by: Cédric Le Goater <clg@kaod.org>
8
Message-id: 20180807075757.7242-2-joel@jms.id.au
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
---
10
---
14
hw/intc/armv7m_nvic.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++
11
include/hw/misc/aspeed_sdmc.h | 2 +-
15
target/arm/helper.c | 2 --
12
1 file changed, 1 insertion(+), 1 deletion(-)
16
2 files changed, 53 insertions(+), 2 deletions(-)
17
13
18
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
14
diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h
19
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/intc/armv7m_nvic.c
16
--- a/include/hw/misc/aspeed_sdmc.h
21
+++ b/hw/intc/armv7m_nvic.c
17
+++ b/include/hw/misc/aspeed_sdmc.h
22
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq)
18
@@ -XXX,XX +XXX,XX @@
23
19
#define TYPE_ASPEED_SDMC "aspeed.sdmc"
24
vec = &s->vectors[irq];
20
#define ASPEED_SDMC(obj) OBJECT_CHECK(AspeedSDMCState, (obj), TYPE_ASPEED_SDMC)
25
trace_nvic_set_pending(irq, vec->enabled, vec->prio);
21
26
+
22
-#define ASPEED_SDMC_NR_REGS (0x8 >> 2)
27
+
23
+#define ASPEED_SDMC_NR_REGS (0x174 >> 2)
28
+ if (irq >= ARMV7M_EXCP_HARD && irq < ARMV7M_EXCP_PENDSV) {
24
29
+ /* If a synchronous exception is pending then it may be
25
typedef struct AspeedSDMCState {
30
+ * escalated to HardFault if:
26
/*< private >*/
31
+ * * it is equal or lower priority to current execution
32
+ * * it is disabled
33
+ * (ie we need to take it immediately but we can't do so).
34
+ * Asynchronous exceptions (and interrupts) simply remain pending.
35
+ *
36
+ * For QEMU, we don't have any imprecise (asynchronous) faults,
37
+ * so we can assume that PREFETCH_ABORT and DATA_ABORT are always
38
+ * synchronous.
39
+ * Debug exceptions are awkward because only Debug exceptions
40
+ * resulting from the BKPT instruction should be escalated,
41
+ * but we don't currently implement any Debug exceptions other
42
+ * than those that result from BKPT, so we treat all debug exceptions
43
+ * as needing escalation.
44
+ *
45
+ * This all means we can identify whether to escalate based only on
46
+ * the exception number and don't (yet) need the caller to explicitly
47
+ * tell us whether this exception is synchronous or not.
48
+ */
49
+ int running = nvic_exec_prio(s);
50
+ bool escalate = false;
51
+
52
+ if (vec->prio >= running) {
53
+ trace_nvic_escalate_prio(irq, vec->prio, running);
54
+ escalate = true;
55
+ } else if (!vec->enabled) {
56
+ trace_nvic_escalate_disabled(irq);
57
+ escalate = true;
58
+ }
59
+
60
+ if (escalate) {
61
+ if (running < 0) {
62
+ /* We want to escalate to HardFault but we can't take a
63
+ * synchronous HardFault at this point either. This is a
64
+ * Lockup condition due to a guest bug. We don't model
65
+ * Lockup, so report via cpu_abort() instead.
66
+ */
67
+ cpu_abort(&s->cpu->parent_obj,
68
+ "Lockup: can't escalate %d to HardFault "
69
+ "(current priority %d)\n", irq, running);
70
+ }
71
+
72
+ /* We can do the escalation, so we take HardFault instead */
73
+ irq = ARMV7M_EXCP_HARD;
74
+ vec = &s->vectors[irq];
75
+ s->cpu->env.v7m.hfsr |= R_V7M_HFSR_FORCED_MASK;
76
+ }
77
+ }
78
+
79
if (!vec->pending) {
80
vec->pending = 1;
81
nvic_irq_update(s);
82
diff --git a/target/arm/helper.c b/target/arm/helper.c
83
index XXXXXXX..XXXXXXX 100644
84
--- a/target/arm/helper.c
85
+++ b/target/arm/helper.c
86
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
87
88
/* For exceptions we just mark as pending on the NVIC, and let that
89
handle it. */
90
- /* TODO: Need to escalate if the current priority is higher than the
91
- one we're raising. */
92
switch (cs->exception_index) {
93
case EXCP_UDEF:
94
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
95
--
27
--
96
2.7.4
28
2.18.0
97
29
98
30
diff view generated by jsdifflib
1
Rename the nvic_state struct to NVICState, to match
1
From: Joel Stanley <joel@jms.id.au>
2
our naming conventions.
3
2
3
This fixes the intended protection of read-only values in the
4
configuration register. They were being always set to zero by mistake.
5
6
The read-only fields depend on the configured memory size of the system,
7
so they cannot be fixed at compile time. The most straight forward
8
option was to store them in the state structure.
9
10
Signed-off-by: Joel Stanley <joel@jms.id.au>
11
Reviewed-by: Cédric Le Goater <clg@kaod.org>
12
Tested-by: Cédric Le Goater <clg@kaod.org>
13
Message-id: 20180807075757.7242-3-joel@jms.id.au
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
---
15
---
8
hw/intc/armv7m_nvic.c | 44 ++++++++++++++++++++++----------------------
16
include/hw/misc/aspeed_sdmc.h | 1 +
9
1 file changed, 22 insertions(+), 22 deletions(-)
17
hw/misc/aspeed_sdmc.c | 27 ++++++++-------------------
18
2 files changed, 9 insertions(+), 19 deletions(-)
10
19
11
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
20
diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h
12
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/intc/armv7m_nvic.c
22
--- a/include/hw/misc/aspeed_sdmc.h
14
+++ b/hw/intc/armv7m_nvic.c
23
+++ b/include/hw/misc/aspeed_sdmc.h
15
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSDMCState {
16
#include "gic_internal.h"
25
uint32_t silicon_rev;
17
#include "qemu/log.h"
26
uint32_t ram_bits;
18
27
uint64_t ram_size;
19
-typedef struct {
28
+ uint32_t fixed_conf;
20
+typedef struct NVICState {
29
21
GICState gic;
30
} AspeedSDMCState;
22
ARMCPU *cpu;
31
23
struct {
32
diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
24
@@ -XXX,XX +XXX,XX @@ typedef struct {
33
index XXXXXXX..XXXXXXX 100644
25
MemoryRegion container;
34
--- a/hw/misc/aspeed_sdmc.c
26
uint32_t num_irq;
35
+++ b/hw/misc/aspeed_sdmc.c
27
qemu_irq sysresetreq;
36
@@ -XXX,XX +XXX,XX @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
28
-} nvic_state;
37
case AST2400_A0_SILICON_REV:
29
+} NVICState;
38
case AST2400_A1_SILICON_REV:
30
39
data &= ~ASPEED_SDMC_READONLY_MASK;
31
#define TYPE_NVIC "armv7m_nvic"
40
+ data |= s->fixed_conf;
32
/**
41
break;
33
@@ -XXX,XX +XXX,XX @@ typedef struct NVICClass {
42
case AST2500_A0_SILICON_REV:
34
#define NVIC_GET_CLASS(obj) \
43
case AST2500_A1_SILICON_REV:
35
OBJECT_GET_CLASS(NVICClass, (obj), TYPE_NVIC)
44
data &= ~ASPEED_SDMC_AST2500_READONLY_MASK;
36
#define NVIC(obj) \
45
+ data |= s->fixed_conf;
37
- OBJECT_CHECK(nvic_state, (obj), TYPE_NVIC)
46
break;
38
+ OBJECT_CHECK(NVICState, (obj), TYPE_NVIC)
47
default:
39
48
g_assert_not_reached();
40
static const uint8_t nvic_id[] = {
49
@@ -XXX,XX +XXX,XX @@ static void aspeed_sdmc_reset(DeviceState *dev)
41
0x00, 0xb0, 0x1b, 0x00, 0x0d, 0xe0, 0x05, 0xb1
50
memset(s->regs, 0, sizeof(s->regs));
42
@@ -XXX,XX +XXX,XX @@ static const uint8_t nvic_id[] = {
51
43
int system_clock_scale;
52
/* Set ram size bit and defaults values */
44
53
- switch (s->silicon_rev) {
45
/* Conversion factor from qemu timer to SysTick frequencies. */
54
- case AST2400_A0_SILICON_REV:
46
-static inline int64_t systick_scale(nvic_state *s)
55
- case AST2400_A1_SILICON_REV:
47
+static inline int64_t systick_scale(NVICState *s)
56
- s->regs[R_CONF] |=
48
{
57
- ASPEED_SDMC_VGA_COMPAT |
49
if (s->systick.control & SYSTICK_CLKSOURCE)
58
- ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
50
return system_clock_scale;
59
- break;
51
@@ -XXX,XX +XXX,XX @@ static inline int64_t systick_scale(nvic_state *s)
60
-
52
return 1000;
61
- case AST2500_A0_SILICON_REV:
62
- case AST2500_A1_SILICON_REV:
63
- s->regs[R_CONF] |=
64
- ASPEED_SDMC_HW_VERSION(1) |
65
- ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB) |
66
- ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
67
- break;
68
-
69
- default:
70
- g_assert_not_reached();
71
- }
72
+ s->regs[R_CONF] = s->fixed_conf;
53
}
73
}
54
74
55
-static void systick_reload(nvic_state *s, int reset)
75
static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
56
+static void systick_reload(NVICState *s, int reset)
76
@@ -XXX,XX +XXX,XX @@ static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
57
{
77
case AST2400_A0_SILICON_REV:
58
/* The Cortex-M3 Devices Generic User Guide says that "When the
78
case AST2400_A1_SILICON_REV:
59
* ENABLE bit is set to 1, the counter loads the RELOAD value from the
79
s->ram_bits = ast2400_rambits(s);
60
@@ -XXX,XX +XXX,XX @@ static void systick_reload(nvic_state *s, int reset)
80
+ s->fixed_conf = ASPEED_SDMC_VGA_COMPAT |
61
81
+ ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
62
static void systick_timer_tick(void * opaque)
82
break;
63
{
83
case AST2500_A0_SILICON_REV:
64
- nvic_state *s = (nvic_state *)opaque;
84
case AST2500_A1_SILICON_REV:
65
+ NVICState *s = (NVICState *)opaque;
85
s->ram_bits = ast2500_rambits(s);
66
s->systick.control |= SYSTICK_COUNTFLAG;
86
+ s->fixed_conf = ASPEED_SDMC_HW_VERSION(1) |
67
if (s->systick.control & SYSTICK_TICKINT) {
87
+ ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB) |
68
/* Trigger the interrupt. */
88
+ ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
69
@@ -XXX,XX +XXX,XX @@ static void systick_timer_tick(void * opaque)
89
break;
70
}
90
default:
71
}
91
g_assert_not_reached();
72
73
-static void systick_reset(nvic_state *s)
74
+static void systick_reset(NVICState *s)
75
{
76
s->systick.control = 0;
77
s->systick.reload = 0;
78
@@ -XXX,XX +XXX,XX @@ static void systick_reset(nvic_state *s)
79
IRQ is #16. The internal GIC routines use #32 as the first IRQ. */
80
void armv7m_nvic_set_pending(void *opaque, int irq)
81
{
82
- nvic_state *s = (nvic_state *)opaque;
83
+ NVICState *s = (NVICState *)opaque;
84
if (irq >= 16)
85
irq += 16;
86
gic_set_pending_private(&s->gic, 0, irq);
87
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq)
88
/* Make pending IRQ active. */
89
int armv7m_nvic_acknowledge_irq(void *opaque)
90
{
91
- nvic_state *s = (nvic_state *)opaque;
92
+ NVICState *s = (NVICState *)opaque;
93
uint32_t irq;
94
95
irq = gic_acknowledge_irq(&s->gic, 0, MEMTXATTRS_UNSPECIFIED);
96
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_acknowledge_irq(void *opaque)
97
98
void armv7m_nvic_complete_irq(void *opaque, int irq)
99
{
100
- nvic_state *s = (nvic_state *)opaque;
101
+ NVICState *s = (NVICState *)opaque;
102
if (irq >= 16)
103
irq += 16;
104
gic_complete_irq(&s->gic, 0, irq, MEMTXATTRS_UNSPECIFIED);
105
}
106
107
-static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
108
+static uint32_t nvic_readl(NVICState *s, uint32_t offset)
109
{
110
ARMCPU *cpu = s->cpu;
111
uint32_t val;
112
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
113
}
114
}
115
116
-static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
117
+static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
118
{
119
ARMCPU *cpu = s->cpu;
120
uint32_t oldval;
121
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
122
static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
123
unsigned size)
124
{
125
- nvic_state *s = (nvic_state *)opaque;
126
+ NVICState *s = (NVICState *)opaque;
127
uint32_t offset = addr;
128
int i;
129
uint32_t val;
130
@@ -XXX,XX +XXX,XX @@ static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
131
static void nvic_sysreg_write(void *opaque, hwaddr addr,
132
uint64_t value, unsigned size)
133
{
134
- nvic_state *s = (nvic_state *)opaque;
135
+ NVICState *s = (NVICState *)opaque;
136
uint32_t offset = addr;
137
int i;
138
139
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_nvic = {
140
.version_id = 1,
141
.minimum_version_id = 1,
142
.fields = (VMStateField[]) {
143
- VMSTATE_UINT32(systick.control, nvic_state),
144
- VMSTATE_UINT32(systick.reload, nvic_state),
145
- VMSTATE_INT64(systick.tick, nvic_state),
146
- VMSTATE_TIMER_PTR(systick.timer, nvic_state),
147
+ VMSTATE_UINT32(systick.control, NVICState),
148
+ VMSTATE_UINT32(systick.reload, NVICState),
149
+ VMSTATE_INT64(systick.tick, NVICState),
150
+ VMSTATE_TIMER_PTR(systick.timer, NVICState),
151
VMSTATE_END_OF_LIST()
152
}
153
};
154
155
static void armv7m_nvic_reset(DeviceState *dev)
156
{
157
- nvic_state *s = NVIC(dev);
158
+ NVICState *s = NVIC(dev);
159
NVICClass *nc = NVIC_GET_CLASS(s);
160
nc->parent_reset(dev);
161
/* Common GIC reset resets to disabled; the NVIC doesn't have
162
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_reset(DeviceState *dev)
163
164
static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
165
{
166
- nvic_state *s = NVIC(dev);
167
+ NVICState *s = NVIC(dev);
168
NVICClass *nc = NVIC_GET_CLASS(s);
169
Error *local_err = NULL;
170
171
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_instance_init(Object *obj)
172
*/
173
GICState *s = ARM_GIC_COMMON(obj);
174
DeviceState *dev = DEVICE(obj);
175
- nvic_state *nvic = NVIC(obj);
176
+ NVICState *nvic = NVIC(obj);
177
/* The ARM v7m may have anything from 0 to 496 external interrupt
178
* IRQ lines. We default to 64. Other boards may differ and should
179
* set the num-irq property appropriately.
180
@@ -XXX,XX +XXX,XX @@ static const TypeInfo armv7m_nvic_info = {
181
.name = TYPE_NVIC,
182
.parent = TYPE_ARM_GIC_COMMON,
183
.instance_init = armv7m_nvic_instance_init,
184
- .instance_size = sizeof(nvic_state),
185
+ .instance_size = sizeof(NVICState),
186
.class_init = armv7m_nvic_class_init,
187
.class_size = sizeof(NVICClass),
188
};
189
--
92
--
190
2.7.4
93
2.18.0
191
94
192
95
diff view generated by jsdifflib
1
Switch to using qcrypto_random_bytes() rather than rand() as
1
From: Joel Stanley <joel@jms.id.au>
2
our source of randomness for the BCM2835 RNG.
3
2
4
If qcrypto_random_bytes() fails, we don't want to return the guest a
3
The SDRAM training routine sets the 'Enable cache initial' bit, and then
5
non-random value in case they're really using it for cryptographic
4
waits for the 'cache initial sequence' to be done.
6
purposes, so the best we can do is a fatal error. This shouldn't
7
happen unless something's broken, though.
8
5
9
In theory we could implement this device's full FIFO and interrupt
6
Have it always return done, as there is no other side effects that the
10
semantics and then just stop filling the FIFO. That's a lot of work,
7
model needs to implement. This allows the upstream u-boot training to
11
though, and doesn't really give a very nice diagnostic to the user
8
proceed on the ast2500-evb board.
12
since the guest will just seem to hang.
13
9
10
Signed-off-by: Joel Stanley <joel@jms.id.au>
11
Reviewed-by: Cédric Le Goater <clg@kaod.org>
12
Tested-by: Cédric Le Goater <clg@kaod.org>
13
Message-id: 20180807075757.7242-4-joel@jms.id.au
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
16
---
15
---
17
hw/misc/bcm2835_rng.c | 27 ++++++++++++++++++++++++++-
16
hw/misc/aspeed_sdmc.c | 1 +
18
1 file changed, 26 insertions(+), 1 deletion(-)
17
1 file changed, 1 insertion(+)
19
18
20
diff --git a/hw/misc/bcm2835_rng.c b/hw/misc/bcm2835_rng.c
19
diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
21
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/bcm2835_rng.c
21
--- a/hw/misc/aspeed_sdmc.c
23
+++ b/hw/misc/bcm2835_rng.c
22
+++ b/hw/misc/aspeed_sdmc.c
24
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
25
24
s->ram_bits = ast2500_rambits(s);
26
#include "qemu/osdep.h"
25
s->fixed_conf = ASPEED_SDMC_HW_VERSION(1) |
27
#include "qemu/log.h"
26
ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB) |
28
+#include "qapi/error.h"
27
+ ASPEED_SDMC_CACHE_INITIAL_DONE |
29
+#include "crypto/random.h"
28
ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
30
#include "hw/misc/bcm2835_rng.h"
31
32
+static uint32_t get_random_bytes(void)
33
+{
34
+ uint32_t res;
35
+ Error *err = NULL;
36
+
37
+ if (qcrypto_random_bytes((uint8_t *)&res, sizeof(res), &err) < 0) {
38
+ /* On failure we don't want to return the guest a non-random
39
+ * value in case they're really using it for cryptographic
40
+ * purposes, so the best we can do is die here.
41
+ * This shouldn't happen unless something's broken.
42
+ * In theory we could implement this device's full FIFO
43
+ * and interrupt semantics and then just stop filling the
44
+ * FIFO. That's a lot of work, though, so we assume any
45
+ * errors are systematic problems and trust that if we didn't
46
+ * fail as the guest inited then we won't fail later on
47
+ * mid-run.
48
+ */
49
+ error_report_err(err);
50
+ exit(1);
51
+ }
52
+ return res;
53
+}
54
+
55
static uint64_t bcm2835_rng_read(void *opaque, hwaddr offset,
56
unsigned size)
57
{
58
@@ -XXX,XX +XXX,XX @@ static uint64_t bcm2835_rng_read(void *opaque, hwaddr offset,
59
res = s->rng_status | (1 << 24);
60
break;
29
break;
61
case 0x8: /* rng_data */
62
- res = rand();
63
+ res = get_random_bytes();
64
break;
65
66
default:
30
default:
67
--
31
--
68
2.7.4
32
2.18.0
69
33
70
34
diff view generated by jsdifflib
1
From: Prasad J Pandit <pjp@fedoraproject.org>
1
From: Joel Stanley <joel@jms.id.au>
2
2
3
In SDHCI protocol, the 'Block count enable' bit of the Transfer
3
The ast2500 SDRAM training routine busy waits on the 'init cycle busy
4
Mode register is relevant only in multi block transfers. We need
4
state' bit in DDR PHY Control/Status register #1 (MCR60).
5
not check it in single block transfers.
6
5
7
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
6
This ensures the bit always reads zero, and allows training to
8
Message-id: 20170214185225.7994-5-ppandit@redhat.com
7
complete with upstream u-boot on the ast2500-evb.
9
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
8
9
Signed-off-by: Joel Stanley <joel@jms.id.au>
10
Reviewed-by: Cédric Le Goater <clg@kaod.org>
11
Tested-by: Cédric Le Goater <clg@kaod.org>
12
Message-id: 20180807075757.7242-5-joel@jms.id.au
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
14
---
12
hw/sd/sdhci.c | 6 +-----
15
hw/misc/aspeed_sdmc.c | 15 +++++++++++++++
13
1 file changed, 1 insertion(+), 5 deletions(-)
16
1 file changed, 15 insertions(+)
14
17
15
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
18
diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/sd/sdhci.c
20
--- a/hw/misc/aspeed_sdmc.c
18
+++ b/hw/sd/sdhci.c
21
+++ b/hw/misc/aspeed_sdmc.c
19
@@ -XXX,XX +XXX,XX @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
22
@@ -XXX,XX +XXX,XX @@
20
}
23
/* Configuration Register */
21
24
#define R_CONF (0x04 / 4)
22
/* single block SDMA transfer */
25
23
-
26
+/* Control/Status Register #1 (ast2500) */
24
static void sdhci_sdma_transfer_single_block(SDHCIState *s)
27
+#define R_STATUS1 (0x60 / 4)
25
{
28
+#define PHY_BUSY_STATE BIT(0)
26
int n;
29
+
27
@@ -XXX,XX +XXX,XX @@ static void sdhci_sdma_transfer_single_block(SDHCIState *s)
30
/*
28
sdbus_write_data(&s->sdbus, s->fifo_buffer[n]);
31
* Configuration register Ox4 (for Aspeed AST2400 SOC)
32
*
33
@@ -XXX,XX +XXX,XX @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
34
g_assert_not_reached();
29
}
35
}
30
}
36
}
31
-
37
+ if (s->silicon_rev == AST2500_A0_SILICON_REV ||
32
- if (s->trnmod & SDHC_TRNS_BLK_CNT_EN) {
38
+ s->silicon_rev == AST2500_A1_SILICON_REV) {
33
- s->blkcnt--;
39
+ switch (addr) {
34
- }
40
+ case R_STATUS1:
35
+ s->blkcnt--;
41
+ /* Will never return 'busy' */
36
42
+ data &= ~PHY_BUSY_STATE;
37
sdhci_end_transfer(s);
43
+ break;
44
+ default:
45
+ break;
46
+ }
47
+ }
48
49
s->regs[addr] = data;
38
}
50
}
39
--
51
--
40
2.7.4
52
2.18.0
41
53
42
54
diff view generated by jsdifflib
1
Add a state field for the v7M PRIGROUP register and implent
1
From: Joel Stanley <joel@jms.id.au>
2
reading and writing it. The current NVIC doesn't honour
3
the values written, but the new version will.
4
2
3
This is required to ensure u-boot SDRAM training completes.
4
5
Signed-off-by: Joel Stanley <joel@jms.id.au>
6
Reviewed-by: Cédric Le Goater <clg@kaod.org>
7
Tested-by: Cédric Le Goater <clg@kaod.org>
8
Message-id: 20180807075757.7242-6-joel@jms.id.au
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
---
10
---
9
hw/intc/armv7m_nvic.c | 14 ++++++++------
11
hw/misc/aspeed_sdmc.c | 9 +++++++++
10
1 file changed, 8 insertions(+), 6 deletions(-)
12
1 file changed, 9 insertions(+)
11
13
12
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
14
diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/armv7m_nvic.c
16
--- a/hw/misc/aspeed_sdmc.c
15
+++ b/hw/intc/armv7m_nvic.c
17
+++ b/hw/misc/aspeed_sdmc.c
16
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@
17
typedef struct NVICState {
19
#define R_STATUS1 (0x60 / 4)
18
GICState gic;
20
#define PHY_BUSY_STATE BIT(0)
19
ARMCPU *cpu;
21
22
+#define R_ECC_TEST_CTRL (0x70 / 4)
23
+#define ECC_TEST_FINISHED BIT(12)
24
+#define ECC_TEST_FAIL BIT(13)
20
+
25
+
21
+ uint32_t prigroup;
26
/*
22
+
27
* Configuration register Ox4 (for Aspeed AST2400 SOC)
23
struct {
28
*
24
uint32_t control;
29
@@ -XXX,XX +XXX,XX @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
25
uint32_t reload;
30
/* Will never return 'busy' */
26
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
31
data &= ~PHY_BUSY_STATE;
27
case 0xd08: /* Vector Table Offset. */
32
break;
28
return cpu->env.v7m.vecbase;
33
+ case R_ECC_TEST_CTRL:
29
case 0xd0c: /* Application Interrupt/Reset Control. */
34
+ /* Always done, always happy */
30
- return 0xfa050000;
35
+ data |= ECC_TEST_FINISHED;
31
+ return 0xfa050000 | (s->prigroup << 8);
36
+ data &= ~ECC_TEST_FAIL;
32
case 0xd10: /* System Control. */
37
+ break;
33
/* TODO: Implement SLEEPONEXIT. */
38
default:
34
return 0;
39
break;
35
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
36
if (value & 1) {
37
qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
38
}
39
- if (value & 0x700) {
40
- qemu_log_mask(LOG_UNIMP, "PRIGROUP unimplemented\n");
41
- }
42
+ s->prigroup = extract32(value, 8, 3);
43
}
40
}
44
break;
45
case 0xd10: /* System Control. */
46
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_sysreg_ops = {
47
48
static const VMStateDescription vmstate_nvic = {
49
.name = "armv7m_nvic",
50
- .version_id = 1,
51
- .minimum_version_id = 1,
52
+ .version_id = 2,
53
+ .minimum_version_id = 2,
54
.fields = (VMStateField[]) {
55
VMSTATE_UINT32(systick.control, NVICState),
56
VMSTATE_UINT32(systick.reload, NVICState),
57
VMSTATE_INT64(systick.tick, NVICState),
58
VMSTATE_TIMER_PTR(systick.timer, NVICState),
59
+ VMSTATE_UINT32(prigroup, NVICState),
60
VMSTATE_END_OF_LIST()
61
}
62
};
63
--
41
--
64
2.7.4
42
2.18.0
65
43
66
44
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
From: Cédric Le Goater <clg@kaod.org>
2
2
3
Despite some superficial similarities of register layout, the
3
This will be used to construct a memory region beyond the RAM region
4
M-profile NVIC is really very different from the A-profile GIC.
4
to let firmwares scan the address space with load/store to guess how
5
Our current attempt to reuse the GIC code means that we have
5
much RAM the SoC has.
6
significant bugs in our NVIC.
7
6
8
Implement the NVIC as an entirely separate device, to give
7
Signed-off-by: Cédric Le Goater <clg@kaod.org>
9
us somewhere we can get the behaviour correct.
8
Signed-off-by: Joel Stanley <joel@jms.id.au>
9
Tested-by: Cédric Le Goater <clg@kaod.org>
10
Message-id: 20180807075757.7242-7-joel@jms.id.au
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
include/hw/misc/aspeed_sdmc.h | 1 +
15
hw/arm/aspeed.c | 31 +++++++++++++++++++++++++++++++
16
hw/arm/aspeed_soc.c | 2 ++
17
hw/misc/aspeed_sdmc.c | 3 +++
18
4 files changed, 37 insertions(+)
10
19
11
This initial commit does not attempt to implement exception
20
diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h
12
priority escalation, since the GIC-based code didn't either.
13
It does fix a few bugs in passing:
14
* ICSR.RETTOBASE polarity was wrong and didn't account for
15
internal exceptions
16
* ICSR.VECTPENDING was 16 too high if the pending exception
17
was for an external interrupt
18
* UsageFault, BusFault and MemFault were not disabled on reset
19
as they are supposed to be
20
21
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
22
[PMM: reworked, various bugs and stylistic cleanups]
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
25
---
26
hw/intc/armv7m_nvic.c | 738 ++++++++++++++++++++++++++++++++++++++++----------
27
hw/intc/trace-events | 15 +
28
2 files changed, 609 insertions(+), 144 deletions(-)
29
30
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
31
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/intc/armv7m_nvic.c
22
--- a/include/hw/misc/aspeed_sdmc.h
33
+++ b/hw/intc/armv7m_nvic.c
23
+++ b/include/hw/misc/aspeed_sdmc.h
34
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSDMCState {
35
#include "hw/sysbus.h"
25
uint32_t silicon_rev;
36
#include "qemu/timer.h"
26
uint32_t ram_bits;
37
#include "hw/arm/arm.h"
27
uint64_t ram_size;
38
+#include "target/arm/cpu.h"
28
+ uint64_t max_ram_size;
39
#include "exec/address-spaces.h"
29
uint32_t fixed_conf;
40
-#include "gic_internal.h"
30
41
#include "qemu/log.h"
31
} AspeedSDMCState;
42
+#include "trace.h"
32
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
43
+
33
index XXXXXXX..XXXXXXX 100644
44
+/* IRQ number counting:
34
--- a/hw/arm/aspeed.c
45
+ *
35
+++ b/hw/arm/aspeed.c
46
+ * the num-irq property counts the number of external IRQ lines
36
@@ -XXX,XX +XXX,XX @@ static struct arm_boot_info aspeed_board_binfo = {
47
+ *
37
typedef struct AspeedBoardState {
48
+ * NVICState::num_irq counts the total number of exceptions
38
AspeedSoCState soc;
49
+ * (external IRQs, the 15 internal exceptions including reset,
39
MemoryRegion ram;
50
+ * and one for the unused exception number 0).
40
+ MemoryRegion max_ram;
51
+ *
41
} AspeedBoardState;
52
+ * NVIC_MAX_IRQ is the highest permitted number of external IRQ lines.
42
53
+ *
43
typedef struct AspeedBoardConfig {
54
+ * NVIC_MAX_VECTORS is the highest permitted number of exceptions.
44
@@ -XXX,XX +XXX,XX @@ static const AspeedBoardConfig aspeed_boards[] = {
55
+ *
45
},
56
+ * Iterating through all exceptions should typically be done with
46
};
57
+ * for (i = 1; i < s->num_irq; i++) to avoid the unused slot 0.
47
58
+ *
48
+/*
59
+ * The external qemu_irq lines are the NVIC's external IRQ lines,
49
+ * The max ram region is for firmwares that scan the address space
60
+ * so line 0 is exception 16.
50
+ * with load/store to guess how much RAM the SoC has.
61
+ *
62
+ * In the terminology of the architecture manual, "interrupts" are
63
+ * a subcategory of exception referring to the external interrupts
64
+ * (which are exception numbers NVIC_FIRST_IRQ and upward).
65
+ * For historical reasons QEMU tends to use "interrupt" and
66
+ * "exception" more or less interchangeably.
67
+ */
51
+ */
68
+#define NVIC_FIRST_IRQ 16
52
+static uint64_t max_ram_read(void *opaque, hwaddr offset, unsigned size)
69
+#define NVIC_MAX_VECTORS 512
70
+#define NVIC_MAX_IRQ (NVIC_MAX_VECTORS - NVIC_FIRST_IRQ)
71
+
72
+/* Effective running priority of the CPU when no exception is active
73
+ * (higher than the highest possible priority value)
74
+ */
75
+#define NVIC_NOEXC_PRIO 0x100
76
+
77
+typedef struct VecInfo {
78
+ /* Exception priorities can range from -3 to 255; only the unmodifiable
79
+ * priority values for RESET, NMI and HardFault can be negative.
80
+ */
81
+ int16_t prio;
82
+ uint8_t enabled;
83
+ uint8_t pending;
84
+ uint8_t active;
85
+ uint8_t level; /* exceptions <=15 never set level */
86
+} VecInfo;
87
88
typedef struct NVICState {
89
- GICState gic;
90
+ /*< private >*/
91
+ SysBusDevice parent_obj;
92
+ /*< public >*/
93
+
94
ARMCPU *cpu;
95
96
+ VecInfo vectors[NVIC_MAX_VECTORS];
97
uint32_t prigroup;
98
99
+ /* vectpending and exception_prio are both cached state that can
100
+ * be recalculated from the vectors[] array and the prigroup field.
101
+ */
102
+ unsigned int vectpending; /* highest prio pending enabled exception */
103
+ int exception_prio; /* group prio of the highest prio active exception */
104
+
105
struct {
106
uint32_t control;
107
uint32_t reload;
108
int64_t tick;
109
QEMUTimer *timer;
110
} systick;
111
+
112
MemoryRegion sysregmem;
113
- MemoryRegion gic_iomem_alias;
114
MemoryRegion container;
115
+
116
uint32_t num_irq;
117
+ qemu_irq excpout;
118
qemu_irq sysresetreq;
119
} NVICState;
120
121
#define TYPE_NVIC "armv7m_nvic"
122
-/**
123
- * NVICClass:
124
- * @parent_reset: the parent class' reset handler.
125
- *
126
- * A model of the v7M NVIC and System Controller
127
- */
128
-typedef struct NVICClass {
129
- /*< private >*/
130
- ARMGICClass parent_class;
131
- /*< public >*/
132
- DeviceRealize parent_realize;
133
- void (*parent_reset)(DeviceState *dev);
134
-} NVICClass;
135
-
136
-#define NVIC_CLASS(klass) \
137
- OBJECT_CLASS_CHECK(NVICClass, (klass), TYPE_NVIC)
138
-#define NVIC_GET_CLASS(obj) \
139
- OBJECT_GET_CLASS(NVICClass, (obj), TYPE_NVIC)
140
+
141
#define NVIC(obj) \
142
OBJECT_CHECK(NVICState, (obj), TYPE_NVIC)
143
144
@@ -XXX,XX +XXX,XX @@ static void systick_reset(NVICState *s)
145
timer_del(s->systick.timer);
146
}
147
148
-/* The external routines use the hardware vector numbering, ie. the first
149
- IRQ is #16. The internal GIC routines use #32 as the first IRQ. */
150
+static int nvic_pending_prio(NVICState *s)
151
+{
53
+{
152
+ /* return the priority of the current pending interrupt,
153
+ * or NVIC_NOEXC_PRIO if no interrupt is pending
154
+ */
155
+ return s->vectpending ? s->vectors[s->vectpending].prio : NVIC_NOEXC_PRIO;
156
+}
157
+
158
+/* Return the value of the ISCR RETTOBASE bit:
159
+ * 1 if there is exactly one active exception
160
+ * 0 if there is more than one active exception
161
+ * UNKNOWN if there are no active exceptions (we choose 1,
162
+ * which matches the choice Cortex-M3 is documented as making).
163
+ *
164
+ * NB: some versions of the documentation talk about this
165
+ * counting "active exceptions other than the one shown by IPSR";
166
+ * this is only different in the obscure corner case where guest
167
+ * code has manually deactivated an exception and is about
168
+ * to fail an exception-return integrity check. The definition
169
+ * above is the one from the v8M ARM ARM and is also in line
170
+ * with the behaviour documented for the Cortex-M3.
171
+ */
172
+static bool nvic_rettobase(NVICState *s)
173
+{
174
+ int irq, nhand = 0;
175
+
176
+ for (irq = ARMV7M_EXCP_RESET; irq < s->num_irq; irq++) {
177
+ if (s->vectors[irq].active) {
178
+ nhand++;
179
+ if (nhand == 2) {
180
+ return 0;
181
+ }
182
+ }
183
+ }
184
+
185
+ return 1;
186
+}
187
+
188
+/* Return the value of the ISCR ISRPENDING bit:
189
+ * 1 if an external interrupt is pending
190
+ * 0 if no external interrupt is pending
191
+ */
192
+static bool nvic_isrpending(NVICState *s)
193
+{
194
+ int irq;
195
+
196
+ /* We can shortcut if the highest priority pending interrupt
197
+ * happens to be external or if there is nothing pending.
198
+ */
199
+ if (s->vectpending > NVIC_FIRST_IRQ) {
200
+ return true;
201
+ }
202
+ if (s->vectpending == 0) {
203
+ return false;
204
+ }
205
+
206
+ for (irq = NVIC_FIRST_IRQ; irq < s->num_irq; irq++) {
207
+ if (s->vectors[irq].pending) {
208
+ return true;
209
+ }
210
+ }
211
+ return false;
212
+}
213
+
214
+/* Return a mask word which clears the subpriority bits from
215
+ * a priority value for an M-profile exception, leaving only
216
+ * the group priority.
217
+ */
218
+static inline uint32_t nvic_gprio_mask(NVICState *s)
219
+{
220
+ return ~0U << (s->prigroup + 1);
221
+}
222
+
223
+/* Recompute vectpending and exception_prio */
224
+static void nvic_recompute_state(NVICState *s)
225
+{
226
+ int i;
227
+ int pend_prio = NVIC_NOEXC_PRIO;
228
+ int active_prio = NVIC_NOEXC_PRIO;
229
+ int pend_irq = 0;
230
+
231
+ for (i = 1; i < s->num_irq; i++) {
232
+ VecInfo *vec = &s->vectors[i];
233
+
234
+ if (vec->enabled && vec->pending && vec->prio < pend_prio) {
235
+ pend_prio = vec->prio;
236
+ pend_irq = i;
237
+ }
238
+ if (vec->active && vec->prio < active_prio) {
239
+ active_prio = vec->prio;
240
+ }
241
+ }
242
+
243
+ s->vectpending = pend_irq;
244
+ s->exception_prio = active_prio & nvic_gprio_mask(s);
245
+
246
+ trace_nvic_recompute_state(s->vectpending, s->exception_prio);
247
+}
248
+
249
+/* Return the current execution priority of the CPU
250
+ * (equivalent to the pseudocode ExecutionPriority function).
251
+ * This is a value between -2 (NMI priority) and NVIC_NOEXC_PRIO.
252
+ */
253
+static inline int nvic_exec_prio(NVICState *s)
254
+{
255
+ CPUARMState *env = &s->cpu->env;
256
+ int running;
257
+
258
+ if (env->daif & PSTATE_F) { /* FAULTMASK */
259
+ running = -1;
260
+ } else if (env->daif & PSTATE_I) { /* PRIMASK */
261
+ running = 0;
262
+ } else if (env->v7m.basepri > 0) {
263
+ running = env->v7m.basepri & nvic_gprio_mask(s);
264
+ } else {
265
+ running = NVIC_NOEXC_PRIO; /* lower than any possible priority */
266
+ }
267
+ /* consider priority of active handler */
268
+ return MIN(running, s->exception_prio);
269
+}
270
+
271
+/* caller must call nvic_irq_update() after this */
272
+static void set_prio(NVICState *s, unsigned irq, uint8_t prio)
273
+{
274
+ assert(irq > ARMV7M_EXCP_NMI); /* only use for configurable prios */
275
+ assert(irq < s->num_irq);
276
+
277
+ s->vectors[irq].prio = prio;
278
+
279
+ trace_nvic_set_prio(irq, prio);
280
+}
281
+
282
+/* Recompute state and assert irq line accordingly.
283
+ * Must be called after changes to:
284
+ * vec->active, vec->enabled, vec->pending or vec->prio for any vector
285
+ * prigroup
286
+ */
287
+static void nvic_irq_update(NVICState *s)
288
+{
289
+ int lvl;
290
+ int pend_prio;
291
+
292
+ nvic_recompute_state(s);
293
+ pend_prio = nvic_pending_prio(s);
294
+
295
+ /* Raise NVIC output if this IRQ would be taken, except that we
296
+ * ignore the effects of the BASEPRI, FAULTMASK and PRIMASK (which
297
+ * will be checked for in arm_v7m_cpu_exec_interrupt()); changes
298
+ * to those CPU registers don't cause us to recalculate the NVIC
299
+ * pending info.
300
+ */
301
+ lvl = (pend_prio < s->exception_prio);
302
+ trace_nvic_irq_update(s->vectpending, pend_prio, s->exception_prio, lvl);
303
+ qemu_set_irq(s->excpout, lvl);
304
+}
305
+
306
+static void armv7m_nvic_clear_pending(void *opaque, int irq)
307
+{
308
+ NVICState *s = (NVICState *)opaque;
309
+ VecInfo *vec;
310
+
311
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
312
+
313
+ vec = &s->vectors[irq];
314
+ trace_nvic_clear_pending(irq, vec->enabled, vec->prio);
315
+ if (vec->pending) {
316
+ vec->pending = 0;
317
+ nvic_irq_update(s);
318
+ }
319
+}
320
+
321
void armv7m_nvic_set_pending(void *opaque, int irq)
322
{
323
NVICState *s = (NVICState *)opaque;
324
- if (irq >= 16)
325
- irq += 16;
326
- gic_set_pending_private(&s->gic, 0, irq);
327
+ VecInfo *vec;
328
+
329
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
330
+
331
+ vec = &s->vectors[irq];
332
+ trace_nvic_set_pending(irq, vec->enabled, vec->prio);
333
+ if (!vec->pending) {
334
+ vec->pending = 1;
335
+ nvic_irq_update(s);
336
+ }
337
}
338
339
/* Make pending IRQ active. */
340
int armv7m_nvic_acknowledge_irq(void *opaque)
341
{
342
NVICState *s = (NVICState *)opaque;
343
- uint32_t irq;
344
-
345
- irq = gic_acknowledge_irq(&s->gic, 0, MEMTXATTRS_UNSPECIFIED);
346
- if (irq == 1023)
347
- hw_error("Interrupt but no vector\n");
348
- if (irq >= 32)
349
- irq -= 16;
350
- return irq;
351
+ CPUARMState *env = &s->cpu->env;
352
+ const int pending = s->vectpending;
353
+ const int running = nvic_exec_prio(s);
354
+ int pendgroupprio;
355
+ VecInfo *vec;
356
+
357
+ assert(pending > ARMV7M_EXCP_RESET && pending < s->num_irq);
358
+
359
+ vec = &s->vectors[pending];
360
+
361
+ assert(vec->enabled);
362
+ assert(vec->pending);
363
+
364
+ pendgroupprio = vec->prio & nvic_gprio_mask(s);
365
+ assert(pendgroupprio < running);
366
+
367
+ trace_nvic_acknowledge_irq(pending, vec->prio);
368
+
369
+ vec->active = 1;
370
+ vec->pending = 0;
371
+
372
+ env->v7m.exception = s->vectpending;
373
+
374
+ nvic_irq_update(s);
375
+
376
+ return env->v7m.exception;
377
}
378
379
void armv7m_nvic_complete_irq(void *opaque, int irq)
380
{
381
NVICState *s = (NVICState *)opaque;
382
- if (irq >= 16)
383
- irq += 16;
384
- gic_complete_irq(&s->gic, 0, irq, MEMTXATTRS_UNSPECIFIED);
385
+ VecInfo *vec;
386
+
387
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
388
+
389
+ vec = &s->vectors[irq];
390
+
391
+ trace_nvic_complete_irq(irq);
392
+
393
+ vec->active = 0;
394
+ if (vec->level) {
395
+ /* Re-pend the exception if it's still held high; only
396
+ * happens for extenal IRQs
397
+ */
398
+ assert(irq >= NVIC_FIRST_IRQ);
399
+ vec->pending = 1;
400
+ }
401
+
402
+ nvic_irq_update(s);
403
+}
404
+
405
+/* callback when external interrupt line is changed */
406
+static void set_irq_level(void *opaque, int n, int level)
407
+{
408
+ NVICState *s = opaque;
409
+ VecInfo *vec;
410
+
411
+ n += NVIC_FIRST_IRQ;
412
+
413
+ assert(n >= NVIC_FIRST_IRQ && n < s->num_irq);
414
+
415
+ trace_nvic_set_irq_level(n, level);
416
+
417
+ /* The pending status of an external interrupt is
418
+ * latched on rising edge and exception handler return.
419
+ *
420
+ * Pulsing the IRQ will always run the handler
421
+ * once, and the handler will re-run until the
422
+ * level is low when the handler completes.
423
+ */
424
+ vec = &s->vectors[n];
425
+ if (level != vec->level) {
426
+ vec->level = level;
427
+ if (level) {
428
+ armv7m_nvic_set_pending(s, n);
429
+ }
430
+ }
431
}
432
433
static uint32_t nvic_readl(NVICState *s, uint32_t offset)
434
{
435
ARMCPU *cpu = s->cpu;
436
uint32_t val;
437
- int irq;
438
439
switch (offset) {
440
case 4: /* Interrupt Control Type. */
441
- return (s->num_irq / 32) - 1;
442
+ return ((s->num_irq - NVIC_FIRST_IRQ) / 32) - 1;
443
case 0x10: /* SysTick Control and Status. */
444
val = s->systick.control;
445
s->systick.control &= ~SYSTICK_COUNTFLAG;
446
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
447
case 0xd04: /* Interrupt Control State. */
448
/* VECTACTIVE */
449
val = cpu->env.v7m.exception;
450
- if (val == 1023) {
451
- val = 0;
452
- } else if (val >= 32) {
453
- val -= 16;
454
- }
455
/* VECTPENDING */
456
- if (s->gic.current_pending[0] != 1023)
457
- val |= (s->gic.current_pending[0] << 12);
458
- /* ISRPENDING and RETTOBASE */
459
- for (irq = 32; irq < s->num_irq; irq++) {
460
- if (s->gic.irq_state[irq].pending) {
461
- val |= (1 << 22);
462
- break;
463
- }
464
- if (irq != cpu->env.v7m.exception && s->gic.irq_state[irq].active) {
465
- val |= (1 << 11);
466
- }
467
+ val |= (s->vectpending & 0xff) << 12;
468
+ /* ISRPENDING - set if any external IRQ is pending */
469
+ if (nvic_isrpending(s)) {
470
+ val |= (1 << 22);
471
+ }
472
+ /* RETTOBASE - set if only one handler is active */
473
+ if (nvic_rettobase(s)) {
474
+ val |= (1 << 11);
475
}
476
/* PENDSTSET */
477
- if (s->gic.irq_state[ARMV7M_EXCP_SYSTICK].pending)
478
+ if (s->vectors[ARMV7M_EXCP_SYSTICK].pending) {
479
val |= (1 << 26);
480
+ }
481
/* PENDSVSET */
482
- if (s->gic.irq_state[ARMV7M_EXCP_PENDSV].pending)
483
+ if (s->vectors[ARMV7M_EXCP_PENDSV].pending) {
484
val |= (1 << 28);
485
+ }
486
/* NMIPENDSET */
487
- if (s->gic.irq_state[ARMV7M_EXCP_NMI].pending)
488
+ if (s->vectors[ARMV7M_EXCP_NMI].pending) {
489
val |= (1 << 31);
490
+ }
491
+ /* ISRPREEMPT not implemented */
492
return val;
493
case 0xd08: /* Vector Table Offset. */
494
return cpu->env.v7m.vecbase;
495
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
496
return cpu->env.v7m.ccr;
497
case 0xd24: /* System Handler Status. */
498
val = 0;
499
- if (s->gic.irq_state[ARMV7M_EXCP_MEM].active) val |= (1 << 0);
500
- if (s->gic.irq_state[ARMV7M_EXCP_BUS].active) val |= (1 << 1);
501
- if (s->gic.irq_state[ARMV7M_EXCP_USAGE].active) val |= (1 << 3);
502
- if (s->gic.irq_state[ARMV7M_EXCP_SVC].active) val |= (1 << 7);
503
- if (s->gic.irq_state[ARMV7M_EXCP_DEBUG].active) val |= (1 << 8);
504
- if (s->gic.irq_state[ARMV7M_EXCP_PENDSV].active) val |= (1 << 10);
505
- if (s->gic.irq_state[ARMV7M_EXCP_SYSTICK].active) val |= (1 << 11);
506
- if (s->gic.irq_state[ARMV7M_EXCP_USAGE].pending) val |= (1 << 12);
507
- if (s->gic.irq_state[ARMV7M_EXCP_MEM].pending) val |= (1 << 13);
508
- if (s->gic.irq_state[ARMV7M_EXCP_BUS].pending) val |= (1 << 14);
509
- if (s->gic.irq_state[ARMV7M_EXCP_SVC].pending) val |= (1 << 15);
510
- if (s->gic.irq_state[ARMV7M_EXCP_MEM].enabled) val |= (1 << 16);
511
- if (s->gic.irq_state[ARMV7M_EXCP_BUS].enabled) val |= (1 << 17);
512
- if (s->gic.irq_state[ARMV7M_EXCP_USAGE].enabled) val |= (1 << 18);
513
+ if (s->vectors[ARMV7M_EXCP_MEM].active) {
514
+ val |= (1 << 0);
515
+ }
516
+ if (s->vectors[ARMV7M_EXCP_BUS].active) {
517
+ val |= (1 << 1);
518
+ }
519
+ if (s->vectors[ARMV7M_EXCP_USAGE].active) {
520
+ val |= (1 << 3);
521
+ }
522
+ if (s->vectors[ARMV7M_EXCP_SVC].active) {
523
+ val |= (1 << 7);
524
+ }
525
+ if (s->vectors[ARMV7M_EXCP_DEBUG].active) {
526
+ val |= (1 << 8);
527
+ }
528
+ if (s->vectors[ARMV7M_EXCP_PENDSV].active) {
529
+ val |= (1 << 10);
530
+ }
531
+ if (s->vectors[ARMV7M_EXCP_SYSTICK].active) {
532
+ val |= (1 << 11);
533
+ }
534
+ if (s->vectors[ARMV7M_EXCP_USAGE].pending) {
535
+ val |= (1 << 12);
536
+ }
537
+ if (s->vectors[ARMV7M_EXCP_MEM].pending) {
538
+ val |= (1 << 13);
539
+ }
540
+ if (s->vectors[ARMV7M_EXCP_BUS].pending) {
541
+ val |= (1 << 14);
542
+ }
543
+ if (s->vectors[ARMV7M_EXCP_SVC].pending) {
544
+ val |= (1 << 15);
545
+ }
546
+ if (s->vectors[ARMV7M_EXCP_MEM].enabled) {
547
+ val |= (1 << 16);
548
+ }
549
+ if (s->vectors[ARMV7M_EXCP_BUS].enabled) {
550
+ val |= (1 << 17);
551
+ }
552
+ if (s->vectors[ARMV7M_EXCP_USAGE].enabled) {
553
+ val |= (1 << 18);
554
+ }
555
return val;
556
case 0xd28: /* Configurable Fault Status. */
557
return cpu->env.v7m.cfsr;
558
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
559
if (value & (1 << 28)) {
560
armv7m_nvic_set_pending(s, ARMV7M_EXCP_PENDSV);
561
} else if (value & (1 << 27)) {
562
- s->gic.irq_state[ARMV7M_EXCP_PENDSV].pending = 0;
563
- gic_update(&s->gic);
564
+ armv7m_nvic_clear_pending(s, ARMV7M_EXCP_PENDSV);
565
}
566
if (value & (1 << 26)) {
567
armv7m_nvic_set_pending(s, ARMV7M_EXCP_SYSTICK);
568
} else if (value & (1 << 25)) {
569
- s->gic.irq_state[ARMV7M_EXCP_SYSTICK].pending = 0;
570
- gic_update(&s->gic);
571
+ armv7m_nvic_clear_pending(s, ARMV7M_EXCP_SYSTICK);
572
}
573
break;
574
case 0xd08: /* Vector Table Offset. */
575
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
576
qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
577
}
578
s->prigroup = extract32(value, 8, 3);
579
+ nvic_irq_update(s);
580
}
581
break;
582
case 0xd10: /* System Control. */
583
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
584
case 0xd24: /* System Handler Control. */
585
/* TODO: Real hardware allows you to set/clear the active bits
586
under some circumstances. We don't implement this. */
587
- s->gic.irq_state[ARMV7M_EXCP_MEM].enabled = (value & (1 << 16)) != 0;
588
- s->gic.irq_state[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0;
589
- s->gic.irq_state[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0;
590
+ s->vectors[ARMV7M_EXCP_MEM].enabled = (value & (1 << 16)) != 0;
591
+ s->vectors[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0;
592
+ s->vectors[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0;
593
+ nvic_irq_update(s);
594
break;
595
case 0xd28: /* Configurable Fault Status. */
596
cpu->env.v7m.cfsr &= ~value; /* W1C */
597
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
598
"NVIC: Aux fault status registers unimplemented\n");
599
break;
600
case 0xf00: /* Software Triggered Interrupt Register */
601
+ {
602
/* user mode can only write to STIR if CCR.USERSETMPEND permits it */
603
- if ((value & 0x1ff) < s->num_irq &&
604
+ int excnum = (value & 0x1ff) + NVIC_FIRST_IRQ;
605
+ if (excnum < s->num_irq &&
606
(arm_current_el(&cpu->env) ||
607
(cpu->env.v7m.ccr & R_V7M_CCR_USERSETMPEND_MASK))) {
608
- gic_set_pending_private(&s->gic, 0, value & 0x1ff);
609
+ armv7m_nvic_set_pending(s, excnum);
610
}
611
break;
612
+ }
613
default:
614
qemu_log_mask(LOG_GUEST_ERROR,
615
"NVIC: Bad write offset 0x%x\n", offset);
616
@@ -XXX,XX +XXX,XX @@ static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
617
{
618
NVICState *s = (NVICState *)opaque;
619
uint32_t offset = addr;
620
- int i;
621
+ unsigned i, startvec, end;
622
uint32_t val;
623
624
switch (offset) {
625
+ /* reads of set and clear both return the status */
626
+ case 0x100 ... 0x13f: /* NVIC Set enable */
627
+ offset += 0x80;
628
+ /* fall through */
629
+ case 0x180 ... 0x1bf: /* NVIC Clear enable */
630
+ val = 0;
631
+ startvec = offset - 0x180 + NVIC_FIRST_IRQ; /* vector # */
632
+
633
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
634
+ if (s->vectors[startvec + i].enabled) {
635
+ val |= (1 << i);
636
+ }
637
+ }
638
+ break;
639
+ case 0x200 ... 0x23f: /* NVIC Set pend */
640
+ offset += 0x80;
641
+ /* fall through */
642
+ case 0x280 ... 0x2bf: /* NVIC Clear pend */
643
+ val = 0;
644
+ startvec = offset - 0x280 + NVIC_FIRST_IRQ; /* vector # */
645
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
646
+ if (s->vectors[startvec + i].pending) {
647
+ val |= (1 << i);
648
+ }
649
+ }
650
+ break;
651
+ case 0x300 ... 0x33f: /* NVIC Active */
652
+ val = 0;
653
+ startvec = offset - 0x300 + NVIC_FIRST_IRQ; /* vector # */
654
+
655
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
656
+ if (s->vectors[startvec + i].active) {
657
+ val |= (1 << i);
658
+ }
659
+ }
660
+ break;
661
+ case 0x400 ... 0x5ef: /* NVIC Priority */
662
+ val = 0;
663
+ startvec = offset - 0x400 + NVIC_FIRST_IRQ; /* vector # */
664
+
665
+ for (i = 0; i < size && startvec + i < s->num_irq; i++) {
666
+ val |= s->vectors[startvec + i].prio << (8 * i);
667
+ }
668
+ break;
669
case 0xd18 ... 0xd23: /* System Handler Priority. */
670
val = 0;
671
for (i = 0; i < size; i++) {
672
- val |= s->gic.priority1[(offset - 0xd14) + i][0] << (i * 8);
673
+ val |= s->vectors[(offset - 0xd14) + i].prio << (i * 8);
674
}
675
- return val;
676
+ break;
677
case 0xfe0 ... 0xfff: /* ID. */
678
if (offset & 3) {
679
- return 0;
680
+ val = 0;
681
+ } else {
682
+ val = nvic_id[(offset - 0xfe0) >> 2];
683
+ }
684
+ break;
685
+ default:
686
+ if (size == 4) {
687
+ val = nvic_readl(s, offset);
688
+ } else {
689
+ qemu_log_mask(LOG_GUEST_ERROR,
690
+ "NVIC: Bad read of size %d at offset 0x%x\n",
691
+ size, offset);
692
+ val = 0;
693
}
694
- return nvic_id[(offset - 0xfe0) >> 2];
695
- }
696
- if (size == 4) {
697
- return nvic_readl(s, offset);
698
}
699
- qemu_log_mask(LOG_GUEST_ERROR,
700
- "NVIC: Bad read of size %d at offset 0x%x\n", size, offset);
701
- return 0;
702
+
703
+ trace_nvic_sysreg_read(addr, val, size);
704
+ return val;
705
}
706
707
static void nvic_sysreg_write(void *opaque, hwaddr addr,
708
@@ -XXX,XX +XXX,XX @@ static void nvic_sysreg_write(void *opaque, hwaddr addr,
709
{
710
NVICState *s = (NVICState *)opaque;
711
uint32_t offset = addr;
712
- int i;
713
+ unsigned i, startvec, end;
714
+ unsigned setval = 0;
715
+
716
+ trace_nvic_sysreg_write(addr, value, size);
717
718
switch (offset) {
719
+ case 0x100 ... 0x13f: /* NVIC Set enable */
720
+ offset += 0x80;
721
+ setval = 1;
722
+ /* fall through */
723
+ case 0x180 ... 0x1bf: /* NVIC Clear enable */
724
+ startvec = 8 * (offset - 0x180) + NVIC_FIRST_IRQ;
725
+
726
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
727
+ if (value & (1 << i)) {
728
+ s->vectors[startvec + i].enabled = setval;
729
+ }
730
+ }
731
+ nvic_irq_update(s);
732
+ return;
733
+ case 0x200 ... 0x23f: /* NVIC Set pend */
734
+ /* the special logic in armv7m_nvic_set_pending()
735
+ * is not needed since IRQs are never escalated
736
+ */
737
+ offset += 0x80;
738
+ setval = 1;
739
+ /* fall through */
740
+ case 0x280 ... 0x2bf: /* NVIC Clear pend */
741
+ startvec = 8 * (offset - 0x280) + NVIC_FIRST_IRQ; /* vector # */
742
+
743
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
744
+ if (value & (1 << i)) {
745
+ s->vectors[startvec + i].pending = setval;
746
+ }
747
+ }
748
+ nvic_irq_update(s);
749
+ return;
750
+ case 0x300 ... 0x33f: /* NVIC Active */
751
+ return; /* R/O */
752
+ case 0x400 ... 0x5ef: /* NVIC Priority */
753
+ startvec = 8 * (offset - 0x400) + NVIC_FIRST_IRQ; /* vector # */
754
+
755
+ for (i = 0; i < size && startvec + i < s->num_irq; i++) {
756
+ set_prio(s, startvec + i, (value >> (i * 8)) & 0xff);
757
+ }
758
+ nvic_irq_update(s);
759
+ return;
760
case 0xd18 ... 0xd23: /* System Handler Priority. */
761
for (i = 0; i < size; i++) {
762
- s->gic.priority1[(offset - 0xd14) + i][0] =
763
- (value >> (i * 8)) & 0xff;
764
+ unsigned hdlidx = (offset - 0xd14) + i;
765
+ set_prio(s, hdlidx, (value >> (i * 8)) & 0xff);
766
}
767
- gic_update(&s->gic);
768
+ nvic_irq_update(s);
769
return;
770
}
771
if (size == 4) {
772
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_sysreg_ops = {
773
.endianness = DEVICE_NATIVE_ENDIAN,
774
};
775
776
+static int nvic_post_load(void *opaque, int version_id)
777
+{
778
+ NVICState *s = opaque;
779
+ unsigned i;
780
+
781
+ /* Check for out of range priority settings */
782
+ if (s->vectors[ARMV7M_EXCP_RESET].prio != -3 ||
783
+ s->vectors[ARMV7M_EXCP_NMI].prio != -2 ||
784
+ s->vectors[ARMV7M_EXCP_HARD].prio != -1) {
785
+ return 1;
786
+ }
787
+ for (i = ARMV7M_EXCP_MEM; i < s->num_irq; i++) {
788
+ if (s->vectors[i].prio & ~0xff) {
789
+ return 1;
790
+ }
791
+ }
792
+
793
+ nvic_recompute_state(s);
794
+
795
+ return 0;
54
+ return 0;
796
+}
55
+}
797
+
56
+
798
+static const VMStateDescription vmstate_VecInfo = {
57
+static void max_ram_write(void *opaque, hwaddr offset, uint64_t value,
799
+ .name = "armv7m_nvic_info",
58
+ unsigned size)
800
+ .version_id = 1,
59
+{
801
+ .minimum_version_id = 1,
60
+ /* Discard writes */
802
+ .fields = (VMStateField[]) {
61
+}
803
+ VMSTATE_INT16(prio, VecInfo),
62
+
804
+ VMSTATE_UINT8(enabled, VecInfo),
63
+static const MemoryRegionOps max_ram_ops = {
805
+ VMSTATE_UINT8(pending, VecInfo),
64
+ .read = max_ram_read,
806
+ VMSTATE_UINT8(active, VecInfo),
65
+ .write = max_ram_write,
807
+ VMSTATE_UINT8(level, VecInfo),
66
+ .endianness = DEVICE_NATIVE_ENDIAN,
808
+ VMSTATE_END_OF_LIST()
809
+ }
810
+};
67
+};
811
+
68
+
812
static const VMStateDescription vmstate_nvic = {
69
#define FIRMWARE_ADDR 0x0
813
.name = "armv7m_nvic",
70
814
- .version_id = 2,
71
static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size,
815
- .minimum_version_id = 2,
72
@@ -XXX,XX +XXX,XX @@ static void aspeed_board_init(MachineState *machine,
816
+ .version_id = 3,
73
AspeedBoardState *bmc;
817
+ .minimum_version_id = 3,
74
AspeedSoCClass *sc;
818
+ .post_load = &nvic_post_load,
75
DriveInfo *drive0 = drive_get(IF_MTD, 0, 0);
819
.fields = (VMStateField[]) {
76
+ ram_addr_t max_ram_size;
820
+ VMSTATE_STRUCT_ARRAY(vectors, NVICState, NVIC_MAX_VECTORS, 1,
77
821
+ vmstate_VecInfo, VecInfo),
78
bmc = g_new0(AspeedBoardState, 1);
822
VMSTATE_UINT32(systick.control, NVICState),
79
object_initialize(&bmc->soc, (sizeof(bmc->soc)), cfg->soc_name);
823
VMSTATE_UINT32(systick.reload, NVICState),
80
@@ -XXX,XX +XXX,XX @@ static void aspeed_board_init(MachineState *machine,
824
VMSTATE_INT64(systick.tick, NVICState),
81
object_property_add_const_link(OBJECT(&bmc->soc), "ram", OBJECT(&bmc->ram),
825
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_nvic = {
82
&error_abort);
826
}
83
84
+ max_ram_size = object_property_get_uint(OBJECT(&bmc->soc), "max-ram-size",
85
+ &error_abort);
86
+ memory_region_init_io(&bmc->max_ram, NULL, &max_ram_ops, NULL,
87
+ "max_ram", max_ram_size - ram_size);
88
+ memory_region_add_subregion(get_system_memory(),
89
+ sc->info->sdram_base + ram_size,
90
+ &bmc->max_ram);
91
+
92
aspeed_board_init_flashes(&bmc->soc.fmc, cfg->fmc_model, &error_abort);
93
aspeed_board_init_flashes(&bmc->soc.spi[0], cfg->spi_model, &error_abort);
94
95
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
96
index XXXXXXX..XXXXXXX 100644
97
--- a/hw/arm/aspeed_soc.c
98
+++ b/hw/arm/aspeed_soc.c
99
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
100
sc->info->silicon_rev);
101
object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc),
102
"ram-size", &error_abort);
103
+ object_property_add_alias(obj, "max-ram-size", OBJECT(&s->sdmc),
104
+ "max-ram-size", &error_abort);
105
106
for (i = 0; i < sc->info->wdts_num; i++) {
107
object_initialize(&s->wdt[i], sizeof(s->wdt[i]), TYPE_ASPEED_WDT);
108
diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
109
index XXXXXXX..XXXXXXX 100644
110
--- a/hw/misc/aspeed_sdmc.c
111
+++ b/hw/misc/aspeed_sdmc.c
112
@@ -XXX,XX +XXX,XX @@ static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
113
case AST2400_A0_SILICON_REV:
114
case AST2400_A1_SILICON_REV:
115
s->ram_bits = ast2400_rambits(s);
116
+ s->max_ram_size = 512 << 20;
117
s->fixed_conf = ASPEED_SDMC_VGA_COMPAT |
118
ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
119
break;
120
case AST2500_A0_SILICON_REV:
121
case AST2500_A1_SILICON_REV:
122
s->ram_bits = ast2500_rambits(s);
123
+ s->max_ram_size = 1024 << 20;
124
s->fixed_conf = ASPEED_SDMC_HW_VERSION(1) |
125
ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB) |
126
ASPEED_SDMC_CACHE_INITIAL_DONE |
127
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_aspeed_sdmc = {
128
static Property aspeed_sdmc_properties[] = {
129
DEFINE_PROP_UINT32("silicon-rev", AspeedSDMCState, silicon_rev, 0),
130
DEFINE_PROP_UINT64("ram-size", AspeedSDMCState, ram_size, 0),
131
+ DEFINE_PROP_UINT64("max-ram-size", AspeedSDMCState, max_ram_size, 0),
132
DEFINE_PROP_END_OF_LIST(),
827
};
133
};
828
134
829
+static Property props_nvic[] = {
830
+ /* Number of external IRQ lines (so excluding the 16 internal exceptions) */
831
+ DEFINE_PROP_UINT32("num-irq", NVICState, num_irq, 64),
832
+ DEFINE_PROP_END_OF_LIST()
833
+};
834
+
835
static void armv7m_nvic_reset(DeviceState *dev)
836
{
837
NVICState *s = NVIC(dev);
838
- NVICClass *nc = NVIC_GET_CLASS(s);
839
- nc->parent_reset(dev);
840
- /* Common GIC reset resets to disabled; the NVIC doesn't have
841
- * per-CPU interfaces so mark our non-existent CPU interface
842
- * as enabled by default, and with a priority mask which allows
843
- * all interrupts through.
844
+
845
+ s->vectors[ARMV7M_EXCP_NMI].enabled = 1;
846
+ s->vectors[ARMV7M_EXCP_HARD].enabled = 1;
847
+ /* MEM, BUS, and USAGE are enabled through
848
+ * the System Handler Control register
849
*/
850
- s->gic.cpu_ctlr[0] = GICC_CTLR_EN_GRP0;
851
- s->gic.priority_mask[0] = 0x100;
852
- /* The NVIC as a whole is always enabled. */
853
- s->gic.ctlr = 1;
854
+ s->vectors[ARMV7M_EXCP_SVC].enabled = 1;
855
+ s->vectors[ARMV7M_EXCP_DEBUG].enabled = 1;
856
+ s->vectors[ARMV7M_EXCP_PENDSV].enabled = 1;
857
+ s->vectors[ARMV7M_EXCP_SYSTICK].enabled = 1;
858
+
859
+ s->vectors[ARMV7M_EXCP_RESET].prio = -3;
860
+ s->vectors[ARMV7M_EXCP_NMI].prio = -2;
861
+ s->vectors[ARMV7M_EXCP_HARD].prio = -1;
862
+
863
+ /* Strictly speaking the reset handler should be enabled.
864
+ * However, we don't simulate soft resets through the NVIC,
865
+ * and the reset vector should never be pended.
866
+ * So we leave it disabled to catch logic errors.
867
+ */
868
+
869
+ s->exception_prio = NVIC_NOEXC_PRIO;
870
+ s->vectpending = 0;
871
+
872
systick_reset(s);
873
}
874
875
static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
876
{
877
NVICState *s = NVIC(dev);
878
- NVICClass *nc = NVIC_GET_CLASS(s);
879
- Error *local_err = NULL;
880
881
s->cpu = ARM_CPU(qemu_get_cpu(0));
882
assert(s->cpu);
883
- /* The NVIC always has only one CPU */
884
- s->gic.num_cpu = 1;
885
- /* Tell the common code we're an NVIC */
886
- s->gic.revision = 0xffffffff;
887
- s->num_irq = s->gic.num_irq;
888
- nc->parent_realize(dev, &local_err);
889
- if (local_err) {
890
- error_propagate(errp, local_err);
891
+
892
+ if (s->num_irq > NVIC_MAX_IRQ) {
893
+ error_setg(errp, "num-irq %d exceeds NVIC maximum", s->num_irq);
894
return;
895
}
896
- gic_init_irqs_and_distributor(&s->gic);
897
- /* The NVIC and system controller register area looks like this:
898
- * 0..0xff : system control registers, including systick
899
- * 0x100..0xcff : GIC-like registers
900
- * 0xd00..0xfff : system control registers
901
- * We use overlaying to put the GIC like registers
902
- * over the top of the system control register region.
903
+
904
+ qdev_init_gpio_in(dev, set_irq_level, s->num_irq);
905
+
906
+ /* include space for internal exception vectors */
907
+ s->num_irq += NVIC_FIRST_IRQ;
908
+
909
+ /* The NVIC and System Control Space (SCS) starts at 0xe000e000
910
+ * and looks like this:
911
+ * 0x004 - ICTR
912
+ * 0x010 - 0x1c - systick
913
+ * 0x100..0x7ec - NVIC
914
+ * 0x7f0..0xcff - Reserved
915
+ * 0xd00..0xd3c - SCS registers
916
+ * 0xd40..0xeff - Reserved or Not implemented
917
+ * 0xf00 - STIR
918
+ *
919
+ * At the moment there is only one thing in the container region,
920
+ * but we leave it in place to allow us to pull systick out into
921
+ * its own device object later.
922
*/
923
memory_region_init(&s->container, OBJECT(s), "nvic", 0x1000);
924
/* The system register region goes at the bottom of the priority
925
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
926
memory_region_init_io(&s->sysregmem, OBJECT(s), &nvic_sysreg_ops, s,
927
"nvic_sysregs", 0x1000);
928
memory_region_add_subregion(&s->container, 0, &s->sysregmem);
929
- /* Alias the GIC region so we can get only the section of it
930
- * we need, and layer it on top of the system register region.
931
- */
932
- memory_region_init_alias(&s->gic_iomem_alias, OBJECT(s),
933
- "nvic-gic", &s->gic.iomem,
934
- 0x100, 0xc00);
935
- memory_region_add_subregion_overlap(&s->container, 0x100,
936
- &s->gic_iomem_alias, 1);
937
+
938
/* Map the whole thing into system memory at the location required
939
* by the v7M architecture.
940
*/
941
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_instance_init(Object *obj)
942
* any user-specified property setting, so just modify the
943
* value in the GICState struct.
944
*/
945
- GICState *s = ARM_GIC_COMMON(obj);
946
DeviceState *dev = DEVICE(obj);
947
NVICState *nvic = NVIC(obj);
948
- /* The ARM v7m may have anything from 0 to 496 external interrupt
949
- * IRQ lines. We default to 64. Other boards may differ and should
950
- * set the num-irq property appropriately.
951
- */
952
- s->num_irq = 64;
953
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
954
+
955
+ sysbus_init_irq(sbd, &nvic->excpout);
956
qdev_init_gpio_out_named(dev, &nvic->sysresetreq, "SYSRESETREQ", 1);
957
}
958
959
static void armv7m_nvic_class_init(ObjectClass *klass, void *data)
960
{
961
- NVICClass *nc = NVIC_CLASS(klass);
962
DeviceClass *dc = DEVICE_CLASS(klass);
963
964
- nc->parent_reset = dc->reset;
965
- nc->parent_realize = dc->realize;
966
dc->vmsd = &vmstate_nvic;
967
+ dc->props = props_nvic;
968
dc->reset = armv7m_nvic_reset;
969
dc->realize = armv7m_nvic_realize;
970
}
971
972
static const TypeInfo armv7m_nvic_info = {
973
.name = TYPE_NVIC,
974
- .parent = TYPE_ARM_GIC_COMMON,
975
+ .parent = TYPE_SYS_BUS_DEVICE,
976
.instance_init = armv7m_nvic_instance_init,
977
.instance_size = sizeof(NVICState),
978
.class_init = armv7m_nvic_class_init,
979
- .class_size = sizeof(NVICClass),
980
+ .class_size = sizeof(SysBusDeviceClass),
981
};
982
983
static void armv7m_nvic_register_types(void)
984
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
985
index XXXXXXX..XXXXXXX 100644
986
--- a/hw/intc/trace-events
987
+++ b/hw/intc/trace-events
988
@@ -XXX,XX +XXX,XX @@ gicv3_redist_write(uint32_t cpu, uint64_t offset, uint64_t data, unsigned size,
989
gicv3_redist_badwrite(uint32_t cpu, uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 redistributor %x write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d: error"
990
gicv3_redist_set_irq(uint32_t cpu, int irq, int level) "GICv3 redistributor %x interrupt %d level changed to %d"
991
gicv3_redist_send_sgi(uint32_t cpu, int irq) "GICv3 redistributor %x pending SGI %d"
992
+
993
+# hw/intc/armv7m_nvic.c
994
+nvic_recompute_state(int vectpending, int exception_prio) "NVIC state recomputed: vectpending %d exception_prio %d"
995
+nvic_set_prio(int irq, uint8_t prio) "NVIC set irq %d priority %d"
996
+nvic_irq_update(int vectpending, int pendprio, int exception_prio, int level) "NVIC vectpending %d pending prio %d exception_prio %d: setting irq line to %d"
997
+nvic_escalate_prio(int irq, int irqprio, int runprio) "NVIC escalating irq %d to HardFault: insufficient priority %d >= %d"
998
+nvic_escalate_disabled(int irq) "NVIC escalating irq %d to HardFault: disabled"
999
+nvic_set_pending(int irq, int en, int prio) "NVIC set pending irq %d (enabled: %d priority %d)"
1000
+nvic_clear_pending(int irq, int en, int prio) "NVIC clear pending irq %d (enabled: %d priority %d)"
1001
+nvic_set_pending_level(int irq) "NVIC set pending: irq %d higher prio than vectpending: setting irq line to 1"
1002
+nvic_acknowledge_irq(int irq, int prio) "NVIC acknowledge IRQ: %d now active (prio %d)"
1003
+nvic_complete_irq(int irq) "NVIC complete IRQ %d"
1004
+nvic_set_irq_level(int irq, int level) "NVIC external irq %d level set to %d"
1005
+nvic_sysreg_read(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
1006
+nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
1007
--
135
--
1008
2.7.4
136
2.18.0
1009
137
1010
138
diff view generated by jsdifflib
1
Implement the exception return consistency checks
1
From: Richard Henderson <richard.henderson@linaro.org>
2
described in the v7M pseudocode ExceptionReturn().
3
2
4
Inspired by a patch from Michael Davidsaver's series, but
3
When support for FZ16 was added, we failed to include the bit
5
this is a reimplementation from scratch based on the
4
within FPCR_MASK, which means that it could never be set.
6
ARM ARM pseudocode.
5
Continue to zero FZ16 when ARMv8.2-FP16 is not enabled.
7
6
7
Fixes: d81ce0ef2c4
8
Cc: qemu-stable@nongnu.org (3.0.1)
9
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
12
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
13
Message-id: 20180810193129.1556-2-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
---
15
---
11
target/arm/cpu.h | 12 +++++-
16
target/arm/cpu.h | 2 +-
12
hw/intc/armv7m_nvic.c | 12 +++++-
17
target/arm/helper.c | 5 +++++
13
target/arm/helper.c | 112 +++++++++++++++++++++++++++++++++++++++++++++-----
18
2 files changed, 6 insertions(+), 1 deletion(-)
14
3 files changed, 123 insertions(+), 13 deletions(-)
15
19
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
22
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
23
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
24
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
21
#endif
25
* we store the underlying state in fpscr and just mask on read/write.
22
void armv7m_nvic_set_pending(void *opaque, int irq);
26
*/
23
void armv7m_nvic_acknowledge_irq(void *opaque);
27
#define FPSR_MASK 0xf800009f
24
-void armv7m_nvic_complete_irq(void *opaque, int irq);
28
-#define FPCR_MASK 0x07f79f00
25
+/**
29
+#define FPCR_MASK 0x07ff9f00
26
+ * armv7m_nvic_complete_irq: complete specified interrupt or exception
30
27
+ * @opaque: the NVIC
31
#define FPCR_FZ16 (1 << 19) /* ARMv8.2+, FP16 flush-to-zero */
28
+ * @irq: the exception number to complete
32
#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
29
+ *
30
+ * Returns: -1 if the irq was not active
31
+ * 1 if completing this irq brought us back to base (no active irqs)
32
+ * 0 if there is still an irq active after this one was completed
33
+ * (Ignoring -1, this is the same as the RETTOBASE value before completion.)
34
+ */
35
+int armv7m_nvic_complete_irq(void *opaque, int irq);
36
37
/* Interface for defining coprocessor registers.
38
* Registers are defined in tables of arm_cp_reginfo structs
39
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/intc/armv7m_nvic.c
42
+++ b/hw/intc/armv7m_nvic.c
43
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_acknowledge_irq(void *opaque)
44
nvic_irq_update(s);
45
}
46
47
-void armv7m_nvic_complete_irq(void *opaque, int irq)
48
+int armv7m_nvic_complete_irq(void *opaque, int irq)
49
{
50
NVICState *s = (NVICState *)opaque;
51
VecInfo *vec;
52
+ int ret;
53
54
assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
55
56
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_complete_irq(void *opaque, int irq)
57
58
trace_nvic_complete_irq(irq);
59
60
+ if (!vec->active) {
61
+ /* Tell the caller this was an illegal exception return */
62
+ return -1;
63
+ }
64
+
65
+ ret = nvic_rettobase(s);
66
+
67
vec->active = 0;
68
if (vec->level) {
69
/* Re-pend the exception if it's still held high; only
70
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_complete_irq(void *opaque, int irq)
71
}
72
73
nvic_irq_update(s);
74
+
75
+ return ret;
76
}
77
78
/* callback when external interrupt line is changed */
79
diff --git a/target/arm/helper.c b/target/arm/helper.c
33
diff --git a/target/arm/helper.c b/target/arm/helper.c
80
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
81
--- a/target/arm/helper.c
35
--- a/target/arm/helper.c
82
+++ b/target/arm/helper.c
36
+++ b/target/arm/helper.c
83
@@ -XXX,XX +XXX,XX @@ static void v7m_push_stack(ARMCPU *cpu)
37
@@ -XXX,XX +XXX,XX @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
84
v7m_push(env, env->regs[0]);
38
int i;
85
}
39
uint32_t changed;
86
40
87
-static void do_v7m_exception_exit(CPUARMState *env)
41
+ /* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */
88
+static void do_v7m_exception_exit(ARMCPU *cpu)
42
+ if (!arm_feature(env, ARM_FEATURE_V8_FP16)) {
89
{
43
+ val &= ~FPCR_FZ16;
90
+ CPUARMState *env = &cpu->env;
91
uint32_t type;
92
uint32_t xpsr;
93
-
94
+ bool ufault = false;
95
+ bool return_to_sp_process = false;
96
+ bool return_to_handler = false;
97
+ bool rettobase = false;
98
+
99
+ /* We can only get here from an EXCP_EXCEPTION_EXIT, and
100
+ * arm_v7m_do_unassigned_access() enforces the architectural rule
101
+ * that jumps to magic addresses don't have magic behaviour unless
102
+ * we're in Handler mode (compare pseudocode BXWritePC()).
103
+ */
104
+ assert(env->v7m.exception != 0);
105
+
106
+ /* In the spec pseudocode ExceptionReturn() is called directly
107
+ * from BXWritePC() and gets the full target PC value including
108
+ * bit zero. In QEMU's implementation we treat it as a normal
109
+ * jump-to-register (which is then caught later on), and so split
110
+ * the target value up between env->regs[15] and env->thumb in
111
+ * gen_bx(). Reconstitute it.
112
+ */
113
type = env->regs[15];
114
+ if (env->thumb) {
115
+ type |= 1;
116
+ }
44
+ }
117
+
45
+
118
+ qemu_log_mask(CPU_LOG_INT, "Exception return: magic PC %" PRIx32
46
changed = env->vfp.xregs[ARM_VFP_FPSCR];
119
+ " previous exception %d\n",
47
env->vfp.xregs[ARM_VFP_FPSCR] = (val & 0xffc8ffff);
120
+ type, env->v7m.exception);
48
env->vfp.vec_len = (val >> 16) & 7;
121
+
122
+ if (extract32(type, 5, 23) != extract32(-1, 5, 23)) {
123
+ qemu_log_mask(LOG_GUEST_ERROR, "M profile: zero high bits in exception "
124
+ "exit PC value 0x%" PRIx32 " are UNPREDICTABLE\n", type);
125
+ }
126
+
127
if (env->v7m.exception != ARMV7M_EXCP_NMI) {
128
/* Auto-clear FAULTMASK on return from other than NMI */
129
env->daif &= ~PSTATE_F;
130
}
131
- if (env->v7m.exception != 0) {
132
- armv7m_nvic_complete_irq(env->nvic, env->v7m.exception);
133
+
134
+ switch (armv7m_nvic_complete_irq(env->nvic, env->v7m.exception)) {
135
+ case -1:
136
+ /* attempt to exit an exception that isn't active */
137
+ ufault = true;
138
+ break;
139
+ case 0:
140
+ /* still an irq active now */
141
+ break;
142
+ case 1:
143
+ /* we returned to base exception level, no nesting.
144
+ * (In the pseudocode this is written using "NestedActivation != 1"
145
+ * where we have 'rettobase == false'.)
146
+ */
147
+ rettobase = true;
148
+ break;
149
+ default:
150
+ g_assert_not_reached();
151
+ }
152
+
153
+ switch (type & 0xf) {
154
+ case 1: /* Return to Handler */
155
+ return_to_handler = true;
156
+ break;
157
+ case 13: /* Return to Thread using Process stack */
158
+ return_to_sp_process = true;
159
+ /* fall through */
160
+ case 9: /* Return to Thread using Main stack */
161
+ if (!rettobase &&
162
+ !(env->v7m.ccr & R_V7M_CCR_NONBASETHRDENA_MASK)) {
163
+ ufault = true;
164
+ }
165
+ break;
166
+ default:
167
+ ufault = true;
168
+ }
169
+
170
+ if (ufault) {
171
+ /* Bad exception return: instead of popping the exception
172
+ * stack, directly take a usage fault on the current stack.
173
+ */
174
+ env->v7m.cfsr |= R_V7M_CFSR_INVPC_MASK;
175
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
176
+ v7m_exception_taken(cpu, type | 0xf0000000);
177
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
178
+ "stackframe: failed exception return integrity check\n");
179
+ return;
180
}
181
182
/* Switch to the target stack. */
183
- switch_v7m_sp(env, (type & 4) != 0);
184
+ switch_v7m_sp(env, return_to_sp_process);
185
/* Pop registers. */
186
env->regs[0] = v7m_pop(env);
187
env->regs[1] = v7m_pop(env);
188
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(CPUARMState *env)
189
/* Undo stack alignment. */
190
if (xpsr & 0x200)
191
env->regs[13] |= 4;
192
- /* ??? The exception return type specifies Thread/Handler mode. However
193
- this is also implied by the xPSR value. Not sure what to do
194
- if there is a mismatch. */
195
- /* ??? Likewise for mismatches between the CONTROL register and the stack
196
- pointer. */
197
+
198
+ /* The restored xPSR exception field will be zero if we're
199
+ * resuming in Thread mode. If that doesn't match what the
200
+ * exception return type specified then this is a UsageFault.
201
+ */
202
+ if (return_to_handler == (env->v7m.exception == 0)) {
203
+ /* Take an INVPC UsageFault by pushing the stack again. */
204
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
205
+ env->v7m.cfsr |= R_V7M_CFSR_INVPC_MASK;
206
+ v7m_push_stack(cpu);
207
+ v7m_exception_taken(cpu, type | 0xf0000000);
208
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on new stackframe: "
209
+ "failed exception return integrity check\n");
210
+ return;
211
+ }
212
+
213
+ /* Otherwise, we have a successful exception exit. */
214
+ qemu_log_mask(CPU_LOG_INT, "...successful exception return\n");
215
}
216
217
static void arm_log_exception(int idx)
218
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
219
case EXCP_IRQ:
220
break;
221
case EXCP_EXCEPTION_EXIT:
222
- do_v7m_exception_exit(env);
223
+ do_v7m_exception_exit(cpu);
224
return;
225
default:
226
cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
227
--
49
--
228
2.7.4
50
2.18.0
229
51
230
52
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
All the places in armv7m_cpu_do_interrupt() which pend an
3
When FZ is set, input_denormal exceptions are recognized, but this does
4
exception in the NVIC are doing so for synchronous
4
not happen with FZ16. The softfloat code has no way to distinguish
5
exceptions. We know that we will always take some
5
these bits and will raise such exceptions into fp_status_f16.flags,
6
exception in this case, so we can just acknowledge it
6
so ignore them when computing the accumulated flags.
7
immediately, rather than returning and then immediately
8
being called again because the NVIC has raised its outbound
9
IRQ line.
10
7
11
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
8
Cc: qemu-stable@nongnu.org (3.0.1)
12
[PMM: tweaked commit message; added DEBUG to the set of
9
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
13
exceptions we handle immediately, since it is synchronous
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
when it results from the BKPT instruction]
11
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
12
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
13
Message-id: 20180810193129.1556-3-richard.henderson@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
17
---
15
---
18
target/arm/helper.c | 15 +++++++++------
16
target/arm/helper.c | 6 +++++-
19
1 file changed, 9 insertions(+), 6 deletions(-)
17
1 file changed, 5 insertions(+), 1 deletion(-)
20
18
21
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper.c
21
--- a/target/arm/helper.c
24
+++ b/target/arm/helper.c
22
+++ b/target/arm/helper.c
25
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
23
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
26
case EXCP_UDEF:
24
fpscr = (env->vfp.xregs[ARM_VFP_FPSCR] & 0xffc8ffff)
27
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
25
| (env->vfp.vec_len << 16)
28
env->v7m.cfsr |= R_V7M_CFSR_UNDEFINSTR_MASK;
26
| (env->vfp.vec_stride << 20);
29
- return;
30
+ break;
31
case EXCP_NOCP:
32
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
33
env->v7m.cfsr |= R_V7M_CFSR_NOCP_MASK;
34
- return;
35
+ break;
36
case EXCP_SWI:
37
/* The PC already points to the next instruction. */
38
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC);
39
- return;
40
+ break;
41
case EXCP_PREFETCH_ABORT:
42
case EXCP_DATA_ABORT:
43
/* TODO: if we implemented the MPU registers, this is where we
44
* should set the MMFAR, etc from exception.fsr and exception.vaddress.
45
*/
46
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM);
47
- return;
48
+ break;
49
case EXCP_BKPT:
50
if (semihosting_enabled()) {
51
int nr;
52
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
53
}
54
}
55
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG);
56
- return;
57
+ break;
58
case EXCP_IRQ:
59
- armv7m_nvic_acknowledge_irq(env->nvic);
60
break;
61
case EXCP_EXCEPTION_EXIT:
62
do_v7m_exception_exit(env);
63
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
64
return; /* Never happens. Keep compiler happy. */
65
}
66
67
+ armv7m_nvic_acknowledge_irq(env->nvic);
68
+
27
+
69
+ qemu_log_mask(CPU_LOG_INT, "... as %d\n", env->v7m.exception);
28
i = get_float_exception_flags(&env->vfp.fp_status);
29
i |= get_float_exception_flags(&env->vfp.standard_fp_status);
30
- i |= get_float_exception_flags(&env->vfp.fp_status_f16);
31
+ /* FZ16 does not generate an input denormal exception. */
32
+ i |= (get_float_exception_flags(&env->vfp.fp_status_f16)
33
+ & ~float_flag_input_denormal);
70
+
34
+
71
/* Align stack pointer if the guest wants that */
35
fpscr |= vfp_exceptbits_from_host(i);
72
if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) {
36
return fpscr;
73
env->regs[13] -= 4;
37
}
74
--
38
--
75
2.7.4
39
2.18.0
76
40
77
41
diff view generated by jsdifflib
1
In get_page_addr_code(), if the guest PC doesn't correspond to RAM
1
From: Richard Henderson <richard.henderson@linaro.org>
2
then we currently run the CPU's do_unassigned_access() hook if it has
3
one, and otherwise we give up and exit QEMU with a more-or-less
4
useful message. This code assumes that the do_unassigned_access hook
5
will never return, because if it does then we'll plough on attempting
6
to use a non-RAM TLB entry to get a RAM address and will abort() in
7
qemu_ram_addr_from_host_nofail(). Unfortunately some CPU
8
implementations of this hook do return: Microblaze, SPARC and the ARM
9
v7M.
10
2
11
Change the code to call report_bad_exec() if the hook returns, as
3
This makes float16_muladd correctly use FZ16 not FZ.
12
well as if it didn't have one. This means we can tidy it up to use
13
the cpu_unassigned_access() function which wraps the "get the CPU
14
class and call the hook if it has one" work, since we aren't trying
15
to distinguish "no hook" from "hook existed and returned" any more.
16
4
17
This brings the handling of this hook into line with the handling
5
Fixes: 6ceabaad110
18
used for data accesses, where "hook returned" is treated the
6
Cc: qemu-stable@nongnu.org (3.0.1)
19
same as "no hook existed" and gets you the default behaviour.
7
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
10
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
11
Message-id: 20180810193129.1556-4-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
target/arm/sve_helper.c | 2 +-
15
1 file changed, 1 insertion(+), 1 deletion(-)
20
16
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
22
Reviewed-by: Richard Henderson <rth@twiddle.net>
23
---
24
cputlb.c | 15 +++++++--------
25
1 file changed, 7 insertions(+), 8 deletions(-)
26
27
diff --git a/cputlb.c b/cputlb.c
28
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
29
--- a/cputlb.c
19
--- a/target/arm/sve_helper.c
30
+++ b/cputlb.c
20
+++ b/target/arm/sve_helper.c
31
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
21
@@ -XXX,XX +XXX,XX @@ static void do_fmla_zpzzz_h(CPUARMState *env, void *vg, uint32_t desc,
32
pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
22
e1 = *(uint16_t *)(vn + H1_2(i)) ^ neg1;
33
mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
23
e2 = *(uint16_t *)(vm + H1_2(i));
34
if (memory_region_is_unassigned(mr)) {
24
e3 = *(uint16_t *)(va + H1_2(i)) ^ neg3;
35
- CPUClass *cc = CPU_GET_CLASS(cpu);
25
- r = float16_muladd(e1, e2, e3, 0, &env->vfp.fp_status);
36
-
26
+ r = float16_muladd(e1, e2, e3, 0, &env->vfp.fp_status_f16);
37
- if (cc->do_unassigned_access) {
27
*(uint16_t *)(vd + H1_2(i)) = r;
38
- cc->do_unassigned_access(cpu, addr, false, true, 0, 4);
28
}
39
- } else {
29
} while (i & 63);
40
- report_bad_exec(cpu, addr);
41
- exit(1);
42
- }
43
+ cpu_unassigned_access(cpu, addr, false, true, 0, 4);
44
+ /* The CPU's unassigned access hook might have longjumped out
45
+ * with an exception. If it didn't (or there was no hook) then
46
+ * we can't proceed further.
47
+ */
48
+ report_bad_exec(cpu, addr);
49
+ exit(1);
50
}
51
p = (void *)((uintptr_t)addr + env1->tlb_table[mmu_idx][page_index].addend);
52
return qemu_ram_addr_from_host_nofail(p);
53
--
30
--
54
2.7.4
31
2.18.0
55
32
56
33
diff view generated by jsdifflib
1
From: Kurban Mallachiev <mallachiev@ispras.ru>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The i.MX timer device can be reset by writing to the SWR bit
3
We were using the wrong flush-to-zero bit for the non-half input.
4
of the CR register. This has to behave differently from hard
5
(power-on) reset because it does not reset all of the bits
6
in the CR register.
7
4
8
We were incorrectly implementing soft reset and hard reset
5
Fixes: 46d33d1e3c9
9
the same way, and in addition had a logic error which meant
6
Cc: qemu-stable@nongnu.org (3.0.1)
10
that we were clearing the bits that soft-reset is supposed
7
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
11
to preserve and not touching the bits that soft-reset clears.
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
This was not correct behaviour for either kind of reset.
9
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
13
10
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
14
Separate out the soft reset and hard reset code paths, and
11
Message-id: 20180810193129.1556-5-richard.henderson@linaro.org
15
correct the handling of reset of the CR register so that it
16
is correct in both cases.
17
18
Signed-off-by: Kurban Mallachiev <mallachiev@ispras.ru>
19
[PMM: rephrased commit message, spacing on operators;
20
use bool rather than int for is_soft_reset]
21
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
13
---
24
hw/timer/imx_gpt.c | 33 +++++++++++++++++++++++++--------
14
target/arm/translate-sve.c | 4 ++--
25
1 file changed, 25 insertions(+), 8 deletions(-)
15
1 file changed, 2 insertions(+), 2 deletions(-)
26
16
27
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
17
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
28
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/timer/imx_gpt.c
19
--- a/target/arm/translate-sve.c
30
+++ b/hw/timer/imx_gpt.c
20
+++ b/target/arm/translate-sve.c
31
@@ -XXX,XX +XXX,XX @@ static uint64_t imx_gpt_read(void *opaque, hwaddr offset, unsigned size)
21
@@ -XXX,XX +XXX,XX @@ static bool do_zpz_ptr(DisasContext *s, int rd, int rn, int pg,
32
return reg_value;
22
23
static bool trans_FCVT_sh(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
24
{
25
- return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_fcvt_sh);
26
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvt_sh);
33
}
27
}
34
28
35
-static void imx_gpt_reset(DeviceState *dev)
29
static bool trans_FCVT_hs(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
36
-{
30
@@ -XXX,XX +XXX,XX @@ static bool trans_FCVT_hs(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
37
- IMXGPTState *s = IMX_GPT(dev);
31
38
32
static bool trans_FCVT_dh(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
39
+static void imx_gpt_reset_common(IMXGPTState *s, bool is_soft_reset)
33
{
40
+{
34
- return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_fcvt_dh);
41
/* stop timer */
35
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvt_dh);
42
ptimer_stop(s->timer);
43
44
- /*
45
- * Soft reset doesn't touch some bits; hard reset clears them
46
+ /* Soft reset and hard reset differ only in their handling of the CR
47
+ * register -- soft reset preserves the values of some bits there.
48
*/
49
- s->cr &= ~(GPT_CR_EN|GPT_CR_ENMOD|GPT_CR_STOPEN|GPT_CR_DOZEN|
50
- GPT_CR_WAITEN|GPT_CR_DBGEN);
51
+ if (is_soft_reset) {
52
+ /* Clear all CR bits except those that are preserved by soft reset. */
53
+ s->cr &= GPT_CR_EN | GPT_CR_ENMOD | GPT_CR_STOPEN | GPT_CR_DOZEN |
54
+ GPT_CR_WAITEN | GPT_CR_DBGEN |
55
+ (GPT_CR_CLKSRC_MASK << GPT_CR_CLKSRC_SHIFT);
56
+ } else {
57
+ s->cr = 0;
58
+ }
59
s->sr = 0;
60
s->pr = 0;
61
s->ir = 0;
62
@@ -XXX,XX +XXX,XX @@ static void imx_gpt_reset(DeviceState *dev)
63
}
64
}
36
}
65
37
66
+static void imx_gpt_soft_reset(DeviceState *dev)
38
static bool trans_FCVT_hd(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
67
+{
68
+ IMXGPTState *s = IMX_GPT(dev);
69
+ imx_gpt_reset_common(s, true);
70
+}
71
+
72
+static void imx_gpt_reset(DeviceState *dev)
73
+{
74
+ IMXGPTState *s = IMX_GPT(dev);
75
+ imx_gpt_reset_common(s, false);
76
+}
77
+
78
static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
79
unsigned size)
80
{
81
@@ -XXX,XX +XXX,XX @@ static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
82
s->cr = value & ~0x7c14;
83
if (s->cr & GPT_CR_SWR) { /* force reset */
84
/* handle the reset */
85
- imx_gpt_reset(DEVICE(s));
86
+ imx_gpt_soft_reset(DEVICE(s));
87
} else {
88
/* set our freq, as the source might have changed */
89
imx_gpt_set_freq(s);
90
--
39
--
91
2.7.4
40
2.18.0
92
41
93
42
diff view generated by jsdifflib
1
From: Prasad J Pandit <pjp@fedoraproject.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
In sdhci_write invoke multi block transfer if it is enabled
3
These insns require u=1; failed to include that in the switch
4
in the transfer mode register 's->trnmod'.
4
cases. This probably happened during one of the rebases just
5
before final commit.
5
6
6
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
7
Fixes: d17b7cdcf4e
7
Message-id: 20170214185225.7994-4-ppandit@redhat.com
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
9
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
10
Message-id: 20180810193129.1556-6-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
12
---
11
hw/sd/sdhci.c | 6 +++++-
13
target/arm/translate-a64.c | 12 ++++++------
12
1 file changed, 5 insertions(+), 1 deletion(-)
14
1 file changed, 6 insertions(+), 6 deletions(-)
13
15
14
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
16
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/sd/sdhci.c
18
--- a/target/arm/translate-a64.c
17
+++ b/hw/sd/sdhci.c
19
+++ b/target/arm/translate-a64.c
18
@@ -XXX,XX +XXX,XX @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
20
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
19
/* Writing to last byte of sdmasysad might trigger transfer */
20
if (!(mask & 0xFF000000) && TRANSFERRING_DATA(s->prnsts) && s->blkcnt &&
21
s->blksize && SDHC_DMA_TYPE(s->hostctl) == SDHC_CTRL_SDMA) {
22
- sdhci_sdma_transfer_multi_blocks(s);
23
+ if (s->trnmod & SDHC_TRNS_MULTI) {
24
+ sdhci_sdma_transfer_multi_blocks(s);
25
+ } else {
26
+ sdhci_sdma_transfer_single_block(s);
27
+ }
28
}
21
}
22
feature = ARM_FEATURE_V8_DOTPROD;
29
break;
23
break;
30
case SDHC_BLKSIZE:
24
- case 0x8: /* FCMLA, #0 */
25
- case 0x9: /* FCMLA, #90 */
26
- case 0xa: /* FCMLA, #180 */
27
- case 0xb: /* FCMLA, #270 */
28
- case 0xc: /* FCADD, #90 */
29
- case 0xe: /* FCADD, #270 */
30
+ case 0x18: /* FCMLA, #0 */
31
+ case 0x19: /* FCMLA, #90 */
32
+ case 0x1a: /* FCMLA, #180 */
33
+ case 0x1b: /* FCMLA, #270 */
34
+ case 0x1c: /* FCADD, #90 */
35
+ case 0x1e: /* FCADD, #270 */
36
if (size == 0
37
|| (size == 1 && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))
38
|| (size == 3 && !is_q)) {
31
--
39
--
32
2.7.4
40
2.18.0
33
41
34
42
diff view generated by jsdifflib
1
From: Prasad J Pandit <pjp@fedoraproject.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
In the SDHCI protocol, the transfer mode register value
3
For 0x1.0000000000003p+0 + 0x1.ffffffep+14 = 0x1.0001fffp+15
4
is used during multi block transfer to check if block count
4
we dropped the sticky bit and so failed to raise inexact.
5
register is enabled and should be updated. Transfer mode
6
register could be set such that, block count register would
7
not be updated, thus leading to an infinite loop. Add check
8
to avoid it.
9
5
10
Reported-by: Wjjzhang <wjjzhang@tencent.com>
6
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
11
Reported-by: Jiang Xin <jiangxin1@huawei.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
8
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
13
Message-id: 20170214185225.7994-3-ppandit@redhat.com
9
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
14
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
10
Message-id: 20180810193129.1556-7-richard.henderson@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
12
---
17
hw/sd/sdhci.c | 10 +++++-----
13
fpu/softfloat.c | 2 +-
18
1 file changed, 5 insertions(+), 5 deletions(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
19
15
20
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
16
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
21
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/sd/sdhci.c
18
--- a/fpu/softfloat.c
23
+++ b/hw/sd/sdhci.c
19
+++ b/fpu/softfloat.c
24
@@ -XXX,XX +XXX,XX @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
20
@@ -XXX,XX +XXX,XX @@ static FloatParts addsub_floats(FloatParts a, FloatParts b, bool subtract,
25
uint32_t boundary_chk = 1 << (((s->blksize & 0xf000) >> 12) + 12);
21
}
26
uint32_t boundary_count = boundary_chk - (s->sdmasysad % boundary_chk);
22
a.frac += b.frac;
27
23
if (a.frac & DECOMPOSED_OVERFLOW_BIT) {
28
+ if (!(s->trnmod & SDHC_TRNS_BLK_CNT_EN) || !s->blkcnt) {
24
- a.frac >>= 1;
29
+ qemu_log_mask(LOG_UNIMP, "infinite transfer is not supported\n");
25
+ shift64RightJamming(a.frac, 1, &a.frac);
30
+ return;
26
a.exp += 1;
31
+ }
27
}
32
+
28
return a;
33
/* XXX: Some sd/mmc drivers (for example, u-boot-slp) do not account for
34
* possible stop at page boundary if initial address is not page aligned,
35
* allow them to work properly */
36
@@ -XXX,XX +XXX,XX @@ static void sdhci_data_transfer(void *opaque)
37
if (s->trnmod & SDHC_TRNS_DMA) {
38
switch (SDHC_DMA_TYPE(s->hostctl)) {
39
case SDHC_CTRL_SDMA:
40
- if ((s->trnmod & SDHC_TRNS_MULTI) &&
41
- (!(s->trnmod & SDHC_TRNS_BLK_CNT_EN) || s->blkcnt == 0)) {
42
- break;
43
- }
44
-
45
if ((s->blkcnt == 1) || !(s->trnmod & SDHC_TRNS_MULTI)) {
46
sdhci_sdma_transfer_single_block(s);
47
} else {
48
--
29
--
49
2.7.4
30
2.18.0
50
31
51
32
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
This adds the bcm2835_sdhost and bcm2835_gpio to the BCM2835 platform.
3
Now that we've got the common sysbus_init_child_obj() function, we do
4
not need the local init_sysbus_child() anymore.
4
5
5
For supporting the SD controller selection (alternate function of GPIOs
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
6
48-53), the bcm2835_gpio now exposes an sdbus.
7
Message-id: 1534420566-15799-1-git-send-email-thuth@redhat.com
7
It also has a link to both the sdbus of sdhci and sdhost controllers,
8
and the card is reparented from one bus to another when the alternate
9
function of GPIOs 48-53 is modified.
10
11
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
12
Message-id: 20170224164021.9066-5-clement.deschamps@antfield.fr
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
10
---
16
include/hw/arm/bcm2835_peripherals.h | 4 ++++
11
hw/arm/mps2-tz.c | 32 +++++++++++---------------------
17
hw/arm/bcm2835_peripherals.c | 43 ++++++++++++++++++++++++++++++++++--
12
1 file changed, 11 insertions(+), 21 deletions(-)
18
2 files changed, 45 insertions(+), 2 deletions(-)
19
13
20
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
14
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
21
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/arm/bcm2835_peripherals.h
16
--- a/hw/arm/mps2-tz.c
23
+++ b/include/hw/arm/bcm2835_peripherals.h
17
+++ b/hw/arm/mps2-tz.c
24
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static void make_ram_alias(MemoryRegion *mr, const char *name,
25
#include "hw/misc/bcm2835_rng.h"
19
memory_region_add_subregion(get_system_memory(), base, mr);
26
#include "hw/misc/bcm2835_mbox.h"
27
#include "hw/sd/sdhci.h"
28
+#include "hw/sd/bcm2835_sdhost.h"
29
+#include "hw/gpio/bcm2835_gpio.h"
30
31
#define TYPE_BCM2835_PERIPHERALS "bcm2835-peripherals"
32
#define BCM2835_PERIPHERALS(obj) \
33
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2835PeripheralState {
34
BCM2835RngState rng;
35
BCM2835MboxState mboxes;
36
SDHCIState sdhci;
37
+ BCM2835SDHostState sdhost;
38
+ BCM2835GpioState gpio;
39
} BCM2835PeripheralState;
40
41
#endif /* BCM2835_PERIPHERALS_H */
42
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/arm/bcm2835_peripherals.c
45
+++ b/hw/arm/bcm2835_peripherals.c
46
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
47
object_property_add_child(obj, "sdhci", OBJECT(&s->sdhci), NULL);
48
qdev_set_parent_bus(DEVICE(&s->sdhci), sysbus_get_default());
49
50
+ /* SDHOST */
51
+ object_initialize(&s->sdhost, sizeof(s->sdhost), TYPE_BCM2835_SDHOST);
52
+ object_property_add_child(obj, "sdhost", OBJECT(&s->sdhost), NULL);
53
+ qdev_set_parent_bus(DEVICE(&s->sdhost), sysbus_get_default());
54
+
55
/* DMA Channels */
56
object_initialize(&s->dma, sizeof(s->dma), TYPE_BCM2835_DMA);
57
object_property_add_child(obj, "dma", OBJECT(&s->dma), NULL);
58
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
59
60
object_property_add_const_link(OBJECT(&s->dma), "dma-mr",
61
OBJECT(&s->gpu_bus_mr), &error_abort);
62
+
63
+ /* GPIO */
64
+ object_initialize(&s->gpio, sizeof(s->gpio), TYPE_BCM2835_GPIO);
65
+ object_property_add_child(obj, "gpio", OBJECT(&s->gpio), NULL);
66
+ qdev_set_parent_bus(DEVICE(&s->gpio), sysbus_get_default());
67
+
68
+ object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhci",
69
+ OBJECT(&s->sdhci.sdbus), &error_abort);
70
+ object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhost",
71
+ OBJECT(&s->sdhost.sdbus), &error_abort);
72
}
20
}
73
21
74
static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
22
-static void init_sysbus_child(Object *parent, const char *childname,
75
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
23
- void *child, size_t childsize,
76
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0,
24
- const char *childtype)
77
qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
25
-{
78
INTERRUPT_ARASANSDIO));
26
- object_initialize(child, childsize, childtype);
79
- object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->sdhci), "sd-bus",
27
- object_property_add_child(parent, childname, OBJECT(child), &error_abort);
80
- &err);
28
- qdev_set_parent_bus(DEVICE(child), sysbus_get_default());
81
+
29
-
82
+ /* SDHOST */
30
-}
83
+ object_property_set_bool(OBJECT(&s->sdhost), true, "realized", &err);
31
-
84
if (err) {
32
/* Most of the devices in the AN505 FPGA image sit behind
85
error_propagate(errp, err);
33
* Peripheral Protection Controllers. These data structures
86
return;
34
* define the layout of which devices sit behind which PPCs.
35
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
36
*/
37
UnimplementedDeviceState *uds = opaque;
38
39
- init_sysbus_child(OBJECT(mms), name, uds,
40
- sizeof(UnimplementedDeviceState),
41
- TYPE_UNIMPLEMENTED_DEVICE);
42
+ sysbus_init_child_obj(OBJECT(mms), name, uds,
43
+ sizeof(UnimplementedDeviceState),
44
+ TYPE_UNIMPLEMENTED_DEVICE);
45
qdev_prop_set_string(DEVICE(uds), "name", name);
46
qdev_prop_set_uint64(DEVICE(uds), "size", size);
47
object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal);
48
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
49
DeviceState *iotkitdev = DEVICE(&mms->iotkit);
50
DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
51
52
- init_sysbus_child(OBJECT(mms), name, uart,
53
- sizeof(mms->uart[0]), TYPE_CMSDK_APB_UART);
54
+ sysbus_init_child_obj(OBJECT(mms), name, uart, sizeof(mms->uart[0]),
55
+ TYPE_CMSDK_APB_UART);
56
qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i));
57
qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", SYSCLK_FRQ);
58
object_property_set_bool(OBJECT(uart), true, "realized", &error_fatal);
59
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
60
61
memory_region_init_ram(ssram, NULL, name, ramsize[i], &error_fatal);
62
63
- init_sysbus_child(OBJECT(mms), mpcname, mpc,
64
- sizeof(mms->ssram_mpc[0]), TYPE_TZ_MPC);
65
+ sysbus_init_child_obj(OBJECT(mms), mpcname, mpc, sizeof(mms->ssram_mpc[0]),
66
+ TYPE_TZ_MPC);
67
object_property_set_link(OBJECT(mpc), OBJECT(ssram),
68
"downstream", &error_fatal);
69
object_property_set_bool(OBJECT(mpc), true, "realized", &error_fatal);
70
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
71
exit(1);
87
}
72
}
88
73
89
+ memory_region_add_subregion(&s->peri_mr, MMCI0_OFFSET,
74
- init_sysbus_child(OBJECT(machine), "iotkit", &mms->iotkit,
90
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhost), 0));
75
- sizeof(mms->iotkit), TYPE_IOTKIT);
91
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhost), 0,
76
+ sysbus_init_child_obj(OBJECT(machine), "iotkit", &mms->iotkit,
92
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
77
+ sizeof(mms->iotkit), TYPE_IOTKIT);
93
+ INTERRUPT_SDIO));
78
iotkitdev = DEVICE(&mms->iotkit);
94
+
79
object_property_set_link(OBJECT(&mms->iotkit), OBJECT(system_memory),
95
/* DMA Channels */
80
"memory", &error_abort);
96
object_property_set_bool(OBJECT(&s->dma), true, "realized", &err);
81
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
97
if (err) {
82
int port;
98
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
83
char *gpioname;
99
BCM2835_IC_GPU_IRQ,
84
100
INTERRUPT_DMA0 + n));
85
- init_sysbus_child(OBJECT(machine), ppcinfo->name, ppc,
101
}
86
- sizeof(TZPPC), TYPE_TZ_PPC);
102
+
87
+ sysbus_init_child_obj(OBJECT(machine), ppcinfo->name, ppc,
103
+ /* GPIO */
88
+ sizeof(TZPPC), TYPE_TZ_PPC);
104
+ object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err);
89
ppcdev = DEVICE(ppc);
105
+ if (err) {
90
106
+ error_propagate(errp, err);
91
for (port = 0; port < TZ_NUM_PORTS; port++) {
107
+ return;
108
+ }
109
+
110
+ memory_region_add_subregion(&s->peri_mr, GPIO_OFFSET,
111
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0));
112
+
113
+ object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-bus",
114
+ &err);
115
+ if (err) {
116
+ error_propagate(errp, err);
117
+ return;
118
+ }
119
}
120
121
static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data)
122
--
92
--
123
2.7.4
93
2.18.0
124
94
125
95
diff view generated by jsdifflib