|  | /* | 
|  | * linux/arch/arm/mach-omap2/timer.c | 
|  | * | 
|  | * OMAP2 GP timer support. | 
|  | * | 
|  | * Copyright (C) 2009 Nokia Corporation | 
|  | * | 
|  | * Update to use new clocksource/clockevent layers | 
|  | * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com> | 
|  | * Copyright (C) 2007 MontaVista Software, Inc. | 
|  | * | 
|  | * Original driver: | 
|  | * Copyright (C) 2005 Nokia Corporation | 
|  | * Author: Paul Mundt <paul.mundt@nokia.com> | 
|  | *         Juha Yrjölä <juha.yrjola@nokia.com> | 
|  | * OMAP Dual-mode timer framework support by Timo Teras | 
|  | * | 
|  | * Some parts based off of TI's 24xx code: | 
|  | * | 
|  | * Copyright (C) 2004-2009 Texas Instruments, Inc. | 
|  | * | 
|  | * Roughly modelled after the OMAP1 MPU timer code. | 
|  | * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com> | 
|  | * | 
|  | * This file is subject to the terms and conditions of the GNU General Public | 
|  | * License. See the file "COPYING" in the main directory of this archive | 
|  | * for more details. | 
|  | */ | 
|  | #include <linux/clk.h> | 
|  | #include <linux/clocksource.h> | 
|  |  | 
|  | #include "soc.h" | 
|  | #include "common.h" | 
|  | #include "control.h" | 
|  | #include "omap-secure.h" | 
|  |  | 
|  | #define REALTIME_COUNTER_BASE				0x48243200 | 
|  | #define INCREMENTER_NUMERATOR_OFFSET			0x10 | 
|  | #define INCREMENTER_DENUMERATOR_RELOAD_OFFSET		0x14 | 
|  | #define NUMERATOR_DENUMERATOR_MASK			0xfffff000 | 
|  |  | 
|  | static unsigned long arch_timer_freq; | 
|  |  | 
|  | void set_cntfreq(void) | 
|  | { | 
|  | omap_smc1(OMAP5_DRA7_MON_SET_CNTFRQ_INDEX, arch_timer_freq); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * The realtime counter also called master counter, is a free-running | 
|  | * counter, which is related to real time. It produces the count used | 
|  | * by the CPU local timer peripherals in the MPU cluster. The timer counts | 
|  | * at a rate of 6.144 MHz. Because the device operates on different clocks | 
|  | * in different power modes, the master counter shifts operation between | 
|  | * clocks, adjusting the increment per clock in hardware accordingly to | 
|  | * maintain a constant count rate. | 
|  | */ | 
|  | static void __init realtime_counter_init(void) | 
|  | { | 
|  | void __iomem *base; | 
|  | static struct clk *sys_clk; | 
|  | unsigned long rate; | 
|  | unsigned int reg; | 
|  | unsigned long long num, den; | 
|  |  | 
|  | base = ioremap(REALTIME_COUNTER_BASE, SZ_32); | 
|  | if (!base) { | 
|  | pr_err("%s: ioremap failed\n", __func__); | 
|  | return; | 
|  | } | 
|  | sys_clk = clk_get(NULL, "sys_clkin"); | 
|  | if (IS_ERR(sys_clk)) { | 
|  | pr_err("%s: failed to get system clock handle\n", __func__); | 
|  | iounmap(base); | 
|  | return; | 
|  | } | 
|  |  | 
|  | rate = clk_get_rate(sys_clk); | 
|  | clk_put(sys_clk); | 
|  |  | 
|  | if (soc_is_dra7xx()) { | 
|  | /* | 
|  | * Errata i856 says the 32.768KHz crystal does not start at | 
|  | * power on, so the CPU falls back to an emulated 32KHz clock | 
|  | * based on sysclk / 610 instead. This causes the master counter | 
|  | * frequency to not be 6.144MHz but at sysclk / 610 * 375 / 2 | 
|  | * (OR sysclk * 75 / 244) | 
|  | * | 
|  | * This affects at least the DRA7/AM572x 1.0, 1.1 revisions. | 
|  | * Of course any board built without a populated 32.768KHz | 
|  | * crystal would also need this fix even if the CPU is fixed | 
|  | * later. | 
|  | * | 
|  | * Either case can be detected by using the two speedselect bits | 
|  | * If they are not 0, then the 32.768KHz clock driving the | 
|  | * coarse counter that corrects the fine counter every time it | 
|  | * ticks is actually rate/610 rather than 32.768KHz and we | 
|  | * should compensate to avoid the 570ppm (at 20MHz, much worse | 
|  | * at other rates) too fast system time. | 
|  | */ | 
|  | reg = omap_ctrl_readl(DRA7_CTRL_CORE_BOOTSTRAP); | 
|  | if (reg & DRA7_SPEEDSELECT_MASK) { | 
|  | num = 75; | 
|  | den = 244; | 
|  | goto sysclk1_based; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Numerator/denumerator values refer TRM Realtime Counter section */ | 
|  | switch (rate) { | 
|  | case 12000000: | 
|  | num = 64; | 
|  | den = 125; | 
|  | break; | 
|  | case 13000000: | 
|  | num = 768; | 
|  | den = 1625; | 
|  | break; | 
|  | case 19200000: | 
|  | num = 8; | 
|  | den = 25; | 
|  | break; | 
|  | case 20000000: | 
|  | num = 192; | 
|  | den = 625; | 
|  | break; | 
|  | case 26000000: | 
|  | num = 384; | 
|  | den = 1625; | 
|  | break; | 
|  | case 27000000: | 
|  | num = 256; | 
|  | den = 1125; | 
|  | break; | 
|  | case 38400000: | 
|  | default: | 
|  | /* Program it for 38.4 MHz */ | 
|  | num = 4; | 
|  | den = 25; | 
|  | break; | 
|  | } | 
|  |  | 
|  | sysclk1_based: | 
|  | /* Program numerator and denumerator registers */ | 
|  | reg = readl_relaxed(base + INCREMENTER_NUMERATOR_OFFSET) & | 
|  | NUMERATOR_DENUMERATOR_MASK; | 
|  | reg |= num; | 
|  | writel_relaxed(reg, base + INCREMENTER_NUMERATOR_OFFSET); | 
|  |  | 
|  | reg = readl_relaxed(base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET) & | 
|  | NUMERATOR_DENUMERATOR_MASK; | 
|  | reg |= den; | 
|  | writel_relaxed(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET); | 
|  |  | 
|  | arch_timer_freq = DIV_ROUND_UP_ULL(rate * num, den); | 
|  | set_cntfreq(); | 
|  |  | 
|  | iounmap(base); | 
|  | } | 
|  |  | 
|  | void __init omap5_realtime_timer_init(void) | 
|  | { | 
|  | omap_clk_init(); | 
|  | realtime_counter_init(); | 
|  |  | 
|  | timer_probe(); | 
|  | } |