printk_foo -> printk(BIOS_FOO, ...)
[coreboot.git] / src / northbridge / amd / amdfam10 / amdfam10_conf.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2007 Advanced Micro Devices, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
18  */
19
20 #if defined(__PRE_RAM__)
21 typedef struct sys_info sys_info_conf_t;
22 #else
23 typedef struct amdfam10_sysconf_t sys_info_conf_t;
24 #endif
25
26 struct dram_base_mask_t {
27         u32 base; //[47:27] at [28:8]
28         u32 mask; //[47:27] at [28:8] and enable at bit 0
29 };
30
31 static struct dram_base_mask_t get_dram_base_mask(u32 nodeid)
32 {
33         device_t dev;
34         struct dram_base_mask_t d;
35 #if defined(__PRE_RAM__)
36         dev = PCI_DEV(CONFIG_CBB, CONFIG_CDB, 1);
37 #else
38         dev = __f1_dev[0];
39 #endif
40
41 #if CONFIG_EXT_CONF_SUPPORT == 1
42         // I will use ext space only for simple
43         pci_write_config32(dev, 0x110, nodeid | (1<<28)); // [47:27] at [28:8]
44         d.mask = pci_read_config32(dev, 0x114);  // enable is bit 0
45         pci_write_config32(dev, 0x110, nodeid | (0<<28));
46         d.base = pci_read_config32(dev, 0x114) & 0x1fffff00; //[47:27] at [28:8];
47 #else
48         u32 temp;
49         temp = pci_read_config32(dev, 0x44 + (nodeid << 3)); //[39:24] at [31:16]
50         d.mask = ((temp & 0xfff80000)>>(8+3)); // mask out  DramMask [26:24] too
51         temp = pci_read_config32(dev, 0x144 + (nodeid <<3)) & 0xff; //[47:40] at [7:0]
52         d.mask |= temp<<21;
53
54         temp = pci_read_config32(dev, 0x40 + (nodeid << 3)); //[39:24] at [31:16]
55         d.mask |= (temp & 1); // enable bit
56
57         d.base = ((temp & 0xfff80000)>>(8+3)); // mask out DramBase [26:24) too
58         temp = pci_read_config32(dev, 0x140 + (nodeid <<3)) & 0xff; //[47:40] at [7:0]
59         d.base |= temp<<21;
60 #endif
61         return d;
62 }
63
64 static void set_dram_base_mask(u32 nodeid, struct dram_base_mask_t d, u32 nodes)
65 {
66         u32 i;
67         device_t dev;
68 #if CONFIG_EXT_CONF_SUPPORT == 1
69         // I will use ext space only for simple
70         u32 d_base_i, d_base_d, d_mask_i, d_mask_d;
71         d_base_i = nodeid | (0<<28);
72         d_base_d = d.base | nodeid; //[47:27] at [28:8];
73         d_mask_i = nodeid | (1<<28); // [47:27] at [28:8]
74         d_mask_d = d.mask;  // enable is bit 0
75
76 #else
77         u32 d_base_lo, d_base_hi, d_mask_lo, d_mask_hi;
78         u32 d_base_lo_reg, d_base_hi_reg, d_mask_lo_reg, d_mask_hi_reg;
79         d_mask_lo =  (((d.mask<<(8+3))|(0x07<<16)) & 0xffff0000)|nodeid; // need to fill DramMask[26:24] with ones
80         d_mask_hi =  (d.mask>>21) & 0xff;
81         d_base_lo = ((d.base<<(8+3)) & 0xffff0000);
82         if(d.mask & 1) d_base_lo |= 3;
83         d_base_hi = (d.base>>21) & 0xff;
84         d_mask_lo_reg = 0x44+(nodeid<<3);
85         d_mask_hi_reg = 0x144+(nodeid<<3);
86         d_base_lo_reg = 0x40+(nodeid<<3);
87         d_base_hi_reg = 0x140+(nodeid<<3);
88 #endif
89
90         for(i=0;i<nodes;i++) {
91 #if defined(__PRE_RAM__)
92                 dev = NODE_PCI(i, 1);
93 #else
94                 dev = __f1_dev[i];
95 #endif
96
97 #if CONFIG_EXT_CONF_SUPPORT == 1
98                 // I will use ext space only for simple
99                 pci_write_config32(dev, 0x110, d_base_i);
100                 pci_write_config32(dev, 0x114, d_base_d); //[47:27] at [28:8];
101                 pci_write_config32(dev, 0x110, d_mask_i); // [47:27] at [28:8]
102                 pci_write_config32(dev, 0x114, d_mask_d);  // enable is bit 0
103 #else
104                 pci_write_config32(dev, d_mask_lo_reg, d_mask_lo); // need to fill DramMask[26:24] with ones
105                 pci_write_config32(dev, d_mask_hi_reg, d_mask_hi);
106                 pci_write_config32(dev, d_base_lo_reg, d_base_lo);
107                 pci_write_config32(dev, d_base_hi_reg, d_base_hi);
108 #endif
109         }
110
111 #if defined(__PRE_RAM__)
112         dev = NODE_PCI(nodeid, 1);
113 #else
114         dev = __f1_dev[nodeid];
115 #endif
116         pci_write_config32(dev, 0x120, d.base>>8);
117         pci_write_config32(dev, 0x124, d.mask>>8);
118
119 }
120
121
122 static void set_DctSelBaseAddr(u32 i, u32 sel_m)
123 {
124         device_t dev;
125 #if defined(__PRE_RAM__)
126         dev = NODE_PCI(i, 2);
127 #else
128                 dev = __f2_dev[i];
129 #endif
130         u32 dcs_lo;
131         dcs_lo = pci_read_config32(dev, DRAM_CTRL_SEL_LOW);
132         dcs_lo &= ~(DCSL_DctSelBaseAddr_47_27_MASK<<DCSL_DctSelBaseAddr_47_27_SHIFT);
133         dcs_lo |= (sel_m<<(20+DCSL_DctSelBaseAddr_47_27_SHIFT-27));
134         pci_write_config32(dev, DRAM_CTRL_SEL_LOW, dcs_lo);
135
136 }
137
138
139 static u32 get_DctSelBaseAddr(u32 i)
140 {
141         device_t dev;
142 #if defined(__PRE_RAM__)
143         dev = NODE_PCI(i, 2);
144 #else
145                 dev = __f2_dev[i];
146 #endif
147         u32 sel_m;
148         u32 dcs_lo;
149         dcs_lo = pci_read_config32(dev, DRAM_CTRL_SEL_LOW);
150         dcs_lo &= DCSL_DctSelBaseAddr_47_27_MASK<<DCSL_DctSelBaseAddr_47_27_SHIFT;
151         sel_m = dcs_lo>>(20+DCSL_DctSelBaseAddr_47_27_SHIFT-27);
152         return sel_m;
153 }
154
155
156 static void set_DctSelHiEn(u32 i, u32 val)
157 {
158         device_t dev;
159 #if defined(__PRE_RAM__)
160         dev = NODE_PCI(i, 2);
161 #else
162                 dev = __f2_dev[i];
163 #endif
164         u32 dcs_lo;
165         dcs_lo = pci_read_config32(dev, DRAM_CTRL_SEL_LOW);
166         dcs_lo &= ~(7);
167         dcs_lo |= (val & 7);
168         pci_write_config32(dev, DRAM_CTRL_SEL_LOW, dcs_lo);
169
170 }
171
172 static u32 get_DctSelHiEn(u32 i)
173 {
174         device_t dev;
175 #if defined(__PRE_RAM__)
176         dev = NODE_PCI(i, 2);
177 #else
178         dev = __f2_dev[i];
179 #endif
180         u32 dcs_lo;
181         dcs_lo = pci_read_config32(dev, DRAM_CTRL_SEL_LOW);
182         dcs_lo &= 7;
183         return dcs_lo;
184
185 }
186
187 static void set_DctSelBaseOffset(u32 i, u32 sel_off_m)
188 {
189         device_t dev;
190 #if defined(__PRE_RAM__)
191         dev = NODE_PCI(i, 2);
192 #else
193         dev = __f2_dev[i];
194 #endif
195         u32 dcs_hi;
196         dcs_hi = pci_read_config32(dev, DRAM_CTRL_SEL_HIGH);
197         dcs_hi &= ~(DCSH_DctSelBaseOffset_47_26_MASK<<DCSH_DctSelBaseOffset_47_26_SHIFT);
198         dcs_hi |= sel_off_m<<(20+DCSH_DctSelBaseOffset_47_26_SHIFT-26);
199         pci_write_config32(dev, DRAM_CTRL_SEL_HIGH, dcs_hi);
200
201 }
202
203 static u32 get_DctSelBaseOffset(u32 i)
204 {
205         device_t dev;
206 #if defined(__PRE_RAM__)
207         dev = NODE_PCI(i, 2);
208 #else
209         dev = __f2_dev[i];
210 #endif
211         u32 sel_off_m;
212         u32 dcs_hi;
213         dcs_hi = pci_read_config32(dev, DRAM_CTRL_SEL_HIGH);
214         dcs_hi &= DCSH_DctSelBaseOffset_47_26_MASK<<DCSH_DctSelBaseOffset_47_26_SHIFT;
215         sel_off_m = dcs_hi>>(20+DCSH_DctSelBaseOffset_47_26_SHIFT-26);
216         return sel_off_m;
217 }
218 #if CONFIG_AMDMCT == 0
219
220 static u32 get_one_DCT(struct mem_info *meminfo)
221 {
222         u32 one_DCT = 1;
223         if(meminfo->is_Width128) {
224                 one_DCT = 1;
225         } else {
226                 u32 dimm_mask = meminfo->dimm_mask;
227                 if((dimm_mask >> DIMM_SOCKETS) && (dimm_mask & ((1<<DIMM_SOCKETS)-1))) {
228                          one_DCT = 0;
229                 }
230         }
231
232         return one_DCT;
233 }
234 #endif
235 #if CONFIG_HW_MEM_HOLE_SIZEK != 0
236
237 static u32 hoist_memory(u32 hole_startk, u32 i, u32 one_DCT, u32 nodes)
238 {
239         u32 ii;
240         u32 carry_over;
241         device_t dev;
242         struct dram_base_mask_t d;
243         u32 sel_m;
244         u32 sel_hi_en;
245         u32 hoist;
246
247
248         carry_over = (4*1024*1024) - hole_startk;
249
250         for(ii=nodes - 1;ii>i;ii--) {
251                 d = get_dram_base_mask(ii);
252                 if(!(d.mask & 1)) continue;
253                 d.base += (carry_over>>9);
254                 d.mask += (carry_over>>9);
255                 set_dram_base_mask(ii, d, nodes);
256
257                 if(get_DctSelHiEn(ii) & 1) {
258                         sel_m = get_DctSelBaseAddr(ii);
259                         sel_m += carry_over>>10;
260                         set_DctSelBaseAddr(ii, sel_m);
261                 }
262
263         }
264         d = get_dram_base_mask(i);
265         d.mask += (carry_over>>9);
266         set_dram_base_mask(i,d, nodes);
267 #if defined(__PRE_RAM__)
268         dev = NODE_PCI(i, 1);
269 #else
270         dev = __f1_dev[i];
271 #endif
272         sel_hi_en =  get_DctSelHiEn(i);
273         if(sel_hi_en & 1) {
274                 sel_m = get_DctSelBaseAddr(i);
275         }
276         if(d.base == (hole_startk>>9)) {
277                 //don't need set memhole here, because hole off set will be 0, overflow
278                 //so need to change base reg instead, new basek will be 4*1024*1024
279                 d.base = (4*1024*1024)>>9;
280                 set_dram_base_mask(i, d, nodes);
281
282                 if(sel_hi_en & 1) {
283                         sel_m += carry_over>>10;
284                         set_DctSelBaseAddr(i, sel_m);
285                 }
286         } else {
287                 hoist = /* hole start address */
288                         ((hole_startk << 10) & 0xff000000) +
289                         /* enable */
290                         1;
291                 if(one_DCT||(sel_m>=(hole_startk>>10))) { //one DCT or hole in DCT0
292                         hoist +=
293                         /* hole address to memory controller address */
294                         ((((d.base<<9) + carry_over) >> 6) & 0x0000ff00) ;
295
296                         if(sel_hi_en & 1) {
297                                 sel_m += (carry_over>>10);
298                                 set_DctSelBaseAddr(i, sel_m);
299                                 set_DctSelBaseOffset(i, sel_m);
300                         }
301                 } else { // hole in DCT1 range
302                         hoist +=
303                         /* hole address to memory controller address */
304                         ((((sel_m<<10) + carry_over) >> 6) & 0x0000ff00) ;
305                         // don't need to update DctSelBaseAddr
306                         if(sel_hi_en & 1) {
307                                 set_DctSelBaseOffset(i, sel_m);
308                         }
309                 }
310                 pci_write_config32(dev, 0xf0, hoist);
311
312         }
313
314         return carry_over;
315 }
316 #endif
317
318
319 #if CONFIG_EXT_CONF_SUPPORT
320 static void set_addr_map_reg_4_6_in_one_node(u32 nodeid, u32 cfg_map_dest,
321                                                 u32 busn_min, u32 busn_max,
322                                                 u32 type)
323 {
324         device_t dev;
325         u32 i;
326         u32 tempreg;
327         u32 index_min, index_max;
328         u32 dest_min, dest_max;
329         index_min = busn_min>>2; dest_min = busn_min - (index_min<<2);
330         index_max = busn_max>>2; dest_max = busn_max - (index_max<<2);
331
332         // three case: index_min==index_max, index_min+1=index_max; index_min+1<index_max
333 #if defined(__PRE_RAM__)
334         dev = NODE_PCI(nodeid, 1);
335 #else
336         dev = __f1_dev[nodeid];
337 #endif
338         if(index_min== index_max) {
339                 pci_write_config32(dev, 0x110, index_min | (type<<28));
340                 tempreg = pci_read_config32(dev, 0x114);
341                 for(i=dest_min; i<=dest_max; i++) {
342                         tempreg &= ~(0xff<<(i*8));
343                         tempreg |= (cfg_map_dest<<(i*8));
344                 }
345                 pci_write_config32(dev, 0x110, index_min | (type<<28)); // do i need to write it again
346                 pci_write_config32(dev, 0x114, tempreg);
347         } else if(index_min<index_max) {
348                 pci_write_config32(dev, 0x110, index_min | (type<<28));
349                 tempreg = pci_read_config32(dev, 0x114);
350                 for(i=dest_min; i<=3; i++) {
351                         tempreg &= ~(0xff<<(i*8));
352                         tempreg |= (cfg_map_dest<<(i*8));
353                 }
354                 pci_write_config32(dev, 0x110, index_min | (type<<28)); // do i need to write it again
355                 pci_write_config32(dev, 0x114, tempreg);
356
357                 pci_write_config32(dev, 0x110, index_max | (type<<28));
358                 tempreg = pci_read_config32(dev, 0x114);
359                 for(i=0; i<=dest_max; i++) {
360                         tempreg &= ~(0xff<<(i*8));
361                         tempreg |= (cfg_map_dest<<(i*8));
362                 }
363                 pci_write_config32(dev, 0x110, index_max | (type<<28)); // do i need to write it again
364                 pci_write_config32(dev, 0x114, tempreg);
365                 if((index_max-index_min)>1) {
366                         tempreg = 0;
367                         for(i=0; i<=3; i++) {
368                                 tempreg &= ~(0xff<<(i*8));
369                                 tempreg |= (cfg_map_dest<<(i*8));
370                         }
371                         for(i=index_min+1; i<index_max;i++) {
372                                 pci_write_config32(dev, 0x110, i | (type<<28));
373                                 pci_write_config32(dev, 0x114, tempreg);
374                         }
375                 }
376         }
377 }
378 #endif
379
380 static void set_config_map_reg(u32 nodeid, u32 linkn, u32 ht_c_index,
381                                 u32 busn_min, u32 busn_max, u32 segbit,
382                                 u32 nodes)
383 {
384         u32 tempreg;
385         u32 i;
386         device_t dev;
387
388         busn_min>>=segbit;
389         busn_max>>=segbit;
390
391 #if CONFIG_EXT_CONF_SUPPORT
392         if(ht_c_index < 4) {
393 #endif
394                 tempreg = 3 | ((nodeid&0xf)<<4) | ((nodeid & 0x30)<<(12-4))|(linkn<<8)|((busn_min & 0xff)<<16)|((busn_max&0xff)<<24);
395                 for(i=0; i<nodes; i++) {
396                 #if defined(__PRE_RAM__)
397                         dev = NODE_PCI(i, 1);
398                 #else
399                         dev = __f1_dev[i];
400                 #endif
401                         pci_write_config32(dev, 0xe0 + ht_c_index * 4, tempreg);
402                 }
403 #if CONFIG_EXT_CONF_SUPPORT
404
405                 return;
406         }
407
408         // if ht_c_index > 3, We should use extend space x114_x6
409         u32 cfg_map_dest;
410         u32 j;
411
412         // for nodeid at first
413         cfg_map_dest = (1<<7) | (1<<6) | (linkn<<0);
414
415         set_addr_map_reg_4_6_in_one_node(nodeid, cfg_map_dest, busn_min, busn_max, 6);
416
417         // all other nodes
418         cfg_map_dest = (1<<7) | (0<<6) | (nodeid<<0);
419         for(j = 0; j< nodes; j++) {
420                 if(j== nodeid) continue;
421                 set_addr_map_reg_4_6_in_one_node(j,cfg_map_dest, busn_min, busn_max, 6);
422         }
423 #endif
424 }
425
426 static void clear_config_map_reg(u32 nodeid, u32 linkn, u32 ht_c_index,
427                                         u32 busn_min, u32 busn_max, u32 nodes)
428 {
429         u32 i;
430         device_t dev;
431
432 #if CONFIG_EXT_CONF_SUPPORT
433         if(ht_c_index<4) {
434 #endif
435                 for(i=0; i<nodes; i++) {
436                 #if defined(__PRE_RAM__)
437                         dev = NODE_PCI(i, 1);
438                 #else
439                         dev = __f1_dev[i];
440                 #endif
441                         pci_write_config32(dev, 0xe0 + ht_c_index * 4, 0);
442                 }
443 #if CONFIG_EXT_CONF_SUPPORT
444                 return;
445         }
446
447         // if hc_c_index >3, We should use busn_min and busn_max to clear extend space
448         u32 cfg_map_dest;
449         u32 j;
450
451
452         // all nodes
453         cfg_map_dest = 0;
454         for(j = 0; j< nodes; j++) {
455                 set_addr_map_reg_4_6_in_one_node(j,cfg_map_dest, busn_min, busn_max, 6);
456         }
457 #endif
458
459 }
460
461 #if CONFIG_PCI_BUS_SEGN_BITS
462 static u32 check_segn(device_t dev, u32 segbusn, u32 nodes,
463                         sys_info_conf_t *sysinfo)
464 {
465         //check segbusn here, We need every node have the same segn
466         if((segbusn & 0xff)>(0xe0-1)) {// use next segn
467                 u32 segn = (segbusn >> 8) & 0x0f;
468                 segn++;
469                 segbusn = segn<<8;
470         }
471         if(segbusn>>8) {
472                 u32 val;
473                 val = pci_read_config32(dev, 0x160);
474                 val &= ~(0xf<<25);
475                 val |= (segbusn & 0xf00)<<(25-8);
476                 pci_write_config32(dev, 0x160, val);
477         }
478
479         return segbusn;
480 }
481 #endif
482
483 #if defined(__PRE_RAM__)
484 static void set_ht_c_io_addr_reg(u32 nodeid, u32 linkn, u32 ht_c_index,
485                                         u32 io_min, u32 io_max, u32 nodes)
486 {
487         u32 i;
488         u32 tempreg;
489         device_t dev;
490
491 #if CONFIG_EXT_CONF_SUPPORT
492         if(ht_c_index<4) {
493 #endif
494                 /* io range allocation */
495                 tempreg = (nodeid&0xf) | ((nodeid & 0x30)<<(8-4)) | (linkn<<4) |  ((io_max&0xf0)<<(12-4)); //limit
496                 for(i=0; i<nodes; i++) {
497                 #if defined(__PRE_RAM__)
498                         dev = NODE_PCI(i, 1);
499                 #else
500                         dev = __f1_dev[i];
501                 #endif
502                         pci_write_config32(dev, 0xC4 + ht_c_index * 8, tempreg);
503                 }
504                 tempreg = 3 /*| ( 3<<4)*/ | ((io_min&0xf0)<<(12-4));         //base :ISA and VGA ?
505                 for(i=0; i<nodes; i++){
506                 #if defined(__PRE_RAM__)
507                         dev = NODE_PCI(i, 1);
508                 #else
509                         dev = __f1_dev[i];
510                 #endif
511                         pci_write_config32(dev, 0xC0 + ht_c_index * 8, tempreg);
512                 }
513 #if CONFIG_EXT_CONF_SUPPORT
514                 return;
515         }
516
517         u32 cfg_map_dest;
518         u32 j;
519
520         // if ht_c_index > 3, We should use extend space
521
522         if(io_min>io_max) return;
523
524         // for nodeid at first
525         cfg_map_dest = (1<<7) | (1<<6) | (linkn<<0);
526
527         set_addr_map_reg_4_6_in_one_node(nodeid, cfg_map_dest, io_min, io_max, 4);
528
529         // all other nodes
530         cfg_map_dest = (1<<7) | (0<<6) | (nodeid<<0);
531         for(j = 0; j< nodes; j++) {
532                 if(j== nodeid) continue;
533                 set_addr_map_reg_4_6_in_one_node(j,cfg_map_dest, io_min, io_max, 4);
534         }
535 #endif
536 }
537
538
539 static void clear_ht_c_io_addr_reg(u32 nodeid, u32 linkn, u32 ht_c_index,
540                                         u32 io_min, u32 io_max, u32 nodes)
541 {
542         u32 i;
543         device_t dev;
544 #if CONFIG_EXT_CONF_SUPPORT
545         if(ht_c_index<4) {
546 #endif
547                  /* io range allocation */
548                 for(i=0; i<nodes; i++) {
549                 #if defined(__PRE_RAM__)
550                         dev = NODE_PCI(i, 1);
551                 #else
552                         dev = __f1_dev[i];
553                 #endif
554                         pci_write_config32(dev, 0xC4 + ht_c_index * 8, 0);
555                         pci_write_config32(dev, 0xC0 + ht_c_index * 8, 0);
556                 }
557 #if CONFIG_EXT_CONF_SUPPORT
558                 return;
559         }
560         // : if hc_c_index > 3, We should use io_min, io_max to clear extend space
561         u32 cfg_map_dest;
562         u32 j;
563
564
565         // all nodes
566         cfg_map_dest = 0;
567         for(j = 0; j< nodes; j++) {
568                 set_addr_map_reg_4_6_in_one_node(j,cfg_map_dest, io_min, io_max, 4);
569         }
570 #endif
571 }
572 #endif
573
574
575 static void re_set_all_config_map_reg(u32 nodes, u32 segbit,
576                                         sys_info_conf_t *sysinfo)
577 {
578         u32 ht_c_index;
579         device_t dev;
580
581         set_config_map_reg(0, sysinfo->sblk, 0, 0, sysinfo->ht_c_conf_bus[0]>>20, segbit, nodes);
582
583         /* clean others */
584         for(ht_c_index=1;ht_c_index<4; ht_c_index++) {
585                 u32 i;
586                 for(i=0; i<nodes; i++) {
587                 #if defined(__PRE_RAM__)
588                         dev = NODE_PCI(i, 1);
589                 #else
590                         dev = __f1_dev[i];
591                 #endif
592                         pci_write_config32(dev, 0xe0 + ht_c_index * 4, 0);
593                 }
594         }
595 #if CONFIG_EXT_CONF_SUPPORT
596         u32 j;
597         // clear the extend space
598         for(j = 0; j< nodes; j++) {
599                 set_addr_map_reg_4_6_in_one_node(j,0, 0, 0xff, 6);
600         }
601 #endif
602
603         for(ht_c_index = 1; ht_c_index<sysinfo->ht_c_num; ht_c_index++) {
604                 u32 nodeid, linkn;
605                 u32 busn_max;
606                 u32 busn_min;
607                 nodeid = (sysinfo->ht_c_conf_bus[ht_c_index] >> 2) & 0x3f;
608                 linkn = (sysinfo->ht_c_conf_bus[ht_c_index]>>8) & 0x7;
609                 busn_max = sysinfo->ht_c_conf_bus[ht_c_index]>>20;
610                 busn_min = (sysinfo->ht_c_conf_bus[ht_c_index]>>12) & 0xff;
611                 busn_min |= busn_max & 0xf00;
612                 set_config_map_reg(nodeid, linkn, ht_c_index, busn_min, busn_max, segbit, nodes);
613         }
614
615 }
616
617
618 static u32 get_ht_c_index(u32 nodeid, u32 linkn, sys_info_conf_t *sysinfo)
619 {
620         u32 tempreg;
621         u32 ht_c_index = 0;
622
623 #if 0
624         tempreg = 3 | ((nodeid & 0xf) <<4) | ((nodeid & 0x30)<<(12-4)) | (linkn<<8);
625
626         for(ht_c_index=0;ht_c_index<4; ht_c_index++) {
627                 reg = pci_read_config32(PCI_DEV(CONFIG_CBB, CONFIG_CDB, 1), 0xe0 + ht_c_index * 4);
628                 if(((reg & 0xffff) == 0x0000)) {  /*found free*/
629                         break;
630                 }
631         }
632 #endif
633         tempreg = 3 | ((nodeid & 0x3f)<<2) | (linkn<<8);
634         for(ht_c_index=0; ht_c_index<32; ht_c_index++) {
635                 if(((sysinfo->ht_c_conf_bus[ht_c_index] & 0xfff) == tempreg)){
636                         return ht_c_index;
637                 }
638         }
639
640         for(ht_c_index=0; ht_c_index<32; ht_c_index++) {
641                 if((sysinfo->ht_c_conf_bus[ht_c_index] == 0)){
642                          return ht_c_index;
643                 }
644         }
645
646         return  -1;
647
648 }
649
650 static void store_ht_c_conf_bus(u32 nodeid, u32 linkn, u32 ht_c_index,
651                                 u32 busn_min, u32 busn_max,
652                                 sys_info_conf_t *sysinfo)
653 {
654         u32 val;
655         val = 3 | ((nodeid & 0x3f)<<2) | (linkn<<8);
656         sysinfo->ht_c_conf_bus[ht_c_index] = val | ((busn_min & 0xff) <<12) | (busn_max<<20);  // same node need segn are same
657
658 }
659
660
661 static  void set_BusSegmentEn(u32 node, u32 segbit)
662 {
663 #if CONFIG_PCI_BUS_SEGN_BITS
664         u32 dword;
665         device_t dev;
666
667 #if defined(__PRE_RAM__)
668         dev = NODE_PCI(node, 0);
669 #else
670         dev = __f0_dev[node];
671 #endif
672
673         dword = pci_read_config32(dev, 0x68);
674         dword &= ~(7<<28);
675         dword |= (segbit<<28); /* bus segment enable */
676         pci_write_config32(dev, 0x68, dword);
677 #endif
678 }
679
680 #if !defined(__PRE_RAM__)
681 static u32 get_io_addr_index(u32 nodeid, u32 linkn)
682 {
683         u32 index;
684
685         for(index=0; index<256; index++) {
686                 if((sysconf.conf_io_addrx[index+4] == 0)){
687                         sysconf.conf_io_addr[index+4] =  (nodeid & 0x3f)  ;
688                         sysconf.conf_io_addrx[index+4] = 1 | ((linkn & 0x7)<<4);
689                         return index;
690                  }
691          }
692
693          return  0;
694
695 }
696
697 static u32 get_mmio_addr_index(u32 nodeid, u32 linkn)
698 {
699         u32 index;
700
701
702         for(index=0; index<64; index++) {
703                 if((sysconf.conf_mmio_addrx[index+8] == 0)){
704                         sysconf.conf_mmio_addr[index+8] = (nodeid & 0x3f) ;
705                         sysconf.conf_mmio_addrx[index+8] = 1 | ((linkn & 0x7)<<4);
706                         return index;
707                 }
708         }
709
710         return   0;
711
712 }
713
714 static void store_conf_io_addr(u32 nodeid, u32 linkn, u32 reg, u32 index,
715                                 u32 io_min, u32 io_max)
716 {
717         u32 val;
718 #if CONFIG_EXT_CONF_SUPPORT
719         if(reg!=0x110) {
720 #endif
721                 /* io range allocation */
722                 index = (reg-0xc0)>>3;
723 #if CONFIG_EXT_CONF_SUPPORT
724         } else {
725                 index+=4;
726         }
727 #endif
728
729         val = (nodeid & 0x3f); // 6 bits used
730         sysconf.conf_io_addr[index] = val | ((io_max<<8) & 0xfffff000); //limit : with nodeid
731         val = 3 | ((linkn & 0x7)<<4) ; // 8 bits used
732         sysconf.conf_io_addrx[index] = val | ((io_min<<8) & 0xfffff000); // base : with enable bit
733
734         if( sysconf.io_addr_num<(index+1))
735                 sysconf.io_addr_num = index+1;
736 }
737
738
739 static void store_conf_mmio_addr(u32 nodeid, u32 linkn, u32 reg, u32 index,
740                                         u32 mmio_min, u32 mmio_max)
741 {
742         u32 val;
743 #if CONFIG_EXT_CONF_SUPPORT
744         if(reg!=0x110) {
745 #endif
746                 /* io range allocation */
747                 index = (reg-0x80)>>3;
748 #if CONFIG_EXT_CONF_SUPPORT
749         } else {
750                 index+=8;
751         }
752 #endif
753
754         val = (nodeid & 0x3f) ; // 6 bits used
755         sysconf.conf_mmio_addr[index] = val | (mmio_max & 0xffffff00); //limit : with nodeid and linkn
756         val = 3 | ((linkn & 0x7)<<4) ; // 8 bits used
757         sysconf.conf_mmio_addrx[index] = val | (mmio_min & 0xffffff00); // base : with enable bit
758
759         if( sysconf.mmio_addr_num<(index+1))
760                 sysconf.mmio_addr_num = index+1;
761 }
762
763
764 static void set_io_addr_reg(device_t dev, u32 nodeid, u32 linkn, u32 reg,
765                                 u32 io_min, u32 io_max)
766 {
767
768         u32 i;
769         u32 tempreg;
770 #if CONFIG_EXT_CONF_SUPPORT
771         if(reg!=0x110) {
772 #endif
773                 /* io range allocation */
774                 tempreg = (nodeid&0xf) | ((nodeid & 0x30)<<(8-4)) | (linkn<<4) |  ((io_max&0xf0)<<(12-4)); //limit
775                 for(i=0; i<sysconf.nodes; i++)
776                         pci_write_config32(__f1_dev[i], reg+4, tempreg);
777
778                 tempreg = 3 /*| ( 3<<4)*/ | ((io_min&0xf0)<<(12-4));          //base :ISA and VGA ?
779 #if 0
780                 // FIXME: can we use VGA reg instead?
781                 if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
782                         printk(BIOS_SPEW, "%s, enabling legacy VGA IO forwarding for %s link %s\n",
783                                 __func__, dev_path(dev), link);
784                         tempreg |= PCI_IO_BASE_VGA_EN;
785                 }
786                 if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_NO_ISA) {
787                         tempreg |= PCI_IO_BASE_NO_ISA;
788                 }
789 #endif
790                 for(i=0; i<sysconf.nodes; i++)
791                         pci_write_config32(__f1_dev[i], reg, tempreg);
792 #if CONFIG_EXT_CONF_SUPPORT
793                 return;
794         }
795
796         u32 cfg_map_dest;
797         u32 j;
798         // if ht_c_index > 3, We should use extend space
799         if(io_min>io_max) return;
800         // for nodeid at first
801         cfg_map_dest = (1<<7) | (1<<6) | (linkn<<0);
802
803         set_addr_map_reg_4_6_in_one_node(nodeid, cfg_map_dest, io_min, io_max, 4);
804
805         // all other nodes
806         cfg_map_dest = (1<<7) | (0<<6) | (nodeid<<0);
807         for(j = 0; j< sysconf.nodes; j++) {
808                 if(j== nodeid) continue;
809                 set_addr_map_reg_4_6_in_one_node(j,cfg_map_dest, io_min, io_max, 4);
810         }
811 #endif
812
813 }
814 static void set_mmio_addr_reg(u32 nodeid, u32 linkn, u32 reg, u32 index, u32 mmio_min, u32 mmio_max, u32 nodes)
815 {
816
817         u32 i;
818         u32 tempreg;
819 #if CONFIG_EXT_CONF_SUPPORT
820         if(reg!=0x110) {
821 #endif
822                 /* io range allocation */
823                 tempreg = (nodeid&0xf) | (linkn<<4) |    (mmio_max&0xffffff00); //limit
824                 for(i=0; i<nodes; i++)
825                         pci_write_config32(__f1_dev[i], reg+4, tempreg);
826                 tempreg = 3 | (nodeid & 0x30) | (mmio_min&0xffffff00);
827                 for(i=0; i<sysconf.nodes; i++)
828                         pci_write_config32(__f1_dev[i], reg, tempreg);
829 #if CONFIG_EXT_CONF_SUPPORT
830                 return;
831         }
832
833         device_t dev;
834         u32 j;
835         // if ht_c_index > 3, We should use extend space
836         // for nodeid at first
837         u32 enable;
838
839         if(mmio_min>mmio_max) {
840                 return;
841         }
842
843         enable = 1;
844
845         dev = __f1_dev[nodeid];
846         tempreg = ((mmio_min>>3) & 0x1fffff00)| (1<<6) | (linkn<<0);
847         pci_write_config32(dev, 0x110, index | (2<<28));
848         pci_write_config32(dev, 0x114, tempreg);
849
850         tempreg = ((mmio_max>>3) & 0x1fffff00) | enable;
851         pci_write_config32(dev, 0x110, index | (3<<28));
852         pci_write_config32(dev, 0x114, tempreg);
853
854
855         // all other nodes
856         tempreg = ((mmio_min>>3) & 0x1fffff00) | (0<<6) | (nodeid<<0);
857         for(j = 0; j< sysconf.nodes; j++) {
858                 if(j== nodeid) continue;
859                 dev = __f1_dev[j];
860                 pci_write_config32(dev, 0x110, index | (2<<28));
861                 pci_write_config32(dev, 0x114, tempreg);
862         }
863
864         tempreg = ((mmio_max>>3) & 0x1fffff00) | enable;
865         for(j = 0; j< sysconf.nodes; j++) {
866                 if(j==nodeid) continue;
867                 dev = __f1_dev[j];
868                 pci_write_config32(dev, 0x110, index | (3<<28));
869                 pci_write_config32(dev, 0x114, tempreg);
870          }
871 #endif
872 }
873
874 #endif