brintos

brintos / linux-shallow public Read only

0
0
Text · 4.8 KiB · bd52e7e Raw
188 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) 2018 Intel Corporation7//8// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>9//10 11#include <linux/pci.h>12#include "ops.h"13 14static15bool snd_sof_pci_update_bits_unlocked(struct snd_sof_dev *sdev, u32 offset,16				      u32 mask, u32 value)17{18	struct pci_dev *pci = to_pci_dev(sdev->dev);19	unsigned int old, new;20	u32 ret = 0;21 22	pci_read_config_dword(pci, offset, &ret);23	old = ret;24	dev_dbg(sdev->dev, "Debug PCIR: %8.8x at  %8.8x\n", old & mask, offset);25 26	new = (old & ~mask) | (value & mask);27 28	if (old == new)29		return false;30 31	pci_write_config_dword(pci, offset, new);32	dev_dbg(sdev->dev, "Debug PCIW: %8.8x at  %8.8x\n", value,33		offset);34 35	return true;36}37 38bool snd_sof_pci_update_bits(struct snd_sof_dev *sdev, u32 offset,39			     u32 mask, u32 value)40{41	unsigned long flags;42	bool change;43 44	spin_lock_irqsave(&sdev->hw_lock, flags);45	change = snd_sof_pci_update_bits_unlocked(sdev, offset, mask, value);46	spin_unlock_irqrestore(&sdev->hw_lock, flags);47	return change;48}49EXPORT_SYMBOL(snd_sof_pci_update_bits);50 51bool snd_sof_dsp_update_bits_unlocked(struct snd_sof_dev *sdev, u32 bar,52				      u32 offset, u32 mask, u32 value)53{54	unsigned int old, new;55	u32 ret;56 57	ret = snd_sof_dsp_read(sdev, bar, offset);58 59	old = ret;60	new = (old & ~mask) | (value & mask);61 62	if (old == new)63		return false;64 65	snd_sof_dsp_write(sdev, bar, offset, new);66 67	return true;68}69EXPORT_SYMBOL(snd_sof_dsp_update_bits_unlocked);70 71bool snd_sof_dsp_update_bits64_unlocked(struct snd_sof_dev *sdev, u32 bar,72					u32 offset, u64 mask, u64 value)73{74	u64 old, new;75 76	old = snd_sof_dsp_read64(sdev, bar, offset);77 78	new = (old & ~mask) | (value & mask);79 80	if (old == new)81		return false;82 83	snd_sof_dsp_write64(sdev, bar, offset, new);84 85	return true;86}87EXPORT_SYMBOL(snd_sof_dsp_update_bits64_unlocked);88 89/* This is for registers bits with attribute RWC */90bool snd_sof_dsp_update_bits(struct snd_sof_dev *sdev, u32 bar, u32 offset,91			     u32 mask, u32 value)92{93	unsigned long flags;94	bool change;95 96	spin_lock_irqsave(&sdev->hw_lock, flags);97	change = snd_sof_dsp_update_bits_unlocked(sdev, bar, offset, mask,98						  value);99	spin_unlock_irqrestore(&sdev->hw_lock, flags);100	return change;101}102EXPORT_SYMBOL(snd_sof_dsp_update_bits);103 104bool snd_sof_dsp_update_bits64(struct snd_sof_dev *sdev, u32 bar, u32 offset,105			       u64 mask, u64 value)106{107	unsigned long flags;108	bool change;109 110	spin_lock_irqsave(&sdev->hw_lock, flags);111	change = snd_sof_dsp_update_bits64_unlocked(sdev, bar, offset, mask,112						    value);113	spin_unlock_irqrestore(&sdev->hw_lock, flags);114	return change;115}116EXPORT_SYMBOL(snd_sof_dsp_update_bits64);117 118static119void snd_sof_dsp_update_bits_forced_unlocked(struct snd_sof_dev *sdev, u32 bar,120					     u32 offset, u32 mask, u32 value)121{122	unsigned int old, new;123	u32 ret;124 125	ret = snd_sof_dsp_read(sdev, bar, offset);126 127	old = ret;128	new = (old & ~mask) | (value & mask);129 130	snd_sof_dsp_write(sdev, bar, offset, new);131}132 133/* This is for registers bits with attribute RWC */134void snd_sof_dsp_update_bits_forced(struct snd_sof_dev *sdev, u32 bar,135				    u32 offset, u32 mask, u32 value)136{137	unsigned long flags;138 139	spin_lock_irqsave(&sdev->hw_lock, flags);140	snd_sof_dsp_update_bits_forced_unlocked(sdev, bar, offset, mask, value);141	spin_unlock_irqrestore(&sdev->hw_lock, flags);142}143EXPORT_SYMBOL(snd_sof_dsp_update_bits_forced);144 145/**146 * snd_sof_dsp_panic - handle a received DSP panic message147 * @sdev: Pointer to the device's sdev148 * @offset: offset of panic information149 * @non_recoverable: the panic is fatal, no recovery will be done by the caller150 */151void snd_sof_dsp_panic(struct snd_sof_dev *sdev, u32 offset, bool non_recoverable)152{153	/*154	 * if DSP is not ready and the dsp_oops_offset is not yet set, use the155	 * offset from the panic message.156	 */157	if (!sdev->dsp_oops_offset)158		sdev->dsp_oops_offset = offset;159 160	/*161	 * Print warning if the offset from the panic message differs from162	 * dsp_oops_offset163	 */164	if (sdev->dsp_oops_offset != offset)165		dev_warn(sdev->dev,166			 "%s: dsp_oops_offset %zu differs from panic offset %u\n",167			 __func__, sdev->dsp_oops_offset, offset);168 169	/*170	 * Set the fw_state to crashed only in case of non recoverable DSP panic171	 * event.172	 * Use different message within the snd_sof_dsp_dbg_dump() depending on173	 * the non_recoverable flag.174	 */175	sdev->dbg_dump_printed = false;176	if (non_recoverable) {177		snd_sof_dsp_dbg_dump(sdev, "DSP panic!",178				     SOF_DBG_DUMP_REGS | SOF_DBG_DUMP_MBOX);179		sof_set_fw_state(sdev, SOF_FW_CRASHED);180		sof_fw_trace_fw_crashed(sdev);181	} else {182		snd_sof_dsp_dbg_dump(sdev,183				     "DSP panic (recovery will be attempted)",184				     SOF_DBG_DUMP_REGS | SOF_DBG_DUMP_MBOX);185	}186}187EXPORT_SYMBOL(snd_sof_dsp_panic);188