This adds support for the FT2232H and FT4232H serial adapters.
(FT2232H found on the BeagleBone).

These devices have a 120MHz base clock for the baud rate generator
and need a different encoding for the baud rate divisor.
The values for ibufsize/obufsize are now taken from the endpoint descriptors.

I can't be sure that this does not break anything. It would have to be
tested on various devices.

Regards
Raphael


Index: sys/dev/usb/uftdireg.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/uftdireg.h,v
retrieving revision 1.12
diff -u -p -r1.12 uftdireg.h
--- sys/dev/usb/uftdireg.h      5 Jul 2008 14:41:28 -0000       1.12
+++ sys/dev/usb/uftdireg.h      8 Sep 2012 14:32:13 -0000
@@ -35,7 +35,8 @@

 enum uftdi_type {
        UFTDI_TYPE_SIO,
-       UFTDI_TYPE_8U232AM
+       UFTDI_TYPE_8U232AM,
+       UFTDI_TYPE_2232H
 };

 /*
@@ -91,7 +92,8 @@ enum {
        ftdi_sio_b115200 = 9
 };

-#define FTDI_8U232AM_FREQ 3000000
+#define FTDI_8U232AM_FREQ 3000000 /* (48MHz / 16) */
+#define FTDI_2232H_FREQ 12000000 /* (120MHz / 10) */

 /* Bounds for normal divisors as 4-bit fixed precision ints. */
 #define FTDI_8U232AM_MIN_DIV 0x20
Index: sys/dev/usb/uftdi.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/uftdi.c,v
retrieving revision 1.62
diff -u -p -r1.62 uftdi.c
--- sys/dev/usb/uftdi.c 28 Oct 2011 01:45:55 -0000      1.62
+++ sys/dev/usb/uftdi.c 8 Sep 2012 14:32:14 -0000
@@ -105,6 +105,7 @@ void        uftdi_write(void *sc, int portno, u
                            u_int32_t *count);
 void   uftdi_break(void *sc, int portno, int onoff);
 int    uftdi_8u232am_getrate(speed_t speed, int *rate);
+int    uftdi_2232h_getrate(speed_t speed, int *rate);

 struct ucom_methods uftdi_methods = {
        uftdi_get_status,
@@ -824,6 +825,9 @@ uftdi_attach(struct device *parent, stru
        if (uaa->release < 0x0200) {
                sc->sc_type = UFTDI_TYPE_SIO;
                sc->sc_hdrlen = 1;
+       } else if (uaa->release == 0x0700  || uaa->release == 0x0800) {
+               sc->sc_type = UFTDI_TYPE_2232H;
+               sc->sc_hdrlen = 0;
        } else {
                sc->sc_type = UFTDI_TYPE_8U232AM;
                sc->sc_hdrlen = 0;
@@ -842,11 +846,16 @@ uftdi_attach(struct device *parent, stru
                addr = ed->bEndpointAddress;
                dir = UE_GET_DIR(ed->bEndpointAddress);
                attr = ed->bmAttributes & UE_XFERTYPE;
-               if (dir == UE_DIR_IN && attr == UE_BULK)
+               if (dir == UE_DIR_IN && attr == UE_BULK) {
                        uca.bulkin = addr;
-               else if (dir == UE_DIR_OUT && attr == UE_BULK)
+                       uca.ibufsize = (UGETW(ed->wMaxPacketSize) > 0) ?
+                           UGETW(ed->wMaxPacketSize) : UFTDIIBUFSIZE;
+               } else if (dir == UE_DIR_OUT && attr == UE_BULK) {
                        uca.bulkout = addr;
-               else {
+                       uca.obufsize = (UGETW(ed->wMaxPacketSize) > 0) ?
+                           UGETW(ed->wMaxPacketSize) : UFTDIOBUFSIZE;
+                       uca.obufsize-= sc->sc_hdrlen;
+               } else {
                        printf("%s: unexpected endpoint\n", devname);
                        goto bad;
                }
@@ -867,9 +876,7 @@ uftdi_attach(struct device *parent, stru
        else
                uca.portno = FTDI_PIT_SIOA + id->bInterfaceNumber;
        /* bulkin, bulkout set above */
-       uca.ibufsize = UFTDIIBUFSIZE;
-       uca.obufsize = UFTDIOBUFSIZE - sc->sc_hdrlen;
-       uca.ibufsizepad = UFTDIIBUFSIZE;
+       uca.ibufsizepad = uca.ibufsize;
        uca.opkthdrlen = sc->sc_hdrlen;
        uca.device = dev;
        uca.iface = iface;
@@ -1076,11 +1083,15 @@ uftdi_param(void *vsc, int portno, struc
                if (uftdi_8u232am_getrate(t->c_ospeed, &rate) == -1)
                        return (EINVAL);
                break;
+       case UFTDI_TYPE_2232H:
+               if (uftdi_2232h_getrate(t->c_ospeed, &rate) == -1)
+                        return (EINVAL);
+               break;
        }
        req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
        req.bRequest = FTDI_SIO_SET_BAUD_RATE;
        USETW(req.wValue, rate);
-       USETW(req.wIndex, portno);
+       USETW(req.wIndex, ((rate >> 8) & 0xFF00) | portno);
        USETW(req.wLength, 0);
        DPRINTFN(2,("uftdi_param: reqtype=0x%02x req=0x%02x value=0x%04x "
                    "index=0x%04x len=%d\n", req.bmRequestType, req.bRequest,
@@ -1249,4 +1260,34 @@ uftdi_8u232am_getrate(speed_t speed, int
 done:
        *rate = result;
        return (0);
+}
+
+int
+uftdi_2232h_getrate(speed_t speed, int *rate)
+{
+       char sub[8] = {0, 3, 2, 4, 1, 5, 6, 7};
+       int n = (FTDI_2232H_FREQ << 3) / speed;
+       int s = n & 7;
+       int result = (n >> 3) | (sub[s] << 14);
+       int resultspeed, accuracy;
+
+       /* Special cases */
+       if (result == 1)
+               result = 0;
+       else if (result == 0x4001)
+               result = 1;
+
+       /* Check if resulting baud rate is within 3%. */
+       if (result == 0)
+               goto done;
+       resultspeed = (FTDI_2232H_FREQ << 3) /
+           (((result & 0x00003FFF) << 3) | s);
+       accuracy = (abs(speed - resultspeed) * 100) / speed;
+       if (accuracy > 3)
+               return -1;
+
+done:
+       result|= 0x00020000; /* Set this bit to turn off a divide by 2.5 */
+       *rate = result;
+       return 0;
 }
Index: share/man/man4/uftdi.4
===================================================================
RCS file: /cvs/src/share/man/man4/uftdi.4,v
retrieving revision 1.27
diff -u -p -r1.27 uftdi.4
--- share/man/man4/uftdi.4      7 Nov 2009 05:18:09 -0000       1.27
+++ share/man/man4/uftdi.4      8 Sep 2012 14:32:14 -0000
@@ -41,7 +41,7 @@
 The
 .Nm
 driver provides support for various serial adapters based on the FTDI
-FT8U100AX, FT232BM, FT2232C, FT8U232AM, and FT8U245AM chips.
+FT8U100AX, FT232BM, FT2232C, FT2232H, FT8U232AM, and FT8U245AM chips.
 .Pp
 The device is accessed through the
 .Xr ucom 4

Reply via email to