Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.9-rc2 194 lines 4.3 kB view raw
1/* 2 * Flash partitions described by the OF (or flattened) device tree 3 * 4 * Copyright © 2006 MontaVista Software Inc. 5 * Author: Vitaly Wool <vwool@ru.mvista.com> 6 * 7 * Revised to handle newer style flash binding by: 8 * Copyright © 2007 David Gibson, IBM Corporation. 9 * 10 * This program is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License as published by the 12 * Free Software Foundation; either version 2 of the License, or (at your 13 * option) any later version. 14 */ 15 16#include <linux/module.h> 17#include <linux/init.h> 18#include <linux/of.h> 19#include <linux/mtd/mtd.h> 20#include <linux/slab.h> 21#include <linux/mtd/partitions.h> 22 23static int parse_ofpart_partitions(struct mtd_info *master, 24 struct mtd_partition **pparts, 25 struct mtd_part_parser_data *data) 26{ 27 struct device_node *node; 28 const char *partname; 29 struct device_node *pp; 30 int nr_parts, i; 31 32 33 if (!data) 34 return 0; 35 36 node = data->of_node; 37 if (!node) 38 return 0; 39 40 /* First count the subnodes */ 41 pp = NULL; 42 nr_parts = 0; 43 while ((pp = of_get_next_child(node, pp))) 44 nr_parts++; 45 46 if (nr_parts == 0) 47 return 0; 48 49 *pparts = kzalloc(nr_parts * sizeof(**pparts), GFP_KERNEL); 50 if (!*pparts) 51 return -ENOMEM; 52 53 pp = NULL; 54 i = 0; 55 while ((pp = of_get_next_child(node, pp))) { 56 const __be32 *reg; 57 int len; 58 59 reg = of_get_property(pp, "reg", &len); 60 if (!reg) { 61 nr_parts--; 62 continue; 63 } 64 65 (*pparts)[i].offset = be32_to_cpu(reg[0]); 66 (*pparts)[i].size = be32_to_cpu(reg[1]); 67 68 partname = of_get_property(pp, "label", &len); 69 if (!partname) 70 partname = of_get_property(pp, "name", &len); 71 (*pparts)[i].name = (char *)partname; 72 73 if (of_get_property(pp, "read-only", &len)) 74 (*pparts)[i].mask_flags |= MTD_WRITEABLE; 75 76 if (of_get_property(pp, "lock", &len)) 77 (*pparts)[i].mask_flags |= MTD_POWERUP_LOCK; 78 79 i++; 80 } 81 82 if (!i) { 83 of_node_put(pp); 84 pr_err("No valid partition found on %s\n", node->full_name); 85 kfree(*pparts); 86 *pparts = NULL; 87 return -EINVAL; 88 } 89 90 return nr_parts; 91} 92 93static struct mtd_part_parser ofpart_parser = { 94 .owner = THIS_MODULE, 95 .parse_fn = parse_ofpart_partitions, 96 .name = "ofpart", 97}; 98 99static int parse_ofoldpart_partitions(struct mtd_info *master, 100 struct mtd_partition **pparts, 101 struct mtd_part_parser_data *data) 102{ 103 struct device_node *dp; 104 int i, plen, nr_parts; 105 const struct { 106 __be32 offset, len; 107 } *part; 108 const char *names; 109 110 if (!data) 111 return 0; 112 113 dp = data->of_node; 114 if (!dp) 115 return 0; 116 117 part = of_get_property(dp, "partitions", &plen); 118 if (!part) 119 return 0; /* No partitions found */ 120 121 pr_warning("Device tree uses obsolete partition map binding: %s\n", 122 dp->full_name); 123 124 nr_parts = plen / sizeof(part[0]); 125 126 *pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL); 127 if (!*pparts) 128 return -ENOMEM; 129 130 names = of_get_property(dp, "partition-names", &plen); 131 132 for (i = 0; i < nr_parts; i++) { 133 (*pparts)[i].offset = be32_to_cpu(part->offset); 134 (*pparts)[i].size = be32_to_cpu(part->len) & ~1; 135 /* bit 0 set signifies read only partition */ 136 if (be32_to_cpu(part->len) & 1) 137 (*pparts)[i].mask_flags = MTD_WRITEABLE; 138 139 if (names && (plen > 0)) { 140 int len = strlen(names) + 1; 141 142 (*pparts)[i].name = (char *)names; 143 plen -= len; 144 names += len; 145 } else { 146 (*pparts)[i].name = "unnamed"; 147 } 148 149 part++; 150 } 151 152 return nr_parts; 153} 154 155static struct mtd_part_parser ofoldpart_parser = { 156 .owner = THIS_MODULE, 157 .parse_fn = parse_ofoldpart_partitions, 158 .name = "ofoldpart", 159}; 160 161static int __init ofpart_parser_init(void) 162{ 163 int rc; 164 rc = register_mtd_parser(&ofpart_parser); 165 if (rc) 166 goto out; 167 168 rc = register_mtd_parser(&ofoldpart_parser); 169 if (!rc) 170 return 0; 171 172 deregister_mtd_parser(&ofoldpart_parser); 173out: 174 return rc; 175} 176 177static void __exit ofpart_parser_exit(void) 178{ 179 deregister_mtd_parser(&ofpart_parser); 180 deregister_mtd_parser(&ofoldpart_parser); 181} 182 183module_init(ofpart_parser_init); 184module_exit(ofpart_parser_exit); 185 186MODULE_LICENSE("GPL"); 187MODULE_DESCRIPTION("Parser for MTD partitioning information in device tree"); 188MODULE_AUTHOR("Vitaly Wool, David Gibson"); 189/* 190 * When MTD core cannot find the requested parser, it tries to load the module 191 * with the same name. Since we provide the ofoldpart parser, we should have 192 * the corresponding alias. 193 */ 194MODULE_ALIAS("ofoldpart");