skl-sst.c 15.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * skl-sst.c - HDA DSP library functions for SKL platform
 *
 * Copyright (C) 2014-15, Intel Corporation.
 * Author:Rafal Redzimski <rafal.f.redzimski@intel.com>
 *	Jeeja KP <jeeja.kp@intel.com>
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as version 2, as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 */

#include <linux/module.h>
#include <linux/delay.h>
#include <linux/device.h>
22
#include <linux/err.h>
23
#include <linux/uuid.h>
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
#include "../common/sst-dsp.h"
#include "../common/sst-dsp-priv.h"
#include "../common/sst-ipc.h"
#include "skl-sst-ipc.h"

#define SKL_BASEFW_TIMEOUT	300
#define SKL_INIT_TIMEOUT	1000

/* Intel HD Audio SRAM Window 0*/
#define SKL_ADSP_SRAM0_BASE	0x8000

/* Firmware status window */
#define SKL_ADSP_FW_STATUS	SKL_ADSP_SRAM0_BASE
#define SKL_ADSP_ERROR_CODE	(SKL_ADSP_FW_STATUS + 0x4)

39 40
#define SKL_NUM_MODULES		1

41 42 43 44 45 46 47 48 49 50 51 52 53 54
static bool skl_check_fw_status(struct sst_dsp *ctx, u32 status)
{
	u32 cur_sts;

	cur_sts = sst_dsp_shim_read(ctx, SKL_ADSP_FW_STATUS) & SKL_FW_STS_MASK;

	return (cur_sts == status);
}

static int skl_transfer_firmware(struct sst_dsp *ctx,
		const void *basefw, u32 base_fw_size)
{
	int ret = 0;

55 56
	ret = ctx->cl_dev.ops.cl_copy_to_dmabuf(ctx, basefw, base_fw_size,
								true);
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
	if (ret < 0)
		return ret;

	ret = sst_dsp_register_poll(ctx,
			SKL_ADSP_FW_STATUS,
			SKL_FW_STS_MASK,
			SKL_FW_RFW_START,
			SKL_BASEFW_TIMEOUT,
			"Firmware boot");

	ctx->cl_dev.ops.cl_stop_dma(ctx);

	return ret;
}

72 73
#define SKL_ADSP_FW_BIN_HDR_OFFSET 0x284

74 75 76 77
static int skl_load_base_firmware(struct sst_dsp *ctx)
{
	int ret = 0, i;
	struct skl_sst *skl = ctx->thread_context;
78
	struct firmware stripped_fw;
79 80
	u32 reg;

81 82 83 84
	skl->boot_complete = false;
	init_waitqueue_head(&skl->boot_wait);

	if (ctx->fw == NULL) {
85
		ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev);
86 87 88 89
		if (ret < 0) {
			dev_err(ctx->dev, "Request firmware failed %d\n", ret);
			return -EIO;
		}
90 91
	}

92 93 94 95 96 97 98 99 100
	/* prase uuids on first boot */
	if (skl->is_first_boot) {
		ret = snd_skl_parse_uuids(ctx, ctx->fw, SKL_ADSP_FW_BIN_HDR_OFFSET, 0);
		if (ret < 0) {
			dev_err(ctx->dev, "UUID parsing err: %d\n", ret);
			release_firmware(ctx->fw);
			skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
			return ret;
		}
101 102
	}

103 104 105 106 107 108
	/* check for extended manifest */
	stripped_fw.data = ctx->fw->data;
	stripped_fw.size = ctx->fw->size;

	skl_dsp_strip_extended_manifest(&stripped_fw);

109
	ret = skl_dsp_boot(ctx);
110
	if (ret < 0) {
111
		dev_err(ctx->dev, "Boot dsp core failed ret: %d\n", ret);
112 113 114 115 116
		goto skl_load_base_firmware_failed;
	}

	ret = skl_cldma_prepare(ctx);
	if (ret < 0) {
117
		dev_err(ctx->dev, "CL dma prepare failed : %d\n", ret);
118
		goto skl_load_base_firmware_failed;
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
	}

	/* enable Interrupt */
	skl_ipc_int_enable(ctx);
	skl_ipc_op_int_enable(ctx);

	/* check ROM Status */
	for (i = SKL_INIT_TIMEOUT; i > 0; --i) {
		if (skl_check_fw_status(ctx, SKL_FW_INIT)) {
			dev_dbg(ctx->dev,
				"ROM loaded, we can continue with FW loading\n");
			break;
		}
		mdelay(1);
	}
	if (!i) {
		reg = sst_dsp_shim_read(ctx, SKL_ADSP_FW_STATUS);
		dev_err(ctx->dev,
			"Timeout waiting for ROM init done, reg:0x%x\n", reg);
		ret = -EIO;
139
		goto transfer_firmware_failed;
140 141
	}

