cfi.h revision 1.3
1/* $NetBSD: cfi.h,v 1.3 2011/07/17 00:52:42 dyoung Exp $ */ 2 3#ifndef _CFI_H_ 4#define _CFI_H_ 5 6#include <dev/nor/cfi_0002.h> 7#include <sys/bus.h> 8 9/* 10 * minimum size to bus_space_map for probe/identify QRY: 11 * larget offset needed is CFI_QUERY_MODE_ALT_ADDRESS 12 * scaled by maximum attempted port width, so 13 * min >= (0x555 * sizeof(uint32_t)) 14 */ 15#define CFI_QRY_MIN_MAP_SIZE 0x2000 16 17 18typedef enum { 19 CFI_STATE_DATA_ARRAY = 0, 20 CFI_STATE_QUERY, 21 /* TBD */ 22} cfi_state_t; 23 24 25/* 26 * CFI Query structure 27 */ 28struct cfi_query_data { 29 /* Query info */ 30 uint8_t qry[3]; /* { 'Q', 'R', 'Y' } */ 31 uint16_t id_pri; /* primary comand set ID */ 32 uint16_t addr_pri; /* primary table addr */ 33 uint16_t id_alt; /* alternate command set ID */ 34 uint16_t addr_alt; /* alternate table addr */ 35 /* System Interface info */ 36 uint8_t vcc_min; /* min Vcc */ 37 uint8_t vcc_max; /* max Vcc */ 38 uint8_t vpp_min; /* min Vpp */ 39 uint8_t vpp_max; /* max Vpp */ 40 uint8_t write_word_time_typ; /* typ 1-word timeout, 1<<N usec */ 41 uint8_t write_nbyte_time_typ; /* typ multi-byte timeout, 1<<N usec */ 42 uint8_t erase_blk_time_typ; /* typ 1-blk erase timeout, 1<<N msec */ 43 uint8_t erase_chiptime_typ; /* typ chip erase timeout, 1<<N msec */ 44 uint8_t write_word_time_max; /* max 1-word timeout, typ<<N */ 45 uint8_t write_nbyte_time_max; /* max multi-byte timeout, typ<<N */ 46 uint8_t erase_blk_time_max; /* max 1-blk erase timeout, typ<<N */ 47 uint8_t erase_chiptime_max; /* max chip erase timeout, typ<<N */ 48 /* Device Geometry Definition */ 49 uint8_t device_size; /* 1<<N bytes */ 50 uint16_t interface_code_desc; /* JEP137 interface code description */ 51 uint16_t write_nbyte_size_max; /* max size of multi-byte write, 1<<N */ 52 uint8_t erase_blk_regions; /* number of erase block regions */ 53 struct { 54 uint16_t z; /* Erase Blocks are z * 256 bytes */ 55 uint16_t y; /* y+1 = #Erase Blocks in region */ 56 } erase_blk_info[4]; 57 /* Vendor-specific Primary command set info */ 58 union { 59 struct cmdset_0002_query_data cmd_0002; 60 } pri; 61#ifdef NOTYET 62 /* Vendor-specific Alternate command set info */ 63 union { 64 /* some command set structure here */ 65 } pri; 66#endif 67}; 68 69/* 70 * decode interface_code_desc 71 */ 72static inline const char * 73cfi_interface_desc_str(uint16_t icd) 74{ 75 switch(icd) { 76 case 0: 77 return "x8"; 78 case 1: 79 return "x16"; 80 case 2: 81 return "x8/x16"; 82 default: 83 return ""; 84 } 85} 86 87/* 88 * id_pri: CFI Command set and control assignments 89 */ 90#define CFI_ID_PRI_NONE 0x0000 91#define CFI_ID_PRI_INTEL_EXT 0x0001 92#define CFI_ID_PRI_AMD_STD 0x0002 93#define CFI_ID_PRI_INTEL_STD 0x0003 94#define CFI_ID_PRI_AMD_EXT 0x0004 95#define CFI_ID_PRI_WINBOND 0x0005 96#define CFI_ID_PRI_ST_ADV 0x0020 97#define CFI_ID_PRI_MITSU_ADV 0x0100 98#define CFI_ID_PRI_MITSU_EXT 0x0101 99#define CFI_ID_PRI_SST_PAGE 0x0102 100#define CFI_ID_PRI_SST_OLD 0x0701 101#define CFI_ID_PRI_INTEL_PERF 0x0200 102#define CFI_ID_PRI_INTEL_DATA 0x0210 103#define CFI_ID_PRI_RESV 0xffff /* not allowed, reserved */ 104 105/* 106 * JEDEC ID (autoselect) data 107 */ 108struct cfi_jedec_id_data { 109 uint16_t id_mid; /* manufacturer ID */ 110 uint16_t id_did[3]; /* device ID */ 111 uint16_t id_prot_state; 112 uint16_t id_indicators; 113 uint8_t id_swb_lo; /* lower software bits */ 114 uint8_t id_swb_hi; /* upper software bits */ 115}; 116 117/* 118 * table entry used to determine operating mode by QRY signature 119 */ 120struct cfi_opmodes { 121 uint8_t portwidth; /* (1<<N) bytes */ 122 uint8_t chipwidth; /* (1<<N) bytes */ 123 uint8_t interleave; /* (1<<N) bytes */ 124 uint8_t qsa; /* Query Start Address (in bytes) */ 125 uint8_t len; /* signature length */ 126 const uint8_t *sig; /* signature */ 127 const char *str; /* descriptive string */ 128}; 129 130struct cfi; /* fwd ref */ 131 132struct cfi_ops { 133 void (*cfi_reset)(struct cfi *); 134 int (*cfi_busy)(struct cfi *, flash_off_t); 135 int (*cfi_program_word)(struct cfi *, flash_off_t); 136 int (*cfi_erase_sector)(struct cfi *, flash_off_t); 137}; 138 139/* NOTE: 140 * CFI_0002_STATS are just meant temporarily for debugging 141 * not for long-term use. Some event counters at the flash and nor 142 * layers might be helpful eventually 143 */ 144#define CFI_0002_STATS /* XXX TMP */ 145#ifdef CFI_0002_STATS 146struct cfi_0002_stats { 147 u_long read_page; 148 u_long program_page; 149 u_long erase_all; 150 u_long erase_block; 151 u_long busy; 152 u_long busy_usec_min; 153 u_long busy_usec_max; 154 struct timeval busy_poll_tv; 155 struct timeval busy_yield_tv; 156 u_long busy_poll; 157 u_long busy_yield; 158 u_long busy_yield_hit; 159 u_long busy_yield_miss; 160 u_long busy_yield_timo; 161}; 162 163extern void cfi_0002_stats_reset(struct cfi *); 164extern void cfi_0002_stats_print(struct cfi *); 165#define CFI_0002_STATS_INIT(dev, cfi) \ 166 do { \ 167 aprint_normal_dev(dev, "cfi=%p\n", cfi); \ 168 cfi_0002_stats_reset(cfi); \ 169 } while (0) 170#define CFI_0002_STATS_INC(cfi, field) (cfi)->cfi_0002_stats.field++ 171 172#else 173 174#define CFI_0002_STATS_INIT(cfi) 175#define CFI_0002_STATS_INC(cfi, field) 176 177#endif /* CFI_0002_STATS */ 178 179struct cfi { 180 bus_space_tag_t cfi_bst; 181 bus_space_handle_t cfi_bsh; 182 cfi_state_t cfi_state; 183 uint8_t cfi_portwidth; /* port width, 1<<N bytes */ 184 uint8_t cfi_chipwidth; /* chip width, 1<<N bytes */ 185 struct cfi_query_data cfi_qry_data; /* CFI Query data */ 186 struct cfi_jedec_id_data 187 cfi_id_data; /* JEDEC ID data */ 188 const struct cfi_opmodes 189 *cfi_opmode; 190 struct cfi_ops cfi_ops; /* chip dependent functions */ 191 u_long cfi_yield_time; /* thresh. for yield in wait */ 192#ifdef CFI_0002_STATS 193 struct cfi_0002_stats cfi_0002_stats; 194#endif 195}; 196 197 198enum { 199 CFI_ADDRESS_ANY = 0x00, /* XXX "don't care" */ 200 201 CFI_RESET_DATA = 0xf0, 202 CFI_ALT_RESET_DATA = 0xff, 203 204 CFI_QUERY_MODE_ADDRESS = 0x55, /* some devices accept anything */ 205 CFI_QUERY_MODE_ALT_ADDRESS = 0x555, 206 CFI_QUERY_DATA = 0x98, 207}; 208 209static inline void 210cfi_reset(struct cfi * const cfi) 211{ 212 KASSERT(cfi->cfi_ops.cfi_reset != NULL); 213 cfi->cfi_ops.cfi_reset(cfi); 214} 215 216static inline int 217cfi_erase_sector(struct cfi * const cfi, flash_off_t offset) 218{ 219 KASSERT(cfi->cfi_ops.cfi_erase_sector != NULL); 220 return cfi->cfi_ops.cfi_erase_sector(cfi, offset); 221} 222 223static inline int 224cfi_program_word(struct cfi * const cfi, flash_off_t offset) 225{ 226 KASSERT(cfi->cfi_ops.cfi_program_word != NULL); 227 return cfi->cfi_ops.cfi_program_word(cfi, offset); 228} 229 230extern const struct nor_interface nor_interface_cfi; 231 232extern bool cfi_probe(struct cfi * const); 233extern bool cfi_identify(struct cfi * const); 234extern void cfi_print(device_t, struct cfi * const); 235extern void cfi_reset_default(struct cfi * const); 236extern void cfi_reset_std(struct cfi * const); 237extern void cfi_reset_alt(struct cfi * const); 238extern void cfi_cmd(struct cfi * const, bus_size_t, uint32_t); 239 240#endif /* _CFI_H_ */ 241