2015년 3월 7일 토요일

[Linux Kernel] 93주차(2015.03.07)

ARM10C 93주차 후기

일시 : 2015.03.07 (93주차)
모임명 : NAVER개발자커뮤니티지원_IAMROOT.ORG_10차ARM-C
장소 : 토즈 타워점
장소지원 : NAVER 개발자 커뮤니티 지원 프로그램
참여인원 : 3명

93주차 진도

  • start_kernel() init/main.c
    • ->time_init() 741 /arch/arm/kernel/time.c
      • ->of_clk_init() 154 /arch/arm/kernel/time.c
        • ->clk_init_cb() // exynos5420_clk_init(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소)
          • ->exynos5420_clk_init() 3538 /drivers/clk/samsung/clk-exynos5420.c 
            • ->samsung_clk_register_div() 1324 /drivers/clk/samsung/clk-exynos5420.c 
              • ->clk_register_divider() 544 drivers/clk/clk-divider.c
                • ->_register_divider() 416 drivers/clk/clk-divider.c
                  • ->clk_register() 379 drivers/clk/clk-divider.c
  • NOTE
    • 5420 arndale board 로그에 따라서
    • fout_spll : 600 Mhz 로 분석
    • sclk_fimd1 : 266 Mhz 로 분석
  • sclk_fimd1 자료 참조 
    • // list->name: exynos5420_gate_clks[36].name: "sclk_fimd1",
    • // list->parent_name: exynos5420_gate_clks[36].parent_name: "dout_fimd1",
    • // list->flags: exynos5420_gate_clks[36].flags: 0x4, : 
    • // 0xf0050828,
    • // list->bit_idx: exynos5420_gate_clks[36].bit_idx: 0,
    • // list->gate_flags: exynos5420_gate_clks[36].gate_flags: 0,
    • // &lock
  • init 참조
    • // init.name: "sclk_fimd1"
    • // init.ops: &clk_gate_ops
    • // init.flags: 0x24
    • // init.parent_names: "dout_fimd1"
    • // init.num_parents: 1
    • // (sclk_fimd1))->reg: 0xf0050828
    • // (sclk_fimd1))->bit_idx: 0
    • // (sclk_fimd1))->flags: 0
    • // (sclk_fimd1))->lock: &lock
    • // (sclk_fimd1))->hw.init: &init
  • clk_register(sclk_fimd1) 에서 한일:
    • // (kmem_cache#29-oX (sclk_fimd1))->name: kmem_cache#30-oX ("sclk_fimd1")
    • // (kmem_cache#29-oX (sclk_fimd1))->ops: &clk_gate_ops
    • // (kmem_cache#29-oX (sclk_fimd1))->hw: &(kmem_cache#30-oX (sclk_fimd1))->hw
    • // (kmem_cache#29-oX (sclk_fimd1))->flags: 0x24
    • // (kmem_cache#29-oX (sclk_fimd1))->num_parents 1
    • // (kmem_cache#29-oX (sclk_fimd1))->parent_names[0]: (kmem_cache#30-oX)[0]: kmem_cache#30-oX: "mout_apll"
    • // (kmem_cache#29-oX (sclk_fimd1))->parent: kmem_cache#29-oX (dout_fimd1)
    • // (kmem_cache#29-oX (sclk_fimd1))->rate: 266000000
    • // 
    • // kmem_cache#30-oX (sclk_fimd1)
    • // (kmem_cache#30-oX (sclk_fimd1))->reg: 0xf0050828
    • // (kmem_cache#30-oX (sclk_fimd1))->bit_idx: 0
    • // (kmem_cache#30-oX (sclk_fimd1))->flags: 0
    • // (kmem_cache#30-oX (sclk_fimd1))->lock: &lock
    • // (kmem_cache#30-oX (sclk_fimd1))->hw.init: &init
    • // (kmem_cache#30-oX (sclk_fimd1))->table: NULL

start_kernel()->time_init()

  • start_kernel()
