|
|
|
@ -124,6 +124,9 @@ struct talitos_private { |
|
|
|
|
void __iomem *reg; |
|
|
|
|
int irq[2]; |
|
|
|
|
|
|
|
|
|
/* SEC global registers lock */ |
|
|
|
|
spinlock_t reg_lock ____cacheline_aligned; |
|
|
|
|
|
|
|
|
|
/* SEC version geometry (from device tree node) */ |
|
|
|
|
unsigned int num_channels; |
|
|
|
|
unsigned int chfifo_len; |
|
|
|
@ -412,6 +415,7 @@ static void talitos_done_##name(unsigned long data) \ |
|
|
|
|
{ \
|
|
|
|
|
struct device *dev = (struct device *)data; \
|
|
|
|
|
struct talitos_private *priv = dev_get_drvdata(dev); \
|
|
|
|
|
unsigned long flags; \
|
|
|
|
|
\
|
|
|
|
|
if (ch_done_mask & 1) \
|
|
|
|
|
flush_channel(dev, 0, 0, 0); \
|
|
|
|
@ -427,8 +431,10 @@ static void talitos_done_##name(unsigned long data) \ |
|
|
|
|
out: \
|
|
|
|
|
/* At this point, all completed channels have been processed */ \
|
|
|
|
|
/* Unmask done interrupts for channels completed later on. */ \
|
|
|
|
|
spin_lock_irqsave(&priv->reg_lock, flags); \
|
|
|
|
|
setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
|
|
|
|
|
setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT); \
|
|
|
|
|
spin_unlock_irqrestore(&priv->reg_lock, flags); \
|
|
|
|
|
} |
|
|
|
|
DEF_TALITOS_DONE(4ch, TALITOS_ISR_4CHDONE) |
|
|
|
|
DEF_TALITOS_DONE(ch0_2, TALITOS_ISR_CH_0_2_DONE) |
|
|
|
@ -619,22 +625,28 @@ static irqreturn_t talitos_interrupt_##name(int irq, void *data) \ |
|
|
|
|
struct device *dev = data; \
|
|
|
|
|
struct talitos_private *priv = dev_get_drvdata(dev); \
|
|
|
|
|
u32 isr, isr_lo; \
|
|
|
|
|
unsigned long flags; \
|
|
|
|
|
\
|
|
|
|
|
spin_lock_irqsave(&priv->reg_lock, flags); \
|
|
|
|
|
isr = in_be32(priv->reg + TALITOS_ISR); \
|
|
|
|
|
isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \
|
|
|
|
|
/* Acknowledge interrupt */ \
|
|
|
|
|
out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
|
|
|
|
|
out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \
|
|
|
|
|
\
|
|
|
|
|
if (unlikely((isr & ~TALITOS_ISR_4CHDONE) & ch_err_mask || isr_lo)) \
|
|
|
|
|
talitos_error(dev, isr, isr_lo); \
|
|
|
|
|
else \
|
|
|
|
|
if (unlikely(isr & ch_err_mask || isr_lo)) { \
|
|
|
|
|
spin_unlock_irqrestore(&priv->reg_lock, flags); \
|
|
|
|
|
talitos_error(dev, isr & ch_err_mask, isr_lo); \
|
|
|
|
|
} \
|
|
|
|
|
else { \
|
|
|
|
|
if (likely(isr & ch_done_mask)) { \
|
|
|
|
|
/* mask further done interrupts. */ \
|
|
|
|
|
clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
|
|
|
|
|
/* done_task will unmask done interrupts at exit */ \
|
|
|
|
|
tasklet_schedule(&priv->done_task[tlet]); \
|
|
|
|
|
} \
|
|
|
|
|
spin_unlock_irqrestore(&priv->reg_lock, flags); \
|
|
|
|
|
} \
|
|
|
|
|
\
|
|
|
|
|
return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \
|
|
|
|
|
IRQ_NONE; \
|
|
|
|
@ -2719,6 +2731,8 @@ static int talitos_probe(struct platform_device *ofdev) |
|
|
|
|
|
|
|
|
|
priv->ofdev = ofdev; |
|
|
|
|
|
|
|
|
|
spin_lock_init(&priv->reg_lock); |
|
|
|
|
|
|
|
|
|
err = talitos_probe_irq(ofdev); |
|
|
|
|
if (err) |
|
|
|
|
goto err_out; |
|
|
|
|