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