Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * linux/arch/arm/mach-omap2/timer.c
0003  *
0004  * OMAP2 GP timer support.
0005  *
0006  * Copyright (C) 2009 Nokia Corporation
0007  *
0008  * Update to use new clocksource/clockevent layers
0009  * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
0010  * Copyright (C) 2007 MontaVista Software, Inc.
0011  *
0012  * Original driver:
0013  * Copyright (C) 2005 Nokia Corporation
0014  * Author: Paul Mundt <paul.mundt@nokia.com>
0015  *         Juha Yrjölä <juha.yrjola@nokia.com>
0016  * OMAP Dual-mode timer framework support by Timo Teras
0017  *
0018  * Some parts based off of TI's 24xx code:
0019  *
0020  * Copyright (C) 2004-2009 Texas Instruments, Inc.
0021  *
0022  * Roughly modelled after the OMAP1 MPU timer code.
0023  * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
0024  *
0025  * This file is subject to the terms and conditions of the GNU General Public
0026  * License. See the file "COPYING" in the main directory of this archive
0027  * for more details.
0028  */
0029 #include <linux/clk.h>
0030 #include <linux/clocksource.h>
0031 
0032 #include "soc.h"
0033 #include "common.h"
0034 #include "control.h"
0035 #include "omap-secure.h"
0036 
0037 #define REALTIME_COUNTER_BASE               0x48243200
0038 #define INCREMENTER_NUMERATOR_OFFSET            0x10
0039 #define INCREMENTER_DENUMERATOR_RELOAD_OFFSET       0x14
0040 #define NUMERATOR_DENUMERATOR_MASK          0xfffff000
0041 
0042 static unsigned long arch_timer_freq;
0043 
0044 void set_cntfreq(void)
0045 {
0046     omap_smc1(OMAP5_DRA7_MON_SET_CNTFRQ_INDEX, arch_timer_freq);
0047 }
0048 
0049 /*
0050  * The realtime counter also called master counter, is a free-running
0051  * counter, which is related to real time. It produces the count used
0052  * by the CPU local timer peripherals in the MPU cluster. The timer counts
0053  * at a rate of 6.144 MHz. Because the device operates on different clocks
0054  * in different power modes, the master counter shifts operation between
0055  * clocks, adjusting the increment per clock in hardware accordingly to
0056  * maintain a constant count rate.
0057  */
0058 static void __init realtime_counter_init(void)
0059 {
0060     void __iomem *base;
0061     static struct clk *sys_clk;
0062     unsigned long rate;
0063     unsigned int reg;
0064     unsigned long long num, den;
0065 
0066     base = ioremap(REALTIME_COUNTER_BASE, SZ_32);
0067     if (!base) {
0068         pr_err("%s: ioremap failed\n", __func__);
0069         return;
0070     }
0071     sys_clk = clk_get(NULL, "sys_clkin");
0072     if (IS_ERR(sys_clk)) {
0073         pr_err("%s: failed to get system clock handle\n", __func__);
0074         iounmap(base);
0075         return;
0076     }
0077 
0078     rate = clk_get_rate(sys_clk);
0079 
0080     if (soc_is_dra7xx()) {
0081         /*
0082          * Errata i856 says the 32.768KHz crystal does not start at
0083          * power on, so the CPU falls back to an emulated 32KHz clock
0084          * based on sysclk / 610 instead. This causes the master counter
0085          * frequency to not be 6.144MHz but at sysclk / 610 * 375 / 2
0086          * (OR sysclk * 75 / 244)
0087          *
0088          * This affects at least the DRA7/AM572x 1.0, 1.1 revisions.
0089          * Of course any board built without a populated 32.768KHz
0090          * crystal would also need this fix even if the CPU is fixed
0091          * later.
0092          *
0093          * Either case can be detected by using the two speedselect bits
0094          * If they are not 0, then the 32.768KHz clock driving the
0095          * coarse counter that corrects the fine counter every time it
0096          * ticks is actually rate/610 rather than 32.768KHz and we
0097          * should compensate to avoid the 570ppm (at 20MHz, much worse
0098          * at other rates) too fast system time.
0099          */
0100         reg = omap_ctrl_readl(DRA7_CTRL_CORE_BOOTSTRAP);
0101         if (reg & DRA7_SPEEDSELECT_MASK) {
0102             num = 75;
0103             den = 244;
0104             goto sysclk1_based;
0105         }
0106     }
0107 
0108     /* Numerator/denumerator values refer TRM Realtime Counter section */
0109     switch (rate) {
0110     case 12000000:
0111         num = 64;
0112         den = 125;
0113         break;
0114     case 13000000:
0115         num = 768;
0116         den = 1625;
0117         break;
0118     case 19200000:
0119         num = 8;
0120         den = 25;
0121         break;
0122     case 20000000:
0123         num = 192;
0124         den = 625;
0125         break;
0126     case 26000000:
0127         num = 384;
0128         den = 1625;
0129         break;
0130     case 27000000:
0131         num = 256;
0132         den = 1125;
0133         break;
0134     case 38400000:
0135     default:
0136         /* Program it for 38.4 MHz */
0137         num = 4;
0138         den = 25;
0139         break;
0140     }
0141 
0142 sysclk1_based:
0143     /* Program numerator and denumerator registers */
0144     reg = readl_relaxed(base + INCREMENTER_NUMERATOR_OFFSET) &
0145             NUMERATOR_DENUMERATOR_MASK;
0146     reg |= num;
0147     writel_relaxed(reg, base + INCREMENTER_NUMERATOR_OFFSET);
0148 
0149     reg = readl_relaxed(base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET) &
0150             NUMERATOR_DENUMERATOR_MASK;
0151     reg |= den;
0152     writel_relaxed(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET);
0153 
0154     arch_timer_freq = DIV_ROUND_UP_ULL(rate * num, den);
0155     set_cntfreq();
0156 
0157     iounmap(base);
0158 }
0159 
0160 void __init omap5_realtime_timer_init(void)
0161 {
0162     omap_clk_init();
0163     realtime_counter_init();
0164 
0165     timer_probe();
0166 }