armv7m_systick.c 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /*
  2. * Copyright (C) Maxime Coquelin 2015
  3. * Author: Maxime Coquelin <mcoquelin.stm32@gmail.com>
  4. * License terms: GNU General Public License (GPL), version 2
  5. */
  6. #include <linux/kernel.h>
  7. #include <linux/clocksource.h>
  8. #include <linux/clockchips.h>
  9. #include <linux/of.h>
  10. #include <linux/of_address.h>
  11. #include <linux/clk.h>
  12. #include <linux/bitops.h>
  13. #define SYST_CSR 0x00
  14. #define SYST_RVR 0x04
  15. #define SYST_CVR 0x08
  16. #define SYST_CALIB 0x0c
  17. #define SYST_CSR_ENABLE BIT(0)
  18. #define SYSTICK_LOAD_RELOAD_MASK 0x00FFFFFF
  19. static void __init system_timer_of_register(struct device_node *np)
  20. {
  21. struct clk *clk = NULL;
  22. void __iomem *base;
  23. u32 rate;
  24. int ret;
  25. base = of_iomap(np, 0);
  26. if (!base) {
  27. pr_warn("system-timer: invalid base address\n");
  28. return;
  29. }
  30. ret = of_property_read_u32(np, "clock-frequency", &rate);
  31. if (ret) {
  32. clk = of_clk_get(np, 0);
  33. if (IS_ERR(clk))
  34. goto out_unmap;
  35. ret = clk_prepare_enable(clk);
  36. if (ret)
  37. goto out_clk_put;
  38. rate = clk_get_rate(clk);
  39. if (!rate)
  40. goto out_clk_disable;
  41. }
  42. writel_relaxed(SYSTICK_LOAD_RELOAD_MASK, base + SYST_RVR);
  43. writel_relaxed(SYST_CSR_ENABLE, base + SYST_CSR);
  44. ret = clocksource_mmio_init(base + SYST_CVR, "arm_system_timer", rate,
  45. 200, 24, clocksource_mmio_readl_down);
  46. if (ret) {
  47. pr_err("failed to init clocksource (%d)\n", ret);
  48. if (clk)
  49. goto out_clk_disable;
  50. else
  51. goto out_unmap;
  52. }
  53. pr_info("ARM System timer initialized as clocksource\n");
  54. return;
  55. out_clk_disable:
  56. clk_disable_unprepare(clk);
  57. out_clk_put:
  58. clk_put(clk);
  59. out_unmap:
  60. iounmap(base);
  61. pr_warn("ARM System timer register failed (%d)\n", ret);
  62. }
  63. CLOCKSOURCE_OF_DECLARE(arm_systick, "arm,armv7m-systick",
  64. system_timer_of_register);