Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) // This file is provided under a dual BSD/GPLv2 license.  When using or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) // redistributing this file, you may do so under either license.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) // Copyright(c) 2018 Intel Corporation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) // Generic firmware loader.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <sound/sof.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <sound/sof/ext_manifest.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include "ops.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) static int get_ext_windows(struct snd_sof_dev *sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 			   const struct sof_ipc_ext_data_hdr *ext_hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	const struct sof_ipc_window *w =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 		container_of(ext_hdr, struct sof_ipc_window, ext_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	if (w->num_windows == 0 || w->num_windows > SOF_IPC_MAX_ELEMS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	if (sdev->info_window) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 		if (memcmp(sdev->info_window, w, ext_hdr->hdr.size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 			dev_err(sdev->dev, "error: mismatch between window descriptor from extended manifest and mailbox");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	/* keep a local copy of the data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	sdev->info_window = devm_kmemdup(sdev->dev, w, ext_hdr->hdr.size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 					 GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	if (!sdev->info_window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) static int get_cc_info(struct snd_sof_dev *sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		       const struct sof_ipc_ext_data_hdr *ext_hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	const struct sof_ipc_cc_version *cc =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 		container_of(ext_hdr, struct sof_ipc_cc_version, ext_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	if (sdev->cc_version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 		if (memcmp(sdev->cc_version, cc, cc->ext_hdr.hdr.size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 			dev_err(sdev->dev, "error: receive diverged cc_version descriptions");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	dev_dbg(sdev->dev, "Firmware info: used compiler %s %d:%d:%d%s used optimization flags %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 		cc->name, cc->major, cc->minor, cc->micro, cc->desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 		cc->optim);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	/* create read-only cc_version debugfs to store compiler version info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	/* use local copy of the cc_version to prevent data corruption */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	if (sdev->first_boot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		sdev->cc_version = devm_kmalloc(sdev->dev, cc->ext_hdr.hdr.size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 						GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		if (!sdev->cc_version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 			return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		memcpy(sdev->cc_version, cc, cc->ext_hdr.hdr.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		ret = snd_sof_debugfs_buf_item(sdev, sdev->cc_version,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 					       cc->ext_hdr.hdr.size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 					       "cc_version", 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		/* errors are only due to memory allocation, not debugfs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 			dev_err(sdev->dev, "error: snd_sof_debugfs_buf_item failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) /* parse the extended FW boot data structures from FW boot message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	struct sof_ipc_ext_data_hdr *ext_hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	void *ext_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	ext_data = kzalloc(PAGE_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	if (!ext_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	/* get first header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	snd_sof_dsp_block_read(sdev, bar, offset, ext_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 			       sizeof(*ext_hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	ext_hdr = ext_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	while (ext_hdr->hdr.cmd == SOF_IPC_FW_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		/* read in ext structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		snd_sof_dsp_block_read(sdev, bar, offset + sizeof(*ext_hdr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 				   (void *)((u8 *)ext_data + sizeof(*ext_hdr)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 				   ext_hdr->hdr.size - sizeof(*ext_hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		dev_dbg(sdev->dev, "found ext header type %d size 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 			ext_hdr->type, ext_hdr->hdr.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		/* process structure data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 		switch (ext_hdr->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		case SOF_IPC_EXT_WINDOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 			ret = get_ext_windows(sdev, ext_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		case SOF_IPC_EXT_CC_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 			ret = get_cc_info(sdev, ext_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		case SOF_IPC_EXT_UNUSED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		case SOF_IPC_EXT_PROBE_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		case SOF_IPC_EXT_USER_ABI_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 			/* They are supported but we don't do anything here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 			dev_warn(sdev->dev, "warning: unknown ext header type %d size 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 				 ext_hdr->type, ext_hdr->hdr.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 			ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 			dev_err(sdev->dev, "error: failed to parse ext data type %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 				ext_hdr->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 		/* move to next header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		offset += ext_hdr->hdr.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		snd_sof_dsp_block_read(sdev, bar, offset, ext_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 				       sizeof(*ext_hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		ext_hdr = ext_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	kfree(ext_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) EXPORT_SYMBOL(snd_sof_fw_parse_ext_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static int ext_man_get_fw_version(struct snd_sof_dev *sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 				  const struct sof_ext_man_elem_header *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	const struct sof_ext_man_fw_version *v =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		container_of(hdr, struct sof_ext_man_fw_version, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	memcpy(&sdev->fw_ready.version, &v->version, sizeof(v->version));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	sdev->fw_ready.flags = v->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	/* log ABI versions and check FW compatibility */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	return snd_sof_ipc_valid(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static int ext_man_get_windows(struct snd_sof_dev *sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 			       const struct sof_ext_man_elem_header *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	const struct sof_ext_man_window *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	w = container_of(hdr, struct sof_ext_man_window, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	return get_ext_windows(sdev, &w->ipc_window.ext_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static int ext_man_get_cc_info(struct snd_sof_dev *sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 			       const struct sof_ext_man_elem_header *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	const struct sof_ext_man_cc_version *cc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	cc = container_of(hdr, struct sof_ext_man_cc_version, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	return get_cc_info(sdev, &cc->cc_version.ext_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static int ext_man_get_dbg_abi_info(struct snd_sof_dev *sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 				    const struct sof_ext_man_elem_header *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	const struct ext_man_dbg_abi *dbg_abi =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		container_of(hdr, struct ext_man_dbg_abi, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	if (sdev->first_boot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		dev_dbg(sdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 			"Firmware: DBG_ABI %d:%d:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 			SOF_ABI_VERSION_MAJOR(dbg_abi->dbg_abi.abi_dbg_version),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 			SOF_ABI_VERSION_MINOR(dbg_abi->dbg_abi.abi_dbg_version),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 			SOF_ABI_VERSION_PATCH(dbg_abi->dbg_abi.abi_dbg_version));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static ssize_t snd_sof_ext_man_size(const struct firmware *fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	const struct sof_ext_man_header *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	head = (struct sof_ext_man_header *)fw->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	 * assert fw size is big enough to contain extended manifest header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	 * it prevents from reading unallocated memory from `head` in following
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	 * step.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	if (fw->size < sizeof(*head))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	 * When fw points to extended manifest,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	 * then first u32 must be equal SOF_EXT_MAN_MAGIC_NUMBER.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	if (head->magic == SOF_EXT_MAN_MAGIC_NUMBER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		return head->full_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	/* otherwise given fw don't have an extended manifest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /* parse extended FW manifest data structures */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static int snd_sof_fw_ext_man_parse(struct snd_sof_dev *sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 				    const struct firmware *fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	const struct sof_ext_man_elem_header *elem_hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	const struct sof_ext_man_header *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	ssize_t ext_man_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	ssize_t remaining;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	uintptr_t iptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	head = (struct sof_ext_man_header *)fw->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	remaining = head->full_size - head->header_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	ext_man_size = snd_sof_ext_man_size(fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	/* Assert firmware starts with extended manifest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	if (ext_man_size <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		return ext_man_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	/* incompatible version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	if (SOF_EXT_MAN_VERSION_INCOMPATIBLE(SOF_EXT_MAN_VERSION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 					     head->header_version)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		dev_err(sdev->dev, "error: extended manifest version 0x%X differ from used 0x%X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 			head->header_version, SOF_EXT_MAN_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	/* get first extended manifest element header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	iptr = (uintptr_t)fw->data + head->header_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	while (remaining > sizeof(*elem_hdr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		elem_hdr = (struct sof_ext_man_elem_header *)iptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		dev_dbg(sdev->dev, "found sof_ext_man header type %d size 0x%X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 			elem_hdr->type, elem_hdr->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		if (elem_hdr->size < sizeof(*elem_hdr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		    elem_hdr->size > remaining) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 			dev_err(sdev->dev, "error: invalid sof_ext_man header size, type %d size 0x%X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 				elem_hdr->type, elem_hdr->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		/* process structure data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		switch (elem_hdr->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		case SOF_EXT_MAN_ELEM_FW_VERSION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 			ret = ext_man_get_fw_version(sdev, elem_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		case SOF_EXT_MAN_ELEM_WINDOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 			ret = ext_man_get_windows(sdev, elem_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		case SOF_EXT_MAN_ELEM_CC_VERSION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 			ret = ext_man_get_cc_info(sdev, elem_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		case SOF_EXT_MAN_ELEM_DBG_ABI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 			ret = ext_man_get_dbg_abi_info(sdev, elem_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 			dev_warn(sdev->dev, "warning: unknown sof_ext_man header type %d size 0x%X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 				 elem_hdr->type, elem_hdr->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 			dev_err(sdev->dev, "error: failed to parse sof_ext_man header type %d size 0x%X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 				elem_hdr->type, elem_hdr->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		remaining -= elem_hdr->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		iptr += elem_hdr->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	if (remaining) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 		dev_err(sdev->dev, "error: sof_ext_man header is inconsistent\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	return ext_man_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)  * IPC Firmware ready.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static void sof_get_windows(struct snd_sof_dev *sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	struct sof_ipc_window_elem *elem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	u32 outbox_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	u32 stream_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	u32 inbox_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	u32 outbox_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	u32 stream_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	u32 inbox_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	u32 debug_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	u32 debug_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	int window_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	int bar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	if (!sdev->info_window) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 		dev_err(sdev->dev, "error: have no window info\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	bar = snd_sof_dsp_get_bar_index(sdev, SOF_FW_BLK_TYPE_SRAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	if (bar < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 		dev_err(sdev->dev, "error: have no bar mapping\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	for (i = 0; i < sdev->info_window->num_windows; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 		elem = &sdev->info_window->window[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		window_offset = snd_sof_dsp_get_window_offset(sdev, elem->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		if (window_offset < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 			dev_warn(sdev->dev, "warn: no offset for window %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 				 elem->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 		switch (elem->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		case SOF_IPC_REGION_UPBOX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 			inbox_offset = window_offset + elem->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 			inbox_size = elem->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 			snd_sof_debugfs_io_item(sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 						sdev->bar[bar] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 						inbox_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 						elem->size, "inbox",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 						SOF_DEBUGFS_ACCESS_D0_ONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		case SOF_IPC_REGION_DOWNBOX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 			outbox_offset = window_offset + elem->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 			outbox_size = elem->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 			snd_sof_debugfs_io_item(sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 						sdev->bar[bar] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 						outbox_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 						elem->size, "outbox",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 						SOF_DEBUGFS_ACCESS_D0_ONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 		case SOF_IPC_REGION_TRACE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 			snd_sof_debugfs_io_item(sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 						sdev->bar[bar] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 						window_offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 						elem->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 						elem->size, "etrace",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 						SOF_DEBUGFS_ACCESS_D0_ONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 		case SOF_IPC_REGION_DEBUG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 			debug_offset = window_offset + elem->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 			debug_size = elem->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 			snd_sof_debugfs_io_item(sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 						sdev->bar[bar] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 						window_offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 						elem->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 						elem->size, "debug",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 						SOF_DEBUGFS_ACCESS_D0_ONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 		case SOF_IPC_REGION_STREAM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 			stream_offset = window_offset + elem->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 			stream_size = elem->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 			snd_sof_debugfs_io_item(sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 						sdev->bar[bar] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 						stream_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 						elem->size, "stream",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 						SOF_DEBUGFS_ACCESS_D0_ONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 		case SOF_IPC_REGION_REGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 			snd_sof_debugfs_io_item(sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 						sdev->bar[bar] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 						window_offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 						elem->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 						elem->size, "regs",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 						SOF_DEBUGFS_ACCESS_D0_ONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 		case SOF_IPC_REGION_EXCEPTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 			sdev->dsp_oops_offset = window_offset + elem->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 			snd_sof_debugfs_io_item(sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 						sdev->bar[bar] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 						window_offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 						elem->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 						elem->size, "exception",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 						SOF_DEBUGFS_ACCESS_D0_ONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 			dev_err(sdev->dev, "error: get illegal window info\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	if (outbox_size == 0 || inbox_size == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 		dev_err(sdev->dev, "error: get illegal mailbox window\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	snd_sof_dsp_mailbox_init(sdev, inbox_offset, inbox_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 				 outbox_offset, outbox_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	sdev->stream_box.offset = stream_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	sdev->stream_box.size = stream_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	sdev->debug_box.offset = debug_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	sdev->debug_box.size = debug_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	dev_dbg(sdev->dev, " mailbox upstream 0x%x - size 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 		inbox_offset, inbox_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	dev_dbg(sdev->dev, " mailbox downstream 0x%x - size 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 		outbox_offset, outbox_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	dev_dbg(sdev->dev, " stream region 0x%x - size 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 		stream_offset, stream_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	dev_dbg(sdev->dev, " debug region 0x%x - size 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 		debug_offset, debug_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) /* check for ABI compatibility and create memory windows on first boot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) int sof_fw_ready(struct snd_sof_dev *sdev, u32 msg_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	struct sof_ipc_fw_ready *fw_ready = &sdev->fw_ready;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	int bar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	/* mailbox must be on 4k boundary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	offset = snd_sof_dsp_get_mailbox_offset(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	if (offset < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 		dev_err(sdev->dev, "error: have no mailbox offset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 		return offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	bar = snd_sof_dsp_get_bar_index(sdev, SOF_FW_BLK_TYPE_SRAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	if (bar < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 		dev_err(sdev->dev, "error: have no bar mapping\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	dev_dbg(sdev->dev, "ipc: DSP is ready 0x%8.8x offset 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 		msg_id, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	/* no need to re-check version/ABI for subsequent boots */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	if (!sdev->first_boot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	/* copy data from the DSP FW ready offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	sof_block_read(sdev, bar, offset, fw_ready, sizeof(*fw_ready));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	/* make sure ABI version is compatible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	ret = snd_sof_ipc_valid(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 	/* now check for extended data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	snd_sof_fw_parse_ext_data(sdev, bar, offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 				  sizeof(struct sof_ipc_fw_ready));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	sof_get_windows(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) EXPORT_SYMBOL(sof_fw_ready);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) /* generic module parser for mmaped DSPs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) int snd_sof_parse_module_memcpy(struct snd_sof_dev *sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 				struct snd_sof_mod_hdr *module)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	struct snd_sof_blk_hdr *block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	int count, bar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	u32 offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	size_t remaining;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	dev_dbg(sdev->dev, "new module size 0x%x blocks 0x%x type 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 		module->size, module->num_blocks, module->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	block = (struct snd_sof_blk_hdr *)((u8 *)module + sizeof(*module));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	/* module->size doesn't include header size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	remaining = module->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	for (count = 0; count < module->num_blocks; count++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 		/* check for wrap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 		if (remaining < sizeof(*block)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 			dev_err(sdev->dev, "error: not enough data remaining\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 		/* minus header size of block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 		remaining -= sizeof(*block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 		if (block->size == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 			dev_warn(sdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 				 "warning: block %d size zero\n", count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 			dev_warn(sdev->dev, " type 0x%x offset 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 				 block->type, block->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 		switch (block->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 		case SOF_FW_BLK_TYPE_RSRVD0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 		case SOF_FW_BLK_TYPE_ROM...SOF_FW_BLK_TYPE_RSRVD14:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 			continue;	/* not handled atm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 		case SOF_FW_BLK_TYPE_IRAM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 		case SOF_FW_BLK_TYPE_DRAM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 		case SOF_FW_BLK_TYPE_SRAM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 			offset = block->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 			bar = snd_sof_dsp_get_bar_index(sdev, block->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 			if (bar < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 				dev_err(sdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 					"error: no BAR mapping for block type 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 					block->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 				return bar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 			dev_err(sdev->dev, "error: bad type 0x%x for block 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 				block->type, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 		dev_dbg(sdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 			"block %d type 0x%x size 0x%x ==>  offset 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 			count, block->type, block->size, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 		/* checking block->size to avoid unaligned access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 		if (block->size % sizeof(u32)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 			dev_err(sdev->dev, "error: invalid block size 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 				block->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 		snd_sof_dsp_block_write(sdev, bar, offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 					block + 1, block->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 		if (remaining < block->size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 			dev_err(sdev->dev, "error: not enough data remaining\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 		/* minus body size of block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 		remaining -= block->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 		/* next block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 		block = (struct snd_sof_blk_hdr *)((u8 *)block + sizeof(*block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 			+ block->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) EXPORT_SYMBOL(snd_sof_parse_module_memcpy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) static int check_header(struct snd_sof_dev *sdev, const struct firmware *fw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 			size_t fw_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 	struct snd_sof_fw_header *header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	size_t fw_size = fw->size - fw_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	if (fw->size <= fw_offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 		dev_err(sdev->dev, "error: firmware size must be greater than firmware offset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	/* Read the header information from the data pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 	header = (struct snd_sof_fw_header *)(fw->data + fw_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 	/* verify FW sig */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 	if (strncmp(header->sig, SND_SOF_FW_SIG, SND_SOF_FW_SIG_SIZE) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 		dev_err(sdev->dev, "error: invalid firmware signature\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	/* check size is valid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 	if (fw_size != header->file_size + sizeof(*header)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 		dev_err(sdev->dev, "error: invalid filesize mismatch got 0x%zx expected 0x%zx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 			fw_size, header->file_size + sizeof(*header));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	dev_dbg(sdev->dev, "header size=0x%x modules=0x%x abi=0x%x size=%zu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 		header->file_size, header->num_modules,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 		header->abi, sizeof(*header));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) static int load_modules(struct snd_sof_dev *sdev, const struct firmware *fw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 			size_t fw_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	struct snd_sof_fw_header *header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	struct snd_sof_mod_hdr *module;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 	int (*load_module)(struct snd_sof_dev *sof_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 			   struct snd_sof_mod_hdr *hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 	int ret, count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 	size_t remaining;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 	header = (struct snd_sof_fw_header *)(fw->data + fw_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	load_module = sof_ops(sdev)->load_module;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	if (!load_module)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 	/* parse each module */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 	module = (struct snd_sof_mod_hdr *)(fw->data + fw_offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 					    sizeof(*header));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	remaining = fw->size - sizeof(*header) - fw_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	/* check for wrap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 	if (remaining > fw->size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 		dev_err(sdev->dev, "error: fw size smaller than header size\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 	for (count = 0; count < header->num_modules; count++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 		/* check for wrap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 		if (remaining < sizeof(*module)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 			dev_err(sdev->dev, "error: not enough data remaining\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 		/* minus header size of module */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 		remaining -= sizeof(*module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 		/* module */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 		ret = load_module(sdev, module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 		if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 			dev_err(sdev->dev, "error: invalid module %d\n", count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 		if (remaining < module->size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 			dev_err(sdev->dev, "error: not enough data remaining\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 		/* minus body size of module */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 		remaining -=  module->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 		module = (struct snd_sof_mod_hdr *)((u8 *)module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 			+ sizeof(*module) + module->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 	struct snd_sof_pdata *plat_data = sdev->pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 	const char *fw_filename;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 	ssize_t ext_man_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 	/* Don't request firmware again if firmware is already requested */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 	if (plat_data->fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 	fw_filename = kasprintf(GFP_KERNEL, "%s/%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 				plat_data->fw_filename_prefix,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 				plat_data->fw_filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 	if (!fw_filename)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 	ret = request_firmware(&plat_data->fw, fw_filename, sdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 		dev_err(sdev->dev, "error: request firmware %s failed err: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 			fw_filename, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 		dev_dbg(sdev->dev, "request_firmware %s successful\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 			fw_filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 	/* check for extended manifest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 	ext_man_size = snd_sof_fw_ext_man_parse(sdev, plat_data->fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 	if (ext_man_size > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 		/* when no error occurred, drop extended manifest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 		plat_data->fw_offset = ext_man_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 	} else if (!ext_man_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 		/* No extended manifest, so nothing to skip during FW load */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 		dev_dbg(sdev->dev, "firmware doesn't contain extended manifest\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 		ret = ext_man_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 		dev_err(sdev->dev, "error: firmware %s contains unsupported or invalid extended manifest: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 			fw_filename, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 	kfree(fw_filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) EXPORT_SYMBOL(snd_sof_load_firmware_raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) int snd_sof_load_firmware_memcpy(struct snd_sof_dev *sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 	struct snd_sof_pdata *plat_data = sdev->pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 	ret = snd_sof_load_firmware_raw(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 	/* make sure the FW header and file is valid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 	ret = check_header(sdev, plat_data->fw, plat_data->fw_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 		dev_err(sdev->dev, "error: invalid FW header\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 	/* prepare the DSP for FW loading */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 	ret = snd_sof_dsp_reset(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 		dev_err(sdev->dev, "error: failed to reset DSP\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 	/* parse and load firmware modules to DSP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 	ret = load_modules(sdev, plat_data->fw, plat_data->fw_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 		dev_err(sdev->dev, "error: invalid FW modules\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 	release_firmware(plat_data->fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 	plat_data->fw = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) EXPORT_SYMBOL(snd_sof_load_firmware_memcpy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) int snd_sof_load_firmware(struct snd_sof_dev *sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 	dev_dbg(sdev->dev, "loading firmware\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 	if (sof_ops(sdev)->load_firmware)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 		return sof_ops(sdev)->load_firmware(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) EXPORT_SYMBOL(snd_sof_load_firmware);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) int snd_sof_run_firmware(struct snd_sof_dev *sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) 	int init_core_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) 	init_waitqueue_head(&sdev->boot_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) 	/* create read-only fw_version debugfs to store boot version info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) 	if (sdev->first_boot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) 		ret = snd_sof_debugfs_buf_item(sdev, &sdev->fw_version,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) 					       sizeof(sdev->fw_version),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) 					       "fw_version", 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) 		/* errors are only due to memory allocation, not debugfs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) 		if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 			dev_err(sdev->dev, "error: snd_sof_debugfs_buf_item failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) 	/* perform pre fw run operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) 	ret = snd_sof_dsp_pre_fw_run(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) 		dev_err(sdev->dev, "error: failed pre fw run op\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) 	dev_dbg(sdev->dev, "booting DSP firmware\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) 	/* boot the firmware on the DSP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) 	ret = snd_sof_dsp_run(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) 		dev_err(sdev->dev, "error: failed to reset DSP\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) 	init_core_mask = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) 	 * now wait for the DSP to boot. There are 3 possible outcomes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) 	 * 1. Boot wait times out indicating FW boot failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) 	 * 2. FW boots successfully and fw_ready op succeeds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) 	 * 3. FW boots but fw_ready op fails.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) 	ret = wait_event_timeout(sdev->boot_wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) 				 sdev->fw_state > SOF_FW_BOOT_IN_PROGRESS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) 				 msecs_to_jiffies(sdev->boot_timeout));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) 	if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) 		dev_err(sdev->dev, "error: firmware boot failure\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) 		snd_sof_dsp_dbg_dump(sdev, SOF_DBG_REGS | SOF_DBG_MBOX |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) 			SOF_DBG_TEXT | SOF_DBG_PCI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 		sdev->fw_state = SOF_FW_BOOT_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) 	if (sdev->fw_state == SOF_FW_BOOT_COMPLETE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) 		dev_dbg(sdev->dev, "firmware boot complete\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 		return -EIO; /* FW boots but fw_ready op failed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) 	/* perform post fw run operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) 	ret = snd_sof_dsp_post_fw_run(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) 		dev_err(sdev->dev, "error: failed post fw run op\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) 	/* fw boot is complete. Update the active cores mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) 	sdev->enabled_cores_mask = init_core_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) EXPORT_SYMBOL(snd_sof_run_firmware);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) void snd_sof_fw_unload(struct snd_sof_dev *sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) 	/* TODO: support module unloading at runtime */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) 	release_firmware(sdev->pdata->fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) 	sdev->pdata->fw = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) EXPORT_SYMBOL(snd_sof_fw_unload);