Edward O'Callaghan has submitted this change. ( https://review.coreboot.org/c/flashrom/+/46089 )
Change subject: realtek_mst_i2c_spi.c: Update GPIO pin 88 toggle function ......................................................................
realtek_mst_i2c_spi.c: Update GPIO pin 88 toggle function
Here we provide a helper function to allow indexing MCU configuration registers. The 0x9F port allows access to these MCU configuration registers followed by the high and then low bytes of the register address we wish to index written into 0xF5 or 0xF4 respectively, a read or write can then be made via 0xF5.
For the configuration of GPIO pins on the chip, there are two relevant register address, 0x104F for pin direction (sink input or push-pull in-out) configuration and 0xFE3F for pin data values (1 to push-pull and 0 to sink). The reference design uses GPIO 88 to strap the write protection pin and so we provide a function that allows the call site to toggle this state and therefore de-assert hardware write protection of the external spi flash.
BUG=b:152558985,b:148745673 BRANCH=none TEST=builds && verified the write protection get disabled.
Change-Id: I1aed0086f917e31bebb51857ad5cce138158fe82 Signed-off-by: Shiyu Sun sshiyu@chromium.org Reviewed-on: https://review.coreboot.org/c/flashrom/+/46089 Reviewed-by: Angel Pons th3fanbus@gmail.com Reviewed-by: Edward O'Callaghan quasisec@chromium.org Tested-by: build bot (Jenkins) no-reply@coreboot.org --- M realtek_mst_i2c_spi.c 1 file changed, 46 insertions(+), 17 deletions(-)
Approvals: build bot (Jenkins): Verified Angel Pons: Looks good to me, approved Edward O'Callaghan: Looks good to me, approved
diff --git a/realtek_mst_i2c_spi.c b/realtek_mst_i2c_spi.c index d1f7227..63ff510 100644 --- a/realtek_mst_i2c_spi.c +++ b/realtek_mst_i2c_spi.c @@ -46,6 +46,8 @@ #define OPCODE_READ 3 #define OPCODE_WRITE 2
+#define GPIO_CONFIG_ADDRESS 0x104F +#define GPIO_VALUE_ADDRESS 0xFE3F
struct realtek_mst_i2c_spi_data { int fd; @@ -146,27 +148,54 @@ return ret; }
-static int realtek_mst_i2c_spi_disable_protection(int fd) +static int realtek_mst_i2c_spi_select_indexed_register(int fd, uint16_t address) +{ + int ret = 0; + + ret |= realtek_mst_i2c_spi_write_register(fd, 0xF4, 0x9F); + ret |= realtek_mst_i2c_spi_write_register(fd, 0xF5, address >> 8); + ret |= realtek_mst_i2c_spi_write_register(fd, 0xF4, address & 0xFF); + + return ret; +} + +static int realtek_mst_i2c_spi_write_indexed_register(int fd, uint16_t address, uint8_t val) +{ + int ret = 0; + + ret |= realtek_mst_i2c_spi_select_indexed_register(fd, address); + ret |= realtek_mst_i2c_spi_write_register(fd, 0xF5, val); + + return ret; +} + +static int realtek_mst_i2c_spi_read_indexed_register(int fd, uint16_t address, uint8_t *val) +{ + int ret = 0; + + ret |= realtek_mst_i2c_spi_select_indexed_register(fd, address); + ret |= realtek_mst_i2c_spi_read_register(fd, 0xF5, val); + + return ret; +} + + +/* Toggle the GPIO pin 88, this could be routed to different controls like write + * protection or a led. */ +static int realtek_mst_i2c_spi_toggle_gpio_88_strap(int fd, bool toggle) { int ret = 0; uint8_t val = 0; - // 0xAB[2:0] = b001
- ret |= realtek_mst_i2c_spi_write_register(fd, 0xF4, 0x9F); - ret |= realtek_mst_i2c_spi_write_register(fd, 0xF5, 0x10); - ret |= realtek_mst_i2c_spi_write_register(fd, 0xF4, 0xAB); + /* Read register 0x104F into val. */ + ret |= realtek_mst_i2c_spi_read_indexed_register(fd, GPIO_CONFIG_ADDRESS, &val); + /* Write 0x104F[3:0] = b0001 to enable the toggle of pin value. */ + ret |= realtek_mst_i2c_spi_write_indexed_register(fd, GPIO_CONFIG_ADDRESS, (val & 0xF0) | 0x01);
- ret |= realtek_mst_i2c_spi_read_register(fd, 0xF5, &val); - - ret |= realtek_mst_i2c_spi_write_register(fd, 0xF4, 0x9F); - ret |= realtek_mst_i2c_spi_write_register(fd, 0xF5, 0x10); - ret |= realtek_mst_i2c_spi_write_register(fd, 0xF4, 0xAB); - - ret |= realtek_mst_i2c_spi_write_register(fd, 0xF5, (val & 0xF8) | 0x01); - - /* Set pin value to high, 0xFFD7[0] = 1. */ - ret |= realtek_mst_i2c_spi_read_register(fd, 0xD7, &val); - ret |= realtek_mst_i2c_spi_write_register(fd, 0xD7, (val & 0xFE) | 0x01); + /* Read register 0xFE3F into val. */ + ret |= realtek_mst_i2c_spi_read_indexed_register(fd, GPIO_VALUE_ADDRESS, &val); + /* Write 0xFE3F[0] = b|toggle| to toggle pin value to low/high. */ + ret |= realtek_mst_i2c_spi_write_indexed_register(fd, GPIO_VALUE_ADDRESS, (val & 0xFE) | toggle);
return ret; } @@ -333,7 +362,7 @@ if (fd < 0) return SPI_GENERIC_ERROR;
- ret = realtek_mst_i2c_spi_disable_protection(fd); + ret = realtek_mst_i2c_spi_toggle_gpio_88_strap(fd, true); if (ret) return ret;