brintos

brintos / linux-shallow public Read only

0
0
Text · 15.4 KiB · d277c32 Raw
444 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2018 Macronix4 *5 * Author: Boris Brezillon <boris.brezillon@bootlin.com>6 */7 8#include <linux/bitfield.h>9#include <linux/device.h>10#include <linux/kernel.h>11#include <linux/mtd/spinand.h>12 13#define SPINAND_MFR_MACRONIX		0xC214#define MACRONIX_ECCSR_BF_LAST_PAGE(eccsr) FIELD_GET(GENMASK(3, 0), eccsr)15#define MACRONIX_ECCSR_BF_ACCUMULATED_PAGES(eccsr) FIELD_GET(GENMASK(7, 4), eccsr)16#define MACRONIX_CFG_CONT_READ         BIT(2)17 18#define STATUS_ECC_HAS_BITFLIPS_THRESHOLD (3 << 4)19 20/* Bitflip theshold configuration register */21#define REG_CFG_BFT 0x1022#define CFG_BFT(x) FIELD_PREP(GENMASK(7, 4), (x))23 24struct macronix_priv {25	bool cont_read;26};27 28static SPINAND_OP_VARIANTS(read_cache_variants,29		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),30		SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),31		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),32		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));33 34static SPINAND_OP_VARIANTS(write_cache_variants,35		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),36		SPINAND_PROG_LOAD(false, 0, NULL, 0));37 38static SPINAND_OP_VARIANTS(update_cache_variants,39		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),40		SPINAND_PROG_LOAD(false, 0, NULL, 0));41 42static int mx35lfxge4ab_ooblayout_ecc(struct mtd_info *mtd, int section,43				      struct mtd_oob_region *region)44{45	return -ERANGE;46}47 48static int mx35lfxge4ab_ooblayout_free(struct mtd_info *mtd, int section,49				       struct mtd_oob_region *region)50{51	if (section)52		return -ERANGE;53 54	region->offset = 2;55	region->length = mtd->oobsize - 2;56 57	return 0;58}59 60static const struct mtd_ooblayout_ops mx35lfxge4ab_ooblayout = {61	.ecc = mx35lfxge4ab_ooblayout_ecc,62	.free = mx35lfxge4ab_ooblayout_free,63};64 65static int macronix_get_eccsr(struct spinand_device *spinand, u8 *eccsr)66{67	struct macronix_priv *priv = spinand->priv;68	struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(0x7c, 1),69					  SPI_MEM_OP_NO_ADDR,70					  SPI_MEM_OP_DUMMY(1, 1),71					  SPI_MEM_OP_DATA_IN(1, eccsr, 1));72 73	int ret = spi_mem_exec_op(spinand->spimem, &op);74	if (ret)75		return ret;76 77	/*78	 * ECCSR exposes the number of bitflips for the last read page in bits [3:0].79	 * Continuous read compatible chips also expose the maximum number of80	 * bitflips for the whole (continuous) read operation in bits [7:4].81	 */82	if (!priv->cont_read)83		*eccsr = MACRONIX_ECCSR_BF_LAST_PAGE(*eccsr);84	else85		*eccsr = MACRONIX_ECCSR_BF_ACCUMULATED_PAGES(*eccsr);86 87	return 0;88}89 90static int macronix_ecc_get_status(struct spinand_device *spinand,91				   u8 status)92{93	struct nand_device *nand = spinand_to_nand(spinand);94	u8 eccsr;95 96	switch (status & STATUS_ECC_MASK) {97	case STATUS_ECC_NO_BITFLIPS:98		return 0;99 100	case STATUS_ECC_UNCOR_ERROR:101		return -EBADMSG;102 103	case STATUS_ECC_HAS_BITFLIPS:104		/*105		 * Let's try to retrieve the real maximum number of bitflips106		 * in order to avoid forcing the wear-leveling layer to move107		 * data around if it's not necessary.108		 */109		if (macronix_get_eccsr(spinand, spinand->scratchbuf))110			return nanddev_get_ecc_conf(nand)->strength;111 112		eccsr = *spinand->scratchbuf;113		if (WARN_ON(eccsr > nanddev_get_ecc_conf(nand)->strength || !eccsr))114			return nanddev_get_ecc_conf(nand)->strength;115 116		return eccsr;117	default:118		break;119	}120 121	return -EINVAL;122}123 124static int macronix_set_cont_read(struct spinand_device *spinand, bool enable)125{126	struct macronix_priv *priv = spinand->priv;127	int ret;128 129	ret = spinand_upd_cfg(spinand, MACRONIX_CFG_CONT_READ,130			      enable ? MACRONIX_CFG_CONT_READ : 0);131	if (ret)132		return ret;133 134	priv->cont_read = enable;135 136	return 0;137}138 139static const struct spinand_info macronix_spinand_table[] = {140	SPINAND_INFO("MX35LF1GE4AB",141		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x12),142		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),143		     NAND_ECCREQ(4, 512),144		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,145					      &write_cache_variants,146					      &update_cache_variants),147		     SPINAND_HAS_QE_BIT,148		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,149				     macronix_ecc_get_status)),150	SPINAND_INFO("MX35LF2GE4AB",151		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x22),152		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),153		     NAND_ECCREQ(4, 512),154		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,155					      &write_cache_variants,156					      &update_cache_variants),157		     SPINAND_HAS_QE_BIT |158		     SPINAND_HAS_PROG_PLANE_SELECT_BIT |159		     SPINAND_HAS_READ_PLANE_SELECT_BIT,160		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),161	SPINAND_INFO("MX35LF2GE4AD",162		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x26, 0x03),163		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),164		     NAND_ECCREQ(8, 512),165		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,166					      &write_cache_variants,167					      &update_cache_variants),168		     SPINAND_HAS_QE_BIT,169		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,170				     macronix_ecc_get_status),171		     SPINAND_CONT_READ(macronix_set_cont_read)),172	SPINAND_INFO("MX35LF4GE4AD",173		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x37, 0x03),174		     NAND_MEMORG(1, 4096, 128, 64, 2048, 40, 1, 1, 1),175		     NAND_ECCREQ(8, 512),176		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,177					      &write_cache_variants,178					      &update_cache_variants),179		     SPINAND_HAS_QE_BIT,180		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,181				     macronix_ecc_get_status),182		     SPINAND_CONT_READ(macronix_set_cont_read)),183	SPINAND_INFO("MX35LF1G24AD",184		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14, 0x03),185		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),186		     NAND_ECCREQ(8, 512),187		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,188					      &write_cache_variants,189					      &update_cache_variants),190		     SPINAND_HAS_QE_BIT,191		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),192	SPINAND_INFO("MX35LF2G24AD",193		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24, 0x03),194		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),195		     NAND_ECCREQ(8, 512),196		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,197					      &write_cache_variants,198					      &update_cache_variants),199		     SPINAND_HAS_QE_BIT |200		     SPINAND_HAS_PROG_PLANE_SELECT_BIT,201		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),202	SPINAND_INFO("MX35LF2G24AD-Z4I8",203		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x64, 0x03),204		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),205		     NAND_ECCREQ(8, 512),206		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,207					      &write_cache_variants,208					      &update_cache_variants),209		     SPINAND_HAS_QE_BIT,210		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),211	SPINAND_INFO("MX35LF4G24AD",212		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35, 0x03),213		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 2, 1, 1),214		     NAND_ECCREQ(8, 512),215		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,216					      &write_cache_variants,217					      &update_cache_variants),218		     SPINAND_HAS_QE_BIT |219		     SPINAND_HAS_PROG_PLANE_SELECT_BIT,220		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),221	SPINAND_INFO("MX35LF4G24AD-Z4I8",222		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x75, 0x03),223		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),224		     NAND_ECCREQ(8, 512),225		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,226					      &write_cache_variants,227					      &update_cache_variants),228		     SPINAND_HAS_QE_BIT,229		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),230	SPINAND_INFO("MX31LF1GE4BC",231		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x1e),232		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),233		     NAND_ECCREQ(8, 512),234		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,235					      &write_cache_variants,236					      &update_cache_variants),237		     SPINAND_HAS_QE_BIT,238		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,239				     macronix_ecc_get_status)),240	SPINAND_INFO("MX31UF1GE4BC",241		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x9e),242		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),243		     NAND_ECCREQ(8, 512),244		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,245					      &write_cache_variants,246					      &update_cache_variants),247		     SPINAND_HAS_QE_BIT,248		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,249				     macronix_ecc_get_status)),250 251	SPINAND_INFO("MX35LF2G14AC",252		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x20),253		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),254		     NAND_ECCREQ(4, 512),255		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,256					      &write_cache_variants,257					      &update_cache_variants),258		     SPINAND_HAS_QE_BIT |259		     SPINAND_HAS_PROG_PLANE_SELECT_BIT |260		     SPINAND_HAS_READ_PLANE_SELECT_BIT,261		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,262				     macronix_ecc_get_status)),263	SPINAND_INFO("MX35UF4G24AD",264		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xb5, 0x03),265		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 2, 1, 1),266		     NAND_ECCREQ(8, 512),267		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,268					      &write_cache_variants,269					      &update_cache_variants),270		     SPINAND_HAS_QE_BIT |271		     SPINAND_HAS_PROG_PLANE_SELECT_BIT,272		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,273				     macronix_ecc_get_status)),274	SPINAND_INFO("MX35UF4G24AD-Z4I8",275		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xf5, 0x03),276		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),277		     NAND_ECCREQ(8, 512),278		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,279					      &write_cache_variants,280					      &update_cache_variants),281		     SPINAND_HAS_QE_BIT,282		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,283				     macronix_ecc_get_status)),284	SPINAND_INFO("MX35UF4GE4AD",285		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xb7, 0x03),286		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),287		     NAND_ECCREQ(8, 512),288		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,289					      &write_cache_variants,290					      &update_cache_variants),291		     SPINAND_HAS_QE_BIT,292		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,293				     macronix_ecc_get_status),294		     SPINAND_CONT_READ(macronix_set_cont_read)),295	SPINAND_INFO("MX35UF2G14AC",296		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa0),297		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),298		     NAND_ECCREQ(4, 512),299		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,300					      &write_cache_variants,301					      &update_cache_variants),302		     SPINAND_HAS_QE_BIT |303		     SPINAND_HAS_PROG_PLANE_SELECT_BIT |304		     SPINAND_HAS_READ_PLANE_SELECT_BIT,305		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,306				     macronix_ecc_get_status)),307	SPINAND_INFO("MX35UF2G24AD",308		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa4, 0x03),309		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),310		     NAND_ECCREQ(8, 512),311		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,312					      &write_cache_variants,313					      &update_cache_variants),314		     SPINAND_HAS_QE_BIT |315		     SPINAND_HAS_PROG_PLANE_SELECT_BIT,316		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,317				     macronix_ecc_get_status)),318	SPINAND_INFO("MX35UF2G24AD-Z4I8",319		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xe4, 0x03),320		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),321		     NAND_ECCREQ(8, 512),322		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,323					      &write_cache_variants,324					      &update_cache_variants),325		     SPINAND_HAS_QE_BIT,326		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,327				     macronix_ecc_get_status)),328	SPINAND_INFO("MX35UF2GE4AD",329		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa6, 0x03),330		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),331		     NAND_ECCREQ(8, 512),332		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,333					      &write_cache_variants,334					      &update_cache_variants),335		     SPINAND_HAS_QE_BIT,336		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,337				     macronix_ecc_get_status),338		     SPINAND_CONT_READ(macronix_set_cont_read)),339	SPINAND_INFO("MX35UF2GE4AC",340		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa2, 0x01),341		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),342		     NAND_ECCREQ(4, 512),343		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,344					      &write_cache_variants,345					      &update_cache_variants),346		     SPINAND_HAS_QE_BIT,347		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,348				     macronix_ecc_get_status),349		     SPINAND_CONT_READ(macronix_set_cont_read)),350	SPINAND_INFO("MX35UF1G14AC",351		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x90),352		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),353		     NAND_ECCREQ(4, 512),354		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,355					      &write_cache_variants,356					      &update_cache_variants),357		     SPINAND_HAS_QE_BIT,358		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,359				     macronix_ecc_get_status)),360	SPINAND_INFO("MX35UF1G24AD",361		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x94, 0x03),362		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),363		     NAND_ECCREQ(8, 512),364		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,365					      &write_cache_variants,366					      &update_cache_variants),367		     SPINAND_HAS_QE_BIT,368		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,369				     macronix_ecc_get_status)),370	SPINAND_INFO("MX35UF1GE4AD",371		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x96, 0x03),372		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),373		     NAND_ECCREQ(8, 512),374		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,375					      &write_cache_variants,376					      &update_cache_variants),377		     SPINAND_HAS_QE_BIT,378		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,379				     macronix_ecc_get_status),380		     SPINAND_CONT_READ(macronix_set_cont_read)),381	SPINAND_INFO("MX35UF1GE4AC",382		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x92, 0x01),383		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),384		     NAND_ECCREQ(4, 512),385		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,386					      &write_cache_variants,387					      &update_cache_variants),388		     SPINAND_HAS_QE_BIT,389		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,390				     macronix_ecc_get_status),391		     SPINAND_CONT_READ(macronix_set_cont_read)),392	SPINAND_INFO("MX31LF2GE4BC",393		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x2e),394		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),395		     NAND_ECCREQ(8, 512),396		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,397					      &write_cache_variants,398					      &update_cache_variants),399		     SPINAND_HAS_QE_BIT,400		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,401				     macronix_ecc_get_status)),402	SPINAND_INFO("MX3UF2GE4BC",403		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xae),404		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),405		     NAND_ECCREQ(8, 512),406		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,407					      &write_cache_variants,408					      &update_cache_variants),409		     SPINAND_HAS_QE_BIT,410		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,411				     macronix_ecc_get_status)),412};413 414static int macronix_spinand_init(struct spinand_device *spinand)415{416	struct macronix_priv *priv;417 418	priv = kzalloc(sizeof(*priv), GFP_KERNEL);419	if (!priv)420		return -ENOMEM;421 422	spinand->priv = priv;423 424	return 0;425}426 427static void macronix_spinand_cleanup(struct spinand_device *spinand)428{429	kfree(spinand->priv);430}431 432static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = {433	.init = macronix_spinand_init,434	.cleanup = macronix_spinand_cleanup,435};436 437const struct spinand_manufacturer macronix_spinand_manufacturer = {438	.id = SPINAND_MFR_MACRONIX,439	.name = "Macronix",440	.chips = macronix_spinand_table,441	.nchips = ARRAY_SIZE(macronix_spinand_table),442	.ops = &macronix_spinand_manuf_ops,443};444