From 89b54397909dd1d76737b65f682d2aae0781a33c Mon Sep 17 00:00:00 2001 From: James Courtier-Dutton Date: Fri, 21 May 2010 11:53:25 +0100 Subject: USB: iuu_phoenix: Add support for different baud rates. Signed-off-by: James Courtier-Dutton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/iuu_phoenix.c | 54 ++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 13 deletions(-) (limited to 'drivers/usb/serial/iuu_phoenix.c') diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 74551cb..efc7211 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -1,6 +1,8 @@ /* * Infinity Unlimited USB Phoenix driver * + * Copyright (C) 2010 James Courtier-Dutton (James@superbug.co.uk) + * Copyright (C) 2007 Alain Degreffe (eczema@ecze.com) * * Original code taken from iuutool (Copyright (C) 2006 Juan Carlos Borrás) @@ -40,7 +42,7 @@ static int debug; /* * Version Information */ -#define DRIVER_VERSION "v0.11" +#define DRIVER_VERSION "v0.12" #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver" static const struct usb_device_id id_table[] = { @@ -81,6 +83,9 @@ struct iuu_private { u8 *dbgbuf; /* debug buffer */ u8 len; int vcc; /* vcc (either 3 or 5 V) */ + u32 baud; + u32 boost; + u32 clk; }; @@ -157,13 +162,14 @@ static int iuu_tiocmset(struct tty_struct *tty, struct file *file, port->number, set, clear); spin_lock_irqsave(&priv->lock, flags); - if (set & TIOCM_RTS) - priv->tiostatus = TIOCM_RTS; - if (!(set & TIOCM_RTS) && priv->tiostatus == TIOCM_RTS) { + if ((set & TIOCM_RTS) && !(priv->tiostatus == TIOCM_RTS)) { dbg("%s TIOCMSET RESET called !!!", __func__); priv->reset = 1; } + if (set & TIOCM_RTS) + priv->tiostatus = TIOCM_RTS; + spin_unlock_irqrestore(&priv->lock, flags); return 0; } @@ -851,20 +857,24 @@ static int iuu_uart_off(struct usb_serial_port *port) return status; } -static int iuu_uart_baud(struct usb_serial_port *port, u32 baud, +static int iuu_uart_baud(struct usb_serial_port *port, u32 baud_base, u32 *actual, u8 parity) { int status; + u32 baud; u8 *dataout; u8 DataCount = 0; u8 T1Frekvens = 0; u8 T1reload = 0; unsigned int T1FrekvensHZ = 0; + dbg("%s - enter baud_base=%d", __func__, baud_base); dataout = kmalloc(sizeof(u8) * 5, GFP_KERNEL); if (!dataout) return -ENOMEM; + /*baud = (((priv->clk / 35) * baud_base) / 100000); */ + baud = baud_base; if (baud < 1200 || baud > 230400) { kfree(dataout); @@ -948,15 +958,20 @@ static void iuu_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { const u32 supported_mask = CMSPAR|PARENB|PARODD; - + struct iuu_private *priv = usb_get_serial_port_data(port); unsigned int cflag = tty->termios->c_cflag; int status; u32 actual; u32 parity; int csize = CS7; - int baud = 9600; /* Fixed for the moment */ + int baud; u32 newval = cflag & supported_mask; + /* Just use the ospeed. ispeed should be the same. */ + baud = tty->termios->c_ospeed; + + dbg("%s - enter c_ospeed or baud=%d", __func__, baud); + /* compute the parity parameter */ parity = 0; if (cflag & CMSPAR) { /* Using mark space */ @@ -976,15 +991,15 @@ static void iuu_set_termios(struct tty_struct *tty, /* set it */ status = iuu_uart_baud(port, - (clockmode == 2) ? 16457 : 9600 * boost / 100, + baud * priv->boost / 100, &actual, parity); /* set the termios value to the real one, so the user now what has * changed. We support few fields so its easies to copy the old hw * settings back over and then adjust them */ - if (old_termios) - tty_termios_copy_hw(tty->termios, old_termios); + if (old_termios) + tty_termios_copy_hw(tty->termios, old_termios); if (status != 0) /* Set failed - return old bits */ return; /* Re-encode speed, parity and csize */ @@ -1018,6 +1033,7 @@ static void iuu_close(struct usb_serial_port *port) static void iuu_init_termios(struct tty_struct *tty) { + dbg("%s - enter", __func__); *(tty->termios) = tty_std_termios; tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600 | TIOCM_CTS | CSTOPB | PARENB; @@ -1033,10 +1049,16 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port) struct usb_serial *serial = port->serial; u8 *buf; int result; + int baud; u32 actual; struct iuu_private *priv = usb_get_serial_port_data(port); - dbg("%s - port %d", __func__, port->number); + baud = tty->termios->c_ospeed; + tty->termios->c_ispeed = baud; + /* Re-encode speed */ + tty_encode_baud_rate(tty, baud, baud); + + dbg("%s - port %d, baud %d", __func__, port->number, baud); usb_clear_halt(serial->dev, port->write_urb->pipe); usb_clear_halt(serial->dev, port->read_urb->pipe); @@ -1071,23 +1093,29 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port) iuu_uart_on(port); if (boost < 100) boost = 100; + priv->boost = boost; + priv->baud = baud; switch (clockmode) { case 2: /* 3.680 Mhz */ + priv->clk = IUU_CLK_3680000; iuu_clk(port, IUU_CLK_3680000 * boost / 100); result = - iuu_uart_baud(port, 9600 * boost / 100, &actual, + iuu_uart_baud(port, baud * boost / 100, &actual, IUU_PARITY_EVEN); break; case 3: /* 6.00 Mhz */ iuu_clk(port, IUU_CLK_6000000 * boost / 100); + priv->clk = IUU_CLK_6000000; + /* Ratio of 6000000 to 3500000 for baud 9600 */ result = iuu_uart_baud(port, 16457 * boost / 100, &actual, IUU_PARITY_EVEN); break; default: /* 3.579 Mhz */ iuu_clk(port, IUU_CLK_3579000 * boost / 100); + priv->clk = IUU_CLK_3579000; result = - iuu_uart_baud(port, 9600 * boost / 100, &actual, + iuu_uart_baud(port, baud * boost / 100, &actual, IUU_PARITY_EVEN); } -- cgit v1.1