diff options
author | Aaron Durbin <adurbin@chromium.org> | 2019-12-27 11:47:05 -0700 |
---|---|---|
committer | Aaron Durbin <adurbin@chromium.org> | 2020-01-03 23:06:32 +0000 |
commit | 173620a88dfe3afec1733d7bec8846406f9c8946 (patch) | |
tree | 35950e3e8c541aac02d126ae463d281268dd94a3 /src/soc/amd/common/block/spi/fch_spi_ctrl.c | |
parent | 1513d72a38e7f643c9499fc2079a99a75f0eac3c (diff) |
soc/amd/common/block/spi: remove code duplication
This removes all the duplicated code and logic and leverages
the existing ones in libraries themselves. The current side
effect is that protection cannot be fully enabled because the
read, write, and write enable command are not exposed in struct
spi_flash currently. That support can be revised if protection
scheme makes sense for our use-cases once it's better understood.
BUG=b:146928174
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Change-Id: I8faf9cc719ee33dd9f03fb74b579b02bbc6a5e2e
Reviewed-on: https://review.coreboot.org/c/coreboot/+/37957
Reviewed-by: Marshall Dawson <marshalldawson3rd@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/soc/amd/common/block/spi/fch_spi_ctrl.c')
-rw-r--r-- | src/soc/amd/common/block/spi/fch_spi_ctrl.c | 207 |
1 files changed, 36 insertions, 171 deletions
diff --git a/src/soc/amd/common/block/spi/fch_spi_ctrl.c b/src/soc/amd/common/block/spi/fch_spi_ctrl.c index a7d9c77e12..0a629a3213 100644 --- a/src/soc/amd/common/block/spi/fch_spi_ctrl.c +++ b/src/soc/amd/common/block/spi/fch_spi_ctrl.c @@ -17,14 +17,31 @@ #include <spi_flash.h> #include <soc/southbridge.h> #include <soc/pci_devs.h> -#include <amdblocks/fch_spi.h> #include <amdblocks/lpc.h> -#include <drivers/spi/spi_flash_internal.h> #include <device/pci_ops.h> -#include <timer.h> #include <lib.h> +#include <timer.h> + +#define GRANULARITY_TEST_4k 0x0000f000 /* bits 15-12 */ +#define WORD_TO_DWORD_UPPER(x) ((x << 16) & 0xffff0000) + +/* SPI MMIO registers */ +#define SPI_RESTRICTED_CMD1 0x04 +#define SPI_RESTRICTED_CMD2 0x08 +#define SPI_CNTRL1 0x0c +#define SPI_CMD_CODE 0x45 +#define SPI_CMD_TRIGGER 0x47 +#define SPI_CMD_TRIGGER_EXECUTE BIT(7) +#define SPI_TX_BYTE_COUNT 0x48 +#define SPI_RX_BYTE_COUNT 0x4b +#define SPI_STATUS 0x4c +#define SPI_DONE_BYTE_COUNT_SHIFT 0 +#define SPI_DONE_BYTE_COUNT_MASK 0xff +#define SPI_FIFO_WR_PTR_SHIFT 8 +#define SPI_FIFO_WR_PTR_MASK 0x7f +#define SPI_FIFO_RD_PTR_SHIFT 16 +#define SPI_FIFO_RD_PTR_MASK 0x7f -static struct spi_data ctrl_spi_data; static uint32_t spibar; static inline uint8_t spi_read8(uint8_t reg) @@ -110,12 +127,8 @@ void spi_init(void) printk(BIOS_DEBUG, "%s: Spibar at 0x%08x\n", __func__, spibar); } -const struct spi_data *get_ctrl_spi_data(void) -{ - return &ctrl_spi_data; -} - -static int spi_ctrlr_xfer(const void *dout, size_t bytesout, void *din, size_t bytesin) +static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout, + size_t bytesout, void *din, size_t bytesin) { size_t count; uint8_t cmd; @@ -161,161 +174,10 @@ static int spi_ctrlr_xfer(const void *dout, size_t bytesout, void *din, size_t b return 0; } -static int amd_xfer_vectors(struct spi_op vectors[], size_t count) -{ - int ret; - void *din; - size_t bytes_in; - - if (count < 1 || count > 2) - return -1; - - /* SPI flash commands always have a command first... */ - if (!vectors[0].dout || !vectors[0].bytesout) - return -1; - /* And not read any data during the command. */ - if (vectors[0].din || vectors[0].bytesin) - return -1; - - if (count == 2) { - /* If response bytes requested ensure the buffer is valid. */ - if (vectors[1].bytesin && !vectors[1].din) - return -1; - /* No sends can accompany a receive. */ - if (vectors[1].dout || vectors[1].bytesout) - return -1; - din = vectors[1].din; - bytes_in = vectors[1].bytesin; - } else { - din = NULL; - bytes_in = 0; - } - - ret = spi_ctrlr_xfer(vectors[0].dout, vectors[0].bytesout, din, bytes_in); - - if (ret) { - vectors[0].status = SPI_OP_FAILURE; - if (count == 2) - vectors[1].status = SPI_OP_FAILURE; - } else { - vectors[0].status = SPI_OP_SUCCESS; - if (count == 2) - vectors[1].status = SPI_OP_SUCCESS; - } - - return ret; -} - -int fch_spi_flash_cmd(const void *dout, size_t bytes_out, void *din, size_t bytes_in) +static int xfer_vectors(const struct spi_slave *slave, + struct spi_op vectors[], size_t count) { - /* - * SPI flash requires command-response kind of behavior. Thus, two - * separate SPI vectors are required -- first to transmit dout and other - * to receive in din. - */ - struct spi_op vectors[] = { - [0] = { .dout = dout, .bytesout = bytes_out, - .din = NULL, .bytesin = 0, }, - [1] = { .dout = NULL, .bytesout = 0, - .din = din, .bytesin = bytes_in }, - }; - size_t count = ARRAY_SIZE(vectors); - if (!bytes_in) - count = 1; - - return amd_xfer_vectors(vectors, count); -} - -static void set_ctrl_spi_data(struct spi_flash *flash) -{ - u8 cmd = SPI_PAGE_WRITE; - - ctrl_spi_data.name = flash->name; - ctrl_spi_data.size = flash->size; - ctrl_spi_data.sector_size = flash->sector_size; - ctrl_spi_data.status_cmd = flash->status_cmd; - ctrl_spi_data.erase_cmd = flash->erase_cmd; - ctrl_spi_data.write_enable_cmd = SPI_WRITE_ENABLE; - - if (flash->vendor == VENDOR_ID_SST) { - ctrl_spi_data.non_standard = NON_STANDARD_SPI_SST; - if ((flash->model & 0x00ff) == SST_256) - ctrl_spi_data.page_size = 256; - else { - ctrl_spi_data.page_size = 2; - cmd = CMD_SST_AAI_WP; - } - } else { - ctrl_spi_data.page_size = flash->page_size; - ctrl_spi_data.non_standard = NON_STANDARD_SPI_NONE; - } - ctrl_spi_data.write_cmd = cmd; - - if (CONFIG(SPI_FLASH_NO_FAST_READ)) { - ctrl_spi_data.read_cmd_len = 4; - ctrl_spi_data.read_cmd = CMD_READ_ARRAY_SLOW; - } else { - ctrl_spi_data.read_cmd_len = 5; - ctrl_spi_data.read_cmd = CMD_READ_ARRAY_FAST; - } -} - -static int fch_spi_flash_probe(const struct spi_slave *spi, struct spi_flash *flash) -{ - int ret, i, shift, table_size; - u8 idcode[IDCODE_LEN], *idp, cmd = CMD_READ_ID; - const struct spi_flash_table *flash_ptr = get_spi_flash_table(&table_size); - - /* Read the ID codes */ - ret = fch_spi_flash_cmd(&cmd, 1, idcode, sizeof(idcode)); - if (ret) - return -1; - - if (CONFIG(SOC_AMD_COMMON_BLOCK_SPI_DEBUG)) { - printk(BIOS_SPEW, "SF: Got idcode: "); - for (i = 0; i < sizeof(idcode); i++) - printk(BIOS_SPEW, "%02x ", idcode[i]); - printk(BIOS_SPEW, "\n"); - } - - /* - * All solid state devices have vendor id defined by JEDEC specification JEP106, - * which originally allocated only 7 bits for it plus parity. When number of - * vendors exploded beyond 126, a banking proposition came maintaining - * compatibility with older vendors while allowing for 4 extra bits (16 banks) - * through the introduction of the concept "Continuation Code", denoted by the - * byte value of 0x7f. - * Examples: - * 0xfe, 0x60, 0x18, 0x00, 0x00, 0x00 => vendor 0xfe of bank o - * 0x7f, 0x7f, 0xfe, 0x60, 0x18, 0x00 => vendor 0xfe of bank 2 - * count the number of continuation code bytes - */ - for (shift = 0, idp = idcode; *idp == IDCODE_CONT_CODE; ++shift, ++idp) { - if (shift < IDCODE_CONT_LEN) - continue; - printk(BIOS_ERR, "unsupported ID code bank\n"); - return -1; - } - - printk(BIOS_INFO, "Manufacturer: %02x on bank %d\n", *idp, shift); - - /* search the table for matches in shift and id */ - for (i = 0; i < table_size; ++i) { - if (flash_ptr->shift == shift && flash_ptr->idcode == *idp) { - /* we have a match, call probe */ - if (flash_ptr->probe(spi, idp, flash) == 0) { - flash->vendor = idp[0]; - flash->model = (idp[1] << 8) | idp[2]; - set_ctrl_spi_data(flash); - fch_spi_flash_ops_init(flash); - return 0; - } - } - flash_ptr++; - } - - /* No match, return error. */ - return -1; + return spi_flash_vector_helper(slave, vectors, count, spi_ctrlr_xfer); } static int protect_a_range(u32 value) @@ -408,12 +270,14 @@ static int fch_spi_flash_protect(const struct spi_flash *flash, const struct reg /* define commands to be blocked if in range */ reg32 = 0; if (type & WRITE_PROTECT) { - reg32 |= (ctrl_spi_data.write_enable_cmd << 24); - reg32 |= (ctrl_spi_data.write_cmd << 16); - reg32 |= (ctrl_spi_data.erase_cmd << 8); + /* FIXME */ + printk(BIOS_INFO, "%s: Write Enable and Write Cmd not blocked\n", __func__); + reg32 |= (flash->erase_cmd << 8); + } + if (type & READ_PROTECT) { + /* FIXME */ + printk(BIOS_INFO, "%s: READ_PROTECT not supported.\n", __func__); } - if (type & READ_PROTECT) - reg32 |= ctrl_spi_data.read_cmd; /* Final steps to protect region */ pci_write_config32(SOC_LPC_DEV, SPI_RESTRICTED_CMD1, reg32); @@ -424,9 +288,10 @@ static int fch_spi_flash_protect(const struct spi_flash *flash, const struct reg return 0; } -const struct spi_ctrlr fch_spi_flash_ctrlr = { +static const struct spi_ctrlr fch_spi_flash_ctrlr = { + .xfer_vector = xfer_vectors, .max_xfer_size = SPI_FIFO_DEPTH, - .flash_probe = fch_spi_flash_probe, + .flags = SPI_CNTRLR_DEDUCT_CMD_LEN | SPI_CNTRLR_DEDUCT_OPCODE_LEN, .flash_protect = fch_spi_flash_protect, }; |