summaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-fsl-lpspi.c
diff options
context:
space:
mode:
authorClark Wang <xiaoning.wang@nxp.com>2018-12-06 21:50:36 -0500
committerMark Brown <broonie@kernel.org>2018-12-13 06:57:14 -0500
commitbcd87317aae26b9ac497cbc1232783aaea1aeed4 (patch)
tree3ef7b9fb70ba6f3d9a799b4dab171a21588531cc /drivers/spi/spi-fsl-lpspi.c
parent07d71557494c05b0651def1651bf6d7e7f47bbbb (diff)
spi: lpspi: Add slave mode support
Add slave mode support to the fsl-lpspi driver, only in PIO mode. For now, there are some limitations for slave mode transmission: 1. The stale data in RXFIFO will be dropped when the Slave does any new transfer. 2. One transfer can be finished only after all transfer->len data been transferred to master device 3. Slave device only accepts transfer->len data. Any data longer than this from master device will be dropped. Any data shorter than this from master will cause LPSPI to stuck due to mentioned limitation 2. 4. Only PIO transfer is supported in Slave Mode. Wire connection: GND, SCK, MISO(to MISO of slave), MOSI(to MOSI of slave), SCS Signed-off-by: Clark Wang <xiaoning.wang@nxp.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi/spi-fsl-lpspi.c')
-rw-r--r--drivers/spi/spi-fsl-lpspi.c107
1 files changed, 79 insertions, 28 deletions
diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
index 725d6ac5f814..cbf165e7bd17 100644
--- a/drivers/spi/spi-fsl-lpspi.c
+++ b/drivers/spi/spi-fsl-lpspi.c
@@ -55,6 +55,7 @@
55#define IER_RDIE BIT(1) 55#define IER_RDIE BIT(1)
56#define IER_TDIE BIT(0) 56#define IER_TDIE BIT(0)
57#define CFGR1_PCSCFG BIT(27) 57#define CFGR1_PCSCFG BIT(27)
58#define CFGR1_PINCFG (BIT(24)|BIT(25))
58#define CFGR1_PCSPOL BIT(8) 59#define CFGR1_PCSPOL BIT(8)
59#define CFGR1_NOSTALL BIT(3) 60#define CFGR1_NOSTALL BIT(3)
60#define CFGR1_MASTER BIT(0) 61#define CFGR1_MASTER BIT(0)
@@ -80,6 +81,7 @@ struct fsl_lpspi_data {
80 struct device *dev; 81 struct device *dev;
81 void __iomem *base; 82 void __iomem *base;
82 struct clk *clk; 83 struct clk *clk;
84 bool is_slave;
83 85
84 void *rx_buf; 86 void *rx_buf;
85 const void *tx_buf; 87 const void *tx_buf;
@@ -92,6 +94,8 @@ struct fsl_lpspi_data {
92 94
93 struct lpspi_config config; 95 struct lpspi_config config;
94 struct completion xfer_done; 96 struct completion xfer_done;
97
98 bool slave_aborted;
95}; 99};
96 100
97static const struct of_device_id fsl_lpspi_dt_ids[] = { 101static const struct of_device_id fsl_lpspi_dt_ids[] = {
@@ -206,21 +210,22 @@ static void fsl_lpspi_set_cmd(struct fsl_lpspi_data *fsl_lpspi,
206 u32 temp = 0; 210 u32 temp = 0;
207 211
208 temp |= fsl_lpspi->config.bpw - 1; 212 temp |= fsl_lpspi->config.bpw - 1;
209 temp |= fsl_lpspi->config.prescale << 27;
210 temp |= (fsl_lpspi->config.mode & 0x3) << 30; 213 temp |= (fsl_lpspi->config.mode & 0x3) << 30;
211 temp |= (fsl_lpspi->config.chip_select & 0x3) << 24; 214 if (!fsl_lpspi->is_slave) {
212 215 temp |= fsl_lpspi->config.prescale << 27;
213 /* 216 temp |= (fsl_lpspi->config.chip_select & 0x3) << 24;
214 * Set TCR_CONT will keep SS asserted after current transfer. 217
215 * For the first transfer, clear TCR_CONTC to assert SS. 218 /*
216 * For subsequent transfer, set TCR_CONTC to keep SS asserted. 219 * Set TCR_CONT will keep SS asserted after current transfer.
217 */ 220 * For the first transfer, clear TCR_CONTC to assert SS.
218 temp |= TCR_CONT; 221 * For subsequent transfer, set TCR_CONTC to keep SS asserted.
219 if (is_first_xfer) 222 */
220 temp &= ~TCR_CONTC; 223 temp |= TCR_CONT;
221 else 224 if (is_first_xfer)
222 temp |= TCR_CONTC; 225 temp &= ~TCR_CONTC;
223 226 else
227 temp |= TCR_CONTC;
228 }
224 writel(temp, fsl_lpspi->base + IMX7ULP_TCR); 229 writel(temp, fsl_lpspi->base + IMX7ULP_TCR);
225 230
226 dev_dbg(fsl_lpspi->dev, "TCR=0x%x\n", temp); 231 dev_dbg(fsl_lpspi->dev, "TCR=0x%x\n", temp);
@@ -273,13 +278,18 @@ static int fsl_lpspi_config(struct fsl_lpspi_data *fsl_lpspi)
273 writel(temp, fsl_lpspi->base + IMX7ULP_CR); 278 writel(temp, fsl_lpspi->base + IMX7ULP_CR);
274 writel(0, fsl_lpspi->base + IMX7ULP_CR); 279 writel(0, fsl_lpspi->base + IMX7ULP_CR);
275 280
276 ret = fsl_lpspi_set_bitrate(fsl_lpspi); 281 if (!fsl_lpspi->is_slave) {
277 if (ret) 282 ret = fsl_lpspi_set_bitrate(fsl_lpspi);
278 return ret; 283 if (ret)
284 return ret;
285 }
279 286
280 fsl_lpspi_set_watermark(fsl_lpspi); 287 fsl_lpspi_set_watermark(fsl_lpspi);
281 288
282 temp = CFGR1_PCSCFG | CFGR1_MASTER; 289 if (!fsl_lpspi->is_slave)
290 temp = CFGR1_MASTER;
291 else
292 temp = CFGR1_PINCFG;
283 if (fsl_lpspi->config.mode & SPI_CS_HIGH) 293 if (fsl_lpspi->config.mode & SPI_CS_HIGH)
284 temp |= CFGR1_PCSPOL; 294 temp |= CFGR1_PCSPOL;
285 writel(temp, fsl_lpspi->base + IMX7ULP_CFGR1); 295 writel(temp, fsl_lpspi->base + IMX7ULP_CFGR1);
@@ -322,6 +332,37 @@ static void fsl_lpspi_setup_transfer(struct spi_device *spi,
322 fsl_lpspi_config(fsl_lpspi); 332 fsl_lpspi_config(fsl_lpspi);
323} 333}
324 334
335static int fsl_lpspi_slave_abort(struct spi_controller *controller)
336{
337 struct fsl_lpspi_data *fsl_lpspi =
338 spi_controller_get_devdata(controller);
339
340 fsl_lpspi->slave_aborted = true;
341 complete(&fsl_lpspi->xfer_done);
342 return 0;
343}
344
345static int fsl_lpspi_wait_for_completion(struct spi_controller *controller)
346{
347 struct fsl_lpspi_data *fsl_lpspi =
348 spi_controller_get_devdata(controller);
349
350 if (fsl_lpspi->is_slave) {
351 if (wait_for_completion_interruptible(&fsl_lpspi->xfer_done) ||
352 fsl_lpspi->slave_aborted) {
353 dev_dbg(fsl_lpspi->dev, "interrupted\n");
354 return -EINTR;
355 }
356 } else {
357 if (!wait_for_completion_timeout(&fsl_lpspi->xfer_done, HZ)) {
358 dev_dbg(fsl_lpspi->dev, "wait for completion timeout\n");
359 return -ETIMEDOUT;
360 }
361 }
362
363 return 0;
364}
365
325static int fsl_lpspi_transfer_one(struct spi_controller *controller, 366static int fsl_lpspi_transfer_one(struct spi_controller *controller,
326 struct spi_device *spi, 367 struct spi_device *spi,
327 struct spi_transfer *t) 368 struct spi_transfer *t)
@@ -335,13 +376,13 @@ static int fsl_lpspi_transfer_one(struct spi_controller *controller,
335 fsl_lpspi->remain = t->len; 376 fsl_lpspi->remain = t->len;
336 377
337 reinit_completion(&fsl_lpspi->xfer_done); 378 reinit_completion(&fsl_lpspi->xfer_done);
379 fsl_lpspi->slave_aborted = false;
380
338 fsl_lpspi_write_tx_fifo(fsl_lpspi); 381 fsl_lpspi_write_tx_fifo(fsl_lpspi);
339 382
340 ret = wait_for_completion_timeout(&fsl_lpspi->xfer_done, HZ); 383 ret = fsl_lpspi_wait_for_completion(controller);
341 if (!ret) { 384 if (ret)
342 dev_dbg(fsl_lpspi->dev, "wait for completion timeout\n"); 385 return ret;
343 return -ETIMEDOUT;
344 }
345 386
346 ret = fsl_lpspi_txfifo_empty(fsl_lpspi); 387 ret = fsl_lpspi_txfifo_empty(fsl_lpspi);
347 if (ret) 388 if (ret)
@@ -380,10 +421,12 @@ static int fsl_lpspi_transfer_one_msg(struct spi_controller *controller,
380 } 421 }
381 422
382complete: 423complete:
383 /* de-assert SS, then finalize current message */ 424 if (!fsl_lpspi->is_slave) {
384 temp = readl(fsl_lpspi->base + IMX7ULP_TCR); 425 /* de-assert SS, then finalize current message */
385 temp &= ~TCR_CONTC; 426 temp = readl(fsl_lpspi->base + IMX7ULP_TCR);
386 writel(temp, fsl_lpspi->base + IMX7ULP_TCR); 427 temp &= ~TCR_CONTC;
428 writel(temp, fsl_lpspi->base + IMX7ULP_TCR);
429 }
387 430
388 msg->status = ret; 431 msg->status = ret;
389 spi_finalize_current_message(controller); 432 spi_finalize_current_message(controller);
@@ -421,8 +464,13 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
421 int ret, irq; 464 int ret, irq;
422 u32 temp; 465 u32 temp;
423 466
424 controller = spi_alloc_master(&pdev->dev, 467 if (of_property_read_bool((&pdev->dev)->of_node, "spi-slave"))
468 controller = spi_alloc_slave(&pdev->dev,
469 sizeof(struct fsl_lpspi_data));
470 else
471 controller = spi_alloc_master(&pdev->dev,
425 sizeof(struct fsl_lpspi_data)); 472 sizeof(struct fsl_lpspi_data));
473
426 if (!controller) 474 if (!controller)
427 return -ENOMEM; 475 return -ENOMEM;
428 476
@@ -433,6 +481,8 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
433 481
434 fsl_lpspi = spi_controller_get_devdata(controller); 482 fsl_lpspi = spi_controller_get_devdata(controller);
435 fsl_lpspi->dev = &pdev->dev; 483 fsl_lpspi->dev = &pdev->dev;
484 fsl_lpspi->is_slave = of_property_read_bool((&pdev->dev)->of_node,
485 "spi-slave");
436 486
437 controller->transfer_one_message = fsl_lpspi_transfer_one_msg; 487 controller->transfer_one_message = fsl_lpspi_transfer_one_msg;
438 controller->prepare_transfer_hardware = lpspi_prepare_xfer_hardware; 488 controller->prepare_transfer_hardware = lpspi_prepare_xfer_hardware;
@@ -441,6 +491,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
441 controller->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX; 491 controller->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX;
442 controller->dev.of_node = pdev->dev.of_node; 492 controller->dev.of_node = pdev->dev.of_node;
443 controller->bus_num = pdev->id; 493 controller->bus_num = pdev->id;
494 controller->slave_abort = fsl_lpspi_slave_abort;
444 495
445 init_completion(&fsl_lpspi->xfer_done); 496 init_completion(&fsl_lpspi->xfer_done);
446 497