Blame view

arch/arm/cpu/armv7/mx6/soc.c 26.4 KB
23608e23f   Jason Liu   i.mx: add the ini...
1
2
3
4
  /*
   * (C) Copyright 2007
   * Sascha Hauer, Pengutronix
   *
8dcbd43b9   Peng Fan   MLK-10774-2 HDMI:...
5
   * (C) Copyright 2009-2016 Freescale Semiconductor, Inc.
23608e23f   Jason Liu   i.mx: add the ini...
6
   *
1a4596601   Wolfgang Denk   Add GPL-2.0+ SPDX...
7
   * SPDX-License-Identifier:	GPL-2.0+
23608e23f   Jason Liu   i.mx: add the ini...
8
9
10
11
12
13
14
15
   */
  
  #include <common.h>
  #include <asm/errno.h>
  #include <asm/io.h>
  #include <asm/arch/imx-regs.h>
  #include <asm/arch/clock.h>
  #include <asm/arch/sys_proto.h>
124a06d7f   Troy Kisky   imx-common/cmd_bm...
16
  #include <asm/imx-common/boot_mode.h>
ae695b18d   Stefan Roese   mtd: mxs_nand: Ad...
17
  #include <asm/imx-common/dma.h>
6b50bfe56   Adrian Alonso   arm: imx: add sec...
18
  #include <asm/imx-common/hab.h>
76c91e668   Fabio Estevam   mx6: Disable Powe...
19
  #include <stdbool.h>
5ea7f0e32   Pardeep Kumar Singla   mx6: Factor out c...
20
21
  #include <asm/arch/mxc_hdmi.h>
  #include <asm/arch/crm_regs.h>
7a2641684   Ye.Li   mx6: thermal: Che...
22
23
  #include <dm.h>
  #include <imx_thermal.h>
1a43dc11a   Soeren Moch   imx: mx6: Impleme...
24
  #include <mmc.h>
23d63ff18   Ye Li   MLK-12527-2 andro...
25
26
27
  #if defined(CONFIG_FSL_FASTBOOT) && defined(CONFIG_ANDROID_RECOVERY)
  #include <recovery.h>
  #endif
23608e23f   Jason Liu   i.mx: add the ini...
28

3d622b78b   Fabio Estevam   mx6: soc: Introdu...
29
30
31
32
33
  enum ldo_reg {
  	LDO_ARM,
  	LDO_SOC,
  	LDO_PU,
  };
20332a066   Troy Kisky   mx6: soc: update ...
34
35
36
37
38
39
40
  struct scu_regs {
  	u32	ctrl;
  	u32	config;
  	u32	status;
  	u32	invalidate;
  	u32	fpga_rev;
  };
1368f9934   Adrian Alonso   thermal: imx_ther...
41
  #if defined(CONFIG_IMX_THERMAL)
7a2641684   Ye.Li   mx6: thermal: Che...
42
43
44
45
46
47
48
49
50
51
52
  static const struct imx_thermal_plat imx6_thermal_plat = {
  	.regs = (void *)ANATOP_BASE_ADDR,
  	.fuse_bank = 1,
  	.fuse_word = 6,
  };
  
  U_BOOT_DEVICE(imx6_thermal) = {
  	.name = "imx_thermal",
  	.platdata = &imx6_thermal_plat,
  };
  #endif
6b50bfe56   Adrian Alonso   arm: imx: add sec...
53
54
55
56
57
58
  #if defined(CONFIG_SECURE_BOOT)
  struct imx_sec_config_fuse_t const imx_sec_config_fuse = {
  	.bank = 0,
  	.word = 6,
  };
  #endif
a76df7090   Gabriel Huau   mx6: add support ...
59
60
61
62
63
  u32 get_nr_cpus(void)
  {
  	struct scu_regs *scu = (struct scu_regs *)SCU_BASE_ADDR;
  	return readl(&scu->config) & 3;
  }
23608e23f   Jason Liu   i.mx: add the ini...
64
65
  u32 get_cpu_rev(void)
  {
a76838674   Fabio Estevam   mx6: Read silicon...
66
  	struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
20332a066   Troy Kisky   mx6: soc: update ...
67
68
  	u32 reg = readl(&anatop->digprog_sololite);
  	u32 type = ((reg >> 16) & 0xff);
d0acd9933   Peng Fan   imx: add cpu type...
69
  	u32 major, cfg = 0;
a76838674   Fabio Estevam   mx6: Read silicon...
70

20332a066   Troy Kisky   mx6: soc: update ...
71
72
  	if (type != MXC_CPU_MX6SL) {
  		reg = readl(&anatop->digprog);
94db66557   Fabio Estevam   mx6: Distinguish ...
73
  		struct scu_regs *scu = (struct scu_regs *)SCU_BASE_ADDR;
d0acd9933   Peng Fan   imx: add cpu type...
74
  		cfg = readl(&scu->config) & 3;
20332a066   Troy Kisky   mx6: soc: update ...
75
76
  		type = ((reg >> 16) & 0xff);
  		if (type == MXC_CPU_MX6DL) {
20332a066   Troy Kisky   mx6: soc: update ...
77
78
79
  			if (!cfg)
  				type = MXC_CPU_MX6SOLO;
  		}
94db66557   Fabio Estevam   mx6: Distinguish ...
80
81
82
83
84
  
  		if (type == MXC_CPU_MX6Q) {
  			if (cfg == 1)
  				type = MXC_CPU_MX6D;
  		}
20332a066   Troy Kisky   mx6: soc: update ...
85
  	}
dfd4861c2   Peng Fan   imx: mx6 correct ...
86
  	major = ((reg >> 8) & 0xff);
d0acd9933   Peng Fan   imx: add cpu type...
87
88
89
90
91
92
93
  	if ((major >= 1) &&
  	    ((type == MXC_CPU_MX6Q) || (type == MXC_CPU_MX6D))) {
  		major--;
  		type = MXC_CPU_MX6QP;
  		if (cfg == 1)
  			type = MXC_CPU_MX6DP;
  	}
20332a066   Troy Kisky   mx6: soc: update ...
94
  	reg &= 0xff;		/* mx6 silicon revision */
dfd4861c2   Peng Fan   imx: mx6 correct ...
95
  	return (type << 12) | (reg + (0x10 * (major + 1)));
23608e23f   Jason Liu   i.mx: add the ini...
96
  }
9b9449c3e   Tim Harvey   imx: mx6: add get...
97
98
99
100
101
102
103
104
105
  /*
   * OCOTP_CFG3[17:16] (see Fusemap Description Table offset 0x440)
   * defines a 2-bit SPEED_GRADING
   */
  #define OCOTP_CFG3_SPEED_SHIFT	16
  #define OCOTP_CFG3_SPEED_800MHZ	0
  #define OCOTP_CFG3_SPEED_850MHZ	1
  #define OCOTP_CFG3_SPEED_1GHZ	2
  #define OCOTP_CFG3_SPEED_1P2GHZ	3
2ad1304ae   Peng Fan   MLK-12711 imx: co...
106
107
108
109
110
  /*
   * For i.MX6UL
   */
  #define OCOTP_CFG3_SPEED_528MHZ 1
  #define OCOTP_CFG3_SPEED_696MHZ 2
