Merge branches 'sh/intc-extension', 'sh/dmaengine', 'sh/serial-dma' and 'sh/clkfwk'
authorPaul Mundt <lethal@linux-sh.org>
Tue, 30 Mar 2010 02:26:43 +0000 (11:26 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Tue, 30 Mar 2010 02:26:43 +0000 (11:26 +0900)
Conflicts:
arch/sh/kernel/cpu/clock.c

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
1  2  3  4 
drivers/base/platform.c
drivers/serial/sh-sci.c
drivers/sh/intc.c

diff --combined drivers/base/platform.c
index 4b4b565c835f9c1c6da550fdb7d69ae27396fbf0,1ba9d617d241ba170842eba208b5dca64783960a,4b4b565c835f9c1c6da550fdb7d69ae27396fbf0,f2377f3d95e5b7e91fc3f5c97e19e6b61e551546..d10230adeb3650fe5ec38a51c2ef2434dff5da30
@@@@@ -362,8 -362,6 -362,8 -362,6 +362,8 @@@@@ EXPORT_SYMBOL_GPL(platform_device_unreg
     * enumeration tasks, they don't fully conform to the Linux driver model.
     * In particular, when such drivers are built as modules, they can't be
     * "hotplugged".
 + + *
 + + * Returns &struct platform_device pointer on success, or ERR_PTR() on error.
     */
    struct platform_device *platform_device_register_simple(const char *name,
                                                        int id,
@@@@@ -410,8 -408,6 -410,8 -408,6 +410,8 @@@@@ EXPORT_SYMBOL_GPL(platform_device_regis
     * allocated for the device allows drivers using such devices to be
     * unloaded without waiting for the last reference to the device to be
     * dropped.
 + + *
 + + * Returns &struct platform_device pointer on success, or ERR_PTR() on error.
     */
    struct platform_device *platform_device_register_data(
                struct device *parent,
@@@@@ -563,8 -559,6 -563,8 -559,6 +563,8 @@@@@ EXPORT_SYMBOL_GPL(platform_driver_probe
     *
     * Use this in legacy-style modules that probe hardware directly and
     * register a single platform device and corresponding platform driver.
 + + *
 + + * Returns &struct platform_device pointer on success, or ERR_PTR() on error.
     */
    struct platform_device * __init_or_module platform_create_bundle(
                        struct platform_driver *driver,
@@@@@ -1058,11 -1052,9 -1058,11 -1052,9 +1058,11 @@@@@ static __initdata LIST_HEAD(early_platf
    static __initdata LIST_HEAD(early_platform_device_list);
    
    /**
 - - * early_platform_driver_register
 + + * early_platform_driver_register - register early platform driver
     * @epdrv: early_platform driver structure
     * @buf: string passed from early_param()
 + + *
 + + * Helper function for early_platform_init() / early_platform_init_buffer()
     */
    int __init early_platform_driver_register(struct early_platform_driver *epdrv,
                                          char *buf)
    }
    
    /**
 - - * early_platform_add_devices - add a numbers of early platform devices
 + + * early_platform_add_devices - adds a number of early platform devices
     * @devs: array of early platform devices to add
     * @num: number of early platform devices in array
 + + *
 + + * Used by early architecture code to register early platform devices and
 + + * their platform data.
     */
    void __init early_platform_add_devices(struct platform_device **devs, int num)
    {
    }
    
    /**
 - - * early_platform_driver_register_all
 + + * early_platform_driver_register_all - register early platform drivers
     * @class_str: string to identify early platform driver class
 + + *
 + + * Used by architecture code to register all early platform drivers
 + + * for a certain class. If omitted then only early platform drivers
 + + * with matching kernel command line class parameters will be registered.
     */
    void __init early_platform_driver_register_all(char *class_str)
    {
    }
    
    /**
 - - * early_platform_match
 + + * early_platform_match - find early platform device matching driver
     * @epdrv: early platform driver structure
     * @id: id to match against
     */
@@@@@ -1184,7 -1169,7 -1184,7 -1169,7 +1184,7 @@@@@ early_platform_match(struct early_platf
    }
    
    /**
 - - * early_platform_left
 + + * early_platform_left - check if early platform driver has matching devices
     * @epdrv: early platform driver structure
     * @id: return true if id or above exists
     */
@@@@@ -1202,7 -1187,7 -1202,7 -1187,7 +1202,7 @@@@@ static  __init int early_platform_left(
    }
    
    /**
 - - * early_platform_driver_probe_id
 + + * early_platform_driver_probe_id - probe drivers matching class_str and id
     * @class_str: string to identify early platform driver class
     * @id: id to match against
     * @nr_probe: number of platform devices to successfully probe before exiting
@@@@@ -1254,6 -1239,6 -1254,6 -1239,26 +1254,26 @@@@@ static int __init early_platform_driver
                }
    
                if (match) {
+++                     /*
+++                      * Set up a sensible init_name to enable
+++                      * dev_name() and others to be used before the
+++                      * rest of the driver core is initialized.
+++                      */
+++                     if (!match->dev.init_name) {
+++                             if (match->id != -1)
+++                                     match->dev.init_name =
+++                                             kasprintf(GFP_KERNEL, "%s.%d",
+++                                                       match->name,
+++                                                       match->id);
+++                             else
+++                                     match->dev.init_name =
+++                                             kasprintf(GFP_KERNEL, "%s",
+++                                                       match->name);
+++ 
+++                             if (!match->dev.init_name)
+++                                     return -ENOMEM;
+++                     }
+++ 
                        if (epdrv->pdrv->probe(match))
                                pr_warning("%s: unable to probe %s early.\n",
                                           class_str, match->name);
    }
    
    /**
 - - * early_platform_driver_probe
 + + * early_platform_driver_probe - probe a class of registered drivers
     * @class_str: string to identify early platform driver class
     * @nr_probe: number of platform devices to successfully probe before exiting
     * @user_only: only probe user specified early platform devices
 + + *
 + + * Used by architecture code to probe registered early platform drivers
 + + * within a certain class. For probe to happen a registered early platform
 + + * device matching a registered early platform driver is needed.
     */
    int __init early_platform_driver_probe(char *class_str,
                                       int nr_probe,
diff --combined drivers/serial/sh-sci.c
index 309de6be8204bcc9fc880c6c9ae39884f460c8b3,980f39449ee5635ccb7b4f681151892e92a493b0,304a877d083d68624692a2781217e5a21d58eabb,054a8427c739c519472e60c25f8076d94728bab4..291bc08e2e8406f30f7fb635df49749cf35d2beb
    #include <linux/list.h>
    #include <linux/dmaengine.h>
    #include <linux/scatterlist.h>
 - -#include <linux/timer.h>
    
    #ifdef CONFIG_SUPERH
    #include <asm/sh_bios.h>
@@@@@ -82,16 -83,16 -82,16 -83,16 +82,16 @@@@@ struct sci_port 
    
        /* Interface clock */
        struct clk              *iclk;
---     /* Data clock */
---     struct clk              *dclk;
+++     /* Function clock */
+++     struct clk              *fclk;
    
        struct list_head        node;
        struct dma_chan                 *chan_tx;
        struct dma_chan                 *chan_rx;
    #ifdef CONFIG_SERIAL_SH_SCI_DMA
        struct device                   *dma_dev;
-- -    enum sh_dmae_slave_chan_id      slave_tx;
-- -    enum sh_dmae_slave_chan_id      slave_rx;
++ +    unsigned int                    slave_tx;
++ +    unsigned int                    slave_rx;
        struct dma_async_tx_descriptor  *desc_tx;
        struct dma_async_tx_descriptor  *desc_rx[2];
        dma_cookie_t                    cookie_tx;
        struct work_struct              work_tx;
        struct work_struct              work_rx;
        struct timer_list               rx_timer;
++ +    unsigned int                    rx_timeout;
    #endif
    };
    
@@@@@ -673,22 -674,22 -674,22 -674,22 +674,22 @@@@@ static irqreturn_t sci_rx_interrupt(in
        struct sci_port *s = to_sci_port(port);
    
        if (s->chan_rx) {
-- -            unsigned long tout;
                u16 scr = sci_in(port, SCSCR);
                u16 ssr = sci_in(port, SCxSR);
    
                /* Disable future Rx interrupts */
-- -            sci_out(port, SCSCR, scr & ~SCI_CTRL_FLAGS_RIE);
++ +            if (port->type == PORT_SCIFA) {
++ +                    disable_irq_nosync(irq);
++ +                    scr |= 0x4000;
++ +            } else {
++ +                    scr &= ~SCI_CTRL_FLAGS_RIE;
++ +            }
++ +            sci_out(port, SCSCR, scr);
                /* Clear current interrupt */
                sci_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port)));
-- -            /* Calculate delay for 1.5 DMA buffers */
-- -            tout = (port->timeout - HZ / 50) * s->buf_len_rx * 3 /
-- -                    port->fifosize / 2;
-- -            dev_dbg(port->dev, "Rx IRQ: setup timeout in %lu ms\n",
-- -                    tout * 1000 / HZ);
-- -            if (tout < 2)
-- -                    tout = 2;
-- -            mod_timer(&s->rx_timer, jiffies + tout);
++ +            dev_dbg(port->dev, "Rx IRQ %lu: setup t-out in %u jiffies\n",
++ +                    jiffies, s->rx_timeout);
++ +            mod_timer(&s->rx_timer, jiffies + s->rx_timeout);
    
                return IRQ_HANDLED;
        }
@@@@@ -779,6 -780,10 -780,10 -780,10 +780,6 @@@@@ static irqreturn_t sci_mpxed_interrupt(
        if ((ssr_status & SCxSR_BRK(port)) && err_enabled)
                ret = sci_br_interrupt(irq, ptr);
    
 ---    WARN_ONCE(ret == IRQ_NONE,
 ---              "%s: %d IRQ %d, status %x, control %x\n", __func__,
 ---              irq, port->line, ssr_status, scr_status);
 ---
        return ret;
    }
    
@@@@@ -798,7 -803,7 -803,7 -803,7 +799,7 @@@@@ static int sci_notifier(struct notifier
            (phase == CPUFREQ_RESUMECHANGE)) {
                spin_lock_irqsave(&priv->lock, flags);
                list_for_each_entry(sci_port, &priv->ports, node)
---                     sci_port->port.uartclk = clk_get_rate(sci_port->dclk);
+++                     sci_port->port.uartclk = clk_get_rate(sci_port->iclk);
                spin_unlock_irqrestore(&priv->lock, flags);
        }
    
@@@@@ -809,21 -814,21 -814,21 -814,17 +810,17 @@@@@ static void sci_clk_enable(struct uart_
    {
        struct sci_port *sci_port = to_sci_port(port);
    
---     clk_enable(sci_port->dclk);
---     sci_port->port.uartclk = clk_get_rate(sci_port->dclk);
--- 
---     if (sci_port->iclk)
---             clk_enable(sci_port->iclk);
+++     clk_enable(sci_port->iclk);
+++     sci_port->port.uartclk = clk_get_rate(sci_port->iclk);
+++     clk_enable(sci_port->fclk);
    }
    
    static void sci_clk_disable(struct uart_port *port)
    {
        struct sci_port *sci_port = to_sci_port(port);
    
---     if (sci_port->iclk)
---             clk_disable(sci_port->iclk);
--- 
---     clk_disable(sci_port->dclk);
+++     clk_disable(sci_port->fclk);
+++     clk_disable(sci_port->iclk);
    }
    
    static int sci_request_irq(struct sci_port *port)
@@@@@ -912,22 -917,22 -917,26 -913,22 +909,26 @@@@@ static void sci_dma_tx_complete(void *a
    
        spin_lock_irqsave(&port->lock, flags);
    
-- -    xmit->tail += s->sg_tx.length;
++ +    xmit->tail += sg_dma_len(&s->sg_tx);
        xmit->tail &= UART_XMIT_SIZE - 1;
    
-- -    port->icount.tx += s->sg_tx.length;
++ +    port->icount.tx += sg_dma_len(&s->sg_tx);
    
        async_tx_ack(s->desc_tx);
        s->cookie_tx = -EINVAL;
        s->desc_tx = NULL;
    
-- -    spin_unlock_irqrestore(&port->lock, flags);
-- -
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
                uart_write_wakeup(port);
    
-- -    if (uart_circ_chars_pending(xmit))
++ +    if (!uart_circ_empty(xmit)) {
                schedule_work(&s->work_tx);
++ +    } else if (port->type == PORT_SCIFA) {
++ +            u16 ctrl = sci_in(port, SCSCR);
++ +            sci_out(port, SCSCR, ctrl & ~SCI_CTRL_FLAGS_TIE);
++ +    }
++ +
++ +    spin_unlock_irqrestore(&port->lock, flags);
    }
    
    /* Locking: called with port lock held */
@@@@@ -971,13 -976,13 -980,13 -972,13 +972,13 @@@@@ static void sci_dma_rx_complete(void *a
        unsigned long flags;
        int count;
    
-- -    dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
++ +    dev_dbg(port->dev, "%s(%d) active #%d\n", __func__, port->line, s->active_rx);
    
        spin_lock_irqsave(&port->lock, flags);
    
        count = sci_dma_rx_push(s, tty, s->buf_len_rx);
    
-- -    mod_timer(&s->rx_timer, jiffies + msecs_to_jiffies(5));
++ +    mod_timer(&s->rx_timer, jiffies + s->rx_timeout);
    
        spin_unlock_irqrestore(&port->lock, flags);
    
@@@@@ -1049,6 -1054,6 -1058,8 -1050,6 +1050,8 @@@@@ static void sci_submit_rx(struct sci_po
                        sci_rx_dma_release(s, true);
                        return;
                }
++ +            dev_dbg(s->port.dev, "%s(): cookie %d to #%d\n", __func__,
++ +                    s->cookie_rx[i], i);
        }
    
        s->active_rx = s->cookie_rx[0];
@@@@@ -1106,10 -1111,10 -1117,10 -1107,10 +1109,10 @@@@@ static void work_fn_rx(struct work_stru
                return;
        }
    
-- -    dev_dbg(port->dev, "%s: cookie %d #%d\n", __func__,
-- -            s->cookie_rx[new], new);
-- -
        s->active_rx = s->cookie_rx[!new];
++ +
++ +    dev_dbg(port->dev, "%s: cookie %d #%d, new active #%d\n", __func__,
++ +            s->cookie_rx[new], new, s->active_rx);
    }
    
    static void work_fn_tx(struct work_struct *work)
         */
        spin_lock_irq(&port->lock);
        sg->offset = xmit->tail & (UART_XMIT_SIZE - 1);
-- -    sg->dma_address = (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) +
++ +    sg_dma_address(sg) = (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) +
                sg->offset;
-- -    sg->length = min((int)CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE),
++ +    sg_dma_len(sg) = min((int)CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE),
                CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE));
-- -    sg->dma_length = sg->length;
        spin_unlock_irq(&port->lock);
    
-- -    BUG_ON(!sg->length);
++ +    BUG_ON(!sg_dma_len(sg));
    
        desc = chan->device->device_prep_slave_sg(chan,
                        sg, s->sg_len_tx, DMA_TO_DEVICE,
    
    static void sci_start_tx(struct uart_port *port)
    {
++ +    struct sci_port *s = to_sci_port(port);
        unsigned short ctrl;
    
    #ifdef CONFIG_SERIAL_SH_SCI_DMA
-- -    struct sci_port *s = to_sci_port(port);
-- -
-- -    if (s->chan_tx) {
-- -            if (!uart_circ_empty(&s->port.state->xmit) && s->cookie_tx < 0)
-- -                    schedule_work(&s->work_tx);
-- -
-- -            return;
++ +    if (port->type == PORT_SCIFA) {
++ +            u16 new, scr = sci_in(port, SCSCR);
++ +            if (s->chan_tx)
++ +                    new = scr | 0x8000;
++ +            else
++ +                    new = scr & ~0x8000;
++ +            if (new != scr)
++ +                    sci_out(port, SCSCR, new);
        }
++ +    if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) &&
++ +        s->cookie_tx < 0)
++ +            schedule_work(&s->work_tx);
    #endif
-- -
-- -    /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
-- -    ctrl = sci_in(port, SCSCR);
-- -    ctrl |= SCI_CTRL_FLAGS_TIE;
-- -    sci_out(port, SCSCR, ctrl);
++ +    if (!s->chan_tx || port->type == PORT_SCIFA) {
++ +            /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
++ +            ctrl = sci_in(port, SCSCR);
++ +            sci_out(port, SCSCR, ctrl | SCI_CTRL_FLAGS_TIE);
++ +    }
    }
    
    static void sci_stop_tx(struct uart_port *port)
    
        /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */
        ctrl = sci_in(port, SCSCR);
++ +    if (port->type == PORT_SCIFA)
++ +            ctrl &= ~0x8000;
        ctrl &= ~SCI_CTRL_FLAGS_TIE;
        sci_out(port, SCSCR, ctrl);
    }
@@@@@ -1207,6 -1212,6 -1224,8 -1208,6 +1216,8 @@@@@ static void sci_start_rx(struct uart_po
    
        /* Set RIE (Receive Interrupt Enable) bit in SCSCR */
        ctrl |= sci_in(port, SCSCR);
++ +    if (port->type == PORT_SCIFA)
++ +            ctrl &= ~0x4000;
        sci_out(port, SCSCR, ctrl);
    }
    
@@@@@ -1216,6 -1221,6 -1235,8 -1217,6 +1227,8 @@@@@ static void sci_stop_rx(struct uart_por
    
        /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */
        ctrl = sci_in(port, SCSCR);
++ +    if (port->type == PORT_SCIFA)
++ +            ctrl &= ~0x4000;
        ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE);
        sci_out(port, SCSCR, ctrl);
    }
