~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/clocksource/clksrc-dbx500-prcmu.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) ST-Ericsson SA 2011
 
3
 *
 
4
 * License Terms: GNU General Public License v2
 
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 and Timer 3 on DB5500.
 
14
 */
 
15
#include <linux/clockchips.h>
 
16
#include <linux/clksrc-dbx500-prcmu.h>
 
17
 
 
18
#include <asm/sched_clock.h>
 
19
 
 
20
#include <mach/setup.h>
 
21
#include <mach/hardware.h>
 
22
 
 
23
#define RATE_32K                32768
 
24
 
 
25
#define TIMER_MODE_CONTINOUS    0x1
 
26
#define TIMER_DOWNCOUNT_VAL     0xffffffff
 
27
 
 
28
#define PRCMU_TIMER_REF         0
 
29
#define PRCMU_TIMER_DOWNCOUNT   0x4
 
30
#define PRCMU_TIMER_MODE        0x8
 
31
 
 
32
#define SCHED_CLOCK_MIN_WRAP 131072 /* 2^32 / 32768 */
 
33
 
 
34
static void __iomem *clksrc_dbx500_timer_base;
 
35
 
 
36
static cycle_t clksrc_dbx500_prcmu_read(struct clocksource *cs)
 
37
{
 
38
        u32 count, count2;
 
39
 
 
40
        do {
 
41
                count = readl(clksrc_dbx500_timer_base +
 
42
                              PRCMU_TIMER_DOWNCOUNT);
 
43
                count2 = readl(clksrc_dbx500_timer_base +
 
44
                               PRCMU_TIMER_DOWNCOUNT);
 
45
        } while (count2 != count);
 
46
 
 
47
        /* Negate because the timer is a decrementing counter */
 
48
        return ~count;
 
49
}
 
50
 
 
51
static struct clocksource clocksource_dbx500_prcmu = {
 
52
        .name           = "dbx500-prcmu-timer",
 
53
        .rating         = 300,
 
54
        .read           = clksrc_dbx500_prcmu_read,
 
55
        .shift          = 10,
 
56
        .mask           = CLOCKSOURCE_MASK(32),
 
57
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 
58
};
 
59
 
 
60
#ifdef CONFIG_CLKSRC_DBX500_PRCMU_SCHED_CLOCK
 
61
static DEFINE_CLOCK_DATA(cd);
 
62
 
 
63
unsigned long long notrace sched_clock(void)
 
64
{
 
65
        u32 cyc;
 
66
 
 
67
        if (unlikely(!clksrc_dbx500_timer_base))
 
68
                return 0;
 
69
 
 
70
        cyc = clksrc_dbx500_prcmu_read(&clocksource_dbx500_prcmu);
 
71
 
 
72
        return cyc_to_sched_clock(&cd, cyc, (u32)~0);
 
73
}
 
74
 
 
75
static void notrace clksrc_dbx500_prcmu_update_sched_clock(void)
 
76
{
 
77
        u32 cyc = clksrc_dbx500_prcmu_read(&clocksource_dbx500_prcmu);
 
78
        update_sched_clock(&cd, cyc, (u32)~0);
 
79
}
 
80
#endif
 
81
 
 
82
void __init clksrc_dbx500_prcmu_init(void __iomem *base)
 
83
{
 
84
        clksrc_dbx500_timer_base = base;
 
85
 
 
86
        /*
 
87
         * The A9 sub system expects the timer to be configured as
 
88
         * a continous looping timer.
 
89
         * The PRCMU should configure it but if it for some reason
 
90
         * don't we do it here.
 
91
         */
 
92
        if (readl(clksrc_dbx500_timer_base + PRCMU_TIMER_MODE) !=
 
93
            TIMER_MODE_CONTINOUS) {
 
94
                writel(TIMER_MODE_CONTINOUS,
 
95
                       clksrc_dbx500_timer_base + PRCMU_TIMER_MODE);
 
96
                writel(TIMER_DOWNCOUNT_VAL,
 
97
                       clksrc_dbx500_timer_base + PRCMU_TIMER_REF);
 
98
        }
 
99
#ifdef CONFIG_CLKSRC_DBX500_PRCMU_SCHED_CLOCK
 
100
        init_sched_clock(&cd, clksrc_dbx500_prcmu_update_sched_clock,
 
101
                         32, RATE_32K);
 
102
#endif
 
103
        clocksource_calc_mult_shift(&clocksource_dbx500_prcmu,
 
104
                                    RATE_32K, SCHED_CLOCK_MIN_WRAP);
 
105
        clocksource_register(&clocksource_dbx500_prcmu);
 
106
}