优化预留内存驱动获取唤醒源的方式

This commit is contained in:
张兆鹏 2025-04-22 17:01:16 +08:00
parent 5879cea210
commit 5d71fcb5db
3 changed files with 84 additions and 36 deletions

View File

@ -41,10 +41,6 @@
};
reserved-memory {
wakeup_source: wakeup_source {
reg = <0x0 0x4307F000 0x0 0x00001000>;
no-map;
};
e907_fw: e907_fw {
reg = <0x0 0x43080000 0x0 0x00190000>;
};
@ -97,6 +93,11 @@
reg = <0x0 0x4304A000 0x0 0x1000>;
no-map;
};
wakeup_source: wakeup_source {
reg = <0x0 0x4304B000 0x0 0x00001000>;
compatible = "wakeup-src";
no-map;
};
boot_param: boot_param@0x42FFF000 {
reg = <0x0 0x42FFF000 0x0 0x1000>;

View File

@ -30,6 +30,6 @@ CFG_MELISELF_LOAD_ADDR=0x43080000
#get wakeup source from M0
CFG_GET_WKSRC=y
CFG_WKSRC_ADDR=0x4307F000
CFG_WKSRC_ADDR=0x4304B000
#E907 interrupt table info update
#CFG_UPDATA_IRQ_TAB=y

View File

@ -21,15 +21,48 @@
#include <linux/memblock.h>
#include <linux/pagemap.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#define WEIGHT_ADDR 0x4307F000 // 权重加载的内存地址处
#define M_PAGE_SIZE (4 * 1024) // 内存对齐应该是4K
// #define WEIGHT_ADDR 0x4307F000 // 权重加载的内存地址处
// #define M_PAGE_SIZE (4 * 1024) // 内存对齐应该是4K
#define MEM_ACCESS_RELEASE_PHYS_ADDR _IOR('M', 0, unsigned int)
#define MEM_ACCESS_GET_WKSRC_SRC _IOW('M', 1, unsigned int)
#define MEM_ACCESS_SET_WKSRC_SRC _IOR('M', 2, unsigned int)
typedef struct {
unsigned char readData[sizeof(int)];
} wakeup_src_t;
static int major = 0;
static struct class *mem_operation_class;
struct mem_area_info {
atomic_t init_flag;
void __iomem *g_vaddr;
int len;
};
static struct mem_area_info g_mem = {.init_flag = ATOMIC_INIT(0), .g_vaddr = NULL};
int mem_set_wakeup_source(unsigned char wakeup_src) {
if (atomic_read(&g_mem.init_flag) == 1)
{
writeb(wakeup_src, g_mem.g_vaddr);
return 0;
}
return -1;
}
EXPORT_SYMBOL(mem_set_wakeup_source);
unsigned char mem_get_wakeup_source(void) {
if (atomic_read(&g_mem.init_flag) == 1)
{
return readb(g_mem.g_vaddr);
}
return 0xFF;
}
EXPORT_SYMBOL(mem_get_wakeup_source);
static int check_page_reserved(unsigned long addr)
{
@ -59,9 +92,9 @@ static int mem_operation_drv_close (struct inode *node, struct file *file)
static int mem_operation_drv_mmap(struct file *file, struct vm_area_struct *vma)
{
unsigned long phy = WEIGHT_ADDR;
unsigned long phy = (unsigned long)g_mem.g_vaddr;
if(check_page_reserved(WEIGHT_ADDR) < 0)
if(check_page_reserved((unsigned long)g_mem.g_vaddr) < 0)
return -EINVAL;
/* 设置属性: cache, buffer */
@ -77,9 +110,7 @@ static int mem_operation_drv_mmap(struct file *file, struct vm_area_struct *vma)
return 0;
}
typedef struct {
unsigned char readData[sizeof(int)];
} wakeup_src_t;
static long mem_operation_drv_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
@ -93,57 +124,44 @@ static long mem_operation_drv_ioctl(struct file *file, unsigned int cmd, unsigne
if (get_user(mem_size, (unsigned long __user *)arg))
return -EFAULT;
if(check_page_reserved(WEIGHT_ADDR) < 0)
if(check_page_reserved((unsigned long)g_mem.g_vaddr) < 0)
return -EINVAL;
memblock_free(WEIGHT_ADDR, mem_size);
free_reserved_area(__va(WEIGHT_ADDR), __va(WEIGHT_ADDR + mem_size), -1, "wakeup_source");
printk("release phy addr: 0x%x, size: %d\n", WEIGHT_ADDR, mem_size);
memblock_free((unsigned int)g_mem.g_vaddr, mem_size);
free_reserved_area(__va(g_mem.g_vaddr), __va(g_mem.g_vaddr + mem_size), -1, "wakeup_source");
// printk("release phy addr: 0x%x, size: %d\n", (int)g_mem.g_vaddr, mem_size);
break;
}
case MEM_ACCESS_GET_WKSRC_SRC:
{
void __iomem *vaddr = NULL;
// void __iomem *vaddr = NULL;
// vaddr = ioremap(WEIGHT_ADDR, sizeof(wakeupsrc));
// vaddr = ioremap_nocache(PHYS_ADDR, SIZE);
vaddr = memremap(WEIGHT_ADDR, M_PAGE_SIZE, MEMREMAP_WB);
if (!vaddr)
{
return -EINVAL;
}
wakeupsrc.readData[0] = readb(g_mem.g_vaddr);
wakeupsrc.readData[0] = readb(vaddr);
// memcpy_fromio(buffer, vaddr, SIZE);
// copy_to_user(arg, vaddr, SIZE) ?
// printk(KERN_EMERG "give wake up source:%d\n", wakeupsrc.readData[0]);
if (copy_to_user(arg, &wakeupsrc, sizeof(wakeupsrc)))
if (copy_to_user((void *)arg, &wakeupsrc, sizeof(wakeupsrc)))
{
// iounmap(vaddr);
memunmap(vaddr);
return -EINVAL;
}
// iounmap(vaddr);
memunmap(vaddr);
break;
}
case MEM_ACCESS_SET_WKSRC_SRC:
{
void __iomem *vaddr = NULL;
// void __iomem *vaddr = NULL;
if (copy_from_user(&wakeupsrc, (void __user *)arg, sizeof(wakeupsrc)))
{
return -EFAULT;
}
vaddr = memremap(WEIGHT_ADDR, M_PAGE_SIZE, MEMREMAP_WB);
if (!vaddr)
{
return -EINVAL;
}
writeb(wakeupsrc.readData[0], vaddr);
memunmap(vaddr);
writeb(wakeupsrc.readData[0], g_mem.g_vaddr);
// printk(KERN_EMERG "set wake up source:%d\n", wakeupsrc.readData[0]);
break;
@ -167,8 +185,31 @@ static struct file_operations mem_operation_drv = {
static int __init mem_operation_init(void)
{
int err;
struct device_node *np;
struct resource res;
printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
np = of_find_compatible_node(NULL, NULL, "wakeup-src");
if (!np) {
pr_err("mem Reserved memory node not found\n");
return -ENODEV;
}
if (of_address_to_resource(np, 0, &res)) {
pr_err("mem Failed to parse reg\n");
of_node_put(np);
return -EFAULT;
}
g_mem.len = resource_size(&res);
g_mem.g_vaddr = memremap(res.start, g_mem.len, MEMREMAP_WB);
if (!g_mem.g_vaddr)
{
return -EINVAL;
}
#ifdef CONFIG_XR806_WLAN
writeb(0, g_mem.g_vaddr); // 如果xr806而非boot0获取唤醒源需要先设默认值
#endif
atomic_set(&g_mem.init_flag, 1);
// printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
major = register_chrdev(0, "mem_operation", &mem_operation_drv); /* /dev/mem_operation */
mem_operation_class = class_create(THIS_MODULE, "mem_operation_class");
@ -176,6 +217,7 @@ static int __init mem_operation_init(void)
if (IS_ERR(mem_operation_class)) {
printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
unregister_chrdev(major, "mem_operation");
memunmap(g_mem.g_vaddr);
return -1;
}
@ -190,8 +232,13 @@ static void __exit mem_operation_exit(void)
device_destroy(mem_operation_class, MKDEV(major, 0));
class_destroy(mem_operation_class);
unregister_chrdev(major, "mem_operation");
if (atomic_read(&g_mem.init_flag) == 1)
{
memunmap(g_mem.g_vaddr);
}
}
module_init(mem_operation_init);
// 注意放在disp之前
fs_initcall_sync(mem_operation_init);
module_exit(mem_operation_exit);
MODULE_LICENSE("GPL");