]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge branch 'broonie/spi-next' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorGrant Likely <grant.likely@secretlab.ca>
Tue, 5 Feb 2013 12:30:13 +0000 (12:30 +0000)
committerGrant Likely <grant.likely@secretlab.ca>
Tue, 5 Feb 2013 12:30:13 +0000 (12:30 +0000)
Minor features and bug fixes for PXA, OMAP and GPIO deivce drivers and a
cosmetic change to the bitbang driver.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
12 files changed:
MAINTAINERS
drivers/spi/Kconfig
drivers/spi/spi-bitbang.c
drivers/spi/spi-gpio.c
drivers/spi/spi-omap2-mcspi.c
drivers/spi/spi-pxa2xx-pci.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-s3c64xx.c
include/linux/platform_data/spi-omap2-mcspi.h
include/linux/pxa2xx_ssp.h
include/linux/spi/pxa2xx_spi.h
include/linux/spi/spi_gpio.h

index 212c255b93472ada8cba2016b014eea3b7aa8369..1a747dde9bcb01e65c932b2f85313e94b7e03346 100644 (file)
@@ -7178,6 +7178,7 @@ F:        drivers/clk/spear/
 
 SPI SUBSYSTEM
 M:     Grant Likely <grant.likely@secretlab.ca>
+M:     Mark Brown <broonie@opensource.wolfsonmicro.com>
 L:     spi-devel-general@lists.sourceforge.net
 Q:     http://patchwork.kernel.org/project/spi-devel-general/list/
 T:     git git://git.secretlab.ca/git/linux-2.6.git
index 2e188e1127ebdbc94853f41ce86e488ced1acb1f..a90393d7f1067a699b4d2e23f6057269cf527ae2 100644 (file)
@@ -299,7 +299,7 @@ config SPI_PPC4xx
 
 config SPI_PXA2XX
        tristate "PXA2xx SSP SPI master"
-       depends on (ARCH_PXA || (X86_32 && PCI)) && EXPERIMENTAL
+       depends on ARCH_PXA || PCI
        select PXA_SSP if ARCH_PXA
        help
          This enables using a PXA2xx or Sodaville SSP port as a SPI master
@@ -307,7 +307,7 @@ config SPI_PXA2XX
          additional documentation can be found a Documentation/spi/pxa2xx.
 
 config SPI_PXA2XX_PCI
-       def_bool SPI_PXA2XX && X86_32 && PCI
+       def_tristate SPI_PXA2XX && PCI
 
 config SPI_RSPI
        tristate "Renesas RSPI controller"
