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 * Write sequence operation codes 47 */ 48 #define CS_DSP_WSEQ_FULL 0x00 49 #define CS_DSP_WSEQ_ADDR8 0x02 50 #define CS_DSP_WSEQ_L16 0x04 51 #define CS_DSP_WSEQ_H16 0x05 52 #define CS_DSP_WSEQ_UNLOCK 0xFD 53 #define CS_DSP_WSEQ_END 0xFF 54 55 /** 56 * struct cs_dsp_region - Describes a logical memory region in DSP address space 57 * @type: Memory region type 58 * @base: Address of region 59 */ 60 struct cs_dsp_region { 61 int type; 62 unsigned int base; 63 }; 64 65 /** 66 * struct cs_dsp_alg_region - Describes a logical algorithm region in DSP address space 67 * @list: List node for internal use 68 * @alg: Algorithm id 69 * @ver: Expected algorithm version 70 * @type: Memory region type 71 * @base: Address of region 72 */ 73 struct cs_dsp_alg_region { 74 struct list_head list; 75 unsigned int alg; 76 unsigned int ver; 77 int type; 78 unsigned int base; 79 }; 80 81 /** 82 * struct cs_dsp_coeff_ctl - Describes a coefficient control 83 * @list: List node for internal use 84 * @dsp: DSP instance associated with this control 85 * @cache: Cached value of the control 86 * @fw_name: Name of the firmware 87 * @subname: Name of the control parsed from the WMFW 88 * @subname_len: Length of subname 89 * @offset: Offset of control within alg_region in words 90 * @len: Length of the cached value in bytes 91 * @type: One of the WMFW_CTL_TYPE_ control types defined in wmfw.h 92 * @flags: Bitfield of WMFW_CTL_FLAG_ control flags defined in wmfw.h 93 * @set: Flag indicating the value has been written by the user 94 * @enabled: Flag indicating whether control is enabled 95 * @alg_region: Logical region associated with this control 96 * @priv: For use by the client 97 */ 98 struct cs_dsp_coeff_ctl { 99 struct list_head list; 100 struct cs_dsp *dsp; 101 void *cache; 102 const char *fw_name; 103 /* Subname is needed to match with firmware */ 104 const char *subname; 105 unsigned int subname_len; 106 unsigned int offset; 107 size_t len; 108 unsigned int type; 109 unsigned int flags; 110 unsigned int set:1; 111 unsigned int enabled:1; 112 struct cs_dsp_alg_region alg_region; 113 114 void *priv; 115 }; 116 117 struct cs_dsp_ops; 118 struct cs_dsp_client_ops; 119 120 /** 121 * struct cs_dsp - Configuration and state of a Cirrus Logic DSP 122 * @name: The name of the DSP instance 123 * @rev: Revision of the DSP 124 * @num: DSP instance number 125 * @type: Type of DSP 126 * @dev: Driver model representation of the device 127 * @regmap: Register map of the device 128 * @ops: Function pointers for internal callbacks 129 * @client_ops: Function pointers for client callbacks 130 * @base: Address of the DSP registers 131 * @base_sysinfo: Address of the sysinfo register (Halo only) 132 * @sysclk_reg: Address of the sysclk register (ADSP1 only) 133 * @sysclk_mask: Mask of frequency bits within sysclk register (ADSP1 only) 134 * @sysclk_shift: Shift of frequency bits within sysclk register (ADSP1 only) 135 * @alg_regions: List of currently loaded algorithm regions 136 * @fw_name: Name of the current firmware 137 * @fw_id: ID of the current firmware, obtained from the wmfw 138 * @fw_id_version: Version of the firmware, obtained from the wmfw 139 * @fw_vendor_id: Vendor of the firmware, obtained from the wmfw 140 * @mem: DSP memory region descriptions 141 * @num_mems: Number of memory regions in this DSP 142 * @fw_ver: Version of the wmfw file format 143 * @booted: Flag indicating DSP has been configured 144 * @running: Flag indicating DSP is executing firmware 145 * @ctl_list: Controls defined within the loaded DSP firmware 146 * @lock_regions: Enable MPU traps on specified memory regions 147 * @pwr_lock: Lock used to serialize accesses 148 * @debugfs_root: Debugfs directory for this DSP instance 149 * @wmfw_file_name: Filename of the currently loaded firmware 150 * @bin_file_name: Filename of the currently loaded coefficients 151 */ 152 struct cs_dsp { 153 const char *name; 154 int rev; 155 int num; 156 int type; 157 struct device *dev; 158 struct regmap *regmap; 159 160 const struct cs_dsp_ops *ops; 161 const struct cs_dsp_client_ops *client_ops; 162 163 unsigned int base; 164 unsigned int base_sysinfo; 165 unsigned int sysclk_reg; 166 unsigned int sysclk_mask; 167 unsigned int sysclk_shift; 168 bool no_core_startstop; 169 170 struct list_head alg_regions; 171 172 const char *fw_name; 173 unsigned int fw_id; 174 unsigned int fw_id_version; 175 unsigned int fw_vendor_id; 176 177 const struct cs_dsp_region *mem; 178 int num_mems; 179 180 int wmfw_ver; 181 182 bool booted; 183 bool running; 184 185 struct list_head ctl_list; 186 187 struct mutex pwr_lock; 188 189 unsigned int lock_regions; 190 191 #ifdef CONFIG_DEBUG_FS 192 struct dentry *debugfs_root; 193 char *wmfw_file_name; 194 char *bin_file_name; 195 #endif 196 }; 197 198 /** 199 * struct cs_dsp_client_ops - client callbacks 200 * @control_add: Called under the pwr_lock when a control is created 201 * @control_remove: Called under the pwr_lock when a control is destroyed 202 * @pre_run: Called under the pwr_lock by cs_dsp_run() before the core is started 203 * @post_run: Called under the pwr_lock by cs_dsp_run() after the core is started 204 * @pre_stop: Called under the pwr_lock by cs_dsp_stop() before the core is stopped 205 * @post_stop: Called under the pwr_lock by cs_dsp_stop() after the core is stopped 206 * @watchdog_expired: Called when a watchdog expiry is detected 207 * 208 * These callbacks give the cs_dsp client an opportunity to respond to events 209 * or to perform actions atomically. 210 */ 211 struct cs_dsp_client_ops { 212 int (*control_add)(struct cs_dsp_coeff_ctl *ctl); 213 void (*control_remove)(struct cs_dsp_coeff_ctl *ctl); 214 int (*pre_run)(struct cs_dsp *dsp); 215 int (*post_run)(struct cs_dsp *dsp); 216 void (*pre_stop)(struct cs_dsp *dsp); 217 void (*post_stop)(struct cs_dsp *dsp); 218 void (*watchdog_expired)(struct cs_dsp *dsp); 219 }; 220 221 int cs_dsp_adsp1_init(struct cs_dsp *dsp); 222 int cs_dsp_adsp2_init(struct cs_dsp *dsp); 223 int cs_dsp_halo_init(struct cs_dsp *dsp); 224 225 int cs_dsp_adsp1_power_up(struct cs_dsp *dsp, 226 const struct firmware *wmfw_firmware, const char *wmfw_filename, 227 const struct firmware *coeff_firmware, const char *coeff_filename, 228 const char *fw_name); 229 void cs_dsp_adsp1_power_down(struct cs_dsp *dsp); 230 int cs_dsp_power_up(struct cs_dsp *dsp, 231 const struct firmware *wmfw_firmware, const char *wmfw_filename, 232 const struct firmware *coeff_firmware, const char *coeff_filename, 233 const char *fw_name); 234 void cs_dsp_power_down(struct cs_dsp *dsp); 235 int cs_dsp_run(struct cs_dsp *dsp); 236 void cs_dsp_stop(struct cs_dsp *dsp); 237 238 void cs_dsp_remove(struct cs_dsp *dsp); 239 240 int cs_dsp_set_dspclk(struct cs_dsp *dsp, unsigned int freq); 241 void cs_dsp_adsp2_bus_error(struct cs_dsp *dsp); 242 void cs_dsp_halo_bus_error(struct cs_dsp *dsp); 243 void cs_dsp_halo_wdt_expire(struct cs_dsp *dsp); 244 245 void cs_dsp_init_debugfs(struct cs_dsp *dsp, struct dentry *debugfs_root); 246 void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp); 247 248 int cs_dsp_coeff_write_acked_control(struct cs_dsp_coeff_ctl *ctl, unsigned int event_id); 249 int cs_dsp_coeff_write_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off, 250 const void *buf, size_t len); 251 int cs_dsp_coeff_lock_and_write_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off, 252 const void *buf, size_t len); 253 int cs_dsp_coeff_read_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off, 254 void *buf, size_t len); 255 int cs_dsp_coeff_lock_and_read_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off, 256 void *buf, size_t len); 257 struct cs_dsp_coeff_ctl *cs_dsp_get_ctl(struct cs_dsp *dsp, const char *name, int type, 258 unsigned int alg); 259 260 int cs_dsp_read_raw_data_block(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr, 261 unsigned int num_words, __be32 *data); 262 int cs_dsp_read_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr, u32 *data); 263 int cs_dsp_write_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr, u32 data); 264 void cs_dsp_remove_padding(u32 *buf, int nwords); 265 266 struct cs_dsp_alg_region *cs_dsp_find_alg_region(struct cs_dsp *dsp, 267 int type, unsigned int id); 268 269 const char *cs_dsp_mem_region_name(unsigned int type); 270 271 /** 272 * struct cs_dsp_wseq - Describes a write sequence 273 * @ctl: Write sequence cs_dsp control 274 * @ops: Operations contained within 275 */ 276 struct cs_dsp_wseq { 277 struct cs_dsp_coeff_ctl *ctl; 278 struct list_head ops; 279 }; 280 281 int cs_dsp_wseq_init(struct cs_dsp *dsp, struct cs_dsp_wseq *wseqs, unsigned int num_wseqs); 282 int cs_dsp_wseq_write(struct cs_dsp *dsp, struct cs_dsp_wseq *wseq, u32 addr, u32 data, 283 u8 op_code, bool update); 284 int cs_dsp_wseq_multi_write(struct cs_dsp *dsp, struct cs_dsp_wseq *wseq, 285 const struct reg_sequence *reg_seq, int num_regs, 286 u8 op_code, bool update); 287 288 /** 289 * struct cs_dsp_chunk - Describes a buffer holding data formatted for the DSP 290 * @data: Pointer to underlying buffer memory 291 * @max: Pointer to end of the buffer memory 292 * @bytes: Number of bytes read/written into the memory chunk 293 * @cache: Temporary holding data as it is formatted 294 * @cachebits: Number of bits of data currently in cache 295 */ 296 struct cs_dsp_chunk { 297 u8 *data; 298 u8 *max; 299 int bytes; 300 301 u32 cache; 302 int cachebits; 303 }; 304 305 /** 306 * cs_dsp_chunk() - Create a DSP memory chunk 307 * @data: Pointer to the buffer that will be used to store data 308 * @size: Size of the buffer in bytes 309 * 310 * Return: A cs_dsp_chunk structure 311 */ 312 static inline struct cs_dsp_chunk cs_dsp_chunk(void *data, int size) 313 { 314 struct cs_dsp_chunk ch = { 315 .data = data, 316 .max = data + size, 317 }; 318 319 return ch; 320 } 321 322 /** 323 * cs_dsp_chunk_end() - Check if a DSP memory chunk is full 324 * @ch: Pointer to the chunk structure 325 * 326 * Return: True if the whole buffer has been read/written 327 */ 328 static inline bool cs_dsp_chunk_end(struct cs_dsp_chunk *ch) 329 { 330 return ch->data == ch->max; 331 } 332 333 /** 334 * cs_dsp_chunk_bytes() - Number of bytes written/read from a DSP memory chunk 335 * @ch: Pointer to the chunk structure 336 * 337 * Return: Number of bytes read/written to the buffer 338 */ 339 static inline int cs_dsp_chunk_bytes(struct cs_dsp_chunk *ch) 340 { 341 return ch->bytes; 342 } 343 344 /** 345 * cs_dsp_chunk_valid_addr() - Check if an address is in a DSP memory chunk 346 * @ch: Pointer to the chunk structure 347 * 348 * Return: True if the given address is within the buffer 349 */ 350 static inline bool cs_dsp_chunk_valid_addr(struct cs_dsp_chunk *ch, void *addr) 351 { 352 return (u8 *)addr >= ch->data && (u8 *)addr < ch->max; 353 } 354 355 int cs_dsp_chunk_write(struct cs_dsp_chunk *ch, int nbits, u32 val); 356 int cs_dsp_chunk_flush(struct cs_dsp_chunk *ch); 357 int cs_dsp_chunk_read(struct cs_dsp_chunk *ch, int nbits); 358 359 #endif 360
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.