Blame view

drivers/mtd/ofpart.c 4.38 KB
9a310d211   Scott Wood   [MTD] Factor out ...
1
2
3
  /*
   * Flash partitions described by the OF (or flattened) device tree
   *
a1452a377   David Woodhouse   mtd: Update copyr...
4
   * Copyright © 2006 MontaVista Software Inc.
9a310d211   Scott Wood   [MTD] Factor out ...
5
6
7
   * Author: Vitaly Wool <vwool@ru.mvista.com>
   *
   * Revised to handle newer style flash binding by:
a1452a377   David Woodhouse   mtd: Update copyr...
8
   *   Copyright © 2007 David Gibson, IBM Corporation.
9a310d211   Scott Wood   [MTD] Factor out ...
9
10
11
12
13
14
15
16
17
18
19
   *
   * 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>
5a0e3ad6a   Tejun Heo   include cleanup: ...
20
  #include <linux/slab.h>
9a310d211   Scott Wood   [MTD] Factor out ...
21
  #include <linux/mtd/partitions.h>
e79265ba6   Josh Wu   mtd: ofpart: add ...
22
23
24
25
  static bool node_has_compatible(struct device_node *pp)
  {
  	return of_get_property(pp, "compatible", NULL);
  }
d26c87d64   Dmitry Eremin-Solenikov   mtd: prepare to c...
26
27
28
29
  static int parse_ofpart_partitions(struct mtd_info *master,
  				   struct mtd_partition **pparts,
  				   struct mtd_part_parser_data *data)
  {
628376fb5   Dmitry Eremin-Solenikov   mtd: drop of_mtd_...
30
  	struct device_node *node;
9a310d211   Scott Wood   [MTD] Factor out ...
31
32
33
  	const char *partname;
  	struct device_node *pp;
  	int nr_parts, i;
628376fb5   Dmitry Eremin-Solenikov   mtd: drop of_mtd_...
34
35
36
37
38
39
40
  
  	if (!data)
  		return 0;
  
  	node = data->of_node;
  	if (!node)
  		return 0;
9a310d211   Scott Wood   [MTD] Factor out ...
41
  	/* First count the subnodes */
9a310d211   Scott Wood   [MTD] Factor out ...
42
  	nr_parts = 0;
60ea89e22   Wei Yongjun   mtd: ofpart: use ...
43
  	for_each_child_of_node(node,  pp) {
e79265ba6   Josh Wu   mtd: ofpart: add ...
44
45
  		if (node_has_compatible(pp))
  			continue;
9a310d211   Scott Wood   [MTD] Factor out ...
46
  		nr_parts++;
e79265ba6   Josh Wu   mtd: ofpart: add ...
47
  	}
9a310d211   Scott Wood   [MTD] Factor out ...
48
49
50
51
52
53
54
  
  	if (nr_parts == 0)
  		return 0;
  
  	*pparts = kzalloc(nr_parts * sizeof(**pparts), GFP_KERNEL);
  	if (!*pparts)
  		return -ENOMEM;
9a310d211   Scott Wood   [MTD] Factor out ...
55
  	i = 0;
60ea89e22   Wei Yongjun   mtd: ofpart: use ...
56
  	for_each_child_of_node(node,  pp) {
766f271a6   Ian Munsie   mtd: Fix endianne...
57
  		const __be32 *reg;
9a310d211   Scott Wood   [MTD] Factor out ...
58
  		int len;
05ff8c258   Joe Schaack   mtd: ofpart: supp...
59
  		int a_cells, s_cells;
9a310d211   Scott Wood   [MTD] Factor out ...
60

e79265ba6   Josh Wu   mtd: ofpart: add ...
61
62
  		if (node_has_compatible(pp))
  			continue;
ebd5a74db   Benjamin Krill   mtd: ofpart: Chec...
63
64
  		reg = of_get_property(pp, "reg", &len);
  		if (!reg) {
4b08e149c   Benjamin Krill   [MTD] ofpart: Che...
65
66
67
  			nr_parts--;
  			continue;
  		}
05ff8c258   Joe Schaack   mtd: ofpart: supp...
68
69
70
71
  		a_cells = of_n_addr_cells(pp);
  		s_cells = of_n_size_cells(pp);
  		(*pparts)[i].offset = of_read_number(reg, a_cells);
  		(*pparts)[i].size = of_read_number(reg + a_cells, s_cells);
9a310d211   Scott Wood   [MTD] Factor out ...
72
73
74
75
  
  		partname = of_get_property(pp, "label", &len);
  		if (!partname)
  			partname = of_get_property(pp, "name", &len);
26a6d240e   Geert Uytterhoeven   mtd: make mtd_par...
76
  		(*pparts)[i].name = partname;
9a310d211   Scott Wood   [MTD] Factor out ...
77
78
  
  		if (of_get_property(pp, "read-only", &len))
ab0b00bc6   Josh Radel   mtd: ofpart: Repl...
79
80
81
82
  			(*pparts)[i].mask_flags |= MTD_WRITEABLE;
  
  		if (of_get_property(pp, "lock", &len))
  			(*pparts)[i].mask_flags |= MTD_POWERUP_LOCK;
9a310d211   Scott Wood   [MTD] Factor out ...
83
84
85
  
  		i++;
  	}
ebd5a74db   Benjamin Krill   mtd: ofpart: Chec...
86
87
  	if (!i) {
  		of_node_put(pp);
d26c87d64   Dmitry Eremin-Solenikov   mtd: prepare to c...
88
89
  		pr_err("No valid partition found on %s
  ", node->full_name);
ebd5a74db   Benjamin Krill   mtd: ofpart: Chec...
90
91
92
93
  		kfree(*pparts);
  		*pparts = NULL;
  		return -EINVAL;
  	}
9a310d211   Scott Wood   [MTD] Factor out ...
94
95
  	return nr_parts;
  }
950bcb258   Adrian Bunk   [MTD] mtd/ofpart....
96

d26c87d64   Dmitry Eremin-Solenikov   mtd: prepare to c...
97
98
99
100
101
  static struct mtd_part_parser ofpart_parser = {
  	.owner = THIS_MODULE,
  	.parse_fn = parse_ofpart_partitions,
  	.name = "ofpart",
  };
fbcf62a32   Dmitry Eremin-Solenikov   mtd: physmap_of: ...
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
  static int parse_ofoldpart_partitions(struct mtd_info *master,
  				      struct mtd_partition **pparts,
  				      struct mtd_part_parser_data *data)
  {
  	struct device_node *dp;
  	int i, plen, nr_parts;
  	const struct {
  		__be32 offset, len;
  	} *part;
  	const char *names;
  
  	if (!data)
  		return 0;
  
  	dp = data->of_node;
  	if (!dp)
  		return 0;
  
  	part = of_get_property(dp, "partitions", &plen);
  	if (!part)
  		return 0; /* No partitions found */
  
  	pr_warning("Device tree uses obsolete partition map binding: %s
  ",
  			dp->full_name);
  
  	nr_parts = plen / sizeof(part[0]);
  
  	*pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL);
ecbcbc7b7   Sachin Kamat   mtd: ofpart: Fix ...
131
  	if (!*pparts)
fbcf62a32   Dmitry Eremin-Solenikov   mtd: physmap_of: ...
132
133
134
135
136
137
138
139
140
141
142
143
144
  		return -ENOMEM;
  
  	names = of_get_property(dp, "partition-names", &plen);
  
  	for (i = 0; i < nr_parts; i++) {
  		(*pparts)[i].offset = be32_to_cpu(part->offset);
  		(*pparts)[i].size   = be32_to_cpu(part->len) & ~1;
  		/* bit 0 set signifies read only partition */
  		if (be32_to_cpu(part->len) & 1)
  			(*pparts)[i].mask_flags = MTD_WRITEABLE;
  
  		if (names && (plen > 0)) {
  			int len = strlen(names) + 1;
26a6d240e   Geert Uytterhoeven   mtd: make mtd_par...
145
  			(*pparts)[i].name = names;
fbcf62a32   Dmitry Eremin-Solenikov   mtd: physmap_of: ...
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
  			plen -= len;
  			names += len;
  		} else {
  			(*pparts)[i].name = "unnamed";
  		}
  
  		part++;
  	}
  
  	return nr_parts;
  }
  
  static struct mtd_part_parser ofoldpart_parser = {
  	.owner = THIS_MODULE,
  	.parse_fn = parse_ofoldpart_partitions,
  	.name = "ofoldpart",
  };
d26c87d64   Dmitry Eremin-Solenikov   mtd: prepare to c...
163
164
  static int __init ofpart_parser_init(void)
  {
6e14a61d4   Axel Lin   mtd: make registe...
165
166
167
  	register_mtd_parser(&ofpart_parser);
  	register_mtd_parser(&ofoldpart_parser);
  	return 0;
d26c87d64   Dmitry Eremin-Solenikov   mtd: prepare to c...
168
  }
422f3890a   Lubomir Rintel   mtd: Allow remova...
169
170
171
172
173
  static void __exit ofpart_parser_exit(void)
  {
  	deregister_mtd_parser(&ofpart_parser);
  	deregister_mtd_parser(&ofoldpart_parser);
  }
d26c87d64   Dmitry Eremin-Solenikov   mtd: prepare to c...
174
  module_init(ofpart_parser_init);
422f3890a   Lubomir Rintel   mtd: Allow remova...
175
  module_exit(ofpart_parser_exit);
d26c87d64   Dmitry Eremin-Solenikov   mtd: prepare to c...
176

950bcb258   Adrian Bunk   [MTD] mtd/ofpart....
177
  MODULE_LICENSE("GPL");
d6137bade   Dmitry Eremin-Solenikov   mtd: make ofpart ...
178
179
  MODULE_DESCRIPTION("Parser for MTD partitioning information in device tree");
  MODULE_AUTHOR("Vitaly Wool, David Gibson");
9786f6e68   Dmitry Eremin-Solenikov   mtd: ofpart: add ...
180
181
182
183
184
185
  /*
   * When MTD core cannot find the requested parser, it tries to load the module
   * with the same name. Since we provide the ofoldpart parser, we should have
   * the corresponding alias.
   */
  MODULE_ALIAS("ofoldpart");