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  * 2008-04-25     Yi.qiu       first version
9  */
10 
11 #include <rtthread.h>
12 #include "s3c24x0.h"
13 
14 #define CONFIG_SYS_CLK_FREQ 12000000    // Fin = 12.00MHz
15 
16 #if CONFIG_SYS_CLK_FREQ == 12000000
17     /* MPLL=2*12*100/6=400MHz   */
18     #define     MPL_MIDV    92      /* m=MPL_MDIV+8=100 */
19     #define     MPL_PDIV    4       /* p=MPL_PDIV+2=6   */
20     #define     MPL_SDIV    0       /* s=MPL_SDIV=0 */
21     /* UPLL=12*64/8=96MHz */
22     #define     UPL_MDIV    56      /* m=UPL_MDIV+8=64 */
23     #define     UPL_PDIV    2       /* p=UPL_PDIV+2=4   */
24     #define     UPL_SDIV    1       /* s=UPL_SDIV=1 */
25     /* System clock divider FCLK:HCLK:PCLK=1:4:8 */
26     #define     DIVN_UPLL       0x1     /* UCLK = UPLL clock / 2 */
27     #define     HDIVN           0x2     /* HCLK = FCLK / 4 */
28     #define     PDIVN           0x1     /* PCLK = HCLK / 2 */
29 #endif
30 
31 rt_uint32_t PCLK;
32 rt_uint32_t FCLK;
33 rt_uint32_t HCLK;
34 rt_uint32_t UCLK;
35 
rt_hw_get_clock(void)36 void rt_hw_get_clock(void)
37 {
38     rt_uint32_t val;
39     rt_uint8_t m, p, s;
40 
41     val = MPLLCON;
42     m = (val>>12)&0xff;
43     p = (val>>4)&0x3f;
44     s = val&3;
45 
46     FCLK = ((m+8)*(CONFIG_SYS_CLK_FREQ/100)*2)/((p+2)*(1<<s))*100;
47 
48     val = CLKDIVN;
49     m = (val>>1)&3;
50     p = val&1;
51 
52     switch (m) {
53     case 0:
54         HCLK = FCLK;
55         break;
56     case 1:
57         HCLK = FCLK>>1;
58         break;
59     case 2:
60         if(s&2)
61             HCLK = FCLK>>3;
62         else
63             HCLK = FCLK>>2;
64         break;
65     case 3:
66         if(s&1)
67             HCLK = FCLK/6;
68         else
69             HCLK = FCLK/3;
70         break;
71 }
72 
73     if(p)
74         PCLK = HCLK>>1;
75     else
76         PCLK = HCLK;
77 }
78 
rt_hw_set_mpll_clock(rt_uint8_t sdiv,rt_uint8_t pdiv,rt_uint8_t mdiv)79 void rt_hw_set_mpll_clock(rt_uint8_t sdiv, rt_uint8_t pdiv, rt_uint8_t mdiv)
80 {
81     MPLLCON = sdiv | (pdiv<<4) | (mdiv<<12);
82 }
83 
rt_hw_set_upll_clock(rt_uint8_t sdiv,rt_uint8_t pdiv,rt_uint8_t mdiv)84 void rt_hw_set_upll_clock(rt_uint8_t sdiv, rt_uint8_t pdiv, rt_uint8_t mdiv)
85 {
86     UPLLCON = (mdiv<<12) | (pdiv<<4) | sdiv;
87 }
88 
rt_hw_set_divider(rt_uint8_t hdivn,rt_uint8_t pdivn)89 void rt_hw_set_divider(rt_uint8_t hdivn, rt_uint8_t pdivn)
90 {
91     CLKDIVN = (hdivn<<1) | pdivn;
92 }
93 
94 /**
95  * @brief System Clock Configuration
96  */
rt_hw_clock_init(void)97 void rt_hw_clock_init(void)
98 {
99     LOCKTIME = 0xFFFFFFFF;
100     rt_hw_set_mpll_clock(MPL_SDIV, MPL_PDIV, MPL_MIDV);
101     rt_hw_set_upll_clock(UPL_SDIV, UPL_PDIV, UPL_MDIV);
102     rt_hw_set_divider(HDIVN, PDIVN);
103 }
104 
105