From 91565c4068042b3d8e37e64e393ca105476419bd Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 14 Oct 2010 08:54:55 -0600 Subject: spi/xilinx: Eliminate pdata references from common code. The current code has the OF binding modifying the platform_data pointer which it must not do, and the common code doesn't really need to use a pdata pointer. This patch eliminates the platform_data references from the common part of the driver in preparation for merging the OF and non-OF versions. Signed-off-by: Grant Likely Tested-by: Michal Simek --- drivers/spi/xilinx_spi.c | 14 ++++---------- drivers/spi/xilinx_spi.h | 2 +- drivers/spi/xilinx_spi_of.c | 17 ++++------------- drivers/spi/xilinx_spi_pltfm.c | 4 +++- 4 files changed, 12 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c index 80f2db5bcfd6..efb28ba4a4ec 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/xilinx_spi.c @@ -351,18 +351,12 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id) } struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, - u32 irq, s16 bus_num) + u32 irq, s16 bus_num, int num_cs, int little_endian, int bits_per_word) { struct spi_master *master; struct xilinx_spi *xspi; - struct xspi_platform_data *pdata = dev->platform_data; int ret; - if (!pdata) { - dev_err(dev, "No platform data attached\n"); - return NULL; - } - master = spi_alloc_master(dev, sizeof(struct xilinx_spi)); if (!master) return NULL; @@ -389,21 +383,21 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, } master->bus_num = bus_num; - master->num_chipselect = pdata->num_chipselect; + master->num_chipselect = num_cs; #ifdef CONFIG_OF master->dev.of_node = dev->of_node; #endif xspi->mem = *mem; xspi->irq = irq; - if (pdata->little_endian) { + if (little_endian) { xspi->read_fn = xspi_read32; xspi->write_fn = xspi_write32; } else { xspi->read_fn = xspi_read32_be; xspi->write_fn = xspi_write32_be; } - xspi->bits_per_word = pdata->bits_per_word; + xspi->bits_per_word = bits_per_word; if (xspi->bits_per_word == 8) { xspi->tx_fn = xspi_tx8; xspi->rx_fn = xspi_rx8; diff --git a/drivers/spi/xilinx_spi.h b/drivers/spi/xilinx_spi.h index d211accf68d2..d710a33f569f 100644 --- a/drivers/spi/xilinx_spi.h +++ b/drivers/spi/xilinx_spi.h @@ -26,7 +26,7 @@ #define XILINX_SPI_NAME "xilinx_spi" struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, - u32 irq, s16 bus_num); + u32 irq, s16 bus_num, int num_cs, int little_endian, int bits_per_word); void xilinx_spi_deinit(struct spi_master *master); #endif diff --git a/drivers/spi/xilinx_spi_of.c b/drivers/spi/xilinx_spi_of.c index b66c2dbf20a5..c2d8ade87a38 100644 --- a/drivers/spi/xilinx_spi_of.c +++ b/drivers/spi/xilinx_spi_of.c @@ -42,12 +42,11 @@ static int __devinit xilinx_spi_of_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct spi_master *master; - struct xspi_platform_data *pdata; struct resource r_mem; struct resource r_irq; int rc = 0; const u32 *prop; - int len; + int len, num_cs; rc = of_address_to_resource(ofdev->dev.of_node, 0, &r_mem); if (rc) { @@ -61,21 +60,15 @@ static int __devinit xilinx_spi_of_probe(struct platform_device *ofdev, return -ENODEV; } - ofdev->dev.platform_data = - kzalloc(sizeof(struct xspi_platform_data), GFP_KERNEL); - pdata = ofdev->dev.platform_data; - if (!pdata) - return -ENOMEM; - /* number of slave select bits is required */ prop = of_get_property(ofdev->dev.of_node, "xlnx,num-ss-bits", &len); if (!prop || len < sizeof(*prop)) { dev_warn(&ofdev->dev, "no 'xlnx,num-ss-bits' property\n"); return -EINVAL; } - pdata->num_chipselect = *prop; - pdata->bits_per_word = 8; - master = xilinx_spi_init(&ofdev->dev, &r_mem, r_irq.start, -1); + num_cs = __be32_to_cpup(prop); + master = xilinx_spi_init(&ofdev->dev, &r_mem, r_irq.start, -1, + num_cs, 0, 8); if (!master) return -ENODEV; @@ -88,8 +81,6 @@ static int __devexit xilinx_spi_remove(struct platform_device *ofdev) { xilinx_spi_deinit(dev_get_drvdata(&ofdev->dev)); dev_set_drvdata(&ofdev->dev, 0); - kfree(ofdev->dev.platform_data); - ofdev->dev.platform_data = NULL; return 0; } diff --git a/drivers/spi/xilinx_spi_pltfm.c b/drivers/spi/xilinx_spi_pltfm.c index 24debac646a9..a16722acafea 100644 --- a/drivers/spi/xilinx_spi_pltfm.c +++ b/drivers/spi/xilinx_spi_pltfm.c @@ -54,7 +54,9 @@ static int __devinit xilinx_spi_probe(struct platform_device *dev) if (irq < 0) return -ENXIO; - master = xilinx_spi_init(&dev->dev, r, irq, dev->id); + master = xilinx_spi_init(&dev->dev, r, irq, dev->id, + pdata->num_chipselect, pdata->little_endian, + pdata->bits_per_word); if (!master) return -ENODEV; -- cgit v1.2.3 From 8fd8821b62397f8ddb7bfb23c3246a22770ab2ee Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 14 Oct 2010 09:04:29 -0600 Subject: spi/xilinx: fold platform_driver support into main body This patch merges the platform driver support into the main body of xilinx_spi.c in preparation for merging the OF and non-OF support code. Signed-off-by: Grant Likely Tested-by: Michal Simek --- drivers/spi/Kconfig | 7 --- drivers/spi/Makefile | 1 - drivers/spi/xilinx_spi.c | 79 ++++++++++++++++++++++++++++--- drivers/spi/xilinx_spi_pltfm.c | 104 ----------------------------------------- 4 files changed, 73 insertions(+), 118 deletions(-) delete mode 100644 drivers/spi/xilinx_spi_pltfm.c (limited to 'drivers') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 78f9fd02c1b2..58ad21c700d3 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -368,13 +368,6 @@ config SPI_XILINX_OF help This is the OF driver for the SPI controller IP from the Xilinx EDK. -config SPI_XILINX_PLTFM - tristate "Xilinx SPI controller platform device" - depends on SPI_XILINX - help - This is the platform driver for the SPI controller IP - from the Xilinx EDK. - config SPI_NUC900 tristate "Nuvoton NUC900 series SPI" depends on ARCH_W90X900 && EXPERIMENTAL diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 8bc1a5abac1f..0d03159b5668 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -44,7 +44,6 @@ obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi_topcliff_pch.o obj-$(CONFIG_SPI_TXX9) += spi_txx9.o obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o obj-$(CONFIG_SPI_XILINX_OF) += xilinx_spi_of.o -obj-$(CONFIG_SPI_XILINX_PLTFM) += xilinx_spi_pltfm.o obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o obj-$(CONFIG_SPI_SH_MSIOF) += spi_sh_msiof.o obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c index efb28ba4a4ec..bb3b520df9dd 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/xilinx_spi.c @@ -1,20 +1,22 @@ /* - * xilinx_spi.c - * * Xilinx SPI controller driver (master mode only) * * Author: MontaVista Software, Inc. * source@mvista.com * - * 2002-2007 (c) MontaVista Software, Inc. This file is licensed under the - * terms of the GNU General Public License version 2. This program is licensed - * "as is" without any warranty of any kind, whether express or implied. + * Copyright (c) 2010 Secret Lab Technologies, Ltd. + * Copyright (c) 2009 Intel Corporation + * 2002-2007 (c) MontaVista Software, Inc. + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. */ #include #include #include - +#include #include #include #include @@ -456,6 +458,71 @@ void xilinx_spi_deinit(struct spi_master *master) } EXPORT_SYMBOL(xilinx_spi_deinit); +static int __devinit xilinx_spi_probe(struct platform_device *dev) +{ + struct xspi_platform_data *pdata; + struct resource *r; + int irq; + struct spi_master *master; + u8 i; + + pdata = dev->dev.platform_data; + if (!pdata) + return -ENODEV; + + r = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (!r) + return -ENODEV; + + irq = platform_get_irq(dev, 0); + if (irq < 0) + return -ENXIO; + + master = xilinx_spi_init(&dev->dev, r, irq, dev->id, + pdata->num_chipselect, pdata->little_endian, + pdata->bits_per_word); + if (!master) + return -ENODEV; + + for (i = 0; i < pdata->num_devices; i++) + spi_new_device(master, pdata->devices + i); + + platform_set_drvdata(dev, master); + return 0; +} + +static int __devexit xilinx_spi_remove(struct platform_device *dev) +{ + xilinx_spi_deinit(platform_get_drvdata(dev)); + platform_set_drvdata(dev, 0); + + return 0; +} + +/* work with hotplug and coldplug */ +MODULE_ALIAS("platform:" XILINX_SPI_NAME); + +static struct platform_driver xilinx_spi_driver = { + .probe = xilinx_spi_probe, + .remove = __devexit_p(xilinx_spi_remove), + .driver = { + .name = XILINX_SPI_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init xilinx_spi_pltfm_init(void) +{ + return platform_driver_register(&xilinx_spi_driver); +} +module_init(xilinx_spi_pltfm_init); + +static void __exit xilinx_spi_pltfm_exit(void) +{ + platform_driver_unregister(&xilinx_spi_driver); +} +module_exit(xilinx_spi_pltfm_exit); + MODULE_AUTHOR("MontaVista Software, Inc. "); MODULE_DESCRIPTION("Xilinx SPI driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/spi/xilinx_spi_pltfm.c b/drivers/spi/xilinx_spi_pltfm.c deleted file mode 100644 index a16722acafea..000000000000 --- a/drivers/spi/xilinx_spi_pltfm.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Support for Xilinx SPI platform devices - * Copyright (c) 2009 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* Supports: - * Xilinx SPI devices as platform devices - * - * Inspired by xilinx_spi.c, 2002-2007 (c) MontaVista Software, Inc. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "xilinx_spi.h" - -static int __devinit xilinx_spi_probe(struct platform_device *dev) -{ - struct xspi_platform_data *pdata; - struct resource *r; - int irq; - struct spi_master *master; - u8 i; - - pdata = dev->dev.platform_data; - if (!pdata) - return -ENODEV; - - r = platform_get_resource(dev, IORESOURCE_MEM, 0); - if (!r) - return -ENODEV; - - irq = platform_get_irq(dev, 0); - if (irq < 0) - return -ENXIO; - - master = xilinx_spi_init(&dev->dev, r, irq, dev->id, - pdata->num_chipselect, pdata->little_endian, - pdata->bits_per_word); - if (!master) - return -ENODEV; - - for (i = 0; i < pdata->num_devices; i++) - spi_new_device(master, pdata->devices + i); - - platform_set_drvdata(dev, master); - return 0; -} - -static int __devexit xilinx_spi_remove(struct platform_device *dev) -{ - xilinx_spi_deinit(platform_get_drvdata(dev)); - platform_set_drvdata(dev, 0); - - return 0; -} - -/* work with hotplug and coldplug */ -MODULE_ALIAS("platform:" XILINX_SPI_NAME); - -static struct platform_driver xilinx_spi_driver = { - .probe = xilinx_spi_probe, - .remove = __devexit_p(xilinx_spi_remove), - .driver = { - .name = XILINX_SPI_NAME, - .owner = THIS_MODULE, - }, -}; - -static int __init xilinx_spi_pltfm_init(void) -{ - return platform_driver_register(&xilinx_spi_driver); -} -module_init(xilinx_spi_pltfm_init); - -static void __exit xilinx_spi_pltfm_exit(void) -{ - platform_driver_unregister(&xilinx_spi_driver); -} -module_exit(xilinx_spi_pltfm_exit); - -MODULE_AUTHOR("Mocean Laboratories "); -MODULE_DESCRIPTION("Xilinx SPI platform driver"); -MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From eae6cb31d890e2860f9ce1b8ba73c27b6005af68 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 14 Oct 2010 09:32:53 -0600 Subject: spi/xilinx: merge OF support code into main driver Now that the of_platform_bus_type has been merged with the platform bus type, a single platform driver can handle both OF and non-OF use cases. This patch merges the OF support into the platform driver. Signed-off-by: Grant Likely Tested-by: Michal Simek --- drivers/spi/Kconfig | 7 --- drivers/spi/Makefile | 1 - drivers/spi/xilinx_spi.c | 56 ++++++++++++++++---- drivers/spi/xilinx_spi.h | 32 ------------ drivers/spi/xilinx_spi_of.c | 124 -------------------------------------------- 5 files changed, 45 insertions(+), 175 deletions(-) delete mode 100644 drivers/spi/xilinx_spi.h delete mode 100644 drivers/spi/xilinx_spi_of.c (limited to 'drivers') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 58ad21c700d3..665d03d4e022 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -353,7 +353,6 @@ config SPI_XILINX tristate "Xilinx SPI controller common module" depends on HAS_IOMEM && EXPERIMENTAL select SPI_BITBANG - select SPI_XILINX_OF if (XILINX_VIRTEX || MICROBLAZE) help This exposes the SPI controller IP from the Xilinx EDK. @@ -362,12 +361,6 @@ config SPI_XILINX Or for the DS570, see "XPS Serial Peripheral Interface (SPI) (v2.00b)" -config SPI_XILINX_OF - tristate "Xilinx SPI controller OF device" - depends on SPI_XILINX && (XILINX_VIRTEX || MICROBLAZE) - help - This is the OF driver for the SPI controller IP from the Xilinx EDK. - config SPI_NUC900 tristate "Nuvoton NUC900 series SPI" depends on ARCH_W90X900 && EXPERIMENTAL diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 0d03159b5668..02dad4ae412d 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -43,7 +43,6 @@ obj-$(CONFIG_SPI_TEGRA) += spi_tegra.o obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi_topcliff_pch.o obj-$(CONFIG_SPI_TXX9) += spi_txx9.o obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o -obj-$(CONFIG_SPI_XILINX_OF) += xilinx_spi_of.o obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o obj-$(CONFIG_SPI_SH_MSIOF) += spi_sh_msiof.o obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c index bb3b520df9dd..7adaef62a991 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/xilinx_spi.c @@ -16,13 +16,12 @@ #include #include #include +#include #include #include #include -#include - -#include "xilinx_spi.h" #include +#include #define XILINX_SPI_NAME "xilinx_spi" @@ -352,6 +351,15 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id) return IRQ_HANDLED; } +#ifdef CONFIG_OF +static const struct of_device_id xilinx_spi_of_match[] = { + { .compatible = "xlnx,xps-spi-2.00.a", }, + { .compatible = "xlnx,xps-spi-2.00.b", }, + {} +}; +MODULE_DEVICE_TABLE(of, xilinx_spi_of_match); +#endif + struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, u32 irq, s16 bus_num, int num_cs, int little_endian, int bits_per_word) { @@ -462,13 +470,35 @@ static int __devinit xilinx_spi_probe(struct platform_device *dev) { struct xspi_platform_data *pdata; struct resource *r; - int irq; + int irq, num_cs = 0, little_endian = 0, bits_per_word = 8; struct spi_master *master; u8 i; pdata = dev->dev.platform_data; - if (!pdata) - return -ENODEV; + if (pdata) { + num_cs = pdata->num_chipselect; + little_endian = pdata->little_endian; + bits_per_word = pdata->bits_per_word; + } + +#ifdef CONFIG_OF + if (dev->dev.of_node) { + const __be32 *prop; + int len; + + /* number of slave select bits is required */ + prop = of_get_property(dev->dev.of_node, "xlnx,num-ss-bits", + &len); + if (prop && len >= sizeof(*prop)) + num_cs = __be32_to_cpup(prop); + } +#endif + + if (!num_cs) { + dev_err(&dev->dev, "Missing slave select configuration data\n"); + return -EINVAL; + } + r = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!r) @@ -478,14 +508,15 @@ static int __devinit xilinx_spi_probe(struct platform_device *dev) if (irq < 0) return -ENXIO; - master = xilinx_spi_init(&dev->dev, r, irq, dev->id, - pdata->num_chipselect, pdata->little_endian, - pdata->bits_per_word); + master = xilinx_spi_init(&dev->dev, r, irq, dev->id, num_cs, + little_endian, bits_per_word); if (!master) return -ENODEV; - for (i = 0; i < pdata->num_devices; i++) - spi_new_device(master, pdata->devices + i); + if (pdata) { + for (i = 0; i < pdata->num_devices; i++) + spi_new_device(master, pdata->devices + i); + } platform_set_drvdata(dev, master); return 0; @@ -508,6 +539,9 @@ static struct platform_driver xilinx_spi_driver = { .driver = { .name = XILINX_SPI_NAME, .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = xilinx_spi_of_match, +#endif }, }; diff --git a/drivers/spi/xilinx_spi.h b/drivers/spi/xilinx_spi.h deleted file mode 100644 index d710a33f569f..000000000000 --- a/drivers/spi/xilinx_spi.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Xilinx SPI device driver API and platform data header file - * - * Copyright (c) 2009 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _XILINX_SPI_H_ -#define _XILINX_SPI_H_ - -#include -#include - -#define XILINX_SPI_NAME "xilinx_spi" - -struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, - u32 irq, s16 bus_num, int num_cs, int little_endian, int bits_per_word); - -void xilinx_spi_deinit(struct spi_master *master); -#endif diff --git a/drivers/spi/xilinx_spi_of.c b/drivers/spi/xilinx_spi_of.c deleted file mode 100644 index c2d8ade87a38..000000000000 --- a/drivers/spi/xilinx_spi_of.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Xilinx SPI OF device driver - * - * Copyright (c) 2009 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* Supports: - * Xilinx SPI devices as OF devices - * - * Inspired by xilinx_spi.c, 2002-2007 (c) MontaVista Software, Inc. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include "xilinx_spi.h" - - -static int __devinit xilinx_spi_of_probe(struct platform_device *ofdev, - const struct of_device_id *match) -{ - struct spi_master *master; - struct resource r_mem; - struct resource r_irq; - int rc = 0; - const u32 *prop; - int len, num_cs; - - rc = of_address_to_resource(ofdev->dev.of_node, 0, &r_mem); - if (rc) { - dev_warn(&ofdev->dev, "invalid address\n"); - return rc; - } - - rc = of_irq_to_resource(ofdev->dev.of_node, 0, &r_irq); - if (rc == NO_IRQ) { - dev_warn(&ofdev->dev, "no IRQ found\n"); - return -ENODEV; - } - - /* number of slave select bits is required */ - prop = of_get_property(ofdev->dev.of_node, "xlnx,num-ss-bits", &len); - if (!prop || len < sizeof(*prop)) { - dev_warn(&ofdev->dev, "no 'xlnx,num-ss-bits' property\n"); - return -EINVAL; - } - num_cs = __be32_to_cpup(prop); - master = xilinx_spi_init(&ofdev->dev, &r_mem, r_irq.start, -1, - num_cs, 0, 8); - if (!master) - return -ENODEV; - - dev_set_drvdata(&ofdev->dev, master); - - return 0; -} - -static int __devexit xilinx_spi_remove(struct platform_device *ofdev) -{ - xilinx_spi_deinit(dev_get_drvdata(&ofdev->dev)); - dev_set_drvdata(&ofdev->dev, 0); - return 0; -} - -static int __exit xilinx_spi_of_remove(struct platform_device *op) -{ - return xilinx_spi_remove(op); -} - -static const struct of_device_id xilinx_spi_of_match[] = { - { .compatible = "xlnx,xps-spi-2.00.a", }, - { .compatible = "xlnx,xps-spi-2.00.b", }, - {} -}; - -MODULE_DEVICE_TABLE(of, xilinx_spi_of_match); - -static struct of_platform_driver xilinx_spi_of_driver = { - .probe = xilinx_spi_of_probe, - .remove = __exit_p(xilinx_spi_of_remove), - .driver = { - .name = "xilinx-xps-spi", - .owner = THIS_MODULE, - .of_match_table = xilinx_spi_of_match, - }, -}; - -static int __init xilinx_spi_of_init(void) -{ - return of_register_platform_driver(&xilinx_spi_of_driver); -} -module_init(xilinx_spi_of_init); - -static void __exit xilinx_spi_of_exit(void) -{ - of_unregister_platform_driver(&xilinx_spi_of_driver); -} -module_exit(xilinx_spi_of_exit); - -MODULE_AUTHOR("Mocean Laboratories "); -MODULE_DESCRIPTION("Xilinx SPI platform driver"); -MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From bc3f67a3e1b20756d4bfa5886a6b8fd0c068e6a4 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 14 Nov 2010 19:04:47 -0800 Subject: drivers/spi: Remove unnecessary semicolons Signed-off-by: Joe Perches Signed-off-by: Grant Likely --- drivers/spi/amba-pl022.c | 2 +- drivers/spi/spi_nuc900.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index fb3d1b31772d..2e506319b60f 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c @@ -956,7 +956,7 @@ static int configure_dma(struct pl022 *pl022) tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; break; case WRITING_U32: - tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;; + tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; break; } diff --git a/drivers/spi/spi_nuc900.c b/drivers/spi/spi_nuc900.c index dff63be0d0a8..d5be18b3078c 100644 --- a/drivers/spi/spi_nuc900.c +++ b/drivers/spi/spi_nuc900.c @@ -449,7 +449,7 @@ err_iomap: release_mem_region(hw->res->start, resource_size(hw->res)); kfree(hw->ioarea); err_pdata: - spi_master_put(hw->master);; + spi_master_put(hw->master); err_nomem: return err; -- cgit v1.2.3 From 3b740b10e9424f7ffb9baab1e6a3ff361cbf8ce3 Mon Sep 17 00:00:00 2001 From: Brian Niebuhr Date: Fri, 3 Sep 2010 14:50:07 +0530 Subject: spi: davinci: fix checkpatch errors Fix the following checkpatch error: WARNING: unnecessary whitespace before a quoted newline + dev_info(&pdev->dev, "Controller at 0x%p \n", davinci_spi->base); Signed-off-by: Brian Niebuhr Tested-By: Michael Williamson Signed-off-by: Sekhar Nori --- drivers/spi/davinci_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index b85090caf7cf..6b0476225217 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -1184,7 +1184,7 @@ static int davinci_spi_probe(struct platform_device *pdev) if (ret) goto free_clk; - dev_info(&pdev->dev, "Controller at 0x%p \n", davinci_spi->base); + dev_info(&pdev->dev, "Controller at 0x%p\n", davinci_spi->base); if (!pdata->poll_mode) dev_info(&pdev->dev, "Operating in interrupt mode" -- cgit v1.2.3 From 778e261ed678c3654386fc38bc6c50353ce04cc7 Mon Sep 17 00:00:00 2001 From: Brian Niebuhr Date: Fri, 3 Sep 2010 15:15:06 +0530 Subject: spi: davinci: whitespace cleanup Cleanup unnecessary white space from various parts of the file. Signed-off-by: Brian Niebuhr Tested-By: Michael Williamson Signed-off-by: Sekhar Nori --- drivers/spi/davinci_spi.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index 6b0476225217..2fa5bec807ce 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -175,7 +175,7 @@ struct davinci_spi { u8 *tmp_buf; int count; struct davinci_spi_dma *dma_channels; - 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 *); @@ -435,7 +435,6 @@ static int davinci_spi_request_dma(struct spi_device *spi) * * This functions sets the default transfer method. */ - static int davinci_spi_setup(struct spi_device *spi) { int retval; @@ -1096,7 +1095,6 @@ static int davinci_spi_probe(struct platform_device *pdev) } clk_enable(davinci_spi->clk); - master->bus_num = pdev->id; master->num_chipselect = pdata->num_chipselect; master->setup = davinci_spi_setup; @@ -1113,15 +1111,15 @@ static int davinci_spi_probe(struct platform_device *pdev) davinci_spi->bitbang.flags |= SPI_READY; if (use_dma) { - r = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (r) - dma_rx_chan = r->start; - r = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (r) - dma_tx_chan = r->start; - r = platform_get_resource(pdev, IORESOURCE_DMA, 2); - if (r) - dma_eventq = r->start; + r = platform_get_resource(pdev, IORESOURCE_DMA, 0); + if (r) + dma_rx_chan = r->start; + r = platform_get_resource(pdev, IORESOURCE_DMA, 1); + if (r) + dma_tx_chan = r->start; + r = platform_get_resource(pdev, IORESOURCE_DMA, 2); + if (r) + dma_eventq = r->start; } if (!use_dma || -- cgit v1.2.3 From c3c475c2353f6d13a5c77c3b6203c0240339da7d Mon Sep 17 00:00:00 2001 From: Brian Niebuhr Date: Fri, 3 Sep 2010 16:19:09 +0530 Subject: spi: davinci: remove unused variable 'pdata' The 'pdata' variable is unused in couple of routines. Remove such occurences. Signed-off-by: Brian Niebuhr Tested-By: Michael Williamson Signed-off-by: Sekhar Nori --- drivers/spi/davinci_spi.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index 2fa5bec807ce..a92f507eaff7 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -299,12 +299,10 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, { struct davinci_spi *davinci_spi; - struct davinci_spi_platform_data *pdata; u8 bits_per_word = 0; u32 hz = 0, prescale = 0, clkspeed; davinci_spi = spi_master_get_devdata(spi->master); - pdata = davinci_spi->pdata; if (t) { bits_per_word = t->bits_per_word; @@ -357,11 +355,9 @@ static void davinci_spi_dma_rx_callback(unsigned lch, u16 ch_status, void *data) struct spi_device *spi = (struct spi_device *)data; struct davinci_spi *davinci_spi; struct davinci_spi_dma *davinci_spi_dma; - struct davinci_spi_platform_data *pdata; davinci_spi = spi_master_get_devdata(spi->master); davinci_spi_dma = &(davinci_spi->dma_channels[spi->chip_select]); - pdata = davinci_spi->pdata; if (ch_status == DMA_COMPLETE) edma_stop(davinci_spi_dma->dma_rx_channel); @@ -378,11 +374,9 @@ static void davinci_spi_dma_tx_callback(unsigned lch, u16 ch_status, void *data) struct spi_device *spi = (struct spi_device *)data; struct davinci_spi *davinci_spi; struct davinci_spi_dma *davinci_spi_dma; - struct davinci_spi_platform_data *pdata; davinci_spi = spi_master_get_devdata(spi->master); davinci_spi_dma = &(davinci_spi->dma_channels[spi->chip_select]); - pdata = davinci_spi->pdata; if (ch_status == DMA_COMPLETE) edma_stop(davinci_spi_dma->dma_tx_channel); @@ -398,13 +392,11 @@ static int davinci_spi_request_dma(struct spi_device *spi) { struct davinci_spi *davinci_spi; struct davinci_spi_dma *davinci_spi_dma; - struct davinci_spi_platform_data *pdata; struct device *sdev; int r; davinci_spi = spi_master_get_devdata(spi->master); davinci_spi_dma = &davinci_spi->dma_channels[spi->chip_select]; - pdata = davinci_spi->pdata; sdev = davinci_spi->bitbang.master->dev.parent; r = edma_alloc_channel(davinci_spi_dma->dma_rx_sync_dev, -- cgit v1.2.3 From 8e206f1cbd0d1387bf7d5e463ca880b43458e2ea Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Fri, 20 Aug 2010 16:20:49 +0530 Subject: spi: davinci: removed unused #defines Remove unused defines from code which should help in easy reading of code. Also, use the opportuinity to keep the SPIGCR1 register defines together. Tested-By: Michael Williamson Tested-By: Brian Niebuhr Signed-off-by: Sekhar Nori --- drivers/spi/davinci_spi.c | 33 ++------------------------------- 1 file changed, 2 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index a92f507eaff7..7bd0a55f5bbd 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -54,16 +54,12 @@ #define SPIFMT_WDELAY_SHIFT 24 #define SPIFMT_CHARLEN_MASK 0x0000001Fu -/* SPIGCR1 */ -#define SPIGCR1_SPIENA_MASK 0x01000000u /* SPIPC0 */ #define SPIPC0_DIFUN_MASK BIT(11) /* MISO */ #define SPIPC0_DOFUN_MASK BIT(10) /* MOSI */ #define SPIPC0_CLKFUN_MASK BIT(9) /* CLK */ #define SPIPC0_SPIENA_MASK BIT(8) /* nREADY */ -#define SPIPC0_EN1FUN_MASK BIT(1) -#define SPIPC0_EN0FUN_MASK BIT(0) #define SPIINT_MASKALL 0x0101035F #define SPI_INTLVL_1 0x000001FFu @@ -75,6 +71,7 @@ #define SPIGCR1_CLKMOD_MASK BIT(1) #define SPIGCR1_MASTER_MASK BIT(0) #define SPIGCR1_LOOPBACK_MASK BIT(16) +#define SPIGCR1_SPIENA_MASK BIT(24) /* SPIBUF */ #define SPIBUF_TXFULL_MASK BIT(29) @@ -90,23 +87,12 @@ #define SPIFLG_RX_INTR_MASK BIT(8) #define SPIFLG_TX_INTR_MASK BIT(9) #define SPIFLG_BUF_INIT_ACTIVE_MASK BIT(24) -#define SPIFLG_MASK (SPIFLG_DLEN_ERR_MASK \ - | SPIFLG_TIMEOUT_MASK | SPIFLG_PARERR_MASK \ - | SPIFLG_DESYNC_MASK | SPIFLG_BITERR_MASK \ - | SPIFLG_OVRRUN_MASK | SPIFLG_RX_INTR_MASK \ - | SPIFLG_TX_INTR_MASK \ - | SPIFLG_BUF_INIT_ACTIVE_MASK) - -#define SPIINT_DLEN_ERR_INTR BIT(0) -#define SPIINT_TIMEOUT_INTR BIT(1) -#define SPIINT_PARERR_INTR BIT(2) -#define SPIINT_DESYNC_INTR BIT(3) + #define SPIINT_BITERR_INTR BIT(4) #define SPIINT_OVRRUN_INTR BIT(6) #define SPIINT_RX_INTR BIT(8) #define SPIINT_TX_INTR BIT(9) #define SPIINT_DMA_REQ_EN BIT(16) -#define SPIINT_ENABLE_HIGHZ BIT(24) #define SPI_T2CDELAY_SHIFT 16 #define SPI_C2TDELAY_SHIFT 24 @@ -118,26 +104,11 @@ #define SPILVL 0x0c #define SPIFLG 0x10 #define SPIPC0 0x14 -#define SPIPC1 0x18 -#define SPIPC2 0x1c -#define SPIPC3 0x20 -#define SPIPC4 0x24 -#define SPIPC5 0x28 -#define SPIPC6 0x2c -#define SPIPC7 0x30 -#define SPIPC8 0x34 -#define SPIDAT0 0x38 #define SPIDAT1 0x3c #define SPIBUF 0x40 -#define SPIEMU 0x44 #define SPIDELAY 0x48 #define SPIDEF 0x4c #define SPIFMT0 0x50 -#define SPIFMT1 0x54 -#define SPIFMT2 0x58 -#define SPIFMT3 0x5c -#define TGINTVEC0 0x60 -#define TGINTVEC1 0x64 struct davinci_spi_slave { u32 cmd_to_write; -- cgit v1.2.3 From 50356dd7c1f6338588af6a745649a718f16fe453 Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Fri, 8 Oct 2010 15:27:26 +0530 Subject: spi: davinci: remove unnecessary typecast The typecasting of SPI base address to davinci_spi_reg is unused. Remove it. Tested-By: Michael Williamson Tested-By: Brian Niebuhr Signed-off-by: Sekhar Nori --- drivers/spi/davinci_spi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index 7bd0a55f5bbd..76decda0c8da 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -1020,8 +1020,7 @@ static int davinci_spi_probe(struct platform_device *pdev) goto free_master; } - davinci_spi->base = (struct davinci_spi_reg __iomem *) - ioremap(r->start, davinci_spi->region_size); + davinci_spi->base = ioremap(r->start, davinci_spi->region_size); if (davinci_spi->base == NULL) { ret = -ENOMEM; goto release_region; -- cgit v1.2.3 From 843a713bc53d04f8fac46ddd8693a2cc0422ca5e Mon Sep 17 00:00:00 2001 From: Brian Niebuhr Date: Thu, 12 Aug 2010 12:49:05 +0530 Subject: spi: davinci: set chip-select mode in SPIDEF only once Quit writing the same constant value determining the chip-select mode when no transmissions are in progress in davinci_spi_chipelect(). Instead just setup the SPIDEF register once during probe. Signed-off-by: Brian Niebuhr Tested-By: Michael Williamson Signed-off-by: Sekhar Nori --- drivers/spi/davinci_spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index 76decda0c8da..d6b6a4958088 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -245,8 +245,6 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) * line for the controller */ if (value == BITBANG_CS_INACTIVE) { - set_io_bits(davinci_spi->base + SPIDEF, CS_DEFAULT); - data1_reg_val |= CS_DEFAULT << SPIDAT1_CSNR_SHIFT; iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1); @@ -1132,6 +1130,8 @@ static int davinci_spi_probe(struct platform_device *pdev) clear_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_CLKMOD_MASK); + iowrite32(CS_DEFAULT, davinci_spi->base + SPIDEF); + /* master mode default */ set_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_MASTER_MASK); -- cgit v1.2.3 From 7978b8c385a86f0b5b9304e81a1dfb5dcaf21528 Mon Sep 17 00:00:00 2001 From: Brian Niebuhr Date: Fri, 13 Aug 2010 10:11:03 +0530 Subject: spi: davinci: enable both activation and deactivation of chip-selects Let davinci_spi_chipselect() perform both activation and deactivation of chip selects. This lets spi_bitbang fully control chip select activation, as intended by the SPI API. With this change, the chip select activation code need not be duplicated in davinci_spi_bufs_{pio|dma}(). Also, keeping chip select active control is removed as a platform data and simply controlled using information from spi_bitbang on whether chip slect should be activated or de-activated. Signed-off-by: Brian Niebuhr Tested-By: Michael Williamson Signed-off-by: Sekhar Nori --- drivers/spi/davinci_spi.c | 53 ++++++++++++++++------------------------------- 1 file changed, 18 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index d6b6a4958088..105c686b2cea 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -66,7 +66,7 @@ #define SPI_INTLVL_0 0x00000000u /* SPIDAT1 */ -#define SPIDAT1_CSHOLD_SHIFT 28 +#define SPIDAT1_CSHOLD_MASK BIT(28) #define SPIDAT1_CSNR_SHIFT 16 #define SPIGCR1_CLKMOD_MASK BIT(1) #define SPIGCR1_MASTER_MASK BIT(0) @@ -235,7 +235,8 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) { struct davinci_spi *davinci_spi; struct davinci_spi_platform_data *pdata; - u32 data1_reg_val = 0; + u32 data1_reg_val; + u8 chip_sel = spi->chip_select; davinci_spi = spi_master_get_devdata(spi->master); pdata = davinci_spi->pdata; @@ -244,14 +245,17 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) * Board specific chip select logic decides the polarity and cs * line for the controller */ - if (value == BITBANG_CS_INACTIVE) { - data1_reg_val |= CS_DEFAULT << SPIDAT1_CSNR_SHIFT; - iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1); - - while ((ioread32(davinci_spi->base + SPIBUF) - & SPIBUF_RXEMPTY_MASK) == 0) - cpu_relax(); + data1_reg_val = CS_DEFAULT << SPIDAT1_CSNR_SHIFT; + if (value == BITBANG_CS_ACTIVE) { + data1_reg_val |= SPIDAT1_CSHOLD_MASK; + data1_reg_val &= ~((0x1 << chip_sel) << SPIDAT1_CSNR_SHIFT); } + + iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1); + while ((ioread32(davinci_spi->base + SPIBUF) + & SPIBUF_RXEMPTY_MASK) == 0) + cpu_relax(); + } /** @@ -632,7 +636,7 @@ static int davinci_spi_bufs_pio(struct spi_device *spi, struct spi_transfer *t) { struct davinci_spi *davinci_spi; int int_status, count, ret; - u8 conv, tmp; + u8 conv; u32 tx_data, data1_reg_val; u32 buf_val, flg_val; struct davinci_spi_platform_data *pdata; @@ -647,6 +651,8 @@ static int davinci_spi_bufs_pio(struct spi_device *spi, struct spi_transfer *t) conv = davinci_spi->slave[spi->chip_select].bytes_per_word; davinci_spi->count = t->len / conv; + data1_reg_val = ioread32(davinci_spi->base + SPIDAT1); + INIT_COMPLETION(davinci_spi->done); ret = davinci_spi_bufs_prep(spi, davinci_spi); @@ -661,16 +667,6 @@ static int davinci_spi_bufs_pio(struct spi_device *spi, struct spi_transfer *t) davinci_spi->base + SPIDELAY); count = davinci_spi->count; - data1_reg_val = pdata->cs_hold << SPIDAT1_CSHOLD_SHIFT; - tmp = ~(0x1 << spi->chip_select); - - clear_io_bits(davinci_spi->base + SPIDEF, ~tmp); - - data1_reg_val |= tmp << SPIDAT1_CSNR_SHIFT; - - while ((ioread32(davinci_spi->base + SPIBUF) - & SPIBUF_RXEMPTY_MASK) == 0) - cpu_relax(); /* Determine the command to execute READ or WRITE */ if (t->tx_buf) { @@ -770,7 +766,6 @@ static int davinci_spi_bufs_dma(struct spi_device *spi, struct spi_transfer *t) int int_status = 0; int count, temp_count; u8 conv = 1; - u8 tmp; u32 data1_reg_val; struct davinci_spi_dma *davinci_spi_dma; int word_len, data_type, ret; @@ -794,6 +789,8 @@ static int davinci_spi_bufs_dma(struct spi_device *spi, struct spi_transfer *t) conv = davinci_spi->slave[spi->chip_select].bytes_per_word; davinci_spi->count = t->len / conv; + data1_reg_val = ioread32(davinci_spi->base + SPIDAT1); + INIT_COMPLETION(davinci_spi->done); init_completion(&davinci_spi_dma->dma_rx_completion); @@ -820,28 +817,14 @@ static int davinci_spi_bufs_dma(struct spi_device *spi, struct spi_transfer *t) davinci_spi->base + SPIDELAY); count = davinci_spi->count; /* the number of elements */ - data1_reg_val = pdata->cs_hold << SPIDAT1_CSHOLD_SHIFT; - - /* CS default = 0xFF */ - tmp = ~(0x1 << spi->chip_select); - - clear_io_bits(davinci_spi->base + SPIDEF, ~tmp); - - data1_reg_val |= tmp << SPIDAT1_CSNR_SHIFT; /* disable all interrupts for dma transfers */ clear_io_bits(davinci_spi->base + SPIINT, SPIINT_MASKALL); /* Disable SPI to write configuration bits in SPIDAT */ clear_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_SPIENA_MASK); - iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1); /* Enable SPI */ set_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_SPIENA_MASK); - while ((ioread32(davinci_spi->base + SPIBUF) - & SPIBUF_RXEMPTY_MASK) == 0) - cpu_relax(); - - if (t->tx_buf) { t->tx_dma = dma_map_single(&spi->dev, (void *)t->tx_buf, count, DMA_TO_DEVICE); -- cgit v1.2.3 From cfbc5d1d8fda9d337e912a03502cf77d29870a8e Mon Sep 17 00:00:00 2001 From: Brian Niebuhr Date: Thu, 12 Aug 2010 12:27:33 +0530 Subject: spi: davinci: remove unnecessary data transmit on CS disable On TI DaVinci's SPI controller, the SPIDAT1 register which controls the chip slect status, also has data transmit register in the lower 16 bits. Writing to the whole 32-bits triggers an additional data transmit every time the chip select is disabled. While most SPI slaves cope-up with this, some cannot. This patch fixes this by doing a 16-bit write on the upper half of the SPIDAT1 register While at it, group the SPIGCR1 register related defines seperately from SPIDAT1 register defines. Signed-off-by: Brian Niebuhr Tested-By: Michael Williamson Signed-off-by: Sekhar Nori --- drivers/spi/davinci_spi.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index 105c686b2cea..82dddf83daf7 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -65,9 +65,10 @@ #define SPI_INTLVL_1 0x000001FFu #define SPI_INTLVL_0 0x00000000u -/* SPIDAT1 */ -#define SPIDAT1_CSHOLD_MASK BIT(28) -#define SPIDAT1_CSNR_SHIFT 16 +/* SPIDAT1 (upper 16 bit defines) */ +#define SPIDAT1_CSHOLD_MASK BIT(12) + +/* SPIGCR1 */ #define SPIGCR1_CLKMOD_MASK BIT(1) #define SPIGCR1_MASTER_MASK BIT(0) #define SPIGCR1_LOOPBACK_MASK BIT(16) @@ -235,8 +236,8 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) { struct davinci_spi *davinci_spi; struct davinci_spi_platform_data *pdata; - u32 data1_reg_val; u8 chip_sel = spi->chip_select; + u16 spidat1_cfg = CS_DEFAULT; davinci_spi = spi_master_get_devdata(spi->master); pdata = davinci_spi->pdata; @@ -245,17 +246,12 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) * Board specific chip select logic decides the polarity and cs * line for the controller */ - data1_reg_val = CS_DEFAULT << SPIDAT1_CSNR_SHIFT; if (value == BITBANG_CS_ACTIVE) { - data1_reg_val |= SPIDAT1_CSHOLD_MASK; - data1_reg_val &= ~((0x1 << chip_sel) << SPIDAT1_CSNR_SHIFT); + spidat1_cfg |= SPIDAT1_CSHOLD_MASK; + spidat1_cfg &= ~(0x1 << chip_sel); } - iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1); - while ((ioread32(davinci_spi->base + SPIBUF) - & SPIBUF_RXEMPTY_MASK) == 0) - cpu_relax(); - + iowrite16(spidat1_cfg, davinci_spi->base + SPIDAT1 + 2); } /** -- cgit v1.2.3 From 23853973d9b76eb8b3cf46157689bc6187e141d9 Mon Sep 17 00:00:00 2001 From: Brian Niebuhr Date: Fri, 13 Aug 2010 10:57:44 +0530 Subject: spi: davinci: enable GPIO lines to be used as chip selects Sometimes, the chip selects provided by SPI module are muxed with other functionality and cannot be used in some designs. In such cases, it becomes convenient to use an available GPIO line as chip select. This patch enables the DaVinci SPI driver to treat specific GPIO lines as chip selects based on information provided in platform data. Signed-off-by: Brian Niebuhr Tested-By: Michael Williamson Signed-off-by: Sekhar Nori --- drivers/spi/davinci_spi.c | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index 82dddf83daf7..d5d7014e6ae2 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -238,20 +238,32 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) struct davinci_spi_platform_data *pdata; u8 chip_sel = spi->chip_select; u16 spidat1_cfg = CS_DEFAULT; + bool gpio_chipsel = false; davinci_spi = spi_master_get_devdata(spi->master); pdata = davinci_spi->pdata; + if (pdata->chip_sel && chip_sel < pdata->num_chipselect && + pdata->chip_sel[chip_sel] != SPI_INTERN_CS) + gpio_chipsel = true; + /* * Board specific chip select logic decides the polarity and cs * line for the controller */ - if (value == BITBANG_CS_ACTIVE) { - spidat1_cfg |= SPIDAT1_CSHOLD_MASK; - spidat1_cfg &= ~(0x1 << chip_sel); - } + if (gpio_chipsel) { + if (value == BITBANG_CS_ACTIVE) + gpio_set_value(pdata->chip_sel[chip_sel], 0); + else + gpio_set_value(pdata->chip_sel[chip_sel], 1); + } else { + if (value == BITBANG_CS_ACTIVE) { + spidat1_cfg |= SPIDAT1_CSHOLD_MASK; + spidat1_cfg &= ~(0x1 << chip_sel); + } - iowrite16(spidat1_cfg, davinci_spi->base + SPIDAT1 + 2); + iowrite16(spidat1_cfg, davinci_spi->base + SPIDAT1 + 2); + } } /** @@ -546,6 +558,7 @@ static void davinci_spi_cleanup(struct spi_device *spi) static int davinci_spi_bufs_prep(struct spi_device *spi, struct davinci_spi *davinci_spi) { + struct davinci_spi_platform_data *pdata; int op_mode = 0; /* @@ -558,8 +571,12 @@ static int davinci_spi_bufs_prep(struct spi_device *spi, op_mode = SPIPC0_DIFUN_MASK | SPIPC0_DOFUN_MASK | SPIPC0_CLKFUN_MASK; - if (!(spi->mode & SPI_NO_CS)) - op_mode |= 1 << spi->chip_select; + if (!(spi->mode & SPI_NO_CS)) { + pdata = davinci_spi->pdata; + if (!pdata->chip_sel || + pdata->chip_sel[spi->chip_select] == SPI_INTERN_CS) + op_mode |= 1 << spi->chip_select; + } if (spi->mode & SPI_READY) op_mode |= SPIPC0_SPIENA_MASK; @@ -1101,6 +1118,14 @@ static int davinci_spi_probe(struct platform_device *pdev) udelay(100); iowrite32(1, davinci_spi->base + SPIGCR0); + /* initialize chip selects */ + if (pdata->chip_sel) { + for (i = 0; i < pdata->num_chipselect; i++) { + if (pdata->chip_sel[i] != SPI_INTERN_CS) + gpio_direction_output(pdata->chip_sel[i], 1); + } + } + /* Clock internal */ if (davinci_spi->pdata->clk_internal) set_io_bits(davinci_spi->base + SPIGCR1, -- cgit v1.2.3 From 7fe0092b1f55f58a749d68ace3a3597e8a2a9163 Mon Sep 17 00:00:00 2001 From: Brian Niebuhr Date: Fri, 13 Aug 2010 13:27:23 +0530 Subject: spi: davinci: simplify prescalar calculation Simplify pre-scalar calculation and move it into a seprate function. Refuse to correct invalid pre-scalar values silently as this might lead to unexpected bugs and lower performance. Instead an error will force users to dig into the root-cause of the issue. While at it, remove some device specific checks on the maximum SPI frequency. As the driver supports the SPI interface implemented on various devices, it should only take care of core SPI limitations and leave the device specific handling to platform code. Signed-off-by: Brian Niebuhr Tested-By: Michael Williamson Signed-off-by: Sekhar Nori --- drivers/spi/davinci_spi.c | 53 +++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index d5d7014e6ae2..17269ad54a99 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -53,6 +53,7 @@ #define SPIFMT_WDELAY_MASK 0x3f000000u #define SPIFMT_WDELAY_SHIFT 24 #define SPIFMT_CHARLEN_MASK 0x0000001Fu +#define SPIFMT_PRESCALE_SHIFT 8 /* SPIPC0 */ @@ -266,6 +267,29 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) } } +/** + * davinci_spi_get_prescale - Calculates the correct prescale value + * @maxspeed_hz: the maximum rate the SPI clock can run at + * + * This function calculates the prescale value that generates a clock rate + * less than or equal to the specified maximum. + * + * Returns: calculated prescale - 1 for easy programming into SPI registers + * or negative error number if valid prescalar cannot be updated. + */ +static inline int davinci_spi_get_prescale(struct davinci_spi *davinci_spi, + u32 max_speed_hz) +{ + int ret; + + ret = DIV_ROUND_UP(clk_get_rate(davinci_spi->clk), max_speed_hz); + + if (ret < 3 || ret > 256) + return -EINVAL; + + return ret - 1; +} + /** * davinci_spi_setup_transfer - This functions will determine transfer method * @spi: spi device on which data transfer to be done @@ -281,7 +305,7 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, struct davinci_spi *davinci_spi; u8 bits_per_word = 0; - u32 hz = 0, prescale = 0, clkspeed; + u32 hz = 0, prescale = 0; davinci_spi = spi_master_get_devdata(spi->master); @@ -312,21 +336,18 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, if (!hz) hz = spi->max_speed_hz; + prescale = davinci_spi_get_prescale(davinci_spi, hz); + if (prescale < 0) + return prescale; + clear_fmt_bits(davinci_spi->base, SPIFMT_CHARLEN_MASK, spi->chip_select); set_fmt_bits(davinci_spi->base, bits_per_word & 0x1f, spi->chip_select); - clkspeed = clk_get_rate(davinci_spi->clk); - if (hz > clkspeed / 2) - prescale = 1 << 8; - if (hz < clkspeed / 256) - prescale = 255 << 8; - if (!prescale) - prescale = ((clkspeed / hz - 1) << 8) & 0x0000ff00; - clear_fmt_bits(davinci_spi->base, 0x0000ff00, spi->chip_select); - set_fmt_bits(davinci_spi->base, prescale, spi->chip_select); + set_fmt_bits(davinci_spi->base, + prescale << SPIFMT_PRESCALE_SHIFT, spi->chip_select); return 0; } @@ -413,10 +434,8 @@ static int davinci_spi_setup(struct spi_device *spi) int retval; struct davinci_spi *davinci_spi; struct davinci_spi_dma *davinci_spi_dma; - struct device *sdev; davinci_spi = spi_master_get_devdata(spi->master); - sdev = davinci_spi->bitbang.master->dev.parent; /* if bits per word length is zero then set it default 8 */ if (!spi->bits_per_word) @@ -435,16 +454,6 @@ static int davinci_spi_setup(struct spi_device *spi) } } - /* - * SPI in DaVinci and DA8xx operate between - * 600 KHz and 50 MHz - */ - if (spi->max_speed_hz < 600000 || spi->max_speed_hz > 50000000) { - dev_dbg(sdev, "Operating frequency is not in acceptable " - "range\n"); - return -EINVAL; - } - /* * Set up SPIFMTn register, unique to this chipselect. * -- cgit v1.2.3 From 472880c73da124b6cb5cbc31a36754aa62935afe Mon Sep 17 00:00:00 2001 From: Brian Niebuhr Date: Mon, 16 Aug 2010 10:28:53 +0530 Subject: spi: davinci: remove 'wait_enable' platform data member The SPI_READY bit of struct spi_device:mode serves the purpose of letting the SPI master know if the slave can signal if it is ready for transfer or not. The 'wait_enable' platform data was duplicating this functionality. Use the framework provided method of indicating this capability. Signed-off-by: Brian Niebuhr Tested-By: Michael Williamson Signed-off-by: Sekhar Nori --- drivers/spi/davinci_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index 17269ad54a99..54808577c121 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -522,7 +522,7 @@ static int davinci_spi_setup(struct spi_device *spi) SPIFMT_PARITYENA_MASK, spi->chip_select); - if (davinci_spi->pdata->wait_enable) + if (spi->mode & SPI_READY) set_fmt_bits(davinci_spi->base, SPIFMT_WAITENA_MASK, spi->chip_select); -- cgit v1.2.3 From 53a31b07c5aea4001bbb36ddd5ef2addffc7ccbd Mon Sep 17 00:00:00 2001 From: Brian Niebuhr Date: Mon, 16 Aug 2010 15:05:51 +0530 Subject: spi: davinci: make chip-slect specific parameters really chip-select specific Some chip-select specific paramterers like wdelay, parity, usage of chip-select timers (and the actual timer values) are included in platform data forcing the same behaviour across all chip-selects. Create a new davinci_spi_config data structure which can be passed along using controller_data member of spi_device data structure on a per-device basis. Signed-off-by: Brian Niebuhr Tested-By: Michael Williamson Signed-off-by: Sekhar Nori --- drivers/spi/davinci_spi.c | 67 ++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index 54808577c121..d4320f784070 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -156,6 +156,8 @@ struct davinci_spi { struct davinci_spi_slave slave[SPI_MAX_CHIPSELECT]; }; +static struct davinci_spi_config davinci_spi_default_cfg; + static unsigned use_dma; static void davinci_spi_rx_buf_u8(u32 data, struct davinci_spi *davinci_spi) @@ -434,8 +436,12 @@ static int davinci_spi_setup(struct spi_device *spi) int retval; struct davinci_spi *davinci_spi; struct davinci_spi_dma *davinci_spi_dma; + struct davinci_spi_config *spicfg; davinci_spi = spi_master_get_devdata(spi->master); + spicfg = (struct davinci_spi_config *)spi->controller_data; + if (!spicfg) + spicfg = &davinci_spi_default_cfg; /* if bits per word length is zero then set it default 8 */ if (!spi->bits_per_word) @@ -496,31 +502,34 @@ static int davinci_spi_setup(struct spi_device *spi) */ if (davinci_spi->version == SPI_VERSION_2) { + clear_fmt_bits(davinci_spi->base, SPIFMT_WDELAY_MASK, - spi->chip_select); + spi->chip_select); set_fmt_bits(davinci_spi->base, - (davinci_spi->pdata->wdelay - << SPIFMT_WDELAY_SHIFT) - & SPIFMT_WDELAY_MASK, - spi->chip_select); + (spicfg->wdelay << SPIFMT_WDELAY_SHIFT) & + SPIFMT_WDELAY_MASK, spi->chip_select); - if (davinci_spi->pdata->odd_parity) - set_fmt_bits(davinci_spi->base, - SPIFMT_ODD_PARITY_MASK, - spi->chip_select); + if (spicfg->odd_parity) + set_fmt_bits(davinci_spi->base, SPIFMT_ODD_PARITY_MASK, + spi->chip_select); else clear_fmt_bits(davinci_spi->base, SPIFMT_ODD_PARITY_MASK, spi->chip_select); - if (davinci_spi->pdata->parity_enable) - set_fmt_bits(davinci_spi->base, - SPIFMT_PARITYENA_MASK, - spi->chip_select); + if (spicfg->parity_enable) + set_fmt_bits(davinci_spi->base, SPIFMT_PARITYENA_MASK, + spi->chip_select); else - clear_fmt_bits(davinci_spi->base, - SPIFMT_PARITYENA_MASK, - spi->chip_select); + clear_fmt_bits(davinci_spi->base, SPIFMT_PARITYENA_MASK, + spi->chip_select); + + if (spicfg->timer_disable) + set_fmt_bits(davinci_spi->base, SPIFMT_DISTIMER_MASK, + spi->chip_select); + else + clear_fmt_bits(davinci_spi->base, SPIFMT_DISTIMER_MASK, + spi->chip_select); if (spi->mode & SPI_READY) set_fmt_bits(davinci_spi->base, @@ -531,14 +540,6 @@ static int davinci_spi_setup(struct spi_device *spi) SPIFMT_WAITENA_MASK, spi->chip_select); - if (davinci_spi->pdata->timer_disable) - set_fmt_bits(davinci_spi->base, - SPIFMT_DISTIMER_MASK, - spi->chip_select); - else - clear_fmt_bits(davinci_spi->base, - SPIFMT_DISTIMER_MASK, - spi->chip_select); } retval = davinci_spi_setup_transfer(spi, NULL); @@ -662,9 +663,13 @@ static int davinci_spi_bufs_pio(struct spi_device *spi, struct spi_transfer *t) u32 tx_data, data1_reg_val; u32 buf_val, flg_val; struct davinci_spi_platform_data *pdata; + struct davinci_spi_config *spicfg; davinci_spi = spi_master_get_devdata(spi->master); pdata = davinci_spi->pdata; + spicfg = (struct davinci_spi_config *)spi->controller_data; + if (!spicfg) + spicfg = &davinci_spi_default_cfg; davinci_spi->tx = t->tx_buf; davinci_spi->rx = t->rx_buf; @@ -684,8 +689,8 @@ static int davinci_spi_bufs_pio(struct spi_device *spi, struct spi_transfer *t) /* Enable SPI */ set_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_SPIENA_MASK); - iowrite32(0 | (pdata->c2tdelay << SPI_C2TDELAY_SHIFT) | - (pdata->t2cdelay << SPI_T2CDELAY_SHIFT), + iowrite32((spicfg->c2tdelay << SPI_C2TDELAY_SHIFT) | + (spicfg->t2cdelay << SPI_T2CDELAY_SHIFT), davinci_spi->base + SPIDELAY); count = davinci_spi->count; @@ -792,12 +797,14 @@ static int davinci_spi_bufs_dma(struct spi_device *spi, struct spi_transfer *t) struct davinci_spi_dma *davinci_spi_dma; int word_len, data_type, ret; unsigned long tx_reg, rx_reg; - struct davinci_spi_platform_data *pdata; + struct davinci_spi_config *spicfg; struct device *sdev; davinci_spi = spi_master_get_devdata(spi->master); - pdata = davinci_spi->pdata; sdev = davinci_spi->bitbang.master->dev.parent; + spicfg = (struct davinci_spi_config *)spi->controller_data; + if (!spicfg) + spicfg = &davinci_spi_default_cfg; davinci_spi_dma = &davinci_spi->dma_channels[spi->chip_select]; @@ -834,8 +841,8 @@ static int davinci_spi_bufs_dma(struct spi_device *spi, struct spi_transfer *t) return ret; /* Put delay val if required */ - iowrite32(0 | (pdata->c2tdelay << SPI_C2TDELAY_SHIFT) | - (pdata->t2cdelay << SPI_T2CDELAY_SHIFT), + iowrite32((spicfg->c2tdelay << SPI_C2TDELAY_SHIFT) | + (spicfg->t2cdelay << SPI_T2CDELAY_SHIFT), davinci_spi->base + SPIDELAY); count = davinci_spi->count; /* the number of elements */ -- cgit v1.2.3 From 25f33512f6ae7e37d7b3d353d57d4d6d066033ce Mon Sep 17 00:00:00 2001 From: Brian Niebuhr Date: Thu, 19 Aug 2010 12:15:22 +0530 Subject: spi: davinci: consolidate setup of SPIFMTn in one function Consolidate the setup of SPIFMTn register under davinci_spi_setup_transfer() simplifying the code and avoiding unnecessary reads and writes to the register. The two inline functions {set|clear}_fmt_bits() can be eliminated because of this. Signed-off-by: Brian Niebuhr Tested-By: Michael Williamson Signed-off-by: Sekhar Nori --- drivers/spi/davinci_spi.c | 154 +++++++++++++++------------------------------- 1 file changed, 49 insertions(+), 105 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index d4320f784070..34b28fe2d327 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -52,7 +52,6 @@ #define SPIFMT_ODD_PARITY_MASK BIT(23) #define SPIFMT_WDELAY_MASK 0x3f000000u #define SPIFMT_WDELAY_SHIFT 24 -#define SPIFMT_CHARLEN_MASK 0x0000001Fu #define SPIFMT_PRESCALE_SHIFT 8 @@ -212,16 +211,6 @@ static inline void clear_io_bits(void __iomem *addr, u32 bits) iowrite32(v, addr); } -static inline void set_fmt_bits(void __iomem *addr, u32 bits, int cs_num) -{ - set_io_bits(addr + SPIFMT0 + (0x4 * cs_num), bits); -} - -static inline void clear_fmt_bits(void __iomem *addr, u32 bits, int cs_num) -{ - clear_io_bits(addr + SPIFMT0 + (0x4 * cs_num), bits); -} - static void davinci_spi_set_dma_req(const struct spi_device *spi, int enable) { struct davinci_spi *davinci_spi = spi_master_get_devdata(spi->master); @@ -306,10 +295,14 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, { struct davinci_spi *davinci_spi; + struct davinci_spi_config *spicfg; u8 bits_per_word = 0; - u32 hz = 0, prescale = 0; + u32 hz = 0, spifmt = 0, prescale = 0; davinci_spi = spi_master_get_devdata(spi->master); + spicfg = (struct davinci_spi_config *)spi->controller_data; + if (!spicfg) + spicfg = &davinci_spi_default_cfg; if (t) { bits_per_word = t->bits_per_word; @@ -338,18 +331,55 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, if (!hz) hz = spi->max_speed_hz; + /* Set up SPIFMTn register, unique to this chipselect. */ + prescale = davinci_spi_get_prescale(davinci_spi, hz); if (prescale < 0) return prescale; - clear_fmt_bits(davinci_spi->base, SPIFMT_CHARLEN_MASK, - spi->chip_select); - set_fmt_bits(davinci_spi->base, bits_per_word & 0x1f, - spi->chip_select); + spifmt = (prescale << SPIFMT_PRESCALE_SHIFT) | (bits_per_word & 0x1f); + + if (spi->mode & SPI_LSB_FIRST) + spifmt |= SPIFMT_SHIFTDIR_MASK; + + if (spi->mode & SPI_CPOL) + spifmt |= SPIFMT_POLARITY_MASK; + + if (!(spi->mode & SPI_CPHA)) + spifmt |= SPIFMT_PHASE_MASK; + + /* + * Version 1 hardware supports two basic SPI modes: + * - Standard SPI mode uses 4 pins, with chipselect + * - 3 pin SPI is a 4 pin variant without CS (SPI_NO_CS) + * (distinct from SPI_3WIRE, with just one data wire; + * or similar variants without MOSI or without MISO) + * + * Version 2 hardware supports an optional handshaking signal, + * so it can support two more modes: + * - 5 pin SPI variant is standard SPI plus SPI_READY + * - 4 pin with enable is (SPI_READY | SPI_NO_CS) + */ + + if (davinci_spi->version == SPI_VERSION_2) { + + spifmt |= ((spicfg->wdelay << SPIFMT_WDELAY_SHIFT) + & SPIFMT_WDELAY_MASK); - clear_fmt_bits(davinci_spi->base, 0x0000ff00, spi->chip_select); - set_fmt_bits(davinci_spi->base, - prescale << SPIFMT_PRESCALE_SHIFT, spi->chip_select); + if (spicfg->odd_parity) + spifmt |= SPIFMT_ODD_PARITY_MASK; + + if (spicfg->parity_enable) + spifmt |= SPIFMT_PARITYENA_MASK; + + if (spicfg->timer_disable) + spifmt |= SPIFMT_DISTIMER_MASK; + + if (spi->mode & SPI_READY) + spifmt |= SPIFMT_WAITENA_MASK; + } + + iowrite32(spifmt, davinci_spi->base + SPIFMT0); return 0; } @@ -436,12 +466,8 @@ static int davinci_spi_setup(struct spi_device *spi) int retval; struct davinci_spi *davinci_spi; struct davinci_spi_dma *davinci_spi_dma; - struct davinci_spi_config *spicfg; davinci_spi = spi_master_get_devdata(spi->master); - spicfg = (struct davinci_spi_config *)spi->controller_data; - if (!spicfg) - spicfg = &davinci_spi_default_cfg; /* if bits per word length is zero then set it default 8 */ if (!spi->bits_per_word) @@ -460,88 +486,6 @@ static int davinci_spi_setup(struct spi_device *spi) } } - /* - * Set up SPIFMTn register, unique to this chipselect. - * - * NOTE: we could do all of these with one write. Also, some - * of the "version 2" features are found in chips that don't - * support all of them... - */ - if (spi->mode & SPI_LSB_FIRST) - set_fmt_bits(davinci_spi->base, SPIFMT_SHIFTDIR_MASK, - spi->chip_select); - else - clear_fmt_bits(davinci_spi->base, SPIFMT_SHIFTDIR_MASK, - spi->chip_select); - - if (spi->mode & SPI_CPOL) - set_fmt_bits(davinci_spi->base, SPIFMT_POLARITY_MASK, - spi->chip_select); - else - clear_fmt_bits(davinci_spi->base, SPIFMT_POLARITY_MASK, - spi->chip_select); - - if (!(spi->mode & SPI_CPHA)) - set_fmt_bits(davinci_spi->base, SPIFMT_PHASE_MASK, - spi->chip_select); - else - clear_fmt_bits(davinci_spi->base, SPIFMT_PHASE_MASK, - spi->chip_select); - - /* - * Version 1 hardware supports two basic SPI modes: - * - Standard SPI mode uses 4 pins, with chipselect - * - 3 pin SPI is a 4 pin variant without CS (SPI_NO_CS) - * (distinct from SPI_3WIRE, with just one data wire; - * or similar variants without MOSI or without MISO) - * - * Version 2 hardware supports an optional handshaking signal, - * so it can support two more modes: - * - 5 pin SPI variant is standard SPI plus SPI_READY - * - 4 pin with enable is (SPI_READY | SPI_NO_CS) - */ - - if (davinci_spi->version == SPI_VERSION_2) { - - clear_fmt_bits(davinci_spi->base, SPIFMT_WDELAY_MASK, - spi->chip_select); - set_fmt_bits(davinci_spi->base, - (spicfg->wdelay << SPIFMT_WDELAY_SHIFT) & - SPIFMT_WDELAY_MASK, spi->chip_select); - - if (spicfg->odd_parity) - set_fmt_bits(davinci_spi->base, SPIFMT_ODD_PARITY_MASK, - spi->chip_select); - else - clear_fmt_bits(davinci_spi->base, - SPIFMT_ODD_PARITY_MASK, - spi->chip_select); - - if (spicfg->parity_enable) - set_fmt_bits(davinci_spi->base, SPIFMT_PARITYENA_MASK, - spi->chip_select); - else - clear_fmt_bits(davinci_spi->base, SPIFMT_PARITYENA_MASK, - spi->chip_select); - - if (spicfg->timer_disable) - set_fmt_bits(davinci_spi->base, SPIFMT_DISTIMER_MASK, - spi->chip_select); - else - clear_fmt_