1 /* $NetBSD: amd_pcie_helpers.h,v 1.2 2021/12/18 23:45:08 riastradh Exp $ */
2
3 /*
4 * Copyright 2015 Advanced Micro Devices, Inc.
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
25 #ifndef __AMD_PCIE_HELPERS_H__
26 #define __AMD_PCIE_HELPERS_H__
27
28 #include "amd_pcie.h"
29
is_pcie_gen3_supported(uint32_t pcie_link_speed_cap)30 static inline bool is_pcie_gen3_supported(uint32_t pcie_link_speed_cap)
31 {
32 if (pcie_link_speed_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
33 return true;
34
35 return false;
36 }
37
is_pcie_gen2_supported(uint32_t pcie_link_speed_cap)38 static inline bool is_pcie_gen2_supported(uint32_t pcie_link_speed_cap)
39 {
40 if (pcie_link_speed_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)
41 return true;
42
43 return false;
44 }
45
46 /* Get the new PCIE speed given the ASIC PCIE Cap and the NewState's requested PCIE speed*/
get_pcie_gen_support(uint32_t pcie_link_speed_cap,uint16_t ns_pcie_gen)47 static inline uint16_t get_pcie_gen_support(uint32_t pcie_link_speed_cap,
48 uint16_t ns_pcie_gen)
49 {
50 uint32_t asic_pcie_link_speed_cap = (pcie_link_speed_cap &
51 CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_MASK);
52 uint32_t sys_pcie_link_speed_cap = (pcie_link_speed_cap &
53 CAIL_PCIE_LINK_SPEED_SUPPORT_MASK);
54
55 switch (asic_pcie_link_speed_cap) {
56 case CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1:
57 return PP_PCIEGen1;
58
59 case CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2:
60 return PP_PCIEGen2;
61
62 case CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3:
63 return PP_PCIEGen3;
64
65 default:
66 if (is_pcie_gen3_supported(sys_pcie_link_speed_cap) &&
67 (ns_pcie_gen == PP_PCIEGen3)) {
68 return PP_PCIEGen3;
69 } else if (is_pcie_gen2_supported(sys_pcie_link_speed_cap) &&
70 ((ns_pcie_gen == PP_PCIEGen3) || (ns_pcie_gen == PP_PCIEGen2))) {
71 return PP_PCIEGen2;
72 }
73 }
74
75 return PP_PCIEGen1;
76 }
77
get_pcie_lane_support(uint32_t pcie_lane_width_cap,uint16_t ns_pcie_lanes)78 static inline uint16_t get_pcie_lane_support(uint32_t pcie_lane_width_cap,
79 uint16_t ns_pcie_lanes)
80 {
81 int i, j;
82 uint16_t new_pcie_lanes = ns_pcie_lanes;
83 uint16_t pcie_lanes[7] = {1, 2, 4, 8, 12, 16, 32};
84
85 switch (pcie_lane_width_cap) {
86 case 0:
87 pr_err("No valid PCIE lane width reported\n");
88 break;
89 case CAIL_PCIE_LINK_WIDTH_SUPPORT_X1:
90 new_pcie_lanes = 1;
91 break;
92 case CAIL_PCIE_LINK_WIDTH_SUPPORT_X2:
93 new_pcie_lanes = 2;
94 break;
95 case CAIL_PCIE_LINK_WIDTH_SUPPORT_X4:
96 new_pcie_lanes = 4;
97 break;
98 case CAIL_PCIE_LINK_WIDTH_SUPPORT_X8:
99 new_pcie_lanes = 8;
100 break;
101 case CAIL_PCIE_LINK_WIDTH_SUPPORT_X12:
102 new_pcie_lanes = 12;
103 break;
104 case CAIL_PCIE_LINK_WIDTH_SUPPORT_X16:
105 new_pcie_lanes = 16;
106 break;
107 case CAIL_PCIE_LINK_WIDTH_SUPPORT_X32:
108 new_pcie_lanes = 32;
109 break;
110 default:
111 for (i = 0; i < 7; i++) {
112 if (ns_pcie_lanes == pcie_lanes[i]) {
113 if (pcie_lane_width_cap & (0x10000 << i)) {
114 break;
115 } else {
116 for (j = i - 1; j >= 0; j--) {
117 if (pcie_lane_width_cap & (0x10000 << j)) {
118 new_pcie_lanes = pcie_lanes[j];
119 break;
120 }
121 }
122
123 if (j < 0) {
124 for (j = i + 1; j < 7; j++) {
125 if (pcie_lane_width_cap & (0x10000 << j)) {
126 new_pcie_lanes = pcie_lanes[j];
127 break;
128 }
129 }
130 if (j > 7)
131 pr_err("Cannot find a valid PCIE lane width!\n");
132 }
133 }
134 break;
135 }
136 }
137 break;
138 }
139
140 return new_pcie_lanes;
141 }
142
143 #endif
144