sdk-hwV1.3/lichee/linux-4.9/drivers/soc/sunxi/sunxi-dump.c

104 lines
2.3 KiB
C
Raw Normal View History

2024-05-07 10:09:20 +00:00
/*
* drivers/soc/sunxi-dump.c
*
* Copyright(c) 2019-2020 Allwinnertech Co., Ltd.
* http://www.allwinnertech.com
*
* Allwinner sunxi crash dump debug
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/err.h>
#include <linux/slab.h>
#define SUNXI_DUMP_COMPATIBLE "sunxi-dump"
static LIST_HEAD(dump_group_list);
struct sunxi_dump_group {
char name[10];
u32 *reg_buf;
void __iomem *vir_base;
phys_addr_t phy_base;
u32 len;
struct list_head list;
};
int sunxi_dump_group_reg(struct sunxi_dump_group *group)
{
u32 *buf = group->reg_buf;
void __iomem *membase = group->vir_base;
u32 len = ALIGN(group->len, 4);
int i;
for (i = 0; i < len; i += 4)
*(buf++) = readl(membase + i);
return 0;
}
int sunxi_dump_group_dump(void)
{
struct sunxi_dump_group *dump_group;
list_for_each_entry(dump_group, &dump_group_list, list) {
sunxi_dump_group_reg(dump_group);
}
return 0;
}
EXPORT_SYMBOL(sunxi_dump_group_dump);
int sunxi_dump_group_register(const char *name, phys_addr_t start, u32 len)
{
struct sunxi_dump_group *dump_group = NULL;
dump_group = kmalloc(sizeof(struct sunxi_dump_group), GFP_KERNEL);
if (!dump_group)
return -ENOMEM;
memcpy(dump_group->name, name, sizeof(dump_group->name));
dump_group->phy_base = start;
dump_group->len = len;
dump_group->vir_base = ioremap(dump_group->phy_base, dump_group->len);
if (!dump_group->vir_base) {
pr_err("%s can't iomap\n", dump_group->name);
return -EINVAL;
}
dump_group->reg_buf = kmalloc(dump_group->len, GFP_KERNEL);
if (!dump_group->reg_buf)
return -ENOMEM;
list_add_tail(&dump_group->list, &dump_group_list);
return 0;
}
static int __init sunxi_dump_init(void)
{
struct device_node *node;
int i = 0;
const char *name = NULL;
struct resource res;
node = of_find_compatible_node(NULL, NULL, SUNXI_DUMP_COMPATIBLE);
for (i = 0; ; i++) {
if (of_address_to_resource(node, i, &res))
break;
if (of_property_read_string_index(node, "group-names",
i, &name))
break;
sunxi_dump_group_register(name, res.start, resource_size(&res));
}
return 0;
}
late_initcall(sunxi_dump_init);