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