xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/amd/include/amd_pcie_helpers.h (revision 41ec02673d281bbb3d38e6c78504ce6e30c228c1)
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