Commit 04fe4273d3a3a6d0a0de25d6bfa91e89917d60fb

Authored by Marek Vasut
Committed by Stefano Babic
1 parent fc10272856
Exists in master and in 55 other branches 8qm-imx_v2020.04_5.4.70_2.3.0, emb_lf_v2022.04, emb_lf_v2023.04, imx_v2015.04_4.1.15_1.0.0_ga, pitx_8mp_lf_v2020.04, smarc-8m-android-10.0.0_2.6.0, smarc-8m-android-11.0.0_2.0.0, smarc-8mp-android-11.0.0_2.0.0, smarc-emmc-imx_v2014.04_3.10.53_1.1.0_ga, smarc-emmc-imx_v2014.04_3.14.28_1.0.0_ga, smarc-imx-l5.0.0_1.0.0-ga, smarc-imx6_v2018.03_4.14.98_2.0.0_ga, smarc-imx7_v2017.03_4.9.11_1.0.0_ga, smarc-imx7_v2018.03_4.14.98_2.0.0_ga, smarc-imx_v2014.04_3.14.28_1.0.0_ga, smarc-imx_v2015.04_4.1.15_1.0.0_ga, smarc-imx_v2017.03_4.9.11_1.0.0_ga, smarc-imx_v2017.03_4.9.88_2.0.0_ga, smarc-imx_v2017.03_o8.1.0_1.3.0_8m, smarc-imx_v2018.03_4.14.78_1.0.0_ga, smarc-m6.0.1_2.1.0-ga, smarc-n7.1.2_2.0.0-ga, smarc-rel_imx_4.1.15_2.0.0_ga, smarc_8m-imx_v2018.03_4.14.98_2.0.0_ga, smarc_8m-imx_v2019.04_4.19.35_1.1.0, smarc_8m_00d0-imx_v2018.03_4.14.98_2.0.0_ga, smarc_8mm-imx_v2018.03_4.14.98_2.0.0_ga, smarc_8mm-imx_v2019.04_4.19.35_1.1.0, smarc_8mm-imx_v2020.04_5.4.24_2.1.0, smarc_8mp_lf_v2020.04, smarc_8mq-imx_v2020.04_5.4.24_2.1.0, smarc_8mq_lf_v2020.04, ti-u-boot-2015.07, u-boot-2013.01.y, v2013.10, v2013.10-smarct33, v2013.10-smartmen, v2014.01, v2014.04, v2014.04-smarct33, v2014.04-smarct33-emmc, v2014.04-smartmen, v2014.07, v2014.07-smarct33, v2014.07-smartmen, v2015.07-smarct33, v2015.07-smarct33-emmc, v2015.07-smarct4x, v2016.05-dlt, v2016.05-smarct3x, v2016.05-smarct3x-emmc, v2016.05-smarct4x, v2017.01-smarct3x, v2017.01-smarct3x-emmc, v2017.01-smarct4x

M28: Add MMC SPL

This patch adds SPL code for the M28 board.

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Andy Fleming <afleming@gmail.com>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>

Showing 9 changed files with 1953 additions and 0 deletions Side-by-side Diff

board/denx/m28evk/Makefile
... ... @@ -25,13 +25,21 @@
25 25  
26 26 LIB = $(obj)lib$(BOARD).o
27 27  
  28 +ifndef CONFIG_SPL_BUILD
28 29 COBJS := m28evk.o
  30 +endif
29 31  
  32 +ifdef CONFIG_SPL_BUILD
  33 +COBJS := mem_init.o mmc_boot.o power_init.o
  34 +endif
  35 +
30 36 SRCS := $(COBJS:.o=.c)
31 37 OBJS := $(addprefix $(obj),$(COBJS))
32 38  
33 39 $(LIB): $(obj).depend $(OBJS)
34 40 $(call cmd_link_o_target, $(OBJS))
  41 +
  42 +all: $(ALL)
35 43  
36 44 #########################################################################
37 45  
board/denx/m28evk/m28_init.h
  1 +/*
  2 + * Freescale i.MX28 SPL functions
  3 + *
  4 + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
  5 + * on behalf of DENX Software Engineering GmbH
  6 + *
  7 + * See file CREDITS for list of people who contributed to this
  8 + * project.
  9 + *
  10 + * This program is free software; you can redistribute it and/or
  11 + * modify it under the terms of the GNU General Public License as
  12 + * published by the Free Software Foundation; either version 2 of
  13 + * the License, or (at your option) any later version.
  14 + *
  15 + * This program is distributed in the hope that it will be useful,
  16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18 + * GNU General Public License for more details.
  19 + *
  20 + * You should have received a copy of the GNU General Public License
  21 + * along with this program; if not, write to the Free Software
  22 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  23 + * MA 02111-1307 USA
  24 + */
  25 +
  26 +#ifndef __M28_INIT_H__
  27 +#define __M28_INIT_H__
  28 +
  29 +void early_delay(int delay);
  30 +
  31 +void mx28_power_init(void);
  32 +
  33 +#ifdef CONFIG_SPL_MX28_PSWITCH_WAIT
  34 +void mx28_power_wait_pswitch(void);
  35 +#else
  36 +static inline void mx28_power_wait_pswitch(void) { }
  37 +#endif
  38 +
  39 +void mx28_mem_init(void);
  40 +
  41 +#endif /* __M28_INIT_H__ */
