Look for actual framebuffer size instead of hardcoding UMA
[coreboot.git] / src / southbridge / amd / rs780 / rs780_gfx.c
index 808bcb175fc2298ce1e69f8ef756a0cd1ce4ba7d..88cb935de8faf62ea43a6a81e86f5eef09049fc0 100644 (file)
@@ -25,6 +25,7 @@
  *     RS780M: 0x9612
  *     RS780MC:0x9613
  *     RS780E: 0x9615
+ *     RS785G: 0x9710 - just works, not much tested
  */
 #include <console/console.h>
 #include <device/device.h>
 #include <cpu/x86/msr.h>
 #include "rs780.h"
 
-void set_pcie_reset();
-void set_pcie_dereset();
+void set_pcie_reset(void);
+void set_pcie_dereset(void);
+
+/* Trust the original resource allocation. Don't do it again. */
+#undef DONT_TRUST_RESOURCE_ALLOCATION
+//#define DONT_TRUST_RESOURCE_ALLOCATION
 
 #define CLK_CNTL_INDEX 0x8
 #define CLK_CNTL_DATA  0xC
@@ -44,6 +49,7 @@ void set_pcie_dereset();
 /* The Integrated Info Table. */
 ATOM_INTEGRATED_SYSTEM_INFO_V2 vgainfo;
 
+#ifdef UNUSED_CODE
 static u32 clkind_read(device_t dev, u32 index)
 {
        u32     gfx_bar2 = pci_read_config32(dev, 0x18) & ~0xF;
@@ -51,11 +57,12 @@ static u32 clkind_read(device_t dev, u32 index)
        *(u32*)(gfx_bar2+CLK_CNTL_INDEX) = index & 0x7F;
        return *(u32*)(gfx_bar2+CLK_CNTL_DATA);
 }
