diff options
Diffstat (limited to 'realtek_mst_i2c_spi.c')
-rw-r--r-- | realtek_mst_i2c_spi.c | 171 |
1 files changed, 83 insertions, 88 deletions
diff --git a/realtek_mst_i2c_spi.c b/realtek_mst_i2c_spi.c index ae79fdd3b..57677ec67 100644 --- a/realtek_mst_i2c_spi.c +++ b/realtek_mst_i2c_spi.c @@ -28,7 +28,7 @@ #define MCU_I2C_SLAVE_ADDR 0x94 #define REGISTER_ADDRESS (0x94 >> 1) -#define PAGE_SIZE 128 +#define RTK_PAGE_SIZE 128 #define MAX_SPI_WAIT_RETRIES 1000 #define MCU_MODE 0x6F @@ -51,7 +51,7 @@ struct realtek_mst_i2c_spi_data { int fd; - int reset; + bool reset; }; static int realtek_mst_i2c_spi_write_data(int fd, uint16_t addr, void *buf, uint16_t len) @@ -191,8 +191,7 @@ static int realtek_mst_i2c_spi_read_indexed_register(int fd, uint16_t address, u } -/* Toggle the GPIO pin 88, this could be routed to different controls like write - * protection or a led. */ +/* Toggle the GPIO pin 88, reserved for write protection pin of the external flash. */ static int realtek_mst_i2c_spi_toggle_gpio_88_strap(int fd, bool toggle) { int ret = 0; @@ -310,8 +309,8 @@ static int realtek_mst_i2c_spi_write_page(int fd, uint8_t reg, const uint8_t *bu * Using static buffer with maximum possible size, * extra byte is needed for prefixing the data port register at index 0. */ - uint8_t wbuf[PAGE_SIZE + 1] = { MCU_DATA_PORT }; - if (len > PAGE_SIZE) + uint8_t wbuf[RTK_PAGE_SIZE + 1] = { MCU_DATA_PORT }; + if (len > RTK_PAGE_SIZE) return SPI_GENERIC_ERROR; memcpy(&wbuf[1], buf, len); @@ -352,9 +351,9 @@ static int realtek_mst_i2c_spi_read(struct flashctx *flash, uint8_t *buf, uint8_t dummy; realtek_mst_i2c_spi_read_register(fd, MCU_DATA_PORT, &dummy); - for (i = 0; i < len; i += PAGE_SIZE) { + for (i = 0; i < len; i += RTK_PAGE_SIZE) { ret |= realtek_mst_i2c_spi_read_data(fd, REGISTER_ADDRESS, - buf + i, min(len - i, PAGE_SIZE)); + buf + i, min(len - i, RTK_PAGE_SIZE)); if (ret) return ret; } @@ -376,11 +375,11 @@ static int realtek_mst_i2c_spi_write_256(struct flashctx *flash, const uint8_t * return SPI_GENERIC_ERROR; ret |= realtek_mst_i2c_spi_write_register(fd, 0x6D, 0x02); /* write opcode */ - ret |= realtek_mst_i2c_spi_write_register(fd, 0x71, (PAGE_SIZE - 1)); /* fit len=256 */ + ret |= realtek_mst_i2c_spi_write_register(fd, 0x71, (RTK_PAGE_SIZE - 1)); /* fit len=256 */ - for (i = 0; i < len; i += PAGE_SIZE) { - uint16_t page_len = min(len - i, PAGE_SIZE); - if (len - i < PAGE_SIZE) + for (i = 0; i < len; i += RTK_PAGE_SIZE) { + uint16_t page_len = min(len - i, RTK_PAGE_SIZE); + if (len - i < RTK_PAGE_SIZE) ret |= realtek_mst_i2c_spi_write_register(fd, 0x71, page_len-1); ret |= realtek_mst_i2c_spi_map_page(fd, start + i); if (ret) @@ -398,6 +397,7 @@ static int realtek_mst_i2c_spi_write_256(struct flashctx *flash, const uint8_t * ret |= realtek_mst_i2c_execute_write(fd); if (ret) break; + update_progress(flash, FLASHROM_PROGRESS_WRITE, i + RTK_PAGE_SIZE, len); } return ret; @@ -410,16 +410,6 @@ static int realtek_mst_i2c_spi_write_aai(struct flashctx *flash, const uint8_t * return SPI_GENERIC_ERROR; } -static struct spi_master spi_master_i2c_realtek_mst = { - .max_data_read = 16, - .max_data_write = 8, - .command = realtek_mst_i2c_spi_send_command, - .multicommand = default_spi_send_multicommand, - .read = realtek_mst_i2c_spi_read, - .write_256 = realtek_mst_i2c_spi_write_256, - .write_aai = realtek_mst_i2c_spi_write_aai, -}; - static int realtek_mst_i2c_spi_shutdown(void *data) { int ret = 0; @@ -442,82 +432,85 @@ static int realtek_mst_i2c_spi_shutdown(void *data) return ret; } -static int get_params(int *i2c_bus, int *reset, int *enter_isp) -{ - char *bus_str = NULL, *reset_str = NULL, *isp_str = NULL; - int ret = SPI_GENERIC_ERROR; - - bus_str = extract_programmer_param("bus"); - if (bus_str) { - char *bus_suffix; - errno = 0; - int bus = (int)strtol(bus_str, &bus_suffix, 10); - if (errno != 0 || bus_str == bus_suffix) { - msg_perr("%s: Could not convert 'bus'.\n", __func__); - goto _get_params_failed; - } +static const struct spi_master spi_master_i2c_realtek_mst = { + .max_data_read = 16, + .max_data_write = 8, + .command = realtek_mst_i2c_spi_send_command, + .read = realtek_mst_i2c_spi_read, + .write_256 = realtek_mst_i2c_spi_write_256, + .write_aai = realtek_mst_i2c_spi_write_aai, + .shutdown = realtek_mst_i2c_spi_shutdown, +}; - if (bus < 0 || bus > 255) { - msg_perr("%s: Value for 'bus' is out of range(0-255).\n", __func__); - goto _get_params_failed; - } +static int get_params(const struct programmer_cfg *cfg, bool *reset, bool *enter_isp, bool *allow_brick) +{ + char *param_str; + int ret = 0; - if (strlen(bus_suffix) > 0) { - msg_perr("%s: Garbage following 'bus' value.\n", __func__); - goto _get_params_failed; + *allow_brick = false; /* Default behaviour is to bail. */ + param_str = extract_programmer_param_str(cfg, "allow_brick"); + if (param_str) { + if (!strcmp(param_str, "yes")) { + *allow_brick = true; + } else { + msg_perr("%s: Incorrect param format, allow_brick=yes.\n", __func__); + ret = SPI_GENERIC_ERROR; } - - msg_pinfo("Using i2c bus %i.\n", bus); - *i2c_bus = bus; - ret = 0; - } else { - msg_perr("%s: Bus number not specified.\n", __func__); } - - reset_str = extract_programmer_param("reset-mcu"); - if (reset_str) { - if (reset_str[0] == '1') - *reset = 1; - else if (reset_str[0] == '0') - *reset = 0; - else { - msg_perr("%s: Incorrect param format, reset-mcu=1 or 0.\n", __func__); + free(param_str); + + *reset = false; /* Default behaviour is no MCU reset on tear-down. */ + param_str = extract_programmer_param_str(cfg, "reset_mcu"); + if (param_str) { + if (param_str[0] == '1') { + *reset = true; + } else if (param_str[0] == '0') { + *reset = false; + } else { + msg_perr("%s: Incorrect param format, reset_mcu=1 or 0.\n", __func__); ret = SPI_GENERIC_ERROR; } - } else - *reset = 0; /* Default behaviour is no MCU reset on tear-down. */ - free(reset_str); - - isp_str = extract_programmer_param("enter-isp"); - if (isp_str) { - if (isp_str[0] == '1') - *enter_isp = 1; - else if (isp_str[0] == '0') - *enter_isp = 0; - else { - msg_perr("%s: Incorrect param format, enter-isp=1 or 0.\n", __func__); + } + free(param_str); + + *enter_isp = true; /* Default behaviour is enter ISP on setup. */ + param_str = extract_programmer_param_str(cfg, "enter_isp"); + if (param_str) { + if (param_str[0] == '1') { + *enter_isp = true; + } else if (param_str[0] == '0') { + *enter_isp = false; + } else { + msg_perr("%s: Incorrect param format, enter_isp=1 or 0.\n", __func__); ret = SPI_GENERIC_ERROR; } - } else - *enter_isp = 1; /* Default behaviour is enter ISP on setup. */ - free(isp_str); - -_get_params_failed: - if (bus_str) - free(bus_str); + } + free(param_str); return ret; } -int realtek_mst_i2c_spi_init(void) +static int realtek_mst_i2c_spi_init(const struct programmer_cfg *cfg) { int ret = 0; - int i2c_bus = 0, reset = 0, enter_isp = 0; + bool reset, enter_isp, allow_brick; + + if (get_params(cfg, &reset, &enter_isp, &allow_brick)) + return SPI_GENERIC_ERROR; - if (get_params(&i2c_bus, &reset, &enter_isp)) + /* + * TODO: Once board_enable can facilitate safe i2c allow listing + * then this can be removed. + */ + if (!allow_brick) { + msg_perr("%s: For i2c drivers you must explicitly 'allow_brick=yes'. ", __func__); + msg_perr("There is currently no way to determine if the programmer works on a board " + "as i2c device address space can be overloaded. Set 'allow_brick=yes' if " + "you are sure you know what you are doing.\n"); return SPI_GENERIC_ERROR; + } - int fd = i2c_open(i2c_bus, REGISTER_ADDRESS, 0); + int fd = i2c_open_from_programmer_params(cfg, REGISTER_ADDRESS, 0); if (fd < 0) return fd; @@ -533,7 +526,7 @@ int realtek_mst_i2c_spi_init(void) return ret; } - struct realtek_mst_i2c_spi_data *data = calloc(1, sizeof(struct realtek_mst_i2c_spi_data)); + struct realtek_mst_i2c_spi_data *data = calloc(1, sizeof(*data)); if (!data) { msg_perr("Unable to allocate space for extra SPI master data.\n"); return SPI_GENERIC_ERROR; @@ -541,10 +534,12 @@ int realtek_mst_i2c_spi_init(void) data->fd = fd; data->reset = reset; - ret |= register_shutdown(realtek_mst_i2c_spi_shutdown, data); - - spi_master_i2c_realtek_mst.data = data; - ret |= register_spi_master(&spi_master_i2c_realtek_mst); - - return ret; + return register_spi_master(&spi_master_i2c_realtek_mst, data); } + +const struct programmer_entry programmer_realtek_mst_i2c_spi = { + .name = "realtek_mst_i2c_spi", + .type = OTHER, + .devs.note = "Device files /dev/i2c-*.\n", + .init = realtek_mst_i2c_spi_init, +}; |