Skip to content

Commit

Permalink
Merge tag 'spi-v4.19' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/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
  ...
  • Loading branch information
Linus Torvalds committed Aug 14, 2018
2 parents 792adb9 + c1acb21 commit 010b0e7
Show file tree
Hide file tree
Showing 31 changed files with 1,253 additions and 674 deletions.
6 changes: 4 additions & 2 deletions Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
Synopsys DesignWare AMBA 2.0 Synchronous Serial Interface.

Required properties:
- compatible : "snps,dw-apb-ssi"
- reg : The register base for the controller.
- compatible : "snps,dw-apb-ssi" or "mscc,<soc>-spi", where soc is "ocelot" or
"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.
- #address-cells : <1>, as required by generic SPI binding.
- #size-cells : <0>, also as required by generic SPI binding.
Expand Down
1 change: 1 addition & 0 deletions Documentation/devicetree/bindings/spi/spi-rockchip.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Required Properties:

- compatible: should be one of the following.
"rockchip,rv1108-spi" for rv1108 SoCs.
"rockchip,px30-spi", "rockchip,rk3066-spi" for px30 SoCs.
"rockchip,rk3036-spi" for rk3036 SoCS.
"rockchip,rk3066-spi" for rk3066 SoCs.
"rockchip,rk3188-spi" for rk3188 SoCs.
Expand Down
22 changes: 22 additions & 0 deletions Documentation/devicetree/bindings/spi/spi-uniphier.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
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>;
};
3 changes: 3 additions & 0 deletions drivers/mtd/devices/m25p80.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@ static int m25p_probe(struct spi_mem *spimem)
if (data && 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
* names in flash_platform_data: "name" and "type". Quite often name is
* set to "m25p80" and then "type" provides a real chip name.
Expand Down
13 changes: 13 additions & 0 deletions drivers/spi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,19 @@ config SPI_TXX9
help
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
tristate "Analog Devices AD-FMCOMMS1-EBZ SPI-I2C-bridge driver"
depends on I2C
Expand Down
1 change: 1 addition & 0 deletions drivers/spi/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ spi-thunderx-objs := spi-cavium.o spi-cavium-thunderx.o
obj-$(CONFIG_SPI_THUNDERX) += spi-thunderx.o
obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi-topcliff-pch.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_XILINX) += spi-xilinx.o
obj-$(CONFIG_SPI_XLP) += spi-xlp.o
Expand Down
2 changes: 1 addition & 1 deletion drivers/spi/spi-ath79.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
u32 word, u8 bits)
u32 word, u8 bits, unsigned flags)
{
struct ath79_spi *sp = ath79_spidev_to_sp(spi);
u32 ioc = sp->ioc_base;
Expand Down
50 changes: 37 additions & 13 deletions drivers/spi/spi-bitbang.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,22 +49,26 @@
struct spi_bitbang_cs {
unsigned nsecs; /* (clock cycle time)/2 */
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 *,
u32 (*txrx_word)(
struct spi_device *spi,
unsigned nsecs,
u32 word, u8 bits),
unsigned, struct spi_transfer *);
u32 word, u8 bits,
unsigned flags),
unsigned, struct spi_transfer *,
unsigned);
};

