* [PATCH 0/3]Add quad/memory mapped support for SPI flash. @ 2013-10-09 15:24 ` Sourav Poddar 0 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-09 15:24 UTC (permalink / raw) To: broonie, dwmw2, computersforpeace Cc: spi-devel-general, Sourav Poddar, linux-mtd, balbi This patch add quad/memory mapped support in flash driver(m25p80). Added support for quad memory mapped for TI qspi controller also. This patch has been tested with some internal dts data. Sourav Poddar (3): spi/qspi: Add memory mapped read support. drivers: mtd: devices: Add quad read support. drivers: mtd: devices: Add memory mapped read support. drivers/mtd/devices/m25p80.c | 193 ++++++++++++++++++++++++++++++++++++++++-- drivers/spi/spi-ti-qspi.c | 140 +++++++++++++++++++++++++++--- include/linux/spi/spi.h | 2 + 3 files changed, 312 insertions(+), 23 deletions(-) ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* [PATCH 0/3]Add quad/memory mapped support for SPI flash. @ 2013-10-09 15:24 ` Sourav Poddar 0 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-09 15:24 UTC (permalink / raw) To: broonie, dwmw2, computersforpeace Cc: spi-devel-general, Sourav Poddar, linux-mtd, balbi This patch add quad/memory mapped support in flash driver(m25p80). Added support for quad memory mapped for TI qspi controller also. This patch has been tested with some internal dts data. Sourav Poddar (3): spi/qspi: Add memory mapped read support. drivers: mtd: devices: Add quad read support. drivers: mtd: devices: Add memory mapped read support. drivers/mtd/devices/m25p80.c | 193 ++++++++++++++++++++++++++++++++++++++++-- drivers/spi/spi-ti-qspi.c | 140 +++++++++++++++++++++++++++--- include/linux/spi/spi.h | 2 + 3 files changed, 312 insertions(+), 23 deletions(-) ^ permalink raw reply [flat|nested] 104+ messages in thread
* [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-09 15:24 ` Sourav Poddar @ 2013-10-09 15:24 ` Sourav Poddar -1 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-09 15:24 UTC (permalink / raw) To: broonie, dwmw2, computersforpeace Cc: spi-devel-general, Sourav Poddar, linux-mtd, balbi Qspi controller also supports memory mapped read. Patch adds support for the same. In memory mapped read, controller need to be switched to a memory mapped port using a control module register and a qspi specific register or just a qspi register. Then the read need to be happened from the memory mapped address space. Signed-off-by: Sourav Poddar <sourav.poddar@ti.com> --- drivers/spi/spi-ti-qspi.c | 140 ++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 125 insertions(+), 15 deletions(-) diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index 0b71270..2722840 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -46,6 +46,8 @@ struct ti_qspi { struct spi_master *master; void __iomem *base; + void __iomem *ctrl_base; + void __iomem *mmap_base; struct clk *fclk; struct device *dev; @@ -54,6 +56,9 @@ struct ti_qspi { u32 spi_max_frequency; u32 cmd; u32 dc; + + bool memory_mapped; + bool ctrl_mod; }; #define QSPI_PID (0x0) @@ -109,6 +114,23 @@ struct ti_qspi { #define QSPI_CSPOL(n) (1 << (1 + n * 8)) #define QSPI_CKPOL(n) (1 << (n * 8)) +#define MM_SWITCH 0x01 +#define MEM_CS 0x100 +#define MEM_CS_DIS 0xfffff0ff + +#define QSPI_CMD_RD (0x3 << 0) +#define QSPI_CMD_DUAL_RD (0x3b << 0) +#define QSPI_CMD_QUAD_RD (0x6b << 0) +#define QSPI_CMD_READ_FAST (0x0b << 0) +#define QSPI_SETUP0_A_BYTES (0x3 << 8) +#define QSPI_SETUP0_NO_BITS (0x0 << 10) +#define QSPI_SETUP0_8_BITS (0x1 << 10) +#define QSPI_SETUP0_RD_NORMAL (0x0 << 12) +#define QSPI_SETUP0_RD_DUAL (0x1 << 12) +#define QSPI_SETUP0_RD_QUAD (0x3 << 12) +#define QSPI_CMD_WRITE (0x2 << 16) +#define QSPI_NUM_DUMMY_BITS (0x0 << 24) + #define QSPI_FRAME 4096 #define QSPI_AUTOSUSPEND_TIMEOUT 2000 @@ -125,12 +147,37 @@ static inline void ti_qspi_write(struct ti_qspi *qspi, writel(val, qspi->base + reg); } +void enable_qspi_memory_mapped(struct ti_qspi *qspi) +{ + u32 val; + + ti_qspi_write(qspi, MM_SWITCH, QSPI_SPI_SWITCH_REG); + if (qspi->ctrl_mod) { + val = readl(qspi->ctrl_base); + val |= MEM_CS; + writel(val, qspi->ctrl_base); + } +} + +void disable_qspi_memory_mapped(struct ti_qspi *qspi) +{ + u32 val; + + ti_qspi_write(qspi, ~MM_SWITCH, QSPI_SPI_SWITCH_REG); + if (qspi->ctrl_mod) { + val = readl(qspi->ctrl_base); + val |= MEM_CS_DIS; + writel(val, qspi->ctrl_base); + } +} + static int ti_qspi_setup(struct spi_device *spi) { struct ti_qspi *qspi = spi_master_get_devdata(spi->master); struct ti_qspi_regs *ctx_reg = &qspi->ctx_reg; int clk_div = 0, ret; - u32 clk_ctrl_reg, clk_rate, clk_mask; + u32 clk_ctrl_reg, clk_rate, clk_mask, memval = 0; + qspi->dc = 0; if (spi->master->busy) { dev_dbg(qspi->dev, "master busy doing other trasnfers\n"); @@ -178,6 +225,37 @@ static int ti_qspi_setup(struct spi_device *spi) ti_qspi_write(qspi, clk_mask, QSPI_SPI_CLOCK_CNTRL_REG); ctx_reg->clkctrl = clk_mask; + if (spi->mode & SPI_CPHA) + qspi->dc |= QSPI_CKPHA(spi->chip_select); + if (spi->mode & SPI_CPOL) + qspi->dc |= QSPI_CKPOL(spi->chip_select); + if (spi->mode & SPI_CS_HIGH) + qspi->dc |= QSPI_CSPOL(spi->chip_select); + + ti_qspi_write(qspi, qspi->dc, QSPI_SPI_DC_REG); + + if (qspi->memory_mapped) { + switch (spi->mode) { + case SPI_TX_DUAL: + memval |= (QSPI_CMD_DUAL_RD | QSPI_SETUP0_A_BYTES | + QSPI_SETUP0_8_BITS | QSPI_SETUP0_RD_DUAL | + QSPI_CMD_WRITE | QSPI_NUM_DUMMY_BITS); + break; + case SPI_TX_QUAD: + memval |= (QSPI_CMD_QUAD_RD | QSPI_SETUP0_A_BYTES | + QSPI_SETUP0_8_BITS | QSPI_SETUP0_RD_QUAD | + QSPI_CMD_WRITE | QSPI_NUM_DUMMY_BITS); + break; + default: + memval |= (QSPI_CMD_RD | QSPI_SETUP0_A_BYTES | + QSPI_SETUP0_NO_BITS | QSPI_SETUP0_RD_NORMAL | + QSPI_CMD_WRITE | QSPI_NUM_DUMMY_BITS); + break; + } + ti_qspi_write(qspi, memval, QSPI_SPI_SETUP0_REG); + spi->mode |= SPI_RX_MMAP; + } + pm_runtime_mark_last_busy(qspi->dev); ret = pm_runtime_put_autosuspend(qspi->dev); if (ret < 0) { @@ -340,16 +418,7 @@ static int ti_qspi_start_transfer_one(struct spi_master *master, struct spi_transfer *t; int status = 0, ret; int frame_length; - - /* setup device control reg */ - qspi->dc = 0; - - if (spi->mode & SPI_CPHA) - qspi->dc |= QSPI_CKPHA(spi->chip_select); - if (spi->mode & SPI_CPOL) - qspi->dc |= QSPI_CKPOL(spi->chip_select); - if (spi->mode & SPI_CS_HIGH) - qspi->dc |= QSPI_CSPOL(spi->chip_select); + size_t from = 0; frame_length = (m->frame_length << 3) / spi->bits_per_word; @@ -362,11 +431,21 @@ static int ti_qspi_start_transfer_one(struct spi_master *master, qspi->cmd |= QSPI_WC_CMD_INT_EN; ti_qspi_write(qspi, QSPI_WC_INT_EN, QSPI_INTR_ENABLE_SET_REG); - ti_qspi_write(qspi, qspi->dc, QSPI_SPI_DC_REG); mutex_lock(&qspi->list_lock); list_for_each_entry(t, &m->transfers, transfer_list) { + if (t->memory_map) { + if (t->tx_buf) { + from = t->len; + continue; + } + enable_qspi_memory_mapped(qspi); + memcpy(t->rx_buf, qspi->mmap_base + from, t->len); + disable_qspi_memory_mapped(qspi); + goto out; + } + qspi->cmd |= QSPI_WLEN(t->bits_per_word); ret = qspi_transfer_msg(qspi, t); @@ -379,6 +458,7 @@ static int ti_qspi_start_transfer_one(struct spi_master *master, m->actual_length += t->len; } +out: mutex_unlock(&qspi->list_lock); m->status = status; @@ -437,7 +517,7 @@ static int ti_qspi_probe(struct platform_device *pdev) { struct ti_qspi *qspi; struct spi_master *master; - struct resource *r; + struct resource *r, *res_ctrl, *res_mmap; struct device_node *np = pdev->dev.of_node; u32 max_freq; int ret = 0, num_cs, irq; @@ -446,7 +526,8 @@ static int ti_qspi_probe(struct platform_device *pdev) if (!master) return -ENOMEM; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD; + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD | + SPI_RX_MMAP; master->bus_num = -1; master->flags = SPI_MASTER_HALF_DUPLEX; @@ -465,7 +546,16 @@ static int ti_qspi_probe(struct platform_device *pdev) qspi->master = master; qspi->dev = &pdev->dev; - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi_base"); + if (r == NULL) { + dev_err(&pdev->dev, "missing platform resources data\n"); + return -ENODEV; + } + + res_mmap = platform_get_resource_byname(pdev, + IORESOURCE_MEM, "qspi_mmap"); + res_ctrl = platform_get_resource_byname(pdev, + IORESOURCE_MEM, "qspi_ctrlmod"); irq = platform_get_irq(pdev, 0); if (irq < 0) { @@ -481,6 +571,23 @@ static int ti_qspi_probe(struct platform_device *pdev) goto free_master; } + if (res_ctrl) { + qspi->ctrl_mod = true; + qspi->ctrl_base = devm_ioremap_resource(&pdev->dev, res_ctrl); + if (IS_ERR(qspi->ctrl_base)) { + ret = PTR_ERR(qspi->ctrl_base); + goto free_master; + } + } + + if (res_mmap) { + qspi->mmap_base = devm_ioremap_resource(&pdev->dev, res_mmap); + if (IS_ERR(qspi->mmap_base)) { + ret = PTR_ERR(qspi->mmap_base); + goto free_master; + } + } + ret = devm_request_irq(&pdev->dev, irq, ti_qspi_isr, 0, dev_name(&pdev->dev), qspi); if (ret < 0) { @@ -504,6 +611,9 @@ static int ti_qspi_probe(struct platform_device *pdev) if (!of_property_read_u32(np, "spi-max-frequency", &max_freq)) qspi->spi_max_frequency = max_freq; + if (of_property_read_bool(np, "mmap_read")) + qspi->memory_mapped = true; + ret = devm_spi_register_master(&pdev->dev, master); if (ret) goto free_master; -- 1.7.1 ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply related [flat|nested] 104+ messages in thread
* [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-09 15:24 ` Sourav Poddar 0 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-09 15:24 UTC (permalink / raw) To: broonie, dwmw2, computersforpeace Cc: spi-devel-general, Sourav Poddar, linux-mtd, balbi Qspi controller also supports memory mapped read. Patch adds support for the same. In memory mapped read, controller need to be switched to a memory mapped port using a control module register and a qspi specific register or just a qspi register. Then the read need to be happened from the memory mapped address space. Signed-off-by: Sourav Poddar <sourav.poddar@ti.com> --- drivers/spi/spi-ti-qspi.c | 140 ++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 125 insertions(+), 15 deletions(-) diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index 0b71270..2722840 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -46,6 +46,8 @@ struct ti_qspi { struct spi_master *master; void __iomem *base; + void __iomem *ctrl_base; + void __iomem *mmap_base; struct clk *fclk; struct device *dev; @@ -54,6 +56,9 @@ struct ti_qspi { u32 spi_max_frequency; u32 cmd; u32 dc; + + bool memory_mapped; + bool ctrl_mod; }; #define QSPI_PID (0x0) @@ -109,6 +114,23 @@ struct ti_qspi { #define QSPI_CSPOL(n) (1 << (1 + n * 8)) #define QSPI_CKPOL(n) (1 << (n * 8)) +#define MM_SWITCH 0x01 +#define MEM_CS 0x100 +#define MEM_CS_DIS 0xfffff0ff + +#define QSPI_CMD_RD (0x3 << 0) +#define QSPI_CMD_DUAL_RD (0x3b << 0) +#define QSPI_CMD_QUAD_RD (0x6b << 0) +#define QSPI_CMD_READ_FAST (0x0b << 0) +#define QSPI_SETUP0_A_BYTES (0x3 << 8) +#define QSPI_SETUP0_NO_BITS (0x0 << 10) +#define QSPI_SETUP0_8_BITS (0x1 << 10) +#define QSPI_SETUP0_RD_NORMAL (0x0 << 12) +#define QSPI_SETUP0_RD_DUAL (0x1 << 12) +#define QSPI_SETUP0_RD_QUAD (0x3 << 12) +#define QSPI_CMD_WRITE (0x2 << 16) +#define QSPI_NUM_DUMMY_BITS (0x0 << 24) + #define QSPI_FRAME 4096 #define QSPI_AUTOSUSPEND_TIMEOUT 2000 @@ -125,12 +147,37 @@ static inline void ti_qspi_write(struct ti_qspi *qspi, writel(val, qspi->base + reg); } +void enable_qspi_memory_mapped(struct ti_qspi *qspi) +{ + u32 val; + + ti_qspi_write(qspi, MM_SWITCH, QSPI_SPI_SWITCH_REG); + if (qspi->ctrl_mod) { + val = readl(qspi->ctrl_base); + val |= MEM_CS; + writel(val, qspi->ctrl_base); + } +} + +void disable_qspi_memory_mapped(struct ti_qspi *qspi) +{ + u32 val; + + ti_qspi_write(qspi, ~MM_SWITCH, QSPI_SPI_SWITCH_REG); + if (qspi->ctrl_mod) { + val = readl(qspi->ctrl_base); + val |= MEM_CS_DIS; + writel(val, qspi->ctrl_base); + } +} + static int ti_qspi_setup(struct spi_device *spi) { struct ti_qspi *qspi = spi_master_get_devdata(spi->master); struct ti_qspi_regs *ctx_reg = &qspi->ctx_reg; int clk_div = 0, ret; - u32 clk_ctrl_reg, clk_rate, clk_mask; + u32 clk_ctrl_reg, clk_rate, clk_mask, memval = 0; + qspi->dc = 0; if (spi->master->busy) { dev_dbg(qspi->dev, "master busy doing other trasnfers\n"); @@ -178,6 +225,37 @@ static int ti_qspi_setup(struct spi_device *spi) ti_qspi_write(qspi, clk_mask, QSPI_SPI_CLOCK_CNTRL_REG); ctx_reg->clkctrl = clk_mask; + if (spi->mode & SPI_CPHA) + qspi->dc |= QSPI_CKPHA(spi->chip_select); + if (spi->mode & SPI_CPOL) + qspi->dc |= QSPI_CKPOL(spi->chip_select); + if (spi->mode & SPI_CS_HIGH) + qspi->dc |= QSPI_CSPOL(spi->chip_select); + + ti_qspi_write(qspi, qspi->dc, QSPI_SPI_DC_REG); + + if (qspi->memory_mapped) { + switch (spi->mode) { + case SPI_TX_DUAL: + memval |= (QSPI_CMD_DUAL_RD | QSPI_SETUP0_A_BYTES | + QSPI_SETUP0_8_BITS | QSPI_SETUP0_RD_DUAL | + QSPI_CMD_WRITE | QSPI_NUM_DUMMY_BITS); + break; + case SPI_TX_QUAD: + memval |= (QSPI_CMD_QUAD_RD | QSPI_SETUP0_A_BYTES | + QSPI_SETUP0_8_BITS | QSPI_SETUP0_RD_QUAD | + QSPI_CMD_WRITE | QSPI_NUM_DUMMY_BITS); + break; + default: + memval |= (QSPI_CMD_RD | QSPI_SETUP0_A_BYTES | + QSPI_SETUP0_NO_BITS | QSPI_SETUP0_RD_NORMAL | + QSPI_CMD_WRITE | QSPI_NUM_DUMMY_BITS); + break; + } + ti_qspi_write(qspi, memval, QSPI_SPI_SETUP0_REG); + spi->mode |= SPI_RX_MMAP; + } + pm_runtime_mark_last_busy(qspi->dev); ret = pm_runtime_put_autosuspend(qspi->dev); if (ret < 0) { @@ -340,16 +418,7 @@ static int ti_qspi_start_transfer_one(struct spi_master *master, struct spi_transfer *t; int status = 0, ret; int frame_length; - - /* setup device control reg */ - qspi->dc = 0; - - if (spi->mode & SPI_CPHA) - qspi->dc |= QSPI_CKPHA(spi->chip_select); - if (spi->mode & SPI_CPOL) - qspi->dc |= QSPI_CKPOL(spi->chip_select); - if (spi->mode & SPI_CS_HIGH) - qspi->dc |= QSPI_CSPOL(spi->chip_select); + size_t from = 0; frame_length = (m->frame_length << 3) / spi->bits_per_word; @@ -362,11 +431,21 @@ static int ti_qspi_start_transfer_one(struct spi_master *master, qspi->cmd |= QSPI_WC_CMD_INT_EN; ti_qspi_write(qspi, QSPI_WC_INT_EN, QSPI_INTR_ENABLE_SET_REG); - ti_qspi_write(qspi, qspi->dc, QSPI_SPI_DC_REG); mutex_lock(&qspi->list_lock); list_for_each_entry(t, &m->transfers, transfer_list) { + if (t->memory_map) { + if (t->tx_buf) { + from = t->len; + continue; + } + enable_qspi_memory_mapped(qspi); + memcpy(t->rx_buf, qspi->mmap_base + from, t->len); + disable_qspi_memory_mapped(qspi); + goto out; + } + qspi->cmd |= QSPI_WLEN(t->bits_per_word); ret = qspi_transfer_msg(qspi, t); @@ -379,6 +458,7 @@ static int ti_qspi_start_transfer_one(struct spi_master *master, m->actual_length += t->len; } +out: mutex_unlock(&qspi->list_lock); m->status = status; @@ -437,7 +517,7 @@ static int ti_qspi_probe(struct platform_device *pdev) { struct ti_qspi *qspi; struct spi_master *master; - struct resource *r; + struct resource *r, *res_ctrl, *res_mmap; struct device_node *np = pdev->dev.of_node; u32 max_freq; int ret = 0, num_cs, irq; @@ -446,7 +526,8 @@ static int ti_qspi_probe(struct platform_device *pdev) if (!master) return -ENOMEM; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD; + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD | + SPI_RX_MMAP; master->bus_num = -1; master->flags = SPI_MASTER_HALF_DUPLEX; @@ -465,7 +546,16 @@ static int ti_qspi_probe(struct platform_device *pdev) qspi->master = master; qspi->dev = &pdev->dev; - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi_base"); + if (r == NULL) { + dev_err(&pdev->dev, "missing platform resources data\n"); + return -ENODEV; + } + + res_mmap = platform_get_resource_byname(pdev, + IORESOURCE_MEM, "qspi_mmap"); + res_ctrl = platform_get_resource_byname(pdev, + IORESOURCE_MEM, "qspi_ctrlmod"); irq = platform_get_irq(pdev, 0); if (irq < 0) { @@ -481,6 +571,23 @@ static int ti_qspi_probe(struct platform_device *pdev) goto free_master; } + if (res_ctrl) { + qspi->ctrl_mod = true; + qspi->ctrl_base = devm_ioremap_resource(&pdev->dev, res_ctrl); + if (IS_ERR(qspi->ctrl_base)) { + ret = PTR_ERR(qspi->ctrl_base); + goto free_master; + } + } + + if (res_mmap) { + qspi->mmap_base = devm_ioremap_resource(&pdev->dev, res_mmap); + if (IS_ERR(qspi->mmap_base)) { + ret = PTR_ERR(qspi->mmap_base); + goto free_master; + } + } + ret = devm_request_irq(&pdev->dev, irq, ti_qspi_isr, 0, dev_name(&pdev->dev), qspi); if (ret < 0) { @@ -504,6 +611,9 @@ static int ti_qspi_probe(struct platform_device *pdev) if (!of_property_read_u32(np, "spi-max-frequency", &max_freq)) qspi->spi_max_frequency = max_freq; + if (of_property_read_bool(np, "mmap_read")) + qspi->memory_mapped = true; + ret = devm_spi_register_master(&pdev->dev, master); if (ret) goto free_master; -- 1.7.1 ^ permalink raw reply related [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-09 15:24 ` Sourav Poddar @ 2013-10-09 16:07 ` Mark Brown -1 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-09 16:07 UTC (permalink / raw) To: Sourav Poddar Cc: spi-devel-general, computersforpeace, dwmw2, balbi, linux-mtd [-- Attachment #1.1: Type: text/plain, Size: 849 bytes --] On Wed, Oct 09, 2013 at 08:54:42PM +0530, Sourav Poddar wrote: > Qspi controller also supports memory mapped read. Patch > adds support for the same. > In memory mapped read, controller need to be switched to a > memory mapped port using a control module register and a qspi > specific register or just a qspi register. > Then the read need to be happened from the memory mapped > address space. Can you provide more details on what exactly this means? Looking at the code it looks awfully like this has the same problem that the Freescale code had with needing to know the commands the flash needs? I'm also concerned about the interface here, it looks like this is being made visible to SPI devices (via a dependency on patch 3/3...) but only as a flag they can set - how would devices know to enable this and why would they want to avoid it? [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] [-- Attachment #2: Type: text/plain, Size: 144 bytes --] ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-09 16:07 ` Mark Brown 0 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-09 16:07 UTC (permalink / raw) To: Sourav Poddar Cc: spi-devel-general, computersforpeace, dwmw2, balbi, linux-mtd [-- Attachment #1: Type: text/plain, Size: 849 bytes --] On Wed, Oct 09, 2013 at 08:54:42PM +0530, Sourav Poddar wrote: > Qspi controller also supports memory mapped read. Patch > adds support for the same. > In memory mapped read, controller need to be switched to a > memory mapped port using a control module register and a qspi > specific register or just a qspi register. > Then the read need to be happened from the memory mapped > address space. Can you provide more details on what exactly this means? Looking at the code it looks awfully like this has the same problem that the Freescale code had with needing to know the commands the flash needs? I'm also concerned about the interface here, it looks like this is being made visible to SPI devices (via a dependency on patch 3/3...) but only as a flag they can set - how would devices know to enable this and why would they want to avoid it? [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 104+ messages in thread
[parent not found: <20131009160759.GQ21581-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>]
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-09 16:07 ` Mark Brown @ 2013-10-09 16:54 ` Sourav Poddar -1 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-09 16:54 UTC (permalink / raw) To: Mark Brown Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, computersforpeace-Re5JQEeQqe8AvxtiuMwx3w, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ, balbi-l0cyMroinI0, linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r On Wednesday 09 October 2013 09:37 PM, Mark Brown wrote: > On Wed, Oct 09, 2013 at 08:54:42PM +0530, Sourav Poddar wrote: > >> Qspi controller also supports memory mapped read. Patch >> adds support for the same. >> In memory mapped read, controller need to be switched to a >> memory mapped port using a control module register and a qspi >> specific register or just a qspi register. >> Then the read need to be happened from the memory mapped >> address space. > Can you provide more details on what exactly this means? Looking at the > code it looks awfully like this has the same problem that the Freescale > code had with needing to know the commands the flash needs? Here is the exact feature usecase.. TI qspi controller supports memory mapped read. These memory mapped read configuration depends on the set_up_register, which can be configured once during in setup apis based on the dt node specifying whether the qspi controller supports memory mapped read or not. Once, the qspi controller is configured for a memory mapped read, the qspi controller does not depend on the flash command that comes from the mtd layer. Because, this command are already configured in QSPI set up register. To use qspi in memory mapped mode, we need to switch to memory mapped port using certain registers(for am43x its only qspi register, while for dra7x its qspi register as well as control module register) and once the memory mapped read is done, switch back to configuration mode register. Basically, its not the commands which need to be communicated from the mtd layer,its just the buffer to fill, len of buffer, offset from where to fill need to be communicated. > I'm also concerned about the interface here, it looks like this is being > made visible to SPI devices (via a dependency on patch 3/3...) but only > as a flag they can set - how would devices know to enable this and why > would they want to avoid it? Set spi->mode in qspi driver based on dt entry and use that in mtd layer to decide whether to use memory mapped or not. The idea is whenever, we call mtd_read api from mtd layer, if memory mapped is set then sending the commands does not matter, what matters is the len to read, buffer to fill and "from" offset to read. Then, the intention was to use the memory_map transfer parameter to communicate to the driver that memory mapped read is used so that we can just use memcopy and return without going through the entire SPI based xfer function. ------------------------------------------------------------------------------ October Webinars: Code for Performance Free Intel webinars can help you accelerate application performance. Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from the latest Intel processors and coprocessors. See abstracts and register > http://pubads.g.doubleclick.net/gampad/clk?id=60134071&iu=/4140/ostg.clktrk ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-09 16:54 ` Sourav Poddar 0 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-09 16:54 UTC (permalink / raw) To: Mark Brown; +Cc: spi-devel-general, computersforpeace, dwmw2, balbi, linux-mtd On Wednesday 09 October 2013 09:37 PM, Mark Brown wrote: > On Wed, Oct 09, 2013 at 08:54:42PM +0530, Sourav Poddar wrote: > >> Qspi controller also supports memory mapped read. Patch >> adds support for the same. >> In memory mapped read, controller need to be switched to a >> memory mapped port using a control module register and a qspi >> specific register or just a qspi register. >> Then the read need to be happened from the memory mapped >> address space. > Can you provide more details on what exactly this means? Looking at the > code it looks awfully like this has the same problem that the Freescale > code had with needing to know the commands the flash needs? Here is the exact feature usecase.. TI qspi controller supports memory mapped read. These memory mapped read configuration depends on the set_up_register, which can be configured once during in setup apis based on the dt node specifying whether the qspi controller supports memory mapped read or not. Once, the qspi controller is configured for a memory mapped read, the qspi controller does not depend on the flash command that comes from the mtd layer. Because, this command are already configured in QSPI set up register. To use qspi in memory mapped mode, we need to switch to memory mapped port using certain registers(for am43x its only qspi register, while for dra7x its qspi register as well as control module register) and once the memory mapped read is done, switch back to configuration mode register. Basically, its not the commands which need to be communicated from the mtd layer,its just the buffer to fill, len of buffer, offset from where to fill need to be communicated. > I'm also concerned about the interface here, it looks like this is being > made visible to SPI devices (via a dependency on patch 3/3...) but only > as a flag they can set - how would devices know to enable this and why > would they want to avoid it? Set spi->mode in qspi driver based on dt entry and use that in mtd layer to decide whether to use memory mapped or not. The idea is whenever, we call mtd_read api from mtd layer, if memory mapped is set then sending the commands does not matter, what matters is the len to read, buffer to fill and "from" offset to read. Then, the intention was to use the memory_map transfer parameter to communicate to the driver that memory mapped read is used so that we can just use memcopy and return without going through the entire SPI based xfer function. ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-09 16:54 ` Sourav Poddar @ 2013-10-09 17:40 ` Mark Brown -1 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-09 17:40 UTC (permalink / raw) To: Sourav Poddar Cc: spi-devel-general, computersforpeace, dwmw2, balbi, linux-mtd [-- Attachment #1.1: Type: text/plain, Size: 3085 bytes --] On Wed, Oct 09, 2013 at 10:24:33PM +0530, Sourav Poddar wrote: > Here is the exact feature usecase.. > TI qspi controller supports memory mapped read. These memory > mapped read configuration depends on the set_up_register, which > can be configured once during in setup apis based on the dt node > specifying whether the qspi controller supports memory mapped read > or not. What is "set_up_register"? > Once, the qspi controller is configured for a memory mapped read, the qspi > controller does not depend on the flash command that comes from the > mtd layer. > Because, this command are already configured in QSPI set up register. So this does depend on the flash commands for the specific chip, which means that this has all the same problems as the Freescale chip had with requiring the user to replicate the information about the commands that the chip supports into the device tree. It therefore seems like all the same concerns should apply, though in this case it seems like it's harder for the driver to infer things from looking at the operations being sent to it. Presumably this also only works for flash chips, or things that look like them... > Basically, its not the commands which need to be communicated from > the mtd layer,its just > the buffer to fill, len of buffer, offset from where to fill need to > be communicated. This appears to be based on an assumption that the commands would be replicated into the device trees which seems like it's both more work for users and harder to deploy. > >I'm also concerned about the interface here, it looks like this is being > >made visible to SPI devices (via a dependency on patch 3/3...) but only > >as a flag they can set - how would devices know to enable this and why > >would they want to avoid it? > Set spi->mode in qspi driver based on dt entry and use that in mtd layer to > decide whether to use memory mapped or not. But why would anything not want to use memory mapped mode if it can and why is this something that should be hard coded into the device tree? Especially with the current API... > The idea is whenever, we call mtd_read api from mtd layer, if memory > mapped is set > then sending the commands does not matter, what matters is the len > to read, buffer to fill and > "from" offset to read. Then, the intention was to use the memory_map > transfer parameter to > communicate to the driver that memory mapped read is used so that we > can just use memcopy and > return without going through the entire SPI based xfer function. I'm not convinced that this is the most useful API, it sounds like the hardware can "memory map" the entire flash chip so the whole SPI framework seems like overhead. It also seems seems like it's going to involve the CPU being stalled waiting for reads to complete instead of asking the SPI controller to DMA the data to RAM and allowing the CPU to get on with other things - replacing the explicit transmission of commands with memory to memory DMAs might be advantageous but replacing DMA with memcpy() would need numbers to show that it was a win. [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] [-- Attachment #2: Type: text/plain, Size: 144 bytes --] ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-09 17:40 ` Mark Brown 0 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-09 17:40 UTC (permalink / raw) To: Sourav Poddar Cc: spi-devel-general, computersforpeace, dwmw2, balbi, linux-mtd [-- Attachment #1: Type: text/plain, Size: 3085 bytes --] On Wed, Oct 09, 2013 at 10:24:33PM +0530, Sourav Poddar wrote: > Here is the exact feature usecase.. > TI qspi controller supports memory mapped read. These memory > mapped read configuration depends on the set_up_register, which > can be configured once during in setup apis based on the dt node > specifying whether the qspi controller supports memory mapped read > or not. What is "set_up_register"? > Once, the qspi controller is configured for a memory mapped read, the qspi > controller does not depend on the flash command that comes from the > mtd layer. > Because, this command are already configured in QSPI set up register. So this does depend on the flash commands for the specific chip, which means that this has all the same problems as the Freescale chip had with requiring the user to replicate the information about the commands that the chip supports into the device tree. It therefore seems like all the same concerns should apply, though in this case it seems like it's harder for the driver to infer things from looking at the operations being sent to it. Presumably this also only works for flash chips, or things that look like them... > Basically, its not the commands which need to be communicated from > the mtd layer,its just > the buffer to fill, len of buffer, offset from where to fill need to > be communicated. This appears to be based on an assumption that the commands would be replicated into the device trees which seems like it's both more work for users and harder to deploy. > >I'm also concerned about the interface here, it looks like this is being > >made visible to SPI devices (via a dependency on patch 3/3...) but only > >as a flag they can set - how would devices know to enable this and why > >would they want to avoid it? > Set spi->mode in qspi driver based on dt entry and use that in mtd layer to > decide whether to use memory mapped or not. But why would anything not want to use memory mapped mode if it can and why is this something that should be hard coded into the device tree? Especially with the current API... > The idea is whenever, we call mtd_read api from mtd layer, if memory > mapped is set > then sending the commands does not matter, what matters is the len > to read, buffer to fill and > "from" offset to read. Then, the intention was to use the memory_map > transfer parameter to > communicate to the driver that memory mapped read is used so that we > can just use memcopy and > return without going through the entire SPI based xfer function. I'm not convinced that this is the most useful API, it sounds like the hardware can "memory map" the entire flash chip so the whole SPI framework seems like overhead. It also seems seems like it's going to involve the CPU being stalled waiting for reads to complete instead of asking the SPI controller to DMA the data to RAM and allowing the CPU to get on with other things - replacing the explicit transmission of commands with memory to memory DMAs might be advantageous but replacing DMA with memcpy() would need numbers to show that it was a win. [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-09 17:40 ` Mark Brown @ 2013-10-09 18:15 ` Sourav Poddar -1 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-09 18:15 UTC (permalink / raw) To: Mark Brown; +Cc: spi-devel-general, computersforpeace, dwmw2, balbi, linux-mtd On Wednesday 09 October 2013 11:10 PM, Mark Brown wrote: > On Wed, Oct 09, 2013 at 10:24:33PM +0530, Sourav Poddar wrote: > >> Here is the exact feature usecase.. >> TI qspi controller supports memory mapped read. These memory >> mapped read configuration depends on the set_up_register, which >> can be configured once during in setup apis based on the dt node >> specifying whether the qspi controller supports memory mapped read >> or not. > What is "set_up_register"? set_up_register is a memory mapped specific register with the following fields: - RCMD (Read command, which is actually the flash read command) - NUmber of Address bytes - Number of dummy bytes - Read type(Single, dual and quad read). - Write command. >> Once, the qspi controller is configured for a memory mapped read, the qspi >> controller does not depend on the flash command that comes from the >> mtd layer. >> Because, this command are already configured in QSPI set up register. > So this does depend on the flash commands for the specific chip, which > means that this has all the same problems as the Freescale chip had with > requiring the user to replicate the information about the commands that > the chip supports into the device tree. It therefore seems like all the > same concerns should apply, though in this case it seems like it's > harder for the driver to infer things from looking at the operations > being sent to it. > > Presumably this also only works for flash chips, or things that look > like them... > Yes, true, it depends on flash command, though it is getting filled now in my driver itself. >> Basically, its not the commands which need to be communicated from >> the mtd layer,its just >> the buffer to fill, len of buffer, offset from where to fill need to >> be communicated. > This appears to be based on an assumption that the commands would be > replicated into the device trees which seems like it's both more work > for users and harder to deploy. > >>> I'm also concerned about the interface here, it looks like this is being >>> made visible to SPI devices (via a dependency on patch 3/3...) but only >>> as a flag they can set - how would devices know to enable this and why >>> would they want to avoid it? >> Set spi->mode in qspi driver based on dt entry and use that in mtd layer to >> decide whether to use memory mapped or not. > But why would anything not want to use memory mapped mode if it can and > why is this something that should be hard coded into the device tree? > Especially with the current API... > Thats true, by default also we can keep the memory mapped read. Though, according to the current implementation spi->mode can be set so that in mtd layer, we might use that to selectively used t[o].memory_map. >> The idea is whenever, we call mtd_read api from mtd layer, if memory >> mapped is set >> then sending the commands does not matter, what matters is the len >> to read, buffer to fill and >> "from" offset to read. Then, the intention was to use the memory_map >> transfer parameter to >> communicate to the driver that memory mapped read is used so that we >> can just use memcopy and >> return without going through the entire SPI based xfer function. > I'm not convinced that this is the most useful API, it sounds like the > hardware can "memory map" the entire flash chip so the whole SPI > framework seems like overhead. > But this memory map read will work only with read opcodes.(mtd_read path). For all other operations, normal SPI operations will be used. As for this, I also though of bypassing the SPI frameowrk, and doing a memcopy at the beginning of the mtd_read api. But, then before doing a memory mapped read - 1. Controller need to be switched to memory mapped port using control module register and ti qspi switch register. 2. There is SOC specific memory mapped address space from where read should happen, this is SOC specific and should be known to mtd layer the adreess to read for. So, I thought of going this way using t.memory map flag. > It also seems seems like it's going to involve the CPU being stalled > waiting for reads to complete instead of asking the SPI controller to > DMA the data to RAM and allowing the CPU to get on with other things - > replacing the explicit transmission of commands with memory to memory > DMAs might be advantageous but replacing DMA with memcpy() would need > numbers to show that it was a win. ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-09 18:15 ` Sourav Poddar 0 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-09 18:15 UTC (permalink / raw) To: Mark Brown; +Cc: spi-devel-general, computersforpeace, dwmw2, balbi, linux-mtd On Wednesday 09 October 2013 11:10 PM, Mark Brown wrote: > On Wed, Oct 09, 2013 at 10:24:33PM +0530, Sourav Poddar wrote: > >> Here is the exact feature usecase.. >> TI qspi controller supports memory mapped read. These memory >> mapped read configuration depends on the set_up_register, which >> can be configured once during in setup apis based on the dt node >> specifying whether the qspi controller supports memory mapped read >> or not. > What is "set_up_register"? set_up_register is a memory mapped specific register with the following fields: - RCMD (Read command, which is actually the flash read command) - NUmber of Address bytes - Number of dummy bytes - Read type(Single, dual and quad read). - Write command. >> Once, the qspi controller is configured for a memory mapped read, the qspi >> controller does not depend on the flash command that comes from the >> mtd layer. >> Because, this command are already configured in QSPI set up register. > So this does depend on the flash commands for the specific chip, which > means that this has all the same problems as the Freescale chip had with > requiring the user to replicate the information about the commands that > the chip supports into the device tree. It therefore seems like all the > same concerns should apply, though in this case it seems like it's > harder for the driver to infer things from looking at the operations > being sent to it. > > Presumably this also only works for flash chips, or things that look > like them... > Yes, true, it depends on flash command, though it is getting filled now in my driver itself. >> Basically, its not the commands which need to be communicated from >> the mtd layer,its just >> the buffer to fill, len of buffer, offset from where to fill need to >> be communicated. > This appears to be based on an assumption that the commands would be > replicated into the device trees which seems like it's both more work > for users and harder to deploy. > >>> I'm also concerned about the interface here, it looks like this is being >>> made visible to SPI devices (via a dependency on patch 3/3...) but only >>> as a flag they can set - how would devices know to enable this and why >>> would they want to avoid it? >> Set spi->mode in qspi driver based on dt entry and use that in mtd layer to >> decide whether to use memory mapped or not. > But why would anything not want to use memory mapped mode if it can and > why is this something that should be hard coded into the device tree? > Especially with the current API... > Thats true, by default also we can keep the memory mapped read. Though, according to the current implementation spi->mode can be set so that in mtd layer, we might use that to selectively used t[o].memory_map. >> The idea is whenever, we call mtd_read api from mtd layer, if memory >> mapped is set >> then sending the commands does not matter, what matters is the len >> to read, buffer to fill and >> "from" offset to read. Then, the intention was to use the memory_map >> transfer parameter to >> communicate to the driver that memory mapped read is used so that we >> can just use memcopy and >> return without going through the entire SPI based xfer function. > I'm not convinced that this is the most useful API, it sounds like the > hardware can "memory map" the entire flash chip so the whole SPI > framework seems like overhead. > But this memory map read will work only with read opcodes.(mtd_read path). For all other operations, normal SPI operations will be used. As for this, I also though of bypassing the SPI frameowrk, and doing a memcopy at the beginning of the mtd_read api. But, then before doing a memory mapped read - 1. Controller need to be switched to memory mapped port using control module register and ti qspi switch register. 2. There is SOC specific memory mapped address space from where read should happen, this is SOC specific and should be known to mtd layer the adreess to read for. So, I thought of going this way using t.memory map flag. > It also seems seems like it's going to involve the CPU being stalled > waiting for reads to complete instead of asking the SPI controller to > DMA the data to RAM and allowing the CPU to get on with other things - > replacing the explicit transmission of commands with memory to memory > DMAs might be advantageous but replacing DMA with memcpy() would need > numbers to show that it was a win. ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-09 18:15 ` Sourav Poddar @ 2013-10-09 18:41 ` Mark Brown -1 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-09 18:41 UTC (permalink / raw) To: Sourav Poddar Cc: spi-devel-general, computersforpeace, dwmw2, balbi, linux-mtd [-- Attachment #1.1: Type: text/plain, Size: 1709 bytes --] On Wed, Oct 09, 2013 at 11:45:46PM +0530, Sourav Poddar wrote: > On Wednesday 09 October 2013 11:10 PM, Mark Brown wrote: > >I'm not convinced that this is the most useful API, it sounds like the > >hardware can "memory map" the entire flash chip so the whole SPI > >framework seems like overhead. > But this memory map read will work only with read opcodes.(mtd_read > path). For all other operations, normal SPI operations will be used. > As for this, I also though of bypassing the SPI frameowrk, and doing > a memcopy > at the beginning of the mtd_read api. But, then before doing a memory mapped > read - > 1. Controller need to be switched to memory mapped port using control module > register and ti qspi switch register. > 2. There is SOC specific memory mapped address space from where read > should happen, > this is SOC specific and should be known to mtd layer the > adreess to read for. > So, I thought of going this way using t.memory map flag. Sure, but these things sound like we should be able to support them without having to bounce over to the SPI thread all the time and... > >It also seems seems like it's going to involve the CPU being stalled > >waiting for reads to complete instead of asking the SPI controller to > >DMA the data to RAM and allowing the CPU to get on with other things - > >replacing the explicit transmission of commands with memory to memory > >DMAs might be advantageous but replacing DMA with memcpy() would need > >numbers to show that it was a win. ...like I say it's not clear to me that this is actually a change that's going to be beneficial. I'd really like to see some analysis of the performance showing that this helps and why it helps. [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] [-- Attachment #2: Type: text/plain, Size: 144 bytes --] ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-09 18:41 ` Mark Brown 0 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-09 18:41 UTC (permalink / raw) To: Sourav Poddar Cc: spi-devel-general, computersforpeace, dwmw2, balbi, linux-mtd [-- Attachment #1: Type: text/plain, Size: 1709 bytes --] On Wed, Oct 09, 2013 at 11:45:46PM +0530, Sourav Poddar wrote: > On Wednesday 09 October 2013 11:10 PM, Mark Brown wrote: > >I'm not convinced that this is the most useful API, it sounds like the > >hardware can "memory map" the entire flash chip so the whole SPI > >framework seems like overhead. > But this memory map read will work only with read opcodes.(mtd_read > path). For all other operations, normal SPI operations will be used. > As for this, I also though of bypassing the SPI frameowrk, and doing > a memcopy > at the beginning of the mtd_read api. But, then before doing a memory mapped > read - > 1. Controller need to be switched to memory mapped port using control module > register and ti qspi switch register. > 2. There is SOC specific memory mapped address space from where read > should happen, > this is SOC specific and should be known to mtd layer the > adreess to read for. > So, I thought of going this way using t.memory map flag. Sure, but these things sound like we should be able to support them without having to bounce over to the SPI thread all the time and... > >It also seems seems like it's going to involve the CPU being stalled > >waiting for reads to complete instead of asking the SPI controller to > >DMA the data to RAM and allowing the CPU to get on with other things - > >replacing the explicit transmission of commands with memory to memory > >DMAs might be advantageous but replacing DMA with memcpy() would need > >numbers to show that it was a win. ...like I say it's not clear to me that this is actually a change that's going to be beneficial. I'd really like to see some analysis of the performance showing that this helps and why it helps. [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 104+ messages in thread
[parent not found: <20131009174027.GS21581-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>]
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-09 17:40 ` Mark Brown @ 2013-10-09 19:01 ` Peter Korsgaard -1 siblings, 0 replies; 104+ messages in thread From: Peter Korsgaard @ 2013-10-09 19:01 UTC (permalink / raw) To: Mark Brown Cc: balbi-l0cyMroinI0, linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Sourav Poddar, computersforpeace-Re5JQEeQqe8AvxtiuMwx3w, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ >>>>> "Mark" == Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> writes: Hi, Mark> I'm not convinced that this is the most useful API, it sounds like the Mark> hardware can "memory map" the entire flash chip so the whole SPI Mark> framework seems like overhead. Mark> It also seems seems like it's going to involve the CPU being Mark> stalled waiting for reads to complete instead of asking the SPI Mark> controller to DMA the data to RAM and allowing the CPU to get on Mark> with other things - replacing the explicit transmission of Mark> commands with memory to memory DMAs might be advantageous but Mark> replacing DMA with memcpy() would need numbers to show that it Mark> was a win. Indeed. I can see how such a feature could be useful in E.G. a lowlevel bootloader (because of simplicity), but am less convinced about it in Linux where we could conceivable do something else useful while waiting on the spi controller. But if there's number to prove otherwise.. -- Bye, Peter Korsgaard ------------------------------------------------------------------------------ October Webinars: Code for Performance Free Intel webinars can help you accelerate application performance. Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from the latest Intel processors and coprocessors. See abstracts and register > http://pubads.g.doubleclick.net/gampad/clk?id=60134071&iu=/4140/ostg.clktrk ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-09 19:01 ` Peter Korsgaard 0 siblings, 0 replies; 104+ messages in thread From: Peter Korsgaard @ 2013-10-09 19:01 UTC (permalink / raw) To: Mark Brown Cc: balbi, linux-mtd, spi-devel-general, Sourav Poddar, computersforpeace, dwmw2 >>>>> "Mark" == Mark Brown <broonie@kernel.org> writes: Hi, Mark> I'm not convinced that this is the most useful API, it sounds like the Mark> hardware can "memory map" the entire flash chip so the whole SPI Mark> framework seems like overhead. Mark> It also seems seems like it's going to involve the CPU being Mark> stalled waiting for reads to complete instead of asking the SPI Mark> controller to DMA the data to RAM and allowing the CPU to get on Mark> with other things - replacing the explicit transmission of Mark> commands with memory to memory DMAs might be advantageous but Mark> replacing DMA with memcpy() would need numbers to show that it Mark> was a win. Indeed. I can see how such a feature could be useful in E.G. a lowlevel bootloader (because of simplicity), but am less convinced about it in Linux where we could conceivable do something else useful while waiting on the spi controller. But if there's number to prove otherwise.. -- Bye, Peter Korsgaard ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-09 19:01 ` Peter Korsgaard @ 2013-10-09 19:36 ` Mark Brown -1 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-09 19:36 UTC (permalink / raw) To: Peter Korsgaard Cc: balbi, linux-mtd, spi-devel-general, Sourav Poddar, computersforpeace, dwmw2 [-- Attachment #1.1: Type: text/plain, Size: 883 bytes --] On Wed, Oct 09, 2013 at 09:01:59PM +0200, Peter Korsgaard wrote: > Indeed. I can see how such a feature could be useful in E.G. a lowlevel > bootloader (because of simplicity), but am less convinced about it in > Linux where we could conceivable do something else useful while waiting > on the spi controller. > But if there's number to prove otherwise.. I can see it being useful if there's a DMA controller that can do the transfer as a memory to memory DMA - the hardware can probably issue flash read commands a bit faster than the AP can so you should be able to get closer to saturating the bus. The patches didn't try to do that or make it possible for something further up the stack to do it and the differences should end up being fairly small with optimisations like those in the pxa2xx or pl022 drivers (which I'm currently working on pulling out into the framework). [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] [-- Attachment #2: Type: text/plain, Size: 144 bytes --] ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-09 19:36 ` Mark Brown 0 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-09 19:36 UTC (permalink / raw) To: Peter Korsgaard Cc: balbi, linux-mtd, spi-devel-general, Sourav Poddar, computersforpeace, dwmw2 [-- Attachment #1: Type: text/plain, Size: 883 bytes --] On Wed, Oct 09, 2013 at 09:01:59PM +0200, Peter Korsgaard wrote: > Indeed. I can see how such a feature could be useful in E.G. a lowlevel > bootloader (because of simplicity), but am less convinced about it in > Linux where we could conceivable do something else useful while waiting > on the spi controller. > But if there's number to prove otherwise.. I can see it being useful if there's a DMA controller that can do the transfer as a memory to memory DMA - the hardware can probably issue flash read commands a bit faster than the AP can so you should be able to get closer to saturating the bus. The patches didn't try to do that or make it possible for something further up the stack to do it and the differences should end up being fairly small with optimisations like those in the pxa2xx or pl022 drivers (which I'm currently working on pulling out into the framework). [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 104+ messages in thread
[parent not found: <87hacq1d5k.fsf-D6SC8u56vOOJDPpyT6T3/w@public.gmane.org>]
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-09 19:01 ` Peter Korsgaard @ 2013-10-10 2:27 ` Trent Piepho -1 siblings, 0 replies; 104+ messages in thread From: Trent Piepho @ 2013-10-10 2:27 UTC (permalink / raw) To: Peter Korsgaard Cc: balbi-l0cyMroinI0, Mark Brown, linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Sourav Poddar, computersforpeace-Re5JQEeQqe8AvxtiuMwx3w, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ On Wed, Oct 9, 2013 at 12:01 PM, Peter Korsgaard <peter-+2lRwdCCLRT2eFz/2MeuCQ@public.gmane.org> wrote: >>>>>> "Mark" == Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> writes: > Mark> I'm not convinced that this is the most useful API, it sounds like the > Mark> hardware can "memory map" the entire flash chip so the whole SPI > Mark> framework seems like overhead. > > Mark> It also seems seems like it's going to involve the CPU being > Mark> stalled waiting for reads to complete instead of asking the SPI > Mark> controller to DMA the data to RAM and allowing the CPU to get on > Mark> with other things - replacing the explicit transmission of > Mark> commands with memory to memory DMAs might be advantageous but > Mark> replacing DMA with memcpy() would need numbers to show that it > Mark> was a win. > > Indeed. I can see how such a feature could be useful in E.G. a lowlevel > bootloader (because of simplicity), but am less convinced about it in > Linux where we could conceivable do something else useful while waiting > on the spi controller. I've found that the SPI layer adds rather a lot of overhead to SPI transactions. It appears to come mostly from using another thread to run the queue. A fast SPI message of a few dozen bytes ends up having more overhead from the SPI layer than the time it takes the driver to do the actual transfer. So memory mapped mode via some kind of SPI hack seems like a bad design. All the SPI layer overhead and you don't get DMA. Memory mapped SPI could be a win, but I think you'd need to do it at the MTD layer with a mapping driver that could read the mmapped SPI flash directly. ------------------------------------------------------------------------------ October Webinars: Code for Performance Free Intel webinars can help you accelerate application performance. Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from the latest Intel processors and coprocessors. See abstracts and register > http://pubads.g.doubleclick.net/gampad/clk?id=60134071&iu=/4140/ostg.clktrk ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-10 2:27 ` Trent Piepho 0 siblings, 0 replies; 104+ messages in thread From: Trent Piepho @ 2013-10-10 2:27 UTC (permalink / raw) To: Peter Korsgaard Cc: balbi, Mark Brown, linux-mtd, spi-devel-general, Sourav Poddar, computersforpeace, dwmw2 On Wed, Oct 9, 2013 at 12:01 PM, Peter Korsgaard <peter@korsgaard.com> wrote: >>>>>> "Mark" == Mark Brown <broonie@kernel.org> writes: > Mark> I'm not convinced that this is the most useful API, it sounds like the > Mark> hardware can "memory map" the entire flash chip so the whole SPI > Mark> framework seems like overhead. > > Mark> It also seems seems like it's going to involve the CPU being > Mark> stalled waiting for reads to complete instead of asking the SPI > Mark> controller to DMA the data to RAM and allowing the CPU to get on > Mark> with other things - replacing the explicit transmission of > Mark> commands with memory to memory DMAs might be advantageous but > Mark> replacing DMA with memcpy() would need numbers to show that it > Mark> was a win. > > Indeed. I can see how such a feature could be useful in E.G. a lowlevel > bootloader (because of simplicity), but am less convinced about it in > Linux where we could conceivable do something else useful while waiting > on the spi controller. I've found that the SPI layer adds rather a lot of overhead to SPI transactions. It appears to come mostly from using another thread to run the queue. A fast SPI message of a few dozen bytes ends up having more overhead from the SPI layer than the time it takes the driver to do the actual transfer. So memory mapped mode via some kind of SPI hack seems like a bad design. All the SPI layer overhead and you don't get DMA. Memory mapped SPI could be a win, but I think you'd need to do it at the MTD layer with a mapping driver that could read the mmapped SPI flash directly. ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-10 2:27 ` Trent Piepho @ 2013-10-10 8:52 ` Sourav Poddar -1 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-10 8:52 UTC (permalink / raw) To: Trent Piepho, Peter Korsgaard, Mark Brown Cc: spi-devel-general, computersforpeace, linux-mtd, dwmw2, balbi Hi All, On Thursday 10 October 2013 07:57 AM, Trent Piepho wrote: > On Wed, Oct 9, 2013 at 12:01 PM, Peter Korsgaard<peter@korsgaard.com> wrote: >>>>>>> "Mark" == Mark Brown<broonie@kernel.org> writes: >> Mark> I'm not convinced that this is the most useful API, it sounds like the >> Mark> hardware can "memory map" the entire flash chip so the whole SPI >> Mark> framework seems like overhead. >> >> Mark> It also seems seems like it's going to involve the CPU being >> Mark> stalled waiting for reads to complete instead of asking the SPI >> Mark> controller to DMA the data to RAM and allowing the CPU to get on >> Mark> with other things - replacing the explicit transmission of >> Mark> commands with memory to memory DMAs might be advantageous but >> Mark> replacing DMA with memcpy() would need numbers to show that it >> Mark> was a win. >> >> Indeed. I can see how such a feature could be useful in E.G. a lowlevel >> bootloader (because of simplicity), but am less convinced about it in >> Linux where we could conceivable do something else useful while waiting >> on the spi controller. > I've found that the SPI layer adds rather a lot of overhead to SPI > transactions. It appears to come mostly from using another thread to > run the queue. A fast SPI message of a few dozen bytes ends up having > more overhead from the SPI layer than the time it takes the driver to > do the actual transfer. > > So memory mapped mode via some kind of SPI hack seems like a bad > design. All the SPI layer overhead and you don't get DMA. Memory > mapped SPI could be a win, but I think you'd need to do it at the MTD > layer with a mapping driver that could read the mmapped SPI flash > directly. Yes, you are correct in all your comments above. I also feel that SPI framework should be bypassed. But the subject patch is derived based on the following points/limitation: 1. There is a setup register in QSPI, that need to be filled, as of now I am filling it in my driver as a MACRO. 2. Controller repsonds to memory mapped read for read opcodes, so during the read path we should tell the controller to switch to memory mapped port. [Trent]: With mapping driver, I believe you are hinting at drivers/mtd/maps? I had a look at it and what I got is that it is used/suitable for parallel flashes and not the serial flashes. All in all, Just at the beginning of the read api, I could have done memory mapped read and bypass the spi framework. But, prior to that above 1, 2 point need to be executed and that need to be communicated to controller driver. ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-10 8:52 ` Sourav Poddar 0 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-10 8:52 UTC (permalink / raw) To: Trent Piepho, Peter Korsgaard, Mark Brown Cc: spi-devel-general, computersforpeace, linux-mtd, dwmw2, balbi Hi All, On Thursday 10 October 2013 07:57 AM, Trent Piepho wrote: > On Wed, Oct 9, 2013 at 12:01 PM, Peter Korsgaard<peter@korsgaard.com> wrote: >>>>>>> "Mark" == Mark Brown<broonie@kernel.org> writes: >> Mark> I'm not convinced that this is the most useful API, it sounds like the >> Mark> hardware can "memory map" the entire flash chip so the whole SPI >> Mark> framework seems like overhead. >> >> Mark> It also seems seems like it's going to involve the CPU being >> Mark> stalled waiting for reads to complete instead of asking the SPI >> Mark> controller to DMA the data to RAM and allowing the CPU to get on >> Mark> with other things - replacing the explicit transmission of >> Mark> commands with memory to memory DMAs might be advantageous but >> Mark> replacing DMA with memcpy() would need numbers to show that it >> Mark> was a win. >> >> Indeed. I can see how such a feature could be useful in E.G. a lowlevel >> bootloader (because of simplicity), but am less convinced about it in >> Linux where we could conceivable do something else useful while waiting >> on the spi controller. > I've found that the SPI layer adds rather a lot of overhead to SPI > transactions. It appears to come mostly from using another thread to > run the queue. A fast SPI message of a few dozen bytes ends up having > more overhead from the SPI layer than the time it takes the driver to > do the actual transfer. > > So memory mapped mode via some kind of SPI hack seems like a bad > design. All the SPI layer overhead and you don't get DMA. Memory > mapped SPI could be a win, but I think you'd need to do it at the MTD > layer with a mapping driver that could read the mmapped SPI flash > directly. Yes, you are correct in all your comments above. I also feel that SPI framework should be bypassed. But the subject patch is derived based on the following points/limitation: 1. There is a setup register in QSPI, that need to be filled, as of now I am filling it in my driver as a MACRO. 2. Controller repsonds to memory mapped read for read opcodes, so during the read path we should tell the controller to switch to memory mapped port. [Trent]: With mapping driver, I believe you are hinting at drivers/mtd/maps? I had a look at it and what I got is that it is used/suitable for parallel flashes and not the serial flashes. All in all, Just at the beginning of the read api, I could have done memory mapped read and bypass the spi framework. But, prior to that above 1, 2 point need to be executed and that need to be communicated to controller driver. ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-10 8:52 ` Sourav Poddar @ 2013-10-10 10:14 ` Mark Brown -1 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-10 10:14 UTC (permalink / raw) To: Sourav Poddar Cc: Peter Korsgaard, Trent Piepho, balbi, linux-mtd, spi-devel-general, computersforpeace, dwmw2 [-- Attachment #1.1: Type: text/plain, Size: 487 bytes --] On Thu, Oct 10, 2013 at 02:22:28PM +0530, Sourav Poddar wrote: > [Trent]: With mapping driver, I believe you are hinting at > drivers/mtd/maps? I had > a look at it and what I got is that it is used/suitable for parallel > flashes and not the > serial flashes. Essentially what it looks like this hardware is trying to do is adapt a serial flash so it looks more like a parallel flash. It's not clear that this is a good idea if we are already able to understand serial flash though. [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] [-- Attachment #2: Type: text/plain, Size: 144 bytes --] ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-10 10:14 ` Mark Brown 0 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-10 10:14 UTC (permalink / raw) To: Sourav Poddar Cc: Peter Korsgaard, Trent Piepho, balbi, linux-mtd, spi-devel-general, computersforpeace, dwmw2 [-- Attachment #1: Type: text/plain, Size: 487 bytes --] On Thu, Oct 10, 2013 at 02:22:28PM +0530, Sourav Poddar wrote: > [Trent]: With mapping driver, I believe you are hinting at > drivers/mtd/maps? I had > a look at it and what I got is that it is used/suitable for parallel > flashes and not the > serial flashes. Essentially what it looks like this hardware is trying to do is adapt a serial flash so it looks more like a parallel flash. It's not clear that this is a good idea if we are already able to understand serial flash though. [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-10 10:14 ` Mark Brown @ 2013-10-10 10:17 ` Sourav Poddar -1 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-10 10:17 UTC (permalink / raw) To: Mark Brown Cc: Peter Korsgaard, Trent Piepho, balbi, linux-mtd, spi-devel-general, computersforpeace, dwmw2 On Thursday 10 October 2013 03:44 PM, Mark Brown wrote: > On Thu, Oct 10, 2013 at 02:22:28PM +0530, Sourav Poddar wrote: > >> [Trent]: With mapping driver, I believe you are hinting at >> drivers/mtd/maps? I had >> a look at it and what I got is that it is used/suitable for parallel >> flashes and not the >> serial flashes. > Essentially what it looks like this hardware is trying to do is adapt a > serial flash so it looks more like a parallel flash. It's not clear > that this is a good idea if we are already able to understand serial > flash though. hmm.. one more point I want to add is that QSPI controller has two parts to it: 1. SPI mode (used for SPI based external devices) 2. SFI mode (Serial flash interface) used for flash devices attached. Memory mapped mode is the one more applicable to the second one. ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-10 10:17 ` Sourav Poddar 0 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-10 10:17 UTC (permalink / raw) To: Mark Brown Cc: Peter Korsgaard, Trent Piepho, balbi, linux-mtd, spi-devel-general, computersforpeace, dwmw2 On Thursday 10 October 2013 03:44 PM, Mark Brown wrote: > On Thu, Oct 10, 2013 at 02:22:28PM +0530, Sourav Poddar wrote: > >> [Trent]: With mapping driver, I believe you are hinting at >> drivers/mtd/maps? I had >> a look at it and what I got is that it is used/suitable for parallel >> flashes and not the >> serial flashes. > Essentially what it looks like this hardware is trying to do is adapt a > serial flash so it looks more like a parallel flash. It's not clear > that this is a good idea if we are already able to understand serial > flash though. hmm.. one more point I want to add is that QSPI controller has two parts to it: 1. SPI mode (used for SPI based external devices) 2. SFI mode (Serial flash interface) used for flash devices attached. Memory mapped mode is the one more applicable to the second one. ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-10 10:14 ` Mark Brown @ 2013-10-10 11:08 ` Sourav Poddar -1 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-10 11:08 UTC (permalink / raw) To: Mark Brown Cc: Peter Korsgaard, Trent Piepho, balbi, linux-mtd, spi-devel-general, computersforpeace, dwmw2 Hi Mark, On Thursday 10 October 2013 03:44 PM, Mark Brown wrote: > On Thu, Oct 10, 2013 at 02:22:28PM +0530, Sourav Poddar wrote: > >> [Trent]: With mapping driver, I believe you are hinting at >> drivers/mtd/maps? I had >> a look at it and what I got is that it is used/suitable for parallel >> flashes and not the >> serial flashes. > Essentially what it looks like this hardware is trying to do is adapt a > serial flash so it looks more like a parallel flash. It's not clear > that this is a good idea if we are already able to understand serial > flash though. Do you have any idea of how to go about implementing it in a more cleaner way?(taking care of all what the spi controller hardware needs to do for the memory mapped mode.). I understand doing a memcpy in the caller itself, but how to tackle the spi controller configuration at that point of time. Memory mapped is a spi controller feature rather than a flash. ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-10 11:08 ` Sourav Poddar 0 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-10 11:08 UTC (permalink / raw) To: Mark Brown Cc: Peter Korsgaard, Trent Piepho, balbi, linux-mtd, spi-devel-general, computersforpeace, dwmw2 Hi Mark, On Thursday 10 October 2013 03:44 PM, Mark Brown wrote: > On Thu, Oct 10, 2013 at 02:22:28PM +0530, Sourav Poddar wrote: > >> [Trent]: With mapping driver, I believe you are hinting at >> drivers/mtd/maps? I had >> a look at it and what I got is that it is used/suitable for parallel >> flashes and not the >> serial flashes. > Essentially what it looks like this hardware is trying to do is adapt a > serial flash so it looks more like a parallel flash. It's not clear > that this is a good idea if we are already able to understand serial > flash though. Do you have any idea of how to go about implementing it in a more cleaner way?(taking care of all what the spi controller hardware needs to do for the memory mapped mode.). I understand doing a memcpy in the caller itself, but how to tackle the spi controller configuration at that point of time. Memory mapped is a spi controller feature rather than a flash. ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-10 11:08 ` Sourav Poddar @ 2013-10-11 10:08 ` Mark Brown -1 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-11 10:08 UTC (permalink / raw) To: Sourav Poddar Cc: Peter Korsgaard, Trent Piepho, balbi, linux-mtd, spi-devel-general, computersforpeace, dwmw2 [-- Attachment #1.1: Type: text/plain, Size: 967 bytes --] On Thu, Oct 10, 2013 at 04:38:19PM +0530, Sourav Poddar wrote: > On Thursday 10 October 2013 03:44 PM, Mark Brown wrote: > >Essentially what it looks like this hardware is trying to do is adapt a > >serial flash so it looks more like a parallel flash. It's not clear > >that this is a good idea if we are already able to understand serial > >flash though. > Do you have any idea of how to go about implementing it in a more > cleaner way?(taking care of all what the spi controller hardware needs to > do for the memory mapped mode.). I understand doing a memcpy in the caller > itself, but how to tackle the spi controller configuration at that > point of time. You'd need to lock the bus and return the address for the caller to use until it released the lock. Like I say I'd want to see numbers on this helping though. > Memory mapped is a spi controller feature rather than a flash. The way it appears to be implemented is pretty flash specific isn't it? [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] [-- Attachment #2: Type: text/plain, Size: 144 bytes --] ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-11 10:08 ` Mark Brown 0 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-11 10:08 UTC (permalink / raw) To: Sourav Poddar Cc: Peter Korsgaard, Trent Piepho, balbi, linux-mtd, spi-devel-general, computersforpeace, dwmw2 [-- Attachment #1: Type: text/plain, Size: 967 bytes --] On Thu, Oct 10, 2013 at 04:38:19PM +0530, Sourav Poddar wrote: > On Thursday 10 October 2013 03:44 PM, Mark Brown wrote: > >Essentially what it looks like this hardware is trying to do is adapt a > >serial flash so it looks more like a parallel flash. It's not clear > >that this is a good idea if we are already able to understand serial > >flash though. > Do you have any idea of how to go about implementing it in a more > cleaner way?(taking care of all what the spi controller hardware needs to > do for the memory mapped mode.). I understand doing a memcpy in the caller > itself, but how to tackle the spi controller configuration at that > point of time. You'd need to lock the bus and return the address for the caller to use until it released the lock. Like I say I'd want to see numbers on this helping though. > Memory mapped is a spi controller feature rather than a flash. The way it appears to be implemented is pretty flash specific isn't it? [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-11 10:08 ` Mark Brown @ 2013-10-15 6:06 ` Sourav Poddar -1 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-15 6:06 UTC (permalink / raw) To: Mark Brown Cc: Peter Korsgaard, Trent Piepho, balbi, linux-mtd, spi-devel-general, computersforpeace, dwmw2 Hi Mark, On Friday 11 October 2013 03:38 PM, Mark Brown wrote: > On Thu, Oct 10, 2013 at 04:38:19PM +0530, Sourav Poddar wrote: >> On Thursday 10 October 2013 03:44 PM, Mark Brown wrote: >>> Essentially what it looks like this hardware is trying to do is adapt a >>> serial flash so it looks more like a parallel flash. It's not clear >>> that this is a good idea if we are already able to understand serial >>> flash though. >> Do you have any idea of how to go about implementing it in a more >> cleaner way?(taking care of all what the spi controller hardware needs to >> do for the memory mapped mode.). I understand doing a memcpy in the caller >> itself, but how to tackle the spi controller configuration at that >> point of time. > You'd need to lock the bus and return the address for the caller to use > until it released the lock. Like I say I'd want to see numbers on this > helping though. > I explored the whole scenario at hand and tried to create something based on previous feedbacks that memcpy should be done only at the flash layer and the entire spi framework should be bypassed. But there is one problem which I faced while trying to achieve the above. Currently, spi framework takes care of the runtime clock control part in pump_message(spi.c). So, at the beginning of each transfer, there is a "get_sync" while at the end there is a "put_sync". Now, if I try to do a memcpy in flash and bypass the SPI framework, there is a data abort as the SPI controller clocks are cut. >> Memory mapped is a spi controller feature rather than a flash. > The way it appears to be implemented is pretty flash specific isn't it? ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-15 6:06 ` Sourav Poddar 0 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-15 6:06 UTC (permalink / raw) To: Mark Brown Cc: Peter Korsgaard, Trent Piepho, balbi, linux-mtd, spi-devel-general, computersforpeace, dwmw2 Hi Mark, On Friday 11 October 2013 03:38 PM, Mark Brown wrote: > On Thu, Oct 10, 2013 at 04:38:19PM +0530, Sourav Poddar wrote: >> On Thursday 10 October 2013 03:44 PM, Mark Brown wrote: >>> Essentially what it looks like this hardware is trying to do is adapt a >>> serial flash so it looks more like a parallel flash. It's not clear >>> that this is a good idea if we are already able to understand serial >>> flash though. >> Do you have any idea of how to go about implementing it in a more >> cleaner way?(taking care of all what the spi controller hardware needs to >> do for the memory mapped mode.). I understand doing a memcpy in the caller >> itself, but how to tackle the spi controller configuration at that >> point of time. > You'd need to lock the bus and return the address for the caller to use > until it released the lock. Like I say I'd want to see numbers on this > helping though. > I explored the whole scenario at hand and tried to create something based on previous feedbacks that memcpy should be done only at the flash layer and the entire spi framework should be bypassed. But there is one problem which I faced while trying to achieve the above. Currently, spi framework takes care of the runtime clock control part in pump_message(spi.c). So, at the beginning of each transfer, there is a "get_sync" while at the end there is a "put_sync". Now, if I try to do a memcpy in flash and bypass the SPI framework, there is a data abort as the SPI controller clocks are cut. >> Memory mapped is a spi controller feature rather than a flash. > The way it appears to be implemented is pretty flash specific isn't it? ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-15 6:06 ` Sourav Poddar @ 2013-10-15 11:16 ` Mark Brown -1 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-15 11:16 UTC (permalink / raw) To: Sourav Poddar Cc: Peter Korsgaard, Trent Piepho, balbi, linux-mtd, spi-devel-general, computersforpeace, dwmw2 [-- Attachment #1.1: Type: text/plain, Size: 632 bytes --] On Tue, Oct 15, 2013 at 11:36:47AM +0530, Sourav Poddar wrote: > But there is one problem which I faced while trying to achieve the > above. Currently, spi > framework takes care of the runtime clock control part in > pump_message(spi.c). So, at the > beginning of each transfer, there is a "get_sync" while at the end > there is a "put_sync". Now, if > I try to do a memcpy in flash and bypass the SPI framework, there is > a data abort as the SPI > controller clocks are cut. Can you fix this by enabling the clock is enabled when you return the buffer to the MTD layer and then disabling the clock when the buffer is released? [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] [-- Attachment #2: Type: text/plain, Size: 144 bytes --] ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-15 11:16 ` Mark Brown 0 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-15 11:16 UTC (permalink / raw) To: Sourav Poddar Cc: Peter Korsgaard, Trent Piepho, balbi, linux-mtd, spi-devel-general, computersforpeace, dwmw2 [-- Attachment #1: Type: text/plain, Size: 632 bytes --] On Tue, Oct 15, 2013 at 11:36:47AM +0530, Sourav Poddar wrote: > But there is one problem which I faced while trying to achieve the > above. Currently, spi > framework takes care of the runtime clock control part in > pump_message(spi.c). So, at the > beginning of each transfer, there is a "get_sync" while at the end > there is a "put_sync". Now, if > I try to do a memcpy in flash and bypass the SPI framework, there is > a data abort as the SPI > controller clocks are cut. Can you fix this by enabling the clock is enabled when you return the buffer to the MTD layer and then disabling the clock when the buffer is released? [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-15 11:16 ` Mark Brown @ 2013-10-15 11:49 ` Sourav Poddar -1 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-15 11:49 UTC (permalink / raw) To: Mark Brown Cc: Peter Korsgaard, Trent Piepho, balbi, linux-mtd, spi-devel-general, computersforpeace, dwmw2 Hi Mark, On Tuesday 15 October 2013 04:46 PM, Mark Brown wrote: > On Tue, Oct 15, 2013 at 11:36:47AM +0530, Sourav Poddar wrote: > >> But there is one problem which I faced while trying to achieve the >> above. Currently, spi >> framework takes care of the runtime clock control part in >> pump_message(spi.c). So, at the >> beginning of each transfer, there is a "get_sync" while at the end >> there is a "put_sync". Now, if >> I try to do a memcpy in flash and bypass the SPI framework, there is >> a data abort as the SPI >> controller clocks are cut. > Can you fix this by enabling the clock is enabled when you return the > buffer to the MTD layer and then disabling the clock when the buffer is > released? Sorry, I did not get you here. With memory mapped read, there is no buffer exchanged, everything takes place at the mtd layer only, what gets exchanged is just the memory mapped address. Here is the patch which I did on top of the subject patch series, wherein my controller is in default memory mapped mode, while doing a read in mtd layer its just does a memcopy and return. This gives me a data abort as pm_runtime_get_sync is not called on the qspi controller. Index: linux/drivers/mtd/devices/m25p80.c =================================================================== --- linux.orig/drivers/mtd/devices/m25p80.c 2013-10-15 17:08:15.000000000 +0530 +++ linux/drivers/mtd/devices/m25p80.c 2013-10-15 17:08:26.000000000 +0530 @@ -102,7 +102,7 @@ u8 *command; bool fast_read; bool quad_read; - bool mmap_read; + void *mmap_read; }; static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) @@ -438,18 +438,21 @@ pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev), __func__, (u32)from, len); printk("enter mtd quad..\n"); + + if (flash->mmap_read) { + printk("memory map=%x\n", flash->mmap_read); + memcpy(buf, flash->mmap_read + from, len); + *retlen = len; + return 0; + } + spi_message_init(&m); memset(t, 0, (sizeof(t))); - if (flash->mmap_read) - t[0].memory_map = 1; t[0].tx_buf = flash->command; - t[0].len = flash->mmap_read ? from : (m25p_cmdsz(flash) + (flash->quad_read ? 1 : 0)); - printk("t[0].len=%d\n", t[0].len); + t[0].len = (m25p_cmdsz(flash) + (flash->quad_read ? 1 : 0)); spi_message_add_tail(&t[0], &m); - if (flash->mmap_read) - t[1].memory_map = 1; t[1].rx_buf = buf; t[1].len = len; t[1].rx_nbits = SPI_NBITS_QUAD; @@ -476,7 +479,7 @@ spi_sync(flash->spi, &m); - *retlen = flash->mmap_read ? len : (m.actual_length - m25p_cmdsz(flash) - + *retlen = (m.actual_length - m25p_cmdsz(flash) - (flash->quad_read ? 1 : 0)); mutex_unlock(&flash->lock); @@ -1215,7 +1218,7 @@ if (spi->mode && SPI_RX_MMAP) { printk("memory mapped mode set\n"); - flash->mmap_read = true; + flash->mmap_read = spi->memory_map; } flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : (flash->quad_read ? 1 : 0)), GFP_KERNEL); Index: linux/drivers/spi/spi-ti-qspi.c =================================================================== --- linux.orig/drivers/spi/spi-ti-qspi.c 2013-10-15 17:08:15.000000000 +0530 +++ linux/drivers/spi/spi-ti-qspi.c 2013-10-15 17:15:52.000000000 +0530 @@ -256,6 +256,8 @@ break; } ti_qspi_write(qspi, memval, QSPI_SPI_SETUP0_REG); + enable_qspi_memory_mapped(qspi); + spi->memory_map = qspi->mmap_base; spi->mode |= SPI_RX_MMAP; } @@ -433,22 +435,13 @@ qspi->cmd |= QSPI_FLEN(frame_length); qspi->cmd |= QSPI_WC_CMD_INT_EN; + disable_qspi_memory_mapped(qspi); + ti_qspi_write(qspi, QSPI_WC_INT_EN, QSPI_INTR_ENABLE_SET_REG); mutex_lock(&qspi->list_lock); list_for_each_entry(t, &m->transfers, transfer_list) { - if (t->memory_map) { - if (t->tx_buf) { - from = t->len; - continue; - } - enable_qspi_memory_mapped(qspi); - memcpy(t->rx_buf, qspi->mmap_base + from, t->len); - disable_qspi_memory_mapped(qspi); - goto out; - } - qspi->cmd |= QSPI_WLEN(t->bits_per_word); ret = qspi_transfer_msg(qspi, t); @@ -461,13 +454,13 @@ m->actual_length += t->len; } -out: mutex_unlock(&qspi->list_lock); m->status = status; spi_finalize_current_message(master); ti_qspi_write(qspi, qspi->cmd | QSPI_INVAL, QSPI_SPI_CMD_REG); + enable_qspi_memory_mapped(qspi); return status; } @@ -599,6 +592,7 @@ if (res_mmap) { printk("mmap_available\n"); qspi->mmap_base = devm_ioremap_resource(&pdev->dev, res_mmap); + printk("qspi->mmap_base=%x\n", qspi->mmap_base); if (IS_ERR(qspi->mmap_base)) { ret = PTR_ERR(qspi->mmap_base); goto free_master; Index: linux/include/linux/spi/spi.h =================================================================== --- linux.orig/include/linux/spi/spi.h 2013-10-15 17:08:15.000000000 +0530 +++ linux/include/linux/spi/spi.h 2013-10-15 17:08:26.000000000 +0530 @@ -94,6 +94,7 @@ #define SPI_RX_MMAP 0x1000 /* Memory mapped read */ u8 bits_per_word; int irq; + void __iomem *memory_map; void *controller_state; void *controller_data; char modalias[SPI_NAME_SIZE]; @@ -556,7 +557,6 @@ u16 delay_usecs; u32 speed_hz; - bool memory_map; struct list_head transfer_list; }; ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-15 11:49 ` Sourav Poddar 0 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-15 11:49 UTC (permalink / raw) To: Mark Brown Cc: Peter Korsgaard, Trent Piepho, balbi, linux-mtd, spi-devel-general, computersforpeace, dwmw2 Hi Mark, On Tuesday 15 October 2013 04:46 PM, Mark Brown wrote: > On Tue, Oct 15, 2013 at 11:36:47AM +0530, Sourav Poddar wrote: > >> But there is one problem which I faced while trying to achieve the >> above. Currently, spi >> framework takes care of the runtime clock control part in >> pump_message(spi.c). So, at the >> beginning of each transfer, there is a "get_sync" while at the end >> there is a "put_sync". Now, if >> I try to do a memcpy in flash and bypass the SPI framework, there is >> a data abort as the SPI >> controller clocks are cut. > Can you fix this by enabling the clock is enabled when you return the > buffer to the MTD layer and then disabling the clock when the buffer is > released? Sorry, I did not get you here. With memory mapped read, there is no buffer exchanged, everything takes place at the mtd layer only, what gets exchanged is just the memory mapped address. Here is the patch which I did on top of the subject patch series, wherein my controller is in default memory mapped mode, while doing a read in mtd layer its just does a memcopy and return. This gives me a data abort as pm_runtime_get_sync is not called on the qspi controller. Index: linux/drivers/mtd/devices/m25p80.c =================================================================== --- linux.orig/drivers/mtd/devices/m25p80.c 2013-10-15 17:08:15.000000000 +0530 +++ linux/drivers/mtd/devices/m25p80.c 2013-10-15 17:08:26.000000000 +0530 @@ -102,7 +102,7 @@ u8 *command; bool fast_read; bool quad_read; - bool mmap_read; + void *mmap_read; }; static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) @@ -438,18 +438,21 @@ pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev), __func__, (u32)from, len); printk("enter mtd quad..\n"); + + if (flash->mmap_read) { + printk("memory map=%x\n", flash->mmap_read); + memcpy(buf, flash->mmap_read + from, len); + *retlen = len; + return 0; + } + spi_message_init(&m); memset(t, 0, (sizeof(t))); - if (flash->mmap_read) - t[0].memory_map = 1; t[0].tx_buf = flash->command; - t[0].len = flash->mmap_read ? from : (m25p_cmdsz(flash) + (flash->quad_read ? 1 : 0)); - printk("t[0].len=%d\n", t[0].len); + t[0].len = (m25p_cmdsz(flash) + (flash->quad_read ? 1 : 0)); spi_message_add_tail(&t[0], &m); - if (flash->mmap_read) - t[1].memory_map = 1; t[1].rx_buf = buf; t[1].len = len; t[1].rx_nbits = SPI_NBITS_QUAD; @@ -476,7 +479,7 @@ spi_sync(flash->spi, &m); - *retlen = flash->mmap_read ? len : (m.actual_length - m25p_cmdsz(flash) - + *retlen = (m.actual_length - m25p_cmdsz(flash) - (flash->quad_read ? 1 : 0)); mutex_unlock(&flash->lock); @@ -1215,7 +1218,7 @@ if (spi->mode && SPI_RX_MMAP) { printk("memory mapped mode set\n"); - flash->mmap_read = true; + flash->mmap_read = spi->memory_map; } flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : (flash->quad_read ? 1 : 0)), GFP_KERNEL); Index: linux/drivers/spi/spi-ti-qspi.c =================================================================== --- linux.orig/drivers/spi/spi-ti-qspi.c 2013-10-15 17:08:15.000000000 +0530 +++ linux/drivers/spi/spi-ti-qspi.c 2013-10-15 17:15:52.000000000 +0530 @@ -256,6 +256,8 @@ break; } ti_qspi_write(qspi, memval, QSPI_SPI_SETUP0_REG); + enable_qspi_memory_mapped(qspi); + spi->memory_map = qspi->mmap_base; spi->mode |= SPI_RX_MMAP; } @@ -433,22 +435,13 @@ qspi->cmd |= QSPI_FLEN(frame_length); qspi->cmd |= QSPI_WC_CMD_INT_EN; + disable_qspi_memory_mapped(qspi); + ti_qspi_write(qspi, QSPI_WC_INT_EN, QSPI_INTR_ENABLE_SET_REG); mutex_lock(&qspi->list_lock); list_for_each_entry(t, &m->transfers, transfer_list) { - if (t->memory_map) { - if (t->tx_buf) { - from = t->len; - continue; - } - enable_qspi_memory_mapped(qspi); - memcpy(t->rx_buf, qspi->mmap_base + from, t->len); - disable_qspi_memory_mapped(qspi); - goto out; - } - qspi->cmd |= QSPI_WLEN(t->bits_per_word); ret = qspi_transfer_msg(qspi, t); @@ -461,13 +454,13 @@ m->actual_length += t->len; } -out: mutex_unlock(&qspi->list_lock); m->status = status; spi_finalize_current_message(master); ti_qspi_write(qspi, qspi->cmd | QSPI_INVAL, QSPI_SPI_CMD_REG); + enable_qspi_memory_mapped(qspi); return status; } @@ -599,6 +592,7 @@ if (res_mmap) { printk("mmap_available\n"); qspi->mmap_base = devm_ioremap_resource(&pdev->dev, res_mmap); + printk("qspi->mmap_base=%x\n", qspi->mmap_base); if (IS_ERR(qspi->mmap_base)) { ret = PTR_ERR(qspi->mmap_base); goto free_master; Index: linux/include/linux/spi/spi.h =================================================================== --- linux.orig/include/linux/spi/spi.h 2013-10-15 17:08:15.000000000 +0530 +++ linux/include/linux/spi/spi.h 2013-10-15 17:08:26.000000000 +0530 @@ -94,6 +94,7 @@ #define SPI_RX_MMAP 0x1000 /* Memory mapped read */ u8 bits_per_word; int irq; + void __iomem *memory_map; void *controller_state; void *controller_data; char modalias[SPI_NAME_SIZE]; @@ -556,7 +557,6 @@ u16 delay_usecs; u32 speed_hz; - bool memory_map; struct list_head transfer_list; }; ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-15 11:49 ` Sourav Poddar @ 2013-10-15 12:46 ` Mark Brown -1 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-15 12:46 UTC (permalink / raw) To: Sourav Poddar Cc: Peter Korsgaard, Trent Piepho, balbi, linux-mtd, spi-devel-general, computersforpeace, dwmw2 [-- Attachment #1.1: Type: text/plain, Size: 860 bytes --] On Tue, Oct 15, 2013 at 05:19:07PM +0530, Sourav Poddar wrote: > On Tuesday 15 October 2013 04:46 PM, Mark Brown wrote: > >Can you fix this by enabling the clock is enabled when you return the > >buffer to the MTD layer and then disabling the clock when the buffer is > >released? > Sorry, I did not get you here. With memory mapped read, there is no > buffer exchanged, everything takes place at the mtd layer only, what gets > exchanged is just the memory mapped address. The buffer is the memory mapped address - part of getting the address should be preparing the hardware for it. > if (spi->mode && SPI_RX_MMAP) { > printk("memory mapped mode set\n"); > - flash->mmap_read = true; > + flash->mmap_read = spi->memory_map; So this probably needs to be a function call to get the buffer (and a corresponding one to free it). [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] [-- Attachment #2: Type: text/plain, Size: 144 bytes --] ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-15 12:46 ` Mark Brown 0 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-15 12:46 UTC (permalink / raw) To: Sourav Poddar Cc: Peter Korsgaard, Trent Piepho, balbi, linux-mtd, spi-devel-general, computersforpeace, dwmw2 [-- Attachment #1: Type: text/plain, Size: 860 bytes --] On Tue, Oct 15, 2013 at 05:19:07PM +0530, Sourav Poddar wrote: > On Tuesday 15 October 2013 04:46 PM, Mark Brown wrote: > >Can you fix this by enabling the clock is enabled when you return the > >buffer to the MTD layer and then disabling the clock when the buffer is > >released? > Sorry, I did not get you here. With memory mapped read, there is no > buffer exchanged, everything takes place at the mtd layer only, what gets > exchanged is just the memory mapped address. The buffer is the memory mapped address - part of getting the address should be preparing the hardware for it. > if (spi->mode && SPI_RX_MMAP) { > printk("memory mapped mode set\n"); > - flash->mmap_read = true; > + flash->mmap_read = spi->memory_map; So this probably needs to be a function call to get the buffer (and a corresponding one to free it). [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 104+ messages in thread
[parent not found: <20131015124656.GM2443-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>]
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-15 12:46 ` Mark Brown @ 2013-10-15 13:23 ` Sourav Poddar -1 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-15 13:23 UTC (permalink / raw) To: Mark Brown Cc: Peter Korsgaard, Trent Piepho, balbi-l0cyMroinI0, linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, computersforpeace-Re5JQEeQqe8AvxtiuMwx3w, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ On Tuesday 15 October 2013 06:16 PM, Mark Brown wrote: > On Tue, Oct 15, 2013 at 05:19:07PM +0530, Sourav Poddar wrote: >> On Tuesday 15 October 2013 04:46 PM, Mark Brown wrote: >>> Can you fix this by enabling the clock is enabled when you return the >>> buffer to the MTD layer and then disabling the clock when the buffer is >>> released? >> Sorry, I did not get you here. With memory mapped read, there is no >> buffer exchanged, everything takes place at the mtd layer only, what gets >> exchanged is just the memory mapped address. > The buffer is the memory mapped address - part of getting the address > should be preparing the hardware for it. > >> if (spi->mode&& SPI_RX_MMAP) { >> printk("memory mapped mode set\n"); >> - flash->mmap_read = true; >> + flash->mmap_read = spi->memory_map; > So this probably needs to be a function call to get the buffer (and a > corresponding one to free it). So, the flow can be something like this: drivers/mtd/devices/m25p80.c get_flash_buf() { lock(); t[0] = GET_BUFFER; t[1] = buf; ...... spi_sync(); unlock(); } mtd_read { get_flash_buf(); if (flash->buf) { memcpy(); return 0; } } Not sure, if free buf is needed as devm_* variant is used to allocate that memory. } ------------------------------------------------------------------------------ October Webinars: Code for Performance Free Intel webinars can help you accelerate application performance. Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from the latest Intel processors and coprocessors. See abstracts and register > http://pubads.g.doubleclick.net/gampad/clk?id=60135031&iu=/4140/ostg.clktrk ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-15 13:23 ` Sourav Poddar 0 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-15 13:23 UTC (permalink / raw) To: Mark Brown Cc: Peter Korsgaard, Trent Piepho, balbi, linux-mtd, spi-devel-general, computersforpeace, dwmw2 On Tuesday 15 October 2013 06:16 PM, Mark Brown wrote: > On Tue, Oct 15, 2013 at 05:19:07PM +0530, Sourav Poddar wrote: >> On Tuesday 15 October 2013 04:46 PM, Mark Brown wrote: >>> Can you fix this by enabling the clock is enabled when you return the >>> buffer to the MTD layer and then disabling the clock when the buffer is >>> released? >> Sorry, I did not get you here. With memory mapped read, there is no >> buffer exchanged, everything takes place at the mtd layer only, what gets >> exchanged is just the memory mapped address. > The buffer is the memory mapped address - part of getting the address > should be preparing the hardware for it. > >> if (spi->mode&& SPI_RX_MMAP) { >> printk("memory mapped mode set\n"); >> - flash->mmap_read = true; >> + flash->mmap_read = spi->memory_map; > So this probably needs to be a function call to get the buffer (and a > corresponding one to free it). So, the flow can be something like this: drivers/mtd/devices/m25p80.c get_flash_buf() { lock(); t[0] = GET_BUFFER; t[1] = buf; ...... spi_sync(); unlock(); } mtd_read { get_flash_buf(); if (flash->buf) { memcpy(); return 0; } } Not sure, if free buf is needed as devm_* variant is used to allocate that memory. } ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-15 13:23 ` Sourav Poddar @ 2013-10-15 15:53 ` Mark Brown -1 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-15 15:53 UTC (permalink / raw) To: Sourav Poddar Cc: Peter Korsgaard, Trent Piepho, balbi, linux-mtd, spi-devel-general, computersforpeace, dwmw2 [-- Attachment #1.1: Type: text/plain, Size: 393 bytes --] On Tue, Oct 15, 2013 at 06:53:46PM +0530, Sourav Poddar wrote: > Not sure, if free buf is needed as devm_* variant is used to allocate that > memory. I would expect the buffer to only be requested by the flash driver when actively in use. This will enable the SPI controller driver to save power (by stopping the clock for example as in your case) when the flash isn't actively being used. [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] [-- Attachment #2: Type: text/plain, Size: 144 bytes --] ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-15 15:53 ` Mark Brown 0 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-15 15:53 UTC (permalink / raw) To: Sourav Poddar Cc: Peter Korsgaard, Trent Piepho, balbi, linux-mtd, spi-devel-general, computersforpeace, dwmw2 [-- Attachment #1: Type: text/plain, Size: 393 bytes --] On Tue, Oct 15, 2013 at 06:53:46PM +0530, Sourav Poddar wrote: > Not sure, if free buf is needed as devm_* variant is used to allocate that > memory. I would expect the buffer to only be requested by the flash driver when actively in use. This will enable the SPI controller driver to save power (by stopping the clock for example as in your case) when the flash isn't actively being used. [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 104+ messages in thread
[parent not found: <525D41E2.30206-l0cyMroinI0@public.gmane.org>]
* RE: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-15 13:23 ` Sourav Poddar @ 2013-10-15 15:33 ` Gupta, Pekon -1 siblings, 0 replies; 104+ messages in thread From: Gupta, Pekon @ 2013-10-15 15:33 UTC (permalink / raw) To: Poddar, Sourav, Mark Brown Cc: Peter Korsgaard, Trent Piepho, Balbi, Felipe, linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, computersforpeace-Re5JQEeQqe8AvxtiuMwx3w, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ > From: Poddar, Sourav > > On Tuesday 15 October 2013 06:16 PM, Mark Brown wrote: > > On Tue, Oct 15, 2013 at 05:19:07PM +0530, Sourav Poddar wrote: > >> On Tuesday 15 October 2013 04:46 PM, Mark Brown wrote: > >>> Can you fix this by enabling the clock is enabled when you return the > >>> buffer to the MTD layer and then disabling the clock when the buffer is > >>> released? > >> Sorry, I did not get you here. With memory mapped read, there is no > >> buffer exchanged, everything takes place at the mtd layer only, what gets > >> exchanged is just the memory mapped address. > > The buffer is the memory mapped address - part of getting the address > > should be preparing the hardware for it. > > > >> if (spi->mode&& SPI_RX_MMAP) { > >> printk("memory mapped mode set\n"); > >> - flash->mmap_read = true; > >> + flash->mmap_read = spi->memory_map; > > So this probably needs to be a function call to get the buffer (and a > > corresponding one to free it). > So, the flow can be something like this: > > drivers/mtd/devices/m25p80.c > get_flash_buf() > { > lock(); > > t[0] = GET_BUFFER; > t[1] = buf; > ...... > > spi_sync(); > > unlock(); > } > Problem here.. spi_sync() is not blocking, that means it would just add a spi_message to queue and return. And it depends on kthread_worker when it pumps this spi_message to QPSI controller driver for actual configuration. So this is actually a race-condition. You cannot use spi_sync() to configure. (refer my comments in previous emails). If you really want to configure QSPI controller just before memcpy(), Then you need to somehow prevent spi kthead_worker from accessing. This you can do by locking the spi_meesage queue/list at that time. > mtd_read > { > get_flash_buf(); > > if (flash->buf) { > memcpy(); > return 0; > } > } > > Not sure, if free buf is needed as devm_* variant is used to allocate that > memory. > > > } With regards, pekon ------------------------------------------------------------------------------ October Webinars: Code for Performance Free Intel webinars can help you accelerate application performance. Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from the latest Intel processors and coprocessors. See abstracts and register > http://pubads.g.doubleclick.net/gampad/clk?id=60135031&iu=/4140/ostg.clktrk ^ permalink raw reply [flat|nested] 104+ messages in thread
* RE: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-15 15:33 ` Gupta, Pekon 0 siblings, 0 replies; 104+ messages in thread From: Gupta, Pekon @ 2013-10-15 15:33 UTC (permalink / raw) To: Poddar, Sourav, Mark Brown Cc: Peter Korsgaard, Trent Piepho, Balbi, Felipe, linux-mtd, spi-devel-general, computersforpeace, dwmw2 > From: Poddar, Sourav > > On Tuesday 15 October 2013 06:16 PM, Mark Brown wrote: > > On Tue, Oct 15, 2013 at 05:19:07PM +0530, Sourav Poddar wrote: > >> On Tuesday 15 October 2013 04:46 PM, Mark Brown wrote: > >>> Can you fix this by enabling the clock is enabled when you return the > >>> buffer to the MTD layer and then disabling the clock when the buffer is > >>> released? > >> Sorry, I did not get you here. With memory mapped read, there is no > >> buffer exchanged, everything takes place at the mtd layer only, what gets > >> exchanged is just the memory mapped address. > > The buffer is the memory mapped address - part of getting the address > > should be preparing the hardware for it. > > > >> if (spi->mode&& SPI_RX_MMAP) { > >> printk("memory mapped mode set\n"); > >> - flash->mmap_read = true; > >> + flash->mmap_read = spi->memory_map; > > So this probably needs to be a function call to get the buffer (and a > > corresponding one to free it). > So, the flow can be something like this: > > drivers/mtd/devices/m25p80.c > get_flash_buf() > { > lock(); > > t[0] = GET_BUFFER; > t[1] = buf; > ...... > > spi_sync(); > > unlock(); > } > Problem here.. spi_sync() is not blocking, that means it would just add a spi_message to queue and return. And it depends on kthread_worker when it pumps this spi_message to QPSI controller driver for actual configuration. So this is actually a race-condition. You cannot use spi_sync() to configure. (refer my comments in previous emails). If you really want to configure QSPI controller just before memcpy(), Then you need to somehow prevent spi kthead_worker from accessing. This you can do by locking the spi_meesage queue/list at that time. > mtd_read > { > get_flash_buf(); > > if (flash->buf) { > memcpy(); > return 0; > } > } > > Not sure, if free buf is needed as devm_* variant is used to allocate that > memory. > > > } With regards, pekon ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-15 15:33 ` Gupta, Pekon @ 2013-10-15 16:01 ` Mark Brown -1 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-15 16:01 UTC (permalink / raw) To: Gupta, Pekon Cc: Peter Korsgaard, computersforpeace, Balbi, Felipe, linux-mtd, spi-devel-general, Poddar, Sourav, Trent Piepho, dwmw2 [-- Attachment #1.1: Type: text/plain, Size: 433 bytes --] On Tue, Oct 15, 2013 at 03:33:19PM +0000, Gupta, Pekon wrote: > Problem here.. > spi_sync() is not blocking, that means it would just add a spi_message > to queue and return. And it depends on kthread_worker when it pumps > this spi_message to QPSI controller driver for actual configuration. > So this is actually a race-condition. You cannot use spi_sync() to configure. No, spi_sync() is blocking - spi_async() is non-blocking. [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] [-- Attachment #2: Type: text/plain, Size: 144 bytes --] ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-15 16:01 ` Mark Brown 0 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-15 16:01 UTC (permalink / raw) To: Gupta, Pekon Cc: Peter Korsgaard, computersforpeace, Balbi, Felipe, linux-mtd, spi-devel-general, Poddar, Sourav, Trent Piepho, dwmw2 [-- Attachment #1: Type: text/plain, Size: 433 bytes --] On Tue, Oct 15, 2013 at 03:33:19PM +0000, Gupta, Pekon wrote: > Problem here.. > spi_sync() is not blocking, that means it would just add a spi_message > to queue and return. And it depends on kthread_worker when it pumps > this spi_message to QPSI controller driver for actual configuration. > So this is actually a race-condition. You cannot use spi_sync() to configure. No, spi_sync() is blocking - spi_async() is non-blocking. [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 104+ messages in thread
* RE: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-15 16:01 ` Mark Brown @ 2013-10-15 16:54 ` Gupta, Pekon -1 siblings, 0 replies; 104+ messages in thread From: Gupta, Pekon @ 2013-10-15 16:54 UTC (permalink / raw) To: Mark Brown Cc: Peter Korsgaard, computersforpeace, Balbi, Felipe, linux-mtd, spi-devel-general, Poddar, Sourav, Trent Piepho, dwmw2 > From: Mark Brown [mailto:broonie@kernel.org] > > On Tue, Oct 15, 2013 at 03:33:19PM +0000, Gupta, Pekon wrote: > > Problem here.. > > spi_sync() is not blocking, that means it would just add a spi_message > > to queue and return. And it depends on kthread_worker when it pumps > > this spi_message to QPSI controller driver for actual configuration. > > So this is actually a race-condition. You cannot use spi_sync() to configure. > > No, spi_sync() is blocking - spi_async() is non-blocking. Sorry my bad, I must have been dreaming or something. Yes, it's spi_sync() is blocking, its clearly written in its comments too.. with regards, pekon ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* RE: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-15 16:54 ` Gupta, Pekon 0 siblings, 0 replies; 104+ messages in thread From: Gupta, Pekon @ 2013-10-15 16:54 UTC (permalink / raw) To: Mark Brown Cc: Peter Korsgaard, computersforpeace, Balbi, Felipe, linux-mtd, spi-devel-general, Poddar, Sourav, Trent Piepho, dwmw2 > From: Mark Brown [mailto:broonie@kernel.org] > > On Tue, Oct 15, 2013 at 03:33:19PM +0000, Gupta, Pekon wrote: > > Problem here.. > > spi_sync() is not blocking, that means it would just add a spi_message > > to queue and return. And it depends on kthread_worker when it pumps > > this spi_message to QPSI controller driver for actual configuration. > > So this is actually a race-condition. You cannot use spi_sync() to configure. > > No, spi_sync() is blocking - spi_async() is non-blocking. Sorry my bad, I must have been dreaming or something. Yes, it's spi_sync() is blocking, its clearly written in its comments too.. with regards, pekon ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-15 13:23 ` Sourav Poddar @ 2013-10-15 18:01 ` Brian Norris -1 siblings, 0 replies; 104+ messages in thread From: Brian Norris @ 2013-10-15 18:01 UTC (permalink / raw) To: Sourav Poddar Cc: Peter Korsgaard, balbi-l0cyMroinI0, Mark Brown, linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Trent Piepho, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ Hi Sourav, On Tue, Oct 15, 2013 at 06:53:46PM +0530, Sourav Poddar wrote: > On Tuesday 15 October 2013 06:16 PM, Mark Brown wrote: > >On Tue, Oct 15, 2013 at 05:19:07PM +0530, Sourav Poddar wrote: > >>On Tuesday 15 October 2013 04:46 PM, Mark Brown wrote: > >>>Can you fix this by enabling the clock is enabled when you return the > >>>buffer to the MTD layer and then disabling the clock when the buffer is > >>>released? > >>Sorry, I did not get you here. With memory mapped read, there is no > >>buffer exchanged, everything takes place at the mtd layer only, what gets > >>exchanged is just the memory mapped address. > >The buffer is the memory mapped address - part of getting the address > >should be preparing the hardware for it. > > > >> if (spi->mode&& SPI_RX_MMAP) { > >> printk("memory mapped mode set\n"); > >>- flash->mmap_read = true; > >>+ flash->mmap_read = spi->memory_map; > >So this probably needs to be a function call to get the buffer (and a > >corresponding one to free it). > So, the flow can be something like this: > > drivers/mtd/devices/m25p80.c > get_flash_buf() > { > lock(); > > t[0] = GET_BUFFER; > t[1] = buf; > ...... > > spi_sync(); > > unlock(); > } > > mtd_read > { > get_flash_buf(); > > if (flash->buf) { > memcpy(); > return 0; > } > } > > Not sure, if free buf is needed as devm_* variant is used to allocate that > memory. I believe you are misplacing the discussion of devm_* variants. devm_* is only useful for resources allocated/mapped released/unmapped at probe and release time. They do not magically remove the burden of resource management for I/O and other dynamic operations. In this case, you are not working at probe time, and you are not actually allocating any memory--your 'get_flash_buf()' and corresponding 'release_flash_buf()' would not be allocating memory but would be ensuring that the HW and driver is in the correct state. Brian ------------------------------------------------------------------------------ October Webinars: Code for Performance Free Intel webinars can help you accelerate application performance. Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from the latest Intel processors and coprocessors. See abstracts and register > http://pubads.g.doubleclick.net/gampad/clk?id=60135031&iu=/4140/ostg.clktrk ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-15 18:01 ` Brian Norris 0 siblings, 0 replies; 104+ messages in thread From: Brian Norris @ 2013-10-15 18:01 UTC (permalink / raw) To: Sourav Poddar Cc: Peter Korsgaard, balbi, Mark Brown, linux-mtd, spi-devel-general, Trent Piepho, dwmw2 Hi Sourav, On Tue, Oct 15, 2013 at 06:53:46PM +0530, Sourav Poddar wrote: > On Tuesday 15 October 2013 06:16 PM, Mark Brown wrote: > >On Tue, Oct 15, 2013 at 05:19:07PM +0530, Sourav Poddar wrote: > >>On Tuesday 15 October 2013 04:46 PM, Mark Brown wrote: > >>>Can you fix this by enabling the clock is enabled when you return the > >>>buffer to the MTD layer and then disabling the clock when the buffer is > >>>released? > >>Sorry, I did not get you here. With memory mapped read, there is no > >>buffer exchanged, everything takes place at the mtd layer only, what gets > >>exchanged is just the memory mapped address. > >The buffer is the memory mapped address - part of getting the address > >should be preparing the hardware for it. > > > >> if (spi->mode&& SPI_RX_MMAP) { > >> printk("memory mapped mode set\n"); > >>- flash->mmap_read = true; > >>+ flash->mmap_read = spi->memory_map; > >So this probably needs to be a function call to get the buffer (and a > >corresponding one to free it). > So, the flow can be something like this: > > drivers/mtd/devices/m25p80.c > get_flash_buf() > { > lock(); > > t[0] = GET_BUFFER; > t[1] = buf; > ...... > > spi_sync(); > > unlock(); > } > > mtd_read > { > get_flash_buf(); > > if (flash->buf) { > memcpy(); > return 0; > } > } > > Not sure, if free buf is needed as devm_* variant is used to allocate that > memory. I believe you are misplacing the discussion of devm_* variants. devm_* is only useful for resources allocated/mapped released/unmapped at probe and release time. They do not magically remove the burden of resource management for I/O and other dynamic operations. In this case, you are not working at probe time, and you are not actually allocating any memory--your 'get_flash_buf()' and corresponding 'release_flash_buf()' would not be allocating memory but would be ensuring that the HW and driver is in the correct state. Brian ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-15 18:01 ` Brian Norris @ 2013-10-15 18:10 ` Sourav Poddar -1 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-15 18:10 UTC (permalink / raw) To: Brian Norris Cc: Peter Korsgaard, balbi, Mark Brown, linux-mtd, spi-devel-general, Trent Piepho, dwmw2 Hi Brian, On Tuesday 15 October 2013 11:31 PM, Brian Norris wrote: > Hi Sourav, > > On Tue, Oct 15, 2013 at 06:53:46PM +0530, Sourav Poddar wrote: >> On Tuesday 15 October 2013 06:16 PM, Mark Brown wrote: >>> On Tue, Oct 15, 2013 at 05:19:07PM +0530, Sourav Poddar wrote: >>>> On Tuesday 15 October 2013 04:46 PM, Mark Brown wrote: >>>>> Can you fix this by enabling the clock is enabled when you return the >>>>> buffer to the MTD layer and then disabling the clock when the buffer is >>>>> released? >>>> Sorry, I did not get you here. With memory mapped read, there is no >>>> buffer exchanged, everything takes place at the mtd layer only, what gets >>>> exchanged is just the memory mapped address. >>> The buffer is the memory mapped address - part of getting the address >>> should be preparing the hardware for it. >>> >>>> if (spi->mode&& SPI_RX_MMAP) { >>>> printk("memory mapped mode set\n"); >>>> - flash->mmap_read = true; >>>> + flash->mmap_read = spi->memory_map; >>> So this probably needs to be a function call to get the buffer (and a >>> corresponding one to free it). >> So, the flow can be something like this: >> >> drivers/mtd/devices/m25p80.c >> get_flash_buf() >> { >> lock(); >> >> t[0] = GET_BUFFER; >> t[1] = buf; >> ...... >> >> spi_sync(); >> >> unlock(); >> } >> >> mtd_read >> { >> get_flash_buf(); >> >> if (flash->buf) { >> memcpy(); >> return 0; >> } >> } >> >> Not sure, if free buf is needed as devm_* variant is used to allocate that >> memory. > I believe you are misplacing the discussion of devm_* variants. devm_* > is only useful for resources allocated/mapped released/unmapped at probe > and release time. They do not magically remove the burden of resource > management for I/O and other dynamic operations. > > In this case, you are not working at probe time, and you are not > actually allocating any memory--your 'get_flash_buf()' and corresponding > 'release_flash_buf()' would not be allocating memory but would be > ensuring that the HW and driver is in the correct state. > > Brian Thanks for the reply. I got this. It will be helpful if you can also comment on the thought process till now, as you can see from the series that enabling quad and memory mapped support will effect both the SPI controller and m25p80 side. If the changes proposed on m25p80 looks good to you. ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-15 18:10 ` Sourav Poddar 0 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-15 18:10 UTC (permalink / raw) To: Brian Norris Cc: Peter Korsgaard, balbi, Mark Brown, linux-mtd, spi-devel-general, Trent Piepho, dwmw2 Hi Brian, On Tuesday 15 October 2013 11:31 PM, Brian Norris wrote: > Hi Sourav, > > On Tue, Oct 15, 2013 at 06:53:46PM +0530, Sourav Poddar wrote: >> On Tuesday 15 October 2013 06:16 PM, Mark Brown wrote: >>> On Tue, Oct 15, 2013 at 05:19:07PM +0530, Sourav Poddar wrote: >>>> On Tuesday 15 October 2013 04:46 PM, Mark Brown wrote: >>>>> Can you fix this by enabling the clock is enabled when you return the >>>>> buffer to the MTD layer and then disabling the clock when the buffer is >>>>> released? >>>> Sorry, I did not get you here. With memory mapped read, there is no >>>> buffer exchanged, everything takes place at the mtd layer only, what gets >>>> exchanged is just the memory mapped address. >>> The buffer is the memory mapped address - part of getting the address >>> should be preparing the hardware for it. >>> >>>> if (spi->mode&& SPI_RX_MMAP) { >>>> printk("memory mapped mode set\n"); >>>> - flash->mmap_read = true; >>>> + flash->mmap_read = spi->memory_map; >>> So this probably needs to be a function call to get the buffer (and a >>> corresponding one to free it). >> So, the flow can be something like this: >> >> drivers/mtd/devices/m25p80.c >> get_flash_buf() >> { >> lock(); >> >> t[0] = GET_BUFFER; >> t[1] = buf; >> ...... >> >> spi_sync(); >> >> unlock(); >> } >> >> mtd_read >> { >> get_flash_buf(); >> >> if (flash->buf) { >> memcpy(); >> return 0; >> } >> } >> >> Not sure, if free buf is needed as devm_* variant is used to allocate that >> memory. > I believe you are misplacing the discussion of devm_* variants. devm_* > is only useful for resources allocated/mapped released/unmapped at probe > and release time. They do not magically remove the burden of resource > management for I/O and other dynamic operations. > > In this case, you are not working at probe time, and you are not > actually allocating any memory--your 'get_flash_buf()' and corresponding > 'release_flash_buf()' would not be allocating memory but would be > ensuring that the HW and driver is in the correct state. > > Brian Thanks for the reply. I got this. It will be helpful if you can also comment on the thought process till now, as you can see from the series that enabling quad and memory mapped support will effect both the SPI controller and m25p80 side. If the changes proposed on m25p80 looks good to you. ^ permalink raw reply [flat|nested] 104+ messages in thread
[parent not found: <20131015180142.GS23337-bU/DPfM3abD4WzifrMjOTkcViWtcw2C0@public.gmane.org>]
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-15 18:01 ` Brian Norris @ 2013-10-15 18:13 ` Trent Piepho -1 siblings, 0 replies; 104+ messages in thread From: Trent Piepho @ 2013-10-15 18:13 UTC (permalink / raw) To: Brian Norris Cc: Peter Korsgaard, balbi-l0cyMroinI0, Mark Brown, linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Sourav Poddar, David Woodhouse On Tue, Oct 15, 2013 at 11:01 AM, Brian Norris <computersforpeace-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: >> So, the flow can be something like this: >> >> drivers/mtd/devices/m25p80.c >> get_flash_buf() >> { >> lock(); >> >> t[0] = GET_BUFFER; >> t[1] = buf; >> ...... >> >> spi_sync(); >> >> unlock(); >> } >> >> mtd_read >> { >> get_flash_buf(); >> >> if (flash->buf) { >> memcpy(); >> return 0; >> } >> } >> >> Not sure, if free buf is needed as devm_* variant is used to allocate that >> memory. > > I believe you are misplacing the discussion of devm_* variants. devm_* > is only useful for resources allocated/mapped released/unmapped at probe > and release time. They do not magically remove the burden of resource > management for I/O and other dynamic operations. Are there any numbers to show if memory mapped read support is a benefit in Linux? There is some question as to whether it's useful at all or not. If it is, I think low latency for small reads is probably one of the only advantages. To do that, you aren't going to want to deal with device PM for every single read. It would make more sense to turn the hardware on when the MTD device is opened and leave it on until closed. ------------------------------------------------------------------------------ October Webinars: Code for Performance Free Intel webinars can help you accelerate application performance. Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from the latest Intel processors and coprocessors. See abstracts and register > http://pubads.g.doubleclick.net/gampad/clk?id=60135031&iu=/4140/ostg.clktrk ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-15 18:13 ` Trent Piepho 0 siblings, 0 replies; 104+ messages in thread From: Trent Piepho @ 2013-10-15 18:13 UTC (permalink / raw) To: Brian Norris Cc: Peter Korsgaard, balbi, Mark Brown, linux-mtd, spi-devel-general, Sourav Poddar, David Woodhouse On Tue, Oct 15, 2013 at 11:01 AM, Brian Norris <computersforpeace@gmail.com> wrote: >> So, the flow can be something like this: >> >> drivers/mtd/devices/m25p80.c >> get_flash_buf() >> { >> lock(); >> >> t[0] = GET_BUFFER; >> t[1] = buf; >> ...... >> >> spi_sync(); >> >> unlock(); >> } >> >> mtd_read >> { >> get_flash_buf(); >> >> if (flash->buf) { >> memcpy(); >> return 0; >> } >> } >> >> Not sure, if free buf is needed as devm_* variant is used to allocate that >> memory. > > I believe you are misplacing the discussion of devm_* variants. devm_* > is only useful for resources allocated/mapped released/unmapped at probe > and release time. They do not magically remove the burden of resource > management for I/O and other dynamic operations. Are there any numbers to show if memory mapped read support is a benefit in Linux? There is some question as to whether it's useful at all or not. If it is, I think low latency for small reads is probably one of the only advantages. To do that, you aren't going to want to deal with device PM for every single read. It would make more sense to turn the hardware on when the MTD device is opened and leave it on until closed. ^ permalink raw reply [flat|nested] 104+ messages in thread
* RE: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-15 18:13 ` Trent Piepho @ 2013-10-15 18:33 ` Gupta, Pekon -1 siblings, 0 replies; 104+ messages in thread From: Gupta, Pekon @ 2013-10-15 18:33 UTC (permalink / raw) To: Trent Piepho Cc: Peter Korsgaard, Balbi, Felipe, Mark Brown, linux-mtd, spi-devel-general, Poddar, Sourav, Brian Norris, David Woodhouse > From: Trent Piepho > Are there any numbers to show if memory mapped read support is a > benefit in Linux? There is some question as to whether it's useful at > all or not. > > If it is, I think low latency for small reads is probably one of the > only advantages. To do that, you aren't going to want to deal with > device PM for every single read. It would make more sense to turn the > hardware on when the MTD device is opened and leave it on until > closed. > +1 Therefore early suggestions were to make 'MM_MODE' as default (if device enables it via DT). This means: (1) switch to 'SPI_MODE' _only_ when required for commands like mtd_erase, etc. and switch back to 'MM_MODE' when done. (2) And keep your controller clocks on. This would ensure that you do minimum config-switching when using MM_MODE. And would thus achieve low latency, and no driver intervention. Yes, real thruput numbers would help clear the picture here .. with regards, pekon ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* RE: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-15 18:33 ` Gupta, Pekon 0 siblings, 0 replies; 104+ messages in thread From: Gupta, Pekon @ 2013-10-15 18:33 UTC (permalink / raw) To: Trent Piepho Cc: Peter Korsgaard, Balbi, Felipe, Mark Brown, linux-mtd, spi-devel-general, Poddar, Sourav, Brian Norris, David Woodhouse > From: Trent Piepho > Are there any numbers to show if memory mapped read support is a > benefit in Linux? There is some question as to whether it's useful at > all or not. > > If it is, I think low latency for small reads is probably one of the > only advantages. To do that, you aren't going to want to deal with > device PM for every single read. It would make more sense to turn the > hardware on when the MTD device is opened and leave it on until > closed. > +1 Therefore early suggestions were to make 'MM_MODE' as default (if device enables it via DT). This means: (1) switch to 'SPI_MODE' _only_ when required for commands like mtd_erase, etc. and switch back to 'MM_MODE' when done. (2) And keep your controller clocks on. This would ensure that you do minimum config-switching when using MM_MODE. And would thus achieve low latency, and no driver intervention. Yes, real thruput numbers would help clear the picture here .. with regards, pekon ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-15 18:33 ` Gupta, Pekon @ 2013-10-15 20:52 ` Mark Brown -1 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-15 20:52 UTC (permalink / raw) To: Gupta, Pekon Cc: Peter Korsgaard, Brian Norris, Balbi, Felipe, linux-mtd, spi-devel-general, Poddar, Sourav, Trent Piepho, David Woodhouse [-- Attachment #1.1: Type: text/plain, Size: 611 bytes --] On Tue, Oct 15, 2013 at 06:33:23PM +0000, Gupta, Pekon wrote: > Therefore early suggestions were to make 'MM_MODE' as default > (if device enables it via DT). This means: > (1) switch to 'SPI_MODE' _only_ when required for commands like > mtd_erase, etc. and switch back to 'MM_MODE' when done. > (2) And keep your controller clocks on. This sounds like a policy decision, I don't see any reason for it to be in DT. What works well with one application stack may not be the best choice for another and future developments may change what's most sensible for a given system, it shouldn't be fixed in the DT. [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] [-- Attachment #2: Type: text/plain, Size: 144 bytes --] ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-15 20:52 ` Mark Brown 0 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-15 20:52 UTC (permalink / raw) To: Gupta, Pekon Cc: Peter Korsgaard, Brian Norris, Balbi, Felipe, linux-mtd, spi-devel-general, Poddar, Sourav, Trent Piepho, David Woodhouse [-- Attachment #1: Type: text/plain, Size: 611 bytes --] On Tue, Oct 15, 2013 at 06:33:23PM +0000, Gupta, Pekon wrote: > Therefore early suggestions were to make 'MM_MODE' as default > (if device enables it via DT). This means: > (1) switch to 'SPI_MODE' _only_ when required for commands like > mtd_erase, etc. and switch back to 'MM_MODE' when done. > (2) And keep your controller clocks on. This sounds like a policy decision, I don't see any reason for it to be in DT. What works well with one application stack may not be the best choice for another and future developments may change what's most sensible for a given system, it shouldn't be fixed in the DT. [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 104+ messages in thread
[parent not found: <20131015205254.GX2443-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>]
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-15 20:52 ` Mark Brown @ 2013-10-15 21:03 ` Trent Piepho -1 siblings, 0 replies; 104+ messages in thread From: Trent Piepho @ 2013-10-15 21:03 UTC (permalink / raw) To: Mark Brown Cc: Peter Korsgaard, Balbi, Felipe, linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Gupta, Pekon, spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Poddar, Sourav, Brian Norris, David Woodhouse On Tue, Oct 15, 2013 at 1:52 PM, Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote: > On Tue, Oct 15, 2013 at 06:33:23PM +0000, Gupta, Pekon wrote: > >> Therefore early suggestions were to make 'MM_MODE' as default >> (if device enables it via DT). This means: >> (1) switch to 'SPI_MODE' _only_ when required for commands like >> mtd_erase, etc. and switch back to 'MM_MODE' when done. >> (2) And keep your controller clocks on. > > This sounds like a policy decision, I don't see any reason for it to be > in DT. What works well with one application stack may not be the best > choice for another and future developments may change what's most > sensible for a given system, it shouldn't be fixed in the DT. I could see the driver using the transfer size to decide, memory mapped or SPI with DMA. Small transfers via memory mapped access and larger would use DMA. The spi-mxs driver does this to decide PIO or DMA. The threshold size is hard coded in the driver. If you wanted to be able to change it, I would think a sysfs attribute would be the way to do that. It does get tricky when you're dealing with flash roms, as people often want to boot from those really fast, so you want the kernel to know how to use them in the fastest way before it boots as opposed to after booting when it's obviously too late to configure the kernel to boot faster. ------------------------------------------------------------------------------ October Webinars: Code for Performance Free Intel webinars can help you accelerate application performance. Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from the latest Intel processors and coprocessors. See abstracts and register > http://pubads.g.doubleclick.net/gampad/clk?id=60135031&iu=/4140/ostg.clktrk ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-15 21:03 ` Trent Piepho 0 siblings, 0 replies; 104+ messages in thread From: Trent Piepho @ 2013-10-15 21:03 UTC (permalink / raw) To: Mark Brown Cc: Peter Korsgaard, Balbi, Felipe, linux-mtd, Gupta, Pekon, spi-devel-general, Poddar, Sourav, Brian Norris, David Woodhouse On Tue, Oct 15, 2013 at 1:52 PM, Mark Brown <broonie@kernel.org> wrote: > On Tue, Oct 15, 2013 at 06:33:23PM +0000, Gupta, Pekon wrote: > >> Therefore early suggestions were to make 'MM_MODE' as default >> (if device enables it via DT). This means: >> (1) switch to 'SPI_MODE' _only_ when required for commands like >> mtd_erase, etc. and switch back to 'MM_MODE' when done. >> (2) And keep your controller clocks on. > > This sounds like a policy decision, I don't see any reason for it to be > in DT. What works well with one application stack may not be the best > choice for another and future developments may change what's most > sensible for a given system, it shouldn't be fixed in the DT. I could see the driver using the transfer size to decide, memory mapped or SPI with DMA. Small transfers via memory mapped access and larger would use DMA. The spi-mxs driver does this to decide PIO or DMA. The threshold size is hard coded in the driver. If you wanted to be able to change it, I would think a sysfs attribute would be the way to do that. It does get tricky when you're dealing with flash roms, as people often want to boot from those really fast, so you want the kernel to know how to use them in the fastest way before it boots as opposed to after booting when it's obviously too late to configure the kernel to boot faster. ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-15 21:03 ` Trent Piepho @ 2013-10-15 22:10 ` Mark Brown -1 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-15 22:10 UTC (permalink / raw) To: Trent Piepho Cc: Peter Korsgaard, Balbi, Felipe, linux-mtd, Gupta, Pekon, spi-devel-general, Poddar, Sourav, Brian Norris, David Woodhouse [-- Attachment #1.1: Type: text/plain, Size: 434 bytes --] On Tue, Oct 15, 2013 at 02:03:01PM -0700, Trent Piepho wrote: > It does get tricky when you're dealing with flash roms, as people > often want to boot from those really fast, so you want the kernel to > know how to use them in the fastest way before it boots as opposed to > after booting when it's obviously too late to configure the kernel to > boot faster. I'd guess that having fast as the default would be sane enough, though. [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] [-- Attachment #2: Type: text/plain, Size: 144 bytes --] ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-15 22:10 ` Mark Brown 0 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-15 22:10 UTC (permalink / raw) To: Trent Piepho Cc: Peter Korsgaard, Balbi, Felipe, linux-mtd, Gupta, Pekon, spi-devel-general, Poddar, Sourav, Brian Norris, David Woodhouse [-- Attachment #1: Type: text/plain, Size: 434 bytes --] On Tue, Oct 15, 2013 at 02:03:01PM -0700, Trent Piepho wrote: > It does get tricky when you're dealing with flash roms, as people > often want to boot from those really fast, so you want the kernel to > know how to use them in the fastest way before it boots as opposed to > after booting when it's obviously too late to configure the kernel to > boot faster. I'd guess that having fast as the default would be sane enough, though. [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 104+ messages in thread
[parent not found: <20980858CB6D3A4BAE95CA194937D5E73EA23640-yXqyApvAXouIQmiDNMet8wC/G2K4zDHf@public.gmane.org>]
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-15 18:33 ` Gupta, Pekon @ 2013-10-17 12:24 ` Sourav Poddar -1 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-17 12:24 UTC (permalink / raw) To: Gupta, Pekon, Trent Piepho, Mark Brown Cc: Peter Korsgaard, Balbi, Felipe, linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Brian Norris, David Woodhouse Hi All, On Wednesday 16 October 2013 12:03 AM, Gupta, Pekon wrote: >> From: Trent Piepho >> Are there any numbers to show if memory mapped read support is a >> benefit in Linux? There is some question as to whether it's useful at >> all or not. >> >> If it is, I think low latency for small reads is probably one of the >> only advantages. To do that, you aren't going to want to deal with >> device PM for every single read. It would make more sense to turn the >> hardware on when the MTD device is opened and leave it on until >> closed. >> > +1 > > Therefore early suggestions were to make 'MM_MODE' as default > (if device enables it via DT). This means: > (1) switch to 'SPI_MODE' _only_ when required for commands like > mtd_erase, etc. and switch back to 'MM_MODE' when done. > (2) And keep your controller clocks on. > > This would ensure that you do minimum config-switching when using > MM_MODE. And would thus achieve low latency, and no driver intervention. > > Yes, real thruput numbers would help clear the picture here .. > > with regards, pekon I did some throughput measurement to get some number on the read side. Here are my observations: Case1: -------- Using SPI framework. Setup: Here, the actual memcpy is done in the spi controller, and flash communicates to the qspi controller to do the memcpy using the SPI framework. This is what is propsed in the $subject patch. Measurement method: used jiffies_to_msecs at the beginning and at the end of the mtd_read api and calculated the difference. Result: Tried a transfer of 32KB, which takes around 20 ms of time to read. Case2: -------- Bypassing SPI framework. Setup: Here, the actual memcpy is done in the mtd read api itself, by getting the memmap address from the spi controller. Measurement method: used jiffies_to_msecs before and after memcpy and calculated the difference. Result: Tried a transfer of 32KB, which takes around 10 ms of time to read. So, time reduced almost to half while bypassing the SPI framework. ------------------------------------------------------------------------------ October Webinars: Code for Performance Free Intel webinars can help you accelerate application performance. Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from the latest Intel processors and coprocessors. See abstracts and register > http://pubads.g.doubleclick.net/gampad/clk?id=60135031&iu=/4140/ostg.clktrk ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-17 12:24 ` Sourav Poddar 0 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-17 12:24 UTC (permalink / raw) To: Gupta, Pekon, Trent Piepho, Mark Brown Cc: Peter Korsgaard, Balbi, Felipe, linux-mtd, spi-devel-general, Brian Norris, David Woodhouse Hi All, On Wednesday 16 October 2013 12:03 AM, Gupta, Pekon wrote: >> From: Trent Piepho >> Are there any numbers to show if memory mapped read support is a >> benefit in Linux? There is some question as to whether it's useful at >> all or not. >> >> If it is, I think low latency for small reads is probably one of the >> only advantages. To do that, you aren't going to want to deal with >> device PM for every single read. It would make more sense to turn the >> hardware on when the MTD device is opened and leave it on until >> closed. >> > +1 > > Therefore early suggestions were to make 'MM_MODE' as default > (if device enables it via DT). This means: > (1) switch to 'SPI_MODE' _only_ when required for commands like > mtd_erase, etc. and switch back to 'MM_MODE' when done. > (2) And keep your controller clocks on. > > This would ensure that you do minimum config-switching when using > MM_MODE. And would thus achieve low latency, and no driver intervention. > > Yes, real thruput numbers would help clear the picture here .. > > with regards, pekon I did some throughput measurement to get some number on the read side. Here are my observations: Case1: -------- Using SPI framework. Setup: Here, the actual memcpy is done in the spi controller, and flash communicates to the qspi controller to do the memcpy using the SPI framework. This is what is propsed in the $subject patch. Measurement method: used jiffies_to_msecs at the beginning and at the end of the mtd_read api and calculated the difference. Result: Tried a transfer of 32KB, which takes around 20 ms of time to read. Case2: -------- Bypassing SPI framework. Setup: Here, the actual memcpy is done in the mtd read api itself, by getting the memmap address from the spi controller. Measurement method: used jiffies_to_msecs before and after memcpy and calculated the difference. Result: Tried a transfer of 32KB, which takes around 10 ms of time to read. So, time reduced almost to half while bypassing the SPI framework. ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-17 12:24 ` Sourav Poddar @ 2013-10-17 12:38 ` Mark Brown -1 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-17 12:38 UTC (permalink / raw) To: Sourav Poddar Cc: Peter Korsgaard, Brian Norris, Balbi, Felipe, linux-mtd, Gupta, Pekon, spi-devel-general, Trent Piepho, David Woodhouse [-- Attachment #1.1: Type: text/plain, Size: 784 bytes --] On Thu, Oct 17, 2013 at 05:54:53PM +0530, Sourav Poddar wrote: > Setup: > Here, the actual memcpy is done in the spi controller, and flash > communicates to the qspi controller to do the memcpy using the > SPI framework. This is what is propsed in the $subject patch. > Setup: > Here, the actual memcpy is done in the mtd read api itself, by > getting the > memmap address from the spi controller. > So, time reduced almost to half while bypassing the SPI framework. The interesting case for benchmarking here is more a comparison between normal DMA driven transfers and the memcpy(). Some consideration of the CPU load would also be interesting here, if the SoC is waiting for the flash then it's probably useful if it can make progress on other things. [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] [-- Attachment #2: Type: text/plain, Size: 144 bytes --] ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-17 12:38 ` Mark Brown 0 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-17 12:38 UTC (permalink / raw) To: Sourav Poddar Cc: Peter Korsgaard, Brian Norris, Balbi, Felipe, linux-mtd, Gupta, Pekon, spi-devel-general, Trent Piepho, David Woodhouse [-- Attachment #1: Type: text/plain, Size: 784 bytes --] On Thu, Oct 17, 2013 at 05:54:53PM +0530, Sourav Poddar wrote: > Setup: > Here, the actual memcpy is done in the spi controller, and flash > communicates to the qspi controller to do the memcpy using the > SPI framework. This is what is propsed in the $subject patch. > Setup: > Here, the actual memcpy is done in the mtd read api itself, by > getting the > memmap address from the spi controller. > So, time reduced almost to half while bypassing the SPI framework. The interesting case for benchmarking here is more a comparison between normal DMA driven transfers and the memcpy(). Some consideration of the CPU load would also be interesting here, if the SoC is waiting for the flash then it's probably useful if it can make progress on other things. [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 104+ messages in thread
* RE: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-17 12:38 ` Mark Brown @ 2013-10-17 13:03 ` Gupta, Pekon -1 siblings, 0 replies; 104+ messages in thread From: Gupta, Pekon @ 2013-10-17 13:03 UTC (permalink / raw) To: Mark Brown, Poddar, Sourav, Trent Piepho Cc: Peter Korsgaard, Balbi, Felipe, linux-mtd, spi-devel-general, Brian Norris, David Woodhouse Hi Mark, > From: Mark Brown [mailto:broonie@kernel.org] > > On Thu, Oct 17, 2013 at 05:54:53PM +0530, Sourav Poddar wrote: > > Setup: > > Here, the actual memcpy is done in the spi controller, and flash > > communicates to the qspi controller to do the memcpy using the > > SPI framework. This is what is propsed in the $subject patch. > > > Setup: > > Here, the actual memcpy is done in the mtd read api itself, by > > getting the > > memmap address from the spi controller. > > > So, time reduced almost to half while bypassing the SPI framework. > > The interesting case for benchmarking here is more a comparison between > normal DMA driven transfers and the memcpy(). Some consideration of the > CPU load would also be interesting here, if the SoC is waiting for the > flash then it's probably useful if it can make progress on other things. > So in this CASE-2: SPI framework is bypassed: mtd_read() becomes mtd_read() { if (flash->mmap_mode) if (dma_available) read_via_dma(destination, source, length); else memcpy(destination, source, length); else /* use spi frame-work by default */ } Are you looking for comparison between read_via_dma() v/s memcpy() ? If yes, then unfortunately we are bit constrained because our controller does not support DMA. So, we have to depend on CPU based memcpy() only. However, use of DMA can be added as an independent patch on top of this CASE-2 patch. So will the base patch for CASE-2 (with SPI framework is bypassed) help ? with regards, pekon ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* RE: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-17 13:03 ` Gupta, Pekon 0 siblings, 0 replies; 104+ messages in thread From: Gupta, Pekon @ 2013-10-17 13:03 UTC (permalink / raw) To: Mark Brown, Poddar, Sourav, Trent Piepho Cc: Peter Korsgaard, Balbi, Felipe, linux-mtd, spi-devel-general, Brian Norris, David Woodhouse Hi Mark, > From: Mark Brown [mailto:broonie@kernel.org] > > On Thu, Oct 17, 2013 at 05:54:53PM +0530, Sourav Poddar wrote: > > Setup: > > Here, the actual memcpy is done in the spi controller, and flash > > communicates to the qspi controller to do the memcpy using the > > SPI framework. This is what is propsed in the $subject patch. > > > Setup: > > Here, the actual memcpy is done in the mtd read api itself, by > > getting the > > memmap address from the spi controller. > > > So, time reduced almost to half while bypassing the SPI framework. > > The interesting case for benchmarking here is more a comparison between > normal DMA driven transfers and the memcpy(). Some consideration of the > CPU load would also be interesting here, if the SoC is waiting for the > flash then it's probably useful if it can make progress on other things. > So in this CASE-2: SPI framework is bypassed: mtd_read() becomes mtd_read() { if (flash->mmap_mode) if (dma_available) read_via_dma(destination, source, length); else memcpy(destination, source, length); else /* use spi frame-work by default */ } Are you looking for comparison between read_via_dma() v/s memcpy() ? If yes, then unfortunately we are bit constrained because our controller does not support DMA. So, we have to depend on CPU based memcpy() only. However, use of DMA can be added as an independent patch on top of this CASE-2 patch. So will the base patch for CASE-2 (with SPI framework is bypassed) help ? with regards, pekon ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-17 13:03 ` Gupta, Pekon (?) @ 2013-10-17 23:42 ` Mark Brown 2013-10-18 4:06 ` Sourav Poddar -1 siblings, 1 reply; 104+ messages in thread From: Mark Brown @ 2013-10-17 23:42 UTC (permalink / raw) To: Gupta, Pekon Cc: Peter Korsgaard, Brian Norris, Balbi, Felipe, linux-mtd, spi-devel-general, Poddar, Sourav, Trent Piepho, David Woodhouse [-- Attachment #1: Type: text/plain, Size: 844 bytes --] On Thu, Oct 17, 2013 at 01:03:26PM +0000, Gupta, Pekon wrote: > mtd_read() { > if (flash->mmap_mode) > if (dma_available) > read_via_dma(destination, source, length); > else > memcpy(destination, source, length); > else > /* use spi frame-work by default */ > } > Are you looking for comparison between read_via_dma() v/s memcpy() ? No, I'm looking for a comparison of normal SPI mode (which I'd have expected to DMA) and the memcpy() mode. > If yes, then unfortunately we are bit constrained because our controller > does not support DMA. So, we have to depend on CPU based memcpy() > only. However, use of DMA can be added as an independent patch on > top of this CASE-2 patch. However if the controller can't DMA at all then that's not going to be possible... am I understanding you correctly that normal SPI can't DMA? [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-17 23:42 ` Mark Brown @ 2013-10-18 4:06 ` Sourav Poddar 2013-10-18 5:56 ` Trent Piepho 0 siblings, 1 reply; 104+ messages in thread From: Sourav Poddar @ 2013-10-18 4:06 UTC (permalink / raw) To: Mark Brown Cc: Peter Korsgaard, Brian Norris, Balbi, Felipe, linux-mtd, Gupta, Pekon, spi-devel-general, Trent Piepho, David Woodhouse On Friday 18 October 2013 05:12 AM, Mark Brown wrote: > On Thu, Oct 17, 2013 at 01:03:26PM +0000, Gupta, Pekon wrote: > >> mtd_read() { >> if (flash->mmap_mode) >> if (dma_available) >> read_via_dma(destination, source, length); >> else >> memcpy(destination, source, length); >> else >> /* use spi frame-work by default */ >> } >> Are you looking for comparison between read_via_dma() v/s memcpy() ? > No, I'm looking for a comparison of normal SPI mode (which I'd have > expected to DMA) and the memcpy() mode. > >> If yes, then unfortunately we are bit constrained because our controller >> does not support DMA. So, we have to depend on CPU based memcpy() >> only. However, use of DMA can be added as an independent patch on >> top of this CASE-2 patch. > However if the controller can't DMA at all then that's not going to be > possible... am I understanding you correctly that normal SPI can't DMA? Yes, you are correct, the normal SPI cant DMA. ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-18 4:06 ` Sourav Poddar @ 2013-10-18 5:56 ` Trent Piepho 2013-10-18 6:10 ` Sourav Poddar 0 siblings, 1 reply; 104+ messages in thread From: Trent Piepho @ 2013-10-18 5:56 UTC (permalink / raw) To: Sourav Poddar Cc: Peter Korsgaard, Balbi, Felipe, Mark Brown, linux-mtd, Gupta, Pekon, spi-devel-general, Brian Norris, David Woodhouse On Thu, Oct 17, 2013 at 9:06 PM, Sourav Poddar <sourav.poddar@ti.com> wrote: > On Friday 18 October 2013 05:12 AM, Mark Brown wrote: >>> Are you looking for comparison between read_via_dma() v/s memcpy() ? >> >> No, I'm looking for a comparison of normal SPI mode (which I'd have >> expected to DMA) and the memcpy() mode. >> >>> If yes, then unfortunately we are bit constrained because our controller >>> does not support DMA. So, we have to depend on CPU based memcpy() >>> only. However, use of DMA can be added as an independent patch on >>> top of this CASE-2 patch. >> >> However if the controller can't DMA at all then that's not going to be >> possible... am I understanding you correctly that normal SPI can't DMA? > > Yes, you are correct, the normal SPI cant DMA. Hardware limitation or driver limitation? Adding DMA support to the driver might be much more useful than adding memory mapped read support. ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-18 5:56 ` Trent Piepho @ 2013-10-18 6:10 ` Sourav Poddar 2013-10-18 7:27 ` Sourav Poddar 0 siblings, 1 reply; 104+ messages in thread From: Sourav Poddar @ 2013-10-18 6:10 UTC (permalink / raw) To: Trent Piepho Cc: Peter Korsgaard, Balbi, Felipe, Mark Brown, linux-mtd, Gupta, Pekon, spi-devel-general, Brian Norris, David Woodhouse On Friday 18 October 2013 11:26 AM, Trent Piepho wrote: > On Thu, Oct 17, 2013 at 9:06 PM, Sourav Poddar<sourav.poddar@ti.com> wrote: >> On Friday 18 October 2013 05:12 AM, Mark Brown wrote: >>>> Are you looking for comparison between read_via_dma() v/s memcpy() ? >>> No, I'm looking for a comparison of normal SPI mode (which I'd have >>> expected to DMA) and the memcpy() mode. >>> >>>> If yes, then unfortunately we are bit constrained because our controller >>>> does not support DMA. So, we have to depend on CPU based memcpy() >>>> only. However, use of DMA can be added as an independent patch on >>>> top of this CASE-2 patch. >>> However if the controller can't DMA at all then that's not going to be >>> possible... am I understanding you correctly that normal SPI can't DMA? >> Yes, you are correct, the normal SPI cant DMA. > Hardware limitation or driver limitation? Adding DMA support to the > driver might be much more useful than adding memory mapped read > support. Its a hardware limitation, the qspi controller does not support DMA. ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-18 6:10 ` Sourav Poddar @ 2013-10-18 7:27 ` Sourav Poddar 2013-10-18 10:31 ` Mark Brown 0 siblings, 1 reply; 104+ messages in thread From: Sourav Poddar @ 2013-10-18 7:27 UTC (permalink / raw) To: Trent Piepho, Mark Brown, Gupta, Pekon, Brian Norris Cc: spi-devel-general, Peter Korsgaard, linux-mtd, David Woodhouse, Balbi, Felipe Hi, On Friday 18 October 2013 11:40 AM, Sourav Poddar wrote: > On Friday 18 October 2013 11:26 AM, Trent Piepho wrote: >> On Thu, Oct 17, 2013 at 9:06 PM, Sourav Poddar<sourav.poddar@ti.com> >> wrote: >>> On Friday 18 October 2013 05:12 AM, Mark Brown wrote: >>>>> Are you looking for comparison between read_via_dma() v/s memcpy() ? >>>> No, I'm looking for a comparison of normal SPI mode (which I'd have >>>> expected to DMA) and the memcpy() mode. >>>> >>>>> If yes, then unfortunately we are bit constrained because our >>>>> controller >>>>> does not support DMA. So, we have to depend on CPU based memcpy() >>>>> only. However, use of DMA can be added as an independent patch on >>>>> top of this CASE-2 patch. >>>> However if the controller can't DMA at all then that's not going to be >>>> possible... am I understanding you correctly that normal SPI can't >>>> DMA? >>> Yes, you are correct, the normal SPI cant DMA. >> Hardware limitation or driver limitation? Adding DMA support to the >> driver might be much more useful than adding memory mapped read >> support. > Its a hardware limitation, the qspi controller does not support DMA. > > ______________________________________________________ > Linux MTD discussion mailing list > http://lists.infradead.org/mailman/listinfo/linux-mtd/ So, consolidating all the comments, this is what can be done to improve the $subject patch.. 1. Keep the qspi controller by default in memory mapped mode. 2. While doing operations other than memory mapped, change the controller into config mode and at the end change it into memory mapped mode. 3. For filling memory mapped register in qspi controller, we can pass that information from dt rather than hardcoding as macros. 4. For memory mapped read, do the memcpy in the mtd_read itself and bypass the SPI framework. This has two points to be considered - 4a. Roadblock: To get the mem buf from the spi controller to mtd layer Solution: As suggested by Mark, we can define some apis like get_buf/free_buf in mtd driver and use that to get the buf. 4b. Roadblock: Runtime clock management is handle by SPI framework, so while doing memory read, where we bypass SPI framework, clocks will be disable and we will get an abort while doing memcpy. Possible solution: As suggested by Trent, we can keep the SPI controller clocks always ON ? If the above proposal looks good, should I go ahead and post the next updated patch series? ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-18 7:27 ` Sourav Poddar @ 2013-10-18 10:31 ` Mark Brown 2013-10-18 11:48 ` Sourav Poddar 0 siblings, 1 reply; 104+ messages in thread From: Mark Brown @ 2013-10-18 10:31 UTC (permalink / raw) To: Sourav Poddar Cc: Peter Korsgaard, Trent Piepho, Balbi, Felipe, linux-mtd, Gupta, Pekon, spi-devel-general, Brian Norris, David Woodhouse [-- Attachment #1: Type: text/plain, Size: 828 bytes --] On Fri, Oct 18, 2013 at 12:57:51PM +0530, Sourav Poddar wrote: > 3. For filling memory mapped register in qspi controller, we can > pass that information > from dt rather than hardcoding as macros. Or from the flash driver at runtime... > 4b. > Roadblock: > Runtime clock management is handle by SPI framework, so while > doing memory read, where we bypass SPI framework, clocks will be > disable and we will get an abort while doing memcpy. > Possible solution: > As suggested by Trent, we can keep the SPI controller > clocks always ON ? At the SPI layer I would keep the clocks on while the driver has a region mapped for the flash layer. The flash layer can then decide when to keep the region mapped, for example it could do so whenever the device is opened. [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-18 10:31 ` Mark Brown @ 2013-10-18 11:48 ` Sourav Poddar 2013-10-18 13:08 ` Mark Brown 0 siblings, 1 reply; 104+ messages in thread From: Sourav Poddar @ 2013-10-18 11:48 UTC (permalink / raw) To: Mark Brown Cc: Peter Korsgaard, Trent Piepho, Balbi, Felipe, linux-mtd, Gupta, Pekon, spi-devel-general, Brian Norris, David Woodhouse On Friday 18 October 2013 04:01 PM, Mark Brown wrote: > On Fri, Oct 18, 2013 at 12:57:51PM +0530, Sourav Poddar wrote: > >> 3. For filling memory mapped register in qspi controller, we can >> pass that information >> from dt rather than hardcoding as macros. > Or from the flash driver at runtime... > No, as for now, its better to keep mtd framework independent of this spi controller configuration and pass the information via dt. Since we dont have a common protocol, If we start putting this information in mtd, it will clutter the mtd space and it may happen that we may end up with differnet if defs for all the kind of flash devices. >> 4b. >> Roadblock: >> Runtime clock management is handle by SPI framework, so while >> doing memory read, where we bypass SPI framework, clocks will be >> disable and we will get an abort while doing memcpy. >> Possible solution: >> As suggested by Trent, we can keep the SPI controller >> clocks always ON ? > At the SPI layer I would keep the clocks on while the driver has a > region mapped for the flash layer. The flash layer can then decide when > to keep the region mapped, for example it could do so whenever the > device is opened. ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-18 11:48 ` Sourav Poddar @ 2013-10-18 13:08 ` Mark Brown 2013-10-18 14:47 ` Sourav Poddar 0 siblings, 1 reply; 104+ messages in thread From: Mark Brown @ 2013-10-18 13:08 UTC (permalink / raw) To: Sourav Poddar Cc: Peter Korsgaard, Trent Piepho, Balbi, Felipe, linux-mtd, Gupta, Pekon, spi-devel-general, Brian Norris, David Woodhouse [-- Attachment #1: Type: text/plain, Size: 923 bytes --] On Fri, Oct 18, 2013 at 05:18:15PM +0530, Sourav Poddar wrote: > On Friday 18 October 2013 04:01 PM, Mark Brown wrote: > >On Fri, Oct 18, 2013 at 12:57:51PM +0530, Sourav Poddar wrote: > >>3. For filling memory mapped register in qspi controller, we can > >>pass that information > >> from dt rather than hardcoding as macros. > >Or from the flash driver at runtime... > No, as for now, its better to keep mtd framework independent of this > spi controller configuration and pass the information via dt. > Since we dont have a common protocol, If we start putting this information > in mtd, it will clutter the mtd space and it may happen that we may end up > with differnet if defs for all the kind of flash devices. I thought this was the information for the flash commands that the driver would need to know anyway for use with SPI controllers without explicit flash support? But perhaps I'm misunderstanding. [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-18 13:08 ` Mark Brown @ 2013-10-18 14:47 ` Sourav Poddar 0 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-18 14:47 UTC (permalink / raw) To: Mark Brown Cc: Peter Korsgaard, Trent Piepho, Balbi, Felipe, linux-mtd, Gupta, Pekon, spi-devel-general, Brian Norris, David Woodhouse On Friday 18 October 2013 06:38 PM, Mark Brown wrote: > On Fri, Oct 18, 2013 at 05:18:15PM +0530, Sourav Poddar wrote: >> On Friday 18 October 2013 04:01 PM, Mark Brown wrote: >>> On Fri, Oct 18, 2013 at 12:57:51PM +0530, Sourav Poddar wrote: >>>> 3. For filling memory mapped register in qspi controller, we can >>>> pass that information >>>> from dt rather than hardcoding as macros. >>> Or from the flash driver at runtime... >> No, as for now, its better to keep mtd framework independent of this >> spi controller configuration and pass the information via dt. >> Since we dont have a common protocol, If we start putting this information >> in mtd, it will clutter the mtd space and it may happen that we may end up >> with differnet if defs for all the kind of flash devices. > I thought this was the information for the flash commands that the > driver would need to know anyway for use with SPI controllers without > explicit flash support? But perhaps I'm misunderstanding. Flash driver need to know them, but as of now, everything is done in a api mode stuff in flash driver. As in, we have write/erase/read, quad_read (proposed through this series) where we provide the commands directly. And to handle different flash types, we use macros to decide which command set is used. May be, this can come as a part of a seperate discussion to modify flash driver also to take data(commands, other parameters) through dt. Though, for the case in hand, better to set up spi mem map specific registers with dts from spi controller node itself. There might be different varieties of flashes, with different commands and cluttering mtd flash to configure a controller specific register does not look to be a good idea. ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-15 18:13 ` Trent Piepho @ 2013-10-15 20:59 ` Mark Brown -1 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-15 20:59 UTC (permalink / raw) To: Trent Piepho Cc: Peter Korsgaard, balbi, linux-mtd, spi-devel-general, Sourav Poddar, Brian Norris, David Woodhouse [-- Attachment #1.1: Type: text/plain, Size: 395 bytes --] On Tue, Oct 15, 2013 at 11:13:38AM -0700, Trent Piepho wrote: > If it is, I think low latency for small reads is probably one of the > only advantages. To do that, you aren't going to want to deal with > device PM for every single read. It would make more sense to turn the > hardware on when the MTD device is opened and leave it on until > closed. Autosuspend *might* be efficient enough. [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] [-- Attachment #2: Type: text/plain, Size: 144 bytes --] ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-15 20:59 ` Mark Brown 0 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-15 20:59 UTC (permalink / raw) To: Trent Piepho Cc: Peter Korsgaard, balbi, linux-mtd, spi-devel-general, Sourav Poddar, Brian Norris, David Woodhouse [-- Attachment #1: Type: text/plain, Size: 395 bytes --] On Tue, Oct 15, 2013 at 11:13:38AM -0700, Trent Piepho wrote: > If it is, I think low latency for small reads is probably one of the > only advantages. To do that, you aren't going to want to deal with > device PM for every single read. It would make more sense to turn the > hardware on when the MTD device is opened and leave it on until > closed. Autosuspend *might* be efficient enough. [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 104+ messages in thread
[parent not found: <52566ACC.1080100-l0cyMroinI0@public.gmane.org>]
* RE: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-10 8:52 ` Sourav Poddar @ 2013-10-11 9:30 ` Gupta, Pekon -1 siblings, 0 replies; 104+ messages in thread From: Gupta, Pekon @ 2013-10-11 9:30 UTC (permalink / raw) To: Poddar, Sourav, Trent Piepho, Peter Korsgaard, Mark Brown, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ, computersforpeace-Re5JQEeQqe8AvxtiuMwx3w Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Balbi, Felipe Hi, > From: Poddar, Sourav > > On Thursday 10 October 2013 07:57 AM, Trent Piepho wrote: > > I've found that the SPI layer adds rather a lot of overhead to SPI > > transactions. It appears to come mostly from using another thread to > > run the queue. A fast SPI message of a few dozen bytes ends up having > > more overhead from the SPI layer than the time it takes the driver to > > do the actual transfer. > > > > So memory mapped mode via some kind of SPI hack seems like a bad > > design. All the SPI layer overhead and you don't get DMA. Memory > > mapped SPI could be a win, but I think you'd need to do it at the MTD > > layer with a mapping driver that could read the mmapped SPI flash > > directly. > Yes, you are correct in all your comments above. I also feel that SPI > framework > should be bypassed. But the subject patch is derived based on the > following points/limitation: > > 1. There is a setup register in QSPI, that need to be filled, as of now > I am filling it > in my driver as a MACRO. > Based on you previous information of set_up_register.. > > What is "set_up_register"? > > set_up_register is a memory mapped specific register with the > > following fields: > > - RCMD (Read command, which is actually the flash read command) > > - NUmber of Address bytes > > - Number of dummy bytes > > - Read type(Single, dual and quad read). > > - Write command. set_up_register should be filled from DT not from Macros, as these value change from NAND device to device, and based on that populate 'struct m25p' in m25p_probe().Otherwise it might end-up in similar situation as in fsl_spinor driver. Refer below as an example. http://lists.infradead.org/pipermail/linux-mtd/2013-September/048552.html > 2. Controller repsonds to memory mapped read for read opcodes, > so during the read path we should tell the controller to switch to > memory mapped port. > As you would be know from DT when to enable MMODE, so you can actually make MM_MODE as your *default mode*. And only when SPI framework is used you selectively switch to SPI_MODE and revert back to MM_MODE while returning. This way you can use memcpy() or dma_copy() directly in flash driver like m25p80.c, and avoid getting SPI generic framework delays. So, it should be like this.. /* Make MM_MODE your default mode in controller driver */ qspi_driver.c: configure_qspi_controller(mode) { if (mode == MM_MODE) - do all your controller configurations for MM_MODE - do all OPCODE selections for MM_MODE } qspi_controller_probe() if (of_mode_property("spi-flash-memory-map") { spi->mode |= MM_MODE; /* configure_qspi_controller (MM_MODE) */ } else { /* configure_qspi_controller(SPI_MODE) */ } /* Case 1: MM_MODE=enabled: Flash driver calls memcpy() */ m25p80.c: m25p80_quad_read() { if (flash->mmap_read) /* controller is already in MM_MODE by default */ memcpy(*from, *to, length); else /* usual call to spi_framework */ } /* Case 2: SPI_MODE=enabled: Flash driver follows spi framework */ m25p80.c: m25p80_quad_read() { if (flash->mmap_read) /* ignored */ else spi_add_message_to_tail(); } qspi_driver.c: prepare_transfer_hardware() if (spi->mode & MM_MODE) { /* controller is in MM_MODE by default, so switch * to controller to SPI_MODE */ configure_qspi_controller (SPI_MODE); } else { /* controller is already in SPI_MODE always */ } qspi_driver.c: transfer_one_message () if (spi->mode & MM_MODE) { /* controller was switched to SPI_MODE in * prepare_transfer_hardware(),so revert back * back to MM_MODE */ configure_qspi_controller (MM_MODE); } else { /* controller is already in SPI_MODE always*/ } } *Important* But you need to be careful, because you need to synchronize with kthread_worker running inside SPI generic framework. So, lock your spi_controller while doing MMODE accesses. else you might end up in situation where a starving kthead_worker suddenly woke-up and changed your configurations from MMODE to SPI_MODE in between ongoing memcpy() or dma_cpy(). (Request David W, and Mark B to please review this proposal based on m25p80.c and SPI generic framework, as I may be missing some understanding here). with regards, pekon ------------------------------------------------------------------------------ October Webinars: Code for Performance Free Intel webinars can help you accelerate application performance. Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from the latest Intel processors and coprocessors. See abstracts and register > http://pubads.g.doubleclick.net/gampad/clk?id=60134071&iu=/4140/ostg.clktrk ^ permalink raw reply [flat|nested] 104+ messages in thread
* RE: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-11 9:30 ` Gupta, Pekon 0 siblings, 0 replies; 104+ messages in thread From: Gupta, Pekon @ 2013-10-11 9:30 UTC (permalink / raw) To: Poddar, Sourav, Trent Piepho, Peter Korsgaard, Mark Brown, dwmw2, computersforpeace Cc: spi-devel-general, linux-mtd, Balbi, Felipe Hi, > From: Poddar, Sourav > > On Thursday 10 October 2013 07:57 AM, Trent Piepho wrote: > > I've found that the SPI layer adds rather a lot of overhead to SPI > > transactions. It appears to come mostly from using another thread to > > run the queue. A fast SPI message of a few dozen bytes ends up having > > more overhead from the SPI layer than the time it takes the driver to > > do the actual transfer. > > > > So memory mapped mode via some kind of SPI hack seems like a bad > > design. All the SPI layer overhead and you don't get DMA. Memory > > mapped SPI could be a win, but I think you'd need to do it at the MTD > > layer with a mapping driver that could read the mmapped SPI flash > > directly. > Yes, you are correct in all your comments above. I also feel that SPI > framework > should be bypassed. But the subject patch is derived based on the > following points/limitation: > > 1. There is a setup register in QSPI, that need to be filled, as of now > I am filling it > in my driver as a MACRO. > Based on you previous information of set_up_register.. > > What is "set_up_register"? > > set_up_register is a memory mapped specific register with the > > following fields: > > - RCMD (Read command, which is actually the flash read command) > > - NUmber of Address bytes > > - Number of dummy bytes > > - Read type(Single, dual and quad read). > > - Write command. set_up_register should be filled from DT not from Macros, as these value change from NAND device to device, and based on that populate 'struct m25p' in m25p_probe().Otherwise it might end-up in similar situation as in fsl_spinor driver. Refer below as an example. http://lists.infradead.org/pipermail/linux-mtd/2013-September/048552.html > 2. Controller repsonds to memory mapped read for read opcodes, > so during the read path we should tell the controller to switch to > memory mapped port. > As you would be know from DT when to enable MMODE, so you can actually make MM_MODE as your *default mode*. And only when SPI framework is used you selectively switch to SPI_MODE and revert back to MM_MODE while returning. This way you can use memcpy() or dma_copy() directly in flash driver like m25p80.c, and avoid getting SPI generic framework delays. So, it should be like this.. /* Make MM_MODE your default mode in controller driver */ qspi_driver.c: configure_qspi_controller(mode) { if (mode == MM_MODE) - do all your controller configurations for MM_MODE - do all OPCODE selections for MM_MODE } qspi_controller_probe() if (of_mode_property("spi-flash-memory-map") { spi->mode |= MM_MODE; /* configure_qspi_controller (MM_MODE) */ } else { /* configure_qspi_controller(SPI_MODE) */ } /* Case 1: MM_MODE=enabled: Flash driver calls memcpy() */ m25p80.c: m25p80_quad_read() { if (flash->mmap_read) /* controller is already in MM_MODE by default */ memcpy(*from, *to, length); else /* usual call to spi_framework */ } /* Case 2: SPI_MODE=enabled: Flash driver follows spi framework */ m25p80.c: m25p80_quad_read() { if (flash->mmap_read) /* ignored */ else spi_add_message_to_tail(); } qspi_driver.c: prepare_transfer_hardware() if (spi->mode & MM_MODE) { /* controller is in MM_MODE by default, so switch * to controller to SPI_MODE */ configure_qspi_controller (SPI_MODE); } else { /* controller is already in SPI_MODE always */ } qspi_driver.c: transfer_one_message () if (spi->mode & MM_MODE) { /* controller was switched to SPI_MODE in * prepare_transfer_hardware(),so revert back * back to MM_MODE */ configure_qspi_controller (MM_MODE); } else { /* controller is already in SPI_MODE always*/ } } *Important* But you need to be careful, because you need to synchronize with kthread_worker running inside SPI generic framework. So, lock your spi_controller while doing MMODE accesses. else you might end up in situation where a starving kthead_worker suddenly woke-up and changed your configurations from MMODE to SPI_MODE in between ongoing memcpy() or dma_cpy(). (Request David W, and Mark B to please review this proposal based on m25p80.c and SPI generic framework, as I may be missing some understanding here). with regards, pekon ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-10 2:27 ` Trent Piepho @ 2013-10-10 10:10 ` Mark Brown -1 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-10 10:10 UTC (permalink / raw) To: Trent Piepho Cc: Peter Korsgaard, balbi, linux-mtd, spi-devel-general, Sourav Poddar, computersforpeace, dwmw2 [-- Attachment #1.1: Type: text/plain, Size: 1208 bytes --] On Wed, Oct 09, 2013 at 07:27:11PM -0700, Trent Piepho wrote: > I've found that the SPI layer adds rather a lot of overhead to SPI > transactions. It appears to come mostly from using another thread to > run the queue. A fast SPI message of a few dozen bytes ends up having > more overhead from the SPI layer than the time it takes the driver to > do the actual transfer. Yeah, though of course at the minute the implementation of that thread is pretty much up to the individual drivers which isn't triumph - and the quality of implementation does vary rather a lot. I'm currently working on trying to factor more of this out, hopefully then it'll be easier to push out improvements. It may be nice to be able to kick off the first DMA transfer from within the caller for example. > So memory mapped mode via some kind of SPI hack seems like a bad > design. All the SPI layer overhead and you don't get DMA. Memory > mapped SPI could be a win, but I think you'd need to do it at the MTD > layer with a mapping driver that could read the mmapped SPI flash > directly. Yes, exactly and even then I'm not convinced that it's going to be much advantage for anything except small transfers without DMA. [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] [-- Attachment #2: Type: text/plain, Size: 144 bytes --] ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-10 10:10 ` Mark Brown 0 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-10 10:10 UTC (permalink / raw) To: Trent Piepho Cc: Peter Korsgaard, balbi, linux-mtd, spi-devel-general, Sourav Poddar, computersforpeace, dwmw2 [-- Attachment #1: Type: text/plain, Size: 1208 bytes --] On Wed, Oct 09, 2013 at 07:27:11PM -0700, Trent Piepho wrote: > I've found that the SPI layer adds rather a lot of overhead to SPI > transactions. It appears to come mostly from using another thread to > run the queue. A fast SPI message of a few dozen bytes ends up having > more overhead from the SPI layer than the time it takes the driver to > do the actual transfer. Yeah, though of course at the minute the implementation of that thread is pretty much up to the individual drivers which isn't triumph - and the quality of implementation does vary rather a lot. I'm currently working on trying to factor more of this out, hopefully then it'll be easier to push out improvements. It may be nice to be able to kick off the first DMA transfer from within the caller for example. > So memory mapped mode via some kind of SPI hack seems like a bad > design. All the SPI layer overhead and you don't get DMA. Memory > mapped SPI could be a win, but I think you'd need to do it at the MTD > layer with a mapping driver that could read the mmapped SPI flash > directly. Yes, exactly and even then I'm not convinced that it's going to be much advantage for anything except small transfers without DMA. [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 104+ messages in thread
[parent not found: <20131010101052.GF21581-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>]
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. [not found] ` <20131010101052.GF21581-GFdadSzt00ze9xe1eoZjHA@public.gmane.org> @ 2013-10-10 23:53 ` Trent Piepho 2013-10-11 9:59 ` Mark Brown 0 siblings, 1 reply; 104+ messages in thread From: Trent Piepho @ 2013-10-10 23:53 UTC (permalink / raw) To: Mark Brown Cc: Peter Korsgaard, balbi-l0cyMroinI0, linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Sourav Poddar, Brian Norris, David Woodhouse On Thu, Oct 10, 2013 at 3:10 AM, Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote: > On Wed, Oct 09, 2013 at 07:27:11PM -0700, Trent Piepho wrote: > >> I've found that the SPI layer adds rather a lot of overhead to SPI >> transactions. It appears to come mostly from using another thread to >> run the queue. A fast SPI message of a few dozen bytes ends up having >> more overhead from the SPI layer than the time it takes the driver to >> do the actual transfer. > > Yeah, though of course at the minute the implementation of that thread > is pretty much up to the individual drivers which isn't triumph - and > the quality of implementation does vary rather a lot. I'm currently > working on trying to factor more of this out, hopefully then it'll be > easier to push out improvements. It may be nice to be able to kick off > the first DMA transfer from within the caller for example. I did testing with the mxs driver, which uses transfer_one _message and the spi core queue pumping code. For small messages the overhead of queuing work to the pump_messages queue and waiting for completion is rather more than the time the actual transfer takes. Which makes using a kthread rather pointless. Part of the problem could be the high context switch cost for ARMv5. >> So memory mapped mode via some kind of SPI hack seems like a bad >> design. All the SPI layer overhead and you don't get DMA. Memory >> mapped SPI could be a win, but I think you'd need to do it at the MTD >> layer with a mapping driver that could read the mmapped SPI flash >> directly. > > Yes, exactly and even then I'm not convinced that it's going to be much > advantage for anything except small transfers without DMA. My experience with a device using direct mapped NOR had a similar problem. While NOR was fast, access to it would necessarily use 100% CPU for whatever transfer rate is achieved. The eMMC based flash, while a far more complex driver, was actually better in terms of %CPU/MB because it could use DMA. Writing a custom sDMA script to use the iMX dmaengine for DMA with direct mapped flash would have been interesting. Direct mapping flash and losing DMA is probably always going to be a net lose for Linux filesystems on flash. Maybe on small memory systems there could be an advantage if you supported XIP with the mtd mapping driver. ------------------------------------------------------------------------------ October Webinars: Code for Performance Free Intel webinars can help you accelerate application performance. Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from the latest Intel processors and coprocessors. See abstracts and register > http://pubads.g.doubleclick.net/gampad/clk?id=60134071&iu=/4140/ostg.clktrk ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. 2013-10-10 23:53 ` Trent Piepho @ 2013-10-11 9:59 ` Mark Brown 0 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-11 9:59 UTC (permalink / raw) To: Trent Piepho Cc: Peter Korsgaard, balbi, linux-mtd, spi-devel-general, Sourav Poddar, Brian Norris, David Woodhouse [-- Attachment #1.1: Type: text/plain, Size: 1532 bytes --] On Thu, Oct 10, 2013 at 04:53:46PM -0700, Trent Piepho wrote: > On Thu, Oct 10, 2013 at 3:10 AM, Mark Brown <broonie@kernel.org> wrote: > > Yeah, though of course at the minute the implementation of that thread > > is pretty much up to the individual drivers which isn't triumph - and > > the quality of implementation does vary rather a lot. I'm currently > > working on trying to factor more of this out, hopefully then it'll be > > easier to push out improvements. It may be nice to be able to kick off > > the first DMA transfer from within the caller for example. > I did testing with the mxs driver, which uses transfer_one > _message and the spi core queue pumping code. For small messages the > overhead of queuing work to the pump_messages queue and waiting for > completion is rather more than the time the actual transfer takes. Which > makes using a kthread rather pointless. Part of the problem could be the > high context switch cost for ARMv5. Indeed - that's what I'd expect to happen. Sufficiently small PIO transfers and DMA initiation should both be faster if done from the calling context. The thread starts to get more useful once you start building up work (at which point it should reduce context switches, especially if multiple threads are using the bus) and if the system is very heavily loaded when you can raise the thread priority so it can drive data in more quickly. That said it's also helpful in terms of making the code simpler to just have the one data path. [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] [-- Attachment #2: Type: text/plain, Size: 144 bytes --] ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 1/3] spi/qspi: Add memory mapped read support. @ 2013-10-11 9:59 ` Mark Brown 0 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-11 9:59 UTC (permalink / raw) To: Trent Piepho Cc: Peter Korsgaard, balbi, linux-mtd, spi-devel-general, Sourav Poddar, Brian Norris, David Woodhouse [-- Attachment #1: Type: text/plain, Size: 1532 bytes --] On Thu, Oct 10, 2013 at 04:53:46PM -0700, Trent Piepho wrote: > On Thu, Oct 10, 2013 at 3:10 AM, Mark Brown <broonie@kernel.org> wrote: > > Yeah, though of course at the minute the implementation of that thread > > is pretty much up to the individual drivers which isn't triumph - and > > the quality of implementation does vary rather a lot. I'm currently > > working on trying to factor more of this out, hopefully then it'll be > > easier to push out improvements. It may be nice to be able to kick off > > the first DMA transfer from within the caller for example. > I did testing with the mxs driver, which uses transfer_one > _message and the spi core queue pumping code. For small messages the > overhead of queuing work to the pump_messages queue and waiting for > completion is rather more than the time the actual transfer takes. Which > makes using a kthread rather pointless. Part of the problem could be the > high context switch cost for ARMv5. Indeed - that's what I'd expect to happen. Sufficiently small PIO transfers and DMA initiation should both be faster if done from the calling context. The thread starts to get more useful once you start building up work (at which point it should reduce context switches, especially if multiple threads are using the bus) and if the system is very heavily loaded when you can raise the thread priority so it can drive data in more quickly. That said it's also helpful in terms of making the code simpler to just have the one data path. [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 104+ messages in thread
* [PATCHv3 2/3] drivers: mtd: devices: Add quad read support. 2013-10-09 15:24 ` Sourav Poddar @ 2013-10-09 15:24 ` Sourav Poddar -1 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-09 15:24 UTC (permalink / raw) To: broonie, dwmw2, computersforpeace Cc: spi-devel-general, Sourav Poddar, linux-mtd, balbi Some flash also support quad read mode. Adding support for adding quad mode in m25p80 for spansion and macronix flash. Signed-off-by: Sourav Poddar <sourav.poddar@ti.com> --- v2->v3: Add macronix flash support drivers/mtd/devices/m25p80.c | 184 ++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 176 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 26b14f9..dc9bcbf 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -41,6 +41,7 @@ #define OPCODE_WRSR 0x01 /* Write status register 1 byte */ #define OPCODE_NORM_READ 0x03 /* Read data bytes (low frequency) */ #define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */ +#define OPCODE_QUAD_READ 0x6b /* QUAD READ */ #define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */ #define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ #define OPCODE_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */ @@ -48,6 +49,7 @@ #define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */ #define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */ #define OPCODE_RDID 0x9f /* Read JEDEC ID */ +#define OPCODE_RDCR 0x35 /* Read configuration register */ /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ #define OPCODE_NORM_READ_4B 0x13 /* Read data bytes (low frequency) */ @@ -76,6 +78,10 @@ #define SR_BP2 0x10 /* Block protect 2 */ #define SR_SRWD 0x80 /* SR write protect */ +/* Configuration Register bits. */ +#define SPAN_QUAD_CR_EN 0x2 /* Spansion Quad I/O */ +#define MACR_QUAD_SR_EN 0x40 /* Macronix Quad I/O */ + /* Define max times to check status register before we give up. */ #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ #define MAX_CMD_SIZE 5 @@ -95,6 +101,7 @@ struct m25p { u8 program_opcode; u8 *command; bool fast_read; + bool quad_read; }; static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) @@ -163,6 +170,25 @@ static inline int write_disable(struct m25p *flash) return spi_write_then_read(flash->spi, &code, 1, NULL, 0); } +/* Read the configuration register, returning its value in the location + * Return the configuration register value. + * Returns negative if error occurred. +*/ +static int read_cr(struct m25p *flash) +{ + u8 code = OPCODE_RDCR; + int ret; + u8 val; + + ret = spi_write_then_read(flash->spi, &code, 1, &val, 1); + if (ret < 0) { + dev_err(&flash->spi->dev, "error %d reading CR\n", ret); + return ret; + } + + return val; +} + /* * Enable/disable 4-byte addressing mode. */ @@ -336,6 +362,122 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) return 0; } +/* Write status register and configuration register with 2 bytes +* The first byte will be written to the status register, while the second byte +* will be written to the configuration register. +* Returns negative if error occurred. +*/ +static int write_sr_cr(struct m25p *flash, u16 val) +{ + flash->command[0] = OPCODE_WRSR; + flash->command[1] = val & 0xff; + flash->command[2] = (val >> 8); + + return spi_write(flash->spi, flash->command, 3); +} + +static int macronix_quad_enable(struct m25p *flash) +{ + int ret, val; + u8 cmd[2]; + cmd[0] = OPCODE_WRSR; + + val = read_sr(flash); + cmd[1] = val | MACR_QUAD_SR_EN; + write_enable(flash); + + spi_write(flash->spi, &cmd, 2); + + if (wait_till_ready(flash)) + return 1; + + ret = read_sr(flash); + if (!(ret > 0 && (ret & MACR_QUAD_SR_EN))) { + dev_err(&flash->spi->dev, + "Macronix Quad bit not set"); + return -EINVAL; + } + + return 0; +} + +static int spansion_quad_enable(struct m25p *flash) +{ + int ret; + int quad_en = SPAN_QUAD_CR_EN << 8; + + write_enable(flash); + + ret = write_sr_cr(flash, quad_en); + if (ret < 0) { + dev_err(&flash->spi->dev, + "error while writing configuration register"); + return -EINVAL; + } + + /* read back and check it */ + ret = read_cr(flash); + if (!(ret > 0 && (ret & SPAN_QUAD_CR_EN))) { + dev_err(&flash->spi->dev, + "Spansion Quad bit not set"); + return -EINVAL; + } + + return 0; +} + +static int m25p80_quad_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct m25p *flash = mtd_to_m25p(mtd); + struct spi_transfer t[2]; + struct spi_message m; + uint8_t opcode; + + pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev), + __func__, (u32)from, len); + + spi_message_init(&m); + memset(t, 0, (sizeof(t))); + + t[0].tx_buf = flash->command; + t[0].len = m25p_cmdsz(flash) + (flash->quad_read ? 1 : 0); + spi_message_add_tail(&t[0], &m); + + t[1].rx_buf = buf; + t[1].len = len; + t[1].rx_nbits = SPI_NBITS_QUAD; + spi_message_add_tail(&t[1], &m); + + mutex_lock(&flash->lock); + + /* Wait till previous write/erase is done. */ + if (wait_till_ready(flash)) { + /* REVISIT status return?? */ + mutex_unlock(&flash->lock); + return 1; + } + + /* FIXME switch to OPCODE_QUAD_READ. It's required for higher + * clocks; and at this writing, every chip this driver handles + * supports that opcode. + */ + + /* Set up the write data buffer. */ + opcode = flash->read_opcode; + flash->command[0] = opcode; + m25p_addr2cmd(flash, from, flash->command); + + spi_sync(flash->spi, &m); + + *retlen = m.actual_length - m25p_cmdsz(flash) - + (flash->quad_read ? 1 : 0); + + mutex_unlock(&flash->lock); + + return 0; +} + /* * Read an address range from the flash chip. The address range * may be any size provided it is within the physical boundaries. @@ -928,6 +1070,7 @@ static int m25p_probe(struct spi_device *spi) unsigned i; struct mtd_part_parser_data ppdata; struct device_node __maybe_unused *np = spi->dev.of_node; + int ret; #ifdef CONFIG_MTD_OF_PARTS if (!of_device_is_available(np)) @@ -979,15 +1122,9 @@ static int m25p_probe(struct spi_device *spi) } } - flash = kzalloc(sizeof *flash, GFP_KERNEL); + flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL); if (!flash) return -ENOMEM; - flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : 0), - GFP_KERNEL); - if (!flash->command) { - kfree(flash); - return -ENOMEM; - } flash->spi = spi; mutex_init(&flash->lock); @@ -1015,7 +1152,6 @@ static int m25p_probe(struct spi_device *spi) flash->mtd.flags = MTD_CAP_NORFLASH; flash->mtd.size = info->sector_size * info->n_sectors; flash->mtd._erase = m25p80_erase; - flash->mtd._read = m25p80_read; /* flash protection support for STmicro chips */ if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ST) { @@ -1067,6 +1203,38 @@ static int m25p_probe(struct spi_device *spi) flash->program_opcode = OPCODE_PP; + flash->quad_read = false; + if (spi->mode && SPI_RX_QUAD) + flash->quad_read = true; + + flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : + (flash->quad_read ? 1 : 0)), GFP_KERNEL); + if (!flash->command) { + kfree(flash); + return -ENOMEM; + } + + if (flash->quad_read) { + if (of_property_read_bool(np, "macronix,quad_enable")) { + ret = macronix_quad_enable(flash); + if (ret) { + dev_err(&spi->dev, + "error enabling quad"); + return -EINVAL; + } + } else if (of_property_read_bool(np, "spansion,quad_enable")) { + ret = spansion_quad_enable(flash); + if (ret) { + dev_err(&spi->dev, + "error enabling quad"); + return -EINVAL; + } + } else + dev_dbg(&spi->dev, "quad enable not supported"); + flash->mtd._read = m25p80_quad_read; + } else + flash->mtd._read = m25p80_read; + if (info->addr_width) flash->addr_width = info->addr_width; else if (flash->mtd.size > 0x1000000) { -- 1.7.1 ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply related [flat|nested] 104+ messages in thread
* [PATCHv3 2/3] drivers: mtd: devices: Add quad read support. @ 2013-10-09 15:24 ` Sourav Poddar 0 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-09 15:24 UTC (permalink / raw) To: broonie, dwmw2, computersforpeace Cc: spi-devel-general, Sourav Poddar, linux-mtd, balbi Some flash also support quad read mode. Adding support for adding quad mode in m25p80 for spansion and macronix flash. Signed-off-by: Sourav Poddar <sourav.poddar@ti.com> --- v2->v3: Add macronix flash support drivers/mtd/devices/m25p80.c | 184 ++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 176 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 26b14f9..dc9bcbf 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -41,6 +41,7 @@ #define OPCODE_WRSR 0x01 /* Write status register 1 byte */ #define OPCODE_NORM_READ 0x03 /* Read data bytes (low frequency) */ #define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */ +#define OPCODE_QUAD_READ 0x6b /* QUAD READ */ #define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */ #define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ #define OPCODE_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */ @@ -48,6 +49,7 @@ #define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */ #define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */ #define OPCODE_RDID 0x9f /* Read JEDEC ID */ +#define OPCODE_RDCR 0x35 /* Read configuration register */ /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ #define OPCODE_NORM_READ_4B 0x13 /* Read data bytes (low frequency) */ @@ -76,6 +78,10 @@ #define SR_BP2 0x10 /* Block protect 2 */ #define SR_SRWD 0x80 /* SR write protect */ +/* Configuration Register bits. */ +#define SPAN_QUAD_CR_EN 0x2 /* Spansion Quad I/O */ +#define MACR_QUAD_SR_EN 0x40 /* Macronix Quad I/O */ + /* Define max times to check status register before we give up. */ #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ #define MAX_CMD_SIZE 5 @@ -95,6 +101,7 @@ struct m25p { u8 program_opcode; u8 *command; bool fast_read; + bool quad_read; }; static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) @@ -163,6 +170,25 @@ static inline int write_disable(struct m25p *flash) return spi_write_then_read(flash->spi, &code, 1, NULL, 0); } +/* Read the configuration register, returning its value in the location + * Return the configuration register value. + * Returns negative if error occurred. +*/ +static int read_cr(struct m25p *flash) +{ + u8 code = OPCODE_RDCR; + int ret; + u8 val; + + ret = spi_write_then_read(flash->spi, &code, 1, &val, 1); + if (ret < 0) { + dev_err(&flash->spi->dev, "error %d reading CR\n", ret); + return ret; + } + + return val; +} + /* * Enable/disable 4-byte addressing mode. */ @@ -336,6 +362,122 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) return 0; } +/* Write status register and configuration register with 2 bytes +* The first byte will be written to the status register, while the second byte +* will be written to the configuration register. +* Returns negative if error occurred. +*/ +static int write_sr_cr(struct m25p *flash, u16 val) +{ + flash->command[0] = OPCODE_WRSR; + flash->command[1] = val & 0xff; + flash->command[2] = (val >> 8); + + return spi_write(flash->spi, flash->command, 3); +} + +static int macronix_quad_enable(struct m25p *flash) +{ + int ret, val; + u8 cmd[2]; + cmd[0] = OPCODE_WRSR; + + val = read_sr(flash); + cmd[1] = val | MACR_QUAD_SR_EN; + write_enable(flash); + + spi_write(flash->spi, &cmd, 2); + + if (wait_till_ready(flash)) + return 1; + + ret = read_sr(flash); + if (!(ret > 0 && (ret & MACR_QUAD_SR_EN))) { + dev_err(&flash->spi->dev, + "Macronix Quad bit not set"); + return -EINVAL; + } + + return 0; +} + +static int spansion_quad_enable(struct m25p *flash) +{ + int ret; + int quad_en = SPAN_QUAD_CR_EN << 8; + + write_enable(flash); + + ret = write_sr_cr(flash, quad_en); + if (ret < 0) { + dev_err(&flash->spi->dev, + "error while writing configuration register"); + return -EINVAL; + } + + /* read back and check it */ + ret = read_cr(flash); + if (!(ret > 0 && (ret & SPAN_QUAD_CR_EN))) { + dev_err(&flash->spi->dev, + "Spansion Quad bit not set"); + return -EINVAL; + } + + return 0; +} + +static int m25p80_quad_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct m25p *flash = mtd_to_m25p(mtd); + struct spi_transfer t[2]; + struct spi_message m; + uint8_t opcode; + + pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev), + __func__, (u32)from, len); + + spi_message_init(&m); + memset(t, 0, (sizeof(t))); + + t[0].tx_buf = flash->command; + t[0].len = m25p_cmdsz(flash) + (flash->quad_read ? 1 : 0); + spi_message_add_tail(&t[0], &m); + + t[1].rx_buf = buf; + t[1].len = len; + t[1].rx_nbits = SPI_NBITS_QUAD; + spi_message_add_tail(&t[1], &m); + + mutex_lock(&flash->lock); + + /* Wait till previous write/erase is done. */ + if (wait_till_ready(flash)) { + /* REVISIT status return?? */ + mutex_unlock(&flash->lock); + return 1; + } + + /* FIXME switch to OPCODE_QUAD_READ. It's required for higher + * clocks; and at this writing, every chip this driver handles + * supports that opcode. + */ + + /* Set up the write data buffer. */ + opcode = flash->read_opcode; + flash->command[0] = opcode; + m25p_addr2cmd(flash, from, flash->command); + + spi_sync(flash->spi, &m); + + *retlen = m.actual_length - m25p_cmdsz(flash) - + (flash->quad_read ? 1 : 0); + + mutex_unlock(&flash->lock); + + return 0; +} + /* * Read an address range from the flash chip. The address range * may be any size provided it is within the physical boundaries. @@ -928,6 +1070,7 @@ static int m25p_probe(struct spi_device *spi) unsigned i; struct mtd_part_parser_data ppdata; struct device_node __maybe_unused *np = spi->dev.of_node; + int ret; #ifdef CONFIG_MTD_OF_PARTS if (!of_device_is_available(np)) @@ -979,15 +1122,9 @@ static int m25p_probe(struct spi_device *spi) } } - flash = kzalloc(sizeof *flash, GFP_KERNEL); + flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL); if (!flash) return -ENOMEM; - flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : 0), - GFP_KERNEL); - if (!flash->command) { - kfree(flash); - return -ENOMEM; - } flash->spi = spi; mutex_init(&flash->lock); @@ -1015,7 +1152,6 @@ static int m25p_probe(struct spi_device *spi) flash->mtd.flags = MTD_CAP_NORFLASH; flash->mtd.size = info->sector_size * info->n_sectors; flash->mtd._erase = m25p80_erase; - flash->mtd._read = m25p80_read; /* flash protection support for STmicro chips */ if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ST) { @@ -1067,6 +1203,38 @@ static int m25p_probe(struct spi_device *spi) flash->program_opcode = OPCODE_PP; + flash->quad_read = false; + if (spi->mode && SPI_RX_QUAD) + flash->quad_read = true; + + flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : + (flash->quad_read ? 1 : 0)), GFP_KERNEL); + if (!flash->command) { + kfree(flash); + return -ENOMEM; + } + + if (flash->quad_read) { + if (of_property_read_bool(np, "macronix,quad_enable")) { + ret = macronix_quad_enable(flash); + if (ret) { + dev_err(&spi->dev, + "error enabling quad"); + return -EINVAL; + } + } else if (of_property_read_bool(np, "spansion,quad_enable")) { + ret = spansion_quad_enable(flash); + if (ret) { + dev_err(&spi->dev, + "error enabling quad"); + return -EINVAL; + } + } else + dev_dbg(&spi->dev, "quad enable not supported"); + flash->mtd._read = m25p80_quad_read; + } else + flash->mtd._read = m25p80_read; + if (info->addr_width) flash->addr_width = info->addr_width; else if (flash->mtd.size > 0x1000000) { -- 1.7.1 ^ permalink raw reply related [flat|nested] 104+ messages in thread
[parent not found: <1381332284-21822-3-git-send-email-sourav.poddar-l0cyMroinI0@public.gmane.org>]
* Re: [PATCHv3 2/3] drivers: mtd: devices: Add quad read support. 2013-10-09 15:24 ` Sourav Poddar @ 2013-10-09 18:15 ` Jagan Teki -1 siblings, 0 replies; 104+ messages in thread From: Jagan Teki @ 2013-10-09 18:15 UTC (permalink / raw) To: Sourav Poddar Cc: Felipe Balbi, broonie-DgEjT+Ai2ygdnm+yROfE0A, linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, computersforpeace-Re5JQEeQqe8AvxtiuMwx3w, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ On Wed, Oct 9, 2013 at 8:54 PM, Sourav Poddar <sourav.poddar-l0cyMroinI0@public.gmane.org> wrote: > Some flash also support quad read mode. > Adding support for adding quad mode in m25p80 > for spansion and macronix flash. I am some how not happy with this approach, adding a flags on flash param table for supporting quad operation in specific flash is may be a better idea. But reading SFDP, is a good idea to get the details of flash - quad support is one of them. and we can assign quad read or fast read based on that. Any comments. > > Signed-off-by: Sourav Poddar <sourav.poddar-l0cyMroinI0@public.gmane.org> > --- > v2->v3: > Add macronix flash support > drivers/mtd/devices/m25p80.c | 184 ++++++++++++++++++++++++++++++++++++++++-- > 1 files changed, 176 insertions(+), 8 deletions(-) > > diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c > index 26b14f9..dc9bcbf 100644 > --- a/drivers/mtd/devices/m25p80.c > +++ b/drivers/mtd/devices/m25p80.c > @@ -41,6 +41,7 @@ > #define OPCODE_WRSR 0x01 /* Write status register 1 byte */ > #define OPCODE_NORM_READ 0x03 /* Read data bytes (low frequency) */ > #define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */ > +#define OPCODE_QUAD_READ 0x6b /* QUAD READ */ > #define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */ > #define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ > #define OPCODE_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */ > @@ -48,6 +49,7 @@ > #define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */ > #define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */ > #define OPCODE_RDID 0x9f /* Read JEDEC ID */ > +#define OPCODE_RDCR 0x35 /* Read configuration register */ > > /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ > #define OPCODE_NORM_READ_4B 0x13 /* Read data bytes (low frequency) */ > @@ -76,6 +78,10 @@ > #define SR_BP2 0x10 /* Block protect 2 */ > #define SR_SRWD 0x80 /* SR write protect */ > > +/* Configuration Register bits. */ > +#define SPAN_QUAD_CR_EN 0x2 /* Spansion Quad I/O */ > +#define MACR_QUAD_SR_EN 0x40 /* Macronix Quad I/O */ > + > /* Define max times to check status register before we give up. */ > #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ > #define MAX_CMD_SIZE 5 > @@ -95,6 +101,7 @@ struct m25p { > u8 program_opcode; > u8 *command; > bool fast_read; > + bool quad_read; > }; > > static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) > @@ -163,6 +170,25 @@ static inline int write_disable(struct m25p *flash) > return spi_write_then_read(flash->spi, &code, 1, NULL, 0); > } > > +/* Read the configuration register, returning its value in the location > + * Return the configuration register value. > + * Returns negative if error occurred. > +*/ > +static int read_cr(struct m25p *flash) > +{ > + u8 code = OPCODE_RDCR; > + int ret; > + u8 val; > + > + ret = spi_write_then_read(flash->spi, &code, 1, &val, 1); > + if (ret < 0) { > + dev_err(&flash->spi->dev, "error %d reading CR\n", ret); > + return ret; > + } > + > + return val; > +} > + > /* > * Enable/disable 4-byte addressing mode. > */ > @@ -336,6 +362,122 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) > return 0; > } > > +/* Write status register and configuration register with 2 bytes > +* The first byte will be written to the status register, while the second byte > +* will be written to the configuration register. > +* Returns negative if error occurred. > +*/ > +static int write_sr_cr(struct m25p *flash, u16 val) > +{ > + flash->command[0] = OPCODE_WRSR; > + flash->command[1] = val & 0xff; > + flash->command[2] = (val >> 8); > + > + return spi_write(flash->spi, flash->command, 3); > +} > + > +static int macronix_quad_enable(struct m25p *flash) > +{ > + int ret, val; > + u8 cmd[2]; > + cmd[0] = OPCODE_WRSR; > + > + val = read_sr(flash); > + cmd[1] = val | MACR_QUAD_SR_EN; > + write_enable(flash); > + > + spi_write(flash->spi, &cmd, 2); > + > + if (wait_till_ready(flash)) > + return 1; > + > + ret = read_sr(flash); > + if (!(ret > 0 && (ret & MACR_QUAD_SR_EN))) { > + dev_err(&flash->spi->dev, > + "Macronix Quad bit not set"); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static int spansion_quad_enable(struct m25p *flash) > +{ > + int ret; > + int quad_en = SPAN_QUAD_CR_EN << 8; > + > + write_enable(flash); > + > + ret = write_sr_cr(flash, quad_en); > + if (ret < 0) { > + dev_err(&flash->spi->dev, > + "error while writing configuration register"); > + return -EINVAL; > + } > + > + /* read back and check it */ > + ret = read_cr(flash); > + if (!(ret > 0 && (ret & SPAN_QUAD_CR_EN))) { > + dev_err(&flash->spi->dev, > + "Spansion Quad bit not set"); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static int m25p80_quad_read(struct mtd_info *mtd, loff_t from, size_t len, > + size_t *retlen, u_char *buf) > +{ > + struct m25p *flash = mtd_to_m25p(mtd); > + struct spi_transfer t[2]; > + struct spi_message m; > + uint8_t opcode; > + > + pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev), > + __func__, (u32)from, len); > + > + spi_message_init(&m); > + memset(t, 0, (sizeof(t))); > + > + t[0].tx_buf = flash->command; > + t[0].len = m25p_cmdsz(flash) + (flash->quad_read ? 1 : 0); > + spi_message_add_tail(&t[0], &m); > + > + t[1].rx_buf = buf; > + t[1].len = len; > + t[1].rx_nbits = SPI_NBITS_QUAD; > + spi_message_add_tail(&t[1], &m); > + > + mutex_lock(&flash->lock); > + > + /* Wait till previous write/erase is done. */ > + if (wait_till_ready(flash)) { > + /* REVISIT status return?? */ > + mutex_unlock(&flash->lock); > + return 1; > + } > + > + /* FIXME switch to OPCODE_QUAD_READ. It's required for higher > + * clocks; and at this writing, every chip this driver handles > + * supports that opcode. > + */ > + > + /* Set up the write data buffer. */ > + opcode = flash->read_opcode; > + flash->command[0] = opcode; > + m25p_addr2cmd(flash, from, flash->command); > + > + spi_sync(flash->spi, &m); > + > + *retlen = m.actual_length - m25p_cmdsz(flash) - > + (flash->quad_read ? 1 : 0); > + > + mutex_unlock(&flash->lock); > + > + return 0; > +} > + > /* > * Read an address range from the flash chip. The address range > * may be any size provided it is within the physical boundaries. > @@ -928,6 +1070,7 @@ static int m25p_probe(struct spi_device *spi) > unsigned i; > struct mtd_part_parser_data ppdata; > struct device_node __maybe_unused *np = spi->dev.of_node; > + int ret; > > #ifdef CONFIG_MTD_OF_PARTS > if (!of_device_is_available(np)) > @@ -979,15 +1122,9 @@ static int m25p_probe(struct spi_device *spi) > } > } > > - flash = kzalloc(sizeof *flash, GFP_KERNEL); > + flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL); > if (!flash) > return -ENOMEM; > - flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : 0), > - GFP_KERNEL); > - if (!flash->command) { > - kfree(flash); > - return -ENOMEM; > - } > > flash->spi = spi; > mutex_init(&flash->lock); > @@ -1015,7 +1152,6 @@ static int m25p_probe(struct spi_device *spi) > flash->mtd.flags = MTD_CAP_NORFLASH; > flash->mtd.size = info->sector_size * info->n_sectors; > flash->mtd._erase = m25p80_erase; > - flash->mtd._read = m25p80_read; > > /* flash protection support for STmicro chips */ > if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ST) { > @@ -1067,6 +1203,38 @@ static int m25p_probe(struct spi_device *spi) > > flash->program_opcode = OPCODE_PP; > > + flash->quad_read = false; > + if (spi->mode && SPI_RX_QUAD) > + flash->quad_read = true; > + > + flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : > + (flash->quad_read ? 1 : 0)), GFP_KERNEL); > + if (!flash->command) { > + kfree(flash); > + return -ENOMEM; > + } > + > + if (flash->quad_read) { > + if (of_property_read_bool(np, "macronix,quad_enable")) { > + ret = macronix_quad_enable(flash); > + if (ret) { > + dev_err(&spi->dev, > + "error enabling quad"); > + return -EINVAL; > + } > + } else if (of_property_read_bool(np, "spansion,quad_enable")) { > + ret = spansion_quad_enable(flash); > + if (ret) { > + dev_err(&spi->dev, > + "error enabling quad"); > + return -EINVAL; > + } > + } else > + dev_dbg(&spi->dev, "quad enable not supported"); > + flash->mtd._read = m25p80_quad_read; > + } else > + flash->mtd._read = m25p80_read; > + > if (info->addr_width) > flash->addr_width = info->addr_width; > else if (flash->mtd.size > 0x1000000) { > -- > 1.7.1 > > > ______________________________________________________ > Linux MTD discussion mailing list > http://lists.infradead.org/mailman/listinfo/linux-mtd/ -- Thanks, Jagan. -------- Jagannadha Sutradharudu Teki, E: jagannadh.teki-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org, P: +91-9676773388 Engineer - System Software Hacker U-boot - SPI Custodian and Zynq APSOC Ln: http://www.linkedin.com/in/jaganteki ------------------------------------------------------------------------------ October Webinars: Code for Performance Free Intel webinars can help you accelerate application performance. Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from the latest Intel processors and coprocessors. See abstracts and register > http://pubads.g.doubleclick.net/gampad/clk?id=60134071&iu=/4140/ostg.clktrk ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCHv3 2/3] drivers: mtd: devices: Add quad read support. @ 2013-10-09 18:15 ` Jagan Teki 0 siblings, 0 replies; 104+ messages in thread From: Jagan Teki @ 2013-10-09 18:15 UTC (permalink / raw) To: Sourav Poddar Cc: Felipe Balbi, broonie, linux-mtd, spi-devel-general, computersforpeace, dwmw2 On Wed, Oct 9, 2013 at 8:54 PM, Sourav Poddar <sourav.poddar@ti.com> wrote: > Some flash also support quad read mode. > Adding support for adding quad mode in m25p80 > for spansion and macronix flash. I am some how not happy with this approach, adding a flags on flash param table for supporting quad operation in specific flash is may be a better idea. But reading SFDP, is a good idea to get the details of flash - quad support is one of them. and we can assign quad read or fast read based on that. Any comments. > > Signed-off-by: Sourav Poddar <sourav.poddar@ti.com> > --- > v2->v3: > Add macronix flash support > drivers/mtd/devices/m25p80.c | 184 ++++++++++++++++++++++++++++++++++++++++-- > 1 files changed, 176 insertions(+), 8 deletions(-) > > diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c > index 26b14f9..dc9bcbf 100644 > --- a/drivers/mtd/devices/m25p80.c > +++ b/drivers/mtd/devices/m25p80.c > @@ -41,6 +41,7 @@ > #define OPCODE_WRSR 0x01 /* Write status register 1 byte */ > #define OPCODE_NORM_READ 0x03 /* Read data bytes (low frequency) */ > #define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */ > +#define OPCODE_QUAD_READ 0x6b /* QUAD READ */ > #define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */ > #define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ > #define OPCODE_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */ > @@ -48,6 +49,7 @@ > #define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */ > #define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */ > #define OPCODE_RDID 0x9f /* Read JEDEC ID */ > +#define OPCODE_RDCR 0x35 /* Read configuration register */ > > /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ > #define OPCODE_NORM_READ_4B 0x13 /* Read data bytes (low frequency) */ > @@ -76,6 +78,10 @@ > #define SR_BP2 0x10 /* Block protect 2 */ > #define SR_SRWD 0x80 /* SR write protect */ > > +/* Configuration Register bits. */ > +#define SPAN_QUAD_CR_EN 0x2 /* Spansion Quad I/O */ > +#define MACR_QUAD_SR_EN 0x40 /* Macronix Quad I/O */ > + > /* Define max times to check status register before we give up. */ > #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ > #define MAX_CMD_SIZE 5 > @@ -95,6 +101,7 @@ struct m25p { > u8 program_opcode; > u8 *command; > bool fast_read; > + bool quad_read; > }; > > static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) > @@ -163,6 +170,25 @@ static inline int write_disable(struct m25p *flash) > return spi_write_then_read(flash->spi, &code, 1, NULL, 0); > } > > +/* Read the configuration register, returning its value in the location > + * Return the configuration register value. > + * Returns negative if error occurred. > +*/ > +static int read_cr(struct m25p *flash) > +{ > + u8 code = OPCODE_RDCR; > + int ret; > + u8 val; > + > + ret = spi_write_then_read(flash->spi, &code, 1, &val, 1); > + if (ret < 0) { > + dev_err(&flash->spi->dev, "error %d reading CR\n", ret); > + return ret; > + } > + > + return val; > +} > + > /* > * Enable/disable 4-byte addressing mode. > */ > @@ -336,6 +362,122 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) > return 0; > } > > +/* Write status register and configuration register with 2 bytes > +* The first byte will be written to the status register, while the second byte > +* will be written to the configuration register. > +* Returns negative if error occurred. > +*/ > +static int write_sr_cr(struct m25p *flash, u16 val) > +{ > + flash->command[0] = OPCODE_WRSR; > + flash->command[1] = val & 0xff; > + flash->command[2] = (val >> 8); > + > + return spi_write(flash->spi, flash->command, 3); > +} > + > +static int macronix_quad_enable(struct m25p *flash) > +{ > + int ret, val; > + u8 cmd[2]; > + cmd[0] = OPCODE_WRSR; > + > + val = read_sr(flash); > + cmd[1] = val | MACR_QUAD_SR_EN; > + write_enable(flash); > + > + spi_write(flash->spi, &cmd, 2); > + > + if (wait_till_ready(flash)) > + return 1; > + > + ret = read_sr(flash); > + if (!(ret > 0 && (ret & MACR_QUAD_SR_EN))) { > + dev_err(&flash->spi->dev, > + "Macronix Quad bit not set"); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static int spansion_quad_enable(struct m25p *flash) > +{ > + int ret; > + int quad_en = SPAN_QUAD_CR_EN << 8; > + > + write_enable(flash); > + > + ret = write_sr_cr(flash, quad_en); > + if (ret < 0) { > + dev_err(&flash->spi->dev, > + "error while writing configuration register"); > + return -EINVAL; > + } > + > + /* read back and check it */ > + ret = read_cr(flash); > + if (!(ret > 0 && (ret & SPAN_QUAD_CR_EN))) { > + dev_err(&flash->spi->dev, > + "Spansion Quad bit not set"); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static int m25p80_quad_read(struct mtd_info *mtd, loff_t from, size_t len, > + size_t *retlen, u_char *buf) > +{ > + struct m25p *flash = mtd_to_m25p(mtd); > + struct spi_transfer t[2]; > + struct spi_message m; > + uint8_t opcode; > + > + pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev), > + __func__, (u32)from, len); > + > + spi_message_init(&m); > + memset(t, 0, (sizeof(t))); > + > + t[0].tx_buf = flash->command; > + t[0].len = m25p_cmdsz(flash) + (flash->quad_read ? 1 : 0); > + spi_message_add_tail(&t[0], &m); > + > + t[1].rx_buf = buf; > + t[1].len = len; > + t[1].rx_nbits = SPI_NBITS_QUAD; > + spi_message_add_tail(&t[1], &m); > + > + mutex_lock(&flash->lock); > + > + /* Wait till previous write/erase is done. */ > + if (wait_till_ready(flash)) { > + /* REVISIT status return?? */ > + mutex_unlock(&flash->lock); > + return 1; > + } > + > + /* FIXME switch to OPCODE_QUAD_READ. It's required for higher > + * clocks; and at this writing, every chip this driver handles > + * supports that opcode. > + */ > + > + /* Set up the write data buffer. */ > + opcode = flash->read_opcode; > + flash->command[0] = opcode; > + m25p_addr2cmd(flash, from, flash->command); > + > + spi_sync(flash->spi, &m); > + > + *retlen = m.actual_length - m25p_cmdsz(flash) - > + (flash->quad_read ? 1 : 0); > + > + mutex_unlock(&flash->lock); > + > + return 0; > +} > + > /* > * Read an address range from the flash chip. The address range > * may be any size provided it is within the physical boundaries. > @@ -928,6 +1070,7 @@ static int m25p_probe(struct spi_device *spi) > unsigned i; > struct mtd_part_parser_data ppdata; > struct device_node __maybe_unused *np = spi->dev.of_node; > + int ret; > > #ifdef CONFIG_MTD_OF_PARTS > if (!of_device_is_available(np)) > @@ -979,15 +1122,9 @@ static int m25p_probe(struct spi_device *spi) > } > } > > - flash = kzalloc(sizeof *flash, GFP_KERNEL); > + flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL); > if (!flash) > return -ENOMEM; > - flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : 0), > - GFP_KERNEL); > - if (!flash->command) { > - kfree(flash); > - return -ENOMEM; > - } > > flash->spi = spi; > mutex_init(&flash->lock); > @@ -1015,7 +1152,6 @@ static int m25p_probe(struct spi_device *spi) > flash->mtd.flags = MTD_CAP_NORFLASH; > flash->mtd.size = info->sector_size * info->n_sectors; > flash->mtd._erase = m25p80_erase; > - flash->mtd._read = m25p80_read; > > /* flash protection support for STmicro chips */ > if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ST) { > @@ -1067,6 +1203,38 @@ static int m25p_probe(struct spi_device *spi) > > flash->program_opcode = OPCODE_PP; > > + flash->quad_read = false; > + if (spi->mode && SPI_RX_QUAD) > + flash->quad_read = true; > + > + flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : > + (flash->quad_read ? 1 : 0)), GFP_KERNEL); > + if (!flash->command) { > + kfree(flash); > + return -ENOMEM; > + } > + > + if (flash->quad_read) { > + if (of_property_read_bool(np, "macronix,quad_enable")) { > + ret = macronix_quad_enable(flash); > + if (ret) { > + dev_err(&spi->dev, > + "error enabling quad"); > + return -EINVAL; > + } > + } else if (of_property_read_bool(np, "spansion,quad_enable")) { > + ret = spansion_quad_enable(flash); > + if (ret) { > + dev_err(&spi->dev, > + "error enabling quad"); > + return -EINVAL; > + } > + } else > + dev_dbg(&spi->dev, "quad enable not supported"); > + flash->mtd._read = m25p80_quad_read; > + } else > + flash->mtd._read = m25p80_read; > + > if (info->addr_width) > flash->addr_width = info->addr_width; > else if (flash->mtd.size > 0x1000000) { > -- > 1.7.1 > > > ______________________________________________________ > Linux MTD discussion mailing list > http://lists.infradead.org/mailman/listinfo/linux-mtd/ -- Thanks, Jagan. -------- Jagannadha Sutradharudu Teki, E: jagannadh.teki@gmail.com, P: +91-9676773388 Engineer - System Software Hacker U-boot - SPI Custodian and Zynq APSOC Ln: http://www.linkedin.com/in/jaganteki ^ permalink raw reply [flat|nested] 104+ messages in thread
[parent not found: <CAD6G_RShZMkSpVzvXWEE0+sDX=pcnf7ndChndgDG5_T4EVL2vQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* RE: [PATCHv3 2/3] drivers: mtd: devices: Add quad read support. 2013-10-09 18:15 ` Jagan Teki @ 2013-10-11 7:10 ` Gupta, Pekon -1 siblings, 0 replies; 104+ messages in thread From: Gupta, Pekon @ 2013-10-11 7:10 UTC (permalink / raw) To: Jagan Teki Cc: Balbi, Felipe, broonie-DgEjT+Ai2ygdnm+yROfE0A, linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Poddar, Sourav, computersforpeace-Re5JQEeQqe8AvxtiuMwx3w, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ Hi, > From: Jagan Teki > > Sourav Poddar <sourav.poddar-l0cyMroinI0@public.gmane.org> > > Some flash also support quad read mode. > > Adding support for adding quad mode in m25p80 > > for spansion and macronix flash. > > I am some how not happy with this approach, adding a flags on flash > param table for supporting > quad operation in specific flash is may be a better idea. > > But reading SFDP, is a good idea to get the details of flash - quad > support is one of them. > and we can assign quad read or fast read based on that. > > Any comments. > Currently SFDP is mostly supported only on Micron devices, that too the newer ones. So we don't know whether SFDP would be accepted by other major SPI NOR manufactures like: Spansion, Nymonix, Micronix, Toshiba, Samsung.. Thus, it might end-up like CFI (common flash interface) where some vendors support it while others did not. So unless there are more devices on SFDP from different vendors, I would prefer defer its implementation in generic driver. with regards, pekon ------------------------------------------------------------------------------ October Webinars: Code for Performance Free Intel webinars can help you accelerate application performance. Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from the latest Intel processors and coprocessors. See abstracts and register > http://pubads.g.doubleclick.net/gampad/clk?id=60134071&iu=/4140/ostg.clktrk ^ permalink raw reply [flat|nested] 104+ messages in thread
* RE: [PATCHv3 2/3] drivers: mtd: devices: Add quad read support. @ 2013-10-11 7:10 ` Gupta, Pekon 0 siblings, 0 replies; 104+ messages in thread From: Gupta, Pekon @ 2013-10-11 7:10 UTC (permalink / raw) To: Jagan Teki Cc: Balbi, Felipe, broonie, linux-mtd, spi-devel-general, Poddar, Sourav, computersforpeace, dwmw2 Hi, > From: Jagan Teki > > Sourav Poddar <sourav.poddar@ti.com> > > Some flash also support quad read mode. > > Adding support for adding quad mode in m25p80 > > for spansion and macronix flash. > > I am some how not happy with this approach, adding a flags on flash > param table for supporting > quad operation in specific flash is may be a better idea. > > But reading SFDP, is a good idea to get the details of flash - quad > support is one of them. > and we can assign quad read or fast read based on that. > > Any comments. > Currently SFDP is mostly supported only on Micron devices, that too the newer ones. So we don't know whether SFDP would be accepted by other major SPI NOR manufactures like: Spansion, Nymonix, Micronix, Toshiba, Samsung.. Thus, it might end-up like CFI (common flash interface) where some vendors support it while others did not. So unless there are more devices on SFDP from different vendors, I would prefer defer its implementation in generic driver. with regards, pekon ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCHv3 2/3] drivers: mtd: devices: Add quad read support. 2013-10-09 15:24 ` Sourav Poddar (?) (?) @ 2013-10-24 1:06 ` Brian Norris 2013-10-24 5:44 ` Sourav Poddar -1 siblings, 1 reply; 104+ messages in thread From: Brian Norris @ 2013-10-24 1:06 UTC (permalink / raw) To: Sourav Poddar Cc: Marek Vasut, Jagan Teki, balbi, Huang Shijie, broonie, linux-mtd, spi-devel-general, dwmw2 + others On Wed, Oct 09, 2013 at 08:54:43PM +0530, Sourav Poddar wrote: > Some flash also support quad read mode. > Adding support for adding quad mode in m25p80 > for spansion and macronix flash. > > Signed-off-by: Sourav Poddar <sourav.poddar@ti.com> > --- > v2->v3: > Add macronix flash support > drivers/mtd/devices/m25p80.c | 184 ++++++++++++++++++++++++++++++++++++++++-- > 1 files changed, 176 insertions(+), 8 deletions(-) > > diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c > index 26b14f9..dc9bcbf 100644 > --- a/drivers/mtd/devices/m25p80.c > +++ b/drivers/mtd/devices/m25p80.c > @@ -41,6 +41,7 @@ > #define OPCODE_WRSR 0x01 /* Write status register 1 byte */ > #define OPCODE_NORM_READ 0x03 /* Read data bytes (low frequency) */ > #define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */ > +#define OPCODE_QUAD_READ 0x6b /* QUAD READ */ > #define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */ > #define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ > #define OPCODE_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */ > @@ -48,6 +49,7 @@ > #define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */ > #define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */ > #define OPCODE_RDID 0x9f /* Read JEDEC ID */ > +#define OPCODE_RDCR 0x35 /* Read configuration register */ > > /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ > #define OPCODE_NORM_READ_4B 0x13 /* Read data bytes (low frequency) */ > @@ -76,6 +78,10 @@ > #define SR_BP2 0x10 /* Block protect 2 */ > #define SR_SRWD 0x80 /* SR write protect */ > > +/* Configuration Register bits. */ > +#define SPAN_QUAD_CR_EN 0x2 /* Spansion Quad I/O */ > +#define MACR_QUAD_SR_EN 0x40 /* Macronix Quad I/O */ Perhaps CR_ can be the prefix, like the status register SR_ macros? So: CR_QUAD_EN_SPAN CR_QUAD_EN_MACR > + > /* Define max times to check status register before we give up. */ > #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ > #define MAX_CMD_SIZE 5 > @@ -95,6 +101,7 @@ struct m25p { > u8 program_opcode; > u8 *command; > bool fast_read; > + bool quad_read; > }; > > static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) > @@ -163,6 +170,25 @@ static inline int write_disable(struct m25p *flash) > return spi_write_then_read(flash->spi, &code, 1, NULL, 0); > } > > +/* Read the configuration register, returning its value in the location > + * Return the configuration register value. > + * Returns negative if error occurred. > +*/ > +static int read_cr(struct m25p *flash) > +{ > + u8 code = OPCODE_RDCR; > + int ret; > + u8 val; > + > + ret = spi_write_then_read(flash->spi, &code, 1, &val, 1); > + if (ret < 0) { > + dev_err(&flash->spi->dev, "error %d reading CR\n", ret); > + return ret; > + } > + > + return val; > +} > + > /* > * Enable/disable 4-byte addressing mode. > */ > @@ -336,6 +362,122 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) > return 0; > } > > +/* Write status register and configuration register with 2 bytes > +* The first byte will be written to the status register, while the second byte > +* will be written to the configuration register. > +* Returns negative if error occurred. > +*/ Not quite the correct multi-line comment style. /* * It should be something like this. Note the asterisk alignment. You * also could wrap the right edge neatly to nearly 80 characters. */ > +static int write_sr_cr(struct m25p *flash, u16 val) > +{ > + flash->command[0] = OPCODE_WRSR; > + flash->command[1] = val & 0xff; > + flash->command[2] = (val >> 8); > + > + return spi_write(flash->spi, flash->command, 3); > +} > + > +static int macronix_quad_enable(struct m25p *flash) > +{ > + int ret, val; > + u8 cmd[2]; > + cmd[0] = OPCODE_WRSR; > + > + val = read_sr(flash); > + cmd[1] = val | MACR_QUAD_SR_EN; > + write_enable(flash); > + > + spi_write(flash->spi, &cmd, 2); > + > + if (wait_till_ready(flash)) > + return 1; > + > + ret = read_sr(flash); > + if (!(ret > 0 && (ret & MACR_QUAD_SR_EN))) { > + dev_err(&flash->spi->dev, > + "Macronix Quad bit not set"); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static int spansion_quad_enable(struct m25p *flash) > +{ > + int ret; > + int quad_en = SPAN_QUAD_CR_EN << 8; > + > + write_enable(flash); > + > + ret = write_sr_cr(flash, quad_en); > + if (ret < 0) { > + dev_err(&flash->spi->dev, > + "error while writing configuration register"); > + return -EINVAL; > + } > + > + /* read back and check it */ > + ret = read_cr(flash); > + if (!(ret > 0 && (ret & SPAN_QUAD_CR_EN))) { > + dev_err(&flash->spi->dev, > + "Spansion Quad bit not set"); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static int m25p80_quad_read(struct mtd_info *mtd, loff_t from, size_t len, > + size_t *retlen, u_char *buf) > +{ This function only has 2 meaningful lines difference from m25p80_read(), no? I'd consider combining them. You only need a simple bool/flag to tell whether we're in quad mode + you can re-use the 'read_opcode' field of struct m25p. > + struct m25p *flash = mtd_to_m25p(mtd); > + struct spi_transfer t[2]; > + struct spi_message m; > + uint8_t opcode; > + > + pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev), > + __func__, (u32)from, len); > + > + spi_message_init(&m); > + memset(t, 0, (sizeof(t))); > + > + t[0].tx_buf = flash->command; > + t[0].len = m25p_cmdsz(flash) + (flash->quad_read ? 1 : 0); This is the first of 2 lines that are different from m25p80_read(). It can easily be combined with the existing read implementation. > + spi_message_add_tail(&t[0], &m); > + > + t[1].rx_buf = buf; > + t[1].len = len; > + t[1].rx_nbits = SPI_NBITS_QUAD; This is the second of 2 different lines. You can change m25p80_read() to have something like this: t[1].rx_nbits = flash->quad_read ? SPI_NBITS_QUAD : 1; > + spi_message_add_tail(&t[1], &m); > + > + mutex_lock(&flash->lock); > + > + /* Wait till previous write/erase is done. */ > + if (wait_till_ready(flash)) { > + /* REVISIT status return?? */ > + mutex_unlock(&flash->lock); > + return 1; > + } > + > + /* FIXME switch to OPCODE_QUAD_READ. It's required for higher > + * clocks; and at this writing, every chip this driver handles > + * supports that opcode. > + */ What? It seems you blindly copied/edited the already-out-of-date comment from m25p80_read(). > + > + /* Set up the write data buffer. */ > + opcode = flash->read_opcode; > + flash->command[0] = opcode; > + m25p_addr2cmd(flash, from, flash->command); > + > + spi_sync(flash->spi, &m); > + > + *retlen = m.actual_length - m25p_cmdsz(flash) - > + (flash->quad_read ? 1 : 0); > + > + mutex_unlock(&flash->lock); > + > + return 0; > +} > + > /* > * Read an address range from the flash chip. The address range > * may be any size provided it is within the physical boundaries. > @@ -928,6 +1070,7 @@ static int m25p_probe(struct spi_device *spi) > unsigned i; > struct mtd_part_parser_data ppdata; > struct device_node __maybe_unused *np = spi->dev.of_node; > + int ret; > > #ifdef CONFIG_MTD_OF_PARTS > if (!of_device_is_available(np)) > @@ -979,15 +1122,9 @@ static int m25p_probe(struct spi_device *spi) > } > } > > - flash = kzalloc(sizeof *flash, GFP_KERNEL); > + flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL); > if (!flash) > return -ENOMEM; > - flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : 0), > - GFP_KERNEL); > - if (!flash->command) { > - kfree(flash); > - return -ENOMEM; > - } You're combining a bug fix with your feature addition. The size may be off-by-one (which is insignificant in this case, I think, but still...) so the kmalloc() does needs to move down, but it should be done before this feature patch. (Sorry, I've had a patch queued up but didn't send it out for a while. I think somebody sorta tried to fix this a while ago but didn't send a proper patch.) > > flash->spi = spi; > mutex_init(&flash->lock); > @@ -1015,7 +1152,6 @@ static int m25p_probe(struct spi_device *spi) > flash->mtd.flags = MTD_CAP_NORFLASH; > flash->mtd.size = info->sector_size * info->n_sectors; > flash->mtd._erase = m25p80_erase; > - flash->mtd._read = m25p80_read; > > /* flash protection support for STmicro chips */ > if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ST) { > @@ -1067,6 +1203,38 @@ static int m25p_probe(struct spi_device *spi) > > flash->program_opcode = OPCODE_PP; > > + flash->quad_read = false; > + if (spi->mode && SPI_RX_QUAD) You're looking for bitwise '&', not logical '&&'. > + flash->quad_read = true; But you can just replace the previous 3 lines with: flash->quad_read = spi->mode & SPI_RX_QUAD; or this, if you really want be careful about the bit position: flash->quad_read = !!(spi->mode & SPI_RX_QUAD); > + > + flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : > + (flash->quad_read ? 1 : 0)), GFP_KERNEL); That's an ugly conditional. Maybe we just want to increase MAX_CMD_SIZE and be done with it? Saving an extra byte is not helping anyone (and I think pretty much everyone always has fast_read==true anyway). > + if (!flash->command) { > + kfree(flash); > + return -ENOMEM; > + } > + > + if (flash->quad_read) { > + if (of_property_read_bool(np, "macronix,quad_enable")) { As Jagan mentioned, I think we want this to be discoverable from within m25p80.c. I don't think we should require it to be in DT. (We could still support a DT binding just in case, but I think the majority use-case should be easier to have a flag in the ID table; and if we ever support SFDP, that could complement the flag approach nicely.) Also, be sure to add a documentation patch for the DT binding if you really need the binding. > + ret = macronix_quad_enable(flash); > + if (ret) { > + dev_err(&spi->dev, > + "error enabling quad"); > + return -EINVAL; > + } > + } else if (of_property_read_bool(np, "spansion,quad_enable")) { Ditto on the binding. I don't think it's necessary, and I would prefer we go with the ID table flag or SFDP. But if you need it, document it. > + ret = spansion_quad_enable(flash); > + if (ret) { > + dev_err(&spi->dev, > + "error enabling quad"); > + return -EINVAL; > + } > + } else > + dev_dbg(&spi->dev, "quad enable not supported"); ...and if quad enable is not supported, we just blaze on to use quad mode anyway?? No, I think this needs to be rewritten so that we only set flash->quad_read = true when all of the following are true: (1) the SPI controller supports quad I/O (2) the flash supports it (i.e., after we see that the device supports it in the ID table/DT/SFDP) and (3) we have successfully run one of the quad-enable commands Then if you follow my advice on unifying m25p80_quad_read() and m25p80_read(), you'll never have a mismatch between flash->quad_read, the state of the flash, and the assigned flash->mtd._read callback function. We will trivially fall back to single-I/O read if anything fails, too. > + flash->mtd._read = m25p80_quad_read; > + } else > + flash->mtd._read = m25p80_read; This mtd._read callback assignment should not need to be touched. > + > if (info->addr_width) > flash->addr_width = info->addr_width; > else if (flash->mtd.size > 0x1000000) { Brian ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCHv3 2/3] drivers: mtd: devices: Add quad read support. 2013-10-24 1:06 ` Brian Norris @ 2013-10-24 5:44 ` Sourav Poddar 2013-10-24 7:34 ` Brian Norris 0 siblings, 1 reply; 104+ messages in thread From: Sourav Poddar @ 2013-10-24 5:44 UTC (permalink / raw) To: Brian Norris Cc: Marek Vasut, Jagan Teki, balbi, Huang Shijie, broonie, linux-mtd, spi-devel-general, dwmw2 Hi Brian, Thanks for the review, my reply inlined. On Thursday 24 October 2013 06:36 AM, Brian Norris wrote: > + others > > On Wed, Oct 09, 2013 at 08:54:43PM +0530, Sourav Poddar wrote: >> Some flash also support quad read mode. >> Adding support for adding quad mode in m25p80 >> for spansion and macronix flash. >> >> Signed-off-by: Sourav Poddar<sourav.poddar@ti.com> >> --- >> v2->v3: >> Add macronix flash support >> drivers/mtd/devices/m25p80.c | 184 ++++++++++++++++++++++++++++++++++++++++-- >> 1 files changed, 176 insertions(+), 8 deletions(-) >> >> diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c >> index 26b14f9..dc9bcbf 100644 >> --- a/drivers/mtd/devices/m25p80.c >> +++ b/drivers/mtd/devices/m25p80.c >> @@ -41,6 +41,7 @@ >> #define OPCODE_WRSR 0x01 /* Write status register 1 byte */ >> #define OPCODE_NORM_READ 0x03 /* Read data bytes (low frequency) */ >> #define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */ >> +#define OPCODE_QUAD_READ 0x6b /* QUAD READ */ >> #define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */ >> #define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ >> #define OPCODE_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */ >> @@ -48,6 +49,7 @@ >> #define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */ >> #define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */ >> #define OPCODE_RDID 0x9f /* Read JEDEC ID */ >> +#define OPCODE_RDCR 0x35 /* Read configuration register */ >> >> /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ >> #define OPCODE_NORM_READ_4B 0x13 /* Read data bytes (low frequency) */ >> @@ -76,6 +78,10 @@ >> #define SR_BP2 0x10 /* Block protect 2 */ >> #define SR_SRWD 0x80 /* SR write protect */ >> >> +/* Configuration Register bits. */ >> +#define SPAN_QUAD_CR_EN 0x2 /* Spansion Quad I/O */ >> +#define MACR_QUAD_SR_EN 0x40 /* Macronix Quad I/O */ > Perhaps CR_ can be the prefix, like the status register SR_ macros? So: > > CR_QUAD_EN_SPAN > CR_QUAD_EN_MACR Yes, CR/SR can come as a prefix for Spansion. But, to enable quad mode in macronix, we need to write to status register. So, things should be like.. CR_QUAD_EN_SPAN SR_QUAD_EN_MACR >> + >> /* Define max times to check status register before we give up. */ >> #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ >> #define MAX_CMD_SIZE 5 >> @@ -95,6 +101,7 @@ struct m25p { >> u8 program_opcode; >> u8 *command; >> bool fast_read; >> + bool quad_read; >> }; >> >> static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) >> @@ -163,6 +170,25 @@ static inline int write_disable(struct m25p *flash) >> return spi_write_then_read(flash->spi,&code, 1, NULL, 0); >> } >> >> +/* Read the configuration register, returning its value in the location >> + * Return the configuration register value. >> + * Returns negative if error occurred. >> +*/ >> +static int read_cr(struct m25p *flash) >> +{ >> + u8 code = OPCODE_RDCR; >> + int ret; >> + u8 val; >> + >> + ret = spi_write_then_read(flash->spi,&code, 1,&val, 1); >> + if (ret< 0) { >> + dev_err(&flash->spi->dev, "error %d reading CR\n", ret); >> + return ret; >> + } >> + >> + return val; >> +} >> + >> /* >> * Enable/disable 4-byte addressing mode. >> */ >> @@ -336,6 +362,122 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) >> return 0; >> } >> >> +/* Write status register and configuration register with 2 bytes >> +* The first byte will be written to the status register, while the second byte >> +* will be written to the configuration register. >> +* Returns negative if error occurred. >> +*/ > Not quite the correct multi-line comment style. > > /* > * It should be something like this. Note the asterisk alignment. You > * also could wrap the right edge neatly to nearly 80 characters. > */ > Ok. I will fix this in next version. >> +static int write_sr_cr(struct m25p *flash, u16 val) >> +{ >> + flash->command[0] = OPCODE_WRSR; >> + flash->command[1] = val& 0xff; >> + flash->command[2] = (val>> 8); >> + >> + return spi_write(flash->spi, flash->command, 3); >> +} >> + >> +static int macronix_quad_enable(struct m25p *flash) >> +{ >> + int ret, val; >> + u8 cmd[2]; >> + cmd[0] = OPCODE_WRSR; >> + >> + val = read_sr(flash); >> + cmd[1] = val | MACR_QUAD_SR_EN; >> + write_enable(flash); >> + >> + spi_write(flash->spi,&cmd, 2); >> + >> + if (wait_till_ready(flash)) >> + return 1; >> + >> + ret = read_sr(flash); >> + if (!(ret> 0&& (ret& MACR_QUAD_SR_EN))) { >> + dev_err(&flash->spi->dev, >> + "Macronix Quad bit not set"); >> + return -EINVAL; >> + } >> + >> + return 0; >> +} >> + >> +static int spansion_quad_enable(struct m25p *flash) >> +{ >> + int ret; >> + int quad_en = SPAN_QUAD_CR_EN<< 8; >> + >> + write_enable(flash); >> + >> + ret = write_sr_cr(flash, quad_en); >> + if (ret< 0) { >> + dev_err(&flash->spi->dev, >> + "error while writing configuration register"); >> + return -EINVAL; >> + } >> + >> + /* read back and check it */ >> + ret = read_cr(flash); >> + if (!(ret> 0&& (ret& SPAN_QUAD_CR_EN))) { >> + dev_err(&flash->spi->dev, >> + "Spansion Quad bit not set"); >> + return -EINVAL; >> + } >> + >> + return 0; >> +} >> + >> +static int m25p80_quad_read(struct mtd_info *mtd, loff_t from, size_t len, >> + size_t *retlen, u_char *buf) >> +{ > This function only has 2 meaningful lines difference from m25p80_read(), > no? I'd consider combining them. You only need a simple bool/flag to > tell whether we're in quad mode + you can re-use the 'read_opcode' field > of struct m25p. > Yes, my only motto of keeping a seperate API was that quad supports different sort of commands, with different dummy cycle requirements. So, I thought it might get a bit clumsy to handle, if someone later want to add a particular command along with its dummy cycle requirements. But, yes, you are true, as of now, it can be club into one. >> + struct m25p *flash = mtd_to_m25p(mtd); >> + struct spi_transfer t[2]; >> + struct spi_message m; >> + uint8_t opcode; >> + >> + pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev), >> + __func__, (u32)from, len); >> + >> + spi_message_init(&m); >> + memset(t, 0, (sizeof(t))); >> + >> + t[0].tx_buf = flash->command; >> + t[0].len = m25p_cmdsz(flash) + (flash->quad_read ? 1 : 0); > This is the first of 2 lines that are different from m25p80_read(). It > can easily be combined with the existing read implementation. > >> + spi_message_add_tail(&t[0],&m); >> + >> + t[1].rx_buf = buf; >> + t[1].len = len; >> + t[1].rx_nbits = SPI_NBITS_QUAD; > This is the second of 2 different lines. You can change m25p80_read() to > have something like this: > > t[1].rx_nbits = flash->quad_read ? SPI_NBITS_QUAD : 1; > True, t[0] len can be written as.. t[0].len = m25p_cmdsz(flash) + (flash->quad_read ? 1 : (flash->fast_read ? 1 : 0)); >> + spi_message_add_tail(&t[1],&m); >> + >> + mutex_lock(&flash->lock); >> + >> + /* Wait till previous write/erase is done. */ >> + if (wait_till_ready(flash)) { >> + /* REVISIT status return?? */ >> + mutex_unlock(&flash->lock); >> + return 1; >> + } >> + >> + /* FIXME switch to OPCODE_QUAD_READ. It's required for higher >> + * clocks; and at this writing, every chip this driver handles >> + * supports that opcode. >> + */ > What? It seems you blindly copied/edited the already-out-of-date comment > from m25p80_read(). > Sorry for this, my bad. I will update this in next version. >> + >> + /* Set up the write data buffer. */ >> + opcode = flash->read_opcode; >> + flash->command[0] = opcode; >> + m25p_addr2cmd(flash, from, flash->command); >> + >> + spi_sync(flash->spi,&m); >> + >> + *retlen = m.actual_length - m25p_cmdsz(flash) - >> + (flash->quad_read ? 1 : 0); >> + >> + mutex_unlock(&flash->lock); >> + >> + return 0; >> +} >> + >> /* >> * Read an address range from the flash chip. The address range >> * may be any size provided it is within the physical boundaries. >> @@ -928,6 +1070,7 @@ static int m25p_probe(struct spi_device *spi) >> unsigned i; >> struct mtd_part_parser_data ppdata; >> struct device_node __maybe_unused *np = spi->dev.of_node; >> + int ret; >> >> #ifdef CONFIG_MTD_OF_PARTS >> if (!of_device_is_available(np)) >> @@ -979,15 +1122,9 @@ static int m25p_probe(struct spi_device *spi) >> } >> } >> >> - flash = kzalloc(sizeof *flash, GFP_KERNEL); >> + flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL); >> if (!flash) >> return -ENOMEM; >> - flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : 0), >> - GFP_KERNEL); >> - if (!flash->command) { >> - kfree(flash); >> - return -ENOMEM; >> - } > You're combining a bug fix with your feature addition. The size may be > off-by-one (which is insignificant in this case, I think, but still...) > so the kmalloc() does needs to move down, but it should be done before > this feature patch. (Sorry, I've had a patch queued up but didn't send > it out for a while. I think somebody sorta tried to fix this a while ago > but didn't send a proper patch.) > Yes, true. I can break this patch into two with first patch as the bug fix and second as the feature. Is it ok? >> >> flash->spi = spi; >> mutex_init(&flash->lock); >> @@ -1015,7 +1152,6 @@ static int m25p_probe(struct spi_device *spi) >> flash->mtd.flags = MTD_CAP_NORFLASH; >> flash->mtd.size = info->sector_size * info->n_sectors; >> flash->mtd._erase = m25p80_erase; >> - flash->mtd._read = m25p80_read; >> >> /* flash protection support for STmicro chips */ >> if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ST) { >> @@ -1067,6 +1203,38 @@ static int m25p_probe(struct spi_device *spi) >> >> flash->program_opcode = OPCODE_PP; >> >> + flash->quad_read = false; >> + if (spi->mode&& SPI_RX_QUAD) > You're looking for bitwise '&', not logical'&&'. > >> + flash->quad_read = true; > But you can just replace the previous 3 lines with: > > flash->quad_read = spi->mode& SPI_RX_QUAD; > > or this, if you really want be careful about the bit position: > > flash->quad_read = !!(spi->mode& SPI_RX_QUAD); > True, will fix. >> + >> + flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : >> + (flash->quad_read ? 1 : 0)), GFP_KERNEL); > That's an ugly conditional. Maybe we just want to increase MAX_CMD_SIZE > and be done with it? Saving an extra byte is not helping anyone (and I > think pretty much everyone always has fast_read==true anyway). Yes, this can be done. But, I was not sure about increasing the macro just on coding perspective. If it sounds Ok, I will increase the macro and make the corresponding cleanups. >> + if (!flash->command) { >> + kfree(flash); >> + return -ENOMEM; >> + } >> + >> + if (flash->quad_read) { >> + if (of_property_read_bool(np, "macronix,quad_enable")) { > As Jagan mentioned, I think we want this to be discoverable from within > m25p80.c. I don't think we should require it to be in DT. (We could > still support a DT binding just in case, but I think the majority > use-case should be easier to have a flag in the ID table; and if we ever > support SFDP, that could complement the flag approach nicely.) > > Also, be sure to add a documentation patch for the DT binding if you > really need the binding. > >> + ret = macronix_quad_enable(flash); >> + if (ret) { >> + dev_err(&spi->dev, >> + "error enabling quad"); >> + return -EINVAL; >> + } >> + } else if (of_property_read_bool(np, "spansion,quad_enable")) { > Ditto on the binding. I don't think it's necessary, and I would prefer > we go with the ID table flag or SFDP. But if you need it, document it. > >> + ret = spansion_quad_enable(flash); >> + if (ret) { >> + dev_err(&spi->dev, >> + "error enabling quad"); >> + return -EINVAL; >> + } >> + } else >> + dev_dbg(&spi->dev, "quad enable not supported"); > ...and if quad enable is not supported, we just blaze on to use quad > mode anyway?? No, I think this needs to be rewritten so that we only set > flash->quad_read = true when all of the following are true: > > (1) the SPI controller supports quad I/O > (2) the flash supports it (i.e., after we see that the device supports > it in the ID table/DT/SFDP) and > (3) we have successfully run one of the quad-enable commands I got your idea here and to sum up, my below diff can be done to better clean up the code. diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index f180ffd..6e32f6a 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -851,7 +851,7 @@ static const struct spi_device_id m25p_ids[] = { { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) }, { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, - { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, 0) }, + { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, MX_QUAD_EN) }, /* Micron */ { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, @@ -870,7 +870,7 @@ static const struct spi_device_id m25p_ids[] = { { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, 0) }, { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, 0) }, { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) }, - { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, 0) }, + { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SP_QUAD_EN) }, { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, 0) }, { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, @@ -1094,6 +1094,25 @@ static int m25p_probe(struct spi_device *spi) flash->mtd.size = info->sector_size * info->n_sectors; flash->mtd._erase = m25p80_erase; + if (spi->mode & SPI_RX_QUAD) { + if (info->flags & SP_QUAD_EN) { + ret = spansion_quad_enable(flash); + if (ret) { + dev_err(&spi->dev, "error enabling quad"); + return -EINVAL; + } + flash->quad_read = true; + } else if (info->flags & MX_QUAD_EN) { + ret = spansion_quad_enable(flash); + if (ret) { + dev_err(&spi->dev, "error enabling quad"); + return -EINVAL; + } + flash->quad_read = true; + } else + dev_dbg(&spi->dev, "quad enable not supported"); + } + > Then if you follow my advice on unifying m25p80_quad_read() and > m25p80_read(), you'll never have a mismatch between flash->quad_read, > the state of the flash, and the assigned flash->mtd._read callback > function. We will trivially fall back to single-I/O read if anything > fails, too. > >> + flash->mtd._read = m25p80_quad_read; >> + } else >> + flash->mtd._read = m25p80_read; > This mtd._read callback assignment should not need to be touched. Ok, with your above suggestion on clubbing quad with original read support, this will automatically go. >> + >> if (info->addr_width) >> flash->addr_width = info->addr_width; >> else if (flash->mtd.size> 0x1000000) { > Brian ^ permalink raw reply related [flat|nested] 104+ messages in thread
* Re: [PATCHv3 2/3] drivers: mtd: devices: Add quad read support. 2013-10-24 5:44 ` Sourav Poddar @ 2013-10-24 7:34 ` Brian Norris 2013-10-24 8:44 ` Sourav Poddar 0 siblings, 1 reply; 104+ messages in thread From: Brian Norris @ 2013-10-24 7:34 UTC (permalink / raw) To: Sourav Poddar Cc: Marek Vasut, Jagan Teki, balbi, Huang Shijie, broonie, linux-mtd, spi-devel-general, dwmw2 On Thu, Oct 24, 2013 at 11:14:24AM +0530, Sourav Poddar wrote: > On Thursday 24 October 2013 06:36 AM, Brian Norris wrote: > >On Wed, Oct 09, 2013 at 08:54:43PM +0530, Sourav Poddar wrote: > >>--- a/drivers/mtd/devices/m25p80.c > >>+++ b/drivers/mtd/devices/m25p80.c > >>@@ -76,6 +78,10 @@ > >> #define SR_BP2 0x10 /* Block protect 2 */ > >> #define SR_SRWD 0x80 /* SR write protect */ > >> > >>+/* Configuration Register bits. */ > >>+#define SPAN_QUAD_CR_EN 0x2 /* Spansion Quad I/O */ > >>+#define MACR_QUAD_SR_EN 0x40 /* Macronix Quad I/O */ > >Perhaps CR_ can be the prefix, like the status register SR_ macros? So: > > > > CR_QUAD_EN_SPAN > > CR_QUAD_EN_MACR > Yes, CR/SR can come as a prefix for Spansion. But, to enable quad mode in > macronix, we need to write to status register. So, things should be like.. > CR_QUAD_EN_SPAN > SR_QUAD_EN_MACR Yes, I missed the CR vs. SR. My bad. > >>+ > >> /* Define max times to check status register before we give up. */ > >> #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ > >> #define MAX_CMD_SIZE 5 > >>@@ -95,6 +101,7 @@ struct m25p { > >>@@ -163,6 +170,25 @@ static inline int write_disable(struct m25p *flash) ... > >>+static int m25p80_quad_read(struct mtd_info *mtd, loff_t from, size_t len, > >>+ size_t *retlen, u_char *buf) > >>+{ > >This function only has 2 meaningful lines difference from m25p80_read(), > >no? I'd consider combining them. You only need a simple bool/flag to > >tell whether we're in quad mode + you can re-use the 'read_opcode' field > >of struct m25p. > > > Yes, my only motto of keeping a seperate API was that quad supports > different sort of commands, with different dummy cycle requirements. > So, I thought it might get a bit clumsy to handle, if someone later > want to add a > particular command along with its dummy cycle requirements. > > But, yes, you are true, as of now, it can be club into one. > > >>+ struct m25p *flash = mtd_to_m25p(mtd); > >>+ struct spi_transfer t[2]; > >>+ struct spi_message m; > >>+ uint8_t opcode; > >>+ > >>+ pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev), > >>+ __func__, (u32)from, len); > >>+ > >>+ spi_message_init(&m); > >>+ memset(t, 0, (sizeof(t))); > >>+ > >>+ t[0].tx_buf = flash->command; > >>+ t[0].len = m25p_cmdsz(flash) + (flash->quad_read ? 1 : 0); > >This is the first of 2 lines that are different from m25p80_read(). It > >can easily be combined with the existing read implementation. > > > >>+ spi_message_add_tail(&t[0],&m); > >>+ > >>+ t[1].rx_buf = buf; > >>+ t[1].len = len; > >>+ t[1].rx_nbits = SPI_NBITS_QUAD; > >This is the second of 2 different lines. You can change m25p80_read() to > >have something like this: > > > > t[1].rx_nbits = flash->quad_read ? SPI_NBITS_QUAD : 1; > True, t[0] len can be written as.. > > t[0].len = m25p_cmdsz(flash) + (flash->quad_read ? 1 : > (flash->fast_read ? 1 : 0)); Yikes. I'd go easy with the embedded '?:' operators. If you're going for really fun ways to shorten things, though, you can do: t[0].len = m25p_cmdsz(flash) + !!(flash->quad_read || flash->fast_read); But seriously, I think it may be better to be more verbose to make it clearer. Like: t[0].len = m25p_cmdsz(flash); /* Dummy cycle */ if (flash->quad_read || flash->fast_read) t[0].len++; If you're really looking at making dummy cycles more modular, though, you can add an extra function like this: static inline int m25p80_dummy_cycles_read(struct m25p *flash) { if (flash->quad_read || flash->fast_read) return 1; return 0; } Then it's: t[0].len = m25p_cmdsz(flash) + m25p80_dummy_cycles_read(flash); Then you can convert this to represent the # of bits of dummy cycle if you ever do more exotic commands and implement a proper SPI dummy cycle API. But please, don't just embed a bunch of '?:'. > >>+ spi_message_add_tail(&t[1],&m); > >>+ > >>+ mutex_lock(&flash->lock); > >>+ > >>+ /* Wait till previous write/erase is done. */ > >>+ if (wait_till_ready(flash)) { > >>+ /* REVISIT status return?? */ > >>+ mutex_unlock(&flash->lock); > >>+ return 1; > >>+ } > >>+ > >>+ /* FIXME switch to OPCODE_QUAD_READ. It's required for higher > >>+ * clocks; and at this writing, every chip this driver handles > >>+ * supports that opcode. > >>+ */ > >What? It seems you blindly copied/edited the already-out-of-date comment > >from m25p80_read(). > > > Sorry for this, my bad. I will update this in next version. > >>+ > >>+ /* Set up the write data buffer. */ > >>+ opcode = flash->read_opcode; > >>+ flash->command[0] = opcode; > >>+ m25p_addr2cmd(flash, from, flash->command); > >>+ > >>+ spi_sync(flash->spi,&m); > >>+ > >>+ *retlen = m.actual_length - m25p_cmdsz(flash) - > >>+ (flash->quad_read ? 1 : 0); > >>+ > >>+ mutex_unlock(&flash->lock); > >>+ > >>+ return 0; > >>+} > >>+ > >> /* > >> * Read an address range from the flash chip. The address range > >> * may be any size provided it is within the physical boundaries. > >>@@ -979,15 +1122,9 @@ static int m25p_probe(struct spi_device *spi) > >> } > >> } > >> > >>- flash = kzalloc(sizeof *flash, GFP_KERNEL); > >>+ flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL); > >> if (!flash) > >> return -ENOMEM; > >>- flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : 0), > >>- GFP_KERNEL); > >>- if (!flash->command) { > >>- kfree(flash); > >>- return -ENOMEM; > >>- } > >You're combining a bug fix with your feature addition. The size may be > >off-by-one (which is insignificant in this case, I think, but still...) > >so the kmalloc() does needs to move down, but it should be done before > >this feature patch. (Sorry, I've had a patch queued up but didn't send > >it out for a while. I think somebody sorta tried to fix this a while ago > >but didn't send a proper patch.) > > > Yes, true. I can break this patch into two with first patch as the > bug fix and > second as the feature. Is it ok? I just submitted my cleanups which (among other things) fixes this bug. I believe I CC'd you. Go ahead and review it, and if it works to your liking, please just base your work on top of it. I'll apply some or all of that series if no one objects. > >> > >> flash->spi = spi; > >> mutex_init(&flash->lock); > >>@@ -1067,6 +1203,38 @@ static int m25p_probe(struct spi_device *spi) > >> > >> flash->program_opcode = OPCODE_PP; > >> > >>+ flash->quad_read = false; > >>+ if (spi->mode&& SPI_RX_QUAD) > >You're looking for bitwise '&', not logical'&&'. > > > >>+ flash->quad_read = true; > >But you can just replace the previous 3 lines with: > > > > flash->quad_read = spi->mode& SPI_RX_QUAD; > > > >or this, if you really want be careful about the bit position: > > > > flash->quad_read = !!(spi->mode& SPI_RX_QUAD); > > > True, will fix. > >>+ > >>+ flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : > >>+ (flash->quad_read ? 1 : 0)), GFP_KERNEL); > >That's an ugly conditional. Maybe we just want to increase MAX_CMD_SIZE > >and be done with it? Saving an extra byte is not helping anyone (and I > >think pretty much everyone always has fast_read==true anyway). > Yes, this can be done. But, I was not sure about increasing the macro just > on coding perspective. If it sounds Ok, I will increase the macro and make > the corresponding cleanups. Just take a look at my patch for this issue, please. > >>+ if (of_property_read_bool(np, "macronix,quad_enable")) { ... > >>+ } else if (of_property_read_bool(np, "spansion,quad_enable")) { ... > >>+ } else > >>+ dev_dbg(&spi->dev, "quad enable not supported"); > >...and if quad enable is not supported, we just blaze on to use quad > >mode anyway?? No, I think this needs to be rewritten so that we only set > >flash->quad_read = true when all of the following are true: > > > >(1) the SPI controller supports quad I/O > >(2) the flash supports it (i.e., after we see that the device supports > > it in the ID table/DT/SFDP) and > >(3) we have successfully run one of the quad-enable commands > I got your idea here and to sum up, my below diff can be done to > better clean up the code. Looks a little better. A few comments on it below. > diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c > index f180ffd..6e32f6a 100644 > --- a/drivers/mtd/devices/m25p80.c > +++ b/drivers/mtd/devices/m25p80.c > @@ -851,7 +851,7 @@ static const struct spi_device_id m25p_ids[] = { > { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, > { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) }, > { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, > - { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, 0) }, > + { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, MX_QUAD_EN) }, I don't think we need a separate Macronix and Spansion quad flag; I think we can get by with just a M25P_QUAD flag (or some other name like that). We can differentiate MXIC and Spansion via just the manufacturer by it's ID, right? (See the similarity to set_4byte().) Do all parts that support quad read also support all the other quad opcodes (like quad program)? > > /* Micron */ > { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, > @@ -870,7 +870,7 @@ static const struct spi_device_id m25p_ids[] = { > { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, 0) }, > { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, 0) }, > { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) }, > - { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, 0) }, > + { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, > SP_QUAD_EN) }, > { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, 0) }, > { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, > { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, > @@ -1094,6 +1094,25 @@ static int m25p_probe(struct spi_device *spi) > flash->mtd.size = info->sector_size * info->n_sectors; > flash->mtd._erase = m25p80_erase; > > + if (spi->mode & SPI_RX_QUAD) { > + if (info->flags & SP_QUAD_EN) { > + ret = spansion_quad_enable(flash); > + if (ret) { > + dev_err(&spi->dev, "error enabling quad"); > + return -EINVAL; > + } > + flash->quad_read = true; > + } else if (info->flags & MX_QUAD_EN) { > + ret = spansion_quad_enable(flash); > + if (ret) { > + dev_err(&spi->dev, "error enabling quad"); > + return -EINVAL; > + } > + flash->quad_read = true; > + } else > + dev_dbg(&spi->dev, "quad enable not supported"); > + } > + I think we'll want a separate function set_quad_mode(), so we can just do: if (spi->mode & SPI_RX_QUAD && info->flags & M25P_QUAD) { ret = set_quad_mode(flash, info->jedec_id, 1); if (ret) { dev_err(...); return ret; } flash->quad_read = true; } Then the set_quad_mode() function can do things very similarly to set_4byte(), based on the manufacturer JEDEC ID. Do you plan on supporting Quad Page Program? How about the dedicated 4-byte addressing variants of these Quad commands? Are there any other important side effects when enabling quad mode? I'm reading some things about changes in WP# and HOLD# behavior, but I'm not quite sure right now if that has ramifications on the rest of the driver. Brian ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCHv3 2/3] drivers: mtd: devices: Add quad read support. 2013-10-24 7:34 ` Brian Norris @ 2013-10-24 8:44 ` Sourav Poddar 2013-10-24 17:07 ` Brian Norris 0 siblings, 1 reply; 104+ messages in thread From: Sourav Poddar @ 2013-10-24 8:44 UTC (permalink / raw) To: Brian Norris Cc: Marek Vasut, Jagan Teki, balbi, Huang Shijie, broonie, linux-mtd, spi-devel-general, dwmw2 Hi Brian, On Thursday 24 October 2013 01:04 PM, Brian Norris wrote: > On Thu, Oct 24, 2013 at 11:14:24AM +0530, Sourav Poddar wrote: >> On Thursday 24 October 2013 06:36 AM, Brian Norris wrote: >>> On Wed, Oct 09, 2013 at 08:54:43PM +0530, Sourav Poddar wrote: >>>> --- a/drivers/mtd/devices/m25p80.c >>>> +++ b/drivers/mtd/devices/m25p80.c >>>> @@ -76,6 +78,10 @@ >>>> #define SR_BP2 0x10 /* Block protect 2 */ >>>> #define SR_SRWD 0x80 /* SR write protect */ >>>> >>>> +/* Configuration Register bits. */ >>>> +#define SPAN_QUAD_CR_EN 0x2 /* Spansion Quad I/O */ >>>> +#define MACR_QUAD_SR_EN 0x40 /* Macronix Quad I/O */ >>> Perhaps CR_ can be the prefix, like the status register SR_ macros? So: >>> >>> CR_QUAD_EN_SPAN >>> CR_QUAD_EN_MACR >> Yes, CR/SR can come as a prefix for Spansion. But, to enable quad mode in >> macronix, we need to write to status register. So, things should be like.. >> CR_QUAD_EN_SPAN >> SR_QUAD_EN_MACR > Yes, I missed the CR vs. SR. My bad. > >>>> + >>>> /* Define max times to check status register before we give up. */ >>>> #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ >>>> #define MAX_CMD_SIZE 5 >>>> @@ -95,6 +101,7 @@ struct m25p { >>>> @@ -163,6 +170,25 @@ static inline int write_disable(struct m25p *flash) > ... > >>>> +static int m25p80_quad_read(struct mtd_info *mtd, loff_t from, size_t len, >>>> + size_t *retlen, u_char *buf) >>>> +{ >>> This function only has 2 meaningful lines difference from m25p80_read(), >>> no? I'd consider combining them. You only need a simple bool/flag to >>> tell whether we're in quad mode + you can re-use the 'read_opcode' field >>> of struct m25p. >>> >> Yes, my only motto of keeping a seperate API was that quad supports >> different sort of commands, with different dummy cycle requirements. >> So, I thought it might get a bit clumsy to handle, if someone later >> want to add a >> particular command along with its dummy cycle requirements. >> >> But, yes, you are true, as of now, it can be club into one. >> >>>> + struct m25p *flash = mtd_to_m25p(mtd); >>>> + struct spi_transfer t[2]; >>>> + struct spi_message m; >>>> + uint8_t opcode; >>>> + >>>> + pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev), >>>> + __func__, (u32)from, len); >>>> + >>>> + spi_message_init(&m); >>>> + memset(t, 0, (sizeof(t))); >>>> + >>>> + t[0].tx_buf = flash->command; >>>> + t[0].len = m25p_cmdsz(flash) + (flash->quad_read ? 1 : 0); >>> This is the first of 2 lines that are different from m25p80_read(). It >>> can easily be combined with the existing read implementation. >>> >>>> + spi_message_add_tail(&t[0],&m); >>>> + >>>> + t[1].rx_buf = buf; >>>> + t[1].len = len; >>>> + t[1].rx_nbits = SPI_NBITS_QUAD; >>> This is the second of 2 different lines. You can change m25p80_read() to >>> have something like this: >>> >>> t[1].rx_nbits = flash->quad_read ? SPI_NBITS_QUAD : 1; >> True, t[0] len can be written as.. >> >> t[0].len = m25p_cmdsz(flash) + (flash->quad_read ? 1 : >> (flash->fast_read ? 1 : 0)); > Yikes. I'd go easy with the embedded '?:' operators. > > If you're going for really fun ways to shorten things, though, you can > do: > > t[0].len = m25p_cmdsz(flash) + !!(flash->quad_read || flash->fast_read); > > But seriously, I think it may be better to be more verbose to make it > clearer. Like: > > t[0].len = m25p_cmdsz(flash); > /* Dummy cycle */ > if (flash->quad_read || flash->fast_read) > t[0].len++; > > If you're really looking at making dummy cycles more modular, though, > you can add an extra function like this: > > static inline int m25p80_dummy_cycles_read(struct m25p *flash) > { > if (flash->quad_read || flash->fast_read) > return 1; > return 0; > } > > Then it's: > > t[0].len = m25p_cmdsz(flash) + m25p80_dummy_cycles_read(flash); > > Then you can convert this to represent the # of bits of dummy cycle if > you ever do more exotic commands and implement a proper SPI dummy cycle > API. > > But please, don't just embed a bunch of '?:'. > The above suggestion looks quite clean and verbose. I will go this way in my next version. >>>> + spi_message_add_tail(&t[1],&m); >>>> + >>>> + mutex_lock(&flash->lock); >>>> + >>>> + /* Wait till previous write/erase is done. */ >>>> + if (wait_till_ready(flash)) { >>>> + /* REVISIT status return?? */ >>>> + mutex_unlock(&flash->lock); >>>> + return 1; >>>> + } >>>> + >>>> + /* FIXME switch to OPCODE_QUAD_READ. It's required for higher >>>> + * clocks; and at this writing, every chip this driver handles >>>> + * supports that opcode. >>>> + */ >>> What? It seems you blindly copied/edited the already-out-of-date comment >> >from m25p80_read(). >> Sorry for this, my bad. I will update this in next version. >>>> + >>>> + /* Set up the write data buffer. */ >>>> + opcode = flash->read_opcode; >>>> + flash->command[0] = opcode; >>>> + m25p_addr2cmd(flash, from, flash->command); >>>> + >>>> + spi_sync(flash->spi,&m); >>>> + >>>> + *retlen = m.actual_length - m25p_cmdsz(flash) - >>>> + (flash->quad_read ? 1 : 0); >>>> + >>>> + mutex_unlock(&flash->lock); >>>> + >>>> + return 0; >>>> +} >>>> + >>>> /* >>>> * Read an address range from the flash chip. The address range >>>> * may be any size provided it is within the physical boundaries. >>>> @@ -979,15 +1122,9 @@ static int m25p_probe(struct spi_device *spi) >>>> } >>>> } >>>> >>>> - flash = kzalloc(sizeof *flash, GFP_KERNEL); >>>> + flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL); >>>> if (!flash) >>>> return -ENOMEM; >>>> - flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : 0), >>>> - GFP_KERNEL); >>>> - if (!flash->command) { >>>> - kfree(flash); >>>> - return -ENOMEM; >>>> - } >>> You're combining a bug fix with your feature addition. The size may be >>> off-by-one (which is insignificant in this case, I think, but still...) >>> so the kmalloc() does needs to move down, but it should be done before >>> this feature patch. (Sorry, I've had a patch queued up but didn't send >>> it out for a while. I think somebody sorta tried to fix this a while ago >>> but didn't send a proper patch.) >>> >> Yes, true. I can break this patch into two with first patch as the >> bug fix and >> second as the feature. Is it ok? > I just submitted my cleanups which (among other things) fixes this bug. > I believe I CC'd you. Go ahead and review it, and if it works to your > liking, please just base your work on top of it. I'll apply some or all > of that series if no one objects. > Ok. >>>> flash->spi = spi; >>>> mutex_init(&flash->lock); >>>> @@ -1067,6 +1203,38 @@ static int m25p_probe(struct spi_device *spi) >>>> >>>> flash->program_opcode = OPCODE_PP; >>>> >>>> + flash->quad_read = false; >>>> + if (spi->mode&& SPI_RX_QUAD) >>> You're looking for bitwise '&', not logical'&&'. >>> >>>> + flash->quad_read = true; >>> But you can just replace the previous 3 lines with: >>> >>> flash->quad_read = spi->mode& SPI_RX_QUAD; >>> >>> or this, if you really want be careful about the bit position: >>> >>> flash->quad_read = !!(spi->mode& SPI_RX_QUAD); >>> >> True, will fix. >>>> + >>>> + flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : >>>> + (flash->quad_read ? 1 : 0)), GFP_KERNEL); >>> That's an ugly conditional. Maybe we just want to increase MAX_CMD_SIZE >>> and be done with it? Saving an extra byte is not helping anyone (and I >>> think pretty much everyone always has fast_read==true anyway). >> Yes, this can be done. But, I was not sure about increasing the macro just >> on coding perspective. If it sounds Ok, I will increase the macro and make >> the corresponding cleanups. > Just take a look at my patch for this issue, please. > Ok. >>>> + if (of_property_read_bool(np, "macronix,quad_enable")) { > ... >>>> + } else if (of_property_read_bool(np, "spansion,quad_enable")) { > ... >>>> + } else >>>> + dev_dbg(&spi->dev, "quad enable not supported"); >>> ...and if quad enable is not supported, we just blaze on to use quad >>> mode anyway?? No, I think this needs to be rewritten so that we only set >>> flash->quad_read = true when all of the following are true: >>> >>> (1) the SPI controller supports quad I/O >>> (2) the flash supports it (i.e., after we see that the device supports >>> it in the ID table/DT/SFDP) and >>> (3) we have successfully run one of the quad-enable commands >> I got your idea here and to sum up, my below diff can be done to >> better clean up the code. > Looks a little better. A few comments on it below. > >> diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c >> index f180ffd..6e32f6a 100644 >> --- a/drivers/mtd/devices/m25p80.c >> +++ b/drivers/mtd/devices/m25p80.c >> @@ -851,7 +851,7 @@ static const struct spi_device_id m25p_ids[] = { >> { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, >> { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) }, >> { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, >> - { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, 0) }, >> + { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, MX_QUAD_EN) }, > I don't think we need a separate Macronix and Spansion quad flag; I > think we can get by with just a M25P_QUAD flag (or some other name like > that). We can differentiate MXIC and Spansion via just the manufacturer > by it's ID, right? (See the similarity to set_4byte().) > Yes, I believe this can be done on similar lines to set_4byte. I will try this out in my next version. > Do all parts that support quad read also support all the other quad > opcodes (like quad program)? > I have Spansion and Macronix flash with me. For spansion, supported quad commands are: QOR(0x6b) which is what I am using. QIOR(0xeb) DDR QIOR(0xed) For macronix, QOR(0x6b) which is what I am using. QIOR(0xeb) >> /* Micron */ >> { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, >> @@ -870,7 +870,7 @@ static const struct spi_device_id m25p_ids[] = { >> { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, 0) }, >> { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, 0) }, >> { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) }, >> - { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, 0) }, >> + { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, >> SP_QUAD_EN) }, >> { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, 0) }, >> { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, >> { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, >> @@ -1094,6 +1094,25 @@ static int m25p_probe(struct spi_device *spi) >> flash->mtd.size = info->sector_size * info->n_sectors; >> flash->mtd._erase = m25p80_erase; >> >> + if (spi->mode& SPI_RX_QUAD) { >> + if (info->flags& SP_QUAD_EN) { >> + ret = spansion_quad_enable(flash); >> + if (ret) { >> + dev_err(&spi->dev, "error enabling quad"); >> + return -EINVAL; >> + } >> + flash->quad_read = true; >> + } else if (info->flags& MX_QUAD_EN) { >> + ret = spansion_quad_enable(flash); >> + if (ret) { >> + dev_err(&spi->dev, "error enabling quad"); >> + return -EINVAL; >> + } >> + flash->quad_read = true; >> + } else >> + dev_dbg(&spi->dev, "quad enable not supported"); >> + } >> + > I think we'll want a separate function set_quad_mode(), so we can just do: > > if (spi->mode& SPI_RX_QUAD&& info->flags& M25P_QUAD) { > ret = set_quad_mode(flash, info->jedec_id, 1); > if (ret) { > dev_err(...); > return ret; > } > flash->quad_read = true; > } > > Then the set_quad_mode() function can do things very similarly to > set_4byte(), based on the manufacturer JEDEC ID. Make sense, I will implement this. > Do you plan on supporting Quad Page Program? Currently, I am planning to add Quad output read(8 dummy cycle) only. > How about the dedicated > 4-byte addressing variants of these Quad commands? > Hmm, seems like I missed this. I will add this. > Are there any other important side effects when enabling quad mode? I'm > reading some things about changes in WP# and HOLD# behavior, but I'm not > quite sure right now if that has ramifications on the rest of the > driver. > Nope, I have not faced any. WP# and HOLD# are the IO2 and IO3 lines respectively in quad mode. > Brian ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCHv3 2/3] drivers: mtd: devices: Add quad read support. 2013-10-24 8:44 ` Sourav Poddar @ 2013-10-24 17:07 ` Brian Norris 2013-10-24 17:55 ` Sourav Poddar 0 siblings, 1 reply; 104+ messages in thread From: Brian Norris @ 2013-10-24 17:07 UTC (permalink / raw) To: Sourav Poddar Cc: Marek Vasut, Jagan Teki, balbi, Huang Shijie, broonie, linux-mtd, spi-devel-general, dwmw2 On Thu, Oct 24, 2013 at 02:14:59PM +0530, Sourav Poddar wrote: > On Thursday 24 October 2013 01:04 PM, Brian Norris wrote: > >I just submitted my cleanups which (among other things) fixes this bug. > >I believe I CC'd you. Go ahead and review it, and if it works to your > >liking, please just base your work on top of it. I'll apply some or all > >of that series if no one objects. > > > Ok. I'll push parts the reviewed parts of my patch series now, so you can base off them. (I'm still open to comments on them, though.) > >Do all parts that support quad read also support all the other quad > >opcodes (like quad program)? > > > I have Spansion and Macronix flash with me. > > For spansion, > supported quad commands are: > QOR(0x6b) which is what I am using. > QIOR(0xeb) > DDR QIOR(0xed) > > For macronix, > QOR(0x6b) which is what I am using. > QIOR(0xeb) So it seems there are flash which support quad read but not quad program. So the flag I recommended (M25P80_QUAD) should be made specific to quad read (M25P80_QUAD_READ) I guess, since we may support page program eventually. Brian ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCHv3 2/3] drivers: mtd: devices: Add quad read support. 2013-10-24 17:07 ` Brian Norris @ 2013-10-24 17:55 ` Sourav Poddar 0 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-24 17:55 UTC (permalink / raw) To: Brian Norris Cc: Marek Vasut, Jagan Teki, balbi, Huang Shijie, broonie, linux-mtd, spi-devel-general, dwmw2 Hi Brian, On Thursday 24 October 2013 10:37 PM, Brian Norris wrote: > On Thu, Oct 24, 2013 at 02:14:59PM +0530, Sourav Poddar wrote: >> On Thursday 24 October 2013 01:04 PM, Brian Norris wrote: >>> I just submitted my cleanups which (among other things) fixes this bug. >>> I believe I CC'd you. Go ahead and review it, and if it works to your >>> liking, please just base your work on top of it. I'll apply some or all >>> of that series if no one objects. >>> >> Ok. > I'll push parts the reviewed parts of my patch series now, so you can > base off them. (I'm still open to comments on them, though.) > >>> Do all parts that support quad read also support all the other quad >>> opcodes (like quad program)? >>> >> I have Spansion and Macronix flash with me. >> >> For spansion, >> supported quad commands are: >> QOR(0x6b) which is what I am using. >> QIOR(0xeb) >> DDR QIOR(0xed) >> >> For macronix, >> QOR(0x6b) which is what I am using. >> QIOR(0xeb) > So it seems there are flash which support quad read but not quad > program. So the flag I recommended (M25P80_QUAD) should be made specific > to quad read (M25P80_QUAD_READ) I guess, since we may support page > program eventually. > Sounds good. I will take care of this in my next version. ~Sourav > Brian ^ permalink raw reply [flat|nested] 104+ messages in thread
* [RFC/PATCH 3/3] drivers: mtd: devices: Add memory mapped read support. 2013-10-09 15:24 ` Sourav Poddar @ 2013-10-09 15:24 ` Sourav Poddar -1 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-09 15:24 UTC (permalink / raw) To: broonie, dwmw2, computersforpeace Cc: spi-devel-general, Sourav Poddar, linux-mtd, balbi Add memory mapped flash read support. In memory mapped, only the len, from and t->rx_buf is required from the flash side, while other configuration will be taken care of from the respective controller side with the help of the transfer flag(memory_map). Signed-off-by: Sourav Poddar <sourav.poddar@ti.com> --- drivers/mtd/devices/m25p80.c | 13 +++++++++++-- include/linux/spi/spi.h | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index dc9bcbf..9d09bad 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -102,6 +102,7 @@ struct m25p { u8 *command; bool fast_read; bool quad_read; + bool mmap_read; }; static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) @@ -440,10 +441,15 @@ static int m25p80_quad_read(struct mtd_info *mtd, loff_t from, size_t len, spi_message_init(&m); memset(t, 0, (sizeof(t))); + if (flash->mmap_read) + t[0].memory_map = 1; t[0].tx_buf = flash->command; - t[0].len = m25p_cmdsz(flash) + (flash->quad_read ? 1 : 0); + t[0].len = flash->mmap_read ? from : m25p_cmdsz(flash) + + (flash->quad_read ? 1 : 0); spi_message_add_tail(&t[0], &m); + if (flash->mmap_read) + t[1].memory_map = 1; t[1].rx_buf = buf; t[1].len = len; t[1].rx_nbits = SPI_NBITS_QUAD; @@ -470,7 +476,7 @@ static int m25p80_quad_read(struct mtd_info *mtd, loff_t from, size_t len, spi_sync(flash->spi, &m); - *retlen = m.actual_length - m25p_cmdsz(flash) - + *retlen = flash->mmap_read ? len : m.actual_length - m25p_cmdsz(flash) - (flash->quad_read ? 1 : 0); mutex_unlock(&flash->lock); @@ -1207,6 +1213,9 @@ static int m25p_probe(struct spi_device *spi) if (spi->mode && SPI_RX_QUAD) flash->quad_read = true; + if (spi->mode && SPI_RX_MMAP) + flash->mmap_read = true; + flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : (flash->quad_read ? 1 : 0)), GFP_KERNEL); if (!flash->command) { diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 4d634d6..a6ffb52 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -91,6 +91,7 @@ struct spi_device { #define SPI_TX_QUAD 0x200 /* transmit with 4 wires */ #define SPI_RX_DUAL 0x400 /* receive with 2 wires */ #define SPI_RX_QUAD 0x800 /* receive with 4 wires */ +#define SPI_RX_MMAP 0x1000 /* Memory mapped read */ u8 bits_per_word; int irq; void *controller_state; @@ -557,6 +558,7 @@ struct spi_transfer { u16 delay_usecs; u32 speed_hz; + bool memory_map; struct list_head transfer_list; }; -- 1.7.1 ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply related [flat|nested] 104+ messages in thread
* [RFC/PATCH 3/3] drivers: mtd: devices: Add memory mapped read support. @ 2013-10-09 15:24 ` Sourav Poddar 0 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-09 15:24 UTC (permalink / raw) To: broonie, dwmw2, computersforpeace Cc: spi-devel-general, Sourav Poddar, linux-mtd, balbi Add memory mapped flash read support. In memory mapped, only the len, from and t->rx_buf is required from the flash side, while other configuration will be taken care of from the respective controller side with the help of the transfer flag(memory_map). Signed-off-by: Sourav Poddar <sourav.poddar@ti.com> --- drivers/mtd/devices/m25p80.c | 13 +++++++++++-- include/linux/spi/spi.h | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index dc9bcbf..9d09bad 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -102,6 +102,7 @@ struct m25p { u8 *command; bool fast_read; bool quad_read; + bool mmap_read; }; static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) @@ -440,10 +441,15 @@ static int m25p80_quad_read(struct mtd_info *mtd, loff_t from, size_t len, spi_message_init(&m); memset(t, 0, (sizeof(t))); + if (flash->mmap_read) + t[0].memory_map = 1; t[0].tx_buf = flash->command; - t[0].len = m25p_cmdsz(flash) + (flash->quad_read ? 1 : 0); + t[0].len = flash->mmap_read ? from : m25p_cmdsz(flash) + + (flash->quad_read ? 1 : 0); spi_message_add_tail(&t[0], &m); + if (flash->mmap_read) + t[1].memory_map = 1; t[1].rx_buf = buf; t[1].len = len; t[1].rx_nbits = SPI_NBITS_QUAD; @@ -470,7 +476,7 @@ static int m25p80_quad_read(struct mtd_info *mtd, loff_t from, size_t len, spi_sync(flash->spi, &m); - *retlen = m.actual_length - m25p_cmdsz(flash) - + *retlen = flash->mmap_read ? len : m.actual_length - m25p_cmdsz(flash) - (flash->quad_read ? 1 : 0); mutex_unlock(&flash->lock); @@ -1207,6 +1213,9 @@ static int m25p_probe(struct spi_device *spi) if (spi->mode && SPI_RX_QUAD) flash->quad_read = true; + if (spi->mode && SPI_RX_MMAP) + flash->mmap_read = true; + flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : (flash->quad_read ? 1 : 0)), GFP_KERNEL); if (!flash->command) { diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 4d634d6..a6ffb52 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -91,6 +91,7 @@ struct spi_device { #define SPI_TX_QUAD 0x200 /* transmit with 4 wires */ #define SPI_RX_DUAL 0x400 /* receive with 2 wires */ #define SPI_RX_QUAD 0x800 /* receive with 4 wires */ +#define SPI_RX_MMAP 0x1000 /* Memory mapped read */ u8 bits_per_word; int irq; void *controller_state; @@ -557,6 +558,7 @@ struct spi_transfer { u16 delay_usecs; u32 speed_hz; + bool memory_map; struct list_head transfer_list; }; -- 1.7.1 ^ permalink raw reply related [flat|nested] 104+ messages in thread
* Re: [RFC/PATCH 3/3] drivers: mtd: devices: Add memory mapped read support. 2013-10-09 15:24 ` Sourav Poddar @ 2013-10-09 15:45 ` Mark Brown -1 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-09 15:45 UTC (permalink / raw) To: Sourav Poddar Cc: spi-devel-general, computersforpeace, dwmw2, balbi, linux-mtd [-- Attachment #1.1: Type: text/plain, Size: 240 bytes --] On Wed, Oct 09, 2013 at 08:54:44PM +0530, Sourav Poddar wrote: > drivers/mtd/devices/m25p80.c | 13 +++++++++++-- > include/linux/spi/spi.h | 2 ++ You shouldn't be adding the SPI feature in the same change as you add the user. [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] [-- Attachment #2: Type: text/plain, Size: 144 bytes --] ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [RFC/PATCH 3/3] drivers: mtd: devices: Add memory mapped read support. @ 2013-10-09 15:45 ` Mark Brown 0 siblings, 0 replies; 104+ messages in thread From: Mark Brown @ 2013-10-09 15:45 UTC (permalink / raw) To: Sourav Poddar Cc: spi-devel-general, computersforpeace, dwmw2, balbi, linux-mtd [-- Attachment #1: Type: text/plain, Size: 240 bytes --] On Wed, Oct 09, 2013 at 08:54:44PM +0530, Sourav Poddar wrote: > drivers/mtd/devices/m25p80.c | 13 +++++++++++-- > include/linux/spi/spi.h | 2 ++ You shouldn't be adding the SPI feature in the same change as you add the user. [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 0/3]Add quad/memory mapped support for SPI flash. 2013-10-09 15:24 ` Sourav Poddar ` (3 preceding siblings ...) (?) @ 2013-10-24 0:22 ` Brian Norris 2013-10-24 4:51 ` Sourav Poddar -1 siblings, 1 reply; 104+ messages in thread From: Brian Norris @ 2013-10-24 0:22 UTC (permalink / raw) To: Sourav Poddar; +Cc: spi-devel-general, broonie, dwmw2, balbi, linux-mtd Hi Sourav, I must admit, I missed some of this series due to a combination of strange Gmail filtering (I just learned that a filter for "PATCH" doesn't match "PATCHv3" in Gmail...) and the inconsistent naming in your patch series. (I see PATCH, PATCHv3, and RFC/PATCH.) I'll try to prevent that in the future. On Wed, Oct 09, 2013 at 08:54:41PM +0530, Sourav Poddar wrote: > This patch add quad/memory mapped support in flash driver(m25p80). Does "memory mapped" supoprt need to be in the same series as quad read support? Those are very different topics, it seems. > Added support for quad memory mapped for TI qspi controller also. > > This patch has been tested with some internal dts data. Your patches use new DT bindings which are not documented. If you are adding bindings, please document them in Documentation/devicetree/bindings/ and CC devicetree@vger.kernel.org. (You only need to CC them for the binding documenation, not necessarily all your code changes.) That being said, I'm not sure you need some of the bindings that you're using. I'll comment on the affected patch(es). Brian ^ permalink raw reply [flat|nested] 104+ messages in thread
* Re: [PATCH 0/3]Add quad/memory mapped support for SPI flash. 2013-10-24 0:22 ` [PATCH 0/3]Add quad/memory mapped support for SPI flash Brian Norris @ 2013-10-24 4:51 ` Sourav Poddar 0 siblings, 0 replies; 104+ messages in thread From: Sourav Poddar @ 2013-10-24 4:51 UTC (permalink / raw) To: Brian Norris; +Cc: spi-devel-general, broonie, dwmw2, balbi, linux-mtd Hi Brian, Thanks for the reply. On Thursday 24 October 2013 05:52 AM, Brian Norris wrote: > Hi Sourav, > > I must admit, I missed some of this series due to a combination of > strange Gmail filtering (I just learned that a filter for "PATCH" > doesn't match "PATCHv3" in Gmail...) and the inconsistent naming in your > patch series. (I see PATCH, PATCHv3, and RFC/PATCH.) I'll try to prevent > that in the future. > Sorry for this, I tried to keep the tag according to the status of the patch. I will try to be uniform in my patch subject. > On Wed, Oct 09, 2013 at 08:54:41PM +0530, Sourav Poddar wrote: >> This patch add quad/memory mapped support in flash driver(m25p80). > Does "memory mapped" supoprt need to be in the same series as quad read > support? Those are very different topics, it seems. > Yes, this are different topic and I can send you the quad support seperately as a single patch ? >> Added support for quad memory mapped for TI qspi controller also. >> >> This patch has been tested with some internal dts data. > Your patches use new DT bindings which are not documented. If you are > adding bindings, please document them in > Documentation/devicetree/bindings/ and CC devicetree@vger.kernel.org. > (You only need to CC them for the binding documenation, not necessarily > all your code changes.) Ok. I will take care of this. > That being said, I'm not sure you need some of the bindings that you're > using. I'll comment on the affected patch(es). > > Brian ^ permalink raw reply [flat|nested] 104+ messages in thread
end of thread, other threads:[~2013-10-24 17:56 UTC | newest] Thread overview: 104+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2013-10-09 15:24 [PATCH 0/3]Add quad/memory mapped support for SPI flash Sourav Poddar 2013-10-09 15:24 ` Sourav Poddar 2013-10-09 15:24 ` [PATCH 1/3] spi/qspi: Add memory mapped read support Sourav Poddar 2013-10-09 15:24 ` Sourav Poddar 2013-10-09 16:07 ` Mark Brown 2013-10-09 16:07 ` Mark Brown [not found] ` <20131009160759.GQ21581-GFdadSzt00ze9xe1eoZjHA@public.gmane.org> 2013-10-09 16:54 ` Sourav Poddar 2013-10-09 16:54 ` Sourav Poddar 2013-10-09 17:40 ` Mark Brown 2013-10-09 17:40 ` Mark Brown 2013-10-09 18:15 ` Sourav Poddar 2013-10-09 18:15 ` Sourav Poddar 2013-10-09 18:41 ` Mark Brown 2013-10-09 18:41 ` Mark Brown [not found] ` <20131009174027.GS21581-GFdadSzt00ze9xe1eoZjHA@public.gmane.org> 2013-10-09 19:01 ` Peter Korsgaard 2013-10-09 19:01 ` Peter Korsgaard 2013-10-09 19:36 ` Mark Brown 2013-10-09 19:36 ` Mark Brown [not found] ` <87hacq1d5k.fsf-D6SC8u56vOOJDPpyT6T3/w@public.gmane.org> 2013-10-10 2:27 ` Trent Piepho 2013-10-10 2:27 ` Trent Piepho 2013-10-10 8:52 ` Sourav Poddar 2013-10-10 8:52 ` Sourav Poddar 2013-10-10 10:14 ` Mark Brown 2013-10-10 10:14 ` Mark Brown 2013-10-10 10:17 ` Sourav Poddar 2013-10-10 10:17 ` Sourav Poddar 2013-10-10 11:08 ` Sourav Poddar 2013-10-10 11:08 ` Sourav Poddar 2013-10-11 10:08 ` Mark Brown 2013-10-11 10:08 ` Mark Brown 2013-10-15 6:06 ` Sourav Poddar 2013-10-15 6:06 ` Sourav Poddar 2013-10-15 11:16 ` Mark Brown 2013-10-15 11:16 ` Mark Brown 2013-10-15 11:49 ` Sourav Poddar 2013-10-15 11:49 ` Sourav Poddar 2013-10-15 12:46 ` Mark Brown 2013-10-15 12:46 ` Mark Brown [not found] ` <20131015124656.GM2443-GFdadSzt00ze9xe1eoZjHA@public.gmane.org> 2013-10-15 13:23 ` Sourav Poddar 2013-10-15 13:23 ` Sourav Poddar 2013-10-15 15:53 ` Mark Brown 2013-10-15 15:53 ` Mark Brown [not found] ` <525D41E2.30206-l0cyMroinI0@public.gmane.org> 2013-10-15 15:33 ` Gupta, Pekon 2013-10-15 15:33 ` Gupta, Pekon 2013-10-15 16:01 ` Mark Brown 2013-10-15 16:01 ` Mark Brown 2013-10-15 16:54 ` Gupta, Pekon 2013-10-15 16:54 ` Gupta, Pekon 2013-10-15 18:01 ` Brian Norris 2013-10-15 18:01 ` Brian Norris 2013-10-15 18:10 ` Sourav Poddar 2013-10-15 18:10 ` Sourav Poddar [not found] ` <20131015180142.GS23337-bU/DPfM3abD4WzifrMjOTkcViWtcw2C0@public.gmane.org> 2013-10-15 18:13 ` Trent Piepho 2013-10-15 18:13 ` Trent Piepho 2013-10-15 18:33 ` Gupta, Pekon 2013-10-15 18:33 ` Gupta, Pekon 2013-10-15 20:52 ` Mark Brown 2013-10-15 20:52 ` Mark Brown [not found] ` <20131015205254.GX2443-GFdadSzt00ze9xe1eoZjHA@public.gmane.org> 2013-10-15 21:03 ` Trent Piepho 2013-10-15 21:03 ` Trent Piepho 2013-10-15 22:10 ` Mark Brown 2013-10-15 22:10 ` Mark Brown [not found] ` <20980858CB6D3A4BAE95CA194937D5E73EA23640-yXqyApvAXouIQmiDNMet8wC/G2K4zDHf@public.gmane.org> 2013-10-17 12:24 ` Sourav Poddar 2013-10-17 12:24 ` Sourav Poddar 2013-10-17 12:38 ` Mark Brown 2013-10-17 12:38 ` Mark Brown 2013-10-17 13:03 ` Gupta, Pekon 2013-10-17 13:03 ` Gupta, Pekon 2013-10-17 23:42 ` Mark Brown 2013-10-18 4:06 ` Sourav Poddar 2013-10-18 5:56 ` Trent Piepho 2013-10-18 6:10 ` Sourav Poddar 2013-10-18 7:27 ` Sourav Poddar 2013-10-18 10:31 ` Mark Brown 2013-10-18 11:48 ` Sourav Poddar 2013-10-18 13:08 ` Mark Brown 2013-10-18 14:47 ` Sourav Poddar 2013-10-15 20:59 ` Mark Brown 2013-10-15 20:59 ` Mark Brown [not found] ` <52566ACC.1080100-l0cyMroinI0@public.gmane.org> 2013-10-11 9:30 ` Gupta, Pekon 2013-10-11 9:30 ` Gupta, Pekon 2013-10-10 10:10 ` Mark Brown 2013-10-10 10:10 ` Mark Brown [not found] ` <20131010101052.GF21581-GFdadSzt00ze9xe1eoZjHA@public.gmane.org> 2013-10-10 23:53 ` Trent Piepho 2013-10-11 9:59 ` Mark Brown 2013-10-11 9:59 ` Mark Brown 2013-10-09 15:24 ` [PATCHv3 2/3] drivers: mtd: devices: Add quad " Sourav Poddar 2013-10-09 15:24 ` Sourav Poddar [not found] ` <1381332284-21822-3-git-send-email-sourav.poddar-l0cyMroinI0@public.gmane.org> 2013-10-09 18:15 ` Jagan Teki 2013-10-09 18:15 ` Jagan Teki [not found] ` <CAD6G_RShZMkSpVzvXWEE0+sDX=pcnf7ndChndgDG5_T4EVL2vQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2013-10-11 7:10 ` Gupta, Pekon 2013-10-11 7:10 ` Gupta, Pekon 2013-10-24 1:06 ` Brian Norris 2013-10-24 5:44 ` Sourav Poddar 2013-10-24 7:34 ` Brian Norris 2013-10-24 8:44 ` Sourav Poddar 2013-10-24 17:07 ` Brian Norris 2013-10-24 17:55 ` Sourav Poddar 2013-10-09 15:24 ` [RFC/PATCH 3/3] drivers: mtd: devices: Add memory mapped " Sourav Poddar 2013-10-09 15:24 ` Sourav Poddar 2013-10-09 15:45 ` Mark Brown 2013-10-09 15:45 ` Mark Brown 2013-10-24 0:22 ` [PATCH 0/3]Add quad/memory mapped support for SPI flash Brian Norris 2013-10-24 4:51 ` Sourav Poddar
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.