blob: f3aa0000018c39fb897c5cf1bc8f6daf4bb86644 [file] [log] [blame]
David Hendricks398714f2014-07-03 17:49:41 -07001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2014 Google Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * Neither the name of Google or the names of contributors or
18 * licensors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * This software is provided "AS IS," without a warranty of any kind.
22 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
23 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
24 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
25 * GOOGLE INC AND ITS LICENSORS SHALL NOT BE LIABLE
26 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
27 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
28 * GOOGLE OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
29 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
30 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
31 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
32 * EVEN IF GOOGLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
33 *
David Hendricks43d9afd2015-03-13 20:54:23 -070034 * s25f.c - Helper functions for Spansion S25FL and S25FS SPI flash chips.
Vadim Bendebury3a501162014-10-21 20:38:13 -070035 * Uses 24 bit addressing for the FS chips and 32 bit addressing for the FL
36 * chips (which is required by the overlayed sector size devices).
37 * TODO: Implement fancy hybrid sector architecture helpers.
David Hendricks398714f2014-07-03 17:49:41 -070038 */
39
Vadim Bendebury3a501162014-10-21 20:38:13 -070040#include <string.h>
41
David Hendricks398714f2014-07-03 17:49:41 -070042#include "chipdrivers.h"
43#include "spi.h"
David Hendricks43d9afd2015-03-13 20:54:23 -070044#include "writeprotect.h"
David Hendricks398714f2014-07-03 17:49:41 -070045
David Hendricks43d9afd2015-03-13 20:54:23 -070046/*
47 * RDAR and WRAR are supported on chips which have more than one set of status
48 * and control registers and take an address of the register to read/write.
49 * WRR, RDSR2, and RDCR are used on chips with a more limited set of control/
50 * status registers.
51 *
52 * WRR is somewhat peculiar. It shares the same opcode as JEDEC_WRSR, and if
53 * given one data byte (following the opcode) it acts the same way. If it's
54 * given two data bytes, the first data byte overwrites status register 1
55 * and the second data byte overwrites config register 1.
56 */
57#define CMD_WRR 0x01
58#define CMD_WRDI 0x04
59#define CMD_RDSR2 0x07 /* note: read SR1 with JEDEC RDSR opcode */
60#define CMD_RDCR 0x35
David Hendricks398714f2014-07-03 17:49:41 -070061#define CMD_RDAR 0x65
62#define CMD_WRAR 0x71
David Hendricks43d9afd2015-03-13 20:54:23 -070063
64/* TODO: For now, commands which use an address assume 24-bit addressing */
65#define CMD_WRR_LEN 3
66#define CMD_WRDI_LEN 1
David Hendricks398714f2014-07-03 17:49:41 -070067#define CMD_RDAR_LEN 4
68#define CMD_WRAR_LEN 5
69
70#define CMD_RSTEN 0x66
71#define CMD_RST 0x99
72
David Hendricksa9884852014-12-11 15:31:12 -080073#define CR1NV_ADDR 0x000002
David Hendricks43d9afd2015-03-13 20:54:23 -070074#define CR1_BPNV_O (1 << 3)
75#define CR1_TBPROT_O (1 << 5)
David Hendricks398714f2014-07-03 17:49:41 -070076#define CR3NV_ADDR 0x000004
77#define CR3NV_20H_NV (1 << 3)
78
David Hendricks43d9afd2015-03-13 20:54:23 -070079/* See "Embedded Algorithm Performance Tables for additional timing specs. */
80#define T_W 145 * 1000 /* NV register write time (145ms) */
81#define T_RPH 35 /* Reset pulse hold time (35us) */
82#define S25FS_T_SE 145 * 1000 /* Sector Erase Time (145ms) */
83#define S25FL_T_SE 130 * 1000 /* Sector Erase Time (130ms) */
84
85static int s25f_legacy_software_reset(const struct flashchip *flash)
86{
87 int result;
88 struct spi_command cmds[] = {
89 {
90 .writecnt = 1,
91 .writearr = (const unsigned char[]){ CMD_RSTEN },
92 .readcnt = 0,
93 .readarr = NULL,
94 }, {
95 .writecnt = 1,
96 .writearr = (const unsigned char[]){ 0xf0 },
97 .readcnt = 0,
98 .readarr = NULL,
99 }, {
100 .writecnt = 0,
101 .writearr = NULL,
102 .readcnt = 0,
103 .readarr = NULL,
104 }};
105
106 result = spi_send_multicommand(cmds);
107 if (result) {
108 msg_cerr("%s failed during command execution\n", __func__);
109 return result;
110 }
111
112 /* Allow time for reset command to execute. The datasheet specifies
113 * Trph = 35us, double that to be safe. */
114 programmer_delay(T_RPH * 2);
115
116 return 0;
117}
118
119/* "Legacy software reset" is disabled by default on S25FS, use this instead. */
120static int s25fs_software_reset(struct flashchip *flash)
121{
122 int result;
123 struct spi_command cmds[] = {
124 {
125 .writecnt = 1,
126 .writearr = (const unsigned char[]){ CMD_RSTEN },
127 .readcnt = 0,
128 .readarr = NULL,
129 }, {
130 .writecnt = 1,
131 .writearr = (const unsigned char[]){ CMD_RST },
132 .readcnt = 0,
133 .readarr = NULL,
134 }, {
135 .writecnt = 0,
136 .writearr = NULL,
137 .readcnt = 0,
138 .readarr = NULL,
139 }};
140
141 result = spi_send_multicommand(cmds);
142 if (result) {
143 msg_cerr("%s failed during command execution\n", __func__);
144 return result;
145 }
146
147 /* Allow time for reset command to execute. Double tRPH to be safe. */
148 programmer_delay(T_RPH * 2);
149
150 return 0;
151}
152
153static int s25f_poll_status(const struct flashchip *flash)
154{
155 uint8_t tmp = spi_read_status_register();
156
157 while (tmp & JEDEC_RDSR_BIT_WIP) {
158 /*
159 * The WIP bit on S25F chips remains set to 1 if erase or
160 * programming errors occur, so we must check for those
161 * errors here. If an error is encountered, do a software
162 * reset to clear WIP and other volatile bits, otherwise
163 * the chip will be unresponsive to further commands.
164 */
165 if (tmp & JEDEC_RDSR_BIT_ERASE_ERR) {
166 msg_cerr("Erase error occurred\n");
167 s25f_legacy_software_reset(flash);
168 return -1;
169 }
170
171 if (tmp & (1 << 6)) {
172 msg_cerr("Programming error occurred\n");
173 s25f_legacy_software_reset(flash);
174 return -1;
175 }
176
177 programmer_delay(1000 * 10);
178 tmp = spi_read_status_register();
179 }
180
181 return 0;
182}
183
184/* "Read Any Register" instruction only supported on S25FS */
David Hendricks636c74a2014-12-12 11:30:00 -0800185static int s25fs_read_cr(const struct flashchip *flash, uint32_t addr)
David Hendricks398714f2014-07-03 17:49:41 -0700186{
187 int result;
188 uint8_t cfg;
189 /* By default, 8 dummy cycles are necessary for variable-latency
190 commands such as RDAR (see CR2NV[3:0]). */
191 unsigned char read_cr_cmd[] = {
192 CMD_RDAR,
193 (addr >> 16) & 0xff,
194 (addr >> 8) & 0xff,
195 (addr & 0xff),
196 0x00, 0x00, 0x00, 0x00,
197 0x00, 0x00, 0x00, 0x00,
198 };
199
200 result = spi_send_command(sizeof(read_cr_cmd), 1, read_cr_cmd, &cfg);
201 if (result) {
202 msg_cerr("%s failed during command execution at address 0x%x\n",
203 __func__, addr);
David Hendricks688b5e22014-12-12 11:15:44 -0800204 return -1;
David Hendricks398714f2014-07-03 17:49:41 -0700205 }
206
207 return cfg;
208}
209
David Hendricks43d9afd2015-03-13 20:54:23 -0700210static int s25f_read_cr1(const struct flashchip *flash)
211{
212 int result;
213 uint8_t cfg;
214 unsigned char read_cr_cmd[] = { CMD_RDCR };
215
216 result = spi_send_command(sizeof(read_cr_cmd), 1, read_cr_cmd, &cfg);
217 if (result) {
218 msg_cerr("%s failed during command execution\n", __func__);
219 return -1;
220 }
221
222 return cfg;
223}
224
225/* "Write Any Register" instruction only supported on S25FS */
226static int s25fs_write_cr(const struct flashchip *flash,
227 uint32_t addr, uint8_t data)
David Hendricks398714f2014-07-03 17:49:41 -0700228{
229 int result;
230 struct spi_command cmds[] = {
231 {
232 .writecnt = JEDEC_WREN_OUTSIZE,
233 .writearr = (const unsigned char[]){ JEDEC_WREN },
234 .readcnt = 0,
235 .readarr = NULL,
236 }, {
237 .writecnt = CMD_WRAR_LEN,
238 .writearr = (const unsigned char[]){
239 CMD_WRAR,
240 (addr >> 16) & 0xff,
241 (addr >> 8) & 0xff,
242 (addr & 0xff),
243 data
244 },
245 .readcnt = 0,
246 .readarr = NULL,
247 }, {
248 .writecnt = 0,
249 .writearr = NULL,
250 .readcnt = 0,
251 .readarr = NULL,
252 }};
253
254 result = spi_send_multicommand(cmds);
255 if (result) {
256 msg_cerr("%s failed during command execution at address 0x%x\n",
257 __func__, addr);
David Hendricks688b5e22014-12-12 11:15:44 -0800258 return -1;
David Hendricks398714f2014-07-03 17:49:41 -0700259 }
260
David Hendricks43d9afd2015-03-13 20:54:23 -0700261 programmer_delay(T_W);
262 return s25f_poll_status(flash);
David Hendricks398714f2014-07-03 17:49:41 -0700263}
264
David Hendricks43d9afd2015-03-13 20:54:23 -0700265static int s25f_write_cr1(const struct flashchip *flash, uint8_t data)
David Hendricks398714f2014-07-03 17:49:41 -0700266{
267 int result;
268 struct spi_command cmds[] = {
269 {
David Hendricks43d9afd2015-03-13 20:54:23 -0700270 .writecnt = JEDEC_WREN_OUTSIZE,
271 .writearr = (const unsigned char[]){ JEDEC_WREN },
David Hendricks398714f2014-07-03 17:49:41 -0700272 .readcnt = 0,
273 .readarr = NULL,
274 }, {
David Hendricks43d9afd2015-03-13 20:54:23 -0700275 .writecnt = CMD_WRR_LEN,
276 .writearr = (const unsigned char[]){
277 CMD_WRR,
278 spi_read_status_register(),
279 data,
280 },
David Hendricks398714f2014-07-03 17:49:41 -0700281 .readcnt = 0,
282 .readarr = NULL,
283 }, {
284 .writecnt = 0,
285 .writearr = NULL,
286 .readcnt = 0,
287 .readarr = NULL,
288 }};
289
290 result = spi_send_multicommand(cmds);
291 if (result) {
292 msg_cerr("%s failed during command execution\n", __func__);
David Hendricks43d9afd2015-03-13 20:54:23 -0700293 return -1;
David Hendricks398714f2014-07-03 17:49:41 -0700294 }
295
David Hendricks43d9afd2015-03-13 20:54:23 -0700296 programmer_delay(T_W);
297 return s25f_poll_status(flash);
David Hendricks398714f2014-07-03 17:49:41 -0700298}
299
300static int s25fs_restore_cr3nv(struct flashchip *flash, uint8_t cfg)
301{
302 int ret = 0;
303
304 msg_cdbg("Restoring CR3NV value to 0x%02x\n", cfg);
David Hendricks636c74a2014-12-12 11:30:00 -0800305 ret |= s25fs_write_cr(flash, CR3NV_ADDR, cfg);
David Hendricks398714f2014-07-03 17:49:41 -0700306 ret |= s25fs_software_reset(flash);
307 return ret;
308}
309
David Hendricksa9884852014-12-11 15:31:12 -0800310/* returns state of top/bottom block protection, or <0 to indicate error */
311int s25fs_tbprot_o(const struct flashchip *flash)
312{
David Hendricks43d9afd2015-03-13 20:54:23 -0700313 int cr1 = s25f_read_cr1(flash);
David Hendricksa9884852014-12-11 15:31:12 -0800314
David Hendricks43d9afd2015-03-13 20:54:23 -0700315 if (cr1 < 0)
David Hendricksa9884852014-12-11 15:31:12 -0800316 return -1;
317
318 /*
319 * 1 = BP starts at bottom (low address)
320 * 0 = BP start at top (high address)
321 */
David Hendricks43d9afd2015-03-13 20:54:23 -0700322 return cr1 & CR1_TBPROT_O ? 1 : 0;
David Hendricksa9884852014-12-11 15:31:12 -0800323}
324
David Hendricks398714f2014-07-03 17:49:41 -0700325int s25fs_block_erase_d8(struct flashchip *flash,
326 unsigned int addr, unsigned int blocklen)
327{
328 unsigned char cfg;
329 int result;
330 static int cr3nv_checked = 0;
331
332 struct spi_command erase_cmds[] = {
333 {
334 .writecnt = JEDEC_WREN_OUTSIZE,
335 .writearr = (const unsigned char[]){ JEDEC_WREN },
336 .readcnt = 0,
337 .readarr = NULL,
338 }, {
339 .writecnt = JEDEC_BE_D8_OUTSIZE,
340 .writearr = (const unsigned char[]){
341 JEDEC_BE_D8,
342 (addr >> 16) & 0xff,
343 (addr >> 8) & 0xff,
344 (addr & 0xff)
345 },
346 .readcnt = 0,
347 .readarr = NULL,
348 }, {
349 .writecnt = 0,
350 .writearr = NULL,
351 .readcnt = 0,
352 .readarr = NULL,
353 }};
354
355 /* Check if hybrid sector architecture is in use and, if so,
356 * switch to uniform sectors. */
357 if (!cr3nv_checked) {
David Hendricks636c74a2014-12-12 11:30:00 -0800358 cfg = s25fs_read_cr(flash, CR3NV_ADDR);
David Hendricks398714f2014-07-03 17:49:41 -0700359 if (!(cfg & CR3NV_20H_NV)) {
David Hendricks636c74a2014-12-12 11:30:00 -0800360 s25fs_write_cr(flash, CR3NV_ADDR, cfg | CR3NV_20H_NV);
David Hendricks398714f2014-07-03 17:49:41 -0700361 s25fs_software_reset(flash);
362
David Hendricks636c74a2014-12-12 11:30:00 -0800363 cfg = s25fs_read_cr(flash, CR3NV_ADDR);
David Hendricks398714f2014-07-03 17:49:41 -0700364 if (!(cfg & CR3NV_20H_NV)) {
365 msg_cerr("%s: Unable to enable uniform "
366 "block sizes.\n", __func__);
367 return 1;
368 }
369
370 msg_cdbg("\n%s: CR3NV updated (0x%02x -> 0x%02x)\n",
371 __func__, cfg,
David Hendricks636c74a2014-12-12 11:30:00 -0800372 s25fs_read_cr(flash, CR3NV_ADDR));
David Hendricks398714f2014-07-03 17:49:41 -0700373 /* Restore CR3V when flashrom exits */
374 register_chip_restore(s25fs_restore_cr3nv, flash, cfg);
375 }
376
377 cr3nv_checked = 1;
378 }
379
380 result = spi_send_multicommand(erase_cmds);
381 if (result) {
382 msg_cerr("%s failed during command execution at address 0x%x\n",
383 __func__, addr);
384 return result;
385 }
386
David Hendricks43d9afd2015-03-13 20:54:23 -0700387 programmer_delay(S25FS_T_SE);
388 return s25f_poll_status(flash);
David Hendricks398714f2014-07-03 17:49:41 -0700389}
Vadim Bendebury3a501162014-10-21 20:38:13 -0700390
391int s25fl_block_erase(struct flashchip *flash,
392 unsigned int addr, unsigned int blocklen)
393{
394 unsigned char status;
395 int result;
Vadim Bendebury3a501162014-10-21 20:38:13 -0700396
397 struct spi_command erase_cmds[] = {
398 {
399 .writecnt = JEDEC_WREN_OUTSIZE,
400 .writearr = (const unsigned char[]){
401 JEDEC_WREN
402 },
403 .readcnt = 0,
404 .readarr = NULL,
405 }, {
406 .writecnt = JEDEC_BE_DC_OUTSIZE,
407 .writearr = (const unsigned char[]){
408 JEDEC_BE_DC,
409 (addr >> 24) & 0xff,
410 (addr >> 16) & 0xff,
411 (addr >> 8) & 0xff,
412 (addr & 0xff)
413 },
414 .readcnt = 0,
415 .readarr = NULL,
416 }, {
417 .writecnt = 0,
418 .readcnt = 0,
419 }
420 };
421
422 result = spi_send_multicommand(erase_cmds);
423 if (result) {
424 msg_cerr("%s failed during command execution at address 0x%x\n",
425 __func__, addr);
426 return result;
427 }
428
David Hendricks43d9afd2015-03-13 20:54:23 -0700429 programmer_delay(S25FL_T_SE);
430 return s25f_poll_status(flash);
Vadim Bendebury3a501162014-10-21 20:38:13 -0700431}
432
433
434int probe_spi_big_spansion(struct flashchip *flash)
435{
436 static const unsigned char cmd = JEDEC_RDID;
437 int ret;
438 unsigned char dev_id[6]; /* We care only about 6 first bytes */
439
440 ret = spi_send_command(sizeof(cmd), sizeof(dev_id), &cmd, dev_id);
441
442 if (!ret) {
443 int i;
444
445 for (i = 0; i < sizeof(dev_id); i++)
446 msg_gdbg(" 0x%02x", dev_id[i]);
447 msg_gdbg(".\n");
448
449 if (dev_id[0] == flash->manufacture_id) {
450 union {
451 uint8_t array[4];
452 uint32_t whole;
453 } model_id;
454
455 /*
456 * The structure of the RDID output is as follows:
457 *
458 * offset value meaning
459 * 00h 01h Manufacturer ID for Spansion
460 * 01h 20h 128 Mb capacity
461 * 01h 02h 256 Mb capacity
462 * 02h 18h 128 Mb capacity
463 * 02h 19h 256 Mb capacity
464 * 03h 4Dh Full size of the RDID output (ignored)
465 * 04h 00h FS: 256-kB physical sectors
466 * 04h 01h FS: 64-kB physical sectors
467 * 04h 00h FL: 256-kB physical sectors
468 * 04h 01h FL: Mix of 64-kB and 4KB overlayed sectors
469 * 05h 80h FL family
470 * 05h 81h FS family
471 *
472 * Need to use bytes 1, 2, 4, and 5 to properly identify one of eight
473 * possible chips:
474 *
475 * 2 types * 2 possible sizes * 2 possible sector layouts
476 *
477 */
478 memcpy(model_id.array, dev_id + 1, 2);
479 memcpy(model_id.array + 2, dev_id + 4, 2);
480 if (be_to_cpu32(model_id.whole) == flash->model_id)
481 return 1;
482 }
483 }
484 return 0;
485}