diff options
author | Joakim Tjernlund <Joakim.Tjernlund@transmode.se> | 2010-05-14 05:14:26 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2010-05-25 02:17:51 -0400 |
commit | 0398fb70940e1f10939d6126eafb760bd48d1566 (patch) | |
tree | fabaaf8936b0e68ec058192cc155640672919694 | |
parent | f9218c2a60facc6ff9a793a9d9ab956194d70012 (diff) |
spi/spi_mpc8xxx: Fix QE mode Litte Endian
QE mode uses Little Endian so words > 8 bits are byte swapped.
Workaround this by always enforcing wordsize 8 for words
> 8 bits. Unfortunately this will not work for LSB transfers
where wordsize is > 8 bits so disable these for now.
Also move the different quirks into its own function to keep
mpc8xxx_spi_setup_transfer() sane.
Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
Acked-by: Anton Vorontsov <cbouatmailru@gmail.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-rw-r--r-- | drivers/spi/spi_mpc8xxx.c | 101 |
1 files changed, 70 insertions, 31 deletions
diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c index 0dfc482bbff5..66517ce750f3 100644 --- a/drivers/spi/spi_mpc8xxx.c +++ b/drivers/spi/spi_mpc8xxx.c | |||
@@ -286,36 +286,12 @@ static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value) | |||
286 | } | 286 | } |
287 | } | 287 | } |
288 | 288 | ||
289 | static | 289 | static int |
290 | int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | 290 | mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs, |
291 | struct spi_device *spi, | ||
292 | struct mpc8xxx_spi *mpc8xxx_spi, | ||
293 | int bits_per_word) | ||
291 | { | 294 | { |
292 | struct mpc8xxx_spi *mpc8xxx_spi; | ||
293 | u8 bits_per_word, pm; | ||
294 | u32 hz; | ||
295 | struct spi_mpc8xxx_cs *cs = spi->controller_state; | ||
296 | |||
297 | mpc8xxx_spi = spi_master_get_devdata(spi->master); | ||
298 | |||
299 | if (t) { | ||
300 | bits_per_word = t->bits_per_word; | ||
301 | hz = t->speed_hz; | ||
302 | } else { | ||
303 | bits_per_word = 0; | ||
304 | hz = 0; | ||
305 | } | ||
306 | |||
307 | /* spi_transfer level calls that work per-word */ | ||
308 | if (!bits_per_word) | ||
309 | bits_per_word = spi->bits_per_word; | ||
310 | |||
311 | /* Make sure its a bit width we support [4..16, 32] */ | ||
312 | if ((bits_per_word < 4) | ||
313 | || ((bits_per_word > 16) && (bits_per_word != 32))) | ||
314 | return -EINVAL; | ||
315 | |||
316 | if (!hz) | ||
317 | hz = spi->max_speed_hz; | ||
318 | |||
319 | cs->rx_shift = 0; | 295 | cs->rx_shift = 0; |
320 | cs->tx_shift = 0; | 296 | cs->tx_shift = 0; |
321 | if (bits_per_word <= 8) { | 297 | if (bits_per_word <= 8) { |
@@ -339,19 +315,82 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
339 | return -EINVAL; | 315 | return -EINVAL; |
340 | 316 | ||
341 | if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE && | 317 | if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE && |
342 | spi->mode & SPI_LSB_FIRST) { | 318 | spi->mode & SPI_LSB_FIRST) { |
343 | cs->tx_shift = 0; | 319 | cs->tx_shift = 0; |
344 | if (bits_per_word <= 8) | 320 | if (bits_per_word <= 8) |
345 | cs->rx_shift = 8; | 321 | cs->rx_shift = 8; |
346 | else | 322 | else |
347 | cs->rx_shift = 0; | 323 | cs->rx_shift = 0; |
348 | } | 324 | } |
349 | |||
350 | mpc8xxx_spi->rx_shift = cs->rx_shift; | 325 | mpc8xxx_spi->rx_shift = cs->rx_shift; |
351 | mpc8xxx_spi->tx_shift = cs->tx_shift; | 326 | mpc8xxx_spi->tx_shift = cs->tx_shift; |
352 | mpc8xxx_spi->get_rx = cs->get_rx; | 327 | mpc8xxx_spi->get_rx = cs->get_rx; |
353 | mpc8xxx_spi->get_tx = cs->get_tx; | 328 | mpc8xxx_spi->get_tx = cs->get_tx; |
354 | 329 | ||
330 | return bits_per_word; | ||
331 | } | ||
332 | |||
333 | static int | ||
334 | mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs, | ||
335 | struct spi_device *spi, | ||
336 | int bits_per_word) | ||
337 | { | ||
338 | /* QE uses Little Endian for words > 8 | ||
339 | * so transform all words > 8 into 8 bits | ||
340 | * Unfortnatly that doesn't work for LSB so | ||
341 | * reject these for now */ | ||
342 | /* Note: 32 bits word, LSB works iff | ||
343 | * tfcr/rfcr is set to CPMFCR_GBL */ | ||
344 | if (spi->mode & SPI_LSB_FIRST && | ||
345 | bits_per_word > 8) | ||
346 | return -EINVAL; | ||
347 | if (bits_per_word > 8) | ||
348 | return 8; /* pretend its 8 bits */ | ||
349 | return bits_per_word; | ||
350 | } | ||
351 | |||
352 | static | ||
353 | int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | ||
354 | { | ||
355 | struct mpc8xxx_spi *mpc8xxx_spi; | ||
356 | int bits_per_word; | ||
357 | u8 pm; | ||
358 | u32 hz; | ||
359 | struct spi_mpc8xxx_cs *cs = spi->controller_state; | ||
360 | |||
361 | mpc8xxx_spi = spi_master_get_devdata(spi->master); | ||
362 | |||
363 | if (t) { | ||
364 | bits_per_word = t->bits_per_word; | ||
365 | hz = t->speed_hz; | ||
366 | } else { | ||
367 | bits_per_word = 0; | ||
368 | hz = 0; | ||
369 | } | ||
370 | |||
371 | /* spi_transfer level calls that work per-word */ | ||
372 | if (!bits_per_word) | ||
373 | bits_per_word = spi->bits_per_word; | ||
374 | |||
375 | /* Make sure its a bit width we support [4..16, 32] */ | ||
376 | if ((bits_per_word < 4) | ||
377 | || ((bits_per_word > 16) && (bits_per_word != 32))) | ||
378 | return -EINVAL; | ||
379 | |||
380 | if (!hz) | ||
381 | hz = spi->max_speed_hz; | ||
382 | |||
383 | if (!(mpc8xxx_spi->flags & SPI_CPM_MODE)) | ||
384 | bits_per_word = mspi_apply_cpu_mode_quirks(cs, spi, | ||
385 | mpc8xxx_spi, | ||
386 | bits_per_word); | ||
387 | else if (mpc8xxx_spi->flags & SPI_QE) | ||
388 | bits_per_word = mspi_apply_qe_mode_quirks(cs, spi, | ||
389 | bits_per_word); | ||
390 | |||
391 | if (bits_per_word < 0) | ||
392 | return bits_per_word; | ||
393 | |||
355 | if (bits_per_word == 32) | 394 | if (bits_per_word == 32) |
356 | bits_per_word = 0; | 395 | bits_per_word = 0; |
357 | else | 396 | else |