OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [mtd/] [maps/] [physmap_of.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Flash mappings described by the OF (or flattened) device tree
3
 *
4
 * Copyright (C) 2006 MontaVista Software Inc.
5
 * Author: Vitaly Wool <vwool@ru.mvista.com>
6
 *
7
 * Revised to handle newer style flash binding by:
8
 *   Copyright (C) 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/types.h>
18
#include <linux/init.h>
19
#include <linux/device.h>
20
#include <linux/mtd/mtd.h>
21
#include <linux/mtd/map.h>
22
#include <linux/mtd/partitions.h>
23
#include <linux/of.h>
24
#include <linux/of_platform.h>
25
 
26
struct of_flash {
27
        struct mtd_info         *mtd;
28
        struct map_info         map;
29
        struct resource         *res;
30
#ifdef CONFIG_MTD_PARTITIONS
31
        struct mtd_partition    *parts;
32
#endif
33
};
34
 
35
#ifdef CONFIG_MTD_PARTITIONS
36
#define OF_FLASH_PARTS(info)    ((info)->parts)
37
 
38
static int parse_obsolete_partitions(struct of_device *dev,
39
                                     struct of_flash *info,
40
                                     struct device_node *dp)
41
{
42
        int i, plen, nr_parts;
43
        const struct {
44
                u32 offset, len;
45
        } *part;
46
        const char *names;
47
 
48
        part = of_get_property(dp, "partitions", &plen);
49
        if (!part)
50
                return 0; /* No partitions found */
51
 
52
        dev_warn(&dev->dev, "Device tree uses obsolete partition map binding\n");
53
 
54
        nr_parts = plen / sizeof(part[0]);
55
 
56
        info->parts = kzalloc(nr_parts * sizeof(*info->parts), GFP_KERNEL);
57
        if (!info->parts)
58
                return -ENOMEM;
59
 
60
        names = of_get_property(dp, "partition-names", &plen);
61
 
62
        for (i = 0; i < nr_parts; i++) {
63
                info->parts[i].offset = part->offset;
64
                info->parts[i].size   = part->len & ~1;
65
                if (part->len & 1) /* bit 0 set signifies read only partition */
66
                        info->parts[i].mask_flags = MTD_WRITEABLE;
67
 
68
                if (names && (plen > 0)) {
69
                        int len = strlen(names) + 1;
70
 
71
                        info->parts[i].name = (char *)names;
72
                        plen -= len;
73
                        names += len;
74
                } else {
75
                        info->parts[i].name = "unnamed";
76
                }
77
 
78
                part++;
79
        }
80
 
81
        return nr_parts;
82
}
83
 
84
static int __devinit parse_partitions(struct of_flash *info,
85
                                      struct of_device *dev)
86
{
87
        const char *partname;
88
        static const char *part_probe_types[]
89
                = { "cmdlinepart", "RedBoot", NULL };
90
        struct device_node *dp = dev->node, *pp;
91
        int nr_parts, i;
92
 
93
        /* First look for RedBoot table or partitions on the command
94
         * line, these take precedence over device tree information */
95
        nr_parts = parse_mtd_partitions(info->mtd, part_probe_types,
96
                                        &info->parts, 0);
97
        if (nr_parts > 0) {
98
                add_mtd_partitions(info->mtd, info->parts, nr_parts);
99
                return 0;
100
        }
101
 
102
        /* First count the subnodes */
103
        nr_parts = 0;
104
        for (pp = dp->child; pp; pp = pp->sibling)
105
                nr_parts++;
106
 
107
        if (nr_parts == 0)
108
                return parse_obsolete_partitions(dev, info, dp);
109
 
110
        info->parts = kzalloc(nr_parts * sizeof(*info->parts),
111
                              GFP_KERNEL);
112
        if (!info->parts)
113
                return -ENOMEM;
114
 
115
        for (pp = dp->child, i = 0; pp; pp = pp->sibling, i++) {
116
                const u32 *reg;
117
                int len;
118
 
119
                reg = of_get_property(pp, "reg", &len);
120
                if (!reg || (len != 2*sizeof(u32))) {
121
                        dev_err(&dev->dev, "Invalid 'reg' on %s\n",
122
                                dp->full_name);
123
                        kfree(info->parts);
124
                        info->parts = NULL;
125
                        return -EINVAL;
126
                }
127
                info->parts[i].offset = reg[0];
128
                info->parts[i].size = reg[1];
129
 
130
                partname = of_get_property(pp, "label", &len);
131
                if (!partname)
132
                        partname = of_get_property(pp, "name", &len);
133
                info->parts[i].name = (char *)partname;
134
 
135
                if (of_get_property(pp, "read-only", &len))
136
                        info->parts[i].mask_flags = MTD_WRITEABLE;
137
        }
138
 
139
        return nr_parts;
140
}
141
#else /* MTD_PARTITIONS */
142
#define OF_FLASH_PARTS(info)            (0)
143
#define parse_partitions(info, dev)     (0)
144
#endif /* MTD_PARTITIONS */
145
 
146
static int of_flash_remove(struct of_device *dev)
147
{
148
        struct of_flash *info;
149
 
150
        info = dev_get_drvdata(&dev->dev);
151
        if (!info)
152
                return 0;
153
        dev_set_drvdata(&dev->dev, NULL);
154
 
155
        if (info->mtd) {
156
                if (OF_FLASH_PARTS(info)) {
157
                        del_mtd_partitions(info->mtd);
158
                        kfree(OF_FLASH_PARTS(info));
159
                } else {
160
                        del_mtd_device(info->mtd);
161
                }
162
                map_destroy(info->mtd);
163
        }
164
 
165
        if (info->map.virt)
166
                iounmap(info->map.virt);
167
 
168
        if (info->res) {
169
                release_resource(info->res);
170
                kfree(info->res);
171
        }
172
 
173
        return 0;
174
}
175
 
176
/* Helper function to handle probing of the obsolete "direct-mapped"
177
 * compatible binding, which has an extra "probe-type" property
178
 * describing the type of flash probe necessary. */
179
static struct mtd_info * __devinit obsolete_probe(struct of_device *dev,
180
                                                  struct map_info *map)
181
{
182
        struct device_node *dp = dev->node;
183
        const char *of_probe;
184
        struct mtd_info *mtd;
185
        static const char *rom_probe_types[]
186
                = { "cfi_probe", "jedec_probe", "map_rom"};
187
        int i;
188
 
189
        dev_warn(&dev->dev, "Device tree uses obsolete \"direct-mapped\" "
190
                 "flash binding\n");
191
 
192
        of_probe = of_get_property(dp, "probe-type", NULL);
193
        if (!of_probe) {
194
                for (i = 0; i < ARRAY_SIZE(rom_probe_types); i++) {
195
                        mtd = do_map_probe(rom_probe_types[i], map);
196
                        if (mtd)
197
                                return mtd;
198
                }
199
                return NULL;
200
        } else if (strcmp(of_probe, "CFI") == 0) {
201
                return do_map_probe("cfi_probe", map);
202
        } else if (strcmp(of_probe, "JEDEC") == 0) {
203
                return do_map_probe("jedec_probe", map);
204
        } else {
205
                if (strcmp(of_probe, "ROM") != 0)
206
                        dev_warn(&dev->dev, "obsolete_probe: don't know probe "
207
                                 "type '%s', mapping as rom\n", of_probe);
208
                return do_map_probe("mtd_rom", map);
209
        }
210
}
211
 
212
static int __devinit of_flash_probe(struct of_device *dev,
213
                                    const struct of_device_id *match)
214
{
215
        struct device_node *dp = dev->node;
216
        struct resource res;
217
        struct of_flash *info;
218
        const char *probe_type = match->data;
219
        const u32 *width;
220
        int err;
221
 
222
        err = -ENXIO;
223
        if (of_address_to_resource(dp, 0, &res)) {
224
                dev_err(&dev->dev, "Can't get IO address from device tree\n");
225
                goto err_out;
226
        }
227
 
228
        dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n",
229
                (unsigned long long)res.start, (unsigned long long)res.end);
230
 
231
        err = -ENOMEM;
232
        info = kzalloc(sizeof(*info), GFP_KERNEL);
233
        if (!info)
234
                goto err_out;
235
 
236
        dev_set_drvdata(&dev->dev, info);
237
 
238
        err = -EBUSY;
239
        info->res = request_mem_region(res.start, res.end - res.start + 1,
240
                                       dev->dev.bus_id);
241
        if (!info->res)
242
                goto err_out;
243
 
244
        err = -ENXIO;
245
        width = of_get_property(dp, "bank-width", NULL);
246
        if (!width) {
247
                dev_err(&dev->dev, "Can't get bank width from device tree\n");
248
                goto err_out;
249
        }
250
 
251
        info->map.name = dev->dev.bus_id;
252
        info->map.phys = res.start;
253
        info->map.size = res.end - res.start + 1;
254
        info->map.bankwidth = *width;
255
 
256
        err = -ENOMEM;
257
        info->map.virt = ioremap(info->map.phys, info->map.size);
258
        if (!info->map.virt) {
259
                dev_err(&dev->dev, "Failed to ioremap() flash region\n");
260
                goto err_out;
261
        }
262
 
263
        simple_map_init(&info->map);
264
 
265
        if (probe_type)
266
                info->mtd = do_map_probe(probe_type, &info->map);
267
        else
268
                info->mtd = obsolete_probe(dev, &info->map);
269
 
270
        err = -ENXIO;
271
        if (!info->mtd) {
272
                dev_err(&dev->dev, "do_map_probe() failed\n");
273
                goto err_out;
274
        }
275
        info->mtd->owner = THIS_MODULE;
276
 
277
        err = parse_partitions(info, dev);
278
        if (err < 0)
279
                goto err_out;
280
 
281
        if (err > 0)
282
                add_mtd_partitions(info->mtd, OF_FLASH_PARTS(info), err);
283
        else
284
                add_mtd_device(info->mtd);
285
 
286
        return 0;
287
 
288
err_out:
289
        of_flash_remove(dev);
290
        return err;
291
}
292
 
