~ubuntu-branches/ubuntu/utopic/linux-ti-omap/utopic

« back to all changes in this revision

Viewing changes to drivers/mtd/maps/physmap.c

  • Committer: Bazaar Package Importer
  • Author(s): Amit Kucheria, Amit Kucheria
  • Date: 2010-03-10 02:28:15 UTC
  • Revision ID: james.westby@ubuntu.com-20100310022815-7sd3gwvn5kenaq33
Tags: 2.6.33-500.1
[ Amit Kucheria ]

* Initial release of a 2.6.33-based OMAP kernel
* UBUNTU: [Upstream] Fix omap 1-wire driver compilation
* UBUNTU: ubuntu: AppArmor -- update to mainline 2010-03-04

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Normal mappings of chips in physical memory
 
3
 *
 
4
 * Copyright (C) 2003 MontaVista Software Inc.
 
5
 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
 
6
 *
 
7
 * 031022 - [jsun] add run-time configure and partition setup
 
8
 */
 
9
 
 
10
#include <linux/module.h>
 
11
#include <linux/types.h>
 
12
#include <linux/kernel.h>
 
13
#include <linux/init.h>
 
14
#include <linux/slab.h>
 
15
#include <linux/device.h>
 
16
#include <linux/platform_device.h>
 
17
#include <linux/mtd/mtd.h>
 
18
#include <linux/mtd/map.h>
 
19
#include <linux/mtd/partitions.h>
 
20
#include <linux/mtd/physmap.h>
 
21
#include <linux/mtd/concat.h>
 
22
#include <linux/io.h>
 
23
 
 
24
#define MAX_RESOURCES           4
 
25
 
 
26
struct physmap_flash_info {
 
27
        struct mtd_info         *mtd[MAX_RESOURCES];
 
28
        struct mtd_info         *cmtd;
 
29
        struct map_info         map[MAX_RESOURCES];
 
30
#ifdef CONFIG_MTD_PARTITIONS
 
31
        int                     nr_parts;
 
32
        struct mtd_partition    *parts;
 
33
#endif
 
34
};
 
35
 
 
36
static int physmap_flash_remove(struct platform_device *dev)
 
37
{
 
38
        struct physmap_flash_info *info;
 
39
        struct physmap_flash_data *physmap_data;
 
40
        int i;
 
41
 
 
42
        info = platform_get_drvdata(dev);
 
43
        if (info == NULL)
 
44
                return 0;
 
45
        platform_set_drvdata(dev, NULL);
 
46
 
 
47
        physmap_data = dev->dev.platform_data;
 
48
 
 
49
        if (info->cmtd) {
 
50
#ifdef CONFIG_MTD_PARTITIONS
 
51
                if (info->nr_parts || physmap_data->nr_parts) {
 
52
                        del_mtd_partitions(info->cmtd);
 
53
 
 
54
                        if (info->nr_parts)
 
55
                                kfree(info->parts);
 
56
                } else {
 
57
                        del_mtd_device(info->cmtd);
 
58
                }
 
59
#else
 
60
                del_mtd_device(info->cmtd);
 
61
#endif
 
62
#ifdef CONFIG_MTD_CONCAT
 
63
                if (info->cmtd != info->mtd[0])
 
64
                        mtd_concat_destroy(info->cmtd);
 
65
#endif
 
66
        }
 
67
 
 
68
        for (i = 0; i < MAX_RESOURCES; i++) {
 
69
                if (info->mtd[i] != NULL)
 
70
                        map_destroy(info->mtd[i]);
 
71
        }
 
72
        return 0;
 
73
}
 
74
 
 
75
static const char *rom_probe_types[] = {
 
76
                                        "cfi_probe",
 
77
                                        "jedec_probe",
 
78
                                        "qinfo_probe",
 
79
                                        "map_rom",
 
80
                                        NULL };
 
81
#ifdef CONFIG_MTD_PARTITIONS
 
82
static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
 
83
#endif
 
84
 
 
85
static int physmap_flash_probe(struct platform_device *dev)
 
