123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384 |
- /**
- ******************************************************************************
- * @file timer.c
- * @author StarFive Technology
- * @version V1.0
- * @date 07/24/2020
- * @brief
- ******************************************************************************
- * @copy
- *
- * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
- * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
- * TIME. AS A RESULT, STARFIVE SHALL NOT BE HELD LIABLE FOR ANY
- * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
- * FROM THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
- * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
- *
- * COPYRIGHT 2020 Shanghai StarFive Technology Co., Ltd.
- */
- #include <comdef.h>
- #include <sys.h>
- #include <timer.h>
- #include <clkgen_ctrl_macro.h>
- #include <uart.h>
- #include <div64.h>
- #define TIMER_RATE_HZ (TIMER_CLK_HZ /1000)
- #if 0
- #define VIC_TIMER_NUM 7
- #define VIC_TIMER_NUM_MAX 7
- #define VIC_SYS_TIMER 0
- #define CONFIG_SYS_HZ 1000
- #define TIMER_RATE_HZ (CONFIG_SYS_HZ_CLOCK /1000)
- #define WDOG_UNKOCK 0x378f0765
- u32 interrupt_count = 0;
- /*
- * variables definition for local use
- */
- static const u32 timer_clk = CONFIG_SYS_HZ_CLOCK;
- static u64 lastdec;//Last decremneter snapshot
- static u64 timestamp;//Monotonic incrementing timer
- static u64 timer_load_val;
- struct timer_regs{
- u32 interrupt_status; //0x00
- struct time_reg{
- u32 control; //0x04+i*0x10
- u32 load_reg; //0x08+i*0x10
- u32 res0; //0x0c+i*0x10
- u32 enable_reg; //0x10+i*0x10
- u32 reload_reg; //0x14 + i * 0x10
- u32 timer_value; //0x18 + i * 0x10
- u32 res1; //0x1c
- u32 interrupt_clr; //0x20
- u32 interrupt_mask; //0x24
- u32 res3[5];
- u32 watchdog_lock; //0x3c+i*0x40 watchdog use ONLY
- u32 res4; //0x40+i*0x40
- }timer[VIC_TIMER_NUM_MAX];
- };
- struct timer_int_arg{
- u32 id;
- void (*callback)(void *);
- void *arg;
- u32 wdog_reset;
- };
- /*
- * local functions
- */
- struct timer_regs *timer_driver_to_base(struct timer_driver *driver)
- {
- return (struct timer_regs *)driver->base;
- }
- static struct timer_driver g_timer_driver;
- void timer_int_enable(u32 id)
- {
- struct timer_driver *driver = &g_timer_driver;
- volatile struct timer_regs *base;
- base = timer_driver_to_base(driver);
- base->timer[id].interrupt_mask = 0;
- }
- void timer_int_disable(u32 id)
- {
- struct timer_driver *driver = &g_timer_driver;
- volatile struct timer_regs *base;
- base = timer_driver_to_base(driver);
- base->timer[id].interrupt_mask = 1;
- }
- void timer_disable(u32 id)
- {
- struct timer_driver *driver = &g_timer_driver;
- volatile struct timer_regs *base;
- base = timer_driver_to_base(driver);
- base->timer[id].enable_reg = 0;
- }
- int timer_is_timeout(u32 id)
- {
- struct timer_driver *driver = &g_timer_driver;
- volatile struct timer_regs *base;
- base = timer_driver_to_base(driver);
- //printf("addr = 0x%x,base[id].raw_int_status = 0x%x\r\n", &(base[id].raw_int_status), base[id].raw_int_status);
-
- return (base->interrupt_status == 1) ? true : false;
- }
- void timer_set_mode(u32 id,u32 run_mode)
- {
- struct timer_driver *driver = &g_timer_driver;
- volatile struct timer_regs *base;
- base = timer_driver_to_base(driver);
- base->timer[id].control = run_mode;
- }
- void timer_set_val(u32 id,u32 val)
- {
- struct timer_driver *driver = &g_timer_driver;
- volatile struct timer_regs *base;
- base = timer_driver_to_base(driver);
- base->timer[id].load_reg = val;
- }
- void timer_set_reload_val(u32 id,u32 val)
- {
- struct timer_driver *driver = &g_timer_driver;
- volatile struct timer_regs *base;
- base = timer_driver_to_base(driver);
- base->timer[id].reload_reg = val;
- }
- static struct timer_int_arg int_arg[VIC_TIMER_NUM_MAX];
- int timer_set(u32 id,struct timer_init_s *init)
- {
- u32 irq = 0;
- timer_disable(id);
- timer_set_mode(id,init->run_mode);
- timer_set_val(id,init->count);
- timer_int_disable(id);
- timer_set_reload_val(id, init->count);
- timestamp=0;
- timer_load_val=init->count;
- lastdec=timer_load_val;
- //_ENABLE_CLOCK_clk_wdtimer_apb_;
- switch (id){
- case 0:
- _ENABLE_CLOCK_clk_timer0_coreclk_;
- break;
- case 1:
- _ENABLE_CLOCK_clk_timer1_coreclk_;
- break;
- case 2:
- _ENABLE_CLOCK_clk_timer2_coreclk_;
- break;
- case 3:
- _ENABLE_CLOCK_clk_timer3_coreclk_;
- break;
- case 4:
- _ENABLE_CLOCK_clk_timer4_coreclk_;
- break;
- case 5:
- _ENABLE_CLOCK_clk_timer5_coreclk_;
- break;
- case 6:
- _ENABLE_CLOCK_clk_timer6_coreclk_;
- break;
- }
-
- timer_int_disable(id);
- //timer_int_disable(id);
-
- return 0;
- }
- void timer_enable(u32 id)
- {
- struct timer_driver *driver = &g_timer_driver;
- volatile struct timer_regs *base;
- base = timer_driver_to_base(driver);
- base->timer[id].enable_reg = 1;
- }
- /*
- * public functions
- */
- int timer_clr_int_status(u32 id)
- {
- struct timer_driver *driver = &g_timer_driver;
- volatile struct timer_regs *base;
- int clr;
- //printf("clr timer id = %d\r\n", id);
- base = timer_driver_to_base(driver);
- base->timer[id].interrupt_clr = 1;
- return clr;
- }
- u32 timer_get_val(u32 id)
- {
- struct timer_driver *driver = &g_timer_driver;
- volatile struct timer_regs *base;
- base = timer_driver_to_base(driver);
- return base->timer[id].timer_value;
- }
- int timer_stop(u32 id)
- {
- int irq;
-
- timer_int_disable(id);
- timer_disable(id);
- timer_clr_int_status(id);
- return 0;
- }
- int timer_start(u32 id)
- {
- timer_enable(id);
- return 0;
- }
- int timer_exit(void)
- {
- return 0;
- }
- int timer_init(int id)
- {
- struct timer_driver *driver = &g_timer_driver;
- struct timer_init_s timer_init_param;
- int reg_value;
- /* timer clk use apb clk */
- /* reset */
- driver->base = (void *)TIMER_BASE_ADDR;
- driver->freq = CONFIG_SYS_HZ_CLOCK;
- // _ASSERT_RESET_rstn_apb_timer_;
- // _CLEAR_RESET_rstn_apb_timer_;
-
-
- if(id == SOC_SYS_TIMER)/* start timer0 as system delay timer */
- {
- timer_init_param.int_en = 0;//0:interrupt disable 1:interrupt enable
- timer_init_param.run_mode = 0;//0:continuous 1:single
- timer_init_param.count = 0xffffffff;
- timer_init_param.one_shot = 0;
- timer_init_param.callback = NULL;
- timer_init_param.arg = NULL;
- //_SET_SYSCON_REG_SCFG_misc_ctrl1_timclken1(1);
- timer_set(id, &timer_init_param);
- timer_start(id);
- }
- else
- {
- timer_set(id, &timer_init_param);
- timer_start(id);
- }
- return 0;
- }
- u32 get_ticks(u32 tick_base)
- {
- u32 id = SOC_SYS_TIMER;
- u32 now = timer_get_val(id);
- //printf("time value = 0x%x\r\n",now);
-
- if (lastdec >= now) {
- /* normal mode */
- timestamp += lastdec - now;
- } else {
- /* we have an overflow ... */
- timestamp += lastdec + timer_load_val - now;
- }
- lastdec = now;
- return (u32)(timestamp-tick_base);
- }
- #endif
- #include "platform.h"
- unsigned long long get_ticks(void)
- {
- return readq(CLINT_CTRL_MTIME);
- }
- u32 get_timer(unsigned int base)
- {
- return lldiv(get_ticks(), TIMER_RATE_HZ) - base;
- }
- #if 0
- u32 usec_to_tick(u32 usec)
- {
- u32 value = usec*(timer_clk/1000000);
- //printf("value = 0x%x\r\n", value);
-
- return usec*(timer_clk/1000000);
- }
- int udelay(u32 usec)
- {
- UINT64 tmp;
- UINT64 tmo;
- tmo = usec_to_tick(usec);
- tmp = get_ticks(0) + tmo; /* get current timestamp */
- while (get_ticks(0) < tmp)/* loop till event */
- /*NOP*/
- {
- }
- return 0;
- }
- #endif
- u64 usec_to_tick(u64 usec)
- {
- u64 value;
- value = usec*(TIMER_CLK_HZ/1000)/1000;
- return value;
- }
- /* delay x useconds */
- int udelay(unsigned int usec)
- {
- unsigned long tmp;
- tmp = readq((volatile void *)CLINT_CTRL_MTIME) + usec_to_tick(usec); /* get current timestamp */
-
- while (readq((volatile void *)CLINT_CTRL_MTIME) < tmp);
- }
- void mdelay(unsigned int ms)
- {
- udelay(1000*ms);
- }
- void sdelay(unsigned int s)
- {
- mdelay(1000*s);
- }
|