time.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. * linux/arch/arm/mach-w90x900/time.c
  3. *
  4. * Based on linux/arch/arm/plat-s3c24xx/time.c by Ben Dooks
  5. *
  6. * Copyright (c) 2009 Nuvoton technology corporation
  7. * All rights reserved.
  8. *
  9. * Wan ZongShun <mcuos.com@gmail.com>
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. */
  17. #include <linux/kernel.h>
  18. #include <linux/sched.h>
  19. #include <linux/init.h>
  20. #include <linux/interrupt.h>
  21. #include <linux/err.h>
  22. #include <linux/clk.h>
  23. #include <linux/io.h>
  24. #include <linux/leds.h>
  25. #include <linux/clocksource.h>
  26. #include <linux/clockchips.h>
  27. #include <asm/mach-types.h>
  28. #include <asm/mach/irq.h>
  29. #include <asm/mach/time.h>
  30. #include <mach/map.h>
  31. #include <mach/regs-timer.h>
  32. #define RESETINT 0x1f
  33. #define PERIOD (0x01 << 27)
  34. #define ONESHOT (0x00 << 27)
  35. #define COUNTEN (0x01 << 30)
  36. #define INTEN (0x01 << 29)
  37. #define TICKS_PER_SEC 100
  38. #define PRESCALE 0x63 /* Divider = prescale + 1 */
  39. unsigned int timer0_load;
  40. static void nuc900_clockevent_setmode(enum clock_event_mode mode,
  41. struct clock_event_device *clk)
  42. {
  43. unsigned int val;
  44. val = __raw_readl(REG_TCSR0);
  45. val &= ~(0x03 << 27);
  46. switch (mode) {
  47. case CLOCK_EVT_MODE_PERIODIC:
  48. __raw_writel(timer0_load, REG_TICR0);
  49. val |= (PERIOD | COUNTEN | INTEN | PRESCALE);
  50. break;
  51. case CLOCK_EVT_MODE_ONESHOT:
  52. val |= (ONESHOT | COUNTEN | INTEN | PRESCALE);
  53. break;
  54. case CLOCK_EVT_MODE_UNUSED:
  55. case CLOCK_EVT_MODE_SHUTDOWN:
  56. case CLOCK_EVT_MODE_RESUME:
  57. break;
  58. }
  59. __raw_writel(val, REG_TCSR0);
  60. }
  61. static int nuc900_clockevent_setnextevent(unsigned long evt,
  62. struct clock_event_device *clk)
  63. {
  64. unsigned int val;
  65. __raw_writel(evt, REG_TICR0);
  66. val = __raw_readl(REG_TCSR0);
  67. val |= (COUNTEN | INTEN | PRESCALE);
  68. __raw_writel(val, REG_TCSR0);
  69. return 0;
  70. }
  71. static struct clock_event_device nuc900_clockevent_device = {
  72. .name = "nuc900-timer0",
  73. .shift = 32,
  74. .features = CLOCK_EVT_MODE_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
  75. .set_mode = nuc900_clockevent_setmode,
  76. .set_next_event = nuc900_clockevent_setnextevent,
  77. .rating = 300,
  78. };
  79. /*IRQ handler for the timer*/
  80. static irqreturn_t nuc900_timer0_interrupt(int irq, void *dev_id)
  81. {
  82. struct clock_event_device *evt = &nuc900_clockevent_device;
  83. __raw_writel(0x01, REG_TISR); /* clear TIF0 */
  84. evt->event_handler(evt);
  85. return IRQ_HANDLED;
  86. }
  87. static struct irqaction nuc900_timer0_irq = {
  88. .name = "nuc900-timer0",
  89. .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
  90. .handler = nuc900_timer0_interrupt,
  91. };
  92. static void __init nuc900_clockevents_init(unsigned int rate)
  93. {
  94. nuc900_clockevent_device.mult = div_sc(rate, NSEC_PER_SEC,
  95. nuc900_clockevent_device.shift);
  96. nuc900_clockevent_device.max_delta_ns = clockevent_delta2ns(0xffffffff,
  97. &nuc900_clockevent_device);
  98. nuc900_clockevent_device.min_delta_ns = clockevent_delta2ns(0xf,
  99. &nuc900_clockevent_device);
  100. nuc900_clockevent_device.cpumask = cpumask_of(0);
  101. clockevents_register_device(&nuc900_clockevent_device);
  102. }
  103. static cycle_t nuc900_get_cycles(struct clocksource *cs)
  104. {
  105. return ~__raw_readl(REG_TDR1);
  106. }
  107. static struct clocksource clocksource_nuc900 = {
  108. .name = "nuc900-timer1",
  109. .rating = 200,
  110. .read = nuc900_get_cycles,
  111. .mask = CLOCKSOURCE_MASK(32),
  112. .shift = 20,
  113. .flags = CLOCK_SOURCE_IS_CONTINUOUS,
  114. };
  115. static void __init nuc900_clocksource_init(unsigned int rate)
  116. {
  117. unsigned int val;
  118. __raw_writel(0xffffffff, REG_TICR1);
  119. val = __raw_readl(REG_TCSR1);
  120. val |= (COUNTEN | PERIOD);
  121. __raw_writel(val, REG_TCSR1);
  122. clocksource_nuc900.mult =
  123. clocksource_khz2mult((rate / 1000), clocksource_nuc900.shift);
  124. clocksource_register(&clocksource_nuc900);
  125. }
  126. static void __init nuc900_timer_init(void)
  127. {
  128. struct clk *ck_ext = clk_get(NULL, "ext");
  129. unsigned int rate;
  130. BUG_ON(IS_ERR(ck_ext));
  131. rate = clk_get_rate(ck_ext);
  132. clk_put(ck_ext);
  133. rate = rate / (PRESCALE + 0x01);
  134. /* set a known state */
  135. __raw_writel(0x00, REG_TCSR0);
  136. __raw_writel(0x00, REG_TCSR1);
  137. __raw_writel(RESETINT, REG_TISR);
  138. timer0_load = (rate / TICKS_PER_SEC);
  139. setup_irq(IRQ_TIMER0, &nuc900_timer0_irq);
  140. nuc900_clocksource_init(rate);
  141. nuc900_clockevents_init(rate);
  142. }
  143. struct sys_timer nuc900_timer = {
  144. .init = nuc900_timer_init,
  145. };