Commit f056d29e authored by Andy Walls's avatar Andy Walls Committed by Mauro Carvalho Chehab

V4L/DVB (9510): cx18: Fix write retries for registers that always change - part 2.

cx18: Fix write retries for registers that always change - part 2.
Some registers, especially interrupt related ones, will never read
back the value just written.  Modified interrupt register readback
checks to make sure the intended effect was achieved.
Signed-off-by: default avatarAndy Walls <awalls@radix.net>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 58ae1c23
...@@ -88,6 +88,19 @@ void cx18_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr) ...@@ -88,6 +88,19 @@ void cx18_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr)
cx18_log_write_retries(cx, i, addr); cx18_log_write_retries(cx, i, addr);
} }
void _cx18_writel_expect(struct cx18 *cx, u32 val, void __iomem *addr,
u32 eval, u32 mask)
{
int i;
eval &= mask;
for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
cx18_writel_noretry(cx, val, addr);
if (eval == (cx18_readl_noretry(cx, addr) & mask))
break;
}
cx18_log_write_retries(cx, i, addr);
}
void cx18_writew_retry(struct cx18 *cx, u16 val, void __iomem *addr) void cx18_writew_retry(struct cx18 *cx, u16 val, void __iomem *addr)
{ {
int i; int i;
...@@ -218,7 +231,7 @@ void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count) ...@@ -218,7 +231,7 @@ void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count)
void cx18_sw1_irq_enable(struct cx18 *cx, u32 val) void cx18_sw1_irq_enable(struct cx18 *cx, u32 val)
{ {
u32 r; u32 r;
cx18_write_reg_noretry(cx, val, SW1_INT_STATUS); cx18_write_reg_expect(cx, val, SW1_INT_STATUS, ~val, val);
r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI); r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI);
cx18_write_reg(cx, r | val, SW1_INT_ENABLE_PCI); cx18_write_reg(cx, r | val, SW1_INT_ENABLE_PCI);
} }
...@@ -233,7 +246,7 @@ void cx18_sw1_irq_disable(struct cx18 *cx, u32 val) ...@@ -233,7 +246,7 @@ void cx18_sw1_irq_disable(struct cx18 *cx, u32 val)
void cx18_sw2_irq_enable(struct cx18 *cx, u32 val) void cx18_sw2_irq_enable(struct cx18 *cx, u32 val)
{ {
u32 r; u32 r;
cx18_write_reg_noretry(cx, val, SW2_INT_STATUS); cx18_write_reg_expect(cx, val, SW2_INT_STATUS, ~val, val);
r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI); r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI);
cx18_write_reg(cx, r | val, SW2_INT_ENABLE_PCI); cx18_write_reg(cx, r | val, SW2_INT_ENABLE_PCI);
} }
......
...@@ -133,6 +133,8 @@ static inline void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr) ...@@ -133,6 +133,8 @@ static inline void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr)
cx18_writel_noretry(cx, val, addr); cx18_writel_noretry(cx, val, addr);
} }
void _cx18_writel_expect(struct cx18 *cx, u32 val, void __iomem *addr,
u32 eval, u32 mask);
static inline static inline
void cx18_writew_noretry(struct cx18 *cx, u16 val, void __iomem *addr) void cx18_writew_noretry(struct cx18 *cx, u16 val, void __iomem *addr)
...@@ -271,6 +273,21 @@ static inline void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg) ...@@ -271,6 +273,21 @@ static inline void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg)
cx18_write_reg_noretry(cx, val, reg); cx18_write_reg_noretry(cx, val, reg);
} }
static inline void _cx18_write_reg_expect(struct cx18 *cx, u32 val, u32 reg,
u32 eval, u32 mask)
{
_cx18_writel_expect(cx, val, cx->reg_mem + reg, eval, mask);
}
static inline void cx18_write_reg_expect(struct cx18 *cx, u32 val, u32 reg,
u32 eval, u32 mask)
{
if (cx18_retry_mmio)
_cx18_write_reg_expect(cx, val, reg, eval, mask);
else
cx18_write_reg_noretry(cx, val, reg);
}
static inline u32 cx18_read_reg_noretry(struct cx18 *cx, u32 reg) static inline u32 cx18_read_reg_noretry(struct cx18 *cx, u32 reg)
{ {
......
...@@ -142,16 +142,19 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id) ...@@ -142,16 +142,19 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id)
spin_lock(&cx->dma_reg_lock); spin_lock(&cx->dma_reg_lock);
hw2_mask = cx18_read_reg(cx, HW2_INT_MASK5_PCI);
hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & hw2_mask;
sw2_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK;
sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & sw2_mask;
sw1_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU; sw1_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU;
sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & sw1_mask; sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & sw1_mask;
sw2_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK;
sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & sw2_mask;
hw2_mask = cx18_read_reg(cx, HW2_INT_MASK5_PCI);
hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & hw2_mask;
cx18_write_reg_noretry(cx, sw2&sw2_mask, SW2_INT_STATUS); if (sw1)
cx18_write_reg_noretry(cx, sw1&sw1_mask, SW1_INT_STATUS); cx18_write_reg_expect(cx, sw1, SW1_INT_STATUS, ~sw1, sw1);
cx18_write_reg_noretry(cx, hw2&hw2_mask, HW2_INT_CLR_STATUS); if (sw2)
cx18_write_reg_expect(cx, sw2, SW2_INT_STATUS, ~sw2, sw2);
if (hw2)
cx18_write_reg_expect(cx, hw2, HW2_INT_CLR_STATUS, ~hw2, hw2);
if (sw1 || sw2 || hw2) if (sw1 || sw2 || hw2)
CX18_DEBUG_HI_IRQ("SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2); CX18_DEBUG_HI_IRQ("SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2);
...@@ -178,5 +181,5 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id) ...@@ -178,5 +181,5 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id)
hpu_cmd(cx, sw1); hpu_cmd(cx, sw1);
spin_unlock(&cx->dma_reg_lock); spin_unlock(&cx->dma_reg_lock);
return (hw2 | sw1 | sw2) ? IRQ_HANDLED : IRQ_NONE; return (sw1 || sw2 || hw2) ? IRQ_HANDLED : IRQ_NONE;
} }
...@@ -176,7 +176,7 @@ long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb) ...@@ -176,7 +176,7 @@ long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb)
cx18_setup_page(cx, SCB_OFFSET); cx18_setup_page(cx, SCB_OFFSET);
cx18_write_sync(cx, mb->request, &ack_mb->ack); cx18_write_sync(cx, mb->request, &ack_mb->ack);
cx18_write_reg_noretry(cx, ack_irq, SW2_INT_SET); cx18_write_reg_expect(cx, ack_irq, SW2_INT_SET, ack_irq, ack_irq);
return 0; return 0;
} }
...@@ -225,7 +225,7 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) ...@@ -225,7 +225,7 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
} }
if (info->flags & API_FAST) if (info->flags & API_FAST)
timeout /= 2; timeout /= 2;
cx18_write_reg_noretry(cx, irq, SW1_INT_SET); cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq);
while (!sig && cx18_readl(cx, &mb->ack) != cx18_readl(cx, &mb->request) while (!sig && cx18_readl(cx, &mb->ack) != cx18_readl(cx, &mb->request)
&& cnt < 660) { && cnt < 660) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment