// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2019 MediaTek Inc. */ /** * @file gpueb_reserved_mem.c * @brief Reserved memory info init for GPUEB */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gpueb_helper.h" #include "gpueb_reserved_mem.h" phys_addr_t gpueb_mem_base_phys; phys_addr_t gpueb_mem_base_virt; phys_addr_t gpueb_mem_size; unsigned int gpueb_mem_num = 0; struct gpueb_reserve_mblock *gpueb_reserve_mblock_ary; const char *gpueb_reserve_mblock_ary_name[20]; int gpueb_reserve_mem_of_init(struct reserved_mem *rmem) { gpueb_pr_debug("@%s: %pa %pa\n", __func__, &rmem->base, &rmem->size); gpueb_mem_base_phys = (phys_addr_t) rmem->base; gpueb_mem_size = (phys_addr_t) rmem->size; return 0; } RESERVEDMEM_OF_DECLARE(gpueb_reserve_mem_init, GPUEB_MEM_RESERVED_KEY, gpueb_reserve_mem_of_init); phys_addr_t gpueb_get_reserve_mem_phys(unsigned int id) { if (id >= gpueb_mem_num) { gpueb_pr_debug("@%s: no reserve memory for %d", __func__, id); return 0; } else return gpueb_reserve_mblock_ary[id].start_phys; } EXPORT_SYMBOL_GPL(gpueb_get_reserve_mem_phys); phys_addr_t gpueb_get_reserve_mem_virt(unsigned int id) { if (id >= gpueb_mem_num) { gpueb_pr_debug("@%s: no reserve memory for %d", __func__, id); return 0; } else return gpueb_reserve_mblock_ary[id].start_virt; } EXPORT_SYMBOL_GPL(gpueb_get_reserve_mem_virt); phys_addr_t gpueb_get_reserve_mem_size(unsigned int id) { if (id >= gpueb_mem_num) { gpueb_pr_debug("@%s: no reserve memory for %d", __func__, id); return 0; } else return gpueb_reserve_mblock_ary[id].size; } EXPORT_SYMBOL_GPL(gpueb_get_reserve_mem_size); phys_addr_t gpueb_get_reserve_mem_phys_by_name(char *mem_id_name) { int id = -1; int i; for (i = 0; i < gpueb_mem_num; i++) { if (!strcmp(gpueb_reserve_mblock_ary_name[i], mem_id_name)) id = i; } if (id < 0 || id >= gpueb_mem_num) { gpueb_pr_debug("@%s: no reserve memory for %d (%s)", __func__, id, mem_id_name); return 0; } else return gpueb_reserve_mblock_ary[id].start_phys; } EXPORT_SYMBOL_GPL(gpueb_get_reserve_mem_phys_by_name); phys_addr_t gpueb_get_reserve_mem_virt_by_name(char *mem_id_name) { int id = -1; int i; for (i = 0; i < gpueb_mem_num; i++) { if (!strcmp(gpueb_reserve_mblock_ary_name[i], mem_id_name)) id = i; } if (id < 0 || id >= gpueb_mem_num) { gpueb_pr_debug("@%s: no reserve memory for %d (%s)", __func__, id, mem_id_name); return 0; } else return gpueb_reserve_mblock_ary[id].start_virt; } EXPORT_SYMBOL_GPL(gpueb_get_reserve_mem_virt_by_name); phys_addr_t gpueb_get_reserve_mem_size_by_name(char *mem_id_name) { int id = -1; int i; for (i = 0; i < gpueb_mem_num; i++) { if (!strcmp(gpueb_reserve_mblock_ary_name[i], mem_id_name)) id = i; } if (id < 0 || id >= gpueb_mem_num) { gpueb_pr_debug("@%s: no reserve memory for %d (%s)", __func__, id, mem_id_name); return 0; } else return gpueb_reserve_mblock_ary[id].size; } EXPORT_SYMBOL_GPL(gpueb_get_reserve_mem_size_by_name); int gpueb_reserved_mem_init(struct platform_device *pdev) { struct device_node *of_gpueb = pdev->dev.of_node; unsigned int i, m_idx, m_size; phys_addr_t accumlate_memory_size = 0; int ret; of_property_read_u64(of_gpueb, "gpueb_mem_addr", &gpueb_mem_base_phys); of_property_read_u64(of_gpueb, "gpueb_mem_size", &gpueb_mem_size); if (!gpueb_mem_base_phys || !gpueb_mem_size) { gpueb_pr_debug("@%s: invalid gpueb_mem_base_phys (0x%llx), gpueb_mem_size (%llx)\n", __func__, gpueb_mem_base_phys, gpueb_mem_size); return -EINVAL; } gpueb_pr_debug("@%s: base_phys = 0x%llx, size = 0x%llx", __func__, gpueb_mem_base_phys, gpueb_mem_size); if ((gpueb_mem_base_phys >= 0x800000000ULL) || (gpueb_mem_base_phys < 0x40000000ULL)) { /* * The gpueb remapped region is fixed, only * 0x4000_0000 ~ 0x7_FFFF_FFFF is accessible. */ gpueb_pr_debug("@%s: Error: Wrong Address (0x%llx)\n", __func__, gpueb_mem_base_phys); BUG_ON(1); return -1; } // Set reserved memory table gpueb_mem_num = of_property_count_u32_elems( pdev->dev.of_node, "gpueb_mem_table") / MEMORY_TBL_ELEM_NUM; if (gpueb_mem_num <= 0) { gpueb_pr_debug("@%s: gpueb_mem_table not found\n", __func__); gpueb_mem_num = 0; } // Get reserved mblock name ret = of_property_read_string_array(pdev->dev.of_node, "gpueb_mem_name_table", gpueb_reserve_mblock_ary_name, gpueb_mem_num); if (ret < 0) { gpueb_pr_debug("@%s: gpueb_mem_name_table not found\n", __func__); return -1; } for (i = 0; i < gpueb_mem_num; i++) { gpueb_pr_debug("gpueb_reserve_mblock_ary_name[%d] = %s\n", i, gpueb_reserve_mblock_ary_name[i]); } gpueb_reserve_mblock_ary = vzalloc(sizeof(struct gpueb_reserve_mblock) * gpueb_mem_num); for (i = 0; i < gpueb_mem_num; i++) { // Get reserved block's ID ret = of_property_read_u32_index(pdev->dev.of_node, "gpueb_mem_table", i * MEMORY_TBL_ELEM_NUM, &m_idx); if (ret) { gpueb_pr_debug("@%s: Cannot get memory index(%d)\n", __func__, i); return -1; } gpueb_reserve_mblock_ary[m_idx].num = m_idx; // Get reserved block's size ret = of_property_read_u32_index(pdev->dev.of_node, "gpueb_mem_table", (i * MEMORY_TBL_ELEM_NUM) + 1, &m_size); if (ret) { gpueb_pr_debug("@%s: Cannot get memory size(%d)\n", __func__, i); return -1; } if (m_idx >= gpueb_mem_num) { gpueb_pr_debug("@%s: Skip unexpected index, %d\n", __func__, m_idx); continue; } gpueb_reserve_mblock_ary[m_idx].size = m_size; gpueb_pr_debug("@%s: Reserved block <%d %d>\n", __func__, m_idx, m_size); } // Transfer physical address to virtual address gpueb_mem_base_virt = (phys_addr_t)(size_t)ioremap_wc( gpueb_mem_base_phys, gpueb_mem_size); gpueb_pr_debug("@%s: Reserved phy_base = 0x%llx, len:0x%llx, Reserved virt_base = 0x%llx\n", __func__, gpueb_mem_base_phys, gpueb_mem_size, gpueb_mem_base_virt); // Init the access address for each block for (i = 0; i < gpueb_mem_num; i++) { gpueb_reserve_mblock_ary[i].start_phys = gpueb_mem_base_phys + accumlate_memory_size; gpueb_reserve_mblock_ary[i].start_virt = gpueb_mem_base_virt + accumlate_memory_size; accumlate_memory_size += gpueb_reserve_mblock_ary[i].size; gpueb_pr_debug("@%s: Reserved block[%d] phys:0x%llx, virt:0x%llx, len:0x%llx\n", __func__, i, gpueb_reserve_mblock_ary[i].start_phys, gpueb_reserve_mblock_ary[i].start_virt, gpueb_reserve_mblock_ary[i].size); } if (accumlate_memory_size > gpueb_mem_size) gpueb_pr_debug("@%s: Total memory in memory table is more than reserved", __func__); return 0; }