18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Common code to handle map devices which are simple ROM
38c2ecf20Sopenharmony_ci * (C) 2000 Red Hat. GPL'd.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <linux/module.h>
78c2ecf20Sopenharmony_ci#include <linux/types.h>
88c2ecf20Sopenharmony_ci#include <linux/kernel.h>
98c2ecf20Sopenharmony_ci#include <asm/io.h>
108c2ecf20Sopenharmony_ci#include <asm/byteorder.h>
118c2ecf20Sopenharmony_ci#include <linux/errno.h>
128c2ecf20Sopenharmony_ci#include <linux/slab.h>
138c2ecf20Sopenharmony_ci#include <linux/init.h>
148c2ecf20Sopenharmony_ci#include <linux/of.h>
158c2ecf20Sopenharmony_ci#include <linux/mtd/mtd.h>
168c2ecf20Sopenharmony_ci#include <linux/mtd/map.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_cistatic int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
198c2ecf20Sopenharmony_cistatic int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
208c2ecf20Sopenharmony_cistatic void maprom_nop (struct mtd_info *);
218c2ecf20Sopenharmony_cistatic struct mtd_info *map_rom_probe(struct map_info *map);
228c2ecf20Sopenharmony_cistatic int maprom_erase (struct mtd_info *mtd, struct erase_info *info);
238c2ecf20Sopenharmony_cistatic int maprom_point (struct mtd_info *mtd, loff_t from, size_t len,
248c2ecf20Sopenharmony_ci			 size_t *retlen, void **virt, resource_size_t *phys);
258c2ecf20Sopenharmony_cistatic int maprom_unpoint(struct mtd_info *mtd, loff_t from, size_t len);
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_cistatic struct mtd_chip_driver maprom_chipdrv = {
298c2ecf20Sopenharmony_ci	.probe	= map_rom_probe,
308c2ecf20Sopenharmony_ci	.name	= "map_rom",
318c2ecf20Sopenharmony_ci	.module	= THIS_MODULE
328c2ecf20Sopenharmony_ci};
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cistatic unsigned int default_erasesize(struct map_info *map)
358c2ecf20Sopenharmony_ci{
368c2ecf20Sopenharmony_ci	const __be32 *erase_size = NULL;
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	erase_size = of_get_property(map->device_node, "erase-size", NULL);
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	return !erase_size ? map->size : be32_to_cpu(*erase_size);
418c2ecf20Sopenharmony_ci}
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_cistatic struct mtd_info *map_rom_probe(struct map_info *map)
448c2ecf20Sopenharmony_ci{
458c2ecf20Sopenharmony_ci	struct mtd_info *mtd;
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
488c2ecf20Sopenharmony_ci	if (!mtd)
498c2ecf20Sopenharmony_ci		return NULL;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	map->fldrv = &maprom_chipdrv;
528c2ecf20Sopenharmony_ci	mtd->priv = map;
538c2ecf20Sopenharmony_ci	mtd->name = map->name;
548c2ecf20Sopenharmony_ci	mtd->type = MTD_ROM;
558c2ecf20Sopenharmony_ci	mtd->size = map->size;
568c2ecf20Sopenharmony_ci	mtd->_point = maprom_point;
578c2ecf20Sopenharmony_ci	mtd->_unpoint = maprom_unpoint;
588c2ecf20Sopenharmony_ci	mtd->_read = maprom_read;
598c2ecf20Sopenharmony_ci	mtd->_write = maprom_write;
608c2ecf20Sopenharmony_ci	mtd->_sync = maprom_nop;
618c2ecf20Sopenharmony_ci	mtd->_erase = maprom_erase;
628c2ecf20Sopenharmony_ci	mtd->flags = MTD_CAP_ROM;
638c2ecf20Sopenharmony_ci	mtd->erasesize = default_erasesize(map);
648c2ecf20Sopenharmony_ci	mtd->writesize = 1;
658c2ecf20Sopenharmony_ci	mtd->writebufsize = 1;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	__module_get(THIS_MODULE);
688c2ecf20Sopenharmony_ci	return mtd;
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_cistatic int maprom_point(struct mtd_info *mtd, loff_t from, size_t len,
738c2ecf20Sopenharmony_ci			size_t *retlen, void **virt, resource_size_t *phys)
748c2ecf20Sopenharmony_ci{
758c2ecf20Sopenharmony_ci	struct map_info *map = mtd->priv;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	if (!map->virt)
788c2ecf20Sopenharmony_ci		return -EINVAL;
798c2ecf20Sopenharmony_ci	*virt = map->virt + from;
808c2ecf20Sopenharmony_ci	if (phys)
818c2ecf20Sopenharmony_ci		*phys = map->phys + from;
828c2ecf20Sopenharmony_ci	*retlen = len;
838c2ecf20Sopenharmony_ci	return 0;
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_cistatic int maprom_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
878c2ecf20Sopenharmony_ci{
888c2ecf20Sopenharmony_ci	return 0;
898c2ecf20Sopenharmony_ci}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistatic int maprom_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
928c2ecf20Sopenharmony_ci{
938c2ecf20Sopenharmony_ci	struct map_info *map = mtd->priv;
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	map_copy_from(map, buf, from, len);
968c2ecf20Sopenharmony_ci	*retlen = len;
978c2ecf20Sopenharmony_ci	return 0;
988c2ecf20Sopenharmony_ci}
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_cistatic void maprom_nop(struct mtd_info *mtd)
1018c2ecf20Sopenharmony_ci{
1028c2ecf20Sopenharmony_ci	/* Nothing to see here */
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_cistatic int maprom_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
1068c2ecf20Sopenharmony_ci{
1078c2ecf20Sopenharmony_ci	return -EROFS;
1088c2ecf20Sopenharmony_ci}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_cistatic int maprom_erase (struct mtd_info *mtd, struct erase_info *info)
1118c2ecf20Sopenharmony_ci{
1128c2ecf20Sopenharmony_ci	/* We do our best 8) */
1138c2ecf20Sopenharmony_ci	return -EROFS;
1148c2ecf20Sopenharmony_ci}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_cistatic int __init map_rom_init(void)
1178c2ecf20Sopenharmony_ci{
1188c2ecf20Sopenharmony_ci	register_mtd_chip_driver(&maprom_chipdrv);
1198c2ecf20Sopenharmony_ci	return 0;
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_cistatic void __exit map_rom_exit(void)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	unregister_mtd_chip_driver(&maprom_chipdrv);
1258c2ecf20Sopenharmony_ci}
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_cimodule_init(map_rom_init);
1288c2ecf20Sopenharmony_cimodule_exit(map_rom_exit);
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
1318c2ecf20Sopenharmony_ciMODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
1328c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("MTD chip driver for ROM chips");
133