Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 23 Oct 2010 02:59:04 +0000 (19:59 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 23 Oct 2010 02:59:04 +0000 (19:59 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6: (49 commits)
  serial8250: ratelimit "too much work" error
  serial: bfin_sport_uart: speed up sport RX sample rate to be 3% faster
  serial: abstraction for 8250 legacy ports
  serial/imx: check that the buffer is non-empty before sending it out
  serial: mfd: add more baud rates support
  jsm: Remove the uart port on errors
  Alchemy: Add UART PM methods.
  8250: allow platforms to override PM hook.
  altera_uart: Don't use plain integer as NULL pointer
  altera_uart: Fix missing prototype for registering an early console
  altera_uart: Fixup type usage of port flags
  altera_uart: Make it possible to use Altera UART and 8250 ports together
  altera_uart: Add support for different address strides
  altera_uart: Add support for getting mapbase and IRQ from resources
  altera_uart: Add support for polling mode (IRQ-less)
  serial: Factor out uart_poll_timeout() from 8250 driver
  serial: mark the 8250 driver as maintained
  serial: 8250: Don't delay after transmitter is ready.
  tty: MAINTAINERS: add drivers/serial/jsm/ as maintained driver
  vcs: invoke the vt update callback when /dev/vcs* is written to
  ...

1  2 
MAINTAINERS
drivers/char/ip2/ip2main.c
drivers/char/pcmcia/synclink_cs.c
drivers/serial/Kconfig
drivers/serial/mfd.c

diff --combined MAINTAINERS
@@@ -157,9 -157,11 +157,11 @@@ S:       Maintaine
  F:    drivers/net/r8169.c
  
  8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
+ M:    Greg Kroah-Hartman <gregkh@suse.de>
  L:    linux-serial@vger.kernel.org
  W:    http://serial.sourceforge.net
- S:    Orphan
+ S:    Maintained
+ T:    quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
  F:    drivers/serial/8250*
  F:    include/linux/serial_8250.h
  
@@@ -990,23 -992,11 +992,23 @@@ S:      Supporte
  F:    arch/arm/mach-shmobile/
  F:    drivers/sh/
  
 +ARM/TELECHIPS ARM ARCHITECTURE
 +M:    "Hans J. Koch" <hjk@linutronix.de>
 +L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 +S:    Maintained
 +F:    arch/arm/plat-tcc/
 +F:    arch/arm/mach-tcc8k/
 +
  ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
  M:    Lennert Buytenhek <kernel@wantstofly.org>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
  
 +ARM/TETON BGA MACHINE SUPPORT
 +M:    Mark F. Brown <mark.brown314@gmail.com>
 +L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 +S:    Maintained
 +
  ARM/THECUS N2100 MACHINE SUPPORT
  M:    Lennert Buytenhek <kernel@wantstofly.org>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@@ -1539,8 -1529,6 +1541,8 @@@ T:      git git://git.kernel.org/pub/scm/lin
  S:    Supported
  F:    Documentation/filesystems/ceph.txt
  F:    fs/ceph
 +F:    net/ceph
 +F:    include/linux/ceph
  
  CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM:
  M:    David Vrabel <david.vrabel@csr.com>
@@@ -2064,16 -2052,14 +2066,16 @@@ F:   drivers/block/drbd
  F:    lib/lru_cache.c
  F:    Documentation/blockdev/drbd/
  
 -DRIVER CORE, KOBJECTS, AND SYSFS
 +DRIVER CORE, KOBJECTS, DEBUGFS AND SYSFS
  M:    Greg Kroah-Hartman <gregkh@suse.de>
  T:    quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
  S:    Supported
  F:    Documentation/kobject.txt
  F:    drivers/base/
  F:    fs/sysfs/
 +F:    fs/debugfs/
  F:    include/linux/kobj*
 +F:    include/linux/debugfs.h
  F:    lib/kobj*
  
  DRM DRIVERS
@@@ -3255,12 -3241,6 +3257,12 @@@ F:    drivers/net/irda
  F:    include/net/irda/
  F:    net/irda/
  
 +IRQ SUBSYSTEM
 +M:    Thomas Gleixner <tglx@linutronix.de>
 +S:    Maintained
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git irq/core
 +F:    kernel/irq/
 +
  ISAPNP
  M:    Jaroslav Kysela <perex@perex.cz>
  S:    Maintained
@@@ -3352,6 -3332,12 +3354,12 @@@ S:    Maintaine
  F:    fs/jbd*/
  F:    include/linux/ext*jbd*.h
  F:    include/linux/jbd*.h
+ JSM Neo PCI based serial card
+ M:    Breno Leitao <leitao@linux.vnet.ibm.com>
+ L:    linux-serial@vger.kernel.org
+ S:    Maintained
+ F:    drivers/serial/jsm/
  
  K8TEMP HARDWARE MONITORING DRIVER
  M:    Rudolf Marek <r.marek@assembler.cz>
@@@ -4827,15 -4813,6 +4835,15 @@@ F:    fs/qnx4
  F:    include/linux/qnx4_fs.h
  F:    include/linux/qnxtypes.h
  
 +RADOS BLOCK DEVICE (RBD)
 +F:    include/linux/qnxtypes.h
 +M:    Yehuda Sadeh <yehuda@hq.newdream.net>
 +M:    Sage Weil <sage@newdream.net>
 +M:    ceph-devel@vger.kernel.org
 +S:    Supported
 +F:    drivers/block/rbd.c
 +F:    drivers/block/rbd_types.h
 +
  RADEON FRAMEBUFFER DISPLAY DRIVER
  M:    Benjamin Herrenschmidt <benh@kernel.crashing.org>
  L:    linux-fbdev@vger.kernel.org
@@@ -98,7 -98,7 +98,7 @@@
  #include <linux/major.h>
  #include <linux/wait.h>
  #include <linux/device.h>
 -#include <linux/smp_lock.h>
 +#include <linux/mutex.h>
  #include <linux/firmware.h>
  #include <linux/platform_device.h>
  
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
  
 +static DEFINE_MUTEX(ip2_mutex);
  static const struct file_operations ip2mem_proc_fops;
  static const struct file_operations ip2_proc_fops;
  
@@@ -184,6 -183,8 +184,8 @@@ static void ip2_hangup(PTTY)
  static int  ip2_tiocmget(struct tty_struct *tty, struct file *file);
  static int  ip2_tiocmset(struct tty_struct *tty, struct file *file,
                         unsigned int set, unsigned int clear);
+ static int ip2_get_icount(struct tty_struct *tty,
+               struct serial_icounter_struct *icount);
  
  static void set_irq(int, int);
  static void ip2_interrupt_bh(struct work_struct *work);
@@@ -237,7 -238,6 +239,7 @@@ static const struct file_operations ip2
        .write          = ip2_ipl_write,
        .unlocked_ioctl = ip2_ipl_ioctl,
        .open           = ip2_ipl_open,
 +      .llseek         = noop_llseek,
  }; 
  
  static unsigned long irq_counter;
@@@ -456,6 -456,7 +458,7 @@@ static const struct tty_operations ip2_
        .hangup          = ip2_hangup,
        .tiocmget        = ip2_tiocmget,
        .tiocmset        = ip2_tiocmset,
+       .get_icount      = ip2_get_icount,
        .proc_fops       = &ip2_proc_fops,
  };
  
