cregit-Linux how code gets into the kernel

Release 4.11 arch/arm/mach-spear/time.c

/*
 * arch/arm/plat-spear/time.c
 *
 * Copyright (C) 2010 ST Microelectronics
 * Shiraz Hashim<shiraz.linux.kernel@gmail.com>
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2. This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */

#include <linux/clk.h>
#include <linux/clockchips.h>
#include <linux/clocksource.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/time.h>
#include <linux/irq.h>
#include <asm/mach/time.h>
#include "generic.h"

/*
 * We would use TIMER0 and TIMER1 as clockevent and clocksource.
 * Timer0 and Timer1 both belong to same gpt block in cpu subbsystem. Further
 * they share same functional clock. Any change in one's functional clock will
 * also affect other timer.
 */


#define CLKEVT	0	
/* gpt0, channel0 as clockevent */

#define CLKSRC	1	
/* gpt0, channel1 as clocksource */

/* Register offsets, x is channel number */

#define CR(x)		((x) * 0x80 + 0x80)

#define IR(x)		((x) * 0x80 + 0x84)

#define LOAD(x)		((x) * 0x80 + 0x88)

#define COUNT(x)	((x) * 0x80 + 0x8C)

/* Reg bit definitions */

#define CTRL_INT_ENABLE		0x0100

#define CTRL_ENABLE		0x0020

#define CTRL_ONE_SHOT		0x0010


#define CTRL_PRESCALER1		0x0

#define CTRL_PRESCALER2		0x1

#define CTRL_PRESCALER4		0x2

#define CTRL_PRESCALER8		0x3

#define CTRL_PRESCALER16	0x4

#define CTRL_PRESCALER32	0x5

#define CTRL_PRESCALER64	0x6

#define CTRL_PRESCALER128	0x7

#define CTRL_PRESCALER256	0x8


#define INT_STATUS		0x1

/*
 * Minimum clocksource/clockevent timer range in seconds
 */

#define SPEAR_MIN_RANGE 4


static __iomem void *gpt_base;

static struct clk *gpt_clk;

static int clockevent_next_event(unsigned long evt,
				 struct clock_event_device *clk_event_dev);


static void __init spear_clocksource_init(void) { u32 tick_rate; u16 val; /* program the prescaler (/256)*/ writew(CTRL_PRESCALER256, gpt_base + CR(CLKSRC)); /* find out actual clock driving Timer */ tick_rate = clk_get_rate(gpt_clk); tick_rate >>= CTRL_PRESCALER256; writew(0xFFFF, gpt_base + LOAD(CLKSRC)); val = readw(gpt_base + CR(CLKSRC)); val &= ~CTRL_ONE_SHOT; /* autoreload mode */ val |= CTRL_ENABLE ; writew(val, gpt_base + CR(CLKSRC)); /* register the clocksource */ clocksource_mmio_init(gpt_base + COUNT(CLKSRC), "tmr1", tick_rate, 200, 16, clocksource_mmio_readw_up); }

Contributors

PersonTokensPropCommitsCommitProp
Viresh Kumar9084.11%125.00%
Russell King1614.95%250.00%
Alex Elder10.93%125.00%
Total107100.00%4100.00%


static inline void timer_shutdown(struct clock_event_device *evt) { u16 val = readw(gpt_base + CR(CLKEVT)); /* stop the timer */ val &= ~CTRL_ENABLE; writew(val, gpt_base + CR(CLKEVT)); }

Contributors

PersonTokensPropCommitsCommitProp
Viresh Kumar43100.00%2100.00%
Total43100.00%2100.00%