86
{
 
87
        struct physmap_flash_data *physmap_data;
 
88
        struct physmap_flash_info *info;
 
89
        const char **probe_type;
 
90
        int err = 0;
 
91
        int i;
 
92
        int devices_found = 0;
 
93
 
 
94
        physmap_data = dev->dev.platform_data;
 
95
        if (physmap_data == NULL)
 
96
                return -ENODEV;
 
97
 
 
98
        info = devm_kzalloc(&dev->dev, sizeof(struct physmap_flash_info),
 
99
                            GFP_KERNEL);
 
100
        if (info == NULL) {
 
101
                err = -ENOMEM;
 
102
                goto err_out;
 
103
        }
 
104
 
 
105
        platform_set_drvdata(dev, info);
 
106
 
 
107
        for (i = 0; i < dev->num_resources; i++) {
 
108
                printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n",
 
109
                       (unsigned long long)(dev->resource[i].end - dev->resource[i].start + 1),
 
110
                       (unsigned long long)dev->resource[i].start);
 
111
 
 
112
                if (!devm_request_mem_region(&dev->dev,
 
113
                        dev->resource[i].start,
 
114
                        dev->resource[i].end - dev->resource[i].start + 1,
 
115
                        dev_name(&dev->dev))) {
 
116
                        dev_err(&dev->dev, "Could not reserve memory region\n");
 
117
                        err = -ENOMEM;
 
118
                        goto err_out;
 
119
                }
 
120
 
 
121
                info->map[i].name = dev_name(&dev->dev);
 
122
                info->map[i].phys = dev->resource[i].start;
 
123
                info->map[i].size = dev->resource[i].end - dev->resource[i].start + 1;
 
124
                info->map[i].bankwidth = physmap_data->width;
 
125
                info->map[i].set_vpp = physmap_data->set_vpp;
 
126
                info->map[i].pfow_base = physmap_data->pfow_base;
 
127
 
 
128
                info->map[i].virt = devm_ioremap(&dev->dev, info->map[i].phys,
 
129
                                                 info->map[i].size);
 
130
                if (info->map[i].virt == NULL) {
 
131
                        dev_err(&dev->dev, "Failed to ioremap flash region\n");
 
132
                        err = -EIO;
 
133
                        goto err_out;
 
134
                }
 
135
 
 
136
                simple_map_init(&info->map[i]);
 
137
 
 
138
                probe_type = rom_probe_types;
 
139
                for (; info->mtd[i] == NULL && *probe_type != NULL; probe_type++)
 
140
                        info->mtd[i] = do_map_probe(*probe_type, &info->map[i]);
 
141
                if (info->mtd[i] == NULL) {
 
142
                        dev_err(&dev->dev, "map_probe failed\n");
 
143
                        err = -ENXIO;
 
144
                        goto err_out;
 
145
                } else {
 
146
                        devices_found++;
 
147
                }
 
148
                info->mtd[i]->owner = THIS_MODULE;
 
149
                info->mtd[i]->dev.parent = &dev->dev;
 
150
        }
 
151
 
 
152
        if (devices_found == 1) {
 
153
                info->cmtd = info->mtd[0];
 
154
        } else if (devices_found > 1) {
 
155
                /*
 
156
                 * We detected multiple devices. Concatenate them together.
 
157
                 */
 
158
#ifdef CONFIG_MTD_CONCAT
 
159
                info->cmtd = mtd_concat_create(info->mtd, devices_found, dev_name(&dev->dev));
 
160
                if (info->cmtd == NULL)
 
161
                        err = -ENXIO;
 
162
#else
 
163
                printk(KERN_ERR "physmap-flash: multiple devices "
 
164
                       "found but MTD concat support disabled.\n");
 
165
                err = -ENXIO;
 
166
#endif
 
167
        }
 
168
        if (err)
 
169
                goto err_out;
 
170
 
 
171
#ifdef CONFIG_MTD_PARTITIONS
 
172
        err = parse_mtd_partitions(info->cmtd, part_probe_types,
 
173
                                &info->parts, 0);
 
174
        if (err > 0) {
 
175
                add_mtd_partitions(info->cmtd, info->parts, err);
 
176
                info->nr_parts = err;
 
177
                return 0;
 
178
        }
 
179
 
 
180
        if (physmap_data->nr_parts) {
 
181
                printk(KERN_NOTICE "Using physmap partition information\n");
 
182
                add_mtd_partitions(info->cmtd, physmap_data->parts,
 
183
                                   physmap_data->nr_parts);
 
184
                return 0;
 
185
        }
 
186
#endif
 
187
 
 
188
        add_mtd_device(info->cmtd);
 
189
        return 0;
 
