Commit 01996acd7788c831fc06872c59af99f3bd6f6b03
1 parent
c3e9e81a4c
Exists in
smarc-imx-l5.0.0_1.0.0-ga
ENGR00326994 iMX6: Checking PLL2 PFD0 and PFD2 for periph_clk before reset
u-boot v2014 upstream codes have a problem in pfd reset (s_init function) that imx6 Dual is not applied for PLL2 PFD2 reset. It is originated by using dynamical cpu type checking and introducing two cpu types: MXC_CPU_MX6Q and MXC_CPU_MX6D for iMX6 Dual/Quad platform. Fixed this problem by checking the pre_periph_clk_sel and pre_periph2_clk of CCM CBCMR register, if the PLL2 PFD0 or PLL2 PFD2 is used for the clock source, do not reset this PFD to avoid system hang. Signed-off-by: Ye.Li <B37916@freescale.com>
Showing 1 changed file with 16 additions and 7 deletions Inline Diff
arch/arm/cpu/armv7/mx6/soc.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2007 | 2 | * (C) Copyright 2007 |
3 | * Sascha Hauer, Pengutronix | 3 | * Sascha Hauer, Pengutronix |
4 | * | 4 | * |
5 | * (C) Copyright 2009-2014 Freescale Semiconductor, Inc. | 5 | * (C) Copyright 2009-2014 Freescale Semiconductor, Inc. |
6 | * | 6 | * |
7 | * SPDX-License-Identifier: GPL-2.0+ | 7 | * SPDX-License-Identifier: GPL-2.0+ |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <common.h> | 10 | #include <common.h> |
11 | #include <asm/armv7.h> | 11 | #include <asm/armv7.h> |
12 | #include <asm/pl310.h> | 12 | #include <asm/pl310.h> |
13 | #include <asm/errno.h> | 13 | #include <asm/errno.h> |
14 | #include <asm/io.h> | 14 | #include <asm/io.h> |
15 | #include <asm/arch/imx-regs.h> | 15 | #include <asm/arch/imx-regs.h> |
16 | #include <asm/arch/clock.h> | 16 | #include <asm/arch/clock.h> |
17 | #include <asm/arch/sys_proto.h> | 17 | #include <asm/arch/sys_proto.h> |
18 | #include <asm/imx-common/boot_mode.h> | 18 | #include <asm/imx-common/boot_mode.h> |
19 | #include <asm/imx-common/dma.h> | 19 | #include <asm/imx-common/dma.h> |
20 | #include <libfdt.h> | 20 | #include <libfdt.h> |
21 | #include <stdbool.h> | 21 | #include <stdbool.h> |
22 | #include <asm/arch/mxc_hdmi.h> | 22 | #include <asm/arch/mxc_hdmi.h> |
23 | #include <asm/arch/crm_regs.h> | 23 | #include <asm/arch/crm_regs.h> |
24 | #ifdef CONFIG_FASTBOOT | 24 | #ifdef CONFIG_FASTBOOT |
25 | #ifdef CONFIG_ANDROID_RECOVERY | 25 | #ifdef CONFIG_ANDROID_RECOVERY |
26 | #include <recovery.h> | 26 | #include <recovery.h> |
27 | #endif | 27 | #endif |
28 | #endif | 28 | #endif |
29 | #ifdef CONFIG_IMX_UDC | 29 | #ifdef CONFIG_IMX_UDC |
30 | #include <asm/arch/mx6_usbphy.h> | 30 | #include <asm/arch/mx6_usbphy.h> |
31 | #include <usb/imx_udc.h> | 31 | #include <usb/imx_udc.h> |
32 | #endif | 32 | #endif |
33 | 33 | ||
34 | enum ldo_reg { | 34 | enum ldo_reg { |
35 | LDO_ARM, | 35 | LDO_ARM, |
36 | LDO_SOC, | 36 | LDO_SOC, |
37 | LDO_PU, | 37 | LDO_PU, |
38 | }; | 38 | }; |
39 | 39 | ||
40 | struct scu_regs { | 40 | struct scu_regs { |
41 | u32 ctrl; | 41 | u32 ctrl; |
42 | u32 config; | 42 | u32 config; |
43 | u32 status; | 43 | u32 status; |
44 | u32 invalidate; | 44 | u32 invalidate; |
45 | u32 fpga_rev; | 45 | u32 fpga_rev; |
46 | }; | 46 | }; |
47 | 47 | ||
48 | #define TEMPERATURE_MIN -40 | 48 | #define TEMPERATURE_MIN -40 |
49 | #define TEMPERATURE_HOT 80 | 49 | #define TEMPERATURE_HOT 80 |
50 | #define TEMPERATURE_MAX 125 | 50 | #define TEMPERATURE_MAX 125 |
51 | #define FACTOR1 15976 | 51 | #define FACTOR1 15976 |
52 | #define FACTOR2 4297157 | 52 | #define FACTOR2 4297157 |
53 | #define MEASURE_FREQ 327 | 53 | #define MEASURE_FREQ 327 |
54 | 54 | ||
55 | #define REG_VALUE_TO_CEL(ratio, raw) \ | 55 | #define REG_VALUE_TO_CEL(ratio, raw) \ |
56 | ((raw_n40c - raw) * 100 / ratio - 40) | 56 | ((raw_n40c - raw) * 100 / ratio - 40) |
57 | 57 | ||
58 | static unsigned int fuse = ~0; | 58 | static unsigned int fuse = ~0; |
59 | 59 | ||
60 | u32 get_cpu_rev(void) | 60 | u32 get_cpu_rev(void) |
61 | { | 61 | { |
62 | struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; | 62 | struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; |
63 | u32 reg = readl(&anatop->digprog_sololite); | 63 | u32 reg = readl(&anatop->digprog_sololite); |
64 | u32 type = ((reg >> 16) & 0xff); | 64 | u32 type = ((reg >> 16) & 0xff); |
65 | 65 | ||
66 | if (type != MXC_CPU_MX6SL) { | 66 | if (type != MXC_CPU_MX6SL) { |
67 | reg = readl(&anatop->digprog); | 67 | reg = readl(&anatop->digprog); |
68 | struct scu_regs *scu = (struct scu_regs *)SCU_BASE_ADDR; | 68 | struct scu_regs *scu = (struct scu_regs *)SCU_BASE_ADDR; |
69 | u32 cfg = readl(&scu->config) & 3; | 69 | u32 cfg = readl(&scu->config) & 3; |
70 | type = ((reg >> 16) & 0xff); | 70 | type = ((reg >> 16) & 0xff); |
71 | if (type == MXC_CPU_MX6DL) { | 71 | if (type == MXC_CPU_MX6DL) { |
72 | if (!cfg) | 72 | if (!cfg) |
73 | type = MXC_CPU_MX6SOLO; | 73 | type = MXC_CPU_MX6SOLO; |
74 | } | 74 | } |
75 | 75 | ||
76 | if (type == MXC_CPU_MX6Q) { | 76 | if (type == MXC_CPU_MX6Q) { |
77 | if (cfg == 1) | 77 | if (cfg == 1) |
78 | type = MXC_CPU_MX6D; | 78 | type = MXC_CPU_MX6D; |
79 | } | 79 | } |
80 | 80 | ||
81 | } | 81 | } |
82 | reg &= 0xff; /* mx6 silicon revision */ | 82 | reg &= 0xff; /* mx6 silicon revision */ |
83 | return (type << 12) | (reg + 0x10); | 83 | return (type << 12) | (reg + 0x10); |
84 | } | 84 | } |
85 | 85 | ||
86 | #ifdef CONFIG_REVISION_TAG | 86 | #ifdef CONFIG_REVISION_TAG |
87 | u32 __weak get_board_rev(void) | 87 | u32 __weak get_board_rev(void) |
88 | { | 88 | { |
89 | u32 cpurev = get_cpu_rev(); | 89 | u32 cpurev = get_cpu_rev(); |
90 | u32 type = ((cpurev >> 12) & 0xff); | 90 | u32 type = ((cpurev >> 12) & 0xff); |
91 | if (type == MXC_CPU_MX6SOLO) | 91 | if (type == MXC_CPU_MX6SOLO) |
92 | cpurev = (MXC_CPU_MX6DL) << 12 | (cpurev & 0xFFF); | 92 | cpurev = (MXC_CPU_MX6DL) << 12 | (cpurev & 0xFFF); |
93 | 93 | ||
94 | if (type == MXC_CPU_MX6D) | 94 | if (type == MXC_CPU_MX6D) |
95 | cpurev = (MXC_CPU_MX6Q) << 12 | (cpurev & 0xFFF); | 95 | cpurev = (MXC_CPU_MX6Q) << 12 | (cpurev & 0xFFF); |
96 | 96 | ||
97 | return cpurev; | 97 | return cpurev; |
98 | } | 98 | } |
99 | #endif | 99 | #endif |
100 | 100 | ||
101 | void init_aips(void) | 101 | void init_aips(void) |
102 | { | 102 | { |
103 | struct aipstz_regs *aips1, *aips2; | 103 | struct aipstz_regs *aips1, *aips2; |
104 | #ifdef CONFIG_MX6SX | 104 | #ifdef CONFIG_MX6SX |
105 | struct aipstz_regs *aips3; | 105 | struct aipstz_regs *aips3; |
106 | #endif | 106 | #endif |
107 | 107 | ||
108 | aips1 = (struct aipstz_regs *)AIPS1_BASE_ADDR; | 108 | aips1 = (struct aipstz_regs *)AIPS1_BASE_ADDR; |
109 | aips2 = (struct aipstz_regs *)AIPS2_BASE_ADDR; | 109 | aips2 = (struct aipstz_regs *)AIPS2_BASE_ADDR; |
110 | #ifdef CONFIG_MX6SX | 110 | #ifdef CONFIG_MX6SX |
111 | aips3 = (struct aipstz_regs *)AIPS3_CONFIG_BASE_ADDR; | 111 | aips3 = (struct aipstz_regs *)AIPS3_CONFIG_BASE_ADDR; |
112 | #endif | 112 | #endif |
113 | 113 | ||
114 | /* | 114 | /* |
115 | * Set all MPROTx to be non-bufferable, trusted for R/W, | 115 | * Set all MPROTx to be non-bufferable, trusted for R/W, |
116 | * not forced to user-mode. | 116 | * not forced to user-mode. |
117 | */ | 117 | */ |
118 | writel(0x77777777, &aips1->mprot0); | 118 | writel(0x77777777, &aips1->mprot0); |
119 | writel(0x77777777, &aips1->mprot1); | 119 | writel(0x77777777, &aips1->mprot1); |
120 | writel(0x77777777, &aips2->mprot0); | 120 | writel(0x77777777, &aips2->mprot0); |
121 | writel(0x77777777, &aips2->mprot1); | 121 | writel(0x77777777, &aips2->mprot1); |
122 | 122 | ||
123 | /* | 123 | /* |
124 | * Set all OPACRx to be non-bufferable, not require | 124 | * Set all OPACRx to be non-bufferable, not require |
125 | * supervisor privilege level for access,allow for | 125 | * supervisor privilege level for access,allow for |
126 | * write access and untrusted master access. | 126 | * write access and untrusted master access. |
127 | */ | 127 | */ |
128 | writel(0x00000000, &aips1->opacr0); | 128 | writel(0x00000000, &aips1->opacr0); |
129 | writel(0x00000000, &aips1->opacr1); | 129 | writel(0x00000000, &aips1->opacr1); |
130 | writel(0x00000000, &aips1->opacr2); | 130 | writel(0x00000000, &aips1->opacr2); |
131 | writel(0x00000000, &aips1->opacr3); | 131 | writel(0x00000000, &aips1->opacr3); |
132 | writel(0x00000000, &aips1->opacr4); | 132 | writel(0x00000000, &aips1->opacr4); |
133 | writel(0x00000000, &aips2->opacr0); | 133 | writel(0x00000000, &aips2->opacr0); |
134 | writel(0x00000000, &aips2->opacr1); | 134 | writel(0x00000000, &aips2->opacr1); |
135 | writel(0x00000000, &aips2->opacr2); | 135 | writel(0x00000000, &aips2->opacr2); |
136 | writel(0x00000000, &aips2->opacr3); | 136 | writel(0x00000000, &aips2->opacr3); |
137 | writel(0x00000000, &aips2->opacr4); | 137 | writel(0x00000000, &aips2->opacr4); |
138 | 138 | ||
139 | #ifdef CONFIG_MX6SX | 139 | #ifdef CONFIG_MX6SX |
140 | /* | 140 | /* |
141 | * Set all MPROTx to be non-bufferable, trusted for R/W, | 141 | * Set all MPROTx to be non-bufferable, trusted for R/W, |
142 | * not forced to user-mode. | 142 | * not forced to user-mode. |
143 | */ | 143 | */ |
144 | writel(0x77777777, &aips3->mprot0); | 144 | writel(0x77777777, &aips3->mprot0); |
145 | writel(0x77777777, &aips3->mprot1); | 145 | writel(0x77777777, &aips3->mprot1); |
146 | 146 | ||
147 | /* | 147 | /* |
148 | * Set all OPACRx to be non-bufferable, not require | 148 | * Set all OPACRx to be non-bufferable, not require |
149 | * supervisor privilege level for access,allow for | 149 | * supervisor privilege level for access,allow for |
150 | * write access and untrusted master access. | 150 | * write access and untrusted master access. |
151 | */ | 151 | */ |
152 | writel(0x00000000, &aips3->opacr0); | 152 | writel(0x00000000, &aips3->opacr0); |
153 | writel(0x00000000, &aips3->opacr1); | 153 | writel(0x00000000, &aips3->opacr1); |
154 | writel(0x00000000, &aips3->opacr2); | 154 | writel(0x00000000, &aips3->opacr2); |
155 | writel(0x00000000, &aips3->opacr3); | 155 | writel(0x00000000, &aips3->opacr3); |
156 | writel(0x00000000, &aips3->opacr4); | 156 | writel(0x00000000, &aips3->opacr4); |
157 | #endif | 157 | #endif |
158 | } | 158 | } |
159 | 159 | ||
160 | static void clear_ldo_ramp(void) | 160 | static void clear_ldo_ramp(void) |
161 | { | 161 | { |
162 | struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; | 162 | struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; |
163 | int reg; | 163 | int reg; |
164 | 164 | ||
165 | /* ROM may modify LDO ramp up time according to fuse setting, so in | 165 | /* ROM may modify LDO ramp up time according to fuse setting, so in |
166 | * order to be in the safe side we neeed to reset these settings to | 166 | * order to be in the safe side we neeed to reset these settings to |
167 | * match the reset value: 0'b00 | 167 | * match the reset value: 0'b00 |
168 | */ | 168 | */ |
169 | reg = readl(&anatop->ana_misc2); | 169 | reg = readl(&anatop->ana_misc2); |
170 | reg &= ~(0x3f << 24); | 170 | reg &= ~(0x3f << 24); |
171 | writel(reg, &anatop->ana_misc2); | 171 | writel(reg, &anatop->ana_misc2); |
172 | } | 172 | } |
173 | 173 | ||
174 | /* | 174 | /* |
175 | * Set the PMU_REG_CORE register | 175 | * Set the PMU_REG_CORE register |
176 | * | 176 | * |
177 | * Set LDO_SOC/PU/ARM regulators to the specified millivolt level. | 177 | * Set LDO_SOC/PU/ARM regulators to the specified millivolt level. |
178 | * Possible values are from 0.725V to 1.450V in steps of | 178 | * Possible values are from 0.725V to 1.450V in steps of |
179 | * 0.025V (25mV). | 179 | * 0.025V (25mV). |
180 | */ | 180 | */ |
181 | static int set_ldo_voltage(enum ldo_reg ldo, u32 mv) | 181 | static int set_ldo_voltage(enum ldo_reg ldo, u32 mv) |
182 | { | 182 | { |
183 | struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; | 183 | struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; |
184 | u32 val, step, old, reg = readl(&anatop->reg_core); | 184 | u32 val, step, old, reg = readl(&anatop->reg_core); |
185 | u8 shift; | 185 | u8 shift; |
186 | 186 | ||
187 | if (mv < 725) | 187 | if (mv < 725) |
188 | val = 0x00; /* Power gated off */ | 188 | val = 0x00; /* Power gated off */ |
189 | else if (mv > 1450) | 189 | else if (mv > 1450) |
190 | val = 0x1F; /* Power FET switched full on. No regulation */ | 190 | val = 0x1F; /* Power FET switched full on. No regulation */ |
191 | else | 191 | else |
192 | val = (mv - 700) / 25; | 192 | val = (mv - 700) / 25; |
193 | 193 | ||
194 | clear_ldo_ramp(); | 194 | clear_ldo_ramp(); |
195 | 195 | ||
196 | switch (ldo) { | 196 | switch (ldo) { |
197 | case LDO_SOC: | 197 | case LDO_SOC: |
198 | shift = 18; | 198 | shift = 18; |
199 | break; | 199 | break; |
200 | case LDO_PU: | 200 | case LDO_PU: |
201 | shift = 9; | 201 | shift = 9; |
202 | break; | 202 | break; |
203 | case LDO_ARM: | 203 | case LDO_ARM: |
204 | shift = 0; | 204 | shift = 0; |
205 | break; | 205 | break; |
206 | default: | 206 | default: |
207 | return -EINVAL; | 207 | return -EINVAL; |
208 | } | 208 | } |
209 | 209 | ||
210 | old = (reg & (0x1F << shift)) >> shift; | 210 | old = (reg & (0x1F << shift)) >> shift; |
211 | step = abs(val - old); | 211 | step = abs(val - old); |
212 | if (step == 0) | 212 | if (step == 0) |
213 | return 0; | 213 | return 0; |
214 | 214 | ||
215 | reg = (reg & ~(0x1F << shift)) | (val << shift); | 215 | reg = (reg & ~(0x1F << shift)) | (val << shift); |
216 | writel(reg, &anatop->reg_core); | 216 | writel(reg, &anatop->reg_core); |
217 | 217 | ||
218 | /* | 218 | /* |
219 | * The LDO ramp-up is based on 64 clock cycles of 24 MHz = 2.6 us per | 219 | * The LDO ramp-up is based on 64 clock cycles of 24 MHz = 2.6 us per |
220 | * step | 220 | * step |
221 | */ | 221 | */ |
222 | udelay(3 * step); | 222 | udelay(3 * step); |
223 | 223 | ||
224 | return 0; | 224 | return 0; |
225 | } | 225 | } |
226 | 226 | ||
227 | static void imx_set_wdog_powerdown(bool enable) | 227 | static void imx_set_wdog_powerdown(bool enable) |
228 | { | 228 | { |
229 | struct wdog_regs *wdog1 = (struct wdog_regs *)WDOG1_BASE_ADDR; | 229 | struct wdog_regs *wdog1 = (struct wdog_regs *)WDOG1_BASE_ADDR; |
230 | struct wdog_regs *wdog2 = (struct wdog_regs *)WDOG2_BASE_ADDR; | 230 | struct wdog_regs *wdog2 = (struct wdog_regs *)WDOG2_BASE_ADDR; |
231 | 231 | ||
232 | /* Write to the PDE (Power Down Enable) bit */ | 232 | /* Write to the PDE (Power Down Enable) bit */ |
233 | writew(enable, &wdog1->wmcr); | 233 | writew(enable, &wdog1->wmcr); |
234 | writew(enable, &wdog2->wmcr); | 234 | writew(enable, &wdog2->wmcr); |
235 | } | 235 | } |
236 | 236 | ||
237 | static int read_cpu_temperature(void) | 237 | static int read_cpu_temperature(void) |
238 | { | 238 | { |
239 | int temperature; | 239 | int temperature; |
240 | unsigned int ccm_ccgr2; | 240 | unsigned int ccm_ccgr2; |
241 | unsigned int reg, tmp; | 241 | unsigned int reg, tmp; |
242 | unsigned int raw_25c, raw_n40c, ratio; | 242 | unsigned int raw_25c, raw_n40c, ratio; |
243 | struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; | 243 | struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; |
244 | struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; | 244 | struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; |
245 | struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; | 245 | struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; |
246 | struct fuse_bank *bank = &ocotp->bank[1]; | 246 | struct fuse_bank *bank = &ocotp->bank[1]; |
247 | struct fuse_bank1_regs *fuse_bank1 = | 247 | struct fuse_bank1_regs *fuse_bank1 = |
248 | (struct fuse_bank1_regs *)bank->fuse_regs; | 248 | (struct fuse_bank1_regs *)bank->fuse_regs; |
249 | 249 | ||
250 | /* need to make sure pll3 is enabled for thermal sensor */ | 250 | /* need to make sure pll3 is enabled for thermal sensor */ |
251 | if ((readl(&anatop->usb1_pll_480_ctrl) & | 251 | if ((readl(&anatop->usb1_pll_480_ctrl) & |
252 | BM_ANADIG_USB1_PLL_480_CTRL_LOCK) == 0) { | 252 | BM_ANADIG_USB1_PLL_480_CTRL_LOCK) == 0) { |
253 | /* enable pll's power */ | 253 | /* enable pll's power */ |
254 | writel(BM_ANADIG_USB1_PLL_480_CTRL_POWER, | 254 | writel(BM_ANADIG_USB1_PLL_480_CTRL_POWER, |
255 | &anatop->usb1_pll_480_ctrl_set); | 255 | &anatop->usb1_pll_480_ctrl_set); |
256 | writel(0x80, &anatop->ana_misc2_clr); | 256 | writel(0x80, &anatop->ana_misc2_clr); |
257 | /* wait for pll lock */ | 257 | /* wait for pll lock */ |
258 | while ((readl(&anatop->usb1_pll_480_ctrl) & | 258 | while ((readl(&anatop->usb1_pll_480_ctrl) & |
259 | BM_ANADIG_USB1_PLL_480_CTRL_LOCK) == 0) | 259 | BM_ANADIG_USB1_PLL_480_CTRL_LOCK) == 0) |
260 | ; | 260 | ; |
261 | /* disable bypass */ | 261 | /* disable bypass */ |
262 | writel(BM_ANADIG_USB1_PLL_480_CTRL_BYPASS, | 262 | writel(BM_ANADIG_USB1_PLL_480_CTRL_BYPASS, |
263 | &anatop->usb1_pll_480_ctrl_clr); | 263 | &anatop->usb1_pll_480_ctrl_clr); |
264 | /* enable pll output */ | 264 | /* enable pll output */ |
265 | writel(BM_ANADIG_USB1_PLL_480_CTRL_ENABLE, | 265 | writel(BM_ANADIG_USB1_PLL_480_CTRL_ENABLE, |
266 | &anatop->usb1_pll_480_ctrl_set); | 266 | &anatop->usb1_pll_480_ctrl_set); |
267 | } | 267 | } |
268 | 268 | ||
269 | ccm_ccgr2 = readl(&mxc_ccm->CCGR2); | 269 | ccm_ccgr2 = readl(&mxc_ccm->CCGR2); |
270 | /* enable OCOTP_CTRL clock in CCGR2 */ | 270 | /* enable OCOTP_CTRL clock in CCGR2 */ |
271 | writel(ccm_ccgr2 | MXC_CCM_CCGR2_OCOTP_CTRL_MASK, &mxc_ccm->CCGR2); | 271 | writel(ccm_ccgr2 | MXC_CCM_CCGR2_OCOTP_CTRL_MASK, &mxc_ccm->CCGR2); |
272 | fuse = readl(&fuse_bank1->ana1); | 272 | fuse = readl(&fuse_bank1->ana1); |
273 | 273 | ||
274 | /* restore CCGR2 */ | 274 | /* restore CCGR2 */ |
275 | writel(ccm_ccgr2, &mxc_ccm->CCGR2); | 275 | writel(ccm_ccgr2, &mxc_ccm->CCGR2); |
276 | 276 | ||
277 | if (fuse == 0 || fuse == 0xffffffff || (fuse & 0xfff00000) == 0) | 277 | if (fuse == 0 || fuse == 0xffffffff || (fuse & 0xfff00000) == 0) |
278 | return TEMPERATURE_MIN; | 278 | return TEMPERATURE_MIN; |
279 | 279 | ||
280 | /* | 280 | /* |
281 | * fuse data layout: | 281 | * fuse data layout: |
282 | * [31:20] sensor value @ 25C | 282 | * [31:20] sensor value @ 25C |
283 | * [19:8] sensor value of hot | 283 | * [19:8] sensor value of hot |
284 | * [7:0] hot temperature value | 284 | * [7:0] hot temperature value |
285 | */ | 285 | */ |
286 | raw_25c = fuse >> 20; | 286 | raw_25c = fuse >> 20; |
287 | 287 | ||
288 | /* | 288 | /* |
289 | * The universal equation for thermal sensor | 289 | * The universal equation for thermal sensor |
290 | * is slope = 0.4297157 - (0.0015976 * 25C fuse), | 290 | * is slope = 0.4297157 - (0.0015976 * 25C fuse), |
291 | * here we convert them to integer to make them | 291 | * here we convert them to integer to make them |
292 | * easy for counting, FACTOR1 is 15976, | 292 | * easy for counting, FACTOR1 is 15976, |
293 | * FACTOR2 is 4297157. Our ratio = -100 * slope | 293 | * FACTOR2 is 4297157. Our ratio = -100 * slope |
294 | */ | 294 | */ |
295 | ratio = ((FACTOR1 * raw_25c - FACTOR2) + 50000) / 100000; | 295 | ratio = ((FACTOR1 * raw_25c - FACTOR2) + 50000) / 100000; |
296 | 296 | ||
297 | debug("Thermal sensor with ratio = %d\n", ratio); | 297 | debug("Thermal sensor with ratio = %d\n", ratio); |
298 | 298 | ||
299 | raw_n40c = raw_25c + (13 * ratio) / 20; | 299 | raw_n40c = raw_25c + (13 * ratio) / 20; |
300 | 300 | ||
301 | /* | 301 | /* |
302 | * now we only use single measure, every time we read | 302 | * now we only use single measure, every time we read |
303 | * the temperature, we will power on/down anadig thermal | 303 | * the temperature, we will power on/down anadig thermal |
304 | * module | 304 | * module |
305 | */ | 305 | */ |
306 | writel(BM_ANADIG_TEMPSENSE0_POWER_DOWN, &anatop->tempsense0_clr); | 306 | writel(BM_ANADIG_TEMPSENSE0_POWER_DOWN, &anatop->tempsense0_clr); |
307 | writel(BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_set); | 307 | writel(BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_set); |
308 | 308 | ||
309 | /* write measure freq */ | 309 | /* write measure freq */ |
310 | reg = readl(&anatop->tempsense1); | 310 | reg = readl(&anatop->tempsense1); |
311 | reg &= ~BM_ANADIG_TEMPSENSE1_MEASURE_FREQ; | 311 | reg &= ~BM_ANADIG_TEMPSENSE1_MEASURE_FREQ; |
312 | reg |= MEASURE_FREQ; | 312 | reg |= MEASURE_FREQ; |
313 | writel(reg, &anatop->tempsense1); | 313 | writel(reg, &anatop->tempsense1); |
314 | 314 | ||
315 | writel(BM_ANADIG_TEMPSENSE0_MEASURE_TEMP, &anatop->tempsense0_clr); | 315 | writel(BM_ANADIG_TEMPSENSE0_MEASURE_TEMP, &anatop->tempsense0_clr); |
316 | writel(BM_ANADIG_TEMPSENSE0_FINISHED, &anatop->tempsense0_clr); | 316 | writel(BM_ANADIG_TEMPSENSE0_FINISHED, &anatop->tempsense0_clr); |
317 | writel(BM_ANADIG_TEMPSENSE0_MEASURE_TEMP, &anatop->tempsense0_set); | 317 | writel(BM_ANADIG_TEMPSENSE0_MEASURE_TEMP, &anatop->tempsense0_set); |
318 | 318 | ||
319 | while ((readl(&anatop->tempsense0) & | 319 | while ((readl(&anatop->tempsense0) & |
320 | BM_ANADIG_TEMPSENSE0_FINISHED) == 0) | 320 | BM_ANADIG_TEMPSENSE0_FINISHED) == 0) |
321 | udelay(10000); | 321 | udelay(10000); |
322 | 322 | ||
323 | reg = readl(&anatop->tempsense0); | 323 | reg = readl(&anatop->tempsense0); |
324 | tmp = (reg & BM_ANADIG_TEMPSENSE0_TEMP_VALUE) | 324 | tmp = (reg & BM_ANADIG_TEMPSENSE0_TEMP_VALUE) |
325 | >> BP_ANADIG_TEMPSENSE0_TEMP_VALUE; | 325 | >> BP_ANADIG_TEMPSENSE0_TEMP_VALUE; |
326 | writel(BM_ANADIG_TEMPSENSE0_FINISHED, &anatop->tempsense0_clr); | 326 | writel(BM_ANADIG_TEMPSENSE0_FINISHED, &anatop->tempsense0_clr); |
327 | 327 | ||
328 | if (tmp <= raw_n40c) | 328 | if (tmp <= raw_n40c) |
329 | temperature = REG_VALUE_TO_CEL(ratio, tmp); | 329 | temperature = REG_VALUE_TO_CEL(ratio, tmp); |
330 | else | 330 | else |
331 | temperature = TEMPERATURE_MIN; | 331 | temperature = TEMPERATURE_MIN; |
332 | /* power down anatop thermal sensor */ | 332 | /* power down anatop thermal sensor */ |
333 | writel(BM_ANADIG_TEMPSENSE0_POWER_DOWN, &anatop->tempsense0_set); | 333 | writel(BM_ANADIG_TEMPSENSE0_POWER_DOWN, &anatop->tempsense0_set); |
334 | writel(BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_clr); | 334 | writel(BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_clr); |
335 | 335 | ||
336 | return temperature; | 336 | return temperature; |
337 | } | 337 | } |
338 | 338 | ||
339 | void check_cpu_temperature(void) | 339 | void check_cpu_temperature(void) |
340 | { | 340 | { |
341 | int cpu_tmp = 0; | 341 | int cpu_tmp = 0; |
342 | 342 | ||
343 | cpu_tmp = read_cpu_temperature(); | 343 | cpu_tmp = read_cpu_temperature(); |
344 | while (cpu_tmp > TEMPERATURE_MIN && cpu_tmp < TEMPERATURE_MAX) { | 344 | while (cpu_tmp > TEMPERATURE_MIN && cpu_tmp < TEMPERATURE_MAX) { |
345 | if (cpu_tmp >= TEMPERATURE_HOT) { | 345 | if (cpu_tmp >= TEMPERATURE_HOT) { |
346 | printf("CPU is %d C, too hot to boot, waiting...\n", | 346 | printf("CPU is %d C, too hot to boot, waiting...\n", |
347 | cpu_tmp); | 347 | cpu_tmp); |
348 | udelay(5000000); | 348 | udelay(5000000); |
349 | cpu_tmp = read_cpu_temperature(); | 349 | cpu_tmp = read_cpu_temperature(); |
350 | } else | 350 | } else |
351 | break; | 351 | break; |
352 | } | 352 | } |
353 | if (cpu_tmp > TEMPERATURE_MIN && cpu_tmp < TEMPERATURE_MAX) | 353 | if (cpu_tmp > TEMPERATURE_MIN && cpu_tmp < TEMPERATURE_MAX) |
354 | printf("CPU: Temperature %d C, calibration data: 0x%x\n", | 354 | printf("CPU: Temperature %d C, calibration data: 0x%x\n", |
355 | cpu_tmp, fuse); | 355 | cpu_tmp, fuse); |
356 | else | 356 | else |
357 | printf("CPU: Temperature: can't get valid data!\n"); | 357 | printf("CPU: Temperature: can't get valid data!\n"); |
358 | } | 358 | } |
359 | 359 | ||
360 | static void set_ahb_rate(u32 val) | 360 | static void set_ahb_rate(u32 val) |
361 | { | 361 | { |
362 | struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; | 362 | struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; |
363 | u32 reg, div; | 363 | u32 reg, div; |
364 | 364 | ||
365 | div = get_periph_clk() / val - 1; | 365 | div = get_periph_clk() / val - 1; |
366 | reg = readl(&mxc_ccm->cbcdr); | 366 | reg = readl(&mxc_ccm->cbcdr); |
367 | 367 | ||
368 | writel((reg & (~MXC_CCM_CBCDR_AHB_PODF_MASK)) | | 368 | writel((reg & (~MXC_CCM_CBCDR_AHB_PODF_MASK)) | |
369 | (div << MXC_CCM_CBCDR_AHB_PODF_OFFSET), &mxc_ccm->cbcdr); | 369 | (div << MXC_CCM_CBCDR_AHB_PODF_OFFSET), &mxc_ccm->cbcdr); |
370 | } | 370 | } |
371 | 371 | ||
372 | static void clear_mmdc_ch_mask(void) | 372 | static void clear_mmdc_ch_mask(void) |
373 | { | 373 | { |
374 | struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; | 374 | struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; |
375 | 375 | ||
376 | /* Clear MMDC channel mask */ | 376 | /* Clear MMDC channel mask */ |
377 | writel(0, &mxc_ccm->ccdr); | 377 | writel(0, &mxc_ccm->ccdr); |
378 | } | 378 | } |
379 | 379 | ||
380 | #ifdef CONFIG_MX6SX | 380 | #ifdef CONFIG_MX6SX |
381 | void vadc_power_up(void) | 381 | void vadc_power_up(void) |
382 | { | 382 | { |
383 | struct iomuxc *iomux = (struct iomuxc *)IOMUXC_GPR_BASE_ADDR; | 383 | struct iomuxc *iomux = (struct iomuxc *)IOMUXC_GPR_BASE_ADDR; |
384 | u32 val; | 384 | u32 val; |
385 | 385 | ||
386 | /* csi0 */ | 386 | /* csi0 */ |
387 | val = readl(&iomux->gpr[5]); | 387 | val = readl(&iomux->gpr[5]); |
388 | val &= ~IMX6SX_GPR5_CSI1_MUX_CTRL_MASK, | 388 | val &= ~IMX6SX_GPR5_CSI1_MUX_CTRL_MASK, |
389 | val |= IMX6SX_GPR5_CSI1_MUX_CTRL_CVD; | 389 | val |= IMX6SX_GPR5_CSI1_MUX_CTRL_CVD; |
390 | writel(val, &iomux->gpr[5]); | 390 | writel(val, &iomux->gpr[5]); |
391 | 391 | ||
392 | /* Power on vadc analog | 392 | /* Power on vadc analog |
393 | * Power down vadc ext power */ | 393 | * Power down vadc ext power */ |
394 | val = readl(GPC_BASE_ADDR + 0); | 394 | val = readl(GPC_BASE_ADDR + 0); |
395 | val &= ~0x60000; | 395 | val &= ~0x60000; |
396 | writel(val, GPC_BASE_ADDR + 0); | 396 | writel(val, GPC_BASE_ADDR + 0); |
397 | 397 | ||
398 | /* software reset afe */ | 398 | /* software reset afe */ |
399 | val = readl(&iomux->gpr[1]); | 399 | val = readl(&iomux->gpr[1]); |
400 | writel(val | 0x80000, &iomux->gpr[1]); | 400 | writel(val | 0x80000, &iomux->gpr[1]); |
401 | 401 | ||
402 | udelay(10*1000); | 402 | udelay(10*1000); |
403 | 403 | ||
404 | /* Release reset bit */ | 404 | /* Release reset bit */ |
405 | writel(val & ~0x80000, &iomux->gpr[1]); | 405 | writel(val & ~0x80000, &iomux->gpr[1]); |
406 | 406 | ||
407 | /* Power on vadc ext power */ | 407 | /* Power on vadc ext power */ |
408 | val = readl(GPC_BASE_ADDR + 0); | 408 | val = readl(GPC_BASE_ADDR + 0); |
409 | val |= 0x40000; | 409 | val |= 0x40000; |
410 | writel(val, GPC_BASE_ADDR + 0); | 410 | writel(val, GPC_BASE_ADDR + 0); |
411 | } | 411 | } |
412 | 412 | ||
413 | void vadc_power_down(void) | 413 | void vadc_power_down(void) |
414 | { | 414 | { |
415 | struct iomuxc *iomux = (struct iomuxc *)IOMUXC_GPR_BASE_ADDR; | 415 | struct iomuxc *iomux = (struct iomuxc *)IOMUXC_GPR_BASE_ADDR; |
416 | u32 val; | 416 | u32 val; |
417 | 417 | ||
418 | /* Power down vadc ext power | 418 | /* Power down vadc ext power |
419 | * Power off vadc analog */ | 419 | * Power off vadc analog */ |
420 | val = readl(GPC_BASE_ADDR + 0); | 420 | val = readl(GPC_BASE_ADDR + 0); |
421 | val &= ~0x40000; | 421 | val &= ~0x40000; |
422 | val |= 0x20000; | 422 | val |= 0x20000; |
423 | writel(val, GPC_BASE_ADDR + 0); | 423 | writel(val, GPC_BASE_ADDR + 0); |
424 | 424 | ||
425 | /* clean csi0 connect to vadc */ | 425 | /* clean csi0 connect to vadc */ |
426 | val = readl(&iomux->gpr[5]); | 426 | val = readl(&iomux->gpr[5]); |
427 | val &= ~IMX6SX_GPR5_CSI1_MUX_CTRL_MASK, | 427 | val &= ~IMX6SX_GPR5_CSI1_MUX_CTRL_MASK, |
428 | writel(val, &iomux->gpr[5]); | 428 | writel(val, &iomux->gpr[5]); |
429 | } | 429 | } |
430 | 430 | ||
431 | void pcie_power_up(void) | 431 | void pcie_power_up(void) |
432 | { | 432 | { |
433 | set_ldo_voltage(LDO_PU, 1100); /* Set VDDPU to 1.1V */ | 433 | set_ldo_voltage(LDO_PU, 1100); /* Set VDDPU to 1.1V */ |
434 | } | 434 | } |
435 | 435 | ||
436 | void pcie_power_off(void) | 436 | void pcie_power_off(void) |
437 | { | 437 | { |
438 | set_ldo_voltage(LDO_PU, 0); /* Set VDDPU to 1.1V */ | 438 | set_ldo_voltage(LDO_PU, 0); /* Set VDDPU to 1.1V */ |
439 | } | 439 | } |
440 | #endif | 440 | #endif |
441 | 441 | ||
442 | static void imx_set_vddpu_power_down(void) | 442 | static void imx_set_vddpu_power_down(void) |
443 | { | 443 | { |
444 | struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; | 444 | struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; |
445 | u32 val; | 445 | u32 val; |
446 | 446 | ||
447 | /* need to power down xPU in GPC before turn off PU LDO */ | 447 | /* need to power down xPU in GPC before turn off PU LDO */ |
448 | val = readl(GPC_BASE_ADDR + 0x260); | 448 | val = readl(GPC_BASE_ADDR + 0x260); |
449 | writel(val | 0x1, GPC_BASE_ADDR + 0x260); | 449 | writel(val | 0x1, GPC_BASE_ADDR + 0x260); |
450 | 450 | ||
451 | val = readl(GPC_BASE_ADDR + 0x0); | 451 | val = readl(GPC_BASE_ADDR + 0x0); |
452 | writel(val | 0x1, GPC_BASE_ADDR + 0x0); | 452 | writel(val | 0x1, GPC_BASE_ADDR + 0x0); |
453 | while (readl(GPC_BASE_ADDR + 0x0) & 0x1) | 453 | while (readl(GPC_BASE_ADDR + 0x0) & 0x1) |
454 | ; | 454 | ; |
455 | 455 | ||
456 | /* disable VDDPU */ | 456 | /* disable VDDPU */ |
457 | val = 0x3e00; | 457 | val = 0x3e00; |
458 | writel(val, &anatop->reg_core_clr); | 458 | writel(val, &anatop->reg_core_clr); |
459 | } | 459 | } |
460 | 460 | ||
461 | #ifndef CONFIG_MX6SL | 461 | #ifndef CONFIG_MX6SL |
462 | static void imx_set_pcie_phy_power_down(void) | 462 | static void imx_set_pcie_phy_power_down(void) |
463 | { | 463 | { |
464 | u32 val; | 464 | u32 val; |
465 | 465 | ||
466 | #ifndef CONFIG_MX6SX | 466 | #ifndef CONFIG_MX6SX |
467 | val = readl(IOMUXC_BASE_ADDR + 0x4); | 467 | val = readl(IOMUXC_BASE_ADDR + 0x4); |
468 | val |= 0x1 << 18; | 468 | val |= 0x1 << 18; |
469 | writel(val, IOMUXC_BASE_ADDR + 0x4); | 469 | writel(val, IOMUXC_BASE_ADDR + 0x4); |
470 | #else | 470 | #else |
471 | val = readl(IOMUXC_GPR_BASE_ADDR + 0x30); | 471 | val = readl(IOMUXC_GPR_BASE_ADDR + 0x30); |
472 | val |= 0x1 << 30; | 472 | val |= 0x1 << 30; |
473 | writel(val, IOMUXC_GPR_BASE_ADDR + 0x30); | 473 | writel(val, IOMUXC_GPR_BASE_ADDR + 0x30); |
474 | #endif | 474 | #endif |
475 | } | 475 | } |
476 | #endif | 476 | #endif |
477 | 477 | ||
478 | int arch_cpu_init(void) | 478 | int arch_cpu_init(void) |
479 | { | 479 | { |
480 | #if !defined(CONFIG_MX6SX) && !defined(CONFIG_MX6SL) | 480 | #if !defined(CONFIG_MX6SX) && !defined(CONFIG_MX6SL) |
481 | /* | 481 | /* |
482 | * imx6sl doesn't have pcie at all. | 482 | * imx6sl doesn't have pcie at all. |
483 | * this bit is not used by imx6sx anymore | 483 | * this bit is not used by imx6sx anymore |
484 | */ | 484 | */ |
485 | u32 val; | 485 | u32 val; |
486 | 486 | ||
487 | /* | 487 | /* |
488 | * There are about 0.02% percentage, random pcie link down | 488 | * There are about 0.02% percentage, random pcie link down |
489 | * when warm-reset is used. | 489 | * when warm-reset is used. |
490 | * clear the ref_ssp_en bit16 of gpr1 to workaround it. | 490 | * clear the ref_ssp_en bit16 of gpr1 to workaround it. |
491 | * then warm-reset imx6q/dl/solo again. | 491 | * then warm-reset imx6q/dl/solo again. |
492 | */ | 492 | */ |
493 | val = readl(IOMUXC_BASE_ADDR + 0x4); | 493 | val = readl(IOMUXC_BASE_ADDR + 0x4); |
494 | if (val & (0x1 << 16)) { | 494 | if (val & (0x1 << 16)) { |
495 | val &= ~(0x1 << 16); | 495 | val &= ~(0x1 << 16); |
496 | writel(val, IOMUXC_BASE_ADDR + 0x4); | 496 | writel(val, IOMUXC_BASE_ADDR + 0x4); |
497 | reset_cpu(0); | 497 | reset_cpu(0); |
498 | } | 498 | } |
499 | #endif | 499 | #endif |
500 | 500 | ||
501 | init_aips(); | 501 | init_aips(); |
502 | 502 | ||
503 | /* Need to clear MMDC_CHx_MASK to make warm reset work. */ | 503 | /* Need to clear MMDC_CHx_MASK to make warm reset work. */ |
504 | clear_mmdc_ch_mask(); | 504 | clear_mmdc_ch_mask(); |
505 | 505 | ||
506 | /* | 506 | /* |
507 | * When low freq boot is enabled, ROM will not set AHB | 507 | * When low freq boot is enabled, ROM will not set AHB |
508 | * freq, so we need to ensure AHB freq is 132MHz in such | 508 | * freq, so we need to ensure AHB freq is 132MHz in such |
509 | * scenario. | 509 | * scenario. |
510 | */ | 510 | */ |
511 | if (mxc_get_clock(MXC_ARM_CLK) == 396000000) | 511 | if (mxc_get_clock(MXC_ARM_CLK) == 396000000) |
512 | set_ahb_rate(132000000); | 512 | set_ahb_rate(132000000); |
513 | 513 | ||
514 | imx_set_wdog_powerdown(false); /* Disable PDE bit of WMCR register */ | 514 | imx_set_wdog_powerdown(false); /* Disable PDE bit of WMCR register */ |
515 | 515 | ||
516 | #ifndef CONFIG_MX6SL | 516 | #ifndef CONFIG_MX6SL |
517 | imx_set_pcie_phy_power_down(); | 517 | imx_set_pcie_phy_power_down(); |
518 | #endif | 518 | #endif |
519 | imx_set_vddpu_power_down(); | 519 | imx_set_vddpu_power_down(); |
520 | 520 | ||
521 | #ifdef CONFIG_APBH_DMA | 521 | #ifdef CONFIG_APBH_DMA |
522 | /* Start APBH DMA */ | 522 | /* Start APBH DMA */ |
523 | mxs_dma_init(); | 523 | mxs_dma_init(); |
524 | #endif | 524 | #endif |
525 | 525 | ||
526 | return 0; | 526 | return 0; |
527 | } | 527 | } |
528 | 528 | ||
529 | int board_postclk_init(void) | 529 | int board_postclk_init(void) |
530 | { | 530 | { |
531 | set_ldo_voltage(LDO_SOC, 1175); /* Set VDDSOC to 1.175V */ | 531 | set_ldo_voltage(LDO_SOC, 1175); /* Set VDDSOC to 1.175V */ |
532 | 532 | ||
533 | return 0; | 533 | return 0; |
534 | } | 534 | } |
535 | 535 | ||
536 | #ifdef CONFIG_SERIAL_TAG | 536 | #ifdef CONFIG_SERIAL_TAG |
537 | void get_board_serial(struct tag_serialnr *serialnr) | 537 | void get_board_serial(struct tag_serialnr *serialnr) |
538 | { | 538 | { |
539 | struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; | 539 | struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; |
540 | struct fuse_bank *bank = &ocotp->bank[0]; | 540 | struct fuse_bank *bank = &ocotp->bank[0]; |
541 | struct fuse_bank0_regs *fuse = | 541 | struct fuse_bank0_regs *fuse = |
542 | (struct fuse_bank0_regs *)bank->fuse_regs; | 542 | (struct fuse_bank0_regs *)bank->fuse_regs; |
543 | 543 | ||
544 | serialnr->low = fuse->uid_low; | 544 | serialnr->low = fuse->uid_low; |
545 | serialnr->high = fuse->uid_high; | 545 | serialnr->high = fuse->uid_high; |
546 | } | 546 | } |
547 | #endif | 547 | #endif |
548 | 548 | ||
549 | #ifndef CONFIG_SYS_DCACHE_OFF | 549 | #ifndef CONFIG_SYS_DCACHE_OFF |
550 | void enable_caches(void) | 550 | void enable_caches(void) |
551 | { | 551 | { |
552 | #if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) | 552 | #if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) |
553 | enum dcache_option option = DCACHE_WRITETHROUGH; | 553 | enum dcache_option option = DCACHE_WRITETHROUGH; |
554 | #else | 554 | #else |
555 | enum dcache_option option = DCACHE_WRITEBACK; | 555 | enum dcache_option option = DCACHE_WRITEBACK; |
556 | #endif | 556 | #endif |
557 | 557 | ||
558 | /* Avoid random hang when download by usb */ | 558 | /* Avoid random hang when download by usb */ |
559 | invalidate_dcache_all(); | 559 | invalidate_dcache_all(); |
560 | 560 | ||
561 | /* Enable D-cache. I-cache is already enabled in start.S */ | 561 | /* Enable D-cache. I-cache is already enabled in start.S */ |
562 | dcache_enable(); | 562 | dcache_enable(); |
563 | 563 | ||
564 | /* Enable caching on OCRAM and ROM */ | 564 | /* Enable caching on OCRAM and ROM */ |
565 | mmu_set_region_dcache_behaviour(ROMCP_ARB_BASE_ADDR, | 565 | mmu_set_region_dcache_behaviour(ROMCP_ARB_BASE_ADDR, |
566 | ROMCP_ARB_END_ADDR, | 566 | ROMCP_ARB_END_ADDR, |
567 | option); | 567 | option); |
568 | mmu_set_region_dcache_behaviour(IRAM_BASE_ADDR, | 568 | mmu_set_region_dcache_behaviour(IRAM_BASE_ADDR, |
569 | IRAM_SIZE, | 569 | IRAM_SIZE, |
570 | option); | 570 | option); |
571 | } | 571 | } |
572 | #endif | 572 | #endif |
573 | 573 | ||
574 | #if defined(CONFIG_FEC_MXC) | 574 | #if defined(CONFIG_FEC_MXC) |
575 | void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) | 575 | void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) |
576 | { | 576 | { |
577 | struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; | 577 | struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; |
578 | struct fuse_bank *bank = &ocotp->bank[4]; | 578 | struct fuse_bank *bank = &ocotp->bank[4]; |
579 | struct fuse_bank4_regs *fuse = | 579 | struct fuse_bank4_regs *fuse = |
580 | (struct fuse_bank4_regs *)bank->fuse_regs; | 580 | (struct fuse_bank4_regs *)bank->fuse_regs; |
581 | 581 | ||
582 | #ifdef CONFIG_MX6SX | 582 | #ifdef CONFIG_MX6SX |
583 | if (0 == dev_id) { | 583 | if (0 == dev_id) { |
584 | u32 value = readl(&fuse->mac_addr1); | 584 | u32 value = readl(&fuse->mac_addr1); |
585 | mac[0] = (value >> 8); | 585 | mac[0] = (value >> 8); |
586 | mac[1] = value ; | 586 | mac[1] = value ; |
587 | 587 | ||
588 | value = readl(&fuse->mac_addr0); | 588 | value = readl(&fuse->mac_addr0); |
589 | mac[2] = value >> 24 ; | 589 | mac[2] = value >> 24 ; |
590 | mac[3] = value >> 16 ; | 590 | mac[3] = value >> 16 ; |
591 | mac[4] = value >> 8 ; | 591 | mac[4] = value >> 8 ; |
592 | mac[5] = value ; | 592 | mac[5] = value ; |
593 | } else { | 593 | } else { |
594 | u32 value = readl(&fuse->mac_addr2); | 594 | u32 value = readl(&fuse->mac_addr2); |
595 | mac[0] = value >> 24 ; | 595 | mac[0] = value >> 24 ; |
596 | mac[1] = value >> 16 ; | 596 | mac[1] = value >> 16 ; |
597 | mac[2] = value >> 8 ; | 597 | mac[2] = value >> 8 ; |
598 | mac[3] = value ; | 598 | mac[3] = value ; |
599 | 599 | ||
600 | value = readl(&fuse->mac_addr1); | 600 | value = readl(&fuse->mac_addr1); |
601 | mac[4] = value >> 24 ; | 601 | mac[4] = value >> 24 ; |
602 | mac[5] = value >> 16 ; | 602 | mac[5] = value >> 16 ; |
603 | } | 603 | } |
604 | #else | 604 | #else |
605 | u32 value = readl(&fuse->mac_addr_high); | 605 | u32 value = readl(&fuse->mac_addr_high); |
606 | mac[0] = (value >> 8); | 606 | mac[0] = (value >> 8); |
607 | mac[1] = value ; | 607 | mac[1] = value ; |
608 | 608 | ||
609 | value = readl(&fuse->mac_addr_low); | 609 | value = readl(&fuse->mac_addr_low); |
610 | mac[2] = value >> 24 ; | 610 | mac[2] = value >> 24 ; |
611 | mac[3] = value >> 16 ; | 611 | mac[3] = value >> 16 ; |
612 | mac[4] = value >> 8 ; | 612 | mac[4] = value >> 8 ; |
613 | mac[5] = value ; | 613 | mac[5] = value ; |
614 | #endif | 614 | #endif |
615 | } | 615 | } |
616 | #endif | 616 | #endif |
617 | 617 | ||
618 | #ifdef CONFIG_MX6SX | 618 | #ifdef CONFIG_MX6SX |
619 | int arch_auxiliary_core_up(u32 core_id, u32 boot_private_data) | 619 | int arch_auxiliary_core_up(u32 core_id, u32 boot_private_data) |
620 | { | 620 | { |
621 | struct src *src_reg; | 621 | struct src *src_reg; |
622 | u32 stack, pc; | 622 | u32 stack, pc; |
623 | 623 | ||
624 | if (!boot_private_data) | 624 | if (!boot_private_data) |
625 | return 1; | 625 | return 1; |
626 | 626 | ||
627 | stack = *(u32 *)boot_private_data; | 627 | stack = *(u32 *)boot_private_data; |
628 | pc = *(u32 *)(boot_private_data + 4); | 628 | pc = *(u32 *)(boot_private_data + 4); |
629 | 629 | ||
630 | /* Set the stack and pc to M4 bootROM */ | 630 | /* Set the stack and pc to M4 bootROM */ |
631 | writel(stack, M4_BOOTROM_BASE_ADDR); | 631 | writel(stack, M4_BOOTROM_BASE_ADDR); |
632 | writel(pc, M4_BOOTROM_BASE_ADDR + 4); | 632 | writel(pc, M4_BOOTROM_BASE_ADDR + 4); |
633 | 633 | ||
634 | /* Enable M4 */ | 634 | /* Enable M4 */ |
635 | src_reg = (struct src *)SRC_BASE_ADDR; | 635 | src_reg = (struct src *)SRC_BASE_ADDR; |
636 | setbits_le32(&src_reg->scr, 0x00400000); | 636 | setbits_le32(&src_reg->scr, 0x00400000); |
637 | clrbits_le32(&src_reg->scr, 0x00000010); | 637 | clrbits_le32(&src_reg->scr, 0x00000010); |
638 | 638 | ||
639 | return 0; | 639 | return 0; |
640 | } | 640 | } |
641 | 641 | ||
642 | int arch_auxiliary_core_check_up(u32 core_id) | 642 | int arch_auxiliary_core_check_up(u32 core_id) |
643 | { | 643 | { |
644 | struct src *src_reg = (struct src *)SRC_BASE_ADDR; | 644 | struct src *src_reg = (struct src *)SRC_BASE_ADDR; |
645 | unsigned val; | 645 | unsigned val; |
646 | 646 | ||
647 | val = readl(&src_reg->scr); | 647 | val = readl(&src_reg->scr); |
648 | 648 | ||
649 | if (val & 0x00000010) | 649 | if (val & 0x00000010) |
650 | return 0; /* assert in reset */ | 650 | return 0; /* assert in reset */ |
651 | 651 | ||
652 | return 1; | 652 | return 1; |
653 | } | 653 | } |
654 | #endif | 654 | #endif |
655 | 655 | ||
656 | void boot_mode_apply(unsigned cfg_val) | 656 | void boot_mode_apply(unsigned cfg_val) |
657 | { | 657 | { |
658 | unsigned reg; | 658 | unsigned reg; |
659 | struct src *psrc = (struct src *)SRC_BASE_ADDR; | 659 | struct src *psrc = (struct src *)SRC_BASE_ADDR; |
660 | writel(cfg_val, &psrc->gpr9); | 660 | writel(cfg_val, &psrc->gpr9); |
661 | reg = readl(&psrc->gpr10); | 661 | reg = readl(&psrc->gpr10); |
662 | if (cfg_val) | 662 | if (cfg_val) |
663 | reg |= 1 << 28; | 663 | reg |= 1 << 28; |
664 | else | 664 | else |
665 | reg &= ~(1 << 28); | 665 | reg &= ~(1 << 28); |
666 | writel(reg, &psrc->gpr10); | 666 | writel(reg, &psrc->gpr10); |
667 | } | 667 | } |
668 | /* | 668 | /* |
669 | * cfg_val will be used for | 669 | * cfg_val will be used for |
670 | * Boot_cfg4[7:0]:Boot_cfg3[7:0]:Boot_cfg2[7:0]:Boot_cfg1[7:0] | 670 | * Boot_cfg4[7:0]:Boot_cfg3[7:0]:Boot_cfg2[7:0]:Boot_cfg1[7:0] |
671 | * After reset, if GPR10[28] is 1, ROM will copy GPR9[25:0] | 671 | * After reset, if GPR10[28] is 1, ROM will copy GPR9[25:0] |
672 | * to SBMR1, which will determine the boot device. | 672 | * to SBMR1, which will determine the boot device. |
673 | */ | 673 | */ |
674 | const struct boot_mode soc_boot_modes[] = { | 674 | const struct boot_mode soc_boot_modes[] = { |
675 | {"normal", MAKE_CFGVAL(0x00, 0x00, 0x00, 0x00)}, | 675 | {"normal", MAKE_CFGVAL(0x00, 0x00, 0x00, 0x00)}, |
676 | /* reserved value should start rom usb */ | 676 | /* reserved value should start rom usb */ |
677 | {"usb", MAKE_CFGVAL(0x01, 0x00, 0x00, 0x00)}, | 677 | {"usb", MAKE_CFGVAL(0x01, 0x00, 0x00, 0x00)}, |
678 | {"sata", MAKE_CFGVAL(0x20, 0x00, 0x00, 0x00)}, | 678 | {"sata", MAKE_CFGVAL(0x20, 0x00, 0x00, 0x00)}, |
679 | {"escpi1:0", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x08)}, | 679 | {"escpi1:0", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x08)}, |
680 | {"escpi1:1", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x18)}, | 680 | {"escpi1:1", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x18)}, |
681 | {"escpi1:2", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x28)}, | 681 | {"escpi1:2", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x28)}, |
682 | {"escpi1:3", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x38)}, | 682 | {"escpi1:3", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x38)}, |
683 | /* 4 bit bus width */ | 683 | /* 4 bit bus width */ |
684 | {"esdhc1", MAKE_CFGVAL(0x40, 0x20, 0x00, 0x00)}, | 684 | {"esdhc1", MAKE_CFGVAL(0x40, 0x20, 0x00, 0x00)}, |
685 | {"esdhc2", MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)}, | 685 | {"esdhc2", MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)}, |
686 | {"esdhc3", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)}, | 686 | {"esdhc3", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)}, |
687 | {"esdhc4", MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00)}, | 687 | {"esdhc4", MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00)}, |
688 | {NULL, 0}, | 688 | {NULL, 0}, |
689 | }; | 689 | }; |
690 | 690 | ||
691 | enum boot_device get_boot_device(void) | 691 | enum boot_device get_boot_device(void) |
692 | { | 692 | { |
693 | enum boot_device boot_dev = UNKNOWN_BOOT; | 693 | enum boot_device boot_dev = UNKNOWN_BOOT; |
694 | uint soc_sbmr = readl(SRC_BASE_ADDR + 0x4); | 694 | uint soc_sbmr = readl(SRC_BASE_ADDR + 0x4); |
695 | uint bt_mem_ctl = (soc_sbmr & 0x000000FF) >> 4 ; | 695 | uint bt_mem_ctl = (soc_sbmr & 0x000000FF) >> 4 ; |
696 | uint bt_mem_type = (soc_sbmr & 0x00000008) >> 3; | 696 | uint bt_mem_type = (soc_sbmr & 0x00000008) >> 3; |
697 | uint bt_dev_port = (soc_sbmr & 0x00001800) >> 11; | 697 | uint bt_dev_port = (soc_sbmr & 0x00001800) >> 11; |
698 | 698 | ||
699 | switch (bt_mem_ctl) { | 699 | switch (bt_mem_ctl) { |
700 | case 0x0: | 700 | case 0x0: |
701 | if (bt_mem_type) | 701 | if (bt_mem_type) |
702 | boot_dev = ONE_NAND_BOOT; | 702 | boot_dev = ONE_NAND_BOOT; |
703 | else | 703 | else |
704 | boot_dev = WEIM_NOR_BOOT; | 704 | boot_dev = WEIM_NOR_BOOT; |
705 | break; | 705 | break; |
706 | case 0x2: | 706 | case 0x2: |
707 | boot_dev = SATA_BOOT; | 707 | boot_dev = SATA_BOOT; |
708 | break; | 708 | break; |
709 | case 0x3: | 709 | case 0x3: |
710 | if (bt_mem_type) | 710 | if (bt_mem_type) |
711 | boot_dev = I2C_BOOT; | 711 | boot_dev = I2C_BOOT; |
712 | else | 712 | else |
713 | boot_dev = SPI_NOR_BOOT; | 713 | boot_dev = SPI_NOR_BOOT; |
714 | break; | 714 | break; |
715 | case 0x4: | 715 | case 0x4: |
716 | case 0x5: | 716 | case 0x5: |
717 | boot_dev = bt_dev_port + SD1_BOOT; | 717 | boot_dev = bt_dev_port + SD1_BOOT; |
718 | break; | 718 | break; |
719 | case 0x6: | 719 | case 0x6: |
720 | case 0x7: | 720 | case 0x7: |
721 | boot_dev = bt_dev_port + MMC1_BOOT; | 721 | boot_dev = bt_dev_port + MMC1_BOOT; |
722 | break; | 722 | break; |
723 | case 0x8 ... 0xf: | 723 | case 0x8 ... 0xf: |
724 | boot_dev = NAND_BOOT; | 724 | boot_dev = NAND_BOOT; |
725 | break; | 725 | break; |
726 | default: | 726 | default: |
727 | boot_dev = UNKNOWN_BOOT; | 727 | boot_dev = UNKNOWN_BOOT; |
728 | break; | 728 | break; |
729 | } | 729 | } |
730 | 730 | ||
731 | return boot_dev; | 731 | return boot_dev; |
732 | } | 732 | } |
733 | 733 | ||
734 | void s_init(void) | 734 | void s_init(void) |
735 | { | 735 | { |
736 | struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; | 736 | struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; |
737 | int is_6q = is_cpu_type(MXC_CPU_MX6Q); | 737 | struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; |
738 | int is_6sx = is_cpu_type(MXC_CPU_MX6SX); | 738 | int is_6sx = is_cpu_type(MXC_CPU_MX6SX); |
739 | u32 mask480; | 739 | u32 mask480; |
740 | u32 mask528; | 740 | u32 mask528; |
741 | u32 reg, periph1, periph2; | ||
741 | 742 | ||
742 | /* Don't reset PFD for MX6SX */ | 743 | /* Don't reset PFD for MX6SX */ |
743 | if (is_6sx) | 744 | if (is_6sx) |
744 | return; | 745 | return; |
745 | 746 | ||
746 | /* Due to hardware limitation, on MX6Q we need to gate/ungate all PFDs | 747 | /* Due to hardware limitation, on MX6Q we need to gate/ungate all PFDs |
747 | * to make sure PFD is working right, otherwise, PFDs may | 748 | * to make sure PFD is working right, otherwise, PFDs may |
748 | * not output clock after reset, MX6DL and MX6SL have added 396M pfd | 749 | * not output clock after reset, MX6DL and MX6SL have added 396M pfd |
749 | * workaround in ROM code, as bus clock need it | 750 | * workaround in ROM code, as bus clock need it |
750 | */ | 751 | */ |
751 | 752 | ||
752 | mask480 = ANATOP_PFD_CLKGATE_MASK(0) | | 753 | mask480 = ANATOP_PFD_CLKGATE_MASK(0) | |
753 | ANATOP_PFD_CLKGATE_MASK(1) | | 754 | ANATOP_PFD_CLKGATE_MASK(1) | |
754 | ANATOP_PFD_CLKGATE_MASK(2) | | 755 | ANATOP_PFD_CLKGATE_MASK(2) | |
755 | ANATOP_PFD_CLKGATE_MASK(3); | 756 | ANATOP_PFD_CLKGATE_MASK(3); |
756 | mask528 = ANATOP_PFD_CLKGATE_MASK(0) | | 757 | mask528 = ANATOP_PFD_CLKGATE_MASK(1) | |
757 | ANATOP_PFD_CLKGATE_MASK(1) | | ||
758 | ANATOP_PFD_CLKGATE_MASK(3); | 758 | ANATOP_PFD_CLKGATE_MASK(3); |
759 | 759 | ||
760 | /* | 760 | reg = readl(&ccm->cbcmr); |
761 | * Don't reset PFD2 on DL/S | 761 | periph2 = ((reg & MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK) |
762 | */ | 762 | >> MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET); |
763 | if (is_6q) | 763 | periph1 = ((reg & MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK) |
764 | >> MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET); | ||
765 | |||
766 | /* Checking if PLL2 PFD0 or PLL2 PFD2 is using for periph clock */ | ||
767 | if ((periph2 != 0x2) && (periph1 != 0x2)) | ||
768 | mask528 |= ANATOP_PFD_CLKGATE_MASK(0); | ||
769 | |||
770 | if ((periph2 != 0x1) && (periph1 != 0x1) && | ||
771 | (periph2 != 0x3) && (periph1 != 0x3)) | ||
764 | mask528 |= ANATOP_PFD_CLKGATE_MASK(2); | 772 | mask528 |= ANATOP_PFD_CLKGATE_MASK(2); |
773 | |||
765 | writel(mask480, &anatop->pfd_480_set); | 774 | writel(mask480, &anatop->pfd_480_set); |
766 | writel(mask528, &anatop->pfd_528_set); | 775 | writel(mask528, &anatop->pfd_528_set); |
767 | writel(mask480, &anatop->pfd_480_clr); | 776 | writel(mask480, &anatop->pfd_480_clr); |
768 | writel(mask528, &anatop->pfd_528_clr); | 777 | writel(mask528, &anatop->pfd_528_clr); |
769 | } | 778 | } |
770 | 779 | ||
771 | #ifdef CONFIG_LDO_BYPASS_CHECK | 780 | #ifdef CONFIG_LDO_BYPASS_CHECK |
772 | DECLARE_GLOBAL_DATA_PTR; | 781 | DECLARE_GLOBAL_DATA_PTR; |
773 | static int ldo_bypass; | 782 | static int ldo_bypass; |
774 | 783 | ||
775 | int check_ldo_bypass(void) | 784 | int check_ldo_bypass(void) |
776 | { | 785 | { |
777 | const int *ldo_mode; | 786 | const int *ldo_mode; |
778 | int node; | 787 | int node; |
779 | 788 | ||
780 | /* get the right fdt_blob from the global working_fdt */ | 789 | /* get the right fdt_blob from the global working_fdt */ |
781 | gd->fdt_blob = working_fdt; | 790 | gd->fdt_blob = working_fdt; |
782 | /* Get the node from FDT for anatop ldo-bypass */ | 791 | /* Get the node from FDT for anatop ldo-bypass */ |
783 | node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, | 792 | node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, |
784 | "fsl,imx6q-gpc"); | 793 | "fsl,imx6q-gpc"); |
785 | if (node < 0) { | 794 | if (node < 0) { |
786 | printf("No gpc device node %d, force to ldo-enable.\n", node); | 795 | printf("No gpc device node %d, force to ldo-enable.\n", node); |
787 | return 0; | 796 | return 0; |
788 | } | 797 | } |
789 | ldo_mode = fdt_getprop(gd->fdt_blob, node, "fsl,ldo-bypass", NULL); | 798 | ldo_mode = fdt_getprop(gd->fdt_blob, node, "fsl,ldo-bypass", NULL); |
790 | /* | 799 | /* |
791 | * return 1 if "fsl,ldo-bypass = <1>", else return 0 if | 800 | * return 1 if "fsl,ldo-bypass = <1>", else return 0 if |
792 | * "fsl,ldo-bypass = <0>" or no "fsl,ldo-bypass" property | 801 | * "fsl,ldo-bypass = <0>" or no "fsl,ldo-bypass" property |
793 | */ | 802 | */ |
794 | ldo_bypass = fdt32_to_cpu(*ldo_mode) == 1 ? 1 : 0; | 803 | ldo_bypass = fdt32_to_cpu(*ldo_mode) == 1 ? 1 : 0; |
795 | 804 | ||
796 | return ldo_bypass; | 805 | return ldo_bypass; |
797 | } | 806 | } |
798 | 807 | ||
799 | int check_1_2G(void) | 808 | int check_1_2G(void) |
800 | { | 809 | { |
801 | u32 reg; | 810 | u32 reg; |
802 | int result = 0; | 811 | int result = 0; |
803 | struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; | 812 | struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; |
804 | struct fuse_bank *bank = &ocotp->bank[0]; | 813 | struct fuse_bank *bank = &ocotp->bank[0]; |
805 | struct fuse_bank0_regs *fuse_bank0 = | 814 | struct fuse_bank0_regs *fuse_bank0 = |
806 | (struct fuse_bank0_regs *)bank->fuse_regs; | 815 | (struct fuse_bank0_regs *)bank->fuse_regs; |
807 | 816 | ||
808 | reg = readl(&fuse_bank0->cfg3); | 817 | reg = readl(&fuse_bank0->cfg3); |
809 | if (((reg >> 16) & 0x3) == 0x3) { | 818 | if (((reg >> 16) & 0x3) == 0x3) { |
810 | if (ldo_bypass) { | 819 | if (ldo_bypass) { |
811 | printf("Wrong dtb file used! i.MX6Q@1.2Ghz only " | 820 | printf("Wrong dtb file used! i.MX6Q@1.2Ghz only " |
812 | "works with ldo-enable mode!\n"); | 821 | "works with ldo-enable mode!\n"); |
813 | /* | 822 | /* |
814 | * Currently, only imx6q-sabresd board might be here, | 823 | * Currently, only imx6q-sabresd board might be here, |
815 | * since only i.MX6Q support 1.2G and only Sabresd board | 824 | * since only i.MX6Q support 1.2G and only Sabresd board |
816 | * support ldo-bypass mode. So hardcode here. | 825 | * support ldo-bypass mode. So hardcode here. |
817 | * You can also modify your board(i.MX6Q) dtb name if it | 826 | * You can also modify your board(i.MX6Q) dtb name if it |
818 | * supports both ldo-bypass and ldo-enable mode. | 827 | * supports both ldo-bypass and ldo-enable mode. |
819 | */ | 828 | */ |
820 | printf("Please use imx6q-sabresd-ldo.dtb!\n"); | 829 | printf("Please use imx6q-sabresd-ldo.dtb!\n"); |
821 | hang(); | 830 | hang(); |
822 | } | 831 | } |
823 | result = 1; | 832 | result = 1; |
824 | } | 833 | } |
825 | 834 | ||
826 | return result; | 835 | return result; |
827 | } | 836 | } |
828 | 837 | ||
829 | void set_anatop_bypass(void) | 838 | void set_anatop_bypass(void) |
830 | { | 839 | { |
831 | struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; | 840 | struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; |
832 | u32 reg = readl(&anatop->reg_core); | 841 | u32 reg = readl(&anatop->reg_core); |
833 | 842 | ||
834 | /* bypass VDDARM/VDDSOC */ | 843 | /* bypass VDDARM/VDDSOC */ |
835 | reg = reg | (0x1F << 18) | 0x1F; | 844 | reg = reg | (0x1F << 18) | 0x1F; |
836 | writel(reg, &anatop->reg_core); | 845 | writel(reg, &anatop->reg_core); |
837 | } | 846 | } |
838 | #endif | 847 | #endif |
839 | 848 | ||
840 | #ifdef CONFIG_IMX_HDMI | 849 | #ifdef CONFIG_IMX_HDMI |
841 | void imx_enable_hdmi_phy(void) | 850 | void imx_enable_hdmi_phy(void) |
842 | { | 851 | { |
843 | struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR; | 852 | struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR; |
844 | u8 reg; | 853 | u8 reg; |
845 | reg = readb(&hdmi->phy_conf0); | 854 | reg = readb(&hdmi->phy_conf0); |
846 | reg |= HDMI_PHY_CONF0_PDZ_MASK; | 855 | reg |= HDMI_PHY_CONF0_PDZ_MASK; |
847 | writeb(reg, &hdmi->phy_conf0); | 856 | writeb(reg, &hdmi->phy_conf0); |
848 | udelay(3000); | 857 | udelay(3000); |
849 | reg |= HDMI_PHY_CONF0_ENTMDS_MASK; | 858 | reg |= HDMI_PHY_CONF0_ENTMDS_MASK; |
850 | writeb(reg, &hdmi->phy_conf0); | 859 | writeb(reg, &hdmi->phy_conf0); |
851 | udelay(3000); | 860 | udelay(3000); |
852 | reg |= HDMI_PHY_CONF0_GEN2_TXPWRON_MASK; | 861 | reg |= HDMI_PHY_CONF0_GEN2_TXPWRON_MASK; |
853 | writeb(reg, &hdmi->phy_conf0); | 862 | writeb(reg, &hdmi->phy_conf0); |
854 | writeb(HDMI_MC_PHYRSTZ_ASSERT, &hdmi->mc_phyrstz); | 863 | writeb(HDMI_MC_PHYRSTZ_ASSERT, &hdmi->mc_phyrstz); |
855 | } | 864 | } |
856 | 865 | ||
857 | void imx_setup_hdmi(void) | 866 | void imx_setup_hdmi(void) |
858 | { | 867 | { |
859 | struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; | 868 | struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; |
860 | struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR; | 869 | struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR; |
861 | int reg, count; | 870 | int reg, count; |
862 | u8 val; | 871 | u8 val; |
863 | 872 | ||
864 | /* Turn on HDMI PHY clock */ | 873 | /* Turn on HDMI PHY clock */ |
865 | reg = readl(&mxc_ccm->CCGR2); | 874 | reg = readl(&mxc_ccm->CCGR2); |
866 | reg |= MXC_CCM_CCGR2_HDMI_TX_IAHBCLK_MASK| | 875 | reg |= MXC_CCM_CCGR2_HDMI_TX_IAHBCLK_MASK| |
867 | MXC_CCM_CCGR2_HDMI_TX_ISFRCLK_MASK; | 876 | MXC_CCM_CCGR2_HDMI_TX_ISFRCLK_MASK; |
868 | writel(reg, &mxc_ccm->CCGR2); | 877 | writel(reg, &mxc_ccm->CCGR2); |
869 | writeb(HDMI_MC_PHYRSTZ_DEASSERT, &hdmi->mc_phyrstz); | 878 | writeb(HDMI_MC_PHYRSTZ_DEASSERT, &hdmi->mc_phyrstz); |
870 | reg = readl(&mxc_ccm->chsccdr); | 879 | reg = readl(&mxc_ccm->chsccdr); |
871 | reg &= ~(MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK| | 880 | reg &= ~(MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK| |
872 | MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK| | 881 | MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK| |
873 | MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK); | 882 | MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK); |
874 | reg |= (CHSCCDR_PODF_DIVIDE_BY_3 | 883 | reg |= (CHSCCDR_PODF_DIVIDE_BY_3 |
875 | << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET) | 884 | << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET) |
876 | |(CHSCCDR_IPU_PRE_CLK_540M_PFD | 885 | |(CHSCCDR_IPU_PRE_CLK_540M_PFD |
877 | << MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET); | 886 | << MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET); |
878 | writel(reg, &mxc_ccm->chsccdr); | 887 | writel(reg, &mxc_ccm->chsccdr); |
879 | 888 | ||
880 | /* Workaround to clear the overflow condition */ | 889 | /* Workaround to clear the overflow condition */ |
881 | if (readb(&hdmi->ih_fc_stat2) & HDMI_IH_FC_STAT2_OVERFLOW_MASK) { | 890 | if (readb(&hdmi->ih_fc_stat2) & HDMI_IH_FC_STAT2_OVERFLOW_MASK) { |
882 | /* TMDS software reset */ | 891 | /* TMDS software reset */ |
883 | writeb((u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, &hdmi->mc_swrstz); | 892 | writeb((u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, &hdmi->mc_swrstz); |
884 | val = readb(&hdmi->fc_invidconf); | 893 | val = readb(&hdmi->fc_invidconf); |
885 | for (count = 0 ; count < 5 ; count++) | 894 | for (count = 0 ; count < 5 ; count++) |
886 | writeb(val, &hdmi->fc_invidconf); | 895 | writeb(val, &hdmi->fc_invidconf); |
887 | } | 896 | } |
888 | } | 897 | } |
889 | #endif | 898 | #endif |
890 | 899 | ||
891 | #ifndef CONFIG_SYS_L2CACHE_OFF | 900 | #ifndef CONFIG_SYS_L2CACHE_OFF |
892 | #define IOMUXC_GPR11_L2CACHE_AS_OCRAM 0x00000002 | 901 | #define IOMUXC_GPR11_L2CACHE_AS_OCRAM 0x00000002 |
893 | void v7_outer_cache_enable(void) | 902 | void v7_outer_cache_enable(void) |
894 | { | 903 | { |
895 | struct pl310_regs *const pl310 = (struct pl310_regs *)L2_PL310_BASE; | 904 | struct pl310_regs *const pl310 = (struct pl310_regs *)L2_PL310_BASE; |
896 | unsigned int val; | 905 | unsigned int val; |
897 | 906 | ||
898 | #if defined CONFIG_MX6SL | 907 | #if defined CONFIG_MX6SL |
899 | struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; | 908 | struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; |
900 | val = readl(&iomux->gpr[11]); | 909 | val = readl(&iomux->gpr[11]); |
901 | if (val & IOMUXC_GPR11_L2CACHE_AS_OCRAM) { | 910 | if (val & IOMUXC_GPR11_L2CACHE_AS_OCRAM) { |
902 | /* L2 cache configured as OCRAM, reset it */ | 911 | /* L2 cache configured as OCRAM, reset it */ |
903 | val &= ~IOMUXC_GPR11_L2CACHE_AS_OCRAM; | 912 | val &= ~IOMUXC_GPR11_L2CACHE_AS_OCRAM; |
904 | writel(val, &iomux->gpr[11]); | 913 | writel(val, &iomux->gpr[11]); |
905 | } | 914 | } |
906 | #endif | 915 | #endif |
907 | 916 | ||
908 | /* Must disable the L2 before changing the latency parameters */ | 917 | /* Must disable the L2 before changing the latency parameters */ |
909 | clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN); | 918 | clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN); |
910 | 919 | ||
911 | writel(0x132, &pl310->pl310_tag_latency_ctrl); | 920 | writel(0x132, &pl310->pl310_tag_latency_ctrl); |
912 | writel(0x132, &pl310->pl310_data_latency_ctrl); | 921 | writel(0x132, &pl310->pl310_data_latency_ctrl); |
913 | 922 | ||
914 | val = readl(&pl310->pl310_prefetch_ctrl); | 923 | val = readl(&pl310->pl310_prefetch_ctrl); |
915 | 924 | ||
916 | /* Turn on the L2 I/D prefetch */ | 925 | /* Turn on the L2 I/D prefetch */ |
917 | val |= 0x30000000; | 926 | val |= 0x30000000; |
918 | 927 | ||
919 | /* | 928 | /* |
920 | * The L2 cache controller(PL310) version on the i.MX6D/Q is r3p1-50rel0 | 929 | * The L2 cache controller(PL310) version on the i.MX6D/Q is r3p1-50rel0 |
921 | * The L2 cache controller(PL310) version on the i.MX6DL/SOLO/SL is r3p2 | 930 | * The L2 cache controller(PL310) version on the i.MX6DL/SOLO/SL is r3p2 |
922 | * But according to ARM PL310 errata: 752271 | 931 | * But according to ARM PL310 errata: 752271 |
923 | * ID: 752271: Double linefill feature can cause data corruption | 932 | * ID: 752271: Double linefill feature can cause data corruption |
924 | * Fault Status: Present in: r3p0, r3p1, r3p1-50rel0. Fixed in r3p2 | 933 | * Fault Status: Present in: r3p0, r3p1, r3p1-50rel0. Fixed in r3p2 |
925 | * Workaround: The only workaround to this erratum is to disable the | 934 | * Workaround: The only workaround to this erratum is to disable the |
926 | * double linefill feature. This is the default behavior. | 935 | * double linefill feature. This is the default behavior. |
927 | */ | 936 | */ |
928 | 937 | ||
929 | #ifndef CONFIG_MX6Q | 938 | #ifndef CONFIG_MX6Q |
930 | val |= 0x40800000; | 939 | val |= 0x40800000; |
931 | #endif | 940 | #endif |
932 | writel(val, &pl310->pl310_prefetch_ctrl); | 941 | writel(val, &pl310->pl310_prefetch_ctrl); |
933 | 942 | ||
934 | val = readl(&pl310->pl310_power_ctrl); | 943 | val = readl(&pl310->pl310_power_ctrl); |
935 | val |= L2X0_DYNAMIC_CLK_GATING_EN; | 944 | val |= L2X0_DYNAMIC_CLK_GATING_EN; |
936 | val |= L2X0_STNDBY_MODE_EN; | 945 | val |= L2X0_STNDBY_MODE_EN; |
937 | writel(val, &pl310->pl310_power_ctrl); | 946 | writel(val, &pl310->pl310_power_ctrl); |
938 | 947 | ||
939 | setbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN); | 948 | setbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN); |
940 | } | 949 | } |
941 | 950 | ||
942 | void v7_outer_cache_disable(void) | 951 | void v7_outer_cache_disable(void) |
943 | { | 952 | { |
944 | struct pl310_regs *const pl310 = (struct pl310_regs *)L2_PL310_BASE; | 953 | struct pl310_regs *const pl310 = (struct pl310_regs *)L2_PL310_BASE; |
945 | 954 | ||
946 | clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN); | 955 | clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN); |
947 | } | 956 | } |
948 | #endif /* !CONFIG_SYS_L2CACHE_OFF */ | 957 | #endif /* !CONFIG_SYS_L2CACHE_OFF */ |
949 | 958 | ||
950 | #ifdef CONFIG_FASTBOOT | 959 | #ifdef CONFIG_FASTBOOT |
951 | 960 | ||
952 | #ifdef CONFIG_ANDROID_RECOVERY | 961 | #ifdef CONFIG_ANDROID_RECOVERY |
953 | #define ANDROID_RECOVERY_BOOT (1 << 7) | 962 | #define ANDROID_RECOVERY_BOOT (1 << 7) |
954 | /* check if the recovery bit is set by kernel, it can be set by kernel | 963 | /* check if the recovery bit is set by kernel, it can be set by kernel |
955 | * issue a command '# reboot recovery' */ | 964 | * issue a command '# reboot recovery' */ |
956 | int recovery_check_and_clean_flag(void) | 965 | int recovery_check_and_clean_flag(void) |
957 | { | 966 | { |
958 | int flag_set = 0; | 967 | int flag_set = 0; |
959 | u32 reg; | 968 | u32 reg; |
960 | reg = readl(SNVS_BASE_ADDR + SNVS_LPGPR); | 969 | reg = readl(SNVS_BASE_ADDR + SNVS_LPGPR); |
961 | 970 | ||
962 | flag_set = !!(reg & ANDROID_RECOVERY_BOOT); | 971 | flag_set = !!(reg & ANDROID_RECOVERY_BOOT); |
963 | printf("check_and_clean: reg %x, flag_set %d\n", reg, flag_set); | 972 | printf("check_and_clean: reg %x, flag_set %d\n", reg, flag_set); |
964 | /* clean it in case looping infinite here.... */ | 973 | /* clean it in case looping infinite here.... */ |
965 | if (flag_set) { | 974 | if (flag_set) { |
966 | reg &= ~ANDROID_RECOVERY_BOOT; | 975 | reg &= ~ANDROID_RECOVERY_BOOT; |
967 | writel(reg, SNVS_BASE_ADDR + SNVS_LPGPR); | 976 | writel(reg, SNVS_BASE_ADDR + SNVS_LPGPR); |
968 | } | 977 | } |
969 | 978 | ||
970 | return flag_set; | 979 | return flag_set; |
971 | } | 980 | } |
972 | #endif /*CONFIG_ANDROID_RECOVERY*/ | 981 | #endif /*CONFIG_ANDROID_RECOVERY*/ |
973 | 982 | ||
974 | #define ANDROID_FASTBOOT_BOOT (1 << 8) | 983 | #define ANDROID_FASTBOOT_BOOT (1 << 8) |
975 | /* check if the recovery bit is set by kernel, it can be set by kernel | 984 | /* check if the recovery bit is set by kernel, it can be set by kernel |
976 | * issue a command '# reboot fastboot' */ | 985 | * issue a command '# reboot fastboot' */ |
977 | int fastboot_check_and_clean_flag(void) | 986 | int fastboot_check_and_clean_flag(void) |
978 | { | 987 | { |
979 | int flag_set = 0; | 988 | int flag_set = 0; |
980 | u32 reg; | 989 | u32 reg; |
981 | 990 | ||
982 | reg = readl(SNVS_BASE_ADDR + SNVS_LPGPR); | 991 | reg = readl(SNVS_BASE_ADDR + SNVS_LPGPR); |
983 | 992 | ||
984 | flag_set = !!(reg & ANDROID_FASTBOOT_BOOT); | 993 | flag_set = !!(reg & ANDROID_FASTBOOT_BOOT); |
985 | 994 | ||
986 | /* clean it in case looping infinite here.... */ | 995 | /* clean it in case looping infinite here.... */ |
987 | if (flag_set) { | 996 | if (flag_set) { |
988 | reg &= ~ANDROID_FASTBOOT_BOOT; | 997 | reg &= ~ANDROID_FASTBOOT_BOOT; |
989 | writel(reg, SNVS_BASE_ADDR + SNVS_LPGPR); | 998 | writel(reg, SNVS_BASE_ADDR + SNVS_LPGPR); |
990 | } | 999 | } |
991 | 1000 | ||
992 | return flag_set; | 1001 | return flag_set; |
993 | } | 1002 | } |
994 | #endif /*CONFIG_FASTBOOT*/ | 1003 | #endif /*CONFIG_FASTBOOT*/ |
995 | 1004 | ||
996 | #ifdef CONFIG_IMX_UDC | 1005 | #ifdef CONFIG_IMX_UDC |
997 | void set_usboh3_clk(void) | 1006 | void set_usboh3_clk(void) |
998 | { | 1007 | { |
999 | udc_pins_setting(); | 1008 | udc_pins_setting(); |
1000 | } | 1009 | } |
1001 | 1010 | ||
1002 | void set_usb_phy1_clk(void) | 1011 | void set_usb_phy1_clk(void) |
1003 | { | 1012 | { |
1004 | /* make sure pll3 is enable here */ | 1013 | /* make sure pll3 is enable here */ |
1005 | writel((BM_ANADIG_USB1_CHRG_DETECT_EN_B | | 1014 | writel((BM_ANADIG_USB1_CHRG_DETECT_EN_B | |
1006 | BM_ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B), | 1015 | BM_ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B), |
1007 | ANATOP_BASE_ADDR + HW_ANADIG_USB1_CHRG_DETECT_SET); | 1016 | ANATOP_BASE_ADDR + HW_ANADIG_USB1_CHRG_DETECT_SET); |
1008 | 1017 | ||
1009 | writel(BM_ANADIG_USB1_PLL_480_CTRL_EN_USB_CLKS, | 1018 | writel(BM_ANADIG_USB1_PLL_480_CTRL_EN_USB_CLKS, |
1010 | ANATOP_BASE_ADDR + HW_ANADIG_USB1_PLL_480_CTRL_SET); | 1019 | ANATOP_BASE_ADDR + HW_ANADIG_USB1_PLL_480_CTRL_SET); |
1011 | } | 1020 | } |
1012 | void enable_usb_phy1_clk(unsigned char enable) | 1021 | void enable_usb_phy1_clk(unsigned char enable) |
1013 | { | 1022 | { |
1014 | if (enable) | 1023 | if (enable) |
1015 | writel(BM_USBPHY_CTRL_CLKGATE, | 1024 | writel(BM_USBPHY_CTRL_CLKGATE, |
1016 | USB_PHY0_BASE_ADDR + HW_USBPHY_CTRL_CLR); | 1025 | USB_PHY0_BASE_ADDR + HW_USBPHY_CTRL_CLR); |
1017 | else | 1026 | else |
1018 | writel(BM_USBPHY_CTRL_CLKGATE, | 1027 | writel(BM_USBPHY_CTRL_CLKGATE, |
1019 | USB_PHY0_BASE_ADDR + HW_USBPHY_CTRL_SET); | 1028 | USB_PHY0_BASE_ADDR + HW_USBPHY_CTRL_SET); |
1020 | } | 1029 | } |
1021 | 1030 | ||
1022 | void reset_usb_phy1(void) | 1031 | void reset_usb_phy1(void) |
1023 | { | 1032 | { |
1024 | /* Reset USBPHY module */ | 1033 | /* Reset USBPHY module */ |
1025 | u32 temp; | 1034 | u32 temp; |
1026 | temp = readl(USB_PHY0_BASE_ADDR + HW_USBPHY_CTRL); | 1035 | temp = readl(USB_PHY0_BASE_ADDR + HW_USBPHY_CTRL); |
1027 | temp |= BM_USBPHY_CTRL_SFTRST; | 1036 | temp |= BM_USBPHY_CTRL_SFTRST; |
1028 | writel(temp, USB_PHY0_BASE_ADDR + HW_USBPHY_CTRL); | 1037 | writel(temp, USB_PHY0_BASE_ADDR + HW_USBPHY_CTRL); |
1029 | udelay(10); | 1038 | udelay(10); |
1030 | 1039 | ||
1031 | /* Remove CLKGATE and SFTRST */ | 1040 | /* Remove CLKGATE and SFTRST */ |
1032 | temp = readl(USB_PHY0_BASE_ADDR + HW_USBPHY_CTRL); | 1041 | temp = readl(USB_PHY0_BASE_ADDR + HW_USBPHY_CTRL); |
1033 | temp &= ~(BM_USBPHY_CTRL_CLKGATE | BM_USBPHY_CTRL_SFTRST); | 1042 | temp &= ~(BM_USBPHY_CTRL_CLKGATE | BM_USBPHY_CTRL_SFTRST); |
1034 | writel(temp, USB_PHY0_BASE_ADDR + HW_USBPHY_CTRL); | 1043 | writel(temp, USB_PHY0_BASE_ADDR + HW_USBPHY_CTRL); |
1035 | udelay(10); | 1044 | udelay(10); |
1036 | 1045 | ||
1037 | /* Power up the PHY */ | 1046 | /* Power up the PHY */ |
1038 | writel(0, USB_PHY0_BASE_ADDR + HW_USBPHY_PWD); | 1047 | writel(0, USB_PHY0_BASE_ADDR + HW_USBPHY_PWD); |
1039 | } | 1048 | } |
1040 | #endif | 1049 | #endif |