diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/base/platform.c | 20 | ||||
-rw-r--r-- | drivers/clocksource/sh_cmt.c | 42 | ||||
-rw-r--r-- | drivers/clocksource/sh_mtu2.c | 34 | ||||
-rw-r--r-- | drivers/clocksource/sh_tmu.c | 38 | ||||
-rw-r--r-- | drivers/dma/shdma.c | 13 | ||||
-rw-r--r-- | drivers/dma/shdma.h | 4 | ||||
-rw-r--r-- | drivers/serial/sh-sci.c | 189 | ||||
-rw-r--r-- | drivers/sh/intc.c | 95 |
8 files changed, 305 insertions, 130 deletions
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 4b4b565c835f..d10230adeb36 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -1254,6 +1254,26 @@ static int __init early_platform_driver_probe_id(char *class_str, } 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); diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 578595c4425d..c5f66171a713 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -149,13 +149,12 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) { - struct sh_timer_config *cfg = p->pdev->dev.platform_data; int ret; /* enable clock */ ret = clk_enable(p->clk); if (ret) { - pr_err("sh_cmt: cannot enable clock \"%s\"\n", cfg->clk); + dev_err(&p->pdev->dev, "cannot enable clock\n"); return ret; } @@ -278,7 +277,7 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p, delay = 1; if (!delay) - pr_warning("sh_cmt: too long delay\n"); + dev_warn(&p->pdev->dev, "too long delay\n"); } while (delay); } @@ -288,7 +287,7 @@ static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta) unsigned long flags; if (delta > p->max_match_value) - pr_warning("sh_cmt: delta out of range\n"); + dev_warn(&p->pdev->dev, "delta out of range\n"); spin_lock_irqsave(&p->lock, flags); p->next_match_value = delta; @@ -450,7 +449,7 @@ static int sh_cmt_register_clocksource(struct sh_cmt_priv *p, cs->resume = sh_cmt_clocksource_resume; cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8); cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; - pr_info("sh_cmt: %s used as clock source\n", cs->name); + dev_info(&p->pdev->dev, "used as clock source\n"); clocksource_register(cs); return 0; } @@ -496,13 +495,11 @@ static void sh_cmt_clock_event_mode(enum clock_event_mode mode, switch (mode) { case CLOCK_EVT_MODE_PERIODIC: - pr_info("sh_cmt: %s used for periodic clock events\n", - ced->name); + dev_info(&p->pdev->dev, "used for periodic clock events\n"); sh_cmt_clock_event_start(p, 1); break; case CLOCK_EVT_MODE_ONESHOT: - pr_info("sh_cmt: %s used for oneshot clock events\n", - ced->name); + dev_info(&p->pdev->dev, "used for oneshot clock events\n"); sh_cmt_clock_event_start(p, 0); break; case CLOCK_EVT_MODE_SHUTDOWN: @@ -543,7 +540,7 @@ static void sh_cmt_register_clockevent(struct sh_cmt_priv *p, ced->set_next_event = sh_cmt_clock_event_next; ced->set_mode = sh_cmt_clock_event_mode; - pr_info("sh_cmt: %s used for clock events\n", ced->name); + dev_info(&p->pdev->dev, "used for clock events\n"); clockevents_register_device(ced); } @@ -600,22 +597,26 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) /* map memory, let mapbase point to our channel */ p->mapbase = ioremap_nocache(res->start, resource_size(res)); if (p->mapbase == NULL) { - pr_err("sh_cmt: failed to remap I/O memory\n"); + dev_err(&p->pdev->dev, "failed to remap I/O memory\n"); goto err0; } /* request irq using setup_irq() (too early for request_irq()) */ - p->irqaction.name = cfg->name; + p->irqaction.name = dev_name(&p->pdev->dev); p->irqaction.handler = sh_cmt_interrupt; p->irqaction.dev_id = p; p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; /* get hold of clock */ - p->clk = clk_get(&p->pdev->dev, cfg->clk); + p->clk = clk_get(&p->pdev->dev, "cmt_fck"); if (IS_ERR(p->clk)) { - pr_err("sh_cmt: cannot get clock \"%s\"\n", cfg->clk); - ret = PTR_ERR(p->clk); - goto err1; + dev_warn(&p->pdev->dev, "using deprecated clock lookup\n"); + p->clk = clk_get(&p->pdev->dev, cfg->clk); + if (IS_ERR(p->clk)) { + dev_err(&p->pdev->dev, "cannot get clock\n"); + ret = PTR_ERR(p->clk); + goto err1; + } } if (resource_size(res) == 6) { @@ -628,17 +629,17 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) p->clear_bits = ~0xc000; } - ret = sh_cmt_register(p, cfg->name, + ret = sh_cmt_register(p, (char *)dev_name(&p->pdev->dev), cfg->clockevent_rating, cfg->clocksource_rating); if (ret) { - pr_err("sh_cmt: registration failed\n"); + dev_err(&p->pdev->dev, "registration failed\n"); goto err1; } ret = setup_irq(irq, &p->irqaction); if (ret) { - pr_err("sh_cmt: failed to request irq %d\n", irq); + dev_err(&p->pdev->dev, "failed to request irq %d\n", irq); goto err1; } @@ -653,11 +654,10 @@ err0: static int __devinit sh_cmt_probe(struct platform_device *pdev) { struct sh_cmt_priv *p = platform_get_drvdata(pdev); - struct sh_timer_config *cfg = pdev->dev.platform_data; int ret; if (p) { - pr_info("sh_cmt: %s kept as earlytimer\n", cfg->name); + dev_info(&pdev->dev, "kept as earlytimer\n"); return 0; } diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index 4c8a759e60cd..b11882e0f1bd 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c @@ -118,13 +118,12 @@ static void sh_mtu2_start_stop_ch(struct sh_mtu2_priv *p, int start) static int sh_mtu2_enable(struct sh_mtu2_priv *p) { - struct sh_timer_config *cfg = p->pdev->dev.platform_data; int ret; /* enable clock */ ret = clk_enable(p->clk); if (ret) { - pr_err("sh_mtu2: cannot enable clock \"%s\"\n", cfg->clk); + dev_err(&p->pdev->dev, "cannot enable clock\n"); return ret; } @@ -193,8 +192,7 @@ static void sh_mtu2_clock_event_mode(enum clock_event_mode mode, switch (mode) { case CLOCK_EVT_MODE_PERIODIC: - pr_info("sh_mtu2: %s used for periodic clock events\n", - ced->name); + dev_info(&p->pdev->dev, "used for periodic clock events\n"); sh_mtu2_enable(p); break; case CLOCK_EVT_MODE_UNUSED: @@ -221,13 +219,13 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_priv *p, ced->cpumask = cpumask_of(0); ced->set_mode = sh_mtu2_clock_event_mode; - pr_info("sh_mtu2: %s used for clock events\n", ced->name); + dev_info(&p->pdev->dev, "used for clock events\n"); clockevents_register_device(ced); ret = setup_irq(p->irqaction.irq, &p->irqaction); if (ret) { - pr_err("sh_mtu2: failed to request irq %d\n", - p->irqaction.irq); + dev_err(&p->pdev->dev, "failed to request irq %d\n", + p->irqaction.irq); return; } } @@ -273,26 +271,31 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev) /* map memory, let mapbase point to our channel */ p->mapbase = ioremap_nocache(res->start, resource_size(res)); if (p->mapbase == NULL) { - pr_err("sh_mtu2: failed to remap I/O memory\n"); + dev_err(&p->pdev->dev, "failed to remap I/O memory\n"); goto err0; } /* setup data for setup_irq() (too early for request_irq()) */ - p->irqaction.name = cfg->name; + p->irqaction.name = dev_name(&p->pdev->dev); p->irqaction.handler = sh_mtu2_interrupt; p->irqaction.dev_id = p; p->irqaction.irq = irq; p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; /* get hold of clock */ - p->clk = clk_get(&p->pdev->dev, cfg->clk); + p->clk = clk_get(&p->pdev->dev, "mtu2_fck"); if (IS_ERR(p->clk)) { - pr_err("sh_mtu2: cannot get clock \"%s\"\n", cfg->clk); - ret = PTR_ERR(p->clk); - goto err1; + dev_warn(&p->pdev->dev, "using deprecated clock lookup\n"); + p->clk = clk_get(&p->pdev->dev, cfg->clk); + if (IS_ERR(p->clk)) { + dev_err(&p->pdev->dev, "cannot get clock\n"); + ret = PTR_ERR(p->clk); + goto err1; + } } - return sh_mtu2_register(p, cfg->name, cfg->clockevent_rating); + return sh_mtu2_register(p, (char *)dev_name(&p->pdev->dev), + cfg->clockevent_rating); err1: iounmap(p->mapbase); err0: @@ -302,11 +305,10 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev) static int __devinit sh_mtu2_probe(struct platform_device *pdev) { struct sh_mtu2_priv *p = platform_get_drvdata(pdev); - struct sh_timer_config *cfg = pdev->dev.platform_data; int ret; if (p) { - pr_info("sh_mtu2: %s kept as earlytimer\n", cfg->name); + dev_info(&pdev->dev, "kept as earlytimer\n"); return 0; } diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index 961f5b5ef6a3..6b62283c1aba 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c @@ -106,13 +106,12 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start) static int sh_tmu_enable(struct sh_tmu_priv *p) { - struct sh_timer_config *cfg = p->pdev->dev.platform_data; int ret; /* enable clock */ ret = clk_enable(p->clk); if (ret) { - pr_err("sh_tmu: cannot enable clock \"%s\"\n", cfg->clk); + dev_err(&p->pdev->dev, "cannot enable clock\n"); return ret; } @@ -228,7 +227,7 @@ static int sh_tmu_register_clocksource(struct sh_tmu_priv *p, cs->disable = sh_tmu_clocksource_disable; cs->mask = CLOCKSOURCE_MASK(32); cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; - pr_info("sh_tmu: %s used as clock source\n", cs->name); + dev_info(&p->pdev->dev, "used as clock source\n"); clocksource_register(cs); return 0; } @@ -276,13 +275,11 @@ static void sh_tmu_clock_event_mode(enum clock_event_mode mode, switch (mode) { case CLOCK_EVT_MODE_PERIODIC: - pr_info("sh_tmu: %s used for periodic clock events\n", - ced->name); + dev_info(&p->pdev->dev, "used for periodic clock events\n"); sh_tmu_clock_event_start(p, 1); break; case CLOCK_EVT_MODE_ONESHOT: - pr_info("sh_tmu: %s used for oneshot clock events\n", - ced->name); + dev_info(&p->pdev->dev, "used for oneshot clock events\n"); sh_tmu_clock_event_start(p, 0); break; case CLOCK_EVT_MODE_UNUSED: @@ -323,13 +320,13 @@ static void sh_tmu_register_clockevent(struct sh_tmu_priv *p, ced->set_next_event = sh_tmu_clock_event_next; ced->set_mode = sh_tmu_clock_event_mode; - pr_info("sh_tmu: %s used for clock events\n", ced->name); + dev_info(&p->pdev->dev, "used for clock events\n"); clockevents_register_device(ced); ret = setup_irq(p->irqaction.irq, &p->irqaction); if (ret) { - pr_err("sh_tmu: failed to request irq %d\n", - p->irqaction.irq); + dev_err(&p->pdev->dev, "failed to request irq %d\n", + p->irqaction.irq); return; } } @@ -378,26 +375,30 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev) /* map memory, let mapbase point to our channel */ p->mapbase = ioremap_nocache(res->start, resource_size(res)); if (p->mapbase == NULL) { - pr_err("sh_tmu: failed to remap I/O memory\n"); + dev_err(&p->pdev->dev, "failed to remap I/O memory\n"); goto err0; } /* setup data for setup_irq() (too early for request_irq()) */ - p->irqaction.name = cfg->name; + p->irqaction.name = dev_name(&p->pdev->dev); p->irqaction.handler = sh_tmu_interrupt; p->irqaction.dev_id = p; p->irqaction.irq = irq; p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; /* get hold of clock */ - p->clk = clk_get(&p->pdev->dev, cfg->clk); + p->clk = clk_get(&p->pdev->dev, "tmu_fck"); if (IS_ERR(p->clk)) { - pr_err("sh_tmu: cannot get clock \"%s\"\n", cfg->clk); - ret = PTR_ERR(p->clk); - goto err1; + dev_warn(&p->pdev->dev, "using deprecated clock lookup\n"); + p->clk = clk_get(&p->pdev->dev, cfg->clk); + if (IS_ERR(p->clk)) { + dev_err(&p->pdev->dev, "cannot get clock\n"); + ret = PTR_ERR(p->clk); + goto err1; + } } - return sh_tmu_register(p, cfg->name, + return sh_tmu_register(p, (char *)dev_name(&p->pdev->dev), cfg->clockevent_rating, cfg->clocksource_rating); err1: @@ -409,11 +410,10 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev) static int __devinit sh_tmu_probe(struct platform_device *pdev) { struct sh_tmu_priv *p = platform_get_drvdata(pdev); - struct sh_timer_config *cfg = pdev->dev.platform_data; int ret; if (p) { - pr_info("sh_tmu: %s kept as earlytimer\n", cfg->name); + dev_info(&pdev->dev, "kept as earlytimer\n"); return 0; } diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 5d17e09cb625..7a18b580f626 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -25,8 +25,7 @@ #include <linux/dma-mapping.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> - -#include <asm/dmaengine.h> +#include <linux/sh_dma.h> #include "shdma.h" @@ -44,7 +43,7 @@ enum sh_dmae_desc_status { #define LOG2_DEFAULT_XFER_SIZE 2 /* A bitmask with bits enough for enum sh_dmae_slave_chan_id */ -static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SHDMA_SLAVE_NUMBER)]; +static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SH_DMA_SLAVE_NUMBER)]; static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all); @@ -266,7 +265,7 @@ static struct sh_desc *sh_dmae_get_desc(struct sh_dmae_chan *sh_chan) } static struct sh_dmae_slave_config *sh_dmae_find_slave( - struct sh_dmae_chan *sh_chan, enum sh_dmae_slave_chan_id slave_id) + struct sh_dmae_chan *sh_chan, struct sh_dmae_slave *param) { struct dma_device *dma_dev = sh_chan->common.device; struct sh_dmae_device *shdev = container_of(dma_dev, @@ -274,11 +273,11 @@ static struct sh_dmae_slave_config *sh_dmae_find_slave( struct sh_dmae_pdata *pdata = shdev->pdata; int i; - if ((unsigned)slave_id >= SHDMA_SLAVE_NUMBER) + if (param->slave_id >= SH_DMA_SLAVE_NUMBER) return NULL; for (i = 0; i < pdata->slave_num; i++) - if (pdata->slave[i].slave_id == slave_id) + if (pdata->slave[i].slave_id == param->slave_id) return pdata->slave + i; return NULL; @@ -299,7 +298,7 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan) if (param) { struct sh_dmae_slave_config *cfg; - cfg = sh_dmae_find_slave(sh_chan, param->slave_id); + cfg = sh_dmae_find_slave(sh_chan, param); if (!cfg) return -EINVAL; diff --git a/drivers/dma/shdma.h b/drivers/dma/shdma.h index 153609a1e96c..4021275a0a43 100644 --- a/drivers/dma/shdma.h +++ b/drivers/dma/shdma.h @@ -17,8 +17,8 @@ #include <linux/interrupt.h> #include <linux/list.h> -#include <asm/dmaengine.h> - +#define SH_DMAC_MAX_CHANNELS 6 +#define SH_DMA_SLAVE_NUMBER 256 #define SH_DMA_TCR_MAX 0x00FFFFFF /* 16MB */ struct device; diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 309de6be8204..291bc08e2e84 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -82,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; @@ -106,6 +106,7 @@ struct sci_port { struct work_struct work_tx; struct work_struct work_rx; struct timer_list rx_timer; + unsigned int rx_timeout; #endif }; @@ -673,22 +674,22 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) 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; } @@ -798,7 +799,7 @@ static int sci_notifier(struct notifier_block *self, (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 +810,17 @@ static void sci_clk_enable(struct uart_port *port) { 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 +909,26 @@ static void sci_dma_tx_complete(void *arg) 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 +972,13 @@ static void sci_dma_rx_complete(void *arg) 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 +1050,8 @@ static void sci_submit_rx(struct sci_port *s) 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 +1109,10 @@ static void work_fn_rx(struct work_struct *work) 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) @@ -1130,14 +1133,13 @@ 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, @@ -1172,23 +1174,28 @@ static void work_fn_tx(struct work_struct *work) 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) @@ -1197,6 +1204,8 @@ 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 +1216,8 @@ static void sci_start_rx(struct uart_port *port) /* 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 +1227,8 @@ static void sci_stop_rx(struct uart_port *port) /* 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 +1263,12 @@ static void rx_timer_fn(unsigned long arg) { 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 +1355,7 @@ static void sci_request_dma(struct uart_port *port) 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 +1418,12 @@ static void sci_shutdown(struct uart_port *port) 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. @@ -1426,7 +1446,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, 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) @@ -1457,10 +1477,32 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, } 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 +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; @@ -1576,8 +1618,23 @@ static void __devinit sci_init_single(struct platform_device *dev, } 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; @@ -1604,6 +1661,7 @@ static void __devinit sci_init_single(struct platform_device *dev, #endif memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs)); + return 0; } #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE @@ -1753,8 +1811,11 @@ static int sci_remove(struct platform_device *dev) 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 +1841,9 @@ static int __devinit sci_probe_single(struct platform_device *dev, 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 --git a/drivers/sh/intc.c b/drivers/sh/intc.c index a3d8677af6a5..f43850527645 100644 --- a/drivers/sh/intc.c +++ b/drivers/sh/intc.c @@ -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; @@ -57,6 +63,8 @@ struct intc_desc_int { 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; }; @@ -446,11 +454,39 @@ static int intc_set_sense(unsigned int irq, unsigned int type) 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; @@ -800,6 +836,8 @@ 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 +853,52 @@ static void intc_redirect_irq(unsigned int irq, struct irq_desc *desc) 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; @@ -848,6 +913,8 @@ void __init register_intc_controller(struct intc_desc *desc) 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]); @@ -859,6 +926,8 @@ void __init register_intc_controller(struct intc_desc *desc) 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); @@ -941,6 +1010,28 @@ void __init register_intc_controller(struct intc_desc *desc) /* 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) |