]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
84c7204b MS |
2 | /* |
3 | * (C) Copyright 2014 - 2015 Xilinx, Inc. | |
174d7284 | 4 | * Michal Simek <michal.simek@amd.com> |
84c7204b MS |
5 | */ |
6 | ||
d678a59d | 7 | #include <common.h> |
691d719d | 8 | #include <init.h> |
049f8d6f | 9 | #include <time.h> |
84c7204b MS |
10 | #include <asm/arch/hardware.h> |
11 | #include <asm/arch/sys_proto.h> | |
96519f31 | 12 | #include <asm/armv8/mmu.h> |
90526e9f | 13 | #include <asm/cache.h> |
401d1c4f | 14 | #include <asm/global_data.h> |
84c7204b | 15 | #include <asm/io.h> |
009ab7b9 | 16 | #include <zynqmp_firmware.h> |
6184858b | 17 | #include <asm/cache.h> |
a890a53a | 18 | #include <dm/platdata.h> |
84c7204b MS |
19 | |
20 | #define ZYNQ_SILICON_VER_MASK 0xF000 | |
21 | #define ZYNQ_SILICON_VER_SHIFT 12 | |
22 | ||
23 | DECLARE_GLOBAL_DATA_PTR; | |
24 | ||
0678941a NJ |
25 | /* |
26 | * Number of filled static entries and also the first empty | |
27 | * slot in zynqmp_mem_map. | |
28 | */ | |
29 | #define ZYNQMP_MEM_MAP_USED 4 | |
30 | ||
3b644a3c | 31 | #if !defined(CONFIG_ZYNQMP_NO_DDR) |
0678941a NJ |
32 | #define DRAM_BANKS CONFIG_NR_DRAM_BANKS |
33 | #else | |
34 | #define DRAM_BANKS 0 | |
3b644a3c | 35 | #endif |
0678941a NJ |
36 | |
37 | #if defined(CONFIG_DEFINE_TCM_OCM_MMAP) | |
38 | #define TCM_MAP 1 | |
39 | #else | |
40 | #define TCM_MAP 0 | |
41 | #endif | |
42 | ||
43 | /* +1 is end of list which needs to be empty */ | |
44 | #define ZYNQMP_MEM_MAP_MAX (ZYNQMP_MEM_MAP_USED + DRAM_BANKS + TCM_MAP + 1) | |
45 | ||
46 | static struct mm_region zynqmp_mem_map[ZYNQMP_MEM_MAP_MAX] = { | |
3b644a3c | 47 | { |
cd4b0c5f YS |
48 | .virt = 0x80000000UL, |
49 | .phys = 0x80000000UL, | |
96519f31 AG |
50 | .size = 0x70000000UL, |
51 | .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | | |
52 | PTE_BLOCK_NON_SHARE | | |
53 | PTE_BLOCK_PXN | PTE_BLOCK_UXN | |
0678941a | 54 | }, { |
cd4b0c5f YS |
55 | .virt = 0xf8000000UL, |
56 | .phys = 0xf8000000UL, | |
96519f31 AG |
57 | .size = 0x07e00000UL, |
58 | .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | | |
59 | PTE_BLOCK_NON_SHARE | | |
60 | PTE_BLOCK_PXN | PTE_BLOCK_UXN | |
96519f31 | 61 | }, { |
cd4b0c5f YS |
62 | .virt = 0x400000000UL, |
63 | .phys = 0x400000000UL, | |
501fbc67 | 64 | .size = 0x400000000UL, |
96519f31 AG |
65 | .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | |
66 | PTE_BLOCK_NON_SHARE | | |
67 | PTE_BLOCK_PXN | PTE_BLOCK_UXN | |
0678941a | 68 | }, { |
501fbc67 AH |
69 | .virt = 0x1000000000UL, |
70 | .phys = 0x1000000000UL, | |
71 | .size = 0xf000000000UL, | |
96519f31 AG |
72 | .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | |
73 | PTE_BLOCK_NON_SHARE | | |
74 | PTE_BLOCK_PXN | PTE_BLOCK_UXN | |
96519f31 AG |
75 | } |
76 | }; | |
0678941a NJ |
77 | |
78 | void mem_map_fill(void) | |
79 | { | |
80 | int banks = ZYNQMP_MEM_MAP_USED; | |
81 | ||
82 | #if defined(CONFIG_DEFINE_TCM_OCM_MMAP) | |
83 | zynqmp_mem_map[banks].virt = 0xffe00000UL; | |
84 | zynqmp_mem_map[banks].phys = 0xffe00000UL; | |
85 | zynqmp_mem_map[banks].size = 0x00200000UL; | |
86 | zynqmp_mem_map[banks].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | | |
87 | PTE_BLOCK_INNER_SHARE; | |
88 | banks = banks + 1; | |
89 | #endif | |
90 | ||
91 | #if !defined(CONFIG_ZYNQMP_NO_DDR) | |
92 | for (int i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { | |
93 | /* Zero size means no more DDR that's this is end */ | |
94 | if (!gd->bd->bi_dram[i].size) | |
95 | break; | |
96 | ||
97 | zynqmp_mem_map[banks].virt = gd->bd->bi_dram[i].start; | |
98 | zynqmp_mem_map[banks].phys = gd->bd->bi_dram[i].start; | |
99 | zynqmp_mem_map[banks].size = gd->bd->bi_dram[i].size; | |
100 | zynqmp_mem_map[banks].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | | |
101 | PTE_BLOCK_INNER_SHARE; | |
102 | banks = banks + 1; | |
103 | } | |
104 | #endif | |
105 | } | |
106 | ||
96519f31 AG |
107 | struct mm_region *mem_map = zynqmp_mem_map; |
108 | ||
9c152edd MS |
109 | u64 get_page_table_size(void) |
110 | { | |
111 | return 0x14000; | |
112 | } | |
113 | ||
5860bc16 SDPP |
114 | #if defined(CONFIG_SYS_MEM_RSVD_FOR_MMU) || defined(CONFIG_DEFINE_TCM_OCM_MMAP) |
115 | void tcm_init(u8 mode) | |
e042d36e | 116 | { |
12ad2994 SDPP |
117 | puts("WARNING: Initializing TCM overwrites TCM content\n"); |
118 | initialize_tcm(mode); | |
e042d36e | 119 | memset((void *)ZYNQMP_TCM_BASE_ADDR, 0, ZYNQMP_TCM_SIZE); |
12ad2994 | 120 | } |
5860bc16 | 121 | #endif |
12ad2994 | 122 | |
5860bc16 | 123 | #ifdef CONFIG_SYS_MEM_RSVD_FOR_MMU |
6184858b | 124 | int arm_reserve_mmu(void) |
12ad2994 SDPP |
125 | { |
126 | tcm_init(TCM_LOCK); | |
e042d36e SDPP |
127 | gd->arch.tlb_size = PGTABLE_SIZE; |
128 | gd->arch.tlb_addr = ZYNQMP_TCM_BASE_ADDR; | |
129 | ||
130 | return 0; | |
131 | } | |
132 | #endif | |
133 | ||
0785dfd8 MS |
134 | static unsigned int zynqmp_get_silicon_version_secure(void) |
135 | { | |
136 | u32 ver; | |
137 | ||
138 | ver = readl(&csu_base->version); | |
139 | ver &= ZYNQMP_SILICON_VER_MASK; | |
140 | ver >>= ZYNQMP_SILICON_VER_SHIFT; | |
141 | ||
142 | return ver; | |
143 | } | |
144 | ||
84c7204b MS |
145 | unsigned int zynqmp_get_silicon_version(void) |
146 | { | |
0785dfd8 MS |
147 | if (current_el() == 3) |
148 | return zynqmp_get_silicon_version_secure(); | |
149 | ||
84c7204b MS |
150 | gd->cpu_clk = get_tbclk(); |
151 | ||
152 | switch (gd->cpu_clk) { | |
153 | case 50000000: | |
154 | return ZYNQMP_CSU_VERSION_QEMU; | |
155 | } | |
156 | ||
be6f6af1 | 157 | return ZYNQMP_CSU_VERSION_SILICON; |
84c7204b | 158 | } |
e0752bc1 | 159 | |
cb186e74 | 160 | static int zynqmp_mmio_rawwrite(const u32 address, |
e0752bc1 SDPP |
161 | const u32 mask, |
162 | const u32 value) | |
163 | { | |
164 | u32 data; | |
165 | u32 value_local = value; | |
e3c26b8d MS |
166 | int ret; |
167 | ||
168 | ret = zynqmp_mmio_read(address, &data); | |
169 | if (ret) | |
170 | return ret; | |
e0752bc1 | 171 | |
e0752bc1 SDPP |
172 | data &= ~mask; |
173 | value_local &= mask; | |
174 | value_local |= data; | |
175 | writel(value_local, (ulong)address); | |
176 | return 0; | |
177 | } | |
178 | ||
cb186e74 | 179 | static int zynqmp_mmio_rawread(const u32 address, u32 *value) |
e0752bc1 SDPP |
180 | { |
181 | *value = readl((ulong)address); | |
182 | return 0; | |
183 | } | |
cb186e74 SDPP |
184 | |
185 | int zynqmp_mmio_write(const u32 address, | |
186 | const u32 mask, | |
187 | const u32 value) | |
188 | { | |
189 | if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) | |
190 | return zynqmp_mmio_rawwrite(address, mask, value); | |
866225f3 | 191 | #if defined(CONFIG_ZYNQMP_FIRMWARE) |
549d684d | 192 | else |
40361951 MS |
193 | return xilinx_pm_request(PM_MMIO_WRITE, address, mask, |
194 | value, 0, NULL); | |
866225f3 | 195 | #endif |
cb186e74 SDPP |
196 | |
197 | return -EINVAL; | |
198 | } | |
199 | ||
200 | int zynqmp_mmio_read(const u32 address, u32 *value) | |
201 | { | |
866225f3 | 202 | u32 ret = -EINVAL; |
cb186e74 SDPP |
203 | |
204 | if (!value) | |
866225f3 | 205 | return ret; |
cb186e74 SDPP |
206 | |
207 | if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) { | |
208 | ret = zynqmp_mmio_rawread(address, value); | |
866225f3 MS |
209 | } |
210 | #if defined(CONFIG_ZYNQMP_FIRMWARE) | |
211 | else { | |
212 | u32 ret_payload[PAYLOAD_ARG_CNT]; | |
213 | ||
40361951 MS |
214 | ret = xilinx_pm_request(PM_MMIO_READ, address, 0, 0, |
215 | 0, ret_payload); | |
cb186e74 SDPP |
216 | *value = ret_payload[1]; |
217 | } | |
866225f3 | 218 | #endif |
cb186e74 SDPP |
219 | |
220 | return ret; | |
221 | } | |
a890a53a KR |
222 | |
223 | U_BOOT_DRVINFO(soc_xilinx_zynqmp) = { | |
224 | .name = "soc_xilinx_zynqmp", | |
225 | }; |