xref: /openbmc/linux/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gk104.c (revision d0034a7a4ac7fae708146ac0059b9c47a1543f0d)
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