/*
- * MPC52xx SPC in SPI mode driver.
+ * MPC52xx PSC in SPI mode driver.
*
* Maintainer: Dragos Carp
*
/* driver internal data */
struct mpc52xx_psc __iomem *psc;
+ struct mpc52xx_psc_fifo __iomem *fifo;
unsigned int irq;
u8 bits_per_word;
u8 busy;
{
struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
struct mpc52xx_psc __iomem *psc = mps->psc;
+ struct mpc52xx_psc_fifo __iomem *fifo = mps->fifo;
unsigned rb = 0; /* number of bytes receieved */
unsigned sb = 0; /* number of bytes sent */
unsigned char *rx_buf = (unsigned char *)t->rx_buf;
}
- /* enable interupts and wait for wake up
+ /* enable interrupts and wait for wake up
* if just one byte is expected the Rx FIFO genererates no
* FFULL interrupt, so activate the RxRDY interrupt
*/
out_8(&psc->mode, 0);
} else {
out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL);
- out_be16(&psc->rfalarm, rfalarm);
+ out_be16(&fifo->rfalarm, rfalarm);
}
out_be16(&psc->mpc52xx_psc_imr, MPC52xx_PSC_IMR_RXRDY);
wait_for_completion(&mps->done);
- recv_at_once = in_be16(&psc->rfnum);
+ recv_at_once = in_be16(&fifo->rfnum);
dev_dbg(&spi->dev, "%d bytes received\n", recv_at_once);
send_at_once = recv_at_once;
spin_unlock_irq(&mps->lock);
}
+/* the spi->mode bits understood by this driver: */
+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST)
+
static int mpc52xx_psc_spi_setup(struct spi_device *spi)
{
struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
if (spi->bits_per_word%8)
return -EINVAL;
+ if (spi->mode & ~MODEBITS) {
+ dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+ spi->mode & ~MODEBITS);
+ return -EINVAL;
+ }
+
if (!cs) {
cs = kzalloc(sizeof *cs, GFP_KERNEL);
if (!cs)
static int mpc52xx_psc_spi_port_config(int psc_id, struct mpc52xx_psc_spi *mps)
{
- struct mpc52xx_cdm __iomem *cdm;
- struct mpc52xx_gpio __iomem *gpio;
struct mpc52xx_psc __iomem *psc = mps->psc;
- u32 ul;
+ struct mpc52xx_psc_fifo __iomem *fifo = mps->fifo;
u32 mclken_div;
int ret = 0;
-#if defined(CONFIG_PPC_MERGE)
- cdm = mpc52xx_find_and_map("mpc5200-cdm");
- gpio = mpc52xx_find_and_map("mpc5200-gpio");
-#else
- cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
- gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE);
-#endif
- if (!cdm || !gpio) {
- printk(KERN_ERR "Error mapping CDM/GPIO\n");
- ret = -EFAULT;
- goto unmap_regs;
- }
-
/* default sysclk is 512MHz */
- mclken_div = 0x8000 |
- (((mps->sysclk ? mps->sysclk : 512000000) / MCLK) & 0x1FF);
-
- switch (psc_id) {
- case 1:
- ul = in_be32(&gpio->port_config);
- ul &= 0xFFFFFFF8;
- ul |= 0x00000006;
- out_be32(&gpio->port_config, ul);
- out_be16(&cdm->mclken_div_psc1, mclken_div);
- ul = in_be32(&cdm->clk_enables);
- ul |= 0x00000020;
- out_be32(&cdm->clk_enables, ul);
- break;
- case 2:
- ul = in_be32(&gpio->port_config);
- ul &= 0xFFFFFF8F;
- ul |= 0x00000060;
- out_be32(&gpio->port_config, ul);
- out_be16(&cdm->mclken_div_psc2, mclken_div);
- ul = in_be32(&cdm->clk_enables);
- ul |= 0x00000040;
- out_be32(&cdm->clk_enables, ul);
- break;
- case 3:
- ul = in_be32(&gpio->port_config);
- ul &= 0xFFFFF0FF;
- ul |= 0x00000600;
- out_be32(&gpio->port_config, ul);
- out_be16(&cdm->mclken_div_psc3, mclken_div);
- ul = in_be32(&cdm->clk_enables);
- ul |= 0x00000080;
- out_be32(&cdm->clk_enables, ul);
- break;
- case 6:
- ul = in_be32(&gpio->port_config);
- ul &= 0xFF8FFFFF;
- ul |= 0x00700000;
- out_be32(&gpio->port_config, ul);
- out_be16(&cdm->mclken_div_psc6, mclken_div);
- ul = in_be32(&cdm->clk_enables);
- ul |= 0x00000010;
- out_be32(&cdm->clk_enables, ul);
- break;
- default:
- ret = -EINVAL;
- goto unmap_regs;
- }
+ mclken_div = (mps->sysclk ? mps->sysclk : 512000000) / MCLK;
+ mpc52xx_set_psc_clkdiv(psc_id, mclken_div);
/* Reset the PSC into a known state */
out_8(&psc->command, MPC52xx_PSC_RST_RX);
/* Disable interrupts, interrupts are based on alarm level */
out_be16(&psc->mpc52xx_psc_imr, 0);
out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
- out_8(&psc->rfcntl, 0);
+ out_8(&fifo->rfcntl, 0);
out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL);
/* Configure 8bit codec mode as a SPI master and use EOF flags */
mps->bits_per_word = 8;
-unmap_regs:
- if (cdm)
- iounmap(cdm);
- if (gpio)
- iounmap(gpio);
-
return ret;
}
ret = -EFAULT;
goto free_master;
}
+ /* On the 5200, fifo regs are immediately ajacent to the psc regs */
+ mps->fifo = ((void __iomem *)mps->psc) + sizeof(struct mpc52xx_psc);
ret = request_irq(mps->irq, mpc52xx_psc_spi_isr, 0, "mpc52xx-psc-spi",
mps);
INIT_LIST_HEAD(&mps->queue);
mps->workqueue = create_singlethread_workqueue(
- master->cdev.dev->bus_id);
+ master->dev.parent->bus_id);
if (mps->workqueue == NULL) {
ret = -EBUSY;
goto free_irq;
return mpc52xx_psc_spi_do_remove(&dev->dev);
}
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:mpc52xx-psc-spi");
+
static struct platform_driver mpc52xx_psc_spi_platform_driver = {
.remove = __exit_p(mpc52xx_psc_spi_remove),
.driver = {
}
static struct of_device_id mpc52xx_psc_spi_of_match[] = {
- { .type = "spi", .compatible = "mpc5200-psc-spi", },
- {},
+ { .compatible = "fsl,mpc5200-psc-spi", },
+ { .compatible = "mpc5200-psc-spi", }, /* old */
+ {}
};
MODULE_DEVICE_TABLE(of, mpc52xx_psc_spi_of_match);