9b9449c3e   Tim Harvey   imx: mx6: add get...
111
112
113
114
115
116
117
118
119
120
121
  u32 get_cpu_speed_grade_hz(void)
  {
  	struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
  	struct fuse_bank *bank = &ocotp->bank[0];
  	struct fuse_bank0_regs *fuse =
  		(struct fuse_bank0_regs *)bank->fuse_regs;
  	uint32_t val;
  
  	val = readl(&fuse->cfg3);
  	val >>= OCOTP_CFG3_SPEED_SHIFT;
  	val &= 0x3;
05922b0ab   Peng Fan   MLK-12767 imx6ull...
122
  	if (is_cpu_type(MXC_CPU_MX6UL) || is_cpu_type(MXC_CPU_MX6ULL)) {
2ad1304ae   Peng Fan   MLK-12711 imx: co...
123
124
125
126
127
128
129
  		if (val == OCOTP_CFG3_SPEED_528MHZ)
  			return 528000000;
  		else if (val == OCOTP_CFG3_SPEED_696MHZ)
  			return 69600000;
  		else
  			return 0;
  	}
9b9449c3e   Tim Harvey   imx: mx6: add get...
130
131
132
  	switch (val) {
  	/* Valid for IMX6DQ */
  	case OCOTP_CFG3_SPEED_1P2GHZ:
39ea1ae1f   Ye Li   MLK-12737 mx6qp/m...
133
134
  		if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D) ||
  			is_cpu_type(MXC_CPU_MX6QP) || is_cpu_type(MXC_CPU_MX6DP))
9b9449c3e   Tim Harvey   imx: mx6: add get...
135
136
137
138
139
140
  			return 1200000000;
  	/* Valid for IMX6SX/IMX6SDL/IMX6DQ */
  	case OCOTP_CFG3_SPEED_1GHZ:
  		return 996000000;
  	/* Valid for IMX6DQ */
  	case OCOTP_CFG3_SPEED_850MHZ:
39ea1ae1f   Ye Li   MLK-12737 mx6qp/m...
141
142
  		if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D) ||
  			is_cpu_type(MXC_CPU_MX6QP) || is_cpu_type(MXC_CPU_MX6DP))
9b9449c3e   Tim Harvey   imx: mx6: add get...
143
144
145
146
147
148
149
  			return 852000000;
  	/* Valid for IMX6SX/IMX6SDL/IMX6DQ */
  	case OCOTP_CFG3_SPEED_800MHZ:
  		return 792000000;
  	}
  	return 0;
  }
f0e8e8944   Tim Harvey   imx: mx6: add get...
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
  /*
   * OCOTP_MEM0[7:6] (see Fusemap Description Table offset 0x480)
   * defines a 2-bit Temperature Grade
   *
   * return temperature grade and min/max temperature in celcius
   */
  #define OCOTP_MEM0_TEMP_SHIFT          6
  
  u32 get_cpu_temp_grade(int *minc, int *maxc)
  {
  	struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
  	struct fuse_bank *bank = &ocotp->bank[1];
  	struct fuse_bank1_regs *fuse =
  		(struct fuse_bank1_regs *)bank->fuse_regs;
  	uint32_t val;
  
  	val = readl(&fuse->mem0);
  	val >>= OCOTP_MEM0_TEMP_SHIFT;
  	val &= 0x3;
  
  	if (minc && maxc) {
  		if (val == TEMP_AUTOMOTIVE) {
  			*minc = -40;
  			*maxc = 125;
  		} else if (val == TEMP_INDUSTRIAL) {
  			*minc = -40;
  			*maxc = 105;
  		} else if (val == TEMP_EXTCOMMERCIAL) {
  			*minc = -20;
  			*maxc = 105;
  		} else {
  			*minc = 0;
  			*maxc = 95;
  		}
  	}
  	return val;
  }
38e700772   Fabio Estevam   mx6: Fix get_boar...
187
188
189
190
191
192
193
  #ifdef CONFIG_REVISION_TAG
  u32 __weak get_board_rev(void)
  {
  	u32 cpurev = get_cpu_rev();
  	u32 type = ((cpurev >> 12) & 0xff);
  	if (type == MXC_CPU_MX6SOLO)
  		cpurev = (MXC_CPU_MX6DL) << 12 | (cpurev & 0xFFF);
94db66557   Fabio Estevam   mx6: Distinguish ...
194
195
  	if (type == MXC_CPU_MX6D)
  		cpurev = (MXC_CPU_MX6Q) << 12 | (cpurev & 0xFFF);
39ea1ae1f   Ye Li   MLK-12737 mx6qp/m...
196
197
  	if (type == MXC_CPU_MX6QP || type == MXC_CPU_MX6DP)
  		cpurev = (MXC_CPU_MX6Q) << 12 | ((cpurev + 0x10) & 0xFFF);
38e700772   Fabio Estevam   mx6: Fix get_boar...
198
199
200
  	return cpurev;
  }
  #endif
e113fd197   Fabio Estevam   mx6: soc: Clear t...
201
202
203
204
205
206
207
208
209
210
211
212
213
  static void clear_ldo_ramp(void)
  {
  	struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
  	int reg;
  
  	/* ROM may modify LDO ramp up time according to fuse setting, so in
  	 * order to be in the safe side we neeed to reset these settings to
  	 * match the reset value: 0'b00
  	 */
  	reg = readl(&anatop->ana_misc2);
  	reg &= ~(0x3f << 24);
  	writel(reg, &anatop->ana_misc2);
  }
cac833a98   Dirk Behme   i.MX6: Add ANATOP...
214
  /*
157f45da9   Fabio Estevam   mx6: soc: Update ...
215
   * Set the PMU_REG_CORE register
cac833a98   Dirk Behme   i.MX6: Add ANATOP...
216
   *
157f45da9   Fabio Estevam   mx6: soc: Update ...
217
   * Set LDO_SOC/PU/ARM regulators to the specified millivolt level.
cac833a98   Dirk Behme   i.MX6: Add ANATOP...
218
219
220
   * Possible values are from 0.725V to 1.450V in steps of
   * 0.025V (25mV).
   */
3d622b78b   Fabio Estevam   mx6: soc: Introdu...
221
  static int set_ldo_voltage(enum ldo_reg ldo, u32 mv)
