[U-Boot] [PATCH 00/13] M28EVK/i.MX28 improvements

These are some improvements that were stuck in my tree for a while, time to expunge them, please consider applying.
Tested on: * DENX M28EVK v2.0 * DENX M28EVK v1.1 * Mysterious board #1 ... * Unnamed board #2 ...
Marek Vasut (13): FEC: Abstract out register setup M28EVK: Implement support for new board V2.0 M28EVK: Add SD update command i.MX28: Improve passing of data from SPL to U-Boot i.MX28: Implement boot pads sampling and reporting i.MX28: Add LCDIF register definitions i.MX28: Shut down the LCD controller before reset i.MX28: Add LRADC register definitions i.MX28: Add LRADC init to i.MX28 SPL i.MX28: Reorder battery status functions in SPL i.MX28: Add battery boot components to SPL i.MX28: Check if WP detection is implemented at all i.MX28: Avoid redefining serial_put[cs]()
arch/arm/cpu/arm926ejs/mx28/Makefile | 2 +- arch/arm/cpu/arm926ejs/mx28/mx28.c | 29 +- arch/arm/cpu/arm926ejs/mx28/mx28_init.h | 4 + arch/arm/cpu/arm926ejs/mx28/spl_boot.c | 57 ++++ arch/arm/cpu/arm926ejs/mx28/spl_lradc_init.c | 86 ++++++ arch/arm/cpu/arm926ejs/mx28/spl_mem_init.c | 10 +- arch/arm/cpu/arm926ejs/mx28/spl_power_init.c | 224 ++++++++++----- arch/arm/include/asm/arch-mx28/imx-regs.h | 2 + arch/arm/include/asm/arch-mx28/regs-lcdif.h | 212 ++++++++++++++ arch/arm/include/asm/arch-mx28/regs-lradc.h | 400 ++++++++++++++++++++++++++ arch/arm/include/asm/arch-mx28/sys_proto.h | 30 ++ board/denx/m28evk/m28evk.c | 20 +- board/denx/m28evk/spl_boot.c | 8 +- drivers/mmc/mxsmmc.c | 3 +- drivers/net/fec_mxc.c | 84 +++--- include/configs/m28evk.h | 10 + include/configs/mx28evk.h | 1 + 17 files changed, 1043 insertions(+), 139 deletions(-) create mode 100644 arch/arm/cpu/arm926ejs/mx28/spl_lradc_init.c create mode 100644 arch/arm/include/asm/arch-mx28/regs-lcdif.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-lradc.h
Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de

Abstract out common register setup. This also configured r_cntrl to correct value at registration time.
Signed-off-by: Marek Vasut marex@denx.de Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de --- drivers/net/fec_mxc.c | 84 ++++++++++++++++++++++--------------------------- 1 file changed, 38 insertions(+), 46 deletions(-)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index d8db9f0..04750c5 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -398,6 +398,42 @@ static void fec_eth_phy_config(struct eth_device *dev) #endif }
+/* + * Do initial configuration of the FEC registers + */ +static void fec_reg_setup(struct fec_priv *fec) +{ + uint32_t rcntrl; + + /* + * Set interrupt mask register + */ + writel(0x00000000, &fec->eth->imask); + + /* + * Clear FEC-Lite interrupt event register(IEVENT) + */ + writel(0xffffffff, &fec->eth->ievent); + + + /* + * Set FEC-Lite receive control register(R_CNTRL): + */ + + /* Start with frame length = 1518, common for all modes. */ + rcntrl = PKTSIZE << FEC_RCNTRL_MAX_FL_SHIFT; + if (fec->xcv_type == SEVENWIRE) + rcntrl |= FEC_RCNTRL_FCE; + else if (fec->xcv_type == RGMII) + rcntrl |= FEC_RCNTRL_RGMII; + else if (fec->xcv_type == RMII) + rcntrl |= FEC_RCNTRL_RMII; + else /* MII mode */ + rcntrl |= FEC_RCNTRL_FCE | FEC_RCNTRL_MII_MODE; + + writel(rcntrl, &fec->eth->r_cntrl); +} + /** * Start the FEC engine * @param[in] dev Our device to handle @@ -512,7 +548,6 @@ static int fec_init(struct eth_device *dev, bd_t* bd) { struct fec_priv *fec = (struct fec_priv *)dev->priv; uint32_t mib_ptr = (uint32_t)&fec->eth->rmon_t_drop; - uint32_t rcntrl; uint32_t size; int i, ret;
@@ -560,33 +595,7 @@ static int fec_init(struct eth_device *dev, bd_t* bd) (unsigned)fec->rbd_base + size); }
- /* - * Set interrupt mask register - */ - writel(0x00000000, &fec->eth->imask); - - /* - * Clear FEC-Lite interrupt event register(IEVENT) - */ - writel(0xffffffff, &fec->eth->ievent); - - - /* - * Set FEC-Lite receive control register(R_CNTRL): - */ - - /* Start with frame length = 1518, common for all modes. */ - rcntrl = PKTSIZE << FEC_RCNTRL_MAX_FL_SHIFT; - if (fec->xcv_type == SEVENWIRE) - rcntrl |= FEC_RCNTRL_FCE; - else if (fec->xcv_type == RGMII) - rcntrl |= FEC_RCNTRL_RGMII; - else if (fec->xcv_type == RMII) - rcntrl |= FEC_RCNTRL_RMII; - else /* MII mode */ - rcntrl |= FEC_RCNTRL_FCE | FEC_RCNTRL_MII_MODE; - - writel(rcntrl, &fec->eth->r_cntrl); + fec_reg_setup(fec);
if (fec->xcv_type == MII10 || fec->xcv_type == MII100) fec_mii_setspeed(fec); @@ -933,24 +942,7 @@ static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr) udelay(10); }
- /* - * Set interrupt mask register - */ - writel(0x00000000, &fec->eth->imask); - - /* - * Clear FEC-Lite interrupt event register(IEVENT) - */ - writel(0xffffffff, &fec->eth->ievent); - - /* - * Set FEC-Lite receive control register(R_CNTRL): - */ - /* - * Frame length=1518; MII mode; - */ - writel((PKTSIZE << FEC_RCNTRL_MAX_FL_SHIFT) | FEC_RCNTRL_FCE | - FEC_RCNTRL_MII_MODE, &fec->eth->r_cntrl); + fec_reg_setup(fec); fec_mii_setspeed(fec);
if (dev_id == -1) {

Signed-off-by: Marek Vasut marex@denx.de Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de --- board/denx/m28evk/m28evk.c | 20 +++++++++++++++++++- board/denx/m28evk/spl_boot.c | 8 ++++++-- 2 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/board/denx/m28evk/m28evk.c b/board/denx/m28evk/m28evk.c index 53df476..3d28ea8 100644 --- a/board/denx/m28evk/m28evk.c +++ b/board/denx/m28evk/m28evk.c @@ -90,6 +90,8 @@ int board_mmc_init(bd_t *bis) { /* Configure WP as input. */ gpio_direction_input(MX28_PAD_AUART2_CTS__GPIO_3_10); + /* Turn on the power to the card. */ + gpio_direction_output(MX28_PAD_PWM3__GPIO_3_28, 0);
return mxsmmc_initialize(bis, 0, m28_mmc_wp); } @@ -103,10 +105,18 @@ int board_mmc_init(bd_t *bis)
int fecmxc_mii_postcall(int phy) { +#if defined(CONFIG_DENX_M28_V11) || defined(CONFIG_DENX_M28_V10) + /* KZ8031 PHY on old boards. */ + const uint32_t freq = 0x0080; +#else + /* KZ8021 PHY on new boards. */ + const uint32_t freq = 0x0000; +#endif + miiphy_write("FEC1", phy, MII_BMCR, 0x9000); miiphy_write("FEC1", phy, MII_OPMODE_STRAP_OVERRIDE, 0x0202); if (phy == 3) - miiphy_write("FEC1", 3, MII_PHY_CTRL2, 0x8180); + miiphy_write("FEC1", 3, MII_PHY_CTRL2, 0x8100 | freq); return 0; }
@@ -123,6 +133,14 @@ int board_eth_init(bd_t *bis) CLKCTRL_ENET_TIME_SEL_MASK | CLKCTRL_ENET_CLK_OUT_EN, CLKCTRL_ENET_TIME_SEL_RMII_CLK);
+#if !defined(CONFIG_DENX_M28_V11) && !defined(CONFIG_DENX_M28_V10) + /* Reset the new PHY */ + gpio_direction_output(MX28_PAD_AUART2_RTS__GPIO_3_11, 0); + udelay(10000); + gpio_set_value(MX28_PAD_AUART2_RTS__GPIO_3_11, 1); + udelay(10000); +#endif + ret = fecmxc_initialize_multi(bis, 0, 0, MXS_ENET0_BASE); if (ret) { printf("FEC MXS: Unable to init FEC0\n"); diff --git a/board/denx/m28evk/spl_boot.c b/board/denx/m28evk/spl_boot.c index a04fe18..7a12592 100644 --- a/board/denx/m28evk/spl_boot.c +++ b/board/denx/m28evk/spl_boot.c @@ -109,8 +109,9 @@ const iomux_cfg_t iomux_setup[] = { (MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL), MX28_PAD_SSP0_SCK__SSP0_SCK | (MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL), - MX28_PAD_PWM3__GPIO_3_28 | MUX_CONFIG_SSP0, /* Power .. FIXME */ - MX28_PAD_AUART2_CTS__GPIO_3_10, /* WP ... FIXME */ + MX28_PAD_PWM3__GPIO_3_28 | MUX_CONFIG_SSP0 | + (MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL), /* Power */ + MX28_PAD_AUART2_CTS__GPIO_3_10, /* WP */
/* GPMI NAND */ MX28_PAD_GPMI_D00__GPMI_D0 | MUX_CONFIG_GPMI, @@ -147,6 +148,9 @@ const iomux_cfg_t iomux_setup[] = { MX28_PAD_ENET0_RXD3__ENET1_RXD1 | MUX_CONFIG_ENET, MX28_PAD_ENET0_TXD2__ENET1_TXD0 | MUX_CONFIG_ENET, MX28_PAD_ENET0_TXD3__ENET1_TXD1 | MUX_CONFIG_ENET, +#if !defined(CONFIG_DENX_M28_V11) && !defined(CONFIG_DENX_M28_V10) + MX28_PAD_AUART2_RTS__GPIO_3_11, /* PHY reset */ +#endif
/* I2C */ MX28_PAD_I2C0_SCL__I2C0_SCL,

On 01/05/2012 23:09, Marek Vasut wrote:
Signed-off-by: Marek Vasut marex@denx.de Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de
board/denx/m28evk/m28evk.c | 20 +++++++++++++++++++- board/denx/m28evk/spl_boot.c | 8 ++++++-- 2 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/board/denx/m28evk/m28evk.c b/board/denx/m28evk/m28evk.c index 53df476..3d28ea8 100644 --- a/board/denx/m28evk/m28evk.c +++ b/board/denx/m28evk/m28evk.c @@ -90,6 +90,8 @@ int board_mmc_init(bd_t *bis) { /* Configure WP as input. */ gpio_direction_input(MX28_PAD_AUART2_CTS__GPIO_3_10);
/* Turn on the power to the card. */
gpio_direction_output(MX28_PAD_PWM3__GPIO_3_28, 0);
return mxsmmc_initialize(bis, 0, m28_mmc_wp);
} @@ -103,10 +105,18 @@ int board_mmc_init(bd_t *bis)
int fecmxc_mii_postcall(int phy) { +#if defined(CONFIG_DENX_M28_V11) || defined(CONFIG_DENX_M28_V10)
Do we really have no other way to get the board version ? We can use it if we have no other chance, but it seems quite nasty.
Stefano

Dear Stefano Babic,
On 01/05/2012 23:09, Marek Vasut wrote:
Signed-off-by: Marek Vasut marex@denx.de Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de
board/denx/m28evk/m28evk.c | 20 +++++++++++++++++++- board/denx/m28evk/spl_boot.c | 8 ++++++-- 2 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/board/denx/m28evk/m28evk.c b/board/denx/m28evk/m28evk.c index 53df476..3d28ea8 100644 --- a/board/denx/m28evk/m28evk.c +++ b/board/denx/m28evk/m28evk.c @@ -90,6 +90,8 @@ int board_mmc_init(bd_t *bis)
{
/* Configure WP as input. */ gpio_direction_input(MX28_PAD_AUART2_CTS__GPIO_3_10);
/* Turn on the power to the card. */
gpio_direction_output(MX28_PAD_PWM3__GPIO_3_28, 0);
return mxsmmc_initialize(bis, 0, m28_mmc_wp);
}
@@ -103,10 +105,18 @@ int board_mmc_init(bd_t *bis)
int fecmxc_mii_postcall(int phy) {
+#if defined(CONFIG_DENX_M28_V11) || defined(CONFIG_DENX_M28_V10)
Do we really have no other way to get the board version ? We can use it if we have no other chance, but it seems quite nasty.
We don't ... but eventually, I'd be forced to add subsequent patch that drops support for v1.1 and v1.0 revisions anyway (as noone has them). I just want this in before removing it, so I can revert such patch (I still have v1.0 revision here) for myself.
Stefano
Best regards, Marek Vasut

Add "update_sd_firmware" command to easily reload the SD card of m28evk kit. This comes handy when the board boots from SD card.
Signed-off-by: Marek Vasut marex@denx.de Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de --- include/configs/m28evk.h | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h index 012381a..c40d2a8 100644 --- a/include/configs/m28evk.h +++ b/include/configs/m28evk.h @@ -286,6 +286,7 @@ #define CONFIG_EXTRA_ENV_SETTINGS \ "update_nand_full_filename=u-boot.nand\0" \ "update_nand_firmware_filename=u-boot.sb\0" \ + "update_sd_firmware_filename=u-boot.sd\0" \ "update_nand_firmware_maxsz=0x100000\0" \ "update_nand_stride=0x40\0" /* MX28 datasheet ch. 12.12 */ \ "update_nand_count=0x4\0" /* MX28 datasheet ch. 12.12 */ \ @@ -312,6 +313,14 @@ "nand erase ${fcb_sz} ${fw_sz} ; " \ "nand write ${loadaddr} ${fcb_sz} ${filesize} ; " \ "nand write ${loadaddr} ${fw_off} ${filesize} ; " \ + "fi\0" \ + "update_sd_firmware=" /* Update the SD firmware partition */ \ + "if mmc rescan ; then " \ + "if tftp ${update_sd_firmware_filename} ; then " \ + "setexpr fw_sz ${filesize} / 0x200 ; " /* SD block size */ \ + "setexpr fw_sz ${fw_sz} + 1 ; " \ + "mmc write ${loadaddr} 0x800 ${fw_sz} ; " \ + "fi ; " \ "fi\0"
#endif /* __M28_H__ */

Pass memory size from SPL via structure located in SRAM instead of SCRATCH registers. This allows passing more data about boot from SPL to U-Boot, like the boot mode pads configuration.
Signed-off-by: Marek Vasut marex@denx.de Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de --- arch/arm/cpu/arm926ejs/mx28/mx28.c | 16 +++++----------- arch/arm/cpu/arm926ejs/mx28/mx28_init.h | 1 + arch/arm/cpu/arm926ejs/mx28/spl_boot.c | 7 +++++++ arch/arm/cpu/arm926ejs/mx28/spl_mem_init.c | 10 +++------- arch/arm/include/asm/arch-mx28/sys_proto.h | 4 ++++ 5 files changed, 20 insertions(+), 18 deletions(-)
diff --git a/arch/arm/cpu/arm926ejs/mx28/mx28.c b/arch/arm/cpu/arm926ejs/mx28/mx28.c index dc0338d..54a68e1 100644 --- a/arch/arm/cpu/arm926ejs/mx28/mx28.c +++ b/arch/arm/cpu/arm926ejs/mx28/mx28.c @@ -279,22 +279,16 @@ void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
int mx28_dram_init(void) { - struct mx28_digctl_regs *digctl_regs = - (struct mx28_digctl_regs *)MXS_DIGCTL_BASE; - uint32_t sz[2]; + struct mx28_spl_data *data = (struct mx28_spl_data *) + ((CONFIG_SYS_TEXT_BASE - sizeof(struct mx28_spl_data)) & ~0xf);
- sz[0] = readl(&digctl_regs->hw_digctl_scratch0); - sz[1] = readl(&digctl_regs->hw_digctl_scratch1); - - if (sz[0] != sz[1]) { + if (data->mem_dram_size == 0) { printf("MX28:\n" - "Error, the RAM size in HW_DIGCTRL_SCRATCH0 and\n" - "HW_DIGCTRL_SCRATCH1 is not the same. Please\n" - "verify these two registers contain valid RAM size!\n"); + "Error, the RAM size passed up from SPL is 0!\n"); hang(); }
- gd->ram_size = sz[0]; + gd->ram_size = data->mem_dram_size; return 0; }
diff --git a/arch/arm/cpu/arm926ejs/mx28/mx28_init.h b/arch/arm/cpu/arm926ejs/mx28/mx28_init.h index 98d3631..8eac958 100644 --- a/arch/arm/cpu/arm926ejs/mx28/mx28_init.h +++ b/arch/arm/cpu/arm926ejs/mx28/mx28_init.h @@ -37,5 +37,6 @@ static inline void mx28_power_wait_pswitch(void) { } #endif
void mx28_mem_init(void); +uint32_t mx28_mem_get_size(void);
#endif /* __M28_INIT_H__ */ diff --git a/arch/arm/cpu/arm926ejs/mx28/spl_boot.c b/arch/arm/cpu/arm926ejs/mx28/spl_boot.c index dfb8309..37e1eb7 100644 --- a/arch/arm/cpu/arm926ejs/mx28/spl_boot.c +++ b/arch/arm/cpu/arm926ejs/mx28/spl_boot.c @@ -28,6 +28,7 @@ #include <asm/io.h> #include <asm/arch/iomux-mx28.h> #include <asm/arch/imx-regs.h> +#include <asm/arch/sys_proto.h>
#include "mx28_init.h"
@@ -49,9 +50,15 @@ void early_delay(int delay) void mx28_common_spl_init(const iomux_cfg_t *iomux_setup, const unsigned int iomux_size) { + struct mx28_spl_data *data = (struct mx28_spl_data *) + ((CONFIG_SYS_TEXT_BASE - sizeof(struct mx28_spl_data)) & ~0xf); + mxs_iomux_setup_multiple_pads(iomux_setup, iomux_size); mx28_power_init(); + mx28_mem_init(); + data->mem_dram_size = mx28_mem_get_size(); + mx28_power_wait_pswitch(); }
diff --git a/arch/arm/cpu/arm926ejs/mx28/spl_mem_init.c b/arch/arm/cpu/arm926ejs/mx28/spl_mem_init.c index 911bbef..4f62142 100644 --- a/arch/arm/cpu/arm926ejs/mx28/spl_mem_init.c +++ b/arch/arm/cpu/arm926ejs/mx28/spl_mem_init.c @@ -173,10 +173,8 @@ void mx28_mem_setup_vddd(void) &power_regs->hw_power_vdddctrl); }
-void mx28_mem_get_size(void) +uint32_t mx28_mem_get_size(void) { - struct mx28_digctl_regs *digctl_regs = - (struct mx28_digctl_regs *)MXS_DIGCTL_BASE; uint32_t sz, da; uint32_t *vt = (uint32_t *)0x20; /* The following is "subs pc, r14, #4", used as return from DABT. */ @@ -187,11 +185,11 @@ void mx28_mem_get_size(void) vt[4] = data_abort_memdetect_handler;
sz = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE); - writel(sz, &digctl_regs->hw_digctl_scratch0); - writel(sz, &digctl_regs->hw_digctl_scratch1);
/* Restore the old DABT handler. */ vt[4] = da; + + return sz; }
void mx28_mem_init(void) @@ -239,6 +237,4 @@ void mx28_mem_init(void) early_delay(10000);
mx28_mem_setup_cpu_and_hbus(); - - mx28_mem_get_size(); } diff --git a/arch/arm/include/asm/arch-mx28/sys_proto.h b/arch/arm/include/asm/arch-mx28/sys_proto.h index 15d8de3..04f2e4d 100644 --- a/arch/arm/include/asm/arch-mx28/sys_proto.h +++ b/arch/arm/include/asm/arch-mx28/sys_proto.h @@ -39,6 +39,10 @@ void mx28_common_spl_init(const iomux_cfg_t *iomux_setup, const unsigned int iomux_size); #endif
+struct mx28_spl_data { + uint32_t mem_dram_size; +}; + int mx28_dram_init(void);
#endif /* __MX28_H__ */