142
	ret = skl_transfer_firmware(ctx, stripped_fw.data, stripped_fw.size);
143 144
	if (ret < 0) {
		dev_err(ctx->dev, "Transfer firmware failed%d\n", ret);
145
		goto transfer_firmware_failed;
146 147 148 149 150 151
	} else {
		ret = wait_event_timeout(skl->boot_wait, skl->boot_complete,
					msecs_to_jiffies(SKL_IPC_BOOT_MSECS));
		if (ret == 0) {
			dev_err(ctx->dev, "DSP boot failed, FW Ready timed-out\n");
			ret = -EIO;
152
			goto transfer_firmware_failed;
153 154 155
		}

		dev_dbg(ctx->dev, "Download firmware successful%d\n", ret);
156
		skl->fw_loaded = true;
157 158
	}
	return 0;
159 160
transfer_firmware_failed:
	ctx->cl_dev.ops.cl_cleanup_controller(ctx);
161
skl_load_base_firmware_failed:
162
	skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
163 164
	release_firmware(ctx->fw);
	ctx->fw = NULL;
165 166 167
	return ret;
}

168
static int skl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id)
169 170
{
	int ret;
171 172 173
	struct skl_ipc_dxstate_info dx;
	struct skl_sst *skl = ctx->thread_context;
	unsigned int core_mask = SKL_DSP_CORE_MASK(core_id);
174

175 176 177 178 179 180 181
	/* If core0 is being turned on, we need to load the FW */
	if (core_id == SKL_DSP_CORE0_ID) {
		ret = skl_load_base_firmware(ctx);
		if (ret < 0) {
			dev_err(ctx->dev, "unable to load firmware\n");
			return ret;
		}
182 183 184 185 186 187 188 189 190 191 192 193

		/* load libs as they are also lost on D3 */
		if (skl->lib_count > 1) {
			ret = ctx->fw_ops.load_library(ctx, skl->lib_info,
							skl->lib_count);
			if (ret < 0) {
				dev_err(ctx->dev, "reload libs failed: %d\n",
						ret);
				return ret;
			}

		}
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
	}

	/*
	 * If any core other than core 0 is being moved to D0, enable the
	 * core and send the set dx IPC for the core.
	 */
	if (core_id != SKL_DSP_CORE0_ID) {
		ret = skl_dsp_enable_core(ctx, core_mask);
		if (ret < 0)
			return ret;

		dx.core_mask = core_mask;
		dx.dx_mask = core_mask;

		ret = skl_ipc_set_dx(&skl->ipc, SKL_INSTANCE_ID,
					SKL_BASE_FW_MODULE_ID, &dx);
		if (ret < 0) {
			dev_err(ctx->dev, "Failed to set dsp to D0:core id= %d\n",
					core_id);
			skl_dsp_disable_core(ctx, core_mask);
		}
215 216
	}

217
	skl->cores.state[core_id] = SKL_DSP_RUNNING;
218

219
	return 0;
220 221
}

222
static int skl_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id)
223 224 225 226
{
	int ret;
	struct skl_ipc_dxstate_info dx;
	struct skl_sst *skl = ctx->thread_context;
227
	unsigned int core_mask = SKL_DSP_CORE_MASK(core_id);
228

229
	dx.core_mask = core_mask;
230
	dx.dx_mask = SKL_IPC_D3_MASK;
231

232
	ret = skl_ipc_set_dx(&skl->ipc, SKL_INSTANCE_ID, SKL_BASE_FW_MODULE_ID, &dx);
233
	if (ret < 0)
234 235 236 237 238 239 240 241
		dev_err(ctx->dev, "set Dx core %d fail: %d\n", core_id, ret);

	if (core_id == SKL_DSP_CORE0_ID) {
		/* disable Interrupt */
		ctx->cl_dev.ops.cl_cleanup_controller(ctx);
		skl_cldma_int_disable(ctx);
		skl_ipc_op_int_disable(ctx);
		skl_ipc_int_disable(ctx);
242 243
	}

244 245 246 247 248
	ret = skl_dsp_disable_core(ctx, core_mask);
	if (ret < 0)
		return ret;

	skl->cores.state[core_id] = SKL_DSP_RESET;
249 250 251 252 253 254 255 256
	return ret;
}

