diff options
Diffstat (limited to 'drivers/spi/spi-mpc512x-psc.c')
-rw-r--r-- | drivers/spi/spi-mpc512x-psc.c | 70 |
1 files changed, 47 insertions, 23 deletions
diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c index 965d2bdcf..1e7534168 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 }, {}, }; |