mirror of https://github.com/OpenIPC/firmware.git
108 lines
2.7 KiB
Diff
108 lines
2.7 KiB
Diff
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 <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 + 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);
|