2 * This file is part of the coreboot project.
4 * Copyright (C) 2005 Linux Networx
5 * (Written by Eric Biederman <ebiederman@lnxi.com> for Linux Networx)
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
17 #include <console/console.h>
18 #include <device/device.h>
19 #include <device/pci.h>
20 #include <device/pci_ids.h>
21 #include <device/pcix.h>
23 static void pcix_tune_dev(device_t dev
)
27 unsigned int cap
, max_read
, max_tran
;
29 if (dev
->hdr_type
!= PCI_HEADER_TYPE_NORMAL
)
32 cap
= pci_find_capability(dev
, PCI_CAP_ID_PCIX
);
36 printk(BIOS_DEBUG
, "%s PCI-X tuning\n", dev_path(dev
));
38 status
= pci_read_config32(dev
, cap
+ PCI_X_STATUS
);
39 orig_cmd
= cmd
= pci_read_config16(dev
, cap
+ PCI_X_CMD
);
41 max_read
= (status
& PCI_X_STATUS_MAX_READ
) >> 21;
42 max_tran
= (status
& PCI_X_STATUS_MAX_SPLIT
) >> 23;
43 if (max_read
!= ((cmd
& PCI_X_CMD_MAX_READ
) >> 2)) {
44 cmd
&= ~PCI_X_CMD_MAX_READ
;
47 if (max_tran
!= ((cmd
& PCI_X_CMD_MAX_SPLIT
) >> 4)) {
48 cmd
&= ~PCI_X_CMD_MAX_SPLIT
;
52 /* Don't attempt to handle PCI-X errors. */
53 cmd
&= ~PCI_X_CMD_DPERR_E
;
55 /* Enable relaxed ordering. */
59 pci_write_config16(dev
, cap
+ PCI_X_CMD
, cmd
);
62 static void pcix_tune_bus(struct bus
*bus
)
66 for (child
= bus
->children
; child
; child
= child
->sibling
)
70 const char *pcix_speed(u16 sstatus
)
72 static const char conventional
[] = "Conventional PCI";
73 static const char pcix_66mhz
[] = "66MHz PCI-X";
74 static const char pcix_100mhz
[] = "100MHz PCI-X";
75 static const char pcix_133mhz
[] = "133MHz PCI-X";
76 static const char pcix_266mhz
[] = "266MHz PCI-X";
77 static const char pcix_533mhz
[] = "533MHZ PCI-X";
78 static const char unknown
[] = "Unknown";
83 switch (PCI_X_SSTATUS_MFREQ(sstatus
)) {
84 case PCI_X_SSTATUS_CONVENTIONAL_PCI
:
85 result
= conventional
;
87 case PCI_X_SSTATUS_MODE1_66MHZ
:
90 case PCI_X_SSTATUS_MODE1_100MHZ
:
93 case PCI_X_SSTATUS_MODE1_133MHZ
:
96 case PCI_X_SSTATUS_MODE2_266MHZ_REF_66MHZ
:
97 case PCI_X_SSTATUS_MODE2_266MHZ_REF_100MHZ
:
98 case PCI_X_SSTATUS_MODE2_266MHZ_REF_133MHZ
:
101 case PCI_X_SSTATUS_MODE2_533MHZ_REF_66MHZ
:
102 case PCI_X_SSTATUS_MODE2_533MHZ_REF_100MHZ
:
103 case PCI_X_SSTATUS_MODE2_533MHZ_REF_133MHZ
:
104 result
= pcix_533mhz
;
111 void pcix_scan_bridge(device_t dev
)
116 do_pci_scan_bridge(dev
, pci_scan_bus
);
118 /* Find the PCI-X capability. */
119 pos
= pci_find_capability(dev
, PCI_CAP_ID_PCIX
);
120 sstatus
= pci_read_config16(dev
, pos
+ PCI_X_SEC_STATUS
);
122 if (PCI_X_SSTATUS_MFREQ(sstatus
) != PCI_X_SSTATUS_CONVENTIONAL_PCI
)
123 pcix_tune_bus(dev
->link_list
);
125 /* Print the PCI-X bus speed. */
126 printk(BIOS_DEBUG
, "PCI: %02x: %s\n", dev
->link_list
->secondary
,
127 pcix_speed(sstatus
));
130 /** Default device operations for PCI-X bridges */
131 static struct pci_operations pcix_bus_ops_pci
= {
135 struct device_operations default_pcix_ops_bus
= {
136 .read_resources
= pci_bus_read_resources
,
137 .set_resources
= pci_dev_set_resources
,
138 .enable_resources
= pci_bus_enable_resources
,
140 .scan_bus
= pcix_scan_bridge
,
142 .reset_bus
= pci_bus_reset
,
143 .ops_pci
= &pcix_bus_ops_pci
,