index 61beaec7cbed46ad4fbfbcd5bd935bc2a03c3b02..a63d7da3bfe2209bebd921bfc81cdafb5d0a8cfd 100644 (file)
@@ -427,40 +427,41 @@ EXPORT_SYMBOL_GPL(spi_bitbang_transfer);
  */
 int spi_bitbang_start(struct spi_bitbang *bitbang)
 {
-       int     status;
+       struct spi_master *master = bitbang->master;
+       int status;
 
-       if (!bitbang->master || !bitbang->chipselect)
+       if (!master || !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 (!master->mode_bits)
+               master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags;
 
-       if (!bitbang->master->transfer)
-               bitbang->master->transfer = spi_bitbang_transfer;
+       if (!master->transfer)
+               master->transfer = spi_bitbang_transfer;
        if (!bitbang->txrx_bufs) {
                bitbang->use_dma = 0;
                bitbang->txrx_bufs = spi_bitbang_bufs;
-               if (!bitbang->master->setup) {
+               if (!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;
+                       master->setup = spi_bitbang_setup;
+                       master->cleanup = spi_bitbang_cleanup;
                }
-       } else if (!bitbang->master->setup)
+       } else if (!master->setup)
                return -EINVAL;
-       if (bitbang->master->transfer == spi_bitbang_transfer &&
+       if (master->transfer == spi_bitbang_transfer &&
                        !bitbang->setup_transfer)
                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(master->dev.parent));
        if (bitbang->workqueue == NULL) {
                status = -EBUSY;
                goto err1;
@@ -469,7 +470,7 @@ int spi_bitbang_start(struct spi_bitbang *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(master);
        if (status < 0)
                goto err2;
 
index c7cf0b7a069b7e5f88be75b3d88daa53e251cd53..9ddef55a716549422f00b11b1eca8603428873cf 100644 (file)
@@ -365,9 +365,26 @@ static int spi_gpio_probe_dt(struct platform_device *pdev)
        if (!pdata)
                return -ENOMEM;
 
-       pdata->sck = of_get_named_gpio(np, "gpio-sck", 0);
-       pdata->miso = of_get_named_gpio(np, "gpio-miso", 0);
-       pdata->mosi = of_get_named_gpio(np, "gpio-mosi", 0);
+       ret = of_get_named_gpio(np, "gpio-sck", 0);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "gpio-sck property not found\n");
+               goto error_free;
+       }
+       pdata->sck = ret;
+
+       ret = of_get_named_gpio(np, "gpio-miso", 0);
+       if (ret < 0) {
+               dev_info(&pdev->dev, "gpio-miso property not found, switching to no-rx mode\n");
+               pdata->miso = SPI_GPIO_NO_MISO;
+       } else
+               pdata->miso = ret;
+
+       ret = of_get_named_gpio(np, "gpio-mosi", 0);
+       if (ret < 0) {
+               dev_info(&pdev->dev, "gpio-mosi property not found, switching to no-tx mode\n");
+               pdata->mosi = SPI_GPIO_NO_MOSI;
+       } else
+               pdata->mosi = ret;
 
        ret = of_property_read_u32(np, "num-chipselects", &tmp);
        if (ret < 0) {
index 68446dbd554586b36ca1f449f076dbeca976155d..69945b014c969093f57e4a207f498ec287a75eb5 100644 (file)
@@ -927,6 +927,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
 
        struct spi_device               *spi;
        struct spi_transfer             *t = NULL;
+       struct spi_master               *master;
        int                             cs_active = 0;
        struct omap2_mcspi_cs           *cs;
        struct omap2_mcspi_device_config *cd;
@@ -935,6 +936,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
        u32                             chconf;
 
        spi = m->spi;
+       master = spi->master;
        cs = spi->controller_state;
        cd = spi->controller_data;
 
@@ -952,6 +954,14 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
                        if (!t->speed_hz && !t->bits_per_word)
                                par_override = 0;
                }
+               if (cd && cd->cs_per_word) {
+                       chconf = mcspi->ctx.modulctrl;
+                       chconf &= ~OMAP2_MCSPI_MODULCTRL_SINGLE;
+                       mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, chconf);
+                       mcspi->ctx.modulctrl =
+                               mcspi_read_cs_reg(spi, OMAP2_MCSPI_MODULCTRL);
+               }
+
 
                if (!cs_active) {
                        omap2_mcspi_force_cs(spi, 1);
@@ -1013,6 +1023,14 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
        if (cs_active)
                omap2_mcspi_force_cs(spi, 0);
 
+       if (cd && cd->cs_per_word) {
+               chconf = mcspi->ctx.modulctrl;
+               chconf |= OMAP2_MCSPI_MODULCTRL_SINGLE;
+               mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, chconf);
+               mcspi->ctx.modulctrl =
+                       mcspi_read_cs_reg(spi, OMAP2_MCSPI_MODULCTRL);
+       }
+
        omap2_mcspi_set_enable(spi, 0);
 
        m->status = status;
@@ -1020,7 +1038,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
 }
 
 static int omap2_mcspi_transfer_one_message(struct spi_master *master,
-                                               struct spi_message *m)
+               struct spi_message *m)
 {
        struct omap2_mcspi      *mcspi;
        struct spi_transfer     *t;
@@ -1041,7 +1059,7 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
                                || (len && !(rx_buf || tx_buf))
                                || (t->bits_per_word &&
                                        (  t->bits_per_word < 4
-                                       || t->bits_per_word > 32))) {
+                                          || t->bits_per_word > 32))) {
                        dev_dbg(mcspi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
                                        t->speed_hz,
                                        len,
@@ -1052,8 +1070,8 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
                }
                if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) {
                        dev_dbg(mcspi->dev, "speed_hz %d below minimum %d Hz\n",
-                               t->speed_hz,
-                               OMAP2_MCSPI_MAX_FREQ >> 15);
+                                       t->speed_hz,
+                                       OMAP2_MCSPI_MAX_FREQ >> 15);
                        return -EINVAL;
                }
 
@@ -1099,7 +1117,7 @@ static int omap2_mcspi_master_setup(struct omap2_mcspi *mcspi)
                return ret;
 
        mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE,
-                               OMAP2_MCSPI_WAKEUPENABLE_WKEN);
+                       OMAP2_MCSPI_WAKEUPENABLE_WKEN);
        ctx->wakeupenable = OMAP2_MCSPI_WAKEUPENABLE_WKEN;
 
        omap2_mcspi_set_master_mode(master);
@@ -1228,7 +1246,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
 
                sprintf(dma_ch_name, "rx%d", i);
                dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
