2 * This file is part of the coreboot project.
4 * Copyright (C) 2008 Advanced Micro Devices, Inc.
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.
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.
16 #include <console/console.h>
17 #include <device/device.h>
18 #include <device/pci.h>
19 #include <device/pci_ids.h>
20 #include <device/pci_ops.h>
22 #include <arch/acpi.h>
25 static void ht_dev_set_resources(device_t dev
)
27 #if CONFIG_EXT_CONF_SUPPORT
30 resource_t rbase
, rend
;
32 struct resource
*resource
;
34 printk(BIOS_DEBUG
,"%s %s\n", dev_path(dev
), __func__
);
36 resource
= probe_resource(dev
, 0x1C);
38 set_nbmisc_enable_bits(dev
, 0x0, 1 << 3, 0 << 3); // make bar3 visible
39 set_nbcfg_enable_bits(dev
, 0x7C, 1 << 30, 1 << 30); /* Enables writes to the BAR3 register. */
40 set_nbcfg_enable_bits(dev
, 0x84, 7 << 16, 0 << 16); // program bus range: 255 busses
41 pci_write_config32(dev
, 0x1C, resource
->base
);
42 /* Enable MMCONFIG decoding. */
43 set_htiu_enable_bits(dev
, 0x32, 1 << 28, 1 << 28); /* PCIEMiscInit */
44 set_nbcfg_enable_bits(dev
, 0x7C, 1 << 30, 0 << 30); /* Disable writes to the BAR3 register. */
45 set_nbmisc_enable_bits(dev
, 0x0, 1 << 3, 1 << 3); // hide bar 3
47 // setup resource nonposted in k8 mmio
48 /* Get the base address */
49 rbase
= resource
->base
;
50 /* Get the limit (rounded up) */
51 rend
= resource_end(resource
);
52 printk(BIOS_DEBUG
,"%s: %s[0x1C] base = %0llx limit = %0llx\n", __func__
, dev_path(dev
), rbase
, rend
);
53 k8_f1
= dev_find_slot(0,PCI_DEVFN(0x18,1));
54 // find a not assigned resource
55 for( reg
= 0xb8; reg
>= 0x80; reg
-= 8 ) {
56 base
= pci_read_config32(k8_f1
,reg
);
57 limit
= pci_read_config32(k8_f1
,reg
+4);
58 if( !(base
& 3) ) break; // found a not assigned resource
62 device_t k8_f0
= dev_find_slot(0, PCI_DEVFN(0x18, 0));
63 /* Remember this resource has been stored. */
64 resource
->flags
|= IORESOURCE_STORED
;
65 report_resource_stored(dev
, resource
, " <mmconfig>");
66 /* Get SBLink value (HyperTransport I/O Hub Link ID). */
67 sblk
= (pci_read_config32(k8_f0
, 0x64) >> 8) & 0x3;
69 base
|= ((rbase
>> 8) & 0xffffff00);
72 limit
|= ((rend
>> 8) & 0xffffff00);
75 printk(BIOS_INFO
, "%s <- index %x base %04x limit %04x\n", dev_path(k8_f1
), reg
, base
, limit
);
76 pci_write_config32(k8_f1
, reg
+4, limit
);
77 pci_write_config32(k8_f1
, reg
, base
);
81 pci_dev_set_resources(dev
);
84 unsigned long acpi_fill_mcfg(unsigned long current
)
86 #if CONFIG_EXT_CONF_SUPPORT
88 resource_t mmconf_base
= EXT_CONF_BASE_ADDRESS
; // default
90 device_t dev
= dev_find_slot(0,PCI_DEVFN(0,0));
91 // we report mmconf base
92 res
= probe_resource(dev
, 0x1C);
94 mmconf_base
= res
->base
;
96 current
+= acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t
*)current
, mmconf_base
, 0x0, 0x0, 0x1f); // Fix me: should i reserve 255 busses ?
101 static void ht_dev_read_resources(device_t dev
)
103 #if CONFIG_EXT_CONF_SUPPORT
104 struct resource
*res
;
106 printk(BIOS_DEBUG
,"%s %s\n", dev_path(dev
), __func__
);
107 set_nbmisc_enable_bits(dev
, 0x0, 1 << 3, 1 << 3); // hide bar 3
110 pci_dev_read_resources(dev
);
112 #if CONFIG_EXT_CONF_SUPPORT
113 /* Add an MMCONFIG resource. */
114 res
= new_resource(dev
, 0x1C);
115 res
->base
= EXT_CONF_BASE_ADDRESS
;
116 res
->size
= 256 * 1024 * 1024; // 256 busses, 1MB memory space each
117 res
->align
= log2(res
->size
);
118 res
->gran
= log2(res
->size
);
119 res
->limit
= 0xffffffffffffffffULL
; /* 64bit */
120 res
->flags
= IORESOURCE_FIXED
| IORESOURCE_MEM
| IORESOURCE_PCI64
|
121 IORESOURCE_ASSIGNED
| IORESOURCE_RESERVE
;
123 compact_resources(dev
);
127 /* for UMA internal graphics */
128 void avoid_lpc_dma_deadlock(device_t nb_dev
, device_t sb_dev
)
133 k8_f0
= dev_find_slot(0, PCI_DEVFN(0x18, 0));
134 set_nbcfg_enable_bits(k8_f0
, 0x68, 3 << 21, 1 << 21);
136 reg
= nbpcie_p_read_index(sb_dev
, 0x10);
137 reg
|= 0x100; /* bit9=1 */
138 nbpcie_p_write_index(sb_dev
, 0x10, reg
);
140 reg
= nbpcie_p_read_index(nb_dev
, 0x10);
141 reg
|= 0x100; /* bit9=1 */
142 nbpcie_p_write_index(nb_dev
, 0x10, reg
);
144 /* Enable NP protocol over PCIE for memory-mapped writes targeting LPC
145 * Set this bit to avoid a deadlock condition. */
146 reg
= htiu_read_index(nb_dev
, 0x6);
147 reg
|= 0x1000000; /* bit26 */
148 htiu_write_index(nb_dev
, 0x6, reg
);
151 static void pcie_init(struct device
*dev
)
153 /* Enable pci error detecting */
156 printk(BIOS_INFO
, "pcie_init in rs690_ht.c\n");
158 /* System error enable */
159 dword
= pci_read_config32(dev
, 0x04);
160 dword
|= (1 << 8); /* System error enable */
161 dword
|= (1 << 30); /* Clear possible errors */
162 pci_write_config32(dev
, 0x04, dword
);
166 * 18 is enable nb to accept A4 interrupt request from SB.
168 dword
= pci_read_config32(dev
, 0x4C);
169 dword
|= 1 << 1 | 1 << 18; /* Clear possible errors */
170 pci_write_config32(dev
, 0x4C, dword
);
173 static void ht_dev_set_subsystem(struct device
*dev
, unsigned vendor
, unsigned device
)
175 pci_write_config32(dev
, 0x50, ((device
& 0xffff) << 16) | (vendor
& 0xffff));
178 static struct pci_operations lops_pci
= {
179 .set_subsystem
= ht_dev_set_subsystem
,
182 static struct device_operations ht_ops
= {
183 .read_resources
= ht_dev_read_resources
,
184 .set_resources
= ht_dev_set_resources
,
185 .enable_resources
= pci_dev_enable_resources
,
188 .ops_pci
= &lops_pci
,
191 static const struct pci_driver ht_driver __pci_driver
= {
193 .vendor
= PCI_VENDOR_ID_ATI
,
194 .device
= PCI_DEVICE_ID_ATI_RS690_HT
,