diff options
author | Robert Jarzmik <robert.jarzmik@free.fr> | 2011-10-05 09:22:34 -0400 |
---|---|---|
committer | Artem Bityutskiy <artem.bityutskiy@intel.com> | 2011-10-14 05:03:47 -0400 |
commit | efa2ca73a7bc1a8f8e66bcfad33391746819ffe6 (patch) | |
tree | 09846f5b9888fcf935be868b1362cef767d9ebec /drivers/mtd/devices/docg3.c | |
parent | 86a9893d08420a320191a1bcc0136ec2b6b04595 (diff) |
mtd: Add DiskOnChip G3 support
Add support for DiskOnChip G3 chips. The support is quite
limited yet :
- no flash writes/erases are implemented
- ECC fixes are not implemented
- powerdown is not implemented
- IPL handling is not yet done
On the brighter side, the chip reading does work.
Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
Diffstat (limited to 'drivers/mtd/devices/docg3.c')
-rw-r--r-- | drivers/mtd/devices/docg3.c | 1114 |
1 files changed, 1114 insertions, 0 deletions
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c new file mode 100644 index 000000000000..bdcf5df982e8 --- /dev/null +++ b/drivers/mtd/devices/docg3.c | |||
@@ -0,0 +1,1114 @@ | |||
1 | /* | ||
2 | * Handles the M-Systems DiskOnChip G3 chip | ||
3 | * | ||
4 | * Copyright (C) 2011 Robert Jarzmik | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/string.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/io.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/mtd/mtd.h> | ||
31 | #include <linux/mtd/partitions.h> | ||
32 | |||
33 | #include <linux/debugfs.h> | ||
34 | #include <linux/seq_file.h> | ||
35 | |||
36 | #define CREATE_TRACE_POINTS | ||
37 | #include "docg3.h" | ||
38 | |||
39 | /* | ||
40 | * This driver handles the DiskOnChip G3 flash memory. | ||
41 | * | ||
42 | * As no specification is available from M-Systems/Sandisk, this drivers lacks | ||
43 | * several functions available on the chip, as : | ||
44 | * - block erase | ||
45 | * - page write | ||
46 | * - IPL write | ||
47 | * - ECC fixing (lack of BCH algorith understanding) | ||
48 | * - powerdown / powerup | ||
49 | * | ||
50 | * The bus data width (8bits versus 16bits) is not handled (if_cfg flag), and | ||
51 | * the driver assumes a 16bits data bus. | ||
52 | * | ||
53 | * DocG3 relies on 2 ECC algorithms, which are handled in hardware : | ||
54 | * - a 1 byte Hamming code stored in the OOB for each page | ||
55 | * - a 7 bytes BCH code stored in the OOB for each page | ||
56 | * The BCH part is only used for check purpose, no correction is available as | ||
57 | * some information is missing. What is known is that : | ||
58 | * - BCH is in GF(2^14) | ||
59 | * - BCH is over data of 520 bytes (512 page + 7 page_info bytes | ||
60 | * + 1 hamming byte) | ||
61 | * - BCH can correct up to 4 bits (t = 4) | ||
62 | * - BCH syndroms are calculated in hardware, and checked in hardware as well | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | static inline u8 doc_readb(struct docg3 *docg3, u16 reg) | ||
67 | { | ||
68 | u8 val = readb(docg3->base + reg); | ||
69 | |||
70 | trace_docg3_io(0, 8, reg, (int)val); | ||
71 | return val; | ||
72 | } | ||
73 | |||
74 | static inline u16 doc_readw(struct docg3 *docg3, u16 reg) | ||
75 | { | ||
76 | u16 val = readw(docg3->base + reg); | ||
77 | |||
78 | trace_docg3_io(0, 16, reg, (int)val); | ||
79 | return val; | ||
80 | } | ||
81 | |||
82 | static inline void doc_writeb(struct docg3 *docg3, u8 val, u16 reg) | ||
83 | { | ||
84 | writeb(val, docg3->base + reg); | ||
85 | trace_docg3_io(1, 16, reg, val); | ||
86 | } | ||
87 | |||
88 | static inline void doc_writew(struct docg3 *docg3, u16 val, u16 reg) | ||
89 | { | ||
90 | writew(val, docg3->base + reg); | ||
91 | trace_docg3_io(1, 16, reg, val); | ||
92 | } | ||
93 | |||
94 | static inline void doc_flash_command(struct docg3 *docg3, u8 cmd) | ||
95 | { | ||
96 | doc_writeb(docg3, cmd, DOC_FLASHCOMMAND); | ||
97 | } | ||
98 | |||
99 | static inline void doc_flash_sequence(struct docg3 *docg3, u8 seq) | ||
100 | { | ||
101 | doc_writeb(docg3, seq, DOC_FLASHSEQUENCE); | ||
102 | } | ||
103 | |||
104 | static inline void doc_flash_address(struct docg3 *docg3, u8 addr) | ||
105 | { | ||
106 | doc_writeb(docg3, addr, DOC_FLASHADDRESS); | ||
107 | } | ||
108 | |||
109 | static char const *part_probes[] = { "cmdlinepart", "saftlpart", NULL }; | ||
110 | |||
111 | static int doc_register_readb(struct docg3 *docg3, int reg) | ||
112 | { | ||
113 | u8 val; | ||
114 | |||
115 | doc_writew(docg3, reg, DOC_READADDRESS); | ||
116 | val = doc_readb(docg3, reg); | ||
117 | doc_vdbg("Read register %04x : %02x\n", reg, val); | ||
118 | return val; | ||
119 | } | ||
120 | |||
121 | static int doc_register_readw(struct docg3 *docg3, int reg) | ||
122 | { | ||
123 | u16 val; | ||
124 | |||
125 | doc_writew(docg3, reg, DOC_READADDRESS); | ||
126 | val = doc_readw(docg3, reg); | ||
127 | doc_vdbg("Read register %04x : %04x\n", reg, val); | ||
128 | return val; | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * doc_delay - delay docg3 operations | ||
133 | * @docg3: the device | ||
134 | * @nbNOPs: the number of NOPs to issue | ||
135 | * | ||
136 | * As no specification is available, the right timings between chip commands are | ||
137 | * unknown. The only available piece of information are the observed nops on a | ||
138 | * working docg3 chip. | ||
139 | * Therefore, doc_delay relies on a busy loop of NOPs, instead of scheduler | ||
140 | * friendlier msleep() functions or blocking mdelay(). | ||
141 | */ | ||
142 | static void doc_delay(struct docg3 *docg3, int nbNOPs) | ||
143 | { | ||
144 | int i; | ||
145 | |||
146 | doc_dbg("NOP x %d\n", nbNOPs); | ||
147 | for (i = 0; i < nbNOPs; i++) | ||
148 | doc_writeb(docg3, 0, DOC_NOP); | ||
149 | } | ||
150 | |||
151 | static int is_prot_seq_error(struct docg3 *docg3) | ||
152 | { | ||
153 | int ctrl; | ||
154 | |||
155 | ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL); | ||
156 | return ctrl & (DOC_CTRL_PROTECTION_ERROR | DOC_CTRL_SEQUENCE_ERROR); | ||
157 | } | ||
158 | |||
159 | static int doc_is_ready(struct docg3 *docg3) | ||
160 | { | ||
161 | int ctrl; | ||
162 | |||
163 | ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL); | ||
164 | return ctrl & DOC_CTRL_FLASHREADY; | ||
165 | } | ||
166 | |||
167 | static int doc_wait_ready(struct docg3 *docg3) | ||
168 | { | ||
169 | int maxWaitCycles = 100; | ||
170 | |||
171 | do { | ||
172 | doc_delay(docg3, 4); | ||
173 | cpu_relax(); | ||
174 | } while (!doc_is_ready(docg3) && maxWaitCycles--); | ||
175 | doc_delay(docg3, 2); | ||
176 | if (maxWaitCycles > 0) | ||
177 | return 0; | ||
178 | else | ||
179 | return -EIO; | ||
180 | } | ||
181 | |||
182 | static int doc_reset_seq(struct docg3 *docg3) | ||
183 | { | ||
184 | int ret; | ||
185 | |||
186 | doc_writeb(docg3, 0x10, DOC_FLASHCONTROL); | ||
187 | doc_flash_sequence(docg3, DOC_SEQ_RESET); | ||
188 | doc_flash_command(docg3, DOC_CMD_RESET); | ||
189 | doc_delay(docg3, 2); | ||
190 | ret = doc_wait_ready(docg3); | ||
191 | |||
192 | doc_dbg("doc_reset_seq() -> isReady=%s\n", ret ? "false" : "true"); | ||
193 | return ret; | ||
194 | } | ||
195 | |||
196 | /** | ||
197 | * doc_read_data_area - Read data from data area | ||
198 | * @docg3: the device | ||
199 | * @buf: the buffer to fill in | ||
200 | * @len: the lenght to read | ||
201 | * @first: first time read, DOC_READADDRESS should be set | ||
202 | * | ||
203 | * Reads bytes from flash data. Handles the single byte / even bytes reads. | ||
204 | */ | ||
205 | static void doc_read_data_area(struct docg3 *docg3, void *buf, int len, | ||
206 | int first) | ||
207 | { | ||
208 | int i, cdr, len4; | ||
209 | u16 data16, *dst16; | ||
210 | u8 data8, *dst8; | ||
211 | |||
212 | doc_dbg("doc_read_data_area(buf=%p, len=%d)\n", buf, len); | ||
213 | cdr = len & 0x3; | ||
214 | len4 = len - cdr; | ||
215 | |||
216 | if (first) | ||
217 | doc_writew(docg3, DOC_IOSPACE_DATA, DOC_READADDRESS); | ||
218 | dst16 = buf; | ||
219 | for (i = 0; i < len4; i += 2) { | ||
220 | data16 = doc_readw(docg3, DOC_IOSPACE_DATA); | ||
221 | *dst16 = data16; | ||
222 | dst16++; | ||
223 | } | ||
224 | |||
225 | if (cdr) { | ||
226 | doc_writew(docg3, DOC_IOSPACE_DATA | DOC_READADDR_ONE_BYTE, | ||
227 | DOC_READADDRESS); | ||
228 | doc_delay(docg3, 1); | ||
229 | dst8 = (u8 *)dst16; | ||
230 | for (i = 0; i < cdr; i++) { | ||
231 | data8 = doc_readb(docg3, DOC_IOSPACE_DATA); | ||
232 | *dst8 = data8; | ||
233 | dst8++; | ||
234 | } | ||
235 | } | ||
236 | } | ||
237 | |||
238 | /** | ||
239 | * doc_set_data_mode - Sets the flash to reliable data mode | ||
240 | * @docg3: the device | ||
241 | * | ||
242 | * The reliable data mode is a bit slower than the fast mode, but less errors | ||
243 | * occur. Entering the reliable mode cannot be done without entering the fast | ||
244 | * mode first. | ||
245 | */ | ||
246 | static void doc_set_reliable_mode(struct docg3 *docg3) | ||
247 | { | ||
248 | doc_dbg("doc_set_reliable_mode()\n"); | ||
249 | doc_flash_sequence(docg3, DOC_SEQ_SET_MODE); | ||
250 | doc_flash_command(docg3, DOC_CMD_FAST_MODE); | ||
251 | doc_flash_command(docg3, DOC_CMD_RELIABLE_MODE); | ||
252 | doc_delay(docg3, 2); | ||
253 | } | ||
254 | |||
255 | /** | ||
256 | * doc_set_asic_mode - Set the ASIC mode | ||
257 | * @docg3: the device | ||
258 | * @mode: the mode | ||
259 | * | ||
260 | * The ASIC can work in 3 modes : | ||
261 | * - RESET: all registers are zeroed | ||
262 | * - NORMAL: receives and handles commands | ||
263 | * - POWERDOWN: minimal poweruse, flash parts shut off | ||
264 | */ | ||
265 | static void doc_set_asic_mode(struct docg3 *docg3, u8 mode) | ||
266 | { | ||
267 | int i; | ||
268 | |||
269 | for (i = 0; i < 12; i++) | ||
270 | doc_readb(docg3, DOC_IOSPACE_IPL); | ||
271 | |||
272 | mode |= DOC_ASICMODE_MDWREN; | ||
273 | doc_dbg("doc_set_asic_mode(%02x)\n", mode); | ||
274 | doc_writeb(docg3, mode, DOC_ASICMODE); | ||
275 | doc_writeb(docg3, ~mode, DOC_ASICMODECONFIRM); | ||
276 | doc_delay(docg3, 1); | ||
277 | } | ||
278 | |||
279 | /** | ||
280 | * doc_set_device_id - Sets the devices id for cascaded G3 chips | ||
281 | * @docg3: the device | ||
282 | * @id: the chip to select (amongst 0, 1, 2, 3) | ||
283 | * | ||
284 | * There can be 4 cascaded G3 chips. This function selects the one which will | ||
285 | * should be the active one. | ||
286 | */ | ||
287 | static void doc_set_device_id(struct docg3 *docg3, int id) | ||
288 | { | ||
289 | u8 ctrl; | ||
290 | |||
291 | doc_dbg("doc_set_device_id(%d)\n", id); | ||
292 | doc_writeb(docg3, id, DOC_DEVICESELECT); | ||
293 | ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL); | ||
294 | |||
295 | ctrl &= ~DOC_CTRL_VIOLATION; | ||
296 | ctrl |= DOC_CTRL_CE; | ||
297 | doc_writeb(docg3, ctrl, DOC_FLASHCONTROL); | ||
298 | } | ||
299 | |||
300 | /** | ||
301 | * doc_set_extra_page_mode - Change flash page layout | ||
302 | * @docg3: the device | ||
303 | * | ||
304 | * Normally, the flash page is split into the data (512 bytes) and the out of | ||
305 | * band data (16 bytes). For each, 4 more bytes can be accessed, where the wear | ||
306 | * leveling counters are stored. To access this last area of 4 bytes, a special | ||
307 | * mode must be input to the flash ASIC. | ||
308 | * | ||
309 | * Returns 0 if no error occured, -EIO else. | ||
310 | */ | ||
311 | static int doc_set_extra_page_mode(struct docg3 *docg3) | ||
312 | { | ||
313 | int fctrl; | ||
314 | |||
315 | doc_dbg("doc_set_extra_page_mode()\n"); | ||
316 | doc_flash_sequence(docg3, DOC_SEQ_PAGE_SIZE_532); | ||
317 | doc_flash_command(docg3, DOC_CMD_PAGE_SIZE_532); | ||
318 | doc_delay(docg3, 2); | ||
319 | |||
320 | fctrl = doc_register_readb(docg3, DOC_FLASHCONTROL); | ||
321 | if (fctrl & (DOC_CTRL_PROTECTION_ERROR | DOC_CTRL_SEQUENCE_ERROR)) | ||
322 | return -EIO; | ||
323 | else | ||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | /** | ||
328 | * doc_seek - Set both flash planes to the specified block, page for reading | ||
329 | * @docg3: the device | ||
330 | * @block0: the first plane block index | ||
331 | * @block1: the second plane block index | ||
332 | * @page: the page index within the block | ||
333 | * @wear: if true, read will occur on the 4 extra bytes of the wear area | ||
334 | * @ofs: offset in page to read | ||
335 | * | ||
336 | * Programs the flash even and odd planes to the specific block and page. | ||
337 | * Alternatively, programs the flash to the wear area of the specified page. | ||
338 | */ | ||
339 | static int doc_read_seek(struct docg3 *docg3, int block0, int block1, int page, | ||
340 | int wear, int ofs) | ||
341 | { | ||
342 | int sector, ret = 0; | ||
343 | |||
344 | doc_dbg("doc_seek(blocks=(%d,%d), page=%d, ofs=%d, wear=%d)\n", | ||
345 | block0, block1, page, ofs, wear); | ||
346 | |||
347 | if (!wear && (ofs < 2 * DOC_LAYOUT_PAGE_SIZE)) { | ||
348 | doc_flash_sequence(docg3, DOC_SEQ_SET_PLANE1); | ||
349 | doc_flash_command(docg3, DOC_CMD_READ_PLANE1); | ||
350 | doc_delay(docg3, 2); | ||
351 | } else { | ||
352 | doc_flash_sequence(docg3, DOC_SEQ_SET_PLANE2); | ||
353 | doc_flash_command(docg3, DOC_CMD_READ_PLANE2); | ||
354 | doc_delay(docg3, 2); | ||
355 | } | ||
356 | |||
357 | doc_set_reliable_mode(docg3); | ||
358 | if (wear) | ||
359 | ret = doc_set_extra_page_mode(docg3); | ||
360 | if (ret) | ||
361 | goto out; | ||
362 | |||
363 | sector = (block0 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK); | ||
364 | doc_flash_sequence(docg3, DOC_SEQ_READ); | ||
365 | doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR); | ||
366 | doc_delay(docg3, 1); | ||
367 | doc_flash_address(docg3, sector & 0xff); | ||
368 | doc_flash_address(docg3, (sector >> 8) & 0xff); | ||
369 | doc_flash_address(docg3, (sector >> 16) & 0xff); | ||
370 | doc_delay(docg3, 1); | ||
371 | |||
372 | sector = (block1 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK); | ||
373 | doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR); | ||
374 | doc_delay(docg3, 1); | ||
375 | doc_flash_address(docg3, sector & 0xff); | ||
376 | doc_flash_address(docg3, (sector >> 8) & 0xff); | ||
377 | doc_flash_address(docg3, (sector >> 16) & 0xff); | ||
378 | doc_delay(docg3, 2); | ||
379 | |||
380 | out: | ||
381 | return ret; | ||
382 | } | ||
383 | |||
384 | /** | ||
385 | * doc_read_page_ecc_init - Initialize hardware ECC engine | ||
386 | * @docg3: the device | ||
387 | * @len: the number of bytes covered by the ECC (BCH covered) | ||
388 | * | ||
389 | * The function does initialize the hardware ECC engine to compute the Hamming | ||
390 | * ECC (on 1 byte) and the BCH Syndroms (on 7 bytes). | ||
391 | * | ||
392 | * Return 0 if succeeded, -EIO on error | ||
393 | */ | ||
394 | static int doc_read_page_ecc_init(struct docg3 *docg3, int len) | ||
395 | { | ||
396 | doc_writew(docg3, DOC_ECCCONF0_READ_MODE | ||
397 | | DOC_ECCCONF0_BCH_ENABLE | DOC_ECCCONF0_HAMMING_ENABLE | ||
398 | | (len & DOC_ECCCONF0_DATA_BYTES_MASK), | ||
399 | DOC_ECCCONF0); | ||
400 | doc_delay(docg3, 4); | ||
401 | doc_register_readb(docg3, DOC_FLASHCONTROL); | ||
402 | return doc_wait_ready(docg3); | ||
403 | } | ||
404 | |||
405 | /** | ||
406 | * doc_read_page_prepare - Prepares reading data from a flash page | ||
407 | * @docg3: the device | ||
408 | * @block0: the first plane block index on flash memory | ||
409 | * @block1: the second plane block index on flash memory | ||
410 | * @page: the page index in the block | ||
411 | * @offset: the offset in the page (must be a multiple of 4) | ||
412 | * | ||
413 | * Prepares the page to be read in the flash memory : | ||
414 | * - tell ASIC to map the flash pages | ||
415 | * - tell ASIC to be in read mode | ||
416 | * | ||
417 | * After a call to this method, a call to doc_read_page_finish is mandatory, | ||
418 | * to end the read cycle of the flash. | ||
419 | * | ||
420 | * Read data from a flash page. The length to be read must be between 0 and | ||
421 | * (page_size + oob_size + wear_size), ie. 532, and a multiple of 4 (because | ||
422 | * the extra bytes reading is not implemented). | ||
423 | * | ||
424 | * As pages are grouped by 2 (in 2 planes), reading from a page must be done | ||
425 | * in two steps: | ||
426 | * - one read of 512 bytes at offset 0 | ||
427 | * - one read of 512 bytes at offset 512 + 16 | ||
428 | * | ||
429 | * Returns 0 if successful, -EIO if a read error occured. | ||
430 | */ | ||
431 | static int doc_read_page_prepare(struct docg3 *docg3, int block0, int block1, | ||
432 | int page, int offset) | ||
433 | { | ||
434 | int wear_area = 0, ret = 0; | ||
435 | |||
436 | doc_dbg("doc_read_page_prepare(blocks=(%d,%d), page=%d, ofsInPage=%d)\n", | ||
437 | block0, block1, page, offset); | ||
438 | if (offset >= DOC_LAYOUT_WEAR_OFFSET) | ||
439 | wear_area = 1; | ||
440 | if (!wear_area && offset > (DOC_LAYOUT_PAGE_OOB_SIZE * 2)) | ||
441 | return -EINVAL; | ||
442 | |||
443 | doc_set_device_id(docg3, docg3->device_id); | ||
444 | ret = doc_reset_seq(docg3); | ||
445 | if (ret) | ||
446 | goto err; | ||
447 | |||
448 | /* Program the flash address block and page */ | ||
449 | ret = doc_read_seek(docg3, block0, block1, page, wear_area, offset); | ||
450 | if (ret) | ||
451 | goto err; | ||
452 | |||
453 | doc_flash_command(docg3, DOC_CMD_READ_ALL_PLANES); | ||
454 | doc_delay(docg3, 2); | ||
455 | doc_wait_ready(docg3); | ||
456 | |||
457 | doc_flash_command(docg3, DOC_CMD_SET_ADDR_READ); | ||
458 | doc_delay(docg3, 1); | ||
459 | if (offset >= DOC_LAYOUT_PAGE_SIZE * 2) | ||
460 | offset -= 2 * DOC_LAYOUT_PAGE_SIZE; | ||
461 | doc_flash_address(docg3, offset >> 2); | ||
462 | doc_delay(docg3, 1); | ||
463 | doc_wait_ready(docg3); | ||
464 | |||
465 | doc_flash_command(docg3, DOC_CMD_READ_FLASH); | ||
466 | |||
467 | return 0; | ||
468 | err: | ||
469 | doc_writeb(docg3, 0, DOC_DATAEND); | ||
470 | doc_delay(docg3, 2); | ||
471 | return -EIO; | ||
472 | } | ||
473 | |||
474 | /** | ||
475 | * doc_read_page_getbytes - Reads bytes from a prepared page | ||
476 | * @docg3: the device | ||
477 | * @len: the number of bytes to be read (must be a multiple of 4) | ||
478 | * @buf: the buffer to be filled in | ||
479 | * @first: 1 if first time read, DOC_READADDRESS should be set | ||
480 | * | ||
481 | */ | ||
482 | static int doc_read_page_getbytes(struct docg3 *docg3, int len, u_char *buf, | ||
483 | int first) | ||
484 | { | ||
485 | doc_read_data_area(docg3, buf, len, first); | ||
486 | doc_delay(docg3, 2); | ||
487 | return len; | ||
488 | } | ||
489 | |||
490 | /** | ||
491 | * doc_get_hw_bch_syndroms - Get hardware calculated BCH syndroms | ||
492 | * @docg3: the device | ||
493 | * @syns: the array of 7 integers where the syndroms will be stored | ||
494 | */ | ||
495 | static void doc_get_hw_bch_syndroms(struct docg3 *docg3, int *syns) | ||
496 | { | ||
497 | int i; | ||
498 | |||
499 | for (i = 0; i < DOC_ECC_BCH_SIZE; i++) | ||
500 | syns[i] = doc_register_readb(docg3, DOC_BCH_SYNDROM(i)); | ||
501 | } | ||
502 | |||
503 | /** | ||
504 | * doc_read_page_finish - Ends reading of a flash page | ||
505 | * @docg3: the device | ||
506 | * | ||
507 | * As a side effect, resets the chip selector to 0. This ensures that after each | ||
508 | * read operation, the floor 0 is selected. Therefore, if the systems halts, the | ||
509 | * reboot will boot on floor 0, where the IPL is. | ||
510 | */ | ||
511 | static void doc_read_page_finish(struct docg3 *docg3) | ||
512 | { | ||
513 | doc_writeb(docg3, 0, DOC_DATAEND); | ||
514 | doc_delay(docg3, 2); | ||
515 | doc_set_device_id(docg3, 0); | ||
516 | } | ||
517 | |||
518 | /** | ||
519 | * calc_block_sector - Calculate blocks, pages and ofs. | ||
520 | |||
521 | * @from: offset in flash | ||
522 | * @block0: first plane block index calculated | ||
523 | * @block1: second plane block index calculated | ||
524 | * @page: page calculated | ||
525 | * @ofs: offset in page | ||
526 | */ | ||
527 | static void calc_block_sector(loff_t from, int *block0, int *block1, int *page, | ||
528 | int *ofs) | ||
529 | { | ||
530 | uint sector; | ||
531 | |||
532 | sector = from / DOC_LAYOUT_PAGE_SIZE; | ||
533 | *block0 = sector / (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_NBPLANES) | ||
534 | * DOC_LAYOUT_NBPLANES; | ||
535 | *block1 = *block0 + 1; | ||
536 | *page = sector % (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_NBPLANES); | ||
537 | *page /= DOC_LAYOUT_NBPLANES; | ||
538 | if (sector % 2) | ||
539 | *ofs = DOC_LAYOUT_PAGE_OOB_SIZE; | ||
540 | else | ||
541 | *ofs = 0; | ||
542 | } | ||
543 | |||
544 | /** | ||
545 | * doc_read - Read bytes from flash | ||
546 | * @mtd: the device | ||
547 | * @from: the offset from first block and first page, in bytes, aligned on page | ||
548 | * size | ||
549 | * @len: the number of bytes to read (must be a multiple of 4) | ||
550 | * @retlen: the number of bytes actually read | ||
551 | * @buf: the filled in buffer | ||
552 | * | ||
553 | * Reads flash memory pages. This function does not read the OOB chunk, but only | ||
554 | * the page data. | ||
555 | * | ||
556 | * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured | ||
557 | */ | ||
558 | static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, | ||
559 | size_t *retlen, u_char *buf) | ||
560 | { | ||
561 | struct docg3 *docg3 = mtd->priv; | ||
562 | int block0, block1, page, readlen, ret, ofs = 0; | ||
563 | int syn[DOC_ECC_BCH_SIZE], eccconf1; | ||
564 | u8 oob[DOC_LAYOUT_OOB_SIZE]; | ||
565 | |||
566 | ret = -EINVAL; | ||
567 | doc_dbg("doc_read(from=%lld, len=%zu, buf=%p)\n", from, len, buf); | ||
568 | if (from % DOC_LAYOUT_PAGE_SIZE) | ||
569 | goto err; | ||
570 | if (len % 4) | ||
571 | goto err; | ||
572 | calc_block_sector(from, &block0, &block1, &page, &ofs); | ||
573 | if (block1 > docg3->max_block) | ||
574 | goto err; | ||
575 | |||
576 | *retlen = 0; | ||
577 | ret = 0; | ||
578 | readlen = min_t(size_t, len, (size_t)DOC_LAYOUT_PAGE_SIZE); | ||
579 | while (!ret && len > 0) { | ||
580 | readlen = min_t(size_t, len, (size_t)DOC_LAYOUT_PAGE_SIZE); | ||
581 | ret = doc_read_page_prepare(docg3, block0, block1, page, ofs); | ||
582 | if (ret < 0) | ||
583 | goto err; | ||
584 | ret = doc_read_page_ecc_init(docg3, DOC_ECC_BCH_COVERED_BYTES); | ||
585 | if (ret < 0) | ||
586 | goto err_in_read; | ||
587 | ret = doc_read_page_getbytes(docg3, readlen, buf, 1); | ||
588 | if (ret < readlen) | ||
589 | goto err_in_read; | ||
590 | ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE, | ||
591 | oob, 0); | ||
592 | if (ret < DOC_LAYOUT_OOB_SIZE) | ||
593 | goto err_in_read; | ||
594 | |||
595 | *retlen += readlen; | ||
596 | buf += readlen; | ||
597 | len -= readlen; | ||
598 | |||
599 | ofs ^= DOC_LAYOUT_PAGE_OOB_SIZE; | ||
600 | if (ofs == 0) | ||
601 | page += 2; | ||
602 | if (page > DOC_ADDR_PAGE_MASK) { | ||
603 | page = 0; | ||
604 | block0 += 2; | ||
605 | block1 += 2; | ||
606 | } | ||
607 | |||
608 | /* | ||
609 | * There should be a BCH bitstream fixing algorithm here ... | ||
610 | * By now, a page read failure is triggered by BCH error | ||
611 | */ | ||
612 | doc_get_hw_bch_syndroms(docg3, syn); | ||
613 | eccconf1 = doc_register_readb(docg3, DOC_ECCCONF1); | ||
614 | |||
615 | doc_dbg("OOB - INFO: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
616 | oob[0], oob[1], oob[2], oob[3], oob[4], | ||
617 | oob[5], oob[6]); | ||
618 | doc_dbg("OOB - HAMMING: %02x\n", oob[7]); | ||
619 | doc_dbg("OOB - BCH_ECC: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
620 | oob[8], oob[9], oob[10], oob[11], oob[12], | ||
621 | oob[13], oob[14]); | ||
622 | doc_dbg("OOB - UNUSED: %02x\n", oob[15]); | ||
623 | doc_dbg("ECC checks: ECCConf1=%x\n", eccconf1); | ||
624 | doc_dbg("ECC BCH syndrom: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
625 | syn[0], syn[1], syn[2], syn[3], syn[4], syn[5], syn[6]); | ||
626 | |||
627 | ret = -EBADMSG; | ||
628 | if (block0 >= DOC_LAYOUT_BLOCK_FIRST_DATA) { | ||
629 | if (eccconf1 & DOC_ECCCONF1_BCH_SYNDROM_ERR) | ||
630 | goto err_in_read; | ||
631 | if (is_prot_seq_error(docg3)) | ||
632 | goto err_in_read; | ||
633 | } | ||
634 | doc_read_page_finish(docg3); | ||
635 | } | ||
636 | |||
637 | return 0; | ||
638 | err_in_read: | ||
639 | doc_read_page_finish(docg3); | ||
640 | err: | ||
641 | return ret; | ||
642 | } | ||
643 | |||
644 | /** | ||
645 | * doc_read_oob - Read out of band bytes from flash | ||
646 | * @mtd: the device | ||
647 | * @from: the offset from first block and first page, in bytes, aligned on page | ||
648 | * size | ||
649 | * @ops: the mtd oob structure | ||
650 | * | ||
651 | * Reads flash memory OOB area of pages. | ||
652 | * | ||
653 | * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured | ||
654 | */ | ||
655 | static int doc_read_oob(struct mtd_info *mtd, loff_t from, | ||
656 | struct mtd_oob_ops *ops) | ||
657 | { | ||
658 | struct docg3 *docg3 = mtd->priv; | ||
659 | int block0, block1, page, ofs, ret; | ||
660 | u8 *buf = ops->oobbuf; | ||
661 | size_t len = ops->ooblen; | ||
662 | |||
663 | doc_dbg("doc_read_oob(from=%lld, buf=%p, len=%zu)\n", from, buf, len); | ||
664 | if (len != DOC_LAYOUT_OOB_SIZE) | ||
665 | return -EINVAL; | ||
666 | |||
667 | switch (ops->mode) { | ||
668 | case MTD_OPS_PLACE_OOB: | ||
669 | buf += ops->ooboffs; | ||
670 | break; | ||
671 | default: | ||
672 | break; | ||
673 | } | ||
674 | |||
675 | calc_block_sector(from, &block0, &block1, &page, &ofs); | ||
676 | if (block1 > docg3->max_block) | ||
677 | return -EINVAL; | ||
678 | |||
679 | ret = doc_read_page_prepare(docg3, block0, block1, page, | ||
680 | ofs + DOC_LAYOUT_PAGE_SIZE); | ||
681 | if (!ret) | ||
682 | ret = doc_read_page_ecc_init(docg3, DOC_LAYOUT_OOB_SIZE); | ||
683 | if (!ret) | ||
684 | ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE, | ||
685 | buf, 1); | ||
686 | doc_read_page_finish(docg3); | ||
687 | |||
688 | if (ret > 0) | ||
689 | ops->oobretlen = ret; | ||
690 | else | ||
691 | ops->oobretlen = 0; | ||
692 | return (ret > 0) ? 0 : ret; | ||
693 | } | ||
694 | |||
695 | static int doc_reload_bbt(struct docg3 *docg3) | ||
696 | { | ||
697 | int block = DOC_LAYOUT_BLOCK_BBT; | ||
698 | int ret = 0, nbpages, page; | ||
699 | u_char *buf = docg3->bbt; | ||
700 | |||
701 | nbpages = DIV_ROUND_UP(docg3->max_block + 1, 8 * DOC_LAYOUT_PAGE_SIZE); | ||
702 | for (page = 0; !ret && (page < nbpages); page++) { | ||
703 | ret = doc_read_page_prepare(docg3, block, block + 1, | ||
704 | page + DOC_LAYOUT_PAGE_BBT, 0); | ||
705 | if (!ret) | ||
706 | ret = doc_read_page_ecc_init(docg3, | ||
707 | DOC_LAYOUT_PAGE_SIZE); | ||
708 | if (!ret) | ||
709 | doc_read_page_getbytes(docg3, DOC_LAYOUT_PAGE_SIZE, | ||
710 | buf, 1); | ||
711 | buf += DOC_LAYOUT_PAGE_SIZE; | ||
712 | } | ||
713 | doc_read_page_finish(docg3); | ||
714 | return ret; | ||
715 | } | ||
716 | |||
717 | /** | ||
718 | * doc_block_isbad - Checks whether a block is good or not | ||
719 | * @mtd: the device | ||
720 | * @from: the offset to find the correct block | ||
721 | * | ||
722 | * Returns 1 if block is bad, 0 if block is good | ||
723 | */ | ||
724 | static int doc_block_isbad(struct mtd_info *mtd, loff_t from) | ||
725 | { | ||
726 | struct docg3 *docg3 = mtd->priv; | ||
727 | int block0, block1, page, ofs, is_good; | ||
728 | |||
729 | calc_block_sector(from, &block0, &block1, &page, &ofs); | ||
730 | doc_dbg("doc_block_isbad(from=%lld) => block=(%d,%d), page=%d, ofs=%d\n", | ||
731 | from, block0, block1, page, ofs); | ||
732 | |||
733 | if (block0 < DOC_LAYOUT_BLOCK_FIRST_DATA) | ||
734 | return 0; | ||
735 | if (block1 > docg3->max_block) | ||
736 | return -EINVAL; | ||
737 | |||
738 | is_good = docg3->bbt[block0 >> 3] & (1 << (block0 & 0x7)); | ||
739 | return !is_good; | ||
740 | } | ||
741 | |||
742 | /** | ||
743 | * doc_get_erase_count - Get block erase count | ||
744 | * @docg3: the device | ||
745 | * @from: the offset in which the block is. | ||
746 | * | ||
747 | * Get the number of times a block was erased. The number is the maximum of | ||
748 | * erase times between first and second plane (which should be equal normally). | ||
749 | * | ||
750 | * Returns The number of erases, or -EINVAL or -EIO on error. | ||
751 | */ | ||
752 | static int doc_get_erase_count(struct docg3 *docg3, loff_t from) | ||
753 | { | ||
754 | u8 buf[DOC_LAYOUT_WEAR_SIZE]; | ||
755 | int ret, plane1_erase_count, plane2_erase_count; | ||
756 | int block0, block1, page, ofs; | ||
757 | |||
758 | doc_dbg("doc_get_erase_count(from=%lld, buf=%p)\n", from, buf); | ||
759 | if (from % DOC_LAYOUT_PAGE_SIZE) | ||
760 | return -EINVAL; | ||
761 | calc_block_sector(from, &block0, &block1, &page, &ofs); | ||
762 | if (block1 > docg3->max_block) | ||
763 | return -EINVAL; | ||
764 | |||
765 | ret = doc_reset_seq(docg3); | ||
766 | if (!ret) | ||
767 | ret = doc_read_page_prepare(docg3, block0, block1, page, | ||
768 | ofs + DOC_LAYOUT_WEAR_OFFSET); | ||
769 | if (!ret) | ||
770 | ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_WEAR_SIZE, | ||
771 | buf, 1); | ||
772 | doc_read_page_finish(docg3); | ||
773 | |||
774 | if (ret || (buf[0] != DOC_ERASE_MARK) || (buf[2] != DOC_ERASE_MARK)) | ||
775 | return -EIO; | ||
776 | plane1_erase_count = (u8)(~buf[1]) | ((u8)(~buf[4]) << 8) | ||
777 | | ((u8)(~buf[5]) << 16); | ||
778 | plane2_erase_count = (u8)(~buf[3]) | ((u8)(~buf[6]) << 8) | ||
779 | | ((u8)(~buf[7]) << 16); | ||
780 | |||
781 | return max(plane1_erase_count, plane2_erase_count); | ||
782 | } | ||
783 | |||
784 | /* | ||
785 | * Debug sysfs entries | ||
786 | */ | ||
787 | static int dbg_flashctrl_show(struct seq_file *s, void *p) | ||
788 | { | ||
789 | struct docg3 *docg3 = (struct docg3 *)s->private; | ||
790 | |||
791 | int pos = 0; | ||
792 | u8 fctrl = doc_register_readb(docg3, DOC_FLASHCONTROL); | ||
793 | |||
794 | pos += seq_printf(s, | ||
795 | "FlashControl : 0x%02x (%s,CE# %s,%s,%s,flash %s)\n", | ||
796 | fctrl, | ||
797 | fctrl & DOC_CTRL_VIOLATION ? "protocol violation" : "-", | ||
798 | fctrl & DOC_CTRL_CE ? "active" : "inactive", | ||
799 | fctrl & DOC_CTRL_PROTECTION_ERROR ? "protection error" : "-", | ||
800 | fctrl & DOC_CTRL_SEQUENCE_ERROR ? "sequence error" : "-", | ||
801 | fctrl & DOC_CTRL_FLASHREADY ? "ready" : "not ready"); | ||
802 | return pos; | ||
803 | } | ||
804 | DEBUGFS_RO_ATTR(flashcontrol, dbg_flashctrl_show); | ||
805 | |||
806 | static int dbg_asicmode_show(struct seq_file *s, void *p) | ||
807 | { | ||
808 | struct docg3 *docg3 = (struct docg3 *)s->private; | ||
809 | |||
810 | int pos = 0; | ||
811 | int pctrl = doc_register_readb(docg3, DOC_ASICMODE); | ||
812 | int mode = pctrl & 0x03; | ||
813 | |||
814 | pos += seq_printf(s, | ||
815 | "%04x : RAM_WE=%d,RSTIN_RESET=%d,BDETCT_RESET=%d,WRITE_ENABLE=%d,POWERDOWN=%d,MODE=%d%d (", | ||
816 | pctrl, | ||
817 | pctrl & DOC_ASICMODE_RAM_WE ? 1 : 0, | ||
818 | pctrl & DOC_ASICMODE_RSTIN_RESET ? 1 : 0, | ||
819 | pctrl & DOC_ASICMODE_BDETCT_RESET ? 1 : 0, | ||
820 | pctrl & DOC_ASICMODE_MDWREN ? 1 : 0, | ||
821 | pctrl & DOC_ASICMODE_POWERDOWN ? 1 : 0, | ||
822 | mode >> 1, mode & 0x1); | ||
823 | |||
824 | switch (mode) { | ||
825 | case DOC_ASICMODE_RESET: | ||
826 | pos += seq_printf(s, "reset"); | ||
827 | break; | ||
828 | case DOC_ASICMODE_NORMAL: | ||
829 | pos += seq_printf(s, "normal"); | ||
830 | break; | ||
831 | case DOC_ASICMODE_POWERDOWN: | ||
832 | pos += seq_printf(s, "powerdown"); | ||
833 | break; | ||
834 | } | ||
835 | pos += seq_printf(s, ")\n"); | ||
836 | return pos; | ||
837 | } | ||
838 | DEBUGFS_RO_ATTR(asic_mode, dbg_asicmode_show); | ||
839 | |||
840 | static int dbg_device_id_show(struct seq_file *s, void *p) | ||
841 | { | ||
842 | struct docg3 *docg3 = (struct docg3 *)s->private; | ||
843 | int pos = 0; | ||
844 | int id = doc_register_readb(docg3, DOC_DEVICESELECT); | ||
845 | |||
846 | pos += seq_printf(s, "DeviceId = %d\n", id); | ||
847 | return pos; | ||
848 | } | ||
849 | DEBUGFS_RO_ATTR(device_id, dbg_device_id_show); | ||
850 | |||
851 | static int dbg_protection_show(struct seq_file *s, void *p) | ||
852 | { | ||
853 | struct docg3 *docg3 = (struct docg3 *)s->private; | ||
854 | int pos = 0; | ||
855 | int protect = doc_register_readb(docg3, DOC_PROTECTION); | ||
856 | int dps0 = doc_register_readb(docg3, DOC_DPS0_STATUS); | ||
857 | int dps0_low = doc_register_readb(docg3, DOC_DPS0_ADDRLOW); | ||
858 | int dps0_high = doc_register_readb(docg3, DOC_DPS0_ADDRHIGH); | ||
859 | int dps1 = doc_register_readb(docg3, DOC_DPS1_STATUS); | ||
860 | int dps1_low = doc_register_readb(docg3, DOC_DPS1_ADDRLOW); | ||
861 | int dps1_high = doc_register_readb(docg3, DOC_DPS1_ADDRHIGH); | ||
862 | |||
863 | pos += seq_printf(s, "Protection = 0x%02x (", | ||
864 | protect); | ||
865 | if (protect & DOC_PROTECT_FOUNDRY_OTP_LOCK) | ||
866 | pos += seq_printf(s, "FOUNDRY_OTP_LOCK,"); | ||
867 | if (protect & DOC_PROTECT_CUSTOMER_OTP_LOCK) | ||
868 | pos += seq_printf(s, "CUSTOMER_OTP_LOCK,"); | ||
869 | if (protect & DOC_PROTECT_LOCK_INPUT) | ||
870 | pos += seq_printf(s, "LOCK_INPUT,"); | ||
871 | if (protect & DOC_PROTECT_STICKY_LOCK) | ||
872 | pos += seq_printf(s, "STICKY_LOCK,"); | ||
873 | if (protect & DOC_PROTECT_PROTECTION_ENABLED) | ||
874 | pos += seq_printf(s, "PROTECTION ON,"); | ||
875 | if (protect & DOC_PROTECT_IPL_DOWNLOAD_LOCK) | ||
876 | pos += seq_printf(s, "IPL_DOWNLOAD_LOCK,"); | ||
877 | if (protect & DOC_PROTECT_PROTECTION_ERROR) | ||
878 | pos += seq_printf(s, "PROTECT_ERR,"); | ||
879 | else | ||
880 | pos += seq_printf(s, "NO_PROTECT_ERR"); | ||
881 | pos += seq_printf(s, ")\n"); | ||
882 | |||
883 | pos += seq_printf(s, "DPS0 = 0x%02x : " | ||
884 | "Protected area [0x%x - 0x%x] : OTP=%d, READ=%d, " | ||
885 | "WRITE=%d, HW_LOCK=%d, KEY_OK=%d\n", | ||
886 | dps0, dps0_low, dps0_high, | ||
887 | !!(dps0 & DOC_DPS_OTP_PROTECTED), | ||
888 | !!(dps0 & DOC_DPS_READ_PROTECTED), | ||
889 | !!(dps0 & DOC_DPS_WRITE_PROTECTED), | ||
890 | !!(dps0 & DOC_DPS_HW_LOCK_ENABLED), | ||
891 | !!(dps0 & DOC_DPS_KEY_OK)); | ||
892 | pos += seq_printf(s, "DPS1 = 0x%02x : " | ||
893 | "Protected area [0x%x - 0x%x] : OTP=%d, READ=%d, " | ||
894 | "WRITE=%d, HW_LOCK=%d, KEY_OK=%d\n", | ||
895 | dps1, dps1_low, dps1_high, | ||
896 | !!(dps1 & DOC_DPS_OTP_PROTECTED), | ||
897 | !!(dps1 & DOC_DPS_READ_PROTECTED), | ||
898 | !!(dps1 & DOC_DPS_WRITE_PROTECTED), | ||
899 | !!(dps1 & DOC_DPS_HW_LOCK_ENABLED), | ||
900 | !!(dps1 & DOC_DPS_KEY_OK)); | ||
901 | return pos; | ||
902 | } | ||
903 | DEBUGFS_RO_ATTR(protection, dbg_protection_show); | ||
904 | |||
905 | static int __init doc_dbg_register(struct docg3 *docg3) | ||
906 | { | ||
907 | struct dentry *root, *entry; | ||
908 | |||
909 | root = debugfs_create_dir("docg3", NULL); | ||
910 | if (!root) | ||
911 | return -ENOMEM; | ||
912 | |||
913 | entry = debugfs_create_file("flashcontrol", S_IRUSR, root, docg3, | ||
914 | &flashcontrol_fops); | ||
915 | if (entry) | ||
916 | entry = debugfs_create_file("asic_mode", S_IRUSR, root, | ||
917 | docg3, &asic_mode_fops); | ||
918 | if (entry) | ||
919 | entry = debugfs_create_file("device_id", S_IRUSR, root, | ||
920 | docg3, &device_id_fops); | ||
921 | if (entry) | ||
922 | entry = debugfs_create_file("protection", S_IRUSR, root, | ||
923 | docg3, &protection_fops); | ||
924 | if (entry) { | ||
925 | docg3->debugfs_root = root; | ||
926 | return 0; | ||
927 | } else { | ||
928 | debugfs_remove_recursive(root); | ||
929 | return -ENOMEM; | ||
930 | } | ||
931 | } | ||
932 | |||
933 | static void __exit doc_dbg_unregister(struct docg3 *docg3) | ||
934 | { | ||
935 | debugfs_remove_recursive(docg3->debugfs_root); | ||
936 | } | ||
937 | |||
938 | /** | ||
939 | * doc_set_driver_info - Fill the mtd_info structure and docg3 structure | ||
940 | * @chip_id: The chip ID of the supported chip | ||
941 | * @mtd: The structure to fill | ||
942 | */ | ||
943 | static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd) | ||
944 | { | ||
945 | struct docg3 *docg3 = mtd->priv; | ||
946 | int cfg; | ||
947 | |||
948 | cfg = doc_register_readb(docg3, DOC_CONFIGURATION); | ||
949 | docg3->if_cfg = (cfg & DOC_CONF_IF_CFG ? 1 : 0); | ||
950 | |||
951 | switch (chip_id) { | ||
952 | case DOC_CHIPID_G3: | ||
953 | mtd->name = "DiskOnChip G3"; | ||
954 | docg3->max_block = 2047; | ||
955 | break; | ||
956 | } | ||
957 | mtd->type = MTD_NANDFLASH; | ||
958 | /* | ||
959 | * Once write methods are added, the correct flags will be set. | ||
960 | * mtd->flags = MTD_CAP_NANDFLASH; | ||
961 | */ | ||
962 | mtd->flags = MTD_CAP_ROM; | ||
963 | mtd->size = (docg3->max_block + 1) * DOC_LAYOUT_BLOCK_SIZE; | ||
964 | mtd->erasesize = DOC_LAYOUT_BLOCK_SIZE * DOC_LAYOUT_NBPLANES; | ||
965 | mtd->writesize = DOC_LAYOUT_PAGE_SIZE; | ||
966 | mtd->oobsize = DOC_LAYOUT_OOB_SIZE; | ||
967 | mtd->owner = THIS_MODULE; | ||
968 | mtd->erase = NULL; | ||
969 | mtd->point = NULL; | ||
970 | mtd->unpoint = NULL; | ||
971 | mtd->read = doc_read; | ||
972 | mtd->write = NULL; | ||
973 | mtd->read_oob = doc_read_oob; | ||
974 | mtd->write_oob = NULL; | ||
975 | mtd->sync = NULL; | ||
976 | mtd->block_isbad = doc_block_isbad; | ||
977 | } | ||
978 | |||
979 | /** | ||
980 | * doc_probe - Probe the IO space for a DiskOnChip G3 chip | ||
981 | * @pdev: platform device | ||
982 | * | ||
983 | * Probes for a G3 chip at the specified IO space in the platform data | ||
984 | * ressources. | ||
985 | * | ||
986 | * Returns 0 on success, -ENOMEM, -ENXIO on error | ||
987 | */ | ||
988 | static int __init docg3_probe(struct platform_device *pdev) | ||
989 | { | ||
990 | struct device *dev = &pdev->dev; | ||
991 | struct docg3 *docg3; | ||
992 | struct mtd_info *mtd; | ||
993 | struct resource *ress; | ||
994 | int ret, bbt_nbpages; | ||
995 | u16 chip_id, chip_id_inv; | ||
996 | |||
997 | ret = -ENOMEM; | ||
998 | docg3 = kzalloc(sizeof(struct docg3), GFP_KERNEL); | ||
999 | if (!docg3) | ||
1000 | goto nomem1; | ||
1001 | mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); | ||
1002 | if (!mtd) | ||
1003 | goto nomem2; | ||
1004 | mtd->priv = docg3; | ||
1005 | |||
1006 | ret = -ENXIO; | ||
1007 | ress = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1008 | if (!ress) { | ||
1009 | dev_err(dev, "No I/O memory resource defined\n"); | ||
1010 | goto noress; | ||
1011 | } | ||
1012 | docg3->base = ioremap(ress->start, DOC_IOSPACE_SIZE); | ||
1013 | |||
1014 | docg3->dev = &pdev->dev; | ||
1015 | docg3->device_id = 0; | ||
1016 | doc_set_device_id(docg3, docg3->device_id); | ||
1017 | doc_set_asic_mode(docg3, DOC_ASICMODE_RESET); | ||
1018 | doc_set_asic_mode(docg3, DOC_ASICMODE_NORMAL); | ||
1019 | |||
1020 | chip_id = doc_register_readw(docg3, DOC_CHIPID); | ||
1021 | chip_id_inv = doc_register_readw(docg3, DOC_CHIPID_INV); | ||
1022 | |||
1023 | ret = -ENODEV; | ||
1024 | if (chip_id != (u16)(~chip_id_inv)) { | ||
1025 | doc_info("No device found at IO addr %p\n", | ||
1026 | (void *)ress->start); | ||
1027 | goto nochipfound; | ||
1028 | } | ||
1029 | |||
1030 | switch (chip_id) { | ||
1031 | case DOC_CHIPID_G3: | ||
1032 | doc_info("Found a G3 DiskOnChip at addr %p\n", | ||
1033 | (void *)ress->start); | ||
1034 | break; | ||
1035 | default: | ||
1036 | doc_err("Chip id %04x is not a DiskOnChip G3 chip\n", chip_id); | ||
1037 | goto nochipfound; | ||
1038 | } | ||
1039 | |||
1040 | doc_set_driver_info(chip_id, mtd); | ||
1041 | platform_set_drvdata(pdev, mtd); | ||
1042 | |||
1043 | ret = -ENOMEM; | ||
1044 | bbt_nbpages = DIV_ROUND_UP(docg3->max_block + 1, | ||
1045 | 8 * DOC_LAYOUT_PAGE_SIZE); | ||
1046 | docg3->bbt = kzalloc(bbt_nbpages * DOC_LAYOUT_PAGE_SIZE, GFP_KERNEL); | ||
1047 | if (!docg3->bbt) | ||
1048 | goto nochipfound; | ||
1049 | doc_reload_bbt(docg3); | ||
1050 | |||
1051 | ret = mtd_device_parse_register(mtd, part_probes, | ||
1052 | NULL, NULL, 0); | ||
1053 | if (ret) | ||
1054 | goto register_error; | ||
1055 | |||
1056 | doc_dbg_register(docg3); | ||
1057 | return 0; | ||
1058 | |||
1059 | register_error: | ||
1060 | kfree(docg3->bbt); | ||
1061 | nochipfound: | ||
1062 | iounmap(docg3->base); | ||
1063 | noress: | ||
1064 | kfree(mtd); | ||
1065 | nomem2: | ||
1066 | kfree(docg3); | ||
1067 | nomem1: | ||
1068 | return ret; | ||
1069 | } | ||
1070 | |||
1071 | /** | ||
1072 | * docg3_release - Release the driver | ||
1073 | * @pdev: the platform device | ||
1074 | * | ||
1075 | * Returns 0 | ||
1076 | */ | ||
1077 | static int __exit docg3_release(struct platform_device *pdev) | ||
1078 | { | ||
1079 | struct mtd_info *mtd = platform_get_drvdata(pdev); | ||
1080 | struct docg3 *docg3 = mtd->priv; | ||
1081 | |||
1082 | doc_dbg_unregister(docg3); | ||
1083 | mtd_device_unregister(mtd); | ||
1084 | iounmap(docg3->base); | ||
1085 | kfree(docg3->bbt); | ||
1086 | kfree(docg3); | ||
1087 | kfree(mtd); | ||
1088 | return 0; | ||
1089 | } | ||
1090 | |||
1091 | static struct platform_driver g3_driver = { | ||
1092 | .driver = { | ||
1093 | .name = "docg3", | ||
1094 | .owner = THIS_MODULE, | ||
1095 | }, | ||
1096 | .remove = __exit_p(docg3_release), | ||
1097 | }; | ||
1098 | |||
1099 | static int __init docg3_init(void) | ||
1100 | { | ||
1101 | return platform_driver_probe(&g3_driver, docg3_probe); | ||
1102 | } | ||
1103 | module_init(docg3_init); | ||
1104 | |||
1105 | |||
1106 | static void __exit docg3_exit(void) | ||
1107 | { | ||
1108 | platform_driver_unregister(&g3_driver); | ||
1109 | } | ||
1110 | module_exit(docg3_exit); | ||
1111 | |||
1112 | MODULE_LICENSE("GPL"); | ||
1113 | MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik@free.fr>"); | ||
1114 | MODULE_DESCRIPTION("MTD driver for DiskOnChip G3"); | ||