cac833a98   Dirk Behme   i.MX6: Add ANATOP...
222
223
  {
  	struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
39f0ac934   Fabio Estevam   mx6: soc: Add the...
224
  	u32 val, step, old, reg = readl(&anatop->reg_core);
3d622b78b   Fabio Estevam   mx6: soc: Introdu...
225
  	u8 shift;
cac833a98   Dirk Behme   i.MX6: Add ANATOP...
226
227
228
229
230
231
232
  
  	if (mv < 725)
  		val = 0x00;	/* Power gated off */
  	else if (mv > 1450)
  		val = 0x1F;	/* Power FET switched full on. No regulation */
  	else
  		val = (mv - 700) / 25;
e113fd197   Fabio Estevam   mx6: soc: Clear t...
233
  	clear_ldo_ramp();
3d622b78b   Fabio Estevam   mx6: soc: Introdu...
234
235
236
237
238
239
240
241
242
243
244
245
246
  	switch (ldo) {
  	case LDO_SOC:
  		shift = 18;
  		break;
  	case LDO_PU:
  		shift = 9;
  		break;
  	case LDO_ARM:
  		shift = 0;
  		break;
  	default:
  		return -EINVAL;
  	}
39f0ac934   Fabio Estevam   mx6: soc: Add the...
247
248
249
250
  	old = (reg & (0x1F << shift)) >> shift;
  	step = abs(val - old);
  	if (step == 0)
  		return 0;
3d622b78b   Fabio Estevam   mx6: soc: Introdu...
251
  	reg = (reg & ~(0x1F << shift)) | (val << shift);
cac833a98   Dirk Behme   i.MX6: Add ANATOP...
252
  	writel(reg, &anatop->reg_core);
3d622b78b   Fabio Estevam   mx6: soc: Introdu...
253

39f0ac934   Fabio Estevam   mx6: soc: Add the...
254
255
256
257
258
  	/*
  	 * The LDO ramp-up is based on 64 clock cycles of 24 MHz = 2.6 us per
  	 * step
  	 */
  	udelay(3 * step);
3d622b78b   Fabio Estevam   mx6: soc: Introdu...
259
  	return 0;
cac833a98   Dirk Behme   i.MX6: Add ANATOP...
260
  }
5c92edc21   Anson Huang   imx6: ensure AHB ...
261
262
263
264
265
266
267
268
269
270
271
  static void set_ahb_rate(u32 val)
  {
  	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
  	u32 reg, div;
  
  	div = get_periph_clk() / val - 1;
  	reg = readl(&mxc_ccm->cbcdr);
  
  	writel((reg & (~MXC_CCM_CBCDR_AHB_PODF_MASK)) |
  		(div << MXC_CCM_CBCDR_AHB_PODF_OFFSET), &mxc_ccm->cbcdr);
  }
16197bb8b   Anson Huang   imx6: make sure M...
272
273
274
  static void clear_mmdc_ch_mask(void)
  {
  	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
e1c2d68b3   Peng Fan   imx: mx6: ccm: Ch...
275
276
  	u32 reg;
  	reg = readl(&mxc_ccm->ccdr);
16197bb8b   Anson Huang   imx6: make sure M...
277
278
  
  	/* Clear MMDC channel mask */
05922b0ab   Peng Fan   MLK-12767 imx6ull...
279
280
  	if (is_cpu_type(MXC_CPU_MX6SX) || is_cpu_type(MXC_CPU_MX6UL) ||
  	    is_cpu_type(MXC_CPU_MX6SL) || is_cpu_type(MXC_CPU_MX6ULL))
b0cf100ab   Ye Li   MLK-12488 mx6sl/u...
281
282
283
  		reg &= ~(MXC_CCM_CCDR_MMDC_CH1_HS_MASK);
  	else
  		reg &= ~(MXC_CCM_CCDR_MMDC_CH1_HS_MASK | MXC_CCM_CCDR_MMDC_CH0_HS_MASK);
e1c2d68b3   Peng Fan   imx: mx6: ccm: Ch...
284
  	writel(reg, &mxc_ccm->ccdr);
16197bb8b   Anson Huang   imx6: make sure M...
285
  }
911fcf93b   Bai Ping   MLK-13124 ARM: im...
286
  #define OCOTP_MEM0_REFTOP_TRIM_SHIFT          8
1f516faa4   Peng Fan   ARM: imx6: disabl...
287
288
289
  static void init_bandgap(void)
  {
  	struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
911fcf93b   Bai Ping   MLK-13124 ARM: im...
290
291
292
293
294
  	struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
  	struct fuse_bank *bank = &ocotp->bank[1];
  	struct fuse_bank1_regs *fuse =
  		(struct fuse_bank1_regs *)bank->fuse_regs;
  	uint32_t val;
1f516faa4   Peng Fan   ARM: imx6: disabl...
295
296
297
298
299
300
301
302
303
304
305
  	/*
  	 * Ensure the bandgap has stabilized.
  	 */
  	while (!(readl(&anatop->ana_misc0) & 0x80))
  		;
  	/*
  	 * For best noise performance of the analog blocks using the
  	 * outputs of the bandgap, the reftop_selfbiasoff bit should
  	 * be set.
  	 */
  	writel(BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_set);
91703d067   Bai Ping   MLK-12894 imx6ull...
306
  	/*
911fcf93b   Bai Ping   MLK-13124 ARM: im...
307
308
309
310
311
312
313
314
315
316
  	 * On i.MX6ULL,we need to set VBGADJ bits according to the
  	 * REFTOP_TRIM[3:0] in fuse table
  	 *	000 - set REFTOP_VBGADJ[2:0] to 3b'110,
  	 *	110 - set REFTOP_VBGADJ[2:0] to 3b'000,
  	 *	001 - set REFTOP_VBGADJ[2:0] to 3b'001,
  	 *	010 - set REFTOP_VBGADJ[2:0] to 3b'010,
  	 *	011 - set REFTOP_VBGADJ[2:0] to 3b'011,
  	 *	100 - set REFTOP_VBGADJ[2:0] to 3b'100,
  	 *	101 - set REFTOP_VBGADJ[2:0] to 3b'101,
  	 *	111 - set REFTOP_VBGADJ[2:0] to 3b'111,
91703d067   Bai Ping   MLK-12894 imx6ull...
317
  	 */
911fcf93b   Bai Ping   MLK-13124 ARM: im...
318
319
320
321
  	if (is_cpu_type(MXC_CPU_MX6ULL)) {
  		val = readl(&fuse->mem0);
  		val >>= OCOTP_MEM0_REFTOP_TRIM_SHIFT;
  		val &= 0x7;
911fcf93b   Bai Ping   MLK-13124 ARM: im...
322
323
324
  		writel(val << BM_ANADIG_ANA_MISC0_REFTOP_VBGADJ_SHIFT,
  		       &anatop->ana_misc0_set);
  	}
1f516faa4   Peng Fan   ARM: imx6: disabl...
325
  }
0f8ec145b   Ye.Li   imx: mx6sl: Set t...
326
327
328
329
330
331
332
333
334
335
336
  #ifdef CONFIG_MX6SL
  static void set_preclk_from_osc(void)
  {
  	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
  	u32 reg;
  
  	reg = readl(&mxc_ccm->cscmr1);
  	reg |= MXC_CCM_CSCMR1_PER_CLK_SEL_MASK;
  	writel(reg, &mxc_ccm->cscmr1);
  }
  #endif
