2022-01-29 11:02:37

by Bjorn Andersson

[permalink] [raw]
Subject: [PATCH 00/13] soc: qcom: mdt_loader: Support Qualcomm SM8450

The Qualcomm SM8450 platform comes with both some smaller changes in the
firmware packaging and a new requirement to hold onto the metadata buffer until
PAS auth_and_reset has been completed.

Extend the PAS api and rework the mdt_loader to meet these new requirements,
then wire this up with the PAS remoteproc driver and finally add the SM8450
remoteproc instances.

Bjorn Andersson (13):
firmware: qcom: scm: Introduce pas_metadata context
soc: qcom: mdt_loader: Split out split-file-loader
soc: qcom: mdt_loader: Allow hash segment to be split out
soc: qcom: mdt_loader: Allow hash to reside in any segment
soc: qcom: mdt_loader: Extend check for split firmware
soc: qcom: mdt_loader: Reorder parts of __qcom_mdt_load()
soc: qcom: mdt_loader: Always invoke PAS mem_setup
soc: qcom: mdt_loader: Extract PAS operations
remoteproc: qcom: pas: Carry PAS metadata context
dt-bindings: remoteproc: qcom: pas: Add SM8450 PAS compatibles
remoteproc: qcom: pas: Add SM8450 remoteproc support
arm64: dts: qcom: sm8450: Add remoteproc enablers and instances
arm64: dts: qcom: sm8450-qrd: Enable remoteproc instances

.../bindings/remoteproc/qcom,adsp.yaml | 16 +
arch/arm64/boot/dts/qcom/sm8450-qrd.dts | 20 ++
arch/arm64/boot/dts/qcom/sm8450.dtsi | 297 ++++++++++++++++++
drivers/firmware/qcom_scm.c | 39 ++-
drivers/remoteproc/qcom_q6v5_mss.c | 7 +-
drivers/remoteproc/qcom_q6v5_pas.c | 36 ++-
drivers/soc/qcom/mdt_loader.c | 232 +++++++++-----
include/linux/qcom_scm.h | 10 +-
include/linux/soc/qcom/mdt_loader.h | 17 +-
9 files changed, 579 insertions(+), 95 deletions(-)

--
2.33.1


2022-01-29 11:57:45

by Bjorn Andersson

[permalink] [raw]
Subject: [PATCH 01/13] firmware: qcom: scm: Introduce pas_metadata context

Starting with Qualcomm SM8450, some new security enhancements has been
done in the secure world, which results in the requirement to keep the
metadata segment accessible by the secure world from init_image() until
auth_and_reset().

Introduce a "PAS metadata context" object that can be passed to
init_image() for tracking the mapped memory and a related release
function for client drivers to release the mapping once either
auth_and_reset() has been invoked or in error handling paths on the way
there.

Signed-off-by: Bjorn Andersson <[email protected]>
---
drivers/firmware/qcom_scm.c | 39 ++++++++++++++++++++++++++++++-----
drivers/soc/qcom/mdt_loader.c | 2 +-
include/linux/qcom_scm.h | 10 ++++++++-
3 files changed, 44 insertions(+), 7 deletions(-)

diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index 7db8066b19fd..3218d13cbf83 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -435,10 +435,16 @@ static void qcom_scm_set_download_mode(bool enable)
* and optional blob of data used for authenticating the metadata
* and the rest of the firmware
* @size: size of the metadata
+ * @ctx: optional metadata context
*
- * Returns 0 on success.
+ * Return: 0 on success.
+ *
+ * Upon successful return, the PAS metadata context (@ctx) will be used to
+ * track the metadata allocation, this needs to be released by invoking
+ * qcom_scm_pas_metadata_release() by the caller.
*/
-int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size)
+int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size,
+ struct qcom_scm_pas_metadata *ctx)
{
dma_addr_t mdata_phys;
void *mdata_buf;
@@ -467,7 +473,7 @@ int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size)

ret = qcom_scm_clk_enable();
if (ret)
- goto free_metadata;
+ goto out;

desc.args[1] = mdata_phys;

@@ -475,13 +481,36 @@ int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size)

qcom_scm_clk_disable();

-free_metadata:
- dma_free_coherent(__scm->dev, size, mdata_buf, mdata_phys);
+out:
+ if (ret < 0 || !ctx) {
+ dma_free_coherent(__scm->dev, size, mdata_buf, mdata_phys);
+ } else if (ctx) {
+ ctx->ptr = mdata_buf;
+ ctx->phys = mdata_phys;
+ ctx->size = size;
+ }

return ret ? : res.result[0];
}
EXPORT_SYMBOL(qcom_scm_pas_init_image);

+/**
+ * qcom_scm_pas_metadata_release() - release metadata context
+ * @ctx: metadata context
+ */
+void qcom_scm_pas_metadata_release(struct qcom_scm_pas_metadata *ctx)
+{
+ if (!ctx->ptr)
+ return;
+
+ dma_free_coherent(__scm->dev, ctx->size, ctx->ptr, ctx->phys);
+
+ ctx->ptr = NULL;
+ ctx->phys = 0;
+ ctx->size = 0;
+}
+EXPORT_SYMBOL(qcom_scm_pas_metadata_release);
+
/**
* qcom_scm_pas_mem_setup() - Prepare the memory related to a given peripheral
* for firmware loading
diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index 72fc2b539213..b00586db5391 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -171,7 +171,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
goto out;
}

- ret = qcom_scm_pas_init_image(pas_id, metadata, metadata_len);
+ ret = qcom_scm_pas_init_image(pas_id, metadata, metadata_len, NULL);

kfree(metadata);
if (ret) {
diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h
index 81cad9e1e412..4d8371410b05 100644
--- a/include/linux/qcom_scm.h
+++ b/include/linux/qcom_scm.h
@@ -68,8 +68,16 @@ extern int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus);
extern void qcom_scm_cpu_power_down(u32 flags);
extern int qcom_scm_set_remote_state(u32 state, u32 id);

+struct qcom_scm_pas_metadata {
+ void *ptr;
+ dma_addr_t phys;
+ ssize_t size;
+};
+
extern int qcom_scm_pas_init_image(u32 peripheral, const void *metadata,
- size_t size);
+ size_t size,
+ struct qcom_scm_pas_metadata *ctx);
+void qcom_scm_pas_metadata_release(struct qcom_scm_pas_metadata *ctx);
extern int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr,
phys_addr_t size);
extern int qcom_scm_pas_auth_and_reset(u32 peripheral);
--
2.33.1

2022-01-29 11:57:46

by Bjorn Andersson

[permalink] [raw]
Subject: [PATCH 02/13] soc: qcom: mdt_loader: Split out split-file-loader

Spotted in a SM8450 device, the hash metadata segment is split out in a
separate .bNN file which means that the logic for loading split out
segmenents needs to be duplicated in qcom_mdt_read_metadata().

Split out the existing logic to a helper function that can be used in
both code paths.

Signed-off-by: Bjorn Andersson <[email protected]>
---
drivers/soc/qcom/mdt_loader.c | 72 ++++++++++++++++++++---------------
1 file changed, 41 insertions(+), 31 deletions(-)

diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index b00586db5391..c9e5bdfac371 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -31,6 +31,44 @@ static bool mdt_phdr_valid(const struct elf32_phdr *phdr)
return true;
}

+static ssize_t mdt_load_split_segment(void *ptr, const struct elf32_phdr *phdrs,
+ unsigned int segment, const char *fw_name,
+ struct device *dev)
+{
+ const struct elf32_phdr *phdr = &phdrs[segment];
+ const struct firmware *seg_fw;
+ char *seg_name;
+ ssize_t ret;
+
+ if (strlen(fw_name) < 4)
+ return -EINVAL;
+
+ seg_name = kstrdup(fw_name, GFP_KERNEL);
+ if (!seg_name)
+ return -ENOMEM;
+
+ sprintf(seg_name + strlen(fw_name) - 3, "b%02d", segment);
+ ret = request_firmware_into_buf(&seg_fw, seg_name, dev,
+ ptr, phdr->p_filesz);
+ if (ret) {
+ dev_err(dev, "error %zd loading %s\n", ret, seg_name);
+ kfree(seg_name);
+ return ret;
+ }
+
+ if (seg_fw->size != phdr->p_filesz) {
+ dev_err(dev,
+ "failed to load segment %d from truncated file %s\n",
+ segment, seg_name);
+ ret = -EINVAL;
+ }
+
+ release_firmware(seg_fw);
+ kfree(seg_name);
+
+ return ret;
+}
+
/**
* qcom_mdt_get_size() - acquire size of the memory region needed to load mdt
* @fw: firmware object for the mdt file
@@ -127,22 +165,19 @@ void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len)
EXPORT_SYMBOL_GPL(qcom_mdt_read_metadata);

static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
- const char *firmware, int pas_id, void *mem_region,
+ const char *fw_name, int pas_id, void *mem_region,
phys_addr_t mem_phys, size_t mem_size,
phys_addr_t *reloc_base, bool pas_init)
{
const struct elf32_phdr *phdrs;
const struct elf32_phdr *phdr;
const struct elf32_hdr *ehdr;
- const struct firmware *seg_fw;
phys_addr_t mem_reloc;
phys_addr_t min_addr = PHYS_ADDR_MAX;
phys_addr_t max_addr = 0;
size_t metadata_len;
- size_t fw_name_len;
ssize_t offset;
void *metadata;
- char *fw_name;
bool relocate = false;
void *ptr;
int ret = 0;
@@ -154,14 +189,6 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
ehdr = (struct elf32_hdr *)fw->data;
phdrs = (struct elf32_phdr *)(ehdr + 1);

- fw_name_len = strlen(firmware);
- if (fw_name_len <= 4)
- return -EINVAL;
-
- fw_name = kstrdup(firmware, GFP_KERNEL);
- if (!fw_name)
- return -ENOMEM;
-
if (pas_init) {
metadata = qcom_mdt_read_metadata(fw, &metadata_len);
if (IS_ERR(metadata)) {
@@ -258,25 +285,9 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
memcpy(ptr, fw->data + phdr->p_offset, phdr->p_filesz);
} else if (phdr->p_filesz) {
/* Firmware not large enough, load split-out segments */
- sprintf(fw_name + fw_name_len - 3, "b%02d", i);
- ret = request_firmware_into_buf(&seg_fw, fw_name, dev,
- ptr, phdr->p_filesz);
- if (ret) {
- dev_err(dev, "error %d loading %s\n",
- ret, fw_name);
+ ret = mdt_load_split_segment(ptr, phdrs, i, fw_name, dev);
+ if (ret)
break;
- }
-
- if (seg_fw->size != phdr->p_filesz) {
- dev_err(dev,
- "failed to load segment %d from truncated file %s\n",
- i, fw_name);
- release_firmware(seg_fw);
- ret = -EINVAL;
- break;
- }
-
- release_firmware(seg_fw);
}

