Commit 6e695472 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'spi/topic/imx', 'spi/topic/mxs',...

Merge remote-tracking branches 'spi/topic/imx', 'spi/topic/mxs', 'spi/topic/orion', 'spi/topic/rspi' and 'spi/topic/s3c64xx' into spi-next
...@@ -5,11 +5,14 @@ Required properties: ...@@ -5,11 +5,14 @@ Required properties:
"renesas,rspi-<soctype>", "renesas,rspi" as fallback. "renesas,rspi-<soctype>", "renesas,rspi" as fallback.
For Renesas Serial Peripheral Interface on RZ/A1H: For Renesas Serial Peripheral Interface on RZ/A1H:
"renesas,rspi-<soctype>", "renesas,rspi-rz" as fallback. "renesas,rspi-<soctype>", "renesas,rspi-rz" as fallback.
For Quad Serial Peripheral Interface on R-Car Gen2: For Quad Serial Peripheral Interface on R-Car Gen2 and
RZ/G1 devices:
"renesas,qspi-<soctype>", "renesas,qspi" as fallback. "renesas,qspi-<soctype>", "renesas,qspi" as fallback.
Examples with soctypes are: Examples with soctypes are:
- "renesas,rspi-sh7757" (SH) - "renesas,rspi-sh7757" (SH)
- "renesas,rspi-r7s72100" (RZ/A1H) - "renesas,rspi-r7s72100" (RZ/A1H)
- "renesas,qspi-r8a7743" (RZ/G1M)
- "renesas,qspi-r8a7745" (RZ/G1E)
- "renesas,qspi-r8a7790" (R-Car H2) - "renesas,qspi-r8a7790" (R-Car H2)
- "renesas,qspi-r8a7791" (R-Car M2-W) - "renesas,qspi-r8a7791" (R-Car M2-W)
- "renesas,qspi-r8a7792" (R-Car V2H) - "renesas,qspi-r8a7792" (R-Car V2H)
......
...@@ -53,10 +53,13 @@ ...@@ -53,10 +53,13 @@
/* generic defines to abstract from the different register layouts */ /* generic defines to abstract from the different register layouts */
#define MXC_INT_RR (1 << 0) /* Receive data ready interrupt */ #define MXC_INT_RR (1 << 0) /* Receive data ready interrupt */
#define MXC_INT_TE (1 << 1) /* Transmit FIFO empty interrupt */ #define MXC_INT_TE (1 << 1) /* Transmit FIFO empty interrupt */
#define MXC_INT_RDR BIT(4) /* Receive date threshold interrupt */
/* The maximum bytes that a sdma BD can transfer.*/ /* The maximum bytes that a sdma BD can transfer.*/
#define MAX_SDMA_BD_BYTES (1 << 15) #define MAX_SDMA_BD_BYTES (1 << 15)
#define MX51_ECSPI_CTRL_MAX_BURST 512 #define MX51_ECSPI_CTRL_MAX_BURST 512
/* The maximum bytes that IMX53_ECSPI can transfer in slave mode.*/
#define MX53_MAX_TRANSFER_BYTES 512
enum spi_imx_devtype { enum spi_imx_devtype {
IMX1_CSPI, IMX1_CSPI,
...@@ -76,7 +79,9 @@ struct spi_imx_devtype_data { ...@@ -76,7 +79,9 @@ struct spi_imx_devtype_data {
void (*trigger)(struct spi_imx_data *); void (*trigger)(struct spi_imx_data *);
int (*rx_available)(struct spi_imx_data *); int (*rx_available)(struct spi_imx_data *);
void (*reset)(struct spi_imx_data *); void (*reset)(struct spi_imx_data *);
void (*disable)(struct spi_imx_data *);
bool has_dmamode; bool has_dmamode;
bool has_slavemode;
unsigned int fifo_size; unsigned int fifo_size;
bool dynamic_burst; bool dynamic_burst;
enum spi_imx_devtype devtype; enum spi_imx_devtype devtype;
...@@ -108,6 +113,11 @@ struct spi_imx_data { ...@@ -108,6 +113,11 @@ struct spi_imx_data {
unsigned int dynamic_burst, read_u32; unsigned int dynamic_burst, read_u32;
unsigned int word_mask; unsigned int word_mask;
/* Slave mode */
bool slave_mode;
bool slave_aborted;
unsigned int slave_burst;
/* DMA */ /* DMA */
bool usedma; bool usedma;
u32 wml; u32 wml;
...@@ -221,6 +231,9 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, ...@@ -221,6 +231,9 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
if (!master->dma_rx) if (!master->dma_rx)
return false; return false;
if (spi_imx->slave_mode)
return false;
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) if (bytes_per_word != 1 && bytes_per_word != 2 && bytes_per_word != 4)
...@@ -262,6 +275,7 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, ...@@ -262,6 +275,7 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
#define MX51_ECSPI_INT 0x10 #define MX51_ECSPI_INT 0x10
#define MX51_ECSPI_INT_TEEN (1 << 0) #define MX51_ECSPI_INT_TEEN (1 << 0)
#define MX51_ECSPI_INT_RREN (1 << 3) #define MX51_ECSPI_INT_RREN (1 << 3)
#define MX51_ECSPI_INT_RDREN (1 << 4)
#define MX51_ECSPI_DMA 0x14 #define MX51_ECSPI_DMA 0x14
#define MX51_ECSPI_DMA_TX_WML(wml) ((wml) & 0x3f) #define MX51_ECSPI_DMA_TX_WML(wml) ((wml) & 0x3f)
...@@ -378,6 +392,44 @@ static void spi_imx_buf_tx_swap(struct spi_imx_data *spi_imx) ...@@ -378,6 +392,44 @@ static void spi_imx_buf_tx_swap(struct spi_imx_data *spi_imx)
spi_imx_buf_tx_u16(spi_imx); spi_imx_buf_tx_u16(spi_imx);
} }
static void mx53_ecspi_rx_slave(struct spi_imx_data *spi_imx)
{
u32 val = be32_to_cpu(readl(spi_imx->base + MXC_CSPIRXDATA));
if (spi_imx->rx_buf) {
int n_bytes = spi_imx->slave_burst % sizeof(val);
if (!n_bytes)
n_bytes = sizeof(val);
memcpy(spi_imx->rx_buf,
((u8 *)&val) + sizeof(val) - n_bytes, n_bytes);
spi_imx->rx_buf += n_bytes;
spi_imx->slave_burst -= n_bytes;
}
}
static void mx53_ecspi_tx_slave(struct spi_imx_data *spi_imx)
{
u32 val = 0;
int n_bytes = spi_imx->count % sizeof(val);
if (!n_bytes)
n_bytes = sizeof(val);
if (spi_imx->tx_buf) {
memcpy(((u8 *)&val) + sizeof(val) - n_bytes,
spi_imx->tx_buf, n_bytes);
val = cpu_to_be32(val);
spi_imx->tx_buf += n_bytes;
}
spi_imx->count -= n_bytes;
writel(val, spi_imx->base + MXC_CSPITXDATA);
}
/* MX51 eCSPI */ /* MX51 eCSPI */
static unsigned int mx51_ecspi_clkdiv(struct spi_imx_data *spi_imx, static unsigned int mx51_ecspi_clkdiv(struct spi_imx_data *spi_imx,
unsigned int fspi, unsigned int *fres) unsigned int fspi, unsigned int *fres)
...@@ -427,6 +479,9 @@ static void mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int enable) ...@@ -427,6 +479,9 @@ static void mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int enable)
if (enable & MXC_INT_RR) if (enable & MXC_INT_RR)
val |= MX51_ECSPI_INT_RREN; val |= MX51_ECSPI_INT_RREN;
if (enable & MXC_INT_RDR)
val |= MX51_ECSPI_INT_RDREN;
writel(val, spi_imx->base + MX51_ECSPI_INT); writel(val, spi_imx->base + MX51_ECSPI_INT);
} }
...@@ -439,6 +494,15 @@ static void mx51_ecspi_trigger(struct spi_imx_data *spi_imx) ...@@ -439,6 +494,15 @@ static void mx51_ecspi_trigger(struct spi_imx_data *spi_imx)
writel(reg, spi_imx->base + MX51_ECSPI_CTRL); writel(reg, spi_imx->base + MX51_ECSPI_CTRL);
} }
static void mx51_ecspi_disable(struct spi_imx_data *spi_imx)
{
u32 ctrl;
ctrl = readl(spi_imx->base + MX51_ECSPI_CTRL);
ctrl &= ~MX51_ECSPI_CTRL_ENABLE;
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
}
static int mx51_ecspi_config(struct spi_device *spi) static int mx51_ecspi_config(struct spi_device *spi)
{ {
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
...@@ -446,14 +510,11 @@ static int mx51_ecspi_config(struct spi_device *spi) ...@@ -446,14 +510,11 @@ static int mx51_ecspi_config(struct spi_device *spi)
u32 clk = spi_imx->speed_hz, delay, reg; u32 clk = spi_imx->speed_hz, delay, reg;
u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG); u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
/* /* set Master or Slave mode */
* The hardware seems to have a race condition when changing modes. The if (spi_imx->slave_mode)
* current assumption is that the selection of the channel arrives ctrl &= ~MX51_ECSPI_CTRL_MODE_MASK;
* earlier in the hardware than the mode bits when they are written at else
* the same time. ctrl |= MX51_ECSPI_CTRL_MODE_MASK;
* So set master mode for all channels as we do not support slave mode.
*/
ctrl |= MX51_ECSPI_CTRL_MODE_MASK;
/* /*
* Enable SPI_RDY handling (falling edge/level triggered). * Enable SPI_RDY handling (falling edge/level triggered).
...@@ -468,9 +529,22 @@ static int mx51_ecspi_config(struct spi_device *spi) ...@@ -468,9 +529,22 @@ static int mx51_ecspi_config(struct spi_device *spi)
/* set chip select to use */ /* set chip select to use */
ctrl |= MX51_ECSPI_CTRL_CS(spi->chip_select); ctrl |= MX51_ECSPI_CTRL_CS(spi->chip_select);
ctrl |= (spi_imx->bits_per_word - 1) << MX51_ECSPI_CTRL_BL_OFFSET; if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx))
ctrl |= (spi_imx->slave_burst * 8 - 1)
<< MX51_ECSPI_CTRL_BL_OFFSET;
else
ctrl |= (spi_imx->bits_per_word - 1)
<< MX51_ECSPI_CTRL_BL_OFFSET;
cfg |= MX51_ECSPI_CONFIG_SBBCTRL(spi->chip_select); /*
* eCSPI burst completion by Chip Select signal in Slave mode
* is not functional for imx53 Soc, config SPI burst completed when
* BURST_LENGTH + 1 bits are received
*/
if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx))
cfg &= ~MX51_ECSPI_CONFIG_SBBCTRL(spi->chip_select);
else
cfg |= MX51_ECSPI_CONFIG_SBBCTRL(spi->chip_select);
if (spi->mode & SPI_CPHA) if (spi->mode & SPI_CPHA)
cfg |= MX51_ECSPI_CONFIG_SCLKPHA(spi->chip_select); cfg |= MX51_ECSPI_CONFIG_SCLKPHA(spi->chip_select);
...@@ -805,6 +879,7 @@ static struct spi_imx_devtype_data imx1_cspi_devtype_data = { ...@@ -805,6 +879,7 @@ static struct spi_imx_devtype_data imx1_cspi_devtype_data = {
.fifo_size = 8, .fifo_size = 8,
.has_dmamode = false, .has_dmamode = false,
.dynamic_burst = false, .dynamic_burst = false,
.has_slavemode = false,
.devtype = IMX1_CSPI, .devtype = IMX1_CSPI,
}; };
...@@ -817,6 +892,7 @@ static struct spi_imx_devtype_data imx21_cspi_devtype_data = { ...@@ -817,6 +892,7 @@ static struct spi_imx_devtype_data imx21_cspi_devtype_data = {
.fifo_size = 8, .fifo_size = 8,
.has_dmamode = false, .has_dmamode = false,
.dynamic_burst = false, .dynamic_burst = false,
.has_slavemode = false,
.devtype = IMX21_CSPI, .devtype = IMX21_CSPI,
}; };
...@@ -830,6 +906,7 @@ static struct spi_imx_devtype_data imx27_cspi_devtype_data = { ...@@ -830,6 +906,7 @@ static struct spi_imx_devtype_data imx27_cspi_devtype_data = {
.fifo_size = 8, .fifo_size = 8,
.has_dmamode = false, .has_dmamode = false,
.dynamic_burst = false, .dynamic_burst = false,
.has_slavemode = false,
.devtype = IMX27_CSPI, .devtype = IMX27_CSPI,
}; };
...@@ -842,6 +919,7 @@ static struct spi_imx_devtype_data imx31_cspi_devtype_data = { ...@@ -842,6 +919,7 @@ static struct spi_imx_devtype_data imx31_cspi_devtype_data = {
.fifo_size = 8, .fifo_size = 8,
.has_dmamode = false, .has_dmamode = false,
.dynamic_burst = false, .dynamic_burst = false,
.has_slavemode = false,
.devtype = IMX31_CSPI, .devtype = IMX31_CSPI,
}; };
...@@ -855,6 +933,7 @@ static struct spi_imx_devtype_data imx35_cspi_devtype_data = { ...@@ -855,6 +933,7 @@ static struct spi_imx_devtype_data imx35_cspi_devtype_data = {
.fifo_size = 8, .fifo_size = 8,
.has_dmamode = true, .has_dmamode = true,
.dynamic_burst = false, .dynamic_burst = false,
.has_slavemode = false,
.devtype = IMX35_CSPI, .devtype = IMX35_CSPI,
}; };
...@@ -867,6 +946,8 @@ static struct spi_imx_devtype_data imx51_ecspi_devtype_data = { ...@@ -867,6 +946,8 @@ static struct spi_imx_devtype_data imx51_ecspi_devtype_data = {
.fifo_size = 64, .fifo_size = 64,
.has_dmamode = true, .has_dmamode = true,
.dynamic_burst = true, .dynamic_burst = true,
.has_slavemode = true,
.disable = mx51_ecspi_disable,
.devtype = IMX51_ECSPI, .devtype = IMX51_ECSPI,
}; };
...@@ -878,6 +959,8 @@ static struct spi_imx_devtype_data imx53_ecspi_devtype_data = { ...@@ -878,6 +959,8 @@ static struct spi_imx_devtype_data imx53_ecspi_devtype_data = {
.reset = mx51_ecspi_reset, .reset = mx51_ecspi_reset,
.fifo_size = 64, .fifo_size = 64,
.has_dmamode = true, .has_dmamode = true,
.has_slavemode = true,
.disable = mx51_ecspi_disable,
.devtype = IMX53_ECSPI, .devtype = IMX53_ECSPI,
}; };
...@@ -945,14 +1028,16 @@ static void spi_imx_push(struct spi_imx_data *spi_imx) ...@@ -945,14 +1028,16 @@ static void spi_imx_push(struct spi_imx_data *spi_imx)
spi_imx->txfifo++; spi_imx->txfifo++;
} }
spi_imx->devtype_data->trigger(spi_imx); if (!spi_imx->slave_mode)
spi_imx->devtype_data->trigger(spi_imx);
} }
static irqreturn_t spi_imx_isr(int irq, void *dev_id) static irqreturn_t spi_imx_isr(int irq, void *dev_id)
{ {
struct spi_imx_data *spi_imx = dev_id; struct spi_imx_data *spi_imx = dev_id;
while (spi_imx->devtype_data->rx_available(spi_imx)) { while (spi_imx->txfifo &&
spi_imx->devtype_data->rx_available(spi_imx)) {
spi_imx->rx(spi_imx); spi_imx->rx(spi_imx);
spi_imx->txfifo--; spi_imx->txfifo--;
} }
...@@ -1034,7 +1119,7 @@ static int spi_imx_setupxfer(struct spi_device *spi, ...@@ -1034,7 +1119,7 @@ static int spi_imx_setupxfer(struct spi_device *spi,
spi_imx->speed_hz = t->speed_hz; spi_imx->speed_hz = t->speed_hz;
/* Initialize the functions for transfer */ /* Initialize the functions for transfer */
if (spi_imx->devtype_data->dynamic_burst) { if (spi_imx->devtype_data->dynamic_burst && !spi_imx->slave_mode) {
u32 mask; u32 mask;
spi_imx->dynamic_burst = 0; spi_imx->dynamic_burst = 0;
...@@ -1078,6 +1163,12 @@ static int spi_imx_setupxfer(struct spi_device *spi, ...@@ -1078,6 +1163,12 @@ static int spi_imx_setupxfer(struct spi_device *spi,
return ret; return ret;
} }
if (is_imx53_ecspi(spi_imx) && spi_imx->slave_mode) {
spi_imx->rx = mx53_ecspi_rx_slave;
spi_imx->tx = mx53_ecspi_tx_slave;
spi_imx->slave_burst = t->len;
}
spi_imx->devtype_data->config(spi); spi_imx->devtype_data->config(spi);
return 0; return 0;
...@@ -1262,11 +1353,61 @@ static int spi_imx_pio_transfer(struct spi_device *spi, ...@@ -1262,11 +1353,61 @@ static int spi_imx_pio_transfer(struct spi_device *spi,
return transfer->len; return transfer->len;
} }
static int spi_imx_pio_transfer_slave(struct spi_device *spi,
struct spi_transfer *transfer)
{
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
int ret = transfer->len;
if (is_imx53_ecspi(spi_imx) &&
transfer->len > MX53_MAX_TRANSFER_BYTES) {
dev_err(&spi->dev, "Transaction too big, max size is %d bytes\n",
MX53_MAX_TRANSFER_BYTES);
return -EMSGSIZE;
}
spi_imx->tx_buf = transfer->tx_buf;
spi_imx->rx_buf = transfer->rx_buf;
spi_imx->count = transfer->len;
spi_imx->txfifo = 0;
reinit_completion(&spi_imx->xfer_done);
spi_imx->slave_aborted = false;
spi_imx_push(spi_imx);
spi_imx->devtype_data->intctrl(spi_imx, MXC_INT_TE | MXC_INT_RDR);
if (wait_for_completion_interruptible(&spi_imx->xfer_done) ||
spi_imx->slave_aborted) {
dev_dbg(&spi->dev, "interrupted\n");
ret = -EINTR;
}
/* ecspi has a HW issue when works in Slave mode,
* after 64 words writtern to TXFIFO, even TXFIFO becomes empty,
* ECSPI_TXDATA keeps shift out the last word data,
* so we have to disable ECSPI when in slave mode after the
* transfer completes
*/
if (spi_imx->devtype_data->disable)
spi_imx->devtype_data->disable(spi_imx);
return ret;
}
static int spi_imx_transfer(struct spi_device *spi, static int spi_imx_transfer(struct spi_device *spi,
struct spi_transfer *transfer) struct spi_transfer *transfer)
{ {
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
/* flush rxfifo before transfer */
while (spi_imx->devtype_data->rx_available(spi_imx))
spi_imx->rx(spi_imx);
if (spi_imx->slave_mode)
return spi_imx_pio_transfer_slave(spi, transfer);
if (spi_imx->usedma) if (spi_imx->usedma)
return spi_imx_dma_transfer(spi_imx, transfer); return spi_imx_dma_transfer(spi_imx, transfer);
else else
...@@ -1323,6 +1464,16 @@ spi_imx_unprepare_message(struct spi_master *master, struct spi_message *msg) ...@@ -1323,6 +1464,16 @@ spi_imx_unprepare_message(struct spi_master *master, struct spi_message *msg)
return 0; return 0;
} }
static int spi_imx_slave_abort(struct spi_master *master)
{
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
spi_imx->slave_aborted = true;
complete(&spi_imx->xfer_done);
return 0;
}
static int spi_imx_probe(struct platform_device *pdev) static int spi_imx_probe(struct platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
...@@ -1334,13 +1485,23 @@ static int spi_imx_probe(struct platform_device *pdev) ...@@ -1334,13 +1485,23 @@ static int spi_imx_probe(struct platform_device *pdev)
struct spi_imx_data *spi_imx; struct spi_imx_data *spi_imx;
struct resource *res; struct resource *res;
int i, ret, irq, spi_drctl; int i, ret, irq, spi_drctl;
const struct spi_imx_devtype_data *devtype_data = of_id ? of_id->data :
(struct spi_imx_devtype_data *)pdev->id_entry->driver_data;
bool slave_mode;
if (!np && !mxc_platform_info) { if (!np && !mxc_platform_info) {
dev_err(&pdev->dev, "can't get the platform data\n"); dev_err(&pdev->dev, "can't get the platform data\n");
return -EINVAL; return -EINVAL;
} }
master = spi_alloc_master(&pdev->dev, sizeof(struct spi_imx_data)); slave_mode = devtype_data->has_slavemode &&
of_property_read_bool(np, "spi-slave");
if (slave_mode)
master = spi_alloc_slave(&pdev->dev,
sizeof(struct spi_imx_data));
else
master = spi_alloc_master(&pdev->dev,
sizeof(struct spi_imx_data));
if (!master) if (!master)
return -ENOMEM; return -ENOMEM;
...@@ -1358,20 +1519,29 @@ static int spi_imx_probe(struct platform_device *pdev) ...@@ -1358,20 +1519,29 @@ static int spi_imx_probe(struct platform_device *pdev)
spi_imx = spi_master_get_devdata(master); spi_imx = spi_master_get_devdata(master);
spi_imx->bitbang.master = master; spi_imx->bitbang.master = master;
spi_imx->dev = &pdev->dev; spi_imx->dev = &pdev->dev;
spi_imx->slave_mode = slave_mode;
spi_imx->devtype_data = of_id ? of_id->data : spi_imx->devtype_data = devtype_data;
(struct spi_imx_devtype_data *)pdev->id_entry->driver_data;
/* Get number of chip selects, either platform data or OF */
if (mxc_platform_info) { if (mxc_platform_info) {
master->num_chipselect = mxc_platform_info->num_chipselect; master->num_chipselect = mxc_platform_info->num_chipselect;
master->cs_gpios = devm_kzalloc(&master->dev, if (mxc_platform_info->chipselect) {
sizeof(int) * master->num_chipselect, GFP_KERNEL); master->cs_gpios = devm_kzalloc(&master->dev,
if (!master->cs_gpios) sizeof(int) * master->num_chipselect, GFP_KERNEL);
return -ENOMEM; if (!master->cs_gpios)
return -ENOMEM;
for (i = 0; i < master->num_chipselect; i++)
master->cs_gpios[i] = mxc_platform_info->chipselect[i];
}
} else {
u32 num_cs;
for (i = 0; i < master->num_chipselect; i++) if (!of_property_read_u32(np, "num-cs", &num_cs))
master->cs_gpios[i] = mxc_platform_info->chipselect[i]; master->num_chipselect = num_cs;
} /* If not preset, default value of 1 is used */
}
spi_imx->bitbang.chipselect = spi_imx_chipselect; spi_imx->bitbang.chipselect = spi_imx_chipselect;
spi_imx->bitbang.setup_transfer = spi_imx_setupxfer; spi_imx->bitbang.setup_transfer = spi_imx_setupxfer;
...@@ -1380,6 +1550,7 @@ static int spi_imx_probe(struct platform_device *pdev) ...@@ -1380,6 +1550,7 @@ static int spi_imx_probe(struct platform_device *pdev)
spi_imx->bitbang.master->cleanup = spi_imx_cleanup; spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message; spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message;
spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message; spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
spi_imx->bitbang.master->slave_abort = spi_imx_slave_abort;
spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \ spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
| SPI_NO_CS; | SPI_NO_CS;
if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx) || if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx) ||
...@@ -1451,37 +1622,38 @@ static int spi_imx_probe(struct platform_device *pdev) ...@@ -1451,37 +1622,38 @@ static int spi_imx_probe(struct platform_device *pdev)
spi_imx->devtype_data->intctrl(spi_imx, 0); spi_imx->devtype_data->intctrl(spi_imx, 0);
master->dev.of_node = pdev->dev.of_node; master->dev.of_node = pdev->dev.of_node;
/* Request GPIO CS lines, if any */
if (!spi_imx->slave_mode && master->cs_gpios) {
for (i = 0; i < master->num_chipselect; i++) {
if (!gpio_is_valid(master->cs_gpios[i]))
continue;
ret = devm_gpio_request(&pdev->dev,
master->cs_gpios[i],
DRIVER_NAME);
if (ret) {
dev_err(&pdev->dev, "Can't get CS GPIO %i\n",
master->cs_gpios[i]);
goto out_spi_bitbang;
}
}
}
ret = spi_bitbang_start(&spi_imx->bitbang); ret = spi_bitbang_start(&spi_imx->bitbang);
if (ret) { if (ret) {
dev_err(&pdev->dev, "bitbang start failed with %d\n", ret); dev_err(&pdev->dev, "bitbang start failed with %d\n", ret);
goto out_clk_put; goto out_clk_put;
} }
if (!master->cs_gpios) {
dev_err(&pdev->dev, "No CS GPIOs available\n");
ret = -EINVAL;
goto out_clk_put;
}
for (i = 0; i < master->num_chipselect; i++) {
if (!gpio_is_valid(master->cs_gpios[i]))
continue;
ret = devm_gpio_request(&pdev->dev, master->cs_gpios[i],
DRIVER_NAME);
if (ret) {
dev_err(&pdev->dev, "Can't get CS GPIO %i\n",
master->cs_gpios[i]);
goto out_clk_put;
}
}
dev_info(&pdev->dev, "probed\n"); dev_info(&pdev->dev, "probed\n");
clk_disable(spi_imx->clk_ipg); clk_disable(spi_imx->clk_ipg);
clk_disable(spi_imx->clk_per); clk_disable(spi_imx->clk_per);
return ret; return ret;
out_spi_bitbang:
spi_bitbang_stop(&spi_imx->bitbang);
out_clk_put: out_clk_put:
clk_disable_unprepare(spi_imx->clk_ipg); clk_disable_unprepare(spi_imx->clk_ipg);
out_put_per: out_put_per:
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/stmp_device.h> #include <linux/stmp_device.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
...@@ -442,6 +443,85 @@ static int mxs_spi_transfer_one(struct spi_master *master, ...@@ -442,6 +443,85 @@ static int mxs_spi_transfer_one(struct spi_master *master,
return status; return status;
} }
static int mxs_spi_runtime_suspend(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
struct mxs_spi *spi = spi_master_get_devdata(master);
struct mxs_ssp *ssp = &spi->ssp;
int ret;
clk_disable_unprepare(ssp->clk);
ret = pinctrl_pm_select_idle_state(dev);
if (ret) {
int ret2 = clk_prepare_enable(ssp->clk);
if (ret2)
dev_warn(dev, "Failed to reenable clock after failing pinctrl request (pinctrl: %d, clk: %d)\n",
ret, ret2);
}
return ret;
}
static int mxs_spi_runtime_resume(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
struct mxs_spi *spi = spi_master_get_devdata(master);
struct mxs_ssp *ssp = &spi->ssp;
int ret;
ret = pinctrl_pm_select_default_state(dev);
if (ret)
return ret;
ret = clk_prepare_enable(ssp->clk);
if (ret)
pinctrl_pm_select_idle_state(dev);
return ret;
}
static int __maybe_unused mxs_spi_suspend(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
int ret;
ret = spi_master_suspend(master);
if (ret)
return ret;
if (!pm_runtime_suspended(dev))
return mxs_spi_runtime_suspend(dev);
else
return 0;
}
static int __maybe_unused mxs_spi_resume(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
int ret;
if (!pm_runtime_suspended(dev))
ret = mxs_spi_runtime_resume(dev);
else
ret = 0;
if (ret)
return ret;
ret = spi_master_resume(master);
if (ret < 0 && !pm_runtime_suspended(dev))
mxs_spi_runtime_suspend(dev);
return ret;
}
static const struct dev_pm_ops mxs_spi_pm = {
SET_RUNTIME_PM_OPS(mxs_spi_runtime_suspend,
mxs_spi_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(mxs_spi_suspend, mxs_spi_resume)
};
static const struct of_device_id mxs_spi_dt_ids[] = { static const struct of_device_id mxs_spi_dt_ids[] = {
{ .compatible = "fsl,imx23-spi", .data = (void *) IMX23_SSP, }, { .compatible = "fsl,imx23-spi", .data = (void *) IMX23_SSP, },
{ .compatible = "fsl,imx28-spi", .data = (void *) IMX28_SSP, }, { .compatible = "fsl,imx28-spi", .data = (void *) IMX28_SSP, },
...@@ -493,12 +573,15 @@ static int mxs_spi_probe(struct platform_device *pdev) ...@@ -493,12 +573,15 @@ static int mxs_spi_probe(struct platform_device *pdev)
if (!master) if (!master)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(pdev, master);
master->transfer_one_message = mxs_spi_transfer_one; master->transfer_one_message = mxs_spi_transfer_one;
master->bits_per_word_mask = SPI_BPW_MASK(8); master->bits_per_word_mask = SPI_BPW_MASK(8);
master->mode_bits = SPI_CPOL | SPI_CPHA; master->mode_bits = SPI_CPOL | SPI_CPHA;
master->num_chipselect = 3; master->num_chipselect = 3;
master->dev.of_node = np; master->dev.of_node = np;
master->flags = SPI_MASTER_HALF_DUPLEX; master->flags = SPI_MASTER_HALF_DUPLEX;
master->auto_runtime_pm = true;
spi = spi_master_get_devdata(master); spi = spi_master_get_devdata(master);
ssp = &spi->ssp; ssp = &spi->ssp;
...@@ -521,28 +604,41 @@ static int mxs_spi_probe(struct platform_device *pdev) ...@@ -521,28 +604,41 @@ static int mxs_spi_probe(struct platform_device *pdev)
goto out_master_free; goto out_master_free;
} }
ret = clk_prepare_enable(ssp->clk); pm_runtime_enable(ssp->dev);
if (ret) if (!pm_runtime_enabled(ssp->dev)) {
goto out_dma_release; ret = mxs_spi_runtime_resume(ssp->dev);
if (ret < 0) {
dev_err(ssp->dev, "runtime resume failed\n");
goto out_dma_release;
}
}
ret = pm_runtime_get_sync(ssp->dev);
if (ret < 0) {
dev_err(ssp->dev, "runtime_get_sync failed\n");
goto out_pm_runtime_disable;
}
clk_set_rate(ssp->clk, clk_freq); clk_set_rate(ssp->clk, clk_freq);
ret = stmp_reset_block(ssp->base); ret = stmp_reset_block(ssp->base);
if (ret) if (ret)
goto out_disable_clk; goto out_pm_runtime_put;
platform_set_drvdata(pdev, master);
ret = devm_spi_register_master(&pdev->dev, master); ret = devm_spi_register_master(&pdev->dev, master);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Cannot register SPI master, %d\n", ret); dev_err(&pdev->dev, "Cannot register SPI master, %d\n", ret);
goto out_disable_clk; goto out_pm_runtime_put;
} }
pm_runtime_put(ssp->dev);
return 0; return 0;
out_disable_clk: out_pm_runtime_put:
clk_disable_unprepare(ssp->clk); pm_runtime_put(ssp->dev);
out_pm_runtime_disable:
pm_runtime_disable(ssp->dev);
out_dma_release: out_dma_release:
dma_release_channel(ssp->dmach); dma_release_channel(ssp->dmach);
out_master_free: out_master_free:
...@@ -560,7 +656,10 @@ static int mxs_spi_remove(struct platform_device *pdev) ...@@ -560,7 +656,10 @@ static int mxs_spi_remove(struct platform_device *pdev)
spi = spi_master_get_devdata(master); spi = spi_master_get_devdata(master);
ssp = &spi->ssp; ssp = &spi->ssp;
clk_disable_unprepare(ssp->clk); pm_runtime_disable(&pdev->dev);
if (!pm_runtime_status_suspended(&pdev->dev))
mxs_spi_runtime_suspend(&pdev->dev);
dma_release_channel(ssp->dmach); dma_release_channel(ssp->dmach);
return 0; return 0;
...@@ -572,6 +671,7 @@ static struct platform_driver mxs_spi_driver = { ...@@ -572,6 +671,7 @@ static struct platform_driver mxs_spi_driver = {
.driver = { .driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.of_match_table = mxs_spi_dt_ids, .of_match_table = mxs_spi_dt_ids,
.pm = &mxs_spi_pm,
}, },
}; };
......
...@@ -671,7 +671,6 @@ static int orion_spi_probe(struct platform_device *pdev) ...@@ -671,7 +671,6 @@ static int orion_spi_probe(struct platform_device *pdev)
dev_err(&pdev->dev, dev_err(&pdev->dev,
"%pOF has no valid 'reg' property (%d)\n", "%pOF has no valid 'reg' property (%d)\n",
np, status); np, status);
status = 0;
continue; continue;
} }
......
...@@ -1221,7 +1221,6 @@ static int rspi_probe(struct platform_device *pdev) ...@@ -1221,7 +1221,6 @@ static int rspi_probe(struct platform_device *pdev)
struct spi_master *master; struct spi_master *master;
struct rspi_data *rspi; struct rspi_data *rspi;
int ret; int ret;
const struct of_device_id *of_id;
const struct rspi_plat_data *rspi_pd; const struct rspi_plat_data *rspi_pd;
const struct spi_ops *ops; const struct spi_ops *ops;
...@@ -1229,9 +1228,8 @@ static int rspi_probe(struct platform_device *pdev) ...@@ -1229,9 +1228,8 @@ static int rspi_probe(struct platform_device *pdev)
if (master == NULL) if (master == NULL)
return -ENOMEM; return -ENOMEM;
of_id = of_match_device(rspi_of_match, &pdev->dev); ops = of_device_get_match_data(&pdev->dev);
if (of_id) { if (ops) {
ops = of_id->data;
ret = rspi_parse_dt(&pdev->dev, master); ret = rspi_parse_dt(&pdev->dev, master);
if (ret) if (ret)
goto error1; goto error1;
......
...@@ -752,7 +752,6 @@ static int s3c64xx_spi_setup(struct spi_device *spi) ...@@ -752,7 +752,6 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
{ {
struct s3c64xx_spi_csinfo *cs = spi->controller_data; struct s3c64xx_spi_csinfo *cs = spi->controller_data;
struct s3c64xx_spi_driver_data *sdd; struct s3c64xx_spi_driver_data *sdd;
struct s3c64xx_spi_info *sci;
int err; int err;
sdd = spi_master_get_devdata(spi->master); sdd = spi_master_get_devdata(spi->master);
...@@ -788,8 +787,6 @@ static int s3c64xx_spi_setup(struct spi_device *spi) ...@@ -788,8 +787,6 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
spi_set_ctldata(spi, cs); spi_set_ctldata(spi, cs);
} }
sci = sdd->cntrlr_info;
pm_runtime_get_sync(&sdd->pdev->dev); pm_runtime_get_sync(&sdd->pdev->dev);
/* Check if we can provide the requested rate */ /* Check if we can provide the requested rate */
......
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