@@@ -2130,7 -2131,6 +2133,6 @@@ ip2_ioctl ( PTTY tty, struct file *pFil
        i2ChanStrPtr pCh = DevTable[tty->index];
        i2eBordStrPtr pB;
        struct async_icount cprev, cnow;        /* kernel counter temps */
-       struct serial_icounter_struct __user *p_cuser;
        int rc = 0;
        unsigned long flags;
        void __user *argp = (void __user *)arg;
                return rc;
                break;
  
-       /*
-        * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-        * Return: write counters to the user passed counter struct
-        * NB: both 1->0 and 0->1 transitions are counted except for RI where
-        * only 0->1 is counted. The controller is quite capable of counting
-        * both, but this done to preserve compatibility with the standard
-        * serial driver.
-        */
-       case TIOCGICOUNT:
-               ip2trace (CHANN, ITRC_IOCTL, 11, 1, rc );
-               write_lock_irqsave(&pB->read_fifo_spinlock, flags);
-               cnow = pCh->icount;
-               write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
-               p_cuser = argp;
-               rc = put_user(cnow.cts, &p_cuser->cts);
-               rc = put_user(cnow.dsr, &p_cuser->dsr);
-               rc = put_user(cnow.rng, &p_cuser->rng);
-               rc = put_user(cnow.dcd, &p_cuser->dcd);
-               rc = put_user(cnow.rx, &p_cuser->rx);
-               rc = put_user(cnow.tx, &p_cuser->tx);
-               rc = put_user(cnow.frame, &p_cuser->frame);
-               rc = put_user(cnow.overrun, &p_cuser->overrun);
-               rc = put_user(cnow.parity, &p_cuser->parity);
-               rc = put_user(cnow.brk, &p_cuser->brk);
-               rc = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
-               break;
        /*
         * The rest are not supported by this driver. By returning -ENOIOCTLCMD they
         * will be passed to the line discipline for it to handle.
        return rc;
  }
  
+ static int ip2_get_icount(struct tty_struct *tty,
+               struct serial_icounter_struct *icount)
+ {
+       i2ChanStrPtr pCh = DevTable[tty->index];
+       i2eBordStrPtr pB;
+       struct async_icount cnow;       /* kernel counter temp */
+       unsigned long flags;
+       if ( pCh == NULL )
+               return -ENODEV;
+       pB = pCh->pMyBord;
+       /*
+        * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+        * Return: write counters to the user passed counter struct
+        * NB: both 1->0 and 0->1 transitions are counted except for RI where
+        * only 0->1 is counted. The controller is quite capable of counting
+        * both, but this done to preserve compatibility with the standard
+        * serial driver.
+        */
+       write_lock_irqsave(&pB->read_fifo_spinlock, flags);
+       cnow = pCh->icount;
+       write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
+       icount->cts = cnow.cts;
+       icount->dsr = cnow.dsr;
+       icount->rng = cnow.rng;
+       icount->dcd = cnow.dcd;
+       icount->rx = cnow.rx;
+       icount->tx = cnow.tx;
+       icount->frame = cnow.frame;
+       icount->overrun = cnow.overrun;
+       icount->parity = cnow.parity;
+       icount->brk = cnow.brk;
+       icount->buf_overrun = cnow.buf_overrun;
+       return 0;
+ }
  /******************************************************************************/
  /* Function:   GetSerialInfo()                                                */
  /* Parameters: Pointer to channel structure                                   */
