From 81827aad3cf4a65128b8e609b183e8a240d08350 Mon Sep 17 00:00:00 2001 From: Nicholas Chin Date: Mon, 10 Oct 2022 20:39:03 -0600 Subject: drivers/usb/gadget.c: Add support for EHCI debug using the WCH CH347 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The WCH CH347 presents a USB CDC serial port on interface 4 while in operating modes 0, 1, and 3. Mode 0 also presents a UART on interface 2 but this is ignored for compatibility with the other modes. Mode 2 uses vendor defined HID usages for communication and is not currently supported. Like the FT232H the data format is hard coded to 8n1. Tested using a CH347 breakout board and a Dell Latitude E6400. Change-Id: Ibd4ad17b7369948003fff7e825b46fe852bc7eb9 Signed-off-by: Nicholas Chin Reviewed-on: https://review.coreboot.org/c/coreboot/+/68264 Reviewed-by: Angel Pons Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki --- src/drivers/usb/Kconfig | 18 +++++++++++++ src/drivers/usb/gadget.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) (limited to 'src/drivers/usb') diff --git a/src/drivers/usb/Kconfig b/src/drivers/usb/Kconfig index 6854c4a6b6..36fda75c8d 100644 --- a/src/drivers/usb/Kconfig +++ b/src/drivers/usb/Kconfig @@ -92,6 +92,14 @@ config USBDEBUG_DONGLE_FTDI_FT232H Use this with FT232H usb-to-uart. Configuration is hard-coded to use 8n1, no flow control. +config USBDEBUG_DONGLE_WCH_CH347 + bool "WCH CH347 UART" + help + Use this with CH347 usb-to-uart. Configuration is hard-coded + to use 8n1, no flow control. For compatibility across modes + 0, 1, and 3, only UART 1 is supported. The UART in mode 2 is + not currently supported. + endchoice config USBDEBUG_DONGLE_FTDI_FT232H_BAUD @@ -104,6 +112,16 @@ config USBDEBUG_DONGLE_FTDI_FT232H_BAUD connection works with it. Multiples of 115,200 seem to be a good choice, and EHCI debug usually can't saturate more than 576,000. +config USBDEBUG_DONGLE_WCH_CH347_BAUD + int "WCH CH347 baud rate" + default 115200 + depends on USBDEBUG_DONGLE_WCH_CH347 + help + Select baud rate for CH347 in the range 1200..9,000,000. Make + sure that your receiving side supports the same setting and your + connection works with it. Multiples of 115,200 seem to be a good + choice, and EHCI debug usually can't saturate more than 576,000. + config USBDEBUG_OPTIONAL_HUB_PORT int default 2 if USBDEBUG_DONGLE_BEAGLEBONE diff --git a/src/drivers/usb/gadget.c b/src/drivers/usb/gadget.c index fcb361cc83..d7614474ce 100644 --- a/src/drivers/usb/gadget.c +++ b/src/drivers/usb/gadget.c @@ -205,6 +205,73 @@ small_write: return 0; } +/* Refer to USB CDC PSTN Subclass specification section 6.3 */ +#define CDC_SET_LINE_CODING_REQUEST 0x20 +struct cdc_line_coding { + u32 baudrate; + u8 stop_bits; + u8 parity; + u8 data_bits; +} __packed; + +static int probe_for_ch347(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe) +{ + int ret; + u8 devnum = 0; + u8 uart_if = 2; /* CH347 UART 1 */ + + /* Move the device to 127 if it isn't already there */ + ret = dbgp_control_msg(ehci_debug, devnum, + USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, + USB_REQ_SET_ADDRESS, USB_DEBUG_DEVNUM, 0, NULL, 0); + if (ret < 0) { + printk(BIOS_INFO, "Could not move attached device to %d.\n", + USB_DEBUG_DEVNUM); + return -2; + } + devnum = USB_DEBUG_DEVNUM; + printk(BIOS_INFO, "EHCI debug device renamed to %d.\n", devnum); + + /* Send Set Configure request to device. */ + ret = dbgp_control_msg(ehci_debug, devnum, + USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, + USB_REQ_SET_CONFIGURATION, 1, 0, NULL, 0); + if (ret < 0) { + printk(BIOS_INFO, "CH347 set configuration failed.\n"); + return -2; + } + + struct cdc_line_coding line_coding = { + .baudrate = CONFIG_USBDEBUG_DONGLE_WCH_CH347_BAUD, + .stop_bits = 0, /* 1 stop bit */ + .parity = 0, /* No parity */ + .data_bits = 8 + }; + + ret = dbgp_control_msg(ehci_debug, devnum, + USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + CDC_SET_LINE_CODING_REQUEST, 0, uart_if, &line_coding, sizeof(line_coding)); + if (ret < 0) { + printk(BIOS_INFO, "CDC SET_LINE_CODING failed.\n"); + return -3; + } + + /* Modes 0, 1, and 3 all have UART 1 on endpoint 4 in common */ + pipe[DBGP_CONSOLE_EPOUT].endpoint = 0x04; + pipe[DBGP_CONSOLE_EPIN].endpoint = 0x84; + + ack_set_configuration(pipe, devnum, 1000); + + /* Perform a small write. */ + ret = dbgp_bulk_write_x(&pipe[DBGP_CONSOLE_EPOUT], "USB\r\n", 5); + if (ret < 0) { + printk(BIOS_INFO, "dbgp_bulk_write failed: %d\n", ret); + return -4; + } + printk(BIOS_INFO, "Test write done\n"); + return 0; +} + /* FTDI FT232H UART programming. */ #define FTDI_SIO_SET_FLOW_CTRL_REQUEST 0x02 #define FTDI_SIO_SET_BAUDRATE_REQUEST 0x03 @@ -329,6 +396,8 @@ int dbgp_probe_gadget(struct ehci_dbg_port *ehci_debug, struct dbgp_pipe *pipe) if (CONFIG(USBDEBUG_DONGLE_FTDI_FT232H)) { ret = probe_for_ftdi(ehci_debug, pipe); + } else if (CONFIG(USBDEBUG_DONGLE_WCH_CH347)) { + ret = probe_for_ch347(ehci_debug, pipe); } else { ret = probe_for_debug_descriptor(ehci_debug, pipe); } -- cgit v1.2.3