]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/mtd/maps/integrator-flash.c
[PATCH] MTD_NAND_SHARPSL and MTD_NAND_NANDSIM should be tristate's
[mirror_ubuntu-jammy-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
29#include <linux/config.h>
30#include <linux/module.h>
31#include <linux/types.h>
32#include <linux/kernel.h>
33#include <linux/slab.h>
34#include <linux/ioport.h>
d052d1be 35#include <linux/platform_device.h>
1da177e4
LT
36#include <linux/init.h>
37
38#include <linux/mtd/mtd.h>
39#include <linux/mtd/map.h>
40#include <linux/mtd/partitions.h>
41
42#include <asm/mach/flash.h>
43#include <asm/hardware.h>
44#include <asm/io.h>
45#include <asm/system.h>
46
47#ifdef CONFIG_ARCH_P720T
48#define FLASH_BASE (0x04000000)
49#define FLASH_SIZE (64*1024*1024)
50#endif
51
52struct armflash_info {
53 struct flash_platform_data *plat;
54 struct resource *res;
55 struct mtd_partition *parts;
56 struct mtd_info *mtd;
57 struct map_info map;
58};
59
60static void armflash_set_vpp(struct map_info *map, int on)
61{
62 struct armflash_info *info = container_of(map, struct armflash_info, map);
63
64 if (info->plat && info->plat->set_vpp)
65 info->plat->set_vpp(on);
66}
67
68static const char *probes[] = { "cmdlinepart", "RedBoot", "afs", NULL };
69
3ae5eaec 70static int armflash_probe(struct platform_device *dev)
1da177e4 71{
1da177e4
LT
72 struct flash_platform_data *plat = dev->dev.platform_data;
73 struct resource *res = dev->resource;
74 unsigned int size = res->end - res->start + 1;
75 struct armflash_info *info;
76 int err;
77 void __iomem *base;
78
79 info = kmalloc(sizeof(struct armflash_info), GFP_KERNEL);
80 if (!info) {
81 err = -ENOMEM;
82 goto out;
83 }
84
85 memset(info, 0, sizeof(struct armflash_info));
86
87 info->plat = plat;
88 if (plat && plat->init) {
89 err = plat->init();
90 if (err)
91 goto no_resource;
92 }
93
94 info->res = request_mem_region(res->start, size, "armflash");
95 if (!info->res) {
96 err = -EBUSY;
97 goto no_resource;
98 }
99
100 base = ioremap(res->start, size);
101 if (!base) {
102 err = -ENOMEM;
103 goto no_mem;
104 }
105
106 /*
107 * look for CFI based flash parts fitted to this board
108 */
109 info->map.size = size;
110 info->map.bankwidth = plat->width;
111 info->map.phys = res->start;
112 info->map.virt = base;
113 info->map.name = dev->dev.bus_id;
114 info->map.set_vpp = armflash_set_vpp;
115
116 simple_map_init(&info->map);
117
118 /*
119 * Also, the CFI layer automatically works out what size
120 * of chips we have, and does the necessary identification
121 * for us automatically.
122 */
123 info->mtd = do_map_probe(plat->map_name, &info->map);
124 if (!info->mtd) {
125 err = -ENXIO;
126 goto no_device;
127 }
128
129 info->mtd->owner = THIS_MODULE;
130
131 err = parse_mtd_partitions(info->mtd, probes, &info->parts, 0);
132 if (err > 0) {
133 err = add_mtd_partitions(info->mtd, info->parts, err);
134 if (err)
135 printk(KERN_ERR
136 "mtd partition registration failed: %d\n", err);
137 }
138
139 if (err == 0)
3ae5eaec 140 platform_set_drvdata(dev, info);
1da177e4
LT
141
142 /*
143 * If we got an error, free all resources.
144 */
145 if (err < 0) {
146 if (info->mtd) {
147 del_mtd_partitions(info->mtd);
148 map_destroy(info->mtd);
149 }
fa671646 150 kfree(info->parts);
1da177e4
LT
151
152 no_device:
153 iounmap(base);
154 no_mem:
155 release_mem_region(res->start, size);
156 no_resource:
157 if (plat && plat->exit)
158 plat->exit();
159 kfree(info);
160 }
161 out:
162 return err;
163}
164
3ae5eaec 165static int armflash_remove(struct platform_device *dev)
1da177e4 166{
3ae5eaec 167 struct armflash_info *info = platform_get_drvdata(dev);
1da177e4 168
3ae5eaec 169 platform_set_drvdata(dev, NULL);
1da177e4
LT
170
171 if (info) {
172 if (info->mtd) {
173 del_mtd_partitions(info->mtd);
174 map_destroy(info->mtd);
175 }
fa671646 176 kfree(info->parts);
1da177e4
LT
177
178 iounmap(info->map.virt);
179 release_resource(info->res);
180 kfree(info->res);
181
182 if (info->plat && info->plat->exit)
183 info->plat->exit();
184
185 kfree(info);
186 }
187
188 return 0;
189}
190
3ae5eaec 191static struct platform_driver armflash_driver = {
1da177e4
LT
192 .probe = armflash_probe,
193 .remove = armflash_remove,
3ae5eaec
RK
194 .driver = {
195 .name = "armflash",
196 },
1da177e4
LT
197};
198
199static int __init armflash_init(void)
200{
3ae5eaec 201 return platform_driver_register(&armflash_driver);
1da177e4
LT
202}
203
204static void __exit armflash_exit(void)
205{
3ae5eaec 206 platform_driver_unregister(&armflash_driver);
1da177e4
LT
207}
208
209module_init(armflash_init);
210module_exit(armflash_exit);
211
212MODULE_AUTHOR("ARM Ltd");
213MODULE_DESCRIPTION("ARM Integrator CFI map driver");
214MODULE_LICENSE("GPL");