Commit aed361ad authored by Bjorn Andersson's avatar Bjorn Andersson Committed by Bjorn Andersson

remoteproc: qcom: Introduce WCNSS peripheral image loader

This introduces the peripheral image loader, for loading WCNSS firmware
and boot the core on e.g. MSM8974. The firmware is verified and booted
with the help of the Peripheral Authentication System (PAS) in
TrustZone.
Tested-by: default avatarJohn Stultz <john.stultz@linaro.org>
Signed-off-by: default avatarBjorn Andersson <bjorn.andersson@sonymobile.com>
Signed-off-by: default avatarBjorn Andersson <bjorn.andersson@linaro.org>
parent 3103405f
...@@ -91,6 +91,22 @@ config QCOM_Q6V5_PIL ...@@ -91,6 +91,22 @@ config QCOM_Q6V5_PIL
Say y here to support the Qualcomm Peripherial Image Loader for the Say y here to support the Qualcomm Peripherial Image Loader for the
Hexagon V5 based remote processors. Hexagon V5 based remote processors.
config QCOM_WCNSS_IRIS
tristate
depends on OF && ARCH_QCOM
config QCOM_WCNSS_PIL
tristate "Qualcomm WCNSS Peripheral Image Loader"
depends on OF && ARCH_QCOM
depends on QCOM_SMEM
select QCOM_MDT_LOADER
select QCOM_SCM
select QCOM_WCNSS_IRIS
select REMOTEPROC
help
Say y here to support the Peripheral Image Loader for the Qualcomm
Wireless Connectivity Subsystem.
config ST_REMOTEPROC config ST_REMOTEPROC
tristate "ST remoteproc support" tristate "ST remoteproc support"
depends on ARCH_STI depends on ARCH_STI
......
...@@ -13,4 +13,6 @@ obj-$(CONFIG_WKUP_M3_RPROC) += wkup_m3_rproc.o ...@@ -13,4 +13,6 @@ obj-$(CONFIG_WKUP_M3_RPROC) += wkup_m3_rproc.o
obj-$(CONFIG_DA8XX_REMOTEPROC) += da8xx_remoteproc.o obj-$(CONFIG_DA8XX_REMOTEPROC) += da8xx_remoteproc.o
obj-$(CONFIG_QCOM_MDT_LOADER) += qcom_mdt_loader.o obj-$(CONFIG_QCOM_MDT_LOADER) += qcom_mdt_loader.o
obj-$(CONFIG_QCOM_Q6V5_PIL) += qcom_q6v5_pil.o obj-$(CONFIG_QCOM_Q6V5_PIL) += qcom_q6v5_pil.o
obj-$(CONFIG_QCOM_WCNSS_IRIS) += qcom_wcnss_iris.o
obj-$(CONFIG_QCOM_WCNSS_PIL) += qcom_wcnss.o
obj-$(CONFIG_ST_REMOTEPROC) += st_remoteproc.o obj-$(CONFIG_ST_REMOTEPROC) += st_remoteproc.o
This diff is collapsed.
#ifndef __QCOM_WNCSS_H__
#define __QCOM_WNCSS_H__
struct qcom_iris;
struct qcom_wcnss;
struct wcnss_vreg_info {
const char * const name;
int min_voltage;
int max_voltage;
int load_uA;
bool super_turbo;
};
int qcom_iris_enable(struct qcom_iris *iris);
void qcom_iris_disable(struct qcom_iris *iris);
void qcom_wcnss_assign_iris(struct qcom_wcnss *wcnss, struct qcom_iris *iris, bool use_48mhz_xo);
#endif
/*
* Qualcomm Wireless Connectivity Subsystem Iris driver
*
* Copyright (C) 2016 Linaro Ltd
* Copyright (C) 2014 Sony Mobile Communications AB
* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include "qcom_wcnss.h"
struct qcom_iris {
struct device *dev;
struct clk *xo_clk;
struct regulator_bulk_data *vregs;
size_t num_vregs;
};
struct iris_data {
const struct wcnss_vreg_info *vregs;
size_t num_vregs;
bool use_48mhz_xo;
};
static const struct iris_data wcn3620_data = {
.vregs = (struct wcnss_vreg_info[]) {
{ "vddxo", 1800000, 1800000, 10000 },
{ "vddrfa", 1300000, 1300000, 100000 },
{ "vddpa", 3300000, 3300000, 515000 },
{ "vdddig", 1800000, 1800000, 10000 },
},
.num_vregs = 4,
.use_48mhz_xo = false,
};
static const struct iris_data wcn3660_data = {
.vregs = (struct wcnss_vreg_info[]) {
{ "vddxo", 1800000, 1800000, 10000 },
{ "vddrfa", 1300000, 1300000, 100000 },
{ "vddpa", 2900000, 3000000, 515000 },
{ "vdddig", 1200000, 1225000, 10000 },
},
.num_vregs = 4,
.use_48mhz_xo = true,
};
static const struct iris_data wcn3680_data = {
.vregs = (struct wcnss_vreg_info[]) {
{ "vddxo", 1800000, 1800000, 10000 },
{ "vddrfa", 1300000, 1300000, 100000 },
{ "vddpa", 3300000, 3300000, 515000 },
{ "vdddig", 1800000, 1800000, 10000 },
},
.num_vregs = 4,
.use_48mhz_xo = true,
};
int qcom_iris_enable(struct qcom_iris *iris)
{
int ret;
ret = regulator_bulk_enable(iris->num_vregs, iris->vregs);
if (ret)
return ret;
ret = clk_prepare_enable(iris->xo_clk);
if (ret) {
dev_err(iris->dev, "failed to enable xo clk\n");
goto disable_regulators;
}
return 0;
disable_regulators:
regulator_bulk_disable(iris->num_vregs, iris->vregs);
return ret;
}
EXPORT_SYMBOL_GPL(qcom_iris_enable);
void qcom_iris_disable(struct qcom_iris *iris)
{
clk_disable_unprepare(iris->xo_clk);
regulator_bulk_disable(iris->num_vregs, iris->vregs);
}
EXPORT_SYMBOL_GPL(qcom_iris_disable);
static int qcom_iris_probe(struct platform_device *pdev)
{
const struct iris_data *data;
struct qcom_wcnss *wcnss;
struct qcom_iris *iris;
int ret;
int i;
iris = devm_kzalloc(&pdev->dev, sizeof(struct qcom_iris), GFP_KERNEL);
if (!iris)
return -ENOMEM;
data = of_device_get_match_data(&pdev->dev);
wcnss = dev_get_drvdata(pdev->dev.parent);
iris->xo_clk = devm_clk_get(&pdev->dev, "xo");
if (IS_ERR(iris->xo_clk)) {
if (PTR_ERR(iris->xo_clk) != -EPROBE_DEFER)
dev_err(&pdev->dev, "failed to acquire xo clk\n");
return PTR_ERR(iris->xo_clk);
}
iris->num_vregs = data->num_vregs;
iris->vregs = devm_kcalloc(&pdev->dev,
iris->num_vregs,
sizeof(struct regulator_bulk_data),
GFP_KERNEL);
if (!iris->vregs)
return -ENOMEM;
for (i = 0; i < iris->num_vregs; i++)
iris->vregs[i].supply = data->vregs[i].name;
ret = devm_regulator_bulk_get(&pdev->dev, iris->num_vregs, iris->vregs);
if (ret) {
dev_err(&pdev->dev, "failed to get regulators\n");
return ret;
}
for (i = 0; i < iris->num_vregs; i++) {
if (data->vregs[i].max_voltage)
regulator_set_voltage(iris->vregs[i].consumer,
data->vregs[i].min_voltage,
data->vregs[i].max_voltage);
if (data->vregs[i].load_uA)
regulator_set_load(iris->vregs[i].consumer,
data->vregs[i].load_uA);
}
qcom_wcnss_assign_iris(wcnss, iris, data->use_48mhz_xo);
return 0;
}
static int qcom_iris_remove(struct platform_device *pdev)
{
struct qcom_wcnss *wcnss = dev_get_drvdata(pdev->dev.parent);
qcom_wcnss_assign_iris(wcnss, NULL, false);
return 0;
}
static const struct of_device_id iris_of_match[] = {
{ .compatible = "qcom,wcn3620", .data = &wcn3620_data },
{ .compatible = "qcom,wcn3660", .data = &wcn3660_data },
{ .compatible = "qcom,wcn3680", .data = &wcn3680_data },
{}
};
static struct platform_driver wcnss_driver = {
.probe = qcom_iris_probe,
.remove = qcom_iris_remove,
.driver = {
.name = "qcom-iris",
.of_match_table = iris_of_match,
},
};
module_platform_driver(wcnss_driver);
MODULE_DESCRIPTION("Qualcomm Wireless Subsystem Iris driver");
MODULE_LICENSE("GPL v2");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment