2 * STM32L4x5 SYSCFG (System Configuration Controller)
4 * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
5 * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
7 * SPDX-License-Identifier: GPL-2.0-or-later
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
12 * This work is based on the stm32f4xx_syscfg by Alistair Francis.
13 * Original code is licensed under the MIT License:
15 * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
19 * The reference used is the STMicroElectronics RM0351 Reference manual
20 * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
21 * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
24 #include "qemu/osdep.h"
28 #include "migration/vmstate.h"
29 #include "hw/misc/stm32l4x5_syscfg.h"
30 #include "hw/gpio/stm32l4x5_gpio.h"
32 #define SYSCFG_MEMRMP 0x00
33 #define SYSCFG_CFGR1 0x04
34 #define SYSCFG_EXTICR1 0x08
35 #define SYSCFG_EXTICR2 0x0C
36 #define SYSCFG_EXTICR3 0x10
37 #define SYSCFG_EXTICR4 0x14
38 #define SYSCFG_SCSR 0x18
39 #define SYSCFG_CFGR2 0x1C
40 #define SYSCFG_SWPR 0x20
41 #define SYSCFG_SKR 0x24
42 #define SYSCFG_SWPR2 0x28
44 /* 00000000_00000000_00000001_00000111 */
45 #define ACTIVABLE_BITS_MEMRP 0x00000107
47 /* 11111100_11111111_00000001_00000000 */
48 #define ACTIVABLE_BITS_CFGR1 0xFCFF0100
49 /* 00000000_00000000_00000000_00000001 */
50 #define FIREWALL_DISABLE_CFGR1 0x00000001
52 /* 00000000_00000000_11111111_11111111 */
53 #define ACTIVABLE_BITS_EXTICR 0x0000FFFF
55 /* 00000000_00000000_00000000_00000011 */
56 /* #define ACTIVABLE_BITS_SCSR 0x00000003 */
58 /* 00000000_00000000_00000000_00001111 */
59 #define ECC_LOCK_CFGR2 0x0000000F
60 /* 00000000_00000000_00000001_00000000 */
61 #define SRAM2_PARITY_ERROR_FLAG_CFGR2 0x00000100
63 /* 00000000_00000000_00000000_11111111 */
64 #define ACTIVABLE_BITS_SKR 0x000000FF
66 #define NUM_LINES_PER_EXTICR_REG 4
68 static void stm32l4x5_syscfg_hold_reset(Object
*obj
)
70 Stm32l4x5SyscfgState
*s
= STM32L4X5_SYSCFG(obj
);
72 s
->memrmp
= 0x00000000;
73 s
->cfgr1
= 0x7C000001;
74 s
->exticr
[0] = 0x00000000;
75 s
->exticr
[1] = 0x00000000;
76 s
->exticr
[2] = 0x00000000;
77 s
->exticr
[3] = 0x00000000;
79 s
->cfgr2
= 0x00000000;
82 s
->swpr2
= 0x00000000;
85 static void stm32l4x5_syscfg_set_irq(void *opaque
, int irq
, int level
)
87 Stm32l4x5SyscfgState
*s
= opaque
;
88 const uint8_t gpio
= irq
/ GPIO_NUM_PINS
;
89 const int line
= irq
% GPIO_NUM_PINS
;
91 const int exticr_reg
= line
/ NUM_LINES_PER_EXTICR_REG
;
92 const int startbit
= (line
% NUM_LINES_PER_EXTICR_REG
) * 4;
94 g_assert(gpio
< NUM_GPIOS
);
95 trace_stm32l4x5_syscfg_set_irq(gpio
, line
, level
);
97 if (extract32(s
->exticr
[exticr_reg
], startbit
, 4) == gpio
) {
98 trace_stm32l4x5_syscfg_forward_exti(line
);
99 qemu_set_irq(s
->gpio_out
[line
], level
);
103 static uint64_t stm32l4x5_syscfg_read(void *opaque
, hwaddr addr
,
106 Stm32l4x5SyscfgState
*s
= opaque
;
108 trace_stm32l4x5_syscfg_read(addr
);
115 case SYSCFG_EXTICR1
...SYSCFG_EXTICR4
:
116 return s
->exticr
[(addr
- SYSCFG_EXTICR1
) / 4];
128 qemu_log_mask(LOG_GUEST_ERROR
,
129 "%s: Bad offset 0x%" HWADDR_PRIx
"\n", __func__
, addr
);
133 static void stm32l4x5_syscfg_write(void *opaque
, hwaddr addr
,
134 uint64_t value
, unsigned int size
)
136 Stm32l4x5SyscfgState
*s
= opaque
;
138 trace_stm32l4x5_syscfg_write(addr
, value
);
142 qemu_log_mask(LOG_UNIMP
,
143 "%s: Changing the memory mapping isn't supported\n",
145 s
->memrmp
= value
& ACTIVABLE_BITS_MEMRP
;
148 qemu_log_mask(LOG_UNIMP
,
149 "%s: Functions in CFGRx aren't supported\n",
151 /* bit 0 (firewall dis.) is cleared by software, set only by reset. */
152 s
->cfgr1
= (s
->cfgr1
& value
& FIREWALL_DISABLE_CFGR1
) |
153 (value
& ACTIVABLE_BITS_CFGR1
);
155 case SYSCFG_EXTICR1
...SYSCFG_EXTICR4
:
156 s
->exticr
[(addr
- SYSCFG_EXTICR1
) / 4] =
157 (value
& ACTIVABLE_BITS_EXTICR
);
160 qemu_log_mask(LOG_UNIMP
,
161 "%s: Erasing SRAM2 isn't supported\n",
164 * only non reserved bits are :
165 * bit 0 (write-protected by a passkey), bit 1 (meant to be read)
166 * so it serves no purpose yet to add :
167 * s->scsr = value & 0x3;
171 qemu_log_mask(LOG_UNIMP
,
172 "%s: Functions in CFGRx aren't supported\n",
174 /* bit 8 (SRAM2 PEF) is cleared by software by writing a '1'.*/
175 /* bits[3:0] (ECC Lock) are set by software, cleared only by reset.*/
176 s
->cfgr2
= (s
->cfgr2
| (value
& ECC_LOCK_CFGR2
)) &
177 ~(value
& SRAM2_PARITY_ERROR_FLAG_CFGR2
);
180 qemu_log_mask(LOG_UNIMP
,
181 "%s: Write protecting SRAM2 isn't supported\n",
183 /* These bits are set by software and cleared only by reset.*/
187 qemu_log_mask(LOG_UNIMP
,
188 "%s: Erasing SRAM2 isn't supported\n",
190 s
->skr
= value
& ACTIVABLE_BITS_SKR
;
193 qemu_log_mask(LOG_UNIMP
,
194 "%s: Write protecting SRAM2 isn't supported\n",
196 /* These bits are set by software and cleared only by reset.*/
200 qemu_log_mask(LOG_GUEST_ERROR
,
201 "%s: Bad offset 0x%" HWADDR_PRIx
"\n", __func__
, addr
);
205 static const MemoryRegionOps stm32l4x5_syscfg_ops
= {
206 .read
= stm32l4x5_syscfg_read
,
207 .write
= stm32l4x5_syscfg_write
,
208 .endianness
= DEVICE_NATIVE_ENDIAN
,
209 .impl
.min_access_size
= 4,
210 .impl
.max_access_size
= 4,
211 .impl
.unaligned
= false,
212 .valid
.min_access_size
= 4,
213 .valid
.max_access_size
= 4,
214 .valid
.unaligned
= false,
217 static void stm32l4x5_syscfg_init(Object
*obj
)
219 Stm32l4x5SyscfgState
*s
= STM32L4X5_SYSCFG(obj
);
221 memory_region_init_io(&s
->mmio
, obj
, &stm32l4x5_syscfg_ops
, s
,
222 TYPE_STM32L4X5_SYSCFG
, 0x400);
223 sysbus_init_mmio(SYS_BUS_DEVICE(obj
), &s
->mmio
);
225 qdev_init_gpio_in(DEVICE(obj
), stm32l4x5_syscfg_set_irq
,
226 GPIO_NUM_PINS
* NUM_GPIOS
);
227 qdev_init_gpio_out(DEVICE(obj
), s
->gpio_out
, GPIO_NUM_PINS
);
230 static const VMStateDescription vmstate_stm32l4x5_syscfg
= {
231 .name
= TYPE_STM32L4X5_SYSCFG
,
233 .minimum_version_id
= 1,
234 .fields
= (VMStateField
[]) {
235 VMSTATE_UINT32(memrmp
, Stm32l4x5SyscfgState
),
236 VMSTATE_UINT32(cfgr1
, Stm32l4x5SyscfgState
),
237 VMSTATE_UINT32_ARRAY(exticr
, Stm32l4x5SyscfgState
,
239 VMSTATE_UINT32(scsr
, Stm32l4x5SyscfgState
),
240 VMSTATE_UINT32(cfgr2
, Stm32l4x5SyscfgState
),
241 VMSTATE_UINT32(swpr
, Stm32l4x5SyscfgState
),
242 VMSTATE_UINT32(skr
, Stm32l4x5SyscfgState
),
243 VMSTATE_UINT32(swpr2
, Stm32l4x5SyscfgState
),
244 VMSTATE_END_OF_LIST()
248 static void stm32l4x5_syscfg_class_init(ObjectClass
*klass
, void *data
)
250 DeviceClass
*dc
= DEVICE_CLASS(klass
);
251 ResettableClass
*rc
= RESETTABLE_CLASS(klass
);
253 dc
->vmsd
= &vmstate_stm32l4x5_syscfg
;
254 rc
->phases
.hold
= stm32l4x5_syscfg_hold_reset
;
257 static const TypeInfo stm32l4x5_syscfg_info
[] = {
259 .name
= TYPE_STM32L4X5_SYSCFG
,
260 .parent
= TYPE_SYS_BUS_DEVICE
,
261 .instance_size
= sizeof(Stm32l4x5SyscfgState
),
262 .instance_init
= stm32l4x5_syscfg_init
,
263 .class_init
= stm32l4x5_syscfg_class_init
,
267 DEFINE_TYPES(stm32l4x5_syscfg_info
)