Linux Audio

Check our new training course

Loading...
v4.17
  1/*
  2 * Copyright (C) 2007-2013 Michal Simek <monstr@monstr.eu>
  3 * Copyright (C) 2012-2013 Xilinx, Inc.
  4 * Copyright (C) 2007-2009 PetaLogix
  5 * Copyright (C) 2006 Atmark Techno, Inc.
  6 *
  7 * This file is subject to the terms and conditions of the GNU General Public
  8 * License. See the file "COPYING" in the main directory of this archive
  9 * for more details.
 10 */
 11
 
 
 
 12#include <linux/interrupt.h>
 
 
 13#include <linux/delay.h>
 14#include <linux/sched.h>
 15#include <linux/sched/clock.h>
 16#include <linux/sched_clock.h>
 17#include <linux/clk.h>
 
 18#include <linux/clockchips.h>
 19#include <linux/of_address.h>
 20#include <linux/of_irq.h>
 21#include <linux/timecounter.h>
 22#include <asm/cpuinfo.h>
 23
 24static void __iomem *timer_baseaddr;
 
 
 
 
 
 
 
 
 
 
 25
 26static unsigned int freq_div_hz;
 27static unsigned int timer_clock_freq;
 28
 29#define TCSR0	(0x00)
 30#define TLR0	(0x04)
 31#define TCR0	(0x08)
 32#define TCSR1	(0x10)
 33#define TLR1	(0x14)
 34#define TCR1	(0x18)
 35
 36#define TCSR_MDT	(1<<0)
 37#define TCSR_UDT	(1<<1)
 38#define TCSR_GENT	(1<<2)
 39#define TCSR_CAPT	(1<<3)
 40#define TCSR_ARHT	(1<<4)
 41#define TCSR_LOAD	(1<<5)
 42#define TCSR_ENIT	(1<<6)
 43#define TCSR_ENT	(1<<7)
 44#define TCSR_TINT	(1<<8)
 45#define TCSR_PWMA	(1<<9)
 46#define TCSR_ENALL	(1<<10)
 47
 48static unsigned int (*read_fn)(void __iomem *);
 49static void (*write_fn)(u32, void __iomem *);
 50
 51static void timer_write32(u32 val, void __iomem *addr)
 52{
 53	iowrite32(val, addr);
 54}
 55
 56static unsigned int timer_read32(void __iomem *addr)
 57{
 58	return ioread32(addr);
 59}
 60
 61static void timer_write32_be(u32 val, void __iomem *addr)
 62{
 63	iowrite32be(val, addr);
 64}
 65
 66static unsigned int timer_read32_be(void __iomem *addr)
 67{
 68	return ioread32be(addr);
 69}
 70
 71static inline void xilinx_timer0_stop(void)
 72{
 73	write_fn(read_fn(timer_baseaddr + TCSR0) & ~TCSR_ENT,
 74		 timer_baseaddr + TCSR0);
 75}
 76
 77static inline void xilinx_timer0_start_periodic(unsigned long load_val)
 78{
 79	if (!load_val)
 80		load_val = 1;
 81	/* loading value to timer reg */
 82	write_fn(load_val, timer_baseaddr + TLR0);
 83
 84	/* load the initial value */
 85	write_fn(TCSR_LOAD, timer_baseaddr + TCSR0);
 86
 87	/* see timer data sheet for detail
 88	 * !ENALL - don't enable 'em all
 89	 * !PWMA - disable pwm
 90	 * TINT - clear interrupt status
 91	 * ENT- enable timer itself
 92	 * ENIT - enable interrupt
 93	 * !LOAD - clear the bit to let go
 94	 * ARHT - auto reload
 95	 * !CAPT - no external trigger
 96	 * !GENT - no external signal
 97	 * UDT - set the timer as down counter
 98	 * !MDT0 - generate mode
 99	 */
100	write_fn(TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT,
101		 timer_baseaddr + TCSR0);
102}
103
104static inline void xilinx_timer0_start_oneshot(unsigned long load_val)
105{
106	if (!load_val)
107		load_val = 1;
108	/* loading value to timer reg */
109	write_fn(load_val, timer_baseaddr + TLR0);
110
111	/* load the initial value */
112	write_fn(TCSR_LOAD, timer_baseaddr + TCSR0);
113
114	write_fn(TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT,
115		 timer_baseaddr + TCSR0);
116}
117
118static int xilinx_timer_set_next_event(unsigned long delta,
119					struct clock_event_device *dev)
120{
121	pr_debug("%s: next event, delta %x\n", __func__, (u32)delta);
122	xilinx_timer0_start_oneshot(delta);
123	return 0;
124}
125
126static int xilinx_timer_shutdown(struct clock_event_device *evt)
 
