#include <common.h>
#include <asm/armv7.h>
+#include <asm/bootm.h>
#include <asm/pl310.h>
#include <asm/errno.h>
#include <asm/io.h>
#include <stdbool.h>
#include <asm/arch/mxc_hdmi.h>
#include <asm/arch/crm_regs.h>
+#include <dm.h>
+#include <imx_thermal.h>
enum ldo_reg {
LDO_ARM,
u32 fpga_rev;
};
+#if defined(CONFIG_IMX6_THERMAL)
+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
+
u32 get_nr_cpus(void)
{
struct scu_regs *scu = (struct scu_regs *)SCU_BASE_ADDR;
struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
u32 reg = readl(&anatop->digprog_sololite);
u32 type = ((reg >> 16) & 0xff);
+ u32 major;
if (type != MXC_CPU_MX6SL) {
reg = readl(&anatop->digprog);
}
}
+ major = ((reg >> 8) & 0xff);
reg &= 0xff; /* mx6 silicon revision */
- return (type << 12) | (reg + 0x10);
+ return (type << 12) | (reg + (0x10 * (major + 1)));
+}
+
+/*
+ * 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
+
+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;
+
+ switch (val) {
+ /* Valid for IMX6DQ */
+ case OCOTP_CFG3_SPEED_1P2GHZ:
+ if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D))
+ return 1200000000;
+ /* Valid for IMX6SX/IMX6SDL/IMX6DQ */
+ case OCOTP_CFG3_SPEED_1GHZ:
+ return 996000000;
+ /* Valid for IMX6DQ */
+ case OCOTP_CFG3_SPEED_850MHZ:
+ if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D))
+ return 852000000;
+ /* Valid for IMX6SX/IMX6SDL/IMX6DQ */
+ case OCOTP_CFG3_SPEED_800MHZ:
+ return 792000000;
+ }
+ return 0;
+}
+
+/*
+ * 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;
}
#ifdef CONFIG_REVISION_TAG
aips1 = (struct aipstz_regs *)AIPS1_BASE_ADDR;
aips2 = (struct aipstz_regs *)AIPS2_BASE_ADDR;
#ifdef CONFIG_MX6SX
- aips3 = (struct aipstz_regs *)AIPS3_BASE_ADDR;
+ aips3 = (struct aipstz_regs *)AIPS3_CONFIG_BASE_ADDR;
#endif
/*
struct wdog_regs *wdog1 = (struct wdog_regs *)WDOG1_BASE_ADDR;
struct wdog_regs *wdog2 = (struct wdog_regs *)WDOG2_BASE_ADDR;
+#ifdef CONFIG_MX6SX
+ struct wdog_regs *wdog3 = (struct wdog_regs *)WDOG3_BASE_ADDR;
+ writew(enable, &wdog3->wmcr);
+#endif
+
/* Write to the PDE (Power Down Enable) bit */
writew(enable, &wdog1->wmcr);
writew(enable, &wdog2->wmcr);
writel(0, &mxc_ccm->ccdr);
}
+static void init_bandgap(void)
+{
+ struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
+ /*
+ * 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);
+}
+
+
+#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
+
+#define SRC_SCR_WARM_RESET_ENABLE 0
+
+static void init_src(void)
+{
+ struct src *src_regs = (struct src *)SRC_BASE_ADDR;
+ u32 val;
+
+ /*
+ * force warm reset sources to generate cold reset
+ * for a more reliable restart
+ */
+ val = readl(&src_regs->scr);
+ val &= ~(1 << SRC_SCR_WARM_RESET_ENABLE);
+ writel(val, &src_regs->scr);
+}
+
int arch_cpu_init(void)
{
init_aips();
/* Need to clear MMDC_CHx_MASK to make warm reset work. */
clear_mmdc_ch_mask();
+ /*
+ * 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();
+
/*
* When low freq boot is enabled, ROM will not set AHB
* freq, so we need to ensure AHB freq is 132MHz in such
if (mxc_get_clock(MXC_ARM_CLK) == 396000000)
set_ahb_rate(132000000);
+ /* Set perclk to source from OSC 24MHz */
+#if defined(CONFIG_MX6SL)
+ set_preclk_from_osc();
+#endif
+
imx_set_wdog_powerdown(false); /* Disable PDE bit of WMCR register */
#ifdef CONFIG_APBH_DMA
mxs_dma_init();
#endif
+ init_src();
+
return 0;
}
/*
* cfg_val will be used for
* Boot_cfg4[7:0]:Boot_cfg3[7:0]:Boot_cfg2[7:0]:Boot_cfg1[7:0]
- * After reset, if GPR10[28] is 1, ROM will copy GPR9[25:0]
- * to SBMR1, which will determine the boot device.
+ * After reset, if GPR10[28] is 1, ROM will use GPR9[25:0]
+ * instead of SBMR1 to determine the boot device.
*/
const struct boot_mode soc_boot_modes[] = {
{"normal", MAKE_CFGVAL(0x00, 0x00, 0x00, 0x00)},
struct pl310_regs *const pl310 = (struct pl310_regs *)L2_PL310_BASE;
unsigned int val;
+
+ /*
+ * Set bit 22 in the auxiliary control register. If this bit
+ * is cleared, PL310 treats Normal Shared Non-cacheable
+ * accesses as Cacheable no-allocate.
+ */
+ setbits_le32(&pl310->pl310_aux_ctrl, L310_SHARED_ATT_OVERRIDE_ENABLE);
+
#if defined CONFIG_MX6SL
struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
val = readl(&iomux->gpr[11]);