1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2020-12-20     Lyons        first version
9  * 2021-06-24     RiceChen     add spi and lcd clock config
10  */
11 
12 #include "board.h"
13 #include "fsl_clock.h"
14 
15 #define _K_GPT_LOAD_VALUE RT_UINT32_MAX
16 
17 /* only used by MCIMX6Y2.h */
18 uint32_t *g_ccm_vbase = (uint32_t*)IMX6ULL_CCM_BASE;
19 uint32_t *g_ccm_analog_vbase = (uint32_t*)IMX6ULL_CCM_ANALOGY_BASE;
20 uint32_t *g_pmu_vbase = (uint32_t*)IMX6ULL_PMU_BASE;
21 
22 uint32_t g_usbphy1_base = IMX6ULL_USBPHY1_BASE;
23 uint32_t g_usbphy2_base = IMX6ULL_USBPHY2_BASE;
24 
25 uint32_t g_usb1_base = IMX6ULL_USB1_BASE;
26 uint32_t g_usb2_base = IMX6ULL_USB2_BASE;
27 uint32_t g_usb_analog_base = IMX6ULL_USB_ANALOG_BASE;
28 /* used by all files */
29 uint32_t *g_iomuxc_vbase = (uint32_t*)IMX6ULL_IOMUXC_BASE;
30 uint32_t *g_iomuxc_snvs_vbase = (uint32_t*)IMX6ULL_IOMUXC_SNVS_BASE;
31 uint32_t *g_src_vbase = (uint32_t*)IMX6ULL_SRC_BASE;
32 uint32_t *g_wdog1_vbase = (uint32_t*)IMX6ULL_WATCHDOG1_BASE;
33 uint32_t *g_snvs_vbase = (uint32_t*)IMX6ULL_SNVS_BASE;
34 
35 _internal_rw uint32_t *_s_gpt1_vbase = (uint32_t*)IMX6ULL_GPT1_BASE;
36 
_clk_enable(CCM_Type * base)37 static void _clk_enable( CCM_Type *base )
38 {
39     base->CCGR0 = 0XFFFFFFFF;
40     base->CCGR1 = 0XFFFFFFFF;
41     base->CCGR2 = 0XFFFFFFFF;
42     base->CCGR3 = 0XFFFFFFFF;
43     base->CCGR4 = 0XFFFFFFFF;
44     base->CCGR5 = 0XFFFFFFFF;
45     base->CCGR6 = 0XFFFFFFFF;
46 }
47 
BOARD_BootClockRUN(void)48 void BOARD_BootClockRUN(void)
49 {
50     rt_uint32_t reg_value;
51 
52     /* Boot ROM did initialize the XTAL, here we only sets external XTAL OSC freq */
53     CLOCK_SetXtalFreq(24000000U);
54     CLOCK_SetRtcXtalFreq(32768U);
55 
56     /*
57      * ARM_CLK from 'pll1_sw_clk', whitch from 'pll1_main_clk' or 'step_clk'
58      * if edit 'pll1_main_clk', switch to 'step_clk' first
59      */
60     reg_value = CCM->CCSR;
61     if (0 == (reg_value & CCM_CCSR_PLL1_SW_CLK_SEL_MASK)) //if sel 'pll1_main_clk'
62     {
63         reg_value &= ~CCM_CCSR_STEP_SEL_MASK;
64         reg_value |=  CCM_CCSR_STEP_SEL(0); //sel 'osc_clk(24M)'
65         reg_value |=  CCM_CCSR_PLL1_SW_CLK_SEL(1); //sel 'step_clk'
66         CCM->CCSR  =  reg_value;
67     }
68 
69     /*
70      * set PLL1(ARM PLL) at 1056MHz
71      * set ARM_CLK at 528MHz
72      * PLL output frequency = Fref * DIV_SEL / 2
73      *                      = 24M * DIV_SEL / 2 = 1056M
74      */
75     CCM_ANALOG->PLL_ARM = CCM_ANALOG_PLL_ARM_ENABLE(1)
76                         | CCM_ANALOG_PLL_ARM_DIV_SELECT(88);
77 
78     reg_value  =  CCM->CCSR;
79     reg_value &= ~CCM_CCSR_PLL1_SW_CLK_SEL_MASK;
80     reg_value |=  CCM_CCSR_PLL1_SW_CLK_SEL(0); //resel 'pll1_main_clk'
81     CCM->CCSR  =  reg_value;
82 
83     CCM->CACRR = CCM_CACRR_ARM_PODF(1); //'CACRR[ARM_PODF]=0b001' divide by 2
84 
85     /*
86      * set PLL2(System PLL) at fixed 528MHz
87      * PLL2_PFD0: 528M * 18 / FRAC
88      * PLL2_PFD1: 528M * 18 / FRAC
89      * PLL2_PFD2: 528M * 18 / FRAC
90      * PLL2_PFD3: 528M * 18 / FRAC
91      */
92     reg_value  =  CCM_ANALOG->PFD_528;
93     reg_value &= ~0x3F3F3F3F;
94     reg_value |=  CCM_ANALOG_PFD_528_SET_PFD0_FRAC(27); //27: 352MHz
95     reg_value |=  CCM_ANALOG_PFD_528_SET_PFD1_FRAC(16); //16: 594MHz
96     reg_value |=  CCM_ANALOG_PFD_528_SET_PFD2_FRAC(24); //24: 396MHz
97     reg_value |=  CCM_ANALOG_PFD_528_SET_PFD3_FRAC(32); //32: 297MHz
98     CCM_ANALOG->PFD_528 = reg_value;
99 
100     /*
101      * set PLL3(USB  PLL) at fixed 480MHz
102      * PLL3_PFD0: 480M * 18 / FRAC
103      * PLL3_PFD1: 480M * 18 / FRAC
104      * PLL3_PFD2: 480M * 18 / FRAC
105      * PLL3_PFD3: 480M * 18 / FRAC
106      */
107     reg_value  =  CCM_ANALOG->PFD_480;
108     reg_value &= ~0x3F3F3F3F;
109     reg_value |=  CCM_ANALOG_PFD_480_SET_PFD0_FRAC(12); //12: 720MHz
110     reg_value |=  CCM_ANALOG_PFD_480_SET_PFD1_FRAC(16); //16: 540MHz
111     reg_value |=  CCM_ANALOG_PFD_480_SET_PFD2_FRAC(17); //17: 508.24MHz
112     reg_value |=  CCM_ANALOG_PFD_480_SET_PFD3_FRAC(19); //19: 457.74MHz
113     CCM_ANALOG->PFD_480 = reg_value;
114 
115     /*
116      * set PERCLK_CLK at 66MHz from IPG_CLK
117      */
118     reg_value  =  CCM->CSCMR1;
119     reg_value &= ~CCM_CSCMR1_PERCLK_CLK_SEL_MASK;
120     reg_value |=  CCM_CSCMR1_PERCLK_CLK_SEL(0); //sel IPG_CLK
121     reg_value &= ~CCM_CSCMR1_PERCLK_PODF_MASK;
122     reg_value |=  CCM_CSCMR1_PERCLK_PODF(0); //'CSCMR1[PERCLK_PODF]=0b000000' divide by 1
123     CCM->CSCMR1 = reg_value;
124 
125     CLOCK_DeinitAudioPll();
126     CLOCK_DeinitVideoPll();
127     CLOCK_DeinitEnetPll();
128 
129     /* Configure UART divider to default */
130     CLOCK_SetMux(kCLOCK_UartMux, 0); /* Set UART source to PLL3 80M */
131     CLOCK_SetDiv(kCLOCK_UartDiv, 0); /* Set UART divider to 1 */
132 
133     /* Configure ECSPI divider to default */
134     CLOCK_SetMux(kCLOCK_EcspiMux, 0);           /* Set ECSPI source to PLL3 60M */
135     CLOCK_SetDiv(kCLOCK_EcspiDiv, 0);           /* Set ECSPI divider to 1 */
136 
137     /* Set LCDIF_PRED. */
138     CLOCK_SetDiv(kCLOCK_Lcdif1PreDiv, 2);
139     /* Set LCDIF_CLK_PODF. */
140     CLOCK_SetDiv(kCLOCK_Lcdif1Div, 4);
141     /* Set Lcdif pre clock source. */
142     CLOCK_SetMux(kCLOCK_Lcdif1PreMux, 2);
143     CLOCK_SetMux(kCLOCK_Lcdif1Mux, 0);
144 }
145 
BOARD_DelayInit(void)146 void BOARD_DelayInit(void)
147 {
148     GPT_Type *_GPT = (GPT_Type*)_s_gpt1_vbase;
149 
150     _GPT->CR = 0;
151 
152     _GPT->CR = GPT_CR_SWR(1);
153     while (_GPT->CR & GPT_CR_SWR_MASK);
154 
155     /*
156      * 000 No clock
157      * 001 derive clock from ipg_clk
158      * 010 derive clock from ipg_clk_highfreq
159      * 011 derive clock from External Clock
160      * 100 derive clock from ipg_clk_32k
161      * 101 derive clock from ipg_clk_24M
162      */
163     _GPT->CR = GPT_CR_CLKSRC(0x1);
164 
165     _GPT->PR = GPT_PR_PRESCALER(65); //Set GPT1 Clock to 66MHz/66 = 1MHz
166 
167     _GPT->OCR[0] = GPT_OCR_COMP(_K_GPT_LOAD_VALUE);
168 
169     _GPT->CR |= GPT_CR_EN(1);
170 }
171 
172 //execution before SystemClockInit called
SystemAddressMapping(void)173 void SystemAddressMapping(void)
174 {
175     g_ccm_vbase = (uint32_t*)platform_get_periph_vaddr((rt_uint32_t)g_ccm_vbase);
176     g_ccm_analog_vbase = (uint32_t*)platform_get_periph_vaddr((rt_uint32_t)g_ccm_analog_vbase);
177     g_pmu_vbase = (uint32_t*)platform_get_periph_vaddr((rt_uint32_t)g_pmu_vbase);
178 
179     g_iomuxc_vbase = (uint32_t*)platform_get_periph_vaddr((rt_uint32_t)g_iomuxc_vbase);
180     g_iomuxc_snvs_vbase = (uint32_t*)platform_get_periph_vaddr((rt_uint32_t)g_iomuxc_snvs_vbase);
181     g_src_vbase = (uint32_t*)platform_get_periph_vaddr((rt_uint32_t)g_src_vbase);
182     g_wdog1_vbase = (uint32_t*)platform_get_periph_vaddr((rt_uint32_t)g_wdog1_vbase);
183     g_snvs_vbase = (uint32_t*)platform_get_periph_vaddr((rt_uint32_t)g_snvs_vbase);
184 
185     _s_gpt1_vbase = (uint32_t*)platform_get_periph_vaddr((rt_uint32_t)_s_gpt1_vbase);
186     g_usbphy1_base = (uint32_t)platform_get_periph_vaddr((rt_uint32_t)g_usbphy1_base);
187     g_usbphy2_base = (uint32_t)platform_get_periph_vaddr((rt_uint32_t)g_usbphy2_base);
188 
189     g_usb1_base = (uint32_t)platform_get_periph_vaddr((rt_uint32_t)g_usb1_base);
190     g_usb2_base = (uint32_t)platform_get_periph_vaddr((rt_uint32_t)g_usb2_base);
191     g_usb_analog_base = (uint32_t)platform_get_periph_vaddr((rt_uint32_t)g_usb_analog_base);
192 }
193 
SystemClockInit(void)194 void SystemClockInit(void)
195 {
196     BOARD_BootClockRUN();
197     BOARD_DelayInit();
198 
199     _clk_enable(CCM);
200 }
201 
rt_hw_us_delay(uint32_t us)202 void rt_hw_us_delay(uint32_t us)
203 {
204     GPT_Type *_GPT = (GPT_Type*)_s_gpt1_vbase;
205 
206     rt_uint64_t old_cnt, new_cnt;
207     rt_uint64_t total = 0;
208 
209     old_cnt = _GPT->CNT;
210     while (1)
211     {
212         new_cnt = _GPT->CNT;
213         if (old_cnt != new_cnt)
214         {
215             if (new_cnt > old_cnt)
216             {
217                 total += (new_cnt - old_cnt);
218             } else {
219                 total += (new_cnt + _K_GPT_LOAD_VALUE - old_cnt);
220             }
221             old_cnt = new_cnt;
222 
223             if (total >= us)
224                 break;
225         }
226     }
227 }
228 
rt_hw_ms_delay(uint32_t ms)229 void rt_hw_ms_delay(uint32_t ms)
230 {
231     while (ms--)
232     {
233         rt_hw_us_delay(1000);
234     }
235 }
236