[U-Boot] [PATCH v10 03/27] mtd: add SPI-NOR core support

Jagan Teki
2018-01-02T10:31:24Z

On Tue, Jan 2, 2018 at 3:48 PM, Prabhakar Kushwaha
<prabhakar.kushwaha@nxp.com> wrote:
> Hi Jagan,
>
>
>> -----Original Message-----
>> From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Jagan Teki
>> Sent: Thursday, December 28, 2017 11:42 AM
>> To: u-boot at lists.denx.de
>> Cc: Tom Rini <trini@konsulko.com>
>> Subject: [U-Boot] [PATCH v10 03/27] mtd: add SPI-NOR core support
>>
>> Some of the SPI device drivers at drivers/spi not a real
>> spi controllers, Unlike normal/generic SPI controllers they
>> operates only with SPI-NOR flash devices. these were technically
>> termed as SPI-NOR controllers, Ex: drivers/spi/fsl_qspi.c
>>
>> The problem with these were resides at drivers/spi is entire
>> SPI layer becomes SPI-NOR flash oriented which is absolutely
>> a wrong indication where SPI layer getting effected more with
>> flash operations - So this SPI-NOR core will resolve this issue
>> by separating all SPI-NOR flash operations from spi layer and
>> creats a generic layer called SPI-NOR core which can be used to
>> interact SPI-NOR to SPI driver interface layer and the SPI-NOR
>> controller driver. The idea is taken from Linux spi-nor framework.
>>
>> =======================================
>> cmd/spinor.c
>> =======================================
>> mtd-uclass.c
>> =======================================
>> spi-nor-uclass.c
>> =======================================
>> spi-nor.c
>> =======================================
>> m25p80.c zynq_qspinor.c
>> =======================================
>> spi-uclass.c
>> =======================================
>> zynq_qspi.c
>> =======================================
>> #####SPI NOR chip######
>> =======================================
>>
>
> <snip>
>
>
>> + * SPDX-License-Identifier: GPL-2.0+
>> + */
>> +
>> +#include <common.h>
>> +#include <dm.h>
>> +#include <errno.h>
>> +#include <mapmem.h>
>> +#include <mtd.h>
>> +
>> +#include <dm/device-internal.h>
>> +#include <linux/math64.h>
>> +#include <linux/types.h>
>> +#include <linux/mtd/spi-nor.h>
>> +
>> +int spi_nor_scan(struct spi_nor *nor)
>> +{
>> + struct mtd_info *mtd = spi_nor_get_mtd_info(nor);
>> + struct mtd_ops *ops = mtd_get_ops(mtd->dev);
>> + const struct spi_nor_info *info = NULL;
>> + int ret;
>> +
>> + struct spi_nor_uclass_priv *upriv = dev_get_uclass_priv(nor->dev);
>> + upriv->spi_nor = nor;
>> +
>> + if (nor->init_done)
>> + return 0;
>> +
>> + info = spi_nor_id(nor->dev);
>> + if (IS_ERR_OR_NULL(info)) {
>> + ret = -ENOENT;
>> + goto err;
>> + }
>> +
>> + /*
>> + * Flash powers up read-only, so clear BP# bits.
>> + *
>> + * Note on some flash (like Macronix), QE (quad enable) bit is in the
>> + * same status register as BP# bits, and we need preserve its original
>> + * value during a reboot cycle as this is required by some platforms
>> + * (like Intel ICH SPI controller working under descriptor mode).
>> + */
>> + if (JEDEC_MFR(info) == SNOR_MFR_ATMEL ||
>> + (JEDEC_MFR(info) == SNOR_MFR_SST) ||
>> + (JEDEC_MFR(info) == SNOR_MFR_MACRONIX)) {
>> + u8 sr = 0;
>> +
>> + if (JEDEC_MFR(info) == SNOR_MFR_MACRONIX)
>> + sr = read_sr(nor->dev) & SR_QUAD_EN_MX;
>> + write_sr(nor->dev, sr);
>> + }
>> +
>> + mtd->name = info->name;
>> + mtd->priv = nor;
>> + mtd->type = MTD_NORFLASH;
>> + mtd->writesize = 1;
>> + mtd->flags = MTD_CAP_NORFLASH;
>> +
>> + if (info->flags & E_FSR)
>> + nor->flags |= SNOR_F_USE_FSR;
>> +
>> + if (info->flags & SST_WR)
>> + nor->flags |= SNOR_F_SST_WRITE;
>> +
>> + ops->write = spi_nor_mwrite;
>> +
>> + /* compute the flash size */
>> + nor->page_size = info->page_size;
>> + /*
>> + * The Spansion S25FL032P and S25FL064P have 256b pages, yet use the
>> + * 0x4d00 Extended JEDEC code. The rest of the Spansion flashes with
>> + * the 0x4d00 Extended JEDEC code have 512b pages. All of the others
>> + * have 256b pages.
>> + */
>> + if (JEDEC_EXT(info) == 0x4d00) {
>> + if ((JEDEC_ID(info) != 0x0215) &&
>> + (JEDEC_ID(info) != 0x0216))
>> + nor->page_size = 512;
>> + }
>> + mtd->writebufsize = nor->page_size;
>> + mtd->size = info->sector_size * info->n_sectors;
>> +
>> +#ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS
>> + /* prefer "small sector" erase if possible */
>> + if (info->flags & SECT_4K) {
>> + nor->erase_opcode = SNOR_OP_BE_4K;
>> + mtd->erasesize = 4096;
>> + } else
>> +#endif
>> + {
>> + nor->erase_opcode = SNOR_OP_SE;
>> + mtd->erasesize = info->sector_size;
>> + }
>> +
>> + /* Look for read opcode */
>> + nor->read_opcode = SNOR_OP_READ_FAST;
>> + if (nor->mode & SNOR_READ)
>> + nor->read_opcode = SNOR_OP_READ;
>> + else if (nor->mode & SNOR_READ_1_1_4 && info->flags & RD_QUAD)
>> + nor->read_opcode = SNOR_OP_READ_1_1_4;
>> + else if (nor->mode & SNOR_READ_1_1_2 && info->flags & RD_DUAL)
>> + nor->read_opcode = SNOR_OP_READ_1_1_2;
>> +
>
> Are you planning to store read_protocol i.e. 1-1-1. 1-1-2, 1-4-4, 4-4-4 etc information in nor structure?
> It will help low level controller driver to configure number of lines to be used during read in instruction, address and data phase.
>
> Similar framework is present in Linux.
>
> struct spi_nor :
> * @read_proto: the SPI protocol for read operations
> * @write_proto: the SPI protocol for write operations
> * @reg_proto the SPI protocol for read_reg/write_reg/erase operations

ok try these and mention code sizes for the same.