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

clksrc-dbx500-prcmu.c (2152B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) ST-Ericsson SA 2011
      4 *
      5 * Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson
      6 * Author: Sundar Iyer for ST-Ericsson
      7 * sched_clock implementation is based on:
      8 * plat-nomadik/timer.c Linus Walleij <linus.walleij@stericsson.com>
      9 *
     10 * DBx500-PRCMU Timer
     11 * The PRCMU has 5 timers which are available in a always-on
     12 * power domain.  We use the Timer 4 for our always-on clock
     13 * source on DB8500.
     14 */
     15#include <linux/of.h>
     16#include <linux/of_address.h>
     17#include <linux/clockchips.h>
     18
     19#define RATE_32K		32768
     20
     21#define TIMER_MODE_CONTINUOUS	0x1
     22#define TIMER_DOWNCOUNT_VAL	0xffffffff
     23
     24#define PRCMU_TIMER_REF		0
     25#define PRCMU_TIMER_DOWNCOUNT	0x4
     26#define PRCMU_TIMER_MODE	0x8
     27
     28static void __iomem *clksrc_dbx500_timer_base;
     29
     30static u64 notrace clksrc_dbx500_prcmu_read(struct clocksource *cs)
     31{
     32	void __iomem *base = clksrc_dbx500_timer_base;
     33	u32 count, count2;
     34
     35	do {
     36		count = readl_relaxed(base + PRCMU_TIMER_DOWNCOUNT);
     37		count2 = readl_relaxed(base + PRCMU_TIMER_DOWNCOUNT);
     38	} while (count2 != count);
     39
     40	/* Negate because the timer is a decrementing counter */
     41	return ~count;
     42}
     43
     44static struct clocksource clocksource_dbx500_prcmu = {
     45	.name		= "dbx500-prcmu-timer",
     46	.rating		= 100,
     47	.read		= clksrc_dbx500_prcmu_read,
     48	.mask		= CLOCKSOURCE_MASK(32),
     49	.flags		= CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_SUSPEND_NONSTOP,
     50};
     51
     52static int __init clksrc_dbx500_prcmu_init(struct device_node *node)
     53{
     54	clksrc_dbx500_timer_base = of_iomap(node, 0);
     55
     56	/*
     57	 * The A9 sub system expects the timer to be configured as
     58	 * a continuous looping timer.
     59	 * The PRCMU should configure it but if it for some reason
     60	 * don't we do it here.
     61	 */
     62	if (readl(clksrc_dbx500_timer_base + PRCMU_TIMER_MODE) !=
     63	    TIMER_MODE_CONTINUOUS) {
     64		writel(TIMER_MODE_CONTINUOUS,
     65		       clksrc_dbx500_timer_base + PRCMU_TIMER_MODE);
     66		writel(TIMER_DOWNCOUNT_VAL,
     67		       clksrc_dbx500_timer_base + PRCMU_TIMER_REF);
     68	}
     69	return clocksource_register_hz(&clocksource_dbx500_prcmu, RATE_32K);
     70}
     71TIMER_OF_DECLARE(dbx500_prcmu, "stericsson,db8500-prcmu-timer-4",
     72		       clksrc_dbx500_prcmu_init);