pit.c 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /***************************************************************************/
  2. /*
  3. * pit.c -- Motorola ColdFire PIT timer. Currently this type of
  4. * hardware timer only exists in the Motorola ColdFire
  5. * 5270/5271 and 5282 CPUs.
  6. *
  7. * Copyright (C) 1999-2004, Greg Ungerer (gerg@snapgear.com)
  8. * Copyright (C) 2001-2004, SnapGear Inc. (www.snapgear.com)
  9. *
  10. */
  11. /***************************************************************************/
  12. #include <linux/config.h>
  13. #include <linux/kernel.h>
  14. #include <linux/sched.h>
  15. #include <linux/param.h>
  16. #include <linux/init.h>
  17. #include <linux/interrupt.h>
  18. #include <asm/irq.h>
  19. #include <asm/coldfire.h>
  20. #include <asm/mcfpit.h>
  21. #include <asm/mcfsim.h>
  22. /***************************************************************************/
  23. void coldfire_pit_tick(void)
  24. {
  25. volatile struct mcfpit *tp;
  26. /* Reset the ColdFire timer */
  27. tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1);
  28. tp->pcsr |= MCFPIT_PCSR_PIF;
  29. }
  30. /***************************************************************************/
  31. void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *))
  32. {
  33. volatile unsigned char *icrp;
  34. volatile unsigned long *imrp;
  35. volatile struct mcfpit *tp;
  36. request_irq(MCFINT_VECBASE + MCFINT_PIT1, handler, SA_INTERRUPT,
  37. "ColdFire Timer", NULL);
  38. icrp = (volatile unsigned char *) (MCF_IPSBAR + MCFICM_INTC0 +
  39. MCFINTC_ICR0 + MCFINT_PIT1);
  40. *icrp = 0x2b; /* PIT1 with level 5, priority 3 */
  41. imrp = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH);
  42. *imrp &= ~(1 << (MCFINT_PIT1 - 32));
  43. /* Set up PIT timer 1 as poll clock */
  44. tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1);
  45. tp->pcsr = MCFPIT_PCSR_DISABLE;
  46. tp->pmr = ((MCF_CLK / 2) / 64) / HZ;
  47. tp->pcsr = MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | MCFPIT_PCSR_OVW |
  48. MCFPIT_PCSR_RLD | MCFPIT_PCSR_CLK64;
  49. }
  50. /***************************************************************************/
  51. unsigned long coldfire_pit_offset(void)
  52. {
  53. volatile struct mcfpit *tp;
  54. volatile unsigned long *ipr;
  55. unsigned long pmr, pcntr, offset;
  56. tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1);
  57. ipr = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IPRH);
  58. pmr = *(&tp->pmr);
  59. pcntr = *(&tp->pcntr);
  60. /*
  61. * If we are still in the first half of the upcount and a
  62. * timer interupt is pending, then add on a ticks worth of time.
  63. */
  64. offset = ((pmr - pcntr) * (1000000 / HZ)) / pmr;
  65. if ((offset < (1000000 / HZ / 2)) && (*ipr & (1 << (MCFINT_PIT1 - 32))))
  66. offset += 1000000 / HZ;
  67. return offset;
  68. }
  69. /***************************************************************************/