1 /*
2 * Copyright (c) 2017 Google Inc. All rights reserved
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 #include <debug.h>
25 #include <dev/interrupt/arm_gic.h>
26 #include <dev/timer/arm_generic.h>
27 #include <imx-regs.h>
28 #include <kernel/vm.h>
29 #include <lk/init.h>
30 #include <string.h>
31 #ifdef WITH_TZASC
32 #include <platform/tzasc.h>
33 #include <tzasc_regions.h>
34 #endif
35
36 #define ARM_GENERIC_TIMER_INT_CNTV 27
37 #define ARM_GENERIC_TIMER_INT_CNTPS 29
38 #define ARM_GENERIC_TIMER_INT_CNTP 30
39
40 #define ARM_GENERIC_TIMER_INT_SELECTED(timer) ARM_GENERIC_TIMER_INT_##timer
41 #define XARM_GENERIC_TIMER_INT_SELECTED(timer) \
42 ARM_GENERIC_TIMER_INT_SELECTED(timer)
43 #define ARM_GENERIC_TIMER_INT \
44 XARM_GENERIC_TIMER_INT_SELECTED(TIMER_ARM_GENERIC_SELECTED)
45
46 /* initial memory mappings. parsed by start.S */
47 struct mmu_initial_mapping mmu_initial_mappings[] = {
48 /* Mark next entry as dynamic as it might be updated
49 by platform_reset code to specify actual size and
50 location of RAM to use */
51 {.phys = MEMBASE + KERNEL_LOAD_OFFSET,
52 .virt = KERNEL_BASE + KERNEL_LOAD_OFFSET,
53 .size = MEMSIZE,
54 .flags = MMU_INITIAL_MAPPING_FLAG_DYNAMIC,
55 .name = "ram"},
56 {.phys = SOC_REGS_PHY,
57 .virt = SOC_REGS_VIRT,
58 .size = SOC_REGS_SIZE,
59 .flags = MMU_INITIAL_MAPPING_FLAG_DEVICE,
60 .name = "soc"},
61 /* null entry to terminate the list */
62 {0}};
63
64 static pmm_arena_t ram_arena = {.name = "ram",
65 .base = MEMBASE + KERNEL_LOAD_OFFSET,
66 .size = MEMSIZE,
67 .flags = PMM_ARENA_FLAG_KMAP};
68
platform_init_mmu_mappings(void)69 void platform_init_mmu_mappings(void) {
70 /* go through mmu_initial_mapping to find dynamic entry
71 * matching ram_arena (by name) and adjust it.
72 */
73 struct mmu_initial_mapping* m = mmu_initial_mappings;
74 for (uint i = 0; i < countof(mmu_initial_mappings); i++, m++) {
75 if (!(m->flags & MMU_INITIAL_MAPPING_FLAG_DYNAMIC))
76 continue;
77
78 if (strcmp(m->name, ram_arena.name) == 0) {
79 /* update ram_arena */
80 ram_arena.base = m->phys;
81 ram_arena.size = m->size;
82 ram_arena.flags = PMM_ARENA_FLAG_KMAP;
83
84 break;
85 }
86 }
87 pmm_add_arena(&ram_arena);
88 }
89
generic_arm64_map_regs(const char * name,vaddr_t vaddr,paddr_t paddr,size_t size)90 static void generic_arm64_map_regs(const char* name,
91 vaddr_t vaddr,
92 paddr_t paddr,
93 size_t size) {
94 status_t ret;
95 void* vaddrp = (void*)vaddr;
96
97 ret = vmm_alloc_physical(
98 vmm_get_kernel_aspace(), name, size, &vaddrp, 0, paddr,
99 VMM_FLAG_VALLOC_SPECIFIC,
100 ARCH_MMU_FLAG_UNCACHED_DEVICE | ARCH_MMU_FLAG_PERM_NO_EXECUTE);
101 if (ret) {
102 dprintf(CRITICAL, "%s: failed %d name=%s\n", __func__, ret, name);
103 }
104 }
105
platform_after_vm_init(uint level)106 static void platform_after_vm_init(uint level) {
107 generic_arm64_map_regs("gic", GIC_BASE_VIRT, GIC_BASE_PHY, GIC_REG_SIZE);
108
109 /* Initialize the interrupt controller. */
110 arm_gic_init();
111
112 /* Initialize the timer block. */
113 arm_generic_timer_init(ARM_GENERIC_TIMER_INT, 0);
114
115 /* SOC is mapped in initial mapping */
116
117 #ifdef WITH_TZASC
118 /* Initialize TZASC. */
119 /* TZASC registers are mapped by initial mapping */
120 initial_tzasc(tzasc_regions, countof(tzasc_regions));
121 #endif
122 }
123
124 LK_INIT_HOOK(platform_after_vm, platform_after_vm_init, LK_INIT_LEVEL_VM + 1);
125
126 #if WITH_VIRT_TIMER_INIT
127 extern void virt_timer_init(void);
128
129 /* Reset CNTVOFF register to be able to use virt arch timer */
platform_per_cpu_virt_timer_init(uint level)130 static void platform_per_cpu_virt_timer_init(uint level) {
131 virt_timer_init();
132 }
133
134 LK_INIT_HOOK_FLAGS(platform_per_cpu_virt_timer,
135 platform_per_cpu_virt_timer_init,
136 LK_INIT_LEVEL_PLATFORM_EARLY,
137 LK_INIT_FLAG_ALL_CPUS);
138
139 #endif
140