1 /* This file is part of the coreboot project. */
2 /* SPDX-License-Identifier: GPL-2.0-or-later */
5 * Driver for SST serial flashes
8 #include <console/console.h>
9 #include <commonlib/helpers.h>
10 #include <spi_flash.h>
11 #include <spi-generic.h>
14 #include "spi_flash_internal.h"
16 #define CMD_SST_WREN 0x06 /* Write Enable */
17 #define CMD_SST_WRDI 0x04 /* Write Disable */
18 #define CMD_SST_RDSR 0x05 /* Read Status Register */
19 #define CMD_SST_WRSR 0x01 /* Write Status Register */
20 #define CMD_SST_EWSR 0x50 /* Enable Write Status Register */
21 #define CMD_SST_READ 0x03 /* Read Data Bytes */
22 #define CMD_SST_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */
23 #define CMD_SST_BP 0x02 /* Byte Program */
24 #define CMD_SST_PP 0x02 /* Page Program */
25 #define CMD_SST_AAI_WP 0xAD /* Auto Address Increment Word Program */
26 #define CMD_SST_SE 0x20 /* Sector Erase */
28 #define SST_SR_WIP (1 << 0) /* Write-in-Progress */
29 #define SST_SR_WEL (1 << 1) /* Write enable */
30 #define SST_SR_BP0 (1 << 2) /* Block Protection 0 */
31 #define SST_SR_BP1 (1 << 3) /* Block Protection 1 */
32 #define SST_SR_BP2 (1 << 4) /* Block Protection 2 */
33 #define SST_SR_AAI (1 << 6) /* Addressing mode */
34 #define SST_SR_BPL (1 << 7) /* BP bits lock */
36 static const struct spi_flash_part_id flash_table_ai
[] = {
40 .nr_sectors_shift
= 7,
44 .nr_sectors_shift
= 8,
48 .nr_sectors_shift
= 8,
52 .nr_sectors_shift
= 9,
56 .nr_sectors_shift
= 10,
60 .nr_sectors_shift
= 4,
64 .nr_sectors_shift
= 5,
68 .nr_sectors_shift
= 6,
72 .nr_sectors_shift
= 7,
76 .nr_sectors_shift
= 8,
80 .nr_sectors_shift
= 8,
84 static const struct spi_flash_part_id flash_table_pp256
[] = {
88 .nr_sectors_shift
= 11,
93 sst_enable_writing(const struct spi_flash
*flash
)
95 int ret
= spi_flash_cmd(&flash
->spi
, CMD_SST_WREN
, NULL
, 0);
97 printk(BIOS_WARNING
, "SF: Enabling Write failed\n");
102 sst_enable_writing_status(const struct spi_flash
*flash
)
104 int ret
= spi_flash_cmd(&flash
->spi
, CMD_SST_EWSR
, NULL
, 0);
106 printk(BIOS_WARNING
, "SF: Enabling Write Status failed\n");
111 sst_disable_writing(const struct spi_flash
*flash
)
113 int ret
= spi_flash_cmd(&flash
->spi
, CMD_SST_WRDI
, NULL
, 0);
115 printk(BIOS_WARNING
, "SF: Disabling Write failed\n");
120 sst_byte_write(const struct spi_flash
*flash
, u32 offset
, const void *buf
)
130 #if CONFIG(DEBUG_SPI_FLASH)
131 printk(BIOS_SPEW
, "BP[%02x]: %p => cmd = { 0x%02x 0x%06x }\n",
132 spi_w8r8(&flash
->spi
, CMD_SST_RDSR
), buf
, cmd
[0], offset
);
135 ret
= sst_enable_writing(flash
);
139 ret
= spi_flash_cmd_write(&flash
->spi
, cmd
, sizeof(cmd
), buf
, 1);
143 return spi_flash_cmd_wait_ready(flash
, SPI_FLASH_PROG_TIMEOUT_MS
);
146 static int sst_write_ai(const struct spi_flash
*flash
, u32 offset
, size_t len
,
149 size_t actual
, cmd_len
;
153 /* If the data is not word aligned, write out leading single byte */
156 ret
= sst_byte_write(flash
, offset
, buf
);
162 ret
= sst_enable_writing(flash
);
167 cmd
[0] = CMD_SST_AAI_WP
;
168 cmd
[1] = offset
>> 16;
169 cmd
[2] = offset
>> 8;
172 for (; actual
< len
- 1; actual
+= 2) {
173 #if CONFIG(DEBUG_SPI_FLASH)
174 printk(BIOS_SPEW
, "WP[%02x]: %p => cmd = { 0x%02x 0x%06x }\n",
175 spi_w8r8(&flash
->spi
, CMD_SST_RDSR
), buf
+ actual
, cmd
[0],
179 ret
= spi_flash_cmd_write(&flash
->spi
, cmd
, cmd_len
,
182 printk(BIOS_WARNING
, "SF: SST word program failed\n");
186 ret
= spi_flash_cmd_wait_ready(flash
,
187 SPI_FLASH_PROG_TIMEOUT_MS
);
196 ret
= sst_disable_writing(flash
);
198 /* If there is a single trailing byte, write it out */
199 if (!ret
&& actual
!= len
)
200 ret
= sst_byte_write(flash
, offset
, buf
+ actual
);
203 #if CONFIG(DEBUG_SPI_FLASH)
204 printk(BIOS_SPEW
, "SF: SST: program %s %zu bytes @ 0x%lx\n",
205 ret
? "failure" : "success", len
, (unsigned long)offset
- actual
);
210 /* Flash powers up read-only, so clear BP# bits */
211 static int sst_unlock(const struct spi_flash
*flash
)
216 ret
= sst_enable_writing_status(flash
);
222 ret
= spi_flash_cmd_write(&flash
->spi
, &cmd
, 1, &status
, 1);
224 printk(BIOS_WARNING
, "SF: Unable to set status byte\n");
226 printk(BIOS_INFO
, "SF: SST: status = %x\n", spi_w8r8(&flash
->spi
, CMD_SST_RDSR
));
231 static const struct spi_flash_ops_descriptor descai
= {
232 .erase_cmd
= CMD_SST_SE
,
233 .status_cmd
= CMD_SST_RDSR
,
234 .wren_cmd
= CMD_SST_WREN
,
236 .read
= spi_flash_cmd_read
,
237 .write
= sst_write_ai
,
238 .erase
= spi_flash_cmd_erase
,
239 .status
= spi_flash_cmd_status
,
243 const struct spi_flash_vendor_info spi_flash_sst_ai_vi
= {
245 .sector_size_kib_shift
= 2,
246 .match_id_mask
[0] = 0xff,
247 .ids
= flash_table_ai
,
248 .nr_part_ids
= ARRAY_SIZE(flash_table_ai
),
250 .after_probe
= sst_unlock
,
253 const struct spi_flash_vendor_info spi_flash_sst_vi
= {
255 .page_size_shift
= 8,
256 .sector_size_kib_shift
= 2,
257 .match_id_mask
[0] = 0xff,
258 .ids
= flash_table_pp256
,
259 .nr_part_ids
= ARRAY_SIZE(flash_table_pp256
),
260 .desc
= &spi_flash_pp_0x20_sector_desc
,
261 .after_probe
= sst_unlock
,