/* mbed Microcontroller Library * Copyright (c) 2018-2020 ARM Limited * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "sleep_api.h" #include "cmsis.h" #include "mbed_interface.h" #include "mbed_critical.h" #include "iodefine.h" #if DEVICE_SLEEP static volatile uint8_t wk_CPGSTBCR3; static volatile uint8_t wk_CPGSTBCR4; static volatile uint8_t wk_CPGSTBCR5; static volatile uint8_t wk_CPGSTBCR6; static volatile uint8_t wk_CPGSTBCR7; static volatile uint8_t wk_CPGSTBCR8; static volatile uint8_t wk_CPGSTBCR9; static volatile uint8_t wk_CPGSTBCR10; typedef struct { volatile uint8_t * p_wk_stbcr; volatile uint8_t * p_stbcr; volatile uint8_t * p_stbreq; volatile uint8_t * p_stback; uint8_t mstp; uint8_t stbrq; } module_stanby_t; static const module_stanby_t module_stanby[] = { {&wk_CPGSTBCR5, &CPG.STBCR5.BYTE, &CPG.STBREQ1.BYTE, &CPG.STBACK1.BYTE, 0x40, 0x01}, /* CEU */ {&wk_CPGSTBCR5, &CPG.STBCR5.BYTE, &CPG.STBREQ1.BYTE, &CPG.STBACK1.BYTE, 0x02, 0x08}, /* JCU */ {&wk_CPGSTBCR6, &CPG.STBCR6.BYTE, &CPG.STBREQ2.BYTE, &CPG.STBACK2.BYTE, 0x40, 0x80}, /* VIN */ {&wk_CPGSTBCR6, &CPG.STBCR6.BYTE, &CPG.STBREQ2.BYTE, &CPG.STBACK2.BYTE, 0x20, 0x40}, /* ethernet0 */ {&wk_CPGSTBCR6, &CPG.STBCR6.BYTE, &CPG.STBREQ2.BYTE, &CPG.STBACK2.BYTE, 0x10, 0x40}, /* ethernet1 */ {&wk_CPGSTBCR6, &CPG.STBCR6.BYTE, &CPG.STBREQ2.BYTE, &CPG.STBACK2.BYTE, 0x08, 0x40}, /* ethernet PTP */ {&wk_CPGSTBCR6, &CPG.STBCR6.BYTE, &CPG.STBREQ2.BYTE, &CPG.STBACK2.BYTE, 0x04, 0x40}, /* ethernet M */ {&wk_CPGSTBCR6, &CPG.STBCR6.BYTE, &CPG.STBREQ3.BYTE, &CPG.STBACK3.BYTE, 0x02, 0x03}, /* USB host 0 */ {&wk_CPGSTBCR6, &CPG.STBCR6.BYTE, &CPG.STBREQ3.BYTE, &CPG.STBACK3.BYTE, 0x01, 0x0C}, /* USB host 1 */ {&wk_CPGSTBCR7, &CPG.STBCR7.BYTE, &CPG.STBREQ2.BYTE, &CPG.STBACK2.BYTE, 0x80, 0x08}, /* IMR */ {&wk_CPGSTBCR7, &CPG.STBCR7.BYTE, &CPG.STBREQ2.BYTE, &CPG.STBACK2.BYTE, 0x40, 0x03}, /* DAVE-2D */ {&wk_CPGSTBCR8, &CPG.STBCR8.BYTE, &CPG.STBREQ2.BYTE, &CPG.STBACK2.BYTE, 0x02, 0x20}, /* VDC-6 */ {&wk_CPGSTBCR9, &CPG.STBCR9.BYTE, &CPG.STBREQ2.BYTE, &CPG.STBACK2.BYTE, 0x01, 0x10}, /* DRP */ {&wk_CPGSTBCR10, &CPG.STBCR10.BYTE, &CPG.STBREQ2.BYTE, &CPG.STBACK2.BYTE, 0x10, 0x04}, /* NAND */ {&wk_CPGSTBCR10, &CPG.STBCR10.BYTE, &CPG.STBREQ3.BYTE, &CPG.STBACK3.BYTE, 0x08, 0x04}, /* SD host 0 */ {&wk_CPGSTBCR10, &CPG.STBCR10.BYTE, &CPG.STBREQ3.BYTE, &CPG.STBACK3.BYTE, 0x02, 0x02}, /* SD host 1 */ {0, 0, 0, 0, 0} /* None */ }; static void module_standby_in(void) { volatile uint32_t cnt; volatile uint8_t dummy_8; const module_stanby_t * p_module = &module_stanby[0]; while (p_module->p_wk_stbcr != 0) { if ((*p_module->p_wk_stbcr & p_module->mstp) == 0) { *p_module->p_stbreq |= p_module->stbrq; dummy_8 = *p_module->p_stbreq; for (cnt = 0; cnt < 1000; cnt++) { // wait time if ((*p_module->p_stback & p_module->stbrq) == p_module->stbrq) { break; } } *p_module->p_stbcr |= p_module->mstp; dummy_8 = *p_module->p_stbcr; } p_module++; } (void)dummy_8; } static void module_standby_out(void) { volatile uint32_t cnt; volatile uint8_t dummy_8; const module_stanby_t * p_module = &module_stanby[0]; while (p_module->p_wk_stbcr != 0) { if ((*p_module->p_wk_stbcr & p_module->mstp) == 0) { *p_module->p_stbreq &= ~(p_module->stbrq); dummy_8 = *p_module->p_stbreq; for (cnt = 0; cnt < 1000; cnt++) { if ((*p_module->p_stback & p_module->stbrq) == 0) { break; } } } p_module++; } (void)dummy_8; } void hal_sleep(void) { // Transition to Sleep Mode __WFI(); } void hal_deepsleep(void) { volatile uint8_t dummy_8; core_util_critical_section_enter(); /* For powerdown the peripheral module, save current standby control register values(just in case) */ wk_CPGSTBCR3 = CPG.STBCR3.BYTE; wk_CPGSTBCR4 = CPG.STBCR4.BYTE; wk_CPGSTBCR5 = CPG.STBCR5.BYTE; wk_CPGSTBCR6 = CPG.STBCR6.BYTE; wk_CPGSTBCR7 = CPG.STBCR7.BYTE; wk_CPGSTBCR8 = CPG.STBCR8.BYTE; wk_CPGSTBCR9 = CPG.STBCR9.BYTE; wk_CPGSTBCR10 = CPG.STBCR10.BYTE; /* non */ CPG.STBCR3.BYTE = 0xFF; dummy_8 = CPG.STBCR3.BYTE; /* non */ CPG.STBCR4.BYTE = 0xFF; dummy_8 = CPG.STBCR4.BYTE; /* Realtime Clock, CEU, JCU */ CPG.STBCR5.BYTE |= ~(0x4A); dummy_8 = CPG.STBCR5.BYTE; /* VIN, ethernet0, ethernet1, ethernet PTP, ethernet M, USB host 0, USB host 1 */ CPG.STBCR6.BYTE |= ~(0x7F); dummy_8 = CPG.STBCR6.BYTE; /* IMR, DAVE-2D */ CPG.STBCR7.BYTE |= ~(0xC0); dummy_8 = CPG.STBCR7.BYTE; /* VDC-6 */ CPG.STBCR8.BYTE |= ~(0x02); dummy_8 = CPG.STBCR8.BYTE; /* DRP */ CPG.STBCR9.BYTE |= ~(0x01); dummy_8 = CPG.STBCR9.BYTE; /* NAND, SD host 0, SD host 1 */ CPG.STBCR10.BYTE |= ~(0x1A); dummy_8 = CPG.STBCR10.BYTE; module_standby_in(); // Transition to Sleep Mode __WFI(); /* Revert standby control register values */ CPG.STBCR3.BYTE = wk_CPGSTBCR3; dummy_8 = CPG.STBCR3.BYTE; CPG.STBCR4.BYTE = wk_CPGSTBCR4; dummy_8 = CPG.STBCR4.BYTE; CPG.STBCR5.BYTE = wk_CPGSTBCR5; dummy_8 = CPG.STBCR5.BYTE; CPG.STBCR6.BYTE = wk_CPGSTBCR6; dummy_8 = CPG.STBCR6.BYTE; CPG.STBCR7.BYTE = wk_CPGSTBCR7; dummy_8 = CPG.STBCR7.BYTE; CPG.STBCR8.BYTE = wk_CPGSTBCR8; dummy_8 = CPG.STBCR8.BYTE; CPG.STBCR9.BYTE = wk_CPGSTBCR9; dummy_8 = CPG.STBCR9.BYTE; CPG.STBCR10.BYTE = wk_CPGSTBCR10; dummy_8 = CPG.STBCR10.BYTE; module_standby_out(); core_util_critical_section_exit(); (void)dummy_8; } #endif