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 * @sst_drv_ctx: intel_sst_drv context pointer 53 * 54 * This resets DSP in case of MRFLD platfroms 55 */ 56 int intel_sst_reset_dsp_mrfld(struct intel_sst_drv *sst_drv_ctx) 57 { 58 union config_status_reg_mrfld csr; 59 60 dev_dbg(sst_drv_ctx->dev, "sst: Resetting the DSP in mrfld\n"); 61 csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR); 62 63 dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full); 64 65 csr.full |= 0x7; 66 sst_shim_write64(sst_drv_ctx->shim, SST_CSR, csr.full); 67 csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR); 68 69 dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full); 70 71 csr.full &= ~(0x1); 72 sst_shim_write64(sst_drv_ctx->shim, SST_CSR, csr.full); 73 74 csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR); 75 dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full); 76 return 0; 77 } 78 79 /** 80 * sst_start_merrifield - Start the SST DSP processor 81 * @sst_drv_ctx: intel_sst_drv context pointer 82 * 83 * This starts the DSP in MERRIFIELD platfroms 84 */ 85 int sst_start_mrfld(struct intel_sst_drv *sst_drv_ctx) 86 { 87 union config_status_reg_mrfld csr; 88 89 dev_dbg(sst_drv_ctx->dev, "sst: Starting the DSP in mrfld LALALALA\n"); 90 csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR); 91 dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full); 92 93 csr.full |= 0x7; 94 sst_shim_write64(sst_drv_ctx->shim, SST_CSR, csr.full); 95 96 csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR); 97 dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full); 98 99 csr.part.xt_snoop = 1; 100 csr.full &= ~(0x5); 101 sst_shim_write64(sst_drv_ctx->shim, SST_CSR, csr.full); 102 103 csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR); 104 dev_dbg(sst_drv_ctx->dev, "sst: Starting the DSP_merrifield:%llx\n", 105 csr.full); 106 return 0; 107 } 108 109 static int sst_validate_fw_image(struct intel_sst_drv *ctx, unsigned long size, 110 struct fw_module_header **module, u32 *num_modules) 111 { 112 struct sst_fw_header *header; 113 const void *sst_fw_in_mem = ctx->fw_in_mem; 114 115 dev_dbg(ctx->dev, "Enter\n"); 116 117 /* Read the header information from the data pointer */ 118 header = (struct sst_fw_header *)sst_fw_in_mem; 119 dev_dbg(ctx->dev, 120 "header sign=%s size=%x modules=%x fmt=%x size=%zx\n", 121 header->signature, header->file_size, header->modules, 122 header->file_format, sizeof(*header)); 123 124 /* verify FW */ 125 if ((strncmp(header->signature, SST_FW_SIGN, 4) != 0) || 126 (size != header->file_size + sizeof(*header))) { 127 /* Invalid FW signature */ 128 dev_err(ctx->dev, "InvalidFW sign/filesize mismatch\n"); 129 return -EINVAL; 130 } 131 *num_modules = header->modules; 132 *module = (void *)sst_fw_in_mem + sizeof(*header); 133 134 return 0; 135 } 136 137 /* 138 * sst_fill_memcpy_list - Fill the memcpy list 139 * 140 * @memcpy_list: List to be filled 141 * @destn: Destination addr to be filled in the list 142 * @src: Source addr to be filled in the list 143 * @size: Size to be filled in the list 144 * 145 * Adds the node to the list after required fields 146 * are populated in the node 147 */ 148 static int sst_fill_memcpy_list(struct list_head *memcpy_list, 149 void *destn, const void *src, u32 size, bool is_io) 150 { 151 struct sst_memcpy_list *listnode; 152 153 listnode = kzalloc(sizeof(*listnode), GFP_KERNEL); 154 if (listnode == NULL) 155 return -ENOMEM; 156 listnode->dstn = destn; 157 listnode->src = src; 158 listnode->size = size; 159 listnode->is_io = is_io; 160 list_add_tail(&listnode->memcpylist, memcpy_list); 161 162 return 0; 163 } 164 165 /** 166 * sst_parse_module_memcpy - Parse audio FW modules and populate the memcpy list 167 * 168 * @sst_drv_ctx : driver context 169 * @module : FW module header 170 * @memcpy_list : Pointer to the list to be populated 171 * Create the memcpy list as the number of block to be copied 172 * returns error or 0 if module sizes are proper 173 */ 174 static int sst_parse_module_memcpy(struct intel_sst_drv *sst_drv_ctx, 175 struct fw_module_header *module, struct list_head *memcpy_list) 176 { 177 struct fw_block_info *block; 178 u32 count; 179 int ret_val = 0; 180 void __iomem *ram_iomem; 181 182 dev_dbg(sst_drv_ctx->dev, "module sign %s size %x blocks %x type %x\n", 183 module->signature, module->mod_size, 184 module->blocks, module->type); 185 dev_dbg(sst_drv_ctx->dev, "module entrypoint 0x%x\n", module->entry_point); 186 187 block = (void *)module + sizeof(*module); 188 189 for (count = 0; count < module->blocks; count++) { 190 if (block->size <= 0) { 191 dev_err(sst_drv_ctx->dev, "block size invalid\n"); 192 return -EINVAL; 193 } 194 switch (block->type) { 195 case SST_IRAM: 196 ram_iomem = sst_drv_ctx->iram; 197 break; 198 case SST_DRAM: 199 ram_iomem = sst_drv_ctx->dram; 200 break; 201 case SST_DDR: 202 ram_iomem = sst_drv_ctx->ddr; 203 break; 204 case SST_CUSTOM_INFO: 205 block = (void *)block + sizeof(*block) + block->size; 206 continue; 207 default: 208 dev_err(sst_drv_ctx->dev, "wrong ram type0x%x in block0x%x\n", 209 block->type, count); 210 return -EINVAL; 211 } 212 213 ret_val = sst_fill_memcpy_list(memcpy_list, 214 ram_iomem + block->ram_offset, 215 (void *)block + sizeof(*block), block->size, 1); 216 if (ret_val) 217 return ret_val; 218 219 block = (void *)block + sizeof(*block) + block->size; 220 } 221 return 0; 222 } 223 224 /** 225 * sst_parse_fw_memcpy - parse the firmware image & populate the list for memcpy 226 * 227 * @ctx : pointer to drv context 228 * @size : size of the firmware 229 * @fw_list : pointer to list_head to be populated 230 * This function parses the FW image and saves the parsed image in the list 231 * for memcpy 232 */ 233 static int sst_parse_fw_memcpy(struct intel_sst_drv *ctx, unsigned long size, 234 struct list_head *fw_list) 235 { 236 struct fw_module_header *module; 237 u32 count, num_modules; 238 int ret_val; 239 240 ret_val = sst_validate_fw_image(ctx, size, &module, &num_modules); 241 if (ret_val) 242 return ret_val; 243 244 for (count = 0; count < num_modules; count++) { 245 ret_val = sst_parse_module_memcpy(ctx, module, fw_list); 246 if (ret_val) 247 return ret_val; 248 module = (void *)module + sizeof(*module) + module->mod_size; 249 } 250 251 return 0; 252 } 253 254 /** 255 * sst_do_memcpy - function initiates the memcpy 256 * 257 * @memcpy_list: Pter to memcpy list on which the memcpy needs to be initiated 258 * 259 * Triggers the memcpy 260 */ 261 static void sst_do_memcpy(struct list_head *memcpy_list) 262 { 263 struct sst_memcpy_list *listnode; 264 265 list_for_each_entry(listnode, memcpy_list, memcpylist) { 266 if (listnode->is_io) 267 memcpy32_toio((void __iomem *)listnode->dstn, 268 listnode->src, listnode->size); 269 else 270 memcpy(listnode->dstn, listnode->src, listnode->size); 271 } 272 } 273 274 void sst_memcpy_free_resources(struct intel_sst_drv *sst_drv_ctx) 275 { 276 struct sst_memcpy_list *listnode, *tmplistnode; 277 278 /* Free the list */ 279 list_for_each_entry_safe(listnode, tmplistnode, 280 &sst_drv_ctx->memcpy_list, memcpylist) { 281 list_del(&listnode->memcpylist); 282 kfree(listnode); 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 * @sst_drv_ctx: intel_sst_drv context pointer 391 * 392 * Transfers the FW to DSP using dma/memcpy 393 */ 394 int sst_load_fw(struct intel_sst_drv *sst_drv_ctx) 395 { 396 int ret_val = 0; 397 struct sst_block *block; 398 399 dev_dbg(sst_drv_ctx->dev, "sst_load_fw\n"); 400 401 if (sst_drv_ctx->sst_state != SST_RESET || 402 sst_drv_ctx->sst_state == SST_SHUTDOWN) 403 return -EAGAIN; 404 405 if (!sst_drv_ctx->fw_in_mem) { 406 dev_dbg(sst_drv_ctx->dev, "sst: FW not in memory retry to download\n"); 407 ret_val = sst_request_fw(sst_drv_ctx); 408 if (ret_val) 409 return ret_val; 410 } 411 412 block = sst_create_block(sst_drv_ctx, 0, FW_DWNL_ID); 413 if (block == NULL) 414 return -ENOMEM; 415 416 /* Prevent C-states beyond C6 */ 417 cpu_latency_qos_update_request(sst_drv_ctx->qos, 0); 418 419 sst_drv_ctx->sst_state = SST_FW_LOADING; 420 421 ret_val = sst_drv_ctx->ops->reset(sst_drv_ctx); 422 if (ret_val) 423 goto restore; 424 425 sst_do_memcpy(&sst_drv_ctx->memcpy_list); 426 427 /* Write the DRAM/DCCM config before enabling FW */ 428 if (sst_drv_ctx->ops->post_download) 429 sst_drv_ctx->ops->post_download(sst_drv_ctx); 430 431 /* bring sst out of reset */ 432 ret_val = sst_drv_ctx->ops->start(sst_drv_ctx); 433 if (ret_val) 434 goto restore; 435 436 ret_val = sst_wait_timeout(sst_drv_ctx, block); 437 if (ret_val) { 438 dev_err(sst_drv_ctx->dev, "fw download failed %d\n" , ret_val); 439 /* FW download failed due to timeout */ 440 ret_val = -EBUSY; 441 442 } 443 444 445 restore: 446 /* Re-enable Deeper C-states beyond C6 */ 447 cpu_latency_qos_update_request(sst_drv_ctx->qos, PM_QOS_DEFAULT_VALUE); 448 sst_free_block(sst_drv_ctx, block); 449 dev_dbg(sst_drv_ctx->dev, "fw load successful!!!\n"); 450 451 if (sst_drv_ctx->ops->restore_dsp_context) 452 sst_drv_ctx->ops->restore_dsp_context(); 453 sst_drv_ctx->sst_state = SST_FW_RUNNING; 454 return ret_val; 455 } 456 457