board/denx/m28evk/mem_init.c
  1 +/*
  2 + * Freescale i.MX28 RAM init
  3 + *
  4 + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
  5 + * on behalf of DENX Software Engineering GmbH
  6 + *
  7 + * See file CREDITS for list of people who contributed to this
  8 + * project.
  9 + *
  10 + * This program is free software; you can redistribute it and/or
  11 + * modify it under the terms of the GNU General Public License as
  12 + * published by the Free Software Foundation; either version 2 of
  13 + * the License, or (at your option) any later version.
  14 + *
  15 + * This program is distributed in the hope that it will be useful,
  16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18 + * GNU General Public License for more details.
  19 + *
  20 + * You should have received a copy of the GNU General Public License
  21 + * along with this program; if not, write to the Free Software
  22 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  23 + * MA 02111-1307 USA
  24 + */
  25 +
  26 +#include <common.h>
  27 +#include <config.h>
  28 +#include <asm/io.h>
  29 +#include <asm/arch/iomux-mx28.h>
  30 +#include <asm/arch/imx-regs.h>
  31 +
  32 +#include "m28_init.h"
  33 +
  34 +uint32_t dram_vals[] = {
  35 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  36 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  37 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  38 + 0x00000000, 0x00000000, 0x00000100, 0x00000000, 0x00000000,
  39 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  40 + 0x00000000, 0x00010101, 0x01010101, 0x000f0f01, 0x0f02020a,
  41 + 0x00000000, 0x00010101, 0x00000100, 0x00000100, 0x00000000,
  42 + 0x00000002, 0x01010000, 0x05060302, 0x06005003, 0x0a0000c8,
  43 + 0x02009c40, 0x0000030c, 0x0036a609, 0x031a0612, 0x02030202,
  44 + 0x00c8001c, 0x00000000, 0x00000000, 0x00012100, 0xffff0303,
  45 + 0x00012100, 0xffff0303, 0x00012100, 0xffff0303, 0x00012100,
  46 + 0xffff0303, 0x00000003, 0x00000000, 0x00000000, 0x00000000,
  47 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  48 + 0x00000000, 0x00000612, 0x01000F02, 0x06120612, 0x00000200,
  49 + 0x00020007, 0xf5014b27, 0xf5014b27, 0xf5014b27, 0xf5014b27,
  50 + 0x07000300, 0x07000300, 0x07000300, 0x07000300, 0x00000006,
  51 + 0x00000000, 0x00000000, 0x01000000, 0x01020408, 0x08040201,
  52 + 0x000f1133, 0x00000000, 0x00001f04, 0x00001f04, 0x00001f04,
  53 + 0x00001f04, 0x00001f04, 0x00001f04, 0x00001f04, 0x00001f04,
  54 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  55 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  56 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  57 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  58 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  59 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  60 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  61 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  62 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  63 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  64 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  65 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  66 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  67 + 0x00000000, 0x00000000, 0x00010000, 0x00020304, 0x00000004,
  68 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  69 + 0x00000000, 0x01010000, 0x01000000, 0x03030000, 0x00010303,
  70 + 0x01020202, 0x00000000, 0x02040303, 0x21002103, 0x00061200,
  71 + 0x06120612, 0x04320432, 0x04320432, 0x00040004, 0x00040004,
  72 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010001
  73 +};
  74 +
  75 +void init_m28_200mhz_ddr2(void)
  76 +{
  77 + int i;
  78 +
  79 + for (i = 0; i < ARRAY_SIZE(dram_vals); i++)
  80 + writel(dram_vals[i], MXS_DRAM_BASE + (4 * i));
  81 +}
  82 +
  83 +void mx28_mem_init_clock(void)
  84 +{
  85 + struct mx28_clkctrl_regs *clkctrl_regs =
  86 + (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
  87 +
  88 + /* Gate EMI clock */
  89 + writel(CLKCTRL_FRAC0_CLKGATEEMI,
  90 + &clkctrl_regs->hw_clkctrl_frac0_set);
  91 +
  92 + /* EMI = 205MHz */
  93 + writel(CLKCTRL_FRAC0_EMIFRAC_MASK,
  94 + &clkctrl_regs->hw_clkctrl_frac0_set);
  95 + writel((0x2a << CLKCTRL_FRAC0_EMIFRAC_OFFSET) &
  96 + CLKCTRL_FRAC0_EMIFRAC_MASK,
  97 + &clkctrl_regs->hw_clkctrl_frac0_clr);
  98 +
  99 + /* Ungate EMI clock */
  100 + writel(CLKCTRL_FRAC0_CLKGATEEMI,
  101 + &clkctrl_regs->hw_clkctrl_frac0_clr);
  102 +
  103 + early_delay(11000);
  104 +
  105 + writel((2 << CLKCTRL_EMI_DIV_EMI_OFFSET) |
  106 + (1 << CLKCTRL_EMI_DIV_XTAL_OFFSET),
  107 + &clkctrl_regs->hw_clkctrl_emi);
  108 +
  109 + /* Unbypass EMI */
  110 + writel(CLKCTRL_CLKSEQ_BYPASS_EMI,
  111 + &clkctrl_regs->hw_clkctrl_clkseq_clr);
  112 +
  113 + early_delay(10000);
  114 +}
  115 +
  116 +void mx28_mem_setup_cpu_and_hbus(void)
  117 +{
  118 + struct mx28_clkctrl_regs *clkctrl_regs =
  119 + (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
  120 +
  121 + /* CPU = 454MHz and ungate CPU clock */
  122 + clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0,
  123 + CLKCTRL_FRAC0_CPUFRAC_MASK | CLKCTRL_FRAC0_CLKGATECPU,
  124 + 19 << CLKCTRL_FRAC0_CPUFRAC_OFFSET);
  125 +
  126 + /* Set CPU bypass */
  127 + writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
  128 + &clkctrl_regs->hw_clkctrl_clkseq_set);
  129 +
  130 + /* HBUS = 151MHz */
  131 + writel(CLKCTRL_HBUS_DIV_MASK, &clkctrl_regs->hw_clkctrl_hbus_set);
  132 + writel(((~3) << CLKCTRL_HBUS_DIV_OFFSET) & CLKCTRL_HBUS_DIV_MASK,
  133 + &clkctrl_regs->hw_clkctrl_hbus_clr);
  134 +
  135 + early_delay(10000);
  136 +
  137 + /* CPU clock divider = 1 */
  138 + clrsetbits_le32(&clkctrl_regs->hw_clkctrl_cpu,
  139 + CLKCTRL_CPU_DIV_CPU_MASK, 1);
  140 +
  141 + /* Disable CPU bypass */
  142 + writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
  143 + &clkctrl_regs->hw_clkctrl_clkseq_clr);
  144 +}
  145 +
  146 +void mx28_mem_setup_vdda(void)
  147 +{
  148 + struct mx28_power_regs *power_regs =
  149 + (struct mx28_power_regs *)MXS_POWER_BASE;
  150 +
  151 + writel((0xc << POWER_VDDACTRL_TRG_OFFSET) |
  152 + (0x7 << POWER_VDDACTRL_BO_OFFSET_OFFSET) |
  153 + POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW,
  154 + &power_regs->hw_power_vddactrl);
  155 +}
  156 +
  157 +void mx28_mem_setup_vddd(void)
  158 +{
  159 + struct mx28_power_regs *power_regs =
  160 + (struct mx28_power_regs *)MXS_POWER_BASE;
  161 +
  162 + writel((0x1c << POWER_VDDDCTRL_TRG_OFFSET) |
  163 + (0x7 << POWER_VDDDCTRL_BO_OFFSET_OFFSET) |
  164 + POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW,
  165 + &power_regs->hw_power_vdddctrl);
  166 +}
  167 +
  168 +void mx28_mem_init(void)
  169 +{
  170 + struct mx28_clkctrl_regs *clkctrl_regs =
  171 + (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
  172 + struct mx28_pinctrl_regs *pinctrl_regs =
  173 + (struct mx28_pinctrl_regs *)MXS_PINCTRL_BASE;
  174 +
  175 + /* Set DDR2 mode */
  176 + writel(PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2,
  177 + &pinctrl_regs->hw_pinctrl_emi_ds_ctrl_set);
  178 +
  179 + /* Power up PLL0 */
  180 + writel(CLKCTRL_PLL0CTRL0_POWER,
  181 + &clkctrl_regs->hw_clkctrl_pll0ctrl0_set);
  182 +
  183 + early_delay(11000);
  184 +
  185 + mx28_mem_init_clock();
  186 +
  187 + mx28_mem_setup_vdda();
  188 +
  189 + /*
  190 + * Configure the DRAM registers
  191 + */
  192 +
  193 + /* Clear START bit from DRAM_CTL16 */
  194 + clrbits_le32(MXS_DRAM_BASE + 0x40, 1);
  195 +
  196 + init_m28_200mhz_ddr2();
  197 +
  198 + /* Clear SREFRESH bit from DRAM_CTL17 */
  199 + clrbits_le32(MXS_DRAM_BASE + 0x44, 1);
  200 +
  201 + /* Set START bit in DRAM_CTL16 */
  202 + setbits_le32(MXS_DRAM_BASE + 0x40, 1);
  203 +
  204 + /* Wait for bit 20 (DRAM init complete) in DRAM_CTL58 */
  205 + while (!(readl(MXS_DRAM_BASE + 0xe8) & (1 << 20)))
  206 + ;
  207 +
  208 + mx28_mem_setup_vddd();
  209 +
  210 + early_delay(10000);
  211 +
  212 + mx28_mem_setup_cpu_and_hbus();
  213 +}
board/denx/m28evk/mmc_boot.c
  1 +/*
  2 + * Freescale i.MX28 Boot setup
  3 + *
  4 + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
  5 + * on behalf of DENX Software Engineering GmbH
  6 + *
  7 + * See file CREDITS for list of people who contributed to this
  8 + * project.
  9 + *
  10 + * This program is free software; you can redistribute it and/or
  11 + * modify it under the terms of the GNU General Public License as
  12 + * published by the Free Software Foundation; either version 2 of
  13 + * the License, or (at your option) any later version.
  14 + *
  15 + * This program is distributed in the hope that it will be useful,
  16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18 + * GNU General Public License for more details.
  19 + *
  20 + * You should have received a copy of the GNU General Public License
  21 + * along with this program; if not, write to the Free Software
  22 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  23 + * MA 02111-1307 USA
  24 + */
  25 +
  26 +#include <common.h>
  27 +#include <config.h>
  28 +#include <asm/io.h>
  29 +#include <asm/arch/iomux-mx28.h>
  30 +
  31 +#include "m28_init.h"
  32 +
  33 +/*
  34 + * This delay function is intended to be used only in early stage of boot, where
  35 + * clock are not set up yet. The timer used here is reset on every boot and
  36 + * takes a few seconds to roll. The boot doesn't take that long, so to keep the
  37 + * code simple, it doesn't take rolling into consideration.
  38 + */
  39 +#define HW_DIGCTRL_MICROSECONDS 0x8001c0c0
  40 +void early_delay(int delay)
  41 +{
  42 + uint32_t st = readl(HW_DIGCTRL_MICROSECONDS);
  43 + st += delay;
  44 + while (st > readl(HW_DIGCTRL_MICROSECONDS))
  45 + ;
  46 +}
  47 +
  48 +#define MUX_CONFIG_LED (MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL)
  49 +#define MUX_CONFIG_LCD (MXS_PAD_3V3 | MXS_PAD_4MA)
  50 +#define MUX_CONFIG_TSC (MXS_PAD_3V3 | MXS_PAD_8MA | MXS_PAD_PULLUP)
  51 +#define MUX_CONFIG_SSP0 (MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_PULLUP)
  52 +#define MUX_CONFIG_SSP2 (MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_PULLUP)
  53 +#define MUX_CONFIG_GPMI (MXS_PAD_1V8 | MXS_PAD_4MA | MXS_PAD_NOPULL)
  54 +#define MUX_CONFIG_ENET (MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_PULLUP)
  55 +#define MUX_CONFIG_EMI (MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL)
  56 +
  57 +const iomux_cfg_t iomux_setup[] = {
  58 + /* LED */
  59 + MX28_PAD_ENET0_RXD3__GPIO_4_10 | MUX_CONFIG_LED,
  60 +
  61 + /* framebuffer */
  62 + MX28_PAD_LCD_D00__LCD_D0 | MUX_CONFIG_LCD,
  63 + MX28_PAD_LCD_D01__LCD_D1 | MUX_CONFIG_LCD,
  64 + MX28_PAD_LCD_D02__LCD_D2 | MUX_CONFIG_LCD,
  65 + MX28_PAD_LCD_D03__LCD_D3 | MUX_CONFIG_LCD,
  66 + MX28_PAD_LCD_D04__LCD_D4 | MUX_CONFIG_LCD,
  67 + MX28_PAD_LCD_D05__LCD_D5 | MUX_CONFIG_LCD,
  68 + MX28_PAD_LCD_D06__LCD_D6 | MUX_CONFIG_LCD,
  69 + MX28_PAD_LCD_D07__LCD_D7 | MUX_CONFIG_LCD,
  70 + MX28_PAD_LCD_D08__LCD_D8 | MUX_CONFIG_LCD,
  71 + MX28_PAD_LCD_D09__LCD_D9 | MUX_CONFIG_LCD,
  72 + MX28_PAD_LCD_D10__LCD_D10 | MUX_CONFIG_LCD,
  73 + MX28_PAD_LCD_D11__LCD_D11 | MUX_CONFIG_LCD,
  74 + MX28_PAD_LCD_D12__LCD_D12 | MUX_CONFIG_LCD,
  75 + MX28_PAD_LCD_D13__LCD_D13 | MUX_CONFIG_LCD,
  76 + MX28_PAD_LCD_D14__LCD_D14 | MUX_CONFIG_LCD,
  77 + MX28_PAD_LCD_D15__LCD_D15 | MUX_CONFIG_LCD,
  78 + MX28_PAD_LCD_D16__LCD_D16 | MUX_CONFIG_LCD,
  79 + MX28_PAD_LCD_D17__LCD_D17 | MUX_CONFIG_LCD,
  80 + MX28_PAD_LCD_D18__LCD_D18 | MUX_CONFIG_LCD,
  81 + MX28_PAD_LCD_D19__LCD_D19 | MUX_CONFIG_LCD,
  82 + MX28_PAD_LCD_D20__LCD_D20 | MUX_CONFIG_LCD,
  83 + MX28_PAD_LCD_D21__LCD_D21 | MUX_CONFIG_LCD,
  84 + MX28_PAD_LCD_D22__LCD_D22 | MUX_CONFIG_LCD,
  85 + MX28_PAD_LCD_D23__LCD_D23 | MUX_CONFIG_LCD,
  86 + MX28_PAD_LCD_RD_E__LCD_VSYNC | MUX_CONFIG_LCD,
  87 + MX28_PAD_LCD_WR_RWN__LCD_HSYNC | MUX_CONFIG_LCD,
  88 + MX28_PAD_LCD_RS__LCD_DOTCLK | MUX_CONFIG_LCD,
  89 + MX28_PAD_LCD_CS__LCD_CS | MUX_CONFIG_LCD,
  90 + MX28_PAD_LCD_VSYNC__LCD_VSYNC | MUX_CONFIG_LCD,
  91 + MX28_PAD_LCD_HSYNC__LCD_HSYNC | MUX_CONFIG_LCD,
  92 + MX28_PAD_LCD_DOTCLK__LCD_DOTCLK | MUX_CONFIG_LCD,
  93 + MX28_PAD_LCD_ENABLE__GPIO_1_31 | MUX_CONFIG_LCD,
  94 + MX28_PAD_LCD_RESET__GPIO_3_30 | MUX_CONFIG_LCD,
  95 +
  96 + /* UART1 */
  97 + MX28_PAD_PWM0__DUART_RX,
  98 + MX28_PAD_PWM1__DUART_TX,
  99 + MX28_PAD_AUART0_TX__DUART_RTS,
  100 + MX28_PAD_AUART0_RX__DUART_CTS,
  101 +
  102 + /* UART2 */
  103 + MX28_PAD_AUART1_RX__AUART1_RX,
  104 + MX28_PAD_AUART1_TX__AUART1_TX,
  105 + MX28_PAD_AUART1_RTS__AUART1_RTS,
  106 + MX28_PAD_AUART1_CTS__AUART1_CTS,
  107 +
  108 + /* CAN */
  109 + MX28_PAD_GPMI_RDY2__CAN0_TX,
  110 + MX28_PAD_GPMI_RDY3__CAN0_RX,
  111 +
  112 + /* I2C */
  113 + MX28_PAD_I2C0_SCL__I2C0_SCL,
  114 + MX28_PAD_I2C0_SDA__I2C0_SDA,
  115 +
  116 + /* TSC2007 */
  117 + MX28_PAD_SAIF0_MCLK__GPIO_3_20 | MUX_CONFIG_TSC,
  118 +
  119 + /* MMC0 */
  120 + MX28_PAD_SSP0_DATA0__SSP0_D0 | MUX_CONFIG_SSP0,
  121 + MX28_PAD_SSP0_DATA1__SSP0_D1 | MUX_CONFIG_SSP0,
  122 + MX28_PAD_SSP0_DATA2__SSP0_D2 | MUX_CONFIG_SSP0,
  123 + MX28_PAD_SSP0_DATA3__SSP0_D3 | MUX_CONFIG_SSP0,
  124 + MX28_PAD_SSP0_DATA4__SSP0_D4 | MUX_CONFIG_SSP0,
  125 + MX28_PAD_SSP0_DATA5__SSP0_D5 | MUX_CONFIG_SSP0,
  126 + MX28_PAD_SSP0_DATA6__SSP0_D6 | MUX_CONFIG_SSP0,
  127 + MX28_PAD_SSP0_DATA7__SSP0_D7 | MUX_CONFIG_SSP0,
  128 + MX28_PAD_SSP0_CMD__SSP0_CMD | MUX_CONFIG_SSP0,
  129 + MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT |
  130 + (MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL),
  131 + MX28_PAD_SSP0_SCK__SSP0_SCK |
  132 + (MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL),
  133 + MX28_PAD_PWM3__GPIO_3_28 | MUX_CONFIG_SSP0, /* Power .. FIXME */
  134 + MX28_PAD_AUART2_CTS__GPIO_3_10, /* WP ... FIXME */
  135 +
  136 + /* GPMI NAND */
  137 + MX28_PAD_GPMI_D00__GPMI_D0 | MUX_CONFIG_GPMI,
  138 + MX28_PAD_GPMI_D01__GPMI_D1 | MUX_CONFIG_GPMI,
  139 + MX28_PAD_GPMI_D02__GPMI_D2 | MUX_CONFIG_GPMI,
  140 + MX28_PAD_GPMI_D03__GPMI_D3 | MUX_CONFIG_GPMI,
  141 + MX28_PAD_GPMI_D04__GPMI_D4 | MUX_CONFIG_GPMI,
  142 + MX28_PAD_GPMI_D05__GPMI_D5 | MUX_CONFIG_GPMI,
  143 + MX28_PAD_GPMI_D06__GPMI_D6 | MUX_CONFIG_GPMI,
  144 + MX28_PAD_GPMI_D07__GPMI_D7 | MUX_CONFIG_GPMI,
  145 + MX28_PAD_GPMI_CE0N__GPMI_CE0N | MUX_CONFIG_GPMI,
  146 + MX28_PAD_GPMI_RDY0__GPMI_READY0 | MUX_CONFIG_GPMI,
  147 + MX28_PAD_GPMI_RDN__GPMI_RDN |
  148 + (MXS_PAD_1V8 | MXS_PAD_8MA | MXS_PAD_PULLUP),
  149 + MX28_PAD_GPMI_WRN__GPMI_WRN | MUX_CONFIG_GPMI,
  150 + MX28_PAD_GPMI_ALE__GPMI_ALE | MUX_CONFIG_GPMI,
  151 + MX28_PAD_GPMI_CLE__GPMI_CLE | MUX_CONFIG_GPMI,
  152 + MX28_PAD_GPMI_RESETN__GPMI_RESETN | MUX_CONFIG_GPMI,
  153 +
  154 + /* FEC Ethernet */
  155 + MX28_PAD_ENET0_MDC__ENET0_MDC | MUX_CONFIG_ENET,
  156 + MX28_PAD_ENET0_MDIO__ENET0_MDIO | MUX_CONFIG_ENET,
  157 + MX28_PAD_ENET0_RX_EN__ENET0_RX_EN | MUX_CONFIG_ENET,
  158 + MX28_PAD_ENET0_TX_EN__ENET0_TX_EN | MUX_CONFIG_ENET,
  159 + MX28_PAD_ENET0_RXD0__ENET0_RXD0 | MUX_CONFIG_ENET,
  160 + MX28_PAD_ENET0_RXD1__ENET0_RXD1 | MUX_CONFIG_ENET,
  161 + MX28_PAD_ENET0_TXD0__ENET0_TXD0 | MUX_CONFIG_ENET,
  162 + MX28_PAD_ENET0_TXD1__ENET0_TXD1 | MUX_CONFIG_ENET,
  163 + MX28_PAD_ENET_CLK__CLKCTRL_ENET | MUX_CONFIG_ENET,
  164 +
  165 + MX28_PAD_ENET0_COL__ENET1_TX_EN | MUX_CONFIG_ENET,
  166 + MX28_PAD_ENET0_CRS__ENET1_RX_EN | MUX_CONFIG_ENET,
  167 + MX28_PAD_ENET0_RXD2__ENET1_RXD0 | MUX_CONFIG_ENET,
  168 + MX28_PAD_ENET0_RXD3__ENET1_RXD1 | MUX_CONFIG_ENET,
  169 + MX28_PAD_ENET0_TXD2__ENET1_TXD0 | MUX_CONFIG_ENET,
  170 + MX28_PAD_ENET0_TXD3__ENET1_TXD1 | MUX_CONFIG_ENET,
  171 +
  172 + /* I2C */
  173 + MX28_PAD_I2C0_SCL__I2C0_SCL,
  174 + MX28_PAD_I2C0_SDA__I2C0_SDA,
  175 +
  176 + /* EMI */
  177 + MX28_PAD_EMI_D00__EMI_DATA0 | MUX_CONFIG_EMI,
  178 + MX28_PAD_EMI_D01__EMI_DATA1 | MUX_CONFIG_EMI,
  179 + MX28_PAD_EMI_D02__EMI_DATA2 | MUX_CONFIG_EMI,
  180 + MX28_PAD_EMI_D03__EMI_DATA3 | MUX_CONFIG_EMI,
  181 + MX28_PAD_EMI_D04__EMI_DATA4 | MUX_CONFIG_EMI,
  182 + MX28_PAD_EMI_D05__EMI_DATA5 | MUX_CONFIG_EMI,
  183 + MX28_PAD_EMI_D06__EMI_DATA6 | MUX_CONFIG_EMI,
  184 + MX28_PAD_EMI_D07__EMI_DATA7 | MUX_CONFIG_EMI,
  185 + MX28_PAD_EMI_D08__EMI_DATA8 | MUX_CONFIG_EMI,
  186 + MX28_PAD_EMI_D09__EMI_DATA9 | MUX_CONFIG_EMI,
  187 + MX28_PAD_EMI_D10__EMI_DATA10 | MUX_CONFIG_EMI,
  188 + MX28_PAD_EMI_D11__EMI_DATA11 | MUX_CONFIG_EMI,
  189 + MX28_PAD_EMI_D12__EMI_DATA12 | MUX_CONFIG_EMI,
  190 + MX28_PAD_EMI_D13__EMI_DATA13 | MUX_CONFIG_EMI,
  191 + MX28_PAD_EMI_D14__EMI_DATA14 | MUX_CONFIG_EMI,
  192 + MX28_PAD_EMI_D15__EMI_DATA15 | MUX_CONFIG_EMI,
  193 + MX28_PAD_EMI_ODT0__EMI_ODT0 | MUX_CONFIG_EMI,
  194 + MX28_PAD_EMI_DQM0__EMI_DQM0 | MUX_CONFIG_EMI,
  195 + MX28_PAD_EMI_ODT1__EMI_ODT1 | MUX_CONFIG_EMI,
  196 + MX28_PAD_EMI_DQM1__EMI_DQM1 | MUX_CONFIG_EMI,
  197 + MX28_PAD_EMI_DDR_OPEN_FB__EMI_DDR_OPEN_FEEDBACK | MUX_CONFIG_EMI,
  198 + MX28_PAD_EMI_CLK__EMI_CLK | MUX_CONFIG_EMI,
  199 + MX28_PAD_EMI_DQS0__EMI_DQS0 | MUX_CONFIG_EMI,
  200 + MX28_PAD_EMI_DQS1__EMI_DQS1 | MUX_CONFIG_EMI,
  201 + MX28_PAD_EMI_DDR_OPEN__EMI_DDR_OPEN | MUX_CONFIG_EMI,
  202 +
  203 + MX28_PAD_EMI_A00__EMI_ADDR0 | MUX_CONFIG_EMI,
  204 + MX28_PAD_EMI_A01__EMI_ADDR1 | MUX_CONFIG_EMI,
  205 + MX28_PAD_EMI_A02__EMI_ADDR2 | MUX_CONFIG_EMI,
  206 + MX28_PAD_EMI_A03__EMI_ADDR3 | MUX_CONFIG_EMI,
  207 + MX28_PAD_EMI_A04__EMI_ADDR4 | MUX_CONFIG_EMI,
  208 + MX28_PAD_EMI_A05__EMI_ADDR5 | MUX_CONFIG_EMI,
  209 + MX28_PAD_EMI_A06__EMI_ADDR6 | MUX_CONFIG_EMI,
  210 + MX28_PAD_EMI_A07__EMI_ADDR7 | MUX_CONFIG_EMI,
  211 + MX28_PAD_EMI_A08__EMI_ADDR8 | MUX_CONFIG_EMI,
  212 + MX28_PAD_EMI_A09__EMI_ADDR9 | MUX_CONFIG_EMI,
  213 + MX28_PAD_EMI_A10__EMI_ADDR10 | MUX_CONFIG_EMI,
  214 + MX28_PAD_EMI_A11__EMI_ADDR11 | MUX_CONFIG_EMI,
  215 + MX28_PAD_EMI_A12__EMI_ADDR12 | MUX_CONFIG_EMI,
  216 + MX28_PAD_EMI_A13__EMI_ADDR13 | MUX_CONFIG_EMI,
  217 + MX28_PAD_EMI_A14__EMI_ADDR14 | MUX_CONFIG_EMI,
  218 + MX28_PAD_EMI_BA0__EMI_BA0 | MUX_CONFIG_EMI,
  219 + MX28_PAD_EMI_BA1__EMI_BA1 | MUX_CONFIG_EMI,
  220 + MX28_PAD_EMI_BA2__EMI_BA2 | MUX_CONFIG_EMI,
  221 + MX28_PAD_EMI_CASN__EMI_CASN | MUX_CONFIG_EMI,
  222 + MX28_PAD_EMI_RASN__EMI_RASN | MUX_CONFIG_EMI,
  223 + MX28_PAD_EMI_WEN__EMI_WEN | MUX_CONFIG_EMI,
  224 + MX28_PAD_EMI_CE0N__EMI_CE0N | MUX_CONFIG_EMI,
  225 + MX28_PAD_EMI_CE1N__EMI_CE1N | MUX_CONFIG_EMI,
  226 + MX28_PAD_EMI_CKE__EMI_CKE | MUX_CONFIG_EMI,
  227 +
  228 + /* SPI2 (for flash) */
  229 + MX28_PAD_SSP2_SCK__SSP2_SCK | MUX_CONFIG_SSP2,
  230 + MX28_PAD_SSP2_MOSI__SSP2_CMD | MUX_CONFIG_SSP2,
  231 + MX28_PAD_SSP2_MISO__SSP2_D0 | MUX_CONFIG_SSP2,
  232 + MX28_PAD_SSP2_SS0__SSP2_D3 |
  233 + (MXS_PAD_3V3 | MXS_PAD_8MA | MXS_PAD_PULLUP),
  234 +};
  235 +
  236 +void board_init_ll(void)
  237 +{
  238 + mxs_iomux_setup_multiple_pads(iomux_setup, ARRAY_SIZE(iomux_setup));
  239 + mx28_power_init();
  240 + mx28_mem_init();
  241 + mx28_power_wait_pswitch();
  242 +}
  243 +
  244 +/* Support aparatus */
  245 +inline void board_init_f(unsigned long bootflag)
  246 +{
  247 + for (;;)
  248 + ;
  249 +}
  250 +
  251 +inline void board_init_r(gd_t *id, ulong dest_addr)
  252 +{
  253 + for (;;)
  254 + ;
  255 +}
  256 +
  257 +inline int printf(const char *fmt, ...)
  258 +{
  259 + return 0;
  260 +}
  261 +
  262 +inline void __coloured_LED_init(void) {}
  263 +inline void __red_LED_on(void) {}
  264 +void coloured_LED_init(void)
  265 + __attribute__((weak, alias("__coloured_LED_init")));
  266 +void red_LED_on(void)
  267 + __attribute__((weak, alias("__red_LED_on")));
  268 +void hang(void) __attribute__ ((noreturn));
  269 +void hang(void)
  270 +{
  271 + for (;;)
  272 + ;
  273 +}
board/denx/m28evk/power_init.c
  1 +/*
  2 + * Freescale i.MX28 Boot PMIC init
  3 + *
  4 + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
  5 + * on behalf of DENX Software Engineering GmbH
  6 + *
  7 + * See file CREDITS for list of people who contributed to this
  8 + * project.
  9 + *
  10 + * This program is free software; you can redistribute it and/or
  11 + * modify it under the terms of the GNU General Public License as
  12 + * published by the Free Software Foundation; either version 2 of
  13 + * the License, or (at your option) any later version.
  14 + *
  15 + * This program is distributed in the hope that it will be useful,
  16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18 + * GNU General Public License for more details.
  19 + *
  20 + * You should have received a copy of the GNU General Public License
  21 + * along with this program; if not, write to the Free Software
  22 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  23 + * MA 02111-1307 USA
  24 + */
  25 +
  26 +#include <common.h>
  27 +#include <config.h>
  28 +#include <asm/io.h>
  29 +#include <asm/arch/imx-regs.h>
  30 +
  31 +#include "m28_init.h"
  32 +
  33 +void mx28_power_clock2xtal(void)
  34 +{
  35 + struct mx28_clkctrl_regs *clkctrl_regs =
  36 + (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
  37 +
  38 + /* Set XTAL as CPU reference clock */
  39 + writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
  40 + &clkctrl_regs->hw_clkctrl_clkseq_set);
  41 +}
  42 +
  43 +void mx28_power_clock2pll(void)
  44 +{
  45 + struct mx28_clkctrl_regs *clkctrl_regs =
  46 + (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
  47 +
  48 + writel(CLKCTRL_PLL0CTRL0_POWER,
  49 + &clkctrl_regs->hw_clkctrl_pll0ctrl0_set);
  50 + early_delay(100);
  51 + writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
  52 + &clkctrl_regs->hw_clkctrl_clkseq_clr);
  53 +}
  54 +
  55 +void mx28_power_clear_auto_restart(void)
  56 +{
  57 + struct mx28_rtc_regs *rtc_regs =
  58 + (struct mx28_rtc_regs *)MXS_RTC_BASE;
  59 +
  60 + writel(RTC_CTRL_SFTRST, &rtc_regs->hw_rtc_ctrl_clr);
  61 + while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_SFTRST)
  62 + ;
  63 +
  64 + writel(RTC_CTRL_CLKGATE, &rtc_regs->hw_rtc_ctrl_clr);
  65 + while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_CLKGATE)
  66 + ;
  67 +
  68 + /*
  69 + * Due to the hardware design bug of mx28 EVK-A
  70 + * we need to set the AUTO_RESTART bit.
  71 + */
  72 + if (readl(&rtc_regs->hw_rtc_persistent0) & RTC_PERSISTENT0_AUTO_RESTART)
  73 + return;
  74 +
  75 + while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
  76 + ;
  77 +
  78 + setbits_le32(&rtc_regs->hw_rtc_persistent0,
  79 + RTC_PERSISTENT0_AUTO_RESTART);
  80 + writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_set);
  81 + writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_clr);
  82 + while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK)
  83 + ;
  84 + while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_STALE_REGS_MASK)
  85 + ;
  86 +}
  87 +
  88 +void mx28_power_set_linreg(void)
  89 +{
  90 + struct mx28_power_regs *power_regs =
  91 + (struct mx28_power_regs *)MXS_POWER_BASE;
  92 +
  93 + /* Set linear regulator 25mV below switching converter */
  94 + clrsetbits_le32(&power_regs->hw_power_vdddctrl,
  95 + POWER_VDDDCTRL_LINREG_OFFSET_MASK,
  96 + POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
  97 +
  98 + clrsetbits_le32(&power_regs->hw_power_vddactrl,
  99 + POWER_VDDACTRL_LINREG_OFFSET_MASK,
  100 + POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW);
  101 +
  102 + clrsetbits_le32(&power_regs->hw_power_vddioctrl,
  103 + POWER_VDDIOCTRL_LINREG_OFFSET_MASK,
  104 + POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW);
  105 +}
  106 +
  107 +void mx28_power_setup_5v_detect(void)
  108 +{
  109 + struct mx28_power_regs *power_regs =
  110 + (struct mx28_power_regs *)MXS_POWER_BASE;
  111 +
  112 + /* Start 5V detection */
  113 + clrsetbits_le32(&power_regs->hw_power_5vctrl,
  114 + POWER_5VCTRL_VBUSVALID_TRSH_MASK,
  115 + POWER_5VCTRL_VBUSVALID_TRSH_4V4 |
  116 + POWER_5VCTRL_PWRUP_VBUS_CMPS);
  117 +}
  118 +
  119 +void mx28_src_power_init(void)
  120 +{
  121 + struct mx28_power_regs *power_regs =
  122 + (struct mx28_power_regs *)MXS_POWER_BASE;
  123 +
  124 + /* Improve efficieny and reduce transient ripple */
  125 + writel(POWER_LOOPCTRL_TOGGLE_DIF | POWER_LOOPCTRL_EN_CM_HYST |
  126 + POWER_LOOPCTRL_EN_DF_HYST, &power_regs->hw_power_loopctrl_set);
  127 +
  128 + clrsetbits_le32(&power_regs->hw_power_dclimits,
  129 + POWER_DCLIMITS_POSLIMIT_BUCK_MASK,
  130 + 0x30 << POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET);
  131 +
  132 + setbits_le32(&power_regs->hw_power_battmonitor,
  133 + POWER_BATTMONITOR_EN_BATADJ);
  134 +
  135 + /* Increase the RCSCALE level for quick DCDC response to dynamic load */
  136 + clrsetbits_le32(&power_regs->hw_power_loopctrl,
  137 + POWER_LOOPCTRL_EN_RCSCALE_MASK,
  138 + POWER_LOOPCTRL_RCSCALE_THRESH |
  139 + POWER_LOOPCTRL_EN_RCSCALE_8X);
  140 +
  141 + clrsetbits_le32(&power_regs->hw_power_minpwr,
  142 + POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
  143 +
  144 + /* 5V to battery handoff ... FIXME */
  145 + setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
  146 + early_delay(30);
  147 + clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
  148 +}
  149 +
  150 +void mx28_power_init_4p2_params(void)
  151 +{
  152 + struct mx28_power_regs *power_regs =
  153 + (struct mx28_power_regs *)MXS_POWER_BASE;
  154 +
  155 + /* Setup 4P2 parameters */
  156 + clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
  157 + POWER_DCDC4P2_CMPTRIP_MASK | POWER_DCDC4P2_TRG_MASK,
  158 + POWER_DCDC4P2_TRG_4V2 | (31 << POWER_DCDC4P2_CMPTRIP_OFFSET));
  159 +
  160 + clrsetbits_le32(&power_regs->hw_power_5vctrl,
  161 + POWER_5VCTRL_HEADROOM_ADJ_MASK,
  162 + 0x4 << POWER_5VCTRL_HEADROOM_ADJ_OFFSET);
  163 +
  164 + clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
  165 + POWER_DCDC4P2_DROPOUT_CTRL_MASK,
  166 + POWER_DCDC4P2_DROPOUT_CTRL_100MV |
  167 + POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL);
  168 +
  169 + clrsetbits_le32(&power_regs->hw_power_5vctrl,
  170 + POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
  171 + 0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
  172 +}
  173 +
  174 +void mx28_enable_4p2_dcdc_input(int xfer)
  175 +{
  176 + struct mx28_power_regs *power_regs =
  177 + (struct mx28_power_regs *)MXS_POWER_BASE;
  178 + uint32_t tmp, vbus_thresh, vbus_5vdetect, pwd_bo;
  179 + uint32_t prev_5v_brnout, prev_5v_droop;
  180 +
  181 + prev_5v_brnout = readl(&power_regs->hw_power_5vctrl) &
  182 + POWER_5VCTRL_PWDN_5VBRNOUT;
  183 + prev_5v_droop = readl(&power_regs->hw_power_ctrl) &
  184 + POWER_CTRL_ENIRQ_VDD5V_DROOP;
  185 +
  186 + clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
  187 + writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
  188 + &power_regs->hw_power_reset);
  189 +
  190 + clrbits_le32(&power_regs->hw_power_ctrl, POWER_CTRL_ENIRQ_VDD5V_DROOP);
  191 +
  192 + if (xfer && (readl(&power_regs->hw_power_5vctrl) &
  193 + POWER_5VCTRL_ENABLE_DCDC)) {
  194 + return;
  195 + }
  196 +
  197 + /*
  198 + * Recording orignal values that will be modified temporarlily
  199 + * to handle a chip bug. See chip errata for CQ ENGR00115837
  200 + */
  201 + tmp = readl(&power_regs->hw_power_5vctrl);
  202 + vbus_thresh = tmp & POWER_5VCTRL_VBUSVALID_TRSH_MASK;
  203 + vbus_5vdetect = tmp & POWER_5VCTRL_VBUSVALID_5VDETECT;
  204 +
  205 + pwd_bo = readl(&power_regs->hw_power_minpwr) & POWER_MINPWR_PWD_BO;
  206 +
  207 + /*
  208 + * Disable mechanisms that get erroneously tripped by when setting
  209 + * the DCDC4P2 EN_DCDC
  210 + */
  211 + clrbits_le32(&power_regs->hw_power_5vctrl,
  212 + POWER_5VCTRL_VBUSVALID_5VDETECT |
  213 + POWER_5VCTRL_VBUSVALID_TRSH_MASK);
  214 +
  215 + writel(POWER_MINPWR_PWD_BO, &power_regs->hw_power_minpwr_set);
  216 +
  217 + if (xfer) {
  218 + setbits_le32(&power_regs->hw_power_5vctrl,
  219 + POWER_5VCTRL_DCDC_XFER);
  220 + early_delay(20);
  221 + clrbits_le32(&power_regs->hw_power_5vctrl,
  222 + POWER_5VCTRL_DCDC_XFER);
  223 +
  224 + setbits_le32(&power_regs->hw_power_5vctrl,
  225 + POWER_5VCTRL_ENABLE_DCDC);
  226 + } else {
  227 + setbits_le32(&power_regs->hw_power_dcdc4p2,
  228 + POWER_DCDC4P2_ENABLE_DCDC);
  229 + }
  230 +
  231 + early_delay(25);
  232 +
  233 + clrsetbits_le32(&power_regs->hw_power_5vctrl,
  234 + POWER_5VCTRL_VBUSVALID_TRSH_MASK, vbus_thresh);
  235 +
  236 + if (vbus_5vdetect)
  237 + writel(vbus_5vdetect, &power_regs->hw_power_5vctrl_set);
  238 +
  239 + if (!pwd_bo)
  240 + clrbits_le32(&power_regs->hw_power_minpwr, POWER_MINPWR_PWD_BO);
  241 +
  242 + while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ)
  243 + clrbits_le32(&power_regs->hw_power_ctrl,
  244 + POWER_CTRL_VBUS_VALID_IRQ);
  245 +
  246 + if (prev_5v_brnout) {
  247 + writel(POWER_5VCTRL_PWDN_5VBRNOUT,
  248 + &power_regs->hw_power_5vctrl_set);
  249 + writel(POWER_RESET_UNLOCK_KEY,
  250 + &power_regs->hw_power_reset);
  251 + } else {
  252 + writel(POWER_5VCTRL_PWDN_5VBRNOUT,
  253 + &power_regs->hw_power_5vctrl_clr);
  254 + writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
  255 + &power_regs->hw_power_reset);
  256 + }
  257 +
  258 + while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VDD5V_DROOP_IRQ)
  259 + clrbits_le32(&power_regs->hw_power_ctrl,
  260 + POWER_CTRL_VDD5V_DROOP_IRQ);
  261 +
  262 + if (prev_5v_droop)
  263 + clrbits_le32(&power_regs->hw_power_ctrl,
  264 + POWER_CTRL_ENIRQ_VDD5V_DROOP);
  265 + else
  266 + setbits_le32(&power_regs->hw_power_ctrl,
  267 + POWER_CTRL_ENIRQ_VDD5V_DROOP);
  268 +}
  269 +
  270 +void mx28_power_init_4p2_regulator(void)
  271 +{
  272 + struct mx28_power_regs *power_regs =
  273 + (struct mx28_power_regs *)MXS_POWER_BASE;
  274 + uint32_t tmp, tmp2;
  275 +
  276 + setbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_ENABLE_4P2);
  277 +
  278 + writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_set);
  279 +
  280 + writel(POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
  281 + &power_regs->hw_power_5vctrl_clr);
  282 + clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_TRG_MASK);
  283 +
  284 + /* Power up the 4p2 rail and logic/control */
  285 + writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
  286 + &power_regs->hw_power_5vctrl_clr);
  287 +
  288 + /*
  289 + * Start charging up the 4p2 capacitor. We ramp of this charge
  290 + * gradually to avoid large inrush current from the 5V cable which can
  291 + * cause transients/problems
  292 + */
  293 + mx28_enable_4p2_dcdc_input(0);
  294 +
  295 + if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
  296 + /*
  297 + * If we arrived here, we were unable to recover from mx23 chip
  298 + * errata 5837. 4P2 is disabled and sufficient battery power is
  299 + * not present. Exiting to not enable DCDC power during 5V
  300 + * connected state.
  301 + */
  302 + clrbits_le32(&power_regs->hw_power_dcdc4p2,
  303 + POWER_DCDC4P2_ENABLE_DCDC);
  304 + writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
  305 + &power_regs->hw_power_5vctrl_set);
  306 + hang();
  307 + }
  308 +
  309 + /*
  310 + * Here we set the 4p2 brownout level to something very close to 4.2V.
  311 + * We then check the brownout status. If the brownout status is false,
  312 + * the voltage is already close to the target voltage of 4.2V so we
  313 + * can go ahead and set the 4P2 current limit to our max target limit.
  314 + * If the brownout status is true, we need to ramp us the current limit
  315 + * so that we don't cause large inrush current issues. We step up the
  316 + * current limit until the brownout status is false or until we've
  317 + * reached our maximum defined 4p2 current limit.
  318 + */
  319 + clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
  320 + POWER_DCDC4P2_BO_MASK,
  321 + 22 << POWER_DCDC4P2_BO_OFFSET); /* 4.15V */
  322 +
  323 + if (!(readl(&power_regs->hw_power_sts) & POWER_STS_DCDC_4P2_BO)) {
  324 + setbits_le32(&power_regs->hw_power_5vctrl,
  325 + 0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
  326 + } else {
  327 + tmp = (readl(&power_regs->hw_power_5vctrl) &
  328 + POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK) >>
  329 + POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
  330 + while (tmp < 0x3f) {
  331 + if (!(readl(&power_regs->hw_power_sts) &
  332 + POWER_STS_DCDC_4P2_BO)) {
  333 + tmp = readl(&power_regs->hw_power_5vctrl);
  334 + tmp |= POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
  335 + early_delay(100);
  336 + writel(tmp, &power_regs->hw_power_5vctrl);
  337 + break;
  338 + } else {
  339 + tmp++;
  340 + tmp2 = readl(&power_regs->hw_power_5vctrl);
  341 + tmp2 &= ~POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK;
  342 + tmp2 |= tmp <<
  343 + POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET;
  344 + writel(tmp2, &power_regs->hw_power_5vctrl);
  345 + early_delay(100);
  346 + }
  347 + }
  348 + }
  349 +
  350 + clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK);
  351 + writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
  352 +}
  353 +
  354 +void mx28_power_init_dcdc_4p2_source(void)
  355 +{
  356 + struct mx28_power_regs *power_regs =
  357 + (struct mx28_power_regs *)MXS_POWER_BASE;
  358 +
  359 + if (!(readl(&power_regs->hw_power_dcdc4p2) &
  360 + POWER_DCDC4P2_ENABLE_DCDC)) {
  361 + hang();
  362 + }
  363 +
  364 + mx28_enable_4p2_dcdc_input(1);
  365 +
  366 + if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
  367 + clrbits_le32(&power_regs->hw_power_dcdc4p2,
  368 + POWER_DCDC4P2_ENABLE_DCDC);
  369 + writel(POWER_5VCTRL_ENABLE_DCDC,
  370 + &power_regs->hw_power_5vctrl_clr);
  371 + writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
  372 + &power_regs->hw_power_5vctrl_set);
  373 + }
  374 +}
  375 +
  376 +void mx28_power_enable_4p2(void)
  377 +{
  378 + struct mx28_power_regs *power_regs =
  379 + (struct mx28_power_regs *)MXS_POWER_BASE;
  380 + uint32_t vdddctrl, vddactrl, vddioctrl;
  381 + uint32_t tmp;
  382 +
  383 + vdddctrl = readl(&power_regs->hw_power_vdddctrl);
  384 + vddactrl = readl(&power_regs->hw_power_vddactrl);
  385 + vddioctrl = readl(&power_regs->hw_power_vddioctrl);
  386 +
  387 + setbits_le32(&power_regs->hw_power_vdddctrl,
  388 + POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
  389 + POWER_VDDDCTRL_PWDN_BRNOUT);
  390 +
  391 + setbits_le32(&power_regs->hw_power_vddactrl,
  392 + POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG |
  393 + POWER_VDDACTRL_PWDN_BRNOUT);
  394 +
  395 + setbits_le32(&power_regs->hw_power_vddioctrl,
  396 + POWER_VDDIOCTRL_DISABLE_FET | POWER_VDDIOCTRL_PWDN_BRNOUT);
  397 +
  398 + mx28_power_init_4p2_params();
  399 + mx28_power_init_4p2_regulator();
  400 +
  401 + /* Shutdown battery (none present) */
  402 + clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK);
  403 + writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
  404 + writel(POWER_CTRL_ENIRQ_DCDC4P2_BO, &power_regs->hw_power_ctrl_clr);
  405 +
  406 + mx28_power_init_dcdc_4p2_source();
  407 +
  408 + writel(vdddctrl, &power_regs->hw_power_vdddctrl);
  409 + early_delay(20);
  410 + writel(vddactrl, &power_regs->hw_power_vddactrl);
  411 + early_delay(20);
  412 + writel(vddioctrl, &power_regs->hw_power_vddioctrl);
  413 +
  414 + /*
  415 + * Check if FET is enabled on either powerout and if so,
  416 + * disable load.
  417 + */
  418 + tmp = 0;
  419 + tmp |= !(readl(&power_regs->hw_power_vdddctrl) &
  420 + POWER_VDDDCTRL_DISABLE_FET);
  421 + tmp |= !(readl(&power_regs->hw_power_vddactrl) &
  422 + POWER_VDDACTRL_DISABLE_FET);
  423 + tmp |= !(readl(&power_regs->hw_power_vddioctrl) &
  424 + POWER_VDDIOCTRL_DISABLE_FET);
  425 + if (tmp)
  426 + writel(POWER_CHARGE_ENABLE_LOAD,
  427 + &power_regs->hw_power_charge_clr);
  428 +}
  429 +
  430 +void mx28_boot_valid_5v(void)
  431 +{
  432 + struct mx28_power_regs *power_regs =
  433 + (struct mx28_power_regs *)MXS_POWER_BASE;
  434 +
  435 + /*
  436 + * Use VBUSVALID level instead of VDD5V_GT_VDDIO level to trigger a 5V
  437 + * disconnect event. FIXME
  438 + */
  439 + writel(POWER_5VCTRL_VBUSVALID_5VDETECT,
  440 + &power_regs->hw_power_5vctrl_set);
  441 +
  442 + /* Configure polarity to check for 5V disconnection. */
  443 + writel(POWER_CTRL_POLARITY_VBUSVALID |
  444 + POWER_CTRL_POLARITY_VDD5V_GT_VDDIO,
  445 + &power_regs->hw_power_ctrl_clr);
  446 +
  447 + writel(POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_VDD5V_GT_VDDIO_IRQ,
  448 + &power_regs->hw_power_ctrl_clr);
  449 +
  450 + mx28_power_enable_4p2();
  451 +}
  452 +
  453 +void mx28_powerdown(void)
  454 +{
  455 + struct mx28_power_regs *power_regs =
  456 + (struct mx28_power_regs *)MXS_POWER_BASE;
  457 + writel(POWER_RESET_UNLOCK_KEY, &power_regs->hw_power_reset);
  458 + writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
  459 + &power_regs->hw_power_reset);
  460 +}
  461 +
  462 +void mx28_handle_5v_conflict(void)
  463 +{
  464 + struct mx28_power_regs *power_regs =
  465 + (struct mx28_power_regs *)MXS_POWER_BASE;
  466 + uint32_t tmp;
  467 +
  468 + setbits_le32(&power_regs->hw_power_vddioctrl,
  469 + POWER_VDDIOCTRL_BO_OFFSET_MASK);
  470 +
  471 + for (;;) {
  472 + tmp = readl(&power_regs->hw_power_sts);
  473 +
  474 + if (tmp & POWER_STS_VDDIO_BO) {
  475 + mx28_powerdown();
  476 + break;
  477 + }
  478 +
  479 + if (tmp & POWER_STS_VDD5V_GT_VDDIO) {
  480 + mx28_boot_valid_5v();
  481 + break;
  482 + } else {
  483 + mx28_powerdown();
  484 + break;
  485 + }
  486 + }
  487 +}
  488 +
  489 +int mx28_get_batt_volt(void)
  490 +{
  491 + struct mx28_power_regs *power_regs =
  492 + (struct mx28_power_regs *)MXS_POWER_BASE;
  493 + uint32_t volt = readl(&power_regs->hw_power_battmonitor);
  494 + volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
  495 + volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
  496 + volt *= 8;
  497 + return volt;
  498 +}
  499 +
  500 +int mx28_is_batt_ready(void)
  501 +{
  502 + return (mx28_get_batt_volt() >= 3600);
  503 +}
  504 +
  505 +void mx28_5v_boot(void)
  506 +{
  507 + struct mx28_power_regs *power_regs =
  508 + (struct mx28_power_regs *)MXS_POWER_BASE;
  509 +
  510 + /*
  511 + * NOTE: In original IMX-Bootlets, this also checks for VBUSVALID,
  512 + * but their implementation always returns 1 so we omit it here.
  513 + */
  514 + if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
  515 + mx28_boot_valid_5v();
  516 + return;
  517 + }
  518 +
  519 + early_delay(1000);
  520 + if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
  521 + mx28_boot_valid_5v();
  522 + return;
  523 + }
  524 +
  525 + mx28_handle_5v_conflict();
  526 +}
  527 +
  528 +void mx28_init_batt_bo(void)
  529 +{
  530 + struct mx28_power_regs *power_regs =
  531 + (struct mx28_power_regs *)MXS_POWER_BASE;
  532 +
  533 + /* Brownout at 3V */
  534 + clrsetbits_le32(&power_regs->hw_power_battmonitor,
  535 + POWER_BATTMONITOR_BRWNOUT_LVL_MASK,
  536 + 15 << POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET);
  537 +
  538 + writel(POWER_CTRL_BATT_BO_IRQ, &power_regs->hw_power_ctrl_clr);
  539 + writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr);
  540 +}
  541 +
  542 +void mx28_switch_vddd_to_dcdc_source(void)
  543 +{
  544 + struct mx28_power_regs *power_regs =
  545 + (struct mx28_power_regs *)MXS_POWER_BASE;
  546 +
  547 + clrsetbits_le32(&power_regs->hw_power_vdddctrl,
  548 + POWER_VDDDCTRL_LINREG_OFFSET_MASK,
  549 + POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
  550 +
  551 + clrbits_le32(&power_regs->hw_power_vdddctrl,
  552 + POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG |
  553 + POWER_VDDDCTRL_DISABLE_STEPPING);
  554 +}
  555 +
  556 +int mx28_is_batt_good(void)
  557 +{
  558 + struct mx28_power_regs *power_regs =
  559 + (struct mx28_power_regs *)MXS_POWER_BASE;
  560 + uint32_t volt;
  561 +
  562 + volt = readl(&power_regs->hw_power_battmonitor);
  563 + volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
  564 + volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
  565 + volt *= 8;
  566 +
  567 + if ((volt >= 2400) && (volt <= 4300))
  568 + return 1;
  569 +
  570 + clrsetbits_le32(&power_regs->hw_power_5vctrl,
  571 + POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
  572 + 0x3 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
  573 + writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
  574 + &power_regs->hw_power_5vctrl_clr);
  575 +
  576 + clrsetbits_le32(&power_regs->hw_power_charge,
  577 + POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
  578 + POWER_CHARGE_STOP_ILIMIT_10MA | 0x3);
  579 +
  580 + writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_clr);
  581 + writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
  582 + &power_regs->hw_power_5vctrl_clr);
  583 +
  584 + early_delay(500000);
  585 +
  586 + volt = readl(&power_regs->hw_power_battmonitor);
  587 + volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
  588 + volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
  589 + volt *= 8;
  590 +
  591 + if (volt >= 3500)
  592 + return 0;
  593 +
  594 + if (volt >= 2400)
  595 + return 1;
  596 +
  597 + writel(POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
  598 + &power_regs->hw_power_charge_clr);
  599 + writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
  600 +
  601 + return 0;
  602 +}
  603 +
  604 +void mx28_power_configure_power_source(void)
  605 +{
  606 + mx28_src_power_init();
  607 +
  608 + mx28_5v_boot();
  609 + mx28_power_clock2pll();
  610 +
  611 + mx28_init_batt_bo();
  612 + mx28_switch_vddd_to_dcdc_source();
  613 +}
  614 +
  615 +void mx28_enable_output_rail_protection(void)
  616 +{
  617 + struct mx28_power_regs *power_regs =
  618 + (struct mx28_power_regs *)MXS_POWER_BASE;
  619 +
  620 + writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
  621 + POWER_CTRL_VDDIO_BO_IRQ, &power_regs->hw_power_ctrl_clr);
  622 +
  623 + setbits_le32(&power_regs->hw_power_vdddctrl,
  624 + POWER_VDDDCTRL_PWDN_BRNOUT);
  625 +
  626 + setbits_le32(&power_regs->hw_power_vddactrl,
  627 + POWER_VDDACTRL_PWDN_BRNOUT);
  628 +
  629 + setbits_le32(&power_regs->hw_power_vddioctrl,
  630 + POWER_VDDIOCTRL_PWDN_BRNOUT);
  631 +}
  632 +
  633 +int mx28_get_vddio_power_source_off(void)
  634 +{
  635 + struct mx28_power_regs *power_regs =
  636 + (struct mx28_power_regs *)MXS_POWER_BASE;
  637 + uint32_t tmp;
  638 +
  639 + if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
  640 + tmp = readl(&power_regs->hw_power_vddioctrl);
  641 + if (tmp & POWER_VDDIOCTRL_DISABLE_FET) {
  642 + if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
  643 + POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
  644 + return 1;
  645 + }
  646 + }
  647 +
  648 + if (!(readl(&power_regs->hw_power_5vctrl) &
  649 + POWER_5VCTRL_ENABLE_DCDC)) {
  650 + if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) ==
  651 + POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
  652 + return 1;
  653 + }
  654 + }
  655 + }
  656 +
  657 + return 0;
  658 +
  659 +}
  660 +
  661 +int mx28_get_vddd_power_source_off(void)
  662 +{
  663 + struct mx28_power_regs *power_regs =
  664 + (struct mx28_power_regs *)MXS_POWER_BASE;
  665 + uint32_t tmp;
  666 +
  667 + tmp = readl(&power_regs->hw_power_vdddctrl);
  668 + if (tmp & POWER_VDDDCTRL_DISABLE_FET) {
  669 + if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
  670 + POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) {
  671 + return 1;
  672 + }
  673 + }
  674 +
  675 + if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
  676 + if (!(readl(&power_regs->hw_power_5vctrl) &
  677 + POWER_5VCTRL_ENABLE_DCDC)) {
  678 + return 1;
  679 + }
  680 + }
  681 +
  682 + if (!(tmp & POWER_VDDDCTRL_ENABLE_LINREG)) {
  683 + if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) ==
  684 + POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW) {
  685 + return 1;
  686 + }
  687 + }
  688 +
  689 + return 0;
  690 +}
  691 +
  692 +void mx28_power_set_vddio(uint32_t new_target, uint32_t new_brownout)
  693 +{
  694 + struct mx28_power_regs *power_regs =
  695 + (struct mx28_power_regs *)MXS_POWER_BASE;
  696 + uint32_t cur_target, diff, bo_int = 0;
  697 + uint32_t powered_by_linreg = 0;
  698 +
  699 + new_brownout = new_target - new_brownout;
  700 +
  701 + cur_target = readl(&power_regs->hw_power_vddioctrl);
  702 + cur_target &= POWER_VDDIOCTRL_TRG_MASK;
  703 + cur_target *= 50; /* 50 mV step*/
  704 + cur_target += 2800; /* 2800 mV lowest */
  705 +
  706 + powered_by_linreg = mx28_get_vddio_power_source_off();
  707 + if (new_target > cur_target) {
  708 +
  709 + if (powered_by_linreg) {
  710 + bo_int = readl(&power_regs->hw_power_vddioctrl);
  711 + clrbits_le32(&power_regs->hw_power_vddioctrl,
  712 + POWER_CTRL_ENIRQ_VDDIO_BO);
  713 + }
  714 +
  715 + setbits_le32(&power_regs->hw_power_vddioctrl,
  716 + POWER_VDDIOCTRL_BO_OFFSET_MASK);
  717 + do {
  718 + if (new_target - cur_target > 100)
  719 + diff = cur_target + 100;
  720 + else
  721 + diff = new_target;
  722 +
  723 + diff -= 2800;
  724 + diff /= 50;
  725 +
  726 + clrsetbits_le32(&power_regs->hw_power_vddioctrl,
  727 + POWER_VDDIOCTRL_TRG_MASK, diff);
  728 +
  729 + if (powered_by_linreg)
  730 + early_delay(1500);
  731 + else {
  732 + while (!(readl(&power_regs->hw_power_sts) &
  733 + POWER_STS_DC_OK))
  734 + ;
  735 +
  736 + }
  737 +
  738 + cur_target = readl(&power_regs->hw_power_vddioctrl);
  739 + cur_target &= POWER_VDDIOCTRL_TRG_MASK;
  740 + cur_target *= 50; /* 50 mV step*/
  741 + cur_target += 2800; /* 2800 mV lowest */
  742 + } while (new_target > cur_target);
  743 +
  744 + if (powered_by_linreg) {
  745 + writel(POWER_CTRL_VDDIO_BO_IRQ,
  746 + &power_regs->hw_power_ctrl_clr);
  747 + if (bo_int & POWER_CTRL_ENIRQ_VDDIO_BO)
  748 + setbits_le32(&power_regs->hw_power_vddioctrl,
  749 + POWER_CTRL_ENIRQ_VDDIO_BO);
  750 + }
  751 + } else {
  752 + do {
  753 + if (cur_target - new_target > 100)
  754 + diff = cur_target - 100;
  755 + else
  756 + diff = new_target;
  757 +
  758 + diff -= 2800;
  759 + diff /= 50;
  760 +
  761 + clrsetbits_le32(&power_regs->hw_power_vddioctrl,
  762 + POWER_VDDIOCTRL_TRG_MASK, diff);
  763 +
  764 + if (powered_by_linreg)
  765 + early_delay(1500);
  766 + else {
  767 + while (!(readl(&power_regs->hw_power_sts) &
  768 + POWER_STS_DC_OK))
  769 + ;
  770 +
  771 + }
  772 +
  773 + cur_target = readl(&power_regs->hw_power_vddioctrl);
  774 + cur_target &= POWER_VDDIOCTRL_TRG_MASK;
  775 + cur_target *= 50; /* 50 mV step*/
  776 + cur_target += 2800; /* 2800 mV lowest */
  777 + } while (new_target < cur_target);
  778 + }
  779 +
  780 + clrsetbits_le32(&power_regs->hw_power_vddioctrl,
  781 + POWER_VDDDCTRL_BO_OFFSET_MASK,
  782 + new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET);
  783 +}
  784 +
  785 +void mx28_power_set_vddd(uint32_t new_target, uint32_t new_brownout)
  786 +{
  787 + struct mx28_power_regs *power_regs =
  788 + (struct mx28_power_regs *)MXS_POWER_BASE;
  789 + uint32_t cur_target, diff, bo_int = 0;
  790 + uint32_t powered_by_linreg = 0;
  791 +
  792 + new_brownout = new_target - new_brownout;
  793 +
  794 + cur_target = readl(&power_regs->hw_power_vdddctrl);
  795 + cur_target &= POWER_VDDDCTRL_TRG_MASK;
  796 + cur_target *= 25; /* 25 mV step*/
  797 + cur_target += 800; /* 800 mV lowest */
  798 +
  799 + powered_by_linreg = mx28_get_vddd_power_source_off();
  800 + if (new_target > cur_target) {
  801 + if (powered_by_linreg) {
  802 + bo_int = readl(&power_regs->hw_power_vdddctrl);
  803 + clrbits_le32(&power_regs->hw_power_vdddctrl,
  804 + POWER_CTRL_ENIRQ_VDDD_BO);
  805 + }
  806 +
  807 + setbits_le32(&power_regs->hw_power_vdddctrl,
  808 + POWER_VDDDCTRL_BO_OFFSET_MASK);
  809 +
  810 + do {
  811 + if (new_target - cur_target > 100)
  812 + diff = cur_target + 100;
  813 + else
  814 + diff = new_target;
  815 +
  816 + diff -= 800;
  817 + diff /= 25;
  818 +
  819 + clrsetbits_le32(&power_regs->hw_power_vdddctrl,
  820 + POWER_VDDDCTRL_TRG_MASK, diff);
  821 +
  822 + if (powered_by_linreg)
  823 + early_delay(1500);
  824 + else {
  825 + while (!(readl(&power_regs->hw_power_sts) &
  826 + POWER_STS_DC_OK))
  827 + ;
  828 +
  829 + }
  830 +
  831 + cur_target = readl(&power_regs->hw_power_vdddctrl);
  832 + cur_target &= POWER_VDDDCTRL_TRG_MASK;
  833 + cur_target *= 25; /* 25 mV step*/
  834 + cur_target += 800; /* 800 mV lowest */
  835 + } while (new_target > cur_target);
  836 +
  837 + if (powered_by_linreg) {
  838 + writel(POWER_CTRL_VDDD_BO_IRQ,
  839 + &power_regs->hw_power_ctrl_clr);
  840 + if (bo_int & POWER_CTRL_ENIRQ_VDDD_BO)
  841 + setbits_le32(&power_regs->hw_power_vdddctrl,
  842 + POWER_CTRL_ENIRQ_VDDD_BO);
  843 + }
  844 + } else {
  845 + do {
  846 + if (cur_target - new_target > 100)
  847 + diff = cur_target - 100;
  848 + else
  849 + diff = new_target;
  850 +
  851 + diff -= 800;
  852 + diff /= 25;
  853 +
  854 + clrsetbits_le32(&power_regs->hw_power_vdddctrl,
  855 + POWER_VDDDCTRL_TRG_MASK, diff);
  856 +
  857 + if (powered_by_linreg)
  858 + early_delay(1500);
  859 + else {
  860 + while (!(readl(&power_regs->hw_power_sts) &
  861 + POWER_STS_DC_OK))
  862 + ;
  863 +
  864 + }
  865 +
  866 + cur_target = readl(&power_regs->hw_power_vdddctrl);
  867 + cur_target &= POWER_VDDDCTRL_TRG_MASK;
  868 + cur_target *= 25; /* 25 mV step*/
  869 + cur_target += 800; /* 800 mV lowest */
  870 + } while (new_target < cur_target);
  871 + }
  872 +
  873 + clrsetbits_le32(&power_regs->hw_power_vdddctrl,
  874 + POWER_VDDDCTRL_BO_OFFSET_MASK,
  875 + new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET);
  876 +}
  877 +
  878 +void mx28_power_init(void)
  879 +{
  880 + struct mx28_power_regs *power_regs =
  881 + (struct mx28_power_regs *)MXS_POWER_BASE;
  882 +
  883 + mx28_power_clock2xtal();
  884 + mx28_power_clear_auto_restart();
  885 + mx28_power_set_linreg();
  886 + mx28_power_setup_5v_detect();
  887 + mx28_power_configure_power_source();
  888 + mx28_enable_output_rail_protection();
  889 +
  890 + mx28_power_set_vddio(3300, 3150);
  891 +
  892 + mx28_power_set_vddd(1350, 1200);
  893 +
  894 + writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
  895 + POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ |
  896 + POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_BATT_BO_IRQ |
  897 + POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
  898 +
  899 + writel(POWER_5VCTRL_PWDN_5VBRNOUT, &power_regs->hw_power_5vctrl_set);
  900 +
  901 + early_delay(1000);
  902 +}
  903 +
  904 +#ifdef CONFIG_SPL_MX28_PSWITCH_WAIT
  905 +void mx28_power_wait_pswitch(void)
  906 +{
  907 + struct mx28_power_regs *power_regs =
  908 + (struct mx28_power_regs *)MXS_POWER_BASE;
  909 +
  910 + while (!(readl(&power_regs->hw_power_sts) & POWER_STS_PSWITCH_MASK))
  911 + ;
  912 +}
  913 +#endif