-                                                       dma_ch_name);
+                               dma_ch_name);
                if (!dma_res) {
                        dev_dbg(&pdev->dev, "cannot get DMA RX channel\n");
                        status = -ENODEV;
@@ -1238,7 +1256,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
                mcspi->dma_channels[i].dma_rx_sync_dev = dma_res->start;
                sprintf(dma_ch_name, "tx%d", i);
                dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
-                                                       dma_ch_name);
+                               dma_ch_name);
                if (!dma_res) {
                        dev_dbg(&pdev->dev, "cannot get DMA TX channel\n");
                        status = -ENODEV;
@@ -1254,7 +1272,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
        pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
        if (IS_ERR(pinctrl))
                dev_warn(&pdev->dev,
-                       "pins are not configured from the driver\n");
+                               "pins are not configured from the driver\n");
 
        pm_runtime_use_autosuspend(&pdev->dev);
        pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
index cf95587eefde4c0aa87b0460b4d4ea6926a00de8..364964d2ed04f32a1436710a5019f7b7ccd3c261 100644 (file)
 #include <linux/module.h>
 #include <linux/spi/pxa2xx_spi.h>
 
-struct ce4100_info {
-       struct ssp_device ssp;
-       struct platform_device *spi_pdev;
-};
-
-static DEFINE_MUTEX(ssp_lock);
-static LIST_HEAD(ssp_list);
-
-struct ssp_device *pxa_ssp_request(int port, const char *label)
-{
-       struct ssp_device *ssp = NULL;
-
-       mutex_lock(&ssp_lock);
-
-       list_for_each_entry(ssp, &ssp_list, node) {
-               if (ssp->port_id == port && ssp->use_count == 0) {
-                       ssp->use_count++;
-                       ssp->label = label;
-                       break;
-               }
-       }
-
-       mutex_unlock(&ssp_lock);
-
-       if (&ssp->node == &ssp_list)
-               return NULL;
-
-       return ssp;
-}
-EXPORT_SYMBOL_GPL(pxa_ssp_request);
-
-void pxa_ssp_free(struct ssp_device *ssp)
-{
-       mutex_lock(&ssp_lock);
-       if (ssp->use_count) {
-               ssp->use_count--;
-               ssp->label = NULL;
-       } else
-               dev_err(&ssp->pdev->dev, "device already free\n");
-       mutex_unlock(&ssp_lock);
-}
-EXPORT_SYMBOL_GPL(pxa_ssp_free);
-
 static int ce4100_spi_probe(struct pci_dev *dev,
                const struct pci_device_id *ent)
 {
+       struct platform_device_info pi;
        int ret;
-       resource_size_t phys_beg;
-       resource_size_t phys_len;
-       struct ce4100_info *spi_info;
        struct platform_device *pdev;
        struct pxa2xx_spi_master spi_pdata;
        struct ssp_device *ssp;
 
-       ret = pci_enable_device(dev);
+       ret = pcim_enable_device(dev);
        if (ret)
                return ret;
 
-       phys_beg = pci_resource_start(dev, 0);
-       phys_len = pci_resource_len(dev, 0);
-
-       if (!request_mem_region(phys_beg, phys_len,
-                               "CE4100 SPI")) {
-               dev_err(&dev->dev, "Can't request register space.\n");
-               ret = -EBUSY;
+       ret = pcim_iomap_regions(dev, 1 << 0, "PXA2xx SPI");
+       if (!ret)
                return ret;
-       }
 
-       pdev = platform_device_alloc("pxa2xx-spi", dev->devfn);
-       spi_info = kzalloc(sizeof(*spi_info), GFP_KERNEL);
-       if (!pdev || !spi_info ) {
-               ret = -ENOMEM;
-               goto err_nomem;
-       }
        memset(&spi_pdata, 0, sizeof(spi_pdata));
        spi_pdata.num_chipselect = dev->devfn;
 
-       ret = platform_device_add_data(pdev, &spi_pdata, sizeof(spi_pdata));
-       if (ret)
-               goto err_nomem;
-
-       pdev->dev.parent = &dev->dev;
-       pdev->dev.of_node = dev->dev.of_node;
-       ssp = &spi_info->ssp;
+       ssp = &spi_pdata.ssp;
        ssp->phys_base = pci_resource_start(dev, 0);
-       ssp->mmio_base = ioremap(phys_beg, phys_len);
+       ssp->mmio_base = pcim_iomap_table(dev)[0];
        if (!ssp->mmio_base) {
-               dev_err(&pdev->dev, "failed to ioremap() registers\n");
-               ret = -EIO;
-               goto err_nomem;
+               dev_err(&dev->dev, "failed to ioremap() registers\n");
+               return -EIO;
        }
        ssp->irq = dev->irq;
-       ssp->port_id = pdev->id;
+       ssp->port_id = dev->devfn;
        ssp->type = PXA25x_SSP;
 
-       mutex_lock(&ssp_lock);
-       list_add(&ssp->node, &ssp_list);
-       mutex_unlock(&ssp_lock);
+       memset(&pi, 0, sizeof(pi));
+       pi.parent = &dev->dev;
+       pi.name = "pxa2xx-spi";
+       pi.id = ssp->port_id;
+       pi.data = &spi_pdata;
+       pi.size_data = sizeof(spi_pdata);
 
-       pci_set_drvdata(dev, spi_info);
+       pdev = platform_device_register_full(&pi);
+       if (!pdev)
+               return -ENOMEM;
 
-       ret = platform_device_add(pdev);
-       if (ret)
-               goto err_dev_add;
+       pci_set_drvdata(dev, pdev);
 
-       return ret;
-
-err_dev_add:
-       pci_set_drvdata(dev, NULL);
-       mutex_lock(&ssp_lock);
-       list_del(&ssp->node);
-       mutex_unlock(&ssp_lock);
-       iounmap(ssp->mmio_base);
-
-err_nomem:
-       release_mem_region(phys_beg, phys_len);
-       platform_device_put(pdev);
-       kfree(spi_info);
-       return ret;
+       return 0;
 }
 
 static void ce4100_spi_remove(struct pci_dev *dev)
 {
-       struct ce4100_info *spi_info;
-       struct ssp_device *ssp;
-
-       spi_info = pci_get_drvdata(dev);
-       ssp = &spi_info->ssp;
-       platform_device_unregister(spi_info->spi_pdev);
-
-       iounmap(ssp->mmio_base);
-       release_mem_region(pci_resource_start(dev, 0),
-                       pci_resource_len(dev, 0));
-
-       mutex_lock(&ssp_lock);
-       list_del(&ssp->node);
-       mutex_unlock(&ssp_lock);
+       struct platform_device *pdev = pci_get_drvdata(dev);
 
-       pci_set_drvdata(dev, NULL);
-       pci_disable_device(dev);
-       kfree(spi_info);
+       platform_device_unregister(pdev);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(ce4100_spi_devices) = {
index 5c8c4f5883c49f8fefcbbc6f36a6662879dce0b8..304cf6eb50e6baea4c2aee11ed7eba867194028f 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
+#include <linux/clk.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -47,7 +48,7 @@ MODULE_ALIAS("platform:pxa2xx-spi");
 
 #define DMA_INT_MASK           (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
 #define RESET_DMA_CHANNEL      (DCSR_NODESC | DMA_INT_MASK)
-#define IS_DMA_ALIGNED(x)      ((((u32)(x)) & 0x07) == 0)
+#define IS_DMA_ALIGNED(x)      IS_ALIGNED((unsigned long)(x), DMA_ALIGNMENT)
 #define MAX_DMA_LEN            8191
 #define DMA_ALIGNMENT          8
 
@@ -85,9 +86,6 @@ DEFINE_SSP_REG(SSPSP, 0x2c)
 #define DONE_STATE ((void*)2)
 #define ERROR_STATE ((void*)-1)
 
-#define QUEUE_RUNNING 0
-#define QUEUE_STOPPED 1
-
 struct driver_data {
        /* Driver model hookup */
        struct platform_device *pdev;
@@ -117,13 +115,8 @@ struct driver_data {
        u32 clear_sr;
        u32 mask_sr;
 
-       /* Driver message queue */
-       struct workqueue_struct *workqueue;
-       struct work_struct pump_messages;
-       spinlock_t lock;
-       struct list_head queue;
-       int busy;
-       int run;
+       /* Maximun clock rate */
+       unsigned long max_clk_rate;
 
        /* Message Transfer pump */
        struct tasklet_struct pump_transfers;
@@ -173,8 +166,6 @@ struct chip_data {
        void (*cs_control)(u32 command);
 };
 
-static void pump_messages(struct work_struct *work);
-
 static void cs_assert(struct driver_data *drv_data)
 {
        struct chip_data *chip = drv_data->cur_chip;
@@ -444,15 +435,11 @@ static void unmap_dma_buffers(struct driver_data *drv_data)
 static void giveback(struct driver_data *drv_data)
 {
        struct spi_transfer* last_transfer;
-       unsigned long flags;
        struct spi_message *msg;
 
-       spin_lock_irqsave(&drv_data->lock, flags);
        msg = drv_data->cur_msg;
        drv_data->cur_msg = NULL;
        drv_data->cur_transfer = NULL;
-       queue_work(drv_data->workqueue, &drv_data->pump_messages);
-       spin_unlock_irqrestore(&drv_data->lock, flags);
 
        last_transfer = list_entry(msg->transfers.prev,
                                        struct spi_transfer,
@@ -481,13 +468,7 @@ static void giveback(struct driver_data *drv_data)
                 */
 
                /* get a pointer to the next message, if any */
-               spin_lock_irqsave(&drv_data->lock, flags);
-               if (list_empty(&drv_data->queue))
-                       next_msg = NULL;
-               else
-                       next_msg = list_entry(drv_data->queue.next,
-                                       struct spi_message, queue);
-               spin_unlock_irqrestore(&drv_data->lock, flags);
+               next_msg = spi_get_next_queued_message(drv_data->master);
 
                /* see if the next and current messages point
                 * to the same chip
@@ -498,10 +479,7 @@ static void giveback(struct driver_data *drv_data)
                        cs_deassert(drv_data);
        }
 
-       msg->state = NULL;
-       if (msg->complete)
-               msg->complete(msg->context);
-
+       spi_finalize_current_message(drv_data->master);
        drv_data->cur_chip = NULL;
 }
 
@@ -917,9 +895,12 @@ static int set_dma_burst_and_threshold(struct chip_data *chip,
        return retval;
 }
 
-static unsigned int ssp_get_clk_div(struct ssp_device *ssp, int rate)
+static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate)
 {
-       unsigned long ssp_clk = clk_get_rate(ssp->clk);
+       unsigned long ssp_clk = drv_data->max_clk_rate;
+       const struct ssp_device *ssp = drv_data->ssp;
+
+       rate = min_t(int, ssp_clk, rate);
 
        if (ssp->type == PXA25x_SSP || ssp->type == CE4100_SSP)
                return ((ssp_clk / (2 * rate) - 1) & 0xff) << 8;
@@ -934,7 +915,6 @@ static void pump_transfers(unsigned long data)
        struct spi_transfer *transfer = NULL;
        struct spi_transfer *previous = NULL;
        struct chip_data *chip = NULL;
-       struct ssp_device *ssp = drv_data->ssp;
        void __iomem *reg = drv_data->ioaddr;
        u32 clk_div = 0;
        u8 bits = 0;
@@ -1031,7 +1011,7 @@ static void pump_transfers(unsigned long data)
                if (transfer->bits_per_word)
                        bits = transfer->bits_per_word;
 
-               clk_div = ssp_get_clk_div(ssp, speed);
+               clk_div = ssp_get_clk_div(drv_data, speed);
 
                if (bits <= 8) {
                        drv_data->n_bytes = 1;
@@ -1176,31 +1156,12 @@ static void pump_transfers(unsigned long data)
        write_SSCR1(cr1, reg);
 }
 
-static void pump_messages(struct work_struct *work)
+static int pxa2xx_spi_transfer_one_message(struct spi_master *master,
+                                          struct spi_message *msg)
 {
-       struct driver_data *drv_data =
-               container_of(work, struct driver_data, pump_messages);
-       unsigned long flags;
-
-       /* Lock queue and check for queue work */
-       spin_lock_irqsave(&drv_data->lock, flags);
-       if (list_empty(&drv_data->queue) || drv_data->run == QUEUE_STOPPED) {
-               drv_data->busy = 0;
-               spin_unlock_irqrestore(&drv_data->lock, flags);
-               return;
-       }
-
-       /* Make sure we are not already running a message */
-       if (drv_data->cur_msg) {
-               spin_unlock_irqrestore(&drv_data->lock, flags);
-               return;
-       }
-
-       /* Extract head of queue */
-       drv_data->cur_msg = list_entry(drv_data->queue.next,
-                                       struct spi_message, queue);
-       list_del_init(&drv_data->cur_msg->queue);
+       struct driver_data *drv_data = spi_master_get_devdata(master);
 
+       drv_data->cur_msg = msg;
        /* Initial message state*/
        drv_data->cur_msg->state = START_STATE;
        drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
@@ -1213,34 +1174,6 @@ static void pump_messages(struct work_struct *work)
 
        /* Mark as busy and launch transfers */
        tasklet_schedule(&drv_data->pump_transfers);
-
-       drv_data->busy = 1;
-       spin_unlock_irqrestore(&drv_data->lock, flags);
-}
-
-static int transfer(struct spi_device *spi, struct spi_message *msg)
-{
-       struct driver_data *drv_data = spi_master_get_devdata(spi->master);
-       unsigned long flags;
-
-       spin_lock_irqsave(&drv_data->lock, flags);
-
-       if (drv_data->run == QUEUE_STOPPED) {
-               spin_unlock_irqrestore(&drv_data->lock, flags);
-               return -ESHUTDOWN;
-       }
-
-       msg->actual_length = 0;
-       msg->status = -EINPROGRESS;
-       msg->state = START_STATE;
-
-       list_add_tail(&msg->queue, &drv_data->queue);
-
-       if (drv_data->run == QUEUE_RUNNING && !drv_data->busy)
-               queue_work(drv_data->workqueue, &drv_data->pump_messages);
-
-       spin_unlock_irqrestore(&drv_data->lock, flags);
-
        return 0;
 }
 
@@ -1287,7 +1220,6 @@ static int setup(struct spi_device *spi)
        struct pxa2xx_spi_chip *chip_info = NULL;
        struct chip_data *chip;
        struct driver_data *drv_data = spi_master_get_devdata(spi->master);
-       struct ssp_device *ssp = drv_data->ssp;
        unsigned int clk_div;
        uint tx_thres = TX_THRESH_DFLT;
        uint rx_thres = RX_THRESH_DFLT;
@@ -1369,7 +1301,7 @@ static int setup(struct spi_device *spi)
                }
        }
 
-       clk_div = ssp_get_clk_div(ssp, spi->max_speed_hz);
+       clk_div = ssp_get_clk_div(drv_data, spi->max_speed_hz);
        chip->speed_hz = spi->max_speed_hz;
 
        chip->cr0 = clk_div
@@ -1385,12 +1317,12 @@ static int setup(struct spi_device *spi)
        /* NOTE:  PXA25x_SSP _could_ use external clocking ... */
        if (!pxa25x_ssp_comp(drv_data))
                dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
-                       clk_get_rate(ssp->clk)
+                       drv_data->max_clk_rate
                                / (1 + ((chip->cr0 & SSCR0_SCR(0xfff)) >> 8)),
                        chip->enable_dma ? "DMA" : "PIO");
        else
                dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
-                       clk_get_rate(ssp->clk) / 2
+                       drv_data->max_clk_rate / 2
                                / (1 + ((chip->cr0 & SSCR0_SCR(0x0ff)) >> 8)),
                        chip->enable_dma ? "DMA" : "PIO");
 
@@ -1438,94 +1370,6 @@ static void cleanup(struct spi_device *spi)
        kfree(chip);
 }
 
-static int init_queue(struct driver_data *drv_data)
-{
-       INIT_LIST_HEAD(&drv_data->queue);
-       spin_lock_init(&drv_data->lock);
-
-       drv_data->run = QUEUE_STOPPED;
-       drv_data->busy = 0;
-
-       tasklet_init(&drv_data->pump_transfers,
-                       pump_transfers, (unsigned long)drv_data);
-
-       INIT_WORK(&drv_data->pump_messages, pump_messages);
-       drv_data->workqueue = create_singlethread_workqueue(
-                               dev_name(drv_data->master->dev.parent));
-       if (drv_data->workqueue == NULL)
-               return -EBUSY;
-
-       return 0;
-}
-
-static int start_queue(struct driver_data *drv_data)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&drv_data->lock, flags);
-
-       if (drv_data->run == QUEUE_RUNNING || drv_data->busy) {
-               spin_unlock_irqrestore(&drv_data->lock, flags);
-               return -EBUSY;
-       }
-
-       drv_data->run = QUEUE_RUNNING;
-       drv_data->cur_msg = NULL;
-       drv_data->cur_transfer = NULL;
-       drv_data->cur_chip = NULL;
-       spin_unlock_irqrestore(&drv_data->lock, flags);
-
-       queue_work(drv_data->workqueue, &drv_data->pump_messages);
-
-       return 0;
-}
-
-static int stop_queue(struct driver_data *drv_data)
-{
-       unsigned long flags;
-       unsigned limit = 500;
-       int status = 0;
-
-       spin_lock_irqsave(&drv_data->lock, flags);
-
-       /* This is a bit lame, but is optimized for the common execution path.
-        * A wait_queue on the drv_data->busy could be used, but then the common
-        * execution path (pump_messages) would be required to call wake_up or
-        * friends on every SPI message. Do this instead */
-       drv_data->run = QUEUE_STOPPED;
-       while ((!list_empty(&drv_data->queue) || drv_data->busy) && limit--) {
-               spin_unlock_irqrestore(&drv_data->lock, flags);
-               msleep(10);
-               spin_lock_irqsave(&drv_data->lock, flags);
-       }
-
-       if (!list_empty(&drv_data->queue) || drv_data->busy)
-               status = -EBUSY;
-
-       spin_unlock_irqrestore(&drv_data->lock, flags);
-
-       return status;
-}
-
-static int destroy_queue(struct driver_data *drv_data)
-{
-       int status;
-
-       status = stop_queue(drv_data);
-       /* we are unloading the module or failing to load (only two calls
-        * to this routine), and neither call can handle a return value.
-        * However, destroy_workqueue calls flush_workqueue, and that will
-        * block until all work is done.  If the reason that stop_queue
-        * timed out is that the work will never finish, then it does no
-        * good to call destroy_workqueue, so return anyway. */
-       if (status != 0)
-               return status;
-
-       destroy_workqueue(drv_data->workqueue);
-
-       return 0;
-}
-
 static int pxa2xx_spi_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -1535,11 +1379,18 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
        struct ssp_device *ssp;
        int status;
 
