160d33fcdSPeng Fan // SPDX-License-Identifier: GPL-2.0+
260d33fcdSPeng Fan /*
360d33fcdSPeng Fan * Copyright 2018 NXP
460d33fcdSPeng Fan */
560d33fcdSPeng Fan
660d33fcdSPeng Fan #include <common.h>
760d33fcdSPeng Fan #include <clk.h>
82fdb1a1dSAnatolij Gustschin #include <cpu.h>
960d33fcdSPeng Fan #include <dm.h>
1060d33fcdSPeng Fan #include <dm/device-internal.h>
1160d33fcdSPeng Fan #include <dm/lists.h>
1260d33fcdSPeng Fan #include <dm/uclass.h>
1360d33fcdSPeng Fan #include <errno.h>
1460d33fcdSPeng Fan #include <asm/arch/sci/sci.h>
158aa1505bSPeng Fan #include <asm/arch/sys_proto.h>
1660d33fcdSPeng Fan #include <asm/arch-imx/cpu.h>
1760d33fcdSPeng Fan #include <asm/armv8/cpu.h>
18930b5952SPeng Fan #include <asm/armv8/mmu.h>
198aa1505bSPeng Fan #include <asm/mach-imx/boot_mode.h>
2060d33fcdSPeng Fan
2160d33fcdSPeng Fan DECLARE_GLOBAL_DATA_PTR;
2260d33fcdSPeng Fan
231ef20a3dSPeng Fan #define BT_PASSOVER_TAG 0x504F
get_pass_over_info(void)241ef20a3dSPeng Fan struct pass_over_info_t *get_pass_over_info(void)
251ef20a3dSPeng Fan {
261ef20a3dSPeng Fan struct pass_over_info_t *p =
271ef20a3dSPeng Fan (struct pass_over_info_t *)PASS_OVER_INFO_ADDR;
281ef20a3dSPeng Fan
291ef20a3dSPeng Fan if (p->barker != BT_PASSOVER_TAG ||
301ef20a3dSPeng Fan p->len != sizeof(struct pass_over_info_t))
311ef20a3dSPeng Fan return NULL;
321ef20a3dSPeng Fan
331ef20a3dSPeng Fan return p;
341ef20a3dSPeng Fan }
351ef20a3dSPeng Fan
arch_cpu_init(void)361ef20a3dSPeng Fan int arch_cpu_init(void)
371ef20a3dSPeng Fan {
389382f73bSPeng Fan #ifdef CONFIG_SPL_BUILD
399382f73bSPeng Fan struct pass_over_info_t *pass_over;
401ef20a3dSPeng Fan
419382f73bSPeng Fan if (is_soc_rev(CHIP_REV_A)) {
429382f73bSPeng Fan pass_over = get_pass_over_info();
431ef20a3dSPeng Fan if (pass_over && pass_over->g_ap_mu == 0) {
441ef20a3dSPeng Fan /*
451ef20a3dSPeng Fan * When ap_mu is 0, means the U-Boot booted
461ef20a3dSPeng Fan * from first container
471ef20a3dSPeng Fan */
481ef20a3dSPeng Fan sc_misc_boot_status(-1, SC_MISC_BOOT_STATUS_SUCCESS);
491ef20a3dSPeng Fan }
509382f73bSPeng Fan }
519382f73bSPeng Fan #endif
521ef20a3dSPeng Fan
531ef20a3dSPeng Fan return 0;
541ef20a3dSPeng Fan }
551ef20a3dSPeng Fan
arch_cpu_init_dm(void)561ef20a3dSPeng Fan int arch_cpu_init_dm(void)
571ef20a3dSPeng Fan {
581ef20a3dSPeng Fan struct udevice *devp;
591ef20a3dSPeng Fan int node, ret;
601ef20a3dSPeng Fan
611ef20a3dSPeng Fan node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "fsl,imx8-mu");
621ef20a3dSPeng Fan ret = device_bind_driver_to_node(gd->dm_root, "imx8_scu", "imx8_scu",
631ef20a3dSPeng Fan offset_to_ofnode(node), &devp);
641ef20a3dSPeng Fan
651ef20a3dSPeng Fan if (ret) {
661ef20a3dSPeng Fan printf("could not find scu %d\n", ret);
671ef20a3dSPeng Fan return ret;
681ef20a3dSPeng Fan }
691ef20a3dSPeng Fan
701ef20a3dSPeng Fan ret = device_probe(devp);
711ef20a3dSPeng Fan if (ret) {
721ef20a3dSPeng Fan printf("scu probe failed %d\n", ret);
731ef20a3dSPeng Fan return ret;
741ef20a3dSPeng Fan }
751ef20a3dSPeng Fan
761ef20a3dSPeng Fan return 0;
771ef20a3dSPeng Fan }
781ef20a3dSPeng Fan
print_bootinfo(void)798aa1505bSPeng Fan int print_bootinfo(void)
808aa1505bSPeng Fan {
818aa1505bSPeng Fan enum boot_device bt_dev = get_boot_device();
828aa1505bSPeng Fan
838aa1505bSPeng Fan puts("Boot: ");
848aa1505bSPeng Fan switch (bt_dev) {
858aa1505bSPeng Fan case SD1_BOOT:
868aa1505bSPeng Fan puts("SD0\n");
878aa1505bSPeng Fan break;
888aa1505bSPeng Fan case SD2_BOOT:
898aa1505bSPeng Fan puts("SD1\n");
908aa1505bSPeng Fan break;
918aa1505bSPeng Fan case SD3_BOOT:
928aa1505bSPeng Fan puts("SD2\n");
938aa1505bSPeng Fan break;
948aa1505bSPeng Fan case MMC1_BOOT:
958aa1505bSPeng Fan puts("MMC0\n");
968aa1505bSPeng Fan break;
978aa1505bSPeng Fan case MMC2_BOOT:
988aa1505bSPeng Fan puts("MMC1\n");
998aa1505bSPeng Fan break;
1008aa1505bSPeng Fan case MMC3_BOOT:
1018aa1505bSPeng Fan puts("MMC2\n");
1028aa1505bSPeng Fan break;
1038aa1505bSPeng Fan case FLEXSPI_BOOT:
1048aa1505bSPeng Fan puts("FLEXSPI\n");
1058aa1505bSPeng Fan break;
1068aa1505bSPeng Fan case SATA_BOOT:
1078aa1505bSPeng Fan puts("SATA\n");
1088aa1505bSPeng Fan break;
1098aa1505bSPeng Fan case NAND_BOOT:
1108aa1505bSPeng Fan puts("NAND\n");
1118aa1505bSPeng Fan break;
1128aa1505bSPeng Fan case USB_BOOT:
1138aa1505bSPeng Fan puts("USB\n");
1148aa1505bSPeng Fan break;
1158aa1505bSPeng Fan default:
1168aa1505bSPeng Fan printf("Unknown device %u\n", bt_dev);
1178aa1505bSPeng Fan break;
1188aa1505bSPeng Fan }
1198aa1505bSPeng Fan
1208aa1505bSPeng Fan return 0;
1218aa1505bSPeng Fan }
1228aa1505bSPeng Fan
get_boot_device(void)1238aa1505bSPeng Fan enum boot_device get_boot_device(void)
1248aa1505bSPeng Fan {
1258aa1505bSPeng Fan enum boot_device boot_dev = SD1_BOOT;
1268aa1505bSPeng Fan
1278aa1505bSPeng Fan sc_rsrc_t dev_rsrc;
1288aa1505bSPeng Fan
1298aa1505bSPeng Fan sc_misc_get_boot_dev(-1, &dev_rsrc);
1308aa1505bSPeng Fan
1318aa1505bSPeng Fan switch (dev_rsrc) {
1328aa1505bSPeng Fan case SC_R_SDHC_0:
1338aa1505bSPeng Fan boot_dev = MMC1_BOOT;
1348aa1505bSPeng Fan break;
1358aa1505bSPeng Fan case SC_R_SDHC_1:
1368aa1505bSPeng Fan boot_dev = SD2_BOOT;
1378aa1505bSPeng Fan break;
1388aa1505bSPeng Fan case SC_R_SDHC_2:
1398aa1505bSPeng Fan boot_dev = SD3_BOOT;
1408aa1505bSPeng Fan break;
1418aa1505bSPeng Fan case SC_R_NAND:
1428aa1505bSPeng Fan boot_dev = NAND_BOOT;
1438aa1505bSPeng Fan break;
1448aa1505bSPeng Fan case SC_R_FSPI_0:
1458aa1505bSPeng Fan boot_dev = FLEXSPI_BOOT;
1468aa1505bSPeng Fan break;
1478aa1505bSPeng Fan case SC_R_SATA_0:
1488aa1505bSPeng Fan boot_dev = SATA_BOOT;
1498aa1505bSPeng Fan break;
1508aa1505bSPeng Fan case SC_R_USB_0:
1518aa1505bSPeng Fan case SC_R_USB_1:
1528aa1505bSPeng Fan case SC_R_USB_2:
1538aa1505bSPeng Fan boot_dev = USB_BOOT;
1548aa1505bSPeng Fan break;
1558aa1505bSPeng Fan default:
1568aa1505bSPeng Fan break;
1578aa1505bSPeng Fan }
1588aa1505bSPeng Fan
1598aa1505bSPeng Fan return boot_dev;
1608aa1505bSPeng Fan }
161c1aae21dSPeng Fan
162c1aae21dSPeng Fan #ifdef CONFIG_ENV_IS_IN_MMC
board_mmc_get_env_dev(int devno)163c1aae21dSPeng Fan __weak int board_mmc_get_env_dev(int devno)
164c1aae21dSPeng Fan {
165c1aae21dSPeng Fan return CONFIG_SYS_MMC_ENV_DEV;
166c1aae21dSPeng Fan }
167c1aae21dSPeng Fan
mmc_get_env_dev(void)168c1aae21dSPeng Fan int mmc_get_env_dev(void)
169c1aae21dSPeng Fan {
170c1aae21dSPeng Fan sc_rsrc_t dev_rsrc;
171c1aae21dSPeng Fan int devno;
172c1aae21dSPeng Fan
173c1aae21dSPeng Fan sc_misc_get_boot_dev(-1, &dev_rsrc);
174c1aae21dSPeng Fan
175c1aae21dSPeng Fan switch (dev_rsrc) {
176c1aae21dSPeng Fan case SC_R_SDHC_0:
177c1aae21dSPeng Fan devno = 0;
178c1aae21dSPeng Fan break;
179c1aae21dSPeng Fan case SC_R_SDHC_1:
180c1aae21dSPeng Fan devno = 1;
181c1aae21dSPeng Fan break;
182c1aae21dSPeng Fan case SC_R_SDHC_2:
183c1aae21dSPeng Fan devno = 2;
184c1aae21dSPeng Fan break;
185c1aae21dSPeng Fan default:
186c1aae21dSPeng Fan /* If not boot from sd/mmc, use default value */
187c1aae21dSPeng Fan return CONFIG_SYS_MMC_ENV_DEV;
188c1aae21dSPeng Fan }
189c1aae21dSPeng Fan
190c1aae21dSPeng Fan return board_mmc_get_env_dev(devno);
191c1aae21dSPeng Fan }
192c1aae21dSPeng Fan #endif
193930b5952SPeng Fan
194930b5952SPeng Fan #define MEMSTART_ALIGNMENT SZ_2M /* Align the memory start with 2MB */
195930b5952SPeng Fan
get_owned_memreg(sc_rm_mr_t mr,sc_faddr_t * addr_start,sc_faddr_t * addr_end)196930b5952SPeng Fan static int get_owned_memreg(sc_rm_mr_t mr, sc_faddr_t *addr_start,
197930b5952SPeng Fan sc_faddr_t *addr_end)
198930b5952SPeng Fan {
199930b5952SPeng Fan sc_faddr_t start, end;
200930b5952SPeng Fan int ret;
201930b5952SPeng Fan bool owned;
202930b5952SPeng Fan
203930b5952SPeng Fan owned = sc_rm_is_memreg_owned(-1, mr);
204930b5952SPeng Fan if (owned) {
205930b5952SPeng Fan ret = sc_rm_get_memreg_info(-1, mr, &start, &end);
206930b5952SPeng Fan if (ret) {
207930b5952SPeng Fan printf("Memreg get info failed, %d\n", ret);
208930b5952SPeng Fan return -EINVAL;
209930b5952SPeng Fan }
210930b5952SPeng Fan debug("0x%llx -- 0x%llx\n", start, end);
211930b5952SPeng Fan *addr_start = start;
212930b5952SPeng Fan *addr_end = end;
213930b5952SPeng Fan
214930b5952SPeng Fan return 0;
215930b5952SPeng Fan }
216930b5952SPeng Fan
217930b5952SPeng Fan return -EINVAL;
218930b5952SPeng Fan }
219930b5952SPeng Fan
get_effective_memsize(void)220930b5952SPeng Fan phys_size_t get_effective_memsize(void)
221930b5952SPeng Fan {
222930b5952SPeng Fan sc_rm_mr_t mr;
223930b5952SPeng Fan sc_faddr_t start, end, end1;
224930b5952SPeng Fan int err;
225930b5952SPeng Fan
226930b5952SPeng Fan end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE;
227930b5952SPeng Fan
228930b5952SPeng Fan for (mr = 0; mr < 64; mr++) {
229930b5952SPeng Fan err = get_owned_memreg(mr, &start, &end);
230930b5952SPeng Fan if (!err) {
231930b5952SPeng Fan start = roundup(start, MEMSTART_ALIGNMENT);
232930b5952SPeng Fan /* Too small memory region, not use it */
233930b5952SPeng Fan if (start > end)
234930b5952SPeng Fan continue;
235930b5952SPeng Fan
2361ef20a3dSPeng Fan /* Find the memory region runs the U-Boot */
237930b5952SPeng Fan if (start >= PHYS_SDRAM_1 && start <= end1 &&
238930b5952SPeng Fan (start <= CONFIG_SYS_TEXT_BASE &&
239930b5952SPeng Fan end >= CONFIG_SYS_TEXT_BASE)) {
240930b5952SPeng Fan if ((end + 1) <= ((sc_faddr_t)PHYS_SDRAM_1 +
241930b5952SPeng Fan PHYS_SDRAM_1_SIZE))
242930b5952SPeng Fan return (end - PHYS_SDRAM_1 + 1);
243930b5952SPeng Fan else
244930b5952SPeng Fan return PHYS_SDRAM_1_SIZE;
245930b5952SPeng Fan }
246930b5952SPeng Fan }
247930b5952SPeng Fan }
248930b5952SPeng Fan
249930b5952SPeng Fan return PHYS_SDRAM_1_SIZE;
250930b5952SPeng Fan }
251930b5952SPeng Fan
dram_init(void)252930b5952SPeng Fan int dram_init(void)
253930b5952SPeng Fan {
254930b5952SPeng Fan sc_rm_mr_t mr;
255930b5952SPeng Fan sc_faddr_t start, end, end1, end2;
256930b5952SPeng Fan int err;
257930b5952SPeng Fan
258930b5952SPeng Fan end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE;
259930b5952SPeng Fan end2 = (sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE;
260930b5952SPeng Fan for (mr = 0; mr < 64; mr++) {
261930b5952SPeng Fan err = get_owned_memreg(mr, &start, &end);
262930b5952SPeng Fan if (!err) {
263930b5952SPeng Fan start = roundup(start, MEMSTART_ALIGNMENT);
264930b5952SPeng Fan /* Too small memory region, not use it */
265930b5952SPeng Fan if (start > end)
266930b5952SPeng Fan continue;
267930b5952SPeng Fan
268930b5952SPeng Fan if (start >= PHYS_SDRAM_1 && start <= end1) {
269930b5952SPeng Fan if ((end + 1) <= end1)
270930b5952SPeng Fan gd->ram_size += end - start + 1;
271930b5952SPeng Fan else
272930b5952SPeng Fan gd->ram_size += end1 - start;
273930b5952SPeng Fan } else if (start >= PHYS_SDRAM_2 && start <= end2) {
274930b5952SPeng Fan if ((end + 1) <= end2)
275930b5952SPeng Fan gd->ram_size += end - start + 1;
276930b5952SPeng Fan else
277930b5952SPeng Fan gd->ram_size += end2 - start;
278930b5952SPeng Fan }
279930b5952SPeng Fan }
280930b5952SPeng Fan }
281930b5952SPeng Fan
282930b5952SPeng Fan /* If error, set to the default value */
283930b5952SPeng Fan if (!gd->ram_size) {
284930b5952SPeng Fan gd->ram_size = PHYS_SDRAM_1_SIZE;
285930b5952SPeng Fan gd->ram_size += PHYS_SDRAM_2_SIZE;
286930b5952SPeng Fan }
287930b5952SPeng Fan return 0;
288930b5952SPeng Fan }
289930b5952SPeng Fan
dram_bank_sort(int current_bank)290930b5952SPeng Fan static void dram_bank_sort(int current_bank)
291930b5952SPeng Fan {
292930b5952SPeng Fan phys_addr_t start;
293930b5952SPeng Fan phys_size_t size;
294930b5952SPeng Fan
295930b5952SPeng Fan while (current_bank > 0) {
296930b5952SPeng Fan if (gd->bd->bi_dram[current_bank - 1].start >
297930b5952SPeng Fan gd->bd->bi_dram[current_bank].start) {
298930b5952SPeng Fan start = gd->bd->bi_dram[current_bank - 1].start;
299930b5952SPeng Fan size = gd->bd->bi_dram[current_bank - 1].size;
300930b5952SPeng Fan
301930b5952SPeng Fan gd->bd->bi_dram[current_bank - 1].start =
302930b5952SPeng Fan gd->bd->bi_dram[current_bank].start;
303930b5952SPeng Fan gd->bd->bi_dram[current_bank - 1].size =
304930b5952SPeng Fan gd->bd->bi_dram[current_bank].size;
305930b5952SPeng Fan
306930b5952SPeng Fan gd->bd->bi_dram[current_bank].start = start;
307930b5952SPeng Fan gd->bd->bi_dram[current_bank].size = size;
308930b5952SPeng Fan }
309930b5952SPeng Fan current_bank--;
310930b5952SPeng Fan }
311930b5952SPeng Fan }
312930b5952SPeng Fan
dram_init_banksize(void)313930b5952SPeng Fan int dram_init_banksize(void)
314930b5952SPeng Fan {
315930b5952SPeng Fan sc_rm_mr_t mr;
316930b5952SPeng Fan sc_faddr_t start, end, end1, end2;
317930b5952SPeng Fan int i = 0;
318930b5952SPeng Fan int err;
319930b5952SPeng Fan
320930b5952SPeng Fan end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE;
321930b5952SPeng Fan end2 = (sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE;
322930b5952SPeng Fan
323930b5952SPeng Fan for (mr = 0; mr < 64 && i < CONFIG_NR_DRAM_BANKS; mr++) {
324930b5952SPeng Fan err = get_owned_memreg(mr, &start, &end);
325930b5952SPeng Fan if (!err) {
326930b5952SPeng Fan start = roundup(start, MEMSTART_ALIGNMENT);
327930b5952SPeng Fan if (start > end) /* Small memory region, no use it */
328930b5952SPeng Fan continue;
329930b5952SPeng Fan
330930b5952SPeng Fan if (start >= PHYS_SDRAM_1 && start <= end1) {
331930b5952SPeng Fan gd->bd->bi_dram[i].start = start;
332930b5952SPeng Fan
333930b5952SPeng Fan if ((end + 1) <= end1)
334930b5952SPeng Fan gd->bd->bi_dram[i].size =
335930b5952SPeng Fan end - start + 1;
336930b5952SPeng Fan else
337930b5952SPeng Fan gd->bd->bi_dram[i].size = end1 - start;
338930b5952SPeng Fan
339930b5952SPeng Fan dram_bank_sort(i);
340930b5952SPeng Fan i++;
341930b5952SPeng Fan } else if (start >= PHYS_SDRAM_2 && start <= end2) {
342930b5952SPeng Fan gd->bd->bi_dram[i].start = start;
343930b5952SPeng Fan
344930b5952SPeng Fan if ((end + 1) <= end2)
345930b5952SPeng Fan gd->bd->bi_dram[i].size =
346930b5952SPeng Fan end - start + 1;
347930b5952SPeng Fan else
348930b5952SPeng Fan gd->bd->bi_dram[i].size = end2 - start;
349930b5952SPeng Fan
350930b5952SPeng Fan dram_bank_sort(i);
351930b5952SPeng Fan i++;
352930b5952SPeng Fan }
353930b5952SPeng Fan }
354930b5952SPeng Fan }
355930b5952SPeng Fan
356930b5952SPeng Fan /* If error, set to the default value */
357930b5952SPeng Fan if (!i) {
358930b5952SPeng Fan gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
359930b5952SPeng Fan gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
360930b5952SPeng Fan gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
361930b5952SPeng Fan gd->bd->bi_dram[1].size = PHYS_SDRAM_2_SIZE;
362930b5952SPeng Fan }
363930b5952SPeng Fan
364930b5952SPeng Fan return 0;
365930b5952SPeng Fan }
366930b5952SPeng Fan
get_block_attrs(sc_faddr_t addr_start)367930b5952SPeng Fan static u64 get_block_attrs(sc_faddr_t addr_start)
368930b5952SPeng Fan {
369930b5952SPeng Fan u64 attr = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE |
370930b5952SPeng Fan PTE_BLOCK_PXN | PTE_BLOCK_UXN;
371930b5952SPeng Fan
372930b5952SPeng Fan if ((addr_start >= PHYS_SDRAM_1 &&
373930b5952SPeng Fan addr_start <= ((sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE)) ||
374930b5952SPeng Fan (addr_start >= PHYS_SDRAM_2 &&
375930b5952SPeng Fan addr_start <= ((sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE)))
376930b5952SPeng Fan return (PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_OUTER_SHARE);
377930b5952SPeng Fan
378930b5952SPeng Fan return attr;
379930b5952SPeng Fan }
380930b5952SPeng Fan
get_block_size(sc_faddr_t addr_start,sc_faddr_t addr_end)381930b5952SPeng Fan static u64 get_block_size(sc_faddr_t addr_start, sc_faddr_t addr_end)
382930b5952SPeng Fan {
383930b5952SPeng Fan sc_faddr_t end1, end2;
384930b5952SPeng Fan
385930b5952SPeng Fan end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE;
386930b5952SPeng Fan end2 = (sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE;
387930b5952SPeng Fan
388930b5952SPeng Fan if (addr_start >= PHYS_SDRAM_1 && addr_start <= end1) {
389930b5952SPeng Fan if ((addr_end + 1) > end1)
390930b5952SPeng Fan return end1 - addr_start;
391930b5952SPeng Fan } else if (addr_start >= PHYS_SDRAM_2 && addr_start <= end2) {
392930b5952SPeng Fan if ((addr_end + 1) > end2)
393930b5952SPeng Fan return end2 - addr_start;
394930b5952SPeng Fan }
395930b5952SPeng Fan
396930b5952SPeng Fan return (addr_end - addr_start + 1);
397930b5952SPeng Fan }
398930b5952SPeng Fan
399930b5952SPeng Fan #define MAX_PTE_ENTRIES 512
400930b5952SPeng Fan #define MAX_MEM_MAP_REGIONS 16
401930b5952SPeng Fan
402930b5952SPeng Fan static struct mm_region imx8_mem_map[MAX_MEM_MAP_REGIONS];
403930b5952SPeng Fan struct mm_region *mem_map = imx8_mem_map;
404930b5952SPeng Fan
enable_caches(void)405930b5952SPeng Fan void enable_caches(void)
406930b5952SPeng Fan {
407930b5952SPeng Fan sc_rm_mr_t mr;
408930b5952SPeng Fan sc_faddr_t start, end;
409930b5952SPeng Fan int err, i;
410930b5952SPeng Fan
411930b5952SPeng Fan /* Create map for registers access from 0x1c000000 to 0x80000000*/
412930b5952SPeng Fan imx8_mem_map[0].virt = 0x1c000000UL;
413930b5952SPeng Fan imx8_mem_map[0].phys = 0x1c000000UL;
414930b5952SPeng Fan imx8_mem_map[0].size = 0x64000000UL;
415930b5952SPeng Fan imx8_mem_map[0].attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
416930b5952SPeng Fan PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN;
417930b5952SPeng Fan
418930b5952SPeng Fan i = 1;
419930b5952SPeng Fan for (mr = 0; mr < 64 && i < MAX_MEM_MAP_REGIONS; mr++) {
420930b5952SPeng Fan err = get_owned_memreg(mr, &start, &end);
421930b5952SPeng Fan if (!err) {
422930b5952SPeng Fan imx8_mem_map[i].virt = start;
423930b5952SPeng Fan imx8_mem_map[i].phys = start;
424930b5952SPeng Fan imx8_mem_map[i].size = get_block_size(start, end);
425930b5952SPeng Fan imx8_mem_map[i].attrs = get_block_attrs(start);
426930b5952SPeng Fan i++;
427930b5952SPeng Fan }
428930b5952SPeng Fan }
429930b5952SPeng Fan
430930b5952SPeng Fan if (i < MAX_MEM_MAP_REGIONS) {
431930b5952SPeng Fan imx8_mem_map[i].size = 0;
432930b5952SPeng Fan imx8_mem_map[i].attrs = 0;
433930b5952SPeng Fan } else {
434930b5952SPeng Fan puts("Error, need more MEM MAP REGIONS reserved\n");
435930b5952SPeng Fan icache_enable();
436930b5952SPeng Fan return;
437930b5952SPeng Fan }
438930b5952SPeng Fan
439930b5952SPeng Fan for (i = 0; i < MAX_MEM_MAP_REGIONS; i++) {
440930b5952SPeng Fan debug("[%d] vir = 0x%llx phys = 0x%llx size = 0x%llx attrs = 0x%llx\n",
441930b5952SPeng Fan i, imx8_mem_map[i].virt, imx8_mem_map[i].phys,
442930b5952SPeng Fan imx8_mem_map[i].size, imx8_mem_map[i].attrs);
443930b5952SPeng Fan }
444930b5952SPeng Fan
445930b5952SPeng Fan icache_enable();
446930b5952SPeng Fan dcache_enable();
447930b5952SPeng Fan }
448930b5952SPeng Fan
449930b5952SPeng Fan #ifndef CONFIG_SYS_DCACHE_OFF
get_page_table_size(void)450930b5952SPeng Fan u64 get_page_table_size(void)
451930b5952SPeng Fan {
452930b5952SPeng Fan u64 one_pt = MAX_PTE_ENTRIES * sizeof(u64);
453930b5952SPeng Fan u64 size = 0;
454930b5952SPeng Fan
455930b5952SPeng Fan /*
456930b5952SPeng Fan * For each memory region, the max table size:
457930b5952SPeng Fan * 2 level 3 tables + 2 level 2 tables + 1 level 1 table
458930b5952SPeng Fan */
459930b5952SPeng Fan size = (2 + 2 + 1) * one_pt * MAX_MEM_MAP_REGIONS + one_pt;
460930b5952SPeng Fan
461930b5952SPeng Fan /*
462930b5952SPeng Fan * We need to duplicate our page table once to have an emergency pt to
463930b5952SPeng Fan * resort to when splitting page tables later on
464930b5952SPeng Fan */
465930b5952SPeng Fan size *= 2;
466930b5952SPeng Fan
467930b5952SPeng Fan /*
468930b5952SPeng Fan * We may need to split page tables later on if dcache settings change,
469930b5952SPeng Fan * so reserve up to 4 (random pick) page tables for that.
470930b5952SPeng Fan */
471930b5952SPeng Fan size += one_pt * 4;
472930b5952SPeng Fan
473930b5952SPeng Fan return size;
474930b5952SPeng Fan }
475930b5952SPeng Fan #endif
47670b4b49bSAnatolij Gustschin
47770b4b49bSAnatolij Gustschin #define FUSE_MAC0_WORD0 708
47870b4b49bSAnatolij Gustschin #define FUSE_MAC0_WORD1 709
47970b4b49bSAnatolij Gustschin #define FUSE_MAC1_WORD0 710
48070b4b49bSAnatolij Gustschin #define FUSE_MAC1_WORD1 711
48170b4b49bSAnatolij Gustschin
imx_get_mac_from_fuse(int dev_id,unsigned char * mac)48270b4b49bSAnatolij Gustschin void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
48370b4b49bSAnatolij Gustschin {
48470b4b49bSAnatolij Gustschin u32 word[2], val[2] = {};
48570b4b49bSAnatolij Gustschin int i, ret;
48670b4b49bSAnatolij Gustschin
48770b4b49bSAnatolij Gustschin if (dev_id == 0) {
48870b4b49bSAnatolij Gustschin word[0] = FUSE_MAC0_WORD0;
48970b4b49bSAnatolij Gustschin word[1] = FUSE_MAC0_WORD1;
49070b4b49bSAnatolij Gustschin } else {
49170b4b49bSAnatolij Gustschin word[0] = FUSE_MAC1_WORD0;
49270b4b49bSAnatolij Gustschin word[1] = FUSE_MAC1_WORD1;
49370b4b49bSAnatolij Gustschin }
49470b4b49bSAnatolij Gustschin
49570b4b49bSAnatolij Gustschin for (i = 0; i < 2; i++) {
49670b4b49bSAnatolij Gustschin ret = sc_misc_otp_fuse_read(-1, word[i], &val[i]);
49770b4b49bSAnatolij Gustschin if (ret < 0)
49870b4b49bSAnatolij Gustschin goto err;
49970b4b49bSAnatolij Gustschin }
50070b4b49bSAnatolij Gustschin
50170b4b49bSAnatolij Gustschin mac[0] = val[0];
50270b4b49bSAnatolij Gustschin mac[1] = val[0] >> 8;
50370b4b49bSAnatolij Gustschin mac[2] = val[0] >> 16;
50470b4b49bSAnatolij Gustschin mac[3] = val[0] >> 24;
50570b4b49bSAnatolij Gustschin mac[4] = val[1];
50670b4b49bSAnatolij Gustschin mac[5] = val[1] >> 8;
50770b4b49bSAnatolij Gustschin
50870b4b49bSAnatolij Gustschin debug("%s: MAC%d: %02x.%02x.%02x.%02x.%02x.%02x\n",
50970b4b49bSAnatolij Gustschin __func__, dev_id, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
51070b4b49bSAnatolij Gustschin return;
51170b4b49bSAnatolij Gustschin err:
51270b4b49bSAnatolij Gustschin printf("%s: fuse %d, err: %d\n", __func__, word[i], ret);
51370b4b49bSAnatolij Gustschin }
5142fdb1a1dSAnatolij Gustschin
get_cpu_rev(void)5152fdb1a1dSAnatolij Gustschin u32 get_cpu_rev(void)
5162fdb1a1dSAnatolij Gustschin {
5172fdb1a1dSAnatolij Gustschin u32 id = 0, rev = 0;
5182fdb1a1dSAnatolij Gustschin int ret;
5192fdb1a1dSAnatolij Gustschin
5202fdb1a1dSAnatolij Gustschin ret = sc_misc_get_control(-1, SC_R_SYSTEM, SC_C_ID, &id);
5212fdb1a1dSAnatolij Gustschin if (ret)
5222fdb1a1dSAnatolij Gustschin return 0;
5232fdb1a1dSAnatolij Gustschin
5242fdb1a1dSAnatolij Gustschin rev = (id >> 5) & 0xf;
5252fdb1a1dSAnatolij Gustschin id = (id & 0x1f) + MXC_SOC_IMX8; /* Dummy ID for chip */
5262fdb1a1dSAnatolij Gustschin
5272fdb1a1dSAnatolij Gustschin return (id << 12) | rev;
5282fdb1a1dSAnatolij Gustschin }
5292fdb1a1dSAnatolij Gustschin
5309382f73bSPeng Fan #if CONFIG_IS_ENABLED(CPU)
5319382f73bSPeng Fan struct cpu_imx_platdata {
5329382f73bSPeng Fan const char *name;
5339382f73bSPeng Fan const char *rev;
5349382f73bSPeng Fan const char *type;
5359382f73bSPeng Fan u32 cpurev;
5369382f73bSPeng Fan u32 freq_mhz;
5379382f73bSPeng Fan };
5389382f73bSPeng Fan
get_imx8_type(u32 imxtype)5392fdb1a1dSAnatolij Gustschin const char *get_imx8_type(u32 imxtype)
5402fdb1a1dSAnatolij Gustschin {
5412fdb1a1dSAnatolij Gustschin switch (imxtype) {
5422fdb1a1dSAnatolij Gustschin case MXC_CPU_IMX8QXP:
5432fdb1a1dSAnatolij Gustschin case MXC_CPU_IMX8QXP_A0:
5442fdb1a1dSAnatolij Gustschin return "QXP";
5452fdb1a1dSAnatolij Gustschin default:
5462fdb1a1dSAnatolij Gustschin return "??";
5472fdb1a1dSAnatolij Gustschin }
5482fdb1a1dSAnatolij Gustschin }
5492fdb1a1dSAnatolij Gustschin
get_imx8_rev(u32 rev)5502fdb1a1dSAnatolij Gustschin const char *get_imx8_rev(u32 rev)
5512fdb1a1dSAnatolij Gustschin {
5522fdb1a1dSAnatolij Gustschin switch (rev) {
5532fdb1a1dSAnatolij Gustschin case CHIP_REV_A:
5542fdb1a1dSAnatolij Gustschin return "A";
5552fdb1a1dSAnatolij Gustschin case CHIP_REV_B:
5562fdb1a1dSAnatolij Gustschin return "B";
5572fdb1a1dSAnatolij Gustschin default:
5582fdb1a1dSAnatolij Gustschin return "?";
5592fdb1a1dSAnatolij Gustschin }
5602fdb1a1dSAnatolij Gustschin }
5612fdb1a1dSAnatolij Gustschin
get_core_name(void)5622fdb1a1dSAnatolij Gustschin const char *get_core_name(void)
5632fdb1a1dSAnatolij Gustschin {
5642fdb1a1dSAnatolij Gustschin if (is_cortex_a35())
5652fdb1a1dSAnatolij Gustschin return "A35";
5662fdb1a1dSAnatolij Gustschin else if (is_cortex_a53())
5672fdb1a1dSAnatolij Gustschin return "A53";
5682fdb1a1dSAnatolij Gustschin else if (is_cortex_a72())
5692fdb1a1dSAnatolij Gustschin return "A72";
5702fdb1a1dSAnatolij Gustschin else
5712fdb1a1dSAnatolij Gustschin return "?";
5722fdb1a1dSAnatolij Gustschin }
5732fdb1a1dSAnatolij Gustschin
cpu_imx_get_desc(struct udevice * dev,char * buf,int size)5742fdb1a1dSAnatolij Gustschin int cpu_imx_get_desc(struct udevice *dev, char *buf, int size)
5752fdb1a1dSAnatolij Gustschin {
5762fdb1a1dSAnatolij Gustschin struct cpu_imx_platdata *plat = dev_get_platdata(dev);
5772fdb1a1dSAnatolij Gustschin
5782fdb1a1dSAnatolij Gustschin if (size < 100)
5792fdb1a1dSAnatolij Gustschin return -ENOSPC;
5802fdb1a1dSAnatolij Gustschin
581da72574bSPeng Fan snprintf(buf, size, "NXP i.MX8%s Rev%s %s at %u MHz\n",
5822fdb1a1dSAnatolij Gustschin plat->type, plat->rev, plat->name, plat->freq_mhz);
5832fdb1a1dSAnatolij Gustschin
5842fdb1a1dSAnatolij Gustschin return 0;
5852fdb1a1dSAnatolij Gustschin }
5862fdb1a1dSAnatolij Gustschin
cpu_imx_get_info(struct udevice * dev,struct cpu_info * info)5872fdb1a1dSAnatolij Gustschin static int cpu_imx_get_info(struct udevice *dev, struct cpu_info *info)
5882fdb1a1dSAnatolij Gustschin {
5892fdb1a1dSAnatolij Gustschin struct cpu_imx_platdata *plat = dev_get_platdata(dev);
5902fdb1a1dSAnatolij Gustschin
5912fdb1a1dSAnatolij Gustschin info->cpu_freq = plat->freq_mhz * 1000;
5922fdb1a1dSAnatolij Gustschin info->features = BIT(CPU_FEAT_L1_CACHE) | BIT(CPU_FEAT_MMU);
5932fdb1a1dSAnatolij Gustschin return 0;
5942fdb1a1dSAnatolij Gustschin }
5952fdb1a1dSAnatolij Gustschin
cpu_imx_get_count(struct udevice * dev)5962fdb1a1dSAnatolij Gustschin static int cpu_imx_get_count(struct udevice *dev)
5972fdb1a1dSAnatolij Gustschin {
5982fdb1a1dSAnatolij Gustschin return 4;
5992fdb1a1dSAnatolij Gustschin }
6002fdb1a1dSAnatolij Gustschin
cpu_imx_get_vendor(struct udevice * dev,char * buf,int size)6012fdb1a1dSAnatolij Gustschin static int cpu_imx_get_vendor(struct udevice *dev, char *buf, int size)
6022fdb1a1dSAnatolij Gustschin {
6032fdb1a1dSAnatolij Gustschin snprintf(buf, size, "NXP");
6042fdb1a1dSAnatolij Gustschin return 0;
6052fdb1a1dSAnatolij Gustschin }
6062fdb1a1dSAnatolij Gustschin
6072fdb1a1dSAnatolij Gustschin static const struct cpu_ops cpu_imx8_ops = {
6082fdb1a1dSAnatolij Gustschin .get_desc = cpu_imx_get_desc,
6092fdb1a1dSAnatolij Gustschin .get_info = cpu_imx_get_info,
6102fdb1a1dSAnatolij Gustschin .get_count = cpu_imx_get_count,
6112fdb1a1dSAnatolij Gustschin .get_vendor = cpu_imx_get_vendor,
6122fdb1a1dSAnatolij Gustschin };
6132fdb1a1dSAnatolij Gustschin
6142fdb1a1dSAnatolij Gustschin static const struct udevice_id cpu_imx8_ids[] = {
6152fdb1a1dSAnatolij Gustschin { .compatible = "arm,cortex-a35" },
6162fdb1a1dSAnatolij Gustschin { }
6172fdb1a1dSAnatolij Gustschin };
6182fdb1a1dSAnatolij Gustschin
imx8_get_cpu_rate(void)619*75cd09cbSFabio Estevam static ulong imx8_get_cpu_rate(void)
620*75cd09cbSFabio Estevam {
621*75cd09cbSFabio Estevam ulong rate;
622*75cd09cbSFabio Estevam int ret;
623*75cd09cbSFabio Estevam
624*75cd09cbSFabio Estevam ret = sc_pm_get_clock_rate(-1, SC_R_A35, SC_PM_CLK_CPU,
625*75cd09cbSFabio Estevam (sc_pm_clock_rate_t *)&rate);
626*75cd09cbSFabio Estevam if (ret) {
627*75cd09cbSFabio Estevam printf("Could not read CPU frequency: %d\n", ret);
628*75cd09cbSFabio Estevam return 0;
629*75cd09cbSFabio Estevam }
630*75cd09cbSFabio Estevam
631*75cd09cbSFabio Estevam return rate;
632*75cd09cbSFabio Estevam }
633*75cd09cbSFabio Estevam
imx8_cpu_probe(struct udevice * dev)6342fdb1a1dSAnatolij Gustschin static int imx8_cpu_probe(struct udevice *dev)
6352fdb1a1dSAnatolij Gustschin {
6362fdb1a1dSAnatolij Gustschin struct cpu_imx_platdata *plat = dev_get_platdata(dev);
6372fdb1a1dSAnatolij Gustschin u32 cpurev;
6382fdb1a1dSAnatolij Gustschin
6392fdb1a1dSAnatolij Gustschin cpurev = get_cpu_rev();
6402fdb1a1dSAnatolij Gustschin plat->cpurev = cpurev;
6412fdb1a1dSAnatolij Gustschin plat->name = get_core_name();
6422fdb1a1dSAnatolij Gustschin plat->rev = get_imx8_rev(cpurev & 0xFFF);
6432fdb1a1dSAnatolij Gustschin plat->type = get_imx8_type((cpurev & 0xFF000) >> 12);
644*75cd09cbSFabio Estevam plat->freq_mhz = imx8_get_cpu_rate() / 1000000;
6452fdb1a1dSAnatolij Gustschin return 0;
6462fdb1a1dSAnatolij Gustschin }
6472fdb1a1dSAnatolij Gustschin
6482fdb1a1dSAnatolij Gustschin U_BOOT_DRIVER(cpu_imx8_drv) = {
6492fdb1a1dSAnatolij Gustschin .name = "imx8x_cpu",
6502fdb1a1dSAnatolij Gustschin .id = UCLASS_CPU,
6512fdb1a1dSAnatolij Gustschin .of_match = cpu_imx8_ids,
6522fdb1a1dSAnatolij Gustschin .ops = &cpu_imx8_ops,
6532fdb1a1dSAnatolij Gustschin .probe = imx8_cpu_probe,
6542fdb1a1dSAnatolij Gustschin .platdata_auto_alloc_size = sizeof(struct cpu_imx_platdata),
6552fdb1a1dSAnatolij Gustschin .flags = DM_FLAG_PRE_RELOC,
6562fdb1a1dSAnatolij Gustschin };
6572fdb1a1dSAnatolij Gustschin #endif
658