From e1b0f0df6a08329ce2f123240a5218c3e5c43b74 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 20 Dec 2012 18:27:31 +0000 Subject: spi/s3c64xx: Complain if we fail to set a transfer speed Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index ad93231a8038..6495352bcc19 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -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; } -- cgit v1.2.3 From 0202775bc3a28f2436ea6ee13ef3eb0e8f237857 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Mon, 7 Jan 2013 12:44:32 +0200 Subject: spi/pxa2xx-pci: switch to use pcim_* interfaces Instead of open-coding all the error management in the driver we can take advantage of the pcim_* interfaces that release the resources automatically. We also use platform_device_register_full() to register the platform device because it allows us to create and register the platform device at one go, simplifying the error management. This a preparatory step for getting rid of pxa_ssp_request()/free() which we will do in the next patch. Signed-off-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx-pci.c | 86 ++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 56 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c index cf95587eefde..ece979e9c642 100644 --- a/drivers/spi/spi-pxa2xx-pci.c +++ b/drivers/spi/spi-pxa2xx-pci.c @@ -54,101 +54,75 @@ 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; - } + spi_info = devm_kzalloc(&dev->dev, sizeof(*spi_info), GFP_KERNEL); + if (!spi_info) + return -ENOMEM; + 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->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); - pci_set_drvdata(dev, spi_info); + 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); - ret = platform_device_add(pdev); - if (ret) - goto err_dev_add; + pdev = platform_device_register_full(&pi); + if (!pdev) { + mutex_lock(&ssp_lock); + list_del(&ssp->node); + mutex_unlock(&ssp_lock); - return ret; + return -ENOMEM; + } -err_dev_add: - pci_set_drvdata(dev, NULL); - mutex_lock(&ssp_lock); - list_del(&ssp->node); - mutex_unlock(&ssp_lock); - iounmap(ssp->mmio_base); + spi_info->spi_pdev = pdev; + pci_set_drvdata(dev, spi_info); -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; + struct ce4100_info *spi_info = pci_get_drvdata(dev); + struct ssp_device *ssp = &spi_info->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); - - pci_set_drvdata(dev, NULL); - pci_disable_device(dev); - kfree(spi_info); } static DEFINE_PCI_DEVICE_TABLE(ce4100_spi_devices) = { -- cgit v1.2.3 From 851bacf5902cad15f9bb789d278a1ee9608c8f25 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Mon, 7 Jan 2013 12:44:33 +0200 Subject: spi/pxa2xx: embed the ssp_device to platform data The spi-pxa2xx-pci glue driver had to implement pxa_ssp_request()/free() in order to support the spi-pxa2xx platform driver. Since the ACPI enabled platforms can use the same platform driver we would need to implement pxa_ssp_request()/free() in some central place that can be shared by the ACPI and PCI glue code. Instead of doing that we can make pxa_ssp_request()/free() to be available only when CONFIG_ARCH_PXA is set. On other arches these are being stubbed out in preference to passing the ssp_device from the platform data directly. We also change the SPI bus number to be taken from ssp->port_id instead of platform device id. This way the supporting code that passes the ssp can decide the number (or it can set it to the same as pdev->id). Signed-off-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx-pci.c | 73 +++----------------------------------------- drivers/spi/spi-pxa2xx.c | 15 ++++++--- 2 files changed, 16 insertions(+), 72 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c index ece979e9c642..364964d2ed04 100644 --- a/drivers/spi/spi-pxa2xx-pci.c +++ b/drivers/spi/spi-pxa2xx-pci.c @@ -8,55 +8,11 @@ #include #include -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; - struct ce4100_info *spi_info; struct platform_device *pdev; struct pxa2xx_spi_master spi_pdata; struct ssp_device *ssp; @@ -69,14 +25,10 @@ static int ce4100_spi_probe(struct pci_dev *dev, if (!ret) return ret; - spi_info = devm_kzalloc(&dev->dev, sizeof(*spi_info), GFP_KERNEL); - if (!spi_info) - return -ENOMEM; - memset(&spi_pdata, 0, sizeof(spi_pdata)); spi_pdata.num_chipselect = dev->devfn; - ssp = &spi_info->ssp; + ssp = &spi_pdata.ssp; ssp->phys_base = pci_resource_start(dev, 0); ssp->mmio_base = pcim_iomap_table(dev)[0]; if (!ssp->mmio_base) { @@ -87,10 +39,6 @@ static int ce4100_spi_probe(struct pci_dev *dev, 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"; @@ -99,30 +47,19 @@ static int ce4100_spi_probe(struct pci_dev *dev, pi.size_data = sizeof(spi_pdata); pdev = platform_device_register_full(&pi); - if (!pdev) { - mutex_lock(&ssp_lock); - list_del(&ssp->node); - mutex_unlock(&ssp_lock); - + if (!pdev) return -ENOMEM; - } - spi_info->spi_pdev = pdev; - pci_set_drvdata(dev, spi_info); + pci_set_drvdata(dev, pdev); return 0; } static void ce4100_spi_remove(struct pci_dev *dev) { - struct ce4100_info *spi_info = pci_get_drvdata(dev); - struct ssp_device *ssp = &spi_info->ssp; - - platform_device_unregister(spi_info->spi_pdev); + struct platform_device *pdev = pci_get_drvdata(dev); - mutex_lock(&ssp_lock); - list_del(&ssp->node); - mutex_unlock(&ssp_lock); + platform_device_unregister(pdev); } static DEFINE_PCI_DEVICE_TABLE(ce4100_spi_devices) = { diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 5c8c4f5883c4..54097ad76356 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1535,11 +1535,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,7 +1568,7 @@ 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; -- cgit v1.2.3 From 7a5d8ca12aece480e0fe5eda8ce4236dddf55363 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 10 Jan 2013 13:13:56 +0100 Subject: spi: bitbang: simplify pointer arithmetics Add a pointer variable to make spi_bitbang_start() look simpler. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mark Brown --- drivers/spi/spi-bitbang.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index 8b3d8efafd3c..328c4dcd3d52 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -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; -- cgit v1.2.3 From 2b49ebda39d66db1ae79a94c2bfec2d44f26ff94 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 22 Jan 2013 12:26:24 +0200 Subject: spi/pxa2xx: allow building on a 64-bit kernel We are going to use it on 64-bit kernel on Intel Lynxpoint so make sure we can build it into such kernel. Signed-off-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 2e188e1127eb..a90393d7f106 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -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" -- cgit v1.2.3 From 2b9b84f497638ebd60a762cb1c7fa7b4ff7dce4d Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 22 Jan 2013 12:26:25 +0200 Subject: spi/pxa2xx: fix warnings when compiling a 64-bit kernel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix following warnings seen when compiling 64-bit: drivers/spi/spi-pxa2xx.c: In function ‘map_dma_buffers’: drivers/spi/spi-pxa2xx.c:384:7: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] drivers/spi/spi-pxa2xx.c:384:40: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] drivers/spi/spi-pxa2xx.c: In function ‘pxa2xx_spi_probe’: drivers/spi/spi-pxa2xx.c:1572:34: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] drivers/spi/spi-pxa2xx.c:1572:34: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] drivers/spi/spi-pxa2xx.c:1572:34: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] drivers/spi/spi-pxa2xx.c:1572:27: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] Signed-off-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 54097ad76356..ef0a78650e96 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -47,7 +47,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 @@ -1576,8 +1576,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) master->transfer = transfer; 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; -- cgit v1.2.3 From 7f86bde90e2e1f693d93922fc0f4d50f001ce1a5 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 22 Jan 2013 12:26:26 +0200 Subject: spi/pxa2xx: convert to the pump message infrastructure The SPI core provides infrastructure for standard message queueing so use that instead of handling everything in the driver. This simplifies the driver. Signed-off-by: Mika Westerberg Acked-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 212 +++-------------------------------------------- 1 file changed, 12 insertions(+), 200 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index ef0a78650e96..a241891355db 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -85,9 +85,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,14 +114,6 @@ 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; - /* Message Transfer pump */ struct tasklet_struct pump_transfers; @@ -173,8 +162,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 +431,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 +464,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 +475,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; } @@ -1176,31 +1150,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 +1168,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; } @@ -1438,94 +1365,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; @@ -1573,7 +1412,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) 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 *)PTR_ALIGN(&drv_data[1], DMA_ALIGNMENT); @@ -1646,31 +1485,19 @@ 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); @@ -1693,26 +1520,11 @@ 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); @@ -1755,7 +1567,7 @@ 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); @@ -1781,7 +1593,7 @@ static int pxa2xx_spi_resume(struct device *dev) clk_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; -- cgit v1.2.3 From 3343b7a6d2cd0a980d0c4a0ce02ef48b6bfcc12a Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 22 Jan 2013 12:26:27 +0200 Subject: spi/pxa2xx: convert to the common clk framework Convert clk_enable() to clk_prepare_enable() and clk_disable() to clk_disable_unprepare() respectively in order to support the common clk framework. Otherwise we get warnings on the console as the clock is not prepared before it is enabled. In addition we must cache the maximum clock rate to drv_data->max_clk_rate at probe time because clk_get_rate() cannot be called in tasklet context. Signed-off-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index a241891355db..304cf6eb50e6 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -114,6 +115,9 @@ struct driver_data { u32 clear_sr; u32 mask_sr; + /* Maximun clock rate */ + unsigned long max_clk_rate; + /* Message Transfer pump */ struct tasklet_struct pump_transfers; @@ -891,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; @@ -908,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; @@ -1005,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; @@ -1214,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; @@ -1296,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 @@ -1312,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"); @@ -1470,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); @@ -1499,7 +1506,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) return status; out_error_clock_enabled: - clk_disable(ssp->clk); + clk_disable_unprepare(ssp->clk); out_error_dma_alloc: if (drv_data->tx_channel != -1) @@ -1527,7 +1534,7 @@ static int pxa2xx_spi_remove(struct platform_device *pdev) /* 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) { @@ -1571,7 +1578,7 @@ static int pxa2xx_spi_suspend(struct device *dev) if (status != 0) return status; write_SSCR0(0, drv_data->ioaddr); - clk_disable(ssp->clk); + clk_disable_unprepare(ssp->clk); return 0; } @@ -1590,7 +1597,7 @@ 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 = spi_master_resume(drv_data->master); -- cgit v1.2.3 From 0202a32d5f4a129ced47db76001f958cd33adeb7 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 25 Jan 2013 09:39:34 +0100 Subject: spi: spi-gpio: Add checks for the dt properties The bindings assumed that the gpios properties were always there, which made the NO_TX and NO_RX mode not usable from device tree. Add extra checks to make sure that the driver can work if either MOSI or MISO is not used. Signed-off-by: Maxime Ripard Cc: Mark Brown Signed-off-by: Mark Brown --- drivers/spi/spi-gpio.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index c7cf0b7a069b..9ddef55a7165 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -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) { -- cgit v1.2.3 From 18dd6199fa4527229cede5784244b6eb37a21d62 Mon Sep 17 00:00:00 2001 From: Matthias Brugger Date: Thu, 24 Jan 2013 13:28:58 +0100 Subject: spi: spi-omap2-mcspi.c: fix coding style This patch fixes some indentation errors. Signed-off-by: Matthias Brugger Reviewed-by: Jarkko Nikula Signed-off-by: Mark Brown --- drivers/spi/spi-omap2-mcspi.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index b610f522ca44..31f6e842ea86 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -1020,7 +1020,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 +1041,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 +1052,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 +1099,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 +1228,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 +1238,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 +1254,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); -- cgit v1.2.3 From 5cbc7ca987fb3f293203dc14a6c53b91b7c978a5 Mon Sep 17 00:00:00 2001 From: Matthias Brugger Date: Thu, 24 Jan 2013 13:40:41 +0100 Subject: spi: spi-omap2-mcspi.c: Toggle CS after each word This patch allows the board code to define SPI devices which needs to toggle the chip select after every word send. This is needed to get a better resolution reading e.g. an ADC data stream. Apart from that, as in the normal code CS is controlled by software, a transfer is done much faster. Signed-off-by: Matthias Brugger Signed-off-by: Mark Brown --- drivers/spi/spi-omap2-mcspi.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 31f6e842ea86..12789fcfa980 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -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; -- cgit v1.2.3 From 830379e04858098d65c59f07f68be3d73244ae54 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 12 Dec 2012 10:45:59 +0200 Subject: spi/omap2: disable DMA requests before complete() No actual errors have been found for completing before disabling DMA request lines, but it just looks more semantically correct that on our DMA callback we quiesce the whole thing before stating transfer is finished. Signed-off-by: Felipe Balbi Signed-off-by: Grant Likely --- drivers/spi/spi-omap2-mcspi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index b610f522ca44..68446dbd5545 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -298,10 +298,10 @@ static void omap2_mcspi_rx_callback(void *data) struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi->chip_select]; - complete(&mcspi_dma->dma_rx_completion); - /* We must disable the DMA RX request */ omap2_mcspi_set_dma_req(spi, 1, 0); + + complete(&mcspi_dma->dma_rx_completion); } static void omap2_mcspi_tx_callback(void *data) @@ -310,10 +310,10 @@ static void omap2_mcspi_tx_callback(void *data) struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi->chip_select]; - complete(&mcspi_dma->dma_tx_completion); - /* We must disable the DMA TX request */ omap2_mcspi_set_dma_req(spi, 0, 0); + + complete(&mcspi_dma->dma_tx_completion); } static void omap2_mcspi_tx_dma(struct spi_device *spi, -- cgit v1.2.3 From aae7147dfc522062b3448f67f5517d32fbdab1fb Mon Sep 17 00:00:00 2001 From: Murali Karicheri Date: Tue, 11 Dec 2012 16:20:39 -0500 Subject: spi/davinci: add OF support for the spi controller This adds OF support to DaVinci SPI controller to configure platform data through device bindings. Also replaces clk_enable() with of clk_prepare_enable() as well as clk_disable() with clk_disable_unprepare(). Signed-off-by: Murali Karicheri Signed-off-by: Grant Likely --- drivers/spi/spi-davinci.c | 102 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 88 insertions(+), 14 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 13661e129d96..50bd2cdc52de 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include #include @@ -135,7 +137,7 @@ struct davinci_spi { int dma_rx_chnum; int dma_tx_chnum; - struct davinci_spi_platform_data *pdata; + struct davinci_spi_platform_data pdata; void (*get_rx)(u32 rx_data, struct davinci_spi *); u32 (*get_tx)(struct davinci_spi *); @@ -213,7 +215,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) bool gpio_chipsel = false; dspi = spi_master_get_devdata(spi->master); - pdata = dspi->pdata; + pdata = &dspi->pdata; if (pdata->chip_sel && chip_sel < pdata->num_chipselect && pdata->chip_sel[chip_sel] != SPI_INTERN_CS) @@ -392,7 +394,7 @@ static int davinci_spi_setup(struct spi_device *spi) struct davinci_spi_platform_data *pdata; dspi = spi_master_get_devdata(spi->master); - pdata = dspi->pdata; + pdata = &dspi->pdata; /* if bits per word length is zero then set it default 8 */ if (!spi->bits_per_word) @@ -534,7 +536,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) struct scatterlist sg_rx, sg_tx; dspi = spi_master_get_devdata(spi->master); - pdata = dspi->pdata; + pdata = &dspi->pdata; spicfg = (struct davinci_spi_config *)spi->controller_data; if (!spicfg) spicfg = &davinci_spi_default_cfg; @@ -758,6 +760,70 @@ rx_dma_failed: return r; } +#if defined(CONFIG_OF) +static const struct of_device_id davinci_spi_of_match[] = { + { + .compatible = "ti,dm644x-spi", + }, + { + .compatible = "ti,da8xx-spi", + .data = (void *)SPI_VERSION_2, + }, + { }, +}; +MODULE_DEVICE_TABLE(of, davini_spi_of_match); + +/** + * spi_davinci_get_pdata - Get platform data from DTS binding + * @pdev: ptr to platform data + * @dspi: ptr to driver data + * + * Parses and populates pdata in dspi from device tree bindings. + * + * NOTE: Not all platform data params are supported currently. + */ +static int spi_davinci_get_pdata(struct platform_device *pdev, + struct davinci_spi *dspi) +{ + struct device_node *node = pdev->dev.of_node; + struct davinci_spi_platform_data *pdata; + unsigned int num_cs, intr_line = 0; + const struct of_device_id *match; + + pdata = &dspi->pdata; + + pdata->version = SPI_VERSION_1; + match = of_match_device(of_match_ptr(davinci_spi_of_match), + &pdev->dev); + if (!match) + return -ENODEV; + + /* match data has the SPI version number for SPI_VERSION_2 */ + if (match->data == (void *)SPI_VERSION_2) + pdata->version = SPI_VERSION_2; + + /* + * default num_cs is 1 and all chipsel are internal to the chip + * indicated by chip_sel being NULL. GPIO based CS is not + * supported yet in DT bindings. + */ + num_cs = 1; + of_property_read_u32(node, "num-cs", &num_cs); + pdata->num_chipselect = num_cs; + of_property_read_u32(node, "ti,davinci-spi-intr-line", &intr_line); + pdata->intr_line = intr_line; + return 0; +} +#else +#define davinci_spi_of_match NULL +static struct davinci_spi_platform_data + *spi_davinci_get_pdata(struct platform_device *pdev, + struct davinci_spi *dspi) +{ + return -ENODEV; +} +#endif + /** * davinci_spi_probe - probe function for SPI Master Controller * @pdev: platform_device structure which contains plateform specific data @@ -780,12 +846,6 @@ static int davinci_spi_probe(struct platform_device *pdev) int i = 0, ret = 0; u32 spipc0; - pdata = pdev->dev.platform_data; - if (pdata == NULL) { - ret = -ENODEV; - goto err; - } - master = spi_alloc_master(&pdev->dev, sizeof(struct davinci_spi)); if (master == NULL) { ret = -ENOMEM; @@ -800,6 +860,19 @@ static int davinci_spi_probe(struct platform_device *pdev) goto free_master; } + if (pdev->dev.platform_data) { + pdata = pdev->dev.platform_data; + dspi->pdata = *pdata; + } else { + /* update dspi pdata with that from the DT */ + ret = spi_davinci_get_pdata(pdev, dspi); + if (ret < 0) + goto free_master; + } + + /* pdata in dspi is now updated and point pdata to that */ + pdata = &dspi->pdata; + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (r == NULL) { ret = -ENOENT; @@ -807,7 +880,6 @@ static int davinci_spi_probe(struct platform_device *pdev) } dspi->pbase = r->start; - dspi->pdata = pdata; mem = request_mem_region(r->start, resource_size(r), pdev->name); if (mem == NULL) { @@ -843,8 +915,9 @@ static int davinci_spi_probe(struct platform_device *pdev) ret = -ENODEV; goto put_master; } - clk_enable(dspi->clk); + clk_prepare_enable(dspi->clk); + master->dev.of_node = pdev->dev.of_node; master->bus_num = pdev->id; master->num_chipselect = pdata->num_chipselect; master->setup = davinci_spi_setup; @@ -927,7 +1000,7 @@ free_dma: dma_release_channel(dspi->dma_rx); dma_release_channel(dspi->dma_tx); free_clk: - clk_disable(dspi->clk); + clk_disable_unprepare(dspi->clk); clk_put(dspi->clk); put_master: spi_master_put(master); @@ -963,7 +1036,7 @@ static int davinci_spi_remove(struct platform_device *pdev) spi_bitbang_stop(&dspi->bitbang); - clk_disable(dspi->clk); + clk_disable_unprepare(dspi->clk); clk_put(dspi->clk); spi_master_put(master); free_irq(dspi->irq, dspi); @@ -978,6 +1051,7 @@ static struct platform_driver davinci_spi_driver = { .driver = { .name = "spi_davinci", .owner = THIS_MODULE, + .of_match_table = davinci_spi_of_match, }, .probe = davinci_spi_probe, .remove = davinci_spi_remove, -- cgit v1.2.3 From cf9c86efecf9510e62388fd174cf607671c59fa3 Mon Sep 17 00:00:00 2001 From: Bastian Hecht Date: Wed, 12 Dec 2012 12:54:48 +0100 Subject: spi/sh-msiof: Add device tree parsing to driver This adds the capability to retrieve setup data from the device tree node. The usage of platform data is still available. Signed-off-by: Bastian Hecht Signed-off-by: Grant Likely --- drivers/spi/spi-sh-msiof.c | 56 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index 96358d0eabb7..8b40d0884f8b 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -592,6 +593,37 @@ static u32 sh_msiof_spi_txrx_word(struct spi_device *spi, unsigned nsecs, return 0; } +#ifdef CONFIG_OF +static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev) +{ + struct sh_msiof_spi_info *info; + struct device_node *np = dev->of_node; + u32 num_cs = 0; + + info = devm_kzalloc(dev, sizeof(struct sh_msiof_spi_info), GFP_KERNEL); + if (!info) { + dev_err(dev, "failed to allocate setup data\n"); + return NULL; + } + + /* Parse the MSIOF properties */ + of_property_read_u32(np, "num-cs", &num_cs); + of_property_read_u32(np, "renesas,tx-fifo-size", + &info->tx_fifo_override); + of_property_read_u32(np, "renesas,rx-fifo-size", + &info->rx_fifo_override); + + info->num_chipselect = num_cs; + + return info; +} +#else +static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev) +{ + return NULL; +} +#endif + static int sh_msiof_spi_probe(struct platform_device *pdev) { struct resource *r; @@ -610,7 +642,17 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) p = spi_master_get_devdata(master); platform_set_drvdata(pdev, p); - p->info = pdev->dev.platform_data; + if (pdev->dev.of_node) + p->info = sh_msiof_spi_parse_dt(&pdev->dev); + else + p->info = pdev->dev.platform_data; + + if (!p->info) { + dev_err(&pdev->dev, "failed to obtain device info\n"); + ret = -ENXIO; + goto err1; + } + init_completion(&p->done); p->clk = clk_get(&pdev->dev, NULL); @@ -715,6 +757,17 @@ static int sh_msiof_spi_runtime_nop(struct device *dev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id sh_msiof_match[] = { + { .compatible = "renesas,sh-msiof", }, + { .compatible = "renesas,sh-mobile-msiof", }, + {}, +}; +MODULE_DEVICE_TABLE(of, sh_msiof_match); +#else +#define sh_msiof_match NULL +#endif + static struct dev_pm_ops sh_msiof_spi_dev_pm_ops = { .runtime_suspend = sh_msiof_spi_runtime_nop, .runtime_resume = sh_msiof_spi_runtime_nop, @@ -727,6 +780,7 @@ static struct platform_driver sh_msiof_spi_drv = { .name = "spi_sh_msiof", .owner = THIS_MODULE, .pm = &sh_msiof_spi_dev_pm_ops, + .of_match_table = sh_msiof_match, }, }; module_platform_driver(sh_msiof_spi_drv); -- cgit v1.2.3 From bb29785e0d6d150181704be2efcc3141044625e2 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Fri, 21 Dec 2012 19:32:09 +0000 Subject: spi/of: Use DT aliases for assigning bus number Linux assigns a number to each spi_master in the system, but when the platform used the device tree, the numbers are dynamically assigned and are not predictable. In general this shouldn't matter since the kernel doesn't use the bus number for anything other than matching a bus to spi_boardinfo (not used for DT). However, sometimes userspace needs to figure out which bus is which, so it makes sense to use the global /aliases namespace to choose a specific bus number. It is safe to derive the bus number from an alias because aliases will never cause two buses to try and use the same bus number. (At one time the cell-index property was used for this purpose, but cell-index has the risk of an id collision). Signed-off-by: Grant Likely Cc: Anatolij Gustschin Cc: Mark Brown --- drivers/spi/spi.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/spi') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 19ee901577da..08ff4acd5225 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1135,6 +1135,9 @@ int spi_register_master(struct spi_master *master) if (master->num_chipselect == 0) return -EINVAL; + if ((master->bus_num < 0) && master->dev.of_node) + master->bus_num = of_alias_get_id(master->dev.of_node, "spi"); + /* convention: dynamically assigned bus IDs count down from the max */ if (master->bus_num < 0) { /* FIXME switch to an IDR based scheme, something like -- cgit v1.2.3 From 766ed70447e0a9cfb23d068a4a929e18e54b0022 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Tue, 18 Dec 2012 14:25:43 +0530 Subject: spi: remove check for bits_per_word on transfer from low level driver The spi core make sure that each transfer structure have the proper setting for bits_per_word before calling low level transfer APIs. Hence it is no more require to check again in low level driver for this field whether this is set correct or not. Removing such code from low level driver. The txx9 change also removes a test for bits_per_word set to 0, and forcing it to 8 in that case. This can also be removed now since spi_setup() ensures spi->bits_per_word is not zero. if (!spi->bits_per_word) spi->bits_per_word = 8; Signed-off-by: Laxman Dewangan Signed-off-by: Grant Likely --- drivers/spi/spi-altera.c | 2 +- drivers/spi/spi-bfin-sport.c | 3 +-- drivers/spi/spi-bfin5xx.c | 3 +-- drivers/spi/spi-bitbang.c | 6 +++--- drivers/spi/spi-clps711x.c | 2 +- drivers/spi/spi-coldfire-qspi.c | 3 +-- drivers/spi/spi-ep93xx.c | 2 +- drivers/spi/spi-s3c64xx.c | 2 +- drivers/spi/spi-sirf.c | 3 +-- drivers/spi/spi-tegra20-slink.c | 9 +++------ drivers/spi/spi-txx9.c | 6 ++---- 11 files changed, 16 insertions(+), 25 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-altera.c b/drivers/spi/spi-altera.c index 5e7314ac51e9..a537f8dffc09 100644 --- a/drivers/spi/spi-altera.c +++ b/drivers/spi/spi-altera.c @@ -134,7 +134,7 @@ static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t) hw->tx = t->tx_buf; hw->rx = t->rx_buf; hw->count = 0; - hw->bytes_per_word = (t->bits_per_word ? : spi->bits_per_word) / 8; + hw->bytes_per_word = t->bits_per_word / 8; hw->len = t->len / hw->bytes_per_word; if (hw->irq >= 0) { diff --git a/drivers/spi/spi-bfin-sport.c b/drivers/spi/spi-bfin-sport.c index ac7ffca7ba47..39b0d1711b4e 100644 --- a/drivers/spi/spi-bfin-sport.c +++ b/drivers/spi/spi-bfin-sport.c @@ -416,8 +416,7 @@ bfin_sport_spi_pump_transfers(unsigned long data) drv_data->cs_change = transfer->cs_change; /* Bits per word setup */ - bits_per_word = transfer->bits_per_word ? : - message->spi->bits_per_word ? : 8; + bits_per_word = transfer->bits_per_word; if (bits_per_word % 16 == 0) drv_data->ops = &bfin_sport_transfer_ops_u16; else diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c index 0429d833f75b..7d7c9918fffe 100644 --- a/drivers/spi/spi-bfin5xx.c +++ b/drivers/spi/spi-bfin5xx.c @@ -642,8 +642,7 @@ static void bfin_spi_pump_transfers(unsigned long data) drv_data->cs_change = transfer->cs_change; /* Bits per word setup */ - bits_per_word = transfer->bits_per_word ? : - message->spi->bits_per_word ? : 8; + bits_per_word = transfer->bits_per_word; if (bits_per_word % 16 == 0) { drv_data->n_bytes = bits_per_word/8; drv_data->len = (transfer->len) >> 1; diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index 8b3d8efafd3c..61beaec7cbed 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -69,7 +69,7 @@ static unsigned bitbang_txrx_8( unsigned ns, struct spi_transfer *t ) { - unsigned bits = t->bits_per_word ? : spi->bits_per_word; + unsigned bits = t->bits_per_word; unsigned count = t->len; const u8 *tx = t->tx_buf; u8 *rx = t->rx_buf; @@ -95,7 +95,7 @@ static unsigned bitbang_txrx_16( unsigned ns, struct spi_transfer *t ) { - unsigned bits = t->bits_per_word ? : spi->bits_per_word; + unsigned bits = t->bits_per_word; unsigned count = t->len; const u16 *tx = t->tx_buf; u16 *rx = t->rx_buf; @@ -121,7 +121,7 @@ static unsigned bitbang_txrx_32( unsigned ns, struct spi_transfer *t ) { - unsigned bits = t->bits_per_word ? : spi->bits_per_word; + unsigned bits = t->bits_per_word; unsigned count = t->len; const u32 *tx = t->tx_buf; u32 *rx = t->rx_buf; diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c index 1366c4620d5d..a11cbf02691a 100644 --- a/drivers/spi/spi-clps711x.c +++ b/drivers/spi/spi-clps711x.c @@ -68,7 +68,7 @@ static int spi_clps711x_setup_xfer(struct spi_device *spi, struct spi_transfer *xfer) { u32 speed = xfer->speed_hz ? : spi->max_speed_hz; - u8 bpw = xfer->bits_per_word ? : spi->bits_per_word; + u8 bpw = xfer->bits_per_word; struct spi_clps711x_data *hw = spi_master_get_devdata(spi->master); if (bpw != 8) { diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c index 58466b810da4..7b5cc9e4e94d 100644 --- a/drivers/spi/spi-coldfire-qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c @@ -329,8 +329,7 @@ static int mcfqspi_transfer_one_message(struct spi_master *master, mcfqspi_cs_select(mcfqspi, spi->chip_select, cs_high); mcfqspi_wr_qir(mcfqspi, MCFQSPI_QIR_SPIFE); - if ((t->bits_per_word ? t->bits_per_word : - spi->bits_per_word) == 8) + if (t->bits_per_word == 8) mcfqspi_transfer_msg8(mcfqspi, t->len, t->tx_buf, t->rx_buf); else diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index acb1e1935c5a..aecbff16ad60 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -446,7 +446,7 @@ static inline int bits_per_word(const struct ep93xx_spi *espi) struct spi_message *msg = espi->current_msg; struct spi_transfer *t = msg->state; - return t->bits_per_word ? t->bits_per_word : msg->spi->bits_per_word; + return t->bits_per_word; } static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index ad93231a8038..d77b6560b67f 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -697,7 +697,7 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, INIT_COMPLETION(sdd->xfer_completion); /* Only BPW and Speed may change across transfers */ - bpw = xfer->bits_per_word ? : spi->bits_per_word; + bpw = xfer->bits_per_word; speed = xfer->speed_hz ? : spi->max_speed_hz; if (xfer->len % (bpw / 8)) { diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index e0f43a512e84..750666751efd 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c @@ -382,8 +382,7 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) sspi = spi_master_get_devdata(spi->master); - bits_per_word = t && t->bits_per_word ? t->bits_per_word : - spi->bits_per_word; + bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word; hz = t && t->speed_hz ? t->speed_hz : spi->max_speed_hz; /* Enable IO mode for RX, TX */ diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index 651167f2e0af..7a95bddfb604 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -284,8 +284,7 @@ static unsigned tegra_slink_calculate_curr_xfer_param( unsigned max_len; unsigned total_fifo_words; - bits_per_word = t->bits_per_word ? t->bits_per_word : - spi->bits_per_word; + bits_per_word = t->bits_per_word; tspi->bytes_per_word = (bits_per_word - 1) / 8 + 1; if (bits_per_word == 8 || bits_per_word == 16) { @@ -378,8 +377,7 @@ static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf( } else { unsigned int bits_per_word; - bits_per_word = t->bits_per_word ? t->bits_per_word : - tspi->cur_spi->bits_per_word; + bits_per_word = t->bits_per_word; for (count = 0; count < rx_full_count; count++) { x = tegra_slink_readl(tspi, SLINK_RX_FIFO); for (i = 0; (i < tspi->bytes_per_word); i++) @@ -444,8 +442,7 @@ static void tegra_slink_copy_spi_rxbuf_to_client_rxbuf( unsigned int x; unsigned int rx_mask, bits_per_word; - bits_per_word = t->bits_per_word ? t->bits_per_word : - tspi->cur_spi->bits_per_word; + bits_per_word = t->bits_per_word; rx_mask = (1 << bits_per_word) - 1; for (count = 0; count < tspi->curr_dma_words; count++) { x = tspi->rx_dma_buf[count]; diff --git a/drivers/spi/spi-txx9.c b/drivers/spi/spi-txx9.c index d5a3cbb646cb..550b5f48fd8f 100644 --- a/drivers/spi/spi-txx9.c +++ b/drivers/spi/spi-txx9.c @@ -189,9 +189,8 @@ static void txx9spi_work_one(struct txx9spi *c, struct spi_message *m) unsigned int len = t->len; unsigned int wsize; u32 speed_hz = t->speed_hz ? : spi->max_speed_hz; - u8 bits_per_word = t->bits_per_word ? : spi->bits_per_word; + u8 bits_per_word = t->bits_per_word; - bits_per_word = bits_per_word ? : 8; wsize = bits_per_word >> 3; /* in bytes */ if (prev_speed_hz != speed_hz @@ -316,9 +315,8 @@ static int txx9spi_transfer(struct spi_device *spi, struct spi_message *m) /* check each transfer's parameters */ list_for_each_entry (t, &m->transfers, transfer_list) { u32 speed_hz = t->speed_hz ? : spi->max_speed_hz; - u8 bits_per_word = t->bits_per_word ? : spi->bits_per_word; + u8 bits_per_word = t->bits_per_word; - bits_per_word = bits_per_word ? : 8; if (!t->tx_buf && !t->rx_buf && t->len) return -EINVAL; if (bits_per_word != 8 && bits_per_word != 16) -- cgit v1.2.3 From e5118cd2c2881db18a92eec68d1b29db9bcbcaf3 Mon Sep 17 00:00:00 2001 From: Barry Song Date: Wed, 26 Dec 2012 10:48:33 +0800 Subject: spi/sirf: use clk_prepare_enable and clk_disable_unprepare Convert clk_enable/clk_disable to clk_prepare_enable/clk_disable_unprepare calls as required by common clock framework. Signed-off-by: Barry Song Signed-off-by: Grant Likely --- drivers/spi/spi-sirf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index 750666751efd..1f04979492aa 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c @@ -569,7 +569,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) ret = -EINVAL; goto free_pin; } - clk_enable(sspi->clk); + clk_prepare_enable(sspi->clk); sspi->ctrl_freq = clk_get_rate(sspi->clk); init_completion(&sspi->done); @@ -593,7 +593,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) return 0; free_clk: - clk_disable(sspi->clk); + clk_disable_unprepare(sspi->clk); clk_put(sspi->clk); free_pin: pinctrl_put(sspi->p); @@ -617,7 +617,7 @@ static int spi_sirfsoc_remove(struct platform_device *pdev) if (sspi->chipselect[i] > 0) gpio_free(sspi->chipselect[i]); } - clk_disable(sspi->clk); + clk_disable_unprepare(sspi->clk); clk_put(sspi->clk); pinctrl_put(sspi->p); spi_master_put(master); -- cgit v1.2.3 From f3b8a8ecc5922d9dff303ae2fadc1eae608a6f7c Mon Sep 17 00:00:00 2001 From: Barry Song Date: Wed, 26 Dec 2012 10:48:34 +0800 Subject: spi/sirf: add support for new SiRFmarco SMP SoC the driver is also compatible with SiRFmarco except SiRFprimaII, so simply add "sirf,marco-spi" to OF match table. Signed-off-by: Barry Song Signed-off-by: Grant Likely --- drivers/spi/spi-sirf.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/spi') diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index 1f04979492aa..6a5626d146b7 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c @@ -658,6 +658,7 @@ static const struct dev_pm_ops spi_sirfsoc_pm_ops = { static const struct of_device_id spi_sirfsoc_of_match[] = { { .compatible = "sirf,prima2-spi", }, + { .compatible = "sirf,marco-spi", }, {}