1 /*
2 * Copyright (c) 2021 Weidmueller Interface GmbH & Co. KG
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #include <zephyr/arch/cpu.h>
7 #include <zephyr/device.h>
8 #include <zephyr/devicetree.h>
9 #include <zephyr/sys/sys_io.h>
10 #include <zephyr/sys/util.h>
11
12 #include <cmsis_core.h>
13 #include <zephyr/arch/arm/mmu/arm_mmu.h>
14 #include "soc.h"
15
16 /* System Level Control Registers (SLCR) */
17 #define SLCR_UNLOCK 0x0008
18 #define SLCR_UNLOCK_KEY 0xdf0d
19 #define AXI_GPIO_MMU_ENTRY(id)\
20 MMU_REGION_FLAT_ENTRY("axigpio",\
21 DT_REG_ADDR(id),\
22 DT_REG_SIZE(id),\
23 MT_DEVICE | MATTR_SHARED | MPERM_R | MPERM_W),
24
25 static const struct arm_mmu_region mmu_regions[] = {
26
27 MMU_REGION_FLAT_ENTRY("vectors",
28 0x00000000,
29 0x1000,
30 MT_STRONGLY_ORDERED | MPERM_R | MPERM_X),
31 MMU_REGION_FLAT_ENTRY("mpcore",
32 0xF8F00000,
33 0x2000,
34 MT_STRONGLY_ORDERED | MPERM_R | MPERM_W),
35 MMU_REGION_FLAT_ENTRY("ocm",
36 DT_REG_ADDR(DT_CHOSEN(zephyr_ocm)),
37 DT_REG_SIZE(DT_CHOSEN(zephyr_ocm)),
38 MT_STRONGLY_ORDERED | MPERM_R | MPERM_W),
39 /* ARM Arch timer, GIC are covered by the MPCore mapping */
40
41 /* GEMs */
42 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gem0))
43 MMU_REGION_FLAT_ENTRY("gem0",
44 DT_REG_ADDR(DT_NODELABEL(gem0)),
45 DT_REG_SIZE(DT_NODELABEL(gem0)),
46 MT_DEVICE | MATTR_SHARED | MPERM_R | MPERM_W),
47 #endif
48 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(gem1))
49 MMU_REGION_FLAT_ENTRY("gem1",
50 DT_REG_ADDR(DT_NODELABEL(gem1)),
51 DT_REG_SIZE(DT_NODELABEL(gem1)),
52 MT_DEVICE | MATTR_SHARED | MPERM_R | MPERM_W),
53 #endif
54
55 DT_FOREACH_STATUS_OKAY(xlnx_xps_gpio_1_00_a, AXI_GPIO_MMU_ENTRY)
56
57 };
58
59 const struct arm_mmu_config mmu_config = {
60 .num_regions = ARRAY_SIZE(mmu_regions),
61 .mmu_regions = mmu_regions,
62 };
63
64 /* Platform-specific early initialization */
65
soc_reset_hook(void)66 void soc_reset_hook(void)
67 {
68 /*
69 * When coming out of u-boot rather than downloading the Zephyr binary
70 * via JTAG, a few things modified by u-boot have to be re-set to a
71 * suitable default value for Zephyr to run, namely:
72 *
73 * - u-boot places the exception vectors somewhere in RAM and then
74 * lets the VBAR register point to them. Zephyr uses the default
75 * vector table location at address zero (and maybe at some later
76 * time alternatively the HIVECS position). If VBAR isn't reset
77 * to zero, the system crashes during the first context switch when
78 * SVC is invoked.
79 * - u-boot sets the following bits in the SCTLR register:
80 * - [I] ICache enable
81 * - [C] DCache enable
82 * - [Z] Branch prediction enable
83 * - [A] Enforce strict alignment enable
84 * [I] and [C] will be enabled during the MMU init -> disable them
85 * until then. [Z] is probably not harmful. [A] will cause a crash
86 * as early as z_mem_manage_init when an unaligned access is performed
87 * -> clear [A].
88 */
89
90 uint32_t vbar = 0;
91
92 __set_VBAR(vbar);
93
94 uint32_t sctlr = __get_SCTLR();
95
96 sctlr &= ~SCTLR_I_Msk;
97 sctlr &= ~SCTLR_C_Msk;
98 sctlr &= ~SCTLR_A_Msk;
99 __set_SCTLR(sctlr);
100
101 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(slcr))
102 mm_reg_t addr = DT_REG_ADDR(DT_NODELABEL(slcr));
103
104 /* Unlock System Level Control Registers (SLCR) */
105 sys_write32(SLCR_UNLOCK_KEY, addr + SLCR_UNLOCK);
106 #endif
107 }
108