if (phdr->p_memsz > phdr->p_filesz)
@@ -287,7 +298,6 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
*reloc_base = mem_reloc;

out:
- kfree(fw_name);

return ret;
}
--
2.33.1

2022-01-29 11:57:47

by Bjorn Andersson

[permalink] [raw]
Subject: [PATCH 03/13] soc: qcom: mdt_loader: Allow hash segment to be split out

It's been observed that some firmware found in a Qualcomm SM8450 device
has the hash table in a separate .bNN file. Use the newly extracted
helper function to load this segment from the separate file, if it's
determined that the hashes are not part of the already loaded firmware.

In order to do this, the function needs access to the firmware basename
and to provide more useful error messages a struct device to associate
the errors with.

Signed-off-by: Bjorn Andersson <[email protected]>
---
drivers/remoteproc/qcom_q6v5_mss.c | 7 ++++---
drivers/soc/qcom/mdt_loader.c | 29 +++++++++++++++++++++--------
include/linux/soc/qcom/mdt_loader.h | 6 ++++--
3 files changed, 29 insertions(+), 13 deletions(-)

diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
index 43ea8455546c..a2c231a17b2b 100644
--- a/drivers/remoteproc/qcom_q6v5_mss.c
+++ b/drivers/remoteproc/qcom_q6v5_mss.c
@@ -928,7 +928,8 @@ static void q6v5proc_halt_axi_port(struct q6v5 *qproc,
regmap_write(halt_map, offset + AXI_HALTREQ_REG, 0);
}

-static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw)
+static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw,
+ const char *fw_name)
{
unsigned long dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS;
dma_addr_t phys;
@@ -939,7 +940,7 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw)
void *ptr;
int ret;

- metadata = qcom_mdt_read_metadata(fw, &size);
+ metadata = qcom_mdt_read_metadata(fw, &size, fw_name, qproc->dev);
if (IS_ERR(metadata))
return PTR_ERR(metadata);

@@ -1289,7 +1290,7 @@ static int q6v5_mpss_load(struct q6v5 *qproc)
/* Initialize the RMB validator */
writel(0, qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG);

- ret = q6v5_mpss_init_image(qproc, fw);
+ ret = q6v5_mpss_init_image(qproc, fw, qproc->hexagon_mdt_image);
if (ret)
goto release_firmware;

diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index c9e5bdfac371..4372d8e38b29 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -121,13 +121,15 @@ EXPORT_SYMBOL_GPL(qcom_mdt_get_size);
*
* Return: pointer to data, or ERR_PTR()
*/
-void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len)
+void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len,
+ const char *fw_name, struct device *dev)
{
const struct elf32_phdr *phdrs;
const struct elf32_hdr *ehdr;
size_t hash_offset;
size_t hash_size;
size_t ehdr_size;
+ ssize_t ret;
void *data;

ehdr = (struct elf32_hdr *)fw->data;
@@ -149,14 +151,25 @@ void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len)
if (!data)
return ERR_PTR(-ENOMEM);

- /* Is the header and hash already packed */
- if (ehdr_size + hash_size == fw->size)
+ /* Copy ELF header */
+ memcpy(data, fw->data, ehdr_size);
+
+ if (ehdr_size + hash_size == fw->size) {
+ /* Firmware is split and hash is packed following the ELF header */
hash_offset = phdrs[0].p_filesz;
- else
+ memcpy(data + ehdr_size, fw->data + hash_offset, hash_size);
+ } else if (phdrs[1].p_offset + hash_size <= fw->size) {
+ /* Hash is in its own segment, but within the loaded file */
hash_offset = phdrs[1].p_offset;
-
- memcpy(data, fw->data, ehdr_size);
- memcpy(data + ehdr_size, fw->data + hash_offset, hash_size);
+ memcpy(data + ehdr_size, fw->data + hash_offset, hash_size);
+ } else {
+ /* Hash is in its own segment, beyond the loaded file */
+ ret = mdt_load_split_segment(data + ehdr_size, phdrs, 1, fw_name, dev);
+ if (ret) {
+ kfree(data);
+ return ERR_PTR(ret);
+ }
+ }

*data_len = ehdr_size + hash_size;

@@ -190,7 +203,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
phdrs = (struct elf32_phdr *)(ehdr + 1);

if (pas_init) {
- metadata = qcom_mdt_read_metadata(fw, &metadata_len);
+ metadata = qcom_mdt_read_metadata(fw, &metadata_len, fw_name, dev);
if (IS_ERR(metadata)) {
ret = PTR_ERR(metadata);
dev_err(dev, "error %d reading firmware %s metadata\n",
diff --git a/include/linux/soc/qcom/mdt_loader.h b/include/linux/soc/qcom/mdt_loader.h
index afd47217996b..46bdb7bace9a 100644
--- a/include/linux/soc/qcom/mdt_loader.h
+++ b/include/linux/soc/qcom/mdt_loader.h
@@ -23,7 +23,8 @@ int qcom_mdt_load_no_init(struct device *dev, const struct firmware *fw,
const char *fw_name, int pas_id, void *mem_region,
phys_addr_t mem_phys, size_t mem_size,
phys_addr_t *reloc_base);
-void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len);
+void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len,
+ const char *fw_name, struct device *dev);

#else /* !IS_ENABLED(CONFIG_QCOM_MDT_LOADER) */

@@ -51,7 +52,8 @@ static inline int qcom_mdt_load_no_init(struct device *dev,
}

static inline void *qcom_mdt_read_metadata(const struct firmware *fw,
- size_t *data_len)
+ size_t *data_len, const char *fw_name,
+ struct device *dev)
{
return ERR_PTR(-ENODEV);
}
--
2.33.1

2022-01-29 11:57:49

by Bjorn Andersson

[permalink] [raw]
Subject: [PATCH 04/13] soc: qcom: mdt_loader: Allow hash to reside in any segment

It's been observed that some firmware found on Qualcomm SM8450 devices
carries the hash segment as the last segment in the ELF. Extend the
support to allow picking the hash from any segment in the MDT/MBN.

