2 * This file is part of the coreboot project.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
16 * Driver for SST serial flashes
19 #include <console/console.h>
20 #include <commonlib/helpers.h>
21 #include <spi_flash.h>
22 #include <spi-generic.h>
25 #include "spi_flash_internal.h"
27 #define CMD_SST_WREN 0x06 /* Write Enable */
28 #define CMD_SST_WRDI 0x04 /* Write Disable */
29 #define CMD_SST_RDSR 0x05 /* Read Status Register */
30 #define CMD_SST_WRSR 0x01 /* Write Status Register */
31 #define CMD_SST_EWSR 0x50 /* Enable Write Status Register */
32 #define CMD_SST_READ 0x03 /* Read Data Bytes */
33 #define CMD_SST_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */
34 #define CMD_SST_BP 0x02 /* Byte Program */
35 #define CMD_SST_AAI_WP 0xAD /* Auto Address Increment Word Program */
36 #define CMD_SST_SE 0x20 /* Sector Erase */
38 #define SST_SR_WIP (1 << 0) /* Write-in-Progress */
39 #define SST_SR_WEL (1 << 1) /* Write enable */
40 #define SST_SR_BP0 (1 << 2) /* Block Protection 0 */
41 #define SST_SR_BP1 (1 << 3) /* Block Protection 1 */
42 #define SST_SR_BP2 (1 << 4) /* Block Protection 2 */
43 #define SST_SR_AAI (1 << 6) /* Addressing mode */
44 #define SST_SR_BPL (1 << 7) /* BP bits lock */
46 struct sst_spi_flash_params
{
50 const struct spi_flash_ops
*ops
;
53 static int sst_write_ai(const struct spi_flash
*flash
, u32 offset
, size_t len
,
55 static int sst_write_256(const struct spi_flash
*flash
, u32 offset
, size_t len
,
58 static const struct spi_flash_ops spi_flash_ops_write_ai
= {
59 .write
= sst_write_ai
,
60 .erase
= spi_flash_cmd_erase
,
61 .status
= spi_flash_cmd_status
,
64 static const struct spi_flash_ops spi_flash_ops_write_256
= {
65 .write
= sst_write_256
,
66 .erase
= spi_flash_cmd_erase
,
67 .status
= spi_flash_cmd_status
,
70 #define SST_SECTOR_SIZE (4 * 1024)
71 static const struct sst_spi_flash_params sst_spi_flash_table
[] = {
75 .name
= "SST25VF040B",
76 .ops
= &spi_flash_ops_write_ai
,
80 .name
= "SST25VF080B",
81 .ops
= &spi_flash_ops_write_ai
,
86 .ops
= &spi_flash_ops_write_ai
,
90 .name
= "SST25VF016B",
91 .ops
= &spi_flash_ops_write_ai
,
95 .name
= "SST25VF032B",
96 .ops
= &spi_flash_ops_write_ai
,
100 .name
= "SST25VF064C",
101 .ops
= &spi_flash_ops_write_256
,
105 .name
= "SST25WF512",
106 .ops
= &spi_flash_ops_write_ai
,
110 .name
= "SST25WF010",
111 .ops
= &spi_flash_ops_write_ai
,
115 .name
= "SST25WF020",
116 .ops
= &spi_flash_ops_write_ai
,
120 .name
= "SST25WF040",
121 .ops
= &spi_flash_ops_write_ai
,
125 .name
= "SST25WF080",
126 .ops
= &spi_flash_ops_write_ai
,
130 .name
= "SST25WF080B",
131 .ops
= &spi_flash_ops_write_ai
,
136 sst_enable_writing(const struct spi_flash
*flash
)
138 int ret
= spi_flash_cmd(&flash
->spi
, CMD_SST_WREN
, NULL
, 0);
140 printk(BIOS_WARNING
, "SF: Enabling Write failed\n");
145 sst_enable_writing_status(const struct spi_flash
*flash
)
147 int ret
= spi_flash_cmd(&flash
->spi
, CMD_SST_EWSR
, NULL
, 0);
149 printk(BIOS_WARNING
, "SF: Enabling Write Status failed\n");
154 sst_disable_writing(const struct spi_flash
*flash
)
156 int ret
= spi_flash_cmd(&flash
->spi
, CMD_SST_WRDI
, NULL
, 0);
158 printk(BIOS_WARNING
, "SF: Disabling Write failed\n");
163 sst_byte_write(const struct spi_flash
*flash
, u32 offset
, const void *buf
)
173 #if CONFIG(DEBUG_SPI_FLASH)
174 printk(BIOS_SPEW
, "BP[%02x]: %p => cmd = { 0x%02x 0x%06x }\n",
175 spi_w8r8(&flash
->spi
, CMD_SST_RDSR
), buf
, cmd
[0], offset
);
178 ret
= sst_enable_writing(flash
);
182 ret
= spi_flash_cmd_write(&flash
->spi
, cmd
, sizeof(cmd
), buf
, 1);
186 return spi_flash_cmd_wait_ready(flash
, SPI_FLASH_PROG_TIMEOUT_MS
);
189 static int sst_write_256(const struct spi_flash
*flash
, u32 offset
, size_t len
,
192 size_t actual
, chunk_len
;
193 unsigned long byte_addr
;
194 unsigned long page_size
;
200 /* If the data is not word aligned, write out leading single byte */
203 ret
= sst_byte_write(flash
, offset
, buf
);
209 ret
= sst_enable_writing(flash
);
213 cmd
[0] = CMD_SST_AAI_WP
;
214 cmd
[1] = offset
>> 16;
215 cmd
[2] = offset
>> 8;
218 for (actual
= 0; actual
< len
; actual
+= chunk_len
) {
219 byte_addr
= offset
% page_size
;
220 chunk_len
= MIN(len
- actual
, page_size
- byte_addr
);
221 chunk_len
= spi_crop_chunk(&flash
->spi
, sizeof(cmd
), chunk_len
);
224 cmd
[1] = (offset
>> 16) & 0xff;
225 cmd
[2] = (offset
>> 8) & 0xff;
226 cmd
[3] = offset
& 0xff;
227 #if CONFIG(DEBUG_SPI_FLASH)
228 printk(BIOS_SPEW
, "PP: %p => cmd = { 0x%02x 0x%02x%02x%02x }"
229 " chunk_len = %zu\n",
230 buf
+ actual
, cmd
[0], cmd
[1], cmd
[2], cmd
[3], chunk_len
);
233 ret
= spi_flash_cmd(&flash
->spi
, CMD_SST_WREN
, NULL
, 0);
235 printk(BIOS_WARNING
, "SF: Enabling Write failed\n");
239 ret
= spi_flash_cmd_write(&flash
->spi
, cmd
, sizeof(cmd
),
240 buf
+ actual
, chunk_len
);
242 printk(BIOS_WARNING
, "SF: SST Page Program failed\n");
246 ret
= spi_flash_cmd_wait_ready(flash
,
247 SPI_FLASH_PROG_TIMEOUT_MS
);
255 #if CONFIG(DEBUG_SPI_FLASH)
256 printk(BIOS_SPEW
, "SF: SST: program %s %zu bytes @ 0x%lx\n",
257 ret
? "failure" : "success", len
, (unsigned long)offset
- actual
);
262 static int sst_write_ai(const struct spi_flash
*flash
, u32 offset
, size_t len
,
265 size_t actual
, cmd_len
;
269 /* If the data is not word aligned, write out leading single byte */
272 ret
= sst_byte_write(flash
, offset
, buf
);
278 ret
= sst_enable_writing(flash
);
283 cmd
[0] = CMD_SST_AAI_WP
;
284 cmd
[1] = offset
>> 16;
285 cmd
[2] = offset
>> 8;
288 for (; actual
< len
- 1; actual
+= 2) {
289 #if CONFIG(DEBUG_SPI_FLASH)
290 printk(BIOS_SPEW
, "WP[%02x]: %p => cmd = { 0x%02x 0x%06x }\n",
291 spi_w8r8(&flash
->spi
, CMD_SST_RDSR
), buf
+ actual
, cmd
[0],
295 ret
= spi_flash_cmd_write(&flash
->spi
, cmd
, cmd_len
,
298 printk(BIOS_WARNING
, "SF: SST word program failed\n");
302 ret
= spi_flash_cmd_wait_ready(flash
,
303 SPI_FLASH_PROG_TIMEOUT_MS
);
312 ret
= sst_disable_writing(flash
);
314 /* If there is a single trailing byte, write it out */
315 if (!ret
&& actual
!= len
)
316 ret
= sst_byte_write(flash
, offset
, buf
+ actual
);
319 #if CONFIG(DEBUG_SPI_FLASH)
320 printk(BIOS_SPEW
, "SF: SST: program %s %zu bytes @ 0x%lx\n",
321 ret
? "failure" : "success", len
, (unsigned long)offset
- actual
);
328 sst_unlock(const struct spi_flash
*flash
)
333 ret
= sst_enable_writing_status(flash
);
339 ret
= spi_flash_cmd_write(&flash
->spi
, &cmd
, 1, &status
, 1);
341 printk(BIOS_WARNING
, "SF: Unable to set status byte\n");
343 printk(BIOS_INFO
, "SF: SST: status = %x\n", spi_w8r8(&flash
->spi
, CMD_SST_RDSR
));
348 int spi_flash_probe_sst(const struct spi_slave
*spi
, u8
*idcode
,
349 struct spi_flash
*flash
)
351 const struct sst_spi_flash_params
*params
;
354 for (i
= 0; i
< ARRAY_SIZE(sst_spi_flash_table
); ++i
) {
355 params
= &sst_spi_flash_table
[i
];
356 if (params
->idcode1
== idcode
[2])
360 if (i
== ARRAY_SIZE(sst_spi_flash_table
)) {
361 printk(BIOS_WARNING
, "SF: Unsupported SST ID %02x\n", idcode
[1]);
365 memcpy(&flash
->spi
, spi
, sizeof(*spi
));
366 flash
->name
= params
->name
;
367 flash
->sector_size
= SST_SECTOR_SIZE
;
368 flash
->size
= flash
->sector_size
* params
->nr_sectors
;
369 flash
->erase_cmd
= CMD_SST_SE
;
370 flash
->status_cmd
= CMD_SST_RDSR
;
372 flash
->ops
= params
->ops
;
374 /* Flash powers up read-only, so clear BP# bits */