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 *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 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