对比新文件 |
| | |
| | | /* |
| | | * Copyright (c) 2019-2023 Beijing Hanwei Innovation Technology Ltd. Co. and |
| | | * its subsidiaries and affiliates (collectly called MKSEMI). |
| | | * |
| | | * All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * 1. Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * |
| | | * 2. Redistributions in binary form, except as embedded into an MKSEMI |
| | | * integrated circuit in a product or a software update for such product, |
| | | * must reproduce the above copyright notice, this list of conditions and |
| | | * the following disclaimer in the documentation and/or other materials |
| | | * provided with the distribution. |
| | | * |
| | | * 3. Neither the name of MKSEMI nor the names of its contributors may be used |
| | | * to endorse or promote products derived from this software without |
| | | * specific prior written permission. |
| | | * |
| | | * 4. This software, with or without modification, must only be used with a |
| | | * MKSEMI integrated circuit. |
| | | * |
| | | * 5. Any software provided in binary form under this license must not be |
| | | * reverse engineered, decompiled, modified and/or disassembled. |
| | | * |
| | | * THIS SOFTWARE IS PROVIDED BY MKSEMI "AS IS" AND ANY EXPRESS OR IMPLIED |
| | | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| | | * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| | | * DISCLAIMED. IN NO EVENT SHALL MKSEMI OR CONTRIBUTORS BE LIABLE FOR ANY |
| | | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| | | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| | | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| | | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| | | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| | | */ |
| | | |
| | | #include "mk_clock.h" |
| | | |
| | | static void clock_32K_clk_config(uint8_t choice) |
| | | { |
| | | // 0 - 32KHz RCO |
| | | // 1 - 32KHz XTAL oscillator |
| | | // 2 - External sine wave |
| | | // 3 - External square wave |
| | | if (choice) |
| | | { |
| | | if ((choice == 2) || (choice == 3)) |
| | | { |
| | | clock_xtal32k_injection_set(choice == 3 ? CLOCK_XTAL_INJECTION_SQUARE : CLOCK_XTAL_INJECTION_SINE); |
| | | } |
| | | |
| | | // XTAL, wait for ready |
| | | while (!(SYSCON->CLK_STATUS & SYSCON_CLK_STATUS_XTAL_32K_REDAY_MSK)) |
| | | { |
| | | } |
| | | SYSCON->SYS_CMU |= SYSCON_SYS_CMU_32K_CLK_SEL_MSK; |
| | | } |
| | | else |
| | | { |
| | | SYSCON->SYS_CMU &= ~SYSCON_SYS_CMU_32K_CLK_SEL_MSK; |
| | | } |
| | | } |
| | | |
| | | static void clock_sys_clk_config(uint8_t choice) |
| | | { |
| | | // 0 - 32KHz |
| | | // 1 - 48MHz RO |
| | | // 2 - 62.4MHz Clock XTAL38.4M |
| | | // 3 - 62.4MHz Clock External 38.4M sine wave |
| | | // 4 - 62.4MHz Clock External 38.4M square wave |
| | | |
| | | uint32_t sys_cmu = SYSCON->SYS_CMU; |
| | | |
| | | if (choice == 0) |
| | | { |
| | | sys_cmu = (sys_cmu & ~SYSCON_SYS_CMU_SYS_CLK_SEL_MSK); |
| | | } |
| | | else if (choice == 1) |
| | | { |
| | | sys_cmu = (sys_cmu | SYSCON_SYS_CMU_SYS_CLK_SEL_MSK); |
| | | sys_cmu = (sys_cmu & ~SYSCON_SYS_CMU_HS_CLK_SEL_MSK); |
| | | } |
| | | else |
| | | { |
| | | if ((choice == 3) || (choice == 4)) |
| | | { |
| | | clock_xtal38m4_injection_set(choice == 4 ? CLOCK_XTAL_INJECTION_SQUARE : CLOCK_XTAL_INJECTION_SINE); |
| | | } |
| | | |
| | | // XTAL, wait for REFPLL ready |
| | | while (!(SYSCON->CLK_STATUS & SYSCON_CLK_STATUS_REFPLL_REDAY_MSK)) |
| | | { |
| | | } |
| | | sys_cmu = (sys_cmu | SYSCON_SYS_CMU_SYS_CLK_SEL_MSK | SYSCON_SYS_CMU_HS_CLK_SEL_MSK); |
| | | } |
| | | |
| | | SYSCON->SYS_CMU = sys_cmu; |
| | | } |
| | | |
| | | static void clock_wdt_clk_config(uint8_t choice) |
| | | { |
| | | if (choice) |
| | | { |
| | | SYSCON->CLK_DIV |= SYSCON_CLK_DIV_WDT_CLK_SEL_MSK; |
| | | } |
| | | else |
| | | { |
| | | SYSCON->CLK_DIV &= ~SYSCON_CLK_DIV_WDT_CLK_SEL_MSK; |
| | | } |
| | | } |
| | | |
| | | static uint32_t clock_get_sys_clk_freq(void) |
| | | { |
| | | uint32_t freq; |
| | | if (SYSCON->SYS_CMU & SYSCON_SYS_CMU_SYS_CLK_SEL_MSK) |
| | | { |
| | | freq = (SYSCON->SYS_CMU & SYSCON_SYS_CMU_HS_CLK_SEL_MSK) ? CLOCK_XTAL38P4M : CLOCK_RO_48M; |
| | | } |
| | | else |
| | | { |
| | | freq = (SYSCON->SYS_CMU & SYSCON_SYS_CMU_32K_CLK_SEL_MSK) ? CLOCK_XTAL_32K : CLOCK_RCO_32K; |
| | | } |
| | | |
| | | return (freq); |
| | | } |
| | | |
| | | static uint32_t clock_get_ahb_clk_freq(void) |
| | | { |
| | | return (clock_get_sys_clk_freq() / (1 << GET_BIT_FIELD(SYSCON->CLK_DIV, SYSCON_CLK_DIV_HCLK_DIV_MSK, SYSCON_CLK_DIV_HCLK_DIV_POS))); |
| | | } |
| | | |
| | | static uint32_t clock_get_apb_clk_freq(void) |
| | | { |
| | | return (clock_get_ahb_clk_freq() / (1 << GET_BIT_FIELD(SYSCON->CLK_DIV, SYSCON_CLK_DIV_PCLK_DIV_MSK, SYSCON_CLK_DIV_PCLK_DIV_POS))); |
| | | } |
| | | |
| | | static uint32_t clock_get_32k_clk_freq(void) |
| | | { |
| | | return ((SYSCON->SYS_CMU & SYSCON_SYS_CMU_32K_CLK_SEL_MSK) ? CLOCK_XTAL_32K : CLOCK_RCO_32K); |
| | | } |
| | | |
| | | static uint32_t clock_get_wdt_clk_freq(void) |
| | | { |
| | | return ((SYSCON->CLK_DIV & SYSCON_CLK_DIV_WDT_CLK_SEL_MSK) ? clock_get_apb_clk_freq() : clock_get_32k_clk_freq()); |
| | | } |
| | | |
| | | static uint32_t clock_get_flash_clk_freq(void) |
| | | { |
| | | return (clock_get_sys_clk_freq() / (1 << GET_BIT_FIELD(SYSCON->CLK_DIV, SYSCON_CLK_DIV_FLASH_CTRL_DIV_MSK, SYSCON_CLK_DIV_FLASH_CTRL_DIV_POS))); |
| | | } |
| | | |
| | | void clock_enable(enum CLOCK_GATE_T clk) |
| | | { |
| | | SYSCON->SYS_CMU |= (1U << clk); |
| | | } |
| | | |
| | | void clock_disable(enum CLOCK_GATE_T clk) |
| | | { |
| | | SYSCON->SYS_CMU &= ~(1U << clk); |
| | | } |
| | | |
| | | void clock_attach(enum CLOCK_ATTACH_TYPE_T connection) |
| | | { |
| | | uint8_t mux, choice; |
| | | |
| | | mux = (uint8_t)connection; |
| | | choice = (uint8_t)(connection >> 8); |
| | | |
| | | switch (mux) |
| | | { |
| | | case CLOCK_32K_CLK_SEL: |
| | | clock_32K_clk_config(choice); |
| | | break; |
| | | case CLOCK_SYS_CLK_SEL: |
| | | clock_sys_clk_config(choice); |
| | | break; |
| | | case CLOCK_WDT_CLK_SEL: |
| | | clock_wdt_clk_config(choice); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | |
| | | void clock_set_divider(enum CLOCK_DIVIDER_T div_name, uint8_t div_value) |
| | | { |
| | | switch (div_name) |
| | | { |
| | | case CLOCK_AHB_DIV: |
| | | SYSCON->CLK_DIV = (SYSCON->CLK_DIV & ~SYSCON_CLK_DIV_HCLK_DIV_MSK) | SYSCON_CLK_DIV_HCLK_DIV(div_value); |
| | | break; |
| | | case CLOCK_APB_DIV: |
| | | SYSCON->CLK_DIV = (SYSCON->CLK_DIV & ~SYSCON_CLK_DIV_PCLK_DIV_MSK) | SYSCON_CLK_DIV_PCLK_DIV(div_value); |
| | | break; |
| | | case CLOCK_FLASH_CTRL_DIV: |
| | | SYSCON->CLK_DIV = (SYSCON->CLK_DIV & ~SYSCON_CLK_DIV_FLASH_CTRL_DIV_MSK) | SYSCON_CLK_DIV_FLASH_CTRL_DIV(div_value); |
| | | break; |
| | | case CLOCK_UART1_FDIV: |
| | | SYSCON->CLK_DIV = (SYSCON->CLK_DIV & ~SYSCON_CLK_DIV_UART1_FDIV_MSK) | SYSCON_CLK_DIV_UART1_FDIV(div_value); |
| | | break; |
| | | case CLOCK_UART0_FDIV: |
| | | SYSCON->CLK_DIV = (SYSCON->CLK_DIV & ~SYSCON_CLK_DIV_UART0_FDIV_MSK) | SYSCON_CLK_DIV_UART0_FDIV(div_value); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | uint32_t clock_get_frequency(enum CLOCK_TYPE_T clk_name) |
| | | { |
| | | uint32_t freq = 0; |
| | | switch (clk_name) |
| | | { |
| | | case CLOCK_SYS_CLK: |
| | | freq = clock_get_sys_clk_freq(); |
| | | break; |
| | | case CLOCK_AHB_CLK: |
| | | freq = clock_get_ahb_clk_freq(); |
| | | break; |
| | | case CLOCK_APB_CLK: |
| | | freq = clock_get_apb_clk_freq(); |
| | | break; |
| | | case CLOCK_WDT_CLK: |
| | | freq = clock_get_wdt_clk_freq(); |
| | | break; |
| | | case CLOCK_32K_CLK: |
| | | freq = clock_get_32k_clk_freq(); |
| | | break; |
| | | case CLOCK_FLASH_CLK: |
| | | freq = clock_get_flash_clk_freq(); |
| | | break; |
| | | } |
| | | return freq; |
| | | } |
| | | |
| | | void clock_xtal38m4_injection_set(enum CLOCK_XTAL_INJECTION_TYPE_T type) |
| | | { |
| | | uint32_t tmp_val = REG_READ(0x40000048); |
| | | tmp_val &= ~((0x3U << 16) | 0x7fU); |
| | | REG_WRITE(0x40000048, tmp_val | (type << 16)); |
| | | |
| | | REG_WRITE(0x40000210, 0x0); |
| | | REG_WRITE(0x40000104, 0x0FFF); |
| | | |
| | | tmp_val = REG_READ(0x40000214); |
| | | REG_WRITE(0x40000214, tmp_val | (1 << 12) | (2 << 10) | (2 << 8)); |
| | | } |
| | | |
| | | void clock_xtal32k_injection_set(enum CLOCK_XTAL_INJECTION_TYPE_T type) |
| | | { |
| | | uint32_t tmp_val = REG_READ(0x4000004C); |
| | | tmp_val &= ~(0x3U << 16); |
| | | REG_WRITE(0x4000004C, tmp_val | (type << 16)); |
| | | } |