aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVignesh R <vigneshr@ti.com>2015-12-10 23:09:57 -0500
committerMark Brown <broonie@kernel.org>2016-02-09 14:34:43 -0500
commit4dea6c9b0b64fc4cbd543b5a3b6320218be8ca9c (patch)
tree0f0a7b1b097a62a59583f225c4fcf3af407c2aea
parent556351f14e74db4cd3ddde386457edce7bf0b27f (diff)
spi: spi-ti-qspi: add mmap mode read support
ti-qspi controller provides mmap port to read data from SPI flashes. mmap port is enabled in QSPI_SPI_SWITCH_REG. ctrl module register may also need to be accessed for some SoCs. The QSPI_SPI_SETUP_REGx needs to be populated with flash specific information like read opcode, read mode(quad, dual, normal), address width and dummy bytes. Once, controller is in mmap mode, the whole flash memory is available as a memory region at SoC specific address. This region can be accessed using normal memcpy() (or mem-to-mem dma copy). The ti-qspi controller hardware will internally communicate with SPI flash over SPI bus and get the requested data. Implement spi_flash_read() callback to support mmap read over SPI flash devices. With this, the read throughput increases from ~100kB/s to ~2.5 MB/s. Signed-off-by: Vignesh R <vigneshr@ti.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/spi/spi-ti-qspi.c139
1 files changed, 110 insertions, 29 deletions
diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c
index 64318fcfacf2..eac3c960b2de 100644
--- a/drivers/spi/spi-ti-qspi.c
+++ b/drivers/spi/spi-ti-qspi.c
@@ -31,6 +31,8 @@
31#include <linux/of.h> 31#include <linux/of.h>
32#include <linux/of_device.h> 32#include <linux/of_device.h>
33#include <linux/pinctrl/consumer.h> 33#include <linux/pinctrl/consumer.h>
34#include <linux/mfd/syscon.h>
35#include <linux/regmap.h>
34 36
35#include <linux/spi/spi.h> 37#include <linux/spi/spi.h>
36 38
@@ -44,8 +46,9 @@ struct ti_qspi {
44 46
45 struct spi_master *master; 47 struct spi_master *master;
46 void __iomem *base; 48 void __iomem *base;
47 void __iomem *ctrl_base;
48 void __iomem *mmap_base; 49 void __iomem *mmap_base;
50 struct regmap *ctrl_base;
51 unsigned int ctrl_reg;
49 struct clk *fclk; 52 struct clk *fclk;
50 struct device *dev; 53 struct device *dev;
51 54
@@ -55,7 +58,7 @@ struct ti_qspi {
55 u32 cmd; 58 u32 cmd;
56 u32 dc; 59 u32 dc;
57 60
58 bool ctrl_mod; 61 bool mmap_enabled;
59}; 62};
60 63
61#define QSPI_PID (0x0) 64#define QSPI_PID (0x0)
@@ -65,11 +68,8 @@ struct ti_qspi {
65#define QSPI_SPI_CMD_REG (0x48) 68#define QSPI_SPI_CMD_REG (0x48)
66#define QSPI_SPI_STATUS_REG (0x4c) 69#define QSPI_SPI_STATUS_REG (0x4c)
67#define QSPI_SPI_DATA_REG (0x50) 70#define QSPI_SPI_DATA_REG (0x50)
68#define QSPI_SPI_SETUP0_REG (0x54) 71#define QSPI_SPI_SETUP_REG(n) ((0x54 + 4 * n))
69#define QSPI_SPI_SWITCH_REG (0x64) 72#define QSPI_SPI_SWITCH_REG (0x64)
70#define QSPI_SPI_SETUP1_REG (0x58)
71#define QSPI_SPI_SETUP2_REG (0x5c)
72#define QSPI_SPI_SETUP3_REG (0x60)
73#define QSPI_SPI_DATA_REG_1 (0x68) 73#define QSPI_SPI_DATA_REG_1 (0x68)
74#define QSPI_SPI_DATA_REG_2 (0x6c) 74#define QSPI_SPI_DATA_REG_2 (0x6c)
75#define QSPI_SPI_DATA_REG_3 (0x70) 75#define QSPI_SPI_DATA_REG_3 (0x70)
@@ -109,6 +109,17 @@ struct ti_qspi {
109 109
110#define QSPI_AUTOSUSPEND_TIMEOUT 2000 110#define QSPI_AUTOSUSPEND_TIMEOUT 2000
111 111
112#define MEM_CS_EN(n) ((n + 1) << 8)
113#define MEM_CS_MASK (7 << 8)
114
115#define MM_SWITCH 0x1
116
117#define QSPI_SETUP_RD_NORMAL (0x0 << 12)
118#define QSPI_SETUP_RD_DUAL (0x1 << 12)
119#define QSPI_SETUP_RD_QUAD (0x3 << 12)
120#define QSPI_SETUP_ADDR_SHIFT 8
121#define QSPI_SETUP_DUMMY_SHIFT 10
122
112static inline unsigned long ti_qspi_read(struct ti_qspi *qspi, 123static inline unsigned long ti_qspi_read(struct ti_qspi *qspi,
113 unsigned long reg) 124 unsigned long reg)
114{ 125{
@@ -366,6 +377,72 @@ static int qspi_transfer_msg(struct ti_qspi *qspi, struct spi_transfer *t)
366 return 0; 377 return 0;
367} 378}
368 379
380static void ti_qspi_enable_memory_map(struct spi_device *spi)
381{
382 struct ti_qspi *qspi = spi_master_get_devdata(spi->master);
383
384 ti_qspi_write(qspi, MM_SWITCH, QSPI_SPI_SWITCH_REG);
385 if (qspi->ctrl_base) {
386 regmap_update_bits(qspi->ctrl_base, qspi->ctrl_reg,
387 MEM_CS_EN(spi->chip_select),
388 MEM_CS_MASK);
389 }
390 qspi->mmap_enabled = true;
391}
392
393static void ti_qspi_disable_memory_map(struct spi_device *spi)
394{
395 struct ti_qspi *qspi = spi_master_get_devdata(spi->master);
396
397 ti_qspi_write(qspi, 0, QSPI_SPI_SWITCH_REG);
398 if (qspi->ctrl_base)
399 regmap_update_bits(qspi->ctrl_base, qspi->ctrl_reg,
400 0, MEM_CS_MASK);
401 qspi->mmap_enabled = false;
402}
403
404static void ti_qspi_setup_mmap_read(struct spi_device *spi,
405 struct spi_flash_read_message *msg)
406{
407 struct ti_qspi *qspi = spi_master_get_devdata(spi->master);
408 u32 memval = msg->read_opcode;
409
410 switch (msg->data_nbits) {
411 case SPI_NBITS_QUAD:
412 memval |= QSPI_SETUP_RD_QUAD;
413 break;
414 case SPI_NBITS_DUAL:
415 memval |= QSPI_SETUP_RD_DUAL;
416 break;
417 default:
418 memval |= QSPI_SETUP_RD_NORMAL;
419 break;
420 }
421 memval |= ((msg->addr_width - 1) << QSPI_SETUP_ADDR_SHIFT |
422 msg->dummy_bytes << QSPI_SETUP_DUMMY_SHIFT);
423 ti_qspi_write(qspi, memval,
424 QSPI_SPI_SETUP_REG(spi->chip_select));
425}
426
427static int ti_qspi_spi_flash_read(struct spi_device *spi,
428 struct spi_flash_read_message *msg)
429{
430 struct ti_qspi *qspi = spi_master_get_devdata(spi->master);
431 int ret = 0;
432
433 mutex_lock(&qspi->list_lock);
434
435 if (!qspi->mmap_enabled)
436 ti_qspi_enable_memory_map(spi);
437 ti_qspi_setup_mmap_read(spi, msg);
438 memcpy_fromio(msg->buf, qspi->mmap_base + msg->from, msg->len);
439 msg->retlen = msg->len;
440
441 mutex_unlock(&qspi->list_lock);
442
443 return ret;
444}
445
369static int ti_qspi_start_transfer_one(struct spi_master *master, 446static int ti_qspi_start_transfer_one(struct spi_master *master,
370 struct spi_message *m) 447 struct spi_message *m)
371{ 448{
@@ -398,6 +475,9 @@ static int ti_qspi_start_transfer_one(struct spi_master *master,
398 475
399 mutex_lock(&qspi->list_lock); 476 mutex_lock(&qspi->list_lock);
400 477
478 if (qspi->mmap_enabled)
479 ti_qspi_disable_memory_map(spi);
480
401 list_for_each_entry(t, &m->transfers, transfer_list) { 481 list_for_each_entry(t, &m->transfers, transfer_list) {
402 qspi->cmd |= QSPI_WLEN(t->bits_per_word); 482 qspi->cmd |= QSPI_WLEN(t->bits_per_word);
403 483
@@ -441,7 +521,7 @@ static int ti_qspi_probe(struct platform_device *pdev)
441{ 521{
442 struct ti_qspi *qspi; 522 struct ti_qspi *qspi;
443 struct spi_master *master; 523 struct spi_master *master;
444 struct resource *r, *res_ctrl, *res_mmap; 524 struct resource *r, *res_mmap;
445 struct device_node *np = pdev->dev.of_node; 525 struct device_node *np = pdev->dev.of_node;
446 u32 max_freq; 526 u32 max_freq;
447 int ret = 0, num_cs, irq; 527 int ret = 0, num_cs, irq;
@@ -487,16 +567,6 @@ static int ti_qspi_probe(struct platform_device *pdev)
487 } 567 }
488 } 568 }
489 569
490 res_ctrl = platform_get_resource_byname(pdev,
491 IORESOURCE_MEM, "qspi_ctrlmod");
492 if (res_ctrl == NULL) {
493 res_ctrl = platform_get_resource(pdev, IORESOURCE_MEM, 2);
494 if (res_ctrl == NULL) {
495 dev_dbg(&pdev->dev,
496 "control module resources not required\n");
497 }
498 }
499
500 irq = platform_get_irq(pdev, 0); 570 irq = platform_get_irq(pdev, 0);
501 if (irq < 0) { 571 if (irq < 0) {
502 dev_err(&pdev->dev, "no irq resource?\n"); 572 dev_err(&pdev->dev, "no irq resource?\n");
@@ -511,20 +581,31 @@ static int ti_qspi_probe(struct platform_device *pdev)
511 goto free_master; 581 goto free_master;
512 } 582 }
513 583
514 if (res_ctrl) {
515 qspi->ctrl_mod = true;
516 qspi->ctrl_base = devm_ioremap_resource(&pdev->dev, res_ctrl);
517 if (IS_ERR(qspi->ctrl_base)) {
518 ret = PTR_ERR(qspi->ctrl_base);
519 goto free_master;
520 }
521 }
522
523 if (res_mmap) { 584 if (res_mmap) {
524 qspi->mmap_base = devm_ioremap_resource(&pdev->dev, res_mmap); 585 qspi->mmap_base = devm_ioremap_resource(&pdev->dev,
586 res_mmap);
587 master->spi_flash_read = ti_qspi_spi_flash_read;
525 if (IS_ERR(qspi->mmap_base)) { 588 if (IS_ERR(qspi->mmap_base)) {
526 ret = PTR_ERR(qspi->mmap_base); 589 dev_err(&pdev->dev,
527 goto free_master; 590 "falling back to PIO mode\n");
591 master->spi_flash_read = NULL;
592 }
593 }
594 qspi->mmap_enabled = false;
595
596 if (of_property_read_bool(np, "syscon-chipselects")) {
597 qspi->ctrl_base =
598 syscon_regmap_lookup_by_phandle(np,
599 "syscon-chipselects");
600 if (IS_ERR(qspi->ctrl_base))
601 return PTR_ERR(qspi->ctrl_base);
602 ret = of_property_read_u32_index(np,
603 "syscon-chipselects",
604 1, &qspi->ctrl_reg);
605 if (ret) {
606 dev_err(&pdev->dev,
607 "couldn't get ctrl_mod reg index\n");
608 return ret;
528 } 609 }
529 } 610 }
530 611