mtdram.c revision 21c8db9eff95260e543535dfc6f27164c4c0c0ff
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mtdram - a test mtd device
3c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel * $Id: mtdram.c,v 1.37 2005/04/21 03:42:11 joern Exp $
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author: Alexander Larsson <alex@cendio.se>
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 1999 Alexander Larsson <alex@cendio.se>
7c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel * Copyright (c) 2005 Joern Engel <joern@wh.fh-wedel.de>
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This code is GPL
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/config.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/vmalloc.h>
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mtd/compatmac.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mtd/mtd.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long total_size = CONFIG_MTDRAM_TOTAL_SIZE;
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long erase_size = CONFIG_MTDRAM_ERASE_SIZE;
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTDRAM_TOTAL_SIZE (total_size * 1024)
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTDRAM_ERASE_SIZE (erase_size * 1024)
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel#ifdef MODULE
28c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engelmodule_param(total_size, ulong, 0);
29c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern EngelMODULE_PARM_DESC(total_size, "Total device size in KiB");
30c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engelmodule_param(erase_size, ulong, 0);
31c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern EngelMODULE_PARM_DESC(erase_size, "Device erase block size in KiB");
32c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel#endif
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// We could store these in the mtd structure, but we only support 1 device..
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mtd_info *mtd_info;
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engelstatic int ram_erase(struct mtd_info *mtd, struct erase_info *instr)
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
39c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	if (instr->addr + instr->len > mtd->size)
40c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel		return -EINVAL;
41c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel
42c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	memset((char *)mtd->priv + instr->addr, 0xff, instr->len);
43c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel
44c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	instr->state = MTD_ERASE_DONE;
45c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	mtd_erase_callback(instr);
46c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel
47c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	return 0;
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engelstatic int ram_point(struct mtd_info *mtd, loff_t from, size_t len,
51c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel		size_t *retlen, u_char **mtdbuf)
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
53c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	if (from + len > mtd->size)
54c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel		return -EINVAL;
55c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel
56c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	*mtdbuf = mtd->priv + from;
57c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	*retlen = len;
58c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	return 0;
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
61c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engelstatic void ram_unpoint(struct mtd_info *mtd, u_char * addr, loff_t from,
62c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel		size_t len)
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ram_read(struct mtd_info *mtd, loff_t from, size_t len,
67c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel		size_t *retlen, u_char *buf)
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
69c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	if (from + len > mtd->size)
70c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel		return -EINVAL;
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
72c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	memcpy(buf, mtd->priv + from, len);
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
74c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	*retlen = len;
75c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	return 0;
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ram_write(struct mtd_info *mtd, loff_t to, size_t len,
79c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel		size_t *retlen, const u_char *buf)
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
81c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	if (to + len > mtd->size)
82c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel		return -EINVAL;
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
84c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	memcpy((char *)mtd->priv + to, buf, len);
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
86c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	*retlen = len;
87c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	return 0;
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit cleanup_mtdram(void)
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
92c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	if (mtd_info) {
93c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel		del_mtd_device(mtd_info);
94f9101210e7aa72daf92722d451a2f7e3af5f781fJesper Juhl		vfree(mtd_info->priv);
95c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel		kfree(mtd_info);
96c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	}
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
99c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engelint mtdram_init_device(struct mtd_info *mtd, void *mapped_address,
100c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel		unsigned long size, char *name)
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
102c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	memset(mtd, 0, sizeof(*mtd));
103c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel
104c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	/* Setup the MTD structure */
105c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	mtd->name = name;
10621c8db9eff95260e543535dfc6f27164c4c0c0ffDavid Woodhouse	mtd->type = MTD_RAM;
107c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	mtd->flags = MTD_CAP_RAM;
108c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	mtd->size = size;
109783ed81ff39d3f938a6b2efd09fbad96e41e5c1fArtem B. Bityutskiy	mtd->writesize = 1;
110c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	mtd->erasesize = MTDRAM_ERASE_SIZE;
111c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	mtd->priv = mapped_address;
112c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel
113c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	mtd->owner = THIS_MODULE;
114c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	mtd->erase = ram_erase;
115c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	mtd->point = ram_point;
116c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	mtd->unpoint = ram_unpoint;
117c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	mtd->read = ram_read;
118c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	mtd->write = ram_write;
119c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel
120c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	if (add_mtd_device(mtd)) {
121c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel		return -EIO;
122c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	}
123c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel
124c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	return 0;
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init init_mtdram(void)
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
129c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	void *addr;
130c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	int err;
131c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel
132c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	if (!total_size)
133c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel		return -EINVAL;
134c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel
135c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	/* Allocate some memory */
136c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	mtd_info = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
137c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	if (!mtd_info)
138c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel		return -ENOMEM;
139c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel
140c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	addr = vmalloc(MTDRAM_TOTAL_SIZE);
141c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	if (!addr) {
142c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel		kfree(mtd_info);
143c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel		mtd_info = NULL;
144c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel		return -ENOMEM;
145c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	}
146c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	err = mtdram_init_device(mtd_info, addr, MTDRAM_TOTAL_SIZE, "mtdram test device");
147c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	if (err) {
148c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel		vfree(addr);
149c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel		kfree(mtd_info);
150c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel		mtd_info = NULL;
151c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel		return err;
152c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	}
153c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	memset(mtd_info->priv, 0xff, MTDRAM_TOTAL_SIZE);
154c13cbf3b5086d4ed51360b86b6b0ef8b82b179dcJoern Engel	return err;
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(init_mtdram);
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(cleanup_mtdram);
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Alexander Larsson <alexl@redhat.com>");
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Simulated MTD driver for testing");
163