From a4898f396561e41410cfed2bac5fcb593d2efc77 Mon Sep 17 00:00:00 2001 From: Johan Palsson Date: Mon, 24 Oct 2011 11:37:11 +0200 Subject: mach-ux500: Save dbx500 registers on crash Reads specific DBx500 register in case of kernel crash and saves it in kernel system memory. ST-Ericsson ID: 367366 ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson Linux next: N/A Change-Id: Ib8da2ab5eaad57b780c00aad495c5d689b081460 Signed-off-by: Johan Bjornstedt Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/34368 Reviewed-by: Jonas ABERG --- arch/arm/mach-ux500/Kconfig | 8 +++ arch/arm/mach-ux500/Makefile | 1 + arch/arm/mach-ux500/dbx500_dump.c | 135 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 arch/arm/mach-ux500/dbx500_dump.c (limited to 'arch') diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index 1f19ebe9aa2..27ff6c55bc1 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -149,6 +149,14 @@ config UX500_L2X0_PREFETCH_CTRL Adds interface to control instruction and data prefetch. Communication with Trustzone is done through TEE driver. +config UX500_DB_DUMP + bool "DBx500 register dump on crash" + depends on (UX500_SOC_DB8500 || UX500_SOC_DB5500) + default y + help + Reads specific DBx500 register in case of kernel crash + and saves it. + source "arch/arm/mach-ux500/Kconfig-arch" source "arch/arm/mach-ux500/pm/Kconfig" diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 07988f6f823..8e8fafae775 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_HWMEM) += hwmem-int.o obj-$(CONFIG_UX500_L2X0_PREFETCH_CTRL) += l2x0-prefetch.o obj-$(CONFIG_AB5500_BM) += board-u5500-bm.o obj-$(CONFIG_DBX500_PRCMU_DEBUG) += prcmu-debug.o +obj-$(CONFIG_UX500_DB_DUMP) += dbx500_dump.o ifeq ($(CONFIG_UX500_SOC_DB8500), y) obj-$(CONFIG_STM_TRACE) += board-mop500-stm.o endif diff --git a/arch/arm/mach-ux500/dbx500_dump.c b/arch/arm/mach-ux500/dbx500_dump.c new file mode 100644 index 00000000000..ca2691d204b --- /dev/null +++ b/arch/arm/mach-ux500/dbx500_dump.c @@ -0,0 +1,135 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License Terms: GNU General Public License v2 + * Author: Johan Bjornstedt + * + * Save DBx500 registers in case of kernel crash + */ +#include +#include +#include +#include +#include + +#include +#include + +struct dbx500_dump_info { + char *name; + int *data; + int *io_addr; + int phy_addr; + int size; +}; + +static struct dbx500_dump_info db8500_dump[] = { + { + .name = "prcmu_tcdm", + .phy_addr = U8500_PRCMU_TCDM_BASE, + .size = 0x1000, + }, + { + .name = "prcmu_non_sec_1", + .phy_addr = U8500_PRCMU_BASE, + .size = 0x340, + }, + { + .name = "prcmu_pmb", + .phy_addr = (U8500_PRCMU_BASE + 0x344), + .size = 0xC, + }, + { + .name = "prcmu_thermal", + .phy_addr = (U8500_PRCMU_BASE + 0x3C0), + .size = 0x40, + }, + { + .name = "prcmu_non_sec_2", + .phy_addr = (U8500_PRCMU_BASE + 0x404), + .size = 0x1FC, + }, + { + .name = "prcmu_icn_pmu", + .phy_addr = (U8500_PRCMU_BASE + 0xE00), + .size = 0x118, + }, +}; + +static struct dbx500_dump_info db5500_dump[] = { + {}, +}; + +static struct dbx500_dump_info *dbx500_dump; +static int dbx500_dump_size; + +static int crash_notifier(struct notifier_block *nb, unsigned long val, + void *data) +{ + int i; + + pr_info("dbx500_dump notified of crash\n"); + + for (i = 0; i < dbx500_dump_size; i++) { + memcpy_fromio(dbx500_dump[i].data, dbx500_dump[i].io_addr, + dbx500_dump[i].size); + } + + return 0; +} + +static void __init init_io_addresses(void) +{ + int i; + + for (i = 0; i < dbx500_dump_size; i++) + dbx500_dump[i].io_addr = __io_address(dbx500_dump[i].phy_addr); +} + +static struct notifier_block die_notifier = { + .notifier_call = crash_notifier, + .priority = 0, +}; + +int __init dbx500_dump_init(void) +{ + int err, i; + + if (cpu_is_u5500()) { + dbx500_dump = db5500_dump; + dbx500_dump_size = ARRAY_SIZE(db5500_dump); + } else if (cpu_is_u8500()) { + dbx500_dump = db8500_dump; + dbx500_dump_size = ARRAY_SIZE(db8500_dump); + } else { + ux500_unknown_soc(); + } + + for (i = 0; i < dbx500_dump_size; i++) { + dbx500_dump[i].data = kmalloc(dbx500_dump[i].size, GFP_KERNEL); + if (!dbx500_dump[i].data) { + pr_err("dbx500_dump: Could not allocate memory for " + "%s\n", dbx500_dump[i].name); + err = -ENOMEM; + goto free_mem; + } + } + + init_io_addresses(); + + err = register_die_notifier(&die_notifier); + if (err != 0) { + pr_err("dbx500_dump: Unable to register a die notifier %d\n", + err); + goto free_mem; + } + pr_info("dbx500_dump: driver initialized\n"); + return err; + +free_mem: + for (i = i - 1; i >= 0; i--) + kfree(dbx500_dump[i].data); + + return err; +} +arch_initcall(dbx500_dump_init); -- cgit v1.2.3