// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2011-2015 MediaTek Inc. */ #include /* needed by all modules */ #include /* needed by module macros */ #include /* needed by file_operations* */ #include /* needed by miscdevice* */ #include /* needed by device_* */ #include /* needed by kmalloc */ #include /* needed by copy_to_user */ #include /* needed by file_operations* */ #include /* needed by kmalloc */ #include /* needed by poll */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sspm_define.h" #include "sspm_helper.h" #include "sspm_reservedmem.h" #define _SSPM_INTERNAL_ #include "sspm_reservedmem_define.h" #ifdef CONFIG_OF_RESERVED_MEM #include #define SSPM_MEM_RESERVED_KEY "mediatek,reserve-memory-sspm_share" #endif static phys_addr_t sspm_mem_base_phys; static phys_addr_t sspm_mem_base_virt; static phys_addr_t sspm_mem_size; #ifdef CONFIG_OF_RESERVED_MEM static int __init sspm_reserve_mem_of_init(struct reserved_mem *rmem) { unsigned int id; phys_addr_t accumlate_memory_size = 0; sspm_mem_base_phys = (phys_addr_t) rmem->base; sspm_mem_size = (phys_addr_t) rmem->size; pr_debug("[SSPM] phys:0x%llx - 0x%llx (0x%llx)\n", (unsigned long long)rmem->base, (unsigned long long)rmem->base + (unsigned long long)rmem->size, (unsigned long long)rmem->size); accumlate_memory_size = 0; for (id = 0; id < NUMS_MEM_ID; id++) { sspm_reserve_mblock[id].start_phys = sspm_mem_base_phys + accumlate_memory_size; accumlate_memory_size += sspm_reserve_mblock[id].size; pr_debug("[SSPM][reserve_mem:%d]: ", id); pr_debug("phys:0x%llx - 0x%llx (0x%llx)\n", sspm_reserve_mblock[id].start_phys, sspm_reserve_mblock[id].start_phys + sspm_reserve_mblock[id].size, sspm_reserve_mblock[id].size); } return 0; } RESERVEDMEM_OF_DECLARE(sspm_reservedmem, SSPM_MEM_RESERVED_KEY, sspm_reserve_mem_of_init); #endif phys_addr_t sspm_reserve_mem_get_phys(unsigned int id) { if (id >= NUMS_MEM_ID) { pr_err("[SSPM] no reserve memory for 0x%x", id); return 0; } else return sspm_reserve_mblock[id].start_phys; } EXPORT_SYMBOL_GPL(sspm_reserve_mem_get_phys); phys_addr_t sspm_reserve_mem_get_virt(unsigned int id) { if (id >= NUMS_MEM_ID) { pr_err("[SSPM] no reserve memory for 0x%x", id); return 0; } else return sspm_reserve_mblock[id].start_virt; } EXPORT_SYMBOL_GPL(sspm_reserve_mem_get_virt); phys_addr_t sspm_reserve_mem_get_size(unsigned int id) { if (id >= NUMS_MEM_ID) { pr_err("[SSPM] no reserve memory for 0x%x", id); return 0; } else return sspm_reserve_mblock[id].size; } EXPORT_SYMBOL_GPL(sspm_reserve_mem_get_size); #ifdef SSPM_SHARE_BUFFER_SUPPORT void __iomem *sspm_base; phys_addr_t sspm_sbuf_get(unsigned int offset) { if (!is_sspm_ready()) { pr_notice("[SSPM] device resource is not ready\n"); return 0; } if (offset < SSPM_SHARE_REGION_BASE || offset > SSPM_SHARE_REGION_BASE + SSPM_SHARE_REGION_SIZE) { pr_notice("[SSPM] illegal sbuf request: 0x%x\n", offset); return 0; } else { return (phys_addr_t)(sspm_base + offset); } } EXPORT_SYMBOL_GPL(sspm_sbuf_get); #endif int sspm_reserve_memory_init(void) { unsigned int id; phys_addr_t accumlate_memory_size; if (NUMS_MEM_ID == 0) return 0; if (sspm_mem_base_phys == 0) return -1; accumlate_memory_size = 0; sspm_mem_base_virt = (phys_addr_t)(uintptr_t) ioremap_wc(sspm_mem_base_phys, sspm_mem_size); pr_debug("[SSPM]reserve mem: virt:0x%llx - 0x%llx (0x%llx)\n", (unsigned long long)sspm_mem_base_virt, (unsigned long long)sspm_mem_base_virt + (unsigned long long)sspm_mem_size, (unsigned long long)sspm_mem_size); for (id = 0; id < NUMS_MEM_ID; id++) { sspm_reserve_mblock[id].start_virt = sspm_mem_base_virt + accumlate_memory_size; accumlate_memory_size += sspm_reserve_mblock[id].size; } /* the reserved memory should be larger then expected memory * or sspm_reserve_mblock does not match dts */ BUG_ON(accumlate_memory_size > sspm_mem_size); #ifdef DEBUG for (id = 0; id < NUMS_MEM_ID; id++) { pr_debug("[SSPM][mem_reserve-%d] ", id); pr_debug("phys:0x%llx,virt:0x%llx,size:0x%llx\n", (unsigned long long)sspm_reserve_mem_get_phys(id), (unsigned long long)sspm_reserve_mem_get_virt(id), (unsigned long long)sspm_reserve_mem_get_size(id)); } #endif return 0; } void sspm_lock_emi_mpu(void) { #if SSPM_EMI_PROTECTION_SUPPORT if (sspm_mem_size > 0) sspm_set_emi_mpu(sspm_mem_base_phys, sspm_mem_size); #endif } #ifdef SSPM_SHARE_BUFFER_SUPPORT int sspm_sbuf_init(void) { struct device *dev = &sspm_pdev->dev; struct resource *res; if (sspm_pdev) { res = platform_get_resource_byname(sspm_pdev, IORESOURCE_MEM, "sspm_base"); sspm_base = devm_ioremap_resource(dev, res); if (IS_ERR((void const *) sspm_base)) return -1; } return 0; } #endif