This patch implements code that samples i.MX28 boot pads and reports boot mode accordingly.
Signed-off-by: Marek Vasut marex@denx.de Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de --- arch/arm/cpu/arm926ejs/mx28/mx28.c | 4 +++ arch/arm/cpu/arm926ejs/mx28/spl_boot.c | 48 ++++++++++++++++++++++++++++ arch/arm/include/asm/arch-mx28/sys_proto.h | 26 +++++++++++++++ include/configs/m28evk.h | 1 + include/configs/mx28evk.h | 1 + 5 files changed, 80 insertions(+)
diff --git a/arch/arm/cpu/arm926ejs/mx28/mx28.c b/arch/arm/cpu/arm926ejs/mx28/mx28.c index 54a68e1..865dbb3 100644 --- a/arch/arm/cpu/arm926ejs/mx28/mx28.c +++ b/arch/arm/cpu/arm926ejs/mx28/mx28.c @@ -185,8 +185,12 @@ int arch_cpu_init(void) #if defined(CONFIG_DISPLAY_CPUINFO) int print_cpuinfo(void) { + struct mx28_spl_data *data = (struct mx28_spl_data *) + ((CONFIG_SYS_TEXT_BASE - sizeof(struct mx28_spl_data)) & ~0xf); + printf("Freescale i.MX28 family at %d MHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000); + printf("BOOT: %s\n", mx28_boot_modes[data->boot_mode_idx].mode); return 0; } #endif diff --git a/arch/arm/cpu/arm926ejs/mx28/spl_boot.c b/arch/arm/cpu/arm926ejs/mx28/spl_boot.c index 37e1eb7..c9b4566 100644 --- a/arch/arm/cpu/arm926ejs/mx28/spl_boot.c +++ b/arch/arm/cpu/arm926ejs/mx28/spl_boot.c @@ -29,6 +29,7 @@ #include <asm/arch/iomux-mx28.h> #include <asm/arch/imx-regs.h> #include <asm/arch/sys_proto.h> +#include <asm/gpio.h>
#include "mx28_init.h"
@@ -47,11 +48,56 @@ void early_delay(int delay) ; }
+#define MUX_CONFIG_BOOTMODE_PAD (MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL) +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, +}; + +uint8_t mx28_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(mx28_boot_modes); i++) { + masked = bootmode & mx28_boot_modes[i].boot_mask; + if (masked == mx28_boot_modes[i].boot_pads) + break; + } + + return i; +} + void mx28_common_spl_init(const iomux_cfg_t *iomux_setup, const unsigned int iomux_size) { struct mx28_spl_data *data = (struct mx28_spl_data *) ((CONFIG_SYS_TEXT_BASE - sizeof(struct mx28_spl_data)) & ~0xf); + uint8_t bootmode = mx28_get_bootmode_index();
mxs_iomux_setup_multiple_pads(iomux_setup, iomux_size); mx28_power_init(); @@ -59,6 +105,8 @@ void mx28_common_spl_init(const iomux_cfg_t *iomux_setup, mx28_mem_init(); data->mem_dram_size = mx28_mem_get_size();
+ data->boot_mode_idx = bootmode; + mx28_power_wait_pswitch(); }
diff --git a/arch/arm/include/asm/arch-mx28/sys_proto.h b/arch/arm/include/asm/arch-mx28/sys_proto.h index 04f2e4d..e701c64 100644 --- a/arch/arm/include/asm/arch-mx28/sys_proto.h +++ b/arch/arm/include/asm/arch-mx28/sys_proto.h @@ -39,7 +39,33 @@ void mx28_common_spl_init(const iomux_cfg_t *iomux_setup, const unsigned int iomux_size); #endif
+struct mx28_pair { + uint8_t boot_pads; + uint8_t boot_mask; + const char *mode; +}; + +static const struct mx28_pair mx28_boot_modes[] = { + { 0x00, 0x0f, "USB #0" }, + { 0x01, 0x1f, "I2C #0, master, 3V3" }, + { 0x11, 0x1f, "I2C #0, master, 1V8" }, + { 0x02, 0x1f, "SSP SPI #2, master, 3V3 NOR" }, + { 0x12, 0x1f, "SSP SPI #2, master, 1V8 NOR" }, + { 0x03, 0x1f, "SSP SPI #3, master, 3V3 NOR" }, + { 0x13, 0x1f, "SSP SPI #3, master, 1V8 NOR" }, + { 0x04, 0x1f, "NAND, 3V3" }, + { 0x14, 0x1f, "NAND, 1V8" }, + { 0x08, 0x1f, "SSP SPI #3, master, 3V3 EEPROM" }, + { 0x18, 0x1f, "SSP SPI #3, master, 1V8 EEPROM" }, + { 0x09, 0x1f, "SSP SD/MMC #0, 3V3" }, + { 0x19, 0x1f, "SSP SD/MMC #0, 1V8" }, + { 0x0a, 0x1f, "SSP SD/MMC #1, 3V3" }, + { 0x1a, 0x1f, "SSP SD/MMC #1, 1V8" }, + { 0x00, 0x00, "Reserved/Unknown/Wrong" }, +}; + struct mx28_spl_data { + uint8_t boot_mode_idx; uint32_t mem_dram_size; };
diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h index c40d2a8..12059db 100644 --- a/include/configs/m28evk.h +++ b/include/configs/m28evk.h @@ -52,6 +52,7 @@ #define CONFIG_SPL_LDSCRIPT "arch/arm/cpu/arm926ejs/mx28/u-boot-spl.lds" #define CONFIG_SPL_LIBCOMMON_SUPPORT #define CONFIG_SPL_LIBGENERIC_SUPPORT +#define CONFIG_SPL_GPIO_SUPPORT
/* * U-Boot Commands diff --git a/include/configs/mx28evk.h b/include/configs/mx28evk.h index 02f3366..0984d70 100644 --- a/include/configs/mx28evk.h +++ b/include/configs/mx28evk.h @@ -46,6 +46,7 @@ #define CONFIG_SPL_LDSCRIPT "arch/arm/cpu/arm926ejs/mx28/u-boot-spl.lds" #define CONFIG_SPL_LIBCOMMON_SUPPORT #define CONFIG_SPL_LIBGENERIC_SUPPORT +#define CONFIG_SPL_GPIO_SUPPORT
/* * U-Boot Commands

From: Marek Vasut marek.vasut@gmail.com
Signed-off-by: Marek Vasut marek.vasut@gmail.com Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de --- arch/arm/include/asm/arch-mx28/imx-regs.h | 1 + arch/arm/include/asm/arch-mx28/regs-lcdif.h | 212 +++++++++++++++++++++++++++ 2 files changed, 213 insertions(+) create mode 100644 arch/arm/include/asm/arch-mx28/regs-lcdif.h
diff --git a/arch/arm/include/asm/arch-mx28/imx-regs.h b/arch/arm/include/asm/arch-mx28/imx-regs.h index f9e6c53..581bf0a 100644 --- a/arch/arm/include/asm/arch-mx28/imx-regs.h +++ b/arch/arm/include/asm/arch-mx28/imx-regs.h @@ -30,6 +30,7 @@ #include <asm/arch/regs-digctl.h> #include <asm/arch/regs-gpmi.h> #include <asm/arch/regs-i2c.h> +#include <asm/arch/regs-lcdif.h> #include <asm/arch/regs-ocotp.h> #include <asm/arch/regs-pinctrl.h> #include <asm/arch/regs-power.h> diff --git a/arch/arm/include/asm/arch-mx28/regs-lcdif.h b/arch/arm/include/asm/arch-mx28/regs-lcdif.h new file mode 100644 index 0000000..cb47e41 --- /dev/null +++ b/arch/arm/include/asm/arch-mx28/regs-lcdif.h @@ -0,0 +1,212 @@ +/* + * Freescale i.MX28 LCDIF Register Definitions + * + * Copyright (C) 2011 Marek Vasut marek.vasut@gmail.com + * on behalf of DENX Software Engineering GmbH + * + * Based on code from LTIB: + * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. + * + * 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 + * + */ + +#ifndef __MX28_REGS_LCDIF_H__ +#define __MX28_REGS_LCDIF_H__ + +#include <asm/arch/regs-common.h> + +#ifndef __ASSEMBLY__ +struct mx28_lcdif_regs { + mx28_reg_32(hw_lcdif_ctrl) /* 0x00 */ + mx28_reg_32(hw_lcdif_ctrl1) /* 0x10 */ + mx28_reg_32(hw_lcdif_ctrl2) /* 0x20 */ + mx28_reg_32(hw_lcdif_transfer_count) /* 0x30 */ + mx28_reg_32(hw_lcdif_cur_buf) /* 0x40 */ + mx28_reg_32(hw_lcdif_next_buf) /* 0x50 */ + mx28_reg_32(hw_lcdif_timing) /* 0x60 */ + mx28_reg_32(hw_lcdif_vdctrl0) /* 0x70 */ + mx28_reg_32(hw_lcdif_vdctrl1) /* 0x80 */ + mx28_reg_32(hw_lcdif_vdctrl2) /* 0x90 */ + mx28_reg_32(hw_lcdif_vdctrl3) /* 0xa0 */ + mx28_reg_32(hw_lcdif_vdctrl4) /* 0xb0 */ + mx28_reg_32(hw_lcdif_dvictrl0) /* 0xc0 */ + mx28_reg_32(hw_lcdif_dvictrl1) /* 0xd0 */ + mx28_reg_32(hw_lcdif_dvictrl2) /* 0xe0 */ + mx28_reg_32(hw_lcdif_dvictrl3) /* 0xf0 */ + mx28_reg_32(hw_lcdif_dvictrl4) /* 0x100 */ + mx28_reg_32(hw_lcdif_csc_coeffctrl0) /* 0x110 */ + mx28_reg_32(hw_lcdif_csc_coeffctrl1) /* 0x120 */ + mx28_reg_32(hw_lcdif_csc_coeffctrl2) /* 0x130 */ + mx28_reg_32(hw_lcdif_csc_coeffctrl3) /* 0x140 */ + mx28_reg_32(hw_lcdif_csc_coeffctrl4) /* 0x150 */ + mx28_reg_32(hw_lcdif_csc_offset) /* 0x160 */ + mx28_reg_32(hw_lcdif_csc_limit) /* 0x170 */ + mx28_reg_32(hw_lcdif_data) /* 0x180 */ + mx28_reg_32(hw_lcdif_bm_error_stat) /* 0x190 */ + mx28_reg_32(hw_lcdif_crc_stat) /* 0x1a0 */ + mx28_reg_32(hw_lcdif_lcdif_stat) /* 0x1b0 */ + mx28_reg_32(hw_lcdif_version) /* 0x1c0 */ + mx28_reg_32(hw_lcdif_debug0) /* 0x1d0 */ + mx28_reg_32(hw_lcdif_debug1) /* 0x1e0 */ + mx28_reg_32(hw_lcdif_debug2) /* 0x1f0 */ +}; +#endif + +#define LCDIF_CTRL_SFTRST (1 << 31) +#define LCDIF_CTRL_CLKGATE (1 << 30) +#define LCDIF_CTRL_YCBCR422_INPUT (1 << 29) +#define LCDIF_CTRL_READ_WRITEB (1 << 28) +#define LCDIF_CTRL_WAIT_FOR_VSYNC_EDGE (1 << 27) +#define LCDIF_CTRL_DATA_SHIFT_DIR (1 << 26) +#define LCDIF_CTRL_SHIFT_NUM_BITS_MASK (0x1f << 21) +#define LCDIF_CTRL_SHIFT_NUM_BITS_OFFSET 21 +#define LCDIF_CTRL_DVI_MODE (1 << 20) +#define LCDIF_CTRL_BYPASS_COUNT (1 << 19) +#define LCDIF_CTRL_VSYNC_MODE (1 << 18) +#define LCDIF_CTRL_DOTCLK_MODE (1 << 17) +#define LCDIF_CTRL_DATA_SELECT (1 << 16) +#define LCDIF_CTRL_INPUT_DATA_SWIZZLE_MASK (0x3 << 14) +#define LCDIF_CTRL_INPUT_DATA_SWIZZLE_OFFSET 14 +#define LCDIF_CTRL_CSC_DATA_SWIZZLE_MASK (0x3 << 12) +#define LCDIF_CTRL_CSC_DATA_SWIZZLE_OFFSET 12 +#define LCDIF_CTRL_LCD_DATABUS_WIDTH_MASK (0x3 << 10) +#define LCDIF_CTRL_LCD_DATABUS_WIDTH_OFFSET 10 +#define LCDIF_CTRL_LCD_DATABUS_WIDTH_16BIT (0 << 10) +#define LCDIF_CTRL_LCD_DATABUS_WIDTH_8BIT (1 << 10) +#define LCDIF_CTRL_LCD_DATABUS_WIDTH_18BIT (2 << 10) +#define LCDIF_CTRL_LCD_DATABUS_WIDTH_24BIT (3 << 10) +#define LCDIF_CTRL_WORD_LENGTH_MASK (0x3 << 8) +#define LCDIF_CTRL_WORD_LENGTH_OFFSET 8 +#define LCDIF_CTRL_WORD_LENGTH_16BIT (0 << 8) +#define LCDIF_CTRL_WORD_LENGTH_8BIT (1 << 8) +#define LCDIF_CTRL_WORD_LENGTH_18BIT (2 << 8) +#define LCDIF_CTRL_WORD_LENGTH_24BIT (3 << 8) +#define LCDIF_CTRL_RGB_TO_YCBCR422_CSC (1 << 7) +#define LCDIF_CTRL_LCDIF_MASTER (1 << 5) +#define LCDIF_CTRL_DATA_FORMAT_16_BIT (1 << 3) +#define LCDIF_CTRL_DATA_FORMAT_18_BIT (1 << 2) +#define LCDIF_CTRL_DATA_FORMAT_24_BIT (1 << 1) +#define LCDIF_CTRL_RUN (1 << 0) + +#define LCDIF_CTRL1_COMBINE_MPU_WR_STRB (1 << 27) +#define LCDIF_CTRL1_BM_ERROR_IRQ_EN (1 << 26) +#define LCDIF_CTRL1_BM_ERROR_IRQ (1 << 25) +#define LCDIF_CTRL1_RECOVER_ON_UNDERFLOW (1 << 24) +#define LCDIF_CTRL1_INTERLACE_FIELDS (1 << 23) +#define LCDIF_CTRL1_START_INTERLACE_FROM_SECOND_FIELD (1 << 22) +#define LCDIF_CTRL1_FIFO_CLEAR (1 << 21) +#define LCDIF_CTRL1_IRQ_ON_ALTERNATE_FIELDS (1 << 20) +#define LCDIF_CTRL1_BYTE_PACKING_FORMAT_MASK (0xf << 16) +#define LCDIF_CTRL1_BYTE_PACKING_FORMAT_OFFSET 16 +#define LCDIF_CTRL1_OVERFLOW_IRQ_EN (1 << 15) +#define LCDIF_CTRL1_UNDERFLOW_IRQ_EN (1 << 14) +#define LCDIF_CTRL1_CUR_FRAME_DONE_IRQ_EN (1 << 13) +#define LCDIF_CTRL1_VSYNC_EDGE_IRQ_EN (1 << 12) +#define LCDIF_CTRL1_OVERFLOW_IRQ (1 << 11) +#define LCDIF_CTRL1_UNDERFLOW_IRQ (1 << 10) +#define LCDIF_CTRL1_CUR_FRAME_DONE_IRQ (1 << 9) +#define LCDIF_CTRL1_VSYNC_EDGE_IRQ (1 << 8) +#define LCDIF_CTRL1_BUSY_ENABLE (1 << 2) +#define LCDIF_CTRL1_MODE86 (1 << 1) +#define LCDIF_CTRL1_RESET (1 << 0) + +#define LCDIF_CTRL2_OUTSTANDING_REQS_MASK (0x7 << 21) +#define LCDIF_CTRL2_OUTSTANDING_REQS_OFFSET 21 +#define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_1 (0x0 << 21) +#define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_2 (0x1 << 21) +#define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_4 (0x2 << 21) +#define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_8 (0x3 << 21) +#define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_16 (0x4 << 21) +#define LCDIF_CTRL2_BURST_LEN_8 (1 << 20) +#define LCDIF_CTRL2_ODD_LINE_PATTERN_MASK (0x7 << 16) +#define LCDIF_CTRL2_ODD_LINE_PATTERN_OFFSET 16 +#define LCDIF_CTRL2_ODD_LINE_PATTERN_RGB (0x0 << 16) +#define LCDIF_CTRL2_ODD_LINE_PATTERN_RBG (0x1 << 16) +#define LCDIF_CTRL2_ODD_LINE_PATTERN_GBR (0x2 << 16) +#define LCDIF_CTRL2_ODD_LINE_PATTERN_GRB (0x3 << 16) +#define LCDIF_CTRL2_ODD_LINE_PATTERN_BRG (0x4 << 16) +#define LCDIF_CTRL2_ODD_LINE_PATTERN_BGR (0x5 << 16) +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_MASK (0x7 << 12) +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_OFFSET 12 +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_RGB (0x0 << 12) +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_RBG (0x1 << 12) +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_GBR (0x2 << 12) +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_GRB (0x3 << 12) +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_BRG (0x4 << 12) +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_BGR (0x5 << 12) +#define LCDIF_CTRL2_READ_PACK_DIR (1 << 10) +#define LCDIF_CTRL2_READ_MODE_OUTPUT_IN_RGB_FORMAT (1 << 9) +#define LCDIF_CTRL2_READ_MODE_6_BIT_INPUT (1 << 8) +#define LCDIF_CTRL2_READ_MODE_NUM_PACKED_SUBWORDS_MASK (0x7 << 4) +#define LCDIF_CTRL2_READ_MODE_NUM_PACKED_SUBWORDS_OFFSET 4 +#define LCDIF_CTRL2_INITIAL_DUMMY_READ_MASK (0x7 << 1) +#define LCDIF_CTRL2_INITIAL_DUMMY_READ_OFFSET 1 + +#define LCDIF_TRANSFER_COUNT_V_COUNT_MASK (0xffff << 16) +#define LCDIF_TRANSFER_COUNT_V_COUNT_OFFSET 16 +#define LCDIF_TRANSFER_COUNT_H_COUNT_MASK (0xffff << 0) +#define LCDIF_TRANSFER_COUNT_H_COUNT_OFFSET 0 + +#define LCDIF_CUR_BUF_ADDR_MASK 0xffffffff +#define LCDIF_CUR_BUF_ADDR_OFFSET 0 + +#define LCDIF_NEXT_BUF_ADDR_MASK 0xffffffff +#define LCDIF_NEXT_BUF_ADDR_OFFSET 0 + +#define LCDIF_TIMING_CMD_HOLD_MASK (0xff << 24) +#define LCDIF_TIMING_CMD_HOLD_OFFSET 24 +#define LCDIF_TIMING_CMD_SETUP_MASK (0xff << 16) +#define LCDIF_TIMING_CMD_SETUP_OFFSET 16 +#define LCDIF_TIMING_DATA_HOLD_MASK (0xff << 8) +#define LCDIF_TIMING_DATA_HOLD_OFFSET 8 +#define LCDIF_TIMING_DATA_SETUP_MASK (0xff << 0) +#define LCDIF_TIMING_DATA_SETUP_OFFSET 0 + +#define LCDIF_VDCTRL0_VSYNC_OEB (1 << 29) +#define LCDIF_VDCTRL0_ENABLE_PRESENT (1 << 28) +#define LCDIF_VDCTRL0_VSYNC_POL (1 << 27) +#define LCDIF_VDCTRL0_HSYNC_POL (1 << 26) +#define LCDIF_VDCTRL0_DOTCLK_POL (1 << 25) +#define LCDIF_VDCTRL0_ENABLE_POL (1 << 24) +#define LCDIF_VDCTRL0_VSYNC_PERIOD_UNIT (1 << 21) +#define LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20) +#define LCDIF_VDCTRL0_HALF_LINE (1 << 19) +#define LCDIF_VDCTRL0_HALF_LINE_MODE (1 << 18) +#define LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_MASK 0x3ffff +#define LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_OFFSET 0 + +#define LCDIF_VDCTRL1_VSYNC_PERIOD_MASK 0xffffffff +#define LCDIF_VDCTRL1_VSYNC_PERIOD_OFFSET 0 + +#define LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_MASK (0x3fff << 18) +#define LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_OFFSET 18 +#define LCDIF_VDCTRL2_HSYNC_PERIOD_MASK 0x3ffff +#define LCDIF_VDCTRL2_HSYNC_PERIOD_OFFSET 0 + +#define LCDIF_VDCTRL3_MUX_SYNC_SIGNALS (1 << 29) +#define LCDIF_VDCTRL3_VSYNC_ONLY (1 << 28) +#define LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT_MASK (0xfff << 16) +#define LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT_OFFSET 16 +#define LCDIF_VDCTRL3_VERTICAL_WAIT_CNT_MASK (0xffff << 0) +#define LCDIF_VDCTRL3_VERTICAL_WAIT_CNT_OFFSET 0 + +#define LCDIF_VDCTRL4_DOTCLK_DLY_SEL_MASK (0x7 << 29) +#define LCDIF_VDCTRL4_DOTCLK_DLY_SEL_OFFSET 29 +#define LCDIF_VDCTRL4_SYNC_SIGNALS_ON (1 << 18) +#define LCDIF_VDCTRL4_DOTCLK_H_VALID_DATA_CNT_MASK 0x3ffff +#define LCDIF_VDCTRL4_DOTCLK_H_VALID_DATA_CNT_OFFSET 0 + +#endif /* __MX28_REGS_LCDIF_H__ */

