1d1d95fcbSLiam Girdwood // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) 2d1d95fcbSLiam Girdwood // 3d1d95fcbSLiam Girdwood // This file is provided under a dual BSD/GPLv2 license. When using or 4d1d95fcbSLiam Girdwood // redistributing this file, you may do so under either license. 5d1d95fcbSLiam Girdwood // 6d1d95fcbSLiam Girdwood // Copyright(c) 2018 Intel Corporation. All rights reserved. 7d1d95fcbSLiam Girdwood // 8d1d95fcbSLiam Girdwood // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> 9d1d95fcbSLiam Girdwood // 10d1d95fcbSLiam Girdwood 11d1d95fcbSLiam Girdwood #include <linux/pci.h> 12d1d95fcbSLiam Girdwood #include "ops.h" 13d1d95fcbSLiam Girdwood 14d1d95fcbSLiam Girdwood static 15d1d95fcbSLiam Girdwood bool snd_sof_pci_update_bits_unlocked(struct snd_sof_dev *sdev, u32 offset, 16d1d95fcbSLiam Girdwood u32 mask, u32 value) 17d1d95fcbSLiam Girdwood { 18d1d95fcbSLiam Girdwood struct pci_dev *pci = to_pci_dev(sdev->dev); 19d1d95fcbSLiam Girdwood unsigned int old, new; 20c41d384cSTakashi Iwai u32 ret = 0; 21d1d95fcbSLiam Girdwood 22d1d95fcbSLiam Girdwood pci_read_config_dword(pci, offset, &ret); 23d1d95fcbSLiam Girdwood old = ret; 24d1d95fcbSLiam Girdwood dev_dbg(sdev->dev, "Debug PCIR: %8.8x at %8.8x\n", old & mask, offset); 25d1d95fcbSLiam Girdwood 26d1d95fcbSLiam Girdwood new = (old & ~mask) | (value & mask); 27d1d95fcbSLiam Girdwood 28d1d95fcbSLiam Girdwood if (old == new) 29d1d95fcbSLiam Girdwood return false; 30d1d95fcbSLiam Girdwood 31d1d95fcbSLiam Girdwood pci_write_config_dword(pci, offset, new); 32d1d95fcbSLiam Girdwood dev_dbg(sdev->dev, "Debug PCIW: %8.8x at %8.8x\n", value, 33d1d95fcbSLiam Girdwood offset); 34d1d95fcbSLiam Girdwood 35d1d95fcbSLiam Girdwood return true; 36d1d95fcbSLiam Girdwood } 37d1d95fcbSLiam Girdwood 38d1d95fcbSLiam Girdwood bool snd_sof_pci_update_bits(struct snd_sof_dev *sdev, u32 offset, 39d1d95fcbSLiam Girdwood u32 mask, u32 value) 40d1d95fcbSLiam Girdwood { 41d1d95fcbSLiam Girdwood unsigned long flags; 42d1d95fcbSLiam Girdwood bool change; 43d1d95fcbSLiam Girdwood 44d1d95fcbSLiam Girdwood spin_lock_irqsave(&sdev->hw_lock, flags); 45d1d95fcbSLiam Girdwood change = snd_sof_pci_update_bits_unlocked(sdev, offset, mask, value); 46d1d95fcbSLiam Girdwood spin_unlock_irqrestore(&sdev->hw_lock, flags); 47d1d95fcbSLiam Girdwood return change; 48d1d95fcbSLiam Girdwood } 49d1d95fcbSLiam Girdwood EXPORT_SYMBOL(snd_sof_pci_update_bits); 50d1d95fcbSLiam Girdwood 51d1d95fcbSLiam Girdwood bool snd_sof_dsp_update_bits_unlocked(struct snd_sof_dev *sdev, u32 bar, 52d1d95fcbSLiam Girdwood u32 offset, u32 mask, u32 value) 53d1d95fcbSLiam Girdwood { 54d1d95fcbSLiam Girdwood unsigned int old, new; 55d1d95fcbSLiam Girdwood u32 ret; 56d1d95fcbSLiam Girdwood 57d1d95fcbSLiam Girdwood ret = snd_sof_dsp_read(sdev, bar, offset); 58d1d95fcbSLiam Girdwood 59d1d95fcbSLiam Girdwood old = ret; 60d1d95fcbSLiam Girdwood new = (old & ~mask) | (value & mask); 61d1d95fcbSLiam Girdwood 62d1d95fcbSLiam Girdwood if (old == new) 63d1d95fcbSLiam Girdwood return false; 64d1d95fcbSLiam Girdwood 65d1d95fcbSLiam Girdwood snd_sof_dsp_write(sdev, bar, offset, new); 66d1d95fcbSLiam Girdwood 67d1d95fcbSLiam Girdwood return true; 68d1d95fcbSLiam Girdwood } 69d1d95fcbSLiam Girdwood EXPORT_SYMBOL(snd_sof_dsp_update_bits_unlocked); 70d1d95fcbSLiam Girdwood 71d1d95fcbSLiam Girdwood bool snd_sof_dsp_update_bits64_unlocked(struct snd_sof_dev *sdev, u32 bar, 72d1d95fcbSLiam Girdwood u32 offset, u64 mask, u64 value) 73d1d95fcbSLiam Girdwood { 74d1d95fcbSLiam Girdwood u64 old, new; 75d1d95fcbSLiam Girdwood 76d1d95fcbSLiam Girdwood old = snd_sof_dsp_read64(sdev, bar, offset); 77d1d95fcbSLiam Girdwood 78d1d95fcbSLiam Girdwood new = (old & ~mask) | (value & mask); 79d1d95fcbSLiam Girdwood 80d1d95fcbSLiam Girdwood if (old == new) 81d1d95fcbSLiam Girdwood return false; 82d1d95fcbSLiam Girdwood 83d1d95fcbSLiam Girdwood snd_sof_dsp_write64(sdev, bar, offset, new); 84d1d95fcbSLiam Girdwood 85d1d95fcbSLiam Girdwood return true; 86d1d95fcbSLiam Girdwood } 87d1d95fcbSLiam Girdwood EXPORT_SYMBOL(snd_sof_dsp_update_bits64_unlocked); 88d1d95fcbSLiam Girdwood 89d1d95fcbSLiam Girdwood /* This is for registers bits with attribute RWC */ 90d1d95fcbSLiam Girdwood bool snd_sof_dsp_update_bits(struct snd_sof_dev *sdev, u32 bar, u32 offset, 91d1d95fcbSLiam Girdwood u32 mask, u32 value) 92d1d95fcbSLiam Girdwood { 93d1d95fcbSLiam Girdwood unsigned long flags; 94d1d95fcbSLiam Girdwood bool change; 95d1d95fcbSLiam Girdwood 96d1d95fcbSLiam Girdwood spin_lock_irqsave(&sdev->hw_lock, flags); 97d1d95fcbSLiam Girdwood change = snd_sof_dsp_update_bits_unlocked(sdev, bar, offset, mask, 98d1d95fcbSLiam Girdwood value); 99d1d95fcbSLiam Girdwood spin_unlock_irqrestore(&sdev->hw_lock, flags); 100d1d95fcbSLiam Girdwood return change; 101d1d95fcbSLiam Girdwood } 102d1d95fcbSLiam Girdwood EXPORT_SYMBOL(snd_sof_dsp_update_bits); 103d1d95fcbSLiam Girdwood 104d1d95fcbSLiam Girdwood bool snd_sof_dsp_update_bits64(struct snd_sof_dev *sdev, u32 bar, u32 offset, 105d1d95fcbSLiam Girdwood u64 mask, u64 value) 106d1d95fcbSLiam Girdwood { 107d1d95fcbSLiam Girdwood unsigned long flags; 108d1d95fcbSLiam Girdwood bool change; 109d1d95fcbSLiam Girdwood 110d1d95fcbSLiam Girdwood spin_lock_irqsave(&sdev->hw_lock, flags); 111d1d95fcbSLiam Girdwood change = snd_sof_dsp_update_bits64_unlocked(sdev, bar, offset, mask, 112d1d95fcbSLiam Girdwood value); 113d1d95fcbSLiam Girdwood spin_unlock_irqrestore(&sdev->hw_lock, flags); 114d1d95fcbSLiam Girdwood return change; 115d1d95fcbSLiam Girdwood } 116d1d95fcbSLiam Girdwood EXPORT_SYMBOL(snd_sof_dsp_update_bits64); 117d1d95fcbSLiam Girdwood 118d1d95fcbSLiam Girdwood static 119d1d95fcbSLiam Girdwood void snd_sof_dsp_update_bits_forced_unlocked(struct snd_sof_dev *sdev, u32 bar, 120d1d95fcbSLiam Girdwood u32 offset, u32 mask, u32 value) 121d1d95fcbSLiam Girdwood { 122d1d95fcbSLiam Girdwood unsigned int old, new; 123d1d95fcbSLiam Girdwood u32 ret; 124d1d95fcbSLiam Girdwood 125d1d95fcbSLiam Girdwood ret = snd_sof_dsp_read(sdev, bar, offset); 126d1d95fcbSLiam Girdwood 127d1d95fcbSLiam Girdwood old = ret; 128d1d95fcbSLiam Girdwood new = (old & ~mask) | (value & mask); 129d1d95fcbSLiam Girdwood 130d1d95fcbSLiam Girdwood snd_sof_dsp_write(sdev, bar, offset, new); 131d1d95fcbSLiam Girdwood } 132d1d95fcbSLiam Girdwood 133d1d95fcbSLiam Girdwood /* This is for registers bits with attribute RWC */ 134d1d95fcbSLiam Girdwood void snd_sof_dsp_update_bits_forced(struct snd_sof_dev *sdev, u32 bar, 135d1d95fcbSLiam Girdwood u32 offset, u32 mask, u32 value) 136d1d95fcbSLiam Girdwood { 137d1d95fcbSLiam Girdwood unsigned long flags; 138d1d95fcbSLiam Girdwood 139d1d95fcbSLiam Girdwood spin_lock_irqsave(&sdev->hw_lock, flags); 140d1d95fcbSLiam Girdwood snd_sof_dsp_update_bits_forced_unlocked(sdev, bar, offset, mask, value); 141d1d95fcbSLiam Girdwood spin_unlock_irqrestore(&sdev->hw_lock, flags); 142d1d95fcbSLiam Girdwood } 143d1d95fcbSLiam Girdwood EXPORT_SYMBOL(snd_sof_dsp_update_bits_forced); 144d1d95fcbSLiam Girdwood 145d1d95fcbSLiam Girdwood void snd_sof_dsp_panic(struct snd_sof_dev *sdev, u32 offset) 146d1d95fcbSLiam Girdwood { 147d1d95fcbSLiam Girdwood dev_err(sdev->dev, "error : DSP panic!\n"); 148d1d95fcbSLiam Girdwood 149d1d95fcbSLiam Girdwood /* 150d1d95fcbSLiam Girdwood * check if DSP is not ready and did not set the dsp_oops_offset. 151d1d95fcbSLiam Girdwood * if the dsp_oops_offset is not set, set it from the panic message. 152d1d95fcbSLiam Girdwood * Also add a check to memory window setting with panic message. 153d1d95fcbSLiam Girdwood */ 154d1d95fcbSLiam Girdwood if (!sdev->dsp_oops_offset) 155d1d95fcbSLiam Girdwood sdev->dsp_oops_offset = offset; 156d1d95fcbSLiam Girdwood else 157d1d95fcbSLiam Girdwood dev_dbg(sdev->dev, "panic: dsp_oops_offset %zu offset %d\n", 158d1d95fcbSLiam Girdwood sdev->dsp_oops_offset, offset); 159d1d95fcbSLiam Girdwood 160d1d95fcbSLiam Girdwood snd_sof_dsp_dbg_dump(sdev, SOF_DBG_REGS | SOF_DBG_MBOX); 161d1d95fcbSLiam Girdwood snd_sof_trace_notify_for_error(sdev); 162d1d95fcbSLiam Girdwood } 163d1d95fcbSLiam Girdwood EXPORT_SYMBOL(snd_sof_dsp_panic); 164