sifive_clint.c 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  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. int riscv_get_time(u64 *time)
  24. {
  25. *time = readq((void __iomem *)MTIME_REG(gd->arch.clint));
  26. return 0;
  27. }
  28. int riscv_set_timecmp(int hart, u64 cmp)
  29. {
  30. writeq(cmp, (void __iomem *)MTIMECMP_REG(gd->arch.clint, hart));
  31. return 0;
  32. }
  33. int riscv_init_ipi(void)
  34. {
  35. long *ret = syscon_get_first_range(RISCV_SYSCON_CLINT);
  36. if (IS_ERR(ret))
  37. return PTR_ERR(ret);
  38. gd->arch.clint = ret;
  39. return 0;
  40. }
  41. int riscv_send_ipi(int hart)
  42. {
  43. writel(1, (void __iomem *)MSIP_REG(gd->arch.clint, hart));
  44. return 0;
  45. }
  46. int riscv_clear_ipi(int hart)
  47. {
  48. writel(0, (void __iomem *)MSIP_REG(gd->arch.clint, hart));
  49. return 0;
  50. }
  51. int riscv_get_ipi(int hart, int *pending)
  52. {
  53. *pending = readl((void __iomem *)MSIP_REG(gd->arch.clint, hart));
  54. return 0;
  55. }
  56. static const struct udevice_id sifive_clint_ids[] = {
  57. { .compatible = "riscv,clint0", .data = RISCV_SYSCON_CLINT },
  58. { }
  59. };
  60. U_BOOT_DRIVER(sifive_clint) = {
  61. .name = "sifive_clint",
  62. .id = UCLASS_SYSCON,
  63. .of_match = sifive_clint_ids,
  64. .flags = DM_FLAG_PRE_RELOC,
  65. };