File indexing completed on 2025-05-11 08:22:48
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #include <bsp/power.h>
0029 #include <bsp/linker-symbols.h>
0030
0031 #include <libchip/chip.h>
0032
0033 BSP_FAST_TEXT_SECTION static void
0034 pmc_wait_for_master_clock_ready(volatile Pmc *pmc)
0035 {
0036 while ((pmc->PMC_SR & PMC_SR_MCKRDY) == 0) {
0037
0038 }
0039 }
0040
0041 BSP_FAST_TEXT_SECTION static void
0042 pmc_set_master_clock_source(volatile Pmc *pmc, uint32_t mckr)
0043 {
0044 pmc->PMC_MCKR =
0045 (pmc->PMC_MCKR & ~PMC_MCKR_CSS_Msk) | (mckr & PMC_MCKR_CSS_Msk);
0046 }
0047
0048 BSP_FAST_TEXT_SECTION static void
0049 pmc_set_master_clock_prescaler(volatile Pmc *pmc, uint32_t mckr)
0050 {
0051 pmc->PMC_MCKR =
0052 (pmc->PMC_MCKR & ~PMC_MCKR_PRES_Msk) | (mckr & PMC_MCKR_PRES_Msk);
0053 }
0054
0055 BSP_FAST_TEXT_SECTION static void
0056 pmc_set_master_clock_division(volatile Pmc *pmc, uint32_t mckr)
0057 {
0058 pmc->PMC_MCKR =
0059 (pmc->PMC_MCKR & ~PMC_MCKR_MDIV_Msk) | (mckr & PMC_MCKR_MDIV_Msk);
0060 }
0061
0062 BSP_FAST_TEXT_SECTION static void
0063 pmc_wait_for_main_rc_osc(volatile Pmc *pmc)
0064 {
0065 while ((pmc->PMC_SR & PMC_SR_MOSCRCS) == 0) {
0066
0067 }
0068 }
0069
0070 BSP_FAST_TEXT_SECTION static void
0071 pmc_wait_for_main_osc_selection(volatile Pmc *pmc)
0072 {
0073 while ((pmc->PMC_SR & PMC_SR_MOSCSELS) == 0) {
0074
0075 }
0076 }
0077
0078 BSP_FAST_TEXT_SECTION static void
0079 pmc_use_main_rc_osc_4mhz(volatile Pmc *pmc)
0080 {
0081 uint32_t ckgr_mor;
0082
0083 ckgr_mor = pmc->CKGR_MOR;
0084 ckgr_mor |= CKGR_MOR_KEY_PASSWD;
0085
0086
0087 ckgr_mor |= CKGR_MOR_MOSCRCEN;
0088 PMC->CKGR_MOR = ckgr_mor;
0089 pmc_wait_for_main_rc_osc(pmc);
0090
0091
0092 ckgr_mor &= ~CKGR_MOR_MOSCRCF_Msk;
0093 ckgr_mor |= CKGR_MOR_MOSCRCF_4_MHz;
0094 pmc->CKGR_MOR = ckgr_mor;
0095 pmc_wait_for_main_rc_osc(pmc);
0096
0097
0098 ckgr_mor &= ~CKGR_MOR_MOSCSEL;
0099 pmc->CKGR_MOR = ckgr_mor;
0100 pmc_wait_for_main_osc_selection(pmc);
0101 pmc_wait_for_master_clock_ready(pmc);
0102 }
0103
0104 BSP_FAST_TEXT_SECTION static void
0105 pmc_use_main_ext_osc(volatile Pmc *pmc)
0106 {
0107 uint32_t ckgr_mor;
0108
0109 ckgr_mor = pmc->CKGR_MOR;
0110 ckgr_mor |= CKGR_MOR_KEY_PASSWD;
0111
0112
0113 ckgr_mor |= CKGR_MOR_MOSCRCF_12_MHz | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCRCEN |
0114 CKGR_MOR_MOSCXTST(DEFAUTL_MAIN_OSC_COUNT);
0115 PMC->CKGR_MOR = ckgr_mor;
0116 pmc_wait_for_main_rc_osc(pmc);
0117 pmc_wait_for_master_clock_ready(pmc);
0118
0119
0120 ckgr_mor |= CKGR_MOR_MOSCSEL;
0121 pmc->CKGR_MOR = ckgr_mor;
0122 pmc_wait_for_main_osc_selection(pmc);
0123 pmc_wait_for_master_clock_ready(pmc);
0124 }
0125
0126 BSP_FAST_TEXT_SECTION void
0127 atsam_power_handler_wait_mode(
0128 const atsam_power_control *control,
0129 atsam_power_state state
0130 )
0131 {
0132 rtems_interrupt_level level;
0133 volatile Pmc *pmc;
0134 uint32_t mckr;
0135 uint32_t fmr;
0136 uint32_t fsmr;
0137
0138 (void) control;
0139 pmc = PMC;
0140
0141 switch (state) {
0142 case ATSAM_POWER_OFF:
0143 rtems_interrupt_disable(level);
0144
0145 mckr = pmc->PMC_MCKR;
0146
0147
0148 pmc_use_main_rc_osc_4mhz(pmc);
0149 pmc_set_master_clock_source(pmc, PMC_MCKR_CSS_MAIN_CLK);
0150 pmc_wait_for_master_clock_ready(pmc);
0151 pmc_set_master_clock_prescaler(pmc, PMC_MCKR_PRES_CLK_1);
0152 pmc_wait_for_master_clock_ready(pmc);
0153 pmc_set_master_clock_division(pmc, PMC_MCKR_MDIV_EQ_PCK);
0154 pmc_wait_for_master_clock_ready(pmc);
0155
0156
0157 fmr = EFC->EEFC_FMR;
0158 EFC->EEFC_FMR = EEFC_FMR_FWS(0);
0159
0160
0161 fsmr = pmc->PMC_FSMR;
0162 pmc->PMC_FSMR = fsmr | PMC_FSMR_LPM;
0163 pmc->CKGR_MOR = CKGR_MOR_KEY_PASSWD | CKGR_MOR_WAITMODE;
0164 pmc_wait_for_master_clock_ready(pmc);
0165 __asm__ volatile ( "wfe" : : : "memory" );
0166 pmc->PMC_FSMR = fsmr;
0167
0168
0169 pmc_set_master_clock_prescaler(pmc, mckr);
0170 pmc_wait_for_master_clock_ready(pmc);
0171 pmc_set_master_clock_division(pmc, mckr);
0172 pmc_wait_for_master_clock_ready(pmc);
0173 pmc_set_master_clock_source(pmc, mckr);
0174 pmc_wait_for_master_clock_ready(pmc);
0175 pmc_use_main_ext_osc(pmc);
0176
0177
0178 EFC->EEFC_FMR = fmr;
0179
0180 rtems_interrupt_enable(level);
0181 break;
0182 case ATSAM_POWER_INIT:
0183 rtems_interrupt_disable(level);
0184
0185 pmc->PMC_FSMR = (pmc->PMC_FSMR & ~PMC_FSMR_FLPM_Msk)
0186 | PMC_FSMR_FLPM(PMC_FSMR_FLPM_FLASH_DEEP_POWERDOWN);
0187
0188
0189 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
0190
0191 rtems_interrupt_enable(level);
0192 default:
0193 break;
0194 }
0195 }