18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci#include <linux/highmem.h> 48c2ecf20Sopenharmony_ci#include <linux/genalloc.h> 58c2ecf20Sopenharmony_ci#include <asm/tlbflush.h> 68c2ecf20Sopenharmony_ci#include <asm/fixmap.h> 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#if (CONFIG_ITCM_RAM_BASE == 0xffffffff) 98c2ecf20Sopenharmony_ci#error "You should define ITCM_RAM_BASE" 108c2ecf20Sopenharmony_ci#endif 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#ifdef CONFIG_HAVE_DTCM 138c2ecf20Sopenharmony_ci#if (CONFIG_DTCM_RAM_BASE == 0xffffffff) 148c2ecf20Sopenharmony_ci#error "You should define DTCM_RAM_BASE" 158c2ecf20Sopenharmony_ci#endif 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#if (CONFIG_DTCM_RAM_BASE == CONFIG_ITCM_RAM_BASE) 188c2ecf20Sopenharmony_ci#error "You should define correct DTCM_RAM_BASE" 198c2ecf20Sopenharmony_ci#endif 208c2ecf20Sopenharmony_ci#endif 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ciextern char __tcm_start, __tcm_end, __dtcm_start; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistatic struct gen_pool *tcm_pool; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic void __init tcm_mapping_init(void) 278c2ecf20Sopenharmony_ci{ 288c2ecf20Sopenharmony_ci pte_t *tcm_pte; 298c2ecf20Sopenharmony_ci unsigned long vaddr, paddr; 308c2ecf20Sopenharmony_ci int i; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci paddr = CONFIG_ITCM_RAM_BASE; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci if (pfn_valid(PFN_DOWN(CONFIG_ITCM_RAM_BASE))) 358c2ecf20Sopenharmony_ci goto panic; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#ifndef CONFIG_HAVE_DTCM 388c2ecf20Sopenharmony_ci for (i = 0; i < TCM_NR_PAGES; i++) { 398c2ecf20Sopenharmony_ci#else 408c2ecf20Sopenharmony_ci for (i = 0; i < CONFIG_ITCM_NR_PAGES; i++) { 418c2ecf20Sopenharmony_ci#endif 428c2ecf20Sopenharmony_ci vaddr = __fix_to_virt(FIX_TCM - i); 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci tcm_pte = 458c2ecf20Sopenharmony_ci pte_offset_kernel((pmd_t *)pgd_offset_k(vaddr), vaddr); 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci set_pte(tcm_pte, pfn_pte(__phys_to_pfn(paddr), PAGE_KERNEL)); 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci flush_tlb_one(vaddr); 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci paddr = paddr + PAGE_SIZE; 528c2ecf20Sopenharmony_ci } 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci#ifdef CONFIG_HAVE_DTCM 558c2ecf20Sopenharmony_ci if (pfn_valid(PFN_DOWN(CONFIG_DTCM_RAM_BASE))) 568c2ecf20Sopenharmony_ci goto panic; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci paddr = CONFIG_DTCM_RAM_BASE; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci for (i = 0; i < CONFIG_DTCM_NR_PAGES; i++) { 618c2ecf20Sopenharmony_ci vaddr = __fix_to_virt(FIX_TCM - CONFIG_ITCM_NR_PAGES - i); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci tcm_pte = 648c2ecf20Sopenharmony_ci pte_offset_kernel((pmd_t *) pgd_offset_k(vaddr), vaddr); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci set_pte(tcm_pte, pfn_pte(__phys_to_pfn(paddr), PAGE_KERNEL)); 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci flush_tlb_one(vaddr); 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci paddr = paddr + PAGE_SIZE; 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci#endif 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci#ifndef CONFIG_HAVE_DTCM 758c2ecf20Sopenharmony_ci memcpy((void *)__fix_to_virt(FIX_TCM), 768c2ecf20Sopenharmony_ci &__tcm_start, &__tcm_end - &__tcm_start); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci pr_info("%s: mapping tcm va:0x%08lx to pa:0x%08x\n", 798c2ecf20Sopenharmony_ci __func__, __fix_to_virt(FIX_TCM), CONFIG_ITCM_RAM_BASE); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci pr_info("%s: __tcm_start va:0x%08lx size:%d\n", 828c2ecf20Sopenharmony_ci __func__, (unsigned long)&__tcm_start, &__tcm_end - &__tcm_start); 838c2ecf20Sopenharmony_ci#else 848c2ecf20Sopenharmony_ci memcpy((void *)__fix_to_virt(FIX_TCM), 858c2ecf20Sopenharmony_ci &__tcm_start, &__dtcm_start - &__tcm_start); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci pr_info("%s: mapping itcm va:0x%08lx to pa:0x%08x\n", 888c2ecf20Sopenharmony_ci __func__, __fix_to_virt(FIX_TCM), CONFIG_ITCM_RAM_BASE); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci pr_info("%s: __itcm_start va:0x%08lx size:%d\n", 918c2ecf20Sopenharmony_ci __func__, (unsigned long)&__tcm_start, &__dtcm_start - &__tcm_start); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci memcpy((void *)__fix_to_virt(FIX_TCM - CONFIG_ITCM_NR_PAGES), 948c2ecf20Sopenharmony_ci &__dtcm_start, &__tcm_end - &__dtcm_start); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci pr_info("%s: mapping dtcm va:0x%08lx to pa:0x%08x\n", 978c2ecf20Sopenharmony_ci __func__, __fix_to_virt(FIX_TCM - CONFIG_ITCM_NR_PAGES), 988c2ecf20Sopenharmony_ci CONFIG_DTCM_RAM_BASE); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci pr_info("%s: __dtcm_start va:0x%08lx size:%d\n", 1018c2ecf20Sopenharmony_ci __func__, (unsigned long)&__dtcm_start, &__tcm_end - &__dtcm_start); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci#endif 1048c2ecf20Sopenharmony_ci return; 1058c2ecf20Sopenharmony_cipanic: 1068c2ecf20Sopenharmony_ci panic("TCM init error"); 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_civoid *tcm_alloc(size_t len) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci unsigned long vaddr; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci if (!tcm_pool) 1148c2ecf20Sopenharmony_ci return NULL; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci vaddr = gen_pool_alloc(tcm_pool, len); 1178c2ecf20Sopenharmony_ci if (!vaddr) 1188c2ecf20Sopenharmony_ci return NULL; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci return (void *) vaddr; 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcm_alloc); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_civoid tcm_free(void *addr, size_t len) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci gen_pool_free(tcm_pool, (unsigned long) addr, len); 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcm_free); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_cistatic int __init tcm_setup_pool(void) 1318c2ecf20Sopenharmony_ci{ 1328c2ecf20Sopenharmony_ci#ifndef CONFIG_HAVE_DTCM 1338c2ecf20Sopenharmony_ci u32 pool_size = (u32) (TCM_NR_PAGES * PAGE_SIZE) 1348c2ecf20Sopenharmony_ci - (u32) (&__tcm_end - &__tcm_start); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci u32 tcm_pool_start = __fix_to_virt(FIX_TCM) 1378c2ecf20Sopenharmony_ci + (u32) (&__tcm_end - &__tcm_start); 1388c2ecf20Sopenharmony_ci#else 1398c2ecf20Sopenharmony_ci u32 pool_size = (u32) (CONFIG_DTCM_NR_PAGES * PAGE_SIZE) 1408c2ecf20Sopenharmony_ci - (u32) (&__tcm_end - &__dtcm_start); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci u32 tcm_pool_start = __fix_to_virt(FIX_TCM - CONFIG_ITCM_NR_PAGES) 1438c2ecf20Sopenharmony_ci + (u32) (&__tcm_end - &__dtcm_start); 1448c2ecf20Sopenharmony_ci#endif 1458c2ecf20Sopenharmony_ci int ret; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci tcm_pool = gen_pool_create(2, -1); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci ret = gen_pool_add(tcm_pool, tcm_pool_start, pool_size, -1); 1508c2ecf20Sopenharmony_ci if (ret) { 1518c2ecf20Sopenharmony_ci pr_err("%s: gen_pool add failed!\n", __func__); 1528c2ecf20Sopenharmony_ci return ret; 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci pr_info("%s: Added %d bytes @ 0x%08x to memory pool\n", 1568c2ecf20Sopenharmony_ci __func__, pool_size, tcm_pool_start); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci return 0; 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cistatic int __init tcm_init(void) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci tcm_mapping_init(); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci tcm_setup_pool(); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci return 0; 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ciarch_initcall(tcm_init); 170