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 pr_err("No valid PCIE lane width reported\n"); 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 pr_err("Cannot find a valid PCIE lane width!\n"); 130 } 131 } 132 break; 133 } 134 } 135 break; 136 } 137 138 return new_pcie_lanes; 139 } 140 141 #endif 142