1 /*
2  * Copyright (c) 2021 Telink Semiconductor
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "sys.h"
8 #include "clock.h"
9 #include <zephyr/init.h>
10 #include <zephyr/devicetree.h>
11 
12 /* Software reset defines */
13 #define reg_reset                   REG_ADDR8(0x1401ef)
14 #define SOFT_RESET                  0x20u
15 
16 /* List of supported CCLK frequencies */
17 #define CLK_16MHZ                   16000000u
18 #define CLK_24MHZ                   24000000u
19 #define CLK_32MHZ                   32000000u
20 #define CLK_48MHZ                   48000000u
21 #define CLK_64MHZ                   64000000u
22 #define CLK_96MHZ                   96000000u
23 
24 /* Define 48 MHz and 96 MHz CCLK clock options (not present in HAL) */
25 #define CCLK_64M_HCLK_32M_PCLK_16M  clock_init(PLL_CLK_192M,	  \
26 					       PAD_PLL_DIV,	  \
27 					       PLL_DIV3_TO_CCLK,  \
28 					       CCLK_DIV2_TO_HCLK, \
29 					       HCLK_DIV2_TO_PCLK, \
30 					       PLL_DIV4_TO_MSPI_CLK)
31 
32 #define CCLK_96M_HCLK_48M_PCLK_24M  clock_init(PLL_CLK_192M,	  \
33 					       PAD_PLL_DIV,	  \
34 					       PLL_DIV2_TO_CCLK,  \
35 					       CCLK_DIV2_TO_HCLK, \
36 					       HCLK_DIV2_TO_PCLK, \
37 					       PLL_DIV4_TO_MSPI_CLK)
38 
39 /* Power Mode value */
40 #if DT_ENUM_IDX(DT_NODELABEL(power), power_mode) == 0
41 	#define POWER_MODE      LDO_1P4_LDO_1P8
42 #elif DT_ENUM_IDX(DT_NODELABEL(power), power_mode) == 1
43 	#define POWER_MODE      DCDC_1P4_LDO_1P8
44 #elif DT_ENUM_IDX(DT_NODELABEL(power), power_mode) == 2
45 	#define POWER_MODE      DCDC_1P4_DCDC_1P8
46 #else
47 	#error "Wrong value for power-mode parameter"
48 #endif
49 
50 /* Vbat Type value */
51 #if DT_ENUM_IDX(DT_NODELABEL(power), vbat_type) == 0
52 	#define VBAT_TYPE       VBAT_MAX_VALUE_LESS_THAN_3V6
53 #elif DT_ENUM_IDX(DT_NODELABEL(power), vbat_type) == 1
54 	#define VBAT_TYPE       VBAT_MAX_VALUE_GREATER_THAN_3V6
55 #else
56 	#error "Wrong value for vbat-type parameter"
57 #endif
58 
59 /* Check System Clock value. */
60 #if ((DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency) != CLK_16MHZ) &&	 \
61 	(DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency) != CLK_24MHZ) && \
62 	(DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency) != CLK_32MHZ) && \
63 	(DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency) != CLK_48MHZ) && \
64 	(DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency) != CLK_64MHZ) && \
65 	(DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency) != CLK_96MHZ))
66 	#error "Unsupported clock-frequency. Supported values: 16, 24, 32, 48, 64 and 96 MHz"
67 #endif
68 
69 /**
70  * @brief Perform basic initialization at boot.
71  *
72  * @return 0
73  */
soc_early_init_hook(void)74 void soc_early_init_hook(void)
75 {
76 	unsigned int cclk = DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency);
77 
78 
79 	/* system init */
80 	sys_init(POWER_MODE, VBAT_TYPE);
81 
82 	/* clocks init: CCLK, HCLK, PCLK */
83 	switch (cclk) {
84 	case CLK_16MHZ:
85 		CCLK_16M_HCLK_16M_PCLK_16M;
86 		break;
87 
88 	case CLK_24MHZ:
89 		CCLK_24M_HCLK_24M_PCLK_24M;
90 		break;
91 
92 	case CLK_32MHZ:
93 		CCLK_32M_HCLK_32M_PCLK_16M;
94 		break;
95 
96 	case CLK_48MHZ:
97 		CCLK_48M_HCLK_48M_PCLK_24M;
98 		break;
99 
100 	case CLK_64MHZ:
101 		CCLK_64M_HCLK_32M_PCLK_16M;
102 		break;
103 
104 	case CLK_96MHZ:
105 		CCLK_96M_HCLK_48M_PCLK_24M;
106 		break;
107 	}
108 
109 	/* Init Machine Timer source clock: 32 KHz RC */
110 	clock_32k_init(CLK_32K_RC);
111 	clock_cal_32k_rc();
112 }
113 
114 /**
115  * @brief Reset the system.
116  */
sys_arch_reboot(int type)117 void sys_arch_reboot(int type)
118 {
119 	ARG_UNUSED(type);
120 
121 	reg_reset = SOFT_RESET;
122 }
123