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
@ -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
|
static
|
||||||
int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
|
int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
|
||||||
{
|
{
|
||||||
struct mpc8xxx_spi *mpc8xxx_spi;
|
struct mpc8xxx_spi *mpc8xxx_spi;
|
||||||
u8 bits_per_word, pm;
|
int bits_per_word;
|
||||||
|
u8 pm;
|
||||||
u32 hz;
|
u32 hz;
|
||||||
struct spi_mpc8xxx_cs *cs = spi->controller_state;
|
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)
|
if (!hz)
|
||||||
hz = spi->max_speed_hz;
|
hz = spi->max_speed_hz;
|
||||||
|
|
||||||
cs->rx_shift = 0;
|
if (!(mpc8xxx_spi->flags & SPI_CPM_MODE))
|
||||||
cs->tx_shift = 0;
|
bits_per_word = mspi_apply_cpu_mode_quirks(cs, spi,
|
||||||
if (bits_per_word <= 8) {
|
mpc8xxx_spi,
|
||||||
cs->get_rx = mpc8xxx_spi_rx_buf_u8;
|
bits_per_word);
|
||||||
cs->get_tx = mpc8xxx_spi_tx_buf_u8;
|
else if (mpc8xxx_spi->flags & SPI_QE)
|
||||||
if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
|
bits_per_word = mspi_apply_qe_mode_quirks(cs, spi,
|
||||||
cs->rx_shift = 16;
|
bits_per_word);
|
||||||
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 &&
|
if (bits_per_word < 0)
|
||||||
spi->mode & SPI_LSB_FIRST) {
|
return bits_per_word;
|
||||||
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 == 32)
|
if (bits_per_word == 32)
|
||||||
bits_per_word = 0;
|
bits_per_word = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user