cfi.h revision 1.2 1 /* $NetBSD: cfi.h,v 1.2 2011/07/15 19:19:57 cliff Exp $ */
2
3 #ifndef _CFI_H_
4 #define _CFI_H_
5
6 #include <dev/nor/cfi_0002.h>
7 #include <machine/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
18 typedef 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 */
28 struct 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 */
72 static inline const char *
73 cfi_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 */
108 struct 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 */
120 struct 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
130 struct cfi; /* fwd ref */
131
132 struct 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
146 struct 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
163 extern void cfi_0002_stats_reset(struct cfi *);
164 extern 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
179 struct 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
198 enum {
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
209 static inline void
210 cfi_reset(struct cfi * const cfi)
211 {
212 KASSERT(cfi->cfi_ops.cfi_reset != NULL);
213 cfi->cfi_ops.cfi_reset(cfi);
214 }
215
216 static inline int
217 cfi_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
223 static inline int
224 cfi_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
230 extern const struct nor_interface nor_interface_cfi;
231
232 extern bool cfi_probe(struct cfi * const);
233 extern bool cfi_identify(struct cfi * const);
234 extern void cfi_print(device_t, struct cfi * const);
235 extern void cfi_reset_default(struct cfi * const);
236 extern void cfi_reset_std(struct cfi * const);
237 extern void cfi_reset_alt(struct cfi * const);
238 extern void cfi_cmd(struct cfi * const, bus_size_t, uint32_t);
239
240 #endif /* _CFI_H_ */
241