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.
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
20 #include <console/console.h>
21 #include <device/device.h>
22 #include <device/pci.h>
23 #include <device/pci_ids.h>
24 #include <device/pci_ops.h>
28 /*------------------------------------------------
30 ------------------------------------------------*/
31 PCIE_CFG AtiPcieCfg = {
32 PCIE_ENABLE_STATIC_DEV_REMAP, /* Config */
33 0, /* ResetReleaseDelay */
38 0, /* PortDetect, filled by GppSbInit */
51 static void PciePowerOffGppPorts(device_t nb_dev, device_t dev, u32 port);
52 static void ValidatePortEn(device_t nb_dev);
54 static void ValidatePortEn(device_t nb_dev)
59 /*****************************************************************
60 * Compliant with CIM_33's PCIEPowerOffGppPorts
61 * Power off unused GPP lines
62 *****************************************************************/
63 static void PciePowerOffGppPorts(device_t nb_dev, device_t dev, u32 port)
67 struct southbridge_amd_rs690_config *cfg =
68 (struct southbridge_amd_rs690_config *)nb_dev->chip_info;
69 u8 state = cfg->port_enable;
71 if (!(AtiPcieCfg.Config & PCIE_DISABLE_HIDE_UNUSED_PORTS))
72 state &= AtiPcieCfg.PortDetect;
74 state &= (1 << 4) + (1 << 5) + (1 << 6) + (1 << 7);
75 state_save = state << 17;
76 state &= !(AtiPcieCfg.PortHp);
77 reg = nbmisc_read_index(nb_dev, 0x0c);
79 nbmisc_write_index(nb_dev, 0x0c, reg);
81 reg = nbmisc_read_index(nb_dev, 0x08);
83 nbmisc_write_index(nb_dev, 0x08, reg);
85 if ((AtiPcieCfg.Config & PCIE_OFF_UNUSED_GPP_LANES)
87 Config & (PCIE_DISABLE_HIDE_UNUSED_PORTS +
88 PCIE_GFX_COMPLIANCE))) {
90 /* step 3 Power Down Control for Southbridge */
91 reg = nbpcie_p_read_index(dev, 0xa2);
93 switch ((reg >> 4) & 0x7) { /* get bit 4-6, LC_LINK_WIDTH_RD */
95 nbpcie_ind_write_index(nb_dev, 0x65, 0x0e0e);
98 nbpcie_ind_write_index(nb_dev, 0x65, 0x0c0c);
105 static void pcie_init(struct device *dev)
107 /* Enable pci error detecting */
110 printk_debug("pcie_init in rs690_pcie.c\n");
112 /* System error enable */
113 dword = pci_read_config32(dev, 0x04);
114 dword |= (1 << 8); /* System error enable */
115 dword |= (1 << 30); /* Clear possible errors */
116 pci_write_config32(dev, 0x04, dword);
119 static struct pci_operations lops_pci = {
123 static struct device_operations pcie_ops = {
124 .read_resources = pci_bus_read_resources,
125 .set_resources = pci_dev_set_resources,
126 .enable_resources = pci_bus_enable_resources,
128 .scan_bus = pci_scan_bridge,
129 /*.enable = rs690_enable, */
130 .ops_pci = &lops_pci,
133 static struct pci_driver pcie_driver __pci_driver = {
135 .vendor = PCI_VENDOR_ID_ATI,
136 .device = PCI_DEVICE_ID_ATI_RS690_PCIE,
139 static struct pci_driver pcie_driver_dev7 __pci_driver = {
141 .vendor = PCI_VENDOR_ID_ATI,
142 .device = PCI_DEVICE_ID_ATI_RS690_PCIE_DEV7,
144 static struct pci_driver pcie_driver_dev8 __pci_driver = {
146 .vendor = PCI_VENDOR_ID_ATI,
147 .device = PCI_DEVICE_ID_ATI_RS690_PCIE_DEV8,
150 /**********************************************************************
151 **********************************************************************/
152 static void switching_gpp_configurations(device_t nb_dev, device_t sb_dev)
155 struct southbridge_amd_rs690_config *cfg =
156 (struct southbridge_amd_rs690_config *)nb_dev->chip_info;
158 /* enables GPP reconfiguration */
159 reg = nbmisc_read_index(nb_dev, PCIE_NBCFG_REG7);
161 (RECONFIG_GPPSB_EN + RECONFIG_GPPSB_LINK_CONFIG +
162 RECONFIG_GPPSB_ATOMIC_RESET);
163 nbmisc_write_index(nb_dev, PCIE_NBCFG_REG7, reg);
165 /* sets desired GPPSB configurations, bit4-7 */
166 reg = nbmisc_read_index(nb_dev, 0x67);
167 reg &= 0xff0f; /* clean */
168 reg |= cfg->gpp_configuration;
169 nbmisc_write_index(nb_dev, 0x67, reg);
171 /* read bit14 and write back its inverst value */
172 reg = nbmisc_read_index(nb_dev, PCIE_NBCFG_REG7);
173 reg ^= RECONFIG_GPPSB_GPPSB;
174 nbmisc_write_index(nb_dev, PCIE_NBCFG_REG7, reg);
179 /* waits until SB has trained to L0, poll for bit0-5 = 0x10 */
181 reg = nbpcie_p_read_index(sb_dev, PCIE_LC_STATE0);
182 reg &= 0x1f; /* remain LSB 5 bits */
183 } while (LC_STATE_RECONFIG_GPPSB != reg);
185 /* ensures that virtual channel negotiation is completed. poll for bit1 = 0 */
188 pci_ext_read_config32(nb_dev, sb_dev,
189 PCIE_VC0_RESOURCE_STATUS);
190 } while (reg & VC_NEGOTIATION_PENDING);
193 /*****************************************************************
194 * The rs690 uses NBCONFIG:0x1c (BAR3) to map the PCIE Extended Configuration
195 * Space to a 256MB range within the first 4GB of addressable memory.
196 *****************************************************************/
197 void enable_pcie_bar3(device_t nb_dev)
199 printk_debug("enable_pcie_bar3()\n");
200 set_nbcfg_enable_bits(nb_dev, 0x7C, 1 << 30, 1 << 30); /* Enables writes to the BAR3 register. */
201 set_nbcfg_enable_bits(nb_dev, 0x84, 7 << 16, 0 << 16);
203 pci_write_config32(nb_dev, 0x1C, EXT_CONF_BASE_ADDRESS); /* PCIEMiscInit */
204 pci_write_config32(nb_dev, 0x20, 0x00000000);
205 set_htiu_enable_bits(nb_dev, 0x32, 1 << 28, 1 << 28); /* PCIEMiscInit */
206 ProgK8TempMmioBase(1, EXT_CONF_BASE_ADDRESS, TEMP_MMIO_BASE_ADDRESS);
209 /*****************************************************************
210 * We should disable bar3 when we want to exit rs690_enable, because bar3 will be
211 * remapped in set_resource later.
212 *****************************************************************/
213 void disable_pcie_bar3(device_t nb_dev)
215 printk_debug("disable_pcie_bar3()\n");
216 set_nbcfg_enable_bits(nb_dev, 0x7C, 1 << 30, 0 << 30); /* Disable writes to the BAR3. */
217 pci_write_config32(nb_dev, 0x1C, 0); /* clear BAR3 address */
218 ProgK8TempMmioBase(0, EXT_CONF_BASE_ADDRESS, TEMP_MMIO_BASE_ADDRESS);
221 /*****************************************
222 * Compliant with CIM_33's PCIEGPPInit
228 * p2p bridge number, 4-8
229 *****************************************/
230 void rs690_gpp_sb_init(device_t nb_dev, device_t dev, u32 port)
235 struct southbridge_amd_rs690_config *cfg =
236 (struct southbridge_amd_rs690_config *)nb_dev->chip_info;
237 printk_debug("gpp_sb_init nb_dev=0x%x, dev=0x%x, port=0x%x\n", nb_dev, dev, port);
240 set_pcie_enable_bits(nb_dev, 0x20 | PCIE_CORE_INDEX_GPPSB, 1 << 8,
242 /* PCIE initialization 5.10.2: rpr 2.12*/
243 set_pcie_enable_bits(nb_dev, 0x02 | PCIE_CORE_INDEX_GPPSB, 1 << 0, 1 << 0); /* no description in datasheet. */
245 /* init GPPSB port */
246 /* Sets RCB timeout to be 100ms by setting bits[18:16] to 3 b101 and shortens the enumeration timer by setting bit[19] to 0*/
247 set_pcie_enable_bits(dev, 0x70, 7 << 16, 0xd << 16);
248 /* PCIE initialization 5.10.2: rpr 2.4 */
249 set_pcie_enable_bits(dev, 0x02, ~0xffffffff, 1 << 14);
250 /* Do not gate the electrical idle from the PHY and enables the escape from L1L23 */
251 set_pcie_enable_bits(dev, 0xA0, ~0xffffffbf, (3 << 30) | (3 << 12) | (3 << 4));
252 /* PCIE initialization 5.10.2: rpr 2.13 */
253 set_pcie_enable_bits(dev, 0x02, ~0xffffffff, 1 << 6);
255 /* SLOT_IMPLEMENTED in pcieConfig space */
256 reg8 = pci_read_config8(dev, 0x5b);
258 pci_write_config8(dev, 0x5b, reg8);
260 reg16 = pci_read_config16(dev, 0x5a);
262 pci_write_config16(dev, 0x5a, reg16);
263 nbmisc_write_index(nb_dev, 0x34, 0);
265 /* check compliance rpr step 2.1*/
266 if (AtiPcieCfg.Config & PCIE_GPP_COMPLIANCE) {
268 tmp = nbmisc_read_index(nb_dev, 0x67);
270 nbmisc_write_index(nb_dev, 0x67, tmp);
273 /* step 5: dynamic slave CPL buffer allocation */
274 set_pcie_enable_bits(dev, 0x20, 1 << 11, 1 << 11);
276 /* step 5a: Training for GPP devices */
283 /* Blocks DMA traffic during C3 state */
284 set_pcie_enable_bits(dev, 0x10, 1 << 0, 0 << 0);
285 /* Enabels TLP flushing */
286 set_pcie_enable_bits(dev, 0x20, 1 << 19, 0 << 19);
288 /* check port enable */
289 if (cfg->port_enable & (1 << port)) {
290 PcieReleasePortTraining(nb_dev, dev, port);
291 if (!(AtiPcieCfg.Config & PCIE_GPP_COMPLIANCE)) {
292 u8 res = PcieTrainPort(nb_dev, dev, port);
293 printk_debug("PcieTrainPort port=0x%x result=%d\n", port, res);
295 AtiPcieCfg.PortDetect |= 1 << port;
303 PciePowerOffGppPorts(nb_dev, dev, port);
305 /* step 5b: GFX devices in a GPP slot */
308 sb_dev = dev_find_slot(0, PCI_DEVFN(8, 0));
311 pci_ext_write_config32(nb_dev, sb_dev, 0x114, 0x3f << 1, 0 << 1);
312 /* Maps Traffic Class 1-7 to VC1 */
313 pci_ext_write_config32(nb_dev, sb_dev, 0x120, 0x7f << 1, 0x7f << 1);
314 /* Assigns VC ID to 1 */
315 pci_ext_write_config32(nb_dev, sb_dev, 0x120, 7 << 24, 1 << 24);
317 pci_ext_write_config32(nb_dev, sb_dev, 0x120, 1 << 31, 1 << 31);
320 reg16 = pci_ext_read_config32(nb_dev, sb_dev, 0x124);
322 } while (reg16); /*bit[1] = 0 means VC1 flow control initialization is successful */
326 /* step 6b: L0s for the southbridge link */
327 /* To enalbe L0s in the southbridage*/
329 /* step 6c: L0s for the GPP link(s) */
330 /* To eable L0s in the RS690 for the GPP port(s) */
331 set_pcie_enable_bits(nb_dev, 0xf9, 3 << 13, 2 << 13);
332 set_pcie_enable_bits(dev, 0xa0, 0xf << 8, 0x9 << 8);
333 reg16 = pci_read_config16(dev, 0x68);
335 pci_write_config16(dev, 0x68, reg16);
337 /* step 6d: ASPM L1 for the southbridge link */
338 /* To enalbe L1s in the southbridage*/
340 /* step 6e: ASPM L1 for GPP link(s) */;
341 set_pcie_enable_bits(nb_dev, 0xf9, 3 << 13, 2 << 13);
342 set_pcie_enable_bits(dev, 0xa0, 3 << 12, 3 << 12);
343 set_pcie_enable_bits(dev, 0xa0, 0xf << 4, 3 << 4);
344 reg16 = pci_read_config16(dev, 0x68);
347 pci_write_config16(dev, 0x68, reg16);
349 /* step 6f: Turning off PLL during L1/L23 */
350 set_pcie_enable_bits(nb_dev, 0x40, 1 << 3, 1 << 3);
351 set_pcie_enable_bits(nb_dev, 0x40, 1 << 9, 1 << 9);
353 /* step 6g: TXCLK clock gating */
354 set_nbmisc_enable_bits(nb_dev, 0x7, 3 << 4, 3 << 4);
355 set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 22, 1 << 22);
356 set_pcie_enable_bits(nb_dev, 0x11, 0xf << 4, 0xc << 4);
358 /* step 6h: LCLK clock gating, done in rs690_config_misc_clk() */
361 /*****************************************
362 * Compliant with CIM_33's PCIEConfigureGPPCore
363 *****************************************/
364 void config_gpp_core(device_t nb_dev, device_t sb_dev)
367 struct southbridge_amd_rs690_config *cfg =
368 (struct southbridge_amd_rs690_config *)nb_dev->chip_info;
370 reg = nbmisc_read_index(nb_dev, 0x20);
371 if (AtiPcieCfg.Config & PCIE_ENABLE_STATIC_DEV_REMAP)
372 reg &= 0xfffffffd; /* set bit1 = 0 */
374 reg |= 0x2; /* set bit1 = 1 */
375 nbmisc_write_index(nb_dev, 0x20, reg);
377 reg = nbmisc_read_index(nb_dev, 0x67); /* get STRAP_BIF_LINK_CONFIG_GPPSB at bit 4-7 */
378 if (cfg->gpp_configuration != ((reg >> 4) & 0xf))
379 switching_gpp_configurations(nb_dev, sb_dev);
380 ValidatePortEn(nb_dev);
383 /*****************************************
384 * Compliant with CIM_33's PCIEMiscClkProg
385 *****************************************/
386 void pcie_config_misc_clk(device_t nb_dev)
389 struct bus pbus; /* fake bus for dev0 fun1 */
391 reg = pci_read_config32(nb_dev, 0x4c);
393 pci_write_config32(nb_dev, 0x4c, reg);
395 if (AtiPcieCfg.Config & PCIE_GFX_CLK_GATING) {
396 /* TXCLK Clock Gating */
397 set_nbmisc_enable_bits(nb_dev, 0x07, 3 << 0, 3 << 0);
398 set_nbmisc_enable_bits(nb_dev, 0x07, 1 << 22, 1 << 22);
399 set_pcie_enable_bits(nb_dev, 0x11 | PCIE_CORE_INDEX_GFX, (3 << 6) | (~0xf), 3 << 6);
401 /* LCLK Clock Gating */
402 reg = pci_cf8_conf1.read32(&pbus, 0, 1, 0x94);
404 pci_cf8_conf1.write32(&pbus, 0, 1, 0x94, reg);
407 if (AtiPcieCfg.Config & PCIE_GPP_CLK_GATING) {
408 /* TXCLK Clock Gating */
409 set_nbmisc_enable_bits(nb_dev, 0x07, 3 << 4, 3 << 4);
410 set_nbmisc_enable_bits(nb_dev, 0x07, 1 << 22, 1 << 22);
411 set_pcie_enable_bits(nb_dev, 0x11 | PCIE_CORE_INDEX_GPPSB, (3 << 6) | (~0xf), 3 << 6);
413 /* LCLK Clock Gating */
414 reg = pci_cf8_conf1.read32(&pbus, 0, 1, 0x94);
416 pci_cf8_conf1.write32(&pbus, 0, 1, 0x94, reg);
419 reg = pci_read_config32(nb_dev, 0x4c);
421 pci_write_config32(nb_dev, 0x4c, reg);