b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | #ifndef _SPI_FLASH_H |
| 2 | #define _SPI_FLASH_H |
| 3 | |
| 4 | #include "Typedef.h" |
| 5 | #include "Flash.h" |
| 6 | #include "predefines.h" |
| 7 | |
| 8 | #define false 0 |
| 9 | #define true 1 |
| 10 | |
| 11 | #ifndef min |
| 12 | #define min(a, b) ((a) < (b) ? (a) : (b)) |
| 13 | #endif |
| 14 | |
| 15 | #ifndef max |
| 16 | #define max(a, b) ((a) > (b) ? (a) : (b)) |
| 17 | #endif |
| 18 | |
| 19 | #define _readb(p) (*(volatile uint8_t *)(p)) |
| 20 | #define _readw(p) (*(volatile uint16_t *)(p)) |
| 21 | #define _readl(p) (*(volatile uint32_t *)(p)) |
| 22 | |
| 23 | #define _writeb(v,p) (*(volatile uint8_t *)(p) = ((uint8_t)v)) |
| 24 | #define _writew(v,p) (*(volatile uint16_t *)(p) = ((uint16_t)v)) |
| 25 | #define _writel(v,p) (*(volatile uint32_t *)(p) = (v)) |
| 26 | |
| 27 | /* Vendor Manufacture ID */ |
| 28 | #define SPIFLASH_MFR_MICRON 0x2C |
| 29 | #define SPIFLASH_MFR_GIGADEVICE 0xC8 |
| 30 | #define SPIFLASH_MFR_WINBOND 0xEF |
| 31 | #define SPIFLASH_MFR_MXIC 0xC2 |
| 32 | #define SPIFLASH_MFR_DOSILICON 0xE5 |
| 33 | #define SPIFLASH_MFR_ZETTADEVICE 0xBA |
| 34 | #define SPIFLASH_MFR_DOUQI 0x54 |
| 35 | #define SPIFLASH_MFR_DOSILICON_NOR 0xF8 |
| 36 | #define SPIFLASH_MFR_PUYA 0x85 |
| 37 | #define SPIFLASH_MFR_XM 0x20 |
| 38 | #define SPIFLASH_MFR_FMSH 0xA1 |
| 39 | |
| 40 | struct spi_flash_chip; |
| 41 | struct spi_flash_ops { |
| 42 | int (*reset)(struct spi_flash_chip *chip); |
| 43 | int (*read_id)(struct spi_flash_chip *chip, uint8_t *buf); |
| 44 | int (*read)(struct spi_flash_chip *chip, int addr, int size, uint8_t *rbuf); |
| 45 | int (*write)(struct spi_flash_chip *chip, int addr, int size, uint8_t *wbuf); |
| 46 | int (*erase)(struct spi_flash_chip *chip, int addr, int len); |
| 47 | }; |
| 48 | |
| 49 | struct micron_onfi_specific { |
| 50 | uint8_t two_plane_page_read; /*166*/ |
| 51 | uint8_t reserved0[8]; /*167-174*/ |
| 52 | uint8_t otp_mode; /*175*/ |
| 53 | uint8_t otp_page_start; /*176*/ |
| 54 | uint8_t otp_data_protect_addr; /*177*/ |
| 55 | uint8_t otp_page_number; /*178*/ |
| 56 | uint8_t otp_feature_addr; /*179*/ |
| 57 | uint8_t reserved1[68]; /*180-247*/ |
| 58 | uint8_t ecc_ability; /*248*/ |
| 59 | uint8_t die_selection; /*249*/ |
| 60 | uint8_t reserved2[3]; /*250-252*/ |
| 61 | uint8_t parameter_page_version; /*253*/ |
| 62 | } __attribute__((packed)); |
| 63 | |
| 64 | union spi_nand_vendor_specific { |
| 65 | uint8_t vendor_specific[88]; |
| 66 | struct micron_onfi_specific micron_sepcific; |
| 67 | }; |
| 68 | |
| 69 | struct spi_nand_onfi_params { |
| 70 | /* rev info and features block */ |
| 71 | /* 'O' 'N' 'F' 'I' */ |
| 72 | uint8_t sig[4]; /*0-3*/ |
| 73 | uint16_t revision; /*4-5*/ |
| 74 | uint16_t features; /*6-7*/ |
| 75 | uint16_t opt_cmd; /*8-9*/ |
| 76 | uint8_t reserved0[22]; /*10-31*/ |
| 77 | |
| 78 | /* manufacturer information block */ |
| 79 | char manufacturer[12]; /*32-43*/ |
| 80 | char model[20]; /*44-63*/ |
| 81 | uint8_t mfr_id; /*64*/ |
| 82 | uint16_t date_code; /*65-66*/ |
| 83 | uint8_t reserved1[13]; /*67-79*/ |
| 84 | |
| 85 | /* memory organization block */ |
| 86 | uint32_t byte_per_page; /*80-83*/ |
| 87 | uint16_t spare_bytes_per_page; /*84*85*/ |
| 88 | uint32_t data_bytes_per_ppage; /*86-89*/ |
| 89 | uint16_t spare_bytes_per_ppage; /*90-91*/ |
| 90 | uint32_t pages_per_block; /*92-95*/ |
| 91 | uint32_t blocks_per_lun; /*96-99*/ |
| 92 | uint8_t lun_count; /*100*/ |
| 93 | uint8_t addr_cycles; /*101*/ |
| 94 | uint8_t bits_per_cell; /*102*/ |
| 95 | uint16_t bb_per_lun; /*103-104*/ |
| 96 | uint16_t block_endurance; /*105-106*/ |
| 97 | uint8_t guaranteed_good_blocks; /*107*/ |
| 98 | uint16_t guaranteed_block_endurance; /*108-109*/ |
| 99 | uint8_t programs_per_page; /*110*/ |
| 100 | uint8_t ppage_attr; /*111*/ |
| 101 | uint8_t ecc_bits; /*112*/ |
| 102 | uint8_t interleaved_bits; /*113*/ |
| 103 | uint8_t interleaved_ops; /*114*/ |
| 104 | uint8_t reserved2[13]; /*115-127*/ |
| 105 | |
| 106 | /* electrical parameter block */ |
| 107 | uint8_t io_pin_capacitance_max; /*128*/ |
| 108 | uint16_t timing_mode; /*129-130*/ |
| 109 | uint16_t program_cache_timing_mode; /*131-132*/ |
| 110 | uint16_t t_prog; /*133-134*/ |
| 111 | uint16_t t_bers; /*135-136*/ |
| 112 | uint16_t t_r; /*137-138*/ |
| 113 | uint16_t t_ccs; /*139-140*/ |
| 114 | uint8_t reserved3[23]; /*141-163*/ |
| 115 | |
| 116 | /* vendor */ |
| 117 | uint16_t vendor_specific_revision; /*164-165*/ |
| 118 | union spi_nand_vendor_specific vendor; /*166-253*/ |
| 119 | |
| 120 | uint16_t crc; /*254-255*/ |
| 121 | } __attribute__((packed)); |
| 122 | |
| 123 | #define ONFI_CRC_BASE 0x4F4E |
| 124 | |
| 125 | /** |
| 126 | * struct spi_flash_chip - SPI-NAND Private Flash Chip Data |
| 127 | * @name: name of the chip |
| 128 | * @spi: [INTERN] point to spi device structure |
| 129 | * @mfr_id: [BOARDSPECIFIC] manufacture id |
| 130 | * @dev_id: [BOARDSPECIFIC] device id |
| 131 | * @read_cache_op: [REPLACEABLE] Opcode of read from cache |
| 132 | * @write_cache_op: [REPLACEABLE] Opcode of program load |
| 133 | * @write_cache_rdm_op: [REPLACEABLE] Opcode of program load random |
| 134 | * @oobbuf: [INTERN] buffer for read/write oob |
| 135 | * @size: [INTERN] the size of chip |
| 136 | * @block_size: [INTERN] the size of eraseblock |
| 137 | * @page_size: [INTERN] the size of page |
| 138 | * @oob_size: [INTERN] the size of page oob size |
| 139 | * @block_shift: [INTERN] number of address bits in a eraseblock |
| 140 | * @page_shift: [INTERN] number of address bits in a page (column |
| 141 | * address bits). |
| 142 | * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1 |
| 143 | * @options: [BOARDSPECIFIC] various chip options. They can partly |
| 144 | * be set to inform nand_scan about special functionality. |
| 145 | * @ecc_strength: [INTERN] ECC correctability |
| 146 | * @refresh_threshold: [INTERN] Bitflip threshold to return -EUCLEAN |
| 147 | * @ecclayout: [BOARDSPECIFIC] ECC layout control structure |
| 148 | * See the defines for further explanation. |
| 149 | * @onfi_params: [INTERN] holds the ONFI page parameter |
| 150 | */ |
| 151 | struct spi_flash_chip { |
| 152 | char *name; |
| 153 | struct spi_flash_cmd_cfg *table; |
| 154 | struct spi_flash_ops *ops; |
| 155 | struct qspi_host *host; |
| 156 | |
| 157 | uint8_t cs; |
| 158 | uint8_t mfr_id; |
| 159 | uint16_t dev_id; |
| 160 | uint32_t tx_max_len; |
| 161 | uint32_t rx_max_len; |
| 162 | uint8_t gd_ver_c; |
| 163 | uint8_t read_op; |
| 164 | uint8_t read_cache_op; |
| 165 | uint8_t write_op; |
| 166 | uint8_t write_cache_op; |
| 167 | uint8_t write_cache_rdm_op; |
| 168 | |
| 169 | int (*enable_ecc)(struct spi_flash_chip *chip); |
| 170 | int (*disable_ecc)(struct spi_flash_chip *chip); |
| 171 | void (*get_ecc_status)(struct spi_flash_chip *chip, uint8_t status, |
| 172 | uint32_t *corrected, uint32_t *ecc_error); |
| 173 | |
| 174 | uint8_t en_addr_4byte; |
| 175 | uint8_t qpi_enabled; |
| 176 | uint8_t qpi_dummy; |
| 177 | uint8_t *oobbuf; |
| 178 | uint64_t size; |
| 179 | uint32_t block_size; |
| 180 | uint16_t page_size; |
| 181 | uint16_t oob_size; |
| 182 | uint8_t lun_shift; |
| 183 | uint8_t block_shift; |
| 184 | uint8_t page_shift; |
| 185 | uint16_t page_mask; |
| 186 | uint32_t options; |
| 187 | uint32_t ecc_strength; |
| 188 | uint8_t refresh_threshold; |
| 189 | uint8_t lun; |
| 190 | uint32_t max_mhz; |
| 191 | void * flash_info; |
| 192 | //struct nand_ecclayout *ecclayout; |
| 193 | struct spi_nand_onfi_params onfi_params; |
| 194 | }; |
| 195 | |
| 196 | enum { |
| 197 | CMD_W_NO_DATA = 0, |
| 198 | CMD_W_RX_DATA = 1, |
| 199 | CMD_W_TX_DATA = 2, |
| 200 | }; |
| 201 | |
| 202 | struct spi_flash_cmd_cfg { |
| 203 | uint8_t opcode; |
| 204 | uint8_t cmd_dtr; |
| 205 | uint8_t addr_bytes; |
| 206 | uint8_t addr_pins; |
| 207 | uint8_t addr_dtr; |
| 208 | uint8_t mode_bits; |
| 209 | uint8_t mode_pins; |
| 210 | uint8_t mode_dtr; |
| 211 | uint8_t dummy_cycles; |
| 212 | uint8_t dummy_pins; |
| 213 | uint8_t data_pins; |
| 214 | uint8_t data_dtr; |
| 215 | int8_t seq_id; |
| 216 | int8_t type; |
| 217 | }; |
| 218 | |
| 219 | #define SPI_CMD_DTR(_opcode,_cmd_dtr,_addr_bytes,_addr_pins,_addr_dtr, \ |
| 220 | _mode_bits,_mode_pins,_mode_dtr,_dummy_cycles,_dummy_pins, \ |
| 221 | _data_pins,_data_dtr, _seq_id, _type) \ |
| 222 | { \ |
| 223 | .opcode = _opcode, \ |
| 224 | .cmd_dtr = _cmd_dtr, \ |
| 225 | .addr_bytes = _addr_bytes, \ |
| 226 | .addr_pins = _addr_pins, \ |
| 227 | .addr_dtr = _addr_dtr, \ |
| 228 | .mode_bits = _mode_bits, \ |
| 229 | .mode_pins = _mode_pins, \ |
| 230 | .mode_dtr = _mode_dtr, \ |
| 231 | .dummy_cycles = _dummy_cycles, \ |
| 232 | .dummy_pins = _dummy_pins, \ |
| 233 | .data_pins = _data_pins, \ |
| 234 | .data_dtr = _data_dtr, \ |
| 235 | .seq_id = _seq_id, \ |
| 236 | .type = _type, \ |
| 237 | } |
| 238 | |
| 239 | |
| 240 | #define SPI_CMD(_opcode,_addr_bytes,_addr_pins,_mode_bits, \ |
| 241 | _mode_pins,_dummy_cycles,_dummy_pins,_data_pins, \ |
| 242 | _seq_id, _type) \ |
| 243 | SPI_CMD_DTR(_opcode,0,_addr_bytes,_addr_pins,0, \ |
| 244 | _mode_bits,_mode_pins,0,_dummy_cycles,_dummy_pins, \ |
| 245 | _data_pins,0, _seq_id, _type) \ |
| 246 | |
| 247 | enum { |
| 248 | RST_AHB_DOMAIN = 1 << 0, |
| 249 | AHB_MAP_SIZE_PAGE = 1 << 1, |
| 250 | }; |
| 251 | |
| 252 | #define SPINAND_MAX_ADDR_LEN 4 |
| 253 | |
| 254 | struct spi_flash_cmd { |
| 255 | struct spi_flash_cmd_cfg *cmd_cfg; |
| 256 | uint8_t n_addr; /* Number of address */ |
| 257 | uint8_t addr[SPINAND_MAX_ADDR_LEN]; /* Reg Offset */ |
| 258 | uint32_t n_tx; /* Number of tx bytes */ |
| 259 | const uint8_t *tx_buf; /* Tx buf */ |
| 260 | uint32_t n_rx; /* Number of rx bytes */ |
| 261 | uint8_t *rx_buf; /* Rx buf */ |
| 262 | uint8_t mode; |
| 263 | uint8_t flag; |
| 264 | int error; |
| 265 | }; |
| 266 | |
| 267 | /* feature registers */ |
| 268 | #define REG_BLOCK_LOCK 0xa0 |
| 269 | #define REG_CFG 0xb0 |
| 270 | #define REG_STATUS 0xc0 |
| 271 | #define REG_DIE_SELECT 0xd0 |
| 272 | |
| 273 | /* status */ |
| 274 | #define STATUS_OIP_MASK 0x01 |
| 275 | #define STATUS_CRBSY_MASK 0x80 |
| 276 | #define STATUS_READY (0 << 0) |
| 277 | #define STATUS_BUSY (1 << 0) |
| 278 | |
| 279 | #define STATUS_E_FAIL_MASK 0x04 |
| 280 | #define STATUS_E_FAIL (1 << 2) |
| 281 | |
| 282 | #define STATUS_P_FAIL_MASK 0x08 |
| 283 | #define STATUS_P_FAIL (1 << 3) |
| 284 | |
| 285 | enum { |
| 286 | NORMAL_MODE, |
| 287 | OTP_MODE, |
| 288 | OTP_PROTECT_MODE, |
| 289 | SNOR_READ_ENABLE_MODE, |
| 290 | }; |
| 291 | |
| 292 | /* Ability of SPI Controllers */ |
| 293 | #define SPI_OPM_RX_QUAD 1 << 2 /* Support 4 pin RX */ |
| 294 | #define SPI_OPM_RX_DUAL 1 << 1 /* Support 2 pin RX */ |
| 295 | #define SPI_OPM_RX 1 << 0 /* Support 1 pin RX */ |
| 296 | #define SPI_OPM_TX_QUAD 1 << 2 /* Support 4 pin TX */ |
| 297 | #define SPI_OPM_TX 1 << 0 /* Support 1 pin TX */ |
| 298 | |
| 299 | static inline uint8_t ilog2(unsigned int v) |
| 300 | { |
| 301 | uint8_t l = 0; |
| 302 | while ((1UL << l) < v) |
| 303 | l++; |
| 304 | return l; |
| 305 | } |
| 306 | |
| 307 | #endif |