Home | History | Annotate | Download | only in stv0991
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Copyright (C) 2014, STMicroelectronics - All Rights Reserved
      4  * Author(s): Vikas Manocha, <vikas.manocha (at) st.com> for STMicroelectronics.
      5  */
      6 
      7 #include <common.h>
      8 #include <asm/io.h>
      9 #include <asm/arch-stv0991/hardware.h>
     10 #include <asm/arch-stv0991/stv0991_cgu.h>
     11 #include <asm/arch-stv0991/stv0991_gpt.h>
     12 
     13 static struct stv0991_cgu_regs *const stv0991_cgu_regs = \
     14 				(struct stv0991_cgu_regs *) (CGU_BASE_ADDR);
     15 
     16 #define READ_TIMER()	(readl(&gpt1_regs_ptr->cnt) & GPT_FREE_RUNNING)
     17 #define GPT_RESOLUTION	(CONFIG_STV0991_HZ_CLOCK / CONFIG_STV0991_HZ)
     18 
     19 DECLARE_GLOBAL_DATA_PTR;
     20 
     21 #define timestamp gd->arch.tbl
     22 #define lastdec gd->arch.lastinc
     23 
     24 int timer_init(void)
     25 {
     26 	/* Timer1 clock configuration */
     27 	writel(TIMER1_CLK_CFG, &stv0991_cgu_regs->tim_freq);
     28 	writel(readl(&stv0991_cgu_regs->cgu_enable_2) |
     29 			TIMER1_CLK_EN, &stv0991_cgu_regs->cgu_enable_2);
     30 
     31 	/* Stop the timer */
     32 	writel(readl(&gpt1_regs_ptr->cr1) & ~GPT_CR1_CEN, &gpt1_regs_ptr->cr1);
     33 	writel(GPT_PRESCALER_128, &gpt1_regs_ptr->psc);
     34 	/* Configure timer for auto-reload */
     35 	writel(readl(&gpt1_regs_ptr->cr1) | GPT_MODE_AUTO_RELOAD,
     36 			&gpt1_regs_ptr->cr1);
     37 
     38 	/* load value for free running */
     39 	writel(GPT_FREE_RUNNING, &gpt1_regs_ptr->arr);
     40 
     41 	/* start timer */
     42 	writel(readl(&gpt1_regs_ptr->cr1) | GPT_CR1_CEN,
     43 			&gpt1_regs_ptr->cr1);
     44 
     45 	/* Reset the timer */
     46 	lastdec = READ_TIMER();
     47 	timestamp = 0;
     48 
     49 	return 0;
     50 }
     51 
     52 /*
     53  * timer without interrupts
     54  */
     55 ulong get_timer(ulong base)
     56 {
     57 	return (get_timer_masked() / GPT_RESOLUTION) - base;
     58 }
     59 
     60 void __udelay(unsigned long usec)
     61 {
     62 	ulong tmo;
     63 	ulong start = get_timer_masked();
     64 	ulong tenudelcnt = CONFIG_STV0991_HZ_CLOCK / (1000 * 100);
     65 	ulong rndoff;
     66 
     67 	rndoff = (usec % 10) ? 1 : 0;
     68 
     69 	/* tenudelcnt timer tick gives 10 microsecconds delay */
     70 	tmo = ((usec / 10) + rndoff) * tenudelcnt;
     71 
     72 	while ((ulong) (get_timer_masked() - start) < tmo)
     73 		;
     74 }
     75 
     76 ulong get_timer_masked(void)
     77 {
     78 	ulong now = READ_TIMER();
     79 
     80 	if (now >= lastdec) {
     81 		/* normal mode */
     82 		timestamp += now - lastdec;
     83 	} else {
     84 		/* we have an overflow ... */
     85 		timestamp += now + GPT_FREE_RUNNING - lastdec;
     86 	}
     87 	lastdec = now;
     88 
     89 	return timestamp;
     90 }
     91 
     92 void udelay_masked(unsigned long usec)
     93 {
     94 	return udelay(usec);
     95 }
     96 
     97 /*
     98  * This function is derived from PowerPC code (read timebase as long long).
     99  * On ARM it just returns the timer value.
    100  */
    101 unsigned long long get_ticks(void)
    102 {
    103 	return get_timer(0);
    104 }
    105 
    106 /*
    107  * This function is derived from PowerPC code (timebase clock frequency).
    108  * On ARM it returns the number of timer ticks per second.
    109  */
    110 ulong get_tbclk(void)
    111 {
    112 	return CONFIG_STV0991_HZ;
    113 }
    114