diff options
Diffstat (limited to 'firmware/target/arm/imx31/spi-imx31.c')
-rw-r--r-- | firmware/target/arm/imx31/spi-imx31.c | 27 |
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 | { |