Signed-off-by: Bjorn Andersson <[email protected]>
---
drivers/soc/qcom/mdt_loader.c | 21 ++++++++++++++++-----
1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index 4372d8e38b29..c5bd13b05c1a 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -126,9 +126,11 @@ void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len,
{
const struct elf32_phdr *phdrs;
const struct elf32_hdr *ehdr;
+ unsigned int hash_segment = 0;
size_t hash_offset;
size_t hash_size;
size_t ehdr_size;
+ unsigned int i;
ssize_t ret;
void *data;

@@ -141,11 +143,20 @@ void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len,
if (phdrs[0].p_type == PT_LOAD)
return ERR_PTR(-EINVAL);

- if ((phdrs[1].p_flags & QCOM_MDT_TYPE_MASK) != QCOM_MDT_TYPE_HASH)
+ for (i = 1; i < ehdr->e_phnum; i++) {
+ if ((phdrs[i].p_flags & QCOM_MDT_TYPE_MASK) == QCOM_MDT_TYPE_HASH) {
+ hash_segment = i;
+ break;
+ }
+ }
+
+ if (!hash_segment) {
+ dev_err(dev, "no hash segment found in %s\n", fw_name);
return ERR_PTR(-EINVAL);
+ }

ehdr_size = phdrs[0].p_filesz;
- hash_size = phdrs[1].p_filesz;
+ hash_size = phdrs[hash_segment].p_filesz;

data = kmalloc(ehdr_size + hash_size, GFP_KERNEL);
if (!data)
@@ -158,13 +169,13 @@ void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len,
/* Firmware is split and hash is packed following the ELF header */
hash_offset = phdrs[0].p_filesz;
memcpy(data + ehdr_size, fw->data + hash_offset, hash_size);
- } else if (phdrs[1].p_offset + hash_size <= fw->size) {
+ } else if (phdrs[hash_segment].p_offset + hash_size <= fw->size) {
/* Hash is in its own segment, but within the loaded file */
- hash_offset = phdrs[1].p_offset;
+ hash_offset = phdrs[hash_segment].p_offset;
memcpy(data + ehdr_size, fw->data + hash_offset, hash_size);
} else {
/* Hash is in its own segment, beyond the loaded file */
- ret = mdt_load_split_segment(data + ehdr_size, phdrs, 1, fw_name, dev);
+ ret = mdt_load_split_segment(data + ehdr_size, phdrs, hash_segment, fw_name, dev);
if (ret) {
kfree(data);
return ERR_PTR(ret);
--
2.33.1

2022-01-29 11:57:57

by Bjorn Andersson

[permalink] [raw]
Subject: [PATCH 05/13] soc: qcom: mdt_loader: Extend check for split firmware

Some of the Qualcomm SM8450 firmware files are padded such that the
start of the first segment falls within the .mdt file but the segment to
be loaded is stored as a separate .bNN file.

Extend the condition to only attempt to read a segment inline if the
entire segment would be available.

Signed-off-by: Bjorn Andersson <[email protected]>
---
drivers/soc/qcom/mdt_loader.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index c5bd13b05c1a..37e2e734bc5d 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -297,7 +297,8 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,

ptr = mem_region + offset;

- if (phdr->p_filesz && phdr->p_offset < fw->size) {
+ if (phdr->p_filesz && phdr->p_offset < fw->size &&
+ phdr->p_offset + phdr->p_filesz < fw->size) {
/* Firmware is large enough to be non-split */
if (phdr->p_offset + phdr->p_filesz > fw->size) {
dev_err(dev, "file %s segment %d would be truncated\n",
--
2.33.1

2022-01-29 11:58:05

by Bjorn Andersson

[permalink] [raw]
Subject: [PATCH 06/13] soc: qcom: mdt_loader: Reorder parts of __qcom_mdt_load()

Move the traversal of the program headers to the start of the function,
to make sure that min_ and max_addr are in scope as the call to
qcom_scm_pas_mem_setup() is moved in the next commit.

Signed-off-by: Bjorn Andersson <[email protected]>
---
drivers/soc/qcom/mdt_loader.c | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index 37e2e734bc5d..ee991784a738 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -213,6 +213,22 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
ehdr = (struct elf32_hdr *)fw->data;
phdrs = (struct elf32_phdr *)(ehdr + 1);

+ for (i = 0; i < ehdr->e_phnum; i++) {
+ phdr = &phdrs[i];
+
+ if (!mdt_phdr_valid(phdr))
+ continue;
+
+ if (phdr->p_flags & QCOM_MDT_RELOCATABLE)
+ relocate = true;
+
+ if (phdr->p_paddr < min_addr)
+ min_addr = phdr->p_paddr;
+
+ if (phdr->p_paddr + phdr->p_memsz > max_addr)
+ max_addr = ALIGN(phdr->p_paddr + phdr->p_memsz, SZ_4K);
+ }
+
if (pas_init) {
metadata = qcom_mdt_read_metadata(fw, &metadata_len, fw_name, dev);
if (IS_ERR(metadata)) {
@@ -233,22 +249,6 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
}
}

- for (i = 0; i < ehdr->e_phnum; i++) {
- phdr = &phdrs[i];
-
- if (!mdt_phdr_valid(phdr))
- continue;
-
- if (phdr->p_flags & QCOM_MDT_RELOCATABLE)
- relocate = true;
-
- if (phdr->p_paddr < min_addr)
- min_addr = phdr->p_paddr;
-
- if (phdr->p_paddr + phdr->p_memsz > max_addr)
- max_addr = ALIGN(phdr->p_paddr + phdr->p_memsz, SZ_4K);
- }
-
if (relocate) {
if (pas_init) {
ret = qcom_scm_pas_mem_setup(pas_id, mem_phys,
--
2.33.1

2022-01-29 11:58:06

by Bjorn Andersson

[permalink] [raw]
Subject: [PATCH 07/13] soc: qcom: mdt_loader: Always invoke PAS mem_setup

After spelunking various old kernel trees no finds has been found
indicating that the PAS mem_setup call should actually be made
conditional on the image being relocatable.

Group the two PAS operations together, to facilitate splitting them out
in a following patch.

Signed-off-by: Bjorn Andersson <[email protected]>
---
drivers/soc/qcom/mdt_loader.c | 19 ++++++++-----------
1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index ee991784a738..c8d43dc50cff 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -247,20 +247,17 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
ret, fw_name);
goto out;
}
- }

- if (relocate) {
- if (pas_init) {
- ret = qcom_scm_pas_mem_setup(pas_id, mem_phys,
- max_addr - min_addr);
- if (ret) {
- /* Unable to set up relocation */
- dev_err(dev, "error %d setting up firmware %s\n",
- ret, fw_name);
- goto out;
- }
+ ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr);
+ if (ret) {
+ /* Unable to set up relocation */
+ dev_err(dev, "error %d setting up firmware %s\n",
+ ret, fw_name);
+ goto out;
}
+ }

+ if (relocate) {
/*
* The image is relocatable, so offset each segment based on
* the lowest segment address.
--
2.33.1

2022-01-29 11:58:10

by Bjorn Andersson

[permalink] [raw]
Subject: [PATCH 10/13] dt-bindings: remoteproc: qcom: pas: Add SM8450 PAS compatibles

The Qualcomm SM8450 has the usual audio, compute, sensor and modem
remoteprocs, add compatibles to the documentation for these.

Signed-off-by: Bjorn Andersson <[email protected]>
---
.../bindings/remoteproc/qcom,adsp.yaml | 16 ++++++++++++++++
1 file changed, 16 insertions(+)

diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml
index c635c181d2c2..64c182428e94 100644
--- a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml
@@ -47,6 +47,10 @@ properties:
- qcom,sm8350-cdsp-pas
- qcom,sm8350-slpi-pas
- qcom,sm8350-mpss-pas
+ - qcom,sm8450-adsp-pas
+ - qcom,sm8450-cdsp-pas
+ - qcom,sm8450-mpss-pas
+ - qcom,sm8450-slpi-pas

reg:
maxItems: 1
@@ -175,6 +179,10 @@ allOf:
- qcom,sm8350-cdsp-pas
- qcom,sm8350-slpi-pas
- qcom,sm8350-mpss-pas
+ - qcom,sm8450-adsp-pas
+ - qcom,sm8450-cdsp-pas
+ - qcom,sm8450-slpi-pas
+ - qcom,sm8450-mpss-pas
then:
properties:
clocks:
@@ -283,6 +291,9 @@ allOf:
- qcom,sm8350-adsp-pas
- qcom,sm8350-cdsp-pas
- qcom,sm8350-slpi-pas
+ - qcom,sm8450-adsp-pas
+ - qcom,sm8450-cdsp-pas
+ - qcom,sm8450-slpi-pas
then:
properties:
interrupts:
@@ -312,6 +323,7 @@ allOf:
- qcom,sm6350-mpss-pas
- qcom,sm8150-mpss-pas
- qcom,sm8350-mpss-pas
+ - qcom,sm8450-mpss-pas
then:
properties:
interrupts:
@@ -434,6 +446,7 @@ allOf:
- qcom,sm6350-mpss-pas
- qcom,sm8150-mpss-pas
- qcom,sm8350-mpss-pas
+ - qcom,sm8450-mpss-pas
then:
properties:
power-domains:
@@ -458,6 +471,8 @@ allOf:
- qcom,sm8250-slpi-pas
- qcom,sm8350-adsp-pas
- qcom,sm8350-slpi-pas
+ - qcom,sm8450-adsp-pas
+ - qcom,sm8450-slpi-pas
then:
properties:
power-domains:
@@ -475,6 +490,7 @@ allOf:
contains:
enum:
- qcom,sm8350-cdsp-pas
+ - qcom,sm8450-cdsp-pas
then:
properties:
power-domains:
--
2.33.1

2022-01-29 11:58:13

by Bjorn Andersson

[permalink] [raw]
Subject: [PATCH 08/13] soc: qcom: mdt_loader: Extract PAS operations

Rather than passing a boolean to indicate if the PAS operations should
be performed from within __mdt_load(), extract them to their own helper
function.

This will allow clients to invoke this directly, with some
qcom_scm_pas_metadata context that they later needs to release, without
further having to complicate the prototype of qcom_mdt_load().

Signed-off-by: Bjorn Andersson <[email protected]>
---
drivers/soc/qcom/mdt_loader.c | 110 +++++++++++++++++++---------
include/linux/soc/qcom/mdt_loader.h | 11 +++
2 files changed, 85 insertions(+), 36 deletions(-)

diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index c8d43dc50cff..f0b1d969567c 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -188,6 +188,74 @@ void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len,
}
EXPORT_SYMBOL_GPL(qcom_mdt_read_metadata);

+/**
+ * qcom_mdt_pas_init() - initialize PAS region for firmware loading
+ * @dev: device handle to associate resources with
+ * @fw: firmware object for the mdt file
+ * @firmware: name of the firmware, for construction of segment file names
+ * @pas_id: PAS identifier
+ * @mem_phys: physical address of allocated memory region
+ * @ctx: PAS metadata context, to be released by caller
+ *
+ * Returns 0 on success, negative errno otherwise.
+ */
+int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw,
+ const char *fw_name, int pas_id, phys_addr_t mem_phys,
+ struct qcom_scm_pas_metadata *ctx)
+{
+ const struct elf32_phdr *phdrs;
+ const struct elf32_phdr *phdr;
+ const struct elf32_hdr *ehdr;
+ phys_addr_t min_addr = PHYS_ADDR_MAX;
+ phys_addr_t max_addr = 0;
+ size_t metadata_len;
+ void *metadata;
+ int ret;
+ int i;
+
+ ehdr = (struct elf32_hdr *)fw->data;
+ phdrs = (struct elf32_phdr *)(ehdr + 1);
+
+ for (i = 0; i < ehdr->e_phnum; i++) {
+ phdr = &phdrs[i];
+
+ if (!mdt_phdr_valid(phdr))
+ continue;
+
+ if (phdr->p_paddr < min_addr)
+ min_addr = phdr->p_paddr;
+
+ if (phdr->p_paddr + phdr->p_memsz > max_addr)
+ max_addr = ALIGN(phdr->p_paddr + phdr->p_memsz, SZ_4K);
+ }
+
+ metadata = qcom_mdt_read_metadata(fw, &metadata_len, fw_name, dev);
+ if (IS_ERR(metadata)) {
+ ret = PTR_ERR(metadata);
+ dev_err(dev, "error %d reading firmware %s metadata\n", ret, fw_name);
+ goto out;
+ }
+
+ ret = qcom_scm_pas_init_image(pas_id, metadata, metadata_len, ctx);
+ kfree(metadata);
+ if (ret) {
+ /* Invalid firmware metadata */
+ dev_err(dev, "error %d initializing firmware %s\n", ret, fw_name);
+ goto out;
+ }
+
+ ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr);
+ if (ret) {
+ /* Unable to set up relocation */
+ dev_err(dev, "error %d setting up firmware %s\n", ret, fw_name);
+ goto out;
+ }
+
+out:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(qcom_mdt_pas_init);
+
static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
const char *fw_name, int pas_id, void *mem_region,
phys_addr_t mem_phys, size_t mem_size,
@@ -198,10 +266,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
const struct elf32_hdr *ehdr;
phys_addr_t mem_reloc;
phys_addr_t min_addr = PHYS_ADDR_MAX;
- phys_addr_t max_addr = 0;
- size_t metadata_len;
ssize_t offset;
- void *metadata;
bool relocate = false;
void *ptr;
int ret = 0;
@@ -224,37 +289,6 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,

if (phdr->p_paddr < min_addr)
min_addr = phdr->p_paddr;
-
- if (phdr->p_paddr + phdr->p_memsz > max_addr)
- max_addr = ALIGN(phdr->p_paddr + phdr->p_memsz, SZ_4K);
- }
-
- if (pas_init) {
- metadata = qcom_mdt_read_metadata(fw, &metadata_len, fw_name, dev);
- if (IS_ERR(metadata)) {
- ret = PTR_ERR(metadata);
- dev_err(dev, "error %d reading firmware %s metadata\n",
- ret, fw_name);
- goto out;
- }
-
- ret = qcom_scm_pas_init_image(pas_id, metadata, metadata_len, NULL);
-
- kfree(metadata);
- if (ret) {
- /* Invalid firmware metadata */
- dev_err(dev, "error %d initializing firmware %s\n",
- ret, fw_name);
- goto out;
- }
-
- ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr);
- if (ret) {
- /* Unable to set up relocation */
- dev_err(dev, "error %d setting up firmware %s\n",
- ret, fw_name);
- goto out;
- }
}

if (relocate) {
@@ -319,8 +353,6 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
if (reloc_base)
*reloc_base = mem_reloc;

-out:
-
return ret;
}

@@ -342,6 +374,12 @@ int qcom_mdt_load(struct device *dev, const struct firmware *fw,
phys_addr_t mem_phys, size_t mem_size,
phys_addr_t *reloc_base)
{
+ int ret;
+
+ ret = qcom_mdt_pas_init(dev, fw, firmware, pas_id, mem_phys, NULL);
+ if (ret)
+ return ret;
+
return __qcom_mdt_load(dev, fw, firmware, pas_id, mem_region, mem_phys,
mem_size, reloc_base, true);
}
diff --git a/include/linux/soc/qcom/mdt_loader.h b/include/linux/soc/qcom/mdt_loader.h
index 46bdb7bace9a..ef8a6278264d 100644
--- a/include/linux/soc/qcom/mdt_loader.h
+++ b/include/linux/soc/qcom/mdt_loader.h
@@ -10,10 +10,14 @@

struct device;
struct firmware;
+struct qcom_scm_pas_metadata;

#if IS_ENABLED(CONFIG_QCOM_MDT_LOADER)

ssize_t qcom_mdt_get_size(const struct firmware *fw);
+int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw,
+ const char *fw_name, int pas_id, phys_addr_t mem_phys,
+ struct qcom_scm_pas_metadata *pas_metadata_ctx);
int qcom_mdt_load(struct device *dev, const struct firmware *fw,
const char *fw_name, int pas_id, void *mem_region,
phys_addr_t mem_phys, size_t mem_size,
@@ -33,6 +37,13 @@ static inline ssize_t qcom_mdt_get_size(const struct firmware *fw)
return -ENODEV;
}

+static int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw,
+ const char *fw_name, int pas_id, phys_addr_t mem_phys,
+ struct qcom_scm_pas_metadata *pas_metadata_ctx)
+{
+ return -ENODEV;
+}
+
static inline int qcom_mdt_load(struct device *dev, const struct firmware *fw,
const char *fw_name, int pas_id,
void *mem_region, phys_addr_t mem_phys,
--
2.33.1

2022-01-29 11:58:18

by Bjorn Andersson

[permalink] [raw]
Subject: [PATCH 09/13] remoteproc: qcom: pas: Carry PAS metadata context

Starting with Qualcomm SM8450 the metadata object shared with the secure
world during authentication and booting of a remoteproc needs to be
alive from init_image() until auth_and_reset().

Use the newly introduced "PAS metadata context" object to track this
context from load until the firmware has been booted.

In the even that load is performed but the process for some reason
doesn't reach auth_and_reset the unprepare callback is used to clean up
the allocated memory.

Signed-off-by: Bjorn Andersson <[email protected]>
---
drivers/remoteproc/qcom_q6v5_pas.c | 32 +++++++++++++++++++++++++++---
1 file changed, 29 insertions(+), 3 deletions(-)

diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
index 184bb7cdf95a..5e806f657fec 100644
--- a/drivers/remoteproc/qcom_q6v5_pas.c
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
@@ -79,6 +79,8 @@ struct qcom_adsp {
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)
@@ -126,14 +128,34 @@ static void adsp_pds_disable(struct qcom_adsp *adsp, struct device **pds,
}
}

+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_load(adsp->dev, fw, rproc->firmware, adsp->pas_id,
- adsp->mem_region, adsp->mem_phys, adsp->mem_size,
- &adsp->mem_reloc);
+ 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;

@@ -185,6 +207,8 @@ static int adsp_start(struct rproc *rproc)
goto disable_px_supply;
}

+ qcom_scm_pas_metadata_release(&adsp->pas_metadata);
+
return 0;

disable_px_supply:
@@ -255,6 +279,7 @@ static unsigned long adsp_panic(struct rproc *rproc)
}

