blob: 282302b1fc15a1224db191608106dec7f8f59596 [file] [log] [blame]
Jason Liudec11122011-11-25 00:18:02 +00001/*
2 * (C) Copyright 2007
3 * Sascha Hauer, Pengutronix
4 *
5 * (C) Copyright 2009 Freescale Semiconductor, Inc.
6 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02007 * SPDX-License-Identifier: GPL-2.0+
Jason Liudec11122011-11-25 00:18:02 +00008 */
9
10#include <common.h>
11#include <asm/errno.h>
12#include <asm/io.h>
13#include <asm/arch/imx-regs.h>
14#include <asm/arch/clock.h>
15#include <asm/arch/sys_proto.h>
Troy Kisky0ca618c2012-08-15 10:31:20 +000016#include <asm/imx-common/boot_mode.h>
Stefan Roese8338d1d2013-04-15 21:14:12 +000017#include <asm/imx-common/dma.h>
Fabio Estevam48e65b02013-02-07 06:45:23 +000018#include <stdbool.h>
Pardeep Kumar Singlac1fa1302013-07-25 12:12:13 -050019#include <asm/arch/mxc_hdmi.h>
20#include <asm/arch/crm_regs.h>
Ye.Lif19692c2014-11-20 21:14:14 +080021#include <dm.h>
22#include <imx_thermal.h>
Jason Liudec11122011-11-25 00:18:02 +000023
Fabio Estevama47ec522013-12-26 14:51:33 -020024enum ldo_reg {
25 LDO_ARM,
26 LDO_SOC,
27 LDO_PU,
28};
29
Troy Kisky58394932012-10-23 10:57:46 +000030struct scu_regs {
31 u32 ctrl;
32 u32 config;
33 u32 status;
34 u32 invalidate;
35 u32 fpga_rev;
36};
37
Adrian Alonsoce08c362015-09-02 13:54:13 -050038#if defined(CONFIG_IMX_THERMAL)
Ye.Lif19692c2014-11-20 21:14:14 +080039static const struct imx_thermal_plat imx6_thermal_plat = {
40 .regs = (void *)ANATOP_BASE_ADDR,
41 .fuse_bank = 1,
42 .fuse_word = 6,
43};
44
45U_BOOT_DEVICE(imx6_thermal) = {
46 .name = "imx_thermal",
47 .platdata = &imx6_thermal_plat,
48};
49#endif
50
Gabriel Huau170ceaf2014-07-26 11:35:43 -070051u32 get_nr_cpus(void)
52{
53 struct scu_regs *scu = (struct scu_regs *)SCU_BASE_ADDR;
54 return readl(&scu->config) & 3;
55}
56
Jason Liudec11122011-11-25 00:18:02 +000057u32 get_cpu_rev(void)
58{
Fabio Estevam46e97332012-03-20 04:21:45 +000059 struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
Troy Kisky58394932012-10-23 10:57:46 +000060 u32 reg = readl(&anatop->digprog_sololite);
61 u32 type = ((reg >> 16) & 0xff);
Peng Fan5f247922015-07-11 11:38:42 +080062 u32 major, cfg = 0;
Fabio Estevam46e97332012-03-20 04:21:45 +000063
Troy Kisky58394932012-10-23 10:57:46 +000064 if (type != MXC_CPU_MX6SL) {
65 reg = readl(&anatop->digprog);
Fabio Estevamf3d5a2c2014-01-26 15:06:41 -020066 struct scu_regs *scu = (struct scu_regs *)SCU_BASE_ADDR;
Peng Fan5f247922015-07-11 11:38:42 +080067 cfg = readl(&scu->config) & 3;
Troy Kisky58394932012-10-23 10:57:46 +000068 type = ((reg >> 16) & 0xff);
69 if (type == MXC_CPU_MX6DL) {
Troy Kisky58394932012-10-23 10:57:46 +000070 if (!cfg)
71 type = MXC_CPU_MX6SOLO;
72 }
Fabio Estevamf3d5a2c2014-01-26 15:06:41 -020073
74 if (type == MXC_CPU_MX6Q) {
75 if (cfg == 1)
76 type = MXC_CPU_MX6D;
77 }
78
Troy Kisky58394932012-10-23 10:57:46 +000079 }
Peng Fan88383232015-06-11 18:30:36 +080080 major = ((reg >> 8) & 0xff);
Peng Fan5f247922015-07-11 11:38:42 +080081 if ((major >= 1) &&
82 ((type == MXC_CPU_MX6Q) || (type == MXC_CPU_MX6D))) {
83 major--;
84 type = MXC_CPU_MX6QP;
85 if (cfg == 1)
86 type = MXC_CPU_MX6DP;
87 }
Troy Kisky58394932012-10-23 10:57:46 +000088 reg &= 0xff; /* mx6 silicon revision */
Peng Fan88383232015-06-11 18:30:36 +080089 return (type << 12) | (reg + (0x10 * (major + 1)));
Jason Liudec11122011-11-25 00:18:02 +000090}
91
Tim Harvey258d0462015-05-18 07:02:24 -070092/*
93 * OCOTP_CFG3[17:16] (see Fusemap Description Table offset 0x440)
94 * defines a 2-bit SPEED_GRADING
95 */
96#define OCOTP_CFG3_SPEED_SHIFT 16
97#define OCOTP_CFG3_SPEED_800MHZ 0
98#define OCOTP_CFG3_SPEED_850MHZ 1
99#define OCOTP_CFG3_SPEED_1GHZ 2
100#define OCOTP_CFG3_SPEED_1P2GHZ 3
101
102u32 get_cpu_speed_grade_hz(void)
103{
104 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
105 struct fuse_bank *bank = &ocotp->bank[0];
106 struct fuse_bank0_regs *fuse =
107 (struct fuse_bank0_regs *)bank->fuse_regs;
108 uint32_t val;
109
110 val = readl(&fuse->cfg3);
111 val >>= OCOTP_CFG3_SPEED_SHIFT;
112 val &= 0x3;
113
114 switch (val) {
115 /* Valid for IMX6DQ */
116 case OCOTP_CFG3_SPEED_1P2GHZ:
117 if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D))
118 return 1200000000;
119 /* Valid for IMX6SX/IMX6SDL/IMX6DQ */
120 case OCOTP_CFG3_SPEED_1GHZ:
121 return 996000000;
122 /* Valid for IMX6DQ */
123 case OCOTP_CFG3_SPEED_850MHZ:
124 if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D))
125 return 852000000;
126 /* Valid for IMX6SX/IMX6SDL/IMX6DQ */
127 case OCOTP_CFG3_SPEED_800MHZ:
128 return 792000000;
129 }
130 return 0;
131}
132
Tim Harvey5e0e1932015-05-18 06:56:45 -0700133/*
134 * OCOTP_MEM0[7:6] (see Fusemap Description Table offset 0x480)
135 * defines a 2-bit Temperature Grade
136 *
137 * return temperature grade and min/max temperature in celcius
138 */
139#define OCOTP_MEM0_TEMP_SHIFT 6
140
141u32 get_cpu_temp_grade(int *minc, int *maxc)
142{
143 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
144 struct fuse_bank *bank = &ocotp->bank[1];
145 struct fuse_bank1_regs *fuse =
146 (struct fuse_bank1_regs *)bank->fuse_regs;
147 uint32_t val;
148
149 val = readl(&fuse->mem0);
150 val >>= OCOTP_MEM0_TEMP_SHIFT;
151 val &= 0x3;
152
153 if (minc && maxc) {
154 if (val == TEMP_AUTOMOTIVE) {
155 *minc = -40;
156 *maxc = 125;
157 } else if (val == TEMP_INDUSTRIAL) {
158 *minc = -40;
159 *maxc = 105;
160 } else if (val == TEMP_EXTCOMMERCIAL) {
161 *minc = -20;
162 *maxc = 105;
163 } else {
164 *minc = 0;
165 *maxc = 95;
166 }
167 }
168 return val;
169}
170
Fabio Estevam435998b2013-03-27 07:36:55 +0000171#ifdef CONFIG_REVISION_TAG
172u32 __weak get_board_rev(void)
173{
174 u32 cpurev = get_cpu_rev();
175 u32 type = ((cpurev >> 12) & 0xff);
176 if (type == MXC_CPU_MX6SOLO)
177 cpurev = (MXC_CPU_MX6DL) << 12 | (cpurev & 0xFFF);
178
Fabio Estevamf3d5a2c2014-01-26 15:06:41 -0200179 if (type == MXC_CPU_MX6D)
180 cpurev = (MXC_CPU_MX6Q) << 12 | (cpurev & 0xFFF);
181
Fabio Estevam435998b2013-03-27 07:36:55 +0000182 return cpurev;
183}
184#endif
185
Fabio Estevamcf621ff2013-12-26 14:51:31 -0200186static void clear_ldo_ramp(void)
187{
188 struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
189 int reg;
190
191 /* ROM may modify LDO ramp up time according to fuse setting, so in
192 * order to be in the safe side we neeed to reset these settings to
193 * match the reset value: 0'b00
194 */
195 reg = readl(&anatop->ana_misc2);
196 reg &= ~(0x3f << 24);
197 writel(reg, &anatop->ana_misc2);
198}
199
Dirk Behme8c465942012-05-02 02:12:17 +0000200/*
Fabio Estevam2e95fe12014-06-13 01:42:37 -0300201 * Set the PMU_REG_CORE register
Dirk Behme8c465942012-05-02 02:12:17 +0000202 *
Fabio Estevam2e95fe12014-06-13 01:42:37 -0300203 * Set LDO_SOC/PU/ARM regulators to the specified millivolt level.
Dirk Behme8c465942012-05-02 02:12:17 +0000204 * Possible values are from 0.725V to 1.450V in steps of
205 * 0.025V (25mV).
206 */
Fabio Estevama47ec522013-12-26 14:51:33 -0200207static int set_ldo_voltage(enum ldo_reg ldo, u32 mv)
Dirk Behme8c465942012-05-02 02:12:17 +0000208{
209 struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
Fabio Estevam99b370b2013-12-26 14:51:34 -0200210 u32 val, step, old, reg = readl(&anatop->reg_core);
Fabio Estevama47ec522013-12-26 14:51:33 -0200211 u8 shift;
Dirk Behme8c465942012-05-02 02:12:17 +0000212
213 if (mv < 725)
214 val = 0x00; /* Power gated off */
215 else if (mv > 1450)
216 val = 0x1F; /* Power FET switched full on. No regulation */
217 else
218 val = (mv - 700) / 25;
219
Fabio Estevamcf621ff2013-12-26 14:51:31 -0200220 clear_ldo_ramp();
221
Fabio Estevama47ec522013-12-26 14:51:33 -0200222 switch (ldo) {
223 case LDO_SOC:
224 shift = 18;
225 break;
226 case LDO_PU:
227 shift = 9;
228 break;
229 case LDO_ARM:
230 shift = 0;
231 break;
232 default:
233 return -EINVAL;
234 }
235
Fabio Estevam99b370b2013-12-26 14:51:34 -0200236 old = (reg & (0x1F << shift)) >> shift;
237 step = abs(val - old);
238 if (step == 0)
239 return 0;
240
Fabio Estevama47ec522013-12-26 14:51:33 -0200241 reg = (reg & ~(0x1F << shift)) | (val << shift);
Dirk Behme8c465942012-05-02 02:12:17 +0000242 writel(reg, &anatop->reg_core);
Fabio Estevama47ec522013-12-26 14:51:33 -0200243
Fabio Estevam99b370b2013-12-26 14:51:34 -0200244 /*
245 * The LDO ramp-up is based on 64 clock cycles of 24 MHz = 2.6 us per
246 * step
247 */
248 udelay(3 * step);
249
Fabio Estevama47ec522013-12-26 14:51:33 -0200250 return 0;
Dirk Behme8c465942012-05-02 02:12:17 +0000251}
252
Anson Huang05a464f2014-01-23 14:00:18 +0800253static void set_ahb_rate(u32 val)
254{
255 struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
256 u32 reg, div;
257
258 div = get_periph_clk() / val - 1;
259 reg = readl(&mxc_ccm->cbcdr);
260
261 writel((reg & (~MXC_CCM_CBCDR_AHB_PODF_MASK)) |
262 (div << MXC_CCM_CBCDR_AHB_PODF_OFFSET), &mxc_ccm->cbcdr);
263}
264
Anson Huang9a149bc2014-01-23 14:00:19 +0800265static void clear_mmdc_ch_mask(void)
266{
267 struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
Peng Fan53f3c9e2015-07-11 11:38:43 +0800268 u32 reg;
269 reg = readl(&mxc_ccm->ccdr);
Anson Huang9a149bc2014-01-23 14:00:19 +0800270
271 /* Clear MMDC channel mask */
Peng Fan53f3c9e2015-07-11 11:38:43 +0800272 reg &= ~(MXC_CCM_CCDR_MMDC_CH1_HS_MASK | MXC_CCM_CCDR_MMDC_CH0_HS_MASK);
273 writel(reg, &mxc_ccm->ccdr);
Anson Huang9a149bc2014-01-23 14:00:19 +0800274}
275
Peng Fanc0e0ebf2015-01-15 14:22:32 +0800276static void init_bandgap(void)
277{
278 struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
279 /*
280 * Ensure the bandgap has stabilized.
281 */
282 while (!(readl(&anatop->ana_misc0) & 0x80))
283 ;
284 /*
285 * For best noise performance of the analog blocks using the
286 * outputs of the bandgap, the reftop_selfbiasoff bit should
287 * be set.
288 */
289 writel(BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_set);
290}
291
292
Ye.Li622dfbd2014-10-30 18:20:58 +0800293#ifdef CONFIG_MX6SL
294static void set_preclk_from_osc(void)
295{
296 struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
297 u32 reg;
298
299 reg = readl(&mxc_ccm->cscmr1);
300 reg |= MXC_CCM_CSCMR1_PER_CLK_SEL_MASK;
301 writel(reg, &mxc_ccm->cscmr1);
302}
303#endif
304
Jason Liudec11122011-11-25 00:18:02 +0000305int arch_cpu_init(void)
306{
307 init_aips();
308
Anson Huang9a149bc2014-01-23 14:00:19 +0800309 /* Need to clear MMDC_CHx_MASK to make warm reset work. */
310 clear_mmdc_ch_mask();
311
Anson Huang05a464f2014-01-23 14:00:18 +0800312 /*
Peng Fanc0e0ebf2015-01-15 14:22:32 +0800313 * Disable self-bias circuit in the analog bandap.
314 * The self-bias circuit is used by the bandgap during startup.
315 * This bit should be set after the bandgap has initialized.
316 */
317 init_bandgap();
318
319 /*
Anson Huang05a464f2014-01-23 14:00:18 +0800320 * When low freq boot is enabled, ROM will not set AHB
321 * freq, so we need to ensure AHB freq is 132MHz in such
322 * scenario.
323 */
324 if (mxc_get_clock(MXC_ARM_CLK) == 396000000)
325 set_ahb_rate(132000000);
326
Ye.Li622dfbd2014-10-30 18:20:58 +0800327 /* Set perclk to source from OSC 24MHz */
328#if defined(CONFIG_MX6SL)
329 set_preclk_from_osc();
330#endif
331
Fabio Estevam48e65b02013-02-07 06:45:23 +0000332 imx_set_wdog_powerdown(false); /* Disable PDE bit of WMCR register */
Stefan Roese8338d1d2013-04-15 21:14:12 +0000333
334#ifdef CONFIG_APBH_DMA
335 /* Start APBH DMA */
336 mxs_dma_init();
337#endif
338
Dirk Behme0adb2152015-03-09 14:48:48 +0100339 init_src();
340
Jason Liudec11122011-11-25 00:18:02 +0000341 return 0;
342}
Jason Liudec11122011-11-25 00:18:02 +0000343
Fabio Estevam99b370b2013-12-26 14:51:34 -0200344int board_postclk_init(void)
345{
346 set_ldo_voltage(LDO_SOC, 1175); /* Set VDDSOC to 1.175V */
347
348 return 0;
349}
350
Jason Liudec11122011-11-25 00:18:02 +0000351#if defined(CONFIG_FEC_MXC)
Fabio Estevam04fc1282011-12-20 05:46:31 +0000352void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
Jason Liudec11122011-11-25 00:18:02 +0000353{
Benoît Thébaudeaufa7e3952013-04-23 10:17:38 +0000354 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
355 struct fuse_bank *bank = &ocotp->bank[4];
Jason Liudec11122011-11-25 00:18:02 +0000356 struct fuse_bank4_regs *fuse =
357 (struct fuse_bank4_regs *)bank->fuse_regs;
358
Jason Liubf651aa2011-12-19 02:38:13 +0000359 u32 value = readl(&fuse->mac_addr_high);
360 mac[0] = (value >> 8);
361 mac[1] = value ;
Jason Liudec11122011-11-25 00:18:02 +0000362
Jason Liubf651aa2011-12-19 02:38:13 +0000363 value = readl(&fuse->mac_addr_low);
364 mac[2] = value >> 24 ;
365 mac[3] = value >> 16 ;
366 mac[4] = value >> 8 ;
367 mac[5] = value ;
Jason Liudec11122011-11-25 00:18:02 +0000368
369}
370#endif
Troy Kisky0ca618c2012-08-15 10:31:20 +0000371
Troy Kisky0ca618c2012-08-15 10:31:20 +0000372/*
373 * cfg_val will be used for
374 * Boot_cfg4[7:0]:Boot_cfg3[7:0]:Boot_cfg2[7:0]:Boot_cfg1[7:0]
Nikita Kiryanov9fba8422014-10-29 19:28:33 +0200375 * After reset, if GPR10[28] is 1, ROM will use GPR9[25:0]
376 * instead of SBMR1 to determine the boot device.
Troy Kisky0ca618c2012-08-15 10:31:20 +0000377 */
378const struct boot_mode soc_boot_modes[] = {
379 {"normal", MAKE_CFGVAL(0x00, 0x00, 0x00, 0x00)},
380 /* reserved value should start rom usb */
381 {"usb", MAKE_CFGVAL(0x01, 0x00, 0x00, 0x00)},
382 {"sata", MAKE_CFGVAL(0x20, 0x00, 0x00, 0x00)},
Nikolay Dimitrov284d9012014-08-10 20:03:07 +0300383 {"ecspi1:0", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x08)},
384 {"ecspi1:1", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x18)},
385 {"ecspi1:2", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x28)},
386 {"ecspi1:3", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x38)},
Troy Kisky0ca618c2012-08-15 10:31:20 +0000387 /* 4 bit bus width */
388 {"esdhc1", MAKE_CFGVAL(0x40, 0x20, 0x00, 0x00)},
389 {"esdhc2", MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)},
390 {"esdhc3", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)},
391 {"esdhc4", MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00)},
392 {NULL, 0},
393};
Stephen Warren57ab23f2013-02-26 12:28:29 +0000394
395void s_init(void)
396{
Eric Nelson2c37d3b2013-08-29 12:41:46 -0700397 struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
Ye.Li29876872014-09-09 10:17:00 +0800398 struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
Eric Nelson2c37d3b2013-08-29 12:41:46 -0700399 u32 mask480;
400 u32 mask528;
Ye.Li29876872014-09-09 10:17:00 +0800401 u32 reg, periph1, periph2;
Fabio Estevam6633e3f2014-07-09 16:13:29 -0300402
Peng Fancf333da2015-07-20 19:28:29 +0800403 if (is_cpu_type(MXC_CPU_MX6SX) || is_cpu_type(MXC_CPU_MX6UL))
Fabio Estevam6633e3f2014-07-09 16:13:29 -0300404 return;
405
Eric Nelson2c37d3b2013-08-29 12:41:46 -0700406 /* Due to hardware limitation, on MX6Q we need to gate/ungate all PFDs
407 * to make sure PFD is working right, otherwise, PFDs may
408 * not output clock after reset, MX6DL and MX6SL have added 396M pfd
409 * workaround in ROM code, as bus clock need it
410 */
411
412 mask480 = ANATOP_PFD_CLKGATE_MASK(0) |
413 ANATOP_PFD_CLKGATE_MASK(1) |
414 ANATOP_PFD_CLKGATE_MASK(2) |
415 ANATOP_PFD_CLKGATE_MASK(3);
Ye.Li29876872014-09-09 10:17:00 +0800416 mask528 = ANATOP_PFD_CLKGATE_MASK(1) |
Eric Nelson2c37d3b2013-08-29 12:41:46 -0700417 ANATOP_PFD_CLKGATE_MASK(3);
418
Ye.Li29876872014-09-09 10:17:00 +0800419 reg = readl(&ccm->cbcmr);
420 periph2 = ((reg & MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK)
421 >> MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET);
422 periph1 = ((reg & MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK)
423 >> MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET);
424
425 /* Checking if PLL2 PFD0 or PLL2 PFD2 is using for periph clock */
426 if ((periph2 != 0x2) && (periph1 != 0x2))
427 mask528 |= ANATOP_PFD_CLKGATE_MASK(0);
428
429 if ((periph2 != 0x1) && (periph1 != 0x1) &&
430 (periph2 != 0x3) && (periph1 != 0x3))
Eric Nelson2c37d3b2013-08-29 12:41:46 -0700431 mask528 |= ANATOP_PFD_CLKGATE_MASK(2);
Ye.Li29876872014-09-09 10:17:00 +0800432
Eric Nelson2c37d3b2013-08-29 12:41:46 -0700433 writel(mask480, &anatop->pfd_480_set);
434 writel(mask528, &anatop->pfd_528_set);
435 writel(mask480, &anatop->pfd_480_clr);
436 writel(mask528, &anatop->pfd_528_clr);
Stephen Warren57ab23f2013-02-26 12:28:29 +0000437}
Pardeep Kumar Singlac1fa1302013-07-25 12:12:13 -0500438
439#ifdef CONFIG_IMX_HDMI
440void imx_enable_hdmi_phy(void)
441{
442 struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
443 u8 reg;
444 reg = readb(&hdmi->phy_conf0);
445 reg |= HDMI_PHY_CONF0_PDZ_MASK;
446 writeb(reg, &hdmi->phy_conf0);
447 udelay(3000);
448 reg |= HDMI_PHY_CONF0_ENTMDS_MASK;
449 writeb(reg, &hdmi->phy_conf0);
450 udelay(3000);
451 reg |= HDMI_PHY_CONF0_GEN2_TXPWRON_MASK;
452 writeb(reg, &hdmi->phy_conf0);
453 writeb(HDMI_MC_PHYRSTZ_ASSERT, &hdmi->mc_phyrstz);
454}
455
456void imx_setup_hdmi(void)
457{
458 struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
459 struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
460 int reg;
461
462 /* Turn on HDMI PHY clock */
463 reg = readl(&mxc_ccm->CCGR2);
464 reg |= MXC_CCM_CCGR2_HDMI_TX_IAHBCLK_MASK|
465 MXC_CCM_CCGR2_HDMI_TX_ISFRCLK_MASK;
466 writel(reg, &mxc_ccm->CCGR2);
467 writeb(HDMI_MC_PHYRSTZ_DEASSERT, &hdmi->mc_phyrstz);
468 reg = readl(&mxc_ccm->chsccdr);
469 reg &= ~(MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK|
470 MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK|
471 MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK);
472 reg |= (CHSCCDR_PODF_DIVIDE_BY_3
473 << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET)
474 |(CHSCCDR_IPU_PRE_CLK_540M_PFD
475 << MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET);
476 writel(reg, &mxc_ccm->chsccdr);
477}
478#endif