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
11static int
12is25lp256_post_bfpt_fixups(struct spi_nor *nor,
13			   const struct sfdp_parameter_header *bfpt_header,
14			   const struct sfdp_bfpt *bfpt)
15{
16	/*
17	 * IS25LP256 supports 4B opcodes, but the BFPT advertises
18	 * BFPT_DWORD1_ADDRESS_BYTES_3_ONLY.
19	 * Overwrite the number of address bytes advertised by the BFPT.
20	 */
21	if ((bfpt->dwords[SFDP_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) ==
22		BFPT_DWORD1_ADDRESS_BYTES_3_ONLY)
23		nor->params->addr_nbytes = 4;
24
25	return 0;
26}
27
28static const struct spi_nor_fixups is25lp256_fixups = {
29	.post_bfpt = is25lp256_post_bfpt_fixups,
30};
31
32static int pm25lv_nor_late_init(struct spi_nor *nor)
33{
34	struct spi_nor_erase_map *map = &nor->params->erase_map;
35	int i;
36
37	/* The PM25LV series has a different 4k sector erase opcode */
38	for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++)
39		if (map->erase_type[i].size == 4096)
40			map->erase_type[i].opcode = SPINOR_OP_BE_4K_PMC;
41
42	return 0;
43}
44
45static const struct spi_nor_fixups pm25lv_nor_fixups = {
46	.late_init = pm25lv_nor_late_init,
47};
48
49static const struct flash_info issi_nor_parts[] = {
50	/* ISSI */
51	{ "is25cd512",  INFO(0x7f9d20, 0, 32 * 1024,   2)
52		NO_SFDP_FLAGS(SECT_4K) },
53	{ "is25lq040b", INFO(0x9d4013, 0, 64 * 1024,   8)
54		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
55	{ "is25lp016d", INFO(0x9d6015, 0, 64 * 1024,  32)
56		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
57	{ "is25lp080d", INFO(0x9d6014, 0, 64 * 1024,  16)
58		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
59	{ "is25lp032",  INFO(0x9d6016, 0, 64 * 1024,  64)
60		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ) },
61	{ "is25lp064",  INFO(0x9d6017, 0, 64 * 1024, 128)
62		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ) },
63	{ "is25lp128",  INFO(0x9d6018, 0, 64 * 1024, 256)
64		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ) },
65	{ "is25lp256",  INFO(0x9d6019, 0, 64 * 1024, 512)
66		PARSE_SFDP
67		FIXUP_FLAGS(SPI_NOR_4B_OPCODES)
68		.fixups = &is25lp256_fixups },
69	{ "is25wp032",  INFO(0x9d7016, 0, 64 * 1024,  64)
70		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
71	{ "is25wp064",  INFO(0x9d7017, 0, 64 * 1024, 128)
72		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
73	{ "is25wp128",  INFO(0x9d7018, 0, 64 * 1024, 256)
74		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
75	{ "is25wp256", INFO(0x9d7019, 0, 0, 0)
76		PARSE_SFDP
77		FIXUP_FLAGS(SPI_NOR_4B_OPCODES)
78		FLAGS(SPI_NOR_QUAD_PP)
79		.fixups = &is25lp256_fixups },
80
81	/* PMC */
82	{ "pm25lv512",   INFO(0,        0, 32 * 1024,    2)
83		NO_SFDP_FLAGS(SECT_4K)
84		.fixups = &pm25lv_nor_fixups
85	},
86	{ "pm25lv010",   INFO(0,        0, 32 * 1024,    4)
87		NO_SFDP_FLAGS(SECT_4K)
88		.fixups = &pm25lv_nor_fixups
89	},
90	{ "pm25lq032",   INFO(0x7f9d46, 0, 64 * 1024,   64)
91		NO_SFDP_FLAGS(SECT_4K) },
92};
93
94static void issi_nor_default_init(struct spi_nor *nor)
95{
96	nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
97}
98
99static const struct spi_nor_fixups issi_fixups = {
100	.default_init = issi_nor_default_init,
101};
102
103const struct spi_nor_manufacturer spi_nor_issi = {
104	.name = "issi",
105	.parts = issi_nor_parts,
106	.nparts = ARRAY_SIZE(issi_nor_parts),
107	.fixups = &issi_fixups,
108};
109