@@@@@ -1250,8 -1255,8 -1271,12 -1251,8 +1263,12 @@@@@ static void rx_timer_fn(unsigned long a
    {
        struct sci_port *s = (struct sci_port *)arg;
        struct uart_port *port = &s->port;
-- -
        u16 scr = sci_in(port, SCSCR);
++ +
++ +    if (port->type == PORT_SCIFA) {
++ +            scr &= ~0x4000;
++ +            enable_irq(s->irqs[1]);
++ +    }
        sci_out(port, SCSCR, scr | SCI_CTRL_FLAGS_RIE);
        dev_dbg(port->dev, "DMA Rx timed out\n");
        schedule_work(&s->work_rx);
@@@@@ -1338,8 -1343,8 -1363,7 -1339,8 +1355,7 @@@@@ static void sci_request_dma(struct uart
                        sg_init_table(sg, 1);
                        sg_set_page(sg, virt_to_page(buf[i]), s->buf_len_rx,
                                    (int)buf[i] & ~PAGE_MASK);
-- -                    sg->dma_address = dma[i];
-- -                    sg->dma_length = sg->length;
++ +                    sg_dma_address(sg) = dma[i];
                }
    
                INIT_WORK(&s->work_rx, work_fn_rx);
@@@@@ -1402,8 -1407,8 -1426,12 -1403,8 +1418,12 @@@@@ static void sci_shutdown(struct uart_po
    static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
                            struct ktermios *old)
    {
++ +#ifdef CONFIG_SERIAL_SH_SCI_DMA
++ +    struct sci_port *s = to_sci_port(port);
++ +#endif
        unsigned int status, baud, smr_val, max_baud;
        int t = -1;
++ +    u16 scfcr = 0;
    
        /*
         * earlyprintk comes here early on with port->uartclk set to zero.
        sci_out(port, SCSCR, 0x00);     /* TE=0, RE=0, CKE1=0 */
    
        if (port->type != PORT_SCI)
-- -            sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
++ +            sci_out(port, SCFCR, scfcr | SCFCR_RFRST | SCFCR_TFRST);
    
        smr_val = sci_in(port, SCSMR) & 3;
        if ((termios->c_cflag & CSIZE) == CS7)
        }
    
        sci_init_pins(port, termios->c_cflag);
-- -    sci_out(port, SCFCR, (termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0);
++ +    sci_out(port, SCFCR, scfcr | ((termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0));
    
        sci_out(port, SCSCR, SCSCR_INIT(port));
    
++ +#ifdef CONFIG_SERIAL_SH_SCI_DMA
++ +    /*
++ +     * Calculate delay for 1.5 DMA buffers: see
++ +     * drivers/serial/serial_core.c::uart_update_timeout(). With 10 bits
++ +     * (CS8), 250Hz, 115200 baud and 64 bytes FIFO, the above function
++ +     * calculates 1 jiffie for the data plus 5 jiffies for the "slop(e)."
++ +     * Then below we calculate 3 jiffies (12ms) for 1.5 DMA buffers (3 FIFO
++ +     * sizes), but it has been found out experimentally, that this is not
++ +     * enough: the driver too often needlessly runs on a DMA timeout. 20ms
++ +     * as a minimum seem to work perfectly.
++ +     */
++ +    if (s->chan_rx) {
++ +            s->rx_timeout = (port->timeout - HZ / 50) * s->buf_len_rx * 3 /
++ +                    port->fifosize / 2;
++ +            dev_dbg(port->dev,
++ +                    "DMA Rx t-out %ums, tty t-out %u jiffies\n",
++ +                    s->rx_timeout * 1000 / HZ, port->timeout);
++ +            if (s->rx_timeout < msecs_to_jiffies(20))
++ +                    s->rx_timeout = msecs_to_jiffies(20);
++ +    }
++ +#endif
++ +
        if ((termios->c_cflag & CREAD) != 0)
                sci_start_rx(port);
    }
@@@@@ -1552,10 -1557,10 -1602,10 -1553,10 +1594,10 @@@@@ static struct uart_ops sci_uart_ops = 
    #endif
    };
    
--- static void __devinit sci_init_single(struct platform_device *dev,
---                                   struct sci_port *sci_port,
---                                   unsigned int index,
---                                   struct plat_sci_port *p)
+++ static int __devinit sci_init_single(struct platform_device *dev,
+++                                  struct sci_port *sci_port,
+++                                  unsigned int index,
+++                                  struct plat_sci_port *p)
    {
        struct uart_port *port = &sci_port->port;
    
        }
    
        if (dev) {
---             sci_port->iclk = p->clk ? clk_get(&dev->dev, p->clk) : NULL;
---             sci_port->dclk = clk_get(&dev->dev, "peripheral_clk");
+++             sci_port->iclk = clk_get(&dev->dev, "sci_ick");
+++             if (IS_ERR(sci_port->iclk)) {
+++                     sci_port->iclk = clk_get(&dev->dev, "peripheral_clk");
+++                     if (IS_ERR(sci_port->iclk)) {
+++                             dev_err(&dev->dev, "can't get iclk\n");
+++                             return PTR_ERR(sci_port->iclk);
+++                     }
+++             }
+++ 
+++             /*
+++              * The function clock is optional, ignore it if we can't
+++              * find it.
+++              */
+++             sci_port->fclk = clk_get(&dev->dev, "sci_fck");
+++             if (IS_ERR(sci_port->fclk))
+++                     sci_port->fclk = NULL;
+++ 
                sci_port->enable = sci_clk_enable;
                sci_port->disable = sci_clk_disable;
                port->dev = &dev->dev;
    #endif
    
        memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs));
+++     return 0;
    }
    
    #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
