0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <linux/pci.h>
0018 #include <linux/delay.h>
0019 #include <linux/fs.h>
0020 #include <linux/sched.h>
0021 #include <linux/firmware.h>
0022 #include <linux/dmaengine.h>
0023 #include <linux/pm_runtime.h>
0024 #include <linux/pm_qos.h>
0025 #include <sound/core.h>
0026 #include <sound/pcm.h>
0027 #include <sound/soc.h>
0028 #include <sound/compress_driver.h>
0029 #include <asm/platform_sst_audio.h>
0030 #include "../sst-mfld-platform.h"
0031 #include "sst.h"
0032
0033 void memcpy32_toio(void __iomem *dst, const void *src, int count)
0034 {
0035
0036
0037
0038 __iowrite32_copy(dst, src, count / 4);
0039 }
0040
0041 void memcpy32_fromio(void *dst, const void __iomem *src, int count)
0042 {
0043
0044
0045
0046 __ioread32_copy(dst, src, count / 4);
0047 }
0048
0049
0050
0051
0052
0053
0054
0055 int intel_sst_reset_dsp_mrfld(struct intel_sst_drv *sst_drv_ctx)
0056 {
0057 union config_status_reg_mrfld csr;
0058
0059 dev_dbg(sst_drv_ctx->dev, "sst: Resetting the DSP in mrfld\n");
0060 csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR);
0061
0062 dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full);
0063
0064 csr.full |= 0x7;
0065 sst_shim_write64(sst_drv_ctx->shim, SST_CSR, csr.full);
0066 csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR);
0067
0068 dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full);
0069
0070 csr.full &= ~(0x1);
0071 sst_shim_write64(sst_drv_ctx->shim, SST_CSR, csr.full);
0072
0073 csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR);
0074 dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full);
0075 return 0;
0076 }
0077
0078
0079
0080
0081
0082
0083
0084 int sst_start_mrfld(struct intel_sst_drv *sst_drv_ctx)
0085 {
0086 union config_status_reg_mrfld csr;
0087
0088 dev_dbg(sst_drv_ctx->dev, "sst: Starting the DSP in mrfld LALALALA\n");
0089 csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR);
0090 dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full);
0091
0092 csr.full |= 0x7;
0093 sst_shim_write64(sst_drv_ctx->shim, SST_CSR, csr.full);
0094
0095 csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR);
0096 dev_dbg(sst_drv_ctx->dev, "value:0x%llx\n", csr.full);
0097
0098 csr.part.xt_snoop = 1;
0099 csr.full &= ~(0x5);
0100 sst_shim_write64(sst_drv_ctx->shim, SST_CSR, csr.full);
0101
0102 csr.full = sst_shim_read64(sst_drv_ctx->shim, SST_CSR);
0103 dev_dbg(sst_drv_ctx->dev, "sst: Starting the DSP_merrifield:%llx\n",
0104 csr.full);
0105 return 0;
0106 }
0107
0108 static int sst_validate_fw_image(struct intel_sst_drv *ctx, unsigned long size,
0109 struct fw_module_header **module, u32 *num_modules)
0110 {
0111 struct sst_fw_header *header;
0112 const void *sst_fw_in_mem = ctx->fw_in_mem;
0113
0114 dev_dbg(ctx->dev, "Enter\n");
0115
0116
0117 header = (struct sst_fw_header *)sst_fw_in_mem;
0118 dev_dbg(ctx->dev,
0119 "header sign=%s size=%x modules=%x fmt=%x size=%zx\n",
0120 header->signature, header->file_size, header->modules,
0121 header->file_format, sizeof(*header));
0122
0123
0124 if ((strncmp(header->signature, SST_FW_SIGN, 4) != 0) ||
0125 (size != header->file_size + sizeof(*header))) {
0126
0127 dev_err(ctx->dev, "InvalidFW sign/filesize mismatch\n");
0128 return -EINVAL;
0129 }
0130 *num_modules = header->modules;
0131 *module = (void *)sst_fw_in_mem + sizeof(*header);
0132
0133 return 0;
0134 }
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147 static int sst_fill_memcpy_list(struct list_head *memcpy_list,
0148 void *destn, const void *src, u32 size, bool is_io)
0149 {
0150 struct sst_memcpy_list *listnode;
0151
0152 listnode = kzalloc(sizeof(*listnode), GFP_KERNEL);
0153 if (listnode == NULL)
0154 return -ENOMEM;
0155 listnode->dstn = destn;
0156 listnode->src = src;
0157 listnode->size = size;
0158 listnode->is_io = is_io;
0159 list_add_tail(&listnode->memcpylist, memcpy_list);
0160
0161 return 0;
0162 }
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173 static int sst_parse_module_memcpy(struct intel_sst_drv *sst_drv_ctx,
0174 struct fw_module_header *module, struct list_head *memcpy_list)
0175 {
0176 struct fw_block_info *block;
0177 u32 count;
0178 int ret_val = 0;
0179 void __iomem *ram_iomem;
0180
0181 dev_dbg(sst_drv_ctx->dev, "module sign %s size %x blocks %x type %x\n",
0182 module->signature, module->mod_size,
0183 module->blocks, module->type);
0184 dev_dbg(sst_drv_ctx->dev, "module entrypoint 0x%x\n", module->entry_point);
0185
0186 block = (void *)module + sizeof(*module);
0187
0188 for (count = 0; count < module->blocks; count++) {
0189 if (block->size <= 0) {
0190 dev_err(sst_drv_ctx->dev, "block size invalid\n");
0191 return -EINVAL;
0192 }
0193 switch (block->type) {
0194 case SST_IRAM:
0195 ram_iomem = sst_drv_ctx->iram;
0196 break;
0197 case SST_DRAM:
0198 ram_iomem = sst_drv_ctx->dram;
0199 break;
0200 case SST_DDR:
0201 ram_iomem = sst_drv_ctx->ddr;
0202 break;
0203 case SST_CUSTOM_INFO:
0204 block = (void *)block + sizeof(*block) + block->size;
0205 continue;
0206 default:
0207 dev_err(sst_drv_ctx->dev, "wrong ram type0x%x in block0x%x\n",
0208 block->type, count);
0209 return -EINVAL;
0210 }
0211
0212 ret_val = sst_fill_memcpy_list(memcpy_list,
0213 ram_iomem + block->ram_offset,
0214 (void *)block + sizeof(*block), block->size, 1);
0215 if (ret_val)
0216 return ret_val;
0217
0218 block = (void *)block + sizeof(*block) + block->size;
0219 }
0220 return 0;
0221 }
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232 static int sst_parse_fw_memcpy(struct intel_sst_drv *ctx, unsigned long size,
0233 struct list_head *fw_list)
0234 {
0235 struct fw_module_header *module;
0236 u32 count, num_modules;
0237 int ret_val;
0238
0239 ret_val = sst_validate_fw_image(ctx, size, &module, &num_modules);
0240 if (ret_val)
0241 return ret_val;
0242
0243 for (count = 0; count < num_modules; count++) {
0244 ret_val = sst_parse_module_memcpy(ctx, module, fw_list);
0245 if (ret_val)
0246 return ret_val;
0247 module = (void *)module + sizeof(*module) + module->mod_size;
0248 }
0249
0250 return 0;
0251 }
0252
0253
0254
0255
0256
0257
0258
0259
0260 static void sst_do_memcpy(struct list_head *memcpy_list)
0261 {
0262 struct sst_memcpy_list *listnode;
0263
0264 list_for_each_entry(listnode, memcpy_list, memcpylist) {
0265 if (listnode->is_io)
0266 memcpy32_toio((void __iomem *)listnode->dstn,
0267 listnode->src, listnode->size);
0268 else
0269 memcpy(listnode->dstn, listnode->src, listnode->size);
0270 }
0271 }
0272
0273 void sst_memcpy_free_resources(struct intel_sst_drv *sst_drv_ctx)
0274 {
0275 struct sst_memcpy_list *listnode, *tmplistnode;
0276
0277
0278 list_for_each_entry_safe(listnode, tmplistnode,
0279 &sst_drv_ctx->memcpy_list, memcpylist) {
0280 list_del(&listnode->memcpylist);
0281 kfree(listnode);
0282 }
0283 }
0284
0285 static int sst_cache_and_parse_fw(struct intel_sst_drv *sst,
0286 const struct firmware *fw)
0287 {
0288 int retval = 0;
0289
0290 sst->fw_in_mem = kzalloc(fw->size, GFP_KERNEL);
0291 if (!sst->fw_in_mem) {
0292 retval = -ENOMEM;
0293 goto end_release;
0294 }
0295 dev_dbg(sst->dev, "copied fw to %p", sst->fw_in_mem);
0296 dev_dbg(sst->dev, "phys: %lx", (unsigned long)virt_to_phys(sst->fw_in_mem));
0297 memcpy(sst->fw_in_mem, fw->data, fw->size);
0298 retval = sst_parse_fw_memcpy(sst, fw->size, &sst->memcpy_list);
0299 if (retval) {
0300 dev_err(sst->dev, "Failed to parse fw\n");
0301 kfree(sst->fw_in_mem);
0302 sst->fw_in_mem = NULL;
0303 }
0304
0305 end_release:
0306 release_firmware(fw);
0307 return retval;
0308
0309 }
0310
0311 void sst_firmware_load_cb(const struct firmware *fw, void *context)
0312 {
0313 struct intel_sst_drv *ctx = context;
0314
0315 dev_dbg(ctx->dev, "Enter\n");
0316
0317 if (fw == NULL) {
0318 dev_err(ctx->dev, "request fw failed\n");
0319 return;
0320 }
0321
0322 mutex_lock(&ctx->sst_lock);
0323
0324 if (ctx->sst_state != SST_RESET ||
0325 ctx->fw_in_mem != NULL) {
0326 release_firmware(fw);
0327 mutex_unlock(&ctx->sst_lock);
0328 return;
0329 }
0330
0331 dev_dbg(ctx->dev, "Request Fw completed\n");
0332 sst_cache_and_parse_fw(ctx, fw);
0333 mutex_unlock(&ctx->sst_lock);
0334 }
0335
0336
0337
0338
0339
0340
0341
0342 static int sst_request_fw(struct intel_sst_drv *sst)
0343 {
0344 int retval = 0;
0345 const struct firmware *fw;
0346
0347 retval = request_firmware(&fw, sst->firmware_name, sst->dev);
0348 if (retval) {
0349 dev_err(sst->dev, "request fw failed %d\n", retval);
0350 return retval;
0351 }
0352 if (fw == NULL) {
0353 dev_err(sst->dev, "fw is returning as null\n");
0354 return -EINVAL;
0355 }
0356 mutex_lock(&sst->sst_lock);
0357 retval = sst_cache_and_parse_fw(sst, fw);
0358 mutex_unlock(&sst->sst_lock);
0359
0360 return retval;
0361 }
0362
0363
0364
0365
0366
0367 static void sst_dccm_config_write(void __iomem *dram_base,
0368 unsigned int ddr_base)
0369 {
0370 void __iomem *addr;
0371 u32 bss_reset = 0;
0372
0373 addr = (void __iomem *)(dram_base + MRFLD_FW_DDR_BASE_OFFSET);
0374 memcpy32_toio(addr, (void *)&ddr_base, sizeof(u32));
0375 bss_reset |= (1 << MRFLD_FW_BSS_RESET_BIT);
0376 addr = (void __iomem *)(dram_base + MRFLD_FW_FEATURE_BASE_OFFSET);
0377 memcpy32_toio(addr, &bss_reset, sizeof(u32));
0378
0379 }
0380
0381 void sst_post_download_mrfld(struct intel_sst_drv *ctx)
0382 {
0383 sst_dccm_config_write(ctx->dram, ctx->ddr_base);
0384 dev_dbg(ctx->dev, "config written to DCCM\n");
0385 }
0386
0387
0388
0389
0390
0391
0392
0393 int sst_load_fw(struct intel_sst_drv *sst_drv_ctx)
0394 {
0395 int ret_val = 0;
0396 struct sst_block *block;
0397
0398 dev_dbg(sst_drv_ctx->dev, "sst_load_fw\n");
0399
0400 if (sst_drv_ctx->sst_state != SST_RESET)
0401 return -EAGAIN;
0402
0403 if (!sst_drv_ctx->fw_in_mem) {
0404 dev_dbg(sst_drv_ctx->dev, "sst: FW not in memory retry to download\n");
0405 ret_val = sst_request_fw(sst_drv_ctx);
0406 if (ret_val)
0407 return ret_val;
0408 }
0409
0410 block = sst_create_block(sst_drv_ctx, 0, FW_DWNL_ID);
0411 if (block == NULL)
0412 return -ENOMEM;
0413
0414
0415 cpu_latency_qos_update_request(sst_drv_ctx->qos, 0);
0416
0417 sst_drv_ctx->sst_state = SST_FW_LOADING;
0418
0419 ret_val = sst_drv_ctx->ops->reset(sst_drv_ctx);
0420 if (ret_val)
0421 goto restore;
0422
0423 sst_do_memcpy(&sst_drv_ctx->memcpy_list);
0424
0425
0426 if (sst_drv_ctx->ops->post_download)
0427 sst_drv_ctx->ops->post_download(sst_drv_ctx);
0428
0429
0430 ret_val = sst_drv_ctx->ops->start(sst_drv_ctx);
0431 if (ret_val)
0432 goto restore;
0433
0434 ret_val = sst_wait_timeout(sst_drv_ctx, block);
0435 if (ret_val) {
0436 dev_err(sst_drv_ctx->dev, "fw download failed %d\n" , ret_val);
0437
0438 ret_val = -EBUSY;
0439
0440 }
0441
0442
0443 restore:
0444
0445 cpu_latency_qos_update_request(sst_drv_ctx->qos, PM_QOS_DEFAULT_VALUE);
0446 sst_free_block(sst_drv_ctx, block);
0447 dev_dbg(sst_drv_ctx->dev, "fw load successful!!!\n");
0448
0449 if (sst_drv_ctx->ops->restore_dsp_context)
0450 sst_drv_ctx->ops->restore_dsp_context();
0451 sst_drv_ctx->sst_state = SST_FW_RUNNING;
0452 return ret_val;
0453 }
0454