mirror of
https://github.com/openwrt/openwrt.git
synced 2025-01-01 19:46:51 +00:00
ac7d45b5e7
This adds quirks support to the "ofpart" parser. It's required to support fixed partitions that require some extra logic. Right now only BCM4908 binding is supported (BCM4908 requires detecting currently used "firmware" partition). Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
195 lines
5.7 KiB
Diff
195 lines
5.7 KiB
Diff
From 09cf6ee6d21cd9ef2eb857ccb24305cf51166792 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
|
Date: Thu, 11 Feb 2021 23:04:27 +0100
|
|
Subject: [PATCH] mtd: parsers: ofpart: support BCM4908 fixed partitions
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
BCM4908 partitioning is based on fixed layout but allows specifying
|
|
multiple firmware partitions. It requires detecting which firmware
|
|
partition was used for booting current kernel.
|
|
|
|
To support such cases without duplicating a lot of code (without copying
|
|
most of the ofpart.c code) support for post-parsing callback was added.
|
|
|
|
BCM4908 callback simply reads offset of currently used firmware
|
|
partition from the DT. Bootloader specifies it using the "brcm_blparms"
|
|
property.
|
|
|
|
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
|
Signed-off-by: Richard Weinberger <richard@nod.at>
|
|
---
|
|
drivers/mtd/parsers/Makefile | 1 +
|
|
drivers/mtd/parsers/bcm4908-partitions.c | 64 ++++++++++++++++++++++++
|
|
drivers/mtd/parsers/bcm4908-partitions.h | 7 +++
|
|
drivers/mtd/parsers/ofpart.c | 28 ++++++++++-
|
|
4 files changed, 98 insertions(+), 2 deletions(-)
|
|
create mode 100644 drivers/mtd/parsers/bcm4908-partitions.c
|
|
create mode 100644 drivers/mtd/parsers/bcm4908-partitions.h
|
|
|
|
--- a/drivers/mtd/parsers/Makefile
|
|
+++ b/drivers/mtd/parsers/Makefile
|
|
@@ -4,6 +4,7 @@ obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm4
|
|
obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o
|
|
obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
|
|
obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o
|
|
+obj-$(CONFIG_MTD_OF_PARTS) += bcm4908-partitions.o
|
|
obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o
|
|
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
|
|
obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o
|
|
--- /dev/null
|
|
+++ b/drivers/mtd/parsers/bcm4908-partitions.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 "bcm4908-partitions.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;
|
|
+}
|
|
--- /dev/null
|
|
+++ b/drivers/mtd/parsers/bcm4908-partitions.h
|
|
@@ -0,0 +1,7 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0 */
|
|
+#ifndef __BCM4908_PARTITIONS_H
|
|
+#define __BCM4908_PARTITIONS_H
|
|
+
|
|
+int bcm4908_partitions_post_parse(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts);
|
|
+
|
|
+#endif
|
|
--- a/drivers/mtd/parsers/ofpart.c
|
|
+++ b/drivers/mtd/parsers/ofpart.c
|
|
@@ -16,6 +16,18 @@
|
|
#include <linux/slab.h>
|
|
#include <linux/mtd/partitions.h>
|
|
|
|
+#include "bcm4908-partitions.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
|
|
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
|
|
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
|
|
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) {
|
|
@@ -123,6 +141,9 @@ static int parse_fixed_partitions(struct
|
|
if (!nr_parts)
|
|
goto ofpart_none;
|
|
|
|
+ if (quirks && quirks->post_parse)
|
|
+ quirks->post_parse(master, parts, nr_parts);
|
|
+
|
|
*pparts = parts;
|
|
return nr_parts;
|
|
|
|
@@ -137,7 +158,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);
|