~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/mtd/maps/latch-addr-flash.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Interface for NOR flash driver whose high address lines are latched
 
3
 *
 
4
 * Copyright © 2000 Nicolas Pitre <nico@cam.org>
 
5
 * Copyright © 2005-2008 Analog Devices Inc.
 
6
 * Copyright © 2008 MontaVista Software, Inc. <source@mvista.com>
 
7
 *
 
8
 * This file is licensed under the terms of the GNU General Public License
 
9
 * version 2. This program is licensed "as is" without any warranty of any
 
10
 * kind, whether express or implied.
 
11
 */
 
12
 
 
13
#include <linux/init.h>
 
14
#include <linux/kernel.h>
 
15
#include <linux/module.h>
 
16
#include <linux/mtd/mtd.h>
 
17
#include <linux/mtd/map.h>
 
18
#include <linux/mtd/partitions.h>
 
19
#include <linux/platform_device.h>
 
20
#include <linux/mtd/latch-addr-flash.h>
 
21
#include <linux/slab.h>
 
22
 
 
23
#define DRIVER_NAME "latch-addr-flash"
 
24
 
 
25
struct latch_addr_flash_info {
 
26
        struct mtd_info         *mtd;
 
27
        struct map_info         map;
 
28
        struct resource         *res;
 
29
 
 
30
        void                    (*set_window)(unsigned long offset, void *data);
 
31
        void                    *data;
 
32
 
 
33
        /* cache; could be found out of res */
 
34
        unsigned long           win_mask;
 
35
 
 
36
        int                     nr_parts;
 
37
        struct mtd_partition    *parts;
 
38
 
 
39
        spinlock_t              lock;
 
40
};
 
41
 
 
42
static map_word lf_read(struct map_info *map, unsigned long ofs)
 
43
{
 
44
        struct latch_addr_flash_info *info;
 
45
        map_word datum;
 
46
 
 
47
        info = (struct latch_addr_flash_info *)map->map_priv_1;
 
48
 
 
49
        spin_lock(&info->lock);
 
50
 
 
51
        info->set_window(ofs, info->data);
 
52
        datum = inline_map_read(map, info->win_mask & ofs);
 
53
 
 
54
        spin_unlock(&info->lock);
 
55
 
 
56
        return datum;
 
57
}
 
58
 
 
59
static void lf_write(struct map_info *map, map_word datum, unsigned long ofs)
 
60
{
 
61
        struct latch_addr_flash_info *info;
 
62
 
 
63
        info = (struct latch_addr_flash_info *)map->map_priv_1;
 
64
 
 
65
        spin_lock(&info->lock);
 
66
 
 
67
        info->set_window(ofs, info->data);
 
68
        inline_map_write(map, datum, info->win_mask & ofs);
 
69
 
 
70
        spin_unlock(&info->lock);
 
71
}
 
72
 
 
73
static void lf_copy_from(struct map_info *map, void *to,
 
74
                unsigned long from, ssize_t len)
 
75
{
 
76
        struct latch_addr_flash_info *info =
 
77
                (struct latch_addr_flash_info *) map->map_priv_1;
 
78
        unsigned n;
 
79
 
 
80
        while (len > 0) {
 
81
                n = info->win_mask + 1 - (from & info->win_mask);
 
82
                if (n > len)
 
83
                        n = len;
 
84
 
 
85
                spin_lock(&info->lock);
 
86
 
 
87
                info->set_window(from, info->data);
 
88
                memcpy_fromio(to, map->virt + (from & info->win_mask), n);
 
89
 
 
90
                spin_unlock(&info->lock);
 
91
 
 
92
                to += n;
 
93
                from += n;
 
94
                len -= n;
 
95
        }
 
96
}
 
97
 
 
98
static char *rom_probe_types[] = { "cfi_probe", NULL };
 
99
 
 
100
static char *part_probe_types[] = { "cmdlinepart", NULL };
 
101
 
 
102
static int latch_addr_flash_remove(struct platform_device *dev)
 
103
{
 
104
        struct latch_addr_flash_info *info;
 
105
        struct latch_addr_flash_data *latch_addr_data;
 
106
 
 
107
        info = platform_get_drvdata(dev);
 
108
        if (info == NULL)
 
109
                return 0;
 
110
        platform_set_drvdata(dev, NULL);
 
111
 
 
112
        latch_addr_data = dev->dev.platform_data;
 
113
 
 
114
        if (info->mtd != NULL) {
 
115
                if (info->nr_parts)
 
116
                        kfree(info->parts);
 
117
                mtd_device_unregister(info->mtd);
 
118
                map_destroy(info->mtd);
 
119
        }
 
120
 
 
121
        if (info->map.virt != NULL)
 
122
                iounmap(info->map.virt);
 
123
 
 
124
        if (info->res != NULL)
 
125
                release_mem_region(info->res->start, resource_size(info->res));
 
126
 
 
127
        kfree(info);
 
128
 
 
129
        if (latch_addr_data->done)
 
130
                latch_addr_data->done(latch_addr_data->data);
 
131
 
 
132
        return 0;
 
133
}
 
134
 
 
135
static int __devinit latch_addr_flash_probe(struct platform_device *dev)
 