-       platform_info = dev->platform_data;
+       platform_info = dev_get_platdata(dev);
+       if (!platform_info) {
+               dev_err(&pdev->dev, "missing platform data\n");
+               return -ENODEV;
+       }
 
        ssp = pxa_ssp_request(pdev->id, pdev->name);
-       if (ssp == NULL) {
-               dev_err(&pdev->dev, "failed to request SSP%d\n", pdev->id);
+       if (!ssp)
+               ssp = &platform_info->ssp;
+
+       if (!ssp->mmio_base) {
+               dev_err(&pdev->dev, "failed to get ssp\n");
                return -ENODEV;
        }
 
@@ -1561,16 +1412,15 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
        /* the spi->mode bits understood by this driver: */
        master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 
-       master->bus_num = pdev->id;
+       master->bus_num = ssp->port_id;
        master->num_chipselect = platform_info->num_chipselect;
        master->dma_alignment = DMA_ALIGNMENT;
        master->cleanup = cleanup;
        master->setup = setup;
-       master->transfer = transfer;
+       master->transfer_one_message = pxa2xx_spi_transfer_one_message;
 
        drv_data->ssp_type = ssp->type;
-       drv_data->null_dma_buf = (u32 *)ALIGN((u32)(drv_data +
-                                               sizeof(struct driver_data)), 8);
+       drv_data->null_dma_buf = (u32 *)PTR_ALIGN(&drv_data[1], DMA_ALIGNMENT);
 
        drv_data->ioaddr = ssp->mmio_base;
        drv_data->ssdr_physical = ssp->phys_base + SSDR;
@@ -1625,7 +1475,9 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
        }
 
        /* Enable SOC clock */
