sifive_clint.c 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
  4. *
  5. * U-Boot syscon driver for SiFive's Core Local Interruptor (CLINT).
  6. * The CLINT block holds memory-mapped control and status registers
  7. * associated with software and timer interrupts.
  8. */
  9. #include <common.h>
  10. #include <dm.h>
  11. #include <regmap.h>
  12. #include <syscon.h>
  13. #include <asm/io.h>
  14. #include <asm/syscon.h>
  15. #include <linux/err.h>
  16. /* MSIP registers */
  17. #define MSIP_REG(base, hart) ((ulong)(base) + (hart) * 4)
  18. /* mtime compare register */
  19. #define MTIMECMP_REG(base, hart) ((ulong)(base) + 0x4000 + (hart) * 8)
  20. /* mtime register */
  21. #define MTIME_REG(base) ((ulong)(base) + 0xbff8)
  22. DECLARE_GLOBAL_DATA_PTR;
  23. #define CLINT_BASE_GET(void) \
  24. do { \
  25. long *ret; \
  26. \
  27. if (!gd->arch.clint) { \
  28. ret = syscon_get_first_range(RISCV_SYSCON_CLINT); \
  29. if (IS_ERR(ret)) \
  30. return PTR_ERR(ret); \
  31. gd->arch.clint = ret; \
  32. } \
  33. } while (0)
  34. int riscv_get_time(u64 *time)
  35. {
  36. CLINT_BASE_GET();
  37. *time = readq((void __iomem *)MTIME_REG(gd->arch.clint));
  38. return 0;
  39. }
  40. int riscv_set_timecmp(int hart, u64 cmp)
  41. {
  42. CLINT_BASE_GET();
  43. writeq(cmp, (void __iomem *)MTIMECMP_REG(gd->arch.clint, hart));
  44. return 0;
  45. }
  46. int riscv_send_ipi(int hart)
  47. {
  48. CLINT_BASE_GET();
  49. writel(1, (void __iomem *)MSIP_REG(gd->arch.clint, hart));
  50. return 0;
  51. }
  52. int riscv_clear_ipi(int hart)
  53. {
  54. CLINT_BASE_GET();
  55. writel(0, (void __iomem *)MSIP_REG(gd->arch.clint, hart));
  56. return 0;
  57. }
  58. int riscv_get_ipi(int hart, int *pending)
  59. {
  60. CLINT_BASE_GET();
  61. *pending = readl((void __iomem *)MSIP_REG(gd->arch.clint, hart));
  62. return 0;
  63. }
  64. static const struct udevice_id sifive_clint_ids[] = {
  65. { .compatible = "riscv,clint0", .data = RISCV_SYSCON_CLINT },
  66. { }
  67. };
  68. U_BOOT_DRIVER(sifive_clint) = {
  69. .name = "sifive_clint",
  70. .id = UCLASS_SYSCON,
  71. .of_match = sifive_clint_ids,
  72. .flags = DM_FLAG_PRE_RELOC,
  73. };