1 /*
2 * Copyright (c) 2018 Synopsys, Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/devicetree.h>
8 #include "sysconf.h"
9
10 /* default system clock */
11 #define SYSCLK_DEFAULT_IOSC_HZ MHZ(16)
12
13 #define PLL_CLK_IN (SYSCLK_DEFAULT_IOSC_HZ / 1000000) /* PLL clock in */
14
15
16 #define sysconf_reg_ptr ((sysconf_reg_t *)(DT_REG_ADDR(DT_NODELABEL(sysconf))))
17
18
19 typedef struct pll_conf {
20 uint32_t fout;
21 uint32_t pll;
22 } pll_conf_t;
23
24 #define PLL_CONF_VAL(n, m, od) \
25 (((n) << PLLCON_BIT_OFFSET_N) | \
26 ((m) << (PLLCON_BIT_OFFSET_M)) | \
27 ((od) << PLLCON_BIT_OFFSET_OD))
28
29
30 /* the following configuration is based on Fin = 16 Mhz */
31 static const pll_conf_t pll_configuration[] = {
32 {100, PLL_CONF_VAL(1, 25, 2)}, /* 100 Mhz */
33 {50, PLL_CONF_VAL(1, 25, 3)}, /* 50 Mhz */
34 {150, PLL_CONF_VAL(4, 75, 1)}, /* 150 Mhz */
35 {75, PLL_CONF_VAL(4, 75, 2)}, /* 75 Mhz */
36 {25, PLL_CONF_VAL(2, 25, 3)}, /* 25 Mhz */
37 {72, PLL_CONF_VAL(8, 144, 2)}, /* 72 Mhz */
38 {144, PLL_CONF_VAL(8, 144, 1)}, /* 144 Mhz */
39 };
40
41
42 /**
43 * PLL Fout = Fin * M/ (N *n NO)
44 *
45 * Fref = Fin / N; Fvco = Fref * M Fout = Fvco / NO
46 *
47 * N = input divider value (1, 2, 3 … 15)
48 * M = feedback divider value (4, 5, 6 … 16383)
49 * NO = output divider value (1, 2, 4, or 8)
50 *
51 * 1 Mhz <= Fref <= 50 Mhz
52 * 200 Mhz <= Fvco <= 400 Mhz
53 *
54 */
arc_iot_pll_conf_reg(uint32_t val)55 void arc_iot_pll_conf_reg(uint32_t val)
56 {
57
58 sysconf_reg_ptr->CLKSEL = CLKSEL_EXT_16M;
59 /* 0x52000000 is not described in spec. */
60 sysconf_reg_ptr->PLLCON = val | (0x52000000);
61
62 sysconf_reg_ptr->PLLCON = val | (1 << PLLCON_BIT_OFFSET_PLLRST);
63 sysconf_reg_ptr->PLLCON = val & (~(1 << PLLCON_BIT_OFFSET_PLLRST));
64
65 while (!(sysconf_reg_ptr->PLLSTAT & (1 << PLLSTAT_BIT_OFFSET_PLLSTB))) {
66 ;
67 }
68
69 sysconf_reg_ptr->CLKSEL = CLKSEL_PLL;
70 /* from AHB_CLK_DIVIDER, not from DVFSS&PMC */
71 sysconf_reg_ptr->AHBCLKDIV_SEL |= 1;
72 /* AHB clk divisor = 1 */
73 sysconf_reg_ptr->AHBCLKDIV = 0x1;
74 }
75
arc_iot_pll_fout_config(uint32_t freq)76 int32_t arc_iot_pll_fout_config(uint32_t freq)
77 {
78 uint32_t i;
79
80 if (freq == PLL_CLK_IN) {
81 sysconf_reg_ptr->CLKSEL = CLKSEL_EXT_16M;
82 }
83
84 for (i = 0U; i < ARRAY_SIZE(pll_configuration); i++) {
85 if (pll_configuration[i].fout == freq) {
86 break;
87 }
88 }
89
90 if (i >= ARRAY_SIZE(pll_configuration)) {
91 return -1;
92 }
93
94 /* config eflash clk, must be < 100 Mhz */
95 if (freq > 100) {
96 arc_iot_eflash_clk_div(2);
97 } else {
98 arc_iot_eflash_clk_div(1);
99 }
100
101 arc_iot_pll_conf_reg(pll_configuration[i].pll);
102
103 return 0;
104 }
105
arc_iot_ahb_clk_divisor(uint8_t div)106 void arc_iot_ahb_clk_divisor(uint8_t div)
107 {
108 sysconf_reg_ptr->AHBCLKDIV = div;
109 }
110
arc_iot_ahb_clk_enable(uint8_t dev)111 void arc_iot_ahb_clk_enable(uint8_t dev)
112 {
113 if (dev > AHBCLKEN_BIT_SDIO) {
114 return;
115 }
116
117 sysconf_reg_ptr->AHBCLKEN |= (1 << dev);
118 }
119
arc_iot_ahb_clk_disable(uint8_t dev)120 void arc_iot_ahb_clk_disable(uint8_t dev)
121 {
122 if (dev > AHBCLKEN_BIT_SDIO) {
123 return;
124 }
125
126 sysconf_reg_ptr->AHBCLKEN &= (~(1 << dev));
127 }
128
arc_iot_apb_clk_divisor(uint8_t div)129 void arc_iot_apb_clk_divisor(uint8_t div)
130 {
131 sysconf_reg_ptr->APBCLKDIV = div;
132 }
133
arc_iot_apb_clk_enable(uint8_t dev)134 void arc_iot_apb_clk_enable(uint8_t dev)
135 {
136 if (dev > APBCLKEN_BIT_I3C) {
137 return;
138 }
139
140 sysconf_reg_ptr->APBCLKEN |= (1 << dev);
141 }
142
arc_iot_apb_clk_disable(uint8_t dev)143 void arc_iot_apb_clk_disable(uint8_t dev)
144 {
145 if (dev > APBCLKEN_BIT_I3C) {
146 return;
147 }
148
149 sysconf_reg_ptr->APBCLKEN &= (~(1 << dev));
150 }
151
arc_iot_dio_clk_divisor(uint8_t div)152 void arc_iot_dio_clk_divisor(uint8_t div)
153 {
154 sysconf_reg_ptr->SDIO_REFCLK_DIV;
155 }
156
arc_iot_spi_master_clk_divisor(uint8_t id,uint8_t div)157 void arc_iot_spi_master_clk_divisor(uint8_t id, uint8_t div)
158 {
159 if (id == SPI_MASTER_0) {
160 sysconf_reg_ptr->SPI_MST_CLKDIV =
161 (sysconf_reg_ptr->SPI_MST_CLKDIV & 0xffffff00) | div;
162 } else if (id == SPI_MASTER_1) {
163 sysconf_reg_ptr->SPI_MST_CLKDIV =
164 (sysconf_reg_ptr->SPI_MST_CLKDIV & 0xffff00ff) | (div << 8);
165 } else if (id == SPI_MASTER_2) {
166 sysconf_reg_ptr->SPI_MST_CLKDIV =
167 (sysconf_reg_ptr->SPI_MST_CLKDIV & 0xff00ffff) | (div << 16);
168 }
169 }
170
arc_iot_gpio8b_dbclk_div(uint8_t bank,uint8_t div)171 void arc_iot_gpio8b_dbclk_div(uint8_t bank, uint8_t div)
172 {
173 if (bank == GPIO8B_BANK0) {
174 sysconf_reg_ptr->GPIO8B_DBCLK_DIV =
175 (sysconf_reg_ptr->GPIO8B_DBCLK_DIV & 0xffffff00) | div;
176 } else if (bank == GPIO8B_BANK1) {
177 sysconf_reg_ptr->GPIO8B_DBCLK_DIV =
178 (sysconf_reg_ptr->GPIO8B_DBCLK_DIV & 0xffff00ff) | (div << 8);
179 } else if (bank == GPIO8B_BANK2) {
180 sysconf_reg_ptr->GPIO8B_DBCLK_DIV =
181 (sysconf_reg_ptr->GPIO8B_DBCLK_DIV & 0xff00ffff) | (div << 16);
182 } else if (bank == GPIO8B_BANK3) {
183 sysconf_reg_ptr->GPIO8B_DBCLK_DIV =
184 (sysconf_reg_ptr->GPIO8B_DBCLK_DIV & 0x00ffffff) | (div << 24);
185 }
186 }
187
arc_iot_gpio4b_dbclk_div(uint8_t bank,uint8_t div)188 void arc_iot_gpio4b_dbclk_div(uint8_t bank, uint8_t div)
189 {
190 if (bank == GPIO4B_BANK0) {
191 sysconf_reg_ptr->GPIO4B_DBCLK_DIV =
192 (sysconf_reg_ptr->GPIO4B_DBCLK_DIV & 0xffffff00) | div;
193 } else if (bank == GPIO4B_BANK1) {
194 sysconf_reg_ptr->GPIO4B_DBCLK_DIV =
195 (sysconf_reg_ptr->GPIO4B_DBCLK_DIV & 0xffff00ff) | (div << 8);
196 } else if (bank == GPIO4B_BANK2) {
197 sysconf_reg_ptr->GPIO4B_DBCLK_DIV =
198 (sysconf_reg_ptr->GPIO4B_DBCLK_DIV & 0xff00ffff) | (div << 16);
199 }
200 }
201
arc_iot_i2s_tx_clk_div(uint8_t div)202 void arc_iot_i2s_tx_clk_div(uint8_t div)
203 {
204 sysconf_reg_ptr->I2S_TX_SCLKDIV = div;
205 }
206
arc_iot_i2s_rx_clk_div(uint8_t div)207 void arc_iot_i2s_rx_clk_div(uint8_t div)
208 {
209 sysconf_reg_ptr->I2S_RX_SCLKDIV = div;
210 }
211
arc_iot_i2s_rx_clk_sel(uint8_t sel)212 void arc_iot_i2s_rx_clk_sel(uint8_t sel)
213 {
214 sysconf_reg_ptr->I2S_RX_SCLKSEL = sel;
215 }
216
arc_iot_syscon_reset(void)217 void arc_iot_syscon_reset(void)
218 {
219 sysconf_reg_ptr->RSTCON = 0x55AA6699;
220 }
221
arc_iot_is_poweron_rst(void)222 uint32_t arc_iot_is_poweron_rst(void)
223 {
224 if (sysconf_reg_ptr->RSTSTAT & SYS_RST_SOFTWARE_ON) {
225 return 0;
226 } else {
227 return 1;
228 }
229 }
230
arc_iot_dvfs_clk_divisor(uint8_t level,uint8_t div)231 void arc_iot_dvfs_clk_divisor(uint8_t level, uint8_t div)
232 {
233 if (level == DVFS_PERF_LEVEL0) {
234 sysconf_reg_ptr->DVFS_CLKDIV =
235 (sysconf_reg_ptr->DVFS_CLKDIV & 0xffffff00) | div;
236 } else if (level == DVFS_PERF_LEVEL1) {
237 sysconf_reg_ptr->DVFS_CLKDIV =
238 (sysconf_reg_ptr->DVFS_CLKDIV & 0xffff00ff) | (div << 8);
239 } else if (level == DVFS_PERF_LEVEL2) {
240 sysconf_reg_ptr->DVFS_CLKDIV =
241 (sysconf_reg_ptr->DVFS_CLKDIV & 0xff00ffff) | (div << 16);
242 } else if (level == DVFS_PERF_LEVEL3) {
243 sysconf_reg_ptr->DVFS_CLKDIV =
244 (sysconf_reg_ptr->DVFS_CLKDIV & 0x00ffffff) | (div << 24);
245 }
246 }
247
arc_iot_dvfs_vdd_config(uint8_t level,uint8_t val)248 void arc_iot_dvfs_vdd_config(uint8_t level, uint8_t val)
249 {
250 val &= 0xf;
251
252 if (level == DVFS_PERF_LEVEL0) {
253 sysconf_reg_ptr->DVFS_VDDSET =
254 (sysconf_reg_ptr->DVFS_VDDSET & 0xfffffff0) | val;
255 } else if (level == DVFS_PERF_LEVEL1) {
256 sysconf_reg_ptr->DVFS_VDDSET =
257 (sysconf_reg_ptr->DVFS_VDDSET & 0xffffff0f) | (val << 4);
258 } else if (level == DVFS_PERF_LEVEL2) {
259 sysconf_reg_ptr->DVFS_VDDSET =
260 (sysconf_reg_ptr->DVFS_VDDSET & 0xfffff0ff) | (val << 8);
261 } else if (level == DVFS_PERF_LEVEL3) {
262 sysconf_reg_ptr->DVFS_CLKDIV =
263 (sysconf_reg_ptr->DVFS_CLKDIV & 0xffff0fff) | (val << 12);
264 }
265 }
266
arc_iot_dvfs_vwtime_config(uint8_t time)267 void arc_iot_dvfs_vwtime_config(uint8_t time)
268 {
269 sysconf_reg_ptr->DVFS_VWTIME = time;
270 }
271
arc_iot_pmc_pwwtime_config(uint8_t time)272 void arc_iot_pmc_pwwtime_config(uint8_t time)
273 {
274 sysconf_reg_ptr->PMC_PUWTIME = time;
275 }
276
arc_iot_uart3_clk_divisor(uint8_t div)277 void arc_iot_uart3_clk_divisor(uint8_t div)
278 {
279 sysconf_reg_ptr->UART3SCLK_DIV = div;
280 }
281
arc_iot_reset_powerdown_vector(uint32_t addr)282 void arc_iot_reset_powerdown_vector(uint32_t addr)
283 {
284 sysconf_reg_ptr->RESET_PD_VECTOR = addr;
285 }
286
arc_iot_pwm_timer_pause(uint32_t id,uint32_t pause)287 void arc_iot_pwm_timer_pause(uint32_t id, uint32_t pause)
288 {
289 uint32_t val = sysconf_reg_ptr->TIMER_PAUSE;
290
291 if (id > PWM_TIMER5) {
292 return;
293 }
294
295 if (pause) {
296 val |= (1 << id);
297 } else {
298 val &= (~(1 << id));
299 }
300
301 sysconf_reg_ptr->TIMER_PAUSE = val;
302 }
303
arc_iot_eflash_clk_div(uint8_t div)304 void arc_iot_eflash_clk_div(uint8_t div)
305 {
306 sysconf_reg_ptr->AHBCLKDIV |= (div << 8);
307 }
308