diff options
Diffstat (limited to 'drivers/spi/spi_mpc83xx.c')
-rw-r--r-- | drivers/spi/spi_mpc83xx.c | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c index e9798bf7b8c..3295cfcc9f2 100644 --- a/drivers/spi/spi_mpc83xx.c +++ b/drivers/spi/spi_mpc83xx.c @@ -47,6 +47,7 @@ struct mpc83xx_spi_reg { #define SPMODE_ENABLE (1 << 24) #define SPMODE_LEN(x) ((x) << 20) #define SPMODE_PM(x) ((x) << 16) +#define SPMODE_OP (1 << 14) /* * Default for SPI Mode: @@ -85,6 +86,11 @@ struct mpc83xx_spi { unsigned nsecs; /* (clock cycle time)/2 */ u32 sysclk; + u32 rx_shift; /* RX data reg shift when in qe mode */ + u32 tx_shift; /* TX data reg shift when in qe mode */ + + bool qe_mode; + void (*activate_cs) (u8 cs, u8 polarity); void (*deactivate_cs) (u8 cs, u8 polarity); }; @@ -103,7 +109,7 @@ static inline u32 mpc83xx_spi_read_reg(__be32 __iomem * reg) void mpc83xx_spi_rx_buf_##type(u32 data, struct mpc83xx_spi *mpc83xx_spi) \ { \ type * rx = mpc83xx_spi->rx; \ - *rx++ = (type)data; \ + *rx++ = (type)(data >> mpc83xx_spi->rx_shift); \ mpc83xx_spi->rx = rx; \ } @@ -114,7 +120,7 @@ u32 mpc83xx_spi_tx_buf_##type(struct mpc83xx_spi *mpc83xx_spi) \ const type * tx = mpc83xx_spi->tx; \ if (!tx) \ return 0; \ - data = *tx++; \ + data = *tx++ << mpc83xx_spi->tx_shift; \ mpc83xx_spi->tx = tx; \ return data; \ } @@ -158,6 +164,12 @@ static void mpc83xx_spi_chipselect(struct spi_device *spi, int value) if ((mpc83xx_spi->sysclk / spi->max_speed_hz) >= 64) { u8 pm = mpc83xx_spi->sysclk / (spi->max_speed_hz * 64); + if (pm > 0x0f) { + printk(KERN_WARNING "MPC83xx SPI: SPICLK can't be less then a SYSCLK/1024!\n" + "Requested SPICLK is %d Hz. Will use %d Hz instead.\n", + spi->max_speed_hz, mpc83xx_spi->sysclk / 1024); + pm = 0x0f; + } regval |= SPMODE_PM(pm) | SPMODE_DIV16; } else { u8 pm = mpc83xx_spi->sysclk / (spi->max_speed_hz * 4); @@ -197,12 +209,22 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) || ((bits_per_word > 16) && (bits_per_word != 32))) return -EINVAL; + mpc83xx_spi->rx_shift = 0; + mpc83xx_spi->tx_shift = 0; if (bits_per_word <= 8) { mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8; mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8; + if (mpc83xx_spi->qe_mode) { + mpc83xx_spi->rx_shift = 16; + mpc83xx_spi->tx_shift = 24; + } } else if (bits_per_word <= 16) { mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u16; mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u16; + if (mpc83xx_spi->qe_mode) { + mpc83xx_spi->rx_shift = 16; + mpc83xx_spi->tx_shift = 16; + } } else if (bits_per_word <= 32) { mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u32; mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u32; @@ -232,12 +254,21 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) return 0; } +/* the spi->mode bits understood by this driver: */ +#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH) + static int mpc83xx_spi_setup(struct spi_device *spi) { struct spi_bitbang *bitbang; struct mpc83xx_spi *mpc83xx_spi; int retval; + if (spi->mode & ~MODEBITS) { + dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", + spi->mode & ~MODEBITS); + return -EINVAL; + } + if (!spi->max_speed_hz) return -EINVAL; @@ -371,7 +402,6 @@ static int __init mpc83xx_spi_probe(struct platform_device *dev) ret = -ENODEV; goto free_master; } - mpc83xx_spi = spi_master_get_devdata(master); mpc83xx_spi->bitbang.master = spi_master_get(master); mpc83xx_spi->bitbang.chipselect = mpc83xx_spi_chipselect; @@ -380,9 +410,17 @@ static int __init mpc83xx_spi_probe(struct platform_device *dev) mpc83xx_spi->sysclk = pdata->sysclk; mpc83xx_spi->activate_cs = pdata->activate_cs; mpc83xx_spi->deactivate_cs = pdata->deactivate_cs; + mpc83xx_spi->qe_mode = pdata->qe_mode; mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8; mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8; + mpc83xx_spi->rx_shift = 0; + mpc83xx_spi->tx_shift = 0; + if (mpc83xx_spi->qe_mode) { + mpc83xx_spi->rx_shift = 16; + mpc83xx_spi->tx_shift = 24; + } + mpc83xx_spi->bitbang.master->setup = mpc83xx_spi_setup; init_completion(&mpc83xx_spi->done); @@ -417,6 +455,9 @@ static int __init mpc83xx_spi_probe(struct platform_device *dev) /* Enable SPI interface */ regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE; + if (pdata->qe_mode) + regval |= SPMODE_OP; + mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval); ret = spi_bitbang_start(&mpc83xx_spi->bitbang); |