diff options
Diffstat (limited to 'drivers/dma/ipu')
| -rw-r--r-- | drivers/dma/ipu/ipu_idmac.c | 208 | ||||
| -rw-r--r-- | drivers/dma/ipu/ipu_irq.c | 124 |
2 files changed, 133 insertions, 199 deletions
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c index cb26ee9773d..128ca143486 100644 --- a/drivers/dma/ipu/ipu_idmac.c +++ b/drivers/dma/ipu/ipu_idmac.c @@ -9,6 +9,7 @@ * published by the Free Software Foundation. */ +#include <linux/dma-mapping.h> #include <linux/init.h> #include <linux/platform_device.h> #include <linux/err.h> @@ -20,9 +21,10 @@ #include <linux/string.h> #include <linux/interrupt.h> #include <linux/io.h> +#include <linux/module.h> +#include <linux/dma/ipu-dma.h> -#include <mach/ipu.h> - +#include "../dmaengine.h" #include "ipu_intern.h" #define FS_VF_IN_VALID 0x00000002 @@ -310,7 +312,7 @@ static void ipu_ch_param_set_size(union chan_param_mem *params, case IPU_PIX_FMT_RGB565: params->ip.bpp = 2; params->ip.pfs = 4; - params->ip.npb = 7; + params->ip.npb = 15; params->ip.sat = 2; /* SAT = 32-bit access */ params->ip.ofs0 = 0; /* Red bit offset */ params->ip.ofs1 = 5; /* Green bit offset */ @@ -420,12 +422,6 @@ static void ipu_ch_param_set_size(union chan_param_mem *params, params->pp.nsb = 1; } -static void ipu_ch_param_set_burst_size(union chan_param_mem *params, - uint16_t burst_pixels) -{ - params->pp.npb = burst_pixels - 1; -} - static void ipu_ch_param_set_buffer(union chan_param_mem *params, dma_addr_t buf0, dma_addr_t buf1) { @@ -688,23 +684,6 @@ static int ipu_init_channel_buffer(struct idmac_channel *ichan, ipu_ch_param_set_size(¶ms, pixel_fmt, width, height, stride_bytes); ipu_ch_param_set_buffer(¶ms, phyaddr_0, phyaddr_1); ipu_ch_param_set_rotation(¶ms, rot_mode); - /* Some channels (rotation) have restriction on burst length */ - switch (channel) { - case IDMAC_IC_7: /* Hangs with burst 8, 16, other values - invalid - Table 44-30 */ -/* - ipu_ch_param_set_burst_size(¶ms, 8); - */ - break; - case IDMAC_SDC_0: - case IDMAC_SDC_1: - /* In original code only IPU_PIX_FMT_RGB565 was setting burst */ - ipu_ch_param_set_burst_size(¶ms, 16); - break; - case IDMAC_IC_0: - default: - break; - } spin_lock_irqsave(&ipu->lock, flags); @@ -887,14 +866,7 @@ static dma_cookie_t idmac_tx_submit(struct dma_async_tx_descriptor *tx) dev_dbg(dev, "Submitting sg %p\n", &desc->sg[0]); - cookie = ichan->dma_chan.cookie; - - if (++cookie < 0) - cookie = 1; - - /* from dmaengine.h: "last cookie value returned to client" */ - ichan->dma_chan.cookie = cookie; - tx->cookie = cookie; + cookie = dma_cookie_assign(tx); /* ipu->lock can be taken under ichan->lock, but not v.v. */ spin_lock_irqsave(&ichan->lock, flags); @@ -1145,29 +1117,6 @@ static int ipu_disable_channel(struct idmac *idmac, struct idmac_channel *ichan, reg = idmac_read_icreg(ipu, IDMAC_CHA_EN); idmac_write_icreg(ipu, reg & ~chan_mask, IDMAC_CHA_EN); - /* - * Problem (observed with channel DMAIC_7): after enabling the channel - * and initialising buffers, there comes an interrupt with current still - * pointing at buffer 0, whereas it should use buffer 0 first and only - * generate an interrupt when it is done, then current should already - * point to buffer 1. This spurious interrupt also comes on channel - * DMASDC_0. With DMAIC_7 normally, is we just leave the ISR after the - * first interrupt, there comes the second with current correctly - * pointing to buffer 1 this time. But sometimes this second interrupt - * doesn't come and the channel hangs. Clearing BUFx_RDY when disabling - * the channel seems to prevent the channel from hanging, but it doesn't - * prevent the spurious interrupt. This might also be unsafe. Think - * about the IDMAC controller trying to switch to a buffer, when we - * clear the ready bit, and re-enable it a moment later. - */ - reg = idmac_read_ipureg(ipu, IPU_CHA_BUF0_RDY); - idmac_write_ipureg(ipu, 0, IPU_CHA_BUF0_RDY); - idmac_write_ipureg(ipu, reg & ~(1UL << channel), IPU_CHA_BUF0_RDY); - - reg = idmac_read_ipureg(ipu, IPU_CHA_BUF1_RDY); - idmac_write_ipureg(ipu, 0, IPU_CHA_BUF1_RDY); - idmac_write_ipureg(ipu, reg & ~(1UL << channel), IPU_CHA_BUF1_RDY); - spin_unlock_irqrestore(&ipu->lock, flags); return 0; @@ -1246,33 +1195,6 @@ static irqreturn_t idmac_interrupt(int irq, void *dev_id) /* Other interrupts do not interfere with this channel */ spin_lock(&ichan->lock); - if (unlikely(chan_id != IDMAC_SDC_0 && chan_id != IDMAC_SDC_1 && - ((curbuf >> chan_id) & 1) == ichan->active_buffer && - !list_is_last(ichan->queue.next, &ichan->queue))) { - int i = 100; - - /* This doesn't help. See comment in ipu_disable_channel() */ - while (--i) { - curbuf = idmac_read_ipureg(&ipu_data, IPU_CHA_CUR_BUF); - if (((curbuf >> chan_id) & 1) != ichan->active_buffer) - break; - cpu_relax(); - } - - if (!i) { - spin_unlock(&ichan->lock); - dev_dbg(dev, - "IRQ on active buffer on channel %x, active " - "%d, ready %x, %x, current %x!\n", chan_id, - ichan->active_buffer, ready0, ready1, curbuf); - return IRQ_NONE; - } else - dev_dbg(dev, - "Buffer deactivated on channel %x, active " - "%d, ready %x, %x, current %x, rest %d!\n", chan_id, - ichan->active_buffer, ready0, ready1, curbuf, i); - } - if (unlikely((ichan->active_buffer && (ready1 >> chan_id) & 1) || (!ichan->active_buffer && (ready0 >> chan_id) & 1) )) { @@ -1310,8 +1232,10 @@ static irqreturn_t idmac_interrupt(int irq, void *dev_id) desc = list_entry(ichan->queue.next, struct idmac_tx_desc, list); descnew = desc; - dev_dbg(dev, "IDMAC irq %d, dma 0x%08x, next dma 0x%08x, current %d, curbuf 0x%08x\n", - irq, sg_dma_address(*sg), sgnext ? sg_dma_address(sgnext) : 0, ichan->active_buffer, curbuf); + dev_dbg(dev, "IDMAC irq %d, dma %#llx, next dma %#llx, current %d, curbuf %#x\n", + irq, (u64)sg_dma_address(*sg), + sgnext ? (u64)sg_dma_address(sgnext) : 0, + ichan->active_buffer, curbuf); /* Find the descriptor of sgnext */ sgnew = idmac_sg_next(ichan, &descnew, *sg); @@ -1356,6 +1280,7 @@ static irqreturn_t idmac_interrupt(int irq, void *dev_id) ipu_submit_buffer(ichan, descnew, sgnew, ichan->active_buffer) < 0) { callback = descnew->txd.callback; callback_param = descnew->txd.callback_param; + list_del_init(&descnew->list); spin_unlock(&ichan->lock); if (callback) callback(callback_param); @@ -1365,7 +1290,7 @@ static irqreturn_t idmac_interrupt(int irq, void *dev_id) /* Flip the active buffer - even if update above failed */ ichan->active_buffer = !ichan->active_buffer; if (done) - ichan->completed = desc->txd.cookie; + dma_cookie_complete(&desc->txd); callback = desc->txd.callback; callback_param = desc->txd.callback_param; @@ -1411,7 +1336,8 @@ static void ipu_gc_tasklet(unsigned long arg) /* Allocate and initialise a transfer descriptor. */ static struct dma_async_tx_descriptor *idmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, - enum dma_data_direction direction, unsigned long tx_flags) + enum dma_transfer_direction direction, unsigned long tx_flags, + void *context) { struct idmac_channel *ichan = to_idmac_chan(chan); struct idmac_tx_desc *desc = NULL; @@ -1423,7 +1349,7 @@ static struct dma_async_tx_descriptor *idmac_prep_slave_sg(struct dma_chan *chan chan->chan_id != IDMAC_IC_7) return NULL; - if (direction != DMA_FROM_DEVICE && direction != DMA_TO_DEVICE) { + if (!is_slave_direction(direction)) { dev_err(chan->device->dev, "Invalid DMA direction %d!\n", direction); return NULL; } @@ -1477,39 +1403,58 @@ static int __idmac_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, { struct idmac_channel *ichan = to_idmac_chan(chan); struct idmac *idmac = to_idmac(chan->device); + struct ipu *ipu = to_ipu(idmac); + struct list_head *list, *tmp; unsigned long flags; int i; - /* Only supports DMA_TERMINATE_ALL */ - if (cmd != DMA_TERMINATE_ALL) - return -ENXIO; + switch (cmd) { + case DMA_PAUSE: + spin_lock_irqsave(&ipu->lock, flags); + ipu_ic_disable_task(ipu, chan->chan_id); - ipu_disable_channel(idmac, ichan, - ichan->status >= IPU_CHANNEL_ENABLED); + /* Return all descriptors into "prepared" state */ + list_for_each_safe(list, tmp, &ichan->queue) + list_del_init(list); - tasklet_disable(&to_ipu(idmac)->tasklet); + ichan->sg[0] = NULL; + ichan->sg[1] = NULL; - /* ichan->queue is modified in ISR, have to spinlock */ - spin_lock_irqsave(&ichan->lock, flags); - list_splice_init(&ichan->queue, &ichan->free_list); + spin_unlock_irqrestore(&ipu->lock, flags); - if (ichan->desc) - for (i = 0; i < ichan->n_tx_desc; i++) { - struct idmac_tx_desc *desc = ichan->desc + i; - if (list_empty(&desc->list)) - /* Descriptor was prepared, but not submitted */ - list_add(&desc->list, &ichan->free_list); + ichan->status = IPU_CHANNEL_INITIALIZED; + break; + case DMA_TERMINATE_ALL: + ipu_disable_channel(idmac, ichan, + ichan->status >= IPU_CHANNEL_ENABLED); - async_tx_clear_ack(&desc->txd); - } + tasklet_disable(&ipu->tasklet); - ichan->sg[0] = NULL; - ichan->sg[1] = NULL; - spin_unlock_irqrestore(&ichan->lock, flags); + /* ichan->queue is modified in ISR, have to spinlock */ + spin_lock_irqsave(&ichan->lock, flags); + list_splice_init(&ichan->queue, &ichan->free_list); - tasklet_enable(&to_ipu(idmac)->tasklet); + if (ichan->desc) + for (i = 0; i < ichan->n_tx_desc; i++) { + struct idmac_tx_desc *desc = ichan->desc + i; + if (list_empty(&desc->list)) + /* Descriptor was prepared, but not submitted */ + list_add(&desc->list, &ichan->free_list); - ichan->status = IPU_CHANNEL_INITIALIZED; + async_tx_clear_ack(&desc->txd); + } + + ichan->sg[0] = NULL; + ichan->sg[1] = NULL; + spin_unlock_irqrestore(&ichan->lock, flags); + + tasklet_enable(&ipu->tasklet); + + ichan->status = IPU_CHANNEL_INITIALIZED; + break; + default: + return -ENOSYS; + } return 0; } @@ -1561,8 +1506,7 @@ static int idmac_alloc_chan_resources(struct dma_chan *chan) BUG_ON(chan->client_count > 1); WARN_ON(ichan->status != IPU_CHANNEL_FREE); - chan->cookie = 1; - ichan->completed = -ENXIO; + dma_cookie_init(chan); ret = ipu_irq_map(chan->chan_id); if (ret < 0) @@ -1651,12 +1595,7 @@ static void idmac_free_chan_resources(struct dma_chan *chan) static enum dma_status idmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie, struct dma_tx_state *txstate) { - struct idmac_channel *ichan = to_idmac_chan(chan); - - dma_set_tx_state(txstate, ichan->completed, chan->cookie, 0); - if (cookie != chan->cookie) - return DMA_ERROR; - return DMA_SUCCESS; + return dma_cookie_status(chan, cookie, txstate); } static int __init ipu_idmac_init(struct ipu *ipu) @@ -1689,11 +1628,10 @@ static int __init ipu_idmac_init(struct ipu *ipu) ichan->status = IPU_CHANNEL_FREE; ichan->sec_chan_en = false; - ichan->completed = -ENXIO; snprintf(ichan->eof_name, sizeof(ichan->eof_name), "IDMAC EOF %d", i); dma_chan->device = &idmac->dma; - dma_chan->cookie = 1; + dma_cookie_init(dma_chan); dma_chan->chan_id = i; list_add_tail(&dma_chan->device_node, &dma->channels); } @@ -1703,7 +1641,7 @@ static int __init ipu_idmac_init(struct ipu *ipu) return dma_async_device_register(&idmac->dma); } -static void __exit ipu_idmac_exit(struct ipu *ipu) +static void ipu_idmac_exit(struct ipu *ipu) { int i; struct idmac *idmac = &ipu->idmac; @@ -1712,7 +1650,6 @@ static void __exit ipu_idmac_exit(struct ipu *ipu) struct idmac_channel *ichan = ipu->channel + i; idmac_control(&ichan->dma_chan, DMA_TERMINATE_ALL, 0); - idmac_prep_slave_sg(&ichan->dma_chan, NULL, 0, DMA_NONE, 0); } dma_async_device_unregister(&idmac->dma); @@ -1724,7 +1661,6 @@ static void __exit ipu_idmac_exit(struct ipu *ipu) static int __init ipu_probe(struct platform_device *pdev) { - struct ipu_platform_data *pdata = pdev->dev.platform_data; struct resource *mem_ipu, *mem_ic; int ret; @@ -1732,7 +1668,7 @@ static int __init ipu_probe(struct platform_device *pdev) mem_ipu = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem_ic = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!pdata || !mem_ipu || !mem_ic) + if (!mem_ipu || !mem_ic) return -EINVAL; ipu_data.dev = &pdev->dev; @@ -1749,22 +1685,19 @@ static int __init ipu_probe(struct platform_device *pdev) goto err_noirq; ipu_data.irq_err = ret; - ipu_data.irq_base = pdata->irq_base; - dev_dbg(&pdev->dev, "fn irq %u, err irq %u, irq-base %u\n", - ipu_data.irq_fn, ipu_data.irq_err, ipu_data.irq_base); + dev_dbg(&pdev->dev, "fn irq %u, err irq %u\n", + ipu_data.irq_fn, ipu_data.irq_err); /* Remap IPU common registers */ - ipu_data.reg_ipu = ioremap(mem_ipu->start, - mem_ipu->end - mem_ipu->start + 1); + ipu_data.reg_ipu = ioremap(mem_ipu->start, resource_size(mem_ipu)); if (!ipu_data.reg_ipu) { ret = -ENOMEM; goto err_ioremap_ipu; } /* Remap Image Converter and Image DMA Controller registers */ - ipu_data.reg_ic = ioremap(mem_ic->start, - mem_ic->end - mem_ic->start + 1); + ipu_data.reg_ic = ioremap(mem_ic->start, resource_size(mem_ic)); if (!ipu_data.reg_ic) { ret = -ENOMEM; goto err_ioremap_ic; @@ -1778,7 +1711,7 @@ static int __init ipu_probe(struct platform_device *pdev) } /* Make sure IPU HSP clock is running */ - clk_enable(ipu_data.ipu_clk); + clk_prepare_enable(ipu_data.ipu_clk); /* Disable all interrupts */ idmac_write_ipureg(&ipu_data, 0, IPU_INT_CTRL_1); @@ -1810,7 +1743,7 @@ static int __init ipu_probe(struct platform_device *pdev) err_idmac_init: err_attach_irq: ipu_irq_detach_irq(&ipu_data, pdev); - clk_disable(ipu_data.ipu_clk); + clk_disable_unprepare(ipu_data.ipu_clk); clk_put(ipu_data.ipu_clk); err_clk_get: iounmap(ipu_data.reg_ic); @@ -1822,18 +1755,17 @@ err_noirq: return ret; } -static int __exit ipu_remove(struct platform_device *pdev) +static int ipu_remove(struct platform_device *pdev) { struct ipu *ipu = platform_get_drvdata(pdev); ipu_idmac_exit(ipu); ipu_irq_detach_irq(ipu, pdev); - clk_disable(ipu->ipu_clk); + clk_disable_unprepare(ipu->ipu_clk); clk_put(ipu->ipu_clk); iounmap(ipu->reg_ic); iounmap(ipu->reg_ipu); tasklet_kill(&ipu->tasklet); - platform_set_drvdata(pdev, NULL); return 0; } @@ -1847,7 +1779,7 @@ static struct platform_driver ipu_platform_driver = { .name = "ipu-core", .owner = THIS_MODULE, }, - .remove = __exit_p(ipu_remove), + .remove = ipu_remove, }; static int __init ipu_init(void) diff --git a/drivers/dma/ipu/ipu_irq.c b/drivers/dma/ipu/ipu_irq.c index dd8ebc75b66..2e284a4438b 100644 --- a/drivers/dma/ipu/ipu_irq.c +++ b/drivers/dma/ipu/ipu_irq.c @@ -14,8 +14,8 @@ #include <linux/clk.h> #include <linux/irq.h> #include <linux/io.h> - -#include <mach/ipu.h> +#include <linux/module.h> +#include <linux/dma/ipu-dma.h> #include "ipu_intern.h" @@ -44,7 +44,6 @@ static void ipu_write_reg(struct ipu *ipu, u32 value, unsigned long reg) struct ipu_irq_bank { unsigned int control; unsigned int status; - spinlock_t lock; struct ipu *ipu; }; @@ -81,7 +80,7 @@ static struct ipu_irq_map irq_map[CONFIG_MX3_IPU_IRQS]; /* Protects allocations from the above array of maps */ static DEFINE_MUTEX(map_lock); /* Protects register accesses and individual mappings */ -static DEFINE_SPINLOCK(bank_lock); +static DEFINE_RAW_SPINLOCK(bank_lock); static struct ipu_irq_map *src2map(unsigned int src) { @@ -94,19 +93,19 @@ static struct ipu_irq_map *src2map(unsigned int src) return NULL; } -static void ipu_irq_unmask(unsigned int irq) +static void ipu_irq_unmask(struct irq_data *d) { - struct ipu_irq_map *map = get_irq_chip_data(irq); + struct ipu_irq_map *map = irq_data_get_irq_chip_data(d); struct ipu_irq_bank *bank; uint32_t reg; unsigned long lock_flags; - spin_lock_irqsave(&bank_lock, lock_flags); + raw_spin_lock_irqsave(&bank_lock, lock_flags); bank = map->bank; if (!bank) { - spin_unlock_irqrestore(&bank_lock, lock_flags); - pr_err("IPU: %s(%u) - unmapped!\n", __func__, irq); + raw_spin_unlock_irqrestore(&bank_lock, lock_flags); + pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq); return; } @@ -114,22 +113,22 @@ static void ipu_irq_unmask(unsigned int irq) reg |= (1UL << (map->source & 31)); ipu_write_reg(bank->ipu, reg, bank->control); - spin_unlock_irqrestore(&bank_lock, lock_flags); + raw_spin_unlock_irqrestore(&bank_lock, lock_flags); } -static void ipu_irq_mask(unsigned int irq) +static void ipu_irq_mask(struct irq_data *d) { - struct ipu_irq_map *map = get_irq_chip_data(irq); + struct ipu_irq_map *map = irq_data_get_irq_chip_data(d); struct ipu_irq_bank *bank; uint32_t reg; unsigned long lock_flags; - spin_lock_irqsave(&bank_lock, lock_flags); + raw_spin_lock_irqsave(&bank_lock, lock_flags); bank = map->bank; if (!bank) { - spin_unlock_irqrestore(&bank_lock, lock_flags); - pr_err("IPU: %s(%u) - unmapped!\n", __func__, irq); + raw_spin_unlock_irqrestore(&bank_lock, lock_flags); + pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq); return; } @@ -137,26 +136,26 @@ static void ipu_irq_mask(unsigned int irq) reg &= ~(1UL << (map->source & 31)); ipu_write_reg(bank->ipu, reg, bank->control); - spin_unlock_irqrestore(&bank_lock, lock_flags); + raw_spin_unlock_irqrestore(&bank_lock, lock_flags); } -static void ipu_irq_ack(unsigned int irq) +static void ipu_irq_ack(struct irq_data *d) { - struct ipu_irq_map *map = get_irq_chip_data(irq); + struct ipu_irq_map *map = irq_data_get_irq_chip_data(d); struct ipu_irq_bank *bank; unsigned long lock_flags; - spin_lock_irqsave(&bank_lock, lock_flags); + raw_spin_lock_irqsave(&bank_lock, lock_flags); bank = map->bank; if (!bank) { - spin_unlock_irqrestore(&bank_lock, lock_flags); - pr_err("IPU: %s(%u) - unmapped!\n", __func__, irq); + raw_spin_unlock_irqrestore(&bank_lock, lock_flags); + pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq); return; } ipu_write_reg(bank->ipu, 1UL << (map->source & 31), bank->status); - spin_unlock_irqrestore(&bank_lock, lock_flags); + raw_spin_unlock_irqrestore(&bank_lock, lock_flags); } /** @@ -167,16 +166,16 @@ static void ipu_irq_ack(unsigned int irq) */ bool ipu_irq_status(unsigned int irq) { - struct ipu_irq_map *map = get_irq_chip_data(irq); + struct ipu_irq_map *map = irq_get_chip_data(irq); struct ipu_irq_bank *bank; unsigned long lock_flags; bool ret; - spin_lock_irqsave(&bank_lock, lock_flags); + raw_spin_lock_irqsave(&bank_lock, lock_flags); bank = map->bank; ret = bank && ipu_read_reg(bank->ipu, bank->status) & (1UL << (map->source & 31)); - spin_unlock_irqrestore(&bank_lock, lock_flags); + raw_spin_unlock_irqrestore(&bank_lock, lock_flags); return ret; } @@ -213,10 +212,10 @@ int ipu_irq_map(unsigned int source) if (irq_map[i].source < 0) { unsigned long lock_flags; - spin_lock_irqsave(&bank_lock, lock_flags); + raw_spin_lock_irqsave(&bank_lock, lock_flags); irq_map[i].source = source; irq_map[i].bank = irq_bank + source / 32; - spin_unlock_irqrestore(&bank_lock, lock_flags); + raw_spin_unlock_irqrestore(&bank_lock, lock_flags); ret = irq_map[i].irq; pr_debug("IPU: mapped source %u to IRQ %u\n", @@ -252,10 +251,10 @@ int ipu_irq_unmap(unsigned int source) pr_debug("IPU: unmapped source %u from IRQ %u\n", source, irq_map[i].irq); - spin_lock_irqsave(&bank_lock, lock_flags); + raw_spin_lock_irqsave(&bank_lock, lock_flags); irq_map[i].source = -EINVAL; irq_map[i].bank = NULL; - spin_unlock_irqrestore(&bank_lock, lock_flags); + raw_spin_unlock_irqrestore(&bank_lock, lock_flags); ret = 0; break; @@ -269,14 +268,14 @@ int ipu_irq_unmap(unsigned int source) /* Chained IRQ handler for IPU error interrupt */ static void ipu_irq_err(unsigned int irq, struct irq_desc *desc) { - struct ipu *ipu = get_irq_data(irq); + struct ipu *ipu = irq_get_handler_data(irq); u32 status; int i, line; for (i = IPU_IRQ_NR_FN_BANKS; i < IPU_IRQ_NR_BANKS; i++) { struct ipu_irq_bank *bank = irq_bank + i; - spin_lock(&bank_lock); + raw_spin_lock(&bank_lock); status = ipu_read_reg(ipu, bank->status); /* * Don't think we have to clear all interrupts here, they will @@ -284,18 +283,18 @@ static void ipu_irq_err(unsigned int irq, struct irq_desc *desc) * might want to clear unhandled interrupts after the loop... */ status &= ipu_read_reg(ipu, bank->control); - spin_unlock(&bank_lock); + raw_spin_unlock(&bank_lock); while ((line = ffs(status))) { struct ipu_irq_map *map; line--; status &= ~(1UL << line); - spin_lock(&bank_lock); + raw_spin_lock(&bank_lock); map = src2map(32 * i + line); if (map) irq = map->irq; - spin_unlock(&bank_lock); + raw_spin_unlock(&bank_lock); if (!map) { pr_err("IPU: Interrupt on unmapped source %u bank %d\n", @@ -310,29 +309,29 @@ static void ipu_irq_err(unsigned int irq, struct irq_desc *desc) /* Chained IRQ handler for IPU function interrupt */ static void ipu_irq_fn(unsigned int irq, struct irq_desc *desc) { - struct ipu *ipu = get_irq_data(irq); + struct ipu *ipu = irq_desc_get_handler_data(desc); u32 status; int i, line; for (i = 0; i < IPU_IRQ_NR_FN_BANKS; i++) { struct ipu_irq_bank *bank = irq_bank + i; - spin_lock(&bank_lock); + raw_spin_lock(&bank_lock); status = ipu_read_reg(ipu, bank->status); /* Not clearing all interrupts, see above */ status &= ipu_read_reg(ipu, bank->control); - spin_unlock(&bank_lock); + raw_spin_unlock(&bank_lock); while ((line = ffs(status))) { struct ipu_irq_map *map; line--; status &= ~(1UL << line); - spin_lock(&bank_lock); + raw_spin_lock(&bank_lock); map = src2map(32 * i + line); if (map) irq = map->irq; - spin_unlock(&bank_lock); + raw_spin_unlock(&bank_lock); if (!map) { pr_err("IPU: Interrupt on unmapped source %u bank %d\n", @@ -345,19 +344,21 @@ static void ipu_irq_fn(unsigned int irq, struct irq_desc *desc) } static struct irq_chip ipu_irq_chip = { - .name = "ipu_irq", - .ack = ipu_irq_ack, - .mask = ipu_irq_mask, - .unmask = ipu_irq_unmask, + .name = "ipu_irq", + .irq_ack = ipu_irq_ack, + .irq_mask = ipu_irq_mask, + .irq_unmask = ipu_irq_unmask, }; /* Install the IRQ handler */ int __init ipu_irq_attach_irq(struct ipu *ipu, struct platform_device *dev) { - struct ipu_platform_data *pdata = dev->dev.platform_data; - unsigned int irq, irq_base, i; + unsigned int irq, i; + int irq_base = irq_alloc_descs(-1, 0, CONFIG_MX3_IPU_IRQS, + numa_node_id()); - irq_base = pdata->irq_base; + if (irq_base < 0) + return irq_base; for (i = 0; i < IPU_IRQ_NR_BANKS; i++) irq_bank[i].ipu = ipu; @@ -366,48 +367,49 @@ int __init ipu_irq_attach_irq(struct ipu *ipu, struct platform_device *dev) int ret; irq = irq_base + i; - ret = set_irq_chip(irq, &ipu_irq_chip); + ret = irq_set_chip(irq, &ipu_irq_chip); if (ret < 0) return ret; - ret = set_irq_chip_data(irq, irq_map + i); + ret = irq_set_chip_data(irq, irq_map + i); if (ret < 0) return ret; irq_map[i].ipu = ipu; irq_map[i].irq = irq; irq_map[i].source = -EINVAL; - set_irq_handler(irq, handle_level_irq); + irq_set_handler(irq, handle_level_irq); #ifdef CONFIG_ARM set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); #endif } - set_irq_data(ipu->irq_fn, ipu); - set_irq_chained_handler(ipu->irq_fn, ipu_irq_fn); + irq_set_handler_data(ipu->irq_fn, ipu); + irq_set_chained_handler(ipu->irq_fn, ipu_irq_fn); + + irq_set_handler_data(ipu->irq_err, ipu); + irq_set_chained_handler(ipu->irq_err, ipu_irq_err); - set_irq_data(ipu->irq_err, ipu); - set_irq_chained_handler(ipu->irq_err, ipu_irq_err); + ipu->irq_base = irq_base; return 0; } void ipu_irq_detach_irq(struct ipu *ipu, struct platform_device *dev) { - struct ipu_platform_data *pdata = dev->dev.platform_data; unsigned int irq, irq_base; - irq_base = pdata->irq_base; + irq_base = ipu->irq_base; - set_irq_chained_handler(ipu->irq_fn, NULL); - set_irq_data(ipu->irq_fn, NULL); + irq_set_chained_handler(ipu->irq_fn, NULL); + irq_set_handler_data(ipu->irq_fn, NULL); - set_irq_chained_handler(ipu->irq_err, NULL); - set_irq_data(ipu->irq_err, NULL); + irq_set_chained_handler(ipu->irq_err, NULL); + irq_set_handler_data(ipu->irq_err, NULL); for (irq = irq_base; irq < irq_base + CONFIG_MX3_IPU_IRQS; irq++) { #ifdef CONFIG_ARM set_irq_flags(irq, 0); #endif - set_irq_chip(irq, NULL); - set_irq_chip_data(irq, NULL); + irq_set_chip(irq, NULL); + irq_set_chip_data(irq, NULL); } } |