If the LCD controller is on before the CPU goes into reset, the traffic on LCDIF data pins interferes with the BootROM's boot mode sampling. So shut the controller down.
Signed-off-by: Marek Vasut marex@denx.de Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de --- arch/arm/cpu/arm926ejs/mx28/mx28.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/arch/arm/cpu/arm926ejs/mx28/mx28.c b/arch/arm/cpu/arm926ejs/mx28/mx28.c index 865dbb3..a82ff25 100644 --- a/arch/arm/cpu/arm926ejs/mx28/mx28.c +++ b/arch/arm/cpu/arm926ejs/mx28/mx28.c @@ -51,9 +51,16 @@ void reset_cpu(ulong ignored) __attribute__((noreturn));
void reset_cpu(ulong ignored) { - struct mx28_rtc_regs *rtc_regs = (struct mx28_rtc_regs *)MXS_RTC_BASE; + struct mx28_lcdif_regs *lcdif_regs = + (struct mx28_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);

From: Marek Vasut marek.vasut@gmail.com
Signed-off-by: Marek Vasut marek.vasut@gmail.com Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de --- arch/arm/include/asm/arch-mx28/imx-regs.h | 1 + arch/arm/include/asm/arch-mx28/regs-lradc.h | 400 +++++++++++++++++++++++++++ 2 files changed, 401 insertions(+) create mode 100644 arch/arm/include/asm/arch-mx28/regs-lradc.h
diff --git a/arch/arm/include/asm/arch-mx28/imx-regs.h b/arch/arm/include/asm/arch-mx28/imx-regs.h index 581bf0a..37d0a93 100644 --- a/arch/arm/include/asm/arch-mx28/imx-regs.h +++ b/arch/arm/include/asm/arch-mx28/imx-regs.h @@ -31,6 +31,7 @@ #include <asm/arch/regs-gpmi.h> #include <asm/arch/regs-i2c.h> #include <asm/arch/regs-lcdif.h> +#include <asm/arch/regs-lradc.h> #include <asm/arch/regs-ocotp.h> #include <asm/arch/regs-pinctrl.h> #include <asm/arch/regs-power.h> diff --git a/arch/arm/include/asm/arch-mx28/regs-lradc.h b/arch/arm/include/asm/arch-mx28/regs-lradc.h new file mode 100644 index 0000000..16e2bbf --- /dev/null +++ b/arch/arm/include/asm/arch-mx28/regs-lradc.h @@ -0,0 +1,400 @@ +/* + * Freescale i.MX28 LRADC Register Definitions + * + * Copyright (C) 2011 Marek Vasut marek.vasut@gmail.com + * on behalf of DENX Software Engineering GmbH + * + * Based on code from LTIB: + * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. + * + * 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 + * + */ + +#ifndef __MX28_REGS_LRADC_H__ +#define __MX28_REGS_LRADC_H__ + +#include <asm/arch/regs-common.h> + +#ifndef __ASSEMBLY__ +struct mx28_lradc_regs { + mx28_reg_32(hw_lradc_ctrl0); + mx28_reg_32(hw_lradc_ctrl1); + mx28_reg_32(hw_lradc_ctrl2); + mx28_reg_32(hw_lradc_ctrl3); + mx28_reg_32(hw_lradc_status); + mx28_reg_32(hw_lradc_ch0); + mx28_reg_32(hw_lradc_ch1); + mx28_reg_32(hw_lradc_ch2); + mx28_reg_32(hw_lradc_ch3); + mx28_reg_32(hw_lradc_ch4); + mx28_reg_32(hw_lradc_ch5); + mx28_reg_32(hw_lradc_ch6); + mx28_reg_32(hw_lradc_ch7); + mx28_reg_32(hw_lradc_delay0); + mx28_reg_32(hw_lradc_delay1); + mx28_reg_32(hw_lradc_delay2); + mx28_reg_32(hw_lradc_delay3); + mx28_reg_32(hw_lradc_debug0); + mx28_reg_32(hw_lradc_debug1); + mx28_reg_32(hw_lradc_conversion); + mx28_reg_32(hw_lradc_ctrl4); + mx28_reg_32(hw_lradc_treshold0); + mx28_reg_32(hw_lradc_treshold1); + mx28_reg_32(hw_lradc_version); +}; +#endif + +#define LRADC_CTRL0_SFTRST (1 << 31) +#define LRADC_CTRL0_CLKGATE (1 << 30) +#define LRADC_CTRL0_ONCHIP_GROUNDREF (1 << 26) +#define LRADC_CTRL0_BUTTON1_DETECT_ENABLE (1 << 25) +#define LRADC_CTRL0_BUTTON0_DETECT_ENABLE (1 << 24) +#define LRADC_CTRL0_TOUCH_DETECT_ENABLE (1 << 23) +#define LRADC_CTRL0_TOUCH_SCREEN_TYPE (1 << 22) +#define LRADC_CTRL0_YNLRSW (1 << 21) +#define LRADC_CTRL0_YPLLSW_MASK (0x3 << 19) +#define LRADC_CTRL0_YPLLSW_OFFSET 19 +#define LRADC_CTRL0_XNURSW_MASK (0x3 << 17) +#define LRADC_CTRL0_XNURSW_OFFSET 17 +#define LRADC_CTRL0_XPULSW (1 << 16) +#define LRADC_CTRL0_SCHEDULE_MASK 0xff +#define LRADC_CTRL0_SCHEDULE_OFFSET 0 + +#define LRADC_CTRL1_BUTTON1_DETECT_IRQ_EN (1 << 28) +#define LRADC_CTRL1_BUTTON0_DETECT_IRQ_EN (1 << 27) +#define LRADC_CTRL1_THRESHOLD1_DETECT_IRQ_EN (1 << 26) +#define LRADC_CTRL1_THRESHOLD0_DETECT_IRQ_EN (1 << 25) +#define LRADC_CTRL1_TOUCH_DETECT_IRQ_EN (1 << 24) +#define LRADC_CTRL1_LRADC7_IRQ_EN (1 << 23) +#define LRADC_CTRL1_LRADC6_IRQ_EN (1 << 22) +#define LRADC_CTRL1_LRADC5_IRQ_EN (1 << 21) +#define LRADC_CTRL1_LRADC4_IRQ_EN (1 << 20) +#define LRADC_CTRL1_LRADC3_IRQ_EN (1 << 19) +#define LRADC_CTRL1_LRADC2_IRQ_EN (1 << 18) +#define LRADC_CTRL1_LRADC1_IRQ_EN (1 << 17) +#define LRADC_CTRL1_LRADC0_IRQ_EN (1 << 16) +#define LRADC_CTRL1_BUTTON1_DETECT_IRQ (1 << 12) +#define LRADC_CTRL1_BUTTON0_DETECT_IRQ (1 << 11) +#define LRADC_CTRL1_THRESHOLD1_DETECT_IRQ (1 << 10) +#define LRADC_CTRL1_THRESHOLD0_DETECT_IRQ (1 << 9) +#define LRADC_CTRL1_TOUCH_DETECT_IRQ (1 << 8) +#define LRADC_CTRL1_LRADC7_IRQ (1 << 7) +#define LRADC_CTRL1_LRADC6_IRQ (1 << 6) +#define LRADC_CTRL1_LRADC5_IRQ (1 << 5) +#define LRADC_CTRL1_LRADC4_IRQ (1 << 4) +#define LRADC_CTRL1_LRADC3_IRQ (1 << 3) +#define LRADC_CTRL1_LRADC2_IRQ (1 << 2) +#define LRADC_CTRL1_LRADC1_IRQ (1 << 1) +#define LRADC_CTRL1_LRADC0_IRQ (1 << 0) + +#define LRADC_CTRL2_DIVIDE_BY_TWO_MASK (0xff << 24) +#define LRADC_CTRL2_DIVIDE_BY_TWO_OFFSET 24 +#define LRADC_CTRL2_TEMPSENSE_PWD (1 << 15) +#define LRADC_CTRL2_VTHSENSE_MASK (0x3 << 13) +#define LRADC_CTRL2_VTHSENSE_OFFSET 13 +#define LRADC_CTRL2_DISABLE_MUXAMP_BYPASS (1 << 12) +#define LRADC_CTRL2_TEMP_SENSOR_IENABLE1 (1 << 9) +#define LRADC_CTRL2_TEMP_SENSOR_IENABLE0 (1 << 8) +#define LRADC_CTRL2_TEMP_ISRC1_MASK (0xf << 4) +#define LRADC_CTRL2_TEMP_ISRC1_OFFSET 4 +#define LRADC_CTRL2_TEMP_ISRC1_300 (0xf << 4) +#define LRADC_CTRL2_TEMP_ISRC1_280 (0xe << 4) +#define LRADC_CTRL2_TEMP_ISRC1_260 (0xd << 4) +#define LRADC_CTRL2_TEMP_ISRC1_240 (0xc << 4) +#define LRADC_CTRL2_TEMP_ISRC1_220 (0xb << 4) +#define LRADC_CTRL2_TEMP_ISRC1_200 (0xa << 4) +#define LRADC_CTRL2_TEMP_ISRC1_180 (0x9 << 4) +#define LRADC_CTRL2_TEMP_ISRC1_160 (0x8 << 4) +#define LRADC_CTRL2_TEMP_ISRC1_140 (0x7 << 4) +#define LRADC_CTRL2_TEMP_ISRC1_120 (0x6 << 4) +#define LRADC_CTRL2_TEMP_ISRC1_100 (0x5 << 4) +#define LRADC_CTRL2_TEMP_ISRC1_80 (0x4 << 4) +#define LRADC_CTRL2_TEMP_ISRC1_60 (0x3 << 4) +#define LRADC_CTRL2_TEMP_ISRC1_40 (0x2 << 4) +#define LRADC_CTRL2_TEMP_ISRC1_20 (0x1 << 4) +#define LRADC_CTRL2_TEMP_ISRC1_ZERO (0x0 << 4) +#define LRADC_CTRL2_TEMP_ISRC0_MASK (0xf << 0) +#define LRADC_CTRL2_TEMP_ISRC0_OFFSET 0 +#define LRADC_CTRL2_TEMP_ISRC0_300 (0xf << 0) +#define LRADC_CTRL2_TEMP_ISRC0_280 (0xe << 0) +#define LRADC_CTRL2_TEMP_ISRC0_260 (0xd << 0) +#define LRADC_CTRL2_TEMP_ISRC0_240 (0xc << 0) +#define LRADC_CTRL2_TEMP_ISRC0_220 (0xb << 0) +#define LRADC_CTRL2_TEMP_ISRC0_200 (0xa << 0) +#define LRADC_CTRL2_TEMP_ISRC0_180 (0x9 << 0) +#define LRADC_CTRL2_TEMP_ISRC0_160 (0x8 << 0) +#define LRADC_CTRL2_TEMP_ISRC0_140 (0x7 << 0) +#define LRADC_CTRL2_TEMP_ISRC0_120 (0x6 << 0) +#define LRADC_CTRL2_TEMP_ISRC0_100 (0x5 << 0) +#define LRADC_CTRL2_TEMP_ISRC0_80 (0x4 << 0) +#define LRADC_CTRL2_TEMP_ISRC0_60 (0x3 << 0) +#define LRADC_CTRL2_TEMP_ISRC0_40 (0x2 << 0) +#define LRADC_CTRL2_TEMP_ISRC0_20 (0x1 << 0) +#define LRADC_CTRL2_TEMP_ISRC0_ZERO (0x0 << 0) + +#define LRADC_CTRL3_DISCARD_MASK (0x3 << 24) +#define LRADC_CTRL3_DISCARD_OFFSET 24 +#define LRADC_CTRL3_DISCARD_1_SAMPLE (0x1 << 24) +#define LRADC_CTRL3_DISCARD_2_SAMPLES (0x2 << 24) +#define LRADC_CTRL3_DISCARD_3_SAMPLES (0x3 << 24) +#define LRADC_CTRL3_FORCE_ANALOG_PWUP (1 << 23) +#define LRADC_CTRL3_FORCE_ANALOG_PWDN (1 << 22) +#define LRADC_CTRL3_CYCLE_TIME_MASK (0x3 << 8) +#define LRADC_CTRL3_CYCLE_TIME_OFFSET 8 +#define LRADC_CTRL3_CYCLE_TIME_6MHZ (0x0 << 8) +#define LRADC_CTRL3_CYCLE_TIME_4MHZ (0x1 << 8) +#define LRADC_CTRL3_CYCLE_TIME_3MHZ (0x2 << 8) +#define LRADC_CTRL3_CYCLE_TIME_2MHZ (0x3 << 8) +#define LRADC_CTRL3_HIGH_TIME_MASK (0x3 << 4) +#define LRADC_CTRL3_HIGH_TIME_OFFSET 4 +#define LRADC_CTRL3_HIGH_TIME_42NS (0x0 << 4) +#define LRADC_CTRL3_HIGH_TIME_83NS (0x1 << 4) +#define LRADC_CTRL3_HIGH_TIME_125NS (0x2 << 4) +#define LRADC_CTRL3_HIGH_TIME_250NS (0x3 << 4) +#define LRADC_CTRL3_DELAY_CLOCK (1 << 1) +#define LRADC_CTRL3_INVERT_CLOCK (1 << 0) + +#define LRADC_STATUS_BUTTON1_PRESENT (1 << 28) +#define LRADC_STATUS_BUTTON0_PRESENT (1 << 27) +#define LRADC_STATUS_TEMP1_PRESENT (1 << 26) +#define LRADC_STATUS_TEMP0_PRESENT (1 << 25) +#define LRADC_STATUS_TOUCH_PANEL_PRESENT (1 << 24) +#define LRADC_STATUS_CHANNEL7_PRESENT (1 << 23) +#define LRADC_STATUS_CHANNEL6_PRESENT (1 << 22) +#define LRADC_STATUS_CHANNEL5_PRESENT (1 << 21) +#define LRADC_STATUS_CHANNEL4_PRESENT (1 << 20) +#define LRADC_STATUS_CHANNEL3_PRESENT (1 << 19) +#define LRADC_STATUS_CHANNEL2_PRESENT (1 << 18) +#define LRADC_STATUS_CHANNEL1_PRESENT (1 << 17) +#define LRADC_STATUS_CHANNEL0_PRESENT (1 << 16) +#define LRADC_STATUS_BUTTON1_DETECT_RAW (1 << 2) +#define LRADC_STATUS_BUTTON0_DETECT_RAW (1 << 1) +#define LRADC_STATUS_TOUCH_DETECT_RAW (1 << 0) + +#define LRADC_CH_TOGGLE (1 << 31) +#define LRADC_CH7_TESTMODE_TOGGLE (1 << 30) +#define LRADC_CH_ACCUMULATE (1 << 29) +#define LRADC_CH_NUM_SAMPLES_MASK (0x1f << 24) +#define LRADC_CH_NUM_SAMPLES_OFFSET 24 +#define LRADC_CH_VALUE_MASK 0x3ffff +#define LRADC_CH_VALUE_OFFSET 0 + +#define LRADC_DELAY_TRIGGER_LRADCS_MASK (0xff << 24) +#define LRADC_DELAY_TRIGGER_LRADCS_OFFSET 24 +#define LRADC_DELAY_KICK (1 << 20) +#define LRADC_DELAY_TRIGGER_DELAYS_MASK (0xf << 16) +#define LRADC_DELAY_TRIGGER_DELAYS_OFFSET 16 +#define LRADC_DELAY_LOOP_COUNT_MASK (0x1f << 11) +#define LRADC_DELAY_LOOP_COUNT_OFFSET 11 +#define LRADC_DELAY_DELAY_MASK 0x7ff +#define LRADC_DELAY_DELAY_OFFSET 0 + +#define LRADC_DEBUG0_READONLY_MASK (0xffff << 16) +#define LRADC_DEBUG0_READONLY_OFFSET 16 +#define LRADC_DEBUG0_STATE_MASK (0xfff << 0) +#define LRADC_DEBUG0_STATE_OFFSET 0 + +#define LRADC_DEBUG1_REQUEST_MASK (0xff << 16) +#define LRADC_DEBUG1_REQUEST_OFFSET 16 +#define LRADC_DEBUG1_TESTMODE_COUNT_MASK (0x1f << 8) +#define LRADC_DEBUG1_TESTMODE_COUNT_OFFSET 8 +#define LRADC_DEBUG1_TESTMODE6 (1 << 2) +#define LRADC_DEBUG1_TESTMODE5 (1 << 1) +#define LRADC_DEBUG1_TESTMODE (1 << 0) + +#define LRADC_CONVERSION_AUTOMATIC (1 << 20) +#define LRADC_CONVERSION_SCALE_FACTOR_MASK (0x3 << 16) +#define LRADC_CONVERSION_SCALE_FACTOR_OFFSET 16 +#define LRADC_CONVERSION_SCALE_FACTOR_NIMH (0x0 << 16) +#define LRADC_CONVERSION_SCALE_FACTOR_DUAL_NIMH (0x1 << 16) +#define LRADC_CONVERSION_SCALE_FACTOR_LI_ION (0x2 << 16) +#define LRADC_CONVERSION_SCALE_FACTOR_ALT_LI_ION (0x3 << 16) +#define LRADC_CONVERSION_SCALED_BATT_VOLTAGE_MASK 0x3ff +#define LRADC_CONVERSION_SCALED_BATT_VOLTAGE_OFFSET 0 + +#define LRADC_CTRL4_LRADC7SELECT_MASK (0xf << 28) +#define LRADC_CTRL4_LRADC7SELECT_OFFSET 28 +#define LRADC_CTRL4_LRADC7SELECT_CHANNEL0 (0x0 << 28) +#define LRADC_CTRL4_LRADC7SELECT_CHANNEL1 (0x1 << 28) +#define LRADC_CTRL4_LRADC7SELECT_CHANNEL2 (0x2 << 28) +#define LRADC_CTRL4_LRADC7SELECT_CHANNEL3 (0x3 << 28) +#define LRADC_CTRL4_LRADC7SELECT_CHANNEL4 (0x4 << 28) +#define LRADC_CTRL4_LRADC7SELECT_CHANNEL5 (0x5 << 28) +#define LRADC_CTRL4_LRADC7SELECT_CHANNEL6 (0x6 << 28) +#define LRADC_CTRL4_LRADC7SELECT_CHANNEL7 (0x7 << 28) +#define LRADC_CTRL4_LRADC7SELECT_CHANNEL8 (0x8 << 28) +#define LRADC_CTRL4_LRADC7SELECT_CHANNEL9 (0x9 << 28) +#define LRADC_CTRL4_LRADC7SELECT_CHANNEL10 (0xa << 28) +#define LRADC_CTRL4_LRADC7SELECT_CHANNEL11 (0xb << 28) +#define LRADC_CTRL4_LRADC7SELECT_CHANNEL12 (0xc << 28) +#define LRADC_CTRL4_LRADC7SELECT_CHANNEL13 (0xd << 28) +#define LRADC_CTRL4_LRADC7SELECT_CHANNEL14 (0xe << 28) +#define LRADC_CTRL4_LRADC7SELECT_CHANNEL15 (0xf << 28) +#define LRADC_CTRL4_LRADC6SELECT_MASK (0xf << 24) +#define LRADC_CTRL4_LRADC6SELECT_OFFSET 24 +#define LRADC_CTRL4_LRADC6SELECT_CHANNEL0 (0x0 << 24) +#define LRADC_CTRL4_LRADC6SELECT_CHANNEL1 (0x1 << 24) +#define LRADC_CTRL4_LRADC6SELECT_CHANNEL2 (0x2 << 24) +#define LRADC_CTRL4_LRADC6SELECT_CHANNEL3 (0x3 << 24) +#define LRADC_CTRL4_LRADC6SELECT_CHANNEL4 (0x4 << 24) +#define LRADC_CTRL4_LRADC6SELECT_CHANNEL5 (0x5 << 24) +#define LRADC_CTRL4_LRADC6SELECT_CHANNEL6 (0x6 << 24) +#define LRADC_CTRL4_LRADC6SELECT_CHANNEL7 (0x7 << 24) +#define LRADC_CTRL4_LRADC6SELECT_CHANNEL8 (0x8 << 24) +#define LRADC_CTRL4_LRADC6SELECT_CHANNEL9 (0x9 << 24) +#define LRADC_CTRL4_LRADC6SELECT_CHANNEL10 (0xa << 24) +#define LRADC_CTRL4_LRADC6SELECT_CHANNEL11 (0xb << 24) +#define LRADC_CTRL4_LRADC6SELECT_CHANNEL12 (0xc << 24) +#define LRADC_CTRL4_LRADC6SELECT_CHANNEL13 (0xd << 24) +#define LRADC_CTRL4_LRADC6SELECT_CHANNEL14 (0xe << 24) +#define LRADC_CTRL4_LRADC6SELECT_CHANNEL15 (0xf << 24) +#define LRADC_CTRL4_LRADC5SELECT_MASK (0xf << 20) +#define LRADC_CTRL4_LRADC5SELECT_OFFSET 20 +#define LRADC_CTRL4_LRADC5SELECT_CHANNEL0 (0x0 << 20) +#define LRADC_CTRL4_LRADC5SELECT_CHANNEL1 (0x1 << 20) +#define LRADC_CTRL4_LRADC5SELECT_CHANNEL2 (0x2 << 20) +#define LRADC_CTRL4_LRADC5SELECT_CHANNEL3 (0x3 << 20) +#define LRADC_CTRL4_LRADC5SELECT_CHANNEL4 (0x4 << 20) +#define LRADC_CTRL4_LRADC5SELECT_CHANNEL5 (0x5 << 20) +#define LRADC_CTRL4_LRADC5SELECT_CHANNEL6 (0x6 << 20) +#define LRADC_CTRL4_LRADC5SELECT_CHANNEL7 (0x7 << 20) +#define LRADC_CTRL4_LRADC5SELECT_CHANNEL8 (0x8 << 20) +#define LRADC_CTRL4_LRADC5SELECT_CHANNEL9 (0x9 << 20) +#define LRADC_CTRL4_LRADC5SELECT_CHANNEL10 (0xa << 20) +#define LRADC_CTRL4_LRADC5SELECT_CHANNEL11 (0xb << 20) +#define LRADC_CTRL4_LRADC5SELECT_CHANNEL12 (0xc << 20) +#define LRADC_CTRL4_LRADC5SELECT_CHANNEL13 (0xd << 20) +#define LRADC_CTRL4_LRADC5SELECT_CHANNEL14 (0xe << 20) +#define LRADC_CTRL4_LRADC5SELECT_CHANNEL15 (0xf << 20) +#define LRADC_CTRL4_LRADC4SELECT_MASK (0xf << 16) +#define LRADC_CTRL4_LRADC4SELECT_OFFSET 16 +#define LRADC_CTRL4_LRADC4SELECT_CHANNEL0 (0x0 << 16) +#define LRADC_CTRL4_LRADC4SELECT_CHANNEL1 (0x1 << 16) +#define LRADC_CTRL4_LRADC4SELECT_CHANNEL2 (0x2 << 16) +#define LRADC_CTRL4_LRADC4SELECT_CHANNEL3 (0x3 << 16) +#define LRADC_CTRL4_LRADC4SELECT_CHANNEL4 (0x4 << 16) +#define LRADC_CTRL4_LRADC4SELECT_CHANNEL5 (0x5 << 16) +#define LRADC_CTRL4_LRADC4SELECT_CHANNEL6 (0x6 << 16) +#define LRADC_CTRL4_LRADC4SELECT_CHANNEL7 (0x7 << 16) +#define LRADC_CTRL4_LRADC4SELECT_CHANNEL8 (0x8 << 16) +#define LRADC_CTRL4_LRADC4SELECT_CHANNEL9 (0x9 << 16) +#define LRADC_CTRL4_LRADC4SELECT_CHANNEL10 (0xa << 16) +#define LRADC_CTRL4_LRADC4SELECT_CHANNEL11 (0xb << 16) +#define LRADC_CTRL4_LRADC4SELECT_CHANNEL12 (0xc << 16) +#define LRADC_CTRL4_LRADC4SELECT_CHANNEL13 (0xd << 16) +#define LRADC_CTRL4_LRADC4SELECT_CHANNEL14 (0xe << 16) +#define LRADC_CTRL4_LRADC4SELECT_CHANNEL15 (0xf << 16) +#define LRADC_CTRL4_LRADC3SELECT_MASK (0xf << 12) +#define LRADC_CTRL4_LRADC3SELECT_OFFSET 12 +#define LRADC_CTRL4_LRADC3SELECT_CHANNEL0 (0x0 << 12) +#define LRADC_CTRL4_LRADC3SELECT_CHANNEL1 (0x1 << 12) +#define LRADC_CTRL4_LRADC3SELECT_CHANNEL2 (0x2 << 12) +#define LRADC_CTRL4_LRADC3SELECT_CHANNEL3 (0x3 << 12) +#define LRADC_CTRL4_LRADC3SELECT_CHANNEL4 (0x4 << 12) +#define LRADC_CTRL4_LRADC3SELECT_CHANNEL5 (0x5 << 12) +#define LRADC_CTRL4_LRADC3SELECT_CHANNEL6 (0x6 << 12) +#define LRADC_CTRL4_LRADC3SELECT_CHANNEL7 (0x7 << 12) +#define LRADC_CTRL4_LRADC3SELECT_CHANNEL8 (0x8 << 12) +#define LRADC_CTRL4_LRADC3SELECT_CHANNEL9 (0x9 << 12) +#define LRADC_CTRL4_LRADC3SELECT_CHANNEL10 (0xa << 12) +#define LRADC_CTRL4_LRADC3SELECT_CHANNEL11 (0xb << 12) +#define LRADC_CTRL4_LRADC3SELECT_CHANNEL12 (0xc << 12) +#define LRADC_CTRL4_LRADC3SELECT_CHANNEL13 (0xd << 12) +#define LRADC_CTRL4_LRADC3SELECT_CHANNEL14 (0xe << 12) +#define LRADC_CTRL4_LRADC3SELECT_CHANNEL15 (0xf << 12) +#define LRADC_CTRL4_LRADC2SELECT_MASK (0xf << 8) +#define LRADC_CTRL4_LRADC2SELECT_OFFSET 8 +#define LRADC_CTRL4_LRADC2SELECT_CHANNEL0 (0x0 << 8) +#define LRADC_CTRL4_LRADC2SELECT_CHANNEL1 (0x1 << 8) +#define LRADC_CTRL4_LRADC2SELECT_CHANNEL2 (0x2 << 8) +#define LRADC_CTRL4_LRADC2SELECT_CHANNEL3 (0x3 << 8) +#define LRADC_CTRL4_LRADC2SELECT_CHANNEL4 (0x4 << 8) +#define LRADC_CTRL4_LRADC2SELECT_CHANNEL5 (0x5 << 8) +#define LRADC_CTRL4_LRADC2SELECT_CHANNEL6 (0x6 << 8) +#define LRADC_CTRL4_LRADC2SELECT_CHANNEL7 (0x7 << 8) +#define LRADC_CTRL4_LRADC2SELECT_CHANNEL8 (0x8 << 8) +#define LRADC_CTRL4_LRADC2SELECT_CHANNEL9 (0x9 << 8) +#define LRADC_CTRL4_LRADC2SELECT_CHANNEL10 (0xa << 8) +#define LRADC_CTRL4_LRADC2SELECT_CHANNEL11 (0xb << 8) +#define LRADC_CTRL4_LRADC2SELECT_CHANNEL12 (0xc << 8) +#define LRADC_CTRL4_LRADC2SELECT_CHANNEL13 (0xd << 8) +#define LRADC_CTRL4_LRADC2SELECT_CHANNEL14 (0xe << 8) +#define LRADC_CTRL4_LRADC2SELECT_CHANNEL15 (0xf << 8) +#define LRADC_CTRL4_LRADC1SELECT_MASK (0xf << 4) +#define LRADC_CTRL4_LRADC1SELECT_OFFSET 4 +#define LRADC_CTRL4_LRADC1SELECT_CHANNEL0 (0x0 << 4) +#define LRADC_CTRL4_LRADC1SELECT_CHANNEL1 (0x1 << 4) +#define LRADC_CTRL4_LRADC1SELECT_CHANNEL2 (0x2 << 4) +#define LRADC_CTRL4_LRADC1SELECT_CHANNEL3 (0x3 << 4) +#define LRADC_CTRL4_LRADC1SELECT_CHANNEL4 (0x4 << 4) +#define LRADC_CTRL4_LRADC1SELECT_CHANNEL5 (0x5 << 4) +#define LRADC_CTRL4_LRADC1SELECT_CHANNEL6 (0x6 << 4) +#define LRADC_CTRL4_LRADC1SELECT_CHANNEL7 (0x7 << 4) +#define LRADC_CTRL4_LRADC1SELECT_CHANNEL8 (0x8 << 4) +#define LRADC_CTRL4_LRADC1SELECT_CHANNEL9 (0x9 << 4) +#define LRADC_CTRL4_LRADC1SELECT_CHANNEL10 (0xa << 4) +#define LRADC_CTRL4_LRADC1SELECT_CHANNEL11 (0xb << 4) +#define LRADC_CTRL4_LRADC1SELECT_CHANNEL12 (0xc << 4) +#define LRADC_CTRL4_LRADC1SELECT_CHANNEL13 (0xd << 4) +#define LRADC_CTRL4_LRADC1SELECT_CHANNEL14 (0xe << 4) +#define LRADC_CTRL4_LRADC1SELECT_CHANNEL15 (0xf << 4) +#define LRADC_CTRL4_LRADC0SELECT_MASK 0xf +#define LRADC_CTRL4_LRADC0SELECT_CHANNEL0 (0x0 << 0) +#define LRADC_CTRL4_LRADC0SELECT_CHANNEL1 (0x1 << 0) +#define LRADC_CTRL4_LRADC0SELECT_CHANNEL2 (0x2 << 0) +#define LRADC_CTRL4_LRADC0SELECT_CHANNEL3 (0x3 << 0) +#define LRADC_CTRL4_LRADC0SELECT_CHANNEL4 (0x4 << 0) +#define LRADC_CTRL4_LRADC0SELECT_CHANNEL5 (0x5 << 0) +#define LRADC_CTRL4_LRADC0SELECT_CHANNEL6 (0x6 << 0) +#define LRADC_CTRL4_LRADC0SELECT_CHANNEL7 (0x7 << 0) +#define LRADC_CTRL4_LRADC0SELECT_CHANNEL8 (0x8 << 0) +#define LRADC_CTRL4_LRADC0SELECT_CHANNEL9 (0x9 << 0) +#define LRADC_CTRL4_LRADC0SELECT_CHANNEL10 (0xa << 0) +#define LRADC_CTRL4_LRADC0SELECT_CHANNEL11 (0xb << 0) +#define LRADC_CTRL4_LRADC0SELECT_CHANNEL12 (0xc << 0) +#define LRADC_CTRL4_LRADC0SELECT_CHANNEL13 (0xd << 0) +#define LRADC_CTRL4_LRADC0SELECT_CHANNEL14 (0xe << 0) +#define LRADC_CTRL4_LRADC0SELECT_CHANNEL15 (0xf << 0) + +#define LRADC_THRESHOLD_ENABLE (1 << 24) +#define LRADC_THRESHOLD_BATTCHRG_DISABLE (1 << 23) +#define LRADC_THRESHOLD_CHANNEL_SEL_MASK (0x7 << 20) +#define LRADC_THRESHOLD_CHANNEL_SEL_OFFSET 20 +#define LRADC_THRESHOLD_CHANNEL_SEL_CHANNEL0 (0x0 << 20) +#define LRADC_THRESHOLD_CHANNEL_SEL_CHANNEL1 (0x1 << 20) +#define LRADC_THRESHOLD_CHANNEL_SEL_CHANNEL2 (0x2 << 20) +#define LRADC_THRESHOLD_CHANNEL_SEL_CHANNEL3 (0x3 << 20) +#define LRADC_THRESHOLD_CHANNEL_SEL_CHANNEL4 (0x4 << 20) +#define LRADC_THRESHOLD_CHANNEL_SEL_CHANNEL5 (0x5 << 20) +#define LRADC_THRESHOLD_CHANNEL_SEL_CHANNEL6 (0x6 << 20) +#define LRADC_THRESHOLD_CHANNEL_SEL_CHANNEL7 (0x7 << 20) +#define LRADC_THRESHOLD_SETTING_MASK (0x3 << 18) +#define LRADC_THRESHOLD_SETTING_OFFSET 18 +#define LRADC_THRESHOLD_SETTING_NO_COMPARE (0x0 << 18) +#define LRADC_THRESHOLD_SETTING_DETECT_LOW (0x1 << 18) +#define LRADC_THRESHOLD_SETTING_DETECT_HIGH (0x2 << 18) +#define LRADC_THRESHOLD_SETTING_RESERVED (0x3 << 18) +#define LRADC_THRESHOLD_VALUE_MASK 0x3ffff +#define LRADC_THRESHOLD_VALUE_OFFSET 0 + +#define LRADC_VERSION_MAJOR_MASK (0xff << 24) +#define LRADC_VERSION_MAJOR_OFFSET 24 +#define LRADC_VERSION_MINOR_MASK (0xff << 16) +#define LRADC_VERSION_MINOR_OFFSET 16 +#define LRADC_VERSION_STEP_MASK 0xffff +#define LRADC_VERSION_STEP_OFFSET 0 + +#endif /* __MX28_REGS_LRADC_H__ */

From: Marek Vasut marek.vasut@gmail.com
This code is part of battery boot support for i.MX28.
Signed-off-by: Marek Vasut marek.vasut@gmail.com Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de --- arch/arm/cpu/arm926ejs/mx28/Makefile | 2 +- arch/arm/cpu/arm926ejs/mx28/mx28_init.h | 3 + arch/arm/cpu/arm926ejs/mx28/spl_lradc_init.c | 86 ++++++++++++++++++++++++++ arch/arm/cpu/arm926ejs/mx28/spl_power_init.c | 10 +++ 4 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 arch/arm/cpu/arm926ejs/mx28/spl_lradc_init.c
diff --git a/arch/arm/cpu/arm926ejs/mx28/Makefile b/arch/arm/cpu/arm926ejs/mx28/Makefile index a2e3f77..674a3af 100644 --- a/arch/arm/cpu/arm926ejs/mx28/Makefile +++ b/arch/arm/cpu/arm926ejs/mx28/Makefile @@ -28,7 +28,7 @@ LIB = $(obj)lib$(SOC).o COBJS = clock.o mx28.o iomux.o timer.o
ifdef CONFIG_SPL_BUILD -COBJS += spl_boot.o spl_mem_init.o spl_power_init.o +COBJS += spl_boot.o spl_lradc_init.o spl_mem_init.o spl_power_init.o endif
SRCS := $(START:.o=.S) $(COBJS:.o=.c) diff --git a/arch/arm/cpu/arm926ejs/mx28/mx28_init.h b/arch/arm/cpu/arm926ejs/mx28/mx28_init.h index 8eac958..e3a4493 100644 --- a/arch/arm/cpu/arm926ejs/mx28/mx28_init.h +++ b/arch/arm/cpu/arm926ejs/mx28/mx28_init.h @@ -39,4 +39,7 @@ static inline void mx28_power_wait_pswitch(void) { } void mx28_mem_init(void); uint32_t mx28_mem_get_size(void);
+void mx28_lradc_init(void); +void mx28_lradc_enable_batt_measurement(void); + #endif /* __M28_INIT_H__ */ diff --git a/arch/arm/cpu/arm926ejs/mx28/spl_lradc_init.c b/arch/arm/cpu/arm926ejs/mx28/spl_lradc_init.c new file mode 100644 index 0000000..88a603c --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mx28/spl_lradc_init.c @@ -0,0 +1,86 @@ +/* + * Freescale i.MX28 Battery measurement 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 "mx28_init.h" + +void mx28_lradc_init(void) +{ + struct mx28_lradc_regs *regs = (struct mx28_lradc_regs *)MXS_LRADC_BASE; + + writel(LRADC_CTRL0_SFTRST, ®s->hw_lradc_ctrl0_clr); + writel(LRADC_CTRL0_CLKGATE, ®s->hw_lradc_ctrl0_clr); + writel(LRADC_CTRL0_ONCHIP_GROUNDREF, ®s->hw_lradc_ctrl0_clr); + + clrsetbits_le32(®s->hw_lradc_ctrl3, + LRADC_CTRL3_CYCLE_TIME_MASK, + LRADC_CTRL3_CYCLE_TIME_6MHZ); + + clrsetbits_le32(®s->hw_lradc_ctrl4, + LRADC_CTRL4_LRADC7SELECT_MASK | + LRADC_CTRL4_LRADC6SELECT_MASK, + LRADC_CTRL4_LRADC7SELECT_CHANNEL7 | + LRADC_CTRL4_LRADC6SELECT_CHANNEL10); +} + +void mx28_lradc_enable_batt_measurement(void) +{ + struct mx28_lradc_regs *regs = (struct mx28_lradc_regs *)MXS_LRADC_BASE; + + /* Check if the channel is present at all. */ + if (!(readl(®s->hw_lradc_status) & LRADC_STATUS_CHANNEL7_PRESENT)) + return; + + writel(LRADC_CTRL1_LRADC7_IRQ_EN, ®s->hw_lradc_ctrl1_clr); + writel(LRADC_CTRL1_LRADC7_IRQ, ®s->hw_lradc_ctrl1_clr); + + clrsetbits_le32(®s->hw_lradc_conversion, + LRADC_CONVERSION_SCALE_FACTOR_MASK, + LRADC_CONVERSION_SCALE_FACTOR_LI_ION); + writel(LRADC_CONVERSION_AUTOMATIC, ®s->hw_lradc_conversion_set); + + /* Configure the channel. */ + writel((1 << 7) << LRADC_CTRL2_DIVIDE_BY_TWO_OFFSET, + ®s->hw_lradc_ctrl2_clr); + writel(0xffffffff, ®s->hw_lradc_ch7_clr); + clrbits_le32(®s->hw_lradc_ch7, LRADC_CH_NUM_SAMPLES_MASK); + writel(LRADC_CH_ACCUMULATE, ®s->hw_lradc_ch7_clr); + + /* Schedule the channel. */ + writel(1 << 7, ®s->hw_lradc_ctrl0_set); + + /* Start the channel sampling. */ + writel(((1 << 7) << LRADC_DELAY_TRIGGER_LRADCS_OFFSET) | + ((1 << 3) << LRADC_DELAY_TRIGGER_DELAYS_OFFSET) | + 100, ®s->hw_lradc_delay3); + + writel(0xffffffff, ®s->hw_lradc_ch7_clr); + + writel(LRADC_DELAY_KICK, ®s->hw_lradc_delay3_set); +} diff --git a/arch/arm/cpu/arm926ejs/mx28/spl_power_init.c b/arch/arm/cpu/arm926ejs/mx28/spl_power_init.c index aa4117d..dfb62eb 100644 --- a/arch/arm/cpu/arm926ejs/mx28/spl_power_init.c +++ b/arch/arm/cpu/arm926ejs/mx28/spl_power_init.c @@ -883,6 +883,13 @@ void mx28_power_set_vddd(uint32_t new_target, uint32_t new_brownout) new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET); }
+void mx28_setup_batt_detect(void) +{ + mx28_lradc_init(); + mx28_lradc_enable_batt_measurement(); + early_delay(10); +} + void mx28_power_init(void) { struct mx28_power_regs *power_regs = @@ -892,6 +899,9 @@ void mx28_power_init(void) mx28_power_clear_auto_restart(); mx28_power_set_linreg(); mx28_power_setup_5v_detect(); + + mx28_setup_batt_detect(); + mx28_power_configure_power_source(); mx28_enable_output_rail_protection();

From: Marek Vasut marek.vasut@gmail.com
Signed-off-by: Marek Vasut marek.vasut@gmail.com Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de --- arch/arm/cpu/arm926ejs/mx28/spl_power_init.c | 120 ++++++++++++-------------- 1 file changed, 56 insertions(+), 64 deletions(-)
diff --git a/arch/arm/cpu/arm926ejs/mx28/spl_power_init.c b/arch/arm/cpu/arm926ejs/mx28/spl_power_init.c index dfb62eb..ac942b4 100644 --- a/arch/arm/cpu/arm926ejs/mx28/spl_power_init.c +++ b/arch/arm/cpu/arm926ejs/mx28/spl_power_init.c @@ -104,6 +104,62 @@ void mx28_power_set_linreg(void) POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW); }
+int mx28_get_batt_volt(void) +{ + struct mx28_power_regs *power_regs = + (struct mx28_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; +} + +int mx28_is_batt_ready(void) +{ + return (mx28_get_batt_volt() >= 3600); +} + +int mx28_is_batt_good(void) +{ + struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE; + uint32_t volt = mx28_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 = mx28_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; +} + void mx28_power_setup_5v_detect(void) { struct mx28_power_regs *power_regs = @@ -486,22 +542,6 @@ void mx28_handle_5v_conflict(void) } }
-int mx28_get_batt_volt(void) -{ - struct mx28_power_regs *power_regs = - (struct mx28_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; -} - -int mx28_is_batt_ready(void) -{ - return (mx28_get_batt_volt() >= 3600); -} - void mx28_5v_boot(void) { struct mx28_power_regs *power_regs = @@ -553,54 +593,6 @@ void mx28_switch_vddd_to_dcdc_source(void) POWER_VDDDCTRL_DISABLE_STEPPING); }
-int mx28_is_batt_good(void) -{ - struct mx28_power_regs *power_regs = - (struct mx28_power_regs *)MXS_POWER_BASE; - uint32_t volt; - - volt = readl(&power_regs->hw_power_battmonitor); - volt &= POWER_BATTMONITOR_BATT_VAL_MASK; - volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET; - volt *= 8; - - 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 = readl(&power_regs->hw_power_battmonitor); - volt &= POWER_BATTMONITOR_BATT_VAL_MASK; - volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET; - volt *= 8; - - 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; -} - void mx28_power_configure_power_source(void) { mx28_src_power_init();

From: Marek Vasut marek.vasut@gmail.com
Signed-off-by: Marek Vasut marek.vasut@gmail.com Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de --- arch/arm/cpu/arm926ejs/mx28/spl_power_init.c | 100 +++++++++++++++++++++++--- 1 file changed, 92 insertions(+), 8 deletions(-)
diff --git a/arch/arm/cpu/arm926ejs/mx28/spl_power_init.c b/arch/arm/cpu/arm926ejs/mx28/spl_power_init.c index ac942b4..4b09b0c 100644 --- a/arch/arm/cpu/arm926ejs/mx28/spl_power_init.c +++ b/arch/arm/cpu/arm926ejs/mx28/spl_power_init.c @@ -45,11 +45,11 @@ void mx28_power_clock2pll(void) struct mx28_clkctrl_regs *clkctrl_regs = (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
- writel(CLKCTRL_PLL0CTRL0_POWER, - &clkctrl_regs->hw_clkctrl_pll0ctrl0_set); + setbits_le32(&clkctrl_regs->hw_clkctrl_pll0ctrl0, + CLKCTRL_PLL0CTRL0_POWER); early_delay(100); - writel(CLKCTRL_CLKSEQ_BYPASS_CPU, - &clkctrl_regs->hw_clkctrl_clkseq_clr); + setbits_le32(&clkctrl_regs->hw_clkctrl_clkseq, + CLKCTRL_CLKSEQ_BYPASS_CPU); }
void mx28_power_clear_auto_restart(void) @@ -455,9 +455,14 @@ void mx28_power_enable_4p2(void) mx28_power_init_4p2_regulator();
/* Shutdown battery (none present) */ - 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); + if (!mx28_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); + }
mx28_power_init_dcdc_4p2_source();
@@ -515,6 +520,50 @@ void mx28_powerdown(void) &power_regs->hw_power_reset); }
+void mx28_batt_boot(void) +{ + struct mx28_power_regs *power_regs = + (struct mx28_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); + + mx28_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); +} + void mx28_handle_5v_conflict(void) { struct mx28_power_regs *power_regs = @@ -539,6 +588,11 @@ void mx28_handle_5v_conflict(void) mx28_powerdown(); break; } + + if (tmp & POWER_STS_PSWITCH_MASK) { + mx28_batt_boot(); + break; + } } }
@@ -595,12 +649,42 @@ void mx28_switch_vddd_to_dcdc_source(void)
void mx28_power_configure_power_source(void) { + int batt_ready, batt_good; + struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE; + struct mx28_lradc_regs *lradc_regs = + (struct mx28_lradc_regs *)MXS_LRADC_BASE; + mx28_src_power_init();
- mx28_5v_boot(); + batt_ready = mx28_is_batt_ready(); + + if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) { + batt_good = mx28_is_batt_good(); + if (batt_ready) { + /* 5V source detected, good battery detected. */ + mx28_batt_boot(); + } else { + if (batt_good) { + /* 5V source detected, low battery detceted. */ + } else { + /* 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); + } + mx28_5v_boot(); + } + } else { + /* 5V not detected, booting from battery. */ + mx28_batt_boot(); + } + mx28_power_clock2pll();
mx28_init_batt_bo(); + mx28_switch_vddd_to_dcdc_source(); }

Hi Marek,
On 05/02/2012 12:09 AM, Marek Vasut wrote:
From: Marek Vasut marek.vasut@gmail.com
Signed-off-by: Marek Vasut marek.vasut@gmail.com Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de
arch/arm/cpu/arm926ejs/mx28/spl_power_init.c | 100 +++++++++++++++++++++++--- 1 file changed, 92 insertions(+), 8 deletions(-)
This patch increases the power consumption about 250 mW (~50mA @ 5V). I think it could be nice to disable LRADC after spl boot if it is not really needed.
Best regards, Lauri Hintsala

On 07/25/2012 05:17 PM, Lauri Hintsala wrote:
Hi Marek,
On 05/02/2012 12:09 AM, Marek Vasut wrote:
From: Marek Vasut marek.vasut@gmail.com
Signed-off-by: Marek Vasut marek.vasut@gmail.com Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de
arch/arm/cpu/arm926ejs/mx28/spl_power_init.c | 100 +++++++++++++++++++++++--- 1 file changed, 92 insertions(+), 8 deletions(-)
This patch increases the power consumption about 250 mW (~50mA @ 5V). I think it could be nice to disable LRADC after spl boot if it is not really needed.
This happens only on our machine. The increase is only 25 mW (5mA) on mx28evk.
Lauri

Dear Lauri Hintsala,
On 07/25/2012 05:17 PM, Lauri Hintsala wrote:
Hi Marek,
On 05/02/2012 12:09 AM, Marek Vasut wrote:
From: Marek Vasut marek.vasut@gmail.com
Signed-off-by: Marek Vasut marek.vasut@gmail.com Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de
arch/arm/cpu/arm926ejs/mx28/spl_power_init.c | 100
+++++++++++++++++++++++---
1 file changed, 92 insertions(+), 8 deletions(-)
This patch increases the power consumption about 250 mW (~50mA @ 5V). I think it could be nice to disable LRADC after spl boot if it is not really needed.
This happens only on our machine. The increase is only 25 mW (5mA) on mx28evk.
You tried with latest mainline?
Sure it's OK to disable LRADC afterwards, will you submit a patch please?
Lauri
Best regards, Marek Vasut

On 07/25/2012 10:28 PM, Marek Vasut wrote:
Dear Lauri Hintsala,
On 07/25/2012 05:17 PM, Lauri Hintsala wrote:
Hi Marek,
On 05/02/2012 12:09 AM, Marek Vasut wrote:
From: Marek Vasut marek.vasut@gmail.com
Signed-off-by: Marek Vasut marek.vasut@gmail.com Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de
arch/arm/cpu/arm926ejs/mx28/spl_power_init.c | 100
+++++++++++++++++++++++---
1 file changed, 92 insertions(+), 8 deletions(-)
This patch increases the power consumption about 250 mW (~50mA @ 5V). I think it could be nice to disable LRADC after spl boot if it is not really needed.
This happens only on our machine. The increase is only 25 mW (5mA) on mx28evk.
You tried with latest mainline?
Yes, I'm using v2012.07-rc2.
Sure it's OK to disable LRADC afterwards, will you submit a patch please?
I just noticed the power was not eaten by LRADC. Power consumption is increasing because of a battery charger. The charger circuit is enabled even if the machine has no a battery connected to CPU.
I added debug code to see the status of the battery charger:
--- a/arch/arm/cpu/arm926ejs/mx28/spl_power_init.c +++ b/arch/arm/cpu/arm926ejs/mx28/spl_power_init.c @@ -1003,6 +1003,14 @@ void mx28_power_init(void)
writel(POWER_5VCTRL_PWDN_5VBRNOUT, &power_regs->hw_power_5vctrl_set);
+ /* + power_regs->hw_power_charge_set = POWER_CHARGE_PWD_BATTCHRG; + early_delay(1000); + */ + + serial_printf("Charger circuit: %s\n", + power_regs->hw_power_charge & POWER_CHARGE_PWD_BATTCHRG?"down":"up"); + early_delay(1000); }
After disabling battery charger at the end of power init 25 mW power leak has been gone. Tested with mx28evk rev D. Is there any reason to enable the charger without a battery?
Lauri

