ifneq ($(BUILD_DIR),)
saved-output := $(BUILD_DIR)
--# Attempt to create a output directory.
++# Attempt to create an output directory.
$(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR})
# Verify if it was successful.
$(OBJCOPY) ${OBJCFLAGS} -I binary \
--pad-to=$(CONFIG_SPL_MAX_SIZE) -O binary \
$(obj)spl/u-boot-spl.ais $(obj)spl/u-boot-spl-pad.ais
- cat $(obj)spl/u-boot-spl-pad.ais $(obj)u-boot.bin > \
+ cat $(obj)spl/u-boot-spl-pad.ais $(obj)u-boot.img > \
$(obj)u-boot.ais
- rm $(obj)spl/u-boot-spl{,-pad}.ais
- $(obj)u-boot.bd: $(TOPDIR)/board/$(BOARDDIR)/u-boot.bd
- sed "s:@@BUILD_DIR@@:$(obj):g" $< > $@
+ # Specify the target for use in elftosb call
+ ELFTOSB_TARGET-$(CONFIG_MX28) = imx28
+
-$(obj)u-boot.sb: $(obj)u-boot.bin $(obj)spl/u-boot-spl.bin
- elftosb -zf $(ELFTOSB_TARGET-y) -c $(TOPDIR)/$(CPUDIR)/$(SOC)/u-boot-$(ELFTOSB_TARGET-y).bd \
++$(obj)u-boot.sb: $(obj)u-boot.bin $(obj)spl/u-boot-spl.bin elftosb
++ cd $(OBJTREE); \
++ $(TOPDIR)/$(SUBDIR_TOOLS)/elftosb/bld/linux/elftosb -zdf $(ELFTOSB_TARGET-y) -c $(TOPDIR)/$(CPUDIR)/$(SOC)/u-boot-$(ELFTOSB_TARGET-y).bd \
+ -o $(obj)u-boot.sb
+
+ # On x600 (SPEAr600) U-Boot is appended to U-Boot SPL.
+ # Both images are created using mkimage (crc etc), so that the ROM
+ # bootloader can check its integrity. Padding needs to be done to the
+ # SPL image (with mkimage header) and not the binary. Otherwise the resulting image
+ # which is loaded/copied by the ROM bootloader to SRAM doesn't fit.
+ # The resulting image containing both U-Boot images is called u-boot.spr
+ $(obj)u-boot.spr: $(obj)u-boot.img $(obj)spl/u-boot-spl.bin
+ $(obj)tools/mkimage -A $(ARCH) -T firmware -C none \
+ -a $(CONFIG_SPL_TEXT_BASE) -e $(CONFIG_SPL_TEXT_BASE) -n XLOADER \
+ -d $(obj)spl/u-boot-spl.bin $(obj)spl/u-boot-spl.img
+ tr "\000" "\377" < /dev/zero | dd ibs=1 count=$(CONFIG_SPL_PAD_TO) \
+ of=$(obj)spl/u-boot-spl-pad.img 2>/dev/null
+ dd if=$(obj)spl/u-boot-spl.img of=$(obj)spl/u-boot-spl-pad.img \
+ conv=notrunc 2>/dev/null
+ cat $(obj)spl/u-boot-spl-pad.img $(obj)u-boot.img > $@
+
+ ifeq ($(SOC),tegra20)
+ ifeq ($(CONFIG_OF_SEPARATE),y)
+ nodtb=dtb
+ dtbfile=$(obj)u-boot.dtb
+ else
+ nodtb=nodtb
+ dtbfile=
+ endif
+
+ $(obj)u-boot-$(nodtb)-tegra.bin: $(obj)spl/u-boot-spl.bin $(obj)u-boot.bin $(dtbfile)
+ $(OBJCOPY) ${OBJCFLAGS} --pad-to=$(CONFIG_SYS_TEXT_BASE) -O binary $(obj)spl/u-boot-spl $(obj)spl/u-boot-spl-pad.bin
+ cat $(obj)spl/u-boot-spl-pad.bin $(obj)u-boot.bin $(dtbfile) > $@
+ rm $(obj)spl/u-boot-spl-pad.bin
+ endif
- $(obj)u-boot.sb: $(obj)u-boot.bd elftosb $(obj)u-boot.bin $(obj)spl/u-boot-spl.bin
- $(TOPDIR)/tools/elftosb/bld/linux/elftosb -zdf imx28 -c $< -o $@
+ $(obj)u-boot-img.bin: $(obj)spl/u-boot-spl.bin $(obj)u-boot.img
+ cat $(obj)spl/u-boot-spl.bin $(obj)u-boot.img > $@
ifeq ($(CONFIG_SANDBOX),y)
GEN_UBOOT = \
--- /dev/null
- while (--timeout) {
- if ((readl(®->reg) & mask) == mask)
- break;
+ /*
+ * Freescale i.MX28 common code
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+ #include <common.h>
+ #include <asm/errno.h>
+ #include <asm/io.h>
+ #include <asm/arch/clock.h>
+ #include <asm/arch/dma.h>
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/iomux.h>
+ #include <asm/arch/imx-regs.h>
+ #include <asm/arch/sys_proto.h>
+
+ DECLARE_GLOBAL_DATA_PTR;
+
+ /* 1 second delay should be plenty of time for block reset. */
+ #define RESET_MAX_TIMEOUT 1000000
+
+ #define MXS_BLOCK_SFTRST (1 << 31)
+ #define MXS_BLOCK_CLKGATE (1 << 30)
+
+ /* Lowlevel init isn't used on i.MX28, so just have a dummy here */
+ inline void lowlevel_init(void) {}
+
+ void reset_cpu(ulong ignored) __attribute__((noreturn));
+
+ void reset_cpu(ulong ignored)
+ {
+ struct mxs_rtc_regs *rtc_regs =
+ (struct mxs_rtc_regs *)MXS_RTC_BASE;
+ struct mxs_lcdif_regs *lcdif_regs =
+ (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
+
+ /*
+ * Shut down the LCD controller as it interferes with BootROM boot mode
+ * pads sampling.
+ */
+ writel(LCDIF_CTRL_RUN, &lcdif_regs->hw_lcdif_ctrl_clr);
+
+ /* Wait 1 uS before doing the actual watchdog reset */
+ writel(1, &rtc_regs->hw_rtc_watchdog);
+ writel(RTC_CTRL_WATCHDOGEN, &rtc_regs->hw_rtc_ctrl_set);
+
+ /* Endless loop, reset will exit from here */
+ for (;;)
+ ;
+ }
+
+ void enable_caches(void)
+ {
+ #ifndef CONFIG_SYS_ICACHE_OFF
+ icache_enable();
+ #endif
+ #ifndef CONFIG_SYS_DCACHE_OFF
+ dcache_enable();
+ #endif
+ }
+
++#define MX28_HW_DIGCTL_MICROSECONDS (void *)0x8001c0c0
++
+ int mxs_wait_mask_set(struct mxs_register_32 *reg, uint32_t mask, unsigned
+ int timeout)
+ {
- while (--timeout) {
- if ((readl(®->reg) & mask) == 0)
- break;
++ uint32_t start = readl(MX28_HW_DIGCTL_MICROSECONDS);
++
++ /* Wait for at least one microsecond for the bit mask to be set */
++ while (readl(MX28_HW_DIGCTL_MICROSECONDS) - start <= 1 || --timeout) {
++ if ((readl(®->reg) & mask) == mask) {
++ while (readl(MX28_HW_DIGCTL_MICROSECONDS) - start <= 1)
++ ;
++ return 0;
++ }
+ udelay(1);
+ }
+
+ return !timeout;
+ }
+
+ int mxs_wait_mask_clr(struct mxs_register_32 *reg, uint32_t mask, unsigned
+ int timeout)
+ {
- if (mxs_wait_mask_clr(reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
++ uint32_t start = readl(MX28_HW_DIGCTL_MICROSECONDS);
++
++ /* Wait for at least one microsecond for the bit mask to be cleared */
++ while (readl(MX28_HW_DIGCTL_MICROSECONDS) - start <= 1 || --timeout) {
++ if ((readl(®->reg) & mask) == 0) {
++ while (readl(MX28_HW_DIGCTL_MICROSECONDS) - start <= 1)
++ ;
++ return 0;
++ }
+ udelay(1);
+ }
+
+ return !timeout;
+ }
+
+ int mxs_reset_block(struct mxs_register_32 *reg)
+ {
+ /* Clear SFTRST */
+ writel(MXS_BLOCK_SFTRST, ®->reg_clr);
+
- if (mxs_wait_mask_set(reg, MXS_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
++ if (mxs_wait_mask_clr(reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT)) {
++ printf("TIMEOUT waiting for SFTRST[%p] to clear: %08x\n",
++ reg, readl(®->reg));
+ return 1;
++ }
+
+ /* Clear CLKGATE */
+ writel(MXS_BLOCK_CLKGATE, ®->reg_clr);
+
+ /* Set SFTRST */
+ writel(MXS_BLOCK_SFTRST, ®->reg_set);
+
+ /* Wait for CLKGATE being set */
- if (mxs_wait_mask_clr(reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
++ if (mxs_wait_mask_set(reg, MXS_BLOCK_CLKGATE, RESET_MAX_TIMEOUT)) {
++ printf("TIMEOUT waiting for CLKGATE[%p] to set: %08x\n",
++ reg, readl(®->reg));
+ return 1;
++ }
+
+ /* Clear SFTRST */
+ writel(MXS_BLOCK_SFTRST, ®->reg_clr);
+
- if (mxs_wait_mask_clr(reg, MXS_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
++ if (mxs_wait_mask_clr(reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT)) {
++ printf("TIMEOUT waiting for SFTRST[%p] to clear: %08x\n",
++ reg, readl(®->reg));
+ return 1;
++ }
+
+ /* Clear CLKGATE */
+ writel(MXS_BLOCK_CLKGATE, ®->reg_clr);
+
- /* Enable pad output */
- setbits_le32(&clkctrl_regs->hw_clkctrl_enet, CLKCTRL_ENET_CLK_OUT_EN);
-
++ if (mxs_wait_mask_clr(reg, MXS_BLOCK_CLKGATE, RESET_MAX_TIMEOUT)) {
++ printf("TIMEOUT waiting for CLKGATE[%p] to clear: %08x\n",
++ reg, readl(®->reg));
+ return 1;
++ }
+
+ return 0;
+ }
+
+ void mx28_fixup_vt(uint32_t start_addr)
+ {
+ uint32_t *vt = (uint32_t *)0x20;
+ int i;
+
+ for (i = 0; i < 8; i++)
+ vt[i] = start_addr + (4 * i);
+ }
+
+ #ifdef CONFIG_ARCH_MISC_INIT
+ int arch_misc_init(void)
+ {
+ mx28_fixup_vt(gd->relocaddr);
+ return 0;
+ }
+ #endif
+
++#ifdef CONFIG_ARCH_CPU_INIT
+ int arch_cpu_init(void)
+ {
+ struct mxs_clkctrl_regs *clkctrl_regs =
+ (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+ extern uint32_t _start;
+
+ mx28_fixup_vt((uint32_t)&_start);
+
+ /*
+ * Enable NAND clock
+ */
+ /* Clear bypass bit */
+ writel(CLKCTRL_CLKSEQ_BYPASS_GPMI,
+ &clkctrl_regs->hw_clkctrl_clkseq_set);
+
+ /* Set GPMI clock to ref_gpmi / 12 */
+ clrsetbits_le32(&clkctrl_regs->hw_clkctrl_gpmi,
+ CLKCTRL_GPMI_CLKGATE | CLKCTRL_GPMI_DIV_MASK, 1);
+
+ udelay(1000);
+
+ /*
+ * Configure GPIO unit
+ */
+ mxs_gpio_init();
+
+ #ifdef CONFIG_APBH_DMA
+ /* Start APBH DMA */
+ mxs_dma_init();
+ #endif
+
+ return 0;
+ }
++#endif
+
+ #if defined(CONFIG_DISPLAY_CPUINFO)
+ static const char *get_cpu_type(void)
+ {
+ struct mxs_digctl_regs *digctl_regs =
+ (struct mxs_digctl_regs *)MXS_DIGCTL_BASE;
+
+ switch (readl(&digctl_regs->hw_digctl_chipid) & HW_DIGCTL_CHIPID_MASK) {
+ case HW_DIGCTL_CHIPID_MX28:
+ return "28";
+ default:
+ return "??";
+ }
+ }
+
+ static const char *get_cpu_rev(void)
+ {
+ struct mxs_digctl_regs *digctl_regs =
+ (struct mxs_digctl_regs *)MXS_DIGCTL_BASE;
+ uint8_t rev = readl(&digctl_regs->hw_digctl_chipid) & 0x000000FF;
+
+ switch (readl(&digctl_regs->hw_digctl_chipid) & HW_DIGCTL_CHIPID_MASK) {
+ case HW_DIGCTL_CHIPID_MX28:
+ switch (rev) {
+ case 0x1:
+ return "1.2";
+ default:
+ return "??";
+ }
+ default:
+ return "??";
+ }
+ }
+
+ int print_cpuinfo(void)
+ {
+ struct mxs_spl_data *data = (struct mxs_spl_data *)
+ ((CONFIG_SYS_TEXT_BASE - sizeof(struct mxs_spl_data)) & ~0xf);
+
+ printf("CPU: Freescale i.MX%s rev%s at %d MHz\n",
+ get_cpu_type(),
+ get_cpu_rev(),
+ mxc_get_clock(MXC_ARM_CLK) / 1000000);
+ printf("BOOT: %s\n", mxs_boot_modes[data->boot_mode_idx].mode);
+ return 0;
+ }
+ #endif
+
+ int do_mx28_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+ {
+ printf("CPU: %3d MHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000);
+ printf("BUS: %3d MHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000000);
+ printf("EMI: %3d MHz\n", mxc_get_clock(MXC_EMI_CLK));
+ printf("GPMI: %3d MHz\n", mxc_get_clock(MXC_GPMI_CLK) / 1000000);
+ return 0;
+ }
+
+ /*
+ * Initializes on-chip ethernet controllers.
+ */
+ #if defined(CONFIG_MX28) && defined(CONFIG_CMD_NET)
+ int cpu_eth_init(bd_t *bis)
+ {
+ struct mxs_clkctrl_regs *clkctrl_regs =
+ (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+ /* Turn on ENET clocks */
+ clrbits_le32(&clkctrl_regs->hw_clkctrl_enet,
+ CLKCTRL_ENET_SLEEP | CLKCTRL_ENET_DISABLE);
+
+ /* Set up ENET PLL for 50 MHz */
+ /* Power on ENET PLL */
+ writel(CLKCTRL_PLL2CTRL0_POWER,
+ &clkctrl_regs->hw_clkctrl_pll2ctrl0_set);
+
+ udelay(10);
+
++ /*
++ * Enable pad output; must be done BEFORE enabling PLL
++ * according to i.MX28 Ref. Manual Rev. 1, 2010 p. 883
++ */
++ setbits_le32(&clkctrl_regs->hw_clkctrl_enet, CLKCTRL_ENET_CLK_OUT_EN);
++
+ /* Gate on ENET PLL */
+ writel(CLKCTRL_PLL2CTRL0_CLKGATE,
+ &clkctrl_regs->hw_clkctrl_pll2ctrl0_clr);
+
+ return 0;
+ }
+ #endif
+
+ static void __mx28_adjust_mac(int dev_id, unsigned char *mac)
+ {
+ mac[0] = 0x00;
+ mac[1] = 0x04; /* Use FSL vendor MAC address by default */
+
+ if (dev_id == 1) /* Let MAC1 be MAC0 + 1 by default */
+ mac[5] += 1;
+ }
+
+ void mx28_adjust_mac(int dev_id, unsigned char *mac)
+ __attribute__((weak, alias("__mx28_adjust_mac")));
+
+ #ifdef CONFIG_MX28_FEC_MAC_IN_OCOTP
+
+ #define MXS_OCOTP_MAX_TIMEOUT 1000000
+ void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
+ {
+ struct mxs_ocotp_regs *ocotp_regs =
+ (struct mxs_ocotp_regs *)MXS_OCOTP_BASE;
+ uint32_t data;
+
+ memset(mac, 0, 6);
+
+ writel(OCOTP_CTRL_RD_BANK_OPEN, &ocotp_regs->hw_ocotp_ctrl_set);
+
+ if (mxs_wait_mask_clr(&ocotp_regs->hw_ocotp_ctrl_reg, OCOTP_CTRL_BUSY,
+ MXS_OCOTP_MAX_TIMEOUT)) {
+ printf("MXS FEC: Can't get MAC from OCOTP\n");
+ return;
+ }
+
+ data = readl(&ocotp_regs->hw_ocotp_cust0);
+
+ mac[2] = (data >> 24) & 0xff;
+ mac[3] = (data >> 16) & 0xff;
+ mac[4] = (data >> 8) & 0xff;
+ mac[5] = data & 0xff;
+ mx28_adjust_mac(dev_id, mac);
+ }
+ #else
+ void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
+ {
+ memset(mac, 0, 6);
+ }
+ #endif
+
+ int mxs_dram_init(void)
+ {
+ struct mxs_spl_data *data = (struct mxs_spl_data *)
+ ((CONFIG_SYS_TEXT_BASE - sizeof(struct mxs_spl_data)) & ~0xf);
+
+ if (data->mem_dram_size == 0) {
+ printf("MXS:\n"
+ "Error, the RAM size passed up from SPL is 0!\n");
+ hang();
+ }
+
+ gd->ram_size = data->mem_dram_size;
+ return 0;
+ }
+
+ U_BOOT_CMD(
+ clocks, CONFIG_SYS_MAXARGS, 1, do_mx28_showclocks,
+ "display clocks",
+ ""
+ );
--- /dev/null
- uint32_t st = readl(&digctl_regs->hw_digctl_microseconds);
- st += delay;
- while (st > readl(&digctl_regs->hw_digctl_microseconds))
- ;
+ /*
+ * Freescale i.MX28 Boot setup
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+ #include <common.h>
+ #include <config.h>
+ #include <asm/io.h>
+ #include <asm/arch/imx-regs.h>
+ #include <asm/arch/sys_proto.h>
+ #include <asm/gpio.h>
+
+ #include "mxs_init.h"
+
+ /*
+ * This delay function is intended to be used only in early stage of boot, where
+ * clock are not set up yet. The timer used here is reset on every boot and
+ * takes a few seconds to roll. The boot doesn't take that long, so to keep the
+ * code simple, it doesn't take rolling into consideration.
+ */
++/*
++ * There's nothing to be taken into consideration for the rollover.
++ * Two's complement arithmetic used correctly does all the magic automagically.
++ */
+ void early_delay(int delay)
+ {
+ struct mxs_digctl_regs *digctl_regs =
+ (struct mxs_digctl_regs *)MXS_DIGCTL_BASE;
++ u32 start = readl(&digctl_regs->hw_digctl_microseconds);
+
-/* Support aparatus */
++ while (readl(&digctl_regs->hw_digctl_microseconds) - start < delay);
+ }
+
+ #define MUX_CONFIG_BOOTMODE_PAD (MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL)
+ static const iomux_cfg_t iomux_boot[] = {
+ MX28_PAD_LCD_D00__GPIO_1_0 | MUX_CONFIG_BOOTMODE_PAD,
+ MX28_PAD_LCD_D01__GPIO_1_1 | MUX_CONFIG_BOOTMODE_PAD,
+ MX28_PAD_LCD_D02__GPIO_1_2 | MUX_CONFIG_BOOTMODE_PAD,
+ MX28_PAD_LCD_D03__GPIO_1_3 | MUX_CONFIG_BOOTMODE_PAD,
+ MX28_PAD_LCD_D04__GPIO_1_4 | MUX_CONFIG_BOOTMODE_PAD,
+ MX28_PAD_LCD_D05__GPIO_1_5 | MUX_CONFIG_BOOTMODE_PAD,
+ };
+
+ static uint8_t mxs_get_bootmode_index(void)
+ {
+ uint8_t bootmode = 0;
+ int i;
+ uint8_t masked;
+
+ /* Setup IOMUX of bootmode pads to GPIO */
+ mxs_iomux_setup_multiple_pads(iomux_boot, ARRAY_SIZE(iomux_boot));
+
+ /* Setup bootmode pins as GPIO input */
+ gpio_direction_input(MX28_PAD_LCD_D00__GPIO_1_0);
+ gpio_direction_input(MX28_PAD_LCD_D01__GPIO_1_1);
+ gpio_direction_input(MX28_PAD_LCD_D02__GPIO_1_2);
+ gpio_direction_input(MX28_PAD_LCD_D03__GPIO_1_3);
+ gpio_direction_input(MX28_PAD_LCD_D04__GPIO_1_4);
+ gpio_direction_input(MX28_PAD_LCD_D05__GPIO_1_5);
+
+ /* Read bootmode pads */
+ bootmode |= (gpio_get_value(MX28_PAD_LCD_D00__GPIO_1_0) ? 1 : 0) << 0;
+ bootmode |= (gpio_get_value(MX28_PAD_LCD_D01__GPIO_1_1) ? 1 : 0) << 1;
+ bootmode |= (gpio_get_value(MX28_PAD_LCD_D02__GPIO_1_2) ? 1 : 0) << 2;
+ bootmode |= (gpio_get_value(MX28_PAD_LCD_D03__GPIO_1_3) ? 1 : 0) << 3;
+ bootmode |= (gpio_get_value(MX28_PAD_LCD_D04__GPIO_1_4) ? 1 : 0) << 4;
+ bootmode |= (gpio_get_value(MX28_PAD_LCD_D05__GPIO_1_5) ? 1 : 0) << 5;
+
+ for (i = 0; i < ARRAY_SIZE(mxs_boot_modes); i++) {
+ masked = bootmode & mxs_boot_modes[i].boot_mask;
+ if (masked == mxs_boot_modes[i].boot_pads)
+ break;
+ }
+
+ return i;
+ }
+
+ void mxs_common_spl_init(const iomux_cfg_t *iomux_setup,
+ const unsigned int iomux_size)
+ {
+ struct mxs_spl_data *data = (struct mxs_spl_data *)
+ ((CONFIG_SYS_TEXT_BASE - sizeof(struct mxs_spl_data)) & ~0xf);
+ uint8_t bootmode = mxs_get_bootmode_index();
+
+ mxs_iomux_setup_multiple_pads(iomux_setup, iomux_size);
+ mxs_power_init();
+
+ mxs_mem_init();
+ data->mem_dram_size = mxs_mem_get_size();
+
+ data->boot_mode_idx = bootmode;
+
+ mxs_power_wait_pswitch();
+ }
+
++/* Support apparatus */
+ inline void board_init_f(unsigned long bootflag)
+ {
+ for (;;)
+ ;
+ }
+
+ inline void board_init_r(gd_t *id, ulong dest_addr)
+ {
+ for (;;)
+ ;
+ }
+
++#ifndef CONFIG_SPL_SERIAL_SUPPORT
++void serial_putc(const char c) {}
++void serial_puts(const char *s) {}
++#endif
+ void hang(void) __attribute__ ((noreturn));
+ void hang(void)
+ {
++ serial_puts("ERROR: please reset the target\n");
+ for (;;)
+ ;
+ }
--- /dev/null
- early_delay(11000);
+ /*
+ * Freescale i.MX28 RAM init
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+ #include <common.h>
+ #include <config.h>
+ #include <asm/io.h>
+ #include <asm/arch/imx-regs.h>
+
+ #include "mxs_init.h"
+
+ static uint32_t dram_vals[] = {
+ /*
+ * i.MX28 DDR2 at 200MHz
+ */
+ #if defined(CONFIG_MX28)
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000100, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00010101, 0x01010101,
+ 0x000f0f01, 0x0f02020a, 0x00000000, 0x00010101,
+ 0x00000100, 0x00000100, 0x00000000, 0x00000002,
+ 0x01010000, 0x05060302, 0x06005003, 0x0a0000c8,
+ 0x02009c40, 0x0000030c, 0x0036a609, 0x031a0612,
+ 0x02030202, 0x00c8001c, 0x00000000, 0x00000000,
+ 0x00012100, 0xffff0303, 0x00012100, 0xffff0303,
+ 0x00012100, 0xffff0303, 0x00012100, 0xffff0303,
+ 0x00000003, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000612, 0x01000F02,
+ 0x06120612, 0x00000200, 0x00020007, 0xf5014b27,
+ 0xf5014b27, 0xf5014b27, 0xf5014b27, 0x07000300,
+ 0x07000300, 0x07000300, 0x07000300, 0x00000006,
+ 0x00000000, 0x00000000, 0x01000000, 0x01020408,
+ 0x08040201, 0x000f1133, 0x00000000, 0x00001f04,
+ 0x00001f04, 0x00001f04, 0x00001f04, 0x00001f04,
+ 0x00001f04, 0x00001f04, 0x00001f04, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00010000, 0x00020304,
+ 0x00000004, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x01010000,
+ 0x01000000, 0x03030000, 0x00010303, 0x01020202,
+ 0x00000000, 0x02040303, 0x21002103, 0x00061200,
+ 0x06120612, 0x04320432, 0x04320432, 0x00040004,
+ 0x00040004, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00010001
+ #else
+ #error Unsupported memory initialization
+ #endif
+ };
+
+ void __mxs_adjust_memory_params(uint32_t *dram_vals)
+ {
+ }
+ void mxs_adjust_memory_params(uint32_t *dram_vals)
+ __attribute__((weak, alias("__mxs_adjust_memory_params")));
+
+ static void initialize_dram_values(void)
+ {
+ int i;
+
+ mxs_adjust_memory_params(dram_vals);
+
+ for (i = 0; i < ARRAY_SIZE(dram_vals); i++)
+ writel(dram_vals[i], MXS_DRAM_BASE + (4 * i));
+ }
+
+ static void mxs_mem_init_clock(void)
+ {
+ struct mxs_clkctrl_regs *clkctrl_regs =
+ (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+ /* Gate EMI clock */
+ writeb(CLKCTRL_FRAC_CLKGATE,
+ &clkctrl_regs->hw_clkctrl_frac0_set[CLKCTRL_FRAC0_EMI]);
+
+ /* Set fractional divider for ref_emi to 480 * 18 / 21 = 411MHz */
+ writeb(CLKCTRL_FRAC_CLKGATE | (21 & CLKCTRL_FRAC_FRAC_MASK),
+ &clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_EMI]);
+
+ /* Ungate EMI clock */
+ writeb(CLKCTRL_FRAC_CLKGATE,
+ &clkctrl_regs->hw_clkctrl_frac0_clr[CLKCTRL_FRAC0_EMI]);
+
-
- early_delay(10000);
+
+ /* Set EMI clock divider for EMI clock to 411 / 2 = 205MHz */
+ writel((2 << CLKCTRL_EMI_DIV_EMI_OFFSET) |
+ (1 << CLKCTRL_EMI_DIV_XTAL_OFFSET),
+ &clkctrl_regs->hw_clkctrl_emi);
++ while (readl(&clkctrl_regs->hw_clkctrl_emi) & CLKCTRL_EMI_BUSY_REF_EMI)
++ ;
+
+ /* Unbypass EMI */
+ writel(CLKCTRL_CLKSEQ_BYPASS_EMI,
+ &clkctrl_regs->hw_clkctrl_clkseq_clr);
- writel(CLKCTRL_HBUS_DIV_MASK, &clkctrl_regs->hw_clkctrl_hbus_set);
- writel(((~3) << CLKCTRL_HBUS_DIV_OFFSET) & CLKCTRL_HBUS_DIV_MASK,
- &clkctrl_regs->hw_clkctrl_hbus_clr);
-
- early_delay(10000);
+ }
+
+ static void mxs_mem_setup_cpu_and_hbus(void)
+ {
+ struct mxs_clkctrl_regs *clkctrl_regs =
+ (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+ /* Set fractional divider for ref_cpu to 480 * 18 / 19 = 454MHz
+ * and ungate CPU clock */
+ writeb(19 & CLKCTRL_FRAC_FRAC_MASK,
+ (uint8_t *)&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_CPU]);
+
+ /* Set CPU bypass */
+ writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+ &clkctrl_regs->hw_clkctrl_clkseq_set);
+
+ /* HBUS = 151MHz */
- CLKCTRL_CPU_DIV_CPU_MASK, 1);
++ clrsetbits_le32(&clkctrl_regs->hw_clkctrl_hbus,
++ CLKCTRL_HBUS_DIV_MASK,
++ 3 << CLKCTRL_HBUS_DIV_OFFSET);
++ while (readl(&clkctrl_regs->hw_clkctrl_hbus) & CLKCTRL_HBUS_ASM_BUSY)
++ ;
+
+ /* CPU clock divider = 1 */
+ clrsetbits_le32(&clkctrl_regs->hw_clkctrl_cpu,
-
- early_delay(15000);
++ CLKCTRL_CPU_DIV_CPU_MASK,
++ 1 << CLKCTRL_CPU_DIV_CPU_OFFSET);
++ while (readl(&clkctrl_regs->hw_clkctrl_cpu) & CLKCTRL_CPU_BUSY_REF_CPU)
++ ;
+
+ /* Disable CPU bypass */
+ writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+ &clkctrl_regs->hw_clkctrl_clkseq_clr);
-static void mxs_mem_setup_vdda(void)
+ }
+
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
- writel((0xc << POWER_VDDACTRL_TRG_OFFSET) |
- (0x7 << POWER_VDDACTRL_BO_OFFSET_OFFSET) |
- POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW,
- &power_regs->hw_power_vddactrl);
++static void __attribute__((naked)) data_abort_memdetect_handler(void)
+ {
- /* The following is "subs pc, r14, #4", used as return from DABT. */
- const uint32_t data_abort_memdetect_handler = 0xe25ef004;
++ asm volatile("subs pc, r14, #4");
+ }
+
+ uint32_t mxs_mem_get_size(void)
+ {
+ uint32_t sz, da;
+ uint32_t *vt = (uint32_t *)0x20;
- vt[4] = data_abort_memdetect_handler;
+
+ /* Replace the DABT handler. */
+ da = vt[4];
- early_delay(11000);
++ vt[4] = (uint32_t)data_abort_memdetect_handler;
+
+ sz = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
+
+ /* Restore the old DABT handler. */
+ vt[4] = da;
+
+ return sz;
+ }
+
+ void mxs_mem_init(void)
+ {
+ struct mxs_clkctrl_regs *clkctrl_regs =
+ (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+ struct mxs_pinctrl_regs *pinctrl_regs =
+ (struct mxs_pinctrl_regs *)MXS_PINCTRL_BASE;
+
+ /* Set DDR2 mode */
+ writel(PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2,
+ &pinctrl_regs->hw_pinctrl_emi_ds_ctrl_set);
+
+ /* Power up PLL0 */
+ writel(CLKCTRL_PLL0CTRL0_POWER,
+ &clkctrl_regs->hw_clkctrl_pll0ctrl0_set);
+
- mxs_mem_setup_vdda();
-
++ /* enabling the PLL requires a 10µs delay before use as clk source */
++ early_delay(11);
+
+ mxs_mem_init_clock();
+
- early_delay(10000);
-
+ /*
+ * Configure the DRAM registers
+ */
+
+ /* Clear START bit from DRAM_CTL16 */
+ clrbits_le32(MXS_DRAM_BASE + 0x40, 1);
+
+ initialize_dram_values();
+
+ /* Clear SREFRESH bit from DRAM_CTL17 */
+ clrbits_le32(MXS_DRAM_BASE + 0x44, 1);
+
+ /* Set START bit in DRAM_CTL16 */
+ setbits_le32(MXS_DRAM_BASE + 0x40, 1);
+
+ /* Wait for bit 20 (DRAM init complete) in DRAM_CTL58 */
+ while (!(readl(MXS_DRAM_BASE + 0xe8) & (1 << 20)))
+ ;
+
+ mxs_mem_setup_cpu_and_hbus();
+ }
--- /dev/null
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
+ /*
+ * Freescale i.MX28 Boot PMIC init
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+ #include <common.h>
+ #include <config.h>
+ #include <asm/io.h>
+ #include <asm/arch/imx-regs.h>
+
+ #include "mxs_init.h"
+
++#ifdef CONFIG_SYS_SPL_VDDD_VAL
++#define VDDD_VAL CONFIG_SYS_SPL_VDDD_VAL
++#else
++#define VDDD_VAL 1350
++#endif
++#ifdef CONFIG_SYS_SPL_VDDIO_VAL
++#define VDDIO_VAL CONFIG_SYS_SPL_VDDIO_VAL
++#else
++#define VDDIO_VAL 3300
++#endif
++#ifdef CONFIG_SYS_SPL_VDDA_VAL
++#define VDDA_VAL CONFIG_SYS_SPL_VDDA_VAL
++#else
++#define VDDA_VAL 1800
++#endif
++#ifdef CONFIG_SYS_SPL_VDDMEM_VAL
++#define VDDMEM_VAL CONFIG_SYS_SPL_VDDMEM_VAL
++#else
++#define VDDMEM_VAL 1500
++#endif
++
++#ifdef CONFIG_SYS_SPL_VDDD_BO_VAL
++#define VDDD_BO_VAL CONFIG_SYS_SPL_VDDD_BO_VAL
++#else
++#define VDDD_BO_VAL 150
++#endif
++#ifdef CONFIG_SYS_SPL_VDDIO_BO_VAL
++#define VDDIO_BO_VAL CONFIG_SYS_SPL_VDDIO_BO_VAL
++#else
++#define VDDIO_BO_VAL 150
++#endif
++#ifdef CONFIG_SYS_SPL_VDDA_BO_VAL
++#define VDDA_BO_VAL CONFIG_SYS_SPL_VDDA_BO_VAL
++#else
++#define VDDA_BO_VAL 175
++#endif
++#ifdef CONFIG_SYS_SPL_VDDMEM_BO_VAL
++#define VDDMEM_BO_VAL CONFIG_SYS_SPL_VDDMEM_BO_VAL
++#else
++#define VDDMEM_BO_VAL 25
++#endif
++
++#ifdef CONFIG_SYS_SPL_BATT_BO_LEVEL
++#if CONFIG_SYS_SPL_BATT_BO_LEVEL < 2400 || CONFIG_SYS_SPL_BATT_BO_LEVEL > 3640
++#error CONFIG_SYS_SPL_BATT_BO_LEVEL out of range
++#endif
++#define BATT_BO_VAL (((CONFIG_SYS_SPL_BATT_BO_LEVEL) - 2400) / 40)
++#else
++/* Brownout default at 3V */
++#define BATT_BO_VAL ((3000 - 2400) / 40)
++#endif
++
++#ifdef CONFIG_SYS_SPL_FIXED_BATT_SUPPLY
++static const int fixed_batt_supply = 1;
++#else
++static const int fixed_batt_supply;
++#endif
++
++static struct mxs_power_regs *power_regs = (void *)MXS_POWER_BASE;
++
+ static void mxs_power_clock2xtal(void)
+ {
+ struct mxs_clkctrl_regs *clkctrl_regs =
+ (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+ /* Set XTAL as CPU reference clock */
+ writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
+ &clkctrl_regs->hw_clkctrl_clkseq_set);
+ }
+
+ static void mxs_power_clock2pll(void)
+ {
+ struct mxs_clkctrl_regs *clkctrl_regs =
+ (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+
+ setbits_le32(&clkctrl_regs->hw_clkctrl_pll0ctrl0,
+ CLKCTRL_PLL0CTRL0_POWER);
+ early_delay(100);
+ setbits_le32(&clkctrl_regs->hw_clkctrl_clkseq,
+ CLKCTRL_CLKSEQ_BYPASS_CPU);
+ }
+
+ static void mxs_power_clear_auto_restart(void)
+ {
+ struct mxs_rtc_regs *rtc_regs =
+ (struct mxs_rtc_regs *)MXS_RTC_BASE;
+
+ writel(RTC_CTRL_SFTRST, &rtc_regs->hw_rtc_ctrl_clr);
+ while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_SFTRST)
+ ;
+
+ writel(RTC_CTRL_CLKGATE, &rtc_regs->hw_rtc_ctrl_clr);
+ while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_CLKGATE)
+ ;
+
+ /*
+ * Due to the hardware design bug of mx28 EVK-A
+ * we need to set the AUTO_RESTART bit.
+ */
+ if (readl(&rtc_regs->hw_rtc_persistent0) & RTC_PERSISTENT0_AUTO_RESTART)
+ return;
+
+ while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
+ ;
+
+ setbits_le32(&rtc_regs->hw_rtc_persistent0,
+ RTC_PERSISTENT0_AUTO_RESTART);
+ writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_set);
+ writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_clr);
+ while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
+ ;
+ while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_STALE_REGS_MASK)
+ ;
+ }
+
+ static void mxs_power_set_linreg(void)
+ {
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
+ /* Set linear regulator 25mV below switching converter */
+ clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+ POWER_VDDDCTRL_LINREG_OFFSET_MASK,
+ POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
+
+ clrsetbits_le32(&power_regs->hw_power_vddactrl,
+ POWER_VDDACTRL_LINREG_OFFSET_MASK,
+ POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW);
+
+ clrsetbits_le32(&power_regs->hw_power_vddioctrl,
+ POWER_VDDIOCTRL_LINREG_OFFSET_MASK,
+ POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW);
+ }
+
+ static int mxs_get_batt_volt(void)
+ {
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
+ uint32_t volt = readl(&power_regs->hw_power_battmonitor);
++
+ volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
+ volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
+ volt *= 8;
+ return volt;
+ }
+
+ static int mxs_is_batt_ready(void)
+ {
+ return (mxs_get_batt_volt() >= 3600);
+ }
+
+ static int mxs_is_batt_good(void)
+ {
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
+ uint32_t volt = mxs_get_batt_volt();
+
+ if ((volt >= 2400) && (volt <= 4300))
+ return 1;
+
+ clrsetbits_le32(&power_regs->hw_power_5vctrl,
+ POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+ 0x3 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+ writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+ &power_regs->hw_power_5vctrl_clr);
+
+ clrsetbits_le32(&power_regs->hw_power_charge,
+ POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
+ POWER_CHARGE_STOP_ILIMIT_10MA | 0x3);
+
+ writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_clr);
+ writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+ &power_regs->hw_power_5vctrl_clr);
+
+ early_delay(500000);
+
+ volt = mxs_get_batt_volt();
+
+ if (volt >= 3500)
+ return 0;
+
+ if (volt >= 2400)
+ return 1;
+
+ writel(POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
+ &power_regs->hw_power_charge_clr);
+ writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
+
+ return 0;
+ }
+
+ static void mxs_power_setup_5v_detect(void)
+ {
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
+ /* Start 5V detection */
+ clrsetbits_le32(&power_regs->hw_power_5vctrl,
+ POWER_5VCTRL_VBUSVALID_TRSH_MASK,
+ POWER_5VCTRL_VBUSVALID_TRSH_4V4 |
+ POWER_5VCTRL_PWRUP_VBUS_CMPS);
+ }
+
+ static void mxs_src_power_init(void)
+ {
- setbits_le32(&power_regs->hw_power_battmonitor,
+ /* Improve efficieny and reduce transient ripple */
+ writel(POWER_LOOPCTRL_TOGGLE_DIF | POWER_LOOPCTRL_EN_CM_HYST |
+ POWER_LOOPCTRL_EN_DF_HYST, &power_regs->hw_power_loopctrl_set);
+
+ clrsetbits_le32(&power_regs->hw_power_dclimits,
+ POWER_DCLIMITS_POSLIMIT_BUCK_MASK,
+ 0x30 << POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET);
+
- /* 5V to battery handoff ... FIXME */
- setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
- early_delay(30);
- clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
++ if (!fixed_batt_supply) {
++ /* FIXME: This requires the LRADC to be set up! */
++ setbits_le32(&power_regs->hw_power_battmonitor,
+ POWER_BATTMONITOR_EN_BATADJ);
++ } else {
++ clrbits_le32(&power_regs->hw_power_battmonitor,
++ POWER_BATTMONITOR_EN_BATADJ);
++ }
+
+ /* Increase the RCSCALE level for quick DCDC response to dynamic load */
+ clrsetbits_le32(&power_regs->hw_power_loopctrl,
+ POWER_LOOPCTRL_EN_RCSCALE_MASK,
+ POWER_LOOPCTRL_RCSCALE_THRESH |
+ POWER_LOOPCTRL_EN_RCSCALE_8X);
+
+ clrsetbits_le32(&power_regs->hw_power_minpwr,
+ POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
+
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
++ if (!fixed_batt_supply) {
++ /* 5V to battery handoff ... FIXME */
++ setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
++ early_delay(30);
++ clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
++ }
+ }
+
+ static void mxs_power_init_4p2_params(void)
+ {
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
+ /* Setup 4P2 parameters */
+ clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
+ POWER_DCDC4P2_CMPTRIP_MASK | POWER_DCDC4P2_TRG_MASK,
+ POWER_DCDC4P2_TRG_4V2 | (31 << POWER_DCDC4P2_CMPTRIP_OFFSET));
+
+ clrsetbits_le32(&power_regs->hw_power_5vctrl,
+ POWER_5VCTRL_HEADROOM_ADJ_MASK,
+ 0x4 << POWER_5VCTRL_HEADROOM_ADJ_OFFSET);
+
+ clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
+ POWER_DCDC4P2_DROPOUT_CTRL_MASK,
+ POWER_DCDC4P2_DROPOUT_CTRL_100MV |
+ POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL);
+
+ clrsetbits_le32(&power_regs->hw_power_5vctrl,
+ POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+ 0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+ }
+
+ static void mxs_enable_4p2_dcdc_input(int xfer)
+ {
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
+ uint32_t tmp, vbus_thresh, vbus_5vdetect, pwd_bo;
+ uint32_t prev_5v_brnout, prev_5v_droop;
+
+ prev_5v_brnout = readl(&power_regs->hw_power_5vctrl) &
+ POWER_5VCTRL_PWDN_5VBRNOUT;
+ prev_5v_droop = readl(&power_regs->hw_power_ctrl) &
+ POWER_CTRL_ENIRQ_VDD5V_DROOP;
+
+ clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
+ writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
+ &power_regs->hw_power_reset);
+
+ clrbits_le32(&power_regs->hw_power_ctrl, POWER_CTRL_ENIRQ_VDD5V_DROOP);
+
+ if (xfer && (readl(&power_regs->hw_power_5vctrl) &
+ POWER_5VCTRL_ENABLE_DCDC)) {
+ return;
+ }
+
+ /*
+ * Recording orignal values that will be modified temporarlily
+ * to handle a chip bug. See chip errata for CQ ENGR00115837
+ */
+ tmp = readl(&power_regs->hw_power_5vctrl);
+ vbus_thresh = tmp & POWER_5VCTRL_VBUSVALID_TRSH_MASK;
+ vbus_5vdetect = tmp & POWER_5VCTRL_VBUSVALID_5VDETECT;
+
+ pwd_bo = readl(&power_regs->hw_power_minpwr) & POWER_MINPWR_PWD_BO;
+
+ /*
+ * Disable mechanisms that get erroneously tripped by when setting
+ * the DCDC4P2 EN_DCDC
+ */
+ clrbits_le32(&power_regs->hw_power_5vctrl,
+ POWER_5VCTRL_VBUSVALID_5VDETECT |
+ POWER_5VCTRL_VBUSVALID_TRSH_MASK);
+
+ writel(POWER_MINPWR_PWD_BO, &power_regs->hw_power_minpwr_set);
+
+ if (xfer) {
+ setbits_le32(&power_regs->hw_power_5vctrl,
+ POWER_5VCTRL_DCDC_XFER);
+ early_delay(20);
+ clrbits_le32(&power_regs->hw_power_5vctrl,
+ POWER_5VCTRL_DCDC_XFER);
+
+ setbits_le32(&power_regs->hw_power_5vctrl,
+ POWER_5VCTRL_ENABLE_DCDC);
+ } else {
+ setbits_le32(&power_regs->hw_power_dcdc4p2,
+ POWER_DCDC4P2_ENABLE_DCDC);
+ }
+
+ early_delay(25);
+
+ clrsetbits_le32(&power_regs->hw_power_5vctrl,
+ POWER_5VCTRL_VBUSVALID_TRSH_MASK, vbus_thresh);
+
+ if (vbus_5vdetect)
+ writel(vbus_5vdetect, &power_regs->hw_power_5vctrl_set);
+
+ if (!pwd_bo)
+ clrbits_le32(&power_regs->hw_power_minpwr, POWER_MINPWR_PWD_BO);
+
+ while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ)
+ writel(POWER_CTRL_VBUS_VALID_IRQ,
+ &power_regs->hw_power_ctrl_clr);
+
+ if (prev_5v_brnout) {
+ writel(POWER_5VCTRL_PWDN_5VBRNOUT,
+ &power_regs->hw_power_5vctrl_set);
+ writel(POWER_RESET_UNLOCK_KEY,
+ &power_regs->hw_power_reset);
+ } else {
+ writel(POWER_5VCTRL_PWDN_5VBRNOUT,
+ &power_regs->hw_power_5vctrl_clr);
+ writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
+ &power_regs->hw_power_reset);
+ }
+
+ while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VDD5V_DROOP_IRQ)
+ writel(POWER_CTRL_VDD5V_DROOP_IRQ,
+ &power_regs->hw_power_ctrl_clr);
+
+ if (prev_5v_droop)
+ clrbits_le32(&power_regs->hw_power_ctrl,
+ POWER_CTRL_ENIRQ_VDD5V_DROOP);
+ else
+ setbits_le32(&power_regs->hw_power_ctrl,
+ POWER_CTRL_ENIRQ_VDD5V_DROOP);
+ }
+
+ static void mxs_power_init_4p2_regulator(void)
+ {
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
+ uint32_t tmp, tmp2;
+
+ setbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_ENABLE_4P2);
+
+ writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_set);
+
+ writel(POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+ &power_regs->hw_power_5vctrl_clr);
+ clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_TRG_MASK);
+
+ /* Power up the 4p2 rail and logic/control */
+ writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+ &power_regs->hw_power_5vctrl_clr);
+
+ /*
+ * Start charging up the 4p2 capacitor. We ramp of this charge
+ * gradually to avoid large inrush current from the 5V cable which can
+ * cause transients/problems
+ */
+ mxs_enable_4p2_dcdc_input(0);
+
+ if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
+ /*
+ * If we arrived here, we were unable to recover from mx23 chip
+ * errata 5837. 4P2 is disabled and sufficient battery power is
+ * not present. Exiting to not enable DCDC power during 5V
+ * connected state.
+ */
+ clrbits_le32(&power_regs->hw_power_dcdc4p2,
+ POWER_DCDC4P2_ENABLE_DCDC);
+ writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+ &power_regs->hw_power_5vctrl_set);
+ hang();
+ }
+
+ /*
+ * Here we set the 4p2 brownout level to something very close to 4.2V.
+ * We then check the brownout status. If the brownout status is false,
+ * the voltage is already close to the target voltage of 4.2V so we
+ * can go ahead and set the 4P2 current limit to our max target limit.
+ * If the brownout status is true, we need to ramp us the current limit
+ * so that we don't cause large inrush current issues. We step up the
+ * current limit until the brownout status is false or until we've
+ * reached our maximum defined 4p2 current limit.
+ */
+ clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
+ POWER_DCDC4P2_BO_MASK,
+ 22 << POWER_DCDC4P2_BO_OFFSET); /* 4.15V */
+
+ if (!(readl(&power_regs->hw_power_sts) & POWER_STS_DCDC_4P2_BO)) {
+ setbits_le32(&power_regs->hw_power_5vctrl,
+ 0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+ } else {
+ tmp = (readl(&power_regs->hw_power_5vctrl) &
+ POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK) >>
+ POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
+ while (tmp < 0x3f) {
+ if (!(readl(&power_regs->hw_power_sts) &
+ POWER_STS_DCDC_4P2_BO)) {
+ tmp = readl(&power_regs->hw_power_5vctrl);
+ tmp |= POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
+ early_delay(100);
+ writel(tmp, &power_regs->hw_power_5vctrl);
+ break;
+ } else {
+ tmp++;
+ tmp2 = readl(&power_regs->hw_power_5vctrl);
+ tmp2 &= ~POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
+ tmp2 |= tmp <<
+ POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
+ writel(tmp2, &power_regs->hw_power_5vctrl);
+ early_delay(100);
+ }
+ }
+ }
+
+ clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK);
+ writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+ }
+
+ static void mxs_power_init_dcdc_4p2_source(void)
+ {
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
+ if (!(readl(&power_regs->hw_power_dcdc4p2) &
+ POWER_DCDC4P2_ENABLE_DCDC)) {
+ hang();
+ }
+
+ mxs_enable_4p2_dcdc_input(1);
+
+ if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
+ clrbits_le32(&power_regs->hw_power_dcdc4p2,
+ POWER_DCDC4P2_ENABLE_DCDC);
+ writel(POWER_5VCTRL_ENABLE_DCDC,
+ &power_regs->hw_power_5vctrl_clr);
+ writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
+ &power_regs->hw_power_5vctrl_set);
+ }
+ }
+
+ static void mxs_power_enable_4p2(void)
+ {
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
+ uint32_t vdddctrl, vddactrl, vddioctrl;
+ uint32_t tmp;
+
+ vdddctrl = readl(&power_regs->hw_power_vdddctrl);
+ vddactrl = readl(&power_regs->hw_power_vddactrl);
+ vddioctrl = readl(&power_regs->hw_power_vddioctrl);
+
+ setbits_le32(&power_regs->hw_power_vdddctrl,
+ POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
+ POWER_VDDDCTRL_PWDN_BRNOUT);
+
+ setbits_le32(&power_regs->hw_power_vddactrl,
+ POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG |
+ POWER_VDDACTRL_PWDN_BRNOUT);
+
+ setbits_le32(&power_regs->hw_power_vddioctrl,
+ POWER_VDDIOCTRL_DISABLE_FET | POWER_VDDIOCTRL_PWDN_BRNOUT);
+
+ mxs_power_init_4p2_params();
+ mxs_power_init_4p2_regulator();
+
+ /* Shutdown battery (none present) */
+ if (!mxs_is_batt_ready()) {
+ clrbits_le32(&power_regs->hw_power_dcdc4p2,
+ POWER_DCDC4P2_BO_MASK);
+ writel(POWER_CTRL_DCDC4P2_BO_IRQ,
+ &power_regs->hw_power_ctrl_clr);
+ writel(POWER_CTRL_ENIRQ_DCDC4P2_BO,
+ &power_regs->hw_power_ctrl_clr);
+ }
+
+ mxs_power_init_dcdc_4p2_source();
+
+ writel(vdddctrl, &power_regs->hw_power_vdddctrl);
+ early_delay(20);
+ writel(vddactrl, &power_regs->hw_power_vddactrl);
+ early_delay(20);
+ writel(vddioctrl, &power_regs->hw_power_vddioctrl);
+
+ /*
+ * Check if FET is enabled on either powerout and if so,
+ * disable load.
+ */
+ tmp = 0;
+ tmp |= !(readl(&power_regs->hw_power_vdddctrl) &
+ POWER_VDDDCTRL_DISABLE_FET);
+ tmp |= !(readl(&power_regs->hw_power_vddactrl) &
+ POWER_VDDACTRL_DISABLE_FET);
+ tmp |= !(readl(&power_regs->hw_power_vddioctrl) &
+ POWER_VDDIOCTRL_DISABLE_FET);
+ if (tmp)
+ writel(POWER_CHARGE_ENABLE_LOAD,
+ &power_regs->hw_power_charge_clr);
+ }
+
+ static void mxs_boot_valid_5v(void)
+ {
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
+ /*
+ * Use VBUSVALID level instead of VDD5V_GT_VDDIO level to trigger a 5V
+ * disconnect event. FIXME
+ */
+ writel(POWER_5VCTRL_VBUSVALID_5VDETECT,
+ &power_regs->hw_power_5vctrl_set);
+
+ /* Configure polarity to check for 5V disconnection. */
+ writel(POWER_CTRL_POLARITY_VBUSVALID |
+ POWER_CTRL_POLARITY_VDD5V_GT_VDDIO,
+ &power_regs->hw_power_ctrl_clr);
+
+ writel(POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_VDD5V_GT_VDDIO_IRQ,
+ &power_regs->hw_power_ctrl_clr);
+
+ mxs_power_enable_4p2();
+ }
+
+ static void mxs_powerdown(void)
+ {
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
+ writel(POWER_RESET_UNLOCK_KEY, &power_regs->hw_power_reset);
+ writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
+ &power_regs->hw_power_reset);
+ }
+
+ static void mxs_batt_boot(void)
+ {
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
+ clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
+ clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_ENABLE_DCDC);
+
+ clrbits_le32(&power_regs->hw_power_dcdc4p2,
+ POWER_DCDC4P2_ENABLE_DCDC | POWER_DCDC4P2_ENABLE_4P2);
+ writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_clr);
+
+ /* 5V to battery handoff. */
+ setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
+ early_delay(30);
+ clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
+
+ writel(POWER_CTRL_ENIRQ_DCDC4P2_BO, &power_regs->hw_power_ctrl_clr);
+
+ clrsetbits_le32(&power_regs->hw_power_minpwr,
+ POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
+
+ mxs_power_set_linreg();
+
+ clrbits_le32(&power_regs->hw_power_vdddctrl,
+ POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG);
+
+ clrbits_le32(&power_regs->hw_power_vddactrl,
+ POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG);
+
+ clrbits_le32(&power_regs->hw_power_vddioctrl,
+ POWER_VDDIOCTRL_DISABLE_FET);
+
+ setbits_le32(&power_regs->hw_power_5vctrl,
+ POWER_5VCTRL_PWD_CHARGE_4P2_MASK);
+
+ setbits_le32(&power_regs->hw_power_5vctrl,
+ POWER_5VCTRL_ENABLE_DCDC);
+
+ clrsetbits_le32(&power_regs->hw_power_5vctrl,
+ POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
+ 0x8 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
+ }
+
+ static void mxs_handle_5v_conflict(void)
+ {
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
+ uint32_t tmp;
+
+ setbits_le32(&power_regs->hw_power_vddioctrl,
+ POWER_VDDIOCTRL_BO_OFFSET_MASK);
+
+ for (;;) {
+ tmp = readl(&power_regs->hw_power_sts);
+
+ if (tmp & POWER_STS_VDDIO_BO) {
+ /*
+ * VDDIO has a brownout, then the VDD5V_GT_VDDIO becomes
+ * unreliable
+ */
+ mxs_powerdown();
+ break;
+ }
+
+ if (tmp & POWER_STS_VDD5V_GT_VDDIO) {
+ mxs_boot_valid_5v();
+ break;
+ } else {
+ mxs_powerdown();
+ break;
+ }
+
+ if (tmp & POWER_STS_PSWITCH_MASK) {
+ mxs_batt_boot();
+ break;
+ }
+ }
+ }
+
+ static void mxs_5v_boot(void)
+ {
-static void mxs_init_batt_bo(void)
+ /*
+ * NOTE: In original IMX-Bootlets, this also checks for VBUSVALID,
+ * but their implementation always returns 1 so we omit it here.
+ */
+ if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+ mxs_boot_valid_5v();
+ return;
+ }
+
+ early_delay(1000);
+ if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+ mxs_boot_valid_5v();
+ return;
+ }
+
+ mxs_handle_5v_conflict();
+ }
+
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
++static void mxs_fixed_batt_boot(void)
+ {
- /* Brownout at 3V */
++ writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr);
++
++ setbits_le32(&power_regs->hw_power_5vctrl,
++ POWER_5VCTRL_PWDN_5VBRNOUT |
++ POWER_5VCTRL_ENABLE_DCDC |
++ POWER_5VCTRL_ILIMIT_EQ_ZERO |
++ POWER_5VCTRL_PWDN_5VBRNOUT |
++ POWER_5VCTRL_PWD_CHARGE_4P2_MASK);
++
++ writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
++
++ clrbits_le32(&power_regs->hw_power_vdddctrl,
++ POWER_VDDDCTRL_DISABLE_FET |
++ POWER_VDDDCTRL_ENABLE_LINREG |
++ POWER_VDDDCTRL_DISABLE_STEPPING);
++
++ clrbits_le32(&power_regs->hw_power_vddactrl,
++ POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG |
++ POWER_VDDACTRL_DISABLE_STEPPING);
++
++ clrbits_le32(&power_regs->hw_power_vddioctrl,
++ POWER_VDDIOCTRL_DISABLE_FET |
++ POWER_VDDIOCTRL_DISABLE_STEPPING);
+
- 15 << POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET);
++ /* Stop 5V detection */
++ writel(POWER_5VCTRL_PWRUP_VBUS_CMPS,
++ &power_regs->hw_power_5vctrl_clr);
++}
++
++static void mxs_init_batt_bo(void)
++{
+ clrsetbits_le32(&power_regs->hw_power_battmonitor,
+ POWER_BATTMONITOR_BRWNOUT_LVL_MASK,
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
++ BATT_BO_VAL << POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET);
+
+ writel(POWER_CTRL_BATT_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+ writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr);
+ }
+
+ static void mxs_switch_vddd_to_dcdc_source(void)
+ {
- int batt_ready, batt_good;
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
+ clrsetbits_le32(&power_regs->hw_power_vdddctrl,
+ POWER_VDDDCTRL_LINREG_OFFSET_MASK,
+ POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
+
+ clrbits_le32(&power_regs->hw_power_vdddctrl,
+ POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
+ POWER_VDDDCTRL_DISABLE_STEPPING);
+ }
+
+ static void mxs_power_configure_power_source(void)
+ {
- if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
- batt_ready = mxs_is_batt_ready();
- if (batt_ready) {
- /* 5V source detected, good battery detected. */
- mxs_batt_boot();
- } else {
- batt_good = mxs_is_batt_good();
- if (!batt_good) {
- /* 5V source detected, bad battery detected. */
- writel(LRADC_CONVERSION_AUTOMATIC,
- &lradc_regs->hw_lradc_conversion_clr);
- clrbits_le32(&power_regs->hw_power_battmonitor,
- POWER_BATTMONITOR_BATT_VAL_MASK);
+ struct mxs_lradc_regs *lradc_regs =
+ (struct mxs_lradc_regs *)MXS_LRADC_BASE;
+
+ mxs_src_power_init();
+
- mxs_5v_boot();
++ if (!fixed_batt_supply) {
++ if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
++ if (mxs_is_batt_ready()) {
++ /* 5V source detected, good battery detected. */
++ mxs_batt_boot();
++ } else {
++ if (!mxs_is_batt_good()) {
++ /* 5V source detected, bad battery detected. */
++ writel(LRADC_CONVERSION_AUTOMATIC,
++ &lradc_regs->hw_lradc_conversion_clr);
++ clrbits_le32(&power_regs->hw_power_battmonitor,
++ POWER_BATTMONITOR_BATT_VAL_MASK);
++ }
++ mxs_5v_boot();
+ }
- /* 5V not detected, booting from battery. */
- mxs_batt_boot();
++ } else {
++ /* 5V not detected, booting from battery. */
++ mxs_batt_boot();
+ }
+ } else {
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
++ mxs_fixed_batt_boot();
+ }
+
+ mxs_power_clock2pll();
+
+ mxs_init_batt_bo();
+
+ mxs_switch_vddd_to_dcdc_source();
+ }
+
+ static void mxs_enable_output_rail_protection(void)
+ {
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
+ writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
+ POWER_CTRL_VDDIO_BO_IRQ, &power_regs->hw_power_ctrl_clr);
+
+ setbits_le32(&power_regs->hw_power_vdddctrl,
+ POWER_VDDDCTRL_PWDN_BRNOUT);
+
+ setbits_le32(&power_regs->hw_power_vddactrl,
+ POWER_VDDACTRL_PWDN_BRNOUT);
+
+ setbits_le32(&power_regs->hw_power_vddioctrl,
+ POWER_VDDIOCTRL_PWDN_BRNOUT);
+ }
+
+ static int mxs_get_vddio_power_source_off(void)
+ {
- if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+ uint32_t tmp;
+
-
++ if ((readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) &&
++ !(readl(&power_regs->hw_power_5vctrl) &
++ POWER_5VCTRL_ILIMIT_EQ_ZERO)) {
++
+ tmp = readl(&power_regs->hw_power_vddioctrl);
+ if (tmp & POWER_VDDIOCTRL_DISABLE_FET) {
+ if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
+ POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS) {
+ return 1;
+ }
+ }
+
+ if (!(readl(&power_regs->hw_power_5vctrl) &
+ POWER_5VCTRL_ENABLE_DCDC)) {
+ if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
+ POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS) {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
+ }
+
+ static int mxs_get_vddd_power_source_off(void)
+ {
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
+ uint32_t tmp;
+
+ tmp = readl(&power_regs->hw_power_vdddctrl);
+ if (tmp & POWER_VDDDCTRL_DISABLE_FET) {
+ if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
+ POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
+ return 1;
+ }
+ }
+
+ if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+ if (!(readl(&power_regs->hw_power_5vctrl) &
+ POWER_5VCTRL_ENABLE_DCDC)) {
+ return 1;
+ }
+ }
+
+ if (!(tmp & POWER_VDDDCTRL_ENABLE_LINREG)) {
+ if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
+ POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW) {
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+
++static int mxs_get_vdda_power_source_off(void)
++{
++ uint32_t tmp;
++
++ tmp = readl(&power_regs->hw_power_vddactrl);
++ if (tmp & POWER_VDDACTRL_DISABLE_FET) {
++ if ((tmp & POWER_VDDACTRL_LINREG_OFFSET_MASK) ==
++ POWER_VDDACTRL_LINREG_OFFSET_0STEPS) {
++ return 1;
++ }
++ }
++
++ if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
++ if (!(readl(&power_regs->hw_power_5vctrl) &
++ POWER_5VCTRL_ENABLE_DCDC)) {
++ return 1;
++ }
++ }
++
++ if (!(tmp & POWER_VDDACTRL_ENABLE_LINREG)) {
++ if ((tmp & POWER_VDDACTRL_LINREG_OFFSET_MASK) ==
++ POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW) {
++ return 1;
++ }
++ }
++
++ return 0;
++}
++
+ struct mxs_vddx_cfg {
+ uint32_t *reg;
+ uint8_t step_mV;
+ uint16_t lowest_mV;
++ uint16_t highest_mV;
+ int (*powered_by_linreg)(void);
+ uint32_t trg_mask;
+ uint32_t bo_irq;
+ uint32_t bo_enirq;
+ uint32_t bo_offset_mask;
+ uint32_t bo_offset_offset;
+ };
+
+ static const struct mxs_vddx_cfg mxs_vddio_cfg = {
+ .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)->
+ hw_power_vddioctrl),
+ .step_mV = 50,
+ .lowest_mV = 2800,
++ .highest_mV = 3600,
+ .powered_by_linreg = mxs_get_vddio_power_source_off,
+ .trg_mask = POWER_VDDIOCTRL_TRG_MASK,
+ .bo_irq = POWER_CTRL_VDDIO_BO_IRQ,
+ .bo_enirq = POWER_CTRL_ENIRQ_VDDIO_BO,
+ .bo_offset_mask = POWER_VDDIOCTRL_BO_OFFSET_MASK,
+ .bo_offset_offset = POWER_VDDIOCTRL_BO_OFFSET_OFFSET,
+ };
+
+ static const struct mxs_vddx_cfg mxs_vddd_cfg = {
+ .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)->
+ hw_power_vdddctrl),
+ .step_mV = 25,
+ .lowest_mV = 800,
++ .highest_mV = 1575,
+ .powered_by_linreg = mxs_get_vddd_power_source_off,
+ .trg_mask = POWER_VDDDCTRL_TRG_MASK,
+ .bo_irq = POWER_CTRL_VDDD_BO_IRQ,
+ .bo_enirq = POWER_CTRL_ENIRQ_VDDD_BO,
+ .bo_offset_mask = POWER_VDDDCTRL_BO_OFFSET_MASK,
+ .bo_offset_offset = POWER_VDDDCTRL_BO_OFFSET_OFFSET,
+ };
+
++static const struct mxs_vddx_cfg mxs_vdda_cfg = {
++ .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)->
++ hw_power_vddactrl),
++ .step_mV = 50,
++ .lowest_mV = 2800,
++ .highest_mV = 3600,
++ .powered_by_linreg = mxs_get_vdda_power_source_off,
++ .trg_mask = POWER_VDDACTRL_TRG_MASK,
++ .bo_irq = POWER_CTRL_VDDA_BO_IRQ,
++ .bo_enirq = POWER_CTRL_ENIRQ_VDDA_BO,
++ .bo_offset_mask = POWER_VDDACTRL_BO_OFFSET_MASK,
++ .bo_offset_offset = POWER_VDDACTRL_BO_OFFSET_OFFSET,
++};
++
++static const struct mxs_vddx_cfg mxs_vddmem_cfg = {
++ .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)->
++ hw_power_vddmemctrl),
++ .step_mV = 25,
++ .lowest_mV = 1100,
++ .highest_mV = 1750,
++ .bo_offset_mask = POWER_VDDMEMCTRL_BO_OFFSET_MASK,
++ .bo_offset_offset = POWER_VDDMEMCTRL_BO_OFFSET_OFFSET,
++};
++
+ static void mxs_power_set_vddx(const struct mxs_vddx_cfg *cfg,
+ uint32_t new_target, uint32_t new_brownout)
+ {
- uint32_t powered_by_linreg = 0;
- int adjust_up, tmp;
+ uint32_t cur_target, diff, bo_int = 0;
- powered_by_linreg = cfg->powered_by_linreg();
++ int powered_by_linreg = 0;
++ int adjust_up;
++
++ if (new_target < cfg->lowest_mV)
++ new_target = cfg->lowest_mV;
++ if (new_target > cfg->highest_mV)
++ new_target = cfg->highest_mV;
+
+ new_brownout = DIV_ROUND(new_target - new_brownout, cfg->step_mV);
+
+ cur_target = readl(cfg->reg);
+ cur_target &= cfg->trg_mask;
+ cur_target *= cfg->step_mV;
+ cur_target += cfg->lowest_mV;
+
+ adjust_up = new_target > cur_target;
- POWER_STS_VDD5V_GT_VDDIO))
++ if (cfg->powered_by_linreg)
++ powered_by_linreg = cfg->powered_by_linreg();
+
+ if (adjust_up) {
+ if (powered_by_linreg) {
+ bo_int = readl(cfg->reg);
+ clrbits_le32(cfg->reg, cfg->bo_enirq);
+ }
+ setbits_le32(cfg->reg, cfg->bo_offset_mask);
+ }
+
+ do {
+ if (abs(new_target - cur_target) > 100) {
+ if (adjust_up)
+ diff = cur_target + 100;
+ else
+ diff = cur_target - 100;
+ } else {
+ diff = new_target;
+ }
+
+ diff -= cfg->lowest_mV;
+ diff /= cfg->step_mV;
+
+ clrsetbits_le32(cfg->reg, cfg->trg_mask, diff);
+
+ if (powered_by_linreg ||
+ (readl(&power_regs->hw_power_sts) &
- else {
- for (;;) {
- tmp = readl(&power_regs->hw_power_sts);
- if (tmp & POWER_STS_DC_OK)
- break;
++ POWER_STS_VDD5V_GT_VDDIO)) {
+ early_delay(500);
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
++ } else {
++ while (!(readl(&power_regs->hw_power_sts) &
++ POWER_STS_DC_OK)) {
++
+ }
+ }
+
+ cur_target = readl(cfg->reg);
+ cur_target &= cfg->trg_mask;
+ cur_target *= cfg->step_mV;
+ cur_target += cfg->lowest_mV;
+ } while (new_target > cur_target);
+
+ if (adjust_up && powered_by_linreg) {
+ writel(cfg->bo_irq, &power_regs->hw_power_ctrl_clr);
+ if (bo_int & cfg->bo_enirq)
+ setbits_le32(cfg->reg, cfg->bo_enirq);
+ }
+
+ clrsetbits_le32(cfg->reg, cfg->bo_offset_mask,
+ new_brownout << cfg->bo_offset_offset);
+ }
+
+ static void mxs_setup_batt_detect(void)
+ {
+ mxs_lradc_init();
+ mxs_lradc_enable_batt_measurement();
+ early_delay(10);
+ }
+
+ void mxs_power_init(void)
+ {
- mxs_power_setup_5v_detect();
+ mxs_power_clock2xtal();
+ mxs_power_clear_auto_restart();
+ mxs_power_set_linreg();
- mxs_setup_batt_detect();
+
- mxs_power_set_vddx(&mxs_vddio_cfg, 3300, 3150);
- mxs_power_set_vddx(&mxs_vddd_cfg, 1500, 1000);
-
++ if (!fixed_batt_supply) {
++ mxs_power_setup_5v_detect();
++ mxs_setup_batt_detect();
++ }
+
+ mxs_power_configure_power_source();
+ mxs_enable_output_rail_protection();
+
-
- writel(POWER_5VCTRL_PWDN_5VBRNOUT, &power_regs->hw_power_5vctrl_set);
-
- early_delay(1000);
++ mxs_power_set_vddx(&mxs_vddio_cfg, VDDIO_VAL, VDDIO_BO_VAL);
++ mxs_power_set_vddx(&mxs_vddd_cfg, VDDD_VAL, VDDD_BO_VAL);
++ mxs_power_set_vddx(&mxs_vdda_cfg, VDDA_VAL, VDDA_BO_VAL);
++#if VDDMEM_VAL > 0
++ mxs_power_set_vddx(&mxs_vddmem_cfg, VDDMEM_VAL, VDDMEM_BO_VAL);
++
++ setbits_le32(&power_regs->hw_power_vddmemctrl,
++ POWER_VDDMEMCTRL_ENABLE_LINREG);
++ early_delay(500);
++ clrbits_le32(&power_regs->hw_power_vddmemctrl,
++ POWER_VDDMEMCTRL_ENABLE_ILIMIT);
++#else
++ clrbits_le32(&power_regs->hw_power_vddmemctrl,
++ POWER_VDDMEMCTRL_ENABLE_LINREG);
++#endif
+ writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
+ POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ |
+ POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_BATT_BO_IRQ |
+ POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
- struct mxs_power_regs *power_regs =
- (struct mxs_power_regs *)MXS_POWER_BASE;
-
++ if (!fixed_batt_supply)
++ writel(POWER_5VCTRL_PWDN_5VBRNOUT,
++ &power_regs->hw_power_5vctrl_set);
+ }
+
+ #ifdef CONFIG_SPL_MX28_PSWITCH_WAIT
+ void mxs_power_wait_pswitch(void)
+ {
+ while (!(readl(&power_regs->hw_power_sts) & POWER_STS_PSWITCH_MASK))
+ ;
+ }
+ #endif
--- /dev/null
-#define timestamp (gd->arch.tbl)
-#define lastdec (gd->arch.lastinc)
+ /*
+ * Freescale i.MX28 timer driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * Based on code from LTIB:
+ * (C) Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+ #include <common.h>
+ #include <asm/io.h>
+ #include <asm/arch/imx-regs.h>
+ #include <asm/arch/sys_proto.h>
+
+ /* Maximum fixed count */
+ #define TIMER_LOAD_VAL 0xffffffff
+
+ DECLARE_GLOBAL_DATA_PTR;
+
-#define MX28_INCREMENTER_HZ 1000
++/* Enable this to verify that the code can correctly
++ * handle the timer rollover
++ */
++/* #define DEBUG_TIMER_WRAP */
++
++#ifdef DEBUG_TIMER_WRAP
++/*
++ * Let the timer wrap 15 seconds after start to catch misbehaving
++ * timer related code early
++ */
++#define TIMER_START (-time_to_tick(15 * CONFIG_SYS_HZ))
++#else
++#define TIMER_START 0UL
++#endif
+
+ /*
+ * This driver uses 1kHz clock source.
+ */
- return tick / (MX28_INCREMENTER_HZ / CONFIG_SYS_HZ);
++#define MXS_INCREMENTER_HZ 1000
+
+ static inline unsigned long tick_to_time(unsigned long tick)
+ {
- return time * (MX28_INCREMENTER_HZ / CONFIG_SYS_HZ);
-}
-
-/* Calculate how many ticks happen in "us" microseconds */
-static inline unsigned long us_to_tick(unsigned long us)
-{
- return (us * MX28_INCREMENTER_HZ) / 1000000;
++ return tick / (MXS_INCREMENTER_HZ / CONFIG_SYS_HZ);
+ }
+
+ static inline unsigned long time_to_tick(unsigned long time)
+ {
- /* Set fixed_count to maximal value */
++ return time * (MXS_INCREMENTER_HZ / CONFIG_SYS_HZ);
+ }
+
+ int timer_init(void)
+ {
+ struct mxs_timrot_regs *timrot_regs =
+ (struct mxs_timrot_regs *)MXS_TIMROT_BASE;
+
+ /* Reset Timers and Rotary Encoder module */
+ mxs_reset_block(&timrot_regs->hw_timrot_rotctrl_reg);
+
+ /* Set fixed_count to 0 */
+ writel(0, &timrot_regs->hw_timrot_fixed_count0);
+
+ /* Set UPDATE bit and 1Khz frequency */
+ writel(TIMROT_TIMCTRLn_UPDATE | TIMROT_TIMCTRLn_RELOAD |
+ TIMROT_TIMCTRLn_SELECT_1KHZ_XTAL,
+ &timrot_regs->hw_timrot_timctrl0);
+
-
++#ifndef DEBUG_TIMER_WRAP
++ /* Set fixed_count to maximum value */
+ writel(TIMER_LOAD_VAL, &timrot_regs->hw_timrot_fixed_count0);
-
- /* Current tick value */
- uint32_t now = readl(&timrot_regs->hw_timrot_running_count0);
-
- if (lastdec >= now) {
- /*
- * normal mode (non roll)
- * move stamp forward with absolut diff ticks
- */
- timestamp += (lastdec - now);
- } else {
- /* we have rollover of decrementer */
- timestamp += (TIMER_LOAD_VAL - now) + lastdec;
-
- }
- lastdec = now;
-
- return timestamp;
++#else
++ /* Set fixed_count so that the counter will wrap after 20 seconds */
++ writel(20 * MXS_INCREMENTER_HZ,
++ &timrot_regs->hw_timrot_fixed_count0);
++ gd->arch.lastinc = TIMER_LOAD_VAL - 20 * MXS_INCREMENTER_HZ;
++#endif
++#ifdef DEBUG_TIMER_WRAP
++ /* Make the usec counter roll over 30 seconds after startup */
++ writel(-30000000, MXS_HW_DIGCTL_MICROSECONDS);
++#endif
++ writel(TIMROT_TIMCTRLn_UPDATE,
++ &timrot_regs->hw_timrot_timctrl0_clr);
++#ifdef DEBUG_TIMER_WRAP
++ /* Set fixed_count to maximal value for subsequent loads */
++ writel(TIMER_LOAD_VAL, &timrot_regs->hw_timrot_fixed_count0);
++#endif
++ gd->arch.timer_rate_hz = MXS_INCREMENTER_HZ;
++ gd->arch.tbl = TIMER_START;
++ gd->arch.tbu = 0;
+ return 0;
+ }
+
++/* Note: This function works correctly for TIMER_LOAD_VAL == 0xffffffff!
++ * The rollover is handled automagically due to the properties of
++ * two's complement arithmetic.
++ * For any other value of TIMER_LOAD_VAL the calculations would have
++ * to be done modulus(TIMER_LOAD_VAL + 1).
++ */
+ unsigned long long get_ticks(void)
+ {
+ struct mxs_timrot_regs *timrot_regs =
+ (struct mxs_timrot_regs *)MXS_TIMROT_BASE;
- return get_timer_masked() - base;
++ /* The timer is counting down, so subtract the register value from
++ * the counter period length to get an incrementing timestamp
++ */
++ unsigned long now = -readl(&timrot_regs->hw_timrot_running_count0);
++ ulong inc = now - gd->arch.lastinc;
++
++ gd->arch.tbl += inc;
++ gd->arch.lastinc = now;
++ /* Since the get_timer() function only uses a 32bit value
++ * it doesn't make sense to return a real 64 bit value here.
++ */
++ return gd->arch.tbl;
+ }
+
+ ulong get_timer_masked(void)
+ {
+ return tick_to_time(get_ticks());
+ }
+
+ ulong get_timer(ulong base)
+ {
-#define MX28_HW_DIGCTL_MICROSECONDS 0x8001c0c0
++ /* NOTE: time_to_tick(base) is required to correctly handle rollover! */
++ return tick_to_time(get_ticks() - time_to_tick(base));
+ }
+
+ /* We use the HW_DIGCTL_MICROSECONDS register for sub-millisecond timer. */
- uint32_t old, new, incr;
- uint32_t counter = 0;
-
- old = readl(MX28_HW_DIGCTL_MICROSECONDS);
-
- while (counter < usec) {
- new = readl(MX28_HW_DIGCTL_MICROSECONDS);
-
- /* Check if the timer wrapped. */
- if (new < old) {
- incr = 0xffffffff - old;
- incr += new;
- } else {
- incr = new - old;
- }
-
- /*
- * Check if we are close to the maximum time and the counter
- * would wrap if incremented. If that's the case, break out
- * from the loop as the requested delay time passed.
++#define MXS_HW_DIGCTL_MICROSECONDS 0x8001c0c0
+
+ void __udelay(unsigned long usec)
+ {
- if (counter + incr < counter)
- break;
-
- counter += incr;
- old = new;
- }
++ uint32_t start = readl(MXS_HW_DIGCTL_MICROSECONDS);
++
++ while (readl(MXS_HW_DIGCTL_MICROSECONDS) - start <= usec)
++ /* use '<=' to guarantee a delay of _at least_
++ * the given number of microseconds.
++ * No need for fancy rollover checks
++ * Two's complement arithmetic applied correctly
++ * does everything that's needed automagically!
+ */
- return MX28_INCREMENTER_HZ;
++ ;
+ }
+
+ ulong get_tbclk(void)
+ {
++ return gd->arch.timer_rate_hz;
+ }
--- /dev/null
- u_boot_spl="spl/u-boot-spl.bin";
- u_boot="u-boot.bin";
+ sources {
- load u_boot_spl > 0x0000;
- load ivt (entry = 0x0014) > 0x8000;
++ u_boot_spl="spl/u-boot-spl";
++ u_boot="u-boot";
+ }
+
+ section (0) {
- load u_boot > 0x40000100;
- load ivt (entry = 0x40000100) > 0x8000;
++ load u_boot_spl;
++ load ivt (entry = u_boot_spl:reset) > 0x8000;
+ hab call 0x8000;
+
++ load u_boot;
++ load ivt (entry = u_boot:reset) > 0x8000;
+ hab call 0x8000;
+ }
COBJS += clock.o
COBJS += sys_info.o
- COBJS-$(CONFIG_SYS_SDRAM_DDR3) += ddr3.o
- COBJS-$(CONFIG_SYS_SDRAM_DDR2) += ddr2.o
COBJS += mem.o
+ COBJS += ddr.o
COBJS += emif4.o
COBJS += board.o
+ COBJS += mux.o
+ COBJS-$(CONFIG_NAND_OMAP_GPMC) += elm.o
+COBJS-$(CONFIG_NAND_AM33XX) += elm.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS) $(COBJS-y) $(SOBJS))
#include <asm/arch/omap.h>
#include <asm/arch/ddr_defs.h>
#include <asm/arch/clock.h>
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/mem.h>
#include <asm/arch/mmc_host_def.h>
- #include <asm/arch/common_def.h>
+ #include <asm/arch/sys_proto.h>
#include <asm/io.h>
- #include <asm/omap_common.h>
+ #include <asm/emif.h>
+ #include <asm/gpio.h>
+ #include <i2c.h>
+ #include <miiphy.h>
-#include <cpsw.h>
++//#include <cpsw.h>
+ #include <asm/errno.h>
+ #include <linux/usb/ch9.h>
+ #include <linux/usb/gadget.h>
+ #include <linux/usb/musb.h>
+ #include <asm/omap_musb.h>
DECLARE_GLOBAL_DATA_PTR;
- /* UART Defines */
- #ifdef CONFIG_SPL_BUILD
- #define UART_RESET (0x1 << 1)
- #define UART_CLK_RUNNING_MASK 0x1
- #define UART_SMART_IDLE_EN (0x1 << 0x3)
- #endif
+ static const struct gpio_bank gpio_bank_am33xx[4] = {
+ { (void *)AM33XX_GPIO0_BASE, METHOD_GPIO_24XX },
+ { (void *)AM33XX_GPIO1_BASE, METHOD_GPIO_24XX },
+ { (void *)AM33XX_GPIO2_BASE, METHOD_GPIO_24XX },
+ { (void *)AM33XX_GPIO3_BASE, METHOD_GPIO_24XX },
+ };
- void reset_cpu(unsigned long ignored)
- {
- /* clear RESET flags */
- writel(~0, PRM_RSTST);
- writel(PRM_RSTCTRL_RESET, PRM_RSTCTRL);
- }
+ const struct gpio_bank *const omap_gpio_bank = gpio_bank_am33xx;
- /*
- * early system init of muxing and clocks.
- */
- void s_init(void)
+#ifdef CONFIG_HW_WATCHDOG
+void hw_watchdog_reset(void)
+{
+ struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE;
+ static int trg __attribute__((section(".data")));
+
+ switch (trg) {
+ case 0:
+ case 1:
+ if (readl(&wdtimer->wdtwwps) & (1 << 4))
+ return;
+ writel(trg ? 0x5555 : 0xaaaa, &wdtimer->wdtwspr);
+ break;
+ case 2:
+ if (readl(&wdtimer->wdtwwps) & (1 << 2))
+ return;
+ /* 10 sec timeout */
+ writel(-32768 * 10, &wdtimer->wdtwldr);
+
+ if (readl(&wdtimer->wdtwwps) & (1 << 0))
+ return;
+ /* prescaler = 1 */
+ writel(0, &wdtimer->wdtwclr);
+ break;
+
+ case 3:
+ case 4:
+ /* enable watchdog */
+ if (readl(&wdtimer->wdtwwps) & (1 << 4))
+ return;
+ writel((trg & 1) ? 0xBBBB : 0x4444, &wdtimer->wdtwspr);
+ break;
+
+ default:
+ /* retrigger watchdog */
+ if (readl(&wdtimer->wdtwwps) & (1 << 3))
+ return;
+
+ writel(trg, &wdtimer->wdtwtgr);
+ trg ^= 0x2;
+ return;
+ }
+ trg++;
+}
+#endif
+
+ #if defined(CONFIG_OMAP_HSMMC) && !defined(CONFIG_SPL_BUILD)
+ int cpu_mmc_init(bd_t *bis)
{
- #ifdef CONFIG_SPL_BUILD
- #ifndef CONFIG_HW_WATCHDOG
- struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE;
-
- /* WDT1 is already running when the bootloader gets control
- * Disable it to avoid "random" resets
- */
- writel(0xAAAA, &wdtimer->wdtwspr);
- while (readl(&wdtimer->wdtwwps) != 0x0)
- ;
- writel(0x5555, &wdtimer->wdtwspr);
- while (readl(&wdtimer->wdtwwps) != 0x0)
- ;
- #endif
- /* Setup the PLLs and the clocks for the peripherals */
- pll_init();
-
- /* UART softreset */
- u32 regVal;
- struct uart_sys *uart_base = (struct uart_sys *)DEFAULT_UART_BASE;
+ int ret;
- enable_uart0_pin_mux();
-
- regVal = readl(&uart_base->uartsyscfg);
- regVal |= UART_RESET;
- writel(regVal, &uart_base->uartsyscfg);
- while ((readl(&uart_base->uartsyssts) &
- UART_CLK_RUNNING_MASK) != UART_CLK_RUNNING_MASK)
- ;
-
- /* Disable smart idle */
- regVal = readl(&uart_base->uartsyscfg);
- regVal |= UART_SMART_IDLE_EN;
- writel(regVal, &uart_base->uartsyscfg);
+ ret = omap_mmc_init(0, 0, 0);
+ if (ret)
+ return ret;
- /* Initialize the Timer */
- timer_init();
+ return omap_mmc_init(1, 0, 0);
+ }
+ #endif
- preloader_console_init();
+ void setup_clocks_for_console(void)
+ {
+ /* Not yet implemented */
+ return;
+ }
- config_ddr();
+ /* AM33XX has two MUSB controllers which can be host or gadget */
+ #if (defined(CONFIG_MUSB_GADGET) || defined(CONFIG_MUSB_HOST)) && \
+ (defined(CONFIG_AM335X_USB0) || defined(CONFIG_AM335X_USB1))
+ static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE;
- /* Enable MMC0 */
- enable_mmc0_pin_mux();
- #endif
- }
+ /* USB 2.0 PHY Control */
+ #define CM_PHY_PWRDN (1 << 0)
+ #define CM_PHY_OTG_PWRDN (1 << 1)
+ #define OTGVDET_EN (1 << 19)
+ #define OTGSESSENDEN (1 << 20)
- #if defined(CONFIG_OMAP_HSMMC) && !defined(CONFIG_SPL_BUILD)
- int board_mmc_init(bd_t *bis)
+ static void am33xx_usb_set_phy_power(u8 on, u32 *reg_addr)
{
- int ret = 0;
- #ifdef CONFIG_OMAP_MMC_DEV_0
- ret = omap_mmc_init(0, 0, 0);
- if (ret)
- printf("Error %d while initializing MMC dev 0\n", ret);
- #endif
- #ifdef CONFIG_OMAP_MMC_DEV_1
- ret = omap_mmc_init(1, 0, 0);
- if (ret)
- printf("Error %d while initializing MMC dev 1\n", ret);
- #endif
- return ret;
+ if (on) {
+ clrsetbits_le32(reg_addr, CM_PHY_PWRDN | CM_PHY_OTG_PWRDN,
+ OTGVDET_EN | OTGSESSENDEN);
+ } else {
+ clrsetbits_le32(reg_addr, 0, CM_PHY_PWRDN | CM_PHY_OTG_PWRDN);
+ }
}
- #endif
- #ifndef CONFIG_SYS_DCACHE_OFF
- void enable_caches(void)
+ static struct musb_hdrc_config musb_config = {
+ .multipoint = 1,
+ .dyn_fifo = 1,
+ .num_eps = 16,
+ .ram_bits = 12,
+ };
+
+ #ifdef CONFIG_AM335X_USB0
+ static void am33xx_otg0_set_phy_power(u8 on)
{
- /* Enable D-cache. I-cache is already enabled in start.S */
- dcache_enable();
+ am33xx_usb_set_phy_power(on, &cdev->usb_ctrl0);
}
+
+ struct omap_musb_board_data otg0_board_data = {
+ .set_phy_power = am33xx_otg0_set_phy_power,
+ };
+
+ static struct musb_hdrc_platform_data otg0_plat = {
+ .mode = CONFIG_AM335X_USB0_MODE,
+ .config = &musb_config,
+ .power = 50,
+ .platform_ops = &musb_dsps_ops,
+ .board_data = &otg0_board_data,
+ };
#endif
- static u32 cortex_rev(void)
+ #ifdef CONFIG_AM335X_USB1
+ static void am33xx_otg1_set_phy_power(u8 on)
{
-
- unsigned int rev;
-
- /* Read Main ID Register (MIDR) */
- asm ("mrc p15, 0, %0, c0, c0, 0" : "=r" (rev));
-
- return rev;
+ am33xx_usb_set_phy_power(on, &cdev->usb_ctrl1);
}
- void omap_rev_string(void)
- {
- u32 omap_rev = cortex_rev();
- u32 omap_variant = (omap_rev & 0xFFFF0000) >> 16;
- u32 major_rev = (omap_rev & 0x00000F00) >> 8;
- u32 minor_rev = (omap_rev & 0x000000F0) >> 4;
+ struct omap_musb_board_data otg1_board_data = {
+ .set_phy_power = am33xx_otg1_set_phy_power,
+ };
+
+ static struct musb_hdrc_platform_data otg1_plat = {
+ .mode = CONFIG_AM335X_USB1_MODE,
+ .config = &musb_config,
+ .power = 50,
+ .platform_ops = &musb_dsps_ops,
+ .board_data = &otg1_board_data,
+ };
+ #endif
+ #endif
- printf("OMAP%x ES%x.%x\n", omap_variant, major_rev,
- minor_rev);
+ int arch_misc_init(void)
+ {
+ #ifdef CONFIG_AM335X_USB0
+ musb_register(&otg0_plat, &otg0_board_data,
+ (void *)AM335X_USB0_OTG_BASE);
+ #endif
+ #ifdef CONFIG_AM335X_USB1
+ musb_register(&otg1_plat, &otg1_board_data,
+ (void *)AM335X_USB1_OTG_BASE);
+ #endif
+ return 0;
}
#define CLK_DIV_MASK 0x1f
#define CLK_DIV2_MASK 0x7f
#define CLK_SEL_SHIFT 0x8
+#define CLK_MODE_MASK 0x7
#define CLK_MODE_SEL 0x7
-#define CLK_MODE_MASK 0xfffffff8
-#define CLK_DIV_SEL 0xFFFFFFE0
-#define CPGMAC0_IDLE 0x30000
-#define DPLL_CLKDCOLDO_GATE_CTRL 0x300
++#define DPLL_CLKDCOLDO_GATE_CTRL 0x300
+
const struct cm_perpll *cmper = (struct cm_perpll *)CM_PER;
const struct cm_wkuppll *cmwkup = (struct cm_wkuppll *)CM_WKUP;
const struct cm_dpll *cmdpll = (struct cm_dpll *)CM_DPLL;
+ const struct cm_rtc *cmrtc = (struct cm_rtc *)CM_RTC;
+#ifdef CONFIG_SPL_BUILD
+#define enable_clk(reg, val) __enable_clk(#reg, ®, val)
+
+static void __enable_clk(const char *name, const void *reg, u32 mask)
+{
+ unsigned long timeout = 10000000;
+
+ writel(mask, reg);
+ while (readl(reg) != mask)
+ /* poor man's timeout, since timers not initialized */
+ if (timeout-- == 0)
+ /* no error message, since console not yet available */
+ break;
+}
+
static void enable_interface_clocks(void)
{
/* Enable all the Interconnect Modules */
- writel(PRCM_MOD_EN, &cmper->l3clkctrl);
- while (readl(&cmper->l3clkctrl) != PRCM_MOD_EN)
- ;
-
- writel(PRCM_MOD_EN, &cmper->l4lsclkctrl);
- while (readl(&cmper->l4lsclkctrl) != PRCM_MOD_EN)
- ;
-
- writel(PRCM_MOD_EN, &cmper->l4fwclkctrl);
- while (readl(&cmper->l4fwclkctrl) != PRCM_MOD_EN)
- ;
-
- writel(PRCM_MOD_EN, &cmwkup->wkl4wkclkctrl);
- while (readl(&cmwkup->wkl4wkclkctrl) != PRCM_MOD_EN)
- ;
-
- writel(PRCM_MOD_EN, &cmper->l3instrclkctrl);
- while (readl(&cmper->l3instrclkctrl) != PRCM_MOD_EN)
- ;
-
- writel(PRCM_MOD_EN, &cmper->l4hsclkctrl);
- while (readl(&cmper->l4hsclkctrl) != PRCM_MOD_EN)
- ;
-
- writel(PRCM_MOD_EN, &cmwkup->wkgpio0clkctrl);
- while (readl(&cmwkup->wkgpio0clkctrl) != PRCM_MOD_EN)
- ;
+ enable_clk(cmper->l3clkctrl, PRCM_MOD_EN);
+ enable_clk(cmper->l4lsclkctrl, PRCM_MOD_EN);
+ enable_clk(cmper->l4fwclkctrl, PRCM_MOD_EN);
+ enable_clk(cmwkup->wkl4wkclkctrl, PRCM_MOD_EN);
+ enable_clk(cmper->l3instrclkctrl, PRCM_MOD_EN);
+ enable_clk(cmper->l4hsclkctrl, PRCM_MOD_EN);
+#ifdef CONFIG_HW_WATCHDOG
+ enable_clk(cmwkup->wdtimer1ctrl, PRCM_MOD_EN);
+#endif
+ /* GPIO0 */
- enable_clk(cmwkup->gpio0clkctrl, PRCM_MOD_EN);
++ enable_clk(cmwkup->wkgpio0clkctrl, PRCM_MOD_EN);
}
/*
/* Select the Master osc 24 MHZ as Timer2 clock source */
writel(0x1, &cmdpll->clktimer2clk);
+#ifdef CONFIG_SYS_NS16550_COM1
/* UART0 */
- writel(PRCM_MOD_EN, &cmwkup->wkup_uart0ctrl);
- while (readl(&cmwkup->wkup_uart0ctrl) != PRCM_MOD_EN)
- ;
-
- /* UART1 */
-#ifdef CONFIG_SERIAL2
- writel(PRCM_MOD_EN, &cmper->uart1clkctrl);
- while (readl(&cmper->uart1clkctrl) != PRCM_MOD_EN)
- ;
-#endif /* CONFIG_SERIAL2 */
-
- /* UART2 */
-#ifdef CONFIG_SERIAL3
- writel(PRCM_MOD_EN, &cmper->uart2clkctrl);
- while (readl(&cmper->uart2clkctrl) != PRCM_MOD_EN)
- ;
-#endif /* CONFIG_SERIAL3 */
-
- /* UART3 */
-#ifdef CONFIG_SERIAL4
- writel(PRCM_MOD_EN, &cmper->uart3clkctrl);
- while (readl(&cmper->uart3clkctrl) != PRCM_MOD_EN)
- ;
-#endif /* CONFIG_SERIAL4 */
-
- /* UART4 */
-#ifdef CONFIG_SERIAL5
- writel(PRCM_MOD_EN, &cmper->uart4clkctrl);
- while (readl(&cmper->uart4clkctrl) != PRCM_MOD_EN)
- ;
-#endif /* CONFIG_SERIAL5 */
-
- /* UART5 */
-#ifdef CONFIG_SERIAL6
- writel(PRCM_MOD_EN, &cmper->uart5clkctrl);
- while (readl(&cmper->uart5clkctrl) != PRCM_MOD_EN)
- ;
-#endif /* CONFIG_SERIAL6 */
-
+ enable_clk(cmwkup->wkup_uart0ctrl, PRCM_MOD_EN);
+#endif
+#ifdef CONFIG_SYS_NS16550_COM2
+ enable_clk(cmper->uart1clkctrl, PRCM_MOD_EN);
+#endif
+#ifdef CONFIG_SYS_NS16550_COM3
+ enable_clk(cmper->uart2clkctrl, PRCM_MOD_EN);
+#endif
+#ifdef CONFIG_SYS_NS16550_COM4
+ enable_clk(cmper->uart3clkctrl, PRCM_MOD_EN);
+#endif
+#ifdef CONFIG_SYS_NS16550_COM5
+ enable_clk(cmper->uart4clkctrl, PRCM_MOD_EN);
+#endif
+#ifdef CONFIG_SYS_NS16550_COM6
+ enable_clk(cmper->uart5clkctrl, PRCM_MOD_EN);
+#endif
/* GPMC */
- writel(PRCM_MOD_EN, &cmper->gpmcclkctrl);
- while (readl(&cmper->gpmcclkctrl) != PRCM_MOD_EN)
- ;
+ enable_clk(cmper->gpmcclkctrl, PRCM_MOD_EN);
/* ELM */
- writel(PRCM_MOD_EN, &cmper->elmclkctrl);
- while (readl(&cmper->elmclkctrl) != PRCM_MOD_EN)
- ;
+ enable_clk(cmper->elmclkctrl, PRCM_MOD_EN);
- /* MMC0*/
- writel(PRCM_MOD_EN, &cmper->mmc0clkctrl);
- while (readl(&cmper->mmc0clkctrl) != PRCM_MOD_EN)
- ;
+ /* Ethernet */
- enable_clk(cmper->cpswclkctrl, PRCM_MOD_EN);
++ enable_clk(cmper->cpswclkstctrl, PRCM_MOD_EN);
+ enable_clk(cmper->cpgmac0clkctrl, PRCM_MOD_EN);
+
+ /* MMC */
+#ifndef CONFIG_OMAP_MMC_DEV_0
+ enable_clk(cmper->mmc0clkctrl, PRCM_MOD_EN);
+#endif
+#ifdef CONFIG_OMAP_MMC_DEV_1
+ enable_clk(cmper->mmc1clkctrl, PRCM_MOD_EN);
+#endif
+ /* LCD */
- enable_clk(cmper->lcdcclkctrl, PRCM_MOD_EN);
++ enable_clk(cmper->lcdclkctrl, PRCM_MOD_EN);
/* i2c0 */
- writel(PRCM_MOD_EN, &cmwkup->wkup_i2c0ctrl);
- while (readl(&cmwkup->wkup_i2c0ctrl) != PRCM_MOD_EN)
- ;
+ enable_clk(cmwkup->wkup_i2c0ctrl, PRCM_MOD_EN);
- /* gpio1 module */
- writel(PRCM_MOD_EN, &cmper->gpio1clkctrl);
- while (readl(&cmper->gpio1clkctrl) != PRCM_MOD_EN)
- ;
-
- /* gpio2 module */
- writel(PRCM_MOD_EN, &cmper->gpio2clkctrl);
- while (readl(&cmper->gpio2clkctrl) != PRCM_MOD_EN)
- ;
-
- /* gpio3 module */
- writel(PRCM_MOD_EN, &cmper->gpio3clkctrl);
- while (readl(&cmper->gpio3clkctrl) != PRCM_MOD_EN)
- ;
+ /* GPIO1-3 */
+ enable_clk(cmper->gpio1clkctrl, PRCM_MOD_EN);
+ enable_clk(cmper->gpio2clkctrl, PRCM_MOD_EN);
+ enable_clk(cmper->gpio3clkctrl, PRCM_MOD_EN);
+
+ /* i2c1 */
- writel(PRCM_MOD_EN, &cmper->i2c1clkctrl);
- while (readl(&cmper->i2c1clkctrl) != PRCM_MOD_EN)
- ;
-
- /* Ethernet */
- writel(PRCM_MOD_EN, &cmper->cpgmac0clkctrl);
- while ((readl(&cmper->cpgmac0clkctrl) & CPGMAC0_IDLE) != PRCM_FUNCTL)
- ;
++ enable_clk(cmper->i2c1clkctrl, PRCM_MOD_EN);
+
+ /* spi0 */
- writel(PRCM_MOD_EN, &cmper->spi0clkctrl);
- while (readl(&cmper->spi0clkctrl) != PRCM_MOD_EN)
- ;
++ enable_clk(cmper->spi0clkctrl, PRCM_MOD_EN);
+
- /* RTC */
- writel(PRCM_MOD_EN, &cmrtc->rtcclkctrl);
- while (readl(&cmrtc->rtcclkctrl) != PRCM_MOD_EN)
- ;
++ /* rtc */
++ enable_clk(cmrtc->rtcclkctrl, PRCM_MOD_EN);
+
- /* MUSB */
- writel(PRCM_MOD_EN, &cmper->usb0clkctrl);
- while (readl(&cmper->usb0clkctrl) != PRCM_MOD_EN)
- ;
++ /* usb0 */
++ enable_clk(cmper->usb0clkctrl, PRCM_MOD_EN);
}
static void mpu_pll_config(void)
while (readl(&cmwkup->idlestdpllper) != ST_DPLL_CLK)
;
+
+ writel(DPLL_CLKDCOLDO_GATE_CTRL, &cmwkup->clkdcoldodpllper);
}
- static void ddr_pll_config(void)
+static void disp_pll_config(void)
+{
+ u32 clkmode, clksel, div_m2;
+
+ clkmode = readl(&cmwkup->clkmoddplldisp);
+ clksel = readl(&cmwkup->clkseldplldisp);
+ div_m2 = readl(&cmwkup->divm2dplldisp);
+
+ /* Set the PLL to bypass Mode */
+ writel(PLL_BYPASS_MODE, &cmwkup->clkmoddplldisp);
+
+ while (!(readl(&cmwkup->idlestdplldisp) & ST_MN_BYPASS))
+ ;
+
+ clksel &= ~CLK_SEL_MASK;
+ clksel |= (DISPPLL_M << CLK_SEL_SHIFT) | DISPPLL_N;
+ writel(clksel, &cmwkup->clkseldplldisp);
+
+ div_m2 &= ~CLK_DIV2_MASK;
+ div_m2 |= DISPPLL_M2;
+ writel(div_m2, &cmwkup->divm2dplldisp);
+
+ clkmode &= ~CLK_MODE_MASK;
+ clkmode |= CLK_MODE_SEL;
+ writel(clkmode, &cmwkup->clkmoddplldisp);
+
+ while (!(readl(&cmwkup->idlestdplldisp) & ST_DPLL_CLK))
+ ;
+}
+
+ void ddr_pll_config(unsigned int ddrpll_m)
{
u32 clkmode, clksel, div_m2;
writel(clkmode, &cmwkup->clkmoddpllddr);
/* Wait till bypass mode is enabled */
- while ((readl(&cmwkup->idlestdpllddr) & ST_MN_BYPASS)
- != ST_MN_BYPASS)
+ while (!(readl(&cmwkup->idlestdpllddr) & ST_MN_BYPASS))
;
- clksel = clksel & (~CLK_SEL_MASK);
- clksel = clksel | ((ddrpll_m << CLK_SEL_SHIFT) | DDRPLL_N);
+ clksel &= ~CLK_SEL_MASK;
- clksel |= (DDRPLL_M << CLK_SEL_SHIFT) | DDRPLL_N;
++ clksel |= (ddrpll_m << CLK_SEL_SHIFT) | DDRPLL_N;
writel(clksel, &cmwkup->clkseldpllddr);
- div_m2 = div_m2 & CLK_DIV_SEL;
- div_m2 = div_m2 | DDRPLL_M2;
+ div_m2 &= ~CLK_DIV_MASK;
+ div_m2 |= DDRPLL_M2;
writel(div_m2, &cmwkup->divm2dpllddr);
- clkmode = (clkmode & CLK_MODE_MASK) | CLK_MODE_SEL;
+ clkmode &= ~CLK_MODE_MASK;
+ clkmode |= CLK_MODE_SEL;
writel(clkmode, &cmwkup->clkmoddpllddr);
/* Wait till dpll is locked */
mpu_pll_config();
core_pll_config();
per_pll_config();
- ddr_pll_config();
+ disp_pll_config();
/* Enable the required interconnect clocks */
enable_interface_clocks();
return mode;
}
- u32 get_sysboot_freq(void)
+ #ifdef CONFIG_DISPLAY_CPUINFO
+#define SYSBOOT_FREQ_SHIFT 22
+#define SYSBOOT_FREQ_MASK (3 << SYSBOOT_FREQ_SHIFT)
+
+static unsigned long bootfreqs[] = {
+ 19200000,
+ 24000000,
+ 25000000,
+ 26000000,
+};
+
- #ifdef CONFIG_DISPLAY_CPUINFO
++static u32 get_sysboot_freq(void)
+{
+ int mode;
+ mode = readl(&cstat->statusreg) & SYSBOOT_FREQ_MASK;
+ return bootfreqs[mode >> SYSBOOT_FREQ_SHIFT];
+}
+
/**
* Print CPU information
*/
struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)MXC_CCM_BASE;
- void set_usboh3_clk(void)
++int clk_enable(struct clk *clk)
+{
- unsigned int reg;
++ int ret = 0;
++
++ if (!clk)
++ return 0;
++ if (clk->usecount++ == 0) {
++ ret = clk->enable(clk);
++ if (ret)
++ clk->usecount--;
++ }
++ return ret;
++}
+
- reg = readl(&mxc_ccm->cscmr1) &
- ~MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK;
- reg |= 1 << MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET;
- writel(reg, &mxc_ccm->cscmr1);
++void clk_disable(struct clk *clk)
++{
++ if (!clk)
++ return;
+
- reg = readl(&mxc_ccm->cscdr1);
- reg &= ~MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK;
- reg &= ~MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK;
- reg |= 4 << MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET;
- reg |= 1 << MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET;
++ if (!(--clk->usecount)) {
++ if (clk->disable)
++ clk->disable(clk);
++ }
++ if (clk->usecount < 0) {
++ printf("%s: clk %p underflow\n", __func__, clk);
++ hang();
++ }
++}
+
- writel(reg, &mxc_ccm->cscdr1);
+ void set_usboh3_clk(void)
+ {
+ clrsetbits_le32(&mxc_ccm->cscmr1,
+ MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK,
+ MXC_CCM_CSCMR1_USBOH3_CLK_SEL(1));
+ clrsetbits_le32(&mxc_ccm->cscdr1,
+ MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK |
+ MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK,
+ MXC_CCM_CSCDR1_USBOH3_CLK_PRED(4) |
+ MXC_CCM_CSCDR1_USBOH3_CLK_PODF(1));
}
void enable_usboh3_clk(unsigned char enable)
{
- unsigned int reg;
+ unsigned int cg = enable ? MXC_CCM_CCGR_CG_ON : MXC_CCM_CCGR_CG_OFF;
- reg = readl(&mxc_ccm->CCGR2);
- if (enable)
- reg |= 1 << MXC_CCM_CCGR2_CG14_OFFSET;
- else
- reg &= ~(1 << MXC_CCM_CCGR2_CG14_OFFSET);
- writel(reg, &mxc_ccm->CCGR2);
+ clrsetbits_le32(&mxc_ccm->CCGR2,
+ MXC_CCM_CCGR2_USBOH3_60M(MXC_CCM_CCGR_CG_MASK),
+ MXC_CCM_CCGR2_USBOH3_60M(cg));
}
- void set_usb_phy1_clk(void)
++void ipu_clk_enable(void)
+{
- unsigned int reg;
++ /* IPU root clock derived from AXI B */
++ clrsetbits_le32(&mxc_ccm->cbcmr, MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_MASK,
++ MXC_CCM_CBCMR_IPU_HSP_CLK_SEL(1));
+
- reg = readl(&mxc_ccm->cscmr1);
- reg &= ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
- writel(reg, &mxc_ccm->cscmr1);
++ setbits_le32(&mxc_ccm->CCGR5,
++ MXC_CCM_CCGR5_IPU(MXC_CCM_CCGR_CG_MASK));
++
++ /* Handshake with IPU when certain clock rates are changed. */
++ clrbits_le32(&mxc_ccm->ccdr, MXC_CCM_CCDR_IPU_HS_MASK);
++
++ /* Handshake with IPU when LPM is entered as its enabled. */
++ clrbits_le32(&mxc_ccm->clpcr, MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS);
+}
+
- void enable_usb_phy1_clk(unsigned char enable)
++void ipu_clk_disable(void)
++{
++ clrbits_le32(&mxc_ccm->CCGR5,
++ MXC_CCM_CCGR5_IPU(MXC_CCM_CCGR_CG_MASK));
++
++ /* Handshake with IPU when certain clock rates are changed. */
++ setbits_le32(&mxc_ccm->ccdr, MXC_CCM_CCDR_IPU_HS_MASK);
++
++ /* Handshake with IPU when LPM is entered as its enabled. */
++ setbits_le32(&mxc_ccm->clpcr, MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS);
++}
++
+ #ifdef CONFIG_I2C_MXC
+ /* i2c_num can be from 0, to 1 for i.MX51 and 2 for i.MX53 */
+ int enable_i2c_clk(unsigned char enable, unsigned i2c_num)
{
- unsigned int reg;
+ u32 mask;
- reg = readl(&mxc_ccm->CCGR4);
+ #if defined(CONFIG_MX51)
+ if (i2c_num > 1)
+ #elif defined(CONFIG_MX53)
+ if (i2c_num > 2)
+ #endif
+ return -EINVAL;
+ mask = MXC_CCM_CCGR_CG_MASK <<
+ (MXC_CCM_CCGR1_I2C1_OFFSET + (i2c_num << 1));
if (enable)
- reg |= 1 << MXC_CCM_CCGR4_CG5_OFFSET;
+ setbits_le32(&mxc_ccm->CCGR1, mask);
else
- reg &= ~(1 << MXC_CCM_CCGR4_CG5_OFFSET);
- writel(reg, &mxc_ccm->CCGR4);
+ clrbits_le32(&mxc_ccm->CCGR1, mask);
+ return 0;
+ }
+ #endif
+
+ void set_usb_phy_clk(void)
+ {
+ clrbits_le32(&mxc_ccm->cscmr1, MXC_CCM_CSCMR1_USB_PHY_CLK_SEL);
}
- void set_usb_phy2_clk(void)
+ #if defined(CONFIG_MX51)
+ void enable_usb_phy1_clk(unsigned char enable)
{
- unsigned int reg;
+ unsigned int cg = enable ? MXC_CCM_CCGR_CG_ON : MXC_CCM_CCGR_CG_OFF;
- reg = readl(&mxc_ccm->cscmr1);
- reg &= ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
- writel(reg, &mxc_ccm->cscmr1);
+ clrsetbits_le32(&mxc_ccm->CCGR2,
+ MXC_CCM_CCGR2_USB_PHY(MXC_CCM_CCGR_CG_MASK),
+ MXC_CCM_CCGR2_USB_PHY(cg));
+ }
+
+ void enable_usb_phy2_clk(unsigned char enable)
+ {
+ /* i.MX51 has a single USB PHY clock, so do nothing here. */
+ }
+ #elif defined(CONFIG_MX53)
+ void enable_usb_phy1_clk(unsigned char enable)
+ {
+ unsigned int cg = enable ? MXC_CCM_CCGR_CG_ON : MXC_CCM_CCGR_CG_OFF;
+
+ clrsetbits_le32(&mxc_ccm->CCGR4,
+ MXC_CCM_CCGR4_USB_PHY1(MXC_CCM_CCGR_CG_MASK),
+ MXC_CCM_CCGR4_USB_PHY1(cg));
}
void enable_usb_phy2_clk(unsigned char enable)
pll_param->mfi, pll_param->mfn,
pll_param->mfd);
/* Switch back */
- writel(ccsr & ~MXC_CCM_CCSR_PLL3_SW_CLK_SEL,
- &mxc_ccm->ccsr);
+ __raw_writel(ccsr & ~0x1, &mxc_ccm->ccsr);
break;
+ #ifdef CONFIG_MX53
case PLL4_CLOCK:
/* Switch to pll4 bypass clock */
- writel(ccsr | MXC_CCM_CCSR_PLL4_SW_CLK_SEL,
- &mxc_ccm->ccsr);
+ __raw_writel(ccsr | 0x20, &mxc_ccm->ccsr);
CHANGE_PLL_SETTINGS(pll, pll_param->pd,
pll_param->mfi, pll_param->mfn,
pll_param->mfd);
/* Switch back */
- writel(ccsr & ~MXC_CCM_CCSR_PLL4_SW_CLK_SEL,
- &mxc_ccm->ccsr);
+ __raw_writel(ccsr & ~0x20, &mxc_ccm->ccsr);
break;
+ #endif
default:
return -EINVAL;
}
setup_pll PLL1_BASE_ADDR, 864
setup_pll_errata PLL1_BASE_ADDR, W_DP_MFN_800_DIT
#else
+#if !defined(CONFIG_SYS_CPU_CLK) || CONFIG_SYS_CPU_CLK == 800
setup_pll PLL1_BASE_ADDR, 800
+#elif CONFIG_SYS_CPU_CLK == 600
+ setup_pll PLL1_BASE_ADDR, 600
+#else
+#error Unsupported CONFIG_SYS_CPU_CLK value
+#endif
#endif
- #if defined(CONFIG_MX51)
setup_pll PLL3_BASE_ADDR, 665
/* Switch peripheral to PLL 3 */
setup_pll PLL2_BASE_ADDR, 665
/* Switch peripheral to PLL2 */
- ldr r0, =CCM_BASE_ADDR
ldr r1, =0x19239145
str r1, [r0, #CLKCTL_CBCDR]
- ldr r1, =0x000020C0
- orr r1,r1,#CONFIG_SYS_DDR_CLKSEL
- str r1, [r0, #CLKCTL_CBCMR]
- #elif defined(CONFIG_TX53)
- setup_pll PLL3_BASE_ADDR, 400
-
- /* Switch peripheral to PLL 3 */
- ldr r1, [r0, #CLKCTL_CBCMR]
- bic r1, #(0x3 << 12)
- orr r1, r1, #(1 << 12)
+ ldr r1, =0x000020C0 | CONFIG_SYS_DDR_CLKSEL
str r1, [r0, #CLKCTL_CBCMR]
- ldr r1, [r0, #CLKCTL_CBCDR]
- orr r1, r1, #(1 << 25)
- str r1, [r0, #CLKCTL_CBCDR]
- 1:
- /* make sure change is effective */
- ldr r1, [r0, #CLKCTL_CDHIPR]
- tst r1, #0x7f
- bne 1b
- #if CONFIG_SYS_SDRAM_CLK == 400
- setup_pll PLL2_BASE_ADDR, 400
- #elif CONFIG_SYS_SDRAM_CLK == 333
- setup_pll PLL2_BASE_ADDR, 333
- #else
- #error Unsupported CONFIG_SYS_SDRAM_CLK
- #endif
- /* Switch peripheral to PLL2 */
- ldr r0, =CCM_BASE_ADDR
- ldr r1, [r0, #CLKCTL_CBCDR]
- bic r1, #(1 << 25)
- str r1, [r0, #CLKCTL_CBCDR]
-
- ldr r1, [r0, #CLKCTL_CBCMR]
- bic r1, #(3 << 12)
- orr r1, #(2 << 12)
- str r1, [r0, #CLKCTL_CBCMR]
-
- /* make sure change is effective */
- 1:
- ldr r1, [r0, #CLKCTL_CDHIPR]
- cmp r1, #0x0
- bne 1b
- #endif
setup_pll PLL3_BASE_ADDR, 216
/* Set the platform clock dividers */
str r1, [r0, #CLKCTL_CSCMR1]
ldr r1, =0x00C30321
str r1, [r0, #CLKCTL_CSCDR1]
- #elif defined(CONFIG_MX53)
+ /* make sure divider effective */
+ 1: ldr r1, [r0, #CLKCTL_CDHIPR]
+ cmp r1, #0x0
+ bne 1b
+
+ str r4, [r0, #CLKCTL_CCDR]
+
+ /* for cko - for ARM div by 8 */
+ mov r1, #0x000A0000
+ add r1, r1, #0x00000F0
+ str r1, [r0, #CLKCTL_CCOSR]
+ #else /* CONFIG_MX53 */
+ ldr r0, =CCM_BASE_ADDR
+
+ /* Gate of clocks to the peripherals first */
+ ldr r1, =0x3FFFFFFF
+ str r1, [r0, #CLKCTL_CCGR0]
+ str r4, [r0, #CLKCTL_CCGR1]
+ str r4, [r0, #CLKCTL_CCGR2]
+ str r4, [r0, #CLKCTL_CCGR3]
+ str r4, [r0, #CLKCTL_CCGR7]
+ ldr r1, =0x00030000
+ str r1, [r0, #CLKCTL_CCGR4]
+ ldr r1, =0x00FFF030
+ str r1, [r0, #CLKCTL_CCGR5]
+ ldr r1, =0x0F00030F
+ str r1, [r0, #CLKCTL_CCGR6]
+
+ /* Switch ARM to step clock */
+ mov r1, #0x4
+ str r1, [r0, #CLKCTL_CCSR]
+
+ setup_pll PLL1_BASE_ADDR, 800
+
+ setup_pll PLL3_BASE_ADDR, 400
+
+ /* Switch peripheral to PLL3 */
+ ldr r0, =CCM_BASE_ADDR
+ ldr r1, =0x00015154
+ str r1, [r0, #CLKCTL_CBCMR]
+ ldr r1, =0x02888945
+ orr r1, r1, #(1 << 16)
+ str r1, [r0, #CLKCTL_CBCDR]
+ /* make sure change is effective */
+ 1: ldr r1, [r0, #CLKCTL_CDHIPR]
+ cmp r1, #0x0
+ bne 1b
+
+ setup_pll PLL2_BASE_ADDR, 400
+
/* Switch peripheral to PLL2 */
- ldr r0, =CCM_BASE_ADDR
ldr r1, =0x00808145
orr r1, r1, #(2 << 10)
orr r1, r1, #(0 << 16)
ldr r1, =0x00016154
str r1, [r0, #CLKCTL_CBCMR]
- /* Change uart clk parent to pll2*/
+
+ /*change uart clk parent to pll2*/
ldr r1, [r0, #CLKCTL_CSCMR1]
- and r1, r1, #0xfcffffff
- orr r1, r1, #0x01000000
+ bic r1, #(0x3 << 24)
+ orr r1, r1, #(0x1 << 24)
str r1, [r0, #CLKCTL_CSCMR1]
+
+ /* make sure change is effective */
+ 1: ldr r1, [r0, #CLKCTL_CDHIPR]
+ cmp r1, #0x0
+ bne 1b
+
+ setup_pll PLL3_BASE_ADDR, 216
+
+ setup_pll PLL4_BASE_ADDR, 455
+
+ /* Set the platform clock dividers */
+ ldr r0, =ARM_BASE_ADDR
+ ldr r1, =0x00000124
+ str r1, [r0, #0x14]
+
+ ldr r0, =CCM_BASE_ADDR
+ mov r1, #0
+ str r1, [r0, #CLKCTL_CACRR]
+
+ /* Switch ARM back to PLL 1. */
+ mov r1, #0x0
+ str r1, [r0, #CLKCTL_CCSR]
+
+ /* make uart div=6 */
ldr r1, [r0, #CLKCTL_CSCDR1]
- and r1, r1, #0xffffffc0
+ bic r1, #(0x3f << 0)
orr r1, r1, #0x0a
str r1, [r0, #CLKCTL_CSCDR1]
- #endif
+ /* make sure divider effective */
+1: ldr r1, [r0, #CLKCTL_CDHIPR]
+ cmp r1, #0x0
+ bne 1b
- #endif
- mov r1, #0x0
- str r1, [r0, #CLKCTL_CCDR]
- /* for cko - for ARM div by 8 */
- mov r1, #0x000A0000
- add r1, r1, #0x00000F0
- str r1, [r0, #CLKCTL_CCOSR]
+ /* Restore the default values in the Gate registers */
+ ldr r1, =0xFFFFFFFF
+ str r1, [r0, #CLKCTL_CCGR0]
+ str r1, [r0, #CLKCTL_CCGR1]
+ str r1, [r0, #CLKCTL_CCGR2]
+ str r1, [r0, #CLKCTL_CCGR3]
+ str r1, [r0, #CLKCTL_CCGR4]
+ str r1, [r0, #CLKCTL_CCGR5]
+ str r1, [r0, #CLKCTL_CCGR6]
+ str r1, [r0, #CLKCTL_CCGR7]
+
+ mov r1, #0x00000
+ str r1, [r0, #CLKCTL_CCDR]
+
+ /* for cko - for ARM div by 8 */
+ mov r1, #0x000A0000
+ add r1, r1, #0x00000F0
+ str r1, [r0, #CLKCTL_CCOSR]
+
+ #endif /* CONFIG_MX53 */
.endm
.macro setup_wdog
ENDPROC(lowlevel_init)
/* Board level setting value */
- W_DP_OP_864: .word DP_OP_864
- W_DP_MFD_864: .word DP_MFD_864
- W_DP_MFN_864: .word DP_MFN_864
- W_DP_MFN_800_DIT: .word DP_MFN_800_DIT
- W_DP_OP_800: .word DP_OP_800
- W_DP_MFD_800: .word DP_MFD_800
- W_DP_MFN_800: .word DP_MFN_800
- W_DP_OP_665: .word DP_OP_665
- W_DP_MFD_665: .word DP_MFD_665
- W_DP_MFN_665: .word DP_MFN_665
- W_DP_OP_600: .word DP_OP_600
- W_DP_MFD_600: .word DP_MFD_600
- W_DP_MFN_600: .word DP_MFN_600
- W_DP_OP_400: .word DP_OP_400
- W_DP_MFD_400: .word DP_MFD_400
- W_DP_MFN_400: .word DP_MFN_400
- W_DP_OP_333: .word DP_OP_333
- W_DP_MFD_333: .word DP_MFD_333
- W_DP_MFN_333: .word DP_MFN_333
- W_DP_OP_216: .word DP_OP_216
- W_DP_MFD_216: .word DP_MFD_216
- W_DP_MFN_216: .word DP_MFN_216
+ #if defined(CONFIG_MX51_PLL_ERRATA)
+ W_DP_864: .word DP_OP_864
+ .word DP_MFD_864
+ .word DP_MFN_864
+ W_DP_MFN_800_DIT: .word DP_MFN_800_DIT
+ #else
+ W_DP_800: .word DP_OP_800
+ .word DP_MFD_800
+ .word DP_MFN_800
+ #endif
+ #if defined(CONFIG_MX51)
+ W_DP_665: .word DP_OP_665
+ .word DP_MFD_665
+ .word DP_MFN_665
++W_DP_600: .word DP_OP_600
++ .word DP_MFD_600
++ .word DP_MFN_600
+ #endif
+ W_DP_216: .word DP_OP_216
+ .word DP_MFD_216
+ .word DP_MFN_216
+ W_DP_400: .word DP_OP_400
+ .word DP_MFD_400
+ .word DP_MFN_400
+ W_DP_455: .word DP_OP_455
+ .word DP_MFD_455
+ .word DP_MFN_455
return system_rev;
}
+ #ifndef CONFIG_SYS_DCACHE_OFF
+ void enable_caches(void)
+ {
+ /* Enable D-cache. I-cache is already enabled in start.S */
+ dcache_enable();
+ }
+ #endif
+
#if defined(CONFIG_FEC_MXC)
-void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
+static void __imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
{
int i;
struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE;
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
++//#define DEBUG
#include <common.h>
#include <asm/io.h>
#include <asm/arch/sys_proto.h>
enum pll_clocks {
-- PLL_SYS, /* System PLL */
-- PLL_BUS, /* System Bus PLL*/
-- PLL_USBOTG, /* OTG USB PLL */
-- PLL_ENET, /* ENET PLL */
++ PLL_ARM, /* PLL1: ARM PLL */
++ PLL_BUS, /* PLL2: System Bus PLL*/
++ PLL_USBOTG, /* PLL3: OTG USB PLL */
++ PLL_AUDIO, /* PLL4: Audio PLL */
++ PLL_VIDEO, /* PLL5: Video PLL */
++ PLL_ENET, /* PLL6: ENET PLL */
++ PLL_USB2, /* PLL7: USB2 PLL */
++ PLL_MLB, /* PLL8: MLB PLL */
};
--struct mxc_ccm_reg *imx_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
++struct mxc_ccm_reg *const imx_ccm = (void *)CCM_BASE_ADDR;
++struct anatop_regs *const anatop = (void *)ANATOP_BASE_ADDR;
++
++int clk_enable(struct clk *clk)
++{
++ int ret = 0;
++
++ if (!clk)
++ return 0;
++ if (clk->usecount == 0) {
++debug("%s: Enabling %s clock\n", __func__, clk->name);
++ ret = clk->enable(clk);
++ if (ret)
++ return ret;
++ clk->usecount++;
++ }
++ assert(clk->usecount > 0);
++ return ret;
++}
++
++void clk_disable(struct clk *clk)
++{
++ if (!clk)
++ return;
++
++ assert(clk->usecount > 0);
++ if (!(--clk->usecount)) {
++ if (clk->disable) {
++debug("%s: Disabling %s clock\n", __func__, clk->name);
++ clk->disable(clk);
++ }
++ }
++}
void enable_usboh3_clk(unsigned char enable)
{
u32 div;
switch (pll) {
-- case PLL_SYS:
-- div = __raw_readl(&imx_ccm->analog_pll_sys);
-- div &= BM_ANADIG_PLL_SYS_DIV_SELECT;
--
-- return infreq * (div >> 1);
++ case PLL_ARM:
++ div = __raw_readl(&anatop->pll_arm);
++ if (div & BM_ANADIG_PLL_ARM_BYPASS)
++ /* Assume the bypass clock is always derived from OSC */
++ return infreq;
++ div &= BM_ANADIG_PLL_ARM_DIV_SELECT;
++
++ return infreq * div / 2;
case PLL_BUS:
-- div = __raw_readl(&imx_ccm->analog_pll_528);
-- div &= BM_ANADIG_PLL_528_DIV_SELECT;
++ div = __raw_readl(&anatop->pll_528);
++ if (div & BM_ANADIG_PLL_SYS_BYPASS)
++ return infreq;
++ div &= BM_ANADIG_PLL_SYS_DIV_SELECT;
-- return infreq * (20 + (div << 1));
++ return infreq * (20 + div * 2);
case PLL_USBOTG:
-- div = __raw_readl(&imx_ccm->analog_usb1_pll_480_ctrl);
++ div = __raw_readl(&anatop->usb1_pll_480_ctrl);
++ if (div & BM_ANADIG_USB1_PLL_480_CTRL_BYPASS)
++ return infreq;
div &= BM_ANADIG_USB1_PLL_480_CTRL_DIV_SELECT;
-- return infreq * (20 + (div << 1));
++ return infreq * (20 + div * 2);
++ case PLL_AUDIO:
++ div = __raw_readl(&anatop->pll_audio);
++ if (div & BM_ANADIG_PLL_AUDIO_BYPASS)
++ return infreq;
++ div &= BM_ANADIG_PLL_AUDIO_DIV_SELECT;
++
++ return infreq * div;
++ case PLL_VIDEO:
++ div = __raw_readl(&anatop->pll_video);
++ if (div & BM_ANADIG_PLL_VIDEO_BYPASS)
++ return infreq;
++ div &= BM_ANADIG_PLL_VIDEO_DIV_SELECT;
++
++ return infreq * div;
case PLL_ENET:
-- div = __raw_readl(&imx_ccm->analog_pll_enet);
++ div = __raw_readl(&anatop->pll_enet);
++ if (div & BM_ANADIG_PLL_ENET_BYPASS)
++ return infreq;
div &= BM_ANADIG_PLL_ENET_DIV_SELECT;
-- return (div == 3 ? 125000000 : 25000000 * (div << 1));
-- default:
++ return (div == 3 ? 125000000 : 25000000 * div * 2);
++ case PLL_USB2:
++ div = __raw_readl(&anatop->usb2_pll_480_ctrl);
++ if (div & BM_ANADIG_USB2_PLL_480_CTRL_BYPASS)
++ return infreq;
++ div &= BM_ANADIG_USB2_PLL_480_CTRL_DIV_SELECT;
++
++ return infreq * (20 + div * 2);
++ case PLL_MLB:
++ div = __raw_readl(&anatop->pll_mlb);
++ if (div & BM_ANADIG_PLL_MLB_BYPASS)
++ return infreq;
++ /* unknown external clock provided on MLB_CLK pin */
return 0;
}
-- /* NOTREACHED */
++ return 0;
}
static u32 get_mcu_main_clk(void)
reg = __raw_readl(&imx_ccm->cacrr);
reg &= MXC_CCM_CACRR_ARM_PODF_MASK;
reg >>= MXC_CCM_CACRR_ARM_PODF_OFFSET;
- freq = decode_pll(PLL_SYS, CONFIG_SYS_MX6_HCLK);
- freq = decode_pll(PLL_SYS, MXC_HCLK);
++ freq = decode_pll(PLL_ARM, MXC_HCLK);
return freq / (reg + 1);
}
break;
case 1:
case 2:
- freq = CONFIG_SYS_MX6_HCLK;
- break;
- default:
+ freq = MXC_HCLK;
break;
- default:
- break;
}
} else {
reg = __raw_readl(&imx_ccm->cbcmr);
case 3:
freq = PLL2_PFD2_DIV_FREQ;
break;
-- default:
-- break;
}
}
return root_freq / (emi_slow_pof + 1);
}
++static u32 get_nfc_clk(void)
++{
++ u32 cs2cdr = __raw_readl(&imx_ccm->cs2cdr);
++ u32 podf = (cs2cdr & MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK) >> MXC_CCM_CS2CDR_ENFC_CLK_PODF_OFFSET;
++ u32 pred = (cs2cdr & MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK) >> MXC_CCM_CS2CDR_ENFC_CLK_PRED_OFFSET;
++ int nfc_clk_sel = (cs2cdr & MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK) >>
++ MXC_CCM_CS2CDR_ENFC_CLK_SEL_OFFSET;
++ u32 root_freq;
++
++ switch (nfc_clk_sel) {
++ case 0:
++ root_freq = PLL2_PFD0_FREQ;
++ break;
++ case 1:
++ root_freq = decode_pll(PLL_BUS, MXC_HCLK);
++ break;
++ case 2:
++ root_freq = decode_pll(PLL_USBOTG, MXC_HCLK);
++ break;
++ case 3:
++ root_freq = PLL2_PFD2_FREQ;
++ break;
++ }
++
++ return root_freq / (pred + 1) / (podf + 1);
++}
++
static u32 get_mmdc_ch0_clk(void)
{
u32 cbcdr = __raw_readl(&imx_ccm->cbcdr);
int enable_sata_clock(void)
{
-- u32 reg = 0;
++ u32 reg;
s32 timeout = 100000;
-- struct mxc_ccm_reg *const imx_ccm
-- = (struct mxc_ccm_reg *) CCM_BASE_ADDR;
/* Enable sata clock */
reg = readl(&imx_ccm->CCGR5); /* CCGR5 */
writel(reg, &imx_ccm->CCGR5);
/* Enable PLLs */
-- reg = readl(&imx_ccm->analog_pll_enet);
-- reg &= ~BM_ANADIG_PLL_SYS_POWERDOWN;
-- writel(reg, &imx_ccm->analog_pll_enet);
-- reg |= BM_ANADIG_PLL_SYS_ENABLE;
++ reg = readl(&anatop->pll_enet);
++ reg &= ~BM_ANADIG_PLL_ENET_POWERDOWN;
++ writel(reg, &anatop->pll_enet);
++ reg |= BM_ANADIG_PLL_ENET_ENABLE;
while (timeout--) {
-- if (readl(&imx_ccm->analog_pll_enet) & BM_ANADIG_PLL_SYS_LOCK)
++ if (readl(&anatop->pll_enet) & BM_ANADIG_PLL_ENET_LOCK)
break;
}
if (timeout <= 0)
return -EIO;
-- reg &= ~BM_ANADIG_PLL_SYS_BYPASS;
-- writel(reg, &imx_ccm->analog_pll_enet);
++ reg &= ~BM_ANADIG_PLL_ENET_BYPASS;
++ writel(reg, &anatop->pll_enet);
reg |= BM_ANADIG_PLL_ENET_ENABLE_SATA;
-- writel(reg, &imx_ccm->analog_pll_enet);
++ writel(reg, &anatop->pll_enet);
return 0 ;
}
++void ipu_clk_enable(void)
++{
++ u32 reg = readl(&imx_ccm->CCGR3);
++ reg |= MXC_CCM_CCGR3_CG0_MASK;
++ writel(reg, &imx_ccm->CCGR3);
++}
++
++void ipu_clk_disable(void)
++{
++ u32 reg = readl(&imx_ccm->CCGR3);
++ reg &= ~MXC_CCM_CCGR3_CG0_MASK;
++ writel(reg, &imx_ccm->CCGR3);
++}
++
++void ocotp_clk_enable(void)
++{
++ u32 reg = readl(&imx_ccm->CCGR2);
++ reg |= MXC_CCM_CCGR2_CG6_MASK;
++ writel(reg, &imx_ccm->CCGR2);
++}
++
++void ocotp_clk_disable(void)
++{
++ u32 reg = readl(&imx_ccm->CCGR2);
++ reg &= ~MXC_CCM_CCGR2_CG6_MASK;
++ writel(reg, &imx_ccm->CCGR2);
++}
++
unsigned int mxc_get_clock(enum mxc_clock clk)
{
switch (clk) {
return get_usdhc_clk(3);
case MXC_SATA_CLK:
return get_ahb_clk();
-- default:
-- break;
++ case MXC_NFC_CLK:
++ return get_nfc_clk();
}
return -1;
}
++static inline int gcd(int m, int n)
++{
++ int t;
++ while (m > 0) {
++ if (n > m) {
++ t = m;
++ m = n;
++ n = t;
++ } /* swap */
++ m -= n;
++ }
++ return n;
++}
++
++/* Config CPU clock */
++static int config_core_clk(u32 ref, u32 freq)
++{
++ int d;
++ int div = 0;
++ int mul = 0;
++ int min_err = ~0 >> 1;
++ u32 reg;
++
++ if (freq / ref > 108 || freq / ref * 8 < 54) {
++ return -EINVAL;
++ }
++
++ for (d = 1; d < 8; d++) {
++ int m = (freq + (ref - 1)) / ref;
++ unsigned long f;
++ int err;
++
++ if (m > 108 || m < 54)
++ return -EINVAL;
++
++ f = ref * m / d;
++ while (f > freq) {
++ if (--m < 54)
++ return -EINVAL;
++ f = ref * m / d;
++ }
++ err = freq - f;
++ if (err == 0)
++ break;
++ if (err < 0)
++ return -EINVAL;
++ if (err < min_err) {
++ mul = m;
++ div = d;
++ }
++ }
++ printf("Setting M=%3u D=%2u for %u.%03uMHz (actual: %u.%03uMHz)\n",
++ mul, div, freq / 1000000, freq / 1000 % 1000,
++ ref * mul / div / 1000000, ref * mul / div / 1000 % 1000);
++
++ reg = readl(&anatop->pll_arm);
++ printf("anadig_pll_arm=%08x -> %08x\n",
++ reg, (reg & ~0x7f) | mul);
++#if 0
++ writel(div - 1, &imx_ccm->caccr);
++ reg &= 0x7f;
++ writel(reg | mul, &anatop->pll_arm);
++#endif
++ return 0;
++}
++
/*
-- * Dump some core clockes.
++ * This function assumes the expected core clock has to be changed by
++ * modifying the PLL. This is NOT true always but for most of the times,
++ * it is. So it assumes the PLL output freq is the same as the expected
++ * core clock (presc=1) unless the core clock is less than PLL_FREQ_MIN.
++ * In the latter case, it will try to increase the presc value until
++ * (presc*core_clk) is greater than PLL_FREQ_MIN. It then makes call to
++ * calc_pll_params() and obtains the values of PD, MFI,MFN, MFD based
++ * on the targeted PLL and reference input clock to the PLL. Lastly,
++ * it sets the register based on these values along with the dividers.
++ * Note 1) There is no value checking for the passed-in divider values
++ * so the caller has to make sure those values are sensible.
++ * 2) Also adjust the NFC divider such that the NFC clock doesn't
++ * exceed NFC_CLK_MAX.
++ * 3) IPU HSP clock is independent of AHB clock. Even it can go up to
++ * 177MHz for higher voltage, this function fixes the max to 133MHz.
++ * 4) This function should not have allowed diag_printf() calls since
++ * the serial driver has been stoped. But leave then here to allow
++ * easy debugging by NOT calling the cyg_hal_plf_serial_stop().
*/
++int mxc_set_clock(u32 ref, u32 freq, enum mxc_clock clk)
++{
++ freq *= 1000000;
++
++ switch (clk) {
++ case MXC_ARM_CLK:
++ if (config_core_clk(ref, freq))
++ return -EINVAL;
++ break;
++#if 0
++ case MXC_PER_CLK:
++ if (config_periph_clk(ref, freq))
++ return -EINVAL;
++ break;
++ case MXC_DDR_CLK:
++ if (config_ddr_clk(freq))
++ return -EINVAL;
++ break;
++ case MXC_NFC_CLK:
++ if (config_nfc_clk(freq))
++ return -EINVAL;
++ break;
++#endif
++ default:
++ printf("Warning: Unsupported or invalid clock type: %d\n",
++ clk);
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++/*
++ * Dump some core clocks.
++ */
++#define print_pll(pll) printf("%-12s %4d.%03d MHz\n", #pll, \
++ decode_pll(pll, MXC_HCLK) / 1000000, \
++ decode_pll(pll, MXC_HCLK) / 1000 % 1000)
++
++#define MXC_IPG_PER_CLK MXC_IPG_PERCLK
++#define print_clk(clk) printf("%-12s %4d.%03d MHz\n", #clk, \
++ mxc_get_clock(MXC_##clk##_CLK) / 1000000, \
++ mxc_get_clock(MXC_##clk##_CLK) / 1000 % 1000)
++
int do_mx6_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
-- u32 freq;
- freq = decode_pll(PLL_SYS, CONFIG_SYS_MX6_HCLK);
- freq = decode_pll(PLL_SYS, MXC_HCLK);
-- printf("PLL_SYS %8d MHz\n", freq / 1000000);
- freq = decode_pll(PLL_BUS, CONFIG_SYS_MX6_HCLK);
- freq = decode_pll(PLL_BUS, MXC_HCLK);
-- printf("PLL_BUS %8d MHz\n", freq / 1000000);
- freq = decode_pll(PLL_USBOTG, CONFIG_SYS_MX6_HCLK);
- freq = decode_pll(PLL_USBOTG, MXC_HCLK);
-- printf("PLL_OTG %8d MHz\n", freq / 1000000);
- freq = decode_pll(PLL_ENET, CONFIG_SYS_MX6_HCLK);
- freq = decode_pll(PLL_ENET, MXC_HCLK);
-- printf("PLL_NET %8d MHz\n", freq / 1000000);
++ print_pll(PLL_ARM);
++ print_pll(PLL_BUS);
++ print_pll(PLL_USBOTG);
++ print_pll(PLL_AUDIO);
++ print_pll(PLL_VIDEO);
++ print_pll(PLL_ENET);
++ print_pll(PLL_USB2);
printf("\n");
-- printf("IPG %8d kHz\n", mxc_get_clock(MXC_IPG_CLK) / 1000);
-- printf("UART %8d kHz\n", mxc_get_clock(MXC_UART_CLK) / 1000);
-#ifdef CONFIG_MXC_SPI
-- printf("CSPI %8d kHz\n", mxc_get_clock(MXC_CSPI_CLK) / 1000);
-#endif
-- printf("AHB %8d kHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000);
-- printf("AXI %8d kHz\n", mxc_get_clock(MXC_AXI_CLK) / 1000);
-- printf("DDR %8d kHz\n", mxc_get_clock(MXC_DDR_CLK) / 1000);
-- printf("USDHC1 %8d kHz\n", mxc_get_clock(MXC_ESDHC_CLK) / 1000);
-- printf("USDHC2 %8d kHz\n", mxc_get_clock(MXC_ESDHC2_CLK) / 1000);
-- printf("USDHC3 %8d kHz\n", mxc_get_clock(MXC_ESDHC3_CLK) / 1000);
-- printf("USDHC4 %8d kHz\n", mxc_get_clock(MXC_ESDHC4_CLK) / 1000);
-- printf("EMI SLOW %8d kHz\n", mxc_get_clock(MXC_EMI_SLOW_CLK) / 1000);
-- printf("IPG PERCLK %8d kHz\n", mxc_get_clock(MXC_IPG_PERCLK) / 1000);
++ print_clk(IPG);
++ print_clk(UART);
++ print_clk(CSPI);
++ print_clk(AHB);
++ print_clk(AXI);
++ print_clk(DDR);
++ print_clk(ESDHC);
++ print_clk(ESDHC2);
++ print_clk(ESDHC3);
++ print_clk(ESDHC4);
++ print_clk(EMI_SLOW);
++ print_clk(NFC);
++ print_clk(IPG_PER);
++ print_clk(ARM);
return 0;
}
#include <asm/errno.h>
#include <asm/io.h>
#include <asm/arch/imx-regs.h>
++#include <asm/arch/crm_regs.h>
++#include <asm/arch/regs-ocotp.h>
#include <asm/arch/clock.h>
++#include <asm/arch/dma.h>
#include <asm/arch/sys_proto.h>
+ #include <asm/imx-common/boot_mode.h>
++#ifdef CONFIG_VIDEO_IPUV3
++#include <ipu.h>
++#endif
++
++DECLARE_GLOBAL_DATA_PTR;
++
++#define TEMPERATURE_MIN -40
++#define TEMPERATURE_HOT 80
++#define TEMPERATURE_MAX 125
++#define REG_VALUE_TO_CEL(ratio, raw) ((raw_n40c - raw) * 100 / ratio - 40)
++
++#define __data __attribute__((section(".data")))
+
+ struct scu_regs {
+ u32 ctrl;
+ u32 config;
+ u32 status;
+ u32 invalidate;
+ u32 fpga_rev;
+ };
+
++#ifdef CONFIG_HW_WATCHDOG
++#define wdog_base ((void *)WDOG1_BASE_ADDR)
++#define WDOG_WCR 0x00
++#define WCR_WDE (1 << 2)
++#define WDOG_WSR 0x02
++
++void hw_watchdog_reset(void)
++{
++ if (readw(wdog_base + WDOG_WCR) & WCR_WDE) {
++ static u16 toggle = 0xaaaa;
++ static int first = 1;
++
++ if (first) {
++ printf("Watchdog active\n");
++ first = 0;
++ }
++ writew(toggle, wdog_base + WDOG_WSR);
++ toggle ^= 0xffff;
++ }
++}
++#endif
+
u32 get_cpu_rev(void)
{
struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
* Possible values are from 0.725V to 1.450V in steps of
* 0.025V (25mV).
*/
--void set_vddsoc(u32 mv)
++static void set_vddsoc(u32 mv)
{
struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
u32 val, reg = readl(&anatop->reg_core);
writel(reg, &anatop->reg_core);
}
++static u32 __data thermal_calib;
++
++int read_cpu_temperature(void)
++{
++ unsigned int reg, tmp, i;
++ unsigned int raw_25c, raw_hot, hot_temp, raw_n40c, ratio;
++ int temperature;
++ struct anatop_regs *const anatop = (void *)ANATOP_BASE_ADDR;
++ struct mx6_ocotp_regs *const ocotp_regs = (void *)OCOTP_BASE_ADDR;
++
++ if (!thermal_calib) {
++ ocotp_clk_enable();
++ writel(1, &ocotp_regs->hw_ocotp_read_ctrl);
++ thermal_calib = readl(&ocotp_regs->hw_ocotp_ana1);
++ writel(0, &ocotp_regs->hw_ocotp_read_ctrl);
++ ocotp_clk_disable();
++ }
++
++ if (thermal_calib == 0 || thermal_calib == 0xffffffff)
++ return TEMPERATURE_MIN;
++
++ /* Fuse data layout:
++ * [31:20] sensor value @ 25C
++ * [19:8] sensor value of hot
++ * [7:0] hot temperature value */
++ raw_25c = thermal_calib >> 20;
++ raw_hot = (thermal_calib & 0xfff00) >> 8;
++ hot_temp = thermal_calib & 0xff;
++
++ ratio = ((raw_25c - raw_hot) * 100) / (hot_temp - 25);
++ raw_n40c = raw_25c + (13 * ratio) / 20;
++
++ /* now we only using single measure, every time we measure
++ the temperature, we will power on/down the anadig module*/
++ writel(BM_ANADIG_TEMPSENSE0_POWER_DOWN, &anatop->tempsense0_clr);
++ writel(BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_set);
++
++ /* write measure freq */
++ reg = readl(&anatop->tempsense1);
++ reg &= ~BM_ANADIG_TEMPSENSE1_MEASURE_FREQ;
++ reg |= 327;
++ writel(reg, &anatop->tempsense1);
++
++ writel(BM_ANADIG_TEMPSENSE0_MEASURE_TEMP, &anatop->tempsense0_clr);
++ writel(BM_ANADIG_TEMPSENSE0_FINISHED, &anatop->tempsense0_clr);
++ writel(BM_ANADIG_TEMPSENSE0_MEASURE_TEMP, &anatop->tempsense0_set);
++
++ tmp = 0;
++ /* read five times of temperature values to get average*/
++ for (i = 0; i < 5; i++) {
++ while ((readl(&anatop->tempsense0) &
++ BM_ANADIG_TEMPSENSE0_FINISHED) == 0)
++ udelay(10000);
++ reg = readl(&anatop->tempsense0);
++ tmp += (reg & BM_ANADIG_TEMPSENSE0_TEMP_VALUE) >>
++ BP_ANADIG_TEMPSENSE0_TEMP_VALUE;
++ writel(BM_ANADIG_TEMPSENSE0_FINISHED,
++ &anatop->tempsense0_clr);
++ }
++
++ tmp = tmp / 5;
++ if (tmp <= raw_n40c)
++ temperature = REG_VALUE_TO_CEL(ratio, tmp);
++ else
++ temperature = TEMPERATURE_MIN;
++
++ /* power down anatop thermal sensor */
++ writel(BM_ANADIG_TEMPSENSE0_POWER_DOWN, &anatop->tempsense0_set);
++ writel(BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_clr);
++
++ return temperature;
++}
++
++int check_cpu_temperature(int boot)
++{
++ static int __data max_temp;
++ int boot_limit = TEMPERATURE_HOT;
++ int tmp = read_cpu_temperature();
++
++debug("max_temp[%p]=%d diff=%d\n", &max_temp, max_temp, tmp - max_temp);
++
++ if (tmp < TEMPERATURE_MIN || tmp > TEMPERATURE_MAX) {
++ printf("Temperature: can't get valid data!\n");
++ return tmp;
++ }
++
++ while (tmp >= boot_limit) {
++ if (boot) {
++ printf("CPU is %d C, too hot to boot, waiting...\n",
++ tmp);
++ udelay(5000000);
++ tmp = read_cpu_temperature();
++ boot_limit = TEMPERATURE_HOT - 1;
++ } else {
++ printf("CPU is %d C, too hot, resetting...\n",
++ tmp);
++ udelay(1000000);
++ reset_cpu(0);
++ }
++ }
++
++ if (boot) {
++ printf("Temperature: %d C, calibration data 0x%x\n",
++ tmp, thermal_calib);
++ } else if (tmp > max_temp) {
++ if (tmp > TEMPERATURE_HOT - 5)
++ printf("WARNING: CPU temperature %d C\n", tmp);
++ max_temp = tmp;
++ }
++ return tmp;
++}
++
int arch_cpu_init(void)
{
init_aips();
set_vddsoc(1200); /* Set VDDSOC to 1.2V */
++#ifdef CONFIG_VIDEO_IPUV3
++ gd->arch.ipu_hw_rev = IPUV3_HW_REV_IPUV3H;
++#endif
++#ifdef CONFIG_APBH_DMA
++ /* Timer is required for Initializing APBH DMA */
++ timer_init();
++ mxs_dma_init();
++#endif
return 0;
}
- #endif
#ifndef CONFIG_SYS_DCACHE_OFF
void enable_caches(void)
u32 value = readl(&fuse->mac_addr_high);
mac[0] = (value >> 8);
-- mac[1] = value ;
++ mac[1] = value;
value = readl(&fuse->mac_addr_low);
-- mac[2] = value >> 24 ;
-- mac[3] = value >> 16 ;
-- mac[4] = value >> 8 ;
-- mac[5] = value ;
--
++ mac[2] = value >> 24;
++ mac[3] = value >> 16;
++ mac[4] = value >> 8;
++ mac[5] = value;
}
#endif
+
+ void boot_mode_apply(unsigned cfg_val)
+ {
+ unsigned reg;
+ struct src *psrc = (struct src *)SRC_BASE_ADDR;
+ writel(cfg_val, &psrc->gpr9);
+ reg = readl(&psrc->gpr10);
+ if (cfg_val)
+ reg |= 1 << 28;
+ else
+ reg &= ~(1 << 28);
+ writel(reg, &psrc->gpr10);
+ }
+ /*
+ * 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.
+ */
+ 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)},
+ {"escpi1:0", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x08)},
+ {"escpi1:1", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x18)},
+ {"escpi1:2", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x28)},
+ {"escpi1:3", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x38)},
+ /* 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},
+ };
++#define RESET_MAX_TIMEOUT 1000000
++#define MXS_BLOCK_SFTRST (1 << 31)
++#define MXS_BLOCK_CLKGATE (1 << 30)
++#include <div64.h>
++
++static const int scale = 1;
++
++int mxs_wait_mask_set(struct mx6_register_32 *mx6_reg, uint32_t mask, unsigned long timeout)
++{
++ unsigned long loops = 0;
++
++ timeout /= scale;
++ if (timeout == 0)
++ timeout++;
++
++ /* Wait for at least one microsecond for the bit mask to be set */
++ while ((readl(&mx6_reg->reg) & mask) != mask) {
++ if ((loops += scale) >= timeout) {
++ printf("MASK %08x in %p not set after %lu ticks\n",
++ mask, &mx6_reg->reg, loops * scale);
++ return 1;
++ }
++ udelay(scale);
++ }
++ if (loops == 0)
++ udelay(1);
++
++ return 0;
++}
++
++int mxs_wait_mask_clr(struct mx6_register_32 *mx6_reg, uint32_t mask, unsigned long timeout)
++{
++ unsigned long loops = 0;
++
++ timeout /= scale;
++ if (timeout == 0)
++ timeout++;
++
++ /* Wait for at least one microsecond for the bit mask to be cleared */
++ while ((readl(&mx6_reg->reg) & mask) != 0) {
++ if ((loops += scale) >= timeout) {
++ printf("MASK %08x in %p not cleared after %lu ticks\n",
++ mask, &mx6_reg->reg, loops * scale);
++ return 1;
++ }
++ udelay(scale);
++ }
++ if (loops == 0)
++ udelay(1);
++
++ return 0;
++}
++
++int mxs_reset_block(struct mx6_register_32 *mx6_reg)
++{
++ /* Clear SFTRST */
++ writel(MXS_BLOCK_SFTRST, &mx6_reg->reg_clr);
++
++ if (mxs_wait_mask_clr(mx6_reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT)) {
++ printf("TIMEOUT waiting for SFTRST[%p] to clear: %08x\n",
++ &mx6_reg->reg, readl(&mx6_reg->reg));
++ return 1;
++ }
++
++ /* Clear CLKGATE */
++ writel(MXS_BLOCK_CLKGATE, &mx6_reg->reg_clr);
++
++ /* Set SFTRST */
++ writel(MXS_BLOCK_SFTRST, &mx6_reg->reg_set);
++
++ /* Wait for CLKGATE being set */
++ if (mxs_wait_mask_set(mx6_reg, MXS_BLOCK_CLKGATE, RESET_MAX_TIMEOUT)) {
++ printf("TIMEOUT waiting for CLKGATE[%p] to set: %08x\n",
++ &mx6_reg->reg, readl(&mx6_reg->reg));
++ return 0;
++ }
++
++ /* Clear SFTRST */
++ writel(MXS_BLOCK_SFTRST, &mx6_reg->reg_clr);
++
++ if (mxs_wait_mask_clr(mx6_reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT)) {
++ printf("TIMEOUT waiting for SFTRST[%p] to clear: %08x\n",
++ &mx6_reg->reg, readl(&mx6_reg->reg));
++ return 1;
++ }
++
++ /* Clear CLKGATE */
++ writel(MXS_BLOCK_CLKGATE, &mx6_reg->reg_clr);
++
++ if (mxs_wait_mask_clr(mx6_reg, MXS_BLOCK_CLKGATE, RESET_MAX_TIMEOUT)) {
++ printf("TIMEOUT waiting for CLKGATE[%p] to clear: %08x\n",
++ &mx6_reg->reg, readl(&mx6_reg->reg));
++ return 1;
++ }
++
++ return 0;
++}
* We would not typically need to save these parameters in regular
* U-Boot. This is needed only in SPL at the moment.
*/
-u32 omap_bootmode = MMCSD_MODE_FAT;
+u32 omap_bootmode __attribute__ ((section(".data"))) = MMCSD_MODE_UNDEFINED;
- u32 omap_boot_device(void)
+ u32 spl_boot_device(void)
{
- return (u32) (boot_params.omap_bootdevice);
+ return boot_params.omap_bootdevice;
}
- u32 omap_boot_mode(void)
+ u32 spl_boot_mode(void)
{
return omap_bootmode;
}
ldr r1, =boot_params
str r0, [r1]
#ifdef CONFIG_SPL_BUILD
- /* Store the boot device in omap_boot_device */
+ /* Store the boot device in spl_boot_device */
- ldrb r2, [r0, #BOOT_DEVICE_OFFSET] @ r1 <- value of boot device
+ ldrb r2, [r0, #BOOT_DEVICE_OFFSET] @ r2 <- value of boot device
and r2, #BOOT_DEVICE_MASK
- strb r2, [r1, #BOOT_DEVICE_OFFSET] @ omap_boot_device <- r2
- ldr r3, =boot_params
- strb r2, [r3, #BOOT_DEVICE_OFFSET] @ spl_boot_device <- r1
++ strb r2, [r1, #BOOT_DEVICE_OFFSET] @ spl_boot_device <- r2
- /* boot mode is passed only for devices that can do raw/fat mode */
- cmp r2, #2
+ /* boot mode is passed only for devices that can raw/fat mode */
+ cmp r2, #BOOT_DEVICE_XIP
blt 2f
- cmp r2, #7
+ cmp r2, #BOOT_DEVICE_MMC2
bgt 2f
- /* Store the boot mode (raw/FAT) in omap_boot_mode */
+ /* Store the boot mode (raw/FAT) in omap_bootmode */
ldr r2, [r0, #DEV_DESC_PTR_OFFSET] @ get the device descriptor ptr
ldr r2, [r2, #DEV_DATA_PTR_OFFSET] @ get the pDeviceData ptr
ldr r2, [r2, #BOOT_MODE_OFFSET] @ get the boot mode
PUSH {r4-r11, lr} @ save registers - ROM code may pollute
@ our registers
LDR r12, =0x102 @ Set PL310 control register - value in R0
++ smc #0
.word 0xe1600070 @ SMC #0 - hand assembled because -march=armv5
@ call ROM Code API to set control register
POP {r4-r11, pc}
/* start the counter ticking up, reload value on overflow */
writel(TIMER_LOAD_VAL, &timer_base->tldr);
/* enable timer */
- writel((CONFIG_SYS_PTV << 2) | TCLR_PRE | TCLR_AR | TCLR_ST,
- &timer_base->tclr);
-
- /* reset time, capture current incrementer value time */
- gd->arch.lastinc = readl(&timer_base->tcrr) /
- (TIMER_CLOCK / CONFIG_SYS_HZ);
- gd->arch.tbl = 0; /* start "advancing" time stamp from 0 */
-
+ writel(TCLR_VAL, &timer_base->tclr);
+#endif
+#ifndef CONFIG_SPL_BUILD
- gd->lastinc = -30 * TIMER_CLOCK;
- gd->tbl = TIMER_START;
- gd->timer_rate_hz = TIMER_CLOCK;
++ gd->arch.lastinc = -30 * TIMER_CLOCK;
++ gd->arch.tbl = TIMER_START;
++ gd->arch.timer_rate_hz = TIMER_CLOCK;
+#endif
return 0;
}
*/
unsigned long long get_ticks(void)
{
- return get_timer(0);
+ ulong now = readl(&timer_base->tcrr);
- ulong inc = now - gd->lastinc;
++ ulong inc = now - gd->arch.lastinc;
+
- gd->tbl += inc;
- gd->lastinc = now;
- return gd->tbl;
++ gd->arch.tbl += inc;
++ gd->arch.lastinc = now;
++ return gd->arch.tbl;
}
/*
*/
ulong get_tbclk(void)
{
- return gd->timer_rate_hz;
- return CONFIG_SYS_HZ;
++ return gd->arch.timer_rate_hz;
}
.globl _TEXT_BASE
_TEXT_BASE:
- #ifndef CONFIG_SPL_BUILD
-- .word CONFIG_SYS_TEXT_BASE
- #else
- .word CONFIG_SPL_TEXT_BASE
- #endif
++ .word _start
/*
* These are defined in the board-specific linker script.
mov r5, r1 /* save addr of gd */
mov r6, r2 /* save addr of destination */
- /* Set up the stack */
- stack_setup:
- mov sp, r4
-
adr r0, _start
- cmp r0, r6
- moveq r9, #0 /* no relocation. relocation offset(r9) = 0 */
+ subs r9, r6, r0
- beq clear_bss /* skip relocation */
+ beq relocate_done /* skip relocation */
mov r1, r6 /* r1 <- scratch for copy_loop */
ldr r3, _image_copy_end_ofs
add r2, r0, r3 /* r2 <- source end address */
add r2, r2, r0 /* r2 <- rel dyn start in FLASH */
ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */
add r3, r3, r0 /* r3 <- rel dyn end in FLASH */
++ mov r4, r0
fixloop:
ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */
++ cmp r0, r4
++ blo skipfix
add r0, r0, r9 /* r0 <- location to fix up in RAM */
ldr r1, [r2, #4]
and r7, r1, #0xff
add r1, r1, r9
fixnext:
str r1, [r0]
++skipfix:
add r2, r2, #8 /* each rel.dyn entry is 8 bytes */
cmp r2, r3
blo fixloop
--- /dev/null
--- /dev/null
++
++/*
++ * Copyright 2013 Freescale Semiconductor, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++
++/include/ "imx6qdl.dtsi"
++
++/ {
++ cpus {
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ cpu@0 {
++ compatible = "arm,cortex-a9";
++ reg = <0>;
++ next-level-cache = <&L2>;
++ operating-points = <
++ /* kHz uV */
++ 1200000 1275000
++ 996000 1250000
++ 792000 1150000
++ 396000 950000
++ >;
++ clock-latency = <61036>; /* two CLK32 periods */
++ clocks = <&clks 104>, <&clks 6>, <&clks 16>,
++ <&clks 17>, <&clks 170>;
++ clock-names = "arm", "pll2_pfd2_396m", "step",
++ "pll1_sw", "pll1_sys";
++ arm-supply = <®_arm>;
++ pu-supply = <®_pu>;
++ soc-supply = <®_soc>;
++ };
++
++ cpu@1 {
++ compatible = "arm,cortex-a9";
++ reg = <1>;
++ next-level-cache = <&L2>;
++ };
++
++ cpu@2 {
++ compatible = "arm,cortex-a9";
++ reg = <2>;
++ next-level-cache = <&L2>;
++ };
++
++ cpu@3 {
++ compatible = "arm,cortex-a9";
++ reg = <3>;
++ next-level-cache = <&L2>;
++ };
++ };
++
++ soc {
++ aips-bus@02000000 { /* AIPS1 */
++ spba-bus@02000000 {
++ ecspi5: ecspi@02018000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
++ reg = <0x02018000 0x4000>;
++ interrupts = <0 35 0x04>;
++ clocks = <&clks 116>, <&clks 116>;
++ clock-names = "ipg", "per";
++ status = "disabled";
++ };
++ };
++
++ iomuxc: iomuxc@020e0000 {
++ compatible = "fsl,imx6q-iomuxc";
++ reg = <0x020e0000 0x4000>;
++
++ /* shared pinctrl settings */
++ audmux {
++ pinctrl_audmux_1: audmux-1 {
++ fsl,pins = <
++ 18 0x80000000 /* MX6Q_PAD_SD2_DAT0__AUDMUX_AUD4_RXD */
++ 1586 0x80000000 /* MX6Q_PAD_SD2_DAT3__AUDMUX_AUD4_TXC */
++ 11 0x80000000 /* MX6Q_PAD_SD2_DAT2__AUDMUX_AUD4_TXD */
++ 3 0x80000000 /* MX6Q_PAD_SD2_DAT1__AUDMUX_AUD4_TXFS */
++ >;
++ };
++ };
++
++ ecspi1 {
++ pinctrl_ecspi1_1: ecspi1grp-1 {
++ fsl,pins = <
++ 101 0x100b1 /* MX6Q_PAD_EIM_D17__ECSPI1_MISO */
++ 109 0x100b1 /* MX6Q_PAD_EIM_D18__ECSPI1_MOSI */
++ 94 0x100b1 /* MX6Q_PAD_EIM_D16__ECSPI1_SCLK */
++ >;
++ };
++ };
++
++ enet {
++ pinctrl_enet_1: enetgrp-1 {
++ fsl,pins = <
++ 695 0x1b0b0 /* MX6Q_PAD_ENET_MDIO__ENET_MDIO */
++ 756 0x1b0b0 /* MX6Q_PAD_ENET_MDC__ENET_MDC */
++ 24 0x1b0b0 /* MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC */
++ 30 0x1b0b0 /* MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0 */
++ 34 0x1b0b0 /* MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1 */
++ 39 0x1b0b0 /* MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2 */
++ 44 0x1b0b0 /* MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3 */
++ 56 0x1b0b0 /* MX6Q_PAD_RGMII_TX_CTL__RGMII_TX_CTL */
++ 702 0x1b0b0 /* MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK */
++ 74 0x1b0b0 /* MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC */
++ 52 0x1b0b0 /* MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0 */
++ 61 0x1b0b0 /* MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1 */
++ 66 0x1b0b0 /* MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2 */
++ 70 0x1b0b0 /* MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3 */
++ 48 0x1b0b0 /* MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL */
++ 1033 0x4001b0a8 /* MX6Q_PAD_GPIO_16__ENET_ANATOP_ETHERNET_REF_OUT*/
++ >;
++ };
++
++ pinctrl_enet_2: enetgrp-2 {
++ fsl,pins = <
++ 890 0x1b0b0 /* MX6Q_PAD_KEY_COL1__ENET_MDIO */
++ 909 0x1b0b0 /* MX6Q_PAD_KEY_COL2__ENET_MDC */
++ 24 0x1b0b0 /* MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC */
++ 30 0x1b0b0 /* MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0 */
++ 34 0x1b0b0 /* MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1 */
++ 39 0x1b0b0 /* MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2 */
++ 44 0x1b0b0 /* MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3 */
++ 56 0x1b0b0 /* MX6Q_PAD_RGMII_TX_CTL__RGMII_TX_CTL */
++ 702 0x1b0b0 /* MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK */
++ 74 0x1b0b0 /* MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC */
++ 52 0x1b0b0 /* MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0 */
++ 61 0x1b0b0 /* MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1 */
++ 66 0x1b0b0 /* MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2 */
++ 70 0x1b0b0 /* MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3 */
++ 48 0x1b0b0 /* MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL */
++ >;
++ };
++ };
++
++ gpmi-nand {
++ pinctrl_gpmi_nand_1: gpmi-nand-1 {
++ fsl,pins = <
++ 1328 0xb0b1 /* MX6Q_PAD_NANDF_CLE__RAWNAND_CLE */
++ 1336 0xb0b1 /* MX6Q_PAD_NANDF_ALE__RAWNAND_ALE */
++ 1344 0xb0b1 /* MX6Q_PAD_NANDF_WP_B__RAWNAND_RESETN */
++ 1352 0xb000 /* MX6Q_PAD_NANDF_RB0__RAWNAND_READY0 */
++ 1360 0xb0b1 /* MX6Q_PAD_NANDF_CS0__RAWNAND_CE0N */
++ 1365 0xb0b1 /* MX6Q_PAD_NANDF_CS1__RAWNAND_CE1N */
++ 1371 0xb0b1 /* MX6Q_PAD_NANDF_CS2__RAWNAND_CE2N */
++ 1378 0xb0b1 /* MX6Q_PAD_NANDF_CS3__RAWNAND_CE3N */
++ 1387 0xb0b1 /* MX6Q_PAD_SD4_CMD__RAWNAND_RDN */
++ 1393 0xb0b1 /* MX6Q_PAD_SD4_CLK__RAWNAND_WRN */
++ 1397 0xb0b1 /* MX6Q_PAD_NANDF_D0__RAWNAND_D0 */
++ 1405 0xb0b1 /* MX6Q_PAD_NANDF_D1__RAWNAND_D1 */
++ 1413 0xb0b1 /* MX6Q_PAD_NANDF_D2__RAWNAND_D2 */
++ 1421 0xb0b1 /* MX6Q_PAD_NANDF_D3__RAWNAND_D3 */
++ 1429 0xb0b1 /* MX6Q_PAD_NANDF_D4__RAWNAND_D4 */
++ 1437 0xb0b1 /* MX6Q_PAD_NANDF_D5__RAWNAND_D5 */
++ 1445 0xb0b1 /* MX6Q_PAD_NANDF_D6__RAWNAND_D6 */
++ 1453 0xb0b1 /* MX6Q_PAD_NANDF_D7__RAWNAND_D7 */
++ 1463 0x00b1 /* MX6Q_PAD_SD4_DAT0__RAWNAND_DQS */
++ >;
++ };
++ };
++
++ i2c1 {
++ pinctrl_i2c1_1: i2c1grp-1 {
++ fsl,pins = <
++ 137 0x4001b8b1 /* MX6Q_PAD_EIM_D21__I2C1_SCL */
++ 196 0x4001b8b1 /* MX6Q_PAD_EIM_D28__I2C1_SDA */
++ >;
++ };
++ };
++
++ uart1 {
++ pinctrl_uart1_1: uart1grp-1 {
++ fsl,pins = <
++ 1140 0x1b0b1 /* MX6Q_PAD_CSI0_DAT10__UART1_TXD */
++ 1148 0x1b0b1 /* MX6Q_PAD_CSI0_DAT11__UART1_RXD */
++ >;
++ };
++ pinctrl_uart1_2: uart1-grp-2 {
++ fsl,pins = <
++ 120 0x1b0b1 /* MX6Q_PAD_EIM_D19__UART1_CTS */
++ 128 0x1b0b1 /* MX6Q_PAD_EIM_D20__UART1_RTS */
++ >;
++ };
++
++ pinctrl_uart1_3: uart1grp-3 {
++ fsl,pins = <
++ 1242 0x1b0b1 /* MX6Q_PAD_SD3_DAT7__UART1_TXD */
++ 1250 0x1b0b1 /* MX6Q_PAD_SD3_DAT6__UART1_RXD */
++ >;
++ };
++ pinctrl_uart1_4: uart1-grp-4 {
++ fsl,pins = <
++ 1290 0x1b0b1 /* MX6Q_PAD_SD3_DAT0__UART1_CTS */
++ 1298 0x1b0b1 /* MX6Q_PAD_SD3_DAT1__UART1_RTS */
++ >;
++ };
++ };
++
++ uart2 {
++ pinctrl_uart2_1: uart2grp-1 {
++ fsl,pins = <
++ 183 0x1b0b1 /* MX6Q_PAD_EIM_D26__UART2_TXD */
++ 191 0x1b0b1 /* MX6Q_PAD_EIM_D27__UART2_RXD */
++ >;
++ };
++ pinctrl_uart2_2: uart2grp-2 {
++ fsl,pins = <
++ 199 0x1b0b1 /* MX6Q_PAD_EIM_D28__UART2_CTS */
++ 206 0x1b0b1 /* MX6Q_PAD_EIM_D29__UART2_RTS */
++ >;
++ };
++
++ pinctrl_uart2_3: uart2grp-3 {
++ fsl,pins = <
++ 1258 0x1b0b1 /* MX6Q_PAD_SD3_DAT5__UART2_TXD */
++ 1266 0x1b0b1 /* MX6Q_PAD_SD3_DAT6__UART2_RXD */
++ >;
++ };
++ pinctrl_uart2_4: uart2grp-4 {
++ fsl,pins = <
++ 1274 0x1b0b1 /* MX6Q_PAD_SD3_CMD__UART2_CTS */
++ 1282 0x1b0b1 /* MX6Q_PAD_SD3_CLK__UART2_RTS */
++ >;
++ };
++
++ pinctrl_uart2_5: uart2grp-5 {
++ fsl,pins = <
++ 1518 0x1b0b1 /* MX6Q_PAD_SD4_DAT7__UART2_TXD */
++ 1494 0x1b0b1 /* MX6Q_PAD_SD4_DAT4__UART2_RXD */
++ >;
++ };
++ pinctrl_uart2_6: uart2grp-6 {
++ fsl,pins = <
++ 1510 0x1b0b1 /* MX6Q_PAD_SD4_DAT6__UART2_CTS */
++ 1502 0x1b0b1 /* MX6Q_PAD_SD4_DAT5__UART2_RTS */
++ >;
++ };
++
++ pinctrl_uart2_7: uart2grp-7 {
++ fsl,pins = <
++ 1019 0x1b0b1 /* MX6Q_PAD_GPIO_7__UART2_TXD */
++ 1027 0x1b0b1 /* MX6Q_PAD_GPIO_8__UART2_RXD */
++ >;
++ };
++ };
++
++ uart3 {
++ pinctrl_uart3_1: uart3grp-1 {
++ fsl,pins = <
++ 165 0x1b0b1 /* MX6Q_PAD_EIM_D24__UART3_TXD */
++ 173 0x1b0b1 /* MX6Q_PAD_EIM_D25__UART3_RXD */
++ >;
++ };
++ pinctrl_uart3_2: uart3grp-2 {
++ fsl,pins = <
++ 149 0x1b0b1 /* MX6Q_PAD_EIM_D23__UART3_CTS */
++ 157 0x1b0b1 /* MX6Q_PAD_EIM_EB3__UART3_RTS */
++ >;
++ };
++
++ pinctrl_uart3_3: uart3grp-3 {
++ fsl,pins = <
++ 1388 0x1b0b1 /* MX6Q_PAD_SD4_CMD__UART3_TXD */
++ 1394 0x1b0b1 /* MX6Q_PAD_SD4_CLK__UART3_RXD */
++ >;
++ };
++ pinctrl_uart3_4: uart3grp-4 {
++ fsl,pins = <
++ 1313 0x1b0b1 /* MX6Q_PAD_SD3_DAT3__UART3_CTS */
++ 1321 0x1b0b1 /* MX6Q_PAD_SD3_RST__UART3_RTS */
++ >;
++ };
++
++ pinctrl_uart3_5: uart3grp-5 {
++ fsl,pins = <
++ 214 0x1b0b1 /* MX6Q_PAD_EIM_D30__UART3_CTS */
++ 222 0x1b0b1 /* MX6Q_PAD_EIM_D31__UART3_RTS */
++ >;
++ };
++ };
++
++ uart4 {
++ pinctrl_uart4_1: uart4grp-1 {
++ fsl,pins = <
++ 877 0x1b0b1 /* MX6Q_PAD_KEY_COL0__UART4_TXD */
++ 885 0x1b0b1 /* MX6Q_PAD_KEY_ROW0__UART4_RXD */
++ >;
++ };
++ };
++
++ usbotg {
++ pinctrl_usbotg_1: usbotggrp-1 {
++ fsl,pins = <
++ 1592 0x17059 /* MX6Q_PAD_GPIO_1__ANATOP_USBOTG_ID */
++ >;
++ };
++ };
++
++ usdhc1 {
++ pinctrl_usdhc1_1: usdhc1grp-1 {
++ fsl,pins = <
++ 1548 0x17059 /* MX6Q_PAD_SD1_CMD__USDHC1_CMD */
++ 1562 0x10059 /* MX6Q_PAD_SD1_CLK__USDHC1_CLK */
++ 1532 0x17059 /* MX6Q_PAD_SD1_DAT0__USDHC1_DAT0 */
++ 1524 0x17059 /* MX6Q_PAD_SD1_DAT1__USDHC1_DAT1 */
++ 1554 0x17059 /* MX6Q_PAD_SD1_DAT2__USDHC1_DAT2 */
++ 1540 0x17059 /* MX6Q_PAD_SD1_DAT3__USDHC1_DAT3 */
++ 1398 0x17059 /* MX6Q_PAD_NANDF_D0__USDHC1_DAT4 */
++ 1406 0x17059 /* MX6Q_PAD_NANDF_D1__USDHC1_DAT5 */
++ 1414 0x17059 /* MX6Q_PAD_NANDF_D2__USDHC1_DAT6 */
++ 1422 0x17059 /* MX6Q_PAD_NANDF_D3__USDHC1_DAT7 */
++ >;
++ };
++
++ pinctrl_usdhc1_2: usdhc1grp-2 {
++ fsl,pins = <
++ 1548 0x17059 /* MX6Q_PAD_SD1_CMD__USDHC1_CMD */
++ 1562 0x10059 /* MX6Q_PAD_SD1_CLK__USDHC1_CLK */
++ 1532 0x17059 /* MX6Q_PAD_SD1_DAT0__USDHC1_DAT0 */
++ 1524 0x17059 /* MX6Q_PAD_SD1_DAT1__USDHC1_DAT1 */
++ 1554 0x17059 /* MX6Q_PAD_SD1_DAT2__USDHC1_DAT2 */
++ 1540 0x17059 /* MX6Q_PAD_SD1_DAT3__USDHC1_DAT3 */
++ >;
++ };
++ };
++
++ usdhc2 {
++ pinctrl_usdhc2_1: usdhc2grp-1 {
++ fsl,pins = <
++ 1577 0x17059 /* MX6Q_PAD_SD2_CMD__USDHC2_CMD */
++ 1569 0x10059 /* MX6Q_PAD_SD2_CLK__USDHC2_CLK */
++ 16 0x17059 /* MX6Q_PAD_SD2_DAT0__USDHC2_DAT0 */
++ 0 0x17059 /* MX6Q_PAD_SD2_DAT1__USDHC2_DAT1 */
++ 8 0x17059 /* MX6Q_PAD_SD2_DAT2__USDHC2_DAT2 */
++ 1583 0x17059 /* MX6Q_PAD_SD2_DAT3__USDHC2_DAT3 */
++ 1430 0x17059 /* MX6Q_PAD_NANDF_D4__USDHC2_DAT4 */
++ 1438 0x17059 /* MX6Q_PAD_NANDF_D5__USDHC2_DAT5 */
++ 1446 0x17059 /* MX6Q_PAD_NANDF_D6__USDHC2_DAT6 */
++ 1454 0x17059 /* MX6Q_PAD_NANDF_D7__USDHC2_DAT7 */
++ >;
++ };
++
++ pinctrl_usdhc2_2: usdhc2grp-2 {
++ fsl,pins = <
++ 1577 0x17059 /* MX6Q_PAD_SD2_CMD__USDHC2_CMD */
++ 1569 0x10059 /* MX6Q_PAD_SD2_CLK__USDHC2_CLK */
++ 16 0x17059 /* MX6Q_PAD_SD2_DAT0__USDHC2_DAT0 */
++ 0 0x17059 /* MX6Q_PAD_SD2_DAT1__USDHC2_DAT1 */
++ 8 0x17059 /* MX6Q_PAD_SD2_DAT2__USDHC2_DAT2 */
++ 1583 0x17059 /* MX6Q_PAD_SD2_DAT3__USDHC2_DAT3 */
++ >;
++ };
++ };
++
++ usdhc3 {
++ pinctrl_usdhc3_1: usdhc3grp-1 {
++ fsl,pins = <
++ 1273 0x17059 /* MX6Q_PAD_SD3_CMD__USDHC3_CMD */
++ 1281 0x10059 /* MX6Q_PAD_SD3_CLK__USDHC3_CLK */
++ 1289 0x17059 /* MX6Q_PAD_SD3_DAT0__USDHC3_DAT0 */
++ 1297 0x17059 /* MX6Q_PAD_SD3_DAT1__USDHC3_DAT1 */
++ 1305 0x17059 /* MX6Q_PAD_SD3_DAT2__USDHC3_DAT2 */
++ 1312 0x17059 /* MX6Q_PAD_SD3_DAT3__USDHC3_DAT3 */
++ 1265 0x17059 /* MX6Q_PAD_SD3_DAT4__USDHC3_DAT4 */
++ 1257 0x17059 /* MX6Q_PAD_SD3_DAT5__USDHC3_DAT5 */
++ 1249 0x17059 /* MX6Q_PAD_SD3_DAT6__USDHC3_DAT6 */
++ 1241 0x17059 /* MX6Q_PAD_SD3_DAT7__USDHC3_DAT7 */
++ >;
++ };
++
++ pinctrl_usdhc3_2: usdhc3grp-2 {
++ fsl,pins = <
++ 1273 0x17059 /* MX6Q_PAD_SD3_CMD__USDHC3_CMD */
++ 1281 0x10059 /* MX6Q_PAD_SD3_CLK__USDHC3_CLK */
++ 1289 0x17059 /* MX6Q_PAD_SD3_DAT0__USDHC3_DAT0 */
++ 1297 0x17059 /* MX6Q_PAD_SD3_DAT1__USDHC3_DAT1 */
++ 1305 0x17059 /* MX6Q_PAD_SD3_DAT2__USDHC3_DAT2 */
++ 1312 0x17059 /* MX6Q_PAD_SD3_DAT3__USDHC3_DAT3 */
++ >;
++ };
++ };
++
++ usdhc4 {
++ pinctrl_usdhc4_1: usdhc4grp-1 {
++ fsl,pins = <
++ 1386 0x17059 /* MX6Q_PAD_SD4_CMD__USDHC4_CMD */
++ 1392 0x10059 /* MX6Q_PAD_SD4_CLK__USDHC4_CLK */
++ 1462 0x17059 /* MX6Q_PAD_SD4_DAT0__USDHC4_DAT0 */
++ 1470 0x17059 /* MX6Q_PAD_SD4_DAT1__USDHC4_DAT1 */
++ 1478 0x17059 /* MX6Q_PAD_SD4_DAT2__USDHC4_DAT2 */
++ 1486 0x17059 /* MX6Q_PAD_SD4_DAT3__USDHC4_DAT3 */
++ 1493 0x17059 /* MX6Q_PAD_SD4_DAT4__USDHC4_DAT4 */
++ 1501 0x17059 /* MX6Q_PAD_SD4_DAT5__USDHC4_DAT5 */
++ 1509 0x17059 /* MX6Q_PAD_SD4_DAT6__USDHC4_DAT6 */
++ 1517 0x17059 /* MX6Q_PAD_SD4_DAT7__USDHC4_DAT7 */
++ >;
++ };
++
++ pinctrl_usdhc4_2: usdhc4grp-2 {
++ fsl,pins = <
++ 1386 0x17059 /* MX6Q_PAD_SD4_CMD__USDHC4_CMD */
++ 1392 0x10059 /* MX6Q_PAD_SD4_CLK__USDHC4_CLK */
++ 1462 0x17059 /* MX6Q_PAD_SD4_DAT0__USDHC4_DAT0 */
++ 1470 0x17059 /* MX6Q_PAD_SD4_DAT1__USDHC4_DAT1 */
++ 1478 0x17059 /* MX6Q_PAD_SD4_DAT2__USDHC4_DAT2 */
++ 1486 0x17059 /* MX6Q_PAD_SD4_DAT3__USDHC4_DAT3 */
++ >;
++ };
++ };
++ };
++ };
++
++ ipu2: ipu@02800000 {
++ #crtc-cells = <1>;
++ compatible = "fsl,imx6q-ipu";
++ reg = <0x02800000 0x400000>;
++ interrupts = <0 8 0x4 0 7 0x4>;
++ clocks = <&clks 133>, <&clks 134>, <&clks 137>;
++ clock-names = "bus", "di0", "di1";
++ };
++ };
++};
--- /dev/null
-#include <ipu_pixfmt.h>
+ /*
+ * (C) Copyright 2007
+ * Sascha Hauer, Pengutronix
+ *
+ * (C) Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+ #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>
+ #include <asm/arch/crm_regs.h>
-#if defined(CONFIG_MX53) || defined(CONFIG_MX6)
+
+ #ifdef CONFIG_FSL_ESDHC
+ #include <fsl_esdhc.h>
+ #endif
+
+ char *get_reset_cause(void)
+ {
+ u32 cause;
+ struct src *src_regs = (struct src *)SRC_BASE_ADDR;
+
+ cause = readl(&src_regs->srsr);
+ writel(cause, &src_regs->srsr);
+
+ switch (cause) {
+ case 0x00001:
+ case 0x00011:
+ return "POR";
+ case 0x00004:
+ return "CSU";
+ case 0x00008:
+ return "IPP USER";
+ case 0x00010:
+ return "WDOG";
+ case 0x00020:
+ return "JTAG HIGH-Z";
+ case 0x00040:
+ return "JTAG SW";
+ case 0x10000:
+ return "WARM BOOT";
+ default:
+ return "unknown reset";
+ }
+ }
+
-
-#if defined(CONFIG_VIDEO_IPUV3)
-void arch_preboot_os(void)
-{
- /* disable video before launching O/S */
- ipuv3_fb_shutdown();
-}
-#endif
++#if defined(CONFIG_MX53) || defined(CONFIG_MX6Q)
+ #if defined(CONFIG_MX53)
+ #define MEMCTL_BASE ESDCTL_BASE_ADDR;
+ #else
+ #define MEMCTL_BASE MMDC_P0_BASE_ADDR;
+ #endif
+ static const unsigned char col_lookup[] = {9, 10, 11, 8, 12, 9, 9, 9};
+ static const unsigned char bank_lookup[] = {3, 2};
+
+ struct esd_mmdc_regs {
+ uint32_t ctl;
+ uint32_t pdc;
+ uint32_t otc;
+ uint32_t cfg0;
+ uint32_t cfg1;
+ uint32_t cfg2;
+ uint32_t misc;
+ uint32_t scr;
+ uint32_t ref;
+ uint32_t rsvd1;
+ uint32_t rsvd2;
+ uint32_t rwd;
+ uint32_t or;
+ uint32_t mrr;
+ uint32_t cfg3lp;
+ uint32_t mr4;
+ };
+
+ #define ESD_MMDC_CTL_GET_ROW(mdctl) ((ctl >> 24) & 7)
+ #define ESD_MMDC_CTL_GET_COLUMN(mdctl) ((ctl >> 20) & 7)
+ #define ESD_MMDC_CTL_GET_WIDTH(mdctl) ((ctl >> 16) & 3)
+ #define ESD_MMDC_CTL_GET_CS1(mdctl) ((ctl >> 30) & 1)
+ #define ESD_MMDC_MISC_GET_BANK(mdmisc) ((misc >> 5) & 1)
+
+ unsigned imx_ddr_size(void)
+ {
+ struct esd_mmdc_regs *mem = (struct esd_mmdc_regs *)MEMCTL_BASE;
+ unsigned ctl = readl(&mem->ctl);
+ unsigned misc = readl(&mem->misc);
+ int bits = 11 + 0 + 0 + 1; /* row + col + bank + width */
+
+ bits += ESD_MMDC_CTL_GET_ROW(ctl);
+ bits += col_lookup[ESD_MMDC_CTL_GET_COLUMN(ctl)];
+ bits += bank_lookup[ESD_MMDC_MISC_GET_BANK(misc)];
+ bits += ESD_MMDC_CTL_GET_WIDTH(ctl);
+ bits += ESD_MMDC_CTL_GET_CS1(ctl);
+ return 1 << bits;
+ }
+ #endif
+
+ #if defined(CONFIG_DISPLAY_CPUINFO)
+
+ const char *get_imx_type(u32 imxtype)
+ {
+ switch (imxtype) {
+ case MXC_CPU_MX6Q:
+ return "6Q"; /* Quad-core version of the mx6 */
+ case MXC_CPU_MX6DL:
+ return "6DL"; /* Dual Lite version of the mx6 */
+ case MXC_CPU_MX6SOLO:
+ return "6SOLO"; /* Solo version of the mx6 */
+ case MXC_CPU_MX6SL:
+ return "6SL"; /* Solo-Lite version of the mx6 */
+ case MXC_CPU_MX51:
+ return "51";
+ case MXC_CPU_MX53:
+ return "53";
+ default:
+ return "??";
+ }
+ }
+
+ int print_cpuinfo(void)
+ {
+ u32 cpurev;
+
+ cpurev = get_cpu_rev();
+
+ printf("CPU: Freescale i.MX%s rev%d.%d at %d MHz\n",
+ get_imx_type((cpurev & 0xFF000) >> 12),
+ (cpurev & 0x000F0) >> 4,
+ (cpurev & 0x0000F) >> 0,
+ mxc_get_clock(MXC_ARM_CLK) / 1000000);
+ printf("Reset cause: %s\n", get_reset_cause());
+ return 0;
+ }
+ #endif
+
+ int cpu_eth_init(bd_t *bis)
+ {
+ int rc = -ENODEV;
+
+ #if defined(CONFIG_FEC_MXC)
+ rc = fecmxc_initialize(bis);
+ #endif
+
+ return rc;
+ }
+
+ #ifdef CONFIG_FSL_ESDHC
+ /*
+ * Initializes on-chip MMC controllers.
+ * to override, implement board_mmc_init()
+ */
+ int cpu_mmc_init(bd_t *bis)
+ {
+ return fsl_esdhc_mmc_init(bis);
+ }
+ #endif
+
+ u32 get_ahb_clk(void)
+ {
+ struct mxc_ccm_reg *imx_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+ u32 reg, ahb_podf;
+
+ reg = __raw_readl(&imx_ccm->cbcdr);
+ reg &= MXC_CCM_CBCDR_AHB_PODF_MASK;
+ ahb_podf = reg >> MXC_CCM_CBCDR_AHB_PODF_OFFSET;
+
+ return get_periph_clk() / (ahb_podf + 1);
+ }
--- /dev/null
- if (!(pad_ctrl & NO_PAD_CTRL) && pad_ctrl_ofs)
+ /*
+ * Based on the iomux-v3.c from Linux kernel:
+ * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+ * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH,
+ * <armlinux@phytec.de>
+ *
+ * Copyright (C) 2004-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+ #include <common.h>
+ #include <asm/io.h>
+ #include <asm/arch/imx-regs.h>
+ #include <asm/imx-common/iomux-v3.h>
+
+ static void *base = (void *)IOMUXC_BASE_ADDR;
+
+ /*
+ * configures a single pad in the iomuxer
+ */
+ int imx_iomux_v3_setup_pad(iomux_v3_cfg_t pad)
+ {
+ u32 mux_ctrl_ofs = (pad & MUX_CTRL_OFS_MASK) >> MUX_CTRL_OFS_SHIFT;
+ u32 mux_mode = (pad & MUX_MODE_MASK) >> MUX_MODE_SHIFT;
+ u32 sel_input_ofs =
+ (pad & MUX_SEL_INPUT_OFS_MASK) >> MUX_SEL_INPUT_OFS_SHIFT;
+ u32 sel_input =
+ (pad & MUX_SEL_INPUT_MASK) >> MUX_SEL_INPUT_SHIFT;
+ u32 pad_ctrl_ofs =
+ (pad & MUX_PAD_CTRL_OFS_MASK) >> MUX_PAD_CTRL_OFS_SHIFT;
+ u32 pad_ctrl = (pad & MUX_PAD_CTRL_MASK) >> MUX_PAD_CTRL_SHIFT;
+
+ if (mux_ctrl_ofs)
+ __raw_writel(mux_mode, base + mux_ctrl_ofs);
+
+ if (sel_input_ofs)
+ __raw_writel(sel_input, base + sel_input_ofs);
+
++ if ((pad & PAD_CTRL_VALID) && pad_ctrl_ofs)
+ __raw_writel(pad_ctrl, base + pad_ctrl_ofs);
+
+ return 0;
+ }
+
+ int imx_iomux_v3_setup_multiple_pads(iomux_v3_cfg_t const *pad_list,
+ unsigned count)
+ {
+ iomux_v3_cfg_t const *p = pad_list;
+ int i;
+ int ret;
+
+ for (i = 0; i < count; i++) {
++#if 0
++ u32 mux_ctrl_ofs = (*p & MUX_CTRL_OFS_MASK) >> MUX_CTRL_OFS_SHIFT;
++ u32 mux_mode = (*p & MUX_MODE_MASK) >> MUX_MODE_SHIFT;
++ u32 sel_input_ofs =
++ (*p & MUX_SEL_INPUT_OFS_MASK) >> MUX_SEL_INPUT_OFS_SHIFT;
++ u32 sel_input =
++ (*p & MUX_SEL_INPUT_MASK) >> MUX_SEL_INPUT_SHIFT;
++ u32 pad_ctrl_ofs =
++ (*p & MUX_PAD_CTRL_OFS_MASK) >> MUX_PAD_CTRL_OFS_SHIFT;
++ u32 pad_ctrl = (*p & MUX_PAD_CTRL_MASK) >> MUX_PAD_CTRL_SHIFT;
++
++ printf("PAD[%2d]=%016llx mux[%03x]=%02x pad[%03x]=%05x%c inp[%03x]=%d\n",
++ i, *p, mux_ctrl_ofs, mux_mode, pad_ctrl_ofs, pad_ctrl,
++ *p & PAD_CTRL_VALID ? ' ' : '!', sel_input_ofs, sel_input);
++#endif
+ ret = imx_iomux_v3_setup_pad(*p);
+ if (ret)
+ return ret;
+ p++;
+ }
+ return 0;
+ }
--- /dev/null
-#define GPTCR_CLKSOURCE_32 (4 << 6) /* Clock source */
+ /*
+ * (C) Copyright 2007
+ * Sascha Hauer, Pengutronix
+ *
+ * (C) Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+ #include <common.h>
+ #include <asm/io.h>
+ #include <div64.h>
+ #include <asm/arch/imx-regs.h>
+ #include <asm/arch/clock.h>
+
++#define DEBUG_TIMER_WRAP
++
+ /* General purpose timers registers */
+ struct mxc_gpt {
+ unsigned int control;
+ unsigned int prescaler;
+ unsigned int status;
+ unsigned int nouse[6];
+ unsigned int counter;
+ };
+
+ static struct mxc_gpt *cur_gpt = (struct mxc_gpt *)GPT1_BASE_ADDR;
+
+ /* General purpose timers bitfields */
+ #define GPTCR_SWR (1 << 15) /* Software reset */
+ #define GPTCR_FRR (1 << 9) /* Freerun / restart */
-#define timestamp (gd->arch.tbl)
-#define lastinc (gd->arch.lastinc)
++#define GPTCR_CLKSOURCE_IPG (1 << 6) /* Clock source */
++#define GPTCR_CLKSOURCE_CKIH (2 << 6)
++#define GPTCR_CLKSOURCE_32kHz (4 << 6)
++#ifdef CONFIG_MX6Q
++#define GPTCR_CLKSOURCE_OSC_DIV_8 (5 << 6)
++#define GPTCR_CLKSOURCE_OSC (7 << 6)
++#else
++#define GPTCR_CLKSOURCE_OSC (5 << 6)
++#endif
++#define GPTCR_CLKSOURCE_MASK (7 << 6)
+ #define GPTCR_TEN 1 /* Timer enable */
+
++#if 1
++#define GPT_CLKSOURCE GPTCR_CLKSOURCE_OSC
++#define GPT_REFCLK 24000000
++#define GPT_PRESCALER 24
++#else
++#define GPT_CLKSOURCE GPTCR_CLKSOURCE_32kHz
++#define GPT_REFCLK 32768
++#define GPT_PRESCALER 1
++#endif
++#define GPT_CLK (GPT_REFCLK / GPT_PRESCALER)
++
++#ifdef DEBUG_TIMER_WRAP
++/*
++ * Let the timer wrap 30 seconds after start to catch misbehaving
++ * timer related code early
++ */
++#define TIMER_START (-time_to_tick(30 * CONFIG_SYS_HZ))
++#else
++#define TIMER_START 0UL
++#endif
++
+ DECLARE_GLOBAL_DATA_PTR;
+
-static inline unsigned long long tick_to_time(unsigned long long tick)
++static inline unsigned long tick_to_time(unsigned long tick)
++{
++ unsigned long long t = (unsigned long long)tick * CONFIG_SYS_HZ;
++ do_div(t, GPT_CLK);
++ return t;
++}
+
- tick *= CONFIG_SYS_HZ;
- do_div(tick, MXC_CLK32);
++static inline unsigned long time_to_tick(unsigned long time)
+ {
- return tick;
++ unsigned long long ticks = (unsigned long long)time;
+
-static inline unsigned long long us_to_tick(unsigned long long usec)
++ ticks *= GPT_CLK;
++ do_div(ticks, CONFIG_SYS_HZ);
++ return ticks;
+ }
+
- usec = usec * MXC_CLK32 + 999999;
- do_div(usec, 1000000);
++static inline unsigned long us_to_tick(unsigned long usec)
+ {
- return usec;
++ unsigned long long ticks = (unsigned long long)usec;
+
- __raw_writel(0, &cur_gpt->prescaler); /* 32Khz */
++ ticks *= GPT_CLK;
++ do_div(ticks, 1000 * CONFIG_SYS_HZ);
++ return ticks;
+ }
+
+ int timer_init(void)
+ {
+ int i;
+ ulong val;
+
+ /* setup GP Timer 1 */
+ __raw_writel(GPTCR_SWR, &cur_gpt->control);
+
+ /* We have no udelay by now */
+ for (i = 0; i < 100; i++)
+ __raw_writel(0, &cur_gpt->control);
+
- __raw_writel(i | GPTCR_CLKSOURCE_32 | GPTCR_TEN, &cur_gpt->control);
++ __raw_writel(GPT_PRESCALER - 1, &cur_gpt->prescaler);
+
+ /* Freerun Mode, PERCLK1 input */
+ i = __raw_readl(&cur_gpt->control);
- lastinc = val / (MXC_CLK32 / CONFIG_SYS_HZ);
- timestamp = 0;
++ i &= ~GPTCR_CLKSOURCE_MASK;
++ __raw_writel(i | GPT_CLKSOURCE | GPTCR_TEN, &cur_gpt->control);
+
+ val = __raw_readl(&cur_gpt->counter);
- if (now >= lastinc) {
- /*
- * normal mode (non roll)
- * move stamp forward with absolut diff ticks
- */
- timestamp += (now - lastinc);
- } else {
- /* we have rollover of incrementer */
- timestamp += (0xFFFFFFFF - lastinc) + now;
- }
- lastinc = now;
- return timestamp;
++ gd->arch.lastinc = val;
++ gd->arch.tbu = 0;
++ gd->arch.tbl = TIMER_START;
++ gd->arch.timer_rate_hz = GPT_CLK;
+
+ return 0;
+ }
+
+ unsigned long long get_ticks(void)
+ {
+ ulong now = __raw_readl(&cur_gpt->counter); /* current tick value */
++ ulong inc = now - gd->arch.lastinc;
+
- return get_timer_masked() - base;
++ gd->arch.tbl += inc;
++ gd->arch.lastinc = now;
++ return gd->arch.tbl;
+ }
+
+ ulong get_timer_masked(void)
+ {
+ /*
+ * get_ticks() returns a long long (64 bit), it wraps in
+ * 2^64 / MXC_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~
+ * 5 * 10^9 days... and get_ticks() * CONFIG_SYS_HZ wraps in
+ * 5 * 10^6 days - long enough.
+ */
++ /*
++ * LW: get_ticks() returns a long long with the top 32 bits always ZERO!
++ * Thus the calculation above is not true.
++ * A 64bit timer value would only make sense if it was
++ * consistently used throughout the code. Thus also the parameter
++ * to get_timer() and its return value would need to be 64bit wide!
++ */
+ return tick_to_time(get_ticks());
+ }
+
+ ulong get_timer(ulong base)
+ {
- unsigned long long tmp;
- ulong tmo;
++ return tick_to_time(get_ticks() - time_to_tick(base));
+ }
+
++#include <asm/gpio.h>
++
+ /* delay x useconds AND preserve advance timstamp value */
+ void __udelay(unsigned long usec)
+ {
- tmo = us_to_tick(usec);
- tmp = get_ticks() + tmo; /* get current timestamp */
++ unsigned long start = __raw_readl(&cur_gpt->counter);
++ unsigned long ticks;
++
++ if (usec == 0)
++ return;
+
- while (get_ticks() < tmp) /* loop till event */
- /*NOP*/;
++ ticks = us_to_tick(usec);
++ if (ticks == 0)
++ ticks++;
+
- return MXC_CLK32;
++ while (__raw_readl(&cur_gpt->counter) - start < ticks)
++ /* loop till event */;
+ }
+
+ /*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ ulong get_tbclk(void)
+ {
++ return gd->arch.timer_rate_hz;
+ }
#ifndef _CLOCKS_AM33XX_H_
#define _CLOCKS_AM33XX_H_
- #define OSC 24
+ #define OSC (V_OSCK/1000000)
- /* MAIN PLL */
+#ifndef CONFIG_SYS_MPU_CLK
- /* default to 500 MHz */
- #define MPUPLL_M 500
+ /* MAIN PLL Fdll = 550 MHZ, */
+ #define MPUPLL_M 550
-#define MPUPLL_N (OSC-1)
+#else
+#define MPUPLL_M CONFIG_SYS_MPU_CLK
+#endif
- #define MPUPLL_N 23
++#define MPUPLL_N (OSC - 1)
#define MPUPLL_M2 1
/* Core PLL Fdll = 1 GHZ, */
#define COREPLL_M 1000
- #define COREPLL_N 23
-#define COREPLL_N (OSC-1)
++#define COREPLL_N (OSC - 1)
#define COREPLL_M4 10 /* CORE_CLKOUTM4 = 200 MHZ */
#define COREPLL_M5 8 /* CORE_CLKOUTM5 = 250 MHZ */
* For clkout = 192 MHZ, Fdll = 960 MHZ, divider values are given below
*/
#define PERPLL_M 960
- #define PERPLL_N 23
-#define PERPLL_N (OSC-1)
++#define PERPLL_N (OSC - 1)
#define PERPLL_M2 5
/* DDR Freq is 266 MHZ for now */
/* Set Fdll = 400 MHZ , Fdll = M * 2 * CLKINP/ N + 1; clkout = Fdll /(2 * M2) */
+#ifndef CONFIG_SYS_DDR_CLK
#define DDRPLL_M 266
-#define DDRPLL_N (OSC-1)
+#else
+#define DDRPLL_M CONFIG_SYS_DDR_CLK
+#endif
- #define DDRPLL_N 23
++#define DDRPLL_N (OSC - 1)
#define DDRPLL_M2 1
- #define DISPPLL_N 23
+#define DISPPLL_M 200
++#define DISPPLL_N (OSC - 1)
+#define DISPPLL_M2 1
+
extern void pll_init(void);
extern void enable_emif_clocks(void);
#define DEVICE_ID 0x44E10600
/* This gives the status of the boot mode pins on the evm */
-#define SYSBOOT_MASK (BIT(0) | BIT(1) | BIT(2)\
- | BIT(3) | BIT(4))
+#define SYSBOOT_MASK (BIT(0) | BIT(1) | BIT(2) | \
+ BIT(3) | BIT(4))
/* Reset control */
-#ifdef CONFIG_AM33XX
#define PRM_RSTCTRL 0x44E00F00
#define PRM_RSTST 0x44E00F08
-#endif
#define PRM_RSTCTRL_RESET 0x01
+ #define PRM_RSTST_WARM_RESET_MASK 0x232
#ifndef __KERNEL_STRICT_NAMES
#ifndef __ASSEMBLY__
unsigned int l3clkstctrl; /* offset 0x0c */
unsigned int resv1;
unsigned int cpgmac0clkctrl; /* offset 0x14 */
- unsigned int lcdcclkctrl; /* offset 0x18 */
+ unsigned int lcdclkctrl; /* offset 0x18 */
- unsigned int usb0clkctrl; /* offset 0x1C */
+ unsigned int usb0clkctrl; /* offset 0x1c */
- unsigned int resv2[2];
+ unsigned int resv2;
+ unsigned int tptc0clkctrl; /* offset 0x24 */
unsigned int emifclkctrl; /* offset 0x28 */
unsigned int ocmcramclkctrl; /* offset 0x2c */
unsigned int gpmcclkctrl; /* offset 0x30 */
struct ctrl_stat {
unsigned int resv1[16];
unsigned int statusreg; /* ofset 0x40 */
+ unsigned int resv2[51];
+ unsigned int secure_emif_sdram_config; /* offset 0x0110 */
};
- struct gpmc_cs {
- u32 config1; /* 0x00 */
- u32 config2; /* 0x04 */
- u32 config3; /* 0x08 */
- u32 config4; /* 0x0C */
- u32 config5; /* 0x10 */
- u32 config6; /* 0x14 */
- u32 config7; /* 0x18 */
- u32 nand_cmd; /* 0x1C */
- u32 nand_adr; /* 0x20 */
- u32 nand_dat; /* 0x24 */
- u8 res[8]; /* blow up to 0x30 byte */
- };
+ /* AM33XX GPIO registers */
+ #define OMAP_GPIO_REVISION 0x0000
+ #define OMAP_GPIO_SYSCONFIG 0x0010
+ #define OMAP_GPIO_SYSSTATUS 0x0114
+ #define OMAP_GPIO_IRQSTATUS1 0x002c
+ #define OMAP_GPIO_IRQSTATUS2 0x0030
+ #define OMAP_GPIO_CTRL 0x0130
+ #define OMAP_GPIO_OE 0x0134
+ #define OMAP_GPIO_DATAIN 0x0138
+ #define OMAP_GPIO_DATAOUT 0x013c
+ #define OMAP_GPIO_LEVELDETECT0 0x0140
+ #define OMAP_GPIO_LEVELDETECT1 0x0144
+ #define OMAP_GPIO_RISINGDETECT 0x0148
+ #define OMAP_GPIO_FALLINGDETECT 0x014c
+ #define OMAP_GPIO_DEBOUNCE_EN 0x0150
+ #define OMAP_GPIO_DEBOUNCE_VAL 0x0154
+ #define OMAP_GPIO_CLEARDATAOUT 0x0190
+ #define OMAP_GPIO_SETDATAOUT 0x0194
- struct bch_res_0_3 {
- u32 bch_result_x[4];
- };
-
-
-
- struct gpmc {
- u8 res1[0x10];
- u32 sysconfig; /* 0x10 */
- u8 res2[0x4];
- u32 irqstatus; /* 0x18 */
- u32 irqenable; /* 0x1C */
- u8 res3[0x20];
- u32 timeout_control; /* 0x40 */
- u8 res4[0xC];
- u32 config; /* 0x50 */
- u32 status; /* 0x54 */
- u8 res5[0x8]; /* 0x58 */
- struct gpmc_cs cs[8]; /* 0x60, 0x90, .. */
- u8 res6[0x14]; /* 0x1E0 */
- u32 ecc_config; /* 0x1F4 */
- u32 ecc_control; /* 0x1F8 */
- u32 ecc_size_config; /* 0x1FC */
- u32 ecc1_result; /* 0x200 */
- u32 ecc2_result; /* 0x204 */
- u32 ecc3_result; /* 0x208 */
- u32 ecc4_result; /* 0x20C */
- u32 ecc5_result; /* 0x210 */
- u32 ecc6_result; /* 0x214 */
- u32 ecc7_result; /* 0x218 */
- u32 ecc8_result; /* 0x21C */
- u32 ecc9_result; /* 0x220 */
- u8 res7[12]; /* 0x224 */
- u32 testmomde_ctrl; /* 0x230 */
- u8 res8[12]; /* 0x234 */
- struct bch_res_0_3 bch_result_0_3[2]; /* 0x240 */
+ /* Control Device Register */
+ struct ctrl_dev {
+ unsigned int deviceid; /* offset 0x00 */
+ unsigned int resv1[7];
+ unsigned int usb_ctrl0; /* offset 0x20 */
+ unsigned int resv2;
+ unsigned int usb_ctrl1; /* offset 0x28 */
+ unsigned int resv3;
+ unsigned int macid0l; /* offset 0x30 */
+ unsigned int macid0h; /* offset 0x34 */
+ unsigned int macid1l; /* offset 0x38 */
+ unsigned int macid1h; /* offset 0x3c */
+ unsigned int resv4[4];
+ unsigned int miisel; /* offset 0x50 */
};
+
+void init_timer(void);
+
+#define clk_get_rate(c,p) \
+ __clk_get_rate(readl(&(c)->clkseldpll##p), \
+ readl(&(c)->divm2dpll##p))
+
+unsigned long __clk_get_rate(u32 m_n, u32 div_m2);
+
++unsigned long lcdc_clk_rate(void);
++
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL_STRICT_NAMES */
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
*/
- #ifndef _GPIO_AM33XX_H
- #define _GPIO_AM33XX_H
+ #ifndef _GPIO_AM33xx_H
+ #define _GPIO_AM33xx_H
+
+ #include <asm/omap_gpio.h>
- #include <asm-generic/gpio.h>
+ #define AM33XX_GPIO0_BASE 0x44E07000
+ #define AM33XX_GPIO1_BASE 0x4804C000
+ #define AM33XX_GPIO2_BASE 0x481AC000
+ #define AM33XX_GPIO3_BASE 0x481AE000
- #endif /* _GPIO_AM33XX_H */
+#define AM33XX_GPIO_NR(bank, pin) (((bank) << 5) | (pin))
+
+ #endif /* _GPIO_AM33xx_H */
#ifndef __AM33XX_HARDWARE_H
#define __AM33XX_HARDWARE_H
+ #include <asm/arch/omap.h>
+
/* Module base addresses */
- #define SRAM0_START 0x402F0400
+#define LOW_LEVEL_SRAM_STACK 0x4030B7FC
#define UART0_BASE 0x44E09000
/* DM Timer base addresses */
#define DM_TIMER6_BASE 0x48048000
#define DM_TIMER7_BASE 0x4804A000
--/* GPIO Base address */
- #define GPIO0_BASE 0x44E07000
-#define GPIO0_BASE 0x48032000
--#define GPIO1_BASE 0x4804C000
--#define GPIO2_BASE 0x481AC000
- #define GPIO3_BASE 0x481AE000
--
/* BCH Error Location Module */
#define ELM_BASE 0x48080000
/*
* OMAP HSMMC register definitions
*/
-#define OMAP_HSMMC1_BASE 0x48060100
-#define OMAP_HSMMC2_BASE 0x481D8100
+#define OMAP_HSMMC1_BASE 0x48060000
+#define OMAP_HSMMC2_BASE 0x481D8000
+#define OMAP_HSMMC3_BASE 0x47810000
typedef struct hsmmc {
- unsigned char res1[0x110];
- unsigned char res1[0x10];
- unsigned int sysconfig; /* 0x10 */
- unsigned int sysstatus; /* 0x14 */
- unsigned char res2[0x14];
- unsigned int con; /* 0x2C */
- unsigned char res3[0xD4];
- unsigned int blk; /* 0x104 */
- unsigned int arg; /* 0x108 */
- unsigned int cmd; /* 0x10C */
- unsigned int rsp10; /* 0x110 */
- unsigned int rsp32; /* 0x114 */
- unsigned int rsp54; /* 0x118 */
- unsigned int rsp76; /* 0x11C */
- unsigned int data; /* 0x120 */
- unsigned int pstate; /* 0x124 */
- unsigned int hctl; /* 0x128 */
- unsigned int sysctl; /* 0x12C */
- unsigned int stat; /* 0x130 */
- unsigned int ie; /* 0x134 */
- unsigned char res4[0x8];
- unsigned int capa; /* 0x140 */
++ unsigned int res1[0x110 / 4];
+ unsigned int sysconfig; /* 0x110 */
+ unsigned int sysstatus; /* 0x114 */
- unsigned char res2[0x14];
++ unsigned int res2[0x14 / 4];
+ unsigned int con; /* 0x12C */
- unsigned char res3[0xD4];
++ unsigned int res3[0xD4 / 4];
+ unsigned int blk; /* 0x204 */
+ unsigned int arg; /* 0x208 */
+ unsigned int cmd; /* 0x20C */
+ unsigned int rsp10; /* 0x210 */
+ unsigned int rsp32; /* 0x214 */
+ unsigned int rsp54; /* 0x218 */
+ unsigned int rsp76; /* 0x21C */
+ unsigned int data; /* 0x220 */
+ unsigned int pstate; /* 0x224 */
+ unsigned int hctl; /* 0x228 */
+ unsigned int sysctl; /* 0x22C */
+ unsigned int stat; /* 0x230 */
+ unsigned int ie; /* 0x234 */
- unsigned char res4[0x8];
++ unsigned int res4[2];
+ unsigned int capa; /* 0x240 */
} hsmmc_t;
/*
#define DDIR_READ (0x1 << 4)
#define MSBS_SGLEBLK (0x0 << 5)
#define MSBS_MULTIBLK (0x1 << 5)
--#define RSP_TYPE_OFFSET (16)
++#define RSP_TYPE_OFFSET 16
#define RSP_TYPE_MASK (0x3 << 16)
#define RSP_TYPE_NORSP (0x0 << 16)
#define RSP_TYPE_LGHT136 (0x1 << 16)
#ifndef __ASSEMBLY__
struct exynos4_sysreg {
-- unsigned char res1[0x210];
++ unsigned int res1[0x210 / 4];
unsigned int display_ctrl;
unsigned int display_ctrl2;
unsigned int camera_control;
};
struct exynos5_sysreg {
-- unsigned char res1[0x214];
++ unsigned int res1[0x214 / 4];
unsigned int disp1blk_cfg;
unsigned int disp2blk_cfg;
unsigned int hdcp_e_fuse;
unsigned int reserved;
unsigned int ispblk_cfg;
unsigned int usb20phy_cfg;
- unsigned char res2[0x29c];
++ unsigned int res2[0x29c / 4];
unsigned int mipi_dphy;
unsigned int dptx_dphy;
unsigned int phyclk_sel;
MXC_DDR_CLK,
MXC_NFC_CLK,
MXC_PERIPH_CLK,
+ MXC_I2C_CLK,
};
- unsigned int imx_decode_pll(unsigned int pll, unsigned int f_ref);
++
++struct clk {
++ const char *name;
++ int id;
++ /* Source clock this clk depends on */
++ struct clk *parent;
++ /* Secondary clock to enable/disable with this clock */
++ struct clk *secondary;
++ /* Current clock rate */
++ unsigned long rate;
++ /* Reference count of clock enable/disable */
++ __s8 usecount;
++ /* Register bit position for clock's enable/disable control. */
++ u8 enable_shift;
++ /* Register address for clock's enable/disable control. */
++ void *enable_reg;
++ u32 flags;
++ /*
++ * Function ptr to recalculate the clock's rate based on parent
++ * clock's rate
++ */
++ void (*recalc) (struct clk *);
++ /*
++ * Function ptr to set the clock to a new rate. The rate must match a
++ * supported rate returned from round_rate. Leave blank if clock is not
++ * programmable
++ */
++ int (*set_rate) (struct clk *, unsigned long);
++ /*
++ * Function ptr to round the requested clock rate to the nearest
++ * supported rate that is less than or equal to the requested rate.
++ */
++ unsigned long (*round_rate) (struct clk *, unsigned long);
++ /*
++ * Function ptr to enable the clock. Leave blank if clock can not
++ * be gated.
++ */
++ int (*enable) (struct clk *);
++ /*
++ * Function ptr to disable the clock. Leave blank if clock can not
++ * be gated.
++ */
++ void (*disable) (struct clk *);
++ /* Function ptr to set the parent clock of the clock. */
++ int (*set_parent) (struct clk *, struct clk *);
++};
+
u32 imx_get_uartclk(void);
u32 imx_get_fecclk(void);
unsigned int mxc_get_clock(enum mxc_clock clk);
--int mxc_set_clock(u32 ref, u32 freq, u32 clk_type);
- void set_usb_phy2_clk(void);
++int mxc_set_clock(u32 ref, u32 freq, enum mxc_clock clk);
+ void set_usb_phy_clk(void);
+ void enable_usb_phy1_clk(unsigned char enable);
void enable_usb_phy2_clk(unsigned char enable);
void set_usboh3_clk(void);
void enable_usboh3_clk(unsigned char enable);
void mxc_set_sata_internal_clock(void);
+ int enable_i2c_clk(unsigned char enable, unsigned i2c_num);
++void ipu_clk_enable(void);
++void ipu_clk_disable(void);
#endif /* __ASM_ARCH_CLOCK_H */
/* Define the bits in register CSCDR1 */
#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET 22
#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK (0x7 << 22)
+ #define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED(v) (((v) & 0x7) << 22)
+ #define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_RD(r) (((r) >> 22) & 0x7)
#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET 19
#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK (0x7 << 19)
+ #define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF(v) (((v) & 0x7) << 19)
+ #define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_RD(r) (((r) >> 19) & 0x7)
#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET 16
#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK (0x7 << 16)
+ #define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED(v) (((v) & 0x7) << 16)
+ #define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_RD(r) (((r) >> 16) & 0x7)
#define MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET 14
#define MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK (0x3 << 14)
+ #define MXC_CCM_CSCDR1_PGC_CLK_PODF(v) (((v) & 0x3) << 14)
+ #define MXC_CCM_CSCDR1_PGC_CLK_PODF_RD(r) (((r) >> 14) & 0x3)
#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET 11
#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK (0x7 << 11)
+ #define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF(v) (((v) & 0x7) << 11)
+ #define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_RD(r) (((r) >> 11) & 0x7)
#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET 8
#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK (0x7 << 8)
+ #define MXC_CCM_CSCDR1_USBOH3_CLK_PRED(v) (((v) & 0x7) << 8)
+ #define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_RD(r) (((r) >> 8) & 0x7)
#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET 6
#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK (0x3 << 6)
+ #define MXC_CCM_CSCDR1_USBOH3_CLK_PODF(v) (((v) & 0x3) << 6)
+ #define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_RD(r) (((r) >> 6) & 0x3)
#define MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET 3
#define MXC_CCM_CSCDR1_UART_CLK_PRED_MASK (0x7 << 3)
+ #define MXC_CCM_CSCDR1_UART_CLK_PRED(v) (((v) & 0x7) << 3)
+ #define MXC_CCM_CSCDR1_UART_CLK_PRED_RD(r) (((r) >> 3) & 0x7)
#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET 0
#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK 0x7
+ #define MXC_CCM_CSCDR1_UART_CLK_PODF(v) ((v) & 0x7)
+ #define MXC_CCM_CSCDR1_UART_CLK_PODF_RD(r) ((r) & 0x7)
/* Define the bits in register CCDR */
--#define MXC_CCM_CCDR_IPU_HS_MASK (0x1 << 17)
++#define MXC_CCM_CCDR_IPU_HS_MASK (0x1 << 21)
/* Define the bits in register CCGRx */
#define MXC_CCM_CCGR_CG_MASK 0x3
+ #define MXC_CCM_CCGR_CG_OFF 0x0
+ #define MXC_CCM_CCGR_CG_RUN_ON 0x1
+ #define MXC_CCM_CCGR_CG_ON 0x3
+
+ #define MXC_CCM_CCGR0_ARM_BUS_OFFSET 0
+ #define MXC_CCM_CCGR0_ARM_BUS(v) (((v) & 0x3) << 0)
+ #define MXC_CCM_CCGR0_ARM_AXI_OFFSET 2
+ #define MXC_CCM_CCGR0_ARM_AXI(v) (((v) & 0x3) << 2)
+ #define MXC_CCM_CCGR0_ARM_DEBUG_OFFSET 4
+ #define MXC_CCM_CCGR0_ARM_DEBUG(v) (((v) & 0x3) << 4)
+ #define MXC_CCM_CCGR0_TZIC_OFFSET 6
+ #define MXC_CCM_CCGR0_TZIC(v) (((v) & 0x3) << 6)
+ #define MXC_CCM_CCGR0_DAP_OFFSET 8
+ #define MXC_CCM_CCGR0_DAP(v) (((v) & 0x3) << 8)
+ #define MXC_CCM_CCGR0_TPIU_OFFSET 10
+ #define MXC_CCM_CCGR0_TPIU(v) (((v) & 0x3) << 10)
+ #define MXC_CCM_CCGR0_CTI2_OFFSET 12
+ #define MXC_CCM_CCGR0_CTI2(v) (((v) & 0x3) << 12)
+ #define MXC_CCM_CCGR0_CTI3_OFFSET 14
+ #define MXC_CCM_CCGR0_CTI3(v) (((v) & 0x3) << 14)
+ #define MXC_CCM_CCGR0_AHBMUX1_OFFSET 16
+ #define MXC_CCM_CCGR0_AHBMUX1(v) (((v) & 0x3) << 16)
+ #define MXC_CCM_CCGR0_AHBMUX2_OFFSET 18
+ #define MXC_CCM_CCGR0_AHBMUX2(v) (((v) & 0x3) << 18)
+ #define MXC_CCM_CCGR0_ROMCP_OFFSET 20
+ #define MXC_CCM_CCGR0_ROMCP(v) (((v) & 0x3) << 20)
+ #define MXC_CCM_CCGR0_ROM_OFFSET 22
+ #define MXC_CCM_CCGR0_ROM(v) (((v) & 0x3) << 22)
+ #define MXC_CCM_CCGR0_AIPS_TZ1_OFFSET 24
+ #define MXC_CCM_CCGR0_AIPS_TZ1(v) (((v) & 0x3) << 24)
+ #define MXC_CCM_CCGR0_AIPS_TZ2_OFFSET 26
+ #define MXC_CCM_CCGR0_AIPS_TZ2(v) (((v) & 0x3) << 26)
+ #define MXC_CCM_CCGR0_AHB_MAX_OFFSET 28
+ #define MXC_CCM_CCGR0_AHB_MAX(v) (((v) & 0x3) << 28)
+ #define MXC_CCM_CCGR0_IIM_OFFSET 30
+ #define MXC_CCM_CCGR0_IIM(v) (((v) & 0x3) << 30)
+
+ #define MXC_CCM_CCGR1_TMAX1_OFFSET 0
+ #define MXC_CCM_CCGR1_TMAX1(v) (((v) & 0x3) << 0)
+ #define MXC_CCM_CCGR1_TMAX2_OFFSET 2
+ #define MXC_CCM_CCGR1_TMAX2(v) (((v) & 0x3) << 2)
+ #define MXC_CCM_CCGR1_TMAX3_OFFSET 4
+ #define MXC_CCM_CCGR1_TMAX3(v) (((v) & 0x3) << 4)
+ #define MXC_CCM_CCGR1_UART1_IPG_OFFSET 6
+ #define MXC_CCM_CCGR1_UART1_IPG(v) (((v) & 0x3) << 6)
+ #define MXC_CCM_CCGR1_UART1_PER_OFFSET 8
+ #define MXC_CCM_CCGR1_UART1_PER(v) (((v) & 0x3) << 8)
+ #define MXC_CCM_CCGR1_UART2_IPG_OFFSET 10
+ #define MXC_CCM_CCGR1_UART2_IPG(v) (((v) & 0x3) << 10)
+ #define MXC_CCM_CCGR1_UART2_PER_OFFSET 12
+ #define MXC_CCM_CCGR1_UART2_PER(v) (((v) & 0x3) << 12)
+ #define MXC_CCM_CCGR1_UART3_IPG_OFFSET 14
+ #define MXC_CCM_CCGR1_UART3_IPG(v) (((v) & 0x3) << 14)
+ #define MXC_CCM_CCGR1_UART3_PER_OFFSET 16
+ #define MXC_CCM_CCGR1_UART3_PER(v) (((v) & 0x3) << 16)
+ #define MXC_CCM_CCGR1_I2C1_OFFSET 18
+ #define MXC_CCM_CCGR1_I2C1(v) (((v) & 0x3) << 18)
+ #define MXC_CCM_CCGR1_I2C2_OFFSET 20
+ #define MXC_CCM_CCGR1_I2C2(v) (((v) & 0x3) << 20)
+ #if defined(CONFIG_MX51)
+ #define MXC_CCM_CCGR1_HSI2C_IPG_OFFSET 22
+ #define MXC_CCM_CCGR1_HSI2C_IPG(v) (((v) & 0x3) << 22)
+ #define MXC_CCM_CCGR1_HSI2C_SERIAL_OFFSET 24
+ #define MXC_CCM_CCGR1_HSI2C_SERIAL(v) (((v) & 0x3) << 24)
+ #elif defined(CONFIG_MX53)
+ #define MXC_CCM_CCGR1_I2C3_OFFSET 22
+ #define MXC_CCM_CCGR1_I2C3(v) (((v) & 0x3) << 22)
+ #endif
+ #define MXC_CCM_CCGR1_FIRI_IPG_OFFSET 26
+ #define MXC_CCM_CCGR1_FIRI_IPG(v) (((v) & 0x3) << 26)
+ #define MXC_CCM_CCGR1_FIRI_SERIAL_OFFSET 28
+ #define MXC_CCM_CCGR1_FIRI_SERIAL(v) (((v) & 0x3) << 28)
+ #define MXC_CCM_CCGR1_SCC_OFFSET 30
+ #define MXC_CCM_CCGR1_SCC(v) (((v) & 0x3) << 30)
+
+ #if defined(CONFIG_MX51)
+ #define MXC_CCM_CCGR2_USB_PHY_OFFSET 0
+ #define MXC_CCM_CCGR2_USB_PHY(v) (((v) & 0x3) << 0)
+ #endif
+ #define MXC_CCM_CCGR2_EPIT1_IPG_OFFSET 2
+ #define MXC_CCM_CCGR2_EPIT1_IPG(v) (((v) & 0x3) << 2)
+ #define MXC_CCM_CCGR2_EPIT1_HF_OFFSET 4
+ #define MXC_CCM_CCGR2_EPIT1_HF(v) (((v) & 0x3) << 4)
+ #define MXC_CCM_CCGR2_EPIT2_IPG_OFFSET 6
+ #define MXC_CCM_CCGR2_EPIT2_IPG(v) (((v) & 0x3) << 6)
+ #define MXC_CCM_CCGR2_EPIT2_HF_OFFSET 8
+ #define MXC_CCM_CCGR2_EPIT2_HF(v) (((v) & 0x3) << 8)
+ #define MXC_CCM_CCGR2_PWM1_IPG_OFFSET 10
+ #define MXC_CCM_CCGR2_PWM1_IPG(v) (((v) & 0x3) << 10)
+ #define MXC_CCM_CCGR2_PWM1_HF_OFFSET 12
+ #define MXC_CCM_CCGR2_PWM1_HF(v) (((v) & 0x3) << 12)
+ #define MXC_CCM_CCGR2_PWM2_IPG_OFFSET 14
+ #define MXC_CCM_CCGR2_PWM2_IPG(v) (((v) & 0x3) << 14)
+ #define MXC_CCM_CCGR2_PWM2_HF_OFFSET 16
+ #define MXC_CCM_CCGR2_PWM2_HF(v) (((v) & 0x3) << 16)
+ #define MXC_CCM_CCGR2_GPT_IPG_OFFSET 18
+ #define MXC_CCM_CCGR2_GPT_IPG(v) (((v) & 0x3) << 18)
+ #define MXC_CCM_CCGR2_GPT_HF_OFFSET 20
+ #define MXC_CCM_CCGR2_GPT_HF(v) (((v) & 0x3) << 20)
+ #define MXC_CCM_CCGR2_OWIRE_OFFSET 22
+ #define MXC_CCM_CCGR2_OWIRE(v) (((v) & 0x3) << 22)
+ #define MXC_CCM_CCGR2_FEC_OFFSET 24
+ #define MXC_CCM_CCGR2_FEC(v) (((v) & 0x3) << 24)
+ #define MXC_CCM_CCGR2_USBOH3_IPG_AHB_OFFSET 26
+ #define MXC_CCM_CCGR2_USBOH3_IPG_AHB(v) (((v) & 0x3) << 26)
+ #define MXC_CCM_CCGR2_USBOH3_60M_OFFSET 28
+ #define MXC_CCM_CCGR2_USBOH3_60M(v) (((v) & 0x3) << 28)
+ #define MXC_CCM_CCGR2_TVE_OFFSET 30
+ #define MXC_CCM_CCGR2_TVE(v) (((v) & 0x3) << 30)
- #define MXC_CCM_CCGR4_CG5_OFFSET 10
- #define MXC_CCM_CCGR4_CG6_OFFSET 12
- #define MXC_CCM_CCGR5_CG5_OFFSET 10
- #define MXC_CCM_CCGR2_CG14_OFFSET 28
+ #define MXC_CCM_CCGR3_ESDHC1_IPG_OFFSET 0
+ #define MXC_CCM_CCGR3_ESDHC1_IPG(v) (((v) & 0x3) << 0)
+ #define MXC_CCM_CCGR3_ESDHC1_PER_OFFSET 2
+ #define MXC_CCM_CCGR3_ESDHC1_PER(v) (((v) & 0x3) << 2)
+ #define MXC_CCM_CCGR3_ESDHC2_IPG_OFFSET 4
+ #define MXC_CCM_CCGR3_ESDHC2_IPG(v) (((v) & 0x3) << 4)
+ #define MXC_CCM_CCGR3_ESDHC2_PER_OFFSET 6
+ #define MXC_CCM_CCGR3_ESDHC2_PER(v) (((v) & 0x3) << 6)
+ #define MXC_CCM_CCGR3_ESDHC3_IPG_OFFSET 8
+ #define MXC_CCM_CCGR3_ESDHC3_IPG(v) (((v) & 0x3) << 8)
+ #define MXC_CCM_CCGR3_ESDHC3_PER_OFFSET 10
+ #define MXC_CCM_CCGR3_ESDHC3_PER(v) (((v) & 0x3) << 10)
+ #define MXC_CCM_CCGR3_ESDHC4_IPG_OFFSET 12
+ #define MXC_CCM_CCGR3_ESDHC4_IPG(v) (((v) & 0x3) << 12)
+ #define MXC_CCM_CCGR3_ESDHC4_PER_OFFSET 14
+ #define MXC_CCM_CCGR3_ESDHC4_PER(v) (((v) & 0x3) << 14)
+ #define MXC_CCM_CCGR3_SSI1_IPG_OFFSET 16
+ #define MXC_CCM_CCGR3_SSI1_IPG(v) (((v) & 0x3) << 16)
+ #define MXC_CCM_CCGR3_SSI1_SSI_OFFSET 18
+ #define MXC_CCM_CCGR3_SSI1_SSI(v) (((v) & 0x3) << 18)
+ #define MXC_CCM_CCGR3_SSI2_IPG_OFFSET 20
+ #define MXC_CCM_CCGR3_SSI2_IPG(v) (((v) & 0x3) << 20)
+ #define MXC_CCM_CCGR3_SSI2_SSI_OFFSET 22
+ #define MXC_CCM_CCGR3_SSI2_SSI(v) (((v) & 0x3) << 22)
+ #define MXC_CCM_CCGR3_SSI3_IPG_OFFSET 24
+ #define MXC_CCM_CCGR3_SSI3_IPG(v) (((v) & 0x3) << 24)
+ #define MXC_CCM_CCGR3_SSI3_SSI_OFFSET 26
+ #define MXC_CCM_CCGR3_SSI3_SSI(v) (((v) & 0x3) << 26)
+ #define MXC_CCM_CCGR3_SSI_EXT1_OFFSET 28
+ #define MXC_CCM_CCGR3_SSI_EXT1(v) (((v) & 0x3) << 28)
+ #define MXC_CCM_CCGR3_SSI_EXT2_OFFSET 30
+ #define MXC_CCM_CCGR3_SSI_EXT2(v) (((v) & 0x3) << 30)
+
+ #define MXC_CCM_CCGR4_PATA_OFFSET 0
+ #define MXC_CCM_CCGR4_PATA(v) (((v) & 0x3) << 0)
+ #if defined(CONFIG_MX51)
+ #define MXC_CCM_CCGR4_SIM_IPG_OFFSET 2
+ #define MXC_CCM_CCGR4_SIM_IPG(v) (((v) & 0x3) << 2)
+ #define MXC_CCM_CCGR4_SIM_SERIAL_OFFSET 4
+ #define MXC_CCM_CCGR4_SIM_SERIAL(v) (((v) & 0x3) << 4)
+ #elif defined(CONFIG_MX53)
+ #define MXC_CCM_CCGR4_SATA_OFFSET 2
+ #define MXC_CCM_CCGR4_SATA(v) (((v) & 0x3) << 2)
+ #define MXC_CCM_CCGR4_CAN2_IPG_OFFSET 6
+ #define MXC_CCM_CCGR4_CAN2_IPG(v) (((v) & 0x3) << 6)
+ #define MXC_CCM_CCGR4_CAN2_SERIAL_OFFSET 8
+ #define MXC_CCM_CCGR4_CAN2_SERIAL(v) (((v) & 0x3) << 8)
+ #define MXC_CCM_CCGR4_USB_PHY1_OFFSET 10
+ #define MXC_CCM_CCGR4_USB_PHY1(v) (((v) & 0x3) << 10)
+ #define MXC_CCM_CCGR4_USB_PHY2_OFFSET 12
+ #define MXC_CCM_CCGR4_USB_PHY2(v) (((v) & 0x3) << 12)
+ #endif
+ #define MXC_CCM_CCGR4_SAHARA_OFFSET 14
+ #define MXC_CCM_CCGR4_SAHARA(v) (((v) & 0x3) << 14)
+ #define MXC_CCM_CCGR4_RTIC_OFFSET 16
+ #define MXC_CCM_CCGR4_RTIC(v) (((v) & 0x3) << 16)
+ #define MXC_CCM_CCGR4_ECSPI1_IPG_OFFSET 18
+ #define MXC_CCM_CCGR4_ECSPI1_IPG(v) (((v) & 0x3) << 18)
+ #define MXC_CCM_CCGR4_ECSPI1_PER_OFFSET 20
+ #define MXC_CCM_CCGR4_ECSPI1_PER(v) (((v) & 0x3) << 20)
+ #define MXC_CCM_CCGR4_ECSPI2_IPG_OFFSET 22
+ #define MXC_CCM_CCGR4_ECSPI2_IPG(v) (((v) & 0x3) << 22)
+ #define MXC_CCM_CCGR4_ECSPI2_PER_OFFSET 24
+ #define MXC_CCM_CCGR4_ECSPI2_PER(v) (((v) & 0x3) << 24)
+ #define MXC_CCM_CCGR4_CSPI_IPG_OFFSET 26
+ #define MXC_CCM_CCGR4_CSPI_IPG(v) (((v) & 0x3) << 26)
+ #define MXC_CCM_CCGR4_SRTC_OFFSET &nb