sifive_clint.c 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  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/global_data.h>
  13. #include <asm/io.h>
  14. #include <asm/smp.h>
  15. #include <linux/err.h>
  16. /* MSIP registers */
  17. #define MSIP_REG(base, hart) ((ulong)(base) + (hart) * 4)
  18. DECLARE_GLOBAL_DATA_PTR;
  19. int riscv_init_ipi(void)
  20. {
  21. int ret;
  22. struct udevice *dev;
  23. ret = uclass_get_device_by_driver(UCLASS_TIMER,
  24. DM_DRIVER_GET(sifive_clint), &dev);
  25. if (ret)
  26. return ret;
  27. gd->arch.clint = dev_read_addr_ptr(dev);
  28. if (!gd->arch.clint)
  29. return -EINVAL;
  30. return 0;
  31. }
  32. int riscv_send_ipi(int hart)
  33. {
  34. writel(1, (void __iomem *)MSIP_REG(gd->arch.clint, hart));
  35. return 0;
  36. }
  37. int riscv_clear_ipi(int hart)
  38. {
  39. writel(0, (void __iomem *)MSIP_REG(gd->arch.clint, hart));
  40. return 0;
  41. }
  42. int riscv_get_ipi(int hart, int *pending)
  43. {
  44. *pending = readl((void __iomem *)MSIP_REG(gd->arch.clint, hart));
  45. return 0;
  46. }