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 259 lines 6.0 kB view raw
1/* 2 * $Id: ixp4xx.c,v 1.7 2004/11/04 13:24:15 gleixner Exp $ 3 * 4 * drivers/mtd/maps/ixp4xx.c 5 * 6 * MTD Map file for IXP4XX based systems. Please do not make per-board 7 * changes in here. If your board needs special setup, do it in your 8 * platform level code in arch/arm/mach-ixp4xx/board-setup.c 9 * 10 * Original Author: Intel Corporation 11 * Maintainer: Deepak Saxena <dsaxena@mvista.com> 12 * 13 * Copyright (C) 2002 Intel Corporation 14 * Copyright (C) 2003-2004 MontaVista Software, Inc. 15 * 16 */ 17 18#include <linux/module.h> 19#include <linux/types.h> 20#include <linux/init.h> 21#include <linux/kernel.h> 22#include <linux/string.h> 23#include <linux/mtd/mtd.h> 24#include <linux/mtd/map.h> 25#include <linux/mtd/partitions.h> 26#include <linux/ioport.h> 27#include <linux/device.h> 28#include <asm/io.h> 29#include <asm/mach-types.h> 30#include <asm/mach/flash.h> 31 32#include <linux/reboot.h> 33 34#ifndef __ARMEB__ 35#define BYTE0(h) ((h) & 0xFF) 36#define BYTE1(h) (((h) >> 8) & 0xFF) 37#else 38#define BYTE0(h) (((h) >> 8) & 0xFF) 39#define BYTE1(h) ((h) & 0xFF) 40#endif 41 42static map_word ixp4xx_read16(struct map_info *map, unsigned long ofs) 43{ 44 map_word val; 45 val.x[0] = *(__u16 *) (map->map_priv_1 + ofs); 46 return val; 47} 48 49/* 50 * The IXP4xx expansion bus only allows 16-bit wide acceses 51 * when attached to a 16-bit wide device (such as the 28F128J3A), 52 * so we can't just memcpy_fromio(). 53 */ 54static void ixp4xx_copy_from(struct map_info *map, void *to, 55 unsigned long from, ssize_t len) 56{ 57 int i; 58 u8 *dest = (u8 *) to; 59 u16 *src = (u16 *) (map->map_priv_1 + from); 60 u16 data; 61 62 for (i = 0; i < (len / 2); i++) { 63 data = src[i]; 64 dest[i * 2] = BYTE0(data); 65 dest[i * 2 + 1] = BYTE1(data); 66 } 67 68 if (len & 1) 69 dest[len - 1] = BYTE0(src[i]); 70} 71 72/* 73 * Unaligned writes are ignored, causing the 8-bit 74 * probe to fail and proceed to the 16-bit probe (which succeeds). 75 */ 76static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long adr) 77{ 78 if (!(adr & 1)) 79 *(__u16 *) (map->map_priv_1 + adr) = d.x[0]; 80} 81 82/* 83 * Fast write16 function without the probing check above 84 */ 85static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr) 86{ 87 *(__u16 *) (map->map_priv_1 + adr) = d.x[0]; 88} 89 90struct ixp4xx_flash_info { 91 struct mtd_info *mtd; 92 struct map_info map; 93 struct mtd_partition *partitions; 94 struct resource *res; 95}; 96 97static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; 98 99static int ixp4xx_flash_remove(struct device *_dev) 100{ 101 struct platform_device *dev = to_platform_device(_dev); 102 struct flash_platform_data *plat = dev->dev.platform_data; 103 struct ixp4xx_flash_info *info = dev_get_drvdata(&dev->dev); 104 map_word d; 105 106 dev_set_drvdata(&dev->dev, NULL); 107 108 if(!info) 109 return 0; 110 111 /* 112 * This is required for a soft reboot to work. 113 */ 114 d.x[0] = 0xff; 115 ixp4xx_write16(&info->map, d, 0x55 * 0x2); 116 117 if (info->mtd) { 118 del_mtd_partitions(info->mtd); 119 map_destroy(info->mtd); 120 } 121 if (info->map.map_priv_1) 122 iounmap((void *) info->map.map_priv_1); 123 124 if (info->partitions) 125 kfree(info->partitions); 126 127 if (info->res) { 128 release_resource(info->res); 129 kfree(info->res); 130 } 131 132 if (plat->exit) 133 plat->exit(); 134 135 /* Disable flash write */ 136 *IXP4XX_EXP_CS0 &= ~IXP4XX_FLASH_WRITABLE; 137 138 return 0; 139} 140 141static int ixp4xx_flash_probe(struct device *_dev) 142{ 143 struct platform_device *dev = to_platform_device(_dev); 144 struct flash_platform_data *plat = dev->dev.platform_data; 145 struct ixp4xx_flash_info *info; 146 int err = -1; 147 148 if (!plat) 149 return -ENODEV; 150 151 if (plat->init) { 152 err = plat->init(); 153 if (err) 154 return err; 155 } 156 157 info = kmalloc(sizeof(struct ixp4xx_flash_info), GFP_KERNEL); 158 if(!info) { 159 err = -ENOMEM; 160 goto Error; 161 } 162 memzero(info, sizeof(struct ixp4xx_flash_info)); 163 164 dev_set_drvdata(&dev->dev, info); 165 166 /* 167 * Enable flash write 168 * TODO: Move this out to board specific code 169 */ 170 *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; 171 172 /* 173 * Tell the MTD layer we're not 1:1 mapped so that it does 174 * not attempt to do a direct access on us. 175 */ 176 info->map.phys = NO_XIP; 177 info->map.size = dev->resource->end - dev->resource->start + 1; 178 179 /* 180 * We only support 16-bit accesses for now. If and when 181 * any board use 8-bit access, we'll fixup the driver to 182 * handle that. 183 */ 184 info->map.bankwidth = 2; 185 info->map.name = dev->dev.bus_id; 186 info->map.read = ixp4xx_read16, 187 info->map.write = ixp4xx_probe_write16, 188 info->map.copy_from = ixp4xx_copy_from, 189 190 info->res = request_mem_region(dev->resource->start, 191 dev->resource->end - dev->resource->start + 1, 192 "IXP4XXFlash"); 193 if (!info->res) { 194 printk(KERN_ERR "IXP4XXFlash: Could not reserve memory region\n"); 195 err = -ENOMEM; 196 goto Error; 197 } 198 199 info->map.map_priv_1 = ioremap(dev->resource->start, 200 dev->resource->end - dev->resource->start + 1); 201 if (!info->map.map_priv_1) { 202 printk(KERN_ERR "IXP4XXFlash: Failed to ioremap region\n"); 203 err = -EIO; 204 goto Error; 205 } 206 207 info->mtd = do_map_probe(plat->map_name, &info->map); 208 if (!info->mtd) { 209 printk(KERN_ERR "IXP4XXFlash: map_probe failed\n"); 210 err = -ENXIO; 211 goto Error; 212 } 213 info->mtd->owner = THIS_MODULE; 214 215 /* Use the fast version */ 216 info->map.write = ixp4xx_write16, 217 218 err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0); 219 if (err > 0) { 220 err = add_mtd_partitions(info->mtd, info->partitions, err); 221 if(err) 222 printk(KERN_ERR "Could not parse partitions\n"); 223 } 224 225 if (err) 226 goto Error; 227 228 return 0; 229 230Error: 231 ixp4xx_flash_remove(_dev); 232 return err; 233} 234 235static struct device_driver ixp4xx_flash_driver = { 236 .name = "IXP4XX-Flash", 237 .bus = &platform_bus_type, 238 .probe = ixp4xx_flash_probe, 239 .remove = ixp4xx_flash_remove, 240}; 241 242static int __init ixp4xx_flash_init(void) 243{ 244 return driver_register(&ixp4xx_flash_driver); 245} 246 247static void __exit ixp4xx_flash_exit(void) 248{ 249 driver_unregister(&ixp4xx_flash_driver); 250} 251 252 253module_init(ixp4xx_flash_init); 254module_exit(ixp4xx_flash_exit); 255 256MODULE_LICENSE("GPL"); 257MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems") 258MODULE_AUTHOR("Deepak Saxena"); 259