689807d48e6e4c97c00e2c1c585daf8d31d0d92b
[openwrt/staging/rmilecki.git] / target / linux / bcm4908 / patches-5.4 / 140-0003-mtd-parsers-ofpart-support-BCM4908-fixed-partitions.patch
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
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
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.
12
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.
15
16 BCM4908 callback simply reads offset of currently used firmware
17 partition from the DT. Bootloader specifies it using the "brcm_blparms"
18 property.
19
20 Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
21 ---
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
29
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
40 --- /dev/null
41 +++ b/drivers/mtd/parsers/bcm4908-partitions.c
42 @@ -0,0 +1,62 @@
43 +// SPDX-License-Identifier: GPL-2.0
44 +/*
45 + * Copyright (C) 2021 Rafał Miłecki <rafal@milecki.pl>
46 + */
47 +
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>
54 +
55 +#define BLPARAMS_FW_OFFSET "NAND_RFS_OFS"
56 +
57 +static long long bcm4908_partitions_fw_offset(void)
58 +{
59 + struct device_node *root;
60 + struct property *prop;
61 + const char *s;
62 +
63 + root = of_find_node_by_path("/");
64 + if (!root)
65 + return -ENOENT;
66 +
67 + of_property_for_each_string(root, "brcm_blparms", prop, s) {
68 + size_t len = strlen(BLPARAMS_FW_OFFSET);
69 + unsigned long offset;
70 + int err;
71 +
72 + if (strncmp(s, BLPARAMS_FW_OFFSET, len) || s[len] != '=')
73 + continue;
74 +
75 + err = kstrtoul(s + len + 1, 0, &offset);
76 + if (err) {
77 + pr_err("failed to parse %s\n", s + len + 1);
78 + return err;
79 + }
80 +
81 + return offset << 10;
82 + }
83 +
84 + return -ENOENT;
85 +}
86 +
87 +int bcm4908_partitions_post_parse(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts)
88 +{
89 + long long fw_offset;
90 + int i;
91 +
92 + fw_offset = bcm4908_partitions_fw_offset();
93 +
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";
98 + else
99 + parts[i].name = "backup";
100 + }
101 + }
102 +
103 + return 0;
104 +}
105 --- /dev/null
106 +++ b/drivers/mtd/parsers/bcm4908-partitions.h
107 @@ -0,0 +1,7 @@
108 +/* SPDX-License-Identifier: GPL-2.0 */
109 +#ifndef __BCM4908_PARTITIONS_H
110 +#define __BCM4908_PARTITIONS_H
111 +
112 +int bcm4908_partitions_post_parse(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts);
113 +
114 +#endif
115 --- a/drivers/mtd/parsers/ofpart.c
116 +++ b/drivers/mtd/parsers/ofpart.c
117 @@ -16,6 +16,18 @@
118 #include <linux/slab.h>
119 #include <linux/mtd/partitions.h>
120
121 +#include "bcm4908-partitions.h"
122 +
123 +struct fixed_partitions_quirks {
124 + int (*post_parse)(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts);
125 +};
126 +
127 +struct fixed_partitions_quirks bcm4908_partitions_quirks = {
128 + .post_parse = bcm4908_partitions_post_parse,
129 +};
130 +
131 +static const struct of_device_id parse_ofpart_match_table[];
132 +
133 static bool node_has_compatible(struct device_node *pp)
134 {
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)
139 {
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;
148
149 -
150 /* Pull of_node from the master device node */
151 mtd_node = mtd_get_of_node(master);
152 if (!mtd_node)
153 @@ -50,11 +63,16 @@ static int parse_fixed_partitions(struct
154 master->name, mtd_node);
155 ofpart_node = mtd_node;
156 dedicated = false;
157 - } else if (!of_device_is_compatible(ofpart_node, "fixed-partitions")) {
158 + }
159 +
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 */
163 return 0;
164 }
165
166 + quirks = of_id ? of_id->data : NULL;
167 +
168 /* First count the subnodes */
169 nr_parts = 0;
170 for_each_child_of_node(ofpart_node, pp) {
171 @@ -123,6 +141,9 @@ static int parse_fixed_partitions(struct
172 if (!nr_parts)
173 goto ofpart_none;
174
175 + if (quirks && quirks->post_parse)
176 + quirks->post_parse(master, parts, nr_parts);
177 +
178 *pparts = parts;
179 return nr_parts;
180
181 @@ -137,7 +158,10 @@ ofpart_none:
182 }
183
184 static const struct of_device_id parse_ofpart_match_table[] = {
185 + /* Generic */
186 { .compatible = "fixed-partitions" },
187 + /* Customized */
188 + { .compatible = "brcm,bcm4908-partitions", .data = &bcm4908_partitions_quirks, },
189 {},
190 };
191 MODULE_DEVICE_TABLE(of, parse_ofpart_match_table);