[PATCH 2/2] mtd: nand: spi: Support GigaDevice GD5F1GQ5UExxG

Stefan Roese sr at denx.de
Thu Feb 11 10:35:25 CET 2021


On 10.02.21 19:36, Reto Schneider wrote:
> From: Reto Schneider <reto.schneider at husqvarnagroup.com>
> 
> The relevant changes to the already existing GD5F1GQ4UExxG support has
> been determined by consulting the GigaDevice product change notice
> AN-0392-10, version 1.0 from November 30, 2020.
> 
> As the overlaps are huge, variable names have been generalized
> accordingly.
> 
> Apart form the lowered ECC strength (4 instead of 8 bits per 512 bytes),
> the new device ID, and the extra quad IO dummy byte, no changes had to
> be taken into account.
> 
> New hardware features are not supported, namely:
>   - Power on reset
>   - Unique ID
>   - Double transfer rate (DTR)
>   - Parameter page
>   - Random data quad IO
> 
> The inverted semantic of the "driver strength" register bits, defaulting
> to 100% instead of 50% for the Q5 devices, got ignored as the driver has
> never touched them anyway.
> 
> The no longer supported "read from cache during block erase"
> functionality I do not know how to reflect.
> 
> Implementation has been tested on MediaTek MT7688 based GARDENA smart
> Gateways using both, GigaDevice GD5F1GQ5UEYIG and GD5F1GQ4UBYIG.
> 
> Signed-off-by: Reto Schneider <reto.schneider at husqvarnagroup.com>
> CC: Stefan Roese <sr at denx.de>

Looks good, so:

Reviewed-by: Stefan Roese <sr at denx.de>

Thanks,
Stefan

