platform.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * SPDX-License-Identifier: BSD-2-Clause
  3. *
  4. * Copyright (c) 2019 Western Digital Corporation or its affiliates.
  5. *
  6. * Authors:
  7. * Anup Patel <anup.patel@wdc.com>
  8. * Nick Kossifidis <mick@ics.forth.gr>
  9. */
  10. #include <sbi/riscv_encoding.h>
  11. #include <sbi/riscv_io.h>
  12. #include <sbi/sbi_const.h>
  13. #include <sbi/sbi_hart.h>
  14. #include <sbi/sbi_platform.h>
  15. #include <plat/irqchip/plic.h>
  16. #include <plat/serial/uart8250.h>
  17. #include <plat/sys/clint.h>
  18. /* clang-format off */
  19. #define VIRT_HART_COUNT 8
  20. #define VIRT_HART_STACK_SIZE 8192
  21. #define VIRT_TEST_ADDR 0x100000
  22. #define VIRT_TEST_FINISHER_FAIL 0x3333
  23. #define VIRT_TEST_FINISHER_PASS 0x5555
  24. #define VIRT_CLINT_ADDR 0x2000000
  25. #define VIRT_PLIC_ADDR 0xc000000
  26. #define VIRT_PLIC_NUM_SOURCES 127
  27. #define VIRT_PLIC_NUM_PRIORITIES 7
  28. #define VIRT_UART16550_ADDR 0x10000000
  29. #define VIRT_UART_BAUDRATE 115200
  30. #define VIRT_UART_SHIFTREG_ADDR 1843200
  31. /* clang-format on */
  32. static int virt_final_init(bool cold_boot)
  33. {
  34. void *fdt;
  35. if (!cold_boot)
  36. return 0;
  37. fdt = sbi_scratch_thishart_arg1_ptr();
  38. plic_fdt_fixup(fdt, "riscv,plic0");
  39. return 0;
  40. }
  41. static u32 virt_pmp_region_count(u32 hartid)
  42. {
  43. return 1;
  44. }
  45. static int virt_pmp_region_info(u32 hartid, u32 index, ulong *prot, ulong *addr,
  46. ulong *log2size)
  47. {
  48. int ret = 0;
  49. switch (index) {
  50. case 0:
  51. *prot = PMP_R | PMP_W | PMP_X;
  52. *addr = 0;
  53. *log2size = __riscv_xlen;
  54. break;
  55. default:
  56. ret = -1;
  57. break;
  58. };
  59. return ret;
  60. }
  61. static int virt_console_init(void)
  62. {
  63. return uart8250_init(VIRT_UART16550_ADDR, VIRT_UART_SHIFTREG_ADDR,
  64. VIRT_UART_BAUDRATE, 0, 1);
  65. }
  66. static int virt_irqchip_init(bool cold_boot)
  67. {
  68. int rc;
  69. u32 hartid = sbi_current_hartid();
  70. if (cold_boot) {
  71. rc = plic_cold_irqchip_init(
  72. VIRT_PLIC_ADDR, VIRT_PLIC_NUM_SOURCES, VIRT_HART_COUNT);
  73. if (rc)
  74. return rc;
  75. }
  76. return plic_warm_irqchip_init(hartid, (2 * hartid), (2 * hartid + 1));
  77. }
  78. static int virt_ipi_init(bool cold_boot)
  79. {
  80. int rc;
  81. if (cold_boot) {
  82. rc = clint_cold_ipi_init(VIRT_CLINT_ADDR, VIRT_HART_COUNT);
  83. if (rc)
  84. return rc;
  85. }
  86. return clint_warm_ipi_init();
  87. }
  88. static int virt_timer_init(bool cold_boot)
  89. {
  90. int rc;
  91. if (cold_boot) {
  92. rc = clint_cold_timer_init(VIRT_CLINT_ADDR, VIRT_HART_COUNT);
  93. if (rc)
  94. return rc;
  95. }
  96. return clint_warm_timer_init();
  97. }
  98. static int virt_system_down(u32 type)
  99. {
  100. /* Tell the "finisher" that the simulation
  101. * was successful so that QEMU exits
  102. */
  103. writew(VIRT_TEST_FINISHER_PASS, (void *)VIRT_TEST_ADDR);
  104. return 0;
  105. }
  106. const struct sbi_platform platform = {
  107. .name = "QEMU Virt Machine",
  108. .features = SBI_PLATFORM_DEFAULT_FEATURES,
  109. .hart_count = VIRT_HART_COUNT,
  110. .hart_stack_size = VIRT_HART_STACK_SIZE,
  111. .disabled_hart_mask = 0,
  112. .pmp_region_count = virt_pmp_region_count,
  113. .pmp_region_info = virt_pmp_region_info,
  114. .final_init = virt_final_init,
  115. .console_putc = uart8250_putc,
  116. .console_getc = uart8250_getc,
  117. .console_init = virt_console_init,
  118. .irqchip_init = virt_irqchip_init,
  119. .ipi_send = clint_ipi_send,
  120. .ipi_sync = clint_ipi_sync,
  121. .ipi_clear = clint_ipi_clear,
  122. .ipi_init = virt_ipi_init,
  123. .timer_value = clint_timer_value,
  124. .timer_event_stop = clint_timer_event_stop,
  125. .timer_event_start = clint_timer_event_start,
  126. .timer_init = virt_timer_init,
  127. .system_reboot = virt_system_down,
  128. .system_shutdown = virt_system_down
  129. };