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>
This commit is contained in:
parent
f9218c2a60
commit
0398fb7094
1 changed files with 74 additions and 35 deletions
|
@ -286,11 +286,75 @@ static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value)
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
|
||||
struct spi_device *spi,
|
||||
struct mpc8xxx_spi *mpc8xxx_spi,
|
||||
int bits_per_word)
|
||||
{
|
||||
cs->rx_shift = 0;
|
||||
cs->tx_shift = 0;
|
||||
if (bits_per_word <= 8) {
|
||||
cs->get_rx = mpc8xxx_spi_rx_buf_u8;
|
||||
cs->get_tx = mpc8xxx_spi_tx_buf_u8;
|
||||
if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
|
||||
cs->rx_shift = 16;
|
||||
cs->tx_shift = 24;
|
||||
}
|
||||
} else if (bits_per_word <= 16) {
|
||||
cs->get_rx = mpc8xxx_spi_rx_buf_u16;
|
||||
cs->get_tx = mpc8xxx_spi_tx_buf_u16;
|
||||
if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
|
||||
cs->rx_shift = 16;
|
||||
cs->tx_shift = 16;
|
||||
}
|
||||
} else if (bits_per_word <= 32) {
|
||||
cs->get_rx = mpc8xxx_spi_rx_buf_u32;
|
||||
cs->get_tx = mpc8xxx_spi_tx_buf_u32;
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE &&
|
||||
spi->mode & SPI_LSB_FIRST) {
|
||||
cs->tx_shift = 0;
|
||||
if (bits_per_word <= 8)
|
||||
cs->rx_shift = 8;
|
||||
else
|
||||
cs->rx_shift = 0;
|
||||
}
|
||||
mpc8xxx_spi->rx_shift = cs->rx_shift;
|
||||
mpc8xxx_spi->tx_shift = cs->tx_shift;
|
||||
mpc8xxx_spi->get_rx = cs->get_rx;
|
||||
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;
|
||||
u8 bits_per_word, pm;
|
||||
int bits_per_word;
|
||||
u8 pm;
|
||||
u32 hz;
|
||||
struct spi_mpc8xxx_cs *cs = spi->controller_state;
|
||||
|
||||
|
@ -316,41 +380,16 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
|
|||
if (!hz)
|
||||
hz = spi->max_speed_hz;
|
||||
|
||||
cs->rx_shift = 0;
|
||||
cs->tx_shift = 0;
|
||||
if (bits_per_word <= 8) {
|
||||
cs->get_rx = mpc8xxx_spi_rx_buf_u8;
|
||||
cs->get_tx = mpc8xxx_spi_tx_buf_u8;
|
||||
if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
|
||||
cs->rx_shift = 16;
|
||||
cs->tx_shift = 24;
|
||||
}
|
||||
} else if (bits_per_word <= 16) {
|
||||
cs->get_rx = mpc8xxx_spi_rx_buf_u16;
|
||||
cs->get_tx = mpc8xxx_spi_tx_buf_u16;
|
||||
if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
|
||||
cs->rx_shift = 16;
|
||||
cs->tx_shift = 16;
|
||||
}
|
||||
} else if (bits_per_word <= 32) {
|
||||
cs->get_rx = mpc8xxx_spi_rx_buf_u32;
|
||||
cs->get_tx = mpc8xxx_spi_tx_buf_u32;
|
||||
} else
|
||||
return -EINVAL;
|
||||
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 (mpc8xxx_spi->flags & SPI_QE_CPU_MODE &&
|
||||
spi->mode & SPI_LSB_FIRST) {
|
||||
cs->tx_shift = 0;
|
||||
if (bits_per_word <= 8)
|
||||
cs->rx_shift = 8;
|
||||
else
|
||||
cs->rx_shift = 0;
|
||||
}
|
||||
|
||||
mpc8xxx_spi->rx_shift = cs->rx_shift;
|
||||
mpc8xxx_spi->tx_shift = cs->tx_shift;
|
||||
mpc8xxx_spi->get_rx = cs->get_rx;
|
||||
mpc8xxx_spi->get_tx = cs->get_tx;
|
||||
if (bits_per_word < 0)
|
||||
return bits_per_word;
|
||||
|
||||
if (bits_per_word == 32)
|
||||
bits_per_word = 0;
|
||||
|
|
Loading…
Reference in a new issue