summaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-mpc512x-psc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi-mpc512x-psc.c')
-rw-r--r--drivers/spi/spi-mpc512x-psc.c70
1 files changed, 47 insertions, 23 deletions
diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index 965d2bdcfdcc..1e75341689a6 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -30,11 +30,37 @@
#include <linux/gpio.h>
#include <asm/mpc52xx_psc.h>
+enum {
+ TYPE_MPC5121,
+ TYPE_MPC5125,
+};
+
+/*
+ * This macro abstracts the differences in the PSC register layout between
+ * MPC5121 (which uses a struct mpc52xx_psc) and MPC5125 (using mpc5125_psc).
+ */
+#define psc_addr(mps, regname) ({ \
+ void *__ret = NULL; \
+ switch (mps->type) { \
+ case TYPE_MPC5121: { \
+ struct mpc52xx_psc __iomem *psc = mps->psc; \
+ __ret = &psc->regname; \
+ }; \
+ break; \
+ case TYPE_MPC5125: { \
+ struct mpc5125_psc __iomem *psc = mps->psc; \
+ __ret = &psc->regname; \
+ }; \
+ break; \
+ } \
+ __ret; })
+
struct mpc512x_psc_spi {
void (*cs_control)(struct spi_device *spi, bool on);
/* driver internal data */
- struct mpc52xx_psc __iomem *psc;
+ int type;
+ void __iomem *psc;
struct mpc512x_psc_fifo __iomem *fifo;
unsigned int irq;
u8 bits_per_word;
@@ -71,13 +97,12 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
{
struct mpc512x_psc_spi_cs *cs = spi->controller_state;
struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
- struct mpc52xx_psc __iomem *psc = mps->psc;
u32 sicr;
u32 ccr;
int speed;
u16 bclkdiv;
- sicr = in_be32(&psc->sicr);
+ sicr = in_be32(psc_addr(mps, sicr));
/* Set clock phase and polarity */
if (spi->mode & SPI_CPHA)
@@ -94,9 +119,9 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
sicr |= 0x10000000;
else
sicr &= ~0x10000000;
- out_be32(&psc->sicr, sicr);
+ out_be32(psc_addr(mps, sicr), sicr);
- ccr = in_be32(&psc->ccr);
+ ccr = in_be32(psc_addr(mps, ccr));
ccr &= 0xFF000000;
speed = cs->speed_hz;
if (!speed)
@@ -104,7 +129,7 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
bclkdiv = (mps->mclk_rate / speed) - 1;
ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
- out_be32(&psc->ccr, ccr);
+ out_be32(psc_addr(mps, ccr), ccr);
mps->bits_per_word = cs->bits_per_word;
if (mps->cs_control && gpio_is_valid(spi->cs_gpio))
@@ -315,16 +340,15 @@ static int mpc512x_psc_spi_msg_xfer(struct spi_master *master,
static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master)
{
struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
- struct mpc52xx_psc __iomem *psc = mps->psc;
dev_dbg(&master->dev, "%s()\n", __func__);
/* Zero MR2 */
- in_8(&psc->mode);
- out_8(&psc->mode, 0x0);
+ in_8(psc_addr(mps, mr2));
+ out_8(psc_addr(mps, mr2), 0x0);
/* enable transmitter/receiver */
- out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
+ out_8(psc_addr(mps, command), MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
return 0;
}
@@ -332,13 +356,12 @@ static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master)
static int mpc512x_psc_spi_unprep_xfer_hw(struct spi_master *master)
{
struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
- struct mpc52xx_psc __iomem *psc = mps->psc;
struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
dev_dbg(&master->dev, "%s()\n", __func__);
/* disable transmitter/receiver and fifo interrupt */
- out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
+ out_8(psc_addr(mps, command), MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
out_be32(&fifo->tximr, 0);
return 0;
@@ -388,7 +411,6 @@ static void mpc512x_psc_spi_cleanup(struct spi_device *spi)
static int mpc512x_psc_spi_port_config(struct spi_master *master,
struct mpc512x_psc_spi *mps)
{
- struct mpc52xx_psc __iomem *psc = mps->psc;
struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
u32 sicr;
u32 ccr;
@@ -396,12 +418,12 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
u16 bclkdiv;
/* Reset the PSC into a known state */
- out_8(&psc->command, MPC52xx_PSC_RST_RX);
- out_8(&psc->command, MPC52xx_PSC_RST_TX);
- out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
+ out_8(psc_addr(mps, command), MPC52xx_PSC_RST_RX);
+ out_8(psc_addr(mps, command), MPC52xx_PSC_RST_TX);
+ out_8(psc_addr(mps, command), MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
/* Disable psc interrupts all useful interrupts are in fifo */
- out_be16(&psc->isr_imr.imr, 0);
+ out_be16(psc_addr(mps, isr_imr.imr), 0);
/* Disable fifo interrupts, will be enabled later */
out_be32(&fifo->tximr, 0);
@@ -417,18 +439,18 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
0x00004000 | /* MSTR = 1 -- SPI master */
0x00000800; /* UseEOF = 1 -- SS low until EOF */
- out_be32(&psc->sicr, sicr);
+ out_be32(psc_addr(mps, sicr), sicr);
- ccr = in_be32(&psc->ccr);
+ ccr = in_be32(psc_addr(mps, ccr));
ccr &= 0xFF000000;
speed = 1000000; /* default 1MHz */
bclkdiv = (mps->mclk_rate / speed) - 1;
ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
- out_be32(&psc->ccr, ccr);
+ out_be32(psc_addr(mps, ccr), ccr);
/* Set 2ms DTL delay */
- out_8(&psc->ctur, 0x00);
- out_8(&psc->ctlr, 0x82);
+ out_8(psc_addr(mps, ctur), 0x00);
+ out_8(psc_addr(mps, ctlr), 0x82);
/* we don't use the alarms */
out_be32(&fifo->rxalarm, 0xfff);
@@ -482,6 +504,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
dev_set_drvdata(dev, master);
mps = spi_master_get_devdata(master);
+ mps->type = (int)of_device_get_match_data(dev);
mps->irq = irq;
if (pdata == NULL) {
@@ -589,7 +612,8 @@ static int mpc512x_psc_spi_of_remove(struct platform_device *op)
}
static const struct of_device_id mpc512x_psc_spi_of_match[] = {
- { .compatible = "fsl,mpc5121-psc-spi", },
+ { .compatible = "fsl,mpc5121-psc-spi", .data = (void *)TYPE_MPC5121 },
+ { .compatible = "fsl,mpc5125-psc-spi", .data = (void *)TYPE_MPC5125 },
{},
};