diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2011-12-18 10:41:43 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2011-12-18 10:41:43 +0000 |
commit | 292e7cab73c75260b7cfb7f90ad28938c8f1117a (patch) | |
tree | 4341681314958c3a9aa663e5ace52eb4b1e107ab /firmware/target/arm/imx31/spi-imx31.c | |
parent | 0efabb3d19e7690585641c4a19eca131d15b59d8 (diff) | |
download | rockbox-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.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 | { |