/** CA9 global timer driver @file timer.c @ingroup @note Copyright Novatek Microelectronics Corp. 2019. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. */ #include #include #include #include #include #include #include DECLARE_GLOBAL_DATA_PTR; static struct globaltimer *global_timer = \ (struct globaltimer *)GLOBAL_TIMER_BASE_ADDR; #define CLK2MHZ(clk) (clk / 1000 / 1000) u32 get_timer_clk(void) { return (get_cpu_clk() / 1000) / 8; } static u64 get_cpu_global_timer(void) { u32 low, high; u64 timer; u32 old = readl(&global_timer->cnt_h); while (1) { low = readl(&global_timer->cnt_l); high = readl(&global_timer->cnt_h); if (old == high) break; else old = high; } timer = high; return (u64)((timer << 32) | low); } int timer_init(void) { u32 val = 0; val = readl(&global_timer->ctl); if (!(val & 0x01)) { writel(0x01, &global_timer->ctl); printf("ARM CA9 global timer init successfully\n"); } else { printf("ARM CA9 global timer had already been initiated\n"); } return 0; } void __udelay(unsigned long usec) { u64 wait_tick = 0; unsigned long long now_tick, start = get_cpu_global_timer(); wait_tick = get_timer_clk() * usec; do { now_tick = get_cpu_global_timer(); } while ((now_tick - start) < wait_tick); } ulong get_timer(ulong base) { u64 now = get_cpu_global_timer(), timer_freq = get_timer_clk(); ulong time_msec; do_div(now, timer_freq * 1000); time_msec = (ulong)now; return time_msec - base; } unsigned long long get_ticks(void) { return get_cpu_global_timer(); } ulong get_tbclk(void) { return (ulong)get_timer_clk(); }