Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / obp / tools / gen-seeprom / cpu-seeprom.c
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* Hypervisor Software File: cpu-seeprom.c
5*
6* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
7*
8* - Do no alter or remove copyright notices
9*
10* - Redistribution and use of this software in source and binary forms, with
11* or without modification, are permitted provided that the following
12* conditions are met:
13*
14* - Redistribution of source code must retain the above copyright notice,
15* this list of conditions and the following disclaimer.
16*
17* - Redistribution in binary form must reproduce the above copyright notice,
18* this list of conditions and the following disclaimer in the
19* documentation and/or other materials provided with the distribution.
20*
21* Neither the name of Sun Microsystems, Inc. or the names of contributors
22* may be used to endorse or promote products derived from this software
23* without specific prior written permission.
24*
25* This software is provided "AS IS," without a warranty of any kind.
26* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
27* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
28* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
29* MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
30* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
31* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
32* OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
33* FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
34* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
35* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
36* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
37*
38* You acknowledge that this software is not designed, licensed or
39* intended for use in the design, construction, operation or maintenance of
40* any nuclear facility.
41*
42* ========== Copyright Header End ============================================
43*/
44/*
45 * id: @(#)cpu-seeprom.c 1.10 05/11/15
46 * purpose:
47 * copyright: Copyright 2005 Sun Microsystems, Inc. All Rights Reserved
48 * copyright: Use is subject to license terms.
49*/
50
51#include <stdio.h>
52#include <stdlib.h>
53#include <strings.h>
54#include "gen-seeprom.h"
55#include "cpu-seeprom.h"
56#include "prototypes.h"
57
58#define ULTRA3_MODE 1 /* Ultra3 */
59#define ULTRA3_PLUS 2 /* Ultra3+ in 2way E$ mode */
60#define ULTRA3_PLUS_DM 3 /* Ultra3+ in direct mapped mode */
61
62int format_mode, id_magic;
63int clk_div_set = 0;
64static int speed_ratio_max = 6;
65static int speed_ratio_min = 4;
66static int cpu_ratios_min = 3;
67static int cpu_ratios_bits = 8; /* # of bits in cpu ratios fru parameter */
68
69extern int do_checksum;
70extern int system_type, type;
71extern struct fixed_seeprom *seeprom_data;
72
73void
74set_magic_bytes(void *data)
75{
76 if ((int)data != CPU_DEFAULT_MAGIC) {
77 do_checksum = 1;
78 }
79 id_magic = (int)data;
80}
81
82void
83set_format_byte(void *data)
84{
85 format_mode = (int)data;
86}
87
88void
89set_clk_div_byte(void *data)
90{
91 clk_div_set = 1;
92}
93
94struct fixed_seeprom cpu_seeprom_data[] = {
95 /* name size type value */
96 { "id_magic", 2, NUM, 0, set_magic_bytes },
97 { "id_format", 1, NUM, 0, set_format_byte },
98 { "cpu_ratios", 1, NUM, 0, NULL },
99 { "checksum", 2, NUM, 0, NULL },
100 { "clk_divisor", 1, NUM, 0, set_clk_div_byte },
101 { "cpu_id", 1, NUM, 0, NULL },
102 { "dcr", 8, NUM, 0, NULL },
103 { "lsucr", 8, NUM, 0, NULL },
104 { "ecache_size", 4, NUM, 0, NULL },
105 { "stick_divisor", 1, NUM, 0, NULL },
106 { "speed_table_width", 1, NUM, 0, NULL },
107 { "num_ecache_cfgs", 1, NUM, 0, NULL },
108/*
109 on excal, the next entry is a pad byte. Instead of defining
110 2 different structs with different names for this byte, we use
111 num_memc_cfgs and just leave it as 0 for excal.
112*/
113 { "num_memc_cfgs", 1, NUM, 0, NULL },
114/* { "pad", 1, NUM, 0, NULL }, */
115 { NULL, 0, 0, 0, NULL },
116};
117
118struct fixed_seeprom gm_cpu_seeprom_data[] = {
119 /* name size type value */
120 { "id_magic", 2, NUM, 0, set_magic_bytes },
121 { "id_format", 1, NUM, 0, set_format_byte },
122 { "cpu_ratios", 1, NUM, 0, NULL },
123 { "checksum", 2, NUM, 0, NULL },
124 { "clk_divisor", 1, NUM, 0, set_clk_div_byte },
125 { "cpu_id", 1, NUM, 0, NULL },
126 { "dcr", 8, NUM, 0, NULL },
127 { "lsucr", 8, NUM, 0, NULL },
128 { "core_config", 8, NUM, 0, NULL },
129 { "ecache_size", 4, NUM, 0, NULL },
130 { "stick_divisor", 1, NUM, 0, NULL },
131 { "speed_table_width", 1, NUM, 0, NULL },
132 { "num_ecache_cfgs", 1, NUM, 0, NULL },
133 { "num_memc_cfgs", 1, NUM, 0, NULL },
134 { NULL, 0, 0, 0, NULL },
135};
136
137struct fixed_seeprom serrano_cpu_seeprom_data[] = {
138 /* name size type value */
139 { "id_magic", 2, NUM, 0, set_magic_bytes },
140 { "id_format", 1, NUM, 0, set_format_byte },
141 { "cpu_id", 1, NUM, 0, NULL },
142 { "checksum", 2, NUM, 0, NULL },
143 { "cpu_ratios", 2, NUM, 0, NULL },
144 { "dcr", 8, NUM, 0, NULL },
145 { "lsucr", 8, NUM, 0, NULL },
146 { "ecache_size", 4, NUM, 0, NULL },
147 { "clk_divisor", 1, NUM, 0, set_clk_div_byte },
148 { "stick_divisor", 1, NUM, 0, NULL },
149 { "speed_table_width", 1, NUM, 0, NULL },
150 { "num_ecache_cfgs", 1, NUM, 0, NULL },
151 { "num_memc_cfgs", 1, NUM, 0, NULL },
152 { "pad", 7, NUM, 0, NULL },
153 { NULL, 0, 0, 0, NULL },
154};
155
156struct fixed_seeprom cpu_rw_data[] = {
157 /* name size type value */
158 { "id_magic", 2, NUM, 0, NULL },
159 { "id_format", 1, NUM, 0, set_format_byte },
160 { "num_memc_cfgs", 1, NUM, 0, NULL },
161 { NULL, 0, 0, 0, NULL },
162};
163
164
165data_reg dcr[] = {
166 /* field pos size */
167 { "obs", 6, 3 },
168 { "bpe", 5, 1 },
169 { "rpe", 4, 1 },
170 { "si", 3, 1 },
171 { "ms", 0, 1 },
172 { NULL, 0, 0 },
173};
174
175data_reg lsucr[] = {
176 /* field pos size */
177 { "cp", 49, 1 },
178 { "cv", 48, 1 },
179 { "me", 47, 1 },
180 { "re", 46, 1 },
181 { "pe", 45, 1 },
182 { "hpe", 44, 1 },
183 { "spe", 43, 1 },
184 { "sl", 42, 1 },
185 { "we", 41, 1 },
186 { "pm", 33, 8 },
187 { "vm", 25, 8 },
188 { "pr", 24, 1 },
189 { "pw", 23, 1 },
190 { "vr", 22, 1 },
191 { "vw", 21, 1 },
192 { "fm", 4, 16 },
193 { "dm", 3, 1 },
194 { "im", 2, 1 },
195 { "dc", 1, 1 },
196 { "ic", 0, 1 },
197 { NULL, 0, 0 },
198};
199
200static struct ecache_entry *cpu_ecache_table = NULL;
201static struct speed_entry *speed_table = NULL;
202static struct fiesta_memc_entry *fiesta_memc = NULL;
203
204static int
205calculate_mspd(unsigned short mclk, unsigned long long mcr2,
206 unsigned int cpuspeed)
207{
208
209#define MEM_SPEED(a, b) ((cpuspeed * a) / b)
210
211 int rc = NO_ERROR;
212 unsigned int mspeed, mcr2_ratio;
213
214 if (system_type == SERRANO) {
215 mcr2_ratio = mcr2 & 0x1f;
216 } else {
217 mcr2_ratio = mcr2 & 0xf;
218 }
219 switch (mcr2_ratio) {
220 case 0:
221 mspeed = MEM_SPEED(1, 8);
222 break;
223 case 2:
224 mspeed = MEM_SPEED(1, 9);
225 break;
226 case 4:
227 mspeed = MEM_SPEED(1, 10);
228 break;
229 case 5:
230 mspeed = MEM_SPEED(2, 21);
231 break;
232 case 6:
233 mspeed = MEM_SPEED(1, 11);
234 break;
235 case 8:
236 mspeed = MEM_SPEED(1, 12);
237 break;
238 case 9:
239 mspeed = MEM_SPEED(2, 25);
240 break;
241 case 0xa:
242 mspeed = MEM_SPEED(1, 13);
243 break;
244 case 0xb:
245 mspeed = MEM_SPEED(2, 27);
246 break;
247 case 0xc:
248 mspeed = MEM_SPEED(1, 14);
249 break;
250 case 0xe:
251 mspeed = MEM_SPEED(1, 15);
252 break;
253 /* following entries with bit 4 set are Serrano only */
254 case 0x10:
255 mspeed = MEM_SPEED(1, 16);
256 break;
257 case 0x11:
258 mspeed = MEM_SPEED(2, 33);
259 break;
260 case 0x13:
261 mspeed = MEM_SPEED(2, 35);
262 break;
263 case 0x14:
264 mspeed = MEM_SPEED(1, 18);
265 break;
266 default:
267 sprintf(err_string,
268 "memc_entry: Invalid CPU_SDRAM clk ratio %x",
269 mcr2_ratio);
270 rc = ERROR;
271 break;
272 }
273 if (mspeed > mclk) {
274 sprintf(err_string,
275 "memc_entry: calculated mem speed %d exceeds mclk %hd",
276 mspeed, mclk);
277 rc = ERROR;
278 }
279 return (rc);
280}
281
282/*
283 * MCR0_CTL_MASK is used to check if following control bits are set
284 * in the memc_entries, they should be 0:
285 * X4DIMM, Addr_Gen, DIMMX_bankY, AUTO_REFRESH_EN, CKE_EN, CLK_UPDATE,
286 * PRECHG_ALL, SET_MODE_REG
287 */
288
289#define MCR0_CTL_MASK -1 ^ 0x0ffffb03ff803fffLL
290
291/*
292 * Get fiesta_memc_entries parameters of format:
293 * memc_entry bus_max(Mhz) bus_min(Mhz) ratio mspeed mcr0 mcr1 mcr2
294 */
295
296static unsigned int
297fiesta_memc_input(char *line, struct fiesta_memc_entry *entry)
298{
299 char parameter[MAXNAMESIZE];
300 unsigned short bus_hi, bus_lo, entry_id, ratio, mclk;
301 unsigned long long mcr[3];
302 int i, entries;
303
304 for (i = 0; i < 3; i++)
305 mcr[i] = 0;
306
307 entries = sscanf(line, "%32s %hd %hd %hd %hd %hd %llx %llx %llx",
308 parameter, &bus_hi, &bus_lo, &entry_id, &ratio, &mclk, &mcr[0],
309 &mcr[1], &mcr[2]);
310 if ((entries != 9)) {
311 print_error("memc_entry line incorrectly defined");
312 return (ERROR);
313 }
314 if (bus_hi < bus_lo) {
315 print_error("memc_entry.bus_hi must be greater than bus_lo!");
316 return (ERROR);
317 }
318 if (entry_id > FIESTA_MAX_MEMC) {
319 sprintf(err_string, "memc_entry: id cannot exceed %d",
320 FIESTA_MAX_MEMC);
321 print_error(err_string);
322 return (ERROR);
323 }
324
325 entry->bus_hi = bus_hi;
326 entry->bus_lo = bus_lo;
327 entry->entry_id = entry_id;
328 entry->ratio = ratio;
329
330 if (calculate_mspd(mclk, mcr[1], bus_hi * ratio)) {
331 print_error(err_string);
332 sprintf(err_string, "Error in memc_entry %d", entry_id);
333 print_error(err_string);
334 return (ERROR);
335 } else {
336 entry->memclk = mclk;
337 }
338 if (system_type != SERRANO && mclk != 133) {
339 print_error("memc_entry.mspd must be 133 only !");
340 return (ERROR);
341 }
342 if (mcr[0] & ((unsigned long long) MCR0_CTL_MASK)) {
343 sprintf(err_string, "memc_entry id %d: "
344 "MCR0 control bits not zero. "
345 "Should be %llx\n", entry_id,
346 mcr[0] & (-1 ^ ((unsigned long long) MCR0_CTL_MASK)));
347 print_error(err_string);
348 return (ERROR);
349 }
350 for (i = 0; i < 3; i++) {
351 entry->mcr[i] = mcr[i];
352 }
353 entry->next = NULL;
354 return (NO_ERROR);
355}
356
357/*
358 * Get ecache_ctrl_reg parameters of format:
359 * ecache_ctrl_reg cpu_max(Mhz) cpu_min(Mhz) ecache_ctrl_reg_default
360 */
361static unsigned int
362get_ecache_input(char *line, struct ecache_entry *entry)
363{
364 char parameter[MAXNAMESIZE];
365 unsigned short cpu_max, cpu_min;
366 unsigned long long ecache[2];
367 int entries;
368
369 ecache[0] = 0;
370 ecache[1] = 0;
371 entries = sscanf(line, "%32s %hd %hd %llx %llx",
372 parameter, &cpu_max, &cpu_min, &ecache[0], &ecache[1]);
373 if ((entries < 4) || (entries > 5)) {
374 print_error("ecache_ctrl.reg line incorrectly defined");
375 return (0);
376 }
377 if (cpu_max < cpu_min) {
378 print_error("ecache_ctrl.reg.cpu_max must be greater"
379 "than cpu_min!");
380 return (0);
381 }
382 entry->cpu_max = cpu_max;
383 entry->cpu_min = cpu_min;
384 entry->ecache_cfg[0] = ecache[0];
385 if (entries == 5) entry->ecache_cfg[1] = ecache[1];
386 entry->next = NULL;
387 return (1);
388}
389
390/*
391 * Add fiesta_memc_entry to data structure
392 */
393static void
394update_fiesta_memc(struct fiesta_memc_entry *entry)
395{
396 struct fiesta_memc_entry *ptr;
397 unsigned long long temp;
398
399 ptr = fiesta_memc;
400 if (ptr == NULL) {
401 fiesta_memc = malloc(sizeof (struct fiesta_memc_entry));
402 *fiesta_memc = *entry;
403 } else {
404 while (ptr->next != NULL)
405 ptr = ptr->next;
406 ptr->next = malloc(sizeof (struct fiesta_memc_entry));
407 *ptr->next = *entry;
408 }
409 temp = get_seeprom("num_memc_cfgs");
410 update_seeprom("num_memc_cfgs", temp+1);
411}
412
413/*
414 * Add ecache_ctrl_reg entry to data structure
415 */
416static void
417update_ecache_table(struct ecache_entry *entry)
418{
419 struct ecache_entry *ptr;
420 unsigned long long temp;
421
422 ptr = cpu_ecache_table;
423 if (ptr == NULL) {
424 cpu_ecache_table = malloc(sizeof (struct ecache_entry));
425 *cpu_ecache_table = *entry;
426 } else {
427 while (ptr->next != NULL)
428 ptr = ptr->next;
429 ptr->next = malloc(sizeof (struct ecache_entry));
430 *ptr->next = *entry;
431 }
432 temp = get_seeprom("num_ecache_cfgs");
433 update_seeprom("num_ecache_cfgs", temp+1);
434}
435
436/*
437 * Remove duplicate speed entries and sort from lowest to highest
438 */
439static int
440sort_speed(unsigned short *speed_list, int num_speeds)
441{
442 unsigned short sort_list[MAXSPEEDLIST];
443 int i, j, done;
444 unsigned short lowest;
445
446 if (num_speeds == 1) {
447 if (speed_list[0] > MAX_SAFARI_SPEED) {
448 sprintf(err_string,
449 "cpu_sys_ratio.safari_speed must be <= %dMhz!",
450 MAX_SAFARI_SPEED);
451 print_error(err_string);
452 return (-1);
453 } else
454 return (1);
455 }
456
457 i = done = 0;
458 while (!done) {
459 done = 1;
460 lowest = MAX_SAFARI_SPEED;
461 for (j = 0; j < num_speeds; j++) {
462 if (speed_list[j] != 0) {
463 if (speed_list[j] > MAX_SAFARI_SPEED) {
464 sprintf(err_string,
465 "cpu_sys_ratio.safari_speed "
466 "must be <= %dMhz!",
467 MAX_SAFARI_SPEED);
468 print_error(err_string);
469 return (-1);
470 } else {
471 lowest = (lowest <= speed_list[j]) ?
472 lowest : speed_list[j];
473 done = 0;
474 }
475 }
476 }
477 if (!done) {
478 sort_list[i++] = lowest;
479 for (j = 0; j < num_speeds; j++) {
480 if (speed_list[j] == lowest) {
481 speed_list[j] = 0;
482 }
483 }
484 }
485 }
486 for (j = 0; j < i; j++)
487 speed_list[j] = sort_list[j];
488 return (i);
489}
490
491/*
492 * Update data structure with new speed entry
493 */
494static void
495update_speeds(unsigned short *speeds, unsigned short ratio, int num_speeds)
496{
497 struct speed_entry *ptr, *prev, *temp_ptr;
498 unsigned long long cpu_ratios;
499
500 int i;
501
502 /*
503 * if we already have entries for this ratio, delete them
504 */
505 if (get_seeprom("cpu_ratios") & (1 << (ratio - cpu_ratios_min))) {
506 ptr = prev = speed_table;
507 while (ptr->ratio != ratio) {
508 prev = ptr;
509 ptr = ptr->next;
510 }
511 while ((ptr != NULL) && (ptr->ratio == ratio)) {
512 temp_ptr = ptr;
513 ptr = ptr->next;
514 free(temp_ptr);
515 }
516 if (prev == speed_table)
517 speed_table = ptr;
518 else
519 prev->next = ptr;
520 }
521
522 /*
523 * add speeds for this ratio to the list
524 */
525
526 for (i = 0; i < num_speeds; i++) {
527 temp_ptr = malloc(sizeof (struct speed_entry));
528 temp_ptr->ratio = ratio;
529 temp_ptr->speed_hi = temp_ptr->speed_lo = speeds[i];
530 temp_ptr->next = NULL;
531 if (speed_table == NULL) {
532 speed_table = temp_ptr;
533 } else {
534 ptr = speed_table;
535 while (ptr->next != NULL) {
536 ptr = ptr->next;
537 }
538 ptr->next = temp_ptr;
539 }
540 }
541 cpu_ratios = get_seeprom("cpu_ratios");
542 cpu_ratios |= (1 << (ratio - cpu_ratios_min));
543 update_seeprom("cpu_ratios", cpu_ratios);
544}
545
546/*
547Get cpu_sys_ratio parameters of format:
548cpu_sys_ratio cpu/sys_ratio Valid_Safari_speed(Mhz)
549
550Multiple valid Safari speeds may be separated by commas.
551*/
552static unsigned int
553get_speed_input(char *line, unsigned short *speeds,
554 unsigned short *ratio, int *num_speeds)
555{
556 char parameter[MAXNAMESIZE], speedinfo[MAXLINE];
557 char *temp;
558 int i;
559
560 if (sscanf(line, "%32s %hd %s", parameter, ratio, speedinfo) == 3) {
561 if ((*ratio > speed_ratio_max) || (*ratio < speed_ratio_min)) {
562 sprintf(err_string, "Invalid cpu_sys_ratio: %d",
563 *ratio);
564 print_error(err_string);
565 return (0);
566 }
567 temp = strtok(speedinfo, ",");
568 i = 0;
569 while (temp != NULL) {
570 if (sscanf(temp, "%hd", &speeds[i++])) {
571 temp = strtok(NULL, ",");
572 } else {
573 sprintf(err_string,
574 "Invalid cpu_sys_ratio.safari_speed: %s",
575 temp);
576 print_error(err_string);
577 return (0);
578 }
579 }
580 *num_speeds = sort_speed(speeds, i);
581 if (*num_speeds == -1)
582 return (0);
583 else
584 return (1);
585 }
586 return (0);
587}
588
589/*
590Calculate speed table width
591*/
592static unsigned long long
593speed_table_width(void)
594{
595 struct speed_entry *ptr;
596 unsigned short count, biggest;
597
598 ptr = speed_table;
599 biggest = count = 1;
600 while (ptr->next != NULL) {
601 if (ptr->ratio == ptr->next->ratio) {
602 count++;
603 if (count > biggest) biggest = count;
604 } else {
605 count = 1;
606 }
607 ptr = ptr->next;
608 }
609 return (biggest);
610}
611
612int
613cpu_dynamic(char *parameter, char *line)
614{
615 if (strcmp(parameter, "ecache_ctrl_reg") == 0) {
616 if (system_type != GMFIESTA) {
617 struct ecache_entry new_ecache_entry;
618 if (get_ecache_input(line, &new_ecache_entry))
619 update_ecache_table(&new_ecache_entry);
620 else
621 return (ERROR);
622 }
623 } else if (strcmp(parameter, "cpu_sys_ratio") == 0) {
624 unsigned short speed_list[MAXSPEEDLIST];
625 unsigned short ratio;
626 int num_speeds;
627 switch (system_type) {
628 case FIESTA:
629 case GMFIESTA:
630 speed_ratio_max = 10;
631 speed_ratio_min = 6;
632 cpu_ratios_min = 3;
633 cpu_ratios_bits = 8;
634 break;
635 case SERRANO:
636 speed_ratio_max = 16;
637 speed_ratio_min = 6;
638 cpu_ratios_min = 6;
639 cpu_ratios_bits = 16;
640 break;
641 default:
642 speed_ratio_max = 10;
643 speed_ratio_min = 4;
644 cpu_ratios_min = 3;
645 cpu_ratios_bits = 8;
646 break;
647 }
648 if (get_speed_input(line, speed_list, &ratio, &num_speeds))
649 update_speeds(speed_list, ratio, num_speeds);
650 else
651 return (ERROR);
652 } else if (strcmp(parameter, "memc_entry") == 0) {
653 switch (system_type) {
654 struct fiesta_memc_entry new_memc_entry;
655 case FIESTA:
656 case GMFIESTA:
657 case SERRANO:
658 if (!fiesta_memc_input(line, &new_memc_entry))
659 update_fiesta_memc(&new_memc_entry);
660 else
661 return (ERROR);
662 default:
663 break;
664 }
665 } else {
666 return (UNKNOWN);
667 }
668 return (NO_ERROR);
669}
670
671static void
672free_cpu(void)
673{
674 struct ecache_entry *ecache, *tmp1;
675 struct speed_entry *speed, *tmp2;
676 struct fiesta_memc_entry *memc, *tmp3;
677
678 if (cpu_ecache_table != NULL) {
679 ecache = cpu_ecache_table;
680 while (ecache->next != NULL) {
681 tmp1 = ecache->next;
682 free(ecache);
683 ecache = tmp1;
684 }
685 free(ecache);
686 }
687
688 if (speed_table != NULL) {
689 speed = speed_table;
690 while (speed->next != NULL) {
691 tmp2 = speed->next;
692 free(speed);
693 speed = tmp2;
694 }
695 free(speed);
696 }
697
698 if (fiesta_memc != NULL) {
699 memc = fiesta_memc;
700 while (memc->next != NULL) {
701 tmp3 = memc->next;
702 free(memc);
703 memc = tmp3;
704 }
705 free(memc);
706 }
707}
708
709void
710write_cpu(unsigned char **ptr)
711{
712 struct ecache_entry *ecache;
713 struct speed_entry *speed;
714 struct fiesta_memc_entry *memc;
715 unsigned short ratio;
716 int i;
717
718 ecache = cpu_ecache_table;
719 while (ecache != NULL) {
720 store_bytes(2, (unsigned long long) ecache->cpu_max, ptr);
721 store_bytes(2, (unsigned long long) ecache->cpu_min, ptr);
722 store_bytes(8, ecache->ecache_cfg[0], ptr);
723 if (format_mode == 2 || format_mode == 3) {
724 store_bytes(8, ecache->ecache_cfg[1], ptr);
725 }
726 ecache = ecache->next;
727 }
728
729 if (fixed_parameter("speed_table_width")) {
730 int width = (int)get_seeprom("speed_table_width");
731 int found = 0;
732
733 for (i = 0; i < cpu_ratios_bits; i++, found = 0) {
734 if (get_seeprom("cpu_ratios") & (1 << i)) {
735 ratio = i+ cpu_ratios_min;
736 speed = speed_table;
737 /*
738 * Stay at this ratio until all found and
739 * stored.
740 */
741 while (speed != NULL) {
742 if (speed->ratio == ratio) {
743 store_bytes(1, speed->speed_hi,
744 ptr);
745 store_bytes(1, speed->speed_lo,
746 ptr);
747 speed->ratio = 0;
748 found++;
749 }
750 speed = speed->next;
751 }
752 while (found++ < width) {
753 store_bytes(2, 0, ptr);
754 }
755 }
756 }
757 }
758 memc = fiesta_memc;
759 while (memc != NULL) {
760 store_bytes(2, (unsigned long long) memc->bus_hi, ptr);
761 store_bytes(2, (unsigned long long) memc->bus_lo, ptr);
762 store_bytes(1, (unsigned long long) memc->entry_id, ptr);
763 store_bytes(1, (unsigned long long) memc->ratio, ptr);
764 store_bytes(2, (unsigned long long) memc->memclk, ptr);
765 for (i = 0; i < 3; i++)
766 store_bytes(8, memc->mcr[i], ptr);
767 memc = memc->next;
768 }
769 free_cpu();
770}
771
772void
773dump_cpu(void)
774{
775 struct ecache_entry *ecache;
776 struct speed_entry *speed;
777 struct fiesta_memc_entry *memc;
778
779 ecache = cpu_ecache_table;
780 if (ecache != NULL)
781 printf("ecache_ctrl_reg: "
782 "cpu_max cpu_min ecache_cfg\n");
783 while (ecache != NULL) {
784 printf(" %hd"
785 " %hd 0x%llx",
786 ecache->cpu_max, ecache->cpu_min, ecache->ecache_cfg[0]);
787 if (format_mode == 2 || format_mode == 3)
788 printf(" 0x%llx", ecache->ecache_cfg[1]);
789 printf("\n");
790 ecache = ecache->next;
791 }
792
793 speed = speed_table;
794 if (speed != NULL)
795 printf("cpu_sys_ratio: ratio speed\n");
796 while (speed != NULL) {
797 printf(" %hd %hd\n",
798 speed->ratio, speed->speed_hi);
799 speed = speed->next;
800 }
801
802 memc = fiesta_memc;
803 if (memc != NULL) {
804 printf("memc_entries:\n");
805 printf("hi lo id ratio memclk");
806 printf(" mcr1 mcr2 mcr3\n");
807 while (memc != NULL) {
808 printf("%-4hd %-4hd %-1hd %-1hd %-4hd",
809 memc->bus_hi, memc->bus_lo, memc->entry_id,
810 memc->ratio, memc->memclk);
811 printf(" 0x%016llx 0x%016llx 0x%016llx\n",
812 memc->mcr[0], memc->mcr[1], memc->mcr[2]);
813 memc = memc->next;
814 }
815 }
816}
817
818int
819match_ecache_cfg(unsigned short speed)
820{
821 struct ecache_entry *ecache;
822
823 ecache = cpu_ecache_table;
824 while (ecache != NULL) {
825 if ((speed >= ecache->cpu_min) && (speed <= ecache->cpu_max)) {
826 return (1);
827 }
828 ecache = ecache->next;
829 }
830 sprintf(err_string, "No ecache cfg entry for cpu speed %d", speed);
831 print_error(err_string);
832 return (0);
833}
834
835static int
836ecache_fmt(unsigned long long e_size, int format)
837{
838 struct ecache_entry *ecache;
839 unsigned int ecache_code;
840 int error = NO_ERROR;
841 int size_pos = 0;
842
843 switch (system_type) {
844 case EXCALIBUR:
845 switch (format) {
846 case 1:
847 case 2:
848 case 3:
849 switch (e_size) {
850 case 0x100000:
851 case 0x400000:
852 case 0x800000:
853 size_pos = 13;
854 ecache_code = e_size / 0x400000;
855 ecache_code <<= size_pos;
856 break;
857 default:
858 error = ERROR;
859 break;
860 }
861 break;
862 default:
863 error = ERROR;
864 break;
865 }
866 break;
867 default:
868 error = ERROR;
869 break;
870 }
871
872 if (error == NO_ERROR) {
873 ecache = cpu_ecache_table;
874 while (ecache != NULL) {
875 int cfg = ecache->ecache_cfg[0] &
876 (3 << size_pos);
877 if (cfg != ecache_code) {
878 fprintf(stderr,
879 "WARNING: Changing "
880 "ecache_cfg.EC_SIZE "
881 "to match ecache_size!\n");
882 }
883 ecache->ecache_cfg[0] &= (-1^(3 << size_pos));
884 ecache->ecache_cfg[0] |= ecache_code;
885 ecache = ecache->next;
886 }
887 } else {
888 printf("Invalid id_format or ecache size!\n");
889 }
890 return (error);
891}
892
893int
894match_memc_cfg(unsigned short speed, unsigned short ratio)
895{
896 struct fiesta_memc_entry *memc_table;
897
898 memc_table = fiesta_memc;
899 while (memc_table != NULL) {
900 if ((memc_table->bus_hi == speed) &&
901 (memc_table->ratio == ratio)) {
902 return (1);
903 }
904 memc_table = memc_table->next;
905 }
906 sprintf(err_string, "No memc cfg entry for ratio %d sys speed %d",
907 ratio, speed);
908 print_error(err_string);
909 return (0);
910}
911
912int
913check_cpu(void)
914{
915 int error = 0;
916 struct speed_entry *speed_ptr;
917 unsigned long long temp;
918
919 if (type == CPU) {
920 if (speed_table == NULL) {
921 print_error("Must specify a cpu_sys_ratio entry!");
922 error = ERROR;
923 } else {
924 update_seeprom("speed_table_width",
925 speed_table_width());
926 speed_ptr = speed_table;
927 while (speed_ptr != NULL) {
928 if (system_type != GMFIESTA &&
929 !match_ecache_cfg(speed_ptr->speed_hi*
930 speed_ptr->ratio))
931 error = ERROR;
932 if (system_type == FIESTA ||
933 system_type == GMFIESTA ||
934 system_type == SERRANO)
935 if (!match_memc_cfg(speed_ptr->speed_hi,
936 speed_ptr->ratio))
937 error = ERROR;
938 speed_ptr = speed_ptr->next;
939 }
940 }
941 }
942 if (type == CPU_RW &&
943 (system_type == FIESTA || system_type == GMFIESTA ||
944 system_type == SERRANO)) {
945 if (format_mode != 1) {
946 print_error("Invalid id_format!");
947 error = ERROR;
948 }
949 }
950 if (fiesta_memc == NULL &&
951 (system_type == FIESTA || system_type == GMFIESTA ||
952 system_type == SERRANO)) {
953 print_error("Must specify a memc entry!");
954 error = ERROR;
955 }
956
957 if (fixed_parameter("ecache_size") && (system_type == EXCALIBUR)) {
958 if (ecache_fmt(get_seeprom("ecache_size"), format_mode))
959 error = ERROR;
960 }
961 if ((type == CPU) && (id_magic != CPU_DEFAULT_MAGIC)) {
962 if (!clk_div_set) {
963 print_error("Must specify clk_divisor!");
964 error = ERROR;
965 }
966 }
967 return (error);
968}
969
970int
971reg_cpu(char *s1, data_reg **reg)
972{
973 int count = 0;
974 if (strcmp(s1, "lsucr") == 0) {
975 *reg = &lsucr[0];
976 count = sizeof (lsucr) / sizeof (data_reg);
977 } else if (strcmp(s1, "dcr") == 0) {
978 *reg = &dcr[0];
979 count = sizeof (dcr) / sizeof (data_reg);
980 }
981 return (count);
982}