Linux Audio

Check our new training course

Loading...
v6.8
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Qualcomm ADSP/SLPI Peripheral Image Loader for MSM8974 and MSM8996
   4 *
   5 * Copyright (C) 2016 Linaro Ltd
   6 * Copyright (C) 2014 Sony Mobile Communications AB
   7 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
   8 */
   9
  10#include <linux/clk.h>
  11#include <linux/delay.h>
  12#include <linux/firmware.h>
  13#include <linux/interrupt.h>
  14#include <linux/kernel.h>
  15#include <linux/module.h>
  16#include <linux/of.h>
  17#include <linux/of_address.h>
  18#include <linux/of_reserved_mem.h>
  19#include <linux/platform_device.h>
  20#include <linux/pm_domain.h>
  21#include <linux/pm_runtime.h>
  22#include <linux/firmware/qcom/qcom_scm.h>
  23#include <linux/regulator/consumer.h>
  24#include <linux/remoteproc.h>
  25#include <linux/soc/qcom/mdt_loader.h>
  26#include <linux/soc/qcom/smem.h>
  27#include <linux/soc/qcom/smem_state.h>
  28
  29#include "qcom_common.h"
  30#include "qcom_pil_info.h"
  31#include "qcom_q6v5.h"
  32#include "remoteproc_internal.h"
  33
  34#define ADSP_DECRYPT_SHUTDOWN_DELAY_MS	100
  35
 
 
  36struct adsp_data {
  37	int crash_reason_smem;
  38	const char *firmware_name;
  39	const char *dtb_firmware_name;
  40	int pas_id;
  41	int dtb_pas_id;
 
  42	unsigned int minidump_id;
  43	bool auto_boot;
  44	bool decrypt_shutdown;
  45
  46	char **proxy_pd_names;
  47
  48	const char *load_state;
  49	const char *ssr_name;
  50	const char *sysmon_name;
  51	int ssctl_id;
  52
  53	int region_assign_idx;
 
 
 
  54};
  55
  56struct qcom_adsp {
  57	struct device *dev;
  58	struct rproc *rproc;
  59
  60	struct qcom_q6v5 q6v5;
  61
  62	struct clk *xo;
  63	struct clk *aggre2_clk;
  64
  65	struct regulator *cx_supply;
  66	struct regulator *px_supply;
  67
  68	struct device *proxy_pds[3];
  69
  70	int proxy_pd_count;
  71
  72	const char *dtb_firmware_name;
  73	int pas_id;
  74	int dtb_pas_id;
 
  75	unsigned int minidump_id;
  76	int crash_reason_smem;
  77	bool decrypt_shutdown;
  78	const char *info_name;
  79
  80	const struct firmware *firmware;
  81	const struct firmware *dtb_firmware;
  82
  83	struct completion start_done;
  84	struct completion stop_done;
  85
  86	phys_addr_t mem_phys;
  87	phys_addr_t dtb_mem_phys;
  88	phys_addr_t mem_reloc;
  89	phys_addr_t dtb_mem_reloc;
  90	phys_addr_t region_assign_phys;
  91	void *mem_region;
  92	void *dtb_mem_region;
  93	size_t mem_size;
  94	size_t dtb_mem_size;
  95	size_t region_assign_size;
  96
  97	int region_assign_idx;
  98	u64 region_assign_perms;
 
 
 
  99
 100	struct qcom_rproc_glink glink_subdev;
 101	struct qcom_rproc_subdev smd_subdev;
 102	struct qcom_rproc_ssr ssr_subdev;
 103	struct qcom_sysmon *sysmon;
 104
 105	struct qcom_scm_pas_metadata pas_metadata;
 106	struct qcom_scm_pas_metadata dtb_pas_metadata;
 107};
 108
 109static void adsp_segment_dump(struct rproc *rproc, struct rproc_dump_segment *segment,
 110		       void *dest, size_t offset, size_t size)
 111{
 112	struct qcom_adsp *adsp = rproc->priv;
 113	int total_offset;
 114
 115	total_offset = segment->da + segment->offset + offset - adsp->mem_phys;
 116	if (total_offset < 0 || total_offset + size > adsp->mem_size) {
 117		dev_err(adsp->dev,
 118			"invalid copy request for segment %pad with offset %zu and size %zu)\n",
 119			&segment->da, offset, size);
 120		memset(dest, 0xff, size);
 121		return;
 122	}
 123
 124	memcpy_fromio(dest, adsp->mem_region + total_offset, size);
 125}
 126
 127static void adsp_minidump(struct rproc *rproc)
 128{
 129	struct qcom_adsp *adsp = rproc->priv;
 130
 131	if (rproc->dump_conf == RPROC_COREDUMP_DISABLED)
 132		return;
 133
 134	qcom_minidump(rproc, adsp->minidump_id, adsp_segment_dump);
 135}
 136
 137static int adsp_pds_enable(struct qcom_adsp *adsp, struct device **pds,
 138			   size_t pd_count)
 139{
 140	int ret;
 141	int i;
 142
 143	for (i = 0; i < pd_count; i++) {
 144		dev_pm_genpd_set_performance_state(pds[i], INT_MAX);
 145		ret = pm_runtime_get_sync(pds[i]);
 146		if (ret < 0) {
 147			pm_runtime_put_noidle(pds[i]);
 148			dev_pm_genpd_set_performance_state(pds[i], 0);
 149			goto unroll_pd_votes;
 150		}
 151	}
 152
 153	return 0;
 154
 155unroll_pd_votes:
 156	for (i--; i >= 0; i--) {
 157		dev_pm_genpd_set_performance_state(pds[i], 0);
 158		pm_runtime_put(pds[i]);
 159	}
 160
 161	return ret;
 162};
 163
 164static void adsp_pds_disable(struct qcom_adsp *adsp, struct device **pds,
 165			     size_t pd_count)
 166{
 167	int i;
 168
 169	for (i = 0; i < pd_count; i++) {
 170		dev_pm_genpd_set_performance_state(pds[i], 0);
 171		pm_runtime_put(pds[i]);
 172	}
 173}
 174
 175static int adsp_shutdown_poll_decrypt(struct qcom_adsp *adsp)
 176{
 177	unsigned int retry_num = 50;
 178	int ret;
 179
 180	do {
 181		msleep(ADSP_DECRYPT_SHUTDOWN_DELAY_MS);
 182		ret = qcom_scm_pas_shutdown(adsp->pas_id);
 183	} while (ret == -EINVAL && --retry_num);
 184
 185	return ret;
 186}
 187
 188static int adsp_unprepare(struct rproc *rproc)
 189{
 190	struct qcom_adsp *adsp = rproc->priv;
 191
 192	/*
 193	 * adsp_load() did pass pas_metadata to the SCM driver for storing
 194	 * metadata context. It might have been released already if
 195	 * auth_and_reset() was successful, but in other cases clean it up
 196	 * here.
 197	 */
 198	qcom_scm_pas_metadata_release(&adsp->pas_metadata);
 199	if (adsp->dtb_pas_id)
 200		qcom_scm_pas_metadata_release(&adsp->dtb_pas_metadata);
 201
 202	return 0;
 203}
 204
 205static int adsp_load(struct rproc *rproc, const struct firmware *fw)
 206{
 207	struct qcom_adsp *adsp = rproc->priv;
 208	int ret;
 209
 210	/* Store firmware handle to be used in adsp_start() */
 211	adsp->firmware = fw;
 212
 
 
 
 213	if (adsp->dtb_pas_id) {
 214		ret = request_firmware(&adsp->dtb_firmware, adsp->dtb_firmware_name, adsp->dev);
 215		if (ret) {
 216			dev_err(adsp->dev, "request_firmware failed for %s: %d\n",
 217				adsp->dtb_firmware_name, ret);
 218			return ret;
 219		}
 220
 221		ret = qcom_mdt_pas_init(adsp->dev, adsp->dtb_firmware, adsp->dtb_firmware_name,
 222					adsp->dtb_pas_id, adsp->dtb_mem_phys,
 223					&adsp->dtb_pas_metadata);
 224		if (ret)
 225			goto release_dtb_firmware;
 226
 227		ret = qcom_mdt_load_no_init(adsp->dev, adsp->dtb_firmware, adsp->dtb_firmware_name,
 228					    adsp->dtb_pas_id, adsp->dtb_mem_region,
 229					    adsp->dtb_mem_phys, adsp->dtb_mem_size,
 230					    &adsp->dtb_mem_reloc);
 231		if (ret)
 232			goto release_dtb_metadata;
 233	}
 234
 235	return 0;
 236
 237release_dtb_metadata:
 238	qcom_scm_pas_metadata_release(&adsp->dtb_pas_metadata);
 239
 240release_dtb_firmware:
 241	release_firmware(adsp->dtb_firmware);
 242
 243	return ret;
 244}
 245
 246static int adsp_start(struct rproc *rproc)
 247{
 248	struct qcom_adsp *adsp = rproc->priv;
 249	int ret;
 250
 251	ret = qcom_q6v5_prepare(&adsp->q6v5);
 252	if (ret)
 253		return ret;
 254
 255	ret = adsp_pds_enable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
 256	if (ret < 0)
 257		goto disable_irqs;
 258
 259	ret = clk_prepare_enable(adsp->xo);
 260	if (ret)
 261		goto disable_proxy_pds;
 262
 263	ret = clk_prepare_enable(adsp->aggre2_clk);
 264	if (ret)
 265		goto disable_xo_clk;
 266
 267	if (adsp->cx_supply) {
 268		ret = regulator_enable(adsp->cx_supply);
 269		if (ret)
 270			goto disable_aggre2_clk;
 271	}
 272
 273	if (adsp->px_supply) {
 274		ret = regulator_enable(adsp->px_supply);
 275		if (ret)
 276			goto disable_cx_supply;
 277	}
 278
 279	if (adsp->dtb_pas_id) {
 280		ret = qcom_scm_pas_auth_and_reset(adsp->dtb_pas_id);
 281		if (ret) {
 282			dev_err(adsp->dev,
 283				"failed to authenticate dtb image and release reset\n");
 284			goto disable_px_supply;
 285		}
 286	}
 287
 288	ret = qcom_mdt_pas_init(adsp->dev, adsp->firmware, rproc->firmware, adsp->pas_id,
 289				adsp->mem_phys, &adsp->pas_metadata);
 290	if (ret)
 291		goto disable_px_supply;
 292
 293	ret = qcom_mdt_load_no_init(adsp->dev, adsp->firmware, rproc->firmware, adsp->pas_id,
 294				    adsp->mem_region, adsp->mem_phys, adsp->mem_size,
 295				    &adsp->mem_reloc);
 296	if (ret)
 297		goto release_pas_metadata;
 298
 299	qcom_pil_info_store(adsp->info_name, adsp->mem_phys, adsp->mem_size);
 300
 301	ret = qcom_scm_pas_auth_and_reset(adsp->pas_id);
 302	if (ret) {
 303		dev_err(adsp->dev,
 304			"failed to authenticate image and release reset\n");
 305		goto release_pas_metadata;
 306	}
 307
 308	ret = qcom_q6v5_wait_for_start(&adsp->q6v5, msecs_to_jiffies(5000));
 309	if (ret == -ETIMEDOUT) {
 310		dev_err(adsp->dev, "start timed out\n");
 311		qcom_scm_pas_shutdown(adsp->pas_id);
 312		goto release_pas_metadata;
 313	}
 314
 315	qcom_scm_pas_metadata_release(&adsp->pas_metadata);
 316	if (adsp->dtb_pas_id)
 317		qcom_scm_pas_metadata_release(&adsp->dtb_pas_metadata);
 318
 319	/* Remove pointer to the loaded firmware, only valid in adsp_load() & adsp_start() */
 320	adsp->firmware = NULL;
 321
 322	return 0;
 323
 324release_pas_metadata:
 325	qcom_scm_pas_metadata_release(&adsp->pas_metadata);
 326	if (adsp->dtb_pas_id)
 327		qcom_scm_pas_metadata_release(&adsp->dtb_pas_metadata);
 328disable_px_supply:
 329	if (adsp->px_supply)
 330		regulator_disable(adsp->px_supply);
 331disable_cx_supply:
 332	if (adsp->cx_supply)
 333		regulator_disable(adsp->cx_supply);
 334disable_aggre2_clk:
 335	clk_disable_unprepare(adsp->aggre2_clk);
 336disable_xo_clk:
 337	clk_disable_unprepare(adsp->xo);
 338disable_proxy_pds:
 339	adsp_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
 340disable_irqs:
 341	qcom_q6v5_unprepare(&adsp->q6v5);
 342
 343	/* Remove pointer to the loaded firmware, only valid in adsp_load() & adsp_start() */
 344	adsp->firmware = NULL;
 345
 346	return ret;
 347}
 348
 349static void qcom_pas_handover(struct qcom_q6v5 *q6v5)
 350{
 351	struct qcom_adsp *adsp = container_of(q6v5, struct qcom_adsp, q6v5);
 352
 353	if (adsp->px_supply)
 354		regulator_disable(adsp->px_supply);
 355	if (adsp->cx_supply)
 356		regulator_disable(adsp->cx_supply);
 357	clk_disable_unprepare(adsp->aggre2_clk);
 358	clk_disable_unprepare(adsp->xo);
 359	adsp_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
 360}
 361
 362static int adsp_stop(struct rproc *rproc)
 363{
 364	struct qcom_adsp *adsp = rproc->priv;
 365	int handover;
 366	int ret;
 367
 368	ret = qcom_q6v5_request_stop(&adsp->q6v5, adsp->sysmon);
 369	if (ret == -ETIMEDOUT)
 370		dev_err(adsp->dev, "timed out on wait\n");
 371
 372	ret = qcom_scm_pas_shutdown(adsp->pas_id);
 373	if (ret && adsp->decrypt_shutdown)
 374		ret = adsp_shutdown_poll_decrypt(adsp);
 375
 376	if (ret)
 377		dev_err(adsp->dev, "failed to shutdown: %d\n", ret);
 378
 379	if (adsp->dtb_pas_id) {
 380		ret = qcom_scm_pas_shutdown(adsp->dtb_pas_id);
 381		if (ret)
 382			dev_err(adsp->dev, "failed to shutdown dtb: %d\n", ret);
 383	}
 384
 385	handover = qcom_q6v5_unprepare(&adsp->q6v5);
 386	if (handover)
 387		qcom_pas_handover(&adsp->q6v5);
 388
 389	return ret;
 390}
 391
 392static void *adsp_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 393{
 394	struct qcom_adsp *adsp = rproc->priv;
 395	int offset;
 396
 397	offset = da - adsp->mem_reloc;
 398	if (offset < 0 || offset + len > adsp->mem_size)
 399		return NULL;
 400
 401	if (is_iomem)
 402		*is_iomem = true;
 403
 404	return adsp->mem_region + offset;
 405}
 406
 407static unsigned long adsp_panic(struct rproc *rproc)
 408{
 409	struct qcom_adsp *adsp = rproc->priv;
 410
 411	return qcom_q6v5_panic(&adsp->q6v5);
 412}
 413
 414static const struct rproc_ops adsp_ops = {
 415	.unprepare = adsp_unprepare,
 416	.start = adsp_start,
 417	.stop = adsp_stop,
 418	.da_to_va = adsp_da_to_va,
 419	.parse_fw = qcom_register_dump_segments,
 420	.load = adsp_load,
 421	.panic = adsp_panic,
 422};
 423
 424static const struct rproc_ops adsp_minidump_ops = {
 425	.unprepare = adsp_unprepare,
 426	.start = adsp_start,
 427	.stop = adsp_stop,
 428	.da_to_va = adsp_da_to_va,
 429	.parse_fw = qcom_register_dump_segments,
 430	.load = adsp_load,
 431	.panic = adsp_panic,
 432	.coredump = adsp_minidump,
 433};
 434
 435static int adsp_init_clock(struct qcom_adsp *adsp)
 436{
 437	int ret;
 438
 439	adsp->xo = devm_clk_get(adsp->dev, "xo");
 440	if (IS_ERR(adsp->xo)) {
 441		ret = PTR_ERR(adsp->xo);
 442		if (ret != -EPROBE_DEFER)
 443			dev_err(adsp->dev, "failed to get xo clock");
 444		return ret;
 445	}
 446
 447	adsp->aggre2_clk = devm_clk_get_optional(adsp->dev, "aggre2");
 448	if (IS_ERR(adsp->aggre2_clk)) {
 449		ret = PTR_ERR(adsp->aggre2_clk);
 450		if (ret != -EPROBE_DEFER)
 451			dev_err(adsp->dev,
 452				"failed to get aggre2 clock");
 453		return ret;
 454	}
 455
 456	return 0;
 457}
 458
 459static int adsp_init_regulator(struct qcom_adsp *adsp)
 460{
 461	adsp->cx_supply = devm_regulator_get_optional(adsp->dev, "cx");
 462	if (IS_ERR(adsp->cx_supply)) {
 463		if (PTR_ERR(adsp->cx_supply) == -ENODEV)
 464			adsp->cx_supply = NULL;
 465		else
 466			return PTR_ERR(adsp->cx_supply);
 467	}
 468
 469	if (adsp->cx_supply)
 470		regulator_set_load(adsp->cx_supply, 100000);
 471
 472	adsp->px_supply = devm_regulator_get_optional(adsp->dev, "px");
 473	if (IS_ERR(adsp->px_supply)) {
 474		if (PTR_ERR(adsp->px_supply) == -ENODEV)
 475			adsp->px_supply = NULL;
 476		else
 477			return PTR_ERR(adsp->px_supply);
 478	}
 479
 480	return 0;
 481}
 482
 483static int adsp_pds_attach(struct device *dev, struct device **devs,
 484			   char **pd_names)
 485{
 486	size_t num_pds = 0;
 487	int ret;
 488	int i;
 489
 490	if (!pd_names)
 491		return 0;
 492
 493	/* Handle single power domain */
 494	if (dev->pm_domain) {
 495		devs[0] = dev;
 496		pm_runtime_enable(dev);
 497		return 1;
 498	}
 499
 500	while (pd_names[num_pds])
 501		num_pds++;
 502
 503	for (i = 0; i < num_pds; i++) {
 504		devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]);
 505		if (IS_ERR_OR_NULL(devs[i])) {
 506			ret = PTR_ERR(devs[i]) ? : -ENODATA;
 507			goto unroll_attach;
 508		}
 509	}
 510
 511	return num_pds;
 512
 513unroll_attach:
 514	for (i--; i >= 0; i--)
 515		dev_pm_domain_detach(devs[i], false);
 516
 517	return ret;
 518};
 519
 520static void adsp_pds_detach(struct qcom_adsp *adsp, struct device **pds,
 521			    size_t pd_count)
 522{
 523	struct device *dev = adsp->dev;
 524	int i;
 525
 526	/* Handle single power domain */
 527	if (dev->pm_domain && pd_count) {
 528		pm_runtime_disable(dev);
 529		return;
 530	}
 531
 532	for (i = 0; i < pd_count; i++)
 533		dev_pm_domain_detach(pds[i], false);
 534}
 535
 536static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
 537{
 538	struct reserved_mem *rmem;
 539	struct device_node *node;
 540
 541	node = of_parse_phandle(adsp->dev->of_node, "memory-region", 0);
 542	if (!node) {
 543		dev_err(adsp->dev, "no memory-region specified\n");
 544		return -EINVAL;
 545	}
 546
 547	rmem = of_reserved_mem_lookup(node);
 548	of_node_put(node);
 549	if (!rmem) {
 550		dev_err(adsp->dev, "unable to resolve memory-region\n");
 551		return -EINVAL;
 552	}
 553
 554	adsp->mem_phys = adsp->mem_reloc = rmem->base;
 555	adsp->mem_size = rmem->size;
 556	adsp->mem_region = devm_ioremap_wc(adsp->dev, adsp->mem_phys, adsp->mem_size);
 557	if (!adsp->mem_region) {
 558		dev_err(adsp->dev, "unable to map memory region: %pa+%zx\n",
 559			&rmem->base, adsp->mem_size);
 560		return -EBUSY;
 561	}
 562
 563	if (!adsp->dtb_pas_id)
 564		return 0;
 565
 566	node = of_parse_phandle(adsp->dev->of_node, "memory-region", 1);
 567	if (!node) {
 568		dev_err(adsp->dev, "no dtb memory-region specified\n");
 569		return -EINVAL;
 570	}
 571
 572	rmem = of_reserved_mem_lookup(node);
 573	of_node_put(node);
 574	if (!rmem) {
 575		dev_err(adsp->dev, "unable to resolve dtb memory-region\n");
 576		return -EINVAL;
 577	}
 578
 579	adsp->dtb_mem_phys = adsp->dtb_mem_reloc = rmem->base;
 580	adsp->dtb_mem_size = rmem->size;
 581	adsp->dtb_mem_region = devm_ioremap_wc(adsp->dev, adsp->dtb_mem_phys, adsp->dtb_mem_size);
 582	if (!adsp->dtb_mem_region) {
 583		dev_err(adsp->dev, "unable to map dtb memory region: %pa+%zx\n",
 584			&rmem->base, adsp->dtb_mem_size);
 585		return -EBUSY;
 586	}
 587
 588	return 0;
 589}
 590
 591static int adsp_assign_memory_region(struct qcom_adsp *adsp)
 592{
 593	struct reserved_mem *rmem = NULL;
 594	struct qcom_scm_vmperm perm;
 595	struct device_node *node;
 
 
 596	int ret;
 597
 598	if (!adsp->region_assign_idx)
 599		return 0;
 600
 601	node = of_parse_phandle(adsp->dev->of_node, "memory-region", adsp->region_assign_idx);
 602	if (node)
 603		rmem = of_reserved_mem_lookup(node);
 604	of_node_put(node);
 605	if (!rmem) {
 606		dev_err(adsp->dev, "unable to resolve shareable memory-region\n");
 607		return -EINVAL;
 608	}
 609
 610	perm.vmid = QCOM_SCM_VMID_MSS_MSA;
 611	perm.perm = QCOM_SCM_PERM_RW;
 
 
 
 
 
 
 
 
 612
 613	adsp->region_assign_phys = rmem->base;
 614	adsp->region_assign_size = rmem->size;
 615	adsp->region_assign_perms = BIT(QCOM_SCM_VMID_HLOS);
 616
 617	ret = qcom_scm_assign_mem(adsp->region_assign_phys,
 618				  adsp->region_assign_size,
 619				  &adsp->region_assign_perms,
 620				  &perm, 1);
 621	if (ret < 0) {
 622		dev_err(adsp->dev, "assign memory failed\n");
 623		return ret;
 
 
 
 
 
 
 
 
 
 
 
 
 
 624	}
 625
 626	return 0;
 627}
 628
 629static void adsp_unassign_memory_region(struct qcom_adsp *adsp)
 630{
 631	struct qcom_scm_vmperm perm;
 
 632	int ret;
 633
 634	if (!adsp->region_assign_idx)
 635		return;
 636
 637	perm.vmid = QCOM_SCM_VMID_HLOS;
 638	perm.perm = QCOM_SCM_PERM_RW;
 639
 640	ret = qcom_scm_assign_mem(adsp->region_assign_phys,
 641				  adsp->region_assign_size,
 642				  &adsp->region_assign_perms,
 643				  &perm, 1);
 644	if (ret < 0)
 645		dev_err(adsp->dev, "unassign memory failed\n");
 
 
 646}
 647
 648static int adsp_probe(struct platform_device *pdev)
 649{
 650	const struct adsp_data *desc;
 651	struct qcom_adsp *adsp;
 652	struct rproc *rproc;
 653	const char *fw_name, *dtb_fw_name = NULL;
 654	const struct rproc_ops *ops = &adsp_ops;
 655	int ret;
 656
 657	desc = of_device_get_match_data(&pdev->dev);
 658	if (!desc)
 659		return -EINVAL;
 660
 661	if (!qcom_scm_is_available())
 662		return -EPROBE_DEFER;
 663
 664	fw_name = desc->firmware_name;
 665	ret = of_property_read_string(pdev->dev.of_node, "firmware-name",
 666				      &fw_name);
 667	if (ret < 0 && ret != -EINVAL)
 668		return ret;
 669
 670	if (desc->dtb_firmware_name) {
 671		dtb_fw_name = desc->dtb_firmware_name;
 672		ret = of_property_read_string_index(pdev->dev.of_node, "firmware-name", 1,
 673						    &dtb_fw_name);
 674		if (ret < 0 && ret != -EINVAL)
 675			return ret;
 676	}
 677
 678	if (desc->minidump_id)
 679		ops = &adsp_minidump_ops;
 680
 681	rproc = rproc_alloc(&pdev->dev, pdev->name, ops, fw_name, sizeof(*adsp));
 682
 683	if (!rproc) {
 684		dev_err(&pdev->dev, "unable to allocate remoteproc\n");
 685		return -ENOMEM;
 686	}
 687
 688	rproc->auto_boot = desc->auto_boot;
 689	rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);
 690
 691	adsp = rproc->priv;
 692	adsp->dev = &pdev->dev;
 693	adsp->rproc = rproc;
 694	adsp->minidump_id = desc->minidump_id;
 695	adsp->pas_id = desc->pas_id;
 
 696	adsp->info_name = desc->sysmon_name;
 697	adsp->decrypt_shutdown = desc->decrypt_shutdown;
 698	adsp->region_assign_idx = desc->region_assign_idx;
 
 
 
 699	if (dtb_fw_name) {
 700		adsp->dtb_firmware_name = dtb_fw_name;
 701		adsp->dtb_pas_id = desc->dtb_pas_id;
 702	}
 703	platform_set_drvdata(pdev, adsp);
 704
 705	ret = device_init_wakeup(adsp->dev, true);
 706	if (ret)
 707		goto free_rproc;
 708
 709	ret = adsp_alloc_memory_region(adsp);
 710	if (ret)
 711		goto free_rproc;
 712
 713	ret = adsp_assign_memory_region(adsp);
 714	if (ret)
 715		goto free_rproc;
 716
 717	ret = adsp_init_clock(adsp);
 718	if (ret)
 719		goto free_rproc;
 720
 721	ret = adsp_init_regulator(adsp);
 722	if (ret)
 723		goto free_rproc;
 724
 725	ret = adsp_pds_attach(&pdev->dev, adsp->proxy_pds,
 726			      desc->proxy_pd_names);
 727	if (ret < 0)
 728		goto free_rproc;
 729	adsp->proxy_pd_count = ret;
 730
 731	ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem, desc->load_state,
 732			     qcom_pas_handover);
 733	if (ret)
 734		goto detach_proxy_pds;
 735
 736	qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
 737	qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
 738	adsp->sysmon = qcom_add_sysmon_subdev(rproc,
 739					      desc->sysmon_name,
 740					      desc->ssctl_id);
 741	if (IS_ERR(adsp->sysmon)) {
 742		ret = PTR_ERR(adsp->sysmon);
 743		goto detach_proxy_pds;
 744	}
 745
 746	qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
 747	ret = rproc_add(rproc);
 748	if (ret)
 749		goto detach_proxy_pds;
 750
 751	return 0;
 752
 753detach_proxy_pds:
 754	adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
 755free_rproc:
 756	device_init_wakeup(adsp->dev, false);
 757	rproc_free(rproc);
 758
 759	return ret;
 760}
 761
 762static void adsp_remove(struct platform_device *pdev)
 763{
 764	struct qcom_adsp *adsp = platform_get_drvdata(pdev);
 765
 766	rproc_del(adsp->rproc);
 767
 768	qcom_q6v5_deinit(&adsp->q6v5);
 769	adsp_unassign_memory_region(adsp);
 770	qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
 771	qcom_remove_sysmon_subdev(adsp->sysmon);
 772	qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
 773	qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
 774	adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
 775	device_init_wakeup(adsp->dev, false);
 776	rproc_free(adsp->rproc);
 777}
 778
 779static const struct adsp_data adsp_resource_init = {
 780		.crash_reason_smem = 423,
 781		.firmware_name = "adsp.mdt",
 782		.pas_id = 1,
 783		.auto_boot = true,
 784		.ssr_name = "lpass",
 785		.sysmon_name = "adsp",
 786		.ssctl_id = 0x14,
 787};
 788
 789static const struct adsp_data sdm845_adsp_resource_init = {
 790		.crash_reason_smem = 423,
 791		.firmware_name = "adsp.mdt",
 792		.pas_id = 1,
 793		.auto_boot = true,
 794		.load_state = "adsp",
 795		.ssr_name = "lpass",
 796		.sysmon_name = "adsp",
 797		.ssctl_id = 0x14,
 798};
 799
 800static const struct adsp_data sm6350_adsp_resource = {
 801	.crash_reason_smem = 423,
 802	.firmware_name = "adsp.mdt",
 803	.pas_id = 1,
 804	.auto_boot = true,
 805	.proxy_pd_names = (char*[]){
 806		"lcx",
 807		"lmx",
 808		NULL
 809	},
 810	.load_state = "adsp",
 811	.ssr_name = "lpass",
 812	.sysmon_name = "adsp",
 813	.ssctl_id = 0x14,
 814};
 815
 816static const struct adsp_data sm6375_mpss_resource = {
 817	.crash_reason_smem = 421,
 818	.firmware_name = "modem.mdt",
 819	.pas_id = 4,
 820	.minidump_id = 3,
 821	.auto_boot = false,
 822	.proxy_pd_names = (char*[]){
 823		"cx",
 824		NULL
 825	},
 826	.ssr_name = "mpss",
 827	.sysmon_name = "modem",
 828	.ssctl_id = 0x12,
 829};
 830
 831static const struct adsp_data sm8150_adsp_resource = {
 832		.crash_reason_smem = 423,
 833		.firmware_name = "adsp.mdt",
 834		.pas_id = 1,
 835		.auto_boot = true,
 836		.proxy_pd_names = (char*[]){
 837			"cx",
 838			NULL
 839		},
 840		.load_state = "adsp",
 841		.ssr_name = "lpass",
 842		.sysmon_name = "adsp",
 843		.ssctl_id = 0x14,
 844};
 845
 846static const struct adsp_data sm8250_adsp_resource = {
 847	.crash_reason_smem = 423,
 848	.firmware_name = "adsp.mdt",
 849	.pas_id = 1,
 850	.auto_boot = true,
 851	.proxy_pd_names = (char*[]){
 852		"lcx",
 853		"lmx",
 854		NULL
 855	},
 856	.load_state = "adsp",
 857	.ssr_name = "lpass",
 858	.sysmon_name = "adsp",
 859	.ssctl_id = 0x14,
 860};
 861
 862static const struct adsp_data sm8350_adsp_resource = {
 863	.crash_reason_smem = 423,
 864	.firmware_name = "adsp.mdt",
 865	.pas_id = 1,
 866	.auto_boot = true,
 867	.proxy_pd_names = (char*[]){
 868		"lcx",
 869		"lmx",
 870		NULL
 871	},
 872	.load_state = "adsp",
 873	.ssr_name = "lpass",
 874	.sysmon_name = "adsp",
 875	.ssctl_id = 0x14,
 876};
 877
 878static const struct adsp_data msm8996_adsp_resource = {
 879		.crash_reason_smem = 423,
 880		.firmware_name = "adsp.mdt",
 881		.pas_id = 1,
 882		.auto_boot = true,
 883		.proxy_pd_names = (char*[]){
 884			"cx",
 885			NULL
 886		},
 887		.ssr_name = "lpass",
 888		.sysmon_name = "adsp",
 889		.ssctl_id = 0x14,
 890};
 891
 892static const struct adsp_data cdsp_resource_init = {
 893	.crash_reason_smem = 601,
 894	.firmware_name = "cdsp.mdt",
 895	.pas_id = 18,
 896	.auto_boot = true,
 897	.ssr_name = "cdsp",
 898	.sysmon_name = "cdsp",
 899	.ssctl_id = 0x17,
 900};
 901
 902static const struct adsp_data sdm845_cdsp_resource_init = {
 903	.crash_reason_smem = 601,
 904	.firmware_name = "cdsp.mdt",
 905	.pas_id = 18,
 906	.auto_boot = true,
 907	.load_state = "cdsp",
 908	.ssr_name = "cdsp",
 909	.sysmon_name = "cdsp",
 910	.ssctl_id = 0x17,
 911};
 912
 913static const struct adsp_data sm6350_cdsp_resource = {
 914	.crash_reason_smem = 601,
 915	.firmware_name = "cdsp.mdt",
 916	.pas_id = 18,
 917	.auto_boot = true,
 918	.proxy_pd_names = (char*[]){
 919		"cx",
 920		"mx",
 921		NULL
 922	},
 923	.load_state = "cdsp",
 924	.ssr_name = "cdsp",
 925	.sysmon_name = "cdsp",
 926	.ssctl_id = 0x17,
 927};
 928
 929static const struct adsp_data sm8150_cdsp_resource = {
 930	.crash_reason_smem = 601,
 931	.firmware_name = "cdsp.mdt",
 932	.pas_id = 18,
 933	.auto_boot = true,
 934	.proxy_pd_names = (char*[]){
 935		"cx",
 936		NULL
 937	},
 938	.load_state = "cdsp",
 939	.ssr_name = "cdsp",
 940	.sysmon_name = "cdsp",
 941	.ssctl_id = 0x17,
 942};
 943
 944static const struct adsp_data sm8250_cdsp_resource = {
 945	.crash_reason_smem = 601,
 946	.firmware_name = "cdsp.mdt",
 947	.pas_id = 18,
 948	.auto_boot = true,
 949	.proxy_pd_names = (char*[]){
 950		"cx",
 951		NULL
 952	},
 953	.load_state = "cdsp",
 954	.ssr_name = "cdsp",
 955	.sysmon_name = "cdsp",
 956	.ssctl_id = 0x17,
 957};
 958
 959static const struct adsp_data sc8280xp_nsp0_resource = {
 960	.crash_reason_smem = 601,
 961	.firmware_name = "cdsp.mdt",
 962	.pas_id = 18,
 963	.auto_boot = true,
 964	.proxy_pd_names = (char*[]){
 965		"nsp",
 966		NULL
 967	},
 968	.ssr_name = "cdsp0",
 969	.sysmon_name = "cdsp",
 970	.ssctl_id = 0x17,
 971};
 972
 973static const struct adsp_data sc8280xp_nsp1_resource = {
 974	.crash_reason_smem = 633,
 975	.firmware_name = "cdsp.mdt",
 976	.pas_id = 30,
 977	.auto_boot = true,
 978	.proxy_pd_names = (char*[]){
 979		"nsp",
 980		NULL
 981	},
 982	.ssr_name = "cdsp1",
 983	.sysmon_name = "cdsp1",
 984	.ssctl_id = 0x20,
 985};
 986
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 987static const struct adsp_data sm8350_cdsp_resource = {
 988	.crash_reason_smem = 601,
 989	.firmware_name = "cdsp.mdt",
 990	.pas_id = 18,
 991	.auto_boot = true,
 992	.proxy_pd_names = (char*[]){
 993		"cx",
 994		"mxc",
 995		NULL
 996	},
 997	.load_state = "cdsp",
 998	.ssr_name = "cdsp",
 999	.sysmon_name = "cdsp",
1000	.ssctl_id = 0x17,
1001};
1002
1003static const struct adsp_data mpss_resource_init = {
1004	.crash_reason_smem = 421,
1005	.firmware_name = "modem.mdt",
1006	.pas_id = 4,
1007	.minidump_id = 3,
1008	.auto_boot = false,
1009	.proxy_pd_names = (char*[]){
1010		"cx",
1011		"mss",
1012		NULL
1013	},
1014	.load_state = "modem",
1015	.ssr_name = "mpss",
1016	.sysmon_name = "modem",
1017	.ssctl_id = 0x12,
1018};
1019
1020static const struct adsp_data sc8180x_mpss_resource = {
1021	.crash_reason_smem = 421,
1022	.firmware_name = "modem.mdt",
1023	.pas_id = 4,
1024	.auto_boot = false,
1025	.proxy_pd_names = (char*[]){
1026		"cx",
1027		NULL
1028	},
1029	.load_state = "modem",
1030	.ssr_name = "mpss",
1031	.sysmon_name = "modem",
1032	.ssctl_id = 0x12,
1033};
1034
1035static const struct adsp_data msm8996_slpi_resource_init = {
1036		.crash_reason_smem = 424,
1037		.firmware_name = "slpi.mdt",
1038		.pas_id = 12,
1039		.auto_boot = true,
1040		.proxy_pd_names = (char*[]){
1041			"ssc_cx",
1042			NULL
1043		},
1044		.ssr_name = "dsps",
1045		.sysmon_name = "slpi",
1046		.ssctl_id = 0x16,
1047};
1048
1049static const struct adsp_data sdm845_slpi_resource_init = {
1050		.crash_reason_smem = 424,
1051		.firmware_name = "slpi.mdt",
1052		.pas_id = 12,
1053		.auto_boot = true,
1054		.proxy_pd_names = (char*[]){
1055			"lcx",
1056			"lmx",
1057			NULL
1058		},
1059		.load_state = "slpi",
1060		.ssr_name = "dsps",
1061		.sysmon_name = "slpi",
1062		.ssctl_id = 0x16,
1063};
1064
1065static const struct adsp_data wcss_resource_init = {
1066	.crash_reason_smem = 421,
1067	.firmware_name = "wcnss.mdt",
1068	.pas_id = 6,
1069	.auto_boot = true,
1070	.ssr_name = "mpss",
1071	.sysmon_name = "wcnss",
1072	.ssctl_id = 0x12,
1073};
1074
1075static const struct adsp_data sdx55_mpss_resource = {
1076	.crash_reason_smem = 421,
1077	.firmware_name = "modem.mdt",
1078	.pas_id = 4,
1079	.auto_boot = true,
1080	.proxy_pd_names = (char*[]){
1081		"cx",
1082		"mss",
1083		NULL
1084	},
1085	.ssr_name = "mpss",
1086	.sysmon_name = "modem",
1087	.ssctl_id = 0x22,
1088};
1089
1090static const struct adsp_data sm8450_mpss_resource = {
1091	.crash_reason_smem = 421,
1092	.firmware_name = "modem.mdt",
1093	.pas_id = 4,
1094	.minidump_id = 3,
1095	.auto_boot = false,
1096	.decrypt_shutdown = true,
1097	.proxy_pd_names = (char*[]){
1098		"cx",
1099		"mss",
1100		NULL
1101	},
1102	.load_state = "modem",
1103	.ssr_name = "mpss",
1104	.sysmon_name = "modem",
1105	.ssctl_id = 0x12,
1106};
1107
1108static const struct adsp_data sm8550_adsp_resource = {
1109	.crash_reason_smem = 423,
1110	.firmware_name = "adsp.mdt",
1111	.dtb_firmware_name = "adsp_dtb.mdt",
1112	.pas_id = 1,
1113	.dtb_pas_id = 0x24,
1114	.minidump_id = 5,
1115	.auto_boot = true,
1116	.proxy_pd_names = (char*[]){
1117		"lcx",
1118		"lmx",
1119		NULL
1120	},
1121	.load_state = "adsp",
1122	.ssr_name = "lpass",
1123	.sysmon_name = "adsp",
1124	.ssctl_id = 0x14,
1125};
1126
1127static const struct adsp_data sm8550_cdsp_resource = {
1128	.crash_reason_smem = 601,
1129	.firmware_name = "cdsp.mdt",
1130	.dtb_firmware_name = "cdsp_dtb.mdt",
1131	.pas_id = 18,
1132	.dtb_pas_id = 0x25,
1133	.minidump_id = 7,
1134	.auto_boot = true,
1135	.proxy_pd_names = (char*[]){
1136		"cx",
1137		"mxc",
1138		"nsp",
1139		NULL
1140	},
1141	.load_state = "cdsp",
1142	.ssr_name = "cdsp",
1143	.sysmon_name = "cdsp",
1144	.ssctl_id = 0x17,
1145};
1146
1147static const struct adsp_data sm8550_mpss_resource = {
1148	.crash_reason_smem = 421,
1149	.firmware_name = "modem.mdt",
1150	.dtb_firmware_name = "modem_dtb.mdt",
1151	.pas_id = 4,
1152	.dtb_pas_id = 0x26,
1153	.minidump_id = 3,
1154	.auto_boot = false,
1155	.decrypt_shutdown = true,
1156	.proxy_pd_names = (char*[]){
1157		"cx",
1158		"mss",
1159		NULL
1160	},
1161	.load_state = "modem",
1162	.ssr_name = "mpss",
1163	.sysmon_name = "modem",
1164	.ssctl_id = 0x12,
1165	.region_assign_idx = 2,
 
 
1166};
1167
1168static const struct adsp_data sc7280_wpss_resource = {
1169	.crash_reason_smem = 626,
1170	.firmware_name = "wpss.mdt",
1171	.pas_id = 6,
1172	.auto_boot = true,
1173	.proxy_pd_names = (char*[]){
1174		"cx",
1175		"mx",
1176		NULL
1177	},
1178	.load_state = "wpss",
1179	.ssr_name = "wpss",
1180	.sysmon_name = "wpss",
1181	.ssctl_id = 0x19,
1182};
1183
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1184static const struct of_device_id adsp_of_match[] = {
1185	{ .compatible = "qcom,msm8226-adsp-pil", .data = &adsp_resource_init},
1186	{ .compatible = "qcom,msm8953-adsp-pil", .data = &msm8996_adsp_resource},
1187	{ .compatible = "qcom,msm8974-adsp-pil", .data = &adsp_resource_init},
1188	{ .compatible = "qcom,msm8996-adsp-pil", .data = &msm8996_adsp_resource},
1189	{ .compatible = "qcom,msm8996-slpi-pil", .data = &msm8996_slpi_resource_init},
1190	{ .compatible = "qcom,msm8998-adsp-pas", .data = &msm8996_adsp_resource},
1191	{ .compatible = "qcom,msm8998-slpi-pas", .data = &msm8996_slpi_resource_init},
1192	{ .compatible = "qcom,qcs404-adsp-pas", .data = &adsp_resource_init },
1193	{ .compatible = "qcom,qcs404-cdsp-pas", .data = &cdsp_resource_init },
1194	{ .compatible = "qcom,qcs404-wcss-pas", .data = &wcss_resource_init },
1195	{ .compatible = "qcom,sc7180-adsp-pas", .data = &sm8250_adsp_resource},
1196	{ .compatible = "qcom,sc7180-mpss-pas", .data = &mpss_resource_init},
1197	{ .compatible = "qcom,sc7280-adsp-pas", .data = &sm8350_adsp_resource},
1198	{ .compatible = "qcom,sc7280-cdsp-pas", .data = &sm6350_cdsp_resource},
1199	{ .compatible = "qcom,sc7280-mpss-pas", .data = &mpss_resource_init},
1200	{ .compatible = "qcom,sc7280-wpss-pas", .data = &sc7280_wpss_resource},
1201	{ .compatible = "qcom,sc8180x-adsp-pas", .data = &sm8150_adsp_resource},
1202	{ .compatible = "qcom,sc8180x-cdsp-pas", .data = &sm8150_cdsp_resource},
1203	{ .compatible = "qcom,sc8180x-mpss-pas", .data = &sc8180x_mpss_resource},
1204	{ .compatible = "qcom,sc8280xp-adsp-pas", .data = &sm8250_adsp_resource},
1205	{ .compatible = "qcom,sc8280xp-nsp0-pas", .data = &sc8280xp_nsp0_resource},
1206	{ .compatible = "qcom,sc8280xp-nsp1-pas", .data = &sc8280xp_nsp1_resource},
1207	{ .compatible = "qcom,sdm660-adsp-pas", .data = &adsp_resource_init},
1208	{ .compatible = "qcom,sdm845-adsp-pas", .data = &sdm845_adsp_resource_init},
1209	{ .compatible = "qcom,sdm845-cdsp-pas", .data = &sdm845_cdsp_resource_init},
1210	{ .compatible = "qcom,sdm845-slpi-pas", .data = &sdm845_slpi_resource_init},
1211	{ .compatible = "qcom,sdx55-mpss-pas", .data = &sdx55_mpss_resource},
1212	{ .compatible = "qcom,sm6115-adsp-pas", .data = &adsp_resource_init},
1213	{ .compatible = "qcom,sm6115-cdsp-pas", .data = &cdsp_resource_init},
1214	{ .compatible = "qcom,sm6115-mpss-pas", .data = &sc8180x_mpss_resource},
1215	{ .compatible = "qcom,sm6350-adsp-pas", .data = &sm6350_adsp_resource},
1216	{ .compatible = "qcom,sm6350-cdsp-pas", .data = &sm6350_cdsp_resource},
1217	{ .compatible = "qcom,sm6350-mpss-pas", .data = &mpss_resource_init},
1218	{ .compatible = "qcom,sm6375-adsp-pas", .data = &sm6350_adsp_resource},
1219	{ .compatible = "qcom,sm6375-cdsp-pas", .data = &sm8150_cdsp_resource},
1220	{ .compatible = "qcom,sm6375-mpss-pas", .data = &sm6375_mpss_resource},
1221	{ .compatible = "qcom,sm8150-adsp-pas", .data = &sm8150_adsp_resource},
1222	{ .compatible = "qcom,sm8150-cdsp-pas", .data = &sm8150_cdsp_resource},
1223	{ .compatible = "qcom,sm8150-mpss-pas", .data = &mpss_resource_init},
1224	{ .compatible = "qcom,sm8150-slpi-pas", .data = &sdm845_slpi_resource_init},
1225	{ .compatible = "qcom,sm8250-adsp-pas", .data = &sm8250_adsp_resource},
1226	{ .compatible = "qcom,sm8250-cdsp-pas", .data = &sm8250_cdsp_resource},
1227	{ .compatible = "qcom,sm8250-slpi-pas", .data = &sdm845_slpi_resource_init},
1228	{ .compatible = "qcom,sm8350-adsp-pas", .data = &sm8350_adsp_resource},
1229	{ .compatible = "qcom,sm8350-cdsp-pas", .data = &sm8350_cdsp_resource},
1230	{ .compatible = "qcom,sm8350-slpi-pas", .data = &sdm845_slpi_resource_init},
1231	{ .compatible = "qcom,sm8350-mpss-pas", .data = &mpss_resource_init},
1232	{ .compatible = "qcom,sm8450-adsp-pas", .data = &sm8350_adsp_resource},
1233	{ .compatible = "qcom,sm8450-cdsp-pas", .data = &sm8350_cdsp_resource},
1234	{ .compatible = "qcom,sm8450-slpi-pas", .data = &sdm845_slpi_resource_init},
1235	{ .compatible = "qcom,sm8450-mpss-pas", .data = &sm8450_mpss_resource},
1236	{ .compatible = "qcom,sm8550-adsp-pas", .data = &sm8550_adsp_resource},
1237	{ .compatible = "qcom,sm8550-cdsp-pas", .data = &sm8550_cdsp_resource},
1238	{ .compatible = "qcom,sm8550-mpss-pas", .data = &sm8550_mpss_resource},
 
 
 
 
 
1239	{ },
1240};
1241MODULE_DEVICE_TABLE(of, adsp_of_match);
1242
1243static struct platform_driver adsp_driver = {
1244	.probe = adsp_probe,
1245	.remove_new = adsp_remove,
1246	.driver = {
1247		.name = "qcom_q6v5_pas",
1248		.of_match_table = adsp_of_match,
1249	},
1250};
1251
1252module_platform_driver(adsp_driver);
1253MODULE_DESCRIPTION("Qualcomm Hexagon v5 Peripheral Authentication Service driver");
1254MODULE_LICENSE("GPL v2");
v6.9.4
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Qualcomm ADSP/SLPI Peripheral Image Loader for MSM8974 and MSM8996
   4 *
   5 * Copyright (C) 2016 Linaro Ltd
   6 * Copyright (C) 2014 Sony Mobile Communications AB
   7 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
   8 */
   9
  10#include <linux/clk.h>
  11#include <linux/delay.h>
  12#include <linux/firmware.h>
  13#include <linux/interrupt.h>
  14#include <linux/kernel.h>
  15#include <linux/module.h>
  16#include <linux/of.h>
  17#include <linux/of_address.h>
  18#include <linux/of_reserved_mem.h>
  19#include <linux/platform_device.h>
  20#include <linux/pm_domain.h>
  21#include <linux/pm_runtime.h>
  22#include <linux/firmware/qcom/qcom_scm.h>
  23#include <linux/regulator/consumer.h>
  24#include <linux/remoteproc.h>
  25#include <linux/soc/qcom/mdt_loader.h>
  26#include <linux/soc/qcom/smem.h>
  27#include <linux/soc/qcom/smem_state.h>
  28
  29#include "qcom_common.h"
  30#include "qcom_pil_info.h"
  31#include "qcom_q6v5.h"
  32#include "remoteproc_internal.h"
  33
  34#define ADSP_DECRYPT_SHUTDOWN_DELAY_MS	100
  35
  36#define MAX_ASSIGN_COUNT 3
  37
  38struct adsp_data {
  39	int crash_reason_smem;
  40	const char *firmware_name;
  41	const char *dtb_firmware_name;
  42	int pas_id;
  43	int dtb_pas_id;
  44	int lite_pas_id;
  45	unsigned int minidump_id;
  46	bool auto_boot;
  47	bool decrypt_shutdown;
  48
  49	char **proxy_pd_names;
  50
  51	const char *load_state;
  52	const char *ssr_name;
  53	const char *sysmon_name;
  54	int ssctl_id;
  55
  56	int region_assign_idx;
  57	int region_assign_count;
  58	bool region_assign_shared;
  59	int region_assign_vmid;
  60};
  61
  62struct qcom_adsp {
  63	struct device *dev;
  64	struct rproc *rproc;
  65
  66	struct qcom_q6v5 q6v5;
  67
  68	struct clk *xo;
  69	struct clk *aggre2_clk;
  70
  71	struct regulator *cx_supply;
  72	struct regulator *px_supply;
  73
  74	struct device *proxy_pds[3];
  75
  76	int proxy_pd_count;
  77
  78	const char *dtb_firmware_name;
  79	int pas_id;
  80	int dtb_pas_id;
  81	int lite_pas_id;
  82	unsigned int minidump_id;
  83	int crash_reason_smem;
  84	bool decrypt_shutdown;
  85	const char *info_name;
  86
  87	const struct firmware *firmware;
  88	const struct firmware *dtb_firmware;
  89
  90	struct completion start_done;
  91	struct completion stop_done;
  92
  93	phys_addr_t mem_phys;
  94	phys_addr_t dtb_mem_phys;
  95	phys_addr_t mem_reloc;
  96	phys_addr_t dtb_mem_reloc;
  97	phys_addr_t region_assign_phys[MAX_ASSIGN_COUNT];
  98	void *mem_region;
  99	void *dtb_mem_region;
 100	size_t mem_size;
 101	size_t dtb_mem_size;
 102	size_t region_assign_size[MAX_ASSIGN_COUNT];
 103
 104	int region_assign_idx;
 105	int region_assign_count;
 106	bool region_assign_shared;
 107	int region_assign_vmid;
 108	u64 region_assign_owners[MAX_ASSIGN_COUNT];
 109
 110	struct qcom_rproc_glink glink_subdev;
 111	struct qcom_rproc_subdev smd_subdev;
 112	struct qcom_rproc_ssr ssr_subdev;
 113	struct qcom_sysmon *sysmon;
 114
 115	struct qcom_scm_pas_metadata pas_metadata;
 116	struct qcom_scm_pas_metadata dtb_pas_metadata;
 117};
 118
 119static void adsp_segment_dump(struct rproc *rproc, struct rproc_dump_segment *segment,
 120		       void *dest, size_t offset, size_t size)
 121{
 122	struct qcom_adsp *adsp = rproc->priv;
 123	int total_offset;
 124
 125	total_offset = segment->da + segment->offset + offset - adsp->mem_phys;
 126	if (total_offset < 0 || total_offset + size > adsp->mem_size) {
 127		dev_err(adsp->dev,
 128			"invalid copy request for segment %pad with offset %zu and size %zu)\n",
 129			&segment->da, offset, size);
 130		memset(dest, 0xff, size);
 131		return;
 132	}
 133
 134	memcpy_fromio(dest, adsp->mem_region + total_offset, size);
 135}
 136
 137static void adsp_minidump(struct rproc *rproc)
 138{
 139	struct qcom_adsp *adsp = rproc->priv;
 140
 141	if (rproc->dump_conf == RPROC_COREDUMP_DISABLED)
 142		return;
 143
 144	qcom_minidump(rproc, adsp->minidump_id, adsp_segment_dump);
 145}
 146
 147static int adsp_pds_enable(struct qcom_adsp *adsp, struct device **pds,
 148			   size_t pd_count)
 149{
 150	int ret;
 151	int i;
 152
 153	for (i = 0; i < pd_count; i++) {
 154		dev_pm_genpd_set_performance_state(pds[i], INT_MAX);
 155		ret = pm_runtime_get_sync(pds[i]);
 156		if (ret < 0) {
 157			pm_runtime_put_noidle(pds[i]);
 158			dev_pm_genpd_set_performance_state(pds[i], 0);
 159			goto unroll_pd_votes;
 160		}
 161	}
 162
 163	return 0;
 164
 165unroll_pd_votes:
 166	for (i--; i >= 0; i--) {
 167		dev_pm_genpd_set_performance_state(pds[i], 0);
 168		pm_runtime_put(pds[i]);
 169	}
 170
 171	return ret;
 172};
 173
 174static void adsp_pds_disable(struct qcom_adsp *adsp, struct device **pds,
 175			     size_t pd_count)
 176{
 177	int i;
 178
 179	for (i = 0; i < pd_count; i++) {
 180		dev_pm_genpd_set_performance_state(pds[i], 0);
 181		pm_runtime_put(pds[i]);
 182	}
 183}
 184
 185static int adsp_shutdown_poll_decrypt(struct qcom_adsp *adsp)
 186{
 187	unsigned int retry_num = 50;
 188	int ret;
 189
 190	do {
 191		msleep(ADSP_DECRYPT_SHUTDOWN_DELAY_MS);
 192		ret = qcom_scm_pas_shutdown(adsp->pas_id);
 193	} while (ret == -EINVAL && --retry_num);
 194
 195	return ret;
 196}
 197
 198static int adsp_unprepare(struct rproc *rproc)
 199{
 200	struct qcom_adsp *adsp = rproc->priv;
 201
 202	/*
 203	 * adsp_load() did pass pas_metadata to the SCM driver for storing
 204	 * metadata context. It might have been released already if
 205	 * auth_and_reset() was successful, but in other cases clean it up
 206	 * here.
 207	 */
 208	qcom_scm_pas_metadata_release(&adsp->pas_metadata);
 209	if (adsp->dtb_pas_id)
 210		qcom_scm_pas_metadata_release(&adsp->dtb_pas_metadata);
 211
 212	return 0;
 213}
 214
 215static int adsp_load(struct rproc *rproc, const struct firmware *fw)
 216{
 217	struct qcom_adsp *adsp = rproc->priv;
 218	int ret;
 219
 220	/* Store firmware handle to be used in adsp_start() */
 221	adsp->firmware = fw;
 222
 223	if (adsp->lite_pas_id)
 224		ret = qcom_scm_pas_shutdown(adsp->lite_pas_id);
 225
 226	if (adsp->dtb_pas_id) {
 227		ret = request_firmware(&adsp->dtb_firmware, adsp->dtb_firmware_name, adsp->dev);
 228		if (ret) {
 229			dev_err(adsp->dev, "request_firmware failed for %s: %d\n",
 230				adsp->dtb_firmware_name, ret);
 231			return ret;
 232		}
 233
 234		ret = qcom_mdt_pas_init(adsp->dev, adsp->dtb_firmware, adsp->dtb_firmware_name,
 235					adsp->dtb_pas_id, adsp->dtb_mem_phys,
 236					&adsp->dtb_pas_metadata);
 237		if (ret)
 238			goto release_dtb_firmware;
 239
 240		ret = qcom_mdt_load_no_init(adsp->dev, adsp->dtb_firmware, adsp->dtb_firmware_name,
 241					    adsp->dtb_pas_id, adsp->dtb_mem_region,
 242					    adsp->dtb_mem_phys, adsp->dtb_mem_size,
 243					    &adsp->dtb_mem_reloc);
 244		if (ret)
 245			goto release_dtb_metadata;
 246	}
 247
 248	return 0;
 249
 250release_dtb_metadata:
 251	qcom_scm_pas_metadata_release(&adsp->dtb_pas_metadata);
 252
 253release_dtb_firmware:
 254	release_firmware(adsp->dtb_firmware);
 255
 256	return ret;
 257}
 258
 259static int adsp_start(struct rproc *rproc)
 260{
 261	struct qcom_adsp *adsp = rproc->priv;
 262	int ret;
 263
 264	ret = qcom_q6v5_prepare(&adsp->q6v5);
 265	if (ret)
 266		return ret;
 267
 268	ret = adsp_pds_enable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
 269	if (ret < 0)
 270		goto disable_irqs;
 271
 272	ret = clk_prepare_enable(adsp->xo);
 273	if (ret)
 274		goto disable_proxy_pds;
 275
 276	ret = clk_prepare_enable(adsp->aggre2_clk);
 277	if (ret)
 278		goto disable_xo_clk;
 279
 280	if (adsp->cx_supply) {
 281		ret = regulator_enable(adsp->cx_supply);
 282		if (ret)
 283			goto disable_aggre2_clk;
 284	}
 285
 286	if (adsp->px_supply) {
 287		ret = regulator_enable(adsp->px_supply);
 288		if (ret)
 289			goto disable_cx_supply;
 290	}
 291
 292	if (adsp->dtb_pas_id) {
 293		ret = qcom_scm_pas_auth_and_reset(adsp->dtb_pas_id);
 294		if (ret) {
 295			dev_err(adsp->dev,
 296				"failed to authenticate dtb image and release reset\n");
 297			goto disable_px_supply;
 298		}
 299	}
 300
 301	ret = qcom_mdt_pas_init(adsp->dev, adsp->firmware, rproc->firmware, adsp->pas_id,
 302				adsp->mem_phys, &adsp->pas_metadata);
 303	if (ret)
 304		goto disable_px_supply;
 305
 306	ret = qcom_mdt_load_no_init(adsp->dev, adsp->firmware, rproc->firmware, adsp->pas_id,
 307				    adsp->mem_region, adsp->mem_phys, adsp->mem_size,
 308				    &adsp->mem_reloc);
 309	if (ret)
 310		goto release_pas_metadata;
 311
 312	qcom_pil_info_store(adsp->info_name, adsp->mem_phys, adsp->mem_size);
 313
 314	ret = qcom_scm_pas_auth_and_reset(adsp->pas_id);
 315	if (ret) {
 316		dev_err(adsp->dev,
 317			"failed to authenticate image and release reset\n");
 318		goto release_pas_metadata;
 319	}
 320
 321	ret = qcom_q6v5_wait_for_start(&adsp->q6v5, msecs_to_jiffies(5000));
 322	if (ret == -ETIMEDOUT) {
 323		dev_err(adsp->dev, "start timed out\n");
 324		qcom_scm_pas_shutdown(adsp->pas_id);
 325		goto release_pas_metadata;
 326	}
 327
 328	qcom_scm_pas_metadata_release(&adsp->pas_metadata);
 329	if (adsp->dtb_pas_id)
 330		qcom_scm_pas_metadata_release(&adsp->dtb_pas_metadata);
 331
 332	/* Remove pointer to the loaded firmware, only valid in adsp_load() & adsp_start() */
 333	adsp->firmware = NULL;
 334
 335	return 0;
 336
 337release_pas_metadata:
 338	qcom_scm_pas_metadata_release(&adsp->pas_metadata);
 339	if (adsp->dtb_pas_id)
 340		qcom_scm_pas_metadata_release(&adsp->dtb_pas_metadata);
 341disable_px_supply:
 342	if (adsp->px_supply)
 343		regulator_disable(adsp->px_supply);
 344disable_cx_supply:
 345	if (adsp->cx_supply)
 346		regulator_disable(adsp->cx_supply);
 347disable_aggre2_clk:
 348	clk_disable_unprepare(adsp->aggre2_clk);
 349disable_xo_clk:
 350	clk_disable_unprepare(adsp->xo);
 351disable_proxy_pds:
 352	adsp_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
 353disable_irqs:
 354	qcom_q6v5_unprepare(&adsp->q6v5);
 355
 356	/* Remove pointer to the loaded firmware, only valid in adsp_load() & adsp_start() */
 357	adsp->firmware = NULL;
 358
 359	return ret;
 360}
 361
 362static void qcom_pas_handover(struct qcom_q6v5 *q6v5)
 363{
 364	struct qcom_adsp *adsp = container_of(q6v5, struct qcom_adsp, q6v5);
 365
 366	if (adsp->px_supply)
 367		regulator_disable(adsp->px_supply);
 368	if (adsp->cx_supply)
 369		regulator_disable(adsp->cx_supply);
 370	clk_disable_unprepare(adsp->aggre2_clk);
 371	clk_disable_unprepare(adsp->xo);
 372	adsp_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
 373}
 374
 375static int adsp_stop(struct rproc *rproc)
 376{
 377	struct qcom_adsp *adsp = rproc->priv;
 378	int handover;
 379	int ret;
 380
 381	ret = qcom_q6v5_request_stop(&adsp->q6v5, adsp->sysmon);
 382	if (ret == -ETIMEDOUT)
 383		dev_err(adsp->dev, "timed out on wait\n");
 384
 385	ret = qcom_scm_pas_shutdown(adsp->pas_id);
 386	if (ret && adsp->decrypt_shutdown)
 387		ret = adsp_shutdown_poll_decrypt(adsp);
 388
 389	if (ret)
 390		dev_err(adsp->dev, "failed to shutdown: %d\n", ret);
 391
 392	if (adsp->dtb_pas_id) {
 393		ret = qcom_scm_pas_shutdown(adsp->dtb_pas_id);
 394		if (ret)
 395			dev_err(adsp->dev, "failed to shutdown dtb: %d\n", ret);
 396	}
 397
 398	handover = qcom_q6v5_unprepare(&adsp->q6v5);
 399	if (handover)
 400		qcom_pas_handover(&adsp->q6v5);
 401
 402	return ret;
 403}
 404
 405static void *adsp_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 406{
 407	struct qcom_adsp *adsp = rproc->priv;
 408	int offset;
 409
 410	offset = da - adsp->mem_reloc;
 411	if (offset < 0 || offset + len > adsp->mem_size)
 412		return NULL;
 413
 414	if (is_iomem)
 415		*is_iomem = true;
 416
 417	return adsp->mem_region + offset;
 418}
 419
 420static unsigned long adsp_panic(struct rproc *rproc)
 421{
 422	struct qcom_adsp *adsp = rproc->priv;
 423
 424	return qcom_q6v5_panic(&adsp->q6v5);
 425}
 426
 427static const struct rproc_ops adsp_ops = {
 428	.unprepare = adsp_unprepare,
 429	.start = adsp_start,
 430	.stop = adsp_stop,
 431	.da_to_va = adsp_da_to_va,
 432	.parse_fw = qcom_register_dump_segments,
 433	.load = adsp_load,
 434	.panic = adsp_panic,
 435};
 436
 437static const struct rproc_ops adsp_minidump_ops = {
 438	.unprepare = adsp_unprepare,
 439	.start = adsp_start,
 440	.stop = adsp_stop,
 441	.da_to_va = adsp_da_to_va,
 442	.parse_fw = qcom_register_dump_segments,
 443	.load = adsp_load,
 444	.panic = adsp_panic,
 445	.coredump = adsp_minidump,
 446};
 447
 448static int adsp_init_clock(struct qcom_adsp *adsp)
 449{
 450	int ret;
 451
 452	adsp->xo = devm_clk_get(adsp->dev, "xo");
 453	if (IS_ERR(adsp->xo)) {
 454		ret = PTR_ERR(adsp->xo);
 455		if (ret != -EPROBE_DEFER)
 456			dev_err(adsp->dev, "failed to get xo clock");
 457		return ret;
 458	}
 459
 460	adsp->aggre2_clk = devm_clk_get_optional(adsp->dev, "aggre2");
 461	if (IS_ERR(adsp->aggre2_clk)) {
 462		ret = PTR_ERR(adsp->aggre2_clk);
 463		if (ret != -EPROBE_DEFER)
 464			dev_err(adsp->dev,
 465				"failed to get aggre2 clock");
 466		return ret;
 467	}
 468
 469	return 0;
 470}
 471
 472static int adsp_init_regulator(struct qcom_adsp *adsp)
 473{
 474	adsp->cx_supply = devm_regulator_get_optional(adsp->dev, "cx");
 475	if (IS_ERR(adsp->cx_supply)) {
 476		if (PTR_ERR(adsp->cx_supply) == -ENODEV)
 477			adsp->cx_supply = NULL;
 478		else
 479			return PTR_ERR(adsp->cx_supply);
 480	}
 481
 482	if (adsp->cx_supply)
 483		regulator_set_load(adsp->cx_supply, 100000);
 484
 485	adsp->px_supply = devm_regulator_get_optional(adsp->dev, "px");
 486	if (IS_ERR(adsp->px_supply)) {
 487		if (PTR_ERR(adsp->px_supply) == -ENODEV)
 488			adsp->px_supply = NULL;
 489		else
 490			return PTR_ERR(adsp->px_supply);
 491	}
 492
 493	return 0;
 494}
 495
 496static int adsp_pds_attach(struct device *dev, struct device **devs,
 497			   char **pd_names)
 498{
 499	size_t num_pds = 0;
 500	int ret;
 501	int i;
 502
 503	if (!pd_names)
 504		return 0;
 505
 506	/* Handle single power domain */
 507	if (dev->pm_domain) {
 508		devs[0] = dev;
 509		pm_runtime_enable(dev);
 510		return 1;
 511	}
 512
 513	while (pd_names[num_pds])
 514		num_pds++;
 515
 516	for (i = 0; i < num_pds; i++) {
 517		devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]);
 518		if (IS_ERR_OR_NULL(devs[i])) {
 519			ret = PTR_ERR(devs[i]) ? : -ENODATA;
 520			goto unroll_attach;
 521		}
 522	}
 523
 524	return num_pds;
 525
 526unroll_attach:
 527	for (i--; i >= 0; i--)
 528		dev_pm_domain_detach(devs[i], false);
 529
 530	return ret;
 531};
 532
 533static void adsp_pds_detach(struct qcom_adsp *adsp, struct device **pds,
 534			    size_t pd_count)
 535{
 536	struct device *dev = adsp->dev;
 537	int i;
 538
 539	/* Handle single power domain */
 540	if (dev->pm_domain && pd_count) {
 541		pm_runtime_disable(dev);
 542		return;
 543	}
 544
 545	for (i = 0; i < pd_count; i++)
 546		dev_pm_domain_detach(pds[i], false);
 547}
 548
 549static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
 550{
 551	struct reserved_mem *rmem;
 552	struct device_node *node;
 553
 554	node = of_parse_phandle(adsp->dev->of_node, "memory-region", 0);
 555	if (!node) {
 556		dev_err(adsp->dev, "no memory-region specified\n");
 557		return -EINVAL;
 558	}
 559
 560	rmem = of_reserved_mem_lookup(node);
 561	of_node_put(node);
 562	if (!rmem) {
 563		dev_err(adsp->dev, "unable to resolve memory-region\n");
 564		return -EINVAL;
 565	}
 566
 567	adsp->mem_phys = adsp->mem_reloc = rmem->base;
 568	adsp->mem_size = rmem->size;
 569	adsp->mem_region = devm_ioremap_wc(adsp->dev, adsp->mem_phys, adsp->mem_size);
 570	if (!adsp->mem_region) {
 571		dev_err(adsp->dev, "unable to map memory region: %pa+%zx\n",
 572			&rmem->base, adsp->mem_size);
 573		return -EBUSY;
 574	}
 575
 576	if (!adsp->dtb_pas_id)
 577		return 0;
 578
 579	node = of_parse_phandle(adsp->dev->of_node, "memory-region", 1);
 580	if (!node) {
 581		dev_err(adsp->dev, "no dtb memory-region specified\n");
 582		return -EINVAL;
 583	}
 584
 585	rmem = of_reserved_mem_lookup(node);
 586	of_node_put(node);
 587	if (!rmem) {
 588		dev_err(adsp->dev, "unable to resolve dtb memory-region\n");
 589		return -EINVAL;
 590	}
 591
 592	adsp->dtb_mem_phys = adsp->dtb_mem_reloc = rmem->base;
 593	adsp->dtb_mem_size = rmem->size;
 594	adsp->dtb_mem_region = devm_ioremap_wc(adsp->dev, adsp->dtb_mem_phys, adsp->dtb_mem_size);
 595	if (!adsp->dtb_mem_region) {
 596		dev_err(adsp->dev, "unable to map dtb memory region: %pa+%zx\n",
 597			&rmem->base, adsp->dtb_mem_size);
 598		return -EBUSY;
 599	}
 600
 601	return 0;
 602}
 603
 604static int adsp_assign_memory_region(struct qcom_adsp *adsp)
 605{
 606	struct qcom_scm_vmperm perm[MAX_ASSIGN_COUNT];
 
 607	struct device_node *node;
 608	unsigned int perm_size;
 609	int offset;
 610	int ret;
 611
 612	if (!adsp->region_assign_idx)
 613		return 0;
 614
 615	for (offset = 0; offset < adsp->region_assign_count; ++offset) {
 616		struct reserved_mem *rmem = NULL;
 
 
 
 
 
 
 617
 618		node = of_parse_phandle(adsp->dev->of_node, "memory-region",
 619					adsp->region_assign_idx + offset);
 620		if (node)
 621			rmem = of_reserved_mem_lookup(node);
 622		of_node_put(node);
 623		if (!rmem) {
 624			dev_err(adsp->dev, "unable to resolve shareable memory-region index %d\n",
 625				offset);
 626			return -EINVAL;
 627		}
 628
 629		if (adsp->region_assign_shared)  {
 630			perm[0].vmid = QCOM_SCM_VMID_HLOS;
 631			perm[0].perm = QCOM_SCM_PERM_RW;
 632			perm[1].vmid = adsp->region_assign_vmid;
 633			perm[1].perm = QCOM_SCM_PERM_RW;
 634			perm_size = 2;
 635		} else {
 636			perm[0].vmid = adsp->region_assign_vmid;
 637			perm[0].perm = QCOM_SCM_PERM_RW;
 638			perm_size = 1;
 639		}
 640
 641		adsp->region_assign_phys[offset] = rmem->base;
 642		adsp->region_assign_size[offset] = rmem->size;
 643		adsp->region_assign_owners[offset] = BIT(QCOM_SCM_VMID_HLOS);
 644
 645		ret = qcom_scm_assign_mem(adsp->region_assign_phys[offset],
 646					  adsp->region_assign_size[offset],
 647					  &adsp->region_assign_owners[offset],
 648					  perm, perm_size);
 649		if (ret < 0) {
 650			dev_err(adsp->dev, "assign memory %d failed\n", offset);
 651			return ret;
 652		}
 653	}
 654
 655	return 0;
 656}
 657
 658static void adsp_unassign_memory_region(struct qcom_adsp *adsp)
 659{
 660	struct qcom_scm_vmperm perm;
 661	int offset;
 662	int ret;
 663
 664	if (!adsp->region_assign_idx || adsp->region_assign_shared)
 665		return;
 666
 667	for (offset = 0; offset < adsp->region_assign_count; ++offset) {
 668		perm.vmid = QCOM_SCM_VMID_HLOS;
 669		perm.perm = QCOM_SCM_PERM_RW;
 670
 671		ret = qcom_scm_assign_mem(adsp->region_assign_phys[offset],
 672					  adsp->region_assign_size[offset],
 673					  &adsp->region_assign_owners[offset],
 674					  &perm, 1);
 675		if (ret < 0)
 676			dev_err(adsp->dev, "unassign memory %d failed\n", offset);
 677	}
 678}
 679
 680static int adsp_probe(struct platform_device *pdev)
 681{
 682	const struct adsp_data *desc;
 683	struct qcom_adsp *adsp;
 684	struct rproc *rproc;
 685	const char *fw_name, *dtb_fw_name = NULL;
 686	const struct rproc_ops *ops = &adsp_ops;
 687	int ret;
 688
 689	desc = of_device_get_match_data(&pdev->dev);
 690	if (!desc)
 691		return -EINVAL;
 692
 693	if (!qcom_scm_is_available())
 694		return -EPROBE_DEFER;
 695
 696	fw_name = desc->firmware_name;
 697	ret = of_property_read_string(pdev->dev.of_node, "firmware-name",
 698				      &fw_name);
 699	if (ret < 0 && ret != -EINVAL)
 700		return ret;
 701
 702	if (desc->dtb_firmware_name) {
 703		dtb_fw_name = desc->dtb_firmware_name;
 704		ret = of_property_read_string_index(pdev->dev.of_node, "firmware-name", 1,
 705						    &dtb_fw_name);
 706		if (ret < 0 && ret != -EINVAL)
 707			return ret;
 708	}
 709
 710	if (desc->minidump_id)
 711		ops = &adsp_minidump_ops;
 712
 713	rproc = devm_rproc_alloc(&pdev->dev, pdev->name, ops, fw_name, sizeof(*adsp));
 714
 715	if (!rproc) {
 716		dev_err(&pdev->dev, "unable to allocate remoteproc\n");
 717		return -ENOMEM;
 718	}
 719
 720	rproc->auto_boot = desc->auto_boot;
 721	rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);
 722
 723	adsp = rproc->priv;
 724	adsp->dev = &pdev->dev;
 725	adsp->rproc = rproc;
 726	adsp->minidump_id = desc->minidump_id;
 727	adsp->pas_id = desc->pas_id;
 728	adsp->lite_pas_id = desc->lite_pas_id;
 729	adsp->info_name = desc->sysmon_name;
 730	adsp->decrypt_shutdown = desc->decrypt_shutdown;
 731	adsp->region_assign_idx = desc->region_assign_idx;
 732	adsp->region_assign_count = min_t(int, MAX_ASSIGN_COUNT, desc->region_assign_count);
 733	adsp->region_assign_vmid = desc->region_assign_vmid;
 734	adsp->region_assign_shared = desc->region_assign_shared;
 735	if (dtb_fw_name) {
 736		adsp->dtb_firmware_name = dtb_fw_name;
 737		adsp->dtb_pas_id = desc->dtb_pas_id;
 738	}
 739	platform_set_drvdata(pdev, adsp);
 740
 741	ret = device_init_wakeup(adsp->dev, true);
 742	if (ret)
 743		goto free_rproc;
 744
 745	ret = adsp_alloc_memory_region(adsp);
 746	if (ret)
 747		goto free_rproc;
 748
 749	ret = adsp_assign_memory_region(adsp);
 750	if (ret)
 751		goto free_rproc;
 752
 753	ret = adsp_init_clock(adsp);
 754	if (ret)
 755		goto free_rproc;
 756
 757	ret = adsp_init_regulator(adsp);
 758	if (ret)
 759		goto free_rproc;
 760
 761	ret = adsp_pds_attach(&pdev->dev, adsp->proxy_pds,
 762			      desc->proxy_pd_names);
 763	if (ret < 0)
 764		goto free_rproc;
 765	adsp->proxy_pd_count = ret;
 766
 767	ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem, desc->load_state,
 768			     qcom_pas_handover);
 769	if (ret)
 770		goto detach_proxy_pds;
 771
 772	qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
 773	qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
 774	adsp->sysmon = qcom_add_sysmon_subdev(rproc,
 775					      desc->sysmon_name,
 776					      desc->ssctl_id);
 777	if (IS_ERR(adsp->sysmon)) {
 778		ret = PTR_ERR(adsp->sysmon);
 779		goto detach_proxy_pds;
 780	}
 781
 782	qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
 783	ret = rproc_add(rproc);
 784	if (ret)
 785		goto detach_proxy_pds;
 786
 787	return 0;
 788
 789detach_proxy_pds:
 790	adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
 791free_rproc:
 792	device_init_wakeup(adsp->dev, false);
 
 793
 794	return ret;
 795}
 796
 797static void adsp_remove(struct platform_device *pdev)
 798{
 799	struct qcom_adsp *adsp = platform_get_drvdata(pdev);
 800
 801	rproc_del(adsp->rproc);
 802
 803	qcom_q6v5_deinit(&adsp->q6v5);
 804	adsp_unassign_memory_region(adsp);
 805	qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
 806	qcom_remove_sysmon_subdev(adsp->sysmon);
 807	qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
 808	qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
 809	adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
 810	device_init_wakeup(adsp->dev, false);
 
 811}
 812
 813static const struct adsp_data adsp_resource_init = {
 814	.crash_reason_smem = 423,
 815	.firmware_name = "adsp.mdt",
 816	.pas_id = 1,
 817	.auto_boot = true,
 818	.ssr_name = "lpass",
 819	.sysmon_name = "adsp",
 820	.ssctl_id = 0x14,
 821};
 822
 823static const struct adsp_data sdm845_adsp_resource_init = {
 824	.crash_reason_smem = 423,
 825	.firmware_name = "adsp.mdt",
 826	.pas_id = 1,
 827	.auto_boot = true,
 828	.load_state = "adsp",
 829	.ssr_name = "lpass",
 830	.sysmon_name = "adsp",
 831	.ssctl_id = 0x14,
 832};
 833
 834static const struct adsp_data sm6350_adsp_resource = {
 835	.crash_reason_smem = 423,
 836	.firmware_name = "adsp.mdt",
 837	.pas_id = 1,
 838	.auto_boot = true,
 839	.proxy_pd_names = (char*[]){
 840		"lcx",
 841		"lmx",
 842		NULL
 843	},
 844	.load_state = "adsp",
 845	.ssr_name = "lpass",
 846	.sysmon_name = "adsp",
 847	.ssctl_id = 0x14,
 848};
 849
 850static const struct adsp_data sm6375_mpss_resource = {
 851	.crash_reason_smem = 421,
 852	.firmware_name = "modem.mdt",
 853	.pas_id = 4,
 854	.minidump_id = 3,
 855	.auto_boot = false,
 856	.proxy_pd_names = (char*[]){
 857		"cx",
 858		NULL
 859	},
 860	.ssr_name = "mpss",
 861	.sysmon_name = "modem",
 862	.ssctl_id = 0x12,
 863};
 864
 865static const struct adsp_data sm8150_adsp_resource = {
 866	.crash_reason_smem = 423,
 867	.firmware_name = "adsp.mdt",
 868	.pas_id = 1,
 869	.auto_boot = true,
 870	.proxy_pd_names = (char*[]){
 871		"cx",
 872		NULL
 873	},
 874	.load_state = "adsp",
 875	.ssr_name = "lpass",
 876	.sysmon_name = "adsp",
 877	.ssctl_id = 0x14,
 878};
 879
 880static const struct adsp_data sm8250_adsp_resource = {
 881	.crash_reason_smem = 423,
 882	.firmware_name = "adsp.mdt",
 883	.pas_id = 1,
 884	.auto_boot = true,
 885	.proxy_pd_names = (char*[]){
 886		"lcx",
 887		"lmx",
 888		NULL
 889	},
 890	.load_state = "adsp",
 891	.ssr_name = "lpass",
 892	.sysmon_name = "adsp",
 893	.ssctl_id = 0x14,
 894};
 895
 896static const struct adsp_data sm8350_adsp_resource = {
 897	.crash_reason_smem = 423,
 898	.firmware_name = "adsp.mdt",
 899	.pas_id = 1,
 900	.auto_boot = true,
 901	.proxy_pd_names = (char*[]){
 902		"lcx",
 903		"lmx",
 904		NULL
 905	},
 906	.load_state = "adsp",
 907	.ssr_name = "lpass",
 908	.sysmon_name = "adsp",
 909	.ssctl_id = 0x14,
 910};
 911
 912static const struct adsp_data msm8996_adsp_resource = {
 913	.crash_reason_smem = 423,
 914	.firmware_name = "adsp.mdt",
 915	.pas_id = 1,
 916	.auto_boot = true,
 917	.proxy_pd_names = (char*[]){
 918		"cx",
 919		NULL
 920	},
 921	.ssr_name = "lpass",
 922	.sysmon_name = "adsp",
 923	.ssctl_id = 0x14,
 924};
 925
 926static const struct adsp_data cdsp_resource_init = {
 927	.crash_reason_smem = 601,
 928	.firmware_name = "cdsp.mdt",
 929	.pas_id = 18,
 930	.auto_boot = true,
 931	.ssr_name = "cdsp",
 932	.sysmon_name = "cdsp",
 933	.ssctl_id = 0x17,
 934};
 935
 936static const struct adsp_data sdm845_cdsp_resource_init = {
 937	.crash_reason_smem = 601,
 938	.firmware_name = "cdsp.mdt",
 939	.pas_id = 18,
 940	.auto_boot = true,
 941	.load_state = "cdsp",
 942	.ssr_name = "cdsp",
 943	.sysmon_name = "cdsp",
 944	.ssctl_id = 0x17,
 945};
 946
 947static const struct adsp_data sm6350_cdsp_resource = {
 948	.crash_reason_smem = 601,
 949	.firmware_name = "cdsp.mdt",
 950	.pas_id = 18,
 951	.auto_boot = true,
 952	.proxy_pd_names = (char*[]){
 953		"cx",
 954		"mx",
 955		NULL
 956	},
 957	.load_state = "cdsp",
 958	.ssr_name = "cdsp",
 959	.sysmon_name = "cdsp",
 960	.ssctl_id = 0x17,
 961};
 962
 963static const struct adsp_data sm8150_cdsp_resource = {
 964	.crash_reason_smem = 601,
 965	.firmware_name = "cdsp.mdt",
 966	.pas_id = 18,
 967	.auto_boot = true,
 968	.proxy_pd_names = (char*[]){
 969		"cx",
 970		NULL
 971	},
 972	.load_state = "cdsp",
 973	.ssr_name = "cdsp",
 974	.sysmon_name = "cdsp",
 975	.ssctl_id = 0x17,
 976};
 977
 978static const struct adsp_data sm8250_cdsp_resource = {
 979	.crash_reason_smem = 601,
 980	.firmware_name = "cdsp.mdt",
 981	.pas_id = 18,
 982	.auto_boot = true,
 983	.proxy_pd_names = (char*[]){
 984		"cx",
 985		NULL
 986	},
 987	.load_state = "cdsp",
 988	.ssr_name = "cdsp",
 989	.sysmon_name = "cdsp",
 990	.ssctl_id = 0x17,
 991};
 992
 993static const struct adsp_data sc8280xp_nsp0_resource = {
 994	.crash_reason_smem = 601,
 995	.firmware_name = "cdsp.mdt",
 996	.pas_id = 18,
 997	.auto_boot = true,
 998	.proxy_pd_names = (char*[]){
 999		"nsp",
1000		NULL
1001	},
1002	.ssr_name = "cdsp0",
1003	.sysmon_name = "cdsp",
1004	.ssctl_id = 0x17,
1005};
1006
1007static const struct adsp_data sc8280xp_nsp1_resource = {
1008	.crash_reason_smem = 633,
1009	.firmware_name = "cdsp.mdt",
1010	.pas_id = 30,
1011	.auto_boot = true,
1012	.proxy_pd_names = (char*[]){
1013		"nsp",
1014		NULL
1015	},
1016	.ssr_name = "cdsp1",
1017	.sysmon_name = "cdsp1",
1018	.ssctl_id = 0x20,
1019};
1020
1021static const struct adsp_data x1e80100_adsp_resource = {
1022	.crash_reason_smem = 423,
1023	.firmware_name = "adsp.mdt",
1024	.dtb_firmware_name = "adsp_dtb.mdt",
1025	.pas_id = 1,
1026	.dtb_pas_id = 0x24,
1027	.lite_pas_id = 0x1f,
1028	.minidump_id = 5,
1029	.auto_boot = true,
1030	.proxy_pd_names = (char*[]){
1031		"lcx",
1032		"lmx",
1033		NULL
1034	},
1035	.load_state = "adsp",
1036	.ssr_name = "lpass",
1037	.sysmon_name = "adsp",
1038	.ssctl_id = 0x14,
1039};
1040
1041static const struct adsp_data x1e80100_cdsp_resource = {
1042	.crash_reason_smem = 601,
1043	.firmware_name = "cdsp.mdt",
1044	.dtb_firmware_name = "cdsp_dtb.mdt",
1045	.pas_id = 18,
1046	.dtb_pas_id = 0x25,
1047	.minidump_id = 7,
1048	.auto_boot = true,
1049	.proxy_pd_names = (char*[]){
1050		"cx",
1051		"mxc",
1052		"nsp",
1053		NULL
1054	},
1055	.load_state = "cdsp",
1056	.ssr_name = "cdsp",
1057	.sysmon_name = "cdsp",
1058	.ssctl_id = 0x17,
1059};
1060
1061static const struct adsp_data sm8350_cdsp_resource = {
1062	.crash_reason_smem = 601,
1063	.firmware_name = "cdsp.mdt",
1064	.pas_id = 18,
1065	.auto_boot = true,
1066	.proxy_pd_names = (char*[]){
1067		"cx",
1068		"mxc",
1069		NULL
1070	},
1071	.load_state = "cdsp",
1072	.ssr_name = "cdsp",
1073	.sysmon_name = "cdsp",
1074	.ssctl_id = 0x17,
1075};
1076
1077static const struct adsp_data mpss_resource_init = {
1078	.crash_reason_smem = 421,
1079	.firmware_name = "modem.mdt",
1080	.pas_id = 4,
1081	.minidump_id = 3,
1082	.auto_boot = false,
1083	.proxy_pd_names = (char*[]){
1084		"cx",
1085		"mss",
1086		NULL
1087	},
1088	.load_state = "modem",
1089	.ssr_name = "mpss",
1090	.sysmon_name = "modem",
1091	.ssctl_id = 0x12,
1092};
1093
1094static const struct adsp_data sc8180x_mpss_resource = {
1095	.crash_reason_smem = 421,
1096	.firmware_name = "modem.mdt",
1097	.pas_id = 4,
1098	.auto_boot = false,
1099	.proxy_pd_names = (char*[]){
1100		"cx",
1101		NULL
1102	},
1103	.load_state = "modem",
1104	.ssr_name = "mpss",
1105	.sysmon_name = "modem",
1106	.ssctl_id = 0x12,
1107};
1108
1109static const struct adsp_data msm8996_slpi_resource_init = {
1110	.crash_reason_smem = 424,
1111	.firmware_name = "slpi.mdt",
1112	.pas_id = 12,
1113	.auto_boot = true,
1114	.proxy_pd_names = (char*[]){
1115		"ssc_cx",
1116		NULL
1117	},
1118	.ssr_name = "dsps",
1119	.sysmon_name = "slpi",
1120	.ssctl_id = 0x16,
1121};
1122
1123static const struct adsp_data sdm845_slpi_resource_init = {
1124	.crash_reason_smem = 424,
1125	.firmware_name = "slpi.mdt",
1126	.pas_id = 12,
1127	.auto_boot = true,
1128	.proxy_pd_names = (char*[]){
1129		"lcx",
1130		"lmx",
1131		NULL
1132	},
1133	.load_state = "slpi",
1134	.ssr_name = "dsps",
1135	.sysmon_name = "slpi",
1136	.ssctl_id = 0x16,
1137};
1138
1139static const struct adsp_data wcss_resource_init = {
1140	.crash_reason_smem = 421,
1141	.firmware_name = "wcnss.mdt",
1142	.pas_id = 6,
1143	.auto_boot = true,
1144	.ssr_name = "mpss",
1145	.sysmon_name = "wcnss",
1146	.ssctl_id = 0x12,
1147};
1148
1149static const struct adsp_data sdx55_mpss_resource = {
1150	.crash_reason_smem = 421,
1151	.firmware_name = "modem.mdt",
1152	.pas_id = 4,
1153	.auto_boot = true,
1154	.proxy_pd_names = (char*[]){
1155		"cx",
1156		"mss",
1157		NULL
1158	},
1159	.ssr_name = "mpss",
1160	.sysmon_name = "modem",
1161	.ssctl_id = 0x22,
1162};
1163
1164static const struct adsp_data sm8450_mpss_resource = {
1165	.crash_reason_smem = 421,
1166	.firmware_name = "modem.mdt",
1167	.pas_id = 4,
1168	.minidump_id = 3,
1169	.auto_boot = false,
1170	.decrypt_shutdown = true,
1171	.proxy_pd_names = (char*[]){
1172		"cx",
1173		"mss",
1174		NULL
1175	},
1176	.load_state = "modem",
1177	.ssr_name = "mpss",
1178	.sysmon_name = "modem",
1179	.ssctl_id = 0x12,
1180};
1181
1182static const struct adsp_data sm8550_adsp_resource = {
1183	.crash_reason_smem = 423,
1184	.firmware_name = "adsp.mdt",
1185	.dtb_firmware_name = "adsp_dtb.mdt",
1186	.pas_id = 1,
1187	.dtb_pas_id = 0x24,
1188	.minidump_id = 5,
1189	.auto_boot = true,
1190	.proxy_pd_names = (char*[]){
1191		"lcx",
1192		"lmx",
1193		NULL
1194	},
1195	.load_state = "adsp",
1196	.ssr_name = "lpass",
1197	.sysmon_name = "adsp",
1198	.ssctl_id = 0x14,
1199};
1200
1201static const struct adsp_data sm8550_cdsp_resource = {
1202	.crash_reason_smem = 601,
1203	.firmware_name = "cdsp.mdt",
1204	.dtb_firmware_name = "cdsp_dtb.mdt",
1205	.pas_id = 18,
1206	.dtb_pas_id = 0x25,
1207	.minidump_id = 7,
1208	.auto_boot = true,
1209	.proxy_pd_names = (char*[]){
1210		"cx",
1211		"mxc",
1212		"nsp",
1213		NULL
1214	},
1215	.load_state = "cdsp",
1216	.ssr_name = "cdsp",
1217	.sysmon_name = "cdsp",
1218	.ssctl_id = 0x17,
1219};
1220
1221static const struct adsp_data sm8550_mpss_resource = {
1222	.crash_reason_smem = 421,
1223	.firmware_name = "modem.mdt",
1224	.dtb_firmware_name = "modem_dtb.mdt",
1225	.pas_id = 4,
1226	.dtb_pas_id = 0x26,
1227	.minidump_id = 3,
1228	.auto_boot = false,
1229	.decrypt_shutdown = true,
1230	.proxy_pd_names = (char*[]){
1231		"cx",
1232		"mss",
1233		NULL
1234	},
1235	.load_state = "modem",
1236	.ssr_name = "mpss",
1237	.sysmon_name = "modem",
1238	.ssctl_id = 0x12,
1239	.region_assign_idx = 2,
1240	.region_assign_count = 1,
1241	.region_assign_vmid = QCOM_SCM_VMID_MSS_MSA,
1242};
1243
1244static const struct adsp_data sc7280_wpss_resource = {
1245	.crash_reason_smem = 626,
1246	.firmware_name = "wpss.mdt",
1247	.pas_id = 6,
1248	.auto_boot = true,
1249	.proxy_pd_names = (char*[]){
1250		"cx",
1251		"mx",
1252		NULL
1253	},
1254	.load_state = "wpss",
1255	.ssr_name = "wpss",
1256	.sysmon_name = "wpss",
1257	.ssctl_id = 0x19,
1258};
1259
1260static const struct adsp_data sm8650_cdsp_resource = {
1261	.crash_reason_smem = 601,
1262	.firmware_name = "cdsp.mdt",
1263	.dtb_firmware_name = "cdsp_dtb.mdt",
1264	.pas_id = 18,
1265	.dtb_pas_id = 0x25,
1266	.minidump_id = 7,
1267	.auto_boot = true,
1268	.proxy_pd_names = (char*[]){
1269		"cx",
1270		"mxc",
1271		"nsp",
1272		NULL
1273	},
1274	.load_state = "cdsp",
1275	.ssr_name = "cdsp",
1276	.sysmon_name = "cdsp",
1277	.ssctl_id = 0x17,
1278	.region_assign_idx = 2,
1279	.region_assign_count = 1,
1280	.region_assign_shared = true,
1281	.region_assign_vmid = QCOM_SCM_VMID_CDSP,
1282};
1283
1284static const struct adsp_data sm8650_mpss_resource = {
1285	.crash_reason_smem = 421,
1286	.firmware_name = "modem.mdt",
1287	.dtb_firmware_name = "modem_dtb.mdt",
1288	.pas_id = 4,
1289	.dtb_pas_id = 0x26,
1290	.minidump_id = 3,
1291	.auto_boot = false,
1292	.decrypt_shutdown = true,
1293	.proxy_pd_names = (char*[]){
1294		"cx",
1295		"mss",
1296		NULL
1297	},
1298	.load_state = "modem",
1299	.ssr_name = "mpss",
1300	.sysmon_name = "modem",
1301	.ssctl_id = 0x12,
1302	.region_assign_idx = 2,
1303	.region_assign_count = 3,
1304	.region_assign_vmid = QCOM_SCM_VMID_MSS_MSA,
1305};
1306
1307static const struct of_device_id adsp_of_match[] = {
1308	{ .compatible = "qcom,msm8226-adsp-pil", .data = &adsp_resource_init},
1309	{ .compatible = "qcom,msm8953-adsp-pil", .data = &msm8996_adsp_resource},
1310	{ .compatible = "qcom,msm8974-adsp-pil", .data = &adsp_resource_init},
1311	{ .compatible = "qcom,msm8996-adsp-pil", .data = &msm8996_adsp_resource},
1312	{ .compatible = "qcom,msm8996-slpi-pil", .data = &msm8996_slpi_resource_init},
1313	{ .compatible = "qcom,msm8998-adsp-pas", .data = &msm8996_adsp_resource},
1314	{ .compatible = "qcom,msm8998-slpi-pas", .data = &msm8996_slpi_resource_init},
1315	{ .compatible = "qcom,qcs404-adsp-pas", .data = &adsp_resource_init },
1316	{ .compatible = "qcom,qcs404-cdsp-pas", .data = &cdsp_resource_init },
1317	{ .compatible = "qcom,qcs404-wcss-pas", .data = &wcss_resource_init },
1318	{ .compatible = "qcom,sc7180-adsp-pas", .data = &sm8250_adsp_resource},
1319	{ .compatible = "qcom,sc7180-mpss-pas", .data = &mpss_resource_init},
1320	{ .compatible = "qcom,sc7280-adsp-pas", .data = &sm8350_adsp_resource},
1321	{ .compatible = "qcom,sc7280-cdsp-pas", .data = &sm6350_cdsp_resource},
1322	{ .compatible = "qcom,sc7280-mpss-pas", .data = &mpss_resource_init},
1323	{ .compatible = "qcom,sc7280-wpss-pas", .data = &sc7280_wpss_resource},
1324	{ .compatible = "qcom,sc8180x-adsp-pas", .data = &sm8150_adsp_resource},
1325	{ .compatible = "qcom,sc8180x-cdsp-pas", .data = &sm8150_cdsp_resource},
1326	{ .compatible = "qcom,sc8180x-mpss-pas", .data = &sc8180x_mpss_resource},
1327	{ .compatible = "qcom,sc8280xp-adsp-pas", .data = &sm8250_adsp_resource},
1328	{ .compatible = "qcom,sc8280xp-nsp0-pas", .data = &sc8280xp_nsp0_resource},
1329	{ .compatible = "qcom,sc8280xp-nsp1-pas", .data = &sc8280xp_nsp1_resource},
1330	{ .compatible = "qcom,sdm660-adsp-pas", .data = &adsp_resource_init},
1331	{ .compatible = "qcom,sdm845-adsp-pas", .data = &sdm845_adsp_resource_init},
1332	{ .compatible = "qcom,sdm845-cdsp-pas", .data = &sdm845_cdsp_resource_init},
1333	{ .compatible = "qcom,sdm845-slpi-pas", .data = &sdm845_slpi_resource_init},
1334	{ .compatible = "qcom,sdx55-mpss-pas", .data = &sdx55_mpss_resource},
1335	{ .compatible = "qcom,sm6115-adsp-pas", .data = &adsp_resource_init},
1336	{ .compatible = "qcom,sm6115-cdsp-pas", .data = &cdsp_resource_init},
1337	{ .compatible = "qcom,sm6115-mpss-pas", .data = &sc8180x_mpss_resource},
1338	{ .compatible = "qcom,sm6350-adsp-pas", .data = &sm6350_adsp_resource},
1339	{ .compatible = "qcom,sm6350-cdsp-pas", .data = &sm6350_cdsp_resource},
1340	{ .compatible = "qcom,sm6350-mpss-pas", .data = &mpss_resource_init},
1341	{ .compatible = "qcom,sm6375-adsp-pas", .data = &sm6350_adsp_resource},
1342	{ .compatible = "qcom,sm6375-cdsp-pas", .data = &sm8150_cdsp_resource},
1343	{ .compatible = "qcom,sm6375-mpss-pas", .data = &sm6375_mpss_resource},
1344	{ .compatible = "qcom,sm8150-adsp-pas", .data = &sm8150_adsp_resource},
1345	{ .compatible = "qcom,sm8150-cdsp-pas", .data = &sm8150_cdsp_resource},
1346	{ .compatible = "qcom,sm8150-mpss-pas", .data = &mpss_resource_init},
1347	{ .compatible = "qcom,sm8150-slpi-pas", .data = &sdm845_slpi_resource_init},
1348	{ .compatible = "qcom,sm8250-adsp-pas", .data = &sm8250_adsp_resource},
1349	{ .compatible = "qcom,sm8250-cdsp-pas", .data = &sm8250_cdsp_resource},
1350	{ .compatible = "qcom,sm8250-slpi-pas", .data = &sdm845_slpi_resource_init},
1351	{ .compatible = "qcom,sm8350-adsp-pas", .data = &sm8350_adsp_resource},
1352	{ .compatible = "qcom,sm8350-cdsp-pas", .data = &sm8350_cdsp_resource},
1353	{ .compatible = "qcom,sm8350-slpi-pas", .data = &sdm845_slpi_resource_init},
1354	{ .compatible = "qcom,sm8350-mpss-pas", .data = &mpss_resource_init},
1355	{ .compatible = "qcom,sm8450-adsp-pas", .data = &sm8350_adsp_resource},
1356	{ .compatible = "qcom,sm8450-cdsp-pas", .data = &sm8350_cdsp_resource},
1357	{ .compatible = "qcom,sm8450-slpi-pas", .data = &sdm845_slpi_resource_init},
1358	{ .compatible = "qcom,sm8450-mpss-pas", .data = &sm8450_mpss_resource},
1359	{ .compatible = "qcom,sm8550-adsp-pas", .data = &sm8550_adsp_resource},
1360	{ .compatible = "qcom,sm8550-cdsp-pas", .data = &sm8550_cdsp_resource},
1361	{ .compatible = "qcom,sm8550-mpss-pas", .data = &sm8550_mpss_resource},
1362	{ .compatible = "qcom,sm8650-adsp-pas", .data = &sm8550_adsp_resource},
1363	{ .compatible = "qcom,sm8650-cdsp-pas", .data = &sm8650_cdsp_resource},
1364	{ .compatible = "qcom,sm8650-mpss-pas", .data = &sm8650_mpss_resource},
1365	{ .compatible = "qcom,x1e80100-adsp-pas", .data = &x1e80100_adsp_resource},
1366	{ .compatible = "qcom,x1e80100-cdsp-pas", .data = &x1e80100_cdsp_resource},
1367	{ },
1368};
1369MODULE_DEVICE_TABLE(of, adsp_of_match);
1370
1371static struct platform_driver adsp_driver = {
1372	.probe = adsp_probe,
1373	.remove_new = adsp_remove,
1374	.driver = {
1375		.name = "qcom_q6v5_pas",
1376		.of_match_table = adsp_of_match,
1377	},
1378};
1379
1380module_platform_driver(adsp_driver);
1381MODULE_DESCRIPTION("Qualcomm Hexagon v5 Peripheral Authentication Service driver");
1382MODULE_LICENSE("GPL v2");