blob: cd3693892a0d7ecdc6413d46e984cc5334d88ec0 [file] [log] [blame]
Andrii Anisov355d1e42020-08-06 12:42:47 +03001// SPDX-License-Identifier: GPL-2.0
2/*
3 * (C) 2013
4 * David Feng <fenghua@phytium.com.cn>
5 * Sharma Bhupesh <bhupesh.sharma@freescale.com>
6 *
7 * (C) 2020 EPAM Systems Inc
8 */
9
10#include <common.h>
11#include <cpu_func.h>
12#include <dm.h>
13#include <errno.h>
14#include <malloc.h>
15
16#include <asm/io.h>
17#include <asm/armv8/mmu.h>
18#include <asm/xen.h>
19#include <asm/xen/hypercall.h>
Peng Fan8162f8f2020-08-06 12:42:50 +030020#include <asm/xen/system.h>
Andrii Anisov355d1e42020-08-06 12:42:47 +030021
22#include <linux/compiler.h>
23
Oleksandr Andrushchenko3cc1dcc2020-08-06 12:42:54 +030024#include <xen/gnttab.h>
Peng Fan8162f8f2020-08-06 12:42:50 +030025#include <xen/hvm.h>
26
Andrii Anisov355d1e42020-08-06 12:42:47 +030027DECLARE_GLOBAL_DATA_PTR;
28
29int board_init(void)
30{
31 return 0;
32}
33
34/*
35 * Use fdt provided by Xen: according to
36 * https://www.kernel.org/doc/Documentation/arm64/booting.txt
37 * x0 is the physical address of the device tree blob (dtb) in system RAM.
38 * This is stored in rom_pointer during low level init.
39 */
40void *board_fdt_blob_setup(void)
41{
42 if (fdt_magic(rom_pointer[0]) != FDT_MAGIC)
43 return NULL;
44 return (void *)rom_pointer[0];
45}
46
47#define MAX_MEM_MAP_REGIONS 5
48static struct mm_region xen_mem_map[MAX_MEM_MAP_REGIONS];
49struct mm_region *mem_map = xen_mem_map;
50
51static int get_next_memory_node(const void *blob, int mem)
52{
53 do {
54 mem = fdt_node_offset_by_prop_value(blob, mem,
55 "device_type", "memory", 7);
56 } while (!fdtdec_get_is_enabled(blob, mem));
57
58 return mem;
59}
60
61static int setup_mem_map(void)
62{
Peng Fan8162f8f2020-08-06 12:42:50 +030063 int i = 0, ret, mem, reg = 0;
Andrii Anisov355d1e42020-08-06 12:42:47 +030064 struct fdt_resource res;
65 const void *blob = gd->fdt_blob;
Peng Fan8162f8f2020-08-06 12:42:50 +030066 u64 gfn;
Oleksandr Andrushchenko3cc1dcc2020-08-06 12:42:54 +030067 phys_addr_t gnttab_base;
68 phys_size_t gnttab_sz;
Peng Fan8162f8f2020-08-06 12:42:50 +030069
70 /*
71 * Add "magic" region which is used by Xen to provide some essentials
Oleksandr Andrushchenko4b728452020-08-06 12:42:53 +030072 * for the guest: we need console and xenstore.
Peng Fan8162f8f2020-08-06 12:42:50 +030073 */
74 ret = hvm_get_parameter_maintain_dcache(HVM_PARAM_CONSOLE_PFN, &gfn);
75 if (ret < 0) {
76 printf("%s: Can't get HVM_PARAM_CONSOLE_PFN, ret %d\n",
77 __func__, ret);
78 return -EINVAL;
79 }
80
81 xen_mem_map[i].virt = PFN_PHYS(gfn);
82 xen_mem_map[i].phys = PFN_PHYS(gfn);
83 xen_mem_map[i].size = PAGE_SIZE;
84 xen_mem_map[i].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) |
85 PTE_BLOCK_INNER_SHARE);
86 i++;
Andrii Anisov355d1e42020-08-06 12:42:47 +030087
Oleksandr Andrushchenko4b728452020-08-06 12:42:53 +030088 ret = hvm_get_parameter_maintain_dcache(HVM_PARAM_STORE_PFN, &gfn);
89 if (ret < 0) {
90 printf("%s: Can't get HVM_PARAM_STORE_PFN, ret %d\n",
91 __func__, ret);
92 return -EINVAL;
93 }
94
95 xen_mem_map[i].virt = PFN_PHYS(gfn);
96 xen_mem_map[i].phys = PFN_PHYS(gfn);
97 xen_mem_map[i].size = PAGE_SIZE;
98 xen_mem_map[i].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) |
99 PTE_BLOCK_INNER_SHARE);
100 i++;
101
Oleksandr Andrushchenko3cc1dcc2020-08-06 12:42:54 +0300102 /* Get Xen's suggested physical page assignments for the grant table. */
103 get_gnttab_base(&gnttab_base, &gnttab_sz);
104
105 xen_mem_map[i].virt = gnttab_base;
106 xen_mem_map[i].phys = gnttab_base;
107 xen_mem_map[i].size = gnttab_sz;
108 xen_mem_map[i].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) |
109 PTE_BLOCK_INNER_SHARE);
110 i++;
111
Andrii Anisov355d1e42020-08-06 12:42:47 +0300112 mem = get_next_memory_node(blob, -1);
113 if (mem < 0) {
114 printf("%s: Missing /memory node\n", __func__);
115 return -EINVAL;
116 }
117
Peng Fan8162f8f2020-08-06 12:42:50 +0300118 for (; i < MAX_MEM_MAP_REGIONS; i++) {
Andrii Anisov355d1e42020-08-06 12:42:47 +0300119 ret = fdt_get_resource(blob, mem, "reg", reg++, &res);
120 if (ret == -FDT_ERR_NOTFOUND) {
121 reg = 0;
122 mem = get_next_memory_node(blob, mem);
123 if (mem == -FDT_ERR_NOTFOUND)
124 break;
125
126 ret = fdt_get_resource(blob, mem, "reg", reg++, &res);
127 if (ret == -FDT_ERR_NOTFOUND)
128 break;
129 }
130 if (ret != 0) {
131 printf("No reg property for memory node\n");
132 return -EINVAL;
133 }
134
135 xen_mem_map[i].virt = (phys_addr_t)res.start;
136 xen_mem_map[i].phys = (phys_addr_t)res.start;
137 xen_mem_map[i].size = (phys_size_t)(res.end - res.start + 1);
138 xen_mem_map[i].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) |
139 PTE_BLOCK_INNER_SHARE);
140 }
141 return 0;
142}
143
144void enable_caches(void)
145{
146 /* Re-setup the memory map as BSS gets cleared after relocation. */
147 setup_mem_map();
148 icache_enable();
149 dcache_enable();
150}
151
152/* Read memory settings from the Xen provided device tree. */
153int dram_init(void)
154{
155 int ret;
156
157 ret = fdtdec_setup_mem_size_base();
158 if (ret < 0)
159 return ret;
160 /* Setup memory map, so MMU page table size can be estimated. */
161 return setup_mem_map();
162}
163
164int dram_init_banksize(void)
165{
166 return fdtdec_setup_memory_banksize();
167}
168
169/*
170 * Board specific reset that is system reset.
171 */
172void reset_cpu(ulong addr)
173{
174}
175
176int ft_system_setup(void *blob, struct bd_info *bd)
177{
178 return 0;
179}
180
181int ft_board_setup(void *blob, struct bd_info *bd)
182{
183 return 0;
184}
185
186int board_early_init_f(void)
187{
188 return 0;
189}
190
191int print_cpuinfo(void)
192{
193 printf("Xen virtual CPU\n");
194 return 0;
195}
196