Dear Lauri Hintsala,
On 07/25/2012 10:28 PM, Marek Vasut wrote:
Dear Lauri Hintsala,
On 07/25/2012 05:17 PM, Lauri Hintsala wrote:
Hi Marek,
On 05/02/2012 12:09 AM, Marek Vasut wrote:
From: Marek Vasut marek.vasut@gmail.com
Signed-off-by: Marek Vasut marek.vasut@gmail.com Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de
arch/arm/cpu/arm926ejs/mx28/spl_power_init.c | 100
+++++++++++++++++++++++---
1 file changed, 92 insertions(+), 8 deletions(-)
This patch increases the power consumption about 250 mW (~50mA @ 5V). I think it could be nice to disable LRADC after spl boot if it is not really needed.
This happens only on our machine. The increase is only 25 mW (5mA) on mx28evk.
You tried with latest mainline?
Yes, I'm using v2012.07-rc2.
Sure it's OK to disable LRADC afterwards, will you submit a patch please?
I just noticed the power was not eaten by LRADC. Power consumption is increasing because of a battery charger. The charger circuit is enabled even if the machine has no a battery connected to CPU.
I added debug code to see the status of the battery charger:
--- a/arch/arm/cpu/arm926ejs/mx28/spl_power_init.c +++ b/arch/arm/cpu/arm926ejs/mx28/spl_power_init.c @@ -1003,6 +1003,14 @@ void mx28_power_init(void)
writel(POWER_5VCTRL_PWDN_5VBRNOUT, &power_regs->hw_power_5vctrl_set);
- /*
- power_regs->hw_power_charge_set = POWER_CHARGE_PWD_BATTCHRG;
- early_delay(1000);
- */
- serial_printf("Charger circuit: %s\n",
power_regs->hw_power_charge &
POWER_CHARGE_PWD_BATTCHRG?"down":"up");
- early_delay(1000); }
After disabling battery charger at the end of power init 25 mW power leak has been gone. Tested with mx28evk rev D. Is there any reason to enable the charger without a battery?
No, no reason at all, disable it in case you're not running from battery. But please cross check with imx bootlets.
Lauri
Best regards, Marek Vasut

