drivers/usb/gadget.c: Add support for EHCI debug using the WCH CH347

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 <nic.c3.14@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/68264
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
This commit is contained in:
Nicholas Chin 2022-10-10 20:39:03 -06:00 committed by Kyösti Mälkki
parent 458751c2d5
commit 81827aad3c
2 changed files with 87 additions and 0 deletions

View File

@ -92,6 +92,14 @@ config USBDEBUG_DONGLE_FTDI_FT232H
Use this with FT232H usb-to-uart. Configuration is hard-coded Use this with FT232H usb-to-uart. Configuration is hard-coded
to use 8n1, no flow control. 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 endchoice
config USBDEBUG_DONGLE_FTDI_FT232H_BAUD 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 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. 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 config USBDEBUG_OPTIONAL_HUB_PORT
int int
default 2 if USBDEBUG_DONGLE_BEAGLEBONE default 2 if USBDEBUG_DONGLE_BEAGLEBONE

View File

@ -205,6 +205,73 @@ small_write:
return 0; 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. */ /* FTDI FT232H UART programming. */
#define FTDI_SIO_SET_FLOW_CTRL_REQUEST 0x02 #define FTDI_SIO_SET_FLOW_CTRL_REQUEST 0x02
#define FTDI_SIO_SET_BAUDRATE_REQUEST 0x03 #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)) { if (CONFIG(USBDEBUG_DONGLE_FTDI_FT232H)) {
ret = probe_for_ftdi(ehci_debug, pipe); ret = probe_for_ftdi(ehci_debug, pipe);
} else if (CONFIG(USBDEBUG_DONGLE_WCH_CH347)) {
ret = probe_for_ch347(ehci_debug, pipe);
} else { } else {
ret = probe_for_debug_descriptor(ehci_debug, pipe); ret = probe_for_debug_descriptor(ehci_debug, pipe);
} }