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 /drivers | |
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>
Diffstat (limited to 'drivers')
-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) { |