127{
128	pr_info("%s\n", __func__);
129	xilinx_timer0_stop();
130	return 0;
131}
132
133static int xilinx_timer_set_periodic(struct clock_event_device *evt)
134{
135	pr_info("%s\n", __func__);
136	xilinx_timer0_start_periodic(freq_div_hz);
137	return 0;
 
 
 
 
 
 
 
 
 
138}
139
140static struct clock_event_device clockevent_xilinx_timer = {
141	.name			= "xilinx_clockevent",
142	.features		= CLOCK_EVT_FEAT_ONESHOT |
143				  CLOCK_EVT_FEAT_PERIODIC,
144	.shift			= 8,
145	.rating			= 300,
146	.set_next_event		= xilinx_timer_set_next_event,
147	.set_state_shutdown	= xilinx_timer_shutdown,
148	.set_state_periodic	= xilinx_timer_set_periodic,
149};
150
151static inline void timer_ack(void)
152{
153	write_fn(read_fn(timer_baseaddr + TCSR0), timer_baseaddr + TCSR0);
154}
155
156static irqreturn_t timer_interrupt(int irq, void *dev_id)
157{
158	struct clock_event_device *evt = &clockevent_xilinx_timer;
159#ifdef CONFIG_HEART_BEAT
160	microblaze_heartbeat();
161#endif
162	timer_ack();
163	evt->event_handler(evt);
164	return IRQ_HANDLED;
165}
166
167static struct irqaction timer_irqaction = {
168	.handler = timer_interrupt,
169	.flags = IRQF_TIMER,
170	.name = "timer",
171	.dev_id = &clockevent_xilinx_timer,
172};
173
174static __init int xilinx_clockevent_init(void)
175{
176	clockevent_xilinx_timer.mult =
177		div_sc(timer_clock_freq, NSEC_PER_SEC,
178				clockevent_xilinx_timer.shift);
179	clockevent_xilinx_timer.max_delta_ns =
180		clockevent_delta2ns((u32)~0, &clockevent_xilinx_timer);
181	clockevent_xilinx_timer.max_delta_ticks = (u32)~0;
182	clockevent_xilinx_timer.min_delta_ns =
183		clockevent_delta2ns(1, &clockevent_xilinx_timer);
184	clockevent_xilinx_timer.min_delta_ticks = 1;
185	clockevent_xilinx_timer.cpumask = cpumask_of(0);
186	clockevents_register_device(&clockevent_xilinx_timer);
187
188	return 0;
189}
190
191static u64 xilinx_clock_read(void)
192{
193	return read_fn(timer_baseaddr + TCR1);
194}
195
196static u64 xilinx_read(struct clocksource *cs)
197{
198	/* reading actual value of timer 1 */
199	return (u64)xilinx_clock_read();
200}
201
202static struct timecounter xilinx_tc = {
203	.cc = NULL,
204};
205
206static u64 xilinx_cc_read(const struct cyclecounter *cc)
207{
208	return xilinx_read(NULL);
209}
210
211static struct cyclecounter xilinx_cc = {
212	.read = xilinx_cc_read,
213	.mask = CLOCKSOURCE_MASK(32),
214	.shift = 8,
215};
216
217static int __init init_xilinx_timecounter(void)
218{
219	xilinx_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC,
220				xilinx_cc.shift);
221
222	timecounter_init(&xilinx_tc, &xilinx_cc, sched_clock());
223
224	return 0;
225}
226
227static struct clocksource clocksource_microblaze = {
228	.name		= "xilinx_clocksource",
229	.rating		= 300,
230	.read		= xilinx_read,
231	.mask		= CLOCKSOURCE_MASK(32),
232	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
233};
234
235static int __init xilinx_clocksource_init(void)
236{
237	int ret;
238
239	ret = clocksource_register_hz(&clocksource_microblaze,
240				      timer_clock_freq);
241	if (ret) {
242		pr_err("failed to register clocksource");
243		return ret;
244	}
245
246	/* stop timer1 */
247	write_fn(read_fn(timer_baseaddr + TCSR1) & ~TCSR_ENT,
248		 timer_baseaddr + TCSR1);
249	/* start timer1 - up counting without interrupt */
250	write_fn(TCSR_TINT|TCSR_ENT|TCSR_ARHT, timer_baseaddr + TCSR1);
251
252	/* register timecounter - for ftrace support */
253	return init_xilinx_timecounter();
 
254}
255
256static int __init xilinx_timer_init(struct device_node *timer)
 
 
 
 
 
 
257{
258	struct clk *clk;
259	static int initialized;
260	u32 irq;
261	u32 timer_num = 1;
262	int ret;
263
264	if (initialized)
265		return -EINVAL;
266
267	initialized = 1;
268
269	timer_baseaddr = of_iomap(timer, 0);
270	if (!timer_baseaddr) {
271		pr_err("ERROR: invalid timer base address\n");
272		return -ENXIO;
273	}
274
275	write_fn = timer_write32;
276	read_fn = timer_read32;
277
278	write_fn(TCSR_MDT, timer_baseaddr + TCSR0);
279	if (!(read_fn(timer_baseaddr + TCSR0) & TCSR_MDT)) {
280		write_fn = timer_write32_be;
281		read_fn = timer_read32_be;
282	}
283
 
 
284	irq = irq_of_parse_and_map(timer, 0);
285	if (irq <= 0) {
286		pr_err("Failed to parse and map irq");
287		return -EINVAL;
288	}
289
290	of_property_read_u32(timer, "xlnx,one-timer-only", &timer_num);
291	if (timer_num) {
292		pr_err("Please enable two timers in HW\n");
293		return -EINVAL;
294	}
295
296	pr_info("%pOF: irq=%d\n", timer, irq);
297
298	clk = of_clk_get(timer, 0);
299	if (IS_ERR(clk)) {
300		pr_err("ERROR: timer CCF input clock not found\n");
301		/* If there is clock-frequency property than use it */
302		of_property_read_u32(timer, "clock-frequency",
303				    &timer_clock_freq);
304	} else {
305		timer_clock_freq = clk_get_rate(clk);
306	}
307
308	if (!timer_clock_freq) {
309		pr_err("ERROR: Using CPU clock frequency\n");
 
 
 
310		timer_clock_freq = cpuinfo.cpu_clock_freq;
311	}
312
313	freq_div_hz = timer_clock_freq / HZ;
314
315	ret = setup_irq(irq, &timer_irqaction);
316	if (ret) {
317		pr_err("Failed to setup IRQ");
318		return ret;
319	}
320
321#ifdef CONFIG_HEART_BEAT
322	microblaze_setup_heartbeat();
323#endif
 
 
 
 
324
325	ret = xilinx_clocksource_init();
326	if (ret)
327		return ret;
328
329	ret = xilinx_clockevent_init();
330	if (ret)
331		return ret;
332
333	sched_clock_register(xilinx_clock_read, 32, timer_clock_freq);
334
 
 
 
335	return 0;
336}
337
338TIMER_OF_DECLARE(xilinx_timer, "xlnx,xps-timer-1.00.a",
339		       xilinx_timer_init);
v3.5.6
  1/*
  2 * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
 
  3 * Copyright (C) 2007-2009 PetaLogix
  4 * Copyright (C) 2006 Atmark Techno, Inc.
  5 *
  6 * This file is subject to the terms and conditions of the GNU General Public
  7 * License. See the file "COPYING" in the main directory of this archive
  8 * for more details.
  9 */
 10
 11#include <linux/init.h>
 12#include <linux/kernel.h>
 13#include <linux/param.h>
 14#include <linux/interrupt.h>
 15#include <linux/profile.h>
 16#include <linux/irq.h>
 17#include <linux/delay.h>
 18#include <linux/sched.h>
 19#include <linux/spinlock.h>
 20#include <linux/err.h>
 21#include <linux/clk.h>
 22#include <linux/clocksource.h>
 23#include <linux/clockchips.h>
 24#include <linux/io.h>
 25#include <linux/bug.h>
 
 26#include <asm/cpuinfo.h>
 27#include <asm/setup.h>
 28#include <asm/prom.h>
 29#include <asm/irq.h>
 30#include <linux/cnt32_to_63.h>
 31
 32#ifdef CONFIG_SELFMOD_TIMER
 33#include <asm/selfmod.h>
 34#define TIMER_BASE	BARRIER_BASE_ADDR
 35#else
 36static unsigned int timer_baseaddr;
 37#define TIMER_BASE	timer_baseaddr
 38#endif
 39
 40static unsigned int freq_div_hz;
 41static unsigned int timer_clock_freq;
 42
 43#define TCSR0	(0x00)
 44#define TLR0	(0x04)
 45#define TCR0	(0x08)
 46#define TCSR1	(0x10)
 47#define TLR1	(0x14)
 48#define TCR1	(0x18)
 49
 50#define TCSR_MDT	(1<<0)
 51#define TCSR_UDT	(1<<1)
 52#define TCSR_GENT	(1<<2)
 53#define TCSR_CAPT	(1<<3)
 54#define TCSR_ARHT	(1<<4)
 55#define TCSR_LOAD	(1<<5)
 56#define TCSR_ENIT	(1<<6)
 57#define TCSR_ENT	(1<<7)
 58#define TCSR_TINT	(1<<8)
 59#define TCSR_PWMA	(1<<9)
 60#define TCSR_ENALL	(1<<10)
 61
 62static inline void microblaze_timer0_stop(void)
 
 
 
 
 
 
 
 
 
 
 
 
 
 63{
 64	out_be32(TIMER_BASE + TCSR0, in_be32(TIMER_BASE + TCSR0) & ~TCSR_ENT);
 65}
 66
 67static inline void microblaze_timer0_start_periodic(unsigned long load_val)
 
 
 
 
 
 
 
 
 
 
 
 68{
 69	if (!load_val)
 70		load_val = 1;
 71	out_be32(TIMER_BASE + TLR0, load_val); /* loading value to timer reg */
 
 72
 73	/* load the initial value */
 74	out_be32(TIMER_BASE + TCSR0, TCSR_LOAD);
 75
 76	/* see timer data sheet for detail
 77	 * !ENALL - don't enable 'em all
 78	 * !PWMA - disable pwm
 79	 * TINT - clear interrupt status
 80	 * ENT- enable timer itself
 81	 * ENIT - enable interrupt
 82	 * !LOAD - clear the bit to let go
 83	 * ARHT - auto reload
 84	 * !CAPT - no external trigger
 85	 * !GENT - no external signal
 86	 * UDT - set the timer as down counter
 87	 * !MDT0 - generate mode
 88	 */
 89	out_be32(TIMER_BASE + TCSR0,
 90			TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT);
 91}
 92
 93static inline void microblaze_timer0_start_oneshot(unsigned long load_val)
 94{
 95	if (!load_val)
 96		load_val = 1;
 97	out_be32(TIMER_BASE + TLR0, load_val); /* loading value to timer reg */
 
 98
 99	/* load the initial value */
100	out_be32(TIMER_BASE + TCSR0, TCSR_LOAD);
101
102	out_be32(TIMER_BASE + TCSR0,
103			TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT);
104}
105
106static int microblaze_timer_set_next_event(unsigned long delta,
107					struct clock_event_device *dev)
108{
109	pr_debug("%s: next event, delta %x\n", __func__, (u32)delta);
110	microblaze_timer0_start_oneshot(delta);
111	return 0;
112}
113
114static void microblaze_timer_set_mode(enum clock_event_mode mode,
115				struct clock_event_device *evt)
116{
117	switch (mode) {
118	case CLOCK_EVT_MODE_PERIODIC:
119		printk(KERN_INFO "%s: periodic\n", __func__);
120		microblaze_timer0_start_periodic(freq_div_hz);
121		break;
122	case CLOCK_EVT_MODE_ONESHOT:
123		printk(KERN_INFO "%s: oneshot\n", __func__);
124		break;
125	case CLOCK_EVT_MODE_UNUSED:
126		printk(KERN_INFO "%s: unused\n", __func__);
127		break;
128	case CLOCK_EVT_MODE_SHUTDOWN:
129		printk(KERN_INFO "%s: shutdown\n", __func__);
130		microblaze_timer0_stop();
131		break;
132	case CLOCK_EVT_MODE_RESUME:
133		printk(KERN_INFO "%s: resume\n", __func__);
134		break;
135	}
136}
137
138static struct clock_event_device clockevent_microblaze_timer = {
139	.name		= "microblaze_clockevent",
140	.features       = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
141	.shift		= 8,
142	.rating		= 300,
143	.set_next_event	= microblaze_timer_set_next_event,
144	.set_mode	= microblaze_timer_set_mode,
 
 
145};
146
147static inline void timer_ack(void)
148{
149	out_be32(TIMER_BASE + TCSR0, in_be32(TIMER_BASE + TCSR0));
150}
151
152static irqreturn_t timer_interrupt(int irq, void *dev_id)
153{
154	struct clock_event_device *evt = &clockevent_microblaze_timer;
155#ifdef CONFIG_HEART_BEAT
156	heartbeat();
157#endif
158	timer_ack();
159	evt->event_handler(evt);
160	return IRQ_HANDLED;
161}
162
163static struct irqaction timer_irqaction = {
164	.handler = timer_interrupt,
165	.flags = IRQF_DISABLED | IRQF_TIMER,
166	.name = "timer",
167	.dev_id = &clockevent_microblaze_timer,
168};
169
170static __init void microblaze_clockevent_init(void)
171{
172	clockevent_microblaze_timer.mult =
173		div_sc(timer_clock_freq, NSEC_PER_SEC,
174				clockevent_microblaze_timer.shift);
175	clockevent_microblaze_timer.max_delta_ns =
176		clockevent_delta2ns((u32)~0, &clockevent_microblaze_timer);
177	clockevent_microblaze_timer.min_delta_ns =
178		clockevent_delta2ns(1, &clockevent_microblaze_timer);
179	clockevent_microblaze_timer.cpumask = cpumask_of(0);
180	clockevents_register_device(&clockevent_microblaze_timer);
 
 
 
 
 
 
 
 
 
181}
182
183static cycle_t microblaze_read(struct clocksource *cs)
184{
185	/* reading actual value of timer 1 */
186	return (cycle_t) (in_be32(TIMER_BASE + TCR1));
187}
188
189static struct timecounter microblaze_tc = {
190	.cc = NULL,
191};
192
193static cycle_t microblaze_cc_read(const struct cyclecounter *cc)
194{
195	return microblaze_read(NULL);
196}
197
198static struct cyclecounter microblaze_cc = {
199	.read = microblaze_cc_read,
200	.mask = CLOCKSOURCE_MASK(32),
201	.shift = 8,
202};
203
204static int __init init_microblaze_timecounter(void)
205{
206	microblaze_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC,
207				microblaze_cc.shift);
208
209	timecounter_init(&microblaze_tc, &microblaze_cc, sched_clock());
210
211	return 0;
212}
213
214static struct clocksource clocksource_microblaze = {
215	.name		= "microblaze_clocksource",
216	.rating		= 300,
217	.read		= microblaze_read,
218	.mask		= CLOCKSOURCE_MASK(32),
219	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
220};
221
222static int __init microblaze_clocksource_init(void)
223{
224	if (clocksource_register_hz(&clocksource_microblaze, timer_clock_freq))
225		panic("failed to register clocksource");
 
 
 
 
 
 
226
227	/* stop timer1 */
228	out_be32(TIMER_BASE + TCSR1, in_be32(TIMER_BASE + TCSR1) & ~TCSR_ENT);
 
229	/* start timer1 - up counting without interrupt */
230	out_be32(TIMER_BASE + TCSR1, TCSR_TINT|TCSR_ENT|TCSR_ARHT);
231
232	/* register timecounter - for ftrace support */
233	init_microblaze_timecounter();
234	return 0;
235}
236
237/*
238 * We have to protect accesses before timer initialization
239 * and return 0 for sched_clock function below.
240 */
241static int timer_initialized;
242
243void __init time_init(void)
244{
 
 
245	u32 irq;
246	u32 timer_num = 1;
247	struct device_node *timer = NULL;
248	const void *prop;
249#ifdef CONFIG_SELFMOD_TIMER
250	unsigned int timer_baseaddr = 0;
251	int arr_func[] = {
252				(int)&microblaze_read,
253				(int)&timer_interrupt,
254				(int)&microblaze_clocksource_init,
255				(int)&microblaze_timer_set_mode,
256				(int)&microblaze_timer_set_next_event,
257				0
258			};
259#endif
260	timer = of_find_compatible_node(NULL, NULL, "xlnx,xps-timer-1.00.a");
261	BUG_ON(!timer);
 
 
 
 
 
 
262
263	timer_baseaddr = be32_to_cpup(of_get_property(timer, "reg", NULL));
264	timer_baseaddr = (unsigned long) ioremap(timer_baseaddr, PAGE_SIZE);
265	irq = irq_of_parse_and_map(timer, 0);
266	timer_num = be32_to_cpup(of_get_property(timer,
267						"xlnx,one-timer-only", NULL));
 
 
 
 
268	if (timer_num) {
269		printk(KERN_EMERG "Please enable two timers in HW\n");
270		BUG();
271	}
272
273#ifdef CONFIG_SELFMOD_TIMER
274	selfmod_function((int *) arr_func, timer_baseaddr);
275#endif
276	printk(KERN_INFO "%s #0 at 0x%08x, irq=%d\n",
277		timer->name, timer_baseaddr, irq);
 
 
 
 
 
 
278
279	/* If there is clock-frequency property than use it */
280	prop = of_get_property(timer, "clock-frequency", NULL);
281	if (prop)
282		timer_clock_freq = be32_to_cpup(prop);
283	else
284		timer_clock_freq = cpuinfo.cpu_clock_freq;
 
285
286	freq_div_hz = timer_clock_freq / HZ;
287
288	setup_irq(irq, &timer_irqaction);
 
 
 
 
 
289#ifdef CONFIG_HEART_BEAT
290	setup_heartbeat();
291#endif
292	microblaze_clocksource_init();
293	microblaze_clockevent_init();
294	timer_initialized = 1;
295}
296
297unsigned long long notrace sched_clock(void)
298{
299	if (timer_initialized) {
300		struct clocksource *cs = &clocksource_microblaze;
 
 
 
 
 
301
302		cycle_t cyc = cnt32_to_63(cs->read(NULL)) & LLONG_MAX;
303		return clocksource_cyc2ns(cyc, cs->mult, cs->shift);
304	}
305	return 0;
306}