ASoC: SOF: Move xtensa oops/stack dump out of SOF core

Move it to sof/xtensa/core.c

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig
index 0e2a262..640f805 100644
--- a/sound/soc/sof/Kconfig
+++ b/sound/soc/sof/Kconfig
@@ -43,3 +43,4 @@
           If unsure select "N".
 
 source "sound/soc/sof/intel/Kconfig"
+source "sound/soc/sof/xtensa/Kconfig"
diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile
index b759554..e081723 100644
--- a/sound/soc/sof/Makefile
+++ b/sound/soc/sof/Makefile
@@ -22,3 +22,4 @@
 obj-$(CONFIG_SND_SOC_SOF_SPIDSP) += snd-sof-spi.o
 
 obj-$(CONFIG_SND_SOC_SOF_INTEL)	+= intel/
+obj-$(CONFIG_SND_SOC_SOF_XTENSA) += xtensa/
diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c
index 1df5b95..8d57722 100644
--- a/sound/soc/sof/core.c
+++ b/sound/soc/sof/core.c
@@ -135,136 +135,6 @@ static const struct sof_panic_msg panic_msg[] = {
 	{SOF_IPC_PANIC_IDLE, "can't enter idle"},
 };
 
-struct sof_exception_cause {
-	u32 id;
-	const char *msg;
-	const char *description;
-};
-
-/* From 4.4.1.5 table 4-64 Exception Causes of
- * Xtensa Instruction Set Architecture (ISA) Reference Manual
- */
-static const struct sof_exception_cause xtensa_exception_causes[] = {
-	{0, "IllegalInstructionCause", "Illegal instruction"},
-	{1, "SyscallCause", "SYSCALL instruction"},
-	{2, "InstructionFetchErrorCause",
-	"Processor internal physical address or data error during instruction fetch"},
-	{3, "LoadStoreErrorCause",
-	"Processor internal physical address or data error during load or store"},
-	{4, "Level1InterruptCause",
-	"Level-1 interrupt as indicated by set level-1 bits in the INTERRUPT register"},
-	{5, "AllocaCause",
-	"MOVSP instruction, if caller’s registers are not in the register file"},
-	{6, "IntegerDivideByZeroCause",
-	"QUOS, QUOU, REMS, or REMU divisor operand is zero"},
-	{8, "PrivilegedCause",
-	"Attempt to execute a privileged operation when CRING ? 0"},
-	{9, "LoadStoreAlignmentCause", "Load or store to an unaligned address"},
-	{12, "InstrPIFDataErrorCause",
-	"PIF data error during instruction fetch"},
-	{13, "LoadStorePIFDataErrorCause",
-	"Synchronous PIF data error during LoadStore access"},
-	{14, "InstrPIFAddrErrorCause",
-	"PIF address error during instruction fetch"},
-	{15, "LoadStorePIFAddrErrorCause",
-	"Synchronous PIF address error during LoadStore access"},
-	{16, "InstTLBMissCause", "Error during Instruction TLB refill"},
-	{17, "InstTLBMultiHitCause",
-	"Multiple instruction TLB entries matched"},
-	{18, "InstFetchPrivilegeCause",
-	"An instruction fetch referenced a virtual address at a ring level less than CRING"},
-	{20, "InstFetchProhibitedCause",
-	"An instruction fetch referenced a page mapped with an attribute that does not permit instruction fetch"},
-	{24, "LoadStoreTLBMissCause",
-	"Error during TLB refill for a load or store"},
-	{25, "LoadStoreTLBMultiHitCause",
-	"Multiple TLB entries matched for a load or store"},
-	{26, "LoadStorePrivilegeCause",
-	"A load or store referenced a virtual address at a ring level less than CRING"},
-	{28, "LoadProhibitedCause",
-	"A load referenced a page mapped with an attribute that does not permit loads"},
-	{32, "Coprocessor0Disabled",
-	"Coprocessor 0 instruction when cp0 disabled"},
-	{33, "Coprocessor1Disabled",
-	"Coprocessor 1 instruction when cp1 disabled"},
-	{34, "Coprocessor2Disabled",
-	"Coprocessor 2 instruction when cp2 disabled"},
-	{35, "Coprocessor3Disabled",
-	"Coprocessor 3 instruction when cp3 disabled"},
-	{36, "Coprocessor4Disabled",
-	"Coprocessor 4 instruction when cp4 disabled"},
-	{37, "Coprocessor5Disabled",
-	"Coprocessor 5 instruction when cp5 disabled"},
-	{38, "Coprocessor6Disabled",
-	"Coprocessor 6 instruction when cp6 disabled"},
-	{39, "Coprocessor7Disabled",
-	"Coprocessor 7 instruction when cp7 disabled"},
-};
-
-/* only need xtensa atm */
-static void sof_arch_dsp_oops(struct snd_sof_dev *sdev, void *oops)
-{
-	struct sof_ipc_dsp_oops_xtensa *xoops = oops;
-	int i;
-
-	dev_err(sdev->dev, "error: DSP Firmware Oops\n");
-	for (i = 0; i < ARRAY_SIZE(xtensa_exception_causes); i++) {
-		if (xtensa_exception_causes[i].id == xoops->exccause) {
-			dev_err(sdev->dev, "error: Exception Cause: %s, %s\n",
-				xtensa_exception_causes[i].msg,
-				xtensa_exception_causes[i].description);
-		}
-	}
-	dev_err(sdev->dev, "EXCCAUSE 0x%8.8x EXCVADDR 0x%8.8x PS       0x%8.8x SAR     0x%8.8x\n",
-		xoops->exccause, xoops->excvaddr, xoops->ps, xoops->sar);
-	dev_err(sdev->dev, "EPC1     0x%8.8x EPC2     0x%8.8x EPC3     0x%8.8x EPC4    0x%8.8x",
-		xoops->epc1, xoops->epc2, xoops->epc3, xoops->epc4);
-	dev_err(sdev->dev, "EPC5     0x%8.8x EPC6     0x%8.8x EPC7     0x%8.8x DEPC    0x%8.8x",
-		xoops->epc5, xoops->epc6, xoops->epc7, xoops->depc);
-	dev_err(sdev->dev, "EPS2     0x%8.8x EPS3     0x%8.8x EPS4     0x%8.8x EPS5    0x%8.8x",
-		xoops->eps2, xoops->eps3, xoops->eps4, xoops->eps5);
-	dev_err(sdev->dev, "EPS6     0x%8.8x EPS7     0x%8.8x INTENABL 0x%8.8x INTERRU 0x%8.8x",
-		xoops->eps6, xoops->eps7, xoops->intenable, xoops->interrupt);
-}
-
-static void sof_dsp_dump_stack(struct snd_sof_dev *sdev, void *oops,
-			       u32 *stack, u32 stack_words)
-{
-	struct sof_ipc_dsp_oops_xtensa *xoops = oops;
-	u32 stack_ptr = xoops->stack;
-	int i;
-
-	dev_err(sdev->dev, "stack dump from 0x%8.8x\n", stack_ptr);
-
-	for (i = 0; i <= stack_words - 4; i += 4) {
-		dev_err(sdev->dev, "0x%8.8x: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n",
-			stack_ptr + i, stack[i], stack[i + 1], stack[i + 2],
-			stack[i + 3]);
-	}
-
-	/* deal with any remaining words */
-	switch (stack_words - i) {
-	case 0:
-		break;
-	case 1:
-		dev_err(sdev->dev, "0x%8.8x: 0x%8.8x\n",
-			stack_ptr + stack_words - 1, stack[stack_words - 1]);
-		break;
-	case 2:
-		dev_err(sdev->dev, "0x%8.8x: 0x%8.8x 0x%8.8x\n",
-			stack_ptr + stack_words - 2, stack[stack_words - 2],
-			stack[stack_words - 1]);
-		break;
-	case 3:
-		dev_err(sdev->dev, "0x%8.8x: 0x%8.8x 0x%8.8x 0x%8.8x\n",
-			stack_ptr + stack_words - 3, stack[stack_words - 3],
-			stack[stack_words - 2], stack[stack_words - 1]);
-		break;
-	default:
-		break;
-	}
-}
-
 int snd_sof_get_status(struct snd_sof_dev *sdev, u32 panic_code,
 		       u32 tracep_code, void *oops, void *stack,
 		       size_t stack_words)