static int spear_shutdown(struct clock_event_device *evt) { timer_shutdown(evt); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Viresh Kumar19100.00%2100.00%
Total19100.00%2100.00%


static int spear_set_oneshot(struct clock_event_device *evt) { u16 val; /* stop the timer */ timer_shutdown(evt); val = readw(gpt_base + CR(CLKEVT)); val |= CTRL_ONE_SHOT; writew(val, gpt_base + CR(CLKEVT)); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Viresh Kumar51100.00%2100.00%
Total51100.00%2100.00%


static int spear_set_periodic(struct clock_event_device *evt) { u32 period; u16 val; /* stop the timer */ timer_shutdown(evt); period = clk_get_rate(gpt_clk) / HZ; period >>= CTRL_PRESCALER16; writew(period, gpt_base + LOAD(CLKEVT)); val = readw(gpt_base + CR(CLKEVT)); val &= ~CTRL_ONE_SHOT; val |= CTRL_ENABLE | CTRL_INT_ENABLE; writew(val, gpt_base + CR(CLKEVT)); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Viresh Kumar86100.00%2100.00%
Total86100.00%2100.00%

static struct clock_event_device clkevt = { .name = "tmr0", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_state_shutdown = spear_shutdown, .set_state_periodic = spear_set_periodic, .set_state_oneshot = spear_set_oneshot, .tick_resume = spear_shutdown, .set_next_event = clockevent_next_event, .shift = 0, /* to be computed */ };
static int clockevent_next_event(unsigned long cycles, struct clock_event_device *clk_event_dev) { u16 val = readw(gpt_base + CR(CLKEVT)); if (val & CTRL_ENABLE) writew(val & ~CTRL_ENABLE, gpt_base + CR(CLKEVT)); writew(cycles, gpt_base + LOAD(CLKEVT)); val |= CTRL_ENABLE | CTRL_INT_ENABLE; writew(val, gpt_base + CR(CLKEVT)); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Viresh Kumar5769.51%150.00%
Gilles Chanteperdrix2530.49%150.00%
Total82100.00%2100.00%


static irqreturn_t spear_timer_interrupt(int irq, void *dev_id) { struct clock_event_device *evt = &clkevt; writew(INT_STATUS, gpt_base + IR(CLKEVT)); evt->event_handler(evt); return IRQ_HANDLED; }

Contributors

PersonTokensPropCommitsCommitProp
Viresh Kumar43100.00%1100.00%
Total43100.00%1100.00%

static struct irqaction spear_timer_irq = { .name = "timer", .flags = IRQF_TIMER, .handler = spear_timer_interrupt };
static void __init spear_clockevent_init(int irq) { u32 tick_rate; /* program the prescaler */ writew(CTRL_PRESCALER16, gpt_base + CR(CLKEVT)); tick_rate = clk_get_rate(gpt_clk); tick_rate >>= CTRL_PRESCALER16; clkevt.cpumask = cpumask_of(0); clockevents_config_and_register(&clkevt, tick_rate, 3, 0xfff0); setup_irq(irq, &spear_timer_irq); }

Contributors

PersonTokensPropCommitsCommitProp
Viresh Kumar5684.85%133.33%
Shawn Guo710.61%133.33%
Arnd Bergmann34.55%133.33%
Total66100.00%3100.00%

static const struct of_device_id const timer_of_match[] __initconst = { { .compatible = "st,spear-timer", }, { }, };
void __init spear_setup_of_timer(void) { struct device_node *np; int irq, ret; np = of_find_matching_node(NULL, timer_of_match); if (!np) { pr_err("%s: No timer passed via DT\n", __func__); return; } irq = irq_of_parse_and_map(np, 0); if (!irq) { pr_err("%s: No irq passed for timer via DT\n", __func__); return; } gpt_base = of_iomap(np, 0); if (!gpt_base) { pr_err("%s: of iomap failed\n", __func__); return; } gpt_clk = clk_get_sys("gpt0", NULL); if (IS_ERR(gpt_clk)) { pr_err("%s:couldn't get clk for gpt\n", __func__); goto err_iomap; } ret = clk_prepare_enable(gpt_clk); if (ret < 0) { pr_err("%s:couldn't prepare-enable gpt clock\n", __func__); goto err_prepare_enable_clk; } spear_clockevent_init(irq); spear_clocksource_init(); return; err_prepare_enable_clk: clk_put(gpt_clk); err_iomap: iounmap(gpt_base); }

Contributors

PersonTokensPropCommitsCommitProp
Viresh Kumar14788.55%350.00%
Shiraz Hashim137.83%116.67%
Christophe Jaillet31.81%116.67%
Arnd Bergmann31.81%116.67%
Total166100.00%6100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Viresh Kumar84491.14%531.25%
Gilles Chanteperdrix252.70%16.25%
Russell King161.73%212.50%
Shiraz Hashim131.40%16.25%
Arnd Bergmann101.08%212.50%
Shawn Guo70.76%16.25%
Linus Walleij50.54%16.25%
Christophe Jaillet30.32%16.25%
Nico Pitre20.22%16.25%
Alex Elder10.11%16.25%
Total926100.00%16100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.