[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