cpu_spin_table.c 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. */
  9. #include <rthw.h>
  10. #include <rtthread.h>
  11. #include <ioremap.h>
  12. #include "cpu.h"
  13. #define DBG_TAG "libcpu.aarch64.cpu_spin_table"
  14. #define DBG_LVL DBG_INFO
  15. #include <rtdbg.h>
  16. #include "cpu_ops_common.h"
  17. #ifdef RT_USING_SMP
  18. #ifdef RT_USING_FDT
  19. #include <dtb_node.h>
  20. static rt_uint64_t cpu_release_addr[RT_CPUS_NR];
  21. static int spin_table_cpu_init(rt_uint32_t cpuid)
  22. {
  23. struct dtb_node *cpu = get_cpu_node(cpuid);
  24. if (!cpu)
  25. return -1; /* uninitialized cpu node in fdt */
  26. int size;
  27. rt_uint64_t *phead = (rt_uint64_t*)dtb_node_get_dtb_node_property_value(cpu, "cpu-release-addr", &size);
  28. cpu_release_addr[cpuid] = fdt64_to_cpu(*phead);
  29. LOG_D("Using release address 0x%p for CPU %d", cpu_release_addr[cpuid], cpuid);
  30. return 0;
  31. }
  32. static int spin_table_cpu_boot(rt_uint32_t cpuid)
  33. {
  34. rt_uint64_t secondary_entry_pa = get_secondary_entry_pa();
  35. if (!secondary_entry_pa)
  36. return -1;
  37. // map release_addr to addressable place
  38. void *rel_va = rt_ioremap((void *)cpu_release_addr[cpuid], sizeof(cpu_release_addr[0]));
  39. if (!rel_va)
  40. {
  41. LOG_E("IO remap failing");
  42. return -1;
  43. }
  44. __asm__ volatile("str %0, [%1]" ::"rZ"(secondary_entry_pa), "r"(rel_va));
  45. __asm__ volatile("dsb sy");
  46. __asm__ volatile("sev");
  47. rt_iounmap(rel_va);
  48. return 0;
  49. }
  50. #endif /* RT_USING_FDT */
  51. struct cpu_ops_t cpu_ops_spin_tbl = {
  52. .method = "spin-table",
  53. #ifdef RT_USING_FDT
  54. .cpu_init = spin_table_cpu_init,
  55. .cpu_boot = spin_table_cpu_boot,
  56. #endif
  57. };
  58. #endif /* RT_USING_SMP */