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                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");
 195
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.