diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 5b3e9769ca21..3fd1577a162f 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include #include @@ -83,8 +82,6 @@ struct sci_port { /* Function clock */ struct clk *fclk; - struct list_head node; - struct dma_chan *chan_tx; struct dma_chan *chan_rx; @@ -105,16 +102,14 @@ struct sci_port { struct timer_list rx_timer; unsigned int rx_timeout; #endif -}; -struct sh_sci_priv { - spinlock_t lock; - struct list_head ports; - struct notifier_block clk_nb; + struct notifier_block freq_transition; }; /* Function prototypes */ +static void sci_start_tx(struct uart_port *port); static void sci_stop_tx(struct uart_port *port); +static void sci_start_rx(struct uart_port *port); #define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS @@ -827,17 +822,17 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) static int sci_notifier(struct notifier_block *self, unsigned long phase, void *p) { - struct sh_sci_priv *priv = container_of(self, - struct sh_sci_priv, clk_nb); struct sci_port *sci_port; unsigned long flags; + sci_port = container_of(self, struct sci_port, freq_transition); + if ((phase == CPUFREQ_POSTCHANGE) || (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->iclk); - spin_unlock_irqrestore(&priv->lock, flags); + struct uart_port *port = &sci_port->port; + spin_lock_irqsave(&port->lock, flags); + port->uartclk = clk_get_rate(sci_port->iclk); + spin_unlock_irqrestore(&port->lock, flags); } return NOTIFY_OK; @@ -1025,9 +1020,6 @@ static void sci_dma_rx_complete(void *arg) schedule_work(&s->work_rx); } -static void sci_start_rx(struct uart_port *port); -static void sci_start_tx(struct uart_port *port); - static void sci_rx_dma_release(struct sci_port *s, bool enable_pio) { struct dma_chan *chan = s->chan_rx; @@ -1874,24 +1866,18 @@ static struct uart_driver sci_uart_driver = { .cons = SCI_CONSOLE, }; - static int sci_remove(struct platform_device *dev) { - struct sh_sci_priv *priv = platform_get_drvdata(dev); - struct sci_port *p; - unsigned long flags; + struct sci_port *port = platform_get_drvdata(dev); - cpufreq_unregister_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER); + cpufreq_unregister_notifier(&port->freq_transition, + CPUFREQ_TRANSITION_NOTIFIER); - spin_lock_irqsave(&priv->lock, flags); - 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); + uart_remove_one_port(&sci_uart_driver, &port->port); + + clk_put(port->iclk); + clk_put(port->fclk); - kfree(priv); return 0; } @@ -1900,8 +1886,6 @@ static int __devinit sci_probe_single(struct platform_device *dev, struct plat_sci_port *p, struct sci_port *sciport) { - struct sh_sci_priv *priv = platform_get_drvdata(dev); - unsigned long flags; int ret; /* Sanity check */ @@ -1918,17 +1902,7 @@ static int __devinit sci_probe_single(struct platform_device *dev, if (ret) return ret; - ret = uart_add_one_port(&sci_uart_driver, &sciport->port); - if (ret) - return ret; - - INIT_LIST_HEAD(&sciport->node); - - spin_lock_irqsave(&priv->lock, flags); - list_add(&sciport->node, &priv->ports); - spin_unlock_irqrestore(&priv->lock, flags); - - return 0; + return uart_add_one_port(&sci_uart_driver, &sciport->port); } /* @@ -1940,46 +1914,38 @@ static int __devinit sci_probe_single(struct platform_device *dev, static int __devinit sci_probe(struct platform_device *dev) { struct plat_sci_port *p = dev->dev.platform_data; - struct sh_sci_priv *priv; - int i, ret = -EINVAL; + struct sci_port *sp = &sci_ports[dev->id]; + int ret = -EINVAL; #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE if (is_early_platform_device(dev)) { - if (dev->id == -1) - return -ENOTSUPP; early_serial_console.index = dev->id; early_serial_console.data = &early_serial_port.port; + sci_init_single(NULL, &early_serial_port, dev->id, p); + serial_console_setup(&early_serial_console, early_serial_buf); + if (!strstr(early_serial_buf, "keep")) early_serial_console.flags |= CON_BOOT; + register_console(&early_serial_console); return 0; } #endif - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; + platform_set_drvdata(dev, sp); - INIT_LIST_HEAD(&priv->ports); - spin_lock_init(&priv->lock); - platform_set_drvdata(dev, priv); + ret = sci_probe_single(dev, dev->id, p, &sci_ports[dev->id]); + if (ret) + goto err_unreg; - priv->clk_nb.notifier_call = sci_notifier; - cpufreq_register_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER); + sp->freq_transition.notifier_call = sci_notifier; - if (dev->id != -1) { - ret = sci_probe_single(dev, dev->id, p, &sci_ports[dev->id]); - if (ret) - goto err_unreg; - } else { - for (i = 0; p && p->flags != 0; p++, i++) { - ret = sci_probe_single(dev, i, p, &sci_ports[i]); - if (ret) - goto err_unreg; - } - } + ret = cpufreq_register_notifier(&sp->freq_transition, + CPUFREQ_TRANSITION_NOTIFIER); + if (unlikely(ret < 0)) + goto err_unreg; #ifdef CONFIG_SH_STANDARD_BIOS sh_bios_gdb_detach(); @@ -1994,28 +1960,20 @@ static int __devinit sci_probe(struct platform_device *dev) static int sci_suspend(struct device *dev) { - struct sh_sci_priv *priv = dev_get_drvdata(dev); - struct sci_port *p; - unsigned long flags; + struct sci_port *sport = dev_get_drvdata(dev); - spin_lock_irqsave(&priv->lock, flags); - list_for_each_entry(p, &priv->ports, node) - uart_suspend_port(&sci_uart_driver, &p->port); - spin_unlock_irqrestore(&priv->lock, flags); + if (sport) + uart_suspend_port(&sci_uart_driver, &sport->port); return 0; } static int sci_resume(struct device *dev) { - struct sh_sci_priv *priv = dev_get_drvdata(dev); - struct sci_port *p; - unsigned long flags; + struct sci_port *sport = dev_get_drvdata(dev); - spin_lock_irqsave(&priv->lock, flags); - list_for_each_entry(p, &priv->ports, node) - uart_resume_port(&sci_uart_driver, &p->port); - spin_unlock_irqrestore(&priv->lock, flags); + if (sport) + uart_resume_port(&sci_uart_driver, &sport->port); return 0; }