d50b53f13   Ye.Li   ENGR00315894-77 m...
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
  #ifdef CONFIG_MX6SX
  void vadc_power_up(void)
  {
  	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
  	u32 val;
  
  	/* csi0 */
  	val = readl(&iomux->gpr[5]);
  	val &= ~IMX6SX_GPR5_CSI1_MUX_CTRL_MASK,
  	val |= IMX6SX_GPR5_CSI1_MUX_CTRL_CVD;
  	writel(val, &iomux->gpr[5]);
  
  	/* Power on vadc analog
  	 * Power down vadc ext power */
  	val = readl(GPC_BASE_ADDR + 0);
  	val &= ~0x60000;
  	writel(val, GPC_BASE_ADDR + 0);
  
  	/* software reset afe  */
  	val = readl(&iomux->gpr[1]);
  	writel(val | 0x80000, &iomux->gpr[1]);
  
  	udelay(10*1000);
  
  	/* Release reset bit  */
  	writel(val & ~0x80000, &iomux->gpr[1]);
  
  	/* Power on vadc ext power */
  	val = readl(GPC_BASE_ADDR + 0);
  	val |= 0x40000;
  	writel(val, GPC_BASE_ADDR + 0);
  }
  
  void vadc_power_down(void)
  {
2065b417a   Sandor Yu   ENGR00321299 gis:...
372
  	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
d50b53f13   Ye.Li   ENGR00315894-77 m...
373
374
375
376
377
378
379
380
  	u32 val;
  
  	/* Power down vadc ext power
  	 * Power off vadc analog */
  	val = readl(GPC_BASE_ADDR + 0);
  	val &= ~0x40000;
  	val |= 0x20000;
  	writel(val, GPC_BASE_ADDR + 0);
2065b417a   Sandor Yu   ENGR00321299 gis:...
381
382
383
384
385
  
  	/* clean csi0 connect to vadc  */
  	val = readl(&iomux->gpr[5]);
  	val &= ~IMX6SX_GPR5_CSI1_MUX_CTRL_MASK,
  	writel(val, &iomux->gpr[5]);
d50b53f13   Ye.Li   ENGR00315894-77 m...
386
  }
81fd30250   Ye Li   ENGR00325255 pcie...
387
388
389
390
391
392
393
394
395
396
  
  void pcie_power_up(void)
  {
  	set_ldo_voltage(LDO_PU, 1100);	/* Set VDDPU to 1.1V */
  }
  
  void pcie_power_off(void)
  {
  	set_ldo_voltage(LDO_PU, 0);	/* Set VDDPU to 1.1V */
  }
d50b53f13   Ye.Li   ENGR00315894-77 m...
397
  #endif
416dea861   Ye Li   MLK-12533 mx6sx: ...
398
399
400
401
402
403
404
405
406
  static void set_uart_from_osc(void)
  {
  	u32 reg;
  
  	/* set uart clk to OSC */
  	reg = readl(CCM_BASE_ADDR + 0x24);
  	reg |= MXC_CCM_CSCDR1_UART_CLK_SEL;
  	writel(reg, CCM_BASE_ADDR + 0x24);
  }
5c96ea91f   Ye Li   MLK-12534 mx6: sh...
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
  static void imx_set_vddpu_power_down(void)
  {
  	struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
  	u32 val;
  
  	/* need to power down xPU in GPC before turn off PU LDO */
  	val = readl(GPC_BASE_ADDR + 0x260);
  	writel(val | 0x1, GPC_BASE_ADDR + 0x260);
  
  	val = readl(GPC_BASE_ADDR + 0x0);
  	writel(val | 0x1, GPC_BASE_ADDR + 0x0);
  	while (readl(GPC_BASE_ADDR + 0x0) & 0x1)
  		;
  
  	/* disable VDDPU */
  	val = 0x3e00;
  	writel(val, &anatop->reg_core_clr);
  }
  
  static void imx_set_pcie_phy_power_down(void)
  {
  	u32 val;
  
  	if (!is_cpu_type(MXC_CPU_MX6SX)) {
  		val = readl(IOMUXC_BASE_ADDR + 0x4);
  		val |= 0x1 << 18;
  		writel(val, IOMUXC_BASE_ADDR + 0x4);
  	} else {
  		val = readl(IOMUXC_GPR_BASE_ADDR + 0x30);
  		val |= 0x1 << 30;
  		writel(val, IOMUXC_GPR_BASE_ADDR + 0x30);
  	}
  }