@@@ -2899,7 -2911,7 +2913,7 @@@ ip2_ipl_ioctl (struct file *pFile, UIN
        printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg );
  #endif
  
 -      lock_kernel();
 +      mutex_lock(&ip2_mutex);
  
        switch ( iplminor ) {
        case 0:     // IPL device
                rc = -ENODEV;
                break;
        }
 -      unlock_kernel();
 +      mutex_unlock(&ip2_mutex);
        return rc;
  }
  
@@@ -2984,6 -2996,7 +2998,6 @@@ ip2_ipl_open( struct inode *pInode, str
  #ifdef IP2DEBUG_IPL
        printk (KERN_DEBUG "IP2IPL: open\n" );
  #endif
 -      cycle_kernel_lock();
        return 0;
  }
  
@@@ -70,6 -70,7 +70,6 @@@
  #include <linux/workqueue.h>
  #include <linux/hdlc.h>
  
 -#include <pcmcia/cs.h>
  #include <pcmcia/cistpl.h>
  #include <pcmcia/cisreg.h>
  #include <pcmcia/ds.h>
@@@ -549,6 -550,9 +549,6 @@@ static int mgslpc_probe(struct pcmcia_d
  
      /* Initialize the struct pcmcia_device structure */
  
 -    link->conf.Attributes = 0;
 -    link->conf.IntType = INT_MEMORY_AND_IO;
 -
      ret = mgslpc_config(link);
      if (ret)
            return ret;
  /* Card has been inserted.
   */
  
 -static int mgslpc_ioprobe(struct pcmcia_device *p_dev,
 -                        cistpl_cftable_entry_t *cfg,
 -                        cistpl_cftable_entry_t *dflt,
 -                        unsigned int vcc,
 -                        void *priv_data)
 +static int mgslpc_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
  {
 -      if (!cfg->io.nwin)
 -              return -ENODEV;
 -
 -      p_dev->resource[0]->start = cfg->io.win[0].base;
 -      p_dev->resource[0]->end = cfg->io.win[0].len;
 -      p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
 -      p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
 -
        return pcmcia_request_io(p_dev);
  }
  
@@@ -574,24 -590,32 +574,24 @@@ static int mgslpc_config(struct pcmcia_
      if (debug_level >= DEBUG_LEVEL_INFO)
            printk("mgslpc_config(0x%p)\n", link);
  
 +    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 +
      ret = pcmcia_loop_config(link, mgslpc_ioprobe, NULL);
      if (ret != 0)
            goto failed;
  
 -    link->conf.Attributes = CONF_ENABLE_IRQ;
 -    link->conf.IntType = INT_MEMORY_AND_IO;
 -    link->conf.ConfigIndex = 8;
 -    link->conf.Present = PRESENT_OPTION;
 +    link->config_index = 8;
 +    link->config_regs = PRESENT_OPTION;
  
      ret = pcmcia_request_irq(link, mgslpc_isr);
      if (ret)
            goto failed;
 -    ret = pcmcia_request_configuration(link, &link->conf);
 +    ret = pcmcia_enable_device(link);
      if (ret)
            goto failed;
  
      info->io_base = link->resource[0]->start;
      info->irq_level = link->irq;
 -
 -    dev_info(&link->dev, "index 0x%02x:",
 -          link->conf.ConfigIndex);
 -    if (link->conf.Attributes & CONF_ENABLE_IRQ)
 -          printk(", irq %d", link->irq);
 -    if (link->resource[0])
 -          printk(", io %pR", link->resource[0]);
 -    printk("\n");
      return 0;
  
  failed:
@@@ -2191,6 -2215,32 +2191,32 @@@ static int mgslpc_break(struct tty_stru
        return 0;
  }
  
+ static int mgslpc_get_icount(struct tty_struct *tty,
+                               struct serial_icounter_struct *icount)
+ {
+       MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
+       struct mgsl_icount cnow;        /* kernel counter temps */
+       unsigned long flags;
+       spin_lock_irqsave(&info->lock,flags);
+       cnow = info->icount;
+       spin_unlock_irqrestore(&info->lock,flags);
+       icount->cts = cnow.cts;
+       icount->dsr = cnow.dsr;
+       icount->rng = cnow.rng;
+       icount->dcd = cnow.dcd;
+       icount->rx = cnow.rx;
+       icount->tx = cnow.tx;
+       icount->frame = cnow.frame;
+       icount->overrun = cnow.overrun;
+       icount->parity = cnow.parity;
+       icount->brk = cnow.brk;
+       icount->buf_overrun = cnow.buf_overrun;
+       return 0;
+ }
  /* Service an IOCTL request
   *
   * Arguments:
@@@ -2206,11 -2256,7 +2232,7 @@@ static int mgslpc_ioctl(struct tty_stru
                        unsigned int cmd, unsigned long arg)
  {
        MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
-       int error;
-       struct mgsl_icount cnow;        /* kernel counter temps */
-       struct serial_icounter_struct __user *p_cuser;  /* user space */
        void __user *argp = (void __user *)arg;
-       unsigned long flags;
  
        if (debug_level >= DEBUG_LEVEL_INFO)
                printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
                return -ENODEV;
  
        if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-           (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+           (cmd != TIOCMIWAIT)) {
                if (tty->flags & (1 << TTY_IO_ERROR))
                    return -EIO;
        }
                return wait_events(info, argp);
        case TIOCMIWAIT:
                return modem_input_wait(info,(int)arg);
-       case TIOCGICOUNT:
-               spin_lock_irqsave(&info->lock,flags);
-               cnow = info->icount;
-               spin_unlock_irqrestore(&info->lock,flags);
-               p_cuser = argp;
-               PUT_USER(error,cnow.cts, &p_cuser->cts);
-               if (error) return error;
-               PUT_USER(error,cnow.dsr, &p_cuser->dsr);
-               if (error) return error;
-               PUT_USER(error,cnow.rng, &p_cuser->rng);
-               if (error) return error;
-               PUT_USER(error,cnow.dcd, &p_cuser->dcd);
-               if (error) return error;
-               PUT_USER(error,cnow.rx, &p_cuser->rx);
-               if (error) return error;
-               PUT_USER(error,cnow.tx, &p_cuser->tx);
-               if (error) return error;
-               PUT_USER(error,cnow.frame, &p_cuser->frame);
-               if (error) return error;
-               PUT_USER(error,cnow.overrun, &p_cuser->overrun);
-               if (error) return error;
-               PUT_USER(error,cnow.parity, &p_cuser->parity);
-               if (error) return error;
-               PUT_USER(error,cnow.brk, &p_cuser->brk);
-               if (error) return error;
-               PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
-               if (error) return error;
-               return 0;
        default:
                return -ENOIOCTLCMD;
        }
@@@ -2773,7 -2791,9 +2767,7 @@@ MODULE_DEVICE_TABLE(pcmcia, mgslpc_ids)
  
  static struct pcmcia_driver mgslpc_driver = {
        .owner          = THIS_MODULE,
 -      .drv            = {
 -              .name   = "synclink_cs",
 -      },
 +      .name           = "synclink_cs",
        .probe          = mgslpc_probe,
        .remove         = mgslpc_detach,
        .id_table       = mgslpc_ids,
@@@ -2809,6 -2829,8 +2803,6 @@@ static void synclink_cs_cleanup(void
  {
        int rc;
  
 -      printk("Unloading %s: version %s\n", driver_name, driver_version);
 -
        while(mgslpc_device_list)
                mgslpc_remove_device(mgslpc_device_list);
  
@@@ -2831,6 -2853,8 +2825,6 @@@ static int __init synclink_cs_init(void
            BREAKPOINT();
      }
  
 -    printk("%s %s\n", driver_name, driver_version);
 -
      if ((rc = pcmcia_register_driver(&mgslpc_driver)) < 0)
            return rc;
  
@@@ -4097,8 -4121,6 +4091,8 @@@ static int hdlcdev_ioctl(struct net_dev
        if (cmd != SIOCWANDEV)
                return hdlc_ioctl(dev, ifr, cmd);
  
 +      memset(&new_line, 0, size);
 +
        switch(ifr->ifr_settings.type) {
        case IF_GET_IFACE: /* return current sync_serial_settings */
  
diff --combined drivers/serial/Kconfig
@@@ -458,7 -458,6 +458,7 @@@ config SERIAL_SAMSUNG_UART
        int
        depends on ARM && PLAT_SAMSUNG
        default 2 if ARCH_S3C2400
 +      default 6 if ARCH_S5P6450
        default 4 if SERIAL_SAMSUNG_UARTS_4
        default 3
        help
@@@ -527,12 -526,12 +527,12 @@@ config SERIAL_S3C24A
          Serial port support for the Samsung S3C24A0 SoC
  
  config SERIAL_S3C6400
 -      tristate "Samsung S3C6400/S3C6410/S5P6440/S5PC100 Serial port support"
 -      depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5PC100)
 +      tristate "Samsung S3C6400/S3C6410/S5P6440/S5P6450/S5PC100 Serial port support"
 +      depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5P6450 || CPU_S5PC100)
        select SERIAL_SAMSUNG_UARTS_4
        default y
        help
 -        Serial port support for the Samsung S3C6400, S3C6410, S5P6440
 +        Serial port support for the Samsung S3C6400, S3C6410, S5P6440, S5P6450
          and S5PC100 SoCs
  
  config SERIAL_S5PV210
@@@ -718,13 -717,6 +718,6 @@@ config SERIAL_MRST_MAX311
          the Intel Moorestown platform. On other systems use the max3100
          driver.
  
- config MRST_MAX3110_IRQ
-       boolean "Enable GPIO IRQ for Max3110 over Moorestown"
-       default n
-       depends on SERIAL_MRST_MAX3110 && GPIO_LANGWELL
-       help
-         This has to be enabled after Moorestown GPIO driver is loaded
  config SERIAL_MFD_HSU
        tristate "Medfield High Speed UART support"
        depends on PCI
diff --combined drivers/serial/mfd.c
@@@ -172,6 -172,9 +172,9 @@@ static ssize_t port_show_regs(struct fi
        len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
                        "DIV: \t\t0x%08x\n", serial_in(up, UART_DIV));
  
+       if (len > HSU_REGS_BUFSIZE)
+               len = HSU_REGS_BUFSIZE;
        ret =  simple_read_from_buffer(user_buf, count, ppos, buf, len);
        kfree(buf);
        return ret;
@@@ -219,6 -222,9 +222,9 @@@ static ssize_t dma_show_regs(struct fil
        len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
                        "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3TSR));
  
+       if (len > HSU_REGS_BUFSIZE)
+               len = HSU_REGS_BUFSIZE;
        ret =  simple_read_from_buffer(user_buf, count, ppos, buf, len);
        kfree(buf);
        return ret;
@@@ -228,14 -234,12 +234,14 @@@ static const struct file_operations por
        .owner          = THIS_MODULE,
        .open           = hsu_show_regs_open,
        .read           = port_show_regs,
 +      .llseek         = default_llseek,
  };
  
  static const struct file_operations dma_regs_ops = {
        .owner          = THIS_MODULE,
        .open           = hsu_show_regs_open,
        .read           = dma_show_regs,
 +      .llseek         = default_llseek,
  };
  
  static int hsu_debugfs_init(struct hsu_port *hsu)
@@@ -925,39 -929,52 +931,52 @@@ serial_hsu_set_termios(struct uart_por
                cval |= UART_LCR_EPAR;
  
        /*
+        * The base clk is 50Mhz, and the baud rate come from:
+        *      baud = 50M * MUL / (DIV * PS * DLAB)
+        *
         * For those basic low baud rate we can get the direct
-        * scalar from 2746800, like 115200 = 2746800/24, for those
-        * higher baud rate, we have to handle them case by case,
-        * but DIV reg is never touched as its default value 0x3d09
+        * scalar from 2746800, like 115200 = 2746800/24. For those
+        * higher baud rate, we handle them case by case, mainly by
+        * adjusting the MUL/PS registers, and DIV register is kept
+        * as default value 0x3d09 to make things simple
         */
        baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
-       quot = uart_get_divisor(port, baud);
  
+       quot = 1;
        switch (baud) {
        case 3500000:
                mul = 0x3345;
                ps = 0xC;
-               quot = 1;
+               break;
+       case 3000000:
+               mul = 0x2EE0;
                break;
        case 2500000:
                mul = 0x2710;
-               ps = 0x10;
-               quot = 1;
                break;
-       case 18432000:
+       case 2000000:
+               mul = 0x1F40;
+               break;
+       case 1843200:
                mul = 0x2400;
-               ps = 0x10;
-               quot = 1;
                break;
        case 1500000:
-               mul = 0x1D4C;
-               ps = 0xc;
-               quot = 1;
+               mul = 0x1770;
+               break;
+       case 1000000:
+               mul = 0xFA0;
+               break;
+       case 500000:
+               mul = 0x7D0;
                break;
        default:
-               ;
+               /* Use uart_get_divisor to get quot for other baud rates */
+               quot = 0;
        }
  
+       if (!quot)
+               quot = uart_get_divisor(port, baud);
        if ((up->port.uartclk / quot) < (2400 * 16))
                fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_1B;
        else if ((up->port.uartclk / quot) < (230400 * 16))