1 /* $NetBSD: nouveau_nvkm_subdev_pci_gk104.c,v 1.2 2021/12/18 23:45:41 riastradh Exp $ */ 2 3 /* 4 * Copyright 2015 Karol Herbst <nouveau (at) karolherbst.de> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: Karol Herbst <nouveau (at) karolherbst.de> 25 */ 26 #include <sys/cdefs.h> 27 __KERNEL_RCSID(0, "$NetBSD: nouveau_nvkm_subdev_pci_gk104.c,v 1.2 2021/12/18 23:45:41 riastradh Exp $"); 28 29 #include "priv.h" 30 31 static int 32 gk104_pcie_version_supported(struct nvkm_pci *pci) 33 { 34 return (nvkm_rd32(pci->subdev.device, 0x8c1c0) & 0x4) == 0x4 ? 2 : 1; 35 } 36 37 static void 38 gk104_pcie_set_cap_speed(struct nvkm_pci *pci, enum nvkm_pcie_speed speed) 39 { 40 struct nvkm_device *device = pci->subdev.device; 41 42 switch (speed) { 43 case NVKM_PCIE_SPEED_2_5: 44 gf100_pcie_set_cap_speed(pci, false); 45 nvkm_mask(device, 0x8c1c0, 0x30000, 0x10000); 46 break; 47 case NVKM_PCIE_SPEED_5_0: 48 gf100_pcie_set_cap_speed(pci, true); 49 nvkm_mask(device, 0x8c1c0, 0x30000, 0x20000); 50 break; 51 case NVKM_PCIE_SPEED_8_0: 52 gf100_pcie_set_cap_speed(pci, true); 53 nvkm_mask(device, 0x8c1c0, 0x30000, 0x30000); 54 break; 55 } 56 } 57 58 static enum nvkm_pcie_speed 59 gk104_pcie_cap_speed(struct nvkm_pci *pci) 60 { 61 int speed = gf100_pcie_cap_speed(pci); 62 63 if (speed == 0) 64 return NVKM_PCIE_SPEED_2_5; 65 66 if (speed >= 1) { 67 int speed2 = nvkm_rd32(pci->subdev.device, 0x8c1c0) & 0x30000; 68 switch (speed2) { 69 case 0x00000: 70 case 0x10000: 71 return NVKM_PCIE_SPEED_2_5; 72 case 0x20000: 73 return NVKM_PCIE_SPEED_5_0; 74 case 0x30000: 75 return NVKM_PCIE_SPEED_8_0; 76 } 77 } 78 79 return -EINVAL; 80 } 81 82 static void 83 gk104_pcie_set_lnkctl_speed(struct nvkm_pci *pci, enum nvkm_pcie_speed speed) 84 { 85 u8 reg_v = 0; 86 switch (speed) { 87 case NVKM_PCIE_SPEED_2_5: 88 reg_v = 1; 89 break; 90 case NVKM_PCIE_SPEED_5_0: 91 reg_v = 2; 92 break; 93 case NVKM_PCIE_SPEED_8_0: 94 reg_v = 3; 95 break; 96 } 97 nvkm_pci_mask(pci, 0xa8, 0x3, reg_v); 98 } 99 100 static enum nvkm_pcie_speed 101 gk104_pcie_lnkctl_speed(struct nvkm_pci *pci) 102 { 103 u8 reg_v = nvkm_pci_rd32(pci, 0xa8) & 0x3; 104 switch (reg_v) { 105 case 0: 106 case 1: 107 return NVKM_PCIE_SPEED_2_5; 108 case 2: 109 return NVKM_PCIE_SPEED_5_0; 110 case 3: 111 return NVKM_PCIE_SPEED_8_0; 112 } 113 return -1; 114 } 115 116 static enum nvkm_pcie_speed 117 gk104_pcie_max_speed(struct nvkm_pci *pci) 118 { 119 u32 max_speed = nvkm_rd32(pci->subdev.device, 0x8c1c0) & 0x300000; 120 switch (max_speed) { 121 case 0x000000: 122 return NVKM_PCIE_SPEED_8_0; 123 case 0x100000: 124 return NVKM_PCIE_SPEED_5_0; 125 case 0x200000: 126 return NVKM_PCIE_SPEED_2_5; 127 } 128 return NVKM_PCIE_SPEED_2_5; 129 } 130 131 static void 132 gk104_pcie_set_link_speed(struct nvkm_pci *pci, enum nvkm_pcie_speed speed) 133 { 134 struct nvkm_device *device = pci->subdev.device; 135 u32 mask_value; 136 137 switch (speed) { 138 case NVKM_PCIE_SPEED_8_0: 139 mask_value = 0x00000; 140 break; 141 case NVKM_PCIE_SPEED_5_0: 142 mask_value = 0x40000; 143 break; 144 case NVKM_PCIE_SPEED_2_5: 145 default: 146 mask_value = 0x80000; 147 break; 148 } 149 150 nvkm_mask(device, 0x8c040, 0xc0000, mask_value); 151 nvkm_mask(device, 0x8c040, 0x1, 0x1); 152 } 153 154 static int 155 gk104_pcie_init(struct nvkm_pci * pci) 156 { 157 enum nvkm_pcie_speed lnkctl_speed, max_speed, cap_speed; 158 struct nvkm_subdev *subdev = &pci->subdev; 159 160 if (gf100_pcie_version(pci) < 2) 161 return 0; 162 163 lnkctl_speed = gk104_pcie_lnkctl_speed(pci); 164 max_speed = gk104_pcie_max_speed(pci); 165 cap_speed = gk104_pcie_cap_speed(pci); 166 167 if (cap_speed != max_speed) { 168 nvkm_trace(subdev, "adjusting cap to max speed\n"); 169 gk104_pcie_set_cap_speed(pci, max_speed); 170 cap_speed = gk104_pcie_cap_speed(pci); 171 if (cap_speed != max_speed) 172 nvkm_warn(subdev, "failed to adjust cap speed\n"); 173 } 174 175 if (lnkctl_speed != max_speed) { 176 nvkm_debug(subdev, "adjusting lnkctl to max speed\n"); 177 gk104_pcie_set_lnkctl_speed(pci, max_speed); 178 lnkctl_speed = gk104_pcie_lnkctl_speed(pci); 179 if (lnkctl_speed != max_speed) 180 nvkm_error(subdev, "failed to adjust lnkctl speed\n"); 181 } 182 183 return 0; 184 } 185 186 static int 187 gk104_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width) 188 { 189 struct nvkm_subdev *subdev = &pci->subdev; 190 enum nvkm_pcie_speed lnk_ctl_speed = gk104_pcie_lnkctl_speed(pci); 191 enum nvkm_pcie_speed lnk_cap_speed = gk104_pcie_cap_speed(pci); 192 193 if (speed > lnk_cap_speed) { 194 speed = lnk_cap_speed; 195 nvkm_warn(subdev, "dropping requested speed due too low cap" 196 " speed\n"); 197 } 198 199 if (speed > lnk_ctl_speed) { 200 speed = lnk_ctl_speed; 201 nvkm_warn(subdev, "dropping requested speed due too low" 202 " lnkctl speed\n"); 203 } 204 205 gk104_pcie_set_link_speed(pci, speed); 206 return 0; 207 } 208 209 210 static const struct nvkm_pci_func 211 gk104_pci_func = { 212 .init = g84_pci_init, 213 .rd32 = nv40_pci_rd32, 214 .wr08 = nv40_pci_wr08, 215 .wr32 = nv40_pci_wr32, 216 .msi_rearm = nv40_pci_msi_rearm, 217 218 .pcie.init = gk104_pcie_init, 219 .pcie.set_link = gk104_pcie_set_link, 220 221 .pcie.max_speed = gk104_pcie_max_speed, 222 .pcie.cur_speed = g84_pcie_cur_speed, 223 224 .pcie.set_version = gf100_pcie_set_version, 225 .pcie.version = gf100_pcie_version, 226 .pcie.version_supported = gk104_pcie_version_supported, 227 }; 228 229 int 230 gk104_pci_new(struct nvkm_device *device, int index, struct nvkm_pci **ppci) 231 { 232 return nvkm_pci_new_(&gk104_pci_func, device, index, ppci); 233 } 234