tcm.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/highmem.h>
  3. #include <linux/genalloc.h>
  4. #include <asm/tlbflush.h>
  5. #include <asm/fixmap.h>
  6. #if (CONFIG_ITCM_RAM_BASE == 0xffffffff)
  7. #error "You should define ITCM_RAM_BASE"
  8. #endif
  9. #ifdef CONFIG_HAVE_DTCM
  10. #if (CONFIG_DTCM_RAM_BASE == 0xffffffff)
  11. #error "You should define DTCM_RAM_BASE"
  12. #endif
  13. #if (CONFIG_DTCM_RAM_BASE == CONFIG_ITCM_RAM_BASE)
  14. #error "You should define correct DTCM_RAM_BASE"
  15. #endif
  16. #endif
  17. extern char __tcm_start, __tcm_end, __dtcm_start;
  18. static struct gen_pool *tcm_pool;
  19. static void __init tcm_mapping_init(void)
  20. {
  21. pte_t *tcm_pte;
  22. unsigned long vaddr, paddr;
  23. int i;
  24. paddr = CONFIG_ITCM_RAM_BASE;
  25. if (pfn_valid(PFN_DOWN(CONFIG_ITCM_RAM_BASE)))
  26. goto panic;
  27. #ifndef CONFIG_HAVE_DTCM
  28. for (i = 0; i < TCM_NR_PAGES; i++) {
  29. #else
  30. for (i = 0; i < CONFIG_ITCM_NR_PAGES; i++) {
  31. #endif
  32. vaddr = __fix_to_virt(FIX_TCM - i);
  33. tcm_pte =
  34. pte_offset_kernel((pmd_t *)pgd_offset_k(vaddr), vaddr);
  35. set_pte(tcm_pte, pfn_pte(__phys_to_pfn(paddr), PAGE_KERNEL));
  36. flush_tlb_one(vaddr);
  37. paddr = paddr + PAGE_SIZE;
  38. }
  39. #ifdef CONFIG_HAVE_DTCM
  40. if (pfn_valid(PFN_DOWN(CONFIG_DTCM_RAM_BASE)))
  41. goto panic;
  42. paddr = CONFIG_DTCM_RAM_BASE;
  43. for (i = 0; i < CONFIG_DTCM_NR_PAGES; i++) {
  44. vaddr = __fix_to_virt(FIX_TCM - CONFIG_ITCM_NR_PAGES - i);
  45. tcm_pte =
  46. pte_offset_kernel((pmd_t *) pgd_offset_k(vaddr), vaddr);
  47. set_pte(tcm_pte, pfn_pte(__phys_to_pfn(paddr), PAGE_KERNEL));
  48. flush_tlb_one(vaddr);
  49. paddr = paddr + PAGE_SIZE;
  50. }
  51. #endif
  52. #ifndef CONFIG_HAVE_DTCM
  53. memcpy((void *)__fix_to_virt(FIX_TCM),
  54. &__tcm_start, &__tcm_end - &__tcm_start);
  55. pr_info("%s: mapping tcm va:0x%08lx to pa:0x%08x\n",
  56. __func__, __fix_to_virt(FIX_TCM), CONFIG_ITCM_RAM_BASE);
  57. pr_info("%s: __tcm_start va:0x%08lx size:%d\n",
  58. __func__, (unsigned long)&__tcm_start, &__tcm_end - &__tcm_start);
  59. #else
  60. memcpy((void *)__fix_to_virt(FIX_TCM),
  61. &__tcm_start, &__dtcm_start - &__tcm_start);
  62. pr_info("%s: mapping itcm va:0x%08lx to pa:0x%08x\n",
  63. __func__, __fix_to_virt(FIX_TCM), CONFIG_ITCM_RAM_BASE);
  64. pr_info("%s: __itcm_start va:0x%08lx size:%d\n",
  65. __func__, (unsigned long)&__tcm_start, &__dtcm_start - &__tcm_start);
  66. memcpy((void *)__fix_to_virt(FIX_TCM - CONFIG_ITCM_NR_PAGES),
  67. &__dtcm_start, &__tcm_end - &__dtcm_start);
  68. pr_info("%s: mapping dtcm va:0x%08lx to pa:0x%08x\n",
  69. __func__, __fix_to_virt(FIX_TCM - CONFIG_ITCM_NR_PAGES),
  70. CONFIG_DTCM_RAM_BASE);
  71. pr_info("%s: __dtcm_start va:0x%08lx size:%d\n",
  72. __func__, (unsigned long)&__dtcm_start, &__tcm_end - &__dtcm_start);
  73. #endif
  74. return;
  75. panic:
  76. panic("TCM init error");
  77. }
  78. void *tcm_alloc(size_t len)
  79. {
  80. unsigned long vaddr;
  81. if (!tcm_pool)
  82. return NULL;
  83. vaddr = gen_pool_alloc(tcm_pool, len);
  84. if (!vaddr)
  85. return NULL;
  86. return (void *) vaddr;
  87. }
  88. EXPORT_SYMBOL(tcm_alloc);
  89. void tcm_free(void *addr, size_t len)
  90. {
  91. gen_pool_free(tcm_pool, (unsigned long) addr, len);
  92. }
  93. EXPORT_SYMBOL(tcm_free);
  94. static int __init tcm_setup_pool(void)
  95. {
  96. #ifndef CONFIG_HAVE_DTCM
  97. u32 pool_size = (u32) (TCM_NR_PAGES * PAGE_SIZE)
  98. - (u32) (&__tcm_end - &__tcm_start);
  99. u32 tcm_pool_start = __fix_to_virt(FIX_TCM)
  100. + (u32) (&__tcm_end - &__tcm_start);
  101. #else
  102. u32 pool_size = (u32) (CONFIG_DTCM_NR_PAGES * PAGE_SIZE)
  103. - (u32) (&__tcm_end - &__dtcm_start);
  104. u32 tcm_pool_start = __fix_to_virt(FIX_TCM - CONFIG_ITCM_NR_PAGES)
  105. + (u32) (&__tcm_end - &__dtcm_start);
  106. #endif
  107. int ret;
  108. tcm_pool = gen_pool_create(2, -1);
  109. ret = gen_pool_add(tcm_pool, tcm_pool_start, pool_size, -1);
  110. if (ret) {
  111. pr_err("%s: gen_pool add failed!\n", __func__);
  112. return ret;
  113. }
  114. pr_info("%s: Added %d bytes @ 0x%08x to memory pool\n",
  115. __func__, pool_size, tcm_pool_start);
  116. return 0;
  117. }
  118. static int __init tcm_init(void)
  119. {
  120. tcm_mapping_init();
  121. tcm_setup_pool();
  122. return 0;
  123. }
  124. arch_initcall(tcm_init);