If the WP function is NULL, simply assume the card is always RW.
Signed-off-by: Marek Vasut marex@denx.de Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com --- drivers/mmc/mxsmmc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c index 35c6bda..c7200ee 100644 --- a/drivers/mmc/mxsmmc.c +++ b/drivers/mmc/mxsmmc.c @@ -133,7 +133,8 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) /* READ or WRITE */ if (data->flags & MMC_DATA_READ) { ctrl0 |= SSP_CTRL0_READ; - } else if (priv->mmc_is_wp(mmc->block_dev.dev)) { + } else if (priv->mmc_is_wp && + priv->mmc_is_wp(mmc->block_dev.dev)) { printf("MMC%d: Can not write a locked card!\n", mmc->block_dev.dev); return UNUSABLE_ERR;

On 01/05/2012 23:09, Marek Vasut wrote:
If the WP function is NULL, simply assume the card is always RW.
Signed-off-by: Marek Vasut marex@denx.de Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com
drivers/mmc/mxsmmc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c index 35c6bda..c7200ee 100644 --- a/drivers/mmc/mxsmmc.c +++ b/drivers/mmc/mxsmmc.c @@ -133,7 +133,8 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) /* READ or WRITE */ if (data->flags & MMC_DATA_READ) { ctrl0 |= SSP_CTRL0_READ;
} else if (priv->mmc_is_wp(mmc->block_dev.dev)) {
} else if (priv->mmc_is_wp &&
priv->mmc_is_wp(mmc->block_dev.dev)) { printf("MMC%d: Can not write a locked card!\n", mmc->block_dev.dev); return UNUSABLE_ERR;
This is clearly a bug fix, thanks.
Acked-by: Stefano Babic sbabic@denx.de
Best regards, Stefano Babic

Do not define serial_putc() and serial_puts() calls if CONFIG_SPL_SERIAL_SUPPORT is set.
Signed-off-by: Marek Vasut marex@denx.de Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de --- arch/arm/cpu/arm926ejs/mx28/spl_boot.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/arch/arm/cpu/arm926ejs/mx28/spl_boot.c b/arch/arm/cpu/arm926ejs/mx28/spl_boot.c index c9b4566..a6dfca3 100644 --- a/arch/arm/cpu/arm926ejs/mx28/spl_boot.c +++ b/arch/arm/cpu/arm926ejs/mx28/spl_boot.c @@ -123,8 +123,10 @@ inline void board_init_r(gd_t *id, ulong dest_addr) ; }
+#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) {

