]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/armv7/mx6/soc.c
arm: mx6: make shutdown temperature configurable
[karo-tx-uboot.git] / arch / arm / cpu / armv7 / mx6 / soc.c
1 /*
2  * (C) Copyright 2007
3  * Sascha Hauer, Pengutronix
4  *
5  * (C) Copyright 2009 Freescale Semiconductor, Inc.
6  *
7  * SPDX-License-Identifier:     GPL-2.0+
8  */
9
10 #include <common.h>
11 #include <asm/errno.h>
12 #include <asm/io.h>
13 #include <asm/arch/imx-regs.h>
14 #include <asm/arch/crm_regs.h>
15 #include <asm/arch/regs-ocotp.h>
16 #include <asm/arch/clock.h>
17 #include <asm/arch/sys_proto.h>
18 #include <asm/imx-common/boot_mode.h>
19 #include <asm/imx-common/dma.h>
20 #include <stdbool.h>
21 #ifdef CONFIG_VIDEO_IPUV3
22 #include <ipu.h>
23 #endif
24
25 DECLARE_GLOBAL_DATA_PTR;
26
27 #ifdef CONFIG_MX6_TEMPERATURE_MIN
28 #define TEMPERATURE_MIN                 CONFIG_MX6_TEMPERATURE_MIN
29 #else
30 #define TEMPERATURE_MIN                 (-40)
31 #endif
32 #ifdef CONFIG_MX6_TEMPERATURE_HOT
33 #define TEMPERATURE_HOT                 CONFIG_MX6_TEMPERATURE_HOT
34 #else
35 #define TEMPERATURE_HOT                 80
36 #endif
37 #ifdef CONFIG_MX6_TEMPERATURE_MAX
38 #define TEMPERATURE_MAX                 CONFIG_MX6_TEMPERATURE_MAX
39 #else
40 #define TEMPERATURE_MAX                 125
41 #endif
42 #define TEMP_AVG_COUNT                  5
43 #define TEMP_WARN_THRESHOLD             5
44 #define REG_VALUE_TO_CEL(ratio, raw) ((raw_n40c - raw) * 100 / ratio - 40)
45
46 #define __data  __attribute__((section(".data")))
47
48 struct scu_regs {
49         u32     ctrl;
50         u32     config;
51         u32     status;
52         u32     invalidate;
53         u32     fpga_rev;
54 };
55
56 #ifdef CONFIG_HW_WATCHDOG
57 #define wdog_base       ((void *)WDOG1_BASE_ADDR)
58 #define WDOG_WCR        0x00
59 #define WCR_WDE         (1 << 2)
60 #define WDOG_WSR        0x02
61
62 void hw_watchdog_reset(void)
63 {
64         if (readw(wdog_base + WDOG_WCR) & WCR_WDE) {
65                 static u16 __data toggle = 0xaaaa;
66                 static int __data first = 1;
67
68                 if (first) {
69                         printf("Watchdog active\n");
70                         first = 0;
71                 }
72                 writew(toggle, wdog_base + WDOG_WSR);
73                 toggle ^= 0xffff;
74         }
75 }
76 #endif
77
78 u32 get_cpu_rev(void)
79 {
80         struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
81         u32 reg = readl(&anatop->digprog_sololite);
82         u32 type = ((reg >> 16) & 0xff);
83
84         if (type != MXC_CPU_MX6SL) {
85                 reg = readl(&anatop->digprog);
86                 type = ((reg >> 16) & 0xff);
87                 if (type == MXC_CPU_MX6DL) {
88                         struct scu_regs *scu = (struct scu_regs *)SCU_BASE_ADDR;
89                         u32 cfg = readl(&scu->config) & 3;
90
91                         if (!cfg)
92                                 type = MXC_CPU_MX6SOLO;
93                 }
94         }
95         reg &= 0xff;            /* mx6 silicon revision */
96         return (type << 12) | (reg + 0x10);
97 }
98
99 #ifdef CONFIG_REVISION_TAG
100 u32 __weak get_board_rev(void)
101 {
102         u32 cpurev = get_cpu_rev();
103         u32 type = ((cpurev >> 12) & 0xff);
104         if (type == MXC_CPU_MX6SOLO)
105                 cpurev = (MXC_CPU_MX6DL) << 12 | (cpurev & 0xFFF);
106
107         return cpurev;
108 }
109 #endif
110
111 void init_aips(void)
112 {
113         struct aipstz_regs *aips1, *aips2;
114
115         aips1 = (struct aipstz_regs *)AIPS1_BASE_ADDR;
116         aips2 = (struct aipstz_regs *)AIPS2_BASE_ADDR;
117
118         /*
119          * Set all MPROTx to be non-bufferable, trusted for R/W,
120          * not forced to user-mode.
121          */
122         writel(0x77777777, &aips1->mprot0);
123         writel(0x77777777, &aips1->mprot1);
124         writel(0x77777777, &aips2->mprot0);
125         writel(0x77777777, &aips2->mprot1);
126
127         /*
128          * Set all OPACRx to be non-bufferable, not require
129          * supervisor privilege level for access,allow for
130          * write access and untrusted master access.
131          */
132         writel(0x00000000, &aips1->opacr0);
133         writel(0x00000000, &aips1->opacr1);
134         writel(0x00000000, &aips1->opacr2);
135         writel(0x00000000, &aips1->opacr3);
136         writel(0x00000000, &aips1->opacr4);
137         writel(0x00000000, &aips2->opacr0);
138         writel(0x00000000, &aips2->opacr1);
139         writel(0x00000000, &aips2->opacr2);
140         writel(0x00000000, &aips2->opacr3);
141         writel(0x00000000, &aips2->opacr4);
142 }
143
144 /*
145  * Set the VDDSOC
146  *
147  * Mask out the REG_CORE[22:18] bits (REG2_TRIG) and set
148  * them to the specified millivolt level.
149  * Possible values are from 0.725V to 1.450V in steps of
150  * 0.025V (25mV).
151  */
152 static void set_vddsoc(u32 mv)
153 {
154         struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
155         u32 val, reg = readl(&anatop->reg_core);
156
157         if (mv < 725)
158                 val = 0x00;     /* Power gated off */
159         else if (mv > 1450)
160                 val = 0x1F;     /* Power FET switched full on. No regulation */
161         else
162                 val = (mv - 700) / 25;
163
164         /*
165          * Mask out the REG_CORE[22:18] bits (REG2_TRIG)
166          * and set them to the calculated value (0.7V + val * 0.25V)
167          */
168         reg = (reg & ~(0x1F << 18)) | (val << 18);
169         writel(reg, &anatop->reg_core);
170 }
171
172 static u32 __data thermal_calib;
173
174 int read_cpu_temperature(void)
175 {
176         unsigned int reg, tmp, i;
177         unsigned int raw_25c, raw_hot, hot_temp, raw_n40c, ratio;
178         int temperature;
179         struct anatop_regs *const anatop = (void *)ANATOP_BASE_ADDR;
180         struct mx6_ocotp_regs *const ocotp_regs = (void *)OCOTP_BASE_ADDR;
181
182         if (!thermal_calib) {
183                 ocotp_clk_enable();
184                 writel(1, &ocotp_regs->hw_ocotp_read_ctrl);
185                 thermal_calib = readl(&ocotp_regs->hw_ocotp_ana1);
186                 writel(0, &ocotp_regs->hw_ocotp_read_ctrl);
187                 ocotp_clk_disable();
188         }
189
190         if (thermal_calib == 0 || thermal_calib == 0xffffffff)
191                 return TEMPERATURE_MIN;
192
193         /* Fuse data layout:
194          * [31:20] sensor value @ 25C
195          * [19:8] sensor value of hot
196          * [7:0] hot temperature value */
197         raw_25c = thermal_calib >> 20;
198         raw_hot = (thermal_calib & 0xfff00) >> 8;
199         hot_temp = thermal_calib & 0xff;
200
201         ratio = ((raw_25c - raw_hot) * 100) / (hot_temp - 25);
202         raw_n40c = raw_25c + (13 * ratio) / 20;
203
204         /* now we only using single measure, every time we measure
205          * the temperature, we will power on/off the anadig module
206          */
207         writel(BM_ANADIG_TEMPSENSE0_POWER_DOWN, &anatop->tempsense0_clr);
208         writel(BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_set);
209
210         /* write measure freq */
211         reg = readl(&anatop->tempsense1);
212         reg &= ~BM_ANADIG_TEMPSENSE1_MEASURE_FREQ;
213         reg |= 327;
214         writel(reg, &anatop->tempsense1);
215
216         writel(BM_ANADIG_TEMPSENSE0_MEASURE_TEMP, &anatop->tempsense0_clr);
217         writel(BM_ANADIG_TEMPSENSE0_FINISHED, &anatop->tempsense0_clr);
218         writel(BM_ANADIG_TEMPSENSE0_MEASURE_TEMP, &anatop->tempsense0_set);
219
220         tmp = 0;
221         /* read five times of temperature values to get average*/
222         for (i = 0; i < 5; i++) {
223                 while ((readl(&anatop->tempsense0) &
224                                 BM_ANADIG_TEMPSENSE0_FINISHED) == 0)
225                         udelay(10000);
226                 reg = readl(&anatop->tempsense0);
227                 tmp += (reg & BM_ANADIG_TEMPSENSE0_TEMP_VALUE) >>
228                         BP_ANADIG_TEMPSENSE0_TEMP_VALUE;
229                 writel(BM_ANADIG_TEMPSENSE0_FINISHED,
230                         &anatop->tempsense0_clr);
231         }
232
233         tmp = tmp / 5;
234         if (tmp <= raw_n40c)
235                 temperature = REG_VALUE_TO_CEL(ratio, tmp);
236         else
237                 temperature = TEMPERATURE_MIN;
238
239         /* power down anatop thermal sensor */
240         writel(BM_ANADIG_TEMPSENSE0_POWER_DOWN, &anatop->tempsense0_set);
241         writel(BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_clr);
242
243         return temperature;
244 }
245
246 int check_cpu_temperature(int boot)
247 {
248         static int __data max_temp;
249         int boot_limit = getenv_ulong("max_boot_temp", 10, TEMPERATURE_HOT);
250         int tmp = read_cpu_temperature();
251         bool first = true;
252
253         if (tmp < TEMPERATURE_MIN || tmp > TEMPERATURE_MAX) {
254                 printf("Temperature:   can't get valid data!\n");
255                 return tmp;
256         }
257
258         if (!boot) {
259                 if (tmp > boot_limit) {
260                         printf("CPU is %d C, too hot, resetting...\n", tmp);
261                         udelay(100000);
262                         reset_cpu(0);
263                 }
264                 if (tmp > max_temp) {
265                         if (tmp > boot_limit - TEMP_WARN_THRESHOLD)
266                                 printf("WARNING: CPU temperature %d C\n", tmp);
267                         max_temp = tmp;
268                 }
269         } else {
270                 printf("Temperature:   %d C, calibration data 0x%x\n",
271                         tmp, thermal_calib);
272                 while (tmp >= boot_limit) {
273                         if (first) {
274                                 printf("CPU is %d C, too hot to boot, waiting...\n",
275                                         tmp);
276                                 first = false;
277                         }
278                         if (ctrlc())
279                                 break;
280                         udelay(50000);
281                         tmp = read_cpu_temperature();
282                         if (tmp > boot_limit - TEMP_WARN_THRESHOLD && tmp != max_temp)
283                                 printf("WARNING: CPU temperature %d C\n", tmp);
284                         max_temp = tmp;
285                 }
286         }
287         return tmp;
288 }
289
290 static void imx_set_wdog_powerdown(bool enable)
291 {
292         struct wdog_regs *wdog1 = (struct wdog_regs *)WDOG1_BASE_ADDR;
293         struct wdog_regs *wdog2 = (struct wdog_regs *)WDOG2_BASE_ADDR;
294
295         /* Write to the PDE (Power Down Enable) bit */
296         writew(enable, &wdog1->wmcr);
297         writew(enable, &wdog2->wmcr);
298 }
299
300 #ifdef CONFIG_ARCH_CPU_INIT
301 int arch_cpu_init(void)
302 {
303         init_aips();
304
305         set_vddsoc(1200);       /* Set VDDSOC to 1.2V */
306
307         imx_set_wdog_powerdown(false); /* Disable PDE bit of WMCR register */
308
309 #ifdef CONFIG_VIDEO_IPUV3
310         gd->arch.ipu_hw_rev = IPUV3_HW_REV_IPUV3H;
311 #endif
312 #ifdef  CONFIG_APBH_DMA
313         /* Timer is required for Initializing APBH DMA */
314         timer_init();
315         mxs_dma_init();
316 #endif
317         return 0;
318 }
319 #endif
320
321 #ifndef CONFIG_SYS_DCACHE_OFF
322 void enable_caches(void)
323 {
324         /* Enable D-cache. I-cache is already enabled in start.S */
325         dcache_enable();
326 }
327 #endif
328
329 #if defined(CONFIG_FEC_MXC)
330 void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
331 {
332         struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
333         struct fuse_bank *bank = &ocotp->bank[4];
334         struct fuse_bank4_regs *fuse =
335                         (struct fuse_bank4_regs *)bank->fuse_regs;
336
337         u32 value = readl(&fuse->mac_addr_high);
338         mac[0] = (value >> 8);
339         mac[1] = value;
340
341         value = readl(&fuse->mac_addr_low);
342         mac[2] = value >> 24;
343         mac[3] = value >> 16;
344         mac[4] = value >> 8;
345         mac[5] = value;
346 }
347 #endif
348
349 void boot_mode_apply(unsigned cfg_val)
350 {
351         unsigned reg;
352         struct src *psrc = (struct src *)SRC_BASE_ADDR;
353         writel(cfg_val, &psrc->gpr9);
354         reg = readl(&psrc->gpr10);
355         if (cfg_val)
356                 reg |= 1 << 28;
357         else
358                 reg &= ~(1 << 28);
359         writel(reg, &psrc->gpr10);
360 }
361 /*
362  * cfg_val will be used for
363  * Boot_cfg4[7:0]:Boot_cfg3[7:0]:Boot_cfg2[7:0]:Boot_cfg1[7:0]
364  * After reset, if GPR10[28] is 1, ROM will copy GPR9[25:0]
365  * to SBMR1, which will determine the boot device.
366  */
367 const struct boot_mode soc_boot_modes[] = {
368         {"normal",      MAKE_CFGVAL(0x00, 0x00, 0x00, 0x00)},
369         /* reserved value should start rom usb */
370         {"usb",         MAKE_CFGVAL(0x01, 0x00, 0x00, 0x00)},
371         {"sata",        MAKE_CFGVAL(0x20, 0x00, 0x00, 0x00)},
372         {"escpi1:0",    MAKE_CFGVAL(0x30, 0x00, 0x00, 0x08)},
373         {"escpi1:1",    MAKE_CFGVAL(0x30, 0x00, 0x00, 0x18)},
374         {"escpi1:2",    MAKE_CFGVAL(0x30, 0x00, 0x00, 0x28)},
375         {"escpi1:3",    MAKE_CFGVAL(0x30, 0x00, 0x00, 0x38)},
376         /* 4 bit bus width */
377         {"esdhc1",      MAKE_CFGVAL(0x40, 0x20, 0x00, 0x00)},
378         {"esdhc2",      MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)},
379         {"esdhc3",      MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)},
380         {"esdhc4",      MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00)},
381         {NULL,          0},
382 };
383
384 void s_init(void)
385 {
386 }