forked from Minki/linux
8447d0e750
devm_regulator_get_optional() API will return -ENODEV if the regulator was not found. For the optional supplies CX, PX we should not fail in that case but rather continue. So let's catch that error and continue silently if those regulators are not found. The commit3f52d118f9
("remoteproc: qcom_q6v5_pas: Deal silently with optional px and cx regulators") was supposed to do the same but it missed the fact that devm_regulator_get_optional() API returns -ENODEV when the regulator was not found. Cc: Abel Vesa <abel.vesa@linaro.org> Fixes:3f52d118f9
("remoteproc: qcom_q6v5_pas: Deal silently with optional px and cx regulators") Reported-by: Steev Klimaszewski <steev@kali.org> Reviewed-by: Abel Vesa <abel.vesa@linaro.org> Reviewed-by: Johan Hovold <johan+linaro@kernel.org> Tested-by: Steev Klimaszewski <steev@kali.org> Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org> Link: https://lore.kernel.org/r/20220801053939.12556-1-manivannan.sadhasivam@linaro.org
1005 lines
23 KiB
C
1005 lines
23 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Qualcomm ADSP/SLPI Peripheral Image Loader for MSM8974 and MSM8996
|
|
*
|
|
* Copyright (C) 2016 Linaro Ltd
|
|
* Copyright (C) 2014 Sony Mobile Communications AB
|
|
* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/clk.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/firmware.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/of_address.h>
|
|
#include <linux/of_device.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/pm_domain.h>
|
|
#include <linux/pm_runtime.h>
|
|
#include <linux/qcom_scm.h>
|
|
#include <linux/regulator/consumer.h>
|
|
#include <linux/remoteproc.h>
|
|
#include <linux/soc/qcom/mdt_loader.h>
|
|
#include <linux/soc/qcom/smem.h>
|
|
#include <linux/soc/qcom/smem_state.h>
|
|
|
|
#include "qcom_common.h"
|
|
#include "qcom_pil_info.h"
|
|
#include "qcom_q6v5.h"
|
|
#include "remoteproc_internal.h"
|
|
|
|
#define ADSP_DECRYPT_SHUTDOWN_DELAY_MS 100
|
|
|
|
struct adsp_data {
|
|
int crash_reason_smem;
|
|
const char *firmware_name;
|
|
int pas_id;
|
|
unsigned int minidump_id;
|
|
bool has_aggre2_clk;
|
|
bool auto_boot;
|
|
bool decrypt_shutdown;
|
|
|
|
char **proxy_pd_names;
|
|
|
|
const char *load_state;
|
|
const char *ssr_name;
|
|
const char *sysmon_name;
|
|
int ssctl_id;
|
|
};
|
|
|
|
struct qcom_adsp {
|
|
struct device *dev;
|
|
struct rproc *rproc;
|
|
|
|
struct qcom_q6v5 q6v5;
|
|
|
|
struct clk *xo;
|
|
struct clk *aggre2_clk;
|
|
|
|
struct regulator *cx_supply;
|
|
struct regulator *px_supply;
|
|
|
|
struct device *proxy_pds[3];
|
|
|
|
int proxy_pd_count;
|
|
|
|
int pas_id;
|
|
unsigned int minidump_id;
|
|
int crash_reason_smem;
|
|
bool has_aggre2_clk;
|
|
bool decrypt_shutdown;
|
|
const char *info_name;
|
|
|
|
struct completion start_done;
|
|
struct completion stop_done;
|
|
|
|
phys_addr_t mem_phys;
|
|
phys_addr_t mem_reloc;
|
|
void *mem_region;
|
|
size_t mem_size;
|
|
|
|
struct qcom_rproc_glink glink_subdev;
|
|
struct qcom_rproc_subdev smd_subdev;
|
|
struct qcom_rproc_ssr ssr_subdev;
|
|
struct qcom_sysmon *sysmon;
|
|
|
|
struct qcom_scm_pas_metadata pas_metadata;
|
|
};
|
|
|
|
static void adsp_minidump(struct rproc *rproc)
|
|
{
|
|
struct qcom_adsp *adsp = rproc->priv;
|
|
|
|
if (rproc->dump_conf == RPROC_COREDUMP_DISABLED)
|
|
return;
|
|
|
|
qcom_minidump(rproc, adsp->minidump_id);
|
|
}
|
|
|
|
static int adsp_pds_enable(struct qcom_adsp *adsp, struct device **pds,
|
|
size_t pd_count)
|
|
{
|
|
int ret;
|
|
int i;
|
|
|
|
for (i = 0; i < pd_count; i++) {
|
|
dev_pm_genpd_set_performance_state(pds[i], INT_MAX);
|
|
ret = pm_runtime_get_sync(pds[i]);
|
|
if (ret < 0) {
|
|
pm_runtime_put_noidle(pds[i]);
|
|
dev_pm_genpd_set_performance_state(pds[i], 0);
|
|
goto unroll_pd_votes;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
|
|
unroll_pd_votes:
|
|
for (i--; i >= 0; i--) {
|
|
dev_pm_genpd_set_performance_state(pds[i], 0);
|
|
pm_runtime_put(pds[i]);
|
|
}
|
|
|
|
return ret;
|
|
};
|
|
|
|
static void adsp_pds_disable(struct qcom_adsp *adsp, struct device **pds,
|
|
size_t pd_count)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < pd_count; i++) {
|
|
dev_pm_genpd_set_performance_state(pds[i], 0);
|
|
pm_runtime_put(pds[i]);
|
|
}
|
|
}
|
|
|
|
static int adsp_shutdown_poll_decrypt(struct qcom_adsp *adsp)
|
|
{
|
|
unsigned int retry_num = 50;
|
|
int ret;
|
|
|
|
do {
|
|
msleep(ADSP_DECRYPT_SHUTDOWN_DELAY_MS);
|
|
ret = qcom_scm_pas_shutdown(adsp->pas_id);
|
|
} while (ret == -EINVAL && --retry_num);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int adsp_unprepare(struct rproc *rproc)
|
|
{
|
|
struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
|
|
|
|
/*
|
|
* adsp_load() did pass pas_metadata to the SCM driver for storing
|
|
* metadata context. It might have been released already if
|
|
* auth_and_reset() was successful, but in other cases clean it up
|
|
* here.
|
|
*/
|
|
qcom_scm_pas_metadata_release(&adsp->pas_metadata);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int adsp_load(struct rproc *rproc, const struct firmware *fw)
|
|
{
|
|
struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
|
|
int ret;
|
|
|
|
ret = qcom_mdt_pas_init(adsp->dev, fw, rproc->firmware, adsp->pas_id,
|
|
adsp->mem_phys, &adsp->pas_metadata);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = qcom_mdt_load_no_init(adsp->dev, fw, rproc->firmware, adsp->pas_id,
|
|
adsp->mem_region, adsp->mem_phys, adsp->mem_size,
|
|
&adsp->mem_reloc);
|
|
if (ret)
|
|
return ret;
|
|
|
|
qcom_pil_info_store(adsp->info_name, adsp->mem_phys, adsp->mem_size);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int adsp_start(struct rproc *rproc)
|
|
{
|
|
struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
|
|
int ret;
|
|
|
|
ret = qcom_q6v5_prepare(&adsp->q6v5);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = adsp_pds_enable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
|
|
if (ret < 0)
|
|
goto disable_irqs;
|
|
|
|
ret = clk_prepare_enable(adsp->xo);
|
|
if (ret)
|
|
goto disable_proxy_pds;
|
|
|
|
ret = clk_prepare_enable(adsp->aggre2_clk);
|
|
if (ret)
|
|
goto disable_xo_clk;
|
|
|
|
if (adsp->cx_supply) {
|
|
ret = regulator_enable(adsp->cx_supply);
|
|
if (ret)
|
|
goto disable_aggre2_clk;
|
|
}
|
|
|
|
if (adsp->px_supply) {
|
|
ret = regulator_enable(adsp->px_supply);
|
|
if (ret)
|
|
goto disable_cx_supply;
|
|
}
|
|
|
|
ret = qcom_scm_pas_auth_and_reset(adsp->pas_id);
|
|
if (ret) {
|
|
dev_err(adsp->dev,
|
|
"failed to authenticate image and release reset\n");
|
|
goto disable_px_supply;
|
|
}
|
|
|
|
ret = qcom_q6v5_wait_for_start(&adsp->q6v5, msecs_to_jiffies(5000));
|
|
if (ret == -ETIMEDOUT) {
|
|
dev_err(adsp->dev, "start timed out\n");
|
|
qcom_scm_pas_shutdown(adsp->pas_id);
|
|
goto disable_px_supply;
|
|
}
|
|
|
|
qcom_scm_pas_metadata_release(&adsp->pas_metadata);
|
|
|
|
return 0;
|
|
|
|
disable_px_supply:
|
|
if (adsp->px_supply)
|
|
regulator_disable(adsp->px_supply);
|
|
disable_cx_supply:
|
|
if (adsp->cx_supply)
|
|
regulator_disable(adsp->cx_supply);
|
|
disable_aggre2_clk:
|
|
clk_disable_unprepare(adsp->aggre2_clk);
|
|
disable_xo_clk:
|
|
clk_disable_unprepare(adsp->xo);
|
|
disable_proxy_pds:
|
|
adsp_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
|
|
disable_irqs:
|
|
qcom_q6v5_unprepare(&adsp->q6v5);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void qcom_pas_handover(struct qcom_q6v5 *q6v5)
|
|
{
|
|
struct qcom_adsp *adsp = container_of(q6v5, struct qcom_adsp, q6v5);
|
|
|
|
if (adsp->px_supply)
|
|
regulator_disable(adsp->px_supply);
|
|
if (adsp->cx_supply)
|
|
regulator_disable(adsp->cx_supply);
|
|
clk_disable_unprepare(adsp->aggre2_clk);
|
|
clk_disable_unprepare(adsp->xo);
|
|
adsp_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
|
|
}
|
|
|
|
static int adsp_stop(struct rproc *rproc)
|
|
{
|
|
struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
|
|
int handover;
|
|
int ret;
|
|
|
|
ret = qcom_q6v5_request_stop(&adsp->q6v5, adsp->sysmon);
|
|
if (ret == -ETIMEDOUT)
|
|
dev_err(adsp->dev, "timed out on wait\n");
|
|
|
|
ret = qcom_scm_pas_shutdown(adsp->pas_id);
|
|
if (ret && adsp->decrypt_shutdown)
|
|
ret = adsp_shutdown_poll_decrypt(adsp);
|
|
|
|
if (ret)
|
|
dev_err(adsp->dev, "failed to shutdown: %d\n", ret);
|
|
|
|
handover = qcom_q6v5_unprepare(&adsp->q6v5);
|
|
if (handover)
|
|
qcom_pas_handover(&adsp->q6v5);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void *adsp_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
|
|
{
|
|
struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
|
|
int offset;
|
|
|
|
offset = da - adsp->mem_reloc;
|
|
if (offset < 0 || offset + len > adsp->mem_size)
|
|
return NULL;
|
|
|
|
if (is_iomem)
|
|
*is_iomem = true;
|
|
|
|
return adsp->mem_region + offset;
|
|
}
|
|
|
|
static unsigned long adsp_panic(struct rproc *rproc)
|
|
{
|
|
struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
|
|
|
|
return qcom_q6v5_panic(&adsp->q6v5);
|
|
}
|
|
|
|
static const struct rproc_ops adsp_ops = {
|
|
.unprepare = adsp_unprepare,
|
|
.start = adsp_start,
|
|
.stop = adsp_stop,
|
|
.da_to_va = adsp_da_to_va,
|
|
.parse_fw = qcom_register_dump_segments,
|
|
.load = adsp_load,
|
|
.panic = adsp_panic,
|
|
};
|
|
|
|
static const struct rproc_ops adsp_minidump_ops = {
|
|
.unprepare = adsp_unprepare,
|
|
.start = adsp_start,
|
|
.stop = adsp_stop,
|
|
.da_to_va = adsp_da_to_va,
|
|
.load = adsp_load,
|
|
.panic = adsp_panic,
|
|
.coredump = adsp_minidump,
|
|
};
|
|
|
|
static int adsp_init_clock(struct qcom_adsp *adsp)
|
|
{
|
|
int ret;
|
|
|
|
adsp->xo = devm_clk_get(adsp->dev, "xo");
|
|
if (IS_ERR(adsp->xo)) {
|
|
ret = PTR_ERR(adsp->xo);
|
|
if (ret != -EPROBE_DEFER)
|
|
dev_err(adsp->dev, "failed to get xo clock");
|
|
return ret;
|
|
}
|
|
|
|
if (adsp->has_aggre2_clk) {
|
|
adsp->aggre2_clk = devm_clk_get(adsp->dev, "aggre2");
|
|
if (IS_ERR(adsp->aggre2_clk)) {
|
|
ret = PTR_ERR(adsp->aggre2_clk);
|
|
if (ret != -EPROBE_DEFER)
|
|
dev_err(adsp->dev,
|
|
"failed to get aggre2 clock");
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int adsp_init_regulator(struct qcom_adsp *adsp)
|
|
{
|
|
adsp->cx_supply = devm_regulator_get_optional(adsp->dev, "cx");
|
|
if (IS_ERR(adsp->cx_supply)) {
|
|
if (PTR_ERR(adsp->cx_supply) == -ENODEV)
|
|
adsp->cx_supply = NULL;
|
|
else
|
|
return PTR_ERR(adsp->cx_supply);
|
|
}
|
|
|
|
if (adsp->cx_supply)
|
|
regulator_set_load(adsp->cx_supply, 100000);
|
|
|
|
adsp->px_supply = devm_regulator_get_optional(adsp->dev, "px");
|
|
if (IS_ERR(adsp->px_supply)) {
|
|
if (PTR_ERR(adsp->px_supply) == -ENODEV)
|
|
adsp->px_supply = NULL;
|
|
else
|
|
return PTR_ERR(adsp->px_supply);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int adsp_pds_attach(struct device *dev, struct device **devs,
|
|
char **pd_names)
|
|
{
|
|
size_t num_pds = 0;
|
|
int ret;
|
|
int i;
|
|
|
|
if (!pd_names)
|
|
return 0;
|
|
|
|
/* Handle single power domain */
|
|
if (dev->pm_domain) {
|
|
devs[0] = dev;
|
|
pm_runtime_enable(dev);
|
|
return 1;
|
|
}
|
|
|
|
while (pd_names[num_pds])
|
|
num_pds++;
|
|
|
|
for (i = 0; i < num_pds; i++) {
|
|
devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]);
|
|
if (IS_ERR_OR_NULL(devs[i])) {
|
|
ret = PTR_ERR(devs[i]) ? : -ENODATA;
|
|
goto unroll_attach;
|
|
}
|
|
}
|
|
|
|
return num_pds;
|
|
|
|
unroll_attach:
|
|
for (i--; i >= 0; i--)
|
|
dev_pm_domain_detach(devs[i], false);
|
|
|
|
return ret;
|
|
};
|
|
|
|
static void adsp_pds_detach(struct qcom_adsp *adsp, struct device **pds,
|
|
size_t pd_count)
|
|
{
|
|
struct device *dev = adsp->dev;
|
|
int i;
|
|
|
|
/* Handle single power domain */
|
|
if (dev->pm_domain && pd_count) {
|
|
pm_runtime_disable(dev);
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < pd_count; i++)
|
|
dev_pm_domain_detach(pds[i], false);
|
|
}
|
|
|
|
static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
|
|
{
|
|
struct device_node *node;
|
|
struct resource r;
|
|
int ret;
|
|
|
|
node = of_parse_phandle(adsp->dev->of_node, "memory-region", 0);
|
|
if (!node) {
|
|
dev_err(adsp->dev, "no memory-region specified\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
ret = of_address_to_resource(node, 0, &r);
|
|
if (ret)
|
|
return ret;
|
|
|
|
adsp->mem_phys = adsp->mem_reloc = r.start;
|
|
adsp->mem_size = resource_size(&r);
|
|
adsp->mem_region = devm_ioremap_wc(adsp->dev, adsp->mem_phys, adsp->mem_size);
|
|
if (!adsp->mem_region) {
|
|
dev_err(adsp->dev, "unable to map memory region: %pa+%zx\n",
|
|
&r.start, adsp->mem_size);
|
|
return -EBUSY;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int adsp_probe(struct platform_device *pdev)
|
|
{
|
|
const struct adsp_data *desc;
|
|
struct qcom_adsp *adsp;
|
|
struct rproc *rproc;
|
|
const char *fw_name;
|
|
const struct rproc_ops *ops = &adsp_ops;
|
|
int ret;
|
|
|
|
desc = of_device_get_match_data(&pdev->dev);
|
|
if (!desc)
|
|
return -EINVAL;
|
|
|
|
if (!qcom_scm_is_available())
|
|
return -EPROBE_DEFER;
|
|
|
|
fw_name = desc->firmware_name;
|
|
ret = of_property_read_string(pdev->dev.of_node, "firmware-name",
|
|
&fw_name);
|
|
if (ret < 0 && ret != -EINVAL)
|
|
return ret;
|
|
|
|
if (desc->minidump_id)
|
|
ops = &adsp_minidump_ops;
|
|
|
|
rproc = rproc_alloc(&pdev->dev, pdev->name, ops, fw_name, sizeof(*adsp));
|
|
|
|
if (!rproc) {
|
|
dev_err(&pdev->dev, "unable to allocate remoteproc\n");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
rproc->auto_boot = desc->auto_boot;
|
|
rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);
|
|
|
|
adsp = (struct qcom_adsp *)rproc->priv;
|
|
adsp->dev = &pdev->dev;
|
|
adsp->rproc = rproc;
|
|
adsp->minidump_id = desc->minidump_id;
|
|
adsp->pas_id = desc->pas_id;
|
|
adsp->has_aggre2_clk = desc->has_aggre2_clk;
|
|
adsp->info_name = desc->sysmon_name;
|
|
adsp->decrypt_shutdown = desc->decrypt_shutdown;
|
|
platform_set_drvdata(pdev, adsp);
|
|
|
|
ret = device_init_wakeup(adsp->dev, true);
|
|
if (ret)
|
|
goto free_rproc;
|
|
|
|
ret = adsp_alloc_memory_region(adsp);
|
|
if (ret)
|
|
goto free_rproc;
|
|
|
|
ret = adsp_init_clock(adsp);
|
|
if (ret)
|
|
goto free_rproc;
|
|
|
|
ret = adsp_init_regulator(adsp);
|
|
if (ret)
|
|
goto free_rproc;
|
|
|
|
ret = adsp_pds_attach(&pdev->dev, adsp->proxy_pds,
|
|
desc->proxy_pd_names);
|
|
if (ret < 0)
|
|
goto free_rproc;
|
|
adsp->proxy_pd_count = ret;
|
|
|
|
ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem, desc->load_state,
|
|
qcom_pas_handover);
|
|
if (ret)
|
|
goto detach_proxy_pds;
|
|
|
|
qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
|
|
qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
|
|
qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
|
|
adsp->sysmon = qcom_add_sysmon_subdev(rproc,
|
|
desc->sysmon_name,
|
|
desc->ssctl_id);
|
|
if (IS_ERR(adsp->sysmon)) {
|
|
ret = PTR_ERR(adsp->sysmon);
|
|
goto detach_proxy_pds;
|
|
}
|
|
|
|
ret = rproc_add(rproc);
|
|
if (ret)
|
|
goto detach_proxy_pds;
|
|
|
|
return 0;
|
|
|
|
detach_proxy_pds:
|
|
adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
|
|
free_rproc:
|
|
rproc_free(rproc);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int adsp_remove(struct platform_device *pdev)
|
|
{
|
|
struct qcom_adsp *adsp = platform_get_drvdata(pdev);
|
|
|
|
rproc_del(adsp->rproc);
|
|
|
|
qcom_q6v5_deinit(&adsp->q6v5);
|
|
qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
|
|
qcom_remove_sysmon_subdev(adsp->sysmon);
|
|
qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
|
|
qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
|
|
rproc_free(adsp->rproc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct adsp_data adsp_resource_init = {
|
|
.crash_reason_smem = 423,
|
|
.firmware_name = "adsp.mdt",
|
|
.pas_id = 1,
|
|
.has_aggre2_clk = false,
|
|
.auto_boot = true,
|
|
.ssr_name = "lpass",
|
|
.sysmon_name = "adsp",
|
|
.ssctl_id = 0x14,
|
|
};
|
|
|
|
static const struct adsp_data sdm845_adsp_resource_init = {
|
|
.crash_reason_smem = 423,
|
|
.firmware_name = "adsp.mdt",
|
|
.pas_id = 1,
|
|
.has_aggre2_clk = false,
|
|
.auto_boot = true,
|
|
.load_state = "adsp",
|
|
.ssr_name = "lpass",
|
|
.sysmon_name = "adsp",
|
|
.ssctl_id = 0x14,
|
|
};
|
|
|
|
static const struct adsp_data sm6350_adsp_resource = {
|
|
.crash_reason_smem = 423,
|
|
.firmware_name = "adsp.mdt",
|
|
.pas_id = 1,
|
|
.has_aggre2_clk = false,
|
|
.auto_boot = true,
|
|
.proxy_pd_names = (char*[]){
|
|
"lcx",
|
|
"lmx",
|
|
NULL
|
|
},
|
|
.load_state = "adsp",
|
|
.ssr_name = "lpass",
|
|
.sysmon_name = "adsp",
|
|
.ssctl_id = 0x14,
|
|
};
|
|
|
|
static const struct adsp_data sm8150_adsp_resource = {
|
|
.crash_reason_smem = 423,
|
|
.firmware_name = "adsp.mdt",
|
|
.pas_id = 1,
|
|
.has_aggre2_clk = false,
|
|
.auto_boot = true,
|
|
.proxy_pd_names = (char*[]){
|
|
"cx",
|
|
NULL
|
|
},
|
|
.load_state = "adsp",
|
|
.ssr_name = "lpass",
|
|
.sysmon_name = "adsp",
|
|
.ssctl_id = 0x14,
|
|
};
|
|
|
|
static const struct adsp_data sm8250_adsp_resource = {
|
|
.crash_reason_smem = 423,
|
|
.firmware_name = "adsp.mdt",
|
|
.pas_id = 1,
|
|
.has_aggre2_clk = false,
|
|
.auto_boot = true,
|
|
.proxy_pd_names = (char*[]){
|
|
"lcx",
|
|
"lmx",
|
|
NULL
|
|
},
|
|
.load_state = "adsp",
|
|
.ssr_name = "lpass",
|
|
.sysmon_name = "adsp",
|
|
.ssctl_id = 0x14,
|
|
};
|
|
|
|
static const struct adsp_data sm8350_adsp_resource = {
|
|
.crash_reason_smem = 423,
|
|
.firmware_name = "adsp.mdt",
|
|
.pas_id = 1,
|
|
.has_aggre2_clk = false,
|
|
.auto_boot = true,
|
|
.proxy_pd_names = (char*[]){
|
|
"lcx",
|
|
"lmx",
|
|
NULL
|
|
},
|
|
.load_state = "adsp",
|
|
.ssr_name = "lpass",
|
|
.sysmon_name = "adsp",
|
|
.ssctl_id = 0x14,
|
|
};
|
|
|
|
static const struct adsp_data msm8996_adsp_resource = {
|
|
.crash_reason_smem = 423,
|
|
.firmware_name = "adsp.mdt",
|
|
.pas_id = 1,
|
|
.has_aggre2_clk = false,
|
|
.auto_boot = true,
|
|
.proxy_pd_names = (char*[]){
|
|
"cx",
|
|
NULL
|
|
},
|
|
.ssr_name = "lpass",
|
|
.sysmon_name = "adsp",
|
|
.ssctl_id = 0x14,
|
|
};
|
|
|
|
static const struct adsp_data cdsp_resource_init = {
|
|
.crash_reason_smem = 601,
|
|
.firmware_name = "cdsp.mdt",
|
|
.pas_id = 18,
|
|
.has_aggre2_clk = false,
|
|
.auto_boot = true,
|
|
.ssr_name = "cdsp",
|
|
.sysmon_name = "cdsp",
|
|
.ssctl_id = 0x17,
|
|
};
|
|
|
|
static const struct adsp_data sdm845_cdsp_resource_init = {
|
|
.crash_reason_smem = 601,
|
|
.firmware_name = "cdsp.mdt",
|
|
.pas_id = 18,
|
|
.has_aggre2_clk = false,
|
|
.auto_boot = true,
|
|
.load_state = "cdsp",
|
|
.ssr_name = "cdsp",
|
|
.sysmon_name = "cdsp",
|
|
.ssctl_id = 0x17,
|
|
};
|
|
|
|
static const struct adsp_data sm6350_cdsp_resource = {
|
|
.crash_reason_smem = 601,
|
|
.firmware_name = "cdsp.mdt",
|
|
.pas_id = 18,
|
|
.has_aggre2_clk = false,
|
|
.auto_boot = true,
|
|
.proxy_pd_names = (char*[]){
|
|
"cx",
|
|
"mx",
|
|
NULL
|
|
},
|
|
.load_state = "cdsp",
|
|
.ssr_name = "cdsp",
|
|
.sysmon_name = "cdsp",
|
|
.ssctl_id = 0x17,
|
|
};
|
|
|
|
static const struct adsp_data sm8150_cdsp_resource = {
|
|
.crash_reason_smem = 601,
|
|
.firmware_name = "cdsp.mdt",
|
|
.pas_id = 18,
|
|
.has_aggre2_clk = false,
|
|
.auto_boot = true,
|
|
.proxy_pd_names = (char*[]){
|
|
"cx",
|
|
NULL
|
|
},
|
|
.load_state = "cdsp",
|
|
.ssr_name = "cdsp",
|
|
.sysmon_name = "cdsp",
|
|
.ssctl_id = 0x17,
|
|
};
|
|
|
|
static const struct adsp_data sm8250_cdsp_resource = {
|
|
.crash_reason_smem = 601,
|
|
.firmware_name = "cdsp.mdt",
|
|
.pas_id = 18,
|
|
.has_aggre2_clk = false,
|
|
.auto_boot = true,
|
|
.proxy_pd_names = (char*[]){
|
|
"cx",
|
|
NULL
|
|
},
|
|
.load_state = "cdsp",
|
|
.ssr_name = "cdsp",
|
|
.sysmon_name = "cdsp",
|
|
.ssctl_id = 0x17,
|
|
};
|
|
|
|
static const struct adsp_data sc8280xp_nsp0_resource = {
|
|
.crash_reason_smem = 601,
|
|
.firmware_name = "cdsp.mdt",
|
|
.pas_id = 18,
|
|
.has_aggre2_clk = false,
|
|
.auto_boot = true,
|
|
.proxy_pd_names = (char*[]){
|
|
"nsp",
|
|
NULL
|
|
},
|
|
.ssr_name = "cdsp0",
|
|
.sysmon_name = "cdsp",
|
|
.ssctl_id = 0x17,
|
|
};
|
|
|
|
static const struct adsp_data sc8280xp_nsp1_resource = {
|
|
.crash_reason_smem = 633,
|
|
.firmware_name = "cdsp.mdt",
|
|
.pas_id = 30,
|
|
.has_aggre2_clk = false,
|
|
.auto_boot = true,
|
|
.proxy_pd_names = (char*[]){
|
|
"nsp",
|
|
NULL
|
|
},
|
|
.ssr_name = "cdsp1",
|
|
.sysmon_name = "cdsp1",
|
|
.ssctl_id = 0x20,
|
|
};
|
|
|
|
static const struct adsp_data sm8350_cdsp_resource = {
|
|
.crash_reason_smem = 601,
|
|
.firmware_name = "cdsp.mdt",
|
|
.pas_id = 18,
|
|
.has_aggre2_clk = false,
|
|
.auto_boot = true,
|
|
.proxy_pd_names = (char*[]){
|
|
"cx",
|
|
"mxc",
|
|
NULL
|
|
},
|
|
.load_state = "cdsp",
|
|
.ssr_name = "cdsp",
|
|
.sysmon_name = "cdsp",
|
|
.ssctl_id = 0x17,
|
|
};
|
|
|
|
static const struct adsp_data mpss_resource_init = {
|
|
.crash_reason_smem = 421,
|
|
.firmware_name = "modem.mdt",
|
|
.pas_id = 4,
|
|
.minidump_id = 3,
|
|
.has_aggre2_clk = false,
|
|
.auto_boot = false,
|
|
.proxy_pd_names = (char*[]){
|
|
"cx",
|
|
"mss",
|
|
NULL
|
|
},
|
|
.load_state = "modem",
|
|
.ssr_name = "mpss",
|
|
.sysmon_name = "modem",
|
|
.ssctl_id = 0x12,
|
|
};
|
|
|
|
static const struct adsp_data sc8180x_mpss_resource = {
|
|
.crash_reason_smem = 421,
|
|
.firmware_name = "modem.mdt",
|
|
.pas_id = 4,
|
|
.has_aggre2_clk = false,
|
|
.auto_boot = false,
|
|
.proxy_pd_names = (char*[]){
|
|
"cx",
|
|
NULL
|
|
},
|
|
.load_state = "modem",
|
|
.ssr_name = "mpss",
|
|
.sysmon_name = "modem",
|
|
.ssctl_id = 0x12,
|
|
};
|
|
|
|
static const struct adsp_data slpi_resource_init = {
|
|
.crash_reason_smem = 424,
|
|
.firmware_name = "slpi.mdt",
|
|
.pas_id = 12,
|
|
.has_aggre2_clk = true,
|
|
.auto_boot = true,
|
|
.proxy_pd_names = (char*[]){
|
|
"ssc_cx",
|
|
NULL
|
|
},
|
|
.ssr_name = "dsps",
|
|
.sysmon_name = "slpi",
|
|
.ssctl_id = 0x16,
|
|
};
|
|
|
|
static const struct adsp_data sm8150_slpi_resource = {
|
|
.crash_reason_smem = 424,
|
|
.firmware_name = "slpi.mdt",
|
|
.pas_id = 12,
|
|
.has_aggre2_clk = false,
|
|
.auto_boot = true,
|
|
.proxy_pd_names = (char*[]){
|
|
"lcx",
|
|
"lmx",
|
|
NULL
|
|
},
|
|
.load_state = "slpi",
|
|
.ssr_name = "dsps",
|
|
.sysmon_name = "slpi",
|
|
.ssctl_id = 0x16,
|
|
};
|
|
|
|
static const struct adsp_data sm8250_slpi_resource = {
|
|
.crash_reason_smem = 424,
|
|
.firmware_name = "slpi.mdt",
|
|
.pas_id = 12,
|
|
.has_aggre2_clk = false,
|
|
.auto_boot = true,
|
|
.proxy_pd_names = (char*[]){
|
|
"lcx",
|
|
"lmx",
|
|
NULL
|
|
},
|
|
.load_state = "slpi",
|
|
.ssr_name = "dsps",
|
|
.sysmon_name = "slpi",
|
|
.ssctl_id = 0x16,
|
|
};
|
|
|
|
static const struct adsp_data sm8350_slpi_resource = {
|
|
.crash_reason_smem = 424,
|
|
.firmware_name = "slpi.mdt",
|
|
.pas_id = 12,
|
|
.has_aggre2_clk = false,
|
|
.auto_boot = true,
|
|
.proxy_pd_names = (char*[]){
|
|
"lcx",
|
|
"lmx",
|
|
NULL
|
|
},
|
|
.load_state = "slpi",
|
|
.ssr_name = "dsps",
|
|
.sysmon_name = "slpi",
|
|
.ssctl_id = 0x16,
|
|
};
|
|
|
|
static const struct adsp_data wcss_resource_init = {
|
|
.crash_reason_smem = 421,
|
|
.firmware_name = "wcnss.mdt",
|
|
.pas_id = 6,
|
|
.auto_boot = true,
|
|
.ssr_name = "mpss",
|
|
.sysmon_name = "wcnss",
|
|
.ssctl_id = 0x12,
|
|
};
|
|
|
|
static const struct adsp_data sdx55_mpss_resource = {
|
|
.crash_reason_smem = 421,
|
|
.firmware_name = "modem.mdt",
|
|
.pas_id = 4,
|
|
.has_aggre2_clk = false,
|
|
.auto_boot = true,
|
|
.proxy_pd_names = (char*[]){
|
|
"cx",
|
|
"mss",
|
|
NULL
|
|
},
|
|
.ssr_name = "mpss",
|
|
.sysmon_name = "modem",
|
|
.ssctl_id = 0x22,
|
|
};
|
|
|
|
static const struct adsp_data sm8450_mpss_resource = {
|
|
.crash_reason_smem = 421,
|
|
.firmware_name = "modem.mdt",
|
|
.pas_id = 4,
|
|
.minidump_id = 3,
|
|
.has_aggre2_clk = false,
|
|
.auto_boot = false,
|
|
.decrypt_shutdown = true,
|
|
.proxy_pd_names = (char*[]){
|
|
"cx",
|
|
"mss",
|
|
NULL
|
|
},
|
|
.load_state = "modem",
|
|
.ssr_name = "mpss",
|
|
.sysmon_name = "modem",
|
|
.ssctl_id = 0x12,
|
|
};
|
|
|
|
static const struct of_device_id adsp_of_match[] = {
|
|
{ .compatible = "qcom,msm8226-adsp-pil", .data = &adsp_resource_init},
|
|
{ .compatible = "qcom,msm8974-adsp-pil", .data = &adsp_resource_init},
|
|
{ .compatible = "qcom,msm8996-adsp-pil", .data = &msm8996_adsp_resource},
|
|
{ .compatible = "qcom,msm8996-slpi-pil", .data = &slpi_resource_init},
|
|
{ .compatible = "qcom,msm8998-adsp-pas", .data = &msm8996_adsp_resource},
|
|
{ .compatible = "qcom,msm8998-slpi-pas", .data = &slpi_resource_init},
|
|
{ .compatible = "qcom,qcs404-adsp-pas", .data = &adsp_resource_init },
|
|
{ .compatible = "qcom,qcs404-cdsp-pas", .data = &cdsp_resource_init },
|
|
{ .compatible = "qcom,qcs404-wcss-pas", .data = &wcss_resource_init },
|
|
{ .compatible = "qcom,sc7180-mpss-pas", .data = &mpss_resource_init},
|
|
{ .compatible = "qcom,sc7280-mpss-pas", .data = &mpss_resource_init},
|
|
{ .compatible = "qcom,sc8180x-adsp-pas", .data = &sm8150_adsp_resource},
|
|
{ .compatible = "qcom,sc8180x-cdsp-pas", .data = &sm8150_cdsp_resource},
|
|
{ .compatible = "qcom,sc8180x-mpss-pas", .data = &sc8180x_mpss_resource},
|
|
{ .compatible = "qcom,sc8280xp-adsp-pas", .data = &sm8250_adsp_resource},
|
|
{ .compatible = "qcom,sc8280xp-nsp0-pas", .data = &sc8280xp_nsp0_resource},
|
|
{ .compatible = "qcom,sc8280xp-nsp1-pas", .data = &sc8280xp_nsp1_resource},
|
|
{ .compatible = "qcom,sdm660-adsp-pas", .data = &adsp_resource_init},
|
|
{ .compatible = "qcom,sdm845-adsp-pas", .data = &sdm845_adsp_resource_init},
|
|
{ .compatible = "qcom,sdm845-cdsp-pas", .data = &sdm845_cdsp_resource_init},
|
|
{ .compatible = "qcom,sdx55-mpss-pas", .data = &sdx55_mpss_resource},
|
|
{ .compatible = "qcom,sm6350-adsp-pas", .data = &sm6350_adsp_resource},
|
|
{ .compatible = "qcom,sm6350-cdsp-pas", .data = &sm6350_cdsp_resource},
|
|
{ .compatible = "qcom,sm6350-mpss-pas", .data = &mpss_resource_init},
|
|
{ .compatible = "qcom,sm8150-adsp-pas", .data = &sm8150_adsp_resource},
|
|
{ .compatible = "qcom,sm8150-cdsp-pas", .data = &sm8150_cdsp_resource},
|
|
{ .compatible = "qcom,sm8150-mpss-pas", .data = &mpss_resource_init},
|
|
{ .compatible = "qcom,sm8150-slpi-pas", .data = &sm8150_slpi_resource},
|
|
{ .compatible = "qcom,sm8250-adsp-pas", .data = &sm8250_adsp_resource},
|
|
{ .compatible = "qcom,sm8250-cdsp-pas", .data = &sm8250_cdsp_resource},
|
|
{ .compatible = "qcom,sm8250-slpi-pas", .data = &sm8250_slpi_resource},
|
|
{ .compatible = "qcom,sm8350-adsp-pas", .data = &sm8350_adsp_resource},
|
|
{ .compatible = "qcom,sm8350-cdsp-pas", .data = &sm8350_cdsp_resource},
|
|
{ .compatible = "qcom,sm8350-slpi-pas", .data = &sm8350_slpi_resource},
|
|
{ .compatible = "qcom,sm8350-mpss-pas", .data = &mpss_resource_init},
|
|
{ .compatible = "qcom,sm8450-adsp-pas", .data = &sm8350_adsp_resource},
|
|
{ .compatible = "qcom,sm8450-cdsp-pas", .data = &sm8350_cdsp_resource},
|
|
{ .compatible = "qcom,sm8450-slpi-pas", .data = &sm8350_slpi_resource},
|
|
{ .compatible = "qcom,sm8450-mpss-pas", .data = &sm8450_mpss_resource},
|
|
{ },
|
|
};
|
|
MODULE_DEVICE_TABLE(of, adsp_of_match);
|
|
|
|
static struct platform_driver adsp_driver = {
|
|
.probe = adsp_probe,
|
|
.remove = adsp_remove,
|
|
.driver = {
|
|
.name = "qcom_q6v5_pas",
|
|
.of_match_table = adsp_of_match,
|
|
},
|
|
};
|
|
|
|
module_platform_driver(adsp_driver);
|
|
MODULE_DESCRIPTION("Qualcomm Hexagon v5 Peripheral Authentication Service driver");
|
|
MODULE_LICENSE("GPL v2");
|