| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * cnl-sst.c - DSP library functions for CNL platform |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 11 | 12 | * |
|---|
| 12 | 13 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 13 | 14 | * |
|---|
| 14 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 15 | | - * it under the terms of the GNU General Public License as version 2, as |
|---|
| 16 | | - * published by the Free Software Foundation. |
|---|
| 17 | | - * |
|---|
| 18 | | - * This program is distributed in the hope that it will be useful, but |
|---|
| 19 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 20 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|---|
| 21 | | - * General Public License for more details. |
|---|
| 22 | | - * |
|---|
| 23 | 15 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 24 | 16 | */ |
|---|
| 25 | 17 | |
|---|
| .. | .. |
|---|
| 32 | 24 | #include "../common/sst-dsp-priv.h" |
|---|
| 33 | 25 | #include "../common/sst-ipc.h" |
|---|
| 34 | 26 | #include "cnl-sst-dsp.h" |
|---|
| 35 | | -#include "skl-sst-dsp.h" |
|---|
| 36 | | -#include "skl-sst-ipc.h" |
|---|
| 27 | +#include "skl.h" |
|---|
| 37 | 28 | |
|---|
| 38 | 29 | #define CNL_FW_ROM_INIT 0x1 |
|---|
| 39 | 30 | #define CNL_FW_INIT 0x5 |
|---|
| .. | .. |
|---|
| 66 | 57 | ctx->dsp_ops.stream_tag = stream_tag; |
|---|
| 67 | 58 | memcpy(ctx->dmab.area, fwdata, fwsize); |
|---|
| 68 | 59 | |
|---|
| 60 | + ret = skl_dsp_core_power_up(ctx, SKL_DSP_CORE0_MASK); |
|---|
| 61 | + if (ret < 0) { |
|---|
| 62 | + dev_err(ctx->dev, "dsp core0 power up failed\n"); |
|---|
| 63 | + ret = -EIO; |
|---|
| 64 | + goto base_fw_load_failed; |
|---|
| 65 | + } |
|---|
| 66 | + |
|---|
| 69 | 67 | /* purge FW request */ |
|---|
| 70 | 68 | sst_dsp_shim_write(ctx, CNL_ADSP_REG_HIPCIDR, |
|---|
| 71 | 69 | CNL_ADSP_REG_HIPCIDR_BUSY | (CNL_IPC_PURGE | |
|---|
| 72 | 70 | ((stream_tag - 1) << CNL_ROM_CTRL_DMA_ID))); |
|---|
| 73 | 71 | |
|---|
| 74 | | - ret = cnl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK); |
|---|
| 72 | + ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK); |
|---|
| 75 | 73 | if (ret < 0) { |
|---|
| 76 | | - dev_err(ctx->dev, "dsp boot core failed ret: %d\n", ret); |
|---|
| 74 | + dev_err(ctx->dev, "Start dsp core failed ret: %d\n", ret); |
|---|
| 77 | 75 | ret = -EIO; |
|---|
| 76 | + goto base_fw_load_failed; |
|---|
| 77 | + } |
|---|
| 78 | + |
|---|
| 79 | + ret = sst_dsp_register_poll(ctx, CNL_ADSP_REG_HIPCIDA, |
|---|
| 80 | + CNL_ADSP_REG_HIPCIDA_DONE, |
|---|
| 81 | + CNL_ADSP_REG_HIPCIDA_DONE, |
|---|
| 82 | + BXT_INIT_TIMEOUT, "HIPCIDA Done"); |
|---|
| 83 | + if (ret < 0) { |
|---|
| 84 | + dev_err(ctx->dev, "timeout for purge request: %d\n", ret); |
|---|
| 78 | 85 | goto base_fw_load_failed; |
|---|
| 79 | 86 | } |
|---|
| 80 | 87 | |
|---|
| .. | .. |
|---|
| 117 | 124 | static int cnl_load_base_firmware(struct sst_dsp *ctx) |
|---|
| 118 | 125 | { |
|---|
| 119 | 126 | struct firmware stripped_fw; |
|---|
| 120 | | - struct skl_sst *cnl = ctx->thread_context; |
|---|
| 121 | | - int ret; |
|---|
| 127 | + struct skl_dev *cnl = ctx->thread_context; |
|---|
| 128 | + int ret, i; |
|---|
| 122 | 129 | |
|---|
| 123 | 130 | if (!ctx->fw) { |
|---|
| 124 | 131 | ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev); |
|---|
| .. | .. |
|---|
| 140 | 147 | stripped_fw.size = ctx->fw->size; |
|---|
| 141 | 148 | skl_dsp_strip_extended_manifest(&stripped_fw); |
|---|
| 142 | 149 | |
|---|
| 143 | | - ret = cnl_prepare_fw(ctx, stripped_fw.data, stripped_fw.size); |
|---|
| 144 | | - if (ret < 0) { |
|---|
| 145 | | - dev_err(ctx->dev, "prepare firmware failed: %d\n", ret); |
|---|
| 146 | | - goto cnl_load_base_firmware_failed; |
|---|
| 150 | + for (i = 0; i < BXT_FW_ROM_INIT_RETRY; i++) { |
|---|
| 151 | + ret = cnl_prepare_fw(ctx, stripped_fw.data, stripped_fw.size); |
|---|
| 152 | + if (!ret) |
|---|
| 153 | + break; |
|---|
| 154 | + dev_dbg(ctx->dev, "prepare firmware failed: %d\n", ret); |
|---|
| 147 | 155 | } |
|---|
| 156 | + |
|---|
| 157 | + if (ret < 0) |
|---|
| 158 | + goto cnl_load_base_firmware_failed; |
|---|
| 148 | 159 | |
|---|
| 149 | 160 | ret = sst_transfer_fw_host_dma(ctx); |
|---|
| 150 | 161 | if (ret < 0) { |
|---|
| .. | .. |
|---|
| 167 | 178 | return 0; |
|---|
| 168 | 179 | |
|---|
| 169 | 180 | cnl_load_base_firmware_failed: |
|---|
| 181 | + dev_err(ctx->dev, "firmware load failed: %d\n", ret); |
|---|
| 170 | 182 | release_firmware(ctx->fw); |
|---|
| 171 | 183 | ctx->fw = NULL; |
|---|
| 172 | 184 | |
|---|
| .. | .. |
|---|
| 175 | 187 | |
|---|
| 176 | 188 | static int cnl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) |
|---|
| 177 | 189 | { |
|---|
| 178 | | - struct skl_sst *cnl = ctx->thread_context; |
|---|
| 190 | + struct skl_dev *cnl = ctx->thread_context; |
|---|
| 179 | 191 | unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); |
|---|
| 180 | 192 | struct skl_ipc_dxstate_info dx; |
|---|
| 181 | 193 | int ret; |
|---|
| .. | .. |
|---|
| 238 | 250 | |
|---|
| 239 | 251 | static int cnl_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) |
|---|
| 240 | 252 | { |
|---|
| 241 | | - struct skl_sst *cnl = ctx->thread_context; |
|---|
| 253 | + struct skl_dev *cnl = ctx->thread_context; |
|---|
| 242 | 254 | unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); |
|---|
| 243 | 255 | struct skl_ipc_dxstate_info dx; |
|---|
| 244 | 256 | int ret; |
|---|
| .. | .. |
|---|
| 289 | 301 | .irq_handler = cnl_dsp_sst_interrupt, |
|---|
| 290 | 302 | .write = sst_shim32_write, |
|---|
| 291 | 303 | .read = sst_shim32_read, |
|---|
| 292 | | - .ram_read = sst_memcpy_fromio_32, |
|---|
| 293 | | - .ram_write = sst_memcpy_toio_32, |
|---|
| 294 | 304 | .free = cnl_dsp_free, |
|---|
| 295 | 305 | }; |
|---|
| 296 | 306 | |
|---|
| .. | .. |
|---|
| 302 | 312 | static irqreturn_t cnl_dsp_irq_thread_handler(int irq, void *context) |
|---|
| 303 | 313 | { |
|---|
| 304 | 314 | struct sst_dsp *dsp = context; |
|---|
| 305 | | - struct skl_sst *cnl = sst_dsp_get_thread_context(dsp); |
|---|
| 315 | + struct skl_dev *cnl = dsp->thread_context; |
|---|
| 306 | 316 | struct sst_generic_ipc *ipc = &cnl->ipc; |
|---|
| 307 | 317 | struct skl_ipc_header header = {0}; |
|---|
| 308 | 318 | u32 hipcida, hipctdr, hipctdd; |
|---|
| .. | .. |
|---|
| 314 | 324 | |
|---|
| 315 | 325 | hipcida = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCIDA); |
|---|
| 316 | 326 | hipctdr = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCTDR); |
|---|
| 327 | + hipctdd = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCTDD); |
|---|
| 317 | 328 | |
|---|
| 318 | 329 | /* reply message from dsp */ |
|---|
| 319 | 330 | if (hipcida & CNL_ADSP_REG_HIPCIDA_DONE) { |
|---|
| .. | .. |
|---|
| 333 | 344 | |
|---|
| 334 | 345 | /* new message from dsp */ |
|---|
| 335 | 346 | if (hipctdr & CNL_ADSP_REG_HIPCTDR_BUSY) { |
|---|
| 336 | | - hipctdd = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCTDD); |
|---|
| 337 | 347 | header.primary = hipctdr; |
|---|
| 338 | 348 | header.extension = hipctdd; |
|---|
| 339 | 349 | dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x", |
|---|
| .. | .. |
|---|
| 376 | 386 | |
|---|
| 377 | 387 | static void cnl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) |
|---|
| 378 | 388 | { |
|---|
| 379 | | - struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->header); |
|---|
| 389 | + struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->tx.header); |
|---|
| 380 | 390 | |
|---|
| 381 | | - if (msg->tx_size) |
|---|
| 382 | | - sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size); |
|---|
| 391 | + if (msg->tx.size) |
|---|
| 392 | + sst_dsp_outbox_write(ipc->dsp, msg->tx.data, msg->tx.size); |
|---|
| 383 | 393 | sst_dsp_shim_write_unlocked(ipc->dsp, CNL_ADSP_REG_HIPCIDD, |
|---|
| 384 | 394 | header->extension); |
|---|
| 385 | 395 | sst_dsp_shim_write_unlocked(ipc->dsp, CNL_ADSP_REG_HIPCIDR, |
|---|
| .. | .. |
|---|
| 395 | 405 | return (hipcidr & CNL_ADSP_REG_HIPCIDR_BUSY); |
|---|
| 396 | 406 | } |
|---|
| 397 | 407 | |
|---|
| 398 | | -static int cnl_ipc_init(struct device *dev, struct skl_sst *cnl) |
|---|
| 408 | +static int cnl_ipc_init(struct device *dev, struct skl_dev *cnl) |
|---|
| 399 | 409 | { |
|---|
| 400 | 410 | struct sst_generic_ipc *ipc; |
|---|
| 401 | 411 | int err; |
|---|
| .. | .. |
|---|
| 424 | 434 | |
|---|
| 425 | 435 | int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, |
|---|
| 426 | 436 | const char *fw_name, struct skl_dsp_loader_ops dsp_ops, |
|---|
| 427 | | - struct skl_sst **dsp) |
|---|
| 437 | + struct skl_dev **dsp) |
|---|
| 428 | 438 | { |
|---|
| 429 | | - struct skl_sst *cnl; |
|---|
| 439 | + struct skl_dev *cnl; |
|---|
| 430 | 440 | struct sst_dsp *sst; |
|---|
| 431 | 441 | int ret; |
|---|
| 432 | 442 | |
|---|
| .. | .. |
|---|
| 463 | 473 | } |
|---|
| 464 | 474 | EXPORT_SYMBOL_GPL(cnl_sst_dsp_init); |
|---|
| 465 | 475 | |
|---|
| 466 | | -int cnl_sst_init_fw(struct device *dev, struct skl_sst *ctx) |
|---|
| 476 | +int cnl_sst_init_fw(struct device *dev, struct skl_dev *skl) |
|---|
| 467 | 477 | { |
|---|
| 468 | 478 | int ret; |
|---|
| 469 | | - struct sst_dsp *sst = ctx->dsp; |
|---|
| 479 | + struct sst_dsp *sst = skl->dsp; |
|---|
| 470 | 480 | |
|---|
| 471 | | - ret = ctx->dsp->fw_ops.load_fw(sst); |
|---|
| 481 | + ret = skl->dsp->fw_ops.load_fw(sst); |
|---|
| 472 | 482 | if (ret < 0) { |
|---|
| 473 | 483 | dev_err(dev, "load base fw failed: %d", ret); |
|---|
| 474 | 484 | return ret; |
|---|
| .. | .. |
|---|
| 476 | 486 | |
|---|
| 477 | 487 | skl_dsp_init_core_state(sst); |
|---|
| 478 | 488 | |
|---|
| 479 | | - ctx->is_first_boot = false; |
|---|
| 489 | + skl->is_first_boot = false; |
|---|
| 480 | 490 | |
|---|
| 481 | 491 | return 0; |
|---|
| 482 | 492 | } |
|---|
| 483 | 493 | EXPORT_SYMBOL_GPL(cnl_sst_init_fw); |
|---|
| 484 | 494 | |
|---|
| 485 | | -void cnl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) |
|---|
| 495 | +void cnl_sst_dsp_cleanup(struct device *dev, struct skl_dev *skl) |
|---|
| 486 | 496 | { |
|---|
| 487 | | - if (ctx->dsp->fw) |
|---|
| 488 | | - release_firmware(ctx->dsp->fw); |
|---|
| 497 | + if (skl->dsp->fw) |
|---|
| 498 | + release_firmware(skl->dsp->fw); |
|---|
| 489 | 499 | |
|---|
| 490 | | - skl_freeup_uuid_list(ctx); |
|---|
| 491 | | - cnl_ipc_free(&ctx->ipc); |
|---|
| 500 | + skl_freeup_uuid_list(skl); |
|---|
| 501 | + cnl_ipc_free(&skl->ipc); |
|---|
| 492 | 502 | |
|---|
| 493 | | - ctx->dsp->ops->free(ctx->dsp); |
|---|
| 503 | + skl->dsp->ops->free(skl->dsp); |
|---|
| 494 | 504 | } |
|---|
| 495 | 505 | EXPORT_SYMBOL_GPL(cnl_sst_dsp_cleanup); |
|---|
| 496 | 506 | |
|---|