]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/mtd/maps/integrator-flash.c
[MTD] replace kmalloc+memset with kzalloc
[net-next-2.6.git] / drivers / mtd / maps / integrator-flash.c
CommitLineData
1da177e4
LT
1/*======================================================================
2
3 drivers/mtd/maps/integrator-flash.c: ARM Integrator flash map driver
69f34c98 4
1da177e4
LT
5 Copyright (C) 2000 ARM Limited
6 Copyright (C) 2003 Deep Blue Solutions Ltd.
69f34c98 7
1da177e4
LT
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
69f34c98 12
1da177e4
LT
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
69f34c98 17
1da177e4
LT
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
69f34c98
TG
21
22 This is access code for flashes using ARM's flash partitioning
1da177e4
LT
23 standards.
24
69f34c98 25 $Id: integrator-flash.c,v 1.20 2005/11/07 11:14:27 gleixner Exp $
1da177e4
LT
26
27======================================================================*/
28
1da177e4
LT
29#include <linux/module.h>
30#include <linux/types.h>
31#include <linux/kernel.h>
32#include <linux/slab.h>
33#include <linux/ioport.h>
d052d1be 34#include <linux/platform_device.h>
1da177e4
LT
35#include <linux/init.h>
36
37#include <linux/mtd/mtd.h>
38#include <linux/mtd/map.h>
39#include <linux/mtd/partitions.h>
40
41#include <asm/mach/flash.h>
42#include <asm/hardware.h>
43#include <asm/io.h>
44#include <asm/system.h>
45
46#ifdef CONFIG_ARCH_P720T
47#define FLASH_BASE (0x04000000)
48#define FLASH_SIZE (64*1024*1024)
49#endif
50
51struct armflash_info {
52 struct flash_platform_data *plat;
53 struct resource *res;
54 struct mtd_partition *parts;
55 struct mtd_info *mtd;
56 struct map_info map;
57};
58
59static void armflash_set_vpp(struct map_info *map, int on)
60{
61 struct armflash_info *info = container_of(map, struct armflash_info, map);
62
63 if (info->plat && info->plat->set_vpp)
64 info->plat->set_vpp(on);
65}
66
67static const char *probes[] = { "cmdlinepart", "RedBoot", "afs", NULL };
68
3ae5eaec 69static int armflash_probe(struct platform_device *dev)
1da177e4 70{
1da177e4
LT
71 struct flash_platform_data *plat = dev->dev.platform_data;
72 struct resource *res = dev->resource;
73 unsigned int size = res->end - res->start + 1;
74 struct armflash_info *info;
75 int err;
76 void __iomem *base;
77
95b93a0c 78 info = kzalloc(sizeof(struct armflash_info), GFP_KERNEL);
1da177e4
LT
79 if (!info) {
80 err = -ENOMEM;
81 goto out;
82 }
83
1da177e4
LT
84 info->plat = plat;
85 if (plat && plat->init) {
86 err = plat->init();
87 if (err)
88 goto no_resource;
89 }
90
91 info->res = request_mem_region(res->start, size, "armflash");
92 if (!info->res) {
93 err = -EBUSY;
94 goto no_resource;
95 }
96
97 base = ioremap(res->start, size);
98 if (!base) {
99 err = -ENOMEM;
100 goto no_mem;
101 }
102
103 /*
104 * look for CFI based flash parts fitted to this board
105 */
106 info->map.size = size;
107 info->map.bankwidth = plat->width;
108 info->map.phys = res->start;
109 info->map.virt = base;
110 info->map.name = dev->dev.bus_id;
111 info->map.set_vpp = armflash_set_vpp;
112
113 simple_map_init(&info->map);
114
115 /*
116 * Also, the CFI layer automatically works out what size
117 * of chips we have, and does the necessary identification
118 * for us automatically.
119 */
120 info->mtd = do_map_probe(plat->map_name, &info->map);
121 if (!info->mtd) {
122 err = -ENXIO;
123 goto no_device;
124 }
125
126 info->mtd->owner = THIS_MODULE;
127
128 err = parse_mtd_partitions(info->mtd, probes, &info->parts, 0);
129 if (err > 0) {
130 err = add_mtd_partitions(info->mtd, info->parts, err);
131 if (err)
132 printk(KERN_ERR
133 "mtd partition registration failed: %d\n", err);
134 }
135
136 if (err == 0)
3ae5eaec 137 platform_set_drvdata(dev, info);
1da177e4
LT
138
139 /*
140 * If we got an error, free all resources.
141 */
142 if (err < 0) {
143 if (info->mtd) {
144 del_mtd_partitions(info->mtd);
145 map_destroy(info->mtd);
146 }
fa671646 147 kfree(info->parts);
1da177e4
LT
148
149 no_device:
150 iounmap(base);
151 no_mem:
152 release_mem_region(res->start, size);
153 no_resource:
154 if (plat && plat->exit)
155 plat->exit();
156 kfree(info);
157 }
158 out:
159 return err;
160}
161
3ae5eaec 162static int armflash_remove(struct platform_device *dev)
1da177e4 163{
3ae5eaec 164 struct armflash_info *info = platform_get_drvdata(dev);
1da177e4 165
3ae5eaec 166 platform_set_drvdata(dev, NULL);
1da177e4
LT
167
168 if (info) {
169 if (info->mtd) {
170 del_mtd_partitions(info->mtd);
171 map_destroy(info->mtd);
172 }
fa671646 173 kfree(info->parts);
1da177e4
LT
174
175 iounmap(info->map.virt);
176 release_resource(info->res);
177 kfree(info->res);
178
179 if (info->plat && info->plat->exit)
180 info->plat->exit();
181
182 kfree(info);
183 }
184
185 return 0;
186}
187
3ae5eaec 188static struct platform_driver armflash_driver = {
1da177e4
LT
189 .probe = armflash_probe,
190 .remove = armflash_remove,
3ae5eaec
RK
191 .driver = {
192 .name = "armflash",
193 },
1da177e4
LT
194};
195
196static int __init armflash_init(void)
197{
3ae5eaec 198 return platform_driver_register(&armflash_driver);
1da177e4
LT
199}
200
201static void __exit armflash_exit(void)
202{
3ae5eaec 203 platform_driver_unregister(&armflash_driver);
1da177e4
LT
204}
205
206module_init(armflash_init);
207module_exit(armflash_exit);
208
209MODULE_AUTHOR("ARM Ltd");
210MODULE_DESCRIPTION("ARM Integrator CFI map driver");
211MODULE_LICENSE("GPL");