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 v2.6.29-rc8 297 lines 6.9 kB view raw
1/* 2 * drivers/mtd/maps/ixp4xx.c 3 * 4 * MTD Map file for IXP4XX based systems. Please do not make per-board 5 * changes in here. If your board needs special setup, do it in your 6 * platform level code in arch/arm/mach-ixp4xx/board-setup.c 7 * 8 * Original Author: Intel Corporation 9 * Maintainer: Deepak Saxena <dsaxena@mvista.com> 10 * 11 * Copyright (C) 2002 Intel Corporation 12 * Copyright (C) 2003-2004 MontaVista Software, Inc. 13 * 14 */ 15 16#include <linux/module.h> 17#include <linux/types.h> 18#include <linux/init.h> 19#include <linux/kernel.h> 20#include <linux/string.h> 21#include <linux/slab.h> 22#include <linux/ioport.h> 23#include <linux/device.h> 24#include <linux/platform_device.h> 25 26#include <linux/mtd/mtd.h> 27#include <linux/mtd/map.h> 28#include <linux/mtd/partitions.h> 29 30#include <asm/io.h> 31#include <asm/mach/flash.h> 32 33#include <linux/reboot.h> 34 35/* 36 * Read/write a 16 bit word from flash address 'addr'. 37 * 38 * When the cpu is in little-endian mode it swizzles the address lines 39 * ('address coherency') so we need to undo the swizzling to ensure commands 40 * and the like end up on the correct flash address. 41 * 42 * To further complicate matters, due to the way the expansion bus controller 43 * handles 32 bit reads, the byte stream ABCD is stored on the flash as: 44 * D15 D0 45 * +---+---+ 46 * | A | B | 0 47 * +---+---+ 48 * | C | D | 2 49 * +---+---+ 50 * This means that on LE systems each 16 bit word must be swapped. Note that 51 * this requires CONFIG_MTD_CFI_BE_BYTE_SWAP to be enabled to 'unswap' the CFI 52 * data and other flash commands which are always in D7-D0. 53 */ 54#ifndef __ARMEB__ 55#ifndef CONFIG_MTD_CFI_BE_BYTE_SWAP 56# error CONFIG_MTD_CFI_BE_BYTE_SWAP required 57#endif 58 59static inline u16 flash_read16(void __iomem *addr) 60{ 61 return be16_to_cpu(__raw_readw((void __iomem *)((unsigned long)addr ^ 0x2))); 62} 63 64static inline void flash_write16(u16 d, void __iomem *addr) 65{ 66 __raw_writew(cpu_to_be16(d), (void __iomem *)((unsigned long)addr ^ 0x2)); 67} 68 69#define BYTE0(h) ((h) & 0xFF) 70#define BYTE1(h) (((h) >> 8) & 0xFF) 71 72#else 73 74static inline u16 flash_read16(const void __iomem *addr) 75{ 76 return __raw_readw(addr); 77} 78 79static inline void flash_write16(u16 d, void __iomem *addr) 80{ 81 __raw_writew(d, addr); 82} 83 84#define BYTE0(h) (((h) >> 8) & 0xFF) 85#define BYTE1(h) ((h) & 0xFF) 86#endif 87 88static map_word ixp4xx_read16(struct map_info *map, unsigned long ofs) 89{ 90 map_word val; 91 val.x[0] = flash_read16(map->virt + ofs); 92 return val; 93} 94 95/* 96 * The IXP4xx expansion bus only allows 16-bit wide acceses 97 * when attached to a 16-bit wide device (such as the 28F128J3A), 98 * so we can't just memcpy_fromio(). 99 */ 100static void ixp4xx_copy_from(struct map_info *map, void *to, 101 unsigned long from, ssize_t len) 102{ 103 u8 *dest = (u8 *) to; 104 void __iomem *src = map->virt + from; 105 106 if (len <= 0) 107 return; 108 109 if (from & 1) { 110 *dest++ = BYTE1(flash_read16(src)); 111 src++; 112 --len; 113 } 114 115 while (len >= 2) { 116 u16 data = flash_read16(src); 117 *dest++ = BYTE0(data); 118 *dest++ = BYTE1(data); 119 src += 2; 120 len -= 2; 121 } 122 123 if (len > 0) 124 *dest++ = BYTE0(flash_read16(src)); 125} 126 127/* 128 * Unaligned writes are ignored, causing the 8-bit 129 * probe to fail and proceed to the 16-bit probe (which succeeds). 130 */ 131static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long adr) 132{ 133 if (!(adr & 1)) 134 flash_write16(d.x[0], map->virt + adr); 135} 136 137/* 138 * Fast write16 function without the probing check above 139 */ 140static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr) 141{ 142 flash_write16(d.x[0], map->virt + adr); 143} 144 145struct ixp4xx_flash_info { 146 struct mtd_info *mtd; 147 struct map_info map; 148 struct mtd_partition *partitions; 149 struct resource *res; 150}; 151 152static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; 153 154static int ixp4xx_flash_remove(struct platform_device *dev) 155{ 156 struct flash_platform_data *plat = dev->dev.platform_data; 157 struct ixp4xx_flash_info *info = platform_get_drvdata(dev); 158 159 platform_set_drvdata(dev, NULL); 160 161 if(!info) 162 return 0; 163 164 if (info->mtd) { 165 del_mtd_partitions(info->mtd); 166 map_destroy(info->mtd); 167 } 168 if (info->map.virt) 169 iounmap(info->map.virt); 170 171 kfree(info->partitions); 172 173 if (info->res) { 174 release_resource(info->res); 175 kfree(info->res); 176 } 177 178 if (plat->exit) 179 plat->exit(); 180 181 return 0; 182} 183 184static int ixp4xx_flash_probe(struct platform_device *dev) 185{ 186 struct flash_platform_data *plat = dev->dev.platform_data; 187 struct ixp4xx_flash_info *info; 188 int err = -1; 189 190 if (!plat) 191 return -ENODEV; 192 193 if (plat->init) { 194 err = plat->init(); 195 if (err) 196 return err; 197 } 198 199 info = kmalloc(sizeof(struct ixp4xx_flash_info), GFP_KERNEL); 200 if(!info) { 201 err = -ENOMEM; 202 goto Error; 203 } 204 memset(info, 0, sizeof(struct ixp4xx_flash_info)); 205 206 platform_set_drvdata(dev, info); 207 208 /* 209 * Tell the MTD layer we're not 1:1 mapped so that it does 210 * not attempt to do a direct access on us. 211 */ 212 info->map.phys = NO_XIP; 213 info->map.size = dev->resource->end - dev->resource->start + 1; 214 215 /* 216 * We only support 16-bit accesses for now. If and when 217 * any board use 8-bit access, we'll fixup the driver to 218 * handle that. 219 */ 220 info->map.bankwidth = 2; 221 info->map.name = dev_name(&dev->dev); 222 info->map.read = ixp4xx_read16, 223 info->map.write = ixp4xx_probe_write16, 224 info->map.copy_from = ixp4xx_copy_from, 225 226 info->res = request_mem_region(dev->resource->start, 227 dev->resource->end - dev->resource->start + 1, 228 "IXP4XXFlash"); 229 if (!info->res) { 230 printk(KERN_ERR "IXP4XXFlash: Could not reserve memory region\n"); 231 err = -ENOMEM; 232 goto Error; 233 } 234 235 info->map.virt = ioremap(dev->resource->start, 236 dev->resource->end - dev->resource->start + 1); 237 if (!info->map.virt) { 238 printk(KERN_ERR "IXP4XXFlash: Failed to ioremap region\n"); 239 err = -EIO; 240 goto Error; 241 } 242 243 info->mtd = do_map_probe(plat->map_name, &info->map); 244 if (!info->mtd) { 245 printk(KERN_ERR "IXP4XXFlash: map_probe failed\n"); 246 err = -ENXIO; 247 goto Error; 248 } 249 info->mtd->owner = THIS_MODULE; 250 251 /* Use the fast version */ 252 info->map.write = ixp4xx_write16, 253 254 err = parse_mtd_partitions(info->mtd, probes, &info->partitions, dev->resource->start); 255 if (err > 0) { 256 err = add_mtd_partitions(info->mtd, info->partitions, err); 257 if(err) 258 printk(KERN_ERR "Could not parse partitions\n"); 259 } 260 261 if (err) 262 goto Error; 263 264 return 0; 265 266Error: 267 ixp4xx_flash_remove(dev); 268 return err; 269} 270 271static struct platform_driver ixp4xx_flash_driver = { 272 .probe = ixp4xx_flash_probe, 273 .remove = ixp4xx_flash_remove, 274 .driver = { 275 .name = "IXP4XX-Flash", 276 .owner = THIS_MODULE, 277 }, 278}; 279 280static int __init ixp4xx_flash_init(void) 281{ 282 return platform_driver_register(&ixp4xx_flash_driver); 283} 284 285static void __exit ixp4xx_flash_exit(void) 286{ 287 platform_driver_unregister(&ixp4xx_flash_driver); 288} 289 290 291module_init(ixp4xx_flash_init); 292module_exit(ixp4xx_flash_exit); 293 294MODULE_LICENSE("GPL"); 295MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems"); 296MODULE_AUTHOR("Deepak Saxena"); 297MODULE_ALIAS("platform:IXP4XX-Flash");