Skip to content

Commit 4dea6c9

Browse files
r-vigneshbroonie
authored andcommitted
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>
1 parent 556351f commit 4dea6c9

File tree

1 file changed

+110
-29
lines changed

1 file changed

+110
-29
lines changed

drivers/spi/spi-ti-qspi.c

Lines changed: 110 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
#include <linux/of.h>
3232
#include <linux/of_device.h>
3333
#include <linux/pinctrl/consumer.h>
34+
#include <linux/mfd/syscon.h>
35+
#include <linux/regmap.h>
3436

3537
#include <linux/spi/spi.h>
3638

@@ -44,8 +46,9 @@ struct ti_qspi {
4446

4547
struct spi_master *master;
4648
void __iomem *base;
47-
void __iomem *ctrl_base;
4849
void __iomem *mmap_base;
50+
struct regmap *ctrl_base;
51+
unsigned int ctrl_reg;
4952
struct clk *fclk;
5053
struct device *dev;
5154

@@ -55,7 +58,7 @@ struct ti_qspi {
5558
u32 cmd;
5659
u32 dc;
5760

58-
bool ctrl_mod;
61+
bool mmap_enabled;
5962
};
6063

6164
#define QSPI_PID (0x0)
@@ -65,11 +68,8 @@ struct ti_qspi {
6568
#define QSPI_SPI_CMD_REG (0x48)
6669
#define QSPI_SPI_STATUS_REG (0x4c)
6770
#define QSPI_SPI_DATA_REG (0x50)
68-
#define QSPI_SPI_SETUP0_REG (0x54)
71+
#define QSPI_SPI_SETUP_REG(n) ((0x54 + 4 * n))
6972
#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)
7373
#define QSPI_SPI_DATA_REG_1 (0x68)
7474
#define QSPI_SPI_DATA_REG_2 (0x6c)
7575
#define QSPI_SPI_DATA_REG_3 (0x70)
@@ -109,6 +109,17 @@ struct ti_qspi {
109109

110110
#define QSPI_AUTOSUSPEND_TIMEOUT 2000
111111

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+
112123
static inline unsigned long ti_qspi_read(struct ti_qspi *qspi,
113124
unsigned long reg)
114125
{
@@ -366,6 +377,72 @@ static int qspi_transfer_msg(struct ti_qspi *qspi, struct spi_transfer *t)
366377
return 0;
367378
}
368379

380+
static 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+
393+
static 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+
404+
static 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+
427+
static 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+
369446
static int ti_qspi_start_transfer_one(struct spi_master *master,
370447
struct spi_message *m)
371448
{
@@ -398,6 +475,9 @@ static int ti_qspi_start_transfer_one(struct spi_master *master,
398475

399476
mutex_lock(&qspi->list_lock);
400477

478+
if (qspi->mmap_enabled)
479+
ti_qspi_disable_memory_map(spi);
480+
401481
list_for_each_entry(t, &m->transfers, transfer_list) {
402482
qspi->cmd |= QSPI_WLEN(t->bits_per_word);
403483

@@ -441,7 +521,7 @@ static int ti_qspi_probe(struct platform_device *pdev)
441521
{
442522
struct ti_qspi *qspi;
443523
struct spi_master *master;
444-
struct resource *r, *res_ctrl, *res_mmap;
524+
struct resource *r, *res_mmap;
445525
struct device_node *np = pdev->dev.of_node;
446526
u32 max_freq;
447527
int ret = 0, num_cs, irq;
@@ -487,16 +567,6 @@ static int ti_qspi_probe(struct platform_device *pdev)
487567
}
488568
}
489569

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-
500570
irq = platform_get_irq(pdev, 0);
501571
if (irq < 0) {
502572
dev_err(&pdev->dev, "no irq resource?\n");
@@ -511,20 +581,31 @@ static int ti_qspi_probe(struct platform_device *pdev)
511581
goto free_master;
512582
}
513583

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-
523584
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;
525588
if (IS_ERR(qspi->mmap_base)) {
526-
ret = PTR_ERR(qspi->mmap_base);
527-
goto free_master;
589+
dev_err(&pdev->dev,
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;
528609
}
529610
}
530611

0 commit comments

Comments
 (0)