Line data Source code
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 0 : 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 0 : 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 0 : static inline uint16_t get_pcie_gen_support(uint32_t pcie_link_speed_cap, 46 : uint16_t ns_pcie_gen) 47 : { 48 0 : uint32_t asic_pcie_link_speed_cap = (pcie_link_speed_cap & 49 : CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_MASK); 50 0 : uint32_t sys_pcie_link_speed_cap = (pcie_link_speed_cap & 51 : CAIL_PCIE_LINK_SPEED_SUPPORT_MASK); 52 : 53 0 : 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 0 : return PP_PCIEGen2; 59 : 60 : case CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3: 61 0 : return PP_PCIEGen3; 62 : 63 : default: 64 0 : if (is_pcie_gen3_supported(sys_pcie_link_speed_cap) && 65 : (ns_pcie_gen == PP_PCIEGen3)) { 66 : return PP_PCIEGen3; 67 0 : } else if (is_pcie_gen2_supported(sys_pcie_link_speed_cap) && 68 0 : ((ns_pcie_gen == PP_PCIEGen3) || (ns_pcie_gen == PP_PCIEGen2))) { 69 : return PP_PCIEGen2; 70 : } 71 : } 72 : 73 0 : return PP_PCIEGen1; 74 : } 75 : 76 0 : 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 0 : uint16_t new_pcie_lanes = ns_pcie_lanes; 81 0 : uint16_t pcie_lanes[7] = {1, 2, 4, 8, 12, 16, 32}; 82 : 83 0 : switch (pcie_lane_width_cap) { 84 : case 0: 85 0 : pr_err("No valid PCIE lane width reported\n"); 86 0 : 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 0 : new_pcie_lanes = 2; 92 0 : break; 93 : case CAIL_PCIE_LINK_WIDTH_SUPPORT_X4: 94 0 : new_pcie_lanes = 4; 95 0 : break; 96 : case CAIL_PCIE_LINK_WIDTH_SUPPORT_X8: 97 0 : new_pcie_lanes = 8; 98 0 : break; 99 : case CAIL_PCIE_LINK_WIDTH_SUPPORT_X12: 100 0 : new_pcie_lanes = 12; 101 0 : break; 102 : case CAIL_PCIE_LINK_WIDTH_SUPPORT_X16: 103 0 : new_pcie_lanes = 16; 104 0 : break; 105 : case CAIL_PCIE_LINK_WIDTH_SUPPORT_X32: 106 0 : new_pcie_lanes = 32; 107 0 : break; 108 : default: 109 0 : for (i = 0; i < 7; i++) { 110 0 : if (ns_pcie_lanes == pcie_lanes[i]) { 111 0 : if (pcie_lane_width_cap & (0x10000 << i)) { 112 : break; 113 : } else { 114 0 : for (j = i - 1; j >= 0; j--) { 115 0 : if (pcie_lane_width_cap & (0x10000 << j)) { 116 0 : new_pcie_lanes = pcie_lanes[j]; 117 0 : break; 118 : } 119 : } 120 : 121 0 : if (j < 0) { 122 0 : for (j = i + 1; j < 7; j++) { 123 0 : if (pcie_lane_width_cap & (0x10000 << j)) { 124 0 : new_pcie_lanes = pcie_lanes[j]; 125 0 : break; 126 : } 127 : } 128 0 : if (j > 7) 129 0 : pr_err("Cannot find a valid PCIE lane width!\n"); 130 : } 131 : } 132 : break; 133 : } 134 : } 135 : break; 136 : } 137 : 138 0 : return new_pcie_lanes; 139 : } 140 : 141 : #endif