23608e23f   Jason Liu   i.mx: add the ini...
440
441
  int arch_cpu_init(void)
  {
05922b0ab   Peng Fan   MLK-12767 imx6ull...
442
443
  	if (!is_cpu_type(MXC_CPU_MX6SL) && !is_cpu_type(MXC_CPU_MX6SX)
  	    && !is_cpu_type(MXC_CPU_MX6UL) && !is_cpu_type(MXC_CPU_MX6ULL)) {
48a4606ef   Richard Zhu   ENGR00319965 pcie...
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
  		/*
  		 * imx6sl doesn't have pcie at all.
  		 * this bit is not used by imx6sx anymore
  		 */
  		u32 val;
  
  		/*
  		 * There are about 0.02% percentage, random pcie link down
  		 * when warm-reset is used.
  		 * clear the ref_ssp_en bit16 of gpr1 to workaround it.
  		 * then warm-reset imx6q/dl/solo again.
  		 */
  		val = readl(IOMUXC_BASE_ADDR + 0x4);
  		if (val & (0x1 << 16)) {
  			val &= ~(0x1 << 16);
  			writel(val, IOMUXC_BASE_ADDR + 0x4);
  			reset_cpu(0);
  		}
7b4aabedd   Richard Zhu   ENGR00319415 pcie...
462
  	}
7b4aabedd   Richard Zhu   ENGR00319415 pcie...
463

23608e23f   Jason Liu   i.mx: add the ini...
464
  	init_aips();
16197bb8b   Anson Huang   imx6: make sure M...
465
466
  	/* Need to clear MMDC_CHx_MASK to make warm reset work. */
  	clear_mmdc_ch_mask();
5c92edc21   Anson Huang   imx6: ensure AHB ...
467
  	/*
1f516faa4   Peng Fan   ARM: imx6: disabl...
468
469
470
471
472
  	 * Disable self-bias circuit in the analog bandap.
  	 * The self-bias circuit is used by the bandgap during startup.
  	 * This bit should be set after the bandgap has initialized.
  	 */
  	init_bandgap();
7b5267e26   Peng Fan   MLK-12616-7 mx6ul...
473
  	if (!is_cpu_type(MXC_CPU_MX6UL) && !is_cpu_type(MXC_CPU_MX6ULL)) {
49c9146ec   Peng Fan   MLK-12416-7 imx: ...
474
475
476
477
478
479
480
481
  		/*
  		 * When low freq boot is enabled, ROM will not set AHB
  		 * freq, so we need to ensure AHB freq is 132MHz in such
  		 * scenario.
  		 */
  		if (mxc_get_clock(MXC_ARM_CLK) == 396000000)
  			set_ahb_rate(132000000);
  	}
5c92edc21   Anson Huang   imx6: ensure AHB ...
482

9b9d46147   Anson Huang   MLK-12576 imx: im...
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
  	if (is_cpu_type(MXC_CPU_MX6UL)) {
  		if (is_soc_rev(CHIP_REV_1_0)) {
  			/*
  			 * According to the design team's requirement on i.MX6UL,
  			 * the PMIC_STBY_REQ PAD should be configured as open
  			 * drain 100K (0x0000b8a0).
  			 */
  			writel(0x0000b8a0, IOMUXC_BASE_ADDR + 0x29c);
  		} else {
  			/*
  			 * From TO1.1, SNVS adds internal pull up control for POR_B,
  			 * the register filed is GPBIT[1:0], after system boot up,
  			 * it can be set to 2b'01 to disable internal pull up.
  			 * It can save about 30uA power in SNVS mode.
  			 */
ebd4b8a0c   Peng Fan   MLK-12591: Define...
498
499
  			writel((readl(MX6UL_SNVS_LP_BASE_ADDR + 0x10) & (~0x1400)) | 0x400,
  				MX6UL_SNVS_LP_BASE_ADDR + 0x10);
9b9d46147   Anson Huang   MLK-12576 imx: im...
500
  		}
95302eefc   Ye Li   MLK-12532 mx6ul: ...
501
  	}
c5f3ebc2b   Anson Huang   MLK-12658 imx: ad...
502
503
504
505
506
507
508
509
510
511
512
513
514
  	if (is_cpu_type(MXC_CPU_MX6ULL)) {
  		/*
  		 * GPBIT[1:0] is suggested to set to 2'b11:
  		 * 2'b00 : always PUP100K
  		 * 2'b01 : PUP100K when PMIC_ON_REQ or SOC_NOT_FAIL
  		 * 2'b10 : always disable PUP100K
  		 * 2'b11 : PDN100K when SOC_FAIL, PUP100K when SOC_NOT_FAIL
  		 * register offset is different from i.MX6UL, since
  		 * i.MX6UL is fixed by ECO.
  		 */
  		writel(readl(MX6UL_SNVS_LP_BASE_ADDR) |
  			0x3, MX6UL_SNVS_LP_BASE_ADDR);
  	}
0f8ec145b   Ye.Li   imx: mx6sl: Set t...
515
516
517
518
  		/* Set perclk to source from OSC 24MHz */
  #if defined(CONFIG_MX6SL)
  	set_preclk_from_osc();
  #endif
416dea861   Ye Li   MLK-12533 mx6sx: ...
519
520
  	if (is_cpu_type(MXC_CPU_MX6SX))
  		set_uart_from_osc();
76c91e668   Fabio Estevam   mx6: Disable Powe...
521
  	imx_set_wdog_powerdown(false); /* Disable PDE bit of WMCR register */
ae695b18d   Stefan Roese   mtd: mxs_nand: Ad...
522

05922b0ab   Peng Fan   MLK-12767 imx6ull...
523
524
  	if (!is_cpu_type(MXC_CPU_MX6SL) && !is_cpu_type(MXC_CPU_MX6UL) &&
  	    !is_cpu_type(MXC_CPU_MX6ULL))
5c96ea91f   Ye Li   MLK-12534 mx6: sh...
525
  		imx_set_pcie_phy_power_down();
05922b0ab   Peng Fan   MLK-12767 imx6ull...
526
527
  	if (!is_mx6dqp() && !is_cpu_type(MXC_CPU_MX6UL) &&
  	    !is_cpu_type(MXC_CPU_MX6ULL))
5c96ea91f   Ye Li   MLK-12534 mx6: sh...
528
  		imx_set_vddpu_power_down();
ae695b18d   Stefan Roese   mtd: mxs_nand: Ad...
529
530
531
532
  #ifdef CONFIG_APBH_DMA
  	/* Start APBH DMA */
  	mxs_dma_init();
  #endif
9d16c52f6   Dirk Behme   mx6: soc: Switch ...
533
  	init_src();
5dcf073b8   Ye.Li   MLK-11064 imx: mx...
534
535
  	if (is_mx6dqp())
  		writel(0x80000201, 0xbb0608);
23608e23f   Jason Liu   i.mx: add the ini...
536
537
  	return 0;
  }
23608e23f   Jason Liu   i.mx: add the ini...
538

216d286c7   Peng Fan   imx: mx6: impleme...
539
540
541
542
543
  #ifdef CONFIG_ENV_IS_IN_MMC
  __weak int board_mmc_get_env_dev(int devno)
  {
  	return CONFIG_SYS_MMC_ENV_DEV;
  }
1a43dc11a   Soeren Moch   imx: mx6: Impleme...
544
  static int mmc_get_boot_dev(void)
216d286c7   Peng Fan   imx: mx6: impleme...
545
546
547
548
549
550
551
552
553
554
555
556
557
  {
  	struct src *src_regs = (struct src *)SRC_BASE_ADDR;
  	u32 soc_sbmr = readl(&src_regs->sbmr1);
  	u32 bootsel;
  	int devno;
  
  	/*
  	 * Refer to
  	 * "i.MX 6Dual/6Quad Applications Processor Reference Manual"
  	 * Chapter "8.5.3.1 Expansion Device eFUSE Configuration"
  	 * i.MX6SL/SX/UL has same layout.
  	 */
  	bootsel = (soc_sbmr & 0x000000FF) >> 6;
1a43dc11a   Soeren Moch   imx: mx6: Impleme...
558
  	/* No boot from sd/mmc */
216d286c7   Peng Fan   imx: mx6: impleme...
559
  	if (bootsel != 1)
1a43dc11a   Soeren Moch   imx: mx6: Impleme...
560
  		return -1;
216d286c7   Peng Fan   imx: mx6: impleme...
561
562
563
  
  	/* BOOT_CFG2[3] and BOOT_CFG2[4] */
  	devno = (soc_sbmr & 0x00001800) >> 11;
1a43dc11a   Soeren Moch   imx: mx6: Impleme...
564
565
566
567
568
569
570
571
572
573
  	return devno;
  }
  
  int mmc_get_env_dev(void)
  {
  	int devno = mmc_get_boot_dev();
  
  	/* If not boot from sd/mmc, use default value */
  	if (devno < 0)
  		return CONFIG_SYS_MMC_ENV_DEV;
216d286c7   Peng Fan   imx: mx6: impleme...
574
575
  	return board_mmc_get_env_dev(devno);
  }
1a43dc11a   Soeren Moch   imx: mx6: Impleme...
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
  
  #ifdef CONFIG_SYS_MMC_ENV_PART
  __weak int board_mmc_get_env_part(int devno)
  {
  	return CONFIG_SYS_MMC_ENV_PART;
  }
  
  uint mmc_get_env_part(struct mmc *mmc)
  {
  	int devno = mmc_get_boot_dev();
  
  	/* If not boot from sd/mmc, use default value */
  	if (devno < 0)
  		return CONFIG_SYS_MMC_ENV_PART;
  
  	return board_mmc_get_env_part(devno);
  }
  #endif
216d286c7   Peng Fan   imx: mx6: impleme...
594
  #endif
39f0ac934   Fabio Estevam   mx6: soc: Add the...
595
596
597
598
599
600
  int board_postclk_init(void)
  {
  	set_ldo_voltage(LDO_SOC, 1175);	/* Set VDDSOC to 1.175V */
  
  	return 0;
  }
