common: Drop net.h from common header
[oweals/u-boot.git] / arch / arm / mach-imx / cpu.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2007
4  * Sascha Hauer, Pengutronix
5  *
6  * (C) Copyright 2009 Freescale Semiconductor, Inc.
7  */
8
9 #include <bootm.h>
10 #include <common.h>
11 #include <net.h>
12 #include <netdev.h>
13 #include <linux/errno.h>
14 #include <asm/io.h>
15 #include <asm/arch/imx-regs.h>
16 #include <asm/arch/clock.h>
17 #include <asm/arch/sys_proto.h>
18 #include <asm/arch/crm_regs.h>
19 #include <asm/mach-imx/boot_mode.h>
20 #include <imx_thermal.h>
21 #include <ipu_pixfmt.h>
22 #include <thermal.h>
23 #include <sata.h>
24
25 #ifdef CONFIG_FSL_ESDHC_IMX
26 #include <fsl_esdhc_imx.h>
27 #endif
28
29 static u32 reset_cause = -1;
30
31 u32 get_imx_reset_cause(void)
32 {
33         struct src *src_regs = (struct src *)SRC_BASE_ADDR;
34
35         if (reset_cause == -1) {
36                 reset_cause = readl(&src_regs->srsr);
37 /* preserve the value for U-Boot proper */
38 #if !defined(CONFIG_SPL_BUILD)
39                 writel(reset_cause, &src_regs->srsr);
40 #endif
41         }
42
43         return reset_cause;
44 }
45
46 #if defined(CONFIG_DISPLAY_CPUINFO) && !defined(CONFIG_SPL_BUILD)
47 static char *get_reset_cause(void)
48 {
49         switch (get_imx_reset_cause()) {
50         case 0x00001:
51         case 0x00011:
52                 return "POR";
53         case 0x00004:
54                 return "CSU";
55         case 0x00008:
56                 return "IPP USER";
57         case 0x00010:
58 #ifdef  CONFIG_MX7
59                 return "WDOG1";
60 #else
61                 return "WDOG";
62 #endif
63         case 0x00020:
64                 return "JTAG HIGH-Z";
65         case 0x00040:
66                 return "JTAG SW";
67         case 0x00080:
68                 return "WDOG3";
69 #ifdef CONFIG_MX7
70         case 0x00100:
71                 return "WDOG4";
72         case 0x00200:
73                 return "TEMPSENSE";
74 #elif defined(CONFIG_IMX8M)
75         case 0x00100:
76                 return "WDOG2";
77         case 0x00200:
78                 return "TEMPSENSE";
79 #else
80         case 0x00100:
81                 return "TEMPSENSE";
82         case 0x10000:
83                 return "WARM BOOT";
84 #endif
85         default:
86                 return "unknown reset";
87         }
88 }
89 #endif
90
91 #if defined(CONFIG_DISPLAY_CPUINFO) && !defined(CONFIG_SPL_BUILD)
92
93 const char *get_imx_type(u32 imxtype)
94 {
95         switch (imxtype) {
96         case MXC_CPU_IMX8MP:
97                 return "8MP";   /* Quad-core version of the imx8mp */
98         case MXC_CPU_IMX8MN:
99                 return "8MNano Quad"; /* Quad-core version */
100         case MXC_CPU_IMX8MND:
101                 return "8MNano Dual"; /* Dual-core version */
102         case MXC_CPU_IMX8MNS:
103                 return "8MNano Solo"; /* Single-core version */
104         case MXC_CPU_IMX8MNL:
105                 return "8MNano QuadLite"; /* Quad-core Lite version */
106         case MXC_CPU_IMX8MNDL:
107                 return "8MNano DualLite"; /* Dual-core Lite version */
108         case MXC_CPU_IMX8MNSL:
109                 return "8MNano SoloLite"; /* Single-core Lite version */
110         case MXC_CPU_IMX8MM:
111                 return "8MMQ";  /* Quad-core version of the imx8mm */
112         case MXC_CPU_IMX8MML:
113                 return "8MMQL"; /* Quad-core Lite version of the imx8mm */
114         case MXC_CPU_IMX8MMD:
115                 return "8MMD";  /* Dual-core version of the imx8mm */
116         case MXC_CPU_IMX8MMDL:
117                 return "8MMDL"; /* Dual-core Lite version of the imx8mm */
118         case MXC_CPU_IMX8MMS:
119                 return "8MMS";  /* Single-core version of the imx8mm */
120         case MXC_CPU_IMX8MMSL:
121                 return "8MMSL"; /* Single-core Lite version of the imx8mm */
122         case MXC_CPU_IMX8MQ:
123                 return "8MQ";   /* Quad-core version of the imx8mq */
124         case MXC_CPU_IMX8MQL:
125                 return "8MQLite";       /* Quad-core Lite version of the imx8mq */
126         case MXC_CPU_IMX8MD:
127                 return "8MD";   /* Dual-core version of the imx8mq */
128         case MXC_CPU_MX7S:
129                 return "7S";    /* Single-core version of the mx7 */
130         case MXC_CPU_MX7D:
131                 return "7D";    /* Dual-core version of the mx7 */
132         case MXC_CPU_MX6QP:
133                 return "6QP";   /* Quad-Plus version of the mx6 */
134         case MXC_CPU_MX6DP:
135                 return "6DP";   /* Dual-Plus version of the mx6 */
136         case MXC_CPU_MX6Q:
137                 return "6Q";    /* Quad-core version of the mx6 */
138         case MXC_CPU_MX6D:
139                 return "6D";    /* Dual-core version of the mx6 */
140         case MXC_CPU_MX6DL:
141                 return "6DL";   /* Dual Lite version of the mx6 */
142         case MXC_CPU_MX6SOLO:
143                 return "6SOLO"; /* Solo version of the mx6 */
144         case MXC_CPU_MX6SL:
145                 return "6SL";   /* Solo-Lite version of the mx6 */
146         case MXC_CPU_MX6SLL:
147                 return "6SLL";  /* SLL version of the mx6 */
148         case MXC_CPU_MX6SX:
149                 return "6SX";   /* SoloX version of the mx6 */
150         case MXC_CPU_MX6UL:
151                 return "6UL";   /* Ultra-Lite version of the mx6 */
152         case MXC_CPU_MX6ULL:
153                 return "6ULL";  /* ULL version of the mx6 */
154         case MXC_CPU_MX6ULZ:
155                 return "6ULZ";  /* ULZ version of the mx6 */
156         case MXC_CPU_MX51:
157                 return "51";
158         case MXC_CPU_MX53:
159                 return "53";
160         default:
161                 return "??";
162         }
163 }
164
165 int print_cpuinfo(void)
166 {
167         u32 cpurev;
168         __maybe_unused u32 max_freq;
169
170         cpurev = get_cpu_rev();
171
172 #if defined(CONFIG_IMX_THERMAL) || defined(CONFIG_IMX_TMU)
173         struct udevice *thermal_dev;
174         int cpu_tmp, minc, maxc, ret;
175
176         printf("CPU:   Freescale i.MX%s rev%d.%d",
177                get_imx_type((cpurev & 0x1FF000) >> 12),
178                (cpurev & 0x000F0) >> 4,
179                (cpurev & 0x0000F) >> 0);
180         max_freq = get_cpu_speed_grade_hz();
181         if (!max_freq || max_freq == mxc_get_clock(MXC_ARM_CLK)) {
182                 printf(" at %dMHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000);
183         } else {
184                 printf(" %d MHz (running at %d MHz)\n", max_freq / 1000000,
185                        mxc_get_clock(MXC_ARM_CLK) / 1000000);
186         }
187 #else
188         printf("CPU:   Freescale i.MX%s rev%d.%d at %d MHz\n",
189                 get_imx_type((cpurev & 0x1FF000) >> 12),
190                 (cpurev & 0x000F0) >> 4,
191                 (cpurev & 0x0000F) >> 0,
192                 mxc_get_clock(MXC_ARM_CLK) / 1000000);
193 #endif
194
195 #if defined(CONFIG_IMX_THERMAL) || defined(CONFIG_IMX_TMU)
196         puts("CPU:   ");
197         switch (get_cpu_temp_grade(&minc, &maxc)) {
198         case TEMP_AUTOMOTIVE:
199                 puts("Automotive temperature grade ");
200                 break;
201         case TEMP_INDUSTRIAL:
202                 puts("Industrial temperature grade ");
203                 break;
204         case TEMP_EXTCOMMERCIAL:
205                 puts("Extended Commercial temperature grade ");
206                 break;
207         default:
208                 puts("Commercial temperature grade ");
209                 break;
210         }
211         printf("(%dC to %dC)", minc, maxc);
212         ret = uclass_get_device(UCLASS_THERMAL, 0, &thermal_dev);
213         if (!ret) {
214                 ret = thermal_get_temp(thermal_dev, &cpu_tmp);
215
216                 if (!ret)
217                         printf(" at %dC\n", cpu_tmp);
218                 else
219                         debug(" - invalid sensor data\n");
220         } else {
221                 debug(" - invalid sensor device\n");
222         }
223 #endif
224
225         printf("Reset cause: %s\n", get_reset_cause());
226         return 0;
227 }
228 #endif
229
230 int cpu_eth_init(bd_t *bis)
231 {
232         int rc = -ENODEV;
233
234 #if defined(CONFIG_FEC_MXC)
235         rc = fecmxc_initialize(bis);
236 #endif
237
238         return rc;
239 }
240
241 #ifdef CONFIG_FSL_ESDHC_IMX
242 /*
243  * Initializes on-chip MMC controllers.
244  * to override, implement board_mmc_init()
245  */
246 int cpu_mmc_init(bd_t *bis)
247 {
248         return fsl_esdhc_mmc_init(bis);
249 }
250 #endif
251
252 #if !(defined(CONFIG_MX7) || defined(CONFIG_IMX8M))
253 u32 get_ahb_clk(void)
254 {
255         struct mxc_ccm_reg *imx_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
256         u32 reg, ahb_podf;
257
258         reg = __raw_readl(&imx_ccm->cbcdr);
259         reg &= MXC_CCM_CBCDR_AHB_PODF_MASK;
260         ahb_podf = reg >> MXC_CCM_CBCDR_AHB_PODF_OFFSET;
261
262         return get_periph_clk() / (ahb_podf + 1);
263 }
264 #endif
265
266 void arch_preboot_os(void)
267 {
268 #if defined(CONFIG_PCIE_IMX) && !CONFIG_IS_ENABLED(DM_PCI)
269         imx_pcie_remove();
270 #endif
271 #if defined(CONFIG_SATA)
272         if (!is_mx6sdl()) {
273                 sata_remove(0);
274 #if defined(CONFIG_MX6)
275                 disable_sata_clock();
276 #endif
277         }
278 #endif
279 #if defined(CONFIG_VIDEO_IPUV3)
280         /* disable video before launching O/S */
281         ipuv3_fb_shutdown();
282 #endif
283 #if defined(CONFIG_VIDEO_MXS) && !defined(CONFIG_DM_VIDEO)
284         lcdif_power_down();
285 #endif
286 }
287
288 #ifndef CONFIG_IMX8M
289 void set_chipselect_size(int const cs_size)
290 {
291         unsigned int reg;
292         struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
293         reg = readl(&iomuxc_regs->gpr[1]);
294
295         switch (cs_size) {
296         case CS0_128:
297                 reg &= ~0x7;    /* CS0=128MB, CS1=0, CS2=0, CS3=0 */
298                 reg |= 0x5;
299                 break;
300         case CS0_64M_CS1_64M:
301                 reg &= ~0x3F;   /* CS0=64MB, CS1=64MB, CS2=0, CS3=0 */
302                 reg |= 0x1B;
303                 break;
304         case CS0_64M_CS1_32M_CS2_32M:
305                 reg &= ~0x1FF;  /* CS0=64MB, CS1=32MB, CS2=32MB, CS3=0 */
306                 reg |= 0x4B;
307                 break;
308         case CS0_32M_CS1_32M_CS2_32M_CS3_32M:
309                 reg &= ~0xFFF;  /* CS0=32MB, CS1=32MB, CS2=32MB, CS3=32MB */
310                 reg |= 0x249;
311                 break;
312         default:
313                 printf("Unknown chip select size: %d\n", cs_size);
314                 break;
315         }
316
317         writel(reg, &iomuxc_regs->gpr[1]);
318 }
319 #endif
320
321 #if defined(CONFIG_MX7) || defined(CONFIG_IMX8M)
322 /*
323  * OCOTP_TESTER3[9:8] (see Fusemap Description Table offset 0x440)
324  * defines a 2-bit SPEED_GRADING
325  */
326 #define OCOTP_TESTER3_SPEED_SHIFT       8
327 enum cpu_speed {
328         OCOTP_TESTER3_SPEED_GRADE0,
329         OCOTP_TESTER3_SPEED_GRADE1,
330         OCOTP_TESTER3_SPEED_GRADE2,
331         OCOTP_TESTER3_SPEED_GRADE3,
332         OCOTP_TESTER3_SPEED_GRADE4,
333 };
334
335 u32 get_cpu_speed_grade_hz(void)
336 {
337         struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
338         struct fuse_bank *bank = &ocotp->bank[1];
339         struct fuse_bank1_regs *fuse =
340                 (struct fuse_bank1_regs *)bank->fuse_regs;
341         uint32_t val;
342
343         val = readl(&fuse->tester3);
344         val >>= OCOTP_TESTER3_SPEED_SHIFT;
345
346         if (is_imx8mn() || is_imx8mp()) {
347                 val &= 0xf;
348                 return 2300000000 - val * 100000000;
349         }
350
351         if (is_imx8mm())
352                 val &= 0x7;
353         else
354                 val &= 0x3;
355
356         switch(val) {
357         case OCOTP_TESTER3_SPEED_GRADE0:
358                 return 800000000;
359         case OCOTP_TESTER3_SPEED_GRADE1:
360                 return (is_mx7() ? 500000000 : (is_imx8mq() ? 1000000000 : 1200000000));
361         case OCOTP_TESTER3_SPEED_GRADE2:
362                 return (is_mx7() ? 1000000000 : (is_imx8mq() ? 1300000000 : 1600000000));
363         case OCOTP_TESTER3_SPEED_GRADE3:
364                 return (is_mx7() ? 1200000000 : (is_imx8mq() ? 1500000000 : 1800000000));
365         case OCOTP_TESTER3_SPEED_GRADE4:
366                 return 2000000000;
367         }
368
369         return 0;
370 }
371
372 /*
373  * OCOTP_TESTER3[7:6] (see Fusemap Description Table offset 0x440)
374  * defines a 2-bit SPEED_GRADING
375  */
376 #define OCOTP_TESTER3_TEMP_SHIFT        6
377
378 u32 get_cpu_temp_grade(int *minc, int *maxc)
379 {
380         struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
381         struct fuse_bank *bank = &ocotp->bank[1];
382         struct fuse_bank1_regs *fuse =
383                 (struct fuse_bank1_regs *)bank->fuse_regs;
384         uint32_t val;
385
386         val = readl(&fuse->tester3);
387         val >>= OCOTP_TESTER3_TEMP_SHIFT;
388         val &= 0x3;
389
390         if (minc && maxc) {
391                 if (val == TEMP_AUTOMOTIVE) {
392                         *minc = -40;
393                         *maxc = 125;
394                 } else if (val == TEMP_INDUSTRIAL) {
395                         *minc = -40;
396                         *maxc = 105;
397                 } else if (val == TEMP_EXTCOMMERCIAL) {
398                         *minc = -20;
399                         *maxc = 105;
400                 } else {
401                         *minc = 0;
402                         *maxc = 95;
403                 }
404         }
405         return val;
406 }
407 #endif
408
409 #if defined(CONFIG_MX7) || defined(CONFIG_IMX8MQ) || defined(CONFIG_IMX8MM)
410 enum boot_device get_boot_device(void)
411 {
412         struct bootrom_sw_info **p =
413                 (struct bootrom_sw_info **)(ulong)ROM_SW_INFO_ADDR;
414
415         enum boot_device boot_dev = SD1_BOOT;
416         u8 boot_type = (*p)->boot_dev_type;
417         u8 boot_instance = (*p)->boot_dev_instance;
418
419         switch (boot_type) {
420         case BOOT_TYPE_SD:
421                 boot_dev = boot_instance + SD1_BOOT;
422                 break;
423         case BOOT_TYPE_MMC:
424                 boot_dev = boot_instance + MMC1_BOOT;
425                 break;
426         case BOOT_TYPE_NAND:
427                 boot_dev = NAND_BOOT;
428                 break;
429         case BOOT_TYPE_QSPI:
430                 boot_dev = QSPI_BOOT;
431                 break;
432         case BOOT_TYPE_WEIM:
433                 boot_dev = WEIM_NOR_BOOT;
434                 break;
435         case BOOT_TYPE_SPINOR:
436                 boot_dev = SPI_NOR_BOOT;
437                 break;
438 #ifdef CONFIG_IMX8M
439         case BOOT_TYPE_USB:
440                 boot_dev = USB_BOOT;
441                 break;
442 #endif
443         default:
444                 break;
445         }
446
447         return boot_dev;
448 }
449 #endif
450
451 #ifdef CONFIG_NXP_BOARD_REVISION
452 int nxp_board_rev(void)
453 {
454         /*
455          * Get Board ID information from OCOTP_GP1[15:8]
456          * RevA: 0x1
457          * RevB: 0x2
458          * RevC: 0x3
459          */
460         struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
461         struct fuse_bank *bank = &ocotp->bank[4];
462         struct fuse_bank4_regs *fuse =
463                         (struct fuse_bank4_regs *)bank->fuse_regs;
464
465         return (readl(&fuse->gp1) >> 8 & 0x0F);
466 }
467
468 char nxp_board_rev_string(void)
469 {
470         const char *rev = "A";
471
472         return (*rev + nxp_board_rev() - 1);
473 }
474 #endif