/* * This file is part of FH8620 BSP for RT-Thread distribution. * * Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd. * All rights reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Visit http://www.fullhan.com to get contact with Fullhan. * * Change Logs: * Date Author Notes */ #include "clock.h" #include #include "fh_arch.h" #include "libraries/inc/fh_timer.h" #include "fh_pmu.h" //#include "chip_reg.h" //NEED_CAUTION. #define TIMER_CLOCK 1000000 #define FH_CLK_DEBUG #define FH_CLK_DIV_DEFAULT //#define FH_CLK_GATE_DEFAULT //#define FH_DBG_CLK #define FH_CLK_DIV_DEFAULT_VALUE 0x55aaaa55 #define FH_CLK_GATE_DEFAULT_VALUE 0xaa5555aa #define CONFIG_PAE_PTS_CLOCK (1000000) #define TICKS_PER_USEC (CONFIG_PAE_PTS_CLOCK / 1000000) #define REG_PAE_PTS_REG (0xec100000 + 0x0040) #define fh_clk_err(p,fmt,args...)\ rt_kprintf("clk_err: %s->\t"fmt,p->name, ##args) #ifdef FH_CLK_DEBUG #define fh_clk_debug(p,fmt,args...)\ rt_kprintf("%s:\t\t"fmt,p->name, ##args) #define fh_clk_debug_no_handle(fmt,args...)\ rt_kprintf(fmt, ##args) #else //#define fh_clk_err(p,fmt,args...) #define fh_clk_debug(p,fmt,args...) #define fh_clk_debug_no_handle(fmt,args...) #endif struct fh_clk_tree; static struct fh_clk_tree fh_clk_tree; #define __raw_writel(v,a) (*(volatile unsigned int *)(a) = (v)) #define __raw_readl(a) (*(volatile unsigned int *)(a)) #define FH_TIMER_WRITEL(offset,value) __raw_writel(value,(fh_clk_tree.c_base_addr + offset)) #define FH_TIMER_READL(offset) __raw_readl((fh_clk_tree.c_base_addr + offset)) enum clk_gate_enum{ #define CLK_GATE (1) #define CLK_UNGATE (0) ISP_ACLK_GATE = (1<<0), HCLK_GATE = (1<<1), CPU_FCLK0_GATE = (1<<3), VCU_CLK_GATE = (1<<4), VOU_CLK_GATE = (1<<5), MCLK_GATE = (1<<6), SPI0_CLK_GATE = (1<<7), SPI1_CLK_GATE = (1<<8), SDC0_CLK_GATE = (1<<9), SDC1_CLK_GATE = (1<<10), AC_MCLK_GATE = (1<<11), ///// I2C0_CLK_GATE = (1<<12), UART0_CLK_GATE = (1<<13), UART1_CLK_GATE = (1<<14), //can't change WDT_CLK_GATE = (1<<15), PWM_CLK_GATE = (1<<16), TMR0_CLK_GATE = (1<<17), TMR1_CLK_GATE = (1<<18), PTS_CLK_GATE = (1<<19), MIPI_DPHY_CLK20M_GATE = (1<<20), MIPI_P32_CLK_GATE = (1<<21), PIX_CLK_GATE = (1<<22), //// CIS_CLK_OUT_GATE = (1<<23), I2S_SCLK_GATE = (1<<24), ////// ETH_REF_CLK_GATE = (1<<25), SADC_CLK_GATE = (1<<26), I2C1_CLK_GATE = (1<<27), ETH_RX_CLK_GATE = (1<<28), ///// ETH_TX_CLK_GATE = (1<<29), ///// ETH_RMII_CLK_GATE = (1<<30),//// }; //struct fh_clk; typedef void (*clk_update)(struct fh_clk* p_clk); //update func... void clk_in_update(struct fh_clk* p_clk); void pll1_clk_update(struct fh_clk* p_clk); void pll0_clk_update(struct fh_clk* p_clk); void cis_pclk_update(struct fh_clk* p_clk); void ddr_clk_update(struct fh_clk* p_clk); void ddr_clk_update(struct fh_clk* p_clk); void fclk_update(struct fh_clk* p_clk); void aclk_update(struct fh_clk* p_clk); void hclk_update(struct fh_clk* p_clk); void pclk_update(struct fh_clk* p_clk); void isp_aclk_update(struct fh_clk* p_clk); void vcu_clk_update(struct fh_clk* p_clk); void vou_clk_update(struct fh_clk* p_clk); void mipi_p32_clk_update(struct fh_clk* p_clk); void cis_clk_out_update(struct fh_clk* p_clk); void pts_update(struct fh_clk* p_clk); void mipi_pix_clk_update(struct fh_clk* p_clk); void spi0_clk_update(struct fh_clk* p_clk); void spi1_clk_update(struct fh_clk* p_clk); void mipi_dphy_clk20m_update(struct fh_clk* p_clk); void i2c0_clk_update(struct fh_clk* p_clk); void i2c1_clk_update(struct fh_clk* p_clk); void uart0_clk_update(struct fh_clk* p_clk); void uart1_clk_update(struct fh_clk* p_clk); void pwm_clk_update(struct fh_clk* p_clk); void time0_clk_update(struct fh_clk* p_clk); void time1_clk_update(struct fh_clk* p_clk); void sadc_clk_update(struct fh_clk* p_clk); void sdc0_clk2x_update(struct fh_clk* p_clk); void sdc0_clk_update(struct fh_clk* p_clk); void sdc0_clk_out_update(struct fh_clk* p_clk); void sdc0_clk_sample_update(struct fh_clk* p_clk); void sdc0_clk_drv_update(struct fh_clk* p_clk); void sdc1_clk2x_update(struct fh_clk* p_clk); void sdc1_clk_update(struct fh_clk* p_clk); void sdc1_clk_out_update(struct fh_clk* p_clkt); void sdc1_clk_sample_update(struct fh_clk* p_clk); void sdc1_clk_drv_update(struct fh_clk* p_clk); void eth_ref_clk_update(struct fh_clk* p_clk); void wdt_clk_update(struct fh_clk* p_clk); rt_int32_t check_pix_clk_source(rt_uint32_t offset,rt_uint32_t mask,rt_uint32_t *value); void pix_update(struct fh_clk* p_clk); struct fh_clk_div{ //some has prediv.... //this two could have or...... #define PRE_DIV_CAL_ALREADY (0x80000000) #define PRE_DIV_ENABLE (0x01) #define DIV_ENABLE (0x10) rt_uint32_t div_flag; rt_uint32_t pdiv_value; //rt_uint32_t hw_div_value; rt_uint32_t sw_div_value; rt_uint32_t sw_div_multi; //rt_uint32_t clk_in_hz; rt_uint32_t reg_offset; rt_uint32_t reg_mask; //rt_uint32_t rate; }; struct fh_clk_mux{ //#define MUX_LEVEL_1 (1) //#define MUX_LEVEL_2 (2) //#define MAX_MUX_LEVEL MUX_LEVEL_2 // rt_uint32_t lev; #define HAS_MUX (0) #define HAS_NO_MUX (1) rt_uint32_t mux_flag; rt_uint32_t hw_mux_value; rt_uint32_t sw_mux_value; rt_uint32_t reg_offset; rt_uint32_t reg_mask; }; struct fh_clk_gate{ #define HAS_GATE (0) #define HAS_NO_GATE (1) rt_uint32_t gate_flag; #define CLK_UNGATE (0) #define CLK_GATE (1) //rt_uint32_t hw_status; rt_uint32_t sw_status; //rt_uint32_t value; rt_uint32_t reg_offset; rt_uint32_t reg_mask; }; /*************** * * level 1 * ***************/ struct fh_clk_level_1{ rt_uint32_t clk_in_out; }; /*************** * * level 2 * ***************/ struct fh_clk_level_2{ rt_uint32_t clk_in_out; }; /*************** * * level 3 * ***************/ struct fh_clk_level_3_ddr{ //rt_uint32_t mux_level; struct fh_clk_mux mux[2]; struct fh_clk_gate gate; struct fh_clk_div div; }; struct fh_clk_level_3_sdc{ #define DIFF_REFERENCE (0x80000000) rt_uint32_t phase_diff; rt_uint32_t reg_offset; rt_uint32_t reg_mask; }; struct fh_clk_level_3_gmac{ }; struct fh_clk_level_3_normal{ struct fh_clk_mux mux; struct fh_clk_gate gate; struct fh_clk_div div; }; struct fh_clk_level_3 { #define LEVEL_PERI_NORMAL (0x301) #define LEVEL_PERI_DDR (0x302) #define LEVEL_PERI_SDC (0x303) #define LEVEL_PERI_GMAC (0x304) rt_uint32_t peri_flag; union { struct fh_clk_level_3_ddr ddr; struct fh_clk_level_3_sdc sdc; struct fh_clk_level_3_gmac gmac; struct fh_clk_level_3_normal normal; }obj; }; struct fh_clk { char *name; #define LEVEL_CRYSTAL (0x100) #define LEVEL_PLL (0x200) #define LEVEL_PERIPHERAL (0x300) rt_uint32_t level; #define ROOT_NODE (RT_NULL) struct fh_clk *parent; union { struct fh_clk_level_1 crystal; struct fh_clk_level_2 pll; struct fh_clk_level_3 peri; }clk; rt_uint32_t clk_out_rate; #define CLK_HAS_NO_GATE (0x80000000) rt_uint32_t gate; clk_update update_func; //struct fh_clk_tree *p_tree; }; struct fh_clk_tree{ rt_uint32_t c_base_addr; struct fh_clk **clk_head; }; /********* * * * clk map.... * * ********/ #define CRYSTAL_HZ (24000000) struct fh_clk clk_in = { .name = "clk_in", .level = LEVEL_CRYSTAL, .parent = ROOT_NODE, .clk.crystal.clk_in_out = CRYSTAL_HZ, //.clk_out_rate = clk_in.clk.crystal.clk_in_out, .clk_out_rate = CRYSTAL_HZ, .update_func = clk_in_update, }; #define CIS_PCLK_HZ (108000000) struct fh_clk cis_pclk = { .name = "cis_pclk", .level = LEVEL_CRYSTAL, .parent = ROOT_NODE, .clk.crystal.clk_in_out = CIS_PCLK_HZ, //.clk_out_rate = clk_in.clk.crystal.clk_in_out, .clk_out_rate = CIS_PCLK_HZ, .update_func = cis_pclk_update, }; #define PLL0_HZ (864000000) struct fh_clk pll0 = { .name = "pll0", .level = LEVEL_PLL, .parent = &clk_in, .clk.crystal.clk_in_out = PLL0_HZ, //.clk_out_rate = pll0.clk.crystal.clk_in_out, .clk_out_rate = PLL0_HZ, .update_func = pll0_clk_update, }; #define PLL1_HZ (600000000) struct fh_clk pll1 = { .name = "pll1", .level = LEVEL_PLL, .parent = &clk_in, .clk.crystal.clk_in_out = PLL1_HZ, .clk_out_rate = PLL1_HZ, .update_func = pll1_clk_update, }; //NEED_CAUTION parent not fix... static struct fh_clk ddr_clk_normal = { .name = "ddr_normal", .level = LEVEL_PERIPHERAL, //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_DDR, //0:xtal_clk //1:pll0_clk #define MUX0_XTAL_CLK (0) #define MUX0_PLL0_CLK (1) .clk.peri.obj.ddr.mux[0].reg_offset = REG_PMU_SYS_CTRL, .clk.peri.obj.ddr.mux[0].reg_mask = 1<<0, //0:pll0 clk default 864/2M //1:pll1 clk default 600M #define MUX1_PLL0_CLK (0) #define MUX1_PLL1_CLK (1) .clk.peri.obj.ddr.mux[1].reg_offset = REG_PMU_CLK_SEL, .clk.peri.obj.ddr.mux[1].reg_mask = 1<<24, //gate //.clk.peri.obj.ddr.gate.enable_status = CLK_ENABLE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.ddr.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.ddr.gate.sw_status = CLK_UNGATE, #endif .clk.peri.obj.ddr.gate.gate_flag = HAS_GATE, .clk.peri.obj.ddr.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.ddr.gate.reg_mask = MCLK_GATE, //div //clk in maybe cry or pll .clk.peri.obj.ddr.div.div_flag = DIV_ENABLE, //.clk.peri.obj.ddr.div.pdiv_value = 2, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.ddr.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.ddr.div.sw_div_value = 1, #endif .clk.peri.obj.ddr.div.sw_div_multi =1, .clk.peri.obj.ddr.div.reg_offset = REG_PMU_CLK_DIV1, .clk.peri.obj.ddr.div.reg_mask = 0xff <<0, .update_func = ddr_clk_update, }; //NEED_CAUTION parent not fix... static struct fh_clk ddr_clk_div2 = { .name = "ddr_div2", .level = LEVEL_PERIPHERAL, //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_DDR, //0:xtal_clk //1:pll0_clk .clk.peri.obj.ddr.mux[0].reg_offset = REG_PMU_SYS_CTRL, .clk.peri.obj.ddr.mux[0].reg_mask = 1<<0, //0:pll0 clk default 864/2M //1:pll1 clk default 600M .clk.peri.obj.ddr.mux[1].reg_offset = REG_PMU_CLK_SEL, .clk.peri.obj.ddr.mux[1].reg_mask = 1<<24, //gate //.clk.peri.obj.ddr.gate.enable_status = CLK_ENABLE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.ddr.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.ddr.gate.sw_status = CLK_UNGATE, #endif .clk.peri.obj.ddr.gate.gate_flag = HAS_GATE, .clk.peri.obj.ddr.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.ddr.gate.reg_mask = MCLK_GATE, //div //clk in maybe cry or pll .clk.peri.obj.ddr.div.div_flag = PRE_DIV_ENABLE | DIV_ENABLE, .clk.peri.obj.ddr.div.pdiv_value = 2, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.ddr.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.ddr.div.sw_div_value = 1, #endif .clk.peri.obj.ddr.div.sw_div_multi =1, .clk.peri.obj.ddr.div.reg_offset = REG_PMU_CLK_DIV1, .clk.peri.obj.ddr.div.reg_mask = 0xff <<0, .update_func = ddr_clk_update, }; static struct fh_clk cpu_fclk = { .name = "cpu_fclk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, //0:xtal_clk //1:pll0_clk .clk.peri.obj.normal.mux.reg_offset = REG_PMU_SYS_CTRL, .clk.peri.obj.normal.mux.reg_mask = 1<<0, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_NO_GATE, //.clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, //.clk.peri.obj.normal.gate.reg_mask = CPU_FCLK0_GATE, //div .clk.peri.obj.normal.div.div_flag = DIV_ENABLE, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.normal.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.normal.div.sw_div_value = 0, #endif .clk.peri.obj.normal.div.sw_div_multi =1, .clk.peri.obj.normal.div.reg_offset =REG_PMU_CLK_DIV0, .clk.peri.obj.normal.div.reg_mask = 0xff << 0, .update_func = fclk_update, }; //NEED_CAUTION parent not fix... static struct fh_clk cpu_aclk = { .name = "cpu_aclk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, //0:xtal_clk //1:pll0_clk .clk.peri.obj.normal.mux.mux_flag = HAS_NO_MUX, // .clk.peri.obj.normal.mux.reg_offset = REG_PMU_SYS_CTRL, // .clk.peri.obj.normal.mux.reg_mask = 1<<0, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = CPU_FCLK0_GATE, //div .clk.peri.obj.normal.div.div_flag = PRE_DIV_ENABLE, .clk.peri.obj.normal.div.pdiv_value = 2, // .clk.peri.obj.normal.div.reg_offset =REG_PMU_CLK_DIV0, // .clk.peri.obj.normal.div.reg_mask = 0xff << 0, .update_func = aclk_update, }; static struct fh_clk cpu_hclk = { .name = "cpu_hclk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, //0:xtal_clk //1:pll0_clk .clk.peri.obj.normal.mux.reg_offset = REG_PMU_SYS_CTRL, .clk.peri.obj.normal.mux.reg_mask = 1<<0, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_NO_GATE, //.clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, //.clk.peri.obj.normal.gate.reg_mask = CPU_FCLK0_GATE, //div .clk.peri.obj.normal.div.div_flag = DIV_ENABLE, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.normal.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.normal.div.sw_div_value = 1, #endif .clk.peri.obj.normal.div.sw_div_multi =1, .clk.peri.obj.normal.div.reg_offset =REG_PMU_CLK_DIV0, .clk.peri.obj.normal.div.reg_mask = 0xff << 16, .update_func = hclk_update, }; //NEED_CAUTION parent not fix... static struct fh_clk cpu_pclk = { .name = "cpu_pclk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, //0:xtal_clk //1:pll0_clk .clk.peri.obj.normal.mux.mux_flag = HAS_NO_MUX, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = HCLK_GATE, //div .clk.peri.obj.normal.div.div_flag = PRE_DIV_ENABLE, .clk.peri.obj.normal.div.pdiv_value = 2, // .clk.peri.obj.normal.div.reg_offset =REG_PMU_CLK_DIV0, // .clk.peri.obj.normal.div.reg_mask = 0xff << 0, .update_func = pclk_update, }; //NEED_CAUTION parent not fix... static struct fh_clk isp_aclk = { .name = "isp_aclk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, //0:xtal_clk //1:pll0_clk .clk.peri.obj.normal.mux.reg_offset = REG_PMU_SYS_CTRL, .clk.peri.obj.normal.mux.reg_mask = 1<<0, //gate .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = ISP_ACLK_GATE, .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif //div .clk.peri.obj.normal.div.div_flag = DIV_ENABLE, .clk.peri.obj.normal.div.reg_offset = REG_PMU_CLK_DIV0, .clk.peri.obj.normal.div.reg_mask = 0x03 << 8, .clk.peri.obj.normal.div.sw_div_multi =1, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.normal.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.normal.div.sw_div_value = 1, #endif .update_func = isp_aclk_update, }; // ////NEED_CAUTION parent not fix... static struct fh_clk vcu_clk = { .name = "vcu_clk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, //0:xtal_clk //1:pll0_clk .clk.peri.obj.normal.mux.reg_offset = REG_PMU_SYS_CTRL, .clk.peri.obj.normal.mux.reg_mask = 1<<0, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = VCU_CLK_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif //div .clk.peri.obj.normal.div.div_flag = DIV_ENABLE, .clk.peri.obj.normal.div.reg_offset = REG_PMU_CLK_DIV0, .clk.peri.obj.normal.div.reg_mask = 0x03 << 24, .clk.peri.obj.normal.div.sw_div_multi =1, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.normal.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.normal.div.sw_div_value = 1, #endif .update_func = vcu_clk_update, }; static struct fh_clk vou_clk = { .name = "vou_clk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, //0:xtal_clk //1:pll0_clk .clk.peri.obj.normal.mux.reg_offset = REG_PMU_SYS_CTRL, .clk.peri.obj.normal.mux.reg_mask = 1<<0, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = VOU_CLK_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif //div .clk.peri.obj.normal.div.div_flag = DIV_ENABLE, .clk.peri.obj.normal.div.reg_offset = REG_PMU_CLK_DIV1, .clk.peri.obj.normal.div.reg_mask = 0x3f << 8, .clk.peri.obj.normal.div.sw_div_multi =1, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.normal.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.normal.div.sw_div_value = 1, #endif .update_func = vou_clk_update, }; static struct fh_clk mipi_p32_clk = { .name = "mipi_p32_clk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, //0:xtal_clk //1:pll0_clk .clk.peri.obj.normal.mux.reg_offset = REG_PMU_SYS_CTRL, .clk.peri.obj.normal.mux.reg_mask = 1<<0, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = MIPI_P32_CLK_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif //div .clk.peri.obj.normal.div.div_flag = DIV_ENABLE, .clk.peri.obj.normal.div.reg_offset = REG_PMU_CLK_DIV2, .clk.peri.obj.normal.div.reg_mask = 0x0f << 16, .clk.peri.obj.normal.div.sw_div_multi =1, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.normal.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.normal.div.sw_div_value = 1, #endif .update_func = mipi_p32_clk_update, }; static struct fh_clk cis_clk_out = { .name = "cis_clk_out", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, //0:xtal_clk //1:pll0_clk .clk.peri.obj.normal.mux.reg_offset = REG_PMU_SYS_CTRL, .clk.peri.obj.normal.mux.reg_mask = 1<<0, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = CIS_CLK_OUT_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif //div .clk.peri.obj.normal.div.div_flag = DIV_ENABLE, .clk.peri.obj.normal.div.reg_offset = REG_PMU_CLK_DIV1, .clk.peri.obj.normal.div.reg_mask = 0xff << 16, .clk.peri.obj.normal.div.sw_div_multi =1, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.normal.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.normal.div.sw_div_value = 3, #endif .update_func = cis_clk_out_update, }; static struct fh_clk pts_clk = { .name = "pts_clk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, //0:xtal_clk //1:pll0_clk .clk.peri.obj.normal.mux.reg_offset = REG_PMU_SYS_CTRL, .clk.peri.obj.normal.mux.reg_mask = 1<<0, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = PTS_CLK_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif //div .clk.peri.obj.normal.div.div_flag = DIV_ENABLE | PRE_DIV_ENABLE, .clk.peri.obj.normal.div.reg_offset = REG_PMU_CLK_DIV2, .clk.peri.obj.normal.div.reg_mask = 0xff << 0, .clk.peri.obj.normal.div.sw_div_multi =1, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.normal.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.normal.div.sw_div_value = 35, #endif .clk.peri.obj.normal.div.pdiv_value = 12, .update_func = pts_update, }; static struct fh_clk mipi_pix_clk = { .name = "mipi_pix_clk_i", .level = LEVEL_PERIPHERAL, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, //0:xtal_clk //1:pll0_clk .clk.peri.obj.normal.mux.reg_offset = REG_PMU_SYS_CTRL, .clk.peri.obj.normal.mux.reg_mask = 1<<0, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_NO_GATE, //div .clk.peri.obj.normal.div.div_flag = DIV_ENABLE, .clk.peri.obj.normal.div.reg_offset = REG_PMU_CLK_DIV2, .clk.peri.obj.normal.div.reg_mask = 0x0f << 24, .clk.peri.obj.normal.div.sw_div_multi =1, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.normal.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.normal.div.sw_div_value = 3, #endif .update_func = mipi_pix_clk_update, }; static struct fh_clk pix_clk = { .name = "pix_clk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, //0:xtal_clk //1:pll0_clk #define CIS_PIX_CLK (0) #define CIS_PIX_CLK_OPPOSITE (1) #define MIPI_PIX_CLK (2) .clk.peri.obj.normal.mux.reg_offset = REG_PMU_CLK_SEL, .clk.peri.obj.normal.mux.reg_mask = 3<<4, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = PIX_CLK_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif //div .clk.peri.obj.normal.div.div_flag = 0, .update_func = pix_update, }; static struct fh_clk spi0_clk = { .name = "spi0_clk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, .clk.peri.obj.normal.mux.mux_flag = HAS_NO_MUX, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = SPI0_CLK_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif //div .clk.peri.obj.normal.div.div_flag = DIV_ENABLE, .clk.peri.obj.normal.div.reg_offset = REG_PMU_CLK_DIV3, .clk.peri.obj.normal.div.reg_mask = 0xff << 0, .clk.peri.obj.normal.div.sw_div_multi =1, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.normal.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.normal.div.sw_div_value = 11, #endif .update_func = spi0_clk_update, }; static struct fh_clk spi1_clk = { .name = "spi1_clk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, .clk.peri.obj.normal.mux.mux_flag = HAS_NO_MUX, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = SPI1_CLK_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif //div .clk.peri.obj.normal.div.div_flag = DIV_ENABLE, .clk.peri.obj.normal.div.reg_offset = REG_PMU_CLK_DIV3, .clk.peri.obj.normal.div.reg_mask = 0xff << 16, .clk.peri.obj.normal.div.sw_div_multi =1, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.normal.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.normal.div.sw_div_value = 11, #endif #ifdef RT_USING_SPI1 .clk.peri.obj.normal.div.sw_div_value = 11, #endif .update_func = spi1_clk_update, }; static struct fh_clk mipi_dphy_clk20m = { .name = "mipi_dphy_clk20m", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, .clk.peri.obj.normal.mux.mux_flag = HAS_NO_MUX, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = MIPI_DPHY_CLK20M_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif //div .clk.peri.obj.normal.div.div_flag = PRE_DIV_ENABLE, // .clk.peri.obj.normal.div.reg_offset = REG_PMU_CLK_DIV3, // .clk.peri.obj.normal.div.reg_mask = 0xff << 16, .clk.peri.obj.normal.div.sw_div_multi =1, .clk.peri.obj.normal.div.pdiv_value = 30, // .clk.peri.obj.normal.div.sw_div_value = 11, .update_func = mipi_dphy_clk20m_update, }; static struct fh_clk i2c0_clk = { .name = "i2c0_clk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, .clk.peri.obj.normal.mux.mux_flag = HAS_NO_MUX, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = I2C0_CLK_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif //div .clk.peri.obj.normal.div.div_flag = DIV_ENABLE | PRE_DIV_ENABLE, .clk.peri.obj.normal.div.reg_offset = REG_PMU_CLK_DIV4, .clk.peri.obj.normal.div.reg_mask = 0x3f << 16, .clk.peri.obj.normal.div.sw_div_multi = 1, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.normal.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.normal.div.sw_div_value = 1, #endif .clk.peri.obj.normal.div.pdiv_value = 20, .update_func = i2c0_clk_update, }; static struct fh_clk i2c1_clk = { .name = "i2c1_clk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, .clk.peri.obj.normal.mux.mux_flag = HAS_NO_MUX, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = I2C1_CLK_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif //div .clk.peri.obj.normal.div.div_flag = DIV_ENABLE | PRE_DIV_ENABLE, .clk.peri.obj.normal.div.reg_offset = REG_PMU_CLK_DIV4, .clk.peri.obj.normal.div.reg_mask = 0x3f << 24, .clk.peri.obj.normal.div.sw_div_multi = 1, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.normal.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.normal.div.sw_div_value = 1, #endif .clk.peri.obj.normal.div.pdiv_value = 20, .update_func = i2c1_clk_update, }; static struct fh_clk uart0_clk = { .name = "uart0_clk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, .clk.peri.obj.normal.mux.mux_flag = HAS_NO_MUX, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = UART0_CLK_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif //div .clk.peri.obj.normal.div.div_flag = DIV_ENABLE | PRE_DIV_ENABLE, .clk.peri.obj.normal.div.reg_offset = REG_PMU_CLK_DIV4, .clk.peri.obj.normal.div.reg_mask = 0x1f << 0, .clk.peri.obj.normal.div.sw_div_multi = 1, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.normal.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.normal.div.sw_div_value = 1, #endif .clk.peri.obj.normal.div.pdiv_value = 10, .update_func = uart0_clk_update, }; static struct fh_clk uart1_clk = { .name = "uart1_clk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, .clk.peri.obj.normal.mux.mux_flag = HAS_NO_MUX, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = UART1_CLK_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif //div .clk.peri.obj.normal.div.div_flag = DIV_ENABLE | PRE_DIV_ENABLE, .clk.peri.obj.normal.div.reg_offset = REG_PMU_CLK_DIV4, .clk.peri.obj.normal.div.reg_mask = 0x1f << 8, .clk.peri.obj.normal.div.sw_div_multi = 1, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.normal.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.normal.div.sw_div_value = 1, #endif .clk.peri.obj.normal.div.pdiv_value = 10, .update_func = uart1_clk_update, }; static struct fh_clk pwm_clk = { .name = "pwm_clk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, .clk.peri.obj.normal.mux.mux_flag = HAS_NO_MUX, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = PWM_CLK_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif //div .clk.peri.obj.normal.div.div_flag = DIV_ENABLE | PRE_DIV_ENABLE, .clk.peri.obj.normal.div.reg_offset = REG_PMU_CLK_DIV5, .clk.peri.obj.normal.div.reg_mask = 0x3f << 0, .clk.peri.obj.normal.div.sw_div_multi = 1, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.normal.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.normal.div.sw_div_value = 29, #endif .clk.peri.obj.normal.div.pdiv_value = 20, .update_func = pwm_clk_update, }; static struct fh_clk time0_clk = { .name = "time0_clk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, .clk.peri.obj.normal.mux.mux_flag = HAS_NO_MUX, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = TMR0_CLK_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif //div .clk.peri.obj.normal.div.div_flag = DIV_ENABLE | PRE_DIV_ENABLE, .clk.peri.obj.normal.div.reg_offset = REG_PMU_CLK_DIV5, .clk.peri.obj.normal.div.reg_mask = 0x3f << 16, .clk.peri.obj.normal.div.sw_div_multi = 1, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.normal.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.normal.div.sw_div_value = 29, #endif .clk.peri.obj.normal.div.pdiv_value = 20, .update_func = time0_clk_update, }; static struct fh_clk time1_clk = { .name = "time1_clk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, .clk.peri.obj.normal.mux.mux_flag = HAS_NO_MUX, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = TMR1_CLK_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif //div .clk.peri.obj.normal.div.div_flag = DIV_ENABLE | PRE_DIV_ENABLE, .clk.peri.obj.normal.div.reg_offset = REG_PMU_CLK_DIV5, .clk.peri.obj.normal.div.reg_mask = 0x3f << 24, .clk.peri.obj.normal.div.sw_div_multi = 1, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.normal.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.normal.div.sw_div_value = 29, #endif .clk.peri.obj.normal.div.pdiv_value = 20, .update_func = time1_clk_update, }; static struct fh_clk sadc_clk = { .name = "sadc_clk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, .clk.peri.obj.normal.mux.mux_flag = HAS_NO_MUX, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = SADC_CLK_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif //div .clk.peri.obj.normal.div.div_flag = PRE_DIV_ENABLE, .clk.peri.obj.normal.div.sw_div_multi = 1, .clk.peri.obj.normal.div.pdiv_value = 120, .update_func = sadc_clk_update, }; static struct fh_clk sdc0_clk2x = { .name = "sdc0_clk2x", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, .clk.peri.obj.normal.mux.mux_flag = HAS_NO_MUX, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = SDC0_CLK_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif //div .clk.peri.obj.normal.div.div_flag = DIV_ENABLE | PRE_DIV_ENABLE, .clk.peri.obj.normal.div.reg_offset = REG_PMU_CLK_DIV3, .clk.peri.obj.normal.div.reg_mask = 0x0f << 8, .clk.peri.obj.normal.div.sw_div_multi = 1, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.normal.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.normal.div.sw_div_value = 5, #endif .clk.peri.obj.normal.div.pdiv_value = 2, .update_func = sdc0_clk2x_update, }; static struct fh_clk sdc0_clk = { .name = "sdc0_clk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_SDC, .clk.peri.obj.sdc.phase_diff = DIFF_SDC_REFCLK_0 | DIFF_REFERENCE, // .clk.peri.obj.sdc.reg_offset = REG_PMU_CLK_SEL, // .clk.peri.obj.sdc.reg_mask = 0x0, .update_func = sdc0_clk_update, }; static struct fh_clk sdc0_clk_out = { .name = "sdc0_clk_out", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_SDC, .clk.peri.obj.sdc.phase_diff = DIFF_SDC_REFCLK_0, // .clk.peri.obj.sdc.reg_offset = REG_PMU_CLK_SEL, // .clk.peri.obj.sdc.reg_mask = 0x0, .update_func = sdc0_clk_out_update, }; static struct fh_clk sdc0_clk_sample = { .name = "sdc0_clk_sample", .level = LEVEL_PERIPHERAL, .clk.peri.peri_flag = LEVEL_PERI_SDC, .clk.peri.obj.sdc.phase_diff = DIFF_SDC_REFCLK_0, .clk.peri.obj.sdc.reg_offset = REG_PMU_CLK_SEL, .clk.peri.obj.sdc.reg_mask = 3<16, .update_func = sdc0_clk_sample_update, }; static struct fh_clk sdc0_clk_drive = { .name = "sdc0_clk_drive", .level = LEVEL_PERIPHERAL, .clk.peri.peri_flag = LEVEL_PERI_SDC, .clk.peri.obj.sdc.phase_diff = DIFF_SDC_REFCLK_0, .clk.peri.obj.sdc.reg_offset = REG_PMU_CLK_SEL, .clk.peri.obj.sdc.reg_mask = 3<20, .update_func = sdc0_clk_drv_update, }; static struct fh_clk sdc1_clk2x = { .name = "sdc1_clk2x", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, .clk.peri.obj.normal.mux.mux_flag = HAS_NO_MUX, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = SDC1_CLK_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif //div .clk.peri.obj.normal.div.div_flag = DIV_ENABLE | PRE_DIV_ENABLE, .clk.peri.obj.normal.div.reg_offset = REG_PMU_CLK_DIV3, .clk.peri.obj.normal.div.reg_mask = 0x0f << 24, .clk.peri.obj.normal.div.sw_div_multi = 1, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.normal.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.normal.div.sw_div_value = 5, #endif .clk.peri.obj.normal.div.pdiv_value = 2, .update_func = sdc1_clk2x_update, }; static struct fh_clk sdc1_clk = { .name = "sdc1_clk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_SDC, .clk.peri.obj.sdc.phase_diff = DIFF_SDC_REFCLK_0 | DIFF_REFERENCE, // .clk.peri.obj.sdc.reg_offset = REG_PMU_CLK_SEL, // .clk.peri.obj.sdc.reg_mask = 0x0, .update_func = sdc1_clk_update, }; static struct fh_clk sdc1_clk_out = { .name = "sdc1_clk_out", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_SDC, .clk.peri.obj.sdc.phase_diff = DIFF_SDC_REFCLK_0, // .clk.peri.obj.sdc.reg_offset = REG_PMU_CLK_SEL, // .clk.peri.obj.sdc.reg_mask = 0x0, .update_func = sdc1_clk_out_update, }; static struct fh_clk sdc1_clk_sample = { .name = "sdc1_clk_sample", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_SDC, .clk.peri.obj.sdc.phase_diff = DIFF_SDC_REFCLK_0, .clk.peri.obj.sdc.reg_offset = REG_PMU_CLK_SEL, .clk.peri.obj.sdc.reg_mask = 3<8, .update_func = sdc1_clk_sample_update, }; static struct fh_clk sdc1_clk_drive = { .name = "sdc1_clk_drive", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_SDC, .clk.peri.obj.sdc.phase_diff = DIFF_SDC_REFCLK_0, .clk.peri.obj.sdc.reg_offset = REG_PMU_CLK_SEL, .clk.peri.obj.sdc.reg_mask = 3<12, .update_func = sdc1_clk_drv_update, }; static struct fh_clk eth_ref_clk = { .name = "eth_ref_clk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, .clk.peri.obj.normal.mux.mux_flag = HAS_NO_MUX, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_GATE, .clk.peri.obj.normal.gate.reg_offset = REG_PMU_CLK_GATE, .clk.peri.obj.normal.gate.reg_mask = ETH_REF_CLK_GATE, #ifdef FH_CLK_GATE_DEFAULT .clk.peri.obj.normal.gate.sw_status = FH_CLK_GATE_DEFAULT_VALUE, #else .clk.peri.obj.normal.gate.sw_status = CLK_UNGATE, #endif //div .clk.peri.obj.normal.div.div_flag = DIV_ENABLE | PRE_DIV_ENABLE, .clk.peri.obj.normal.div.reg_offset = REG_PMU_CLK_DIV6, .clk.peri.obj.normal.div.reg_mask = 0x0f << 24, .clk.peri.obj.normal.div.sw_div_multi = 1, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.normal.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.normal.div.sw_div_value = 5, #endif .clk.peri.obj.normal.div.pdiv_value = 2, .update_func = eth_ref_clk_update, }; static struct fh_clk wdt_clk = { .name = "wdt_clk", .level = LEVEL_PERIPHERAL, // //.parent = &clk_in, .clk.peri.peri_flag = LEVEL_PERI_NORMAL, .clk.peri.obj.normal.mux.mux_flag = HAS_NO_MUX, //gate .clk.peri.obj.normal.gate.gate_flag = HAS_NO_GATE, //div .clk.peri.obj.normal.div.div_flag = DIV_ENABLE, .clk.peri.obj.normal.div.reg_offset = REG_PMU_CLK_DIV5, .clk.peri.obj.normal.div.reg_mask = 0x3f << 8, .clk.peri.obj.normal.div.sw_div_multi = 1, #ifdef FH_CLK_DIV_DEFAULT .clk.peri.obj.normal.div.sw_div_value = FH_CLK_DIV_DEFAULT_VALUE, #else .clk.peri.obj.normal.div.sw_div_value = 29, #endif .update_func = wdt_clk_update, }; struct fh_clk *fh_clk_array[] = { &clk_in, &cis_pclk, &pll0, &pll1, &ddr_clk_normal, &ddr_clk_div2, &cpu_fclk, &cpu_aclk, &cpu_hclk, &cpu_pclk, &isp_aclk, &vcu_clk, &vou_clk, &mipi_p32_clk, &cis_clk_out, &pts_clk, &mipi_pix_clk, &pix_clk, //pll1 &sdc0_clk2x, &sdc0_clk, &sdc0_clk_out, &sdc0_clk_sample, &sdc0_clk_drive, &sdc1_clk2x, &sdc1_clk, &sdc1_clk_out, &sdc1_clk_sample, &sdc1_clk_drive, &spi0_clk, &spi1_clk, &mipi_dphy_clk20m, &i2c0_clk, &i2c1_clk, &uart0_clk, &uart1_clk, &pwm_clk, &time0_clk, &time1_clk, &sadc_clk, ð_ref_clk, &wdt_clk, }; static inline rt_int32_t wrap_read_reg(rt_uint32_t offset, rt_uint32_t mask, rt_uint32_t *value) { rt_uint32_t temp_v, temp_shift; /* if(fh_pmu_status() == PMU_STATUS_CLOSE) return -1;*/ temp_v = FH_TIMER_READL(offset); temp_v &= mask; temp_shift = __rt_ffs(mask); temp_v = temp_v >> (temp_shift - 1); *value = temp_v; return 0; } static inline rt_int32_t wrap_write_reg(rt_uint32_t offset, rt_uint32_t mask, rt_uint32_t value) { rt_uint32_t temp_v, temp_shift; /* if(fh_pmu_status() == PMU_STATUS_CLOSE) return -1; */ temp_v = FH_TIMER_READL(offset); temp_v &= ~mask; temp_shift = __rt_ffs(mask); temp_v |= value << (temp_shift - 1); FH_TIMER_WRITEL(offset, temp_v); return 0; } rt_int32_t check_pix_clk_source(rt_uint32_t offset, rt_uint32_t mask, rt_uint32_t *value) { rt_uint32_t mux0; rt_int32_t ret; ret = wrap_read_reg(offset, mask, &mux0); if (ret != 0) { return ret; } *value = mux0; return 0; } rt_int32_t check_xtal_pll0(rt_uint32_t offset, rt_uint32_t mask, rt_uint32_t *value) { rt_uint32_t mux0; rt_int32_t ret; ret = wrap_read_reg(offset, mask, &mux0); if (ret != 0) { return ret; } if (mux0 == MUX0_PLL0_CLK) *value = MUX0_PLL0_CLK; else *value = MUX0_XTAL_CLK; return 0; } void cal_pll0_prediv(rt_uint32_t *div_flag, rt_uint32_t *pre_value) { if (!(*div_flag & PRE_DIV_CAL_ALREADY)) { //before has got the prediv value.. if (*div_flag & PRE_DIV_ENABLE) { *pre_value *= 2; } else { *pre_value = 2; } *div_flag |= PRE_DIV_ENABLE | PRE_DIV_CAL_ALREADY; } } rt_int32_t sw_div_process(rt_uint32_t div_flag, rt_uint32_t offset, rt_uint32_t mask, rt_uint32_t *div_value) { //rt_kprintf("----------div go----------\n"); rt_uint32_t div; rt_int32_t ret; if (div_flag & DIV_ENABLE) { ret = wrap_read_reg(offset, mask, &div); if (ret != 0) { return ret; } // // rt_kprintf("hw value is %x\n",div); // rt_kprintf("sw value is %x\n",div_value); // // rt_kprintf("offset is %x,value :%x\n",offset + 0xf0000000,*(rt_uint32_t*)(offset + 0xf0000000)); // rt_kprintf("mask is %x\n",mask); //if use the hw default value.... if (*div_value == FH_CLK_DIV_DEFAULT_VALUE) { *div_value = div; return 0; } if (div != *div_value) { ret = wrap_write_reg(offset, mask, *div_value); if (ret != 0) { return ret; } } } //rt_kprintf("----------div done----------\n"); return 0; //*div_flag |= PRE_DIV_ENABLE; } void cal_baud_hz(rt_uint32_t clk_in, rt_uint32_t div_flag, rt_uint32_t pre_div, rt_uint32_t div, rt_uint32_t div_multi, rt_uint32_t *baud_out) { //div += 1; if (div_flag & PRE_DIV_ENABLE) { *baud_out = (clk_in / pre_div); } else { *baud_out = clk_in; } if (div_flag & DIV_ENABLE) { *baud_out /= ((div + 1) * div_multi); } } void cal_baud_div(rt_uint32_t clk_in, rt_uint32_t div_flag, rt_uint32_t pre_div, rt_uint32_t *div, rt_uint32_t div_multi, rt_uint32_t baud_out) { //div += 1; rt_uint32_t temp_baud_hz, temp_baud_div; if (div_flag & DIV_ENABLE) { if (div_flag & PRE_DIV_ENABLE) { temp_baud_hz = (clk_in / pre_div); } else { temp_baud_hz = clk_in; } temp_baud_div = temp_baud_hz / baud_out; *div = temp_baud_div - 1; } } rt_int32_t process_gate(rt_uint32_t gate_flag, rt_uint32_t reg_offset, rt_uint32_t reg_mask, rt_uint32_t *sw_status, rt_uint32_t *pclk_status) { //rt_kprintf("----------gate go----------\n"); rt_uint32_t hw_gate; rt_int32_t ret; if (gate_flag == HAS_GATE) { ret = wrap_read_reg(reg_offset, reg_mask, &hw_gate); if (ret != 0) { return ret; } if (*sw_status == FH_CLK_GATE_DEFAULT_VALUE) { *sw_status = hw_gate; *pclk_status = *sw_status; return 0; } // rt_kprintf("gate hw is :%x\n",hw_gate); // rt_kprintf("gate sw is :%x\n",sw_status); if (hw_gate != *sw_status) { //update the gate.. // rt_kprintf("gate reg offset is :%x\n",reg_offset); // rt_kprintf("gate reg mask is :%x\n",reg_mask); // rt_kprintf("gate reg write is :%x\n",sw_status); ret = wrap_write_reg(reg_offset, reg_mask, *sw_status); if (ret != 0) { return ret; } } *pclk_status = *sw_status; } else { *pclk_status |= CLK_HAS_NO_GATE; } //rt_kprintf("---------gate done---------\n"); return 0; } void clk_handle(struct fh_clk* p_clk, struct fh_clk *parent) { //rt_uint32_t div; //rt_uint32_t sw_gate; rt_uint32_t phase; rt_int32_t ret; p_clk->parent = parent; // switch //fh_clk_debug(p_clk,"----parent----\t ----clk out rate----\n "); if (p_clk->parent) //rt_kprintf("%-8.*s 0x%02x", RT_NAME_MAX, thread->name, thread->current_priority); fh_clk_debug(p_clk, "parent:'%s'\n", p_clk->parent->name); else fh_clk_debug(p_clk, "'root node'\n"); switch (p_clk->level) { case LEVEL_CRYSTAL: //fh_clk_debug(p_clk,"clk out:%d\n",p_clk->clk_out_rate); break; case LEVEL_PLL: //fh_clk_debug(p_clk,"%d\n",p_clk->clk_out_rate); break; case LEVEL_PERIPHERAL: switch (p_clk->clk.peri.peri_flag) { case LEVEL_PERI_NORMAL: //div = p_clk->clk.peri.obj.normal.div.sw_div_value; ret = sw_div_process( p_clk->clk.peri.obj.normal.div.div_flag, p_clk->clk.peri.obj.normal.div.reg_offset, p_clk->clk.peri.obj.normal.div.reg_mask, &p_clk->clk.peri.obj.normal.div.sw_div_value); if (ret != 0) { fh_clk_err(p_clk, "div process failed.error no:%x\n", ret); break; } //fh_clk_debug(p_clk,"hw div is %d\n",p_clk->clk.peri.obj.ddr.div.hw_div_value); // fh_clk_debug(p_clk,"sw div is %d\n",p_clk->clk.peri.obj.normal.div.sw_div_value); // fh_clk_debug(p_clk,"pre div is %d\n",p_clk->clk.peri.obj.normal.div.pdiv_value); // fh_clk_debug(p_clk,"clk in is %d\n",p_clk->parent->clk_out_rate); // fh_clk_debug(p_clk,"peri flag is %x\n",p_clk->clk.peri.obj.normal.div.div_flag); //hw will self add 1.. cal_baud_hz(p_clk->parent->clk_out_rate, p_clk->clk.peri.obj.normal.div.div_flag, p_clk->clk.peri.obj.normal.div.pdiv_value, p_clk->clk.peri.obj.normal.div.sw_div_value, p_clk->clk.peri.obj.normal.div.sw_div_multi, &p_clk->clk_out_rate); //fh_clk_debug_no_handle("%d\n",p_clk->clk_out_rate); //fix the gate.. //sw_gate = p_clk->clk.peri.obj.normal.gate.sw_status; ret = process_gate( p_clk->clk.peri.obj.normal.gate.gate_flag, p_clk->clk.peri.obj.normal.gate.reg_offset, p_clk->clk.peri.obj.normal.gate.reg_mask, &p_clk->clk.peri.obj.normal.gate.sw_status, &p_clk->gate); if (ret != 0) { fh_clk_err(p_clk, "gate process failed.error no:%x\n", ret); break; } break; case LEVEL_PERI_DDR: //rt_uint32_t mux0,mux1; //div = p_clk->clk.peri.obj.ddr.div.sw_div_value; ret = sw_div_process( p_clk->clk.peri.obj.ddr.div.div_flag, p_clk->clk.peri.obj.ddr.div.reg_offset, p_clk->clk.peri.obj.ddr.div.reg_mask, &p_clk->clk.peri.obj.ddr.div.sw_div_value); if (ret != 0) { fh_clk_err(p_clk, "div process failed.error no:%x\n", ret); break; } // fh_clk_debug(p_clk,"sw div is %d\n",p_clk->clk.peri.obj.ddr.div.sw_div_value); // fh_clk_debug(p_clk,"pre div is %d\n",p_clk->clk.peri.obj.ddr.div.pdiv_value); // fh_clk_debug(p_clk,"clk in is %d\n",p_clk->parent->clk_out_rate); // fh_clk_debug(p_clk,"peri flag is %x\n",p_clk->clk.peri.obj.ddr.div.div_flag); cal_baud_hz(p_clk->parent->clk_out_rate, p_clk->clk.peri.obj.ddr.div.div_flag, p_clk->clk.peri.obj.ddr.div.pdiv_value, p_clk->clk.peri.obj.ddr.div.sw_div_value, p_clk->clk.peri.obj.ddr.div.sw_div_multi, &p_clk->clk_out_rate); //fh_clk_debug_no_handle("%d\n",p_clk->clk_out_rate); //fix the gate.. //fh_clk_debug(p_clk,"gate reg add is:%x\t mask is:%x\n",p_clk->clk.peri.obj.ddr.gate.reg_offset,p_clk->clk.peri.obj.ddr.gate.reg_mask); //sw_gate = p_clk->clk.peri.obj.ddr.gate.sw_status; ret = process_gate( p_clk->clk.peri.obj.ddr.gate.gate_flag, p_clk->clk.peri.obj.ddr.gate.reg_offset, p_clk->clk.peri.obj.ddr.gate.reg_mask, &p_clk->clk.peri.obj.ddr.gate.sw_status, &p_clk->gate); if (ret != 0) { fh_clk_err(p_clk, "gate process failed.error no:%x\n", ret); break; } break; case LEVEL_PERI_SDC: //just need to handle the phase.... p_clk->clk_out_rate = p_clk->parent->clk_out_rate; if (p_clk->clk.peri.obj.sdc.phase_diff & DIFF_REFERENCE) { //fh_clk_debug(p_clk,"this is the reference..no need to process..\n"); break; } //baud ... //phase.. //fh_clk_debug_no_handle("%d\n",p_clk->clk_out_rate); //hw status.. ret = wrap_read_reg(p_clk->clk.peri.obj.sdc.reg_offset, p_clk->clk.peri.obj.sdc.reg_mask, &phase); if (ret != 0) { fh_clk_err(p_clk, "read pmu failed.error no:%x\n", ret); break; } // fh_clk_debug(p_clk,"hw phase is :%x\n",phase); // fh_clk_debug(p_clk,"sw phase is :%x\n",p_clk->clk.peri.obj.sdc.phase_diff); if (phase != p_clk->clk.peri.obj.sdc.phase_diff) { //update the hw para.. ret = wrap_write_reg( p_clk->clk.peri.obj.sdc.reg_offset, p_clk->clk.peri.obj.sdc.reg_mask, p_clk->clk.peri.obj.sdc.phase_diff); if (ret != 0) { fh_clk_err(p_clk, "write pmu failed.error no:%x\n", ret); break; } } break; case LEVEL_PERI_GMAC: break; default: break; } } fh_clk_debug(p_clk, "clk out:%d\n", p_clk->clk_out_rate); } // void clk_in_update(struct fh_clk* p_clk) { clk_handle(p_clk, RT_NULL); } void cis_pclk_update(struct fh_clk* p_clk) { clk_handle(p_clk, RT_NULL); } void pll1_clk_update(struct fh_clk* p_clk) { clk_handle(p_clk, &clk_in); } void pll0_clk_update(struct fh_clk* p_clk) { clk_handle(p_clk, &clk_in); } void ddr_clk_update(struct fh_clk* p_clk) { //check if pll0 or pll1 rt_uint32_t mux0, mux1; rt_int32_t ret; struct fh_clk* parent; //1 step: fix the parent.. ret = wrap_read_reg(p_clk->clk.peri.obj.ddr.mux[1].reg_offset, p_clk->clk.peri.obj.ddr.mux[1].reg_mask, &mux1); if (ret != 0) { fh_clk_err(p_clk, "read pmu failed.error no:%x\n", ret); return; } if (mux1 == MUX1_PLL0_CLK) { ret = check_xtal_pll0(p_clk->clk.peri.obj.ddr.mux[0].reg_offset, p_clk->clk.peri.obj.ddr.mux[0].reg_mask, &mux0); if (ret != 0) { fh_clk_err(p_clk, "read pmu failed.error no:%x\n", ret); return; } if (mux0 == MUX0_PLL0_CLK) { //ddr normal parent is pll0 parent = &pll0; } else { //ddr normal parent is xtal parent = &clk_in; } } else { //ddr normal parent is pll1 parent = &pll1; } p_clk->clk.peri.obj.ddr.mux[0].mux_flag = HAS_MUX; p_clk->clk.peri.obj.ddr.mux[1].mux_flag = HAS_MUX; clk_handle(p_clk, parent); } void fclk_update(struct fh_clk* p_clk) { //check if pll0 or xtal rt_uint32_t mux0; rt_int32_t ret; struct fh_clk* parent; //1 step: fix the parent.. //mux0 = check_xtal_pll0(p_clk->clk.peri.obj.ddr.mux[0].reg_offset,p_clk->clk.peri.obj.ddr.mux[0].reg_mask); ret = check_xtal_pll0(p_clk->clk.peri.obj.normal.mux.reg_offset, p_clk->clk.peri.obj.normal.mux.reg_mask, &mux0); if (ret != 0) { fh_clk_err(p_clk, "read pmu failed.error no:%x\n", ret); return; } //fh_clk_debug(p_clk,"mux0 wrap value is %x\n",mux0); if (mux0 == MUX0_PLL0_CLK) { //ddr normal parent is pll0 parent = &pll0; } else { //ddr normal parent is xtal parent = &clk_in; } p_clk->clk.peri.obj.normal.mux.mux_flag = HAS_MUX; //2 step:fix the div... if (mux0 == MUX0_PLL0_CLK) { //cal_pll0_prediv(&p_clk->clk.peri.obj.ddr.div.div_flag,&p_clk->clk.peri.obj.ddr.div.pdiv_value); cal_pll0_prediv(&p_clk->clk.peri.obj.normal.div.div_flag, &p_clk->clk.peri.obj.normal.div.pdiv_value); } clk_handle(p_clk, parent); } void pix_update(struct fh_clk* p_clk) { //check if pll0 or xtal rt_uint32_t mux0; rt_int32_t ret; struct fh_clk* parent; //1 step: fix the parent.. #if(1) //mux0 = check_xtal_pll0(p_clk->clk.peri.obj.ddr.mux[0].reg_offset,p_clk->clk.peri.obj.ddr.mux[0].reg_mask); ret = check_pix_clk_source(p_clk->clk.peri.obj.normal.mux.reg_offset, p_clk->clk.peri.obj.normal.mux.reg_mask, &mux0); if (ret != 0) { fh_clk_err(p_clk, "read pmu failed.error no:%x\n", ret); return; } //#define CIS_PIX_CLK (0) //#define CIS_PIX_CLK_OPPOSITE (1) //#define MIPI_PIX_CLK (2) //fh_clk_debug(p_clk,"mux0 wrap value is %x\n",mux0); if (mux0 == CIS_PIX_CLK || mux0 == CIS_PIX_CLK_OPPOSITE) { //ddr normal parent is pll0 parent = &cis_pclk; } else { parent = &mipi_pix_clk; } p_clk->clk.peri.obj.normal.mux.mux_flag = HAS_MUX; #endif clk_handle(p_clk, parent); } void aclk_update(struct fh_clk* p_clk) { clk_handle(p_clk, &cpu_fclk); } void hclk_update(struct fh_clk* p_clk) { fclk_update(p_clk); } void pclk_update(struct fh_clk* p_clk) { clk_handle(p_clk, &cpu_hclk); } void isp_aclk_update(struct fh_clk* p_clk) { fclk_update(p_clk); } void vcu_clk_update(struct fh_clk* p_clk) { fclk_update(p_clk); } void vou_clk_update(struct fh_clk* p_clk) { fclk_update(p_clk); } void mipi_p32_clk_update(struct fh_clk* p_clk) { fclk_update(p_clk); } void cis_clk_out_update(struct fh_clk* p_clk) { fclk_update(p_clk); } void pts_update(struct fh_clk* p_clk) { fclk_update(p_clk); } void mipi_pix_clk_update(struct fh_clk* p_clk) { fclk_update(p_clk); } void spi0_clk_update(struct fh_clk* p_clk) { clk_handle(p_clk, &pll1); } void spi1_clk_update(struct fh_clk* p_clk) { clk_handle(p_clk, &pll1); } void mipi_dphy_clk20m_update(struct fh_clk* p_clk) { clk_handle(p_clk, &pll1); } void i2c0_clk_update(struct fh_clk* p_clk) { clk_handle(p_clk, &pll1); } void i2c1_clk_update(struct fh_clk* p_clk) { clk_handle(p_clk, &pll1); } void uart0_clk_update(struct fh_clk* p_clk) { clk_handle(p_clk, &pll1); } void pwm_clk_update(struct fh_clk* p_clk) { clk_handle(p_clk, &pll1); } void time0_clk_update(struct fh_clk* p_clk) { clk_handle(p_clk, &pll1); } void time1_clk_update(struct fh_clk* p_clk) { clk_handle(p_clk, &pll1); } void uart1_clk_update(struct fh_clk* p_clk) { clk_handle(p_clk, &pll1); } void sadc_clk_update(struct fh_clk* p_clk) { clk_handle(p_clk, &pll1); } //sdc0... void sdc0_clk2x_update(struct fh_clk* p_clk) { clk_handle(p_clk, &pll1); } void sdc0_clk_update(struct fh_clk* p_clk) { clk_handle(p_clk, &sdc0_clk2x); } void sdc0_clk_out_update(struct fh_clk* p_clk) { clk_handle(p_clk, &sdc0_clk); } void sdc0_clk_sample_update(struct fh_clk* p_clk) { clk_handle(p_clk, &sdc0_clk2x); } void sdc0_clk_drv_update(struct fh_clk* p_clk) { clk_handle(p_clk, &sdc0_clk2x); } void sdc1_clk2x_update(struct fh_clk* p_clk) { clk_handle(p_clk, &pll1); } void sdc1_clk_update(struct fh_clk* p_clk) { clk_handle(p_clk, &sdc1_clk2x); } void sdc1_clk_out_update(struct fh_clk* p_clk) { clk_handle(p_clk, &sdc1_clk); } void sdc1_clk_sample_update(struct fh_clk* p_clk) { clk_handle(p_clk, &sdc1_clk2x); } void sdc1_clk_drv_update(struct fh_clk* p_clk) { clk_handle(p_clk, &sdc1_clk2x); } void eth_ref_clk_update(struct fh_clk* p_clk) { clk_handle(p_clk, &pll1); } void wdt_clk_update(struct fh_clk* p_clk) { clk_handle(p_clk, &cpu_pclk); } /** * @brief System Clock Configuration */ #define CLK_CONTROL_BASE PMU_REG_BASE void rt_hw_clock_init(void) { struct fh_clk *p; int i; fh_clk_tree.c_base_addr = CLK_CONTROL_BASE; fh_clk_tree.clk_head = fh_clk_array; //first open all the clock.. FH_TIMER_WRITEL(REG_PMU_CLK_GATE, 0x0); for (i = 0; i < sizeof(fh_clk_array) / sizeof(struct fh_clk *); i++) { p = fh_clk_tree.clk_head[i]; if (p->update_func) p->update_func(p); } } /*************** * * new add * **************/ /* clocks cannot be de-registered no refcounting necessary */ struct fh_clk *clk_get(const char *name) { struct fh_clk *p; int i; for (i = 0; i < sizeof(fh_clk_array) / sizeof(struct fh_clk *); i++) { p = fh_clk_tree.clk_head[i]; if (!strcmp(p->name, name)) { return p; } } return RT_NULL; } // //#define HAS_GATE (0) //#define HAS_NO_GATE (1) // rt_uint32_t gate_flag; //#define CLK_UNGATE (0) //#define CLK_GATE (1) void clk_gate_control(struct fh_clk *p_clk, rt_uint32_t status) { if (status > CLK_GATE) return; if (p_clk->level == LEVEL_PERIPHERAL) { switch (p_clk->clk.peri.peri_flag) { case LEVEL_PERI_NORMAL: if (p_clk->clk.peri.obj.normal.gate.gate_flag == HAS_GATE) { p_clk->clk.peri.obj.normal.gate.sw_status = status; } else { rt_kprintf("[%-16.15s]: no gate...\t\n", p_clk->name); } break; case LEVEL_PERI_DDR: if (p_clk->clk.peri.obj.ddr.gate.gate_flag == HAS_GATE) { p_clk->clk.peri.obj.ddr.gate.sw_status = status; } else { rt_kprintf("[%-16.15s]: no gate...\t\n", p_clk->name); } break; default: break; } p_clk->update_func(p_clk); } } void clk_gate(struct fh_clk *p_clk) { clk_gate_control(p_clk, CLK_GATE); } void clk_ungate(struct fh_clk *p_clk) { clk_gate_control(p_clk, CLK_UNGATE); } rt_uint32_t clk_get_rate(struct fh_clk *p_clk) { rt_uint32_t rate; //first update the status p_clk->update_func(p_clk); rate = p_clk->clk_out_rate; return rate; } void clk_set_rate(struct fh_clk *p_clk, rt_uint32_t rate_value) { rt_uint32_t clk_in, div_flag, pre_div, div_multi, baud_out; if (p_clk->level == LEVEL_PERIPHERAL) { switch (p_clk->clk.peri.peri_flag) { case LEVEL_PERI_NORMAL: clk_in = p_clk->parent->clk_out_rate; div_flag = p_clk->clk.peri.obj.normal.div.div_flag; pre_div = p_clk->clk.peri.obj.normal.div.pdiv_value; div_multi = p_clk->clk.peri.obj.normal.div.sw_div_multi; baud_out = rate_value; cal_baud_div(clk_in, div_flag, pre_div, &p_clk->clk.peri.obj.normal.div.sw_div_value, div_multi, baud_out); break; case LEVEL_PERI_DDR: //rt_uint32_t mux0,mux1; clk_in = p_clk->parent->clk_out_rate; div_flag = p_clk->clk.peri.obj.ddr.div.div_flag; pre_div = p_clk->clk.peri.obj.ddr.div.pdiv_value; div_multi = p_clk->clk.peri.obj.ddr.div.sw_div_multi; baud_out = rate_value; cal_baud_div(clk_in, div_flag, pre_div, &p_clk->clk.peri.obj.ddr.div.sw_div_value, div_multi, baud_out); break; case LEVEL_PERI_SDC: fh_clk_debug(p_clk, "sdc can't set baud,please set the 'sdcx_clk2x'\n"); break; case LEVEL_PERI_GMAC: fh_clk_debug(p_clk, "gmac not support set baud\n"); break; default: break; } p_clk->update_func(p_clk); } } rt_uint32_t sdc_get_phase(struct fh_clk *p_clk) { if (p_clk->level == LEVEL_PERIPHERAL) { if (p_clk->clk.peri.peri_flag == LEVEL_PERI_SDC) { p_clk->update_func(p_clk); return p_clk->clk.peri.obj.sdc.phase_diff; } } return SDC_CLK_PARA_ERROR; } rt_uint32_t sdc_set_phase(struct fh_clk *p_clk, rt_uint32_t phase) { if (phase > DIFF_SDC_REFCLK_270) return SDC_CLK_PARA_ERROR; if (p_clk->level == LEVEL_PERIPHERAL) { if (p_clk->clk.peri.peri_flag == LEVEL_PERI_SDC) { p_clk->clk.peri.obj.sdc.phase_diff = phase; p_clk->update_func(p_clk); return SDC_CLK_PARA_OK; } } return SDC_CLK_PARA_ERROR; } #ifdef FH_DBG_CLK int fh_clk_nlist() { struct fh_clk *p; int i; for(i = 0;iupdate_func(p); rt_kprintf("[%-16.15s]:\t\t[baud]:%d\t\n",p->name,p->clk_out_rate); } return 0; } int fh_clk_glist() { struct fh_clk *p; int i; rt_kprintf("first bit set means has no gate..\n"); for(i = 0;iupdate_func(p); if(!(p->gate & CLK_HAS_NO_GATE)) rt_kprintf("[%-16.15s]:\t\t[gate]:%d\t\n",p->name,p->gate); else rt_kprintf("[%-16.15s]:\t\t[gate]:no gate..\t\n",p->name); } return 0; } #endif #ifdef RT_USING_FINSH #include #ifdef FH_DBG_CLK FINSH_FUNCTION_EXPORT(fh_clk_nlist, fh_clk_name_list..); FINSH_FUNCTION_EXPORT(fh_clk_glist, fh_clk_gate_list..); #endif #endif