-       clk_enable(ssp->clk);
+       clk_prepare_enable(ssp->clk);
+
+       drv_data->max_clk_rate = clk_get_rate(ssp->clk);
 
        /* Load default SSP configuration */
        write_SSCR0(0, drv_data->ioaddr);
@@ -1640,33 +1492,21 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
                write_SSTO(0, drv_data->ioaddr);
        write_SSPSP(0, drv_data->ioaddr);
 
-       /* Initial and start queue */
-       status = init_queue(drv_data);
-       if (status != 0) {
-               dev_err(&pdev->dev, "problem initializing queue\n");
-               goto out_error_clock_enabled;
-       }
-       status = start_queue(drv_data);
-       if (status != 0) {
-               dev_err(&pdev->dev, "problem starting queue\n");
-               goto out_error_clock_enabled;
-       }
+       tasklet_init(&drv_data->pump_transfers, pump_transfers,
+                    (unsigned long)drv_data);
 
        /* Register with the SPI framework */
        platform_set_drvdata(pdev, drv_data);
        status = spi_register_master(master);
        if (status != 0) {
                dev_err(&pdev->dev, "problem registering spi master\n");
-               goto out_error_queue_alloc;
+               goto out_error_clock_enabled;
        }
 
        return status;
 
-out_error_queue_alloc:
-       destroy_queue(drv_data);
-
 out_error_clock_enabled:
