[PATCH linux 2/3] mtd: spi-nor: aspeed: add support for SPI dual IO read mode
Cédric Le Goater
clg at kaod.org
Thu Jan 12 05:50:42 AEDT 2017
On 01/11/2017 07:34 PM, Rob Lippert wrote:
> On Wed, Jan 11, 2017 at 3:43 AM, Cédric Le Goater <clg at kaod.org> wrote:
>> On 01/10/2017 11:54 PM, Rob Lippert wrote:
>>> On Tue, Jan 10, 2017 at 12:10 AM, Cédric Le Goater <clg at kaod.org> wrote:
>>>>
>>>> Hello Robert,
>>>>
>>>> On 01/10/2017 02:05 AM, Robert Lippert wrote:
>>>>> 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 at google.com>
>>>>> ---
>>>>>
>>>>> drivers/mtd/spi-nor/aspeed-smc.c | 28 ++++++++++++++++++++++------
>>>>> 1 file changed, 22 insertions(+), 6 deletions(-)
>>>>>
>>>>> diff --git a/drivers/mtd/spi-nor/aspeed-smc.c b/drivers/mtd/spi-nor/aspeed-smc.c
>>>>> index d3bed34f5aa0..a8ca2ab308d7 100644
>>>>> --- a/drivers/mtd/spi-nor/aspeed-smc.c
>>>>> +++ b/drivers/mtd/spi-nor/aspeed-smc.c
>>>>> @@ -540,6 +540,9 @@ static int aspeed_smc_read_user(struct spi_nor *nor, loff_t from, size_t len,
>>>>> {
>>>>> struct aspeed_smc_chip *chip = nor->priv;
>>>>> int ret;
>>>>> + u32 ctl;
>>>>> + int i;
>>>>> + u8 dummy = 0;
>>>>
>>>> OxFF would be a better value.
>>>
>>> OK.
>>>
>>>>
>>>>> mutex_lock(&chip->controller->mutex);
>>>>>
>>>>> @@ -557,6 +560,18 @@ static int aspeed_smc_read_user(struct spi_nor *nor, loff_t from, size_t len,
>>>>>
>>>>> aspeed_smc_start_user(nor);
>>>>> aspeed_smc_send_cmd_addr(nor, nor->read_opcode, from);
>>>>> +
>>>>> + /* Send dummy bytes */
>>>>> + for (i = 0; i < (chip->nor.read_dummy / 8); ++i)
>>>>
>>>> the parentheses are not needed I think.
>>>
>>> Yes not needed, removed.
>>>
>>>>
>>>>> + aspeed_smc_write_to_ahb(chip->base, &dummy, 1);
>>>>> +
>>>>> + if (chip->nor.flash_read == SPI_NOR_DUAL) {
>>>>> + /* Switch to dual I/O mode for data cycle */
>>>>> + ctl = readl(chip->ctl) & ~CONTROL_SPI_IO_MODE_MASK;
>>>>> + ctl |= CONTROL_SPI_IO_DUAL_DATA;
>>>>> + writel(ctl, chip->ctl);
>>>>> + }
>>>>
>>>> So why can not we set the controller in aspeed_smc_chip_setup_finish()
>>>> once and for all ?
>>>
>>> It needs to make sure to only effect the data part of the operation
>>> (the command+addr writes to the device should not be dual-IO mode),
>>> and also needs to not interfere with the aspeed_smc_read_reg read
>>> calls in which the data phase cannot be dual IO mode.
>>
>> ok. it makes sense. Is it much faster ?
>
> Yea it is about twice as much bandwidth, as I mentioned in the cover
> letter it drops the time to dump an entire 64MB flash from 12s to 7s.
Good. Sorry for asking, I scanned the cover a bit quickly it seems.
> With a companion change to u-boot to double the SPI frequency to
> 104Mhz that time drops to 3s and speeds up the entire bmc boot process
> (including uboot) by about 15s.
yes we need to add that to the driver also. I have a few other patches
improving the timing settings but I have been focusing on upstreaming
first.
Thanks,
C.
> Thanks,
> -Rob
>
>>
>> Thanks,
>>
>> C.
>>
>>>>
>>>>> +
>>>>> aspeed_smc_read_from_ahb(read_buf, chip->base, len);
>>>>> aspeed_smc_stop_user(nor);
>>>>>
>>>>> @@ -868,6 +883,7 @@ static int aspeed_smc_chip_setup_finish(struct aspeed_smc_chip *chip)
>>>>> cmd = CONTROL_SPI_COMMAND_MODE_NORMAL;
>>>>> break;
>>>>> case SPI_NOR_FAST:
>>>>> + case SPI_NOR_DUAL:
>>>>> cmd = CONTROL_SPI_COMMAND_MODE_FREAD;
>>>>> break;
>>>>> default:
>>>>> @@ -876,9 +892,13 @@ static int aspeed_smc_chip_setup_finish(struct aspeed_smc_chip *chip)
>>>>> }
>>>>>
>>>>> chip->ctl_val[smc_read] |= cmd |
>>>>> + spi_control_fill_opcode(chip->nor.read_opcode) |
>>>>> CONTROL_SPI_IO_DUMMY_CYCLES_SET(chip->nor.read_dummy / 8);
>>>>>
>>>>> - dev_dbg(controller->dev, "base control register: %08x\n",
>>>>> + if (chip->nor.flash_read == SPI_NOR_DUAL)
>>>>> + chip->ctl_val[smc_read] |= CONTROL_SPI_IO_DUAL_DATA;
>>>>
>>>> may be we can move that part in the switch setting above ?
>>>
>>> Done.
>>>
>>>>
>>>>> + dev_info(controller->dev, "read control register: %08x\n",
>>>>> chip->ctl_val[smc_read]);
>>>>
>>>> may be keep dev_dbg, but the change of 'base' by 'read' is ok.
>>>
>>> OK.
>>>
>>>>
>>>> Thanks,
>>>>
>>>> C.
>>>>
>>>>> return 0;
>>>>> }
>>>>> @@ -980,11 +1000,7 @@ static int aspeed_smc_probe(struct platform_device *pdev)
>>>>> if (err)
>>>>> continue;
>>>>>
>>>>> - /*
>>>>> - * XXX Add support for SPI_NOR_QUAD and SPI_NOR_DUAL attach
>>>>> - * when board support is present as determined by of property.
>>>>> - */
>>>>> - err = spi_nor_scan(&chip->nor, NULL, SPI_NOR_NORMAL);
>>>>> + err = spi_nor_scan(&chip->nor, NULL, SPI_NOR_DUAL);
>>>>> if (err)
>>>>> continue;
>>>>>
>>>>>
>>>>
>>
More information about the openbmc
mailing list