Release 4.7 drivers/clocksource/vt8500_timer.c
/*
* arch/arm/mach-vt8500/timer.c
*
* Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
* Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* This file is copied and modified from the original timer.c provided by
* Alexey Charkov. Minor changes have been made for Device Tree Support.
*/
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/clocksource.h>
#include <linux/clockchips.h>
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#define VT8500_TIMER_OFFSET 0x0100
#define VT8500_TIMER_HZ 3000000
#define TIMER_MATCH_VAL 0x0000
#define TIMER_COUNT_VAL 0x0010
#define TIMER_STATUS_VAL 0x0014
#define TIMER_IER_VAL 0x001c
/* interrupt enable */
#define TIMER_CTRL_VAL 0x0020
#define TIMER_AS_VAL 0x0024
/* access status */
#define TIMER_COUNT_R_ACTIVE (1 << 5)
/* not ready for read */
#define TIMER_COUNT_W_ACTIVE (1 << 4)
/* not ready for write */
#define TIMER_MATCH_W_ACTIVE (1 << 0)
/* not ready for write */
#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
#define MIN_OSCR_DELTA 16
static void __iomem *regbase;
static cycle_t vt8500_timer_read(struct clocksource *cs)
{
int loops = msecs_to_loops(10);
writel(3, regbase + TIMER_CTRL_VAL);
while ((readl((regbase + TIMER_AS_VAL)) & TIMER_COUNT_R_ACTIVE)
&& --loops)
cpu_relax();
return readl(regbase + TIMER_COUNT_VAL);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
alexey charkov | alexey charkov | 57 | 100.00% | 1 | 100.00% |
| Total | 57 | 100.00% | 1 | 100.00% |
static struct clocksource clocksource = {
.name = "vt8500_timer",
.rating = 200,
.read = vt8500_timer_read,
.mask = CLOCKSOURCE_MASK(32),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
static int vt8500_timer_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
{
int loops = msecs_to_loops(10);
cycle_t alarm = clocksource.read(&clocksource) + cycles;
while ((readl(regbase + TIMER_AS_VAL) & TIMER_MATCH_W_ACTIVE)
&& --loops)
cpu_relax();
writel((unsigned long)alarm, regbase + TIMER_MATCH_VAL);
if ((signed)(alarm - clocksource.read(&clocksource)) <= MIN_OSCR_DELTA)
return -ETIME;
writel(1, regbase + TIMER_IER_VAL);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
alexey charkov | alexey charkov | 102 | 99.03% | 1 | 50.00% |
roman volkov | roman volkov | 1 | 0.97% | 1 | 50.00% |
| Total | 103 | 100.00% | 2 | 100.00% |
static int vt8500_shutdown(struct clock_event_device *evt)
{
writel(readl(regbase + TIMER_CTRL_VAL) | 1, regbase + TIMER_CTRL_VAL);
writel(0, regbase + TIMER_IER_VAL);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
alexey charkov | alexey charkov | 34 | 87.18% | 1 | 50.00% |
viresh kumar | viresh kumar | 5 | 12.82% | 1 | 50.00% |
| Total | 39 | 100.00% | 2 | 100.00% |
static struct clock_event_device clockevent = {
.name = "vt8500_timer",
.features = CLOCK_EVT_FEAT_ONESHOT,
.rating = 200,
.set_next_event = vt8500_timer_set_next_event,
.set_state_shutdown = vt8500_shutdown,
.set_state_oneshot = vt8500_shutdown,
};
static irqreturn_t vt8500_timer_interrupt(int irq, void *dev_id)
{
struct clock_event_device *evt = dev_id;
writel(0xf, regbase + TIMER_STATUS_VAL);
evt->event_handler(evt);
return IRQ_HANDLED;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
alexey charkov | alexey charkov | 39 | 100.00% | 1 | 100.00% |
| Total | 39 | 100.00% | 1 | 100.00% |
static struct irqaction irq = {
.name = "vt8500_timer",
.flags = IRQF_TIMER | IRQF_IRQPOLL,
.handler = vt8500_timer_interrupt,
.dev_id = &clockevent,
};
static void __init vt8500_timer_init(struct device_node *np)
{
int timer_irq;
regbase = of_iomap(np, 0);
if (!regbase) {
pr_err("%s: Missing iobase description in Device Tree\n",
__func__);
return;
}
timer_irq = irq_of_parse_and_map(np, 0);
if (!timer_irq) {
pr_err("%s: Missing irq description in Device Tree\n",
__func__);
return;
}
writel(1, regbase + TIMER_CTRL_VAL);
writel(0xf, regbase + TIMER_STATUS_VAL);
writel(~0, regbase + TIMER_MATCH_VAL);
if (clocksource_register_hz(&clocksource, VT8500_TIMER_HZ))
pr_err("%s: vt8500_timer_init: clocksource_register failed for %s\n",
__func__, clocksource.name);
clockevent.cpumask = cpumask_of(0);
if (setup_irq(timer_irq, &irq))
pr_err("%s: setup_irq failed for %s\n", __func__,
clockevent.name);
clockevents_config_and_register(&clockevent, VT8500_TIMER_HZ,
MIN_OSCR_DELTA * 2, 0xf0000000);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
alexey charkov | alexey charkov | 91 | 58.33% | 1 | 16.67% |
tony prisk | tony prisk | 54 | 34.62% | 2 | 33.33% |
shawn guo | shawn guo | 6 | 3.85% | 1 | 16.67% |
roman volkov | roman volkov | 3 | 1.92% | 1 | 16.67% |
rob herring | rob herring | 2 | 1.28% | 1 | 16.67% |
| Total | 156 | 100.00% | 6 | 100.00% |
CLOCKSOURCE_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init);
Overall Contributors
| Person | Tokens | Prop | Commits | CommitProp |
alexey charkov | alexey charkov | 493 | 82.17% | 1 | 11.11% |
tony prisk | tony prisk | 76 | 12.67% | 3 | 33.33% |
viresh kumar | viresh kumar | 12 | 2.00% | 1 | 11.11% |
roman volkov | roman volkov | 8 | 1.33% | 1 | 11.11% |
shawn guo | shawn guo | 6 | 1.00% | 1 | 11.11% |
arnd bergmann | arnd bergmann | 3 | 0.50% | 1 | 11.11% |
rob herring | rob herring | 2 | 0.33% | 1 | 11.11% |
| Total | 600 | 100.00% | 9 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.