Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2015 Karol Herbst <nouveau@karolherbst.de>
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: Karol Herbst <nouveau@karolherbst.de>
0023  */
0024 #include "priv.h"
0025 
0026 static int
0027 gk104_pcie_version_supported(struct nvkm_pci *pci)
0028 {
0029     return (nvkm_rd32(pci->subdev.device, 0x8c1c0) & 0x4) == 0x4 ? 2 : 1;
0030 }
0031 
0032 static void
0033 gk104_pcie_set_cap_speed(struct nvkm_pci *pci, enum nvkm_pcie_speed speed)
0034 {
0035     struct nvkm_device *device = pci->subdev.device;
0036 
0037     switch (speed) {
0038     case NVKM_PCIE_SPEED_2_5:
0039         gf100_pcie_set_cap_speed(pci, false);
0040         nvkm_mask(device, 0x8c1c0, 0x30000, 0x10000);
0041         break;
0042     case NVKM_PCIE_SPEED_5_0:
0043         gf100_pcie_set_cap_speed(pci, true);
0044         nvkm_mask(device, 0x8c1c0, 0x30000, 0x20000);
0045         break;
0046     case NVKM_PCIE_SPEED_8_0:
0047         gf100_pcie_set_cap_speed(pci, true);
0048         nvkm_mask(device, 0x8c1c0, 0x30000, 0x30000);
0049         break;
0050     }
0051 }
0052 
0053 static enum nvkm_pcie_speed
0054 gk104_pcie_cap_speed(struct nvkm_pci *pci)
0055 {
0056     int speed = gf100_pcie_cap_speed(pci);
0057 
0058     if (speed == 0)
0059         return NVKM_PCIE_SPEED_2_5;
0060 
0061     if (speed >= 1) {
0062         int speed2 = nvkm_rd32(pci->subdev.device, 0x8c1c0) & 0x30000;
0063         switch (speed2) {
0064         case 0x00000:
0065         case 0x10000:
0066             return NVKM_PCIE_SPEED_2_5;
0067         case 0x20000:
0068             return NVKM_PCIE_SPEED_5_0;
0069         case 0x30000:
0070             return NVKM_PCIE_SPEED_8_0;
0071         }
0072     }
0073 
0074     return -EINVAL;
0075 }
0076 
0077 static void
0078 gk104_pcie_set_lnkctl_speed(struct nvkm_pci *pci, enum nvkm_pcie_speed speed)
0079 {
0080     u8 reg_v = 0;
0081     switch (speed) {
0082     case NVKM_PCIE_SPEED_2_5:
0083         reg_v = 1;
0084         break;
0085     case NVKM_PCIE_SPEED_5_0:
0086         reg_v = 2;
0087         break;
0088     case NVKM_PCIE_SPEED_8_0:
0089         reg_v = 3;
0090         break;
0091     }
0092     nvkm_pci_mask(pci, 0xa8, 0x3, reg_v);
0093 }
0094 
0095 static enum nvkm_pcie_speed
0096 gk104_pcie_lnkctl_speed(struct nvkm_pci *pci)
0097 {
0098     u8 reg_v = nvkm_pci_rd32(pci, 0xa8) & 0x3;
0099     switch (reg_v) {
0100     case 0:
0101     case 1:
0102         return NVKM_PCIE_SPEED_2_5;
0103     case 2:
0104         return NVKM_PCIE_SPEED_5_0;
0105     case 3:
0106         return NVKM_PCIE_SPEED_8_0;
0107     }
0108     return -1;
0109 }
0110 
0111 static enum nvkm_pcie_speed
0112 gk104_pcie_max_speed(struct nvkm_pci *pci)
0113 {
0114     u32 max_speed = nvkm_rd32(pci->subdev.device, 0x8c1c0) & 0x300000;
0115     switch (max_speed) {
0116     case 0x000000:
0117         return NVKM_PCIE_SPEED_8_0;
0118     case 0x100000:
0119         return NVKM_PCIE_SPEED_5_0;
0120     case 0x200000:
0121         return NVKM_PCIE_SPEED_2_5;
0122     }
0123     return NVKM_PCIE_SPEED_2_5;
0124 }
0125 
0126 static void
0127 gk104_pcie_set_link_speed(struct nvkm_pci *pci, enum nvkm_pcie_speed speed)
0128 {
0129     struct nvkm_device *device = pci->subdev.device;
0130     u32 mask_value;
0131 
0132     switch (speed) {
0133     case NVKM_PCIE_SPEED_8_0:
0134         mask_value = 0x00000;
0135         break;
0136     case NVKM_PCIE_SPEED_5_0:
0137         mask_value = 0x40000;
0138         break;
0139     case NVKM_PCIE_SPEED_2_5:
0140     default:
0141         mask_value = 0x80000;
0142         break;
0143     }
0144 
0145     nvkm_mask(device, 0x8c040, 0xc0000, mask_value);
0146     nvkm_mask(device, 0x8c040, 0x1, 0x1);
0147 }
0148 
0149 static int
0150 gk104_pcie_init(struct nvkm_pci * pci)
0151 {
0152     enum nvkm_pcie_speed lnkctl_speed, max_speed, cap_speed;
0153     struct nvkm_subdev *subdev = &pci->subdev;
0154 
0155     if (gf100_pcie_version(pci) < 2)
0156         return 0;
0157 
0158     lnkctl_speed = gk104_pcie_lnkctl_speed(pci);
0159     max_speed = gk104_pcie_max_speed(pci);
0160     cap_speed = gk104_pcie_cap_speed(pci);
0161 
0162     if (cap_speed != max_speed) {
0163         nvkm_trace(subdev, "adjusting cap to max speed\n");
0164         gk104_pcie_set_cap_speed(pci, max_speed);
0165         cap_speed = gk104_pcie_cap_speed(pci);
0166         if (cap_speed != max_speed)
0167             nvkm_warn(subdev, "failed to adjust cap speed\n");
0168     }
0169 
0170     if (lnkctl_speed != max_speed) {
0171         nvkm_debug(subdev, "adjusting lnkctl to max speed\n");
0172         gk104_pcie_set_lnkctl_speed(pci, max_speed);
0173         lnkctl_speed = gk104_pcie_lnkctl_speed(pci);
0174         if (lnkctl_speed != max_speed)
0175             nvkm_error(subdev, "failed to adjust lnkctl speed\n");
0176     }
0177 
0178     return 0;
0179 }
0180 
0181 static int
0182 gk104_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width)
0183 {
0184     struct nvkm_subdev *subdev = &pci->subdev;
0185     enum nvkm_pcie_speed lnk_ctl_speed = gk104_pcie_lnkctl_speed(pci);
0186     enum nvkm_pcie_speed lnk_cap_speed = gk104_pcie_cap_speed(pci);
0187 
0188     if (speed > lnk_cap_speed) {
0189         speed = lnk_cap_speed;
0190         nvkm_warn(subdev, "dropping requested speed due too low cap"
0191               " speed\n");
0192     }
0193 
0194     if (speed > lnk_ctl_speed) {
0195         speed = lnk_ctl_speed;
0196         nvkm_warn(subdev, "dropping requested speed due too low"
0197               " lnkctl speed\n");
0198     }
0199 
0200     gk104_pcie_set_link_speed(pci, speed);
0201     return 0;
0202 }
0203 
0204 
0205 static const struct nvkm_pci_func
0206 gk104_pci_func = {
0207     .init = g84_pci_init,
0208     .rd32 = nv40_pci_rd32,
0209     .wr08 = nv40_pci_wr08,
0210     .wr32 = nv40_pci_wr32,
0211     .msi_rearm = nv40_pci_msi_rearm,
0212 
0213     .pcie.init = gk104_pcie_init,
0214     .pcie.set_link = gk104_pcie_set_link,
0215 
0216     .pcie.max_speed = gk104_pcie_max_speed,
0217     .pcie.cur_speed = g84_pcie_cur_speed,
0218 
0219     .pcie.set_version = gf100_pcie_set_version,
0220     .pcie.version = gf100_pcie_version,
0221     .pcie.version_supported = gk104_pcie_version_supported,
0222 };
0223 
0224 int
0225 gk104_pci_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
0226           struct nvkm_pci **ppci)
0227 {
0228     return nvkm_pci_new_(&gk104_pci_func, device, type, inst, ppci);
0229 }