[U-Boot] [PATCH v3 1/2] ARM: AM43xx: Add support for RTC only + DDR in self-refresh mode

Keerthy j-keerthy at ti.com
Sat Mar 17 08:01:02 UTC 2018



On Saturday 17 March 2018 01:24 PM, Keerthy wrote:
> Kernel stores information to the RTC_SCRATCH0 and RTC_SCRATCH1 registers
> for wakeup from RTC-only mode with DDR in self-refresh. Parse these
> registers during SPL boot and jump to the kernel resume vector if the
> device is waking up from RTC-only modewith DDR in Self-refresh.
> 

Missed adding Tero's Authorship on this one. I will send v4 of this
patch alone with Author corrected.

> The RTC scratch register layout used is:
> 
> SCRATCH0 : bits00-31 : kernel resume address
> SCRATCH1 : bits00-15 : RTC magic value used to detect valid config
> SCRATCH1 : bits16-31 : board type information populated by bootloader
> 
> During the normal boot path the SCRATCH1 : bits16-31 are updated with
> the eeprom read board type data. In the rtc_only boot path the rtc
> scratchpad register is read and the board type is determined and
> correspondingly ddr dpll parameters are set. This is done so as to avoid
> costly i2c read to eeprom.
> 
> RTC-only +DRR in self-refresh mode support is currently only enabled for
> am43xx_evm_rtconly_config.
> This is not to be used with epos evm builds.
> 
> Signed-off-by: Tero Kristo <t-kristo at ti.com>
> [j-keerthy at ti.com Rebased to latest u-boot master branch]
> Signed-off-by: Keerthy <j-keerthy at ti.com>
> ---
> 
> Changes in v3:
> 
>   * Replaced all RTC Only references with RTC Only plus DDR.
> 
> Changes in v2:
> 
>   * Added more description to CONFIG Option.
>   * Renamed CONFIG_SPL_RTC_ONLY_SUPPORT to CONFIG_SPL_RTC_DDR_SUPPORT
>   * Added the probable kernel file where RTC Magic value will need to be
>     matched.
> 
>  arch/arm/include/asm/arch-am33xx/clock.h  |   6 ++
>  arch/arm/mach-omap2/am33xx/Kconfig        |  14 ++++
>  arch/arm/mach-omap2/am33xx/board.c        | 110 +++++++++++++++++++++++++++---
>  arch/arm/mach-omap2/am33xx/clock.c        |  10 +++
>  arch/arm/mach-omap2/am33xx/clock_am43xx.c |  21 ++++++
>  board/ti/am43xx/MAINTAINERS               |   1 +
>  board/ti/am43xx/board.c                   |  56 +++++++++++++++
>  configs/am43xx_evm_rtconly_defconfig      |  59 ++++++++++++++++
>  8 files changed, 269 insertions(+), 8 deletions(-)
>  create mode 100644 configs/am43xx_evm_rtconly_defconfig
> 
> diff --git a/arch/arm/include/asm/arch-am33xx/clock.h b/arch/arm/include/asm/arch-am33xx/clock.h
> index 9dbcd3a..eeebf16 100644
> --- a/arch/arm/include/asm/arch-am33xx/clock.h
> +++ b/arch/arm/include/asm/arch-am33xx/clock.h
> @@ -122,6 +122,12 @@ void scale_vcores(void);
>  void do_setup_dpll(const struct dpll_regs *, const struct dpll_params *);
>  void prcm_init(void);
>  void enable_basic_clocks(void);
> +
> +void rtc_only_update_board_type(u32 btype);
> +u32 rtc_only_get_board_type(void);
> +void rtc_only_prcm_init(void);
> +void rtc_only_enable_basic_clocks(void);
> +
>  void do_enable_clocks(u32 *const *, u32 *const *, u8);
>  void do_disable_clocks(u32 *const *, u32 *const *, u8);
>  
> diff --git a/arch/arm/mach-omap2/am33xx/Kconfig b/arch/arm/mach-omap2/am33xx/Kconfig
> index 9a9ccd7..76da6d9 100644
> --- a/arch/arm/mach-omap2/am33xx/Kconfig
> +++ b/arch/arm/mach-omap2/am33xx/Kconfig
> @@ -239,6 +239,20 @@ config TARGET_CM_T43
>  
>  endchoice
>  
> +config SPL_RTC_DDR_SUPPORT
> +	bool
> +	depends on SPL
> +	prompt "Enable RTC-DDR ONLY Support"
> +	help
> +	  If you want RTC-DDR ONLY Support, say Y. RTC Only with DDR in
> +	  self-refresh mode is a special power saving mode where in all
> +	  the other voltages are turned off apart from the RTC domain and DDR.
> +	  So only RTC is alive and ticking and one can program it to wake
> +	  up after a predetermined period. Once RTC alarm fires, the PMIC
> +	  powers up all the voltage domains. U-Boot takes a special path
> +	  as the DDR has contents is in self-refresh and restore path is
> +	  followed.
> +
>  endif
>  
>  if AM43XX || AM33XX
> diff --git a/arch/arm/mach-omap2/am33xx/board.c b/arch/arm/mach-omap2/am33xx/board.c
> index ea0caba..ef1de1a 100644
> --- a/arch/arm/mach-omap2/am33xx/board.c
> +++ b/arch/arm/mach-omap2/am33xx/board.c
> @@ -147,6 +147,16 @@ int cpu_mmc_init(bd_t *bis)
>  }
>  #endif
>  
> +/*
> + * RTC only with DDR in self-refresh mode magic value, checked against during
> + * boot to see if we have a valid config. This should be in sync with the value
> + * that will be in drivers/soc/ti/pm33xx.c.
> + */
> +#define RTC_MAGIC_VAL		0x8cd0
> +
> +/* Board type field bit shift for RTC only with DDR in self-refresh mode */
> +#define RTC_BOARD_TYPE_SHIFT	16
> +
>  /* AM33XX has two MUSB controllers which can be host or gadget */
>  #if (defined(CONFIG_USB_MUSB_GADGET) || defined(CONFIG_USB_MUSB_HOST)) && \
>  	(defined(CONFIG_AM335X_USB0) || defined(CONFIG_AM335X_USB1)) && \
> @@ -252,6 +262,48 @@ int arch_misc_init(void)
>  #endif /* CONFIG_USB_MUSB_* && CONFIG_AM335X_USB* && !CONFIG_DM_USB */
>  
>  #ifndef CONFIG_SKIP_LOWLEVEL_INIT
> +
> +#if defined(CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC) || \
> +	(defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_RTC_DDR_SUPPORT))
> +static void rtc32k_unlock(struct davinci_rtc *rtc)
> +{
> +	/*
> +	 * Unlock the RTC's registers.  For more details please see the
> +	 * RTC_SS section of the TRM.  In order to unlock we need to
> +	 * write these specific values (keys) in this order.
> +	 */
> +	writel(RTC_KICK0R_WE, &rtc->kick0r);
> +	writel(RTC_KICK1R_WE, &rtc->kick1r);
> +}
> +#endif
> +
> +#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_RTC_DDR_SUPPORT)
> +/*
> + * Write contents of the RTC_SCRATCH1 register based on board type
> + * Two things are passed
> + * on. First 16 bits (0:15) are written with RTC_MAGIC value. Once the
> + * control gets to kernel, kernel reads the scratchpad register and gets to
> + * know that bootloader has rtc_only support.
> + *
> + * Second important thing is the board type  (16:31). This is needed in the
> + * rtc_only boot where in we want to avoid costly i2c reads to eeprom to
> + * identify the board type and we go ahead and copy the board strings to
> + * am43xx_board_name.
> + */
> +void update_rtc_magic(void)
> +{
> +	struct davinci_rtc *rtc = (struct davinci_rtc *)RTC_BASE;
> +	u32 magic = RTC_MAGIC_VAL;
> +
> +	magic |= (rtc_only_get_board_type() << RTC_BOARD_TYPE_SHIFT);
> +
> +	rtc32k_unlock(rtc);
> +
> +	/* write magic */
> +	writel(magic, &rtc->scratch1);
> +}
> +#endif
> +
>  /*
>   * In the case of non-SPL based booting we'll want to call these
>   * functions a tiny bit later as it will require gd to be set and cleared
> @@ -261,7 +313,9 @@ int board_early_init_f(void)
>  {
>  	prcm_init();
>  	set_mux_conf_regs();
> -
> +#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_RTC_DDR_SUPPORT)
> +	update_rtc_magic();
> +#endif
>  	return 0;
>  }
>  
> @@ -278,13 +332,7 @@ static void rtc32k_enable(void)
>  {
>  	struct davinci_rtc *rtc = (struct davinci_rtc *)RTC_BASE;
>  
> -	/*
> -	 * Unlock the RTC's registers.  For more details please see the
> -	 * RTC_SS section of the TRM.  In order to unlock we need to
> -	 * write these specific values (keys) in this order.
> -	 */
> -	writel(RTC_KICK0R_WE, &rtc->kick0r);
> -	writel(RTC_KICK1R_WE, &rtc->kick1r);
> +	rtc32k_unlock(rtc);
>  
>  	/* Enable the RTC 32K OSC by setting bits 3 and 6. */
>  	writel((1 << 3) | (1 << 6), &rtc->osc);
> @@ -321,8 +369,54 @@ static void watchdog_disable(void)
>  		;
>  }
>  
> +#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_RTC_DDR_SUPPORT)
> +/*
> + * Check if we are executing rtc-only + DDR mode, and resume from it if needed
> + */
> +static void rtc_only(void)
> +{
> +	struct davinci_rtc *rtc = (struct davinci_rtc *)RTC_BASE;
> +	u32 scratch1;
> +	void (*resume_func)(void);
> +
> +	scratch1 = readl(&rtc->scratch1);
> +
> +	/*
> +	 * Check RTC scratch against RTC_MAGIC_VAL, RTC_MAGIC_VAL is only
> +	 * written to this register when we want to wake up from RTC only
> +	 * with DDR in self-refresh mode. Contents of the RTC_SCRATCH1:
> +	 * bits 0-15:  RTC_MAGIC_VAL
> +	 * bits 16-31: board type (needed for sdram_init)
> +	 */
> +	if ((scratch1 & 0xffff) != RTC_MAGIC_VAL)
> +		return;
> +
> +	rtc32k_unlock(rtc);
> +
> +	/* Clear RTC magic */
> +	writel(0, &rtc->scratch1);
> +
> +	/*
> +	 * Update board type based on value stored on RTC_SCRATCH1, this
> +	 * is done so that we don't need to read the board type from eeprom
> +	 * over i2c bus which is expensive
> +	 */
> +	rtc_only_update_board_type(scratch1 >> RTC_BOARD_TYPE_SHIFT);
> +
> +	rtc_only_prcm_init();
> +	sdram_init();
> +
> +	resume_func = (void *)readl(&rtc->scratch0);
> +	if (resume_func)
> +		resume_func();
> +}
> +#endif
> +
>  void s_init(void)
>  {
> +#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_RTC_DDR_SUPPORT)
> +	rtc_only();
> +#endif
>  }
>  
>  void early_system_init(void)
> diff --git a/arch/arm/mach-omap2/am33xx/clock.c b/arch/arm/mach-omap2/am33xx/clock.c
> index 3d17698..ad28d20 100644
> --- a/arch/arm/mach-omap2/am33xx/clock.c
> +++ b/arch/arm/mach-omap2/am33xx/clock.c
> @@ -244,3 +244,13 @@ void prcm_init(void)
>  	scale_vcores();
>  	setup_dplls();
>  }
> +
> +void rtc_only_prcm_init(void)
> +{
> +	const struct dpll_params *params;
> +
> +	rtc_only_enable_basic_clocks();
> +
> +	params = get_dpll_ddr_params();
> +	do_setup_dpll(&dpll_ddr_regs, params);
> +}
> diff --git a/arch/arm/mach-omap2/am33xx/clock_am43xx.c b/arch/arm/mach-omap2/am33xx/clock_am43xx.c
> index 73ea955..117a63e 100644
> --- a/arch/arm/mach-omap2/am33xx/clock_am43xx.c
> +++ b/arch/arm/mach-omap2/am33xx/clock_am43xx.c
> @@ -124,6 +124,27 @@ void enable_basic_clocks(void)
>  	writel(0x4, &cmdpll->clkselmacclk);
>  }
>  
> +void rtc_only_enable_basic_clocks(void)
> +{
> +	u32 *const clk_domains[] = {
> +		&cmper->emifclkstctrl,
> +		0
> +	};
> +
> +	u32 *const clk_modules_explicit_en[] = {
> +		&cmper->gpio5clkctrl,
> +		&cmper->emiffwclkctrl,
> +		&cmper->emifclkctrl,
> +		&cmper->otfaemifclkctrl,
> +		0
> +	};
> +
> +	do_enable_clocks(clk_domains, clk_modules_explicit_en, 1);
> +
> +	/* Select the Master osc clk as Timer2 clock source */
> +	writel(0x1, &cmdpll->clktimer2clk);
> +}
> +
>  #ifdef CONFIG_TI_EDMA3
>  void enable_edma3_clocks(void)
>  {
> diff --git a/board/ti/am43xx/MAINTAINERS b/board/ti/am43xx/MAINTAINERS
> index 83645ac..bf09806 100644
> --- a/board/ti/am43xx/MAINTAINERS
> +++ b/board/ti/am43xx/MAINTAINERS
> @@ -7,4 +7,5 @@ F:	configs/am43xx_evm_defconfig
>  F:	configs/am43xx_evm_ethboot_defconfig
>  F:	configs/am43xx_evm_qspiboot_defconfig
>  F:	configs/am43xx_evm_usbhost_boot_defconfig
> +F:	configs/am43xx_evm_rtconly_defconfig
>  F:	configs/am43xx_hs_evm_defconfig
> diff --git a/board/ti/am43xx/board.c b/board/ti/am43xx/board.c
> index 715960a..d8944ea 100644
> --- a/board/ti/am43xx/board.c
> +++ b/board/ti/am43xx/board.c
> @@ -520,6 +520,62 @@ static void enable_vtt_regulator(void)
>  	writel(temp, AM33XX_GPIO5_BASE + OMAP_GPIO_OE);
>  }
>  
> +enum {
> +	RTC_BOARD_EPOS = 1,
> +	RTC_BOARD_EVM14,
> +	RTC_BOARD_EVM12,
> +	RTC_BOARD_GPEVM,
> +	RTC_BOARD_SK,
> +};
> +
> +/*
> + * In the rtc_only+DRR in self-refresh boot path we have the board type info
> + * in the rtc scratch pad register hence we bypass the costly i2c reads to
> + * eeprom and directly programthe board name string
> + */
> +void rtc_only_update_board_type(u32 btype)
> +{
> +	const char *name = "";
> +	const char *rev = "1.0";
> +
> +	switch (btype) {
> +	case RTC_BOARD_EPOS:
> +		name = "AM43EPOS";
> +		break;
> +	case RTC_BOARD_EVM14:
> +		name = "AM43__GP";
> +		rev = "1.4";
> +		break;
> +	case RTC_BOARD_EVM12:
> +		name = "AM43__GP";
> +		rev = "1.2";
> +		break;
> +	case RTC_BOARD_GPEVM:
> +		name = "AM43__GP";
> +		break;
> +	case RTC_BOARD_SK:
> +		name = "AM43__SK";
> +		break;
> +	}
> +	ti_i2c_eeprom_am_set(name, rev);
> +}
> +
> +u32 rtc_only_get_board_type(void)
> +{
> +	if (board_is_eposevm())
> +		return RTC_BOARD_EPOS;
> +	else if (board_is_evm_14_or_later())
> +		return RTC_BOARD_EVM14;
> +	else if (board_is_evm_12_or_later())
> +		return RTC_BOARD_EVM12;
> +	else if (board_is_gpevm())
> +		return RTC_BOARD_GPEVM;
> +	else if (board_is_sk())
> +		return RTC_BOARD_SK;
> +
> +	return 0;
> +}
> +
>  void sdram_init(void)
>  {
>  	/*
> diff --git a/configs/am43xx_evm_rtconly_defconfig b/configs/am43xx_evm_rtconly_defconfig
> new file mode 100644
> index 0000000..ab0be10
> --- /dev/null
> +++ b/configs/am43xx_evm_rtconly_defconfig
> @@ -0,0 +1,59 @@
> +CONFIG_ARM=y
> +CONFIG_ARCH_OMAP2PLUS=y
> +CONFIG_TI_COMMON_CMD_OPTIONS=y
> +CONFIG_SYS_MALLOC_F_LEN=0x2000
> +CONFIG_AM43XX=y
> +CONFIG_DEFAULT_DEVICE_TREE="am437x-gp-evm"
> +CONFIG_DISTRO_DEFAULTS=y
> +CONFIG_SPL_LOAD_FIT=y
> +CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=1"
> +# CONFIG_USE_BOOTCOMMAND is not set
> +CONFIG_SYS_CONSOLE_INFO_QUIET=y
> +CONFIG_VERSION_VARIABLE=y
> +CONFIG_SPL=y
> +CONFIG_SPL_RTC_DDR_SUPPORT=y
> +CONFIG_SPL_MTD_SUPPORT=y
> +CONFIG_SPL_OS_BOOT=y
> +CONFIG_CMD_SPL=y
> +CONFIG_CMD_SPL_NAND_OFS=0x00100000
> +CONFIG_CMD_SPL_WRITE_SIZE=0x40000
> +# CONFIG_CMD_FLASH is not set
> +CONFIG_CMD_NAND=y
> +# CONFIG_CMD_SETEXPR is not set
> +CONFIG_CMD_MTDPARTS=y
> +CONFIG_MTDIDS_DEFAULT="nand0=nand.0"
> +CONFIG_MTDPARTS_DEFAULT="mtdparts=nand.0:256k(NAND.SPL),256k(NAND.SPL.backup1),256k(NAND.SPL.backup2),256k(NAND.SPL.backup3),512k(NAND.u-boot-spl-os),1m(NAND.u-boot),256k(NAND.u-boot-env),256k(NAND.u-boot-env.backup1),7m(NAND.kernel),-(NAND.file-system)"
> +CONFIG_OF_CONTROL=y
> +CONFIG_OF_LIST="am437x-gp-evm am437x-sk-evm am43x-epos-evm am437x-idk-evm"
> +CONFIG_DM=y
> +# CONFIG_BLK is not set
> +CONFIG_DFU_MMC=y
> +CONFIG_DFU_RAM=y
> +CONFIG_DFU_SF=y
> +CONFIG_DM_GPIO=y
> +CONFIG_DM_MMC=y
> +CONFIG_MMC_OMAP_HS=y
> +CONFIG_NAND=y
> +CONFIG_SPI_FLASH=y
> +CONFIG_SPI_FLASH_MACRONIX=y
> +CONFIG_PHYLIB=y
> +CONFIG_PHY_GIGE=y
> +CONFIG_DM_SERIAL=y
> +CONFIG_SYS_NS16550=y
> +CONFIG_TI_QSPI=y
> +CONFIG_TIMER=y
> +CONFIG_OMAP_TIMER=y
> +CONFIG_USB=y
> +CONFIG_USB_XHCI_HCD=y
> +CONFIG_USB_XHCI_DWC3=y
> +CONFIG_USB_DWC3=y
> +CONFIG_USB_DWC3_GADGET=y
> +CONFIG_USB_DWC3_OMAP=y
> +CONFIG_USB_DWC3_PHY_OMAP=y
> +CONFIG_OMAP_USB_PHY=y
> +CONFIG_USB_STORAGE=y
> +CONFIG_USB_GADGET=y
> +CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
> +CONFIG_USB_GADGET_VENDOR_NUM=0x0403
> +CONFIG_USB_GADGET_PRODUCT_NUM=0xbd00
> +CONFIG_USB_GADGET_DOWNLOAD=y
> 


More information about the U-Boot mailing list