static unsigned int skl_get_errorcode(struct sst_dsp *ctx)
{
	 return sst_dsp_shim_read(ctx, SKL_ADSP_ERROR_CODE);
}

257 258 259 260
/*
 * since get/set_module are called from DAPM context,
 * we don't need lock for usage count
 */
261
static int skl_get_module(struct sst_dsp *ctx, u16 mod_id)
262 263 264 265 266 267 268 269 270 271 272
{
	struct skl_module_table *module;

	list_for_each_entry(module, &ctx->module_list, list) {
		if (module->mod_info->mod_id == mod_id)
			return ++module->usage_cnt;
	}

	return -EINVAL;
}

273
static int skl_put_module(struct sst_dsp *ctx, u16 mod_id)
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
{
	struct skl_module_table *module;

	list_for_each_entry(module, &ctx->module_list, list) {
		if (module->mod_info->mod_id == mod_id)
			return --module->usage_cnt;
	}

	return -EINVAL;
}

static struct skl_module_table *skl_fill_module_table(struct sst_dsp *ctx,
						char *mod_name, int mod_id)
{
	const struct firmware *fw;
	struct skl_module_table *skl_module;
	unsigned int size;
	int ret;

	ret = request_firmware(&fw, mod_name, ctx->dev);
	if (ret < 0) {
		dev_err(ctx->dev, "Request Module %s failed :%d\n",
							mod_name, ret);
		return NULL;
	}

	skl_module = devm_kzalloc(ctx->dev, sizeof(*skl_module), GFP_KERNEL);
	if (skl_module == NULL) {
		release_firmware(fw);
		return NULL;
	}

	size = sizeof(*skl_module->mod_info);
	skl_module->mod_info = devm_kzalloc(ctx->dev, size, GFP_KERNEL);
	if (skl_module->mod_info == NULL) {
		release_firmware(fw);
		return NULL;
	}

	skl_module->mod_info->mod_id = mod_id;
	skl_module->mod_info->fw = fw;
	list_add(&skl_module->list, &ctx->module_list);

	return skl_module;
}

/* get a module from it's unique ID */
static struct skl_module_table *skl_module_get_from_id(
			struct sst_dsp *ctx, u16 mod_id)
{
	struct skl_module_table *module;

	if (list_empty(&ctx->module_list)) {
		dev_err(ctx->dev, "Module list is empty\n");
		return NULL;
	}

	list_for_each_entry(module, &ctx->module_list, list) {
		if (module->mod_info->mod_id == mod_id)
			return module;
	}

	return NULL;
}

339
static int skl_transfer_module(struct sst_dsp *ctx, const void *data,
340
			u32 size, u16 mod_id, u8 table_id, bool is_module)
341
{
342
	int ret, bytes_left, curr_pos;
343
	struct skl_sst *skl = ctx->thread_context;
344
	skl->mod_load_complete = false;
345

346 347 348
	bytes_left = ctx->cl_dev.ops.cl_copy_to_dmabuf(ctx, data, size, false);
	if (bytes_left < 0)
		return bytes_left;
349

350 351
	/* check is_module flag to load module or library */
	if (is_module)
352
		ret = skl_ipc_load_modules(&skl->ipc, SKL_NUM_MODULES, &mod_id);
353 354 355 356 357 358 359
	else
		ret = skl_sst_ipc_load_library(&skl->ipc, 0, table_id, false);

	if (ret < 0) {
		dev_err(ctx->dev, "Failed to Load %s with err %d\n",
				is_module ? "module" : "lib", ret);
		goto out;
360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
	}

	/*
	 * if bytes_left > 0 then wait for BDL complete interrupt and
	 * copy the next chunk till bytes_left is 0. if bytes_left is
	 * is zero, then wait for load module IPC reply
	 */
	while (bytes_left > 0) {
		curr_pos = size - bytes_left;

		ret = skl_cldma_wait_interruptible(ctx);
		if (ret < 0)
			goto out;

		bytes_left = ctx->cl_dev.ops.cl_copy_to_dmabuf(ctx,
							data + curr_pos,
							bytes_left, false);
	}

	ret = wait_event_timeout(skl->mod_load_wait, skl->mod_load_complete,
				msecs_to_jiffies(SKL_IPC_BOOT_MSECS));
	if (ret == 0 || !skl->mod_load_status) {
		dev_err(ctx->dev, "Module Load failed\n");
		ret = -EIO;
	}
385

386
out:
387 388 389 390 391
	ctx->cl_dev.ops.cl_stop_dma(ctx);

	return ret;
}

