3 * Sascha Hauer, Pengutronix
5 * (C) Copyright 2009 Freescale Semiconductor, Inc.
7 * SPDX-License-Identifier: GPL-2.0+
11 #include <asm/errno.h>
13 #include <asm/arch/imx-regs.h>
14 #include <asm/arch/clock.h>
15 #include <asm/arch/sys_proto.h>
16 #include <asm/imx-common/boot_mode.h>
17 #include <asm/imx-common/dma.h>
19 #include <asm/arch/mxc_hdmi.h>
20 #include <asm/arch/crm_regs.h>
22 #include <imx_thermal.h>
38 #if defined(CONFIG_IMX_THERMAL)
39 static const struct imx_thermal_plat imx6_thermal_plat = {
40 .regs = (void *)ANATOP_BASE_ADDR,
45 U_BOOT_DEVICE(imx6_thermal) = {
46 .name = "imx_thermal",
47 .platdata = &imx6_thermal_plat,
53 struct scu_regs *scu = (struct scu_regs *)SCU_BASE_ADDR;
54 return readl(&scu->config) & 3;
59 struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
60 u32 reg = readl(&anatop->digprog_sololite);
61 u32 type = ((reg >> 16) & 0xff);
64 if (type != MXC_CPU_MX6SL) {
65 reg = readl(&anatop->digprog);
66 struct scu_regs *scu = (struct scu_regs *)SCU_BASE_ADDR;
67 cfg = readl(&scu->config) & 3;
68 type = ((reg >> 16) & 0xff);
69 if (type == MXC_CPU_MX6DL) {
71 type = MXC_CPU_MX6SOLO;
74 if (type == MXC_CPU_MX6Q) {
80 major = ((reg >> 8) & 0xff);
82 ((type == MXC_CPU_MX6Q) || (type == MXC_CPU_MX6D))) {
88 reg &= 0xff; /* mx6 silicon revision */
89 return (type << 12) | (reg + (0x10 * (major + 1)));
93 * OCOTP_CFG3[17:16] (see Fusemap Description Table offset 0x440)
94 * defines a 2-bit SPEED_GRADING
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
102 u32 get_cpu_speed_grade_hz(void)
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;
110 val = readl(&fuse->cfg3);
111 val >>= OCOTP_CFG3_SPEED_SHIFT;
115 /* Valid for IMX6DQ */
116 case OCOTP_CFG3_SPEED_1P2GHZ:
117 if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D))
119 /* Valid for IMX6SX/IMX6SDL/IMX6DQ */
120 case OCOTP_CFG3_SPEED_1GHZ:
122 /* Valid for IMX6DQ */
123 case OCOTP_CFG3_SPEED_850MHZ:
124 if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D))
126 /* Valid for IMX6SX/IMX6SDL/IMX6DQ */
127 case OCOTP_CFG3_SPEED_800MHZ:
134 * OCOTP_MEM0[7:6] (see Fusemap Description Table offset 0x480)
135 * defines a 2-bit Temperature Grade
137 * return temperature grade and min/max temperature in celcius
139 #define OCOTP_MEM0_TEMP_SHIFT 6
141 u32 get_cpu_temp_grade(int *minc, int *maxc)
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;
149 val = readl(&fuse->mem0);
150 val >>= OCOTP_MEM0_TEMP_SHIFT;
154 if (val == TEMP_AUTOMOTIVE) {
157 } else if (val == TEMP_INDUSTRIAL) {
160 } else if (val == TEMP_EXTCOMMERCIAL) {
171 #ifdef CONFIG_REVISION_TAG
172 u32 __weak get_board_rev(void)
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);
179 if (type == MXC_CPU_MX6D)
180 cpurev = (MXC_CPU_MX6Q) << 12 | (cpurev & 0xFFF);
186 static void clear_ldo_ramp(void)
188 struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
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
195 reg = readl(&anatop->ana_misc2);
196 reg &= ~(0x3f << 24);
197 writel(reg, &anatop->ana_misc2);
201 * Set the PMU_REG_CORE register
203 * Set LDO_SOC/PU/ARM regulators to the specified millivolt level.
204 * Possible values are from 0.725V to 1.450V in steps of
207 static int set_ldo_voltage(enum ldo_reg ldo, u32 mv)
209 struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
210 u32 val, step, old, reg = readl(&anatop->reg_core);
214 val = 0x00; /* Power gated off */
216 val = 0x1F; /* Power FET switched full on. No regulation */
218 val = (mv - 700) / 25;
236 old = (reg & (0x1F << shift)) >> shift;
237 step = abs(val - old);
241 reg = (reg & ~(0x1F << shift)) | (val << shift);
242 writel(reg, &anatop->reg_core);
245 * The LDO ramp-up is based on 64 clock cycles of 24 MHz = 2.6 us per
253 static void set_ahb_rate(u32 val)
255 struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
258 div = get_periph_clk() / val - 1;
259 reg = readl(&mxc_ccm->cbcdr);
261 writel((reg & (~MXC_CCM_CBCDR_AHB_PODF_MASK)) |
262 (div << MXC_CCM_CBCDR_AHB_PODF_OFFSET), &mxc_ccm->cbcdr);
265 static void clear_mmdc_ch_mask(void)
267 struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
269 reg = readl(&mxc_ccm->ccdr);
271 /* Clear MMDC channel mask */
272 reg &= ~(MXC_CCM_CCDR_MMDC_CH1_HS_MASK | MXC_CCM_CCDR_MMDC_CH0_HS_MASK);
273 writel(reg, &mxc_ccm->ccdr);
276 static void init_bandgap(void)
278 struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
280 * Ensure the bandgap has stabilized.
282 while (!(readl(&anatop->ana_misc0) & 0x80))
285 * For best noise performance of the analog blocks using the
286 * outputs of the bandgap, the reftop_selfbiasoff bit should
289 writel(BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_set);
294 static void set_preclk_from_osc(void)
296 struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
299 reg = readl(&mxc_ccm->cscmr1);
300 reg |= MXC_CCM_CSCMR1_PER_CLK_SEL_MASK;
301 writel(reg, &mxc_ccm->cscmr1);
305 int arch_cpu_init(void)
309 /* Need to clear MMDC_CHx_MASK to make warm reset work. */
310 clear_mmdc_ch_mask();
313 * 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.
320 * When low freq boot is enabled, ROM will not set AHB
321 * freq, so we need to ensure AHB freq is 132MHz in such
324 if (mxc_get_clock(MXC_ARM_CLK) == 396000000)
325 set_ahb_rate(132000000);
327 /* Set perclk to source from OSC 24MHz */
328 #if defined(CONFIG_MX6SL)
329 set_preclk_from_osc();
332 imx_set_wdog_powerdown(false); /* Disable PDE bit of WMCR register */
334 #ifdef CONFIG_APBH_DMA
344 int board_postclk_init(void)
346 set_ldo_voltage(LDO_SOC, 1175); /* Set VDDSOC to 1.175V */
351 #if defined(CONFIG_FEC_MXC)
352 void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
354 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
355 struct fuse_bank *bank = &ocotp->bank[4];
356 struct fuse_bank4_regs *fuse =
357 (struct fuse_bank4_regs *)bank->fuse_regs;
359 u32 value = readl(&fuse->mac_addr_high);
360 mac[0] = (value >> 8);
363 value = readl(&fuse->mac_addr_low);
364 mac[2] = value >> 24 ;
365 mac[3] = value >> 16 ;
366 mac[4] = value >> 8 ;
373 * cfg_val will be used for
374 * Boot_cfg4[7:0]:Boot_cfg3[7:0]:Boot_cfg2[7:0]:Boot_cfg1[7:0]
375 * After reset, if GPR10[28] is 1, ROM will use GPR9[25:0]
376 * instead of SBMR1 to determine the boot device.
378 const 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)},
383 {"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)},
387 /* 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)},
397 struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
398 struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
401 u32 reg, periph1, periph2;
403 if (is_cpu_type(MXC_CPU_MX6SX) || is_cpu_type(MXC_CPU_MX6UL))
406 /* 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
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);
416 mask528 = ANATOP_PFD_CLKGATE_MASK(1) |
417 ANATOP_PFD_CLKGATE_MASK(3);
419 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);
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);
429 if ((periph2 != 0x1) && (periph1 != 0x1) &&
430 (periph2 != 0x3) && (periph1 != 0x3))
431 mask528 |= ANATOP_PFD_CLKGATE_MASK(2);
433 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);
439 #ifdef CONFIG_IMX_HDMI
440 void imx_enable_hdmi_phy(void)
442 struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
444 reg = readb(&hdmi->phy_conf0);
445 reg |= HDMI_PHY_CONF0_PDZ_MASK;
446 writeb(reg, &hdmi->phy_conf0);
448 reg |= HDMI_PHY_CONF0_ENTMDS_MASK;
449 writeb(reg, &hdmi->phy_conf0);
451 reg |= HDMI_PHY_CONF0_GEN2_TXPWRON_MASK;
452 writeb(reg, &hdmi->phy_conf0);
453 writeb(HDMI_MC_PHYRSTZ_ASSERT, &hdmi->mc_phyrstz);
456 void imx_setup_hdmi(void)
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;
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);