cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

timer.c (4449B)


      1/*
      2 * linux/arch/arm/mach-omap2/timer.c
      3 *
      4 * OMAP2 GP timer support.
      5 *
      6 * Copyright (C) 2009 Nokia Corporation
      7 *
      8 * Update to use new clocksource/clockevent layers
      9 * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
     10 * Copyright (C) 2007 MontaVista Software, Inc.
     11 *
     12 * Original driver:
     13 * Copyright (C) 2005 Nokia Corporation
     14 * Author: Paul Mundt <paul.mundt@nokia.com>
     15 *         Juha Yrjölä <juha.yrjola@nokia.com>
     16 * OMAP Dual-mode timer framework support by Timo Teras
     17 *
     18 * Some parts based off of TI's 24xx code:
     19 *
     20 * Copyright (C) 2004-2009 Texas Instruments, Inc.
     21 *
     22 * Roughly modelled after the OMAP1 MPU timer code.
     23 * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
     24 *
     25 * This file is subject to the terms and conditions of the GNU General Public
     26 * License. See the file "COPYING" in the main directory of this archive
     27 * for more details.
     28 */
     29#include <linux/clk.h>
     30#include <linux/clocksource.h>
     31
     32#include "soc.h"
     33#include "common.h"
     34#include "control.h"
     35#include "omap-secure.h"
     36
     37#define REALTIME_COUNTER_BASE				0x48243200
     38#define INCREMENTER_NUMERATOR_OFFSET			0x10
     39#define INCREMENTER_DENUMERATOR_RELOAD_OFFSET		0x14
     40#define NUMERATOR_DENUMERATOR_MASK			0xfffff000
     41
     42static unsigned long arch_timer_freq;
     43
     44void set_cntfreq(void)
     45{
     46	omap_smc1(OMAP5_DRA7_MON_SET_CNTFRQ_INDEX, arch_timer_freq);
     47}
     48
     49/*
     50 * The realtime counter also called master counter, is a free-running
     51 * counter, which is related to real time. It produces the count used
     52 * by the CPU local timer peripherals in the MPU cluster. The timer counts
     53 * at a rate of 6.144 MHz. Because the device operates on different clocks
     54 * in different power modes, the master counter shifts operation between
     55 * clocks, adjusting the increment per clock in hardware accordingly to
     56 * maintain a constant count rate.
     57 */
     58static void __init realtime_counter_init(void)
     59{
     60	void __iomem *base;
     61	static struct clk *sys_clk;
     62	unsigned long rate;
     63	unsigned int reg;
     64	unsigned long long num, den;
     65
     66	base = ioremap(REALTIME_COUNTER_BASE, SZ_32);
     67	if (!base) {
     68		pr_err("%s: ioremap failed\n", __func__);
     69		return;
     70	}
     71	sys_clk = clk_get(NULL, "sys_clkin");
     72	if (IS_ERR(sys_clk)) {
     73		pr_err("%s: failed to get system clock handle\n", __func__);
     74		iounmap(base);
     75		return;
     76	}
     77
     78	rate = clk_get_rate(sys_clk);
     79
     80	if (soc_is_dra7xx()) {
     81		/*
     82		 * Errata i856 says the 32.768KHz crystal does not start at
     83		 * power on, so the CPU falls back to an emulated 32KHz clock
     84		 * based on sysclk / 610 instead. This causes the master counter
     85		 * frequency to not be 6.144MHz but at sysclk / 610 * 375 / 2
     86		 * (OR sysclk * 75 / 244)
     87		 *
     88		 * This affects at least the DRA7/AM572x 1.0, 1.1 revisions.
     89		 * Of course any board built without a populated 32.768KHz
     90		 * crystal would also need this fix even if the CPU is fixed
     91		 * later.
     92		 *
     93		 * Either case can be detected by using the two speedselect bits
     94		 * If they are not 0, then the 32.768KHz clock driving the
     95		 * coarse counter that corrects the fine counter every time it
     96		 * ticks is actually rate/610 rather than 32.768KHz and we
     97		 * should compensate to avoid the 570ppm (at 20MHz, much worse
     98		 * at other rates) too fast system time.
     99		 */
    100		reg = omap_ctrl_readl(DRA7_CTRL_CORE_BOOTSTRAP);
    101		if (reg & DRA7_SPEEDSELECT_MASK) {
    102			num = 75;
    103			den = 244;
    104			goto sysclk1_based;
    105		}
    106	}
    107
    108	/* Numerator/denumerator values refer TRM Realtime Counter section */
    109	switch (rate) {
    110	case 12000000:
    111		num = 64;
    112		den = 125;
    113		break;
    114	case 13000000:
    115		num = 768;
    116		den = 1625;
    117		break;
    118	case 19200000:
    119		num = 8;
    120		den = 25;
    121		break;
    122	case 20000000:
    123		num = 192;
    124		den = 625;
    125		break;
    126	case 26000000:
    127		num = 384;
    128		den = 1625;
    129		break;
    130	case 27000000:
    131		num = 256;
    132		den = 1125;
    133		break;
    134	case 38400000:
    135	default:
    136		/* Program it for 38.4 MHz */
    137		num = 4;
    138		den = 25;
    139		break;
    140	}
    141
    142sysclk1_based:
    143	/* Program numerator and denumerator registers */
    144	reg = readl_relaxed(base + INCREMENTER_NUMERATOR_OFFSET) &
    145			NUMERATOR_DENUMERATOR_MASK;
    146	reg |= num;
    147	writel_relaxed(reg, base + INCREMENTER_NUMERATOR_OFFSET);
    148
    149	reg = readl_relaxed(base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET) &
    150			NUMERATOR_DENUMERATOR_MASK;
    151	reg |= den;
    152	writel_relaxed(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET);
    153
    154	arch_timer_freq = DIV_ROUND_UP_ULL(rate * num, den);
    155	set_cntfreq();
    156
    157	iounmap(base);
    158}
    159
    160void __init omap5_realtime_timer_init(void)
    161{
    162	omap_clk_init();
    163	realtime_counter_init();
    164
    165	timer_probe();
    166}