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