392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
static int
kbl_load_library(struct sst_dsp *ctx, struct skl_lib_info *linfo, int lib_count)
{
	struct skl_sst *skl = ctx->thread_context;
	struct firmware stripped_fw;
	int ret, i;

	/* library indices start from 1 to N. 0 represents base FW */
	for (i = 1; i < lib_count; i++) {
		ret = skl_prepare_lib_load(skl, &skl->lib_info[i], &stripped_fw,
					SKL_ADSP_FW_BIN_HDR_OFFSET, i);
		if (ret < 0)
			goto load_library_failed;
		ret = skl_transfer_module(ctx, stripped_fw.data,
				stripped_fw.size, 0, i, false);
		if (ret < 0)
			goto load_library_failed;
	}

	return 0;

load_library_failed:
	skl_release_library(linfo, lib_count);
	return ret;
}

418
static int skl_load_module(struct sst_dsp *ctx, u16 mod_id, u8 *guid)
419 420 421 422
{
	struct skl_module_table *module_entry = NULL;
	int ret = 0;
	char mod_name[64]; /* guid str = 32 chars + 4 hyphens */
423
	uuid_le *uuid_mod;
424

425 426 427
	uuid_mod = (uuid_le *)guid;
	snprintf(mod_name, sizeof(mod_name), "%s%pUL%s",
				"intel/dsp_fw_", uuid_mod, ".bin");
428 429 430 431 432 433 434 435 436 437 438

	module_entry = skl_module_get_from_id(ctx, mod_id);
	if (module_entry == NULL) {
		module_entry = skl_fill_module_table(ctx, mod_name, mod_id);
		if (module_entry == NULL) {
			dev_err(ctx->dev, "Failed to Load module\n");
			return -EINVAL;
		}
	}

	if (!module_entry->usage_cnt) {
439
		ret = skl_transfer_module(ctx, module_entry->mod_info->fw->data,
440 441
				module_entry->mod_info->fw->size,
				mod_id, 0, true);
442 443 444 445 446 447 448 449 450 451 452 453 454
		if (ret < 0) {
			dev_err(ctx->dev, "Failed to Load module\n");
			return ret;
		}
	}

	ret = skl_get_module(ctx, mod_id);

	return ret;
}

static int skl_unload_module(struct sst_dsp *ctx, u16 mod_id)
{
455
	int usage_cnt;
456 457 458 459 460 461 462 463
	struct skl_sst *skl = ctx->thread_context;
	int ret = 0;

	usage_cnt = skl_put_module(ctx, mod_id);
	if (usage_cnt < 0) {
		dev_err(ctx->dev, "Module bad usage cnt!:%d\n", usage_cnt);
		return -EIO;
	}
464 465 466 467 468

	/* if module is used by others return, no need to unload */
	if (usage_cnt > 0)
		return 0;

469 470 471 472 473 474 475 476 477 478 479
	ret = skl_ipc_unload_modules(&skl->ipc,
			SKL_NUM_MODULES, &mod_id);
	if (ret < 0) {
		dev_err(ctx->dev, "Failed to UnLoad module\n");
		skl_get_module(ctx, mod_id);
		return ret;
	}

	return ret;
}

480 481 482 483
void skl_clear_module_cnt(struct sst_dsp *ctx)
{
	struct skl_module_table *module;

484 485 486
	if (list_empty(&ctx->module_list))
		return;

487 488 489 490 491 492
	list_for_each_entry(module, &ctx->module_list, list) {
		module->usage_cnt = 0;
	}
}
EXPORT_SYMBOL_GPL(skl_clear_module_cnt);

493 494 495 496 497 498 499 500 501 502 503 504 505
static void skl_clear_module_table(struct sst_dsp *ctx)
{
	struct skl_module_table *module, *tmp;

	if (list_empty(&ctx->module_list))
		return;

	list_for_each_entry_safe(module, tmp, &ctx->module_list, list) {
		list_del(&module->list);
		release_firmware(module->mod_info->fw);
	}
}

506
static const struct skl_dsp_fw_ops skl_fw_ops = {
507 508 509 510
	.set_state_D0 = skl_set_dsp_D0,
	.set_state_D3 = skl_set_dsp_D3,
	.load_fw = skl_load_base_firmware,
	.get_fw_errcode = skl_get_errorcode,
511 512
	.load_mod = skl_load_module,
	.unload_mod = skl_unload_module,
513 514
};

