cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

micron-st.c (14373B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2005, Intec Automation Inc.
      4 * Copyright (C) 2014, Freescale Semiconductor, Inc.
      5 */
      6
      7#include <linux/mtd/spi-nor.h>
      8
      9#include "core.h"
     10
     11/* flash_info mfr_flag. Used to read proprietary FSR register. */
     12#define USE_FSR		BIT(0)
     13
     14#define SPINOR_OP_RDFSR		0x70	/* Read flag status register */
     15#define SPINOR_OP_CLFSR		0x50	/* Clear flag status register */
     16#define SPINOR_OP_MT_DTR_RD	0xfd	/* Fast Read opcode in DTR mode */
     17#define SPINOR_OP_MT_RD_ANY_REG	0x85	/* Read volatile register */
     18#define SPINOR_OP_MT_WR_ANY_REG	0x81	/* Write volatile register */
     19#define SPINOR_REG_MT_CFR0V	0x00	/* For setting octal DTR mode */
     20#define SPINOR_REG_MT_CFR1V	0x01	/* For setting dummy cycles */
     21#define SPINOR_REG_MT_CFR1V_DEF	0x1f	/* Default dummy cycles */
     22#define SPINOR_MT_OCT_DTR	0xe7	/* Enable Octal DTR. */
     23#define SPINOR_MT_EXSPI		0xff	/* Enable Extended SPI (default) */
     24
     25/* Flag Status Register bits */
     26#define FSR_READY		BIT(7)	/* Device status, 0 = Busy, 1 = Ready */
     27#define FSR_E_ERR		BIT(5)	/* Erase operation status */
     28#define FSR_P_ERR		BIT(4)	/* Program operation status */
     29#define FSR_PT_ERR		BIT(1)	/* Protection error bit */
     30
     31/* Micron ST SPI NOR flash operations. */
     32#define MICRON_ST_NOR_WR_ANY_REG_OP(naddr, addr, ndata, buf)		\
     33	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_MT_WR_ANY_REG, 0),		\
     34		   SPI_MEM_OP_ADDR(naddr, addr, 0),			\
     35		   SPI_MEM_OP_NO_DUMMY,					\
     36		   SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
     37
     38#define MICRON_ST_RDFSR_OP(buf)						\
     39	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDFSR, 0),			\
     40		   SPI_MEM_OP_NO_ADDR,					\
     41		   SPI_MEM_OP_NO_DUMMY,					\
     42		   SPI_MEM_OP_DATA_IN(1, buf, 0))
     43
     44#define MICRON_ST_CLFSR_OP						\
     45	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLFSR, 0),			\
     46		   SPI_MEM_OP_NO_ADDR,					\
     47		   SPI_MEM_OP_NO_DUMMY,					\
     48		   SPI_MEM_OP_NO_DATA)
     49
     50static int micron_st_nor_octal_dtr_en(struct spi_nor *nor)
     51{
     52	struct spi_mem_op op;
     53	u8 *buf = nor->bouncebuf;
     54	int ret;
     55
     56	/* Use 20 dummy cycles for memory array reads. */
     57	*buf = 20;
     58	op = (struct spi_mem_op)
     59		MICRON_ST_NOR_WR_ANY_REG_OP(3, SPINOR_REG_MT_CFR1V, 1, buf);
     60	ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
     61	if (ret)
     62		return ret;
     63
     64	buf[0] = SPINOR_MT_OCT_DTR;
     65	op = (struct spi_mem_op)
     66		MICRON_ST_NOR_WR_ANY_REG_OP(3, SPINOR_REG_MT_CFR0V, 1, buf);
     67	ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
     68	if (ret)
     69		return ret;
     70
     71	/* Read flash ID to make sure the switch was successful. */
     72	ret = spi_nor_read_id(nor, 0, 8, buf, SNOR_PROTO_8_8_8_DTR);
     73	if (ret) {
     74		dev_dbg(nor->dev, "error %d reading JEDEC ID after enabling 8D-8D-8D mode\n", ret);
     75		return ret;
     76	}
     77
     78	if (memcmp(buf, nor->info->id, nor->info->id_len))
     79		return -EINVAL;
     80
     81	return 0;
     82}
     83
     84static int micron_st_nor_octal_dtr_dis(struct spi_nor *nor)
     85{
     86	struct spi_mem_op op;
     87	u8 *buf = nor->bouncebuf;
     88	int ret;
     89
     90	/*
     91	 * The register is 1-byte wide, but 1-byte transactions are not allowed
     92	 * in 8D-8D-8D mode. The next register is the dummy cycle configuration
     93	 * register. Since the transaction needs to be at least 2 bytes wide,
     94	 * set the next register to its default value. This also makes sense
     95	 * because the value was changed when enabling 8D-8D-8D mode, it should
     96	 * be reset when disabling.
     97	 */
     98	buf[0] = SPINOR_MT_EXSPI;
     99	buf[1] = SPINOR_REG_MT_CFR1V_DEF;
    100	op = (struct spi_mem_op)
    101		MICRON_ST_NOR_WR_ANY_REG_OP(4, SPINOR_REG_MT_CFR0V, 2, buf);
    102	ret = spi_nor_write_any_volatile_reg(nor, &op, SNOR_PROTO_8_8_8_DTR);
    103	if (ret)
    104		return ret;
    105
    106	/* Read flash ID to make sure the switch was successful. */
    107	ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
    108	if (ret) {
    109		dev_dbg(nor->dev, "error %d reading JEDEC ID after disabling 8D-8D-8D mode\n", ret);
    110		return ret;
    111	}
    112
    113	if (memcmp(buf, nor->info->id, nor->info->id_len))
    114		return -EINVAL;
    115
    116	return 0;
    117}
    118
    119static int micron_st_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
    120{
    121	return enable ? micron_st_nor_octal_dtr_en(nor) :
    122			micron_st_nor_octal_dtr_dis(nor);
    123}
    124
    125static void mt35xu512aba_default_init(struct spi_nor *nor)
    126{
    127	nor->params->octal_dtr_enable = micron_st_nor_octal_dtr_enable;
    128}
    129
    130static void mt35xu512aba_post_sfdp_fixup(struct spi_nor *nor)
    131{
    132	/* Set the Fast Read settings. */
    133	nor->params->hwcaps.mask |= SNOR_HWCAPS_READ_8_8_8_DTR;
    134	spi_nor_set_read_settings(&nor->params->reads[SNOR_CMD_READ_8_8_8_DTR],
    135				  0, 20, SPINOR_OP_MT_DTR_RD,
    136				  SNOR_PROTO_8_8_8_DTR);
    137
    138	nor->cmd_ext_type = SPI_NOR_EXT_REPEAT;
    139	nor->params->rdsr_dummy = 8;
    140	nor->params->rdsr_addr_nbytes = 0;
    141
    142	/*
    143	 * The BFPT quad enable field is set to a reserved value so the quad
    144	 * enable function is ignored by spi_nor_parse_bfpt(). Make sure we
    145	 * disable it.
    146	 */
    147	nor->params->quad_enable = NULL;
    148}
    149
    150static const struct spi_nor_fixups mt35xu512aba_fixups = {
    151	.default_init = mt35xu512aba_default_init,
    152	.post_sfdp = mt35xu512aba_post_sfdp_fixup,
    153};
    154
    155static const struct flash_info micron_nor_parts[] = {
    156	{ "mt35xu512aba", INFO(0x2c5b1a, 0, 128 * 1024, 512)
    157		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_OCTAL_READ |
    158			   SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP)
    159		FIXUP_FLAGS(SPI_NOR_4B_OPCODES | SPI_NOR_IO_MODE_EN_VOLATILE)
    160		MFR_FLAGS(USE_FSR)
    161		.fixups = &mt35xu512aba_fixups
    162	},
    163	{ "mt35xu02g", INFO(0x2c5b1c, 0, 128 * 1024, 2048)
    164		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_OCTAL_READ)
    165		FIXUP_FLAGS(SPI_NOR_4B_OPCODES)
    166		MFR_FLAGS(USE_FSR)
    167	},
    168};
    169
    170static const struct flash_info st_nor_parts[] = {
    171	{ "n25q016a",	 INFO(0x20bb15, 0, 64 * 1024,   32)
    172		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_QUAD_READ) },
    173	{ "n25q032",	 INFO(0x20ba16, 0, 64 * 1024,   64)
    174		NO_SFDP_FLAGS(SPI_NOR_QUAD_READ) },
    175	{ "n25q032a",	 INFO(0x20bb16, 0, 64 * 1024,   64)
    176		NO_SFDP_FLAGS(SPI_NOR_QUAD_READ) },
    177	{ "n25q064",     INFO(0x20ba17, 0, 64 * 1024,  128)
    178		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_QUAD_READ) },
    179	{ "n25q064a",    INFO(0x20bb17, 0, 64 * 1024,  128)
    180		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_QUAD_READ) },
    181	{ "n25q128a11",  INFO(0x20bb18, 0, 64 * 1024,  256)
    182		FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP |
    183		      SPI_NOR_BP3_SR_BIT6)
    184		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_QUAD_READ)
    185		MFR_FLAGS(USE_FSR)
    186	},
    187	{ "n25q128a13",  INFO(0x20ba18, 0, 64 * 1024,  256)
    188		FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP |
    189		      SPI_NOR_BP3_SR_BIT6)
    190		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_QUAD_READ)
    191		MFR_FLAGS(USE_FSR)
    192	},
    193	{ "mt25ql256a",  INFO6(0x20ba19, 0x104400, 64 * 1024,  512)
    194		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
    195		FIXUP_FLAGS(SPI_NOR_4B_OPCODES)
    196		MFR_FLAGS(USE_FSR)
    197	},
    198	{ "n25q256a",    INFO(0x20ba19, 0, 64 * 1024,  512)
    199		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ |
    200			      SPI_NOR_QUAD_READ)
    201		MFR_FLAGS(USE_FSR)
    202	},
    203	{ "mt25qu256a",  INFO6(0x20bb19, 0x104400, 64 * 1024,  512)
    204		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
    205		FIXUP_FLAGS(SPI_NOR_4B_OPCODES)
    206		MFR_FLAGS(USE_FSR)
    207	},
    208	{ "n25q256ax1",  INFO(0x20bb19, 0, 64 * 1024,  512)
    209		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_QUAD_READ)
    210		MFR_FLAGS(USE_FSR)
    211	},
    212	{ "mt25ql512a",  INFO6(0x20ba20, 0x104400, 64 * 1024, 1024)
    213		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
    214		FIXUP_FLAGS(SPI_NOR_4B_OPCODES)
    215		MFR_FLAGS(USE_FSR)
    216	},
    217	{ "n25q512ax3",  INFO(0x20ba20, 0, 64 * 1024, 1024)
    218		FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP |
    219		      SPI_NOR_BP3_SR_BIT6)
    220		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_QUAD_READ)
    221		MFR_FLAGS(USE_FSR)
    222	},
    223	{ "mt25qu512a",  INFO6(0x20bb20, 0x104400, 64 * 1024, 1024)
    224		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
    225		FIXUP_FLAGS(SPI_NOR_4B_OPCODES)
    226		MFR_FLAGS(USE_FSR)
    227	},
    228	{ "n25q512a",    INFO(0x20bb20, 0, 64 * 1024, 1024)
    229		FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP |
    230		      SPI_NOR_BP3_SR_BIT6)
    231		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_QUAD_READ)
    232		MFR_FLAGS(USE_FSR)
    233	},
    234	{ "n25q00",      INFO(0x20ba21, 0, 64 * 1024, 2048)
    235		FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP |
    236		      SPI_NOR_BP3_SR_BIT6 | NO_CHIP_ERASE)
    237		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_QUAD_READ)
    238		MFR_FLAGS(USE_FSR)
    239	},
    240	{ "n25q00a",     INFO(0x20bb21, 0, 64 * 1024, 2048)
    241		FLAGS(NO_CHIP_ERASE)
    242		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_QUAD_READ)
    243		MFR_FLAGS(USE_FSR)
    244	},
    245	{ "mt25ql02g",   INFO(0x20ba22, 0, 64 * 1024, 4096)
    246		FLAGS(NO_CHIP_ERASE)
    247		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_QUAD_READ)
    248		MFR_FLAGS(USE_FSR)
    249	},
    250	{ "mt25qu02g",   INFO(0x20bb22, 0, 64 * 1024, 4096)
    251		FLAGS(NO_CHIP_ERASE)
    252		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ |
    253			      SPI_NOR_QUAD_READ)
    254		MFR_FLAGS(USE_FSR)
    255	},
    256
    257	{ "m25p05",  INFO(0x202010,  0,  32 * 1024,   2) },
    258	{ "m25p10",  INFO(0x202011,  0,  32 * 1024,   4) },
    259	{ "m25p20",  INFO(0x202012,  0,  64 * 1024,   4) },
    260	{ "m25p40",  INFO(0x202013,  0,  64 * 1024,   8) },
    261	{ "m25p80",  INFO(0x202014,  0,  64 * 1024,  16) },
    262	{ "m25p16",  INFO(0x202015,  0,  64 * 1024,  32) },
    263	{ "m25p32",  INFO(0x202016,  0,  64 * 1024,  64) },
    264	{ "m25p64",  INFO(0x202017,  0,  64 * 1024, 128) },
    265	{ "m25p128", INFO(0x202018,  0, 256 * 1024,  64) },
    266
    267	{ "m25p05-nonjedec",  INFO(0, 0,  32 * 1024,   2) },
    268	{ "m25p10-nonjedec",  INFO(0, 0,  32 * 1024,   4) },
    269	{ "m25p20-nonjedec",  INFO(0, 0,  64 * 1024,   4) },
    270	{ "m25p40-nonjedec",  INFO(0, 0,  64 * 1024,   8) },
    271	{ "m25p80-nonjedec",  INFO(0, 0,  64 * 1024,  16) },
    272	{ "m25p16-nonjedec",  INFO(0, 0,  64 * 1024,  32) },
    273	{ "m25p32-nonjedec",  INFO(0, 0,  64 * 1024,  64) },
    274	{ "m25p64-nonjedec",  INFO(0, 0,  64 * 1024, 128) },
    275	{ "m25p128-nonjedec", INFO(0, 0, 256 * 1024,  64) },
    276
    277	{ "m45pe10", INFO(0x204011,  0, 64 * 1024,    2) },
    278	{ "m45pe80", INFO(0x204014,  0, 64 * 1024,   16) },
    279	{ "m45pe16", INFO(0x204015,  0, 64 * 1024,   32) },
    280
    281	{ "m25pe20", INFO(0x208012,  0, 64 * 1024,  4) },
    282	{ "m25pe80", INFO(0x208014,  0, 64 * 1024, 16) },
    283	{ "m25pe16", INFO(0x208015,  0, 64 * 1024, 32)
    284		NO_SFDP_FLAGS(SECT_4K) },
    285
    286	{ "m25px16",    INFO(0x207115,  0, 64 * 1024, 32)
    287		NO_SFDP_FLAGS(SECT_4K) },
    288	{ "m25px32",    INFO(0x207116,  0, 64 * 1024, 64)
    289		NO_SFDP_FLAGS(SECT_4K) },
    290	{ "m25px32-s0", INFO(0x207316,  0, 64 * 1024, 64)
    291		NO_SFDP_FLAGS(SECT_4K) },
    292	{ "m25px32-s1", INFO(0x206316,  0, 64 * 1024, 64)
    293		NO_SFDP_FLAGS(SECT_4K) },
    294	{ "m25px64",    INFO(0x207117,  0, 64 * 1024, 128) },
    295	{ "m25px80",    INFO(0x207114,  0, 64 * 1024, 16) },
    296};
    297
    298/**
    299 * micron_st_nor_set_4byte_addr_mode() - Set 4-byte address mode for ST and
    300 * Micron flashes.
    301 * @nor:	pointer to 'struct spi_nor'.
    302 * @enable:	true to enter the 4-byte address mode, false to exit the 4-byte
    303 *		address mode.
    304 *
    305 * Return: 0 on success, -errno otherwise.
    306 */
    307static int micron_st_nor_set_4byte_addr_mode(struct spi_nor *nor, bool enable)
    308{
    309	int ret;
    310
    311	ret = spi_nor_write_enable(nor);
    312	if (ret)
    313		return ret;
    314
    315	ret = spi_nor_set_4byte_addr_mode(nor, enable);
    316	if (ret)
    317		return ret;
    318
    319	return spi_nor_write_disable(nor);
    320}
    321
    322/**
    323 * micron_st_nor_read_fsr() - Read the Flag Status Register.
    324 * @nor:	pointer to 'struct spi_nor'
    325 * @fsr:	pointer to a DMA-able buffer where the value of the
    326 *              Flag Status Register will be written. Should be at least 2
    327 *              bytes.
    328 *
    329 * Return: 0 on success, -errno otherwise.
    330 */
    331static int micron_st_nor_read_fsr(struct spi_nor *nor, u8 *fsr)
    332{
    333	int ret;
    334
    335	if (nor->spimem) {
    336		struct spi_mem_op op = MICRON_ST_RDFSR_OP(fsr);
    337
    338		if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) {
    339			op.addr.nbytes = nor->params->rdsr_addr_nbytes;
    340			op.dummy.nbytes = nor->params->rdsr_dummy;
    341			/*
    342			 * We don't want to read only one byte in DTR mode. So,
    343			 * read 2 and then discard the second byte.
    344			 */
    345			op.data.nbytes = 2;
    346		}
    347
    348		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
    349
    350		ret = spi_mem_exec_op(nor->spimem, &op);
    351	} else {
    352		ret = spi_nor_controller_ops_read_reg(nor, SPINOR_OP_RDFSR, fsr,
    353						      1);
    354	}
    355
    356	if (ret)
    357		dev_dbg(nor->dev, "error %d reading FSR\n", ret);
    358
    359	return ret;
    360}
    361
    362/**
    363 * micron_st_nor_clear_fsr() - Clear the Flag Status Register.
    364 * @nor:	pointer to 'struct spi_nor'.
    365 */
    366static void micron_st_nor_clear_fsr(struct spi_nor *nor)
    367{
    368	int ret;
    369
    370	if (nor->spimem) {
    371		struct spi_mem_op op = MICRON_ST_CLFSR_OP;
    372
    373		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
    374
    375		ret = spi_mem_exec_op(nor->spimem, &op);
    376	} else {
    377		ret = spi_nor_controller_ops_write_reg(nor, SPINOR_OP_CLFSR,
    378						       NULL, 0);
    379	}
    380
    381	if (ret)
    382		dev_dbg(nor->dev, "error %d clearing FSR\n", ret);
    383}
    384
    385/**
    386 * micron_st_nor_ready() - Query the Status Register as well as the Flag Status
    387 * Register to see if the flash is ready for new commands. If there are any
    388 * errors in the FSR clear them.
    389 * @nor:	pointer to 'struct spi_nor'.
    390 *
    391 * Return: 1 if ready, 0 if not ready, -errno on errors.
    392 */
    393static int micron_st_nor_ready(struct spi_nor *nor)
    394{
    395	int sr_ready, ret;
    396
    397	sr_ready = spi_nor_sr_ready(nor);
    398	if (sr_ready < 0)
    399		return sr_ready;
    400
    401	ret = micron_st_nor_read_fsr(nor, nor->bouncebuf);
    402	if (ret)
    403		return ret;
    404
    405	if (nor->bouncebuf[0] & (FSR_E_ERR | FSR_P_ERR)) {
    406		if (nor->bouncebuf[0] & FSR_E_ERR)
    407			dev_err(nor->dev, "Erase operation failed.\n");
    408		else
    409			dev_err(nor->dev, "Program operation failed.\n");
    410
    411		if (nor->bouncebuf[0] & FSR_PT_ERR)
    412			dev_err(nor->dev,
    413				"Attempted to modify a protected sector.\n");
    414
    415		micron_st_nor_clear_fsr(nor);
    416
    417		/*
    418		 * WEL bit remains set to one when an erase or page program
    419		 * error occurs. Issue a Write Disable command to protect
    420		 * against inadvertent writes that can possibly corrupt the
    421		 * contents of the memory.
    422		 */
    423		ret = spi_nor_write_disable(nor);
    424		if (ret)
    425			return ret;
    426
    427		return -EIO;
    428	}
    429
    430	return sr_ready && !!(nor->bouncebuf[0] & FSR_READY);
    431}
    432
    433static void micron_st_nor_default_init(struct spi_nor *nor)
    434{
    435	nor->flags |= SNOR_F_HAS_LOCK;
    436	nor->flags &= ~SNOR_F_HAS_16BIT_SR;
    437	nor->params->quad_enable = NULL;
    438	nor->params->set_4byte_addr_mode = micron_st_nor_set_4byte_addr_mode;
    439}
    440
    441static void micron_st_nor_late_init(struct spi_nor *nor)
    442{
    443	if (nor->info->mfr_flags & USE_FSR)
    444		nor->params->ready = micron_st_nor_ready;
    445}
    446
    447static const struct spi_nor_fixups micron_st_nor_fixups = {
    448	.default_init = micron_st_nor_default_init,
    449	.late_init = micron_st_nor_late_init,
    450};
    451
    452const struct spi_nor_manufacturer spi_nor_micron = {
    453	.name = "micron",
    454	.parts = micron_nor_parts,
    455	.nparts = ARRAY_SIZE(micron_nor_parts),
    456	.fixups = &micron_st_nor_fixups,
    457};
    458
    459const struct spi_nor_manufacturer spi_nor_st = {
    460	.name = "st",
    461	.parts = st_nor_parts,
    462	.nparts = ARRAY_SIZE(st_nor_parts),
    463	.fixups = &micron_st_nor_fixups,
    464};