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