1 From 09cf6ee6d21cd9ef2eb857ccb24305cf51166792 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
3 Date: Thu, 11 Feb 2021 23:04:27 +0100
4 Subject: [PATCH] mtd: parsers: ofpart: support BCM4908 fixed partitions
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
9 BCM4908 partitioning is based on fixed layout but allows specifying
10 multiple firmware partitions. It requires detecting which firmware
11 partition was used for booting current kernel.
13 To support such cases without duplicating a lot of code (without copying
14 most of the ofpart.c code) support for post-parsing callback was added.
16 BCM4908 callback simply reads offset of currently used firmware
17 partition from the DT. Bootloader specifies it using the "brcm_blparms"
20 Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
21 Signed-off-by: Richard Weinberger <richard@nod.at>
23 drivers/mtd/parsers/Makefile | 1 +
24 drivers/mtd/parsers/bcm4908-partitions.c | 64 ++++++++++++++++++++++++
25 drivers/mtd/parsers/bcm4908-partitions.h | 7 +++
26 drivers/mtd/parsers/ofpart.c | 28 ++++++++++-
27 4 files changed, 98 insertions(+), 2 deletions(-)
28 create mode 100644 drivers/mtd/parsers/bcm4908-partitions.c
29 create mode 100644 drivers/mtd/parsers/bcm4908-partitions.h
31 --- a/drivers/mtd/parsers/Makefile
32 +++ b/drivers/mtd/parsers/Makefile
33 @@ -4,6 +4,7 @@ obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm4
34 obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o
35 obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
36 obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o
37 +obj-$(CONFIG_MTD_OF_PARTS) += bcm4908-partitions.o
38 obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o
39 obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
40 obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o
42 +++ b/drivers/mtd/parsers/bcm4908-partitions.c
44 +// SPDX-License-Identifier: GPL-2.0
46 + * Copyright (C) 2021 Rafał Miłecki <rafal@milecki.pl>
49 +#include <linux/module.h>
50 +#include <linux/init.h>
51 +#include <linux/of.h>
52 +#include <linux/mtd/mtd.h>
53 +#include <linux/slab.h>
54 +#include <linux/mtd/partitions.h>
56 +#include "bcm4908-partitions.h"
58 +#define BLPARAMS_FW_OFFSET "NAND_RFS_OFS"
60 +static long long bcm4908_partitions_fw_offset(void)
62 + struct device_node *root;
63 + struct property *prop;
66 + root = of_find_node_by_path("/");
70 + of_property_for_each_string(root, "brcm_blparms", prop, s) {
71 + size_t len = strlen(BLPARAMS_FW_OFFSET);
72 + unsigned long offset;
75 + if (strncmp(s, BLPARAMS_FW_OFFSET, len) || s[len] != '=')
78 + err = kstrtoul(s + len + 1, 0, &offset);
80 + pr_err("failed to parse %s\n", s + len + 1);
84 + return offset << 10;
90 +int bcm4908_partitions_post_parse(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts)
92 + long long fw_offset;
95 + fw_offset = bcm4908_partitions_fw_offset();
97 + for (i = 0; i < nr_parts; i++) {
98 + if (of_device_is_compatible(parts[i].of_node, "brcm,bcm4908-firmware")) {
99 + if (fw_offset < 0 || parts[i].offset == fw_offset)
100 + parts[i].name = "firmware";
102 + parts[i].name = "backup";
109 +++ b/drivers/mtd/parsers/bcm4908-partitions.h
111 +/* SPDX-License-Identifier: GPL-2.0 */
112 +#ifndef __BCM4908_PARTITIONS_H
113 +#define __BCM4908_PARTITIONS_H
115 +int bcm4908_partitions_post_parse(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts);
118 --- a/drivers/mtd/parsers/ofpart.c
119 +++ b/drivers/mtd/parsers/ofpart.c
121 #include <linux/slab.h>
122 #include <linux/mtd/partitions.h>
124 +#include "bcm4908-partitions.h"
126 +struct fixed_partitions_quirks {
127 + int (*post_parse)(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts);
130 +struct fixed_partitions_quirks bcm4908_partitions_quirks = {
131 + .post_parse = bcm4908_partitions_post_parse,
134 +static const struct of_device_id parse_ofpart_match_table[];
136 static bool node_has_compatible(struct device_node *pp)
138 return of_get_property(pp, "compatible", NULL);
139 @@ -25,6 +37,8 @@ static int parse_fixed_partitions(struct
140 const struct mtd_partition **pparts,
141 struct mtd_part_parser_data *data)
143 + const struct fixed_partitions_quirks *quirks;
144 + const struct of_device_id *of_id;
145 struct mtd_partition *parts;
146 struct device_node *mtd_node;
147 struct device_node *ofpart_node;
148 @@ -33,7 +47,6 @@ static int parse_fixed_partitions(struct
149 int nr_parts, i, ret = 0;
150 bool dedicated = true;
153 /* Pull of_node from the master device node */
154 mtd_node = mtd_get_of_node(master);
156 @@ -50,11 +63,16 @@ static int parse_fixed_partitions(struct
157 master->name, mtd_node);
158 ofpart_node = mtd_node;
160 - } else if (!of_device_is_compatible(ofpart_node, "fixed-partitions")) {
163 + of_id = of_match_node(parse_ofpart_match_table, ofpart_node);
164 + if (dedicated && !of_id) {
165 /* The 'partitions' subnode might be used by another parser */
169 + quirks = of_id ? of_id->data : NULL;
171 /* First count the subnodes */
173 for_each_child_of_node(ofpart_node, pp) {
174 @@ -123,6 +141,9 @@ static int parse_fixed_partitions(struct
178 + if (quirks && quirks->post_parse)
179 + quirks->post_parse(master, parts, nr_parts);
184 @@ -137,7 +158,10 @@ ofpart_none:
187 static const struct of_device_id parse_ofpart_match_table[] = {
189 { .compatible = "fixed-partitions" },
191 + { .compatible = "brcm,bcm4908-partitions", .data = &bcm4908_partitions_quirks, },
194 MODULE_DEVICE_TABLE(of, parse_ofpart_match_table);