1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * cs_dsp.h  --  Cirrus Logic DSP firmware support
4 *
5 * Based on sound/soc/codecs/wm_adsp.h
6 *
7 * Copyright 2012 Wolfson Microelectronics plc
8 * Copyright (C) 2015-2021 Cirrus Logic, Inc. and
9 *                         Cirrus Logic International Semiconductor Ltd.
10 */
11#ifndef __CS_DSP_H
12#define __CS_DSP_H
13
14#include <linux/bits.h>
15#include <linux/device.h>
16#include <linux/firmware.h>
17#include <linux/list.h>
18#include <linux/regmap.h>
19
20#define CS_ADSP2_REGION_0 BIT(0)
21#define CS_ADSP2_REGION_1 BIT(1)
22#define CS_ADSP2_REGION_2 BIT(2)
23#define CS_ADSP2_REGION_3 BIT(3)
24#define CS_ADSP2_REGION_4 BIT(4)
25#define CS_ADSP2_REGION_5 BIT(5)
26#define CS_ADSP2_REGION_6 BIT(6)
27#define CS_ADSP2_REGION_7 BIT(7)
28#define CS_ADSP2_REGION_8 BIT(8)
29#define CS_ADSP2_REGION_9 BIT(9)
30#define CS_ADSP2_REGION_1_9 (CS_ADSP2_REGION_1 | \
31		CS_ADSP2_REGION_2 | CS_ADSP2_REGION_3 | \
32		CS_ADSP2_REGION_4 | CS_ADSP2_REGION_5 | \
33		CS_ADSP2_REGION_6 | CS_ADSP2_REGION_7 | \
34		CS_ADSP2_REGION_8 | CS_ADSP2_REGION_9)
35#define CS_ADSP2_REGION_ALL (CS_ADSP2_REGION_0 | CS_ADSP2_REGION_1_9)
36
37#define CS_DSP_DATA_WORD_SIZE                3
38#define CS_DSP_DATA_WORD_BITS                (3 * BITS_PER_BYTE)
39
40#define CS_DSP_ACKED_CTL_TIMEOUT_MS          100
41#define CS_DSP_ACKED_CTL_N_QUICKPOLLS        10
42#define CS_DSP_ACKED_CTL_MIN_VALUE           0
43#define CS_DSP_ACKED_CTL_MAX_VALUE           0xFFFFFF
44
45/**
46 * struct cs_dsp_region - Describes a logical memory region in DSP address space
47 * @type:	Memory region type
48 * @base:	Address of region
49 */
50struct cs_dsp_region {
51	int type;
52	unsigned int base;
53};
54
55/**
56 * struct cs_dsp_alg_region - Describes a logical algorithm region in DSP address space
57 * @list:	List node for internal use
58 * @alg:	Algorithm id
59 * @ver:	Expected algorithm version
60 * @type:	Memory region type
61 * @base:	Address of region
62 */
63struct cs_dsp_alg_region {
64	struct list_head list;
65	unsigned int alg;
66	unsigned int ver;
67	int type;
68	unsigned int base;
69};
70
71/**
72 * struct cs_dsp_coeff_ctl - Describes a coefficient control
73 * @list:		List node for internal use
74 * @dsp:		DSP instance associated with this control
75 * @cache:		Cached value of the control
76 * @fw_name:		Name of the firmware
77 * @subname:		Name of the control parsed from the WMFW
78 * @subname_len:	Length of subname
79 * @offset:		Offset of control within alg_region in words
80 * @len:		Length of the cached value in bytes
81 * @type:		One of the WMFW_CTL_TYPE_ control types defined in wmfw.h
82 * @flags:		Bitfield of WMFW_CTL_FLAG_ control flags defined in wmfw.h
83 * @set:		Flag indicating the value has been written by the user
84 * @enabled:		Flag indicating whether control is enabled
85 * @alg_region:		Logical region associated with this control
86 * @priv:		For use by the client
87 */
88struct cs_dsp_coeff_ctl {
89	struct list_head list;
90	struct cs_dsp *dsp;
91	void *cache;
92	const char *fw_name;
93	/* Subname is needed to match with firmware */
94	const char *subname;
95	unsigned int subname_len;
96	unsigned int offset;
97	size_t len;
98	unsigned int type;
99	unsigned int flags;
100	unsigned int set:1;
101	unsigned int enabled:1;
102	struct cs_dsp_alg_region alg_region;
103
104	void *priv;
105};
106
107struct cs_dsp_ops;
108struct cs_dsp_client_ops;
109
110/**
111 * struct cs_dsp - Configuration and state of a Cirrus Logic DSP
112 * @name:		The name of the DSP instance
113 * @rev:		Revision of the DSP
114 * @num:		DSP instance number
115 * @type:		Type of DSP
116 * @dev:		Driver model representation of the device
117 * @regmap:		Register map of the device
118 * @ops:		Function pointers for internal callbacks
119 * @client_ops:		Function pointers for client callbacks
120 * @base:		Address of the DSP registers
121 * @base_sysinfo:	Address of the sysinfo register (Halo only)
122 * @sysclk_reg:		Address of the sysclk register (ADSP1 only)
123 * @sysclk_mask:	Mask of frequency bits within sysclk register (ADSP1 only)
124 * @sysclk_shift:	Shift of frequency bits within sysclk register (ADSP1 only)
125 * @alg_regions:	List of currently loaded algorithm regions
126 * @fw_name:		Name of the current firmware
127 * @fw_id:		ID of the current firmware, obtained from the wmfw
128 * @fw_id_version:	Version of the firmware, obtained from the wmfw
129 * @fw_vendor_id:	Vendor of the firmware, obtained from the wmfw
130 * @mem:		DSP memory region descriptions
131 * @num_mems:		Number of memory regions in this DSP
132 * @fw_ver:		Version of the wmfw file format
133 * @booted:		Flag indicating DSP has been configured
134 * @running:		Flag indicating DSP is executing firmware
135 * @ctl_list:		Controls defined within the loaded DSP firmware
136 * @lock_regions:	Enable MPU traps on specified memory regions
137 * @pwr_lock:		Lock used to serialize accesses
138 * @debugfs_root:	Debugfs directory for this DSP instance
139 * @wmfw_file_name:	Filename of the currently loaded firmware
140 * @bin_file_name:	Filename of the currently loaded coefficients
141 */
142struct cs_dsp {
143	const char *name;
144	int rev;
145	int num;
146	int type;
147	struct device *dev;
148	struct regmap *regmap;
149
150	const struct cs_dsp_ops *ops;
151	const struct cs_dsp_client_ops *client_ops;
152
153	unsigned int base;
154	unsigned int base_sysinfo;
155	unsigned int sysclk_reg;
156	unsigned int sysclk_mask;
157	unsigned int sysclk_shift;
158	bool no_core_startstop;
159
160	struct list_head alg_regions;
161
162	const char *fw_name;
163	unsigned int fw_id;
164	unsigned int fw_id_version;
165	unsigned int fw_vendor_id;
166
167	const struct cs_dsp_region *mem;
168	int num_mems;
169
170	int fw_ver;
171
172	bool booted;
173	bool running;
174
175	struct list_head ctl_list;
176
177	struct mutex pwr_lock;
178
179	unsigned int lock_regions;
180
181#ifdef CONFIG_DEBUG_FS
182	struct dentry *debugfs_root;
183	char *wmfw_file_name;
184	char *bin_file_name;
185#endif
186};
187
188/**
189 * struct cs_dsp_client_ops - client callbacks
190 * @control_add:	Called under the pwr_lock when a control is created
191 * @control_remove:	Called under the pwr_lock when a control is destroyed
192 * @pre_run:		Called under the pwr_lock by cs_dsp_run() before the core is started
193 * @post_run:		Called under the pwr_lock by cs_dsp_run() after the core is started
194 * @pre_stop:		Called under the pwr_lock by cs_dsp_stop() before the core is stopped
195 * @post_stop:		Called under the pwr_lock by cs_dsp_stop() after the core is stopped
196 * @watchdog_expired:	Called when a watchdog expiry is detected
197 *
198 * These callbacks give the cs_dsp client an opportunity to respond to events
199 * or to perform actions atomically.
200 */
201struct cs_dsp_client_ops {
202	int (*control_add)(struct cs_dsp_coeff_ctl *ctl);
203	void (*control_remove)(struct cs_dsp_coeff_ctl *ctl);
204	int (*pre_run)(struct cs_dsp *dsp);
205	int (*post_run)(struct cs_dsp *dsp);
206	void (*pre_stop)(struct cs_dsp *dsp);
207	void (*post_stop)(struct cs_dsp *dsp);
208	void (*watchdog_expired)(struct cs_dsp *dsp);
209};
210
211int cs_dsp_adsp1_init(struct cs_dsp *dsp);
212int cs_dsp_adsp2_init(struct cs_dsp *dsp);
213int cs_dsp_halo_init(struct cs_dsp *dsp);
214
215int cs_dsp_adsp1_power_up(struct cs_dsp *dsp,
216			  const struct firmware *wmfw_firmware, char *wmfw_filename,
217			  const struct firmware *coeff_firmware, char *coeff_filename,
218			  const char *fw_name);
219void cs_dsp_adsp1_power_down(struct cs_dsp *dsp);
220int cs_dsp_power_up(struct cs_dsp *dsp,
221		    const struct firmware *wmfw_firmware, char *wmfw_filename,
222		    const struct firmware *coeff_firmware, char *coeff_filename,
223		    const char *fw_name);
224void cs_dsp_power_down(struct cs_dsp *dsp);
225int cs_dsp_run(struct cs_dsp *dsp);
226void cs_dsp_stop(struct cs_dsp *dsp);
227
228void cs_dsp_remove(struct cs_dsp *dsp);
229
230int cs_dsp_set_dspclk(struct cs_dsp *dsp, unsigned int freq);
231void cs_dsp_adsp2_bus_error(struct cs_dsp *dsp);
232void cs_dsp_halo_bus_error(struct cs_dsp *dsp);
233void cs_dsp_halo_wdt_expire(struct cs_dsp *dsp);
234
235void cs_dsp_init_debugfs(struct cs_dsp *dsp, struct dentry *debugfs_root);
236void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp);
237
238int cs_dsp_coeff_write_acked_control(struct cs_dsp_coeff_ctl *ctl, unsigned int event_id);
239int cs_dsp_coeff_write_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off,
240			    const void *buf, size_t len);
241int cs_dsp_coeff_read_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off,
242			   void *buf, size_t len);
243struct cs_dsp_coeff_ctl *cs_dsp_get_ctl(struct cs_dsp *dsp, const char *name, int type,
244					unsigned int alg);
245
246int cs_dsp_read_raw_data_block(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr,
247			       unsigned int num_words, __be32 *data);
248int cs_dsp_read_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr, u32 *data);
249int cs_dsp_write_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr, u32 data);
250void cs_dsp_remove_padding(u32 *buf, int nwords);
251
252struct cs_dsp_alg_region *cs_dsp_find_alg_region(struct cs_dsp *dsp,
253						 int type, unsigned int id);
254
255const char *cs_dsp_mem_region_name(unsigned int type);
256
257/**
258 * struct cs_dsp_chunk - Describes a buffer holding data formatted for the DSP
259 * @data:	Pointer to underlying buffer memory
260 * @max:	Pointer to end of the buffer memory
261 * @bytes:	Number of bytes read/written into the memory chunk
262 * @cache:	Temporary holding data as it is formatted
263 * @cachebits:	Number of bits of data currently in cache
264 */
265struct cs_dsp_chunk {
266	u8 *data;
267	u8 *max;
268	int bytes;
269
270	u32 cache;
271	int cachebits;
272};
273
274/**
275 * cs_dsp_chunk() - Create a DSP memory chunk
276 * @data: Pointer to the buffer that will be used to store data
277 * @size: Size of the buffer in bytes
278 *
279 * Return: A cs_dsp_chunk structure
280 */
281static inline struct cs_dsp_chunk cs_dsp_chunk(void *data, int size)
282{
283	struct cs_dsp_chunk ch = {
284		.data = data,
285		.max = data + size,
286	};
287
288	return ch;
289}
290
291/**
292 * cs_dsp_chunk_end() - Check if a DSP memory chunk is full
293 * @ch: Pointer to the chunk structure
294 *
295 * Return: True if the whole buffer has been read/written
296 */
297static inline bool cs_dsp_chunk_end(struct cs_dsp_chunk *ch)
298{
299	return ch->data == ch->max;
300}
301
302/**
303 * cs_dsp_chunk_bytes() - Number of bytes written/read from a DSP memory chunk
304 * @ch: Pointer to the chunk structure
305 *
306 * Return: Number of bytes read/written to the buffer
307 */
308static inline int cs_dsp_chunk_bytes(struct cs_dsp_chunk *ch)
309{
310	return ch->bytes;
311}
312
313/**
314 * cs_dsp_chunk_valid_addr() - Check if an address is in a DSP memory chunk
315 * @ch: Pointer to the chunk structure
316 *
317 * Return: True if the given address is within the buffer
318 */
319static inline bool cs_dsp_chunk_valid_addr(struct cs_dsp_chunk *ch, void *addr)
320{
321	return (u8 *)addr >= ch->data && (u8 *)addr < ch->max;
322}
323
324int cs_dsp_chunk_write(struct cs_dsp_chunk *ch, int nbits, u32 val);
325int cs_dsp_chunk_flush(struct cs_dsp_chunk *ch);
326int cs_dsp_chunk_read(struct cs_dsp_chunk *ch, int nbits);
327
328#endif
329