linux/drivers/mtd/ofpart.c
<<
>>
Prefs
   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                i++;
  77        }
  78
  79        if (!i) {
  80                of_node_put(pp);
  81                pr_err("No valid partition found on %s\n", node->full_name);
  82                kfree(*pparts);
  83                *pparts = NULL;
  84                return -EINVAL;
  85        }
  86
  87        return nr_parts;
  88}
  89
  90static struct mtd_part_parser ofpart_parser = {
  91        .owner = THIS_MODULE,
  92        .parse_fn = parse_ofpart_partitions,
  93        .name = "ofpart",
  94};
  95
  96static int parse_ofoldpart_partitions(struct mtd_info *master,
  97                                      struct mtd_partition **pparts,
  98                                      struct mtd_part_parser_data *data)
  99{
 100        struct device_node *dp;
 101        int i, plen, nr_parts;
 102        const struct {
 103                __be32 offset, len;
 104        } *part;
 105        const char *names;
 106
 107        if (!data)
 108                return 0;
 109
 110        dp = data->of_node;
 111        if (!dp)
 112                return 0;
 113
 114        part = of_get_property(dp, "partitions", &plen);
 115        if (!part)
 116                return 0; /* No partitions found */
 117
 118        pr_warning("Device tree uses obsolete partition map binding: %s\n",
 119                        dp->full_name);
 120
 121        nr_parts = plen / sizeof(part[0]);
 122
 123        *pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL);
 124        if (!*pparts)
 125                return -ENOMEM;
 126
 127        names = of_get_property(dp, "partition-names", &plen);
 128
 129        for (i = 0; i < nr_parts; i++) {
 130                (*pparts)[i].offset = be32_to_cpu(part->offset);
 131                (*pparts)[i].size   = be32_to_cpu(part->len) & ~1;
 132                /* bit 0 set signifies read only partition */
 133                if (be32_to_cpu(part->len) & 1)
 134                        (*pparts)[i].mask_flags = MTD_WRITEABLE;
 135
 136                if (names && (plen > 0)) {
 137                        int len = strlen(names) + 1;
 138
 139                        (*pparts)[i].name = (char *)names;
 140                        plen -= len;
 141                        names += len;
 142                } else {
 143                        (*pparts)[i].name = "unnamed";
 144                }
 145
 146                part++;
 147        }
 148
 149        return nr_parts;
 150}
 151
 152static struct mtd_part_parser ofoldpart_parser = {
 153        .owner = THIS_MODULE,
 154        .parse_fn = parse_ofoldpart_partitions,
 155        .name = "ofoldpart",
 156};
 157
 158static int __init ofpart_parser_init(void)
 159{
 160        int rc;
 161        rc = register_mtd_parser(&ofpart_parser);
 162        if (rc)
 163                goto out;
 164
 165        rc = register_mtd_parser(&ofoldpart_parser);
 166        if (!rc)
 167                return 0;
 168
 169        deregister_mtd_parser(&ofoldpart_parser);
 170out:
 171        return rc;
 172}
 173
 174module_init(ofpart_parser_init);
 175
 176MODULE_LICENSE("GPL");
 177MODULE_DESCRIPTION("Parser for MTD partitioning information in device tree");
 178MODULE_AUTHOR("Vitaly Wool, David Gibson");
 179/*
 180 * When MTD core cannot find the requested parser, it tries to load the module
 181 * with the same name. Since we provide the ofoldpart parser, we should have
 182 * the corresponding alias.
 183 */
 184MODULE_ALIAS("ofoldpart");
 185
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.