162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * linux/arch/arm/mach-omap2/timer.c 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * OMAP2 GP timer support. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2009 Nokia Corporation 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Update to use new clocksource/clockevent layers 962306a36Sopenharmony_ci * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com> 1062306a36Sopenharmony_ci * Copyright (C) 2007 MontaVista Software, Inc. 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Original driver: 1362306a36Sopenharmony_ci * Copyright (C) 2005 Nokia Corporation 1462306a36Sopenharmony_ci * Author: Paul Mundt <paul.mundt@nokia.com> 1562306a36Sopenharmony_ci * Juha Yrjölä <juha.yrjola@nokia.com> 1662306a36Sopenharmony_ci * OMAP Dual-mode timer framework support by Timo Teras 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * Some parts based off of TI's 24xx code: 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * Copyright (C) 2004-2009 Texas Instruments, Inc. 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * Roughly modelled after the OMAP1 MPU timer code. 2362306a36Sopenharmony_ci * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com> 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 2662306a36Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive 2762306a36Sopenharmony_ci * for more details. 2862306a36Sopenharmony_ci */ 2962306a36Sopenharmony_ci#include <linux/clk.h> 3062306a36Sopenharmony_ci#include <linux/clocksource.h> 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#include "soc.h" 3362306a36Sopenharmony_ci#include "common.h" 3462306a36Sopenharmony_ci#include "control.h" 3562306a36Sopenharmony_ci#include "omap-secure.h" 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define REALTIME_COUNTER_BASE 0x48243200 3862306a36Sopenharmony_ci#define INCREMENTER_NUMERATOR_OFFSET 0x10 3962306a36Sopenharmony_ci#define INCREMENTER_DENUMERATOR_RELOAD_OFFSET 0x14 4062306a36Sopenharmony_ci#define NUMERATOR_DENUMERATOR_MASK 0xfffff000 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic unsigned long arch_timer_freq; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_civoid set_cntfreq(void) 4562306a36Sopenharmony_ci{ 4662306a36Sopenharmony_ci omap_smc1(OMAP5_DRA7_MON_SET_CNTFRQ_INDEX, arch_timer_freq); 4762306a36Sopenharmony_ci} 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/* 5062306a36Sopenharmony_ci * The realtime counter also called master counter, is a free-running 5162306a36Sopenharmony_ci * counter, which is related to real time. It produces the count used 5262306a36Sopenharmony_ci * by the CPU local timer peripherals in the MPU cluster. The timer counts 5362306a36Sopenharmony_ci * at a rate of 6.144 MHz. Because the device operates on different clocks 5462306a36Sopenharmony_ci * in different power modes, the master counter shifts operation between 5562306a36Sopenharmony_ci * clocks, adjusting the increment per clock in hardware accordingly to 5662306a36Sopenharmony_ci * maintain a constant count rate. 5762306a36Sopenharmony_ci */ 5862306a36Sopenharmony_cistatic void __init realtime_counter_init(void) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci void __iomem *base; 6162306a36Sopenharmony_ci static struct clk *sys_clk; 6262306a36Sopenharmony_ci unsigned long rate; 6362306a36Sopenharmony_ci unsigned int reg; 6462306a36Sopenharmony_ci unsigned long long num, den; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci base = ioremap(REALTIME_COUNTER_BASE, SZ_32); 6762306a36Sopenharmony_ci if (!base) { 6862306a36Sopenharmony_ci pr_err("%s: ioremap failed\n", __func__); 6962306a36Sopenharmony_ci return; 7062306a36Sopenharmony_ci } 7162306a36Sopenharmony_ci sys_clk = clk_get(NULL, "sys_clkin"); 7262306a36Sopenharmony_ci if (IS_ERR(sys_clk)) { 7362306a36Sopenharmony_ci pr_err("%s: failed to get system clock handle\n", __func__); 7462306a36Sopenharmony_ci iounmap(base); 7562306a36Sopenharmony_ci return; 7662306a36Sopenharmony_ci } 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci rate = clk_get_rate(sys_clk); 7962306a36Sopenharmony_ci clk_put(sys_clk); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci if (soc_is_dra7xx()) { 8262306a36Sopenharmony_ci /* 8362306a36Sopenharmony_ci * Errata i856 says the 32.768KHz crystal does not start at 8462306a36Sopenharmony_ci * power on, so the CPU falls back to an emulated 32KHz clock 8562306a36Sopenharmony_ci * based on sysclk / 610 instead. This causes the master counter 8662306a36Sopenharmony_ci * frequency to not be 6.144MHz but at sysclk / 610 * 375 / 2 8762306a36Sopenharmony_ci * (OR sysclk * 75 / 244) 8862306a36Sopenharmony_ci * 8962306a36Sopenharmony_ci * This affects at least the DRA7/AM572x 1.0, 1.1 revisions. 9062306a36Sopenharmony_ci * Of course any board built without a populated 32.768KHz 9162306a36Sopenharmony_ci * crystal would also need this fix even if the CPU is fixed 9262306a36Sopenharmony_ci * later. 9362306a36Sopenharmony_ci * 9462306a36Sopenharmony_ci * Either case can be detected by using the two speedselect bits 9562306a36Sopenharmony_ci * If they are not 0, then the 32.768KHz clock driving the 9662306a36Sopenharmony_ci * coarse counter that corrects the fine counter every time it 9762306a36Sopenharmony_ci * ticks is actually rate/610 rather than 32.768KHz and we 9862306a36Sopenharmony_ci * should compensate to avoid the 570ppm (at 20MHz, much worse 9962306a36Sopenharmony_ci * at other rates) too fast system time. 10062306a36Sopenharmony_ci */ 10162306a36Sopenharmony_ci reg = omap_ctrl_readl(DRA7_CTRL_CORE_BOOTSTRAP); 10262306a36Sopenharmony_ci if (reg & DRA7_SPEEDSELECT_MASK) { 10362306a36Sopenharmony_ci num = 75; 10462306a36Sopenharmony_ci den = 244; 10562306a36Sopenharmony_ci goto sysclk1_based; 10662306a36Sopenharmony_ci } 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci /* Numerator/denumerator values refer TRM Realtime Counter section */ 11062306a36Sopenharmony_ci switch (rate) { 11162306a36Sopenharmony_ci case 12000000: 11262306a36Sopenharmony_ci num = 64; 11362306a36Sopenharmony_ci den = 125; 11462306a36Sopenharmony_ci break; 11562306a36Sopenharmony_ci case 13000000: 11662306a36Sopenharmony_ci num = 768; 11762306a36Sopenharmony_ci den = 1625; 11862306a36Sopenharmony_ci break; 11962306a36Sopenharmony_ci case 19200000: 12062306a36Sopenharmony_ci num = 8; 12162306a36Sopenharmony_ci den = 25; 12262306a36Sopenharmony_ci break; 12362306a36Sopenharmony_ci case 20000000: 12462306a36Sopenharmony_ci num = 192; 12562306a36Sopenharmony_ci den = 625; 12662306a36Sopenharmony_ci break; 12762306a36Sopenharmony_ci case 26000000: 12862306a36Sopenharmony_ci num = 384; 12962306a36Sopenharmony_ci den = 1625; 13062306a36Sopenharmony_ci break; 13162306a36Sopenharmony_ci case 27000000: 13262306a36Sopenharmony_ci num = 256; 13362306a36Sopenharmony_ci den = 1125; 13462306a36Sopenharmony_ci break; 13562306a36Sopenharmony_ci case 38400000: 13662306a36Sopenharmony_ci default: 13762306a36Sopenharmony_ci /* Program it for 38.4 MHz */ 13862306a36Sopenharmony_ci num = 4; 13962306a36Sopenharmony_ci den = 25; 14062306a36Sopenharmony_ci break; 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cisysclk1_based: 14462306a36Sopenharmony_ci /* Program numerator and denumerator registers */ 14562306a36Sopenharmony_ci reg = readl_relaxed(base + INCREMENTER_NUMERATOR_OFFSET) & 14662306a36Sopenharmony_ci NUMERATOR_DENUMERATOR_MASK; 14762306a36Sopenharmony_ci reg |= num; 14862306a36Sopenharmony_ci writel_relaxed(reg, base + INCREMENTER_NUMERATOR_OFFSET); 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci reg = readl_relaxed(base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET) & 15162306a36Sopenharmony_ci NUMERATOR_DENUMERATOR_MASK; 15262306a36Sopenharmony_ci reg |= den; 15362306a36Sopenharmony_ci writel_relaxed(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET); 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci arch_timer_freq = DIV_ROUND_UP_ULL(rate * num, den); 15662306a36Sopenharmony_ci set_cntfreq(); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci iounmap(base); 15962306a36Sopenharmony_ci} 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_civoid __init omap5_realtime_timer_init(void) 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci omap_clk_init(); 16462306a36Sopenharmony_ci realtime_counter_init(); 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci timer_probe(); 16762306a36Sopenharmony_ci} 168