+#endif
 
 static void clkind_write(device_t dev, u32 index, u32 data)
 {
        u32     gfx_bar2 = pci_read_config32(dev, 0x18) & ~0xF;
-       /* printk(BIOS_INFO, "gfx bar 2 %02x\n", gfx_bar2); */
+       /* printk(BIOS_DEBUG, "gfx bar 2 %02x\n", gfx_bar2); */
 
        *(u32*)(gfx_bar2+CLK_CNTL_INDEX) = index | 1<<7;
        *(u32*)(gfx_bar2+CLK_CNTL_DATA)  = data;
@@ -67,7 +74,7 @@ static void clkind_write(device_t dev, u32 index, u32 data)
 */
 static void rs780_gfx_read_resources(device_t dev)
 {
-       printk(BIOS_INFO, "rs780_gfx_read_resources.\n");
+       printk(BIOS_DEBUG, "rs780_gfx_read_resources.\n");
 
        /* The initial value of 0x24 is 0xFFFFFFFF, which is confusing.
           Even if we write 0xFFFFFFFF into it, it will be 0xFFF00000,
@@ -89,33 +96,34 @@ typedef struct _MMIORANGE
 
 MMIORANGE MMIO[8], CreativeMMIO[8];
 
-MMIORANGE* AllocMMIO(MMIORANGE* pMMIO)
+#define CIM_STATUS u32
+#define CIM_SUCCESS 0x00000000
+#define CIM_ERROR      0x80000000
+#define CIM_UNSUPPORTED        0x80000001
+#define CIM_DISABLEPORT 0x80000002
+
+#define        MMIO_ATTRIB_NP_ONLY     1
+#define MMIO_ATTRIB_BOTTOM_TO_TOP 1<<1
+#define MMIO_ATTRIB_SKIP_ZERO 1<<2
+
+#ifdef DONT_TRUST_RESOURCE_ALLOCATION
+static MMIORANGE* AllocMMIO(MMIORANGE* pMMIO)
 {
        int i;
-       for (i=0; i<8; i++)
-       {
+       for (i=0; i<8; i++) {
                if (pMMIO[i].Limit == 0)
                                return &pMMIO[i];
        }
        return 0;
 }
-void FreeMMIO(MMIORANGE* pMMIO)
+
+static void FreeMMIO(MMIORANGE* pMMIO)
 {
        pMMIO->Base = 0;
        pMMIO->Limit = 0;
 }
 
-#define CIM_STATUS u32
-#define CIM_SUCCESS 0x00000000
-#define CIM_ERROR      0x80000000
-#define CIM_UNSUPPORTED        0x80000001
-#define CIM_DISABLEPORT 0x80000002
-
-#define        MMIO_ATTRIB_NP_ONLY     1
-#define MMIO_ATTRIB_BOTTOM_TO_TOP 1<<1
-#define MMIO_ATTRIB_SKIP_ZERO 1<<2
-
-u32 SetMMIO(u32 Base, u32 Limit, u8 Attribute, MMIORANGE *pMMIO)
+static u32 SetMMIO(u32 Base, u32 Limit, u8 Attribute, MMIORANGE *pMMIO)
 {
        int i;
        MMIORANGE * TempRange;
@@ -139,7 +147,7 @@ u32 SetMMIO(u32 Base, u32 Limit, u8 Attribute, MMIORANGE *pMMIO)
        return 0;
 }
 
-u8 FinalizeMMIO(MMIORANGE *pMMIO)
+static u8 FinalizeMMIO(MMIORANGE *pMMIO)
 {
        int i, j, n = 0;
        for(i=0; i<8; i++)
@@ -173,7 +181,7 @@ u8 FinalizeMMIO(MMIORANGE *pMMIO)
        return n;
 }
 
-CIM_STATUS GetCreativeMMIO(MMIORANGE *pMMIO)
+static CIM_STATUS GetCreativeMMIO(MMIORANGE *pMMIO)
 {
        CIM_STATUS Status = CIM_UNSUPPORTED;
        u8 Bus, Dev, Reg, BusStart, BusEnd;
@@ -241,11 +249,10 @@ CIM_STATUS GetCreativeMMIO(MMIORANGE *pMMIO)
        return Status;
 }
 
-void ProgramMMIO(MMIORANGE *pMMIO, u8 LinkID, u8 Attribute)
+static void ProgramMMIO(MMIORANGE *pMMIO, u8 LinkID, u8 Attribute)
 {
        int i, j, n = 7;
        device_t k8_f1;
-       u32 temp32;
 
        k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1));
 
@@ -288,6 +295,7 @@ void ProgramMMIO(MMIORANGE *pMMIO, u8 LinkID, u8 Attribute)
                pci_write_config32(k8_f1, 0x80+MmioReg*8, Base);
        }
 }
+#endif
 
 static void internal_gfx_pci_dev_init(struct device *dev)
 {
@@ -296,21 +304,19 @@ static void internal_gfx_pci_dev_init(struct device *dev)
        volatile u32 * pointer;
        int i;
        u16 command;
-       u32 value, temp, Base32, Limit32;
-       CIM_STATUS Status;
+       u32 value;
        u16 deviceid, vendorid;
        device_t nb_dev = dev_find_slot(0, 0);
        device_t k8_f2 = dev_find_slot(0, PCI_DEVFN(0x18, 2));
-       device_t k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1));
        device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0));
-       device_t dev0x14 = dev_find_slot(0, PCI_DEVFN(0x14, 4));
 
-       struct southbridge_amd_rs780_config *cfg =
-           (struct southbridge_amd_rs780_config *)dev->chip_info;
+       /* We definetely will use this in future. Just leave it here. */
+       /*struct southbridge_amd_rs780_config *cfg =
+          (struct southbridge_amd_rs780_config *)dev->chip_info;*/
 
        deviceid = pci_read_config16(dev, PCI_DEVICE_ID);
        vendorid = pci_read_config16(dev, PCI_VENDOR_ID);
-       printk(BIOS_INFO, "internal_gfx_pci_dev_init device=%x, vendor=%x.\n",
+       printk(BIOS_DEBUG, "internal_gfx_pci_dev_init device=%x, vendor=%x.\n",
             deviceid, vendorid);
 
        command = pci_read_config16(dev, 0x04);
@@ -331,7 +337,7 @@ static void internal_gfx_pci_dev_init(struct device *dev)
        value = nbmc_read_index(nb_dev, 0x10);
        *(GpuF0MMReg + 0x2000/4) = 0x11;
        *(GpuF0MMReg + 0x2180/4) = ((value&0xff00)>>8)|((value&0xff000000)>>8);
-       *(GpuF0MMReg + 0x2c04/4) = ((value&0xff0)<<8);
+       *(GpuF0MMReg + 0x2c04/4) = ((value&0xff00)<<8);
        *(GpuF0MMReg + 0x5428/4) = ((value&0xffff0000)+0x10000)-((value&0xffff)<<16);
        *(GpuF0MMReg + 0x2000/4) = 0x00000011;
        *(GpuF0MMReg + 0x200c/4) = 0x00000020;
@@ -430,7 +436,8 @@ static void internal_gfx_pci_dev_init(struct device *dev)
        //vgainfo.ulSystemConfig |= 1<<1 | 1<<3 | 1<<4 | 1<<5 | 1<<6 | 1<<7 | 1;
        vgainfo.ulBootUpReqDisplayVector = 0; //?
        vgainfo.ulOtherDisplayMisc = 0; //?
-       vgainfo.ulDDISlot1Config = 0x000c0011; //0; //?
+       vgainfo.ulDDISlot1Config = 0x000c0011; //0; //VGA
+       //vgainfo.ulDDISlot1Config = 0x000c00FF; //0; //HDMI
        vgainfo.ulDDISlot2Config = 0x00130022; //0; //?
        vgainfo.ucMemoryType = 2;
        /* UMA Channel Number: 1 or 2. */
@@ -491,7 +498,7 @@ static void internal_gfx_pci_dev_init(struct device *dev)
                pci_write_config8(dev, 0x4, temp8);
        }
 
-#if 0 /* Trust the original resource allocation. Don't do it again. */
+#ifdef DONT_TRUST_RESOURCE_ALLOCATION
        /* NB_SetupMGMMIO. */
 
        /* clear MMIO and CreativeMMIO. */
@@ -577,7 +584,6 @@ static void rs780_internal_gfx_enable(device_t dev)
 {
        u32 l_dword;
        int i;
-       device_t k8_f0 = 0, k8_f2 = 0;
        device_t nb_dev = dev_find_slot(0, 0);
        msr_t sysmem;
 
@@ -585,10 +591,10 @@ static void rs780_internal_gfx_enable(device_t dev)
        u32 FB_Start, FB_End;
 #endif
 
-       printk(BIOS_INFO, "rs780_internal_gfx_enable dev = 0x%p, nb_dev = 0x%p.\n", dev, nb_dev);
+       printk(BIOS_DEBUG, "rs780_internal_gfx_enable dev = 0x%p, nb_dev = 0x%p.\n", dev, nb_dev);
 
        sysmem = rdmsr(0xc001001a);
-       printk(BIOS_INFO, "sysmem = %x_%x\n", sysmem.hi, sysmem.lo);
+       printk(BIOS_DEBUG, "sysmem = %x_%x\n", sysmem.hi, sysmem.lo);
 
        /* The system top memory in 780. */
        pci_write_config32(nb_dev, 0x90, sysmem.lo);
@@ -610,7 +616,7 @@ static void rs780_internal_gfx_enable(device_t dev)
 
        /* LPC DMA Deadlock workaround? */
        /* GFX_InitCommon*/
-       k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0));
+       device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0));
        l_dword = pci_read_config32(k8_f0, 0x68);
        l_dword &= ~(3 << 21);
        l_dword |= (1 << 21);