@@ -296,8 +166,8 @@ int snd_sof_get_status(struct snd_sof_dev *sdev, u32 panic_code,
 	dev_err(sdev->dev, "error: trace point %8.8x\n", tracep_code);
 
 out:
-	sof_arch_dsp_oops(sdev, oops);
-	sof_dsp_dump_stack(sdev, oops, stack, stack_words);
+	sof_oops(sdev, oops);
+	sof_stack(sdev, oops, stack, stack_words);
 	return -EFAULT;
 }
 EXPORT_SYMBOL(snd_sof_get_status);
diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig
index 08f43e0..89cadbd 100644
--- a/sound/soc/sof/intel/Kconfig
+++ b/sound/soc/sof/intel/Kconfig
@@ -2,6 +2,7 @@
 	tristate "SOF support for Intel audio DSPs"
 	depends on SND_SOC_SOF
 	select SND_SOC_INTEL_MACH
+	select SND_SOC_SOF_XTENSA
 	help
           This adds support for Sound Open Firmware for Intel(R) platforms.
           Say Y if you have such a device.
diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c
index 3c80a83..55bb20d 100644
--- a/sound/soc/sof/intel/bdw.c
+++ b/sound/soc/sof/intel/bdw.c
@@ -600,6 +600,9 @@ static int bdw_probe(struct snd_sof_dev *sdev)
 	u32 base, size;
 	int ret = 0;
 
