Commit 79b4c08fc42cd7f6b51183b5338f337116c6fdf3
Committed by
Jagan Teki
1 parent
7853d76b0b
Exists in
v2017.01-smarct4x
and in
34 other branches
dm: sf: Add Atmel DataFlash spi flash driver
Atmel DataFlash chips have commands different from common spi flash commands. Atmel DataFlash also have special page-size. This driver add support for accessing Atmel DataFlash. It is based on the Driver Model. Example: => sf probe 1:0 SPI DataFlash: Detected AT45DB021B with page size 264 Bytes, erase size 264 Bytes, total 264 KiB, revision d => sf erase 0 42000 SF: 270336 bytes @ 0x0 Erased: OK => mw.l 82000000 45444342 20000 => sf write 82000000 0 42000 SF: 270336 bytes @ 0x0 Written: OK => sf read 83000000 0 42000 SF: 270336 bytes @ 0x0 Read: OK => cmp.b 82000000 83000000 42000 Total of 270336 byte(s) were the same Signed-off-by: Haikun Wang <haikun.wang@freescale.com> Tested-by: Haikun Wang <haikun.wang@freescale.com> Reviewed-by: Simon Glass <sjg@chromium.org> Reviewed-by: Chakra Divi <cdivi@openedev.com> Reviewed-by: Jagan Teki <jteki@openedev.com>
Showing 2 changed files with 712 additions and 0 deletions Side-by-side Diff
drivers/mtd/spi/Makefile
drivers/mtd/spi/sf_dataflash.c
1 | +/* | |
2 | + * | |
3 | + * Atmel DataFlash probing | |
4 | + * | |
5 | + * Copyright (C) 2004-2009, 2015 Freescale Semiconductor, Inc. | |
6 | + * Haikun Wang (haikun.wang@freescale.com) | |
7 | + * | |
8 | + * SPDX-License-Identifier: GPL-2.0+ | |
9 | +*/ | |
10 | +#include <common.h> | |
11 | +#include <dm.h> | |
12 | +#include <errno.h> | |
13 | +#include <fdtdec.h> | |
14 | +#include <spi.h> | |
15 | +#include <spi_flash.h> | |
16 | +#include <div64.h> | |
17 | +#include <linux/err.h> | |
18 | +#include <linux/math64.h> | |
19 | + | |
20 | +#include "sf_internal.h" | |
21 | + | |
22 | +/* | |
23 | + * DataFlash is a kind of SPI flash. Most AT45 chips have two buffers in | |
24 | + * each chip, which may be used for double buffered I/O; but this driver | |
25 | + * doesn't (yet) use these for any kind of i/o overlap or prefetching. | |
26 | + * | |
27 | + * Sometimes DataFlash is packaged in MMC-format cards, although the | |
28 | + * MMC stack can't (yet?) distinguish between MMC and DataFlash | |
29 | + * protocols during enumeration. | |
30 | + */ | |
31 | + | |
32 | +/* reads can bypass the buffers */ | |
33 | +#define OP_READ_CONTINUOUS 0xE8 | |
34 | +#define OP_READ_PAGE 0xD2 | |
35 | + | |
36 | +/* group B requests can run even while status reports "busy" */ | |
37 | +#define OP_READ_STATUS 0xD7 /* group B */ | |
38 | + | |
39 | +/* move data between host and buffer */ | |
40 | +#define OP_READ_BUFFER1 0xD4 /* group B */ | |
41 | +#define OP_READ_BUFFER2 0xD6 /* group B */ | |
42 | +#define OP_WRITE_BUFFER1 0x84 /* group B */ | |
43 | +#define OP_WRITE_BUFFER2 0x87 /* group B */ | |
44 | + | |
45 | +/* erasing flash */ | |
46 | +#define OP_ERASE_PAGE 0x81 | |
47 | +#define OP_ERASE_BLOCK 0x50 | |
48 | + | |
49 | +/* move data between buffer and flash */ | |
50 | +#define OP_TRANSFER_BUF1 0x53 | |
51 | +#define OP_TRANSFER_BUF2 0x55 | |
52 | +#define OP_MREAD_BUFFER1 0xD4 | |
53 | +#define OP_MREAD_BUFFER2 0xD6 | |
54 | +#define OP_MWERASE_BUFFER1 0x83 | |
55 | +#define OP_MWERASE_BUFFER2 0x86 | |
56 | +#define OP_MWRITE_BUFFER1 0x88 /* sector must be pre-erased */ | |
57 | +#define OP_MWRITE_BUFFER2 0x89 /* sector must be pre-erased */ | |
58 | + | |
59 | +/* write to buffer, then write-erase to flash */ | |
60 | +#define OP_PROGRAM_VIA_BUF1 0x82 | |
61 | +#define OP_PROGRAM_VIA_BUF2 0x85 | |
62 | + | |
63 | +/* compare buffer to flash */ | |
64 | +#define OP_COMPARE_BUF1 0x60 | |
65 | +#define OP_COMPARE_BUF2 0x61 | |
66 | + | |
67 | +/* read flash to buffer, then write-erase to flash */ | |
68 | +#define OP_REWRITE_VIA_BUF1 0x58 | |
69 | +#define OP_REWRITE_VIA_BUF2 0x59 | |
70 | + | |
71 | +/* | |
72 | + * newer chips report JEDEC manufacturer and device IDs; chip | |
73 | + * serial number and OTP bits; and per-sector writeprotect. | |
74 | + */ | |
75 | +#define OP_READ_ID 0x9F | |
76 | +#define OP_READ_SECURITY 0x77 | |
77 | +#define OP_WRITE_SECURITY_REVC 0x9A | |
78 | +#define OP_WRITE_SECURITY 0x9B /* revision D */ | |
79 | + | |
80 | + | |
81 | +struct dataflash { | |
82 | + uint8_t command[16]; | |
83 | + unsigned short page_offset; /* offset in flash address */ | |
84 | +}; | |
85 | + | |
86 | +/* | |
87 | + * Return the status of the DataFlash device. | |
88 | + */ | |
89 | +static inline int dataflash_status(struct spi_slave *spi) | |
90 | +{ | |
91 | + int ret; | |
92 | + u8 status; | |
93 | + /* | |
94 | + * NOTE: at45db321c over 25 MHz wants to write | |
95 | + * a dummy byte after the opcode... | |
96 | + */ | |
97 | + ret = spi_flash_cmd(spi, OP_READ_STATUS, &status, 1); | |
98 | + return ret ? -EIO : status; | |
99 | +} | |
100 | + | |
101 | +/* | |
102 | + * Poll the DataFlash device until it is READY. | |
103 | + * This usually takes 5-20 msec or so; more for sector erase. | |
104 | + * ready: return > 0 | |
105 | + */ | |
106 | +static int dataflash_waitready(struct spi_slave *spi) | |
107 | +{ | |
108 | + int status; | |
109 | + int timeout = 2 * CONFIG_SYS_HZ; | |
110 | + int timebase; | |
111 | + | |
112 | + timebase = get_timer(0); | |
113 | + do { | |
114 | + status = dataflash_status(spi); | |
115 | + if (status < 0) | |
116 | + status = 0; | |
117 | + | |
118 | + if (status & (1 << 7)) /* RDY/nBSY */ | |
119 | + return status; | |
120 | + | |
121 | + mdelay(3); | |
122 | + } while (get_timer(timebase) < timeout); | |
123 | + | |
124 | + return -ETIME; | |
125 | +} | |
126 | + | |
127 | +/* | |
128 | + * Erase pages of flash. | |
129 | + */ | |
130 | +static int spi_dataflash_erase(struct udevice *dev, u32 offset, size_t len) | |
131 | +{ | |
132 | + struct dataflash *dataflash; | |
133 | + struct spi_flash *spi_flash; | |
134 | + struct spi_slave *spi; | |
135 | + unsigned blocksize; | |
136 | + uint8_t *command; | |
137 | + uint32_t rem; | |
138 | + int status; | |
139 | + | |
140 | + dataflash = dev_get_priv(dev); | |
141 | + spi_flash = dev_get_uclass_priv(dev); | |
142 | + spi = spi_flash->spi; | |
143 | + | |
144 | + blocksize = spi_flash->page_size << 3; | |
145 | + | |
146 | + memset(dataflash->command, 0 , sizeof(dataflash->command)); | |
147 | + command = dataflash->command; | |
148 | + | |
149 | + debug("%s: erase addr=0x%x len 0x%x\n", dev->name, offset, len); | |
150 | + | |
151 | + div_u64_rem(len, spi_flash->page_size, &rem); | |
152 | + if (rem) | |
153 | + return -EINVAL; | |
154 | + div_u64_rem(offset, spi_flash->page_size, &rem); | |
155 | + if (rem) | |
156 | + return -EINVAL; | |
157 | + | |
158 | + status = spi_claim_bus(spi); | |
159 | + if (status) { | |
160 | + debug("SPI DATAFLASH: unable to claim SPI bus\n"); | |
161 | + return status; | |
162 | + } | |
163 | + | |
164 | + while (len > 0) { | |
165 | + unsigned int pageaddr; | |
166 | + int do_block; | |
167 | + /* | |
168 | + * Calculate flash page address; use block erase (for speed) if | |
169 | + * we're at a block boundary and need to erase the whole block. | |
170 | + */ | |
171 | + pageaddr = div_u64(offset, spi_flash->page_size); | |
172 | + do_block = (pageaddr & 0x7) == 0 && len >= blocksize; | |
173 | + pageaddr = pageaddr << dataflash->page_offset; | |
174 | + | |
175 | + command[0] = do_block ? OP_ERASE_BLOCK : OP_ERASE_PAGE; | |
176 | + command[1] = (uint8_t)(pageaddr >> 16); | |
177 | + command[2] = (uint8_t)(pageaddr >> 8); | |
178 | + command[3] = 0; | |
179 | + | |
180 | + debug("%s ERASE %s: (%x) %x %x %x [%d]\n", | |
181 | + dev->name, do_block ? "block" : "page", | |
182 | + command[0], command[1], command[2], command[3], | |
183 | + pageaddr); | |
184 | + | |
185 | + status = spi_flash_cmd_write(spi, command, 4, NULL, 0); | |
186 | + if (status < 0) { | |
187 | + debug("%s: erase send command error!\n", dev->name); | |
188 | + return -EIO; | |
189 | + } | |
190 | + | |
191 | + status = dataflash_waitready(spi); | |
192 | + if (status < 0) { | |
193 | + debug("%s: erase waitready error!\n", dev->name); | |
194 | + return status; | |
195 | + } | |
196 | + | |
197 | + if (do_block) { | |
198 | + offset += blocksize; | |
199 | + len -= blocksize; | |
200 | + } else { | |
201 | + offset += spi_flash->page_size; | |
202 | + len -= spi_flash->page_size; | |
203 | + } | |
204 | + } | |
205 | + | |
206 | + spi_release_bus(spi); | |
207 | + | |
208 | + return 0; | |
209 | +} | |
210 | + | |
211 | +/* | |
212 | + * Read from the DataFlash device. | |
213 | + * offset : Start offset in flash device | |
214 | + * len : Amount to read | |
215 | + * buf : Buffer containing the data | |
216 | + */ | |
217 | +static int spi_dataflash_read(struct udevice *dev, u32 offset, size_t len, | |
218 | + void *buf) | |
219 | +{ | |
220 | + struct dataflash *dataflash; | |
221 | + struct spi_flash *spi_flash; | |
222 | + struct spi_slave *spi; | |
223 | + unsigned int addr; | |
224 | + uint8_t *command; | |
225 | + int status; | |
226 | + | |
227 | + dataflash = dev_get_priv(dev); | |
228 | + spi_flash = dev_get_uclass_priv(dev); | |
229 | + spi = spi_flash->spi; | |
230 | + | |
231 | + memset(dataflash->command, 0 , sizeof(dataflash->command)); | |
232 | + command = dataflash->command; | |
233 | + | |
234 | + debug("%s: erase addr=0x%x len 0x%x\n", dev->name, offset, len); | |
235 | + debug("READ: (%x) %x %x %x\n", | |
236 | + command[0], command[1], command[2], command[3]); | |
237 | + | |
238 | + /* Calculate flash page/byte address */ | |
239 | + addr = (((unsigned)offset / spi_flash->page_size) | |
240 | + << dataflash->page_offset) | |
241 | + + ((unsigned)offset % spi_flash->page_size); | |
242 | + | |
243 | + status = spi_claim_bus(spi); | |
244 | + if (status) { | |
245 | + debug("SPI DATAFLASH: unable to claim SPI bus\n"); | |
246 | + return status; | |
247 | + } | |
248 | + | |
249 | + /* | |
250 | + * Continuous read, max clock = f(car) which may be less than | |
251 | + * the peak rate available. Some chips support commands with | |
252 | + * fewer "don't care" bytes. Both buffers stay unchanged. | |
253 | + */ | |
254 | + command[0] = OP_READ_CONTINUOUS; | |
255 | + command[1] = (uint8_t)(addr >> 16); | |
256 | + command[2] = (uint8_t)(addr >> 8); | |
257 | + command[3] = (uint8_t)(addr >> 0); | |
258 | + | |
259 | + /* plus 4 "don't care" bytes, command len: 4 + 4 "don't care" bytes */ | |
260 | + status = spi_flash_cmd_read(spi, command, 8, buf, len); | |
261 | + | |
262 | + spi_release_bus(spi); | |
263 | + | |
264 | + return status; | |
265 | +} | |
266 | + | |
267 | +/* | |
268 | + * Write to the DataFlash device. | |
269 | + * offset : Start offset in flash device | |
270 | + * len : Amount to write | |
271 | + * buf : Buffer containing the data | |
272 | + */ | |
273 | +int spi_dataflash_write(struct udevice *dev, u32 offset, size_t len, | |
274 | + const void *buf) | |
275 | +{ | |
276 | + struct dataflash *dataflash; | |
277 | + struct spi_flash *spi_flash; | |
278 | + struct spi_slave *spi; | |
279 | + uint8_t *command; | |
280 | + unsigned int pageaddr, addr, to, writelen; | |
281 | + size_t remaining = len; | |
282 | + u_char *writebuf = (u_char *)buf; | |
283 | + int status = -EINVAL; | |
284 | + | |
285 | + dataflash = dev_get_priv(dev); | |
286 | + spi_flash = dev_get_uclass_priv(dev); | |
287 | + spi = spi_flash->spi; | |
288 | + | |
289 | + memset(dataflash->command, 0 , sizeof(dataflash->command)); | |
290 | + command = dataflash->command; | |
291 | + | |
292 | + debug("%s: write 0x%x..0x%x\n", dev->name, offset, (offset + len)); | |
293 | + | |
294 | + pageaddr = ((unsigned)offset / spi_flash->page_size); | |
295 | + to = ((unsigned)offset % spi_flash->page_size); | |
296 | + if (to + len > spi_flash->page_size) | |
297 | + writelen = spi_flash->page_size - to; | |
298 | + else | |
299 | + writelen = len; | |
300 | + | |
301 | + status = spi_claim_bus(spi); | |
302 | + if (status) { | |
303 | + debug("SPI DATAFLASH: unable to claim SPI bus\n"); | |
304 | + return status; | |
305 | + } | |
306 | + | |
307 | + while (remaining > 0) { | |
308 | + debug("write @ %d:%d len=%d\n", pageaddr, to, writelen); | |
309 | + | |
310 | + /* | |
311 | + * REVISIT: | |
312 | + * (a) each page in a sector must be rewritten at least | |
313 | + * once every 10K sibling erase/program operations. | |
314 | + * (b) for pages that are already erased, we could | |
315 | + * use WRITE+MWRITE not PROGRAM for ~30% speedup. | |
316 | + * (c) WRITE to buffer could be done while waiting for | |
317 | + * a previous MWRITE/MWERASE to complete ... | |
318 | + * (d) error handling here seems to be mostly missing. | |
319 | + * | |
320 | + * Two persistent bits per page, plus a per-sector counter, | |
321 | + * could support (a) and (b) ... we might consider using | |
322 | + * the second half of sector zero, which is just one block, | |
323 | + * to track that state. (On AT91, that sector should also | |
324 | + * support boot-from-DataFlash.) | |
325 | + */ | |
326 | + | |
327 | + addr = pageaddr << dataflash->page_offset; | |
328 | + | |
329 | + /* (1) Maybe transfer partial page to Buffer1 */ | |
330 | + if (writelen != spi_flash->page_size) { | |
331 | + command[0] = OP_TRANSFER_BUF1; | |
332 | + command[1] = (addr & 0x00FF0000) >> 16; | |
333 | + command[2] = (addr & 0x0000FF00) >> 8; | |
334 | + command[3] = 0; | |
335 | + | |
336 | + debug("TRANSFER: (%x) %x %x %x\n", | |
337 | + command[0], command[1], command[2], command[3]); | |
338 | + | |
339 | + status = spi_flash_cmd_write(spi, command, 4, NULL, 0); | |
340 | + if (status < 0) { | |
341 | + debug("%s: write(<pagesize) command error!\n", | |
342 | + dev->name); | |
343 | + return -EIO; | |
344 | + } | |
345 | + | |
346 | + status = dataflash_waitready(spi); | |
347 | + if (status < 0) { | |
348 | + debug("%s: write(<pagesize) waitready error!\n", | |
349 | + dev->name); | |
350 | + return status; | |
351 | + } | |
352 | + } | |
353 | + | |
354 | + /* (2) Program full page via Buffer1 */ | |
355 | + addr += to; | |
356 | + command[0] = OP_PROGRAM_VIA_BUF1; | |
357 | + command[1] = (addr & 0x00FF0000) >> 16; | |
358 | + command[2] = (addr & 0x0000FF00) >> 8; | |
359 | + command[3] = (addr & 0x000000FF); | |
360 | + | |
361 | + debug("PROGRAM: (%x) %x %x %x\n", | |
362 | + command[0], command[1], command[2], command[3]); | |
363 | + | |
364 | + status = spi_flash_cmd_write(spi, command, | |
365 | + 4, writebuf, writelen); | |
366 | + if (status < 0) { | |
367 | + debug("%s: write send command error!\n", dev->name); | |
368 | + return -EIO; | |
369 | + } | |
370 | + | |
371 | + status = dataflash_waitready(spi); | |
372 | + if (status < 0) { | |
373 | + debug("%s: write waitready error!\n", dev->name); | |
374 | + return status; | |
375 | + } | |
376 | + | |
377 | +#ifdef CONFIG_SPI_DATAFLASH_WRITE_VERIFY | |
378 | + /* (3) Compare to Buffer1 */ | |
379 | + addr = pageaddr << dataflash->page_offset; | |
380 | + command[0] = OP_COMPARE_BUF1; | |
381 | + command[1] = (addr & 0x00FF0000) >> 16; | |
382 | + command[2] = (addr & 0x0000FF00) >> 8; | |
383 | + command[3] = 0; | |
384 | + | |
385 | + debug("COMPARE: (%x) %x %x %x\n", | |
386 | + command[0], command[1], command[2], command[3]); | |
387 | + | |
388 | + status = spi_flash_cmd_write(spi, command, | |
389 | + 4, writebuf, writelen); | |
390 | + if (status < 0) { | |
391 | + debug("%s: write(compare) send command error!\n", | |
392 | + dev->name); | |
393 | + return -EIO; | |
394 | + } | |
395 | + | |
396 | + status = dataflash_waitready(spi); | |
397 | + | |
398 | + /* Check result of the compare operation */ | |
399 | + if (status & (1 << 6)) { | |
400 | + printf("SPI DataFlash: write compare page %u, err %d\n", | |
401 | + pageaddr, status); | |
402 | + remaining = 0; | |
403 | + status = -EIO; | |
404 | + break; | |
405 | + } else { | |
406 | + status = 0; | |
407 | + } | |
408 | + | |
409 | +#endif /* CONFIG_SPI_DATAFLASH_WRITE_VERIFY */ | |
410 | + remaining = remaining - writelen; | |
411 | + pageaddr++; | |
412 | + to = 0; | |
413 | + writebuf += writelen; | |
414 | + | |
415 | + if (remaining > spi_flash->page_size) | |
416 | + writelen = spi_flash->page_size; | |
417 | + else | |
418 | + writelen = remaining; | |
419 | + } | |
420 | + | |
421 | + spi_release_bus(spi); | |
422 | + | |
423 | + return 0; | |
424 | +} | |
425 | + | |
426 | +static int add_dataflash(struct udevice *dev, char *name, int nr_pages, | |
427 | + int pagesize, int pageoffset, char revision) | |
428 | +{ | |
429 | + struct spi_flash *spi_flash; | |
430 | + struct dataflash *dataflash; | |
431 | + | |
432 | + dataflash = dev_get_priv(dev); | |
433 | + spi_flash = dev_get_uclass_priv(dev); | |
434 | + | |
435 | + dataflash->page_offset = pageoffset; | |
436 | + | |
437 | + spi_flash->name = name; | |
438 | + spi_flash->page_size = pagesize; | |
439 | + spi_flash->size = nr_pages * pagesize; | |
440 | + spi_flash->erase_size = pagesize; | |
441 | + | |
442 | +#ifndef CONFIG_SPL_BUILD | |
443 | + printf("SPI DataFlash: Detected %s with page size ", spi_flash->name); | |
444 | + print_size(spi_flash->page_size, ", erase size "); | |
445 | + print_size(spi_flash->erase_size, ", total "); | |
446 | + print_size(spi_flash->size, ""); | |
447 | + printf(", revision %c", revision); | |
448 | + puts("\n"); | |
449 | +#endif | |
450 | + | |
451 | + return 0; | |
452 | +} | |
453 | + | |
454 | +struct flash_info { | |
455 | + char *name; | |
456 | + | |
457 | + /* | |
458 | + * JEDEC id has a high byte of zero plus three data bytes: | |
459 | + * the manufacturer id, then a two byte device id. | |
460 | + */ | |
461 | + uint32_t jedec_id; | |
462 | + | |
463 | + /* The size listed here is what works with OP_ERASE_PAGE. */ | |
464 | + unsigned nr_pages; | |
465 | + uint16_t pagesize; | |
466 | + uint16_t pageoffset; | |
467 | + | |
468 | + uint16_t flags; | |
469 | +#define SUP_POW2PS 0x0002 /* supports 2^N byte pages */ | |
470 | +#define IS_POW2PS 0x0001 /* uses 2^N byte pages */ | |
471 | +}; | |
472 | + | |
473 | +static struct flash_info dataflash_data[] = { | |
474 | + /* | |
475 | + * NOTE: chips with SUP_POW2PS (rev D and up) need two entries, | |
476 | + * one with IS_POW2PS and the other without. The entry with the | |
477 | + * non-2^N byte page size can't name exact chip revisions without | |
478 | + * losing backwards compatibility for cmdlinepart. | |
479 | + * | |
480 | + * Those two entries have different name spelling format in order to | |
481 | + * show their difference obviously. | |
482 | + * The upper case refer to the chip isn't in normal 2^N bytes page-size | |
483 | + * mode. | |
484 | + * The lower case refer to the chip is in normal 2^N bytes page-size | |
485 | + * mode. | |
486 | + * | |
487 | + * These newer chips also support 128-byte security registers (with | |
488 | + * 64 bytes one-time-programmable) and software write-protection. | |
489 | + */ | |
490 | + { "AT45DB011B", 0x1f2200, 512, 264, 9, SUP_POW2PS}, | |
491 | + { "at45db011d", 0x1f2200, 512, 256, 8, SUP_POW2PS | IS_POW2PS}, | |
492 | + | |
493 | + { "AT45DB021B", 0x1f2300, 1024, 264, 9, SUP_POW2PS}, | |
494 | + { "at45db021d", 0x1f2300, 1024, 256, 8, SUP_POW2PS | IS_POW2PS}, | |
495 | + | |
496 | + { "AT45DB041x", 0x1f2400, 2048, 264, 9, SUP_POW2PS}, | |
497 | + { "at45db041d", 0x1f2400, 2048, 256, 8, SUP_POW2PS | IS_POW2PS}, | |
498 | + | |
499 | + { "AT45DB081B", 0x1f2500, 4096, 264, 9, SUP_POW2PS}, | |
500 | + { "at45db081d", 0x1f2500, 4096, 256, 8, SUP_POW2PS | IS_POW2PS}, | |
501 | + | |
502 | + { "AT45DB161x", 0x1f2600, 4096, 528, 10, SUP_POW2PS}, | |
503 | + { "at45db161d", 0x1f2600, 4096, 512, 9, SUP_POW2PS | IS_POW2PS}, | |
504 | + | |
505 | + { "AT45DB321x", 0x1f2700, 8192, 528, 10, 0}, /* rev C */ | |
506 | + | |
507 | + { "AT45DB321x", 0x1f2701, 8192, 528, 10, SUP_POW2PS}, | |
508 | + { "at45db321d", 0x1f2701, 8192, 512, 9, SUP_POW2PS | IS_POW2PS}, | |
509 | + | |
510 | + { "AT45DB642x", 0x1f2800, 8192, 1056, 11, SUP_POW2PS}, | |
511 | + { "at45db642d", 0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS}, | |
512 | +}; | |
513 | + | |
514 | +static struct flash_info *jedec_probe(struct spi_slave *spi, u8 *id) | |
515 | +{ | |
516 | + int tmp; | |
517 | + uint32_t jedec; | |
518 | + struct flash_info *info; | |
519 | + int status; | |
520 | + | |
521 | + /* | |
522 | + * JEDEC also defines an optional "extended device information" | |
523 | + * string for after vendor-specific data, after the three bytes | |
524 | + * we use here. Supporting some chips might require using it. | |
525 | + * | |
526 | + * If the vendor ID isn't Atmel's (0x1f), assume this call failed. | |
527 | + * That's not an error; only rev C and newer chips handle it, and | |
528 | + * only Atmel sells these chips. | |
529 | + */ | |
530 | + if (id[0] != 0x1f) | |
531 | + return NULL; | |
532 | + | |
533 | + jedec = id[0]; | |
534 | + jedec = jedec << 8; | |
535 | + jedec |= id[1]; | |
536 | + jedec = jedec << 8; | |
537 | + jedec |= id[2]; | |
538 | + | |
539 | + for (tmp = 0, info = dataflash_data; | |
540 | + tmp < ARRAY_SIZE(dataflash_data); | |
541 | + tmp++, info++) { | |
542 | + if (info->jedec_id == jedec) { | |
543 | + if (info->flags & SUP_POW2PS) { | |
544 | + status = dataflash_status(spi); | |
545 | + if (status < 0) { | |
546 | + debug("SPI DataFlash: status error %d\n", | |
547 | + status); | |
548 | + return NULL; | |
549 | + } | |
550 | + if (status & 0x1) { | |
551 | + if (info->flags & IS_POW2PS) | |
552 | + return info; | |
553 | + } else { | |
554 | + if (!(info->flags & IS_POW2PS)) | |
555 | + return info; | |
556 | + } | |
557 | + } else { | |
558 | + return info; | |
559 | + } | |
560 | + } | |
561 | + } | |
562 | + | |
563 | + /* | |
564 | + * Treat other chips as errors ... we won't know the right page | |
565 | + * size (it might be binary) even when we can tell which density | |
566 | + * class is involved (legacy chip id scheme). | |
567 | + */ | |
568 | + printf("SPI DataFlash: Unsupported flash IDs: "); | |
569 | + printf("manuf %02x, jedec %04x, ext_jedec %04x\n", | |
570 | + id[0], jedec, id[3] << 8 | id[4]); | |
571 | + return NULL; | |
572 | +} | |
573 | + | |
574 | +/* | |
575 | + * Detect and initialize DataFlash device, using JEDEC IDs on newer chips | |
576 | + * or else the ID code embedded in the status bits: | |
577 | + * | |
578 | + * Device Density ID code #Pages PageSize Offset | |
579 | + * AT45DB011B 1Mbit (128K) xx0011xx (0x0c) 512 264 9 | |
580 | + * AT45DB021B 2Mbit (256K) xx0101xx (0x14) 1024 264 9 | |
581 | + * AT45DB041B 4Mbit (512K) xx0111xx (0x1c) 2048 264 9 | |
582 | + * AT45DB081B 8Mbit (1M) xx1001xx (0x24) 4096 264 9 | |
583 | + * AT45DB0161B 16Mbit (2M) xx1011xx (0x2c) 4096 528 10 | |
584 | + * AT45DB0321B 32Mbit (4M) xx1101xx (0x34) 8192 528 10 | |
585 | + * AT45DB0642 64Mbit (8M) xx111xxx (0x3c) 8192 1056 11 | |
586 | + * AT45DB1282 128Mbit (16M) xx0100xx (0x10) 16384 1056 11 | |
587 | + */ | |
588 | +static int spi_dataflash_probe(struct udevice *dev) | |
589 | +{ | |
590 | + struct spi_slave *spi = dev_get_parentdata(dev); | |
591 | + struct spi_flash *spi_flash; | |
592 | + struct flash_info *info; | |
593 | + u8 idcode[5]; | |
594 | + int ret, status = 0; | |
595 | + | |
596 | + spi_flash = dev_get_uclass_priv(dev); | |
597 | + spi_flash->dev = dev; | |
598 | + | |
599 | + ret = spi_claim_bus(spi); | |
600 | + if (ret) | |
601 | + return ret; | |
602 | + | |
603 | + ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode)); | |
604 | + if (ret) { | |
605 | + printf("SPI DataFlash: Failed to get idcodes\n"); | |
606 | + goto err_read_cmd; | |
607 | + } | |
608 | + | |
609 | + /* | |
610 | + * Try to detect dataflash by JEDEC ID. | |
611 | + * If it succeeds we know we have either a C or D part. | |
612 | + * D will support power of 2 pagesize option. | |
613 | + * Both support the security register, though with different | |
614 | + * write procedures. | |
615 | + */ | |
616 | + info = jedec_probe(spi, idcode); | |
617 | + if (info != NULL) | |
618 | + add_dataflash(dev, info->name, info->nr_pages, | |
619 | + info->pagesize, info->pageoffset, | |
620 | + (info->flags & SUP_POW2PS) ? 'd' : 'c'); | |
621 | + else { | |
622 | + /* | |
623 | + * Older chips support only legacy commands, identifing | |
624 | + * capacity using bits in the status byte. | |
625 | + */ | |
626 | + status = dataflash_status(spi); | |
627 | + if (status <= 0 || status == 0xff) { | |
628 | + printf("SPI DataFlash: read status error %d\n", status); | |
629 | + if (status == 0 || status == 0xff) | |
630 | + status = -ENODEV; | |
631 | + goto err_read_cmd; | |
632 | + } | |
633 | + /* | |
634 | + * if there's a device there, assume it's dataflash. | |
635 | + * board setup should have set spi->max_speed_max to | |
636 | + * match f(car) for continuous reads, mode 0 or 3. | |
637 | + */ | |
638 | + switch (status & 0x3c) { | |
639 | + case 0x0c: /* 0 0 1 1 x x */ | |
640 | + status = add_dataflash(dev, "AT45DB011B", | |
641 | + 512, 264, 9, 0); | |
642 | + break; | |
643 | + case 0x14: /* 0 1 0 1 x x */ | |
644 | + status = add_dataflash(dev, "AT45DB021B", | |
645 | + 1024, 264, 9, 0); | |
646 | + break; | |
647 | + case 0x1c: /* 0 1 1 1 x x */ | |
648 | + status = add_dataflash(dev, "AT45DB041x", | |
649 | + 2048, 264, 9, 0); | |
650 | + break; | |
651 | + case 0x24: /* 1 0 0 1 x x */ | |
652 | + status = add_dataflash(dev, "AT45DB081B", | |
653 | + 4096, 264, 9, 0); | |
654 | + break; | |
655 | + case 0x2c: /* 1 0 1 1 x x */ | |
656 | + status = add_dataflash(dev, "AT45DB161x", | |
657 | + 4096, 528, 10, 0); | |
658 | + break; | |
659 | + case 0x34: /* 1 1 0 1 x x */ | |
660 | + status = add_dataflash(dev, "AT45DB321x", | |
661 | + 8192, 528, 10, 0); | |
662 | + break; | |
663 | + case 0x38: /* 1 1 1 x x x */ | |
664 | + case 0x3c: | |
665 | + status = add_dataflash(dev, "AT45DB642x", | |
666 | + 8192, 1056, 11, 0); | |
667 | + break; | |
668 | + /* obsolete AT45DB1282 not (yet?) supported */ | |
669 | + default: | |
670 | + dev_info(&spi->dev, "unsupported device (%x)\n", | |
671 | + status & 0x3c); | |
672 | + status = -ENODEV; | |
673 | + goto err_read_cmd; | |
674 | + } | |
675 | + } | |
676 | + | |
677 | + /* Assign spi data */ | |
678 | + spi_flash->spi = spi; | |
679 | + spi_flash->memory_map = spi->memory_map; | |
680 | + spi_flash->dual_flash = spi->option; | |
681 | + | |
682 | + spi_release_bus(spi); | |
683 | + | |
684 | + return 0; | |
685 | + | |
686 | +err_read_cmd: | |
687 | + spi_release_bus(spi); | |
688 | + | |
689 | + return status; | |
690 | +} | |
691 | + | |
692 | +static const struct dm_spi_flash_ops spi_dataflash_ops = { | |
693 | + .read = spi_dataflash_read, | |
694 | + .write = spi_dataflash_write, | |
695 | + .erase = spi_dataflash_erase, | |
696 | +}; | |
697 | + | |
698 | +static const struct udevice_id spi_dataflash_ids[] = { | |
699 | + { .compatible = "atmel,at45", }, | |
700 | + { .compatible = "atmel,dataflash", }, | |
701 | + { } | |
702 | +}; | |
703 | + | |
704 | +U_BOOT_DRIVER(spi_dataflash) = { | |
705 | + .name = "spi_dataflash", | |
706 | + .id = UCLASS_SPI_FLASH, | |
707 | + .of_match = spi_dataflash_ids, | |
708 | + .probe = spi_dataflash_probe, | |
709 | + .priv_auto_alloc_size = sizeof(struct dataflash), | |
710 | + .ops = &spi_dataflash_ops, | |
711 | +}; |