Message ID | 1491497808-25487-5-git-send-email-clg@kaod.org |
---|---|
State | Superseded |
Delegated to: | Cyrille Pitchen |
Headers | show |
On 04/06/2017 06:56 PM, Cédric Le Goater wrote: > From: Robert Lippert <roblip@gmail.com> > > Implements support for the dual IO read mode on aspeed SMC/FMC > controllers which uses both MISO and MOSI lines for data during a read > to double the read bandwidth. > > Signed-off-by: Robert Lippert <rlippert@google.com> > [clg: adapted to mainline driver ] > Signed-off-by: Cédric Le Goater <clg@kaod.org> > --- > drivers/mtd/spi-nor/aspeed-smc.c | 20 +++++++++++++------- > 1 file changed, 13 insertions(+), 7 deletions(-) > > diff --git a/drivers/mtd/spi-nor/aspeed-smc.c b/drivers/mtd/spi-nor/aspeed-smc.c > index 7dfa1ea0a787..b3c8cfe29765 100644 > --- a/drivers/mtd/spi-nor/aspeed-smc.c > +++ b/drivers/mtd/spi-nor/aspeed-smc.c > @@ -512,6 +512,7 @@ static ssize_t aspeed_smc_read_user(struct spi_nor *nor, loff_t from, > int i; > u8 dummy = 0xFF; > int ret; > + u32 ctl; > > if (aspeed_smc_dma_check(chip, from, len)) { > ret = aspeed_smc_dma_start(chip, from, read_buf, len, 0); > @@ -525,6 +526,13 @@ static ssize_t aspeed_smc_read_user(struct spi_nor *nor, loff_t from, > for (i = 0; i < chip->nor.read_dummy / 8; i++) > aspeed_smc_write_to_ahb(chip->ahb_base, &dummy, sizeof(dummy)); > > + if (chip->nor.flash_read == SPI_NOR_DUAL) { > + /* Switch to dual I/O mode for data cycle */ > + ctl = readl(chip->ctl) & ~CONTROL_IO_MODE_MASK; > + ctl |= CONTROL_IO_DUAL_DATA; > + writel(ctl, chip->ctl); > + } > + Can't you switch the mode at runtime ? If you do, who'll clear the CONTROL_IO_DUAL_DATA in this ctl register if you switch to SINGLE mode for some command ?
On 04/06/2017 09:21 PM, Marek Vasut wrote: > On 04/06/2017 06:56 PM, Cédric Le Goater wrote: >> From: Robert Lippert <roblip@gmail.com> >> >> Implements support for the dual IO read mode on aspeed SMC/FMC >> controllers which uses both MISO and MOSI lines for data during a read >> to double the read bandwidth. >> >> Signed-off-by: Robert Lippert <rlippert@google.com> >> [clg: adapted to mainline driver ] >> Signed-off-by: Cédric Le Goater <clg@kaod.org> >> --- >> drivers/mtd/spi-nor/aspeed-smc.c | 20 +++++++++++++------- >> 1 file changed, 13 insertions(+), 7 deletions(-) >> >> diff --git a/drivers/mtd/spi-nor/aspeed-smc.c b/drivers/mtd/spi-nor/aspeed-smc.c >> index 7dfa1ea0a787..b3c8cfe29765 100644 >> --- a/drivers/mtd/spi-nor/aspeed-smc.c >> +++ b/drivers/mtd/spi-nor/aspeed-smc.c >> @@ -512,6 +512,7 @@ static ssize_t aspeed_smc_read_user(struct spi_nor *nor, loff_t from, >> int i; >> u8 dummy = 0xFF; >> int ret; >> + u32 ctl; >> >> if (aspeed_smc_dma_check(chip, from, len)) { >> ret = aspeed_smc_dma_start(chip, from, read_buf, len, 0); >> @@ -525,6 +526,13 @@ static ssize_t aspeed_smc_read_user(struct spi_nor *nor, loff_t from, >> for (i = 0; i < chip->nor.read_dummy / 8; i++) >> aspeed_smc_write_to_ahb(chip->ahb_base, &dummy, sizeof(dummy)); >> >> + if (chip->nor.flash_read == SPI_NOR_DUAL) { >> + /* Switch to dual I/O mode for data cycle */ >> + ctl = readl(chip->ctl) & ~CONTROL_IO_MODE_MASK; >> + ctl |= CONTROL_IO_DUAL_DATA; >> + writel(ctl, chip->ctl); >> + } >> + > Can't you switch the mode at runtime ? If you do, who'll clear the > CONTROL_IO_DUAL_DATA in this ctl register if you switch to SINGLE > mode for some command ? This is the read routine in User mode. When the read is completed, the previous (and default) setting of the control register is restored with a call to aspeed_smc_stop_user() but you don't see it in the diff hunk above. The default setting of the control register is used when the controller is in Command mode. That is when reads are performed 'automatically' from the AHB bus. C.
On 04/11/2017 10:53 AM, Cédric Le Goater wrote: > On 04/06/2017 09:21 PM, Marek Vasut wrote: >> On 04/06/2017 06:56 PM, Cédric Le Goater wrote: >>> From: Robert Lippert <roblip@gmail.com> >>> >>> Implements support for the dual IO read mode on aspeed SMC/FMC >>> controllers which uses both MISO and MOSI lines for data during a read >>> to double the read bandwidth. >>> >>> Signed-off-by: Robert Lippert <rlippert@google.com> >>> [clg: adapted to mainline driver ] >>> Signed-off-by: Cédric Le Goater <clg@kaod.org> >>> --- >>> drivers/mtd/spi-nor/aspeed-smc.c | 20 +++++++++++++------- >>> 1 file changed, 13 insertions(+), 7 deletions(-) >>> >>> diff --git a/drivers/mtd/spi-nor/aspeed-smc.c b/drivers/mtd/spi-nor/aspeed-smc.c >>> index 7dfa1ea0a787..b3c8cfe29765 100644 >>> --- a/drivers/mtd/spi-nor/aspeed-smc.c >>> +++ b/drivers/mtd/spi-nor/aspeed-smc.c >>> @@ -512,6 +512,7 @@ static ssize_t aspeed_smc_read_user(struct spi_nor *nor, loff_t from, >>> int i; >>> u8 dummy = 0xFF; >>> int ret; >>> + u32 ctl; >>> >>> if (aspeed_smc_dma_check(chip, from, len)) { >>> ret = aspeed_smc_dma_start(chip, from, read_buf, len, 0); >>> @@ -525,6 +526,13 @@ static ssize_t aspeed_smc_read_user(struct spi_nor *nor, loff_t from, >>> for (i = 0; i < chip->nor.read_dummy / 8; i++) >>> aspeed_smc_write_to_ahb(chip->ahb_base, &dummy, sizeof(dummy)); >>> >>> + if (chip->nor.flash_read == SPI_NOR_DUAL) { >>> + /* Switch to dual I/O mode for data cycle */ >>> + ctl = readl(chip->ctl) & ~CONTROL_IO_MODE_MASK; >>> + ctl |= CONTROL_IO_DUAL_DATA; >>> + writel(ctl, chip->ctl); >>> + } >>> + >> Can't you switch the mode at runtime ? If you do, who'll clear the >> CONTROL_IO_DUAL_DATA in this ctl register if you switch to SINGLE >> mode for some command ? > > This is the read routine in User mode. When the read is completed, > the previous (and default) setting of the control register is restored > with a call to aspeed_smc_stop_user() but you don't see it in the diff > hunk above. > > The default setting of the control register is used when the controller > is in Command mode. That is when reads are performed 'automatically' > from the AHB bus. Ah, OK, thanks for clarifying.
diff --git a/drivers/mtd/spi-nor/aspeed-smc.c b/drivers/mtd/spi-nor/aspeed-smc.c index 7dfa1ea0a787..b3c8cfe29765 100644 --- a/drivers/mtd/spi-nor/aspeed-smc.c +++ b/drivers/mtd/spi-nor/aspeed-smc.c @@ -512,6 +512,7 @@ static ssize_t aspeed_smc_read_user(struct spi_nor *nor, loff_t from, int i; u8 dummy = 0xFF; int ret; + u32 ctl; if (aspeed_smc_dma_check(chip, from, len)) { ret = aspeed_smc_dma_start(chip, from, read_buf, len, 0); @@ -525,6 +526,13 @@ static ssize_t aspeed_smc_read_user(struct spi_nor *nor, loff_t from, for (i = 0; i < chip->nor.read_dummy / 8; i++) aspeed_smc_write_to_ahb(chip->ahb_base, &dummy, sizeof(dummy)); + if (chip->nor.flash_read == SPI_NOR_DUAL) { + /* Switch to dual I/O mode for data cycle */ + ctl = readl(chip->ctl) & ~CONTROL_IO_MODE_MASK; + ctl |= CONTROL_IO_DUAL_DATA; + writel(ctl, chip->ctl); + } + aspeed_smc_read_from_ahb(read_buf, chip->ahb_base, len); aspeed_smc_stop_user(nor); out: @@ -751,6 +759,9 @@ static int aspeed_smc_chip_setup_finish(struct aspeed_smc_chip *chip) case SPI_NOR_FAST: cmd = CONTROL_COMMAND_MODE_FREAD; break; + case SPI_NOR_DUAL: + cmd = CONTROL_COMMAND_MODE_FREAD | CONTROL_IO_DUAL_DATA; + break; default: dev_err(chip->nor.dev, "unsupported SPI read mode\n"); return -EINVAL; @@ -760,7 +771,7 @@ static int aspeed_smc_chip_setup_finish(struct aspeed_smc_chip *chip) chip->nor.read_opcode << CONTROL_COMMAND_SHIFT | CONTROL_IO_DUMMY_SET(chip->nor.read_dummy / 8); - dev_dbg(controller->dev, "base control register: %08x\n", + dev_dbg(controller->dev, "read control register: %08x\n", chip->ctl_val[smc_read]); return 0; } @@ -830,12 +841,7 @@ static int aspeed_smc_setup_flash(struct aspeed_smc_controller *controller, if (ret) break; - /* - * TODO: Add support for SPI_NOR_QUAD and SPI_NOR_DUAL - * attach when board support is present as determined - * by of property. - */ - ret = spi_nor_scan(nor, NULL, SPI_NOR_NORMAL); + ret = spi_nor_scan(nor, NULL, SPI_NOR_DUAL); if (ret) break;