asmlinkage void __init start_kernel(void)
{
...
    early_irq_init();
    // irq_desc 0 ~ 15 까지의 object을 할당 받고 초기화를 수행
    // allocated_irqs에 bit를 1로 세팅하고 radix tree에 각 irq_desc를 노트로 추가

    init_IRQ();
    // gic, combiner이 사용할 메모리 할당과 자료 구조 설정,
    // gic irq (0~15), combiner irq (32~63) interrupt 를 enable 시킴

    tick_init();
    // tick 관련 mask 변수를 0으로 초기화 수행

    init_timers();
    // boot_tvec_bases의 맴버 값을 초기화하고 timers_nb를 cpu_notifier 에 등록,
    // softirq_vec[1] 에 run_timer_softirq 등록하여 초기화 수행

    hrtimers_init();
    // hrtimer_bases의 맴버 값을 초기화하고 hrtimers_nb를 cpu_notifier 에 등록,
    // softirq_vec[8] 에 run_hrtimer_softirq 등록하여 초기화 수행

    softirq_init();
    // tasklet_vec, tasklet_hi_vec 맴버 값을 초기화하고,
    // softirq_vec[6]에 tasklet_action, softirq_vec[0]에 tasklet_hi_action 등록하여 초기화 수행

    timekeeping_init();
    // ntp 관련 전역변수 초기화, timekeeper, shadow_timekeeper의 맴버값 초기화 수행

    time_init();
  • call: start_kernel()->time_init()

time_init()->of_clk_init(NULL)

  • called: start_kernel()->time_init()
// ARM10C 20150103
void __init time_init(void)
{
    // machine_desc->init_time: __mach_desc_EXYNOS5_DT.init_time: NULL
    if (machine_desc->init_time) {
        machine_desc->init_time();
    } else {
#ifdef CONFIG_COMMON_CLK // CONFIG_COMMON_CLK=y
        of_clk_init(NULL);
#endif
  • call: start_kernel()->time_init()->of_clk_init()

of_clk_init()->clk_init_cb(np)

  • call: start_kernel()->time_init()->of_clk_init()
    const struct of_device_id *match;
    struct device_node *np;

    // matches: NULL
    if (!matches)
        // __clk_of_table:
        // __clk_of_table_fixed_factor_clk
        // __clk_of_table_fixed_clk
        // __clk_of_table_exynos4210_audss_clk
        // __clk_of_table_exynos5250_audss_clk
        // __clk_of_table_exynos5420_clk
        matches = __clk_of_table;
        // matches:
        // __clk_of_table_fixed_factor_clk
        // __clk_of_table_fixed_clk
        // __clk_of_table_exynos4210_audss_clk
        // __clk_of_table_exynos5250_audss_clk
        // __clk_of_table_exynos5420_clk

    for_each_matching_node_and_match(np, matches, &match) {
    // for (np = of_find_matching_node_and_match(NULL, matches, &match);
    //      np; np = of_find_matching_node_and_match(np, matches, &match))

        // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소, match: __clk_of_table_exynos5420_clk

        // match->data: __clk_of_table_exynos5420_clk.data: exynos5420_clk_init
        of_clk_init_cb_t clk_init_cb = match->data;
        // clk_init_cb: exynos5420_clk_init

        // clk_init_cb: exynos5420_clk_init,
        // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
        // exynos5420_clk_init(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소)
        clk_init_cb(np);
  • call: start_kernel()->time_init()->of_clk_init()->exynos5420_clk_init()
    • // clk_init_cb: exynos5420_clk_init,
    • // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
    • // exynos5420_clk_init(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소)
    • clk_init_cb(np);

exynos5420_clk_init()

  • called: start_kernel()->time_init()->of_clk_init()->exynos5420_clk_init()
    • // clk_init_cb: exynos5420_clk_init,
    • // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
    • // exynos5420_clk_init(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소)
    • clk_init_cb(np);
// ARM10C 20150103
typedef void (*of_clk_init_cb_t)(struct device_node *);
/* register exynos5420 clocks */
// ARM10C 20150103
// devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
static void __init exynos5420_clk_init(struct device_node *np)
{
    void __iomem *reg_base;

    // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
    if (np) {
        // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
        // of_iomap(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소, 0): 0xf0040000
        reg_base = of_iomap(np, 0);
        // reg_base: 0xf0040000
  • of_iomap에서 한일:
    • // device tree 있는 clock node에서 node의 resource 값을 가져옴
    • // of_address_to_resource에서 한일(index: 0):
    • // (&res)->start: 0x10010000
    • // (&res)->end: 0x1003ffff
    • // (&res)->flags: IORESOURCE_MEM: 0x00000200
    • // (&res)->name: "/clock-controller@10010000"
    • /*
    • // alloc area (CLK) 를 만들고 rb tree에 alloc area 를 추가
    • // 가상주소 va_start 기준으로 CLK 를 RB Tree 추가한 결과
//                                  CHID-b
//                               (0xF8000000)
//                              /            \
//                         TMR-b               PMU-b
//                    (0xF6300000)             (0xF8180000)
//                      /      \               /           \
//                GIC#1-r      WDT-b         CMU-b         SRAM-b
//            (0xF0002000)   (0xF6400000)  (0xF8100000)   (0xF8400000)
//             /       \                                          \
//        GIC#0-b     CLK-b                                        ROMC-r
//    (0xF0000000)   (0xF0040000)                                 (0xF84C0000)
//                   /      \
//               COMB-r     SYSC-r
//          (0xF0004000)   (0xF6100000)
//
  • // vmap_area_list에 GIC#0 - GIC#1 - COMB - CLK - SYSC -TMR - WDT - CHID - CMU - PMU - SRAM - ROMC
  • // 순서로 리스트에 연결이 됨
  • //
  • // (kmem_cache#30-oX (vm_struct))->flags: GFP_KERNEL: 0xD0
  • // (kmem_cache#30-oX (vm_struct))->addr: 0xf0040000
  • // (kmem_cache#30-oX (vm_struct))->size: 0x31000
  • // (kmem_cache#30-oX (vm_struct))->caller: __builtin_return_address(0)
  • //
  • // (kmem_cache#30-oX (vmap_area CLK))->vm: kmem_cache#30-oX (vm_struct)
  • // (kmem_cache#30-oX (vmap_area CLK))->flags: 0x04
  • */
  • // device tree 있는 clock node에서 node의 resource 값을 pgtable에 매핑함
  • // 0xc0004780이 가리키는 pte의 시작주소에 0x10010653 값을 갱신
  • // (linux pgtable과 hardware pgtable의 값 같이 갱신)
//  pgd                   pte
// |              |
// +--------------+
// |              |       +--------------+ +0
// |              |       |  0xXXXXXXXX  | ---> 0x10010653 에 매칭되는 linux pgtable 값
// +- - - - - - - +       |  Linux pt 0  |
// |              |       +--------------+ +1024
// |              |       |              |
// +--------------+ +0    |  Linux pt 1  |
// | *(c0004780)  |-----> +--------------+ +2048
// |              |       |  0x10010653  | ---> 2308
// +- - - - - - - + +4    |   h/w pt 0   |
// | *(c0004784)  |-----> +--------------+ +3072
// |              |       +              +
// +--------------+ +8    |   h/w pt 1   |
// |              |       +--------------+ +4096
  • // cache의 값을 전부 메모리에 반영
  • samsung_clk_init()
static void __init exynos5420_clk_init(struct device_node *np)
{
    if (np) {
        // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
        // of_iomap(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소, 0): 0xf0040000
        reg_base = of_iomap(np, 0); 
        // reg_base: 0xf0040000

        // reg_base: 0xf0040000
        if (!reg_base)
            panic("%s: failed to map registers\n", __func__);
    } else {
        panic("%s: unable to determine soc\n", __func__);
    }

    // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소, reg_base: 0xf0040000, nr_clks: 769
    // ARRAY_SIZE(exynos5420_clk_regs): 59
    samsung_clk_init(np, reg_base, nr_clks,
            exynos5420_clk_regs, ARRAY_SIZE(exynos5420_clk_regs),
            NULL, 0);
  • samsung_clk_init() 에서 한일:
    • // struct samsung_clk_reg_dump를 59개 만큼 메모리를 할당 받아
    • // exynos5420_clk_regs의 값으로 맴버값 세팅
    • // (kmem_cache#26-oX)[0...58].offset: exynos5420_clk_regs[0...58]
    • //
    • // syscore_ops_list의 tail에 (&samsung_clk_syscore_ops)->node 를 추가
    • //
    • // struct clk * 를 769개 만큼 메모리를 clk_table에 할당 받음
    • // clk_table: kmem_cache#23-o0
    • //
    • // clk_data.clks: kmem_cache#23-o0 (clk_table)
    • // clk_data.clk_num: 769
    • //
    • // struct of_clk_provider 의 메모리(kmem_cache#30-oX)를 할당 받고 맴버값 초기화 수행
    • //
    • // (kmem_cache#30-oX)->node: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
    • // (kmem_cache#30-oX)->data: &clk_data
    • // (kmem_cache#30-oX)->get: of_clk_src_onecell_get
    • //
    • // list인 of_clk_providers의 head에 (kmem_cache#30-oX)->link를 추가
  • samsung_clk_of_register_fixed_ext()
static void __init exynos5420_clk_init(struct device_node *np)
{
    if (np) {
        // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
        // of_iomap(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소, 0): 0xf0040000
        reg_base = of_iomap(np, 0); 
        // reg_base: 0xf0040000

        // reg_base: 0xf0040000
        if (!reg_base)
            panic("%s: failed to map registers\n", __func__);
    } else {
        panic("%s: unable to determine soc\n", __func__);
    }

    // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소, reg_base: 0xf0040000, nr_clks: 769
    // ARRAY_SIZE(exynos5420_clk_regs): 59
    samsung_clk_init(np, reg_base, nr_clks,
            exynos5420_clk_regs, ARRAY_SIZE(exynos5420_clk_regs),
            NULL, 0);

    // ARRAY_SIZE(exynos5420_fixed_rate_ext_clks): 1
    samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks,
            ARRAY_SIZE(exynos5420_fixed_rate_ext_clks),
            ext_clk_match);
  • samsung_clk_of_register_fixed_ext() 에서 한일:
    • // devtree에서 allnext로 순회 하면서 찾은 fixed-rate-clocks node 에서
    • // fixed-rate-clocks node에서 "clock-frequency" property값을 freq에 읽어옴
    • // freq: 24000000
    • // exynos5420_fixed_rate_ext_clks[0].fixed_rate: 24000000
    • //
    • // struct clk_fixed_rate 만큼 메모리를 kmem_cache#30-oX 할당 받고 struct clk_fixed_rate 의 멤버 값을 아래와 같이 초기화 수행
    • //
    • // (kmem_cache#30-oX)->fixed_rate: 24000000
    • // (kmem_cache#30-oX)->hw.init: &init
    • // (&(kmem_cache#30-oX)->hw)->clk: kmem_cache#29-oX
    • //
    • // struct clk 만큼 메모리를 kmem_cache#29-oX 할당 받고 struct clk 의 멤버 값을 아래와 같이 초기화 수행
    • //
    • // (kmem_cache#29-oX)->name: kmem_cache#30-oX ("fin_pll")
    • // (kmem_cache#29-oX)->ops: &clk_fixed_rate_ops
    • // (kmem_cache#29-oX)->hw: &(kmem_cache#30-oX)->hw
    • // (kmem_cache#29-oX)->flags: 0x30
    • // (kmem_cache#29-oX)->num_parents: 0
    • // (kmem_cache#29-oX)->parent_names: ((void *)16)
    • // (kmem_cache#29-oX)->parent: NULL
    • // (kmem_cache#29-oX)->rate: 24000000
    • //
    • // (&(kmem_cache#29-oX)->child_node)->next: NULL
    • // (&(kmem_cache#29-oX)->child_node)->pprev: &(&(kmem_cache#29-oX)->child_node)
    • //
    • // (&clk_root_list)->first: &(kmem_cache#29-oX)->child_node
    • //
    • // clk_table[1]: (kmem_cache#23-o0)[1]: kmem_cache#29-oX
    • //
    • // struct clk_lookup_alloc 의 메모리를 kmem_cache#30-oX 할당 받고
    • // struct clk_lookup_alloc 맴버값 초기화 수행
    • //
    • // (kmem_cache#30-oX)->cl.clk: kmem_cache#29-oX
    • // (kmem_cache#30-oX)->con_id: "fin_pll"
    • // (kmem_cache#30-oX)->cl.con_id: (kmem_cache#30-oX)->con_id: "fin_pll"
    • //
    • // list clocks에 &(&(kmem_cache#30-oX)->cl)->nade를 tail로 추가
  • samsung_clk_register_pll()
static void __init exynos5420_clk_init(struct device_node *np)
{
    if (np) {
        // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
        // of_iomap(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소, 0): 0xf0040000
        reg_base = of_iomap(np, 0); 
        // reg_base: 0xf0040000

        // reg_base: 0xf0040000
        if (!reg_base)
            panic("%s: failed to map registers\n", __func__);
    } else {
        panic("%s: unable to determine soc\n", __func__);
    }

    // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소, reg_base: 0xf0040000, nr_clks: 769
    // ARRAY_SIZE(exynos5420_clk_regs): 59
    samsung_clk_init(np, reg_base, nr_clks,
            exynos5420_clk_regs, ARRAY_SIZE(exynos5420_clk_regs),
            NULL, 0);

    // ARRAY_SIZE(exynos5420_fixed_rate_ext_clks): 1
    samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks,
            ARRAY_SIZE(exynos5420_fixed_rate_ext_clks),
            ext_clk_match);

    // ARRAY_SIZE(exynos5420_plls): 11, reg_base: 0xf0040000
    samsung_clk_register_pll(exynos5420_plls, ARRAY_SIZE(exynos5420_plls),
                    reg_base);
  • samsung_clk_register_pll() 에서 한일:
    • // exynos5420_plls에 정의되어 있는 PLL 값들을 초기화 수행
    • //
    • // [apll] 의 초기화 값 수행 결과:
    • // struct clk_fixed_rate 만큼 메모리를 kmem_cache#30-oX (apll) 할당 받고 struct clk_fixed_rate 의 멤버 값을 아래와 같이 초기화 수행
    • // pll: kmem_cache#30-oX (apll)
    • //
    • // (kmem_cache#30-oX (apll))->hw.init: &init
    • // (kmem_cache#30-oX (apll))->type: pll_2550: 2
    • // (kmem_cache#30-oX (apll))->lock_reg: 0xf0040000
    • // (kmem_cache#30-oX (apll))->con_reg: 0xf0040100
    • //
    • // struct clk 만큼 메모리를 kmem_cache#29-oX (apll) 할당 받고 struct clk 의 멤버 값을 아래와 같이 초기화 수행
    • //
    • // (kmem_cache#29-oX (apll))->name: kmem_cache#30-oX ("fout_apll")
    • // (kmem_cache#29-oX (apll))->ops: &samsung_pll35xx_clk_min_ops
    • // (kmem_cache#29-oX (apll))->hw: &(kmem_cache#30-oX (apll))->hw
    • // (kmem_cache#29-oX (apll))->flags: 0x40
    • // (kmem_cache#29-oX (apll))->num_parents: 1
    • // (kmem_cache#29-oX (apll))->parent_names: kmem_cache#30-oX
    • // (kmem_cache#29-oX (apll))->parent_names[0]: (kmem_cache#30-oX)[0]: kmem_cache#30-oX: "fin_pll"
    • // (kmem_cache#29-oX (apll))->parent: kmem_cache#29-oX (fin_pll)
    • // (kmem_cache#29-oX (apll))->rate: 1000000000 (1 Ghz)
    • //
    • // (&(kmem_cache#29-oX (apll))->child_node)->next: NULL
    • // (&(kmem_cache#29-oX (apll))->child_node)->pprev: &(&(kmem_cache#29-oX (apll))->child_node)
    • //
    • // (&(kmem_cache#29-oX (fin_pll))->children)->first: &(kmem_cache#29-oX (apll))->child_node
    • //
    • // (&(kmem_cache#30-oX (apll))->hw)->clk: kmem_cache#29-oX (apll)
    • //
    • // clk_table[2]: (kmem_cache#23-o0)[2]: kmem_cache#29-oX (apll)
    • //
    • // struct clk_lookup_alloc 의 메모리를 kmem_cache#30-oX (apll) 할당 받고
    • // struct clk_lookup_alloc 맴버값 초기화 수행
    • //
    • // (kmem_cache#30-oX)->cl.clk: kmem_cache#29-oX (apll)
    • // (kmem_cache#30-oX)->con_id: "fout_apll"
    • // (kmem_cache#30-oX)->cl.con_id: (kmem_cache#30-oX)->con_id: "fout_apll"
    • //
    • // list clocks에 &(&(kmem_cache#30-oX (apll))->cl)->nade를 tail로 추가
    • //
    • // cpll, dpll, epll, rpll, ipll, spll, vpll, mpll, bpll, kpll 초기화 수행 결과는 생략.
  • samsung_clk_register_fixed_rate()
static void __init exynos5420_clk_init(struct device_node *np)
{
    if (np) {
        // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
        // of_iomap(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소, 0): 0xf0040000
        reg_base = of_iomap(np, 0); 
        // reg_base: 0xf0040000

        // reg_base: 0xf0040000
        if (!reg_base)
            panic("%s: failed to map registers\n", __func__);
    } else {
        panic("%s: unable to determine soc\n", __func__);
    }

    // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소, reg_base: 0xf0040000, nr_clks: 769
    // ARRAY_SIZE(exynos5420_clk_regs): 59
    samsung_clk_init(np, reg_base, nr_clks,
            exynos5420_clk_regs, ARRAY_SIZE(exynos5420_clk_regs),
            NULL, 0);

    // ARRAY_SIZE(exynos5420_fixed_rate_ext_clks): 1
    samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks,
            ARRAY_SIZE(exynos5420_fixed_rate_ext_clks),
            ext_clk_match);

    // ARRAY_SIZE(exynos5420_plls): 11, reg_base: 0xf0040000
    samsung_clk_register_pll(exynos5420_plls, ARRAY_SIZE(exynos5420_plls),
                    reg_base);

    // ARRAY_SIZE(exynos5420_fixed_rate_clks): 5
    samsung_clk_register_fixed_rate(exynos5420_fixed_rate_clks,
            ARRAY_SIZE(exynos5420_fixed_rate_clks));
  • samsung_clk_register_fixed_rate() 에서 한일:
    • // exynos5420_fixed_rate_clks에 정의되어 있는 fixed rate 값들을 초기화 수행
    • //
    • // sclk_hdmiphy 의 초기화 값 수행 결과
    • // struct clk_fixed_rate 만큼 메모리를 kmem_cache#30-oX 할당 받고 struct clk_fixed_rate 의 멤버 값을 아래와 같이 초기화 수행
    • //
    • // (kmem_cache#30-oX)->fixed_rate: 24000000
    • // (kmem_cache#30-oX)->hw.init: &init
    • // (&(kmem_cache#30-oX)->hw)->clk: kmem_cache#29-oX
    • //
    • // struct clk 만큼 메모리를 kmem_cache#29-oX 할당 받고 struct clk 의 멤버 값을 아래와 같이 초기화 수행
    • //
    • // (kmem_cache#29-oX)->name: kmem_cache#30-oX ("sclk_hdmiphy")
    • // (kmem_cache#29-oX)->ops: &clk_fixed_rate_ops
    • // (kmem_cache#29-oX)->hw: &(kmem_cache#30-oX)->hw
    • // (kmem_cache#29-oX)->flags: 0x30
    • // (kmem_cache#29-oX)->num_parents: 0
    • // (kmem_cache#29-oX)->parent_names: ((void *)16)
    • // (kmem_cache#29-oX)->parent: NULL
    • // (kmem_cache#29-oX)->rate: 24000000
    • //
    • // (&(kmem_cache#29-oX)->child_node)->next: NULL
    • // (&(kmem_cache#29-oX)->child_node)->pprev: &(&(kmem_cache#29-oX)->child_node)
    • //
    • // (&clk_root_list)->first: &(kmem_cache#29-oX)->child_node
    • //
    • // clk_table[158]: (kmem_cache#23-o0)[158]: kmem_cache#29-oX
    • //
    • // struct clk_lookup_alloc 의 메모리를 kmem_cache#30-oX 할당 받고
    • // struct clk_lookup_alloc 맴버값 초기화 수행
    • //
    • // (kmem_cache#30-oX)->cl.clk: kmem_cache#29-oX
    • // (kmem_cache#30-oX)->con_id: "fin_pll"
    • // (kmem_cache#30-oX)->cl.con_id: (kmem_cache#30-oX)->con_id: "fin_pll"
    • //
    • // list clocks에 &(&(kmem_cache#30-oX)->cl)->nade를 tail로 추가
    • //
    • // "sclk_pwi", "sclk_usbh20", "mphy_refclk_ixtal24", "sclk_usbh20_scan_clk" 초기화 수행 결과는 생략.
  • samsung_clk_register_fixed_factor()
static void __init exynos5420_clk_init(struct device_node *np)
{
    if (np) {
        // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
        // of_iomap(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소, 0): 0xf0040000
        reg_base = of_iomap(np, 0); 
        // reg_base: 0xf0040000

        // reg_base: 0xf0040000
        if (!reg_base)
            panic("%s: failed to map registers\n", __func__);
    } else {
        panic("%s: unable to determine soc\n", __func__);
    }

    // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소, reg_base: 0xf0040000, nr_clks: 769
    // ARRAY_SIZE(exynos5420_clk_regs): 59
    samsung_clk_init(np, reg_base, nr_clks,
            exynos5420_clk_regs, ARRAY_SIZE(exynos5420_clk_regs),
            NULL, 0);

    // ARRAY_SIZE(exynos5420_fixed_rate_ext_clks): 1
    samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks,
            ARRAY_SIZE(exynos5420_fixed_rate_ext_clks),
            ext_clk_match);

    // ARRAY_SIZE(exynos5420_plls): 11, reg_base: 0xf0040000
    samsung_clk_register_pll(exynos5420_plls, ARRAY_SIZE(exynos5420_plls),
                    reg_base);

    // ARRAY_SIZE(exynos5420_fixed_rate_clks): 5
    samsung_clk_register_fixed_rate(exynos5420_fixed_rate_clks,
            ARRAY_SIZE(exynos5420_fixed_rate_clks));

    // ARRAY_SIZE(exynos5420_fixed_factor_clks): 1
    samsung_clk_register_fixed_factor(exynos5420_fixed_factor_clks,
            ARRAY_SIZE(exynos5420_fixed_factor_clks));
  • samsung_clk_register_fixed_factor() 에서 한일:
    • // struct clk_fixed_factor 만큼 메모리를 kmem_cache#30-oX 할당 받고 struct clk_fixed_factor 의 멤버 값을 아래와 같이 초기화 수행
    • //
    • // (kmem_cache#30-oX)->mult: 1
    • // (kmem_cache#30-oX)->div: 2
    • // (kmem_cache#30-oX)->hw.init: &init
    • //
    • // struct clk 만큼 메모리를 kmem_cache#29-oX (sclk_hsic_12m) 할당 받고 struct clk 의 멤버 값을 아래와 같이 초기화 수행
    • //
    • // (kmem_cache#29-oX (sclk_hsic_12m))->name: kmem_cache#30-oX ("sclk_hsic_12m")
    • // (kmem_cache#29-oX (sclk_hsic_12m))->ops: &clk_fixed_factor_ops
    • // (kmem_cache#29-oX (sclk_hsic_12m))->hw: &(kmem_cache#30-oX (sclk_hsic_12m))->hw
    • // (kmem_cache#29-oX (sclk_hsic_12m))->flags: 0x20
    • // (kmem_cache#29-oX (sclk_hsic_12m))->num_parents: 1
    • // (kmem_cache#29-oX (sclk_hsic_12m))->parent_names: kmem_cache#30-oX
    • // (kmem_cache#29-oX (sclk_hsic_12m))->parent_names[0]: (kmem_cache#30-oX)[0]: kmem_cache#30-oX: "fin_pll"
    • // (kmem_cache#29-oX (sclk_hsic_12m))->parent: kmem_cache#29-oX (fin_pll)
    • // (kmem_cache#29-oX (sclk_hsic_12m))->rate: 12000000
    • //
    • // (&(kmem_cache#29-oX (sclk_hsic_12m))->child_node)->next: NULL
    • // (&(kmem_cache#29-oX (sclk_hsic_12m))->child_node)->pprev: &(&(kmem_cache#29-oX (sclk_hsic_12m))->child_node)
    • //
    • // (&(kmem_cache#29-oX (fin_pll))->children)->first: &(kmem_cache#29-oX (sclk_hsic_12m))->child_node
    • //
    • // (&(kmem_cache#30-oX (sclk_hsic_12m))->hw)->clk: kmem_cache#29-oX (sclk_hsic_12m)
    • //
    • // clk_table[0]: (kmem_cache#23-o0)[0]: kmem_cache#29-oX (sclk_hsic_12m)

* samsung_clk_register_mux()

```clk-exynos5420.c
static void __init exynos5420_clk_init(struct device_node *np)
{
    if (np) {
        // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
        // of_iomap(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소, 0): 0xf0040000
        reg_base = of_iomap(np, 0); 
        // reg_base: 0xf0040000

        // reg_base: 0xf0040000
        if (!reg_base)
            panic("%s: failed to map registers\n", __func__);
    } else {
        panic("%s: unable to determine soc\n", __func__);
    }

    // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소, reg_base: 0xf0040000, nr_clks: 769
    // ARRAY_SIZE(exynos5420_clk_regs): 59
    samsung_clk_init(np, reg_base, nr_clks,
            exynos5420_clk_regs, ARRAY_SIZE(exynos5420_clk_regs),
            NULL, 0);

    // ARRAY_SIZE(exynos5420_fixed_rate_ext_clks): 1
    samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks,
            ARRAY_SIZE(exynos5420_fixed_rate_ext_clks),
            ext_clk_match);

    // ARRAY_SIZE(exynos5420_plls): 11, reg_base: 0xf0040000
    samsung_clk_register_pll(exynos5420_plls, ARRAY_SIZE(exynos5420_plls),
                    reg_base);

    // ARRAY_SIZE(exynos5420_fixed_rate_clks): 5
    samsung_clk_register_fixed_rate(exynos5420_fixed_rate_clks,
            ARRAY_SIZE(exynos5420_fixed_rate_clks));

    // ARRAY_SIZE(exynos5420_fixed_factor_clks): 1
    samsung_clk_register_fixed_factor(exynos5420_fixed_factor_clks,
            ARRAY_SIZE(exynos5420_fixed_factor_clks));

    // ARRAY_SIZE(exynos5420_mux_clks): 85
    samsung_clk_register_mux(exynos5420_mux_clks,
            ARRAY_SIZE(exynos5420_mux_clks));
  • samsung_clk_register_mux() 에서 한일:
    • // mout_mspll_kfc, sclk_spll를 수행한 결과:
    • //
    • // (mout_mspll_kfc) 에서 한일:
      • // struct clk_mux 만큼 메모리를 kmem_cache#30-oX (mout_mspll_kfc) 할당 받고 struct clk_mux 의 멤버 값을 아래와 같이 초기화 수행
    • //
    • // (kmem_cache#30-oX)->reg: 0xf005021c
    • // (kmem_cache#30-oX)->shift: 8
    • // (kmem_cache#30-oX)->mask: 0x3
    • // (kmem_cache#30-oX)->flags: 0
    • // (kmem_cache#30-oX)->lock: &lock
    • // (kmem_cache#30-oX)->table: NULL
    • // (kmem_cache#30-oX)->hw.init: &init
    • //
    • // struct clk 만큼 메모리를 kmem_cache#29-oX (mout_mspll_kfc) 할당 받고 struct clk 의 멤버 값을 아래와 같이 초기화 수행
    • //
    • // (kmem_cache#29-oX (mout_mspll_kfc))->name: kmem_cache#30-oX ("mout_mspll_kfc")
    • // (kmem_cache#29-oX (mout_mspll_kfc))->ops: &clk_mux_ops
    • // (kmem_cache#29-oX (mout_mspll_kfc))->hw: &(kmem_cache#30-oX (mout_mspll_kfc))->hw
    • // (kmem_cache#29-oX (mout_mspll_kfc))->flags: 0xa0
    • // (kmem_cache#29-oX (mout_mspll_kfc))->num_parents 4
    • // (kmem_cache#29-oX (mout_mspll_kfc))->parent_names: kmem_cache#30-oX
    • // (kmem_cache#29-oX (mout_mspll_kfc))->parent_names[0]: (kmem_cache#30-oX)[0]: kmem_cache#30-oX: "sclk_cpll"
    • // (kmem_cache#29-oX (mout_mspll_kfc))->parent_names[1]: (kmem_cache#30-oX)[1]: kmem_cache#30-oX: "sclk_dpll"
    • // (kmem_cache#29-oX (mout_mspll_kfc))->parent_names[2]: (kmem_cache#30-oX)[2]: kmem_cache#30-oX: "sclk_mpll"
    • // (kmem_cache#29-oX (mout_mspll_kfc))->parent_names[3]: (kmem_cache#30-oX)[3]: kmem_cache#30-oX: "sclk_spll"
    • // (kmem_cache#29-oX (mout_mspll_kfc))->parent: NULL
    • // (kmem_cache#29-oX (mout_mspll_kfc))->rate: 0
    • //
    • // (kmem_cache#29-oX (mout_mspll_kfc))->parents: kmem_cache#30-oX
    • // (kmem_cache#29-oX (mout_mspll_kfc))->parents[0...3]: (kmem_cache#30-oX)[0...3]: NULL
    • //
    • // (&(kmem_cache#29-oX (mout_mspll_kfc))->child_node)->next: NULL
    • // (&(kmem_cache#29-oX (mout_mspll_kfc))->child_node)->pprev: &(&(kmem_cache#29-oX (mout_mspll_kfc))->child_node)
    • //
    • // (&clk_orphan_list)->first: &(kmem_cache#29-oX (mout_mspll_kfc))->child_node
    • //
    • // (&(kmem_cache#30-oX (mout_mspll_kfc))->hw)->clk: kmem_cache#29-oX (mout_mspll_kfc)
    • // (sclk_spll) 에서 한일:
      • // struct clk_mux 만큼 메모리를 kmem_cache#30-oX (sclk_spll) 할당 받고 struct clk_mux 의 멤버 값을 아래와 같이 초기화 수행
    • //
    • // (kmem_cache#30-oX)->reg: 0xf0050218
    • // (kmem_cache#30-oX)->shift: 8
    • // (kmem_cache#30-oX)->mask: 0x3
    • // (kmem_cache#30-oX)->flags: 0
    • // (kmem_cache#30-oX)->lock: &lock
    • // (kmem_cache#30-oX)->table: NULL
    • // (kmem_cache#30-oX)->hw.init: &init
    • //
    • // struct clk 만큼 메모리를 kmem_cache#29-oX (sclk_spll) 할당 받고 struct clk 의 멤버 값을 아래와 같이 초기화 수행
    • //
    • // (kmem_cache#29-oX (sclk_spll))->name: kmem_cache#30-oX ("sclk_spll")
    • // (kmem_cache#29-oX (sclk_spll))->ops: &clk_mux_ops
    • // (kmem_cache#29-oX (sclk_spll))->hw: &(kmem_cache#30-oX (sclk_spll))->hw
    • // (kmem_cache#29-oX (sclk_spll))->flags: 0xa0
    • // (kmem_cache#29-oX (sclk_spll))->num_parents 2
    • // (kmem_cache#29-oX (sclk_spll))->parent_names: kmem_cache#30-oX
    • // (kmem_cache#29-oX (sclk_spll))->parent_names[0]: (kmem_cache#30-oX)[0]: kmem_cache#30-oX: "fin_pll"
    • // (kmem_cache#29-oX (sclk_spll))->parent_names[1]: (kmem_cache#30-oX)[1]: kmem_cache#30-oX: "fout_spll"
    • // (kmem_cache#29-oX (sclk_spll))->parent: NULL
    • // (kmem_cache#29-oX (sclk_spll))->rate: 600000000
    • //
    • // (kmem_cache#29-oX (sclk_spll))->parents: kmem_cache#30-oX
    • // (kmem_cache#29-oX (sclk_spll))->parents[0]: (kmem_cache#30-oX)[0]: kmem_cache#29-oX (fin_pll)
    • // (kmem_cache#29-oX (sclk_spll))->parents[1]: (kmem_cache#30-oX)[1]: kmem_cache#29-oX (fout_spll)
    • //
    • // parents 인 "fin_pll", "fout_spll" 값들 중에
    • // register CLK_SRC_TOP6 의 값을 읽어서 mux 할 parent clock 을 선택함
    • // return된 값이 선택된 parent clock의 index 값임
    • // parent clock 중에 선택된 parent clock의 이름으로 등록된 clk struct를 반환함
    • //
    • // (&(kmem_cache#29-oX (sclk_spll))->child_node)->next: NULL
    • // (&(kmem_cache#29-oX (sclk_spll))->child_node)->pprev: &(&(kmem_cache#29-oX (sclk_spll))->child_node)
    • //
    • // (&(kmem_cache#29-oX (fout_spll))->children)->first: &(kmem_cache#29-oX (sclk_spll))->child_node
    • //
    • // (&(kmem_cache#30-oX (sclk_spll))->hw)->clk: kmem_cache#29-oX (sclk_spll)
    • //
    • // orphan 으로 등록된 mout_mspll_kfc의 값을 갱신
    • // (&(kmem_cache#29-oX (mout_mspll_kfc))->child_node)->next: NULL
    • // (&(kmem_cache#29-oX (mout_mspll_kfc))->child_node)->pprev: &(&(kmem_cache#29-oX (mout_mspll_kfc))->child_node)
    • //
    • // (&(kmem_cache#29-oX (sclk_spll))->children)->first: &(kmem_cache#29-oX (mout_mspll_kfc))->child_node
    • //
    • // (kmem_cache#29-oX (mout_mspll_kfc))->parent: kmem_cache#29-oX (sclk_spll)
    • //
    • // parent가 있는지 확인후 parent의 clock rate 값으로 clock rate 값을 세팅
    • // (kmem_cache#29-oX (mout_mspll_kfc))->rate: 600000000
  • samsung_clk_register_div()
static void __init exynos5420_clk_init(struct device_node *np)
{
    if (np) {
        // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
        // of_iomap(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소, 0): 0xf0040000
        reg_base = of_iomap(np, 0); 
        // reg_base: 0xf0040000

        // reg_base: 0xf0040000
        if (!reg_base)
            panic("%s: failed to map registers\n", __func__);
    } else {
        panic("%s: unable to determine soc\n", __func__);
    }

    // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소, reg_base: 0xf0040000, nr_clks: 769
    // ARRAY_SIZE(exynos5420_clk_regs): 59
    samsung_clk_init(np, reg_base, nr_clks,
            exynos5420_clk_regs, ARRAY_SIZE(exynos5420_clk_regs),
            NULL, 0);

    // ARRAY_SIZE(exynos5420_fixed_rate_ext_clks): 1
    samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks,
            ARRAY_SIZE(exynos5420_fixed_rate_ext_clks),
            ext_clk_match);

    // ARRAY_SIZE(exynos5420_plls): 11, reg_base: 0xf0040000
    samsung_clk_register_pll(exynos5420_plls, ARRAY_SIZE(exynos5420_plls),
                    reg_base);

    // ARRAY_SIZE(exynos5420_fixed_rate_clks): 5
    samsung_clk_register_fixed_rate(exynos5420_fixed_rate_clks,
            ARRAY_SIZE(exynos5420_fixed_rate_clks));

    // ARRAY_SIZE(exynos5420_fixed_factor_clks): 1
    samsung_clk_register_fixed_factor(exynos5420_fixed_factor_clks,
            ARRAY_SIZE(exynos5420_fixed_factor_clks));

    // ARRAY_SIZE(exynos5420_mux_clks): 85
    samsung_clk_register_mux(exynos5420_mux_clks,
            ARRAY_SIZE(exynos5420_mux_clks));

    // ARRAY_SIZE(exynos5420_div_clks): 53
    samsung_clk_register_div(exynos5420_div_clks,
            ARRAY_SIZE(exynos5420_div_clks));
  • samsung_clk_register_div() 에서 한일:
    • // exynos5420_div_clks의 div 들 중에 array index 1번의
    • // DIV(none, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3) 을 가지고 분석 진행
    • //
    • // struct clk_divider 만큼 메모리를 할당 받아 맴버값 초기화 수행
    • // kmem_cache#30-oX (sclk_apll)
    • // (kmem_cache#30-oX (sclk_apll))->reg: 0xf0040500
    • // (kmem_cache#30-oX (sclk_apll))->shift: 24
    • // (kmem_cache#30-oX (sclk_apll))->width: 3
    • // (kmem_cache#30-oX (sclk_apll))->flags: 0
    • // (kmem_cache#30-oX (sclk_apll))->lock: &lock
    • // (kmem_cache#30-oX (sclk_apll))->hw.init: &init
    • // (kmem_cache#30-oX (sclk_apll))->table: NULL
    • //
    • // struct clk 만큼 메모리를 할당 받아 맴버값 초기화 수행
    • // kmem_cache#29-oX (sclk_apll)
    • // (kmem_cache#29-oX (sclk_apll))->name: kmem_cache#30-oX ("sclk_apll")
    • // (kmem_cache#29-oX (sclk_apll))->ops: &clk_divider_ops
    • // (kmem_cache#29-oX (sclk_apll))->hw: &(kmem_cache#30-oX (sclk_apll))->hw
    • // (kmem_cache#29-oX (sclk_apll))->flags: 0x0
    • // (kmem_cache#29-oX (sclk_apll))->num_parents 1
    • // (kmem_cache#29-oX (sclk_apll))->parent_names[0]: (kmem_cache#30-oX)[0]: kmem_cache#30-oX: "mout_apll"
    • // (kmem_cache#29-oX (sclk_apll))->parent: kmem_cache#29-oX (mout_apll)
    • // (kmem_cache#29-oX (sclk_apll))->rate: 800000000
    • //
    • // clk 의 이름이 "mout_apll"인 메모리 값을 clk_root_list 에서 찾아 리턴 수행
    • //
    • // (&(kmem_cache#29-oX (sclk_apll))->child_node)->next: NULL
    • // (&(kmem_cache#29-oX (sclk_apll))->child_node)->pprev: &(&(kmem_cache#29-oX (sclk_apll))->child_node)
    • //
    • // (&(kmem_cache#29-oX (mout_apll))->children)->first: &(kmem_cache#29-oX (sclk_apll))->child_node
    • //
    • // exynos5420_div_clks의 idx 0, 2...52 까지 loop 수행
  • samsung_clk_register_gate()
static void __init exynos5420_clk_init(struct device_node *np)
{
    if (np) {
        // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
        // of_iomap(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소, 0): 0xf0040000
        reg_base = of_iomap(np, 0); 
        // reg_base: 0xf0040000

        // reg_base: 0xf0040000
        if (!reg_base)
            panic("%s: failed to map registers\n", __func__);
    } else {
        panic("%s: unable to determine soc\n", __func__);
    }

    // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소, reg_base: 0xf0040000, nr_clks: 769
    // ARRAY_SIZE(exynos5420_clk_regs): 59
    samsung_clk_init(np, reg_base, nr_clks,
            exynos5420_clk_regs, ARRAY_SIZE(exynos5420_clk_regs),
            NULL, 0);

    // ARRAY_SIZE(exynos5420_fixed_rate_ext_clks): 1
    samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks,
            ARRAY_SIZE(exynos5420_fixed_rate_ext_clks),
            ext_clk_match);

    // ARRAY_SIZE(exynos5420_plls): 11, reg_base: 0xf0040000
    samsung_clk_register_pll(exynos5420_plls, ARRAY_SIZE(exynos5420_plls),
                    reg_base);

    // ARRAY_SIZE(exynos5420_fixed_rate_clks): 5
    samsung_clk_register_fixed_rate(exynos5420_fixed_rate_clks,
            ARRAY_SIZE(exynos5420_fixed_rate_clks));

    // ARRAY_SIZE(exynos5420_fixed_factor_clks): 1
    samsung_clk_register_fixed_factor(exynos5420_fixed_factor_clks,
            ARRAY_SIZE(exynos5420_fixed_factor_clks));

    // ARRAY_SIZE(exynos5420_mux_clks): 85
    samsung_clk_register_mux(exynos5420_mux_clks,
            ARRAY_SIZE(exynos5420_mux_clks));

    // ARRAY_SIZE(exynos5420_div_clks): 53
    samsung_clk_register_div(exynos5420_div_clks,
            ARRAY_SIZE(exynos5420_div_clks));

    // ARRAY_SIZE(exynos5420_gate_clks): 136
    samsung_clk_register_gate(exynos5420_gate_clks,
            ARRAY_SIZE(exynos5420_gate_clks));
  • call: start_kernel()->time_init()->of_clk_init()->exynos5420_clk_init()
    • // clk_init_cb: exynos5420_clk_init,
    • // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
    • // exynos5420_clk_init(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소)
    • clk_init_cb(np);
      • reg_base = of_iomap(np, 0);
    • samsung_clk_init()
    • samsung_clk_of_register_fixed_ext()
    • samsung_clk_register_pll()
    • samsung_clk_register_fixed_rate()
    • samsung_clk_register_fixed_factor()
    • samsung_clk_register_mux()
    • samsung_clk_register_div()
    • samsung_clk_register_gate()

samsung_clk_register_gate()

  • called: start_kernel()->time_init()->of_clk_init()->exynos5420_clk_init()
    • // clk_init_cb: exynos5420_clk_init,
    • // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
    • // exynos5420_clk_init(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소)
    • clk_init_cb(np);
      • reg_base = of_iomap(np, 0);
    • samsung_clk_init()
    • samsung_clk_of_register_fixed_ext()
    • samsung_clk_register_pll()
    • samsung_clk_register_fixed_rate()
    • samsung_clk_register_fixed_factor()
    • samsung_clk_register_mux()
    • samsung_clk_register_div()
    • samsung_clk_register_gate()
/* register a list of gate clocks */
// ARM10C 20150307
// exynos5420_gate_clks, ARRAY_SIZE(exynos5420_gate_clks): 136
void __init samsung_clk_register_gate(struct samsung_gate_clock *list,
                        unsigned int nr_clk)
{
    struct clk *clk;
    unsigned int idx, ret;

    // NOTE:
    // exynos5420_gate_clks의 gate 들 중에 array index 36번의
    // GATE(sclk_fimd1, "sclk_fimd1", "dout_fimd1", GATE_TOP_SCLK_PERIC, 0, CLK_SET_RATE_PARENT, 0) 을 가지고 분석 진행

    // nr_clk: 136
    for (idx = 0; idx < nr_clk; idx++, list++) {
        // idx: 36,
        // list->name: exynos5420_gate_clks[36].name: "sclk_fimd1",
        // list->parent_name: exynos5420_gate_clks[36].parent_name: "dout_fimd1",
        // list->flags: exynos5420_gate_clks[36].flags: 0x4,
        // list->offset: exynos5420_gate_clks[36].offset: 0x10828,
        // list->bit_idx: exynos5420_gate_clks[36].bit_idx: 0,
        // list->gate_flags: exynos5420_gate_clks[36].gate_flags: 0,
        // &lock
        // reg_base: 0xf0040000
        // clk_register_gate(NULL, "sclk_fimd1", "dout_fimd1", 0x4, 0xf0050828, 0, 0, &lock): kmem_cache#29-oX (sclk_fimd1)
        clk = clk_register_gate(NULL, list->name, list->parent_name,
                list->flags, reg_base + list->offset,
                list->bit_idx, list->gate_flags, &lock);
  • return: start_kernel()->time_init()->of_clk_init()->exynos5420_clk_init()->clk_register_gate()
    • // clk_init_cb: exynos5420_clk_init,
    • // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
    • // exynos5420_clk_init(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소)
    • clk_init_cb(np);
      • reg_base = of_iomap(np, 0);
    • samsung_clk_init()
    • samsung_clk_of_register_fixed_ext()
    • samsung_clk_register_pll()
    • samsung_clk_register_fixed_rate()
    • samsung_clk_register_fixed_factor()
    • samsung_clk_register_mux()
    • samsung_clk_register_div()
    • samsung_clk_register_gate()

exynos5420_clk_init()

  • return: start_kernel()->time_init()->of_clk_init()->exynos5420_clk_init()->clk_register_gate()
    • // clk_init_cb: exynos5420_clk_init,
    • // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
    • // exynos5420_clk_init(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소)
    • clk_init_cb(np);
      • reg_base = of_iomap(np, 0);
    • samsung_clk_init()
    • samsung_clk_of_register_fixed_ext()
    • samsung_clk_register_pll()
    • samsung_clk_register_fixed_rate()
    • samsung_clk_register_fixed_factor()
    • samsung_clk_register_mux()
    • samsung_clk_register_div()
    • samsung_clk_register_gate()
static void __init exynos5420_clk_init(struct device_node *np)
{
    if (np) {
        // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
        // of_iomap(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소, 0): 0xf0040000
        reg_base = of_iomap(np, 0); 
        // reg_base: 0xf0040000

        // reg_base: 0xf0040000
        if (!reg_base)
            panic("%s: failed to map registers\n", __func__);
    } else {
        panic("%s: unable to determine soc\n", __func__);
    }

    // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소, reg_base: 0xf0040000, nr_clks: 769
    // ARRAY_SIZE(exynos5420_clk_regs): 59
    samsung_clk_init(np, reg_base, nr_clks,
            exynos5420_clk_regs, ARRAY_SIZE(exynos5420_clk_regs),
            NULL, 0);

    // ARRAY_SIZE(exynos5420_fixed_rate_ext_clks): 1
    samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks,
            ARRAY_SIZE(exynos5420_fixed_rate_ext_clks),
            ext_clk_match);

    // ARRAY_SIZE(exynos5420_plls): 11, reg_base: 0xf0040000
    samsung_clk_register_pll(exynos5420_plls, ARRAY_SIZE(exynos5420_plls),
                    reg_base);

    // ARRAY_SIZE(exynos5420_fixed_rate_clks): 5
    samsung_clk_register_fixed_rate(exynos5420_fixed_rate_clks,
            ARRAY_SIZE(exynos5420_fixed_rate_clks));

    // ARRAY_SIZE(exynos5420_fixed_factor_clks): 1
    samsung_clk_register_fixed_factor(exynos5420_fixed_factor_clks,
            ARRAY_SIZE(exynos5420_fixed_factor_clks));

    // ARRAY_SIZE(exynos5420_mux_clks): 85
    samsung_clk_register_mux(exynos5420_mux_clks,
            ARRAY_SIZE(exynos5420_mux_clks));

    // ARRAY_SIZE(exynos5420_div_clks): 53
    samsung_clk_register_div(exynos5420_div_clks,
            ARRAY_SIZE(exynos5420_div_clks));

    // ARRAY_SIZE(exynos5420_gate_clks): 136
    samsung_clk_register_gate(exynos5420_gate_clks,
            ARRAY_SIZE(exynos5420_gate_clks));
  • clk = clk_register_gate(NULL, list->name, list->parent_name,...);
    • // clk_register_gate(sclk_fimd1)에서 한일:
    • // struct clk_gate 만큼 메모리를 할당 받아 맴버값 초기화 수행
    • / kmem_cache#30-oX (sclk_fimd1)
    • // (kmem_cache#30-oX (sclk_fimd1))->reg: 0xf0050828
    • // (kmem_cache#30-oX (sclk_fimd1))->bit_idx: 0
    • // (kmem_cache#30-oX (sclk_fimd1))->flags: 0
    • // (kmem_cache#30-oX (sclk_fimd1))->lock: &lock
    • // (kmem_cache#30-oX (sclk_fimd1))->hw.init: &init
    • // (kmem_cache#30-oX (sclk_fimd1))->table: NULL
    • //
    • // struct clk 만큼 메모리를 할당 받아 맴버값 초기화 수행
    • // kmem_cache#29-oX (sclk_fimd1)
    • // (kmem_cache#29-oX (sclk_fimd1))->name: kmem_cache#30-oX ("sclk_fimd1")
    • // (kmem_cache#29-oX (sclk_fimd1))->ops: &clk_gate_ops
    • // (kmem_cache#29-oX (sclk_fimd1))->hw: &(kmem_cache#30-oX (sclk_fimd1))->hw
    • // (kmem_cache#29-oX (sclk_fimd1))->flags: 0x0
    • // (kmem_cache#29-oX (sclk_fimd1))->num_parents 1
    • // (kmem_cache#29-oX (sclk_fimd1))->parent_names[0]: (kmem_cache#30-oX)[0]: kmem_cache#30-oX: "mout_apll"
    • // (kmem_cache#29-oX (sclk_fimd1))->parent: kmem_cache#29-oX (dout_fimd1)
    • // (kmem_cache#29-oX (sclk_fimd1))->rate: 266000000
    • //
    • // clk 의 이름이 "dout_fimd1"인 메모리 값을 clk_root_list 에서 찾아 리턴 수행
    • //
    • // (&(kmem_cache#29-oX (sclk_fimd1))->child_node)->next: NULL
    • // (&(kmem_cache#29-oX (sclk_fimd1))->child_node)->pprev: &(&(kmem_cache#29-oX (sclk_fimd1))->child_node)
    • //
    • // (&(kmem_cache#29-oX (dout_fimd1))->children)->first: &(kmem_cache#29-oX (sclk_fimd1))->child_node
  • call: start_kernel()->time_init()->of_clk_init()->exynos5420_clk_init()->clk_register_gate()->samsung_clk_add_lookup()
    • // clk_init_cb: exynos5420_clk_init,
    • // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
    • // exynos5420_clk_init(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소)
    • clk_init_cb(np);
      • reg_base = of_iomap(np, 0);
    • samsung_clk_init()
    • samsung_clk_of_register_fixed_ext()
    • samsung_clk_register_pll()
    • samsung_clk_register_fixed_rate()
    • samsung_clk_register_fixed_factor()
    • samsung_clk_register_mux()
    • samsung_clk_register_div()
    • samsung_clk_register_gate()
    • samsung_clk_add_lookup()

samsung_clk_add_lookup(clk, list->id);

  • called: start_kernel()->time_init()->of_clk_init()->exynos5420_clk_init()->clk_register_gate()->samsung_clk_add_lookup()
    • // clk_init_cb: exynos5420_clk_init,
    • // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
    • // exynos5420_clk_init(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소)
    • clk_init_cb(np);
      • reg_base = of_iomap(np, 0);
    • samsung_clk_init()
    • samsung_clk_of_register_fixed_ext()
    • samsung_clk_register_pll()
    • samsung_clk_register_fixed_rate()
    • samsung_clk_register_fixed_factor()
    • samsung_clk_register_mux()
    • samsung_clk_register_div()
    • samsung_clk_register_gate()
    • samsung_clk_add_lookup()
/* register a list of gate clocks */
// ARM10C 20150307
// exynos5420_gate_clks, ARRAY_SIZE(exynos5420_gate_clks): 136
void __init samsung_clk_register_gate(struct samsung_gate_clock *list,
                        unsigned int nr_clk)
{
    struct clk *clk;
    unsigned int idx, ret;

    // NOTE:
    // exynos5420_gate_clks의 gate 들 중에 array index 36번의
    // GATE(sclk_fimd1, "sclk_fimd1", "dout_fimd1", GATE_TOP_SCLK_PERIC, 0, CLK_SET_RATE_PARENT, 0) 을 가지고 분석 진행

    // nr_clk: 136
    for (idx = 0; idx < nr_clk; idx++, list++) {
        // idx: 36,
        // list->name: exynos5420_gate_clks[36].name: "sclk_fimd1",
        // list->parent_name: exynos5420_gate_clks[36].parent_name: "dout_fimd1",
        // list->flags: exynos5420_gate_clks[36].flags: 0x4,
        // list->offset: exynos5420_gate_clks[36].offset: 0x10828,
        // list->bit_idx: exynos5420_gate_clks[36].bit_idx: 0,
        // list->gate_flags: exynos5420_gate_clks[36].gate_flags: 0,
        // &lock
        // reg_base: 0xf0040000
        // clk_register_gate(NULL, "sclk_fimd1", "dout_fimd1", 0x4, 0xf0050828, 0, 0, &lock): kmem_cache#29-oX (sclk_fimd1)
        clk = clk_register_gate(NULL, list->name, list->parent_name,
                list->flags, reg_base + list->offset,
                list->bit_idx, list->gate_flags, &lock);
        // clk: kmem_cache#29-oX (sclk_fimd1)

        // clk: kmem_cache#29-oX (sclk_fimd1), IS_ERR(kmem_cache#29-oX (sclk_fimd1)): 0
        if (IS_ERR(clk)) {
            pr_err("%s: failed to register clock %s\n", __func__,
                list->name);
            continue;
        }

        /* register a clock lookup only if a clock alias is specified */
        // list->alias: exynos5420_gate_clks[36].alias: NULL
        if (list->alias) {
            ret = clk_register_clkdev(clk, list->alias,
                            list->dev_name);
            if (ret)
                pr_err("%s: failed to register lookup %s\n",
                    __func__, list->alias);
        }

        // clk: kmem_cache#29-oX (sclk_fimd1), list->id: exynos5420_gate_clks[36].id: 136
        samsung_clk_add_lookup(clk, list->id);
  • call: start_kernel()->time_init()->of_clk_init()->exynos5420_clk_init()
    • // clk_init_cb: exynos5420_clk_init,
    • // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
    • // exynos5420_clk_init(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소)
    • clk_init_cb(np);
      • reg_base = of_iomap(np, 0);
    • samsung_clk_init()
    • samsung_clk_of_register_fixed_ext()
    • samsung_clk_register_pll()
    • samsung_clk_register_fixed_rate()
    • samsung_clk_register_fixed_factor()
    • samsung_clk_register_mux()
    • samsung_clk_register_div()
    • samsung_clk_register_gate()
      • clk = clk_register_gate()
      • samsung_clk_add_lookup()

samsung_clk_add_lookup()

  • call: start_kernel()->time_init()->of_clk_init()->exynos5420_clk_init()
    • // clk_init_cb: exynos5420_clk_init,
    • // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
    • // exynos5420_clk_init(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소)
    • clk_init_cb(np);
      • reg_base = of_iomap(np, 0);
    • samsung_clk_init()
    • samsung_clk_of_register_fixed_ext()
    • samsung_clk_register_pll()
    • samsung_clk_register_fixed_rate()
    • samsung_clk_register_fixed_factor()
    • samsung_clk_register_mux()
    • samsung_clk_register_div()
    • samsung_clk_register_gate()
      • clk = clk_register_gate()
      • samsung_clk_add_lookup()
  • saumsung_clk_add_lookup()
// ARM10C 20150307
// clk: kmem_cache#29-oX (sclk_fimd1), list->id: exynos5420_gate_clks[13].id: 128
void samsung_clk_add_lookup(struct clk *clk, unsigned int id)
{
    // clk_table: kmem_cache#23-o0, id: 128
    if (clk_table && id)
        // clk_table: kmem_cache#23-o0, id: 128, clk_table[128]: (kmem_cache#23-o0)[128],
        // clk: kmem_cache#29-oX (sclk_fimd1)
        clk_table[id] = clk;
        // clk_table[128]: (kmem_cache#23-o0)[128]: kmem_cache#29-oX (sclk_fimd1)
}
  • return: start_kernel()->time_init()->of_clk_init()->exynos5420_clk_init()
    • // clk_init_cb: exynos5420_clk_init,
    • // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
    • // exynos5420_clk_init(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소)
    • clk_init_cb(np);
      • reg_base = of_iomap(np, 0);
    • samsung_clk_init()
    • samsung_clk_of_register_fixed_ext()
    • samsung_clk_register_pll()
    • samsung_clk_register_fixed_rate()
    • samsung_clk_register_fixed_factor()
    • samsung_clk_register_mux()
    • samsung_clk_register_div()
    • samsung_clk_register_gate()
      • clk = clk_register_gate()
      • samsung_clk_add_lookup()

samsung_clk_register_gate()

  • return: start_kernel()->time_init()->of_clk_init()->exynos5420_clk_init()
    • // clk_init_cb: exynos5420_clk_init,
    • // np: devtree에서 allnext로 순회 하면서 찾은 clock node의 주소
    • // exynos5420_clk_init(devtree에서 allnext로 순회 하면서 찾은 clock node의 주소)
    • clk_init_cb(np);
      • reg_base = of_iomap(np, 0);
    • samsung_clk_init()
    • samsung_clk_of_register_fixed_ext()
    • samsung_clk_register_pll()
    • samsung_clk_register_fixed_rate()
    • samsung_clk_register_fixed_factor()
    • samsung_clk_register_mux()
    • samsung_clk_register_div()
    • samsung_clk_register_gate()
      • clk = clk_register_gate()
      • samsung_clk_add_lookup()
/* register a list of gate clocks */
// ARM10C 20150307
// exynos5420_gate_clks, ARRAY_SIZE(exynos5420_gate_clks): 136
void __init samsung_clk_register_gate(struct samsung_gate_clock *list,
                        unsigned int nr_clk)
{
    struct clk *clk;
    unsigned int idx, ret;

    // NOTE:
    // exynos5420_gate_clks의 gate 들 중에 array index 36번의
    // GATE(sclk_fimd1, "sclk_fimd1", "dout_fimd1", GATE_TOP_SCLK_PERIC, 0, CLK_SET_RATE_PARENT, 0) 을 가지고 분석 진행

    // nr_clk: 136
    for (idx = 0; idx < nr_clk; idx++, list++) {
        // idx: 36,
        // list->name: exynos5420_gate_clks[36].name: "sclk_fimd1",
        // list->parent_name: exynos5420_gate_clks[36].parent_name: "dout_fimd1",
        // list->flags: exynos5420_gate_clks[36].flags: 0x4,
        // list->offset: exynos5420_gate_clks[36].offset: 0x10828,
        // list->bit_idx: exynos5420_gate_clks[36].bit_idx: 0,
        // list->gate_flags: exynos5420_gate_clks[36].gate_flags: 0,
        // &lock
        // reg_base: 0xf0040000
        // clk_register_gate(NULL, "sclk_fimd1", "dout_fimd1", 0x4, 0xf0050828, 0, 0, &lock): kmem_cache#29-oX (sclk_fimd1)
        clk = clk_register_gate(NULL, list->name, list->parent_name,
                list->flags, reg_base + list->offset,
                list->bit_idx, list->gate_flags, &lock);
        // clk: kmem_cache#29-oX (sclk_fimd1)

        // clk: kmem_cache#29-oX (sclk_fimd1), IS_ERR(kmem_cache#29-oX (sclk_fimd1)): 0
        if (IS_ERR(clk)) {
            pr_err("%s: failed to register clock %s\n", __func__,
                list->name);
            continue;
        }

        /* register a clock lookup only if a clock alias is specified */
        // list->alias: exynos5420_gate_clks[36].alias: NULL
        if (list->alias) {
            ret = clk_register_clkdev(clk, list->alias,
                            list->dev_name);
            if (ret)
                pr_err("%s: failed to register lookup %s\n",
                    __func__, list->alias);
        }

        // clk: kmem_cache#29-oX (sclk_fimd1), list->id: exynos5420_gate_clks[36].id: 136
        samsung_clk_add_lookup(clk, list->id);
  • samsung_clk_add_lookup() 에서 한 일:
    • // clk_table[136]: (kmem_cache#23-o0)[136]: kmem_cache#29-oX (sclk_fimd1)
    • // idx: 0...12...136 loop 수행

93th log

  • log
   48d2c6a..8dc44c0  master     -> origin/master
Updating 48d2c6a..8dc44c0
Fast-forward
arch/arm/kernel/time.c               | 401 ++++++++++++++++++++++++
arch/arm/kernel/vmlinux.lds.S        |   1 +
drivers/clk/clk-divider.c            |  55 +++-
drivers/clk/clk-gate.c               |  68 ++++-
drivers/clk/clk.c                    | 573 ++++++++++++++++++++++++++++++++++-
drivers/clk/samsung/clk-exynos5420.c | 102 +++++++
drivers/clk/samsung/clk.c            | 102 +++++++
drivers/clk/samsung/clk.h            |  39 +++
drivers/clocksource/arm_arch_timer.c |  16 +
drivers/clocksource/clksrc-of.c      |  20 ++
drivers/clocksource/exynos_mct.c     |  27 ++
drivers/of/base.c                    |  41 +++
drivers/of/irq.c                     | 188 +++++++++---
include/asm-generic/vmlinux.lds.h    |   6 +-
include/linux/clk-private.h          |   1 +
include/linux/clk-provider.h         |   8 +
include/linux/clocksource.h          |   3 +-
include/linux/gfp.h                  |   1 +
include/linux/mod_devicetable.h      |   1 +
include/linux/of.h                   |  10 +-
include/linux/of_irq.h               |   1 +
include/linux/slab.h                 |   2 +
22 files changed, 1622 insertions(+), 44 deletions(-)

댓글 없음:

댓글 쓰기