mtdram.c revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mtdram - a test mtd device
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * $Id: mtdram.c,v 1.35 2005/01/05 18:05:12 dwmw2 Exp $
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author: Alexander Larsson <alex@cendio.se>
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 1999 Alexander Larsson <alex@cendio.se>
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This code is GPL
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/config.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/vmalloc.h>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mtd/compatmac.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mtd/mtd.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef CONFIG_MTDRAM_ABS_POS
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  #define CONFIG_MTDRAM_ABS_POS 0
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if CONFIG_MTDRAM_ABS_POS > 0
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  #include <asm/io.h>
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MODULE
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long total_size = CONFIG_MTDRAM_TOTAL_SIZE;
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long erase_size = CONFIG_MTDRAM_ERASE_SIZE;
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(total_size,ulong,0);
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(total_size, "Total device size in KiB");
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(erase_size,ulong,0);
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(erase_size, "Device erase block size in KiB");
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTDRAM_TOTAL_SIZE (total_size * 1024)
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTDRAM_ERASE_SIZE (erase_size * 1024)
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTDRAM_TOTAL_SIZE (CONFIG_MTDRAM_TOTAL_SIZE * 1024)
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTDRAM_ERASE_SIZE (CONFIG_MTDRAM_ERASE_SIZE * 1024)
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// We could store these in the mtd structure, but we only support 1 device..
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mtd_info *mtd_info;
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsram_erase(struct mtd_info *mtd, struct erase_info *instr)
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  DEBUG(MTD_DEBUG_LEVEL2, "ram_erase(pos:%ld, len:%ld)\n", (long)instr->addr, (long)instr->len);
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (instr->addr + instr->len > mtd->size) {
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    DEBUG(MTD_DEBUG_LEVEL1, "ram_erase() out of bounds (%ld > %ld)\n", (long)(instr->addr + instr->len), (long)mtd->size);
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return -EINVAL;
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  }
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  memset((char *)mtd->priv + instr->addr, 0xff, instr->len);
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  instr->state = MTD_ERASE_DONE;
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  mtd_erase_callback(instr);
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  return 0;
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ram_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf)
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (from + len > mtd->size)
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return -EINVAL;
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  *mtdbuf = mtd->priv + from;
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  *retlen = len;
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  return 0;
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ram_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from,
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 size_t len)
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  DEBUG(MTD_DEBUG_LEVEL2, "ram_unpoint\n");
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ram_read(struct mtd_info *mtd, loff_t from, size_t len,
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     size_t *retlen, u_char *buf)
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  DEBUG(MTD_DEBUG_LEVEL2, "ram_read(pos:%ld, len:%ld)\n", (long)from, (long)len);
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (from + len > mtd->size) {
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    DEBUG(MTD_DEBUG_LEVEL1, "ram_read() out of bounds (%ld > %ld)\n", (long)(from + len), (long)mtd->size);
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return -EINVAL;
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  }
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  memcpy(buf, mtd->priv + from, len);
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  *retlen=len;
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  return 0;
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ram_write(struct mtd_info *mtd, loff_t to, size_t len,
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      size_t *retlen, const u_char *buf)
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  DEBUG(MTD_DEBUG_LEVEL2, "ram_write(pos:%ld, len:%ld)\n", (long)to, (long)len);
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (to + len > mtd->size) {
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    DEBUG(MTD_DEBUG_LEVEL1, "ram_write() out of bounds (%ld > %ld)\n", (long)(to + len), (long)mtd->size);
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return -EINVAL;
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  }
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  memcpy ((char *)mtd->priv + to, buf, len);
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  *retlen=len;
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  return 0;
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit cleanup_mtdram(void)
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (mtd_info) {
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    del_mtd_device(mtd_info);
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if CONFIG_MTDRAM_TOTAL_SIZE > 0
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (mtd_info->priv)
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if CONFIG_MTDRAM_ABS_POS > 0
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      iounmap(mtd_info->priv);
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      vfree(mtd_info->priv);
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    kfree(mtd_info);
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  }
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint mtdram_init_device(struct mtd_info *mtd, void *mapped_address,
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                       unsigned long size, char *name)
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   memset(mtd, 0, sizeof(*mtd));
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   /* Setup the MTD structure */
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   mtd->name = name;
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   mtd->type = MTD_RAM;
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   mtd->flags = MTD_CAP_RAM;
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   mtd->size = size;
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   mtd->erasesize = MTDRAM_ERASE_SIZE;
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   mtd->priv = mapped_address;
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   mtd->owner = THIS_MODULE;
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   mtd->erase = ram_erase;
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   mtd->point = ram_point;
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   mtd->unpoint = ram_unpoint;
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   mtd->read = ram_read;
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   mtd->write = ram_write;
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   if (add_mtd_device(mtd)) {
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     return -EIO;
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   }
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   return 0;
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if CONFIG_MTDRAM_TOTAL_SIZE > 0
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if CONFIG_MTDRAM_ABS_POS > 0
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init init_mtdram(void)
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  void *addr;
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  int err;
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* Allocate some memory */
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   mtd_info = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   if (!mtd_info)
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     return -ENOMEM;
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  addr = ioremap(CONFIG_MTDRAM_ABS_POS, MTDRAM_TOTAL_SIZE);
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (!addr) {
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    DEBUG(MTD_DEBUG_LEVEL1,
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          "Failed to ioremap) memory region of size %ld at ABS_POS:%ld\n",
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          (long)MTDRAM_TOTAL_SIZE, (long)CONFIG_MTDRAM_ABS_POS);
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    kfree(mtd_info);
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    mtd_info = NULL;
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return -ENOMEM;
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  }
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  err = mtdram_init_device(mtd_info, addr,
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                           MTDRAM_TOTAL_SIZE, "mtdram test device");
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (err)
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  {
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    iounmap(addr);
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    kfree(mtd_info);
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    mtd_info = NULL;
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return err;
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  }
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  memset(mtd_info->priv, 0xff, MTDRAM_TOTAL_SIZE);
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  return err;
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else /* CONFIG_MTDRAM_ABS_POS > 0 */
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init init_mtdram(void)
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  void *addr;
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  int err;
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  /* Allocate some memory */
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   mtd_info = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   if (!mtd_info)
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     return -ENOMEM;
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  addr = vmalloc(MTDRAM_TOTAL_SIZE);
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (!addr) {
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    DEBUG(MTD_DEBUG_LEVEL1,
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          "Failed to vmalloc memory region of size %ld\n",
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          (long)MTDRAM_TOTAL_SIZE);
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    kfree(mtd_info);
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    mtd_info = NULL;
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return -ENOMEM;
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  }
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  err = mtdram_init_device(mtd_info, addr,
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                           MTDRAM_TOTAL_SIZE, "mtdram test device");
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  if (err)
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  {
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    vfree(addr);
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    kfree(mtd_info);
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    mtd_info = NULL;
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return err;
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  }
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  memset(mtd_info->priv, 0xff, MTDRAM_TOTAL_SIZE);
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  return err;
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* !(CONFIG_MTDRAM_ABS_POS > 0) */
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else /* CONFIG_MTDRAM_TOTAL_SIZE > 0 */
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init init_mtdram(void)
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  return 0;
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* !(CONFIG_MTDRAM_TOTAL_SIZE > 0) */
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(init_mtdram);
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(cleanup_mtdram);
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Alexander Larsson <alexl@redhat.com>");
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Simulated MTD driver for testing");
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
236