Commit 0dd5235f51fb0eb0b8cef3fed35be39b8a06d7bd

Authored by Artem Bityutskiy
Committed by David Woodhouse
1 parent c3faac4a74

mtd: harmonize mtd_point interface implementation

Some MTD drivers return -EINVAL if the 'phys' parameter is not NULL, trying to
convey that they cannot return the physical address. However, this is not very
logical because they still can return the virtual address ('virt'). But some
drivers (lpddr) just ignore the 'phys' parameter instead, which is a more
logical thing to do.

Let's harmonize this and:

1. Always initialize 'virt' and 'phys' to 'NULL' in 'mtd_point()'.
2. Do not return an error if the physical address cannot be found.

So as a result, all drivers will set 'phys' to 'NULL' if it is not supported.
None of the 'mtd_point()' users use 'phys' anyway, so this should not break
anything. I guess we could also just delete this parameter later.

Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>

Showing 5 changed files with 3 additions and 14 deletions Inline Diff

drivers/mtd/devices/mtdram.c
1 /* 1 /*
2 * mtdram - a test mtd device 2 * mtdram - a test mtd device
3 * Author: Alexander Larsson <alex@cendio.se> 3 * Author: Alexander Larsson <alex@cendio.se>
4 * 4 *
5 * Copyright (c) 1999 Alexander Larsson <alex@cendio.se> 5 * Copyright (c) 1999 Alexander Larsson <alex@cendio.se>
6 * Copyright (c) 2005 Joern Engel <joern@wh.fh-wedel.de> 6 * Copyright (c) 2005 Joern Engel <joern@wh.fh-wedel.de>
7 * 7 *
8 * This code is GPL 8 * This code is GPL
9 * 9 *
10 */ 10 */
11 11
12 #include <linux/module.h> 12 #include <linux/module.h>
13 #include <linux/slab.h> 13 #include <linux/slab.h>
14 #include <linux/ioport.h> 14 #include <linux/ioport.h>
15 #include <linux/vmalloc.h> 15 #include <linux/vmalloc.h>
16 #include <linux/init.h> 16 #include <linux/init.h>
17 #include <linux/mtd/mtd.h> 17 #include <linux/mtd/mtd.h>
18 #include <linux/mtd/mtdram.h> 18 #include <linux/mtd/mtdram.h>
19 19
20 static unsigned long total_size = CONFIG_MTDRAM_TOTAL_SIZE; 20 static unsigned long total_size = CONFIG_MTDRAM_TOTAL_SIZE;
21 static unsigned long erase_size = CONFIG_MTDRAM_ERASE_SIZE; 21 static unsigned long erase_size = CONFIG_MTDRAM_ERASE_SIZE;
22 #define MTDRAM_TOTAL_SIZE (total_size * 1024) 22 #define MTDRAM_TOTAL_SIZE (total_size * 1024)
23 #define MTDRAM_ERASE_SIZE (erase_size * 1024) 23 #define MTDRAM_ERASE_SIZE (erase_size * 1024)
24 24
25 #ifdef MODULE 25 #ifdef MODULE
26 module_param(total_size, ulong, 0); 26 module_param(total_size, ulong, 0);
27 MODULE_PARM_DESC(total_size, "Total device size in KiB"); 27 MODULE_PARM_DESC(total_size, "Total device size in KiB");
28 module_param(erase_size, ulong, 0); 28 module_param(erase_size, ulong, 0);
29 MODULE_PARM_DESC(erase_size, "Device erase block size in KiB"); 29 MODULE_PARM_DESC(erase_size, "Device erase block size in KiB");
30 #endif 30 #endif
31 31
32 // We could store these in the mtd structure, but we only support 1 device.. 32 // We could store these in the mtd structure, but we only support 1 device..
33 static struct mtd_info *mtd_info; 33 static struct mtd_info *mtd_info;
34 34
35 static int ram_erase(struct mtd_info *mtd, struct erase_info *instr) 35 static int ram_erase(struct mtd_info *mtd, struct erase_info *instr)
36 { 36 {
37 memset((char *)mtd->priv + instr->addr, 0xff, instr->len); 37 memset((char *)mtd->priv + instr->addr, 0xff, instr->len);
38 instr->state = MTD_ERASE_DONE; 38 instr->state = MTD_ERASE_DONE;
39 mtd_erase_callback(instr); 39 mtd_erase_callback(instr);
40 return 0; 40 return 0;
41 } 41 }
42 42
43 static int ram_point(struct mtd_info *mtd, loff_t from, size_t len, 43 static int ram_point(struct mtd_info *mtd, loff_t from, size_t len,
44 size_t *retlen, void **virt, resource_size_t *phys) 44 size_t *retlen, void **virt, resource_size_t *phys)
45 { 45 {
46 /* can we return a physical address with this driver? */
47 if (phys)
48 return -EINVAL;
49 *virt = mtd->priv + from; 46 *virt = mtd->priv + from;
50 *retlen = len; 47 *retlen = len;
51 return 0; 48 return 0;
52 } 49 }
53 50
54 static int ram_unpoint(struct mtd_info *mtd, loff_t from, size_t len) 51 static int ram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
55 { 52 {
56 return 0; 53 return 0;
57 } 54 }
58 55
59 /* 56 /*
60 * Allow NOMMU mmap() to directly map the device (if not NULL) 57 * Allow NOMMU mmap() to directly map the device (if not NULL)
61 * - return the address to which the offset maps 58 * - return the address to which the offset maps
62 * - return -ENOSYS to indicate refusal to do the mapping 59 * - return -ENOSYS to indicate refusal to do the mapping
63 */ 60 */
64 static unsigned long ram_get_unmapped_area(struct mtd_info *mtd, 61 static unsigned long ram_get_unmapped_area(struct mtd_info *mtd,
65 unsigned long len, 62 unsigned long len,
66 unsigned long offset, 63 unsigned long offset,
67 unsigned long flags) 64 unsigned long flags)
68 { 65 {
69 return (unsigned long) mtd->priv + offset; 66 return (unsigned long) mtd->priv + offset;
70 } 67 }
71 68
72 static int ram_read(struct mtd_info *mtd, loff_t from, size_t len, 69 static int ram_read(struct mtd_info *mtd, loff_t from, size_t len,
73 size_t *retlen, u_char *buf) 70 size_t *retlen, u_char *buf)
74 { 71 {
75 memcpy(buf, mtd->priv + from, len); 72 memcpy(buf, mtd->priv + from, len);
76 *retlen = len; 73 *retlen = len;
77 return 0; 74 return 0;
78 } 75 }
79 76
80 static int ram_write(struct mtd_info *mtd, loff_t to, size_t len, 77 static int ram_write(struct mtd_info *mtd, loff_t to, size_t len,
81 size_t *retlen, const u_char *buf) 78 size_t *retlen, const u_char *buf)
82 { 79 {
83 memcpy((char *)mtd->priv + to, buf, len); 80 memcpy((char *)mtd->priv + to, buf, len);
84 *retlen = len; 81 *retlen = len;
85 return 0; 82 return 0;
86 } 83 }
87 84
88 static void __exit cleanup_mtdram(void) 85 static void __exit cleanup_mtdram(void)
89 { 86 {
90 if (mtd_info) { 87 if (mtd_info) {
91 mtd_device_unregister(mtd_info); 88 mtd_device_unregister(mtd_info);
92 vfree(mtd_info->priv); 89 vfree(mtd_info->priv);
93 kfree(mtd_info); 90 kfree(mtd_info);
94 } 91 }
95 } 92 }
96 93
97 int mtdram_init_device(struct mtd_info *mtd, void *mapped_address, 94 int mtdram_init_device(struct mtd_info *mtd, void *mapped_address,
98 unsigned long size, char *name) 95 unsigned long size, char *name)
99 { 96 {
100 memset(mtd, 0, sizeof(*mtd)); 97 memset(mtd, 0, sizeof(*mtd));
101 98
102 /* Setup the MTD structure */ 99 /* Setup the MTD structure */
103 mtd->name = name; 100 mtd->name = name;
104 mtd->type = MTD_RAM; 101 mtd->type = MTD_RAM;
105 mtd->flags = MTD_CAP_RAM; 102 mtd->flags = MTD_CAP_RAM;
106 mtd->size = size; 103 mtd->size = size;
107 mtd->writesize = 1; 104 mtd->writesize = 1;
108 mtd->writebufsize = 64; /* Mimic CFI NOR flashes */ 105 mtd->writebufsize = 64; /* Mimic CFI NOR flashes */
109 mtd->erasesize = MTDRAM_ERASE_SIZE; 106 mtd->erasesize = MTDRAM_ERASE_SIZE;
110 mtd->priv = mapped_address; 107 mtd->priv = mapped_address;
111 108
112 mtd->owner = THIS_MODULE; 109 mtd->owner = THIS_MODULE;
113 mtd->_erase = ram_erase; 110 mtd->_erase = ram_erase;
114 mtd->_point = ram_point; 111 mtd->_point = ram_point;
115 mtd->_unpoint = ram_unpoint; 112 mtd->_unpoint = ram_unpoint;
116 mtd->_get_unmapped_area = ram_get_unmapped_area; 113 mtd->_get_unmapped_area = ram_get_unmapped_area;
117 mtd->_read = ram_read; 114 mtd->_read = ram_read;
118 mtd->_write = ram_write; 115 mtd->_write = ram_write;
119 116
120 if (mtd_device_register(mtd, NULL, 0)) 117 if (mtd_device_register(mtd, NULL, 0))
121 return -EIO; 118 return -EIO;
122 119
123 return 0; 120 return 0;
124 } 121 }
125 122
126 static int __init init_mtdram(void) 123 static int __init init_mtdram(void)
127 { 124 {
128 void *addr; 125 void *addr;
129 int err; 126 int err;
130 127
131 if (!total_size) 128 if (!total_size)
132 return -EINVAL; 129 return -EINVAL;
133 130
134 /* Allocate some memory */ 131 /* Allocate some memory */
135 mtd_info = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); 132 mtd_info = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
136 if (!mtd_info) 133 if (!mtd_info)
137 return -ENOMEM; 134 return -ENOMEM;
138 135
139 addr = vmalloc(MTDRAM_TOTAL_SIZE); 136 addr = vmalloc(MTDRAM_TOTAL_SIZE);
140 if (!addr) { 137 if (!addr) {
141 kfree(mtd_info); 138 kfree(mtd_info);
142 mtd_info = NULL; 139 mtd_info = NULL;
143 return -ENOMEM; 140 return -ENOMEM;
144 } 141 }
145 err = mtdram_init_device(mtd_info, addr, MTDRAM_TOTAL_SIZE, "mtdram test device"); 142 err = mtdram_init_device(mtd_info, addr, MTDRAM_TOTAL_SIZE, "mtdram test device");
146 if (err) { 143 if (err) {
147 vfree(addr); 144 vfree(addr);
148 kfree(mtd_info); 145 kfree(mtd_info);
149 mtd_info = NULL; 146 mtd_info = NULL;
150 return err; 147 return err;
151 } 148 }
152 memset(mtd_info->priv, 0xff, MTDRAM_TOTAL_SIZE); 149 memset(mtd_info->priv, 0xff, MTDRAM_TOTAL_SIZE);
153 return err; 150 return err;
154 } 151 }
155 152
156 module_init(init_mtdram); 153 module_init(init_mtdram);
157 module_exit(cleanup_mtdram); 154 module_exit(cleanup_mtdram);
158 155
159 MODULE_LICENSE("GPL"); 156 MODULE_LICENSE("GPL");
160 MODULE_AUTHOR("Alexander Larsson <alexl@redhat.com>"); 157 MODULE_AUTHOR("Alexander Larsson <alexl@redhat.com>");
161 MODULE_DESCRIPTION("Simulated MTD driver for testing"); 158 MODULE_DESCRIPTION("Simulated MTD driver for testing");
162 159
drivers/mtd/devices/phram.c
1 /** 1 /**
2 * Copyright (c) ???? Jochen Schäuble <psionic@psionic.de> 2 * Copyright (c) ???? Jochen Schäuble <psionic@psionic.de>
3 * Copyright (c) 2003-2004 Joern Engel <joern@wh.fh-wedel.de> 3 * Copyright (c) 2003-2004 Joern Engel <joern@wh.fh-wedel.de>
4 * 4 *
5 * Usage: 5 * Usage:
6 * 6 *
7 * one commend line parameter per device, each in the form: 7 * one commend line parameter per device, each in the form:
8 * phram=<name>,<start>,<len> 8 * phram=<name>,<start>,<len>
9 * <name> may be up to 63 characters. 9 * <name> may be up to 63 characters.
10 * <start> and <len> can be octal, decimal or hexadecimal. If followed 10 * <start> and <len> can be octal, decimal or hexadecimal. If followed
11 * by "ki", "Mi" or "Gi", the numbers will be interpreted as kilo, mega or 11 * by "ki", "Mi" or "Gi", the numbers will be interpreted as kilo, mega or
12 * gigabytes. 12 * gigabytes.
13 * 13 *
14 * Example: 14 * Example:
15 * phram=swap,64Mi,128Mi phram=test,900Mi,1Mi 15 * phram=swap,64Mi,128Mi phram=test,900Mi,1Mi
16 */ 16 */
17 17
18 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 18 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19 19
20 #include <asm/io.h> 20 #include <asm/io.h>
21 #include <linux/init.h> 21 #include <linux/init.h>
22 #include <linux/kernel.h> 22 #include <linux/kernel.h>
23 #include <linux/list.h> 23 #include <linux/list.h>
24 #include <linux/module.h> 24 #include <linux/module.h>
25 #include <linux/moduleparam.h> 25 #include <linux/moduleparam.h>
26 #include <linux/slab.h> 26 #include <linux/slab.h>
27 #include <linux/mtd/mtd.h> 27 #include <linux/mtd/mtd.h>
28 28
29 struct phram_mtd_list { 29 struct phram_mtd_list {
30 struct mtd_info mtd; 30 struct mtd_info mtd;
31 struct list_head list; 31 struct list_head list;
32 }; 32 };
33 33
34 static LIST_HEAD(phram_list); 34 static LIST_HEAD(phram_list);
35 35
36 static int phram_erase(struct mtd_info *mtd, struct erase_info *instr) 36 static int phram_erase(struct mtd_info *mtd, struct erase_info *instr)
37 { 37 {
38 u_char *start = mtd->priv; 38 u_char *start = mtd->priv;
39 39
40 memset(start + instr->addr, 0xff, instr->len); 40 memset(start + instr->addr, 0xff, instr->len);
41 41
42 /* This'll catch a few races. Free the thing before returning :) 42 /* This'll catch a few races. Free the thing before returning :)
43 * I don't feel at all ashamed. This kind of thing is possible anyway 43 * I don't feel at all ashamed. This kind of thing is possible anyway
44 * with flash, but unlikely. 44 * with flash, but unlikely.
45 */ 45 */
46 instr->state = MTD_ERASE_DONE; 46 instr->state = MTD_ERASE_DONE;
47 mtd_erase_callback(instr); 47 mtd_erase_callback(instr);
48 return 0; 48 return 0;
49 } 49 }
50 50
51 static int phram_point(struct mtd_info *mtd, loff_t from, size_t len, 51 static int phram_point(struct mtd_info *mtd, loff_t from, size_t len,
52 size_t *retlen, void **virt, resource_size_t *phys) 52 size_t *retlen, void **virt, resource_size_t *phys)
53 { 53 {
54 /* can we return a physical address with this driver? */
55 if (phys)
56 return -EINVAL;
57
58 *virt = mtd->priv + from; 54 *virt = mtd->priv + from;
59 *retlen = len; 55 *retlen = len;
60 return 0; 56 return 0;
61 } 57 }
62 58
63 static int phram_unpoint(struct mtd_info *mtd, loff_t from, size_t len) 59 static int phram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
64 { 60 {
65 return 0; 61 return 0;
66 } 62 }
67 63
68 static int phram_read(struct mtd_info *mtd, loff_t from, size_t len, 64 static int phram_read(struct mtd_info *mtd, loff_t from, size_t len,
69 size_t *retlen, u_char *buf) 65 size_t *retlen, u_char *buf)
70 { 66 {
71 u_char *start = mtd->priv; 67 u_char *start = mtd->priv;
72 68
73 memcpy(buf, start + from, len); 69 memcpy(buf, start + from, len);
74 *retlen = len; 70 *retlen = len;
75 return 0; 71 return 0;
76 } 72 }
77 73
78 static int phram_write(struct mtd_info *mtd, loff_t to, size_t len, 74 static int phram_write(struct mtd_info *mtd, loff_t to, size_t len,
79 size_t *retlen, const u_char *buf) 75 size_t *retlen, const u_char *buf)
80 { 76 {
81 u_char *start = mtd->priv; 77 u_char *start = mtd->priv;
82 78
83 memcpy(start + to, buf, len); 79 memcpy(start + to, buf, len);
84 *retlen = len; 80 *retlen = len;
85 return 0; 81 return 0;
86 } 82 }
87 83
88 static void unregister_devices(void) 84 static void unregister_devices(void)
89 { 85 {
90 struct phram_mtd_list *this, *safe; 86 struct phram_mtd_list *this, *safe;
91 87
92 list_for_each_entry_safe(this, safe, &phram_list, list) { 88 list_for_each_entry_safe(this, safe, &phram_list, list) {
93 mtd_device_unregister(&this->mtd); 89 mtd_device_unregister(&this->mtd);
94 iounmap(this->mtd.priv); 90 iounmap(this->mtd.priv);
95 kfree(this->mtd.name); 91 kfree(this->mtd.name);
96 kfree(this); 92 kfree(this);
97 } 93 }
98 } 94 }
99 95
100 static int register_device(char *name, unsigned long start, unsigned long len) 96 static int register_device(char *name, unsigned long start, unsigned long len)
101 { 97 {
102 struct phram_mtd_list *new; 98 struct phram_mtd_list *new;
103 int ret = -ENOMEM; 99 int ret = -ENOMEM;
104 100
105 new = kzalloc(sizeof(*new), GFP_KERNEL); 101 new = kzalloc(sizeof(*new), GFP_KERNEL);
106 if (!new) 102 if (!new)
107 goto out0; 103 goto out0;
108 104
109 ret = -EIO; 105 ret = -EIO;
110 new->mtd.priv = ioremap(start, len); 106 new->mtd.priv = ioremap(start, len);
111 if (!new->mtd.priv) { 107 if (!new->mtd.priv) {
112 pr_err("ioremap failed\n"); 108 pr_err("ioremap failed\n");
113 goto out1; 109 goto out1;
114 } 110 }
115 111
116 112
117 new->mtd.name = name; 113 new->mtd.name = name;
118 new->mtd.size = len; 114 new->mtd.size = len;
119 new->mtd.flags = MTD_CAP_RAM; 115 new->mtd.flags = MTD_CAP_RAM;
120 new->mtd._erase = phram_erase; 116 new->mtd._erase = phram_erase;
121 new->mtd._point = phram_point; 117 new->mtd._point = phram_point;
122 new->mtd._unpoint = phram_unpoint; 118 new->mtd._unpoint = phram_unpoint;
123 new->mtd._read = phram_read; 119 new->mtd._read = phram_read;
124 new->mtd._write = phram_write; 120 new->mtd._write = phram_write;
125 new->mtd.owner = THIS_MODULE; 121 new->mtd.owner = THIS_MODULE;
126 new->mtd.type = MTD_RAM; 122 new->mtd.type = MTD_RAM;
127 new->mtd.erasesize = PAGE_SIZE; 123 new->mtd.erasesize = PAGE_SIZE;
128 new->mtd.writesize = 1; 124 new->mtd.writesize = 1;
129 125
130 ret = -EAGAIN; 126 ret = -EAGAIN;
131 if (mtd_device_register(&new->mtd, NULL, 0)) { 127 if (mtd_device_register(&new->mtd, NULL, 0)) {
132 pr_err("Failed to register new device\n"); 128 pr_err("Failed to register new device\n");
133 goto out2; 129 goto out2;
134 } 130 }
135 131
136 list_add_tail(&new->list, &phram_list); 132 list_add_tail(&new->list, &phram_list);
137 return 0; 133 return 0;
138 134
139 out2: 135 out2:
140 iounmap(new->mtd.priv); 136 iounmap(new->mtd.priv);
141 out1: 137 out1:
142 kfree(new); 138 kfree(new);
143 out0: 139 out0:
144 return ret; 140 return ret;
145 } 141 }
146 142
147 static int ustrtoul(const char *cp, char **endp, unsigned int base) 143 static int ustrtoul(const char *cp, char **endp, unsigned int base)
148 { 144 {
149 unsigned long result = simple_strtoul(cp, endp, base); 145 unsigned long result = simple_strtoul(cp, endp, base);
150 146
151 switch (**endp) { 147 switch (**endp) {
152 case 'G': 148 case 'G':
153 result *= 1024; 149 result *= 1024;
154 case 'M': 150 case 'M':
155 result *= 1024; 151 result *= 1024;
156 case 'k': 152 case 'k':
157 result *= 1024; 153 result *= 1024;
158 /* By dwmw2 editorial decree, "ki", "Mi" or "Gi" are to be used. */ 154 /* By dwmw2 editorial decree, "ki", "Mi" or "Gi" are to be used. */
159 if ((*endp)[1] == 'i') 155 if ((*endp)[1] == 'i')
160 (*endp) += 2; 156 (*endp) += 2;
161 } 157 }
162 return result; 158 return result;
163 } 159 }
164 160
165 static int parse_num32(uint32_t *num32, const char *token) 161 static int parse_num32(uint32_t *num32, const char *token)
166 { 162 {
167 char *endp; 163 char *endp;
168 unsigned long n; 164 unsigned long n;
169 165
170 n = ustrtoul(token, &endp, 0); 166 n = ustrtoul(token, &endp, 0);
171 if (*endp) 167 if (*endp)
172 return -EINVAL; 168 return -EINVAL;
173 169
174 *num32 = n; 170 *num32 = n;
175 return 0; 171 return 0;
176 } 172 }
177 173
178 static int parse_name(char **pname, const char *token) 174 static int parse_name(char **pname, const char *token)
179 { 175 {
180 size_t len; 176 size_t len;
181 char *name; 177 char *name;
182 178
183 len = strlen(token) + 1; 179 len = strlen(token) + 1;
184 if (len > 64) 180 if (len > 64)
185 return -ENOSPC; 181 return -ENOSPC;
186 182
187 name = kmalloc(len, GFP_KERNEL); 183 name = kmalloc(len, GFP_KERNEL);
188 if (!name) 184 if (!name)
189 return -ENOMEM; 185 return -ENOMEM;
190 186
191 strcpy(name, token); 187 strcpy(name, token);
192 188
193 *pname = name; 189 *pname = name;
194 return 0; 190 return 0;
195 } 191 }
196 192
197 193
198 static inline void kill_final_newline(char *str) 194 static inline void kill_final_newline(char *str)
199 { 195 {
200 char *newline = strrchr(str, '\n'); 196 char *newline = strrchr(str, '\n');
201 if (newline && !newline[1]) 197 if (newline && !newline[1])
202 *newline = 0; 198 *newline = 0;
203 } 199 }
204 200
205 201
206 #define parse_err(fmt, args...) do { \ 202 #define parse_err(fmt, args...) do { \
207 pr_err(fmt , ## args); \ 203 pr_err(fmt , ## args); \
208 return 1; \ 204 return 1; \
209 } while (0) 205 } while (0)
210 206
211 static int phram_setup(const char *val, struct kernel_param *kp) 207 static int phram_setup(const char *val, struct kernel_param *kp)
212 { 208 {
213 char buf[64+12+12], *str = buf; 209 char buf[64+12+12], *str = buf;
214 char *token[3]; 210 char *token[3];
215 char *name; 211 char *name;
216 uint32_t start; 212 uint32_t start;
217 uint32_t len; 213 uint32_t len;
218 int i, ret; 214 int i, ret;
219 215
220 if (strnlen(val, sizeof(buf)) >= sizeof(buf)) 216 if (strnlen(val, sizeof(buf)) >= sizeof(buf))
221 parse_err("parameter too long\n"); 217 parse_err("parameter too long\n");
222 218
223 strcpy(str, val); 219 strcpy(str, val);
224 kill_final_newline(str); 220 kill_final_newline(str);
225 221
226 for (i=0; i<3; i++) 222 for (i=0; i<3; i++)
227 token[i] = strsep(&str, ","); 223 token[i] = strsep(&str, ",");
228 224
229 if (str) 225 if (str)
230 parse_err("too many arguments\n"); 226 parse_err("too many arguments\n");
231 227
232 if (!token[2]) 228 if (!token[2])
233 parse_err("not enough arguments\n"); 229 parse_err("not enough arguments\n");
234 230
235 ret = parse_name(&name, token[0]); 231 ret = parse_name(&name, token[0]);
236 if (ret) 232 if (ret)
237 return ret; 233 return ret;
238 234
239 ret = parse_num32(&start, token[1]); 235 ret = parse_num32(&start, token[1]);
240 if (ret) { 236 if (ret) {
241 kfree(name); 237 kfree(name);
242 parse_err("illegal start address\n"); 238 parse_err("illegal start address\n");
243 } 239 }
244 240
245 ret = parse_num32(&len, token[2]); 241 ret = parse_num32(&len, token[2]);
246 if (ret) { 242 if (ret) {
247 kfree(name); 243 kfree(name);
248 parse_err("illegal device length\n"); 244 parse_err("illegal device length\n");
249 } 245 }
250 246
251 ret = register_device(name, start, len); 247 ret = register_device(name, start, len);
252 if (!ret) 248 if (!ret)
253 pr_info("%s device: %#x at %#x\n", name, len, start); 249 pr_info("%s device: %#x at %#x\n", name, len, start);
254 else 250 else
255 kfree(name); 251 kfree(name);
256 252
257 return ret; 253 return ret;
258 } 254 }
259 255
260 module_param_call(phram, phram_setup, NULL, NULL, 000); 256 module_param_call(phram, phram_setup, NULL, NULL, 000);
261 MODULE_PARM_DESC(phram, "Memory region to map. \"phram=<name>,<start>,<length>\""); 257 MODULE_PARM_DESC(phram, "Memory region to map. \"phram=<name>,<start>,<length>\"");
262 258
263 259
264 static int __init init_phram(void) 260 static int __init init_phram(void)
265 { 261 {
266 return 0; 262 return 0;
267 } 263 }
268 264
269 static void __exit cleanup_phram(void) 265 static void __exit cleanup_phram(void)
270 { 266 {
271 unregister_devices(); 267 unregister_devices();
272 } 268 }
273 269
274 module_init(init_phram); 270 module_init(init_phram);
275 module_exit(cleanup_phram); 271 module_exit(cleanup_phram);
276 272
277 MODULE_LICENSE("GPL"); 273 MODULE_LICENSE("GPL");
278 MODULE_AUTHOR("Joern Engel <joern@wh.fh-wedel.de>"); 274 MODULE_AUTHOR("Joern Engel <joern@wh.fh-wedel.de>");
279 MODULE_DESCRIPTION("MTD driver for physical RAM"); 275 MODULE_DESCRIPTION("MTD driver for physical RAM");
280 276
drivers/mtd/devices/pmc551.c
1 /* 1 /*
2 * PMC551 PCI Mezzanine Ram Device 2 * PMC551 PCI Mezzanine Ram Device
3 * 3 *
4 * Author: 4 * Author:
5 * Mark Ferrell <mferrell@mvista.com> 5 * Mark Ferrell <mferrell@mvista.com>
6 * Copyright 1999,2000 Nortel Networks 6 * Copyright 1999,2000 Nortel Networks
7 * 7 *
8 * License: 8 * License:
9 * As part of this driver was derived from the slram.c driver it 9 * As part of this driver was derived from the slram.c driver it
10 * falls under the same license, which is GNU General Public 10 * falls under the same license, which is GNU General Public
11 * License v2 11 * License v2
12 * 12 *
13 * Description: 13 * Description:
14 * This driver is intended to support the PMC551 PCI Ram device 14 * This driver is intended to support the PMC551 PCI Ram device
15 * from Ramix Inc. The PMC551 is a PMC Mezzanine module for 15 * from Ramix Inc. The PMC551 is a PMC Mezzanine module for
16 * cPCI embedded systems. The device contains a single SROM 16 * cPCI embedded systems. The device contains a single SROM
17 * that initially programs the V370PDC chipset onboard the 17 * that initially programs the V370PDC chipset onboard the
18 * device, and various banks of DRAM/SDRAM onboard. This driver 18 * device, and various banks of DRAM/SDRAM onboard. This driver
19 * implements this PCI Ram device as an MTD (Memory Technology 19 * implements this PCI Ram device as an MTD (Memory Technology
20 * Device) so that it can be used to hold a file system, or for 20 * Device) so that it can be used to hold a file system, or for
21 * added swap space in embedded systems. Since the memory on 21 * added swap space in embedded systems. Since the memory on
22 * this board isn't as fast as main memory we do not try to hook 22 * this board isn't as fast as main memory we do not try to hook
23 * it into main memory as that would simply reduce performance 23 * it into main memory as that would simply reduce performance
24 * on the system. Using it as a block device allows us to use 24 * on the system. Using it as a block device allows us to use
25 * it as high speed swap or for a high speed disk device of some 25 * it as high speed swap or for a high speed disk device of some
26 * sort. Which becomes very useful on diskless systems in the 26 * sort. Which becomes very useful on diskless systems in the
27 * embedded market I might add. 27 * embedded market I might add.
28 * 28 *
29 * Notes: 29 * Notes:
30 * Due to what I assume is more buggy SROM, the 64M PMC551 I 30 * Due to what I assume is more buggy SROM, the 64M PMC551 I
31 * have available claims that all 4 of its DRAM banks have 64MiB 31 * have available claims that all 4 of its DRAM banks have 64MiB
32 * of ram configured (making a grand total of 256MiB onboard). 32 * of ram configured (making a grand total of 256MiB onboard).
33 * This is slightly annoying since the BAR0 size reflects the 33 * This is slightly annoying since the BAR0 size reflects the
34 * aperture size, not the dram size, and the V370PDC supplies no 34 * aperture size, not the dram size, and the V370PDC supplies no
35 * other method for memory size discovery. This problem is 35 * other method for memory size discovery. This problem is
36 * mostly only relevant when compiled as a module, as the 36 * mostly only relevant when compiled as a module, as the
37 * unloading of the module with an aperture size smaller than 37 * unloading of the module with an aperture size smaller than
38 * the ram will cause the driver to detect the onboard memory 38 * the ram will cause the driver to detect the onboard memory
39 * size to be equal to the aperture size when the module is 39 * size to be equal to the aperture size when the module is
40 * reloaded. Soooo, to help, the module supports an msize 40 * reloaded. Soooo, to help, the module supports an msize
41 * option to allow the specification of the onboard memory, and 41 * option to allow the specification of the onboard memory, and
42 * an asize option, to allow the specification of the aperture 42 * an asize option, to allow the specification of the aperture
43 * size. The aperture must be equal to or less then the memory 43 * size. The aperture must be equal to or less then the memory
44 * size, the driver will correct this if you screw it up. This 44 * size, the driver will correct this if you screw it up. This
45 * problem is not relevant for compiled in drivers as compiled 45 * problem is not relevant for compiled in drivers as compiled
46 * in drivers only init once. 46 * in drivers only init once.
47 * 47 *
48 * Credits: 48 * Credits:
49 * Saeed Karamooz <saeed@ramix.com> of Ramix INC. for the 49 * Saeed Karamooz <saeed@ramix.com> of Ramix INC. for the
50 * initial example code of how to initialize this device and for 50 * initial example code of how to initialize this device and for
51 * help with questions I had concerning operation of the device. 51 * help with questions I had concerning operation of the device.
52 * 52 *
53 * Most of the MTD code for this driver was originally written 53 * Most of the MTD code for this driver was originally written
54 * for the slram.o module in the MTD drivers package which 54 * for the slram.o module in the MTD drivers package which
55 * allows the mapping of system memory into an MTD device. 55 * allows the mapping of system memory into an MTD device.
56 * Since the PMC551 memory module is accessed in the same 56 * Since the PMC551 memory module is accessed in the same
57 * fashion as system memory, the slram.c code became a very nice 57 * fashion as system memory, the slram.c code became a very nice
58 * fit to the needs of this driver. All we added was PCI 58 * fit to the needs of this driver. All we added was PCI
59 * detection/initialization to the driver and automatically figure 59 * detection/initialization to the driver and automatically figure
60 * out the size via the PCI detection.o, later changes by Corey 60 * out the size via the PCI detection.o, later changes by Corey
61 * Minyard set up the card to utilize a 1M sliding apature. 61 * Minyard set up the card to utilize a 1M sliding apature.
62 * 62 *
63 * Corey Minyard <minyard@nortelnetworks.com> 63 * Corey Minyard <minyard@nortelnetworks.com>
64 * * Modified driver to utilize a sliding aperture instead of 64 * * Modified driver to utilize a sliding aperture instead of
65 * mapping all memory into kernel space which turned out to 65 * mapping all memory into kernel space which turned out to
66 * be very wasteful. 66 * be very wasteful.
67 * * Located a bug in the SROM's initialization sequence that 67 * * Located a bug in the SROM's initialization sequence that
68 * made the memory unusable, added a fix to code to touch up 68 * made the memory unusable, added a fix to code to touch up
69 * the DRAM some. 69 * the DRAM some.
70 * 70 *
71 * Bugs/FIXMEs: 71 * Bugs/FIXMEs:
72 * * MUST fix the init function to not spin on a register 72 * * MUST fix the init function to not spin on a register
73 * waiting for it to set .. this does not safely handle busted 73 * waiting for it to set .. this does not safely handle busted
74 * devices that never reset the register correctly which will 74 * devices that never reset the register correctly which will
75 * cause the system to hang w/ a reboot being the only chance at 75 * cause the system to hang w/ a reboot being the only chance at
76 * recover. [sort of fixed, could be better] 76 * recover. [sort of fixed, could be better]
77 * * Add I2C handling of the SROM so we can read the SROM's information 77 * * Add I2C handling of the SROM so we can read the SROM's information
78 * about the aperture size. This should always accurately reflect the 78 * about the aperture size. This should always accurately reflect the
79 * onboard memory size. 79 * onboard memory size.
80 * * Comb the init routine. It's still a bit cludgy on a few things. 80 * * Comb the init routine. It's still a bit cludgy on a few things.
81 */ 81 */
82 82
83 #include <linux/kernel.h> 83 #include <linux/kernel.h>
84 #include <linux/module.h> 84 #include <linux/module.h>
85 #include <asm/uaccess.h> 85 #include <asm/uaccess.h>
86 #include <linux/types.h> 86 #include <linux/types.h>
87 #include <linux/init.h> 87 #include <linux/init.h>
88 #include <linux/ptrace.h> 88 #include <linux/ptrace.h>
89 #include <linux/slab.h> 89 #include <linux/slab.h>
90 #include <linux/string.h> 90 #include <linux/string.h>
91 #include <linux/timer.h> 91 #include <linux/timer.h>
92 #include <linux/major.h> 92 #include <linux/major.h>
93 #include <linux/fs.h> 93 #include <linux/fs.h>
94 #include <linux/ioctl.h> 94 #include <linux/ioctl.h>
95 #include <asm/io.h> 95 #include <asm/io.h>
96 #include <asm/system.h> 96 #include <asm/system.h>
97 #include <linux/pci.h> 97 #include <linux/pci.h>
98 #include <linux/mtd/mtd.h> 98 #include <linux/mtd/mtd.h>
99 99
100 #define PMC551_VERSION \ 100 #define PMC551_VERSION \
101 "Ramix PMC551 PCI Mezzanine Ram Driver. (C) 1999,2000 Nortel Networks.\n" 101 "Ramix PMC551 PCI Mezzanine Ram Driver. (C) 1999,2000 Nortel Networks.\n"
102 102
103 #define PCI_VENDOR_ID_V3_SEMI 0x11b0 103 #define PCI_VENDOR_ID_V3_SEMI 0x11b0
104 #define PCI_DEVICE_ID_V3_SEMI_V370PDC 0x0200 104 #define PCI_DEVICE_ID_V3_SEMI_V370PDC 0x0200
105 105
106 #define PMC551_PCI_MEM_MAP0 0x50 106 #define PMC551_PCI_MEM_MAP0 0x50
107 #define PMC551_PCI_MEM_MAP1 0x54 107 #define PMC551_PCI_MEM_MAP1 0x54
108 #define PMC551_PCI_MEM_MAP_MAP_ADDR_MASK 0x3ff00000 108 #define PMC551_PCI_MEM_MAP_MAP_ADDR_MASK 0x3ff00000
109 #define PMC551_PCI_MEM_MAP_APERTURE_MASK 0x000000f0 109 #define PMC551_PCI_MEM_MAP_APERTURE_MASK 0x000000f0
110 #define PMC551_PCI_MEM_MAP_REG_EN 0x00000002 110 #define PMC551_PCI_MEM_MAP_REG_EN 0x00000002
111 #define PMC551_PCI_MEM_MAP_ENABLE 0x00000001 111 #define PMC551_PCI_MEM_MAP_ENABLE 0x00000001
112 112
113 #define PMC551_SDRAM_MA 0x60 113 #define PMC551_SDRAM_MA 0x60
114 #define PMC551_SDRAM_CMD 0x62 114 #define PMC551_SDRAM_CMD 0x62
115 #define PMC551_DRAM_CFG 0x64 115 #define PMC551_DRAM_CFG 0x64
116 #define PMC551_SYS_CTRL_REG 0x78 116 #define PMC551_SYS_CTRL_REG 0x78
117 117
118 #define PMC551_DRAM_BLK0 0x68 118 #define PMC551_DRAM_BLK0 0x68
119 #define PMC551_DRAM_BLK1 0x6c 119 #define PMC551_DRAM_BLK1 0x6c
120 #define PMC551_DRAM_BLK2 0x70 120 #define PMC551_DRAM_BLK2 0x70
121 #define PMC551_DRAM_BLK3 0x74 121 #define PMC551_DRAM_BLK3 0x74
122 #define PMC551_DRAM_BLK_GET_SIZE(x) (524288 << ((x >> 4) & 0x0f)) 122 #define PMC551_DRAM_BLK_GET_SIZE(x) (524288 << ((x >> 4) & 0x0f))
123 #define PMC551_DRAM_BLK_SET_COL_MUX(x, v) (((x) & ~0x00007000) | (((v) & 0x7) << 12)) 123 #define PMC551_DRAM_BLK_SET_COL_MUX(x, v) (((x) & ~0x00007000) | (((v) & 0x7) << 12))
124 #define PMC551_DRAM_BLK_SET_ROW_MUX(x, v) (((x) & ~0x00000f00) | (((v) & 0xf) << 8)) 124 #define PMC551_DRAM_BLK_SET_ROW_MUX(x, v) (((x) & ~0x00000f00) | (((v) & 0xf) << 8))
125 125
126 struct mypriv { 126 struct mypriv {
127 struct pci_dev *dev; 127 struct pci_dev *dev;
128 u_char *start; 128 u_char *start;
129 u32 base_map0; 129 u32 base_map0;
130 u32 curr_map0; 130 u32 curr_map0;
131 u32 asize; 131 u32 asize;
132 struct mtd_info *nextpmc551; 132 struct mtd_info *nextpmc551;
133 }; 133 };
134 134
135 static struct mtd_info *pmc551list; 135 static struct mtd_info *pmc551list;
136 136
137 static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len, 137 static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
138 size_t *retlen, void **virt, resource_size_t *phys); 138 size_t *retlen, void **virt, resource_size_t *phys);
139 139
140 static int pmc551_erase(struct mtd_info *mtd, struct erase_info *instr) 140 static int pmc551_erase(struct mtd_info *mtd, struct erase_info *instr)
141 { 141 {
142 struct mypriv *priv = mtd->priv; 142 struct mypriv *priv = mtd->priv;
143 u32 soff_hi, soff_lo; /* start address offset hi/lo */ 143 u32 soff_hi, soff_lo; /* start address offset hi/lo */
144 u32 eoff_hi, eoff_lo; /* end address offset hi/lo */ 144 u32 eoff_hi, eoff_lo; /* end address offset hi/lo */
145 unsigned long end; 145 unsigned long end;
146 u_char *ptr; 146 u_char *ptr;
147 size_t retlen; 147 size_t retlen;
148 148
149 #ifdef CONFIG_MTD_PMC551_DEBUG 149 #ifdef CONFIG_MTD_PMC551_DEBUG
150 printk(KERN_DEBUG "pmc551_erase(pos:%ld, len:%ld)\n", (long)instr->addr, 150 printk(KERN_DEBUG "pmc551_erase(pos:%ld, len:%ld)\n", (long)instr->addr,
151 (long)instr->len); 151 (long)instr->len);
152 #endif 152 #endif
153 153
154 end = instr->addr + instr->len - 1; 154 end = instr->addr + instr->len - 1;
155 eoff_hi = end & ~(priv->asize - 1); 155 eoff_hi = end & ~(priv->asize - 1);
156 soff_hi = instr->addr & ~(priv->asize - 1); 156 soff_hi = instr->addr & ~(priv->asize - 1);
157 eoff_lo = end & (priv->asize - 1); 157 eoff_lo = end & (priv->asize - 1);
158 soff_lo = instr->addr & (priv->asize - 1); 158 soff_lo = instr->addr & (priv->asize - 1);
159 159
160 pmc551_point(mtd, instr->addr, instr->len, &retlen, 160 pmc551_point(mtd, instr->addr, instr->len, &retlen,
161 (void **)&ptr, NULL); 161 (void **)&ptr, NULL);
162 162
163 if (soff_hi == eoff_hi || mtd->size == priv->asize) { 163 if (soff_hi == eoff_hi || mtd->size == priv->asize) {
164 /* The whole thing fits within one access, so just one shot 164 /* The whole thing fits within one access, so just one shot
165 will do it. */ 165 will do it. */
166 memset(ptr, 0xff, instr->len); 166 memset(ptr, 0xff, instr->len);
167 } else { 167 } else {
168 /* We have to do multiple writes to get all the data 168 /* We have to do multiple writes to get all the data
169 written. */ 169 written. */
170 while (soff_hi != eoff_hi) { 170 while (soff_hi != eoff_hi) {
171 #ifdef CONFIG_MTD_PMC551_DEBUG 171 #ifdef CONFIG_MTD_PMC551_DEBUG
172 printk(KERN_DEBUG "pmc551_erase() soff_hi: %ld, " 172 printk(KERN_DEBUG "pmc551_erase() soff_hi: %ld, "
173 "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi); 173 "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
174 #endif 174 #endif
175 memset(ptr, 0xff, priv->asize); 175 memset(ptr, 0xff, priv->asize);
176 if (soff_hi + priv->asize >= mtd->size) { 176 if (soff_hi + priv->asize >= mtd->size) {
177 goto out; 177 goto out;
178 } 178 }
179 soff_hi += priv->asize; 179 soff_hi += priv->asize;
180 pmc551_point(mtd, (priv->base_map0 | soff_hi), 180 pmc551_point(mtd, (priv->base_map0 | soff_hi),
181 priv->asize, &retlen, 181 priv->asize, &retlen,
182 (void **)&ptr, NULL); 182 (void **)&ptr, NULL);
183 } 183 }
184 memset(ptr, 0xff, eoff_lo); 184 memset(ptr, 0xff, eoff_lo);
185 } 185 }
186 186
187 out: 187 out:
188 instr->state = MTD_ERASE_DONE; 188 instr->state = MTD_ERASE_DONE;
189 #ifdef CONFIG_MTD_PMC551_DEBUG 189 #ifdef CONFIG_MTD_PMC551_DEBUG
190 printk(KERN_DEBUG "pmc551_erase() done\n"); 190 printk(KERN_DEBUG "pmc551_erase() done\n");
191 #endif 191 #endif
192 192
193 mtd_erase_callback(instr); 193 mtd_erase_callback(instr);
194 return 0; 194 return 0;
195 } 195 }
196 196
197 static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len, 197 static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
198 size_t *retlen, void **virt, resource_size_t *phys) 198 size_t *retlen, void **virt, resource_size_t *phys)
199 { 199 {
200 struct mypriv *priv = mtd->priv; 200 struct mypriv *priv = mtd->priv;
201 u32 soff_hi; 201 u32 soff_hi;
202 u32 soff_lo; 202 u32 soff_lo;
203 203
204 #ifdef CONFIG_MTD_PMC551_DEBUG 204 #ifdef CONFIG_MTD_PMC551_DEBUG
205 printk(KERN_DEBUG "pmc551_point(%ld, %ld)\n", (long)from, (long)len); 205 printk(KERN_DEBUG "pmc551_point(%ld, %ld)\n", (long)from, (long)len);
206 #endif 206 #endif
207 207
208 /* can we return a physical address with this driver? */
209 if (phys)
210 return -EINVAL;
211
212 soff_hi = from & ~(priv->asize - 1); 208 soff_hi = from & ~(priv->asize - 1);
213 soff_lo = from & (priv->asize - 1); 209 soff_lo = from & (priv->asize - 1);
214 210
215 /* Cheap hack optimization */ 211 /* Cheap hack optimization */
216 if (priv->curr_map0 != from) { 212 if (priv->curr_map0 != from) {
217 pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0, 213 pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0,
218 (priv->base_map0 | soff_hi)); 214 (priv->base_map0 | soff_hi));
219 priv->curr_map0 = soff_hi; 215 priv->curr_map0 = soff_hi;
220 } 216 }
221 217
222 *virt = priv->start + soff_lo; 218 *virt = priv->start + soff_lo;
223 *retlen = len; 219 *retlen = len;
224 return 0; 220 return 0;
225 } 221 }
226 222
227 static int pmc551_unpoint(struct mtd_info *mtd, loff_t from, size_t len) 223 static int pmc551_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
228 { 224 {
229 #ifdef CONFIG_MTD_PMC551_DEBUG 225 #ifdef CONFIG_MTD_PMC551_DEBUG
230 printk(KERN_DEBUG "pmc551_unpoint()\n"); 226 printk(KERN_DEBUG "pmc551_unpoint()\n");
231 #endif 227 #endif
232 return 0; 228 return 0;
233 } 229 }
234 230
235 static int pmc551_read(struct mtd_info *mtd, loff_t from, size_t len, 231 static int pmc551_read(struct mtd_info *mtd, loff_t from, size_t len,
236 size_t * retlen, u_char * buf) 232 size_t * retlen, u_char * buf)
237 { 233 {
238 struct mypriv *priv = mtd->priv; 234 struct mypriv *priv = mtd->priv;
239 u32 soff_hi, soff_lo; /* start address offset hi/lo */ 235 u32 soff_hi, soff_lo; /* start address offset hi/lo */
240 u32 eoff_hi, eoff_lo; /* end address offset hi/lo */ 236 u32 eoff_hi, eoff_lo; /* end address offset hi/lo */
241 unsigned long end; 237 unsigned long end;
242 u_char *ptr; 238 u_char *ptr;
243 u_char *copyto = buf; 239 u_char *copyto = buf;
244 240
245 #ifdef CONFIG_MTD_PMC551_DEBUG 241 #ifdef CONFIG_MTD_PMC551_DEBUG
246 printk(KERN_DEBUG "pmc551_read(pos:%ld, len:%ld) asize: %ld\n", 242 printk(KERN_DEBUG "pmc551_read(pos:%ld, len:%ld) asize: %ld\n",
247 (long)from, (long)len, (long)priv->asize); 243 (long)from, (long)len, (long)priv->asize);
248 #endif 244 #endif
249 245
250 end = from + len - 1; 246 end = from + len - 1;
251 soff_hi = from & ~(priv->asize - 1); 247 soff_hi = from & ~(priv->asize - 1);
252 eoff_hi = end & ~(priv->asize - 1); 248 eoff_hi = end & ~(priv->asize - 1);
253 soff_lo = from & (priv->asize - 1); 249 soff_lo = from & (priv->asize - 1);
254 eoff_lo = end & (priv->asize - 1); 250 eoff_lo = end & (priv->asize - 1);
255 251
256 pmc551_point(mtd, from, len, retlen, (void **)&ptr, NULL); 252 pmc551_point(mtd, from, len, retlen, (void **)&ptr, NULL);
257 253
258 if (soff_hi == eoff_hi) { 254 if (soff_hi == eoff_hi) {
259 /* The whole thing fits within one access, so just one shot 255 /* The whole thing fits within one access, so just one shot
260 will do it. */ 256 will do it. */
261 memcpy(copyto, ptr, len); 257 memcpy(copyto, ptr, len);
262 copyto += len; 258 copyto += len;
263 } else { 259 } else {
264 /* We have to do multiple writes to get all the data 260 /* We have to do multiple writes to get all the data
265 written. */ 261 written. */
266 while (soff_hi != eoff_hi) { 262 while (soff_hi != eoff_hi) {
267 #ifdef CONFIG_MTD_PMC551_DEBUG 263 #ifdef CONFIG_MTD_PMC551_DEBUG
268 printk(KERN_DEBUG "pmc551_read() soff_hi: %ld, " 264 printk(KERN_DEBUG "pmc551_read() soff_hi: %ld, "
269 "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi); 265 "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
270 #endif 266 #endif
271 memcpy(copyto, ptr, priv->asize); 267 memcpy(copyto, ptr, priv->asize);
272 copyto += priv->asize; 268 copyto += priv->asize;
273 if (soff_hi + priv->asize >= mtd->size) { 269 if (soff_hi + priv->asize >= mtd->size) {
274 goto out; 270 goto out;
275 } 271 }
276 soff_hi += priv->asize; 272 soff_hi += priv->asize;
277 pmc551_point(mtd, soff_hi, priv->asize, retlen, 273 pmc551_point(mtd, soff_hi, priv->asize, retlen,
278 (void **)&ptr, NULL); 274 (void **)&ptr, NULL);
279 } 275 }
280 memcpy(copyto, ptr, eoff_lo); 276 memcpy(copyto, ptr, eoff_lo);
281 copyto += eoff_lo; 277 copyto += eoff_lo;
282 } 278 }
283 279
284 out: 280 out:
285 #ifdef CONFIG_MTD_PMC551_DEBUG 281 #ifdef CONFIG_MTD_PMC551_DEBUG
286 printk(KERN_DEBUG "pmc551_read() done\n"); 282 printk(KERN_DEBUG "pmc551_read() done\n");
287 #endif 283 #endif
288 *retlen = copyto - buf; 284 *retlen = copyto - buf;
289 return 0; 285 return 0;
290 } 286 }
291 287
292 static int pmc551_write(struct mtd_info *mtd, loff_t to, size_t len, 288 static int pmc551_write(struct mtd_info *mtd, loff_t to, size_t len,
293 size_t * retlen, const u_char * buf) 289 size_t * retlen, const u_char * buf)
294 { 290 {
295 struct mypriv *priv = mtd->priv; 291 struct mypriv *priv = mtd->priv;
296 u32 soff_hi, soff_lo; /* start address offset hi/lo */ 292 u32 soff_hi, soff_lo; /* start address offset hi/lo */
297 u32 eoff_hi, eoff_lo; /* end address offset hi/lo */ 293 u32 eoff_hi, eoff_lo; /* end address offset hi/lo */
298 unsigned long end; 294 unsigned long end;
299 u_char *ptr; 295 u_char *ptr;
300 const u_char *copyfrom = buf; 296 const u_char *copyfrom = buf;
301 297
302 #ifdef CONFIG_MTD_PMC551_DEBUG 298 #ifdef CONFIG_MTD_PMC551_DEBUG
303 printk(KERN_DEBUG "pmc551_write(pos:%ld, len:%ld) asize:%ld\n", 299 printk(KERN_DEBUG "pmc551_write(pos:%ld, len:%ld) asize:%ld\n",
304 (long)to, (long)len, (long)priv->asize); 300 (long)to, (long)len, (long)priv->asize);
305 #endif 301 #endif
306 302
307 end = to + len - 1; 303 end = to + len - 1;
308 soff_hi = to & ~(priv->asize - 1); 304 soff_hi = to & ~(priv->asize - 1);
309 eoff_hi = end & ~(priv->asize - 1); 305 eoff_hi = end & ~(priv->asize - 1);
310 soff_lo = to & (priv->asize - 1); 306 soff_lo = to & (priv->asize - 1);
311 eoff_lo = end & (priv->asize - 1); 307 eoff_lo = end & (priv->asize - 1);
312 308
313 pmc551_point(mtd, to, len, retlen, (void **)&ptr, NULL); 309 pmc551_point(mtd, to, len, retlen, (void **)&ptr, NULL);
314 310
315 if (soff_hi == eoff_hi) { 311 if (soff_hi == eoff_hi) {
316 /* The whole thing fits within one access, so just one shot 312 /* The whole thing fits within one access, so just one shot
317 will do it. */ 313 will do it. */
318 memcpy(ptr, copyfrom, len); 314 memcpy(ptr, copyfrom, len);
319 copyfrom += len; 315 copyfrom += len;
320 } else { 316 } else {
321 /* We have to do multiple writes to get all the data 317 /* We have to do multiple writes to get all the data
322 written. */ 318 written. */
323 while (soff_hi != eoff_hi) { 319 while (soff_hi != eoff_hi) {
324 #ifdef CONFIG_MTD_PMC551_DEBUG 320 #ifdef CONFIG_MTD_PMC551_DEBUG
325 printk(KERN_DEBUG "pmc551_write() soff_hi: %ld, " 321 printk(KERN_DEBUG "pmc551_write() soff_hi: %ld, "
326 "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi); 322 "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
327 #endif 323 #endif
328 memcpy(ptr, copyfrom, priv->asize); 324 memcpy(ptr, copyfrom, priv->asize);
329 copyfrom += priv->asize; 325 copyfrom += priv->asize;
330 if (soff_hi >= mtd->size) { 326 if (soff_hi >= mtd->size) {
331 goto out; 327 goto out;
332 } 328 }
333 soff_hi += priv->asize; 329 soff_hi += priv->asize;
334 pmc551_point(mtd, soff_hi, priv->asize, retlen, 330 pmc551_point(mtd, soff_hi, priv->asize, retlen,
335 (void **)&ptr, NULL); 331 (void **)&ptr, NULL);
336 } 332 }
337 memcpy(ptr, copyfrom, eoff_lo); 333 memcpy(ptr, copyfrom, eoff_lo);
338 copyfrom += eoff_lo; 334 copyfrom += eoff_lo;
339 } 335 }
340 336
341 out: 337 out:
342 #ifdef CONFIG_MTD_PMC551_DEBUG 338 #ifdef CONFIG_MTD_PMC551_DEBUG
343 printk(KERN_DEBUG "pmc551_write() done\n"); 339 printk(KERN_DEBUG "pmc551_write() done\n");
344 #endif 340 #endif
345 *retlen = copyfrom - buf; 341 *retlen = copyfrom - buf;
346 return 0; 342 return 0;
347 } 343 }
348 344
349 /* 345 /*
350 * Fixup routines for the V370PDC 346 * Fixup routines for the V370PDC
351 * PCI device ID 0x020011b0 347 * PCI device ID 0x020011b0
352 * 348 *
353 * This function basically kick starts the DRAM oboard the card and gets it 349 * This function basically kick starts the DRAM oboard the card and gets it
354 * ready to be used. Before this is done the device reads VERY erratic, so 350 * ready to be used. Before this is done the device reads VERY erratic, so
355 * much that it can crash the Linux 2.2.x series kernels when a user cat's 351 * much that it can crash the Linux 2.2.x series kernels when a user cat's
356 * /proc/pci .. though that is mainly a kernel bug in handling the PCI DEVSEL 352 * /proc/pci .. though that is mainly a kernel bug in handling the PCI DEVSEL
357 * register. FIXME: stop spinning on registers .. must implement a timeout 353 * register. FIXME: stop spinning on registers .. must implement a timeout
358 * mechanism 354 * mechanism
359 * returns the size of the memory region found. 355 * returns the size of the memory region found.
360 */ 356 */
361 static int fixup_pmc551(struct pci_dev *dev) 357 static int fixup_pmc551(struct pci_dev *dev)
362 { 358 {
363 #ifdef CONFIG_MTD_PMC551_BUGFIX 359 #ifdef CONFIG_MTD_PMC551_BUGFIX
364 u32 dram_data; 360 u32 dram_data;
365 #endif 361 #endif
366 u32 size, dcmd, cfg, dtmp; 362 u32 size, dcmd, cfg, dtmp;
367 u16 cmd, tmp, i; 363 u16 cmd, tmp, i;
368 u8 bcmd, counter; 364 u8 bcmd, counter;
369 365
370 /* Sanity Check */ 366 /* Sanity Check */
371 if (!dev) { 367 if (!dev) {
372 return -ENODEV; 368 return -ENODEV;
373 } 369 }
374 370
375 /* 371 /*
376 * Attempt to reset the card 372 * Attempt to reset the card
377 * FIXME: Stop Spinning registers 373 * FIXME: Stop Spinning registers
378 */ 374 */
379 counter = 0; 375 counter = 0;
380 /* unlock registers */ 376 /* unlock registers */
381 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5); 377 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5);
382 /* read in old data */ 378 /* read in old data */
383 pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd); 379 pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd);
384 /* bang the reset line up and down for a few */ 380 /* bang the reset line up and down for a few */
385 for (i = 0; i < 10; i++) { 381 for (i = 0; i < 10; i++) {
386 counter = 0; 382 counter = 0;
387 bcmd &= ~0x80; 383 bcmd &= ~0x80;
388 while (counter++ < 100) { 384 while (counter++ < 100) {
389 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); 385 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
390 } 386 }
391 counter = 0; 387 counter = 0;
392 bcmd |= 0x80; 388 bcmd |= 0x80;
393 while (counter++ < 100) { 389 while (counter++ < 100) {
394 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); 390 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
395 } 391 }
396 } 392 }
397 bcmd |= (0x40 | 0x20); 393 bcmd |= (0x40 | 0x20);
398 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); 394 pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
399 395
400 /* 396 /*
401 * Take care and turn off the memory on the device while we 397 * Take care and turn off the memory on the device while we
402 * tweak the configurations 398 * tweak the configurations
403 */ 399 */
404 pci_read_config_word(dev, PCI_COMMAND, &cmd); 400 pci_read_config_word(dev, PCI_COMMAND, &cmd);
405 tmp = cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY); 401 tmp = cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
406 pci_write_config_word(dev, PCI_COMMAND, tmp); 402 pci_write_config_word(dev, PCI_COMMAND, tmp);
407 403
408 /* 404 /*
409 * Disable existing aperture before probing memory size 405 * Disable existing aperture before probing memory size
410 */ 406 */
411 pci_read_config_dword(dev, PMC551_PCI_MEM_MAP0, &dcmd); 407 pci_read_config_dword(dev, PMC551_PCI_MEM_MAP0, &dcmd);
412 dtmp = (dcmd | PMC551_PCI_MEM_MAP_ENABLE | PMC551_PCI_MEM_MAP_REG_EN); 408 dtmp = (dcmd | PMC551_PCI_MEM_MAP_ENABLE | PMC551_PCI_MEM_MAP_REG_EN);
413 pci_write_config_dword(dev, PMC551_PCI_MEM_MAP0, dtmp); 409 pci_write_config_dword(dev, PMC551_PCI_MEM_MAP0, dtmp);
414 /* 410 /*
415 * Grab old BAR0 config so that we can figure out memory size 411 * Grab old BAR0 config so that we can figure out memory size
416 * This is another bit of kludge going on. The reason for the 412 * This is another bit of kludge going on. The reason for the
417 * redundancy is I am hoping to retain the original configuration 413 * redundancy is I am hoping to retain the original configuration
418 * previously assigned to the card by the BIOS or some previous 414 * previously assigned to the card by the BIOS or some previous
419 * fixup routine in the kernel. So we read the old config into cfg, 415 * fixup routine in the kernel. So we read the old config into cfg,
420 * then write all 1's to the memory space, read back the result into 416 * then write all 1's to the memory space, read back the result into
421 * "size", and then write back all the old config. 417 * "size", and then write back all the old config.
422 */ 418 */
423 pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &cfg); 419 pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &cfg);
424 #ifndef CONFIG_MTD_PMC551_BUGFIX 420 #ifndef CONFIG_MTD_PMC551_BUGFIX
425 pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, ~0); 421 pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, ~0);
426 pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &size); 422 pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &size);
427 size = (size & PCI_BASE_ADDRESS_MEM_MASK); 423 size = (size & PCI_BASE_ADDRESS_MEM_MASK);
428 size &= ~(size - 1); 424 size &= ~(size - 1);
429 pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, cfg); 425 pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, cfg);
430 #else 426 #else
431 /* 427 /*
432 * Get the size of the memory by reading all the DRAM size values 428 * Get the size of the memory by reading all the DRAM size values
433 * and adding them up. 429 * and adding them up.
434 * 430 *
435 * KLUDGE ALERT: the boards we are using have invalid column and 431 * KLUDGE ALERT: the boards we are using have invalid column and
436 * row mux values. We fix them here, but this will break other 432 * row mux values. We fix them here, but this will break other
437 * memory configurations. 433 * memory configurations.
438 */ 434 */
439 pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data); 435 pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data);
440 size = PMC551_DRAM_BLK_GET_SIZE(dram_data); 436 size = PMC551_DRAM_BLK_GET_SIZE(dram_data);
441 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); 437 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
442 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); 438 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
443 pci_write_config_dword(dev, PMC551_DRAM_BLK0, dram_data); 439 pci_write_config_dword(dev, PMC551_DRAM_BLK0, dram_data);
444 440
445 pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dram_data); 441 pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dram_data);
446 size += PMC551_DRAM_BLK_GET_SIZE(dram_data); 442 size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
447 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); 443 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
448 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); 444 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
449 pci_write_config_dword(dev, PMC551_DRAM_BLK1, dram_data); 445 pci_write_config_dword(dev, PMC551_DRAM_BLK1, dram_data);
450 446
451 pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dram_data); 447 pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dram_data);
452 size += PMC551_DRAM_BLK_GET_SIZE(dram_data); 448 size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
453 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); 449 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
454 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); 450 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
455 pci_write_config_dword(dev, PMC551_DRAM_BLK2, dram_data); 451 pci_write_config_dword(dev, PMC551_DRAM_BLK2, dram_data);
456 452
457 pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dram_data); 453 pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dram_data);
458 size += PMC551_DRAM_BLK_GET_SIZE(dram_data); 454 size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
459 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); 455 dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
460 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); 456 dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
461 pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data); 457 pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data);
462 458
463 /* 459 /*
464 * Oops .. something went wrong 460 * Oops .. something went wrong
465 */ 461 */
466 if ((size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) { 462 if ((size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) {
467 return -ENODEV; 463 return -ENODEV;
468 } 464 }
469 #endif /* CONFIG_MTD_PMC551_BUGFIX */ 465 #endif /* CONFIG_MTD_PMC551_BUGFIX */
470 466
471 if ((cfg & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) { 467 if ((cfg & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) {
472 return -ENODEV; 468 return -ENODEV;
473 } 469 }
474 470
475 /* 471 /*
476 * Precharge Dram 472 * Precharge Dram
477 */ 473 */
478 pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0400); 474 pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0400);
479 pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x00bf); 475 pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x00bf);
480 476
481 /* 477 /*
482 * Wait until command has gone through 478 * Wait until command has gone through
483 * FIXME: register spinning issue 479 * FIXME: register spinning issue
484 */ 480 */
485 do { 481 do {
486 pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd); 482 pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
487 if (counter++ > 100) 483 if (counter++ > 100)
488 break; 484 break;
489 } while ((PCI_COMMAND_IO) & cmd); 485 } while ((PCI_COMMAND_IO) & cmd);
490 486
491 /* 487 /*
492 * Turn on auto refresh 488 * Turn on auto refresh
493 * The loop is taken directly from Ramix's example code. I assume that 489 * The loop is taken directly from Ramix's example code. I assume that
494 * this must be held high for some duration of time, but I can find no 490 * this must be held high for some duration of time, but I can find no
495 * documentation refrencing the reasons why. 491 * documentation refrencing the reasons why.
496 */ 492 */
497 for (i = 1; i <= 8; i++) { 493 for (i = 1; i <= 8; i++) {
498 pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0df); 494 pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0df);
499 495
500 /* 496 /*
501 * Make certain command has gone through 497 * Make certain command has gone through
502 * FIXME: register spinning issue 498 * FIXME: register spinning issue
503 */ 499 */
504 counter = 0; 500 counter = 0;
505 do { 501 do {
506 pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd); 502 pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
507 if (counter++ > 100) 503 if (counter++ > 100)
508 break; 504 break;
509 } while ((PCI_COMMAND_IO) & cmd); 505 } while ((PCI_COMMAND_IO) & cmd);
510 } 506 }
511 507
512 pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0020); 508 pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0020);
513 pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0ff); 509 pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0ff);
514 510
515 /* 511 /*
516 * Wait until command completes 512 * Wait until command completes
517 * FIXME: register spinning issue 513 * FIXME: register spinning issue
518 */ 514 */
519 counter = 0; 515 counter = 0;
520 do { 516 do {
521 pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd); 517 pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
522 if (counter++ > 100) 518 if (counter++ > 100)
523 break; 519 break;
524 } while ((PCI_COMMAND_IO) & cmd); 520 } while ((PCI_COMMAND_IO) & cmd);
525 521
526 pci_read_config_dword(dev, PMC551_DRAM_CFG, &dcmd); 522 pci_read_config_dword(dev, PMC551_DRAM_CFG, &dcmd);
527 dcmd |= 0x02000000; 523 dcmd |= 0x02000000;
528 pci_write_config_dword(dev, PMC551_DRAM_CFG, dcmd); 524 pci_write_config_dword(dev, PMC551_DRAM_CFG, dcmd);
529 525
530 /* 526 /*
531 * Check to make certain fast back-to-back, if not 527 * Check to make certain fast back-to-back, if not
532 * then set it so 528 * then set it so
533 */ 529 */
534 pci_read_config_word(dev, PCI_STATUS, &cmd); 530 pci_read_config_word(dev, PCI_STATUS, &cmd);
535 if ((cmd & PCI_COMMAND_FAST_BACK) == 0) { 531 if ((cmd & PCI_COMMAND_FAST_BACK) == 0) {
536 cmd |= PCI_COMMAND_FAST_BACK; 532 cmd |= PCI_COMMAND_FAST_BACK;
537 pci_write_config_word(dev, PCI_STATUS, cmd); 533 pci_write_config_word(dev, PCI_STATUS, cmd);
538 } 534 }
539 535
540 /* 536 /*
541 * Check to make certain the DEVSEL is set correctly, this device 537 * Check to make certain the DEVSEL is set correctly, this device
542 * has a tendency to assert DEVSEL and TRDY when a write is performed 538 * has a tendency to assert DEVSEL and TRDY when a write is performed
543 * to the memory when memory is read-only 539 * to the memory when memory is read-only
544 */ 540 */
545 if ((cmd & PCI_STATUS_DEVSEL_MASK) != 0x0) { 541 if ((cmd & PCI_STATUS_DEVSEL_MASK) != 0x0) {
546 cmd &= ~PCI_STATUS_DEVSEL_MASK; 542 cmd &= ~PCI_STATUS_DEVSEL_MASK;
547 pci_write_config_word(dev, PCI_STATUS, cmd); 543 pci_write_config_word(dev, PCI_STATUS, cmd);
548 } 544 }
549 /* 545 /*
550 * Set to be prefetchable and put everything back based on old cfg. 546 * Set to be prefetchable and put everything back based on old cfg.
551 * it's possible that the reset of the V370PDC nuked the original 547 * it's possible that the reset of the V370PDC nuked the original
552 * setup 548 * setup
553 */ 549 */
554 /* 550 /*
555 cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH; 551 cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH;
556 pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg ); 552 pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg );
557 */ 553 */
558 554
559 /* 555 /*
560 * Turn PCI memory and I/O bus access back on 556 * Turn PCI memory and I/O bus access back on
561 */ 557 */
562 pci_write_config_word(dev, PCI_COMMAND, 558 pci_write_config_word(dev, PCI_COMMAND,
563 PCI_COMMAND_MEMORY | PCI_COMMAND_IO); 559 PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
564 #ifdef CONFIG_MTD_PMC551_DEBUG 560 #ifdef CONFIG_MTD_PMC551_DEBUG
565 /* 561 /*
566 * Some screen fun 562 * Some screen fun
567 */ 563 */
568 printk(KERN_DEBUG "pmc551: %d%sB (0x%x) of %sprefetchable memory at " 564 printk(KERN_DEBUG "pmc551: %d%sB (0x%x) of %sprefetchable memory at "
569 "0x%llx\n", (size < 1024) ? size : (size < 1048576) ? 565 "0x%llx\n", (size < 1024) ? size : (size < 1048576) ?
570 size >> 10 : size >> 20, 566 size >> 10 : size >> 20,
571 (size < 1024) ? "" : (size < 1048576) ? "Ki" : "Mi", size, 567 (size < 1024) ? "" : (size < 1048576) ? "Ki" : "Mi", size,
572 ((dcmd & (0x1 << 3)) == 0) ? "non-" : "", 568 ((dcmd & (0x1 << 3)) == 0) ? "non-" : "",
573 (unsigned long long)pci_resource_start(dev, 0)); 569 (unsigned long long)pci_resource_start(dev, 0));
574 570
575 /* 571 /*
576 * Check to see the state of the memory 572 * Check to see the state of the memory
577 */ 573 */
578 pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dcmd); 574 pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dcmd);
579 printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n" 575 printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n"
580 "pmc551: DRAM_BLK0 Size: %d at %d\n" 576 "pmc551: DRAM_BLK0 Size: %d at %d\n"
581 "pmc551: DRAM_BLK0 Row MUX: %d, Col MUX: %d\n", 577 "pmc551: DRAM_BLK0 Row MUX: %d, Col MUX: %d\n",
582 (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO", 578 (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
583 (((0x1 << 0) & dcmd) == 0) ? "Off" : "On", 579 (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
584 PMC551_DRAM_BLK_GET_SIZE(dcmd), 580 PMC551_DRAM_BLK_GET_SIZE(dcmd),
585 ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7), 581 ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
586 ((dcmd >> 9) & 0xF)); 582 ((dcmd >> 9) & 0xF));
587 583
588 pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dcmd); 584 pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dcmd);
589 printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n" 585 printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n"
590 "pmc551: DRAM_BLK1 Size: %d at %d\n" 586 "pmc551: DRAM_BLK1 Size: %d at %d\n"
591 "pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n", 587 "pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n",
592 (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO", 588 (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
593 (((0x1 << 0) & dcmd) == 0) ? "Off" : "On", 589 (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
594 PMC551_DRAM_BLK_GET_SIZE(dcmd), 590 PMC551_DRAM_BLK_GET_SIZE(dcmd),
595 ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7), 591 ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
596 ((dcmd >> 9) & 0xF)); 592 ((dcmd >> 9) & 0xF));
597 593
598 pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dcmd); 594 pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dcmd);
599 printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n" 595 printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n"
600 "pmc551: DRAM_BLK2 Size: %d at %d\n" 596 "pmc551: DRAM_BLK2 Size: %d at %d\n"
601 "pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n", 597 "pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n",
602 (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO", 598 (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
603 (((0x1 << 0) & dcmd) == 0) ? "Off" : "On", 599 (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
604 PMC551_DRAM_BLK_GET_SIZE(dcmd), 600 PMC551_DRAM_BLK_GET_SIZE(dcmd),
605 ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7), 601 ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
606 ((dcmd >> 9) & 0xF)); 602 ((dcmd >> 9) & 0xF));
607 603
608 pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dcmd); 604 pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dcmd);
609 printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n" 605 printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n"
610 "pmc551: DRAM_BLK3 Size: %d at %d\n" 606 "pmc551: DRAM_BLK3 Size: %d at %d\n"
611 "pmc551: DRAM_BLK3 Row MUX: %d, Col MUX: %d\n", 607 "pmc551: DRAM_BLK3 Row MUX: %d, Col MUX: %d\n",
612 (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO", 608 (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
613 (((0x1 << 0) & dcmd) == 0) ? "Off" : "On", 609 (((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
614 PMC551_DRAM_BLK_GET_SIZE(dcmd), 610 PMC551_DRAM_BLK_GET_SIZE(dcmd),
615 ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7), 611 ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
616 ((dcmd >> 9) & 0xF)); 612 ((dcmd >> 9) & 0xF));
617 613
618 pci_read_config_word(dev, PCI_COMMAND, &cmd); 614 pci_read_config_word(dev, PCI_COMMAND, &cmd);
619 printk(KERN_DEBUG "pmc551: Memory Access %s\n", 615 printk(KERN_DEBUG "pmc551: Memory Access %s\n",
620 (((0x1 << 1) & cmd) == 0) ? "off" : "on"); 616 (((0x1 << 1) & cmd) == 0) ? "off" : "on");
621 printk(KERN_DEBUG "pmc551: I/O Access %s\n", 617 printk(KERN_DEBUG "pmc551: I/O Access %s\n",
622 (((0x1 << 0) & cmd) == 0) ? "off" : "on"); 618 (((0x1 << 0) & cmd) == 0) ? "off" : "on");
623 619
624 pci_read_config_word(dev, PCI_STATUS, &cmd); 620 pci_read_config_word(dev, PCI_STATUS, &cmd);
625 printk(KERN_DEBUG "pmc551: Devsel %s\n", 621 printk(KERN_DEBUG "pmc551: Devsel %s\n",
626 ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x000) ? "Fast" : 622 ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x000) ? "Fast" :
627 ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x200) ? "Medium" : 623 ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x200) ? "Medium" :
628 ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x400) ? "Slow" : "Invalid"); 624 ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x400) ? "Slow" : "Invalid");
629 625
630 printk(KERN_DEBUG "pmc551: %sFast Back-to-Back\n", 626 printk(KERN_DEBUG "pmc551: %sFast Back-to-Back\n",
631 ((PCI_COMMAND_FAST_BACK & cmd) == 0) ? "Not " : ""); 627 ((PCI_COMMAND_FAST_BACK & cmd) == 0) ? "Not " : "");
632 628
633 pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd); 629 pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd);
634 printk(KERN_DEBUG "pmc551: EEPROM is under %s control\n" 630 printk(KERN_DEBUG "pmc551: EEPROM is under %s control\n"
635 "pmc551: System Control Register is %slocked to PCI access\n" 631 "pmc551: System Control Register is %slocked to PCI access\n"
636 "pmc551: System Control Register is %slocked to EEPROM access\n", 632 "pmc551: System Control Register is %slocked to EEPROM access\n",
637 (bcmd & 0x1) ? "software" : "hardware", 633 (bcmd & 0x1) ? "software" : "hardware",
638 (bcmd & 0x20) ? "" : "un", (bcmd & 0x40) ? "" : "un"); 634 (bcmd & 0x20) ? "" : "un", (bcmd & 0x40) ? "" : "un");
639 #endif 635 #endif
640 return size; 636 return size;
641 } 637 }
642 638
643 /* 639 /*
644 * Kernel version specific module stuffages 640 * Kernel version specific module stuffages
645 */ 641 */
646 642
647 MODULE_LICENSE("GPL"); 643 MODULE_LICENSE("GPL");
648 MODULE_AUTHOR("Mark Ferrell <mferrell@mvista.com>"); 644 MODULE_AUTHOR("Mark Ferrell <mferrell@mvista.com>");
649 MODULE_DESCRIPTION(PMC551_VERSION); 645 MODULE_DESCRIPTION(PMC551_VERSION);
650 646
651 /* 647 /*
652 * Stuff these outside the ifdef so as to not bust compiled in driver support 648 * Stuff these outside the ifdef so as to not bust compiled in driver support
653 */ 649 */
654 static int msize = 0; 650 static int msize = 0;
655 static int asize = 0; 651 static int asize = 0;
656 652
657 module_param(msize, int, 0); 653 module_param(msize, int, 0);
658 MODULE_PARM_DESC(msize, "memory size in MiB [1 - 1024]"); 654 MODULE_PARM_DESC(msize, "memory size in MiB [1 - 1024]");
659 module_param(asize, int, 0); 655 module_param(asize, int, 0);
660 MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1-1024]"); 656 MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1-1024]");
661 657
662 /* 658 /*
663 * PMC551 Card Initialization 659 * PMC551 Card Initialization
664 */ 660 */
665 static int __init init_pmc551(void) 661 static int __init init_pmc551(void)
666 { 662 {
667 struct pci_dev *PCI_Device = NULL; 663 struct pci_dev *PCI_Device = NULL;
668 struct mypriv *priv; 664 struct mypriv *priv;
669 int found = 0; 665 int found = 0;
670 struct mtd_info *mtd; 666 struct mtd_info *mtd;
671 int length = 0; 667 int length = 0;
672 668
673 if (msize) { 669 if (msize) {
674 msize = (1 << (ffs(msize) - 1)) << 20; 670 msize = (1 << (ffs(msize) - 1)) << 20;
675 if (msize > (1 << 30)) { 671 if (msize > (1 << 30)) {
676 printk(KERN_NOTICE "pmc551: Invalid memory size [%d]\n", 672 printk(KERN_NOTICE "pmc551: Invalid memory size [%d]\n",
677 msize); 673 msize);
678 return -EINVAL; 674 return -EINVAL;
679 } 675 }
680 } 676 }
681 677
682 if (asize) { 678 if (asize) {
683 asize = (1 << (ffs(asize) - 1)) << 20; 679 asize = (1 << (ffs(asize) - 1)) << 20;
684 if (asize > (1 << 30)) { 680 if (asize > (1 << 30)) {
685 printk(KERN_NOTICE "pmc551: Invalid aperture size " 681 printk(KERN_NOTICE "pmc551: Invalid aperture size "
686 "[%d]\n", asize); 682 "[%d]\n", asize);
687 return -EINVAL; 683 return -EINVAL;
688 } 684 }
689 } 685 }
690 686
691 printk(KERN_INFO PMC551_VERSION); 687 printk(KERN_INFO PMC551_VERSION);
692 688
693 /* 689 /*
694 * PCU-bus chipset probe. 690 * PCU-bus chipset probe.
695 */ 691 */
696 for (;;) { 692 for (;;) {
697 693
698 if ((PCI_Device = pci_get_device(PCI_VENDOR_ID_V3_SEMI, 694 if ((PCI_Device = pci_get_device(PCI_VENDOR_ID_V3_SEMI,
699 PCI_DEVICE_ID_V3_SEMI_V370PDC, 695 PCI_DEVICE_ID_V3_SEMI_V370PDC,
700 PCI_Device)) == NULL) { 696 PCI_Device)) == NULL) {
701 break; 697 break;
702 } 698 }
703 699
704 printk(KERN_NOTICE "pmc551: Found PCI V370PDC at 0x%llx\n", 700 printk(KERN_NOTICE "pmc551: Found PCI V370PDC at 0x%llx\n",
705 (unsigned long long)pci_resource_start(PCI_Device, 0)); 701 (unsigned long long)pci_resource_start(PCI_Device, 0));
706 702
707 /* 703 /*
708 * The PMC551 device acts VERY weird if you don't init it 704 * The PMC551 device acts VERY weird if you don't init it
709 * first. i.e. it will not correctly report devsel. If for 705 * first. i.e. it will not correctly report devsel. If for
710 * some reason the sdram is in a wrote-protected state the 706 * some reason the sdram is in a wrote-protected state the
711 * device will DEVSEL when it is written to causing problems 707 * device will DEVSEL when it is written to causing problems
712 * with the oldproc.c driver in 708 * with the oldproc.c driver in
713 * some kernels (2.2.*) 709 * some kernels (2.2.*)
714 */ 710 */
715 if ((length = fixup_pmc551(PCI_Device)) <= 0) { 711 if ((length = fixup_pmc551(PCI_Device)) <= 0) {
716 printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n"); 712 printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n");
717 break; 713 break;
718 } 714 }
719 715
720 /* 716 /*
721 * This is needed until the driver is capable of reading the 717 * This is needed until the driver is capable of reading the
722 * onboard I2C SROM to discover the "real" memory size. 718 * onboard I2C SROM to discover the "real" memory size.
723 */ 719 */
724 if (msize) { 720 if (msize) {
725 length = msize; 721 length = msize;
726 printk(KERN_NOTICE "pmc551: Using specified memory " 722 printk(KERN_NOTICE "pmc551: Using specified memory "
727 "size 0x%x\n", length); 723 "size 0x%x\n", length);
728 } else { 724 } else {
729 msize = length; 725 msize = length;
730 } 726 }
731 727
732 mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); 728 mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
733 if (!mtd) { 729 if (!mtd) {
734 printk(KERN_NOTICE "pmc551: Cannot allocate new MTD " 730 printk(KERN_NOTICE "pmc551: Cannot allocate new MTD "
735 "device.\n"); 731 "device.\n");
736 break; 732 break;
737 } 733 }
738 734
739 priv = kzalloc(sizeof(struct mypriv), GFP_KERNEL); 735 priv = kzalloc(sizeof(struct mypriv), GFP_KERNEL);
740 if (!priv) { 736 if (!priv) {
741 printk(KERN_NOTICE "pmc551: Cannot allocate new MTD " 737 printk(KERN_NOTICE "pmc551: Cannot allocate new MTD "
742 "device.\n"); 738 "device.\n");
743 kfree(mtd); 739 kfree(mtd);
744 break; 740 break;
745 } 741 }
746 mtd->priv = priv; 742 mtd->priv = priv;
747 priv->dev = PCI_Device; 743 priv->dev = PCI_Device;
748 744
749 if (asize > length) { 745 if (asize > length) {
750 printk(KERN_NOTICE "pmc551: reducing aperture size to " 746 printk(KERN_NOTICE "pmc551: reducing aperture size to "
751 "fit %dM\n", length >> 20); 747 "fit %dM\n", length >> 20);
752 priv->asize = asize = length; 748 priv->asize = asize = length;
753 } else if (asize == 0 || asize == length) { 749 } else if (asize == 0 || asize == length) {
754 printk(KERN_NOTICE "pmc551: Using existing aperture " 750 printk(KERN_NOTICE "pmc551: Using existing aperture "
755 "size %dM\n", length >> 20); 751 "size %dM\n", length >> 20);
756 priv->asize = asize = length; 752 priv->asize = asize = length;
757 } else { 753 } else {
758 printk(KERN_NOTICE "pmc551: Using specified aperture " 754 printk(KERN_NOTICE "pmc551: Using specified aperture "
759 "size %dM\n", asize >> 20); 755 "size %dM\n", asize >> 20);
760 priv->asize = asize; 756 priv->asize = asize;
761 } 757 }
762 priv->start = pci_iomap(PCI_Device, 0, priv->asize); 758 priv->start = pci_iomap(PCI_Device, 0, priv->asize);
763 759
764 if (!priv->start) { 760 if (!priv->start) {
765 printk(KERN_NOTICE "pmc551: Unable to map IO space\n"); 761 printk(KERN_NOTICE "pmc551: Unable to map IO space\n");
766 kfree(mtd->priv); 762 kfree(mtd->priv);
767 kfree(mtd); 763 kfree(mtd);
768 break; 764 break;
769 } 765 }
770 #ifdef CONFIG_MTD_PMC551_DEBUG 766 #ifdef CONFIG_MTD_PMC551_DEBUG
771 printk(KERN_DEBUG "pmc551: setting aperture to %d\n", 767 printk(KERN_DEBUG "pmc551: setting aperture to %d\n",
772 ffs(priv->asize >> 20) - 1); 768 ffs(priv->asize >> 20) - 1);
773 #endif 769 #endif
774 770
775 priv->base_map0 = (PMC551_PCI_MEM_MAP_REG_EN 771 priv->base_map0 = (PMC551_PCI_MEM_MAP_REG_EN
776 | PMC551_PCI_MEM_MAP_ENABLE 772 | PMC551_PCI_MEM_MAP_ENABLE
777 | (ffs(priv->asize >> 20) - 1) << 4); 773 | (ffs(priv->asize >> 20) - 1) << 4);
778 priv->curr_map0 = priv->base_map0; 774 priv->curr_map0 = priv->base_map0;
779 pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0, 775 pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0,
780 priv->curr_map0); 776 priv->curr_map0);
781 777
782 #ifdef CONFIG_MTD_PMC551_DEBUG 778 #ifdef CONFIG_MTD_PMC551_DEBUG
783 printk(KERN_DEBUG "pmc551: aperture set to %d\n", 779 printk(KERN_DEBUG "pmc551: aperture set to %d\n",
784 (priv->base_map0 & 0xF0) >> 4); 780 (priv->base_map0 & 0xF0) >> 4);
785 #endif 781 #endif
786 782
787 mtd->size = msize; 783 mtd->size = msize;
788 mtd->flags = MTD_CAP_RAM; 784 mtd->flags = MTD_CAP_RAM;
789 mtd->_erase = pmc551_erase; 785 mtd->_erase = pmc551_erase;
790 mtd->_read = pmc551_read; 786 mtd->_read = pmc551_read;
791 mtd->_write = pmc551_write; 787 mtd->_write = pmc551_write;
792 mtd->_point = pmc551_point; 788 mtd->_point = pmc551_point;
793 mtd->_unpoint = pmc551_unpoint; 789 mtd->_unpoint = pmc551_unpoint;
794 mtd->type = MTD_RAM; 790 mtd->type = MTD_RAM;
795 mtd->name = "PMC551 RAM board"; 791 mtd->name = "PMC551 RAM board";
796 mtd->erasesize = 0x10000; 792 mtd->erasesize = 0x10000;
797 mtd->writesize = 1; 793 mtd->writesize = 1;
798 mtd->owner = THIS_MODULE; 794 mtd->owner = THIS_MODULE;
799 795
800 if (mtd_device_register(mtd, NULL, 0)) { 796 if (mtd_device_register(mtd, NULL, 0)) {
801 printk(KERN_NOTICE "pmc551: Failed to register new device\n"); 797 printk(KERN_NOTICE "pmc551: Failed to register new device\n");
802 pci_iounmap(PCI_Device, priv->start); 798 pci_iounmap(PCI_Device, priv->start);
803 kfree(mtd->priv); 799 kfree(mtd->priv);
804 kfree(mtd); 800 kfree(mtd);
805 break; 801 break;
806 } 802 }
807 803
808 /* Keep a reference as the mtd_device_register worked */ 804 /* Keep a reference as the mtd_device_register worked */
809 pci_dev_get(PCI_Device); 805 pci_dev_get(PCI_Device);
810 806
811 printk(KERN_NOTICE "Registered pmc551 memory device.\n"); 807 printk(KERN_NOTICE "Registered pmc551 memory device.\n");
812 printk(KERN_NOTICE "Mapped %dMiB of memory from 0x%p to 0x%p\n", 808 printk(KERN_NOTICE "Mapped %dMiB of memory from 0x%p to 0x%p\n",
813 priv->asize >> 20, 809 priv->asize >> 20,
814 priv->start, priv->start + priv->asize); 810 priv->start, priv->start + priv->asize);
815 printk(KERN_NOTICE "Total memory is %d%sB\n", 811 printk(KERN_NOTICE "Total memory is %d%sB\n",
816 (length < 1024) ? length : 812 (length < 1024) ? length :
817 (length < 1048576) ? length >> 10 : length >> 20, 813 (length < 1048576) ? length >> 10 : length >> 20,
818 (length < 1024) ? "" : (length < 1048576) ? "Ki" : "Mi"); 814 (length < 1024) ? "" : (length < 1048576) ? "Ki" : "Mi");
819 priv->nextpmc551 = pmc551list; 815 priv->nextpmc551 = pmc551list;
820 pmc551list = mtd; 816 pmc551list = mtd;
821 found++; 817 found++;
822 } 818 }
823 819
824 /* Exited early, reference left over */ 820 /* Exited early, reference left over */
825 if (PCI_Device) 821 if (PCI_Device)
826 pci_dev_put(PCI_Device); 822 pci_dev_put(PCI_Device);
827 823
828 if (!pmc551list) { 824 if (!pmc551list) {
829 printk(KERN_NOTICE "pmc551: not detected\n"); 825 printk(KERN_NOTICE "pmc551: not detected\n");
830 return -ENODEV; 826 return -ENODEV;
831 } else { 827 } else {
832 printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found); 828 printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found);
833 return 0; 829 return 0;
834 } 830 }
835 } 831 }
836 832
837 /* 833 /*
838 * PMC551 Card Cleanup 834 * PMC551 Card Cleanup
839 */ 835 */
840 static void __exit cleanup_pmc551(void) 836 static void __exit cleanup_pmc551(void)
841 { 837 {
842 int found = 0; 838 int found = 0;
843 struct mtd_info *mtd; 839 struct mtd_info *mtd;
844 struct mypriv *priv; 840 struct mypriv *priv;
845 841
846 while ((mtd = pmc551list)) { 842 while ((mtd = pmc551list)) {
847 priv = mtd->priv; 843 priv = mtd->priv;
848 pmc551list = priv->nextpmc551; 844 pmc551list = priv->nextpmc551;
849 845
850 if (priv->start) { 846 if (priv->start) {
851 printk(KERN_DEBUG "pmc551: unmapping %dMiB starting at " 847 printk(KERN_DEBUG "pmc551: unmapping %dMiB starting at "
852 "0x%p\n", priv->asize >> 20, priv->start); 848 "0x%p\n", priv->asize >> 20, priv->start);
853 pci_iounmap(priv->dev, priv->start); 849 pci_iounmap(priv->dev, priv->start);
854 } 850 }
855 pci_dev_put(priv->dev); 851 pci_dev_put(priv->dev);
856 852
857 kfree(mtd->priv); 853 kfree(mtd->priv);
858 mtd_device_unregister(mtd); 854 mtd_device_unregister(mtd);
859 kfree(mtd); 855 kfree(mtd);
860 found++; 856 found++;
861 } 857 }
862 858
863 printk(KERN_NOTICE "pmc551: %d pmc551 devices unloaded\n", found); 859 printk(KERN_NOTICE "pmc551: %d pmc551 devices unloaded\n", found);
864 } 860 }
865 861
866 module_init(init_pmc551); 862 module_init(init_pmc551);
867 module_exit(cleanup_pmc551); 863 module_exit(cleanup_pmc551);
868 864
drivers/mtd/devices/slram.c
1 /*====================================================================== 1 /*======================================================================
2 2
3 This driver provides a method to access memory not used by the kernel 3 This driver provides a method to access memory not used by the kernel
4 itself (i.e. if the kernel commandline mem=xxx is used). To actually 4 itself (i.e. if the kernel commandline mem=xxx is used). To actually
5 use slram at least mtdblock or mtdchar is required (for block or 5 use slram at least mtdblock or mtdchar is required (for block or
6 character device access). 6 character device access).
7 7
8 Usage: 8 Usage:
9 9
10 if compiled as loadable module: 10 if compiled as loadable module:
11 modprobe slram map=<name>,<start>,<end/offset> 11 modprobe slram map=<name>,<start>,<end/offset>
12 if statically linked into the kernel use the following kernel cmd.line 12 if statically linked into the kernel use the following kernel cmd.line
13 slram=<name>,<start>,<end/offset> 13 slram=<name>,<start>,<end/offset>
14 14
15 <name>: name of the device that will be listed in /proc/mtd 15 <name>: name of the device that will be listed in /proc/mtd
16 <start>: start of the memory region, decimal or hex (0xabcdef) 16 <start>: start of the memory region, decimal or hex (0xabcdef)
17 <end/offset>: end of the memory region. It's possible to use +0x1234 17 <end/offset>: end of the memory region. It's possible to use +0x1234
18 to specify the offset instead of the absolute address 18 to specify the offset instead of the absolute address
19 19
20 NOTE: 20 NOTE:
21 With slram it's only possible to map a contiguous memory region. Therefore 21 With slram it's only possible to map a contiguous memory region. Therefore
22 if there's a device mapped somewhere in the region specified slram will 22 if there's a device mapped somewhere in the region specified slram will
23 fail to load (see kernel log if modprobe fails). 23 fail to load (see kernel log if modprobe fails).
24 24
25 - 25 -
26 26
27 Jochen Schaeuble <psionic@psionic.de> 27 Jochen Schaeuble <psionic@psionic.de>
28 28
29 ======================================================================*/ 29 ======================================================================*/
30 30
31 31
32 #include <linux/module.h> 32 #include <linux/module.h>
33 #include <asm/uaccess.h> 33 #include <asm/uaccess.h>
34 #include <linux/types.h> 34 #include <linux/types.h>
35 #include <linux/kernel.h> 35 #include <linux/kernel.h>
36 #include <linux/ptrace.h> 36 #include <linux/ptrace.h>
37 #include <linux/slab.h> 37 #include <linux/slab.h>
38 #include <linux/string.h> 38 #include <linux/string.h>
39 #include <linux/timer.h> 39 #include <linux/timer.h>
40 #include <linux/major.h> 40 #include <linux/major.h>
41 #include <linux/fs.h> 41 #include <linux/fs.h>
42 #include <linux/ioctl.h> 42 #include <linux/ioctl.h>
43 #include <linux/init.h> 43 #include <linux/init.h>
44 #include <asm/io.h> 44 #include <asm/io.h>
45 #include <asm/system.h> 45 #include <asm/system.h>
46 46
47 #include <linux/mtd/mtd.h> 47 #include <linux/mtd/mtd.h>
48 48
49 #define SLRAM_MAX_DEVICES_PARAMS 6 /* 3 parameters / device */ 49 #define SLRAM_MAX_DEVICES_PARAMS 6 /* 3 parameters / device */
50 #define SLRAM_BLK_SZ 0x4000 50 #define SLRAM_BLK_SZ 0x4000
51 51
52 #define T(fmt, args...) printk(KERN_DEBUG fmt, ## args) 52 #define T(fmt, args...) printk(KERN_DEBUG fmt, ## args)
53 #define E(fmt, args...) printk(KERN_NOTICE fmt, ## args) 53 #define E(fmt, args...) printk(KERN_NOTICE fmt, ## args)
54 54
55 typedef struct slram_priv { 55 typedef struct slram_priv {
56 u_char *start; 56 u_char *start;
57 u_char *end; 57 u_char *end;
58 } slram_priv_t; 58 } slram_priv_t;
59 59
60 typedef struct slram_mtd_list { 60 typedef struct slram_mtd_list {
61 struct mtd_info *mtdinfo; 61 struct mtd_info *mtdinfo;
62 struct slram_mtd_list *next; 62 struct slram_mtd_list *next;
63 } slram_mtd_list_t; 63 } slram_mtd_list_t;
64 64
65 #ifdef MODULE 65 #ifdef MODULE
66 static char *map[SLRAM_MAX_DEVICES_PARAMS]; 66 static char *map[SLRAM_MAX_DEVICES_PARAMS];
67 67
68 module_param_array(map, charp, NULL, 0); 68 module_param_array(map, charp, NULL, 0);
69 MODULE_PARM_DESC(map, "List of memory regions to map. \"map=<name>, <start>, <length / end>\""); 69 MODULE_PARM_DESC(map, "List of memory regions to map. \"map=<name>, <start>, <length / end>\"");
70 #else 70 #else
71 static char *map; 71 static char *map;
72 #endif 72 #endif
73 73
74 static slram_mtd_list_t *slram_mtdlist = NULL; 74 static slram_mtd_list_t *slram_mtdlist = NULL;
75 75
76 static int slram_erase(struct mtd_info *, struct erase_info *); 76 static int slram_erase(struct mtd_info *, struct erase_info *);
77 static int slram_point(struct mtd_info *, loff_t, size_t, size_t *, void **, 77 static int slram_point(struct mtd_info *, loff_t, size_t, size_t *, void **,
78 resource_size_t *); 78 resource_size_t *);
79 static int slram_unpoint(struct mtd_info *, loff_t, size_t); 79 static int slram_unpoint(struct mtd_info *, loff_t, size_t);
80 static int slram_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *); 80 static int slram_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *);
81 static int slram_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); 81 static int slram_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
82 82
83 static int slram_erase(struct mtd_info *mtd, struct erase_info *instr) 83 static int slram_erase(struct mtd_info *mtd, struct erase_info *instr)
84 { 84 {
85 slram_priv_t *priv = mtd->priv; 85 slram_priv_t *priv = mtd->priv;
86 86
87 memset(priv->start + instr->addr, 0xff, instr->len); 87 memset(priv->start + instr->addr, 0xff, instr->len);
88 /* This'll catch a few races. Free the thing before returning :) 88 /* This'll catch a few races. Free the thing before returning :)
89 * I don't feel at all ashamed. This kind of thing is possible anyway 89 * I don't feel at all ashamed. This kind of thing is possible anyway
90 * with flash, but unlikely. 90 * with flash, but unlikely.
91 */ 91 */
92 instr->state = MTD_ERASE_DONE; 92 instr->state = MTD_ERASE_DONE;
93 mtd_erase_callback(instr); 93 mtd_erase_callback(instr);
94 return(0); 94 return(0);
95 } 95 }
96 96
97 static int slram_point(struct mtd_info *mtd, loff_t from, size_t len, 97 static int slram_point(struct mtd_info *mtd, loff_t from, size_t len,
98 size_t *retlen, void **virt, resource_size_t *phys) 98 size_t *retlen, void **virt, resource_size_t *phys)
99 { 99 {
100 slram_priv_t *priv = mtd->priv; 100 slram_priv_t *priv = mtd->priv;
101 101
102 /* can we return a physical address with this driver? */
103 if (phys)
104 return -EINVAL;
105 *virt = priv->start + from; 102 *virt = priv->start + from;
106 *retlen = len; 103 *retlen = len;
107 return(0); 104 return(0);
108 } 105 }
109 106
110 static int slram_unpoint(struct mtd_info *mtd, loff_t from, size_t len) 107 static int slram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
111 { 108 {
112 return 0; 109 return 0;
113 } 110 }
114 111
115 static int slram_read(struct mtd_info *mtd, loff_t from, size_t len, 112 static int slram_read(struct mtd_info *mtd, loff_t from, size_t len,
116 size_t *retlen, u_char *buf) 113 size_t *retlen, u_char *buf)
117 { 114 {
118 slram_priv_t *priv = mtd->priv; 115 slram_priv_t *priv = mtd->priv;
119 116
120 memcpy(buf, priv->start + from, len); 117 memcpy(buf, priv->start + from, len);
121 *retlen = len; 118 *retlen = len;
122 return(0); 119 return(0);
123 } 120 }
124 121
125 static int slram_write(struct mtd_info *mtd, loff_t to, size_t len, 122 static int slram_write(struct mtd_info *mtd, loff_t to, size_t len,
126 size_t *retlen, const u_char *buf) 123 size_t *retlen, const u_char *buf)
127 { 124 {
128 slram_priv_t *priv = mtd->priv; 125 slram_priv_t *priv = mtd->priv;
129 126
130 memcpy(priv->start + to, buf, len); 127 memcpy(priv->start + to, buf, len);
131 *retlen = len; 128 *retlen = len;
132 return(0); 129 return(0);
133 } 130 }
134 131
135 /*====================================================================*/ 132 /*====================================================================*/
136 133
137 static int register_device(char *name, unsigned long start, unsigned long length) 134 static int register_device(char *name, unsigned long start, unsigned long length)
138 { 135 {
139 slram_mtd_list_t **curmtd; 136 slram_mtd_list_t **curmtd;
140 137
141 curmtd = &slram_mtdlist; 138 curmtd = &slram_mtdlist;
142 while (*curmtd) { 139 while (*curmtd) {
143 curmtd = &(*curmtd)->next; 140 curmtd = &(*curmtd)->next;
144 } 141 }
145 142
146 *curmtd = kmalloc(sizeof(slram_mtd_list_t), GFP_KERNEL); 143 *curmtd = kmalloc(sizeof(slram_mtd_list_t), GFP_KERNEL);
147 if (!(*curmtd)) { 144 if (!(*curmtd)) {
148 E("slram: Cannot allocate new MTD device.\n"); 145 E("slram: Cannot allocate new MTD device.\n");
149 return(-ENOMEM); 146 return(-ENOMEM);
150 } 147 }
151 (*curmtd)->mtdinfo = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); 148 (*curmtd)->mtdinfo = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
152 (*curmtd)->next = NULL; 149 (*curmtd)->next = NULL;
153 150
154 if ((*curmtd)->mtdinfo) { 151 if ((*curmtd)->mtdinfo) {
155 (*curmtd)->mtdinfo->priv = 152 (*curmtd)->mtdinfo->priv =
156 kzalloc(sizeof(slram_priv_t), GFP_KERNEL); 153 kzalloc(sizeof(slram_priv_t), GFP_KERNEL);
157 154
158 if (!(*curmtd)->mtdinfo->priv) { 155 if (!(*curmtd)->mtdinfo->priv) {
159 kfree((*curmtd)->mtdinfo); 156 kfree((*curmtd)->mtdinfo);
160 (*curmtd)->mtdinfo = NULL; 157 (*curmtd)->mtdinfo = NULL;
161 } 158 }
162 } 159 }
163 160
164 if (!(*curmtd)->mtdinfo) { 161 if (!(*curmtd)->mtdinfo) {
165 E("slram: Cannot allocate new MTD device.\n"); 162 E("slram: Cannot allocate new MTD device.\n");
166 return(-ENOMEM); 163 return(-ENOMEM);
167 } 164 }
168 165
169 if (!(((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start = 166 if (!(((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start =
170 ioremap(start, length))) { 167 ioremap(start, length))) {
171 E("slram: ioremap failed\n"); 168 E("slram: ioremap failed\n");
172 return -EIO; 169 return -EIO;
173 } 170 }
174 ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->end = 171 ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->end =
175 ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start + length; 172 ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start + length;
176 173
177 174
178 (*curmtd)->mtdinfo->name = name; 175 (*curmtd)->mtdinfo->name = name;
179 (*curmtd)->mtdinfo->size = length; 176 (*curmtd)->mtdinfo->size = length;
180 (*curmtd)->mtdinfo->flags = MTD_CAP_RAM; 177 (*curmtd)->mtdinfo->flags = MTD_CAP_RAM;
181 (*curmtd)->mtdinfo->_erase = slram_erase; 178 (*curmtd)->mtdinfo->_erase = slram_erase;
182 (*curmtd)->mtdinfo->_point = slram_point; 179 (*curmtd)->mtdinfo->_point = slram_point;
183 (*curmtd)->mtdinfo->_unpoint = slram_unpoint; 180 (*curmtd)->mtdinfo->_unpoint = slram_unpoint;
184 (*curmtd)->mtdinfo->_read = slram_read; 181 (*curmtd)->mtdinfo->_read = slram_read;
185 (*curmtd)->mtdinfo->_write = slram_write; 182 (*curmtd)->mtdinfo->_write = slram_write;
186 (*curmtd)->mtdinfo->owner = THIS_MODULE; 183 (*curmtd)->mtdinfo->owner = THIS_MODULE;
187 (*curmtd)->mtdinfo->type = MTD_RAM; 184 (*curmtd)->mtdinfo->type = MTD_RAM;
188 (*curmtd)->mtdinfo->erasesize = SLRAM_BLK_SZ; 185 (*curmtd)->mtdinfo->erasesize = SLRAM_BLK_SZ;
189 (*curmtd)->mtdinfo->writesize = 1; 186 (*curmtd)->mtdinfo->writesize = 1;
190 187
191 if (mtd_device_register((*curmtd)->mtdinfo, NULL, 0)) { 188 if (mtd_device_register((*curmtd)->mtdinfo, NULL, 0)) {
192 E("slram: Failed to register new device\n"); 189 E("slram: Failed to register new device\n");
193 iounmap(((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start); 190 iounmap(((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start);
194 kfree((*curmtd)->mtdinfo->priv); 191 kfree((*curmtd)->mtdinfo->priv);
195 kfree((*curmtd)->mtdinfo); 192 kfree((*curmtd)->mtdinfo);
196 return(-EAGAIN); 193 return(-EAGAIN);
197 } 194 }
198 T("slram: Registered device %s from %luKiB to %luKiB\n", name, 195 T("slram: Registered device %s from %luKiB to %luKiB\n", name,
199 (start / 1024), ((start + length) / 1024)); 196 (start / 1024), ((start + length) / 1024));
200 T("slram: Mapped from 0x%p to 0x%p\n", 197 T("slram: Mapped from 0x%p to 0x%p\n",
201 ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start, 198 ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start,
202 ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->end); 199 ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->end);
203 return(0); 200 return(0);
204 } 201 }
205 202
206 static void unregister_devices(void) 203 static void unregister_devices(void)
207 { 204 {
208 slram_mtd_list_t *nextitem; 205 slram_mtd_list_t *nextitem;
209 206
210 while (slram_mtdlist) { 207 while (slram_mtdlist) {
211 nextitem = slram_mtdlist->next; 208 nextitem = slram_mtdlist->next;
212 mtd_device_unregister(slram_mtdlist->mtdinfo); 209 mtd_device_unregister(slram_mtdlist->mtdinfo);
213 iounmap(((slram_priv_t *)slram_mtdlist->mtdinfo->priv)->start); 210 iounmap(((slram_priv_t *)slram_mtdlist->mtdinfo->priv)->start);
214 kfree(slram_mtdlist->mtdinfo->priv); 211 kfree(slram_mtdlist->mtdinfo->priv);
215 kfree(slram_mtdlist->mtdinfo); 212 kfree(slram_mtdlist->mtdinfo);
216 kfree(slram_mtdlist); 213 kfree(slram_mtdlist);
217 slram_mtdlist = nextitem; 214 slram_mtdlist = nextitem;
218 } 215 }
219 } 216 }
220 217
221 static unsigned long handle_unit(unsigned long value, char *unit) 218 static unsigned long handle_unit(unsigned long value, char *unit)
222 { 219 {
223 if ((*unit == 'M') || (*unit == 'm')) { 220 if ((*unit == 'M') || (*unit == 'm')) {
224 return(value * 1024 * 1024); 221 return(value * 1024 * 1024);
225 } else if ((*unit == 'K') || (*unit == 'k')) { 222 } else if ((*unit == 'K') || (*unit == 'k')) {
226 return(value * 1024); 223 return(value * 1024);
227 } 224 }
228 return(value); 225 return(value);
229 } 226 }
230 227
231 static int parse_cmdline(char *devname, char *szstart, char *szlength) 228 static int parse_cmdline(char *devname, char *szstart, char *szlength)
232 { 229 {
233 char *buffer; 230 char *buffer;
234 unsigned long devstart; 231 unsigned long devstart;
235 unsigned long devlength; 232 unsigned long devlength;
236 233
237 if ((!devname) || (!szstart) || (!szlength)) { 234 if ((!devname) || (!szstart) || (!szlength)) {
238 unregister_devices(); 235 unregister_devices();
239 return(-EINVAL); 236 return(-EINVAL);
240 } 237 }
241 238
242 devstart = simple_strtoul(szstart, &buffer, 0); 239 devstart = simple_strtoul(szstart, &buffer, 0);
243 devstart = handle_unit(devstart, buffer); 240 devstart = handle_unit(devstart, buffer);
244 241
245 if (*(szlength) != '+') { 242 if (*(szlength) != '+') {
246 devlength = simple_strtoul(szlength, &buffer, 0); 243 devlength = simple_strtoul(szlength, &buffer, 0);
247 devlength = handle_unit(devlength, buffer) - devstart; 244 devlength = handle_unit(devlength, buffer) - devstart;
248 if (devlength < devstart) 245 if (devlength < devstart)
249 goto err_out; 246 goto err_out;
250 247
251 devlength -= devstart; 248 devlength -= devstart;
252 } else { 249 } else {
253 devlength = simple_strtoul(szlength + 1, &buffer, 0); 250 devlength = simple_strtoul(szlength + 1, &buffer, 0);
254 devlength = handle_unit(devlength, buffer); 251 devlength = handle_unit(devlength, buffer);
255 } 252 }
256 T("slram: devname=%s, devstart=0x%lx, devlength=0x%lx\n", 253 T("slram: devname=%s, devstart=0x%lx, devlength=0x%lx\n",
257 devname, devstart, devlength); 254 devname, devstart, devlength);
258 if (devlength % SLRAM_BLK_SZ != 0) 255 if (devlength % SLRAM_BLK_SZ != 0)
259 goto err_out; 256 goto err_out;
260 257
261 if ((devstart = register_device(devname, devstart, devlength))){ 258 if ((devstart = register_device(devname, devstart, devlength))){
262 unregister_devices(); 259 unregister_devices();
263 return((int)devstart); 260 return((int)devstart);
264 } 261 }
265 return(0); 262 return(0);
266 263
267 err_out: 264 err_out:
268 E("slram: Illegal length parameter.\n"); 265 E("slram: Illegal length parameter.\n");
269 return(-EINVAL); 266 return(-EINVAL);
270 } 267 }
271 268
272 #ifndef MODULE 269 #ifndef MODULE
273 270
274 static int __init mtd_slram_setup(char *str) 271 static int __init mtd_slram_setup(char *str)
275 { 272 {
276 map = str; 273 map = str;
277 return(1); 274 return(1);
278 } 275 }
279 276
280 __setup("slram=", mtd_slram_setup); 277 __setup("slram=", mtd_slram_setup);
281 278
282 #endif 279 #endif
283 280
284 static int __init init_slram(void) 281 static int __init init_slram(void)
285 { 282 {
286 char *devname; 283 char *devname;
287 int i; 284 int i;
288 285
289 #ifndef MODULE 286 #ifndef MODULE
290 char *devstart; 287 char *devstart;
291 char *devlength; 288 char *devlength;
292 289
293 i = 0; 290 i = 0;
294 291
295 if (!map) { 292 if (!map) {
296 E("slram: not enough parameters.\n"); 293 E("slram: not enough parameters.\n");
297 return(-EINVAL); 294 return(-EINVAL);
298 } 295 }
299 while (map) { 296 while (map) {
300 devname = devstart = devlength = NULL; 297 devname = devstart = devlength = NULL;
301 298
302 if (!(devname = strsep(&map, ","))) { 299 if (!(devname = strsep(&map, ","))) {
303 E("slram: No devicename specified.\n"); 300 E("slram: No devicename specified.\n");
304 break; 301 break;
305 } 302 }
306 T("slram: devname = %s\n", devname); 303 T("slram: devname = %s\n", devname);
307 if ((!map) || (!(devstart = strsep(&map, ",")))) { 304 if ((!map) || (!(devstart = strsep(&map, ",")))) {
308 E("slram: No devicestart specified.\n"); 305 E("slram: No devicestart specified.\n");
309 } 306 }
310 T("slram: devstart = %s\n", devstart); 307 T("slram: devstart = %s\n", devstart);
311 if ((!map) || (!(devlength = strsep(&map, ",")))) { 308 if ((!map) || (!(devlength = strsep(&map, ",")))) {
312 E("slram: No devicelength / -end specified.\n"); 309 E("slram: No devicelength / -end specified.\n");
313 } 310 }
314 T("slram: devlength = %s\n", devlength); 311 T("slram: devlength = %s\n", devlength);
315 if (parse_cmdline(devname, devstart, devlength) != 0) { 312 if (parse_cmdline(devname, devstart, devlength) != 0) {
316 return(-EINVAL); 313 return(-EINVAL);
317 } 314 }
318 } 315 }
319 #else 316 #else
320 int count; 317 int count;
321 318
322 for (count = 0; count < SLRAM_MAX_DEVICES_PARAMS && map[count]; 319 for (count = 0; count < SLRAM_MAX_DEVICES_PARAMS && map[count];
323 count++) { 320 count++) {
324 } 321 }
325 322
326 if ((count % 3 != 0) || (count == 0)) { 323 if ((count % 3 != 0) || (count == 0)) {
327 E("slram: not enough parameters.\n"); 324 E("slram: not enough parameters.\n");
328 return(-EINVAL); 325 return(-EINVAL);
329 } 326 }
330 for (i = 0; i < (count / 3); i++) { 327 for (i = 0; i < (count / 3); i++) {
331 devname = map[i * 3]; 328 devname = map[i * 3];
332 329
333 if (parse_cmdline(devname, map[i * 3 + 1], map[i * 3 + 2])!=0) { 330 if (parse_cmdline(devname, map[i * 3 + 1], map[i * 3 + 2])!=0) {
334 return(-EINVAL); 331 return(-EINVAL);
335 } 332 }
336 333
337 } 334 }
338 #endif /* !MODULE */ 335 #endif /* !MODULE */
339 336
340 return(0); 337 return(0);
341 } 338 }
342 339
343 static void __exit cleanup_slram(void) 340 static void __exit cleanup_slram(void)
344 { 341 {
345 unregister_devices(); 342 unregister_devices();
346 } 343 }
347 344
348 module_init(init_slram); 345 module_init(init_slram);
349 module_exit(cleanup_slram); 346 module_exit(cleanup_slram);
350 347
351 MODULE_LICENSE("GPL"); 348 MODULE_LICENSE("GPL");
352 MODULE_AUTHOR("Jochen Schaeuble <psionic@psionic.de>"); 349 MODULE_AUTHOR("Jochen Schaeuble <psionic@psionic.de>");
353 MODULE_DESCRIPTION("MTD driver for uncached system RAM"); 350 MODULE_DESCRIPTION("MTD driver for uncached system RAM");
354 351
drivers/mtd/mtdcore.c
1 /* 1 /*
2 * Core registration and callback routines for MTD 2 * Core registration and callback routines for MTD
3 * drivers and users. 3 * drivers and users.
4 * 4 *
5 * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> 5 * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>
6 * Copyright © 2006 Red Hat UK Limited 6 * Copyright © 2006 Red Hat UK Limited
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or 10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version. 11 * (at your option) any later version.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 * 21 *
22 */ 22 */
23 23
24 #include <linux/module.h> 24 #include <linux/module.h>
25 #include <linux/kernel.h> 25 #include <linux/kernel.h>
26 #include <linux/ptrace.h> 26 #include <linux/ptrace.h>
27 #include <linux/seq_file.h> 27 #include <linux/seq_file.h>
28 #include <linux/string.h> 28 #include <linux/string.h>
29 #include <linux/timer.h> 29 #include <linux/timer.h>
30 #include <linux/major.h> 30 #include <linux/major.h>
31 #include <linux/fs.h> 31 #include <linux/fs.h>
32 #include <linux/err.h> 32 #include <linux/err.h>
33 #include <linux/ioctl.h> 33 #include <linux/ioctl.h>
34 #include <linux/init.h> 34 #include <linux/init.h>
35 #include <linux/proc_fs.h> 35 #include <linux/proc_fs.h>
36 #include <linux/idr.h> 36 #include <linux/idr.h>
37 #include <linux/backing-dev.h> 37 #include <linux/backing-dev.h>
38 #include <linux/gfp.h> 38 #include <linux/gfp.h>
39 39
40 #include <linux/mtd/mtd.h> 40 #include <linux/mtd/mtd.h>
41 #include <linux/mtd/partitions.h> 41 #include <linux/mtd/partitions.h>
42 42
43 #include "mtdcore.h" 43 #include "mtdcore.h"
44 /* 44 /*
45 * backing device capabilities for non-mappable devices (such as NAND flash) 45 * backing device capabilities for non-mappable devices (such as NAND flash)
46 * - permits private mappings, copies are taken of the data 46 * - permits private mappings, copies are taken of the data
47 */ 47 */
48 static struct backing_dev_info mtd_bdi_unmappable = { 48 static struct backing_dev_info mtd_bdi_unmappable = {
49 .capabilities = BDI_CAP_MAP_COPY, 49 .capabilities = BDI_CAP_MAP_COPY,
50 }; 50 };
51 51
52 /* 52 /*
53 * backing device capabilities for R/O mappable devices (such as ROM) 53 * backing device capabilities for R/O mappable devices (such as ROM)
54 * - permits private mappings, copies are taken of the data 54 * - permits private mappings, copies are taken of the data
55 * - permits non-writable shared mappings 55 * - permits non-writable shared mappings
56 */ 56 */
57 static struct backing_dev_info mtd_bdi_ro_mappable = { 57 static struct backing_dev_info mtd_bdi_ro_mappable = {
58 .capabilities = (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT | 58 .capabilities = (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT |
59 BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP), 59 BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP),
60 }; 60 };
61 61
62 /* 62 /*
63 * backing device capabilities for writable mappable devices (such as RAM) 63 * backing device capabilities for writable mappable devices (such as RAM)
64 * - permits private mappings, copies are taken of the data 64 * - permits private mappings, copies are taken of the data
65 * - permits non-writable shared mappings 65 * - permits non-writable shared mappings
66 */ 66 */
67 static struct backing_dev_info mtd_bdi_rw_mappable = { 67 static struct backing_dev_info mtd_bdi_rw_mappable = {
68 .capabilities = (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT | 68 .capabilities = (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT |
69 BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP | 69 BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP |
70 BDI_CAP_WRITE_MAP), 70 BDI_CAP_WRITE_MAP),
71 }; 71 };
72 72
73 static int mtd_cls_suspend(struct device *dev, pm_message_t state); 73 static int mtd_cls_suspend(struct device *dev, pm_message_t state);
74 static int mtd_cls_resume(struct device *dev); 74 static int mtd_cls_resume(struct device *dev);
75 75
76 static struct class mtd_class = { 76 static struct class mtd_class = {
77 .name = "mtd", 77 .name = "mtd",
78 .owner = THIS_MODULE, 78 .owner = THIS_MODULE,
79 .suspend = mtd_cls_suspend, 79 .suspend = mtd_cls_suspend,
80 .resume = mtd_cls_resume, 80 .resume = mtd_cls_resume,
81 }; 81 };
82 82
83 static DEFINE_IDR(mtd_idr); 83 static DEFINE_IDR(mtd_idr);
84 84
85 /* These are exported solely for the purpose of mtd_blkdevs.c. You 85 /* These are exported solely for the purpose of mtd_blkdevs.c. You
86 should not use them for _anything_ else */ 86 should not use them for _anything_ else */
87 DEFINE_MUTEX(mtd_table_mutex); 87 DEFINE_MUTEX(mtd_table_mutex);
88 EXPORT_SYMBOL_GPL(mtd_table_mutex); 88 EXPORT_SYMBOL_GPL(mtd_table_mutex);
89 89
90 struct mtd_info *__mtd_next_device(int i) 90 struct mtd_info *__mtd_next_device(int i)
91 { 91 {
92 return idr_get_next(&mtd_idr, &i); 92 return idr_get_next(&mtd_idr, &i);
93 } 93 }
94 EXPORT_SYMBOL_GPL(__mtd_next_device); 94 EXPORT_SYMBOL_GPL(__mtd_next_device);
95 95
96 static LIST_HEAD(mtd_notifiers); 96 static LIST_HEAD(mtd_notifiers);
97 97
98 98
99 #if defined(CONFIG_MTD_CHAR) || defined(CONFIG_MTD_CHAR_MODULE) 99 #if defined(CONFIG_MTD_CHAR) || defined(CONFIG_MTD_CHAR_MODULE)
100 #define MTD_DEVT(index) MKDEV(MTD_CHAR_MAJOR, (index)*2) 100 #define MTD_DEVT(index) MKDEV(MTD_CHAR_MAJOR, (index)*2)
101 #else 101 #else
102 #define MTD_DEVT(index) 0 102 #define MTD_DEVT(index) 0
103 #endif 103 #endif
104 104
105 /* REVISIT once MTD uses the driver model better, whoever allocates 105 /* REVISIT once MTD uses the driver model better, whoever allocates
106 * the mtd_info will probably want to use the release() hook... 106 * the mtd_info will probably want to use the release() hook...
107 */ 107 */
108 static void mtd_release(struct device *dev) 108 static void mtd_release(struct device *dev)
109 { 109 {
110 struct mtd_info __maybe_unused *mtd = dev_get_drvdata(dev); 110 struct mtd_info __maybe_unused *mtd = dev_get_drvdata(dev);
111 dev_t index = MTD_DEVT(mtd->index); 111 dev_t index = MTD_DEVT(mtd->index);
112 112
113 /* remove /dev/mtdXro node if needed */ 113 /* remove /dev/mtdXro node if needed */
114 if (index) 114 if (index)
115 device_destroy(&mtd_class, index + 1); 115 device_destroy(&mtd_class, index + 1);
116 } 116 }
117 117
118 static int mtd_cls_suspend(struct device *dev, pm_message_t state) 118 static int mtd_cls_suspend(struct device *dev, pm_message_t state)
119 { 119 {
120 struct mtd_info *mtd = dev_get_drvdata(dev); 120 struct mtd_info *mtd = dev_get_drvdata(dev);
121 121
122 return mtd ? mtd_suspend(mtd) : 0; 122 return mtd ? mtd_suspend(mtd) : 0;
123 } 123 }
124 124
125 static int mtd_cls_resume(struct device *dev) 125 static int mtd_cls_resume(struct device *dev)
126 { 126 {
127 struct mtd_info *mtd = dev_get_drvdata(dev); 127 struct mtd_info *mtd = dev_get_drvdata(dev);
128 128
129 if (mtd) 129 if (mtd)
130 mtd_resume(mtd); 130 mtd_resume(mtd);
131 return 0; 131 return 0;
132 } 132 }
133 133
134 static ssize_t mtd_type_show(struct device *dev, 134 static ssize_t mtd_type_show(struct device *dev,
135 struct device_attribute *attr, char *buf) 135 struct device_attribute *attr, char *buf)
136 { 136 {
137 struct mtd_info *mtd = dev_get_drvdata(dev); 137 struct mtd_info *mtd = dev_get_drvdata(dev);
138 char *type; 138 char *type;
139 139
140 switch (mtd->type) { 140 switch (mtd->type) {
141 case MTD_ABSENT: 141 case MTD_ABSENT:
142 type = "absent"; 142 type = "absent";
143 break; 143 break;
144 case MTD_RAM: 144 case MTD_RAM:
145 type = "ram"; 145 type = "ram";
146 break; 146 break;
147 case MTD_ROM: 147 case MTD_ROM:
148 type = "rom"; 148 type = "rom";
149 break; 149 break;
150 case MTD_NORFLASH: 150 case MTD_NORFLASH:
151 type = "nor"; 151 type = "nor";
152 break; 152 break;
153 case MTD_NANDFLASH: 153 case MTD_NANDFLASH:
154 type = "nand"; 154 type = "nand";
155 break; 155 break;
156 case MTD_DATAFLASH: 156 case MTD_DATAFLASH:
157 type = "dataflash"; 157 type = "dataflash";
158 break; 158 break;
159 case MTD_UBIVOLUME: 159 case MTD_UBIVOLUME:
160 type = "ubi"; 160 type = "ubi";
161 break; 161 break;
162 default: 162 default:
163 type = "unknown"; 163 type = "unknown";
164 } 164 }
165 165
166 return snprintf(buf, PAGE_SIZE, "%s\n", type); 166 return snprintf(buf, PAGE_SIZE, "%s\n", type);
167 } 167 }
168 static DEVICE_ATTR(type, S_IRUGO, mtd_type_show, NULL); 168 static DEVICE_ATTR(type, S_IRUGO, mtd_type_show, NULL);
169 169
170 static ssize_t mtd_flags_show(struct device *dev, 170 static ssize_t mtd_flags_show(struct device *dev,
171 struct device_attribute *attr, char *buf) 171 struct device_attribute *attr, char *buf)
172 { 172 {
173 struct mtd_info *mtd = dev_get_drvdata(dev); 173 struct mtd_info *mtd = dev_get_drvdata(dev);
174 174
175 return snprintf(buf, PAGE_SIZE, "0x%lx\n", (unsigned long)mtd->flags); 175 return snprintf(buf, PAGE_SIZE, "0x%lx\n", (unsigned long)mtd->flags);
176 176
177 } 177 }
178 static DEVICE_ATTR(flags, S_IRUGO, mtd_flags_show, NULL); 178 static DEVICE_ATTR(flags, S_IRUGO, mtd_flags_show, NULL);
179 179
180 static ssize_t mtd_size_show(struct device *dev, 180 static ssize_t mtd_size_show(struct device *dev,
181 struct device_attribute *attr, char *buf) 181 struct device_attribute *attr, char *buf)
182 { 182 {
183 struct mtd_info *mtd = dev_get_drvdata(dev); 183 struct mtd_info *mtd = dev_get_drvdata(dev);
184 184
185 return snprintf(buf, PAGE_SIZE, "%llu\n", 185 return snprintf(buf, PAGE_SIZE, "%llu\n",
186 (unsigned long long)mtd->size); 186 (unsigned long long)mtd->size);
187 187
188 } 188 }
189 static DEVICE_ATTR(size, S_IRUGO, mtd_size_show, NULL); 189 static DEVICE_ATTR(size, S_IRUGO, mtd_size_show, NULL);
190 190
191 static ssize_t mtd_erasesize_show(struct device *dev, 191 static ssize_t mtd_erasesize_show(struct device *dev,
192 struct device_attribute *attr, char *buf) 192 struct device_attribute *attr, char *buf)
193 { 193 {
194 struct mtd_info *mtd = dev_get_drvdata(dev); 194 struct mtd_info *mtd = dev_get_drvdata(dev);
195 195
196 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->erasesize); 196 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->erasesize);
197 197
198 } 198 }
199 static DEVICE_ATTR(erasesize, S_IRUGO, mtd_erasesize_show, NULL); 199 static DEVICE_ATTR(erasesize, S_IRUGO, mtd_erasesize_show, NULL);
200 200
201 static ssize_t mtd_writesize_show(struct device *dev, 201 static ssize_t mtd_writesize_show(struct device *dev,
202 struct device_attribute *attr, char *buf) 202 struct device_attribute *attr, char *buf)
203 { 203 {
204 struct mtd_info *mtd = dev_get_drvdata(dev); 204 struct mtd_info *mtd = dev_get_drvdata(dev);
205 205
206 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->writesize); 206 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->writesize);
207 207
208 } 208 }
209 static DEVICE_ATTR(writesize, S_IRUGO, mtd_writesize_show, NULL); 209 static DEVICE_ATTR(writesize, S_IRUGO, mtd_writesize_show, NULL);
210 210
211 static ssize_t mtd_subpagesize_show(struct device *dev, 211 static ssize_t mtd_subpagesize_show(struct device *dev,
212 struct device_attribute *attr, char *buf) 212 struct device_attribute *attr, char *buf)
213 { 213 {
214 struct mtd_info *mtd = dev_get_drvdata(dev); 214 struct mtd_info *mtd = dev_get_drvdata(dev);
215 unsigned int subpagesize = mtd->writesize >> mtd->subpage_sft; 215 unsigned int subpagesize = mtd->writesize >> mtd->subpage_sft;
216 216
217 return snprintf(buf, PAGE_SIZE, "%u\n", subpagesize); 217 return snprintf(buf, PAGE_SIZE, "%u\n", subpagesize);
218 218
219 } 219 }
220 static DEVICE_ATTR(subpagesize, S_IRUGO, mtd_subpagesize_show, NULL); 220 static DEVICE_ATTR(subpagesize, S_IRUGO, mtd_subpagesize_show, NULL);
221 221
222 static ssize_t mtd_oobsize_show(struct device *dev, 222 static ssize_t mtd_oobsize_show(struct device *dev,
223 struct device_attribute *attr, char *buf) 223 struct device_attribute *attr, char *buf)
224 { 224 {
225 struct mtd_info *mtd = dev_get_drvdata(dev); 225 struct mtd_info *mtd = dev_get_drvdata(dev);
226 226
227 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->oobsize); 227 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->oobsize);
228 228
229 } 229 }
230 static DEVICE_ATTR(oobsize, S_IRUGO, mtd_oobsize_show, NULL); 230 static DEVICE_ATTR(oobsize, S_IRUGO, mtd_oobsize_show, NULL);
231 231
232 static ssize_t mtd_numeraseregions_show(struct device *dev, 232 static ssize_t mtd_numeraseregions_show(struct device *dev,
233 struct device_attribute *attr, char *buf) 233 struct device_attribute *attr, char *buf)
234 { 234 {
235 struct mtd_info *mtd = dev_get_drvdata(dev); 235 struct mtd_info *mtd = dev_get_drvdata(dev);
236 236
237 return snprintf(buf, PAGE_SIZE, "%u\n", mtd->numeraseregions); 237 return snprintf(buf, PAGE_SIZE, "%u\n", mtd->numeraseregions);
238 238
239 } 239 }
240 static DEVICE_ATTR(numeraseregions, S_IRUGO, mtd_numeraseregions_show, 240 static DEVICE_ATTR(numeraseregions, S_IRUGO, mtd_numeraseregions_show,
241 NULL); 241 NULL);
242 242
243 static ssize_t mtd_name_show(struct device *dev, 243 static ssize_t mtd_name_show(struct device *dev,
244 struct device_attribute *attr, char *buf) 244 struct device_attribute *attr, char *buf)
245 { 245 {
246 struct mtd_info *mtd = dev_get_drvdata(dev); 246 struct mtd_info *mtd = dev_get_drvdata(dev);
247 247
248 return snprintf(buf, PAGE_SIZE, "%s\n", mtd->name); 248 return snprintf(buf, PAGE_SIZE, "%s\n", mtd->name);
249 249
250 } 250 }
251 static DEVICE_ATTR(name, S_IRUGO, mtd_name_show, NULL); 251 static DEVICE_ATTR(name, S_IRUGO, mtd_name_show, NULL);
252 252
253 static struct attribute *mtd_attrs[] = { 253 static struct attribute *mtd_attrs[] = {
254 &dev_attr_type.attr, 254 &dev_attr_type.attr,
255 &dev_attr_flags.attr, 255 &dev_attr_flags.attr,
256 &dev_attr_size.attr, 256 &dev_attr_size.attr,
257 &dev_attr_erasesize.attr, 257 &dev_attr_erasesize.attr,
258 &dev_attr_writesize.attr, 258 &dev_attr_writesize.attr,
259 &dev_attr_subpagesize.attr, 259 &dev_attr_subpagesize.attr,
260 &dev_attr_oobsize.attr, 260 &dev_attr_oobsize.attr,
261 &dev_attr_numeraseregions.attr, 261 &dev_attr_numeraseregions.attr,
262 &dev_attr_name.attr, 262 &dev_attr_name.attr,
263 NULL, 263 NULL,
264 }; 264 };
265 265
266 static struct attribute_group mtd_group = { 266 static struct attribute_group mtd_group = {
267 .attrs = mtd_attrs, 267 .attrs = mtd_attrs,
268 }; 268 };
269 269
270 static const struct attribute_group *mtd_groups[] = { 270 static const struct attribute_group *mtd_groups[] = {
271 &mtd_group, 271 &mtd_group,
272 NULL, 272 NULL,
273 }; 273 };
274 274
275 static struct device_type mtd_devtype = { 275 static struct device_type mtd_devtype = {
276 .name = "mtd", 276 .name = "mtd",
277 .groups = mtd_groups, 277 .groups = mtd_groups,
278 .release = mtd_release, 278 .release = mtd_release,
279 }; 279 };
280 280
281 /** 281 /**
282 * add_mtd_device - register an MTD device 282 * add_mtd_device - register an MTD device
283 * @mtd: pointer to new MTD device info structure 283 * @mtd: pointer to new MTD device info structure
284 * 284 *
285 * Add a device to the list of MTD devices present in the system, and 285 * Add a device to the list of MTD devices present in the system, and
286 * notify each currently active MTD 'user' of its arrival. Returns 286 * notify each currently active MTD 'user' of its arrival. Returns
287 * zero on success or 1 on failure, which currently will only happen 287 * zero on success or 1 on failure, which currently will only happen
288 * if there is insufficient memory or a sysfs error. 288 * if there is insufficient memory or a sysfs error.
289 */ 289 */
290 290
291 int add_mtd_device(struct mtd_info *mtd) 291 int add_mtd_device(struct mtd_info *mtd)
292 { 292 {
293 struct mtd_notifier *not; 293 struct mtd_notifier *not;
294 int i, error; 294 int i, error;
295 295
296 if (!mtd->backing_dev_info) { 296 if (!mtd->backing_dev_info) {
297 switch (mtd->type) { 297 switch (mtd->type) {
298 case MTD_RAM: 298 case MTD_RAM:
299 mtd->backing_dev_info = &mtd_bdi_rw_mappable; 299 mtd->backing_dev_info = &mtd_bdi_rw_mappable;
300 break; 300 break;
301 case MTD_ROM: 301 case MTD_ROM:
302 mtd->backing_dev_info = &mtd_bdi_ro_mappable; 302 mtd->backing_dev_info = &mtd_bdi_ro_mappable;
303 break; 303 break;
304 default: 304 default:
305 mtd->backing_dev_info = &mtd_bdi_unmappable; 305 mtd->backing_dev_info = &mtd_bdi_unmappable;
306 break; 306 break;
307 } 307 }
308 } 308 }
309 309
310 BUG_ON(mtd->writesize == 0); 310 BUG_ON(mtd->writesize == 0);
311 mutex_lock(&mtd_table_mutex); 311 mutex_lock(&mtd_table_mutex);
312 312
313 do { 313 do {
314 if (!idr_pre_get(&mtd_idr, GFP_KERNEL)) 314 if (!idr_pre_get(&mtd_idr, GFP_KERNEL))
315 goto fail_locked; 315 goto fail_locked;
316 error = idr_get_new(&mtd_idr, mtd, &i); 316 error = idr_get_new(&mtd_idr, mtd, &i);
317 } while (error == -EAGAIN); 317 } while (error == -EAGAIN);
318 318
319 if (error) 319 if (error)
320 goto fail_locked; 320 goto fail_locked;
321 321
322 mtd->index = i; 322 mtd->index = i;
323 mtd->usecount = 0; 323 mtd->usecount = 0;
324 324
325 if (is_power_of_2(mtd->erasesize)) 325 if (is_power_of_2(mtd->erasesize))
326 mtd->erasesize_shift = ffs(mtd->erasesize) - 1; 326 mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
327 else 327 else
328 mtd->erasesize_shift = 0; 328 mtd->erasesize_shift = 0;
329 329
330 if (is_power_of_2(mtd->writesize)) 330 if (is_power_of_2(mtd->writesize))
331 mtd->writesize_shift = ffs(mtd->writesize) - 1; 331 mtd->writesize_shift = ffs(mtd->writesize) - 1;
332 else 332 else
333 mtd->writesize_shift = 0; 333 mtd->writesize_shift = 0;
334 334
335 mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1; 335 mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1;
336 mtd->writesize_mask = (1 << mtd->writesize_shift) - 1; 336 mtd->writesize_mask = (1 << mtd->writesize_shift) - 1;
337 337
338 /* Some chips always power up locked. Unlock them now */ 338 /* Some chips always power up locked. Unlock them now */
339 if ((mtd->flags & MTD_WRITEABLE) && (mtd->flags & MTD_POWERUP_LOCK)) { 339 if ((mtd->flags & MTD_WRITEABLE) && (mtd->flags & MTD_POWERUP_LOCK)) {
340 error = mtd_unlock(mtd, 0, mtd->size); 340 error = mtd_unlock(mtd, 0, mtd->size);
341 if (error && error != -EOPNOTSUPP) 341 if (error && error != -EOPNOTSUPP)
342 printk(KERN_WARNING 342 printk(KERN_WARNING
343 "%s: unlock failed, writes may not work\n", 343 "%s: unlock failed, writes may not work\n",
344 mtd->name); 344 mtd->name);
345 } 345 }
346 346
347 /* Caller should have set dev.parent to match the 347 /* Caller should have set dev.parent to match the
348 * physical device. 348 * physical device.
349 */ 349 */
350 mtd->dev.type = &mtd_devtype; 350 mtd->dev.type = &mtd_devtype;
351 mtd->dev.class = &mtd_class; 351 mtd->dev.class = &mtd_class;
352 mtd->dev.devt = MTD_DEVT(i); 352 mtd->dev.devt = MTD_DEVT(i);
353 dev_set_name(&mtd->dev, "mtd%d", i); 353 dev_set_name(&mtd->dev, "mtd%d", i);
354 dev_set_drvdata(&mtd->dev, mtd); 354 dev_set_drvdata(&mtd->dev, mtd);
355 if (device_register(&mtd->dev) != 0) 355 if (device_register(&mtd->dev) != 0)
356 goto fail_added; 356 goto fail_added;
357 357
358 if (MTD_DEVT(i)) 358 if (MTD_DEVT(i))
359 device_create(&mtd_class, mtd->dev.parent, 359 device_create(&mtd_class, mtd->dev.parent,
360 MTD_DEVT(i) + 1, 360 MTD_DEVT(i) + 1,
361 NULL, "mtd%dro", i); 361 NULL, "mtd%dro", i);
362 362
363 pr_debug("mtd: Giving out device %d to %s\n", i, mtd->name); 363 pr_debug("mtd: Giving out device %d to %s\n", i, mtd->name);
364 /* No need to get a refcount on the module containing 364 /* No need to get a refcount on the module containing
365 the notifier, since we hold the mtd_table_mutex */ 365 the notifier, since we hold the mtd_table_mutex */
366 list_for_each_entry(not, &mtd_notifiers, list) 366 list_for_each_entry(not, &mtd_notifiers, list)
367 not->add(mtd); 367 not->add(mtd);
368 368
369 mutex_unlock(&mtd_table_mutex); 369 mutex_unlock(&mtd_table_mutex);
370 /* We _know_ we aren't being removed, because 370 /* We _know_ we aren't being removed, because
371 our caller is still holding us here. So none 371 our caller is still holding us here. So none
372 of this try_ nonsense, and no bitching about it 372 of this try_ nonsense, and no bitching about it
373 either. :) */ 373 either. :) */
374 __module_get(THIS_MODULE); 374 __module_get(THIS_MODULE);
375 return 0; 375 return 0;
376 376
377 fail_added: 377 fail_added:
378 idr_remove(&mtd_idr, i); 378 idr_remove(&mtd_idr, i);
379 fail_locked: 379 fail_locked:
380 mutex_unlock(&mtd_table_mutex); 380 mutex_unlock(&mtd_table_mutex);
381 return 1; 381 return 1;
382 } 382 }
383 383
384 /** 384 /**
385 * del_mtd_device - unregister an MTD device 385 * del_mtd_device - unregister an MTD device
386 * @mtd: pointer to MTD device info structure 386 * @mtd: pointer to MTD device info structure
387 * 387 *
388 * Remove a device from the list of MTD devices present in the system, 388 * Remove a device from the list of MTD devices present in the system,
389 * and notify each currently active MTD 'user' of its departure. 389 * and notify each currently active MTD 'user' of its departure.
390 * Returns zero on success or 1 on failure, which currently will happen 390 * Returns zero on success or 1 on failure, which currently will happen
391 * if the requested device does not appear to be present in the list. 391 * if the requested device does not appear to be present in the list.
392 */ 392 */
393 393
394 int del_mtd_device(struct mtd_info *mtd) 394 int del_mtd_device(struct mtd_info *mtd)
395 { 395 {
396 int ret; 396 int ret;
397 struct mtd_notifier *not; 397 struct mtd_notifier *not;
398 398
399 mutex_lock(&mtd_table_mutex); 399 mutex_lock(&mtd_table_mutex);
400 400
401 if (idr_find(&mtd_idr, mtd->index) != mtd) { 401 if (idr_find(&mtd_idr, mtd->index) != mtd) {
402 ret = -ENODEV; 402 ret = -ENODEV;
403 goto out_error; 403 goto out_error;
404 } 404 }
405 405
406 /* No need to get a refcount on the module containing 406 /* No need to get a refcount on the module containing
407 the notifier, since we hold the mtd_table_mutex */ 407 the notifier, since we hold the mtd_table_mutex */
408 list_for_each_entry(not, &mtd_notifiers, list) 408 list_for_each_entry(not, &mtd_notifiers, list)
409 not->remove(mtd); 409 not->remove(mtd);
410 410
411 if (mtd->usecount) { 411 if (mtd->usecount) {
412 printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n", 412 printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n",
413 mtd->index, mtd->name, mtd->usecount); 413 mtd->index, mtd->name, mtd->usecount);
414 ret = -EBUSY; 414 ret = -EBUSY;
415 } else { 415 } else {
416 device_unregister(&mtd->dev); 416 device_unregister(&mtd->dev);
417 417
418 idr_remove(&mtd_idr, mtd->index); 418 idr_remove(&mtd_idr, mtd->index);
419 419
420 module_put(THIS_MODULE); 420 module_put(THIS_MODULE);
421 ret = 0; 421 ret = 0;
422 } 422 }
423 423
424 out_error: 424 out_error:
425 mutex_unlock(&mtd_table_mutex); 425 mutex_unlock(&mtd_table_mutex);
426 return ret; 426 return ret;
427 } 427 }
428 428
429 /** 429 /**
430 * mtd_device_parse_register - parse partitions and register an MTD device. 430 * mtd_device_parse_register - parse partitions and register an MTD device.
431 * 431 *
432 * @mtd: the MTD device to register 432 * @mtd: the MTD device to register
433 * @types: the list of MTD partition probes to try, see 433 * @types: the list of MTD partition probes to try, see
434 * 'parse_mtd_partitions()' for more information 434 * 'parse_mtd_partitions()' for more information
435 * @parser_data: MTD partition parser-specific data 435 * @parser_data: MTD partition parser-specific data
436 * @parts: fallback partition information to register, if parsing fails; 436 * @parts: fallback partition information to register, if parsing fails;
437 * only valid if %nr_parts > %0 437 * only valid if %nr_parts > %0
438 * @nr_parts: the number of partitions in parts, if zero then the full 438 * @nr_parts: the number of partitions in parts, if zero then the full
439 * MTD device is registered if no partition info is found 439 * MTD device is registered if no partition info is found
440 * 440 *
441 * This function aggregates MTD partitions parsing (done by 441 * This function aggregates MTD partitions parsing (done by
442 * 'parse_mtd_partitions()') and MTD device and partitions registering. It 442 * 'parse_mtd_partitions()') and MTD device and partitions registering. It
443 * basically follows the most common pattern found in many MTD drivers: 443 * basically follows the most common pattern found in many MTD drivers:
444 * 444 *
445 * * It first tries to probe partitions on MTD device @mtd using parsers 445 * * It first tries to probe partitions on MTD device @mtd using parsers
446 * specified in @types (if @types is %NULL, then the default list of parsers 446 * specified in @types (if @types is %NULL, then the default list of parsers
447 * is used, see 'parse_mtd_partitions()' for more information). If none are 447 * is used, see 'parse_mtd_partitions()' for more information). If none are
448 * found this functions tries to fallback to information specified in 448 * found this functions tries to fallback to information specified in
449 * @parts/@nr_parts. 449 * @parts/@nr_parts.
450 * * If any partitioning info was found, this function registers the found 450 * * If any partitioning info was found, this function registers the found
451 * partitions. 451 * partitions.
452 * * If no partitions were found this function just registers the MTD device 452 * * If no partitions were found this function just registers the MTD device
453 * @mtd and exits. 453 * @mtd and exits.
454 * 454 *
455 * Returns zero in case of success and a negative error code in case of failure. 455 * Returns zero in case of success and a negative error code in case of failure.
456 */ 456 */
457 int mtd_device_parse_register(struct mtd_info *mtd, const char **types, 457 int mtd_device_parse_register(struct mtd_info *mtd, const char **types,
458 struct mtd_part_parser_data *parser_data, 458 struct mtd_part_parser_data *parser_data,
459 const struct mtd_partition *parts, 459 const struct mtd_partition *parts,
460 int nr_parts) 460 int nr_parts)
461 { 461 {
462 int err; 462 int err;
463 struct mtd_partition *real_parts; 463 struct mtd_partition *real_parts;
464 464
465 err = parse_mtd_partitions(mtd, types, &real_parts, parser_data); 465 err = parse_mtd_partitions(mtd, types, &real_parts, parser_data);
466 if (err <= 0 && nr_parts && parts) { 466 if (err <= 0 && nr_parts && parts) {
467 real_parts = kmemdup(parts, sizeof(*parts) * nr_parts, 467 real_parts = kmemdup(parts, sizeof(*parts) * nr_parts,
468 GFP_KERNEL); 468 GFP_KERNEL);
469 if (!real_parts) 469 if (!real_parts)
470 err = -ENOMEM; 470 err = -ENOMEM;
471 else 471 else
472 err = nr_parts; 472 err = nr_parts;
473 } 473 }
474 474
475 if (err > 0) { 475 if (err > 0) {
476 err = add_mtd_partitions(mtd, real_parts, err); 476 err = add_mtd_partitions(mtd, real_parts, err);
477 kfree(real_parts); 477 kfree(real_parts);
478 } else if (err == 0) { 478 } else if (err == 0) {
479 err = add_mtd_device(mtd); 479 err = add_mtd_device(mtd);
480 if (err == 1) 480 if (err == 1)
481 err = -ENODEV; 481 err = -ENODEV;
482 } 482 }
483 483
484 return err; 484 return err;
485 } 485 }
486 EXPORT_SYMBOL_GPL(mtd_device_parse_register); 486 EXPORT_SYMBOL_GPL(mtd_device_parse_register);
487 487
488 /** 488 /**
489 * mtd_device_unregister - unregister an existing MTD device. 489 * mtd_device_unregister - unregister an existing MTD device.
490 * 490 *
491 * @master: the MTD device to unregister. This will unregister both the master 491 * @master: the MTD device to unregister. This will unregister both the master
492 * and any partitions if registered. 492 * and any partitions if registered.
493 */ 493 */
494 int mtd_device_unregister(struct mtd_info *master) 494 int mtd_device_unregister(struct mtd_info *master)
495 { 495 {
496 int err; 496 int err;
497 497
498 err = del_mtd_partitions(master); 498 err = del_mtd_partitions(master);
499 if (err) 499 if (err)
500 return err; 500 return err;
501 501
502 if (!device_is_registered(&master->dev)) 502 if (!device_is_registered(&master->dev))
503 return 0; 503 return 0;
504 504
505 return del_mtd_device(master); 505 return del_mtd_device(master);
506 } 506 }
507 EXPORT_SYMBOL_GPL(mtd_device_unregister); 507 EXPORT_SYMBOL_GPL(mtd_device_unregister);
508 508
509 /** 509 /**
510 * register_mtd_user - register a 'user' of MTD devices. 510 * register_mtd_user - register a 'user' of MTD devices.
511 * @new: pointer to notifier info structure 511 * @new: pointer to notifier info structure
512 * 512 *
513 * Registers a pair of callbacks function to be called upon addition 513 * Registers a pair of callbacks function to be called upon addition
514 * or removal of MTD devices. Causes the 'add' callback to be immediately 514 * or removal of MTD devices. Causes the 'add' callback to be immediately
515 * invoked for each MTD device currently present in the system. 515 * invoked for each MTD device currently present in the system.
516 */ 516 */
517 void register_mtd_user (struct mtd_notifier *new) 517 void register_mtd_user (struct mtd_notifier *new)
518 { 518 {
519 struct mtd_info *mtd; 519 struct mtd_info *mtd;
520 520
521 mutex_lock(&mtd_table_mutex); 521 mutex_lock(&mtd_table_mutex);
522 522
523 list_add(&new->list, &mtd_notifiers); 523 list_add(&new->list, &mtd_notifiers);
524 524
525 __module_get(THIS_MODULE); 525 __module_get(THIS_MODULE);
526 526
527 mtd_for_each_device(mtd) 527 mtd_for_each_device(mtd)
528 new->add(mtd); 528 new->add(mtd);
529 529
530 mutex_unlock(&mtd_table_mutex); 530 mutex_unlock(&mtd_table_mutex);
531 } 531 }
532 EXPORT_SYMBOL_GPL(register_mtd_user); 532 EXPORT_SYMBOL_GPL(register_mtd_user);
533 533
534 /** 534 /**
535 * unregister_mtd_user - unregister a 'user' of MTD devices. 535 * unregister_mtd_user - unregister a 'user' of MTD devices.
536 * @old: pointer to notifier info structure 536 * @old: pointer to notifier info structure
537 * 537 *
538 * Removes a callback function pair from the list of 'users' to be 538 * Removes a callback function pair from the list of 'users' to be
539 * notified upon addition or removal of MTD devices. Causes the 539 * notified upon addition or removal of MTD devices. Causes the
540 * 'remove' callback to be immediately invoked for each MTD device 540 * 'remove' callback to be immediately invoked for each MTD device
541 * currently present in the system. 541 * currently present in the system.
542 */ 542 */
543 int unregister_mtd_user (struct mtd_notifier *old) 543 int unregister_mtd_user (struct mtd_notifier *old)
544 { 544 {
545 struct mtd_info *mtd; 545 struct mtd_info *mtd;
546 546
547 mutex_lock(&mtd_table_mutex); 547 mutex_lock(&mtd_table_mutex);
548 548
549 module_put(THIS_MODULE); 549 module_put(THIS_MODULE);
550 550
551 mtd_for_each_device(mtd) 551 mtd_for_each_device(mtd)
552 old->remove(mtd); 552 old->remove(mtd);
553 553
554 list_del(&old->list); 554 list_del(&old->list);
555 mutex_unlock(&mtd_table_mutex); 555 mutex_unlock(&mtd_table_mutex);
556 return 0; 556 return 0;
557 } 557 }
558 EXPORT_SYMBOL_GPL(unregister_mtd_user); 558 EXPORT_SYMBOL_GPL(unregister_mtd_user);
559 559
560 /** 560 /**
561 * get_mtd_device - obtain a validated handle for an MTD device 561 * get_mtd_device - obtain a validated handle for an MTD device
562 * @mtd: last known address of the required MTD device 562 * @mtd: last known address of the required MTD device
563 * @num: internal device number of the required MTD device 563 * @num: internal device number of the required MTD device
564 * 564 *
565 * Given a number and NULL address, return the num'th entry in the device 565 * Given a number and NULL address, return the num'th entry in the device
566 * table, if any. Given an address and num == -1, search the device table 566 * table, if any. Given an address and num == -1, search the device table
567 * for a device with that address and return if it's still present. Given 567 * for a device with that address and return if it's still present. Given
568 * both, return the num'th driver only if its address matches. Return 568 * both, return the num'th driver only if its address matches. Return
569 * error code if not. 569 * error code if not.
570 */ 570 */
571 struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) 571 struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
572 { 572 {
573 struct mtd_info *ret = NULL, *other; 573 struct mtd_info *ret = NULL, *other;
574 int err = -ENODEV; 574 int err = -ENODEV;
575 575
576 mutex_lock(&mtd_table_mutex); 576 mutex_lock(&mtd_table_mutex);
577 577
578 if (num == -1) { 578 if (num == -1) {
579 mtd_for_each_device(other) { 579 mtd_for_each_device(other) {
580 if (other == mtd) { 580 if (other == mtd) {
581 ret = mtd; 581 ret = mtd;
582 break; 582 break;
583 } 583 }
584 } 584 }
585 } else if (num >= 0) { 585 } else if (num >= 0) {
586 ret = idr_find(&mtd_idr, num); 586 ret = idr_find(&mtd_idr, num);
587 if (mtd && mtd != ret) 587 if (mtd && mtd != ret)
588 ret = NULL; 588 ret = NULL;
589 } 589 }
590 590
591 if (!ret) { 591 if (!ret) {
592 ret = ERR_PTR(err); 592 ret = ERR_PTR(err);
593 goto out; 593 goto out;
594 } 594 }
595 595
596 err = __get_mtd_device(ret); 596 err = __get_mtd_device(ret);
597 if (err) 597 if (err)
598 ret = ERR_PTR(err); 598 ret = ERR_PTR(err);
599 out: 599 out:
600 mutex_unlock(&mtd_table_mutex); 600 mutex_unlock(&mtd_table_mutex);
601 return ret; 601 return ret;
602 } 602 }
603 EXPORT_SYMBOL_GPL(get_mtd_device); 603 EXPORT_SYMBOL_GPL(get_mtd_device);
604 604
605 605
606 int __get_mtd_device(struct mtd_info *mtd) 606 int __get_mtd_device(struct mtd_info *mtd)
607 { 607 {
608 int err; 608 int err;
609 609
610 if (!try_module_get(mtd->owner)) 610 if (!try_module_get(mtd->owner))
611 return -ENODEV; 611 return -ENODEV;
612 612
613 if (mtd->_get_device) { 613 if (mtd->_get_device) {
614 err = mtd->_get_device(mtd); 614 err = mtd->_get_device(mtd);
615 615
616 if (err) { 616 if (err) {
617 module_put(mtd->owner); 617 module_put(mtd->owner);
618 return err; 618 return err;
619 } 619 }
620 } 620 }
621 mtd->usecount++; 621 mtd->usecount++;
622 return 0; 622 return 0;
623 } 623 }
624 EXPORT_SYMBOL_GPL(__get_mtd_device); 624 EXPORT_SYMBOL_GPL(__get_mtd_device);
625 625
626 /** 626 /**
627 * get_mtd_device_nm - obtain a validated handle for an MTD device by 627 * get_mtd_device_nm - obtain a validated handle for an MTD device by
628 * device name 628 * device name
629 * @name: MTD device name to open 629 * @name: MTD device name to open
630 * 630 *
631 * This function returns MTD device description structure in case of 631 * This function returns MTD device description structure in case of
632 * success and an error code in case of failure. 632 * success and an error code in case of failure.
633 */ 633 */
634 struct mtd_info *get_mtd_device_nm(const char *name) 634 struct mtd_info *get_mtd_device_nm(const char *name)
635 { 635 {
636 int err = -ENODEV; 636 int err = -ENODEV;
637 struct mtd_info *mtd = NULL, *other; 637 struct mtd_info *mtd = NULL, *other;
638 638
639 mutex_lock(&mtd_table_mutex); 639 mutex_lock(&mtd_table_mutex);
640 640
641 mtd_for_each_device(other) { 641 mtd_for_each_device(other) {
642 if (!strcmp(name, other->name)) { 642 if (!strcmp(name, other->name)) {
643 mtd = other; 643 mtd = other;
644 break; 644 break;
645 } 645 }
646 } 646 }
647 647
648 if (!mtd) 648 if (!mtd)
649 goto out_unlock; 649 goto out_unlock;
650 650
651 err = __get_mtd_device(mtd); 651 err = __get_mtd_device(mtd);
652 if (err) 652 if (err)
653 goto out_unlock; 653 goto out_unlock;
654 654
655 mutex_unlock(&mtd_table_mutex); 655 mutex_unlock(&mtd_table_mutex);
656 return mtd; 656 return mtd;
657 657
658 out_unlock: 658 out_unlock:
659 mutex_unlock(&mtd_table_mutex); 659 mutex_unlock(&mtd_table_mutex);
660 return ERR_PTR(err); 660 return ERR_PTR(err);
661 } 661 }
662 EXPORT_SYMBOL_GPL(get_mtd_device_nm); 662 EXPORT_SYMBOL_GPL(get_mtd_device_nm);
663 663
664 void put_mtd_device(struct mtd_info *mtd) 664 void put_mtd_device(struct mtd_info *mtd)
665 { 665 {
666 mutex_lock(&mtd_table_mutex); 666 mutex_lock(&mtd_table_mutex);
667 __put_mtd_device(mtd); 667 __put_mtd_device(mtd);
668 mutex_unlock(&mtd_table_mutex); 668 mutex_unlock(&mtd_table_mutex);
669 669
670 } 670 }
671 EXPORT_SYMBOL_GPL(put_mtd_device); 671 EXPORT_SYMBOL_GPL(put_mtd_device);
672 672
673 void __put_mtd_device(struct mtd_info *mtd) 673 void __put_mtd_device(struct mtd_info *mtd)
674 { 674 {
675 --mtd->usecount; 675 --mtd->usecount;
676 BUG_ON(mtd->usecount < 0); 676 BUG_ON(mtd->usecount < 0);
677 677
678 if (mtd->_put_device) 678 if (mtd->_put_device)
679 mtd->_put_device(mtd); 679 mtd->_put_device(mtd);
680 680
681 module_put(mtd->owner); 681 module_put(mtd->owner);
682 } 682 }
683 EXPORT_SYMBOL_GPL(__put_mtd_device); 683 EXPORT_SYMBOL_GPL(__put_mtd_device);
684 684
685 /* 685 /*
686 * Erase is an asynchronous operation. Device drivers are supposed 686 * Erase is an asynchronous operation. Device drivers are supposed
687 * to call instr->callback() whenever the operation completes, even 687 * to call instr->callback() whenever the operation completes, even
688 * if it completes with a failure. 688 * if it completes with a failure.
689 * Callers are supposed to pass a callback function and wait for it 689 * Callers are supposed to pass a callback function and wait for it
690 * to be called before writing to the block. 690 * to be called before writing to the block.
691 */ 691 */
692 int mtd_erase(struct mtd_info *mtd, struct erase_info *instr) 692 int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
693 { 693 {
694 if (instr->addr > mtd->size || instr->len > mtd->size - instr->addr) 694 if (instr->addr > mtd->size || instr->len > mtd->size - instr->addr)
695 return -EINVAL; 695 return -EINVAL;
696 if (!(mtd->flags & MTD_WRITEABLE)) 696 if (!(mtd->flags & MTD_WRITEABLE))
697 return -EROFS; 697 return -EROFS;
698 return mtd->_erase(mtd, instr); 698 return mtd->_erase(mtd, instr);
699 } 699 }
700 EXPORT_SYMBOL_GPL(mtd_erase); 700 EXPORT_SYMBOL_GPL(mtd_erase);
701 701
702 /* 702 /*
703 * This stuff for eXecute-In-Place. phys is optional and may be set to NULL. 703 * This stuff for eXecute-In-Place. phys is optional and may be set to NULL.
704 */ 704 */
705 int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, 705 int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
706 void **virt, resource_size_t *phys) 706 void **virt, resource_size_t *phys)
707 { 707 {
708 *retlen = 0; 708 *retlen = 0;
709 *virt = NULL;
710 if (phys)
711 *phys = 0;
709 if (!mtd->_point) 712 if (!mtd->_point)
710 return -EOPNOTSUPP; 713 return -EOPNOTSUPP;
711 if (from < 0 || from > mtd->size || len > mtd->size - from) 714 if (from < 0 || from > mtd->size || len > mtd->size - from)
712 return -EINVAL; 715 return -EINVAL;
713 return mtd->_point(mtd, from, len, retlen, virt, phys); 716 return mtd->_point(mtd, from, len, retlen, virt, phys);
714 } 717 }
715 EXPORT_SYMBOL_GPL(mtd_point); 718 EXPORT_SYMBOL_GPL(mtd_point);
716 719
717 /* We probably shouldn't allow XIP if the unpoint isn't a NULL */ 720 /* We probably shouldn't allow XIP if the unpoint isn't a NULL */
718 int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len) 721 int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
719 { 722 {
720 if (!mtd->_point) 723 if (!mtd->_point)
721 return -EOPNOTSUPP; 724 return -EOPNOTSUPP;
722 if (from < 0 || from > mtd->size || len > mtd->size - from) 725 if (from < 0 || from > mtd->size || len > mtd->size - from)
723 return -EINVAL; 726 return -EINVAL;
724 return mtd->_unpoint(mtd, from, len); 727 return mtd->_unpoint(mtd, from, len);
725 } 728 }
726 EXPORT_SYMBOL_GPL(mtd_unpoint); 729 EXPORT_SYMBOL_GPL(mtd_unpoint);
727 730
728 /* 731 /*
729 * Allow NOMMU mmap() to directly map the device (if not NULL) 732 * Allow NOMMU mmap() to directly map the device (if not NULL)
730 * - return the address to which the offset maps 733 * - return the address to which the offset maps
731 * - return -ENOSYS to indicate refusal to do the mapping 734 * - return -ENOSYS to indicate refusal to do the mapping
732 */ 735 */
733 unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long len, 736 unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long len,
734 unsigned long offset, unsigned long flags) 737 unsigned long offset, unsigned long flags)
735 { 738 {
736 if (!mtd->_get_unmapped_area) 739 if (!mtd->_get_unmapped_area)
737 return -EOPNOTSUPP; 740 return -EOPNOTSUPP;
738 if (offset > mtd->size || len > mtd->size - offset) 741 if (offset > mtd->size || len > mtd->size - offset)
739 return -EINVAL; 742 return -EINVAL;
740 return mtd->_get_unmapped_area(mtd, len, offset, flags); 743 return mtd->_get_unmapped_area(mtd, len, offset, flags);
741 } 744 }
742 EXPORT_SYMBOL_GPL(mtd_get_unmapped_area); 745 EXPORT_SYMBOL_GPL(mtd_get_unmapped_area);
743 746
744 int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, 747 int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
745 u_char *buf) 748 u_char *buf)
746 { 749 {
747 *retlen = 0; 750 *retlen = 0;
748 if (from < 0 || from > mtd->size || len > mtd->size - from) 751 if (from < 0 || from > mtd->size || len > mtd->size - from)
749 return -EINVAL; 752 return -EINVAL;
750 return mtd->_read(mtd, from, len, retlen, buf); 753 return mtd->_read(mtd, from, len, retlen, buf);
751 } 754 }
752 EXPORT_SYMBOL_GPL(mtd_read); 755 EXPORT_SYMBOL_GPL(mtd_read);
753 756
754 int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, 757 int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
755 const u_char *buf) 758 const u_char *buf)
756 { 759 {
757 *retlen = 0; 760 *retlen = 0;
758 if (to < 0 || to > mtd->size || len > mtd->size - to) 761 if (to < 0 || to > mtd->size || len > mtd->size - to)
759 return -EINVAL; 762 return -EINVAL;
760 if (!mtd->_write || !(mtd->flags & MTD_WRITEABLE)) 763 if (!mtd->_write || !(mtd->flags & MTD_WRITEABLE))
761 return -EROFS; 764 return -EROFS;
762 return mtd->_write(mtd, to, len, retlen, buf); 765 return mtd->_write(mtd, to, len, retlen, buf);
763 } 766 }
764 EXPORT_SYMBOL_GPL(mtd_write); 767 EXPORT_SYMBOL_GPL(mtd_write);
765 768
766 /* 769 /*
767 * In blackbox flight recorder like scenarios we want to make successful writes 770 * In blackbox flight recorder like scenarios we want to make successful writes
768 * in interrupt context. panic_write() is only intended to be called when its 771 * in interrupt context. panic_write() is only intended to be called when its
769 * known the kernel is about to panic and we need the write to succeed. Since 772 * known the kernel is about to panic and we need the write to succeed. Since
770 * the kernel is not going to be running for much longer, this function can 773 * the kernel is not going to be running for much longer, this function can
771 * break locks and delay to ensure the write succeeds (but not sleep). 774 * break locks and delay to ensure the write succeeds (but not sleep).
772 */ 775 */
773 int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, 776 int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
774 const u_char *buf) 777 const u_char *buf)
775 { 778 {
776 *retlen = 0; 779 *retlen = 0;
777 if (!mtd->_panic_write) 780 if (!mtd->_panic_write)
778 return -EOPNOTSUPP; 781 return -EOPNOTSUPP;
779 if (to < 0 || to > mtd->size || len > mtd->size - to) 782 if (to < 0 || to > mtd->size || len > mtd->size - to)
780 return -EINVAL; 783 return -EINVAL;
781 if (!(mtd->flags & MTD_WRITEABLE)) 784 if (!(mtd->flags & MTD_WRITEABLE))
782 return -EROFS; 785 return -EROFS;
783 return mtd->_panic_write(mtd, to, len, retlen, buf); 786 return mtd->_panic_write(mtd, to, len, retlen, buf);
784 } 787 }
785 EXPORT_SYMBOL_GPL(mtd_panic_write); 788 EXPORT_SYMBOL_GPL(mtd_panic_write);
786 789
787 /* Chip-supported device locking */ 790 /* Chip-supported device locking */
788 int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 791 int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
789 { 792 {
790 if (!mtd->_lock) 793 if (!mtd->_lock)
791 return -EOPNOTSUPP; 794 return -EOPNOTSUPP;
792 if (ofs < 0 || ofs > mtd->size || len > mtd->size - ofs) 795 if (ofs < 0 || ofs > mtd->size || len > mtd->size - ofs)
793 return -EINVAL; 796 return -EINVAL;
794 return mtd->_lock(mtd, ofs, len); 797 return mtd->_lock(mtd, ofs, len);
795 } 798 }
796 EXPORT_SYMBOL_GPL(mtd_lock); 799 EXPORT_SYMBOL_GPL(mtd_lock);
797 800
798 int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 801 int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
799 { 802 {
800 if (!mtd->_unlock) 803 if (!mtd->_unlock)
801 return -EOPNOTSUPP; 804 return -EOPNOTSUPP;
802 if (ofs < 0 || ofs > mtd->size || len > mtd->size - ofs) 805 if (ofs < 0 || ofs > mtd->size || len > mtd->size - ofs)
803 return -EINVAL; 806 return -EINVAL;
804 return mtd->_unlock(mtd, ofs, len); 807 return mtd->_unlock(mtd, ofs, len);
805 } 808 }
806 EXPORT_SYMBOL_GPL(mtd_unlock); 809 EXPORT_SYMBOL_GPL(mtd_unlock);
807 810
808 int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) 811 int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
809 { 812 {
810 if (!mtd->_is_locked) 813 if (!mtd->_is_locked)
811 return -EOPNOTSUPP; 814 return -EOPNOTSUPP;
812 if (ofs < 0 || ofs > mtd->size || len > mtd->size - ofs) 815 if (ofs < 0 || ofs > mtd->size || len > mtd->size - ofs)
813 return -EINVAL; 816 return -EINVAL;
814 return mtd->_is_locked(mtd, ofs, len); 817 return mtd->_is_locked(mtd, ofs, len);
815 } 818 }
816 EXPORT_SYMBOL_GPL(mtd_is_locked); 819 EXPORT_SYMBOL_GPL(mtd_is_locked);
817 820
818 int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs) 821 int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
819 { 822 {
820 if (!mtd->_block_isbad) 823 if (!mtd->_block_isbad)
821 return 0; 824 return 0;
822 if (ofs < 0 || ofs > mtd->size) 825 if (ofs < 0 || ofs > mtd->size)
823 return -EINVAL; 826 return -EINVAL;
824 return mtd->_block_isbad(mtd, ofs); 827 return mtd->_block_isbad(mtd, ofs);
825 } 828 }
826 EXPORT_SYMBOL_GPL(mtd_block_isbad); 829 EXPORT_SYMBOL_GPL(mtd_block_isbad);
827 830
828 int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs) 831 int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs)
829 { 832 {
830 if (!mtd->_block_markbad) 833 if (!mtd->_block_markbad)
831 return -EOPNOTSUPP; 834 return -EOPNOTSUPP;
832 if (ofs < 0 || ofs > mtd->size) 835 if (ofs < 0 || ofs > mtd->size)
833 return -EINVAL; 836 return -EINVAL;
834 if (!(mtd->flags & MTD_WRITEABLE)) 837 if (!(mtd->flags & MTD_WRITEABLE))
835 return -EROFS; 838 return -EROFS;
836 return mtd->_block_markbad(mtd, ofs); 839 return mtd->_block_markbad(mtd, ofs);
837 } 840 }
838 EXPORT_SYMBOL_GPL(mtd_block_markbad); 841 EXPORT_SYMBOL_GPL(mtd_block_markbad);
839 842
840 /* 843 /*
841 * default_mtd_writev - the default writev method 844 * default_mtd_writev - the default writev method
842 * @mtd: mtd device description object pointer 845 * @mtd: mtd device description object pointer
843 * @vecs: the vectors to write 846 * @vecs: the vectors to write
844 * @count: count of vectors in @vecs 847 * @count: count of vectors in @vecs
845 * @to: the MTD device offset to write to 848 * @to: the MTD device offset to write to
846 * @retlen: on exit contains the count of bytes written to the MTD device. 849 * @retlen: on exit contains the count of bytes written to the MTD device.
847 * 850 *
848 * This function returns zero in case of success and a negative error code in 851 * This function returns zero in case of success and a negative error code in
849 * case of failure. 852 * case of failure.
850 */ 853 */
851 static int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, 854 static int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
852 unsigned long count, loff_t to, size_t *retlen) 855 unsigned long count, loff_t to, size_t *retlen)
853 { 856 {
854 unsigned long i; 857 unsigned long i;
855 size_t totlen = 0, thislen; 858 size_t totlen = 0, thislen;
856 int ret = 0; 859 int ret = 0;
857 860
858 for (i = 0; i < count; i++) { 861 for (i = 0; i < count; i++) {
859 if (!vecs[i].iov_len) 862 if (!vecs[i].iov_len)
860 continue; 863 continue;
861 ret = mtd_write(mtd, to, vecs[i].iov_len, &thislen, 864 ret = mtd_write(mtd, to, vecs[i].iov_len, &thislen,
862 vecs[i].iov_base); 865 vecs[i].iov_base);
863 totlen += thislen; 866 totlen += thislen;
864 if (ret || thislen != vecs[i].iov_len) 867 if (ret || thislen != vecs[i].iov_len)
865 break; 868 break;
866 to += vecs[i].iov_len; 869 to += vecs[i].iov_len;
867 } 870 }
868 *retlen = totlen; 871 *retlen = totlen;
869 return ret; 872 return ret;
870 } 873 }
871 874
872 /* 875 /*
873 * mtd_writev - the vector-based MTD write method 876 * mtd_writev - the vector-based MTD write method
874 * @mtd: mtd device description object pointer 877 * @mtd: mtd device description object pointer
875 * @vecs: the vectors to write 878 * @vecs: the vectors to write
876 * @count: count of vectors in @vecs 879 * @count: count of vectors in @vecs
877 * @to: the MTD device offset to write to 880 * @to: the MTD device offset to write to
878 * @retlen: on exit contains the count of bytes written to the MTD device. 881 * @retlen: on exit contains the count of bytes written to the MTD device.
879 * 882 *
880 * This function returns zero in case of success and a negative error code in 883 * This function returns zero in case of success and a negative error code in
881 * case of failure. 884 * case of failure.
882 */ 885 */
883 int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, 886 int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
884 unsigned long count, loff_t to, size_t *retlen) 887 unsigned long count, loff_t to, size_t *retlen)
885 { 888 {
886 *retlen = 0; 889 *retlen = 0;
887 if (!(mtd->flags & MTD_WRITEABLE)) 890 if (!(mtd->flags & MTD_WRITEABLE))
888 return -EROFS; 891 return -EROFS;
889 if (!mtd->_writev) 892 if (!mtd->_writev)
890 return default_mtd_writev(mtd, vecs, count, to, retlen); 893 return default_mtd_writev(mtd, vecs, count, to, retlen);
891 return mtd->_writev(mtd, vecs, count, to, retlen); 894 return mtd->_writev(mtd, vecs, count, to, retlen);
892 } 895 }
893 EXPORT_SYMBOL_GPL(mtd_writev); 896 EXPORT_SYMBOL_GPL(mtd_writev);
894 897
895 /** 898 /**
896 * mtd_kmalloc_up_to - allocate a contiguous buffer up to the specified size 899 * mtd_kmalloc_up_to - allocate a contiguous buffer up to the specified size
897 * @mtd: mtd device description object pointer 900 * @mtd: mtd device description object pointer
898 * @size: a pointer to the ideal or maximum size of the allocation, points 901 * @size: a pointer to the ideal or maximum size of the allocation, points
899 * to the actual allocation size on success. 902 * to the actual allocation size on success.
900 * 903 *
901 * This routine attempts to allocate a contiguous kernel buffer up to 904 * This routine attempts to allocate a contiguous kernel buffer up to
902 * the specified size, backing off the size of the request exponentially 905 * the specified size, backing off the size of the request exponentially
903 * until the request succeeds or until the allocation size falls below 906 * until the request succeeds or until the allocation size falls below
904 * the system page size. This attempts to make sure it does not adversely 907 * the system page size. This attempts to make sure it does not adversely
905 * impact system performance, so when allocating more than one page, we 908 * impact system performance, so when allocating more than one page, we
906 * ask the memory allocator to avoid re-trying, swapping, writing back 909 * ask the memory allocator to avoid re-trying, swapping, writing back
907 * or performing I/O. 910 * or performing I/O.
908 * 911 *
909 * Note, this function also makes sure that the allocated buffer is aligned to 912 * Note, this function also makes sure that the allocated buffer is aligned to
910 * the MTD device's min. I/O unit, i.e. the "mtd->writesize" value. 913 * the MTD device's min. I/O unit, i.e. the "mtd->writesize" value.
911 * 914 *
912 * This is called, for example by mtd_{read,write} and jffs2_scan_medium, 915 * This is called, for example by mtd_{read,write} and jffs2_scan_medium,
913 * to handle smaller (i.e. degraded) buffer allocations under low- or 916 * to handle smaller (i.e. degraded) buffer allocations under low- or
914 * fragmented-memory situations where such reduced allocations, from a 917 * fragmented-memory situations where such reduced allocations, from a
915 * requested ideal, are allowed. 918 * requested ideal, are allowed.
916 * 919 *
917 * Returns a pointer to the allocated buffer on success; otherwise, NULL. 920 * Returns a pointer to the allocated buffer on success; otherwise, NULL.
918 */ 921 */
919 void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size) 922 void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size)
920 { 923 {
921 gfp_t flags = __GFP_NOWARN | __GFP_WAIT | 924 gfp_t flags = __GFP_NOWARN | __GFP_WAIT |
922 __GFP_NORETRY | __GFP_NO_KSWAPD; 925 __GFP_NORETRY | __GFP_NO_KSWAPD;
923 size_t min_alloc = max_t(size_t, mtd->writesize, PAGE_SIZE); 926 size_t min_alloc = max_t(size_t, mtd->writesize, PAGE_SIZE);
924 void *kbuf; 927 void *kbuf;
925 928
926 *size = min_t(size_t, *size, KMALLOC_MAX_SIZE); 929 *size = min_t(size_t, *size, KMALLOC_MAX_SIZE);
927 930
928 while (*size > min_alloc) { 931 while (*size > min_alloc) {
929 kbuf = kmalloc(*size, flags); 932 kbuf = kmalloc(*size, flags);
930 if (kbuf) 933 if (kbuf)
931 return kbuf; 934 return kbuf;
932 935
933 *size >>= 1; 936 *size >>= 1;
934 *size = ALIGN(*size, mtd->writesize); 937 *size = ALIGN(*size, mtd->writesize);
935 } 938 }
936 939
937 /* 940 /*
938 * For the last resort allocation allow 'kmalloc()' to do all sorts of 941 * For the last resort allocation allow 'kmalloc()' to do all sorts of
939 * things (write-back, dropping caches, etc) by using GFP_KERNEL. 942 * things (write-back, dropping caches, etc) by using GFP_KERNEL.
940 */ 943 */
941 return kmalloc(*size, GFP_KERNEL); 944 return kmalloc(*size, GFP_KERNEL);
942 } 945 }
943 EXPORT_SYMBOL_GPL(mtd_kmalloc_up_to); 946 EXPORT_SYMBOL_GPL(mtd_kmalloc_up_to);
944 947
945 #ifdef CONFIG_PROC_FS 948 #ifdef CONFIG_PROC_FS
946 949
947 /*====================================================================*/ 950 /*====================================================================*/
948 /* Support for /proc/mtd */ 951 /* Support for /proc/mtd */
949 952
950 static struct proc_dir_entry *proc_mtd; 953 static struct proc_dir_entry *proc_mtd;
951 954
952 static int mtd_proc_show(struct seq_file *m, void *v) 955 static int mtd_proc_show(struct seq_file *m, void *v)
953 { 956 {
954 struct mtd_info *mtd; 957 struct mtd_info *mtd;
955 958
956 seq_puts(m, "dev: size erasesize name\n"); 959 seq_puts(m, "dev: size erasesize name\n");
957 mutex_lock(&mtd_table_mutex); 960 mutex_lock(&mtd_table_mutex);
958 mtd_for_each_device(mtd) { 961 mtd_for_each_device(mtd) {
959 seq_printf(m, "mtd%d: %8.8llx %8.8x \"%s\"\n", 962 seq_printf(m, "mtd%d: %8.8llx %8.8x \"%s\"\n",
960 mtd->index, (unsigned long long)mtd->size, 963 mtd->index, (unsigned long long)mtd->size,
961 mtd->erasesize, mtd->name); 964 mtd->erasesize, mtd->name);
962 } 965 }
963 mutex_unlock(&mtd_table_mutex); 966 mutex_unlock(&mtd_table_mutex);
964 return 0; 967 return 0;
965 } 968 }
966 969
967 static int mtd_proc_open(struct inode *inode, struct file *file) 970 static int mtd_proc_open(struct inode *inode, struct file *file)
968 { 971 {
969 return single_open(file, mtd_proc_show, NULL); 972 return single_open(file, mtd_proc_show, NULL);
970 } 973 }
971 974
972 static const struct file_operations mtd_proc_ops = { 975 static const struct file_operations mtd_proc_ops = {
973 .open = mtd_proc_open, 976 .open = mtd_proc_open,
974 .read = seq_read, 977 .read = seq_read,
975 .llseek = seq_lseek, 978 .llseek = seq_lseek,
976 .release = single_release, 979 .release = single_release,
977 }; 980 };
978 #endif /* CONFIG_PROC_FS */ 981 #endif /* CONFIG_PROC_FS */
979 982
980 /*====================================================================*/ 983 /*====================================================================*/
981 /* Init code */ 984 /* Init code */
982 985
983 static int __init mtd_bdi_init(struct backing_dev_info *bdi, const char *name) 986 static int __init mtd_bdi_init(struct backing_dev_info *bdi, const char *name)
984 { 987 {
985 int ret; 988 int ret;
986 989
987 ret = bdi_init(bdi); 990 ret = bdi_init(bdi);
988 if (!ret) 991 if (!ret)
989 ret = bdi_register(bdi, NULL, name); 992 ret = bdi_register(bdi, NULL, name);
990 993
991 if (ret) 994 if (ret)
992 bdi_destroy(bdi); 995 bdi_destroy(bdi);
993 996
994 return ret; 997 return ret;
995 } 998 }
996 999
997 static int __init init_mtd(void) 1000 static int __init init_mtd(void)
998 { 1001 {
999 int ret; 1002 int ret;
1000 1003
1001 ret = class_register(&mtd_class); 1004 ret = class_register(&mtd_class);
1002 if (ret) 1005 if (ret)
1003 goto err_reg; 1006 goto err_reg;
1004 1007
1005 ret = mtd_bdi_init(&mtd_bdi_unmappable, "mtd-unmap"); 1008 ret = mtd_bdi_init(&mtd_bdi_unmappable, "mtd-unmap");
1006 if (ret) 1009 if (ret)
1007 goto err_bdi1; 1010 goto err_bdi1;
1008 1011
1009 ret = mtd_bdi_init(&mtd_bdi_ro_mappable, "mtd-romap"); 1012 ret = mtd_bdi_init(&mtd_bdi_ro_mappable, "mtd-romap");
1010 if (ret) 1013 if (ret)
1011 goto err_bdi2; 1014 goto err_bdi2;
1012 1015
1013 ret = mtd_bdi_init(&mtd_bdi_rw_mappable, "mtd-rwmap"); 1016 ret = mtd_bdi_init(&mtd_bdi_rw_mappable, "mtd-rwmap");
1014 if (ret) 1017 if (ret)
1015 goto err_bdi3; 1018 goto err_bdi3;
1016 1019
1017 #ifdef CONFIG_PROC_FS 1020 #ifdef CONFIG_PROC_FS
1018 proc_mtd = proc_create("mtd", 0, NULL, &mtd_proc_ops); 1021 proc_mtd = proc_create("mtd", 0, NULL, &mtd_proc_ops);
1019 #endif /* CONFIG_PROC_FS */ 1022 #endif /* CONFIG_PROC_FS */
1020 return 0; 1023 return 0;
1021 1024
1022 err_bdi3: 1025 err_bdi3:
1023 bdi_destroy(&mtd_bdi_ro_mappable); 1026 bdi_destroy(&mtd_bdi_ro_mappable);
1024 err_bdi2: 1027 err_bdi2:
1025 bdi_destroy(&mtd_bdi_unmappable); 1028 bdi_destroy(&mtd_bdi_unmappable);
1026 err_bdi1: 1029 err_bdi1:
1027 class_unregister(&mtd_class); 1030 class_unregister(&mtd_class);
1028 err_reg: 1031 err_reg:
1029 pr_err("Error registering mtd class or bdi: %d\n", ret); 1032 pr_err("Error registering mtd class or bdi: %d\n", ret);
1030 return ret; 1033 return ret;
1031 } 1034 }
1032 1035
1033 static void __exit cleanup_mtd(void) 1036 static void __exit cleanup_mtd(void)
1034 { 1037 {
1035 #ifdef CONFIG_PROC_FS 1038 #ifdef CONFIG_PROC_FS
1036 if (proc_mtd) 1039 if (proc_mtd)
1037 remove_proc_entry( "mtd", NULL); 1040 remove_proc_entry( "mtd", NULL);
1038 #endif /* CONFIG_PROC_FS */ 1041 #endif /* CONFIG_PROC_FS */
1039 class_unregister(&mtd_class); 1042 class_unregister(&mtd_class);
1040 bdi_destroy(&mtd_bdi_unmappable); 1043 bdi_destroy(&mtd_bdi_unmappable);
1041 bdi_destroy(&mtd_bdi_ro_mappable); 1044 bdi_destroy(&mtd_bdi_ro_mappable);
1042 bdi_destroy(&mtd_bdi_rw_mappable); 1045 bdi_destroy(&mtd_bdi_rw_mappable);
1043 } 1046 }
1044 1047
1045 module_init(init_mtd); 1048 module_init(init_mtd);
1046 module_exit(cleanup_mtd); 1049 module_exit(cleanup_mtd);
1047 1050
1048 MODULE_LICENSE("GPL"); 1051 MODULE_LICENSE("GPL");
1049 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); 1052 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
1050 MODULE_DESCRIPTION("Core MTD registration and access routines"); 1053 MODULE_DESCRIPTION("Core MTD registration and access routines");
1051 1054