0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/pci.h>
0012 #include "ops.h"
0013
0014 static
0015 bool snd_sof_pci_update_bits_unlocked(struct snd_sof_dev *sdev, u32 offset,
0016 u32 mask, u32 value)
0017 {
0018 struct pci_dev *pci = to_pci_dev(sdev->dev);
0019 unsigned int old, new;
0020 u32 ret = 0;
0021
0022 pci_read_config_dword(pci, offset, &ret);
0023 old = ret;
0024 dev_dbg(sdev->dev, "Debug PCIR: %8.8x at %8.8x\n", old & mask, offset);
0025
0026 new = (old & ~mask) | (value & mask);
0027
0028 if (old == new)
0029 return false;
0030
0031 pci_write_config_dword(pci, offset, new);
0032 dev_dbg(sdev->dev, "Debug PCIW: %8.8x at %8.8x\n", value,
0033 offset);
0034
0035 return true;
0036 }
0037
0038 bool snd_sof_pci_update_bits(struct snd_sof_dev *sdev, u32 offset,
0039 u32 mask, u32 value)
0040 {
0041 unsigned long flags;
0042 bool change;
0043
0044 spin_lock_irqsave(&sdev->hw_lock, flags);
0045 change = snd_sof_pci_update_bits_unlocked(sdev, offset, mask, value);
0046 spin_unlock_irqrestore(&sdev->hw_lock, flags);
0047 return change;
0048 }
0049 EXPORT_SYMBOL(snd_sof_pci_update_bits);
0050
0051 bool snd_sof_dsp_update_bits_unlocked(struct snd_sof_dev *sdev, u32 bar,
0052 u32 offset, u32 mask, u32 value)
0053 {
0054 unsigned int old, new;
0055 u32 ret;
0056
0057 ret = snd_sof_dsp_read(sdev, bar, offset);
0058
0059 old = ret;
0060 new = (old & ~mask) | (value & mask);
0061
0062 if (old == new)
0063 return false;
0064
0065 snd_sof_dsp_write(sdev, bar, offset, new);
0066
0067 return true;
0068 }
0069 EXPORT_SYMBOL(snd_sof_dsp_update_bits_unlocked);
0070
0071 bool snd_sof_dsp_update_bits64_unlocked(struct snd_sof_dev *sdev, u32 bar,
0072 u32 offset, u64 mask, u64 value)
0073 {
0074 u64 old, new;
0075
0076 old = snd_sof_dsp_read64(sdev, bar, offset);
0077
0078 new = (old & ~mask) | (value & mask);
0079
0080 if (old == new)
0081 return false;
0082
0083 snd_sof_dsp_write64(sdev, bar, offset, new);
0084
0085 return true;
0086 }
0087 EXPORT_SYMBOL(snd_sof_dsp_update_bits64_unlocked);
0088
0089
0090 bool snd_sof_dsp_update_bits(struct snd_sof_dev *sdev, u32 bar, u32 offset,
0091 u32 mask, u32 value)
0092 {
0093 unsigned long flags;
0094 bool change;
0095
0096 spin_lock_irqsave(&sdev->hw_lock, flags);
0097 change = snd_sof_dsp_update_bits_unlocked(sdev, bar, offset, mask,
0098 value);
0099 spin_unlock_irqrestore(&sdev->hw_lock, flags);
0100 return change;
0101 }
0102 EXPORT_SYMBOL(snd_sof_dsp_update_bits);
0103
0104 bool snd_sof_dsp_update_bits64(struct snd_sof_dev *sdev, u32 bar, u32 offset,
0105 u64 mask, u64 value)
0106 {
0107 unsigned long flags;
0108 bool change;
0109
0110 spin_lock_irqsave(&sdev->hw_lock, flags);
0111 change = snd_sof_dsp_update_bits64_unlocked(sdev, bar, offset, mask,
0112 value);
0113 spin_unlock_irqrestore(&sdev->hw_lock, flags);
0114 return change;
0115 }
0116 EXPORT_SYMBOL(snd_sof_dsp_update_bits64);
0117
0118 static
0119 void snd_sof_dsp_update_bits_forced_unlocked(struct snd_sof_dev *sdev, u32 bar,
0120 u32 offset, u32 mask, u32 value)
0121 {
0122 unsigned int old, new;
0123 u32 ret;
0124
0125 ret = snd_sof_dsp_read(sdev, bar, offset);
0126
0127 old = ret;
0128 new = (old & ~mask) | (value & mask);
0129
0130 snd_sof_dsp_write(sdev, bar, offset, new);
0131 }
0132
0133
0134 void snd_sof_dsp_update_bits_forced(struct snd_sof_dev *sdev, u32 bar,
0135 u32 offset, u32 mask, u32 value)
0136 {
0137 unsigned long flags;
0138
0139 spin_lock_irqsave(&sdev->hw_lock, flags);
0140 snd_sof_dsp_update_bits_forced_unlocked(sdev, bar, offset, mask, value);
0141 spin_unlock_irqrestore(&sdev->hw_lock, flags);
0142 }
0143 EXPORT_SYMBOL(snd_sof_dsp_update_bits_forced);
0144
0145
0146
0147
0148
0149
0150
0151 void snd_sof_dsp_panic(struct snd_sof_dev *sdev, u32 offset, bool non_recoverable)
0152 {
0153
0154
0155
0156
0157 if (!sdev->dsp_oops_offset)
0158 sdev->dsp_oops_offset = offset;
0159
0160
0161
0162
0163
0164 if (sdev->dsp_oops_offset != offset)
0165 dev_warn(sdev->dev,
0166 "%s: dsp_oops_offset %zu differs from panic offset %u\n",
0167 __func__, sdev->dsp_oops_offset, offset);
0168
0169
0170
0171
0172
0173
0174
0175 sdev->dbg_dump_printed = false;
0176 if (non_recoverable) {
0177 snd_sof_dsp_dbg_dump(sdev, "DSP panic!",
0178 SOF_DBG_DUMP_REGS | SOF_DBG_DUMP_MBOX);
0179 sof_set_fw_state(sdev, SOF_FW_CRASHED);
0180 sof_fw_trace_fw_crashed(sdev);
0181 } else {
0182 snd_sof_dsp_dbg_dump(sdev,
0183 "DSP panic (recovery will be attempted)",
0184 SOF_DBG_DUMP_REGS | SOF_DBG_DUMP_MBOX);
0185 }
0186 }
0187 EXPORT_SYMBOL(snd_sof_dsp_panic);