Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 77b2555b52a894a2e39a42e43d993df875c46a6a 217 lines 5.1 kB view raw
1/*====================================================================== 2 3 drivers/mtd/maps/integrator-flash.c: ARM Integrator flash map driver 4 5 Copyright (C) 2000 ARM Limited 6 Copyright (C) 2003 Deep Blue Solutions Ltd. 7 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. 12 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. 17 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 21 22 This is access code for flashes using ARM's flash partitioning 23 standards. 24 25 $Id: integrator-flash.c,v 1.18 2004/11/01 13:26:15 rmk Exp $ 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> 35#include <linux/device.h> 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 70static int armflash_probe(struct device *_dev) 71{ 72 struct platform_device *dev = to_platform_device(_dev); 73 struct flash_platform_data *plat = dev->dev.platform_data; 74 struct resource *res = dev->resource; 75 unsigned int size = res->end - res->start + 1; 76 struct armflash_info *info; 77 int err; 78 void __iomem *base; 79 80 info = kmalloc(sizeof(struct armflash_info), GFP_KERNEL); 81 if (!info) { 82 err = -ENOMEM; 83 goto out; 84 } 85 86 memset(info, 0, sizeof(struct armflash_info)); 87 88 info->plat = plat; 89 if (plat && plat->init) { 90 err = plat->init(); 91 if (err) 92 goto no_resource; 93 } 94 95 info->res = request_mem_region(res->start, size, "armflash"); 96 if (!info->res) { 97 err = -EBUSY; 98 goto no_resource; 99 } 100 101 base = ioremap(res->start, size); 102 if (!base) { 103 err = -ENOMEM; 104 goto no_mem; 105 } 106 107 /* 108 * look for CFI based flash parts fitted to this board 109 */ 110 info->map.size = size; 111 info->map.bankwidth = plat->width; 112 info->map.phys = res->start; 113 info->map.virt = base; 114 info->map.name = dev->dev.bus_id; 115 info->map.set_vpp = armflash_set_vpp; 116 117 simple_map_init(&info->map); 118 119 /* 120 * Also, the CFI layer automatically works out what size 121 * of chips we have, and does the necessary identification 122 * for us automatically. 123 */ 124 info->mtd = do_map_probe(plat->map_name, &info->map); 125 if (!info->mtd) { 126 err = -ENXIO; 127 goto no_device; 128 } 129 130 info->mtd->owner = THIS_MODULE; 131 132 err = parse_mtd_partitions(info->mtd, probes, &info->parts, 0); 133 if (err > 0) { 134 err = add_mtd_partitions(info->mtd, info->parts, err); 135 if (err) 136 printk(KERN_ERR 137 "mtd partition registration failed: %d\n", err); 138 } 139 140 if (err == 0) 141 dev_set_drvdata(&dev->dev, info); 142 143 /* 144 * If we got an error, free all resources. 145 */ 146 if (err < 0) { 147 if (info->mtd) { 148 del_mtd_partitions(info->mtd); 149 map_destroy(info->mtd); 150 } 151 if (info->parts) 152 kfree(info->parts); 153 154 no_device: 155 iounmap(base); 156 no_mem: 157 release_mem_region(res->start, size); 158 no_resource: 159 if (plat && plat->exit) 160 plat->exit(); 161 kfree(info); 162 } 163 out: 164 return err; 165} 166 167static int armflash_remove(struct device *_dev) 168{ 169 struct platform_device *dev = to_platform_device(_dev); 170 struct armflash_info *info = dev_get_drvdata(&dev->dev); 171 172 dev_set_drvdata(&dev->dev, NULL); 173 174 if (info) { 175 if (info->mtd) { 176 del_mtd_partitions(info->mtd); 177 map_destroy(info->mtd); 178 } 179 if (info->parts) 180 kfree(info->parts); 181 182 iounmap(info->map.virt); 183 release_resource(info->res); 184 kfree(info->res); 185 186 if (info->plat && info->plat->exit) 187 info->plat->exit(); 188 189 kfree(info); 190 } 191 192 return 0; 193} 194 195static struct device_driver armflash_driver = { 196 .name = "armflash", 197 .bus = &platform_bus_type, 198 .probe = armflash_probe, 199 .remove = armflash_remove, 200}; 201 202static int __init armflash_init(void) 203{ 204 return driver_register(&armflash_driver); 205} 206 207static void __exit armflash_exit(void) 208{ 209 driver_unregister(&armflash_driver); 210} 211 212module_init(armflash_init); 213module_exit(armflash_exit); 214 215MODULE_AUTHOR("ARM Ltd"); 216MODULE_DESCRIPTION("ARM Integrator CFI map driver"); 217MODULE_LICENSE("GPL");