brintos

brintos / linux-shallow public Read only

0
0
Text · 8.3 KiB · dbcaac8 Raw
269 lines · c
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)2//3// This file is provided under a dual BSD/GPLv2 license. When using or4// redistributing this file, you may do so under either license.5//6// Copyright(c) 2022 Advanced Micro Devices, Inc.7//8// Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>9//	    V sujith kumar Reddy <Vsujithkumar.Reddy@amd.com>10 11/* ACP-specific Common code */12 13#include "../sof-priv.h"14#include "../sof-audio.h"15#include "../ops.h"16#include "acp.h"17#include "acp-dsp-offset.h"18#include <sound/sof/xtensa.h>19 20/**21 * amd_sof_ipc_dump() - This function is called when IPC tx times out.22 * @sdev: SOF device.23 */24void amd_sof_ipc_dump(struct snd_sof_dev *sdev)25{26	const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);27	u32 base = desc->dsp_intr_base;28	u32 dsp_msg_write = sdev->debug_box.offset +29			    offsetof(struct scratch_ipc_conf, sof_dsp_msg_write);30	u32 dsp_ack_write = sdev->debug_box.offset +31			    offsetof(struct scratch_ipc_conf, sof_dsp_ack_write);32	u32 host_msg_write = sdev->debug_box.offset +33			     offsetof(struct scratch_ipc_conf, sof_host_msg_write);34	u32 host_ack_write = sdev->debug_box.offset +35			     offsetof(struct scratch_ipc_conf, sof_host_ack_write);36	u32 dsp_msg, dsp_ack, host_msg, host_ack, irq_stat;37 38	dsp_msg = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + dsp_msg_write);39	dsp_ack = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + dsp_ack_write);40	host_msg = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + host_msg_write);41	host_ack = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + host_ack_write);42	irq_stat = snd_sof_dsp_read(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET);43 44	dev_err(sdev->dev,45		"dsp_msg = %#x dsp_ack = %#x host_msg = %#x host_ack = %#x irq_stat = %#x\n",46		dsp_msg, dsp_ack, host_msg, host_ack, irq_stat);47}48 49/**50 * amd_get_registers() - This function is called in case of DSP oops51 * in order to gather information about the registers, filename and52 * linenumber and stack.53 * @sdev: SOF device.54 * @xoops: Stores information about registers.55 * @panic_info: Stores information about filename and line number.56 * @stack: Stores the stack dump.57 * @stack_words: Size of the stack dump.58 */59static void amd_get_registers(struct snd_sof_dev *sdev,60			      struct sof_ipc_dsp_oops_xtensa *xoops,61			      struct sof_ipc_panic_info *panic_info,62			      u32 *stack, size_t stack_words)63{64	u32 offset = sdev->dsp_oops_offset;65 66	/* first read registers */67	acp_mailbox_read(sdev, offset, xoops, sizeof(*xoops));68 69	/* then get panic info */70	if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) {71		dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n",72			xoops->arch_hdr.totalsize);73		return;74	}75 76	offset += xoops->arch_hdr.totalsize;77	acp_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));78 79	/* then get the stack */80	offset += sizeof(*panic_info);81	acp_mailbox_read(sdev, offset, stack, stack_words * sizeof(u32));82}83 84/**85 * amd_sof_dump() - This function is called when a panic message is86 * received from the firmware.87 * @sdev: SOF device.88 * @flags: parameter not used but required by ops prototype89 */90void amd_sof_dump(struct snd_sof_dev *sdev, u32 flags)91{92	struct sof_ipc_dsp_oops_xtensa xoops;93	struct sof_ipc_panic_info panic_info;94	u32 stack[AMD_STACK_DUMP_SIZE];95	u32 status;96 97	/* Get information about the panic status from the debug box area.98	 * Compute the trace point based on the status.99	 */100	if (sdev->dsp_oops_offset > sdev->debug_box.offset) {101		acp_mailbox_read(sdev, sdev->debug_box.offset, &status, sizeof(u32));102	} else {103		/* Read DSP Panic status from dsp_box.104		 * As window information for exception box offset and size is not available105		 * before FW_READY106		 */107		acp_mailbox_read(sdev, sdev->dsp_box.offset, &status, sizeof(u32));108		sdev->dsp_oops_offset = sdev->dsp_box.offset + sizeof(status);109	}110 111	/* Get information about the registers, the filename and line112	 * number and the stack.113	 */114	amd_get_registers(sdev, &xoops, &panic_info, stack, AMD_STACK_DUMP_SIZE);115 116	/* Print the information to the console */117	sof_print_oops_and_stack(sdev, KERN_ERR, status, status, &xoops,118				 &panic_info, stack, AMD_STACK_DUMP_SIZE);119}120 121#if IS_ENABLED(CONFIG_SND_SOC_SOF_AMD_SOUNDWIRE)122static int amd_sof_sdw_get_slave_info(struct snd_sof_dev *sdev)123{124	struct acp_dev_data *acp_data = sdev->pdata->hw_pdata;125 126	return sdw_amd_get_slave_info(acp_data->sdw);127}128 129static struct snd_soc_acpi_mach *amd_sof_sdw_machine_select(struct snd_sof_dev *sdev)130{131	struct snd_soc_acpi_mach *mach;132	const struct snd_soc_acpi_link_adr *link;133	struct acp_dev_data *acp_data = sdev->pdata->hw_pdata;134	int ret, i;135 136	if (acp_data->info.count) {137		ret = amd_sof_sdw_get_slave_info(sdev);138		if (ret) {139			dev_info(sdev->dev, "failed to read slave information\n");140			return NULL;141		}142		for (mach = sdev->pdata->desc->alt_machines; mach; mach++) {143			if (!mach->links)144				break;145			link = mach->links;146			for (i = 0; i < acp_data->info.count && link->num_adr; link++, i++) {147				if (!snd_soc_acpi_sdw_link_slaves_found(sdev->dev, link,148									acp_data->sdw->ids,149									acp_data->sdw->num_slaves))150					break;151			}152			if (i == acp_data->info.count || !link->num_adr)153				break;154		}155		if (mach && mach->link_mask) {156			mach->mach_params.subsystem_rev = acp_data->pci_rev;157			mach->mach_params.links = mach->links;158			mach->mach_params.link_mask = mach->link_mask;159			mach->mach_params.platform = dev_name(sdev->dev);160			return mach;161		}162	}163	dev_info(sdev->dev, "No SoundWire machine driver found\n");164	return NULL;165}166 167#else168static struct snd_soc_acpi_mach *amd_sof_sdw_machine_select(struct snd_sof_dev *sdev)169{170	return NULL;171}172#endif173 174struct snd_soc_acpi_mach *amd_sof_machine_select(struct snd_sof_dev *sdev)175{176	struct snd_sof_pdata *sof_pdata = sdev->pdata;177	struct acp_dev_data *acp_data = sdev->pdata->hw_pdata;178	const struct sof_dev_desc *desc = sof_pdata->desc;179	struct snd_soc_acpi_mach *mach = NULL;180 181	if (desc->machines)182		mach = snd_soc_acpi_find_machine(desc->machines);183	if (!mach) {184		mach = amd_sof_sdw_machine_select(sdev);185		if (!mach) {186			dev_warn(sdev->dev, "No matching ASoC machine driver found\n");187			return NULL;188		}189	}190 191	mach->mach_params.subsystem_rev = acp_data->pci_rev;192	sof_pdata->tplg_filename = mach->sof_tplg_filename;193	sof_pdata->fw_filename = mach->fw_filename;194 195	return mach;196}197 198/* AMD Common DSP ops */199const struct snd_sof_dsp_ops sof_acp_common_ops = {200	/* probe and remove */201	.probe			= amd_sof_acp_probe,202	.remove			= amd_sof_acp_remove,203 204	/* Register IO */205	.write			= sof_io_write,206	.read			= sof_io_read,207 208	/* Block IO */209	.block_read		= acp_dsp_block_read,210	.block_write		= acp_dsp_block_write,211 212	/*Firmware loading */213	.load_firmware		= snd_sof_load_firmware_memcpy,214	.pre_fw_run		= acp_dsp_pre_fw_run,215	.get_bar_index		= acp_get_bar_index,216 217	/* DSP core boot */218	.run			= acp_sof_dsp_run,219 220	/*IPC */221	.send_msg		= acp_sof_ipc_send_msg,222	.ipc_msg_data		= acp_sof_ipc_msg_data,223	.set_stream_data_offset = acp_set_stream_data_offset,224	.get_mailbox_offset	= acp_sof_ipc_get_mailbox_offset,225	.get_window_offset      = acp_sof_ipc_get_window_offset,226	.irq_thread		= acp_sof_ipc_irq_thread,227 228	/* stream callbacks */229	.pcm_open		= acp_pcm_open,230	.pcm_close		= acp_pcm_close,231	.pcm_hw_params		= acp_pcm_hw_params,232	.pcm_pointer		= acp_pcm_pointer,233 234	.hw_info		= SNDRV_PCM_INFO_MMAP |235				  SNDRV_PCM_INFO_MMAP_VALID |236				  SNDRV_PCM_INFO_INTERLEAVED |237				  SNDRV_PCM_INFO_PAUSE |238				  SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,239 240	/* Machine driver callbacks */241	.machine_select		= amd_sof_machine_select,242	.machine_register	= sof_machine_register,243	.machine_unregister	= sof_machine_unregister,244 245	/* Trace Logger */246	.trace_init		= acp_sof_trace_init,247	.trace_release		= acp_sof_trace_release,248 249	/* PM */250	.suspend                = amd_sof_acp_suspend,251	.resume                 = amd_sof_acp_resume,252 253	.ipc_dump		= amd_sof_ipc_dump,254	.dbg_dump		= amd_sof_dump,255	.debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem,256	.dsp_arch_ops = &sof_xtensa_arch_ops,257 258	/* probe client device registation */259	.register_ipc_clients = acp_probes_register,260	.unregister_ipc_clients = acp_probes_unregister,261};262EXPORT_SYMBOL_NS(sof_acp_common_ops, SND_SOC_SOF_AMD_COMMON);263 264MODULE_LICENSE("Dual BSD/GPL");265MODULE_DESCRIPTION("ACP SOF COMMON Driver");266MODULE_IMPORT_NS(SND_SOC_SOF_AMD_COMMON);267MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);268MODULE_IMPORT_NS(SOUNDWIRE_AMD_INIT);269