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 <[EMAIL PROTECTED]>
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 <[EMAIL PROTECTED]>
Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
---
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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html