summaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-fsl-lpspi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi-fsl-lpspi.c')
-rw-r--r--drivers/spi/spi-fsl-lpspi.c92
1 files changed, 48 insertions, 44 deletions
diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
index 08dcc3c22e88..391863914043 100644
--- a/drivers/spi/spi-fsl-lpspi.c
+++ b/drivers/spi/spi-fsl-lpspi.c
@@ -48,10 +48,13 @@
48#define CR_RTF BIT(8) 48#define CR_RTF BIT(8)
49#define CR_RST BIT(1) 49#define CR_RST BIT(1)
50#define CR_MEN BIT(0) 50#define CR_MEN BIT(0)
51#define SR_MBF BIT(24)
51#define SR_TCF BIT(10) 52#define SR_TCF BIT(10)
53#define SR_FCF BIT(9)
52#define SR_RDF BIT(1) 54#define SR_RDF BIT(1)
53#define SR_TDF BIT(0) 55#define SR_TDF BIT(0)
54#define IER_TCIE BIT(10) 56#define IER_TCIE BIT(10)
57#define IER_FCIE BIT(9)
55#define IER_RDIE BIT(1) 58#define IER_RDIE BIT(1)
56#define IER_TDIE BIT(0) 59#define IER_TDIE BIT(0)
57#define CFGR1_PCSCFG BIT(27) 60#define CFGR1_PCSCFG BIT(27)
@@ -59,6 +62,7 @@
59#define CFGR1_PCSPOL BIT(8) 62#define CFGR1_PCSPOL BIT(8)
60#define CFGR1_NOSTALL BIT(3) 63#define CFGR1_NOSTALL BIT(3)
61#define CFGR1_MASTER BIT(0) 64#define CFGR1_MASTER BIT(0)
65#define FSR_RXCOUNT (BIT(16)|BIT(17)|BIT(18))
62#define RSR_RXEMPTY BIT(1) 66#define RSR_RXEMPTY BIT(1)
63#define TCR_CPOL BIT(31) 67#define TCR_CPOL BIT(31)
64#define TCR_CPHA BIT(30) 68#define TCR_CPHA BIT(30)
@@ -161,28 +165,10 @@ static int lpspi_unprepare_xfer_hardware(struct spi_controller *controller)
161 return 0; 165 return 0;
162} 166}
163 167
164static int fsl_lpspi_txfifo_empty(struct fsl_lpspi_data *fsl_lpspi)
165{
166 u32 txcnt;
167 unsigned long orig_jiffies = jiffies;
168
169 do {
170 txcnt = readl(fsl_lpspi->base + IMX7ULP_FSR) & 0xff;
171
172 if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
173 dev_dbg(fsl_lpspi->dev, "txfifo empty timeout\n");
174 return -ETIMEDOUT;
175 }
176 cond_resched();
177
178 } while (txcnt);
179
180 return 0;
181}
182
183static void fsl_lpspi_write_tx_fifo(struct fsl_lpspi_data *fsl_lpspi) 168static void fsl_lpspi_write_tx_fifo(struct fsl_lpspi_data *fsl_lpspi)
184{ 169{
185 u8 txfifo_cnt; 170 u8 txfifo_cnt;
171 u32 temp;
186 172
187 txfifo_cnt = readl(fsl_lpspi->base + IMX7ULP_FSR) & 0xff; 173 txfifo_cnt = readl(fsl_lpspi->base + IMX7ULP_FSR) & 0xff;
188 174
@@ -193,9 +179,15 @@ static void fsl_lpspi_write_tx_fifo(struct fsl_lpspi_data *fsl_lpspi)
193 txfifo_cnt++; 179 txfifo_cnt++;
194 } 180 }
195 181
196 if (!fsl_lpspi->remain && (txfifo_cnt < fsl_lpspi->txfifosize)) 182 if (txfifo_cnt < fsl_lpspi->txfifosize) {
197 writel(0, fsl_lpspi->base + IMX7ULP_TDR); 183 if (!fsl_lpspi->is_slave) {
198 else 184 temp = readl(fsl_lpspi->base + IMX7ULP_TCR);
185 temp &= ~TCR_CONTC;
186 writel(temp, fsl_lpspi->base + IMX7ULP_TCR);
187 }
188
189 fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE);
190 } else
199 fsl_lpspi_intctrl(fsl_lpspi, IER_TDIE); 191 fsl_lpspi_intctrl(fsl_lpspi, IER_TDIE);
200} 192}
201 193
@@ -276,10 +268,6 @@ static int fsl_lpspi_config(struct fsl_lpspi_data *fsl_lpspi)
276 u32 temp; 268 u32 temp;
277 int ret; 269 int ret;
278 270
279 temp = CR_RST;
280 writel(temp, fsl_lpspi->base + IMX7ULP_CR);
281 writel(0, fsl_lpspi->base + IMX7ULP_CR);
282
283 if (!fsl_lpspi->is_slave) { 271 if (!fsl_lpspi->is_slave) {
284 ret = fsl_lpspi_set_bitrate(fsl_lpspi); 272 ret = fsl_lpspi_set_bitrate(fsl_lpspi);
285 if (ret) 273 if (ret)
@@ -370,6 +358,24 @@ static int fsl_lpspi_wait_for_completion(struct spi_controller *controller)
370 return 0; 358 return 0;
371} 359}
372 360
361static int fsl_lpspi_reset(struct fsl_lpspi_data *fsl_lpspi)
362{
363 u32 temp;
364
365 /* Disable all interrupt */
366 fsl_lpspi_intctrl(fsl_lpspi, 0);
367
368 /* W1C for all flags in SR */
369 temp = 0x3F << 8;
370 writel(temp, fsl_lpspi->base + IMX7ULP_SR);
371
372 /* Clear FIFO and disable module */
373 temp = CR_RRF | CR_RTF;
374 writel(temp, fsl_lpspi->base + IMX7ULP_CR);
375
376 return 0;
377}
378
373static int fsl_lpspi_transfer_one(struct spi_controller *controller, 379static int fsl_lpspi_transfer_one(struct spi_controller *controller,
374 struct spi_device *spi, 380 struct spi_device *spi,
375 struct spi_transfer *t) 381 struct spi_transfer *t)
@@ -391,11 +397,7 @@ static int fsl_lpspi_transfer_one(struct spi_controller *controller,
391 if (ret) 397 if (ret)
392 return ret; 398 return ret;
393 399
394 ret = fsl_lpspi_txfifo_empty(fsl_lpspi); 400 fsl_lpspi_reset(fsl_lpspi);
395 if (ret)
396 return ret;
397
398 fsl_lpspi_read_rx_fifo(fsl_lpspi);
399 401
400 return 0; 402 return 0;
401} 403}
@@ -408,7 +410,6 @@ static int fsl_lpspi_transfer_one_msg(struct spi_controller *controller,
408 struct spi_device *spi = msg->spi; 410 struct spi_device *spi = msg->spi;
409 struct spi_transfer *xfer; 411 struct spi_transfer *xfer;
410 bool is_first_xfer = true; 412 bool is_first_xfer = true;
411 u32 temp;
412 int ret = 0; 413 int ret = 0;
413 414
414 msg->status = 0; 415 msg->status = 0;
@@ -428,13 +429,6 @@ static int fsl_lpspi_transfer_one_msg(struct spi_controller *controller,
428 } 429 }
429 430
430complete: 431complete:
431 if (!fsl_lpspi->is_slave) {
432 /* de-assert SS, then finalize current message */
433 temp = readl(fsl_lpspi->base + IMX7ULP_TCR);
434 temp &= ~TCR_CONTC;
435 writel(temp, fsl_lpspi->base + IMX7ULP_TCR);
436 }
437
438 msg->status = ret; 432 msg->status = ret;
439 spi_finalize_current_message(controller); 433 spi_finalize_current_message(controller);
440 434
@@ -443,20 +437,30 @@ complete:
443 437
444static irqreturn_t fsl_lpspi_isr(int irq, void *dev_id) 438static irqreturn_t fsl_lpspi_isr(int irq, void *dev_id)
445{ 439{
440 u32 temp_SR, temp_IER;
446 struct fsl_lpspi_data *fsl_lpspi = dev_id; 441 struct fsl_lpspi_data *fsl_lpspi = dev_id;
447 u32 temp;
448 442
443 temp_IER = readl(fsl_lpspi->base + IMX7ULP_IER);
449 fsl_lpspi_intctrl(fsl_lpspi, 0); 444 fsl_lpspi_intctrl(fsl_lpspi, 0);
450 temp = readl(fsl_lpspi->base + IMX7ULP_SR); 445 temp_SR = readl(fsl_lpspi->base + IMX7ULP_SR);
451 446
452 fsl_lpspi_read_rx_fifo(fsl_lpspi); 447 fsl_lpspi_read_rx_fifo(fsl_lpspi);
453 448
454 if (temp & SR_TDF) { 449 if ((temp_SR & SR_TDF) && (temp_IER & IER_TDIE)) {
455 fsl_lpspi_write_tx_fifo(fsl_lpspi); 450 fsl_lpspi_write_tx_fifo(fsl_lpspi);
451 return IRQ_HANDLED;
452 }
456 453
457 if (!fsl_lpspi->remain) 454 if (temp_SR & SR_MBF ||
458 complete(&fsl_lpspi->xfer_done); 455 readl(fsl_lpspi->base + IMX7ULP_FSR) & FSR_RXCOUNT) {
456 writel(SR_FCF, fsl_lpspi->base + IMX7ULP_SR);
457 fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE);
458 return IRQ_HANDLED;
459 }
459 460
461 if (temp_SR & SR_FCF && (temp_IER & IER_FCIE)) {
462 writel(SR_FCF, fsl_lpspi->base + IMX7ULP_SR);
463 complete(&fsl_lpspi->xfer_done);
460 return IRQ_HANDLED; 464 return IRQ_HANDLED;
461 } 465 }
462 466