blob: 27473acae335359c430359c1c7db17db49dc0689 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Stefan Roese5ffceb82015-03-26 15:36:56 +01002/*
3 * Copyright (C) Marvell International Ltd. and its affiliates
Stefan Roese5ffceb82015-03-26 15:36:56 +01004 */
5
6#include <common.h>
7#include <spl.h>
8#include <asm/io.h>
9#include <asm/arch/cpu.h>
10#include <asm/arch/soc.h>
11
12#include "ddr3_init.h"
13
14/* List of allowed frequency listed in order of enum hws_ddr_freq */
15u32 freq_val[DDR_FREQ_LIMIT] = {
16 0, /*DDR_FREQ_LOW_FREQ */
17 400, /*DDR_FREQ_400, */
18 533, /*DDR_FREQ_533, */
19 666, /*DDR_FREQ_667, */
20 800, /*DDR_FREQ_800, */
21 933, /*DDR_FREQ_933, */
22 1066, /*DDR_FREQ_1066, */
23 311, /*DDR_FREQ_311, */
24 333, /*DDR_FREQ_333, */
25 467, /*DDR_FREQ_467, */
26 850, /*DDR_FREQ_850, */
27 600, /*DDR_FREQ_600 */
28 300, /*DDR_FREQ_300 */
29 900, /*DDR_FREQ_900 */
30 360, /*DDR_FREQ_360 */
31 1000 /*DDR_FREQ_1000 */
32};
33
34/* Table for CL values per frequency for each speed bin index */
35struct cl_val_per_freq cas_latency_table[] = {
36 /*
37 * 400M 667M 933M 311M 467M 600M 360
38 * 100M 533M 800M 1066M 333M 850M 900
39 * 1000 (the order is 100, 400, 533 etc.)
40 */
41 /* DDR3-800D */
42 { {6, 5, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 5, 0, 5, 0} },
43 /* DDR3-800E */
44 { {6, 6, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 6, 0, 6, 0} },
45 /* DDR3-1066E */
46 { {6, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 0, 5, 0, 5, 0} },
47 /* DDR3-1066F */
48 { {6, 6, 7, 0, 0, 0, 0, 6, 6, 7, 0, 0, 6, 0, 6, 0} },
49 /* DDR3-1066G */
50 { {6, 6, 8, 0, 0, 0, 0, 6, 6, 8, 0, 0, 6, 0, 6, 0} },
51 /* DDR3-1333F* */
52 { {6, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
53 /* DDR3-1333G */
54 { {6, 5, 7, 8, 0, 0, 0, 5, 5, 7, 0, 8, 5, 0, 5, 0} },
55 /* DDR3-1333H */
56 { {6, 6, 8, 9, 0, 0, 0, 6, 6, 8, 0, 9, 6, 0, 6, 0} },
57 /* DDR3-1333J* */
58 { {6, 6, 8, 10, 0, 0, 0, 6, 6, 8, 0, 10, 6, 0, 6, 0}
59 /* DDR3-1600G* */},
60 { {6, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
61 /* DDR3-1600H */
62 { {6, 5, 6, 8, 9, 0, 0, 5, 5, 6, 0, 8, 5, 0, 5, 0} },
63 /* DDR3-1600J */
64 { {6, 5, 7, 9, 10, 0, 0, 5, 5, 7, 0, 9, 5, 0, 5, 0} },
65 /* DDR3-1600K */
66 { {6, 6, 8, 10, 11, 0, 0, 6, 6, 8, 0, 10, 6, 0, 6, 0 } },
67 /* DDR3-1866J* */
68 { {6, 5, 6, 8, 9, 11, 0, 5, 5, 6, 11, 8, 5, 0, 5, 0} },
69 /* DDR3-1866K */
70 { {6, 5, 7, 8, 10, 11, 0, 5, 5, 7, 11, 8, 5, 11, 5, 11} },
71 /* DDR3-1866L */
72 { {6, 6, 7, 9, 11, 12, 0, 6, 6, 7, 12, 9, 6, 12, 6, 12} },
73 /* DDR3-1866M* */
74 { {6, 6, 8, 10, 11, 13, 0, 6, 6, 8, 13, 10, 6, 13, 6, 13} },
75 /* DDR3-2133K* */
76 { {6, 5, 6, 7, 9, 10, 11, 5, 5, 6, 10, 7, 5, 11, 5, 11} },
77 /* DDR3-2133L */
78 { {6, 5, 6, 8, 9, 11, 12, 5, 5, 6, 11, 8, 5, 12, 5, 12} },
79 /* DDR3-2133M */
80 { {6, 5, 7, 9, 10, 12, 13, 5, 5, 7, 12, 9, 5, 13, 5, 13} },
81 /* DDR3-2133N* */
82 { {6, 6, 7, 9, 11, 13, 14, 6, 6, 7, 13, 9, 6, 14, 6, 14} },
83 /* DDR3-1333H-ext */
84 { {6, 6, 7, 9, 0, 0, 0, 6, 6, 7, 0, 9, 6, 0, 6, 0} },
85 /* DDR3-1600K-ext */
86 { {6, 6, 7, 9, 11, 0, 0, 6, 6, 7, 0, 9, 6, 0, 6, 0} },
87 /* DDR3-1866M-ext */
88 { {6, 6, 7, 9, 11, 13, 0, 6, 6, 7, 13, 9, 6, 13, 6, 13} },
89};
90
91/* Table for CWL values per speedbin index */
92struct cl_val_per_freq cas_write_latency_table[] = {
93 /*
94 * 400M 667M 933M 311M 467M 600M 360
95 * 100M 533M 800M 1066M 333M 850M 900
96 * (the order is 100, 400, 533 etc.)
97 */
98 /* DDR3-800D */
99 { {5, 5, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 5, 0, 5, 0} },
100 /* DDR3-800E */
101 { {5, 5, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 5, 0, 5, 0} },
102 /* DDR3-1066E */
103 { {5, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
104 /* DDR3-1066F */
105 { {5, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
106 /* DDR3-1066G */
107 { {5, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
108 /* DDR3-1333F* */
109 { {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
110 /* DDR3-1333G */
111 { {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
112 /* DDR3-1333H */
113 { {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
114 /* DDR3-1333J* */
115 { {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
116 /* DDR3-1600G* */
117 { {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
118 /* DDR3-1600H */
119 { {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
120 /* DDR3-1600J */
121 { {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
122 /* DDR3-1600K */
123 { {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
124 /* DDR3-1866J* */
125 { {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 0, 5, 0} },
126 /* DDR3-1866K */
127 { {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 0, 5, 0} },
128 /* DDR3-1866L */
129 { {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 9, 5, 9} },
130 /* DDR3-1866M* */
131 { {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 9, 5, 9} },
132 /* DDR3-2133K* */
133 { {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
134 /* DDR3-2133L */
135 { {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
136 /* DDR3-2133M */
137 { {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
138 /* DDR3-2133N* */
139 { {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
140 /* DDR3-1333H-ext */
141 { {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
142 /* DDR3-1600K-ext */
143 { {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
144 /* DDR3-1866M-ext */
145 { {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 9, 5, 9} },
146};
147
148u8 twr_mask_table[] = {
149 10,
150 10,
151 10,
152 10,
153 10,
Chris Packham5450f0c2018-01-18 17:16:10 +1300154 1, /*5*/
155 2, /*6*/
156 3, /*7*/
157 4, /*8*/
Stefan Roese5ffceb82015-03-26 15:36:56 +0100158 10,
Chris Packham5450f0c2018-01-18 17:16:10 +1300159 5, /*10*/
Stefan Roese5ffceb82015-03-26 15:36:56 +0100160 10,
Chris Packham5450f0c2018-01-18 17:16:10 +1300161 6, /*12*/
Stefan Roese5ffceb82015-03-26 15:36:56 +0100162 10,
Chris Packham5450f0c2018-01-18 17:16:10 +1300163 7, /*14*/
Stefan Roese5ffceb82015-03-26 15:36:56 +0100164 10,
Chris Packham5450f0c2018-01-18 17:16:10 +1300165 0 /*16*/
Stefan Roese5ffceb82015-03-26 15:36:56 +0100166};
167
168u8 cl_mask_table[] = {
169 0,
170 0,
171 0,
172 0,
173 0,
174 0x2,
175 0x4,
176 0x6,
177 0x8,
178 0xa,
179 0xc,
180 0xe,
181 0x1,
182 0x3,
183 0x5,
184 0x5
185};
186
187u8 cwl_mask_table[] = {
188 0,
189 0,
190 0,
191 0,
192 0,
193 0,
194 0x1,
195 0x2,
196 0x3,
197 0x4,
198 0x5,
199 0x6,
200 0x7,
201 0x8,
202 0x9,
203 0x9
204};
205
206/* RFC values (in ns) */
207u16 rfc_table[] = {
208 90, /* 512M */
209 110, /* 1G */
210 160, /* 2G */
211 260, /* 4G */
212 350 /* 8G */
213};
214
215u32 speed_bin_table_t_rc[] = {
216 50000,
217 52500,
218 48750,
219 50625,
220 52500,
221 46500,
222 48000,
223 49500,
224 51000,
225 45000,
226 46250,
227 47500,
228 48750,
229 44700,
230 45770,
231 46840,
232 47910,
233 43285,
234 44220,
235 45155,
236 46900
237};
238
239u32 speed_bin_table_t_rcd_t_rp[] = {
240 12500,
241 15000,
242 11250,
243 13125,
244 15000,
245 10500,
246 12000,
247 13500,
248 15000,
249 10000,
250 11250,
251 12500,
252 13750,
253 10700,
254 11770,
255 12840,
256 13910,
257 10285,
258 11022,
259 12155,
260 13090,
261};
262
263enum {
264 PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR = 0,
265 PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM
266};
267
268static u8 pattern_killer_pattern_table_map[KILLER_PATTERN_LENGTH * 2][2] = {
269 /*Aggressor / Victim */
270 {1, 0},
271 {0, 0},
272 {1, 0},
273 {1, 1},
274 {0, 1},
275 {0, 1},
276 {1, 0},
277 {0, 1},
278 {1, 0},
279 {0, 1},
280 {1, 0},
281 {1, 0},
282 {0, 1},
283 {1, 0},
284 {0, 1},
285 {0, 0},
286 {1, 1},
287 {0, 0},
288 {1, 1},
289 {0, 0},
290 {1, 1},
291 {0, 0},
292 {1, 1},
293 {1, 0},
294 {0, 0},
295 {1, 1},
296 {0, 0},
297 {1, 1},
298 {0, 0},
299 {0, 0},
300 {0, 0},
301 {0, 1},
302 {0, 1},
303 {1, 1},
304 {0, 0},
305 {0, 0},
306 {1, 1},
307 {1, 1},
308 {0, 0},
309 {1, 1},
310 {0, 0},
311 {1, 1},
312 {1, 1},
313 {0, 0},
314 {0, 0},
315 {1, 1},
316 {0, 0},
317 {1, 1},
318 {0, 1},
319 {0, 0},
320 {0, 1},
321 {0, 1},
322 {0, 0},
323 {1, 1},
324 {1, 1},
325 {1, 0},
326 {1, 0},
327 {1, 1},
328 {1, 1},
329 {1, 1},
330 {1, 1},
331 {1, 1},
332 {1, 1},
333 {1, 1}
334};
335
336static u8 pattern_vref_pattern_table_map[] = {
337 /* 1 means 0xffffffff, 0 is 0x0 */
338 0xb8,
339 0x52,
340 0x55,
341 0x8a,
342 0x33,
343 0xa6,
344 0x6d,
345 0xfe
346};
347
348/* Return speed Bin value for selected index and t* element */
349u32 speed_bin_table(u8 index, enum speed_bin_table_elements element)
350{
351 u32 result = 0;
352
353 switch (element) {
354 case SPEED_BIN_TRCD:
355 case SPEED_BIN_TRP:
356 result = speed_bin_table_t_rcd_t_rp[index];
357 break;
358 case SPEED_BIN_TRAS:
359 if (index < 6)
360 result = 37500;
361 else if (index < 10)
362 result = 36000;
363 else if (index < 14)
364 result = 35000;
365 else if (index < 18)
366 result = 34000;
367 else
368 result = 33000;
369 break;
370 case SPEED_BIN_TRC:
371 result = speed_bin_table_t_rc[index];
372 break;
373 case SPEED_BIN_TRRD1K:
374 if (index < 3)
375 result = 10000;
376 else if (index < 6)
377 result = 7005;
378 else if (index < 14)
379 result = 6000;
380 else
381 result = 5000;
382 break;
383 case SPEED_BIN_TRRD2K:
384 if (index < 6)
385 result = 10000;
386 else if (index < 14)
387 result = 7005;
388 else
389 result = 6000;
390 break;
391 case SPEED_BIN_TPD:
392 if (index < 3)
393 result = 7500;
394 else if (index < 10)
395 result = 5625;
396 else
397 result = 5000;
398 break;
399 case SPEED_BIN_TFAW1K:
400 if (index < 3)
401 result = 40000;
402 else if (index < 6)
403 result = 37500;
404 else if (index < 14)
405 result = 30000;
406 else if (index < 18)
407 result = 27000;
408 else
409 result = 25000;
410 break;
411 case SPEED_BIN_TFAW2K:
412 if (index < 6)
413 result = 50000;
414 else if (index < 10)
415 result = 45000;
416 else if (index < 14)
417 result = 40000;
418 else
419 result = 35000;
420 break;
421 case SPEED_BIN_TWTR:
422 result = 7500;
423 break;
424 case SPEED_BIN_TRTP:
425 result = 7500;
426 break;
427 case SPEED_BIN_TWR:
428 result = 15000;
429 break;
430 case SPEED_BIN_TMOD:
431 result = 15000;
432 break;
Chris Packham5450f0c2018-01-18 17:16:10 +1300433 case SPEED_BIN_TXPDLL:
434 result = 24000;
435 break;
Stefan Roese5ffceb82015-03-26 15:36:56 +0100436 default:
437 break;
438 }
439
440 return result;
441}
442
443static inline u32 pattern_table_get_killer_word(u8 dqs, u8 index)
444{
445 u8 i, byte = 0;
446 u8 role;
447
448 for (i = 0; i < 8; i++) {
449 role = (i == dqs) ?
450 (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR) :
451 (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM);
452 byte |= pattern_killer_pattern_table_map[index][role] << i;
453 }
454
455 return byte | (byte << 8) | (byte << 16) | (byte << 24);
456}
457
458static inline u32 pattern_table_get_killer_word16(u8 dqs, u8 index)
459{
460 u8 i, byte0 = 0, byte1 = 0;
461 u8 role;
462
463 for (i = 0; i < 8; i++) {
464 role = (i == dqs) ?
465 (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR) :
466 (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM);
467 byte0 |= pattern_killer_pattern_table_map[index * 2][role] << i;
468 }
469
470 for (i = 0; i < 8; i++) {
471 role = (i == dqs) ?
472 (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR) :
473 (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM);
474 byte1 |= pattern_killer_pattern_table_map
475 [index * 2 + 1][role] << i;
476 }
477
478 return byte0 | (byte0 << 8) | (byte1 << 16) | (byte1 << 24);
479}
480
481static inline u32 pattern_table_get_sso_word(u8 sso, u8 index)
482{
483 u8 step = sso + 1;
484
485 if (0 == ((index / step) & 1))
486 return 0x0;
487 else
488 return 0xffffffff;
489}
490
491static inline u32 pattern_table_get_vref_word(u8 index)
492{
493 if (0 == ((pattern_vref_pattern_table_map[index / 8] >>
494 (index % 8)) & 1))
495 return 0x0;
496 else
497 return 0xffffffff;
498}
499
500static inline u32 pattern_table_get_vref_word16(u8 index)
501{
502 if (0 == pattern_killer_pattern_table_map
503 [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2] &&
504 0 == pattern_killer_pattern_table_map
505 [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2 + 1])
506 return 0x00000000;
507 else if (1 == pattern_killer_pattern_table_map
508 [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2] &&
509 0 == pattern_killer_pattern_table_map
510 [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2 + 1])
511 return 0xffff0000;
512 else if (0 == pattern_killer_pattern_table_map
513 [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2] &&
514 1 == pattern_killer_pattern_table_map
515 [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2 + 1])
516 return 0x0000ffff;
517 else
518 return 0xffffffff;
519}
520
521static inline u32 pattern_table_get_static_pbs_word(u8 index)
522{
523 u16 temp;
524
525 temp = ((0x00ff << (index / 3)) & 0xff00) >> 8;
526
527 return temp | (temp << 8) | (temp << 16) | (temp << 24);
528}
529
530inline u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index)
531{
532 u32 pattern;
533 struct hws_topology_map *tm = ddr3_get_topology_map();
534
535 if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 0) {
536 /* 32bit patterns */
537 switch (type) {
538 case PATTERN_PBS1:
539 case PATTERN_PBS2:
540 if (index == 0 || index == 2 || index == 5 ||
541 index == 7)
542 pattern = PATTERN_55;
543 else
544 pattern = PATTERN_AA;
545 break;
546 case PATTERN_PBS3:
547 if (0 == (index & 1))
548 pattern = PATTERN_55;
549 else
550 pattern = PATTERN_AA;
551 break;
552 case PATTERN_RL:
553 if (index < 6)
554 pattern = PATTERN_00;
555 else
556 pattern = PATTERN_80;
557 break;
558 case PATTERN_STATIC_PBS:
559 pattern = pattern_table_get_static_pbs_word(index);
560 break;
561 case PATTERN_KILLER_DQ0:
562 case PATTERN_KILLER_DQ1:
563 case PATTERN_KILLER_DQ2:
564 case PATTERN_KILLER_DQ3:
565 case PATTERN_KILLER_DQ4:
566 case PATTERN_KILLER_DQ5:
567 case PATTERN_KILLER_DQ6:
568 case PATTERN_KILLER_DQ7:
569 pattern = pattern_table_get_killer_word(
570 (u8)(type - PATTERN_KILLER_DQ0), index);
571 break;
572 case PATTERN_RL2:
573 if (index < 6)
574 pattern = PATTERN_00;
575 else
576 pattern = PATTERN_01;
577 break;
578 case PATTERN_TEST:
579 if (index > 1 && index < 6)
580 pattern = PATTERN_20;
581 else
582 pattern = PATTERN_00;
583 break;
584 case PATTERN_FULL_SSO0:
585 case PATTERN_FULL_SSO1:
586 case PATTERN_FULL_SSO2:
587 case PATTERN_FULL_SSO3:
588 pattern = pattern_table_get_sso_word(
589 (u8)(type - PATTERN_FULL_SSO0), index);
590 break;
591 case PATTERN_VREF:
592 pattern = pattern_table_get_vref_word(index);
593 break;
594 default:
595 pattern = 0;
596 break;
597 }
598 } else {
599 /* 16bit patterns */
600 switch (type) {
601 case PATTERN_PBS1:
602 case PATTERN_PBS2:
603 case PATTERN_PBS3:
604 pattern = PATTERN_55AA;
605 break;
606 case PATTERN_RL:
607 if (index < 3)
608 pattern = PATTERN_00;
609 else
610 pattern = PATTERN_80;
611 break;
612 case PATTERN_STATIC_PBS:
613 pattern = PATTERN_00FF;
614 break;
615 case PATTERN_KILLER_DQ0:
616 case PATTERN_KILLER_DQ1:
617 case PATTERN_KILLER_DQ2:
618 case PATTERN_KILLER_DQ3:
619 case PATTERN_KILLER_DQ4:
620 case PATTERN_KILLER_DQ5:
621 case PATTERN_KILLER_DQ6:
622 case PATTERN_KILLER_DQ7:
623 pattern = pattern_table_get_killer_word16(
624 (u8)(type - PATTERN_KILLER_DQ0), index);
625 break;
626 case PATTERN_RL2:
627 if (index < 3)
628 pattern = PATTERN_00;
629 else
630 pattern = PATTERN_01;
631 break;
632 case PATTERN_TEST:
633 pattern = PATTERN_0080;
634 break;
635 case PATTERN_FULL_SSO0:
636 pattern = 0x0000ffff;
637 break;
638 case PATTERN_FULL_SSO1:
639 case PATTERN_FULL_SSO2:
640 case PATTERN_FULL_SSO3:
641 pattern = pattern_table_get_sso_word(
642 (u8)(type - PATTERN_FULL_SSO1), index);
643 break;
644 case PATTERN_VREF:
645 pattern = pattern_table_get_vref_word16(index);
646 break;
647 default:
648 pattern = 0;
649 break;
650 }
651 }
652
653 return pattern;
654}