515
static const struct skl_dsp_fw_ops kbl_fw_ops = {
516 517 518 519
	.set_state_D0 = skl_set_dsp_D0,
	.set_state_D3 = skl_set_dsp_D3,
	.load_fw = skl_load_base_firmware,
	.get_fw_errcode = skl_get_errorcode,
520
	.load_library = kbl_load_library,
521 522 523 524
	.load_mod = skl_load_module,
	.unload_mod = skl_unload_module,
};

525 526 527 528 529 530 531 532 533 534 535 536 537 538 539
static struct sst_ops skl_ops = {
	.irq_handler = skl_dsp_sst_interrupt,
	.write = sst_shim32_write,
	.read = sst_shim32_read,
	.ram_read = sst_memcpy_fromio_32,
	.ram_write = sst_memcpy_toio_32,
	.free = skl_dsp_free,
};

static struct sst_dsp_device skl_dev = {
	.thread = skl_dsp_irq_thread_handler,
	.ops = &skl_ops,
};

int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
540
		const char *fw_name, struct skl_dsp_loader_ops dsp_ops, struct skl_sst **dsp)
541 542 543 544 545
{
	struct skl_sst *skl;
	struct sst_dsp *sst;
	int ret;

546 547 548 549
	ret = skl_sst_ctx_init(dev, irq, fw_name, dsp_ops, dsp, &skl_dev);
	if (ret < 0) {
		dev_err(dev, "%s: no device\n", __func__);
		return ret;
550 551
	}

552
	skl = *dsp;
553 554 555
	sst = skl->dsp;
	sst->addr.lpe = mmio_base;
	sst->addr.shim = mmio_base;
556 557 558 559 560
	sst->addr.sram0_base = SKL_ADSP_SRAM0_BASE;
	sst->addr.sram1_base = SKL_ADSP_SRAM1_BASE;
	sst->addr.w0_stat_sz = SKL_ADSP_W0_STAT_SZ;
	sst->addr.w0_up_sz = SKL_ADSP_W0_UP_SZ;

561 562 563
	sst_dsp_mailbox_init(sst, (SKL_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ),
			SKL_ADSP_W0_UP_SZ, SKL_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ);

564
	ret = skl_ipc_init(dev, skl);
565 566
	if (ret) {
		skl_dsp_free(sst);
567
		return ret;
568
	}
569

570 571
	sst->fw_ops = skl_fw_ops;

572
	return 0;
573 574 575
}
EXPORT_SYMBOL_GPL(skl_sst_dsp_init);

576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596
int kbl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
		const char *fw_name, struct skl_dsp_loader_ops dsp_ops,
		struct skl_sst **dsp)
{
	struct sst_dsp *sst;
	int ret;

	ret = skl_sst_dsp_init(dev, mmio_base, irq, fw_name, dsp_ops, dsp);
	if (ret < 0) {
		dev_err(dev, "%s: Init failed %d\n", __func__, ret);
		return ret;
	}

	sst = (*dsp)->dsp;
	sst->fw_ops = kbl_fw_ops;

	return 0;

}
EXPORT_SYMBOL_GPL(kbl_sst_dsp_init);

597 598 599 600
int skl_sst_init_fw(struct device *dev, struct skl_sst *ctx)
{
	int ret;
	struct sst_dsp *sst = ctx->dsp;
601

602 603
	ret = sst->fw_ops.load_fw(sst);
	if (ret < 0) {
604
		dev_err(dev, "Load base fw failed : %d\n", ret);
605
		return ret;
606 607
	}

608
	skl_dsp_init_core_state(sst);
609 610 611 612 613 614 615 616 617

	if (ctx->lib_count > 1) {
		ret = sst->fw_ops.load_library(sst, ctx->lib_info,
						ctx->lib_count);
		if (ret < 0) {
			dev_err(dev, "Load Library failed : %x\n", ret);
			return ret;
		}
	}
618
	ctx->is_first_boot = false;
619

620
	return 0;
621
}
622
EXPORT_SYMBOL_GPL(skl_sst_init_fw);
623 624 625

void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx)
{
626 627 628

	if (ctx->dsp->fw)
		release_firmware(ctx->dsp->fw);
629
	skl_clear_module_table(ctx->dsp);
630
	skl_freeup_uuid_list(ctx);
631 632
	skl_ipc_free(&ctx->ipc);
	ctx->dsp->ops->free(ctx->dsp);
633 634 635 636
	if (ctx->boot_complete) {
		ctx->dsp->cl_dev.ops.cl_cleanup_controller(ctx->dsp);
		skl_cldma_int_disable(ctx->dsp);
	}
637 638 639 640 641
}
EXPORT_SYMBOL_GPL(skl_sst_dsp_cleanup);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Intel Skylake IPC driver");