1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Common code to handle map devices which are simple ROM |
4 | * (C) 2000 Red Hat. |
5 | */ |
6 | |
7 | #include <linux/module.h> |
8 | #include <linux/types.h> |
9 | #include <linux/kernel.h> |
10 | #include <asm/io.h> |
11 | #include <asm/byteorder.h> |
12 | #include <linux/errno.h> |
13 | #include <linux/slab.h> |
14 | #include <linux/init.h> |
15 | #include <linux/of.h> |
16 | #include <linux/mtd/mtd.h> |
17 | #include <linux/mtd/map.h> |
18 | |
19 | static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); |
20 | static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); |
21 | static void maprom_nop (struct mtd_info *); |
22 | static struct mtd_info *map_rom_probe(struct map_info *map); |
23 | static int maprom_erase (struct mtd_info *mtd, struct erase_info *info); |
24 | static int maprom_point (struct mtd_info *mtd, loff_t from, size_t len, |
25 | size_t *retlen, void **virt, resource_size_t *phys); |
26 | static int maprom_unpoint(struct mtd_info *mtd, loff_t from, size_t len); |
27 | |
28 | |
29 | static struct mtd_chip_driver maprom_chipdrv = { |
30 | .probe = map_rom_probe, |
31 | .name = "map_rom" , |
32 | .module = THIS_MODULE |
33 | }; |
34 | |
35 | static unsigned int default_erasesize(struct map_info *map) |
36 | { |
37 | const __be32 *erase_size = NULL; |
38 | |
39 | erase_size = of_get_property(node: map->device_node, name: "erase-size" , NULL); |
40 | |
41 | return !erase_size ? map->size : be32_to_cpu(*erase_size); |
42 | } |
43 | |
44 | static struct mtd_info *map_rom_probe(struct map_info *map) |
45 | { |
46 | struct mtd_info *mtd; |
47 | |
48 | mtd = kzalloc(size: sizeof(*mtd), GFP_KERNEL); |
49 | if (!mtd) |
50 | return NULL; |
51 | |
52 | map->fldrv = &maprom_chipdrv; |
53 | mtd->priv = map; |
54 | mtd->name = map->name; |
55 | mtd->type = MTD_ROM; |
56 | mtd->size = map->size; |
57 | mtd->_point = maprom_point; |
58 | mtd->_unpoint = maprom_unpoint; |
59 | mtd->_read = maprom_read; |
60 | mtd->_write = maprom_write; |
61 | mtd->_sync = maprom_nop; |
62 | mtd->_erase = maprom_erase; |
63 | mtd->flags = MTD_CAP_ROM; |
64 | mtd->erasesize = default_erasesize(map); |
65 | mtd->writesize = 1; |
66 | mtd->writebufsize = 1; |
67 | |
68 | __module_get(THIS_MODULE); |
69 | return mtd; |
70 | } |
71 | |
72 | |
73 | static int maprom_point(struct mtd_info *mtd, loff_t from, size_t len, |
74 | size_t *retlen, void **virt, resource_size_t *phys) |
75 | { |
76 | struct map_info *map = mtd->priv; |
77 | |
78 | if (!map->virt) |
79 | return -EINVAL; |
80 | *virt = map->virt + from; |
81 | if (phys) |
82 | *phys = map->phys + from; |
83 | *retlen = len; |
84 | return 0; |
85 | } |
86 | |
87 | static int maprom_unpoint(struct mtd_info *mtd, loff_t from, size_t len) |
88 | { |
89 | return 0; |
90 | } |
91 | |
92 | static int maprom_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) |
93 | { |
94 | struct map_info *map = mtd->priv; |
95 | |
96 | map_copy_from(map, buf, from, len); |
97 | *retlen = len; |
98 | return 0; |
99 | } |
100 | |
101 | static void maprom_nop(struct mtd_info *mtd) |
102 | { |
103 | /* Nothing to see here */ |
104 | } |
105 | |
106 | static int maprom_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) |
107 | { |
108 | return -EROFS; |
109 | } |
110 | |
111 | static int maprom_erase (struct mtd_info *mtd, struct erase_info *info) |
112 | { |
113 | /* We do our best 8) */ |
114 | return -EROFS; |
115 | } |
116 | |
117 | static int __init map_rom_init(void) |
118 | { |
119 | register_mtd_chip_driver(&maprom_chipdrv); |
120 | return 0; |
121 | } |
122 | |
123 | static void __exit map_rom_exit(void) |
124 | { |
125 | unregister_mtd_chip_driver(&maprom_chipdrv); |
126 | } |
127 | |
128 | module_init(map_rom_init); |
129 | module_exit(map_rom_exit); |
130 | |
131 | MODULE_LICENSE("GPL" ); |
132 | MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>" ); |
133 | MODULE_DESCRIPTION("MTD chip driver for ROM chips" ); |
134 | |