/* SPDX-License-Identifier: GPL-2.0-only */ /* * cs_dsp.h -- Cirrus Logic DSP firmware support * * Based on sound/soc/codecs/wm_adsp.h * * Copyright 2012 Wolfson Microelectronics plc * Copyright (C) 2015-2021 Cirrus Logic, Inc. and * Cirrus Logic International Semiconductor Ltd. */ #ifndef __CS_DSP_H #define __CS_DSP_H #include <linux/bits.h> #include <linux/device.h> #include <linux/firmware.h> #include <linux/list.h> #include <linux/regmap.h> #define CS_ADSP2_REGION_0 … #define CS_ADSP2_REGION_1 … #define CS_ADSP2_REGION_2 … #define CS_ADSP2_REGION_3 … #define CS_ADSP2_REGION_4 … #define CS_ADSP2_REGION_5 … #define CS_ADSP2_REGION_6 … #define CS_ADSP2_REGION_7 … #define CS_ADSP2_REGION_8 … #define CS_ADSP2_REGION_9 … #define CS_ADSP2_REGION_1_9 … #define CS_ADSP2_REGION_ALL … #define CS_DSP_DATA_WORD_SIZE … #define CS_DSP_DATA_WORD_BITS … #define CS_DSP_ACKED_CTL_TIMEOUT_MS … #define CS_DSP_ACKED_CTL_N_QUICKPOLLS … #define CS_DSP_ACKED_CTL_MIN_VALUE … #define CS_DSP_ACKED_CTL_MAX_VALUE … /* * Write sequence operation codes */ #define CS_DSP_WSEQ_FULL … #define CS_DSP_WSEQ_ADDR8 … #define CS_DSP_WSEQ_L16 … #define CS_DSP_WSEQ_H16 … #define CS_DSP_WSEQ_UNLOCK … #define CS_DSP_WSEQ_END … /** * struct cs_dsp_region - Describes a logical memory region in DSP address space * @type: Memory region type * @base: Address of region */ struct cs_dsp_region { … }; /** * struct cs_dsp_alg_region - Describes a logical algorithm region in DSP address space * @list: List node for internal use * @alg: Algorithm id * @ver: Expected algorithm version * @type: Memory region type * @base: Address of region */ struct cs_dsp_alg_region { … }; /** * struct cs_dsp_coeff_ctl - Describes a coefficient control * @list: List node for internal use * @dsp: DSP instance associated with this control * @cache: Cached value of the control * @fw_name: Name of the firmware * @subname: Name of the control parsed from the WMFW * @subname_len: Length of subname * @offset: Offset of control within alg_region in words * @len: Length of the cached value in bytes * @type: One of the WMFW_CTL_TYPE_ control types defined in wmfw.h * @flags: Bitfield of WMFW_CTL_FLAG_ control flags defined in wmfw.h * @set: Flag indicating the value has been written by the user * @enabled: Flag indicating whether control is enabled * @alg_region: Logical region associated with this control * @priv: For use by the client */ struct cs_dsp_coeff_ctl { … }; struct cs_dsp_ops; struct cs_dsp_client_ops; /** * struct cs_dsp - Configuration and state of a Cirrus Logic DSP * @name: The name of the DSP instance * @rev: Revision of the DSP * @num: DSP instance number * @type: Type of DSP * @dev: Driver model representation of the device * @regmap: Register map of the device * @ops: Function pointers for internal callbacks * @client_ops: Function pointers for client callbacks * @base: Address of the DSP registers * @base_sysinfo: Address of the sysinfo register (Halo only) * @sysclk_reg: Address of the sysclk register (ADSP1 only) * @sysclk_mask: Mask of frequency bits within sysclk register (ADSP1 only) * @sysclk_shift: Shift of frequency bits within sysclk register (ADSP1 only) * @alg_regions: List of currently loaded algorithm regions * @fw_name: Name of the current firmware * @fw_id: ID of the current firmware, obtained from the wmfw * @fw_id_version: Version of the firmware, obtained from the wmfw * @fw_vendor_id: Vendor of the firmware, obtained from the wmfw * @mem: DSP memory region descriptions * @num_mems: Number of memory regions in this DSP * @fw_ver: Version of the wmfw file format * @booted: Flag indicating DSP has been configured * @running: Flag indicating DSP is executing firmware * @ctl_list: Controls defined within the loaded DSP firmware * @lock_regions: Enable MPU traps on specified memory regions * @pwr_lock: Lock used to serialize accesses * @debugfs_root: Debugfs directory for this DSP instance * @wmfw_file_name: Filename of the currently loaded firmware * @bin_file_name: Filename of the currently loaded coefficients */ struct cs_dsp { … }; /** * struct cs_dsp_client_ops - client callbacks * @control_add: Called under the pwr_lock when a control is created * @control_remove: Called under the pwr_lock when a control is destroyed * @pre_run: Called under the pwr_lock by cs_dsp_run() before the core is started * @post_run: Called under the pwr_lock by cs_dsp_run() after the core is started * @pre_stop: Called under the pwr_lock by cs_dsp_stop() before the core is stopped * @post_stop: Called under the pwr_lock by cs_dsp_stop() after the core is stopped * @watchdog_expired: Called when a watchdog expiry is detected * * These callbacks give the cs_dsp client an opportunity to respond to events * or to perform actions atomically. */ struct cs_dsp_client_ops { … }; int cs_dsp_adsp1_init(struct cs_dsp *dsp); int cs_dsp_adsp2_init(struct cs_dsp *dsp); int cs_dsp_halo_init(struct cs_dsp *dsp); int cs_dsp_adsp1_power_up(struct cs_dsp *dsp, const struct firmware *wmfw_firmware, const char *wmfw_filename, const struct firmware *coeff_firmware, const char *coeff_filename, const char *fw_name); void cs_dsp_adsp1_power_down(struct cs_dsp *dsp); int cs_dsp_power_up(struct cs_dsp *dsp, const struct firmware *wmfw_firmware, const char *wmfw_filename, const struct firmware *coeff_firmware, const char *coeff_filename, const char *fw_name); void cs_dsp_power_down(struct cs_dsp *dsp); int cs_dsp_run(struct cs_dsp *dsp); void cs_dsp_stop(struct cs_dsp *dsp); void cs_dsp_remove(struct cs_dsp *dsp); int cs_dsp_set_dspclk(struct cs_dsp *dsp, unsigned int freq); void cs_dsp_adsp2_bus_error(struct cs_dsp *dsp); void cs_dsp_halo_bus_error(struct cs_dsp *dsp); void cs_dsp_halo_wdt_expire(struct cs_dsp *dsp); void cs_dsp_init_debugfs(struct cs_dsp *dsp, struct dentry *debugfs_root); void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp); int cs_dsp_coeff_write_acked_control(struct cs_dsp_coeff_ctl *ctl, unsigned int event_id); int cs_dsp_coeff_write_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off, const void *buf, size_t len); int cs_dsp_coeff_lock_and_write_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off, const void *buf, size_t len); int cs_dsp_coeff_read_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off, void *buf, size_t len); int cs_dsp_coeff_lock_and_read_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off, void *buf, size_t len); struct cs_dsp_coeff_ctl *cs_dsp_get_ctl(struct cs_dsp *dsp, const char *name, int type, unsigned int alg); int cs_dsp_read_raw_data_block(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr, unsigned int num_words, __be32 *data); int cs_dsp_read_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr, u32 *data); int cs_dsp_write_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr, u32 data); void cs_dsp_remove_padding(u32 *buf, int nwords); struct cs_dsp_alg_region *cs_dsp_find_alg_region(struct cs_dsp *dsp, int type, unsigned int id); const char *cs_dsp_mem_region_name(unsigned int type); /** * struct cs_dsp_wseq - Describes a write sequence * @ctl: Write sequence cs_dsp control * @ops: Operations contained within */ struct cs_dsp_wseq { … }; int cs_dsp_wseq_init(struct cs_dsp *dsp, struct cs_dsp_wseq *wseqs, unsigned int num_wseqs); int cs_dsp_wseq_write(struct cs_dsp *dsp, struct cs_dsp_wseq *wseq, u32 addr, u32 data, u8 op_code, bool update); int cs_dsp_wseq_multi_write(struct cs_dsp *dsp, struct cs_dsp_wseq *wseq, const struct reg_sequence *reg_seq, int num_regs, u8 op_code, bool update); /** * struct cs_dsp_chunk - Describes a buffer holding data formatted for the DSP * @data: Pointer to underlying buffer memory * @max: Pointer to end of the buffer memory * @bytes: Number of bytes read/written into the memory chunk * @cache: Temporary holding data as it is formatted * @cachebits: Number of bits of data currently in cache */ struct cs_dsp_chunk { … }; /** * cs_dsp_chunk() - Create a DSP memory chunk * @data: Pointer to the buffer that will be used to store data * @size: Size of the buffer in bytes * * Return: A cs_dsp_chunk structure */ static inline struct cs_dsp_chunk cs_dsp_chunk(void *data, int size) { … } /** * cs_dsp_chunk_end() - Check if a DSP memory chunk is full * @ch: Pointer to the chunk structure * * Return: True if the whole buffer has been read/written */ static inline bool cs_dsp_chunk_end(struct cs_dsp_chunk *ch) { … } /** * cs_dsp_chunk_bytes() - Number of bytes written/read from a DSP memory chunk * @ch: Pointer to the chunk structure * * Return: Number of bytes read/written to the buffer */ static inline int cs_dsp_chunk_bytes(struct cs_dsp_chunk *ch) { … } /** * cs_dsp_chunk_valid_addr() - Check if an address is in a DSP memory chunk * @ch: Pointer to the chunk structure * * Return: True if the given address is within the buffer */ static inline bool cs_dsp_chunk_valid_addr(struct cs_dsp_chunk *ch, void *addr) { … } int cs_dsp_chunk_write(struct cs_dsp_chunk *ch, int nbits, u32 val); int cs_dsp_chunk_flush(struct cs_dsp_chunk *ch); int cs_dsp_chunk_read(struct cs_dsp_chunk *ch, int nbits); #endif