@@ -625,7 +631,7 @@ static void rs780_internal_gfx_enable(device_t dev)
 #if (CONFIG_GFXUMA == 1)
        /* GFX_InitUMA. */
        /* Copy CPU DDR Controller to NB MC. */
-       k8_f2 = dev_find_slot(0, PCI_DEVFN(0x18, 2));
+       device_t k8_f2 = dev_find_slot(0, PCI_DEVFN(0x18, 2));
        for (i = 0; i < 12; i++)
        {
                l_dword = pci_read_config32(k8_f2, 0x40 + i * 4);
@@ -654,8 +660,10 @@ static void rs780_internal_gfx_enable(device_t dev)
 
        /* Set UMA in the 780 side. */
        /* UMA start address, size. */
-       /* The same value in spite of system memory size. */
-       nbmc_write_index(nb_dev, 0x10, 0xcfffc000);
+       /* The UMA starts at 0xC0000000 of internal RS780 address space
+           [31:16] addr of last byte | [31:16] addr of first byte
+       */
+       nbmc_write_index(nb_dev, 0x10, ((uma_memory_size - 1 + 0xC0000000) & (~0xffff)) | 0xc000);
        nbmc_write_index(nb_dev, 0x11, uma_memory_base);
        nbmc_write_index(nb_dev, 0x12, 0);
        nbmc_write_index(nb_dev, 0xf0, 256);
@@ -817,6 +825,11 @@ static const struct pci_driver pcie_driver_780e __pci_driver = {
        .vendor = PCI_VENDOR_ID_ATI,
        .device = PCI_DEVICE_ID_ATI_RS780E_INT_GFX,
 };
+static const struct pci_driver pcie_driver_785g __pci_driver = {
+       .ops = &pcie_ops,
+       .vendor = PCI_VENDOR_ID_ATI,
+       .device = PCI_DEVICE_ID_ATI_RS785G_INT_GFX,
+};
 
 /* step 12 ~ step 14 from rpr */
 static void single_port_configuration(device_t nb_dev, device_t dev)
@@ -826,12 +839,12 @@ static void single_port_configuration(device_t nb_dev, device_t dev)
        struct southbridge_amd_rs780_config *cfg =
            (struct southbridge_amd_rs780_config *)nb_dev->chip_info;
 
-       printk(BIOS_INFO, "rs780_gfx_init single_port_configuration.\n");
+       printk(BIOS_DEBUG, "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(BIOS_INFO, "rs780_gfx_init single_port_configuration step12.\n");
+       printk(BIOS_DEBUG, "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. */
@@ -868,11 +881,11 @@ static void single_port_configuration(device_t nb_dev, device_t dev)
                        break;
                }
        }
-       printk(BIOS_INFO, "rs780_gfx_init single_port_configuration step13.\n");
+       printk(BIOS_DEBUG, "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(BIOS_INFO, "rs780_gfx_init single_port_configuration step14.\n");
+       printk(BIOS_DEBUG, "rs780_gfx_init single_port_configuration step14.\n");
 }
 
 static void dual_port_configuration(device_t nb_dev, device_t dev)
@@ -978,31 +991,16 @@ static void dynamic_link_width_control(device_t nb_dev, device_t dev, u8 width)
 */
 void rs780_gfx_init(device_t nb_dev, device_t dev, u32 port)
 {
-       u16 reg16;
        u32 reg32;
        struct southbridge_amd_rs780_config *cfg =
            (struct southbridge_amd_rs780_config *)nb_dev->chip_info;
 
-       printk(BIOS_INFO, "rs780_gfx_init, nb_dev=0x%p, dev=0x%p, port=0x%x.\n",
+       printk(BIOS_DEBUG, "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 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(BIOS_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(BIOS_INFO, "rs780_gfx_init step2.\n");
-
        /* step 2, TMDS, (only need if CMOS option is enabled) */
        if (cfg->gfx_tmds) {
        }
@@ -1020,7 +1018,7 @@ void rs780_gfx_init(device_t nb_dev, device_t dev, u32 port)
        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_INFO, "misc 28 = %x\n", reg32);
+       printk(BIOS_DEBUG, "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);
@@ -1038,7 +1036,7 @@ void rs780_gfx_init(device_t nb_dev, device_t dev, u32 port)
        set_nbmisc_enable_bits(nb_dev, 0x28, 3 << 6 | 3 << 8 | 3 << 10,
                               0);
        reg32 = nbmisc_read_index(nb_dev, 0x28);
-       printk(BIOS_INFO, "misc 28 = %x\n", reg32);
+       printk(BIOS_DEBUG, "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);
@@ -1079,7 +1077,7 @@ void rs780_gfx_init(device_t nb_dev, device_t dev, u32 port)
                /* 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(BIOS_INFO, "rs780_gfx_init step7.\n");
+               printk(BIOS_DEBUG, "rs780_gfx_init step7.\n");
                return;
        }
 
@@ -1087,11 +1085,11 @@ void rs780_gfx_init(device_t nb_dev, device_t dev, u32 port)
        /* 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(BIOS_INFO, "rs780_gfx_init step5.9.12.1.\n");
+       printk(BIOS_DEBUG, "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(BIOS_INFO, "rs780_gfx_init step5.9.12.3.\n");
+       printk(BIOS_DEBUG, "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);
@@ -1113,7 +1111,7 @@ void rs780_gfx_init(device_t nb_dev, device_t dev, u32 port)
 
        /* 5.9.12.9 CMGOOD_OVERRIDE for end point initiated lane degradation. */
        set_nbmisc_enable_bits(nb_dev, 0x6a, 1 << 17, 1 << 17);
-       printk(BIOS_INFO, "rs780_gfx_init step5.9.12.9.\n");
+       printk(BIOS_DEBUG, "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. */
@@ -1182,13 +1180,42 @@ void rs780_gfx_init(device_t nb_dev, device_t dev, u32 port)
        /* Single-port/Dual-port configureation. */
        switch (cfg->gfx_dual_slot) {
        case 0:
-               single_port_configuration(nb_dev, dev);
+               /* step 1, lane reversal (only need if build config option is enabled) */
+               if (cfg->gfx_lane_reversal) {
+                       set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31);
+                       set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2);
+                       set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31);
+               }
+               printk(BIOS_DEBUG, "rs780_gfx_init step1.\n");
+
+               printk(BIOS_DEBUG, "device = %x\n", dev->path.pci.devfn >> 3);
+               if((dev->path.pci.devfn >> 3) == 2) {
+                       single_port_configuration(nb_dev, dev);
+               } else {
+                       set_nbmisc_enable_bits(nb_dev, 0xc, 0, 0x2 << 2); /* hide the GFX bridge. */
+                       printk(BIOS_INFO, "Single port. Do nothing.\n"); // If dev3
+               }
+
                break;
        case 1:
+               /* step 1, lane reversal (only need if build config option is enabled) */
+               if (cfg->gfx_lane_reversal) {
+                       set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31);
+                       set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2);
+                       set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 3, 1 << 3);
+                       set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31);
+               }
+               printk(BIOS_DEBUG, "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(BIOS_DEBUG, "rs780_gfx_init step2.\n");
+
+               printk(BIOS_DEBUG, "device = %x\n", dev->path.pci.devfn >> 3);
                dual_port_configuration(nb_dev, dev);
                break;
        default:
-               printk(BIOS_INFO, "Incorrect configuration of external gfx slot.\n");
+               printk(BIOS_INFO, "Incorrect configuration of external GFX slot.\n");
                break;
        }
 }