Commit 010b0e70 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'spi-v4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi

Pull spi updates from Mark Brown:
 "Quite an active release for the SPI subsystem, lots of small updates
  and fixes scattered about with highlights including:

   - 3-wire support in the GPIO driver.

   - support for setting a custom memory name in the memory mapped flash
     drivers.

   - support for extended mode in the Freescale DSPI controller.

   - support for the non-standard integration with the Microsemi Ocelot
     platform in the DesignWare driver.

   - new driver for the SocioNext UniPhier"

* tag 'spi-v4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (47 commits)
  spi: davinci: fix a NULL pointer dereference
  spi: spi-mem: Constify spi_mem->name
  mtd: m25p80: Call spi_mem_get_name() to let controller set a custom name
  spi: spi-mem: Extend the SPI mem interface to set a custom memory name
  spi: spi-mem: Fix a typo in the documentation of struct spi_mem
  spi: uniphier: remove unnecessary include headers
  spi: spi-gpio: add SPI_3WIRE support
  spi: add flags parameter to txrx_word function pointers
  spi: add SPI controller driver for UniPhier SoC
  spi: add DT bindings for UniPhier SPI controller
  spi: dw: document Microsemi integration
  spi: img-spfi: Set device select bits for SPFI port state
  spi: omap2-mcspi: remove several redundant variables
  spi: dw-mmio: add MSCC Ocelot support
  spi: dw: export dw_spi_set_cs
  spi: spi-fsl-espi: Log fifo counters on error
  spi: imx: Use the longuest possible burst size when in dynamic_burst
  spi: imx: remove unnecessary check in spi_imx_can_dma
  spi: imx: Use correct number of bytes per words
  spi: imx: Use dynamic bursts only when bits_per_word is 8, 16 or 32
  ...
