1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * sst_dsp.c - Intel SST Driver for audio engine 4 * 5 * Copyright (C) 2008-14 Intel Corp 6 * Authors: Vinod Koul <vinod.koul@intel.com> 7 * Harsha Priya <priya.harsha@intel.com> 8 * Dharageswari R <dharageswari.r@intel.com> 9 * KP Jeeja <jeeja.kp@intel.com> 10 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11 * 12 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 13 * 14 * This file contains all dsp controlling functions like firmware download, 15 * setting/resetting dsp cores, etc 16 */ 17 #include <linux/pci.h> 18 #include <linux/delay.h> 19 #include <linux/fs.h> 20 #include <linux/sched.h> 21 #include <linux/firmware.h> 22 #include <linux/dmaengine.h> 23 #include <linux/pm_runtime.h> 24 #include <linux/pm_qos.h> 25 #include <sound/core.h> 26 #include <sound/pcm.h> 27 #include <sound/soc.h> 28 #include <sound/compress_driver.h> 29 #include <asm/platform_sst_audio.h> 30 #include "../sst-mfld-platform.h" 31 #include "sst.h" 32 #include "../../common/sst-dsp.h" 33 34 void memcpy32_toio(void __iomem *dst, const void *src, int count) 35 { 36 /* __iowrite32_copy uses 32-bit count values so divide by 4 for 37 * right count in words 38 */ 39 __iowrite32_copy(dst, src, count / 4); 40 } 41 42 void memcpy32_fromio(void *dst, const void __iomem *src, int count) 43 { 44 /* __ioread32_copy uses 32-bit count values so divide by 4 for 45 * right count in words 46 */ 47 __ioread32_copy(dst, src, count / 4); 48 } 49 50 /** 51 * intel_sst_reset_dsp_mrfld - Resetting SST DSP 52 * 53 * This resets DSP in case of MRFLD platfroms 54 */ 55 int intel_sst_reset_dsp_mrfld(struct intel_sst_drv *sst_drv_ctx) 56 { 57 union config_status_reg_mrfld csr; 58 59 dev_dbg(sst_drv_ctx->dev, "sst: Resetting the DSP in mrfld\n"); 60 csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR); 61 62 dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full); 63 64 csr.full |= 0x7; 65 sst_shim_write64(sst_drv_ctx->shim, SST_CSR, csr.full); 66 csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR); 67 68 dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full); 69 70 csr.full &= ~(0x1); 71 sst_shim_write64(sst_drv_ctx->shim, SST_CSR, csr.full); 72 73 csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR); 74 dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full); 75 return 0; 76 } 77 78 /** 79 * sst_start_merrifield - Start the SST DSP processor 80 * 81 * This starts the DSP in MERRIFIELD platfroms 82 */ 83 int sst_start_mrfld(struct intel_sst_drv *sst_drv_ctx) 84 { 85 union config_status_reg_mrfld csr; 86 87 dev_dbg(sst_drv_ctx->dev, "sst: Starting the DSP in mrfld LALALALA\n"); 88 csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR); 89 dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full); 90 91 csr.full |= 0x7; 92 sst_shim_write64(sst_drv_ctx->shim, SST_CSR, csr.full); 93 94 csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR); 95 dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full); 96 97 csr.part.xt_snoop = 1; 98 csr.full &= ~(0x5); 99 sst_shim_write64(sst_drv_ctx->shim, SST_CSR, csr.full); 100 101 csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR); 102 dev_dbg(sst_drv_ctx->dev, "sst: Starting the DSP_merrifield:%llx\n", 103 csr.full); 104 return 0; 105 } 106 107 static int sst_validate_fw_image(struct intel_sst_drv *ctx, unsigned long size, 108 struct fw_module_header **module, u32 *num_modules) 109 { 110 struct sst_fw_header *header; 111 const void *sst_fw_in_mem = ctx->fw_in_mem; 112 113 dev_dbg(ctx->dev, "Enter\n"); 114 115 /* Read the header information from the data pointer */ 116 header = (struct sst_fw_header *)sst_fw_in_mem; 117 dev_dbg(ctx->dev, 118 "header sign=%s size=%x modules=%x fmt=%x size=%zx\n", 119 header->signature, header->file_size, header->modules, 120 header->file_format, sizeof(*header)); 121 122 /* verify FW */ 123 if ((strncmp(header->signature, SST_FW_SIGN, 4) != 0) || 124 (size != header->file_size + sizeof(*header))) { 125 /* Invalid FW signature */ 126 dev_err(ctx->dev, "InvalidFW sign/filesize mismatch\n"); 127 return -EINVAL; 128 } 129 *num_modules = header->modules; 130 *module = (void *)sst_fw_in_mem + sizeof(*header); 131 132 return 0; 133 } 134 135 /* 136 * sst_fill_memcpy_list - Fill the memcpy list 137 * 138 * @memcpy_list: List to be filled 139 * @destn: Destination addr to be filled in the list 140 * @src: Source addr to be filled in the list 141 * @size: Size to be filled in the list 142 * 143 * Adds the node to the list after required fields 144 * are populated in the node 145 */ 146 static int sst_fill_memcpy_list(struct list_head *memcpy_list, 147 void *destn, const void *src, u32 size, bool is_io) 148 { 149 struct sst_memcpy_list *listnode; 150 151 listnode = kzalloc(sizeof(*listnode), GFP_KERNEL); 152 if (listnode == NULL) 153 return -ENOMEM; 154 listnode->dstn = destn; 155 listnode->src = src; 156 listnode->size = size; 157 listnode->is_io = is_io; 158 list_add_tail(&listnode->memcpylist, memcpy_list); 159 160 return 0; 161 } 162 163 /** 164 * sst_parse_module_memcpy - Parse audio FW modules and populate the memcpy list 165 * 166 * @sst_drv_ctx : driver context 167 * @module : FW module header 168 * @memcpy_list : Pointer to the list to be populated 169 * Create the memcpy list as the number of block to be copied 170 * returns error or 0 if module sizes are proper 171 */ 172 static int sst_parse_module_memcpy(struct intel_sst_drv *sst_drv_ctx, 173 struct fw_module_header *module, struct list_head *memcpy_list) 174 { 175 struct fw_block_info *block; 176 u32 count; 177 int ret_val = 0; 178 void __iomem *ram_iomem; 179 180 dev_dbg(sst_drv_ctx->dev, "module sign %s size %x blocks %x type %x\n", 181 module->signature, module->mod_size, 182 module->blocks, module->type); 183 dev_dbg(sst_drv_ctx->dev, "module entrypoint 0x%x\n", module->entry_point); 184 185 block = (void *)module + sizeof(*module); 186 187 for (count = 0; count < module->blocks; count++) { 188 if (block->size <= 0) { 189 dev_err(sst_drv_ctx->dev, "block size invalid\n"); 190 return -EINVAL; 191 } 192 switch (block->type) { 193 case SST_IRAM: 194 ram_iomem = sst_drv_ctx->iram; 195 break; 196 case SST_DRAM: 197 ram_iomem = sst_drv_ctx->dram; 198 break; 199 case SST_DDR: 200 ram_iomem = sst_drv_ctx->ddr; 201 break; 202 case SST_CUSTOM_INFO: 203 block = (void *)block + sizeof(*block) + block->size; 204 continue; 205 default: 206 dev_err(sst_drv_ctx->dev, "wrong ram type0x%x in block0x%x\n", 207 block->type, count); 208 return -EINVAL; 209 } 210 211 ret_val = sst_fill_memcpy_list(memcpy_list, 212 ram_iomem + block->ram_offset, 213 (void *)block + sizeof(*block), block->size, 1); 214 if (ret_val) 215 return ret_val; 216 217 block = (void *)block + sizeof(*block) + block->size; 218 } 219 return 0; 220 } 221 222 /** 223 * sst_parse_fw_memcpy - parse the firmware image & populate the list for memcpy 224 * 225 * @ctx : pointer to drv context 226 * @size : size of the firmware 227 * @fw_list : pointer to list_head to be populated 228 * This function parses the FW image and saves the parsed image in the list 229 * for memcpy 230 */ 231 static int sst_parse_fw_memcpy(struct intel_sst_drv *ctx, unsigned long size, 232 struct list_head *fw_list) 233 { 234 struct fw_module_header *module; 235 u32 count, num_modules; 236 int ret_val; 237 238 ret_val = sst_validate_fw_image(ctx, size, &module, &num_modules); 239 if (ret_val) 240 return ret_val; 241 242 for (count = 0; count < num_modules; count++) { 243 ret_val = sst_parse_module_memcpy(ctx, module, fw_list); 244 if (ret_val) 245 return ret_val; 246 module = (void *)module + sizeof(*module) + module->mod_size; 247 } 248 249 return 0; 250 } 251 252 /** 253 * sst_do_memcpy - function initiates the memcpy 254 * 255 * @memcpy_list: Pter to memcpy list on which the memcpy needs to be initiated 256 * 257 * Triggers the memcpy 258 */ 259 static void sst_do_memcpy(struct list_head *memcpy_list) 260 { 261 struct sst_memcpy_list *listnode; 262 263 list_for_each_entry(listnode, memcpy_list, memcpylist) { 264 if (listnode->is_io) 265 memcpy32_toio((void __iomem *)listnode->dstn, 266 listnode->src, listnode->size); 267 else 268 memcpy(listnode->dstn, listnode->src, listnode->size); 269 } 270 } 271 272 void sst_memcpy_free_resources(struct intel_sst_drv *sst_drv_ctx) 273 { 274 struct sst_memcpy_list *listnode, *tmplistnode; 275 276 /* Free the list */ 277 if (!list_empty(&sst_drv_ctx->memcpy_list)) { 278 list_for_each_entry_safe(listnode, tmplistnode, 279 &sst_drv_ctx->memcpy_list, memcpylist) { 280 list_del(&listnode->memcpylist); 281 kfree(listnode); 282 } 283 } 284 } 285 286 static int sst_cache_and_parse_fw(struct intel_sst_drv *sst, 287 const struct firmware *fw) 288 { 289 int retval = 0; 290 291 sst->fw_in_mem = kzalloc(fw->size, GFP_KERNEL); 292 if (!sst->fw_in_mem) { 293 retval = -ENOMEM; 294 goto end_release; 295 } 296 dev_dbg(sst->dev, "copied fw to %p", sst->fw_in_mem); 297 dev_dbg(sst->dev, "phys: %lx", (unsigned long)virt_to_phys(sst->fw_in_mem)); 298 memcpy(sst->fw_in_mem, fw->data, fw->size); 299 retval = sst_parse_fw_memcpy(sst, fw->size, &sst->memcpy_list); 300 if (retval) { 301 dev_err(sst->dev, "Failed to parse fw\n"); 302 kfree(sst->fw_in_mem); 303 sst->fw_in_mem = NULL; 304 } 305 306 end_release: 307 release_firmware(fw); 308 return retval; 309 310 } 311 312 void sst_firmware_load_cb(const struct firmware *fw, void *context) 313 { 314 struct intel_sst_drv *ctx = context; 315 316 dev_dbg(ctx->dev, "Enter\n"); 317 318 if (fw == NULL) { 319 dev_err(ctx->dev, "request fw failed\n"); 320 return; 321 } 322 323 mutex_lock(&ctx->sst_lock); 324 325 if (ctx->sst_state != SST_RESET || 326 ctx->fw_in_mem != NULL) { 327 release_firmware(fw); 328 mutex_unlock(&ctx->sst_lock); 329 return; 330 } 331 332 dev_dbg(ctx->dev, "Request Fw completed\n"); 333 sst_cache_and_parse_fw(ctx, fw); 334 mutex_unlock(&ctx->sst_lock); 335 } 336 337 /* 338 * sst_request_fw - requests audio fw from kernel and saves a copy 339 * 340 * This function requests the SST FW from the kernel, parses it and 341 * saves a copy in the driver context 342 */ 343 static int sst_request_fw(struct intel_sst_drv *sst) 344 { 345 int retval = 0; 346 const struct firmware *fw; 347 348 retval = request_firmware(&fw, sst->firmware_name, sst->dev); 349 if (retval) { 350 dev_err(sst->dev, "request fw failed %d\n", retval); 351 return retval; 352 } 353 if (fw == NULL) { 354 dev_err(sst->dev, "fw is returning as null\n"); 355 return -EINVAL; 356 } 357 mutex_lock(&sst->sst_lock); 358 retval = sst_cache_and_parse_fw(sst, fw); 359 mutex_unlock(&sst->sst_lock); 360 361 return retval; 362 } 363 364 /* 365 * Writing the DDR physical base to DCCM offset 366 * so that FW can use it to setup TLB 367 */ 368 static void sst_dccm_config_write(void __iomem *dram_base, 369 unsigned int ddr_base) 370 { 371 void __iomem *addr; 372 u32 bss_reset = 0; 373 374 addr = (void __iomem *)(dram_base + MRFLD_FW_DDR_BASE_OFFSET); 375 memcpy32_toio(addr, (void *)&ddr_base, sizeof(u32)); 376 bss_reset |= (1 << MRFLD_FW_BSS_RESET_BIT); 377 addr = (void __iomem *)(dram_base + MRFLD_FW_FEATURE_BASE_OFFSET); 378 memcpy32_toio(addr, &bss_reset, sizeof(u32)); 379 380 } 381 382 void sst_post_download_mrfld(struct intel_sst_drv *ctx) 383 { 384 sst_dccm_config_write(ctx->dram, ctx->ddr_base); 385 dev_dbg(ctx->dev, "config written to DCCM\n"); 386 } 387 388 /** 389 * sst_load_fw - function to load FW into DSP 390 * Transfers the FW to DSP using dma/memcpy 391 */ 392 int sst_load_fw(struct intel_sst_drv *sst_drv_ctx) 393 { 394 int ret_val = 0; 395 struct sst_block *block; 396 397 dev_dbg(sst_drv_ctx->dev, "sst_load_fw\n"); 398 399 if (sst_drv_ctx->sst_state != SST_RESET || 400 sst_drv_ctx->sst_state == SST_SHUTDOWN) 401 return -EAGAIN; 402 403 if (!sst_drv_ctx->fw_in_mem) { 404 dev_dbg(sst_drv_ctx->dev, "sst: FW not in memory retry to download\n"); 405 ret_val = sst_request_fw(sst_drv_ctx); 406 if (ret_val) 407 return ret_val; 408 } 409 410 block = sst_create_block(sst_drv_ctx, 0, FW_DWNL_ID); 411 if (block == NULL) 412 return -ENOMEM; 413 414 /* Prevent C-states beyond C6 */ 415 pm_qos_update_request(sst_drv_ctx->qos, 0); 416 417 sst_drv_ctx->sst_state = SST_FW_LOADING; 418 419 ret_val = sst_drv_ctx->ops->reset(sst_drv_ctx); 420 if (ret_val) 421 goto restore; 422 423 sst_do_memcpy(&sst_drv_ctx->memcpy_list); 424 425 /* Write the DRAM/DCCM config before enabling FW */ 426 if (sst_drv_ctx->ops->post_download) 427 sst_drv_ctx->ops->post_download(sst_drv_ctx); 428 429 /* bring sst out of reset */ 430 ret_val = sst_drv_ctx->ops->start(sst_drv_ctx); 431 if (ret_val) 432 goto restore; 433 434 ret_val = sst_wait_timeout(sst_drv_ctx, block); 435 if (ret_val) { 436 dev_err(sst_drv_ctx->dev, "fw download failed %d\n" , ret_val); 437 /* FW download failed due to timeout */ 438 ret_val = -EBUSY; 439 440 } 441 442 443 restore: 444 /* Re-enable Deeper C-states beyond C6 */ 445 pm_qos_update_request(sst_drv_ctx->qos, PM_QOS_DEFAULT_VALUE); 446 sst_free_block(sst_drv_ctx, block); 447 dev_dbg(sst_drv_ctx->dev, "fw load successful!!!\n"); 448 449 if (sst_drv_ctx->ops->restore_dsp_context) 450 sst_drv_ctx->ops->restore_dsp_context(); 451 sst_drv_ctx->sst_state = SST_FW_RUNNING; 452 return ret_val; 453 } 454 455