Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+142
+3
drivers/remoteproc/Kconfig
··· 116 116 It's safe to say N here if you're not interested in the Keystone 117 117 DSPs or just want to use a bare minimum kernel. 118 118 119 + config QCOM_PIL_INFO 120 + tristate 121 + 119 122 config QCOM_RPROC_COMMON 120 123 tristate 121 124
+1
drivers/remoteproc/Makefile
··· 16 16 obj-$(CONFIG_WKUP_M3_RPROC) += wkup_m3_rproc.o 17 17 obj-$(CONFIG_DA8XX_REMOTEPROC) += da8xx_remoteproc.o 18 18 obj-$(CONFIG_KEYSTONE_REMOTEPROC) += keystone_remoteproc.o 19 + obj-$(CONFIG_QCOM_PIL_INFO) += qcom_pil_info.o 19 20 obj-$(CONFIG_QCOM_RPROC_COMMON) += qcom_common.o 20 21 obj-$(CONFIG_QCOM_Q6V5_COMMON) += qcom_q6v5.o 21 22 obj-$(CONFIG_QCOM_Q6V5_ADSP) += qcom_q6v5_adsp.o
+129
drivers/remoteproc/qcom_pil_info.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2019-2020 Linaro Ltd. 4 + */ 5 + #include <linux/kernel.h> 6 + #include <linux/module.h> 7 + #include <linux/mutex.h> 8 + #include <linux/of_address.h> 9 + #include "qcom_pil_info.h" 10 + 11 + /* 12 + * The PIL relocation information region is used to communicate memory regions 13 + * occupied by co-processor firmware for post mortem crash analysis. 14 + * 15 + * It consists of an array of entries with an 8 byte textual identifier of the 16 + * region followed by a 64 bit base address and 32 bit size, both little 17 + * endian. 18 + */ 19 + #define PIL_RELOC_NAME_LEN 8 20 + #define PIL_RELOC_ENTRY_SIZE (PIL_RELOC_NAME_LEN + sizeof(__le64) + sizeof(__le32)) 21 + 22 + struct pil_reloc { 23 + void __iomem *base; 24 + size_t num_entries; 25 + }; 26 + 27 + static struct pil_reloc _reloc __read_mostly; 28 + static DEFINE_MUTEX(pil_reloc_lock); 29 + 30 + static int qcom_pil_info_init(void) 31 + { 32 + struct device_node *np; 33 + struct resource imem; 34 + void __iomem *base; 35 + int ret; 36 + 37 + /* Already initialized? */ 38 + if (_reloc.base) 39 + return 0; 40 + 41 + np = of_find_compatible_node(NULL, NULL, "qcom,pil-reloc-info"); 42 + if (!np) 43 + return -ENOENT; 44 + 45 + ret = of_address_to_resource(np, 0, &imem); 46 + of_node_put(np); 47 + if (ret < 0) 48 + return ret; 49 + 50 + base = ioremap(imem.start, resource_size(&imem)); 51 + if (!base) { 52 + pr_err("failed to map PIL relocation info region\n"); 53 + return -ENOMEM; 54 + } 55 + 56 + memset_io(base, 0, resource_size(&imem)); 57 + 58 + _reloc.base = base; 59 + _reloc.num_entries = resource_size(&imem) / PIL_RELOC_ENTRY_SIZE; 60 + 61 + return 0; 62 + } 63 + 64 + /** 65 + * qcom_pil_info_store() - store PIL information of image in IMEM 66 + * @image: name of the image 67 + * @base: base address of the loaded image 68 + * @size: size of the loaded image 69 + * 70 + * Return: 0 on success, negative errno on failure 71 + */ 72 + int qcom_pil_info_store(const char *image, phys_addr_t base, size_t size) 73 + { 74 + char buf[PIL_RELOC_NAME_LEN]; 75 + void __iomem *entry; 76 + int ret; 77 + int i; 78 + 79 + mutex_lock(&pil_reloc_lock); 80 + ret = qcom_pil_info_init(); 81 + if (ret < 0) { 82 + mutex_unlock(&pil_reloc_lock); 83 + return ret; 84 + } 85 + 86 + for (i = 0; i < _reloc.num_entries; i++) { 87 + entry = _reloc.base + i * PIL_RELOC_ENTRY_SIZE; 88 + 89 + memcpy_fromio(buf, entry, PIL_RELOC_NAME_LEN); 90 + 91 + /* 92 + * An empty record means we didn't find it, given that the 93 + * records are packed. 94 + */ 95 + if (!buf[0]) 96 + goto found_unused; 97 + 98 + if (!strncmp(buf, image, PIL_RELOC_NAME_LEN)) 99 + goto found_existing; 100 + } 101 + 102 + pr_warn("insufficient PIL info slots\n"); 103 + mutex_unlock(&pil_reloc_lock); 104 + return -ENOMEM; 105 + 106 + found_unused: 107 + memcpy_toio(entry, image, PIL_RELOC_NAME_LEN); 108 + found_existing: 109 + /* Use two writel() as base is only aligned to 4 bytes on odd entries */ 110 + writel(base, entry + PIL_RELOC_NAME_LEN); 111 + writel(base >> 32, entry + PIL_RELOC_NAME_LEN + 4); 112 + writel(size, entry + PIL_RELOC_NAME_LEN + sizeof(__le64)); 113 + mutex_unlock(&pil_reloc_lock); 114 + 115 + return 0; 116 + } 117 + EXPORT_SYMBOL_GPL(qcom_pil_info_store); 118 + 119 + static void __exit pil_reloc_exit(void) 120 + { 121 + mutex_lock(&pil_reloc_lock); 122 + iounmap(_reloc.base); 123 + _reloc.base = NULL; 124 + mutex_unlock(&pil_reloc_lock); 125 + } 126 + module_exit(pil_reloc_exit); 127 + 128 + MODULE_DESCRIPTION("Qualcomm PIL relocation info"); 129 + MODULE_LICENSE("GPL v2");
+9
drivers/remoteproc/qcom_pil_info.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef __QCOM_PIL_INFO_H__ 3 + #define __QCOM_PIL_INFO_H__ 4 + 5 + #include <linux/types.h> 6 + 7 + int qcom_pil_info_store(const char *image, phys_addr_t base, size_t size); 8 + 9 + #endif