1 /*
2 * Copyright (c) 2022 HPMicro
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "board.h"
17 #include <hpm_pllctl_drv.h>
18 #include <hpm_enet_drv.h>
19 #include <hpm_gpio_drv.h>
20 #include <hpm_pmp_drv.h>
21 /**
22 * @brief FLASH configuration option definitions:
23 * option[0]:
24 * [31:16] 0xfcf9 - FLASH configuration option tag
25 * [15:4] 0 - Reserved
26 * [3:0] option words (exclude option[0])
27 * option[1]:
28 * [31:28] Flash probe type
29 * 0 - SFDP SDR / 1 - SFDP DDR
30 * 2 - 1-4-4 Read (0xEB, 24-bit address) / 3 - 1-2-2 Read(0xBB, 24-bit address)
31 * 4 - HyperFLASH 1.8V / 5 - HyperFLASH 3V
32 * 6 - OctaBus DDR (SPI -> OPI DDR)
33 * 8 - Xccela DDR (SPI -> OPI DDR)
34 * 10 - EcoXiP DDR (SPI -> OPI DDR)
35 * [27:24] Command Pads after Power-on Reset
36 * 0 - SPI / 1 - DPI / 2 - QPI / 3 - OPI
37 * [23:20] Command Pads after Configuring FLASH
38 * 0 - SPI / 1 - DPI / 2 - QPI / 3 - OPI
39 * [19:16] Quad Enable Sequence (for the device support SFDP 1.0 only)
40 * 0 - Not needed
41 * 1 - QE bit is at bit 6 in Status Register 1
42 * 2 - QE bit is at bit1 in Status Register 2
43 * 3 - QE bit is at bit7 in Status Register 2
44 * 4 - QE bit is at bit1 in Status Register 2 and should be programmed by 0x31
45 * [15:8] Dummy cycles
46 * 0 - Auto-probed / detected / default value
47 * Others - User specified value, for DDR read, the dummy cycles should be 2 * cycles on FLASH datasheet
48 * [7:4] Misc.
49 * 0 - Not used
50 * 1 - SPI mode
51 * 2 - Internal loopback
52 * 3 - External DQS
53 * [3:0] Frequency option
54 * 1 - 30MHz / 2 - 50MHz / 3 - 66MHz / 4 - 80MHz / 5 - 100MHz / 6 - 120MHz / 7 - 133MHz / 8 - 166MHz
55 *
56 * option[2] (Effective only if the bit[3:0] in option[0] > 1)
57 * [31:20] Reserved
58 * [19:16] IO voltage
59 * 0 - 3V / 1 - 1.8V
60 * [15:12] Pin group
61 * 0 - 1st group / 1 - 2nd group
62 * [11:8] Connection selection
63 * 0 - CA_CS0 / 1 - CB_CS0 / 2 - CA_CS0 + CB_CS0 (Two FLASH connected to CA and CB respectively)
64 * [7:0] Drive Strength
65 * 0 - Default value
66 * option[3] (Effective only if the bit[3:0] in option[0] > 2, required only for the QSPI NOR FLASH that not supports
67 * JESD216)
68 * [31:16] reserved
69 * [15:12] Sector Erase Command Option, not required here
70 * [11:8] Sector Size Option, not required here
71 * [7:0] Flash Size Option
72 * 0 - 4MB / 1 - 8MB / 2 - 16MB
73 */
74 #if defined(FLASH_XIP) && FLASH_XIP
75 __attribute__ ((section(".nor_cfg_option"))) const uint32_t option[4] = {0xfcf90001, 0x00000007, 0x0, 0x0};
76 #endif
77
board_delay_us(uint32_t us)78 void board_delay_us(uint32_t us)
79 {
80 clock_cpu_delay_us(us);
81 }
82
board_delay_ms(uint32_t ms)83 void board_delay_ms(uint32_t ms)
84 {
85 clock_cpu_delay_ms(ms);
86 }
87
board_init_clock(void)88 void board_init_clock(void)
89 {
90 uint32_t cpu0_freq = clock_get_frequency(clock_cpu0);
91 if (cpu0_freq == PLLCTL_SOC_PLL_REFCLK_FREQ) {
92 /* Configure the External OSC ramp-up time: ~9ms */
93 pllctl_xtal_set_rampup_time(HPM_PLLCTL, 32UL * 1000UL * 9U);
94
95 /* Select clock setting preset1 */
96 sysctl_clock_set_preset(HPM_SYSCTL, sysctl_preset_1);
97 }
98
99 /* Add most Clocks to group 0 */
100 clock_add_to_group(clock_cpu0, 0);
101 clock_add_to_group(clock_mchtmr0, 0);
102 clock_add_to_group(clock_axi0, 0);
103 clock_add_to_group(clock_axi1, 0);
104 clock_add_to_group(clock_axi2, 0);
105 clock_add_to_group(clock_ahb, 0);
106 clock_add_to_group(clock_dram, 0);
107 clock_add_to_group(clock_xpi0, 0);
108 clock_add_to_group(clock_xpi1, 0);
109 clock_add_to_group(clock_gptmr0, 0);
110 clock_add_to_group(clock_gptmr1, 0);
111 clock_add_to_group(clock_gptmr2, 0);
112 clock_add_to_group(clock_gptmr3, 0);
113 clock_add_to_group(clock_gptmr4, 0);
114 clock_add_to_group(clock_gptmr5, 0);
115 clock_add_to_group(clock_gptmr6, 0);
116 clock_add_to_group(clock_gptmr7, 0);
117 clock_add_to_group(clock_uart0, 0);
118 clock_add_to_group(clock_uart1, 0);
119 clock_add_to_group(clock_uart2, 0);
120 clock_add_to_group(clock_uart3, 0);
121 clock_add_to_group(clock_uart13, 0);
122 clock_add_to_group(clock_i2c0, 0);
123 clock_add_to_group(clock_i2c1, 0);
124 clock_add_to_group(clock_i2c2, 0);
125 clock_add_to_group(clock_i2c3, 0);
126 clock_add_to_group(clock_spi0, 0);
127 clock_add_to_group(clock_spi1, 0);
128 clock_add_to_group(clock_spi2, 0);
129 clock_add_to_group(clock_spi3, 0);
130 clock_add_to_group(clock_can0, 0);
131 clock_add_to_group(clock_can1, 0);
132 clock_add_to_group(clock_can2, 0);
133 clock_add_to_group(clock_can3, 0);
134 clock_add_to_group(clock_display, 0);
135 clock_add_to_group(clock_sdxc0, 0);
136 clock_add_to_group(clock_sdxc1, 0);
137 clock_add_to_group(clock_camera0, 0);
138 clock_add_to_group(clock_camera1, 0);
139 clock_add_to_group(clock_ptpc, 0);
140 clock_add_to_group(clock_ref0, 0);
141 clock_add_to_group(clock_ref1, 0);
142 clock_add_to_group(clock_watchdog0, 0);
143 clock_add_to_group(clock_watchdog1, 0);
144 clock_add_to_group(clock_watchdog2, 0);
145 clock_add_to_group(clock_watchdog3, 0);
146 clock_add_to_group(clock_pwdg, 0);
147 clock_add_to_group(clock_eth0, 0);
148 clock_add_to_group(clock_eth1, 0);
149 clock_add_to_group(clock_sdp, 0);
150 clock_add_to_group(clock_xdma, 0);
151 clock_add_to_group(clock_ram0, 0);
152 clock_add_to_group(clock_ram1, 0);
153 clock_add_to_group(clock_usb0, 0);
154 clock_add_to_group(clock_usb1, 0);
155 clock_add_to_group(clock_jpeg, 0);
156 clock_add_to_group(clock_pdma, 0);
157 clock_add_to_group(clock_kman, 0);
158 clock_add_to_group(clock_gpio, 0);
159 clock_add_to_group(clock_mbx0, 0);
160 clock_add_to_group(clock_hdma, 0);
161 clock_add_to_group(clock_rng, 0);
162 clock_add_to_group(clock_mot0, 0);
163 clock_add_to_group(clock_mot1, 0);
164 clock_add_to_group(clock_mot2, 0);
165 clock_add_to_group(clock_mot3, 0);
166 clock_add_to_group(clock_acmp, 0);
167 clock_add_to_group(clock_dao, 0);
168 clock_add_to_group(clock_msyn, 0);
169 clock_add_to_group(clock_lmm0, 0);
170 clock_add_to_group(clock_lmm1, 0);
171
172 clock_add_to_group(clock_adc0, 0);
173 clock_add_to_group(clock_adc1, 0);
174 clock_add_to_group(clock_adc2, 0);
175 clock_add_to_group(clock_adc3, 0);
176
177 clock_add_to_group(clock_i2s0, 0);
178 clock_add_to_group(clock_i2s1, 0);
179 clock_add_to_group(clock_i2s2, 0);
180 clock_add_to_group(clock_i2s3, 0);
181
182 /* Add the CPU1 clock to Group1 */
183 clock_add_to_group(clock_mchtmr1, 1);
184 clock_add_to_group(clock_mbx1, 1);
185
186 /* Connect Group0 to CPU0 */
187 clock_connect_group_to_cpu(0, 0);
188
189 if (status_success != pllctl_init_int_pll_with_freq(HPM_PLLCTL, 0, BOARD_CPU_FREQ)) {
190 printf("Failed to set pll0_clk0 to %ldHz\n", BOARD_CPU_FREQ);
191 while(1);
192 }
193
194 clock_set_source_divider(clock_cpu0, clk_src_pll0_clk0, 1);
195 clock_set_source_divider(clock_cpu1, clk_src_pll0_clk0, 1);
196 /* Connect Group1 to CPU1 */
197 clock_connect_group_to_cpu(1, 1);
198
199 clock_update_core_clock();
200 }
201
board_init_pmp(void)202 void board_init_pmp(void)
203 {
204 extern uint32_t __noncacheable_start__[];
205 extern uint32_t __noncacheable_end__[];
206
207 uint32_t start_addr = (uint32_t) __noncacheable_start__;
208 uint32_t end_addr = (uint32_t) __noncacheable_end__;
209 uint32_t length = end_addr - start_addr;
210
211 if (length == 0) {
212 return;
213 }
214
215 /* Ensure the address and the length are power of 2 aligned */
216 assert((length & (length - 1U)) == 0U);
217 assert((start_addr & (length - 1U)) == 0U);
218
219 pmp_entry_t pmp_entry[1];
220 pmp_entry[0].pmp_addr = PMP_NAPOT_ADDR(start_addr, length);
221 pmp_entry[0].pmp_cfg.val = PMP_CFG(READ_EN, WRITE_EN, EXECUTE_EN, ADDR_MATCH_NAPOT, REG_UNLOCK);
222 pmp_entry[0].pma_addr = PMA_NAPOT_ADDR(start_addr, length);
223 pmp_entry[0].pma_cfg.val = PMA_CFG(ADDR_MATCH_NAPOT, MEM_TYPE_MEM_NON_CACHE_BUF, AMO_EN);
224
225 pmp_config(&pmp_entry[0], ARRAY_SIZE(pmp_entry));
226 }
227
board_init_ahb(void)228 void board_init_ahb(void)
229 {
230 clock_set_source_divider(clock_ahb, clk_src_pll1_clk1, 2);/*200m hz*/
231 }
232
board_init(void)233 void board_init(void)
234 {
235 board_init_clock();
236 sysctl_set_cpu_lp_mode(HPM_SYSCTL, HPM_CORE0, cpu_lp_mode_ungate_cpu_clock);
237 board_init_pmp();
238 board_init_ahb();
239 }
240
board_print_clock_freq(void)241 void board_print_clock_freq(void)
242 {
243 printf("==============================\r\n");
244 printf(" %s clock summary\r\n", "HPM6750EVK2");
245 printf("==============================\r\n");
246 printf("cpu0:\t\t %dHz\r\n", clock_get_frequency(clock_cpu0));
247 printf("cpu1:\t\t %dHz\r\n", clock_get_frequency(clock_cpu1));
248 printf("axi0:\t\t %dHz\r\n", clock_get_frequency(clock_axi0));
249 printf("axi1:\t\t %dHz\r\n", clock_get_frequency(clock_axi1));
250 printf("axi2:\t\t %dHz\r\n", clock_get_frequency(clock_axi2));
251 printf("ahb:\t\t %dHz\r\n", clock_get_frequency(clock_ahb));
252 printf("mchtmr0:\t %dHz\r\n", clock_get_frequency(clock_mchtmr0));
253 printf("mchtmr1:\t %dHz\r\n", clock_get_frequency(clock_mchtmr1));
254 printf("xpi0:\t\t %dHz\r\n", clock_get_frequency(clock_xpi0));
255 printf("xpi1:\t\t %dHz\r\n", clock_get_frequency(clock_xpi1));
256 printf("dram:\t\t %dHz\r\n", clock_get_frequency(clock_dram));
257 printf("display:\t %dHz\r\n", clock_get_frequency(clock_display));
258 printf("cam0:\t\t %dHz\r\n", clock_get_frequency(clock_camera0));
259 printf("cam1:\t\t %dHz\r\n", clock_get_frequency(clock_camera1));
260 printf("jpeg:\t\t %dHz\r\n", clock_get_frequency(clock_jpeg));
261 printf("pdma:\t\t %dHz\r\n", clock_get_frequency(clock_pdma));
262 printf("==============================\r\n");
263 }
264
board_print_banner(void)265 void board_print_banner(void)
266 {
267 const uint8_t banner[] = {"\n\
268 ----------------------------------------------------------------------\r\n\
269 $$\\ $$\\ $$$$$$$\\ $$\\ $$\\ $$\\\r\n\
270 $$ | $$ |$$ __$$\\ $$$\\ $$$ |\\__|\r\n\
271 $$ | $$ |$$ | $$ |$$$$\\ $$$$ |$$\\ $$$$$$$\\ $$$$$$\\ $$$$$$\\\r\n\
272 $$$$$$$$ |$$$$$$$ |$$\\$$\\$$ $$ |$$ |$$ _____|$$ __$$\\ $$ __$$\\\r\n\
273 $$ __$$ |$$ ____/ $$ \\$$$ $$ |$$ |$$ / $$ | \\__|$$ / $$ |\r\n\
274 $$ | $$ |$$ | $$ |\\$ /$$ |$$ |$$ | $$ | $$ | $$ |\r\n\
275 $$ | $$ |$$ | $$ | \\_/ $$ |$$ |\\$$$$$$$\\ $$ | \\$$$$$$ |\r\n\
276 \\__| \\__|\\__| \\__| \\__|\\__| \\_______|\\__| \\______/\r\n\
277 ----------------------------------------------------------------------\r\n"};
278 printf("%s", banner);
279 }
280
init_enet_pins(ENET_Type * ptr)281 static void init_enet_pins(ENET_Type *ptr)
282 {
283 if (ptr == HPM_ENET0) {
284 HPM_IOC->PAD[IOC_PAD_PF00].FUNC_CTL = IOC_PF00_FUNC_CTL_GPIO_F_00;
285
286 HPM_IOC->PAD[IOC_PAD_PE22].FUNC_CTL = IOC_PE22_FUNC_CTL_ETH0_MDC;
287 HPM_IOC->PAD[IOC_PAD_PE23].FUNC_CTL = IOC_PE23_FUNC_CTL_ETH0_MDIO;
288
289 HPM_IOC->PAD[IOC_PAD_PD31].FUNC_CTL = IOC_PD31_FUNC_CTL_ETH0_RXD_0;
290 HPM_IOC->PAD[IOC_PAD_PE04].FUNC_CTL = IOC_PE04_FUNC_CTL_ETH0_RXD_1;
291 HPM_IOC->PAD[IOC_PAD_PE02].FUNC_CTL = IOC_PE02_FUNC_CTL_ETH0_RXD_2;
292 HPM_IOC->PAD[IOC_PAD_PE07].FUNC_CTL = IOC_PE07_FUNC_CTL_ETH0_RXD_3;
293 HPM_IOC->PAD[IOC_PAD_PE03].FUNC_CTL = IOC_PE03_FUNC_CTL_ETH0_RXCK;
294 HPM_IOC->PAD[IOC_PAD_PD30].FUNC_CTL = IOC_PD30_FUNC_CTL_ETH0_RXDV;
295
296 HPM_IOC->PAD[IOC_PAD_PE06].FUNC_CTL = IOC_PE06_FUNC_CTL_ETH0_TXD_0;
297 HPM_IOC->PAD[IOC_PAD_PD29].FUNC_CTL = IOC_PD29_FUNC_CTL_ETH0_TXD_1;
298 HPM_IOC->PAD[IOC_PAD_PD28].FUNC_CTL = IOC_PD28_FUNC_CTL_ETH0_TXD_2;
299 HPM_IOC->PAD[IOC_PAD_PE05].FUNC_CTL = IOC_PE05_FUNC_CTL_ETH0_TXD_3;
300 HPM_IOC->PAD[IOC_PAD_PE01].FUNC_CTL = IOC_PE01_FUNC_CTL_ETH0_TXCK;
301 HPM_IOC->PAD[IOC_PAD_PE00].FUNC_CTL = IOC_PE00_FUNC_CTL_ETH0_TXEN;
302 } else if (ptr == HPM_ENET1) {
303 HPM_IOC->PAD[IOC_PAD_PE26].FUNC_CTL = IOC_PE26_FUNC_CTL_GPIO_E_26;
304
305 HPM_IOC->PAD[IOC_PAD_PD11].FUNC_CTL = IOC_PD11_FUNC_CTL_ETH1_MDC;
306 HPM_IOC->PAD[IOC_PAD_PD14].FUNC_CTL = IOC_PD14_FUNC_CTL_ETH1_MDIO;
307
308 HPM_IOC->PAD[IOC_PAD_PE20].FUNC_CTL = IOC_PE20_FUNC_CTL_ETH1_RXD_0;
309 HPM_IOC->PAD[IOC_PAD_PE18].FUNC_CTL = IOC_PE18_FUNC_CTL_ETH1_RXD_1;
310 HPM_IOC->PAD[IOC_PAD_PE15].FUNC_CTL = IOC_PE15_FUNC_CTL_ETH1_RXDV;
311
312 HPM_IOC->PAD[IOC_PAD_PE19].FUNC_CTL = IOC_PE19_FUNC_CTL_ETH1_TXD_0;
313 HPM_IOC->PAD[IOC_PAD_PE17].FUNC_CTL = IOC_PE17_FUNC_CTL_ETH1_TXD_1;
314 HPM_IOC->PAD[IOC_PAD_PE14].FUNC_CTL = IOC_PE14_FUNC_CTL_ETH1_TXEN;
315
316 HPM_IOC->PAD[IOC_PAD_PE16].FUNC_CTL = IOC_PAD_FUNC_CTL_LOOP_BACK_MASK | IOC_PE16_FUNC_CTL_ETH1_REFCLK;
317 }
318 }
319
board_init_enet_pins(ENET_Type * ptr)320 hpm_stat_t board_init_enet_pins(ENET_Type *ptr)
321 {
322 init_enet_pins(ptr);
323
324 if (ptr == HPM_ENET0) {
325 gpio_set_pin_output_with_initial(BOARD_ENET_RGMII_RST_GPIO, BOARD_ENET_RGMII_RST_GPIO_INDEX, BOARD_ENET_RGMII_RST_GPIO_PIN, 0);
326 } else if (ptr == HPM_ENET1) {
327 gpio_set_pin_output_with_initial(BOARD_ENET_RMII_RST_GPIO, BOARD_ENET_RMII_RST_GPIO_INDEX, BOARD_ENET_RMII_RST_GPIO_PIN, 0);
328 } else {
329 return status_invalid_argument;
330 }
331
332 return status_success;
333 }
334
board_reset_enet_phy(ENET_Type * ptr)335 hpm_stat_t board_reset_enet_phy(ENET_Type *ptr)
336 {
337 if (ptr == HPM_ENET0) {
338 gpio_write_pin(BOARD_ENET_RGMII_RST_GPIO, BOARD_ENET_RGMII_RST_GPIO_INDEX, BOARD_ENET_RGMII_RST_GPIO_PIN, 0);
339 board_delay_ms(1);
340 gpio_write_pin(BOARD_ENET_RGMII_RST_GPIO, BOARD_ENET_RGMII_RST_GPIO_INDEX, BOARD_ENET_RGMII_RST_GPIO_PIN, 1);
341 } else if (ptr == HPM_ENET1) {
342 gpio_write_pin(BOARD_ENET_RMII_RST_GPIO, BOARD_ENET_RMII_RST_GPIO_INDEX, BOARD_ENET_RMII_RST_GPIO_PIN, 0);
343 board_delay_ms(1);
344 gpio_write_pin(BOARD_ENET_RMII_RST_GPIO, BOARD_ENET_RMII_RST_GPIO_INDEX, BOARD_ENET_RMII_RST_GPIO_PIN, 1);
345 } else {
346 return status_invalid_argument;
347 }
348
349 return status_success;
350 }
351
352
board_init_enet_ptp_clock(ENET_Type * ptr)353 hpm_stat_t board_init_enet_ptp_clock(ENET_Type *ptr)
354 {
355 /* set clock source */
356 if (ptr == HPM_ENET0) {
357 /* make sure pll0_clk0 output clock at 400MHz to get a clock at 100MHz for the enet0 ptp function */
358 clock_set_source_divider(clock_ptp0, clk_src_pll1_clk1, 4); /* 100MHz */
359 } else if (ptr == HPM_ENET1) {
360 /* make sure pll0_clk0 output clock at 400MHz to get a clock at 100MHz for the enet1 ptp function */
361 clock_set_source_divider(clock_ptp1, clk_src_pll1_clk1, 4); /* 100MHz */
362 } else {
363 return status_invalid_argument;
364 }
365
366 return status_success;
367 }
368
board_init_enet_rmii_reference_clock(ENET_Type * ptr,bool internal)369 hpm_stat_t board_init_enet_rmii_reference_clock(ENET_Type *ptr, bool internal)
370 {
371 if (internal == false) {
372 return status_success;
373 }
374 /* Configure Enet clock to output reference clock */
375 if (ptr == HPM_ENET0) {
376 /* make sure pll2_clk1 output clock at 250MHz then set 50MHz for enet0 */
377 clock_set_source_divider(clock_eth0, clk_src_pll2_clk1, 5);
378 } else if (ptr == HPM_ENET1) {
379 /* make sure pll2_clk1 output clock at 250MHz then set 50MHz for enet1 */
380 clock_set_source_divider(clock_eth1, clk_src_pll2_clk1, 5); /* set 50MHz for enet1 */
381 } else {
382 return status_invalid_argument;
383 }
384
385 enet_rmii_enable_clock(ptr, internal);
386
387 return status_success;
388 }
389
board_init_enet_rgmii_clock_delay(ENET_Type * ptr)390 hpm_stat_t board_init_enet_rgmii_clock_delay(ENET_Type *ptr)
391 {
392 return enet_rgmii_set_clock_delay(ptr, BOARD_ENET_RGMII_TX_DLY, BOARD_ENET_RGMII_RX_DLY);
393 }
394