On 01/05/2012 23:09, Marek Vasut wrote:
Do not define serial_putc() and serial_puts() calls if CONFIG_SPL_SERIAL_SUPPORT is set.
Signed-off-by: Marek Vasut marex@denx.de Cc: Detlev Zundel dzu@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de
arch/arm/cpu/arm926ejs/mx28/spl_boot.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/arch/arm/cpu/arm926ejs/mx28/spl_boot.c b/arch/arm/cpu/arm926ejs/mx28/spl_boot.c index c9b4566..a6dfca3 100644 --- a/arch/arm/cpu/arm926ejs/mx28/spl_boot.c +++ b/arch/arm/cpu/arm926ejs/mx28/spl_boot.c @@ -123,8 +123,10 @@ inline void board_init_r(gd_t *id, ulong dest_addr) ; }
+#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) {
Acked-by: Stefano Babic sbabic@denx.de
Best regards, Stefano Babic

On 01/05/2012 23:09, Marek Vasut wrote:
These are some improvements that were stuck in my tree for a while, time to expunge them, please consider applying.
Tested on:
- DENX M28EVK v2.0
- DENX M28EVK v1.1
- Mysterious board #1 ...
- Unnamed board #2 ...
Marek Vasut (13): FEC: Abstract out register setup M28EVK: Implement support for new board V2.0 M28EVK: Add SD update command i.MX28: Improve passing of data from SPL to U-Boot i.MX28: Implement boot pads sampling and reporting i.MX28: Add LCDIF register definitions i.MX28: Shut down the LCD controller before reset i.MX28: Add LRADC register definitions i.MX28: Add LRADC init to i.MX28 SPL i.MX28: Reorder battery status functions in SPL i.MX28: Add battery boot components to SPL i.MX28: Check if WP detection is implemented at all i.MX28: Avoid redefining serial_put[cs]()
Applied to u-boot-imx, thanks
Best regards, Stefano Babic
participants (3)
-
Lauri Hintsala
-
Marek Vasut
-
Stefano Babic