diff options
Diffstat (limited to 'drivers/mtd/parsers')
-rw-r--r-- | drivers/mtd/parsers/Kconfig | 24 | ||||
-rw-r--r-- | drivers/mtd/parsers/Makefile | 3 | ||||
-rw-r--r-- | drivers/mtd/parsers/ofpart_bcm4908.c | 64 | ||||
-rw-r--r-- | drivers/mtd/parsers/ofpart_bcm4908.h | 15 | ||||
-rw-r--r-- | drivers/mtd/parsers/ofpart_core.c (renamed from drivers/mtd/parsers/ofpart.c) | 38 | ||||
-rw-r--r-- | drivers/mtd/parsers/ofpart_linksys_ns.c | 50 | ||||
-rw-r--r-- | drivers/mtd/parsers/ofpart_linksys_ns.h | 18 | ||||
-rw-r--r-- | drivers/mtd/parsers/qcomsmempart.c | 9 |
8 files changed, 214 insertions, 7 deletions
diff --git a/drivers/mtd/parsers/Kconfig b/drivers/mtd/parsers/Kconfig index d90c30229052..9babe678c41b 100644 --- a/drivers/mtd/parsers/Kconfig +++ b/drivers/mtd/parsers/Kconfig @@ -67,6 +67,25 @@ config MTD_OF_PARTS flash memory node, as described in Documentation/devicetree/bindings/mtd/partition.txt. +config MTD_OF_PARTS_BCM4908 + bool "BCM4908 partitioning support" + depends on MTD_OF_PARTS && (ARCH_BCM4908 || COMPILE_TEST) + default ARCH_BCM4908 + help + This provides partitions parser for BCM4908 family devices + that can have multiple "firmware" partitions. It takes care of + finding currently used one and backup ones. + +config MTD_OF_PARTS_LINKSYS_NS + bool "Linksys Northstar partitioning support" + depends on MTD_OF_PARTS && (ARCH_BCM_5301X || ARCH_BCM4908 || COMPILE_TEST) + default ARCH_BCM_5301X + help + This provides partitions parser for Linksys devices based on Broadcom + Northstar architecture. Linksys commonly uses fixed flash layout with + two "firmware" partitions. Currently used firmware has to be detected + using CFE environment variable. + config MTD_PARSER_IMAGETAG tristate "Parser for BCM963XX Image Tag format partitions" depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST @@ -162,9 +181,8 @@ config MTD_REDBOOT_PARTS_READONLY endif # MTD_REDBOOT_PARTS config MTD_QCOMSMEM_PARTS - tristate "Qualcomm SMEM NAND flash partition parser" - depends on MTD_NAND_QCOM || COMPILE_TEST + tristate "Qualcomm SMEM flash partition parser" depends on QCOM_SMEM help This provides support for parsing partitions from Shared Memory (SMEM) - for NAND flash on Qualcomm platforms. + for NAND and SPI flash on Qualcomm platforms. diff --git a/drivers/mtd/parsers/Makefile b/drivers/mtd/parsers/Makefile index 50eb0b0a2210..2e98aa048278 100644 --- a/drivers/mtd/parsers/Makefile +++ b/drivers/mtd/parsers/Makefile @@ -4,6 +4,9 @@ obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o +ofpart-y += ofpart_core.o +ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += ofpart_bcm4908.o +ofpart-$(CONFIG_MTD_OF_PARTS_LINKSYS_NS)+= ofpart_linksys_ns.o obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o obj-$(CONFIG_MTD_AFS_PARTS) += afs.o obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o diff --git a/drivers/mtd/parsers/ofpart_bcm4908.c b/drivers/mtd/parsers/ofpart_bcm4908.c new file mode 100644 index 000000000000..0eddef4c198e --- /dev/null +++ b/drivers/mtd/parsers/ofpart_bcm4908.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021 Rafał Miłecki <rafal@milecki.pl> + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/of.h> +#include <linux/mtd/mtd.h> +#include <linux/slab.h> +#include <linux/mtd/partitions.h> + +#include "ofpart_bcm4908.h" + +#define BLPARAMS_FW_OFFSET "NAND_RFS_OFS" + +static long long bcm4908_partitions_fw_offset(void) +{ + struct device_node *root; + struct property *prop; + const char *s; + + root = of_find_node_by_path("/"); + if (!root) + return -ENOENT; + + of_property_for_each_string(root, "brcm_blparms", prop, s) { + size_t len = strlen(BLPARAMS_FW_OFFSET); + unsigned long offset; + int err; + + if (strncmp(s, BLPARAMS_FW_OFFSET, len) || s[len] != '=') + continue; + + err = kstrtoul(s + len + 1, 0, &offset); + if (err) { + pr_err("failed to parse %s\n", s + len + 1); + return err; + } + + return offset << 10; + } + + return -ENOENT; +} + +int bcm4908_partitions_post_parse(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts) +{ + long long fw_offset; + int i; + + fw_offset = bcm4908_partitions_fw_offset(); + + for (i = 0; i < nr_parts; i++) { + if (of_device_is_compatible(parts[i].of_node, "brcm,bcm4908-firmware")) { + if (fw_offset < 0 || parts[i].offset == fw_offset) + parts[i].name = "firmware"; + else + parts[i].name = "backup"; + } + } + + return 0; +} diff --git a/drivers/mtd/parsers/ofpart_bcm4908.h b/drivers/mtd/parsers/ofpart_bcm4908.h new file mode 100644 index 000000000000..80f8c086641f --- /dev/null +++ b/drivers/mtd/parsers/ofpart_bcm4908.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __BCM4908_PARTITIONS_H +#define __BCM4908_PARTITIONS_H + +#ifdef CONFIG_MTD_OF_PARTS_BCM4908 +int bcm4908_partitions_post_parse(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts); +#else +static inline int bcm4908_partitions_post_parse(struct mtd_info *mtd, struct mtd_partition *parts, + int nr_parts) +{ + return -EOPNOTSUPP; +} +#endif + +#endif diff --git a/drivers/mtd/parsers/ofpart.c b/drivers/mtd/parsers/ofpart_core.c index daf507c123e6..0fd8d2a0db97 100644 --- a/drivers/mtd/parsers/ofpart.c +++ b/drivers/mtd/parsers/ofpart_core.c @@ -16,6 +16,23 @@ #include <linux/slab.h> #include <linux/mtd/partitions.h> +#include "ofpart_bcm4908.h" +#include "ofpart_linksys_ns.h" + +struct fixed_partitions_quirks { + int (*post_parse)(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts); +}; + +static struct fixed_partitions_quirks bcm4908_partitions_quirks = { + .post_parse = bcm4908_partitions_post_parse, +}; + +static struct fixed_partitions_quirks linksys_ns_partitions_quirks = { + .post_parse = linksys_ns_partitions_post_parse, +}; + +static const struct of_device_id parse_ofpart_match_table[]; + static bool node_has_compatible(struct device_node *pp) { return of_get_property(pp, "compatible", NULL); @@ -25,6 +42,8 @@ static int parse_fixed_partitions(struct mtd_info *master, const struct mtd_partition **pparts, struct mtd_part_parser_data *data) { + const struct fixed_partitions_quirks *quirks; + const struct of_device_id *of_id; struct mtd_partition *parts; struct device_node *mtd_node; struct device_node *ofpart_node; @@ -33,14 +52,13 @@ static int parse_fixed_partitions(struct mtd_info *master, int nr_parts, i, ret = 0; bool dedicated = true; - /* Pull of_node from the master device node */ mtd_node = mtd_get_of_node(master); if (!mtd_node) return 0; ofpart_node = of_get_child_by_name(mtd_node, "partitions"); - if (!ofpart_node) { + if (!ofpart_node && !master->parent) { /* * We might get here even when ofpart isn't used at all (e.g., * when using another parser), so don't be louder than @@ -50,11 +68,18 @@ static int parse_fixed_partitions(struct mtd_info *master, master->name, mtd_node); ofpart_node = mtd_node; dedicated = false; - } else if (!of_device_is_compatible(ofpart_node, "fixed-partitions")) { + } + if (!ofpart_node) + return 0; + + of_id = of_match_node(parse_ofpart_match_table, ofpart_node); + if (dedicated && !of_id) { /* The 'partitions' subnode might be used by another parser */ return 0; } + quirks = of_id ? of_id->data : NULL; + /* First count the subnodes */ nr_parts = 0; for_each_child_of_node(ofpart_node, pp) { @@ -126,6 +151,9 @@ static int parse_fixed_partitions(struct mtd_info *master, if (!nr_parts) goto ofpart_none; + if (quirks && quirks->post_parse) + quirks->post_parse(master, parts, nr_parts); + *pparts = parts; return nr_parts; @@ -140,7 +168,11 @@ ofpart_none: } static const struct of_device_id parse_ofpart_match_table[] = { + /* Generic */ { .compatible = "fixed-partitions" }, + /* Customized */ + { .compatible = "brcm,bcm4908-partitions", .data = &bcm4908_partitions_quirks, }, + { .compatible = "linksys,ns-partitions", .data = &linksys_ns_partitions_quirks, }, {}, }; MODULE_DEVICE_TABLE(of, parse_ofpart_match_table); diff --git a/drivers/mtd/parsers/ofpart_linksys_ns.c b/drivers/mtd/parsers/ofpart_linksys_ns.c new file mode 100644 index 000000000000..318c42d0256b --- /dev/null +++ b/drivers/mtd/parsers/ofpart_linksys_ns.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021 Rafał Miłecki <rafal@milecki.pl> + */ + +#include <linux/bcm47xx_nvram.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> + +#include "ofpart_linksys_ns.h" + +#define NVRAM_BOOT_PART "bootpartition" + +static int ofpart_linksys_ns_bootpartition(void) +{ + char buf[4]; + int bootpartition; + + /* Check CFE environment variable */ + if (bcm47xx_nvram_getenv(NVRAM_BOOT_PART, buf, sizeof(buf)) > 0) { + if (!kstrtoint(buf, 0, &bootpartition)) + return bootpartition; + pr_warn("Failed to parse %s value \"%s\"\n", NVRAM_BOOT_PART, + buf); + } else { + pr_warn("Failed to get NVRAM \"%s\"\n", NVRAM_BOOT_PART); + } + + return 0; +} + +int linksys_ns_partitions_post_parse(struct mtd_info *mtd, + struct mtd_partition *parts, + int nr_parts) +{ + int bootpartition = ofpart_linksys_ns_bootpartition(); + int trx_idx = 0; + int i; + + for (i = 0; i < nr_parts; i++) { + if (of_device_is_compatible(parts[i].of_node, "linksys,ns-firmware")) { + if (trx_idx++ == bootpartition) + parts[i].name = "firmware"; + else + parts[i].name = "backup"; + } + } + + return 0; +} diff --git a/drivers/mtd/parsers/ofpart_linksys_ns.h b/drivers/mtd/parsers/ofpart_linksys_ns.h new file mode 100644 index 000000000000..730c46812ebf --- /dev/null +++ b/drivers/mtd/parsers/ofpart_linksys_ns.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __OFPART_LINKSYS_NS_H +#define __OFPART_LINKSYS_NS_H + +#ifdef CONFIG_MTD_OF_PARTS_LINKSYS_NS +int linksys_ns_partitions_post_parse(struct mtd_info *mtd, + struct mtd_partition *parts, + int nr_parts); +#else +static inline int linksys_ns_partitions_post_parse(struct mtd_info *mtd, + struct mtd_partition *parts, + int nr_parts) +{ + return -EOPNOTSUPP; +} +#endif + +#endif diff --git a/drivers/mtd/parsers/qcomsmempart.c b/drivers/mtd/parsers/qcomsmempart.c index 808cb33d71f8..d9083308f6ba 100644 --- a/drivers/mtd/parsers/qcomsmempart.c +++ b/drivers/mtd/parsers/qcomsmempart.c @@ -65,6 +65,13 @@ static int parse_qcomsmem_part(struct mtd_info *mtd, int ret, i, numparts; char *name, *c; + if (IS_ENABLED(CONFIG_MTD_SPI_NOR_USE_4K_SECTORS) + && mtd->type == MTD_NORFLASH) { + pr_err("%s: SMEM partition parser is incompatible with 4K sectors\n", + mtd->name); + return -EINVAL; + } + pr_debug("Parsing partition table info from SMEM\n"); ptable = qcom_smem_get(SMEM_APPS, SMEM_AARM_PARTITION_TABLE, &len); if (IS_ERR(ptable)) { @@ -104,7 +111,7 @@ static int parse_qcomsmem_part(struct mtd_info *mtd, * complete partition table */ ptable = qcom_smem_get(SMEM_APPS, SMEM_AARM_PARTITION_TABLE, &len); - if (IS_ERR_OR_NULL(ptable)) { + if (IS_ERR(ptable)) { pr_err("Error reading partition table\n"); return PTR_ERR(ptable); } |