]> git.sur5r.net Git - u-boot/blob - drivers/mtd/spi/sf_ops.c
sf: Set quad enable bit support
[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 <spi.h>
13 #include <spi_flash.h>
14 #include <watchdog.h>
15
16 #include "sf_internal.h"
17
18 static void spi_flash_addr(u32 addr, u8 *cmd)
19 {
20         /* cmd[0] is actual command */
21         cmd[1] = addr >> 16;
22         cmd[2] = addr >> 8;
23         cmd[3] = addr >> 0;
24 }
25
26 int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr)
27 {
28         u8 cmd;
29         int ret;
30
31         cmd = CMD_WRITE_STATUS;
32         ret = spi_flash_write_common(flash, &cmd, 1, &sr, 1);
33         if (ret < 0) {
34                 debug("SF: fail to write status register\n");
35                 return ret;
36         }
37
38         return 0;
39 }
40
41 #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND)
42 static int spi_flash_cmd_write_config(struct spi_flash *flash, u8 cr)
43 {
44         u8 data[2];
45         u8 cmd;
46         int ret;
47
48         cmd = CMD_READ_STATUS;
49         ret = spi_flash_read_common(flash, &cmd, 1, &data[0], 1);
50         if (ret < 0) {
51                 debug("SF: fail to read status register\n");
52                 return ret;
53         }
54
55         cmd = CMD_WRITE_STATUS;
56         data[1] = cr;
57         ret = spi_flash_write_common(flash, &cmd, 1, &data, 2);
58         if (ret) {
59                 debug("SF: fail to write config register\n");
60                 return ret;
61         }
62
63         return 0;
64 }
65
66 int spi_flash_set_qeb_winspan(struct spi_flash *flash)
67 {
68         u8 qeb_status;
69         u8 cmd;
70         int ret;
71
72         cmd = CMD_READ_CONFIG;
73         ret = spi_flash_read_common(flash, &cmd, 1, &qeb_status, 1);
74         if (ret < 0) {
75                 debug("SF: fail to read config register\n");
76                 return ret;
77         }
78
79         if (qeb_status & STATUS_QEB_WINSPAN) {
80                 debug("SF: Quad enable bit is already set\n");
81         } else {
82                 ret = spi_flash_cmd_write_config(flash, STATUS_QEB_WINSPAN);
83                 if (ret < 0)
84                         return ret;
85         }
86
87         return ret;
88 }
89 #endif
90
91 #ifdef CONFIG_SPI_FLASH_BAR
92 static int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel)
93 {
94         u8 cmd;
95         int ret;
96
97         if (flash->bank_curr == bank_sel) {
98                 debug("SF: not require to enable bank%d\n", bank_sel);
99                 return 0;
100         }
101
102         cmd = flash->bank_write_cmd;
103         ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1);
104         if (ret < 0) {
105                 debug("SF: fail to write bank register\n");
106                 return ret;
107         }
108         flash->bank_curr = bank_sel;
109
110         return 0;
111 }
112
113 static int spi_flash_bank(struct spi_flash *flash, u32 offset)
114 {
115         u8 bank_sel;
116         int ret;
117
118         bank_sel = offset / SPI_FLASH_16MB_BOUN;
119
120         ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
121         if (ret) {
122                 debug("SF: fail to set bank%d\n", bank_sel);
123                 return ret;
124         }
125
126         return 0;
127 }
128 #endif
129
130 int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
131 {
132         struct spi_slave *spi = flash->spi;
133         unsigned long timebase;
134         int ret;
135         u8 status;
136         u8 check_status = 0x0;
137         u8 poll_bit = STATUS_WIP;
138         u8 cmd = flash->poll_cmd;
139
140         if (cmd == CMD_FLAG_STATUS) {
141                 poll_bit = STATUS_PEC;
142                 check_status = poll_bit;
143         }
144
145         ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN);
146         if (ret) {
147                 debug("SF: fail to read %s status register\n",
148                       cmd == CMD_READ_STATUS ? "read" : "flag");
149                 return ret;
150         }
151
152         timebase = get_timer(0);
153         do {
154                 WATCHDOG_RESET();
155
156                 ret = spi_xfer(spi, 8, NULL, &status, 0);
157                 if (ret)
158                         return -1;
159
160                 if ((status & poll_bit) == check_status)
161                         break;
162
163         } while (get_timer(timebase) < timeout);
164
165         spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
166
167         if ((status & poll_bit) == check_status)
168                 return 0;
169
170         /* Timed out */
171         debug("SF: time out!\n");
172         return -1;
173 }
174
175 int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
176                 size_t cmd_len, const void *buf, size_t buf_len)
177 {
178         struct spi_slave *spi = flash->spi;
179         unsigned long timeout = SPI_FLASH_PROG_TIMEOUT;
180         int ret;
181
182         if (buf == NULL)
183                 timeout = SPI_FLASH_PAGE_ERASE_TIMEOUT;
184
185         ret = spi_claim_bus(flash->spi);
186         if (ret) {
187                 debug("SF: unable to claim SPI bus\n");
188                 return ret;
189         }
190
191         ret = spi_flash_cmd_write_enable(flash);
192         if (ret < 0) {
193                 debug("SF: enabling write failed\n");
194                 return ret;
195         }
196
197         ret = spi_flash_cmd_write(spi, cmd, cmd_len, buf, buf_len);
198         if (ret < 0) {
199                 debug("SF: write cmd failed\n");
200                 return ret;
201         }
202
203         ret = spi_flash_cmd_wait_ready(flash, timeout);
204         if (ret < 0) {
205                 debug("SF: write %s timed out\n",
206                       timeout == SPI_FLASH_PROG_TIMEOUT ?
207                         "program" : "page erase");
208                 return ret;
209         }
210
211         spi_release_bus(spi);
212
213         return ret;
214 }
215
216 int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)
217 {
218         u32 erase_size;
219         u8 cmd[4];
220         int ret = -1;
221
222         erase_size = flash->erase_size;
223         if (offset % erase_size || len % erase_size) {
224                 debug("SF: Erase offset/length not multiple of erase size\n");
225                 return -1;
226         }
227
228         cmd[0] = flash->erase_cmd;
229         while (len) {
230 #ifdef CONFIG_SPI_FLASH_BAR
231                 ret = spi_flash_bank(flash, offset);
232                 if (ret < 0)
233                         return ret;
234 #endif
235                 spi_flash_addr(offset, cmd);
236
237                 debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
238                       cmd[2], cmd[3], offset);
239
240                 ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0);
241                 if (ret < 0) {
242                         debug("SF: erase failed\n");
243                         break;
244                 }
245
246                 offset += erase_size;
247                 len -= erase_size;
248         }
249
250         return ret;
251 }
252
253 int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
254                 size_t len, const void *buf)
255 {
256         unsigned long byte_addr, page_size;
257         size_t chunk_len, actual;
258         u8 cmd[4];
259         int ret = -1;
260
261         page_size = flash->page_size;
262
263         cmd[0] = flash->write_cmd;
264         for (actual = 0; actual < len; actual += chunk_len) {
265 #ifdef CONFIG_SPI_FLASH_BAR
266                 ret = spi_flash_bank(flash, offset);
267                 if (ret < 0)
268                         return ret;
269 #endif
270                 byte_addr = offset % page_size;
271                 chunk_len = min(len - actual, page_size - byte_addr);
272
273                 if (flash->spi->max_write_size)
274                         chunk_len = min(chunk_len, flash->spi->max_write_size);
275
276                 spi_flash_addr(offset, cmd);
277
278                 debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
279                       buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
280
281                 ret = spi_flash_write_common(flash, cmd, sizeof(cmd),
282                                         buf + actual, chunk_len);
283                 if (ret < 0) {
284                         debug("SF: write failed\n");
285                         break;
286                 }
287
288                 offset += chunk_len;
289         }
290
291         return ret;
292 }
293
294 int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
295                 size_t cmd_len, void *data, size_t data_len)
296 {
297         struct spi_slave *spi = flash->spi;
298         int ret;
299
300         ret = spi_claim_bus(flash->spi);
301         if (ret) {
302                 debug("SF: unable to claim SPI bus\n");
303                 return ret;
304         }
305
306         ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len);
307         if (ret < 0) {
308                 debug("SF: read cmd failed\n");
309                 return ret;
310         }
311
312         spi_release_bus(spi);
313
314         return ret;
315 }
316
317 int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
318                 size_t len, void *data)
319 {
320         u8 cmd[5], bank_sel = 0;
321         u32 remain_len, read_len;
322         int ret = -1;
323
324         /* Handle memory-mapped SPI */
325         if (flash->memory_map) {
326                 ret = spi_claim_bus(flash->spi);
327                 if (ret) {
328                         debug("SF: unable to claim SPI bus\n");
329                         return ret;
330                 }
331                 spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP);
332                 memcpy(data, flash->memory_map + offset, len);
333                 spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP_END);
334                 spi_release_bus(flash->spi);
335                 return 0;
336         }
337
338         cmd[0] = flash->read_cmd;
339         cmd[4] = 0x00;
340
341         while (len) {
342 #ifdef CONFIG_SPI_FLASH_BAR
343                 bank_sel = offset / SPI_FLASH_16MB_BOUN;
344
345                 ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
346                 if (ret) {
347                         debug("SF: fail to set bank%d\n", bank_sel);
348                         return ret;
349                 }
350 #endif
351                 remain_len = (SPI_FLASH_16MB_BOUN * (bank_sel + 1)) - offset;
352                 if (len < remain_len)
353                         read_len = len;
354                 else
355                         read_len = remain_len;
356
357                 spi_flash_addr(offset, cmd);
358
359                 ret = spi_flash_read_common(flash, cmd, sizeof(cmd),
360                                                         data, read_len);
361                 if (ret < 0) {
362                         debug("SF: read failed\n");
363                         break;
364                 }
365
366                 offset += read_len;
367                 len -= read_len;
368                 data += read_len;
369         }
370
371         return ret;
372 }
373
374 #ifdef CONFIG_SPI_FLASH_SST
375 static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)
376 {
377         int ret;
378         u8 cmd[4] = {
379                 CMD_SST_BP,
380                 offset >> 16,
381                 offset >> 8,
382                 offset,
383         };
384
385         debug("BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
386               spi_w8r8(flash->spi, CMD_READ_STATUS), buf, cmd[0], offset);
387
388         ret = spi_flash_cmd_write_enable(flash);
389         if (ret)
390                 return ret;
391
392         ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf, 1);
393         if (ret)
394                 return ret;
395
396         return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
397 }
398
399 int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len,
400                 const void *buf)
401 {
402         size_t actual, cmd_len;
403         int ret;
404         u8 cmd[4];
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         /* If the data is not word aligned, write out leading single byte */
413         actual = offset % 2;
414         if (actual) {
415                 ret = sst_byte_write(flash, offset, buf);
416                 if (ret)
417                         goto done;
418         }
419         offset += actual;
420
421         ret = spi_flash_cmd_write_enable(flash);
422         if (ret)
423                 goto done;
424
425         cmd_len = 4;
426         cmd[0] = CMD_SST_AAI_WP;
427         cmd[1] = offset >> 16;
428         cmd[2] = offset >> 8;
429         cmd[3] = offset;
430
431         for (; actual < len - 1; actual += 2) {
432                 debug("WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
433                       spi_w8r8(flash->spi, CMD_READ_STATUS), buf + actual,
434                       cmd[0], offset);
435
436                 ret = spi_flash_cmd_write(flash->spi, cmd, cmd_len,
437                                         buf + actual, 2);
438                 if (ret) {
439                         debug("SF: sst word program failed\n");
440                         break;
441                 }
442
443                 ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
444                 if (ret)
445                         break;
446
447                 cmd_len = 1;
448                 offset += 2;
449         }
450
451         if (!ret)
452                 ret = spi_flash_cmd_write_disable(flash);
453
454         /* If there is a single trailing byte, write it out */
455         if (!ret && actual != len)
456                 ret = sst_byte_write(flash, offset, buf + actual);
457
458  done:
459         debug("SF: sst: program %s %zu bytes @ 0x%zx\n",
460               ret ? "failure" : "success", len, offset - actual);
461
462         spi_release_bus(flash->spi);
463         return ret;
464 }
465 #endif