summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31/spi-imx31.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx31/spi-imx31.c')
-rw-r--r--firmware/target/arm/imx31/spi-imx31.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/firmware/target/arm/imx31/spi-imx31.c b/firmware/target/arm/imx31/spi-imx31.c
index 7fcf94ce90..ea3d2f8d77 100644
--- a/firmware/target/arm/imx31/spi-imx31.c
+++ b/firmware/target/arm/imx31/spi-imx31.c
@@ -170,7 +170,10 @@ static bool start_transfer(struct spi_module_desc * const desc,
170 unsigned long intreg; 170 unsigned long intreg;
171 171
172 if (!spi_set_context(desc, xfer)) 172 if (!spi_set_context(desc, xfer))
173 {
174 xfer->count = -1;
173 return false; 175 return false;
176 }
174 177
175 base[CONREG] |= CSPI_CONREG_EN; /* Enable module */ 178 base[CONREG] |= CSPI_CONREG_EN; /* Enable module */
176 179
@@ -249,8 +252,18 @@ static void spi_interrupt(enum spi_module_number spi)
249 if (xfer->count > 0) 252 if (xfer->count > 0)
250 { 253 {
251 /* Data to transmit - fill TXFIFO or write until exhausted. */ 254 /* Data to transmit - fill TXFIFO or write until exhausted. */
252 if (tx_fill_fifo(desc, base, xfer) != 0) 255 int remaining = tx_fill_fifo(desc, base, xfer);
253 return; 256
257 /* If transfer completed because TXFIFO ran out of data, resume it or
258 else it will not finish. */
259 if (!(base[CONREG] & CSPI_CONREG_XCH))
260 {
261 base[STATREG] = CSPI_STATREG_TC;
262 base[CONREG] |= CSPI_CONREG_XCH;
263 }
264
265 if (remaining > 0)
266 return; /* Still more after this */
254 267
255 /* Out of data - stop TX interrupts, enable TC interrupt. */ 268 /* Out of data - stop TX interrupts, enable TC interrupt. */
256 intreg &= ~CSPI_INTREG_THEN; 269 intreg &= ~CSPI_INTREG_THEN;
@@ -263,7 +276,6 @@ static void spi_interrupt(enum spi_module_number spi)
263 /* Outbound transfer is complete. */ 276 /* Outbound transfer is complete. */
264 intreg &= ~CSPI_INTREG_TCEN; 277 intreg &= ~CSPI_INTREG_TCEN;
265 base[INTREG] = intreg; 278 base[INTREG] = intreg;
266 base[STATREG] = CSPI_STATREG_TC; /* Ack 'complete' */
267 } 279 }
268 280
269 if (intreg != 0) 281 if (intreg != 0)
@@ -276,8 +288,6 @@ static void spi_interrupt(enum spi_module_number spi)
276 spi_transfer_cb_fn_type callback = xfer->callback; 288 spi_transfer_cb_fn_type callback = xfer->callback;
277 xfer->next = NULL; 289 xfer->next = NULL;
278 290
279 base[CONREG] &= ~CSPI_CONREG_EN; /* Disable module */
280
281 if (next == xfer) 291 if (next == xfer)
282 { 292 {
283 /* Last job on queue */ 293 /* Last job on queue */
@@ -287,6 +297,8 @@ static void spi_interrupt(enum spi_module_number spi)
287 callback(xfer); 297 callback(xfer);
288 298
289 /* Callback may have restarted transfers. */ 299 /* Callback may have restarted transfers. */
300 if (desc->head == NULL)
301 base[CONREG] &= ~CSPI_CONREG_EN; /* Disable module */
290 } 302 }
291 else 303 else
292 { 304 {
@@ -299,7 +311,6 @@ static void spi_interrupt(enum spi_module_number spi)
299 if (!start_transfer(desc, next)) 311 if (!start_transfer(desc, next))
300 { 312 {
301 xfer = next; 313 xfer = next;
302 xfer->count = -1;
303 continue; /* Failed: try next */ 314 continue; /* Failed: try next */
304 } 315 }
305 } 316 }
@@ -416,10 +427,6 @@ bool spi_transfer(struct spi_transfer_desc *xfer)
416 desc->tail = xfer; 427 desc->tail = xfer;
417 xfer->next = xfer; /* First, self-reference terminate */ 428 xfer->next = xfer; /* First, self-reference terminate */
418 } 429 }
419 else
420 {
421 xfer->count = -1; /* Signal error */
422 }
423 } 430 }
424 else 431 else
425 { 432 {