sf: Optimize BAR write code
[oweals/u-boot.git] / 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 static int spi_flash_poll_status(struct spi_slave *spi, unsigned long timeout,
143                                  u8 cmd, u8 poll_bit)
144 {
145         unsigned long timebase;
146         unsigned long flags = SPI_XFER_BEGIN;
147         int ret;
148         u8 status;
149         u8 check_status = 0x0;
150
151         if (cmd == CMD_FLAG_STATUS)
152                 check_status = poll_bit;
153
154 #ifdef CONFIG_SF_DUAL_FLASH
155         if (spi->flags & SPI_XFER_U_PAGE)
156                 flags |= SPI_XFER_U_PAGE;
157 #endif
158         ret = spi_xfer(spi, 8, &cmd, NULL, flags);
159         if (ret) {
160                 debug("SF: fail to read %s status register\n",
161                       cmd == CMD_READ_STATUS ? "read" : "flag");
162                 return ret;
163         }
164
165         timebase = get_timer(0);
166         do {
167                 WATCHDOG_RESET();
168
169                 ret = spi_xfer(spi, 8, NULL, &status, 0);
170                 if (ret)
171                         return -1;
172
173                 if ((status & poll_bit) == check_status)
174                         break;
175
176         } while (get_timer(timebase) < timeout);
177
178         spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
179
180         if ((status & poll_bit) == check_status)
181                 return 0;
182
183         /* Timed out */
184         debug("SF: time out!\n");
185         return -1;
186 }
187
188 int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
189 {
190         struct spi_slave *spi = flash->spi;
191         int ret;
192         u8 poll_bit = STATUS_WIP;
193         u8 cmd = CMD_READ_STATUS;
194
195         ret = spi_flash_poll_status(spi, timeout, cmd, poll_bit);
196         if (ret < 0)
197                 return ret;
198
199         if (flash->poll_cmd == CMD_FLAG_STATUS) {
200                 poll_bit = STATUS_PEC;
201                 cmd = CMD_FLAG_STATUS;
202                 ret = spi_flash_poll_status(spi, timeout, cmd, poll_bit);
203                 if (ret < 0)
204                         return ret;
205         }
206
207         return 0;
208 }
209
210 int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
211                 size_t cmd_len, const void *buf, size_t buf_len)
212 {
213         struct spi_slave *spi = flash->spi;
214         unsigned long timeout = SPI_FLASH_PROG_TIMEOUT;
215         int ret;
216
217         if (buf == NULL)
218                 timeout = SPI_FLASH_PAGE_ERASE_TIMEOUT;
219
220         ret = spi_claim_bus(flash->spi);
221         if (ret) {
222                 debug("SF: unable to claim SPI bus\n");
223                 return ret;
224         }
225
226         ret = spi_flash_cmd_write_enable(flash);
227         if (ret < 0) {
228                 debug("SF: enabling write failed\n");
229                 return ret;
230         }
231
232         ret = spi_flash_cmd_write(spi, cmd, cmd_len, buf, buf_len);
233         if (ret < 0) {
234                 debug("SF: write cmd failed\n");
235                 return ret;
236         }
237
238         ret = spi_flash_cmd_wait_ready(flash, timeout);
239         if (ret < 0) {
240                 debug("SF: write %s timed out\n",
241                       timeout == SPI_FLASH_PROG_TIMEOUT ?
242                         "program" : "page erase");
243                 return ret;
244         }
245
246         spi_release_bus(spi);
247
248         return ret;
249 }
250
251 int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)
252 {
253         u32 erase_size, erase_addr;
254         u8 cmd[SPI_FLASH_CMD_LEN];
255         int ret = -1;
256
257         erase_size = flash->erase_size;
258         if (offset % erase_size || len % erase_size) {
259                 debug("SF: Erase offset/length not multiple of erase size\n");
260                 return -1;
261         }
262
263         cmd[0] = flash->erase_cmd;
264         while (len) {
265                 erase_addr = offset;
266
267 #ifdef CONFIG_SF_DUAL_FLASH
268                 if (flash->dual_flash > SF_SINGLE_FLASH)
269                         spi_flash_dual_flash(flash, &erase_addr);
270 #endif
271 #ifdef CONFIG_SPI_FLASH_BAR
272                 ret = spi_flash_write_bank(flash, erase_addr);
273                 if (ret < 0)
274                         return ret;
275 #endif
276                 spi_flash_addr(erase_addr, cmd);
277
278                 debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
279                       cmd[2], cmd[3], erase_addr);
280
281                 ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0);
282                 if (ret < 0) {
283                         debug("SF: erase failed\n");
284                         break;
285                 }
286
287                 offset += erase_size;
288                 len -= erase_size;
289         }
290
291         return ret;
292 }
293
294 int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
295                 size_t len, const void *buf)
296 {
297         unsigned long byte_addr, page_size;
298         u32 write_addr;
299         size_t chunk_len, actual;
300         u8 cmd[SPI_FLASH_CMD_LEN];
301         int ret = -1;
302
303         page_size = flash->page_size;
304
305         cmd[0] = flash->write_cmd;
306         for (actual = 0; actual < len; actual += chunk_len) {
307                 write_addr = offset;
308
309 #ifdef CONFIG_SF_DUAL_FLASH
310                 if (flash->dual_flash > SF_SINGLE_FLASH)
311                         spi_flash_dual_flash(flash, &write_addr);
312 #endif
313 #ifdef CONFIG_SPI_FLASH_BAR
314                 ret = spi_flash_write_bank(flash, write_addr);
315                 if (ret < 0)
316                         return ret;
317 #endif
318                 byte_addr = offset % page_size;
319                 chunk_len = min(len - actual, (size_t)(page_size - byte_addr));
320
321                 if (flash->spi->max_write_size)
322                         chunk_len = min(chunk_len,
323                                         (size_t)flash->spi->max_write_size);
324
325                 spi_flash_addr(write_addr, cmd);
326
327                 debug("SF: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
328                       buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
329
330                 ret = spi_flash_write_common(flash, cmd, sizeof(cmd),
331                                         buf + actual, chunk_len);
332                 if (ret < 0) {
333                         debug("SF: write failed\n");
334                         break;
335                 }
336
337                 offset += chunk_len;
338         }
339
340         return ret;
341 }
342
343 int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
344                 size_t cmd_len, void *data, size_t data_len)
345 {
346         struct spi_slave *spi = flash->spi;
347         int ret;
348
349         ret = spi_claim_bus(flash->spi);
350         if (ret) {
351                 debug("SF: unable to claim SPI bus\n");
352                 return ret;
353         }
354
355         ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len);
356         if (ret < 0) {
357                 debug("SF: read cmd failed\n");
358                 return ret;
359         }
360
361         spi_release_bus(spi);
362
363         return ret;
364 }
365
366 void __weak spi_flash_copy_mmap(void *data, void *offset, size_t len)
367 {
368         memcpy(data, offset, len);
369 }
370
371 int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
372                 size_t len, void *data)
373 {
374         u8 *cmd, cmdsz;
375         u32 remain_len, read_len, read_addr;
376         int bank_sel = 0;
377         int ret = -1;
378
379         /* Handle memory-mapped SPI */
380         if (flash->memory_map) {
381                 ret = spi_claim_bus(flash->spi);
382                 if (ret) {
383                         debug("SF: unable to claim SPI bus\n");
384                         return ret;
385                 }
386                 spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP);
387                 spi_flash_copy_mmap(data, flash->memory_map + offset, len);
388                 spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP_END);
389                 spi_release_bus(flash->spi);
390                 return 0;
391         }
392
393         cmdsz = SPI_FLASH_CMD_LEN + flash->dummy_byte;
394         cmd = calloc(1, cmdsz);
395         if (!cmd) {
396                 debug("SF: Failed to allocate cmd\n");
397                 return -ENOMEM;
398         }
399
400         cmd[0] = flash->read_cmd;
401         while (len) {
402                 read_addr = offset;
403
404 #ifdef CONFIG_SF_DUAL_FLASH
405                 if (flash->dual_flash > SF_SINGLE_FLASH)
406                         spi_flash_dual_flash(flash, &read_addr);
407 #endif
408 #ifdef CONFIG_SPI_FLASH_BAR
409                 ret = spi_flash_write_bank(flash, read_addr);
410                 if (ret < 0)
411                         return ret;
412                 bank_sel = flash->bank_curr;
413 #endif
414                 remain_len = ((SPI_FLASH_16MB_BOUN << flash->shift) *
415                                 (bank_sel + 1)) - offset;
416                 if (len < remain_len)
417                         read_len = len;
418                 else
419                         read_len = remain_len;
420
421                 spi_flash_addr(read_addr, cmd);
422
423                 ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len);
424                 if (ret < 0) {
425                         debug("SF: read failed\n");
426                         break;
427                 }
428
429                 offset += read_len;
430                 len -= read_len;
431                 data += read_len;
432         }
433
434         free(cmd);
435         return ret;
436 }
437
438 #ifdef CONFIG_SPI_FLASH_SST
439 static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)
440 {
441         int ret;
442         u8 cmd[4] = {
443                 CMD_SST_BP,
444                 offset >> 16,
445                 offset >> 8,
446                 offset,
447         };
448
449         debug("BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
450               spi_w8r8(flash->spi, CMD_READ_STATUS), buf, cmd[0], offset);
451
452         ret = spi_flash_cmd_write_enable(flash);
453         if (ret)
454                 return ret;
455
456         ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf, 1);
457         if (ret)
458                 return ret;
459
460         return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
461 }
462
463 int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len,
464                 const void *buf)
465 {
466         size_t actual, cmd_len;
467         int ret;
468         u8 cmd[4];
469
470         ret = spi_claim_bus(flash->spi);
471         if (ret) {
472                 debug("SF: Unable to claim SPI bus\n");
473                 return ret;
474         }
475
476         /* If the data is not word aligned, write out leading single byte */
477         actual = offset % 2;
478         if (actual) {
479                 ret = sst_byte_write(flash, offset, buf);
480                 if (ret)
481                         goto done;
482         }
483         offset += actual;
484
485         ret = spi_flash_cmd_write_enable(flash);
486         if (ret)
487                 goto done;
488
489         cmd_len = 4;
490         cmd[0] = CMD_SST_AAI_WP;
491         cmd[1] = offset >> 16;
492         cmd[2] = offset >> 8;
493         cmd[3] = offset;
494
495         for (; actual < len - 1; actual += 2) {
496                 debug("WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
497                       spi_w8r8(flash->spi, CMD_READ_STATUS), buf + actual,
498                       cmd[0], offset);
499
500                 ret = spi_flash_cmd_write(flash->spi, cmd, cmd_len,
501                                         buf + actual, 2);
502                 if (ret) {
503                         debug("SF: sst word program failed\n");
504                         break;
505                 }
506
507                 ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
508                 if (ret)
509                         break;
510
511                 cmd_len = 1;
512                 offset += 2;
513         }
514
515         if (!ret)
516                 ret = spi_flash_cmd_write_disable(flash);
517
518         /* If there is a single trailing byte, write it out */
519         if (!ret && actual != len)
520                 ret = sst_byte_write(flash, offset, buf + actual);
521
522  done:
523         debug("SF: sst: program %s %zu bytes @ 0x%zx\n",
524               ret ? "failure" : "success", len, offset - actual);
525
526         spi_release_bus(flash->spi);
527         return ret;
528 }
529
530 int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len,
531                 const void *buf)
532 {
533         size_t actual;
534         int ret;
535
536         ret = spi_claim_bus(flash->spi);
537         if (ret) {
538                 debug("SF: Unable to claim SPI bus\n");
539                 return ret;
540         }
541
542         for (actual = 0; actual < len; actual++) {
543                 ret = sst_byte_write(flash, offset, buf + actual);
544                 if (ret) {
545                         debug("SF: sst byte program failed\n");
546                         break;
547                 }
548                 offset++;
549         }
550
551         if (!ret)
552                 ret = spi_flash_cmd_write_disable(flash);
553
554         debug("SF: sst: program %s %zu bytes @ 0x%zx\n",
555               ret ? "failure" : "success", len, offset - actual);
556
557         spi_release_bus(flash->spi);
558         return ret;
559 }
560 #endif