1 /* 2 * Copyright (c) 2020 Nuvoton Technology Corporation. 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #ifndef _NUVOTON_NPCX_SOC_CLOCK_H_ 8 #define _NUVOTON_NPCX_SOC_CLOCK_H_ 9 10 #include <stdbool.h> 11 #include <stdint.h> 12 13 #include <zephyr/devicetree.h> 14 15 #ifdef __cplusplus 16 extern "C" { 17 #endif 18 19 /* Common clock control device node for all NPCX series */ 20 #define NPCX_CLK_CTRL_NODE DT_NODELABEL(pcc) 21 22 /** 23 * @brief NPCX clock configuration structure 24 * 25 * Used to indicate the device's clock bus type and corresponding PWDWN_CTL 26 * register/bit to turn on/off its source clock. 27 */ 28 struct npcx_clk_cfg { 29 uint16_t bus:8; 30 uint16_t ctrl:5; 31 uint16_t bit:3; 32 }; 33 34 /* Clock settings from pcc node */ 35 /* Target OFMCLK freq */ 36 #define OFMCLK DT_PROP(DT_NODELABEL(pcc), clock_frequency) 37 /* Core clock prescaler */ 38 #define FPRED_VAL (DT_PROP(DT_NODELABEL(pcc), core_prescaler) - 1) 39 /* APB1 clock divider */ 40 #define APB1DIV_VAL (DT_PROP(DT_NODELABEL(pcc), apb1_prescaler) - 1) 41 /* APB2 clock divider */ 42 #define APB2DIV_VAL (DT_PROP(DT_NODELABEL(pcc), apb2_prescaler) - 1) 43 /* APB3 clock divider */ 44 #define APB3DIV_VAL (DT_PROP(DT_NODELABEL(pcc), apb3_prescaler) - 1) 45 /* APB4 clock divider if supported */ 46 #if DT_NODE_HAS_PROP(DT_NODELABEL(pcc), apb4_prescaler) 47 #if defined(CONFIG_CLOCK_CONTROL_NPCX_SUPP_APB4) /* Supported in NPCX9 and later series */ 48 #define APB4DIV_VAL (DT_PROP(DT_NODELABEL(pcc), apb4_prescaler) - 1) 49 #else 50 #error "APB4 clock divider is not supported but defined in pcc node!" 51 #endif /* CONFIG_CLOCK_CONTROL_NPCX_SUPP_APB4 */ 52 #endif 53 54 /* Construct a uint8_t array from 'pwdwn-ctl-val' prop for PWDWN_CTL initialization. */ 55 #define NPCX_PWDWN_CTL_ITEMS_INIT(node, prop, idx) DT_PROP_BY_IDX(node, prop, idx), 56 #define NPCX_PWDWN_CTL_INIT DT_FOREACH_PROP_ELEM(DT_NODELABEL(pcc), \ 57 pwdwn_ctl_val, NPCX_PWDWN_CTL_ITEMS_INIT) 58 59 /* 60 * NPCX7 and later series clock tree macros: 61 * (Please refer Figure 58. for more information.) 62 * 63 * Maximum OFMCLK in npcx7/9 series is 100MHz, 64 * Maximum OFMCLK in npcx4 series is 120MHz, 65 * 66 * Suggestion for npcx series: 67 * - OFMCLK > MAX_OFMCLK/2, XF_RANGE should be 1, else 0. 68 * - CORE_CLK > MAX_OFMCLK/2, AHB6DIV should be 1, else 0. 69 * - CORE_CLK > MAX_OFMCLK/2, FIUDIV should be 1, else 0. 70 */ 71 /* Core domain clock */ 72 #define CORE_CLK (OFMCLK / DT_PROP(DT_NODELABEL(pcc), core_prescaler)) 73 /* Low Frequency clock */ 74 #define LFCLK 32768 75 76 /* FMUL clock */ 77 #if (OFMCLK > (MAX_OFMCLK / 2)) 78 #define FMCLK (OFMCLK / 2) /* FMUL clock = OFMCLK/2 */ 79 #else 80 #define FMCLK OFMCLK /* FMUL clock = OFMCLK */ 81 #endif 82 83 /* APBs source clock */ 84 #define APBSRC_CLK OFMCLK 85 86 /* AHB6 clock */ 87 #if (CORE_CLK > (MAX_OFMCLK / 2)) 88 #define AHB6DIV_VAL 1 /* AHB6_CLK = CORE_CLK/2 */ 89 #else 90 #define AHB6DIV_VAL 0 /* AHB6_CLK = CORE_CLK */ 91 #endif 92 93 /* FIU clock divider */ 94 #if (CORE_CLK > (MAX_OFMCLK / 2)) 95 #define FIUDIV_VAL 1 /* FIU_CLK = CORE_CLK/2 */ 96 #else 97 #define FIUDIV_VAL 0 /* FIU_CLK = CORE_CLK */ 98 #endif 99 100 #if defined(CONFIG_CLOCK_CONTROL_NPCX_SUPP_FIU1) 101 #if (CORE_CLK > (MAX_OFMCLK / 2)) 102 #define FIU1DIV_VAL 1 /* FIU1_CLK = CORE_CLK/2 */ 103 #else 104 #define FIU1DIV_VAL 0 /* FIU1_CLK = CORE_CLK */ 105 #endif 106 #endif /* CONFIG_CLOCK_CONTROL_NPCX_SUPP_FIU1 */ 107 108 /* I3C clock divider */ 109 #if (OFMCLK == MHZ(120)) /* MCLkD must between 40 mhz to 50 mhz*/ 110 #define MCLKD_SL 2 /* I3C_CLK = (MCLK / 3) */ 111 #elif (OFMCLK <= MHZ(100) && OFMCLK >= MHZ(80)) 112 #define MCLKD_SL 1 /* I3C_CLK = (MCLK / 2) */ 113 #else 114 #define MCLKD_SL 0 /* I3C_CLK = MCLK */ 115 #endif 116 117 118 /* Get APB clock freq */ 119 #define NPCX_APB_CLOCK(no) (APBSRC_CLK / (APB##no##DIV_VAL + 1)) 120 121 /* 122 * Frequency multiplier M/N value definitions according to the requested 123 * OFMCLK (Unit:Hz). 124 */ 125 #if (OFMCLK > (MAX_OFMCLK / 2)) 126 #define HFCGN_VAL 0x82 /* Set XF_RANGE as 1 */ 127 #else 128 #define HFCGN_VAL 0x02 129 #endif 130 #if (OFMCLK == 120000000) 131 #define HFCGMH_VAL 0x0E 132 #define HFCGML_VAL 0x4E 133 #elif (OFMCLK == 100000000) 134 #define HFCGMH_VAL 0x0B 135 #define HFCGML_VAL 0xEC 136 #elif (OFMCLK == 96000000) 137 #define HFCGMH_VAL 0x0B 138 #define HFCGML_VAL 0x72 139 #elif (OFMCLK == 90000000) 140 #define HFCGMH_VAL 0x0A 141 #define HFCGML_VAL 0xBA 142 #elif (OFMCLK == 80000000) 143 #define HFCGMH_VAL 0x09 144 #define HFCGML_VAL 0x89 145 #elif (OFMCLK == 66000000) 146 #define HFCGMH_VAL 0x07 147 #define HFCGML_VAL 0xDE 148 #elif (OFMCLK == 50000000) 149 #define HFCGMH_VAL 0x0B 150 #define HFCGML_VAL 0xEC 151 #elif (OFMCLK == 48000000) 152 #define HFCGMH_VAL 0x0B 153 #define HFCGML_VAL 0x72 154 #else 155 #error "Unsupported OFMCLK Frequency" 156 #endif 157 158 /* Clock prescaler configurations in different series */ 159 #define VAL_HFCGP ((FPRED_VAL << 4) | AHB6DIV_VAL) 160 #if defined(FIU1DIV_VAL) 161 #define VAL_HFCBCD ((FIU1DIV_VAL << 4) | (FIUDIV_VAL << 2)) 162 #else 163 #define VAL_HFCBCD (FIUDIV_VAL << 4) 164 #endif /* FIU1DIV_VAL */ 165 #define VAL_HFCBCD1 (APB1DIV_VAL | (APB2DIV_VAL << 4)) 166 #if defined(APB4DIV_VAL) 167 #define VAL_HFCBCD2 (APB3DIV_VAL | (APB4DIV_VAL << 4)) 168 #else 169 #define VAL_HFCBCD2 APB3DIV_VAL 170 #endif /* APB4DIV_VAL */ 171 /* I3C1~I3C3 share the same configuration */ 172 #define VAL_HFCBCD3 MCLKD_SL 173 174 /** 175 * @brief Function to notify clock driver that backup the counter value of 176 * low-frequency timer before ec entered deep idle state. 177 */ 178 void npcx_clock_capture_low_freq_timer(void); 179 180 /** 181 * @brief Function to notify clock driver that compensate the counter value of 182 * system timer by low-frequency timer after ec left deep idle state. 183 * 184 */ 185 void npcx_clock_compensate_system_timer(void); 186 187 /** 188 * @brief Function to get time ticks in system sleep/deep sleep state. The unit 189 * is ticks. 190 * 191 */ 192 uint64_t npcx_clock_get_sleep_ticks(void); 193 194 /** 195 * @brief Function to configure system sleep settings. After ec received "wfi" 196 * instruction, ec will enter sleep/deep sleep state for better power 197 * consumption. 198 * 199 * @param is_deep A boolean indicating ec enters deep sleep or sleep state 200 * @param is_instant A boolean indicating 'Instant Wake-up' from deep idle is 201 * enabled 202 */ 203 void npcx_clock_control_turn_on_system_sleep(bool is_deep, bool is_instant); 204 205 /** 206 * @brief Function to turn off system sleep mode. 207 */ 208 void npcx_clock_control_turn_off_system_sleep(void); 209 210 #ifdef __cplusplus 211 } 212 #endif 213 214 #endif /* _NUVOTON_NPCX_SOC_CLOCK_H_ */ 215