ZhiYuanNJ has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/82193?usp=email )
Change subject: Bug fix: Fix CH347T PID, interface, and clock settings errors Add functionality : Add support for CH347F. The latest package with F as 347, compared to T, does not require active mode switching and can simultaneously meet communication requirements such as USB to SPI/I2C H347 introduce is available at the following URL: https://www.wch-ic.com/products/CH347.html?from=search&wd=eyJpdiI6Im4zdV... ......................................................................
Bug fix: Fix CH347T PID, interface, and clock settings errors Add functionality : Add support for CH347F. The latest package with F as 347, compared to T, does not require active mode switching and can simultaneously meet communication requirements such as USB to SPI/I2C H347 introduce is available at the following URL: https://www.wch-ic.com/products/CH347.html?from=search&wd=eyJpdiI6Im4zdV...
Change-Id: I693baf1a0d9dc20757f56fba626b5f5ad20f71dd Signed-off-by: ZhiYuanNJ 871238103@qq.com --- M ch347_spi.c 1 file changed, 84 insertions(+), 22 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/93/82193/1
diff --git a/ch347_spi.c b/ch347_spi.c index 570e25b..33caa68 100644 --- a/ch347_spi.c +++ b/ch347_spi.c @@ -7,7 +7,25 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * + * CH347 is a high-speed USB bus converter chip that provides UART, I2C + * and SPI synchronous serial ports and JTAG interface through USB bus. + * + * The SPI interface by CH347 can supports transmission frequency + * configuration up to 60MHz. + * + * The USB2.0 to spi scheme based on CH347 can be used to build + * customized USB high-speed spi debugger and other products. + * + * _____________ + * | |____SPI (MISO,MOSI,SCK,CSC0,CSC1) + * USB__| CH347T/F | + * |_____________|____(UART/I2C/JTAG/SWD/GPIO) + * ______|______ + * | | + * | 8 MHz XTAL | + * |_____________| + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -36,8 +54,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, @@ -46,22 +64,46 @@ #define CH347_PACKET_SIZE 510 #define CH347_MAX_DATA_LEN (CH347_PACKET_SIZE - 3)
+struct device_speeds { + const char *name; + const int speed; +}; + 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, 0x55DD, OK, "QinHeng Electronics", "USB To UART+SPI+I2C"}, //CH347T + {0x1A86, 0x55DE, OK, "QinHeng Electronics", "USB To UART+SPI+I2C"}, //CH347F {0} };
+static const struct device_speeds spispeeds[] = { + {"60M", 0x0}, + {"30M", 0x1}, + {"15M", 0x2}, + {"7.5M", 0x3}, + {"3.75M", 0x4}, + {"1.875M", 0x5}, + {"937.5K", 0x6}, + {"468.75K", 0x7}, + {NULL, 0x0} +}; + +static int ch347_interface[] = { + 2, //CH347T interface number + 4, //CH347F interface number +}; + 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); @@ -215,6 +257,8 @@ /* Not sure what these two bytes do, but the vendor * drivers seem to unconditionally set these values */ + [3] = 0, + [4] = 0, [5] = 4, [6] = 1, /* Clock polarity: bit 1 */ @@ -262,6 +306,11 @@ /* Largely copied from ch341a_spi.c */ static int ch347_spi_init(const struct programmer_cfg *cfg) { + char *arg; + uint16_t vid = devs_ch347_spi[0].vendor_id; + uint16_t pid = 0; + int index = 0; + int spispeed = 0x0; //defaulet 60M SPI struct ch347_spi_data *ch347_data = calloc(1, sizeof(*ch347_data)); if (!ch347_data) { msg_perr("Could not allocate space for SPI data\n"); @@ -281,26 +330,28 @@ #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); - free(ch347_data); - return 1; + 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 open device %04x:%04x.\n", vid, pid); + 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)); goto error_exit; @@ -325,11 +376,22 @@ (desc.bcdDevice >> 0) & 0x000F);
/* TODO: add programmer cfg for things like CS pin and divisor */ - if (ch347_spi_config(ch347_data, 2) < 0) + arg = extract_programmer_param_str(cfg, "spispeed"); + if (arg) { + for (index = 0; spispeeds[index].name; index++) { + if (!strncasecmp(spispeeds[index].name, arg, strlen(spispeeds[index].name))) { + spispeed = spispeeds[index].speed; + break; + } + } + } + if (!spispeeds[index].name || !arg) + msg_perr("Invalid SPI speed, using defaul(60M clock spi).\n"); + free(arg); + /* TODO: add programmer cfg for things like CS pin and divisor */ + if (ch347_spi_config(ch347_data, spispeed) < 0) goto error_exit; - return register_spi_master(&spi_master_ch347_spi, ch347_data); - error_exit: ch347_spi_shutdown(ch347_data); return 1;