summaryrefslogtreecommitdiff
path: root/drivers/spi/spi-omap2-mcspi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-13 19:15:11 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-13 19:15:11 -0800
commitd3b43e12b2c8c69f79ab76dcdc5956f47c376378 (patch)
tree4fba9e425d7407e5abd5ab50d5ac09398ec5bff6 /drivers/spi/spi-omap2-mcspi.c
parent15de0599277f3477ddd11766282587f12d214252 (diff)
parent7cb943615aabbd72624f77f0a84b8c5d627cf846 (diff)
downloadolio-linux-3.10-d3b43e12b2c8c69f79ab76dcdc5956f47c376378.tar.xz
olio-linux-3.10-d3b43e12b2c8c69f79ab76dcdc5956f47c376378.zip
Merge tag 'spi-for-linus' of git://git.secretlab.ca/git/linux-2.6
Pull SPI updates from Grant Likely: "Primarily SPI device driver bug fixes, one removal of an old driver, and some new tegra support. There is some core code change too, but all in all pretty small stuff. The new features to note are: - Common code for describing GPIO CS lines in the device tree - Remove the SPI_BUFSIZ limitation on spi_write_the_read() - core spi ensures bits_per_word is set correctly - SPARC can now use SPI" * tag 'spi-for-linus' of git://git.secretlab.ca/git/linux-2.6: (36 commits) spi/sparc: Allow of_register_spi_devices for sparc spi: Remove HOTPLUG section attributes spi: Add support for specifying 3-wire mode via device tree spi: Fix comparison of different integer types spi/orion: Add SPI_CHPA and SPI_CPOL support to kirkwood driver. spi/sh: Add SH Mobile series as dependency to MSIOF controller spi/sh-msiof: Remove unneeded clock name spi: Remove SPI_BUFSIZ restriction on spi_write_then_read() spi/stmp: remove obsolete driver spi/clps711x: New SPI master driver spi: omap2-mcspi: remove duplicate inclusion of linux/err.h spi: omap2-mcspi: Fix the redifine warning spi/sh-hspi: add CS manual control support of_spi: add generic binding support to specify cs gpio spi: omap2-mcspi: remove duplicated include from spi-omap2-mcspi.c spi/bitbang: (cosmetic) simplify list manipulation spi/bitbang: avoid needless loop flow manipulations spi/omap: fix D0/D1 direction confusion spi: tegra: add spi driver for sflash controller spi: Dont call master->setup if not populated ...
Diffstat (limited to 'drivers/spi/spi-omap2-mcspi.c')
-rw-r--r--drivers/spi/spi-omap2-mcspi.c74
1 files changed, 40 insertions, 34 deletions
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index 3542fdc664b..b610f522ca4 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -39,7 +39,6 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
-#include <linux/err.h>
#include <linux/spi/spi.h>
@@ -130,6 +129,7 @@ struct omap2_mcspi {
struct omap2_mcspi_dma *dma_channels;
struct device *dev;
struct omap2_mcspi_regs ctx;
+ unsigned int pin_dir:1;
};
struct omap2_mcspi_cs {
@@ -323,19 +323,11 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi,
struct omap2_mcspi *mcspi;
struct omap2_mcspi_dma *mcspi_dma;
unsigned int count;
- u8 * rx;
- const u8 * tx;
- void __iomem *chstat_reg;
- struct omap2_mcspi_cs *cs = spi->controller_state;
mcspi = spi_master_get_devdata(spi->master);
mcspi_dma = &mcspi->dma_channels[spi->chip_select];
count = xfer->len;
- rx = xfer->rx_buf;
- tx = xfer->tx_buf;
- chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
-
if (mcspi_dma->dma_tx) {
struct dma_async_tx_descriptor *tx;
struct scatterlist sg;
@@ -359,19 +351,6 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi,
dma_async_issue_pending(mcspi_dma->dma_tx);
omap2_mcspi_set_dma_req(spi, 0, 1);
- wait_for_completion(&mcspi_dma->dma_tx_completion);
- dma_unmap_single(mcspi->dev, xfer->tx_dma, count,
- DMA_TO_DEVICE);
-
- /* for TX_ONLY mode, be sure all words have shifted out */
- if (rx == NULL) {
- if (mcspi_wait_for_reg_bit(chstat_reg,
- OMAP2_MCSPI_CHSTAT_TXS) < 0)
- dev_err(&spi->dev, "TXS timed out\n");
- else if (mcspi_wait_for_reg_bit(chstat_reg,
- OMAP2_MCSPI_CHSTAT_EOT) < 0)
- dev_err(&spi->dev, "EOT timed out\n");
- }
}
static unsigned
@@ -492,6 +471,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
struct dma_slave_config cfg;
enum dma_slave_buswidth width;
unsigned es;
+ void __iomem *chstat_reg;
mcspi = spi_master_get_devdata(spi->master);
mcspi_dma = &mcspi->dma_channels[spi->chip_select];
@@ -526,8 +506,24 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
omap2_mcspi_tx_dma(spi, xfer, cfg);
if (rx != NULL)
- return omap2_mcspi_rx_dma(spi, xfer, cfg, es);
+ count = omap2_mcspi_rx_dma(spi, xfer, cfg, es);
+
+ if (tx != NULL) {
+ chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
+ wait_for_completion(&mcspi_dma->dma_tx_completion);
+ dma_unmap_single(mcspi->dev, xfer->tx_dma, xfer->len,
+ DMA_TO_DEVICE);
+ /* for TX_ONLY mode, be sure all words have shifted out */
+ if (rx == NULL) {
+ if (mcspi_wait_for_reg_bit(chstat_reg,
+ OMAP2_MCSPI_CHSTAT_TXS) < 0)
+ dev_err(&spi->dev, "TXS timed out\n");
+ else if (mcspi_wait_for_reg_bit(chstat_reg,
+ OMAP2_MCSPI_CHSTAT_EOT) < 0)
+ dev_err(&spi->dev, "EOT timed out\n");
+ }
+ }
return count;
}
@@ -765,8 +761,15 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
/* standard 4-wire master mode: SCK, MOSI/out, MISO/in, nCS
* REVISIT: this controller could support SPI_3WIRE mode.
*/
- l &= ~(OMAP2_MCSPI_CHCONF_IS|OMAP2_MCSPI_CHCONF_DPE1);
- l |= OMAP2_MCSPI_CHCONF_DPE0;
+ if (mcspi->pin_dir == MCSPI_PINDIR_D0_IN_D1_OUT) {
+ l &= ~OMAP2_MCSPI_CHCONF_IS;
+ l &= ~OMAP2_MCSPI_CHCONF_DPE1;
+ l |= OMAP2_MCSPI_CHCONF_DPE0;
+ } else {
+ l |= OMAP2_MCSPI_CHCONF_IS;
+ l |= OMAP2_MCSPI_CHCONF_DPE1;
+ l &= ~OMAP2_MCSPI_CHCONF_DPE0;
+ }
/* wordlength */
l &= ~OMAP2_MCSPI_CHCONF_WL_MASK;
@@ -1085,7 +1088,7 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
return 0;
}
-static int __devinit omap2_mcspi_master_setup(struct omap2_mcspi *mcspi)
+static int omap2_mcspi_master_setup(struct omap2_mcspi *mcspi)
{
struct spi_master *master = mcspi->master;
struct omap2_mcspi_regs *ctx = &mcspi->ctx;
@@ -1138,7 +1141,7 @@ static const struct of_device_id omap_mcspi_of_match[] = {
};
MODULE_DEVICE_TABLE(of, omap_mcspi_of_match);
-static int __devinit omap2_mcspi_probe(struct platform_device *pdev)
+static int omap2_mcspi_probe(struct platform_device *pdev)
{
struct spi_master *master;
const struct omap2_mcspi_platform_config *pdata;
@@ -1167,6 +1170,11 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev)
master->cleanup = omap2_mcspi_cleanup;
master->dev.of_node = node;
+ dev_set_drvdata(&pdev->dev, master);
+
+ mcspi = spi_master_get_devdata(master);
+ mcspi->master = master;
+
match = of_match_device(omap_mcspi_of_match, &pdev->dev);
if (match) {
u32 num_cs = 1; /* default number of chipselect */
@@ -1175,19 +1183,17 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev)
of_property_read_u32(node, "ti,spi-num-cs", &num_cs);
master->num_chipselect = num_cs;
master->bus_num = bus_num++;
+ if (of_get_property(node, "ti,pindir-d0-out-d1-in", NULL))
+ mcspi->pin_dir = MCSPI_PINDIR_D0_OUT_D1_IN;
} else {
pdata = pdev->dev.platform_data;
master->num_chipselect = pdata->num_cs;
if (pdev->id != -1)
master->bus_num = pdev->id;
+ mcspi->pin_dir = pdata->pin_dir;
}
regs_offset = pdata->regs_offset;
- dev_set_drvdata(&pdev->dev, master);
-
- mcspi = spi_master_get_devdata(master);
- mcspi->master = master;
-
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (r == NULL) {
status = -ENODEV;
@@ -1272,7 +1278,7 @@ free_master:
return status;
}
-static int __devexit omap2_mcspi_remove(struct platform_device *pdev)
+static int omap2_mcspi_remove(struct platform_device *pdev)
{
struct spi_master *master;
struct omap2_mcspi *mcspi;
@@ -1341,7 +1347,7 @@ static struct platform_driver omap2_mcspi_driver = {
.of_match_table = omap_mcspi_of_match,
},
.probe = omap2_mcspi_probe,
- .remove = __devexit_p(omap2_mcspi_remove),
+ .remove = omap2_mcspi_remove,
};
module_platform_driver(omap2_mcspi_driver);