293
static struct of_device_id of_flash_match[] = {
294
        {
295
                .compatible     = "cfi-flash",
296
                .data           = (void *)"cfi_probe",
297
        },
298
        {
299
                /* FIXME: JEDEC chips can't be safely and reliably
300
                 * probed, although the mtd code gets it right in
301
                 * practice most of the time.  We should use the
302
                 * vendor and device ids specified by the binding to
303
                 * bypass the heuristic probe code, but the mtd layer
304
                 * provides, at present, no interface for doing so
305
                 * :(. */
306
                .compatible     = "jedec-flash",
307
                .data           = (void *)"jedec_probe",
308
        },
309
        {
310
                .type           = "rom",
311
                .compatible     = "direct-mapped"
312
        },
313
        { },
314
};
315
MODULE_DEVICE_TABLE(of, of_flash_match);
316
 
317
static struct of_platform_driver of_flash_driver = {
318
        .name           = "of-flash",
319
        .match_table    = of_flash_match,
320
        .probe          = of_flash_probe,
321
        .remove         = of_flash_remove,
322
};
323
 
324
static int __init of_flash_init(void)
325
{
326
        return of_register_platform_driver(&of_flash_driver);
327
}
328
 
329
static void __exit of_flash_exit(void)
330
{
331
        of_unregister_platform_driver(&of_flash_driver);
332
}
333
 
334
module_init(of_flash_init);
335
module_exit(of_flash_exit);
336
 
337
MODULE_LICENSE("GPL");
338
MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
339
MODULE_DESCRIPTION("Device tree based MTD map driver");

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.