imx8: add arch_cpu_init arch_cpu_init_dm
[oweals/u-boot.git] / arch / arm / mach-imx / imx8 / cpu.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2018 NXP
4  */
5
6 #include <common.h>
7 #include <clk.h>
8 #include <dm.h>
9 #include <dm/device-internal.h>
10 #include <dm/lists.h>
11 #include <dm/uclass.h>
12 #include <errno.h>
13 #include <asm/arch/sci/sci.h>
14 #include <asm/arch/sys_proto.h>
15 #include <asm/arch-imx/cpu.h>
16 #include <asm/armv8/cpu.h>
17 #include <asm/armv8/mmu.h>
18 #include <asm/mach-imx/boot_mode.h>
19
20 DECLARE_GLOBAL_DATA_PTR;
21
22 u32 get_cpu_rev(void)
23 {
24         u32 id = 0, rev = 0;
25         int ret;
26
27         ret = sc_misc_get_control(-1, SC_R_SYSTEM, SC_C_ID, &id);
28         if (ret)
29                 return 0;
30
31         rev = (id >> 5)  & 0xf;
32         id = (id & 0x1f) + MXC_SOC_IMX8;  /* Dummy ID for chip */
33
34         return (id << 12) | rev;
35 }
36
37 #ifdef CONFIG_DISPLAY_CPUINFO
38 const char *get_imx8_type(u32 imxtype)
39 {
40         switch (imxtype) {
41         case MXC_CPU_IMX8QXP:
42                 return "8QXP";
43         default:
44                 return "??";
45         }
46 }
47
48 const char *get_imx8_rev(u32 rev)
49 {
50         switch (rev) {
51         case CHIP_REV_A:
52                 return "A";
53         case CHIP_REV_B:
54                 return "B";
55         default:
56                 return "?";
57         }
58 }
59
60 const char *get_core_name(void)
61 {
62         if (is_cortex_a35())
63                 return "A35";
64         else
65                 return "?";
66 }
67
68 int print_cpuinfo(void)
69 {
70         struct udevice *dev;
71         struct clk cpu_clk;
72         int ret;
73
74         ret = uclass_get_device(UCLASS_CPU, 0, &dev);
75         if (ret)
76                 return 0;
77
78         ret = clk_get_by_index(dev, 0, &cpu_clk);
79         if (ret) {
80                 dev_err(dev, "failed to clk\n");
81                 return 0;
82         }
83
84         u32 cpurev;
85
86         cpurev = get_cpu_rev();
87
88         printf("CPU:   Freescale i.MX%s rev%s %s at %ld MHz\n",
89                get_imx8_type((cpurev & 0xFF000) >> 12),
90                get_imx8_rev((cpurev & 0xFFF)),
91                get_core_name(),
92                clk_get_rate(&cpu_clk) / 1000000);
93
94         return 0;
95 }
96 #endif
97
98 #define BT_PASSOVER_TAG 0x504F
99 struct pass_over_info_t *get_pass_over_info(void)
100 {
101         struct pass_over_info_t *p =
102                 (struct pass_over_info_t *)PASS_OVER_INFO_ADDR;
103
104         if (p->barker != BT_PASSOVER_TAG ||
105             p->len != sizeof(struct pass_over_info_t))
106                 return NULL;
107
108         return p;
109 }
110
111 int arch_cpu_init(void)
112 {
113         struct pass_over_info_t *pass_over = get_pass_over_info();
114
115         if (pass_over && pass_over->g_ap_mu == 0) {
116                 /*
117                  * When ap_mu is 0, means the U-Boot booted
118                  * from first container
119                  */
120                 sc_misc_boot_status(-1, SC_MISC_BOOT_STATUS_SUCCESS);
121         }
122
123         return 0;
124 }
125
126 int arch_cpu_init_dm(void)
127 {
128         struct udevice *devp;
129         int node, ret;
130
131         node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "fsl,imx8-mu");
132         ret = device_bind_driver_to_node(gd->dm_root, "imx8_scu", "imx8_scu",
133                                          offset_to_ofnode(node), &devp);
134
135         if (ret) {
136                 printf("could not find scu %d\n", ret);
137                 return ret;
138         }
139
140         ret = device_probe(devp);
141         if (ret) {
142                 printf("scu probe failed %d\n", ret);
143                 return ret;
144         }
145
146         return 0;
147 }
148
149 int print_bootinfo(void)
150 {
151         enum boot_device bt_dev = get_boot_device();
152
153         puts("Boot:  ");
154         switch (bt_dev) {
155         case SD1_BOOT:
156                 puts("SD0\n");
157                 break;
158         case SD2_BOOT:
159                 puts("SD1\n");
160                 break;
161         case SD3_BOOT:
162                 puts("SD2\n");
163                 break;
164         case MMC1_BOOT:
165                 puts("MMC0\n");
166                 break;
167         case MMC2_BOOT:
168                 puts("MMC1\n");
169                 break;
170         case MMC3_BOOT:
171                 puts("MMC2\n");
172                 break;
173         case FLEXSPI_BOOT:
174                 puts("FLEXSPI\n");
175                 break;
176         case SATA_BOOT:
177                 puts("SATA\n");
178                 break;
179         case NAND_BOOT:
180                 puts("NAND\n");
181                 break;
182         case USB_BOOT:
183                 puts("USB\n");
184                 break;
185         default:
186                 printf("Unknown device %u\n", bt_dev);
187                 break;
188         }
189
190         return 0;
191 }
192
193 enum boot_device get_boot_device(void)
194 {
195         enum boot_device boot_dev = SD1_BOOT;
196
197         sc_rsrc_t dev_rsrc;
198
199         sc_misc_get_boot_dev(-1, &dev_rsrc);
200
201         switch (dev_rsrc) {
202         case SC_R_SDHC_0:
203                 boot_dev = MMC1_BOOT;
204                 break;
205         case SC_R_SDHC_1:
206                 boot_dev = SD2_BOOT;
207                 break;
208         case SC_R_SDHC_2:
209                 boot_dev = SD3_BOOT;
210                 break;
211         case SC_R_NAND:
212                 boot_dev = NAND_BOOT;
213                 break;
214         case SC_R_FSPI_0:
215                 boot_dev = FLEXSPI_BOOT;
216                 break;
217         case SC_R_SATA_0:
218                 boot_dev = SATA_BOOT;
219                 break;
220         case SC_R_USB_0:
221         case SC_R_USB_1:
222         case SC_R_USB_2:
223                 boot_dev = USB_BOOT;
224                 break;
225         default:
226                 break;
227         }
228
229         return boot_dev;
230 }
231
232 #ifdef CONFIG_ENV_IS_IN_MMC
233 __weak int board_mmc_get_env_dev(int devno)
234 {
235         return CONFIG_SYS_MMC_ENV_DEV;
236 }
237
238 int mmc_get_env_dev(void)
239 {
240         sc_rsrc_t dev_rsrc;
241         int devno;
242
243         sc_misc_get_boot_dev(-1, &dev_rsrc);
244
245         switch (dev_rsrc) {
246         case SC_R_SDHC_0:
247                 devno = 0;
248                 break;
249         case SC_R_SDHC_1:
250                 devno = 1;
251                 break;
252         case SC_R_SDHC_2:
253                 devno = 2;
254                 break;
255         default:
256                 /* If not boot from sd/mmc, use default value */
257                 return CONFIG_SYS_MMC_ENV_DEV;
258         }
259
260         return board_mmc_get_env_dev(devno);
261 }
262 #endif
263
264 #define MEMSTART_ALIGNMENT  SZ_2M /* Align the memory start with 2MB */
265
266 static int get_owned_memreg(sc_rm_mr_t mr, sc_faddr_t *addr_start,
267                             sc_faddr_t *addr_end)
268 {
269         sc_faddr_t start, end;
270         int ret;
271         bool owned;
272
273         owned = sc_rm_is_memreg_owned(-1, mr);
274         if (owned) {
275                 ret = sc_rm_get_memreg_info(-1, mr, &start, &end);
276                 if (ret) {
277                         printf("Memreg get info failed, %d\n", ret);
278                         return -EINVAL;
279                 }
280                 debug("0x%llx -- 0x%llx\n", start, end);
281                 *addr_start = start;
282                 *addr_end = end;
283
284                 return 0;
285         }
286
287         return -EINVAL;
288 }
289
290 phys_size_t get_effective_memsize(void)
291 {
292         sc_rm_mr_t mr;
293         sc_faddr_t start, end, end1;
294         int err;
295
296         end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE;
297
298         for (mr = 0; mr < 64; mr++) {
299                 err = get_owned_memreg(mr, &start, &end);
300                 if (!err) {
301                         start = roundup(start, MEMSTART_ALIGNMENT);
302                         /* Too small memory region, not use it */
303                         if (start > end)
304                                 continue;
305
306                         /* Find the memory region runs the U-Boot */
307                         if (start >= PHYS_SDRAM_1 && start <= end1 &&
308                             (start <= CONFIG_SYS_TEXT_BASE &&
309                             end >= CONFIG_SYS_TEXT_BASE)) {
310                                 if ((end + 1) <= ((sc_faddr_t)PHYS_SDRAM_1 +
311                                     PHYS_SDRAM_1_SIZE))
312                                         return (end - PHYS_SDRAM_1 + 1);
313                                 else
314                                         return PHYS_SDRAM_1_SIZE;
315                         }
316                 }
317         }
318
319         return PHYS_SDRAM_1_SIZE;
320 }
321
322 int dram_init(void)
323 {
324         sc_rm_mr_t mr;
325         sc_faddr_t start, end, end1, end2;
326         int err;
327
328         end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE;
329         end2 = (sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE;
330         for (mr = 0; mr < 64; mr++) {
331                 err = get_owned_memreg(mr, &start, &end);
332                 if (!err) {
333                         start = roundup(start, MEMSTART_ALIGNMENT);
334                         /* Too small memory region, not use it */
335                         if (start > end)
336                                 continue;
337
338                         if (start >= PHYS_SDRAM_1 && start <= end1) {
339                                 if ((end + 1) <= end1)
340                                         gd->ram_size += end - start + 1;
341                                 else
342                                         gd->ram_size += end1 - start;
343                         } else if (start >= PHYS_SDRAM_2 && start <= end2) {
344                                 if ((end + 1) <= end2)
345                                         gd->ram_size += end - start + 1;
346                                 else
347                                         gd->ram_size += end2 - start;
348                         }
349                 }
350         }
351
352         /* If error, set to the default value */
353         if (!gd->ram_size) {
354                 gd->ram_size = PHYS_SDRAM_1_SIZE;
355                 gd->ram_size += PHYS_SDRAM_2_SIZE;
356         }
357         return 0;
358 }
359
360 static void dram_bank_sort(int current_bank)
361 {
362         phys_addr_t start;
363         phys_size_t size;
364
365         while (current_bank > 0) {
366                 if (gd->bd->bi_dram[current_bank - 1].start >
367                     gd->bd->bi_dram[current_bank].start) {
368                         start = gd->bd->bi_dram[current_bank - 1].start;
369                         size = gd->bd->bi_dram[current_bank - 1].size;
370
371                         gd->bd->bi_dram[current_bank - 1].start =
372                                 gd->bd->bi_dram[current_bank].start;
373                         gd->bd->bi_dram[current_bank - 1].size =
374                                 gd->bd->bi_dram[current_bank].size;
375
376                         gd->bd->bi_dram[current_bank].start = start;
377                         gd->bd->bi_dram[current_bank].size = size;
378                 }
379                 current_bank--;
380         }
381 }
382
383 int dram_init_banksize(void)
384 {
385         sc_rm_mr_t mr;
386         sc_faddr_t start, end, end1, end2;
387         int i = 0;
388         int err;
389
390         end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE;
391         end2 = (sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE;
392
393         for (mr = 0; mr < 64 && i < CONFIG_NR_DRAM_BANKS; mr++) {
394                 err = get_owned_memreg(mr, &start, &end);
395                 if (!err) {
396                         start = roundup(start, MEMSTART_ALIGNMENT);
397                         if (start > end) /* Small memory region, no use it */
398                                 continue;
399
400                         if (start >= PHYS_SDRAM_1 && start <= end1) {
401                                 gd->bd->bi_dram[i].start = start;
402
403                                 if ((end + 1) <= end1)
404                                         gd->bd->bi_dram[i].size =
405                                                 end - start + 1;
406                                 else
407                                         gd->bd->bi_dram[i].size = end1 - start;
408
409                                 dram_bank_sort(i);
410                                 i++;
411                         } else if (start >= PHYS_SDRAM_2 && start <= end2) {
412                                 gd->bd->bi_dram[i].start = start;
413
414                                 if ((end + 1) <= end2)
415                                         gd->bd->bi_dram[i].size =
416                                                 end - start + 1;
417                                 else
418                                         gd->bd->bi_dram[i].size = end2 - start;
419
420                                 dram_bank_sort(i);
421                                 i++;
422                         }
423                 }
424         }
425
426         /* If error, set to the default value */
427         if (!i) {
428                 gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
429                 gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
430                 gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
431                 gd->bd->bi_dram[1].size = PHYS_SDRAM_2_SIZE;
432         }
433
434         return 0;
435 }
436
437 static u64 get_block_attrs(sc_faddr_t addr_start)
438 {
439         u64 attr = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE |
440                 PTE_BLOCK_PXN | PTE_BLOCK_UXN;
441
442         if ((addr_start >= PHYS_SDRAM_1 &&
443              addr_start <= ((sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE)) ||
444             (addr_start >= PHYS_SDRAM_2 &&
445              addr_start <= ((sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE)))
446                 return (PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_OUTER_SHARE);
447
448         return attr;
449 }
450
451 static u64 get_block_size(sc_faddr_t addr_start, sc_faddr_t addr_end)
452 {
453         sc_faddr_t end1, end2;
454
455         end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE;
456         end2 = (sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE;
457
458         if (addr_start >= PHYS_SDRAM_1 && addr_start <= end1) {
459                 if ((addr_end + 1) > end1)
460                         return end1 - addr_start;
461         } else if (addr_start >= PHYS_SDRAM_2 && addr_start <= end2) {
462                 if ((addr_end + 1) > end2)
463                         return end2 - addr_start;
464         }
465
466         return (addr_end - addr_start + 1);
467 }
468
469 #define MAX_PTE_ENTRIES 512
470 #define MAX_MEM_MAP_REGIONS 16
471
472 static struct mm_region imx8_mem_map[MAX_MEM_MAP_REGIONS];
473 struct mm_region *mem_map = imx8_mem_map;
474
475 void enable_caches(void)
476 {
477         sc_rm_mr_t mr;
478         sc_faddr_t start, end;
479         int err, i;
480
481         /* Create map for registers access from 0x1c000000 to 0x80000000*/
482         imx8_mem_map[0].virt = 0x1c000000UL;
483         imx8_mem_map[0].phys = 0x1c000000UL;
484         imx8_mem_map[0].size = 0x64000000UL;
485         imx8_mem_map[0].attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
486                          PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN;
487
488         i = 1;
489         for (mr = 0; mr < 64 && i < MAX_MEM_MAP_REGIONS; mr++) {
490                 err = get_owned_memreg(mr, &start, &end);
491                 if (!err) {
492                         imx8_mem_map[i].virt = start;
493                         imx8_mem_map[i].phys = start;
494                         imx8_mem_map[i].size = get_block_size(start, end);
495                         imx8_mem_map[i].attrs = get_block_attrs(start);
496                         i++;
497                 }
498         }
499
500         if (i < MAX_MEM_MAP_REGIONS) {
501                 imx8_mem_map[i].size = 0;
502                 imx8_mem_map[i].attrs = 0;
503         } else {
504                 puts("Error, need more MEM MAP REGIONS reserved\n");
505                 icache_enable();
506                 return;
507         }
508
509         for (i = 0; i < MAX_MEM_MAP_REGIONS; i++) {
510                 debug("[%d] vir = 0x%llx phys = 0x%llx size = 0x%llx attrs = 0x%llx\n",
511                       i, imx8_mem_map[i].virt, imx8_mem_map[i].phys,
512                       imx8_mem_map[i].size, imx8_mem_map[i].attrs);
513         }
514
515         icache_enable();
516         dcache_enable();
517 }
518
519 #ifndef CONFIG_SYS_DCACHE_OFF
520 u64 get_page_table_size(void)
521 {
522         u64 one_pt = MAX_PTE_ENTRIES * sizeof(u64);
523         u64 size = 0;
524
525         /*
526          * For each memory region, the max table size:
527          * 2 level 3 tables + 2 level 2 tables + 1 level 1 table
528          */
529         size = (2 + 2 + 1) * one_pt * MAX_MEM_MAP_REGIONS + one_pt;
530
531         /*
532          * We need to duplicate our page table once to have an emergency pt to
533          * resort to when splitting page tables later on
534          */
535         size *= 2;
536
537         /*
538          * We may need to split page tables later on if dcache settings change,
539          * so reserve up to 4 (random pick) page tables for that.
540          */
541         size += one_pt * 4;
542
543         return size;
544 }
545 #endif