time.c 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * linux/arch/arm/common/time-acorn.c
  4. *
  5. * Copyright (c) 1996-2000 Russell King.
  6. *
  7. * Changelog:
  8. * 24-Sep-1996 RMK Created
  9. * 10-Oct-1996 RMK Brought up to date with arch-sa110eval
  10. * 04-Dec-1997 RMK Updated for new arch/arm/time.c
  11. * 13=Jun-2004 DS Moved to arch/arm/common b/c shared w/CLPS7500
  12. */
  13. #include <linux/clocksource.h>
  14. #include <linux/init.h>
  15. #include <linux/interrupt.h>
  16. #include <linux/irq.h>
  17. #include <linux/io.h>
  18. #include <mach/hardware.h>
  19. #include <asm/hardware/ioc.h>
  20. #include <asm/mach/time.h>
  21. #define RPC_CLOCK_FREQ 2000000
  22. #define RPC_LATCH DIV_ROUND_CLOSEST(RPC_CLOCK_FREQ, HZ)
  23. static u32 ioc_time;
  24. static u64 ioc_timer_read(struct clocksource *cs)
  25. {
  26. unsigned int count1, count2, status;
  27. unsigned long flags;
  28. u32 ticks;
  29. local_irq_save(flags);
  30. ioc_writeb (0, IOC_T0LATCH);
  31. barrier ();
  32. count1 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
  33. barrier ();
  34. status = ioc_readb(IOC_IRQREQA);
  35. barrier ();
  36. ioc_writeb (0, IOC_T0LATCH);
  37. barrier ();
  38. count2 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
  39. ticks = ioc_time + RPC_LATCH - count2;
  40. local_irq_restore(flags);
  41. if (count2 < count1) {
  42. /*
  43. * The timer has not reloaded between reading count1 and
  44. * count2, check whether an interrupt was actually pending.
  45. */
  46. if (status & (1 << 5))
  47. ticks += RPC_LATCH;
  48. } else if (count2 > count1) {
  49. /*
  50. * The timer has reloaded, so count2 indicates the new
  51. * count since the wrap. The interrupt would not have
  52. * been processed, so add the missed ticks.
  53. */
  54. ticks += RPC_LATCH;
  55. }
  56. return ticks;
  57. }
  58. static struct clocksource ioctime_clocksource = {
  59. .read = ioc_timer_read,
  60. .mask = CLOCKSOURCE_MASK(32),
  61. .rating = 100,
  62. };
  63. void __init ioctime_init(void)
  64. {
  65. ioc_writeb(RPC_LATCH & 255, IOC_T0LTCHL);
  66. ioc_writeb(RPC_LATCH >> 8, IOC_T0LTCHH);
  67. ioc_writeb(0, IOC_T0GO);
  68. }
  69. static irqreturn_t
  70. ioc_timer_interrupt(int irq, void *dev_id)
  71. {
  72. ioc_time += RPC_LATCH;
  73. legacy_timer_tick(1);
  74. return IRQ_HANDLED;
  75. }
  76. /*
  77. * Set up timer interrupt.
  78. */
  79. void __init ioc_timer_init(void)
  80. {
  81. WARN_ON(clocksource_register_hz(&ioctime_clocksource, RPC_CLOCK_FREQ));
  82. ioctime_init();
  83. if (request_irq(IRQ_TIMER0, ioc_timer_interrupt, 0, "timer", NULL))
  84. pr_err("Failed to request irq %d (timer)\n", IRQ_TIMER0);
  85. }