23d63ff18   Ye Li   MLK-12527-2 andro...
601
602
603
604
605
606
607
608
609
610
611
612
  #ifdef CONFIG_SERIAL_TAG
  void get_board_serial(struct tag_serialnr *serialnr)
  {
  	struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
  	struct fuse_bank *bank = &ocotp->bank[0];
  	struct fuse_bank0_regs *fuse =
  		(struct fuse_bank0_regs *)bank->fuse_regs;
  
  	serialnr->low = fuse->uid_low;
  	serialnr->high = fuse->uid_high;
  }
  #endif
23608e23f   Jason Liu   i.mx: add the ini...
613
  #if defined(CONFIG_FEC_MXC)
be252b654   Fabio Estevam   net: imx: Add mul...
614
  void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
23608e23f   Jason Liu   i.mx: add the ini...
615
  {
8f3ff11c1   Benoît Thébaudeau   imx: Homogenize a...
616
617
  	struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
  	struct fuse_bank *bank = &ocotp->bank[4];
23608e23f   Jason Liu   i.mx: add the ini...
618
619
  	struct fuse_bank4_regs *fuse =
  			(struct fuse_bank4_regs *)bank->fuse_regs;
05922b0ab   Peng Fan   MLK-12767 imx6ull...
620
621
  	if ((is_cpu_type(MXC_CPU_MX6SX) || is_cpu_type(MXC_CPU_MX6UL) ||
  	    is_cpu_type(MXC_CPU_MX6ULL)) && dev_id == 1) {
d4d1dd674   Ye Li   mx6: soc: Add ENE...
622
623
624
625
626
627
628
629
630
  		u32 value = readl(&fuse->mac_addr2);
  		mac[0] = value >> 24 ;
  		mac[1] = value >> 16 ;
  		mac[2] = value >> 8 ;
  		mac[3] = value ;
  
  		value = readl(&fuse->mac_addr1);
  		mac[4] = value >> 24 ;
  		mac[5] = value >> 16 ;
5b87d04db   Ye Li   MLK-12495 mx6: Ad...
631

d4d1dd674   Ye Li   mx6: soc: Add ENE...
632
633
634
635
636
637
638
639
640
641
642
  	} else {
  		u32 value = readl(&fuse->mac_addr1);
  		mac[0] = (value >> 8);
  		mac[1] = value ;
  
  		value = readl(&fuse->mac_addr0);
  		mac[2] = value >> 24 ;
  		mac[3] = value >> 16 ;
  		mac[4] = value >> 8 ;
  		mac[5] = value ;
  	}
23608e23f   Jason Liu   i.mx: add the ini...
643
644
645
  
  }
  #endif
124a06d7f   Troy Kisky   imx-common/cmd_bm...
646

124a06d7f   Troy Kisky   imx-common/cmd_bm...
647
648
649
  /*
   * cfg_val will be used for
   * Boot_cfg4[7:0]:Boot_cfg3[7:0]:Boot_cfg2[7:0]:Boot_cfg1[7:0]
f2863ff3f   Nikita Kiryanov   arm: imx: make bm...
650
651
   * After reset, if GPR10[28] is 1, ROM will use GPR9[25:0]
   * instead of SBMR1 to determine the boot device.
124a06d7f   Troy Kisky   imx-common/cmd_bm...
652
653
654
655
656
657
   */
  const struct boot_mode soc_boot_modes[] = {
  	{"normal",	MAKE_CFGVAL(0x00, 0x00, 0x00, 0x00)},
  	/* reserved value should start rom usb */
  	{"usb",		MAKE_CFGVAL(0x01, 0x00, 0x00, 0x00)},
  	{"sata",	MAKE_CFGVAL(0x20, 0x00, 0x00, 0x00)},
2d59e3ecd   Nikolay Dimitrov   mx6: Fix ECSPI ty...
658
659
660
661
  	{"ecspi1:0",	MAKE_CFGVAL(0x30, 0x00, 0x00, 0x08)},
  	{"ecspi1:1",	MAKE_CFGVAL(0x30, 0x00, 0x00, 0x18)},
  	{"ecspi1:2",	MAKE_CFGVAL(0x30, 0x00, 0x00, 0x28)},
  	{"ecspi1:3",	MAKE_CFGVAL(0x30, 0x00, 0x00, 0x38)},
124a06d7f   Troy Kisky   imx-common/cmd_bm...
662
663
664
665
666
667
668
  	/* 4 bit bus width */
  	{"esdhc1",	MAKE_CFGVAL(0x40, 0x20, 0x00, 0x00)},
  	{"esdhc2",	MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)},
  	{"esdhc3",	MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)},
  	{"esdhc4",	MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00)},
  	{NULL,		0},
  };
8f3937761   Stephen Warren   ARM: mx6: use com...
669

23d63ff18   Ye Li   MLK-12527-2 andro...
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
  enum boot_device get_boot_device(void)
  {
  	enum boot_device boot_dev = UNKNOWN_BOOT;
  	uint soc_sbmr = readl(SRC_BASE_ADDR + 0x4);
  	uint bt_mem_ctl = (soc_sbmr & 0x000000FF) >> 4 ;
  	uint bt_mem_type = (soc_sbmr & 0x00000008) >> 3;
  	uint bt_dev_port = (soc_sbmr & 0x00001800) >> 11;
  
  	switch (bt_mem_ctl) {
  	case 0x0:
  		if (bt_mem_type)
  			boot_dev = ONE_NAND_BOOT;
  		else
  			boot_dev = WEIM_NOR_BOOT;
  		break;
  	case 0x2:
  			boot_dev = SATA_BOOT;
  		break;
  	case 0x3:
  		if (bt_mem_type)
  			boot_dev = I2C_BOOT;
  		else
  			boot_dev = SPI_NOR_BOOT;
  		break;
  	case 0x4:
  	case 0x5:
  		boot_dev = bt_dev_port + SD1_BOOT;
  		break;
  	case 0x6:
  	case 0x7:
  		boot_dev = bt_dev_port + MMC1_BOOT;
  		break;
  	case 0x8 ... 0xf:
  		boot_dev = NAND_BOOT;
  		break;
  	default:
  		boot_dev = UNKNOWN_BOOT;
  		break;
  	}
  
      return boot_dev;
  }
5b87d04db   Ye Li   MLK-12495 mx6: Ad...
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
  void set_wdog_reset(struct wdog_regs *wdog)
  {
  	u32 reg = readw(&wdog->wcr);
  	/*
  	 * use WDOG_B mode to reset external pmic because it's risky for the
  	 * following watchdog reboot in case of cpu freq at lowest 400Mhz with
  	 * ldo-bypass mode. Because boot frequency maybe higher 800Mhz i.e. So
  	 * in ldo-bypass mode watchdog reset will only triger POR reset, not
  	 * WDOG reset. But below code depends on hardware design, if HW didn't
  	 * connect WDOG_B pin to external pmic such as i.mx6slevk, we can skip
  	 * these code since it assumed boot from 400Mhz always.
  	 */
  	reg = readw(&wdog->wcr);
  	reg |= 1 << 3;
  	/*
  	 * WDZST bit is write-once only bit. Align this bit in kernel,
  	 * otherwise kernel code will have no chance to set this bit.
  	 */
  	reg |= 1 << 0;
  	writew(reg, &wdog->wcr);
  }
