sifive_clint.c 1.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2020, Sean Anderson <seanga2@gmail.com>
  4. * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
  5. *
  6. * U-Boot syscon driver for SiFive's Core Local Interruptor (CLINT).
  7. * The CLINT block holds memory-mapped control and status registers
  8. * associated with software and timer interrupts.
  9. */
  10. #include <common.h>
  11. #include <dm.h>
  12. #include <asm/io.h>
  13. #include <asm/smp.h>
  14. #include <linux/err.h>
  15. /* MSIP registers */
  16. #define MSIP_REG(base, hart) ((ulong)(base) + (hart) * 4)
  17. DECLARE_GLOBAL_DATA_PTR;
  18. int riscv_init_ipi(void)
  19. {
  20. int ret;
  21. struct udevice *dev;
  22. ret = uclass_get_device_by_driver(UCLASS_TIMER,
  23. DM_DRIVER_GET(sifive_clint), &dev);
  24. if (ret)
  25. return ret;
  26. gd->arch.clint = dev_read_addr_ptr(dev);
  27. if (!gd->arch.clint)
  28. return -EINVAL;
  29. return 0;
  30. }
  31. int riscv_send_ipi(int hart)
  32. {
  33. writel(1, (void __iomem *)MSIP_REG(gd->arch.clint, hart));
  34. return 0;
  35. }
  36. int riscv_clear_ipi(int hart)
  37. {
  38. writel(0, (void __iomem *)MSIP_REG(gd->arch.clint, hart));
  39. return 0;
  40. }
  41. int riscv_get_ipi(int hart, int *pending)
  42. {
  43. *pending = readl((void __iomem *)MSIP_REG(gd->arch.clint, hart));
  44. return 0;
  45. }