aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/sunxi/patches-4.1/112-mtd-add-dt-nand-partition-parser.patch
blob: 135f50a5cbb954eb9d0ed6575215e226b5839d26 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
From 0460e9868fd82a3675db02f6ceb6edfd8501c194 Mon Sep 17 00:00:00 2001
From: Boris BREZILLON <boris.brezillon@free-electrons.com>
Date: Mon, 28 Jul 2014 14:31:42 +0200
Subject: [PATCH] mtd: nand: Add DT NAND partition parser

Add a of_nandpart_parse function to help parsing NAND partitions from DT.
This function should be called from NAND controller drivers just after the
nand_scan_tail in place of mtd_device_parse_register.
The caller can specify a parser function to retrieve HW specific
informations from the DT.

Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/mtd/nand/ofnandpart.c | 104 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/nand.h      |  17 +++++++
 2 files changed, 121 insertions(+)
 create mode 100644 drivers/mtd/nand/ofnandpart.c

diff --git a/drivers/mtd/nand/ofnandpart.c b/drivers/mtd/nand/ofnandpart.c
new file mode 100644
index 0000000..293daee
--- /dev/null
+++ b/drivers/mtd/nand/ofnandpart.c
@@ -0,0 +1,104 @@
+/*
+ * NAND Flash partitions described by the OF (or flattened) device tree
+ *
+ * Copyright © 2014 Boris BREZILLON <b.brezillon.dev@gmail.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/mtd/mtd.h>
+#include <linux/slab.h>
+#include <linux/mtd/nand.h>
+
+static inline bool node_has_compatible(struct device_node *pp)
+{
+	return of_get_property(pp, "compatible", NULL);
+}
+
+int ofnandpart_parse(struct mtd_info *master,
+		     const struct ofnandpart_data *data)
+{
+	struct device_node *node;
+	const char *partname;
+	struct device_node *pp;
+	int i;
+
+	if (!data)
+		return 0;
+
+	node = data->node;
+	if (!node)
+		return 0;
+
+	i = 0;
+	for_each_child_of_node(node,  pp) {
+		const __be32 *reg;
+		int len;
+		int a_cells, s_cells;
+		uint64_t offset, size;
+		uint32_t mask_flags = 0;
+		struct nand_part *part;
+
+		if (node_has_compatible(pp))
+			continue;
+
+		reg = of_get_property(pp, "reg", &len);
+		if (!reg)
+			continue;
+
+		a_cells = of_n_addr_cells(pp);
+		s_cells = of_n_size_cells(pp);
+		offset = of_read_number(reg, a_cells);
+		size = of_read_number(reg + a_cells, s_cells);
+
+		partname = of_get_property(pp, "label", &len);
+		if (!partname)
+			partname = of_get_property(pp, "name", &len);
+
+		if (of_get_property(pp, "read-only", &len))
+			mask_flags |= MTD_WRITEABLE;
+
+		if (of_get_property(pp, "lock", &len))
+			mask_flags |= MTD_POWERUP_LOCK;
+
+		if (data->parse)
+			part = data->parse(data->priv, master, pp);
+		else
+			part = nandpart_alloc();
+
+		if (IS_ERR(part))
+			continue;
+
+		part->offset = offset;
+		part->master = master;
+		part->mtd.name = partname;
+		part->mtd.size = size;
+		part->mtd.flags = mask_flags;
+
+		if (nand_add_partition(master, part)) {
+			if (part->release)
+				part->release(part);
+			continue;
+		}
+
+		i++;
+	}
+
+	if (!i) {
+		of_node_put(pp);
+		pr_err("No valid partition found on %s\n", node->full_name);
+	}
+
+	return i;
+}
+EXPORT_SYMBOL(ofnandpart_parse);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Parser for NAND flash partitioning information in device tree");
+MODULE_AUTHOR("Boris BREZILLON");
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 510e09b..5616f51 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -1013,6 +1013,23 @@ static inline int jedec_feature(struct nand_chip *chip)
 		: 0;
 }
 
+/**
+ * struct ofnandpart_data - struct used to retrieve NAND partitions from a DT
+ *			    node
+ * @parse:		driver specific parser function
+ * @priv:		driver private data
+ * @node:		OF node containing NAND partitions
+ */
+struct ofnandpart_data {
+	struct nand_part *(*parse)(void *priv, struct mtd_info *master,
+				   struct device_node *pp);
+	void *priv;
+	struct device_node *node;
+};
+
+int ofnandpart_parse(struct mtd_info *master,
+		     const struct ofnandpart_data *data);
+
 /*
  * struct nand_sdr_timings - SDR NAND chip timings
  *