| // SPDX-License-Identifier: (GPL-2.0+ OR MIT) |
| /* |
| * Copyright (c) 2019 Amlogic, Inc. All rights reserved. |
| */ |
| |
| //#define DEBUG |
| #include <linux/module.h> |
| #include <linux/device.h> |
| #include <linux/of_device.h> |
| #include <linux/platform_device.h> |
| #include <linux/types.h> |
| #include <linux/moduleparam.h> |
| #include <linux/io.h> |
| #include <linux/ioport.h> |
| #include <linux/mm.h> |
| #include <linux/kasan.h> |
| #include <linux/amlogic/module_merge.h> |
| #include "main.h" |
| #include <linux/amlogic/aml_free_reserved.h> |
| |
| unsigned long aml_free_reserved_area(void *start, void *end, int poison, const char *s) |
| { |
| void *pos; |
| unsigned long pages = 0; |
| |
| start = (void *)PAGE_ALIGN((unsigned long)start); |
| end = (void *)((unsigned long)end & PAGE_MASK); |
| for (pos = start; pos < end; pos += PAGE_SIZE, pages++) { |
| struct page *page = virt_to_page(pos); |
| void *direct_map_addr; |
| |
| /* |
| * 'direct_map_addr' might be different from 'pos' |
| * because some architectures' virt_to_page() |
| * work with aliases. Getting the direct map |
| * address ensures that we get a _writeable_ |
| * alias for the memset(). |
| */ |
| direct_map_addr = page_address(page); |
| /* |
| * Perform a kasan-unchecked memset() since this memory |
| * has not been initialized. |
| */ |
| direct_map_addr = kasan_reset_tag(direct_map_addr); |
| if ((unsigned int)poison <= 0xFF) |
| memset(direct_map_addr, poison, PAGE_SIZE); |
| |
| free_reserved_page(page); |
| } |
| |
| if (pages && s) |
| pr_info("Freeing %s memory: %ldK\n", |
| s, pages << (PAGE_SHIFT - 10)); |
| |
| return pages; |
| } |
| EXPORT_SYMBOL(aml_free_reserved_area); |
| |
| #if IS_ENABLED(CONFIG_AMLOGIC_DEBUG_IOTRACE) |
| #include <linux/of_address.h> |
| #include <linux/of.h> |
| #include <linux/amlogic/aml_iotrace.h> |
| void free_iotrace_reserved_memory(void) |
| { |
| int ret; |
| struct resource res; |
| struct device_node *node = NULL; |
| |
| node = of_find_node_by_path("/reserved-memory/linux,iotrace"); |
| if (!node) |
| return; |
| |
| ret = of_address_to_resource(node, 0, &res); |
| if (ret) |
| return; |
| |
| // free reserved-memory if no need |
| if (!ramoops_io_en) { |
| aml_free_reserved_area(__va(res.start), __va(PAGE_ALIGN(res.end)), 0, |
| "free_reserved"); |
| pr_info("free iotrace reserved_memory\n"); |
| } |
| } |
| #endif |
| |
| static int __init memory_main_init(void) |
| { |
| pr_debug("### %s() start\n", __func__); |
| call_sub_init(filecache_module_init); |
| call_sub_init(aml_watch_pint_init); |
| call_sub_init(aml_reg_init); |
| call_sub_init(ddr_tool_init); |
| call_sub_init(ramdump_init); |
| #if IS_ENABLED(CONFIG_AMLOGIC_DEBUG_IOTRACE) |
| free_iotrace_reserved_memory(); |
| #endif |
| pr_debug("### %s() end\n", __func__); |
| |
| return 0; |
| } |
| |
| static void __exit memory_main_exit(void) |
| { |
| ramdump_uninit(); |
| ddr_tool_exit(); |
| aml_reg_exit(); |
| aml_watch_point_uninit(); |
| filecache_module_exit(); |
| } |
| |
| module_init(memory_main_init); |
| module_exit(memory_main_exit); |
| MODULE_LICENSE("GPL v2"); |