Loading Documentation/devicetree/bindings/spi/spi-davinci.txt +30 −0 Original line number Diff line number Diff line Davinci SPI controller device bindings Links on DM: Keystone 2 - http://www.ti.com/lit/ug/sprugp2a/sprugp2a.pdf dm644x - http://www.ti.com/lit/ug/sprue32a/sprue32a.pdf OMAP-L138/da830 - http://www.ti.com/lit/ug/spruh77a/spruh77a.pdf Required properties: - #address-cells: number of cells required to define a chip select address on the SPI bus. Should be set to 1. Loading @@ -24,6 +29,30 @@ Optional: cs-gpios = <0>, <0>, <0>, <&gpio1 30 0>, <&gpio1 31 0>; where first three are internal CS and last two are GPIO CS. Optional properties for slave devices: SPI slave nodes can contain the following properties. Not all SPI Peripherals from Texas Instruments support this. Please check SPI peripheral documentation for a device before using these. - ti,spi-wdelay : delay between transmission of words (SPIFMTn.WDELAY, SPIDAT1.WDEL) must be specified in number of SPI module clock periods. delay = WDELAY * SPI_module_clock_period + 2 * SPI_module_clock_period Below is timing diagram which shows functional meaning of "ti,spi-wdelay" parameter. +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ SPI_CLK | | | | | | | | | | | | | | | | +----------+ +-+ +-+ +-+ +-+ +---------------------------+ +-+ +-+ +- SPI_SOMI/SIMO+-----------------+ +----------- +----------+ word1 +---------------------------+word2 +-----------------+ +----------- WDELAY <--------------------------> Example of a NOR flash slave device (n25q032) connected to DaVinci SPI controller device over the SPI bus. Loading @@ -43,6 +72,7 @@ spi0:spi@20BF0000 { compatible = "st,m25p32"; spi-max-frequency = <25000000>; reg = <0>; ti,spi-wdelay = <8>; partition@0 { label = "u-boot-spl"; Loading Documentation/spi/spi-summary +3 −3 Original line number Diff line number Diff line Loading @@ -601,13 +601,13 @@ THANKS TO Contributors to Linux-SPI discussions include (in alphabetical order, by last name): Mark Brown David Brownell Russell King Grant Likely Dmitry Pervushin Stephen Street Mark Underwood Andrew Victor Vitaly Wool Grant Likely Mark Brown Linus Walleij Vitaly Wool drivers/spi/Kconfig +1 −1 Original line number Diff line number Diff line Loading @@ -602,7 +602,7 @@ config SPI_DW_PCI depends on SPI_DESIGNWARE && PCI config SPI_DW_MID_DMA bool "DMA support for DW SPI controller on Intel Moorestown platform" bool "DMA support for DW SPI controller on Intel MID platform" depends on SPI_DW_PCI && INTEL_MID_DMAC config SPI_DW_MMIO Loading drivers/spi/spi-davinci.c +48 −7 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ /* SPIDAT1 (upper 16 bit defines) */ #define SPIDAT1_CSHOLD_MASK BIT(12) #define SPIDAT1_WDEL BIT(10) /* SPIGCR1 */ #define SPIGCR1_CLKMOD_MASK BIT(1) Loading Loading @@ -213,6 +214,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) { struct davinci_spi *dspi; struct davinci_spi_platform_data *pdata; struct davinci_spi_config *spicfg = spi->controller_data; u8 chip_sel = spi->chip_select; u16 spidat1 = CS_DEFAULT; bool gpio_chipsel = false; Loading @@ -227,6 +229,10 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) gpio = spi->cs_gpio; } /* program delay transfers if tx_delay is non zero */ if (spicfg->wdelay) spidat1 |= SPIDAT1_WDEL; /* * Board specific chip select logic decides the polarity and cs * line for the controller Loading @@ -241,10 +247,10 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) spidat1 |= SPIDAT1_CSHOLD_MASK; spidat1 &= ~(0x1 << chip_sel); } } iowrite16(spidat1, dspi->base + SPIDAT1 + 2); } } /** * davinci_spi_get_prescale - Calculates the correct prescale value Loading Loading @@ -289,7 +295,7 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, int prescale; dspi = spi_master_get_devdata(spi->master); spicfg = (struct davinci_spi_config *)spi->controller_data; spicfg = spi->controller_data; if (!spicfg) spicfg = &davinci_spi_default_cfg; Loading Loading @@ -336,6 +342,14 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, if (!(spi->mode & SPI_CPHA)) spifmt |= SPIFMT_PHASE_MASK; /* * Assume wdelay is used only on SPI peripherals that has this field * in SPIFMTn register and when it's configured from board file or DT. */ if (spicfg->wdelay) spifmt |= ((spicfg->wdelay << SPIFMT_WDELAY_SHIFT) & SPIFMT_WDELAY_MASK); /* * Version 1 hardware supports two basic SPI modes: * - Standard SPI mode uses 4 pins, with chipselect Loading @@ -353,9 +367,6 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, u32 delay = 0; spifmt |= ((spicfg->wdelay << SPIFMT_WDELAY_SHIFT) & SPIFMT_WDELAY_MASK); if (spicfg->odd_parity) spifmt |= SPIFMT_ODD_PARITY_MASK; Loading Loading @@ -387,6 +398,26 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, return 0; } static int davinci_spi_of_setup(struct spi_device *spi) { struct davinci_spi_config *spicfg = spi->controller_data; struct device_node *np = spi->dev.of_node; u32 prop; if (spicfg == NULL && np) { spicfg = kzalloc(sizeof(*spicfg), GFP_KERNEL); if (!spicfg) return -ENOMEM; *spicfg = davinci_spi_default_cfg; /* override with dt configured values */ if (!of_property_read_u32(np, "ti,spi-wdelay", &prop)) spicfg->wdelay = (u8)prop; spi->controller_data = spicfg; } return 0; } /** * davinci_spi_setup - This functions will set default transfer method * @spi: spi device on which data transfer to be done Loading Loading @@ -437,7 +468,16 @@ static int davinci_spi_setup(struct spi_device *spi) else clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_LOOPBACK_MASK); return retval; return davinci_spi_of_setup(spi); } static void davinci_spi_cleanup(struct spi_device *spi) { struct davinci_spi_config *spicfg = spi->controller_data; spi->controller_data = NULL; if (spi->dev.of_node) kfree(spicfg); } static int davinci_spi_check_error(struct davinci_spi *dspi, int int_status) Loading Loading @@ -951,6 +991,7 @@ static int davinci_spi_probe(struct platform_device *pdev) master->num_chipselect = pdata->num_chipselect; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 16); master->setup = davinci_spi_setup; master->cleanup = davinci_spi_cleanup; dspi->bitbang.chipselect = davinci_spi_chipselect; dspi->bitbang.setup_transfer = davinci_spi_setup_transfer; Loading drivers/spi/spi-dw-mid.c +34 −31 Original line number Diff line number Diff line /* * Special handling for DW core on Intel MID platform * * Copyright (c) 2009, Intel Corporation. * Copyright (c) 2009, 2014 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, Loading @@ -11,10 +11,6 @@ * 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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include <linux/dma-mapping.h> Loading @@ -39,22 +35,25 @@ static bool mid_spi_dma_chan_filter(struct dma_chan *chan, void *param) { struct dw_spi *dws = param; return dws->dmac && (&dws->dmac->dev == chan->device->dev); return dws->dma_dev == chan->device->dev; } static int mid_spi_dma_init(struct dw_spi *dws) { struct mid_dma *dw_dma = dws->dma_priv; struct pci_dev *dma_dev; struct intel_mid_dma_slave *rxs, *txs; dma_cap_mask_t mask; /* * Get pci device for DMA controller, currently it could only * be the DMA controller of either Moorestown or Medfield * be the DMA controller of Medfield */ dws->dmac = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0813, NULL); if (!dws->dmac) dws->dmac = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0827, NULL); dma_dev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0827, NULL); if (!dma_dev) return -ENODEV; dws->dma_dev = &dma_dev->dev; dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); Loading Loading @@ -83,13 +82,18 @@ static int mid_spi_dma_init(struct dw_spi *dws) free_rxchan: dma_release_channel(dws->rxchan); err_exit: return -1; return -EBUSY; } static void mid_spi_dma_exit(struct dw_spi *dws) { if (!dws->dma_inited) return; dmaengine_terminate_all(dws->txchan); dma_release_channel(dws->txchan); dmaengine_terminate_all(dws->rxchan); dma_release_channel(dws->rxchan); } Loading @@ -109,8 +113,7 @@ static void dw_spi_dma_done(void *arg) static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) { struct dma_async_tx_descriptor *txdesc = NULL, *rxdesc = NULL; struct dma_chan *txchan, *rxchan; struct dma_async_tx_descriptor *txdesc, *rxdesc; struct dma_slave_config txconf, rxconf; u16 dma_ctrl = 0; Loading @@ -120,37 +123,34 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) dw_writew(dws, DW_SPI_DMARDLR, 0xf); dw_writew(dws, DW_SPI_DMATDLR, 0x10); if (dws->tx_dma) dma_ctrl |= 0x2; dma_ctrl |= SPI_DMA_TDMAE; if (dws->rx_dma) dma_ctrl |= 0x1; dma_ctrl |= SPI_DMA_RDMAE; dw_writew(dws, DW_SPI_DMACR, dma_ctrl); spi_enable_chip(dws, 1); } dws->dma_chan_done = 0; txchan = dws->txchan; rxchan = dws->rxchan; /* 2. Prepare the TX dma transfer */ txconf.direction = DMA_MEM_TO_DEV; txconf.dst_addr = dws->dma_addr; txconf.dst_maxburst = LNW_DMA_MSIZE_16; txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; txconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; txconf.dst_addr_width = dws->dma_width; txconf.device_fc = false; txchan->device->device_control(txchan, DMA_SLAVE_CONFIG, (unsigned long) &txconf); dmaengine_slave_config(dws->txchan, &txconf); memset(&dws->tx_sgl, 0, sizeof(dws->tx_sgl)); dws->tx_sgl.dma_address = dws->tx_dma; dws->tx_sgl.length = dws->len; txdesc = dmaengine_prep_slave_sg(txchan, txdesc = dmaengine_prep_slave_sg(dws->txchan, &dws->tx_sgl, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT); DMA_PREP_INTERRUPT | DMA_CTRL_ACK); txdesc->callback = dw_spi_dma_done; txdesc->callback_param = dws; Loading @@ -159,27 +159,30 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) rxconf.src_addr = dws->dma_addr; rxconf.src_maxburst = LNW_DMA_MSIZE_16; rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; rxconf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; rxconf.src_addr_width = dws->dma_width; rxconf.device_fc = false; rxchan->device->device_control(rxchan, DMA_SLAVE_CONFIG, (unsigned long) &rxconf); dmaengine_slave_config(dws->rxchan, &rxconf); memset(&dws->rx_sgl, 0, sizeof(dws->rx_sgl)); dws->rx_sgl.dma_address = dws->rx_dma; dws->rx_sgl.length = dws->len; rxdesc = dmaengine_prep_slave_sg(rxchan, rxdesc = dmaengine_prep_slave_sg(dws->rxchan, &dws->rx_sgl, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); DMA_PREP_INTERRUPT | DMA_CTRL_ACK); rxdesc->callback = dw_spi_dma_done; rxdesc->callback_param = dws; /* rx must be started before tx due to spi instinct */ rxdesc->tx_submit(rxdesc); txdesc->tx_submit(txdesc); dmaengine_submit(rxdesc); dma_async_issue_pending(dws->rxchan); dmaengine_submit(txdesc); dma_async_issue_pending(dws->txchan); return 0; } Loading @@ -190,7 +193,7 @@ static struct dw_spi_dma_ops mid_dma_ops = { }; #endif /* Some specific info for SPI0 controller on Moorestown */ /* Some specific info for SPI0 controller on Intel MID */ /* HW info for MRST CLk Control Unit, one 32b reg */ #define MRST_SPI_CLK_BASE 100000000 /* 100m */ Loading Loading
Documentation/devicetree/bindings/spi/spi-davinci.txt +30 −0 Original line number Diff line number Diff line Davinci SPI controller device bindings Links on DM: Keystone 2 - http://www.ti.com/lit/ug/sprugp2a/sprugp2a.pdf dm644x - http://www.ti.com/lit/ug/sprue32a/sprue32a.pdf OMAP-L138/da830 - http://www.ti.com/lit/ug/spruh77a/spruh77a.pdf Required properties: - #address-cells: number of cells required to define a chip select address on the SPI bus. Should be set to 1. Loading @@ -24,6 +29,30 @@ Optional: cs-gpios = <0>, <0>, <0>, <&gpio1 30 0>, <&gpio1 31 0>; where first three are internal CS and last two are GPIO CS. Optional properties for slave devices: SPI slave nodes can contain the following properties. Not all SPI Peripherals from Texas Instruments support this. Please check SPI peripheral documentation for a device before using these. - ti,spi-wdelay : delay between transmission of words (SPIFMTn.WDELAY, SPIDAT1.WDEL) must be specified in number of SPI module clock periods. delay = WDELAY * SPI_module_clock_period + 2 * SPI_module_clock_period Below is timing diagram which shows functional meaning of "ti,spi-wdelay" parameter. +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ SPI_CLK | | | | | | | | | | | | | | | | +----------+ +-+ +-+ +-+ +-+ +---------------------------+ +-+ +-+ +- SPI_SOMI/SIMO+-----------------+ +----------- +----------+ word1 +---------------------------+word2 +-----------------+ +----------- WDELAY <--------------------------> Example of a NOR flash slave device (n25q032) connected to DaVinci SPI controller device over the SPI bus. Loading @@ -43,6 +72,7 @@ spi0:spi@20BF0000 { compatible = "st,m25p32"; spi-max-frequency = <25000000>; reg = <0>; ti,spi-wdelay = <8>; partition@0 { label = "u-boot-spl"; Loading
Documentation/spi/spi-summary +3 −3 Original line number Diff line number Diff line Loading @@ -601,13 +601,13 @@ THANKS TO Contributors to Linux-SPI discussions include (in alphabetical order, by last name): Mark Brown David Brownell Russell King Grant Likely Dmitry Pervushin Stephen Street Mark Underwood Andrew Victor Vitaly Wool Grant Likely Mark Brown Linus Walleij Vitaly Wool
drivers/spi/Kconfig +1 −1 Original line number Diff line number Diff line Loading @@ -602,7 +602,7 @@ config SPI_DW_PCI depends on SPI_DESIGNWARE && PCI config SPI_DW_MID_DMA bool "DMA support for DW SPI controller on Intel Moorestown platform" bool "DMA support for DW SPI controller on Intel MID platform" depends on SPI_DW_PCI && INTEL_MID_DMAC config SPI_DW_MMIO Loading
drivers/spi/spi-davinci.c +48 −7 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ /* SPIDAT1 (upper 16 bit defines) */ #define SPIDAT1_CSHOLD_MASK BIT(12) #define SPIDAT1_WDEL BIT(10) /* SPIGCR1 */ #define SPIGCR1_CLKMOD_MASK BIT(1) Loading Loading @@ -213,6 +214,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) { struct davinci_spi *dspi; struct davinci_spi_platform_data *pdata; struct davinci_spi_config *spicfg = spi->controller_data; u8 chip_sel = spi->chip_select; u16 spidat1 = CS_DEFAULT; bool gpio_chipsel = false; Loading @@ -227,6 +229,10 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) gpio = spi->cs_gpio; } /* program delay transfers if tx_delay is non zero */ if (spicfg->wdelay) spidat1 |= SPIDAT1_WDEL; /* * Board specific chip select logic decides the polarity and cs * line for the controller Loading @@ -241,10 +247,10 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) spidat1 |= SPIDAT1_CSHOLD_MASK; spidat1 &= ~(0x1 << chip_sel); } } iowrite16(spidat1, dspi->base + SPIDAT1 + 2); } } /** * davinci_spi_get_prescale - Calculates the correct prescale value Loading Loading @@ -289,7 +295,7 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, int prescale; dspi = spi_master_get_devdata(spi->master); spicfg = (struct davinci_spi_config *)spi->controller_data; spicfg = spi->controller_data; if (!spicfg) spicfg = &davinci_spi_default_cfg; Loading Loading @@ -336,6 +342,14 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, if (!(spi->mode & SPI_CPHA)) spifmt |= SPIFMT_PHASE_MASK; /* * Assume wdelay is used only on SPI peripherals that has this field * in SPIFMTn register and when it's configured from board file or DT. */ if (spicfg->wdelay) spifmt |= ((spicfg->wdelay << SPIFMT_WDELAY_SHIFT) & SPIFMT_WDELAY_MASK); /* * Version 1 hardware supports two basic SPI modes: * - Standard SPI mode uses 4 pins, with chipselect Loading @@ -353,9 +367,6 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, u32 delay = 0; spifmt |= ((spicfg->wdelay << SPIFMT_WDELAY_SHIFT) & SPIFMT_WDELAY_MASK); if (spicfg->odd_parity) spifmt |= SPIFMT_ODD_PARITY_MASK; Loading Loading @@ -387,6 +398,26 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, return 0; } static int davinci_spi_of_setup(struct spi_device *spi) { struct davinci_spi_config *spicfg = spi->controller_data; struct device_node *np = spi->dev.of_node; u32 prop; if (spicfg == NULL && np) { spicfg = kzalloc(sizeof(*spicfg), GFP_KERNEL); if (!spicfg) return -ENOMEM; *spicfg = davinci_spi_default_cfg; /* override with dt configured values */ if (!of_property_read_u32(np, "ti,spi-wdelay", &prop)) spicfg->wdelay = (u8)prop; spi->controller_data = spicfg; } return 0; } /** * davinci_spi_setup - This functions will set default transfer method * @spi: spi device on which data transfer to be done Loading Loading @@ -437,7 +468,16 @@ static int davinci_spi_setup(struct spi_device *spi) else clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_LOOPBACK_MASK); return retval; return davinci_spi_of_setup(spi); } static void davinci_spi_cleanup(struct spi_device *spi) { struct davinci_spi_config *spicfg = spi->controller_data; spi->controller_data = NULL; if (spi->dev.of_node) kfree(spicfg); } static int davinci_spi_check_error(struct davinci_spi *dspi, int int_status) Loading Loading @@ -951,6 +991,7 @@ static int davinci_spi_probe(struct platform_device *pdev) master->num_chipselect = pdata->num_chipselect; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 16); master->setup = davinci_spi_setup; master->cleanup = davinci_spi_cleanup; dspi->bitbang.chipselect = davinci_spi_chipselect; dspi->bitbang.setup_transfer = davinci_spi_setup_transfer; Loading
drivers/spi/spi-dw-mid.c +34 −31 Original line number Diff line number Diff line /* * Special handling for DW core on Intel MID platform * * Copyright (c) 2009, Intel Corporation. * Copyright (c) 2009, 2014 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, Loading @@ -11,10 +11,6 @@ * 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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include <linux/dma-mapping.h> Loading @@ -39,22 +35,25 @@ static bool mid_spi_dma_chan_filter(struct dma_chan *chan, void *param) { struct dw_spi *dws = param; return dws->dmac && (&dws->dmac->dev == chan->device->dev); return dws->dma_dev == chan->device->dev; } static int mid_spi_dma_init(struct dw_spi *dws) { struct mid_dma *dw_dma = dws->dma_priv; struct pci_dev *dma_dev; struct intel_mid_dma_slave *rxs, *txs; dma_cap_mask_t mask; /* * Get pci device for DMA controller, currently it could only * be the DMA controller of either Moorestown or Medfield * be the DMA controller of Medfield */ dws->dmac = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0813, NULL); if (!dws->dmac) dws->dmac = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0827, NULL); dma_dev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0827, NULL); if (!dma_dev) return -ENODEV; dws->dma_dev = &dma_dev->dev; dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); Loading Loading @@ -83,13 +82,18 @@ static int mid_spi_dma_init(struct dw_spi *dws) free_rxchan: dma_release_channel(dws->rxchan); err_exit: return -1; return -EBUSY; } static void mid_spi_dma_exit(struct dw_spi *dws) { if (!dws->dma_inited) return; dmaengine_terminate_all(dws->txchan); dma_release_channel(dws->txchan); dmaengine_terminate_all(dws->rxchan); dma_release_channel(dws->rxchan); } Loading @@ -109,8 +113,7 @@ static void dw_spi_dma_done(void *arg) static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) { struct dma_async_tx_descriptor *txdesc = NULL, *rxdesc = NULL; struct dma_chan *txchan, *rxchan; struct dma_async_tx_descriptor *txdesc, *rxdesc; struct dma_slave_config txconf, rxconf; u16 dma_ctrl = 0; Loading @@ -120,37 +123,34 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) dw_writew(dws, DW_SPI_DMARDLR, 0xf); dw_writew(dws, DW_SPI_DMATDLR, 0x10); if (dws->tx_dma) dma_ctrl |= 0x2; dma_ctrl |= SPI_DMA_TDMAE; if (dws->rx_dma) dma_ctrl |= 0x1; dma_ctrl |= SPI_DMA_RDMAE; dw_writew(dws, DW_SPI_DMACR, dma_ctrl); spi_enable_chip(dws, 1); } dws->dma_chan_done = 0; txchan = dws->txchan; rxchan = dws->rxchan; /* 2. Prepare the TX dma transfer */ txconf.direction = DMA_MEM_TO_DEV; txconf.dst_addr = dws->dma_addr; txconf.dst_maxburst = LNW_DMA_MSIZE_16; txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; txconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; txconf.dst_addr_width = dws->dma_width; txconf.device_fc = false; txchan->device->device_control(txchan, DMA_SLAVE_CONFIG, (unsigned long) &txconf); dmaengine_slave_config(dws->txchan, &txconf); memset(&dws->tx_sgl, 0, sizeof(dws->tx_sgl)); dws->tx_sgl.dma_address = dws->tx_dma; dws->tx_sgl.length = dws->len; txdesc = dmaengine_prep_slave_sg(txchan, txdesc = dmaengine_prep_slave_sg(dws->txchan, &dws->tx_sgl, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT); DMA_PREP_INTERRUPT | DMA_CTRL_ACK); txdesc->callback = dw_spi_dma_done; txdesc->callback_param = dws; Loading @@ -159,27 +159,30 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) rxconf.src_addr = dws->dma_addr; rxconf.src_maxburst = LNW_DMA_MSIZE_16; rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; rxconf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; rxconf.src_addr_width = dws->dma_width; rxconf.device_fc = false; rxchan->device->device_control(rxchan, DMA_SLAVE_CONFIG, (unsigned long) &rxconf); dmaengine_slave_config(dws->rxchan, &rxconf); memset(&dws->rx_sgl, 0, sizeof(dws->rx_sgl)); dws->rx_sgl.dma_address = dws->rx_dma; dws->rx_sgl.length = dws->len; rxdesc = dmaengine_prep_slave_sg(rxchan, rxdesc = dmaengine_prep_slave_sg(dws->rxchan, &dws->rx_sgl, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); DMA_PREP_INTERRUPT | DMA_CTRL_ACK); rxdesc->callback = dw_spi_dma_done; rxdesc->callback_param = dws; /* rx must be started before tx due to spi instinct */ rxdesc->tx_submit(rxdesc); txdesc->tx_submit(txdesc); dmaengine_submit(rxdesc); dma_async_issue_pending(dws->rxchan); dmaengine_submit(txdesc); dma_async_issue_pending(dws->txchan); return 0; } Loading @@ -190,7 +193,7 @@ static struct dw_spi_dma_ops mid_dma_ops = { }; #endif /* Some specific info for SPI0 controller on Moorestown */ /* Some specific info for SPI0 controller on Intel MID */ /* HW info for MRST CLk Control Unit, one 32b reg */ #define MRST_SPI_CLK_BASE 100000000 /* 100m */ Loading