Anastasia Klimchuk submitted this change.
ch347_spi: Add driver support for CH347F packaging
CH347F can work simultaneously with SPI, I2C and other signals.
CH347 introduce is available at the following URL:
https://www.wch-ic.com/products/CH347.html
Change-Id: I693baf1a0d9dc20757f56fba626b5f5ad20f71dd
Signed-off-by: ZhiYuanNJ Liu <871238103@qq.com>
Reviewed-on: https://review.coreboot.org/c/flashrom/+/82193
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Anastasia Klimchuk <aklm@chromium.org>
Reviewed-by: Nicholas Chin <nic.c3.14@gmail.com>
---
M ch347_spi.c
1 file changed, 29 insertions(+), 21 deletions(-)
diff --git a/ch347_spi.c b/ch347_spi.c
index 570e25b..21dcabb 100644
--- a/ch347_spi.c
+++ b/ch347_spi.c
@@ -36,8 +36,8 @@
#define WRITE_EP 0x06
#define READ_EP 0x86
-#define MODE_1_IFACE 2
-#define MODE_2_IFACE 1
+#define CH347T_IFACE 2
+#define CH347F_IFACE 4
/* The USB descriptor says the max transfer size is 512 bytes, but the
* vendor driver only seems to transfer a maximum of 510 bytes at once,
@@ -48,25 +48,29 @@
struct ch347_spi_data {
struct libusb_device_handle *handle;
+ int interface;
};
/* TODO: Add support for HID mode */
static const struct dev_entry devs_ch347_spi[] = {
- {0x1A86, 0x55DB, OK, "QinHeng Electronics", "USB To UART+SPI+I2C"},
+ {0x1A86, 0x55DB, OK, "QinHeng Electronics", "USB To UART+SPI+I2C"}, /* CH347T */
+ {0x1A86, 0x55DE, OK, "QinHeng Electronics", "USB To UART+SPI+I2C"}, /* CH347F */
{0}
};
+static int ch347_interface[] = {
+ CH347T_IFACE,
+ CH347F_IFACE,
+};
+
static int ch347_spi_shutdown(void *data)
{
struct ch347_spi_data *ch347_data = data;
-
- /* TODO: Set this depending on the mode */
- int spi_interface = MODE_1_IFACE;
+ int spi_interface = ch347_data->interface;
libusb_release_interface(ch347_data->handle, spi_interface);
libusb_attach_kernel_driver(ch347_data->handle, spi_interface);
libusb_close(ch347_data->handle);
libusb_exit(NULL);
-
free(data);
return 0;
}
@@ -262,6 +266,9 @@
/* Largely copied from ch341a_spi.c */
static int ch347_spi_init(const struct programmer_cfg *cfg)
{
+ uint16_t vid = devs_ch347_spi[0].vendor_id;
+ uint16_t pid = 0;
+ int index = 0;
struct ch347_spi_data *ch347_data = calloc(1, sizeof(*ch347_data));
if (!ch347_data) {
msg_perr("Could not allocate space for SPI data\n");
@@ -274,35 +281,36 @@
free(ch347_data);
return 1;
}
-
/* Enable information, warning, and error messages (only). */
#if LIBUSB_API_VERSION < 0x01000106
libusb_set_debug(NULL, 3);
#else
libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO);
#endif
-
- uint16_t vid = devs_ch347_spi[0].vendor_id;
- uint16_t pid = devs_ch347_spi[0].device_id;
- ch347_data->handle = libusb_open_device_with_vid_pid(NULL, vid, pid);
- if (ch347_data->handle == NULL) {
- msg_perr("Couldn't open device %04x:%04x.\n", vid, pid);
+ while (devs_ch347_spi[index].vendor_id != 0) {
+ vid = devs_ch347_spi[index].vendor_id;
+ pid = devs_ch347_spi[index].device_id;
+ ch347_data->handle = libusb_open_device_with_vid_pid(NULL, vid, pid);
+ if (ch347_data->handle) {
+ ch347_data->interface = ch347_interface[index];
+ break;
+ }
+ index++;
+ }
+ if (!ch347_data->handle) {
+ msg_perr("Couldn't find CH347.\n");
free(ch347_data);
return 1;
}
- /* TODO: set based on mode */
- /* Mode 1 uses interface 2 for the SPI interface */
- int spi_interface = MODE_1_IFACE;
-
- ret = libusb_detach_kernel_driver(ch347_data->handle, spi_interface);
+ ret = libusb_detach_kernel_driver(ch347_data->handle, ch347_data->interface);
if (ret != 0 && ret != LIBUSB_ERROR_NOT_FOUND)
msg_pwarn("Cannot detach the existing USB driver. Claiming the interface may fail. %s\n",
libusb_error_name(ret));
- ret = libusb_claim_interface(ch347_data->handle, spi_interface);
+ ret = libusb_claim_interface(ch347_data->handle, ch347_data->interface);
if (ret != 0) {
- msg_perr("Failed to claim interface 2: '%s'\n", libusb_error_name(ret));
+ msg_perr("Failed to claim interface %d: '%s'\n", ch347_data->interface, libusb_error_name(ret));
goto error_exit;
}
To view, visit change 82193. To unsubscribe, or for help writing mail filters, visit settings.