Commit 4d377539a1190e838eae5d8b8a794dde0696d572
1 parent
64f857aefa
Exists in
smarc_8mm-imx_v2019.04_4.19.35_1.1.0
and in
1 other branch
MLK-22866 imx8: Remove the optee shared memory from DDR banks
Optee has 4MB shared memory at its top space which was assigned to non-secure OS partition in ATF. By default this memory is added to u-boot DDR banks and will pass to kernel. This means kernel has possibility to allocate from this memory for system usage. At same time this memory is used by optee and mem-remapped by optee kernel driver. So it is possible to have conflict and cause kernel crash. Fix the issue by removing the shared memory from u-boot DDR banks. Then it is not visible for both u-boot and kernel and can avoid such issue. Signed-off-by: Ye Li <ye.li@nxp.com> Reviewed-by: Anson Huang <Anson.Huang@nxp.com> (cherry picked from commit 164279c42de0d058b7abe198cc154ee683087e6a)
Showing 1 changed file with 22 additions and 1 deletions Inline Diff
arch/arm/mach-imx/imx8/cpu.c
1 | // SPDX-License-Identifier: GPL-2.0+ | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | 2 | /* |
3 | * Copyright 2017-2019 NXP | 3 | * Copyright 2017-2019 NXP |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <common.h> | 6 | #include <common.h> |
7 | #include <clk.h> | 7 | #include <clk.h> |
8 | #include <cpu.h> | 8 | #include <cpu.h> |
9 | #include <dm.h> | 9 | #include <dm.h> |
10 | #include <dm/device-internal.h> | 10 | #include <dm/device-internal.h> |
11 | #include <dm/lists.h> | 11 | #include <dm/lists.h> |
12 | #include <dm/uclass.h> | 12 | #include <dm/uclass.h> |
13 | #include <errno.h> | 13 | #include <errno.h> |
14 | #include <asm/arch/sci/sci.h> | 14 | #include <asm/arch/sci/sci.h> |
15 | #include <asm/arch/clock.h> | 15 | #include <asm/arch/clock.h> |
16 | #include <power-domain.h> | 16 | #include <power-domain.h> |
17 | #include <dm/device.h> | 17 | #include <dm/device.h> |
18 | #include <dm/uclass-internal.h> | 18 | #include <dm/uclass-internal.h> |
19 | #include <thermal.h> | 19 | #include <thermal.h> |
20 | #include <elf.h> | 20 | #include <elf.h> |
21 | #include <asm/arch/sid.h> | 21 | #include <asm/arch/sid.h> |
22 | #include <asm/arch/sys_proto.h> | 22 | #include <asm/arch/sys_proto.h> |
23 | #include <asm/arch-imx/cpu.h> | 23 | #include <asm/arch-imx/cpu.h> |
24 | #include <asm/armv8/cpu.h> | 24 | #include <asm/armv8/cpu.h> |
25 | #include <asm/armv8/mmu.h> | 25 | #include <asm/armv8/mmu.h> |
26 | #include <asm/setup.h> | 26 | #include <asm/setup.h> |
27 | #include <asm/mach-imx/boot_mode.h> | 27 | #include <asm/mach-imx/boot_mode.h> |
28 | #include <asm/arch/video_common.h> | 28 | #include <asm/arch/video_common.h> |
29 | #include <linux/libfdt.h> | 29 | #include <linux/libfdt.h> |
30 | #include <fdt_support.h> | 30 | #include <fdt_support.h> |
31 | #include <fdtdec.h> | 31 | #include <fdtdec.h> |
32 | #include <generated/version_autogenerated.h> | 32 | #include <generated/version_autogenerated.h> |
33 | #include <asm/mach-imx/imx_vservice.h> | 33 | #include <asm/mach-imx/imx_vservice.h> |
34 | #include <asm/arch/power-domain.h> | 34 | #include <asm/arch/power-domain.h> |
35 | #include <spl.h> | 35 | #include <spl.h> |
36 | #include <asm/arch/lpcg.h> | 36 | #include <asm/arch/lpcg.h> |
37 | 37 | ||
38 | DECLARE_GLOBAL_DATA_PTR; | 38 | DECLARE_GLOBAL_DATA_PTR; |
39 | 39 | ||
40 | struct edma_ch_map { | 40 | struct edma_ch_map { |
41 | sc_rsrc_t ch_start_rsrc; | 41 | sc_rsrc_t ch_start_rsrc; |
42 | u32 ch_start_regs; | 42 | u32 ch_start_regs; |
43 | u32 ch_num; | 43 | u32 ch_num; |
44 | const char* node_path; | 44 | const char* node_path; |
45 | }; | 45 | }; |
46 | 46 | ||
47 | #define BT_PASSOVER_TAG 0x504F | 47 | #define BT_PASSOVER_TAG 0x504F |
48 | struct pass_over_info_t *get_pass_over_info(void) | 48 | struct pass_over_info_t *get_pass_over_info(void) |
49 | { | 49 | { |
50 | struct pass_over_info_t *p = | 50 | struct pass_over_info_t *p = |
51 | (struct pass_over_info_t *)PASS_OVER_INFO_ADDR; | 51 | (struct pass_over_info_t *)PASS_OVER_INFO_ADDR; |
52 | 52 | ||
53 | if (p->barker != BT_PASSOVER_TAG || | 53 | if (p->barker != BT_PASSOVER_TAG || |
54 | p->len != sizeof(struct pass_over_info_t)) | 54 | p->len != sizeof(struct pass_over_info_t)) |
55 | return NULL; | 55 | return NULL; |
56 | 56 | ||
57 | return p; | 57 | return p; |
58 | } | 58 | } |
59 | 59 | ||
60 | #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_RECOVER_SPL_DATA_SECTION) | 60 | #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_RECOVER_SPL_DATA_SECTION) |
61 | char __data_save_start[0] __attribute__((section(".__data_save_start"))); | 61 | char __data_save_start[0] __attribute__((section(".__data_save_start"))); |
62 | char __data_save_end[0] __attribute__((section(".__data_save_end"))); | 62 | char __data_save_end[0] __attribute__((section(".__data_save_end"))); |
63 | 63 | ||
64 | u32 cold_reboot_flag = 1; | 64 | u32 cold_reboot_flag = 1; |
65 | 65 | ||
66 | static void save_restore_data(void) | 66 | static void save_restore_data(void) |
67 | { | 67 | { |
68 | u32 data_size = __data_save_end - __data_save_start; | 68 | u32 data_size = __data_save_end - __data_save_start; |
69 | 69 | ||
70 | if (cold_reboot_flag == 1) { | 70 | if (cold_reboot_flag == 1) { |
71 | /* Save data section to data_save section */ | 71 | /* Save data section to data_save section */ |
72 | memcpy(__data_save_start, __data_save_start - data_size, data_size); | 72 | memcpy(__data_save_start, __data_save_start - data_size, data_size); |
73 | } else { | 73 | } else { |
74 | /* Restore the data_save section to data section */ | 74 | /* Restore the data_save section to data section */ |
75 | memcpy(__data_save_start - data_size, __data_save_start, data_size); | 75 | memcpy(__data_save_start - data_size, __data_save_start, data_size); |
76 | } | 76 | } |
77 | cold_reboot_flag++; | 77 | cold_reboot_flag++; |
78 | } | 78 | } |
79 | #endif | 79 | #endif |
80 | 80 | ||
81 | int arch_cpu_init(void) | 81 | int arch_cpu_init(void) |
82 | { | 82 | { |
83 | #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_RECOVER_SPL_DATA_SECTION) | 83 | #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_RECOVER_SPL_DATA_SECTION) |
84 | save_restore_data(); | 84 | save_restore_data(); |
85 | #endif | 85 | #endif |
86 | 86 | ||
87 | return 0; | 87 | return 0; |
88 | } | 88 | } |
89 | 89 | ||
90 | int arch_cpu_init_dm(void) | 90 | int arch_cpu_init_dm(void) |
91 | { | 91 | { |
92 | struct udevice *devp; | 92 | struct udevice *devp; |
93 | int node, ret; | 93 | int node, ret; |
94 | 94 | ||
95 | node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "fsl,imx8-mu"); | 95 | node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "fsl,imx8-mu"); |
96 | 96 | ||
97 | ret = uclass_get_device_by_of_offset(UCLASS_MISC, node, &devp); | 97 | ret = uclass_get_device_by_of_offset(UCLASS_MISC, node, &devp); |
98 | if (ret) { | 98 | if (ret) { |
99 | printf("could not get scu %d\n", ret); | 99 | printf("could not get scu %d\n", ret); |
100 | return ret; | 100 | return ret; |
101 | } | 101 | } |
102 | 102 | ||
103 | struct pass_over_info_t *pass_over; | 103 | struct pass_over_info_t *pass_over; |
104 | 104 | ||
105 | if (is_soc_rev(CHIP_REV_A)) { | 105 | if (is_soc_rev(CHIP_REV_A)) { |
106 | pass_over = get_pass_over_info(); | 106 | pass_over = get_pass_over_info(); |
107 | if (pass_over && pass_over->g_ap_mu == 0) { | 107 | if (pass_over && pass_over->g_ap_mu == 0) { |
108 | /* | 108 | /* |
109 | * When ap_mu is 0, means the U-Boot booted | 109 | * When ap_mu is 0, means the U-Boot booted |
110 | * from first container | 110 | * from first container |
111 | */ | 111 | */ |
112 | sc_misc_boot_status(-1, SC_MISC_BOOT_STATUS_SUCCESS); | 112 | sc_misc_boot_status(-1, SC_MISC_BOOT_STATUS_SUCCESS); |
113 | } | 113 | } |
114 | } | 114 | } |
115 | 115 | ||
116 | #ifdef CONFIG_IMX_SMMU | 116 | #ifdef CONFIG_IMX_SMMU |
117 | int sciErr; | 117 | int sciErr; |
118 | sciErr = sc_pm_set_resource_power_mode(-1, SC_R_SMMU, | 118 | sciErr = sc_pm_set_resource_power_mode(-1, SC_R_SMMU, |
119 | SC_PM_PW_MODE_ON); | 119 | SC_PM_PW_MODE_ON); |
120 | if (sciErr) | 120 | if (sciErr) |
121 | return 0; | 121 | return 0; |
122 | #endif | 122 | #endif |
123 | 123 | ||
124 | return 0; | 124 | return 0; |
125 | } | 125 | } |
126 | 126 | ||
127 | #ifdef CONFIG_IMX_BOOTAUX | 127 | #ifdef CONFIG_IMX_BOOTAUX |
128 | 128 | ||
129 | #ifdef CONFIG_IMX8QM | 129 | #ifdef CONFIG_IMX8QM |
130 | int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data) | 130 | int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data) |
131 | { | 131 | { |
132 | sc_rsrc_t core_rsrc, mu_rsrc; | 132 | sc_rsrc_t core_rsrc, mu_rsrc; |
133 | sc_faddr_t tcml_addr; | 133 | sc_faddr_t tcml_addr; |
134 | u32 tcm_size = SZ_256K; /* TCML + TCMU */ | 134 | u32 tcm_size = SZ_256K; /* TCML + TCMU */ |
135 | ulong addr; | 135 | ulong addr; |
136 | 136 | ||
137 | 137 | ||
138 | switch (core_id) { | 138 | switch (core_id) { |
139 | case 0: | 139 | case 0: |
140 | core_rsrc = SC_R_M4_0_PID0; | 140 | core_rsrc = SC_R_M4_0_PID0; |
141 | tcml_addr = 0x34FE0000; | 141 | tcml_addr = 0x34FE0000; |
142 | mu_rsrc = SC_R_M4_0_MU_1A; | 142 | mu_rsrc = SC_R_M4_0_MU_1A; |
143 | break; | 143 | break; |
144 | case 1: | 144 | case 1: |
145 | core_rsrc = SC_R_M4_1_PID0; | 145 | core_rsrc = SC_R_M4_1_PID0; |
146 | tcml_addr = 0x38FE0000; | 146 | tcml_addr = 0x38FE0000; |
147 | mu_rsrc = SC_R_M4_1_MU_1A; | 147 | mu_rsrc = SC_R_M4_1_MU_1A; |
148 | break; | 148 | break; |
149 | default: | 149 | default: |
150 | printf("Not support this core boot up, ID:%u\n", core_id); | 150 | printf("Not support this core boot up, ID:%u\n", core_id); |
151 | return -EINVAL; | 151 | return -EINVAL; |
152 | } | 152 | } |
153 | 153 | ||
154 | addr = (sc_faddr_t)boot_private_data; | 154 | addr = (sc_faddr_t)boot_private_data; |
155 | 155 | ||
156 | if (addr >= tcml_addr && addr <= tcml_addr + tcm_size) { | 156 | if (addr >= tcml_addr && addr <= tcml_addr + tcm_size) { |
157 | printf("Wrong image address 0x%lx, should not in TCML\n", | 157 | printf("Wrong image address 0x%lx, should not in TCML\n", |
158 | addr); | 158 | addr); |
159 | return -EINVAL; | 159 | return -EINVAL; |
160 | } | 160 | } |
161 | 161 | ||
162 | printf("Power on M4 and MU\n"); | 162 | printf("Power on M4 and MU\n"); |
163 | 163 | ||
164 | if (sc_pm_set_resource_power_mode(-1, core_rsrc, SC_PM_PW_MODE_ON) != SC_ERR_NONE) | 164 | if (sc_pm_set_resource_power_mode(-1, core_rsrc, SC_PM_PW_MODE_ON) != SC_ERR_NONE) |
165 | return -EIO; | 165 | return -EIO; |
166 | 166 | ||
167 | if (sc_pm_set_resource_power_mode(-1, mu_rsrc, SC_PM_PW_MODE_ON) != SC_ERR_NONE) | 167 | if (sc_pm_set_resource_power_mode(-1, mu_rsrc, SC_PM_PW_MODE_ON) != SC_ERR_NONE) |
168 | return -EIO; | 168 | return -EIO; |
169 | 169 | ||
170 | printf("Copy M4 image from 0x%lx to TCML 0x%lx\n", addr, (ulong)tcml_addr); | 170 | printf("Copy M4 image from 0x%lx to TCML 0x%lx\n", addr, (ulong)tcml_addr); |
171 | 171 | ||
172 | if (addr != tcml_addr) | 172 | if (addr != tcml_addr) |
173 | memcpy((void *)tcml_addr, (void *)addr, tcm_size); | 173 | memcpy((void *)tcml_addr, (void *)addr, tcm_size); |
174 | 174 | ||
175 | printf("Start M4 %u\n", core_id); | 175 | printf("Start M4 %u\n", core_id); |
176 | if (sc_pm_cpu_start(-1, core_rsrc, true, tcml_addr) != SC_ERR_NONE) | 176 | if (sc_pm_cpu_start(-1, core_rsrc, true, tcml_addr) != SC_ERR_NONE) |
177 | return -EIO; | 177 | return -EIO; |
178 | 178 | ||
179 | printf("bootaux complete\n"); | 179 | printf("bootaux complete\n"); |
180 | return 0; | 180 | return 0; |
181 | } | 181 | } |
182 | #endif | 182 | #endif |
183 | 183 | ||
184 | #ifdef CONFIG_IMX8QXP | 184 | #ifdef CONFIG_IMX8QXP |
185 | static unsigned long load_elf_image_shdr(unsigned long addr) | 185 | static unsigned long load_elf_image_shdr(unsigned long addr) |
186 | { | 186 | { |
187 | Elf32_Ehdr *ehdr; /* Elf header structure pointer */ | 187 | Elf32_Ehdr *ehdr; /* Elf header structure pointer */ |
188 | Elf32_Shdr *shdr; /* Section header structure pointer */ | 188 | Elf32_Shdr *shdr; /* Section header structure pointer */ |
189 | unsigned char *strtab = 0; /* String table pointer */ | 189 | unsigned char *strtab = 0; /* String table pointer */ |
190 | unsigned char *image; /* Binary image pointer */ | 190 | unsigned char *image; /* Binary image pointer */ |
191 | int i; /* Loop counter */ | 191 | int i; /* Loop counter */ |
192 | 192 | ||
193 | ehdr = (Elf32_Ehdr *)addr; | 193 | ehdr = (Elf32_Ehdr *)addr; |
194 | 194 | ||
195 | /* Find the section header string table for output info */ | 195 | /* Find the section header string table for output info */ |
196 | shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff + | 196 | shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff + |
197 | (ehdr->e_shstrndx * sizeof(Elf32_Shdr))); | 197 | (ehdr->e_shstrndx * sizeof(Elf32_Shdr))); |
198 | 198 | ||
199 | if (shdr->sh_type == SHT_STRTAB) | 199 | if (shdr->sh_type == SHT_STRTAB) |
200 | strtab = (unsigned char *)(addr + shdr->sh_offset); | 200 | strtab = (unsigned char *)(addr + shdr->sh_offset); |
201 | 201 | ||
202 | /* Load each appropriate section */ | 202 | /* Load each appropriate section */ |
203 | for (i = 0; i < ehdr->e_shnum; ++i) { | 203 | for (i = 0; i < ehdr->e_shnum; ++i) { |
204 | shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff + | 204 | shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff + |
205 | (i * sizeof(Elf32_Shdr))); | 205 | (i * sizeof(Elf32_Shdr))); |
206 | 206 | ||
207 | if (!(shdr->sh_flags & SHF_ALLOC) || | 207 | if (!(shdr->sh_flags & SHF_ALLOC) || |
208 | shdr->sh_addr == 0 || shdr->sh_size == 0) { | 208 | shdr->sh_addr == 0 || shdr->sh_size == 0) { |
209 | continue; | 209 | continue; |
210 | } | 210 | } |
211 | 211 | ||
212 | if (strtab) { | 212 | if (strtab) { |
213 | debug("%sing %s @ 0x%08lx (%ld bytes)\n", | 213 | debug("%sing %s @ 0x%08lx (%ld bytes)\n", |
214 | (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load", | 214 | (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load", |
215 | &strtab[shdr->sh_name], | 215 | &strtab[shdr->sh_name], |
216 | (unsigned long)shdr->sh_addr, | 216 | (unsigned long)shdr->sh_addr, |
217 | (long)shdr->sh_size); | 217 | (long)shdr->sh_size); |
218 | } | 218 | } |
219 | 219 | ||
220 | if (shdr->sh_type == SHT_NOBITS) { | 220 | if (shdr->sh_type == SHT_NOBITS) { |
221 | memset((void *)(uintptr_t)shdr->sh_addr, 0, | 221 | memset((void *)(uintptr_t)shdr->sh_addr, 0, |
222 | shdr->sh_size); | 222 | shdr->sh_size); |
223 | } else { | 223 | } else { |
224 | image = (unsigned char *)addr + shdr->sh_offset; | 224 | image = (unsigned char *)addr + shdr->sh_offset; |
225 | memcpy((void *)(uintptr_t)shdr->sh_addr, | 225 | memcpy((void *)(uintptr_t)shdr->sh_addr, |
226 | (const void *)image, shdr->sh_size); | 226 | (const void *)image, shdr->sh_size); |
227 | } | 227 | } |
228 | flush_cache(shdr->sh_addr, shdr->sh_size); | 228 | flush_cache(shdr->sh_addr, shdr->sh_size); |
229 | } | 229 | } |
230 | 230 | ||
231 | return ehdr->e_entry; | 231 | return ehdr->e_entry; |
232 | } | 232 | } |
233 | 233 | ||
234 | int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data) | 234 | int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data) |
235 | { | 235 | { |
236 | sc_rsrc_t core_rsrc, mu_rsrc = -1; | 236 | sc_rsrc_t core_rsrc, mu_rsrc = -1; |
237 | sc_faddr_t aux_core_ram; | 237 | sc_faddr_t aux_core_ram; |
238 | u32 size; | 238 | u32 size; |
239 | ulong addr; | 239 | ulong addr; |
240 | 240 | ||
241 | switch (core_id) { | 241 | switch (core_id) { |
242 | case 0: | 242 | case 0: |
243 | core_rsrc = SC_R_M4_0_PID0; | 243 | core_rsrc = SC_R_M4_0_PID0; |
244 | aux_core_ram = 0x34FE0000; | 244 | aux_core_ram = 0x34FE0000; |
245 | mu_rsrc = SC_R_M4_0_MU_1A; | 245 | mu_rsrc = SC_R_M4_0_MU_1A; |
246 | size = SZ_256K; | 246 | size = SZ_256K; |
247 | break; | 247 | break; |
248 | case 1: | 248 | case 1: |
249 | core_rsrc = SC_R_DSP; | 249 | core_rsrc = SC_R_DSP; |
250 | aux_core_ram = 0x596f8000; | 250 | aux_core_ram = 0x596f8000; |
251 | size = SZ_2K; | 251 | size = SZ_2K; |
252 | break; | 252 | break; |
253 | default: | 253 | default: |
254 | printf("Not support this core boot up, ID:%u\n", core_id); | 254 | printf("Not support this core boot up, ID:%u\n", core_id); |
255 | return -EINVAL; | 255 | return -EINVAL; |
256 | } | 256 | } |
257 | 257 | ||
258 | addr = (sc_faddr_t)boot_private_data; | 258 | addr = (sc_faddr_t)boot_private_data; |
259 | 259 | ||
260 | if (addr >= aux_core_ram && addr <= aux_core_ram + size) { | 260 | if (addr >= aux_core_ram && addr <= aux_core_ram + size) { |
261 | printf("Wrong image address 0x%lx, should not in aux core ram\n", | 261 | printf("Wrong image address 0x%lx, should not in aux core ram\n", |
262 | addr); | 262 | addr); |
263 | return -EINVAL; | 263 | return -EINVAL; |
264 | } | 264 | } |
265 | 265 | ||
266 | printf("Power on aux core %d\n", core_id); | 266 | printf("Power on aux core %d\n", core_id); |
267 | 267 | ||
268 | if (sc_pm_set_resource_power_mode(-1, core_rsrc, SC_PM_PW_MODE_ON) != SC_ERR_NONE) | 268 | if (sc_pm_set_resource_power_mode(-1, core_rsrc, SC_PM_PW_MODE_ON) != SC_ERR_NONE) |
269 | return -EIO; | 269 | return -EIO; |
270 | 270 | ||
271 | if (mu_rsrc != -1) { | 271 | if (mu_rsrc != -1) { |
272 | if (sc_pm_set_resource_power_mode(-1, mu_rsrc, SC_PM_PW_MODE_ON) != SC_ERR_NONE) | 272 | if (sc_pm_set_resource_power_mode(-1, mu_rsrc, SC_PM_PW_MODE_ON) != SC_ERR_NONE) |
273 | return -EIO; | 273 | return -EIO; |
274 | } | 274 | } |
275 | 275 | ||
276 | if (core_id == 1) { | 276 | if (core_id == 1) { |
277 | struct power_domain pd; | 277 | struct power_domain pd; |
278 | 278 | ||
279 | if (sc_pm_clock_enable(-1, core_rsrc, SC_PM_CLK_PER, true, false) != SC_ERR_NONE) { | 279 | if (sc_pm_clock_enable(-1, core_rsrc, SC_PM_CLK_PER, true, false) != SC_ERR_NONE) { |
280 | printf("Error enable clock\n"); | 280 | printf("Error enable clock\n"); |
281 | return -EIO; | 281 | return -EIO; |
282 | } | 282 | } |
283 | 283 | ||
284 | lpcg_all_clock_on(AUD_DSP_LPCG); | 284 | lpcg_all_clock_on(AUD_DSP_LPCG); |
285 | 285 | ||
286 | if (!power_domain_lookup_name("audio_sai0", &pd)) { | 286 | if (!power_domain_lookup_name("audio_sai0", &pd)) { |
287 | if (power_domain_on(&pd)) { | 287 | if (power_domain_on(&pd)) { |
288 | printf("Error power on SAI0\n"); | 288 | printf("Error power on SAI0\n"); |
289 | return -EIO; | 289 | return -EIO; |
290 | } | 290 | } |
291 | } | 291 | } |
292 | 292 | ||
293 | if (!power_domain_lookup_name("audio_ocram", &pd)) { | 293 | if (!power_domain_lookup_name("audio_ocram", &pd)) { |
294 | if (power_domain_on(&pd)) { | 294 | if (power_domain_on(&pd)) { |
295 | printf("Error power on HIFI RAM\n"); | 295 | printf("Error power on HIFI RAM\n"); |
296 | return -EIO; | 296 | return -EIO; |
297 | } | 297 | } |
298 | } | 298 | } |
299 | 299 | ||
300 | lpcg_all_clock_on(AUD_OCRAM_LPCG); | 300 | lpcg_all_clock_on(AUD_OCRAM_LPCG); |
301 | lpcg_all_clock_on(AUD_SAI_0_LPCG); | 301 | lpcg_all_clock_on(AUD_SAI_0_LPCG); |
302 | } | 302 | } |
303 | 303 | ||
304 | printf("Copy image from 0x%lx to 0x%lx\n", addr, (ulong)aux_core_ram); | 304 | printf("Copy image from 0x%lx to 0x%lx\n", addr, (ulong)aux_core_ram); |
305 | if (core_id == 0) { | 305 | if (core_id == 0) { |
306 | /* M4 use bin file */ | 306 | /* M4 use bin file */ |
307 | memcpy((void *)aux_core_ram, (void *)addr, size); | 307 | memcpy((void *)aux_core_ram, (void *)addr, size); |
308 | } else { | 308 | } else { |
309 | /* HIFI use elf file */ | 309 | /* HIFI use elf file */ |
310 | if (!valid_elf_image(addr)) | 310 | if (!valid_elf_image(addr)) |
311 | return -1; | 311 | return -1; |
312 | addr = load_elf_image_shdr(addr); | 312 | addr = load_elf_image_shdr(addr); |
313 | } | 313 | } |
314 | 314 | ||
315 | printf("Start %s\n", core_id == 0 ? "M4" : "HIFI"); | 315 | printf("Start %s\n", core_id == 0 ? "M4" : "HIFI"); |
316 | 316 | ||
317 | if (sc_pm_cpu_start(-1, core_rsrc, true, aux_core_ram) != SC_ERR_NONE) | 317 | if (sc_pm_cpu_start(-1, core_rsrc, true, aux_core_ram) != SC_ERR_NONE) |
318 | return -EIO; | 318 | return -EIO; |
319 | 319 | ||
320 | printf("bootaux complete\n"); | 320 | printf("bootaux complete\n"); |
321 | return 0; | 321 | return 0; |
322 | } | 322 | } |
323 | #endif | 323 | #endif |
324 | 324 | ||
325 | int arch_auxiliary_core_check_up(u32 core_id) | 325 | int arch_auxiliary_core_check_up(u32 core_id) |
326 | { | 326 | { |
327 | sc_rsrc_t core_rsrc; | 327 | sc_rsrc_t core_rsrc; |
328 | sc_pm_power_mode_t power_mode; | 328 | sc_pm_power_mode_t power_mode; |
329 | 329 | ||
330 | switch (core_id) { | 330 | switch (core_id) { |
331 | case 0: | 331 | case 0: |
332 | core_rsrc = SC_R_M4_0_PID0; | 332 | core_rsrc = SC_R_M4_0_PID0; |
333 | break; | 333 | break; |
334 | #ifdef CONFIG_IMX8QM | 334 | #ifdef CONFIG_IMX8QM |
335 | case 1: | 335 | case 1: |
336 | core_rsrc = SC_R_M4_1_PID0; | 336 | core_rsrc = SC_R_M4_1_PID0; |
337 | break; | 337 | break; |
338 | #endif | 338 | #endif |
339 | default: | 339 | default: |
340 | printf("Not support this core, ID:%u\n", core_id); | 340 | printf("Not support this core, ID:%u\n", core_id); |
341 | return 0; | 341 | return 0; |
342 | } | 342 | } |
343 | 343 | ||
344 | if (sc_pm_get_resource_power_mode(-1, core_rsrc, &power_mode) != SC_ERR_NONE) | 344 | if (sc_pm_get_resource_power_mode(-1, core_rsrc, &power_mode) != SC_ERR_NONE) |
345 | return 0; | 345 | return 0; |
346 | 346 | ||
347 | if (power_mode != SC_PM_PW_MODE_OFF) | 347 | if (power_mode != SC_PM_PW_MODE_OFF) |
348 | return 1; | 348 | return 1; |
349 | 349 | ||
350 | return 0; | 350 | return 0; |
351 | } | 351 | } |
352 | #endif | 352 | #endif |
353 | 353 | ||
354 | static bool check_owned_resource(sc_rsrc_t rsrc_id) | 354 | static bool check_owned_resource(sc_rsrc_t rsrc_id) |
355 | { | 355 | { |
356 | bool owned; | 356 | bool owned; |
357 | 357 | ||
358 | owned = sc_rm_is_resource_owned(-1, rsrc_id); | 358 | owned = sc_rm_is_resource_owned(-1, rsrc_id); |
359 | 359 | ||
360 | return owned; | 360 | return owned; |
361 | } | 361 | } |
362 | 362 | ||
363 | #ifdef CONFIG_IMX_SMMU | 363 | #ifdef CONFIG_IMX_SMMU |
364 | struct smmu_sid dev_sids[] = { | 364 | struct smmu_sid dev_sids[] = { |
365 | }; | 365 | }; |
366 | 366 | ||
367 | int imx8_config_smmu_sid(struct smmu_sid *dev_sids, int size) | 367 | int imx8_config_smmu_sid(struct smmu_sid *dev_sids, int size) |
368 | { | 368 | { |
369 | int i; | 369 | int i; |
370 | int sciErr = 0; | 370 | int sciErr = 0; |
371 | 371 | ||
372 | if ((dev_sids == NULL) || (size <= 0)) | 372 | if ((dev_sids == NULL) || (size <= 0)) |
373 | return 0; | 373 | return 0; |
374 | 374 | ||
375 | for (i = 0; i < size; i++) { | 375 | for (i = 0; i < size; i++) { |
376 | if (!check_owned_resource(dev_sids[i].rsrc)) { | 376 | if (!check_owned_resource(dev_sids[i].rsrc)) { |
377 | printf("%s rsrc[%d] not owned\n", __func__, dev_sids[i].rsrc); | 377 | printf("%s rsrc[%d] not owned\n", __func__, dev_sids[i].rsrc); |
378 | continue; | 378 | continue; |
379 | } | 379 | } |
380 | sciErr = sc_rm_set_master_sid(-1, | 380 | sciErr = sc_rm_set_master_sid(-1, |
381 | dev_sids[i].rsrc, | 381 | dev_sids[i].rsrc, |
382 | dev_sids[i].sid); | 382 | dev_sids[i].sid); |
383 | if (sciErr) { | 383 | if (sciErr) { |
384 | printf("set master sid error\n"); | 384 | printf("set master sid error\n"); |
385 | return sciErr; | 385 | return sciErr; |
386 | } | 386 | } |
387 | } | 387 | } |
388 | 388 | ||
389 | return 0; | 389 | return 0; |
390 | } | 390 | } |
391 | #endif | 391 | #endif |
392 | 392 | ||
393 | void arch_preboot_os(void) | 393 | void arch_preboot_os(void) |
394 | { | 394 | { |
395 | #if defined(CONFIG_VIDEO_IMXDPUV1) | 395 | #if defined(CONFIG_VIDEO_IMXDPUV1) |
396 | imxdpuv1_fb_disable(); | 396 | imxdpuv1_fb_disable(); |
397 | #endif | 397 | #endif |
398 | #ifdef CONFIG_IMX_SMMU | 398 | #ifdef CONFIG_IMX_SMMU |
399 | imx8_config_smmu_sid(dev_sids, ARRAY_SIZE(dev_sids)); | 399 | imx8_config_smmu_sid(dev_sids, ARRAY_SIZE(dev_sids)); |
400 | #endif | 400 | #endif |
401 | } | 401 | } |
402 | 402 | ||
403 | #if defined(CONFIG_ARCH_MISC_INIT) | 403 | #if defined(CONFIG_ARCH_MISC_INIT) |
404 | #define FSL_SIP_BUILDINFO 0xC2000003 | 404 | #define FSL_SIP_BUILDINFO 0xC2000003 |
405 | #define FSL_SIP_BUILDINFO_GET_COMMITHASH 0x00 | 405 | #define FSL_SIP_BUILDINFO_GET_COMMITHASH 0x00 |
406 | extern uint32_t _end_ofs; | 406 | extern uint32_t _end_ofs; |
407 | 407 | ||
408 | static void set_buildinfo_to_env(uint32_t scfw, uint32_t secofw, char *mkimage, char *atf) | 408 | static void set_buildinfo_to_env(uint32_t scfw, uint32_t secofw, char *mkimage, char *atf) |
409 | { | 409 | { |
410 | if (!mkimage || !atf) | 410 | if (!mkimage || !atf) |
411 | return; | 411 | return; |
412 | 412 | ||
413 | env_set("commit_mkimage", mkimage); | 413 | env_set("commit_mkimage", mkimage); |
414 | env_set("commit_atf", atf); | 414 | env_set("commit_atf", atf); |
415 | env_set_hex("commit_scfw", (ulong)scfw); | 415 | env_set_hex("commit_scfw", (ulong)scfw); |
416 | env_set_hex("commit_secofw", (ulong)secofw); | 416 | env_set_hex("commit_secofw", (ulong)secofw); |
417 | } | 417 | } |
418 | 418 | ||
419 | static void acquire_buildinfo(void) | 419 | static void acquire_buildinfo(void) |
420 | { | 420 | { |
421 | uint32_t sc_build = 0, sc_commit = 0; | 421 | uint32_t sc_build = 0, sc_commit = 0; |
422 | uint32_t seco_build = 0, seco_commit = 0; | 422 | uint32_t seco_build = 0, seco_commit = 0; |
423 | char *mkimage_commit, *temp; | 423 | char *mkimage_commit, *temp; |
424 | uint64_t atf_commit = 0; | 424 | uint64_t atf_commit = 0; |
425 | 425 | ||
426 | /* Get SCFW build and commit id */ | 426 | /* Get SCFW build and commit id */ |
427 | sc_misc_build_info(-1, &sc_build, &sc_commit); | 427 | sc_misc_build_info(-1, &sc_build, &sc_commit); |
428 | if (sc_build == 0) { | 428 | if (sc_build == 0) { |
429 | debug("SCFW does not support build info\n"); | 429 | debug("SCFW does not support build info\n"); |
430 | sc_commit = 0; /* Display 0 when the build info is not supported*/ | 430 | sc_commit = 0; /* Display 0 when the build info is not supported*/ |
431 | } | 431 | } |
432 | 432 | ||
433 | /* Get SECO FW build and commit id */ | 433 | /* Get SECO FW build and commit id */ |
434 | sc_seco_build_info(-1, &seco_build, &seco_commit); | 434 | sc_seco_build_info(-1, &seco_build, &seco_commit); |
435 | if (seco_build == 0) { | 435 | if (seco_build == 0) { |
436 | debug("SECO FW does not support build info\n"); | 436 | debug("SECO FW does not support build info\n"); |
437 | seco_commit = 0; /* Display 0 when the build info is not supported*/ | 437 | seco_commit = 0; /* Display 0 when the build info is not supported*/ |
438 | } | 438 | } |
439 | 439 | ||
440 | /* Get imx-mkimage commit id. | 440 | /* Get imx-mkimage commit id. |
441 | * The imx-mkimage puts the commit hash behind the end of u-boot.bin | 441 | * The imx-mkimage puts the commit hash behind the end of u-boot.bin |
442 | */ | 442 | */ |
443 | mkimage_commit = (char *)(ulong)(CONFIG_SYS_TEXT_BASE + _end_ofs + fdt_totalsize(gd->fdt_blob)); | 443 | mkimage_commit = (char *)(ulong)(CONFIG_SYS_TEXT_BASE + _end_ofs + fdt_totalsize(gd->fdt_blob)); |
444 | temp = mkimage_commit + 8; | 444 | temp = mkimage_commit + 8; |
445 | *temp = '\0'; | 445 | *temp = '\0'; |
446 | 446 | ||
447 | if (strlen(mkimage_commit) == 0) { | 447 | if (strlen(mkimage_commit) == 0) { |
448 | debug("IMX-MKIMAGE does not support build info\n"); | 448 | debug("IMX-MKIMAGE does not support build info\n"); |
449 | mkimage_commit = "0"; /* Display 0 */ | 449 | mkimage_commit = "0"; /* Display 0 */ |
450 | } | 450 | } |
451 | 451 | ||
452 | /* Get ARM Trusted Firmware commit id */ | 452 | /* Get ARM Trusted Firmware commit id */ |
453 | atf_commit = call_imx_sip(FSL_SIP_BUILDINFO, FSL_SIP_BUILDINFO_GET_COMMITHASH, 0, 0, 0); | 453 | atf_commit = call_imx_sip(FSL_SIP_BUILDINFO, FSL_SIP_BUILDINFO_GET_COMMITHASH, 0, 0, 0); |
454 | if (atf_commit == 0xffffffff) { | 454 | if (atf_commit == 0xffffffff) { |
455 | debug("ATF does not support build info\n"); | 455 | debug("ATF does not support build info\n"); |
456 | atf_commit = 0x30; /* Display 0, 0 ascii is 0x30 */ | 456 | atf_commit = 0x30; /* Display 0, 0 ascii is 0x30 */ |
457 | } | 457 | } |
458 | 458 | ||
459 | /* Set all to env */ | 459 | /* Set all to env */ |
460 | set_buildinfo_to_env(sc_commit, seco_commit, mkimage_commit, (char *)&atf_commit); | 460 | set_buildinfo_to_env(sc_commit, seco_commit, mkimage_commit, (char *)&atf_commit); |
461 | 461 | ||
462 | printf("\n BuildInfo: \n - SCFW %08x, SECO-FW %08x, IMX-MKIMAGE %s, ATF %s\n - %s \n\n", | 462 | printf("\n BuildInfo: \n - SCFW %08x, SECO-FW %08x, IMX-MKIMAGE %s, ATF %s\n - %s \n\n", |
463 | sc_commit, seco_commit, mkimage_commit, (char *)&atf_commit, U_BOOT_VERSION); | 463 | sc_commit, seco_commit, mkimage_commit, (char *)&atf_commit, U_BOOT_VERSION); |
464 | } | 464 | } |
465 | 465 | ||
466 | int arch_misc_init(void) | 466 | int arch_misc_init(void) |
467 | { | 467 | { |
468 | acquire_buildinfo(); | 468 | acquire_buildinfo(); |
469 | 469 | ||
470 | return 0; | 470 | return 0; |
471 | } | 471 | } |
472 | #endif | 472 | #endif |
473 | 473 | ||
474 | int print_bootinfo(void) | 474 | int print_bootinfo(void) |
475 | { | 475 | { |
476 | enum boot_device bt_dev = get_boot_device(); | 476 | enum boot_device bt_dev = get_boot_device(); |
477 | 477 | ||
478 | puts("Boot: "); | 478 | puts("Boot: "); |
479 | switch (bt_dev) { | 479 | switch (bt_dev) { |
480 | case SD1_BOOT: | 480 | case SD1_BOOT: |
481 | puts("SD0\n"); | 481 | puts("SD0\n"); |
482 | break; | 482 | break; |
483 | case SD2_BOOT: | 483 | case SD2_BOOT: |
484 | puts("SD1\n"); | 484 | puts("SD1\n"); |
485 | break; | 485 | break; |
486 | case SD3_BOOT: | 486 | case SD3_BOOT: |
487 | puts("SD2\n"); | 487 | puts("SD2\n"); |
488 | break; | 488 | break; |
489 | case MMC1_BOOT: | 489 | case MMC1_BOOT: |
490 | puts("MMC0\n"); | 490 | puts("MMC0\n"); |
491 | break; | 491 | break; |
492 | case MMC2_BOOT: | 492 | case MMC2_BOOT: |
493 | puts("MMC1\n"); | 493 | puts("MMC1\n"); |
494 | break; | 494 | break; |
495 | case MMC3_BOOT: | 495 | case MMC3_BOOT: |
496 | puts("MMC2\n"); | 496 | puts("MMC2\n"); |
497 | break; | 497 | break; |
498 | case FLEXSPI_BOOT: | 498 | case FLEXSPI_BOOT: |
499 | puts("FLEXSPI\n"); | 499 | puts("FLEXSPI\n"); |
500 | break; | 500 | break; |
501 | case SATA_BOOT: | 501 | case SATA_BOOT: |
502 | puts("SATA\n"); | 502 | puts("SATA\n"); |
503 | break; | 503 | break; |
504 | case NAND_BOOT: | 504 | case NAND_BOOT: |
505 | puts("NAND\n"); | 505 | puts("NAND\n"); |
506 | break; | 506 | break; |
507 | case USB_BOOT: | 507 | case USB_BOOT: |
508 | puts("USB\n"); | 508 | puts("USB\n"); |
509 | break; | 509 | break; |
510 | default: | 510 | default: |
511 | printf("Unknown device %u\n", bt_dev); | 511 | printf("Unknown device %u\n", bt_dev); |
512 | break; | 512 | break; |
513 | } | 513 | } |
514 | 514 | ||
515 | return 0; | 515 | return 0; |
516 | } | 516 | } |
517 | 517 | ||
518 | enum boot_device get_boot_device(void) | 518 | enum boot_device get_boot_device(void) |
519 | { | 519 | { |
520 | enum boot_device boot_dev = SD1_BOOT; | 520 | enum boot_device boot_dev = SD1_BOOT; |
521 | 521 | ||
522 | sc_rsrc_t dev_rsrc; | 522 | sc_rsrc_t dev_rsrc; |
523 | 523 | ||
524 | sc_misc_get_boot_dev(-1, &dev_rsrc); | 524 | sc_misc_get_boot_dev(-1, &dev_rsrc); |
525 | 525 | ||
526 | switch (dev_rsrc) { | 526 | switch (dev_rsrc) { |
527 | case SC_R_SDHC_0: | 527 | case SC_R_SDHC_0: |
528 | boot_dev = MMC1_BOOT; | 528 | boot_dev = MMC1_BOOT; |
529 | break; | 529 | break; |
530 | case SC_R_SDHC_1: | 530 | case SC_R_SDHC_1: |
531 | boot_dev = SD2_BOOT; | 531 | boot_dev = SD2_BOOT; |
532 | break; | 532 | break; |
533 | case SC_R_SDHC_2: | 533 | case SC_R_SDHC_2: |
534 | boot_dev = SD3_BOOT; | 534 | boot_dev = SD3_BOOT; |
535 | break; | 535 | break; |
536 | case SC_R_NAND: | 536 | case SC_R_NAND: |
537 | boot_dev = NAND_BOOT; | 537 | boot_dev = NAND_BOOT; |
538 | break; | 538 | break; |
539 | case SC_R_FSPI_0: | 539 | case SC_R_FSPI_0: |
540 | boot_dev = FLEXSPI_BOOT; | 540 | boot_dev = FLEXSPI_BOOT; |
541 | break; | 541 | break; |
542 | case SC_R_SATA_0: | 542 | case SC_R_SATA_0: |
543 | boot_dev = SATA_BOOT; | 543 | boot_dev = SATA_BOOT; |
544 | break; | 544 | break; |
545 | case SC_R_USB_0: | 545 | case SC_R_USB_0: |
546 | case SC_R_USB_1: | 546 | case SC_R_USB_1: |
547 | case SC_R_USB_2: | 547 | case SC_R_USB_2: |
548 | boot_dev = USB_BOOT; | 548 | boot_dev = USB_BOOT; |
549 | break; | 549 | break; |
550 | default: | 550 | default: |
551 | break; | 551 | break; |
552 | } | 552 | } |
553 | 553 | ||
554 | return boot_dev; | 554 | return boot_dev; |
555 | } | 555 | } |
556 | 556 | ||
557 | bool is_usb_boot(void) | 557 | bool is_usb_boot(void) |
558 | { | 558 | { |
559 | return get_boot_device() == USB_BOOT; | 559 | return get_boot_device() == USB_BOOT; |
560 | } | 560 | } |
561 | 561 | ||
562 | #ifdef CONFIG_SERIAL_TAG | 562 | #ifdef CONFIG_SERIAL_TAG |
563 | #define FUSE_UNIQUE_ID_WORD0 16 | 563 | #define FUSE_UNIQUE_ID_WORD0 16 |
564 | #define FUSE_UNIQUE_ID_WORD1 17 | 564 | #define FUSE_UNIQUE_ID_WORD1 17 |
565 | void get_board_serial(struct tag_serialnr *serialnr) | 565 | void get_board_serial(struct tag_serialnr *serialnr) |
566 | { | 566 | { |
567 | sc_err_t err; | 567 | sc_err_t err; |
568 | uint32_t val1 = 0, val2 = 0; | 568 | uint32_t val1 = 0, val2 = 0; |
569 | uint32_t word1, word2; | 569 | uint32_t word1, word2; |
570 | 570 | ||
571 | word1 = FUSE_UNIQUE_ID_WORD0; | 571 | word1 = FUSE_UNIQUE_ID_WORD0; |
572 | word2 = FUSE_UNIQUE_ID_WORD1; | 572 | word2 = FUSE_UNIQUE_ID_WORD1; |
573 | 573 | ||
574 | err = sc_misc_otp_fuse_read(-1, word1, &val1); | 574 | err = sc_misc_otp_fuse_read(-1, word1, &val1); |
575 | if (err != SC_ERR_NONE) { | 575 | if (err != SC_ERR_NONE) { |
576 | printf("%s fuse %d read error: %d\n", __func__,word1, err); | 576 | printf("%s fuse %d read error: %d\n", __func__,word1, err); |
577 | return; | 577 | return; |
578 | } | 578 | } |
579 | 579 | ||
580 | err = sc_misc_otp_fuse_read(-1, word2, &val2); | 580 | err = sc_misc_otp_fuse_read(-1, word2, &val2); |
581 | if (err != SC_ERR_NONE) { | 581 | if (err != SC_ERR_NONE) { |
582 | printf("%s fuse %d read error: %d\n", __func__, word2, err); | 582 | printf("%s fuse %d read error: %d\n", __func__, word2, err); |
583 | return; | 583 | return; |
584 | } | 584 | } |
585 | serialnr->low = val1; | 585 | serialnr->low = val1; |
586 | serialnr->high = val2; | 586 | serialnr->high = val2; |
587 | } | 587 | } |
588 | #endif /*CONFIG_SERIAL_TAG*/ | 588 | #endif /*CONFIG_SERIAL_TAG*/ |
589 | 589 | ||
590 | __weak int board_mmc_get_env_dev(int devno) | 590 | __weak int board_mmc_get_env_dev(int devno) |
591 | { | 591 | { |
592 | return devno; | 592 | return devno; |
593 | } | 593 | } |
594 | 594 | ||
595 | int mmc_get_env_dev(void) | 595 | int mmc_get_env_dev(void) |
596 | { | 596 | { |
597 | sc_rsrc_t dev_rsrc; | 597 | sc_rsrc_t dev_rsrc; |
598 | int devno; | 598 | int devno; |
599 | 599 | ||
600 | sc_misc_get_boot_dev(-1, &dev_rsrc); | 600 | sc_misc_get_boot_dev(-1, &dev_rsrc); |
601 | 601 | ||
602 | switch (dev_rsrc) { | 602 | switch (dev_rsrc) { |
603 | case SC_R_SDHC_0: | 603 | case SC_R_SDHC_0: |
604 | devno = 0; | 604 | devno = 0; |
605 | break; | 605 | break; |
606 | case SC_R_SDHC_1: | 606 | case SC_R_SDHC_1: |
607 | devno = 1; | 607 | devno = 1; |
608 | break; | 608 | break; |
609 | case SC_R_SDHC_2: | 609 | case SC_R_SDHC_2: |
610 | devno = 2; | 610 | devno = 2; |
611 | break; | 611 | break; |
612 | default: | 612 | default: |
613 | /* If not boot from sd/mmc, use default value */ | 613 | /* If not boot from sd/mmc, use default value */ |
614 | return env_get_ulong("mmcdev", 10, CONFIG_SYS_MMC_ENV_DEV); | 614 | return env_get_ulong("mmcdev", 10, CONFIG_SYS_MMC_ENV_DEV); |
615 | } | 615 | } |
616 | 616 | ||
617 | return board_mmc_get_env_dev(devno); | 617 | return board_mmc_get_env_dev(devno); |
618 | } | 618 | } |
619 | 619 | ||
620 | static bool check_owned_resources_in_pd_tree(void *blob, int nodeoff, | 620 | static bool check_owned_resources_in_pd_tree(void *blob, int nodeoff, |
621 | unsigned int *unowned_rsrc) | 621 | unsigned int *unowned_rsrc) |
622 | { | 622 | { |
623 | unsigned int rsrc_id; | 623 | unsigned int rsrc_id; |
624 | int phplen; | 624 | int phplen; |
625 | const fdt32_t *php; | 625 | const fdt32_t *php; |
626 | 626 | ||
627 | /* Search the ancestors nodes in current SS power-domain tree, | 627 | /* Search the ancestors nodes in current SS power-domain tree, |
628 | * if all ancestors' resources are owned, we can enable the node, | 628 | * if all ancestors' resources are owned, we can enable the node, |
629 | * otherwise any ancestor is not owned, we should disable the node. | 629 | * otherwise any ancestor is not owned, we should disable the node. |
630 | */ | 630 | */ |
631 | 631 | ||
632 | do { | 632 | do { |
633 | php = fdt_getprop(blob, nodeoff, "power-domains", &phplen); | 633 | php = fdt_getprop(blob, nodeoff, "power-domains", &phplen); |
634 | if (!php) { | 634 | if (!php) { |
635 | debug(" - ignoring no power-domains\n"); | 635 | debug(" - ignoring no power-domains\n"); |
636 | break; | 636 | break; |
637 | } | 637 | } |
638 | if (phplen != 4) { | 638 | if (phplen != 4) { |
639 | printf("ignoring %s power-domains of unexpected length %d\n", | 639 | printf("ignoring %s power-domains of unexpected length %d\n", |
640 | fdt_get_name(blob, nodeoff, NULL), phplen); | 640 | fdt_get_name(blob, nodeoff, NULL), phplen); |
641 | break; | 641 | break; |
642 | } | 642 | } |
643 | nodeoff = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*php)); | 643 | nodeoff = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*php)); |
644 | 644 | ||
645 | rsrc_id = fdtdec_get_uint(blob, nodeoff, "reg", 0); | 645 | rsrc_id = fdtdec_get_uint(blob, nodeoff, "reg", 0); |
646 | if (rsrc_id == SC_R_NONE) { | 646 | if (rsrc_id == SC_R_NONE) { |
647 | debug("%s's power domain use SC_R_NONE\n", | 647 | debug("%s's power domain use SC_R_NONE\n", |
648 | fdt_get_name(blob, nodeoff, NULL)); | 648 | fdt_get_name(blob, nodeoff, NULL)); |
649 | break; | 649 | break; |
650 | } | 650 | } |
651 | 651 | ||
652 | debug("power-domains node 0x%x, resource id %u\n", nodeoff, rsrc_id); | 652 | debug("power-domains node 0x%x, resource id %u\n", nodeoff, rsrc_id); |
653 | 653 | ||
654 | if (!check_owned_resource(rsrc_id)) { | 654 | if (!check_owned_resource(rsrc_id)) { |
655 | if (unowned_rsrc != NULL) | 655 | if (unowned_rsrc != NULL) |
656 | *unowned_rsrc = rsrc_id; | 656 | *unowned_rsrc = rsrc_id; |
657 | return false; | 657 | return false; |
658 | } | 658 | } |
659 | } while (fdt_node_check_compatible(blob, nodeoff, "nxp,imx8-pd")); | 659 | } while (fdt_node_check_compatible(blob, nodeoff, "nxp,imx8-pd")); |
660 | 660 | ||
661 | return true; | 661 | return true; |
662 | } | 662 | } |
663 | 663 | ||
664 | static int disable_fdt_node(void *blob, int nodeoffset) | 664 | static int disable_fdt_node(void *blob, int nodeoffset) |
665 | { | 665 | { |
666 | int rc, ret; | 666 | int rc, ret; |
667 | const char *status = "disabled"; | 667 | const char *status = "disabled"; |
668 | 668 | ||
669 | do { | 669 | do { |
670 | rc = fdt_setprop(blob, nodeoffset, "status", status, strlen(status) + 1); | 670 | rc = fdt_setprop(blob, nodeoffset, "status", status, strlen(status) + 1); |
671 | if (rc) { | 671 | if (rc) { |
672 | if (rc == -FDT_ERR_NOSPACE) { | 672 | if (rc == -FDT_ERR_NOSPACE) { |
673 | ret = fdt_increase_size(blob, 512); | 673 | ret = fdt_increase_size(blob, 512); |
674 | if (ret) | 674 | if (ret) |
675 | return ret; | 675 | return ret; |
676 | } | 676 | } |
677 | } | 677 | } |
678 | } while (rc == -FDT_ERR_NOSPACE); | 678 | } while (rc == -FDT_ERR_NOSPACE); |
679 | 679 | ||
680 | return rc; | 680 | return rc; |
681 | } | 681 | } |
682 | 682 | ||
683 | static void fdt_edma_debug_int_array(u32 *array, int count, u32 stride) | 683 | static void fdt_edma_debug_int_array(u32 *array, int count, u32 stride) |
684 | { | 684 | { |
685 | #ifdef DEBUG | 685 | #ifdef DEBUG |
686 | int i; | 686 | int i; |
687 | for (i = 0; i < count; i++) { | 687 | for (i = 0; i < count; i++) { |
688 | printf("0x%x ", array[i]); | 688 | printf("0x%x ", array[i]); |
689 | if (i % stride == stride - 1) | 689 | if (i % stride == stride - 1) |
690 | printf("\n"); | 690 | printf("\n"); |
691 | } | 691 | } |
692 | 692 | ||
693 | printf("\n"); | 693 | printf("\n"); |
694 | #endif | 694 | #endif |
695 | } | 695 | } |
696 | 696 | ||
697 | static void fdt_edma_debug_stringlist(const char *stringlist, int length) | 697 | static void fdt_edma_debug_stringlist(const char *stringlist, int length) |
698 | { | 698 | { |
699 | #ifdef DEBUG | 699 | #ifdef DEBUG |
700 | int i = 0, len; | 700 | int i = 0, len; |
701 | while (i < length) { | 701 | while (i < length) { |
702 | printf("%s\n", stringlist); | 702 | printf("%s\n", stringlist); |
703 | 703 | ||
704 | len = strlen(stringlist) + 1; | 704 | len = strlen(stringlist) + 1; |
705 | i += len; | 705 | i += len; |
706 | stringlist += len; | 706 | stringlist += len; |
707 | } | 707 | } |
708 | 708 | ||
709 | printf("\n"); | 709 | printf("\n"); |
710 | #endif | 710 | #endif |
711 | } | 711 | } |
712 | 712 | ||
713 | static void fdt_edma_swap_int_array(u32 *array, int count) | 713 | static void fdt_edma_swap_int_array(u32 *array, int count) |
714 | { | 714 | { |
715 | int i; | 715 | int i; |
716 | for (i = 0; i < count; i++) { | 716 | for (i = 0; i < count; i++) { |
717 | array[i] = cpu_to_fdt32(array[i]); | 717 | array[i] = cpu_to_fdt32(array[i]); |
718 | } | 718 | } |
719 | } | 719 | } |
720 | 720 | ||
721 | static int fdt_edma_update_int_array(u32 *array, int count, u32 *new_array, u32 stride, int *remove_array, int remove_count) | 721 | static int fdt_edma_update_int_array(u32 *array, int count, u32 *new_array, u32 stride, int *remove_array, int remove_count) |
722 | { | 722 | { |
723 | int i = 0, j, curr = 0, new_cnt = 0; | 723 | int i = 0, j, curr = 0, new_cnt = 0; |
724 | 724 | ||
725 | do { | 725 | do { |
726 | if (remove_count && curr == remove_array[i]) { | 726 | if (remove_count && curr == remove_array[i]) { |
727 | i++; | 727 | i++; |
728 | remove_count--; | 728 | remove_count--; |
729 | array += stride; | 729 | array += stride; |
730 | } else { | 730 | } else { |
731 | for (j = 0; j< stride; j++) { | 731 | for (j = 0; j< stride; j++) { |
732 | *new_array = *array; | 732 | *new_array = *array; |
733 | new_array++; | 733 | new_array++; |
734 | array++; | 734 | array++; |
735 | } | 735 | } |
736 | new_cnt+= j; | 736 | new_cnt+= j; |
737 | } | 737 | } |
738 | curr++; | 738 | curr++; |
739 | } while ((curr * stride) < count); | 739 | } while ((curr * stride) < count); |
740 | 740 | ||
741 | return new_cnt; | 741 | return new_cnt; |
742 | } | 742 | } |
743 | 743 | ||
744 | static int fdt_edma_update_stringlist(const char *stringlist, int stringlist_count, char *newlist, int *remove_array, int remove_count) | 744 | static int fdt_edma_update_stringlist(const char *stringlist, int stringlist_count, char *newlist, int *remove_array, int remove_count) |
745 | { | 745 | { |
746 | int i = 0, curr = 0, new_len = 0; | 746 | int i = 0, curr = 0, new_len = 0; |
747 | int length; | 747 | int length; |
748 | 748 | ||
749 | debug("fdt_edma_update_stringlist, remove_cnt %d\n", remove_count); | 749 | debug("fdt_edma_update_stringlist, remove_cnt %d\n", remove_count); |
750 | 750 | ||
751 | do { | 751 | do { |
752 | if (remove_count && curr == remove_array[i]) { | 752 | if (remove_count && curr == remove_array[i]) { |
753 | debug("remove %s at %d\n", stringlist, remove_array[i]); | 753 | debug("remove %s at %d\n", stringlist, remove_array[i]); |
754 | 754 | ||
755 | length = strlen(stringlist) + 1; | 755 | length = strlen(stringlist) + 1; |
756 | stringlist += length; | 756 | stringlist += length; |
757 | i++; | 757 | i++; |
758 | remove_count--; | 758 | remove_count--; |
759 | } else { | 759 | } else { |
760 | length = strlen(stringlist) + 1; | 760 | length = strlen(stringlist) + 1; |
761 | strcpy(newlist, stringlist); | 761 | strcpy(newlist, stringlist); |
762 | 762 | ||
763 | debug("copy %s, %s, curr %d, len %d\n", newlist, stringlist, curr, length); | 763 | debug("copy %s, %s, curr %d, len %d\n", newlist, stringlist, curr, length); |
764 | 764 | ||
765 | stringlist += length; | 765 | stringlist += length; |
766 | newlist += length; | 766 | newlist += length; |
767 | new_len += length; | 767 | new_len += length; |
768 | } | 768 | } |
769 | curr++; | 769 | curr++; |
770 | } while (curr < stringlist_count); | 770 | } while (curr < stringlist_count); |
771 | 771 | ||
772 | return new_len; | 772 | return new_len; |
773 | } | 773 | } |
774 | 774 | ||
775 | static int fdt_edma_get_channel_id(u32 *regs, int index, struct edma_ch_map *edma) | 775 | static int fdt_edma_get_channel_id(u32 *regs, int index, struct edma_ch_map *edma) |
776 | { | 776 | { |
777 | u32 ch_reg = regs[(index << 2) + 1]; | 777 | u32 ch_reg = regs[(index << 2) + 1]; |
778 | u32 ch_reg_size = regs[(index << 2) + 3]; | 778 | u32 ch_reg_size = regs[(index << 2) + 3]; |
779 | int ch_id = (ch_reg - edma->ch_start_regs) / ch_reg_size; | 779 | int ch_id = (ch_reg - edma->ch_start_regs) / ch_reg_size; |
780 | if (ch_id >= edma->ch_num) | 780 | if (ch_id >= edma->ch_num) |
781 | return -1; | 781 | return -1; |
782 | 782 | ||
783 | return ch_id; | 783 | return ch_id; |
784 | } | 784 | } |
785 | 785 | ||
786 | static void update_fdt_edma_nodes(void *blob) | 786 | static void update_fdt_edma_nodes(void *blob) |
787 | { | 787 | { |
788 | struct edma_ch_map edma_qm[] = { | 788 | struct edma_ch_map edma_qm[] = { |
789 | { SC_R_DMA_0_CH0, 0x5a200000, 32, "/dma-controller@5a1f0000"}, | 789 | { SC_R_DMA_0_CH0, 0x5a200000, 32, "/dma-controller@5a1f0000"}, |
790 | { SC_R_DMA_1_CH0, 0x5aa00000, 32, "/dma-controller@5a9f0000"}, | 790 | { SC_R_DMA_1_CH0, 0x5aa00000, 32, "/dma-controller@5a9f0000"}, |
791 | { SC_R_DMA_2_CH0, 0x59200000, 5, "/dma-controller@591F0000"}, | 791 | { SC_R_DMA_2_CH0, 0x59200000, 5, "/dma-controller@591F0000"}, |
792 | { SC_R_DMA_2_CH5, 0x59250000, 27, "/dma-controller@591F0000"}, | 792 | { SC_R_DMA_2_CH5, 0x59250000, 27, "/dma-controller@591F0000"}, |
793 | { SC_R_DMA_3_CH0, 0x59a00000, 32, "/dma-controller@599F0000"}, | 793 | { SC_R_DMA_3_CH0, 0x59a00000, 32, "/dma-controller@599F0000"}, |
794 | }; | 794 | }; |
795 | 795 | ||
796 | struct edma_ch_map edma_qxp[] = { | 796 | struct edma_ch_map edma_qxp[] = { |
797 | { SC_R_DMA_0_CH0, 0x59200000, 32, "/dma-controller@591F0000"}, | 797 | { SC_R_DMA_0_CH0, 0x59200000, 32, "/dma-controller@591F0000"}, |
798 | { SC_R_DMA_1_CH0, 0x59a00000, 32, "/dma-controller@599F0000"}, | 798 | { SC_R_DMA_1_CH0, 0x59a00000, 32, "/dma-controller@599F0000"}, |
799 | { SC_R_DMA_2_CH0, 0x5a200000, 5, "/dma-controller@5a1f0000"}, | 799 | { SC_R_DMA_2_CH0, 0x5a200000, 5, "/dma-controller@5a1f0000"}, |
800 | { SC_R_DMA_2_CH5, 0x5a250000, 27, "/dma-controller@5a1f0000"}, | 800 | { SC_R_DMA_2_CH5, 0x5a250000, 27, "/dma-controller@5a1f0000"}, |
801 | { SC_R_DMA_3_CH0, 0x5aa00000, 32, "/dma-controller@5a9f0000"}, | 801 | { SC_R_DMA_3_CH0, 0x5aa00000, 32, "/dma-controller@5a9f0000"}, |
802 | }; | 802 | }; |
803 | 803 | ||
804 | u32 i, j, edma_size; | 804 | u32 i, j, edma_size; |
805 | int nodeoff, ret; | 805 | int nodeoff, ret; |
806 | struct edma_ch_map *edma_array; | 806 | struct edma_ch_map *edma_array; |
807 | 807 | ||
808 | if (is_imx8qm()) { | 808 | if (is_imx8qm()) { |
809 | edma_array = edma_qm; | 809 | edma_array = edma_qm; |
810 | edma_size = ARRAY_SIZE(edma_qm); | 810 | edma_size = ARRAY_SIZE(edma_qm); |
811 | } else { | 811 | } else { |
812 | edma_array = edma_qxp; | 812 | edma_array = edma_qxp; |
813 | edma_size = ARRAY_SIZE(edma_qxp); | 813 | edma_size = ARRAY_SIZE(edma_qxp); |
814 | } | 814 | } |
815 | 815 | ||
816 | for (i = 0; i < edma_size; i++, edma_array++) { | 816 | for (i = 0; i < edma_size; i++, edma_array++) { |
817 | u32 regs[128]; | 817 | u32 regs[128]; |
818 | u32 interrupts[96]; | 818 | u32 interrupts[96]; |
819 | u32 dma_channels; | 819 | u32 dma_channels; |
820 | int regs_count, interrupts_count, int_names_count; | 820 | int regs_count, interrupts_count, int_names_count; |
821 | 821 | ||
822 | const char *list; | 822 | const char *list; |
823 | int list_len, newlist_len; | 823 | int list_len, newlist_len; |
824 | int remove[32]; | 824 | int remove[32]; |
825 | int remove_cnt = 0; | 825 | int remove_cnt = 0; |
826 | char * newlist; | 826 | char * newlist; |
827 | 827 | ||
828 | nodeoff = fdt_path_offset(blob, edma_array->node_path); | 828 | nodeoff = fdt_path_offset(blob, edma_array->node_path); |
829 | if (nodeoff < 0) | 829 | if (nodeoff < 0) |
830 | continue; /* Not found, skip it */ | 830 | continue; /* Not found, skip it */ |
831 | 831 | ||
832 | printf("%s, %d\n", edma_array->node_path, nodeoff); | 832 | printf("%s, %d\n", edma_array->node_path, nodeoff); |
833 | 833 | ||
834 | regs_count = fdtdec_get_int_array_count(blob, nodeoff, "reg", regs, 128); | 834 | regs_count = fdtdec_get_int_array_count(blob, nodeoff, "reg", regs, 128); |
835 | debug("regs_count %d\n", regs_count); | 835 | debug("regs_count %d\n", regs_count); |
836 | if (regs_count < 0) | 836 | if (regs_count < 0) |
837 | continue; | 837 | continue; |
838 | 838 | ||
839 | interrupts_count = fdtdec_get_int_array_count(blob, nodeoff, "interrupts", interrupts, 96); | 839 | interrupts_count = fdtdec_get_int_array_count(blob, nodeoff, "interrupts", interrupts, 96); |
840 | debug("interrupts_count %d\n", interrupts_count); | 840 | debug("interrupts_count %d\n", interrupts_count); |
841 | if (interrupts_count < 0) | 841 | if (interrupts_count < 0) |
842 | continue; | 842 | continue; |
843 | 843 | ||
844 | dma_channels = fdtdec_get_uint(blob, nodeoff, "dma-channels", 0); | 844 | dma_channels = fdtdec_get_uint(blob, nodeoff, "dma-channels", 0); |
845 | if (dma_channels == 0) | 845 | if (dma_channels == 0) |
846 | continue; | 846 | continue; |
847 | 847 | ||
848 | list = fdt_getprop(blob, nodeoff, "interrupt-names", &list_len); | 848 | list = fdt_getprop(blob, nodeoff, "interrupt-names", &list_len); |
849 | if (!list) | 849 | if (!list) |
850 | continue; | 850 | continue; |
851 | 851 | ||
852 | int_names_count = fdt_stringlist_count(blob, nodeoff, "interrupt-names"); | 852 | int_names_count = fdt_stringlist_count(blob, nodeoff, "interrupt-names"); |
853 | 853 | ||
854 | fdt_edma_debug_int_array(regs, regs_count, 4); | 854 | fdt_edma_debug_int_array(regs, regs_count, 4); |
855 | fdt_edma_debug_int_array(interrupts, interrupts_count, 3); | 855 | fdt_edma_debug_int_array(interrupts, interrupts_count, 3); |
856 | fdt_edma_debug_stringlist(list, list_len); | 856 | fdt_edma_debug_stringlist(list, list_len); |
857 | 857 | ||
858 | for (j = 0; j < (regs_count >> 2); j++) { | 858 | for (j = 0; j < (regs_count >> 2); j++) { |
859 | int ch_id = fdt_edma_get_channel_id(regs, j, edma_array); | 859 | int ch_id = fdt_edma_get_channel_id(regs, j, edma_array); |
860 | if (ch_id < 0) | 860 | if (ch_id < 0) |
861 | continue; | 861 | continue; |
862 | 862 | ||
863 | if (!check_owned_resource(edma_array->ch_start_rsrc + ch_id)) { | 863 | if (!check_owned_resource(edma_array->ch_start_rsrc + ch_id)) { |
864 | printf("remove edma items %d\n", j); | 864 | printf("remove edma items %d\n", j); |
865 | 865 | ||
866 | dma_channels--; | 866 | dma_channels--; |
867 | 867 | ||
868 | remove[remove_cnt] = j; | 868 | remove[remove_cnt] = j; |
869 | remove_cnt++; | 869 | remove_cnt++; |
870 | } | 870 | } |
871 | } | 871 | } |
872 | 872 | ||
873 | if (remove_cnt > 0) { | 873 | if (remove_cnt > 0) { |
874 | u32 new_regs[128]; | 874 | u32 new_regs[128]; |
875 | u32 new_interrupts[96]; | 875 | u32 new_interrupts[96]; |
876 | 876 | ||
877 | regs_count = fdt_edma_update_int_array(regs, regs_count, new_regs, 4, remove, remove_cnt); | 877 | regs_count = fdt_edma_update_int_array(regs, regs_count, new_regs, 4, remove, remove_cnt); |
878 | interrupts_count = fdt_edma_update_int_array(interrupts, interrupts_count, new_interrupts, 3, remove, remove_cnt); | 878 | interrupts_count = fdt_edma_update_int_array(interrupts, interrupts_count, new_interrupts, 3, remove, remove_cnt); |
879 | 879 | ||
880 | fdt_edma_debug_int_array(new_regs, regs_count, 4); | 880 | fdt_edma_debug_int_array(new_regs, regs_count, 4); |
881 | fdt_edma_debug_int_array(new_interrupts, interrupts_count, 3); | 881 | fdt_edma_debug_int_array(new_interrupts, interrupts_count, 3); |
882 | 882 | ||
883 | fdt_edma_swap_int_array(new_regs, regs_count); | 883 | fdt_edma_swap_int_array(new_regs, regs_count); |
884 | fdt_edma_swap_int_array(new_interrupts, interrupts_count); | 884 | fdt_edma_swap_int_array(new_interrupts, interrupts_count); |
885 | 885 | ||
886 | /* malloc a new string list */ | 886 | /* malloc a new string list */ |
887 | newlist = (char *)malloc(list_len); | 887 | newlist = (char *)malloc(list_len); |
888 | if (!newlist) { | 888 | if (!newlist) { |
889 | printf("malloc new string list failed, len=%d\n", list_len); | 889 | printf("malloc new string list failed, len=%d\n", list_len); |
890 | continue; | 890 | continue; |
891 | } | 891 | } |
892 | 892 | ||
893 | newlist_len = fdt_edma_update_stringlist(list, int_names_count, newlist, remove, remove_cnt); | 893 | newlist_len = fdt_edma_update_stringlist(list, int_names_count, newlist, remove, remove_cnt); |
894 | fdt_edma_debug_stringlist(newlist, newlist_len); | 894 | fdt_edma_debug_stringlist(newlist, newlist_len); |
895 | 895 | ||
896 | ret = fdt_setprop(blob, nodeoff, "reg", new_regs, regs_count * sizeof(u32)); | 896 | ret = fdt_setprop(blob, nodeoff, "reg", new_regs, regs_count * sizeof(u32)); |
897 | if (ret) | 897 | if (ret) |
898 | printf("fdt_setprop regs error %d\n", ret); | 898 | printf("fdt_setprop regs error %d\n", ret); |
899 | 899 | ||
900 | ret = fdt_setprop(blob, nodeoff, "interrupts", new_interrupts, interrupts_count * sizeof(u32)); | 900 | ret = fdt_setprop(blob, nodeoff, "interrupts", new_interrupts, interrupts_count * sizeof(u32)); |
901 | if (ret) | 901 | if (ret) |
902 | printf("fdt_setprop interrupts error %d\n", ret); | 902 | printf("fdt_setprop interrupts error %d\n", ret); |
903 | 903 | ||
904 | ret = fdt_setprop_u32(blob, nodeoff, "dma-channels", dma_channels); | 904 | ret = fdt_setprop_u32(blob, nodeoff, "dma-channels", dma_channels); |
905 | if (ret) | 905 | if (ret) |
906 | printf("fdt_setprop_u32 dma-channels error %d\n", ret); | 906 | printf("fdt_setprop_u32 dma-channels error %d\n", ret); |
907 | 907 | ||
908 | ret = fdt_setprop(blob, nodeoff, "interrupt-names", newlist, newlist_len); | 908 | ret = fdt_setprop(blob, nodeoff, "interrupt-names", newlist, newlist_len); |
909 | if (ret) | 909 | if (ret) |
910 | printf("fdt_setprop interrupt-names error %d\n", ret); | 910 | printf("fdt_setprop interrupt-names error %d\n", ret); |
911 | 911 | ||
912 | free(newlist); | 912 | free(newlist); |
913 | } | 913 | } |
914 | } | 914 | } |
915 | } | 915 | } |
916 | 916 | ||
917 | static void update_fdt_with_owned_resources(void *blob) | 917 | static void update_fdt_with_owned_resources(void *blob) |
918 | { | 918 | { |
919 | /* Traverses the fdt nodes, | 919 | /* Traverses the fdt nodes, |
920 | * check its power domain and use the resource id in the power domain | 920 | * check its power domain and use the resource id in the power domain |
921 | * for checking whether it is owned by current partition | 921 | * for checking whether it is owned by current partition |
922 | */ | 922 | */ |
923 | 923 | ||
924 | int offset = 0, next_off; | 924 | int offset = 0, next_off; |
925 | int depth = 0, next_depth; | 925 | int depth = 0, next_depth; |
926 | unsigned int rsrc_id; | 926 | unsigned int rsrc_id; |
927 | int rc; | 927 | int rc; |
928 | 928 | ||
929 | for (offset = fdt_next_node(blob, offset, &depth); offset > 0; | 929 | for (offset = fdt_next_node(blob, offset, &depth); offset > 0; |
930 | offset = fdt_next_node(blob, offset, &depth)) { | 930 | offset = fdt_next_node(blob, offset, &depth)) { |
931 | 931 | ||
932 | debug("Node name: %s, depth %d\n", fdt_get_name(blob, offset, NULL), depth); | 932 | debug("Node name: %s, depth %d\n", fdt_get_name(blob, offset, NULL), depth); |
933 | 933 | ||
934 | if (!fdtdec_get_is_enabled(blob, offset)) { | 934 | if (!fdtdec_get_is_enabled(blob, offset)) { |
935 | debug(" - ignoring disabled device\n"); | 935 | debug(" - ignoring disabled device\n"); |
936 | continue; | 936 | continue; |
937 | } | 937 | } |
938 | 938 | ||
939 | if (!fdt_node_check_compatible(blob, offset, "nxp,imx8-pd")) { | 939 | if (!fdt_node_check_compatible(blob, offset, "nxp,imx8-pd")) { |
940 | /* Skip to next depth=1 node*/ | 940 | /* Skip to next depth=1 node*/ |
941 | next_off = offset; | 941 | next_off = offset; |
942 | next_depth = depth; | 942 | next_depth = depth; |
943 | do { | 943 | do { |
944 | offset = next_off; | 944 | offset = next_off; |
945 | depth = next_depth; | 945 | depth = next_depth; |
946 | next_off = fdt_next_node(blob, offset, &next_depth); | 946 | next_off = fdt_next_node(blob, offset, &next_depth); |
947 | if (next_off < 0 || next_depth < 1) | 947 | if (next_off < 0 || next_depth < 1) |
948 | break; | 948 | break; |
949 | 949 | ||
950 | debug("PD name: %s, offset %d, depth %d\n", | 950 | debug("PD name: %s, offset %d, depth %d\n", |
951 | fdt_get_name(blob, next_off, NULL), next_off, next_depth); | 951 | fdt_get_name(blob, next_off, NULL), next_off, next_depth); |
952 | } while (next_depth > 1); | 952 | } while (next_depth > 1); |
953 | 953 | ||
954 | continue; | 954 | continue; |
955 | } | 955 | } |
956 | 956 | ||
957 | if (!check_owned_resources_in_pd_tree(blob, offset, &rsrc_id)) { | 957 | if (!check_owned_resources_in_pd_tree(blob, offset, &rsrc_id)) { |
958 | /* If the resource is not owned, disable it in FDT */ | 958 | /* If the resource is not owned, disable it in FDT */ |
959 | rc = disable_fdt_node(blob, offset); | 959 | rc = disable_fdt_node(blob, offset); |
960 | if (!rc) | 960 | if (!rc) |
961 | printf("Disable %s, resource id %u not owned\n", | 961 | printf("Disable %s, resource id %u not owned\n", |
962 | fdt_get_name(blob, offset, NULL), rsrc_id); | 962 | fdt_get_name(blob, offset, NULL), rsrc_id); |
963 | else | 963 | else |
964 | printf("Unable to disable %s, err=%s\n", | 964 | printf("Unable to disable %s, err=%s\n", |
965 | fdt_get_name(blob, offset, NULL), fdt_strerror(rc)); | 965 | fdt_get_name(blob, offset, NULL), fdt_strerror(rc)); |
966 | } | 966 | } |
967 | 967 | ||
968 | } | 968 | } |
969 | } | 969 | } |
970 | 970 | ||
971 | static void update_fdt_with_owned_resources_v2(void *blob) | 971 | static void update_fdt_with_owned_resources_v2(void *blob) |
972 | { | 972 | { |
973 | int count, i, ret, rc; | 973 | int count, i, ret, rc; |
974 | int offset = 0, depth = 0; | 974 | int offset = 0, depth = 0; |
975 | struct fdtdec_phandle_args args; | 975 | struct fdtdec_phandle_args args; |
976 | 976 | ||
977 | /* Check the new PD, if not find, continue with old PD tree */ | 977 | /* Check the new PD, if not find, continue with old PD tree */ |
978 | count = fdt_node_offset_by_compatible(blob, -1, "fsl,scu-pd"); | 978 | count = fdt_node_offset_by_compatible(blob, -1, "fsl,scu-pd"); |
979 | if (count < 0) | 979 | if (count < 0) |
980 | return update_fdt_with_owned_resources(blob); | 980 | return update_fdt_with_owned_resources(blob); |
981 | 981 | ||
982 | debug("Update FDT V2\n"); | 982 | debug("Update FDT V2\n"); |
983 | 983 | ||
984 | for (offset = fdt_next_node(blob, offset, &depth); offset > 0; | 984 | for (offset = fdt_next_node(blob, offset, &depth); offset > 0; |
985 | offset = fdt_next_node(blob, offset, &depth)) { | 985 | offset = fdt_next_node(blob, offset, &depth)) { |
986 | 986 | ||
987 | debug("Node name: %s, depth %d\n", fdt_get_name(blob, offset, NULL), depth); | 987 | debug("Node name: %s, depth %d\n", fdt_get_name(blob, offset, NULL), depth); |
988 | 988 | ||
989 | if (!fdtdec_get_is_enabled(blob, offset)) { | 989 | if (!fdtdec_get_is_enabled(blob, offset)) { |
990 | debug(" - ignoring disabled device\n"); | 990 | debug(" - ignoring disabled device\n"); |
991 | continue; | 991 | continue; |
992 | } | 992 | } |
993 | 993 | ||
994 | count = fdtdec_parse_phandle_with_args(blob, | 994 | count = fdtdec_parse_phandle_with_args(blob, |
995 | offset, | 995 | offset, |
996 | "power-domains", "#power-domain-cells", | 996 | "power-domains", "#power-domain-cells", |
997 | 0, -1, NULL); | 997 | 0, -1, NULL); |
998 | if (count < 1) { | 998 | if (count < 1) { |
999 | debug("no power-domains found\n"); | 999 | debug("no power-domains found\n"); |
1000 | continue; | 1000 | continue; |
1001 | } | 1001 | } |
1002 | 1002 | ||
1003 | debug("count %d\n", count); | 1003 | debug("count %d\n", count); |
1004 | 1004 | ||
1005 | for (i = 0; i < count; i++) { | 1005 | for (i = 0; i < count; i++) { |
1006 | ret = fdtdec_parse_phandle_with_args(blob, | 1006 | ret = fdtdec_parse_phandle_with_args(blob, |
1007 | offset, | 1007 | offset, |
1008 | "power-domains", "#power-domain-cells", | 1008 | "power-domains", "#power-domain-cells", |
1009 | 0, i, &args); | 1009 | 0, i, &args); |
1010 | 1010 | ||
1011 | if (ret) { | 1011 | if (ret) { |
1012 | debug("Error in parsing power-domains\n"); | 1012 | debug("Error in parsing power-domains\n"); |
1013 | continue; | 1013 | continue; |
1014 | } | 1014 | } |
1015 | 1015 | ||
1016 | debug("check resource id %u\n", args.args[0]); | 1016 | debug("check resource id %u\n", args.args[0]); |
1017 | 1017 | ||
1018 | if (!check_owned_resource(args.args[0])) { | 1018 | if (!check_owned_resource(args.args[0])) { |
1019 | /* If the resource is not owned, disable it in FDT */ | 1019 | /* If the resource is not owned, disable it in FDT */ |
1020 | rc = disable_fdt_node(blob, offset); | 1020 | rc = disable_fdt_node(blob, offset); |
1021 | if (!rc) | 1021 | if (!rc) |
1022 | printf("Disable %s, resource id %u not owned\n", | 1022 | printf("Disable %s, resource id %u not owned\n", |
1023 | fdt_get_name(blob, offset, NULL), args.args[0]); | 1023 | fdt_get_name(blob, offset, NULL), args.args[0]); |
1024 | else | 1024 | else |
1025 | printf("Unable to disable %s, err=%s\n", | 1025 | printf("Unable to disable %s, err=%s\n", |
1026 | fdt_get_name(blob, offset, NULL), fdt_strerror(rc)); | 1026 | fdt_get_name(blob, offset, NULL), fdt_strerror(rc)); |
1027 | } | 1027 | } |
1028 | 1028 | ||
1029 | } | 1029 | } |
1030 | } | 1030 | } |
1031 | } | 1031 | } |
1032 | 1032 | ||
1033 | #ifdef CONFIG_IMX_SMMU | 1033 | #ifdef CONFIG_IMX_SMMU |
1034 | static int get_srsc_from_fdt_node_power_domain(void *blob, int device_offset, int index) | 1034 | static int get_srsc_from_fdt_node_power_domain(void *blob, int device_offset, int index) |
1035 | { | 1035 | { |
1036 | const fdt32_t *prop; | 1036 | const fdt32_t *prop; |
1037 | int pdnode_offset; | 1037 | int pdnode_offset; |
1038 | int ret; | 1038 | int ret; |
1039 | struct fdtdec_phandle_args args; | 1039 | struct fdtdec_phandle_args args; |
1040 | 1040 | ||
1041 | prop = fdt_getprop(blob, device_offset, "power-domains", NULL); | 1041 | prop = fdt_getprop(blob, device_offset, "power-domains", NULL); |
1042 | if (!prop) { | 1042 | if (!prop) { |
1043 | debug("node %s has no power-domains\n", | 1043 | debug("node %s has no power-domains\n", |
1044 | fdt_get_name(blob, device_offset, NULL)); | 1044 | fdt_get_name(blob, device_offset, NULL)); |
1045 | return -ENOENT; | 1045 | return -ENOENT; |
1046 | } | 1046 | } |
1047 | 1047 | ||
1048 | pdnode_offset = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*prop)); | 1048 | pdnode_offset = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*prop)); |
1049 | if (pdnode_offset < 0) { | 1049 | if (pdnode_offset < 0) { |
1050 | pr_err("failed to fetch node %s power-domain", | 1050 | pr_err("failed to fetch node %s power-domain", |
1051 | fdt_get_name(blob, device_offset, NULL)); | 1051 | fdt_get_name(blob, device_offset, NULL)); |
1052 | return pdnode_offset; | 1052 | return pdnode_offset; |
1053 | } | 1053 | } |
1054 | 1054 | ||
1055 | ret = fdtdec_get_uint(blob, pdnode_offset, "reg", -ENOENT); | 1055 | ret = fdtdec_get_uint(blob, pdnode_offset, "reg", -ENOENT); |
1056 | if (ret != -ENOENT) | 1056 | if (ret != -ENOENT) |
1057 | return ret; | 1057 | return ret; |
1058 | 1058 | ||
1059 | ret = fdtdec_parse_phandle_with_args(blob, device_offset, | 1059 | ret = fdtdec_parse_phandle_with_args(blob, device_offset, |
1060 | "power-domains", | 1060 | "power-domains", |
1061 | "#power-domain-cells", 0, index, | 1061 | "#power-domain-cells", 0, index, |
1062 | &args); | 1062 | &args); |
1063 | if (ret) | 1063 | if (ret) |
1064 | return ret; | 1064 | return ret; |
1065 | return args.args[0]; | 1065 | return args.args[0]; |
1066 | } | 1066 | } |
1067 | 1067 | ||
1068 | static int config_smmu_resource_sid(int rsrc, int sid) | 1068 | static int config_smmu_resource_sid(int rsrc, int sid) |
1069 | { | 1069 | { |
1070 | int err; | 1070 | int err; |
1071 | 1071 | ||
1072 | if (!check_owned_resource(rsrc)) { | 1072 | if (!check_owned_resource(rsrc)) { |
1073 | printf("%s rsrc[%d] not owned\n", __func__, rsrc); | 1073 | printf("%s rsrc[%d] not owned\n", __func__, rsrc); |
1074 | return -1; | 1074 | return -1; |
1075 | } | 1075 | } |
1076 | err = sc_rm_set_master_sid(-1, rsrc, sid); | 1076 | err = sc_rm_set_master_sid(-1, rsrc, sid); |
1077 | debug("set_master_sid rsrc=%d sid=0x%x err=%d\n", rsrc, sid, err); | 1077 | debug("set_master_sid rsrc=%d sid=0x%x err=%d\n", rsrc, sid, err); |
1078 | if (err != SC_ERR_NONE) { | 1078 | if (err != SC_ERR_NONE) { |
1079 | pr_err("fail set_master_sid rsrc=%d sid=0x%x err=%d\n", rsrc, sid, err); | 1079 | pr_err("fail set_master_sid rsrc=%d sid=0x%x err=%d\n", rsrc, sid, err); |
1080 | return -EINVAL; | 1080 | return -EINVAL; |
1081 | } | 1081 | } |
1082 | 1082 | ||
1083 | return 0; | 1083 | return 0; |
1084 | } | 1084 | } |
1085 | 1085 | ||
1086 | static int config_smmu_fdt_device_sid(void *blob, int device_offset, int sid) | 1086 | static int config_smmu_fdt_device_sid(void *blob, int device_offset, int sid) |
1087 | { | 1087 | { |
1088 | int rsrc; | 1088 | int rsrc; |
1089 | int proplen; | 1089 | int proplen; |
1090 | int i, count; | 1090 | int i, count; |
1091 | const fdt32_t *prop; | 1091 | const fdt32_t *prop; |
1092 | const char *name = fdt_get_name(blob, device_offset, NULL); | 1092 | const char *name = fdt_get_name(blob, device_offset, NULL); |
1093 | 1093 | ||
1094 | prop = fdt_getprop(blob, device_offset, "fsl,sc_rsrc_id", &proplen); | 1094 | prop = fdt_getprop(blob, device_offset, "fsl,sc_rsrc_id", &proplen); |
1095 | if (prop) { | 1095 | if (prop) { |
1096 | int i; | 1096 | int i; |
1097 | 1097 | ||
1098 | debug("configure node %s sid 0x%x for %d resources\n", | 1098 | debug("configure node %s sid 0x%x for %d resources\n", |
1099 | name, sid, (int)(proplen / sizeof(fdt32_t))); | 1099 | name, sid, (int)(proplen / sizeof(fdt32_t))); |
1100 | for (i = 0; i < proplen / sizeof(fdt32_t); ++i) { | 1100 | for (i = 0; i < proplen / sizeof(fdt32_t); ++i) { |
1101 | config_smmu_resource_sid(fdt32_to_cpu(prop[i]), sid); | 1101 | config_smmu_resource_sid(fdt32_to_cpu(prop[i]), sid); |
1102 | } | 1102 | } |
1103 | 1103 | ||
1104 | return 0; | 1104 | return 0; |
1105 | } | 1105 | } |
1106 | 1106 | ||
1107 | count = fdtdec_parse_phandle_with_args(blob, device_offset, | 1107 | count = fdtdec_parse_phandle_with_args(blob, device_offset, |
1108 | "power-domains", | 1108 | "power-domains", |
1109 | "#power-domain-cells", | 1109 | "#power-domain-cells", |
1110 | 0, -1, NULL); | 1110 | 0, -1, NULL); |
1111 | for (i = 0; i < count; i++) { | 1111 | for (i = 0; i < count; i++) { |
1112 | rsrc = get_srsc_from_fdt_node_power_domain(blob, device_offset, i); | 1112 | rsrc = get_srsc_from_fdt_node_power_domain(blob, device_offset, i); |
1113 | debug("configure node %s sid 0x%x rsrc=%d\n", name, sid, rsrc); | 1113 | debug("configure node %s sid 0x%x rsrc=%d\n", name, sid, rsrc); |
1114 | if (rsrc < 0) { | 1114 | if (rsrc < 0) { |
1115 | debug("failed to determine SC_R_* for node %s\n", name); | 1115 | debug("failed to determine SC_R_* for node %s\n", name); |
1116 | return rsrc; | 1116 | return rsrc; |
1117 | } | 1117 | } |
1118 | 1118 | ||
1119 | config_smmu_resource_sid(rsrc, sid); | 1119 | config_smmu_resource_sid(rsrc, sid); |
1120 | } | 1120 | } |
1121 | 1121 | ||
1122 | return 0; | 1122 | return 0; |
1123 | } | 1123 | } |
1124 | 1124 | ||
1125 | /* assign master sid based on iommu properties in fdt */ | 1125 | /* assign master sid based on iommu properties in fdt */ |
1126 | static int config_smmu_fdt(void *blob) | 1126 | static int config_smmu_fdt(void *blob) |
1127 | { | 1127 | { |
1128 | int offset, proplen, i; | 1128 | int offset, proplen, i; |
1129 | const fdt32_t *prop; | 1129 | const fdt32_t *prop; |
1130 | const char *name; | 1130 | const char *name; |
1131 | 1131 | ||
1132 | /* Legacy smmu bindings, still used by xen. */ | 1132 | /* Legacy smmu bindings, still used by xen. */ |
1133 | offset = fdt_node_offset_by_compatible(blob, 0, "arm,mmu-500"); | 1133 | offset = fdt_node_offset_by_compatible(blob, 0, "arm,mmu-500"); |
1134 | if (offset > 0 && (prop = fdt_getprop(blob, offset, "mmu-masters", &proplen))) | 1134 | if (offset > 0 && (prop = fdt_getprop(blob, offset, "mmu-masters", &proplen))) |
1135 | { | 1135 | { |
1136 | debug("found legacy mmu-masters property\n"); | 1136 | debug("found legacy mmu-masters property\n"); |
1137 | 1137 | ||
1138 | for (i = 0; i < proplen / 8; ++i) { | 1138 | for (i = 0; i < proplen / 8; ++i) { |
1139 | uint32_t phandle = fdt32_to_cpu(prop[2 * i]); | 1139 | uint32_t phandle = fdt32_to_cpu(prop[2 * i]); |
1140 | int sid = fdt32_to_cpu(prop[2 * i + 1]); | 1140 | int sid = fdt32_to_cpu(prop[2 * i + 1]); |
1141 | int device_offset; | 1141 | int device_offset; |
1142 | 1142 | ||
1143 | device_offset = fdt_node_offset_by_phandle(blob, phandle); | 1143 | device_offset = fdt_node_offset_by_phandle(blob, phandle); |
1144 | if (device_offset < 0) { | 1144 | if (device_offset < 0) { |
1145 | pr_err("Failed to fetch device reference from mmu_masters: %d", device_offset); | 1145 | pr_err("Failed to fetch device reference from mmu_masters: %d", device_offset); |
1146 | continue; | 1146 | continue; |
1147 | } | 1147 | } |
1148 | config_smmu_fdt_device_sid(blob, device_offset, sid); | 1148 | config_smmu_fdt_device_sid(blob, device_offset, sid); |
1149 | } | 1149 | } |
1150 | 1150 | ||
1151 | /* Ignore new bindings if old bindings found, just like linux. */ | 1151 | /* Ignore new bindings if old bindings found, just like linux. */ |
1152 | return 0; | 1152 | return 0; |
1153 | } | 1153 | } |
1154 | 1154 | ||
1155 | /* Generic smmu bindings */ | 1155 | /* Generic smmu bindings */ |
1156 | offset = 0; | 1156 | offset = 0; |
1157 | while ((offset = fdt_next_node(blob, offset, NULL)) > 0) | 1157 | while ((offset = fdt_next_node(blob, offset, NULL)) > 0) |
1158 | { | 1158 | { |
1159 | name = fdt_get_name(blob, offset, NULL); | 1159 | name = fdt_get_name(blob, offset, NULL); |
1160 | prop = fdt_getprop(blob, offset, "iommus", &proplen); | 1160 | prop = fdt_getprop(blob, offset, "iommus", &proplen); |
1161 | if (!prop) | 1161 | if (!prop) |
1162 | continue; | 1162 | continue; |
1163 | debug("node %s iommus proplen %d\n", name, proplen); | 1163 | debug("node %s iommus proplen %d\n", name, proplen); |
1164 | 1164 | ||
1165 | if (proplen == 12) { | 1165 | if (proplen == 12) { |
1166 | int sid = fdt32_to_cpu(prop[1]); | 1166 | int sid = fdt32_to_cpu(prop[1]); |
1167 | config_smmu_fdt_device_sid(blob, offset, sid); | 1167 | config_smmu_fdt_device_sid(blob, offset, sid); |
1168 | } else if (proplen != 4) { | 1168 | } else if (proplen != 4) { |
1169 | debug("node %s ignore unexpected iommus proplen=%d\n", name, proplen); | 1169 | debug("node %s ignore unexpected iommus proplen=%d\n", name, proplen); |
1170 | } | 1170 | } |
1171 | } | 1171 | } |
1172 | 1172 | ||
1173 | return 0; | 1173 | return 0; |
1174 | } | 1174 | } |
1175 | #endif | 1175 | #endif |
1176 | 1176 | ||
1177 | #ifdef CONFIG_OF_SYSTEM_SETUP | 1177 | #ifdef CONFIG_OF_SYSTEM_SETUP |
1178 | static int ft_add_optee_node(void *fdt, bd_t *bd) | 1178 | static int ft_add_optee_node(void *fdt, bd_t *bd) |
1179 | { | 1179 | { |
1180 | const char *path, *subpath; | 1180 | const char *path, *subpath; |
1181 | int offs; | 1181 | int offs; |
1182 | 1182 | ||
1183 | /* | 1183 | /* |
1184 | * No TEE space allocated indicating no TEE running, so no | 1184 | * No TEE space allocated indicating no TEE running, so no |
1185 | * need to add optee node in dts | 1185 | * need to add optee node in dts |
1186 | */ | 1186 | */ |
1187 | if (!rom_pointer[1]) | 1187 | if (!rom_pointer[1]) |
1188 | return 0; | 1188 | return 0; |
1189 | 1189 | ||
1190 | offs = fdt_increase_size(fdt, 512); | 1190 | offs = fdt_increase_size(fdt, 512); |
1191 | if (offs) { | 1191 | if (offs) { |
1192 | printf("No Space for dtb\n"); | 1192 | printf("No Space for dtb\n"); |
1193 | return 1; | 1193 | return 1; |
1194 | } | 1194 | } |
1195 | 1195 | ||
1196 | path = "/firmware"; | 1196 | path = "/firmware"; |
1197 | offs = fdt_path_offset(fdt, path); | 1197 | offs = fdt_path_offset(fdt, path); |
1198 | if (offs < 0) { | 1198 | if (offs < 0) { |
1199 | path = "/"; | 1199 | path = "/"; |
1200 | offs = fdt_path_offset(fdt, path); | 1200 | offs = fdt_path_offset(fdt, path); |
1201 | 1201 | ||
1202 | if (offs < 0) { | 1202 | if (offs < 0) { |
1203 | printf("Could not find root node.\n"); | 1203 | printf("Could not find root node.\n"); |
1204 | return 1; | 1204 | return 1; |
1205 | } | 1205 | } |
1206 | 1206 | ||
1207 | subpath = "firmware"; | 1207 | subpath = "firmware"; |
1208 | offs = fdt_add_subnode(fdt, offs, subpath); | 1208 | offs = fdt_add_subnode(fdt, offs, subpath); |
1209 | if (offs < 0) { | 1209 | if (offs < 0) { |
1210 | printf("Could not create %s node.\n", subpath); | 1210 | printf("Could not create %s node.\n", subpath); |
1211 | } | 1211 | } |
1212 | } | 1212 | } |
1213 | 1213 | ||
1214 | subpath = "optee"; | 1214 | subpath = "optee"; |
1215 | offs = fdt_add_subnode(fdt, offs, subpath); | 1215 | offs = fdt_add_subnode(fdt, offs, subpath); |
1216 | if (offs < 0) { | 1216 | if (offs < 0) { |
1217 | printf("Could not create %s node.\n", subpath); | 1217 | printf("Could not create %s node.\n", subpath); |
1218 | } | 1218 | } |
1219 | 1219 | ||
1220 | fdt_setprop_string(fdt, offs, "compatible", "linaro,optee-tz"); | 1220 | fdt_setprop_string(fdt, offs, "compatible", "linaro,optee-tz"); |
1221 | fdt_setprop_string(fdt, offs, "method", "smc"); | 1221 | fdt_setprop_string(fdt, offs, "method", "smc"); |
1222 | 1222 | ||
1223 | return 0; | 1223 | return 0; |
1224 | } | 1224 | } |
1225 | 1225 | ||
1226 | int ft_system_setup(void *blob, bd_t *bd) | 1226 | int ft_system_setup(void *blob, bd_t *bd) |
1227 | { | 1227 | { |
1228 | #if (CONFIG_BOOTAUX_RESERVED_MEM_SIZE != 0x00) | 1228 | #if (CONFIG_BOOTAUX_RESERVED_MEM_SIZE != 0x00) |
1229 | int off; | 1229 | int off; |
1230 | off = fdt_add_mem_rsv(blob, CONFIG_BOOTAUX_RESERVED_MEM_BASE, | 1230 | off = fdt_add_mem_rsv(blob, CONFIG_BOOTAUX_RESERVED_MEM_BASE, |
1231 | CONFIG_BOOTAUX_RESERVED_MEM_SIZE); | 1231 | CONFIG_BOOTAUX_RESERVED_MEM_SIZE); |
1232 | if (off < 0) | 1232 | if (off < 0) |
1233 | printf("Failed to reserve memory for bootaux: %s\n", | 1233 | printf("Failed to reserve memory for bootaux: %s\n", |
1234 | fdt_strerror(off)); | 1234 | fdt_strerror(off)); |
1235 | #endif | 1235 | #endif |
1236 | 1236 | ||
1237 | #ifndef CONFIG_SKIP_RESOURCE_CHECKING | 1237 | #ifndef CONFIG_SKIP_RESOURCE_CHECKING |
1238 | update_fdt_with_owned_resources_v2(blob); | 1238 | update_fdt_with_owned_resources_v2(blob); |
1239 | #endif | 1239 | #endif |
1240 | 1240 | ||
1241 | update_fdt_edma_nodes(blob); | 1241 | update_fdt_edma_nodes(blob); |
1242 | #ifdef CONFIG_IMX_SMMU | 1242 | #ifdef CONFIG_IMX_SMMU |
1243 | config_smmu_fdt(blob); | 1243 | config_smmu_fdt(blob); |
1244 | #endif | 1244 | #endif |
1245 | 1245 | ||
1246 | ft_add_optee_node(blob, bd); | 1246 | ft_add_optee_node(blob, bd); |
1247 | return 0; | 1247 | return 0; |
1248 | } | 1248 | } |
1249 | #endif | 1249 | #endif |
1250 | 1250 | ||
1251 | #define MEMSTART_ALIGNMENT SZ_2M /* Align the memory start with 2MB */ | 1251 | #define MEMSTART_ALIGNMENT SZ_2M /* Align the memory start with 2MB */ |
1252 | 1252 | ||
1253 | static sc_faddr_t reserve_optee_shm(sc_faddr_t addr_start) | ||
1254 | { | ||
1255 | /* OPTEE has a share memory at its top address, | ||
1256 | * ATF assigns the share memory to non-secure os partition for share with kernel | ||
1257 | * We should not add this share memory to DDR bank, as this memory is dedicated for | ||
1258 | * optee, optee driver will memremap it and can't be used by system malloc. | ||
1259 | */ | ||
1260 | |||
1261 | sc_faddr_t optee_start = rom_pointer[0]; | ||
1262 | sc_faddr_t optee_size = rom_pointer[1]; | ||
1263 | |||
1264 | if (optee_size && optee_start <= addr_start && | ||
1265 | addr_start < optee_start + optee_size) { | ||
1266 | debug("optee 0x%llx 0x%llx, addr_start 0x%llx\n", | ||
1267 | optee_start, optee_size, addr_start); | ||
1268 | return optee_start + optee_size; | ||
1269 | } | ||
1270 | |||
1271 | return addr_start; | ||
1272 | } | ||
1273 | |||
1253 | static int get_owned_memreg(sc_rm_mr_t mr, sc_faddr_t *addr_start, | 1274 | static int get_owned_memreg(sc_rm_mr_t mr, sc_faddr_t *addr_start, |
1254 | sc_faddr_t *addr_end) | 1275 | sc_faddr_t *addr_end) |
1255 | { | 1276 | { |
1256 | sc_faddr_t start, end; | 1277 | sc_faddr_t start, end; |
1257 | int ret; | 1278 | int ret; |
1258 | bool owned; | 1279 | bool owned; |
1259 | 1280 | ||
1260 | owned = sc_rm_is_memreg_owned(-1, mr); | 1281 | owned = sc_rm_is_memreg_owned(-1, mr); |
1261 | if (owned) { | 1282 | if (owned) { |
1262 | ret = sc_rm_get_memreg_info(-1, mr, &start, &end); | 1283 | ret = sc_rm_get_memreg_info(-1, mr, &start, &end); |
1263 | if (ret) { | 1284 | if (ret) { |
1264 | printf("Memreg get info failed, %d\n", ret); | 1285 | printf("Memreg get info failed, %d\n", ret); |
1265 | return -EINVAL; | 1286 | return -EINVAL; |
1266 | } | 1287 | } |
1267 | debug("0x%llx -- 0x%llx\n", start, end); | 1288 | debug("0x%llx -- 0x%llx\n", start, end); |
1268 | *addr_start = start; | 1289 | *addr_start = reserve_optee_shm(start); |
1269 | *addr_end = end; | 1290 | *addr_end = end; |
1270 | 1291 | ||
1271 | return 0; | 1292 | return 0; |
1272 | } | 1293 | } |
1273 | 1294 | ||
1274 | return -EINVAL; | 1295 | return -EINVAL; |
1275 | } | 1296 | } |
1276 | 1297 | ||
1277 | phys_size_t get_effective_memsize(void) | 1298 | phys_size_t get_effective_memsize(void) |
1278 | { | 1299 | { |
1279 | sc_rm_mr_t mr; | 1300 | sc_rm_mr_t mr; |
1280 | sc_faddr_t start, end, end1, start_aligned; | 1301 | sc_faddr_t start, end, end1, start_aligned; |
1281 | int err; | 1302 | int err; |
1282 | 1303 | ||
1283 | end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE; | 1304 | end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE; |
1284 | 1305 | ||
1285 | for (mr = 0; mr < 64; mr++) { | 1306 | for (mr = 0; mr < 64; mr++) { |
1286 | err = get_owned_memreg(mr, &start, &end); | 1307 | err = get_owned_memreg(mr, &start, &end); |
1287 | if (!err) { | 1308 | if (!err) { |
1288 | start_aligned = roundup(start, MEMSTART_ALIGNMENT); | 1309 | start_aligned = roundup(start, MEMSTART_ALIGNMENT); |
1289 | /* Too small memory region, not use it */ | 1310 | /* Too small memory region, not use it */ |
1290 | if (start_aligned > end) | 1311 | if (start_aligned > end) |
1291 | continue; | 1312 | continue; |
1292 | 1313 | ||
1293 | /* Find the memory region runs the U-Boot */ | 1314 | /* Find the memory region runs the U-Boot */ |
1294 | if (start >= PHYS_SDRAM_1 && start <= end1 && | 1315 | if (start >= PHYS_SDRAM_1 && start <= end1 && |
1295 | (start <= CONFIG_SYS_TEXT_BASE && | 1316 | (start <= CONFIG_SYS_TEXT_BASE && |
1296 | end >= CONFIG_SYS_TEXT_BASE)) { | 1317 | end >= CONFIG_SYS_TEXT_BASE)) { |
1297 | if ((end + 1) <= ((sc_faddr_t)PHYS_SDRAM_1 + | 1318 | if ((end + 1) <= ((sc_faddr_t)PHYS_SDRAM_1 + |
1298 | PHYS_SDRAM_1_SIZE)) | 1319 | PHYS_SDRAM_1_SIZE)) |
1299 | return (end - PHYS_SDRAM_1 + 1); | 1320 | return (end - PHYS_SDRAM_1 + 1); |
1300 | else | 1321 | else |
1301 | return PHYS_SDRAM_1_SIZE; | 1322 | return PHYS_SDRAM_1_SIZE; |
1302 | } | 1323 | } |
1303 | } | 1324 | } |
1304 | } | 1325 | } |
1305 | 1326 | ||
1306 | return PHYS_SDRAM_1_SIZE; | 1327 | return PHYS_SDRAM_1_SIZE; |
1307 | } | 1328 | } |
1308 | 1329 | ||
1309 | int dram_init(void) | 1330 | int dram_init(void) |
1310 | { | 1331 | { |
1311 | sc_rm_mr_t mr; | 1332 | sc_rm_mr_t mr; |
1312 | sc_faddr_t start, end, end1, end2; | 1333 | sc_faddr_t start, end, end1, end2; |
1313 | int err; | 1334 | int err; |
1314 | 1335 | ||
1315 | end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE; | 1336 | end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE; |
1316 | end2 = (sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE; | 1337 | end2 = (sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE; |
1317 | for (mr = 0; mr < 64; mr++) { | 1338 | for (mr = 0; mr < 64; mr++) { |
1318 | err = get_owned_memreg(mr, &start, &end); | 1339 | err = get_owned_memreg(mr, &start, &end); |
1319 | if (!err) { | 1340 | if (!err) { |
1320 | start = roundup(start, MEMSTART_ALIGNMENT); | 1341 | start = roundup(start, MEMSTART_ALIGNMENT); |
1321 | /* Too small memory region, not use it */ | 1342 | /* Too small memory region, not use it */ |
1322 | if (start > end) | 1343 | if (start > end) |
1323 | continue; | 1344 | continue; |
1324 | 1345 | ||
1325 | if (start >= PHYS_SDRAM_1 && start <= end1) { | 1346 | if (start >= PHYS_SDRAM_1 && start <= end1) { |
1326 | if ((end + 1) <= end1) | 1347 | if ((end + 1) <= end1) |
1327 | gd->ram_size += end - start + 1; | 1348 | gd->ram_size += end - start + 1; |
1328 | else | 1349 | else |
1329 | gd->ram_size += end1 - start; | 1350 | gd->ram_size += end1 - start; |
1330 | } else if (start >= PHYS_SDRAM_2 && start <= end2) { | 1351 | } else if (start >= PHYS_SDRAM_2 && start <= end2) { |
1331 | if ((end + 1) <= end2) | 1352 | if ((end + 1) <= end2) |
1332 | gd->ram_size += end - start + 1; | 1353 | gd->ram_size += end - start + 1; |
1333 | else | 1354 | else |
1334 | gd->ram_size += end2 - start; | 1355 | gd->ram_size += end2 - start; |
1335 | } | 1356 | } |
1336 | } | 1357 | } |
1337 | } | 1358 | } |
1338 | 1359 | ||
1339 | /* If error, set to the default value */ | 1360 | /* If error, set to the default value */ |
1340 | if (!gd->ram_size) { | 1361 | if (!gd->ram_size) { |
1341 | gd->ram_size = PHYS_SDRAM_1_SIZE; | 1362 | gd->ram_size = PHYS_SDRAM_1_SIZE; |
1342 | gd->ram_size += PHYS_SDRAM_2_SIZE; | 1363 | gd->ram_size += PHYS_SDRAM_2_SIZE; |
1343 | } | 1364 | } |
1344 | return 0; | 1365 | return 0; |
1345 | } | 1366 | } |
1346 | 1367 | ||
1347 | static void dram_bank_sort(int current_bank) | 1368 | static void dram_bank_sort(int current_bank) |
1348 | { | 1369 | { |
1349 | phys_addr_t start; | 1370 | phys_addr_t start; |
1350 | phys_size_t size; | 1371 | phys_size_t size; |
1351 | 1372 | ||
1352 | while (current_bank > 0) { | 1373 | while (current_bank > 0) { |
1353 | if (gd->bd->bi_dram[current_bank - 1].start > | 1374 | if (gd->bd->bi_dram[current_bank - 1].start > |
1354 | gd->bd->bi_dram[current_bank].start) { | 1375 | gd->bd->bi_dram[current_bank].start) { |
1355 | start = gd->bd->bi_dram[current_bank - 1].start; | 1376 | start = gd->bd->bi_dram[current_bank - 1].start; |
1356 | size = gd->bd->bi_dram[current_bank - 1].size; | 1377 | size = gd->bd->bi_dram[current_bank - 1].size; |
1357 | 1378 | ||
1358 | gd->bd->bi_dram[current_bank - 1].start = | 1379 | gd->bd->bi_dram[current_bank - 1].start = |
1359 | gd->bd->bi_dram[current_bank].start; | 1380 | gd->bd->bi_dram[current_bank].start; |
1360 | gd->bd->bi_dram[current_bank - 1].size = | 1381 | gd->bd->bi_dram[current_bank - 1].size = |
1361 | gd->bd->bi_dram[current_bank].size; | 1382 | gd->bd->bi_dram[current_bank].size; |
1362 | 1383 | ||
1363 | gd->bd->bi_dram[current_bank].start = start; | 1384 | gd->bd->bi_dram[current_bank].start = start; |
1364 | gd->bd->bi_dram[current_bank].size = size; | 1385 | gd->bd->bi_dram[current_bank].size = size; |
1365 | } | 1386 | } |
1366 | current_bank--; | 1387 | current_bank--; |
1367 | } | 1388 | } |
1368 | } | 1389 | } |
1369 | 1390 | ||
1370 | int dram_init_banksize(void) | 1391 | int dram_init_banksize(void) |
1371 | { | 1392 | { |
1372 | sc_rm_mr_t mr; | 1393 | sc_rm_mr_t mr; |
1373 | sc_faddr_t start, end, end1, end2; | 1394 | sc_faddr_t start, end, end1, end2; |
1374 | int i = 0; | 1395 | int i = 0; |
1375 | int err; | 1396 | int err; |
1376 | 1397 | ||
1377 | end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE; | 1398 | end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE; |
1378 | end2 = (sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE; | 1399 | end2 = (sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE; |
1379 | 1400 | ||
1380 | for (mr = 0; mr < 64 && i < CONFIG_NR_DRAM_BANKS; mr++) { | 1401 | for (mr = 0; mr < 64 && i < CONFIG_NR_DRAM_BANKS; mr++) { |
1381 | err = get_owned_memreg(mr, &start, &end); | 1402 | err = get_owned_memreg(mr, &start, &end); |
1382 | if (!err) { | 1403 | if (!err) { |
1383 | start = roundup(start, MEMSTART_ALIGNMENT); | 1404 | start = roundup(start, MEMSTART_ALIGNMENT); |
1384 | if (start > end) /* Small memory region, no use it */ | 1405 | if (start > end) /* Small memory region, no use it */ |
1385 | continue; | 1406 | continue; |
1386 | 1407 | ||
1387 | if (start >= PHYS_SDRAM_1 && start <= end1) { | 1408 | if (start >= PHYS_SDRAM_1 && start <= end1) { |
1388 | gd->bd->bi_dram[i].start = start; | 1409 | gd->bd->bi_dram[i].start = start; |
1389 | 1410 | ||
1390 | if ((end + 1) <= end1) | 1411 | if ((end + 1) <= end1) |
1391 | gd->bd->bi_dram[i].size = | 1412 | gd->bd->bi_dram[i].size = |
1392 | end - start + 1; | 1413 | end - start + 1; |
1393 | else | 1414 | else |
1394 | gd->bd->bi_dram[i].size = end1 - start; | 1415 | gd->bd->bi_dram[i].size = end1 - start; |
1395 | 1416 | ||
1396 | dram_bank_sort(i); | 1417 | dram_bank_sort(i); |
1397 | i++; | 1418 | i++; |
1398 | } else if (start >= PHYS_SDRAM_2 && start <= end2) { | 1419 | } else if (start >= PHYS_SDRAM_2 && start <= end2) { |
1399 | gd->bd->bi_dram[i].start = start; | 1420 | gd->bd->bi_dram[i].start = start; |
1400 | 1421 | ||
1401 | if ((end + 1) <= end2) | 1422 | if ((end + 1) <= end2) |
1402 | gd->bd->bi_dram[i].size = | 1423 | gd->bd->bi_dram[i].size = |
1403 | end - start + 1; | 1424 | end - start + 1; |
1404 | else | 1425 | else |
1405 | gd->bd->bi_dram[i].size = end2 - start; | 1426 | gd->bd->bi_dram[i].size = end2 - start; |
1406 | 1427 | ||
1407 | dram_bank_sort(i); | 1428 | dram_bank_sort(i); |
1408 | i++; | 1429 | i++; |
1409 | } | 1430 | } |
1410 | } | 1431 | } |
1411 | } | 1432 | } |
1412 | 1433 | ||
1413 | /* If error, set to the default value */ | 1434 | /* If error, set to the default value */ |
1414 | if (!i) { | 1435 | if (!i) { |
1415 | gd->bd->bi_dram[0].start = PHYS_SDRAM_1; | 1436 | gd->bd->bi_dram[0].start = PHYS_SDRAM_1; |
1416 | gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; | 1437 | gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; |
1417 | gd->bd->bi_dram[1].start = PHYS_SDRAM_2; | 1438 | gd->bd->bi_dram[1].start = PHYS_SDRAM_2; |
1418 | gd->bd->bi_dram[1].size = PHYS_SDRAM_2_SIZE; | 1439 | gd->bd->bi_dram[1].size = PHYS_SDRAM_2_SIZE; |
1419 | } | 1440 | } |
1420 | 1441 | ||
1421 | return 0; | 1442 | return 0; |
1422 | } | 1443 | } |
1423 | 1444 | ||
1424 | static u64 get_block_attrs(sc_faddr_t addr_start) | 1445 | static u64 get_block_attrs(sc_faddr_t addr_start) |
1425 | { | 1446 | { |
1426 | u64 attr = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE | | 1447 | u64 attr = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE | |
1427 | PTE_BLOCK_PXN | PTE_BLOCK_UXN; | 1448 | PTE_BLOCK_PXN | PTE_BLOCK_UXN; |
1428 | 1449 | ||
1429 | if ((addr_start >= PHYS_SDRAM_1 && | 1450 | if ((addr_start >= PHYS_SDRAM_1 && |
1430 | addr_start <= ((sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE)) || | 1451 | addr_start <= ((sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE)) || |
1431 | (addr_start >= PHYS_SDRAM_2 && | 1452 | (addr_start >= PHYS_SDRAM_2 && |
1432 | addr_start <= ((sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE))) | 1453 | addr_start <= ((sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE))) |
1433 | #ifdef CONFIG_IMX_TRUSTY_OS | 1454 | #ifdef CONFIG_IMX_TRUSTY_OS |
1434 | return (PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE); | 1455 | return (PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE); |
1435 | #else | 1456 | #else |
1436 | return (PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_OUTER_SHARE); | 1457 | return (PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_OUTER_SHARE); |
1437 | #endif | 1458 | #endif |
1438 | 1459 | ||
1439 | return attr; | 1460 | return attr; |
1440 | } | 1461 | } |
1441 | 1462 | ||
1442 | static u64 get_block_size(sc_faddr_t addr_start, sc_faddr_t addr_end) | 1463 | static u64 get_block_size(sc_faddr_t addr_start, sc_faddr_t addr_end) |
1443 | { | 1464 | { |
1444 | sc_faddr_t end1, end2; | 1465 | sc_faddr_t end1, end2; |
1445 | 1466 | ||
1446 | end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE; | 1467 | end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE; |
1447 | end2 = (sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE; | 1468 | end2 = (sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE; |
1448 | 1469 | ||
1449 | if (addr_start >= PHYS_SDRAM_1 && addr_start <= end1) { | 1470 | if (addr_start >= PHYS_SDRAM_1 && addr_start <= end1) { |
1450 | if ((addr_end + 1) > end1) | 1471 | if ((addr_end + 1) > end1) |
1451 | return end1 - addr_start; | 1472 | return end1 - addr_start; |
1452 | } else if (addr_start >= PHYS_SDRAM_2 && addr_start <= end2) { | 1473 | } else if (addr_start >= PHYS_SDRAM_2 && addr_start <= end2) { |
1453 | if ((addr_end + 1) > end2) | 1474 | if ((addr_end + 1) > end2) |
1454 | return end2 - addr_start; | 1475 | return end2 - addr_start; |
1455 | } | 1476 | } |
1456 | 1477 | ||
1457 | return (addr_end - addr_start + 1); | 1478 | return (addr_end - addr_start + 1); |
1458 | } | 1479 | } |
1459 | 1480 | ||
1460 | #define MAX_PTE_ENTRIES 512 | 1481 | #define MAX_PTE_ENTRIES 512 |
1461 | #define MAX_MEM_MAP_REGIONS 16 | 1482 | #define MAX_MEM_MAP_REGIONS 16 |
1462 | 1483 | ||
1463 | static struct mm_region imx8_mem_map[MAX_MEM_MAP_REGIONS]; | 1484 | static struct mm_region imx8_mem_map[MAX_MEM_MAP_REGIONS]; |
1464 | struct mm_region *mem_map = imx8_mem_map; | 1485 | struct mm_region *mem_map = imx8_mem_map; |
1465 | 1486 | ||
1466 | void enable_caches(void) | 1487 | void enable_caches(void) |
1467 | { | 1488 | { |
1468 | sc_rm_mr_t mr; | 1489 | sc_rm_mr_t mr; |
1469 | sc_faddr_t start, end; | 1490 | sc_faddr_t start, end; |
1470 | int err, i; | 1491 | int err, i; |
1471 | 1492 | ||
1472 | /* Create map for registers access from 0x1c000000 to 0x80000000*/ | 1493 | /* Create map for registers access from 0x1c000000 to 0x80000000*/ |
1473 | imx8_mem_map[0].virt = 0x1c000000UL; | 1494 | imx8_mem_map[0].virt = 0x1c000000UL; |
1474 | imx8_mem_map[0].phys = 0x1c000000UL; | 1495 | imx8_mem_map[0].phys = 0x1c000000UL; |
1475 | imx8_mem_map[0].size = 0x64000000UL; | 1496 | imx8_mem_map[0].size = 0x64000000UL; |
1476 | imx8_mem_map[0].attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | | 1497 | imx8_mem_map[0].attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | |
1477 | PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN; | 1498 | PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN; |
1478 | 1499 | ||
1479 | i = 1; | 1500 | i = 1; |
1480 | 1501 | ||
1481 | #ifdef CONFIG_IMX_VSERVICE_SHARED_BUFFER | 1502 | #ifdef CONFIG_IMX_VSERVICE_SHARED_BUFFER |
1482 | imx8_mem_map[i].virt = CONFIG_IMX_VSERVICE_SHARED_BUFFER; | 1503 | imx8_mem_map[i].virt = CONFIG_IMX_VSERVICE_SHARED_BUFFER; |
1483 | imx8_mem_map[i].phys = CONFIG_IMX_VSERVICE_SHARED_BUFFER; | 1504 | imx8_mem_map[i].phys = CONFIG_IMX_VSERVICE_SHARED_BUFFER; |
1484 | imx8_mem_map[i].size = CONFIG_IMX_VSERVICE_SHARED_BUFFER_SIZE; | 1505 | imx8_mem_map[i].size = CONFIG_IMX_VSERVICE_SHARED_BUFFER_SIZE; |
1485 | imx8_mem_map[i].attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | | 1506 | imx8_mem_map[i].attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | |
1486 | PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN; | 1507 | PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN; |
1487 | i++; | 1508 | i++; |
1488 | #endif | 1509 | #endif |
1489 | 1510 | ||
1490 | for (mr = 0; mr < 64 && i < MAX_MEM_MAP_REGIONS; mr++) { | 1511 | for (mr = 0; mr < 64 && i < MAX_MEM_MAP_REGIONS; mr++) { |
1491 | err = get_owned_memreg(mr, &start, &end); | 1512 | err = get_owned_memreg(mr, &start, &end); |
1492 | if (!err) { | 1513 | if (!err) { |
1493 | imx8_mem_map[i].virt = start; | 1514 | imx8_mem_map[i].virt = start; |
1494 | imx8_mem_map[i].phys = start; | 1515 | imx8_mem_map[i].phys = start; |
1495 | imx8_mem_map[i].size = get_block_size(start, end); | 1516 | imx8_mem_map[i].size = get_block_size(start, end); |
1496 | imx8_mem_map[i].attrs = get_block_attrs(start); | 1517 | imx8_mem_map[i].attrs = get_block_attrs(start); |
1497 | i++; | 1518 | i++; |
1498 | } | 1519 | } |
1499 | } | 1520 | } |
1500 | 1521 | ||
1501 | if (i < MAX_MEM_MAP_REGIONS) { | 1522 | if (i < MAX_MEM_MAP_REGIONS) { |
1502 | imx8_mem_map[i].size = 0; | 1523 | imx8_mem_map[i].size = 0; |
1503 | imx8_mem_map[i].attrs = 0; | 1524 | imx8_mem_map[i].attrs = 0; |
1504 | } else { | 1525 | } else { |
1505 | puts("Error, need more MEM MAP REGIONS reserved\n"); | 1526 | puts("Error, need more MEM MAP REGIONS reserved\n"); |
1506 | icache_enable(); | 1527 | icache_enable(); |
1507 | return; | 1528 | return; |
1508 | } | 1529 | } |
1509 | 1530 | ||
1510 | for (i = 0; i < MAX_MEM_MAP_REGIONS; i++) { | 1531 | for (i = 0; i < MAX_MEM_MAP_REGIONS; i++) { |
1511 | debug("[%d] vir = 0x%llx phys = 0x%llx size = 0x%llx attrs = 0x%llx\n", | 1532 | debug("[%d] vir = 0x%llx phys = 0x%llx size = 0x%llx attrs = 0x%llx\n", |
1512 | i, imx8_mem_map[i].virt, imx8_mem_map[i].phys, | 1533 | i, imx8_mem_map[i].virt, imx8_mem_map[i].phys, |
1513 | imx8_mem_map[i].size, imx8_mem_map[i].attrs); | 1534 | imx8_mem_map[i].size, imx8_mem_map[i].attrs); |
1514 | } | 1535 | } |
1515 | 1536 | ||
1516 | icache_enable(); | 1537 | icache_enable(); |
1517 | dcache_enable(); | 1538 | dcache_enable(); |
1518 | } | 1539 | } |
1519 | 1540 | ||
1520 | #ifndef CONFIG_SYS_DCACHE_OFF | 1541 | #ifndef CONFIG_SYS_DCACHE_OFF |
1521 | u64 get_page_table_size(void) | 1542 | u64 get_page_table_size(void) |
1522 | { | 1543 | { |
1523 | u64 one_pt = MAX_PTE_ENTRIES * sizeof(u64); | 1544 | u64 one_pt = MAX_PTE_ENTRIES * sizeof(u64); |
1524 | u64 size = 0; | 1545 | u64 size = 0; |
1525 | 1546 | ||
1526 | /* | 1547 | /* |
1527 | * For each memory region, the max table size: | 1548 | * For each memory region, the max table size: |
1528 | * 2 level 3 tables + 2 level 2 tables + 1 level 1 table | 1549 | * 2 level 3 tables + 2 level 2 tables + 1 level 1 table |
1529 | */ | 1550 | */ |
1530 | size = (2 + 2 + 1) * one_pt * MAX_MEM_MAP_REGIONS + one_pt; | 1551 | size = (2 + 2 + 1) * one_pt * MAX_MEM_MAP_REGIONS + one_pt; |
1531 | 1552 | ||
1532 | /* | 1553 | /* |
1533 | * We need to duplicate our page table once to have an emergency pt to | 1554 | * We need to duplicate our page table once to have an emergency pt to |
1534 | * resort to when splitting page tables later on | 1555 | * resort to when splitting page tables later on |
1535 | */ | 1556 | */ |
1536 | size *= 2; | 1557 | size *= 2; |
1537 | 1558 | ||
1538 | /* | 1559 | /* |
1539 | * We may need to split page tables later on if dcache settings change, | 1560 | * We may need to split page tables later on if dcache settings change, |
1540 | * so reserve up to 4 (random pick) page tables for that. | 1561 | * so reserve up to 4 (random pick) page tables for that. |
1541 | */ | 1562 | */ |
1542 | size += one_pt * 4; | 1563 | size += one_pt * 4; |
1543 | 1564 | ||
1544 | return size; | 1565 | return size; |
1545 | } | 1566 | } |
1546 | #endif | 1567 | #endif |
1547 | 1568 | ||
1548 | #if defined(CONFIG_IMX8QM) | 1569 | #if defined(CONFIG_IMX8QM) |
1549 | #define FUSE_MAC0_WORD0 452 | 1570 | #define FUSE_MAC0_WORD0 452 |
1550 | #define FUSE_MAC0_WORD1 453 | 1571 | #define FUSE_MAC0_WORD1 453 |
1551 | #define FUSE_MAC1_WORD0 454 | 1572 | #define FUSE_MAC1_WORD0 454 |
1552 | #define FUSE_MAC1_WORD1 455 | 1573 | #define FUSE_MAC1_WORD1 455 |
1553 | #elif defined(CONFIG_IMX8QXP) | 1574 | #elif defined(CONFIG_IMX8QXP) |
1554 | #define FUSE_MAC0_WORD0 708 | 1575 | #define FUSE_MAC0_WORD0 708 |
1555 | #define FUSE_MAC0_WORD1 709 | 1576 | #define FUSE_MAC0_WORD1 709 |
1556 | #define FUSE_MAC1_WORD0 710 | 1577 | #define FUSE_MAC1_WORD0 710 |
1557 | #define FUSE_MAC1_WORD1 711 | 1578 | #define FUSE_MAC1_WORD1 711 |
1558 | #endif | 1579 | #endif |
1559 | 1580 | ||
1560 | void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) | 1581 | void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) |
1561 | { | 1582 | { |
1562 | u32 word[2], val[2] = {}; | 1583 | u32 word[2], val[2] = {}; |
1563 | int i, ret; | 1584 | int i, ret; |
1564 | 1585 | ||
1565 | if (dev_id == 0) { | 1586 | if (dev_id == 0) { |
1566 | word[0] = FUSE_MAC0_WORD0; | 1587 | word[0] = FUSE_MAC0_WORD0; |
1567 | word[1] = FUSE_MAC0_WORD1; | 1588 | word[1] = FUSE_MAC0_WORD1; |
1568 | } else { | 1589 | } else { |
1569 | word[0] = FUSE_MAC1_WORD0; | 1590 | word[0] = FUSE_MAC1_WORD0; |
1570 | word[1] = FUSE_MAC1_WORD1; | 1591 | word[1] = FUSE_MAC1_WORD1; |
1571 | } | 1592 | } |
1572 | 1593 | ||
1573 | for (i = 0; i < 2; i++) { | 1594 | for (i = 0; i < 2; i++) { |
1574 | ret = sc_misc_otp_fuse_read(-1, word[i], &val[i]); | 1595 | ret = sc_misc_otp_fuse_read(-1, word[i], &val[i]); |
1575 | if (ret < 0) | 1596 | if (ret < 0) |
1576 | goto err; | 1597 | goto err; |
1577 | } | 1598 | } |
1578 | 1599 | ||
1579 | mac[0] = val[0]; | 1600 | mac[0] = val[0]; |
1580 | mac[1] = val[0] >> 8; | 1601 | mac[1] = val[0] >> 8; |
1581 | mac[2] = val[0] >> 16; | 1602 | mac[2] = val[0] >> 16; |
1582 | mac[3] = val[0] >> 24; | 1603 | mac[3] = val[0] >> 24; |
1583 | mac[4] = val[1]; | 1604 | mac[4] = val[1]; |
1584 | mac[5] = val[1] >> 8; | 1605 | mac[5] = val[1] >> 8; |
1585 | 1606 | ||
1586 | debug("%s: MAC%d: %02x.%02x.%02x.%02x.%02x.%02x\n", | 1607 | debug("%s: MAC%d: %02x.%02x.%02x.%02x.%02x.%02x\n", |
1587 | __func__, dev_id, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); | 1608 | __func__, dev_id, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); |
1588 | return; | 1609 | return; |
1589 | err: | 1610 | err: |
1590 | printf("%s: fuse %d, err: %d\n", __func__, word[i], ret); | 1611 | printf("%s: fuse %d, err: %d\n", __func__, word[i], ret); |
1591 | } | 1612 | } |
1592 | 1613 | ||
1593 | u32 get_cpu_rev(void) | 1614 | u32 get_cpu_rev(void) |
1594 | { | 1615 | { |
1595 | u32 id = 0, rev = 0; | 1616 | u32 id = 0, rev = 0; |
1596 | int ret; | 1617 | int ret; |
1597 | 1618 | ||
1598 | ret = sc_misc_get_control(-1, SC_R_SYSTEM, SC_C_ID, &id); | 1619 | ret = sc_misc_get_control(-1, SC_R_SYSTEM, SC_C_ID, &id); |
1599 | if (ret) | 1620 | if (ret) |
1600 | return 0; | 1621 | return 0; |
1601 | 1622 | ||
1602 | rev = (id >> 5) & 0xf; | 1623 | rev = (id >> 5) & 0xf; |
1603 | id = (id & 0x1f) + MXC_SOC_IMX8; /* Dummy ID for chip */ | 1624 | id = (id & 0x1f) + MXC_SOC_IMX8; /* Dummy ID for chip */ |
1604 | 1625 | ||
1605 | return (id << 12) | rev; | 1626 | return (id << 12) | rev; |
1606 | } | 1627 | } |
1607 | 1628 | ||
1608 | void disconnect_from_pc(void) | 1629 | void disconnect_from_pc(void) |
1609 | { | 1630 | { |
1610 | int ret; | 1631 | int ret; |
1611 | struct power_domain pd; | 1632 | struct power_domain pd; |
1612 | 1633 | ||
1613 | if (!power_domain_lookup_name("conn_usb0", &pd)) { | 1634 | if (!power_domain_lookup_name("conn_usb0", &pd)) { |
1614 | ret = power_domain_on(&pd); | 1635 | ret = power_domain_on(&pd); |
1615 | if (ret) { | 1636 | if (ret) { |
1616 | printf("conn_usb0 Power up failed! (error = %d)\n", ret); | 1637 | printf("conn_usb0 Power up failed! (error = %d)\n", ret); |
1617 | return; | 1638 | return; |
1618 | } | 1639 | } |
1619 | 1640 | ||
1620 | writel(0x0, USB_BASE_ADDR + 0x140); | 1641 | writel(0x0, USB_BASE_ADDR + 0x140); |
1621 | 1642 | ||
1622 | ret = power_domain_off(&pd); | 1643 | ret = power_domain_off(&pd); |
1623 | if (ret) { | 1644 | if (ret) { |
1624 | printf("conn_usb0 Power off failed! (error = %d)\n", ret); | 1645 | printf("conn_usb0 Power off failed! (error = %d)\n", ret); |
1625 | return; | 1646 | return; |
1626 | } | 1647 | } |
1627 | } else { | 1648 | } else { |
1628 | printf("conn_usb0 finding failed!\n"); | 1649 | printf("conn_usb0 finding failed!\n"); |
1629 | return; | 1650 | return; |
1630 | } | 1651 | } |
1631 | } | 1652 | } |
1632 | 1653 | ||
1633 | #if CONFIG_IS_ENABLED(CPU) | 1654 | #if CONFIG_IS_ENABLED(CPU) |
1634 | struct cpu_imx_platdata { | 1655 | struct cpu_imx_platdata { |
1635 | const char *name; | 1656 | const char *name; |
1636 | const char *rev; | 1657 | const char *rev; |
1637 | const char *type; | 1658 | const char *type; |
1638 | u32 cpurev; | 1659 | u32 cpurev; |
1639 | u32 freq_mhz; | 1660 | u32 freq_mhz; |
1640 | u32 mpidr; | 1661 | u32 mpidr; |
1641 | }; | 1662 | }; |
1642 | 1663 | ||
1643 | const char *get_imx8_type(u32 imxtype) | 1664 | const char *get_imx8_type(u32 imxtype) |
1644 | { | 1665 | { |
1645 | switch (imxtype) { | 1666 | switch (imxtype) { |
1646 | case MXC_CPU_IMX8QM: | 1667 | case MXC_CPU_IMX8QM: |
1647 | return "QM"; /* i.MX8 Quad MAX */ | 1668 | return "QM"; /* i.MX8 Quad MAX */ |
1648 | case MXC_CPU_IMX8QXP: | 1669 | case MXC_CPU_IMX8QXP: |
1649 | case MXC_CPU_IMX8QXP_A0: | 1670 | case MXC_CPU_IMX8QXP_A0: |
1650 | return "QXP"; | 1671 | return "QXP"; |
1651 | default: | 1672 | default: |
1652 | return "??"; | 1673 | return "??"; |
1653 | } | 1674 | } |
1654 | } | 1675 | } |
1655 | 1676 | ||
1656 | const char *get_imx8_rev(u32 rev) | 1677 | const char *get_imx8_rev(u32 rev) |
1657 | { | 1678 | { |
1658 | switch (rev) { | 1679 | switch (rev) { |
1659 | case CHIP_REV_A: | 1680 | case CHIP_REV_A: |
1660 | return "A"; | 1681 | return "A"; |
1661 | case CHIP_REV_B: | 1682 | case CHIP_REV_B: |
1662 | return "B"; | 1683 | return "B"; |
1663 | case CHIP_REV_C: | 1684 | case CHIP_REV_C: |
1664 | return "C"; | 1685 | return "C"; |
1665 | default: | 1686 | default: |
1666 | return "?"; | 1687 | return "?"; |
1667 | } | 1688 | } |
1668 | } | 1689 | } |
1669 | 1690 | ||
1670 | const char *get_core_name(struct udevice *dev) | 1691 | const char *get_core_name(struct udevice *dev) |
1671 | { | 1692 | { |
1672 | const void *blob = gd->fdt_blob; | 1693 | const void *blob = gd->fdt_blob; |
1673 | int node = dev_of_offset(dev); | 1694 | int node = dev_of_offset(dev); |
1674 | 1695 | ||
1675 | if (!fdt_node_check_compatible(blob, node, "arm,cortex-a35")) | 1696 | if (!fdt_node_check_compatible(blob, node, "arm,cortex-a35")) |
1676 | return "A35"; | 1697 | return "A35"; |
1677 | else if (!fdt_node_check_compatible(blob, node, "arm,cortex-a53")) | 1698 | else if (!fdt_node_check_compatible(blob, node, "arm,cortex-a53")) |
1678 | return "A53"; | 1699 | return "A53"; |
1679 | else if (!fdt_node_check_compatible(blob, node, "arm,cortex-a72")) | 1700 | else if (!fdt_node_check_compatible(blob, node, "arm,cortex-a72")) |
1680 | return "A72"; | 1701 | return "A72"; |
1681 | else | 1702 | else |
1682 | return "?"; | 1703 | return "?"; |
1683 | } | 1704 | } |
1684 | 1705 | ||
1685 | int cpu_imx_get_desc(struct udevice *dev, char *buf, int size) | 1706 | int cpu_imx_get_desc(struct udevice *dev, char *buf, int size) |
1686 | { | 1707 | { |
1687 | struct cpu_imx_platdata *plat = dev_get_platdata(dev); | 1708 | struct cpu_imx_platdata *plat = dev_get_platdata(dev); |
1688 | int len; | 1709 | int len; |
1689 | 1710 | ||
1690 | if (size < 100) | 1711 | if (size < 100) |
1691 | return -ENOSPC; | 1712 | return -ENOSPC; |
1692 | 1713 | ||
1693 | len = snprintf(buf, size, "NXP i.MX8%s Rev%s %s at %u MHz", | 1714 | len = snprintf(buf, size, "NXP i.MX8%s Rev%s %s at %u MHz", |
1694 | plat->type, plat->rev, plat->name, plat->freq_mhz); | 1715 | plat->type, plat->rev, plat->name, plat->freq_mhz); |
1695 | 1716 | ||
1696 | #if defined(CONFIG_IMX_SC_THERMAL) | 1717 | #if defined(CONFIG_IMX_SC_THERMAL) |
1697 | struct udevice *thermal_dev; | 1718 | struct udevice *thermal_dev; |
1698 | int cpu_tmp, ret; | 1719 | int cpu_tmp, ret; |
1699 | 1720 | ||
1700 | if (!strcmp(plat->name, "A72")) | 1721 | if (!strcmp(plat->name, "A72")) |
1701 | ret = uclass_get_device_by_name(UCLASS_THERMAL, "cpu-thermal1", &thermal_dev); | 1722 | ret = uclass_get_device_by_name(UCLASS_THERMAL, "cpu-thermal1", &thermal_dev); |
1702 | else | 1723 | else |
1703 | ret = uclass_get_device_by_name(UCLASS_THERMAL, "cpu-thermal0", &thermal_dev); | 1724 | ret = uclass_get_device_by_name(UCLASS_THERMAL, "cpu-thermal0", &thermal_dev); |
1704 | 1725 | ||
1705 | if (!ret) { | 1726 | if (!ret) { |
1706 | ret = thermal_get_temp(thermal_dev, &cpu_tmp); | 1727 | ret = thermal_get_temp(thermal_dev, &cpu_tmp); |
1707 | 1728 | ||
1708 | if (!ret) | 1729 | if (!ret) |
1709 | len += snprintf(buf + len, size," at %dC", cpu_tmp); | 1730 | len += snprintf(buf + len, size," at %dC", cpu_tmp); |
1710 | else | 1731 | else |
1711 | len += snprintf(buf + len, size," - invalid sensor data"); | 1732 | len += snprintf(buf + len, size," - invalid sensor data"); |
1712 | } else { | 1733 | } else { |
1713 | len += snprintf(buf + len, size, " - invalid sensor device"); | 1734 | len += snprintf(buf + len, size, " - invalid sensor device"); |
1714 | } | 1735 | } |
1715 | #endif | 1736 | #endif |
1716 | 1737 | ||
1717 | len += snprintf(buf + len, size, "\n"); | 1738 | len += snprintf(buf + len, size, "\n"); |
1718 | 1739 | ||
1719 | return 0; | 1740 | return 0; |
1720 | } | 1741 | } |
1721 | 1742 | ||
1722 | static int cpu_imx_get_info(struct udevice *dev, struct cpu_info *info) | 1743 | static int cpu_imx_get_info(struct udevice *dev, struct cpu_info *info) |
1723 | { | 1744 | { |
1724 | struct cpu_imx_platdata *plat = dev_get_platdata(dev); | 1745 | struct cpu_imx_platdata *plat = dev_get_platdata(dev); |
1725 | 1746 | ||
1726 | info->cpu_freq = plat->freq_mhz * 1000; | 1747 | info->cpu_freq = plat->freq_mhz * 1000; |
1727 | info->features = BIT(CPU_FEAT_L1_CACHE) | BIT(CPU_FEAT_MMU); | 1748 | info->features = BIT(CPU_FEAT_L1_CACHE) | BIT(CPU_FEAT_MMU); |
1728 | return 0; | 1749 | return 0; |
1729 | } | 1750 | } |
1730 | 1751 | ||
1731 | static int cpu_imx_get_count(struct udevice *dev) | 1752 | static int cpu_imx_get_count(struct udevice *dev) |
1732 | { | 1753 | { |
1733 | if (is_imx8qxp()) | 1754 | if (is_imx8qxp()) |
1734 | return 4; | 1755 | return 4; |
1735 | else | 1756 | else |
1736 | return 6; | 1757 | return 6; |
1737 | } | 1758 | } |
1738 | 1759 | ||
1739 | static int cpu_imx_get_vendor(struct udevice *dev, char *buf, int size) | 1760 | static int cpu_imx_get_vendor(struct udevice *dev, char *buf, int size) |
1740 | { | 1761 | { |
1741 | snprintf(buf, size, "NXP"); | 1762 | snprintf(buf, size, "NXP"); |
1742 | return 0; | 1763 | return 0; |
1743 | } | 1764 | } |
1744 | 1765 | ||
1745 | static bool cpu_imx_is_current(struct udevice *dev) | 1766 | static bool cpu_imx_is_current(struct udevice *dev) |
1746 | { | 1767 | { |
1747 | struct cpu_imx_platdata *plat = dev_get_platdata(dev); | 1768 | struct cpu_imx_platdata *plat = dev_get_platdata(dev); |
1748 | 1769 | ||
1749 | if (plat->mpidr == (read_mpidr() & 0xffff)) | 1770 | if (plat->mpidr == (read_mpidr() & 0xffff)) |
1750 | return true; | 1771 | return true; |
1751 | 1772 | ||
1752 | return false; | 1773 | return false; |
1753 | } | 1774 | } |
1754 | 1775 | ||
1755 | static const struct cpu_ops cpu_imx8_ops = { | 1776 | static const struct cpu_ops cpu_imx8_ops = { |
1756 | .get_desc = cpu_imx_get_desc, | 1777 | .get_desc = cpu_imx_get_desc, |
1757 | .get_info = cpu_imx_get_info, | 1778 | .get_info = cpu_imx_get_info, |
1758 | .get_count = cpu_imx_get_count, | 1779 | .get_count = cpu_imx_get_count, |
1759 | .get_vendor = cpu_imx_get_vendor, | 1780 | .get_vendor = cpu_imx_get_vendor, |
1760 | .is_current_cpu = cpu_imx_is_current, | 1781 | .is_current_cpu = cpu_imx_is_current, |
1761 | }; | 1782 | }; |
1762 | 1783 | ||
1763 | static const struct udevice_id cpu_imx8_ids[] = { | 1784 | static const struct udevice_id cpu_imx8_ids[] = { |
1764 | { .compatible = "arm,cortex-a35" }, | 1785 | { .compatible = "arm,cortex-a35" }, |
1765 | { .compatible = "arm,cortex-a53" }, | 1786 | { .compatible = "arm,cortex-a53" }, |
1766 | { .compatible = "arm,cortex-a72" }, | 1787 | { .compatible = "arm,cortex-a72" }, |
1767 | { } | 1788 | { } |
1768 | }; | 1789 | }; |
1769 | 1790 | ||
1770 | static int imx8_cpu_probe(struct udevice *dev) | 1791 | static int imx8_cpu_probe(struct udevice *dev) |
1771 | { | 1792 | { |
1772 | struct cpu_imx_platdata *plat = dev_get_platdata(dev); | 1793 | struct cpu_imx_platdata *plat = dev_get_platdata(dev); |
1773 | struct clk cpu_clk; | 1794 | struct clk cpu_clk; |
1774 | u32 cpurev; | 1795 | u32 cpurev; |
1775 | int ret; | 1796 | int ret; |
1776 | 1797 | ||
1777 | cpurev = get_cpu_rev(); | 1798 | cpurev = get_cpu_rev(); |
1778 | plat->cpurev = cpurev; | 1799 | plat->cpurev = cpurev; |
1779 | plat->name = get_core_name(dev); | 1800 | plat->name = get_core_name(dev); |
1780 | plat->rev = get_imx8_rev(cpurev & 0xFFF); | 1801 | plat->rev = get_imx8_rev(cpurev & 0xFFF); |
1781 | plat->type = get_imx8_type((cpurev & 0xFF000) >> 12); | 1802 | plat->type = get_imx8_type((cpurev & 0xFF000) >> 12); |
1782 | 1803 | ||
1783 | plat->mpidr = dev_read_addr(dev); | 1804 | plat->mpidr = dev_read_addr(dev); |
1784 | if (plat->mpidr == FDT_ADDR_T_NONE) { | 1805 | if (plat->mpidr == FDT_ADDR_T_NONE) { |
1785 | printf("%s: Failed to get CPU reg property\n", __func__); | 1806 | printf("%s: Failed to get CPU reg property\n", __func__); |
1786 | return -EINVAL; | 1807 | return -EINVAL; |
1787 | } | 1808 | } |
1788 | 1809 | ||
1789 | ret = clk_get_by_index(dev, 0, &cpu_clk); | 1810 | ret = clk_get_by_index(dev, 0, &cpu_clk); |
1790 | if (ret) { | 1811 | if (ret) { |
1791 | debug("%s: Failed to get CPU clk: %d\n", __func__, ret); | 1812 | debug("%s: Failed to get CPU clk: %d\n", __func__, ret); |
1792 | return 0; | 1813 | return 0; |
1793 | } | 1814 | } |
1794 | 1815 | ||
1795 | plat->freq_mhz = clk_get_rate(&cpu_clk) / 1000000; | 1816 | plat->freq_mhz = clk_get_rate(&cpu_clk) / 1000000; |
1796 | return 0; | 1817 | return 0; |
1797 | } | 1818 | } |
1798 | 1819 | ||
1799 | U_BOOT_DRIVER(cpu_imx8_drv) = { | 1820 | U_BOOT_DRIVER(cpu_imx8_drv) = { |
1800 | .name = "imx8x_cpu", | 1821 | .name = "imx8x_cpu", |
1801 | .id = UCLASS_CPU, | 1822 | .id = UCLASS_CPU, |
1802 | .of_match = cpu_imx8_ids, | 1823 | .of_match = cpu_imx8_ids, |
1803 | .ops = &cpu_imx8_ops, | 1824 | .ops = &cpu_imx8_ops, |
1804 | .probe = imx8_cpu_probe, | 1825 | .probe = imx8_cpu_probe, |
1805 | .platdata_auto_alloc_size = sizeof(struct cpu_imx_platdata), | 1826 | .platdata_auto_alloc_size = sizeof(struct cpu_imx_platdata), |
1806 | .flags = DM_FLAG_PRE_RELOC, | 1827 | .flags = DM_FLAG_PRE_RELOC, |
1807 | }; | 1828 | }; |
1808 | #endif | 1829 | #endif |
1809 | 1830 | ||
1810 | static bool check_device_power_off(struct udevice *dev, | 1831 | static bool check_device_power_off(struct udevice *dev, |
1811 | const char* permanent_on_devices[], int size) | 1832 | const char* permanent_on_devices[], int size) |
1812 | { | 1833 | { |
1813 | int i; | 1834 | int i; |
1814 | 1835 | ||
1815 | for (i = 0; i < size; i++) { | 1836 | for (i = 0; i < size; i++) { |
1816 | if (!strcmp(dev->name, permanent_on_devices[i])) | 1837 | if (!strcmp(dev->name, permanent_on_devices[i])) |
1817 | return false; | 1838 | return false; |
1818 | } | 1839 | } |
1819 | 1840 | ||
1820 | return true; | 1841 | return true; |
1821 | } | 1842 | } |
1822 | 1843 | ||
1823 | void power_off_pd_devices(const char* permanent_on_devices[], int size) | 1844 | void power_off_pd_devices(const char* permanent_on_devices[], int size) |
1824 | { | 1845 | { |
1825 | struct udevice *dev; | 1846 | struct udevice *dev; |
1826 | struct power_domain pd; | 1847 | struct power_domain pd; |
1827 | 1848 | ||
1828 | for (uclass_find_first_device(UCLASS_POWER_DOMAIN, &dev); dev; | 1849 | for (uclass_find_first_device(UCLASS_POWER_DOMAIN, &dev); dev; |
1829 | uclass_find_next_device(&dev)) { | 1850 | uclass_find_next_device(&dev)) { |
1830 | 1851 | ||
1831 | if (device_active(dev)) { | 1852 | if (device_active(dev)) { |
1832 | /* Power off active pd devices except the permanent power on devices */ | 1853 | /* Power off active pd devices except the permanent power on devices */ |
1833 | if (check_device_power_off(dev, permanent_on_devices, size)) { | 1854 | if (check_device_power_off(dev, permanent_on_devices, size)) { |
1834 | pd.dev = dev; | 1855 | pd.dev = dev; |
1835 | power_domain_off(&pd); | 1856 | power_domain_off(&pd); |
1836 | } | 1857 | } |
1837 | } | 1858 | } |
1838 | } | 1859 | } |
1839 | } | 1860 | } |
1840 | 1861 | ||
1841 | bool check_owned_udevice(struct udevice *dev) | 1862 | bool check_owned_udevice(struct udevice *dev) |
1842 | { | 1863 | { |
1843 | int ret; | 1864 | int ret; |
1844 | sc_rsrc_t resource_id; | 1865 | sc_rsrc_t resource_id; |
1845 | struct ofnode_phandle_args args; | 1866 | struct ofnode_phandle_args args; |
1846 | 1867 | ||
1847 | /* Get the resource id from its power-domain */ | 1868 | /* Get the resource id from its power-domain */ |
1848 | ret = dev_read_phandle_with_args(dev, "power-domains", | 1869 | ret = dev_read_phandle_with_args(dev, "power-domains", |
1849 | "#power-domain-cells", 0, 0, &args); | 1870 | "#power-domain-cells", 0, 0, &args); |
1850 | if (ret) { | 1871 | if (ret) { |
1851 | printf("no power-domains found\n"); | 1872 | printf("no power-domains found\n"); |
1852 | return false; | 1873 | return false; |
1853 | } | 1874 | } |
1854 | 1875 | ||
1855 | /* Get the owner partition for resource*/ | 1876 | /* Get the owner partition for resource*/ |
1856 | resource_id = (sc_rsrc_t)ofnode_read_u32_default(args.node, "reg", SC_R_NONE); | 1877 | resource_id = (sc_rsrc_t)ofnode_read_u32_default(args.node, "reg", SC_R_NONE); |
1857 | if (resource_id == SC_R_NONE) { | 1878 | if (resource_id == SC_R_NONE) { |
1858 | printf("Can't find the resource id for udev %s\n", dev->name); | 1879 | printf("Can't find the resource id for udev %s\n", dev->name); |
1859 | return false; | 1880 | return false; |
1860 | } | 1881 | } |
1861 | 1882 | ||
1862 | debug("udev %s, resource id %d\n", dev->name, resource_id); | 1883 | debug("udev %s, resource id %d\n", dev->name, resource_id); |
1863 | 1884 | ||
1864 | return check_owned_resource(resource_id); | 1885 | return check_owned_resource(resource_id); |
1865 | } | 1886 | } |
1866 | 1887 | ||
1867 | bool check_m4_parts_boot(void) | 1888 | bool check_m4_parts_boot(void) |
1868 | { | 1889 | { |
1869 | sc_rm_pt_t m4_parts[2]; | 1890 | sc_rm_pt_t m4_parts[2]; |
1870 | int err; | 1891 | int err; |
1871 | 1892 | ||
1872 | err = sc_rm_get_resource_owner(-1, SC_R_M4_0_PID0, &m4_parts[0]); | 1893 | err = sc_rm_get_resource_owner(-1, SC_R_M4_0_PID0, &m4_parts[0]); |
1873 | if (err != SC_ERR_NONE) { | 1894 | if (err != SC_ERR_NONE) { |
1874 | printf("%s get resource [%d] owner error: %d\n", __func__, SC_R_M4_0_PID0, err); | 1895 | printf("%s get resource [%d] owner error: %d\n", __func__, SC_R_M4_0_PID0, err); |
1875 | return false; | 1896 | return false; |
1876 | } | 1897 | } |
1877 | 1898 | ||
1878 | if (sc_pm_is_partition_started(-1, m4_parts[0])) | 1899 | if (sc_pm_is_partition_started(-1, m4_parts[0])) |
1879 | return true; | 1900 | return true; |
1880 | 1901 | ||
1881 | if (is_imx8qm()) { | 1902 | if (is_imx8qm()) { |
1882 | err = sc_rm_get_resource_owner(-1, SC_R_M4_1_PID0, &m4_parts[1]); | 1903 | err = sc_rm_get_resource_owner(-1, SC_R_M4_1_PID0, &m4_parts[1]); |
1883 | if (err != SC_ERR_NONE) { | 1904 | if (err != SC_ERR_NONE) { |
1884 | printf("%s get resource [%d] owner error: %d\n", __func__, SC_R_M4_1_PID0, err); | 1905 | printf("%s get resource [%d] owner error: %d\n", __func__, SC_R_M4_1_PID0, err); |
1885 | return false; | 1906 | return false; |
1886 | } | 1907 | } |
1887 | 1908 | ||
1888 | if (sc_pm_is_partition_started(-1, m4_parts[1])) | 1909 | if (sc_pm_is_partition_started(-1, m4_parts[1])) |
1889 | return true; | 1910 | return true; |
1890 | } | 1911 | } |
1891 | 1912 | ||
1892 | return false; | 1913 | return false; |
1893 | } | 1914 | } |
1894 | 1915 | ||
1895 | #ifdef CONFIG_IMX_VSERVICE | 1916 | #ifdef CONFIG_IMX_VSERVICE |
1896 | struct udevice * board_imx_vservice_find_mu(struct udevice *dev) | 1917 | struct udevice * board_imx_vservice_find_mu(struct udevice *dev) |
1897 | { | 1918 | { |
1898 | int ret; | 1919 | int ret; |
1899 | const char *m4_mu_name[2] = { | 1920 | const char *m4_mu_name[2] = { |
1900 | "mu@5d230000", | 1921 | "mu@5d230000", |
1901 | "mu@5d240000" | 1922 | "mu@5d240000" |
1902 | }; | 1923 | }; |
1903 | struct udevice *m4_mu[2]; | 1924 | struct udevice *m4_mu[2]; |
1904 | sc_rm_pt_t m4_parts[2]; | 1925 | sc_rm_pt_t m4_parts[2]; |
1905 | int err; | 1926 | int err; |
1906 | struct ofnode_phandle_args args; | 1927 | struct ofnode_phandle_args args; |
1907 | sc_rsrc_t resource_id; | 1928 | sc_rsrc_t resource_id; |
1908 | sc_rm_pt_t resource_part; | 1929 | sc_rm_pt_t resource_part; |
1909 | 1930 | ||
1910 | /* Get the resource id from its power-domain */ | 1931 | /* Get the resource id from its power-domain */ |
1911 | ret = dev_read_phandle_with_args(dev, "power-domains", | 1932 | ret = dev_read_phandle_with_args(dev, "power-domains", |
1912 | "#power-domain-cells", 0, 0, &args); | 1933 | "#power-domain-cells", 0, 0, &args); |
1913 | if (ret) { | 1934 | if (ret) { |
1914 | printf("Can't find the power-domains property for udev %s\n", dev->name); | 1935 | printf("Can't find the power-domains property for udev %s\n", dev->name); |
1915 | return NULL; | 1936 | return NULL; |
1916 | } | 1937 | } |
1917 | 1938 | ||
1918 | /* Get the owner partition for resource*/ | 1939 | /* Get the owner partition for resource*/ |
1919 | resource_id = (sc_rsrc_t)ofnode_read_u32_default(args.node, "reg", SC_R_NONE); | 1940 | resource_id = (sc_rsrc_t)ofnode_read_u32_default(args.node, "reg", SC_R_NONE); |
1920 | if (resource_id == SC_R_NONE) { | 1941 | if (resource_id == SC_R_NONE) { |
1921 | printf("Can't find the resource id for udev %s\n", dev->name); | 1942 | printf("Can't find the resource id for udev %s\n", dev->name); |
1922 | return NULL; | 1943 | return NULL; |
1923 | } | 1944 | } |
1924 | 1945 | ||
1925 | err = sc_rm_get_resource_owner(-1, resource_id, &resource_part); | 1946 | err = sc_rm_get_resource_owner(-1, resource_id, &resource_part); |
1926 | if (err != SC_ERR_NONE) { | 1947 | if (err != SC_ERR_NONE) { |
1927 | printf("%s get resource [%d] owner error: %d\n", __func__, resource_id, err); | 1948 | printf("%s get resource [%d] owner error: %d\n", __func__, resource_id, err); |
1928 | return NULL; | 1949 | return NULL; |
1929 | } | 1950 | } |
1930 | 1951 | ||
1931 | debug("udev %s, resource id %d, resource part %d\n", dev->name, resource_id, resource_part); | 1952 | debug("udev %s, resource id %d, resource part %d\n", dev->name, resource_id, resource_part); |
1932 | 1953 | ||
1933 | /* MU8 for communication between M4_0 and u-boot, MU9 for M4_1 and u-boot */ | 1954 | /* MU8 for communication between M4_0 and u-boot, MU9 for M4_1 and u-boot */ |
1934 | err = sc_rm_get_resource_owner(-1, SC_R_M4_0_PID0, &m4_parts[0]); | 1955 | err = sc_rm_get_resource_owner(-1, SC_R_M4_0_PID0, &m4_parts[0]); |
1935 | if (err != SC_ERR_NONE) { | 1956 | if (err != SC_ERR_NONE) { |
1936 | printf("%s get resource [%d] owner error: %d\n", __func__, SC_R_M4_0_PID0, err); | 1957 | printf("%s get resource [%d] owner error: %d\n", __func__, SC_R_M4_0_PID0, err); |
1937 | return NULL; | 1958 | return NULL; |
1938 | } | 1959 | } |
1939 | 1960 | ||
1940 | ret = uclass_find_device_by_name(UCLASS_MISC, m4_mu_name[0], &m4_mu[0]); | 1961 | ret = uclass_find_device_by_name(UCLASS_MISC, m4_mu_name[0], &m4_mu[0]); |
1941 | if (!ret) { | 1962 | if (!ret) { |
1942 | /* If the i2c is in m4_0 partition, return the mu8 */ | 1963 | /* If the i2c is in m4_0 partition, return the mu8 */ |
1943 | if (resource_part == m4_parts[0]) | 1964 | if (resource_part == m4_parts[0]) |
1944 | return m4_mu[0]; | 1965 | return m4_mu[0]; |
1945 | } | 1966 | } |
1946 | 1967 | ||
1947 | if (is_imx8qm()) { | 1968 | if (is_imx8qm()) { |
1948 | err = sc_rm_get_resource_owner(-1, SC_R_M4_1_PID0, &m4_parts[1]); | 1969 | err = sc_rm_get_resource_owner(-1, SC_R_M4_1_PID0, &m4_parts[1]); |
1949 | if (err != SC_ERR_NONE) { | 1970 | if (err != SC_ERR_NONE) { |
1950 | printf("%s get resource [%d] owner error: %d\n", __func__, SC_R_M4_1_PID0, err); | 1971 | printf("%s get resource [%d] owner error: %d\n", __func__, SC_R_M4_1_PID0, err); |
1951 | return NULL; | 1972 | return NULL; |
1952 | } | 1973 | } |
1953 | 1974 | ||
1954 | ret = uclass_find_device_by_name(UCLASS_MISC, m4_mu_name[1], &m4_mu[1]); | 1975 | ret = uclass_find_device_by_name(UCLASS_MISC, m4_mu_name[1], &m4_mu[1]); |
1955 | if (!ret) { | 1976 | if (!ret) { |
1956 | /* If the i2c is in m4_1 partition, return the mu9 */ | 1977 | /* If the i2c is in m4_1 partition, return the mu9 */ |
1957 | if (resource_part == m4_parts[1]) | 1978 | if (resource_part == m4_parts[1]) |
1958 | return m4_mu[1]; | 1979 | return m4_mu[1]; |
1959 | } | 1980 | } |
1960 | } | 1981 | } |
1961 | 1982 | ||
1962 | return NULL; | 1983 | return NULL; |
1963 | } | 1984 | } |
1964 | 1985 | ||
1965 | void * board_imx_vservice_get_buffer(struct imx_vservice_channel *node, u32 size) | 1986 | void * board_imx_vservice_get_buffer(struct imx_vservice_channel *node, u32 size) |
1966 | { | 1987 | { |
1967 | const char *m4_mu_name[2] = { | 1988 | const char *m4_mu_name[2] = { |
1968 | "mu@5d230000", | 1989 | "mu@5d230000", |
1969 | "mu@5d240000" | 1990 | "mu@5d240000" |
1970 | }; | 1991 | }; |
1971 | 1992 | ||
1972 | /* Each MU ownes 1M buffer */ | 1993 | /* Each MU ownes 1M buffer */ |
1973 | if (size <= 0x100000) { | 1994 | if (size <= 0x100000) { |
1974 | if (!strcmp(node->mu_dev->name, m4_mu_name[0])) | 1995 | if (!strcmp(node->mu_dev->name, m4_mu_name[0])) |
1975 | return (void * )CONFIG_IMX_VSERVICE_SHARED_BUFFER; | 1996 | return (void * )CONFIG_IMX_VSERVICE_SHARED_BUFFER; |
1976 | else if (!strcmp(node->mu_dev->name, m4_mu_name[1])) | 1997 | else if (!strcmp(node->mu_dev->name, m4_mu_name[1])) |
1977 | return (void * )(CONFIG_IMX_VSERVICE_SHARED_BUFFER + 0x100000); | 1998 | return (void * )(CONFIG_IMX_VSERVICE_SHARED_BUFFER + 0x100000); |
1978 | else | 1999 | else |
1979 | return NULL; | 2000 | return NULL; |
1980 | } | 2001 | } |
1981 | 2002 | ||
1982 | return NULL; | 2003 | return NULL; |
1983 | } | 2004 | } |
1984 | #endif | 2005 | #endif |
1985 | 2006 | ||
1986 | /* imx8qxp i2c1 has lots of devices may used by both M4 and A core | 2007 | /* imx8qxp i2c1 has lots of devices may used by both M4 and A core |
1987 | * If A core partition does not own the resource, we will start | 2008 | * If A core partition does not own the resource, we will start |
1988 | * virtual i2c driver. Otherwise use local i2c driver. | 2009 | * virtual i2c driver. Otherwise use local i2c driver. |
1989 | */ | 2010 | */ |
1990 | int board_imx_virt_i2c_bind(struct udevice *dev) | 2011 | int board_imx_virt_i2c_bind(struct udevice *dev) |
1991 | { | 2012 | { |
1992 | if (check_owned_udevice(dev)) | 2013 | if (check_owned_udevice(dev)) |
1993 | return -ENODEV; | 2014 | return -ENODEV; |
1994 | 2015 | ||
1995 | return 0; | 2016 | return 0; |
1996 | } | 2017 | } |
1997 | 2018 | ||
1998 | int board_imx_lpi2c_bind(struct udevice *dev) | 2019 | int board_imx_lpi2c_bind(struct udevice *dev) |
1999 | { | 2020 | { |
2000 | if (check_owned_udevice(dev)) | 2021 | if (check_owned_udevice(dev)) |
2001 | return 0; | 2022 | return 0; |
2002 | 2023 | ||
2003 | return -ENODEV; | 2024 | return -ENODEV; |
2004 | } | 2025 | } |
2005 | 2026 | ||
2006 | void board_boot_order(u32 *spl_boot_list) | 2027 | void board_boot_order(u32 *spl_boot_list) |
2007 | { | 2028 | { |
2008 | spl_boot_list[0] = spl_boot_device(); | 2029 | spl_boot_list[0] = spl_boot_device(); |
2009 | 2030 | ||
2010 | if (spl_boot_list[0] == BOOT_DEVICE_SPI) { | 2031 | if (spl_boot_list[0] == BOOT_DEVICE_SPI) { |
2011 | /* Check whether we own the flexspi0, if not, use NOR boot */ | 2032 | /* Check whether we own the flexspi0, if not, use NOR boot */ |
2012 | if (!check_owned_resource(SC_R_FSPI_0)) | 2033 | if (!check_owned_resource(SC_R_FSPI_0)) |
2013 | spl_boot_list[0] = BOOT_DEVICE_NOR; | 2034 | spl_boot_list[0] = BOOT_DEVICE_NOR; |
2014 | } | 2035 | } |
2015 | } | 2036 | } |
2016 | 2037 | ||
2017 | #ifdef CONFIG_USB_PORT_AUTO | 2038 | #ifdef CONFIG_USB_PORT_AUTO |
2018 | int board_usb_gadget_port_auto(void) | 2039 | int board_usb_gadget_port_auto(void) |
2019 | { | 2040 | { |
2020 | int ret; | 2041 | int ret; |
2021 | u32 usb2_data; | 2042 | u32 usb2_data; |
2022 | struct power_domain pd; | 2043 | struct power_domain pd; |
2023 | struct power_domain phy_pd; | 2044 | struct power_domain phy_pd; |
2024 | 2045 | ||
2025 | if (!power_domain_lookup_name("conn_usb0", &pd)) { | 2046 | if (!power_domain_lookup_name("conn_usb0", &pd)) { |
2026 | ret = power_domain_on(&pd); | 2047 | ret = power_domain_on(&pd); |
2027 | if (ret) { | 2048 | if (ret) { |
2028 | printf("conn_usb0 Power up failed!\n"); | 2049 | printf("conn_usb0 Power up failed!\n"); |
2029 | return ret; | 2050 | return ret; |
2030 | } | 2051 | } |
2031 | 2052 | ||
2032 | if (!power_domain_lookup_name("conn_usb0_phy", &phy_pd)) { | 2053 | if (!power_domain_lookup_name("conn_usb0_phy", &phy_pd)) { |
2033 | ret = power_domain_on(&phy_pd); | 2054 | ret = power_domain_on(&phy_pd); |
2034 | if (ret) { | 2055 | if (ret) { |
2035 | printf("conn_usb0_phy Power up failed!\n"); | 2056 | printf("conn_usb0_phy Power up failed!\n"); |
2036 | return ret; | 2057 | return ret; |
2037 | } | 2058 | } |
2038 | } else { | 2059 | } else { |
2039 | return -1; | 2060 | return -1; |
2040 | } | 2061 | } |
2041 | 2062 | ||
2042 | enable_usboh3_clk(1); | 2063 | enable_usboh3_clk(1); |
2043 | usb2_data = readl(USB_BASE_ADDR + 0x154); | 2064 | usb2_data = readl(USB_BASE_ADDR + 0x154); |
2044 | 2065 | ||
2045 | ret = power_domain_off(&phy_pd); | 2066 | ret = power_domain_off(&phy_pd); |
2046 | if (ret) { | 2067 | if (ret) { |
2047 | printf("conn_usb0_phy Power off failed!\n"); | 2068 | printf("conn_usb0_phy Power off failed!\n"); |
2048 | return ret; | 2069 | return ret; |
2049 | } | 2070 | } |
2050 | ret = power_domain_off(&pd); | 2071 | ret = power_domain_off(&pd); |
2051 | if (ret) { | 2072 | if (ret) { |
2052 | printf("conn_usb0 Power off failed!\n"); | 2073 | printf("conn_usb0 Power off failed!\n"); |
2053 | return ret; | 2074 | return ret; |
2054 | } | 2075 | } |
2055 | 2076 | ||
2056 | if (!usb2_data) | 2077 | if (!usb2_data) |
2057 | return 1; | 2078 | return 1; |
2058 | else | 2079 | else |
2059 | return 0; | 2080 | return 0; |
2060 | } | 2081 | } |
2061 | return -1; | 2082 | return -1; |
2062 | } | 2083 | } |
2063 | #endif | 2084 | #endif |
2064 | 2085 |