> ---
>   drivers/mtd/nand/spi/gigadevice.c | 79 +++++++++++++++++++++++++++----
>   1 file changed, 69 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/mtd/nand/spi/gigadevice.c b/drivers/mtd/nand/spi/gigadevice.c
> index 5de0ebbb7b..a2c93486f4 100644
> --- a/drivers/mtd/nand/spi/gigadevice.c
> +++ b/drivers/mtd/nand/spi/gigadevice.c
> @@ -17,9 +17,13 @@
>   #define GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS	(1 << 4)
>   #define GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS	(3 << 4)
>   
> -#define GD5FXGQ4XEXXG_REG_STATUS2		0xf0
> +#define GD5FXGQ5XE_STATUS_ECC_1_4_BITFLIPS	(1 << 4)
> +#define GD5FXGQ5XE_STATUS_ECC_4_BITFLIPS	(3 << 4)
>   
> -static SPINAND_OP_VARIANTS(read_cache_variants,
> +#define GD5FXGQXXEXXG_REG_STATUS2		0xf0
> +
> +/* Q4 devices, QUADIO: Dummy bytes valid for 1 and 2 GBit variants */
> +static SPINAND_OP_VARIANTS(gd5fxgq4_read_cache_variants,
>   		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0),
>   		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
>   		SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
> @@ -27,6 +31,15 @@ static SPINAND_OP_VARIANTS(read_cache_variants,
>   		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
>   		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
>   
> +/* Q5 devices, QUADIO: Dummy bytes only valid for 1 GBit variants */
> +static SPINAND_OP_VARIANTS(gd5f1gq5_read_cache_variants,
> +		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
> +		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
> +		SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
> +		SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
> +		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
> +		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
> +
>   static SPINAND_OP_VARIANTS(write_cache_variants,
>   		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
>   		SPINAND_PROG_LOAD(true, 0, NULL, 0));
> @@ -35,7 +48,7 @@ static SPINAND_OP_VARIANTS(update_cache_variants,
>   		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
>   		SPINAND_PROG_LOAD(false, 0, NULL, 0));
>   
> -static int gd5fxgq4xexxg_ooblayout_ecc(struct mtd_info *mtd, int section,
> +static int gd5fxgqxxexxg_ooblayout_ecc(struct mtd_info *mtd, int section,
>   				       struct mtd_oob_region *region)
>   {
>   	if (section)
> @@ -47,7 +60,7 @@ static int gd5fxgq4xexxg_ooblayout_ecc(struct mtd_info *mtd, int section,
>   	return 0;
>   }
>   
> -static int gd5fxgq4xexxg_ooblayout_free(struct mtd_info *mtd, int section,
> +static int gd5fxgqxxexxg_ooblayout_free(struct mtd_info *mtd, int section,
>   					struct mtd_oob_region *region)
>   {
>   	if (section)
> @@ -64,7 +77,7 @@ static int gd5fxgq4xexxg_ecc_get_status(struct spinand_device *spinand,
>   					u8 status)
>   {
>   	u8 status2;
> -	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQ4XEXXG_REG_STATUS2,
> +	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQXXEXXG_REG_STATUS2,
>   						      &status2);
>   	int ret;
>   
> @@ -102,21 +115,67 @@ static int gd5fxgq4xexxg_ecc_get_status(struct spinand_device *spinand,
>   	return -EINVAL;
>   }
>   
> -static const struct mtd_ooblayout_ops gd5fxgq4xexxg_ooblayout = {
> -	.ecc = gd5fxgq4xexxg_ooblayout_ecc,
> -	.rfree = gd5fxgq4xexxg_ooblayout_free,
> +static int gd5fxgq5xexxg_ecc_get_status(struct spinand_device *spinand,
> +					u8 status)
> +{
> +	u8 status2;
> +	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQXXEXXG_REG_STATUS2,
> +						      &status2);
> +	int ret;
> +
> +	switch (status & STATUS_ECC_MASK) {
> +	case STATUS_ECC_NO_BITFLIPS:
> +		return 0;
> +
> +	case GD5FXGQ5XE_STATUS_ECC_1_4_BITFLIPS:
> +		/*
> +		 * Read status2 register to determine a more fine grained
> +		 * bit error status
> +		 */
> +		ret = spi_mem_exec_op(spinand->slave, &op);
> +		if (ret)
> +			return ret;
> +
> +		/*
> +		 * 1 ... 4 bits are flipped (and corrected)
> +		 */
> +		/* bits sorted this way (1...0): ECCSE1, ECCSE0 */
> +		return ((status2 & STATUS_ECC_MASK) >> 4) + 1;
> +
> +	case STATUS_ECC_UNCOR_ERROR:
> +		return -EBADMSG;
> +
> +	default:
> +		break;
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static const struct mtd_ooblayout_ops gd5fxgqxxexxg_ooblayout = {
> +	.ecc = gd5fxgqxxexxg_ooblayout_ecc,
> +	.rfree = gd5fxgqxxexxg_ooblayout_free,
>   };
>   
>   static const struct spinand_info gigadevice_spinand_table[] = {
>   	SPINAND_INFO("GD5F1GQ4UExxG", 0xd1,
>   		     NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
>   		     NAND_ECCREQ(8, 512),
> -		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
> +		     SPINAND_INFO_OP_VARIANTS(&gd5fxgq4_read_cache_variants,
>   					      &write_cache_variants,
>   					      &update_cache_variants),
>   		     0,
> -		     SPINAND_ECCINFO(&gd5fxgq4xexxg_ooblayout,
> +		     SPINAND_ECCINFO(&gd5fxgqxxexxg_ooblayout,
>   				     gd5fxgq4xexxg_ecc_get_status)),
> +	SPINAND_INFO("GD5F1GQ5UExxG", 0x51,
> +		     NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
> +		     NAND_ECCREQ(4, 512),
> +		     SPINAND_INFO_OP_VARIANTS(&gd5f1gq5_read_cache_variants,
> +					      &write_cache_variants,
> +					      &update_cache_variants),
> +		     0,
> +		     SPINAND_ECCINFO(&gd5fxgqxxexxg_ooblayout,
> +				     gd5fxgq5xexxg_ecc_get_status)),
>   };
>   
>   static int gigadevice_spinand_detect(struct spinand_device *spinand)
> 


Viele Grüße,
Stefan

-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr at denx.de


More information about the U-Boot mailing list