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
12mx25l25635_post_bfpt_fixups(struct spi_nor *nor,
13			    const struct sfdp_parameter_header *bfpt_header,
14			    const struct sfdp_bfpt *bfpt)
15{
16	/*
17	 * MX25L25635F supports 4B opcodes but MX25L25635E does not.
18	 * Unfortunately, Macronix has re-used the same JEDEC ID for both
19	 * variants which prevents us from defining a new entry in the parts
20	 * table.
21	 * We need a way to differentiate MX25L25635E and MX25L25635F, and it
22	 * seems that the F version advertises support for Fast Read 4-4-4 in
23	 * its BFPT table.
24	 */
25	if (bfpt->dwords[SFDP_DWORD(5)] & BFPT_DWORD5_FAST_READ_4_4_4)
26		nor->flags |= SNOR_F_4B_OPCODES;
27
28	return 0;
29}
30
31static const struct spi_nor_fixups mx25l25635_fixups = {
32	.post_bfpt = mx25l25635_post_bfpt_fixups,
33};
34
35static const struct flash_info macronix_nor_parts[] = {
36	{
37		.id = SNOR_ID(0xc2, 0x20, 0x10),
38		.name = "mx25l512e",
39		.size = SZ_64K,
40		.no_sfdp_flags = SECT_4K,
41	}, {
42		.id = SNOR_ID(0xc2, 0x20, 0x12),
43		.name = "mx25l2005a",
44		.size = SZ_256K,
45		.no_sfdp_flags = SECT_4K,
46	}, {
47		.id = SNOR_ID(0xc2, 0x20, 0x13),
48		.name = "mx25l4005a",
49		.size = SZ_512K,
50		.no_sfdp_flags = SECT_4K,
51	}, {
52		.id = SNOR_ID(0xc2, 0x20, 0x14),
53		.name = "mx25l8005",
54		.size = SZ_1M,
55	}, {
56		.id = SNOR_ID(0xc2, 0x20, 0x15),
57		.name = "mx25l1606e",
58		.size = SZ_2M,
59		.no_sfdp_flags = SECT_4K,
60	}, {
61		.id = SNOR_ID(0xc2, 0x20, 0x16),
62		.name = "mx25l3205d",
63		.size = SZ_4M,
64		.no_sfdp_flags = SECT_4K,
65	}, {
66		.id = SNOR_ID(0xc2, 0x20, 0x17),
67		.name = "mx25l6405d",
68		.size = SZ_8M,
69		.no_sfdp_flags = SECT_4K,
70	}, {
71		.id = SNOR_ID(0xc2, 0x20, 0x18),
72		.name = "mx25l12805d",
73		.size = SZ_16M,
74		.flags = SPI_NOR_HAS_LOCK | SPI_NOR_4BIT_BP,
75		.no_sfdp_flags = SECT_4K,
76	}, {
77		.id = SNOR_ID(0xc2, 0x20, 0x19),
78		.name = "mx25l25635e",
79		.size = SZ_32M,
80		.no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
81		.fixups = &mx25l25635_fixups
82	}, {
83		.id = SNOR_ID(0xc2, 0x20, 0x1a),
84		.name = "mx66l51235f",
85		.size = SZ_64M,
86		.no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
87		.fixup_flags = SPI_NOR_4B_OPCODES,
88	}, {
89		.id = SNOR_ID(0xc2, 0x20, 0x1b),
90		.name = "mx66l1g45g",
91		.size = SZ_128M,
92		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
93	}, {
94		.id = SNOR_ID(0xc2, 0x23, 0x14),
95		.name = "mx25v8035f",
96		.size = SZ_1M,
97		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
98	}, {
99		.id = SNOR_ID(0xc2, 0x25, 0x32),
100		.name = "mx25u2033e",
101		.size = SZ_256K,
102		.no_sfdp_flags = SECT_4K,
103	}, {
104		.id = SNOR_ID(0xc2, 0x25, 0x33),
105		.name = "mx25u4035",
106		.size = SZ_512K,
107		.no_sfdp_flags = SECT_4K,
108	}, {
109		.id = SNOR_ID(0xc2, 0x25, 0x34),
110		.name = "mx25u8035",
111		.size = SZ_1M,
112		.no_sfdp_flags = SECT_4K,
113	}, {
114		.id = SNOR_ID(0xc2, 0x25, 0x36),
115		.name = "mx25u3235f",
116		.size = SZ_4M,
117		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
118	}, {
119		.id = SNOR_ID(0xc2, 0x25, 0x37),
120		.name = "mx25u6435f",
121		.size = SZ_8M,
122		.no_sfdp_flags = SECT_4K,
123	}, {
124		.id = SNOR_ID(0xc2, 0x25, 0x38),
125		.name = "mx25u12835f",
126		.size = SZ_16M,
127		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
128	}, {
129		.id = SNOR_ID(0xc2, 0x25, 0x39),
130		.name = "mx25u25635f",
131		.size = SZ_32M,
132		.no_sfdp_flags = SECT_4K,
133		.fixup_flags = SPI_NOR_4B_OPCODES,
134	}, {
135		.id = SNOR_ID(0xc2, 0x25, 0x3a),
136		.name = "mx25u51245g",
137		.size = SZ_64M,
138		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
139		.fixup_flags = SPI_NOR_4B_OPCODES,
140	}, {
141		.id = SNOR_ID(0xc2, 0x25, 0x3a),
142		.name = "mx66u51235f",
143		.size = SZ_64M,
144		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
145		.fixup_flags = SPI_NOR_4B_OPCODES,
146	}, {
147		.id = SNOR_ID(0xc2, 0x25, 0x3c),
148		.name = "mx66u2g45g",
149		.size = SZ_256M,
150		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
151		.fixup_flags = SPI_NOR_4B_OPCODES,
152	}, {
153		.id = SNOR_ID(0xc2, 0x26, 0x18),
154		.name = "mx25l12855e",
155		.size = SZ_16M,
156	}, {
157		.id = SNOR_ID(0xc2, 0x26, 0x19),
158		.name = "mx25l25655e",
159		.size = SZ_32M,
160	}, {
161		.id = SNOR_ID(0xc2, 0x26, 0x1b),
162		.name = "mx66l1g55g",
163		.size = SZ_128M,
164		.no_sfdp_flags = SPI_NOR_QUAD_READ,
165	}, {
166		.id = SNOR_ID(0xc2, 0x28, 0x15),
167		.name = "mx25r1635f",
168		.size = SZ_2M,
169		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
170	}, {
171		.id = SNOR_ID(0xc2, 0x28, 0x16),
172		.name = "mx25r3235f",
173		.size = SZ_4M,
174		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
175	}, {
176		.id = SNOR_ID(0xc2, 0x81, 0x3a),
177		.name = "mx25uw51245g",
178		.n_banks = 4,
179		.flags = SPI_NOR_RWW,
180	}, {
181		.id = SNOR_ID(0xc2, 0x9e, 0x16),
182		.name = "mx25l3255e",
183		.size = SZ_4M,
184		.no_sfdp_flags = SECT_4K,
185	}
186};
187
188static void macronix_nor_default_init(struct spi_nor *nor)
189{
190	nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
191}
192
193static int macronix_nor_late_init(struct spi_nor *nor)
194{
195	if (!nor->params->set_4byte_addr_mode)
196		nor->params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_en4b_ex4b;
197
198	return 0;
199}
200
201static const struct spi_nor_fixups macronix_nor_fixups = {
202	.default_init = macronix_nor_default_init,
203	.late_init = macronix_nor_late_init,
204};
205
206const struct spi_nor_manufacturer spi_nor_macronix = {
207	.name = "macronix",
208	.parts = macronix_nor_parts,
209	.nparts = ARRAY_SIZE(macronix_nor_parts),
210	.fixups = &macronix_nor_fixups,
211};
212