summaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-uniphier.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi-uniphier.c')
-rw-r--r--drivers/spi/spi-uniphier.c89
1 files changed, 68 insertions, 21 deletions
diff --git a/drivers/spi/spi-uniphier.c b/drivers/spi/spi-uniphier.c
index 4e99a0f25c29..47cde1864630 100644
--- a/drivers/spi/spi-uniphier.c
+++ b/drivers/spi/spi-uniphier.c
@@ -7,6 +7,7 @@
7#include <linux/bitfield.h> 7#include <linux/bitfield.h>
8#include <linux/bitops.h> 8#include <linux/bitops.h>
9#include <linux/clk.h> 9#include <linux/clk.h>
10#include <linux/delay.h>
10#include <linux/interrupt.h> 11#include <linux/interrupt.h>
11#include <linux/io.h> 12#include <linux/io.h>
12#include <linux/module.h> 13#include <linux/module.h>
@@ -16,6 +17,7 @@
16#include <asm/unaligned.h> 17#include <asm/unaligned.h>
17 18
18#define SSI_TIMEOUT_MS 2000 19#define SSI_TIMEOUT_MS 2000
20#define SSI_POLL_TIMEOUT_US 200
19#define SSI_MAX_CLK_DIVIDER 254 21#define SSI_MAX_CLK_DIVIDER 254
20#define SSI_MIN_CLK_DIVIDER 4 22#define SSI_MIN_CLK_DIVIDER 4
21 23
@@ -227,8 +229,7 @@ static void uniphier_spi_setup_transfer(struct spi_device *spi,
227 priv->speed_hz = t->speed_hz; 229 priv->speed_hz = t->speed_hz;
228 } 230 }
229 231
230 if (!priv->is_save_param) 232 priv->is_save_param = true;
231 priv->is_save_param = true;
232 233
233 /* reset FIFOs */ 234 /* reset FIFOs */
234 val = SSI_FC_TXFFL | SSI_FC_RXFFL; 235 val = SSI_FC_TXFFL | SSI_FC_RXFFL;
@@ -291,21 +292,23 @@ static void uniphier_spi_recv(struct uniphier_spi_priv *priv)
291 292
292static void uniphier_spi_fill_tx_fifo(struct uniphier_spi_priv *priv) 293static void uniphier_spi_fill_tx_fifo(struct uniphier_spi_priv *priv)
293{ 294{
294 unsigned int tx_count; 295 unsigned int fifo_threshold, fill_bytes;
295 u32 val; 296 u32 val;
296 297
297 tx_count = DIV_ROUND_UP(priv->tx_bytes, 298 fifo_threshold = DIV_ROUND_UP(priv->rx_bytes,
298 bytes_per_word(priv->bits_per_word)); 299 bytes_per_word(priv->bits_per_word));
299 tx_count = min(tx_count, SSI_FIFO_DEPTH); 300 fifo_threshold = min(fifo_threshold, SSI_FIFO_DEPTH);
301
302 fill_bytes = fifo_threshold - (priv->rx_bytes - priv->tx_bytes);
300 303
301 /* set fifo threshold */ 304 /* set fifo threshold */
302 val = readl(priv->base + SSI_FC); 305 val = readl(priv->base + SSI_FC);
303 val &= ~(SSI_FC_TXFTH_MASK | SSI_FC_RXFTH_MASK); 306 val &= ~(SSI_FC_TXFTH_MASK | SSI_FC_RXFTH_MASK);
304 val |= FIELD_PREP(SSI_FC_TXFTH_MASK, tx_count); 307 val |= FIELD_PREP(SSI_FC_TXFTH_MASK, fifo_threshold);
305 val |= FIELD_PREP(SSI_FC_RXFTH_MASK, tx_count); 308 val |= FIELD_PREP(SSI_FC_RXFTH_MASK, fifo_threshold);
306 writel(val, priv->base + SSI_FC); 309 writel(val, priv->base + SSI_FC);
307 310
308 while (tx_count--) 311 while (fill_bytes--)
309 uniphier_spi_send(priv); 312 uniphier_spi_send(priv);
310} 313}
311 314
@@ -324,20 +327,14 @@ static void uniphier_spi_set_cs(struct spi_device *spi, bool enable)
324 writel(val, priv->base + SSI_FPS); 327 writel(val, priv->base + SSI_FPS);
325} 328}
326 329
327static int uniphier_spi_transfer_one(struct spi_master *master, 330static int uniphier_spi_transfer_one_irq(struct spi_master *master,
328 struct spi_device *spi, 331 struct spi_device *spi,
329 struct spi_transfer *t) 332 struct spi_transfer *t)
330{ 333{
331 struct uniphier_spi_priv *priv = spi_master_get_devdata(master); 334 struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
332 struct device *dev = master->dev.parent; 335 struct device *dev = master->dev.parent;
333 unsigned long time_left; 336 unsigned long time_left;
334 337
335 /* Terminate and return success for 0 byte length transfer */
336 if (!t->len)
337 return 0;
338
339 uniphier_spi_setup_transfer(spi, t);
340
341 reinit_completion(&priv->xfer_done); 338 reinit_completion(&priv->xfer_done);
342 339
343 uniphier_spi_fill_tx_fifo(priv); 340 uniphier_spi_fill_tx_fifo(priv);
@@ -357,6 +354,59 @@ static int uniphier_spi_transfer_one(struct spi_master *master,
357 return priv->error; 354 return priv->error;
358} 355}
359 356
357static int uniphier_spi_transfer_one_poll(struct spi_master *master,
358 struct spi_device *spi,
359 struct spi_transfer *t)
360{
361 struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
362 int loop = SSI_POLL_TIMEOUT_US * 10;
363
364 while (priv->tx_bytes) {
365 uniphier_spi_fill_tx_fifo(priv);
366
367 while ((priv->rx_bytes - priv->tx_bytes) > 0) {
368 while (!(readl(priv->base + SSI_SR) & SSI_SR_RNE)
369 && loop--)
370 ndelay(100);
371
372 if (loop == -1)
373 goto irq_transfer;
374
375 uniphier_spi_recv(priv);
376 }
377 }
378
379 return 0;
380
381irq_transfer:
382 return uniphier_spi_transfer_one_irq(master, spi, t);
383}
384
385static int uniphier_spi_transfer_one(struct spi_master *master,
386 struct spi_device *spi,
387 struct spi_transfer *t)
388{
389 struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
390 unsigned long threshold;
391
392 /* Terminate and return success for 0 byte length transfer */
393 if (!t->len)
394 return 0;
395
396 uniphier_spi_setup_transfer(spi, t);
397
398 /*
399 * If the transfer operation will take longer than
400 * SSI_POLL_TIMEOUT_US, it should use irq.
401 */
402 threshold = DIV_ROUND_UP(SSI_POLL_TIMEOUT_US * priv->speed_hz,
403 USEC_PER_SEC * BITS_PER_BYTE);
404 if (t->len > threshold)
405 return uniphier_spi_transfer_one_irq(master, spi, t);
406 else
407 return uniphier_spi_transfer_one_poll(master, spi, t);
408}
409
360static int uniphier_spi_prepare_transfer_hardware(struct spi_master *master) 410static int uniphier_spi_prepare_transfer_hardware(struct spi_master *master)
361{ 411{
362 struct uniphier_spi_priv *priv = spi_master_get_devdata(master); 412 struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
@@ -420,7 +470,6 @@ static int uniphier_spi_probe(struct platform_device *pdev)
420{ 470{
421 struct uniphier_spi_priv *priv; 471 struct uniphier_spi_priv *priv;
422 struct spi_master *master; 472 struct spi_master *master;
423 struct resource *res;
424 unsigned long clk_rate; 473 unsigned long clk_rate;
425 int irq; 474 int irq;
426 int ret; 475 int ret;
@@ -435,8 +484,7 @@ static int uniphier_spi_probe(struct platform_device *pdev)
435 priv->master = master; 484 priv->master = master;
436 priv->is_save_param = false; 485 priv->is_save_param = false;
437 486
438 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 487 priv->base = devm_platform_ioremap_resource(pdev, 0);
439 priv->base = devm_ioremap_resource(&pdev->dev, res);
440 if (IS_ERR(priv->base)) { 488 if (IS_ERR(priv->base)) {
441 ret = PTR_ERR(priv->base); 489 ret = PTR_ERR(priv->base);
442 goto out_master_put; 490 goto out_master_put;
@@ -455,7 +503,6 @@ static int uniphier_spi_probe(struct platform_device *pdev)
455 503
456 irq = platform_get_irq(pdev, 0); 504 irq = platform_get_irq(pdev, 0);
457 if (irq < 0) { 505 if (irq < 0) {
458 dev_err(&pdev->dev, "failed to get IRQ\n");
459 ret = irq; 506 ret = irq;
460 goto out_disable_clk; 507 goto out_disable_clk;
461 } 508 }