2 * Copyright 2015 Karol Herbst <nouveau@karolherbst.de>
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
22 * Authors: Karol Herbst <git@karolherbst.de>
26 static char *nvkm_pcie_speeds
[] = {
32 static enum nvkm_pcie_speed
33 nvkm_pcie_speed(enum pci_bus_speed speed
)
36 case PCIE_SPEED_2_5GT
:
37 return NVKM_PCIE_SPEED_2_5
;
38 case PCIE_SPEED_5_0GT
:
39 return NVKM_PCIE_SPEED_5_0
;
40 case PCIE_SPEED_8_0GT
:
41 return NVKM_PCIE_SPEED_8_0
;
43 /* XXX 0x16 is 8_0, assume 0x17 will be 16_0 for now */
45 return NVKM_PCIE_SPEED_8_0
;
51 nvkm_pcie_get_version(struct nvkm_pci
*pci
)
53 if (!pci
->func
->pcie
.version
)
56 return pci
->func
->pcie
.version(pci
);
60 nvkm_pcie_get_max_version(struct nvkm_pci
*pci
)
62 if (!pci
->func
->pcie
.version_supported
)
65 return pci
->func
->pcie
.version_supported(pci
);
69 nvkm_pcie_set_version(struct nvkm_pci
*pci
, int version
)
71 if (!pci
->func
->pcie
.set_version
)
74 nvkm_trace(&pci
->subdev
, "set to version %i\n", version
);
75 pci
->func
->pcie
.set_version(pci
, version
);
76 return nvkm_pcie_get_version(pci
);
80 nvkm_pcie_oneinit(struct nvkm_pci
*pci
)
82 if (pci
->func
->pcie
.max_speed
)
83 nvkm_debug(&pci
->subdev
, "pcie max speed: %s\n",
84 nvkm_pcie_speeds
[pci
->func
->pcie
.max_speed(pci
)]);
89 nvkm_pcie_init(struct nvkm_pci
*pci
)
91 struct nvkm_subdev
*subdev
= &pci
->subdev
;
94 /* raise pcie version first */
95 ret
= nvkm_pcie_get_version(pci
);
97 int max_version
= nvkm_pcie_get_max_version(pci
);
98 if (max_version
> 0 && max_version
> ret
)
99 ret
= nvkm_pcie_set_version(pci
, max_version
);
101 if (ret
< max_version
)
102 nvkm_error(subdev
, "couldn't raise version: %i\n", ret
);
105 if (pci
->func
->pcie
.init
)
106 pci
->func
->pcie
.init(pci
);
108 if (pci
->pcie
.speed
!= -1)
109 nvkm_pcie_set_link(pci
, pci
->pcie
.speed
, pci
->pcie
.width
);
115 nvkm_pcie_set_link(struct nvkm_pci
*pci
, enum nvkm_pcie_speed speed
, u8 width
)
117 struct nvkm_subdev
*subdev
= &pci
->subdev
;
118 enum nvkm_pcie_speed cur_speed
, max_speed
;
119 struct pci_bus
*pbus
;
122 if (!pci
|| !pci_is_pcie(pci
->pdev
))
124 pbus
= pci
->pdev
->bus
;
126 if (!pci
->func
->pcie
.set_link
)
129 nvkm_trace(subdev
, "requested %s\n", nvkm_pcie_speeds
[speed
]);
131 if (pci
->func
->pcie
.version(pci
) < 2) {
132 nvkm_error(subdev
, "setting link failed due to low version\n");
136 cur_speed
= pci
->func
->pcie
.cur_speed(pci
);
137 max_speed
= min(nvkm_pcie_speed(pbus
->max_bus_speed
),
138 pci
->func
->pcie
.max_speed(pci
));
140 nvkm_trace(subdev
, "current speed: %s\n", nvkm_pcie_speeds
[cur_speed
]);
142 if (speed
> max_speed
) {
143 nvkm_debug(subdev
, "%s not supported by bus or card, dropping"
144 "requested speed to %s", nvkm_pcie_speeds
[speed
],
145 nvkm_pcie_speeds
[max_speed
]);
149 pci
->pcie
.speed
= speed
;
150 pci
->pcie
.width
= width
;
152 if (speed
== cur_speed
) {
153 nvkm_debug(subdev
, "requested matches current speed\n");
157 nvkm_debug(subdev
, "set link to %s x%i\n",
158 nvkm_pcie_speeds
[speed
], width
);
160 ret
= pci
->func
->pcie
.set_link(pci
, speed
, width
);
162 nvkm_error(subdev
, "setting link failed: %i\n", ret
);