board/denx/m28evk/start.S
  1 +/*
  2 + * armboot - Startup Code for ARM926EJS CPU-core
  3 + *
  4 + * Copyright (c) 2003 Texas Instruments
  5 + *
  6 + * ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------
  7 + *
  8 + * Copyright (c) 2001 Marius Groger <mag@sysgo.de>
  9 + * Copyright (c) 2002 Alex Zupke <azu@sysgo.de>
  10 + * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de>
  11 + * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com>
  12 + * Copyright (c) 2003 Kshitij <kshitij@ti.com>
  13 + * Copyright (c) 2010 Albert Aribaud <albert.u.boot@aribaud.net>
  14 + *
  15 + * Change to support call back into iMX28 bootrom
  16 + * Copyright (c) 2011 Marek Vasut <marek.vasut@gmail.com>
  17 + * on behalf of DENX Software Engineering GmbH
  18 + *
  19 + * See file CREDITS for list of people who contributed to this
  20 + * project.
  21 + *
  22 + * This program is free software; you can redistribute it and/or
  23 + * modify it under the terms of the GNU General Public License as
  24 + * published by the Free Software Foundation; either version 2 of
  25 + * the License, or (at your option) any later version.
  26 + *
  27 + * This program is distributed in the hope that it will be useful,
  28 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  29 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  30 + * GNU General Public License for more details.
  31 + *
  32 + * You should have received a copy of the GNU General Public License
  33 + * along with this program; if not, write to the Free Software
  34 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  35 + * MA 02111-1307 USA
  36 + */
  37 +
  38 +#include <asm-offsets.h>
  39 +#include <config.h>
  40 +#include <common.h>
  41 +#include <version.h>
  42 +
  43 +#if defined(CONFIG_OMAP1610)
  44 +#include <./configs/omap1510.h>
  45 +#elif defined(CONFIG_OMAP730)
  46 +#include <./configs/omap730.h>
  47 +#endif
  48 +
  49 +/*
  50 + *************************************************************************
  51 + *
  52 + * Jump vector table as in table 3.1 in [1]
  53 + *
  54 + *************************************************************************
  55 + */
  56 +
  57 +
  58 +.globl _start
  59 +_start:
  60 + b reset
  61 +#ifdef CONFIG_SPL_BUILD
  62 +/* No exception handlers in preloader */
  63 + ldr pc, _hang
  64 + ldr pc, _hang
  65 + ldr pc, _hang
  66 + ldr pc, _hang
  67 + b reset
  68 + ldr pc, _hang
  69 + ldr pc, _hang
  70 +
  71 +_hang:
  72 + .word do_hang
  73 +/* pad to 64 byte boundary */
  74 + .word 0x12345678
  75 + .word 0x12345678
  76 + .word 0x12345678
  77 + .word 0x12345678
  78 + .word 0x12345678
  79 + .word 0x12345678
  80 + .word 0x12345678
  81 +#else
  82 + ldr pc, _undefined_instruction
  83 + ldr pc, _software_interrupt
  84 + ldr pc, _prefetch_abort
  85 + ldr pc, _data_abort
  86 + ldr pc, _not_used
  87 + ldr pc, _irq
  88 + ldr pc, _fiq
  89 +
  90 +_undefined_instruction:
  91 + .word undefined_instruction
  92 +_software_interrupt:
  93 + .word software_interrupt
  94 +_prefetch_abort:
  95 + .word prefetch_abort
  96 +_data_abort:
  97 + .word data_abort
  98 +_not_used:
  99 + .word not_used
  100 +_irq:
  101 + .word irq
  102 +_fiq:
  103 + .word fiq
  104 +
  105 +#endif /* CONFIG_SPL_BUILD */
  106 + .balignl 16,0xdeadbeef
  107 +
  108 +
  109 +/*
  110 + *************************************************************************
  111 + *
  112 + * Startup Code (reset vector)
  113 + *
  114 + * do important init only if we don't start from memory!
  115 + * setup Memory and board specific bits prior to relocation.
  116 + * relocate armboot to ram
  117 + * setup stack
  118 + *
  119 + *************************************************************************
  120 + */
  121 +
  122 +.globl _TEXT_BASE
  123 +_TEXT_BASE:
  124 + .word CONFIG_SYS_TEXT_BASE
  125 +
  126 +/*
  127 + * These are defined in the board-specific linker script.
  128 + * Subtracting _start from them lets the linker put their
  129 + * relative position in the executable instead of leaving
  130 + * them null.
  131 + */
  132 +.globl _bss_start_ofs
  133 +_bss_start_ofs:
  134 + .word __bss_start - _start
  135 +
  136 +.globl _bss_end_ofs
  137 +_bss_end_ofs:
  138 + .word __bss_end__ - _start
  139 +
  140 +.globl _end_ofs
  141 +_end_ofs:
  142 + .word _end - _start
  143 +
  144 +#ifdef CONFIG_USE_IRQ
  145 +/* IRQ stack memory (calculated at run-time) */
  146 +.globl IRQ_STACK_START
  147 +IRQ_STACK_START:
  148 + .word 0x0badc0de
  149 +
  150 +/* IRQ stack memory (calculated at run-time) */
  151 +.globl FIQ_STACK_START
  152 +FIQ_STACK_START:
  153 + .word 0x0badc0de
  154 +#endif
  155 +
  156 +/* IRQ stack memory (calculated at run-time) + 8 bytes */
  157 +.globl IRQ_STACK_START_IN
  158 +IRQ_STACK_START_IN:
  159 + .word 0x0badc0de
  160 +
  161 +/*
  162 + * the actual reset code
  163 + */
  164 +
  165 +reset:
  166 + /*
  167 + * Store all registers on old stack pointer, this will allow us later to
  168 + * return to the BootROM and let the BootROM load U-Boot into RAM.
  169 + */
  170 + push {r0-r12,r14}
  171 +
  172 + /*
  173 + * set the cpu to SVC32 mode
  174 + */
  175 + mrs r0,cpsr
  176 + bic r0,r0,#0x1f
  177 + orr r0,r0,#0xd3
  178 + msr cpsr,r0
  179 +
  180 + /*
  181 + * we do sys-critical inits only at reboot,
  182 + * not when booting from ram!
  183 + */
  184 +#ifndef CONFIG_SKIP_LOWLEVEL_INIT
  185 + bl cpu_init_crit
  186 +#endif
  187 +
  188 + bl board_init_ll
  189 +
  190 + pop {r0-r12,r14}
  191 + bx lr
  192 +
  193 +/*
  194 + *************************************************************************
  195 + *
  196 + * CPU_init_critical registers
  197 + *
  198 + * setup important registers
  199 + * setup memory timing
  200 + *
  201 + *************************************************************************
  202 + */
  203 +#ifndef CONFIG_SKIP_LOWLEVEL_INIT
  204 +cpu_init_crit:
  205 + /*
  206 + * flush v4 I/D caches
  207 + */
  208 + mov r0, #0
  209 + mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
  210 + mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
  211 +
  212 + /*
  213 + * disable MMU stuff and caches
  214 + */
  215 + mrc p15, 0, r0, c1, c0, 0
  216 + bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */
  217 + bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */
  218 + orr r0, r0, #0x00000002 /* set bit 2 (A) Align */
  219 + orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */
  220 + mcr p15, 0, r0, c1, c0, 0
  221 +
  222 + mov pc, lr /* back to my caller */
  223 +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
  224 +
  225 +#ifndef CONFIG_SPL_BUILD
  226 +/*
  227 + *************************************************************************
  228 + *
  229 + * Interrupt handling
  230 + *
  231 + *************************************************************************
  232 + */
  233 +
  234 +@
  235 +@ IRQ stack frame.
  236 +@
  237 +#define S_FRAME_SIZE 72
  238 +
  239 +#define S_OLD_R0 68
  240 +#define S_PSR 64
  241 +#define S_PC 60
  242 +#define S_LR 56
  243 +#define S_SP 52
  244 +
  245 +#define S_IP 48
  246 +#define S_FP 44
  247 +#define S_R10 40
  248 +#define S_R9 36
  249 +#define S_R8 32
  250 +#define S_R7 28
  251 +#define S_R6 24
  252 +#define S_R5 20
  253 +#define S_R4 16
  254 +#define S_R3 12
  255 +#define S_R2 8
  256 +#define S_R1 4
  257 +#define S_R0 0
  258 +
  259 +#define MODE_SVC 0x13
  260 +#define I_BIT 0x80
  261 +
  262 +/*
  263 + * use bad_save_user_regs for abort/prefetch/undef/swi ...
  264 + * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
  265 + */
  266 +
  267 + .macro bad_save_user_regs
  268 + @ carve out a frame on current user stack
  269 + sub sp, sp, #S_FRAME_SIZE
  270 + stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12
  271 + ldr r2, IRQ_STACK_START_IN
  272 + @ get values for "aborted" pc and cpsr (into parm regs)
  273 + ldmia r2, {r2 - r3}
  274 + add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack
  275 + add r5, sp, #S_SP
  276 + mov r1, lr
  277 + stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
  278 + mov r0, sp @ save current stack into r0 (param register)
  279 + .endm
  280 +
  281 + .macro irq_save_user_regs
  282 + sub sp, sp, #S_FRAME_SIZE
  283 + stmia sp, {r0 - r12} @ Calling r0-r12
  284 + @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
  285 + add r8, sp, #S_PC
  286 + stmdb r8, {sp, lr}^ @ Calling SP, LR
  287 + str lr, [r8, #0] @ Save calling PC
  288 + mrs r6, spsr
  289 + str r6, [r8, #4] @ Save CPSR
  290 + str r0, [r8, #8] @ Save OLD_R0
  291 + mov r0, sp
  292 + .endm
  293 +
  294 + .macro irq_restore_user_regs
  295 + ldmia sp, {r0 - lr}^ @ Calling r0 - lr
  296 + mov r0, r0
  297 + ldr lr, [sp, #S_PC] @ Get PC
  298 + add sp, sp, #S_FRAME_SIZE
  299 + subs pc, lr, #4 @ return & move spsr_svc into cpsr
  300 + .endm
  301 +
  302 + .macro get_bad_stack
  303 + ldr r13, IRQ_STACK_START_IN @ setup our mode stack
  304 +
  305 + str lr, [r13] @ save caller lr in position 0 of saved stack
  306 + mrs lr, spsr @ get the spsr
  307 + str lr, [r13, #4] @ save spsr in position 1 of saved stack
  308 + mov r13, #MODE_SVC @ prepare SVC-Mode
  309 + @ msr spsr_c, r13
  310 + msr spsr, r13 @ switch modes, make sure moves will execute
  311 + mov lr, pc @ capture return pc
  312 + movs pc, lr @ jump to next instruction & switch modes.
  313 + .endm
  314 +
  315 + .macro get_irq_stack @ setup IRQ stack
  316 + ldr sp, IRQ_STACK_START
  317 + .endm
  318 +
  319 + .macro get_fiq_stack @ setup FIQ stack
  320 + ldr sp, FIQ_STACK_START
  321 + .endm
  322 +#endif /* CONFIG_SPL_BUILD */
  323 +
  324 +/*
  325 + * exception handlers
  326 + */
  327 +#ifdef CONFIG_SPL_BUILD
  328 + .align 5
  329 +do_hang:
  330 + ldr sp, _TEXT_BASE /* switch to abort stack */
  331 +1:
  332 + bl 1b /* hang and never return */
  333 +#else /* !CONFIG_SPL_BUILD */
  334 + .align 5
  335 +undefined_instruction:
  336 + get_bad_stack
  337 + bad_save_user_regs
  338 + bl do_undefined_instruction
  339 +
  340 + .align 5
  341 +software_interrupt:
  342 + get_bad_stack
  343 + bad_save_user_regs
  344 + bl do_software_interrupt
  345 +
  346 + .align 5
  347 +prefetch_abort:
  348 + get_bad_stack
  349 + bad_save_user_regs
  350 + bl do_prefetch_abort
  351 +
  352 + .align 5
  353 +data_abort:
  354 + get_bad_stack
  355 + bad_save_user_regs
  356 + bl do_data_abort
  357 +
  358 + .align 5
  359 +not_used:
  360 + get_bad_stack
  361 + bad_save_user_regs
  362 + bl do_not_used
  363 +
  364 +#ifdef CONFIG_USE_IRQ
  365 +
  366 + .align 5
  367 +irq:
  368 + get_irq_stack
  369 + irq_save_user_regs
  370 + bl do_irq
  371 + irq_restore_user_regs
  372 +
  373 + .align 5
  374 +fiq:
  375 + get_fiq_stack
  376 + /* someone ought to write a more effiction fiq_save_user_regs */
  377 + irq_save_user_regs
  378 + bl do_fiq
  379 + irq_restore_user_regs
  380 +
  381 +#else
  382 +
  383 + .align 5
  384 +irq:
  385 + get_bad_stack
  386 + bad_save_user_regs
  387 + bl do_irq
  388 +
  389 + .align 5
  390 +fiq:
  391 + get_bad_stack
  392 + bad_save_user_regs
  393 + bl do_fiq
  394 +
  395 +#endif
  396 +#endif /* CONFIG_SPL_BUILD */
board/denx/m28evk/u-boot-spl.lds
  1 +/*
  2 + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
  3 + * on behalf of DENX Software Engineering GmbH
  4 + *
  5 + * January 2004 - Changed to support H4 device
  6 + * Copyright (c) 2004-2008 Texas Instruments
  7 + *
  8 + * (C) Copyright 2002
  9 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
  10 + *
  11 + * See file CREDITS for list of people who contributed to this
  12 + * project.
  13 + *
  14 + * This program is free software; you can redistribute it and/or
  15 + * modify it under the terms of the GNU General Public License as
  16 + * published by the Free Software Foundation; either version 2 of
  17 + * the License, or (at your option) any later version.
  18 + *
  19 + * This program is distributed in the hope that it will be useful,
  20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22 + * GNU General Public License for more details.
  23 + *
  24 + * You should have received a copy of the GNU General Public License
  25 + * along with this program; if not, write to the Free Software
  26 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  27 + * MA 02111-1307 USA
  28 + */
  29 +
  30 +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
  31 +OUTPUT_ARCH(arm)
  32 +ENTRY(_start)
  33 +SECTIONS
  34 +{
  35 + . = 0x00000000;
  36 +
  37 + . = ALIGN(4);
  38 + .text :
  39 + {
  40 + board/denx/m28evk/start.o (.text)
  41 + *(.text)
  42 + }
  43 +
  44 + . = ALIGN(4);
  45 + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
  46 +
  47 + . = ALIGN(4);
  48 + .data : {
  49 + *(.data)
  50 + }
  51 +
  52 + . = ALIGN(4);
  53 + __u_boot_cmd_start = .;
  54 + .u_boot_cmd : { *(.u_boot_cmd) }
  55 + __u_boot_cmd_end = .;
  56 +
  57 + . = ALIGN(4);
  58 +
  59 + .rel.dyn : {
  60 + __rel_dyn_start = .;
  61 + *(.rel*)
  62 + __rel_dyn_end = .;
  63 + }
  64 +
  65 + .dynsym : {
  66 + __dynsym_start = .;
  67 + *(.dynsym)
  68 + }
  69 +
  70 + _end = .;
  71 +
  72 + .bss __rel_dyn_start (OVERLAY) : {
  73 + __bss_start = .;
  74 + *(.bss)
  75 + . = ALIGN(4);
  76 + __bss_end__ = .;
  77 + }
  78 +
  79 + /DISCARD/ : { *(.bss*) }
  80 + /DISCARD/ : { *(.dynstr*) }
  81 + /DISCARD/ : { *(.dynsym*) }
  82 + /DISCARD/ : { *(.dynamic*) }
  83 + /DISCARD/ : { *(.hash*) }
  84 + /DISCARD/ : { *(.plt*) }
  85 + /DISCARD/ : { *(.interp*) }
  86 + /DISCARD/ : { *(.gnu*) }
  87 +}
board/denx/m28evk/u-boot.bd
  1 +sources {
  2 + u_boot_spl="spl/u-boot-spl.bin";
  3 + u_boot="u-boot.bin";
  4 +}
  5 +
  6 +section (0) {
  7 + load u_boot_spl > 0x0000;
  8 + load ivt (entry = 0x0014) > 0x8000;
  9 + hab call 0x8000;
  10 +
  11 + load u_boot > 0x40000100;
  12 + load ivt (entry = 0x40000100) > 0x8000;
  13 + hab call 0x8000;
  14 +}
include/configs/m28evk.h
... ... @@ -43,6 +43,14 @@
43 43 #define CONFIG_ARCH_CPU_INIT
44 44  
45 45 /*
  46 + * SPL
  47 + */
  48 +#define CONFIG_SPL
  49 +#define CONFIG_SPL_NO_CPU_SUPPORT_CODE
  50 +#define CONFIG_SPL_START_S_PATH "board/denx/m28evk"
  51 +#define CONFIG_SPL_LDSCRIPT "board/denx/m28evk/u-boot-spl.lds"
  52 +
  53 +/*
46 54 * U-Boot Commands
47 55 */
48 56 #include <config_cmd_default.h>