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