Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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