From: Magnus Damm <[email protected]>

This hack simply converts struct spi_bitbang from
containing a struct master * to containing the actual
structure itself. This allows us to use container_of()
in spi_bitbang_setup() and spi_bitbang_transfer().

Together with this are the functions spi_init_master()
and spi_bitbang_init() for initialization of static
structures. The idea is that spi_master_release() never
should be invoked, but not sure if I got that right.

Only the drivers spi_gpio.c and spi_sh_msiof.c are converted
at this point. If this seems like a good idea then we should
do this step by step and all drivers should be modified.

Dry coded only at this point.

Signed-off-by: Magnus Damm <[email protected]>
---

 drivers/spi/spi.c               |   17 ++++++++++++++---
 drivers/spi/spi_bitbang.c       |   39 ++++++++++++++++++++++++---------------
 drivers/spi/spi_gpio.c          |   15 ++++++++-------
 drivers/spi/spi_sh_msiof.c      |   18 +++++++++---------
 include/linux/spi/spi.h         |    1 +
 include/linux/spi/spi_bitbang.h |    4 +++-
 6 files changed, 59 insertions(+), 35 deletions(-)

--- 0001/drivers/spi/spi.c
+++ work/drivers/spi/spi.c      2009-12-02 13:57:02.000000000 +0900
@@ -441,6 +441,19 @@ static struct class spi_master_class = {
 
 
 /**
+ * spi_init_master - init SPI master controller
+ * @master: master to initialize
+ * @dev: the controller device
+ */
+void spi_init_master(struct spi_master *master, struct device *dev)
+{
+       device_initialize(&master->dev);
+       master->dev.class = &spi_master_class;
+       master->dev.parent = get_device(dev);
+}
+EXPORT_SYMBOL_GPL(spi_init_master);
+
+/**
  * spi_alloc_master - allocate SPI master controller
  * @dev: the controller, possibly using the platform_bus
  * @size: how much zeroed driver-private data to allocate; the pointer to this
@@ -470,9 +483,7 @@ struct spi_master *spi_alloc_master(stru
        if (!master)
                return NULL;
 
-       device_initialize(&master->dev);
-       master->dev.class = &spi_master_class;
-       master->dev.parent = get_device(dev);
+       spi_init_master(master, dev);
        spi_master_set_devdata(master, &master[1]);
 
        return master;
--- 0001/drivers/spi/spi_bitbang.c
+++ work/drivers/spi/spi_bitbang.c      2009-12-02 13:59:26.000000000 +0900
@@ -186,7 +186,7 @@ int spi_bitbang_setup(struct spi_device 
        int                     retval;
        unsigned long           flags;
 
-       bitbang = spi_master_get_devdata(spi->master);
+       bitbang = container_of(spi->master, struct spi_bitbang, master);
 
        if (!cs) {
                cs = kzalloc(sizeof *cs, GFP_KERNEL);
@@ -398,8 +398,7 @@ int spi_bitbang_transfer(struct spi_devi
 
        m->actual_length = 0;
        m->status = -EINPROGRESS;
-
-       bitbang = spi_master_get_devdata(spi->master);
+       bitbang = container_of(spi->master, struct spi_bitbang, master);
 
        spin_lock_irqsave(&bitbang->lock, flags);
        if (!spi->max_speed_hz)
@@ -443,35 +442,35 @@ int spi_bitbang_start(struct spi_bitbang
 {
        int     status;
 
-       if (!bitbang->master || !bitbang->chipselect)
+       if (!bitbang->chipselect)
                return -EINVAL;
 
        INIT_WORK(&bitbang->work, bitbang_work);
        spin_lock_init(&bitbang->lock);
        INIT_LIST_HEAD(&bitbang->queue);
 
-       if (!bitbang->master->mode_bits)
-               bitbang->master->mode_bits = SPI_CPOL | SPI_CPHA | 
bitbang->flags;
+       if (!bitbang->master.mode_bits)
+               bitbang->master.mode_bits = SPI_CPOL | SPI_CPHA | 
bitbang->flags;
 
-       if (!bitbang->master->transfer)
-               bitbang->master->transfer = spi_bitbang_transfer;
+       if (!bitbang->master.transfer)
+               bitbang->master.transfer = spi_bitbang_transfer;
        if (!bitbang->txrx_bufs) {
                bitbang->use_dma = 0;
                bitbang->txrx_bufs = spi_bitbang_bufs;
-               if (!bitbang->master->setup) {
+               if (!bitbang->master.setup) {
                        if (!bitbang->setup_transfer)
                                bitbang->setup_transfer =
                                         spi_bitbang_setup_transfer;
-                       bitbang->master->setup = spi_bitbang_setup;
-                       bitbang->master->cleanup = spi_bitbang_cleanup;
+                       bitbang->master.setup = spi_bitbang_setup;
+                       bitbang->master.cleanup = spi_bitbang_cleanup;
                }
-       } else if (!bitbang->master->setup)
+       } else if (!bitbang->master.setup)
                return -EINVAL;
 
        /* this task is the only thing to touch the SPI bits */
        bitbang->busy = 0;
        bitbang->workqueue = create_singlethread_workqueue(
-                       dev_name(bitbang->master->dev.parent));
+                       dev_name(bitbang->master.dev.parent));
        if (bitbang->workqueue == NULL) {
                status = -EBUSY;
                goto err1;
@@ -480,7 +479,7 @@ int spi_bitbang_start(struct spi_bitbang
        /* driver may get busy before register() returns, especially
         * if someone registered boardinfo for devices
         */
-       status = spi_register_master(bitbang->master);
+       status = spi_register_master(&bitbang->master);
        if (status < 0)
                goto err2;
 
@@ -498,7 +497,7 @@ EXPORT_SYMBOL_GPL(spi_bitbang_start);
  */
 int spi_bitbang_stop(struct spi_bitbang *bitbang)
 {
-       spi_unregister_master(bitbang->master);
+       spi_unregister_master(&bitbang->master);
 
        WARN_ON(!list_empty(&bitbang->queue));
 
@@ -508,5 +507,15 @@ int spi_bitbang_stop(struct spi_bitbang 
 }
 EXPORT_SYMBOL_GPL(spi_bitbang_stop);
 
+/**
+ * spi_bitbang_init - init SPI bitbang controller
+ */
+void spi_bitbang_init(struct spi_bitbang *bitbang, struct device *dev)
+{
+       spi_init_master(&bitbang->master, dev);
+}
+EXPORT_SYMBOL_GPL(spi_bitbang_init);
+
+
 MODULE_LICENSE("GPL");
 
--- 0001/drivers/spi/spi_gpio.c
+++ work/drivers/spi/spi_gpio.c 2009-12-02 14:05:39.000000000 +0900
@@ -278,24 +278,26 @@ static int __init spi_gpio_probe(struct 
        if (status < 0)
                return status;
 
-       master = spi_alloc_master(&pdev->dev, sizeof *spi_gpio);
-       if (!master) {
+       spi_gpio = kzalloc(sizeof(struct spi_gpio), GFP_KERNEL);
+       if (!spi_gpio) {
                status = -ENOMEM;
                goto gpio_free;
        }
-       spi_gpio = spi_master_get_devdata(master);
+
+       spi_bitbang_init(&spi_gpio->bitbang, &pdev->dev);
+       spi_master_set_devdata(&spi_gpio->bitbang.master, spi_gpio);
        platform_set_drvdata(pdev, spi_gpio);
 
        spi_gpio->pdev = pdev;
        if (pdata)
                spi_gpio->pdata = *pdata;
 
+       master = &spi_gpio->bitbang.master;
        master->bus_num = pdev->id;
        master->num_chipselect = SPI_N_CHIPSEL;
        master->setup = spi_gpio_setup;
        master->cleanup = spi_gpio_cleanup;
 
-       spi_gpio->bitbang.master = spi_master_get(master);
        spi_gpio->bitbang.chipselect = spi_gpio_chipselect;
        spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0;
        spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1;
@@ -306,12 +308,11 @@ static int __init spi_gpio_probe(struct 
 
        status = spi_bitbang_start(&spi_gpio->bitbang);
        if (status < 0) {
-               spi_master_put(spi_gpio->bitbang.master);
 gpio_free:
                gpio_free(SPI_MISO_GPIO);
                gpio_free(SPI_MOSI_GPIO);
                gpio_free(SPI_SCK_GPIO);
-               spi_master_put(master);
+               kfree(spi_gpio);
        }
 
        return status;
@@ -328,7 +329,7 @@ static int __exit spi_gpio_remove(struct
 
        /* stop() unregisters child devices too */
        status = spi_bitbang_stop(&spi_gpio->bitbang);
-       spi_master_put(spi_gpio->bitbang.master);
+       kfree(spi_gpio);
 
        platform_set_drvdata(pdev, NULL);
 
--- 0010/drivers/spi/spi_sh_msiof.c
+++ work/drivers/spi/spi_sh_msiof.c     2009-12-02 14:00:30.000000000 +0900
@@ -29,7 +29,7 @@
 #include <asm/unaligned.h>
 
 struct sh_msiof_spi_priv {
-       struct spi_bitbang bitbang; /* must be first for spi_bitbang.c */
+       struct spi_bitbang bitbang;
        void __iomem *mapbase;
        struct clk *clk;
        struct platform_device *pdev;
@@ -542,15 +542,15 @@ static int sh_msiof_spi_probe(struct pla
        int i;
        int ret;
 
-       master = spi_alloc_master(&pdev->dev, sizeof(struct sh_msiof_spi_priv));
-       if (master == NULL) {
-               dev_err(&pdev->dev, "failed to allocate spi master\n");
+       p = kzalloc(sizeof(struct sh_msiof_spi_priv), GFP_KERNEL);
+       if (!p) {
+               dev_err(&pdev->dev, "failed to allocate private spi data\n");
                ret = -ENOMEM;
                goto err0;
        }
 
-       p = spi_master_get_devdata(master);
-
+       spi_bitbang_init(&p->bitbang, &pdev->dev);
+       spi_master_set_devdata(&p->bitbang.master, p);
        platform_set_drvdata(pdev, p);
        p->info = pdev->dev.platform_data;
        init_completion(&p->done);
@@ -604,6 +604,7 @@ static int sh_msiof_spi_probe(struct pla
                p->rx_fifo_size = p->info->rx_fifo_override;
 
        /* init master and bitbang code */
+       master = &p->bitbang.master;
        master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
        master->mode_bits |= SPI_LSB_FIRST | SPI_3WIRE;
        master->flags = 0;
@@ -612,7 +613,6 @@ static int sh_msiof_spi_probe(struct pla
        master->setup = spi_bitbang_setup;
        master->cleanup = spi_bitbang_cleanup;
 
-       p->bitbang.master = master;
        p->bitbang.chipselect = sh_msiof_spi_chipselect;
        p->bitbang.setup_transfer = sh_msiof_spi_setup_transfer;
        p->bitbang.txrx_bufs = sh_msiof_spi_txrx;
@@ -631,7 +631,7 @@ static int sh_msiof_spi_probe(struct pla
  err2:
        clk_put(p->clk);
  err1:
-       spi_master_put(master);
+       kfree(p);
  err0:
        return ret;
 }
@@ -647,7 +647,7 @@ static int sh_msiof_spi_remove(struct pl
                free_irq(platform_get_irq(pdev, 0), sh_msiof_spi_irq);
                iounmap(p->mapbase);
                clk_put(p->clk);
-               spi_master_put(p->bitbang.master);
+               kfree(p);
        }
        return ret;
 }
--- 0001/include/linux/spi/spi.h
+++ work/include/linux/spi/spi.h        2009-12-02 13:42:23.000000000 +0900
@@ -320,6 +320,7 @@ static inline void spi_master_put(struct
 
 
 /* the spi driver core manages memory for the spi_master classdev */
+extern void spi_init_master(struct spi_master *master, struct device *dev);
 extern struct spi_master *
 spi_alloc_master(struct device *host, unsigned size);
 
--- 0001/include/linux/spi/spi_bitbang.h
+++ work/include/linux/spi/spi_bitbang.h        2009-12-02 13:59:43.000000000 
+0900
@@ -31,7 +31,7 @@ struct spi_bitbang {
        u8                      use_dma;
        u8                      flags;          /* extra spi->mode support */
 
-       struct spi_master       *master;
+       struct spi_master       master;
 
        /* setup_transfer() changes clock and/or wordsize to match settings
         * for this transfer; zeroes restore defaults from spi_device.
@@ -67,6 +67,8 @@ extern int spi_bitbang_setup_transfer(st
 extern int spi_bitbang_start(struct spi_bitbang *spi);
 extern int spi_bitbang_stop(struct spi_bitbang *spi);
 
+extern void spi_bitbang_init(struct spi_bitbang *bitbang, struct device *dev);
+
 #endif /* __SPI_BITBANG_H */
 
 /*-------------------------------------------------------------------------*/

------------------------------------------------------------------------------
Join us December 9, 2009 for the Red Hat Virtual Experience,
a free event focused on virtualization and cloud computing. 
Attend in-depth sessions from your desk. Your couch. Anywhere.
http://p.sf.net/sfu/redhat-sfdev2dev
_______________________________________________
spi-devel-general mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/spi-devel-general

Reply via email to