static const struct rproc_ops adsp_ops = {
+ .unprepare = adsp_unprepare,
.start = adsp_start,
.stop = adsp_stop,
.da_to_va = adsp_da_to_va,
@@ -264,6 +289,7 @@ static const struct rproc_ops adsp_ops = {
};

static const struct rproc_ops adsp_minidump_ops = {
+ .unprepare = adsp_unprepare,
.start = adsp_start,
.stop = adsp_stop,
.da_to_va = adsp_da_to_va,
--
2.33.1

2022-01-29 11:58:22

by Bjorn Andersson

[permalink] [raw]
Subject: [PATCH 13/13] arm64: dts: qcom: sm8450-qrd: Enable remoteproc instances

Enable the audio, compute, sensor and modem remoteproc and specify
firmware path for these on the Qualcomm SM8450 QRD.

Signed-off-by: Bjorn Andersson <[email protected]>
---
arch/arm64/boot/dts/qcom/sm8450-qrd.dts | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sm8450-qrd.dts b/arch/arm64/boot/dts/qcom/sm8450-qrd.dts
index b68ab247e6ae..9526632d4029 100644
--- a/arch/arm64/boot/dts/qcom/sm8450-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/sm8450-qrd.dts
@@ -346,6 +346,26 @@ &qupv3_id_0 {
status = "okay";
};

+&remoteproc_adsp {
+ status = "okay";
+ firmware-name = "qcom/sm8450/adsp.mbn";
+};
+
+&remoteproc_cdsp {
+ status = "okay";
+ firmware-name = "qcom/sm8450/cdsp.mbn";
+};
+
+&remoteproc_mpss {
+ status = "okay";
+ firmware-name = "qcom/sm8450/modem.mbn";
+};
+
+&remoteproc_slpi {
+ status = "okay";
+ firmware-name = "qcom/sm8450/slpi.mbn";
+};
+
&tlmm {
gpio-reserved-ranges = <28 4>, <36 4>;
};
--
2.33.1

2022-01-29 11:58:23

by Bjorn Andersson

[permalink] [raw]
Subject: [PATCH 12/13] arm64: dts: qcom: sm8450: Add remoteproc enablers and instances

The Qualcomm SM8450 carries the familiar set of audio, compute, sensor
and modem remoteprocs. Add these and their dependencies.

Signed-off-by: Bjorn Andersson <[email protected]>
---
arch/arm64/boot/dts/qcom/sm8450.dtsi | 297 +++++++++++++++++++++++++++
1 file changed, 297 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sm8450.dtsi b/arch/arm64/boot/dts/qcom/sm8450.dtsi
index 10c25ad2d0c7..24fb3d3e667b 100644
--- a/arch/arm64/boot/dts/qcom/sm8450.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8450.dtsi
@@ -7,6 +7,7 @@
#include <dt-bindings/clock/qcom,gcc-sm8450.h>
#include <dt-bindings/clock/qcom,rpmh.h>
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/mailbox/qcom-ipcc.h>
#include <dt-bindings/power/qcom-rpmpd.h>
#include <dt-bindings/soc/qcom,rpmh-rsc.h>

@@ -460,6 +461,15 @@ cvp_mem: memory@9ee00000 {
no-map;
};

+ rmtfs_mem: memory@9fd00000 {
+ compatible = "qcom,rmtfs-mem";
+ reg = <0x0 0x9fd00000 0x0 0x280000>;
+ no-map;
+
+ qcom,client-id = <1>;
+ qcom,vmid = <15>;
+ };
+
global_sync_mem: memory@a6f00000 {
reg = <0x0 0xa6f00000 0x0 0x100000>;
no-map;
@@ -540,6 +550,113 @@ trusted_apps_ext_mem: memory@ed900000 {
};
};

+ smp2p-adsp {
+ compatible = "qcom,smp2p";
+ qcom,smem = <443>, <429>;
+ interrupts-extended = <&ipcc IPCC_CLIENT_LPASS
+ IPCC_MPROC_SIGNAL_SMP2P
+ IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&ipcc IPCC_CLIENT_LPASS
+ IPCC_MPROC_SIGNAL_SMP2P>;
+
+ qcom,local-pid = <0>;
+ qcom,remote-pid = <2>;
+
+ smp2p_adsp_out: master-kernel {
+ qcom,entry-name = "master-kernel";
+ #qcom,smem-state-cells = <1>;
+ };
+
+ smp2p_adsp_in: slave-kernel {
+ qcom,entry-name = "slave-kernel";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ smp2p-cdsp {
+ compatible = "qcom,smp2p";
+ qcom,smem = <94>, <432>;
+ interrupts-extended = <&ipcc IPCC_CLIENT_CDSP
+ IPCC_MPROC_SIGNAL_SMP2P
+ IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&ipcc IPCC_CLIENT_CDSP
+ IPCC_MPROC_SIGNAL_SMP2P>;
+
+ qcom,local-pid = <0>;
+ qcom,remote-pid = <5>;
+
+ smp2p_cdsp_out: master-kernel {
+ qcom,entry-name = "master-kernel";
+ #qcom,smem-state-cells = <1>;
+ };
+
+ smp2p_cdsp_in: slave-kernel {
+ qcom,entry-name = "slave-kernel";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ smp2p-modem {
+ compatible = "qcom,smp2p";
+ qcom,smem = <435>, <428>;
+ interrupts-extended = <&ipcc IPCC_CLIENT_MPSS
+ IPCC_MPROC_SIGNAL_SMP2P
+ IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&ipcc IPCC_CLIENT_MPSS
+ IPCC_MPROC_SIGNAL_SMP2P>;
+
+ qcom,local-pid = <0>;
+ qcom,remote-pid = <1>;
+
+ smp2p_modem_out: master-kernel {
+ qcom,entry-name = "master-kernel";
+ #qcom,smem-state-cells = <1>;
+ };
+
+ smp2p_modem_in: slave-kernel {
+ qcom,entry-name = "slave-kernel";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ ipa_smp2p_out: ipa-ap-to-modem {
+ qcom,entry-name = "ipa";
+ #qcom,smem-state-cells = <1>;
+ };
+
+ ipa_smp2p_in: ipa-modem-to-ap {
+ qcom,entry-name = "ipa";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ smp2p-slpi {
+ compatible = "qcom,smp2p";
+ qcom,smem = <481>, <430>;
+ interrupts-extended = <&ipcc IPCC_CLIENT_SLPI
+ IPCC_MPROC_SIGNAL_SMP2P
+ IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&ipcc IPCC_CLIENT_SLPI
+ IPCC_MPROC_SIGNAL_SMP2P>;
+
+ qcom,local-pid = <0>;
+ qcom,remote-pid = <3>;
+
+ smp2p_slpi_out: master-kernel {
+ qcom,entry-name = "master-kernel";
+ #qcom,smem-state-cells = <1>;
+ };
+
+ smp2p_slpi_in: slave-kernel {
+ qcom,entry-name = "slave-kernel";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
soc: soc@0 {
#address-cells = <2>;
#size-cells = <2>;
@@ -672,6 +789,167 @@ usb_1_ssphy: phy@88e9200 {
};
};

+ remoteproc_slpi: remoteproc@2400000 {
+ compatible = "qcom,sm8350-slpi-pas";
+ reg = <0 0x02400000 0 0x4000>;
+
+ interrupts-extended = <&pdc 9 IRQ_TYPE_LEVEL_HIGH>,
+ <&smp2p_slpi_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_slpi_in 1 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_slpi_in 2 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_slpi_in 3 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "wdog", "fatal", "ready",
+ "handover", "stop-ack";
+
+ clocks = <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "xo";
+
+ power-domains = <&rpmhpd SM8450_LCX>,
+ <&rpmhpd SM8450_LMX>;
+ power-domain-names = "lcx", "lmx";
+
+ memory-region = <&slpi_mem>;
+
+ qcom,qmp = <&aoss_qmp>;
+
+ qcom,smem-states = <&smp2p_slpi_out 0>;
+ qcom,smem-state-names = "stop";
+
+ status = "disabled";
+
+ glink-edge {
+ interrupts-extended = <&ipcc IPCC_CLIENT_SLPI
+ IPCC_MPROC_SIGNAL_GLINK_QMP
+ IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&ipcc IPCC_CLIENT_SLPI
+ IPCC_MPROC_SIGNAL_GLINK_QMP>;
+
+ label = "slpi";
+ qcom,remote-pid = <3>;
+ };
+ };
+
+ remoteproc_adsp: remoteproc@30000000 {
+ compatible = "qcom,sm8450-adsp-pas";
+ reg = <0 0x030000000 0 0x100>;
+
+ interrupts-extended = <&pdc 6 IRQ_TYPE_LEVEL_HIGH>,
+ <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_adsp_in 3 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "wdog", "fatal", "ready",
+ "handover", "stop-ack";
+
+ clocks = <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "xo";
+
+ power-domains = <&rpmhpd SM8450_LCX>,
+ <&rpmhpd SM8450_LMX>;
+ power-domain-names = "lcx", "lmx";
+
+ memory-region = <&adsp_mem>;
+
+ qcom,qmp = <&aoss_qmp>;
+
+ qcom,smem-states = <&smp2p_adsp_out 0>;
+ qcom,smem-state-names = "stop";
+
+ status = "disabled";
+
+ remoteproc_adsp_glink: glink-edge {
+ interrupts-extended = <&ipcc IPCC_CLIENT_LPASS
+ IPCC_MPROC_SIGNAL_GLINK_QMP
+ IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&ipcc IPCC_CLIENT_LPASS
+ IPCC_MPROC_SIGNAL_GLINK_QMP>;
+
+ label = "lpass";
+ qcom,remote-pid = <2>;
+ };
+ };
+
+ remoteproc_cdsp: remoteproc@32300000 {
+ compatible = "qcom,sm8450-cdsp-pas";
+ reg = <0 0x032300000 0 0x1400000>;
+
+ interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_LEVEL_HIGH>,
+ <&smp2p_cdsp_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_cdsp_in 1 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_cdsp_in 2 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_cdsp_in 3 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "wdog", "fatal", "ready",
+ "handover", "stop-ack";
+
+ clocks = <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "xo";
+
+ power-domains = <&rpmhpd SM8450_CX>,
+ <&rpmhpd SM8450_MXC>;
+ power-domain-names = "cx", "mxc";
+
+ memory-region = <&cdsp_mem>;
+
+ qcom,qmp = <&aoss_qmp>;
+
+ qcom,smem-states = <&smp2p_cdsp_out 0>;
+ qcom,smem-state-names = "stop";
+
+ status = "disabled";
+
+ glink-edge {
+ interrupts-extended = <&ipcc IPCC_CLIENT_CDSP
+ IPCC_MPROC_SIGNAL_GLINK_QMP
+ IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&ipcc IPCC_CLIENT_CDSP
+ IPCC_MPROC_SIGNAL_GLINK_QMP>;
+
+ label = "cdsp";
+ qcom,remote-pid = <5>;
+ };
+ };
+
+ remoteproc_mpss: remoteproc@4080000 {
+ compatible = "qcom,sm8450-mpss-pas";
+ reg = <0x0 0x04080000 0x0 0x4040>;
+
+ interrupts-extended = <&intc GIC_SPI 264 IRQ_TYPE_LEVEL_HIGH>,
+ <&smp2p_modem_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_modem_in 1 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_modem_in 2 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_modem_in 3 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_modem_in 7 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "wdog", "fatal", "ready", "handover",
+ "stop-ack", "shutdown-ack";
+
+ clocks = <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "xo";
+
+ power-domains = <&rpmhpd 0>,
+ <&rpmhpd 12>;
+ power-domain-names = "cx", "mss";
+
+ memory-region = <&mpss_mem>;
+
+ qcom,qmp = <&aoss_qmp>;
+
+ qcom,smem-states = <&smp2p_modem_out 0>;
+ qcom,smem-state-names = "stop";
+
+ status = "disabled";
+
+ glink-edge {
+ interrupts-extended = <&ipcc IPCC_CLIENT_MPSS
+ IPCC_MPROC_SIGNAL_GLINK_QMP
+ IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&ipcc IPCC_CLIENT_MPSS
+ IPCC_MPROC_SIGNAL_GLINK_QMP>;
+ interrupts = <GIC_SPI 449 IRQ_TYPE_EDGE_RISING>;
+ label = "modem";
+ qcom,remote-pid = <1>;
+ };
+ };
+
pdc: interrupt-controller@b220000 {
compatible = "qcom,sm8450-pdc", "qcom,pdc";
reg = <0 0x0b220000 0 0x30000>, <0 0x174000f0 0 0x64>;
@@ -682,6 +960,25 @@ pdc: interrupt-controller@b220000 {
interrupt-controller;
};

+ aoss_qmp: power-controller@c300000 {
+ compatible = "qcom,sm8450-aoss-qmp", "qcom,aoss-qmp";
+ reg = <0 0x0c300000 0 0x400>;
+ interrupts-extended = <&ipcc IPCC_CLIENT_AOP IPCC_MPROC_SIGNAL_GLINK_QMP
+ IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&ipcc IPCC_CLIENT_AOP IPCC_MPROC_SIGNAL_GLINK_QMP>;
+
+ #clock-cells = <0>;
+ };
+
+ ipcc: mailbox@ed18000 {
+ compatible = "qcom,sm8450-ipcc", "qcom,ipcc";
+ reg = <0 0x0ed18000 0 0x1000>;
+ interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ #mbox-cells = <2>;
+ };
+
tlmm: pinctrl@f100000 {
compatible = "qcom,sm8450-tlmm";
reg = <0 0x0f100000 0 0x300000>;
--
2.33.1

2022-01-29 11:58:25

by Bjorn Andersson

[permalink] [raw]
Subject: [PATCH 11/13] remoteproc: qcom: pas: Add SM8450 remoteproc support

Add audio, compute, sensor and modem remoteproc compatibles to the PAS
remoteproc driver. The resources needed for each one matches those of
SM8350, so its descs are reused.

Signed-off-by: Bjorn Andersson <[email protected]>
---
drivers/remoteproc/qcom_q6v5_pas.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
index 5e806f657fec..1ae47cc153e5 100644
--- a/drivers/remoteproc/qcom_q6v5_pas.c
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
@@ -879,6 +879,10 @@ static const struct of_device_id adsp_of_match[] = {
{ .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 = &mpss_resource_init},
{ },
};
MODULE_DEVICE_TABLE(of, adsp_of_match);
--
2.33.1

2022-02-04 22:58:54

by Bjorn Andersson

[permalink] [raw]
Subject: Re: (subset) [PATCH 00/13] soc: qcom: mdt_loader: Support Qualcomm SM8450

On Thu, 27 Jan 2022 18:55:00 -0800, Bjorn Andersson wrote:
> The Qualcomm SM8450 platform comes with both some smaller changes in the
> firmware packaging and a new requirement to hold onto the metadata buffer until
> PAS auth_and_reset has been completed.
>
> Extend the PAS api and rework the mdt_loader to meet these new requirements,
> then wire this up with the PAS remoteproc driver and finally add the SM8450
> remoteproc instances.
>
> [...]

Applied, thanks!

[12/13] arm64: dts: qcom: sm8450: Add remoteproc enablers and instances
commit: e57f31b02784bdafd35940ea2592df8151ea1190
[13/13] arm64: dts: qcom: sm8450-qrd: Enable remoteproc instances
commit: b48007d6d098dfeb57888c7bc50fbfb99e4e3695

Best regards,
--
Bjorn Andersson <[email protected]>

2022-02-04 23:09:04

by Bjorn Andersson

[permalink] [raw]
Subject: Re: [PATCH 00/13] soc: qcom: mdt_loader: Support Qualcomm SM8450

On Thu 03 Feb 07:11 PST 2022, Dmitry Baryshkov wrote:

> On 28/01/2022 05:55, Bjorn Andersson wrote:
> > The Qualcomm SM8450 platform comes with both some smaller changes in the
> > firmware packaging and a new requirement to hold onto the metadata buffer until
> > PAS auth_and_reset has been completed.
> >
> > Extend the PAS api and rework the mdt_loader to meet these new requirements,
> > then wire this up with the PAS remoteproc driver and finally add the SM8450
> > remoteproc instances.
> >
> > Bjorn Andersson (13):
> > firmware: qcom: scm: Introduce pas_metadata context
> > soc: qcom: mdt_loader: Split out split-file-loader
> > soc: qcom: mdt_loader: Allow hash segment to be split out
> > soc: qcom: mdt_loader: Allow hash to reside in any segment
> > soc: qcom: mdt_loader: Extend check for split firmware
> > soc: qcom: mdt_loader: Reorder parts of __qcom_mdt_load()
> > soc: qcom: mdt_loader: Always invoke PAS mem_setup
> > soc: qcom: mdt_loader: Extract PAS operations
> > remoteproc: qcom: pas: Carry PAS metadata context
> > dt-bindings: remoteproc: qcom: pas: Add SM8450 PAS compatibles
> > remoteproc: qcom: pas: Add SM8450 remoteproc support
> > arm64: dts: qcom: sm8450: Add remoteproc enablers and instances
> > arm64: dts: qcom: sm8450-qrd: Enable remoteproc instances
>
> Reviewed-by: Dmitry Baryshkov <[email protected]>
>

Thanks.

> Minor nitpicks:
> - I'd reorder the series by moving patch 1 (pas_metadata) closer to patch
> 8&9 (pas metadata usage)

For a while the design where such that I would merge the first patch
into a immutable branch and then merge the soc/qcom and remoteproc
changes separately.

But as you can see, in the end the remoteproc patch ended up depending
on the mdt_loader changes.

I like your suggestion, so I can move the scm change down to keep things
together.

> - I would have added pas_metadata as an argument to qcom_mdt_load().
> However I see, why you didn't want to add another argument to the list.
>

I looked at that, but I was already unhappy with the argument explosion
in that function prototype.

By splitting out the difference between qcom_mdt_load() and
qcom_mdt_load_no_init() into a separate function will allow some cleanup
and better reuse in the client drivers.

As we bring up the various clients on SM8450 we will need to perform the
same modifications that was done to the remoteproc driver, by doing it
like this we don't need to change the prototype twice.

Regards,
Bjorn

> >
> > .../bindings/remoteproc/qcom,adsp.yaml | 16 +
> > arch/arm64/boot/dts/qcom/sm8450-qrd.dts | 20 ++
> > arch/arm64/boot/dts/qcom/sm8450.dtsi | 297 ++++++++++++++++++
> > drivers/firmware/qcom_scm.c | 39 ++-
> > drivers/remoteproc/qcom_q6v5_mss.c | 7 +-
> > drivers/remoteproc/qcom_q6v5_pas.c | 36 ++-
> > drivers/soc/qcom/mdt_loader.c | 232 +++++++++-----
> > include/linux/qcom_scm.h | 10 +-
> > include/linux/soc/qcom/mdt_loader.h | 17 +-
> > 9 files changed, 579 insertions(+), 95 deletions(-)
> >
>
>
> --
> With best wishes
> Dmitry

2022-02-07 11:18:16

by Dmitry Baryshkov

[permalink] [raw]
Subject: Re: [PATCH 00/13] soc: qcom: mdt_loader: Support Qualcomm SM8450

On 28/01/2022 05:55, Bjorn Andersson wrote:
> The Qualcomm SM8450 platform comes with both some smaller changes in the
> firmware packaging and a new requirement to hold onto the metadata buffer until
> PAS auth_and_reset has been completed.
>
> Extend the PAS api and rework the mdt_loader to meet these new requirements,
> then wire this up with the PAS remoteproc driver and finally add the SM8450
> remoteproc instances.
>
> Bjorn Andersson (13):
> firmware: qcom: scm: Introduce pas_metadata context
> soc: qcom: mdt_loader: Split out split-file-loader
> soc: qcom: mdt_loader: Allow hash segment to be split out
> soc: qcom: mdt_loader: Allow hash to reside in any segment
> soc: qcom: mdt_loader: Extend check for split firmware
> soc: qcom: mdt_loader: Reorder parts of __qcom_mdt_load()
> soc: qcom: mdt_loader: Always invoke PAS mem_setup
> soc: qcom: mdt_loader: Extract PAS operations
> remoteproc: qcom: pas: Carry PAS metadata context
> dt-bindings: remoteproc: qcom: pas: Add SM8450 PAS compatibles
> remoteproc: qcom: pas: Add SM8450 remoteproc support
> arm64: dts: qcom: sm8450: Add remoteproc enablers and instances
> arm64: dts: qcom: sm8450-qrd: Enable remoteproc instances

Reviewed-by: Dmitry Baryshkov <[email protected]>

Minor nitpicks:
- I'd reorder the series by moving patch 1 (pas_metadata) closer to
patch 8&9 (pas metadata usage)
- I would have added pas_metadata as an argument to qcom_mdt_load().
However I see, why you didn't want to add another argument to the list.

>
> .../bindings/remoteproc/qcom,adsp.yaml | 16 +
> arch/arm64/boot/dts/qcom/sm8450-qrd.dts | 20 ++
> arch/arm64/boot/dts/qcom/sm8450.dtsi | 297 ++++++++++++++++++
> drivers/firmware/qcom_scm.c | 39 ++-
> drivers/remoteproc/qcom_q6v5_mss.c | 7 +-
> drivers/remoteproc/qcom_q6v5_pas.c | 36 ++-
> drivers/soc/qcom/mdt_loader.c | 232 +++++++++-----
> include/linux/qcom_scm.h | 10 +-
> include/linux/soc/qcom/mdt_loader.h | 17 +-
> 9 files changed, 579 insertions(+), 95 deletions(-)
>


--
With best wishes
Dmitry

2022-02-28 10:17:12

by Dmitry Baryshkov

[permalink] [raw]
Subject: Re: [PATCH 12/13] arm64: dts: qcom: sm8450: Add remoteproc enablers and instances

On Fri, 28 Jan 2022 at 05:55, Bjorn Andersson
<[email protected]> wrote:
>
> The Qualcomm SM8450 carries the familiar set of audio, compute, sensor
> and modem remoteprocs. Add these and their dependencies.
>
> Signed-off-by: Bjorn Andersson <[email protected]>
> ---
> arch/arm64/boot/dts/qcom/sm8450.dtsi | 297 +++++++++++++++++++++++++++
> 1 file changed, 297 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/qcom/sm8450.dtsi b/arch/arm64/boot/dts/qcom/sm8450.dtsi
> index 10c25ad2d0c7..24fb3d3e667b 100644
> --- a/arch/arm64/boot/dts/qcom/sm8450.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sm8450.dtsi
> @@ -7,6 +7,7 @@
> #include <dt-bindings/clock/qcom,gcc-sm8450.h>
> #include <dt-bindings/clock/qcom,rpmh.h>
> #include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/mailbox/qcom-ipcc.h>
> #include <dt-bindings/power/qcom-rpmpd.h>
> #include <dt-bindings/soc/qcom,rpmh-rsc.h>
>
> @@ -460,6 +461,15 @@ cvp_mem: memory@9ee00000 {
> no-map;
> };
>
> + rmtfs_mem: memory@9fd00000 {
> + compatible = "qcom,rmtfs-mem";
> + reg = <0x0 0x9fd00000 0x0 0x280000>;
> + no-map;
> +
> + qcom,client-id = <1>;
> + qcom,vmid = <15>;
> + };
> +
> global_sync_mem: memory@a6f00000 {
> reg = <0x0 0xa6f00000 0x0 0x100000>;
> no-map;
> @@ -540,6 +550,113 @@ trusted_apps_ext_mem: memory@ed900000 {
> };
> };
>
> + smp2p-adsp {
> + compatible = "qcom,smp2p";
> + qcom,smem = <443>, <429>;
> + interrupts-extended = <&ipcc IPCC_CLIENT_LPASS
> + IPCC_MPROC_SIGNAL_SMP2P
> + IRQ_TYPE_EDGE_RISING>;
> + mboxes = <&ipcc IPCC_CLIENT_LPASS
> + IPCC_MPROC_SIGNAL_SMP2P>;
> +
> + qcom,local-pid = <0>;
> + qcom,remote-pid = <2>;
> +
> + smp2p_adsp_out: master-kernel {
> + qcom,entry-name = "master-kernel";
> + #qcom,smem-state-cells = <1>;
> + };
> +
> + smp2p_adsp_in: slave-kernel {
> + qcom,entry-name = "slave-kernel";
> + interrupt-controller;
> + #interrupt-cells = <2>;
> + };
> + };
> +
> + smp2p-cdsp {
> + compatible = "qcom,smp2p";
> + qcom,smem = <94>, <432>;
> + interrupts-extended = <&ipcc IPCC_CLIENT_CDSP
> + IPCC_MPROC_SIGNAL_SMP2P
> + IRQ_TYPE_EDGE_RISING>;
> + mboxes = <&ipcc IPCC_CLIENT_CDSP
> + IPCC_MPROC_SIGNAL_SMP2P>;
> +
> + qcom,local-pid = <0>;
> + qcom,remote-pid = <5>;
> +
> + smp2p_cdsp_out: master-kernel {
> + qcom,entry-name = "master-kernel";
> + #qcom,smem-state-cells = <1>;
> + };
> +
> + smp2p_cdsp_in: slave-kernel {
> + qcom,entry-name = "slave-kernel";
> + interrupt-controller;
> + #interrupt-cells = <2>;
> + };
> + };
> +
> + smp2p-modem {
> + compatible = "qcom,smp2p";
> + qcom,smem = <435>, <428>;
> + interrupts-extended = <&ipcc IPCC_CLIENT_MPSS
> + IPCC_MPROC_SIGNAL_SMP2P
> + IRQ_TYPE_EDGE_RISING>;
> + mboxes = <&ipcc IPCC_CLIENT_MPSS
> + IPCC_MPROC_SIGNAL_SMP2P>;
> +
> + qcom,local-pid = <0>;
> + qcom,remote-pid = <1>;
> +
> + smp2p_modem_out: master-kernel {
> + qcom,entry-name = "master-kernel";
> + #qcom,smem-state-cells = <1>;
> + };
> +
> + smp2p_modem_in: slave-kernel {
> + qcom,entry-name = "slave-kernel";
> + interrupt-controller;
> + #interrupt-cells = <2>;
> + };
> +
> + ipa_smp2p_out: ipa-ap-to-modem {
> + qcom,entry-name = "ipa";
> + #qcom,smem-state-cells = <1>;
> + };
> +
> + ipa_smp2p_in: ipa-modem-to-ap {
> + qcom,entry-name = "ipa";
> + interrupt-controller;
> + #interrupt-cells = <2>;
> + };
> + };
> +
> + smp2p-slpi {
> + compatible = "qcom,smp2p";
> + qcom,smem = <481>, <430>;
> + interrupts-extended = <&ipcc IPCC_CLIENT_SLPI
> + IPCC_MPROC_SIGNAL_SMP2P
> + IRQ_TYPE_EDGE_RISING>;
> + mboxes = <&ipcc IPCC_CLIENT_SLPI
> + IPCC_MPROC_SIGNAL_SMP2P>;
> +
> + qcom,local-pid = <0>;
> + qcom,remote-pid = <3>;
> +
> + smp2p_slpi_out: master-kernel {
> + qcom,entry-name = "master-kernel";
> + #qcom,smem-state-cells = <1>;
> + };
> +
> + smp2p_slpi_in: slave-kernel {
> + qcom,entry-name = "slave-kernel";
> + interrupt-controller;
> + #interrupt-cells = <2>;
> + };
> + };
> +
> soc: soc@0 {
> #address-cells = <2>;
> #size-cells = <2>;
> @@ -672,6 +789,167 @@ usb_1_ssphy: phy@88e9200 {
> };
> };
>
> + remoteproc_slpi: remoteproc@2400000 {
> + compatible = "qcom,sm8350-slpi-pas";

I think this should be sm8450-slpi-pas.

Otherwise:

Reviewed-by: Dmitry Baryshkov <[email protected]>

> + reg = <0 0x02400000 0 0x4000>;
> +
> + interrupts-extended = <&pdc 9 IRQ_TYPE_LEVEL_HIGH>,
> + <&smp2p_slpi_in 0 IRQ_TYPE_EDGE_RISING>,
> + <&smp2p_slpi_in 1 IRQ_TYPE_EDGE_RISING>,
> + <&smp2p_slpi_in 2 IRQ_TYPE_EDGE_RISING>,
> + <&smp2p_slpi_in 3 IRQ_TYPE_EDGE_RISING>;
> + interrupt-names = "wdog", "fatal", "ready",
> + "handover", "stop-ack";
> +
> + clocks = <&rpmhcc RPMH_CXO_CLK>;
> + clock-names = "xo";
> +
> + power-domains = <&rpmhpd SM8450_LCX>,
> + <&rpmhpd SM8450_LMX>;
> + power-domain-names = "lcx", "lmx";
> +
> + memory-region = <&slpi_mem>;
> +
> + qcom,qmp = <&aoss_qmp>;
> +
> + qcom,smem-states = <&smp2p_slpi_out 0>;
> + qcom,smem-state-names = "stop";
> +
> + status = "disabled";
> +
> + glink-edge {
> + interrupts-extended = <&ipcc IPCC_CLIENT_SLPI
> + IPCC_MPROC_SIGNAL_GLINK_QMP
> + IRQ_TYPE_EDGE_RISING>;
> + mboxes = <&ipcc IPCC_CLIENT_SLPI
> + IPCC_MPROC_SIGNAL_GLINK_QMP>;
> +
> + label = "slpi";
> + qcom,remote-pid = <3>;
> + };
> + };
> +
> + remoteproc_adsp: remoteproc@30000000 {
> + compatible = "qcom,sm8450-adsp-pas";
> + reg = <0 0x030000000 0 0x100>;
> +
> + interrupts-extended = <&pdc 6 IRQ_TYPE_LEVEL_HIGH>,
> + <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>,
> + <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>,
> + <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>,
> + <&smp2p_adsp_in 3 IRQ_TYPE_EDGE_RISING>;
> + interrupt-names = "wdog", "fatal", "ready",
> + "handover", "stop-ack";
> +
> + clocks = <&rpmhcc RPMH_CXO_CLK>;
> + clock-names = "xo";
> +
> + power-domains = <&rpmhpd SM8450_LCX>,
> + <&rpmhpd SM8450_LMX>;
> + power-domain-names = "lcx", "lmx";
> +
> + memory-region = <&adsp_mem>;
> +
> + qcom,qmp = <&aoss_qmp>;
> +
> + qcom,smem-states = <&smp2p_adsp_out 0>;
> + qcom,smem-state-names = "stop";
> +
> + status = "disabled";
> +
> + remoteproc_adsp_glink: glink-edge {
> + interrupts-extended = <&ipcc IPCC_CLIENT_LPASS
> + IPCC_MPROC_SIGNAL_GLINK_QMP
> + IRQ_TYPE_EDGE_RISING>;
> + mboxes = <&ipcc IPCC_CLIENT_LPASS
> + IPCC_MPROC_SIGNAL_GLINK_QMP>;
> +
> + label = "lpass";
> + qcom,remote-pid = <2>;
> + };
> + };
> +
> + remoteproc_cdsp: remoteproc@32300000 {
> + compatible = "qcom,sm8450-cdsp-pas";
> + reg = <0 0x032300000 0 0x1400000>;
> +
> + interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_LEVEL_HIGH>,
> + <&smp2p_cdsp_in 0 IRQ_TYPE_EDGE_RISING>,
> + <&smp2p_cdsp_in 1 IRQ_TYPE_EDGE_RISING>,
> + <&smp2p_cdsp_in 2 IRQ_TYPE_EDGE_RISING>,
> + <&smp2p_cdsp_in 3 IRQ_TYPE_EDGE_RISING>;
> + interrupt-names = "wdog", "fatal", "ready",
> + "handover", "stop-ack";
> +
> + clocks = <&rpmhcc RPMH_CXO_CLK>;
> + clock-names = "xo";
> +
> + power-domains = <&rpmhpd SM8450_CX>,
> + <&rpmhpd SM8450_MXC>;
> + power-domain-names = "cx", "mxc";
> +
> + memory-region = <&cdsp_mem>;
> +
> + qcom,qmp = <&aoss_qmp>;
> +
> + qcom,smem-states = <&smp2p_cdsp_out 0>;
> + qcom,smem-state-names = "stop";
> +
> + status = "disabled";
> +
> + glink-edge {
> + interrupts-extended = <&ipcc IPCC_CLIENT_CDSP
> + IPCC_MPROC_SIGNAL_GLINK_QMP
> + IRQ_TYPE_EDGE_RISING>;
> + mboxes = <&ipcc IPCC_CLIENT_CDSP
> + IPCC_MPROC_SIGNAL_GLINK_QMP>;
> +
> + label = "cdsp";
> + qcom,remote-pid = <5>;
> + };
> + };
> +
> + remoteproc_mpss: remoteproc@4080000 {
> + compatible = "qcom,sm8450-mpss-pas";
> + reg = <0x0 0x04080000 0x0 0x4040>;
> +
> + interrupts-extended = <&intc GIC_SPI 264 IRQ_TYPE_LEVEL_HIGH>,
> + <&smp2p_modem_in 0 IRQ_TYPE_EDGE_RISING>,
> + <&smp2p_modem_in 1 IRQ_TYPE_EDGE_RISING>,
> + <&smp2p_modem_in 2 IRQ_TYPE_EDGE_RISING>,
> + <&smp2p_modem_in 3 IRQ_TYPE_EDGE_RISING>,
> + <&smp2p_modem_in 7 IRQ_TYPE_EDGE_RISING>;
> + interrupt-names = "wdog", "fatal", "ready", "handover",
> + "stop-ack", "shutdown-ack";
> +
> + clocks = <&rpmhcc RPMH_CXO_CLK>;
> + clock-names = "xo";
> +
> + power-domains = <&rpmhpd 0>,
> + <&rpmhpd 12>;
> + power-domain-names = "cx", "mss";
> +
> + memory-region = <&mpss_mem>;
> +
> + qcom,qmp = <&aoss_qmp>;
> +
> + qcom,smem-states = <&smp2p_modem_out 0>;
> + qcom,smem-state-names = "stop";
> +
> + status = "disabled";
> +
> + glink-edge {
> + interrupts-extended = <&ipcc IPCC_CLIENT_MPSS
> + IPCC_MPROC_SIGNAL_GLINK_QMP
> + IRQ_TYPE_EDGE_RISING>;
> + mboxes = <&ipcc IPCC_CLIENT_MPSS
> + IPCC_MPROC_SIGNAL_GLINK_QMP>;
> + interrupts = <GIC_SPI 449 IRQ_TYPE_EDGE_RISING>;
> + label = "modem";
> + qcom,remote-pid = <1>;
> + };
> + };
> +
> pdc: interrupt-controller@b220000 {
> compatible = "qcom,sm8450-pdc", "qcom,pdc";
> reg = <0 0x0b220000 0 0x30000>, <0 0x174000f0 0 0x64>;
> @@ -682,6 +960,25 @@ pdc: interrupt-controller@b220000 {
> interrupt-controller;
> };
>
> + aoss_qmp: power-controller@c300000 {
> + compatible = "qcom,sm8450-aoss-qmp", "qcom,aoss-qmp";
> + reg = <0 0x0c300000 0 0x400>;
> + interrupts-extended = <&ipcc IPCC_CLIENT_AOP IPCC_MPROC_SIGNAL_GLINK_QMP
> + IRQ_TYPE_EDGE_RISING>;
> + mboxes = <&ipcc IPCC_CLIENT_AOP IPCC_MPROC_SIGNAL_GLINK_QMP>;
> +
> + #clock-cells = <0>;
> + };
> +
> + ipcc: mailbox@ed18000 {
> + compatible = "qcom,sm8450-ipcc", "qcom,ipcc";
> + reg = <0 0x0ed18000 0 0x1000>;
> + interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>;
> + interrupt-controller;
> + #interrupt-cells = <3>;
> + #mbox-cells = <2>;
> + };
> +
> tlmm: pinctrl@f100000 {
> compatible = "qcom,sm8450-tlmm";
> reg = <0 0x0f100000 0 0x300000>;
> --
> 2.33.1
>


--
With best wishes
Dmitry

2023-05-24 11:28:36

by Robert Marko

[permalink] [raw]
Subject: Re: [PATCH 01/13] firmware: qcom: scm: Introduce pas_metadata context


On 28. 01. 2022. 03:55, Bjorn Andersson wrote:
> Starting with Qualcomm SM8450, some new security enhancements has been
> done in the secure world, which results in the requirement to keep the
> metadata segment accessible by the secure world from init_image() until
> auth_and_reset().
>
> Introduce a "PAS metadata context" object that can be passed to
> init_image() for tracking the mapped memory and a related release
> function for client drivers to release the mapping once either
> auth_and_reset() has been invoked or in error handling paths on the way
> there.
>
> Signed-off-by: Bjorn Andersson <[email protected]>

Hi Bjorn,
I know a lot of time has passed since this patch, but this patch breaks
qcom_scm_pas_auth_and_reset SCM call.
I have had MDT loader and SCM changes from this series reverted for a
long time but was unable to
find the exact culprit nor how to fix it.
I even ported the TZ log driver to see if anything is obvious there but
nope, calling qcom_scm_pas_auth_and_reset
after this patch is just failling which is then causing Q6 WCSS on
IPQ8074 to fail probing so WLAN doesnt work.

Since I am out of ideas, I was hoping that you maybe have an idea what
could be the issue, I can provide the TZ log
with all of the SCM calls when it works and when not if required.

Regards,
Robert

> ---
> drivers/firmware/qcom_scm.c | 39 ++++++++++++++++++++++++++++++-----
> drivers/soc/qcom/mdt_loader.c | 2 +-
> include/linux/qcom_scm.h | 10 ++++++++-
> 3 files changed, 44 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
> index 7db8066b19fd..3218d13cbf83 100644
> --- a/drivers/firmware/qcom_scm.c
> +++ b/drivers/firmware/qcom_scm.c
> @@ -435,10 +435,16 @@ static void qcom_scm_set_download_mode(bool enable)
> * and optional blob of data used for authenticating the metadata
> * and the rest of the firmware
> * @size: size of the metadata
> + * @ctx: optional metadata context
> *
> - * Returns 0 on success.
> + * Return: 0 on success.
> + *
> + * Upon successful return, the PAS metadata context (@ctx) will be used to
> + * track the metadata allocation, this needs to be released by invoking
> + * qcom_scm_pas_metadata_release() by the caller.
> */
> -int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size)
> +int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size,
> + struct qcom_scm_pas_metadata *ctx)
> {
> dma_addr_t mdata_phys;
> void *mdata_buf;
> @@ -467,7 +473,7 @@ int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size)
>
> ret = qcom_scm_clk_enable();
> if (ret)
> - goto free_metadata;
> + goto out;
>
> desc.args[1] = mdata_phys;
>
> @@ -475,13 +481,36 @@ int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size)
>
> qcom_scm_clk_disable();
>
> -free_metadata:
> - dma_free_coherent(__scm->dev, size, mdata_buf, mdata_phys);
> +out:
> + if (ret < 0 || !ctx) {
> + dma_free_coherent(__scm->dev, size, mdata_buf, mdata_phys);
> + } else if (ctx) {
> + ctx->ptr = mdata_buf;
> + ctx->phys = mdata_phys;
> + ctx->size = size;
> + }
>
> return ret ? : res.result[0];
> }
> EXPORT_SYMBOL(qcom_scm_pas_init_image);
>
> +/**
> + * qcom_scm_pas_metadata_release() - release metadata context
> + * @ctx: metadata context
> + */
> +void qcom_scm_pas_metadata_release(struct qcom_scm_pas_metadata *ctx)
> +{
> + if (!ctx->ptr)
> + return;
> +
> + dma_free_coherent(__scm->dev, ctx->size, ctx->ptr, ctx->phys);
> +
> + ctx->ptr = NULL;
> + ctx->phys = 0;
> + ctx->size = 0;
> +}
> +EXPORT_SYMBOL(qcom_scm_pas_metadata_release);
> +
> /**
> * qcom_scm_pas_mem_setup() - Prepare the memory related to a given peripheral
> * for firmware loading
> diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
> index 72fc2b539213..b00586db5391 100644
> --- a/drivers/soc/qcom/mdt_loader.c
> +++ b/drivers/soc/qcom/mdt_loader.c
> @@ -171,7 +171,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
> goto out;
> }
>
> - ret = qcom_scm_pas_init_image(pas_id, metadata, metadata_len);
> + ret = qcom_scm_pas_init_image(pas_id, metadata, metadata_len, NULL);
>
> kfree(metadata);
> if (ret) {
> diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h
> index 81cad9e1e412..4d8371410b05 100644
> --- a/include/linux/qcom_scm.h
> +++ b/include/linux/qcom_scm.h
> @@ -68,8 +68,16 @@ extern int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus);
> extern void qcom_scm_cpu_power_down(u32 flags);
> extern int qcom_scm_set_remote_state(u32 state, u32 id);
>
> +struct qcom_scm_pas_metadata {
> + void *ptr;
> + dma_addr_t phys;
> + ssize_t size;
> +};
> +
> extern int qcom_scm_pas_init_image(u32 peripheral, const void *metadata,
> - size_t size);
> + size_t size,
> + struct qcom_scm_pas_metadata *ctx);
> +void qcom_scm_pas_metadata_release(struct qcom_scm_pas_metadata *ctx);
> extern int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr,
> phys_addr_t size);
> extern int qcom_scm_pas_auth_and_reset(u32 peripheral);