/* * @File name : driver_clk.c * @Author : Bluetrum IOT Team * @Date : 2023-04-04 * @Description : This file provides functions to manage the most functionalities * of the CLK peripheral. * * Copyright (c) by Bluetrum, All Rights Reserved. */ #include "driver_clk.h" void clk_gate0_cmd(uint32_t clock_gate, CLK_STATE state) { if (state != CLK_DIS) { CLKGAT0 |= clock_gate; } else { CLKGAT0 &= ~clock_gate; } } void clk_gate1_cmd(uint32_t clock_gate, CLK_STATE state) { if (state != CLK_DIS) { CLKGAT1 |= clock_gate; } else { CLKGAT1 &= ~clock_gate; } } void clk_gate2_cmd(uint32_t clock_gate, CLK_STATE state) { if (state != CLK_DIS) { CLKGAT2 |= clock_gate; } else { CLKGAT2 &= ~clock_gate; } } void clk_clkout_set(CLK_CLKOUT_TYPEDEF clk_sel, uint8_t div, CLK_STATE state) { if (state != CLK_DIS) { CLKCON0 &= ~(0x0f << 13); CLKCON0 |= ((clk_sel & 0x0f) << 13); CLKDIVCON0 &= ~(0x1f << 17); CLKDIVCON0 |= ((div & 0x1f) << 17); } else { CLKCON0 &= ~(0x0f << 13); CLKDIVCON0 &= ~(0x1f << 17); } } void clk_clk32k_rtc_set(CLK_CLK32K_RTC_TYPEDEF clk_sel) { uint32_t rtccon0 = RTCCON0; if ((CLK_CLK32K_RTC_RC2M_RTC == clk_sel) || (CLK_CLK32K_RTC_SNF_RC_RTC == clk_sel)) { rtccon0 |= BIT(19); //RC2M_RTC enable } rtccon0 &= ~(0x03 << 8); rtccon0 |= ((clk_sel & 0x03) << 8); RTCCON0 = rtccon0; } uint32_t clk_clk32k_rtc_get(CLK_VALUE_MODE_TYPEDEF mode) { uint32_t rtccon0 = RTCCON0; u8 index; index = (rtccon0 >> 8) & 0x03; if (mode == CLK_VALUE_MODE_IDX) { return index; } else { switch (index) { case CLK_CLK32K_RTC_1BIT: return -1L; case CLK_CLK32K_RTC_RC2M_RTC: case CLK_CLK32K_RTC_SNF_RC_RTC: return rc2m_clk_nhz_get(1) / 64; case CLK_CLK32K_RTC_X24MDIV12_RTC: return 2000000 / 64; default: return 0; } } } void clk_hsut0_clk_set(CLK_HSUART_CLK_TYPEDEF clk_sel, uint8_t div) { uint32_t clkcon0 = CLKCON0; clkcon0 &= ~(0x03 << 17); clkcon0 |= ((clk_sel & 0x03) << 17); CLKCON0 = clkcon0; if (clk_sel >= CLK_HSUT0_CLK_PLLDIV2_CLK) { CLKDIVCON0 &= ~(0x03 << 22); CLKDIVCON0 |= ((div & 0x03) << 22); PLL0CON |= BIT(13); } } uint32_t clk_hsut0_clk_get(CLK_VALUE_MODE_TYPEDEF mode) { uint32_t clkcon0 = CLKCON0; u8 index; index = ((clkcon0 >> 17) & 0x03); if (mode == CLK_VALUE_MODE_IDX) { return index; } else { switch (index) { case CLK_HSUT0_CLK_XOSC24M_CLK: return 24000000; case CLK_HSUT0_CLK_XOSC48M: return 48000000; case CLK_HSUT0_CLK_PLLDIV2_CLK: return pll_clk_nhz_get() / 2 / (((CLKDIVCON0 >> 22) & 0x03) + 1); case CLK_HSUT0_CLK_UDET_CLKPP: return clk_udet_clk_get(CLK_VALUE_MODE_FREQ) / (((CLKDIVCON0 >> 22) & 0x03) + 1); default: return 0; } } } void clk_saradc_clk_set(CLK_SARADC_CLK_TYPEDEF clk_sel) { uint32_t clkcon0 = CLKCON0; clkcon0 &= ~(0x03 << 28); clkcon0 |= ((clk_sel & 0x03) << 28); CLKCON0 = clkcon0; } uint32_t clk_saradc_clk_get(CLK_VALUE_MODE_TYPEDEF mode) { uint32_t clkcon0 = CLKCON0; u8 index; index = ((clkcon0 >> 28) & 0x03); if (mode == CLK_VALUE_MODE_IDX) { return index; } else { switch (index) { case CLK_SARADC_CLK_RC2M_CLK: return rc2m_clk_nhz_get(0); case CLK_SARADC_CLK_X24M_CLKDIV4: return 6000000; case CLK_SARADC_CLK_X24M_CLKDIV2: return 12000000; case CLK_SARADC_CLK_X24Md32K_CLK: return 32000; default: return 0; } } } void clk_udet_clk_set(CLK_UDET_CLK_TYPEDEF clk_sel) { uint32_t clkcon1 = CLKCON1; clkcon1 &= ~(0x03 << 28); clkcon1 |= ((clk_sel & 0x03) << 28); CLKCON1 = clkcon1; } uint32_t clk_udet_clk_get(CLK_VALUE_MODE_TYPEDEF mode) { uint32_t clkcon1 = CLKCON1; u8 index; index = ((clkcon1 >> 28) & 0x03); if (mode == CLK_VALUE_MODE_IDX) { return index; } else { switch (index) { case CLK_UDET_CLK_RC2M_CLK: return rc2m_clk_nhz_get(0); case CLK_UDET_CLK_RTC_RC2M: return rc2m_clk_nhz_get(1); case XOSC24M_CLK: return 24000000; case XOSC48M: return 48000000; default: return 0; } } } void clk_tmr_inc_set(CLK_TMR_INC_TYPEDEF clk_sel) { uint32_t clkcon0 = CLKCON0; clkcon0 &= ~(0x03 << 23); clkcon0 |= ((clk_sel & 0x03) << 23); CLKCON0 = clkcon0; } uint32_t clk_tmr_inc_get(CLK_VALUE_MODE_TYPEDEF mode) { uint32_t clkcon0 = CLKCON0; u8 index; index = (clkcon0 >> 23) & 0x03; if (mode == CLK_VALUE_MODE_IDX) { return index; } else { switch (index) { case CLK_TMR_INC_OSC32K: return clk_clk32k_rtc_get(CLK_VALUE_MODE_FREQ); case CLK_TMR_INC_CLKOUOT_PIN: return -1L; case CLK_TMR_INC_X24M_DIV_CLK: return 24000000 / (((CLKDIVCON0 >> 24) & 0xff) + 1); case CLK_TMR_INC_RC2M_D0: return rc2m_clk_nhz_get(0) / 2; default: return 0; } } } void clk_uart_inc_set(CLK_UART_INC_TPYEDEF clk_sel) { uint32_t clkcon1 = CLKCON1; clkcon1 &= ~(0x01 << 14); clkcon1 |= ((clk_sel & 0x01) << 14); CLKCON1 = clkcon1; } uint32_t clk_uart_inc_get(CLK_VALUE_MODE_TYPEDEF mode) { uint32_t clkcon1 = CLKCON1; u8 index; index = (clkcon1 >> 14) & 0x01; if (mode == CLK_VALUE_MODE_IDX) { return index; } else { switch (index) { case CLK_UART_INC_X24M_DIV_CLK: return 24000000 / (((CLKDIVCON0 >> 24) & 0xff) + 1); case CLK_UART_INC_X24M_CLKDIV4: return 6000000; default: return 0; } } } void clk_clk2m_ks_set(CLK_CLK2M_KS_TYPEDEF clk_sel) { uint32_t rtccon0 = RTCCON0; rtccon0 &= ~(0x03 << 14); rtccon0 |= ((clk_sel & 0x03) << 14); RTCCON0 = rtccon0; } uint32_t clk_clk2m_ks_get(CLK_VALUE_MODE_TYPEDEF mode) { uint32_t rtccon0 = RTCCON0; u8 index; index = (rtccon0 >> 14) & 0x03; if (mode == CLK_VALUE_MODE_IDX) { return index; } else { switch (index) { case CLK_CLK2M_KS_1BIT: return -1L; case CLK_CLK2M_KS_RC2M_RTC: return rc2m_clk_nhz_get(1); case CLK_CLK2M_KS_SNF_RC_RTC: return rc2m_clk_nhz_get(1); case CLK_CLK2M_KS_X24MDIV12_RTC: return 2000000; default: return 0; } } } void clk_sdadda_clk_set(CLK_SDADDA_CLK_TYPEDEF clk_sel, uint8_t div) { u32 clkcon1 = CLKCON1; u32 clkdivcon0 = CLKDIVCON0; if (clk_sel == 4 || clk_sel > 5) { return; } clkcon1 &= ~0x07; clkcon1 |= clk_sel; CLKCON1 = clkcon1; if (clk_sel == CLK_SDADDA_CLK_ADDA_CLK24_A) { CLKGAT2 |= BIT(14); clkdivcon0 &= ~(0x0f << 4); clkdivcon0 |= ((div & 0x0f) << 4); CLKDIVCON0 = clkdivcon0; } } uint32_t clk_sdadda_clk_get(CLK_VALUE_MODE_TYPEDEF mode) { u32 clkcon1 = CLKCON1; u8 div = ((CLKDIVCON0 >> 4) & 0x0f) + 1; u8 index; index = clkcon1 & 0x07; if (mode == CLK_VALUE_MODE_IDX) { return index; } else { switch (index) { case CLK_SDADDA_CLK_ADDA_CLK24_A: return (pll_clk_nhz_get() / 2 / div / 2); case CLK_SDADDA_CLK_XOSC24M_CLK: return 24000000; case CLK_SDADDA_CLK_XOSC24M_CLK_2PLL: return 24000000; default: return 0; } } } void clk_ledc_clk_set(CLK_LEDC_CLK_TYPEDEF clk_sel) { u32 clkcon1 = CLKCON1; clkcon1 &= ~(0x01 << 27); clkcon1 |= (clk_sel & 0x01) << 27; CLKCON1 = clkcon1; } uint32_t clk_ledc_clk_get(CLK_VALUE_MODE_TYPEDEF mode) { u32 clkcon1 = CLKCON1; u8 index; index = (clkcon1 >> 27) & 0x01; if (mode == CLK_VALUE_MODE_IDX) { return index; } else { switch (index) { case CLK_LEDC_CLK_XOSC24M: return 24000000; case CLK_LEDC_CLK_X24M_CLKDIV2: return 12000000; default: return 0; } } } void clk_touch_key_clk_set(CLK_TOUCH_KEY_TYPEDEF clk_sel) { if (CLK_TOUCH_KEY_CLK_XOSC24M == clk_sel) { XOSCCON |= BIT(10); //xosc enable CLKCON4 &= ~BIT(26); //select xosc24m_p CLKGAT1 |= BIT(29); //x24m_clk enable } else if (CLK_TOUCH_KEY_RC2M == clk_sel) { RTCCON0 |= BIT(19); //RC2M_RTC EN } RTCCON0 = (RTCCON0 & ~(3 << 12)) | (clk_sel << 12); RTCCON &= ~BIT(0); //VRTC11 voltage select RTCCON4 bit26~24 RTCCON4 = (RTCCON4 & ~(0x07 << 24)) | (5 << 24); //vrtc11 voltage select 0.7+0.065*5 = 1.025V } uint32_t clk_touch_key_clk_get(CLK_VALUE_MODE_TYPEDEF mode) { u32 rtccon0 = RTCCON0; u8 index; index = (rtccon0 >> 12) & 0x03; if (mode == CLK_VALUE_MODE_IDX) { return index; } else { switch (index) { case CLK_TOUCH_KEY_RC2M: return rc2m_clk_nhz_get(1); case CLK_TOUCH_KEY_CLK_XOSC24M: return 2000000; default: return 0; } } } void clk_ttmr_inc_set(CLK_TTMR_INC_TYPEDEF clk_sel) { uint32_t clkcon1 = CLKCON1; clkcon1 &= ~(0x03 << 12); clkcon1 |= ((clk_sel & 0x03) << 12); CLKCON1 = clkcon1; } uint32_t clk_ttmr_inc_get(CLK_VALUE_MODE_TYPEDEF mode) { uint32_t clkcon1 = CLKCON1; uint8_t index; index = (clkcon1 >> 12) & 0x03; if (mode == CLK_VALUE_MODE_IDX) { return index; } else { switch (index) { case CLK_TTMR_INC_OSC_32K: return clk_clk32k_rtc_get(CLK_VALUE_MODE_FREQ); case CLK_TTMR_INC_CLKOUT_PIN: /* TODO: */ return -1L; case CLK_TTMR_INC_X24M_DIV_CLK: return 24000000 / (((CLKDIVCON0 >> 24) & 0xff) + 1); case CLK_TTMR_INC_RC2M_D0: return rc2m_clk_nhz_get(0) / 2; default: return 0; } } }