Patrick Georgi | ac95903 | 2020-05-05 22:49:26 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
Martin Roth | effaf8f | 2019-10-20 20:29:22 -0600 | [diff] [blame] | 2 | |
| 3 | /* |
| 4 | * SPI flash internal definitions |
Stefan Reinauer | 1c56d9b | 2012-05-10 11:27:32 -0700 | [diff] [blame] | 5 | */ |
| 6 | |
Edward O'Callaghan | c4561e2 | 2014-06-26 15:02:40 +1000 | [diff] [blame] | 7 | #ifndef SPI_FLASH_INTERNAL_H |
| 8 | #define SPI_FLASH_INTERNAL_H |
| 9 | |
Stefan Reinauer | 1c56d9b | 2012-05-10 11:27:32 -0700 | [diff] [blame] | 10 | /* Common commands */ |
| 11 | #define CMD_READ_ID 0x9f |
| 12 | |
| 13 | #define CMD_READ_ARRAY_SLOW 0x03 |
| 14 | #define CMD_READ_ARRAY_FAST 0x0b |
| 15 | #define CMD_READ_ARRAY_LEGACY 0xe8 |
| 16 | |
Julius Werner | 99e45ce | 2019-06-06 17:03:44 -0700 | [diff] [blame] | 17 | #define CMD_READ_FAST_DUAL_OUTPUT 0x3b |
Julius Werner | df50622 | 2021-07-13 15:57:29 -0700 | [diff] [blame] | 18 | #define CMD_READ_FAST_DUAL_IO 0xbb |
Julius Werner | 99e45ce | 2019-06-06 17:03:44 -0700 | [diff] [blame] | 19 | |
Stefan Reinauer | 1c56d9b | 2012-05-10 11:27:32 -0700 | [diff] [blame] | 20 | #define CMD_READ_STATUS 0x05 |
| 21 | #define CMD_WRITE_ENABLE 0x06 |
| 22 | |
Dan Ehrenberg | a5aac76 | 2015-01-08 10:29:19 -0800 | [diff] [blame] | 23 | #define CMD_BLOCK_ERASE 0xD8 |
| 24 | |
T Michael Turney | d43e688 | 2022-01-20 11:55:40 -0800 | [diff] [blame] | 25 | #define CMD_EXIT_4BYTE_ADDR_MODE 0xe9 |
| 26 | |
Stefan Reinauer | 1c56d9b | 2012-05-10 11:27:32 -0700 | [diff] [blame] | 27 | /* Common status */ |
| 28 | #define STATUS_WIP 0x01 |
| 29 | |
| 30 | /* Send a single-byte command to the device and read the response */ |
Furquan Shaikh | 810e2cd | 2016-12-05 20:32:24 -0800 | [diff] [blame] | 31 | int spi_flash_cmd(const struct spi_slave *spi, u8 cmd, void *response, size_t len); |
Stefan Reinauer | 1c56d9b | 2012-05-10 11:27:32 -0700 | [diff] [blame] | 32 | |
Stefan Reinauer | 1c56d9b | 2012-05-10 11:27:32 -0700 | [diff] [blame] | 33 | /* |
| 34 | * Send a multi-byte command to the device followed by (optional) |
| 35 | * data. Used for programming the flash array, etc. |
| 36 | */ |
Furquan Shaikh | 810e2cd | 2016-12-05 20:32:24 -0800 | [diff] [blame] | 37 | int spi_flash_cmd_write(const struct spi_slave *spi, const u8 *cmd, |
| 38 | size_t cmd_len, const void *data, size_t data_len); |
Stefan Reinauer | 1c56d9b | 2012-05-10 11:27:32 -0700 | [diff] [blame] | 39 | |
Stefan Reinauer | 1c56d9b | 2012-05-10 11:27:32 -0700 | [diff] [blame] | 40 | /* Send a command to the device and wait for some bit to clear itself. */ |
Furquan Shaikh | c28984d | 2016-11-20 21:04:00 -0800 | [diff] [blame] | 41 | int spi_flash_cmd_poll_bit(const struct spi_flash *flash, unsigned long timeout, |
Stefan Reinauer | 1c56d9b | 2012-05-10 11:27:32 -0700 | [diff] [blame] | 42 | u8 cmd, u8 poll_bit); |
| 43 | |
| 44 | /* |
| 45 | * Send the read status command to the device and wait for the wip |
| 46 | * (write-in-progress) bit to clear itself. |
| 47 | */ |
Furquan Shaikh | c28984d | 2016-11-20 21:04:00 -0800 | [diff] [blame] | 48 | int spi_flash_cmd_wait_ready(const struct spi_flash *flash, unsigned long timeout); |
Stefan Reinauer | 1c56d9b | 2012-05-10 11:27:32 -0700 | [diff] [blame] | 49 | |
| 50 | /* Erase sectors. */ |
Furquan Shaikh | c28984d | 2016-11-20 21:04:00 -0800 | [diff] [blame] | 51 | int spi_flash_cmd_erase(const struct spi_flash *flash, u32 offset, size_t len); |
Stefan Reinauer | 1c56d9b | 2012-05-10 11:27:32 -0700 | [diff] [blame] | 52 | |
Duncan Laurie | fb03239 | 2015-01-15 15:28:46 -0800 | [diff] [blame] | 53 | /* Read status register. */ |
Furquan Shaikh | c28984d | 2016-11-20 21:04:00 -0800 | [diff] [blame] | 54 | int spi_flash_cmd_status(const struct spi_flash *flash, u8 *reg); |
Duncan Laurie | fb03239 | 2015-01-15 15:28:46 -0800 | [diff] [blame] | 55 | |
Aaron Durbin | d701ef7 | 2019-12-27 15:16:17 -0700 | [diff] [blame] | 56 | /* Write to flash utilizing page program semantics. */ |
| 57 | int spi_flash_cmd_write_page_program(const struct spi_flash *flash, u32 offset, |
| 58 | size_t len, const void *buf); |
| 59 | |
Aaron Durbin | cb01aa5 | 2020-01-11 11:44:47 -0700 | [diff] [blame] | 60 | /* Read len bytes into buf at offset. */ |
| 61 | int spi_flash_cmd_read(const struct spi_flash *flash, u32 offset, size_t len, void *buf); |
| 62 | |
Aaron Durbin | 1c3086a | 2020-01-03 15:58:11 -0700 | [diff] [blame] | 63 | /* Release from deep sleep an provide alternative rdid information. */ |
| 64 | int stmicro_release_deep_sleep_identify(const struct spi_slave *spi, u8 *idcode); |
Edward O'Callaghan | c4561e2 | 2014-06-26 15:02:40 +1000 | [diff] [blame] | 65 | |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 66 | struct spi_flash_part_id { |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 67 | /* rdid command constructs 2x 16-bit id using the following method |
| 68 | * for matching after reading 5 bytes (1st byte is manuf id): |
| 69 | * id[0] = (id[1] << 8) | id[2] |
| 70 | * id[1] = (id[3] << 8) | id[4] |
| 71 | */ |
| 72 | uint16_t id[2]; |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 73 | /* Log based 2 total number of sectors. */ |
Tyler Wang | f7f661f | 2023-11-14 13:16:30 +0800 | [diff] [blame] | 74 | uint16_t nr_sectors_shift : 4; |
Julius Werner | df50622 | 2021-07-13 15:57:29 -0700 | [diff] [blame] | 75 | uint16_t fast_read_dual_output_support : 1; /* 1-1-2 read */ |
| 76 | uint16_t fast_read_dual_io_support : 1; /* 1-2-2 read */ |
Tyler Wang | f7f661f | 2023-11-14 13:16:30 +0800 | [diff] [blame] | 77 | uint16_t _reserved_for_flags : 2; |
Aaron Durbin | a6c73c8 | 2020-01-11 23:18:51 -0700 | [diff] [blame] | 78 | /* Block protection. Currently used by Winbond. */ |
| 79 | uint16_t protection_granularity_shift : 5; |
| 80 | uint16_t bp_bits : 3; |
| 81 | }; |
| 82 | |
Aaron Durbin | 5abeb06 | 2020-01-12 15:12:18 -0700 | [diff] [blame] | 83 | struct spi_flash_ops_descriptor { |
| 84 | uint8_t erase_cmd; /* Sector Erase */ |
| 85 | uint8_t status_cmd; /* Read Status Register */ |
| 86 | uint8_t pp_cmd; /* Page program command, if supported. */ |
| 87 | uint8_t wren_cmd; /* Write Enable command. */ |
| 88 | struct spi_flash_ops ops; |
| 89 | }; |
| 90 | |
| 91 | /* Vendor info represents a common set of organization and commands by a given |
| 92 | * vendor. One can implement multiple sets from a single vendor by having |
| 93 | * separate objects. */ |
| 94 | struct spi_flash_vendor_info { |
| 95 | uint8_t id; |
| 96 | uint8_t page_size_shift : 4; /* if page programming oriented. */ |
| 97 | /* Log based 2 sector size */ |
| 98 | uint8_t sector_size_kib_shift : 4; |
| 99 | uint16_t nr_part_ids; |
| 100 | const struct spi_flash_part_id *ids; |
Aaron Durbin | fc7b953 | 2020-01-23 11:45:30 -0700 | [diff] [blame] | 101 | uint16_t match_id_mask[2]; /* matching bytes of the id for this set*/ |
Aaron Durbin | 5abeb06 | 2020-01-12 15:12:18 -0700 | [diff] [blame] | 102 | const struct spi_flash_ops_descriptor *desc; |
| 103 | const struct spi_flash_protection_ops *prot_ops; |
| 104 | /* Returns 0 on success. !0 otherwise. */ |
| 105 | int (*after_probe)(const struct spi_flash *flash); |
| 106 | }; |
| 107 | |
| 108 | /* Manufacturer-specific probe information */ |
| 109 | extern const struct spi_flash_vendor_info spi_flash_adesto_vi; |
| 110 | extern const struct spi_flash_vendor_info spi_flash_amic_vi; |
| 111 | extern const struct spi_flash_vendor_info spi_flash_atmel_vi; |
| 112 | extern const struct spi_flash_vendor_info spi_flash_eon_vi; |
| 113 | extern const struct spi_flash_vendor_info spi_flash_gigadevice_vi; |
| 114 | extern const struct spi_flash_vendor_info spi_flash_macronix_vi; |
Martin Roth | 3e25f85 | 2023-09-04 15:37:07 -0600 | [diff] [blame^] | 115 | /* Probing order matters between the Spansion sequence. */ |
Aaron Durbin | 5abeb06 | 2020-01-12 15:12:18 -0700 | [diff] [blame] | 116 | extern const struct spi_flash_vendor_info spi_flash_spansion_ext1_vi; |
| 117 | extern const struct spi_flash_vendor_info spi_flash_spansion_ext2_vi; |
| 118 | extern const struct spi_flash_vendor_info spi_flash_spansion_vi; |
| 119 | extern const struct spi_flash_vendor_info spi_flash_sst_ai_vi; |
| 120 | extern const struct spi_flash_vendor_info spi_flash_sst_vi; |
| 121 | extern const struct spi_flash_vendor_info spi_flash_stmicro1_vi; |
| 122 | extern const struct spi_flash_vendor_info spi_flash_stmicro2_vi; |
| 123 | extern const struct spi_flash_vendor_info spi_flash_stmicro3_vi; |
| 124 | extern const struct spi_flash_vendor_info spi_flash_stmicro4_vi; |
| 125 | extern const struct spi_flash_vendor_info spi_flash_winbond_vi; |
| 126 | |
| 127 | /* Page Programming Command Set with 0x20 Sector Erase command. */ |
| 128 | extern const struct spi_flash_ops_descriptor spi_flash_pp_0x20_sector_desc; |
| 129 | /* Page Programming Command Set with 0xd8 Sector Erase command. */ |
| 130 | extern const struct spi_flash_ops_descriptor spi_flash_pp_0xd8_sector_desc; |
| 131 | |
Edward O'Callaghan | c4561e2 | 2014-06-26 15:02:40 +1000 | [diff] [blame] | 132 | #endif /* SPI_FLASH_INTERNAL_H */ |