1 From db18357719613cc40234300b10e28e4dfa075375 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
3 Date: Fri, 15 Jan 2021 16:23:01 +0100
4 Subject: [PATCH 3/3] 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>
22 drivers/mtd/parsers/Makefile | 1 +
23 drivers/mtd/parsers/bcm4908-partitions.c | 62 ++++++++++++++++++++++++
24 drivers/mtd/parsers/bcm4908-partitions.h | 7 +++
25 drivers/mtd/parsers/ofpart.c | 28 ++++++++++-
26 4 files changed, 96 insertions(+), 2 deletions(-)
27 create mode 100644 drivers/mtd/parsers/bcm4908-partitions.c
28 create mode 100644 drivers/mtd/parsers/bcm4908-partitions.h
30 --- a/drivers/mtd/parsers/Makefile
31 +++ b/drivers/mtd/parsers/Makefile
32 @@ -5,6 +5,7 @@ obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm6
33 obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
34 obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o
35 obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o
36 +obj-$(CONFIG_MTD_OF_PARTS) += bcm4908-partitions.o
37 obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o
38 obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
39 obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o
41 +++ b/drivers/mtd/parsers/bcm4908-partitions.c
43 +// SPDX-License-Identifier: GPL-2.0
45 + * Copyright (C) 2021 Rafał Miłecki <rafal@milecki.pl>
48 +#include <linux/module.h>
49 +#include <linux/init.h>
50 +#include <linux/of.h>
51 +#include <linux/mtd/mtd.h>
52 +#include <linux/slab.h>
53 +#include <linux/mtd/partitions.h>
55 +#define BLPARAMS_FW_OFFSET "NAND_RFS_OFS"
57 +static long long bcm4908_partitions_fw_offset(void)
59 + struct device_node *root;
60 + struct property *prop;
63 + root = of_find_node_by_path("/");
67 + of_property_for_each_string(root, "brcm_blparms", prop, s) {
68 + size_t len = strlen(BLPARAMS_FW_OFFSET);
69 + unsigned long offset;
72 + if (strncmp(s, BLPARAMS_FW_OFFSET, len) || s[len] != '=')
75 + err = kstrtoul(s + len + 1, 0, &offset);
77 + pr_err("failed to parse %s\n", s + len + 1);
81 + return offset << 10;
87 +int bcm4908_partitions_post_parse(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts)
89 + long long fw_offset;
92 + fw_offset = bcm4908_partitions_fw_offset();
94 + for (i = 0; i < nr_parts; i++) {
95 + if (of_device_is_compatible(parts[i].of_node, "brcm,bcm4908-firmware")) {
96 + if (fw_offset < 0 || parts[i].offset == fw_offset)
97 + parts[i].name = "firmware";
99 + parts[i].name = "backup";
106 +++ b/drivers/mtd/parsers/bcm4908-partitions.h
108 +/* SPDX-License-Identifier: GPL-2.0 */
109 +#ifndef __BCM4908_PARTITIONS_H
110 +#define __BCM4908_PARTITIONS_H
112 +int bcm4908_partitions_post_parse(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts);
115 --- a/drivers/mtd/parsers/ofpart.c
116 +++ b/drivers/mtd/parsers/ofpart.c
118 #include <linux/slab.h>
119 #include <linux/mtd/partitions.h>
121 +#include "bcm4908-partitions.h"
123 +struct fixed_partitions_quirks {
124 + int (*post_parse)(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts);
127 +struct fixed_partitions_quirks bcm4908_partitions_quirks = {
128 + .post_parse = bcm4908_partitions_post_parse,
131 +static const struct of_device_id parse_ofpart_match_table[];
133 static bool node_has_compatible(struct device_node *pp)
135 return of_get_property(pp, "compatible", NULL);
136 @@ -25,6 +37,8 @@ static int parse_fixed_partitions(struct
137 const struct mtd_partition **pparts,
138 struct mtd_part_parser_data *data)
140 + const struct fixed_partitions_quirks *quirks;
141 + const struct of_device_id *of_id;
142 struct mtd_partition *parts;
143 struct device_node *mtd_node;
144 struct device_node *ofpart_node;
145 @@ -33,7 +47,6 @@ static int parse_fixed_partitions(struct
146 int nr_parts, i, ret = 0;
147 bool dedicated = true;
150 /* Pull of_node from the master device node */
151 mtd_node = mtd_get_of_node(master);
153 @@ -50,11 +63,16 @@ static int parse_fixed_partitions(struct
154 master->name, mtd_node);
155 ofpart_node = mtd_node;
157 - } else if (!of_device_is_compatible(ofpart_node, "fixed-partitions")) {
160 + of_id = of_match_node(parse_ofpart_match_table, ofpart_node);
161 + if (dedicated && !of_id) {
162 /* The 'partitions' subnode might be used by another parser */
166 + quirks = of_id ? of_id->data : NULL;
168 /* First count the subnodes */
170 for_each_child_of_node(ofpart_node, pp) {
171 @@ -123,6 +141,9 @@ static int parse_fixed_partitions(struct
175 + if (quirks && quirks->post_parse)
176 + quirks->post_parse(master, parts, nr_parts);
181 @@ -137,7 +158,10 @@ ofpart_none:
184 static const struct of_device_id parse_ofpart_match_table[] = {
186 { .compatible = "fixed-partitions" },
188 + { .compatible = "brcm,bcm4908-partitions", .data = &bcm4908_partitions_quirks, },
191 MODULE_DEVICE_TABLE(of, parse_ofpart_match_table);