diff -drupN a/drivers/soc/sunxi/sunxi-dump.c b/drivers/soc/sunxi/sunxi-dump.c --- a/drivers/soc/sunxi/sunxi-dump.c 1970-01-01 03:00:00.000000000 +0300 +++ b/drivers/soc/sunxi/sunxi-dump.c 2022-06-12 05:28:14.000000000 +0300 @@ -0,0 +1,103 @@ +/* + * 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 +#include +#include +#include +#include + +#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 + i) = 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);