special usb hub handling, IDE disks, and retries all over the place
[linux-2.4.git] / drivers / mtd / maps / uclinux.c
1 /****************************************************************************/
2
3 /*
4  *      uclinux.c -- generic memory mapped MTD driver for uclinux
5  *
6  *      (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
7  *
8  *      $Id: uclinux.c,v 1.2 2002/08/07 00:43:45 gerg Exp $
9  */
10
11 /****************************************************************************/
12
13 #include <linux/config.h>
14 #include <linux/module.h>
15 #include <linux/types.h>
16 #include <linux/init.h>
17 #include <linux/kernel.h>
18 #include <linux/fs.h>
19 #include <linux/major.h>
20 #include <linux/mtd/mtd.h>
21 #include <linux/mtd/map.h>
22 #include <linux/mtd/partitions.h>
23 #include <asm/io.h>
24
25 /****************************************************************************/
26
27 __u8 uclinux_read8(struct map_info *map, unsigned long ofs)
28 {
29         return(*((__u8 *) (map->map_priv_1 + ofs)));
30 }
31
32 __u16 uclinux_read16(struct map_info *map, unsigned long ofs)
33 {
34         return(*((__u16 *) (map->map_priv_1 + ofs)));
35 }
36
37 __u32 uclinux_read32(struct map_info *map, unsigned long ofs)
38 {
39         return(*((__u32 *) (map->map_priv_1 + ofs)));
40 }
41
42 void uclinux_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
43 {
44         memcpy(to, (void *)(map->map_priv_1 + from), len);
45 }
46
47 void uclinux_write8(struct map_info *map, __u8 d, unsigned long adr)
48 {
49         *((__u8 *) (map->map_priv_1 + adr)) = d;
50 }
51
52 void uclinux_write16(struct map_info *map, __u16 d, unsigned long adr)
53 {
54         *((__u16 *) (map->map_priv_1 + adr)) = d;
55 }
56
57 void uclinux_write32(struct map_info *map, __u32 d, unsigned long adr)
58 {
59         *((__u32 *) (map->map_priv_1 + adr)) = d;
60 }
61
62 void uclinux_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
63 {
64         memcpy((void *) (map->map_priv_1 + to), from, len);
65 }
66
67 /****************************************************************************/
68
69 struct map_info uclinux_ram_map = {
70         name:           "RAM",
71         read8:          uclinux_read8,
72         read16:         uclinux_read16,
73         read32:         uclinux_read32,
74         copy_from:      uclinux_copy_from,
75         write8:         uclinux_write8,
76         write16:        uclinux_write16,
77         write32:        uclinux_write32,
78         copy_to:        uclinux_copy_to,
79 };
80
81 struct mtd_info *uclinux_ram_mtdinfo;
82
83 /****************************************************************************/
84
85 struct mtd_partition uclinux_romfs[] = {
86         { name: "ROMfs", offset: 0 }
87 };
88
89 #define NUM_PARTITIONS  (sizeof(uclinux_romfs) / sizeof(uclinux_romfs[0]))
90
91 /****************************************************************************/
92
93 int uclinux_point(struct mtd_info *mtd, loff_t from, size_t len,
94         size_t *retlen, u_char **mtdbuf)
95 {
96         struct map_info *map = (struct map_info *) mtd->priv;
97         *mtdbuf = (u_char *) (map->map_priv_1 + ((int) from));
98         *retlen = len;
99         return(0);
100 }
101
102 /****************************************************************************/
103
104 int __init uclinux_mtd_init(void)
105 {
106         struct mtd_info *mtd;
107         struct map_info *mapp;
108         extern char _ebss;
109
110         mapp = &uclinux_ram_map;
111         mapp->map_priv_2 = (unsigned long) &_ebss;
112         mapp->size = PAGE_ALIGN(*((unsigned long *)((&_ebss) + 8)));
113         mapp->buswidth = 4;
114
115         printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n",
116                 (int) mapp->map_priv_2, (int) mapp->size);
117
118         mapp->map_priv_1 = (unsigned long)
119                 ioremap_nocache(mapp->map_priv_2, mapp->size);
120
121         if (mapp->map_priv_1 == 0) {
122                 printk("uclinux[mtd]: ioremap_nocache() failed\n");
123                 return(-EIO);
124         }
125
126         mtd = do_map_probe("map_ram", mapp);
127         if (!mtd) {
128                 printk("uclinux[mtd]: failed to find a mapping?\n");
129                 iounmap((void *) mapp->map_priv_1);
130                 return(-ENXIO);
131         }
132                 
133         mtd->module = THIS_MODULE;
134         mtd->point = uclinux_point;
135         mtd->priv = mapp;
136
137         uclinux_ram_mtdinfo = mtd;
138         add_mtd_partitions(mtd, uclinux_romfs, NUM_PARTITIONS);
139
140         printk("uclinux[mtd]: set %s to be root filesystem\n",
141                 uclinux_romfs[0].name);
142         ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 0);
143         put_mtd_device(mtd);
144
145         return(0);
146 }
147
148 /****************************************************************************/
149
150 void __exit uclinux_mtd_cleanup(void)
151 {
152         if (uclinux_ram_mtdinfo) {
153                 del_mtd_partitions(uclinux_ram_mtdinfo);
154                 map_destroy(uclinux_ram_mtdinfo);
155                 uclinux_ram_mtdinfo = NULL;
156         }
157         if (uclinux_ram_map.map_priv_1) {
158                 iounmap((void *) uclinux_ram_map.map_priv_1);
159                 uclinux_ram_map.map_priv_1 = 0;
160         }
161 }
162
163 /****************************************************************************/
164
165 module_init(uclinux_mtd_init);
166 module_exit(uclinux_mtd_cleanup);
167
168 MODULE_LICENSE("GPL");
169 MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>");
170 MODULE_DESCRIPTION("Generic RAM based MTD for uClinux");
171
172 /****************************************************************************/