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_qos.h> 24 #include <sound/core.h> 25 #include <sound/pcm.h> 26 #include <sound/soc.h> 27 #include <sound/compress_driver.h> 28 #include <asm/platform_sst_audio.h> 29 #include "../sst-mfld-platform.h" 30 #include "sst.h" 31 32 void memcpy32_toio(void __iomem *dst, const void *src, int count) 33 { 34 /* __iowrite32_copy uses 32-bit count values so divide by 4 for 35 * right count in words 36 */ 37 __iowrite32_copy(dst, src, count / 4); 38 } 39 40 void memcpy32_fromio(void *dst, const void __iomem *src, int count) 41 { 42 /* __ioread32_copy uses 32-bit count values so divide by 4 for 43 * right count in words 44 */ 45 __ioread32_copy(dst, src, count / 4); 46 } 47 48 /** 49 * intel_sst_reset_dsp_mrfld - Resetting SST DSP 50 * @sst_drv_ctx: intel_sst_drv context pointer 51 * 52 * This resets DSP in case of MRFLD platfroms 53 */ 54 int intel_sst_reset_dsp_mrfld(struct intel_sst_drv *sst_drv_ctx) 55 { 56 union config_status_reg_mrfld csr; 57 58 dev_dbg(sst_drv_ctx->dev, "sst: Resetting the DSP in mrfld\n"); 59 csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR); 60 61 dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full); 62 63 csr.full |= 0x7; 64 sst_shim_write64(sst_drv_ctx->shim, SST_CSR, csr.full); 65 csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR); 66 67 dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full); 68 69 csr.full &= ~(0x1); 70 sst_shim_write64(sst_drv_ctx->shim, SST_CSR, csr.full); 71 72 csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR); 73 dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full); 74 return 0; 75 } 76 77 /** 78 * sst_start_mrfld - Start the SST DSP processor 79 * @sst_drv_ctx: intel_sst_drv context pointer 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 list_for_each_entry_safe(listnode, tmplistnode, 278 &sst_drv_ctx->memcpy_list, memcpylist) { 279 list_del(&listnode->memcpylist); 280 kfree(listnode); 281 } 282 } 283 284 static int sst_cache_and_parse_fw(struct intel_sst_drv *sst, 285 const struct firmware *fw) 286 { 287 int retval = 0; 288 289 sst->fw_in_mem = kzalloc(fw->size, GFP_KERNEL); 290 if (!sst->fw_in_mem) { 291 retval = -ENOMEM; 292 goto end_release; 293 } 294 dev_dbg(sst->dev, "copied fw to %p", sst->fw_in_mem); 295 dev_dbg(sst->dev, "phys: %lx", (unsigned long)virt_to_phys(sst->fw_in_mem)); 296 memcpy(sst->fw_in_mem, fw->data, fw->size); 297 retval = sst_parse_fw_memcpy(sst, fw->size, &sst->memcpy_list); 298 if (retval) { 299 dev_err(sst->dev, "Failed to parse fw\n"); 300 kfree(sst->fw_in_mem); 301 sst->fw_in_mem = NULL; 302 } 303 304 end_release: 305 release_firmware(fw); 306 return retval; 307 308 } 309 310 void sst_firmware_load_cb(const struct firmware *fw, void *context) 311 { 312 struct intel_sst_drv *ctx = context; 313 314 dev_dbg(ctx->dev, "Enter\n"); 315 316 if (fw == NULL) { 317 dev_err(ctx->dev, "request fw failed\n"); 318 return; 319 } 320 321 mutex_lock(&ctx->sst_lock); 322 323 if (ctx->sst_state != SST_RESET || 324 ctx->fw_in_mem != NULL) { 325 release_firmware(fw); 326 mutex_unlock(&ctx->sst_lock); 327 return; 328 } 329 330 dev_dbg(ctx->dev, "Request Fw completed\n"); 331 sst_cache_and_parse_fw(ctx, fw); 332 mutex_unlock(&ctx->sst_lock); 333 } 334 335 /* 336 * sst_request_fw - requests audio fw from kernel and saves a copy 337 * 338 * This function requests the SST FW from the kernel, parses it and 339 * saves a copy in the driver context 340 */ 341 static int sst_request_fw(struct intel_sst_drv *sst) 342 { 343 int retval = 0; 344 const struct firmware *fw; 345 346 retval = request_firmware(&fw, sst->firmware_name, sst->dev); 347 if (retval) { 348 dev_err(sst->dev, "request fw failed %d\n", retval); 349 return retval; 350 } 351 if (fw == NULL) { 352 dev_err(sst->dev, "fw is returning as null\n"); 353 return -EINVAL; 354 } 355 mutex_lock(&sst->sst_lock); 356 retval = sst_cache_and_parse_fw(sst, fw); 357 mutex_unlock(&sst->sst_lock); 358 359 return retval; 360 } 361 362 /* 363 * Writing the DDR physical base to DCCM offset 364 * so that FW can use it to setup TLB 365 */ 366 static void sst_dccm_config_write(void __iomem *dram_base, 367 unsigned int ddr_base) 368 { 369 void __iomem *addr; 370 u32 bss_reset = 0; 371 372 addr = (void __iomem *)(dram_base + MRFLD_FW_DDR_BASE_OFFSET); 373 memcpy32_toio(addr, (void *)&ddr_base, sizeof(u32)); 374 bss_reset |= (1 << MRFLD_FW_BSS_RESET_BIT); 375 addr = (void __iomem *)(dram_base + MRFLD_FW_FEATURE_BASE_OFFSET); 376 memcpy32_toio(addr, &bss_reset, sizeof(u32)); 377 378 } 379 380 void sst_post_download_mrfld(struct intel_sst_drv *ctx) 381 { 382 sst_dccm_config_write(ctx->dram, ctx->ddr_base); 383 dev_dbg(ctx->dev, "config written to DCCM\n"); 384 } 385 386 /** 387 * sst_load_fw - function to load FW into DSP 388 * @sst_drv_ctx: intel_sst_drv context pointer 389 * 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 return -EAGAIN; 401 402 if (!sst_drv_ctx->fw_in_mem) { 403 dev_dbg(sst_drv_ctx->dev, "sst: FW not in memory retry to download\n"); 404 ret_val = sst_request_fw(sst_drv_ctx); 405 if (ret_val) 406 return ret_val; 407 } 408 409 block = sst_create_block(sst_drv_ctx, 0, FW_DWNL_ID); 410 if (block == NULL) 411 return -ENOMEM; 412 413 /* Prevent C-states beyond C6 */ 414 cpu_latency_qos_update_request(sst_drv_ctx->qos, 0); 415 416 sst_drv_ctx->sst_state = SST_FW_LOADING; 417 418 ret_val = sst_drv_ctx->ops->reset(sst_drv_ctx); 419 if (ret_val) 420 goto restore; 421 422 sst_do_memcpy(&sst_drv_ctx->memcpy_list); 423 424 /* Write the DRAM/DCCM config before enabling FW */ 425 if (sst_drv_ctx->ops->post_download) 426 sst_drv_ctx->ops->post_download(sst_drv_ctx); 427 428 /* bring sst out of reset */ 429 ret_val = sst_drv_ctx->ops->start(sst_drv_ctx); 430 if (ret_val) 431 goto restore; 432 433 ret_val = sst_wait_timeout(sst_drv_ctx, block); 434 if (ret_val) { 435 dev_err(sst_drv_ctx->dev, "fw download failed %d\n" , ret_val); 436 /* FW download failed due to timeout */ 437 ret_val = -EBUSY; 438 439 } 440 441 442 restore: 443 /* Re-enable Deeper C-states beyond C6 */ 444 cpu_latency_qos_update_request(sst_drv_ctx->qos, PM_QOS_DEFAULT_VALUE); 445 sst_free_block(sst_drv_ctx, block); 446 dev_dbg(sst_drv_ctx->dev, "fw load successful!!!\n"); 447 448 if (sst_drv_ctx->ops->restore_dsp_context) 449 sst_drv_ctx->ops->restore_dsp_context(); 450 sst_drv_ctx->sst_state = SST_FW_RUNNING; 451 return ret_val; 452 } 453 454