cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

qcom_q6v5_adsp.c (17989B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Qualcomm Technology Inc. ADSP Peripheral Image Loader for SDM845.
      4 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
      5 */
      6
      7#include <linux/clk.h>
      8#include <linux/delay.h>
      9#include <linux/firmware.h>
     10#include <linux/interrupt.h>
     11#include <linux/io.h>
     12#include <linux/iopoll.h>
     13#include <linux/kernel.h>
     14#include <linux/mfd/syscon.h>
     15#include <linux/module.h>
     16#include <linux/of_address.h>
     17#include <linux/of_device.h>
     18#include <linux/platform_device.h>
     19#include <linux/pm_domain.h>
     20#include <linux/pm_runtime.h>
     21#include <linux/regmap.h>
     22#include <linux/remoteproc.h>
     23#include <linux/reset.h>
     24#include <linux/soc/qcom/mdt_loader.h>
     25#include <linux/soc/qcom/smem.h>
     26#include <linux/soc/qcom/smem_state.h>
     27
     28#include "qcom_common.h"
     29#include "qcom_pil_info.h"
     30#include "qcom_q6v5.h"
     31#include "remoteproc_internal.h"
     32
     33/* time out value */
     34#define ACK_TIMEOUT			1000
     35#define ACK_TIMEOUT_US			1000000
     36#define BOOT_FSM_TIMEOUT		10000
     37/* mask values */
     38#define EVB_MASK			GENMASK(27, 4)
     39/*QDSP6SS register offsets*/
     40#define RST_EVB_REG			0x10
     41#define CORE_START_REG			0x400
     42#define BOOT_CMD_REG			0x404
     43#define BOOT_STATUS_REG			0x408
     44#define RET_CFG_REG			0x1C
     45/*TCSR register offsets*/
     46#define LPASS_MASTER_IDLE_REG		0x8
     47#define LPASS_HALTACK_REG		0x4
     48#define LPASS_PWR_ON_REG		0x10
     49#define LPASS_HALTREQ_REG		0x0
     50
     51#define QDSP6SS_XO_CBCR		0x38
     52#define QDSP6SS_CORE_CBCR	0x20
     53#define QDSP6SS_SLEEP_CBCR	0x3c
     54
     55#define QCOM_Q6V5_RPROC_PROXY_PD_MAX	3
     56
     57struct adsp_pil_data {
     58	int crash_reason_smem;
     59	const char *firmware_name;
     60
     61	const char *ssr_name;
     62	const char *sysmon_name;
     63	int ssctl_id;
     64	bool is_wpss;
     65	bool auto_boot;
     66
     67	const char **clk_ids;
     68	int num_clks;
     69	const char **proxy_pd_names;
     70	const char *load_state;
     71};
     72
     73struct qcom_adsp {
     74	struct device *dev;
     75	struct rproc *rproc;
     76
     77	struct qcom_q6v5 q6v5;
     78
     79	struct clk *xo;
     80
     81	int num_clks;
     82	struct clk_bulk_data *clks;
     83
     84	void __iomem *qdsp6ss_base;
     85
     86	struct reset_control *pdc_sync_reset;
     87	struct reset_control *restart;
     88
     89	struct regmap *halt_map;
     90	unsigned int halt_lpass;
     91
     92	int crash_reason_smem;
     93	const char *info_name;
     94
     95	struct completion start_done;
     96	struct completion stop_done;
     97
     98	phys_addr_t mem_phys;
     99	phys_addr_t mem_reloc;
    100	void *mem_region;
    101	size_t mem_size;
    102
    103	struct device *proxy_pds[QCOM_Q6V5_RPROC_PROXY_PD_MAX];
    104	size_t proxy_pd_count;
    105
    106	struct qcom_rproc_glink glink_subdev;
    107	struct qcom_rproc_ssr ssr_subdev;
    108	struct qcom_sysmon *sysmon;
    109
    110	int (*shutdown)(struct qcom_adsp *adsp);
    111};
    112
    113static int qcom_rproc_pds_attach(struct device *dev, struct qcom_adsp *adsp,
    114				 const char **pd_names)
    115{
    116	struct device **devs = adsp->proxy_pds;
    117	size_t num_pds = 0;
    118	int ret;
    119	int i;
    120
    121	if (!pd_names)
    122		return 0;
    123
    124	/* Handle single power domain */
    125	if (dev->pm_domain) {
    126		devs[0] = dev;
    127		pm_runtime_enable(dev);
    128		return 1;
    129	}
    130
    131	while (pd_names[num_pds])
    132		num_pds++;
    133
    134	if (num_pds > ARRAY_SIZE(adsp->proxy_pds))
    135		return -E2BIG;
    136
    137	for (i = 0; i < num_pds; i++) {
    138		devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]);
    139		if (IS_ERR_OR_NULL(devs[i])) {
    140			ret = PTR_ERR(devs[i]) ? : -ENODATA;
    141			goto unroll_attach;
    142		}
    143	}
    144
    145	return num_pds;
    146
    147unroll_attach:
    148	for (i--; i >= 0; i--)
    149		dev_pm_domain_detach(devs[i], false);
    150
    151	return ret;
    152}
    153
    154static void qcom_rproc_pds_detach(struct qcom_adsp *adsp, struct device **pds,
    155				  size_t pd_count)
    156{
    157	struct device *dev = adsp->dev;
    158	int i;
    159
    160	/* Handle single power domain */
    161	if (dev->pm_domain && pd_count) {
    162		pm_runtime_disable(dev);
    163		return;
    164	}
    165
    166	for (i = 0; i < pd_count; i++)
    167		dev_pm_domain_detach(pds[i], false);
    168}
    169
    170static int qcom_rproc_pds_enable(struct qcom_adsp *adsp, struct device **pds,
    171				 size_t pd_count)
    172{
    173	int ret;
    174	int i;
    175
    176	for (i = 0; i < pd_count; i++) {
    177		dev_pm_genpd_set_performance_state(pds[i], INT_MAX);
    178		ret = pm_runtime_get_sync(pds[i]);
    179		if (ret < 0) {
    180			pm_runtime_put_noidle(pds[i]);
    181			dev_pm_genpd_set_performance_state(pds[i], 0);
    182			goto unroll_pd_votes;
    183		}
    184	}
    185
    186	return 0;
    187
    188unroll_pd_votes:
    189	for (i--; i >= 0; i--) {
    190		dev_pm_genpd_set_performance_state(pds[i], 0);
    191		pm_runtime_put(pds[i]);
    192	}
    193
    194	return ret;
    195}
    196
    197static void qcom_rproc_pds_disable(struct qcom_adsp *adsp, struct device **pds,
    198				   size_t pd_count)
    199{
    200	int i;
    201
    202	for (i = 0; i < pd_count; i++) {
    203		dev_pm_genpd_set_performance_state(pds[i], 0);
    204		pm_runtime_put(pds[i]);
    205	}
    206}
    207
    208static int qcom_wpss_shutdown(struct qcom_adsp *adsp)
    209{
    210	unsigned int val;
    211
    212	regmap_write(adsp->halt_map, adsp->halt_lpass + LPASS_HALTREQ_REG, 1);
    213
    214	/* Wait for halt ACK from QDSP6 */
    215	regmap_read_poll_timeout(adsp->halt_map,
    216				 adsp->halt_lpass + LPASS_HALTACK_REG, val,
    217				 val, 1000, ACK_TIMEOUT_US);
    218
    219	/* Assert the WPSS PDC Reset */
    220	reset_control_assert(adsp->pdc_sync_reset);
    221
    222	/* Place the WPSS processor into reset */
    223	reset_control_assert(adsp->restart);
    224
    225	/* wait after asserting subsystem restart from AOSS */
    226	usleep_range(200, 205);
    227
    228	/* Remove the WPSS reset */
    229	reset_control_deassert(adsp->restart);
    230
    231	/* De-assert the WPSS PDC Reset */
    232	reset_control_deassert(adsp->pdc_sync_reset);
    233
    234	usleep_range(100, 105);
    235
    236	clk_bulk_disable_unprepare(adsp->num_clks, adsp->clks);
    237
    238	regmap_write(adsp->halt_map, adsp->halt_lpass + LPASS_HALTREQ_REG, 0);
    239
    240	/* Wait for halt ACK from QDSP6 */
    241	regmap_read_poll_timeout(adsp->halt_map,
    242				 adsp->halt_lpass + LPASS_HALTACK_REG, val,
    243				 !val, 1000, ACK_TIMEOUT_US);
    244
    245	return 0;
    246}
    247
    248static int qcom_adsp_shutdown(struct qcom_adsp *adsp)
    249{
    250	unsigned long timeout;
    251	unsigned int val;
    252	int ret;
    253
    254	/* Reset the retention logic */
    255	val = readl(adsp->qdsp6ss_base + RET_CFG_REG);
    256	val |= 0x1;
    257	writel(val, adsp->qdsp6ss_base + RET_CFG_REG);
    258
    259	clk_bulk_disable_unprepare(adsp->num_clks, adsp->clks);
    260
    261	/* QDSP6 master port needs to be explicitly halted */
    262	ret = regmap_read(adsp->halt_map,
    263			adsp->halt_lpass + LPASS_PWR_ON_REG, &val);
    264	if (ret || !val)
    265		goto reset;
    266
    267	ret = regmap_read(adsp->halt_map,
    268			adsp->halt_lpass + LPASS_MASTER_IDLE_REG,
    269			&val);
    270	if (ret || val)
    271		goto reset;
    272
    273	regmap_write(adsp->halt_map,
    274			adsp->halt_lpass + LPASS_HALTREQ_REG, 1);
    275
    276	/* Wait for halt ACK from QDSP6 */
    277	timeout = jiffies + msecs_to_jiffies(ACK_TIMEOUT);
    278	for (;;) {
    279		ret = regmap_read(adsp->halt_map,
    280			adsp->halt_lpass + LPASS_HALTACK_REG, &val);
    281		if (ret || val || time_after(jiffies, timeout))
    282			break;
    283
    284		usleep_range(1000, 1100);
    285	}
    286
    287	ret = regmap_read(adsp->halt_map,
    288			adsp->halt_lpass + LPASS_MASTER_IDLE_REG, &val);
    289	if (ret || !val)
    290		dev_err(adsp->dev, "port failed halt\n");
    291
    292reset:
    293	/* Assert the LPASS PDC Reset */
    294	reset_control_assert(adsp->pdc_sync_reset);
    295	/* Place the LPASS processor into reset */
    296	reset_control_assert(adsp->restart);
    297	/* wait after asserting subsystem restart from AOSS */
    298	usleep_range(200, 300);
    299
    300	/* Clear the halt request for the AXIM and AHBM for Q6 */
    301	regmap_write(adsp->halt_map, adsp->halt_lpass + LPASS_HALTREQ_REG, 0);
    302
    303	/* De-assert the LPASS PDC Reset */
    304	reset_control_deassert(adsp->pdc_sync_reset);
    305	/* Remove the LPASS reset */
    306	reset_control_deassert(adsp->restart);
    307	/* wait after de-asserting subsystem restart from AOSS */
    308	usleep_range(200, 300);
    309
    310	return 0;
    311}
    312
    313static int adsp_load(struct rproc *rproc, const struct firmware *fw)
    314{
    315	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
    316	int ret;
    317
    318	ret = qcom_mdt_load_no_init(adsp->dev, fw, rproc->firmware, 0,
    319				    adsp->mem_region, adsp->mem_phys,
    320				    adsp->mem_size, &adsp->mem_reloc);
    321	if (ret)
    322		return ret;
    323
    324	qcom_pil_info_store(adsp->info_name, adsp->mem_phys, adsp->mem_size);
    325
    326	return 0;
    327}
    328
    329static int adsp_start(struct rproc *rproc)
    330{
    331	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
    332	int ret;
    333	unsigned int val;
    334
    335	ret = qcom_q6v5_prepare(&adsp->q6v5);
    336	if (ret)
    337		return ret;
    338
    339	ret = clk_prepare_enable(adsp->xo);
    340	if (ret)
    341		goto disable_irqs;
    342
    343	ret = qcom_rproc_pds_enable(adsp, adsp->proxy_pds,
    344				    adsp->proxy_pd_count);
    345	if (ret < 0)
    346		goto disable_xo_clk;
    347
    348	ret = clk_bulk_prepare_enable(adsp->num_clks, adsp->clks);
    349	if (ret) {
    350		dev_err(adsp->dev, "adsp clk_enable failed\n");
    351		goto disable_power_domain;
    352	}
    353
    354	/* Enable the XO clock */
    355	writel(1, adsp->qdsp6ss_base + QDSP6SS_XO_CBCR);
    356
    357	/* Enable the QDSP6SS sleep clock */
    358	writel(1, adsp->qdsp6ss_base + QDSP6SS_SLEEP_CBCR);
    359
    360	/* Enable the QDSP6 core clock */
    361	writel(1, adsp->qdsp6ss_base + QDSP6SS_CORE_CBCR);
    362
    363	/* Program boot address */
    364	writel(adsp->mem_phys >> 4, adsp->qdsp6ss_base + RST_EVB_REG);
    365
    366	/* De-assert QDSP6 stop core. QDSP6 will execute after out of reset */
    367	writel(0x1, adsp->qdsp6ss_base + CORE_START_REG);
    368
    369	/* Trigger boot FSM to start QDSP6 */
    370	writel(0x1, adsp->qdsp6ss_base + BOOT_CMD_REG);
    371
    372	/* Wait for core to come out of reset */
    373	ret = readl_poll_timeout(adsp->qdsp6ss_base + BOOT_STATUS_REG,
    374			val, (val & BIT(0)) != 0, 10, BOOT_FSM_TIMEOUT);
    375	if (ret) {
    376		dev_err(adsp->dev, "failed to bootup adsp\n");
    377		goto disable_adsp_clks;
    378	}
    379
    380	ret = qcom_q6v5_wait_for_start(&adsp->q6v5, msecs_to_jiffies(5 * HZ));
    381	if (ret == -ETIMEDOUT) {
    382		dev_err(adsp->dev, "start timed out\n");
    383		goto disable_adsp_clks;
    384	}
    385
    386	return 0;
    387
    388disable_adsp_clks:
    389	clk_bulk_disable_unprepare(adsp->num_clks, adsp->clks);
    390disable_power_domain:
    391	qcom_rproc_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
    392disable_xo_clk:
    393	clk_disable_unprepare(adsp->xo);
    394disable_irqs:
    395	qcom_q6v5_unprepare(&adsp->q6v5);
    396
    397	return ret;
    398}
    399
    400static void qcom_adsp_pil_handover(struct qcom_q6v5 *q6v5)
    401{
    402	struct qcom_adsp *adsp = container_of(q6v5, struct qcom_adsp, q6v5);
    403
    404	clk_disable_unprepare(adsp->xo);
    405	qcom_rproc_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
    406}
    407
    408static int adsp_stop(struct rproc *rproc)
    409{
    410	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
    411	int handover;
    412	int ret;
    413
    414	ret = qcom_q6v5_request_stop(&adsp->q6v5, adsp->sysmon);
    415	if (ret == -ETIMEDOUT)
    416		dev_err(adsp->dev, "timed out on wait\n");
    417
    418	ret = adsp->shutdown(adsp);
    419	if (ret)
    420		dev_err(adsp->dev, "failed to shutdown: %d\n", ret);
    421
    422	handover = qcom_q6v5_unprepare(&adsp->q6v5);
    423	if (handover)
    424		qcom_adsp_pil_handover(&adsp->q6v5);
    425
    426	return ret;
    427}
    428
    429static void *adsp_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
    430{
    431	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
    432	int offset;
    433
    434	offset = da - adsp->mem_reloc;
    435	if (offset < 0 || offset + len > adsp->mem_size)
    436		return NULL;
    437
    438	return adsp->mem_region + offset;
    439}
    440
    441static unsigned long adsp_panic(struct rproc *rproc)
    442{
    443	struct qcom_adsp *adsp = rproc->priv;
    444
    445	return qcom_q6v5_panic(&adsp->q6v5);
    446}
    447
    448static const struct rproc_ops adsp_ops = {
    449	.start = adsp_start,
    450	.stop = adsp_stop,
    451	.da_to_va = adsp_da_to_va,
    452	.parse_fw = qcom_register_dump_segments,
    453	.load = adsp_load,
    454	.panic = adsp_panic,
    455};
    456
    457static int adsp_init_clock(struct qcom_adsp *adsp, const char **clk_ids)
    458{
    459	int num_clks = 0;
    460	int i, ret;
    461
    462	adsp->xo = devm_clk_get(adsp->dev, "xo");
    463	if (IS_ERR(adsp->xo)) {
    464		ret = PTR_ERR(adsp->xo);
    465		if (ret != -EPROBE_DEFER)
    466			dev_err(adsp->dev, "failed to get xo clock");
    467		return ret;
    468	}
    469
    470	for (i = 0; clk_ids[i]; i++)
    471		num_clks++;
    472
    473	adsp->num_clks = num_clks;
    474	adsp->clks = devm_kcalloc(adsp->dev, adsp->num_clks,
    475				sizeof(*adsp->clks), GFP_KERNEL);
    476	if (!adsp->clks)
    477		return -ENOMEM;
    478
    479	for (i = 0; i < adsp->num_clks; i++)
    480		adsp->clks[i].id = clk_ids[i];
    481
    482	return devm_clk_bulk_get(adsp->dev, adsp->num_clks, adsp->clks);
    483}
    484
    485static int adsp_init_reset(struct qcom_adsp *adsp)
    486{
    487	adsp->pdc_sync_reset = devm_reset_control_get_optional_exclusive(adsp->dev,
    488			"pdc_sync");
    489	if (IS_ERR(adsp->pdc_sync_reset)) {
    490		dev_err(adsp->dev, "failed to acquire pdc_sync reset\n");
    491		return PTR_ERR(adsp->pdc_sync_reset);
    492	}
    493
    494	adsp->restart = devm_reset_control_get_optional_exclusive(adsp->dev, "restart");
    495
    496	/* Fall back to the  old "cc_lpass" if "restart" is absent */
    497	if (!adsp->restart)
    498		adsp->restart = devm_reset_control_get_exclusive(adsp->dev, "cc_lpass");
    499
    500	if (IS_ERR(adsp->restart)) {
    501		dev_err(adsp->dev, "failed to acquire restart\n");
    502		return PTR_ERR(adsp->restart);
    503	}
    504
    505	return 0;
    506}
    507
    508static int adsp_init_mmio(struct qcom_adsp *adsp,
    509				struct platform_device *pdev)
    510{
    511	struct device_node *syscon;
    512	int ret;
    513
    514	adsp->qdsp6ss_base = devm_platform_ioremap_resource(pdev, 0);
    515	if (IS_ERR(adsp->qdsp6ss_base)) {
    516		dev_err(adsp->dev, "failed to map QDSP6SS registers\n");
    517		return PTR_ERR(adsp->qdsp6ss_base);
    518	}
    519
    520	syscon = of_parse_phandle(pdev->dev.of_node, "qcom,halt-regs", 0);
    521	if (!syscon) {
    522		dev_err(&pdev->dev, "failed to parse qcom,halt-regs\n");
    523		return -EINVAL;
    524	}
    525
    526	adsp->halt_map = syscon_node_to_regmap(syscon);
    527	of_node_put(syscon);
    528	if (IS_ERR(adsp->halt_map))
    529		return PTR_ERR(adsp->halt_map);
    530
    531	ret = of_property_read_u32_index(pdev->dev.of_node, "qcom,halt-regs",
    532			1, &adsp->halt_lpass);
    533	if (ret < 0) {
    534		dev_err(&pdev->dev, "no offset in syscon\n");
    535		return ret;
    536	}
    537
    538	return 0;
    539}
    540
    541static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
    542{
    543	struct device_node *node;
    544	struct resource r;
    545	int ret;
    546
    547	node = of_parse_phandle(adsp->dev->of_node, "memory-region", 0);
    548	if (!node) {
    549		dev_err(adsp->dev, "no memory-region specified\n");
    550		return -EINVAL;
    551	}
    552
    553	ret = of_address_to_resource(node, 0, &r);
    554	of_node_put(node);
    555	if (ret)
    556		return ret;
    557
    558	adsp->mem_phys = adsp->mem_reloc = r.start;
    559	adsp->mem_size = resource_size(&r);
    560	adsp->mem_region = devm_ioremap_wc(adsp->dev,
    561				adsp->mem_phys, adsp->mem_size);
    562	if (!adsp->mem_region) {
    563		dev_err(adsp->dev, "unable to map memory region: %pa+%zx\n",
    564			&r.start, adsp->mem_size);
    565		return -EBUSY;
    566	}
    567
    568	return 0;
    569}
    570
    571static int adsp_probe(struct platform_device *pdev)
    572{
    573	const struct adsp_pil_data *desc;
    574	const char *firmware_name;
    575	struct qcom_adsp *adsp;
    576	struct rproc *rproc;
    577	int ret;
    578
    579	desc = of_device_get_match_data(&pdev->dev);
    580	if (!desc)
    581		return -EINVAL;
    582
    583	firmware_name = desc->firmware_name;
    584	ret = of_property_read_string(pdev->dev.of_node, "firmware-name",
    585				      &firmware_name);
    586	if (ret < 0 && ret != -EINVAL) {
    587		dev_err(&pdev->dev, "unable to read firmware-name\n");
    588		return ret;
    589	}
    590
    591	rproc = rproc_alloc(&pdev->dev, pdev->name, &adsp_ops,
    592			    firmware_name, sizeof(*adsp));
    593	if (!rproc) {
    594		dev_err(&pdev->dev, "unable to allocate remoteproc\n");
    595		return -ENOMEM;
    596	}
    597
    598	rproc->auto_boot = desc->auto_boot;
    599	rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);
    600
    601	adsp = (struct qcom_adsp *)rproc->priv;
    602	adsp->dev = &pdev->dev;
    603	adsp->rproc = rproc;
    604	adsp->info_name = desc->sysmon_name;
    605	platform_set_drvdata(pdev, adsp);
    606
    607	if (desc->is_wpss)
    608		adsp->shutdown = qcom_wpss_shutdown;
    609	else
    610		adsp->shutdown = qcom_adsp_shutdown;
    611
    612	ret = adsp_alloc_memory_region(adsp);
    613	if (ret)
    614		goto free_rproc;
    615
    616	ret = adsp_init_clock(adsp, desc->clk_ids);
    617	if (ret)
    618		goto free_rproc;
    619
    620	ret = qcom_rproc_pds_attach(adsp->dev, adsp,
    621				    desc->proxy_pd_names);
    622	if (ret < 0) {
    623		dev_err(&pdev->dev, "Failed to attach proxy power domains\n");
    624		goto free_rproc;
    625	}
    626	adsp->proxy_pd_count = ret;
    627
    628	ret = adsp_init_reset(adsp);
    629	if (ret)
    630		goto disable_pm;
    631
    632	ret = adsp_init_mmio(adsp, pdev);
    633	if (ret)
    634		goto disable_pm;
    635
    636	ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem,
    637			     desc->load_state, qcom_adsp_pil_handover);
    638	if (ret)
    639		goto disable_pm;
    640
    641	qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
    642	qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
    643	adsp->sysmon = qcom_add_sysmon_subdev(rproc,
    644					      desc->sysmon_name,
    645					      desc->ssctl_id);
    646	if (IS_ERR(adsp->sysmon)) {
    647		ret = PTR_ERR(adsp->sysmon);
    648		goto disable_pm;
    649	}
    650
    651	ret = rproc_add(rproc);
    652	if (ret)
    653		goto disable_pm;
    654
    655	return 0;
    656
    657disable_pm:
    658	qcom_rproc_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
    659
    660free_rproc:
    661	rproc_free(rproc);
    662
    663	return ret;
    664}
    665
    666static int adsp_remove(struct platform_device *pdev)
    667{
    668	struct qcom_adsp *adsp = platform_get_drvdata(pdev);
    669
    670	rproc_del(adsp->rproc);
    671
    672	qcom_q6v5_deinit(&adsp->q6v5);
    673	qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
    674	qcom_remove_sysmon_subdev(adsp->sysmon);
    675	qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
    676	qcom_rproc_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
    677	rproc_free(adsp->rproc);
    678
    679	return 0;
    680}
    681
    682static const struct adsp_pil_data adsp_resource_init = {
    683	.crash_reason_smem = 423,
    684	.firmware_name = "adsp.mdt",
    685	.ssr_name = "lpass",
    686	.sysmon_name = "adsp",
    687	.ssctl_id = 0x14,
    688	.is_wpss = false,
    689	.auto_boot = true,
    690	.clk_ids = (const char*[]) {
    691		"sway_cbcr", "lpass_ahbs_aon_cbcr", "lpass_ahbm_aon_cbcr",
    692		"qdsp6ss_xo", "qdsp6ss_sleep", "qdsp6ss_core", NULL
    693	},
    694	.num_clks = 7,
    695	.proxy_pd_names = (const char*[]) {
    696		"cx", NULL
    697	},
    698};
    699
    700static const struct adsp_pil_data cdsp_resource_init = {
    701	.crash_reason_smem = 601,
    702	.firmware_name = "cdsp.mdt",
    703	.ssr_name = "cdsp",
    704	.sysmon_name = "cdsp",
    705	.ssctl_id = 0x17,
    706	.is_wpss = false,
    707	.auto_boot = true,
    708	.clk_ids = (const char*[]) {
    709		"sway", "tbu", "bimc", "ahb_aon", "q6ss_slave", "q6ss_master",
    710		"q6_axim", NULL
    711	},
    712	.num_clks = 7,
    713	.proxy_pd_names = (const char*[]) {
    714		"cx", NULL
    715	},
    716};
    717
    718static const struct adsp_pil_data wpss_resource_init = {
    719	.crash_reason_smem = 626,
    720	.firmware_name = "wpss.mdt",
    721	.ssr_name = "wpss",
    722	.sysmon_name = "wpss",
    723	.ssctl_id = 0x19,
    724	.is_wpss = true,
    725	.auto_boot = false,
    726	.load_state = "wpss",
    727	.clk_ids = (const char*[]) {
    728		"ahb_bdg", "ahb", "rscp", NULL
    729	},
    730	.num_clks = 3,
    731	.proxy_pd_names = (const char*[]) {
    732		"cx", "mx", NULL
    733	},
    734};
    735
    736static const struct of_device_id adsp_of_match[] = {
    737	{ .compatible = "qcom,qcs404-cdsp-pil", .data = &cdsp_resource_init },
    738	{ .compatible = "qcom,sc7280-wpss-pil", .data = &wpss_resource_init },
    739	{ .compatible = "qcom,sdm845-adsp-pil", .data = &adsp_resource_init },
    740	{ },
    741};
    742MODULE_DEVICE_TABLE(of, adsp_of_match);
    743
    744static struct platform_driver adsp_pil_driver = {
    745	.probe = adsp_probe,
    746	.remove = adsp_remove,
    747	.driver = {
    748		.name = "qcom_q6v5_adsp",
    749		.of_match_table = adsp_of_match,
    750	},
    751};
    752
    753module_platform_driver(adsp_pil_driver);
    754MODULE_DESCRIPTION("QTI SDM845 ADSP Peripheral Image Loader");
    755MODULE_LICENSE("GPL v2");