summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31/spi-imx31.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2011-12-18 10:41:43 +0000
committerMichael Sevakis <jethead71@rockbox.org>2011-12-18 10:41:43 +0000
commit292e7cab73c75260b7cfb7f90ad28938c8f1117a (patch)
tree4341681314958c3a9aa663e5ace52eb4b1e107ab /firmware/target/arm/imx31/spi-imx31.c
parent0efabb3d19e7690585641c4a19eca131d15b59d8 (diff)
downloadrockbox-292e7cab73c75260b7cfb7f90ad28938c8f1117a.tar.gz
rockbox-292e7cab73c75260b7cfb7f90ad28938c8f1117a.zip
Gigabeat S: PMIC SPI improvement and bugfixes.
Nick some aspects from the as3525 ascodec driver to improve throughput in the beast's SPI communications by switching tranfer descriptors to the caller's stack and getting rid of thread synchronization. Fix a bug that suddenly became obvious that could permanently stall the SPI driver because all data could be shifted out before the interrupt could get serviced. In that case, it needs a kick to restart it. Should probably put the SPI interrupt priority above DVFS. A tweak to the event registration interface to simplify it. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31353 a1c6a512-1295-4272-9138-f99709370657
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 {