diff options
-rw-r--r-- | src/drivers/spi/gigadevice.c | 12 | ||||
-rw-r--r-- | src/drivers/spi/macronix.c | 28 | ||||
-rw-r--r-- | src/drivers/spi/spi_flash.c | 51 | ||||
-rw-r--r-- | src/drivers/spi/spi_flash_internal.h | 6 | ||||
-rw-r--r-- | src/drivers/spi/winbond.c | 15 | ||||
-rw-r--r-- | src/include/spi_flash.h | 5 |
6 files changed, 100 insertions, 17 deletions
diff --git a/src/drivers/spi/gigadevice.c b/src/drivers/spi/gigadevice.c index 15ad9078cf..fc2a405302 100644 --- a/src/drivers/spi/gigadevice.c +++ b/src/drivers/spi/gigadevice.c @@ -31,72 +31,84 @@ static const struct spi_flash_part_id flash_table[] = { .id[0] = 0x4014, .nr_sectors_shift = 8, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, }, /* also GD25Q80B */ { /* GD25Q16 */ .id[0] = 0x4015, .nr_sectors_shift = 9, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, }, /* also GD25Q16B */ { /* GD25Q32B */ .id[0] = 0x4016, .nr_sectors_shift = 10, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, }, /* also GD25Q32B */ { /* GD25Q64 */ .id[0] = 0x4017, .nr_sectors_shift = 11, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, }, /* also GD25Q64B, GD25B64C */ { /* GD25Q128 */ .id[0] = 0x4018, .nr_sectors_shift = 12, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, }, /* also GD25Q128B */ { /* GD25VQ80C */ .id[0] = 0x4214, .nr_sectors_shift = 8, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, }, { /* GD25VQ16C */ .id[0] = 0x4215, .nr_sectors_shift = 9, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, }, { /* GD25LQ80 */ .id[0] = 0x6014, .nr_sectors_shift = 8, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, }, { /* GD25LQ16 */ .id[0] = 0x6015, .nr_sectors_shift = 9, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, }, { /* GD25LQ32 */ .id[0] = 0x6016, .nr_sectors_shift = 10, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, }, { /* GD25LQ64C */ .id[0] = 0x6017, .nr_sectors_shift = 11, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, }, /* also GD25LB64C */ { /* GD25LQ128 */ .id[0] = 0x6018, .nr_sectors_shift = 12, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, }, }; diff --git a/src/drivers/spi/macronix.c b/src/drivers/spi/macronix.c index 69e7a9f4c7..b6981e045d 100644 --- a/src/drivers/spi/macronix.c +++ b/src/drivers/spi/macronix.c @@ -63,55 +63,75 @@ static const struct spi_flash_part_id flash_table[] = { .id[0] = 0x2415, .nr_sectors_shift = 9, }, + /* + * NOTE: C225xx JEDEC IDs are basically useless because Macronix keeps + * reusing the same IDs for vastly different chips. 35E versions always + * seem to support Dual I/O but not Dual Output, while 35F versions seem + * to support both, so we only set Dual I/O here to improve our chances + * of compatibility. Since Macronix makes it impossible to search all + * different parts that it recklessly assigned the same IDs to, it's + * hard to know if there may be parts that don't even support Dual I/O + * with these IDs, though (or what we should do if there are). + */ { /* MX25L1635E */ .id[0] = 0x2515, .nr_sectors_shift = 9, + .fast_read_dual_io_support = 1, }, { /* MX25U8032E */ .id[0] = 0x2534, .nr_sectors_shift = 8, + .fast_read_dual_io_support = 1, }, { - /* MX25U1635E */ + /* MX25U1635E/MX25U1635F */ .id[0] = 0x2535, .nr_sectors_shift = 9, + .fast_read_dual_io_support = 1, }, { - /* MX25U3235E */ + /* MX25U3235E/MX25U3235F */ .id[0] = 0x2536, .nr_sectors_shift = 10, + .fast_read_dual_io_support = 1, }, { - /* MX25U6435F */ + /* MX25U6435E/MX25U6435F */ .id[0] = 0x2537, .nr_sectors_shift = 11, + .fast_read_dual_io_support = 1, }, { /* MX25U12835F */ .id[0] = 0x2538, .nr_sectors_shift = 12, + .fast_read_dual_io_support = 1, }, { /* MX25U25635F */ .id[0] = 0x2539, .nr_sectors_shift = 13, + .fast_read_dual_io_support = 1, }, { - /* MX25U51245G */ + /* MX25U51235F */ .id[0] = 0x253a, .nr_sectors_shift = 14, + .fast_read_dual_io_support = 1, }, { /* MX25L12855E */ .id[0] = 0x2618, .nr_sectors_shift = 12, + .fast_read_dual_io_support = 1, }, { /* MX25L3235D/MX25L3225D/MX25L3236D/MX25L3237D */ .id[0] = 0x5e16, .nr_sectors_shift = 10, + .fast_read_dual_io_support = 1, }, { /* MX25L6495F */ diff --git a/src/drivers/spi/spi_flash.c b/src/drivers/spi/spi_flash.c index b674749feb..f3cecd5fc6 100644 --- a/src/drivers/spi/spi_flash.c +++ b/src/drivers/spi/spi_flash.c @@ -20,7 +20,7 @@ static void spi_flash_addr(u32 addr, u8 *cmd) cmd[3] = addr >> 0; } -static int do_spi_flash_cmd(const struct spi_slave *spi, const void *dout, +static int do_spi_flash_cmd(const struct spi_slave *spi, const u8 *dout, size_t bytes_out, void *din, size_t bytes_in) { int ret; @@ -51,8 +51,8 @@ static int do_spi_flash_cmd(const struct spi_slave *spi, const void *dout, return ret; } -static int do_dual_read_cmd(const struct spi_slave *spi, const void *dout, - size_t bytes_out, void *din, size_t bytes_in) +static int do_dual_output_cmd(const struct spi_slave *spi, const u8 *dout, + size_t bytes_out, void *din, size_t bytes_in) { int ret; @@ -79,6 +79,31 @@ static int do_dual_read_cmd(const struct spi_slave *spi, const void *dout, return ret; } +static int do_dual_io_cmd(const struct spi_slave *spi, const u8 *dout, + size_t bytes_out, void *din, size_t bytes_in) +{ + int ret; + + /* Only the very first byte (opcode) is transferred in "single" mode. */ + struct spi_op vector = { .dout = dout, .bytesout = 1, + .din = NULL, .bytesin = 0 }; + + ret = spi_claim_bus(spi); + if (ret) + return ret; + + ret = spi_xfer_vector(spi, &vector, 1); + + if (!ret) + ret = spi->ctrlr->xfer_dual(spi, &dout[1], bytes_out - 1, NULL, 0); + + if (!ret) + ret = spi->ctrlr->xfer_dual(spi, NULL, 0, din, bytes_in); + + spi_release_bus(spi); + return ret; +} + int spi_flash_cmd(const struct spi_slave *spi, u8 cmd, void *response, size_t len) { int ret = do_spi_flash_cmd(spi, &cmd, sizeof(cmd), response, len); @@ -119,18 +144,23 @@ int spi_flash_cmd_read(const struct spi_flash *flash, u32 offset, { u8 cmd[5]; int ret, cmd_len; - int (*do_cmd)(const struct spi_slave *spi, const void *din, + int (*do_cmd)(const struct spi_slave *spi, const u8 *din, size_t in_bytes, void *out, size_t out_bytes); if (CONFIG(SPI_FLASH_NO_FAST_READ)) { cmd_len = 4; cmd[0] = CMD_READ_ARRAY_SLOW; do_cmd = do_spi_flash_cmd; - } else if (flash->flags.dual_spi && flash->spi.ctrlr->xfer_dual) { + } else if (flash->flags.dual_io && flash->spi.ctrlr->xfer_dual) { + cmd_len = 5; + cmd[0] = CMD_READ_FAST_DUAL_IO; + cmd[4] = 0; + do_cmd = do_dual_io_cmd; + } else if (flash->flags.dual_output && flash->spi.ctrlr->xfer_dual) { cmd_len = 5; cmd[0] = CMD_READ_FAST_DUAL_OUTPUT; cmd[4] = 0; - do_cmd = do_dual_read_cmd; + do_cmd = do_dual_output_cmd; } else { cmd_len = 5; cmd[0] = CMD_READ_ARRAY_FAST; @@ -352,7 +382,8 @@ static int fill_spi_flash(const struct spi_slave *spi, struct spi_flash *flash, flash->pp_cmd = vi->desc->pp_cmd; flash->wren_cmd = vi->desc->wren_cmd; - flash->flags.dual_spi = part->fast_read_dual_output_support; + flash->flags.dual_output = part->fast_read_dual_output_support; + flash->flags.dual_io = part->fast_read_dual_io_support; flash->ops = &vi->desc->ops; flash->prot_ops = vi->prot_ops; @@ -471,8 +502,10 @@ int spi_flash_probe(unsigned int bus, unsigned int cs, struct spi_flash *flash) } const char *mode_string = ""; - if (flash->flags.dual_spi && spi.ctrlr->xfer_dual) - mode_string = " (Dual SPI mode)"; + if (flash->flags.dual_io && spi.ctrlr->xfer_dual) + mode_string = " (Dual I/O mode)"; + else if (flash->flags.dual_output && spi.ctrlr->xfer_dual) + mode_string = " (Dual Output mode)"; printk(BIOS_INFO, "SF: Detected %02x %04x with sector size 0x%x, total 0x%x%s\n", flash->vendor, flash->model, flash->sector_size, flash->size, mode_string); diff --git a/src/drivers/spi/spi_flash_internal.h b/src/drivers/spi/spi_flash_internal.h index b4d39b3d31..4a7beeab3e 100644 --- a/src/drivers/spi/spi_flash_internal.h +++ b/src/drivers/spi/spi_flash_internal.h @@ -15,6 +15,7 @@ #define CMD_READ_ARRAY_LEGACY 0xe8 #define CMD_READ_FAST_DUAL_OUTPUT 0x3b +#define CMD_READ_FAST_DUAL_IO 0xbb #define CMD_READ_STATUS 0x05 #define CMD_WRITE_ENABLE 0x06 @@ -69,8 +70,9 @@ struct spi_flash_part_id { uint16_t id[2]; /* Log based 2 total number of sectors. */ uint16_t nr_sectors_shift: 4; - uint16_t fast_read_dual_output_support : 1; - uint16_t _reserved_for_flags: 3; + uint16_t fast_read_dual_output_support : 1; /* 1-1-2 read */ + uint16_t fast_read_dual_io_support : 1; /* 1-2-2 read */ + uint16_t _reserved_for_flags: 2; /* Block protection. Currently used by Winbond. */ uint16_t protection_granularity_shift : 5; uint16_t bp_bits : 3; diff --git a/src/drivers/spi/winbond.c b/src/drivers/spi/winbond.c index 9fe0492b75..8f93e3be92 100644 --- a/src/drivers/spi/winbond.c +++ b/src/drivers/spi/winbond.c @@ -101,12 +101,14 @@ static const struct spi_flash_part_id flash_table[] = { .id[0] = 0x4014, .nr_sectors_shift = 8, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, }, { /* W25Q16_V */ .id[0] = 0x4015, .nr_sectors_shift = 9, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, .protection_granularity_shift = 16, .bp_bits = 3, }, @@ -115,6 +117,7 @@ static const struct spi_flash_part_id flash_table[] = { .id[0] = 0x6015, .nr_sectors_shift = 9, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, .protection_granularity_shift = 16, .bp_bits = 3, }, @@ -123,6 +126,7 @@ static const struct spi_flash_part_id flash_table[] = { .id[0] = 0x4016, .nr_sectors_shift = 10, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, .protection_granularity_shift = 16, .bp_bits = 3, }, @@ -131,6 +135,7 @@ static const struct spi_flash_part_id flash_table[] = { .id[0] = 0x6016, .nr_sectors_shift = 10, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, .protection_granularity_shift = 16, .bp_bits = 3, }, @@ -139,6 +144,7 @@ static const struct spi_flash_part_id flash_table[] = { .id[0] = 0x4017, .nr_sectors_shift = 11, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, .protection_granularity_shift = 17, .bp_bits = 3, }, @@ -147,6 +153,7 @@ static const struct spi_flash_part_id flash_table[] = { .id[0] = 0x6017, .nr_sectors_shift = 11, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, .protection_granularity_shift = 17, .bp_bits = 3, }, @@ -155,6 +162,7 @@ static const struct spi_flash_part_id flash_table[] = { .id[0] = 0x8017, .nr_sectors_shift = 11, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, .protection_granularity_shift = 17, .bp_bits = 3, }, @@ -163,6 +171,7 @@ static const struct spi_flash_part_id flash_table[] = { .id[0] = 0x4018, .nr_sectors_shift = 12, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, .protection_granularity_shift = 18, .bp_bits = 3, }, @@ -171,6 +180,7 @@ static const struct spi_flash_part_id flash_table[] = { .id[0] = 0x6018, .nr_sectors_shift = 12, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, .protection_granularity_shift = 18, .bp_bits = 3, }, @@ -179,6 +189,7 @@ static const struct spi_flash_part_id flash_table[] = { .id[0] = 0x7018, .nr_sectors_shift = 12, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, .protection_granularity_shift = 18, .bp_bits = 3, }, @@ -187,6 +198,7 @@ static const struct spi_flash_part_id flash_table[] = { .id[0] = 0x8018, .nr_sectors_shift = 12, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, .protection_granularity_shift = 18, .bp_bits = 3, }, @@ -195,6 +207,7 @@ static const struct spi_flash_part_id flash_table[] = { .id[0] = 0x8020, .nr_sectors_shift = 11, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, .protection_granularity_shift = 16, .bp_bits = 4, }, @@ -203,6 +216,7 @@ static const struct spi_flash_part_id flash_table[] = { .id[0] = 0x4019, .nr_sectors_shift = 13, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, .protection_granularity_shift = 16, .bp_bits = 4, }, @@ -211,6 +225,7 @@ static const struct spi_flash_part_id flash_table[] = { .id[0] = 0x7019, .nr_sectors_shift = 13, .fast_read_dual_output_support = 1, + .fast_read_dual_io_support = 1, .protection_granularity_shift = 16, .bp_bits = 4, }, diff --git a/src/include/spi_flash.h b/src/include/spi_flash.h index a7f707eb1c..fe77e3ef79 100644 --- a/src/include/spi_flash.h +++ b/src/include/spi_flash.h @@ -86,8 +86,9 @@ struct spi_flash { union { u8 raw; struct { - u8 dual_spi : 1; - u8 _reserved : 7; + u8 dual_output : 1; + u8 dual_io : 1; + u8 _reserved : 6; }; } flags; u16 model; |