eb111bb31   Peng Fan   imx: mx6: impleme...
733
734
735
736
737
738
  void reset_misc(void)
  {
  #ifdef CONFIG_VIDEO_MXS
  	lcdif_power_down();
  #endif
  }
8f3937761   Stephen Warren   ARM: mx6: use com...
739
740
  void s_init(void)
  {
8467faef7   Eric Nelson   i.MX6: Set and cl...
741
  	struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
9293d7fd5   Ye.Li   imx: mx6: Checkin...
742
  	struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
8467faef7   Eric Nelson   i.MX6: Set and cl...
743
744
  	u32 mask480;
  	u32 mask528;
9293d7fd5   Ye.Li   imx: mx6: Checkin...
745
  	u32 reg, periph1, periph2;
a3df99b50   Fabio Estevam   mx6: soc: Do not ...
746

8ee6dc05a   Ye Li   MLK-12616-6 mx6ul...
747
748
  	if (is_cpu_type(MXC_CPU_MX6SX) || is_cpu_type(MXC_CPU_MX6UL) ||
  	    is_cpu_type(MXC_CPU_MX6ULL))
a3df99b50   Fabio Estevam   mx6: soc: Do not ...
749
  		return;
8467faef7   Eric Nelson   i.MX6: Set and cl...
750
751
752
753
754
755
756
757
758
759
  	/* Due to hardware limitation, on MX6Q we need to gate/ungate all PFDs
  	 * to make sure PFD is working right, otherwise, PFDs may
  	 * not output clock after reset, MX6DL and MX6SL have added 396M pfd
  	 * workaround in ROM code, as bus clock need it
  	 */
  
  	mask480 = ANATOP_PFD_CLKGATE_MASK(0) |
  		ANATOP_PFD_CLKGATE_MASK(1) |
  		ANATOP_PFD_CLKGATE_MASK(2) |
  		ANATOP_PFD_CLKGATE_MASK(3);
9293d7fd5   Ye.Li   imx: mx6: Checkin...
760
  	mask528 = ANATOP_PFD_CLKGATE_MASK(1) |
8467faef7   Eric Nelson   i.MX6: Set and cl...
761
  		ANATOP_PFD_CLKGATE_MASK(3);
9293d7fd5   Ye.Li   imx: mx6: Checkin...
762
763
764
765
766
767
768
769
770
771
772
773
  	reg = readl(&ccm->cbcmr);
  	periph2 = ((reg & MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK)
  		>> MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET);
  	periph1 = ((reg & MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK)
  		>> MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET);
  
  	/* Checking if PLL2 PFD0 or PLL2 PFD2 is using for periph clock */
  	if ((periph2 != 0x2) && (periph1 != 0x2))
  		mask528 |= ANATOP_PFD_CLKGATE_MASK(0);
  
  	if ((periph2 != 0x1) && (periph1 != 0x1) &&
  		(periph2 != 0x3) && (periph1 != 0x3))
8467faef7   Eric Nelson   i.MX6: Set and cl...
774
  		mask528 |= ANATOP_PFD_CLKGATE_MASK(2);
9293d7fd5   Ye.Li   imx: mx6: Checkin...
775

8467faef7   Eric Nelson   i.MX6: Set and cl...
776
777
778
779
  	writel(mask480, &anatop->pfd_480_set);
  	writel(mask528, &anatop->pfd_528_set);
  	writel(mask480, &anatop->pfd_480_clr);
  	writel(mask528, &anatop->pfd_528_clr);
8f3937761   Stephen Warren   ARM: mx6: use com...
780
  }
