numachip.c 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. *
  4. * Copyright (C) 2015 Numascale AS. All rights reserved.
  5. */
  6. #include <linux/clockchips.h>
  7. #include <asm/irq.h>
  8. #include <asm/numachip/numachip.h>
  9. #include <asm/numachip/numachip_csr.h>
  10. static DEFINE_PER_CPU(struct clock_event_device, numachip2_ced);
  11. static cycles_t numachip2_timer_read(struct clocksource *cs)
  12. {
  13. return numachip2_read64_lcsr(NUMACHIP2_TIMER_NOW);
  14. }
  15. static struct clocksource numachip2_clocksource = {
  16. .name = "numachip2",
  17. .rating = 295,
  18. .read = numachip2_timer_read,
  19. .mask = CLOCKSOURCE_MASK(64),
  20. .flags = CLOCK_SOURCE_IS_CONTINUOUS,
  21. .mult = 1,
  22. .shift = 0,
  23. };
  24. static int numachip2_set_next_event(unsigned long delta, struct clock_event_device *ced)
  25. {
  26. numachip2_write64_lcsr(NUMACHIP2_TIMER_DEADLINE + numachip2_timer(),
  27. delta);
  28. return 0;
  29. }
  30. static const struct clock_event_device numachip2_clockevent __initconst = {
  31. .name = "numachip2",
  32. .rating = 400,
  33. .set_next_event = numachip2_set_next_event,
  34. .features = CLOCK_EVT_FEAT_ONESHOT,
  35. .mult = 1,
  36. .shift = 0,
  37. .min_delta_ns = 1250,
  38. .min_delta_ticks = 1250,
  39. .max_delta_ns = LONG_MAX,
  40. .max_delta_ticks = LONG_MAX,
  41. };
  42. static void numachip_timer_interrupt(void)
  43. {
  44. struct clock_event_device *ced = this_cpu_ptr(&numachip2_ced);
  45. ced->event_handler(ced);
  46. }
  47. static __init void numachip_timer_each(struct work_struct *work)
  48. {
  49. unsigned local_apicid = __this_cpu_read(x86_cpu_to_apicid) & 0xff;
  50. struct clock_event_device *ced = this_cpu_ptr(&numachip2_ced);
  51. /* Setup IPI vector to local core and relative timing mode */
  52. numachip2_write64_lcsr(NUMACHIP2_TIMER_INT + numachip2_timer(),
  53. (3 << 22) | (X86_PLATFORM_IPI_VECTOR << 14) |
  54. (local_apicid << 6));
  55. *ced = numachip2_clockevent;
  56. ced->cpumask = cpumask_of(smp_processor_id());
  57. clockevents_register_device(ced);
  58. }
  59. static int __init numachip_timer_init(void)
  60. {
  61. if (numachip_system != 2)
  62. return -ENODEV;
  63. /* Reset timer */
  64. numachip2_write64_lcsr(NUMACHIP2_TIMER_RESET, 0);
  65. clocksource_register_hz(&numachip2_clocksource, NSEC_PER_SEC);
  66. /* Setup per-cpu clockevents */
  67. x86_platform_ipi_callback = numachip_timer_interrupt;
  68. schedule_on_each_cpu(&numachip_timer_each);
  69. return 0;
  70. }
  71. arch_initcall(numachip_timer_init);