162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2005, Intec Automation Inc.
462306a36Sopenharmony_ci * Copyright (C) 2014, Freescale Semiconductor, Inc.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/mtd/spi-nor.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include "core.h"
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_cistatic int
1262306a36Sopenharmony_ciis25lp256_post_bfpt_fixups(struct spi_nor *nor,
1362306a36Sopenharmony_ci			   const struct sfdp_parameter_header *bfpt_header,
1462306a36Sopenharmony_ci			   const struct sfdp_bfpt *bfpt)
1562306a36Sopenharmony_ci{
1662306a36Sopenharmony_ci	/*
1762306a36Sopenharmony_ci	 * IS25LP256 supports 4B opcodes, but the BFPT advertises
1862306a36Sopenharmony_ci	 * BFPT_DWORD1_ADDRESS_BYTES_3_ONLY.
1962306a36Sopenharmony_ci	 * Overwrite the number of address bytes advertised by the BFPT.
2062306a36Sopenharmony_ci	 */
2162306a36Sopenharmony_ci	if ((bfpt->dwords[SFDP_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) ==
2262306a36Sopenharmony_ci		BFPT_DWORD1_ADDRESS_BYTES_3_ONLY)
2362306a36Sopenharmony_ci		nor->params->addr_nbytes = 4;
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci	return 0;
2662306a36Sopenharmony_ci}
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistatic const struct spi_nor_fixups is25lp256_fixups = {
2962306a36Sopenharmony_ci	.post_bfpt = is25lp256_post_bfpt_fixups,
3062306a36Sopenharmony_ci};
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_cistatic int pm25lv_nor_late_init(struct spi_nor *nor)
3362306a36Sopenharmony_ci{
3462306a36Sopenharmony_ci	struct spi_nor_erase_map *map = &nor->params->erase_map;
3562306a36Sopenharmony_ci	int i;
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	/* The PM25LV series has a different 4k sector erase opcode */
3862306a36Sopenharmony_ci	for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++)
3962306a36Sopenharmony_ci		if (map->erase_type[i].size == 4096)
4062306a36Sopenharmony_ci			map->erase_type[i].opcode = SPINOR_OP_BE_4K_PMC;
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	return 0;
4362306a36Sopenharmony_ci}
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cistatic const struct spi_nor_fixups pm25lv_nor_fixups = {
4662306a36Sopenharmony_ci	.late_init = pm25lv_nor_late_init,
4762306a36Sopenharmony_ci};
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistatic const struct flash_info issi_nor_parts[] = {
5062306a36Sopenharmony_ci	/* ISSI */
5162306a36Sopenharmony_ci	{ "is25cd512",  INFO(0x7f9d20, 0, 32 * 1024,   2)
5262306a36Sopenharmony_ci		NO_SFDP_FLAGS(SECT_4K) },
5362306a36Sopenharmony_ci	{ "is25lq040b", INFO(0x9d4013, 0, 64 * 1024,   8)
5462306a36Sopenharmony_ci		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
5562306a36Sopenharmony_ci	{ "is25lp016d", INFO(0x9d6015, 0, 64 * 1024,  32)
5662306a36Sopenharmony_ci		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
5762306a36Sopenharmony_ci	{ "is25lp080d", INFO(0x9d6014, 0, 64 * 1024,  16)
5862306a36Sopenharmony_ci		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
5962306a36Sopenharmony_ci	{ "is25lp032",  INFO(0x9d6016, 0, 64 * 1024,  64)
6062306a36Sopenharmony_ci		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ) },
6162306a36Sopenharmony_ci	{ "is25lp064",  INFO(0x9d6017, 0, 64 * 1024, 128)
6262306a36Sopenharmony_ci		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ) },
6362306a36Sopenharmony_ci	{ "is25lp128",  INFO(0x9d6018, 0, 64 * 1024, 256)
6462306a36Sopenharmony_ci		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ) },
6562306a36Sopenharmony_ci	{ "is25lp256",  INFO(0x9d6019, 0, 64 * 1024, 512)
6662306a36Sopenharmony_ci		PARSE_SFDP
6762306a36Sopenharmony_ci		FIXUP_FLAGS(SPI_NOR_4B_OPCODES)
6862306a36Sopenharmony_ci		.fixups = &is25lp256_fixups },
6962306a36Sopenharmony_ci	{ "is25wp032",  INFO(0x9d7016, 0, 64 * 1024,  64)
7062306a36Sopenharmony_ci		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
7162306a36Sopenharmony_ci	{ "is25wp064",  INFO(0x9d7017, 0, 64 * 1024, 128)
7262306a36Sopenharmony_ci		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
7362306a36Sopenharmony_ci	{ "is25wp128",  INFO(0x9d7018, 0, 64 * 1024, 256)
7462306a36Sopenharmony_ci		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
7562306a36Sopenharmony_ci	{ "is25wp256", INFO(0x9d7019, 0, 0, 0)
7662306a36Sopenharmony_ci		PARSE_SFDP
7762306a36Sopenharmony_ci		FIXUP_FLAGS(SPI_NOR_4B_OPCODES)
7862306a36Sopenharmony_ci		FLAGS(SPI_NOR_QUAD_PP)
7962306a36Sopenharmony_ci		.fixups = &is25lp256_fixups },
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	/* PMC */
8262306a36Sopenharmony_ci	{ "pm25lv512",   INFO(0,        0, 32 * 1024,    2)
8362306a36Sopenharmony_ci		NO_SFDP_FLAGS(SECT_4K)
8462306a36Sopenharmony_ci		.fixups = &pm25lv_nor_fixups
8562306a36Sopenharmony_ci	},
8662306a36Sopenharmony_ci	{ "pm25lv010",   INFO(0,        0, 32 * 1024,    4)
8762306a36Sopenharmony_ci		NO_SFDP_FLAGS(SECT_4K)
8862306a36Sopenharmony_ci		.fixups = &pm25lv_nor_fixups
8962306a36Sopenharmony_ci	},
9062306a36Sopenharmony_ci	{ "pm25lq032",   INFO(0x7f9d46, 0, 64 * 1024,   64)
9162306a36Sopenharmony_ci		NO_SFDP_FLAGS(SECT_4K) },
9262306a36Sopenharmony_ci};
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistatic void issi_nor_default_init(struct spi_nor *nor)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistatic const struct spi_nor_fixups issi_fixups = {
10062306a36Sopenharmony_ci	.default_init = issi_nor_default_init,
10162306a36Sopenharmony_ci};
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ciconst struct spi_nor_manufacturer spi_nor_issi = {
10462306a36Sopenharmony_ci	.name = "issi",
10562306a36Sopenharmony_ci	.parts = issi_nor_parts,
10662306a36Sopenharmony_ci	.nparts = ARRAY_SIZE(issi_nor_parts),
10762306a36Sopenharmony_ci	.fixups = &issi_fixups,
10862306a36Sopenharmony_ci};
109