summaryrefslogtreecommitdiffstats
path: root/realtek_mst_i2c_spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'realtek_mst_i2c_spi.c')
-rw-r--r--realtek_mst_i2c_spi.c171
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,
+};