Commit b88f5577 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull spi updates from Mark Brown:
 "A fairly quiet release for the SPI subsystem:

   - Move to using IDR for allocating bus numbers

   - Modernisation of the ep93xx driver, removing a lot of open coding
     and using the framework more

   - The tools have been moved to use the standard tools build system
     and an install target added (there will be a fairly trivial
     conflict with tip resulting from the changes in the main tools
     Makefile)

   - A refactoring of the Qualcomm QUP driver which enables new variants
     to be supported

   - Explicit support for the Freescale i.MX53 and i.MX6 SPI, Renesas
     R-Car H3 and Rockchip RV1108 controllers"

* tag 'spi-v4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (71 commits)
  spi: spi-falcon: drop check of boot select
  spi: imx: fix use of native chip-selects with devicetree
  spi: pl022: constify amba_id
  spi: imx: fix little-endian build
  spi: omap: Allocate bus number from spi framework
  spi: Kernel coding style fixes
  spi: imx: dynamic burst length adjust for PIO mode
  spi: Pick spi bus number from Linux idr or spi alias
  spi: rockchip: configure CTRLR1 according to size and data frame
  spi: altera: Consolidate TX/RX data register access
  spi: altera: Switch to SPI core transfer queue management
  spi: rockchip: add compatible string for rv1108 spi
  spi: qup: fix 64-bit build warning
  spi: qup: hide warning for uninitialized variable
  spi: spi-ep93xx: use the default master transfer queueing mechanism
  spi: spi-ep93xx: remove private data 'current_msg'
  spi: spi-ep93xx: pass the spi_master pointer around
  spi: spi-ep93xx: absorb the interrupt enable/disable helpers
  spi: spi-ep93xx: add spi master prepare_transfer_hardware()
  spi: spi-ep93xx: use 32-bit read/write for all registers
  ...
