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_SOC_SERIES_NPCX9)
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
52 #endif
53 
54 /*
55  * NPCX7 and later series clock tree macros:
56  * (Please refer Figure 58. for more information.)
57  *
58  * Suggestion:
59  * - OFMCLK > 50MHz, XF_RANGE should be 1, else 0.
60  * - CORE_CLK > 50MHz, AHB6DIV should be 1, else 0.
61  * - CORE_CLK > 50MHz, FIUDIV should be 1, else 0.
62  */
63 
64 /* Core domain clock */
65 #define CORE_CLK (OFMCLK / DT_PROP(DT_NODELABEL(pcc), core_prescaler))
66 /* Low Frequency clock */
67 #define LFCLK 32768
68 
69 /* FMUL clock */
70 #if (OFMCLK > 50000000)
71 #define FMCLK (OFMCLK / 2) /* FMUL clock = OFMCLK/2 if OFMCLK > 50MHz */
72 #else
73 #define FMCLK OFMCLK /* FMUL clock = OFMCLK */
74 #endif
75 
76 /* APBs source clock */
77 #define APBSRC_CLK OFMCLK
78 
79 /* AHB6 clock */
80 #if (CORE_CLK > 50000000)
81 #define AHB6DIV_VAL 1 /* AHB6_CLK = CORE_CLK/2 if CORE_CLK > 50MHz */
82 #else
83 #define AHB6DIV_VAL 0 /* AHB6_CLK = CORE_CLK */
84 #endif
85 /* FIU clock divider */
86 #if (CORE_CLK > 50000000)
87 #define FIUDIV_VAL 1 /* FIU_CLK = CORE_CLK/2 */
88 #else
89 #define FIUDIV_VAL 0 /* FIU_CLK = CORE_CLK */
90 #endif
91 
92 /* Get APB clock freq */
93 #define NPCX_APB_CLOCK(no) (APBSRC_CLK / (APB##no##DIV_VAL + 1))
94 
95 /*
96  * Frequency multiplier M/N value definitions according to the requested
97  * OFMCLK (Unit:Hz).
98  */
99 #if (OFMCLK > 50000000)
100 #define HFCGN_VAL    0x82 /* Set XF_RANGE as 1 if OFMCLK > 50MHz */
101 #else
102 #define HFCGN_VAL    0x02
103 #endif
104 #if   (OFMCLK == 100000000)
105 #define HFCGMH_VAL   0x0B
106 #define HFCGML_VAL   0xEC
107 #elif (OFMCLK == 96000000)
108 #define HFCGMH_VAL   0x0B
109 #define HFCGML_VAL   0x72
110 #elif (OFMCLK == 90000000)
111 #define HFCGMH_VAL   0x0A
112 #define HFCGML_VAL   0xBA
113 #elif (OFMCLK == 80000000)
114 #define HFCGMH_VAL   0x09
115 #define HFCGML_VAL   0x89
116 #elif (OFMCLK == 66000000)
117 #define HFCGMH_VAL   0x07
118 #define HFCGML_VAL   0xDE
119 #elif (OFMCLK == 50000000)
120 #define HFCGMH_VAL   0x0B
121 #define HFCGML_VAL   0xEC
122 #elif (OFMCLK == 48000000)
123 #define HFCGMH_VAL   0x0B
124 #define HFCGML_VAL   0x72
125 #elif (OFMCLK == 40000000)
126 #define HFCGMH_VAL   0x09
127 #define HFCGML_VAL   0x89
128 #elif (OFMCLK == 33000000)
129 #define HFCGMH_VAL   0x07
130 #define HFCGML_VAL   0xDE
131 #else
132 #error "Unsupported OFMCLK Frequency"
133 #endif
134 
135 /**
136  * @brief Function to notify clock driver that backup the counter value of
137  *        low-frequency timer before ec entered deep idle state.
138  */
139 void npcx_clock_capture_low_freq_timer(void);
140 
141 /**
142  * @brief Function to notify clock driver that compensate the counter value of
143  *        system timer by low-frequency timer after ec left deep idle state.
144  *
145  */
146 void npcx_clock_compensate_system_timer(void);
147 
148 /**
149  * @brief Function to get time ticks in system sleep/deep sleep state. The unit
150  *        is ticks.
151  *
152  */
153 uint64_t npcx_clock_get_sleep_ticks(void);
154 
155 /**
156  * @brief Function to configure system sleep settings. After ec received "wfi"
157  *        instruction, ec will enter sleep/deep sleep state for better power
158  *        consumption.
159  *
160  * @param is_deep A boolean indicating ec enters deep sleep or sleep state
161  * @param is_instant A boolean indicating 'Instant Wake-up' from deep idle is
162  *                   enabled
163  */
164 void npcx_clock_control_turn_on_system_sleep(bool is_deep, bool is_instant);
165 
166 /**
167  * @brief Function to turn off system sleep mode.
168  */
169 void npcx_clock_control_turn_off_system_sleep(void);
170 
171 #ifdef __cplusplus
172 }
173 #endif
174 
175 #endif /* _NUVOTON_NPCX_SOC_CLOCK_H_ */
176