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 | static int |
12 | mx25l25635_post_bfpt_fixups(struct spi_nor *nor, |
13 | const struct sfdp_parameter_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 | |
31 | static const struct spi_nor_fixups mx25l25635_fixups = { |
32 | .post_bfpt = mx25l25635_post_bfpt_fixups, |
33 | }; |
34 | |
35 | static 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 | |
188 | static void macronix_nor_default_init(struct spi_nor *nor) |
189 | { |
190 | nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable; |
191 | } |
192 | |
193 | static 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 | |
201 | static const struct spi_nor_fixups macronix_nor_fixups = { |
202 | .default_init = macronix_nor_default_init, |
203 | .late_init = macronix_nor_late_init, |
204 | }; |
205 | |
206 | const struct spi_nor_manufacturer spi_nor_macronix = { |
207 | .name = "macronix" , |
208 | .parts = macronix_nor_parts, |
209 | .nparts = ARRAY_SIZE(macronix_nor_parts), |
210 | .fixups = ¯onix_nor_fixups, |
211 | }; |
212 | |