1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 2020-2022 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 #include "soe/soe_nvswitch.h" 25 #include "soe/soe_priv_nvswitch.h" 26 27 #include "rmlsfm.h" 28 29 #include "nvlink_export.h" 30 31 #include "common_nvswitch.h" 32 #include "ls10/ls10.h" 33 #include "ls10/soe_ls10.h" 34 #include "lr10/soe_lr10.h" 35 36 #include "nvswitch/ls10/dev_soe_ip.h" 37 #include "nvswitch/ls10/dev_soe_ip_addendum.h" 38 #include "nvswitch/ls10/dev_falcon_v4.h" 39 #include "nvswitch/ls10/dev_nvlsaw_ip.h" 40 #include "nvswitch/ls10/dev_nvlsaw_ip_addendum.h" 41 #include "nvswitch/ls10/dev_riscv_pri.h" 42 43 #include "flcn/flcnable_nvswitch.h" 44 #include "flcn/flcn_nvswitch.h" 45 #include "rmflcncmdif_nvswitch.h" 46 #include "soe/soeifcmn.h" 47 48 /** 49 * @brief Sets pEngDescUc and pEngDescBc to the discovered 50 * engine that matches this flcnable instance 51 * 52 * @param[in] device nvswitch_device pointer 53 * @param[in] pSoe SOE pointer 54 * @param[out] pEngDescUc pointer to the UniCast Engine 55 * Descriptor 56 * @param[out] pEngDescBc pointer to the BroadCast Engine 57 * Descriptor 58 */ 59 static void 60 _soeFetchEngines_LS10 61 ( 62 nvswitch_device *device, 63 FLCNABLE *pSoe, 64 ENGINE_DESCRIPTOR_TYPE *pEngDescUc, 65 ENGINE_DESCRIPTOR_TYPE *pEngDescBc 66 ) 67 { 68 pEngDescUc->initialized = NV_FALSE; 69 if (NVSWITCH_ENG_IS_VALID(device, SOE, 0)) 70 { 71 pEngDescUc->base = NVSWITCH_GET_ENG(device, SOE, , 0); 72 } 73 else 74 { 75 pEngDescUc->base = 0; 76 } 77 78 pEngDescBc->initialized = NV_FALSE; 79 pEngDescBc->base = 0; 80 } 81 82 /* 83 * @Brief : Send a test command to SOE 84 * 85 * @param device The nvswitch device 86 */ 87 static NV_STATUS 88 _nvswitch_soe_send_test_cmd 89 ( 90 nvswitch_device *device 91 ) 92 { 93 RM_FLCN_CMD_SOE cmd; 94 NVSWITCH_TIMEOUT timeout; 95 NvU32 cmdSeqDesc; 96 NV_STATUS status; 97 98 FLCN *pFlcn = device->pSoe->pFlcn; 99 100 nvswitch_os_memset(&cmd, 0, sizeof(cmd)); 101 102 cmd.hdr.unitId = RM_SOE_UNIT_NULL; 103 // sending nothing but a header for UNIT_NULL 104 cmd.hdr.size = RM_FLCN_QUEUE_HDR_SIZE; 105 106 nvswitch_timeout_create(NVSWITCH_INTERVAL_1SEC_IN_NS * 5, &timeout); 107 status = flcnQueueCmdPostBlocking(device, pFlcn, 108 (PRM_FLCN_CMD)&cmd, 109 NULL, // pMsg - not used for now 110 NULL, // pPayload - not used for now 111 SOE_RM_CMDQ_LOG_ID, 112 &cmdSeqDesc, 113 &timeout); 114 115 NVSWITCH_ASSERT(status == NVL_SUCCESS); 116 return status; 117 } 118 119 #if defined(DEVELOP) || defined(DEBUG) || defined(NV_MODS) 120 /*! 121 * Helper function to dump some registers for debug. 122 * 123 * @param[in] device nvswitch_device pointer 124 */ 125 static void 126 dumpDebugRegisters 127 ( 128 nvswitch_device *device 129 ) 130 { 131 FLCN *pFlcn = device->pSoe->pFlcn; 132 133 NvU32 regOS = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_OS); 134 NvU32 regPC = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_RPC); 135 NvU32 regCPUCTL = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_CPUCTL); 136 NvU32 regIDLESTATE = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_IDLESTATE); 137 NvU32 regMAILBOX0 = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_MAILBOX0); 138 NvU32 regMAILBOX1 = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_MAILBOX1); 139 NvU32 regIRQSTAT = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_IRQSTAT); 140 NvU32 regIRQMODE = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_IRQMODE); 141 NvU32 regIRQMASK = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_IRQMASK); 142 NvU32 regIRQDEST = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_IRQDEST); 143 NvU32 regIRQDELEG = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_IRQDELEG); 144 NvU32 regDMACTL = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_DMACTL); 145 NvU32 regDMATRFCMD = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_DMATRFCMD); 146 NvU32 regDMATRFBASE = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_DMATRFBASE); 147 NvU32 regDMATRFMOFFS = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_DMATRFMOFFS); 148 NvU32 regDMATRFFBOFFS = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_DMATRFFBOFFS); 149 NvU32 regPRIVERR_STAT = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_PRIV_ERR_STAT); 150 NvU32 regPRIVERR_INFO = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_PRIV_ERR_INFO); 151 NvU32 regPRIVERR_ADDR_HI = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_PRIV_ERR_ADDR_HI); 152 NvU32 regPRIVERR_ADDR_LO = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_PRIV_ERR_ADDR); 153 NvU32 regHUBERR_STAT = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_HUB_ERR_STAT); 154 NvU32 regBCR_CTRL = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_BCR_CTRL); 155 NvU32 regRESET_PLM = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_RESET_PRIV_LEVEL_MASK); 156 NvU32 regEXE_PLM = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_EXE_PRIV_LEVEL_MASK); 157 158 NVSWITCH_PRINT(device, ERROR, "Peregrine Registers:\n"); 159 NVSWITCH_PRINT(device, ERROR, "OS : 0x%08x\n", regOS); 160 NVSWITCH_PRINT(device, ERROR, "PC (lo32) : 0x%08x\n", regPC); 161 NVSWITCH_PRINT(device, ERROR, "CPUCTL : 0x%08x\n", regCPUCTL); 162 NVSWITCH_PRINT(device, ERROR, "IDLESTATE : 0x%08x\n", regIDLESTATE); 163 NVSWITCH_PRINT(device, ERROR, "MAILBOX0 : 0x%08x\n", regMAILBOX0); 164 NVSWITCH_PRINT(device, ERROR, "MAILBOX1 : 0x%08x\n", regMAILBOX1); 165 NVSWITCH_PRINT(device, ERROR, "IRQSTAT : 0x%08x\n", regIRQSTAT); 166 NVSWITCH_PRINT(device, ERROR, "IRQMODE : 0x%08x\n", regIRQMODE); 167 NVSWITCH_PRINT(device, ERROR, "IRQMASK : 0x%08x\n", regIRQMASK); 168 NVSWITCH_PRINT(device, ERROR, "IRQDEST : 0x%08x\n", regIRQDEST); 169 NVSWITCH_PRINT(device, ERROR, "IRQDELEG : 0x%08x\n", regIRQDELEG); 170 NVSWITCH_PRINT(device, ERROR, "DMACTL : 0x%08x\n", regDMACTL); 171 NVSWITCH_PRINT(device, ERROR, "DMATRFCMD : 0x%08x\n", regDMATRFCMD); 172 NVSWITCH_PRINT(device, ERROR, "DMATRFBASE : 0x%08x\n", regDMATRFBASE); 173 NVSWITCH_PRINT(device, ERROR, "DMATRFMOFFS : 0x%08x\n", regDMATRFMOFFS); 174 NVSWITCH_PRINT(device, ERROR, "DMATRFFBOFFS : 0x%08x\n", regDMATRFFBOFFS); 175 NVSWITCH_PRINT(device, ERROR, "PRIVERR_STAT : 0x%08x\n", regPRIVERR_STAT); 176 NVSWITCH_PRINT(device, ERROR, "PRIVERR_INFO : 0x%08x\n", regPRIVERR_INFO); 177 NVSWITCH_PRINT(device, ERROR, "PRIVERR_ADDR : 0x%08x%08x\n", regPRIVERR_ADDR_HI, regPRIVERR_ADDR_LO); 178 NVSWITCH_PRINT(device, ERROR, "HUBERR_STAT : 0x%08x\n", regHUBERR_STAT); 179 NVSWITCH_PRINT(device, ERROR, "BCR_CTRL : 0x%08x\n", regBCR_CTRL); 180 NVSWITCH_PRINT(device, ERROR, "RESET_PLM : 0x%08x\n", regRESET_PLM); 181 NVSWITCH_PRINT(device, ERROR, "EXE_PLM : 0x%08x\n", regEXE_PLM); 182 } 183 #endif // defined(DEVELOP) || defined(DEBUG) || defined(NV_MODS) 184 185 /* 186 * @Brief : Attach or Detach driver to SOE Queues 187 * 188 * @param[in] device 189 */ 190 static void 191 _nvswitch_soe_attach_detach_driver_ls10 192 ( 193 nvswitch_device *device, 194 NvBool bAttach 195 ) 196 { 197 NvU32 val; 198 199 val = NVSWITCH_SAW_RD32_LS10(device, _NVLSAW, _DRIVER_ATTACH_DETACH); 200 201 if (bAttach) 202 { 203 val = FLD_SET_DRF(_NVLSAW, _DRIVER_ATTACH_DETACH, _STATUS, 204 _ATTACHED, val); 205 } 206 else 207 { 208 val = FLD_SET_DRF(_NVLSAW, _DRIVER_ATTACH_DETACH, _STATUS, 209 _DETACHED, val); 210 } 211 212 NVSWITCH_SAW_WR32_LS10(device, _NVLSAW, _DRIVER_ATTACH_DETACH, val); 213 } 214 215 /* 216 * @Brief : Returns if SOE is attached to the Queues 217 * 218 * @param[in] device 219 */ 220 static NvBool 221 _nvswitch_is_soe_attached_ls10 222 ( 223 nvswitch_device *device 224 ) 225 { 226 NvU32 val; 227 228 val = NVSWITCH_SAW_RD32_LS10(device, _NVLSAW, _SOE_ATTACH_DETACH); 229 230 return FLD_TEST_DRF(_NVLSAW, _SOE_ATTACH_DETACH, _STATUS, _ATTACHED, val); 231 } 232 233 /* 234 * @Brief : Backup NPORT state and issue NPORT reset 235 * 236 * @param[in] device 237 * @param[in] nport 238 */ 239 NvlStatus 240 nvswitch_soe_issue_nport_reset_ls10 241 ( 242 nvswitch_device *device, 243 NvU32 nport 244 ) 245 { 246 FLCN *pFlcn = device->pSoe->pFlcn; 247 NvU32 cmdSeqDesc = 0; 248 NV_STATUS status; 249 RM_FLCN_CMD_SOE cmd; 250 NVSWITCH_TIMEOUT timeout; 251 RM_SOE_CORE_CMD_NPORT_RESET *pNportReset; 252 253 nvswitch_os_memset(&cmd, 0, sizeof(cmd)); 254 255 cmd.hdr.unitId = RM_SOE_UNIT_CORE; 256 cmd.hdr.size = RM_SOE_CMD_SIZE(CORE, NPORT_RESET); 257 258 pNportReset = &cmd.cmd.core.nportReset; 259 pNportReset->nport = nport; 260 pNportReset->cmdType = RM_SOE_CORE_CMD_ISSUE_NPORT_RESET; 261 262 nvswitch_timeout_create(NVSWITCH_INTERVAL_5MSEC_IN_NS, &timeout); 263 status = flcnQueueCmdPostBlocking(device, pFlcn, 264 (PRM_FLCN_CMD)&cmd, 265 NULL, // pMsg 266 NULL, // pPayload 267 SOE_RM_CMDQ_LOG_ID, 268 &cmdSeqDesc, 269 &timeout); 270 if (status != NV_OK) 271 { 272 NVSWITCH_PRINT(device, ERROR, "%s: Failed to send NPORT RESET command to SOE status 0x%x\n", 273 __FUNCTION__, status); 274 return -NVL_ERR_INVALID_STATE; 275 } 276 277 return NVL_SUCCESS; 278 } 279 280 /* 281 * @Brief : De-Assert NPORT reset and restore NPORT state 282 * 283 * @param[in] device 284 * @param[in] nport 285 */ 286 NvlStatus 287 nvswitch_soe_restore_nport_state_ls10 288 ( 289 nvswitch_device *device, 290 NvU32 nport 291 ) 292 { 293 FLCN *pFlcn = device->pSoe->pFlcn; 294 NvU32 cmdSeqDesc = 0; 295 NV_STATUS status; 296 RM_FLCN_CMD_SOE cmd; 297 NVSWITCH_TIMEOUT timeout; 298 RM_SOE_CORE_CMD_NPORT_STATE *pNportState; 299 300 nvswitch_os_memset(&cmd, 0, sizeof(cmd)); 301 302 cmd.hdr.unitId = RM_SOE_UNIT_CORE; 303 cmd.hdr.size = RM_SOE_CMD_SIZE(CORE, NPORT_STATE); 304 305 pNportState = &cmd.cmd.core.nportState; 306 pNportState->nport = nport; 307 pNportState->cmdType = RM_SOE_CORE_CMD_RESTORE_NPORT_STATE; 308 309 nvswitch_timeout_create(NVSWITCH_INTERVAL_5MSEC_IN_NS, &timeout); 310 status = flcnQueueCmdPostBlocking(device, pFlcn, 311 (PRM_FLCN_CMD)&cmd, 312 NULL, // pMsg 313 NULL, // pPayload 314 SOE_RM_CMDQ_LOG_ID, 315 &cmdSeqDesc, 316 &timeout); 317 if (status != NV_OK) 318 { 319 NVSWITCH_PRINT(device, ERROR, "%s: Failed to send NPORT BACKUP command to SOE status 0x%x\n", 320 __FUNCTION__, status); 321 return -NVL_ERR_INVALID_STATE; 322 } 323 324 return NVL_SUCCESS; 325 } 326 327 /* 328 * @Brief : Set NPORT TPROD state in SOE 329 * 330 * @param[in] device 331 * @param[in] nport 332 */ 333 NvlStatus 334 nvswitch_set_nport_tprod_state_ls10 335 ( 336 nvswitch_device *device, 337 NvU32 nport 338 ) 339 { 340 FLCN *pFlcn = device->pSoe->pFlcn; 341 NvU32 cmdSeqDesc = 0; 342 NV_STATUS status; 343 RM_FLCN_CMD_SOE cmd; 344 NVSWITCH_TIMEOUT timeout; 345 RM_SOE_CORE_CMD_NPORT_TPROD_STATE *nportTprodState; 346 347 nvswitch_os_memset(&cmd, 0, sizeof(cmd)); 348 349 cmd.hdr.unitId = RM_SOE_UNIT_CORE; 350 cmd.hdr.size = sizeof(cmd); 351 352 nportTprodState = &cmd.cmd.core.nportTprodState; 353 nportTprodState->nport = nport; 354 nportTprodState->cmdType = RM_SOE_CORE_CMD_SET_NPORT_TPROD_STATE; 355 356 nvswitch_timeout_create(NVSWITCH_INTERVAL_5MSEC_IN_NS, &timeout); 357 status = flcnQueueCmdPostBlocking(device, pFlcn, 358 (PRM_FLCN_CMD)&cmd, 359 NULL, // pMsg 360 NULL, // pPayload 361 SOE_RM_CMDQ_LOG_ID, 362 &cmdSeqDesc, 363 &timeout); 364 if (status != NV_OK) 365 { 366 NVSWITCH_PRINT(device, ERROR, "%s: Failed to send NPORT SET_TPROD_STATE command to SOE, status 0x%x\n", 367 __FUNCTION__, status); 368 return -NVL_ERR_INVALID_STATE; 369 } 370 371 return NVL_SUCCESS; 372 } 373 374 /* 375 * @Brief : INIT L2 register state in SOE 376 * 377 * @param[in] device 378 * @param[in] nport 379 */ 380 void 381 nvswitch_soe_init_l2_state_ls10 382 ( 383 nvswitch_device *device 384 ) 385 { 386 FLCN *pFlcn; 387 NvU32 cmdSeqDesc = 0; 388 NV_STATUS status; 389 RM_FLCN_CMD_SOE cmd; 390 NVSWITCH_TIMEOUT timeout; 391 RM_SOE_CORE_CMD_L2_STATE *pL2State; 392 393 if (!nvswitch_is_soe_supported(device)) 394 { 395 NVSWITCH_PRINT(device, INFO, "%s: SOE is not supported\n", 396 __FUNCTION__); 397 return; 398 } 399 400 pFlcn = device->pSoe->pFlcn; 401 402 nvswitch_os_memset(&cmd, 0, sizeof(cmd)); 403 cmd.hdr.unitId = RM_SOE_UNIT_CORE; 404 cmd.hdr.size = sizeof(cmd); 405 406 pL2State = &cmd.cmd.core.l2State; 407 pL2State->cmdType = RM_SOE_CORE_CMD_INIT_L2_STATE; 408 409 nvswitch_timeout_create(NVSWITCH_INTERVAL_5MSEC_IN_NS, &timeout); 410 status = flcnQueueCmdPostBlocking(device, pFlcn, 411 (PRM_FLCN_CMD)&cmd, 412 NULL, // pMsg 413 NULL, // pPayload 414 SOE_RM_CMDQ_LOG_ID, 415 &cmdSeqDesc, 416 &timeout); 417 if (status != NV_OK) 418 { 419 NVSWITCH_PRINT(device, ERROR, "%s: Failed to send INIT_L2_STATE command to SOE, status 0x%x\n", 420 __FUNCTION__, status); 421 } 422 } 423 424 425 /* 426 * @Brief : Init sequence for SOE FSP RISCV image 427 * 428 * The driver assumes SOE is already booted by FSP. 429 * Driver checks for SOE state and handshakes with a test command. 430 * If FSP or SOE fails to boot, driver fails and quits. 431 * 432 * @param[in] nvswitch device 433 */ 434 NvlStatus 435 nvswitch_init_soe_ls10 436 ( 437 nvswitch_device *device 438 ) 439 { 440 NvlStatus status; 441 NvU32 data; 442 FLCN *pFlcn = device->pSoe->pFlcn; 443 444 // 445 // Check if SOE has halted unexpectedly. 446 // 447 // The explicit check is required because the interrupts 448 // are not yet enabled as the device is still initializing. 449 // 450 if (soeIsCpuHalted_HAL(device, ((PSOE)pFlcn->pFlcnable))) 451 { 452 NVSWITCH_PRINT(device, ERROR, 453 "%s: SOE halted\n", 454 __FUNCTION__); 455 NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_SOE_BOOTSTRAP, 456 "SOE init Failed(0)\n"); 457 status = -NVL_ERR_INVALID_STATE; 458 goto nvswitch_init_soe_fail; 459 } 460 461 // Check for SOE BOOT SUCCESS 462 data = flcnRegRead_HAL(device, pFlcn, NV_PFALCON_FALCON_MAILBOX1); 463 if (data != SOE_BOOTSTRAP_SUCCESS) 464 { 465 NVSWITCH_PRINT(device, ERROR, 466 "%s: SOE boot failed\n", 467 __FUNCTION__); 468 NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_SOE_BOOTSTRAP, 469 "SOE init failed(1)\n"); 470 status = -NVL_ERR_INVALID_STATE; 471 goto nvswitch_init_soe_fail; 472 } 473 474 // Register SOE callbacks 475 status = nvswitch_soe_register_event_callbacks(device); 476 if (status != NVL_SUCCESS) 477 { 478 NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_SOE_COMMAND_QUEUE, 479 "Failed to register SOE events\n"); 480 NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_SOE_BOOTSTRAP, 481 "SOE init failed(2)\n"); 482 return status; 483 } 484 485 // 486 // Set TRACEPC to stack mode for better ucode trace 487 // In Vulcan CR firmware, this is set to reduced mode in the SOE's manifest 488 // 489 data = flcnRiscvRegRead_HAL(device, pFlcn, NV_PRISCV_RISCV_TRACECTL); 490 data = FLD_SET_DRF(_PRISCV, _RISCV_TRACECTL, _MODE, _STACK, data); 491 flcnRiscvRegWrite_HAL(device, pFlcn, NV_PRISCV_RISCV_TRACECTL, data); 492 493 // Sanity the command and message queues as a final check 494 if (_nvswitch_soe_send_test_cmd(device) != NV_OK) 495 { 496 NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_SOE_BOOTSTRAP, 497 "SOE init failed(4)\n"); 498 status = -NVL_ERR_INVALID_STATE; 499 goto nvswitch_init_soe_fail; 500 } 501 502 NVSWITCH_PRINT(device, SETUP, 503 "%s: SOE successfully bootstrapped.\n", 504 __FUNCTION__); 505 506 return NVL_SUCCESS; 507 508 nvswitch_init_soe_fail : 509 // Log any failures SOE may have had during bootstrap 510 (void)soeService_HAL(device, ((PSOE)pFlcn->pFlcnable)); 511 #if defined(DEVELOP) || defined(DEBUG) || defined(NV_MODS) 512 dumpDebugRegisters(device); 513 #endif // defined(DEVELOP) || defined(DEBUG) || defined(NV_MODS) 514 515 flcnDbgInfoCapturePcTrace_HAL(device, pFlcn); 516 NVSWITCH_ASSERT(0); 517 return status; 518 } 519 520 /* 521 * @Brief : Shutdown SOE during driver unload 522 * 523 * @param[in] device Bootstrap SOE on this device 524 */ 525 NvlStatus 526 nvswitch_unload_soe_ls10 527 ( 528 nvswitch_device *device 529 ) 530 { 531 // Detach driver from SOE Queues 532 _nvswitch_soe_attach_detach_driver_ls10(device, NV_FALSE); 533 534 return NVL_SUCCESS; 535 } 536 537 /*! 538 * @brief : Register callback functions for events and messages from SOE 539 * 540 * @param[in] device nvswitch_device pointer 541 */ 542 NvlStatus 543 nvswitch_soe_register_event_callbacks_ls10 544 ( 545 nvswitch_device *device 546 ) 547 { 548 549 NV_STATUS status; 550 PFLCN pFlcn = device->pSoe->pFlcn; 551 PSOE pSoe = (PSOE)device->pSoe; 552 553 // Register Thermal callback funcion 554 status = flcnQueueEventRegister( 555 device, pFlcn, 556 RM_SOE_UNIT_THERM, 557 NULL, 558 nvswitch_therm_soe_callback_lr10, 559 NULL, 560 &pSoe->thermEvtDesc); 561 if (status != NV_OK) 562 { 563 NVSWITCH_PRINT(device, ERROR, 564 "%s: Failed to register thermal event handler.\n", 565 __FUNCTION__); 566 return -NVL_ERR_INVALID_STATE; 567 } 568 569 return NVL_SUCCESS; 570 } 571 572 void 573 nvswitch_soe_unregister_events_ls10 574 ( 575 nvswitch_device *device 576 ) 577 { 578 PFLCN pFlcn = device->pSoe->pFlcn; 579 PSOE pSoe = (PSOE)device->pSoe; 580 NV_STATUS status; 581 582 // un-register thermal callback funcion 583 status = flcnQueueEventUnregister(device, pFlcn, 584 pSoe->thermEvtDesc); 585 if (status != NV_OK) 586 { 587 NVSWITCH_PRINT(device, ERROR, 588 "%s: Failed to un-register thermal event handler.\n", 589 __FUNCTION__); 590 } 591 } 592 593 /*! 594 * @brief Determine if the SOE RISCV CPU is halted 595 * 596 * @param[in] device nvswitch_device pointer 597 * @param[in] pSoe SOE pointer 598 * 599 * @return NvBool reflecting the SOE Riscv CPU halted state 600 */ 601 static NvBool 602 _soeIsCpuHalted_LS10 603 ( 604 nvswitch_device *device, 605 PSOE pSoe 606 ) 607 { 608 NvU32 data; 609 610 data = NVSWITCH_SOE_RD32_LS10(device, 0, _SOE_RISCV, _CPUCTL); 611 return FLD_TEST_DRF(_PFALCON, _FALCON_CPUCTL, _HALTED, _TRUE, data); 612 } 613 614 static NvU32 615 _soeIntrStatus_LS10 616 ( 617 nvswitch_device *device 618 ) 619 { 620 NvU32 irq, mask, dest; 621 622 irq = NVSWITCH_SOE_RD32_LS10(device, 0, _SOE_FALCON, _IRQSTAT); 623 mask = NVSWITCH_SOE_RD32_LS10(device, 0, _SOE_RISCV, _IRQMASK); 624 dest = NVSWITCH_SOE_RD32_LS10(device, 0, _SOE_RISCV, _IRQDEST); 625 626 return (irq & mask & dest); 627 } 628 629 /*! 630 * @brief Top level service routine 631 * 632 * @param[in] device nvswitch_device pointer 633 * @param[in] pSoe SOE pointer 634 * 635 * @return 32-bit interrupt status AFTER all known interrupt-sources were 636 * serviced. 637 */ 638 static NvU32 639 _soeService_LS10 640 ( 641 nvswitch_device *device, 642 PSOE pSoe 643 ) 644 { 645 NvBool bRecheckMsgQ = NV_FALSE; 646 NvBool bRecheckPrintQ = NV_FALSE; 647 NvU32 clearBits = 0; 648 NvU32 intrStatus; 649 PFLCN pFlcn = ENG_GET_FLCN(pSoe); 650 651 if (pFlcn == NULL) 652 { 653 NVSWITCH_ASSERT(0); 654 return NV_ERR_INVALID_ARGUMENT; 655 } 656 657 // Get the IRQ status and mask the sources not directed to host. 658 intrStatus = _soeIntrStatus_LS10(device); 659 660 // Exit if there is nothing to do 661 if (intrStatus == 0) 662 { 663 return 0; 664 } 665 666 // Service pending interrupts 667 if (intrStatus & DRF_DEF(_PFALCON, _FALCON_IRQSTAT, _WDTMR, _TRUE)) 668 { 669 NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_SOE_WATCHDOG, 670 "SOE Watchdog error\n"); 671 NVSWITCH_PRINT(device, INFO, 672 "%s: Watchdog timer fired. We do not support this " 673 "yet.\n", __FUNCTION__); 674 NVSWITCH_ASSERT(0); 675 676 clearBits |= DRF_DEF(_PFALCON, _FALCON_IRQSCLR, _WDTMR, _SET); 677 } 678 679 if (intrStatus & DRF_DEF(_PFALCON, _FALCON_IRQSTAT, _EXTERR, _TRUE)) 680 { 681 clearBits |= DRF_DEF(_PFALCON, _FALCON_IRQSCLR, _EXTERR, _SET); 682 683 NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_SOE_EXTERR, "SOE EXTERR\n"); 684 } 685 686 if (intrStatus & DRF_DEF(_PFALCON, _FALCON_IRQSTAT, _HALT, _TRUE)) 687 { 688 clearBits |= DRF_DEF(_PFALCON, _FALCON_IRQSCLR, _HALT, _SET); 689 690 NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_SOE_HALT, "SOE HALTED\n"); 691 soeServiceHalt_HAL(device, pSoe); 692 } 693 694 if (intrStatus & DRF_DEF(_PFALCON, _FALCON_IRQSTAT, _SWGEN0, _TRUE)) 695 { 696 clearBits |= DRF_DEF(_PFALCON, _FALCON_IRQSCLR, _SWGEN0, _SET); 697 698 NVSWITCH_PRINT(device, MMIO, 699 "%s: Received a message from SOE via SWGEN0\n", 700 __FUNCTION__); 701 soeProcessMessages_HAL(device, pSoe); 702 bRecheckMsgQ = NV_TRUE; 703 } 704 705 if (intrStatus & DRF_DEF(_PFALCON, _FALCON_IRQSTAT, _SWGEN1, _TRUE)) 706 { 707 clearBits |= DRF_DEF(_PFALCON, _FALCON_IRQSCLR, _SWGEN1, _SET); 708 709 NVSWITCH_PRINT(device, INFO, 710 "%s: Received a SWGEN1 interrupt\n", 711 __FUNCTION__); 712 flcnDebugBufferDisplay_HAL(device, pFlcn); 713 bRecheckPrintQ = NV_TRUE; 714 } 715 716 // Clear any sources that were serviced and get the new status. 717 flcnRegWrite_HAL(device, pFlcn, NV_PFALCON_FALCON_IRQSCLR, clearBits); 718 719 // Re-read interrupt status before retriggering to return correct value 720 intrStatus = _soeIntrStatus_LS10(device); 721 722 // 723 // If we just processed a SWGEN0 message queue interrupt, peek 724 // into the message queue and see if any messages were missed the last time 725 // the queue was purged (above). If it is not empty, re-generate SWGEN0 726 // (since it is now cleared) and exit. As long as an interrupt is pending, 727 // this function will be re-entered and the message(s) will be processed. 728 // 729 if (bRecheckMsgQ) 730 { 731 PFALCON_QUEUE_INFO pQueueInfo; 732 FLCNQUEUE *pMsgQ; 733 734 pQueueInfo = pFlcn->pQueueInfo; 735 736 NVSWITCH_ASSERT(pQueueInfo != NULL); 737 NVSWITCH_ASSERT(pQueueInfo->pQueues != NULL); 738 739 pMsgQ = &pQueueInfo->pQueues[SOE_RM_MSGQ_LOG_ID]; 740 741 if (!pMsgQ->isEmpty(device, pFlcn, pMsgQ)) 742 { 743 // It is not necessary to RMW IRQSSET (zeros are ignored) 744 flcnRegWrite_HAL(device, pFlcn, NV_PFALCON_FALCON_IRQSSET, 745 DRF_DEF(_PFALCON, _FALCON_IRQSSET, _SWGEN0, _SET)); 746 } 747 } 748 749 // 750 // If we just processed a SWGEN1 interrupt (Debug Buffer interrupt), peek 751 // into the Debug Buffer and see if any text was missed the last time 752 // the buffer was displayed (above). If it is not empty, re-generate SWGEN1 753 // (since it is now cleared) and exit. As long as an interrupt is pending, 754 // this function will be re-entered and the message(s) will be processed. 755 // 756 if (bRecheckPrintQ) 757 { 758 if (!flcnDebugBufferIsEmpty_HAL(device, pFlcn)) 759 { 760 flcnRegWrite_HAL(device, pFlcn, NV_PFALCON_FALCON_IRQSSET, 761 DRF_DEF(_PFALCON, _FALCON_IRQSSET, _SWGEN1, _SET)); 762 } 763 } 764 765 flcnIntrRetrigger_HAL(device, pFlcn); 766 767 return intrStatus; 768 } 769 770 /*! 771 * Called by soeService to handle a SOE halt. This function will dump the 772 * current status of SOE and then trap the CPU for further inspection for a 773 * debug build. 774 * 775 * @param[in] device nvswitch_device pointer 776 * @param[in] pSoe SOE object pointer 777 */ 778 static void 779 _soeServiceHalt_LS10 780 ( 781 nvswitch_device *device, 782 PSOE pSoe 783 ) 784 { 785 PFLCN pFlcn = ENG_GET_FLCN(pSoe); 786 787 NVSWITCH_PRINT(device, ERROR, 788 "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" 789 "!! ** SOE HALTED ** !!\n" 790 "!! Please file a bug with the following information. !!\n" 791 "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n"); 792 793 #if defined(DEVELOP) || defined(DEBUG) || defined(NV_MODS) 794 dumpDebugRegisters(device); 795 #endif // defined(DEVELOP) || defined(DEBUG) || defined(NV_MODS) 796 797 flcnDbgInfoCaptureRiscvPcTrace_HAL(device, pFlcn); 798 NVSWITCH_ASSERT(0); 799 } 800 801 /*! 802 * Use the SOE INIT Message to construct, initialize or update SOE Queues. 803 * 804 * @param[in] device nvswitch_device pointer 805 * @param[in] pSoe SOE object pointer 806 * 807 * @return 'NV_OK' upon successful creation of all SOE Queues 808 */ 809 static NV_STATUS 810 _soeUpdateInitMsgQueuesInfo 811 ( 812 nvswitch_device *device, 813 PSOE pSoe 814 ) 815 { 816 FLCNQUEUE *pQueue; 817 PFLCN pFlcn = ENG_GET_FLCN(pSoe); 818 PFALCON_QUEUE_INFO pQueueInfo; 819 NvU32 queueOffset; 820 NvU16 queueSize; 821 NvU8 queuePhyId; 822 NvU8 queueLogId; 823 NV_STATUS status; 824 825 // 826 // No command should be longer than half the queue size. 827 // See _soeQueueCmdValidate_IMPL(). 828 // 829 ct_assert(sizeof(RM_FLCN_CMD_SOE) <= (SOE_CMD_QUEUE_LENGTH / 2)); 830 831 NVSWITCH_ASSERT(pFlcn != NULL); 832 833 pQueueInfo = pFlcn->pQueueInfo; 834 NVSWITCH_ASSERT(pQueueInfo != NULL); 835 836 // Construct DMEM for CMDQ 837 queueOffset = SOE_EMEM_CHANNEL_CMDQ_OFFSET; 838 queueSize = SOE_CMD_QUEUE_LENGTH; 839 queuePhyId = 0; 840 queueLogId = SOE_RM_CMDQ_LOG_ID; 841 pQueue = &pQueueInfo->pQueues[queueLogId]; 842 status = flcnQueueConstruct_dmem_nvswitch( 843 device, 844 pFlcn, 845 &pQueue, // ppQueue 846 queueLogId, // Logical ID of the queue 847 queuePhyId, // Physical ID of the queue 848 queueOffset, // offset 849 queueSize, // size 850 RM_FLCN_QUEUE_HDR_SIZE); // cmdHdrSize 851 if (status != NV_OK) 852 { 853 NVSWITCH_PRINT(device, ERROR, 854 "%s: Error constructing SOE CmdQueue (status=" 855 "0x%08x).\n", __FUNCTION__, status); 856 NVSWITCH_ASSERT(0); 857 return status; 858 } 859 860 // Construct DMEM for MSGQ 861 queueOffset = SOE_EMEM_CHANNEL_MSGQ_OFFSET; 862 queueSize = SOE_MSG_QUEUE_LENGTH; 863 queuePhyId = 0; 864 queueLogId = SOE_RM_MSGQ_LOG_ID; 865 pQueue = &pQueueInfo->pQueues[queueLogId]; 866 status = flcnQueueConstruct_dmem_nvswitch( 867 device, 868 pFlcn, 869 &pQueue, // ppQueue 870 queueLogId, // Logical ID of the queue 871 queuePhyId, // Physical ID of the queue 872 queueOffset, // offset 873 queueSize, // size 874 RM_FLCN_QUEUE_HDR_SIZE); // cmdHdrSize 875 if (status != NV_OK) 876 { 877 NVSWITCH_PRINT(device, ERROR, 878 "%s: Error constructing SOE MsgQueue (status=" 879 "0x%08x).\n", __FUNCTION__, status); 880 NVSWITCH_ASSERT(0); 881 return status; 882 } 883 884 pFlcn->bOSReady = NV_TRUE; 885 886 return NV_OK; 887 } 888 889 static NV_STATUS 890 _soeWaitForInitAck_LS10 891 ( 892 nvswitch_device *device, 893 PSOE pSoe 894 ) 895 { 896 NV_STATUS status; 897 PFLCN pFlcn = ENG_GET_FLCN(pSoe); 898 899 if (!_nvswitch_is_soe_attached_ls10(device)) 900 { 901 NVSWITCH_PRINT(device, ERROR, 902 "%s SOE is not to attached!\n", 903 __FUNCTION__); 904 NVSWITCH_ASSERT(0); 905 return NV_ERR_NOT_READY; 906 } 907 908 // Update InitMsg Queue info before sending any commands 909 if (!pFlcn->bOSReady) 910 { 911 status = _soeUpdateInitMsgQueuesInfo(device, pSoe); 912 if (status != NV_OK) 913 { 914 NVSWITCH_PRINT(device, ERROR, 915 "%s Failed to attach driver!\n", 916 __FUNCTION__); 917 NVSWITCH_ASSERT(0); 918 return status; 919 } 920 921 // Attach driver to SOE Queues 922 _nvswitch_soe_attach_detach_driver_ls10(device, NV_TRUE); 923 } 924 925 return NV_OK; 926 } 927 928 /*! 929 * Purges all the messages from the SOE's message queue. Each message will 930 * be analyzed, clients will be notified of status, and events will be routed 931 * to all registered event listeners. 932 * 933 * @param[in] device nvswitch_device pointer 934 * @param[in] pSoe SOE object pointer 935 * 936 * @return 'NV_OK' if the message queue was successfully purged. 937 */ 938 static NV_STATUS 939 _soeProcessMessages_LS10 940 ( 941 nvswitch_device *device, 942 PSOE pSoe 943 ) 944 { 945 RM_FLCN_MSG_SOE soeMessage; 946 NV_STATUS status; 947 PFLCN pFlcn = ENG_GET_FLCN(pSoe); 948 949 // Update InitMsg Queue info before recieving any messages 950 if (!pFlcn->bOSReady) 951 { 952 status = _soeUpdateInitMsgQueuesInfo(device, pSoe); 953 if (status != NV_OK) 954 { 955 NVSWITCH_PRINT(device, ERROR, 956 "%s Failed to attach driver!\n", 957 __FUNCTION__); 958 NVSWITCH_ASSERT(0); 959 return status; 960 } 961 962 // Attach driver to SOE Queues 963 _nvswitch_soe_attach_detach_driver_ls10(device, NV_TRUE); 964 } 965 966 967 // keep processing messages until no more exist in the message queue 968 while (NV_OK == (status = flcnQueueReadData( 969 device, 970 pFlcn, 971 SOE_RM_MSGQ_LOG_ID, 972 (RM_FLCN_MSG *)&soeMessage, NV_TRUE))) 973 { 974 NVSWITCH_PRINT(device, MMIO, 975 "%s: unitId=0x%02x, size=0x%02x, ctrlFlags=0x%02x, " \ 976 "seqNumId=0x%02x\n", 977 __FUNCTION__, 978 soeMessage.hdr.unitId, 979 soeMessage.hdr.size, 980 soeMessage.hdr.ctrlFlags, 981 soeMessage.hdr.seqNumId); 982 983 // check to see if the message is a reply or an event. 984 if ((soeMessage.hdr.ctrlFlags &= RM_FLCN_QUEUE_HDR_FLAGS_EVENT) != 0) 985 { 986 flcnQueueEventHandle(device, pFlcn, (RM_FLCN_MSG *)&soeMessage, NV_OK); 987 } 988 // the message is a response from a previously queued command 989 else 990 { 991 flcnQueueResponseHandle(device, pFlcn, (RM_FLCN_MSG *)&soeMessage); 992 } 993 } 994 995 // 996 // Status NV_ERR_NOT_READY implies, Queue is empty. 997 // Log the message in other error cases. 998 // 999 if (status != NV_ERR_NOT_READY) 1000 { 1001 NVSWITCH_PRINT(device, ERROR, 1002 "%s: unexpected error while purging message queue (status=0x%x).\n", 1003 __FUNCTION__, (status)); 1004 } 1005 1006 return status; 1007 } 1008 1009 static NV_STATUS 1010 _soeHandleInitEvent_LS10 1011 ( 1012 nvswitch_device *device, 1013 PFLCNABLE pSoe, 1014 RM_FLCN_MSG *pGenMsg 1015 ) 1016 { 1017 NVSWITCH_PRINT(device, ERROR, 1018 "%s: Init handle event not Supported!\n", 1019 __FUNCTION__); 1020 NVSWITCH_ASSERT(0); 1021 return NV_ERR_GENERIC; 1022 } 1023 1024 static NvlStatus 1025 _soeI2CAccessSend 1026 ( 1027 nvswitch_device *device, 1028 void *cpuAddr, 1029 NvU64 dmaHandle, 1030 NvU16 xferSize 1031 ) 1032 { 1033 FLCN *pFlcn = device->pSoe->pFlcn; 1034 NvU32 cmdSeqDesc; 1035 NV_STATUS status; 1036 RM_FLCN_CMD_SOE cmd; 1037 RM_SOE_CORE_CMD_I2C *pI2cCmd; 1038 NVSWITCH_TIMEOUT timeout; 1039 1040 nvswitch_os_memset(&cmd, 0, sizeof(cmd)); 1041 1042 cmd.hdr.unitId = RM_SOE_UNIT_CORE; 1043 cmd.hdr.size = RM_SOE_CMD_SIZE(CORE, I2C); 1044 1045 pI2cCmd = &cmd.cmd.core.i2c; 1046 RM_FLCN_U64_PACK(&pI2cCmd->dmaHandle, &dmaHandle); 1047 pI2cCmd->xferSize = xferSize; 1048 pI2cCmd->cmdType = RM_SOE_CORE_CMD_I2C_ACCESS; 1049 1050 cmdSeqDesc = 0; 1051 1052 nvswitch_timeout_create(NVSWITCH_INTERVAL_1SEC_IN_NS * 5, &timeout); 1053 status = flcnQueueCmdPostBlocking(device, pFlcn, 1054 (PRM_FLCN_CMD)&cmd, 1055 NULL, // pMsg 1056 NULL, // pPayload 1057 SOE_RM_CMDQ_LOG_ID, 1058 &cmdSeqDesc, 1059 &timeout); 1060 if (status != NV_OK) 1061 { 1062 NVSWITCH_PRINT(device, ERROR, "%s: Failed to send I2C command to SOE status 0x%x\n", 1063 __FUNCTION__, status); 1064 return -NVL_ERR_INVALID_STATE; 1065 } 1066 1067 return NVL_SUCCESS; 1068 } 1069 1070 static NvlStatus 1071 _soeI2cFlcnStatusToNvlStatus 1072 ( 1073 NvU8 flcnStatus 1074 ) 1075 { 1076 switch (flcnStatus) 1077 { 1078 case FLCN_OK: 1079 return NVL_SUCCESS; 1080 case FLCN_ERR_INVALID_ARGUMENT: 1081 return -NVL_BAD_ARGS; 1082 case FLCN_ERR_OBJECT_NOT_FOUND: 1083 return -NVL_NOT_FOUND; 1084 case FLCN_ERROR: 1085 return -NVL_ERR_GENERIC; 1086 case FLCN_ERR_INVALID_STATE: 1087 return -NVL_ERR_INVALID_STATE; 1088 case FLCN_ERR_MORE_PROCESSING_REQUIRED: 1089 return -NVL_MORE_PROCESSING_REQUIRED; 1090 case FLCN_ERR_TIMEOUT: 1091 return -NVL_IO_ERROR; 1092 case FLCN_ERR_I2C_BUSY: 1093 return -NVL_ERR_STATE_IN_USE; 1094 case FLCN_ERR_NOT_SUPPORTED: 1095 return -NVL_ERR_NOT_SUPPORTED; 1096 default: 1097 return -NVL_ERR_GENERIC; 1098 } 1099 } 1100 1101 static NvlStatus 1102 _soeI2CAccess_LS10 1103 ( 1104 nvswitch_device *device, 1105 NVSWITCH_CTRL_I2C_INDEXED_PARAMS *pParams 1106 ) 1107 { 1108 NvlStatus ret; 1109 NvU8 flcnRet; 1110 PNVSWITCH_OBJI2C pI2c; 1111 void *pCpuAddr; 1112 NvU64 dmaHandle; 1113 1114 if (pParams == NULL) 1115 { 1116 return -NVL_BAD_ARGS; 1117 } 1118 1119 pI2c = device->pI2c; 1120 1121 if (pI2c == NULL || !pI2c->soeI2CSupported) 1122 { 1123 return -NVL_ERR_NOT_SUPPORTED; 1124 } 1125 1126 pCpuAddr = pI2c->pCpuAddr; 1127 dmaHandle = pI2c->dmaHandle; 1128 1129 ret = nvswitch_os_sync_dma_region_for_cpu(device->os_handle, dmaHandle, 1130 SOE_I2C_DMA_BUF_SIZE, 1131 NVSWITCH_DMA_DIR_FROM_SYSMEM); 1132 if (ret != NVL_SUCCESS) 1133 { 1134 NVSWITCH_PRINT(device, ERROR, "%s: nvswitch_os_sync_dma_region_for_cpu returned %d\n", 1135 __FUNCTION__, ret); 1136 return ret; 1137 } 1138 1139 // Required for error reporting from SOE to driver 1140 ct_assert(sizeof(NVSWITCH_CTRL_I2C_INDEXED_PARAMS) < SOE_I2C_STATUS_INDEX); 1141 1142 // Copy I2C struct into buffer 1143 nvswitch_os_memcpy(pCpuAddr, pParams, sizeof(NVSWITCH_CTRL_I2C_INDEXED_PARAMS)); 1144 1145 ret = nvswitch_os_sync_dma_region_for_device(device->os_handle, dmaHandle, 1146 SOE_I2C_DMA_BUF_SIZE, 1147 NVSWITCH_DMA_DIR_FROM_SYSMEM); 1148 if (ret != NVL_SUCCESS) 1149 { 1150 NVSWITCH_PRINT(device, ERROR, "%s: nvswitch_os_sync_dma_region_for_device returned %d\n", 1151 __FUNCTION__, ret); 1152 return ret; 1153 } 1154 1155 // Send I2C access command to SOE 1156 ret = _soeI2CAccessSend(device, pCpuAddr, dmaHandle, SOE_I2C_DMA_BUF_SIZE); 1157 if (ret != NVL_SUCCESS) 1158 { 1159 NVSWITCH_PRINT(device, ERROR, "%s: _soeI2CAccessSend returned %d\n", 1160 __FUNCTION__, ret); 1161 return ret; 1162 } 1163 1164 // Get result 1165 ret = nvswitch_os_sync_dma_region_for_cpu(device->os_handle, dmaHandle, 1166 SOE_I2C_DMA_BUF_SIZE, 1167 NVSWITCH_DMA_DIR_TO_SYSMEM); 1168 if (ret != NVL_SUCCESS) 1169 { 1170 NVSWITCH_PRINT(device, ERROR, "%s: nvswitch_os_sync_dma_region_for_cpu returned %d\n", 1171 __FUNCTION__, ret); 1172 return ret; 1173 } 1174 1175 nvswitch_os_memcpy(pParams, pCpuAddr, sizeof(NVSWITCH_CTRL_I2C_INDEXED_PARAMS)); 1176 1177 // Return value of the I2C operation that was performed in SOE 1178 flcnRet = ((NvU8*)pCpuAddr)[SOE_I2C_STATUS_INDEX]; 1179 ret = _soeI2cFlcnStatusToNvlStatus(flcnRet); 1180 1181 return ret; 1182 } 1183 1184 /** 1185 * @brief set hal function pointers for functions defined in LR10 (i.e. this file) 1186 * 1187 * this function has to be at the end of the file so that all the 1188 * other functions are already defined. 1189 * 1190 * @param[in] pFlcnable The flcnable for which to set hals 1191 */ 1192 void 1193 soeSetupHal_LS10 1194 ( 1195 SOE *pSoe 1196 ) 1197 { 1198 soe_hal *pHal = pSoe->base.pHal; 1199 flcnable_hal *pParentHal = (flcnable_hal *)pHal; 1200 1201 soeSetupHal_LR10(pSoe); 1202 1203 pParentHal->fetchEngines = _soeFetchEngines_LS10; 1204 pParentHal->handleInitEvent = _soeHandleInitEvent_LS10; 1205 1206 pHal->isCpuHalted = _soeIsCpuHalted_LS10; 1207 pHal->service = _soeService_LS10; 1208 pHal->serviceHalt = _soeServiceHalt_LS10; 1209 pHal->processMessages = _soeProcessMessages_LS10; 1210 pHal->waitForInitAck = _soeWaitForInitAck_LS10; 1211 pHal->i2cAccess = _soeI2CAccess_LS10; 1212 } 1213 1214