Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
  1/*
  2 * This file contains driver for the Xilinx PS Timer Counter IP.
  3 *
  4 *  Copyright (C) 2011 Xilinx
  5 *
  6 * based on arch/mips/kernel/time.c timer driver
  7 *
  8 * This software is licensed under the terms of the GNU General Public
  9 * License version 2, as published by the Free Software Foundation, and
 10 * may be copied, distributed, and modified under those terms.
 11 *
 12 * This program is distributed in the hope that it will be useful,
 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15 * GNU General Public License for more details.
 16 */
 17
 18#include <linux/kernel.h>
 19#include <linux/init.h>
 20#include <linux/interrupt.h>
 21#include <linux/irq.h>
 22#include <linux/types.h>
 23#include <linux/clocksource.h>
 24#include <linux/clockchips.h>
 25#include <linux/io.h>
 26
 27#include <asm/mach/time.h>
 28#include <mach/zynq_soc.h>
 29#include "common.h"
 30
 31#define IRQ_TIMERCOUNTER0	42
 32
 33/*
 34 * This driver configures the 2 16-bit count-up timers as follows:
 35 *
 36 * T1: Timer 1, clocksource for generic timekeeping
 37 * T2: Timer 2, clockevent source for hrtimers
 38 * T3: Timer 3, <unused>
 39 *
 40 * The input frequency to the timer module for emulation is 2.5MHz which is
 41 * common to all the timer channels (T1, T2, and T3). With a pre-scaler of 32,
 42 * the timers are clocked at 78.125KHz (12.8 us resolution).
 43 *
 44 * The input frequency to the timer module in silicon will be 200MHz. With the
 45 * pre-scaler of 32, the timers are clocked at 6.25MHz (160ns resolution).
 46 */
 47#define XTTCPSS_CLOCKSOURCE	0	/* Timer 1 as a generic timekeeping */
 48#define XTTCPSS_CLOCKEVENT	1	/* Timer 2 as a clock event */
 49
 50#define XTTCPSS_TIMER_BASE		TTC0_BASE
 51#define XTTCPCC_EVENT_TIMER_IRQ		(IRQ_TIMERCOUNTER0 + 1)
 52/*
 53 * Timer Register Offset Definitions of Timer 1, Increment base address by 4
 54 * and use same offsets for Timer 2
 55 */
 56#define XTTCPSS_CLK_CNTRL_OFFSET	0x00 /* Clock Control Reg, RW */
 57#define XTTCPSS_CNT_CNTRL_OFFSET	0x0C /* Counter Control Reg, RW */
 58#define XTTCPSS_COUNT_VAL_OFFSET	0x18 /* Counter Value Reg, RO */
 59#define XTTCPSS_INTR_VAL_OFFSET		0x24 /* Interval Count Reg, RW */
 60#define XTTCPSS_MATCH_1_OFFSET		0x30 /* Match 1 Value Reg, RW */
 61#define XTTCPSS_MATCH_2_OFFSET		0x3C /* Match 2 Value Reg, RW */
 62#define XTTCPSS_MATCH_3_OFFSET		0x48 /* Match 3 Value Reg, RW */
 63#define XTTCPSS_ISR_OFFSET		0x54 /* Interrupt Status Reg, RO */
 64#define XTTCPSS_IER_OFFSET		0x60 /* Interrupt Enable Reg, RW */
 65
 66#define XTTCPSS_CNT_CNTRL_DISABLE_MASK	0x1
 67
 68/* Setup the timers to use pre-scaling */
 69
 70#define TIMER_RATE (PERIPHERAL_CLOCK_RATE / 32)
 71
 72/**
 73 * struct xttcpss_timer - This definition defines local timer structure
 74 *
 75 * @base_addr:	Base address of timer
 76 **/
 77struct xttcpss_timer {
 78	void __iomem *base_addr;
 79};
 80
 81static struct xttcpss_timer timers[2];
 82static struct clock_event_device xttcpss_clockevent;
 83
 84/**
 85 * xttcpss_set_interval - Set the timer interval value
 86 *
 87 * @timer:	Pointer to the timer instance
 88 * @cycles:	Timer interval ticks
 89 **/
 90static void xttcpss_set_interval(struct xttcpss_timer *timer,
 91					unsigned long cycles)
 92{
 93	u32 ctrl_reg;
 94
 95	/* Disable the counter, set the counter value  and re-enable counter */
 96	ctrl_reg = __raw_readl(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
 97	ctrl_reg |= XTTCPSS_CNT_CNTRL_DISABLE_MASK;
 98	__raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
 99
100	__raw_writel(cycles, timer->base_addr + XTTCPSS_INTR_VAL_OFFSET);
101
102	/* Reset the counter (0x10) so that it starts from 0, one-shot
103	   mode makes this needed for timing to be right. */
104	ctrl_reg |= 0x10;
105	ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK;
106	__raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
107}
108
109/**
110 * xttcpss_clock_event_interrupt - Clock event timer interrupt handler
111 *
112 * @irq:	IRQ number of the Timer
113 * @dev_id:	void pointer to the xttcpss_timer instance
114 *
115 * returns: Always IRQ_HANDLED - success
116 **/
117static irqreturn_t xttcpss_clock_event_interrupt(int irq, void *dev_id)
118{
119	struct clock_event_device *evt = &xttcpss_clockevent;
120	struct xttcpss_timer *timer = dev_id;
121
122	/* Acknowledge the interrupt and call event handler */
123	__raw_writel(__raw_readl(timer->base_addr + XTTCPSS_ISR_OFFSET),
124			timer->base_addr + XTTCPSS_ISR_OFFSET);
125
126	evt->event_handler(evt);
127
128	return IRQ_HANDLED;
129}
130
131static struct irqaction event_timer_irq = {
132	.name	= "xttcpss clockevent",
133	.flags	= IRQF_DISABLED | IRQF_TIMER,
134	.handler = xttcpss_clock_event_interrupt,
135};
136
137/**
138 * xttcpss_timer_hardware_init - Initialize the timer hardware
139 *
140 * Initialize the hardware to start the clock source, get the clock
141 * event timer ready to use, and hook up the interrupt.
142 **/
143static void __init xttcpss_timer_hardware_init(void)
144{
145	/* Setup the clock source counter to be an incrementing counter
146	 * with no interrupt and it rolls over at 0xFFFF. Pre-scale
147	   it by 32 also. Let it start running now.
148	 */
149	timers[XTTCPSS_CLOCKSOURCE].base_addr = XTTCPSS_TIMER_BASE;
150
151	__raw_writel(0x0, timers[XTTCPSS_CLOCKSOURCE].base_addr +
152				XTTCPSS_IER_OFFSET);
153	__raw_writel(0x9, timers[XTTCPSS_CLOCKSOURCE].base_addr +
154				XTTCPSS_CLK_CNTRL_OFFSET);
155	__raw_writel(0x10, timers[XTTCPSS_CLOCKSOURCE].base_addr +
156				XTTCPSS_CNT_CNTRL_OFFSET);
157
158	/* Setup the clock event timer to be an interval timer which
159	 * is prescaled by 32 using the interval interrupt. Leave it
160	 * disabled for now.
161	 */
162
163	timers[XTTCPSS_CLOCKEVENT].base_addr = XTTCPSS_TIMER_BASE + 4;
164
165	__raw_writel(0x23, timers[XTTCPSS_CLOCKEVENT].base_addr +
166			XTTCPSS_CNT_CNTRL_OFFSET);
167	__raw_writel(0x9, timers[XTTCPSS_CLOCKEVENT].base_addr +
168			XTTCPSS_CLK_CNTRL_OFFSET);
169	__raw_writel(0x1, timers[XTTCPSS_CLOCKEVENT].base_addr +
170			XTTCPSS_IER_OFFSET);
171
172	/* Setup IRQ the clock event timer */
173	event_timer_irq.dev_id = &timers[XTTCPSS_CLOCKEVENT];
174	setup_irq(XTTCPCC_EVENT_TIMER_IRQ, &event_timer_irq);
175}
176
177/**
178 * __raw_readl_cycles - Reads the timer counter register
179 *
180 * returns: Current timer counter register value
181 **/
182static cycle_t __raw_readl_cycles(struct clocksource *cs)
183{
184	struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKSOURCE];
185
186	return (cycle_t)__raw_readl(timer->base_addr +
187				XTTCPSS_COUNT_VAL_OFFSET);
188}
189
190
191/*
192 * Instantiate and initialize the clock source structure
193 */
194static struct clocksource clocksource_xttcpss = {
195	.name		= "xttcpss_timer1",
196	.rating		= 200,			/* Reasonable clock source */
197	.read		= __raw_readl_cycles,
198	.mask		= CLOCKSOURCE_MASK(16),
199	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
200};
201
202
203/**
204 * xttcpss_set_next_event - Sets the time interval for next event
205 *
206 * @cycles:	Timer interval ticks
207 * @evt:	Address of clock event instance
208 *
209 * returns: Always 0 - success
210 **/
211static int xttcpss_set_next_event(unsigned long cycles,
212					struct clock_event_device *evt)
213{
214	struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
215
216	xttcpss_set_interval(timer, cycles);
217	return 0;
218}
219
220/**
221 * xttcpss_set_mode - Sets the mode of timer
222 *
223 * @mode:	Mode to be set
224 * @evt:	Address of clock event instance
225 **/
226static void xttcpss_set_mode(enum clock_event_mode mode,
227					struct clock_event_device *evt)
228{
229	struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
230	u32 ctrl_reg;
231
232	switch (mode) {
233	case CLOCK_EVT_MODE_PERIODIC:
234		xttcpss_set_interval(timer, TIMER_RATE / HZ);
235		break;
236	case CLOCK_EVT_MODE_ONESHOT:
237	case CLOCK_EVT_MODE_UNUSED:
238	case CLOCK_EVT_MODE_SHUTDOWN:
239		ctrl_reg = __raw_readl(timer->base_addr +
240					XTTCPSS_CNT_CNTRL_OFFSET);
241		ctrl_reg |= XTTCPSS_CNT_CNTRL_DISABLE_MASK;
242		__raw_writel(ctrl_reg,
243				timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
244		break;
245	case CLOCK_EVT_MODE_RESUME:
246		ctrl_reg = __raw_readl(timer->base_addr +
247					XTTCPSS_CNT_CNTRL_OFFSET);
248		ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK;
249		__raw_writel(ctrl_reg,
250				timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
251		break;
252	}
253}
254
255/*
256 * Instantiate and initialize the clock event structure
257 */
258static struct clock_event_device xttcpss_clockevent = {
259	.name		= "xttcpss_timer2",
260	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
261	.set_next_event	= xttcpss_set_next_event,
262	.set_mode	= xttcpss_set_mode,
263	.rating		= 200,
264};
265
266/**
267 * xttcpss_timer_init - Initialize the timer
268 *
269 * Initializes the timer hardware and register the clock source and clock event
270 * timers with Linux kernal timer framework
271 **/
272static void __init xttcpss_timer_init(void)
273{
274	xttcpss_timer_hardware_init();
275	clocksource_register_hz(&clocksource_xttcpss, TIMER_RATE);
276
277	/* Calculate the parameters to allow the clockevent to operate using
278	   integer math
279	*/
280	clockevents_calc_mult_shift(&xttcpss_clockevent, TIMER_RATE, 4);
281
282	xttcpss_clockevent.max_delta_ns =
283		clockevent_delta2ns(0xfffe, &xttcpss_clockevent);
284	xttcpss_clockevent.min_delta_ns =
285		clockevent_delta2ns(1, &xttcpss_clockevent);
286
287	/* Indicate that clock event is on 1st CPU as SMP boot needs it */
288
289	xttcpss_clockevent.cpumask = cpumask_of(0);
290	clockevents_register_device(&xttcpss_clockevent);
291}
292
293/*
294 * Instantiate and initialize the system timer structure
295 */
296struct sys_timer xttcpss_sys_timer = {
297	.init		= xttcpss_timer_init,
298};