blob: b98db0d0975516fc9fd7604c5e624db764cc11ba [file] [log] [blame]
yuezonghe824eb0c2024-06-27 02:32:26 -07001/*
2 * drivers/clocksource/zx29_timer.c
3 *
4 * Copyright (C) 2015 ZTE-TSP
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/kernel.h>
18#include <linux/interrupt.h>
19#include <linux/irq.h>
20#include <linux/clockchips.h>
21#include <linux/clk.h>
22#include <linux/module.h>
23#include <linux/err.h>
24#include <linux/syscore_ops.h>
25
26#include <asm/mach/time.h>
27
28#include <mach/board.h>
29#include <mach/iomap.h>
30#include <mach/debug.h>
31#include <mach/irqs.h>
32#include <mach/timex.h>
33#include <mach/pcu.h>
34
35#if NEW_LINUX_FRAME
36#include <linux/sched_clock.h>
37#else
38#include <asm/sched_clock.h>
39#endif
40#include <linux/fs.h>
41#include <linux/proc_fs.h>
42#include <linux/seq_file.h>
43
44#define DEBUG_SYS_TIMER 0
45
46#if DEBUG_SYS_TIMER
47#pragma GCC optimize("O0")
48
49typedef struct
50{
51 unsigned int trace_t;
52 unsigned int count_reg;
53 unsigned int load_reg;
54 unsigned int refresh_reg;
55 unsigned int time_t;
56}test_trace;
57
58volatile test_trace oneshot_count_view[1000];
59volatile unsigned int oneshot_count_index=0;
60
61volatile unsigned int timer_int_stamp[1000];
62volatile unsigned int timer_int_index=0;
63#endif
64
65const char *__clk_get_name(struct clk *clk);
66
67static struct clock_event_device timer_clkevt;
68
69volatile static unsigned int sys_time_cnt=0;
70volatile static unsigned int periodic_count_value=0;
71volatile static unsigned int sys_time_count_value=0;
72volatile static unsigned int event_cycle=0; /*it is for translating presistent time*/
73
74static struct clk *cs_wclk = NULL;
75static struct clk *cs_pclk = NULL;
76static struct clk *ce_wclk = NULL;
77static struct clk *ce_pclk = NULL;
78static struct clk *cd_wclk = NULL;
79static struct clk *cd_pclk = NULL;
80
81/*
82 * this function can only just be used for debug
83 */
84unsigned int test_timer_read(void)
85{
86 sys_time_count_value=0x7fffffff-read_timer_clk(CLOCKSOURCE_BASE);
87 return sys_time_count_value;
88}
89EXPORT_SYMBOL(test_timer_read);
90
91static unsigned long zx29_read_current_timer(void)
92{
93 u32 elapsed=0;
94 u32 t=0;
95 t = ioread32(CLOCKDELAY_BASE+CUR_VALUE);
96 elapsed=0x7fffffff-t;
97 return elapsed;
98}
99
100/*
101 * udelay.
102 */
103void udelay(u32 delay_us)
104{
105 u64 start_us = zx29_read_current_timer();
106 s64 remain_us = 0;
107
108 while(1)
109 {
110 remain_us = zx29_read_current_timer() - start_us;
111 if(remain_us < 0)
112 {
113 remain_us += 0x7fffffff;
114 }
115
116 remain_us = div64_s64(remain_us*USEC_PER_SEC, (s64)DELAY_CLOCK_RATE);
117
118 if(remain_us >= (s64)delay_us)
119 return;
120 }
121}
122EXPORT_SYMBOL(udelay);
123
124/*
125 * IRQ handler for the timer.
126 */
127static irqreturn_t zx29_clock_event_isr(int irq, void *dev_id)
128{
129 WARN_ON_ONCE(!irqs_disabled());
130
131// pcu_int_clear(PCU_AP_TIMER0_INT);
132
133#if DEBUG_SYS_TIMER
134 //zx29_gpio1v8_output_data(16,(sys_time_cnt & 0x01)); /*light a led to test systimer*/
135 timer_int_stamp[timer_int_index]= test_timer_read();
136 timer_int_index++;
137 if(timer_int_index==1000)
138 timer_int_index=0;
139#endif
140
141 sys_time_cnt++;
142
143 timer_clkevt.event_handler(&timer_clkevt);
144
145 return IRQ_HANDLED;
146}
147
148void clock_event_handler(void)
149{
150 timer_clkevt.event_handler(&timer_clkevt);
151}
152
153
154/*
155 * Clockevent device: interrupts every 1/HZ
156 */
157static void zx29_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *dev)
158{
159 switch (mode) {
160 case CLOCK_EVT_MODE_PERIODIC:
161 timer_set_load(CLOCKEVENT_BASE, periodic_count_value-2);
162 timer_set_mode(CLOCKEVENT_BASE, true);
163 break;
164
165 case CLOCK_EVT_MODE_ONESHOT:
166 timer_set_mode(CLOCKEVENT_BASE, false);
167 break;
168
169 case CLOCK_EVT_MODE_SHUTDOWN:
170 case CLOCK_EVT_MODE_UNUSED:
171 case CLOCK_EVT_MODE_RESUME:
172 break;
173 }
174}
175
176/*
177 * only for oneshot mode
178 */
179static int zx29_timer_set_next_event(unsigned long cycles,
180 struct clock_event_device *evt)
181{
182 timer_set_load(CLOCKEVENT_BASE, cycles);
183
184#if DEBUG_SYS_TIMER
185 oneshot_count_view[oneshot_count_index].trace_t = cycles;
186 oneshot_count_view[oneshot_count_index].count_reg = ioread32(CLOCKEVENT_BASE+CUR_VALUE);
187 oneshot_count_view[oneshot_count_index].load_reg = ioread32(CLOCKEVENT_BASE+LOAD_REG);
188 oneshot_count_view[oneshot_count_index].refresh_reg = ioread32(CLOCKEVENT_BASE+REFRESH_REG);
189 oneshot_count_view[oneshot_count_index].time_t = test_timer_read();
190 oneshot_count_index++;
191 if(oneshot_count_index==1000)
192 oneshot_count_index=0;
193#endif
194
195 return 0;
196}
197
198static cycle_t zx29_read_timer_clk(struct clocksource *cs)
199{
200#ifdef CONFIG_ARCH_ZX297520V2FPGA
201 u32 t1=0,t2=0;
202
203 t1 = read_timer_clk(CLOCKSOURCE_BASE);
204 do
205 {
206 t2 = read_timer_clk(CLOCKSOURCE_BASE);
207 if(t1==t2) break;
208 t1=t2;
209 }while(1);
210
211 return 0x7fffffff-t1;
212#else
213 return (0x7fffffff-read_timer_clk(CLOCKSOURCE_BASE));
214#endif
215}
216
217static struct clk *pt_wclk = NULL;
218static struct clk *pt_pclk = NULL;
219
220#ifdef CONFIG_PM
221int zx29_clocksource_suspend(void)
222{
223 /*
224 *nothing should be done here.
225 *maybe clocksource should be stoped, but I don't do this
226 *there is no effect on system running, even if clocksource is not suspended actually.
227 *I can use clocksource in power off processing for debug.
228 */
229 return 0;
230}
231
232void zx29_clocksource_resume(void)
233{
234#if 0
235 /*re-initiate the clocksource*/
236 iowrite32(0x7fffffff,SOURCE_BASE_VA+LOAD_REG); // 2^31-1
237#ifdef CONFIG_ARCH_ZX297510FPGA
238 iowrite32(0x02,SOURCE_BASE_VA+CONFIG_REG); // auto load
239#else
240 iowrite32(0x22,SOURCE_BASE_VA+CONFIG_REG); // main clock/13/2 , auto load
241 refresh_config_load_reg(SOURCE_BASE_VA); // refresh load reg and config reg
242 iowrite32(0x1,SOURCE_BASE_VA+START_REG); // start timer
243#endif
244#endif
245}
246
247static struct syscore_ops zx29_clocksource_syscore_ops = {
248 .suspend = zx29_clocksource_suspend,
249 .resume = zx29_clocksource_resume,
250};
251
252/****************************************************************
253 *** wake timer & persistent timer **************************
254 ****************************************************************
255 */
256
257static struct clk *wt_wclk = NULL;
258static struct clk *wt_pclk = NULL;
259
260static irqreturn_t wake_timer_isr(int irq, void *dev_id)
261{
262 pcu_int_clear(PCU_WAKE_TIMER_INT);
263
264 return IRQ_HANDLED;
265}
266
267static struct irqaction wake_timer_irq = {
268 .name = "wake_timer",
269 .flags = IRQF_DISABLED|IRQF_TRIGGER_RISING|IRQF_NO_THREAD,
270 .handler = wake_timer_isr,
271};
272
273void zx29_set_wake_timer(unsigned long cycles)
274{
275 unsigned int t0;
276
277 timer_set_load(WAKE_TIMER_BASE, cycles);
278
279 /* wait data refresh finished. */
280 t0=test_timer_read();
281 while( (test_timer_read()-t0) < 4);
282
283 timer_start(WAKE_TIMER_BASE);
284}
285
286void zx29_stop_wake_timer(void)
287{
288 timer_stop(WAKE_TIMER_BASE);
289}
290#endif /*CONFIG_PM*/
291
292u64 read_persistent_us(void)
293{
294 unsigned int current_cycle1 = 0;
295 unsigned int current_cycle2 = 0;
296
297 current_cycle1 = read_timer_clk(PERSISTENT_TIMER_BASE);
298 do{
299 current_cycle2 = read_timer_clk(PERSISTENT_TIMER_BASE);
300 if (current_cycle1 == current_cycle2)
301 break;
302 current_cycle1 = current_cycle2;
303 }while(1);
304
305 return div64_u64((u64)((u64)0x7fffffff-current_cycle1)*USEC_PER_SEC, (u64)PERSISTENT_TIMER_CLOCK_RATE);
306}
307EXPORT_SYMBOL(read_persistent_us);
308
309static void __init zx29_pm_timer_resources_init(void)
310{
311#if SOURCE_CLK_PERSISTENT
312#else
313 pt_wclk = timer_get_clk(PERSISTENT_TIMER_NAME, "work_clk");
314 if (IS_ERR(pt_wclk))
315 panic("failed to get persistent wclk.");
316
317 pt_pclk = timer_get_clk(PERSISTENT_TIMER_NAME, "apb_clk");
318 if (IS_ERR(pt_pclk))
319 panic("failed to get persistent pclk.");
320 clk_prepare_enable(pt_pclk);
321#endif
322#ifdef CONFIG_PM
323 wt_wclk = timer_get_clk(WAKE_TIMER_NAME, "work_clk");
324 if (IS_ERR(wt_wclk))
325 panic("failed to get wake timer wclk.");
326
327 wt_pclk = timer_get_clk(WAKE_TIMER_NAME, "apb_clk");
328 if (IS_ERR(wt_pclk))
329 panic("failed to get wake timer pclk.");
330 clk_prepare_enable(wt_pclk);
331#endif
332}
333
334static void __init zx29_persistent_timer_init(void)
335{
336 clk_set_rate(pt_wclk, PERSISTENT_TIMER_CLOCK_RATE);
337 clk_prepare_enable(pt_wclk);
338 pr_info("pt_wclk=%lu, parent=%s \n", clk_get_rate(pt_wclk), __clk_get_name(clk_get_parent(pt_wclk)));
339
340 timer_set_load(PERSISTENT_TIMER_BASE, 0x7fffffff);
341 timer_set_mode(PERSISTENT_TIMER_BASE, true);
342 timer_start(PERSISTENT_TIMER_BASE);
343}
344
345static void __init zx29_wake_timer_init(void)
346{
347#ifdef CONFIG_PM
348
349 int ret = 0;
350
351 clk_set_rate(wt_wclk, WAKE_TIMER_CLOCK_RATE);
352 clk_prepare_enable(wt_wclk);
353 pr_info("wt_wclk=%lu, parent=%s \n", clk_get_rate(wt_wclk), __clk_get_name(clk_get_parent(wt_wclk)));
354
355 pcu_int_clear(PCU_WAKE_TIMER_INT);
356 ret=setup_irq(WAKE_TIMER_INT, &wake_timer_irq);
357 if(ret<0)
358 ZDRV_ASSERT(0);
359
360 timer_set_mode(WAKE_TIMER_BASE, false);
361 timer_stop(WAKE_TIMER_BASE);
362#endif
363}
364
365static void __init zx29_pm_timer_init(void)
366{
367 zx29_pm_timer_resources_init();
368#if SOURCE_CLK_PERSISTENT
369#else
370 zx29_persistent_timer_init();
371#endif
372#ifdef CONFIG_PM
373 zx29_wake_timer_init();
374#endif
375}
376
377/*
378 * read_persistent_clock - Return time from a persistent clock.
379 *
380 * Reads the time from a source which isn't disabled during PM, the
381 * 32k sync timer. Convert the cycles elapsed since last read into
382 * nsecs and adds to a monotonically increasing timespec.
383 *
384 * Generally, RTC is used to get this time,but in zx29 platform,
385 * precision of RTC is not enough, so I use a fix timer as persistent clock.
386 * Although the timer can not represent the natural time,
387 * but it doesn't matter, linux just needs a relative time.
388 */
389#if SOURCE_CLK_PERSISTENT
390static struct timespec persistent_ts;
391void read_persistent_clock(struct timespec *ts)
392{
393 u64 delta, persistent_us;
394 struct timespec *tsp = &persistent_ts;
395
396 persistent_us = read_persistent_us();
397
398 tsp->tv_sec = (long)div64_u64(persistent_us, USEC_PER_SEC);
399 delta = persistent_us- (u64)tsp->tv_sec*USEC_PER_SEC;
400 tsp->tv_nsec = (long)delta*1000L;
401
402 *ts = *tsp;
403}
404/*
405static struct timespec persistent_ts;
406static u64 persistent_us, last_persistent_us;
407
408void read_persistent_clock(struct timespec *ts)
409{
410 u64 delta;
411 struct timespec *tsp = &persistent_ts;
412
413 last_persistent_us = persistent_us;
414 persistent_us = read_persistent_us();
415 delta = persistent_us - last_persistent_us;
416
417 timespec_add_ns(tsp, delta * NSEC_PER_USEC);
418 *ts = *tsp;
419}
420*/
421#endif
422
423
424static struct clocksource timer_clksrc = {
425 .name = CLOCKSOURCE_NAME,
426 .rating = 300,
427 .read = zx29_read_timer_clk,
428 .mask = CLOCKSOURCE_MASK(31),
429 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
430};
431
432static struct clock_event_device timer_clkevt = {
433 .name = CLOCKEVENT_NAME,
434#ifdef CONFIG_ARCH_ZX297520V2FPGA
435 .features = CLOCK_EVT_FEAT_PERIODIC,
436#else
437 .features = CLOCK_EVT_FEAT_PERIODIC|CLOCK_EVT_FEAT_ONESHOT,
438#endif
439 .shift = 32,
440 .rating = 300,
441 .set_mode = zx29_timer_set_mode,
442 .set_next_event = zx29_timer_set_next_event,
443};
444
445#if NEW_LINUX_FRAME
446static notrace u64 zx29_sched_clock_read(void)
447{
448 return (u64)timer_clksrc.read(&timer_clksrc);
449}
450#else
451static notrace u32 zx29_sched_clock_read(void)
452{
453 return timer_clksrc.read(&timer_clksrc);
454}
455#endif
456
457static struct irqaction zx29_clock_event_irq =
458{
459 .name = "zx29_tick_irq",
460 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
461 .handler = zx29_clock_event_isr,
462 .dev_id = &timer_clkevt,
463};
464
465static void __init zx29_clockevent_init(void)
466{
467 int ret = 0;
468
469 clk_set_rate(ce_wclk, EVENT_CLOCK_RATE);
470 clk_prepare_enable(ce_wclk);
471 pr_info("ce_wclk=%lu, parent=%s \n", clk_get_rate(ce_wclk), __clk_get_name(clk_get_parent(ce_wclk)));
472
473 /* set count value */
474 periodic_count_value=(EVENT_CLOCK_RATE+HZ/2)/HZ;
475
476 /* Set up irq handler */
477 ret=setup_irq(CLOCKEVENT_INT, &zx29_clock_event_irq);
478 if(ret<0)
479 ZDRV_ASSERT(0);
480
481 /* Set up and register clockevents */
482 timer_clkevt.cpumask = cpumask_of(0);
483 clockevents_config_and_register(&timer_clkevt, EVENT_CLOCK_RATE, 50, 0x7fffffff);
484
485 timer_start(CLOCKEVENT_BASE);
486}
487
488#ifdef CONFIG_PROC_FS
489static int persistent_time_show(struct seq_file * m, void * v)
490{
491 u64 persistent_time;
492
493 persistent_time = read_persistent_us();
494 seq_printf(m, "%llu\n", persistent_time);
495 return 0;
496}
497
498static int persistent_time_open(struct inode *inode, struct file *file)
499{
500 return single_open(file, persistent_time_show, NULL);
501}
502
503static const struct file_operations persistent_clock_fops = {
504 .open = persistent_time_open,
505 .read = seq_read,
506 .llseek = seq_lseek,
507 .release = single_release,
508};
509
510void persistent_clock_procfs(void)
511{
512 struct proc_dir_entry *pde;
513 pde = proc_create("persistent_time", 0444, NULL, &persistent_clock_fops);
514}
515#endif
516
517static void __init zx29_clocksource_init(void)
518{
519 int ret = 0;
520
521#if defined(_USE_CAP_SYS) && !defined(CONFIG_ARCH_ZX297520V3_CAP) && !defined(CONFIG_SYSTEM_RECOVERY)
522#else
523 clk_set_rate(cs_wclk, SOURCE_CLOCK_RATE);
524 clk_prepare_enable(cs_wclk);
525 pr_info("cs_wclk=%lu, parent=%s \n", clk_get_rate(cs_wclk), __clk_get_name(clk_get_parent(cs_wclk)));
526
527 timer_set_load(CLOCKSOURCE_BASE, 0x7fffffff);
528 timer_set_mode(CLOCKSOURCE_BASE, true);
529 timer_start(CLOCKSOURCE_BASE);
530#endif
531
532 /* Register clocksource. */
533 ret = clocksource_register_hz(&timer_clksrc, SOURCE_CLOCK_RATE);
534/* if (ret){
535 printk(KERN_INFO"clocksource_register failed\n");
536 ZDRV_ASSERT(0);
537 }*/
538
539 /*register hardware time stamp*/
540#if NEW_LINUX_FRAME
541 sched_clock_register(zx29_sched_clock_read, 31, SOURCE_CLOCK_RATE);
542#else
543 setup_sched_clock(zx29_sched_clock_read, 31, SOURCE_CLOCK_RATE);
544#endif
545
546#ifdef CONFIG_PM
547 register_syscore_ops(&zx29_clocksource_syscore_ops);
548#endif
549#ifdef CONFIG_PROC_FS
550 persistent_clock_procfs();
551#endif
552}
553
554static void __init zx29_clockdelay_init(void)
555{
556
557 clk_set_rate(cd_wclk, DELAY_CLOCK_RATE);
558 clk_prepare_enable(cd_wclk);
559 pr_info("cd_wclk=%lu, parent=%s \n", clk_get_rate(cd_wclk), __clk_get_name(clk_get_parent(cd_wclk)));
560
561 timer_set_load(CLOCKDELAY_BASE, 0x7fffffff);
562 timer_set_mode(CLOCKDELAY_BASE, true);
563 timer_start(CLOCKDELAY_BASE);
564}
565
566static void __init zx29_timer_resources_init(void)
567{
568 cs_wclk = timer_get_clk(CLOCKSOURCE_NAME, "work_clk");
569 if (IS_ERR(cs_wclk))
570 panic("failed to get clocksource wclk.");
571
572 cs_pclk = timer_get_clk(CLOCKSOURCE_NAME, "apb_clk");
573 if (IS_ERR(cs_pclk))
574 panic("failed to get clocksource pclk.");
575 clk_prepare_enable(cs_pclk);
576
577 ce_wclk = timer_get_clk(CLOCKEVENT_NAME, "work_clk");
578 if (IS_ERR(ce_wclk))
579 panic("failed to get clockevent wclk.");
580
581 ce_pclk = timer_get_clk(CLOCKEVENT_NAME, "apb_clk");
582 if (IS_ERR(ce_pclk))
583 panic("failed to get clockevent pclk.");
584 clk_prepare_enable(ce_pclk);
585
586 cd_wclk = timer_get_clk(DELAY_TIMER_NAME, "work_clk");
587 if (IS_ERR(cd_wclk))
588 panic("failed to get clockdelay wclk.");
589
590 cd_pclk = timer_get_clk(DELAY_TIMER_NAME, "apb_clk");
591 if (IS_ERR(cd_pclk))
592 panic("failed to get clockdelay pclk.");
593 clk_prepare_enable(cd_pclk);
594}
595
596/*
597 * Set up both clocksource and clockevent support.
598 */
599void __init zx29_timer_init(void)
600{
601
602#if DEBUG_SYS_TIMER
603 //zx29_gpio1v8_function_sel(16,0); /*GPIO*/
604 //zx29_gpio1v8_set_direction(16,0); /*output*/
605#endif
606
607 zx29_timer_resources_init();
608 zx29_clockevent_init();
609 zx29_clocksource_init();
610 zx29_clockdelay_init();
611
612//#ifdef CONFIG_PM
613 zx29_pm_timer_init();
614//#endif
615
616 pr_info("zx297520v system timer initialized\n");
617}
618
619#if NEW_LINUX_FRAME
620#else
621struct sys_timer zx29_timer = {
622 .init = zx29_timer_init,
623};
624#endif
625
626#if 0
627extern void cpufreq_test(unsigned int old_index, unsigned int new_index);
628
629void test(void)
630{
631 unsigned int t1,t2,delay;
632 //set cpu rate(156/624)
633
634 cpufreq_test(0,2);//208
635 t1=zx29_read_current_timer();
636 udelay(800);
637 t2=zx29_read_current_timer();
638 delay = (t2-t1)/26;
639 printk("xxx 208M delay:%d us t1 = %d t2 = %d \n",delay,t1,t2);
640
641 cpufreq_test(2,1);//312
642 t1=zx29_read_current_timer();
643 udelay(800);
644 t2=zx29_read_current_timer();
645 delay = (t2-t1)/26;
646 printk("xxx 312M delay:%d us t1 = %d t2 = %d \n",delay,t1,t2);
647
648 cpufreq_test(1,0);//624
649 t1=zx29_read_current_timer();
650 udelay(800);
651 t2=zx29_read_current_timer();
652 delay = (t2-t1)/26;
653 printk("xxx 624M delay:%d us t1 = %d t2 = %d \n",delay,t1,t2);
654
655
656}
657#endif
658
659