136
{
 
137
        struct latch_addr_flash_data *latch_addr_data;
 
138
        struct latch_addr_flash_info *info;
 
139
        resource_size_t win_base = dev->resource->start;
 
140
        resource_size_t win_size = resource_size(dev->resource);
 
141
        char **probe_type;
 
142
        int chipsel;
 
143
        int err;
 
144
 
 
145
        latch_addr_data = dev->dev.platform_data;
 
146
        if (latch_addr_data == NULL)
 
147
                return -ENODEV;
 
148
 
 
149
        pr_notice("latch-addr platform flash device: %#llx byte "
 
150
                  "window at %#.8llx\n",
 
151
                  (unsigned long long)win_size, (unsigned long long)win_base);
 
152
 
 
153
        chipsel = dev->id;
 
154
 
 
155
        if (latch_addr_data->init) {
 
156
                err = latch_addr_data->init(latch_addr_data->data, chipsel);
 
157
                if (err != 0)
 
158
                        return err;
 
159
        }
 
160
 
 
161
        info = kzalloc(sizeof(struct latch_addr_flash_info), GFP_KERNEL);
 
162
        if (info == NULL) {
 
163
                err = -ENOMEM;
 
164
                goto done;
 
165
        }
 
166
 
 
167
        platform_set_drvdata(dev, info);
 
168
 
 
169
        info->res = request_mem_region(win_base, win_size, DRIVER_NAME);
 
170
        if (info->res == NULL) {
 
171
                dev_err(&dev->dev, "Could not reserve memory region\n");
 
172
                err = -EBUSY;
 
173
                goto free_info;
 
174
        }
 
175
 
 
176
        info->map.name          = DRIVER_NAME;
 
177
        info->map.size          = latch_addr_data->size;
 
178
        info->map.bankwidth     = latch_addr_data->width;
 
179
 
 
180
        info->map.phys          = NO_XIP;
 
181
        info->map.virt          = ioremap(win_base, win_size);
 
182
        if (!info->map.virt) {
 
183
                err = -ENOMEM;
 
184
                goto free_res;
 
185
        }
 
186
 
 
187
        info->map.map_priv_1    = (unsigned long)info;
 
188
 
 
189
        info->map.read          = lf_read;
 
190
        info->map.copy_from     = lf_copy_from;
 
191
        info->map.write         = lf_write;
 
192
        info->set_window        = latch_addr_data->set_window;
 
193
        info->data              = latch_addr_data->data;
 
194
        info->win_mask          = win_size - 1;
 
195
 
 
196
        spin_lock_init(&info->lock);
 
197
 
 
198
        for (probe_type = rom_probe_types; !info->mtd && *probe_type;
 
199
                probe_type++)
 
200
                info->mtd = do_map_probe(*probe_type, &info->map);
 
201
 
 
202
        if (info->mtd == NULL) {
 
203
                dev_err(&dev->dev, "map_probe failed\n");
 
204
                err = -ENODEV;
 
205
                goto iounmap;
 
206
        }
 
207
        info->mtd->owner = THIS_MODULE;
 
208
 
 
209
        err = parse_mtd_partitions(info->mtd, (const char **)part_probe_types,
 
210
                                   &info->parts, 0);
 
211
        if (err > 0) {
 
212
                mtd_device_register(info->mtd, info->parts, err);
 
213
                return 0;
 
214
        }
 
215
        if (latch_addr_data->nr_parts) {
 
216
                pr_notice("Using latch-addr-flash partition information\n");
 
217
                mtd_device_register(info->mtd,
 
218
                                    latch_addr_data->parts,
 
219
                                    latch_addr_data->nr_parts);
 
220
                return 0;
 
221
        }
 
222
 
 
223
        mtd_device_register(info->mtd, NULL, 0);
 
224
        return 0;
 
225
 
 
226
iounmap:
 
227
        iounmap(info->map.virt);
 
228
free_res:
 
229
        release_mem_region(info->res->start, resource_size(info->res));
 
230
free_info:
 
231
        kfree(info);
 
232
done:
 
233
        if (latch_addr_data->done)
 
234
                latch_addr_data->done(latch_addr_data->data);
 
235
        return err;
 
236
}
 
237
 
 
238
static struct platform_driver latch_addr_flash_driver = {
 
239
        .probe          = latch_addr_flash_probe,
 
240
        .remove         = __devexit_p(latch_addr_flash_remove),
 
241
        .driver         = {
 
242
                .name   = DRIVER_NAME,
 
243
        },
 
244
};
 
245
 
 
246
static int __init latch_addr_flash_init(void)
 
247
{
 
248
        return platform_driver_register(&latch_addr_flash_driver);
 
249
}
 
250
module_init(latch_addr_flash_init);
 
251
 
 
252
static void __exit latch_addr_flash_exit(void)
 
253
{
 
254
        platform_driver_unregister(&latch_addr_flash_driver);
 
255
}
 
256
module_exit(latch_addr_flash_exit);
 
257
 
 
258
MODULE_AUTHOR("David Griego <dgriego@mvista.com>");
 
259
MODULE_DESCRIPTION("MTD map driver for flashes addressed physically with upper "
 
260
                "address lines being set board specifically");
 
261
MODULE_LICENSE("GPL v2");