parents 792adb90 c1acb21b
Synopsys DesignWare AMBA 2.0 Synchronous Serial Interface. Synopsys DesignWare AMBA 2.0 Synchronous Serial Interface.
Required properties: Required properties:
- compatible : "snps,dw-apb-ssi" - compatible : "snps,dw-apb-ssi" or "mscc,<soc>-spi", where soc is "ocelot" or
- reg : The register base for the controller. "jaguar2"
- reg : The register base for the controller. For "mscc,<soc>-spi", a second
register set is required (named ICPU_CFG:SPI_MST)
- interrupts : One interrupt, used by the controller. - interrupts : One interrupt, used by the controller.
- #address-cells : <1>, as required by generic SPI binding. - #address-cells : <1>, as required by generic SPI binding.
- #size-cells : <0>, also as required by generic SPI binding. - #size-cells : <0>, also as required by generic SPI binding.
......
...@@ -7,6 +7,7 @@ Required Properties: ...@@ -7,6 +7,7 @@ Required Properties:
- compatible: should be one of the following. - compatible: should be one of the following.
"rockchip,rv1108-spi" for rv1108 SoCs. "rockchip,rv1108-spi" for rv1108 SoCs.
"rockchip,px30-spi", "rockchip,rk3066-spi" for px30 SoCs.
"rockchip,rk3036-spi" for rk3036 SoCS. "rockchip,rk3036-spi" for rk3036 SoCS.
"rockchip,rk3066-spi" for rk3066 SoCs. "rockchip,rk3066-spi" for rk3066 SoCs.
"rockchip,rk3188-spi" for rk3188 SoCs. "rockchip,rk3188-spi" for rk3188 SoCs.
......
Socionext UniPhier SPI controller driver
UniPhier SoCs have SCSSI which supports SPI single channel.
Required properties:
- compatible: should be "socionext,uniphier-scssi"
- reg: address and length of the spi master registers
- #address-cells: must be <1>, see spi-bus.txt
- #size-cells: must be <0>, see spi-bus.txt
- clocks: A phandle to the clock for the device.
- resets: A phandle to the reset control for the device.
Example:
spi0: spi@54006000 {
compatible = "socionext,uniphier-scssi";
reg = <0x54006000 0x100>;
#address-cells = <1>;
#size-cells = <0>;
clocks = <&peri_clk 11>;
resets = <&peri_rst 11>;
};
...@@ -199,6 +199,9 @@ static int m25p_probe(struct spi_mem *spimem) ...@@ -199,6 +199,9 @@ static int m25p_probe(struct spi_mem *spimem)
if (data && data->name) if (data && data->name)
nor->mtd.name = data->name; nor->mtd.name = data->name;
if (!nor->mtd.name)
nor->mtd.name = spi_mem_get_name(spimem);
/* For some (historical?) reason many platforms provide two different /* For some (historical?) reason many platforms provide two different
* names in flash_platform_data: "name" and "type". Quite often name is * names in flash_platform_data: "name" and "type". Quite often name is
* set to "m25p80" and then "type" provides a real chip name. * set to "m25p80" and then "type" provides a real chip name.
......
...@@ -688,6 +688,19 @@ config SPI_TXX9 ...@@ -688,6 +688,19 @@ config SPI_TXX9
help help
SPI driver for Toshiba TXx9 MIPS SoCs SPI driver for Toshiba TXx9 MIPS SoCs
config SPI_UNIPHIER
tristate "Socionext UniPhier SPI Controller"
depends on (ARCH_UNIPHIER || COMPILE_TEST) && OF
help
This enables a driver for the Socionext UniPhier SoC SCSSI SPI controller.
UniPhier SoCs have SCSSI and MCSSI SPI controllers.
Every UniPhier SoC has SCSSI which supports single channel.
Older UniPhier Pro4/Pro5 also has MCSSI which support multiple channels.
This driver supports SCSSI only.
If your SoC supports SCSSI, say Y here.
config SPI_XCOMM config SPI_XCOMM
tristate "Analog Devices AD-FMCOMMS1-EBZ SPI-I2C-bridge driver" tristate "Analog Devices AD-FMCOMMS1-EBZ SPI-I2C-bridge driver"
depends on I2C depends on I2C
......
...@@ -101,6 +101,7 @@ spi-thunderx-objs := spi-cavium.o spi-cavium-thunderx.o ...@@ -101,6 +101,7 @@ spi-thunderx-objs := spi-cavium.o spi-cavium-thunderx.o
obj-$(CONFIG_SPI_THUNDERX) += spi-thunderx.o obj-$(CONFIG_SPI_THUNDERX) += spi-thunderx.o
obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi-topcliff-pch.o obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi-topcliff-pch.o
obj-$(CONFIG_SPI_TXX9) += spi-txx9.o obj-$(CONFIG_SPI_TXX9) += spi-txx9.o
obj-$(CONFIG_SPI_UNIPHIER) += spi-uniphier.o
obj-$(CONFIG_SPI_XCOMM) += spi-xcomm.o obj-$(CONFIG_SPI_XCOMM) += spi-xcomm.o
obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o
obj-$(CONFIG_SPI_XLP) += spi-xlp.o obj-$(CONFIG_SPI_XLP) += spi-xlp.o
......
...@@ -176,7 +176,7 @@ static void ath79_spi_cleanup(struct spi_device *spi) ...@@ -176,7 +176,7 @@ static void ath79_spi_cleanup(struct spi_device *spi)
} }
static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned int nsecs, static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned int nsecs,
u32 word, u8 bits) u32 word, u8 bits, unsigned flags)
{ {
struct ath79_spi *sp = ath79_spidev_to_sp(spi); struct ath79_spi *sp = ath79_spidev_to_sp(spi);
u32 ioc = sp->ioc_base; u32 ioc = sp->ioc_base;
......
...@@ -49,22 +49,26 @@ ...@@ -49,22 +49,26 @@
struct spi_bitbang_cs { struct spi_bitbang_cs {
unsigned nsecs; /* (clock cycle time)/2 */ unsigned nsecs; /* (clock cycle time)/2 */
u32 (*txrx_word)(struct spi_device *spi, unsigned nsecs, u32 (*txrx_word)(struct spi_device *spi, unsigned nsecs,
u32 word, u8 bits); u32 word, u8 bits, unsigned flags);
unsigned (*txrx_bufs)(struct spi_device *, unsigned (*txrx_bufs)(struct spi_device *,
u32 (*txrx_word)( u32 (*txrx_word)(
struct spi_device *spi, struct spi_device *spi,
unsigned nsecs, unsigned nsecs,
u32 word, u8 bits), u32 word, u8 bits,
unsigned, struct spi_transfer *); unsigned flags),
unsigned, struct spi_transfer *,
unsigned);
}; };
static unsigned bitbang_txrx_8( static unsigned bitbang_txrx_8(
struct spi_device *spi, struct spi_device *spi,
u32 (*txrx_word)(struct spi_device *spi, u32 (*txrx_word)(struct spi_device *spi,
unsigned nsecs, unsigned nsecs,
u32 word, u8 bits), u32 word, u8 bits,
unsigned flags),
unsigned ns, unsigned ns,
struct spi_transfer *t struct spi_transfer *t,
unsigned flags
) { ) {
unsigned bits = t->bits_per_word; unsigned bits = t->bits_per_word;
unsigned count = t->len; unsigned count = t->len;
...@@ -76,7 +80,7 @@ static unsigned bitbang_txrx_8( ...@@ -76,7 +80,7 @@ static unsigned bitbang_txrx_8(
if (tx) if (tx)
word = *tx++; word = *tx++;
word = txrx_word(spi, ns, word, bits); word = txrx_word(spi, ns, word, bits, flags);
if (rx) if (rx)
*rx++ = word; *rx++ = word;
count -= 1; count -= 1;
...@@ -88,9 +92,11 @@ static unsigned bitbang_txrx_16( ...@@ -88,9 +92,11 @@ static unsigned bitbang_txrx_16(
struct spi_device *spi, struct spi_device *spi,
u32 (*txrx_word)(struct spi_device *spi, u32 (*txrx_word)(struct spi_device *spi,
unsigned nsecs, unsigned nsecs,
u32 word, u8 bits), u32 word, u8 bits,
unsigned flags),
unsigned ns, unsigned ns,
struct spi_transfer *t struct spi_transfer *t,
unsigned flags
) { ) {
unsigned bits = t->bits_per_word; unsigned bits = t->bits_per_word;
unsigned count = t->len; unsigned count = t->len;
...@@ -102,7 +108,7 @@ static unsigned bitbang_txrx_16( ...@@ -102,7 +108,7 @@ static unsigned bitbang_txrx_16(
if (tx) if (tx)
word = *tx++; word = *tx++;
word = txrx_word(spi, ns, word, bits); word = txrx_word(spi, ns, word, bits, flags);
if (rx) if (rx)
*rx++ = word; *rx++ = word;
count -= 2; count -= 2;
...@@ -114,9 +120,11 @@ static unsigned bitbang_txrx_32( ...@@ -114,9 +120,11 @@ static unsigned bitbang_txrx_32(
struct spi_device *spi, struct spi_device *spi,
u32 (*txrx_word)(struct spi_device *spi, u32 (*txrx_word)(struct spi_device *spi,
unsigned nsecs, unsigned nsecs,
u32 word, u8 bits), u32 word, u8 bits,
unsigned flags),
unsigned ns, unsigned ns,
struct spi_transfer *t struct spi_transfer *t,
unsigned flags
) { ) {
unsigned bits = t->bits_per_word; unsigned bits = t->bits_per_word;
unsigned count = t->len; unsigned count = t->len;
...@@ -128,7 +136,7 @@ static unsigned bitbang_txrx_32( ...@@ -128,7 +136,7 @@ static unsigned bitbang_txrx_32(
if (tx) if (tx)
word = *tx++; word = *tx++;
word = txrx_word(spi, ns, word, bits); word = txrx_word(spi, ns, word, bits, flags);
if (rx) if (rx)
*rx++ = word; *rx++ = word;
count -= 4; count -= 4;
...@@ -235,8 +243,24 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t) ...@@ -235,8 +243,24 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t)
{ {
struct spi_bitbang_cs *cs = spi->controller_state; struct spi_bitbang_cs *cs = spi->controller_state;
unsigned nsecs = cs->nsecs; unsigned nsecs = cs->nsecs;
struct spi_bitbang *bitbang;
bitbang = spi_master_get_devdata(spi->master);
if (bitbang->set_line_direction) {
int err;
return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t); err = bitbang->set_line_direction(spi, !!(t->tx_buf));
if (err < 0)
return err;
}
if (spi->mode & SPI_3WIRE) {
unsigned flags;
flags = t->tx_buf ? SPI_MASTER_NO_RX : SPI_MASTER_NO_TX;
return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t, flags);
}
return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t, 0);
} }
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
......
...@@ -144,9 +144,9 @@ static void butterfly_chipselect(struct spi_device *spi, int value) ...@@ -144,9 +144,9 @@ static void butterfly_chipselect(struct spi_device *spi, int value)
static u32 static u32
butterfly_txrx_word_mode0(struct spi_device *spi, unsigned nsecs, u32 word, butterfly_txrx_word_mode0(struct spi_device *spi, unsigned nsecs, u32 word,
u8 bits) u8 bits, unsigned flags)
{ {
return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits); return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);
} }
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
......
...@@ -319,7 +319,7 @@ static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi) ...@@ -319,7 +319,7 @@ static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi)
*/ */
if (cdns_spi_read(xspi, CDNS_SPI_ISR) & if (cdns_spi_read(xspi, CDNS_SPI_ISR) &
CDNS_SPI_IXR_TXFULL) CDNS_SPI_IXR_TXFULL)
usleep_range(10, 20); udelay(10);
if (xspi->txbuf) if (xspi->txbuf)
cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++); cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++);
...@@ -739,7 +739,7 @@ static int __maybe_unused cnds_runtime_resume(struct device *dev) ...@@ -739,7 +739,7 @@ static int __maybe_unused cnds_runtime_resume(struct device *dev)
ret = clk_prepare_enable(xspi->ref_clk); ret = clk_prepare_enable(xspi->ref_clk);
if (ret) { if (ret) {
dev_err(dev, "Cannot enable device clock.\n"); dev_err(dev, "Cannot enable device clock.\n");
clk_disable(xspi->pclk); clk_disable_unprepare(xspi->pclk);
return ret; return ret;
} }
return 0; return 0;
......
...@@ -217,7 +217,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) ...@@ -217,7 +217,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
pdata = &dspi->pdata; pdata = &dspi->pdata;
/* program delay transfers if tx_delay is non zero */ /* program delay transfers if tx_delay is non zero */
if (spicfg->wdelay) if (spicfg && spicfg->wdelay)
spidat1 |= SPIDAT1_WDEL; spidat1 |= SPIDAT1_WDEL;
/* /*
......
...@@ -15,11 +15,13 @@ ...@@ -15,11 +15,13 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/property.h> #include <linux/property.h>
#include <linux/regmap.h>
#include "spi-dw.h" #include "spi-dw.h"
...@@ -28,10 +30,90 @@ ...@@ -28,10 +30,90 @@
struct dw_spi_mmio { struct dw_spi_mmio {
struct dw_spi dws; struct dw_spi dws;
struct clk *clk; struct clk *clk;
void *priv;
}; };
#define MSCC_CPU_SYSTEM_CTRL_GENERAL_CTRL 0x24
#define OCELOT_IF_SI_OWNER_MASK GENMASK(5, 4)
#define OCELOT_IF_SI_OWNER_OFFSET 4
#define MSCC_IF_SI_OWNER_SISL 0
#define MSCC_IF_SI_OWNER_SIBM 1
#define MSCC_IF_SI_OWNER_SIMC 2
#define MSCC_SPI_MST_SW_MODE 0x14
#define MSCC_SPI_MST_SW_MODE_SW_PIN_CTRL_MODE BIT(13)
#define MSCC_SPI_MST_SW_MODE_SW_SPI_CS(x) (x << 5)
struct dw_spi_mscc {
struct regmap *syscon;
void __iomem *spi_mst;
};
/*
* The Designware SPI controller (referred to as master in the documentation)
* automatically deasserts chip select when the tx fifo is empty. The chip
* selects then needs to be either driven as GPIOs or, for the first 4 using the
* the SPI boot controller registers. the final chip select is an OR gate
* between the Designware SPI controller and the SPI boot controller.
*/
static void dw_spi_mscc_set_cs(struct spi_device *spi, bool enable)
{
struct dw_spi *dws = spi_master_get_devdata(spi->master);
struct dw_spi_mmio *dwsmmio = container_of(dws, struct dw_spi_mmio, dws);
struct dw_spi_mscc *dwsmscc = dwsmmio->priv;
u32 cs = spi->chip_select;
if (cs < 4) {
u32 sw_mode = MSCC_SPI_MST_SW_MODE_SW_PIN_CTRL_MODE;
if (!enable)
sw_mode |= MSCC_SPI_MST_SW_MODE_SW_SPI_CS(BIT(cs));
writel(sw_mode, dwsmscc->spi_mst + MSCC_SPI_MST_SW_MODE);
}
dw_spi_set_cs(spi, enable);
}
static int dw_spi_mscc_init(struct platform_device *pdev,
struct dw_spi_mmio *dwsmmio)
{
struct dw_spi_mscc *dwsmscc;
struct resource *res;
dwsmscc = devm_kzalloc(&pdev->dev, sizeof(*dwsmscc), GFP_KERNEL);
if (!dwsmscc)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
dwsmscc->spi_mst = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(dwsmscc->spi_mst)) {
dev_err(&pdev->dev, "SPI_MST region map failed\n");
return PTR_ERR(dwsmscc->spi_mst);
}
dwsmscc->syscon = syscon_regmap_lookup_by_compatible("mscc,ocelot-cpu-syscon");
if (IS_ERR(dwsmscc->syscon))
return PTR_ERR(dwsmscc->syscon);
/* Deassert all CS */
writel(0, dwsmscc->spi_mst + MSCC_SPI_MST_SW_MODE);
/* Select the owner of the SI interface */
regmap_update_bits(dwsmscc->syscon, MSCC_CPU_SYSTEM_CTRL_GENERAL_CTRL,
OCELOT_IF_SI_OWNER_MASK,
MSCC_IF_SI_OWNER_SIMC << OCELOT_IF_SI_OWNER_OFFSET);
dwsmmio->dws.set_cs = dw_spi_mscc_set_cs;
dwsmmio->priv = dwsmscc;
return 0;
}
static int dw_spi_mmio_probe(struct platform_device *pdev) static int dw_spi_mmio_probe(struct platform_device *pdev)
{ {
int (*init_func)(struct platform_device *pdev,
struct dw_spi_mmio *dwsmmio);
struct dw_spi_mmio *dwsmmio; struct dw_spi_mmio *dwsmmio;
struct dw_spi *dws; struct dw_spi *dws;
struct resource *mem; struct resource *mem;
...@@ -99,6 +181,13 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) ...@@ -99,6 +181,13 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
} }
} }
init_func = device_get_match_data(&pdev->dev);
if (init_func) {
ret = init_func(pdev, dwsmmio);
if (ret)
goto out;
}
ret = dw_spi_add_host(&pdev->dev, dws); ret = dw_spi_add_host(&pdev->dev, dws);
if (ret) if (ret)
goto out; goto out;
...@@ -123,6 +212,7 @@ static int dw_spi_mmio_remove(struct platform_device *pdev) ...@@ -123,6 +212,7 @@ static int dw_spi_mmio_remove(struct platform_device *pdev)
static const struct of_device_id dw_spi_mmio_of_match[] = { static const struct of_device_id dw_spi_mmio_of_match[] = {
{ .compatible = "snps,dw-apb-ssi", }, { .compatible = "snps,dw-apb-ssi", },
{ .compatible = "mscc,ocelot-spi", .data = dw_spi_mscc_init},
{ /* end of table */} { /* end of table */}
}; };
MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match); MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
......
...@@ -133,7 +133,7 @@ static inline void dw_spi_debugfs_remove(struct dw_spi *dws) ...@@ -133,7 +133,7 @@ static inline void dw_spi_debugfs_remove(struct dw_spi *dws)
} }
#endif /* CONFIG_DEBUG_FS */ #endif /* CONFIG_DEBUG_FS */
static void dw_spi_set_cs(struct spi_device *spi, bool enable) void dw_spi_set_cs(struct spi_device *spi, bool enable)
{ {
struct dw_spi *dws = spi_controller_get_devdata(spi->controller); struct dw_spi *dws = spi_controller_get_devdata(spi->controller);
struct chip_data *chip = spi_get_ctldata(spi); struct chip_data *chip = spi_get_ctldata(spi);
...@@ -145,6 +145,7 @@ static void dw_spi_set_cs(struct spi_device *spi, bool enable) ...@@ -145,6 +145,7 @@ static void dw_spi_set_cs(struct spi_device *spi, bool enable)
if (!enable) if (!enable)
dw_writel(dws, DW_SPI_SER, BIT(spi->chip_select)); dw_writel(dws, DW_SPI_SER, BIT(spi->chip_select));
} }
EXPORT_SYMBOL_GPL(dw_spi_set_cs);
/* Return the max entries we can fill into tx fifo */ /* Return the max entries we can fill into tx fifo */
static inline u32 tx_max(struct dw_spi *dws) static inline u32 tx_max(struct dw_spi *dws)
...@@ -485,6 +486,8 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) ...@@ -485,6 +486,8 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
dws->dma_inited = 0; dws->dma_inited = 0;
dws->dma_addr = (dma_addr_t)(dws->paddr + DW_SPI_DR); dws->dma_addr = (dma_addr_t)(dws->paddr + DW_SPI_DR);
spi_controller_set_devdata(master, dws);
ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, dev_name(dev), ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, dev_name(dev),
master); master);
if (ret < 0) { if (ret < 0) {
...@@ -505,6 +508,9 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) ...@@ -505,6 +508,9 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
master->dev.of_node = dev->of_node; master->dev.of_node = dev->of_node;
master->flags = SPI_MASTER_GPIO_SS; master->flags = SPI_MASTER_GPIO_SS;
if (dws->set_cs)
master->set_cs = dws->set_cs;
/* Basic HW init */ /* Basic HW init */
spi_hw_init(dev, dws); spi_hw_init(dev, dws);
...@@ -518,7 +524,6 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) ...@@ -518,7 +524,6 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
} }
} }
spi_controller_set_devdata(master, dws);
ret = devm_spi_register_controller(dev, master); ret = devm_spi_register_controller(dev, master);
if (ret) { if (ret) {
dev_err(&master->dev, "problem registering spi master\n"); dev_err(&master->dev, "problem registering spi master\n");
......
...@@ -112,6 +112,7 @@ struct dw_spi { ...@@ -112,6 +112,7 @@ struct dw_spi {
u32 reg_io_width; /* DR I/O width in bytes */ u32 reg_io_width; /* DR I/O width in bytes */
u16 bus_num; u16 bus_num;
u16 num_cs; /* supported slave numbers */ u16 num_cs; /* supported slave numbers */
void (*set_cs)(struct spi_device *spi, bool enable);
/* Current message transfer state info */ /* Current message transfer state info */
size_t len; size_t len;
...@@ -244,6 +245,7 @@ struct dw_spi_chip { ...@@ -244,6 +245,7 @@ struct dw_spi_chip {
void (*cs_control)(u32 command); void (*cs_control)(u32 command);
}; };
extern void dw_spi_set_cs(struct spi_device *spi, bool enable);
extern int dw_spi_add_host(struct device *dev, struct dw_spi *dws); extern int dw_spi_add_host(struct device *dev, struct dw_spi *dws);
extern void dw_spi_remove_host(struct dw_spi *dws); extern void dw_spi_remove_host(struct dw_spi *dws);
extern int dw_spi_suspend_host(struct dw_spi *dws); extern int dw_spi_suspend_host(struct dw_spi *dws);
......
This diff is collapsed.
...@@ -547,8 +547,11 @@ static void fsl_espi_cpu_irq(struct fsl_espi *espi, u32 events) ...@@ -547,8 +547,11 @@ static void fsl_espi_cpu_irq(struct fsl_espi *espi, u32 events)
dev_err(espi->dev, dev_err(espi->dev,
"Transfer done but SPIE_DON isn't set!\n"); "Transfer done but SPIE_DON isn't set!\n");
if (SPIE_RXCNT(events) || SPIE_TXCNT(events) != FSL_ESPI_FIFO_SIZE) if (SPIE_RXCNT(events) || SPIE_TXCNT(events) != FSL_ESPI_FIFO_SIZE) {
dev_err(espi->dev, "Transfer done but rx/tx fifo's aren't empty!\n"); dev_err(espi->dev, "Transfer done but rx/tx fifo's aren't empty!\n");
dev_err(espi->dev, "SPIE_RXCNT = %d, SPIE_TXCNT = %d\n",
SPIE_RXCNT(events), SPIE_TXCNT(events));
}
complete(&espi->done); complete(&espi->done);
} }
......
...@@ -121,7 +121,10 @@ static inline int getmiso(const struct spi_device *spi) ...@@ -121,7 +121,10 @@ static inline int getmiso(const struct spi_device *spi)
{ {
struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
return !!gpiod_get_value_cansleep(spi_gpio->miso); if (spi->mode & SPI_3WIRE)
return !!gpiod_get_value_cansleep(spi_gpio->mosi);
else
return !!gpiod_get_value_cansleep(spi_gpio->miso);
} }
/* /*
...@@ -149,27 +152,27 @@ static inline int getmiso(const struct spi_device *spi) ...@@ -149,27 +152,27 @@ static inline int getmiso(const struct spi_device *spi)
*/ */
static u32 spi_gpio_txrx_word_mode0(struct spi_device *spi, static u32 spi_gpio_txrx_word_mode0(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits, unsigned flags)
{ {
return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits); return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);
} }
static u32 spi_gpio_txrx_word_mode1(struct spi_device *spi, static u32 spi_gpio_txrx_word_mode1(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits, unsigned flags)
{ {
return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits); return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits);
} }
static u32 spi_gpio_txrx_word_mode2(struct spi_device *spi, static u32 spi_gpio_txrx_word_mode2(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits, unsigned flags)
{ {
return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits); return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits);
} }
static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi, static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits, unsigned flags)
{ {
return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits); return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits);
} }
/* /*
...@@ -183,30 +186,30 @@ static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi, ...@@ -183,30 +186,30 @@ static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi,
*/ */
static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi, static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits, unsigned flags)
{ {
unsigned flags = spi->master->flags; flags = spi->master->flags;
return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits); return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);
} }
static u32 spi_gpio_spec_txrx_word_mode1(struct spi_device *spi, static u32 spi_gpio_spec_txrx_word_mode1(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits, unsigned flags)
{ {
unsigned flags = spi->master->flags; flags = spi->master->flags;
return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits); return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits);
} }
static u32 spi_gpio_spec_txrx_word_mode2(struct spi_device *spi, static u32 spi_gpio_spec_txrx_word_mode2(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits, unsigned flags)
{ {
unsigned flags = spi->master->flags; flags = spi->master->flags;
return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits); return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits);
} }
static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi, static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits, unsigned flags)
{ {
unsigned flags = spi->master->flags; flags = spi->master->flags;
return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits); return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits);
} }
...@@ -250,6 +253,16 @@ static int spi_gpio_setup(struct spi_device *spi) ...@@ -250,6 +253,16 @@ static int spi_gpio_setup(struct spi_device *spi)
return status; return status;
} }
static int spi_gpio_set_direction(struct spi_device *spi, bool output)
{
struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
if (output)
return gpiod_direction_output(spi_gpio->mosi, 1);
else
return gpiod_direction_input(spi_gpio->mosi);
}
static void spi_gpio_cleanup(struct spi_device *spi) static void spi_gpio_cleanup(struct spi_device *spi)
{ {
spi_bitbang_cleanup(spi); spi_bitbang_cleanup(spi);
...@@ -395,6 +408,7 @@ static int spi_gpio_probe(struct platform_device *pdev) ...@@ -395,6 +408,7 @@ static int spi_gpio_probe(struct platform_device *pdev)
return status; return status;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
master->mode_bits = SPI_3WIRE | SPI_CPHA | SPI_CPOL;
master->flags = master_flags; master->flags = master_flags;
master->bus_num = pdev->id; master->bus_num = pdev->id;
/* The master needs to think there is a chipselect even if not connected */ /* The master needs to think there is a chipselect even if not connected */
...@@ -407,6 +421,7 @@ static int spi_gpio_probe(struct platform_device *pdev) ...@@ -407,6 +421,7 @@ static int spi_gpio_probe(struct platform_device *pdev)
spi_gpio->bitbang.master = master; spi_gpio->bitbang.master = master;
spi_gpio->bitbang.chipselect = spi_gpio_chipselect; spi_gpio->bitbang.chipselect = spi_gpio_chipselect;
spi_gpio->bitbang.set_line_direction = spi_gpio_set_direction;
if ((master_flags & (SPI_MASTER_NO_TX | SPI_MASTER_NO_RX)) == 0) { if ((master_flags & (SPI_MASTER_NO_TX | SPI_MASTER_NO_RX)) == 0) {
spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0; spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0;
......
...@@ -419,6 +419,9 @@ static int img_spfi_prepare(struct spi_master *master, struct spi_message *msg) ...@@ -419,6 +419,9 @@ static int img_spfi_prepare(struct spi_master *master, struct spi_message *msg)
u32 val; u32 val;
val = spfi_readl(spfi, SPFI_PORT_STATE); val = spfi_readl(spfi, SPFI_PORT_STATE);
val &= ~(SPFI_PORT_STATE_DEV_SEL_MASK <<
SPFI_PORT_STATE_DEV_SEL_SHIFT);
val |= msg->spi->chip_select << SPFI_PORT_STATE_DEV_SEL_SHIFT;
if (msg->spi->mode & SPI_CPHA) if (msg->spi->mode & SPI_CPHA)
val |= SPFI_PORT_STATE_CK_PHASE(msg->spi->chip_select); val |= SPFI_PORT_STATE_CK_PHASE(msg->spi->chip_select);
else else
......
...@@ -94,8 +94,7 @@ struct spi_imx_data { ...@@ -94,8 +94,7 @@ struct spi_imx_data {
void *rx_buf; void *rx_buf;
const void *tx_buf; const void *tx_buf;
unsigned int txfifo; /* number of words pushed in tx FIFO */ unsigned int txfifo; /* number of words pushed in tx FIFO */
unsigned int dynamic_burst, read_u32; unsigned int dynamic_burst;
unsigned int word_mask;
/* Slave mode */ /* Slave mode */
bool slave_mode; bool slave_mode;
...@@ -140,6 +139,8 @@ static void spi_imx_buf_rx_##type(struct spi_imx_data *spi_imx) \ ...@@ -140,6 +139,8 @@ static void spi_imx_buf_rx_##type(struct spi_imx_data *spi_imx) \
*(type *)spi_imx->rx_buf = val; \ *(type *)spi_imx->rx_buf = val; \
spi_imx->rx_buf += sizeof(type); \ spi_imx->rx_buf += sizeof(type); \
} \ } \
\
spi_imx->remainder -= sizeof(type); \
} }
#define MXC_SPI_BUF_TX(type) \ #define MXC_SPI_BUF_TX(type) \
...@@ -203,7 +204,12 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin, ...@@ -203,7 +204,12 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
static int spi_imx_bytes_per_word(const int bits_per_word) static int spi_imx_bytes_per_word(const int bits_per_word)
{ {
return DIV_ROUND_UP(bits_per_word, BITS_PER_BYTE); if (bits_per_word <= 8)
return 1;
else if (bits_per_word <= 16)
return 2;
else
return 4;
} }
static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
...@@ -220,17 +226,11 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, ...@@ -220,17 +226,11 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
bytes_per_word = spi_imx_bytes_per_word(transfer->bits_per_word); bytes_per_word = spi_imx_bytes_per_word(transfer->bits_per_word);
if (bytes_per_word != 1 && bytes_per_word != 2 && bytes_per_word != 4)
return false;
for (i = spi_imx->devtype_data->fifo_size / 2; i > 0; i--) { for (i = spi_imx->devtype_data->fifo_size / 2; i > 0; i--) {
if (!(transfer->len % (i * bytes_per_word))) if (!(transfer->len % (i * bytes_per_word)))
break; break;
} }
if (i == 0)
return false;
spi_imx->wml = i; spi_imx->wml = i;
spi_imx->dynamic_burst = 0; spi_imx->dynamic_burst = 0;
...@@ -291,26 +291,39 @@ static void spi_imx_buf_rx_swap_u32(struct spi_imx_data *spi_imx) ...@@ -291,26 +291,39 @@ static void spi_imx_buf_rx_swap_u32(struct spi_imx_data *spi_imx)
else if (bytes_per_word == 2) else if (bytes_per_word == 2)
val = (val << 16) | (val >> 16); val = (val << 16) | (val >> 16);
#endif #endif
val &= spi_imx->word_mask;
*(u32 *)spi_imx->rx_buf = val; *(u32 *)spi_imx->rx_buf = val;
spi_imx->rx_buf += sizeof(u32); spi_imx->rx_buf += sizeof(u32);
} }
spi_imx->remainder -= sizeof(u32);
} }
static void spi_imx_buf_rx_swap(struct spi_imx_data *spi_imx) static void spi_imx_buf_rx_swap(struct spi_imx_data *spi_imx)
{ {
unsigned int bytes_per_word; int unaligned;
u32 val;
bytes_per_word = spi_imx_bytes_per_word(spi_imx->bits_per_word); unaligned = spi_imx->remainder % 4;
if (spi_imx->read_u32) {
if (!unaligned) {
spi_imx_buf_rx_swap_u32(spi_imx); spi_imx_buf_rx_swap_u32(spi_imx);
return; return;
} }
if (bytes_per_word == 1) if (spi_imx_bytes_per_word(spi_imx->bits_per_word) == 2) {
spi_imx_buf_rx_u8(spi_imx);
else if (bytes_per_word == 2)
spi_imx_buf_rx_u16(spi_imx); spi_imx_buf_rx_u16(spi_imx);
return;
}
val = readl(spi_imx->base + MXC_CSPIRXDATA);
while (unaligned--) {
if (spi_imx->rx_buf) {
*(u8 *)spi_imx->rx_buf = (val >> (8 * unaligned)) & 0xff;
spi_imx->rx_buf++;
}
spi_imx->remainder--;
}
} }
static void spi_imx_buf_tx_swap_u32(struct spi_imx_data *spi_imx) static void spi_imx_buf_tx_swap_u32(struct spi_imx_data *spi_imx)
...@@ -322,7 +335,6 @@ static void spi_imx_buf_tx_swap_u32(struct spi_imx_data *spi_imx) ...@@ -322,7 +335,6 @@ static void spi_imx_buf_tx_swap_u32(struct spi_imx_data *spi_imx)
if (spi_imx->tx_buf) { if (spi_imx->tx_buf) {
val = *(u32 *)spi_imx->tx_buf; val = *(u32 *)spi_imx->tx_buf;
val &= spi_imx->word_mask;
spi_imx->tx_buf += sizeof(u32); spi_imx->tx_buf += sizeof(u32);
} }
...@@ -340,40 +352,30 @@ static void spi_imx_buf_tx_swap_u32(struct spi_imx_data *spi_imx) ...@@ -340,40 +352,30 @@ static void spi_imx_buf_tx_swap_u32(struct spi_imx_data *spi_imx)
static void spi_imx_buf_tx_swap(struct spi_imx_data *spi_imx) static void spi_imx_buf_tx_swap(struct spi_imx_data *spi_imx)
{ {
u32 ctrl, val; int unaligned;
unsigned int bytes_per_word; u32 val = 0;
if (spi_imx->count == spi_imx->remainder) { unaligned = spi_imx->count % 4;
ctrl = readl(spi_imx->base + MX51_ECSPI_CTRL);
ctrl &= ~MX51_ECSPI_CTRL_BL_MASK;
if (spi_imx->count > MX51_ECSPI_CTRL_MAX_BURST) {
spi_imx->remainder = spi_imx->count %
MX51_ECSPI_CTRL_MAX_BURST;
val = MX51_ECSPI_CTRL_MAX_BURST * 8 - 1;
} else if (spi_imx->count >= sizeof(u32)) {
spi_imx->remainder = spi_imx->count % sizeof(u32);
val = (spi_imx->count - spi_imx->remainder) * 8 - 1;
} else {
spi_imx->remainder = 0;
val = spi_imx->bits_per_word - 1;
spi_imx->read_u32 = 0;
}
ctrl |= (val << MX51_ECSPI_CTRL_BL_OFFSET); if (!unaligned) {
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); spi_imx_buf_tx_swap_u32(spi_imx);
return;
} }
if (spi_imx->count >= sizeof(u32)) { if (spi_imx_bytes_per_word(spi_imx->bits_per_word) == 2) {
spi_imx_buf_tx_swap_u32(spi_imx); spi_imx_buf_tx_u16(spi_imx);
return; return;
} }
bytes_per_word = spi_imx_bytes_per_word(spi_imx->bits_per_word); while (unaligned--) {
if (spi_imx->tx_buf) {
val |= *(u8 *)spi_imx->tx_buf << (8 * unaligned);
spi_imx->tx_buf++;
}
spi_imx->count--;
}
if (bytes_per_word == 1) writel(val, spi_imx->base + MXC_CSPITXDATA);
spi_imx_buf_tx_u8(spi_imx);
else if (bytes_per_word == 2)
spi_imx_buf_tx_u16(spi_imx);
} }
static void mx53_ecspi_rx_slave(struct spi_imx_data *spi_imx) static void mx53_ecspi_rx_slave(struct spi_imx_data *spi_imx)
...@@ -392,6 +394,8 @@ static void mx53_ecspi_rx_slave(struct spi_imx_data *spi_imx) ...@@ -392,6 +394,8 @@ static void mx53_ecspi_rx_slave(struct spi_imx_data *spi_imx)
spi_imx->rx_buf += n_bytes; spi_imx->rx_buf += n_bytes;
spi_imx->slave_burst -= n_bytes; spi_imx->slave_burst -= n_bytes;
} }
spi_imx->remainder -= sizeof(u32);
} }
static void mx53_ecspi_tx_slave(struct spi_imx_data *spi_imx) static void mx53_ecspi_tx_slave(struct spi_imx_data *spi_imx)
...@@ -1001,12 +1005,52 @@ static void spi_imx_chipselect(struct spi_device *spi, int is_active) ...@@ -1001,12 +1005,52 @@ static void spi_imx_chipselect(struct spi_device *spi, int is_active)
gpio_set_value(spi->cs_gpio, dev_is_lowactive ^ active); gpio_set_value(spi->cs_gpio, dev_is_lowactive ^ active);
} }
static void spi_imx_set_burst_len(struct spi_imx_data *spi_imx, int n_bits)
{
u32 ctrl;
ctrl = readl(spi_imx->base + MX51_ECSPI_CTRL);
ctrl &= ~MX51_ECSPI_CTRL_BL_MASK;
ctrl |= ((n_bits - 1) << MX51_ECSPI_CTRL_BL_OFFSET);
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
}
static void spi_imx_push(struct spi_imx_data *spi_imx) static void spi_imx_push(struct spi_imx_data *spi_imx)
{ {
unsigned int burst_len, fifo_words;
if (spi_imx->dynamic_burst)
fifo_words = 4;
else
fifo_words = spi_imx_bytes_per_word(spi_imx->bits_per_word);
/*
* Reload the FIFO when the remaining bytes to be transferred in the
* current burst is 0. This only applies when bits_per_word is a
* multiple of 8.
*/
if (!spi_imx->remainder) {
if (spi_imx->dynamic_burst) {
/* We need to deal unaligned data first */
burst_len = spi_imx->count % MX51_ECSPI_CTRL_MAX_BURST;
if (!burst_len)
burst_len = MX51_ECSPI_CTRL_MAX_BURST;
spi_imx_set_burst_len(spi_imx, burst_len * 8);
spi_imx->remainder = burst_len;
} else {
spi_imx->remainder = fifo_words;
}
}
while (spi_imx->txfifo < spi_imx->devtype_data->fifo_size) { while (spi_imx->txfifo < spi_imx->devtype_data->fifo_size) {
if (!spi_imx->count) if (!spi_imx->count)
break; break;
if (spi_imx->txfifo && (spi_imx->count == spi_imx->remainder)) if (spi_imx->dynamic_burst &&
spi_imx->txfifo >= DIV_ROUND_UP(spi_imx->remainder,
fifo_words))
break; break;
spi_imx->tx(spi_imx); spi_imx->tx(spi_imx);
spi_imx->txfifo++; spi_imx->txfifo++;
...@@ -1102,27 +1146,20 @@ static int spi_imx_setupxfer(struct spi_device *spi, ...@@ -1102,27 +1146,20 @@ static int spi_imx_setupxfer(struct spi_device *spi,
spi_imx->bits_per_word = t->bits_per_word; spi_imx->bits_per_word = t->bits_per_word;
spi_imx->speed_hz = t->speed_hz; spi_imx->speed_hz = t->speed_hz;
/* Initialize the functions for transfer */ /*
if (spi_imx->devtype_data->dynamic_burst && !spi_imx->slave_mode) { * Initialize the functions for transfer. To transfer non byte-aligned
u32 mask; * words, we have to use multiple word-size bursts, we can't use
* dynamic_burst in that case.
spi_imx->dynamic_burst = 0; */
spi_imx->remainder = 0; if (spi_imx->devtype_data->dynamic_burst && !spi_imx->slave_mode &&
spi_imx->read_u32 = 1; (spi_imx->bits_per_word == 8 ||
spi_imx->bits_per_word == 16 ||
spi_imx->bits_per_word == 32)) {
mask = (1 << spi_imx->bits_per_word) - 1;
spi_imx->rx = spi_imx_buf_rx_swap; spi_imx->rx = spi_imx_buf_rx_swap;
spi_imx->tx = spi_imx_buf_tx_swap; spi_imx->tx = spi_imx_buf_tx_swap;
spi_imx->dynamic_burst = 1; spi_imx->dynamic_burst = 1;
spi_imx->remainder = t->len;
if (spi_imx->bits_per_word <= 8)
spi_imx->word_mask = mask << 24 | mask << 16
| mask << 8 | mask;
else if (spi_imx->bits_per_word <= 16)
spi_imx->word_mask = mask << 16 | mask;
else
spi_imx->word_mask = mask;
} else { } else {
if (spi_imx->bits_per_word <= 8) { if (spi_imx->bits_per_word <= 8) {
spi_imx->rx = spi_imx_buf_rx_u8; spi_imx->rx = spi_imx_buf_rx_u8;
...@@ -1134,6 +1171,7 @@ static int spi_imx_setupxfer(struct spi_device *spi, ...@@ -1134,6 +1171,7 @@ static int spi_imx_setupxfer(struct spi_device *spi,
spi_imx->rx = spi_imx_buf_rx_u32; spi_imx->rx = spi_imx_buf_rx_u32;
spi_imx->tx = spi_imx_buf_tx_u32; spi_imx->tx = spi_imx_buf_tx_u32;
} }
spi_imx->dynamic_burst = 0;
} }
if (spi_imx_can_dma(spi_imx->bitbang.master, spi, t)) if (spi_imx_can_dma(spi_imx->bitbang.master, spi, t))
...@@ -1317,6 +1355,7 @@ static int spi_imx_pio_transfer(struct spi_device *spi, ...@@ -1317,6 +1355,7 @@ static int spi_imx_pio_transfer(struct spi_device *spi,
spi_imx->rx_buf = transfer->rx_buf; spi_imx->rx_buf = transfer->rx_buf;
spi_imx->count = transfer->len; spi_imx->count = transfer->len;
spi_imx->txfifo = 0; spi_imx->txfifo = 0;
spi_imx->remainder = 0;
reinit_completion(&spi_imx->xfer_done); reinit_completion(&spi_imx->xfer_done);
...@@ -1354,6 +1393,7 @@ static int spi_imx_pio_transfer_slave(struct spi_device *spi, ...@@ -1354,6 +1393,7 @@ static int spi_imx_pio_transfer_slave(struct spi_device *spi,
spi_imx->rx_buf = transfer->rx_buf; spi_imx->rx_buf = transfer->rx_buf;
spi_imx->count = transfer->len; spi_imx->count = transfer->len;
spi_imx->txfifo = 0; spi_imx->txfifo = 0;
spi_imx->remainder = 0;
reinit_completion(&spi_imx->xfer_done); reinit_completion(&spi_imx->xfer_done);
spi_imx->slave_aborted = false; spi_imx->slave_aborted = false;
......
...@@ -188,9 +188,10 @@ static void lm70_chipselect(struct spi_device *spi, int value) ...@@ -188,9 +188,10 @@ static void lm70_chipselect(struct spi_device *spi, int value)
/* /*
* Our actual bitbanger routine. * Our actual bitbanger routine.
*/ */
static u32 lm70_txrx(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits) static u32 lm70_txrx(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits,
unsigned flags)
{ {
return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits); return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);
} }
static void spi_lm70llp_attach(struct parport *p) static void spi_lm70llp_attach(struct parport *p)
......
...@@ -310,6 +310,24 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) ...@@ -310,6 +310,24 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
} }
EXPORT_SYMBOL_GPL(spi_mem_exec_op); EXPORT_SYMBOL_GPL(spi_mem_exec_op);
/**
* spi_mem_get_name() - Return the SPI mem device name to be used by the
* upper layer if necessary
* @mem: the SPI memory
*
* This function allows SPI mem users to retrieve the SPI mem device name.
* It is useful if the upper layer needs to expose a custom name for
* compatibility reasons.
*
* Return: a string containing the name of the memory device to be used
* by the SPI mem user
*/
const char *spi_mem_get_name(struct spi_mem *mem)
{
return mem->name;
}
EXPORT_SYMBOL_GPL(spi_mem_get_name);
/** /**
* spi_mem_adjust_op_size() - Adjust the data size of a SPI mem operation to * spi_mem_adjust_op_size() - Adjust the data size of a SPI mem operation to
* match controller limitations * match controller limitations
...@@ -344,6 +362,7 @@ static inline struct spi_mem_driver *to_spi_mem_drv(struct device_driver *drv) ...@@ -344,6 +362,7 @@ static inline struct spi_mem_driver *to_spi_mem_drv(struct device_driver *drv)
static int spi_mem_probe(struct spi_device *spi) static int spi_mem_probe(struct spi_device *spi)
{ {
struct spi_mem_driver *memdrv = to_spi_mem_drv(spi->dev.driver); struct spi_mem_driver *memdrv = to_spi_mem_drv(spi->dev.driver);
struct spi_controller *ctlr = spi->controller;
struct spi_mem *mem; struct spi_mem *mem;
mem = devm_kzalloc(&spi->dev, sizeof(*mem), GFP_KERNEL); mem = devm_kzalloc(&spi->dev, sizeof(*mem), GFP_KERNEL);
...@@ -351,6 +370,15 @@ static int spi_mem_probe(struct spi_device *spi) ...@@ -351,6 +370,15 @@ static int spi_mem_probe(struct spi_device *spi)
return -ENOMEM; return -ENOMEM;
mem->spi = spi; mem->spi = spi;
if (ctlr->mem_ops && ctlr->mem_ops->get_name)
mem->name = ctlr->mem_ops->get_name(mem);
else
mem->name = dev_name(&spi->dev);
if (IS_ERR_OR_NULL(mem->name))
return PTR_ERR(mem->name);
spi_set_drvdata(spi, mem); spi_set_drvdata(spi, mem);
return memdrv->probe(mem); return memdrv->probe(mem);
......
...@@ -398,11 +398,9 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi, ...@@ -398,11 +398,9 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi,
{ {
struct omap2_mcspi *mcspi; struct omap2_mcspi *mcspi;
struct omap2_mcspi_dma *mcspi_dma; struct omap2_mcspi_dma *mcspi_dma;
unsigned int count;
mcspi = spi_master_get_devdata(spi->master); mcspi = spi_master_get_devdata(spi->master);
mcspi_dma = &mcspi->dma_channels[spi->chip_select]; mcspi_dma = &mcspi->dma_channels[spi->chip_select];
count = xfer->len;
if (mcspi_dma->dma_tx) { if (mcspi_dma->dma_tx) {
struct dma_async_tx_descriptor *tx; struct dma_async_tx_descriptor *tx;
...@@ -582,7 +580,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) ...@@ -582,7 +580,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
struct omap2_mcspi_cs *cs = spi->controller_state; struct omap2_mcspi_cs *cs = spi->controller_state;
struct omap2_mcspi_dma *mcspi_dma; struct omap2_mcspi_dma *mcspi_dma;
unsigned int count; unsigned int count;
u32 l;
u8 *rx; u8 *rx;
const u8 *tx; const u8 *tx;
struct dma_slave_config cfg; struct dma_slave_config cfg;
...@@ -595,8 +592,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) ...@@ -595,8 +592,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
mcspi = spi_master_get_devdata(spi->master); mcspi = spi_master_get_devdata(spi->master);
mcspi_dma = &mcspi->dma_channels[spi->chip_select]; mcspi_dma = &mcspi->dma_channels[spi->chip_select];
l = mcspi_cached_chconf0(spi);
if (cs->word_len <= 8) { if (cs->word_len <= 8) {
width = DMA_SLAVE_BUSWIDTH_1_BYTE; width = DMA_SLAVE_BUSWIDTH_1_BYTE;
...@@ -676,7 +671,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) ...@@ -676,7 +671,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
static unsigned static unsigned
omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
{ {
struct omap2_mcspi *mcspi;
struct omap2_mcspi_cs *cs = spi->controller_state; struct omap2_mcspi_cs *cs = spi->controller_state;
unsigned int count, c; unsigned int count, c;
u32 l; u32 l;
...@@ -686,7 +680,6 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) ...@@ -686,7 +680,6 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
void __iomem *chstat_reg; void __iomem *chstat_reg;
int word_len; int word_len;
mcspi = spi_master_get_devdata(spi->master);
count = xfer->len; count = xfer->len;
c = count; c = count;
word_len = cs->word_len; word_len = cs->word_len;
...@@ -883,13 +876,11 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, ...@@ -883,13 +876,11 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
{ {
struct omap2_mcspi_cs *cs = spi->controller_state; struct omap2_mcspi_cs *cs = spi->controller_state;
struct omap2_mcspi *mcspi; struct omap2_mcspi *mcspi;
struct spi_master *spi_cntrl;
u32 l = 0, clkd = 0, div, extclk = 0, clkg = 0; u32 l = 0, clkd = 0, div, extclk = 0, clkg = 0;
u8 word_len = spi->bits_per_word; u8 word_len = spi->bits_per_word;
u32 speed_hz = spi->max_speed_hz; u32 speed_hz = spi->max_speed_hz;
mcspi = spi_master_get_devdata(spi->master); mcspi = spi_master_get_devdata(spi->master);
spi_cntrl = mcspi->master;
if (t != NULL && t->bits_per_word) if (t != NULL && t->bits_per_word)
word_len = t->bits_per_word; word_len = t->bits_per_word;
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/sizes.h> #include <linux/sizes.h>
#include <linux/gpio.h> #include <linux/gpio.h>
...@@ -681,9 +682,9 @@ static int orion_spi_probe(struct platform_device *pdev) ...@@ -681,9 +682,9 @@ static int orion_spi_probe(struct platform_device *pdev)
goto out_rel_axi_clk; goto out_rel_axi_clk;
} }
/* Scan all SPI devices of this controller for direct mapped devices */
for_each_available_child_of_node(pdev->dev.of_node, np) { for_each_available_child_of_node(pdev->dev.of_node, np) {
u32 cs; u32 cs;
int cs_gpio;
/* Get chip-select number from the "reg" property */ /* Get chip-select number from the "reg" property */
status = of_property_read_u32(np, "reg", &cs); status = of_property_read_u32(np, "reg", &cs);
...@@ -694,6 +695,44 @@ static int orion_spi_probe(struct platform_device *pdev) ...@@ -694,6 +695,44 @@ static int orion_spi_probe(struct platform_device *pdev)
continue; continue;
} }
/*
* Initialize the CS GPIO:
* - properly request the actual GPIO signal
* - de-assert the logical signal so that all GPIO CS lines
* are inactive when probing for slaves
* - find an unused physical CS which will be driven for any
* slave which uses a CS GPIO
*/
cs_gpio = of_get_named_gpio(pdev->dev.of_node, "cs-gpios", cs);
if (cs_gpio > 0) {
char *gpio_name;
int cs_flags;
if (spi->unused_hw_gpio == -1) {
dev_info(&pdev->dev,
"Selected unused HW CS#%d for any GPIO CSes\n",
cs);
spi->unused_hw_gpio = cs;
}
gpio_name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
"%s-CS%d", dev_name(&pdev->dev), cs);
if (!gpio_name) {
status = -ENOMEM;
goto out_rel_axi_clk;
}
cs_flags = of_property_read_bool(np, "spi-cs-high") ?
GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH;
status = devm_gpio_request_one(&pdev->dev, cs_gpio,
cs_flags, gpio_name);
if (status) {
dev_err(&pdev->dev,
"Can't request GPIO for CS %d\n", cs);
goto out_rel_axi_clk;
}
}
/* /*
* Check if an address is configured for this SPI device. If * Check if an address is configured for this SPI device. If
* not, the MBus mapping via the 'ranges' property in the 'soc' * not, the MBus mapping via the 'ranges' property in the 'soc'
...@@ -740,44 +779,8 @@ static int orion_spi_probe(struct platform_device *pdev) ...@@ -740,44 +779,8 @@ static int orion_spi_probe(struct platform_device *pdev)
if (status < 0) if (status < 0)
goto out_rel_pm; goto out_rel_pm;
if (master->cs_gpios) {
int i;
for (i = 0; i < master->num_chipselect; ++i) {
char *gpio_name;
if (!gpio_is_valid(master->cs_gpios[i])) {
continue;
}
gpio_name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
"%s-CS%d", dev_name(&pdev->dev), i);
if (!gpio_name) {
status = -ENOMEM;
goto out_rel_master;
}
status = devm_gpio_request(&pdev->dev,
master->cs_gpios[i], gpio_name);
if (status) {
dev_err(&pdev->dev,
"Can't request GPIO for CS %d\n",
master->cs_gpios[i]);
goto out_rel_master;
}
if (spi->unused_hw_gpio == -1) {
dev_info(&pdev->dev,
"Selected unused HW CS#%d for any GPIO CSes\n",
i);
spi->unused_hw_gpio = i;
}
}
}
return status; return status;
out_rel_master:
spi_unregister_master(master);
out_rel_pm: out_rel_pm:
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
out_rel_axi_clk: out_rel_axi_clk:
......
...@@ -1391,6 +1391,10 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = { ...@@ -1391,6 +1391,10 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = {
{ PCI_VDEVICE(INTEL, 0x31c2), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x31c2), LPSS_BXT_SSP },
{ PCI_VDEVICE(INTEL, 0x31c4), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x31c4), LPSS_BXT_SSP },
{ PCI_VDEVICE(INTEL, 0x31c6), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x31c6), LPSS_BXT_SSP },
/* ICL-LP */
{ PCI_VDEVICE(INTEL, 0x34aa), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x34ab), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x34fb), LPSS_CNL_SSP },
/* APL */ /* APL */
{ PCI_VDEVICE(INTEL, 0x5ac2), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x5ac2), LPSS_BXT_SSP },
{ PCI_VDEVICE(INTEL, 0x5ac4), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x5ac4), LPSS_BXT_SSP },
......
...@@ -49,6 +49,7 @@ struct sh_msiof_spi_priv { ...@@ -49,6 +49,7 @@ struct sh_msiof_spi_priv {
struct platform_device *pdev; struct platform_device *pdev;
struct sh_msiof_spi_info *info; struct sh_msiof_spi_info *info;
struct completion done; struct completion done;
struct completion done_txdma;
unsigned int tx_fifo_size; unsigned int tx_fifo_size;
unsigned int rx_fifo_size; unsigned int rx_fifo_size;
unsigned int min_div_pow; unsigned int min_div_pow;
...@@ -649,19 +650,21 @@ static int sh_msiof_slave_abort(struct spi_master *master) ...@@ -649,19 +650,21 @@ static int sh_msiof_slave_abort(struct spi_master *master)
p->slave_aborted = true; p->slave_aborted = true;
complete(&p->done); complete(&p->done);
complete(&p->done_txdma);
return 0; return 0;
} }
static int sh_msiof_wait_for_completion(struct sh_msiof_spi_priv *p) static int sh_msiof_wait_for_completion(struct sh_msiof_spi_priv *p,
struct completion *x)
{ {
if (spi_controller_is_slave(p->master)) { if (spi_controller_is_slave(p->master)) {
if (wait_for_completion_interruptible(&p->done) || if (wait_for_completion_interruptible(x) ||
p->slave_aborted) { p->slave_aborted) {
dev_dbg(&p->pdev->dev, "interrupted\n"); dev_dbg(&p->pdev->dev, "interrupted\n");
return -EINTR; return -EINTR;
} }
} else { } else {
if (!wait_for_completion_timeout(&p->done, HZ)) { if (!wait_for_completion_timeout(x, HZ)) {
dev_err(&p->pdev->dev, "timeout\n"); dev_err(&p->pdev->dev, "timeout\n");
return -ETIMEDOUT; return -ETIMEDOUT;
} }
...@@ -711,7 +714,7 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, ...@@ -711,7 +714,7 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
} }
/* wait for tx fifo to be emptied / rx fifo to be filled */ /* wait for tx fifo to be emptied / rx fifo to be filled */
ret = sh_msiof_wait_for_completion(p); ret = sh_msiof_wait_for_completion(p, &p->done);
if (ret) if (ret)
goto stop_reset; goto stop_reset;
...@@ -740,10 +743,7 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, ...@@ -740,10 +743,7 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
static void sh_msiof_dma_complete(void *arg) static void sh_msiof_dma_complete(void *arg)
{ {
struct sh_msiof_spi_priv *p = arg; complete(arg);
sh_msiof_write(p, IER, 0);
complete(&p->done);
} }
static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
...@@ -764,7 +764,7 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, ...@@ -764,7 +764,7 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
return -EAGAIN; return -EAGAIN;
desc_rx->callback = sh_msiof_dma_complete; desc_rx->callback = sh_msiof_dma_complete;
desc_rx->callback_param = p; desc_rx->callback_param = &p->done;
cookie = dmaengine_submit(desc_rx); cookie = dmaengine_submit(desc_rx);
if (dma_submit_error(cookie)) if (dma_submit_error(cookie))
return cookie; return cookie;
...@@ -782,13 +782,8 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, ...@@ -782,13 +782,8 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
goto no_dma_tx; goto no_dma_tx;
} }
if (rx) { desc_tx->callback = sh_msiof_dma_complete;
/* No callback */ desc_tx->callback_param = &p->done_txdma;
desc_tx->callback = NULL;
} else {
desc_tx->callback = sh_msiof_dma_complete;
desc_tx->callback_param = p;
}
cookie = dmaengine_submit(desc_tx); cookie = dmaengine_submit(desc_tx);
if (dma_submit_error(cookie)) { if (dma_submit_error(cookie)) {
ret = cookie; ret = cookie;
...@@ -805,6 +800,8 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, ...@@ -805,6 +800,8 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
sh_msiof_write(p, IER, ier_bits); sh_msiof_write(p, IER, ier_bits);
reinit_completion(&p->done); reinit_completion(&p->done);
if (tx)
reinit_completion(&p->done_txdma);
p->slave_aborted = false; p->slave_aborted = false;
/* Now start DMA */ /* Now start DMA */
...@@ -819,17 +816,24 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, ...@@ -819,17 +816,24 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
goto stop_dma; goto stop_dma;
} }
/* wait for tx/rx DMA completion */ if (tx) {
ret = sh_msiof_wait_for_completion(p); /* wait for tx DMA completion */
if (ret) ret = sh_msiof_wait_for_completion(p, &p->done_txdma);
goto stop_reset; if (ret)
goto stop_reset;
}
if (!rx) { if (rx) {
reinit_completion(&p->done); /* wait for rx DMA completion */
sh_msiof_write(p, IER, IER_TEOFE); ret = sh_msiof_wait_for_completion(p, &p->done);
if (ret)
goto stop_reset;
sh_msiof_write(p, IER, 0);
} else {
/* wait for tx fifo to be emptied */ /* wait for tx fifo to be emptied */
ret = sh_msiof_wait_for_completion(p); sh_msiof_write(p, IER, IER_TEOFE);
ret = sh_msiof_wait_for_completion(p, &p->done);
if (ret) if (ret)
goto stop_reset; goto stop_reset;
} }
...@@ -1327,6 +1331,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) ...@@ -1327,6 +1331,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
p->min_div_pow = chipdata->min_div_pow; p->min_div_pow = chipdata->min_div_pow;
init_completion(&p->done); init_completion(&p->done);
init_completion(&p->done_txdma);
p->clk = devm_clk_get(&pdev->dev, NULL); p->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(p->clk)) { if (IS_ERR(p->clk)) {
......
...@@ -80,27 +80,31 @@ static inline u32 getmiso(struct spi_device *dev) ...@@ -80,27 +80,31 @@ static inline u32 getmiso(struct spi_device *dev)
#include "spi-bitbang-txrx.h" #include "spi-bitbang-txrx.h"
static u32 sh_sci_spi_txrx_mode0(struct spi_device *spi, static u32 sh_sci_spi_txrx_mode0(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits,
unsigned flags)
{ {
return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits); return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);
} }
static u32 sh_sci_spi_txrx_mode1(struct spi_device *spi, static u32 sh_sci_spi_txrx_mode1(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits,
unsigned flags)
{ {
return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits); return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits);
} }
static u32 sh_sci_spi_txrx_mode2(struct spi_device *spi, static u32 sh_sci_spi_txrx_mode2(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits,
unsigned flags)
{ {
return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits); return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits);
} }
static u32 sh_sci_spi_txrx_mode3(struct spi_device *spi, static u32 sh_sci_spi_txrx_mode3(struct spi_device *spi,
unsigned nsecs, u32 word, u8 bits) unsigned nsecs, u32 word, u8 bits,
unsigned flags)
{ {
return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits); return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits);
} }
static void sh_sci_spi_chipselect(struct spi_device *dev, int value) static void sh_sci_spi_chipselect(struct spi_device *dev, int value)
......
This diff is collapsed.
...@@ -54,7 +54,7 @@ static inline void xtfpga_spi_wait_busy(struct xtfpga_spi *xspi) ...@@ -54,7 +54,7 @@ static inline void xtfpga_spi_wait_busy(struct xtfpga_spi *xspi)
} }
static u32 xtfpga_spi_txrx_word(struct spi_device *spi, unsigned nsecs, static u32 xtfpga_spi_txrx_word(struct spi_device *spi, unsigned nsecs,
u32 v, u8 bits) u32 v, u8 bits, unsigned flags)
{ {
struct xtfpga_spi *xspi = spi_master_get_devdata(spi->master); struct xtfpga_spi *xspi = spi_master_get_devdata(spi->master);
......
This diff is collapsed.
...@@ -124,7 +124,8 @@ struct spi_mem_op { ...@@ -124,7 +124,8 @@ struct spi_mem_op {
/** /**
* struct spi_mem - describes a SPI memory device * struct spi_mem - describes a SPI memory device
* @spi: the underlying SPI device * @spi: the underlying SPI device
* @drvpriv: spi_mem_drviver private data * @drvpriv: spi_mem_driver private data
* @name: name of the SPI memory device
* *
* Extra information that describe the SPI memory device and may be needed by * Extra information that describe the SPI memory device and may be needed by
* the controller to properly handle this device should be placed here. * the controller to properly handle this device should be placed here.
...@@ -135,6 +136,7 @@ struct spi_mem_op { ...@@ -135,6 +136,7 @@ struct spi_mem_op {
struct spi_mem { struct spi_mem {
struct spi_device *spi; struct spi_device *spi;
void *drvpriv; void *drvpriv;
const char *name;
}; };
/** /**
...@@ -167,6 +169,13 @@ static inline void *spi_mem_get_drvdata(struct spi_mem *mem) ...@@ -167,6 +169,13 @@ static inline void *spi_mem_get_drvdata(struct spi_mem *mem)
* limitations) * limitations)
* @supports_op: check if an operation is supported by the controller * @supports_op: check if an operation is supported by the controller
* @exec_op: execute a SPI memory operation * @exec_op: execute a SPI memory operation
* @get_name: get a custom name for the SPI mem device from the controller.
* This might be needed if the controller driver has been ported
* to use the SPI mem layer and a custom name is used to keep
* mtdparts compatible.
* Note that if the implementation of this function allocates memory
* dynamically, then it should do so with devm_xxx(), as we don't
* have a ->free_name() function.
* *
* This interface should be implemented by SPI controllers providing an * This interface should be implemented by SPI controllers providing an
* high-level interface to execute SPI memory operation, which is usually the * high-level interface to execute SPI memory operation, which is usually the
...@@ -178,6 +187,7 @@ struct spi_controller_mem_ops { ...@@ -178,6 +187,7 @@ struct spi_controller_mem_ops {
const struct spi_mem_op *op); const struct spi_mem_op *op);
int (*exec_op)(struct spi_mem *mem, int (*exec_op)(struct spi_mem *mem,
const struct spi_mem_op *op); const struct spi_mem_op *op);
const char *(*get_name)(struct spi_mem *mem);
}; };
/** /**
...@@ -236,6 +246,8 @@ bool spi_mem_supports_op(struct spi_mem *mem, ...@@ -236,6 +246,8 @@ bool spi_mem_supports_op(struct spi_mem *mem,
int spi_mem_exec_op(struct spi_mem *mem, int spi_mem_exec_op(struct spi_mem *mem,
const struct spi_mem_op *op); const struct spi_mem_op *op);
const char *spi_mem_get_name(struct spi_mem *mem);
int spi_mem_driver_register_with_owner(struct spi_mem_driver *drv, int spi_mem_driver_register_with_owner(struct spi_mem_driver *drv,
struct module *owner); struct module *owner);
......
...@@ -8,7 +8,7 @@ struct spi_bitbang { ...@@ -8,7 +8,7 @@ struct spi_bitbang {
struct mutex lock; struct mutex lock;
u8 busy; u8 busy;
u8 use_dma; u8 use_dma;
u8 flags; /* extra spi->mode support */ u16 flags; /* extra spi->mode support */
struct spi_master *master; struct spi_master *master;
...@@ -30,7 +30,8 @@ struct spi_bitbang { ...@@ -30,7 +30,8 @@ struct spi_bitbang {
/* txrx_word[SPI_MODE_*]() just looks like a shift register */ /* txrx_word[SPI_MODE_*]() just looks like a shift register */
u32 (*txrx_word[4])(struct spi_device *spi, u32 (*txrx_word[4])(struct spi_device *spi,
unsigned nsecs, unsigned nsecs,
u32 word, u8 bits); u32 word, u8 bits, unsigned flags);
int (*set_line_direction)(struct spi_device *spi, bool output);
}; };
/* you can call these default bitbang->master methods from your custom /* you can call these default bitbang->master methods from your custom
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment