static int ark3116_port_probe(struct usb_serial_port *port) { struct usb_serial *serial = port->serial; struct ark3116_private *priv; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; mutex_init(&priv->hw_lock); spin_lock_init(&priv->status_lock); priv->irda = is_irda(serial); usb_set_serial_port_data(port, priv); /* setup the hardware */ ark3116_write_reg(serial, UART_IER, 0); /* disable DMA */ ark3116_write_reg(serial, UART_FCR, 0); /* handshake control */ priv->hcr = 0; ark3116_write_reg(serial, 0x8 , 0); /* modem control */ priv->mcr = 0; ark3116_write_reg(serial, UART_MCR, 0); if (!(priv->irda)) { ark3116_write_reg(serial, 0xb , 0); } else { ark3116_write_reg(serial, 0xb , 1); ark3116_write_reg(serial, 0xc , 0); ark3116_write_reg(serial, 0xd , 0x41); ark3116_write_reg(serial, 0xa , 1); } /* setup baudrate */ ark3116_write_reg(serial, UART_LCR, UART_LCR_DLAB); /* setup for 9600 8N1 */ priv->quot = calc_divisor(9600); ark3116_write_reg(serial, UART_DLL, priv->quot & 0xff); ark3116_write_reg(serial, UART_DLM, (priv->quot>>8) & 0xff); priv->lcr = UART_LCR_WLEN8; ark3116_write_reg(serial, UART_LCR, UART_LCR_WLEN8); ark3116_write_reg(serial, 0xe, 0); if (priv->irda) ark3116_write_reg(serial, 0x9, 0); dev_info(&serial->dev->dev, "%s using %s mode\n", KBUILD_MODNAME, priv->irda ? "IrDA" : "RS232"); return 0; }
static void ark3116_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct ark3116_private *priv = usb_get_serial_port_data(port); struct ktermios *termios = &tty->termios; unsigned int cflag = termios->c_cflag; int bps = tty_get_baud_rate(tty); int quot; __u8 lcr, hcr, eval; /* set data bit count */ switch (cflag & CSIZE) { case CS5: lcr = UART_LCR_WLEN5; break; case CS6: lcr = UART_LCR_WLEN6; break; case CS7: lcr = UART_LCR_WLEN7; break; default: case CS8: lcr = UART_LCR_WLEN8; break; } if (cflag & CSTOPB) lcr |= UART_LCR_STOP; if (cflag & PARENB) lcr |= UART_LCR_PARITY; if (!(cflag & PARODD)) lcr |= UART_LCR_EPAR; #ifdef CMSPAR if (cflag & CMSPAR) lcr |= UART_LCR_SPAR; #endif /* handshake control */ hcr = (cflag & CRTSCTS) ? 0x03 : 0x00; /* calc baudrate */ dev_dbg(&port->dev, "%s - setting bps to %d\n", __func__, bps); eval = 0; switch (bps) { case 0: quot = calc_divisor(9600); break; default: if ((bps < 75) || (bps > 3000000)) bps = 9600; quot = calc_divisor(bps); break; case 460800: eval = 1; quot = calc_divisor(bps); break; case 921600: eval = 2; quot = calc_divisor(bps); break; } /* Update state: synchronize */ mutex_lock(&priv->hw_lock); /* keep old LCR_SBC bit */ lcr |= (priv->lcr & UART_LCR_SBC); dev_dbg(&port->dev, "%s - setting hcr:0x%02x,lcr:0x%02x,quot:%d\n", __func__, hcr, lcr, quot); /* handshake control */ if (priv->hcr != hcr) { priv->hcr = hcr; ark3116_write_reg(serial, 0x8, hcr); } /* baudrate */ if (priv->quot != quot) { priv->quot = quot; priv->lcr = lcr; /* need to write lcr anyway */ /* disable DMA since transmit/receive is * shadowed by UART_DLL */ ark3116_write_reg(serial, UART_FCR, 0); ark3116_write_reg(serial, UART_LCR, lcr|UART_LCR_DLAB); ark3116_write_reg(serial, UART_DLL, quot & 0xff); ark3116_write_reg(serial, UART_DLM, (quot>>8) & 0xff); /* restore lcr */ ark3116_write_reg(serial, UART_LCR, lcr); /* magic baudrate thingy: not sure what it does, * but windows does this as well. */ ark3116_write_reg(serial, 0xe, eval); /* enable DMA */ ark3116_write_reg(serial, UART_FCR, UART_FCR_DMA_SELECT); } else if (priv->lcr != lcr) {
static int ark3116_attach(struct usb_serial *serial) { struct usb_serial_port *port = serial->port[0]; struct ark3116_private *priv; /* make sure we have our end-points */ if ((serial->num_bulk_in == 0) || (serial->num_bulk_out == 0) || (serial->num_interrupt_in == 0)) { dev_err(&serial->dev->dev, "%s - missing endpoint - " "bulk in: %d, bulk out: %d, int in %d\n", KBUILD_MODNAME, serial->num_bulk_in, serial->num_bulk_out, serial->num_interrupt_in); return -EINVAL; } priv = kzalloc(sizeof(struct ark3116_private), GFP_KERNEL); if (!priv) return -ENOMEM; init_waitqueue_head(&priv->delta_msr_wait); mutex_init(&priv->hw_lock); spin_lock_init(&priv->status_lock); priv->irda = is_irda(serial); usb_set_serial_port_data(port, priv); /* setup the hardware */ ark3116_write_reg(serial, UART_IER, 0); /* disable DMA */ ark3116_write_reg(serial, UART_FCR, 0); /* handshake control */ priv->hcr = 0; ark3116_write_reg(serial, 0x8 , 0); /* modem control */ priv->mcr = 0; ark3116_write_reg(serial, UART_MCR, 0); if (!(priv->irda)) { ark3116_write_reg(serial, 0xb , 0); } else { ark3116_write_reg(serial, 0xb , 1); ark3116_write_reg(serial, 0xc , 0); ark3116_write_reg(serial, 0xd , 0x41); ark3116_write_reg(serial, 0xa , 1); } /* setup baudrate */ ark3116_write_reg(serial, UART_LCR, UART_LCR_DLAB); /* setup for 9600 8N1 */ priv->quot = calc_divisor(9600); ark3116_write_reg(serial, UART_DLL, priv->quot & 0xff); ark3116_write_reg(serial, UART_DLM, (priv->quot>>8) & 0xff); priv->lcr = UART_LCR_WLEN8; ark3116_write_reg(serial, UART_LCR, UART_LCR_WLEN8); ark3116_write_reg(serial, 0xe, 0); if (priv->irda) ark3116_write_reg(serial, 0x9, 0); dev_info(&serial->dev->dev, "%s using %s mode\n", KBUILD_MODNAME, priv->irda ? "IrDA" : "RS232"); return 0; }