USB: serial: ch341: name prescaler, divisor registers
authorMichael Hanselmann <public@hansmi.ch>
Wed, 27 May 2020 20:59:53 +0000 (22:59 +0200)
committerJohan Hovold <johan@kernel.org>
Mon, 29 Jun 2020 09:51:53 +0000 (11:51 +0200)
Add constants for the prescaler and divisor registers. Document and
name register 0x25, and put the LCR define to more use.

The 0x25 register (CH341_REG_LCR2) is only used by CH341 chips before
version 0x30 and is involved in configuring the line control parameters.
It's not known to the author whether there any such chips in the wild,
and Linux' ch341 driver never supported them. For chip version 0x30 and
above the 0x25 register is always set to zero. The alternative would've
been to not set the register at all, but that may have unintended
effects.

Signed-off-by: Michael Hanselmann <public@hansmi.ch>
Link: https://lore.kernel.org/r/2e80916d-1be8-dc0f-abf9-adc0feea1803@msgid.hansmi.ch
[ johan: fix up comment ]
Signed-off-by: Johan Hovold <johan@kernel.org>
drivers/usb/serial/ch341.c

index 89675ee..684d595 100644 (file)
 #define CH341_REQ_MODEM_CTRL   0xA4
 
 #define CH341_REG_BREAK        0x05
+#define CH341_REG_PRESCALER    0x12
+#define CH341_REG_DIVISOR      0x13
 #define CH341_REG_LCR          0x18
+#define CH341_REG_LCR2         0x25
+
 #define CH341_NBREAK_BITS      0x01
 
 #define CH341_LCR_ENABLE_RX    0x80
@@ -246,11 +250,20 @@ static int ch341_set_baudrate_lcr(struct usb_device *dev,
         */
        val |= BIT(7);
 
-       r = ch341_control_out(dev, CH341_REQ_WRITE_REG, 0x1312, val);
+       r = ch341_control_out(dev, CH341_REQ_WRITE_REG,
+                             CH341_REG_DIVISOR << 8 | CH341_REG_PRESCALER,
+                             val);
        if (r)
                return r;
 
-       r = ch341_control_out(dev, CH341_REQ_WRITE_REG, 0x2518, lcr);
+       /*
+        * Chip versions before version 0x30 as read using
+        * CH341_REQ_READ_VERSION used separate registers for line control
+        * (stop bits, parity and word length). Version 0x30 and above use
+        * CH341_REG_LCR only and CH341_REG_LCR2 is always set to zero.
+        */
+       r = ch341_control_out(dev, CH341_REQ_WRITE_REG,
+                             CH341_REG_LCR2 << 8 | CH341_REG_LCR, lcr);
        if (r)
                return r;