1 /* Public domain. */ 2 3 #include <linux/types.h> 4 #include <linux/ioport.h> 5 #include <linux/pci.h> 6 #include <drm/i915_drm.h> 7 #include "i915_drv.h" 8 9 struct resource intel_graphics_stolen_res = DEFINE_RES_MEM(0, 0); 10 11 bus_addr_t 12 gen3_stolen_base(struct inteldrm_softc *dev_priv) 13 { 14 uint32_t bsm = pci_conf_read(dev_priv->pc, dev_priv->tag, 15 INTEL_BSM); 16 return bsm & INTEL_BSM_MASK; 17 } 18 19 bus_addr_t 20 gen11_stolen_base(struct inteldrm_softc *dev_priv) 21 { 22 uint64_t bsm = pci_conf_read(dev_priv->pc, dev_priv->tag, 23 INTEL_GEN11_BSM_DW0); 24 bsm &= INTEL_BSM_MASK; 25 bsm |= (uint64_t)pci_conf_read(dev_priv->pc, dev_priv->tag, 26 INTEL_GEN11_BSM_DW1) << 32; 27 return bsm; 28 } 29 30 bus_size_t 31 i830_stolen_size(struct inteldrm_softc *dev_priv) 32 { 33 uint16_t gmch_ctl, gms; 34 35 pci_read_config_word(dev_priv->bridge_dev, I830_GMCH_CTRL, 36 &gmch_ctl); 37 gms = gmch_ctl & I830_GMCH_GMS_MASK; 38 39 switch (gms) { 40 case I830_GMCH_GMS_STOLEN_512: 41 return 512 * 1024; 42 case I830_GMCH_GMS_STOLEN_1024: 43 return 1 * 1024 * 1024; 44 case I830_GMCH_GMS_STOLEN_8192: 45 return 8 * 1024 * 1024; 46 } 47 48 return 0; 49 } 50 51 bus_size_t 52 gen3_stolen_size(struct inteldrm_softc *dev_priv) 53 { 54 uint16_t gmch_ctl, gms; 55 56 pci_read_config_word(dev_priv->bridge_dev, I830_GMCH_CTRL, 57 &gmch_ctl); 58 gms = gmch_ctl & I855_GMCH_GMS_MASK; 59 60 switch (gms) { 61 case I855_GMCH_GMS_STOLEN_1M: 62 return 1 * 1024 * 1024; 63 case I855_GMCH_GMS_STOLEN_4M: 64 return 4 * 1024 * 1024; 65 case I855_GMCH_GMS_STOLEN_8M: 66 return 8 * 1024 * 1024; 67 case I855_GMCH_GMS_STOLEN_16M: 68 return 16 * 1024 * 1024; 69 case I855_GMCH_GMS_STOLEN_32M: 70 return 32 * 1024 * 1024; 71 case I915_GMCH_GMS_STOLEN_48M: 72 return 48 * 1024 * 1024; 73 case I915_GMCH_GMS_STOLEN_64M: 74 return 64 * 1024 * 1024; 75 case G33_GMCH_GMS_STOLEN_128M: 76 return 128 * 1024 * 1024; 77 case G33_GMCH_GMS_STOLEN_256M: 78 return 256 * 1024 * 1024; 79 case INTEL_GMCH_GMS_STOLEN_96M: 80 return 96 * 1024 * 1024; 81 case INTEL_GMCH_GMS_STOLEN_160M: 82 return 160 * 1024 * 1024; 83 case INTEL_GMCH_GMS_STOLEN_224M: 84 return 224 * 1024 * 1024; 85 case INTEL_GMCH_GMS_STOLEN_352M: 86 return 352 * 1024 * 1024; 87 } 88 89 return 0; 90 } 91 92 bus_size_t 93 gen6_stolen_size(struct inteldrm_softc *dev_priv) 94 { 95 struct pci_dev *pdev = dev_priv->drm.pdev; 96 uint16_t gmch_ctl, gms; 97 98 pci_read_config_word(pdev, SNB_GMCH_CTRL, &gmch_ctl); 99 gms = (gmch_ctl >> SNB_GMCH_GMS_SHIFT) & SNB_GMCH_GMS_MASK; 100 101 return gms * (32 * 1024 * 1024); 102 } 103 104 bus_size_t 105 chv_stolen_size(struct inteldrm_softc *dev_priv) 106 { 107 struct pci_dev *pdev = dev_priv->drm.pdev; 108 uint16_t gmch_ctl, gms; 109 110 pci_read_config_word(pdev, SNB_GMCH_CTRL, &gmch_ctl); 111 gms = (gmch_ctl >> SNB_GMCH_GMS_SHIFT) & SNB_GMCH_GMS_MASK; 112 113 if (gms < 0x11) 114 return gms * (32 * 1024 * 1024); 115 else if (gms < 0x17) 116 return (gms - 0x11) * (4 * 1024 * 1024) + (8 * 1024 * 1024); 117 else 118 return (gms - 0x17) + (4 * 1024 * 1024) + (36 * 1024 * 1024); 119 } 120 121 bus_size_t 122 gen8_stolen_size(struct inteldrm_softc *dev_priv) 123 { 124 struct pci_dev *pdev = dev_priv->drm.pdev; 125 uint16_t gmch_ctl, gms; 126 127 pci_read_config_word(pdev, SNB_GMCH_CTRL, &gmch_ctl); 128 gms = (gmch_ctl >> BDW_GMCH_GMS_SHIFT) & BDW_GMCH_GMS_MASK; 129 130 return gms * (32 * 1024 * 1024); 131 } 132 133 bus_size_t 134 gen9_stolen_size(struct inteldrm_softc *dev_priv) 135 { 136 struct pci_dev *pdev = dev_priv->drm.pdev; 137 uint16_t gmch_ctl, gms; 138 139 pci_read_config_word(pdev, SNB_GMCH_CTRL, &gmch_ctl); 140 gms = (gmch_ctl >> BDW_GMCH_GMS_SHIFT) & BDW_GMCH_GMS_MASK; 141 if (gms < 0xf0) 142 return gms * (32 * 1024 * 1024); 143 else 144 return (gms - 0xf0) * (4 * 1024 * 1024) + (4 * 1024 * 1024); 145 } 146 147 void 148 intel_init_stolen_res(struct inteldrm_softc *dev_priv) 149 { 150 bus_addr_t stolen_base = 0; 151 bus_size_t stolen_size = 0; 152 153 #ifdef notyet 154 if (IS_I830(dev_priv)) 155 stolen_base = i830_stolen_base(dev_priv); 156 else if (IS_I845G(dev_priv)) 157 stolen_base = i845_stolen_base(dev_priv); 158 else if (IS_I85X(dev_priv)) 159 stolen_base = i85x_stolen_base(dev_priv); 160 else if (IS_I865G(dev_priv)) 161 stolen_base = i865_stolen_base(dev_priv); 162 #endif 163 164 if (INTEL_GEN(dev_priv) >= 3 && INTEL_GEN(dev_priv) < 11) 165 stolen_base = gen3_stolen_base(dev_priv); 166 else if (INTEL_GEN(dev_priv) == 11) 167 stolen_base = gen11_stolen_base(dev_priv); 168 169 if (IS_I830(dev_priv) || IS_I845G(dev_priv)) 170 stolen_size = i830_stolen_size(dev_priv); 171 else if (IS_I85X(dev_priv) || IS_I865G(dev_priv) || 172 (INTEL_GEN(dev_priv) >= 3 && INTEL_GEN(dev_priv) <= 5)) 173 stolen_size = gen3_stolen_size(dev_priv); 174 else if (IS_CHERRYVIEW(dev_priv)) 175 stolen_size = chv_stolen_size(dev_priv); 176 else if (INTEL_GEN(dev_priv) >= 6 && INTEL_GEN(dev_priv) < 8) 177 stolen_size = gen6_stolen_size(dev_priv); 178 else if (INTEL_GEN(dev_priv) == 8) 179 stolen_size = gen8_stolen_size(dev_priv); 180 else if (INTEL_GEN(dev_priv) >= 9 && INTEL_GEN(dev_priv) < 12) 181 stolen_size = gen9_stolen_size(dev_priv); 182 183 if (stolen_base == 0 || stolen_size == 0) 184 return; 185 186 intel_graphics_stolen_res.start = stolen_base; 187 intel_graphics_stolen_res.end = stolen_base + stolen_size - 1; 188 } 189