+	/* set DSP arch ops */
+	sdev->arch_ops = &sof_xtensa_arch_ops;
+
 	/* LPE base */
 	mmio = platform_get_resource(pdev, IORESOURCE_MEM,
 				     desc->resindex_lpe_base);
diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c
index ae65e7b..075d183 100644
--- a/sound/soc/sof/intel/byt.c
+++ b/sound/soc/sof/intel/byt.c
@@ -531,6 +531,9 @@ static int byt_acpi_probe(struct snd_sof_dev *sdev)
 	u32 base, size;
 	int ret = 0;
 
+	/* set DSP arch ops */
+	sdev->arch_ops = &sof_xtensa_arch_ops;
+
 	/* DSP DMA can only access low 31 bits of host memory */
 	ret = dma_coerce_mask_and_coherent(sdev->dev, DMA_BIT_MASK(31));
 	if (ret < 0) {
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index 20085cf..a275f8c 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -299,6 +299,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev)
 	int i;
 	int ret = 0;
 
+	/* set DSP arch ops */
+	sdev->arch_ops = &sof_xtensa_arch_ops;
+
 	chip = get_chip_info(sdev->pci->device);
 	if (!chip) {
 		dev_err(sdev->dev, "no such device supported, chip id:%x\n",
diff --git a/sound/soc/sof/intel/hsw.c b/sound/soc/sof/intel/hsw.c
index c47974f..7718929 100644
--- a/sound/soc/sof/intel/hsw.c
+++ b/sound/soc/sof/intel/hsw.c
@@ -601,6 +601,9 @@ static int hsw_probe(struct snd_sof_dev *sdev)
 	u32 base, size;
 	int ret = 0;
 
+	/* set DSP arch ops */
+	sdev->arch_ops = &sof_xtensa_arch_ops;
+
 	/* LPE base */
 	mmio = platform_get_resource(pdev, IORESOURCE_MEM,
 				     desc->resindex_lpe_base);
diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h
index f652f69..e0827b7 100644
--- a/sound/soc/sof/sof-priv.h
+++ b/sound/soc/sof/sof-priv.h
@@ -129,6 +129,12 @@ struct snd_sof_dsp_ops {
 	int (*trace_trigger)(struct snd_sof_dev *sdev, int cmd);
 };
 
+struct sof_arch_ops {
+	void (*dsp_oops)(struct snd_sof_dev *sdev, void *oops);
+	void (*dsp_stack)(struct snd_sof_dev *sdev, void *oops,
+			  u32 *stack, u32 stack_words);
+};
+
 struct snd_sof_pdata;
 
 struct sof_ops_table {
@@ -249,6 +255,7 @@ struct snd_sof_dev {
 	struct snd_sof_pdata *pdata;
 	const struct snd_sof_dsp_ops *ops;
 	struct sof_intel_hda_dev *hda;	/* for HDA based DSP HW */
+	const struct sof_arch_ops *arch_ops;
 
 	/* IPC */
 	struct snd_sof_ipc *ipc;
@@ -429,4 +436,21 @@ int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
 int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
 		      struct snd_ctl_elem_value *ucontrol);
 
+/*
+ * DSP Architectures.
+ */
+static inline void sof_stack(struct snd_sof_dev *sdev, void *oops, u32 *stack,
+			     u32 stack_words)
+{
+	if (sdev->arch_ops->dsp_stack)
+		sdev->arch_ops->dsp_stack(sdev, oops, stack, stack_words);
+}
+
+static inline void sof_oops(struct snd_sof_dev *sdev, void *oops)
+{
+	if (sdev->arch_ops->dsp_oops)
+		sdev->arch_ops->dsp_oops(sdev, oops);
+}
+
+extern const struct sof_arch_ops sof_xtensa_arch_ops;
 #endif
diff --git a/sound/soc/sof/xtensa/Kconfig b/sound/soc/sof/xtensa/Kconfig
new file mode 100644
index 0000000..f66f17b
--- /dev/null
+++ b/sound/soc/sof/xtensa/Kconfig
@@ -0,0 +1,3 @@
+config SND_SOC_SOF_XTENSA
+	tristate
+
diff --git a/sound/soc/sof/xtensa/Makefile b/sound/soc/sof/xtensa/Makefile
new file mode 100644
index 0000000..34b27be
--- /dev/null
+++ b/sound/soc/sof/xtensa/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+
+ccflags-y += -DDEBUG
+
+snd-sof-xtensa-dsp-objs := core.o
+
+obj-$(CONFIG_SND_SOC_SOF_XTENSA) += snd-sof-xtensa-dsp.o
diff --git a/sound/soc/sof/xtensa/core.c b/sound/soc/sof/xtensa/core.c
new file mode 100644
index 0000000..5ca9185
--- /dev/null
+++ b/sound/soc/sof/xtensa/core.c
@@ -0,0 +1,159 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * Copyright(c) 2018 Intel Corporation. All rights reserved.
+ *
+ * Author: Pan Xiuli <xiuli.pan@linux.intel.com>
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/sof.h>
+#include "../sof-priv.h"
+#include "../ops.h"
+
+struct xtensa_exception_cause {
+	u32 id;
+	const char *msg;
+	const char *description;
+};
+
+/* From 4.4.1.5 table 4-64 Exception Causes of
+ * Xtensa Instruction Set Architecture (ISA) Reference Manual
+ */
+static const struct xtensa_exception_cause xtensa_exception_causes[] = {
+	{0, "IllegalInstructionCause", "Illegal instruction"},
+	{1, "SyscallCause", "SYSCALL instruction"},
+	{2, "InstructionFetchErrorCause",
+	"Processor internal physical address or data error during instruction fetch"},
+	{3, "LoadStoreErrorCause",
+	"Processor internal physical address or data error during load or store"},
+	{4, "Level1InterruptCause",
+	"Level-1 interrupt as indicated by set level-1 bits in the INTERRUPT register"},
+	{5, "AllocaCause",
+	"MOVSP instruction, if caller’s registers are not in the register file"},
+	{6, "IntegerDivideByZeroCause",
+	"QUOS, QUOU, REMS, or REMU divisor operand is zero"},
+	{8, "PrivilegedCause",
+	"Attempt to execute a privileged operation when CRING ? 0"},
+	{9, "LoadStoreAlignmentCause", "Load or store to an unaligned address"},
+	{12, "InstrPIFDataErrorCause",
+	"PIF data error during instruction fetch"},
+	{13, "LoadStorePIFDataErrorCause",
+	"Synchronous PIF data error during LoadStore access"},
+	{14, "InstrPIFAddrErrorCause",
+	"PIF address error during instruction fetch"},
+	{15, "LoadStorePIFAddrErrorCause",
+	"Synchronous PIF address error during LoadStore access"},
+	{16, "InstTLBMissCause", "Error during Instruction TLB refill"},
+	{17, "InstTLBMultiHitCause",
+	"Multiple instruction TLB entries matched"},
+	{18, "InstFetchPrivilegeCause",
+	"An instruction fetch referenced a virtual address at a ring level less than CRING"},
+	{20, "InstFetchProhibitedCause",
+	"An instruction fetch referenced a page mapped with an attribute that does not permit instruction fetch"},
+	{24, "LoadStoreTLBMissCause",
+	"Error during TLB refill for a load or store"},
+	{25, "LoadStoreTLBMultiHitCause",
+	"Multiple TLB entries matched for a load or store"},
+	{26, "LoadStorePrivilegeCause",
+	"A load or store referenced a virtual address at a ring level less than CRING"},
+	{28, "LoadProhibitedCause",
+	"A load referenced a page mapped with an attribute that does not permit loads"},
+	{32, "Coprocessor0Disabled",
+	"Coprocessor 0 instruction when cp0 disabled"},
+	{33, "Coprocessor1Disabled",
+	"Coprocessor 1 instruction when cp1 disabled"},
+	{34, "Coprocessor2Disabled",
+	"Coprocessor 2 instruction when cp2 disabled"},
+	{35, "Coprocessor3Disabled",
+	"Coprocessor 3 instruction when cp3 disabled"},
+	{36, "Coprocessor4Disabled",
+	"Coprocessor 4 instruction when cp4 disabled"},
+	{37, "Coprocessor5Disabled",
+	"Coprocessor 5 instruction when cp5 disabled"},
+	{38, "Coprocessor6Disabled",
+	"Coprocessor 6 instruction when cp6 disabled"},
+	{39, "Coprocessor7Disabled",
+	"Coprocessor 7 instruction when cp7 disabled"},
+};
+
+/* only need xtensa atm */
+static void xtensa_dsp_oops(struct snd_sof_dev *sdev, void *oops)
+{
+	struct sof_ipc_dsp_oops_xtensa *xoops = oops;
+	int i;
+
+	dev_err(sdev->dev, "error: DSP Firmware Oops\n");
+	for (i = 0; i < ARRAY_SIZE(xtensa_exception_causes); i++) {
+		if (xtensa_exception_causes[i].id == xoops->exccause) {
+			dev_err(sdev->dev, "error: Exception Cause: %s, %s\n",
+				xtensa_exception_causes[i].msg,
+				xtensa_exception_causes[i].description);
+		}
+	}
+	dev_err(sdev->dev, "EXCCAUSE 0x%8.8x EXCVADDR 0x%8.8x PS       0x%8.8x SAR     0x%8.8x\n",
+		xoops->exccause, xoops->excvaddr, xoops->ps, xoops->sar);
+	dev_err(sdev->dev, "EPC1     0x%8.8x EPC2     0x%8.8x EPC3     0x%8.8x EPC4    0x%8.8x",
+		xoops->epc1, xoops->epc2, xoops->epc3, xoops->epc4);
+	dev_err(sdev->dev, "EPC5     0x%8.8x EPC6     0x%8.8x EPC7     0x%8.8x DEPC    0x%8.8x",
+		xoops->epc5, xoops->epc6, xoops->epc7, xoops->depc);
+	dev_err(sdev->dev, "EPS2     0x%8.8x EPS3     0x%8.8x EPS4     0x%8.8x EPS5    0x%8.8x",
+		xoops->eps2, xoops->eps3, xoops->eps4, xoops->eps5);
+	dev_err(sdev->dev, "EPS6     0x%8.8x EPS7     0x%8.8x INTENABL 0x%8.8x INTERRU 0x%8.8x",
+		xoops->eps6, xoops->eps7, xoops->intenable, xoops->interrupt);
+}
+
+static void xtensa_stack(struct snd_sof_dev *sdev, void *oops, u32 *stack,
+			 u32 stack_words)
+{
+	struct sof_ipc_dsp_oops_xtensa *xoops = oops;
+	u32 stack_ptr = xoops->stack;
+	int i;
+
+	dev_err(sdev->dev, "stack dump from 0x%8.8x\n", stack_ptr);
+
+	for (i = 0; i <= stack_words - 4; i += 4) {
+		dev_err(sdev->dev, "0x%8.8x: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n",
+			stack_ptr + i, stack[i], stack[i + 1], stack[i + 2],
+			stack[i + 3]);
+	}
+
+	/* deal with any remaining words */
+	switch (stack_words - i) {
+	case 0:
+		break;
+	case 1:
+		dev_err(sdev->dev, "0x%8.8x: 0x%8.8x\n",
+			stack_ptr + stack_words - 1, stack[stack_words - 1]);
+		break;
+	case 2:
+		dev_err(sdev->dev, "0x%8.8x: 0x%8.8x 0x%8.8x\n",
+			stack_ptr + stack_words - 2, stack[stack_words - 2],
+			stack[stack_words - 1]);
+		break;
+	case 3:
+		dev_err(sdev->dev, "0x%8.8x: 0x%8.8x 0x%8.8x 0x%8.8x\n",
+			stack_ptr + stack_words - 3, stack[stack_words - 3],
+			stack[stack_words - 2], stack[stack_words - 1]);
+		break;
+	default:
+		break;
+	}
+}
+
+const struct sof_arch_ops sof_xtensa_arch_ops = {
+	.dsp_oops = xtensa_dsp_oops,
+	.dsp_stack = xtensa_stack,
+};
+EXPORT_SYMBOL(sof_xtensa_arch_ops);
+
+MODULE_DESCRIPTION("SOF Xtensa DSP support");
+MODULE_LICENSE("Dual BSD/GPL");