USB: iuu_phoenix: Add support for different baud rates.

Signed-off-by: James Courtier-Dutton <James@superbug.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

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 @@
 /*
  * 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 @@
 	u8 *dbgbuf;		/* debug buffer */
 	u8 len;
 	int vcc;		/* vcc (either 3 or 5 V) */
+	u32 baud;
+	u32 boost;
+	u32 clk;
 };
 
 
@@ -157,13 +162,14 @@
 	    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 @@
 	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 @@
 		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 @@
 
 	/* 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_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 @@
 	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 @@
 	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);
 	}