summaryrefslogtreecommitdiff
path: root/sys/dev/usb
diff options
context:
space:
mode:
authorsasano <sasano@cvs.openbsd.org>2014-05-16 14:05:40 +0000
committersasano <sasano@cvs.openbsd.org>2014-05-16 14:05:40 +0000
commit28b155d8eb0ab2ad321858434438a3d3d9a2bf6c (patch)
tree4e6e5323e5ce04d66e1ef6ab4b7f1e1295ff7180 /sys/dev/usb
parent1266f11a4fbb0f3bc17e3c639e1f80ad16fddf35 (diff)
It seems that there is new and old revision of CH340.
Previous uchcom(4) driver targeted old one, and new one could not work because of uchcom_set_line_control() broke the value of UCHCOM_REG_LCR1(0x18). To support new CH340, uchcom_set_line_control() and uchcom_reset_chip() have been overhauled. Current uchcom(4) does not change the value of UCHCOM_REG_LCR1 register, it means even/odd parity mode is no longer supported with old CH340. ok by mpi@
Diffstat (limited to 'sys/dev/usb')
-rw-r--r--sys/dev/usb/uchcom.c89
1 files changed, 16 insertions, 73 deletions
diff --git a/sys/dev/usb/uchcom.c b/sys/dev/usb/uchcom.c
index 8f92ebe0b5b..502b920b3c5 100644
--- a/sys/dev/usb/uchcom.c
+++ b/sys/dev/usb/uchcom.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uchcom.c,v 1.19 2013/11/15 10:17:39 pirofti Exp $ */
+/* $OpenBSD: uchcom.c,v 1.20 2014/05/16 14:05:39 sasano Exp $ */
/* $NetBSD: uchcom.c,v 1.1 2007/09/03 17:57:37 tshiozak Exp $ */
/*
@@ -91,18 +91,17 @@ int uchcomdebug = 0;
#define UCHCOM_BRK1_MASK 0x01
#define UCHCOM_BRK2_MASK 0x40
-#define UCHCOM_LCR1_MASK 0xAF
-#define UCHCOM_LCR2_MASK 0x07
-#define UCHCOM_LCR1_PARENB 0x80
-#define UCHCOM_LCR2_PAREVEN 0x07
-#define UCHCOM_LCR2_PARODD 0x06
-#define UCHCOM_LCR2_PARMARK 0x05
-#define UCHCOM_LCR2_PARSPACE 0x04
-
#define UCHCOM_INTR_STAT1 0x02
#define UCHCOM_INTR_STAT2 0x03
#define UCHCOM_INTR_LEAST 4
+/*
+ * XXX - these magic numbers come from Linux (drivers/usb/serial/ch341.c).
+ * The manufacturer was unresponsive when asked for documentation.
+ */
+#define UCHCOM_RESET_VALUE 0x501F /* line mode? */
+#define UCHCOM_RESET_INDEX 0xD90A /* baud rate? */
+
#define UCHCOMIBUFSIZE 256
#define UCHCOMOBUFSIZE 256
@@ -707,27 +706,10 @@ uchcom_set_dte_rate(struct uchcom_softc *sc, uint32_t rate)
int
uchcom_set_line_control(struct uchcom_softc *sc, tcflag_t cflag)
{
- usbd_status err;
- uint8_t lcr1 = 0, lcr2 = 0;
-
- err = uchcom_read_reg(sc, UCHCOM_REG_LCR1, &lcr1, UCHCOM_REG_LCR2,
- &lcr2);
- if (err) {
- printf("%s: cannot get LCR: %s\n",
- sc->sc_dev.dv_xname, usbd_errstr(err));
- return EIO;
- }
-
- lcr1 &= ~UCHCOM_LCR1_MASK;
- lcr2 &= ~UCHCOM_LCR2_MASK;
-
/*
* XXX: it is difficult to handle the line control appropriately:
- * - CS8, !CSTOPB and any parity mode seems ok, but
- * - the chip doesn't have the function to calculate parity
- * in !CS8 mode.
- * - it is unclear that the chip supports CS5,6 mode.
- * - it is unclear how to handle stop bits.
+ * work as chip default - CS8, no parity, !CSTOPB
+ * other modes are not supported.
*/
switch (ISSET(cflag, CSIZE)) {
@@ -739,21 +721,8 @@ uchcom_set_line_control(struct uchcom_softc *sc, tcflag_t cflag)
break;
}
- if (ISSET(cflag, PARENB)) {
- lcr1 |= UCHCOM_LCR1_PARENB;
- if (ISSET(cflag, PARODD))
- lcr2 |= UCHCOM_LCR2_PARODD;
- else
- lcr2 |= UCHCOM_LCR2_PAREVEN;
- }
-
- err = uchcom_write_reg(sc, UCHCOM_REG_LCR1, lcr1, UCHCOM_REG_LCR2,
- lcr2);
- if (err) {
- printf("%s: cannot set LCR: %s\n",
- sc->sc_dev.dv_xname, usbd_errstr(err));
- return EIO;
- }
+ if (ISSET(cflag, PARENB) || ISSET(cflag, CSTOPB))
+ return EINVAL;
return 0;
}
@@ -778,38 +747,12 @@ int
uchcom_reset_chip(struct uchcom_softc *sc)
{
usbd_status err;
- uint8_t lcr1, lcr2, pre, div, mod;
- uint16_t val=0, idx=0;
-
- err = uchcom_read_reg(sc, UCHCOM_REG_LCR1, &lcr1, UCHCOM_REG_LCR2, &lcr2);
- if (err)
- goto failed;
-
- err = uchcom_read_reg(sc, UCHCOM_REG_BPS_PRE, &pre, UCHCOM_REG_BPS_DIV,
- &div);
- if (err)
- goto failed;
- err = uchcom_read_reg(sc, UCHCOM_REG_BPS_MOD, &mod, UCHCOM_REG_BPS_PAD,
- NULL);
- if (err)
- goto failed;
+ DPRINTF(("%s: reset\n", sc->sc_dev.dv_xname));
- val |= (uint16_t)(lcr1&0xF0) << 8;
- val |= 0x01;
- val |= (uint16_t)(lcr2&0x0F) << 8;
- val |= 0x02;
- idx |= pre & 0x07;
- val |= 0x04;
- idx |= (uint16_t)div << 8;
- val |= 0x08;
- idx |= mod & 0xF8;
- val |= 0x10;
-
- DPRINTF(("%s: reset v=0x%04X, i=0x%04X\n",
- sc->sc_dev.dv_xname, val, idx));
-
- err = uchcom_generic_control_out(sc, UCHCOM_REQ_RESET, val, idx);
+ err = uchcom_generic_control_out(sc, UCHCOM_REQ_RESET,
+ UCHCOM_RESET_VALUE,
+ UCHCOM_RESET_INDEX);
if (err)
goto failed;