Commit 0398fb70 authored by Joakim Tjernlund's avatar Joakim Tjernlund Committed by Grant Likely

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: default avatarJoakim Tjernlund <Joakim.Tjernlund@transmode.se>
Acked-by: default avatarAnton Vorontsov <cbouatmailru@gmail.com>
Signed-off-by: default avatarGrant Likely <grant.likely@secretlab.ca>
parent f9218c2a
...@@ -286,36 +286,12 @@ static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value) ...@@ -286,36 +286,12 @@ static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value)
} }
} }
static static int
int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
struct spi_device *spi,
struct mpc8xxx_spi *mpc8xxx_spi,
int bits_per_word)
{ {
struct mpc8xxx_spi *mpc8xxx_spi;
u8 bits_per_word, pm;
u32 hz;
struct spi_mpc8xxx_cs *cs = spi->controller_state;
mpc8xxx_spi = spi_master_get_devdata(spi->master);
if (t) {
bits_per_word = t->bits_per_word;
hz = t->speed_hz;
} else {
bits_per_word = 0;
hz = 0;
}
/* spi_transfer level calls that work per-word */
if (!bits_per_word)
bits_per_word = spi->bits_per_word;
/* Make sure its a bit width we support [4..16, 32] */
if ((bits_per_word < 4)
|| ((bits_per_word > 16) && (bits_per_word != 32)))
return -EINVAL;
if (!hz)
hz = spi->max_speed_hz;
cs->rx_shift = 0; cs->rx_shift = 0;
cs->tx_shift = 0; cs->tx_shift = 0;
if (bits_per_word <= 8) { if (bits_per_word <= 8) {
...@@ -339,19 +315,82 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -339,19 +315,82 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
return -EINVAL; return -EINVAL;
if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE && if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE &&
spi->mode & SPI_LSB_FIRST) { spi->mode & SPI_LSB_FIRST) {
cs->tx_shift = 0; cs->tx_shift = 0;
if (bits_per_word <= 8) if (bits_per_word <= 8)
cs->rx_shift = 8; cs->rx_shift = 8;
else else
cs->rx_shift = 0; cs->rx_shift = 0;
} }
mpc8xxx_spi->rx_shift = cs->rx_shift; mpc8xxx_spi->rx_shift = cs->rx_shift;
mpc8xxx_spi->tx_shift = cs->tx_shift; mpc8xxx_spi->tx_shift = cs->tx_shift;
mpc8xxx_spi->get_rx = cs->get_rx; mpc8xxx_spi->get_rx = cs->get_rx;
mpc8xxx_spi->get_tx = cs->get_tx; mpc8xxx_spi->get_tx = cs->get_tx;
return bits_per_word;
}
static int
mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
struct spi_device *spi,
int bits_per_word)
{
/* QE uses Little Endian for words > 8
* so transform all words > 8 into 8 bits
* Unfortnatly that doesn't work for LSB so
* reject these for now */
/* Note: 32 bits word, LSB works iff
* tfcr/rfcr is set to CPMFCR_GBL */
if (spi->mode & SPI_LSB_FIRST &&
bits_per_word > 8)
return -EINVAL;
if (bits_per_word > 8)
return 8; /* pretend its 8 bits */
return bits_per_word;
}
static
int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
{
struct mpc8xxx_spi *mpc8xxx_spi;
int bits_per_word;
u8 pm;
u32 hz;
struct spi_mpc8xxx_cs *cs = spi->controller_state;
mpc8xxx_spi = spi_master_get_devdata(spi->master);
if (t) {
bits_per_word = t->bits_per_word;
hz = t->speed_hz;
} else {
bits_per_word = 0;
hz = 0;
}
/* spi_transfer level calls that work per-word */
if (!bits_per_word)
bits_per_word = spi->bits_per_word;
/* Make sure its a bit width we support [4..16, 32] */
if ((bits_per_word < 4)
|| ((bits_per_word > 16) && (bits_per_word != 32)))
return -EINVAL;
if (!hz)
hz = spi->max_speed_hz;
if (!(mpc8xxx_spi->flags & SPI_CPM_MODE))
bits_per_word = mspi_apply_cpu_mode_quirks(cs, spi,
mpc8xxx_spi,
bits_per_word);
else if (mpc8xxx_spi->flags & SPI_QE)
bits_per_word = mspi_apply_qe_mode_quirks(cs, spi,
bits_per_word);
if (bits_per_word < 0)
return bits_per_word;
if (bits_per_word == 32) if (bits_per_word == 32)
bits_per_word = 0; bits_per_word = 0;
else else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment