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 v3.10 281 lines 6.5 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-1)); 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 resource *res; 149}; 150 151static const char * const probes[] = { "RedBoot", "cmdlinepart", NULL }; 152 153static int ixp4xx_flash_remove(struct platform_device *dev) 154{ 155 struct flash_platform_data *plat = dev->dev.platform_data; 156 struct ixp4xx_flash_info *info = platform_get_drvdata(dev); 157 158 platform_set_drvdata(dev, NULL); 159 160 if(!info) 161 return 0; 162 163 if (info->mtd) { 164 mtd_device_unregister(info->mtd); 165 map_destroy(info->mtd); 166 } 167 if (info->map.virt) 168 iounmap(info->map.virt); 169 170 if (info->res) { 171 release_resource(info->res); 172 kfree(info->res); 173 } 174 175 if (plat->exit) 176 plat->exit(); 177 178 return 0; 179} 180 181static int ixp4xx_flash_probe(struct platform_device *dev) 182{ 183 struct flash_platform_data *plat = dev->dev.platform_data; 184 struct ixp4xx_flash_info *info; 185 struct mtd_part_parser_data ppdata = { 186 .origin = dev->resource->start, 187 }; 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 = kzalloc(sizeof(struct ixp4xx_flash_info), GFP_KERNEL); 200 if(!info) { 201 err = -ENOMEM; 202 goto Error; 203 } 204 205 platform_set_drvdata(dev, info); 206 207 /* 208 * Tell the MTD layer we're not 1:1 mapped so that it does 209 * not attempt to do a direct access on us. 210 */ 211 info->map.phys = NO_XIP; 212 info->map.size = resource_size(dev->resource); 213 214 /* 215 * We only support 16-bit accesses for now. If and when 216 * any board use 8-bit access, we'll fixup the driver to 217 * handle that. 218 */ 219 info->map.bankwidth = 2; 220 info->map.name = dev_name(&dev->dev); 221 info->map.read = ixp4xx_read16; 222 info->map.write = ixp4xx_probe_write16; 223 info->map.copy_from = ixp4xx_copy_from; 224 225 info->res = request_mem_region(dev->resource->start, 226 resource_size(dev->resource), 227 "IXP4XXFlash"); 228 if (!info->res) { 229 printk(KERN_ERR "IXP4XXFlash: Could not reserve memory region\n"); 230 err = -ENOMEM; 231 goto Error; 232 } 233 234 info->map.virt = ioremap(dev->resource->start, 235 resource_size(dev->resource)); 236 if (!info->map.virt) { 237 printk(KERN_ERR "IXP4XXFlash: Failed to ioremap region\n"); 238 err = -EIO; 239 goto Error; 240 } 241 242 info->mtd = do_map_probe(plat->map_name, &info->map); 243 if (!info->mtd) { 244 printk(KERN_ERR "IXP4XXFlash: map_probe failed\n"); 245 err = -ENXIO; 246 goto Error; 247 } 248 info->mtd->owner = THIS_MODULE; 249 250 /* Use the fast version */ 251 info->map.write = ixp4xx_write16; 252 253 err = mtd_device_parse_register(info->mtd, probes, &ppdata, 254 plat->parts, plat->nr_parts); 255 if (err) { 256 printk(KERN_ERR "Could not parse partitions\n"); 257 goto Error; 258 } 259 260 return 0; 261 262Error: 263 ixp4xx_flash_remove(dev); 264 return err; 265} 266 267static struct platform_driver ixp4xx_flash_driver = { 268 .probe = ixp4xx_flash_probe, 269 .remove = ixp4xx_flash_remove, 270 .driver = { 271 .name = "IXP4XX-Flash", 272 .owner = THIS_MODULE, 273 }, 274}; 275 276module_platform_driver(ixp4xx_flash_driver); 277 278MODULE_LICENSE("GPL"); 279MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems"); 280MODULE_AUTHOR("Deepak Saxena"); 281MODULE_ALIAS("platform:IXP4XX-Flash");