101-5.12-mtd-parsers-Add-Qcom-SMEM-parser.patch 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. From 803eb124e1a64e42888542c3444bfe6dac412c7f Mon Sep 17 00:00:00 2001
  2. From: Manivannan Sadhasivam <[email protected]>
  3. Date: Mon, 4 Jan 2021 09:41:35 +0530
  4. Subject: mtd: parsers: Add Qcom SMEM parser
  5. NAND based Qualcomm platforms have the partition table populated in the
  6. Shared Memory (SMEM). Hence, add a parser for parsing the partitions
  7. from it.
  8. Signed-off-by: Manivannan Sadhasivam <[email protected]>
  9. Signed-off-by: Miquel Raynal <[email protected]>
  10. Link: https://lore.kernel.org/linux-mtd/[email protected]
  11. ---
  12. drivers/mtd/parsers/Kconfig | 8 ++
  13. drivers/mtd/parsers/Makefile | 1 +
  14. drivers/mtd/parsers/qcomsmempart.c | 170 +++++++++++++++++++++++++++++++++++++
  15. 3 files changed, 179 insertions(+)
  16. create mode 100644 drivers/mtd/parsers/qcomsmempart.c
  17. diff --git a/drivers/mtd/parsers/Kconfig b/drivers/mtd/parsers/Kconfig
  18. index e72354322f628..d90c302290522 100644
  19. --- a/drivers/mtd/parsers/Kconfig
  20. +++ b/drivers/mtd/parsers/Kconfig
  21. @@ -160,6 +160,14 @@ config MTD_REDBOOT_PARTS_READONLY
  22. 'FIS directory' images, enable this option.
  23. endif # MTD_REDBOOT_PARTS
  24. +
  25. +config MTD_QCOMSMEM_PARTS
  26. + tristate "Qualcomm SMEM NAND flash partition parser"
  27. + depends on MTD_NAND_QCOM || COMPILE_TEST
  28. + depends on QCOM_SMEM
  29. + help
  30. + This provides support for parsing partitions from Shared Memory (SMEM)
  31. + for NAND flash on Qualcomm platforms.
  32. config MTD_ROUTERBOOT_PARTS
  33. tristate "RouterBoot flash partition parser"
  34. diff --git a/drivers/mtd/parsers/Makefile b/drivers/mtd/parsers/Makefile
  35. index b0c5f62f9e858..50eb0b0a22105 100644
  36. --- a/drivers/mtd/parsers/Makefile
  37. +++ b/drivers/mtd/parsers/Makefile
  38. @@ -9,4 +9,5 @@ obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
  39. obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o
  40. obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o
  41. obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
  42. +obj-$(CONFIG_MTD_QCOMSMEM_PARTS) += qcomsmempart.o
  43. obj-$(CONFIG_MTD_ROUTERBOOT_PARTS) += routerbootpart.o
  44. diff --git a/drivers/mtd/parsers/qcomsmempart.c b/drivers/mtd/parsers/qcomsmempart.c
  45. new file mode 100644
  46. index 0000000000000..808cb33d71f8e
  47. --- /dev/null
  48. +++ b/drivers/mtd/parsers/qcomsmempart.c
  49. @@ -0,0 +1,170 @@
  50. +// SPDX-License-Identifier: GPL-2.0-only
  51. +/*
  52. + * Qualcomm SMEM NAND flash partition parser
  53. + *
  54. + * Copyright (C) 2020, Linaro Ltd.
  55. + */
  56. +
  57. +#include <linux/ctype.h>
  58. +#include <linux/module.h>
  59. +#include <linux/mtd/mtd.h>
  60. +#include <linux/mtd/partitions.h>
  61. +#include <linux/slab.h>
  62. +#include <linux/soc/qcom/smem.h>
  63. +
  64. +#define SMEM_AARM_PARTITION_TABLE 9
  65. +#define SMEM_APPS 0
  66. +
  67. +#define SMEM_FLASH_PART_MAGIC1 0x55ee73aa
  68. +#define SMEM_FLASH_PART_MAGIC2 0xe35ebddb
  69. +#define SMEM_FLASH_PTABLE_V3 3
  70. +#define SMEM_FLASH_PTABLE_V4 4
  71. +#define SMEM_FLASH_PTABLE_MAX_PARTS_V3 16
  72. +#define SMEM_FLASH_PTABLE_MAX_PARTS_V4 48
  73. +#define SMEM_FLASH_PTABLE_HDR_LEN (4 * sizeof(u32))
  74. +#define SMEM_FLASH_PTABLE_NAME_SIZE 16
  75. +
  76. +/**
  77. + * struct smem_flash_pentry - SMEM Flash partition entry
  78. + * @name: Name of the partition
  79. + * @offset: Offset in blocks
  80. + * @length: Length of the partition in blocks
  81. + * @attr: Flags for this partition
  82. + */
  83. +struct smem_flash_pentry {
  84. + char name[SMEM_FLASH_PTABLE_NAME_SIZE];
  85. + __le32 offset;
  86. + __le32 length;
  87. + u8 attr;
  88. +} __packed __aligned(4);
  89. +
  90. +/**
  91. + * struct smem_flash_ptable - SMEM Flash partition table
  92. + * @magic1: Partition table Magic 1
  93. + * @magic2: Partition table Magic 2
  94. + * @version: Partition table version
  95. + * @numparts: Number of partitions in this ptable
  96. + * @pentry: Flash partition entries belonging to this ptable
  97. + */
  98. +struct smem_flash_ptable {
  99. + __le32 magic1;
  100. + __le32 magic2;
  101. + __le32 version;
  102. + __le32 numparts;
  103. + struct smem_flash_pentry pentry[SMEM_FLASH_PTABLE_MAX_PARTS_V4];
  104. +} __packed __aligned(4);
  105. +
  106. +static int parse_qcomsmem_part(struct mtd_info *mtd,
  107. + const struct mtd_partition **pparts,
  108. + struct mtd_part_parser_data *data)
  109. +{
  110. + struct smem_flash_pentry *pentry;
  111. + struct smem_flash_ptable *ptable;
  112. + size_t len = SMEM_FLASH_PTABLE_HDR_LEN;
  113. + struct mtd_partition *parts;
  114. + int ret, i, numparts;
  115. + char *name, *c;
  116. +
  117. + pr_debug("Parsing partition table info from SMEM\n");
  118. + ptable = qcom_smem_get(SMEM_APPS, SMEM_AARM_PARTITION_TABLE, &len);
  119. + if (IS_ERR(ptable)) {
  120. + pr_err("Error reading partition table header\n");
  121. + return PTR_ERR(ptable);
  122. + }
  123. +
  124. + /* Verify ptable magic */
  125. + if (le32_to_cpu(ptable->magic1) != SMEM_FLASH_PART_MAGIC1 ||
  126. + le32_to_cpu(ptable->magic2) != SMEM_FLASH_PART_MAGIC2) {
  127. + pr_err("Partition table magic verification failed\n");
  128. + return -EINVAL;
  129. + }
  130. +
  131. + /* Ensure that # of partitions is less than the max we have allocated */
  132. + numparts = le32_to_cpu(ptable->numparts);
  133. + if (numparts > SMEM_FLASH_PTABLE_MAX_PARTS_V4) {
  134. + pr_err("Partition numbers exceed the max limit\n");
  135. + return -EINVAL;
  136. + }
  137. +
  138. + /* Find out length of partition data based on table version */
  139. + if (le32_to_cpu(ptable->version) <= SMEM_FLASH_PTABLE_V3) {
  140. + len = SMEM_FLASH_PTABLE_HDR_LEN + SMEM_FLASH_PTABLE_MAX_PARTS_V3 *
  141. + sizeof(struct smem_flash_pentry);
  142. + } else if (le32_to_cpu(ptable->version) == SMEM_FLASH_PTABLE_V4) {
  143. + len = SMEM_FLASH_PTABLE_HDR_LEN + SMEM_FLASH_PTABLE_MAX_PARTS_V4 *
  144. + sizeof(struct smem_flash_pentry);
  145. + } else {
  146. + pr_err("Unknown ptable version (%d)", le32_to_cpu(ptable->version));
  147. + return -EINVAL;
  148. + }
  149. +
  150. + /*
  151. + * Now that the partition table header has been parsed, verified
  152. + * and the length of the partition table calculated, read the
  153. + * complete partition table
  154. + */
  155. + ptable = qcom_smem_get(SMEM_APPS, SMEM_AARM_PARTITION_TABLE, &len);
  156. + if (IS_ERR_OR_NULL(ptable)) {
  157. + pr_err("Error reading partition table\n");
  158. + return PTR_ERR(ptable);
  159. + }
  160. +
  161. + parts = kcalloc(numparts, sizeof(*parts), GFP_KERNEL);
  162. + if (!parts)
  163. + return -ENOMEM;
  164. +
  165. + for (i = 0; i < numparts; i++) {
  166. + pentry = &ptable->pentry[i];
  167. + if (pentry->name[0] == '\0')
  168. + continue;
  169. +
  170. + name = kstrdup(pentry->name, GFP_KERNEL);
  171. + if (!name) {
  172. + ret = -ENOMEM;
  173. + goto out_free_parts;
  174. + }
  175. +
  176. + /* Convert name to lower case */
  177. + for (c = name; *c != '\0'; c++)
  178. + *c = tolower(*c);
  179. +
  180. + parts[i].name = name;
  181. + parts[i].offset = le32_to_cpu(pentry->offset) * mtd->erasesize;
  182. + parts[i].mask_flags = pentry->attr;
  183. + parts[i].size = le32_to_cpu(pentry->length) * mtd->erasesize;
  184. + pr_debug("%d: %s offs=0x%08x size=0x%08x attr:0x%08x\n",
  185. + i, pentry->name, le32_to_cpu(pentry->offset),
  186. + le32_to_cpu(pentry->length), pentry->attr);
  187. + }
  188. +
  189. + pr_debug("SMEM partition table found: ver: %d len: %d\n",
  190. + le32_to_cpu(ptable->version), numparts);
  191. + *pparts = parts;
  192. +
  193. + return numparts;
  194. +
  195. +out_free_parts:
  196. + while (--i >= 0)
  197. + kfree(parts[i].name);
  198. + kfree(parts);
  199. + *pparts = NULL;
  200. +
  201. + return ret;
  202. +}
  203. +
  204. +static const struct of_device_id qcomsmem_of_match_table[] = {
  205. + { .compatible = "qcom,smem-part" },
  206. + {},
  207. +};
  208. +MODULE_DEVICE_TABLE(of, qcomsmem_of_match_table);
  209. +
  210. +static struct mtd_part_parser mtd_parser_qcomsmem = {
  211. + .parse_fn = parse_qcomsmem_part,
  212. + .name = "qcomsmem",
  213. + .of_match_table = qcomsmem_of_match_table,
  214. +};
  215. +module_mtd_part_parser(mtd_parser_qcomsmem);
  216. +
  217. +MODULE_LICENSE("GPL v2");
  218. +MODULE_AUTHOR("Manivannan Sadhasivam <[email protected]>");
  219. +MODULE_DESCRIPTION("Qualcomm SMEM NAND flash partition parser");
  220. --
  221. cgit 1.2.3-1.el7