@@@@@ -1753,8 -1758,8 -1803,8 -1770,11 +1811,11 @@@@@ static int sci_remove(struct platform_d
        cpufreq_unregister_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER);
    
        spin_lock_irqsave(&priv->lock, flags);
---     list_for_each_entry(p, &priv->ports, node)
+++     list_for_each_entry(p, &priv->ports, node) {
                uart_remove_one_port(&sci_uart_driver, &p->port);
+++             clk_put(p->iclk);
+++             clk_put(p->fclk);
+++     }
        spin_unlock_irqrestore(&priv->lock, flags);
    
        kfree(priv);
@@@@@ -1780,7 -1785,7 -1830,7 -1800,9 +1841,9 @@@@@ static int __devinit sci_probe_single(s
                return 0;
        }
    
---     sci_init_single(dev, sciport, index, p);
+++     ret = sci_init_single(dev, sciport, index, p);
+++     if (ret)
+++             return ret;
    
        ret = uart_add_one_port(&sci_uart_driver, &sciport->port);
        if (ret)
diff --combined drivers/sh/intc.c
index a3d8677af6a52dd1db005fcb13d3fc12ede75c16,a700dfec8dc36d3d980732856605a5707928a9df,a3d8677af6a52dd1db005fcb13d3fc12ede75c16,b8983fed76f51f073aabef451d084895806b78b3..f43850527645dedc863eeba5e0fccf4b1e6cedc2
@@@@@ -2,7 -2,7 -2,7 -2,7 +2,7 @@@@@
     * Shared interrupt handling code for IPR and INTC2 types of IRQs.
     *
     * Copyright (C) 2007, 2008 Magnus Damm
 -   * Copyright (C) 2009 Paul Mundt
 +   * Copyright (C) 2009, 2010 Paul Mundt
     *
     * Based on intc2.c and ipr.c
     *
    #include <linux/list.h>
    #include <linux/topology.h>
    #include <linux/bitmap.h>
 +  #include <linux/cpumask.h>
    
    #define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \
        ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \
@@@@@ -44,6 -43,12 -44,6 -44,6 +44,12 @@@@@ struct intc_handle_int 
        unsigned long handle;
    };
    
+ ++struct intc_window {
+ ++    phys_addr_t phys;
+ ++    void __iomem *virt;
+ ++    unsigned long size;
+ ++};
+ ++
    struct intc_desc_int {
        struct list_head list;
        struct sys_device sysdev;
        unsigned int nr_prio;
        struct intc_handle_int *sense;
        unsigned int nr_sense;
+ ++    struct intc_window *window;
+ ++    unsigned int nr_windows;
        struct irq_chip chip;
    };
    
@@@@@ -235,10 -242,6 -235,10 -235,10 +243,10 @@@@@ static inline void _intc_enable(unsigne
        unsigned int cpu;
    
        for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
 +  #ifdef CONFIG_SMP
 +              if (!cpumask_test_cpu(cpu, irq_to_desc(irq)->affinity))
 +                      continue;
 +  #endif
                addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
                intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\
                                                    [_INTC_FN(handle)], irq);
@@@@@ -258,10 -261,6 -258,10 -258,10 +266,10 @@@@@ static void intc_disable(unsigned int i
        unsigned int cpu;
    
        for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) {
 +  #ifdef CONFIG_SMP
 +              if (!cpumask_test_cpu(cpu, irq_to_desc(irq)->affinity))
 +                      continue;
 +  #endif
                addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu);
                intc_disable_fns[_INTC_MODE(handle)](addr, handle,intc_reg_fns\
                                                     [_INTC_FN(handle)], irq);
