1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2007,2008 Nobobuhiro Iwamatsu <iwamatsu (at) nigauri.org> 4 * Copyright (C) 2008 Renesas Solutions Corp. 5 * 6 * (C) Copyright 2003 7 * Wolfgang Denk, DENX Software Engineering, wd (at) denx.de. 8 */ 9 10 #include <common.h> 11 #include <asm/io.h> 12 #include <asm/processor.h> 13 14 #define CMT_CMCSR_INIT 0x0001 /* PCLK/32 */ 15 #define CMT_CMCSR_CALIB 0x0000 16 #define CMT_MAX_COUNTER (0xFFFFFFFF) 17 #define CMT_TIMER_RESET (0xFFFF) 18 19 static vu_long cmt0_timer; 20 21 static void cmt_timer_start(unsigned int timer) 22 { 23 writew(readw(CMSTR) | 0x01, CMSTR); 24 } 25 26 static void cmt_timer_stop(unsigned int timer) 27 { 28 writew(readw(CMSTR) & ~0x01, CMSTR); 29 } 30 31 int timer_init(void) 32 { 33 cmt0_timer = 0; 34 /* Divide clock by 32 */ 35 readw(CMCSR_0); 36 writew(CMT_CMCSR_INIT, CMCSR_0); 37 38 /* User Device 0 only */ 39 cmt_timer_stop(0); 40 writew(CMT_TIMER_RESET, CMCOR_0); 41 cmt_timer_start(0); 42 43 return 0; 44 } 45 46 unsigned long long get_ticks(void) 47 { 48 return cmt0_timer; 49 } 50 51 static vu_long cmcnt = 0; 52 static unsigned long get_usec (void) 53 { 54 ulong data = readw(CMCNT_0); 55 56 if (data >= cmcnt) 57 cmcnt = data - cmcnt; 58 else 59 cmcnt = (CMT_TIMER_RESET - cmcnt) + data; 60 61 if ((cmt0_timer + cmcnt) > CMT_MAX_COUNTER) 62 cmt0_timer = ((cmt0_timer + cmcnt) - CMT_MAX_COUNTER); 63 else 64 cmt0_timer += cmcnt; 65 66 cmcnt = data; 67 return cmt0_timer; 68 } 69 70 /* return msec */ 71 ulong get_timer(ulong base) 72 { 73 return (get_usec() / 1000) - base; 74 } 75 76 void __udelay(unsigned long usec) 77 { 78 unsigned long end = get_usec() + usec; 79 80 while (get_usec() < end) 81 continue; 82 } 83 84 unsigned long get_tbclk(void) 85 { 86 return CONFIG_SH_CMT_CLK_FREQ; 87 } 88