linux/drivers/clocksource/clksrc-dbx500-prcmu.c
<<
>>
Prefs
   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);
  73