@@@@@ -310,23 -309,6 -310,23 -310,23 +318,23 @@@@@ static int intc_set_wake(unsigned int i
        return 0; /* allow wakeup, but setup hardware in intc_suspend() */
    }
    
 +  #ifdef CONFIG_SMP
 +  /*
 +   * This is held with the irq desc lock held, so we don't require any
 +   * additional locking here at the intc desc level. The affinity mask is
 +   * later tested in the enable/disable paths.
 +   */
 +  static int intc_set_affinity(unsigned int irq, const struct cpumask *cpumask)
 +  {
 +      if (!cpumask_intersects(cpumask, cpu_online_mask))
 +              return -1;
 +  
 +      cpumask_copy(irq_to_desc(irq)->affinity, cpumask);
 +  
 +      return 0;
 +  }
 +  #endif
 +  
    static void intc_mask_ack(unsigned int irq)
    {
        struct intc_desc_int *d = get_intc_desc(irq);
@@@@@ -446,11 -428,39 -446,11 -446,11 +454,39 @@@@@ static int intc_set_sense(unsigned int 
        return 0;
    }
    
+ ++static unsigned long intc_phys_to_virt(struct intc_desc_int *d,
+ ++                                   unsigned long address)
+ ++{
+ ++    struct intc_window *window;
+ ++    int k;
+ ++
+ ++    /* scan through physical windows and convert address */
+ ++    for (k = 0; k < d->nr_windows; k++) {
+ ++            window = d->window + k;
+ ++
+ ++            if (address < window->phys)
+ ++                    continue;
+ ++
+ ++            if (address >= (window->phys + window->size))
+ ++                    continue;
+ ++
+ ++            address -= window->phys;
+ ++            address += (unsigned long)window->virt;
+ ++
+ ++            return address;
+ ++    }
+ ++
+ ++    /* no windows defined, register must be 1:1 mapped virt:phys */
+ ++    return address;
+ ++}
+ ++
    static unsigned int __init intc_get_reg(struct intc_desc_int *d,
- --                             unsigned long address)
+ ++                                    unsigned long address)
    {
        unsigned int k;
    
+ ++    address = intc_phys_to_virt(d, address);
+ ++
        for (k = 0; k < d->nr_reg; k++) {
                if (d->reg[k] == address)
                        return k;
@@@@@ -788,10 -798,10 -788,10 -788,6 +824,10 @@@@@ static void __init intc_register_irq(st
    
        if (desc->hw.ack_regs)
                ack_handle[irq] = intc_ack_data(desc, d, enum_id);
   +
   +#ifdef CONFIG_ARM
   +    set_irq_flags(irq, IRQF_VALID); /* Enable IRQ on ARM systems */
   +#endif
    }
    
    static unsigned int __init save_reg(struct intc_desc_int *d,
                                    unsigned int smp)
    {
        if (value) {
+ ++            value = intc_phys_to_virt(d, value);
+ ++
                d->reg[cnt] = value;
    #ifdef CONFIG_SMP
                d->smp[cnt] = smp;
@@@@@ -815,25 -827,52 -815,25 -811,25 +853,52 @@@@@ static void intc_redirect_irq(unsigned 
        generic_handle_irq((unsigned int)get_irq_data(irq));
    }
    
- --void __init register_intc_controller(struct intc_desc *desc)
+ ++int __init register_intc_controller(struct intc_desc *desc)
    {
        unsigned int i, k, smp;
        struct intc_hw_desc *hw = &desc->hw;
        struct intc_desc_int *d;
+ ++    struct resource *res;
    
        d = kzalloc(sizeof(*d), GFP_NOWAIT);
+ ++    if (!d)
+ ++            goto err0;
    
        INIT_LIST_HEAD(&d->list);
        list_add(&d->list, &intc_list);
    
+ ++    if (desc->num_resources) {
+ ++            d->nr_windows = desc->num_resources;
+ ++            d->window = kzalloc(d->nr_windows * sizeof(*d->window),
+ ++                                GFP_NOWAIT);
+ ++            if (!d->window)
+ ++                    goto err1;
+ ++
+ ++            for (k = 0; k < d->nr_windows; k++) {
+ ++                    res = desc->resource + k;
+ ++                    WARN_ON(resource_type(res) != IORESOURCE_MEM);
+ ++                    d->window[k].phys = res->start;
+ ++                    d->window[k].size = resource_size(res);
+ ++                    d->window[k].virt = ioremap_nocache(res->start,
+ ++                                                     resource_size(res));
+ ++                    if (!d->window[k].virt)
+ ++                            goto err2;
+ ++            }
+ ++    }
+ ++
        d->nr_reg = hw->mask_regs ? hw->nr_mask_regs * 2 : 0;
        d->nr_reg += hw->prio_regs ? hw->nr_prio_regs * 2 : 0;
        d->nr_reg += hw->sense_regs ? hw->nr_sense_regs : 0;
        d->nr_reg += hw->ack_regs ? hw->nr_ack_regs : 0;
    
        d->reg = kzalloc(d->nr_reg * sizeof(*d->reg), GFP_NOWAIT);
+ ++    if (!d->reg)
+ ++            goto err2;
+ ++
    #ifdef CONFIG_SMP
        d->smp = kzalloc(d->nr_reg * sizeof(*d->smp), GFP_NOWAIT);
+ ++    if (!d->smp)
+ ++            goto err3;
    #endif
        k = 0;
    
        if (hw->prio_regs) {
                d->prio = kzalloc(hw->nr_vectors * sizeof(*d->prio),
                                  GFP_NOWAIT);
+ ++            if (!d->prio)
+ ++                    goto err4;
    
                for (i = 0; i < hw->nr_prio_regs; i++) {
                        smp = IS_SMP(hw->prio_regs[i]);
        if (hw->sense_regs) {
                d->sense = kzalloc(hw->nr_vectors * sizeof(*d->sense),
                                   GFP_NOWAIT);
+ ++            if (!d->sense)
+ ++                    goto err5;
    
                for (i = 0; i < hw->nr_sense_regs; i++)
                        k += save_reg(d, k, hw->sense_regs[i].reg, 0);
        d->chip.shutdown = intc_disable;
        d->chip.set_type = intc_set_sense;
        d->chip.set_wake = intc_set_wake;
 +  #ifdef CONFIG_SMP
 +      d->chip.set_affinity = intc_set_affinity;
 +  #endif
    
        if (hw->ack_regs) {
                for (i = 0; i < hw->nr_ack_regs; i++)
        /* enable bits matching force_enable after registering irqs */
        if (desc->force_enable)
                intc_enable_disable_enum(desc, d, desc->force_enable, 1);
+ ++
+ ++    return 0;
+ ++err5:
+ ++    kfree(d->prio);
+ ++err4:
+ ++#ifdef CONFIG_SMP
+ ++    kfree(d->smp);
+ ++err3:
+ ++#endif
+ ++    kfree(d->reg);
+ ++err2:
+ ++    for (k = 0; k < d->nr_windows; k++)
+ ++            if (d->window[k].virt)
+ ++                    iounmap(d->window[k].virt);
+ ++
+ ++    kfree(d->window);
+ ++err1:
+ ++    kfree(d);
+ ++err0:
+ ++    pr_err("unable to allocate INTC memory\n");
+ ++
+ ++    return -ENOMEM;
    }
    
    static int intc_suspend(struct sys_device *dev, pm_message_t state)
@@@@@ -1057,12 -1119,12 -1057,12 -1053,8 +1148,12 @@@@@ unsigned int create_irq_nr(unsigned in
    out_unlock:
        spin_unlock_irqrestore(&vector_lock, flags);
    
   -    if (irq > 0)
   +    if (irq > 0) {
                dynamic_irq_init(irq);
   +#ifdef CONFIG_ARM
   +            set_irq_flags(irq, IRQF_VALID); /* Enable IRQ on ARM systems */
   +#endif
   +    }
    
        return irq;
    }