diff options
| author | Andy Walls <awalls@radix.net> | 2008-10-31 19:49:12 -0400 |
|---|---|---|
| committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-11-11 05:11:28 -0500 |
| commit | f056d29eebd2c8800cf42528ba0470c77a928821 (patch) | |
| tree | ec57c96e5b7b95ef2597c572f6c90dfa0a40581f | |
| parent | 58ae1c23184772a7b2d02a4a82f5515a7820a155 (diff) | |
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: Andy Walls <awalls@radix.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
| -rw-r--r-- | drivers/media/video/cx18/cx18-io.c | 17 | ||||
| -rw-r--r-- | drivers/media/video/cx18/cx18-io.h | 17 | ||||
| -rw-r--r-- | drivers/media/video/cx18/cx18-irq.c | 19 | ||||
| -rw-r--r-- | drivers/media/video/cx18/cx18-mailbox.c | 4 |
4 files changed, 45 insertions, 12 deletions
diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/video/cx18/cx18-io.c index 31be5e8684dc..220fae8d4ad7 100644 --- a/drivers/media/video/cx18/cx18-io.c +++ b/drivers/media/video/cx18/cx18-io.c | |||
| @@ -88,6 +88,19 @@ void cx18_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr) | |||
| 88 | cx18_log_write_retries(cx, i, addr); | 88 | cx18_log_write_retries(cx, i, addr); |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | void _cx18_writel_expect(struct cx18 *cx, u32 val, void __iomem *addr, | ||
| 92 | u32 eval, u32 mask) | ||
| 93 | { | ||
| 94 | int i; | ||
| 95 | eval &= mask; | ||
| 96 | for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { | ||
| 97 | cx18_writel_noretry(cx, val, addr); | ||
| 98 | if (eval == (cx18_readl_noretry(cx, addr) & mask)) | ||
| 99 | break; | ||
| 100 | } | ||
| 101 | cx18_log_write_retries(cx, i, addr); | ||
| 102 | } | ||
| 103 | |||
| 91 | void cx18_writew_retry(struct cx18 *cx, u16 val, void __iomem *addr) | 104 | void cx18_writew_retry(struct cx18 *cx, u16 val, void __iomem *addr) |
| 92 | { | 105 | { |
| 93 | int i; | 106 | int i; |
| @@ -218,7 +231,7 @@ void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count) | |||
| 218 | void cx18_sw1_irq_enable(struct cx18 *cx, u32 val) | 231 | void cx18_sw1_irq_enable(struct cx18 *cx, u32 val) |
| 219 | { | 232 | { |
| 220 | u32 r; | 233 | u32 r; |
| 221 | cx18_write_reg_noretry(cx, val, SW1_INT_STATUS); | 234 | cx18_write_reg_expect(cx, val, SW1_INT_STATUS, ~val, val); |
| 222 | r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI); | 235 | r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI); |
| 223 | cx18_write_reg(cx, r | val, SW1_INT_ENABLE_PCI); | 236 | cx18_write_reg(cx, r | val, SW1_INT_ENABLE_PCI); |
| 224 | } | 237 | } |
| @@ -233,7 +246,7 @@ void cx18_sw1_irq_disable(struct cx18 *cx, u32 val) | |||
| 233 | void cx18_sw2_irq_enable(struct cx18 *cx, u32 val) | 246 | void cx18_sw2_irq_enable(struct cx18 *cx, u32 val) |
| 234 | { | 247 | { |
| 235 | u32 r; | 248 | u32 r; |
| 236 | cx18_write_reg_noretry(cx, val, SW2_INT_STATUS); | 249 | cx18_write_reg_expect(cx, val, SW2_INT_STATUS, ~val, val); |
| 237 | r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI); | 250 | r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI); |
| 238 | cx18_write_reg(cx, r | val, SW2_INT_ENABLE_PCI); | 251 | cx18_write_reg(cx, r | val, SW2_INT_ENABLE_PCI); |
| 239 | } | 252 | } |
diff --git a/drivers/media/video/cx18/cx18-io.h b/drivers/media/video/cx18/cx18-io.h index 287a5e8bf67b..425244453ea7 100644 --- a/drivers/media/video/cx18/cx18-io.h +++ b/drivers/media/video/cx18/cx18-io.h | |||
| @@ -133,6 +133,8 @@ static inline void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr) | |||
| 133 | cx18_writel_noretry(cx, val, addr); | 133 | cx18_writel_noretry(cx, val, addr); |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | void _cx18_writel_expect(struct cx18 *cx, u32 val, void __iomem *addr, | ||
| 137 | u32 eval, u32 mask); | ||
| 136 | 138 | ||
| 137 | static inline | 139 | static inline |
| 138 | void cx18_writew_noretry(struct cx18 *cx, u16 val, void __iomem *addr) | 140 | 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 | cx18_write_reg_noretry(cx, val, reg); | 273 | cx18_write_reg_noretry(cx, val, reg); |
| 272 | } | 274 | } |
| 273 | 275 | ||
| 276 | static inline void _cx18_write_reg_expect(struct cx18 *cx, u32 val, u32 reg, | ||
| 277 | u32 eval, u32 mask) | ||
| 278 | { | ||
| 279 | _cx18_writel_expect(cx, val, cx->reg_mem + reg, eval, mask); | ||
| 280 | } | ||
| 281 | |||
| 282 | static inline void cx18_write_reg_expect(struct cx18 *cx, u32 val, u32 reg, | ||
| 283 | u32 eval, u32 mask) | ||
| 284 | { | ||
| 285 | if (cx18_retry_mmio) | ||
| 286 | _cx18_write_reg_expect(cx, val, reg, eval, mask); | ||
| 287 | else | ||
| 288 | cx18_write_reg_noretry(cx, val, reg); | ||
| 289 | } | ||
| 290 | |||
| 274 | 291 | ||
| 275 | static inline u32 cx18_read_reg_noretry(struct cx18 *cx, u32 reg) | 292 | static inline u32 cx18_read_reg_noretry(struct cx18 *cx, u32 reg) |
| 276 | { | 293 | { |
diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c index 447fc9c391ac..a366259bbb7b 100644 --- a/drivers/media/video/cx18/cx18-irq.c +++ b/drivers/media/video/cx18/cx18-irq.c | |||
| @@ -142,16 +142,19 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id) | |||
| 142 | 142 | ||
| 143 | spin_lock(&cx->dma_reg_lock); | 143 | spin_lock(&cx->dma_reg_lock); |
| 144 | 144 | ||
| 145 | hw2_mask = cx18_read_reg(cx, HW2_INT_MASK5_PCI); | ||
| 146 | hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & hw2_mask; | ||
| 147 | sw2_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK; | ||
| 148 | sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & sw2_mask; | ||
| 149 | sw1_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU; | 145 | sw1_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU; |
| 150 | sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & sw1_mask; | 146 | sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & sw1_mask; |
| 147 | sw2_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK; | ||
| 148 | sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & sw2_mask; | ||
| 149 | hw2_mask = cx18_read_reg(cx, HW2_INT_MASK5_PCI); | ||
| 150 | hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & hw2_mask; | ||
| 151 | 151 | ||
| 152 | cx18_write_reg_noretry(cx, sw2&sw2_mask, SW2_INT_STATUS); | 152 | if (sw1) |
| 153 | cx18_write_reg_noretry(cx, sw1&sw1_mask, SW1_INT_STATUS); | 153 | cx18_write_reg_expect(cx, sw1, SW1_INT_STATUS, ~sw1, sw1); |
| 154 | cx18_write_reg_noretry(cx, hw2&hw2_mask, HW2_INT_CLR_STATUS); | 154 | if (sw2) |
| 155 | cx18_write_reg_expect(cx, sw2, SW2_INT_STATUS, ~sw2, sw2); | ||
| 156 | if (hw2) | ||
| 157 | cx18_write_reg_expect(cx, hw2, HW2_INT_CLR_STATUS, ~hw2, hw2); | ||
| 155 | 158 | ||
| 156 | if (sw1 || sw2 || hw2) | 159 | if (sw1 || sw2 || hw2) |
| 157 | CX18_DEBUG_HI_IRQ("SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2); | 160 | 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 | hpu_cmd(cx, sw1); | 181 | hpu_cmd(cx, sw1); |
| 179 | spin_unlock(&cx->dma_reg_lock); | 182 | spin_unlock(&cx->dma_reg_lock); |
| 180 | 183 | ||
| 181 | return (hw2 | sw1 | sw2) ? IRQ_HANDLED : IRQ_NONE; | 184 | return (sw1 || sw2 || hw2) ? IRQ_HANDLED : IRQ_NONE; |
| 182 | } | 185 | } |
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 87f7c8e2c181..851a905376bb 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c | |||
| @@ -176,7 +176,7 @@ long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb) | |||
| 176 | 176 | ||
| 177 | cx18_setup_page(cx, SCB_OFFSET); | 177 | cx18_setup_page(cx, SCB_OFFSET); |
| 178 | cx18_write_sync(cx, mb->request, &ack_mb->ack); | 178 | cx18_write_sync(cx, mb->request, &ack_mb->ack); |
| 179 | cx18_write_reg_noretry(cx, ack_irq, SW2_INT_SET); | 179 | cx18_write_reg_expect(cx, ack_irq, SW2_INT_SET, ack_irq, ack_irq); |
| 180 | return 0; | 180 | return 0; |
| 181 | } | 181 | } |
| 182 | 182 | ||
| @@ -225,7 +225,7 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) | |||
| 225 | } | 225 | } |
| 226 | if (info->flags & API_FAST) | 226 | if (info->flags & API_FAST) |
| 227 | timeout /= 2; | 227 | timeout /= 2; |
| 228 | cx18_write_reg_noretry(cx, irq, SW1_INT_SET); | 228 | cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq); |
| 229 | 229 | ||
| 230 | while (!sig && cx18_readl(cx, &mb->ack) != cx18_readl(cx, &mb->request) | 230 | while (!sig && cx18_readl(cx, &mb->ack) != cx18_readl(cx, &mb->request) |
| 231 | && cnt < 660) { | 231 | && cnt < 660) { |
