ZhiYuanNJ has uploaded this change for review.

View Change

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=eyJpdiI6Im4zdVRJdHdpNks1WUFLSUFDNnRsYnc9PSIsInZhbHVlIjoicHFsU3EwQlgzWmgzM1ZIYnBpZXFiUT09IiwibWFjIjoiNjZjNjc5ZDQ4Yzg2ZDdhNzc5YzM4OTA0MTlkM2FiYWQ1Yzg0ZTZkNWNiZDczZDM1NjM1ODIwN2NjZDhlOTNmOCJ9

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;

To view, visit change 82193. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: flashrom
Gerrit-Branch: main
Gerrit-Change-Id: I693baf1a0d9dc20757f56fba626b5f5ad20f71dd
Gerrit-Change-Number: 82193
Gerrit-PatchSet: 1
Gerrit-Owner: ZhiYuanNJ
Gerrit-MessageType: newchange