5ea7f0e32   Pardeep Kumar Singla   mx6: Factor out c...
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
  
  #ifdef CONFIG_IMX_HDMI
  void imx_enable_hdmi_phy(void)
  {
  	struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
  	u8 reg;
  	reg = readb(&hdmi->phy_conf0);
  	reg |= HDMI_PHY_CONF0_PDZ_MASK;
  	writeb(reg, &hdmi->phy_conf0);
  	udelay(3000);
  	reg |= HDMI_PHY_CONF0_ENTMDS_MASK;
  	writeb(reg, &hdmi->phy_conf0);
  	udelay(3000);
  	reg |= HDMI_PHY_CONF0_GEN2_TXPWRON_MASK;
  	writeb(reg, &hdmi->phy_conf0);
  	writeb(HDMI_MC_PHYRSTZ_ASSERT, &hdmi->mc_phyrstz);
  }
  
  void imx_setup_hdmi(void)
  {
  	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
  	struct hdmi_regs *hdmi  = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
8dcbd43b9   Peng Fan   MLK-10774-2 HDMI:...
803
804
  	int reg, count;
  	u8 val;
5ea7f0e32   Pardeep Kumar Singla   mx6: Factor out c...
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
  
  	/* Turn on HDMI PHY clock */
  	reg = readl(&mxc_ccm->CCGR2);
  	reg |=  MXC_CCM_CCGR2_HDMI_TX_IAHBCLK_MASK|
  		 MXC_CCM_CCGR2_HDMI_TX_ISFRCLK_MASK;
  	writel(reg, &mxc_ccm->CCGR2);
  	writeb(HDMI_MC_PHYRSTZ_DEASSERT, &hdmi->mc_phyrstz);
  	reg = readl(&mxc_ccm->chsccdr);
  	reg &= ~(MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK|
  		 MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK|
  		 MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK);
  	reg |= (CHSCCDR_PODF_DIVIDE_BY_3
  		 << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET)
  		 |(CHSCCDR_IPU_PRE_CLK_540M_PFD
  		 << MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET);
  	writel(reg, &mxc_ccm->chsccdr);
8dcbd43b9   Peng Fan   MLK-10774-2 HDMI:...
821
822
823
824
825
826
827
828
829
  
  	/* Workaround to clear the overflow condition */
  	if (readb(&hdmi->ih_fc_stat2) & HDMI_IH_FC_STAT2_OVERFLOW_MASK) {
  		/* TMDS software reset */
  		writeb((u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, &hdmi->mc_swrstz);
  		val = readb(&hdmi->fc_invidconf);
  		for (count = 0 ; count < 5 ; count++)
  			writeb(val, &hdmi->fc_invidconf);
  	}
5ea7f0e32   Pardeep Kumar Singla   mx6: Factor out c...
830
831
  }
  #endif
0623d375c   Peng Fan   imx: mx6: impleme...
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
  
  #ifdef CONFIG_IMX_BOOTAUX
  int arch_auxiliary_core_up(u32 core_id, u32 boot_private_data)
  {
  	struct src *src_reg;
  	u32 stack, pc;
  
  	if (!boot_private_data)
  		return -EINVAL;
  
  	stack = *(u32 *)boot_private_data;
  	pc = *(u32 *)(boot_private_data + 4);
  
  	/* Set the stack and pc to M4 bootROM */
  	writel(stack, M4_BOOTROM_BASE_ADDR);
  	writel(pc, M4_BOOTROM_BASE_ADDR + 4);
  
  	/* Enable M4 */
  	src_reg = (struct src *)SRC_BASE_ADDR;
  	clrsetbits_le32(&src_reg->scr, SRC_SCR_M4C_NON_SCLR_RST_MASK,
  			SRC_SCR_M4_ENABLE_MASK);
  
  	return 0;
  }
  
  int arch_auxiliary_core_check_up(u32 core_id)
  {
  	struct src *src_reg = (struct src *)SRC_BASE_ADDR;
  	unsigned val;
  
  	val = readl(&src_reg->scr);
  
  	if (val & SRC_SCR_M4C_NON_SCLR_RST_MASK)
  		return 0;  /* assert in reset */
  
  	return 1;
  }
  #endif
5b87d04db   Ye Li   MLK-12495 mx6: Ad...
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
  
  #ifdef CONFIG_LDO_BYPASS_CHECK
  DECLARE_GLOBAL_DATA_PTR;
  static int ldo_bypass;
  
  int check_ldo_bypass(void)
  {
  	const int *ldo_mode;
  	int node;
  
  	/* get the right fdt_blob from the global working_fdt */
  	gd->fdt_blob = working_fdt;
  	/* Get the node from FDT for anatop ldo-bypass */
  	node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
  		"fsl,imx6q-gpc");
  	if (node < 0) {
  		printf("No gpc device node %d, force to ldo-enable.
  ", node);
  		return 0;
  	}
  	ldo_mode = fdt_getprop(gd->fdt_blob, node, "fsl,ldo-bypass", NULL);
  	/*
  	 * return 1 if "fsl,ldo-bypass = <1>", else return 0 if
  	 * "fsl,ldo-bypass = <0>" or no "fsl,ldo-bypass" property
  	 */
  	ldo_bypass = fdt32_to_cpu(*ldo_mode) == 1 ? 1 : 0;
  
  	return ldo_bypass;
  }
  
  int check_1_2G(void)
  {
  	u32 reg;
  	int result = 0;
  	struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
  	struct fuse_bank *bank = &ocotp->bank[0];
  	struct fuse_bank0_regs *fuse_bank0 =
  			(struct fuse_bank0_regs *)bank->fuse_regs;
  
  	reg = readl(&fuse_bank0->cfg3);
  	if (((reg >> 16) & 0x3) == 0x3) {
  		if (ldo_bypass) {
  			printf("Wrong dtb file used! i.MX6Q@1.2Ghz only "
  				"works with ldo-enable mode!
  ");
  			/*
  			 * Currently, only imx6q-sabresd board might be here,
  			 * since only i.MX6Q support 1.2G and only Sabresd board
  			 * support ldo-bypass mode. So hardcode here.
  			 * You can also modify your board(i.MX6Q) dtb name if it
  			 * supports both ldo-bypass and ldo-enable mode.
  			 */
  			printf("Please use imx6q-sabresd-ldo.dtb!
  ");
  			hang();
  		}
  		result = 1;
  	}
  
  	return result;
  }
  
  static int arm_orig_podf;
  void set_arm_freq_400M(bool is_400M)
  {
  	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
  
  	if (is_400M)
  		writel(0x1, &mxc_ccm->cacrr);
  	else
  		writel(arm_orig_podf, &mxc_ccm->cacrr);
  }
  
  void prep_anatop_bypass(void)
  {
  	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
  
  	arm_orig_podf = readl(&mxc_ccm->cacrr);
  	/*
  	 * Downgrade ARM speed to 400Mhz as half of boot 800Mhz before ldo
  	 * bypassed, also downgrade internal vddarm ldo to 0.975V.
  	 * VDDARM_IN 0.975V + 125mV = 1.1V < Max(1.3V)
  	 * otherwise at 800Mhz(i.mx6dl):
  	 * VDDARM_IN 1.175V + 125mV = 1.3V = Max(1.3V)
  	 * We need provide enough gap in this case.
  	 * skip if boot from 400M.
  	 */
  	if (!arm_orig_podf)
  		set_arm_freq_400M(true);
  
  	if (!is_cpu_type(MXC_CPU_MX6DL) && !is_cpu_type(MXC_CPU_MX6SX))
  		set_ldo_voltage(LDO_ARM, 975);
  	else
  		set_ldo_voltage(LDO_ARM, 1150);
  }
  
  int set_anatop_bypass(int wdog_reset_pin)
  {
  	struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
  	struct wdog_regs *wdog;
  	u32 reg = readl(&anatop->reg_core);
  
  	/* bypass VDDARM/VDDSOC */
  	reg = reg | (0x1F << 18) | 0x1F;
  	writel(reg, &anatop->reg_core);
  
  	if (wdog_reset_pin == 2)
  		wdog = (struct wdog_regs *) WDOG2_BASE_ADDR;
  	else if (wdog_reset_pin == 1)
  		wdog = (struct wdog_regs *) WDOG1_BASE_ADDR;
  	else
  		return arm_orig_podf;
  	set_wdog_reset(wdog);
  	return arm_orig_podf;
  }
  
  void finish_anatop_bypass(void)
  {
  	if (!arm_orig_podf)
  		set_arm_freq_400M(false);
  }
  #endif
23d63ff18   Ye Li   MLK-12527-2 andro...
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
  
  #ifdef CONFIG_FSL_FASTBOOT
  
  #ifdef CONFIG_ANDROID_RECOVERY
  #define ANDROID_RECOVERY_BOOT  (1 << 7)
  /* check if the recovery bit is set by kernel, it can be set by kernel
   * issue a command '# reboot recovery' */
  int recovery_check_and_clean_flag(void)
  {
  	int flag_set = 0;
  	u32 reg;
  	reg = readl(SNVS_BASE_ADDR + SNVS_LPGPR);
  
  	flag_set = !!(reg & ANDROID_RECOVERY_BOOT);
      printf("check_and_clean: reg %x, flag_set %d
  ", reg, flag_set);
  	/* clean it in case looping infinite here.... */
  	if (flag_set) {
  		reg &= ~ANDROID_RECOVERY_BOOT;
  		writel(reg, SNVS_BASE_ADDR + SNVS_LPGPR);
  	}
  
  	return flag_set;
  }
  #endif /*CONFIG_ANDROID_RECOVERY*/
  
  #define ANDROID_FASTBOOT_BOOT  (1 << 8)
  /* check if the recovery bit is set by kernel, it can be set by kernel
   * issue a command '# reboot fastboot' */
  int fastboot_check_and_clean_flag(void)
  {
  	int flag_set = 0;
  	u32 reg;
  
  	reg = readl(SNVS_BASE_ADDR + SNVS_LPGPR);
  
  	flag_set = !!(reg & ANDROID_FASTBOOT_BOOT);
  
  	/* clean it in case looping infinite here.... */
  	if (flag_set) {
  		reg &= ~ANDROID_FASTBOOT_BOOT;
  		writel(reg, SNVS_BASE_ADDR + SNVS_LPGPR);
  	}
  
  	return flag_set;
  }
  
  void fastboot_enable_flag(void)
  {
  	setbits_le32(SNVS_BASE_ADDR + SNVS_LPGPR,
  		ANDROID_FASTBOOT_BOOT);
  }
  #endif /*CONFIG_FSL_FASTBOOT*/