xref: /linux/drivers/mtd/chips/map_absent.c (revision 58e16d792a6a8c6b750f637a4649967fcac853dc)
1*09c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * Common code to handle absent "placeholder" devices
41da177e4SLinus Torvalds  * Copyright 2001 Resilience Corporation <ebrower@resilience.com>
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * This map driver is used to allocate "placeholder" MTD
71da177e4SLinus Torvalds  * devices on systems that have socketed/removable media.
81da177e4SLinus Torvalds  * Use of this driver as a fallback preserves the expected
91da177e4SLinus Torvalds  * registration of MTD device nodes regardless of probe outcome.
101da177e4SLinus Torvalds  * A usage example is as follows:
111da177e4SLinus Torvalds  *
121da177e4SLinus Torvalds  *		my_dev[i] = do_map_probe("cfi", &my_map[i]);
131da177e4SLinus Torvalds  *		if(NULL == my_dev[i]) {
141da177e4SLinus Torvalds  *			my_dev[i] = do_map_probe("map_absent", &my_map[i]);
151da177e4SLinus Torvalds  *		}
161da177e4SLinus Torvalds  *
171da177e4SLinus Torvalds  * Any device 'probed' with this driver will return -ENODEV
181da177e4SLinus Torvalds  * upon open.
191da177e4SLinus Torvalds  */
201da177e4SLinus Torvalds 
211da177e4SLinus Torvalds #include <linux/module.h>
221da177e4SLinus Torvalds #include <linux/types.h>
231da177e4SLinus Torvalds #include <linux/kernel.h>
241da177e4SLinus Torvalds #include <linux/errno.h>
251da177e4SLinus Torvalds #include <linux/slab.h>
261da177e4SLinus Torvalds #include <linux/init.h>
271da177e4SLinus Torvalds #include <linux/mtd/mtd.h>
281da177e4SLinus Torvalds #include <linux/mtd/map.h>
291da177e4SLinus Torvalds 
301da177e4SLinus Torvalds static int map_absent_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
311da177e4SLinus Torvalds static int map_absent_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
321da177e4SLinus Torvalds static int map_absent_erase (struct mtd_info *, struct erase_info *);
331da177e4SLinus Torvalds static void map_absent_sync (struct mtd_info *);
341da177e4SLinus Torvalds static struct mtd_info *map_absent_probe(struct map_info *map);
351da177e4SLinus Torvalds static void map_absent_destroy (struct mtd_info *);
361da177e4SLinus Torvalds 
371da177e4SLinus Torvalds 
381da177e4SLinus Torvalds static struct mtd_chip_driver map_absent_chipdrv = {
391da177e4SLinus Torvalds 	.probe		= map_absent_probe,
401da177e4SLinus Torvalds 	.destroy	= map_absent_destroy,
411da177e4SLinus Torvalds 	.name		= "map_absent",
421da177e4SLinus Torvalds 	.module		= THIS_MODULE
431da177e4SLinus Torvalds };
441da177e4SLinus Torvalds 
451da177e4SLinus Torvalds static struct mtd_info *map_absent_probe(struct map_info *map)
461da177e4SLinus Torvalds {
471da177e4SLinus Torvalds 	struct mtd_info *mtd;
481da177e4SLinus Torvalds 
4995b93a0cSBurman Yan 	mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
501da177e4SLinus Torvalds 	if (!mtd) {
511da177e4SLinus Torvalds 		return NULL;
521da177e4SLinus Torvalds 	}
531da177e4SLinus Torvalds 
541da177e4SLinus Torvalds 	map->fldrv 	= &map_absent_chipdrv;
551da177e4SLinus Torvalds 	mtd->priv 	= map;
561da177e4SLinus Torvalds 	mtd->name 	= map->name;
571da177e4SLinus Torvalds 	mtd->type 	= MTD_ABSENT;
581da177e4SLinus Torvalds 	mtd->size 	= map->size;
593c3c10bbSArtem Bityutskiy 	mtd->_erase 	= map_absent_erase;
603c3c10bbSArtem Bityutskiy 	mtd->_read 	= map_absent_read;
613c3c10bbSArtem Bityutskiy 	mtd->_write 	= map_absent_write;
623c3c10bbSArtem Bityutskiy 	mtd->_sync 	= map_absent_sync;
631da177e4SLinus Torvalds 	mtd->flags 	= 0;
641da177e4SLinus Torvalds 	mtd->erasesize  = PAGE_SIZE;
6517ffc7baSArtem B. Bityutskiy 	mtd->writesize  = 1;
661da177e4SLinus Torvalds 
671da177e4SLinus Torvalds 	__module_get(THIS_MODULE);
681da177e4SLinus Torvalds 	return mtd;
691da177e4SLinus Torvalds }
701da177e4SLinus Torvalds 
711da177e4SLinus Torvalds 
721da177e4SLinus Torvalds static int map_absent_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
731da177e4SLinus Torvalds {
741da177e4SLinus Torvalds 	return -ENODEV;
751da177e4SLinus Torvalds }
761da177e4SLinus Torvalds 
771da177e4SLinus Torvalds static int map_absent_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
781da177e4SLinus Torvalds {
791da177e4SLinus Torvalds 	return -ENODEV;
801da177e4SLinus Torvalds }
811da177e4SLinus Torvalds 
821da177e4SLinus Torvalds static int map_absent_erase(struct mtd_info *mtd, struct erase_info *instr)
831da177e4SLinus Torvalds {
841da177e4SLinus Torvalds 	return -ENODEV;
851da177e4SLinus Torvalds }
861da177e4SLinus Torvalds 
871da177e4SLinus Torvalds static void map_absent_sync(struct mtd_info *mtd)
881da177e4SLinus Torvalds {
891da177e4SLinus Torvalds 	/* nop */
901da177e4SLinus Torvalds }
911da177e4SLinus Torvalds 
921da177e4SLinus Torvalds static void map_absent_destroy(struct mtd_info *mtd)
931da177e4SLinus Torvalds {
941da177e4SLinus Torvalds 	/* nop */
951da177e4SLinus Torvalds }
961da177e4SLinus Torvalds 
971da177e4SLinus Torvalds static int __init map_absent_init(void)
981da177e4SLinus Torvalds {
991da177e4SLinus Torvalds 	register_mtd_chip_driver(&map_absent_chipdrv);
1001da177e4SLinus Torvalds 	return 0;
1011da177e4SLinus Torvalds }
1021da177e4SLinus Torvalds 
1031da177e4SLinus Torvalds static void __exit map_absent_exit(void)
1041da177e4SLinus Torvalds {
1051da177e4SLinus Torvalds 	unregister_mtd_chip_driver(&map_absent_chipdrv);
1061da177e4SLinus Torvalds }
1071da177e4SLinus Torvalds 
1081da177e4SLinus Torvalds module_init(map_absent_init);
1091da177e4SLinus Torvalds module_exit(map_absent_exit);
1101da177e4SLinus Torvalds 
1111da177e4SLinus Torvalds MODULE_LICENSE("GPL");
1121da177e4SLinus Torvalds MODULE_AUTHOR("Resilience Corporation - Eric Brower <ebrower@resilience.com>");
1131da177e4SLinus Torvalds MODULE_DESCRIPTION("Placeholder MTD chip driver for 'absent' chips");
114