X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fsouthbridge%2Famd%2Frs780%2Fgfx.c;h=65a5e2bd2f21557eabc6bdf8a3c3149ef7114752;hb=5ff7c13e858a31addf1558731a12cf6c753b576d;hp=4a141314f9a7a61aaf05ee10a415cc782f5f9839;hpb=4a778db86edfb65fe74ba2a2596efe3347780b8c;p=coreboot.git diff --git a/src/southbridge/amd/rs780/gfx.c b/src/southbridge/amd/rs780/gfx.c index 4a141314f..65a5e2bd2 100644 --- a/src/southbridge/amd/rs780/gfx.c +++ b/src/southbridge/amd/rs780/gfx.c @@ -26,6 +26,10 @@ * RS780MC:0x9613 * RS780E: 0x9615 * RS785G: 0x9710 - just works, not much tested + * RS785C: 0x9711 + * RS785M: 0x9712 + * RS785MC:0x9713 + * RS785D: 0x9714 */ #include #include @@ -299,6 +303,43 @@ static void ProgramMMIO(MMIORANGE *pMMIO, u8 LinkID, u8 Attribute) } #endif +#define GFX_CONFIG_DDI1 0x04 +#define GFX_CONFIG_DDI2 0x08 +#define GFX_CONFIG_DDI (GFX_CONFIG_DDI1 | GFX_CONFIG_DDI2) + +/** + * Force poweron pads for lanes used for DDI + * reference CIMx PCIEL_PowerOnDDILanes() + * + * Inactive B_PRX_PDNB_FDIS B_PTX_PDNB_FDIS + * Lanes + * Lanes 0-1 Bit 8 Bit 0 + * Lanes 2-3 Bit 9 Bit 1 + * Lanes 4-5 Bit 10 Bit 2 + * Lanes 6-7 Bit 11 Bit 3 + * Lanes 8-9 Bit 12 Bit 4 + * Lanes 10-11 Bit 13 Bit 5 + * Lanes 12-13 Bit 14 Bit 6 + * Lanes 14-15 Bit 15 Bit 7 + */ +static void poweron_ddi_lanes(device_t nb_dev) +{ + u8 i; + u32 gfx_cfg = 0; + u32 ddi_pads = 0; + + ddi_pads = ~(nbpcie_ind_read_index(nb_dev, 0x65)); /* save original setting */ + gfx_cfg = nbmisc_read_index(nb_dev, 0x74); + for (i = 0; i < 3 ; i++) { + if (gfx_cfg & GFX_CONFIG_DDI) { + ddi_pads |= (3 << (i * 2)); + } + gfx_cfg >>= 8; + } + ddi_pads |= ddi_pads << 8; /* both TX and RX */ + nbpcie_ind_write_index(nb_dev, 0x65, ~ddi_pads); +} + static void internal_gfx_pci_dev_init(struct device *dev) { unsigned char * bpointer; @@ -470,7 +511,7 @@ static void internal_gfx_pci_dev_init(struct device *dev) vgainfo.ucUMAChannelNumber = 2; } } - + // processor type if (is_family0Fh()) vgainfo.ulCPUCapInfo = 3; @@ -498,9 +539,9 @@ static void internal_gfx_pci_dev_init(struct device *dev) /* HT width. */ value = pci_read_config8(nb_dev, 0xcb); - vgainfo.usMinDownStreamHTLinkWidth = - vgainfo.usMaxDownStreamHTLinkWidth = - vgainfo.usMinUpStreamHTLinkWidth = + vgainfo.usMinDownStreamHTLinkWidth = + vgainfo.usMaxDownStreamHTLinkWidth = + vgainfo.usMinUpStreamHTLinkWidth = vgainfo.usMaxUpStreamHTLinkWidth = vgainfo.usMinHTLinkWidth = vgainfo.usMaxHTLinkWidth = ht_width_lookup [extractbits(value, 0, 2)]; @@ -531,6 +572,9 @@ static void internal_gfx_pci_dev_init(struct device *dev) } } + /* Poweron DDI Lanes */ + poweron_ddi_lanes(nb_dev); + /* Transfer the Table to VBIOS. */ pointer = (u32 *)&vgainfo; for(i=0; i> 4) & 0x7; printk(BIOS_DEBUG, "GFX LC_LINK_WIDTH = 0x%x.\n", width); @@ -1085,6 +1153,147 @@ void rs780_gfx_init(device_t nb_dev, device_t dev, u32 port) /* step 2, TMDS, (only need if CMOS option is enabled) */ if (cfg->gfx_tmds) { + /** + * PCIe Initialization for DDI. + * The VBIOS/Driver is responsible for DDI programming sequence, + * The SBIOS is responsible for programming the lane and clock muxing specific to each case. + * Refer to RPR Chapter 7: "PCIe Initialization for DDI". + * Note: This programming must be done before hold training is released. + */ + switch (cfg->gfx_pcie_config) { + case 1: /* 1x16 GFX -default case, no programming required */ + break; + case 2: /* 1x8 GFX on Lanes 0-7 */ + case 5: /* 1x4 GPP on Lanes 0-3 */ + set_nbmisc_enable_bits(nb_dev, 0x27, 0x1 << 6, 0x1 << 6); /* Disables PCIe mode on PHY Lanes 8-11 */ + set_nbmisc_enable_bits(nb_dev, 0x27, 0x1 << 7, 0x1 << 7); /* Disables PCIe mode on PHY Lanes 12-15 */ + break; + case 3: /* 1x8 on Lanes 8-15 */ + case 7: /* 1x4 GPP on Lanes 8-11 */ + /* TXCLK */ + set_nbmisc_enable_bits(nb_dev, 0x07, 1 << 16, 1 << 16); + set_nbmisc_enable_bits(nb_dev, 0x07, 0xF << 12, 0xF << 12); + set_nbmisc_enable_bits(nb_dev, 0x07, 0x3 << 24, 0x2 << 24); + set_nbmisc_enable_bits(nb_dev, 0x28, 0x3 << 0, 0x0 << 0); + /* RXCLK */ + set_nbmisc_enable_bits(nb_dev, 0x27, 0x3 << 8, 0x2 << 8); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x3 << 10, 0x2 << 10); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x3 << 12, 0x2 << 12); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x3 << 14, 0x2 << 14); + /* TX Lane Muxing */ + set_nbmisc_enable_bits(nb_dev, 0x27, 0x1 << 2, 0x1 << 2); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x1 << 3, 0x1 << 3); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x1 << 4, 0x1 << 4); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x1 << 5, 0x1 << 5); + break; + case 4: /* 2x8 */ + case 10: /* 1x4 GPP on Lanes 0-3 and 1x4 GPP on Lanes 8-11 */ + case 14: /* 1x8 GFX on Lanes 0-7 and 1x4 GPP on Lanes 8-11 */ + case 17: /* 1x4 GPP on Lanes 0-3 and 1x8 GFX on Lanes 8-15 */ + /* Set dual slot configuration */ + set_nbmisc_enable_bits(nb_dev, 0x08, 0xF << 8, 0x5 << 8); + break; + case 9: /* PCIe 2x4 GPPs on Lanes 0-7 */ + case 6: /* PCIe 1x4 GPP on Lanes 4-7 */ + /* Set dual slot configuration */ + set_nbmisc_enable_bits(nb_dev, 0x08, 0xF << 8, 0x5 << 8); + /* TXCLK */ + set_nbmisc_enable_bits(nb_dev, 0x07, 1 << 16, 0 << 16); + set_nbmisc_enable_bits(nb_dev, 0x07, 0xF << 12, 0x0 << 12); + set_nbmisc_enable_bits(nb_dev, 0x07, 0x3 << 20, 0x0 << 20); + set_nbmisc_enable_bits(nb_dev, 0x28, 0x1 << 0, 0x0 << 0); + /* RXCLK */ + set_nbmisc_enable_bits(nb_dev, 0x27, 0x3 << 8, 0x0 << 8); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x3 << 10, 0x1 << 10); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x3 << 12, 0x3 << 12); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x3 << 14, 0x0 << 14); + /* TX Lane Muxing */ + set_nbmisc_enable_bits(nb_dev, 0x27, 0x1 << 1, 0x1 << 1); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x1 << 6, 0x1 << 6); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x1 << 7, 0x1 << 7); + break; + case 13: /* 2x4 GPPs on Lanes 8-15 */ + case 8: /* 1x4 GPP on Lanes 12-15 */ + /* Set dual slot configuration */ + set_nbmisc_enable_bits(nb_dev, 0x08, 0xF << 8, 0x5 << 8); + /* TXCLK */ + set_nbmisc_enable_bits(nb_dev, 0x07, 1 << 16, 1 << 16); + set_nbmisc_enable_bits(nb_dev, 0x07, 0xF << 12, 0xF << 12); + set_nbmisc_enable_bits(nb_dev, 0x07, 0x3 << 24, 0x2 << 24); + set_nbmisc_enable_bits(nb_dev, 0x28, 0x3 << 0, 0x3 << 0); + /* RXCLK */ + set_nbmisc_enable_bits(nb_dev, 0x27, 0x3 << 8, 0x2 << 8); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x3 << 10, 0x3 << 10); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x3 << 12, 0x1 << 12); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x3 << 14, 0x2 << 14); + /* TX Lane Muxing */ + set_nbmisc_enable_bits(nb_dev, 0x27, 0x1 << 2, 0x1 << 2); + set_nbmisc_enable_bits(nb_dev, 0x28, 0x1 << 14, 0x1 << 14); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x1 << 4, 0x1 << 4); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x1 << 5, 0x1 << 5); + break; + case 15: /* 1x8 GFX on Lanes 0-7 and 1x4 GPP on Lanes 12-15 */ + case 11: /* 1x4 GPP on Lanes 0-3 and 1x4 GPP on Lanes 12-15 */ + /* Set dual slot configuration */ + set_nbmisc_enable_bits(nb_dev, 0x08, 0xF << 8, 0x5 << 8); + /* TXCLK */ + set_nbmisc_enable_bits(nb_dev, 0x07, 1 << 16, 0 << 16); + set_nbmisc_enable_bits(nb_dev, 0x07, 0xF << 12, 0x0 << 12); + set_nbmisc_enable_bits(nb_dev, 0x07, 0x3 << 20, 0x0 << 20); + set_nbmisc_enable_bits(nb_dev, 0x28, 0x3 << 0, 0x1 << 0); + /* RXCLK */ + set_nbmisc_enable_bits(nb_dev, 0x27, 0x3 << 8, 0x0 << 8); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x3 << 10, 0x0 << 10); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x3 << 12, 0x1 << 12); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x3 << 14, 0x3 << 14); + /* TX Lane Muxing */ + set_nbmisc_enable_bits(nb_dev, 0x28, 0x1 << 14, 0x1 << 14); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x1 << 6, 0x1 << 6); + break; + case 16: /* 1x8 GFX on Lanes 8-15 and 1x4 GPP on Lanes 4-7 */ + case 12: /* 1x4 GPP on Lanes 4-7 and 1x8 GFX on Lanes 8-15 */ + /* Set dual slot configuration */ + set_nbmisc_enable_bits(nb_dev, 0x08, 0xF << 8, 0x5 << 8); + /* TXCLK */ + set_nbmisc_enable_bits(nb_dev, 0x07, 1 << 16, 1 << 16); + set_nbmisc_enable_bits(nb_dev, 0x07, 0xF << 12, 0xF << 12); + set_nbmisc_enable_bits(nb_dev, 0x07, 0x3 << 24, 0x2 << 24); + set_nbmisc_enable_bits(nb_dev, 0x07, 0x3 << 22, 0x2 << 22); + set_nbmisc_enable_bits(nb_dev, 0x28, 0x3 << 0, 0x2 << 0); + /* RXCLK */ + set_nbmisc_enable_bits(nb_dev, 0x27, 0x3 << 8, 0x2 << 8); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x3 << 10, 0x2 << 10); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x3 << 12, 0x3 << 12); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x3 << 14, 0x1 << 14); + /* TX Lane Muxing */ + set_nbmisc_enable_bits(nb_dev, 0x27, 0x1 << 2, 0x1 << 2); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x1 << 3, 0x1 << 3); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x1 << 1, 0x1 << 1); + set_nbmisc_enable_bits(nb_dev, 0x27, 0x1 << 4, 0x1 << 4); + break; + default: + printk(BIOS_INFO, "Incorrect configuration of external GFX slot.\n"); + break; + } + + /* DDI Configuration */ + switch (cfg->gfx_ddi_config) { + case 1: /* DDI_SL lanes0-3 */ + nbmisc_write_index(nb_dev, 0x74, GFX_CONFIG_DDI); + break; + case 2: /* DDI_SL lanes4-7 */ + nbmisc_write_index(nb_dev, 0x74, (GFX_CONFIG_DDI << 8)); + break; + case 5: /* DDI_SL lanes0-4, lanes4-7 */ + nbmisc_write_index(nb_dev, 0x74, (GFX_CONFIG_DDI << 8) | GFX_CONFIG_DDI); + break; + case 6: /* DDI_DL lanes0-7 */ + nbmisc_write_index(nb_dev, 0x74, (GFX_CONFIG_DDI << 8) | GFX_CONFIG_DDI); + break; + default: + printk(BIOS_INFO, "Incorrect configuration of external GFX slot.\n"); + break; + } } #if 1 /* external clock mode */ @@ -1097,8 +1306,6 @@ void rs780_gfx_init(device_t nb_dev, device_t dev, u32 port) /* 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(BIOS_DEBUG, "misc 28 = %x\n", reg32);