diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mtd/parsers/Kconfig | 9 | ||||
-rw-r--r-- | drivers/mtd/parsers/Makefile | 2 | ||||
-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) | 28 |
5 files changed, 116 insertions, 2 deletions
diff --git a/drivers/mtd/parsers/Kconfig b/drivers/mtd/parsers/Kconfig index 96d5716db544..0528855cf6c1 100644 --- a/drivers/mtd/parsers/Kconfig +++ b/drivers/mtd/parsers/Kconfig @@ -67,6 +67,15 @@ 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_PARSER_IMAGETAG tristate "Parser for BCM963XX Image Tag format partitions" depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST diff --git a/drivers/mtd/parsers/Makefile b/drivers/mtd/parsers/Makefile index 50eb0b0a2210..2dfe9fb602de 100644 --- a/drivers/mtd/parsers/Makefile +++ b/drivers/mtd/parsers/Makefile @@ -4,6 +4,8 @@ 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 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..258c06a42283 100644 --- a/drivers/mtd/parsers/ofpart.c +++ b/drivers/mtd/parsers/ofpart_core.c @@ -16,6 +16,18 @@ #include <linux/slab.h> #include <linux/mtd/partitions.h> +#include "ofpart_bcm4908.h" + +struct fixed_partitions_quirks { + int (*post_parse)(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts); +}; + +struct fixed_partitions_quirks bcm4908_partitions_quirks = { + .post_parse = bcm4908_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 +37,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,7 +47,6 @@ 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) @@ -50,11 +63,16 @@ 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")) { + } + + 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 +144,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 +161,10 @@ 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, }, {}, }; MODULE_DEVICE_TABLE(of, parse_ofpart_match_table); |