parents 16a832a2 ecb478bf
...@@ -9,6 +9,7 @@ Required properties: ...@@ -9,6 +9,7 @@ Required properties:
- "fsl,imx31-cspi" for SPI compatible with the one integrated on i.MX31 - "fsl,imx31-cspi" for SPI compatible with the one integrated on i.MX31
- "fsl,imx35-cspi" for SPI compatible with the one integrated on i.MX35 - "fsl,imx35-cspi" for SPI compatible with the one integrated on i.MX35
- "fsl,imx51-ecspi" for SPI compatible with the one integrated on i.MX51 - "fsl,imx51-ecspi" for SPI compatible with the one integrated on i.MX51
- "fsl,imx53-ecspi" for SPI compatible with the one integrated on i.MX53 and later Soc
- reg : Offset and length of the register set for the device - reg : Offset and length of the register set for the device
- interrupts : Should contain CSPI/eCSPI interrupt - interrupts : Should contain CSPI/eCSPI interrupt
- cs-gpios : Specifies the gpio pins to be used for chipselects. - cs-gpios : Specifies the gpio pins to be used for chipselects.
......
...@@ -6,6 +6,7 @@ Required properties: ...@@ -6,6 +6,7 @@ Required properties:
"renesas,msiof-r8a7792" (R-Car V2H) "renesas,msiof-r8a7792" (R-Car V2H)
"renesas,msiof-r8a7793" (R-Car M2-N) "renesas,msiof-r8a7793" (R-Car M2-N)
"renesas,msiof-r8a7794" (R-Car E2) "renesas,msiof-r8a7794" (R-Car E2)
"renesas,msiof-r8a7795" (R-Car H3)
"renesas,msiof-r8a7796" (R-Car M3-W) "renesas,msiof-r8a7796" (R-Car M3-W)
"renesas,msiof-sh73a0" (SH-Mobile AG5) "renesas,msiof-sh73a0" (SH-Mobile AG5)
"renesas,sh-mobile-msiof" (generic SH-Mobile compatibile device) "renesas,sh-mobile-msiof" (generic SH-Mobile compatibile device)
......
...@@ -6,6 +6,7 @@ and display controllers using the SPI communication interface. ...@@ -6,6 +6,7 @@ and display controllers using the SPI communication interface.
Required Properties: Required Properties:
- compatible: should be one of the following. - compatible: should be one of the following.
"rockchip,rv1108-spi" for rv1108 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.
......
...@@ -55,7 +55,6 @@ comment "SPI Master Controller Drivers" ...@@ -55,7 +55,6 @@ comment "SPI Master Controller Drivers"
config SPI_ALTERA config SPI_ALTERA
tristate "Altera SPI Controller" tristate "Altera SPI Controller"
select SPI_BITBANG
help help
This is the driver for the Altera SPI Controller. This is the driver for the Altera SPI Controller.
...@@ -518,8 +517,8 @@ config SPI_PPC4xx ...@@ -518,8 +517,8 @@ config SPI_PPC4xx
config SPI_PXA2XX config SPI_PXA2XX
tristate "PXA2xx SSP SPI master" tristate "PXA2xx SSP SPI master"
depends on (ARCH_PXA || PCI || ACPI) depends on (ARCH_PXA || ARCH_MMP || PCI || ACPI)
select PXA_SSP if ARCH_PXA select PXA_SSP if ARCH_PXA || ARCH_MMP
help help
This enables using a PXA2xx or Sodaville SSP port as a SPI master This enables using a PXA2xx or Sodaville SSP port as a SPI master
controller. The driver can be configured to use any SSP port and controller. The driver can be configured to use any SSP port and
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h> #include <linux/of.h>
...@@ -45,10 +44,6 @@ ...@@ -45,10 +44,6 @@
#define ALTERA_SPI_CONTROL_SSO_MSK 0x400 #define ALTERA_SPI_CONTROL_SSO_MSK 0x400
struct altera_spi { struct altera_spi {
/* bitbang has to be first */
struct spi_bitbang bitbang;
struct completion done;
void __iomem *base; void __iomem *base;
int irq; int irq;
int len; int len;
...@@ -66,59 +61,64 @@ static inline struct altera_spi *altera_spi_to_hw(struct spi_device *sdev) ...@@ -66,59 +61,64 @@ static inline struct altera_spi *altera_spi_to_hw(struct spi_device *sdev)
return spi_master_get_devdata(sdev->master); return spi_master_get_devdata(sdev->master);
} }
static void altera_spi_chipsel(struct spi_device *spi, int value) static void altera_spi_set_cs(struct spi_device *spi, bool is_high)
{ {
struct altera_spi *hw = altera_spi_to_hw(spi); struct altera_spi *hw = altera_spi_to_hw(spi);
if (spi->mode & SPI_CS_HIGH) { if (is_high) {
switch (value) { hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
case BITBANG_CS_INACTIVE: writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
writel(1 << spi->chip_select, writel(0, hw->base + ALTERA_SPI_SLAVE_SEL);
hw->base + ALTERA_SPI_SLAVE_SEL);
hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
break;
case BITBANG_CS_ACTIVE:
hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
writel(0, hw->base + ALTERA_SPI_SLAVE_SEL);
break;
}
} else { } else {
switch (value) { writel(BIT(spi->chip_select), hw->base + ALTERA_SPI_SLAVE_SEL);
case BITBANG_CS_INACTIVE: hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK; writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL); }
break; }
static void altera_spi_tx_word(struct altera_spi *hw)
{
unsigned int txd = 0;
case BITBANG_CS_ACTIVE: if (hw->tx) {
writel(1 << spi->chip_select, switch (hw->bytes_per_word) {
hw->base + ALTERA_SPI_SLAVE_SEL); case 1:
hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK; txd = hw->tx[hw->count];
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL); break;
case 2:
txd = (hw->tx[hw->count * 2]
| (hw->tx[hw->count * 2 + 1] << 8));
break; break;
} }
} }
writel(txd, hw->base + ALTERA_SPI_TXDATA);
} }
static inline unsigned int hw_txbyte(struct altera_spi *hw, int count) static void altera_spi_rx_word(struct altera_spi *hw)
{ {
if (hw->tx) { unsigned int rxd;
rxd = readl(hw->base + ALTERA_SPI_RXDATA);
if (hw->rx) {
switch (hw->bytes_per_word) { switch (hw->bytes_per_word) {
case 1: case 1:
return hw->tx[count]; hw->rx[hw->count] = rxd;
break;
case 2: case 2:
return (hw->tx[count * 2] hw->rx[hw->count * 2] = rxd;
| (hw->tx[count * 2 + 1] << 8)); hw->rx[hw->count * 2 + 1] = rxd >> 8;
break;
} }
} }
return 0;
hw->count++;
} }
static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t) static int altera_spi_txrx(struct spi_master *master,
struct spi_device *spi, struct spi_transfer *t)
{ {
struct altera_spi *hw = altera_spi_to_hw(spi); struct altera_spi *hw = spi_master_get_devdata(master);
hw->tx = t->tx_buf; hw->tx = t->tx_buf;
hw->rx = t->rx_buf; hw->rx = t->rx_buf;
...@@ -132,67 +132,39 @@ static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t) ...@@ -132,67 +132,39 @@ static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL); writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
/* send the first byte */ /* send the first byte */
writel(hw_txbyte(hw, 0), hw->base + ALTERA_SPI_TXDATA); altera_spi_tx_word(hw);
wait_for_completion(&hw->done);
/* disable receive interrupt */
hw->imr &= ~ALTERA_SPI_CONTROL_IRRDY_MSK;
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
} else { } else {
while (hw->count < hw->len) { while (hw->count < hw->len) {
unsigned int rxd; altera_spi_tx_word(hw);
writel(hw_txbyte(hw, hw->count),
hw->base + ALTERA_SPI_TXDATA);
while (!(readl(hw->base + ALTERA_SPI_STATUS) & while (!(readl(hw->base + ALTERA_SPI_STATUS) &
ALTERA_SPI_STATUS_RRDY_MSK)) ALTERA_SPI_STATUS_RRDY_MSK))
cpu_relax(); cpu_relax();
rxd = readl(hw->base + ALTERA_SPI_RXDATA); altera_spi_rx_word(hw);
if (hw->rx) {
switch (hw->bytes_per_word) {
case 1:
hw->rx[hw->count] = rxd;
break;
case 2:
hw->rx[hw->count * 2] = rxd;
hw->rx[hw->count * 2 + 1] = rxd >> 8;
break;
}
}
hw->count++;
} }
spi_finalize_current_transfer(master);
} }
return hw->count * hw->bytes_per_word; return t->len;
} }
static irqreturn_t altera_spi_irq(int irq, void *dev) static irqreturn_t altera_spi_irq(int irq, void *dev)
{ {
struct altera_spi *hw = dev; struct spi_master *master = dev;
unsigned int rxd; struct altera_spi *hw = spi_master_get_devdata(master);
rxd = readl(hw->base + ALTERA_SPI_RXDATA); altera_spi_rx_word(hw);
if (hw->rx) {
switch (hw->bytes_per_word) {
case 1:
hw->rx[hw->count] = rxd;
break;
case 2:
hw->rx[hw->count * 2] = rxd;
hw->rx[hw->count * 2 + 1] = rxd >> 8;
break;
}
}
hw->count++; if (hw->count < hw->len) {
altera_spi_tx_word(hw);
} else {
/* disable receive interrupt */
hw->imr &= ~ALTERA_SPI_CONTROL_IRRDY_MSK;
writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
if (hw->count < hw->len) spi_finalize_current_transfer(master);
writel(hw_txbyte(hw, hw->count), hw->base + ALTERA_SPI_TXDATA); }
else
complete(&hw->done);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -214,14 +186,10 @@ static int altera_spi_probe(struct platform_device *pdev) ...@@ -214,14 +186,10 @@ static int altera_spi_probe(struct platform_device *pdev)
master->mode_bits = SPI_CS_HIGH; master->mode_bits = SPI_CS_HIGH;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16); master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16);
master->dev.of_node = pdev->dev.of_node; master->dev.of_node = pdev->dev.of_node;
master->transfer_one = altera_spi_txrx;
master->set_cs = altera_spi_set_cs;
hw = spi_master_get_devdata(master); hw = spi_master_get_devdata(master);
platform_set_drvdata(pdev, hw);
/* setup the state for the bitbang driver */
hw->bitbang.master = master;
hw->bitbang.chipselect = altera_spi_chipsel;
hw->bitbang.txrx_bufs = altera_spi_txrx;
/* find and map our resources */ /* find and map our resources */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
...@@ -239,15 +207,13 @@ static int altera_spi_probe(struct platform_device *pdev) ...@@ -239,15 +207,13 @@ static int altera_spi_probe(struct platform_device *pdev)
/* irq is optional */ /* irq is optional */
hw->irq = platform_get_irq(pdev, 0); hw->irq = platform_get_irq(pdev, 0);
if (hw->irq >= 0) { if (hw->irq >= 0) {
init_completion(&hw->done);
err = devm_request_irq(&pdev->dev, hw->irq, altera_spi_irq, 0, err = devm_request_irq(&pdev->dev, hw->irq, altera_spi_irq, 0,
pdev->name, hw); pdev->name, master);
if (err) if (err)
goto exit; goto exit;
} }
/* register our spi controller */ err = devm_spi_register_master(&pdev->dev, master);
err = spi_bitbang_start(&hw->bitbang);
if (err) if (err)
goto exit; goto exit;
dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq); dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq);
...@@ -258,16 +224,6 @@ static int altera_spi_probe(struct platform_device *pdev) ...@@ -258,16 +224,6 @@ static int altera_spi_probe(struct platform_device *pdev)
return err; return err;
} }
static int altera_spi_remove(struct platform_device *dev)
{
struct altera_spi *hw = platform_get_drvdata(dev);
struct spi_master *master = hw->bitbang.master;
spi_bitbang_stop(&hw->bitbang);
spi_master_put(master);
return 0;
}
#ifdef CONFIG_OF #ifdef CONFIG_OF
static const struct of_device_id altera_spi_match[] = { static const struct of_device_id altera_spi_match[] = {
{ .compatible = "ALTR,spi-1.0", }, { .compatible = "ALTR,spi-1.0", },
...@@ -279,7 +235,6 @@ MODULE_DEVICE_TABLE(of, altera_spi_match); ...@@ -279,7 +235,6 @@ MODULE_DEVICE_TABLE(of, altera_spi_match);
static struct platform_driver altera_spi_driver = { static struct platform_driver altera_spi_driver = {
.probe = altera_spi_probe, .probe = altera_spi_probe,
.remove = altera_spi_remove,
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.pm = NULL, .pm = NULL,
......
...@@ -39,15 +39,15 @@ struct ath79_spi { ...@@ -39,15 +39,15 @@ struct ath79_spi {
u32 reg_ctrl; u32 reg_ctrl;
void __iomem *base; void __iomem *base;
struct clk *clk; struct clk *clk;
unsigned rrw_delay; unsigned int rrw_delay;
}; };
static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg) static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned int reg)
{ {
return ioread32(sp->base + reg); return ioread32(sp->base + reg);
} }
static inline void ath79_spi_wr(struct ath79_spi *sp, unsigned reg, u32 val) static inline void ath79_spi_wr(struct ath79_spi *sp, unsigned int reg, u32 val)
{ {
iowrite32(val, sp->base + reg); iowrite32(val, sp->base + reg);
} }
...@@ -57,7 +57,7 @@ static inline struct ath79_spi *ath79_spidev_to_sp(struct spi_device *spi) ...@@ -57,7 +57,7 @@ static inline struct ath79_spi *ath79_spidev_to_sp(struct spi_device *spi)
return spi_master_get_devdata(spi->master); return spi_master_get_devdata(spi->master);
} }
static inline void ath79_spi_delay(struct ath79_spi *sp, unsigned nsecs) static inline void ath79_spi_delay(struct ath79_spi *sp, unsigned int nsecs)
{ {
if (nsecs > sp->rrw_delay) if (nsecs > sp->rrw_delay)
ndelay(nsecs - sp->rrw_delay); ndelay(nsecs - sp->rrw_delay);
...@@ -148,9 +148,8 @@ static int ath79_spi_setup_cs(struct spi_device *spi) ...@@ -148,9 +148,8 @@ static int ath79_spi_setup_cs(struct spi_device *spi)
static void ath79_spi_cleanup_cs(struct spi_device *spi) static void ath79_spi_cleanup_cs(struct spi_device *spi)
{ {
if (gpio_is_valid(spi->cs_gpio)) { if (gpio_is_valid(spi->cs_gpio))
gpio_free(spi->cs_gpio); gpio_free(spi->cs_gpio);
}
} }
static int ath79_spi_setup(struct spi_device *spi) static int ath79_spi_setup(struct spi_device *spi)
...@@ -176,7 +175,7 @@ static void ath79_spi_cleanup(struct spi_device *spi) ...@@ -176,7 +175,7 @@ static void ath79_spi_cleanup(struct spi_device *spi)
spi_bitbang_cleanup(spi); spi_bitbang_cleanup(spi);
} }
static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned nsecs, static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned int nsecs,
u32 word, u8 bits) u32 word, u8 bits)
{ {
struct ath79_spi *sp = ath79_spidev_to_sp(spi); struct ath79_spi *sp = ath79_spidev_to_sp(spi);
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mtd/spi-nor.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -349,76 +348,60 @@ static void bcm_qspi_bspi_set_xfer_params(struct bcm_qspi *qspi, u8 cmd_byte, ...@@ -349,76 +348,60 @@ static void bcm_qspi_bspi_set_xfer_params(struct bcm_qspi *qspi, u8 cmd_byte,
bcm_qspi_write(qspi, BSPI, BSPI_FLEX_MODE_ENABLE, flex_mode); bcm_qspi_write(qspi, BSPI, BSPI_FLEX_MODE_ENABLE, flex_mode);
} }
static int bcm_qspi_bspi_set_flex_mode(struct bcm_qspi *qspi, int width, static int bcm_qspi_bspi_set_flex_mode(struct bcm_qspi *qspi,
int addrlen, int hp) struct spi_flash_read_message *msg,
int hp)
{ {
int bpc = 0, bpp = 0; int bpc = 0, bpp = 0;
u8 command = SPINOR_OP_READ_FAST; u8 command = msg->read_opcode;
int flex_mode = 1, rv = 0; int width = msg->data_nbits ? msg->data_nbits : SPI_NBITS_SINGLE;
bool spans_4byte = false; int addrlen = msg->addr_width;
int addr_nbits = msg->addr_nbits ? msg->addr_nbits : SPI_NBITS_SINGLE;
int flex_mode = 1;
dev_dbg(&qspi->pdev->dev, "set flex mode w %x addrlen %x hp %d\n", dev_dbg(&qspi->pdev->dev, "set flex mode w %x addrlen %x hp %d\n",
width, addrlen, hp); width, addrlen, hp);
if (addrlen == BSPI_ADDRLEN_4BYTES) { if (addrlen == BSPI_ADDRLEN_4BYTES)
bpp = BSPI_BPP_ADDR_SELECT_MASK; bpp = BSPI_BPP_ADDR_SELECT_MASK;
spans_4byte = true;
}
bpp |= 8; bpp |= msg->dummy_bytes * (8/addr_nbits);
switch (width) { switch (width) {
case SPI_NBITS_SINGLE: case SPI_NBITS_SINGLE:
if (addrlen == BSPI_ADDRLEN_3BYTES) if (addrlen == BSPI_ADDRLEN_3BYTES)
/* default mode, does not need flex_cmd */ /* default mode, does not need flex_cmd */
flex_mode = 0; flex_mode = 0;
else
command = SPINOR_OP_READ_FAST_4B;
break; break;
case SPI_NBITS_DUAL: case SPI_NBITS_DUAL:
bpc = 0x00000001; bpc = 0x00000001;
if (hp) { if (hp) {
bpc |= 0x00010100; /* address and mode are 2-bit */ bpc |= 0x00010100; /* address and mode are 2-bit */
bpp = BSPI_BPP_MODE_SELECT_MASK; bpp = BSPI_BPP_MODE_SELECT_MASK;
command = OPCODE_DIOR;
if (spans_4byte)
command = OPCODE_DIOR_4B;
} else {
command = SPINOR_OP_READ_1_1_2;
if (spans_4byte)
command = SPINOR_OP_READ_1_1_2_4B;
} }
break; break;
case SPI_NBITS_QUAD: case SPI_NBITS_QUAD:
bpc = 0x00000002; bpc = 0x00000002;
if (hp) { if (hp) {
bpc |= 0x00020200; /* address and mode are 4-bit */ bpc |= 0x00020200; /* address and mode are 4-bit */
bpp = 4; /* dummy cycles */ bpp |= BSPI_BPP_MODE_SELECT_MASK;
bpp |= BSPI_BPP_ADDR_SELECT_MASK;
command = OPCODE_QIOR;
if (spans_4byte)
command = OPCODE_QIOR_4B;
} else {
command = SPINOR_OP_READ_1_1_4;
if (spans_4byte)
command = SPINOR_OP_READ_1_1_4_4B;
} }
break; break;
default: default:
rv = -EINVAL; return -EINVAL;
break;
} }
if (rv == 0) bcm_qspi_bspi_set_xfer_params(qspi, command, bpp, bpc, flex_mode);
bcm_qspi_bspi_set_xfer_params(qspi, command, bpp, bpc,
flex_mode);
return rv; return 0;
} }
static int bcm_qspi_bspi_set_override(struct bcm_qspi *qspi, int width, static int bcm_qspi_bspi_set_override(struct bcm_qspi *qspi,
int addrlen, int hp) struct spi_flash_read_message *msg,
int hp)
{ {
int width = msg->data_nbits ? msg->data_nbits : SPI_NBITS_SINGLE;
int addrlen = msg->addr_width;
u32 data = bcm_qspi_read(qspi, BSPI, BSPI_STRAP_OVERRIDE_CTRL); u32 data = bcm_qspi_read(qspi, BSPI, BSPI_STRAP_OVERRIDE_CTRL);
dev_dbg(&qspi->pdev->dev, "set override mode w %x addrlen %x hp %d\n", dev_dbg(&qspi->pdev->dev, "set override mode w %x addrlen %x hp %d\n",
...@@ -430,7 +413,6 @@ static int bcm_qspi_bspi_set_override(struct bcm_qspi *qspi, int width, ...@@ -430,7 +413,6 @@ static int bcm_qspi_bspi_set_override(struct bcm_qspi *qspi, int width,
data &= ~(BSPI_STRAP_OVERRIDE_CTRL_DATA_QUAD | data &= ~(BSPI_STRAP_OVERRIDE_CTRL_DATA_QUAD |
BSPI_STRAP_OVERRIDE_CTRL_DATA_DUAL); BSPI_STRAP_OVERRIDE_CTRL_DATA_DUAL);
break; break;
case SPI_NBITS_QUAD: case SPI_NBITS_QUAD:
/* clear dual mode and set quad mode */ /* clear dual mode and set quad mode */
data &= ~BSPI_STRAP_OVERRIDE_CTRL_DATA_DUAL; data &= ~BSPI_STRAP_OVERRIDE_CTRL_DATA_DUAL;
...@@ -455,15 +437,17 @@ static int bcm_qspi_bspi_set_override(struct bcm_qspi *qspi, int width, ...@@ -455,15 +437,17 @@ static int bcm_qspi_bspi_set_override(struct bcm_qspi *qspi, int width,
/* set the override mode */ /* set the override mode */
data |= BSPI_STRAP_OVERRIDE_CTRL_OVERRIDE; data |= BSPI_STRAP_OVERRIDE_CTRL_OVERRIDE;
bcm_qspi_write(qspi, BSPI, BSPI_STRAP_OVERRIDE_CTRL, data); bcm_qspi_write(qspi, BSPI, BSPI_STRAP_OVERRIDE_CTRL, data);
bcm_qspi_bspi_set_xfer_params(qspi, SPINOR_OP_READ_FAST, 0, 0, 0); bcm_qspi_bspi_set_xfer_params(qspi, msg->read_opcode, 0, 0, 0);
return 0; return 0;
} }
static int bcm_qspi_bspi_set_mode(struct bcm_qspi *qspi, static int bcm_qspi_bspi_set_mode(struct bcm_qspi *qspi,
int width, int addrlen, int hp) struct spi_flash_read_message *msg, int hp)
{ {
int error = 0; int error = 0;
int width = msg->data_nbits ? msg->data_nbits : SPI_NBITS_SINGLE;
int addrlen = msg->addr_width;
/* default mode */ /* default mode */
qspi->xfer_mode.flex_mode = true; qspi->xfer_mode.flex_mode = true;
...@@ -475,23 +459,13 @@ static int bcm_qspi_bspi_set_mode(struct bcm_qspi *qspi, ...@@ -475,23 +459,13 @@ static int bcm_qspi_bspi_set_mode(struct bcm_qspi *qspi,
mask = BSPI_STRAP_OVERRIDE_CTRL_OVERRIDE; mask = BSPI_STRAP_OVERRIDE_CTRL_OVERRIDE;
if (val & mask || qspi->s3_strap_override_ctrl & mask) { if (val & mask || qspi->s3_strap_override_ctrl & mask) {
qspi->xfer_mode.flex_mode = false; qspi->xfer_mode.flex_mode = false;
bcm_qspi_write(qspi, BSPI, BSPI_FLEX_MODE_ENABLE, bcm_qspi_write(qspi, BSPI, BSPI_FLEX_MODE_ENABLE, 0);
0); error = bcm_qspi_bspi_set_override(qspi, msg, hp);
if ((val | qspi->s3_strap_override_ctrl) &
BSPI_STRAP_OVERRIDE_CTRL_DATA_DUAL)
width = SPI_NBITS_DUAL;
else if ((val | qspi->s3_strap_override_ctrl) &
BSPI_STRAP_OVERRIDE_CTRL_DATA_QUAD)
width = SPI_NBITS_QUAD;
error = bcm_qspi_bspi_set_override(qspi, width, addrlen,
hp);
} }
} }
if (qspi->xfer_mode.flex_mode) if (qspi->xfer_mode.flex_mode)
error = bcm_qspi_bspi_set_flex_mode(qspi, width, addrlen, hp); error = bcm_qspi_bspi_set_flex_mode(qspi, msg, hp);
if (error) { if (error) {
dev_warn(&qspi->pdev->dev, dev_warn(&qspi->pdev->dev,
...@@ -981,7 +955,7 @@ static int bcm_qspi_flash_read(struct spi_device *spi, ...@@ -981,7 +955,7 @@ static int bcm_qspi_flash_read(struct spi_device *spi,
struct bcm_qspi *qspi = spi_master_get_devdata(spi->master); struct bcm_qspi *qspi = spi_master_get_devdata(spi->master);
int ret = 0; int ret = 0;
bool mspi_read = false; bool mspi_read = false;
u32 io_width, addrlen, addr, len; u32 addr, len;
u_char *buf; u_char *buf;
buf = msg->buf; buf = msg->buf;
...@@ -1010,9 +984,7 @@ static int bcm_qspi_flash_read(struct spi_device *spi, ...@@ -1010,9 +984,7 @@ static int bcm_qspi_flash_read(struct spi_device *spi,
if (mspi_read) if (mspi_read)
return bcm_qspi_mspi_flash_read(spi, msg); return bcm_qspi_mspi_flash_read(spi, msg);
io_width = msg->data_nbits ? msg->data_nbits : SPI_NBITS_SINGLE; ret = bcm_qspi_bspi_set_mode(qspi, msg, -1);
addrlen = msg->addr_width;
ret = bcm_qspi_bspi_set_mode(qspi, io_width, addrlen, -1);
if (!ret) if (!ret)
ret = bcm_qspi_bspi_flash_read(spi, msg); ret = bcm_qspi_bspi_flash_read(spi, msg);
...@@ -1422,6 +1394,11 @@ static int __maybe_unused bcm_qspi_suspend(struct device *dev) ...@@ -1422,6 +1394,11 @@ static int __maybe_unused bcm_qspi_suspend(struct device *dev)
{ {
struct bcm_qspi *qspi = dev_get_drvdata(dev); struct bcm_qspi *qspi = dev_get_drvdata(dev);
/* store the override strap value */
if (!bcm_qspi_bspi_ver_three(qspi))
qspi->s3_strap_override_ctrl =
bcm_qspi_read(qspi, BSPI, BSPI_STRAP_OVERRIDE_CTRL);
spi_master_suspend(qspi->master); spi_master_suspend(qspi->master);
clk_disable(qspi->clk); clk_disable(qspi->clk);
bcm_qspi_hw_uninit(qspi); bcm_qspi_hw_uninit(qspi);
......
...@@ -108,7 +108,7 @@ struct bcm63xx_hsspi { ...@@ -108,7 +108,7 @@ struct bcm63xx_hsspi {
u8 cs_polarity; u8 cs_polarity;
}; };
static void bcm63xx_hsspi_set_cs(struct bcm63xx_hsspi *bs, unsigned cs, static void bcm63xx_hsspi_set_cs(struct bcm63xx_hsspi *bs, unsigned int cs,
bool active) bool active)
{ {
u32 reg; u32 reg;
...@@ -127,7 +127,7 @@ static void bcm63xx_hsspi_set_cs(struct bcm63xx_hsspi *bs, unsigned cs, ...@@ -127,7 +127,7 @@ static void bcm63xx_hsspi_set_cs(struct bcm63xx_hsspi *bs, unsigned cs,
static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs, static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs,
struct spi_device *spi, int hz) struct spi_device *spi, int hz)
{ {
unsigned profile = spi->chip_select; unsigned int profile = spi->chip_select;
u32 reg; u32 reg;
reg = DIV_ROUND_UP(2048, DIV_ROUND_UP(bs->speed_hz, hz)); reg = DIV_ROUND_UP(2048, DIV_ROUND_UP(bs->speed_hz, hz));
...@@ -154,7 +154,7 @@ static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs, ...@@ -154,7 +154,7 @@ static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs,
static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t) static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t)
{ {
struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master); struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master);
unsigned chip_select = spi->chip_select; unsigned int chip_select = spi->chip_select;
u16 opcode = 0; u16 opcode = 0;
int pending = t->len; int pending = t->len;
int step_size = HSSPI_BUFFER_LEN; int step_size = HSSPI_BUFFER_LEN;
...@@ -338,8 +338,8 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) ...@@ -338,8 +338,8 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0) {
dev_err(dev, "no irq\n"); dev_err(dev, "no irq: %d\n", irq);
return -ENXIO; return irq;
} }
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
......
...@@ -530,8 +530,8 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) ...@@ -530,8 +530,8 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0) {
dev_err(dev, "no irq\n"); dev_err(dev, "no irq: %d\n", irq);
return -ENXIO; return irq;
} }
clk = devm_clk_get(dev, "spi"); clk = devm_clk_get(dev, "spi");
......
...@@ -576,10 +576,10 @@ static int cdns_spi_probe(struct platform_device *pdev) ...@@ -576,10 +576,10 @@ static int cdns_spi_probe(struct platform_device *pdev)
goto clk_dis_apb; goto clk_dis_apb;
} }
pm_runtime_enable(&pdev->dev);
pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT); pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
pm_runtime_set_active(&pdev->dev); pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
ret = of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs); ret = of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs);
if (ret < 0) if (ret < 0)
...@@ -704,7 +704,9 @@ static int __maybe_unused cdns_spi_resume(struct device *dev) ...@@ -704,7 +704,9 @@ static int __maybe_unused cdns_spi_resume(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct spi_master *master = platform_get_drvdata(pdev); struct spi_master *master = platform_get_drvdata(pdev);
struct cdns_spi *xspi = spi_master_get_devdata(master);
cdns_spi_init_hw(xspi);
return spi_master_resume(master); return spi_master_resume(master);
} }
......
This diff is collapsed.
...@@ -395,11 +395,6 @@ static int falcon_sflash_probe(struct platform_device *pdev) ...@@ -395,11 +395,6 @@ static int falcon_sflash_probe(struct platform_device *pdev)
struct spi_master *master; struct spi_master *master;
int ret; int ret;
if (ltq_boot_select() != BS_SPI) {
dev_err(&pdev->dev, "invalid bootstrap options\n");
return -ENODEV;
}
master = spi_alloc_master(&pdev->dev, sizeof(*priv)); master = spi_alloc_master(&pdev->dev, sizeof(*priv));
if (!master) if (!master)
return -ENOMEM; return -ENOMEM;
......
This diff is collapsed.
...@@ -32,39 +32,50 @@ ...@@ -32,39 +32,50 @@
#include "spi-test.h" #include "spi-test.h"
/* flag to only simulate transfers */ /* flag to only simulate transfers */
int simulate_only; static int simulate_only;
module_param(simulate_only, int, 0); module_param(simulate_only, int, 0);
MODULE_PARM_DESC(simulate_only, "if not 0 do not execute the spi message"); MODULE_PARM_DESC(simulate_only, "if not 0 do not execute the spi message");
/* dump spi messages */ /* dump spi messages */
int dump_messages; static int dump_messages;
module_param(dump_messages, int, 0); module_param(dump_messages, int, 0);
MODULE_PARM_DESC(dump_messages, MODULE_PARM_DESC(dump_messages,
"=1 dump the basic spi_message_structure, " \ "=1 dump the basic spi_message_structure, " \
"=2 dump the spi_message_structure including data, " \ "=2 dump the spi_message_structure including data, " \
"=3 dump the spi_message structure before and after execution"); "=3 dump the spi_message structure before and after execution");
/* the device is jumpered for loopback - enabling some rx_buf tests */ /* the device is jumpered for loopback - enabling some rx_buf tests */
int loopback; static int loopback;
module_param(loopback, int, 0); module_param(loopback, int, 0);
MODULE_PARM_DESC(loopback, MODULE_PARM_DESC(loopback,
"if set enable loopback mode, where the rx_buf " \ "if set enable loopback mode, where the rx_buf " \
"is checked to match tx_buf after the spi_message " \ "is checked to match tx_buf after the spi_message " \
"is executed"); "is executed");
static int loop_req;
module_param(loop_req, int, 0);
MODULE_PARM_DESC(loop_req,
"if set controller will be asked to enable test loop mode. " \
"If controller supported it, MISO and MOSI will be connected");
static int no_cs;
module_param(no_cs, int, 0);
MODULE_PARM_DESC(no_cs,
"if set Chip Select (CS) will not be used");
/* run only a specific test */ /* run only a specific test */
int run_only_test = -1; static int run_only_test = -1;
module_param(run_only_test, int, 0); module_param(run_only_test, int, 0);
MODULE_PARM_DESC(run_only_test, MODULE_PARM_DESC(run_only_test,
"only run the test with this number (0-based !)"); "only run the test with this number (0-based !)");
/* use vmalloc'ed buffers */ /* use vmalloc'ed buffers */
int use_vmalloc; static int use_vmalloc;
module_param(use_vmalloc, int, 0644); module_param(use_vmalloc, int, 0644);
MODULE_PARM_DESC(use_vmalloc, MODULE_PARM_DESC(use_vmalloc,
"use vmalloc'ed buffers instead of kmalloc'ed"); "use vmalloc'ed buffers instead of kmalloc'ed");
/* check rx ranges */ /* check rx ranges */
int check_ranges = 1; static int check_ranges = 1;
module_param(check_ranges, int, 0644); module_param(check_ranges, int, 0644);
MODULE_PARM_DESC(check_ranges, MODULE_PARM_DESC(check_ranges,
"checks rx_buffer pattern are valid"); "checks rx_buffer pattern are valid");
...@@ -313,6 +324,17 @@ static int spi_loopback_test_probe(struct spi_device *spi) ...@@ -313,6 +324,17 @@ static int spi_loopback_test_probe(struct spi_device *spi)
{ {
int ret; int ret;
if (loop_req || no_cs) {
spi->mode |= loop_req ? SPI_LOOP : 0;
spi->mode |= no_cs ? SPI_NO_CS : 0;
ret = spi_setup(spi);
if (ret) {
dev_err(&spi->dev, "SPI setup with SPI_LOOP or SPI_NO_CS failed (%d)\n",
ret);
return ret;
}
}
dev_info(&spi->dev, "Executing spi-loopback-tests\n"); dev_info(&spi->dev, "Executing spi-loopback-tests\n");
ret = spi_test_run_tests(spi, spi_tests); ret = spi_test_run_tests(spi, spi_tests);
......
...@@ -1338,7 +1338,6 @@ static int omap2_mcspi_probe(struct platform_device *pdev) ...@@ -1338,7 +1338,6 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
struct resource *r; struct resource *r;
int status = 0, i; int status = 0, i;
u32 regs_offset = 0; u32 regs_offset = 0;
static int bus_num = 1;
struct device_node *node = pdev->dev.of_node; struct device_node *node = pdev->dev.of_node;
const struct of_device_id *match; const struct of_device_id *match;
...@@ -1374,14 +1373,11 @@ static int omap2_mcspi_probe(struct platform_device *pdev) ...@@ -1374,14 +1373,11 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
of_property_read_u32(node, "ti,spi-num-cs", &num_cs); of_property_read_u32(node, "ti,spi-num-cs", &num_cs);
master->num_chipselect = num_cs; master->num_chipselect = num_cs;
master->bus_num = bus_num++;
if (of_get_property(node, "ti,pindir-d0-out-d1-in", NULL)) if (of_get_property(node, "ti,pindir-d0-out-d1-in", NULL))
mcspi->pin_dir = MCSPI_PINDIR_D0_OUT_D1_IN; mcspi->pin_dir = MCSPI_PINDIR_D0_OUT_D1_IN;
} else { } else {
pdata = dev_get_platdata(&pdev->dev); pdata = dev_get_platdata(&pdev->dev);
master->num_chipselect = pdata->num_cs; master->num_chipselect = pdata->num_cs;
if (pdev->id != -1)
master->bus_num = pdev->id;
mcspi->pin_dir = pdata->pin_dir; mcspi->pin_dir = pdata->pin_dir;
} }
regs_offset = pdata->regs_offset; regs_offset = pdata->regs_offset;
......
...@@ -669,8 +669,8 @@ static int orion_spi_probe(struct platform_device *pdev) ...@@ -669,8 +669,8 @@ static int orion_spi_probe(struct platform_device *pdev)
status = of_property_read_u32(np, "reg", &cs); status = of_property_read_u32(np, "reg", &cs);
if (status) { if (status) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"%s has no valid 'reg' property (%d)\n", "%pOF has no valid 'reg' property (%d)\n",
np->full_name, status); np, status);
status = 0; status = 0;
continue; continue;
} }
......
...@@ -52,14 +52,14 @@ struct pic32_spi_regs { ...@@ -52,14 +52,14 @@ struct pic32_spi_regs {
/* Bit fields of SPI Control Register */ /* Bit fields of SPI Control Register */
#define CTRL_RX_INT_SHIFT 0 /* Rx interrupt generation */ #define CTRL_RX_INT_SHIFT 0 /* Rx interrupt generation */
#define RX_FIFO_EMTPY 0 #define RX_FIFO_EMPTY 0
#define RX_FIFO_NOT_EMPTY 1 /* not empty */ #define RX_FIFO_NOT_EMPTY 1 /* not empty */
#define RX_FIFO_HALF_FULL 2 /* full by half or more */ #define RX_FIFO_HALF_FULL 2 /* full by half or more */
#define RX_FIFO_FULL 3 /* completely full */ #define RX_FIFO_FULL 3 /* completely full */
#define CTRL_TX_INT_SHIFT 2 /* TX interrupt generation */ #define CTRL_TX_INT_SHIFT 2 /* TX interrupt generation */
#define TX_FIFO_ALL_EMPTY 0 /* completely empty */ #define TX_FIFO_ALL_EMPTY 0 /* completely empty */
#define TX_FIFO_EMTPY 1 /* empty */ #define TX_FIFO_EMPTY 1 /* empty */
#define TX_FIFO_HALF_EMPTY 2 /* empty by half or more */ #define TX_FIFO_HALF_EMPTY 2 /* empty by half or more */
#define TX_FIFO_NOT_FULL 3 /* atleast one empty */ #define TX_FIFO_NOT_FULL 3 /* atleast one empty */
......
...@@ -2429,7 +2429,7 @@ static struct vendor_data vendor_lsi = { ...@@ -2429,7 +2429,7 @@ static struct vendor_data vendor_lsi = {
.internal_cs_ctrl = true, .internal_cs_ctrl = true,
}; };
static struct amba_id pl022_ids[] = { static const struct amba_id pl022_ids[] = {
{ {
/* /*
* ARM PL022 variant, this has a 16bit wide * ARM PL022 variant, this has a 16bit wide
......
...@@ -402,8 +402,8 @@ static void cs_assert(struct driver_data *drv_data) ...@@ -402,8 +402,8 @@ static void cs_assert(struct driver_data *drv_data)
return; return;
} }
if (gpio_is_valid(chip->gpio_cs)) { if (chip->gpiod_cs) {
gpio_set_value(chip->gpio_cs, chip->gpio_cs_inverted); gpiod_set_value(chip->gpiod_cs, chip->gpio_cs_inverted);
return; return;
} }
...@@ -424,8 +424,8 @@ static void cs_deassert(struct driver_data *drv_data) ...@@ -424,8 +424,8 @@ static void cs_deassert(struct driver_data *drv_data)
return; return;
} }
if (gpio_is_valid(chip->gpio_cs)) { if (chip->gpiod_cs) {
gpio_set_value(chip->gpio_cs, !chip->gpio_cs_inverted); gpiod_set_value(chip->gpiod_cs, !chip->gpio_cs_inverted);
return; return;
} }
...@@ -1213,17 +1213,16 @@ static int setup_cs(struct spi_device *spi, struct chip_data *chip, ...@@ -1213,17 +1213,16 @@ static int setup_cs(struct spi_device *spi, struct chip_data *chip,
struct pxa2xx_spi_chip *chip_info) struct pxa2xx_spi_chip *chip_info)
{ {
struct driver_data *drv_data = spi_master_get_devdata(spi->master); struct driver_data *drv_data = spi_master_get_devdata(spi->master);
struct gpio_desc *gpiod;
int err = 0; int err = 0;
if (chip == NULL) if (chip == NULL)
return 0; return 0;
if (drv_data->cs_gpiods) { if (drv_data->cs_gpiods) {
struct gpio_desc *gpiod;
gpiod = drv_data->cs_gpiods[spi->chip_select]; gpiod = drv_data->cs_gpiods[spi->chip_select];
if (gpiod) { if (gpiod) {
chip->gpio_cs = desc_to_gpio(gpiod); chip->gpiod_cs = gpiod;
chip->gpio_cs_inverted = spi->mode & SPI_CS_HIGH; chip->gpio_cs_inverted = spi->mode & SPI_CS_HIGH;
gpiod_set_value(gpiod, chip->gpio_cs_inverted); gpiod_set_value(gpiod, chip->gpio_cs_inverted);
} }
...@@ -1237,8 +1236,10 @@ static int setup_cs(struct spi_device *spi, struct chip_data *chip, ...@@ -1237,8 +1236,10 @@ static int setup_cs(struct spi_device *spi, struct chip_data *chip,
/* NOTE: setup() can be called multiple times, possibly with /* NOTE: setup() can be called multiple times, possibly with
* different chip_info, release previously requested GPIO * different chip_info, release previously requested GPIO
*/ */
if (gpio_is_valid(chip->gpio_cs)) if (chip->gpiod_cs) {
gpio_free(chip->gpio_cs); gpio_free(desc_to_gpio(chip->gpiod_cs));
chip->gpiod_cs = NULL;
}
/* If (*cs_control) is provided, ignore GPIO chip select */ /* If (*cs_control) is provided, ignore GPIO chip select */
if (chip_info->cs_control) { if (chip_info->cs_control) {
...@@ -1254,11 +1255,11 @@ static int setup_cs(struct spi_device *spi, struct chip_data *chip, ...@@ -1254,11 +1255,11 @@ static int setup_cs(struct spi_device *spi, struct chip_data *chip,
return err; return err;
} }
chip->gpio_cs = chip_info->gpio_cs; gpiod = gpio_to_desc(chip_info->gpio_cs);
chip->gpiod_cs = gpiod;
chip->gpio_cs_inverted = spi->mode & SPI_CS_HIGH; chip->gpio_cs_inverted = spi->mode & SPI_CS_HIGH;
err = gpio_direction_output(chip->gpio_cs, err = gpiod_direction_output(gpiod, !chip->gpio_cs_inverted);
!chip->gpio_cs_inverted);
} }
return err; return err;
...@@ -1317,8 +1318,7 @@ static int setup(struct spi_device *spi) ...@@ -1317,8 +1318,7 @@ static int setup(struct spi_device *spi)
} }
chip->frm = spi->chip_select; chip->frm = spi->chip_select;
} else }
chip->gpio_cs = -1;
chip->enable_dma = drv_data->master_info->enable_dma; chip->enable_dma = drv_data->master_info->enable_dma;
chip->timeout = TIMOUT_DFLT; chip->timeout = TIMOUT_DFLT;
} }
...@@ -1416,8 +1416,8 @@ static void cleanup(struct spi_device *spi) ...@@ -1416,8 +1416,8 @@ static void cleanup(struct spi_device *spi)
return; return;
if (drv_data->ssp_type != CE4100_SSP && !drv_data->cs_gpiods && if (drv_data->ssp_type != CE4100_SSP && !drv_data->cs_gpiods &&
gpio_is_valid(chip->gpio_cs)) chip->gpiod_cs)
gpio_free(chip->gpio_cs); gpio_free(desc_to_gpio(chip->gpiod_cs));
kfree(chip); kfree(chip);
} }
...@@ -1769,8 +1769,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) ...@@ -1769,8 +1769,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
for (i = 0; i < master->num_chipselect; i++) { for (i = 0; i < master->num_chipselect; i++) {
struct gpio_desc *gpiod; struct gpio_desc *gpiod;
gpiod = devm_gpiod_get_index(dev, "cs", i, gpiod = devm_gpiod_get_index(dev, "cs", i, GPIOD_ASIS);
GPIOD_OUT_HIGH);
if (IS_ERR(gpiod)) { if (IS_ERR(gpiod)) {
/* Means use native chip select */ /* Means use native chip select */
if (PTR_ERR(gpiod) == -ENOENT) if (PTR_ERR(gpiod) == -ENOENT)
......
...@@ -83,7 +83,7 @@ struct chip_data { ...@@ -83,7 +83,7 @@ struct chip_data {
u16 lpss_tx_threshold; u16 lpss_tx_threshold;
u8 enable_dma; u8 enable_dma;
union { union {
int gpio_cs; struct gpio_desc *gpiod_cs;
unsigned int frm; unsigned int frm;
}; };
int gpio_cs_inverted; int gpio_cs_inverted;
......
This diff is collapsed.
...@@ -568,7 +568,13 @@ static void rockchip_spi_config(struct rockchip_spi *rs) ...@@ -568,7 +568,13 @@ static void rockchip_spi_config(struct rockchip_spi *rs)
writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0); writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0);
writel_relaxed(rs->len - 1, rs->regs + ROCKCHIP_SPI_CTRLR1); if (rs->n_bytes == 1)
writel_relaxed(rs->len - 1, rs->regs + ROCKCHIP_SPI_CTRLR1);
else if (rs->n_bytes == 2)
writel_relaxed((rs->len / 2) - 1, rs->regs + ROCKCHIP_SPI_CTRLR1);
else
writel_relaxed((rs->len * 2) - 1, rs->regs + ROCKCHIP_SPI_CTRLR1);
writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_TXFTLR); writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_TXFTLR);
writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_RXFTLR); writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_RXFTLR);
...@@ -666,7 +672,7 @@ static bool rockchip_spi_can_dma(struct spi_master *master, ...@@ -666,7 +672,7 @@ static bool rockchip_spi_can_dma(struct spi_master *master,
static int rockchip_spi_probe(struct platform_device *pdev) static int rockchip_spi_probe(struct platform_device *pdev)
{ {
int ret = 0; int ret;
struct rockchip_spi *rs; struct rockchip_spi *rs;
struct spi_master *master; struct spi_master *master;
struct resource *mem; struct resource *mem;
...@@ -703,13 +709,13 @@ static int rockchip_spi_probe(struct platform_device *pdev) ...@@ -703,13 +709,13 @@ static int rockchip_spi_probe(struct platform_device *pdev)
} }
ret = clk_prepare_enable(rs->apb_pclk); ret = clk_prepare_enable(rs->apb_pclk);
if (ret) { if (ret < 0) {
dev_err(&pdev->dev, "Failed to enable apb_pclk\n"); dev_err(&pdev->dev, "Failed to enable apb_pclk\n");
goto err_put_master; goto err_put_master;
} }
ret = clk_prepare_enable(rs->spiclk); ret = clk_prepare_enable(rs->spiclk);
if (ret) { if (ret < 0) {
dev_err(&pdev->dev, "Failed to enable spi_clk\n"); dev_err(&pdev->dev, "Failed to enable spi_clk\n");
goto err_disable_apbclk; goto err_disable_apbclk;
} }
...@@ -786,7 +792,7 @@ static int rockchip_spi_probe(struct platform_device *pdev) ...@@ -786,7 +792,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
} }
ret = devm_spi_register_master(&pdev->dev, master); ret = devm_spi_register_master(&pdev->dev, master);
if (ret) { if (ret < 0) {
dev_err(&pdev->dev, "Failed to register master\n"); dev_err(&pdev->dev, "Failed to register master\n");
goto err_free_dma_rx; goto err_free_dma_rx;
} }
...@@ -816,11 +822,15 @@ static int rockchip_spi_remove(struct platform_device *pdev) ...@@ -816,11 +822,15 @@ static int rockchip_spi_remove(struct platform_device *pdev)
struct spi_master *master = spi_master_get(platform_get_drvdata(pdev)); struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
struct rockchip_spi *rs = spi_master_get_devdata(master); struct rockchip_spi *rs = spi_master_get_devdata(master);
pm_runtime_disable(&pdev->dev); pm_runtime_get_sync(&pdev->dev);
clk_disable_unprepare(rs->spiclk); clk_disable_unprepare(rs->spiclk);
clk_disable_unprepare(rs->apb_pclk); clk_disable_unprepare(rs->apb_pclk);
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
if (rs->dma_tx.ch) if (rs->dma_tx.ch)
dma_release_channel(rs->dma_tx.ch); dma_release_channel(rs->dma_tx.ch);
if (rs->dma_rx.ch) if (rs->dma_rx.ch)
...@@ -834,43 +844,34 @@ static int rockchip_spi_remove(struct platform_device *pdev) ...@@ -834,43 +844,34 @@ static int rockchip_spi_remove(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int rockchip_spi_suspend(struct device *dev) static int rockchip_spi_suspend(struct device *dev)
{ {
int ret = 0; int ret;
struct spi_master *master = dev_get_drvdata(dev); struct spi_master *master = dev_get_drvdata(dev);
struct rockchip_spi *rs = spi_master_get_devdata(master); struct rockchip_spi *rs = spi_master_get_devdata(master);
ret = spi_master_suspend(rs->master); ret = spi_master_suspend(rs->master);
if (ret) if (ret < 0)
return ret; return ret;
if (!pm_runtime_suspended(dev)) { ret = pm_runtime_force_suspend(dev);
clk_disable_unprepare(rs->spiclk); if (ret < 0)
clk_disable_unprepare(rs->apb_pclk); return ret;
}
pinctrl_pm_select_sleep_state(dev); pinctrl_pm_select_sleep_state(dev);
return ret; return 0;
} }
static int rockchip_spi_resume(struct device *dev) static int rockchip_spi_resume(struct device *dev)
{ {
int ret = 0; int ret;
struct spi_master *master = dev_get_drvdata(dev); struct spi_master *master = dev_get_drvdata(dev);
struct rockchip_spi *rs = spi_master_get_devdata(master); struct rockchip_spi *rs = spi_master_get_devdata(master);
pinctrl_pm_select_default_state(dev); pinctrl_pm_select_default_state(dev);
if (!pm_runtime_suspended(dev)) { ret = pm_runtime_force_resume(dev);
ret = clk_prepare_enable(rs->apb_pclk); if (ret < 0)
if (ret < 0) return ret;
return ret;
ret = clk_prepare_enable(rs->spiclk);
if (ret < 0) {
clk_disable_unprepare(rs->apb_pclk);
return ret;
}
}
ret = spi_master_resume(rs->master); ret = spi_master_resume(rs->master);
if (ret < 0) { if (ret < 0) {
...@@ -878,7 +879,7 @@ static int rockchip_spi_resume(struct device *dev) ...@@ -878,7 +879,7 @@ static int rockchip_spi_resume(struct device *dev)
clk_disable_unprepare(rs->apb_pclk); clk_disable_unprepare(rs->apb_pclk);
} }
return ret; return 0;
} }
#endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM_SLEEP */
...@@ -901,14 +902,14 @@ static int rockchip_spi_runtime_resume(struct device *dev) ...@@ -901,14 +902,14 @@ static int rockchip_spi_runtime_resume(struct device *dev)
struct rockchip_spi *rs = spi_master_get_devdata(master); struct rockchip_spi *rs = spi_master_get_devdata(master);
ret = clk_prepare_enable(rs->apb_pclk); ret = clk_prepare_enable(rs->apb_pclk);
if (ret) if (ret < 0)
return ret; return ret;
ret = clk_prepare_enable(rs->spiclk); ret = clk_prepare_enable(rs->spiclk);
if (ret) if (ret < 0)
clk_disable_unprepare(rs->apb_pclk); clk_disable_unprepare(rs->apb_pclk);
return ret; return 0;
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
...@@ -919,6 +920,7 @@ static const struct dev_pm_ops rockchip_spi_pm = { ...@@ -919,6 +920,7 @@ static const struct dev_pm_ops rockchip_spi_pm = {
}; };
static const struct of_device_id rockchip_spi_dt_match[] = { static const struct of_device_id rockchip_spi_dt_match[] = {
{ .compatible = "rockchip,rv1108-spi", },
{ .compatible = "rockchip,rk3036-spi", }, { .compatible = "rockchip,rk3036-spi", },
{ .compatible = "rockchip,rk3066-spi", }, { .compatible = "rockchip,rk3066-spi", },
{ .compatible = "rockchip,rk3188-spi", }, { .compatible = "rockchip,rk3188-spi", },
......
...@@ -38,6 +38,7 @@ struct sh_msiof_chipdata { ...@@ -38,6 +38,7 @@ struct sh_msiof_chipdata {
u16 tx_fifo_size; u16 tx_fifo_size;
u16 rx_fifo_size; u16 rx_fifo_size;
u16 master_flags; u16 master_flags;
u16 min_div;
}; };
struct sh_msiof_spi_priv { struct sh_msiof_spi_priv {
...@@ -49,6 +50,7 @@ struct sh_msiof_spi_priv { ...@@ -49,6 +50,7 @@ struct sh_msiof_spi_priv {
struct completion done; struct completion done;
unsigned int tx_fifo_size; unsigned int tx_fifo_size;
unsigned int rx_fifo_size; unsigned int rx_fifo_size;
unsigned int min_div;
void *tx_dma_page; void *tx_dma_page;
void *rx_dma_page; void *rx_dma_page;
dma_addr_t tx_dma_addr; dma_addr_t tx_dma_addr;
...@@ -261,6 +263,8 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p, ...@@ -261,6 +263,8 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,
if (!WARN_ON(!spi_hz || !parent_rate)) if (!WARN_ON(!spi_hz || !parent_rate))
div = DIV_ROUND_UP(parent_rate, spi_hz); div = DIV_ROUND_UP(parent_rate, spi_hz);
div = max_t(unsigned long, div, p->min_div);
for (k = 0; k < ARRAY_SIZE(sh_msiof_spi_div_table); k++) { for (k = 0; k < ARRAY_SIZE(sh_msiof_spi_div_table); k++) {
brps = DIV_ROUND_UP(div, sh_msiof_spi_div_table[k].div); brps = DIV_ROUND_UP(div, sh_msiof_spi_div_table[k].div);
/* SCR_BRDV_DIV_1 is valid only if BRPS is x 1/1 or x 1/2 */ /* SCR_BRDV_DIV_1 is valid only if BRPS is x 1/1 or x 1/2 */
...@@ -998,24 +1002,33 @@ static const struct sh_msiof_chipdata sh_data = { ...@@ -998,24 +1002,33 @@ static const struct sh_msiof_chipdata sh_data = {
.tx_fifo_size = 64, .tx_fifo_size = 64,
.rx_fifo_size = 64, .rx_fifo_size = 64,
.master_flags = 0, .master_flags = 0,
.min_div = 1,
};
static const struct sh_msiof_chipdata rcar_gen2_data = {
.tx_fifo_size = 64,
.rx_fifo_size = 64,
.master_flags = SPI_MASTER_MUST_TX,
.min_div = 1,
}; };
static const struct sh_msiof_chipdata r8a779x_data = { static const struct sh_msiof_chipdata rcar_gen3_data = {
.tx_fifo_size = 64, .tx_fifo_size = 64,
.rx_fifo_size = 64, .rx_fifo_size = 64,
.master_flags = SPI_MASTER_MUST_TX, .master_flags = SPI_MASTER_MUST_TX,
.min_div = 2,
}; };
static const struct of_device_id sh_msiof_match[] = { static const struct of_device_id sh_msiof_match[] = {
{ .compatible = "renesas,sh-mobile-msiof", .data = &sh_data }, { .compatible = "renesas,sh-mobile-msiof", .data = &sh_data },
{ .compatible = "renesas,msiof-r8a7790", .data = &r8a779x_data }, { .compatible = "renesas,msiof-r8a7790", .data = &rcar_gen2_data },
{ .compatible = "renesas,msiof-r8a7791", .data = &r8a779x_data }, { .compatible = "renesas,msiof-r8a7791", .data = &rcar_gen2_data },
{ .compatible = "renesas,msiof-r8a7792", .data = &r8a779x_data }, { .compatible = "renesas,msiof-r8a7792", .data = &rcar_gen2_data },
{ .compatible = "renesas,msiof-r8a7793", .data = &r8a779x_data }, { .compatible = "renesas,msiof-r8a7793", .data = &rcar_gen2_data },
{ .compatible = "renesas,msiof-r8a7794", .data = &r8a779x_data }, { .compatible = "renesas,msiof-r8a7794", .data = &rcar_gen2_data },
{ .compatible = "renesas,rcar-gen2-msiof", .data = &r8a779x_data }, { .compatible = "renesas,rcar-gen2-msiof", .data = &rcar_gen2_data },
{ .compatible = "renesas,msiof-r8a7796", .data = &r8a779x_data }, { .compatible = "renesas,msiof-r8a7796", .data = &rcar_gen3_data },
{ .compatible = "renesas,rcar-gen3-msiof", .data = &r8a779x_data }, { .compatible = "renesas,rcar-gen3-msiof", .data = &rcar_gen3_data },
{ .compatible = "renesas,sh-msiof", .data = &sh_data }, /* Deprecated */ { .compatible = "renesas,sh-msiof", .data = &sh_data }, /* Deprecated */
{}, {},
}; };
...@@ -1230,6 +1243,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) ...@@ -1230,6 +1243,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, p); platform_set_drvdata(pdev, p);
p->master = master; p->master = master;
p->info = info; p->info = info;
p->min_div = chipdata->min_div;
init_completion(&p->done); init_completion(&p->done);
......
...@@ -446,8 +446,8 @@ static int spi_sh_probe(struct platform_device *pdev) ...@@ -446,8 +446,8 @@ static int spi_sh_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0) {
dev_err(&pdev->dev, "platform_get_irq error\n"); dev_err(&pdev->dev, "platform_get_irq error: %d\n", irq);
return -ENODEV; return irq;
} }
master = spi_alloc_master(&pdev->dev, sizeof(struct spi_sh_data)); master = spi_alloc_master(&pdev->dev, sizeof(struct spi_sh_data));
......
...@@ -1132,7 +1132,7 @@ static int stm32_spi_probe(struct platform_device *pdev) ...@@ -1132,7 +1132,7 @@ static int stm32_spi_probe(struct platform_device *pdev)
goto err_master_put; goto err_master_put;
} }
spi->rst = devm_reset_control_get(&pdev->dev, NULL); spi->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
if (!IS_ERR(spi->rst)) { if (!IS_ERR(spi->rst)) {
reset_control_assert(spi->rst); reset_control_assert(spi->rst);
udelay(2); udelay(2);
......
...@@ -502,7 +502,7 @@ static int sun6i_spi_probe(struct platform_device *pdev) ...@@ -502,7 +502,7 @@ static int sun6i_spi_probe(struct platform_device *pdev)
init_completion(&sspi->done); init_completion(&sspi->done);
sspi->rstc = devm_reset_control_get(&pdev->dev, NULL); sspi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
if (IS_ERR(sspi->rstc)) { if (IS_ERR(sspi->rstc)) {
dev_err(&pdev->dev, "Couldn't get reset controller\n"); dev_err(&pdev->dev, "Couldn't get reset controller\n");
ret = PTR_ERR(sspi->rstc); ret = PTR_ERR(sspi->rstc);
......
...@@ -1083,7 +1083,7 @@ static int tegra_spi_probe(struct platform_device *pdev) ...@@ -1083,7 +1083,7 @@ static int tegra_spi_probe(struct platform_device *pdev)
goto exit_free_irq; goto exit_free_irq;
} }
tspi->rst = devm_reset_control_get(&pdev->dev, "spi"); tspi->rst = devm_reset_control_get_exclusive(&pdev->dev, "spi");
if (IS_ERR(tspi->rst)) { if (IS_ERR(tspi->rst)) {
dev_err(&pdev->dev, "can not get reset\n"); dev_err(&pdev->dev, "can not get reset\n");
ret = PTR_ERR(tspi->rst); ret = PTR_ERR(tspi->rst);
......
...@@ -485,7 +485,7 @@ static int tegra_sflash_probe(struct platform_device *pdev) ...@@ -485,7 +485,7 @@ static int tegra_sflash_probe(struct platform_device *pdev)
goto exit_free_irq; goto exit_free_irq;
} }
tsd->rst = devm_reset_control_get(&pdev->dev, "spi"); tsd->rst = devm_reset_control_get_exclusive(&pdev->dev, "spi");
if (IS_ERR(tsd->rst)) { if (IS_ERR(tsd->rst)) {
dev_err(&pdev->dev, "can not get reset\n"); dev_err(&pdev->dev, "can not get reset\n");
ret = PTR_ERR(tsd->rst); ret = PTR_ERR(tsd->rst);
......
...@@ -1081,7 +1081,7 @@ static int tegra_slink_probe(struct platform_device *pdev) ...@@ -1081,7 +1081,7 @@ static int tegra_slink_probe(struct platform_device *pdev)
goto exit_free_irq; goto exit_free_irq;
} }
tspi->rst = devm_reset_control_get(&pdev->dev, "spi"); tspi->rst = devm_reset_control_get_exclusive(&pdev->dev, "spi");
if (IS_ERR(tspi->rst)) { if (IS_ERR(tspi->rst)) {
dev_err(&pdev->dev, "can not get reset\n"); dev_err(&pdev->dev, "can not get reset\n");
ret = PTR_ERR(tspi->rst); ret = PTR_ERR(tspi->rst);
......
...@@ -393,8 +393,8 @@ static int xlp_spi_probe(struct platform_device *pdev) ...@@ -393,8 +393,8 @@ static int xlp_spi_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0) {
dev_err(&pdev->dev, "no IRQ resource found\n"); dev_err(&pdev->dev, "no IRQ resource found: %d\n", irq);
return -EINVAL; return irq;
} }
err = devm_request_irq(&pdev->dev, irq, xlp_spi_interrupt, 0, err = devm_request_irq(&pdev->dev, irq, xlp_spi_interrupt, 0,
pdev->name, xspi); pdev->name, xspi);
......
...@@ -40,9 +40,13 @@ ...@@ -40,9 +40,13 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/highmem.h> #include <linux/highmem.h>
#include <linux/idr.h>
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include <trace/events/spi.h> #include <trace/events/spi.h>
#define SPI_DYN_FIRST_BUS_NUM 0
static DEFINE_IDR(spi_master_idr);
static void spidev_release(struct device *dev) static void spidev_release(struct device *dev)
{ {
...@@ -321,8 +325,7 @@ static int spi_uevent(struct device *dev, struct kobj_uevent_env *env) ...@@ -321,8 +325,7 @@ static int spi_uevent(struct device *dev, struct kobj_uevent_env *env)
if (rc != -ENODEV) if (rc != -ENODEV)
return rc; return rc;
add_uevent_var(env, "MODALIAS=%s%s", SPI_MODULE_PREFIX, spi->modalias); return add_uevent_var(env, "MODALIAS=%s%s", SPI_MODULE_PREFIX, spi->modalias);
return 0;
} }
struct bus_type spi_bus_type = { struct bus_type spi_bus_type = {
...@@ -421,6 +424,7 @@ static LIST_HEAD(spi_controller_list); ...@@ -421,6 +424,7 @@ static LIST_HEAD(spi_controller_list);
/* /*
* Used to protect add/del opertion for board_info list and * Used to protect add/del opertion for board_info list and
* spi_controller list, and their matching process * spi_controller list, and their matching process
* also used to protect object of type struct idr
*/ */
static DEFINE_MUTEX(board_lock); static DEFINE_MUTEX(board_lock);
...@@ -1533,15 +1537,15 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, ...@@ -1533,15 +1537,15 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
int rc; int rc;
/* Mode (clock phase/polarity/etc.) */ /* Mode (clock phase/polarity/etc.) */
if (of_find_property(nc, "spi-cpha", NULL)) if (of_property_read_bool(nc, "spi-cpha"))
spi->mode |= SPI_CPHA; spi->mode |= SPI_CPHA;
if (of_find_property(nc, "spi-cpol", NULL)) if (of_property_read_bool(nc, "spi-cpol"))
spi->mode |= SPI_CPOL; spi->mode |= SPI_CPOL;
if (of_find_property(nc, "spi-cs-high", NULL)) if (of_property_read_bool(nc, "spi-cs-high"))
spi->mode |= SPI_CS_HIGH; spi->mode |= SPI_CS_HIGH;
if (of_find_property(nc, "spi-3wire", NULL)) if (of_property_read_bool(nc, "spi-3wire"))
spi->mode |= SPI_3WIRE; spi->mode |= SPI_3WIRE;
if (of_find_property(nc, "spi-lsb-first", NULL)) if (of_property_read_bool(nc, "spi-lsb-first"))
spi->mode |= SPI_LSB_FIRST; spi->mode |= SPI_LSB_FIRST;
/* Device DUAL/QUAD mode */ /* Device DUAL/QUAD mode */
...@@ -1583,8 +1587,8 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, ...@@ -1583,8 +1587,8 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
if (spi_controller_is_slave(ctlr)) { if (spi_controller_is_slave(ctlr)) {
if (strcmp(nc->name, "slave")) { if (strcmp(nc->name, "slave")) {
dev_err(&ctlr->dev, "%s is not called 'slave'\n", dev_err(&ctlr->dev, "%pOF is not called 'slave'\n",
nc->full_name); nc);
return -EINVAL; return -EINVAL;
} }
return 0; return 0;
...@@ -1593,8 +1597,8 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, ...@@ -1593,8 +1597,8 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
/* Device address */ /* Device address */
rc = of_property_read_u32(nc, "reg", &value); rc = of_property_read_u32(nc, "reg", &value);
if (rc) { if (rc) {
dev_err(&ctlr->dev, "%s has no valid 'reg' property (%d)\n", dev_err(&ctlr->dev, "%pOF has no valid 'reg' property (%d)\n",
nc->full_name, rc); nc, rc);
return rc; return rc;
} }
spi->chip_select = value; spi->chip_select = value;
...@@ -1603,8 +1607,7 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, ...@@ -1603,8 +1607,7 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
rc = of_property_read_u32(nc, "spi-max-frequency", &value); rc = of_property_read_u32(nc, "spi-max-frequency", &value);
if (rc) { if (rc) {
dev_err(&ctlr->dev, dev_err(&ctlr->dev,
"%s has no valid 'spi-max-frequency' property (%d)\n", "%pOF has no valid 'spi-max-frequency' property (%d)\n", nc, rc);
nc->full_name, rc);
return rc; return rc;
} }
spi->max_speed_hz = value; spi->max_speed_hz = value;
...@@ -1621,8 +1624,7 @@ of_register_spi_device(struct spi_controller *ctlr, struct device_node *nc) ...@@ -1621,8 +1624,7 @@ of_register_spi_device(struct spi_controller *ctlr, struct device_node *nc)
/* Alloc an spi_device */ /* Alloc an spi_device */
spi = spi_alloc_device(ctlr); spi = spi_alloc_device(ctlr);
if (!spi) { if (!spi) {
dev_err(&ctlr->dev, "spi_device alloc error for %s\n", dev_err(&ctlr->dev, "spi_device alloc error for %pOF\n", nc);
nc->full_name);
rc = -ENOMEM; rc = -ENOMEM;
goto err_out; goto err_out;
} }
...@@ -1631,8 +1633,7 @@ of_register_spi_device(struct spi_controller *ctlr, struct device_node *nc) ...@@ -1631,8 +1633,7 @@ of_register_spi_device(struct spi_controller *ctlr, struct device_node *nc)
rc = of_modalias_node(nc, spi->modalias, rc = of_modalias_node(nc, spi->modalias,
sizeof(spi->modalias)); sizeof(spi->modalias));
if (rc < 0) { if (rc < 0) {
dev_err(&ctlr->dev, "cannot find modalias for %s\n", dev_err(&ctlr->dev, "cannot find modalias for %pOF\n", nc);
nc->full_name);
goto err_out; goto err_out;
} }
...@@ -1647,8 +1648,7 @@ of_register_spi_device(struct spi_controller *ctlr, struct device_node *nc) ...@@ -1647,8 +1648,7 @@ of_register_spi_device(struct spi_controller *ctlr, struct device_node *nc)
/* Register the new device */ /* Register the new device */
rc = spi_add_device(spi); rc = spi_add_device(spi);
if (rc) { if (rc) {
dev_err(&ctlr->dev, "spi_device register error %s\n", dev_err(&ctlr->dev, "spi_device register error %pOF\n", nc);
nc->full_name);
goto err_of_node_put; goto err_of_node_put;
} }
...@@ -1682,8 +1682,7 @@ static void of_register_spi_devices(struct spi_controller *ctlr) ...@@ -1682,8 +1682,7 @@ static void of_register_spi_devices(struct spi_controller *ctlr)
spi = of_register_spi_device(ctlr, nc); spi = of_register_spi_device(ctlr, nc);
if (IS_ERR(spi)) { if (IS_ERR(spi)) {
dev_warn(&ctlr->dev, dev_warn(&ctlr->dev,
"Failed to create SPI device for %s\n", "Failed to create SPI device for %pOF\n", nc);
nc->full_name);
of_node_clear_flag(nc, OF_POPULATED); of_node_clear_flag(nc, OF_POPULATED);
} }
} }
...@@ -2052,11 +2051,10 @@ static int of_spi_register_master(struct spi_controller *ctlr) ...@@ -2052,11 +2051,10 @@ static int of_spi_register_master(struct spi_controller *ctlr)
*/ */
int spi_register_controller(struct spi_controller *ctlr) int spi_register_controller(struct spi_controller *ctlr)
{ {
static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1);
struct device *dev = ctlr->dev.parent; struct device *dev = ctlr->dev.parent;
struct boardinfo *bi; struct boardinfo *bi;
int status = -ENODEV; int status = -ENODEV;
int dynamic = 0; int id;
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
...@@ -2072,19 +2070,28 @@ int spi_register_controller(struct spi_controller *ctlr) ...@@ -2072,19 +2070,28 @@ int spi_register_controller(struct spi_controller *ctlr)
*/ */
if (ctlr->num_chipselect == 0) if (ctlr->num_chipselect == 0)
return -EINVAL; return -EINVAL;
/* allocate dynamic bus number using Linux idr */
if ((ctlr->bus_num < 0) && ctlr->dev.of_node) if ((ctlr->bus_num < 0) && ctlr->dev.of_node) {
ctlr->bus_num = of_alias_get_id(ctlr->dev.of_node, "spi"); id = of_alias_get_id(ctlr->dev.of_node, "spi");
if (id >= 0) {
/* convention: dynamically assigned bus IDs count down from the max */ ctlr->bus_num = id;
mutex_lock(&board_lock);
id = idr_alloc(&spi_master_idr, ctlr, ctlr->bus_num,
ctlr->bus_num + 1, GFP_KERNEL);
mutex_unlock(&board_lock);
if (WARN(id < 0, "couldn't get idr"))
return id == -ENOSPC ? -EBUSY : id;
}
}
if (ctlr->bus_num < 0) { if (ctlr->bus_num < 0) {
/* FIXME switch to an IDR based scheme, something like mutex_lock(&board_lock);
* I2C now uses, so we can't run out of "dynamic" IDs id = idr_alloc(&spi_master_idr, ctlr, SPI_DYN_FIRST_BUS_NUM, 0,
*/ GFP_KERNEL);
ctlr->bus_num = atomic_dec_return(&dyn_bus_id); mutex_unlock(&board_lock);
dynamic = 1; if (WARN(id < 0, "couldn't get idr"))
return id;
ctlr->bus_num = id;
} }
INIT_LIST_HEAD(&ctlr->queue); INIT_LIST_HEAD(&ctlr->queue);
spin_lock_init(&ctlr->queue_lock); spin_lock_init(&ctlr->queue_lock);
spin_lock_init(&ctlr->bus_lock_spinlock); spin_lock_init(&ctlr->bus_lock_spinlock);
...@@ -2100,11 +2107,16 @@ int spi_register_controller(struct spi_controller *ctlr) ...@@ -2100,11 +2107,16 @@ int spi_register_controller(struct spi_controller *ctlr)
*/ */
dev_set_name(&ctlr->dev, "spi%u", ctlr->bus_num); dev_set_name(&ctlr->dev, "spi%u", ctlr->bus_num);
status = device_add(&ctlr->dev); status = device_add(&ctlr->dev);
if (status < 0) if (status < 0) {
/* free bus id */
mutex_lock(&board_lock);
idr_remove(&spi_master_idr, ctlr->bus_num);
mutex_unlock(&board_lock);
goto done; goto done;
dev_dbg(dev, "registered %s %s%s\n", }
dev_dbg(dev, "registered %s %s\n",
spi_controller_is_slave(ctlr) ? "slave" : "master", spi_controller_is_slave(ctlr) ? "slave" : "master",
dev_name(&ctlr->dev), dynamic ? " (dynamic)" : ""); dev_name(&ctlr->dev));
/* If we're using a queued driver, start the queue */ /* If we're using a queued driver, start the queue */
if (ctlr->transfer) if (ctlr->transfer)
...@@ -2113,6 +2125,10 @@ int spi_register_controller(struct spi_controller *ctlr) ...@@ -2113,6 +2125,10 @@ int spi_register_controller(struct spi_controller *ctlr)
status = spi_controller_initialize_queue(ctlr); status = spi_controller_initialize_queue(ctlr);
if (status) { if (status) {
device_del(&ctlr->dev); device_del(&ctlr->dev);
/* free bus id */
mutex_lock(&board_lock);
idr_remove(&spi_master_idr, ctlr->bus_num);
mutex_unlock(&board_lock);
goto done; goto done;
} }
} }
...@@ -2191,19 +2207,33 @@ static int __unregister(struct device *dev, void *null) ...@@ -2191,19 +2207,33 @@ static int __unregister(struct device *dev, void *null)
*/ */
void spi_unregister_controller(struct spi_controller *ctlr) void spi_unregister_controller(struct spi_controller *ctlr)
{ {
struct spi_controller *found;
int dummy; int dummy;
/* First make sure that this controller was ever added */
mutex_lock(&board_lock);
found = idr_find(&spi_master_idr, ctlr->bus_num);
mutex_unlock(&board_lock);
if (found != ctlr) {
dev_dbg(&ctlr->dev,
"attempting to delete unregistered controller [%s]\n",
dev_name(&ctlr->dev));
return;
}
if (ctlr->queued) { if (ctlr->queued) {
if (spi_destroy_queue(ctlr)) if (spi_destroy_queue(ctlr))
dev_err(&ctlr->dev, "queue remove failed\n"); dev_err(&ctlr->dev, "queue remove failed\n");
} }
mutex_lock(&board_lock); mutex_lock(&board_lock);
list_del(&ctlr->list); list_del(&ctlr->list);
mutex_unlock(&board_lock); mutex_unlock(&board_lock);
dummy = device_for_each_child(&ctlr->dev, NULL, __unregister); dummy = device_for_each_child(&ctlr->dev, NULL, __unregister);
device_unregister(&ctlr->dev); device_unregister(&ctlr->dev);
/* free bus id */
mutex_lock(&board_lock);
idr_remove(&spi_master_idr, ctlr->bus_num);
mutex_unlock(&board_lock);
} }
EXPORT_SYMBOL_GPL(spi_unregister_controller); EXPORT_SYMBOL_GPL(spi_unregister_controller);
...@@ -3311,8 +3341,8 @@ static int of_spi_notify(struct notifier_block *nb, unsigned long action, ...@@ -3311,8 +3341,8 @@ static int of_spi_notify(struct notifier_block *nb, unsigned long action,
put_device(&ctlr->dev); put_device(&ctlr->dev);
if (IS_ERR(spi)) { if (IS_ERR(spi)) {
pr_err("%s: failed to create for '%s'\n", pr_err("%s: failed to create for '%pOF'\n",
__func__, rd->dn->full_name); __func__, rd->dn);
of_node_clear_flag(rd->dn, OF_POPULATED); of_node_clear_flag(rd->dn, OF_POPULATED);
return notifier_from_errno(PTR_ERR(spi)); return notifier_from_errno(PTR_ERR(spi));
} }
......
...@@ -90,7 +90,7 @@ kvm_stat: FORCE ...@@ -90,7 +90,7 @@ kvm_stat: FORCE
$(call descend,kvm/$@) $(call descend,kvm/$@)
all: acpi cgroup cpupower gpio hv firewire liblockdep \ all: acpi cgroup cpupower gpio hv firewire liblockdep \
perf selftests turbostat usb \ perf selftests spi turbostat usb \
virtio vm net x86_energy_perf_policy \ virtio vm net x86_energy_perf_policy \
tmon freefall iio objtool kvm_stat tmon freefall iio objtool kvm_stat
...@@ -100,7 +100,7 @@ acpi_install: ...@@ -100,7 +100,7 @@ acpi_install:
cpupower_install: cpupower_install:
$(call descend,power/$(@:_install=),install) $(call descend,power/$(@:_install=),install)
cgroup_install firewire_install gpio_install hv_install iio_install perf_install usb_install virtio_install vm_install net_install objtool_install: cgroup_install firewire_install gpio_install hv_install iio_install perf_install spi_install usb_install virtio_install vm_install net_install objtool_install:
$(call descend,$(@:_install=),install) $(call descend,$(@:_install=),install)
liblockdep_install: liblockdep_install:
......
spidev_test-y += spidev_test.o
spidev_fdx-y += spidev_fdx.o
include ../scripts/Makefile.include
bindir ?= /usr/bin
ifeq ($(srctree),)
srctree := $(patsubst %/,%,$(dir $(CURDIR)))
srctree := $(patsubst %/,%,$(dir $(srctree)))
endif
# Do not use make's built-in rules
# (this improves performance and avoids hard-to-debug behaviour);
MAKEFLAGS += -r
CC = $(CROSS_COMPILE)gcc CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include
ALL_TARGETS := spidev_test spidev_fdx
ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS))
all: $(ALL_PROGRAMS)
export srctree OUTPUT CC LD CFLAGS
include $(srctree)/tools/build/Makefile.include
all: spidev_test spidev_fdx #
# We need the following to be outside of kernel tree
#
$(OUTPUT)include/linux/spi/spidev.h: ../../include/uapi/linux/spi/spidev.h
mkdir -p $(OUTPUT)include/linux/spi 2>&1 || true
ln -sf $(CURDIR)/../../include/uapi/linux/spi/spidev.h $@
prepare: $(OUTPUT)include/linux/spi/spidev.h
#
# spidev_test
#
SPIDEV_TEST_IN := $(OUTPUT)spidev_test-in.o
$(SPIDEV_TEST_IN): prepare FORCE
$(Q)$(MAKE) $(build)=spidev_test
$(OUTPUT)spidev_test: $(SPIDEV_TEST_IN)
$(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
#
# spidev_fdx
#
SPIDEV_FDX_IN := $(OUTPUT)spidev_fdx-in.o
$(SPIDEV_FDX_IN): prepare FORCE
$(Q)$(MAKE) $(build)=spidev_fdx
$(OUTPUT)spidev_fdx: $(SPIDEV_FDX_IN)
$(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
clean: clean:
$(RM) spidev_test spidev_fdx rm -f $(ALL_PROGRAMS)
rm -f $(OUTPUT)include/linux/spi/spidev.h
find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete
install: $(ALL_PROGRAMS)
install -d -m 755 $(DESTDIR)$(bindir); \
for program in $(ALL_PROGRAMS); do \
install $$program $(DESTDIR)$(bindir); \
done
FORCE:
.PHONY: all install clean FORCE prepare
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