128c80605SKarol Herbst /*
228c80605SKarol Herbst * Copyright 2015 Karol Herbst <nouveau@karolherbst.de>
328c80605SKarol Herbst *
428c80605SKarol Herbst * Permission is hereby granted, free of charge, to any person obtaining a
528c80605SKarol Herbst * copy of this software and associated documentation files (the "Software"),
628c80605SKarol Herbst * to deal in the Software without restriction, including without limitation
728c80605SKarol Herbst * the rights to use, copy, modify, merge, publish, distribute, sublicense,
828c80605SKarol Herbst * and/or sell copies of the Software, and to permit persons to whom the
928c80605SKarol Herbst * Software is furnished to do so, subject to the following conditions:
1028c80605SKarol Herbst *
1128c80605SKarol Herbst * The above copyright notice and this permission notice shall be included in
1228c80605SKarol Herbst * all copies or substantial portions of the Software.
1328c80605SKarol Herbst *
1428c80605SKarol Herbst * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1528c80605SKarol Herbst * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1628c80605SKarol Herbst * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1728c80605SKarol Herbst * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
1828c80605SKarol Herbst * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1928c80605SKarol Herbst * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2028c80605SKarol Herbst * OTHER DEALINGS IN THE SOFTWARE.
2128c80605SKarol Herbst *
2228c80605SKarol Herbst * Authors: Karol Herbst <nouveau@karolherbst.de>
2328c80605SKarol Herbst */
2428c80605SKarol Herbst #include "priv.h"
2528c80605SKarol Herbst
263aba825fSKarol Herbst static int
gk104_pcie_version_supported(struct nvkm_pci * pci)273aba825fSKarol Herbst gk104_pcie_version_supported(struct nvkm_pci *pci)
283aba825fSKarol Herbst {
293aba825fSKarol Herbst return (nvkm_rd32(pci->subdev.device, 0x8c1c0) & 0x4) == 0x4 ? 2 : 1;
303aba825fSKarol Herbst }
313aba825fSKarol Herbst
323aba825fSKarol Herbst static void
gk104_pcie_set_cap_speed(struct nvkm_pci * pci,enum nvkm_pcie_speed speed)333aba825fSKarol Herbst gk104_pcie_set_cap_speed(struct nvkm_pci *pci, enum nvkm_pcie_speed speed)
343aba825fSKarol Herbst {
353aba825fSKarol Herbst struct nvkm_device *device = pci->subdev.device;
363aba825fSKarol Herbst
373aba825fSKarol Herbst switch (speed) {
383aba825fSKarol Herbst case NVKM_PCIE_SPEED_2_5:
393aba825fSKarol Herbst gf100_pcie_set_cap_speed(pci, false);
403aba825fSKarol Herbst nvkm_mask(device, 0x8c1c0, 0x30000, 0x10000);
413aba825fSKarol Herbst break;
423aba825fSKarol Herbst case NVKM_PCIE_SPEED_5_0:
433aba825fSKarol Herbst gf100_pcie_set_cap_speed(pci, true);
443aba825fSKarol Herbst nvkm_mask(device, 0x8c1c0, 0x30000, 0x20000);
453aba825fSKarol Herbst break;
463aba825fSKarol Herbst case NVKM_PCIE_SPEED_8_0:
473aba825fSKarol Herbst gf100_pcie_set_cap_speed(pci, true);
483aba825fSKarol Herbst nvkm_mask(device, 0x8c1c0, 0x30000, 0x30000);
493aba825fSKarol Herbst break;
503aba825fSKarol Herbst }
513aba825fSKarol Herbst }
523aba825fSKarol Herbst
533aba825fSKarol Herbst static enum nvkm_pcie_speed
gk104_pcie_cap_speed(struct nvkm_pci * pci)543aba825fSKarol Herbst gk104_pcie_cap_speed(struct nvkm_pci *pci)
553aba825fSKarol Herbst {
563aba825fSKarol Herbst int speed = gf100_pcie_cap_speed(pci);
573aba825fSKarol Herbst
583aba825fSKarol Herbst if (speed == 0)
593aba825fSKarol Herbst return NVKM_PCIE_SPEED_2_5;
603aba825fSKarol Herbst
613aba825fSKarol Herbst if (speed >= 1) {
623aba825fSKarol Herbst int speed2 = nvkm_rd32(pci->subdev.device, 0x8c1c0) & 0x30000;
633aba825fSKarol Herbst switch (speed2) {
643aba825fSKarol Herbst case 0x00000:
653aba825fSKarol Herbst case 0x10000:
663aba825fSKarol Herbst return NVKM_PCIE_SPEED_2_5;
673aba825fSKarol Herbst case 0x20000:
683aba825fSKarol Herbst return NVKM_PCIE_SPEED_5_0;
693aba825fSKarol Herbst case 0x30000:
703aba825fSKarol Herbst return NVKM_PCIE_SPEED_8_0;
713aba825fSKarol Herbst }
723aba825fSKarol Herbst }
733aba825fSKarol Herbst
743aba825fSKarol Herbst return -EINVAL;
753aba825fSKarol Herbst }
763aba825fSKarol Herbst
773aba825fSKarol Herbst static void
gk104_pcie_set_lnkctl_speed(struct nvkm_pci * pci,enum nvkm_pcie_speed speed)783aba825fSKarol Herbst gk104_pcie_set_lnkctl_speed(struct nvkm_pci *pci, enum nvkm_pcie_speed speed)
793aba825fSKarol Herbst {
803aba825fSKarol Herbst u8 reg_v = 0;
813aba825fSKarol Herbst switch (speed) {
823aba825fSKarol Herbst case NVKM_PCIE_SPEED_2_5:
833aba825fSKarol Herbst reg_v = 1;
843aba825fSKarol Herbst break;
853aba825fSKarol Herbst case NVKM_PCIE_SPEED_5_0:
863aba825fSKarol Herbst reg_v = 2;
873aba825fSKarol Herbst break;
883aba825fSKarol Herbst case NVKM_PCIE_SPEED_8_0:
893aba825fSKarol Herbst reg_v = 3;
903aba825fSKarol Herbst break;
913aba825fSKarol Herbst }
923aba825fSKarol Herbst nvkm_pci_mask(pci, 0xa8, 0x3, reg_v);
933aba825fSKarol Herbst }
943aba825fSKarol Herbst
953aba825fSKarol Herbst static enum nvkm_pcie_speed
gk104_pcie_lnkctl_speed(struct nvkm_pci * pci)963aba825fSKarol Herbst gk104_pcie_lnkctl_speed(struct nvkm_pci *pci)
973aba825fSKarol Herbst {
983aba825fSKarol Herbst u8 reg_v = nvkm_pci_rd32(pci, 0xa8) & 0x3;
993aba825fSKarol Herbst switch (reg_v) {
1003aba825fSKarol Herbst case 0:
1013aba825fSKarol Herbst case 1:
1023aba825fSKarol Herbst return NVKM_PCIE_SPEED_2_5;
1033aba825fSKarol Herbst case 2:
1043aba825fSKarol Herbst return NVKM_PCIE_SPEED_5_0;
1053aba825fSKarol Herbst case 3:
1063aba825fSKarol Herbst return NVKM_PCIE_SPEED_8_0;
1073aba825fSKarol Herbst }
1083aba825fSKarol Herbst return -1;
1093aba825fSKarol Herbst }
1103aba825fSKarol Herbst
1113aba825fSKarol Herbst static enum nvkm_pcie_speed
gk104_pcie_max_speed(struct nvkm_pci * pci)1123aba825fSKarol Herbst gk104_pcie_max_speed(struct nvkm_pci *pci)
1133aba825fSKarol Herbst {
1143aba825fSKarol Herbst u32 max_speed = nvkm_rd32(pci->subdev.device, 0x8c1c0) & 0x300000;
1153aba825fSKarol Herbst switch (max_speed) {
1163aba825fSKarol Herbst case 0x000000:
1173aba825fSKarol Herbst return NVKM_PCIE_SPEED_8_0;
1183aba825fSKarol Herbst case 0x100000:
1193aba825fSKarol Herbst return NVKM_PCIE_SPEED_5_0;
1203aba825fSKarol Herbst case 0x200000:
1213aba825fSKarol Herbst return NVKM_PCIE_SPEED_2_5;
1223aba825fSKarol Herbst }
1233aba825fSKarol Herbst return NVKM_PCIE_SPEED_2_5;
1243aba825fSKarol Herbst }
1253aba825fSKarol Herbst
1263aba825fSKarol Herbst static void
gk104_pcie_set_link_speed(struct nvkm_pci * pci,enum nvkm_pcie_speed speed)1273aba825fSKarol Herbst gk104_pcie_set_link_speed(struct nvkm_pci *pci, enum nvkm_pcie_speed speed)
1283aba825fSKarol Herbst {
1293aba825fSKarol Herbst struct nvkm_device *device = pci->subdev.device;
1303aba825fSKarol Herbst u32 mask_value;
1313aba825fSKarol Herbst
1323aba825fSKarol Herbst switch (speed) {
1333aba825fSKarol Herbst case NVKM_PCIE_SPEED_8_0:
1343aba825fSKarol Herbst mask_value = 0x00000;
1353aba825fSKarol Herbst break;
1363aba825fSKarol Herbst case NVKM_PCIE_SPEED_5_0:
1373aba825fSKarol Herbst mask_value = 0x40000;
1383aba825fSKarol Herbst break;
1393aba825fSKarol Herbst case NVKM_PCIE_SPEED_2_5:
1403aba825fSKarol Herbst default:
1413aba825fSKarol Herbst mask_value = 0x80000;
1423aba825fSKarol Herbst break;
1433aba825fSKarol Herbst }
1443aba825fSKarol Herbst
1453aba825fSKarol Herbst nvkm_mask(device, 0x8c040, 0xc0000, mask_value);
1463aba825fSKarol Herbst nvkm_mask(device, 0x8c040, 0x1, 0x1);
1473aba825fSKarol Herbst }
1483aba825fSKarol Herbst
1493aba825fSKarol Herbst static int
gk104_pcie_init(struct nvkm_pci * pci)1503aba825fSKarol Herbst gk104_pcie_init(struct nvkm_pci * pci)
1513aba825fSKarol Herbst {
1523aba825fSKarol Herbst enum nvkm_pcie_speed lnkctl_speed, max_speed, cap_speed;
1533aba825fSKarol Herbst struct nvkm_subdev *subdev = &pci->subdev;
1543aba825fSKarol Herbst
1553aba825fSKarol Herbst if (gf100_pcie_version(pci) < 2)
1563aba825fSKarol Herbst return 0;
1573aba825fSKarol Herbst
1583aba825fSKarol Herbst lnkctl_speed = gk104_pcie_lnkctl_speed(pci);
1593aba825fSKarol Herbst max_speed = gk104_pcie_max_speed(pci);
1603aba825fSKarol Herbst cap_speed = gk104_pcie_cap_speed(pci);
1613aba825fSKarol Herbst
1623aba825fSKarol Herbst if (cap_speed != max_speed) {
1633aba825fSKarol Herbst nvkm_trace(subdev, "adjusting cap to max speed\n");
1643aba825fSKarol Herbst gk104_pcie_set_cap_speed(pci, max_speed);
1653aba825fSKarol Herbst cap_speed = gk104_pcie_cap_speed(pci);
1663aba825fSKarol Herbst if (cap_speed != max_speed)
1673aba825fSKarol Herbst nvkm_warn(subdev, "failed to adjust cap speed\n");
1683aba825fSKarol Herbst }
1693aba825fSKarol Herbst
1703aba825fSKarol Herbst if (lnkctl_speed != max_speed) {
1713aba825fSKarol Herbst nvkm_debug(subdev, "adjusting lnkctl to max speed\n");
1723aba825fSKarol Herbst gk104_pcie_set_lnkctl_speed(pci, max_speed);
1733aba825fSKarol Herbst lnkctl_speed = gk104_pcie_lnkctl_speed(pci);
1743aba825fSKarol Herbst if (lnkctl_speed != max_speed)
1753aba825fSKarol Herbst nvkm_error(subdev, "failed to adjust lnkctl speed\n");
1763aba825fSKarol Herbst }
1773aba825fSKarol Herbst
1783aba825fSKarol Herbst return 0;
1793aba825fSKarol Herbst }
1803aba825fSKarol Herbst
1813aba825fSKarol Herbst static int
gk104_pcie_set_link(struct nvkm_pci * pci,enum nvkm_pcie_speed speed,u8 width)1823aba825fSKarol Herbst gk104_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width)
1833aba825fSKarol Herbst {
1843aba825fSKarol Herbst struct nvkm_subdev *subdev = &pci->subdev;
1853aba825fSKarol Herbst enum nvkm_pcie_speed lnk_ctl_speed = gk104_pcie_lnkctl_speed(pci);
1863aba825fSKarol Herbst enum nvkm_pcie_speed lnk_cap_speed = gk104_pcie_cap_speed(pci);
1873aba825fSKarol Herbst
1883aba825fSKarol Herbst if (speed > lnk_cap_speed) {
1893aba825fSKarol Herbst speed = lnk_cap_speed;
1903aba825fSKarol Herbst nvkm_warn(subdev, "dropping requested speed due too low cap"
1913aba825fSKarol Herbst " speed\n");
1923aba825fSKarol Herbst }
1933aba825fSKarol Herbst
1943aba825fSKarol Herbst if (speed > lnk_ctl_speed) {
1953aba825fSKarol Herbst speed = lnk_ctl_speed;
1963aba825fSKarol Herbst nvkm_warn(subdev, "dropping requested speed due too low"
1973aba825fSKarol Herbst " lnkctl speed\n");
1983aba825fSKarol Herbst }
1993aba825fSKarol Herbst
2003aba825fSKarol Herbst gk104_pcie_set_link_speed(pci, speed);
2013aba825fSKarol Herbst return 0;
2023aba825fSKarol Herbst }
2033aba825fSKarol Herbst
2043aba825fSKarol Herbst
20528c80605SKarol Herbst static const struct nvkm_pci_func
20628c80605SKarol Herbst gk104_pci_func = {
20728c80605SKarol Herbst .init = g84_pci_init,
20828c80605SKarol Herbst .rd32 = nv40_pci_rd32,
20928c80605SKarol Herbst .wr08 = nv40_pci_wr08,
21028c80605SKarol Herbst .wr32 = nv40_pci_wr32,
21128c80605SKarol Herbst .msi_rearm = nv40_pci_msi_rearm,
2123aba825fSKarol Herbst
2133aba825fSKarol Herbst .pcie.init = gk104_pcie_init,
2143aba825fSKarol Herbst .pcie.set_link = gk104_pcie_set_link,
2153aba825fSKarol Herbst
2163aba825fSKarol Herbst .pcie.max_speed = gk104_pcie_max_speed,
2173aba825fSKarol Herbst .pcie.cur_speed = g84_pcie_cur_speed,
2183aba825fSKarol Herbst
2193aba825fSKarol Herbst .pcie.set_version = gf100_pcie_set_version,
2203aba825fSKarol Herbst .pcie.version = gf100_pcie_version,
2213aba825fSKarol Herbst .pcie.version_supported = gk104_pcie_version_supported,
22228c80605SKarol Herbst };
22328c80605SKarol Herbst
22428c80605SKarol Herbst int
gk104_pci_new(struct nvkm_device * device,enum nvkm_subdev_type type,int inst,struct nvkm_pci ** ppci)225*9b70cd54SBen Skeggs gk104_pci_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
226*9b70cd54SBen Skeggs struct nvkm_pci **ppci)
22728c80605SKarol Herbst {
228*9b70cd54SBen Skeggs return nvkm_pci_new_(&gk104_pci_func, device, type, inst, ppci);
22928c80605SKarol Herbst }
230