summaryrefslogtreecommitdiff
path: root/libcpu/arm/s3c24x0/system_clock.c
blob: 235c5e5e5c690945f7247e71879d0ea0b16c7d82 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2008-04-25     Yi.qiu       first version
 */

#include <rtthread.h>
#include "s3c24x0.h"

#define CONFIG_SYS_CLK_FREQ 12000000    // Fin = 12.00MHz

#if CONFIG_SYS_CLK_FREQ == 12000000
    /* MPLL=2*12*100/6=400MHz   */
    #define     MPL_MIDV    92      /* m=MPL_MDIV+8=100 */
    #define     MPL_PDIV    4       /* p=MPL_PDIV+2=6   */
    #define     MPL_SDIV    0       /* s=MPL_SDIV=0 */
    /* UPLL=12*64/8=96MHz */
    #define     UPL_MDIV    56      /* m=UPL_MDIV+8=64 */
    #define     UPL_PDIV    2       /* p=UPL_PDIV+2=4   */
    #define     UPL_SDIV    1       /* s=UPL_SDIV=1 */
    /* System clock divider FCLK:HCLK:PCLK=1:4:8 */
    #define     DIVN_UPLL       0x1     /* UCLK = UPLL clock / 2 */
    #define     HDIVN           0x2     /* HCLK = FCLK / 4 */
    #define     PDIVN           0x1     /* PCLK = HCLK / 2 */
#endif

rt_uint32_t PCLK;
rt_uint32_t FCLK;
rt_uint32_t HCLK;
rt_uint32_t UCLK;

void rt_hw_get_clock(void)
{
    rt_uint32_t val;
    rt_uint8_t m, p, s;

    val = MPLLCON;
    m = (val>>12)&0xff;
    p = (val>>4)&0x3f;
    s = val&3;

    FCLK = ((m+8)*(CONFIG_SYS_CLK_FREQ/100)*2)/((p+2)*(1<<s))*100;

    val = CLKDIVN;
    m = (val>>1)&3;
    p = val&1;

    switch (m) {
    case 0:
        HCLK = FCLK;
        break;
    case 1:
        HCLK = FCLK>>1;
        break;
    case 2:
        if(s&2)
            HCLK = FCLK>>3;
        else
            HCLK = FCLK>>2;
        break;
    case 3:
        if(s&1)
            HCLK = FCLK/6;
        else
            HCLK = FCLK/3;
        break;
}

    if(p)
        PCLK = HCLK>>1;
    else
        PCLK = HCLK;
}

void rt_hw_set_mpll_clock(rt_uint8_t sdiv, rt_uint8_t pdiv, rt_uint8_t mdiv)
{
    MPLLCON = sdiv | (pdiv<<4) | (mdiv<<12);
}

void rt_hw_set_upll_clock(rt_uint8_t sdiv, rt_uint8_t pdiv, rt_uint8_t mdiv)
{
    UPLLCON = (mdiv<<12) | (pdiv<<4) | sdiv;
}

void rt_hw_set_divider(rt_uint8_t hdivn, rt_uint8_t pdivn)
{
    CLKDIVN = (hdivn<<1) | pdivn;
}

/**
 * @brief System Clock Configuration
 */
void rt_hw_clock_init(void)
{
    LOCKTIME = 0xFFFFFFFF;
    rt_hw_set_mpll_clock(MPL_SDIV, MPL_PDIV, MPL_MIDV);
    rt_hw_set_upll_clock(UPL_SDIV, UPL_PDIV, UPL_MDIV);
    rt_hw_set_divider(HDIVN, PDIVN);
}