@@ -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);
@@ -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
@@ -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)
@@ -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);
+}
@@ -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)
{
@@ -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
@@ -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)
{
/*
new file mode 100644
@@ -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