| .. | .. | 
|---|
|  | 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 |  | 
|---|