1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 2018-2020 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 * SPDX-License-Identifier: MIT 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24 25 #include "export_nvswitch.h" 26 #include "common_nvswitch.h" 27 #include "error_nvswitch.h" 28 #include "lr10/lr10.h" 29 #include "lr10/therm_lr10.h" 30 #include "soe/soeiftherm.h" 31 #include "rmflcncmdif_nvswitch.h" 32 #include "soe/soe_nvswitch.h" 33 34 #include "nvswitch/lr10/dev_therm.h" 35 #include "nvswitch/lr10/dev_nvlsaw_ip.h" 36 37 // 38 // Thermal functions 39 // 40 41 // 42 // Initialize thermal offsets for External Tdiode. 43 // 44 45 NvlStatus 46 nvswitch_init_thermal_lr10 47 ( 48 nvswitch_device *device 49 ) 50 { 51 lr10_device *chip_device = NVSWITCH_GET_CHIP_DEVICE_LR10(device); 52 53 // Mark everything invalid 54 chip_device->tdiode.method = NVSWITCH_THERM_METHOD_UNKNOWN; 55 56 return NVL_SUCCESS; 57 } 58 59 static void 60 _nvswitch_read_max_tsense_temperature 61 ( 62 nvswitch_device *device, 63 NVSWITCH_CTRL_GET_TEMPERATURE_PARAMS *info, 64 NvU32 channel 65 ) 66 { 67 NvU32 offset; 68 NvU32 temperature; 69 70 temperature = nvswitch_reg_read_32(device, NV_THERM_TSENSE_MAXIMUM_TEMPERATURE); 71 temperature = DRF_VAL(_THERM_TSENSE, _MAXIMUM_TEMPERATURE, _MAXIMUM_TEMPERATURE, temperature); 72 73 if (channel == NVSWITCH_THERM_CHANNEL_LR10_TSENSE_MAX) 74 { 75 offset = nvswitch_reg_read_32(device, NV_THERM_TSENSE_U2_A_0_BJT_0_TEMPERATURE_MODIFICATIONS); 76 offset = DRF_VAL(_THERM_TSENSE, _U2_A_0_BJT_0_TEMPERATURE_MODIFICATIONS, _TEMPERATURE_OFFSET, offset); 77 78 // Temperature of the sensor reported equals calculation of the max temperature reported 79 // from the TSENSE HUB plus the temperature offset programmed by SW. This offset needs to 80 // be substracted to get the actual temperature of the sensor. 81 temperature -= offset; 82 } 83 84 info->temperature[channel] = NV_TSENSE_FXP_9_5_TO_24_8(temperature); 85 info->status[channel] = NVL_SUCCESS; 86 } 87 88 static void 89 _nvswitch_read_external_tdiode_temperature 90 ( 91 nvswitch_device *device, 92 NVSWITCH_CTRL_GET_TEMPERATURE_PARAMS *info, 93 NvU32 channel 94 ) 95 { 96 } 97 98 NvlStatus 99 nvswitch_ctrl_therm_read_temperature_lr10 100 ( 101 nvswitch_device *device, 102 NVSWITCH_CTRL_GET_TEMPERATURE_PARAMS *info 103 ) 104 { 105 NvU32 channel; 106 107 if (!info->channelMask) 108 { 109 NVSWITCH_PRINT(device, ERROR, 110 "%s: No channel given in the input.\n", 111 __FUNCTION__); 112 113 return -NVL_BAD_ARGS; 114 } 115 116 nvswitch_os_memset(info->temperature, 0x0, sizeof(info->temperature)); 117 118 channel = NVSWITCH_THERM_CHANNEL_LR10_TSENSE_MAX; 119 if (info->channelMask & NVBIT(channel)) 120 { 121 _nvswitch_read_max_tsense_temperature(device, info, channel); 122 info->channelMask &= ~NVBIT(channel); 123 } 124 125 channel = NVSWITCH_THERM_CHANNEL_LR10_TSENSE_OFFSET_MAX; 126 if (info->channelMask & NVBIT(channel)) 127 { 128 _nvswitch_read_max_tsense_temperature(device, info, channel); 129 info->channelMask &= ~NVBIT(channel); 130 } 131 132 channel = NVSWITCH_THERM_CHANNEL_LR10_TDIODE; 133 if (info->channelMask & NVBIT(channel)) 134 { 135 _nvswitch_read_external_tdiode_temperature(device, info, channel); 136 info->channelMask &= ~NVBIT(channel); 137 } 138 139 channel = NVSWITCH_THERM_CHANNEL_LR10_TDIODE_OFFSET; 140 if (info->channelMask & NVBIT(channel)) 141 { 142 _nvswitch_read_external_tdiode_temperature(device, info, channel); 143 info->channelMask &= ~NVBIT(channel); 144 } 145 146 if (info->channelMask) 147 { 148 NVSWITCH_PRINT(device, ERROR, 149 "%s: ChannelMask %x absent on LR10.\n", 150 __FUNCTION__, info->channelMask); 151 152 return -NVL_BAD_ARGS; 153 } 154 155 return NVL_SUCCESS; 156 } 157 158 NvlStatus 159 nvswitch_ctrl_therm_get_temperature_limit_lr10 160 ( 161 nvswitch_device *device, 162 NVSWITCH_CTRL_GET_TEMPERATURE_LIMIT_PARAMS *info 163 ) 164 { 165 NvU32 threshold; 166 NvU32 temperature; 167 168 threshold = nvswitch_reg_read_32(device, NV_THERM_TSENSE_THRESHOLD_TEMPERATURES); 169 170 switch (info->thermalEventId) 171 { 172 case NVSWITCH_CTRL_THERMAL_EVENT_ID_WARN: 173 { 174 // Get Slowdown temperature 175 temperature = DRF_VAL(_THERM_TSENSE, _THRESHOLD_TEMPERATURES, 176 _WARNING_TEMPERATURE, threshold); 177 break; 178 } 179 case NVSWITCH_CTRL_THERMAL_EVENT_ID_OVERT: 180 { 181 // Get Shutdown temperature 182 temperature = DRF_VAL(_THERM_TSENSE, _THRESHOLD_TEMPERATURES, 183 _OVERTEMP_TEMPERATURE, threshold); 184 break; 185 } 186 default: 187 { 188 NVSWITCH_PRINT(device, ERROR, "Invalid Thermal Event Id: 0x%x\n", info->thermalEventId); 189 return -NVL_BAD_ARGS; 190 } 191 } 192 193 info->temperatureLimit = NV_TSENSE_FXP_9_5_TO_24_8(temperature); 194 195 return NVL_SUCCESS; 196 } 197 198 // Background task to monitor thermal warn and adjust link mode 199 void 200 nvswitch_monitor_thermal_alert_lr10 201 ( 202 nvswitch_device *device 203 ) 204 { 205 return; 206 } 207 208 /* 209 * @brief Callback function to recieve thermal messages from SOE. 210 */ 211 void 212 nvswitch_therm_soe_callback_lr10 213 ( 214 nvswitch_device *device, 215 RM_FLCN_MSG *pGenMsg, 216 void *pParams, 217 NvU32 seqDesc, 218 NV_STATUS status 219 ) 220 { 221 RM_SOE_THERM_MSG_SLOWDOWN_STATUS slowdown_status; 222 RM_SOE_THERM_MSG_SHUTDOWN_STATUS shutdown_status; 223 RM_FLCN_MSG_SOE *pMsg = (RM_FLCN_MSG_SOE *)pGenMsg; 224 NvU32 temperature; 225 NvU32 threshold; 226 227 switch (pMsg->msg.soeTherm.msgType) 228 { 229 case RM_SOE_THERM_MSG_ID_SLOWDOWN_STATUS: 230 { 231 slowdown_status = pMsg->msg.soeTherm.slowdown; 232 if (slowdown_status.bSlowdown) 233 { 234 if (slowdown_status.source.bTsense) // TSENSE_THERM_ALERT 235 { 236 temperature = RM_SOE_NV_TEMP_TO_CELSIUS_TRUNCED(slowdown_status.maxTemperature); 237 threshold = RM_SOE_NV_TEMP_TO_CELSIUS_TRUNCED(slowdown_status.warnThreshold); 238 239 NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_HOST_THERMAL_EVENT_START, 240 "NVSWITCH Temperature %dC | TSENSE WARN Threshold %dC\n", 241 temperature, threshold); 242 243 NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_HOST_THERMAL_EVENT_START, 244 "Thermal Slowdown Engaged | Temp higher than WARN Threshold\n"); 245 } 246 247 if (slowdown_status.source.bPmgr) // PMGR_THERM_ALERT 248 { 249 NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_HOST_THERMAL_EVENT_START, 250 "Thermal Slowdown Engaged | PMGR WARN Threshold reached\n"); 251 } 252 } 253 else // REVERT_SLOWDOWN 254 { 255 temperature = RM_SOE_NV_TEMP_TO_CELSIUS_TRUNCED(slowdown_status.maxTemperature); 256 threshold = RM_SOE_NV_TEMP_TO_CELSIUS_TRUNCED(slowdown_status.warnThreshold); 257 258 NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_HOST_THERMAL_EVENT_END, 259 "NVSWITCH Temperature %dC | TSENSE WARN Threshold %dC\n", 260 temperature, threshold); 261 262 NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_HOST_THERMAL_EVENT_END, 263 "Thermal slowdown Disengaged\n"); 264 } 265 break; 266 } 267 268 case RM_SOE_THERM_MSG_ID_SHUTDOWN_STATUS: 269 { 270 shutdown_status = pMsg->msg.soeTherm.shutdown; 271 if (shutdown_status.source.bTsense) // TSENSE_THERM_SHUTDOWN 272 { 273 temperature = RM_SOE_NV_TEMP_TO_CELSIUS_TRUNCED(shutdown_status.maxTemperature); 274 threshold = RM_SOE_NV_TEMP_TO_CELSIUS_TRUNCED(shutdown_status.overtThreshold); 275 276 NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_HOST_THERMAL_SHUTDOWN, 277 "NVSWITCH Temperature %dC | OVERT Threshold %dC\n", 278 temperature, threshold); 279 280 NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_HOST_THERMAL_SHUTDOWN, 281 "TSENSE OVERT Threshold reached. Shutting Down\n"); 282 } 283 284 285 if (shutdown_status.source.bPmgr) // PMGR_THERM_SHUTDOWN 286 { 287 NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_HOST_THERMAL_EVENT_START, 288 "PMGR OVERT Threshold reached. Shutting Down\n"); 289 } 290 break; 291 } 292 default: 293 { 294 NVSWITCH_PRINT(device, ERROR, "%s Unknown message Id\n", __FUNCTION__); 295 NVSWITCH_ASSERT(0); 296 } 297 } 298 } 299 300 // 301 // nvswitch_therm_read_voltage 302 // 303 // Temperature and voltage are only available on SKUs which have thermal and 304 // voltage sensors. 305 // 306 307 NvlStatus 308 nvswitch_ctrl_therm_read_voltage_lr10 309 ( 310 nvswitch_device *device, 311 NVSWITCH_CTRL_GET_VOLTAGE_PARAMS *info 312 ) 313 { 314 return -NVL_ERR_NOT_SUPPORTED; 315 } 316 317