xref: /openbmc/linux/sound/soc/sof/ops.c (revision c41d384c)
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