cfi_0002.c revision 1.1 1 /* $NetBSD: cfi_0002.c,v 1.1 2011/07/15 19:19:57 cliff Exp $ */
2
3 #include "opt_flash.h"
4
5 #include <sys/cdefs.h>
6 __KERNEL_RCSID(0, "$NetBSD: cfi_0002.c,v 1.1 2011/07/15 19:19:57 cliff Exp $");
7
8 #include <sys/param.h>
9 #include <sys/systm.h>
10 #include <sys/cdefs.h>
11 #include <sys/device.h>
12 #include <sys/endian.h>
13 #include <sys/time.h>
14
15 #include <machine/bus.h>
16
17 #include <dev/nor/nor.h>
18 #include <dev/nor/cfi.h>
19 #include <dev/nor/cfi_0002.h>
20
21
22 static void cfi_0002_version_init(struct cfi * const);
23 static int cfi_0002_read_page(device_t, flash_off_t, uint8_t *);
24 static int cfi_0002_program_page(device_t, flash_off_t, const uint8_t *);
25 static int cfi_0002_erase_block(device_t, flash_off_t);
26 static int cfi_0002_erase_all(device_t);
27 static int cfi_0002_busy(device_t, flash_off_t, u_long);
28 static int cfi_0002_busy_wait(struct cfi * const, flash_off_t, u_long);
29 static int cfi_0002_busy_poll(struct cfi * const, flash_off_t, u_long);
30 static int cfi_0002_busy_yield(struct cfi * const, flash_off_t, u_long);
31 static int cfi_0002_busy_dq7(struct cfi * const , flash_off_t);
32 #ifdef NOTYET
33 static int cfi_0002_busy_reg(struct cfi * const, flash_off_t);
34 #endif
35
36
37 static const char *page_mode_str[] = {
38 "(not supported)",
39 "4 word page",
40 "8 word page",
41 "16 word page",
42 };
43
44 static const char *wp_mode_str[] = {
45 "Flash device without WP Protect (No Boot)",
46 "Eight 8 kB Sectors at TOP and Bottom with WP (Dual Boot)",
47 "Bottom Boot Device with WP Protect (Bottom Boot)",
48 "Top Boot Device with WP Protect (Top Boot)",
49 "Uniform, Bottom WP Protect (Uniform Bottom Boot)",
50 "Uniform, Top WP Protect (Uniform Top Boot)",
51 "WP Protect for all sectors",
52 "Uniform, Top or Bottom WP Protect",
53 };
54
55
56 static inline const char *
57 cfi_0002_page_mode_str(uint8_t mode)
58 {
59 if (mode >= __arraycount(page_mode_str))
60 panic("%s: mode %d out of range", __func__, mode);
61 return page_mode_str[mode];
62 }
63
64 static inline const char *
65 cfi_0002_wp_mode_str(uint8_t mode)
66 {
67 if (mode >= __arraycount(wp_mode_str))
68 panic("%s: mode %d out of range", __func__, mode);
69 return wp_mode_str[mode];
70 }
71
72 /*
73 * cfi_0002_time_write_nbyte - maximum usec delay waiting for write buffer
74 */
75 static inline u_long
76 cfi_0002_time_write_nbyte(struct cfi *cfi)
77 {
78 u_int shft = cfi->cfi_qry_data.write_nbyte_time_typ;
79 shft += cfi->cfi_qry_data.write_nbyte_time_max;
80 u_long usec = 1UL << shft;
81 return usec;
82 }
83
84 /*
85 * cfi_0002_time_erase_blk - maximum usec delay waiting for erase block
86 */
87 static inline u_long
88 cfi_0002_time_erase_blk(struct cfi *cfi)
89 {
90 u_int shft = cfi->cfi_qry_data.erase_blk_time_typ;
91 shft += cfi->cfi_qry_data.erase_blk_time_max;
92 u_long usec = 1000UL << shft;
93 return usec;
94 }
95
96 /*
97 * cfi_0002_time_erase_all - maximum usec delay waiting for erase chip
98 */
99 static inline u_long
100 cfi_0002_time_erase_all(struct cfi *cfi)
101 {
102 u_int shft = cfi->cfi_qry_data.erase_chiptime_typ;
103 shft += cfi->cfi_qry_data.erase_chiptime_max;
104 u_long usec = 1000UL << shft;
105 return usec;
106 }
107
108 /*
109 * cfi_0002_time_dflt - maximum usec delay to use waiting for ready
110 *
111 * use the maximum delay for chip erase function
112 * that should be the worst non-sick case
113 */
114 static inline u_long
115 cfi_0002_time_dflt(struct cfi *cfi)
116 {
117 return cfi_0002_time_erase_all(cfi);
118 }
119
120 void
121 cfi_0002_init(struct nor_softc * const sc, struct cfi * const cfi,
122 struct nor_chip * const chip)
123 {
124 CFI_0002_STATS_INIT(sc->sc_dev, cfi);
125
126 cfi_0002_version_init(cfi);
127
128 cfi->cfi_ops.cfi_reset = cfi_reset_std;
129 cfi->cfi_yield_time = 500; /* 500 usec */
130
131 /* page size for buffered write */
132 chip->nc_page_size =
133 1 << cfi->cfi_qry_data.write_nbyte_size_max;
134
135 /* these are unused */
136 chip->nc_spare_size = 0;
137 chip->nc_badmarker_offs = 0;
138
139 /* establish command-set-specific interface ops */
140 sc->sc_nor_if->read_page = cfi_0002_read_page;
141 sc->sc_nor_if->program_page = cfi_0002_program_page;
142 sc->sc_nor_if->erase_block = cfi_0002_erase_block;
143 sc->sc_nor_if->erase_all = cfi_0002_erase_all;
144 sc->sc_nor_if->busy = cfi_0002_busy;
145
146 }
147
148 /*
149 * cfi_0002_version_init - command set version-specific initialization
150 *
151 * see "Programmer's Guide for the Spansion 65 nm GL-S MirrorBit EclipseTM
152 * Flash Non-Volatile Memory Family Architecture" section 5.
153 */
154 static void
155 cfi_0002_version_init(struct cfi * const cfi)
156 {
157 const uint8_t major = cfi->cfi_qry_data.pri.cmd_0002.version_maj;
158 const uint8_t minor = cfi->cfi_qry_data.pri.cmd_0002.version_min;
159
160 if ((minor == '3') && (major == '1')) {
161 /* cmdset version 1.3 */
162 cfi->cfi_ops.cfi_busy = cfi_0002_busy_dq7;
163 #ifdef NOTYET
164 cfi->cfi_ops.cfi_erase_sector = cfi_0002_erase_sector_q;
165 cfi->cfi_ops.cfi_program_word = cfi_0002_program_word_ub;
166 } else if ((minor >= '5') && (major == '1')) {
167 /* cmdset version 1.5 or later */
168 cfi->cfi_ops.cfi_busy = cfi_0002_busy_reg;
169 cfi->cfi_ops.cfi_erase_sector = cfi_0002_erase_sector_1;
170 cfi->cfi_ops.cfi_program_word = cfi_0002_program_word_no_ub;
171 #endif
172 } else {
173 /* XXX this is excessive */
174 panic("%s: unknown cmdset version %c.%c\n",
175 __func__, major, minor);
176 }
177
178 }
179
180 void
181 cfi_0002_print(device_t self, struct cfi * const cfi)
182 {
183 #ifdef NOR_VERBOSE
184 struct cmdset_0002_query_data *pri = &cfi->cfi_qry_data.pri.cmd_0002;
185
186 aprint_normal_dev(self, "AMD/Fujitsu cmdset (0x0002) version=%c.%c\n",
187 pri->version_maj, pri->version_min);
188 aprint_normal_dev(self, "page mode type: %s\n",
189 cfi_0002_page_mode_str(pri->page_mode_type));
190 aprint_normal_dev(self, "wp protection: %s\n",
191 cfi_0002_wp_mode_str(pri->wp_prot));
192 aprint_normal_dev(self, "program suspend %ssupported\n",
193 (pri->prog_susp == 0) ? "not " : "");
194 aprint_normal_dev(self, "unlock bypass %ssupported\n",
195 (pri->unlock_bypass == 0) ? "not " : "");
196 aprint_normal_dev(self, "secure silicon sector size %#x\n",
197 1 << pri->sss_size);
198 aprint_normal_dev(self, "SW features %#x\n", pri->soft_feat);
199 aprint_normal_dev(self, "page size %d\n", 1 << pri->page_size);
200 #endif
201 }
202
203 static int
204 cfi_0002_read_page(device_t self, flash_off_t offset, uint8_t *datap)
205 {
206 struct nor_softc * const sc = device_private(self);
207 KASSERT(sc != NULL);
208 KASSERT(sc->sc_nor_if != NULL);
209 struct cfi *cfi = (struct cfi * const)sc->sc_nor_if->private;
210 KASSERT(cfi != NULL);
211 struct nor_chip * const chip = &sc->sc_chip;
212 KASSERT(chip != NULL);
213 KASSERT(chip->nc_page_mask != 0);
214 KASSERT((offset & ~chip->nc_page_mask) == 0);
215 KASSERT (chip->nc_page_size != 0);
216 KASSERT((chip->nc_page_size & ((1 << cfi->cfi_portwidth) - 1)) == 0);
217
218 CFI_0002_STATS_INC(cfi, read_page);
219
220 bus_size_t count = chip->nc_page_size >> cfi->cfi_portwidth;
221 /* #words/page */
222
223 int error = cfi_0002_busy_wait(cfi, offset, cfi_0002_time_dflt(cfi));
224 if (error != 0)
225 return error;
226
227 switch(cfi->cfi_portwidth) {
228 case 0:
229 bus_space_read_region_1(cfi->cfi_bst, cfi->cfi_bsh, offset,
230 (uint8_t *)datap, count);
231 break;
232 case 1:
233 bus_space_read_region_2(cfi->cfi_bst, cfi->cfi_bsh, offset,
234 (uint16_t *)datap, count);
235 break;
236 case 2:
237 bus_space_read_region_4(cfi->cfi_bst, cfi->cfi_bsh, offset,
238 (uint32_t *)datap, count);
239 break;
240 default:
241 panic("%s: bad port width %d\n", __func__, cfi->cfi_portwidth);
242 };
243
244 return 0;
245 }
246
247 static int
248 cfi_0002_program_page(device_t self, flash_off_t offset, const uint8_t *datap)
249 {
250 struct nor_softc * const sc = device_private(self);
251 KASSERT(sc != NULL);
252 KASSERT(sc->sc_nor_if != NULL);
253 struct cfi *cfi = (struct cfi * const)sc->sc_nor_if->private;
254 KASSERT(cfi != NULL);
255 struct nor_chip * const chip = &sc->sc_chip;
256 KASSERT(chip != NULL);
257 KASSERT(chip->nc_page_mask != 0);
258 KASSERT((offset & ~chip->nc_page_mask) == 0);
259 KASSERT (chip->nc_page_size != 0);
260 KASSERT((chip->nc_page_size & ((1 << cfi->cfi_portwidth) - 1)) == 0);
261
262 CFI_0002_STATS_INC(cfi, program_page);
263
264 bus_size_t count = chip->nc_page_size >> cfi->cfi_portwidth;
265 /* #words/page */
266 bus_size_t sa = offset >> cfi->cfi_portwidth; /* sector addr */
267 uint32_t wc = count - 1; /* #words - 1 */
268
269 int error = cfi_0002_busy_wait(cfi, offset, cfi_0002_time_dflt(cfi));
270 if (error != 0)
271 return ETIMEDOUT;
272
273 cfi_cmd(cfi, 0x555, 0xaa); /* unlock 1 */
274 cfi_cmd(cfi, 0x2aa, 0x55); /* unlock 2 */
275 cfi_cmd(cfi, sa, 0x25); /* Write To Buffer */
276 cfi_cmd(cfi, sa, wc);
277
278 switch(cfi->cfi_portwidth) {
279 case 0:
280 bus_space_write_region_1(cfi->cfi_bst, cfi->cfi_bsh, offset,
281 (const uint8_t *)datap, count);
282 break;
283 case 1:
284 bus_space_write_region_2(cfi->cfi_bst, cfi->cfi_bsh, offset,
285 (const uint16_t *)datap, count);
286 break;
287 case 2:
288 bus_space_write_region_4(cfi->cfi_bst, cfi->cfi_bsh, offset,
289 (const uint32_t *)datap, count);
290 break;
291 default:
292 panic("%s: bad port width %d\n", __func__, cfi->cfi_portwidth);
293 };
294
295 cfi_cmd(cfi, sa, 0x29); /* Write Buffer Program Confirm */
296
297 error = cfi_0002_busy_wait(cfi, offset, cfi_0002_time_write_nbyte(cfi));
298
299 return error;
300 }
301
302 static int
303 cfi_0002_erase_all(device_t self)
304 {
305 struct nor_softc * const sc = device_private(self);
306 KASSERT(sc != NULL);
307 KASSERT(sc->sc_nor_if != NULL);
308 struct cfi *cfi = (struct cfi * const)sc->sc_nor_if->private;
309 KASSERT(cfi != NULL);
310 struct nor_chip * const chip = &sc->sc_chip;
311 KASSERT(chip != NULL);
312
313 CFI_0002_STATS_INC(cfi, erase_all);
314
315 int error = cfi_0002_busy_wait(cfi, 0, cfi_0002_time_dflt(cfi));
316 if (error != 0)
317 return ETIMEDOUT;
318
319 cfi_cmd(cfi, 0x555, 0xaa); /* unlock 1 */
320 cfi_cmd(cfi, 0x2aa, 0x55); /* unlock 2 */
321 cfi_cmd(cfi, 0x555, 0x80); /* erase start */
322 cfi_cmd(cfi, 0x555, 0xaa); /* unlock 1 */
323 cfi_cmd(cfi, 0x2aa, 0x55); /* unlock 2 */
324 cfi_cmd(cfi, 0x555, 0x10); /* erase chip */
325
326 error = cfi_0002_busy_wait(cfi, 0, cfi_0002_time_erase_all(cfi));
327
328 return error;
329 }
330
331 static int
332 cfi_0002_erase_block(device_t self, flash_off_t offset)
333 {
334 struct nor_softc * const sc = device_private(self);
335 KASSERT(sc != NULL);
336 KASSERT(sc->sc_nor_if != NULL);
337 struct cfi *cfi = (struct cfi * const)sc->sc_nor_if->private;
338 KASSERT(cfi != NULL);
339 struct nor_chip * const chip = &sc->sc_chip;
340 KASSERT(chip != NULL);
341 KASSERT(chip->nc_block_mask != 0);
342 KASSERT((offset & ~chip->nc_block_mask) == 0);
343 KASSERT(chip->nc_block_size != 0);
344 KASSERT((chip->nc_block_size & ((1 << cfi->cfi_portwidth) - 1)) == 0);
345
346 CFI_0002_STATS_INC(cfi, erase_block);
347
348 /* scale sector addr by portwidth or chipwidth ? */
349 bus_size_t sa = offset >> cfi->cfi_portwidth;
350
351 int error = cfi_0002_busy_wait(cfi, offset, cfi_0002_time_dflt(cfi));
352 if (error != 0)
353 return ETIMEDOUT;
354
355 cfi_cmd(cfi, 0x555, 0xaa); /* unlock 1 */
356 cfi_cmd(cfi, 0x2aa, 0x55); /* unlock 2 */
357 cfi_cmd(cfi, 0x555, 0x80); /* erase start */
358 cfi_cmd(cfi, 0x555, 0xaa); /* unlock 1 */
359 cfi_cmd(cfi, 0x2aa, 0x55); /* unlock 2 */
360 cfi_cmd(cfi, sa, 0x30); /* erase sector */
361
362 error = cfi_0002_busy_wait(cfi, offset, cfi_0002_time_erase_blk(cfi));
363
364 return error;
365 }
366
367 /*
368 * cfi_0002_busy - nor_interface busy op
369 */
370 static int
371 cfi_0002_busy(device_t self, flash_off_t offset, u_long usec)
372 {
373 struct nor_softc *sc = device_private(self);
374 KASSERT(sc != NULL);
375 KASSERT(sc->sc_nor_if != NULL);
376 struct cfi * const cfi = (struct cfi * const)sc->sc_nor_if->private;
377
378 CFI_0002_STATS_INC(cfi, busy);
379
380 return cfi_0002_busy_wait(cfi, offset, usec);
381 }
382
383 /*
384 * cfi_0002_busy_wait - wait until device is not busy
385 */
386 static int
387 cfi_0002_busy_wait(struct cfi * const cfi, flash_off_t offset, u_long usec)
388 {
389 int error;
390
391 #ifdef CFI_0002_STATS
392 struct timeval start;
393 struct timeval now;
394 struct timeval delta;
395
396 if (usec > cfi->cfi_0002_stats.busy_usec_max)
397 cfi->cfi_0002_stats.busy_usec_max = usec;
398 if (usec < cfi->cfi_0002_stats.busy_usec_min)
399 cfi->cfi_0002_stats.busy_usec_min = usec;
400 microtime(&start);
401 #endif
402 if (usec > cfi->cfi_yield_time) {
403 error = cfi_0002_busy_yield(cfi, offset, usec);
404 #ifdef CFI_0002_STATS
405 microtime(&now);
406 cfi->cfi_0002_stats.busy_yield++;
407 timersub(&now, &start, &delta);
408 timeradd(&delta,
409 &cfi->cfi_0002_stats.busy_yield_tv,
410 &cfi->cfi_0002_stats.busy_yield_tv);
411 #endif
412 } else {
413 error = cfi_0002_busy_poll(cfi, offset, usec);
414 #ifdef CFI_0002_STATS
415 microtime(&now);
416 cfi->cfi_0002_stats.busy_poll++;
417 timersub(&now, &start, &delta);
418 timeradd(&delta,
419 &cfi->cfi_0002_stats.busy_poll_tv,
420 &cfi->cfi_0002_stats.busy_poll_tv);
421 #endif
422 }
423 return error;
424 }
425
426 /*
427 * cfi_0002_busy_poll - poll until device is not busy
428 */
429 static int
430 cfi_0002_busy_poll(struct cfi * const cfi, flash_off_t offset, u_long usec)
431 {
432 u_long count = usec >> 3;
433 if (count == 0)
434 count = 1; /* enforce minimum */
435 do {
436 if (! cfi->cfi_ops.cfi_busy(cfi, offset))
437 return 0; /* not busy */
438 DELAY(8);
439 } while (count-- != 0);
440
441 return ETIMEDOUT; /* busy */
442 }
443
444 /*
445 * cfi_0002_busy_yield - yield until device is not busy
446 */
447 static int
448 cfi_0002_busy_yield(struct cfi * const cfi, flash_off_t offset, u_long usec)
449 {
450 struct timeval start;
451 struct timeval delta;
452 struct timeval limit;
453 struct timeval now;
454
455 microtime(&start);
456
457 /* try optimism */
458 if (! cfi->cfi_ops.cfi_busy(cfi, offset)) {
459 CFI_0002_STATS_INC(cfi, busy_yield_hit);
460 return 0; /* not busy */
461 }
462 CFI_0002_STATS_INC(cfi, busy_yield_miss);
463
464 delta.tv_sec = usec / 1000000;
465 delta.tv_usec = usec % 1000000;
466 timeradd(&start, &delta, &limit);
467 do {
468 yield();
469 microtime(&now);
470 if (! cfi->cfi_ops.cfi_busy(cfi, offset))
471 return 0; /* not busy */
472 } while (timercmp(&now, &limit, <));
473
474 CFI_0002_STATS_INC(cfi, busy_yield_timo);
475
476 return ETIMEDOUT; /* busy */
477 }
478
479 /*
480 * cfi_0002_busy_dq7 - DQ7 "toggle" method to check busy
481 *
482 * Check busy during/after erase, program, protect operation.
483 *
484 * NOTE:
485 * Chip manufacturers (Spansion) plan to deprecate this method.
486 */
487 static int
488 cfi_0002_busy_dq7(struct cfi * const cfi, flash_off_t offset)
489 {
490 bus_space_tag_t bst = cfi->cfi_bst;
491 bus_space_handle_t bsh = cfi->cfi_bsh;
492 bool busy;
493
494 switch(cfi->cfi_portwidth) {
495 case 0: {
496 uint8_t r0 = bus_space_read_1(bst, bsh, 0) & __BIT(7);
497 uint8_t r1 = bus_space_read_1(bst, bsh, 0) & __BIT(7);
498 busy = (r0 != r1);
499 break;
500 }
501 case 1: {
502 uint16_t r0 = bus_space_read_2(bst, bsh, 0);
503 uint16_t r1 = bus_space_read_2(bst, bsh, 0);
504 busy = (r0 != r1);
505 break;
506 }
507 case 2: {
508 uint32_t r0 = bus_space_read_4(bst, bsh, 0);
509 uint32_t r1 = bus_space_read_4(bst, bsh, 0);
510 busy = (r0 != r1);
511 break;
512 }
513 default:
514 busy = true; /* appeas gcc */
515 panic("%s: bad port width %d\n",
516 __func__, cfi->cfi_portwidth);
517 }
518 return busy;
519 }
520
521 #ifdef NOTYET
522 /*
523 * cfi_0002_busy_reg - read and evaluate Read Status Register
524 *
525 * NOTE:
526 * Read Status Register not present on all chips
527 * use "toggle" method when Read Status Register not available.
528 */
529 static bool
530 cfi_0002_busy_reg(struct cfi * const cfi, flash_off_t offset)
531 {
532 bus_space_tag_t bst = cfi->cfi_bst;
533 bus_space_handle_t bsh = cfi->cfi_bsh;
534 uint32_t r;
535
536 cfi_cmd(cfi, 0x555, 0x70); /* Status Register Read */
537
538 switch(cfi->cfi_portwidth) {
539 case 0:
540 r = bus_space_read_1(bst, bsh, 0);
541 break;
542 case 1:
543 r = bus_space_read_2(bst, bsh, 0);
544 break;
545 case 2:
546 r = bus_space_read_4(bst, bsh, 0);
547 break;
548 default:
549 panic("%s: bad port width %d\n",
550 __func__, cfi->cfi_portwidth);
551 }
552
553 return ((r & __BIT(7)) == 0):
554 }
555 #endif /* NOTYET */
556
557 #ifdef CFI_0002_STATS
558 void
559 cfi_0002_stats_reset(struct cfi *cfi)
560 {
561 memset(&cfi->cfi_0002_stats, 0, sizeof(struct cfi_0002_stats));
562 cfi->cfi_0002_stats.busy_usec_min = ~0;
563 }
564
565 void
566 cfi_0002_stats_print(struct cfi *cfi)
567 {
568 printf("read_page %lu\n", cfi->cfi_0002_stats.read_page);
569 printf("program_page %lu\n", cfi->cfi_0002_stats.program_page);
570 printf("erase_all %lu\n", cfi->cfi_0002_stats.erase_all);
571 printf("erase_block %lu\n", cfi->cfi_0002_stats.erase_block);
572 printf("busy %lu\n", cfi->cfi_0002_stats.busy);
573
574 printf("write_nbyte_time_typ %d\n",
575 cfi->cfi_qry_data.write_nbyte_time_typ);
576 printf("write_nbyte_time_max %d\n",
577 cfi->cfi_qry_data.write_nbyte_time_max);
578
579 printf("erase_blk_time_typ %d\n",
580 cfi->cfi_qry_data.erase_blk_time_typ);
581 printf("erase_blk_time_max %d\n",
582 cfi->cfi_qry_data.erase_blk_time_max);
583
584 printf("erase_chiptime_typ %d\n",
585 cfi->cfi_qry_data.erase_chiptime_typ);
586 printf("erase_chiptime_max %d\n",
587 cfi->cfi_qry_data.erase_chiptime_max);
588
589 printf("time_write_nbyte %lu\n", cfi_0002_time_write_nbyte(cfi));
590 printf("time_erase_blk %lu\n", cfi_0002_time_erase_blk(cfi));
591 printf("time_erase_all %lu\n", cfi_0002_time_erase_all(cfi));
592
593 printf("busy_usec_min %lu\n", cfi->cfi_0002_stats.busy_usec_min);
594 printf("busy_usec_max %lu\n", cfi->cfi_0002_stats.busy_usec_max);
595
596 printf("busy_poll_tv %lld.%d\n",
597 cfi->cfi_0002_stats.busy_poll_tv.tv_sec,
598 cfi->cfi_0002_stats.busy_poll_tv.tv_usec);
599 printf("busy_yield_tv %lld.%d\n",
600 cfi->cfi_0002_stats.busy_yield_tv.tv_sec,
601 cfi->cfi_0002_stats.busy_yield_tv.tv_usec);
602 printf("busy_poll %lu\n", cfi->cfi_0002_stats.busy_poll);
603 printf("busy_yield %lu\n", cfi->cfi_0002_stats.busy_yield);
604 printf("busy_yield_hit %lu\n", cfi->cfi_0002_stats.busy_yield_hit);
605 printf("busy_yield_miss %lu\n", cfi->cfi_0002_stats.busy_yield_miss);
606 printf("busy_yield_timo %lu\n", cfi->cfi_0002_stats.busy_yield_timo);
607 }
608 #endif /* CFI_0002_STATS */
609