190
 
 
191
err_out:
 
192
        physmap_flash_remove(dev);
 
193
        return err;
 
194
}
 
195
 
 
196
#ifdef CONFIG_PM
 
197
static void physmap_flash_shutdown(struct platform_device *dev)
 
198
{
 
199
        struct physmap_flash_info *info = platform_get_drvdata(dev);
 
200
        int i;
 
201
 
 
202
        for (i = 0; i < MAX_RESOURCES && info->mtd[i]; i++)
 
203
                if (info->mtd[i]->suspend && info->mtd[i]->resume)
 
204
                        if (info->mtd[i]->suspend(info->mtd[i]) == 0)
 
205
                                info->mtd[i]->resume(info->mtd[i]);
 
206
}
 
207
#else
 
208
#define physmap_flash_shutdown NULL
 
209
#endif
 
210
 
 
211
static struct platform_driver physmap_flash_driver = {
 
212
        .probe          = physmap_flash_probe,
 
213
        .remove         = physmap_flash_remove,
 
214
        .shutdown       = physmap_flash_shutdown,
 
215
        .driver         = {
 
216
                .name   = "physmap-flash",
 
217
                .owner  = THIS_MODULE,
 
218
        },
 
219
};
 
220
 
 
221
 
 
222
#ifdef CONFIG_MTD_PHYSMAP_COMPAT
 
223
static struct physmap_flash_data physmap_flash_data = {
 
224
        .width          = CONFIG_MTD_PHYSMAP_BANKWIDTH,
 
225
};
 
226
 
 
227
static struct resource physmap_flash_resource = {
 
228
        .start          = CONFIG_MTD_PHYSMAP_START,
 
229
        .end            = CONFIG_MTD_PHYSMAP_START + CONFIG_MTD_PHYSMAP_LEN - 1,
 
230
        .flags          = IORESOURCE_MEM,
 
231
};
 
232
 
 
233
static struct platform_device physmap_flash = {
 
234
        .name           = "physmap-flash",
 
235
        .id             = 0,
 
236
        .dev            = {
 
237
                .platform_data  = &physmap_flash_data,
 
238
        },
 
239
        .num_resources  = 1,
 
240
        .resource       = &physmap_flash_resource,
 
241
};
 
242
 
 
243
void physmap_configure(unsigned long addr, unsigned long size,
 
244
                int bankwidth, void (*set_vpp)(struct map_info *, int))
 
245
{
 
246
        physmap_flash_resource.start = addr;
 
247
        physmap_flash_resource.end = addr + size - 1;
 
248
        physmap_flash_data.width = bankwidth;
 
249
        physmap_flash_data.set_vpp = set_vpp;
 
250
}
 
251
 
 
252
#ifdef CONFIG_MTD_PARTITIONS
 
253
void physmap_set_partitions(struct mtd_partition *parts, int num_parts)
 
254
{
 
255
        physmap_flash_data.nr_parts = num_parts;
 
256
        physmap_flash_data.parts = parts;
 
257
}
 
258
#endif
 
259
#endif
 
260
 
 
261
static int __init physmap_init(void)
 
262
{
 
263
        int err;
 
264
 
 
265
        err = platform_driver_register(&physmap_flash_driver);
 
266
#ifdef CONFIG_MTD_PHYSMAP_COMPAT
 
267
        if (err == 0)
 
268
                platform_device_register(&physmap_flash);
 
269
#endif
 
270
 
 
271
        return err;
 
272
}
 
273
 
 
274
static void __exit physmap_exit(void)
 
275
{
 
276
#ifdef CONFIG_MTD_PHYSMAP_COMPAT
 
277
        platform_device_unregister(&physmap_flash);
 
278
#endif
 
279
        platform_driver_unregister(&physmap_flash_driver);
 
280
}
 
281
 
 
282
module_init(physmap_init);
 
283
module_exit(physmap_exit);
 
284
 
 
285
MODULE_LICENSE("GPL");
 
286
MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
 
287
MODULE_DESCRIPTION("Generic configurable MTD map driver");
 
288
 
 
289
/* legacy platform drivers can't hotplug or coldplg */
 
290
#ifndef CONFIG_MTD_PHYSMAP_COMPAT
 
291
/* work with hotplug and coldplug */
 
292
MODULE_ALIAS("platform:physmap-flash");
 
293
#endif