summaryrefslogtreecommitdiffstats
path: root/drivers/spi/davinci_spi.c
diff options
context:
space:
mode:
authorBrian Niebuhr2010-08-13 07:27:44 +0200
committerSekhar Nori2010-11-18 14:08:25 +0100
commit23853973d9b76eb8b3cf46157689bc6187e141d9 (patch)
tree3eb97d400cb04c54ed0853b71f4d98415846b7cd /drivers/spi/davinci_spi.c
parentspi: davinci: remove unnecessary data transmit on CS disable (diff)
downloadkernel-qcow2-linux-23853973d9b76eb8b3cf46157689bc6187e141d9.tar.gz
kernel-qcow2-linux-23853973d9b76eb8b3cf46157689bc6187e141d9.tar.xz
kernel-qcow2-linux-23853973d9b76eb8b3cf46157689bc6187e141d9.zip
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 <bniebuhr@efjohnson.com> Tested-By: Michael Williamson <michael.williamson@criticallink.com> Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Diffstat (limited to 'drivers/spi/davinci_spi.c')
-rw-r--r--drivers/spi/davinci_spi.c39
1 files changed, 32 insertions, 7 deletions
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,