xref: /openbmc/u-boot/arch/arm/mach-imx/imx8/cpu.c (revision 3d7891d3)
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