forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
remoteproc: qcom: Introduce helper to store pil info in IMEM
A region in IMEM is used to communicate load addresses of remoteproc to post mortem debug tools. Implement a helper function that can be used to store this information in order to enable these tools to process collected ramdumps. Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org> Reviewed-by: Vinod Koul <vkoul@kernel.org> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org> Link: https://lore.kernel.org/r/20200622191942.255460-3-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
- Loading branch information
Showing
4 changed files
with
142 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
// SPDX-License-Identifier: GPL-2.0-only | ||
/* | ||
* Copyright (c) 2019-2020 Linaro Ltd. | ||
*/ | ||
#include <linux/kernel.h> | ||
#include <linux/module.h> | ||
#include <linux/mutex.h> | ||
#include <linux/of_address.h> | ||
#include "qcom_pil_info.h" | ||
|
||
/* | ||
* The PIL relocation information region is used to communicate memory regions | ||
* occupied by co-processor firmware for post mortem crash analysis. | ||
* | ||
* It consists of an array of entries with an 8 byte textual identifier of the | ||
* region followed by a 64 bit base address and 32 bit size, both little | ||
* endian. | ||
*/ | ||
#define PIL_RELOC_NAME_LEN 8 | ||
#define PIL_RELOC_ENTRY_SIZE (PIL_RELOC_NAME_LEN + sizeof(__le64) + sizeof(__le32)) | ||
|
||
struct pil_reloc { | ||
void __iomem *base; | ||
size_t num_entries; | ||
}; | ||
|
||
static struct pil_reloc _reloc __read_mostly; | ||
static DEFINE_MUTEX(pil_reloc_lock); | ||
|
||
static int qcom_pil_info_init(void) | ||
{ | ||
struct device_node *np; | ||
struct resource imem; | ||
void __iomem *base; | ||
int ret; | ||
|
||
/* Already initialized? */ | ||
if (_reloc.base) | ||
return 0; | ||
|
||
np = of_find_compatible_node(NULL, NULL, "qcom,pil-reloc-info"); | ||
if (!np) | ||
return -ENOENT; | ||
|
||
ret = of_address_to_resource(np, 0, &imem); | ||
of_node_put(np); | ||
if (ret < 0) | ||
return ret; | ||
|
||
base = ioremap(imem.start, resource_size(&imem)); | ||
if (!base) { | ||
pr_err("failed to map PIL relocation info region\n"); | ||
return -ENOMEM; | ||
} | ||
|
||
memset_io(base, 0, resource_size(&imem)); | ||
|
||
_reloc.base = base; | ||
_reloc.num_entries = resource_size(&imem) / PIL_RELOC_ENTRY_SIZE; | ||
|
||
return 0; | ||
} | ||
|
||
/** | ||
* qcom_pil_info_store() - store PIL information of image in IMEM | ||
* @image: name of the image | ||
* @base: base address of the loaded image | ||
* @size: size of the loaded image | ||
* | ||
* Return: 0 on success, negative errno on failure | ||
*/ | ||
int qcom_pil_info_store(const char *image, phys_addr_t base, size_t size) | ||
{ | ||
char buf[PIL_RELOC_NAME_LEN]; | ||
void __iomem *entry; | ||
int ret; | ||
int i; | ||
|
||
mutex_lock(&pil_reloc_lock); | ||
ret = qcom_pil_info_init(); | ||
if (ret < 0) { | ||
mutex_unlock(&pil_reloc_lock); | ||
return ret; | ||
} | ||
|
||
for (i = 0; i < _reloc.num_entries; i++) { | ||
entry = _reloc.base + i * PIL_RELOC_ENTRY_SIZE; | ||
|
||
memcpy_fromio(buf, entry, PIL_RELOC_NAME_LEN); | ||
|
||
/* | ||
* An empty record means we didn't find it, given that the | ||
* records are packed. | ||
*/ | ||
if (!buf[0]) | ||
goto found_unused; | ||
|
||
if (!strncmp(buf, image, PIL_RELOC_NAME_LEN)) | ||
goto found_existing; | ||
} | ||
|
||
pr_warn("insufficient PIL info slots\n"); | ||
mutex_unlock(&pil_reloc_lock); | ||
return -ENOMEM; | ||
|
||
found_unused: | ||
memcpy_toio(entry, image, PIL_RELOC_NAME_LEN); | ||
found_existing: | ||
/* Use two writel() as base is only aligned to 4 bytes on odd entries */ | ||
writel(base, entry + PIL_RELOC_NAME_LEN); | ||
writel(base >> 32, entry + PIL_RELOC_NAME_LEN + 4); | ||
writel(size, entry + PIL_RELOC_NAME_LEN + sizeof(__le64)); | ||
mutex_unlock(&pil_reloc_lock); | ||
|
||
return 0; | ||
} | ||
EXPORT_SYMBOL_GPL(qcom_pil_info_store); | ||
|
||
static void __exit pil_reloc_exit(void) | ||
{ | ||
mutex_lock(&pil_reloc_lock); | ||
iounmap(_reloc.base); | ||
_reloc.base = NULL; | ||
mutex_unlock(&pil_reloc_lock); | ||
} | ||
module_exit(pil_reloc_exit); | ||
|
||
MODULE_DESCRIPTION("Qualcomm PIL relocation info"); | ||
MODULE_LICENSE("GPL v2"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
#ifndef __QCOM_PIL_INFO_H__ | ||
#define __QCOM_PIL_INFO_H__ | ||
|
||
#include <linux/types.h> | ||
|
||
int qcom_pil_info_store(const char *image, phys_addr_t base, size_t size); | ||
|
||
#endif |