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/err.h> 17#include <linux/module.h> 18#include <linux/types.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_get_platdata(&dev->dev); 156 struct ixp4xx_flash_info *info = platform_get_drvdata(dev); 157 158 if(!info) 159 return 0; 160 161 if (info->mtd) { 162 mtd_device_unregister(info->mtd); 163 map_destroy(info->mtd); 164 } 165 166 if (plat->exit) 167 plat->exit(); 168 169 return 0; 170} 171 172static int ixp4xx_flash_probe(struct platform_device *dev) 173{ 174 struct flash_platform_data *plat = dev_get_platdata(&dev->dev); 175 struct ixp4xx_flash_info *info; 176 struct mtd_part_parser_data ppdata = { 177 .origin = dev->resource->start, 178 }; 179 int err = -1; 180 181 if (!plat) 182 return -ENODEV; 183 184 if (plat->init) { 185 err = plat->init(); 186 if (err) 187 return err; 188 } 189 190 info = devm_kzalloc(&dev->dev, sizeof(struct ixp4xx_flash_info), 191 GFP_KERNEL); 192 if(!info) { 193 err = -ENOMEM; 194 goto Error; 195 } 196 197 platform_set_drvdata(dev, info); 198 199 /* 200 * Tell the MTD layer we're not 1:1 mapped so that it does 201 * not attempt to do a direct access on us. 202 */ 203 info->map.phys = NO_XIP; 204 info->map.size = resource_size(dev->resource); 205 206 /* 207 * We only support 16-bit accesses for now. If and when 208 * any board use 8-bit access, we'll fixup the driver to 209 * handle that. 210 */ 211 info->map.bankwidth = 2; 212 info->map.name = dev_name(&dev->dev); 213 info->map.read = ixp4xx_read16; 214 info->map.write = ixp4xx_probe_write16; 215 info->map.copy_from = ixp4xx_copy_from; 216 217 info->map.virt = devm_ioremap_resource(&dev->dev, dev->resource); 218 if (IS_ERR(info->map.virt)) { 219 err = PTR_ERR(info->map.virt); 220 goto Error; 221 } 222 223 info->mtd = do_map_probe(plat->map_name, &info->map); 224 if (!info->mtd) { 225 printk(KERN_ERR "IXP4XXFlash: map_probe failed\n"); 226 err = -ENXIO; 227 goto Error; 228 } 229 info->mtd->dev.parent = &dev->dev; 230 231 /* Use the fast version */ 232 info->map.write = ixp4xx_write16; 233 234 err = mtd_device_parse_register(info->mtd, probes, &ppdata, 235 plat->parts, plat->nr_parts); 236 if (err) { 237 printk(KERN_ERR "Could not parse partitions\n"); 238 goto Error; 239 } 240 241 return 0; 242 243Error: 244 ixp4xx_flash_remove(dev); 245 return err; 246} 247 248static struct platform_driver ixp4xx_flash_driver = { 249 .probe = ixp4xx_flash_probe, 250 .remove = ixp4xx_flash_remove, 251 .driver = { 252 .name = "IXP4XX-Flash", 253 }, 254}; 255 256module_platform_driver(ixp4xx_flash_driver); 257 258MODULE_LICENSE("GPL"); 259MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems"); 260MODULE_AUTHOR("Deepak Saxena"); 261MODULE_ALIAS("platform:IXP4XX-Flash"); 262