uboot/arch/arm/mach-imx/timer.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2007
   3 * Sascha Hauer, Pengutronix
   4 *
   5 * (C) Copyright 2009 Freescale Semiconductor, Inc.
   6 *
   7 * SPDX-License-Identifier:     GPL-2.0+
   8 */
   9
  10#include <common.h>
  11#include <asm/io.h>
  12#include <div64.h>
  13#include <asm/arch/imx-regs.h>
  14#include <asm/arch/clock.h>
  15#include <asm/arch/sys_proto.h>
  16
  17/* General purpose timers registers */
  18struct mxc_gpt {
  19        unsigned int control;
  20        unsigned int prescaler;
  21        unsigned int status;
  22        unsigned int nouse[6];
  23        unsigned int counter;
  24};
  25
  26static struct mxc_gpt *cur_gpt = (struct mxc_gpt *)GPT1_BASE_ADDR;
  27
  28/* General purpose timers bitfields */
  29#define GPTCR_SWR               (1 << 15)       /* Software reset */
  30#define GPTCR_24MEN         (1 << 10)   /* Enable 24MHz clock input */
  31#define GPTCR_FRR               (1 << 9)        /* Freerun / restart */
  32#define GPTCR_CLKSOURCE_32      (4 << 6)        /* Clock source 32khz */
  33#define GPTCR_CLKSOURCE_OSC     (5 << 6)        /* Clock source OSC */
  34#define GPTCR_CLKSOURCE_PRE     (1 << 6)        /* Clock source PRECLK */
  35#define GPTCR_CLKSOURCE_MASK (0x7 << 6)
  36#define GPTCR_TEN               1               /* Timer enable */
  37
  38#define GPTPR_PRESCALER24M_SHIFT 12
  39#define GPTPR_PRESCALER24M_MASK (0xF << GPTPR_PRESCALER24M_SHIFT)
  40
  41DECLARE_GLOBAL_DATA_PTR;
  42
  43static inline int gpt_has_clk_source_osc(void)
  44{
  45#if defined(CONFIG_MX6)
  46        if (((is_mx6dq()) && (soc_rev() > CHIP_REV_1_0)) ||
  47            is_mx6dqp() || is_mx6sdl() || is_mx6sx() || is_mx6ul() ||
  48            is_mx6ull() || is_mx6sll())
  49                return 1;
  50
  51        return 0;
  52#else
  53        return 0;
  54#endif
  55}
  56
  57static inline ulong gpt_get_clk(void)
  58{
  59#ifdef CONFIG_MXC_GPT_HCLK
  60        if (gpt_has_clk_source_osc())
  61                return MXC_HCLK >> 3;
  62        else
  63                return mxc_get_clock(MXC_IPG_PERCLK);
  64#else
  65        return MXC_CLK32;
  66#endif
  67}
  68
  69int timer_init(void)
  70{
  71        int i;
  72
  73        /* setup GP Timer 1 */
  74        __raw_writel(GPTCR_SWR, &cur_gpt->control);
  75
  76        /* We have no udelay by now */
  77        __raw_writel(0, &cur_gpt->control);
  78
  79        i = __raw_readl(&cur_gpt->control);
  80        i &= ~GPTCR_CLKSOURCE_MASK;
  81
  82#ifdef CONFIG_MXC_GPT_HCLK
  83        if (gpt_has_clk_source_osc()) {
  84                i |= GPTCR_CLKSOURCE_OSC | GPTCR_TEN;
  85
  86                /*
  87                 * For DL/S, SX, UL, ULL, SLL set 24Mhz OSC
  88                 * Enable bit and prescaler
  89                 */
  90                if (is_mx6sdl() || is_mx6sx() || is_mx6ul() || is_mx6ull() ||
  91                    is_mx6sll()) {
  92                        i |= GPTCR_24MEN;
  93
  94                        /* Produce 3Mhz clock */
  95                        __raw_writel((7 << GPTPR_PRESCALER24M_SHIFT),
  96                                     &cur_gpt->prescaler);
  97                }
  98        } else {
  99                i |= GPTCR_CLKSOURCE_PRE | GPTCR_TEN;
 100        }
 101#else
 102        __raw_writel(0, &cur_gpt->prescaler); /* 32Khz */
 103        i |= GPTCR_CLKSOURCE_32 | GPTCR_TEN;
 104#endif
 105        __raw_writel(i, &cur_gpt->control);
 106
 107        return 0;
 108}
 109
 110unsigned long timer_read_counter(void)
 111{
 112        return __raw_readl(&cur_gpt->counter); /* current tick value */
 113}
 114
 115/*
 116 * This function is derived from PowerPC code (timebase clock frequency).
 117 * On ARM it returns the number of timer ticks per second.
 118 */
 119ulong get_tbclk(void)
 120{
 121        return gpt_get_clk();
 122}
 123
 124/*
 125 * This function is intended for SHORT delays only.
 126 * It will overflow at around 10 seconds @ 400MHz,
 127 * or 20 seconds @ 200MHz.
 128 */
 129unsigned long usec2ticks(unsigned long _usec)
 130{
 131        unsigned long long usec = _usec;
 132
 133        usec *= get_tbclk();
 134        usec += 999999;
 135        do_div(usec, 1000000);
 136
 137        return usec;
 138}
 139