blob: 3bc2dff8b21a9d35fc28f3a8d466ffbb5f938097 [file] [log] [blame]
Haavard Skinnemoen2f5bfb72008-05-16 11:10:33 +02001/*
2 * Atmel SPI DataFlash support
3 *
4 * Copyright (C) 2008 Atmel Corporation
5 */
Mike Frysingerc5431ac2009-03-23 23:03:58 -04006
Haavard Skinnemoen2f5bfb72008-05-16 11:10:33 +02007#include <common.h>
8#include <malloc.h>
9#include <spi_flash.h>
10
11#include "spi_flash_internal.h"
12
13/* AT45-specific commands */
14#define CMD_AT45_READ_STATUS 0xd7
15#define CMD_AT45_ERASE_PAGE 0x81
16#define CMD_AT45_LOAD_PROG_BUF1 0x82
17#define CMD_AT45_LOAD_BUF1 0x84
18#define CMD_AT45_LOAD_PROG_BUF2 0x85
19#define CMD_AT45_LOAD_BUF2 0x87
20#define CMD_AT45_PROG_BUF1 0x88
21#define CMD_AT45_PROG_BUF2 0x89
22
23/* AT45 status register bits */
24#define AT45_STATUS_P2_PAGE_SIZE (1 << 0)
25#define AT45_STATUS_READY (1 << 7)
26
27/* DataFlash family IDs, as obtained from the second idcode byte */
28#define DF_FAMILY_AT26F 0
29#define DF_FAMILY_AT45 1
30#define DF_FAMILY_AT26DF 2 /* AT25DF and AT26DF */
31
32struct atmel_spi_flash_params {
33 u8 idcode1;
34 /* Log2 of page size in power-of-two mode */
35 u8 l2_page_size;
36 u8 pages_per_block;
37 u8 blocks_per_sector;
38 u8 nr_sectors;
39 const char *name;
40};
41
Brad Bozarth615c2202009-01-01 22:45:47 -050042/* spi_flash needs to be first so upper layers can free() it */
Haavard Skinnemoen2f5bfb72008-05-16 11:10:33 +020043struct atmel_spi_flash {
Haavard Skinnemoen2f5bfb72008-05-16 11:10:33 +020044 struct spi_flash flash;
Brad Bozarth615c2202009-01-01 22:45:47 -050045 const struct atmel_spi_flash_params *params;
Haavard Skinnemoen2f5bfb72008-05-16 11:10:33 +020046};
47
48static inline struct atmel_spi_flash *
49to_atmel_spi_flash(struct spi_flash *flash)
50{
51 return container_of(flash, struct atmel_spi_flash, flash);
52}
53
54static const struct atmel_spi_flash_params atmel_spi_flash_table[] = {
55 {
Jean-Christophe PLAGNIOL-VILLARDaf2b2992009-01-04 07:44:07 +010056 .idcode1 = 0x22,
57 .l2_page_size = 8,
58 .pages_per_block = 8,
59 .blocks_per_sector = 16,
60 .nr_sectors = 4,
61 .name = "AT45DB011D",
62 },
63 {
64 .idcode1 = 0x23,
65 .l2_page_size = 8,
66 .pages_per_block = 8,
67 .blocks_per_sector = 16,
68 .nr_sectors = 8,
69 .name = "AT45DB021D",
70 },
71 {
72 .idcode1 = 0x24,
73 .l2_page_size = 8,
74 .pages_per_block = 8,
75 .blocks_per_sector = 32,
76 .nr_sectors = 8,
77 .name = "AT45DB041D",
78 },
79 {
80 .idcode1 = 0x25,
81 .l2_page_size = 8,
82 .pages_per_block = 8,
83 .blocks_per_sector = 32,
84 .nr_sectors = 16,
85 .name = "AT45DB081D",
86 },
87 {
88 .idcode1 = 0x26,
89 .l2_page_size = 9,
90 .pages_per_block = 8,
91 .blocks_per_sector = 32,
92 .nr_sectors = 16,
93 .name = "AT45DB161D",
94 },
95 {
96 .idcode1 = 0x27,
97 .l2_page_size = 9,
98 .pages_per_block = 8,
99 .blocks_per_sector = 64,
100 .nr_sectors = 64,
101 .name = "AT45DB321D",
102 },
103 {
Haavard Skinnemoen2f5bfb72008-05-16 11:10:33 +0200104 .idcode1 = 0x28,
105 .l2_page_size = 10,
106 .pages_per_block = 8,
107 .blocks_per_sector = 32,
108 .nr_sectors = 32,
109 .name = "AT45DB642D",
110 },
111};
112
113static int at45_wait_ready(struct spi_flash *flash, unsigned long timeout)
114{
115 struct spi_slave *spi = flash->spi;
116 unsigned long timebase;
117 int ret;
118 u8 cmd = CMD_AT45_READ_STATUS;
119 u8 status;
120
121 timebase = get_timer(0);
122
123 ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN);
124 if (ret)
125 return -1;
126
127 do {
128 ret = spi_xfer(spi, 8, NULL, &status, 0);
129 if (ret)
130 return -1;
131
132 if (status & AT45_STATUS_READY)
133 break;
134 } while (get_timer(timebase) < timeout);
135
136 /* Deactivate CS */
137 spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
138
139 if (status & AT45_STATUS_READY)
140 return 0;
141
142 /* Timed out */
143 return -1;
144}
145
146/*
147 * Assemble the address part of a command for AT45 devices in
148 * non-power-of-two page size mode.
149 */
150static void at45_build_address(struct atmel_spi_flash *asf, u8 *cmd, u32 offset)
151{
152 unsigned long page_addr;
153 unsigned long byte_addr;
154 unsigned long page_size;
155 unsigned int page_shift;
156
157 /*
158 * The "extra" space per page is the power-of-two page size
159 * divided by 32.
160 */
161 page_shift = asf->params->l2_page_size;
162 page_size = (1 << page_shift) + (1 << (page_shift - 5));
163 page_shift++;
164 page_addr = offset / page_size;
165 byte_addr = offset % page_size;
166
167 cmd[0] = page_addr >> (16 - page_shift);
168 cmd[1] = page_addr << (page_shift - 8) | (byte_addr >> 8);
169 cmd[2] = byte_addr;
170}
171
172static int dataflash_read_fast_p2(struct spi_flash *flash,
173 u32 offset, size_t len, void *buf)
174{
175 u8 cmd[5];
176
177 cmd[0] = CMD_READ_ARRAY_FAST;
178 cmd[1] = offset >> 16;
179 cmd[2] = offset >> 8;
180 cmd[3] = offset;
181 cmd[4] = 0x00;
182
183 return spi_flash_read_common(flash, cmd, sizeof(cmd), buf, len);
184}
185
186static int dataflash_read_fast_at45(struct spi_flash *flash,
187 u32 offset, size_t len, void *buf)
188{
189 struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
190 u8 cmd[5];
191
192 cmd[0] = CMD_READ_ARRAY_FAST;
193 at45_build_address(asf, cmd + 1, offset);
194 cmd[4] = 0x00;
195
196 return spi_flash_read_common(flash, cmd, sizeof(cmd), buf, len);
197}
198
Todor I Mollov6a5a2502009-04-04 07:14:44 -0400199/*
200 * TODO: the two write funcs (_p2/_at45) should get unified ...
201 */
202static int dataflash_write_p2(struct spi_flash *flash,
203 u32 offset, size_t len, const void *buf)
204{
205 struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
206 unsigned long page_size;
207 u32 addr = offset;
208 size_t chunk_len;
209 size_t actual;
210 int ret;
211 u8 cmd[4];
212
213 /*
214 * TODO: This function currently uses only page buffer #1. We can
215 * speed this up by using both buffers and loading one buffer while
216 * the other is being programmed into main memory.
217 */
218
219 page_size = (1 << asf->params->l2_page_size);
220
221 ret = spi_claim_bus(flash->spi);
222 if (ret) {
223 debug("SF: Unable to claim SPI bus\n");
224 return ret;
225 }
226
227 for (actual = 0; actual < len; actual += chunk_len) {
228 chunk_len = min(len - actual, page_size - (addr % page_size));
229
230 /* Use the same address bits for both commands */
231 cmd[0] = CMD_AT45_LOAD_BUF1;
232 cmd[1] = addr >> 16;
233 cmd[2] = addr >> 8;
234 cmd[3] = addr;
235
236 ret = spi_flash_cmd_write(flash->spi, cmd, 4,
237 buf + actual, chunk_len);
238 if (ret < 0) {
239 debug("SF: Loading AT45 buffer failed\n");
240 goto out;
241 }
242
243 cmd[0] = CMD_AT45_PROG_BUF1;
244 ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
245 if (ret < 0) {
246 debug("SF: AT45 page programming failed\n");
247 goto out;
248 }
249
250 ret = at45_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
251 if (ret < 0) {
252 debug("SF: AT45 page programming timed out\n");
253 goto out;
254 }
255
256 addr += chunk_len;
257 }
258
259 debug("SF: AT45: Successfully programmed %zu bytes @ 0x%x\n",
260 len, offset);
261 ret = 0;
262
263out:
264 spi_release_bus(flash->spi);
265 return ret;
266}
267
Haavard Skinnemoen2f5bfb72008-05-16 11:10:33 +0200268static int dataflash_write_at45(struct spi_flash *flash,
269 u32 offset, size_t len, const void *buf)
270{
271 struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
272 unsigned long page_addr;
273 unsigned long byte_addr;
274 unsigned long page_size;
275 unsigned int page_shift;
276 size_t chunk_len;
277 size_t actual;
278 int ret;
279 u8 cmd[4];
280
Todor I Mollov6a5a2502009-04-04 07:14:44 -0400281 /*
282 * TODO: This function currently uses only page buffer #1. We can
283 * speed this up by using both buffers and loading one buffer while
284 * the other is being programmed into main memory.
285 */
286
Haavard Skinnemoen2f5bfb72008-05-16 11:10:33 +0200287 page_shift = asf->params->l2_page_size;
288 page_size = (1 << page_shift) + (1 << (page_shift - 5));
289 page_shift++;
290 page_addr = offset / page_size;
291 byte_addr = offset % page_size;
292
293 ret = spi_claim_bus(flash->spi);
294 if (ret) {
295 debug("SF: Unable to claim SPI bus\n");
296 return ret;
297 }
298
299 for (actual = 0; actual < len; actual += chunk_len) {
300 chunk_len = min(len - actual, page_size - byte_addr);
301
302 /* Use the same address bits for both commands */
303 cmd[0] = CMD_AT45_LOAD_BUF1;
304 cmd[1] = page_addr >> (16 - page_shift);
305 cmd[2] = page_addr << (page_shift - 8) | (byte_addr >> 8);
306 cmd[3] = byte_addr;
307
308 ret = spi_flash_cmd_write(flash->spi, cmd, 4,
309 buf + actual, chunk_len);
310 if (ret < 0) {
311 debug("SF: Loading AT45 buffer failed\n");
312 goto out;
313 }
314
315 cmd[0] = CMD_AT45_PROG_BUF1;
316 ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
317 if (ret < 0) {
318 debug("SF: AT45 page programming failed\n");
319 goto out;
320 }
321
322 ret = at45_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
323 if (ret < 0) {
324 debug("SF: AT45 page programming timed out\n");
325 goto out;
326 }
327
328 page_addr++;
329 byte_addr = 0;
330 }
331
Stefan Roese37628252008-08-06 14:05:38 +0200332 debug("SF: AT45: Successfully programmed %zu bytes @ 0x%x\n",
Haavard Skinnemoen2f5bfb72008-05-16 11:10:33 +0200333 len, offset);
334 ret = 0;
335
336out:
337 spi_release_bus(flash->spi);
338 return ret;
339}
340
Todor I Mollov6a5a2502009-04-04 07:14:44 -0400341/*
342 * TODO: the two erase funcs (_p2/_at45) should get unified ...
343 */
344int dataflash_erase_p2(struct spi_flash *flash, u32 offset, size_t len)
345{
346 struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
347 unsigned long page_size;
348
349 size_t actual;
350 int ret;
351 u8 cmd[4];
352
353 /*
354 * TODO: This function currently uses page erase only. We can
355 * probably speed things up by using block and/or sector erase
356 * when possible.
357 */
358
359 page_size = (1 << asf->params->l2_page_size);
360
361 if (offset % page_size || len % page_size) {
362 debug("SF: Erase offset/length not multiple of page size\n");
363 return -1;
364 }
365
366 cmd[0] = CMD_AT45_ERASE_PAGE;
367 cmd[3] = 0x00;
368
369 ret = spi_claim_bus(flash->spi);
370 if (ret) {
371 debug("SF: Unable to claim SPI bus\n");
372 return ret;
373 }
374
375 for (actual = 0; actual < len; actual += page_size) {
376 cmd[1] = offset >> 16;
377 cmd[2] = offset >> 8;
378
379 ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
380 if (ret < 0) {
381 debug("SF: AT45 page erase failed\n");
382 goto out;
383 }
384
385 ret = at45_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
386 if (ret < 0) {
387 debug("SF: AT45 page erase timed out\n");
388 goto out;
389 }
390
391 offset += page_size;
392 }
393
394 debug("SF: AT45: Successfully erased %zu bytes @ 0x%x\n",
395 len, offset);
396 ret = 0;
397
398out:
399 spi_release_bus(flash->spi);
400 return ret;
401}
402
Haavard Skinnemoen2f5bfb72008-05-16 11:10:33 +0200403int dataflash_erase_at45(struct spi_flash *flash, u32 offset, size_t len)
404{
405 struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
406 unsigned long page_addr;
407 unsigned long page_size;
408 unsigned int page_shift;
409 size_t actual;
410 int ret;
411 u8 cmd[4];
412
413 /*
414 * TODO: This function currently uses page erase only. We can
415 * probably speed things up by using block and/or sector erase
416 * when possible.
417 */
418
419 page_shift = asf->params->l2_page_size;
420 page_size = (1 << page_shift) + (1 << (page_shift - 5));
421 page_shift++;
422 page_addr = offset / page_size;
423
424 if (offset % page_size || len % page_size) {
425 debug("SF: Erase offset/length not multiple of page size\n");
426 return -1;
427 }
428
429 cmd[0] = CMD_AT45_ERASE_PAGE;
430 cmd[3] = 0x00;
431
432 ret = spi_claim_bus(flash->spi);
433 if (ret) {
434 debug("SF: Unable to claim SPI bus\n");
435 return ret;
436 }
437
438 for (actual = 0; actual < len; actual += page_size) {
439 cmd[1] = page_addr >> (16 - page_shift);
440 cmd[2] = page_addr << (page_shift - 8);
441
442 ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
443 if (ret < 0) {
444 debug("SF: AT45 page erase failed\n");
445 goto out;
446 }
447
448 ret = at45_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
449 if (ret < 0) {
450 debug("SF: AT45 page erase timed out\n");
451 goto out;
452 }
453
454 page_addr++;
455 }
456
Stefan Roese37628252008-08-06 14:05:38 +0200457 debug("SF: AT45: Successfully erased %zu bytes @ 0x%x\n",
Haavard Skinnemoen2f5bfb72008-05-16 11:10:33 +0200458 len, offset);
459 ret = 0;
460
461out:
462 spi_release_bus(flash->spi);
463 return ret;
464}
465
466struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
467{
468 const struct atmel_spi_flash_params *params;
469 unsigned long page_size;
470 unsigned int family;
471 struct atmel_spi_flash *asf;
472 unsigned int i;
473 int ret;
474 u8 status;
475
476 for (i = 0; i < ARRAY_SIZE(atmel_spi_flash_table); i++) {
477 params = &atmel_spi_flash_table[i];
478 if (params->idcode1 == idcode[1])
479 break;
480 }
481
482 if (i == ARRAY_SIZE(atmel_spi_flash_table)) {
483 debug("SF: Unsupported DataFlash ID %02x\n",
484 idcode[1]);
485 return NULL;
486 }
487
488 asf = malloc(sizeof(struct atmel_spi_flash));
489 if (!asf) {
490 debug("SF: Failed to allocate memory\n");
491 return NULL;
492 }
493
494 asf->params = params;
495 asf->flash.spi = spi;
496 asf->flash.name = params->name;
497
498 /* Assuming power-of-two page size initially. */
499 page_size = 1 << params->l2_page_size;
500
501 family = idcode[1] >> 5;
502
503 switch (family) {
504 case DF_FAMILY_AT45:
505 /*
506 * AT45 chips have configurable page size. The status
507 * register indicates which configuration is active.
508 */
509 ret = spi_flash_cmd(spi, CMD_AT45_READ_STATUS, &status, 1);
510 if (ret)
511 goto err;
512
513 debug("SF: AT45 status register: %02x\n", status);
514
515 if (!(status & AT45_STATUS_P2_PAGE_SIZE)) {
516 asf->flash.read = dataflash_read_fast_at45;
517 asf->flash.write = dataflash_write_at45;
518 asf->flash.erase = dataflash_erase_at45;
519 page_size += 1 << (params->l2_page_size - 5);
520 } else {
521 asf->flash.read = dataflash_read_fast_p2;
Todor I Mollov6a5a2502009-04-04 07:14:44 -0400522 asf->flash.write = dataflash_write_p2;
523 asf->flash.erase = dataflash_erase_p2;
Haavard Skinnemoen2f5bfb72008-05-16 11:10:33 +0200524 }
525
526 break;
527
528 case DF_FAMILY_AT26F:
529 case DF_FAMILY_AT26DF:
530 asf->flash.read = dataflash_read_fast_p2;
531 break;
532
533 default:
534 debug("SF: Unsupported DataFlash family %u\n", family);
535 goto err;
536 }
537
538 asf->flash.size = page_size * params->pages_per_block
539 * params->blocks_per_sector
540 * params->nr_sectors;
541
Stefan Roese37628252008-08-06 14:05:38 +0200542 debug("SF: Detected %s with page size %lu, total %u bytes\n",
Haavard Skinnemoen2f5bfb72008-05-16 11:10:33 +0200543 params->name, page_size, asf->flash.size);
544
545 return &asf->flash;
546
547err:
548 free(asf);
549 return NULL;
550}