ARM: at91: pm: add ULP1 support for SAM9X60
authorClaudiu Beznea <claudiu.beznea@microchip.com>
Thu, 14 Feb 2019 15:54:57 +0000 (15:54 +0000)
committerLudovic Desroches <ludovic.desroches@microchip.com>
Thu, 28 Mar 2019 10:05:53 +0000 (11:05 +0100)
Add ULP1 support for SAM9X60. In pm_suspend.S enable RC oscillator in
PMC if it is not enabled. At resume the state before suspend is
restored.

Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
Acked-by: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Ludovic Desroches <ludovic.desroches@microchip.com>
arch/arm/mach-at91/pm.c
arch/arm/mach-at91/pm_suspend.S
include/linux/clk/at91_pmc.h

index 27264caa4ec64255c42460f5b207b3a57988078c..5571658b3c46760cda4c656fd6662e17709ef51f 100644 (file)
@@ -100,6 +100,8 @@ static const struct wakeup_source_info ws_info[] = {
        { .pmc_fsmr_bit = AT91_PMC_RTCAL,       .shdwc_mr_bit = BIT(17) },
        { .pmc_fsmr_bit = AT91_PMC_USBAL },
        { .pmc_fsmr_bit = AT91_PMC_SDMMC_CD },
+       { .pmc_fsmr_bit = AT91_PMC_RTTAL },
+       { .pmc_fsmr_bit = AT91_PMC_RXLP_MCE },
 };
 
 static const struct of_device_id sama5d2_ws_ids[] = {
@@ -114,6 +116,17 @@ static const struct of_device_id sama5d2_ws_ids[] = {
        { /* sentinel */ }
 };
 
+static const struct of_device_id sam9x60_ws_ids[] = {
+       { .compatible = "atmel,at91sam9x5-rtc",         .data = &ws_info[1] },
+       { .compatible = "atmel,at91rm9200-ohci",        .data = &ws_info[2] },
+       { .compatible = "usb-ohci",                     .data = &ws_info[2] },
+       { .compatible = "atmel,at91sam9g45-ehci",       .data = &ws_info[2] },
+       { .compatible = "usb-ehci",                     .data = &ws_info[2] },
+       { .compatible = "atmel,at91sam9260-rtt",        .data = &ws_info[4] },
+       { .compatible = "cdns,sam9x60-macb",            .data = &ws_info[5] },
+       { /* sentinel */ }
+};
+
 static int at91_pm_config_ws(unsigned int pm_mode, bool set)
 {
        const struct wakeup_source_info *wsi;
@@ -192,6 +205,13 @@ static int at91_sama5d2_config_pmc_ws(void __iomem *pmc, u32 mode, u32 polarity)
        return 0;
 }
 
+static int at91_sam9x60_config_pmc_ws(void __iomem *pmc, u32 mode, u32 polarity)
+{
+       writel(mode, pmc + AT91_PMC_FSMR);
+
+       return 0;
+}
+
 /*
  * Called after processes are frozen, but before we shutdown devices.
  */
@@ -789,8 +809,12 @@ void __init sam9x60_pm_init(void)
        if (!IS_ENABLED(CONFIG_SOC_AT91SAM9))
                return;
 
+       at91_pm_modes_init();
        at91_dt_ramc();
        at91_pm_init(at91sam9x60_idle);
+
+       soc_pm.ws_ids = sam9x60_ws_ids;
+       soc_pm.config_pmc_ws = at91_sam9x60_config_pmc_ws;
 }
 
 void __init at91sam9_pm_init(void)
index bfe1c4d0690108bce0a250eca54c81e01e7f49fb..8b18cad1dcf51be28cdf153725fe43ddfa0988df 100644 (file)
@@ -197,8 +197,26 @@ ENDPROC(at91_backup_mode)
 .macro at91_pm_ulp1_mode
        ldr     pmc, .pmc_base
 
-       /* Switch the main clock source to 12-MHz RC oscillator */
+       /* Save RC oscillator state and check if it is enabled. */
+       ldr     tmp1, [pmc, #AT91_PMC_SR]
+       str     tmp1, .saved_osc_status
+       tst     tmp1, #AT91_PMC_MOSCRCS
+       bne     2f
+
+       /* Enable RC oscillator */
        ldr     tmp1, [pmc, #AT91_CKGR_MOR]
+       orr     tmp1, tmp1, #AT91_PMC_MOSCRCEN
+       bic     tmp1, tmp1, #AT91_PMC_KEY_MASK
+       orr     tmp1, tmp1, #AT91_PMC_KEY
+       str     tmp1, [pmc, #AT91_CKGR_MOR]
+
+       /* Wait main RC stabilization */
+1:     ldr     tmp1, [pmc, #AT91_PMC_SR]
+       tst     tmp1, #AT91_PMC_MOSCRCS
+       beq     1b
+
+       /* Switch the main clock source to 12-MHz RC oscillator */
+2:     ldr     tmp1, [pmc, #AT91_CKGR_MOR]
        bic     tmp1, tmp1, #AT91_PMC_MOSCSEL
        bic     tmp1, tmp1, #AT91_PMC_KEY_MASK
        orr     tmp1, tmp1, #AT91_PMC_KEY
@@ -262,6 +280,25 @@ ENDPROC(at91_backup_mode)
        str     tmp1, [pmc, #AT91_PMC_MCKR]
 
        wait_mckrdy
+
+       /* Restore RC oscillator state */
+       ldr     tmp1, .saved_osc_status
+       tst     tmp1, #AT91_PMC_MOSCRCS
+       bne     3f
+
+       /* Disable RC oscillator */
+       ldr     tmp1, [pmc, #AT91_CKGR_MOR]
+       bic     tmp1, tmp1, #AT91_PMC_MOSCRCEN
+       bic     tmp1, tmp1, #AT91_PMC_KEY_MASK
+       orr     tmp1, tmp1, #AT91_PMC_KEY
+       str     tmp1, [pmc, #AT91_CKGR_MOR]
+
+       /* Wait RC oscillator disable done */
+4:     ldr     tmp1, [pmc, #AT91_PMC_SR]
+       tst     tmp1, #AT91_PMC_MOSCRCS
+       bne     4b
+
+3:
 .endm
 
 ENTRY(at91_ulp_mode)
@@ -475,6 +512,8 @@ ENDPROC(at91_sramc_self_refresh)
        .word 0
 .saved_sam9_mdr1:
        .word 0
+.saved_osc_status:
+       .word 0
 
 ENTRY(at91_pm_suspend_in_sram_sz)
        .word .-at91_pm_suspend_in_sram
index 931ab05f771d66046fcd566f713bbeaf25139b50..bd3a65c0bad38a18507abb7b79a978bca27248c2 100644 (file)
 
 #define AT91_PMC_FSMR          0x70            /* Fast Startup Mode Register */
 #define AT91_PMC_FSTT(n)       BIT(n)
+#define AT91_PMC_RTTAL         BIT(16)
 #define AT91_PMC_RTCAL         BIT(17)         /* RTC Alarm Enable */
 #define AT91_PMC_USBAL         BIT(18)         /* USB Resume Enable */
 #define AT91_PMC_SDMMC_CD      BIT(19)         /* SDMMC Card Detect Enable */