-       clk_disable(ssp->clk);
+       clk_disable_unprepare(ssp->clk);
 
 out_error_dma_alloc:
        if (drv_data->tx_channel != -1)
@@ -1687,29 +1527,14 @@ static int pxa2xx_spi_remove(struct platform_device *pdev)
 {
        struct driver_data *drv_data = platform_get_drvdata(pdev);
        struct ssp_device *ssp;
-       int status = 0;
 
        if (!drv_data)
                return 0;
        ssp = drv_data->ssp;
 
-       /* Remove the queue */
-       status = destroy_queue(drv_data);
-       if (status != 0)
-               /* the kernel does not check the return status of this
-                * this routine (mod->exit, within the kernel).  Therefore
-                * nothing is gained by returning from here, the module is
-                * going away regardless, and we should not leave any more
-                * resources allocated than necessary.  We cannot free the
-                * message memory in drv_data->queue, but we can release the
-                * resources below.  I think the kernel should honor -EBUSY
-                * returns but... */
-               dev_err(&pdev->dev, "pxa2xx_spi_remove: workqueue will not "
-                       "complete, message memory not freed\n");
-
        /* Disable the SSP at the peripheral and SOC level */
        write_SSCR0(0, drv_data->ioaddr);
-       clk_disable(ssp->clk);
+       clk_disable_unprepare(ssp->clk);
 
        /* Release DMA */
        if (drv_data->master_info->enable_dma) {
@@ -1749,11 +1574,11 @@ static int pxa2xx_spi_suspend(struct device *dev)
        struct ssp_device *ssp = drv_data->ssp;
        int status = 0;
 
-       status = stop_queue(drv_data);
+       status = spi_master_suspend(drv_data->master);
        if (status != 0)
                return status;
        write_SSCR0(0, drv_data->ioaddr);
-       clk_disable(ssp->clk);
+       clk_disable_unprepare(ssp->clk);
 
        return 0;
 }
@@ -1772,10 +1597,10 @@ static int pxa2xx_spi_resume(struct device *dev)
                        DRCMR_MAPVLD | drv_data->tx_channel;
 
        /* Enable the SSP clock */
-       clk_enable(ssp->clk);
+       clk_prepare_enable(ssp->clk);
 
        /* Start the queue running */
-       status = start_queue(drv_data);
+       status = spi_master_resume(drv_data->master);
        if (status != 0) {
                dev_err(dev, "problem starting queue (%d)\n", status);
                return status;
index d77b6560b67f87a1a6c5c92fda9cafd74811811c..a82bfa4af601eada86f40978c7f404d3ced2b66b 100644 (file)
@@ -957,6 +957,8 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
                if (spi->max_speed_hz >= speed) {
                        spi->max_speed_hz = speed;
                } else {
+                       dev_err(&spi->dev, "Can't set %dHz transfer speed\n",
+                               spi->max_speed_hz);
                        err = -EINVAL;
                        goto setup_exit;
                }
index a65572d53211cf2dc51b97c7ca438c2020520862..c100456eab17958bbdbe6571e6346db864c87ead 100644 (file)
@@ -22,6 +22,9 @@ struct omap2_mcspi_dev_attr {
 
 struct omap2_mcspi_device_config {
        unsigned turbo_mode:1;
+
+       /* toggle chip select after every word */
+       unsigned cs_per_word:1;
 };
 
 #endif
index f36632061c668d0b9e7fc8def05d34650a5a55c8..065e7f6c3ad7df548d82fe09cfc9dea3190ef1a6 100644 (file)
@@ -206,6 +206,15 @@ static inline u32 pxa_ssp_read_reg(struct ssp_device *dev, u32 reg)
        return __raw_readl(dev->mmio_base + reg);
 }
 
+#ifdef CONFIG_ARCH_PXA
 struct ssp_device *pxa_ssp_request(int port, const char *label);
 void pxa_ssp_free(struct ssp_device *);
+#else
+static inline struct ssp_device *pxa_ssp_request(int port, const char *label)
+{
+       return NULL;
+}
+static inline void pxa_ssp_free(struct ssp_device *ssp) {}
+#endif
+
 #endif
index c73d1445c77ecfc13a4867f60444f6c3a1adc183..053b5ba51b256e610c393c560285347eb6616e9b 100644 (file)
@@ -28,6 +28,9 @@ struct pxa2xx_spi_master {
        u32 clock_enable;
        u16 num_chipselect;
        u8 enable_dma;
+
+       /* For non-PXA arches */
+       struct ssp_device ssp;
 };
 
 /* spi_board_info.controller_data for SPI slave devices,
@@ -130,23 +133,5 @@ static inline void pxa_free_dma(int dma_ch)
 {
 }
 
-/*
- * The CE4100 does not have the clk framework implemented and SPI clock can
- * not be switched on/off or the divider changed.
- */
-static inline void clk_disable(struct clk *clk)
-{
-}
-
-static inline int clk_enable(struct clk *clk)
-{
-       return 0;
-}
-
-static inline unsigned long clk_get_rate(struct clk *clk)
-{
-       return 3686400;
-}
-
 #endif
 #endif
index 369b3d7d5b956069f3773e6fd4610cb278c8f757..1634ce31c06d40df05cd689941d44da82d1daf40 100644 (file)
@@ -62,8 +62,8 @@
  */
 struct spi_gpio_platform_data {
        unsigned        sck;
-       unsigned        mosi;
-       unsigned        miso;
+       unsigned long   mosi;
+       unsigned long   miso;
 
        u16             num_chipselect;
 };