static unsigned bitbang_txrx_8(
struct spi_device *spi,
u32 (*txrx_word)(struct spi_device *spi,
unsigned nsecs,
u32 word, u8 bits),
u32 word, u8 bits,
unsigned flags),
unsigned ns,
struct spi_transfer *t
struct spi_transfer *t,
unsigned flags
) {
unsigned bits = t->bits_per_word;
unsigned count = t->len;
Expand All @@ -76,7 +80,7 @@ static unsigned bitbang_txrx_8(

if (tx)
word = *tx++;
word = txrx_word(spi, ns, word, bits);
word = txrx_word(spi, ns, word, bits, flags);
if (rx)
*rx++ = word;
count -= 1;
Expand All @@ -88,9 +92,11 @@ static unsigned bitbang_txrx_16(
struct spi_device *spi,
u32 (*txrx_word)(struct spi_device *spi,
unsigned nsecs,
u32 word, u8 bits),
u32 word, u8 bits,
unsigned flags),
unsigned ns,
struct spi_transfer *t
struct spi_transfer *t,
unsigned flags
) {
unsigned bits = t->bits_per_word;
unsigned count = t->len;
Expand All @@ -102,7 +108,7 @@ static unsigned bitbang_txrx_16(

if (tx)
word = *tx++;
word = txrx_word(spi, ns, word, bits);
word = txrx_word(spi, ns, word, bits, flags);
if (rx)
*rx++ = word;
count -= 2;
Expand All @@ -114,9 +120,11 @@ static unsigned bitbang_txrx_32(
struct spi_device *spi,
u32 (*txrx_word)(struct spi_device *spi,
unsigned nsecs,
u32 word, u8 bits),
u32 word, u8 bits,
unsigned flags),
unsigned ns,
struct spi_transfer *t
struct spi_transfer *t,
unsigned flags
) {
unsigned bits = t->bits_per_word;
unsigned count = t->len;
Expand All @@ -128,7 +136,7 @@ static unsigned bitbang_txrx_32(

if (tx)
word = *tx++;
word = txrx_word(spi, ns, word, bits);
word = txrx_word(spi, ns, word, bits, flags);
if (rx)
*rx++ = word;
count -= 4;
Expand Down Expand Up @@ -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;
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);
}

/*----------------------------------------------------------------------*/
Expand Down
4 changes: 2 additions & 2 deletions drivers/spi/spi-butterfly.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,9 @@ static void butterfly_chipselect(struct spi_device *spi, int value)

static u32
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);
}

/*----------------------------------------------------------------------*/
Expand Down
4 changes: 2 additions & 2 deletions drivers/spi/spi-cadence.c
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi)
*/
if (cdns_spi_read(xspi, CDNS_SPI_ISR) &
CDNS_SPI_IXR_TXFULL)
usleep_range(10, 20);
udelay(10);

if (xspi->txbuf)
cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++);
Expand Down Expand Up @@ -739,7 +739,7 @@ static int __maybe_unused cnds_runtime_resume(struct device *dev)
ret = clk_prepare_enable(xspi->ref_clk);
if (ret) {
dev_err(dev, "Cannot enable device clock.\n");
clk_disable(xspi->pclk);
clk_disable_unprepare(xspi->pclk);
return ret;
}
return 0;
Expand Down
2 changes: 1 addition & 1 deletion drivers/spi/spi-davinci.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
pdata = &dspi->pdata;

/* program delay transfers if tx_delay is non zero */
if (spicfg->wdelay)
if (spicfg && spicfg->wdelay)
spidat1 |= SPIDAT1_WDEL;

/*
Expand Down
90 changes: 90 additions & 0 deletions drivers/spi/spi-dw-mmio.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@
#include <linux/slab.h>
#include <linux/spi/spi.h>
#include <linux/scatterlist.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/property.h>
#include <linux/regmap.h>

#include "spi-dw.h"

Expand All @@ -28,10 +30,90 @@
struct dw_spi_mmio {
struct dw_spi dws;
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)
{
int (*init_func)(struct platform_device *pdev,
struct dw_spi_mmio *dwsmmio);
struct dw_spi_mmio *dwsmmio;
struct dw_spi *dws;
struct resource *mem;
Expand Down Expand Up @@ -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);
if (ret)
goto out;
Expand All @@ -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[] = {
{ .compatible = "snps,dw-apb-ssi", },
{ .compatible = "mscc,ocelot-spi", .data = dw_spi_mscc_init},
{ /* end of table */}
};
MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
Expand Down
Loading

0 comments on commit 010b0e7

Please sign in to comment.