summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/dma/shdma.c411
-rw-r--r--drivers/dma/shdma.h7
-rw-r--r--drivers/mtd/nand/Kconfig4
-rw-r--r--drivers/mtd/nand/sh_flctl.c69
-rw-r--r--drivers/serial/sh-sci.h220
-rw-r--r--drivers/sh/intc.c28
-rw-r--r--drivers/sh/pfc.c37
-rw-r--r--drivers/usb/host/r8a66597-hcd.c41
8 files changed, 428 insertions, 389 deletions
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index d10cc899c460..b75ce8b84c46 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -48,23 +48,20 @@ enum sh_dmae_desc_status {
*/
#define RS_DEFAULT (RS_DUAL)
+/* 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 void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all);
#define SH_DMAC_CHAN_BASE(id) (dma_base_addr[id])
static void sh_dmae_writel(struct sh_dmae_chan *sh_dc, u32 data, u32 reg)
{
- ctrl_outl(data, (SH_DMAC_CHAN_BASE(sh_dc->id) + reg));
+ ctrl_outl(data, SH_DMAC_CHAN_BASE(sh_dc->id) + reg);
}
static u32 sh_dmae_readl(struct sh_dmae_chan *sh_dc, u32 reg)
{
- return ctrl_inl((SH_DMAC_CHAN_BASE(sh_dc->id) + reg));
-}
-
-static void dmae_init(struct sh_dmae_chan *sh_chan)
-{
- u32 chcr = RS_DEFAULT; /* default is DUAL mode */
- sh_dmae_writel(sh_chan, chcr, CHCR);
+ return ctrl_inl(SH_DMAC_CHAN_BASE(sh_dc->id) + reg);
}
/*
@@ -95,27 +92,30 @@ static int sh_dmae_rst(int id)
return 0;
}
-static int dmae_is_busy(struct sh_dmae_chan *sh_chan)
+static bool dmae_is_busy(struct sh_dmae_chan *sh_chan)
{
u32 chcr = sh_dmae_readl(sh_chan, CHCR);
- if (chcr & CHCR_DE) {
- if (!(chcr & CHCR_TE))
- return -EBUSY; /* working */
- }
- return 0; /* waiting */
+
+ if ((chcr & (CHCR_DE | CHCR_TE)) == CHCR_DE)
+ return true; /* working */
+
+ return false; /* waiting */
}
-static inline unsigned int calc_xmit_shift(struct sh_dmae_chan *sh_chan)
+static unsigned int ts_shift[] = TS_SHIFT;
+static inline unsigned int calc_xmit_shift(u32 chcr)
{
- u32 chcr = sh_dmae_readl(sh_chan, CHCR);
- return ts_shift[(chcr & CHCR_TS_MASK) >> CHCR_TS_SHIFT];
+ int cnt = ((chcr & CHCR_TS_LOW_MASK) >> CHCR_TS_LOW_SHIFT) |
+ ((chcr & CHCR_TS_HIGH_MASK) >> CHCR_TS_HIGH_SHIFT);
+
+ return ts_shift[cnt];
}
static void dmae_set_reg(struct sh_dmae_chan *sh_chan, struct sh_dmae_regs *hw)
{
sh_dmae_writel(sh_chan, hw->sar, SAR);
sh_dmae_writel(sh_chan, hw->dar, DAR);
- sh_dmae_writel(sh_chan, hw->tcr >> calc_xmit_shift(sh_chan), TCR);
+ sh_dmae_writel(sh_chan, hw->tcr >> sh_chan->xmit_shift, TCR);
}
static void dmae_start(struct sh_dmae_chan *sh_chan)
@@ -123,7 +123,7 @@ static void dmae_start(struct sh_dmae_chan *sh_chan)
u32 chcr = sh_dmae_readl(sh_chan, CHCR);
chcr |= CHCR_DE | CHCR_IE;
- sh_dmae_writel(sh_chan, chcr, CHCR);
+ sh_dmae_writel(sh_chan, chcr & ~CHCR_TE, CHCR);
}
static void dmae_halt(struct sh_dmae_chan *sh_chan)
@@ -134,55 +134,50 @@ static void dmae_halt(struct sh_dmae_chan *sh_chan)
sh_dmae_writel(sh_chan, chcr, CHCR);
}
+static void dmae_init(struct sh_dmae_chan *sh_chan)
+{
+ u32 chcr = RS_DEFAULT; /* default is DUAL mode */
+ sh_chan->xmit_shift = calc_xmit_shift(chcr);
+ sh_dmae_writel(sh_chan, chcr, CHCR);
+}
+
static int dmae_set_chcr(struct sh_dmae_chan *sh_chan, u32 val)
{
- int ret = dmae_is_busy(sh_chan);
/* When DMA was working, can not set data to CHCR */
- if (ret)
- return ret;
+ if (dmae_is_busy(sh_chan))
+ return -EBUSY;
+ sh_chan->xmit_shift = calc_xmit_shift(val);
sh_dmae_writel(sh_chan, val, CHCR);
+
return 0;
}
-#define DMARS1_ADDR 0x04
-#define DMARS2_ADDR 0x08
-#define DMARS_SHIFT 8
-#define DMARS_CHAN_MSK 0x01
+#define DMARS_SHIFT 8
+#define DMARS_CHAN_MSK 0x01
static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val)
{
u32 addr;
int shift = 0;
- int ret = dmae_is_busy(sh_chan);
- if (ret)
- return ret;
+
+ if (dmae_is_busy(sh_chan))
+ return -EBUSY;
if (sh_chan->id & DMARS_CHAN_MSK)
shift = DMARS_SHIFT;
- switch (sh_chan->id) {
- /* DMARS0 */
- case 0:
- case 1:
- addr = SH_DMARS_BASE;
- break;
- /* DMARS1 */
- case 2:
- case 3:
- addr = (SH_DMARS_BASE + DMARS1_ADDR);
- break;
- /* DMARS2 */
- case 4:
- case 5:
- addr = (SH_DMARS_BASE + DMARS2_ADDR);
- break;
- default:
+ if (sh_chan->id < 6)
+ /* DMA0RS0 - DMA0RS2 */
+ addr = SH_DMARS_BASE0 + (sh_chan->id / 2) * 4;
+#ifdef SH_DMARS_BASE1
+ else if (sh_chan->id < 12)
+ /* DMA1RS0 - DMA1RS2 */
+ addr = SH_DMARS_BASE1 + ((sh_chan->id - 6) / 2) * 4;
+#endif
+ else
return -EINVAL;
- }
- ctrl_outw((val << shift) |
- (ctrl_inw(addr) & (shift ? 0xFF00 : 0x00FF)),
- addr);
+ ctrl_outw((val << shift) | (ctrl_inw(addr) & (0xFF00 >> shift)), addr);
return 0;
}
@@ -250,10 +245,53 @@ static struct sh_desc *sh_dmae_get_desc(struct sh_dmae_chan *sh_chan)
return NULL;
}
+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 dma_device *dma_dev = sh_chan->common.device;
+ struct sh_dmae_device *shdev = container_of(dma_dev,
+ struct sh_dmae_device, common);
+ struct sh_dmae_pdata *pdata = &shdev->pdata;
+ int i;
+
+ if ((unsigned)slave_id >= SHDMA_SLAVE_NUMBER)
+ return NULL;
+
+ for (i = 0; i < pdata->config_num; i++)
+ if (pdata->config[i].slave_id == slave_id)
+ return pdata->config + i;
+
+ return NULL;
+}
+
static int sh_dmae_alloc_chan_resources(struct dma_chan *chan)
{
struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
struct sh_desc *desc;
+ struct sh_dmae_slave *param = chan->private;
+
+ /*
+ * This relies on the guarantee from dmaengine that alloc_chan_resources
+ * never runs concurrently with itself or free_chan_resources.
+ */
+ if (param) {
+ struct sh_dmae_slave_config *cfg;
+
+ cfg = sh_dmae_find_slave(sh_chan, param->slave_id);
+ if (!cfg)
+ return -EINVAL;
+
+ if (test_and_set_bit(param->slave_id, sh_dmae_slave_used))
+ return -EBUSY;
+
+ param->config = cfg;
+
+ dmae_set_dmars(sh_chan, cfg->mid_rid);
+ dmae_set_chcr(sh_chan, cfg->chcr);
+ } else {
+ if ((sh_dmae_readl(sh_chan, CHCR) & 0x700) != 0x400)
+ dmae_set_chcr(sh_chan, RS_DEFAULT);
+ }
spin_lock_bh(&sh_chan->desc_lock);
while (sh_chan->descs_allocated < NR_DESCS_PER_CHANNEL) {
@@ -286,10 +324,18 @@ static void sh_dmae_free_chan_resources(struct dma_chan *chan)
struct sh_desc *desc, *_desc;
LIST_HEAD(list);
+ dmae_halt(sh_chan);
+
/* Prepared and not submitted descriptors can still be on the queue */
if (!list_empty(&sh_chan->ld_queue))
sh_dmae_chan_ld_cleanup(sh_chan, true);
+ if (chan->private) {
+ /* The caller is holding dma_list_mutex */
+ struct sh_dmae_slave *param = chan->private;
+ clear_bit(param->slave_id, sh_dmae_slave_used);
+ }
+
spin_lock_bh(&sh_chan->desc_lock);
list_splice_init(&sh_chan->ld_free, &list);
@@ -301,23 +347,97 @@ static void sh_dmae_free_chan_resources(struct dma_chan *chan)
kfree(desc);
}
-static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy(
- struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src,
- size_t len, unsigned long flags)
+/**
+ * sh_dmae_add_desc - get, set up and return one transfer descriptor
+ * @sh_chan: DMA channel
+ * @flags: DMA transfer flags
+ * @dest: destination DMA address, incremented when direction equals
+ * DMA_FROM_DEVICE or DMA_BIDIRECTIONAL
+ * @src: source DMA address, incremented when direction equals
+ * DMA_TO_DEVICE or DMA_BIDIRECTIONAL
+ * @len: DMA transfer length
+ * @first: if NULL, set to the current descriptor and cookie set to -EBUSY
+ * @direction: needed for slave DMA to decide which address to keep constant,
+ * equals DMA_BIDIRECTIONAL for MEMCPY
+ * Returns 0 or an error
+ * Locks: called with desc_lock held
+ */
+static struct sh_desc *sh_dmae_add_desc(struct sh_dmae_chan *sh_chan,
+ unsigned long flags, dma_addr_t *dest, dma_addr_t *src, size_t *len,
+ struct sh_desc **first, enum dma_data_direction direction)
{
- struct sh_dmae_chan *sh_chan;
- struct sh_desc *first = NULL, *prev = NULL, *new;
+ struct sh_desc *new;
size_t copy_size;
- LIST_HEAD(tx_list);
- int chunks = (len + SH_DMA_TCR_MAX) / (SH_DMA_TCR_MAX + 1);
- if (!chan)
+ if (!*len)
return NULL;
- if (!len)
+ /* Allocate the link descriptor from the free list */
+ new = sh_dmae_get_desc(sh_chan);
+ if (!new) {
+ dev_err(sh_chan->dev, "No free link descriptor available\n");
return NULL;
+ }
- sh_chan = to_sh_chan(chan);
+ copy_size = min(*len, (size_t)SH_DMA_TCR_MAX + 1);
+
+ new->hw.sar = *src;
+ new->hw.dar = *dest;
+ new->hw.tcr = copy_size;
+
+ if (!*first) {
+ /* First desc */
+ new->async_tx.cookie = -EBUSY;
+ *first = new;
+ } else {
+ /* Other desc - invisible to the user */
+ new->async_tx.cookie = -EINVAL;
+ }
+
+ dev_dbg(sh_chan->dev,
+ "chaining (%u/%u)@%x -> %x with %p, cookie %d, shift %d\n",
+ copy_size, *len, *src, *dest, &new->async_tx,
+ new->async_tx.cookie, sh_chan->xmit_shift);
+
+ new->mark = DESC_PREPARED;
+ new->async_tx.flags = flags;
+ new->direction = direction;
+
+ *len -= copy_size;
+ if (direction == DMA_BIDIRECTIONAL || direction == DMA_TO_DEVICE)
+ *src += copy_size;
+ if (direction == DMA_BIDIRECTIONAL || direction == DMA_FROM_DEVICE)
+ *dest += copy_size;
+
+ return new;
+}
+
+/*
+ * sh_dmae_prep_sg - prepare transfer descriptors from an SG list
+ *
+ * Common routine for public (MEMCPY) and slave DMA. The MEMCPY case is also
+ * converted to scatter-gather to guarantee consistent locking and a correct
+ * list manipulation. For slave DMA direction carries the usual meaning, and,
+ * logically, the SG list is RAM and the addr variable contains slave address,
+ * e.g., the FIFO I/O register. For MEMCPY direction equals DMA_BIDIRECTIONAL
+ * and the SG list contains only one element and points at the source buffer.
+ */
+static struct dma_async_tx_descriptor *sh_dmae_prep_sg(struct sh_dmae_chan *sh_chan,
+ struct scatterlist *sgl, unsigned int sg_len, dma_addr_t *addr,
+ enum dma_data_direction direction, unsigned long flags)
+{
+ struct scatterlist *sg;
+ struct sh_desc *first = NULL, *new = NULL /* compiler... */;
+ LIST_HEAD(tx_list);
+ int chunks = 0;
+ int i;
+
+ if (!sg_len)
+ return NULL;
+
+ for_each_sg(sgl, sg, sg_len, i)
+ chunks += (sg_dma_len(sg) + SH_DMA_TCR_MAX) /
+ (SH_DMA_TCR_MAX + 1);
/* Have to lock the whole loop to protect against concurrent release */
spin_lock_bh(&sh_chan->desc_lock);
@@ -333,49 +453,32 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy(
* only during this function, then they are immediately spliced
* back onto the free list in form of a chain
*/
- do {
- /* Allocate the link descriptor from the free list */
- new = sh_dmae_get_desc(sh_chan);
- if (!new) {
- dev_err(sh_chan->dev,
- "No free memory for link descriptor\n");
- list_for_each_entry(new, &tx_list, node)
- new->mark = DESC_IDLE;
- list_splice(&tx_list, &sh_chan->ld_free);
- spin_unlock_bh(&sh_chan->desc_lock);
- return NULL;
- }
-
- copy_size = min(len, (size_t)SH_DMA_TCR_MAX + 1);
-
- new->hw.sar = dma_src;
- new->hw.dar = dma_dest;
- new->hw.tcr = copy_size;
- if (!first) {
- /* First desc */
- new->async_tx.cookie = -EBUSY;
- first = new;
- } else {
- /* Other desc - invisible to the user */
- new->async_tx.cookie = -EINVAL;
- }
-
- dev_dbg(sh_chan->dev,
- "chaining %u of %u with %p, dst %x, cookie %d\n",
- copy_size, len, &new->async_tx, dma_dest,
- new->async_tx.cookie);
-
- new->mark = DESC_PREPARED;
- new->async_tx.flags = flags;
- new->chunks = chunks--;
-
- prev = new;
- len -= copy_size;
- dma_src += copy_size;
- dma_dest += copy_size;
- /* Insert the link descriptor to the LD ring */
- list_add_tail(&new->node, &tx_list);
- } while (len);
+ for_each_sg(sgl, sg, sg_len, i) {
+ dma_addr_t sg_addr = sg_dma_address(sg);
+ size_t len = sg_dma_len(sg);
+
+ if (!len)
+ goto err_get_desc;
+
+ do {
+ dev_dbg(sh_chan->dev, "Add SG #%d@%p[%d], dma %llx\n",
+ i, sg, len, (unsigned long long)sg_addr);
+
+ if (direction == DMA_FROM_DEVICE)
+ new = sh_dmae_add_desc(sh_chan, flags,
+ &sg_addr, addr, &len, &first,
+ direction);
+ else
+ new = sh_dmae_add_desc(sh_chan, flags,
+ addr, &sg_addr, &len, &first,
+ direction);
+ if (!new)
+ goto err_get_desc;
+
+ new->chunks = chunks--;
+ list_add_tail(&new->node, &tx_list);
+ } while (len);
+ }
if (new != first)
new->async_tx.cookie = -ENOSPC;
@@ -386,6 +489,77 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy(
spin_unlock_bh(&sh_chan->desc_lock);
return &first->async_tx;
+
+err_get_desc:
+ list_for_each_entry(new, &tx_list, node)
+ new->mark = DESC_IDLE;
+ list_splice(&tx_list, &sh_chan->ld_free);
+
+ spin_unlock_bh(&sh_chan->desc_lock);
+
+ return NULL;
+}
+
+static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy(
+ struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src,
+ size_t len, unsigned long flags)
+{
+ struct sh_dmae_chan *sh_chan;
+ struct scatterlist sg;
+
+ if (!chan || !len)
+ return NULL;
+
+ chan->private = NULL;
+
+ sh_chan = to_sh_chan(chan);
+
+ sg_init_table(&sg, 1);
+ sg_set_page(&sg, pfn_to_page(PFN_DOWN(dma_src)), len,
+ offset_in_page(dma_src));
+ sg_dma_address(&sg) = dma_src;
+ sg_dma_len(&sg) = len;
+
+ return sh_dmae_prep_sg(sh_chan, &sg, 1, &dma_dest, DMA_BIDIRECTIONAL,
+ flags);
+}
+
+static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg(
+ struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len,
+ enum dma_data_direction direction, unsigned long flags)
+{
+ struct sh_dmae_slave *param;
+ struct sh_dmae_chan *sh_chan;
+
+ if (!chan)
+ return NULL;
+
+ sh_chan = to_sh_chan(chan);
+ param = chan->private;
+
+ /* Someone calling slave DMA on a public channel? */
+ if (!param || !sg_len) {
+ dev_warn(sh_chan->dev, "%s: bad parameter: %p, %d, %d\n",
+ __func__, param, sg_len, param ? param->slave_id : -1);
+ return NULL;
+ }
+
+ /*
+ * if (param != NULL), this is a successfully requested slave channel,
+ * therefore param->config != NULL too.
+ */
+ return sh_dmae_prep_sg(sh_chan, sgl, sg_len, &param->config->addr,
+ direction, flags);
+}
+
+static void sh_dmae_terminate_all(struct dma_chan *chan)
+{
+ struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
+
+ if (!chan)
+ return;
+
+ sh_dmae_chan_ld_cleanup(sh_chan, true);
}
static dma_async_tx_callback __ld_cleanup(struct sh_dmae_chan *sh_chan, bool all)
@@ -419,7 +593,11 @@ static dma_async_tx_callback __ld_cleanup(struct sh_dmae_chan *sh_chan, bool all
cookie = tx->cookie;
if (desc->mark == DESC_COMPLETED && desc->chunks == 1) {
- BUG_ON(sh_chan->completed_cookie != desc->cookie - 1);
+ if (sh_chan->completed_cookie != desc->cookie - 1)
+ dev_dbg(sh_chan->dev,
+ "Completing cookie %d, expected %d\n",
+ desc->cookie,
+ sh_chan->completed_cookie + 1);
sh_chan->completed_cookie = desc->cookie;
}
@@ -492,7 +670,7 @@ static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan)
return;
}
- /* Find the first un-transfer desciptor */
+ /* Find the first not transferred desciptor */
list_for_each_entry(sd, &sh_chan->ld_queue, node)
if (sd->mark == DESC_SUBMITTED) {
/* Get the ld start address from ld_queue */
@@ -559,7 +737,7 @@ static irqreturn_t sh_dmae_err(int irq, void *data)
/* IRQ Multi */
if (shdev->pdata.mode & SHDMA_MIX_IRQ) {
- int cnt = 0;
+ int __maybe_unused cnt = 0;
switch (irq) {
#if defined(DMTE6_IRQ) && defined(DMAE1_IRQ)
case DMTE6_IRQ:
@@ -596,11 +774,14 @@ static void dmae_do_tasklet(unsigned long data)
struct sh_dmae_chan *sh_chan = (struct sh_dmae_chan *)data;
struct sh_desc *desc;
u32 sar_buf = sh_dmae_readl(sh_chan, SAR);
+ u32 dar_buf = sh_dmae_readl(sh_chan, DAR);
spin_lock(&sh_chan->desc_lock);
list_for_each_entry(desc, &sh_chan->ld_queue, node) {
- if ((desc->hw.sar + desc->hw.tcr) == sar_buf &&
- desc->mark == DESC_SUBMITTED) {
+ if (desc->mark == DESC_SUBMITTED &&
+ ((desc->direction == DMA_FROM_DEVICE &&
+ (desc->hw.dar + desc->hw.tcr) == dar_buf) ||
+ (desc->hw.sar + desc->hw.tcr) == sar_buf)) {
dev_dbg(sh_chan->dev, "done #%d@%p dst %u\n",
desc->async_tx.cookie, &desc->async_tx,
desc->hw.dar);
@@ -673,7 +854,7 @@ static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id)
}
snprintf(new_sh_chan->dev_id, sizeof(new_sh_chan->dev_id),
- "sh-dmae%d", new_sh_chan->id);
+ "sh-dmae%d", new_sh_chan->id);
/* set up channel irq */
err = request_irq(irq, &sh_dmae_interrupt, irqflags,
@@ -684,11 +865,6 @@ static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id)
goto err_no_irq;
}
- /* CHCR register control function */
- new_sh_chan->set_chcr = dmae_set_chcr;
- /* DMARS register control function */
- new_sh_chan->set_dmars = dmae_set_dmars;
-
shdev->chan[id] = new_sh_chan;
return 0;
@@ -759,12 +935,19 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&shdev->common.channels);
dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask);
+ dma_cap_set(DMA_SLAVE, shdev->common.cap_mask);
+
shdev->common.device_alloc_chan_resources
= sh_dmae_alloc_chan_resources;
shdev->common.device_free_chan_resources = sh_dmae_free_chan_resources;
shdev->common.device_prep_dma_memcpy = sh_dmae_prep_memcpy;
shdev->common.device_is_tx_complete = sh_dmae_is_complete;
shdev->common.device_issue_pending = sh_dmae_memcpy_issue_pending;
+
+ /* Compulsory for DMA_SLAVE fields */
+ shdev->common.device_prep_slave_sg = sh_dmae_prep_slave_sg;
+ shdev->common.device_terminate_all = sh_dmae_terminate_all;
+
shdev->common.dev = &pdev->dev;
/* Default transfer size of 32 bytes requires 32-byte alignment */
shdev->common.copy_align = 5;
diff --git a/drivers/dma/shdma.h b/drivers/dma/shdma.h
index 108f1cffb6f5..7e227f3c87c4 100644
--- a/drivers/dma/shdma.h
+++ b/drivers/dma/shdma.h
@@ -29,6 +29,7 @@ struct sh_desc {
struct sh_dmae_regs hw;
struct list_head node;
struct dma_async_tx_descriptor async_tx;
+ enum dma_data_direction direction;
dma_cookie_t cookie;
int chunks;
int mark;
@@ -45,13 +46,9 @@ struct sh_dmae_chan {
struct device *dev; /* Channel device */
struct tasklet_struct tasklet; /* Tasklet */
int descs_allocated; /* desc count */
+ int xmit_shift; /* log_2(bytes_per_xfer) */
int id; /* Raw id of this channel */
char dev_id[16]; /* unique name per DMAC of channel */
-
- /* Set chcr */
- int (*set_chcr)(struct sh_dmae_chan *sh_chan, u32 regs);
- /* Set DMA resource */
- int (*set_dmars)(struct sh_dmae_chan *sh_chan, u16 res);
};
struct sh_dmae_device {
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 677cd53f18c3..bb6465604235 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -457,10 +457,10 @@ config MTD_NAND_NOMADIK
config MTD_NAND_SH_FLCTL
tristate "Support for NAND on Renesas SuperH FLCTL"
- depends on MTD_NAND && SUPERH && CPU_SUBTYPE_SH7723
+ depends on MTD_NAND && SUPERH
help
Several Renesas SuperH CPU has FLCTL. This option enables support
- for NAND Flash using FLCTL. This driver support SH7723.
+ for NAND Flash using FLCTL.
config MTD_NAND_DAVINCI
tristate "Support NAND on DaVinci SoC"
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
index 02bef21f2e4b..1842df8bdd93 100644
--- a/drivers/mtd/nand/sh_flctl.c
+++ b/drivers/mtd/nand/sh_flctl.c
@@ -1,10 +1,10 @@
/*
* SuperH FLCTL nand controller
*
- * Copyright © 2008 Renesas Solutions Corp.
- * Copyright © 2008 Atom Create Engineering Co., Ltd.
+ * Copyright (c) 2008 Renesas Solutions Corp.
+ * Copyright (c) 2008 Atom Create Engineering Co., Ltd.
*
- * Based on fsl_elbc_nand.c, Copyright © 2006-2007 Freescale Semiconductor
+ * Based on fsl_elbc_nand.c, Copyright (c) 2006-2007 Freescale Semiconductor
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -75,6 +75,11 @@ static void start_translation(struct sh_flctl *flctl)
writeb(TRSTRT, FLTRCR(flctl));
}
+static void timeout_error(struct sh_flctl *flctl, const char *str)
+{
+ dev_err(&flctl->pdev->dev, "Timeout occured in %s\n", str);
+}
+
static void wait_completion(struct sh_flctl *flctl)
{
uint32_t timeout = LOOP_TIMEOUT_MAX;
@@ -87,7 +92,7 @@ static void wait_completion(struct sh_flctl *flctl)
udelay(1);
}
- printk(KERN_ERR "wait_completion(): Timeout occured \n");
+ timeout_error(flctl, __func__);
writeb(0x0, FLTRCR(flctl));
}
@@ -100,6 +105,8 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr)
addr = page_addr; /* ERASE1 */
} else if (page_addr != -1) {
/* SEQIN, READ0, etc.. */
+ if (flctl->chip.options & NAND_BUSWIDTH_16)
+ column >>= 1;
if (flctl->page_size) {
addr = column & 0x0FFF;
addr |= (page_addr & 0xff) << 16;
@@ -132,7 +139,7 @@ static void wait_rfifo_ready(struct sh_flctl *flctl)
return;
udelay(1);
}
- printk(KERN_ERR "wait_rfifo_ready(): Timeout occured \n");
+ timeout_error(flctl, __func__);
}
static void wait_wfifo_ready(struct sh_flctl *flctl)
@@ -146,7 +153,7 @@ static void wait_wfifo_ready(struct sh_flctl *flctl)
return;
udelay(1);
}
- printk(KERN_ERR "wait_wfifo_ready(): Timeout occured \n");
+ timeout_error(flctl, __func__);
}
static int wait_recfifo_ready(struct sh_flctl *flctl, int sector_number)
@@ -198,7 +205,7 @@ static int wait_recfifo_ready(struct sh_flctl *flctl, int sector_number)
writel(0, FL4ECCCR(flctl));
}
- printk(KERN_ERR "wait_recfifo_ready(): Timeout occured \n");
+ timeout_error(flctl, __func__);
return 1; /* timeout */
}
@@ -214,7 +221,7 @@ static void wait_wecfifo_ready(struct sh_flctl *flctl)
return;
udelay(1);
}
- printk(KERN_ERR "wait_wecfifo_ready(): Timeout occured \n");
+ timeout_error(flctl, __func__);
}
static void read_datareg(struct sh_flctl *flctl, int offset)
@@ -275,7 +282,7 @@ static void write_fiforeg(struct sh_flctl *flctl, int rlen, int offset)
static void set_cmd_regs(struct mtd_info *mtd, uint32_t cmd, uint32_t flcmcdr_val)
{
struct sh_flctl *flctl = mtd_to_flctl(mtd);
- uint32_t flcmncr_val = readl(FLCMNCR(flctl));
+ uint32_t flcmncr_val = readl(FLCMNCR(flctl)) & ~SEL_16BIT;
uint32_t flcmdcr_val, addr_len_bytes = 0;
/* Set SNAND bit if page size is 2048byte */
@@ -297,6 +304,8 @@ static void set_cmd_regs(struct mtd_info *mtd, uint32_t cmd, uint32_t flcmcdr_va
case NAND_CMD_READOOB:
addr_len_bytes = flctl->rw_ADRCNT;
flcmdcr_val |= CDSRC_E;
+ if (flctl->chip.options & NAND_BUSWIDTH_16)
+ flcmncr_val |= SEL_16BIT;
break;
case NAND_CMD_SEQIN:
/* This case is that cmd is READ0 or READ1 or READ00 */
@@ -305,6 +314,8 @@ static void set_cmd_regs(struct mtd_info *mtd, uint32_t cmd, uint32_t flcmcdr_va
case NAND_CMD_PAGEPROG:
addr_len_bytes = flctl->rw_ADRCNT;
flcmdcr_val |= DOCMD2_E | CDSRC_E | SELRW;
+ if (flctl->chip.options & NAND_BUSWIDTH_16)
+ flcmncr_val |= SEL_16BIT;
break;
case NAND_CMD_READID:
flcmncr_val &= ~SNAND_E;
@@ -523,6 +534,8 @@ static void flctl_cmdfunc(struct mtd_info *mtd, unsigned int command,
set_addr(mtd, 0, page_addr);
flctl->read_bytes = mtd->writesize + mtd->oobsize;
+ if (flctl->chip.options & NAND_BUSWIDTH_16)
+ column >>= 1;
flctl->index += column;
goto read_normal_exit;
@@ -686,6 +699,18 @@ static uint8_t flctl_read_byte(struct mtd_info *mtd)
return data;
}
+static uint16_t flctl_read_word(struct mtd_info *mtd)
+{
+ struct sh_flctl *flctl = mtd_to_flctl(mtd);
+ int index = flctl->index;
+ uint16_t data;
+ uint16_t *buf = (uint16_t *)&flctl->done_buff[index];
+
+ data = *buf;
+ flctl->index += 2;
+ return data;
+}
+
static void flctl_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
{
int i;
@@ -769,38 +794,36 @@ static int flctl_chip_init_tail(struct mtd_info *mtd)
return 0;
}
-static int __init flctl_probe(struct platform_device *pdev)
+static int __devinit flctl_probe(struct platform_device *pdev)
{
struct resource *res;
struct sh_flctl *flctl;
struct mtd_info *flctl_mtd;
struct nand_chip *nand;
struct sh_flctl_platform_data *pdata;
- int ret;
+ int ret = -ENXIO;
pdata = pdev->dev.platform_data;
if (pdata == NULL) {
- printk(KERN_ERR "sh_flctl platform_data not found.\n");
- return -ENODEV;
+ dev_err(&pdev->dev, "no platform data defined\n");
+ return -EINVAL;
}
flctl = kzalloc(sizeof(struct sh_flctl), GFP_KERNEL);
if (!flctl) {
- printk(KERN_ERR "Unable to allocate NAND MTD dev structure.\n");
+ dev_err(&pdev->dev, "failed to allocate driver data\n");
return -ENOMEM;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
- printk(KERN_ERR "%s: resource not found.\n", __func__);
- ret = -ENODEV;
+ dev_err(&pdev->dev, "failed to get I/O memory\n");
goto err;
}
- flctl->reg = ioremap(res->start, res->end - res->start + 1);
+ flctl->reg = ioremap(res->start, resource_size(res));
if (flctl->reg == NULL) {
- printk(KERN_ERR "%s: ioremap error.\n", __func__);
- ret = -ENOMEM;
+ dev_err(&pdev->dev, "failed to remap I/O memory\n");
goto err;
}
@@ -808,6 +831,7 @@ static int __init flctl_probe(struct platform_device *pdev)
flctl_mtd = &flctl->mtd;
nand = &flctl->chip;
flctl_mtd->priv = nand;
+ flctl->pdev = pdev;
flctl->hwecc = pdata->has_hwecc;
flctl_register_init(flctl, pdata->flcmncr_val);
@@ -825,6 +849,11 @@ static int __init flctl_probe(struct platform_device *pdev)
nand->select_chip = flctl_select_chip;
nand->cmdfunc = flctl_cmdfunc;
+ if (pdata->flcmncr_val & SEL_16BIT) {
+ nand->options |= NAND_BUSWIDTH_16;
+ nand->read_word = flctl_read_word;
+ }
+
ret = nand_scan_ident(flctl_mtd, 1);
if (ret)
goto err;
@@ -846,7 +875,7 @@ err:
return ret;
}
-static int __exit flctl_remove(struct platform_device *pdev)
+static int __devexit flctl_remove(struct platform_device *pdev)
{
struct sh_flctl *flctl = platform_get_drvdata(pdev);
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index 0efcded59ae6..f7d2589926d2 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -518,34 +518,6 @@ static inline int sci_rxd_in(struct uart_port *port)
{
if (port->mapbase == 0xfffffe80)
return __raw_readb(SCPDR)&0x01 ? 1 : 0; /* SCI */
- if (port->mapbase == 0xa4000150)
- return __raw_readb(SCPDR)&0x10 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xa4000140)
- return __raw_readb(SCPDR)&0x04 ? 1 : 0; /* IRDA */
- return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
-static inline int sci_rxd_in(struct uart_port *port)
-{
- if (port->mapbase == SCIF0)
- return __raw_readb(SCPDR)&0x04 ? 1 : 0; /* IRDA */
- if (port->mapbase == SCIF2)
- return __raw_readb(SCPDR)&0x10 ? 1 : 0; /* SCIF */
- return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
-static inline int sci_rxd_in(struct uart_port *port)
-{
- return sci_in(port,SCxSR)&0x0010 ? 1 : 0;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7720) || \
- defined(CONFIG_CPU_SUBTYPE_SH7721)
-static inline int sci_rxd_in(struct uart_port *port)
-{
- if (port->mapbase == 0xa4430000)
- return sci_in(port, SCxSR) & 0x0003 ? 1 : 0;
- else if (port->mapbase == 0xa4438000)
- return sci_in(port, SCxSR) & 0x0003 ? 1 : 0;
return 1;
}
#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \
@@ -558,207 +530,17 @@ static inline int sci_rxd_in(struct uart_port *port)
{
if (port->mapbase == 0xffe00000)
return __raw_readb(SCSPTR1)&0x01 ? 1 : 0; /* SCI */
- if (port->mapbase == 0xffe80000)
- return __raw_readw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */
- return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
-static inline int sci_rxd_in(struct uart_port *port)
-{
- if (port->mapbase == 0xffe80000)
- return __raw_readw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */
return 1;
}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7757)
-static inline int sci_rxd_in(struct uart_port *port)
-{
- if (port->mapbase == 0xfe4b0000)
- return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0;
- if (port->mapbase == 0xfe4c0000)
- return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0;
- if (port->mapbase == 0xfe4d0000)
- return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7760)
-static inline int sci_rxd_in(struct uart_port *port)
-{
- if (port->mapbase == 0xfe600000)
- return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xfe610000)
- return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xfe620000)
- return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
- return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7343)
-static inline int sci_rxd_in(struct uart_port *port)
-{
- if (port->mapbase == 0xffe00000)
- return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xffe10000)
- return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xffe20000)
- return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xffe30000)
- return __raw_readw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
- return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7366)
-static inline int sci_rxd_in(struct uart_port *port)
-{
- if (port->mapbase == 0xffe00000)
- return __raw_readb(SCPDR0) & 0x0001 ? 1 : 0; /* SCIF0 */
- return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
-static inline int sci_rxd_in(struct uart_port *port)
-{
- if (port->mapbase == 0xffe00000)
- return __raw_readb(PSDR) & 0x02 ? 1 : 0; /* SCIF0 */
- if (port->mapbase == 0xffe10000)
- return __raw_readb(PADR) & 0x40 ? 1 : 0; /* SCIF1 */
- if (port->mapbase == 0xffe20000)
- return __raw_readb(PWDR) & 0x04 ? 1 : 0; /* SCIF2 */
-
- return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
-static inline int sci_rxd_in(struct uart_port *port)
-{
- if (port->mapbase == 0xffe00000)
- return __raw_readb(SCSPTR0) & 0x0008 ? 1 : 0; /* SCIF0 */
- if (port->mapbase == 0xffe10000)
- return __raw_readb(SCSPTR1) & 0x0020 ? 1 : 0; /* SCIF1 */
- if (port->mapbase == 0xffe20000)
- return __raw_readb(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF2 */
- if (port->mapbase == 0xa4e30000)
- return __raw_readb(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF3 */
- if (port->mapbase == 0xa4e40000)
- return __raw_readb(SCSPTR4) & 0x0001 ? 1 : 0; /* SCIF4 */
- if (port->mapbase == 0xa4e50000)
- return __raw_readb(SCSPTR5) & 0x0008 ? 1 : 0; /* SCIF5 */
- return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7724)
-# define SCFSR 0x0010
-# define SCASSR 0x0014
-static inline int sci_rxd_in(struct uart_port *port)
-{
- if (port->type == PORT_SCIF)
- return __raw_readw((port->mapbase + SCFSR)) & SCIF_BRK ? 1 : 0;
- if (port->type == PORT_SCIFA)
- return __raw_readw((port->mapbase + SCASSR)) & SCIF_BRK ? 1 : 0;
- return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
-static inline int sci_rxd_in(struct uart_port *port)
-{
- return sci_in(port, SCSPTR)&0x0001 ? 1 : 0; /* SCIF */
-}
#elif defined(__H8300H__) || defined(__H8300S__)
static inline int sci_rxd_in(struct uart_port *port)
{
int ch = (port->mapbase - SMR0) >> 3;
return (H8300_SCI_DR(ch) & h8300_sci_pins[ch].rx) ? 1 : 0;
}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
-static inline int sci_rxd_in(struct uart_port *port)
-{
- if (port->mapbase == 0xffe00000)
- return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xffe08000)
- return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xffe10000)
- return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF/IRDA */
-
- return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7770)
-static inline int sci_rxd_in(struct uart_port *port)
-{
- if (port->mapbase == 0xff923000)
- return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xff924000)
- return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xff925000)
- return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
- return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
-static inline int sci_rxd_in(struct uart_port *port)
-{
- if (port->mapbase == 0xffe00000)
- return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xffe10000)
- return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
- return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \
- defined(CONFIG_CPU_SUBTYPE_SH7786)
-static inline int sci_rxd_in(struct uart_port *port)
-{
- if (port->mapbase == 0xffea0000)
- return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xffeb0000)
- return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xffec0000)
- return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xffed0000)
- return __raw_readw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xffee0000)
- return __raw_readw(SCSPTR4) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xffef0000)
- return __raw_readw(SCSPTR5) & 0x0001 ? 1 : 0; /* SCIF */
- return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7201) || \
- defined(CONFIG_CPU_SUBTYPE_SH7203) || \
- defined(CONFIG_CPU_SUBTYPE_SH7206) || \
- defined(CONFIG_CPU_SUBTYPE_SH7263)
-static inline int sci_rxd_in(struct uart_port *port)
-{
- if (port->mapbase == 0xfffe8000)
- return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xfffe8800)
- return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xfffe9000)
- return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xfffe9800)
- return __raw_readw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
-#if defined(CONFIG_CPU_SUBTYPE_SH7201)
- if (port->mapbase == 0xfffeA000)
- return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xfffeA800)
- return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xfffeB000)
- return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xfffeB800)
- return __raw_readw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
-#endif
- return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
-static inline int sci_rxd_in(struct uart_port *port)
-{
- if (port->mapbase == 0xf8400000)
- return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xf8410000)
- return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xf8420000)
- return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
- return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SHX3)
+#else /* default case for non-SCI processors */
static inline int sci_rxd_in(struct uart_port *port)
{
- if (port->mapbase == 0xffc30000)
- return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xffc40000)
- return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xffc50000)
- return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
- if (port->mapbase == 0xffc60000)
- return __raw_readw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
return 1;
}
#endif
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
index ccee18945d91..3a687396dfa2 100644
--- a/drivers/sh/intc.c
+++ b/drivers/sh/intc.c
@@ -987,7 +987,7 @@ device_initcall(register_intc_sysdevs);
/*
* Dynamic IRQ allocation and deallocation
*/
-static unsigned int create_irq_on_node(unsigned int irq_want, int node)
+unsigned int create_irq_nr(unsigned int irq_want, int node)
{
unsigned int irq = 0, new;
unsigned long flags;
@@ -996,24 +996,28 @@ static unsigned int create_irq_on_node(unsigned int irq_want, int node)
spin_lock_irqsave(&vector_lock, flags);
/*
- * First try the wanted IRQ, then scan.
+ * First try the wanted IRQ
*/
- if (test_and_set_bit(irq_want, intc_irq_map)) {
+ if (test_and_set_bit(irq_want, intc_irq_map) == 0) {
+ new = irq_want;
+ } else {
+ /* .. then fall back to scanning. */
new = find_first_zero_bit(intc_irq_map, nr_irqs);
if (unlikely(new == nr_irqs))
goto out_unlock;
- desc = irq_to_desc_alloc_node(new, node);
- if (unlikely(!desc)) {
- pr_info("can't get irq_desc for %d\n", new);
- goto out_unlock;
- }
-
- desc = move_irq_desc(desc, node);
__set_bit(new, intc_irq_map);
- irq = new;
}
+ desc = irq_to_desc_alloc_node(new, node);
+ if (unlikely(!desc)) {
+ pr_info("can't get irq_desc for %d\n", new);
+ goto out_unlock;
+ }
+
+ desc = move_irq_desc(desc, node);
+ irq = new;
+
out_unlock:
spin_unlock_irqrestore(&vector_lock, flags);
@@ -1028,7 +1032,7 @@ int create_irq(void)
int nid = cpu_to_node(smp_processor_id());
int irq;
- irq = create_irq_on_node(NR_IRQS_LEGACY, nid);
+ irq = create_irq_nr(NR_IRQS_LEGACY, nid);
if (irq == 0)
irq = -1;
diff --git a/drivers/sh/pfc.c b/drivers/sh/pfc.c
index 082604edc4c2..cf0303acab8e 100644
--- a/drivers/sh/pfc.c
+++ b/drivers/sh/pfc.c
@@ -337,12 +337,39 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
if (!enum_id)
break;
+ /* first check if this is a function enum */
in_range = enum_in_range(enum_id, &gpioc->function);
- if (!in_range && range) {
- in_range = enum_in_range(enum_id, range);
-
- if (in_range && enum_id == range->force)
- continue;
+ if (!in_range) {
+ /* not a function enum */
+ if (range) {
+ /*
+ * other range exists, so this pin is
+ * a regular GPIO pin that now is being
+ * bound to a specific direction.
+ *
+ * for this case we only allow function enums
+ * and the enums that match the other range.
+ */
+ in_range = enum_in_range(enum_id, range);
+
+ /*
+ * special case pass through for fixed
+ * input-only or output-only pins without
+ * function enum register association.
+ */
+ if (in_range && enum_id == range->force)
+ continue;
+ } else {
+ /*
+ * no other range exists, so this pin
+ * must then be of the function type.
+ *
+ * allow function type pins to select
+ * any combination of function/in/out
+ * in their MARK lists.
+ */
+ in_range = 1;
+ }
}
if (!in_range)
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 0ceec123ddfd..bee558aed427 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -35,7 +35,9 @@
#include <linux/usb.h>
#include <linux/platform_device.h>
#include <linux/io.h>
+#include <linux/mm.h>
#include <linux/irq.h>
+#include <asm/cacheflush.h>
#include "../core/hcd.h"
#include "r8a66597.h"
@@ -820,6 +822,26 @@ static void enable_r8a66597_pipe(struct r8a66597 *r8a66597, struct urb *urb,
enable_r8a66597_pipe_dma(r8a66597, dev, pipe, urb);
}
+static void r8a66597_urb_done(struct r8a66597 *r8a66597, struct urb *urb,
+ int status)
+__releases(r8a66597->lock)
+__acquires(r8a66597->lock)
+{
+ if (usb_pipein(urb->pipe) && usb_pipetype(urb->pipe) != PIPE_CONTROL) {
+ void *ptr;
+
+ for (ptr = urb->transfer_buffer;
+ ptr < urb->transfer_buffer + urb->transfer_buffer_length;
+ ptr += PAGE_SIZE)
+ flush_dcache_page(virt_to_page(ptr));
+ }
+
+ usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb);
+ spin_unlock(&r8a66597->lock);
+ usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb, status);
+ spin_lock(&r8a66597->lock);
+}
+
/* this function must be called with interrupt disabled */
static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address)
{
@@ -838,15 +860,9 @@ static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address)
list_del(&td->queue);
kfree(td);
- if (urb) {
- usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597),
- urb);
+ if (urb)
+ r8a66597_urb_done(r8a66597, urb, -ENODEV);
- spin_unlock(&r8a66597->lock);
- usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb,
- -ENODEV);
- spin_lock(&r8a66597->lock);
- }
break;
}
}
@@ -1006,6 +1022,8 @@ static void start_root_hub_sampling(struct r8a66597 *r8a66597, int port,
/* this function must be called with interrupt disabled */
static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port,
u16 syssts)
+__releases(r8a66597->lock)
+__acquires(r8a66597->lock)
{
if (syssts == SE0) {
r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port));
@@ -1023,7 +1041,9 @@ static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port,
usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597));
}
+ spin_unlock(&r8a66597->lock);
usb_hcd_poll_rh_status(r8a66597_to_hcd(r8a66597));
+ spin_lock(&r8a66597->lock);
}
/* this function must be called with interrupt disabled */
@@ -1283,10 +1303,7 @@ __releases(r8a66597->lock) __acquires(r8a66597->lock)
if (usb_pipeisoc(urb->pipe))
urb->start_frame = r8a66597_get_frame(hcd);
- usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb);
- spin_unlock(&r8a66597->lock);
- usb_hcd_giveback_urb(hcd, urb, status);
- spin_lock(&r8a66597->lock);
+ r8a66597_urb_done(r8a66597, urb, status);
}
if (restart) {