map_ram.c revision 17ffc7ba6d7ea68b8d5f55a5ca1b87163e69720d
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Common code to handle map devices which are simple RAM 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (C) 2000 Red Hat. GPL'd. 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * $Id: map_ram.c,v 1.22 2005/01/05 18:05:12 dwmw2 Exp $ 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/byteorder.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mtd/mtd.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mtd/map.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mtd/compatmac.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mapram_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mapram_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mapram_erase (struct mtd_info *, struct erase_info *); 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mapram_nop (struct mtd_info *); 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mtd_info *map_ram_probe(struct map_info *map); 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mtd_chip_driver mapram_chipdrv = { 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = map_ram_probe, 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "map_ram", 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .module = THIS_MODULE 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mtd_info *map_ram_probe(struct map_info *map) 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mtd_info *mtd; 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check the first byte is RAM */ 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map_write8(map, 0x55, 0); 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (map_read8(map, 0) != 0x55) 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map_write8(map, 0xAA, 0); 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (map_read8(map, 0) != 0xAA) 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check the last byte is RAM */ 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map_write8(map, 0x55, map->size-1); 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (map_read8(map, map->size-1) != 0x55) 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map_write8(map, 0xAA, map->size-1); 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (map_read8(map, map->size-1) != 0xAA) 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* OK. It seems to be RAM. */ 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!mtd) 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(mtd, 0, sizeof(*mtd)); 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map->fldrv = &mapram_chipdrv; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mtd->priv = map; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mtd->name = map->name; 6721c8db9eff95260e543535dfc6f27164c4c0c0ffDavid Woodhouse mtd->type = MTD_RAM; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mtd->size = map->size; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mtd->erase = mapram_erase; 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mtd->read = mapram_read; 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mtd->write = mapram_write; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mtd->sync = mapram_nop; 73a6c591eda3078f92e7a3ff3db55f6841e4819fb5Jörn Engel mtd->flags = MTD_CAP_RAM; 7417ffc7ba6d7ea68b8d5f55a5ca1b87163e69720dArtem B. Bityutskiy mtd->writesize = 1; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mtd->erasesize = PAGE_SIZE; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while(mtd->size & (mtd->erasesize - 1)) 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mtd->erasesize >>= 1; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __module_get(THIS_MODULE); 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return mtd; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mapram_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct map_info *map = mtd->priv; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map_copy_from(map, buf, from, len); 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *retlen = len; 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mapram_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct map_info *map = mtd->priv; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map_copy_to(map, to, buf, len); 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *retlen = len; 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mapram_erase (struct mtd_info *mtd, struct erase_info *instr) 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Yeah, it's inefficient. Who cares? It's faster than a _real_ 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flash erase. */ 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct map_info *map = mtd->priv; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map_word allff; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long i; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds allff = map_word_ff(map); 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i=0; i<instr->len; i += map_bankwidth(map)) 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map_write(map, allff, instr->addr + i); 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds instr->state = MTD_ERASE_DONE; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mtd_erase_callback(instr); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mapram_nop(struct mtd_info *mtd) 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Nothing to see here */ 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init map_ram_init(void) 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds register_mtd_chip_driver(&mapram_chipdrv); 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit map_ram_exit(void) 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unregister_mtd_chip_driver(&mapram_chipdrv); 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(map_ram_init); 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(map_ram_exit); 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("MTD chip driver for RAM chips"); 145