]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/mtd/maps/integrator-flash.c
[MTD] Fix printk format warning in physmap. (resources again)
[mirror_ubuntu-artful-kernel.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
78 info = kmalloc(sizeof(struct armflash_info), GFP_KERNEL);
79 if (!info) {
80 err = -ENOMEM;
81 goto out;
82 }
83
84 memset(info, 0, sizeof(struct armflash_info));
85
86 info->plat = plat;
87 if (plat && plat->init) {
88 err = plat->init();
89 if (err)
90 goto no_resource;
91 }
92
93 info->res = request_mem_region(res->start, size, "armflash");
94 if (!info->res) {
95 err = -EBUSY;
96 goto no_resource;
97 }
98
99 base = ioremap(res->start, size);
100 if (!base) {
101 err = -ENOMEM;
102 goto no_mem;
103 }
104
105 /*
106 * look for CFI based flash parts fitted to this board
107 */
108 info->map.size = size;
109 info->map.bankwidth = plat->width;
110 info->map.phys = res->start;
111 info->map.virt = base;
112 info->map.name = dev->dev.bus_id;
113 info->map.set_vpp = armflash_set_vpp;
114
115 simple_map_init(&info->map);
116
117 /*
118 * Also, the CFI layer automatically works out what size
119 * of chips we have, and does the necessary identification
120 * for us automatically.
121 */
122 info->mtd = do_map_probe(plat->map_name, &info->map);
123 if (!info->mtd) {
124 err = -ENXIO;
125 goto no_device;
126 }
127
128 info->mtd->owner = THIS_MODULE;
129
130 err = parse_mtd_partitions(info->mtd, probes, &info->parts, 0);
131 if (err > 0) {
132 err = add_mtd_partitions(info->mtd, info->parts, err);
133 if (err)
134 printk(KERN_ERR
135 "mtd partition registration failed: %d\n", err);
136 }
137
138 if (err == 0)
3ae5eaec 139 platform_set_drvdata(dev, info);
1da177e4
LT
140
141 /*
142 * If we got an error, free all resources.
143 */
144 if (err < 0) {
145 if (info->mtd) {
146 del_mtd_partitions(info->mtd);
147 map_destroy(info->mtd);
148 }
fa671646 149 kfree(info->parts);
1da177e4
LT
150
151 no_device:
152 iounmap(base);
153 no_mem:
154 release_mem_region(res->start, size);
155 no_resource:
156 if (plat && plat->exit)
157 plat->exit();
158 kfree(info);
159 }
160 out:
161 return err;
162}
163
3ae5eaec 164static int armflash_remove(struct platform_device *dev)
1da177e4 165{
3ae5eaec 166 struct armflash_info *info = platform_get_drvdata(dev);
1da177e4 167
3ae5eaec 168 platform_set_drvdata(dev, NULL);
1da177e4
LT
169
170 if (info) {
171 if (info->mtd) {
172 del_mtd_partitions(info->mtd);
173 map_destroy(info->mtd);
174 }
fa671646 175 kfree(info->parts);
1da177e4
LT
176
177 iounmap(info->map.virt);
178 release_resource(info->res);
179 kfree(info->res);
180
181 if (info->plat && info->plat->exit)
182 info->plat->exit();
183
184 kfree(info);
185 }
186
187 return 0;
188}
189
3ae5eaec 190static struct platform_driver armflash_driver = {
1da177e4
LT
191 .probe = armflash_probe,
192 .remove = armflash_remove,
3ae5eaec
RK
193 .driver = {
194 .name = "armflash",
195 },
1da177e4
LT
196};
197
198static int __init armflash_init(void)
199{
3ae5eaec 200 return platform_driver_register(&armflash_driver);
1da177e4
LT
201}
202
203static void __exit armflash_exit(void)
204{
3ae5eaec 205 platform_driver_unregister(&armflash_driver);
1da177e4
LT
206}
207
208module_init(armflash_init);
209module_exit(armflash_exit);
210
211MODULE_AUTHOR("ARM Ltd");
212MODULE_DESCRIPTION("ARM Integrator CFI map driver");
213MODULE_LICENSE("GPL");