]> git.sur5r.net Git - u-boot/blob - drivers/mtd/spi/sf_ops.c
c820d48b6c0b37434347c47fd63136536bcc5b4f
[u-boot] / drivers / mtd / spi / sf_ops.c
1 /*
2  * SPI flash operations
3  *
4  * Copyright (C) 2008 Atmel Corporation
5  * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
6  * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc.
7  *
8  * SPDX-License-Identifier:     GPL-2.0+
9  */
10
11 #include <common.h>
12 #include <errno.h>
13 #include <malloc.h>
14 #include <spi.h>
15 #include <spi_flash.h>
16 #include <watchdog.h>
17 #include <linux/compiler.h>
18
19 #include "sf_internal.h"
20
21 static void spi_flash_addr(u32 addr, u8 *cmd)
22 {
23         /* cmd[0] is actual command */
24         cmd[1] = addr >> 16;
25         cmd[2] = addr >> 8;
26         cmd[3] = addr >> 0;
27 }
28
29 int spi_flash_cmd_read_status(struct spi_flash *flash, u8 *rs)
30 {
31         int ret;
32         u8 cmd;
33
34         cmd = CMD_READ_STATUS;
35         ret = spi_flash_read_common(flash, &cmd, 1, rs, 1);
36         if (ret < 0) {
37                 debug("SF: fail to read status register\n");
38                 return ret;
39         }
40
41         return 0;
42 }
43
44 int spi_flash_cmd_write_status(struct spi_flash *flash, u8 ws)
45 {
46         u8 cmd;
47         int ret;
48
49         cmd = CMD_WRITE_STATUS;
50         ret = spi_flash_write_common(flash, &cmd, 1, &ws, 1);
51         if (ret < 0) {
52                 debug("SF: fail to write status register\n");
53                 return ret;
54         }
55
56         return 0;
57 }
58
59 #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND)
60 int spi_flash_cmd_read_config(struct spi_flash *flash, u8 *rc)
61 {
62         int ret;
63         u8 cmd;
64
65         cmd = CMD_READ_CONFIG;
66         ret = spi_flash_read_common(flash, &cmd, 1, rc, 1);
67         if (ret < 0) {
68                 debug("SF: fail to read config register\n");
69                 return ret;
70         }
71
72         return 0;
73 }
74
75 int spi_flash_cmd_write_config(struct spi_flash *flash, u8 wc)
76 {
77         u8 data[2];
78         u8 cmd;
79         int ret;
80
81         ret = spi_flash_cmd_read_status(flash, &data[0]);
82         if (ret < 0)
83                 return ret;
84
85         cmd = CMD_WRITE_STATUS;
86         data[1] = wc;
87         ret = spi_flash_write_common(flash, &cmd, 1, &data, 2);
88         if (ret) {
89                 debug("SF: fail to write config register\n");
90                 return ret;
91         }
92
93         return 0;
94 }
95 #endif
96
97 #ifdef CONFIG_SPI_FLASH_BAR
98 static int spi_flash_write_bank(struct spi_flash *flash, u32 offset)
99 {
100         u8 cmd, bank_sel;
101         int ret;
102
103         bank_sel = offset / (SPI_FLASH_16MB_BOUN << flash->shift);
104         if (bank_sel == flash->bank_curr)
105                 goto bar_end;
106
107         cmd = flash->bank_write_cmd;
108         ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1);
109         if (ret < 0) {
110                 debug("SF: fail to write bank register\n");
111                 return ret;
112         }
113
114 bar_end:
115         flash->bank_curr = bank_sel;
116         return flash->bank_curr;
117 }
118 #endif
119
120 #ifdef CONFIG_SF_DUAL_FLASH
121 static void spi_flash_dual_flash(struct spi_flash *flash, u32 *addr)
122 {
123         switch (flash->dual_flash) {
124         case SF_DUAL_STACKED_FLASH:
125                 if (*addr >= (flash->size >> 1)) {
126                         *addr -= flash->size >> 1;
127                         flash->spi->flags |= SPI_XFER_U_PAGE;
128                 } else {
129                         flash->spi->flags &= ~SPI_XFER_U_PAGE;
130                 }
131                 break;
132         case SF_DUAL_PARALLEL_FLASH:
133                 *addr >>= flash->shift;
134                 break;
135         default:
136                 debug("SF: Unsupported dual_flash=%d\n", flash->dual_flash);
137                 break;
138         }
139 }
140 #endif
141
142 int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
143 {
144         u8 sr;
145         int timebase, ret;
146
147         timebase = get_timer(0);
148
149         while (get_timer(timebase) < timeout) {
150                 ret = spi_flash_cmd_read_status(flash, &sr);
151                 if (ret < 0)
152                         return ret;
153
154                 if (!(sr & STATUS_WIP))
155                         return 0;
156                 else
157                         break;
158         }
159
160         printf("SF: Timeout!\n");
161
162         return -ETIMEDOUT;
163 }
164
165 int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
166                 size_t cmd_len, const void *buf, size_t buf_len)
167 {
168         struct spi_slave *spi = flash->spi;
169         unsigned long timeout = SPI_FLASH_PROG_TIMEOUT;
170         int ret;
171
172         if (buf == NULL)
173                 timeout = SPI_FLASH_PAGE_ERASE_TIMEOUT;
174
175         ret = spi_claim_bus(flash->spi);
176         if (ret) {
177                 debug("SF: unable to claim SPI bus\n");
178                 return ret;
179         }
180
181         ret = spi_flash_cmd_write_enable(flash);
182         if (ret < 0) {
183                 debug("SF: enabling write failed\n");
184                 return ret;
185         }
186
187         ret = spi_flash_cmd_write(spi, cmd, cmd_len, buf, buf_len);
188         if (ret < 0) {
189                 debug("SF: write cmd failed\n");
190                 return ret;
191         }
192
193         ret = spi_flash_cmd_wait_ready(flash, timeout);
194         if (ret < 0) {
195                 debug("SF: write %s timed out\n",
196                       timeout == SPI_FLASH_PROG_TIMEOUT ?
197                         "program" : "page erase");
198                 return ret;
199         }
200
201         spi_release_bus(spi);
202
203         return ret;
204 }
205
206 int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)
207 {
208         u32 erase_size, erase_addr;
209         u8 cmd[SPI_FLASH_CMD_LEN];
210         int ret = -1;
211
212         erase_size = flash->erase_size;
213         if (offset % erase_size || len % erase_size) {
214                 debug("SF: Erase offset/length not multiple of erase size\n");
215                 return -1;
216         }
217
218         cmd[0] = flash->erase_cmd;
219         while (len) {
220                 erase_addr = offset;
221
222 #ifdef CONFIG_SF_DUAL_FLASH
223                 if (flash->dual_flash > SF_SINGLE_FLASH)
224                         spi_flash_dual_flash(flash, &erase_addr);
225 #endif
226 #ifdef CONFIG_SPI_FLASH_BAR
227                 ret = spi_flash_write_bank(flash, erase_addr);
228                 if (ret < 0)
229                         return ret;
230 #endif
231                 spi_flash_addr(erase_addr, cmd);
232
233                 debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
234                       cmd[2], cmd[3], erase_addr);
235
236                 ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0);
237                 if (ret < 0) {
238                         debug("SF: erase failed\n");
239                         break;
240                 }
241
242                 offset += erase_size;
243                 len -= erase_size;
244         }
245
246         return ret;
247 }
248
249 int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
250                 size_t len, const void *buf)
251 {
252         unsigned long byte_addr, page_size;
253         u32 write_addr;
254         size_t chunk_len, actual;
255         u8 cmd[SPI_FLASH_CMD_LEN];
256         int ret = -1;
257
258         page_size = flash->page_size;
259
260         cmd[0] = flash->write_cmd;
261         for (actual = 0; actual < len; actual += chunk_len) {
262                 write_addr = offset;
263
264 #ifdef CONFIG_SF_DUAL_FLASH
265                 if (flash->dual_flash > SF_SINGLE_FLASH)
266                         spi_flash_dual_flash(flash, &write_addr);
267 #endif
268 #ifdef CONFIG_SPI_FLASH_BAR
269                 ret = spi_flash_write_bank(flash, write_addr);
270                 if (ret < 0)
271                         return ret;
272 #endif
273                 byte_addr = offset % page_size;
274                 chunk_len = min(len - actual, (size_t)(page_size - byte_addr));
275
276                 if (flash->spi->max_write_size)
277                         chunk_len = min(chunk_len,
278                                         (size_t)flash->spi->max_write_size);
279
280                 spi_flash_addr(write_addr, cmd);
281
282                 debug("SF: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
283                       buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
284
285                 ret = spi_flash_write_common(flash, cmd, sizeof(cmd),
286                                         buf + actual, chunk_len);
287                 if (ret < 0) {
288                         debug("SF: write failed\n");
289                         break;
290                 }
291
292                 offset += chunk_len;
293         }
294
295         return ret;
296 }
297
298 int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
299                 size_t cmd_len, void *data, size_t data_len)
300 {
301         struct spi_slave *spi = flash->spi;
302         int ret;
303
304         ret = spi_claim_bus(flash->spi);
305         if (ret) {
306                 debug("SF: unable to claim SPI bus\n");
307                 return ret;
308         }
309
310         ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len);
311         if (ret < 0) {
312                 debug("SF: read cmd failed\n");
313                 return ret;
314         }
315
316         spi_release_bus(spi);
317
318         return ret;
319 }
320
321 void __weak spi_flash_copy_mmap(void *data, void *offset, size_t len)
322 {
323         memcpy(data, offset, len);
324 }
325
326 int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
327                 size_t len, void *data)
328 {
329         u8 *cmd, cmdsz;
330         u32 remain_len, read_len, read_addr;
331         int bank_sel = 0;
332         int ret = -1;
333
334         /* Handle memory-mapped SPI */
335         if (flash->memory_map) {
336                 ret = spi_claim_bus(flash->spi);
337                 if (ret) {
338                         debug("SF: unable to claim SPI bus\n");
339                         return ret;
340                 }
341                 spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP);
342                 spi_flash_copy_mmap(data, flash->memory_map + offset, len);
343                 spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP_END);
344                 spi_release_bus(flash->spi);
345                 return 0;
346         }
347
348         cmdsz = SPI_FLASH_CMD_LEN + flash->dummy_byte;
349         cmd = calloc(1, cmdsz);
350         if (!cmd) {
351                 debug("SF: Failed to allocate cmd\n");
352                 return -ENOMEM;
353         }
354
355         cmd[0] = flash->read_cmd;
356         while (len) {
357                 read_addr = offset;
358
359 #ifdef CONFIG_SF_DUAL_FLASH
360                 if (flash->dual_flash > SF_SINGLE_FLASH)
361                         spi_flash_dual_flash(flash, &read_addr);
362 #endif
363 #ifdef CONFIG_SPI_FLASH_BAR
364                 ret = spi_flash_write_bank(flash, read_addr);
365                 if (ret < 0)
366                         return ret;
367                 bank_sel = flash->bank_curr;
368 #endif
369                 remain_len = ((SPI_FLASH_16MB_BOUN << flash->shift) *
370                                 (bank_sel + 1)) - offset;
371                 if (len < remain_len)
372                         read_len = len;
373                 else
374                         read_len = remain_len;
375
376                 spi_flash_addr(read_addr, cmd);
377
378                 ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len);
379                 if (ret < 0) {
380                         debug("SF: read failed\n");
381                         break;
382                 }
383
384                 offset += read_len;
385                 len -= read_len;
386                 data += read_len;
387         }
388
389         free(cmd);
390         return ret;
391 }
392
393 #ifdef CONFIG_SPI_FLASH_SST
394 static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)
395 {
396         int ret;
397         u8 cmd[4] = {
398                 CMD_SST_BP,
399                 offset >> 16,
400                 offset >> 8,
401                 offset,
402         };
403
404         debug("BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
405               spi_w8r8(flash->spi, CMD_READ_STATUS), buf, cmd[0], offset);
406
407         ret = spi_flash_cmd_write_enable(flash);
408         if (ret)
409                 return ret;
410
411         ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf, 1);
412         if (ret)
413                 return ret;
414
415         return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
416 }
417
418 int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len,
419                 const void *buf)
420 {
421         size_t actual, cmd_len;
422         int ret;
423         u8 cmd[4];
424
425         ret = spi_claim_bus(flash->spi);
426         if (ret) {
427                 debug("SF: Unable to claim SPI bus\n");
428                 return ret;
429         }
430
431         /* If the data is not word aligned, write out leading single byte */
432         actual = offset % 2;
433         if (actual) {
434                 ret = sst_byte_write(flash, offset, buf);
435                 if (ret)
436                         goto done;
437         }
438         offset += actual;
439
440         ret = spi_flash_cmd_write_enable(flash);
441         if (ret)
442                 goto done;
443
444         cmd_len = 4;
445         cmd[0] = CMD_SST_AAI_WP;
446         cmd[1] = offset >> 16;
447         cmd[2] = offset >> 8;
448         cmd[3] = offset;
449
450         for (; actual < len - 1; actual += 2) {
451                 debug("WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
452                       spi_w8r8(flash->spi, CMD_READ_STATUS), buf + actual,
453                       cmd[0], offset);
454
455                 ret = spi_flash_cmd_write(flash->spi, cmd, cmd_len,
456                                         buf + actual, 2);
457                 if (ret) {
458                         debug("SF: sst word program failed\n");
459                         break;
460                 }
461
462                 ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
463                 if (ret)
464                         break;
465
466                 cmd_len = 1;
467                 offset += 2;
468         }
469
470         if (!ret)
471                 ret = spi_flash_cmd_write_disable(flash);
472
473         /* If there is a single trailing byte, write it out */
474         if (!ret && actual != len)
475                 ret = sst_byte_write(flash, offset, buf + actual);
476
477  done:
478         debug("SF: sst: program %s %zu bytes @ 0x%zx\n",
479               ret ? "failure" : "success", len, offset - actual);
480
481         spi_release_bus(flash->spi);
482         return ret;
483 }
484
485 int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len,
486                 const void *buf)
487 {
488         size_t actual;
489         int ret;
490
491         ret = spi_claim_bus(flash->spi);
492         if (ret) {
493                 debug("SF: Unable to claim SPI bus\n");
494                 return ret;
495         }
496
497         for (actual = 0; actual < len; actual++) {
498                 ret = sst_byte_write(flash, offset, buf + actual);
499                 if (ret) {
500                         debug("SF: sst byte program failed\n");
501                         break;
502                 }
503                 offset++;
504         }
505
506         if (!ret)
507                 ret = spi_flash_cmd_write_disable(flash);
508
509         debug("SF: sst: program %s %zu bytes @ 0x%zx\n",
510               ret ? "failure" : "success", len, offset - actual);
511
512         spi_release_bus(flash->spi);
513         return ret;
514 }
515 #endif