The patch titled mpc52xx-psc-spi-master-driver update has been added to the -mm tree. Its filename is mpc52xx-psc-spi-master-driver-update.patch *** Remember to use Documentation/SubmitChecklist when testing your code *** See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find out what to do about this ------------------------------------------------------ Subject: mpc52xx-psc-spi-master-driver update From: Dragos Carp <dragos.carp@xxxxxxxxxxx> Related to your comments: I used the constants that were already defined in the mpc52xx.h or mpc52xx_psc.h. I could define them there, but this will be probably a different patch. I chose the bus number starting with 0, because I wanted to use the same rule as the mpc52xx_psc_uart driver, anyway using the OpenFirmware the bus number will be dynamic allocated based on the order in the configuration file. I also changed the name of the driver according to Documentation/powerpc/mpc52xx-device-tree-bindings.txt. The newlines were inserted and the inline-s removed. Cc: David Brownell <dbrownell@xxxxxxxxxxxxxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- drivers/spi/mpc52xx_psc_spi.c | 235 ++++++++++++++++++++++++++++---- 1 file changed, 206 insertions(+), 29 deletions(-) diff -puN drivers/spi/mpc52xx_psc_spi.c~mpc52xx-psc-spi-master-driver-update drivers/spi/mpc52xx_psc_spi.c --- a/drivers/spi/mpc52xx_psc_spi.c~mpc52xx-psc-spi-master-driver-update +++ a/drivers/spi/mpc52xx_psc_spi.c @@ -15,7 +15,13 @@ #include <linux/init.h> #include <linux/errno.h> #include <linux/interrupt.h> + +#if defined(CONFIG_PPC_MERGE) +#include <asm/of_platform.h> +#else #include <linux/platform_device.h> +#endif + #include <linux/workqueue.h> #include <linux/completion.h> #include <linux/io.h> @@ -36,6 +42,7 @@ struct mpc52xx_psc_spi { /* driver internal data */ struct mpc52xx_psc __iomem *psc; + unsigned int irq; u8 bits_per_word; u8 busy; @@ -70,7 +77,7 @@ static int mpc52xx_psc_spi_transfer_setu return 0; } -static inline void mpc52xx_psc_spi_activate_cs(struct spi_device *spi) +static void mpc52xx_psc_spi_activate_cs(struct spi_device *spi) { struct mpc52xx_psc_spi_cs *cs = spi->controller_state; struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master); @@ -114,7 +121,7 @@ static inline void mpc52xx_psc_spi_activ (spi->mode & SPI_CS_HIGH) ? 1 : 0); } -static inline void mpc52xx_psc_spi_deactivate_cs(struct spi_device *spi) +static void mpc52xx_psc_spi_deactivate_cs(struct spi_device *spi) { struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master); @@ -127,7 +134,7 @@ static inline void mpc52xx_psc_spi_deact /* wake up when 80% fifo full */ #define MPC52xx_PSC_RFALARM (MPC52xx_PSC_BUFSIZE * 20 / 100) -static inline int mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi, +static int mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi, struct spi_transfer *t) { struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master); @@ -309,21 +316,25 @@ static int mpc52xx_psc_spi_transfer(stru static void mpc52xx_psc_spi_cleanup(struct spi_device *spi) { - if (spi->controller_state) - kfree(spi->controller_state); + kfree(spi->controller_state); } 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; + struct mpc52xx_psc __iomem *psc = mps->psc; u32 ul; u32 mclken_div; int ret = 0; +#if defined(CONFIG_PPC_MERGE) + cdm = mpc52xx_find_and_map("mpc52xx-cdm"); + gpio = mpc52xx_find_and_map("mpc52xx-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; @@ -379,14 +390,6 @@ static int mpc52xx_psc_spi_port_config(i ret = -EINVAL; goto unmap_regs; } - psc = ioremap(MPC52xx_PA(MPC52xx_PSCx_OFFSET(psc_id)), - MPC52xx_PSC_SIZE); - if (!psc) { - printk(KERN_ERR "Error mapping PSC%d\n", psc_id); - ret = -EFAULT; - goto unmap_regs; - } - mps->psc = psc; /* Reset the PSC into a known state */ out_8(&psc->command, MPC52xx_PSC_RST_RX); @@ -399,7 +402,7 @@ static int mpc52xx_psc_spi_port_config(i out_8(&psc->rfcntl, 0); out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL); - /* Configure 8bit codec mode as an SPI master and use EOF flags */ + /* Configure 8bit codec mode as a SPI master and use EOF flags */ /* SICR_SIM_CODEC8|SICR_GENCLK|SICR_SPI|SICR_MSTR|SICR_USEEOF */ out_be32(&psc->sicr, 0x0180C800); out_be16(&psc->ccr, 0x070F); /* by default SPI Clk 1MHz */ @@ -411,8 +414,10 @@ static int mpc52xx_psc_spi_port_config(i mps->bits_per_word = 8; unmap_regs: - if (cdm) iounmap(cdm); - if (gpio) iounmap(gpio); + if (cdm) + iounmap(cdm); + if (gpio) + iounmap(gpio); return ret; } @@ -431,12 +436,13 @@ static irqreturn_t mpc52xx_psc_spi_isr(i return IRQ_NONE; } +#if !defined(CONFIG_PPC_MERGE) static int __init mpc52xx_psc_spi_probe(struct platform_device *dev) { struct fsl_spi_platform_data *pdata = dev->dev.platform_data; struct mpc52xx_psc_spi *mps; struct spi_master *master; - unsigned int irq = platform_get_irq(dev, 0); + struct mpc52xx_psc __iomem *psc; int ret; if (pdata == NULL) @@ -459,14 +465,32 @@ static int __init mpc52xx_psc_spi_probe( master->transfer = mpc52xx_psc_spi_transfer; master->cleanup = mpc52xx_psc_spi_cleanup; - ret = mpc52xx_psc_spi_port_config(dev->id, mps); - if (ret < 0) + switch(dev->id) { + case 1: case 2: case 3: case 6: + break; + default: + ret = -EINVAL; goto free_master; + } + psc = ioremap(MPC52xx_PA(MPC52xx_PSCx_OFFSET(dev->id)), + MPC52xx_PSC_SIZE); + if (!psc) { + printk(KERN_ERR "Error mapping PSC%d\n", dev->id); + ret = -EFAULT; + goto free_master; + } + mps->psc = psc; - ret = request_irq(irq, mpc52xx_psc_spi_isr, 0, "mpc52xx_psc_spi", mps); + mps->irq = platform_get_irq(dev, 0); + ret = request_irq(mps->irq, mpc52xx_psc_spi_isr, 0, + "mpc52xx-psc-spi", mps); if (ret) goto free_master; + ret = mpc52xx_psc_spi_port_config(dev->id, mps); + if (ret < 0) + goto free_irq; + spin_lock_init(&mps->lock); init_completion(&mps->done); INIT_WORK(&mps->work, mpc52xx_psc_spi_work); @@ -476,7 +500,7 @@ static int __init mpc52xx_psc_spi_probe( master->cdev.dev->bus_id); if (mps->workqueue == NULL) { ret = -EBUSY; - goto err_workq; + goto free_irq; } ret = spi_register_master(master); @@ -487,10 +511,11 @@ static int __init mpc52xx_psc_spi_probe( unreg_master: destroy_workqueue(mps->workqueue); -err_workq: - free_irq(irq, mps); +free_irq: + free_irq(mps->irq, mps); free_master: - if (mps->psc) iounmap(mps->psc); + if (mps->psc) + iounmap(mps->psc); spi_master_put(master); return ret; @@ -500,13 +525,13 @@ static int __exit mpc52xx_psc_spi_remove { struct spi_master *master = platform_get_drvdata(dev); struct mpc52xx_psc_spi *mps = spi_master_get_devdata(master); - unsigned int irq = platform_get_irq(dev, 0); flush_workqueue(mps->workqueue); destroy_workqueue(mps->workqueue); spi_unregister_master(master); - free_irq(irq, mps); - if (mps->psc) iounmap(mps->psc); + free_irq(mps->irq, mps); + if (mps->psc) + iounmap(mps->psc); return 0; } @@ -514,26 +539,178 @@ static int __exit mpc52xx_psc_spi_remove static struct platform_driver mpc52xx_psc_spi_platform_driver = { .remove = __exit_p(mpc52xx_psc_spi_remove), .driver = { - .name = "mpc52xx_psc_spi", + .name = "mpc52xx-psc-spi", .owner = THIS_MODULE, }, }; +#endif /* !defined(CONFIG_PPC_MERGE) */ +#if defined(CONFIG_PPC_MERGE) +static int __init mpc52xx_psc_spi_of_probe(struct of_device *op, + const struct of_device_id *match) +{ + struct device *dev = &op->dev; + struct fsl_spi_platform_data *pdata = dev->platform_data; + struct mpc52xx_psc_spi *mps; + struct spi_master *master; + int ret; + const u32 *regaddr_p; + u64 regaddr64, size64; + struct mpc52xx_psc __iomem *psc; + + if (dev == NULL) + return -ENODEV; + + master = spi_alloc_master(dev, sizeof *mps); + if (master == NULL) + return -ENOMEM; + dev_set_drvdata(dev, master); + mps = spi_master_get_devdata(master); + + regaddr_p = of_get_address(op->node, 0, &size64, NULL); + if (!regaddr_p) { + printk(KERN_ERR "Invalid PSC address\n"); + ret = -EINVAL; + goto free_master; + } + regaddr64 = of_translate_address(op->node, regaddr_p); + psc = ioremap((u32)regaddr64, (u32)size64); + if (!psc) { + printk(KERN_ERR "Error mapping memory at %x (%x bytes)\n", + (u32)regaddr64, (u32)size64); + ret = -EFAULT; + goto free_master; + } + mps->psc = psc; + + mps->irq = irq_of_parse_and_map(op->node, 0); + ret = request_irq(mps->irq, mpc52xx_psc_spi_isr, 0, + "mpc52xx-psc-spi", mps); + if (ret) + goto free_master; + + if (pdata == NULL) { + struct device_node *np; + int i = 0; + + dev_warn(dev, "probe called without platform data, no " + "(de)activate_cs function will be called\n"); + + mps->activate_cs = NULL; + mps->deactivate_cs = NULL; + mps->sysclk = 0; + master->bus_num = -1; + for_each_node_by_type(np, "spi") { + if (of_find_device_by_node(np) == op) { + master->bus_num = i; + break; + } + i++; + } + master->num_chipselect = 255; + } else { + mps->activate_cs = pdata->activate_cs; + mps->deactivate_cs = pdata->deactivate_cs; + mps->sysclk = pdata->sysclk; + master->bus_num = pdata->bus_num; + master->num_chipselect = pdata->max_chipselect; + } + master->setup = mpc52xx_psc_spi_setup; + master->transfer = mpc52xx_psc_spi_transfer; + master->cleanup = mpc52xx_psc_spi_cleanup; + + ret = mpc52xx_psc_spi_port_config(master->bus_num, mps); + if (ret < 0) + goto free_irq; + + spin_lock_init(&mps->lock); + init_completion(&mps->done); + INIT_WORK(&mps->work, mpc52xx_psc_spi_work); + INIT_LIST_HEAD(&mps->queue); + + mps->workqueue = create_singlethread_workqueue( + master->cdev.dev->bus_id); + if (mps->workqueue == NULL) { + ret = -EBUSY; + goto free_irq; + } + + ret = spi_register_master(master); + if (ret < 0) + goto unreg_master; + + return ret; + +unreg_master: + destroy_workqueue(mps->workqueue); +free_irq: + free_irq(mps->irq, mps); +free_master: + if (mps->psc) + iounmap(mps->psc); + spi_master_put(master); + + return ret; +} + +static int __exit mpc52xx_psc_spi_of_remove(struct of_device *op) +{ + struct spi_master *master = dev_get_drvdata(&op->dev); + struct mpc52xx_psc_spi *mps = spi_master_get_devdata(master); + + flush_workqueue(mps->workqueue); + destroy_workqueue(mps->workqueue); + spi_unregister_master(master); + free_irq(mps->irq, mps); + if (mps->psc) + iounmap(mps->psc); + + return 0; +} + +static struct of_device_id mpc52xx_psc_spi_of_match[] = { + { .type = "spi", .compatible = "mpc52xx-psc-spi", }, + {}, +}; + +MODULE_DEVICE_TABLE(of, mpc52xx_psc_spi_of_match); + +static struct of_platform_driver mpc52xx_psc_spi_of_driver = { + .owner = THIS_MODULE, + .name = "mpc52xx-psc-spi", + .match_table = mpc52xx_psc_spi_of_match, + .probe = mpc52xx_psc_spi_of_probe, + .remove = __exit_p(mpc52xx_psc_spi_of_remove), + .driver = { + .name = "mpc52xx-psc-spi", + .owner = THIS_MODULE, + }, +}; +#endif /* defined(CONFIG_PPC_MERGE) */ + /* ======================================================================== */ /* Module */ /* ======================================================================== */ static int __init mpc52xx_psc_spi_init(void) { +#if defined(CONFIG_PPC_MERGE) + return of_register_platform_driver(&mpc52xx_psc_spi_of_driver); +#else return platform_driver_probe(&mpc52xx_psc_spi_platform_driver, mpc52xx_psc_spi_probe); +#endif } module_init(mpc52xx_psc_spi_init); static void __exit mpc52xx_psc_spi_exit(void) { +#if defined(CONFIG_PPC_MERGE) + of_unregister_platform_driver(&mpc52xx_psc_spi_of_driver); +#else platform_driver_unregister(&mpc52xx_psc_spi_platform_driver); +#endif } module_exit(mpc52xx_psc_spi_exit); _ Patches currently in -mm which might be from dragos.carp@xxxxxxxxxxx are mpc52xx-psc-spi-master-driver.patch mpc52xx-psc-spi-master-driver-update.patch - To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html