ARM Linux Kernel 102th weeks
์ผ์ : 2015.05.23 (102 ์ฃผ์ฐจ ์คํฐ๋ ์งํ)
๋ชจ์๋ช
: NAVER๊ฐ๋ฐ์์ปค๋ฎค๋ํฐ์ง์_IAMROOT.ORG_10์ฐจARM-C
์ฅ์ : ํ ์ฆ ํ์์
์ฅ์์ง์ : NAVER ๊ฐ๋ฐ์ ์ปค๋ฎค๋ํฐ ์ง์ ํ๋ก๊ทธ๋จ
1 1 start_kernel 1 ~/kernel/iamroot/linux-stable/init/main.c 2 1 time_init 743 ~/kernel/iamroot/linux-stable/init/main.c 3 1 clocksource_of_init 557 ~/kernel/iamroot/linux-stable/arch/arm/kernel/time.c 4 1 mct_init_spi 56 ~/kernel/iamroot/linux-stable/drivers/clocksource/clksrc-of.c 5 1 mct_init_dt 1420 return mct_init_dt(np, MCT_INT_SPI); 6 1 exynos4_clocksource_init 1410 exynos4_clocksource_init(); 7 1 exynos4_mct_frc_start 425 exynos4_mct_frc_start(0, 0)
main.c::start_kernel()->time_init()
called: start_kernel()->time_init()
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();
time.c::time_init()->of_clk_init(NULL)
called: start_kernel()->time_init()->of_clk_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 clocksource_of_init();
called: start_kernel()->time_init()->clocksource_of_init()
clksrc-of.c::time_init()->clocksource_of_init()
called: start_kernel()->time_init()->clocksource_of_init()
// ARM10C 20150307 void __init clocksource_of_init(void) { struct device_node *np; const struct of_device_id *match; clocksource_of_init_fn init_func; for_each_matching_node_and_match(np, __clksrc_of_table, &match) { // for (np = of_find_matching_node_and_match(NULL, __clksrc_of_table, &match); // np; np = of_find_matching_node_and_match(np, __clksrc_of_table, &match)) // np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, match: __clksrc_of_table_exynos4210 // np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์ // of_device_is_available(devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์): 1 if (!of_device_is_available(np)) continue; // match->data: __clksrc_of_table_exynos4210.data: mct_init_spi init_func = match->data; // init_func: mct_init_spi // init_func: mct_init_spi // np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์ // mct_init_spi(devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์) init_func(np);
init_func(np) ์์ ํธ์ถํ๋ ํจ์.
DTB์ ๋ณด๋ฉด exynos4210-mct ๋ก mct_init_spi()๊ฐ ์ ์๋์๋ค.
// ARM10C 20150307 // #define CLOCKSOURCE_OF_DECLARE(exynos4210, "samsung,exynos4210-mct", mct_init_spi): // static const struct of_device_id __clksrc_of_table_exynos4210 __used __section(__clksrc_of_table) // = { .compatible = "samsung,exynos4210-mct", // .data = (mct_init_spi == (clocksource_of_init_fn)NULL) ? mct_init_spi : mct_init_spi } CLOCKSOURCE_OF_DECLARE(exynos4210, "samsung,exynos4210-mct", mct_init_spi); // ARM10C 20150307 // #define CLOCKSOURCE_OF_DECLARE(exynos4412, "samsung,exynos4412-mct", mct_init_ppi): // static const struct of_device_id __clksrc_of_table_exynos4412 __used __section(__clksrc_of_table) // = { .compatible = "samsung,exynos4412-mct", // .data = (mct_init_ppi == (clocksource_of_init_fn)NULL) ? mct_init_ppi : mct_init_ppi } CLOCKSOURCE_OF_DECLARE(exynos4412, "samsung,exynos4412-mct", mct_init_ppi);
call: start_kernel()->time_init()->clocksource_of_init()->init_func(np)
mct_init_spi(devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์)
exynos_mct.c::mct_init_spi()
called: start_kernel()->time_init()->clocksource_of_init()->init_func(np)
// mct_init_spi(devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์)
init_func(np)->mct_init_spi()
// ARM10C 20150307 // np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์ static void __init mct_init_spi(struct device_node *np) { // np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, MCT_INT_SPI: 0 return mct_init_dt(np, MCT_INT_SPI); }
call: start_kernel()->time_init()->clocksource_of_init()->init_func(np)
// np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, MCT_INT_SPI: 0
init_func(np):mct_init_spi()->mct_init_dt()
exynos_mct.c::mct_init_dt()
called: start_kernel()->time_init()->clocksource_of_init()->init_func(np)
// np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, MCT_INT_SPI: 0
init_func(np):mct_init_spi()->mct_init_dt()
// ARM10C 20150307 // np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, MCT_INT_SPI: 0 static void __init mct_init_dt(struct device_node *np, unsigned int int_type) { u32 nr_irqs, i; // int_type: 0 mct_int_type = int_type; // mct_int_type: 0 /* This driver uses only one global timer interrupt */ // np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, MCT_G0_IRQ: 0 // irq_of_parse_and_map(devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, 0): 347 mct_irqs[MCT_G0_IRQ] = irq_of_parse_and_map(np, MCT_G0_IRQ); // mct_irqs[0]: 347 // irq_of_parse_and_map(mct node, 0)์์ ํ์ผ: // devtree์ mct node์ interrupt์ property์ ๊ฐ์ dtb์ ๋ถ์ํ์ฌ oirq ๊ฐ์ ๊ฐ์ ธ์ด // // (&oirq)->np: combiner node์ ์ฃผ์ // (&oirq)->args_count: 2 // (&oirq)->args[0]: 23 // (&oirq)->args[1]: 3 // // oirq ๊ฐ์ ์ฌ์ฉํ์ฌ combiner domain์์ virq ๊ฐ์ ์ฐพ์ // virq: 347 /* * Find out the number of local irqs specified. The local * timer irqs are specified after the four global timer * irqs are specified. */ #ifdef CONFIG_OF // CONFIG_OF=y // np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์ // of_irq_count(devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์): 8 nr_irqs = of_irq_count(np); // nr_irqs: 8 // of_irq_count(mct node)์์ ํ์ผ: // devtree์ ๋ฑ๋ก๋ mct node์ irq ์ ๊ฐฏ์๋ฅผ ๊ตฌํจ #else nr_irqs = 0; #endif // nr_irqs: 8, MCT_L0_IRQ: 4 for (i = MCT_L0_IRQ; i < nr_irqs; i++) // i: 4, np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์ // irq_of_parse_and_map(devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, 4): 152 mct_irqs[i] = irq_of_parse_and_map(np, i); // mct_irqs[4]: 152 // irq_of_parse_and_map(mct node, 4)์์ ํ์ผ: // devtree์ mct node์ interrupt์ property์ ๊ฐ์ dtb์ ๋ถ์ํ์ฌ oirq ๊ฐ์ ๊ฐ์ ธ์ด // // (&oirq)->np: gic node์ ์ฃผ์ // (&oirq)->args_count: 3 // (&oirq)->args[0]: 0 // (&oirq)->args[1]: 120 // (&oirq)->args[2]: 0 // // oirq ๊ฐ์ ์ฌ์ฉํ์ฌ gic domain์์ virq ๊ฐ์ ์ฐพ์ // virq: 152 // i: 5...7 loop ์ํ // ์ loop์ ์ํ ๊ฒฐ๊ณผ // mct_irqs[4]: 152 // mct_irqs[5]: 153 // mct_irqs[6]: 154 // mct_irqs[7]: 155 // np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์ // of_iomap(devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, 0): 0xf0006000 exynos4_timer_resources(np, of_iomap(np, 0));
// cache์ ๊ฐ์ ์ ๋ถ ๋ฉ๋ชจ๋ฆฌ์ ๋ฐ์
call: start_kernel()->time_init()->clocksource_of_init()->init_func(np)
// np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, MCT_INT_SPI: 0
->init_func(np)->mct_init_spi()->mct_init_dt()
exynos4_timer_resources()
exynos_mct.c::exynos4_timer_resources()
called: start_kernel()->time_init()->clocksource_of_init()->init_func(np)
// np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, MCT_INT_SPI: 0
->init_func(np)->mct_init_spi()->mct_init_dt()
exynos4_timer_resources()
// ARM10C 20150307 // np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, MCT_INT_SPI: 0 static void __init mct_init_dt(struct device_node *np, unsigned int int_type) { u32 nr_irqs, i; // int_type: 0 mct_int_type = int_type; // mct_int_type: 0 /* This driver uses only one global timer interrupt */ // np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, MCT_G0_IRQ: 0 // irq_of_parse_and_map(devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, 0): 347 mct_irqs[MCT_G0_IRQ] = irq_of_parse_and_map(np, MCT_G0_IRQ); // mct_irqs[0]: 347 // irq_of_parse_and_map(mct node, 0)์์ ํ์ผ: // devtree์ mct node์ interrupt์ property์ ๊ฐ์ dtb์ ๋ถ์ํ์ฌ oirq ๊ฐ์ ๊ฐ์ ธ์ด // // (&oirq)->np: combiner node์ ์ฃผ์ // (&oirq)->args_count: 2 // (&oirq)->args[0]: 23 // (&oirq)->args[1]: 3 // // oirq ๊ฐ์ ์ฌ์ฉํ์ฌ combiner domain์์ virq ๊ฐ์ ์ฐพ์ // virq: 347 /* * Find out the number of local irqs specified. The local * timer irqs are specified after the four global timer * irqs are specified. */ #ifdef CONFIG_OF // CONFIG_OF=y // np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์ // of_irq_count(devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์): 8 nr_irqs = of_irq_count(np); // nr_irqs: 8 // of_irq_count(mct node)์์ ํ์ผ: // devtree์ ๋ฑ๋ก๋ mct node์ irq ์ ๊ฐฏ์๋ฅผ ๊ตฌํจ #else nr_irqs = 0; #endif // nr_irqs: 8, MCT_L0_IRQ: 4 for (i = MCT_L0_IRQ; i < nr_irqs; i++) // i: 4, np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์ // irq_of_parse_and_map(devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, 4): 152 mct_irqs[i] = irq_of_parse_and_map(np, i); // mct_irqs[4]: 152 // irq_of_parse_and_map(mct node, 4)์์ ํ์ผ: // devtree์ mct node์ interrupt์ property์ ๊ฐ์ dtb์ ๋ถ์ํ์ฌ oirq ๊ฐ์ ๊ฐ์ ธ์ด // // (&oirq)->np: gic node์ ์ฃผ์ // (&oirq)->args_count: 3 // (&oirq)->args[0]: 0 // (&oirq)->args[1]: 120 // (&oirq)->args[2]: 0 // // oirq ๊ฐ์ ์ฌ์ฉํ์ฌ gic domain์์ virq ๊ฐ์ ์ฐพ์ // virq: 152 // i: 5...7 loop ์ํ // ์ loop์ ์ํ ๊ฒฐ๊ณผ // mct_irqs[4]: 152 // mct_irqs[5]: 153 // mct_irqs[6]: 154 // mct_irqs[7]: 155 // np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์ // of_iomap(devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, 0): 0xf0006000 exynos4_timer_resources(np, of_iomap(np, 0)); exynos4_clocksource_init(); exynos4_clockevent_init(); }
exynos4_timer_resources() ์์ ํ์ผ
// of_iomap์์ ํ์ผ: // device tree ์๋ mct node์์ node์ resource ๊ฐ์ ๊ฐ์ ธ์ด // (&res)->start: 0x101C0000 // (&res)->end: 0x101C07ff // (&res)->flags: IORESOURCE_MEM: 0x00000200 // (&res)->name: "/mct@101C0000" /* // alloc area (MCT) ๋ฅผ ๋ง๋ค๊ณ rb tree์ alloc area ๋ฅผ ์ถ๊ฐ // ๊ฐ์์ฃผ์ va_start ๊ธฐ์ค์ผ๋ก MCT ๋ฅผ RB Tree ์ถ๊ฐํ ๊ฒฐ๊ณผ // // CHID-b // (0xF8000000) // / \ // CLK-b PMU-b // (0xF0040000) (0xF8180000) // / \ / \ // GIC#1-r TMR-r CMU-b SRAM-b // (0xF0002000) (0xF6300000) (0xF8100000) (0xF8400000) // / \ / \ \ // GIC#0-b COMB-b SYSC-b WDT-b ROMC-r // (0xF0000000) (0xF0004000) (0xF6100000) (0xF6400000) (0xF84C0000) // \ // MCT-r // (0xF0006000) // // vmap_area_list์ GIC#0 - GIC#1 - COMB - MCT - 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: 0xf0006000 // (kmem_cache#30-oX (vm_struct))->size: 0x2000 // (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 ์๋ mct node์์ node์ resource ๊ฐ์ pgtable์ ๋งคํํจ // 0xc0004780์ด ๊ฐ๋ฆฌํค๋ pte์ ์์์ฃผ์์ 0x101C0653 ๊ฐ์ ๊ฐฑ์ // (linux pgtable๊ณผ hardware pgtable์ ๊ฐ ๊ฐ์ด ๊ฐฑ์ ) // // pgd pte // | | // +--------------+ // | | +--------------+ +0 // | | | 0xXXXXXXXX | ---> 0x101C0653 ์ ๋งค์นญ๋๋ linux pgtable ๊ฐ // +- - - - - - - + | Linux pt 0 | // | | +--------------+ +1024 // | | | | // +--------------+ +0 | Linux pt 1 | // | *(c0004780) |-----> +--------------+ +2048 // | | | 0x101C0653 | ---> 2076 // +- - - - - - - + +4 | h/w pt 0 | // | *(c0004784) |-----> +--------------+ +3072 // | | + + // +--------------+ +8 | h/w pt 1 | // | | +--------------+ +4096 // // cache์ ๊ฐ์ ์ ๋ถ ๋ฉ๋ชจ๋ฆฌ์ ๋ฐ์ // exynos4_timer_resources์์ ํ์ผ: // // mct node์ property "clock-names" ์ ๊ฐ์ ์ฐพ์์ "fin_pll" ์ด ์๋ ์์น๋ฅผ ์ฐพ๊ณ // ๋ช๋ฒ์งธ ๊ฐ์ธ์ง index๋ฅผ ๊ตฌํจ // // mct node ์์ "clocks" property์ ์ด์ฉํ์ฌ devtree์ ๊ฐ์ ํ์ฑํ์ฌ clkspec์ ๊ฐ์ ๊ฐ์ ธ์ด // (&clkspec)->np: clock node์ ์ฃผ์ // (&clkspec)->args_count: 1 // (&clkspec)->args[0]: 1 // // list of_clk_providers ์ ๋ฑ๋ก๋ ์ ๋ณด๋ค ์ค์ clkspec ์ ๋งค์น๋๋ ์ ๋ณด๋ฅผ ์ฐพ์ // ์ด์ ์ ๋ง๋ค์ด ๋์ clk_data์ clk_table ์ ๋ณด๋ฅผ ์ด์ฉํ์ฌ clkspec์ ์๋ arg ๊ฐ์ ์ด์ฉํ์ฌ clk์ ์ฐพ์ // tick_clk: kmem_cache#29-oX (fin_pll) // // mct node์ property "clock-names" ์ ๊ฐ์ ์ฐพ์์ "mct" ์ด ์๋ ์์น๋ฅผ ์ฐพ๊ณ // ๋ช๋ฒ์งธ ๊ฐ์ธ์ง index๋ฅผ ๊ตฌํจ // // mct node ์์ "clocks" property์ ์ด์ฉํ์ฌ devtree์ ๊ฐ์ ํ์ฑํ์ฌ clkspec์ ๊ฐ์ ๊ฐ์ ธ์ด // (&clkspec)->np: clock node์ ์ฃผ์ // (&clkspec)->args_count: 1 // (&clkspec)->args[0]: 315 // // list of_clk_providers ์ ๋ฑ๋ก๋ ์ ๋ณด๋ค ์ค์ clkspec ์ ๋งค์น๋๋ ์ ๋ณด๋ฅผ ์ฐพ์ // ์ด์ ์ ๋ง๋ค์ด ๋์ clk_data์ clk_table ์ ๋ณด๋ฅผ ์ด์ฉํ์ฌ clkspec์ ์๋ arg ๊ฐ์ ์ด์ฉํ์ฌ clk์ ์ฐพ์ // mct_clk: kmem_cache#29-oX (mct) // // clk_prepare_enable์์ ํ์ผ: // mct clock์ ์์ clock ๋ค์ ops->prepare ํจ์๋ค์ ์ํ. // mct clock์ ์์ clock ๋ค์ ops->enable ํจ์๋ค์ ์ํ. // sck_cpll -- Group1_p -- mout_aclk66 -- dout_aclk66 -- mct // sck_ppll -| // sck_mpll -| // // sck_cpll, mout_aclk66, dout_aclk66 ์ ์ฃผ์์ ๋ง๋ค์ง ์์๊ธฐ ๋๋ฌธ์ // ๋ถ์๋ด์ฉ์ skip ํ๋๋กํจ // // Interrupt pending register์ธ GICD_ITARGETSR38 ๊ฐ์ ์ฝ๊ณ // ๊ทธ ๊ฐ๊ณผ mask ๊ฐ์ธ cpu_bit_bitmap[1][0] ์ or ์ฐ์ฐํ ๊ฐ์ GICD_ITARGETSR38์ // ๋ค์ writeํจ // // GICD_ITARGETSR38 ๊ฐ์ ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ 0x00000000 ๋ก // ์ฝํ๋ ๊ฒ์ผ๋ก ๊ฐ์ ํ๊ณ GICD_ITARGETSR38์ 0x00000001๋ฅผ write ํจ // CPU interface 0์ interrupt๊ฐ ๋ฐ์์ ๋ํ๋ // // (&(kmem_cache#28-oX (irq 152))->irq_data)->affinity->bits[0]: 1 // (&(kmem_cache#28-oX (irq 152))->irq_data)->state_use_accessors: 0x11000 // // register_cpu_notifier ์์ ํ์ผ: // (&cpu_chain)->head: &exynos4_mct_cpu_nb ํฌ์ธํฐ ๋์
// (&exynos4_mct_cpu_nb)->next์ (&hrtimers_nb)->next๋ก ๋์
// // [pcp0] (&percpu_mct_tick)->base: 0x300 // [pcp0] (&percpu_mct_tick)->name: "mct_tick0" // [pcp0] (&(&percpu_mct_tick)->evt)->name: "mct_tick0" // [pcp0] (&(&percpu_mct_tick)->evt)->cpumask: &cpu_bit_bitmap[1][0] // [pcp0] (&(&percpu_mct_tick)->evt)->set_next_event: exynos4_tick_set_next_event // [pcp0] (&(&percpu_mct_tick)->evt)->set_mode: exynos4_tick_set_mode // [pcp0] (&(&percpu_mct_tick)->evt)->features: 0x3 // [pcp0] (&(&percpu_mct_tick)->evt)->rating: 450 // [pcp0] (&(&percpu_mct_tick)->evt)->min_delta_ticks: 0xf // [pcp0] (&(&percpu_mct_tick)->evt)->max_delta_ticks: 0x7fffffff // [pcp0] (&(&percpu_mct_tick)->evt)->mult: 0x3126E98 // [pcp0] (&(&percpu_mct_tick)->evt)->shift: 32 // [pcp0] (&(&percpu_mct_tick)->evt)->min_delta_ns: 0x4E2 // [pcp0] (&(&percpu_mct_tick)->evt)->max_delta_ns: 0x29AAAAA444 // [pcp0] (&(&percpu_mct_tick)->evt)->next_event.tv64: 0x7FFFFFFFFFFFFFFF // [pcp0] (&(&percpu_mct_tick)->evt)->event_handler: tick_handle_periodic // [pcp0] (&(&percpu_mct_tick)->evt)->mode: 2 // [pcp0] (&(&percpu_mct_tick)->evt)->irq: 152 // // [pcp0] (&tick_cpu_device)->mode: 0 // [pcp0] (&tick_cpu_device)->evtdev: [pcp0] &(&percpu_mct_tick)->evt // // [pcp0] (&tick_cpu_sched)->check_clocks: 1 // // list clockevent_devices์ [pcp0] (&(&percpu_mct_tick)->evt)->list๋ฅผ ์ถ๊ฐํจ // // tick_do_timer_cpu: 0 // tick_next_period.tv64: 0 // tick_period.tv64: 10000000 // // timer control register L0_TCON ๊ฐ์ ์ฝ์ด timer start, timer interrupt ์ค์ ์ // ๋์ํ์ง ์๋๋ก ๋ณ๊ฒฝํจ // L0_TCON ๊ฐ์ด 0 ์ผ๋ก ๊ฐ์ ํ์์ผ๋ฏ๋ก timer๋ ๋์ํ์ง ์์ ์ํ์ // // register L_ICNTB ์ 0x8001D4C0 writeํจ // local timer 0 ์ interrupt count buffer ๊ฐ์ 120000 (0x1D4C0) write ํ๊ณ // interrupt manual update๋ฅผ enable ์ํด // // register L_INT_ENB ์ 0x1 writeํจ // local timer 0 ์ ICNTEIE ๊ฐ์ 0x1์ write ํ์ฌ L0_INTCNT ๊ฐ์ด 0 ์ด ๋์์ ๋ // interrupt counter expired interrupt ๊ฐ ๋ฐ์ํ๋๋ก ํจ // // register L_TCON ์ 0x7 writeํจ // local timer 0 ์ interrupt type์ interval mode๋ก ์ค์ ํ๊ณ interrupt, timer ๋ฅผ start ์ํด // // register L_TCNTB ์ 0x1 writeํจ // local timer 0 ์ tick count ๊ฐ์ 1๋ก write ํจ // // struct irqaction์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ํ ๋น ๋ฐ๊ณ ๋งด๋ฒ๊ฐ ์ธํ
// (kmem_cache#30-oX)->handler: exynos4_mct_tick_isr // (kmem_cache#30-oX)->thread_fn: NULL // (kmem_cache#30-oX)->flags: 0x14A00 // (kmem_cache#30-oX)->name: "mct_tick0" // (kmem_cache#30-oX)->dev_id: [pcp0] &percpu_mct_tick // (kmem_cache#30-oX)->irq: 152 // (kmem_cache#30-oX)->dir: NULL // // irq_desc 152์ ๋งด๋ฒ๊ฐ์ ์ด๊ธฐํ // &(&(kmem_cache#28-oX (irq 152))->wait_for_threads)->lock์ ์ฌ์ฉํ spinlock ์ด๊ธฐํ // &(&(kmem_cache#28-oX (irq 152))->wait_for_threads)->task_list๋ฅผ ์ฌ์ฉํ list ์ด๊ธฐํ // (kmem_cache#28-oX (irq 152))->istate: 0 // (kmem_cache#28-oX (irq 152))->depth: 1 // (kmem_cache#28-oX (irq 152))->status_use_accessors: 0x3400 // (kmem_cache#28-oX (irq 152))->irq_count: 0 // (kmem_cache#28-oX (irq 152))->irqs_unhandled: 0 // (&(kmem_cache#28-oX (irq 152))->irq_data)->state_use_accessors: 0x11400
exynos_mct.c::exynos4_timer_resources()
called: start_kernel()->time_init()->clocksource_of_init()->init_func(np)
// np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, MCT_INT_SPI: 0
->init_func(np)->mct_init_spi()->mct_init_dt()
exynos4_timer_resources()
exynos4_clocksource_init()
// ARM10C 20150307 // np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, MCT_INT_SPI: 0 static void __init mct_init_dt(struct device_node *np, unsigned int int_type) { u32 nr_irqs, i; // int_type: 0 mct_int_type = int_type; // mct_int_type: 0 /* This driver uses only one global timer interrupt */ // np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, MCT_G0_IRQ: 0 // irq_of_parse_and_map(devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, 0): 347 mct_irqs[MCT_G0_IRQ] = irq_of_parse_and_map(np, MCT_G0_IRQ); // mct_irqs[0]: 347 #ifdef CONFIG_OF // CONFIG_OF=y // np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์ // of_irq_count(devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์): 8 nr_irqs = of_irq_count(np); // nr_irqs: 8 // of_irq_count(mct node)์์ ํ์ผ: // devtree์ ๋ฑ๋ก๋ mct node์ irq ์ ๊ฐฏ์๋ฅผ ๊ตฌํจ #else nr_irqs = 0; #endif // nr_irqs: 8, MCT_L0_IRQ: 4 for (i = MCT_L0_IRQ; i < nr_irqs; i++) // i: 4, np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์ // irq_of_parse_and_map(devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, 4): 152 mct_irqs[i] = irq_of_parse_and_map(np, i); // mct_irqs[4]: 152 // i: 5...7 loop ์ํ // ์ loop์ ์ํ ๊ฒฐ๊ณผ // mct_irqs[4]: 152 // mct_irqs[5]: 153 // mct_irqs[6]: 154 // mct_irqs[7]: 155 // np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์ // of_iomap(devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, 0): 0xf0006000 exynos4_timer_resources(np, of_iomap(np, 0)); exynos4_clocksource_init();
called: start_kernel()->time_init()->clocksource_of_init()->init_func(np)
// np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, MCT_INT_SPI: 0
->init_func(np)->mct_init_spi()->mct_init_dt()
exynos4_timer_resources()
exynos4_clocksource_init()
exynos_mct.c::exynos4_clocksource_init()
called: start_kernel()->time_init()->clocksource_of_init()->init_func(np)
// np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, MCT_INT_SPI: 0
->init_func(np)->mct_init_spi()->mct_init_dt()
exynos4_timer_resources()
exynos4_clocksource_init()
// ARM10C 20150516 static void __init exynos4_clocksource_init(void) { exynos4_mct_frc_start(0, 0);
call: start_kernel()->time_init()->clocksource_of_init()->init_func(np)
// np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, MCT_INT_SPI: 0
->init_func(np)->mct_init_spi()->mct_init_dt()
exynos4_timer_resources()
exynos4_clocksource_init()
exyos_mct.c::exynos4_mct_frc_start()
called: start_kernel()->time_init()->clocksource_of_init()->init_func(np)
// np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, MCT_INT_SPI: 0
->init_func(np)->mct_init_spi()->mct_init_dt()
exynos4_timer_resources()
exynos4_clocksource_init()
/* Clocksource handling */ // ARM10C 20150516 // 0, 0 static void exynos4_mct_frc_start(u32 hi, u32 lo) { u32 reg; // lo: 0, EXYNOS4_MCT_G_CNT_L: 0x100 exynos4_mct_write(lo, EXYNOS4_MCT_G_CNT_L); // exynos4_mct_write ์์ ํ์ผ: // register G_CNT_L ์ 0x0 writeํจ // FRC count buffer ์ tick count ๊ฐ์ 0๋ก write ํจ // // register G_CNT_WSTAT ์ 0x1 writeํจ // G_CNT_L write status ์ ๊ฐ์ 1๋ก write ํจ // hi: 0, EXYNOS4_MCT_G_CNT_U: 0x104 exynos4_mct_write(hi, EXYNOS4_MCT_G_CNT_U); // exynos4_mct_write ์์ ํ์ผ: // register G_CNT_U ์ 0x0 writeํจ // FRC count buffer ์ tick count ๊ฐ์ 0๋ก write ํจ // // register G_CNT_WSTAT ์ 0x1 writeํจ // G_CNT_U write status ์ ๊ฐ์ 1๋ก write ํจ reg = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
call: start_kernel()->time_init()->clocksource_of_init()->init_func(np)
// np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, MCT_INT_SPI: 0
->init_func(np)->mct_init_spi()->mct_init_dt()
exynos4_timer_resources()
exynos4_clocksource_init()
call: start_kernel()->time_init()->clocksource_of_init()->init_func(np)
// np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, MCT_INT_SPI: 0
->init_func(np)->mct_init_spi()->mct_init_dt()
exynos4_timer_resources()
exynos4_clocksource_init()
// ARM10C 20150509 static inline u32 __raw_readl(const volatile void __iomem *addr) { u32 val; // +, Q, o : inline asm์ ๋ฌธ๋ฒ // FIXME: (*(volatile u32 __force *)addr) ์ ๋ฌธ๋ฒ? addr์ *ํด์ ์ฐ๋ ์ด์ ? // addr: 0xf0000004 asm volatile("ldr %1, %0" : "+Qo" (*(volatile u32 __force *)addr), "=r" (val)); // val: 0x0000FC24 return val; // return 0x0000FC24 }
return : start_kernel()->time_init()->clocksource_of_init()->init_func(np)
// np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, MCT_INT_SPI: 0
->init_func(np)->mct_init_spi()->mct_init_dt()
exynos4_timer_resources()
exynos4_clocksource_init()
exyos_mct.c::exynos4_mct_frc_start()
called: start_kernel()->time_init()->clocksource_of_init()->init_func(np)
// np: devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ mct node์ ์ฃผ์, MCT_INT_SPI: 0
->init_func(np)->mct_init_spi()->mct_init_dt()
exynos4_timer_resources()
exynos4_clocksource_init()
/* Clocksource handling */ // ARM10C 20150516 // 0, 0 static void exynos4_mct_frc_start(u32 hi, u32 lo) { u32 reg; // lo: 0, EXYNOS4_MCT_G_CNT_L: 0x100 exynos4_mct_write(lo, EXYNOS4_MCT_G_CNT_L); // exynos4_mct_write ์์ ํ์ผ: // register G_CNT_L ์ 0x0 writeํจ // FRC count buffer ์ tick count ๊ฐ์ 0๋ก write ํจ // // register G_CNT_WSTAT ์ 0x1 writeํจ // G_CNT_L write status ์ ๊ฐ์ 1๋ก write ํจ // hi: 0, EXYNOS4_MCT_G_CNT_U: 0x104 exynos4_mct_write(hi, EXYNOS4_MCT_G_CNT_U); // exynos4_mct_write ์์ ํ์ผ: // register G_CNT_U ์ 0x0 writeํจ // FRC count buffer ์ tick count ๊ฐ์ 0๋ก write ํจ // // register G_CNT_WSTAT ์ 0x1 writeํจ // G_CNT_U write status ์ ๊ฐ์ 1๋ก write ํจ reg = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON); reg |= MCT_G_TCON_START; exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON); }
exynos_mct.c::exynos4_mct_write()
// hi: 0, EXYNOS4_MCT_G_CNT_U: 0x104 static void exynos4_mct_write(unsigned int value, unsigned long offset) { unsigned long stat_addr; u32 mask; u32 i; // E.R.M: 21.4.1.23 L0_ICNTB // L_ICNTB: Specifies the interrupt count buffer register // 31 bit - interrupt manual update // 30~0 bit - interrupt count buffer // E.R.M: 21.4.1.29 L0_INT_ENB // L_INT_ENB: Specifies the interrupt enable for L_IRQ0 // 1 bit - FRCEIE: free running counter expired (L0_FRCCNT = 0) interrupt enable // 0 bit - ICNTEIE: interrupt counter expired (L0_INTCNT = 0) interrupt enable // E.R.M: 21.4.1.27 L0_TCON // L_TCON: Specifies the timer control register // 3 bit - frc start/stop // 2 bit - interrupt type // 1 bit - interrupt start/stop // 0 bit - timer start/stop // E.R.M: 21.4.1.21 L0_TCNTB // L_TCNTB: Specifies the tick integer count buffer register // 31~0 bit - tick count buffer // E.R.M: 21.4.1.2 G_CNT_L // G_CNT_L: Specifies the lower 32 bit value of FRC buffer register // 31~0 bit - FRC count buffer // E.R.M: 21.4.1.2 G_CNT_U // G_CNT_U: Specifies the upper 32 bit value of FRC buffer register // 31~0 bit - FRC count buffer // value: 0x8001D4C0, reg_base: 0xf0006000, offset: 0x308 // value: 0x1, reg_base: 0xf0006000, offset: 0x334 // value: 0x7, reg_base: 0xf0006000, offset: 0x320 // value: 0x1, reg_base: 0xf0006000, offset: 0x300 // value: 0x0, reg_base: 0xf0006000, offset: 0x100 // value: 0x0, reg_base: 0xf0006000, offset: 0x104 __raw_writel(value, reg_base + offset); // __raw_writel์์ ํ์ผ: // register L_ICNTB ์ 0x8001D4C0 writeํจ // local timer 0 ์ interrupt count buffer ๊ฐ์ 120000 (0x1D4C0)์ write ํ๊ณ // interrupt manual update๋ฅผ enable ์ํด // __raw_writel์์ ํ์ผ: // register L_INT_ENB ์ 0x1 writeํจ // local timer 0 ์ ICNTEIE ๊ฐ์ 0x1์ write ํ์ฌ L0_INTCNT ๊ฐ์ด 0 ์ด ๋์์ ๋ // interrupt counter expired interrupt ๊ฐ ๋ฐ์ํ๋๋ก ํจ // __raw_writel์์ ํ์ผ: // register L_TCON ์ 0x7 writeํจ // local timer 0 ์ interrupt type์ interval mode๋ก ์ค์ ํ๊ณ interrupt, timer ๋ฅผ start ์ํด // __raw_writel์์ ํ์ผ: // register L_TCNTB ์ 0x1 writeํจ // local timer 0 ์ tick count ๊ฐ์ 1๋ก write ํจ // __raw_writel์์ ํ์ผ: // register G_CNT_L ์ 0x0 writeํจ // FRC count buffer ์ tick count ๊ฐ์ 0๋ก write ํจ // __raw_writel์์ ํ์ผ: // register G_CNT_U ์ 0x0 writeํจ // FRC count buffer ์ tick count ๊ฐ์ 0๋ก write ํจ // offset: 0x308, EXYNOS4_MCT_L_BASE(0): 0x300 // offset: 0x334, EXYNOS4_MCT_L_BASE(0): 0x300 // offset: 0x320, EXYNOS4_MCT_L_BASE(0): 0x300 // offset: 0x300, EXYNOS4_MCT_L_BASE(0): 0x300 // offset: 0x100, EXYNOS4_MCT_L_BASE(0): 0x300 // offset: 0x104, EXYNOS4_MCT_L_BASE(0): 0x300 if (likely(offset >= EXYNOS4_MCT_L_BASE(0))) { // offset: 0x308, EXYNOS4_MCT_L_MASK: 0xffffff00, MCT_L_WSTAT_OFFSET: 0x40 // offset: 0x334, EXYNOS4_MCT_L_MASK: 0xffffff00, MCT_L_WSTAT_OFFSET: 0x40 // offset: 0x320, EXYNOS4_MCT_L_MASK: 0xffffff00, MCT_L_WSTAT_OFFSET: 0x40 // offset: 0x300, EXYNOS4_MCT_L_MASK: 0xffffff00, MCT_L_WSTAT_OFFSET: 0x40 stat_addr = (offset & ~EXYNOS4_MCT_L_MASK) + MCT_L_WSTAT_OFFSET; // stat_addr: 0x48 // stat_addr: 0x74 // stat_addr: 0x60 // stat_addr: 0x40 // offset: 0x308, EXYNOS4_MCT_L_MASK: 0xffffff00 // offset: 0x334, EXYNOS4_MCT_L_MASK: 0xffffff00 // offset: 0x320, EXYNOS4_MCT_L_MASK: 0xffffff00 // offset: 0x300, EXYNOS4_MCT_L_MASK: 0xffffff00 switch (offset & EXYNOS4_MCT_L_MASK) { case MCT_L_TCON_OFFSET: // MCT_L_TCON_OFFSET: 0x20 mask = 1 << 3; /* L_TCON write status */ break; case MCT_L_ICNTB_OFFSET: // MCT_L_ICNTB_OFFSET: 0x08 mask = 1 << 1; /* L_ICNTB write status */ break; case MCT_L_TCNTB_OFFSET: // MCT_L_TCNTB_OFFSET: 0x00 mask = 1 << 0; /* L_TCNTB write status */ break; default: return; // return ์ํ // return ์ํ // return ์ํ // return ์ํ } } else { // offset: 0x100 // offset: 0x104 switch (offset) { case EXYNOS4_MCT_G_TCON: // EXYNOS4_MCT_G_TCON: 0x240 stat_addr = EXYNOS4_MCT_G_WSTAT; mask = 1 << 16; /* G_TCON write status */ break; case EXYNOS4_MCT_G_COMP0_L: // EXYNOS4_MCT_G_COMP0_L: 0x200 stat_addr = EXYNOS4_MCT_G_WSTAT; mask = 1 << 0; /* G_COMP0_L write status */ break; case EXYNOS4_MCT_G_COMP0_U: // EXYNOS4_MCT_G_COMP0_U: 0x204 stat_addr = EXYNOS4_MCT_G_WSTAT; mask = 1 << 1; /* G_COMP0_U write status */ break; case EXYNOS4_MCT_G_COMP0_ADD_INCR: // EXYNOS4_MCT_G_COMP0_ADD_INCR: 0x208 stat_addr = EXYNOS4_MCT_G_WSTAT; mask = 1 << 2; /* G_COMP0_ADD_INCR w status */ break; case EXYNOS4_MCT_G_CNT_L: // EXYNOS4_MCT_G_CNT_L: 0x100 // EXYNOS4_MCT_G_CNT_WSTAT: 0x110 stat_addr = EXYNOS4_MCT_G_CNT_WSTAT; // stat_addr: 0x110 mask = 1 << 0; /* G_CNT_L write status */ // mask: 0x1 break; // break ์ํ case EXYNOS4_MCT_G_CNT_U: // EXYNOS4_MCT_G_CNT_U: 0x104 // EXYNOS4_MCT_G_CNT_WSTAT: 0x110 stat_addr = EXYNOS4_MCT_G_CNT_WSTAT; // stat_addr: 0x110 // mask = 1 << 1; /* G_CNT_U write status */ // mask: 0x2 break; // break ์ํ default: return; } } /* Wait maximum 1 ms until written values are applied */ // loops_per_jiffy: 4096, HZ: 100 // loops_per_jiffy: 4096, HZ: 100 for (i = 0; i < loops_per_jiffy / 1000 * HZ; i++) // E.R.M: 21.4.1.4 G_CNT_WSTAT // G_CNT_WSTAT: Specifies G_CNT_L and G_CNT_U SFR write status register // 0 bit - G_CNT_L write status // E.R.M: 21.4.1.4 G_CNT_WSTAT // G_CNT_WSTAT: Specifies G_CNT_L and G_CNT_U SFR write status register // 1 bit - G_CNT_U write status // reg_base: 0xf0006000, stat_addr: 0x110, mask: 0x1, __raw_readl(0xf0006110): 0x1 // reg_base: 0xf0006000, stat_addr: 0x110, mask: 0x2, __raw_readl(0xf0006110): 0x1 if (__raw_readl(reg_base + stat_addr) & mask) { // mask: 0x1, reg_base: 0xf0006000, stat_addr: 0x110 // mask: 0x2, reg_base: 0xf0006000, stat_addr: 0x110 __raw_writel(mask, reg_base + stat_addr); // __raw_writel์์ ํ์ผ: // register G_CNT_WSTAT ์ 0x1 writeํจ // G_CNT_L write status ์ ๊ฐ์ 1๋ก write ํจ // __raw_writel์์ ํ์ผ: // register G_CNT_WSTAT ์ 0x2 writeํจ // G_CNT_L write status ์ ๊ฐ์ 2๋ก write ํจ return; // return ์ํ // return ์ํ } panic("MCT hangs after writing %d (offset:0x%lx)\n", value, offset); }
exynos_mct.c::exynos4_clocksource_init()
// ARM10C 20150516 static void __init exynos4_clocksource_init(void) { exynos4_mct_frc_start(0, 0); if (clocksource_register_hz(&mct_frc, clk_rate)) panic("%s: can't register clocksource\n", mct_frc.name); }
clocksource.h::clocksource_registster_hz()
static inline int clocksource_register_hz(struct clocksource *cs, u32 hz) { return __clocksource_register_scale(cs, 1, hz); }
clocksource.c::__clocksource_register_scale()
int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq) { /* Initialize mult/shift and max_idle_ns */ __clocksource_updatefreq_scale(cs, scale, freq); /* Add clocksource to the clcoksource list */ mutex_lock(&clocksource_mutex); clocksource_enqueue(cs); clocksource_enqueue_watchdog(cs); clocksource_select(); mutex_unlock(&clocksource_mutex); return 0; } EXPORT_SYMBOL_GPL(__clocksource_register_scale);
main.c::start_kernel()->time_init()
called: start_kernel()->time_init()
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();
time.c::time_init()->of_clk_init(NULL)
called: start_kernel()->time_init()->of_clk_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 clocksource_of_init(); } }
// of_clk_init์์ ํ์ผ: // // devtree์์ allnext๋ก ์ํ ํ๋ฉด์ ์ฐพ์ clock node์ ์ฃผ์์์ match: __clk_of_table_exynos5420_clk ์ฐพ์ // exynos5420_clk_init ํจ์๋ฅผ ์ํ // // exynos5420_clk_init์์ ํ์ผ: // // 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 ์์ ํ์ผ: // 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 ์์ ํ์ผ: // // 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์์ ํ์ผ: // 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์์ ํ์ผ: // 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์์ ํ์ผ: // 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 ์์ ํ์ผ: // exynos5420_mux_clks์ ๋ฑ๋ก ๋์ด ์๋ clock 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์์ ํ์ผ: // // 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 ์์ ํ์ผ: // // exynos5420_gate_clks์ gate ๋ค ์ค์ array index 36๋ฒ์ // GATE(sclk_fimd1, "sclk_fimd1", "dout_fimd1", GATE_TOP_SCLK_PERIC, 0, CLK_SET_RATE_PARENT, 0) ์ ๊ฐ์ง๊ณ ๋ถ์ ์งํ // // 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: 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_fimd0) // (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 // // clk_table[136]: (kmem_cache#23-o0)[136]: kmem_cache#29-oX (sclk_fimd1) // // exynos5420_gate_clks์ idx: 0...12...136 loop ์ํ
clocksource_of_init์์ ํ์ผ:
// mct_int_type: 0 // // devtree์ mct node์ interrupt์ property์ ๊ฐ์ dtb์ ๋ถ์ํ์ฌ oirq ๊ฐ์ ๊ฐ์ ธ์ด // // (&oirq)->np: combiner node์ ์ฃผ์ // (&oirq)->args_count: 2 // (&oirq)->args[0]: 23 // (&oirq)->args[1]: 3 // // oirq ๊ฐ์ ์ฌ์ฉํ์ฌ combiner domain์์ virq ๊ฐ์ ์ฐพ์ // virq: 347 // // mct_irqs[4]: 152 // mct_irqs[5]: 153 // mct_irqs[6]: 154 // mct_irqs[7]: 155 // // device tree ์๋ mct node์์ node์ resource ๊ฐ์ ๊ฐ์ ธ์ด // (&res)->start: 0x101C0000 // (&res)->end: 0x101C07ff // (&res)->flags: IORESOURCE_MEM: 0x00000200 // (&res)->name: "/mct@101C0000" /* // alloc area (MCT) ๋ฅผ ๋ง๋ค๊ณ rb tree์ alloc area ๋ฅผ ์ถ๊ฐ // ๊ฐ์์ฃผ์ va_start ๊ธฐ์ค์ผ๋ก MCT ๋ฅผ RB Tree ์ถ๊ฐํ ๊ฒฐ๊ณผ // // CHID-b // (0xF8000000) // / \ // CLK-b PMU-b // (0xF0040000) (0xF8180000) // / \ / \ // GIC#1-r TMR-r CMU-b SRAM-b // (0xF0002000) (0xF6300000) (0xF8100000) (0xF8400000) // / \ / \ \ // GIC#0-b COMB-b SYSC-b WDT-b ROMC-r // (0xF0000000) (0xF0004000) (0xF6100000) (0xF6400000) (0xF84C0000) // \ // MCT-r // (0xF0006000) // // vmap_area_list์ GIC#0 - GIC#1 - COMB - MCT - 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: 0xf0006000 // (kmem_cache#30-oX (vm_struct))->size: 0x2000 // (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 ์๋ mct node์์ node์ resource ๊ฐ์ pgtable์ ๋งคํํจ // 0xc0004780์ด ๊ฐ๋ฆฌํค๋ pte์ ์์์ฃผ์์ 0x101C0653 ๊ฐ์ ๊ฐฑ์ // (linux pgtable๊ณผ hardware pgtable์ ๊ฐ ๊ฐ์ด ๊ฐฑ์ ) // // pgd pte // | | // +--------------+ // | | +--------------+ +0 // | | | 0xXXXXXXXX | ---> 0x101C0653 ์ ๋งค์นญ๋๋ linux pgtable ๊ฐ // +- - - - - - - + | Linux pt 0 | // | | +--------------+ +1024 // | | | | // +--------------+ +0 | Linux pt 1 | // | *(c0004780) |-----> +--------------+ +2048 // | | | 0x101C0653 | ---> 2076 // +- - - - - - - + +4 | h/w pt 0 | // | *(c0004784) |-----> +--------------+ +3072 // | | + + // +--------------+ +8 | h/w pt 1 | // | | +--------------+ +4096 // // cache์ ๊ฐ์ ์ ๋ถ ๋ฉ๋ชจ๋ฆฌ์ ๋ฐ์ // // mct node์ property "clock-names" ์ ๊ฐ์ ์ฐพ์์ "fin_pll" ์ด ์๋ ์์น๋ฅผ ์ฐพ๊ณ // ๋ช๋ฒ์งธ ๊ฐ์ธ์ง index๋ฅผ ๊ตฌํจ // // mct node ์์ "clocks" property์ ์ด์ฉํ์ฌ devtree์ ๊ฐ์ ํ์ฑํ์ฌ clkspec์ ๊ฐ์ ๊ฐ์ ธ์ด // (&clkspec)->np: clock node์ ์ฃผ์ // (&clkspec)->args_count: 1 // (&clkspec)->args[0]: 1 // // list of_clk_providers ์ ๋ฑ๋ก๋ ์ ๋ณด๋ค ์ค์ clkspec ์ ๋งค์น๋๋ ์ ๋ณด๋ฅผ ์ฐพ์ // ์ด์ ์ ๋ง๋ค์ด ๋์ clk_data์ clk_table ์ ๋ณด๋ฅผ ์ด์ฉํ์ฌ clkspec์ ์๋ arg ๊ฐ์ ์ด์ฉํ์ฌ clk์ ์ฐพ์ // tick_clk: kmem_cache#29-oX (fin_pll) // // mct node์ property "clock-names" ์ ๊ฐ์ ์ฐพ์์ "mct" ์ด ์๋ ์์น๋ฅผ ์ฐพ๊ณ // ๋ช๋ฒ์งธ ๊ฐ์ธ์ง index๋ฅผ ๊ตฌํจ // // mct node ์์ "clocks" property์ ์ด์ฉํ์ฌ devtree์ ๊ฐ์ ํ์ฑํ์ฌ clkspec์ ๊ฐ์ ๊ฐ์ ธ์ด // (&clkspec)->np: clock node์ ์ฃผ์ // (&clkspec)->args_count: 1 // (&clkspec)->args[0]: 315 // // list of_clk_providers ์ ๋ฑ๋ก๋ ์ ๋ณด๋ค ์ค์ clkspec ์ ๋งค์น๋๋ ์ ๋ณด๋ฅผ ์ฐพ์ // ์ด์ ์ ๋ง๋ค์ด ๋์ clk_data์ clk_table ์ ๋ณด๋ฅผ ์ด์ฉํ์ฌ clkspec์ ์๋ arg ๊ฐ์ ์ด์ฉํ์ฌ clk์ ์ฐพ์ // mct_clk: kmem_cache#29-oX (mct) // // clk_prepare_enable์์ ํ์ผ: // mct clock์ ์์ clock ๋ค์ ops->prepare ํจ์๋ค์ ์ํ. // mct clock์ ์์ clock ๋ค์ ops->enable ํจ์๋ค์ ์ํ. // sck_cpll -- Group1_p -- mout_aclk66 -- dout_aclk66 -- mct // sck_ppll -| // sck_mpll -| // // sck_cpll, mout_aclk66, dout_aclk66 ์ ์ฃผ์์ ๋ง๋ค์ง ์์๊ธฐ ๋๋ฌธ์ // ๋ถ์๋ด์ฉ์ skip ํ๋๋กํจ // // Interrupt pending register์ธ GICD_ITARGETSR38 ๊ฐ์ ์ฝ๊ณ // ๊ทธ ๊ฐ๊ณผ mask ๊ฐ์ธ cpu_bit_bitmap[1][0] ์ or ์ฐ์ฐํ ๊ฐ์ GICD_ITARGETSR38์ // ๋ค์ writeํจ // // GICD_ITARGETSR38 ๊ฐ์ ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ 0x00000000 ๋ก // ์ฝํ๋ ๊ฒ์ผ๋ก ๊ฐ์ ํ๊ณ GICD_ITARGETSR38์ 0x00000001๋ฅผ write ํจ // CPU interface 0์ interrupt๊ฐ ๋ฐ์์ ๋ํ๋ // // (&(kmem_cache#28-oX (irq 152))->irq_data)->affinity->bits[0]: 1 // (&(kmem_cache#28-oX (irq 152))->irq_data)->state_use_accessors: 0x11000 // // register_cpu_notifier ์์ ํ์ผ: // (&cpu_chain)->head: &exynos4_mct_cpu_nb ํฌ์ธํฐ ๋์
// (&exynos4_mct_cpu_nb)->next์ (&hrtimers_nb)->next๋ก ๋์
// // [pcp0] (&percpu_mct_tick)->base: 0x300 // [pcp0] (&percpu_mct_tick)->name: "mct_tick0" // [pcp0] (&(&percpu_mct_tick)->evt)->name: "mct_tick0" // [pcp0] (&(&percpu_mct_tick)->evt)->cpumask: &cpu_bit_bitmap[1][0] // [pcp0] (&(&percpu_mct_tick)->evt)->set_next_event: exynos4_tick_set_next_event // [pcp0] (&(&percpu_mct_tick)->evt)->set_mode: exynos4_tick_set_mode // [pcp0] (&(&percpu_mct_tick)->evt)->features: 0x3 // [pcp0] (&(&percpu_mct_tick)->evt)->rating: 450 // [pcp0] (&(&percpu_mct_tick)->evt)->min_delta_ticks: 0xf // [pcp0] (&(&percpu_mct_tick)->evt)->max_delta_ticks: 0x7fffffff // [pcp0] (&(&percpu_mct_tick)->evt)->mult: 0x3126E98 // [pcp0] (&(&percpu_mct_tick)->evt)->shift: 32 // [pcp0] (&(&percpu_mct_tick)->evt)->min_delta_ns: 0x4E2 // [pcp0] (&(&percpu_mct_tick)->evt)->max_delta_ns: 0x29AAAAA444 // [pcp0] (&(&percpu_mct_tick)->evt)->next_event.tv64: 0x7FFFFFFFFFFFFFFF // [pcp0] (&(&percpu_mct_tick)->evt)->event_handler: tick_handle_periodic // [pcp0] (&(&percpu_mct_tick)->evt)->mode: 2 // [pcp0] (&(&percpu_mct_tick)->evt)->irq: 152 // // [pcp0] (&tick_cpu_device)->mode: 0 // [pcp0] (&tick_cpu_device)->evtdev: [pcp0] &(&percpu_mct_tick)->evt // // [pcp0] (&tick_cpu_sched)->check_clocks: 1 // // list clockevent_devices์ [pcp0] (&(&percpu_mct_tick)->evt)->list๋ฅผ ์ถ๊ฐํจ // // tick_do_timer_cpu: 0 // tick_next_period.tv64: 0 // tick_period.tv64: 10000000 // // timer control register L0_TCON ๊ฐ์ ์ฝ์ด timer start, timer interrupt ์ค์ ์ // ๋์ํ์ง ์๋๋ก ๋ณ๊ฒฝํจ // L0_TCON ๊ฐ์ด 0 ์ผ๋ก ๊ฐ์ ํ์์ผ๋ฏ๋ก timer๋ ๋์ํ์ง ์์ ์ํ์ // // register L_ICNTB ์ 0x8001D4C0 writeํจ // local timer 0 ์ interrupt count buffer ๊ฐ์ 120000 (0x1D4C0) write ํ๊ณ // interrupt manual update๋ฅผ enable ์ํด // // register L_INT_ENB ์ 0x1 writeํจ // local timer 0 ์ ICNTEIE ๊ฐ์ 0x1์ write ํ์ฌ L0_INTCNT ๊ฐ์ด 0 ์ด ๋์์ ๋ // interrupt counter expired interrupt ๊ฐ ๋ฐ์ํ๋๋ก ํจ // // register L_TCON ์ 0x7 writeํจ // local timer 0 ์ interrupt type์ interval mode๋ก ์ค์ ํ๊ณ interrupt, timer ๋ฅผ start ์ํด // // register L_TCNTB ์ 0x1 writeํจ // local timer 0 ์ tick count ๊ฐ์ 1๋ก write ํจ // // struct irqaction์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ํ ๋น ๋ฐ๊ณ ๋งด๋ฒ๊ฐ ์ธํ
// (kmem_cache#30-oX)->handler: exynos4_mct_tick_isr // (kmem_cache#30-oX)->thread_fn: NULL // (kmem_cache#30-oX)->flags: 0x14A00 // (kmem_cache#30-oX)->name: "mct_tick0" // (kmem_cache#30-oX)->dev_id: [pcp0] &percpu_mct_tick // (kmem_cache#30-oX)->irq: 152 // (kmem_cache#30-oX)->dir: NULL // // irq_desc 152์ ๋งด๋ฒ๊ฐ์ ์ด๊ธฐํ // &(&(kmem_cache#28-oX (irq 152))->wait_for_threads)->lock์ ์ฌ์ฉํ spinlock ์ด๊ธฐํ // &(&(kmem_cache#28-oX (irq 152))->wait_for_threads)->task_list๋ฅผ ์ฌ์ฉํ list ์ด๊ธฐํ // (kmem_cache#28-oX (irq 152))->istate: 0 // (kmem_cache#28-oX (irq 152))->depth: 1 // (kmem_cache#28-oX (irq 152))->action: kmem_cache#30-oX (irqaction) // (kmem_cache#28-oX (irq 152))->status_use_accessors: 0x3400 // (kmem_cache#28-oX (irq 152))->irq_count: 0 // (kmem_cache#28-oX (irq 152))->irqs_unhandled: 0 // (&(kmem_cache#28-oX (irq 152))->irq_data)->state_use_accessors: 0x11400 // // register G_CNT_L ์ 0x0 writeํจ // FRC count buffer ์ tick count ๊ฐ์ 0๋ก write ํจ // // register G_CNT_WSTAT ์ 0x1 writeํจ // G_CNT_L write status ์ ๊ฐ์ 1๋ก write ํจ // // register G_CNT_U ์ 0x0 writeํจ // FRC count buffer ์ tick count ๊ฐ์ 0๋ก write ํจ // // register G_CNT_WSTAT ์ 0x1 writeํจ // G_CNT_U write status ์ ๊ฐ์ 1๋ก write ํจ // // register G_TCON ์ 0x100 writeํจ // global timer enable ์ ๊ฐ์ 1๋ก write ํจ // // (&mct_frc)->mult: 0xA6AAAAAA // (&mct_frc)->shift: 26 // (&mct_frc)->maxadj: 0x12555555 // (&mct_frc)->max_idle_ns: 0x103955554C // (&mct_frc)->flags: 0x21 // // list clocksource_list์ next์ &(&mct_frc)->list๋ฅผ ์ถ๊ฐํจ // // mct_comp_device.cpumask: &cpu_bit_bitmap[1][0 // // (&mct_comp_device)->min_delta_ticks: 0xf // (&mct_comp_device)->max_delta_ticks: 0xffffffff // (&mct_comp_device)->mult: 0x3126E98 // (&mct_comp_device)->shift: 31 // (&mct_comp_device)->min_delta_ns: 0x3E8 // (&mct_comp_device)->max_delta_ns: 0x29AAAAA46E // (&mct_comp_device)->mode: 1 // (&mct_comp_device)->next_event.tv64: 0x7FFFFFFFFFFFFFFF // // list clockevent_devices์ (&mct_comp_device)->list๋ฅผ ์ถ๊ฐํจ // // register G_TCON ์ 0x100 writeํจ // global timer enable ์ ๊ฐ์ 1๋ก write ํจ // // register G_INT_ENB ์ 0x0 writeํจ // global timer interrupt enable ์ ๊ฐ์ 0๋ก write ํจ // // comparator 0์ auto increment0, comp0 enable,comp0 interrupt enable ๊ฐ์ // 0์ผ๋ก clear ํ์ฌ comparator 0๋ฅผ ๋์ํ์ง ์๋๋ก ํจ // // tick_broadcast_device.evtdev: &mct_comp_device // [pcp0] &(&tick_cpu_sched)->check_clocks: 0xf // // &(&(kmem_cache#28-oX (irq 347))->wait_for_threads)->lock์ ์ฌ์ฉํ spinlock ์ด๊ธฐํ // &(&(kmem_cache#28-oX (irq 347))->wait_for_threads)->task_list๋ฅผ ์ฌ์ฉํ list ์ด๊ธฐํ // &(kmem_cache#28-oX (irq 347))->istate: 0 // (kmem_cache#28-oX (irq 347))->depth: 0 // (kmem_cache#28-oX (irq 347))->action: &mct_comp_event_irq // (kmem_cache#28-oX (irq 347))->irq_count: 0 // (kmem_cache#28-oX (irq 347))->irqs_unhandled: 0 // // (&(kmem_cache#28-oX (irq 347))->irq_data)->state_use_accessors: 0x10000 // (&(kmem_cache#28-oX (irq 347))->irq_data)->affinity->bits[0]: 1 // // register IESR5์ MCT_G0 bit ๋ฅผ 1 ๋ก write ํ์ฌ MCT_G0 ์ interrupt ๋ฅผ enable ์ํด // // GICD_ITARGETSR46 ๊ฐ์ ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ 0x00000000 ๋ก // ์ฝํ๋ ๊ฒ์ผ๋ก ๊ฐ์ ํ๊ณ GICD_ITARGETSR46์ 0x1000000๋ฅผ write ํจ // CPU interface 0์ interrupt๊ฐ ๋ฐ์์ ๋ํ๋ // // struct irqaction ๋ฉค๋ฒ ๊ฐ ์ธํ
// (&mct_comp_event_irq)->irq: 347 // (&mct_comp_event_irq)->dir: NULL
5de994b..02918e4 master -> origin/master Updating 5de994b..02918e4 Fast-forward drivers/clocksource/exynos_mct.c | 213 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/proc/internal.h | 1 + include/linux/cpumask.h | 2 ++ include/linux/interrupt.h | 23 +++++++++++++++ include/linux/irq.h | 6 ++++ include/linux/irqdesc.h | 1 + include/linux/spinlock.h | 1 + kernel/irq/internals.h | 6 +++- kernel/irq/irqdesc.c | 2 ++ kernel/irq/manage.c | 73 +++++++++++++++++++++++++++++++++++++++++++++-- kernel/irq/proc.c | 41 +++++++++++++++++++++++++++ 11 files changed, 365 insertions(+), 4 deletions(-)
02918e4..3d96381 master -> origin/master Updating 02918e4..3d96381 Fast-forward drivers/clocksource/exynos_mct.c | 113 ++++++++++++++++++++++++++++++++++++--- include/asm-generic/param.h | 1 + init/main.c | 2 + 3 files changed, 109 insertions(+), 7 deletions(-)
Updating 1e01d49..cf3996e Fast-forward README.md | 4 +++- arch/arm/include/asm/irqflags.h | 3 ++- drivers/clocksource/exynos_mct.c | 1 + include/linux/irqflags.h | 5 ++++- include/linux/list.h | 1 + include/linux/percpu-defs.h | 9 +++++++++ include/linux/tick.h | 3 +++ kernel/time/clocksource.c | 21 ++++++++++++++++++--- kernel/time/tick-common.c | 1 + kernel/time/tick-internal.h | 3 +++ kernel/time/tick-oneshot.c | 13 +++++++++++++ 11 files changed, 58 insertions(+), 6 deletions(-)