You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
961 lines
31 KiB
961 lines
31 KiB
#include <unistd.h>
|
|
#include "rs780_chip.h"
|
|
|
|
extern struct southbridge_amd_rs780_config chip_info;
|
|
|
|
#if 0
|
|
/* step 12 ~ step 14 from rpr */
|
|
static void single_port_configuration(device_t nb_dev, device_t dev)
|
|
{
|
|
u8 result, width;
|
|
u32 reg32;
|
|
struct southbridge_amd_rs780_config *cfg = &chip_info;
|
|
|
|
printk_info("rs780_gfx_init single_port_configuration.\n");
|
|
|
|
/* step 12 training, releases hold training for GFX port 0 (device 2) */
|
|
PcieReleasePortTraining(nb_dev, dev, 2);
|
|
result = PcieTrainPort(nb_dev, dev, 2);
|
|
printk_info("rs780_gfx_init single_port_configuration step12.\n");
|
|
|
|
/* step 13 Power Down Control */
|
|
/* step 13.1 Enables powering down transmitter and receiver pads along with PLL macros. */
|
|
set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 1 << 0);
|
|
|
|
/* step 13.a Link Training was NOT successful */
|
|
if (!result) {
|
|
set_nbmisc_enable_bits(nb_dev, 0x8, 0, 0x3 << 4); /* prevent from training. */
|
|
set_nbmisc_enable_bits(nb_dev, 0xc, 0, 0x3 << 2); /* hide the GFX bridge. */
|
|
if (cfg->gfx_tmds)
|
|
nbpcie_ind_write_index(nb_dev, 0x65, 0xccf0f0);
|
|
else {
|
|
nbpcie_ind_write_index(nb_dev, 0x65, 0xffffffff);
|
|
set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 3, 1 << 3);
|
|
}
|
|
} else { /* step 13.b Link Training was successful */
|
|
set_pcie_enable_bits(dev, 0xA2, 0xFF, 0x1);
|
|
reg32 = nbpcie_p_read_index(dev, 0x29);
|
|
width = reg32 & 0xFF;
|
|
printk_debug("GFX Inactive Lanes = 0x%x.\n", width);
|
|
switch (width) {
|
|
case 1:
|
|
case 2:
|
|
nbpcie_ind_write_index(nb_dev, 0x65,
|
|
cfg->gfx_lane_reversal ? 0x7f7f : 0xccfefe);
|
|
break;
|
|
case 4:
|
|
nbpcie_ind_write_index(nb_dev, 0x65,
|
|
cfg->gfx_lane_reversal ? 0x3f3f : 0xccfcfc);
|
|
break;
|
|
case 8:
|
|
nbpcie_ind_write_index(nb_dev, 0x65,
|
|
cfg->gfx_lane_reversal ? 0x0f0f : 0xccf0f0);
|
|
break;
|
|
}
|
|
}
|
|
printk_info("rs780_gfx_init single_port_configuration step13.\n");
|
|
|
|
/* step 14 Reset Enumeration Timer, disables the shortening of the enumeration timer */
|
|
set_pcie_enable_bits(dev, 0x70, 1 << 19, 0 << 19);
|
|
printk_info("rs780_gfx_init single_port_configuration step14.\n");
|
|
}
|
|
|
|
/* step 15 ~ step 18 from rpr */
|
|
static void dual_port_configuration(device_t nb_dev, device_t dev)
|
|
{
|
|
u8 result, width;
|
|
u32 reg32, dev_ind;
|
|
struct southbridge_amd_rs780_config *cfg = &chip_info;
|
|
|
|
_pci_break_tag(dev, NULL, &dev_ind, NULL);
|
|
/* 5.4.1.2 Dual Port Configuration */
|
|
set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31);
|
|
set_nbmisc_enable_bits(nb_dev, 0x08, 0xF << 8, 0x5 << 8);
|
|
set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31);
|
|
|
|
/* Training for Device 2 */
|
|
/* Releases hold training for GFX port 0 (device 2) */
|
|
PcieReleasePortTraining(nb_dev, dev, dev_ind);
|
|
/* PCIE Link Training Sequence */
|
|
result = PcieTrainPort(nb_dev, dev, dev_ind);
|
|
|
|
/* step 16: Power Down Control for Device 2 */
|
|
/* step 16.a Link Training was NOT successful */
|
|
if (!result) {
|
|
/* Powers down all lanes for port A */
|
|
/* nbpcie_ind_write_index(nb_dev, 0x65, 0x0f0f); */
|
|
/* Note: I have to disable the slot where there isnt a device,
|
|
* otherwise the system will hang. I dont know why. Do you guys know? */
|
|
set_nbmisc_enable_bits(nb_dev, 0x0c, 1 << dev_ind, 1 << dev_ind);
|
|
} else { /* step 16.b Link Training was successful */
|
|
|
|
reg32 = nbpcie_p_read_index(dev, 0xa2);
|
|
width = (reg32 >> 4) & 0x7;
|
|
switch (width) {
|
|
case 1:
|
|
case 2:
|
|
nbpcie_ind_write_index(nb_dev, 0x65,
|
|
cfg->gfx_lane_reversal ? 0x0707 : 0x0e0e);
|
|
break;
|
|
case 4:
|
|
nbpcie_ind_write_index(nb_dev, 0x65,
|
|
cfg->gfx_lane_reversal ? 0x0303 : 0x0c0c);
|
|
break;
|
|
}
|
|
}
|
|
#if 0
|
|
/* step 17: Training for Device 3 */
|
|
set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 5, 0 << 5);
|
|
/* Releases hold training for GFX port 0 (device 3) */
|
|
PcieReleasePortTraining(nb_dev, dev, 3);
|
|
/* PCIE Link Training Sequence */
|
|
result = PcieTrainPort(nb_dev, dev, 3);
|
|
|
|
/*step 18: Power Down Control for Device 3 */
|
|
/* step 18.a Link Training was NOT successful */
|
|
if (!result) {
|
|
/* Powers down all lanes for port B and PLL1 */
|
|
nbpcie_ind_write_index(nb_dev, 0x65, 0xccf0f0);
|
|
} else { /* step 18.b Link Training was successful */
|
|
|
|
reg32 = nbpcie_p_read_index(dev, 0xa2);
|
|
width = (reg32 >> 4) & 0x7;
|
|
switch (width) {
|
|
case 1:
|
|
case 2:
|
|
nbpcie_ind_write_index(nb_dev, 0x65,
|
|
cfg->gfx_lane_reversal ? 0x7070 : 0xe0e0);
|
|
break;
|
|
case 4:
|
|
nbpcie_ind_write_index(nb_dev, 0x65,
|
|
cfg->gfx_lane_reversal ? 0x3030 : 0xc0c0);
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* For single port GFX configuration Only
|
|
* width:
|
|
* 000 = x16
|
|
* 001 = x1
|
|
* 010 = x2
|
|
* 011 = x4
|
|
* 100 = x8
|
|
* 101 = x12 (not supported)
|
|
* 110 = x16
|
|
*/
|
|
static void dynamic_link_width_control(device_t nb_dev, device_t dev, u8 width)
|
|
{
|
|
u32 reg32;
|
|
device_t sb_dev;
|
|
struct southbridge_amd_rs780_config *cfg = &chip_info;
|
|
|
|
/* step 5.9.1.1 */
|
|
reg32 = nbpcie_p_read_index(dev, 0xa2);
|
|
|
|
/* step 5.9.1.2 */
|
|
set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 1 << 0);
|
|
/* step 5.9.1.3 */
|
|
set_pcie_enable_bits(dev, 0xa2, 3 << 0, width << 0);
|
|
/* step 5.9.1.4 */
|
|
set_pcie_enable_bits(dev, 0xa2, 1 << 8, 1 << 8);
|
|
/* step 5.9.2.4 */
|
|
if (0 == cfg->gfx_reconfiguration)
|
|
set_pcie_enable_bits(dev, 0xa2, 1 << 11, 1 << 11);
|
|
|
|
/* step 5.9.1.5 */
|
|
do {
|
|
reg32 = nbpcie_p_read_index(dev, 0xa2);
|
|
}
|
|
while (reg32 & 0x100);
|
|
|
|
/* step 5.9.1.6 */
|
|
//sb_dev = dev_find_slot(0, PCI_DEVFN(8, 0));
|
|
sb_dev = _pci_make_tag(0, 8, 0);
|
|
do {
|
|
reg32 = pci_ext_read_config16(nb_dev, sb_dev,
|
|
PCIE_VC0_RESOURCE_STATUS);
|
|
} while (reg32 & VC_NEGOTIATION_PENDING);
|
|
|
|
/* step 5.9.1.7 */
|
|
reg32 = nbpcie_p_read_index(dev, 0xa2);
|
|
if (((reg32 & 0x70) >> 4) != 0x6) {
|
|
/* the unused lanes should be powered off. */
|
|
}
|
|
|
|
/* step 5.9.1.8 */
|
|
set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 0 << 0);
|
|
}
|
|
|
|
|
|
/*
|
|
* GFX Core initialization, dev2, dev3
|
|
*/
|
|
void rs780_gfx_init(device_t nb_dev, device_t dev, u32 port)
|
|
{
|
|
u16 reg16;
|
|
u32 reg32;
|
|
void set_pcie_reset();
|
|
void set_pcie_dereset();
|
|
struct southbridge_amd_rs780_config *cfg =
|
|
&chip_info;
|
|
|
|
printk_info("rs780_gfx_init, nb_dev=0x%x, dev=0x%x, port=0x%x.\n",
|
|
nb_dev, dev, port);
|
|
|
|
/* step 1, lane reversal (only need if CMOS option is enabled) */
|
|
if (cfg->gfx_lane_reversal) {
|
|
set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2);
|
|
if (cfg->gfx_dual_slot)
|
|
set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 3, 1 << 3);
|
|
}
|
|
printk_info("rs780_gfx_init step1.\n");
|
|
/* step 1.1, dual-slot gfx configuration (only need if CMOS option is enabled) */
|
|
/* AMD calls the configuration CrossFire */
|
|
if (cfg->gfx_dual_slot)
|
|
set_nbmisc_enable_bits(nb_dev, 0x0, 0xf << 8, 5 << 8);
|
|
printk_info("rs780_gfx_init step2.\n");
|
|
/* step 2, TMDS, (only need if CMOS option is enabled) */
|
|
if (cfg->gfx_tmds) {
|
|
}
|
|
|
|
#if 1 /* external clock mode */
|
|
/* table 5-22, 5.9.1. REFCLK */
|
|
/* 5.9.1.1. Disables the GFX REFCLK transmitter so that the GFX
|
|
* REFCLK PAD can be driven by an external source. */
|
|
/* 5.9.1.2. Enables GFX REFCLK receiver to receive the REFCLK from an external source. */
|
|
set_nbmisc_enable_bits(nb_dev, 0x38, 1 << 29 | 1 << 28, 0 << 29 | 1 << 28);
|
|
|
|
/* 5.9.1.3 Selects the GFX REFCLK to be the source for PLL A. */
|
|
/* 5.9.1.4 Selects the GFX REFCLK to be the source for PLL B. */
|
|
/* 5.9.1.5 Selects the GFX REFCLK to be the source for PLL C. */
|
|
set_nbmisc_enable_bits(nb_dev, 0x28, 3 << 6 | 3 << 8 | 3 << 10,
|
|
1 << 6 | 1 << 8 | 1 << 10);
|
|
reg32 = nbmisc_read_index(nb_dev, 0x28);
|
|
printk_info("misc 28 = %x\n", reg32);
|
|
|
|
/* 5.9.1.6.Selects the single ended GFX REFCLK to be the source for core logic. */
|
|
set_nbmisc_enable_bits(nb_dev, 0x6C, 1 << 31, 1 << 31);
|
|
#else /* internal clock mode */
|
|
/* table 5-23, 5.9.1. REFCLK */
|
|
/* 5.9.1.1. Enables the GFX REFCLK transmitter so that the GFX
|
|
* REFCLK PAD can be driven by the SB REFCLK. */
|
|
/* 5.9.1.2. Disables GFX REFCLK receiver from receiving the
|
|
* REFCLK from an external source.*/
|
|
set_nbmisc_enable_bits(nb_dev, 0x38, 1 << 29 | 1 << 28, 1 << 29 | 0 << 28);
|
|
|
|
/* 5.9.1.3 Selects the GFX REFCLK to be the source for PLL A. */
|
|
/* 5.9.1.4 Selects the GFX REFCLK to be the source for PLL B. */
|
|
/* 5.9.1.5 Selects the GFX REFCLK to be the source for PLL C. */
|
|
set_nbmisc_enable_bits(nb_dev, 0x28, 3 << 6 | 3 << 8 | 3 << 10,
|
|
0);
|
|
reg32 = nbmisc_read_index(nb_dev, 0x28);
|
|
printk_info("misc 28 = %x\n", reg32);
|
|
|
|
/* 5.9.1.6.Selects the single ended GFX REFCLK to be the source for core logic. */
|
|
set_nbmisc_enable_bits(nb_dev, 0x6C, 1 << 31, 0 << 31);
|
|
#endif
|
|
/* step 5.9.3, GFX overclocking, (only need if CMOS option is enabled) */
|
|
/* 5.9.3.1. Increases PLL BW for 6G operation.*/
|
|
/* set_nbmisc_enable_bits(nb_dev, 0x36, 0x3FF << 4, 0xB5 << 4); */
|
|
/* skip */
|
|
|
|
/* step 5.9.4, reset the GFX link */
|
|
/* step 5.9.4.1 asserts both calibration reset and global reset */
|
|
set_nbmisc_enable_bits(nb_dev, 0x8, 0x3 << 14, 0x3 << 14);
|
|
|
|
/* step 5.9.4.2 de-asserts calibration reset */
|
|
set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 14, 0 << 14);
|
|
|
|
/* step 5.9.4.3 wait for at least 200us */
|
|
delay(3);
|
|
|
|
/* step 5.9.4.4 de-asserts global reset */
|
|
set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 15, 0 << 15);
|
|
|
|
/* 5.9.5 Reset PCIE_GFX Slot */
|
|
/* It is done in mainboard.c */
|
|
set_pcie_reset();
|
|
delay(1);
|
|
set_pcie_dereset();
|
|
/* step 5.9.8 program PCIE memory mapped configuration space */
|
|
/* done by enable_pci_bar3() before */
|
|
|
|
/* step 7 compliance state, (only need if CMOS option is enabled) */
|
|
/* the compliance stete is just for test. refer to 4.2.5.2 of PCIe specification */
|
|
if (cfg->gfx_compliance) {
|
|
/* force compliance */
|
|
set_nbmisc_enable_bits(nb_dev, 0x32, 1 << 6, 1 << 6);
|
|
/* release hold training for device 2. GFX initialization is done. */
|
|
set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 4, 0 << 4);
|
|
dynamic_link_width_control(nb_dev, dev, cfg->gfx_link_width);
|
|
printk_info("rs780_gfx_init step7.\n");
|
|
return;
|
|
}
|
|
|
|
/* 5.9.12 Core Initialization. */
|
|
/* 5.9.12.1 sets RCB timeout to be 25ms */
|
|
/* 5.9.12.2. RCB Cpl timeout on link down. */
|
|
set_pcie_enable_bits(dev, 0x70, 7 << 16 | 1 << 19, 4 << 16 | 1 << 19);
|
|
printk_info("rs780_gfx_init step5.9.12.1.\n");
|
|
|
|
/* step 5.9.12.3 disables slave ordering logic */
|
|
set_pcie_enable_bits(nb_dev, 0x20, 1 << 8, 1 << 8);
|
|
printk_info("rs780_gfx_init step5.9.12.3.\n");
|
|
|
|
/* step 5.9.12.4 sets DMA payload size to 64 bytes */
|
|
set_pcie_enable_bits(nb_dev, 0x10, 7 << 10, 4 << 10);
|
|
/* 5.9.12.5. Blocks DMA traffic during C3 state. */
|
|
set_pcie_enable_bits(dev, 0x10, 1 << 0, 0 << 0);
|
|
|
|
/* 5.9.12.6. Disables RC ordering logic */
|
|
set_pcie_enable_bits(nb_dev, 0x20, 1 << 9, 1 << 9);
|
|
|
|
/* Enabels TLP flushing. */
|
|
/* Note: It is got from RS690. The system will hang without this action. */
|
|
set_pcie_enable_bits(dev, 0x20, 1 << 19, 0 << 19);
|
|
|
|
/* 5.9.12.7. Ignores DLLPs during L1 so that txclk can be turned off */
|
|
set_pcie_enable_bits(nb_dev, 0x2, 1 << 0, 1 << 0);
|
|
|
|
/* 5.9.12.8 Prevents LC to go from L0 to Rcv_L0s if L1 is armed. */
|
|
set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11);
|
|
|
|
/* 5.9.12.9 CMGOOD_OVERRIDE for end point initiated lane degradation. */
|
|
set_nbmisc_enable_bits(nb_dev, 0x6a, 1 << 17, 1 << 17);
|
|
printk_info("rs780_gfx_init step5.9.12.9.\n");
|
|
|
|
/* 5.9.12.10 Sets the timer in Config state from 20us to */
|
|
/* 5.9.12.11 De-asserts RX_EN in L0s. */
|
|
/* 5.9.12.12 Enables de-assertion of PG2RX_CR_EN to lock clock
|
|
* recovery parameter when lane is in electrical idle in L0s.*/
|
|
set_pcie_enable_bits(dev, 0xB1, 1 << 23 | 1 << 19 | 1 << 28, 1 << 23 | 1 << 19 | 1 << 28);
|
|
|
|
/* 5.9.12.13. Turns off offset calibration. */
|
|
/* 5.9.12.14. Enables Rx Clock gating in CDR */
|
|
set_nbmisc_enable_bits(nb_dev, 0x34, 1 << 10/* | 1 << 22 */, 1 << 10/* | 1 << 22 */);
|
|
|
|
/* 5.9.12.15. Sets number of TX Clocks to drain TX Pipe to 3. */
|
|
set_pcie_enable_bits(dev, 0xA0, 0xF << 4, 3 << 4);
|
|
|
|
/* 5.9.12.16. Lets PI use Electrical Idle from PHY when
|
|
* turning off PLL in L1 at Gen2 speed instead Inferred Electrical Idle. */
|
|
set_pcie_enable_bits(nb_dev, 0x40, 3 << 14, 2 << 14);
|
|
|
|
/* 5.9.12.17. Prevents the Electrical Idle from causing a transition from Rcv_L0 to Rcv_L0s. */
|
|
set_pcie_enable_bits(dev, 0xB1, 1 << 20, 1 << 20);
|
|
|
|
/* 5.9.12.18. Prevents the LTSSM from going to Rcv_L0s if it has already
|
|
* acknowledged a request to go to L1. */
|
|
set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11);
|
|
|
|
/* 5.9.12.19. LDSK only taking deskew on deskewing error detect */
|
|
set_pcie_enable_bits(nb_dev, 0x40, 1 << 28, 0 << 28);
|
|
|
|
/* 5.9.12.20. Bypasses lane de-skew logic if in x1 */
|
|
set_pcie_enable_bits(nb_dev, 0xC2, 1 << 14, 1 << 14);
|
|
|
|
/* 5.9.12.21. Sets Electrical Idle Threshold. */
|
|
set_nbmisc_enable_bits(nb_dev, 0x35, 3 << 21, 2 << 21);
|
|
|
|
/* 5.9.12.22. Advertises -6 dB de-emphasis value in TS1 Data Rate Identifier
|
|
* Only if CMOS Option in section. skip */
|
|
|
|
/* 5.9.12.23. Disables GEN2 capability of the device. */
|
|
set_pcie_enable_bits(dev, 0xA4, 1 << 0, 0 << 0);
|
|
|
|
/* 5.9.12.24.Disables advertising Upconfigure Support. */
|
|
set_pcie_enable_bits(dev, 0xA2, 1 << 13, 1 << 13);
|
|
|
|
/* 5.9.12.25. No comment in RPR. */
|
|
set_nbmisc_enable_bits(nb_dev, 0x39, 1 << 10, 0 << 10);
|
|
|
|
/* 5.9.12.26. This capacity is required since links wider than x1 and/or multiple link
|
|
* speed are supported */
|
|
set_pcie_enable_bits(nb_dev, 0xC1, 1 << 0, 1 << 0);
|
|
|
|
/* 5.9.12.27. Enables NVG86 ECO. A13 above only. */
|
|
/* TODO: Check if it is A13. */
|
|
if (0) /* A12 */
|
|
set_pcie_enable_bits(dev, 0x02, 1 << 11, 1 << 11);
|
|
|
|
/* 5.9.12.28 Hides and disables the completion timeout method. */
|
|
set_pcie_enable_bits(nb_dev, 0xC1, 1 << 2, 0 << 2);
|
|
|
|
/* 5.9.12.29. Use the bif_core de-emphasis strength by default. */
|
|
/* set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 28, 1 << 28); */
|
|
|
|
/* 5.9.12.30. Set TX arbitration algorithm to round robin */
|
|
set_pcie_enable_bits(nb_dev, 0x1C,
|
|
1 << 0 | 0x1F << 1 | 0x1F << 6,
|
|
1 << 0 | 0x04 << 1 | 0x04 << 6);
|
|
|
|
/* Single-port/Dual-port configureation. */
|
|
switch (cfg->gfx_dual_slot) {
|
|
case 0:
|
|
single_port_configuration(nb_dev, dev);
|
|
break;
|
|
case 1:
|
|
dual_port_configuration(nb_dev, dev);
|
|
break;
|
|
default:
|
|
printk_info("Incorrect configuration of external gfx slot.\n");
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
//BTDC
|
|
static void pcie_commoncoreinit(device_t nb_dev, device_t dev)
|
|
{
|
|
u32 reg;
|
|
u16 word;
|
|
u8 byte;
|
|
|
|
set_pcie_enable_bits(nb_dev,0x10, 0x7 << 10, 0x4 << 10);
|
|
set_pcie_enable_bits(nb_dev,0x20, 0x3 << 8, 0x3 << 8);
|
|
set_pcie_enable_bits(nb_dev,0x02, 0x0, 1 << 0 | 1 << 8);
|
|
set_pcie_enable_bits(nb_dev,0x40, 0x3 << 14, 0x2 << 14);
|
|
set_pcie_enable_bits(nb_dev,0x40, 0x1 << 28, 0x0 << 28);
|
|
set_pcie_enable_bits(nb_dev,0xc2, 1 << 14 | 1 << 25, 1 << 14 | 1 << 25);
|
|
set_pcie_enable_bits(nb_dev,0xc1, 1 << 0 | 1 << 2, 1 << 0);
|
|
set_pcie_enable_bits(nb_dev,0x1c, 0xffffffff, 4 << 6 | 4 << 1);
|
|
|
|
|
|
}
|
|
|
|
static void pcie_commonportinit(device_t nb_dev, device_t dev)
|
|
{
|
|
u32 reg;
|
|
u16 word;
|
|
u8 byte;
|
|
|
|
reg = pci_read_config32(dev,0x88);
|
|
reg &= 0xfffffff0;
|
|
reg |= 0x1;
|
|
pci_write_config32(dev, 0x88, reg);
|
|
|
|
set_pcie_enable_bits(dev, 0x02, 1 << 11, 1 << 11);
|
|
set_pcie_enable_bits(dev, 0xa4, 1 << 0 , 0 << 0);
|
|
set_pcie_enable_bits(dev, 0xa0, 0xf << 4 , 0x3 << 4);
|
|
set_pcie_enable_bits(dev, 0xa1, 1 << 11 | 1 << 24 | 1 << 26, 1 << 11);
|
|
set_pcie_enable_bits(dev, 0xb1, 0x0 , 1 << 28 | 1 << 23 | 1 << 19 | 1<< 20);
|
|
set_pcie_enable_bits(dev, 0xa2, 0x0 , 1 << 13);
|
|
set_pcie_enable_bits(dev, 0x70, 1 << 16 | 1 << 17 | 1 << 18 | 1 << 19, 1 << 18 | 1 << 19);
|
|
}
|
|
|
|
//this include PCIE_InitGen2(Port, 1) and PCIE_InitGen2(Port, 0)
|
|
|
|
static void pcie_initgen2(device_t nb_dev, device_t dev)
|
|
{
|
|
u32 reg;
|
|
u16 word;
|
|
u8 byte;
|
|
|
|
set_pcie_enable_bits(dev, 0xa4, 1 << 0, 0 << 0);
|
|
reg = pci_read_config32(dev,0x88);
|
|
reg &= 0xfffffff0;
|
|
reg |= 0x1;
|
|
pci_write_config32(dev, 0x88, reg);
|
|
set_nbmisc_enable_bits(nb_dev, 0x34, 1 << 5, 0 << 5);
|
|
|
|
|
|
set_pcie_enable_bits(dev, 0xa4, 1 << 0, 1 << 0);
|
|
reg = pci_read_config32(dev, 0x88);
|
|
reg &= 0xfffffff0;
|
|
reg |= 0x2;
|
|
pci_write_config32(dev, 0x88, reg);
|
|
set_nbmisc_enable_bits(nb_dev, 0x34, 1 << 5, 1 << 5);
|
|
|
|
|
|
set_pcie_enable_bits(dev, 0xa4, 0, 1 << 29);
|
|
set_pcie_enable_bits(dev, 0xc0, 1 << 15, 0 << 15);
|
|
set_pcie_enable_bits(dev, 0xa2, 1 << 13, 0 << 13);
|
|
|
|
//set interrupt pin info
|
|
pci_write_config8(dev, 0x3d, 0x1);
|
|
|
|
|
|
// while(1);
|
|
|
|
}
|
|
|
|
static void pcie_gen2workaround(device_t nb_dev, device_t dev)
|
|
{
|
|
u32 reg;
|
|
u16 word;
|
|
u8 byte;
|
|
void set_pcie_reset();
|
|
void set_pcie_dereset();
|
|
|
|
|
|
|
|
set_pcie_enable_bits(dev, 0xa4, 1 << 0, 0 << 0);
|
|
reg = pci_read_config32(dev,0x88);
|
|
reg &= 0xfffffff0;
|
|
reg |= 0x1;
|
|
pci_write_config32(dev, 0x88, reg);
|
|
set_nbmisc_enable_bits(nb_dev, 0x34, 1 << 5, 0 << 5);
|
|
|
|
set_pcie_enable_bits(dev, 0xa4, 1 << 29, 0 << 29);
|
|
set_pcie_enable_bits(dev, 0xc0, 1 << 15, 1 << 15);
|
|
set_pcie_enable_bits(dev, 0xa2, 1 << 13, 1 << 13);
|
|
|
|
reg = htiu_read_index(nb_dev, 0x15);
|
|
reg &= ~ (1 << 4);
|
|
htiu_write_index(nb_dev, 0x15, 0);
|
|
|
|
set_pcie_reset();
|
|
delay(1000);
|
|
set_pcie_dereset();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* step 12 ~ step 14 from rpr */
|
|
static void single_port_configuration(device_t nb_dev, device_t dev)
|
|
{
|
|
u8 result, width;
|
|
u32 reg32;
|
|
struct southbridge_amd_rs780_config *cfg =&chip_info;
|
|
|
|
printk_info("rs780_gfx_init single_port_configuration.\n");
|
|
|
|
/* step 12 training, releases hold training for GFX port 0 (device 2) */
|
|
PcieReleasePortTraining(nb_dev, dev, 2);
|
|
result = PcieTrainPort(nb_dev, dev, 2);
|
|
printk_info("rs780_gfx_init single_port_configuration step12.\n");
|
|
|
|
/* step 13 Power Down Control */
|
|
/* step 13.1 Enables powering down transmitter and receiver pads along with PLL macros. */
|
|
set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 1 << 0);
|
|
|
|
/* step 13.a Link Training was NOT successful */
|
|
if (!result) {
|
|
set_nbmisc_enable_bits(nb_dev, 0x8, 0x1 << 4, 0x1 << 4); /* prevent from training. */
|
|
set_nbmisc_enable_bits(nb_dev, 0xc, 0x1 << 2, 0x1 << 2); /* hide the GFX bridge. */
|
|
|
|
if (cfg->gfx_tmds)
|
|
nbpcie_ind_write_index(nb_dev, 0x65, 0xccf0f0);
|
|
else {
|
|
nbpcie_ind_write_index(nb_dev, 0x65, 0xffffffff);
|
|
set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 3, 1 << 3);
|
|
}
|
|
} else { /* step 13.b Link Training was successful */
|
|
|
|
set_pcie_enable_bits(dev, 0xA2, 0xFF, 0x1);
|
|
|
|
reg32 = nbpcie_p_read_index(dev, 0x29);
|
|
width = reg32 & 0xFF;
|
|
printk_debug("GFX Inactive Lanes = 0x%x.\n", width);
|
|
switch (width) {
|
|
case 1:
|
|
case 2:
|
|
nbpcie_ind_write_index(nb_dev, 0x65,
|
|
cfg->gfx_lane_reversal ? 0x7f7f : 0xccfefe);
|
|
break;
|
|
case 4:
|
|
nbpcie_ind_write_index(nb_dev, 0x65,
|
|
cfg->gfx_lane_reversal ? 0x3f3f : 0xccfcfc);
|
|
break;
|
|
case 8:
|
|
nbpcie_ind_write_index(nb_dev, 0x65,
|
|
cfg->gfx_lane_reversal ? 0x0f0f : 0xccf0f0);
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
}
|
|
printk_info("rs780_gfx_init single_port_configuration step13.\n");
|
|
|
|
|
|
|
|
/* step 14 Reset Enumeration Timer, disables the shortening of the enumeration timer */
|
|
set_pcie_enable_bits(dev, 0x70, 1 << 19, 1 << 19);
|
|
printk_info("rs780_gfx_init single_port_configuration step14.\n");
|
|
}
|
|
|
|
/* step 15 ~ step 18 from rpr */
|
|
static void dual_port_configuration(device_t nb_dev, device_t dev)
|
|
{
|
|
u8 result, width;
|
|
u32 reg32, dev_ind;
|
|
struct southbridge_amd_rs780_config *cfg =&chip_info;
|
|
|
|
_pci_break_tag(dev, NULL, &dev_ind, NULL);
|
|
/* 5.4.1.2 Dual Port Configuration */
|
|
set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31);
|
|
set_nbmisc_enable_bits(nb_dev, 0x08, 0xF << 8, 0x5 << 8);
|
|
set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31);
|
|
|
|
/* Training for Device 2 */
|
|
/* Releases hold training for GFX port 0 (device 2) */
|
|
PcieReleasePortTraining(nb_dev, dev, dev_ind);
|
|
/* PCIE Link Training Sequence */
|
|
result = PcieTrainPort(nb_dev, dev, dev_ind);
|
|
|
|
/* step 16: Power Down Control for Device 2 */
|
|
/* step 16.a Link Training was NOT successful */
|
|
if (!result) {
|
|
/* Powers down all lanes for port A */
|
|
/* nbpcie_ind_write_index(nb_dev, 0x65, 0x0f0f); */
|
|
/* Note: I have to disable the slot where there isnt a device,
|
|
* otherwise the system will hang. I dont know why. Do you guys know? */
|
|
set_nbmisc_enable_bits(nb_dev, 0x0c, 1 << dev_ind, 1 << dev_ind);
|
|
|
|
} else { /* step 16.b Link Training was successful */
|
|
/* FIXME: I am confused about this. It looks like about powerdown or something. */
|
|
reg32 = nbpcie_p_read_index(dev, 0xa2);
|
|
width = (reg32 >> 4) & 0x7;
|
|
printk_debug("GFX LC_LINK_WIDTH = 0x%x.\n", width);
|
|
switch (width) {
|
|
case 1:
|
|
case 2:
|
|
nbpcie_ind_write_index(nb_dev, 0x65,
|
|
cfg->gfx_lane_reversal ? 0x0707 : 0x0e0e);
|
|
break;
|
|
case 4:
|
|
nbpcie_ind_write_index(nb_dev, 0x65,
|
|
cfg->gfx_lane_reversal ? 0x0303 : 0x0c0c);
|
|
break;
|
|
}
|
|
}
|
|
#if 0 /* This function will be called twice, so we dont have to do dev 3 here. */
|
|
/* step 17: Training for Device 3 */
|
|
//set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 5, 0 << 5);
|
|
/* Releases hold training for GFX port 0 (device 3) */
|
|
PcieReleasePortTraining(nb_dev, dev, 3);
|
|
/* PCIE Link Training Sequence */
|
|
result = PcieTrainPort(nb_dev, dev, 3);
|
|
|
|
/*step 18: Power Down Control for Device 3 */
|
|
/* step 18.a Link Training was NOT successful */
|
|
if (!result) {
|
|
/* Powers down all lanes for port B and PLL1 */
|
|
nbpcie_ind_write_index(nb_dev, 0x65, 0xccf0f0);
|
|
} else { /* step 18.b Link Training was successful */
|
|
|
|
reg32 = nbpcie_p_read_index(dev, 0xa2);
|
|
width = (reg32 >> 4) & 0x7;
|
|
printk_debug("GFX LC_LINK_WIDTH = 0x%x.\n", width);
|
|
switch (width) {
|
|
case 1:
|
|
case 2:
|
|
nbpcie_ind_write_index(nb_dev, 0x65,
|
|
cfg->gfx_lane_reversal ? 0x7070 : 0xe0e0);
|
|
break;
|
|
case 4:
|
|
nbpcie_ind_write_index(nb_dev, 0x65,
|
|
cfg->gfx_lane_reversal ? 0x3030 : 0x0f0f);
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
/* For single port GFX configuration Only
|
|
* width:
|
|
* 000 = x16
|
|
* 001 = x1
|
|
* 010 = x2
|
|
* 011 = x4
|
|
* 100 = x8
|
|
* 101 = x12 (not supported)
|
|
* 110 = x16
|
|
*/
|
|
static void dynamic_link_width_control(device_t nb_dev, device_t dev, u8 width)
|
|
{
|
|
u32 reg32;
|
|
device_t sb_dev;
|
|
struct southbridge_amd_rs780_config *cfg =&chip_info;
|
|
|
|
/* step 5.9.1.1 */
|
|
reg32 = nbpcie_p_read_index(dev, 0xa2);
|
|
|
|
/* step 5.9.1.2 */
|
|
set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 1 << 0);
|
|
/* step 5.9.1.3 */
|
|
set_pcie_enable_bits(dev, 0xa2, 3 << 0, width << 0);
|
|
/* step 5.9.1.4 */
|
|
set_pcie_enable_bits(dev, 0xa2, 1 << 8, 1 << 8);
|
|
/* step 5.9.2.4 */
|
|
if (0 == cfg->gfx_reconfiguration)
|
|
set_pcie_enable_bits(dev, 0xa2, 1 << 11, 1 << 11);
|
|
|
|
/* step 5.9.1.5 */
|
|
do {
|
|
reg32 = nbpcie_p_read_index(dev, 0xa2);
|
|
}
|
|
while (reg32 & 0x100);
|
|
|
|
/* step 5.9.1.6 */
|
|
sb_dev = _pci_make_tag(0, 8, 0);
|
|
do {
|
|
reg32 = pci_ext_read_config16(nb_dev, sb_dev,
|
|
PCIE_VC0_RESOURCE_STATUS);
|
|
} while (reg32 & VC_NEGOTIATION_PENDING);
|
|
|
|
/* step 5.9.1.7 */
|
|
reg32 = nbpcie_p_read_index(dev, 0xa2);
|
|
if (((reg32 & 0x70) >> 4) != 0x6) {
|
|
/* the unused lanes should be powered off. */
|
|
}
|
|
|
|
/* step 5.9.1.8 */
|
|
set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 0 << 0);
|
|
}
|
|
|
|
/*
|
|
* GFX Core initialization, dev2, dev3
|
|
*/
|
|
void rs780_gfx_init(device_t nb_dev, device_t dev, u32 port)
|
|
{
|
|
u8 byte;
|
|
u16 reg16;
|
|
u32 reg32;
|
|
u32 dev_ind;
|
|
void set_pcie_reset();
|
|
void set_pcie_dereset();
|
|
//u8 is_dev3_present();
|
|
|
|
struct southbridge_amd_rs780_config *cfg =
|
|
&chip_info;
|
|
_pci_break_tag(dev, NULL, &dev_ind, NULL);
|
|
printk_info("rs780_gfx_init, nb_dev=0x%p, dev=0x%p, port=0x%x.\n",
|
|
nb_dev, dev, port);
|
|
|
|
/* GFX Core Initialization */
|
|
//if (port == 2) return;
|
|
|
|
|
|
|
|
/* step 2, TMDS, (only need if CMOS option is enabled) */
|
|
if (cfg->gfx_tmds) {
|
|
}
|
|
|
|
#if 1 /* external clock mode */
|
|
/* table 5-22, 5.9.1. REFCLK */
|
|
/* 5.9.1.1. Disables the GFX REFCLK transmitter so that the GFX
|
|
* REFCLK PAD can be driven by an external source. */
|
|
/* 5.9.1.2. Enables GFX REFCLK receiver to receive the REFCLK from an external source. */
|
|
set_nbmisc_enable_bits(nb_dev, 0x38, 1 << 29 | 1 << 28, 0 << 29 | 1 << 28);
|
|
|
|
/* 5.9.1.3 Selects the GFX REFCLK to be the source for PLL A. */
|
|
/* 5.9.1.4 Selects the GFX REFCLK to be the source for PLL B. */
|
|
/* 5.9.1.5 Selects the GFX REFCLK to be the source for PLL C. */
|
|
set_nbmisc_enable_bits(nb_dev, 0x28, 3 << 6 | 3 << 8 | 3 << 10,
|
|
1 << 6 | 1 << 8 | 1 << 10);
|
|
reg32 = nbmisc_read_index(nb_dev, 0x28);
|
|
printk_info("misc 28 = %x\n", reg32);
|
|
|
|
/* 5.9.1.6.Selects the single ended GFX REFCLK to be the source for core logic. */
|
|
set_nbmisc_enable_bits(nb_dev, 0x6C, 1 << 31, 1 << 31);
|
|
#else /* internal clock mode */
|
|
/* table 5-23, 5.9.1. REFCLK */
|
|
/* 5.9.1.1. Enables the GFX REFCLK transmitter so that the GFX
|
|
* REFCLK PAD can be driven by the SB REFCLK. */
|
|
/* 5.9.1.2. Disables GFX REFCLK receiver from receiving the
|
|
* REFCLK from an external source.*/
|
|
set_nbmisc_enable_bits(nb_dev, 0x38, 1 << 29 | 1 << 28, 1 << 29 | 0 << 28);
|
|
|
|
/* 5.9.1.3 Selects the GFX REFCLK to be the source for PLL A. */
|
|
/* 5.9.1.4 Selects the GFX REFCLK to be the source for PLL B. */
|
|
/* 5.9.1.5 Selects the GFX REFCLK to be the source for PLL C. */
|
|
set_nbmisc_enable_bits(nb_dev, 0x28, 3 << 6 | 3 << 8 | 3 << 10,
|
|
0);
|
|
reg32 = nbmisc_read_index(nb_dev, 0x28);
|
|
printk_info("misc 28 = %x\n", reg32);
|
|
|
|
/* 5.9.1.6.Selects the single ended GFX REFCLK to be the source for core logic. */
|
|
set_nbmisc_enable_bits(nb_dev, 0x6C, 1 << 31, 0 << 31);
|
|
#endif
|
|
|
|
/* step 5.9.3, GFX overclocking, (only need if CMOS option is enabled) */
|
|
/* 5.9.3.1. Increases PLL BW for 6G operation.*/
|
|
/* set_nbmisc_enable_bits(nb_dev, 0x36, 0x3FF << 4, 0xB5 << 4); */
|
|
/* skip */
|
|
|
|
/* step 5.9.4, reset the GFX link */
|
|
/* step 5.9.4.1 asserts both calibration reset and global reset */
|
|
set_nbmisc_enable_bits(nb_dev, 0x8, 0x3 << 14, 0x3 << 14);
|
|
|
|
/* step 5.9.4.2 de-asserts calibration reset */
|
|
set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 14, 0 << 14);
|
|
|
|
/* step 5.9.4.3 wait for at least 200us */
|
|
udelay(300);
|
|
|
|
/* step 5.9.4.4 de-asserts global reset */
|
|
set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 15, 0 << 15);
|
|
|
|
/* 5.9.5 Reset PCIE_GFX Slot */
|
|
/* It is done in mainboard.c */
|
|
set_pcie_reset();
|
|
delay(1000);
|
|
set_pcie_dereset();
|
|
|
|
/* step 5.9.8 program PCIE memory mapped configuration space */
|
|
/* done by enable_pci_bar3() before */
|
|
|
|
/* step 7 compliance state, (only need if CMOS option is enabled) */
|
|
/* the compliance stete is just for test. refer to 4.2.5.2 of PCIe specification */
|
|
if (cfg->gfx_compliance) {
|
|
/* force compliance */
|
|
set_nbmisc_enable_bits(nb_dev, 0x32, 1 << 6, 1 << 6);
|
|
/* release hold training for device 2. GFX initialization is done. */
|
|
set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 4, 0 << 4);
|
|
dynamic_link_width_control(nb_dev, dev, cfg->gfx_link_width);
|
|
printk_info("rs780_gfx_init step7.\n");
|
|
return;
|
|
}
|
|
|
|
/* 5.9.12 Core Initialization. */
|
|
/* 5.9.12.1 sets RCB timeout to be 25ms */
|
|
/* 5.9.12.2. RCB Cpl timeout on link down. */
|
|
set_pcie_enable_bits(dev, 0x70, 7 << 16 | 1 << 19, 4 << 16 | 1 << 19);
|
|
printk_info("rs780_gfx_init step5.9.12.1.\n");
|
|
|
|
/* step 5.9.12.3 disables slave ordering logic */
|
|
set_pcie_enable_bits(nb_dev, 0x20, 1 << 8, 1 << 8);
|
|
printk_info("rs780_gfx_init step5.9.12.3.\n");
|
|
|
|
/* step 5.9.12.4 sets DMA payload size to 64 bytes */
|
|
set_pcie_enable_bits(nb_dev, 0x10, 7 << 10, 4 << 10);
|
|
/* 5.9.12.5. Blocks DMA traffic during C3 state. */
|
|
set_pcie_enable_bits(dev, 0x10, 1 << 0, 0 << 0);
|
|
|
|
/* 5.9.12.6. Disables RC ordering logic */
|
|
set_pcie_enable_bits(nb_dev, 0x20, 1 << 9, 1 << 9);
|
|
|
|
/* Enabels TLP flushing. */
|
|
/* Note: It is got from RS690. The system will hang without this action. */
|
|
set_pcie_enable_bits(dev, 0x20, 1 << 19, 0 << 19);
|
|
|
|
/* 5.9.12.7. Ignores DLLPs during L1 so that txclk can be turned off */
|
|
set_pcie_enable_bits(nb_dev, 0x2, 1 << 0, 1 << 0);
|
|
|
|
/* 5.9.12.8 Prevents LC to go from L0 to Rcv_L0s if L1 is armed. */
|
|
set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11);
|
|
|
|
/* 5.9.12.9 CMGOOD_OVERRIDE for end point initiated lane degradation. */
|
|
set_nbmisc_enable_bits(nb_dev, 0x6a, 1 << 17, 1 << 17);
|
|
printk_info("rs780_gfx_init step5.9.12.9.\n");
|
|
|
|
/* 5.9.12.10 Sets the timer in Config state from 20us to */
|
|
/* 5.9.12.11 De-asserts RX_EN in L0s. */
|
|
/* 5.9.12.12 Enables de-assertion of PG2RX_CR_EN to lock clock
|
|
* recovery parameter when lane is in electrical idle in L0s.*/
|
|
set_pcie_enable_bits(dev, 0xB1, 1 << 23 | 1 << 19 | 1 << 28, 1 << 23 | 1 << 19 | 1 << 28);
|
|
|
|
/* 5.9.12.13. Turns off offset calibration. */
|
|
/* 5.9.12.14. Enables Rx Clock gating in CDR */
|
|
set_nbmisc_enable_bits(nb_dev, 0x34, 1 << 10/* | 1 << 22 */, 1 << 10/* | 1 << 22 */);
|
|
|
|
/* 5.9.12.15. Sets number of TX Clocks to drain TX Pipe to 3. */
|
|
set_pcie_enable_bits(dev, 0xA0, 0xF << 4, 3 << 4);
|
|
|
|
/* 5.9.12.16. Lets PI use Electrical Idle from PHY when
|
|
* turning off PLL in L1 at Gen2 speed instead Inferred Electrical Idle. */
|
|
set_pcie_enable_bits(nb_dev, 0x40, 3 << 14, 2 << 14);
|
|
|
|
/* 5.9.12.17. Prevents the Electrical Idle from causing a transition from Rcv_L0 to Rcv_L0s. */
|
|
set_pcie_enable_bits(dev, 0xB1, 1 << 20, 1 << 20);
|
|
|
|
/* 5.9.12.18. Prevents the LTSSM from going to Rcv_L0s if it has already
|
|
* acknowledged a request to go to L1. */
|
|
set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11);
|
|
|
|
/* 5.9.12.19. LDSK only taking deskew on deskewing error detect */
|
|
set_pcie_enable_bits(nb_dev, 0x40, 1 << 28, 0 << 28);
|
|
|
|
/* 5.9.12.20. Bypasses lane de-skew logic if in x1 */
|
|
set_pcie_enable_bits(nb_dev, 0xC2, 1 << 14, 1 << 14);
|
|
|
|
/* 5.9.12.21. Sets Electrical Idle Threshold. */
|
|
set_nbmisc_enable_bits(nb_dev, 0x35, 3 << 21, 2 << 21);
|
|
|
|
/* 5.9.12.22. Advertises -6 dB de-emphasis value in TS1 Data Rate Identifier
|
|
* Only if CMOS Option in section. skip */
|
|
|
|
/* 5.9.12.23. Disables GEN2 capability of the device. */
|
|
set_pcie_enable_bits(dev, 0xA4, 1 << 0, 0 << 0);
|
|
|
|
/* 5.9.12.24.Disables advertising Upconfigure Support. */
|
|
set_pcie_enable_bits(dev, 0xA2, 1 << 13, 1 << 13);
|
|
|
|
/* 5.9.12.25. No comment in RPR. */
|
|
set_nbmisc_enable_bits(nb_dev, 0x39, 1 << 10, 0 << 10);
|
|
|
|
/* 5.9.12.26. This capacity is required since links wider than x1 and/or multiple link
|
|
* speed are supported */
|
|
set_pcie_enable_bits(nb_dev, 0xC1, 1 << 0, 1 << 0);
|
|
|
|
/* 5.9.12.27. Enables NVG86 ECO. A13 above only. */
|
|
/* TODO: Check if it is A13. */
|
|
if (0) /* A12 */
|
|
set_pcie_enable_bits(dev, 0x02, 1 << 11, 1 << 11);
|
|
|
|
/* 5.9.12.28 Hides and disables the completion timeout method. */
|
|
set_pcie_enable_bits(nb_dev, 0xC1, 1 << 2, 0 << 2);
|
|
|
|
/* 5.9.12.29. Use the bif_core de-emphasis strength by default. */
|
|
/* set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 28, 1 << 28); */
|
|
|
|
/* 5.9.12.30. Set TX arbitration algorithm to round robin */
|
|
set_pcie_enable_bits(nb_dev, 0x1C,
|
|
1 << 0 | 0x1F << 1 | 0x1F << 6,
|
|
1 << 0 | 0x04 << 1 | 0x04 << 6);
|
|
|
|
pcie_commoncoreinit(nb_dev, dev);
|
|
pcie_commonportinit(nb_dev, dev);
|
|
pcie_initgen2(nb_dev, dev);
|
|
pcie_gen2workaround(nb_dev, dev);
|
|
|
|
|
|
/* Single-port/Dual-port configureation. */
|
|
switch (cfg->gfx_dual_slot) {
|
|
case 0:
|
|
/* step 1, lane reversal (only need if CMOS option is enabled) */
|
|
if (cfg->gfx_lane_reversal) {
|
|
set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2);
|
|
}
|
|
printk_info("rs780_gfx_init step1.\n");
|
|
printk_info("rs780_gfx_init step2.\n");
|
|
|
|
printk_info("device = %x\n", dev_ind);
|
|
if(dev_ind == 2)
|
|
single_port_configuration(nb_dev, dev);
|
|
else{
|
|
set_nbmisc_enable_bits(nb_dev, 0xc, 0x2 << 2, 0x2 << 2); /* hide the GFX bridge. */
|
|
printk_info("If dev3.., single port. Do nothing.\n");
|
|
}
|
|
|
|
break;
|
|
case 1:
|
|
/* step 1, lane reversal (only need if CMOS option is enabled) */
|
|
if (cfg->gfx_lane_reversal) {
|
|
set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2);
|
|
set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 3, 1 << 3);
|
|
}
|
|
printk_info("rs780_gfx_init step1.\n");
|
|
/* step 1.1, dual-slot gfx configuration (only need if CMOS option is enabled) */
|
|
/* AMD calls the configuration CrossFire */
|
|
set_nbmisc_enable_bits(nb_dev, 0x0, 0xf << 8, 5 << 8);
|
|
printk_info("rs780_gfx_init step2.\n");
|
|
|
|
printk_info("device = %x\n", dev_ind);
|
|
dual_port_configuration(nb_dev, dev);
|
|
break;
|
|
default:
|
|
printk_info("Incorrect configuration of external gfx slot.\n");
|
|
break;
|
|
}
|
|
}
|