platform.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * SPDX-License-Identifier: BSD-2-Clause
  3. *
  4. # Copyright (c) 2020 Shanghai StarFive Technology Co., Ltd.
  5. #
  6. # Authors:
  7. # StarFive <support@starfivetech.com>
  8. */
  9. #include <libfdt.h>
  10. #include <sbi/riscv_asm.h>
  11. #include <sbi/riscv_io.h>
  12. #include <sbi/riscv_encoding.h>
  13. #include <sbi/sbi_console.h>
  14. #include <sbi/sbi_const.h>
  15. #include <sbi/sbi_platform.h>
  16. #include <sbi_utils/fdt/fdt_fixup.h>
  17. #include <sbi_utils/irqchip/plic.h>
  18. #include <sbi_utils/serial/uart8250.h>
  19. #include <sbi_utils/sys/clint.h>
  20. /* clang-format off */
  21. #define VIC7100_HART_COUNT 2
  22. #define VIC7100_SYS_CLK 1000000000
  23. #define VIC7100_CLINT_ADDR 0x2000000
  24. #define VIC7100_PLIC_ADDR 0xc000000
  25. #define VIC7100_PLIC_NUM_SOURCES 0x7f
  26. #define VIC7100_PLIC_NUM_PRIORITIES 7
  27. #define VIC7100_UART0_ADDR 0x12440000
  28. #define VIC7100_UART_BAUDRATE 115200
  29. #define VIC7100_UART_REG_SHIFT 2
  30. #define VIC7100_UART_REG_WIDTH 4
  31. /* PRCI clock related macros */
  32. //TODO: Do we need a separate driver for this ?
  33. #define VIC7100_PRCI_BASE_ADDR 0x10000000
  34. #define VIC7100_PRCI_CLKMUXSTATUSREG 0x002C
  35. #define VIC7100_PRCI_CLKMUX_STATUS_TLCLKSEL (0x1 << 1)
  36. /* Full tlb flush always */
  37. #define VIC7100_TLB_RANGE_FLUSH_LIMIT 0
  38. /* clang-format on */
  39. static struct plic_data plic = {
  40. .addr = VIC7100_PLIC_ADDR,
  41. .num_src = VIC7100_PLIC_NUM_SOURCES,
  42. };
  43. static struct clint_data clint = {
  44. .addr = VIC7100_CLINT_ADDR,
  45. .first_hartid = 0,
  46. .hart_count = VIC7100_HART_COUNT,
  47. .has_64bit_mmio = TRUE,
  48. };
  49. static void vic7100_modify_dt(void *fdt)
  50. {
  51. fdt_cpu_fixup(fdt);
  52. fdt_fixups(fdt);
  53. /*
  54. * SiFive Freedom U540 has an erratum that prevents S-mode software
  55. * to access a PMP protected region using 1GB page table mapping, so
  56. * always add the no-map attribute on this platform.
  57. */
  58. fdt_reserved_memory_nomap_fixup(fdt);
  59. }
  60. static int vic7100_final_init(bool cold_boot)
  61. {
  62. void *fdt;
  63. if (!cold_boot)
  64. return 0;
  65. fdt = sbi_scratch_thishart_arg1_ptr();
  66. vic7100_modify_dt(fdt);
  67. return 0;
  68. }
  69. static int vic7100_console_init(void)
  70. {
  71. unsigned long peri_in_freq;
  72. if (readl((volatile void *)VIC7100_PRCI_BASE_ADDR +
  73. VIC7100_PRCI_CLKMUXSTATUSREG) &
  74. VIC7100_PRCI_CLKMUX_STATUS_TLCLKSEL) {
  75. peri_in_freq = VIC7100_SYS_CLK;
  76. } else {
  77. peri_in_freq = VIC7100_SYS_CLK / 10;
  78. }
  79. return uart8250_init(VIC7100_UART0_ADDR, peri_in_freq,
  80. VIC7100_UART_BAUDRATE,
  81. VIC7100_UART_REG_SHIFT, VIC7100_UART_REG_WIDTH);
  82. }
  83. static int vic7100_irqchip_init(bool cold_boot)
  84. {
  85. int rc;
  86. u32 hartid = current_hartid();
  87. if (cold_boot) {
  88. rc = plic_cold_irqchip_init(&plic);
  89. if (rc)
  90. return rc;
  91. }
  92. return plic_warm_irqchip_init(&plic, (hartid) ? (2 * hartid - 1) : 0,
  93. (hartid) ? (2 * hartid) : -1);
  94. }
  95. static int vic7100_ipi_init(bool cold_boot)
  96. {
  97. int rc;
  98. if (cold_boot) {
  99. rc = clint_cold_ipi_init(&clint);
  100. if (rc)
  101. return rc;
  102. }
  103. return clint_warm_ipi_init();
  104. }
  105. static u64 vic7100_get_tlbr_flush_limit(void)
  106. {
  107. return VIC7100_TLB_RANGE_FLUSH_LIMIT;
  108. }
  109. static int vic7100_timer_init(bool cold_boot)
  110. {
  111. int rc;
  112. if (cold_boot) {
  113. rc = clint_cold_timer_init(&clint, NULL);
  114. if (rc)
  115. return rc;
  116. }
  117. return clint_warm_timer_init();
  118. }
  119. const struct sbi_platform_operations platform_ops = {
  120. .final_init = vic7100_final_init,
  121. .console_putc = uart8250_putc,
  122. .console_getc = uart8250_getc,
  123. .console_init = vic7100_console_init,
  124. .irqchip_init = vic7100_irqchip_init,
  125. .ipi_send = clint_ipi_send,
  126. .ipi_clear = clint_ipi_clear,
  127. .ipi_init = vic7100_ipi_init,
  128. .get_tlbr_flush_limit = vic7100_get_tlbr_flush_limit,
  129. .timer_value = clint_timer_value,
  130. .timer_event_stop = clint_timer_event_stop,
  131. .timer_event_start = clint_timer_event_start,
  132. .timer_init = vic7100_timer_init,
  133. };
  134. const struct sbi_platform platform = {
  135. .opensbi_version = OPENSBI_VERSION,
  136. .platform_version = SBI_PLATFORM_VERSION(0x0, 0x01),
  137. .name = "StarFive VIC7100",
  138. .features = SBI_PLATFORM_DEFAULT_FEATURES,
  139. .hart_count = (VIC7100_HART_COUNT),
  140. .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE,
  141. .platform_ops_addr = (unsigned long)&platform_ops
  142. };