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