11739a20eSAndy Ritger /*
21739a20eSAndy Ritger  * SPDX-FileCopyrightText: Copyright (c) 2018-2020 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
31739a20eSAndy Ritger  * SPDX-License-Identifier: MIT
41739a20eSAndy Ritger  *
51739a20eSAndy Ritger  * Permission is hereby granted, free of charge, to any person obtaining a
61739a20eSAndy Ritger  * copy of this software and associated documentation files (the "Software"),
71739a20eSAndy Ritger  * to deal in the Software without restriction, including without limitation
81739a20eSAndy Ritger  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
91739a20eSAndy Ritger  * and/or sell copies of the Software, and to permit persons to whom the
101739a20eSAndy Ritger  * Software is furnished to do so, subject to the following conditions:
111739a20eSAndy Ritger  *
121739a20eSAndy Ritger  * The above copyright notice and this permission notice shall be included in
131739a20eSAndy Ritger  * all copies or substantial portions of the Software.
141739a20eSAndy Ritger  *
151739a20eSAndy Ritger  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
161739a20eSAndy Ritger  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
171739a20eSAndy Ritger  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
181739a20eSAndy Ritger  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
191739a20eSAndy Ritger  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
201739a20eSAndy Ritger  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
211739a20eSAndy Ritger  * DEALINGS IN THE SOFTWARE.
221739a20eSAndy Ritger  */
231739a20eSAndy Ritger 
241739a20eSAndy Ritger #include "common_nvswitch.h"
251739a20eSAndy Ritger 
261739a20eSAndy Ritger #include "flcn/flcn_nvswitch.h"
271739a20eSAndy Ritger #include "flcn/flcnable_nvswitch.h"
281739a20eSAndy Ritger 
291739a20eSAndy Ritger static void flcnSetupIpHal(nvswitch_device *device, PFLCN pFlcn);
301739a20eSAndy Ritger 
311739a20eSAndy Ritger /*!
321739a20eSAndy Ritger  * @brief   Get the falcon core revision and subversion.
331739a20eSAndy Ritger  *
341739a20eSAndy Ritger  * @param[in]   device  nvswitch device pointer
351739a20eSAndy Ritger  * @param[in]   pFlcn   FLCN object pointer
361739a20eSAndy Ritger  *
371739a20eSAndy Ritger  * @return the falcon core revision in the format of NV_FLCN_CORE_REV_X_Y.
381739a20eSAndy Ritger  */
391739a20eSAndy Ritger static NvU8
_flcnCoreRevisionGet_IMPL(nvswitch_device * device,PFLCN pFlcn)401739a20eSAndy Ritger _flcnCoreRevisionGet_IMPL
411739a20eSAndy Ritger (
421739a20eSAndy Ritger     nvswitch_device *device,
431739a20eSAndy Ritger     PFLCN            pFlcn
441739a20eSAndy Ritger )
451739a20eSAndy Ritger {
461739a20eSAndy Ritger     if (pFlcn->coreRev == 0x00)
471739a20eSAndy Ritger     {
481739a20eSAndy Ritger         // Falcon core revision has not yet been set.  Set it now.
491739a20eSAndy Ritger         flcnGetCoreInfo_HAL(device, pFlcn);
501739a20eSAndy Ritger     }
511739a20eSAndy Ritger 
521739a20eSAndy Ritger     return pFlcn->coreRev;
531739a20eSAndy Ritger }
541739a20eSAndy Ritger 
551739a20eSAndy Ritger /*!
561739a20eSAndy Ritger  *  @brief Mark the falcon as not ready and inaccessible from RM.
571739a20eSAndy Ritger  *  osHandleGpuSurpriseRemoval will use this routine to prevent access to the
581739a20eSAndy Ritger  *  Falcon, which could crash due to absense of GPU, during driver cleanup.
591739a20eSAndy Ritger  *
601739a20eSAndy Ritger  *  @param[in] device nvswitch_device pointer
611739a20eSAndy Ritger  *  @param[in] pFlcn  FLCN pointer
621739a20eSAndy Ritger  *
631739a20eSAndy Ritger  *  @returns nothing
641739a20eSAndy Ritger  */
651739a20eSAndy Ritger static void
_flcnMarkNotReady_IMPL(nvswitch_device * device,PFLCN pFlcn)661739a20eSAndy Ritger _flcnMarkNotReady_IMPL
671739a20eSAndy Ritger (
681739a20eSAndy Ritger     nvswitch_device *device,
691739a20eSAndy Ritger     PFLCN            pFlcn
701739a20eSAndy Ritger )
711739a20eSAndy Ritger {
721739a20eSAndy Ritger     pFlcn->bOSReady = NV_FALSE;
731739a20eSAndy Ritger }
741739a20eSAndy Ritger 
751739a20eSAndy Ritger /*!
761739a20eSAndy Ritger  * Retrieves the current head pointer for given physical command queue index.
771739a20eSAndy Ritger  *
781739a20eSAndy Ritger  * @param[in]   device  nvswitch device pointer
791739a20eSAndy Ritger  * @param[in]   pFlcn   FLCN object pointer
801739a20eSAndy Ritger  * @param[in]   pQueue  Pointer to the queue
811739a20eSAndy Ritger  * @param[out]  pHead   Pointer to write with the queue's head pointer
821739a20eSAndy Ritger  *
831739a20eSAndy Ritger  * @return 'NV_OK' if head value was successfully retrieved.
841739a20eSAndy Ritger  */
851739a20eSAndy Ritger static NV_STATUS
_flcnCmdQueueHeadGet_IMPL(nvswitch_device * device,PFLCN pFlcn,FLCNQUEUE * pQueue,NvU32 * pHead)861739a20eSAndy Ritger _flcnCmdQueueHeadGet_IMPL
871739a20eSAndy Ritger (
881739a20eSAndy Ritger     nvswitch_device *device,
891739a20eSAndy Ritger     PFLCN            pFlcn,
901739a20eSAndy Ritger     FLCNQUEUE       *pQueue,
911739a20eSAndy Ritger     NvU32           *pHead
921739a20eSAndy Ritger )
931739a20eSAndy Ritger {
941739a20eSAndy Ritger     PFALCON_QUEUE_INFO  pQueueInfo = pFlcn->pQueueInfo;
951739a20eSAndy Ritger 
961739a20eSAndy Ritger     NVSWITCH_ASSERT(pQueueInfo != NULL);
971739a20eSAndy Ritger     NVSWITCH_ASSERT(pQueue->queuePhyId < pQueueInfo->cmdQHeadSize);
981739a20eSAndy Ritger     NVSWITCH_ASSERT(pHead != NULL);
991739a20eSAndy Ritger 
1001739a20eSAndy Ritger     *pHead = flcnRegRead_HAL(device, pFlcn,
1011739a20eSAndy Ritger                                     (pQueueInfo->cmdQHeadBaseAddress +
1021739a20eSAndy Ritger                                     (pQueue->queuePhyId * pQueueInfo->cmdQHeadStride)));
1031739a20eSAndy Ritger     return NV_OK;
1041739a20eSAndy Ritger }
1051739a20eSAndy Ritger 
1061739a20eSAndy Ritger /*!
1071739a20eSAndy Ritger  * Sets the head pointer for the given physical command queue index.
1081739a20eSAndy Ritger  *
1091739a20eSAndy Ritger  * @param[in]  device  nvswitch device pointer
1101739a20eSAndy Ritger  * @param[in]  pFlcn   FLCN object pointer
1111739a20eSAndy Ritger  * @param[in]  pQueue  Pointer to the queue
1121739a20eSAndy Ritger  * @param[in]  head    The desired head value for the queue
1131739a20eSAndy Ritger  *
1141739a20eSAndy Ritger  * @return 'NV_OK' if the head value was successfully set.
1151739a20eSAndy Ritger  */
1161739a20eSAndy Ritger static NV_STATUS
_flcnCmdQueueHeadSet_IMPL(nvswitch_device * device,PFLCN pFlcn,FLCNQUEUE * pQueue,NvU32 head)1171739a20eSAndy Ritger _flcnCmdQueueHeadSet_IMPL
1181739a20eSAndy Ritger (
1191739a20eSAndy Ritger     nvswitch_device *device,
1201739a20eSAndy Ritger     PFLCN            pFlcn,
1211739a20eSAndy Ritger     FLCNQUEUE       *pQueue,
1221739a20eSAndy Ritger     NvU32            head
1231739a20eSAndy Ritger )
1241739a20eSAndy Ritger {
1251739a20eSAndy Ritger     PFALCON_QUEUE_INFO  pQueueInfo = pFlcn->pQueueInfo;
1261739a20eSAndy Ritger 
1271739a20eSAndy Ritger     NVSWITCH_ASSERT(pQueueInfo != NULL);
1281739a20eSAndy Ritger     NVSWITCH_ASSERT(pQueue->queuePhyId < pQueueInfo->cmdQHeadSize);
1291739a20eSAndy Ritger 
1301739a20eSAndy Ritger     flcnRegWrite_HAL(device, pFlcn,
1311739a20eSAndy Ritger                             (pQueueInfo->cmdQHeadBaseAddress +
1321739a20eSAndy Ritger                             (pQueue->queuePhyId * pQueueInfo->cmdQHeadStride)),
1331739a20eSAndy Ritger                             head);
1341739a20eSAndy Ritger     return NV_OK;
1351739a20eSAndy Ritger }
1361739a20eSAndy Ritger 
1371739a20eSAndy Ritger /*!
1381739a20eSAndy Ritger  * Retrieves the current tail pointer for given physical command queue index.
1391739a20eSAndy Ritger  *
1401739a20eSAndy Ritger  * @param[in]   device  nvswitch device pointer
1411739a20eSAndy Ritger  * @param[in]   pFlcn   FLCN object pointer
1421739a20eSAndy Ritger  * @param[in]   pQueue  Pointer to the queue
1431739a20eSAndy Ritger  * @param[out]  pTail   Pointer to write with the queue's tail value
1441739a20eSAndy Ritger  *
1451739a20eSAndy Ritger  * @return 'NV_OK' if the tail value was successfully retrieved.
1461739a20eSAndy Ritger  */
1471739a20eSAndy Ritger static NV_STATUS
_flcnCmdQueueTailGet_IMPL(nvswitch_device * device,PFLCN pFlcn,FLCNQUEUE * pQueue,NvU32 * pTail)1481739a20eSAndy Ritger _flcnCmdQueueTailGet_IMPL
1491739a20eSAndy Ritger (
1501739a20eSAndy Ritger     nvswitch_device *device,
1511739a20eSAndy Ritger     PFLCN            pFlcn,
1521739a20eSAndy Ritger     FLCNQUEUE       *pQueue,
1531739a20eSAndy Ritger     NvU32           *pTail
1541739a20eSAndy Ritger )
1551739a20eSAndy Ritger {
1561739a20eSAndy Ritger     PFALCON_QUEUE_INFO  pQueueInfo = pFlcn->pQueueInfo;
1571739a20eSAndy Ritger 
1581739a20eSAndy Ritger     NVSWITCH_ASSERT(pQueueInfo != NULL);
1591739a20eSAndy Ritger     NVSWITCH_ASSERT(pQueue->queuePhyId < pQueueInfo->cmdQTailSize);
1601739a20eSAndy Ritger     NVSWITCH_ASSERT(pTail != NULL);
1611739a20eSAndy Ritger 
1621739a20eSAndy Ritger     *pTail = flcnRegRead_HAL(device, pFlcn,
1631739a20eSAndy Ritger                                     (pQueueInfo->cmdQTailBaseAddress +
1641739a20eSAndy Ritger                                     (pQueue->queuePhyId * pQueueInfo->cmdQTailStride)));
1651739a20eSAndy Ritger     return NV_OK;
1661739a20eSAndy Ritger }
1671739a20eSAndy Ritger 
1681739a20eSAndy Ritger /*!
1691739a20eSAndy Ritger  * Set the Command Queue tail pointer.
1701739a20eSAndy Ritger  *
1711739a20eSAndy Ritger  * @param[in]  device  nvswitch device pointer
1721739a20eSAndy Ritger  * @param[in]  pFlcn   FLCN object pointer
1731739a20eSAndy Ritger  * @param[in]  pQueue  Pointer to the queue
1741739a20eSAndy Ritger  * @param[in]  tail    The desired tail value
1751739a20eSAndy Ritger  *
1761739a20eSAndy Ritger  * @return 'NV_OK' if the tail value was successfully set.
1771739a20eSAndy Ritger  */
1781739a20eSAndy Ritger static NV_STATUS
_flcnCmdQueueTailSet_IMPL(nvswitch_device * device,PFLCN pFlcn,FLCNQUEUE * pQueue,NvU32 tail)1791739a20eSAndy Ritger _flcnCmdQueueTailSet_IMPL
1801739a20eSAndy Ritger (
1811739a20eSAndy Ritger     nvswitch_device *device,
1821739a20eSAndy Ritger     PFLCN            pFlcn,
1831739a20eSAndy Ritger     FLCNQUEUE       *pQueue,
1841739a20eSAndy Ritger     NvU32            tail
1851739a20eSAndy Ritger )
1861739a20eSAndy Ritger {
1871739a20eSAndy Ritger     PFALCON_QUEUE_INFO  pQueueInfo = pFlcn->pQueueInfo;
1881739a20eSAndy Ritger 
1891739a20eSAndy Ritger     NVSWITCH_ASSERT(pQueueInfo != NULL);
1901739a20eSAndy Ritger     NVSWITCH_ASSERT(pQueue->queuePhyId < pQueueInfo->cmdQTailSize);
1911739a20eSAndy Ritger 
1921739a20eSAndy Ritger     flcnRegWrite_HAL(device, pFlcn,
1931739a20eSAndy Ritger                             (pQueueInfo->cmdQTailBaseAddress +
1941739a20eSAndy Ritger                             (pQueue->queuePhyId * pQueueInfo->cmdQTailStride)),
1951739a20eSAndy Ritger                             tail);
1961739a20eSAndy Ritger     return NV_OK;
1971739a20eSAndy Ritger }
1981739a20eSAndy Ritger 
1991739a20eSAndy Ritger /*!
2001739a20eSAndy Ritger  * Retrieve the current Message Queue Head pointer.
2011739a20eSAndy Ritger  *
2021739a20eSAndy Ritger  * @param[in]  device  nvswitch device pointer
2031739a20eSAndy Ritger  * @param[in]  pFlcn   FLCN object pointer
2041739a20eSAndy Ritger  * @param[in]  pQueue  Pointer to the queue
2051739a20eSAndy Ritger  * @param[in]  pHead   Pointer to write with the queue's head value
2061739a20eSAndy Ritger  *
2071739a20eSAndy Ritger  * @return 'NV_OK' if the queue's head value was successfully retrieved.
2081739a20eSAndy Ritger  */
2091739a20eSAndy Ritger static NV_STATUS
_flcnMsgQueueHeadGet_IMPL(nvswitch_device * device,PFLCN pFlcn,FLCNQUEUE * pQueue,NvU32 * pHead)2101739a20eSAndy Ritger _flcnMsgQueueHeadGet_IMPL
2111739a20eSAndy Ritger (
2121739a20eSAndy Ritger     nvswitch_device *device,
2131739a20eSAndy Ritger     PFLCN            pFlcn,
2141739a20eSAndy Ritger     FLCNQUEUE       *pQueue,
2151739a20eSAndy Ritger     NvU32           *pHead
2161739a20eSAndy Ritger )
2171739a20eSAndy Ritger {
2181739a20eSAndy Ritger     PFALCON_QUEUE_INFO  pQueueInfo = pFlcn->pQueueInfo;
2191739a20eSAndy Ritger 
2201739a20eSAndy Ritger     NVSWITCH_ASSERT(pQueueInfo != NULL);
2211739a20eSAndy Ritger     NVSWITCH_ASSERT(pQueue->queuePhyId < pQueueInfo->msgQHeadSize);
2221739a20eSAndy Ritger     NVSWITCH_ASSERT(pHead != NULL);
2231739a20eSAndy Ritger 
2241739a20eSAndy Ritger     *pHead = flcnRegRead_HAL(device, pFlcn,
2251739a20eSAndy Ritger                                     (pQueueInfo->msgQHeadBaseAddress +
2261739a20eSAndy Ritger                                     (pQueue->queuePhyId * pQueueInfo->msgQHeadStride)));
2271739a20eSAndy Ritger     return NV_OK;
2281739a20eSAndy Ritger }
2291739a20eSAndy Ritger 
2301739a20eSAndy Ritger /*!
2311739a20eSAndy Ritger  * Set the Message Queue Head pointer.
2321739a20eSAndy Ritger  *
2331739a20eSAndy Ritger  * @param[in]  device  nvswitch device pointer
2341739a20eSAndy Ritger  * @param[in]  pFlcn   FLCN object pointer
2351739a20eSAndy Ritger  * @param[in]  pQueue  Pointer to the queue
2361739a20eSAndy Ritger  * @param[in]  head    The desired head value
2371739a20eSAndy Ritger  *
2381739a20eSAndy Ritger  * @return 'NV_OK' if the head value was successfully set.
2391739a20eSAndy Ritger  */
2401739a20eSAndy Ritger static NV_STATUS
_flcnMsgQueueHeadSet_IMPL(nvswitch_device * device,PFLCN pFlcn,FLCNQUEUE * pQueue,NvU32 head)2411739a20eSAndy Ritger _flcnMsgQueueHeadSet_IMPL
2421739a20eSAndy Ritger (
2431739a20eSAndy Ritger     nvswitch_device *device,
2441739a20eSAndy Ritger     PFLCN            pFlcn,
2451739a20eSAndy Ritger     FLCNQUEUE       *pQueue,
2461739a20eSAndy Ritger     NvU32            head
2471739a20eSAndy Ritger )
2481739a20eSAndy Ritger {
2491739a20eSAndy Ritger     PFALCON_QUEUE_INFO  pQueueInfo = pFlcn->pQueueInfo;
2501739a20eSAndy Ritger 
2511739a20eSAndy Ritger     NVSWITCH_ASSERT(pQueueInfo != NULL);
2521739a20eSAndy Ritger     NVSWITCH_ASSERT(pQueue->queuePhyId < pQueueInfo->msgQHeadSize);
2531739a20eSAndy Ritger 
2541739a20eSAndy Ritger     flcnRegWrite_HAL(device, pFlcn,
2551739a20eSAndy Ritger                             (pQueueInfo->msgQHeadBaseAddress +
2561739a20eSAndy Ritger                             (pQueue->queuePhyId * pQueueInfo->msgQHeadStride)),
2571739a20eSAndy Ritger                             head);
2581739a20eSAndy Ritger     return NV_OK;
2591739a20eSAndy Ritger }
2601739a20eSAndy Ritger 
2611739a20eSAndy Ritger /*!
2621739a20eSAndy Ritger  * Retrieve the current Message Queue Tail pointer.
2631739a20eSAndy Ritger  *
2641739a20eSAndy Ritger  * @param[in]   device  nvswitch device pointer
2651739a20eSAndy Ritger  * @param[in]   pFlcn   FLCN object pointer
2661739a20eSAndy Ritger  * @param[in]   pQueue  Pointer to the queue
2671739a20eSAndy Ritger  * @param[out]  pTail   Pointer to write with the message queue's tail value
2681739a20eSAndy Ritger  *
2691739a20eSAndy Ritger  * @return 'NV_OK' if the tail value was successfully retrieved.
2701739a20eSAndy Ritger  */
2711739a20eSAndy Ritger static NV_STATUS
_flcnMsgQueueTailGet_IMPL(nvswitch_device * device,PFLCN pFlcn,FLCNQUEUE * pQueue,NvU32 * pTail)2721739a20eSAndy Ritger _flcnMsgQueueTailGet_IMPL
2731739a20eSAndy Ritger (
2741739a20eSAndy Ritger     nvswitch_device *device,
2751739a20eSAndy Ritger     PFLCN            pFlcn,
2761739a20eSAndy Ritger     FLCNQUEUE       *pQueue,
2771739a20eSAndy Ritger     NvU32           *pTail
2781739a20eSAndy Ritger )
2791739a20eSAndy Ritger {
2801739a20eSAndy Ritger     PFALCON_QUEUE_INFO  pQueueInfo = pFlcn->pQueueInfo;
2811739a20eSAndy Ritger 
2821739a20eSAndy Ritger     NVSWITCH_ASSERT(pQueueInfo != NULL);
2831739a20eSAndy Ritger     NVSWITCH_ASSERT(pQueue->queuePhyId < pQueueInfo->msgQTailSize);
2841739a20eSAndy Ritger     NVSWITCH_ASSERT(pTail != NULL);
2851739a20eSAndy Ritger 
2861739a20eSAndy Ritger     *pTail = flcnRegRead_HAL(device, pFlcn,
2871739a20eSAndy Ritger                                     (pQueueInfo->msgQTailBaseAddress +
2881739a20eSAndy Ritger                                     (pQueue->queuePhyId * pQueueInfo->msgQTailStride)));
2891739a20eSAndy Ritger     return NV_OK;
2901739a20eSAndy Ritger }
2911739a20eSAndy Ritger 
2921739a20eSAndy Ritger /*!
2931739a20eSAndy Ritger  * Set the Message Queue Tail pointer.
2941739a20eSAndy Ritger  *
2951739a20eSAndy Ritger  * @param[in]  device  nvswitch device pointer
2961739a20eSAndy Ritger  * @param[in]  pFlcn   FLCN object pointer
2971739a20eSAndy Ritger  * @param[in]  pQueue  Pointer to the queue
2981739a20eSAndy Ritger  * @param[in]  tail    The desired tail value for the message queue
2991739a20eSAndy Ritger  *
3001739a20eSAndy Ritger  * @return 'NV_OK' if the tail value was successfully set.
3011739a20eSAndy Ritger  */
3021739a20eSAndy Ritger static NV_STATUS
_flcnMsgQueueTailSet_IMPL(nvswitch_device * device,PFLCN pFlcn,FLCNQUEUE * pQueue,NvU32 tail)3031739a20eSAndy Ritger _flcnMsgQueueTailSet_IMPL
3041739a20eSAndy Ritger (
3051739a20eSAndy Ritger     nvswitch_device *device,
3061739a20eSAndy Ritger     PFLCN            pFlcn,
3071739a20eSAndy Ritger     FLCNQUEUE       *pQueue,
3081739a20eSAndy Ritger     NvU32            tail
3091739a20eSAndy Ritger )
3101739a20eSAndy Ritger {
3111739a20eSAndy Ritger     PFALCON_QUEUE_INFO  pQueueInfo = pFlcn->pQueueInfo;
3121739a20eSAndy Ritger 
3131739a20eSAndy Ritger     NVSWITCH_ASSERT(pQueueInfo != NULL);
3141739a20eSAndy Ritger     NVSWITCH_ASSERT(pQueue->queuePhyId < pQueueInfo->msgQTailSize);
3151739a20eSAndy Ritger 
3161739a20eSAndy Ritger     flcnRegWrite_HAL(device, pFlcn,
3171739a20eSAndy Ritger                             (pQueueInfo->msgQTailBaseAddress +
3181739a20eSAndy Ritger                             (pQueue->queuePhyId * pQueueInfo->msgQTailStride)),
3191739a20eSAndy Ritger                             tail);
3201739a20eSAndy Ritger     return NV_OK;
3211739a20eSAndy Ritger }
3221739a20eSAndy Ritger 
3231739a20eSAndy Ritger /*!
3241739a20eSAndy Ritger  * Copies 'sizeBytes' from DMEM offset 'src' to 'pDst' using DMEM access
3251739a20eSAndy Ritger  * port 'port'.
3261739a20eSAndy Ritger  *
3271739a20eSAndy Ritger  * @param[in]   device     nvswitch device pointer
3281739a20eSAndy Ritger  * @param[in]   pFlcn      FLCN pointer
3291739a20eSAndy Ritger  * @param[in]   src        The DMEM offset for the source of the copy
3301739a20eSAndy Ritger  * @param[out]  pDst       Pointer to write with copied data from DMEM
3311739a20eSAndy Ritger  * @param[in]   sizeBytes  The number of bytes to copy from DMEM
3321739a20eSAndy Ritger  * @param[in]   port       The DMEM port index to use when accessing the DMEM
3331739a20eSAndy Ritger  */
3341739a20eSAndy Ritger static NV_STATUS
_flcnDmemCopyFrom_IMPL(nvswitch_device * device,PFLCN pFlcn,NvU32 src,NvU8 * pDst,NvU32 sizeBytes,NvU8 port)3351739a20eSAndy Ritger _flcnDmemCopyFrom_IMPL
3361739a20eSAndy Ritger (
3371739a20eSAndy Ritger     nvswitch_device *device,
3381739a20eSAndy Ritger     PFLCN            pFlcn,
3391739a20eSAndy Ritger     NvU32            src,
3401739a20eSAndy Ritger     NvU8            *pDst,
3411739a20eSAndy Ritger     NvU32            sizeBytes,
3421739a20eSAndy Ritger     NvU8             port
3431739a20eSAndy Ritger )
3441739a20eSAndy Ritger {
3451739a20eSAndy Ritger     return flcnDmemTransfer_HAL(device, pFlcn,
3461739a20eSAndy Ritger                                 src, pDst, sizeBytes, port,
3471739a20eSAndy Ritger                                 NV_TRUE);                   // bCopyFrom
3481739a20eSAndy Ritger }
3491739a20eSAndy Ritger 
3501739a20eSAndy Ritger /*!
3511739a20eSAndy Ritger  * Copies 'sizeBytes' from 'pDst' to DMEM offset 'dst' using DMEM access port
3521739a20eSAndy Ritger  * 'port'.
3531739a20eSAndy Ritger  *
3541739a20eSAndy Ritger  * @param[in]  device     nvswitch device pointer
3551739a20eSAndy Ritger  * @param[in]  pFlcn      FLCN pointer
3561739a20eSAndy Ritger  * @param[in]  dst        The destination DMEM offset for the copy
3571739a20eSAndy Ritger  * @param[in]  pSrc       The pointer to the buffer containing the data to copy
3581739a20eSAndy Ritger  * @param[in]  sizeBytes  The number of bytes to copy into DMEM
3591739a20eSAndy Ritger  * @param[in]  port       The DMEM port index to use when accessing the DMEM
3601739a20eSAndy Ritger  */
3611739a20eSAndy Ritger static NV_STATUS
_flcnDmemCopyTo_IMPL(nvswitch_device * device,PFLCN pFlcn,NvU32 dst,NvU8 * pSrc,NvU32 sizeBytes,NvU8 port)3621739a20eSAndy Ritger _flcnDmemCopyTo_IMPL
3631739a20eSAndy Ritger (
3641739a20eSAndy Ritger     nvswitch_device *device,
3651739a20eSAndy Ritger     PFLCN            pFlcn,
3661739a20eSAndy Ritger     NvU32            dst,
3671739a20eSAndy Ritger     NvU8            *pSrc,
3681739a20eSAndy Ritger     NvU32            sizeBytes,
3691739a20eSAndy Ritger     NvU8             port
3701739a20eSAndy Ritger )
3711739a20eSAndy Ritger {
3721739a20eSAndy Ritger     return flcnDmemTransfer_HAL(device, pFlcn,
3731739a20eSAndy Ritger                                 dst, pSrc, sizeBytes, port,
3741739a20eSAndy Ritger                                 NV_FALSE);                  // bCopyFrom
3751739a20eSAndy Ritger }
3761739a20eSAndy Ritger 
3771739a20eSAndy Ritger static void
_flcnPostDiscoveryInit_IMPL(nvswitch_device * device,FLCN * pFlcn)3781739a20eSAndy Ritger _flcnPostDiscoveryInit_IMPL
3791739a20eSAndy Ritger (
3801739a20eSAndy Ritger     nvswitch_device    *device,
3811739a20eSAndy Ritger     FLCN               *pFlcn
3821739a20eSAndy Ritger )
3831739a20eSAndy Ritger {
3841739a20eSAndy Ritger     flcnableFetchEngines_HAL(device, pFlcn->pFlcnable, &pFlcn->engDescUc, &pFlcn->engDescBc);
3851739a20eSAndy Ritger 
3861739a20eSAndy Ritger     flcnSetupIpHal(device, pFlcn);
3871739a20eSAndy Ritger }
3881739a20eSAndy Ritger 
3891739a20eSAndy Ritger /* -------------------- Object construction/initialization ------------------- */
3901739a20eSAndy Ritger 
3911739a20eSAndy Ritger /**
3921739a20eSAndy Ritger  * @brief   set hal object-interface function pointers to flcn implementations
3931739a20eSAndy Ritger  *
3941739a20eSAndy Ritger  * this function has to be at the end of the file so that all the
3951739a20eSAndy Ritger  * other functions are already defined.
3961739a20eSAndy Ritger  *
3971739a20eSAndy Ritger  * @param[in] pFlcn   The flcn for which to set hals
3981739a20eSAndy Ritger  */
3991739a20eSAndy Ritger static void
flcnSetupHal(PFLCN pFlcn,NvU32 pci_device_id)4001739a20eSAndy Ritger flcnSetupHal
4011739a20eSAndy Ritger (
4021739a20eSAndy Ritger     PFLCN pFlcn,
4031739a20eSAndy Ritger     NvU32 pci_device_id
4041739a20eSAndy Ritger )
4051739a20eSAndy Ritger {
4061739a20eSAndy Ritger     flcn_hal *pHal = NULL;
4071739a20eSAndy Ritger     if (nvswitch_is_lr10_device_id(pci_device_id))
4081739a20eSAndy Ritger     {
4091739a20eSAndy Ritger         flcnSetupHal_LR10(pFlcn);
4101739a20eSAndy Ritger         goto _flcnSetupHal_success;
4111739a20eSAndy Ritger     }
412*758b4ee8SAndy Ritger     if (nvswitch_is_ls10_device_id(pci_device_id))
413*758b4ee8SAndy Ritger     {
414*758b4ee8SAndy Ritger         flcnSetupHal_LS10(pFlcn);
415*758b4ee8SAndy Ritger         goto _flcnSetupHal_success;
416*758b4ee8SAndy Ritger     }
4171739a20eSAndy Ritger 
4181739a20eSAndy Ritger     NVSWITCH_PRINT(NULL, ERROR,
4191739a20eSAndy Ritger         "Flcn hal can't be setup due to unknown device id\n");
4201739a20eSAndy Ritger     NVSWITCH_ASSERT(0);
4211739a20eSAndy Ritger 
4221739a20eSAndy Ritger _flcnSetupHal_success:
4231739a20eSAndy Ritger     //init hal OBJ Interfaces
4241739a20eSAndy Ritger     pHal = pFlcn->pHal;
4251739a20eSAndy Ritger 
4261739a20eSAndy Ritger     pHal->coreRevisionGet         = _flcnCoreRevisionGet_IMPL;
4271739a20eSAndy Ritger     pHal->markNotReady            = _flcnMarkNotReady_IMPL;
4281739a20eSAndy Ritger     pHal->cmdQueueHeadGet         = _flcnCmdQueueHeadGet_IMPL;
4291739a20eSAndy Ritger     pHal->msgQueueHeadGet         = _flcnMsgQueueHeadGet_IMPL;
4301739a20eSAndy Ritger     pHal->cmdQueueTailGet         = _flcnCmdQueueTailGet_IMPL;
4311739a20eSAndy Ritger     pHal->msgQueueTailGet         = _flcnMsgQueueTailGet_IMPL;
4321739a20eSAndy Ritger     pHal->cmdQueueHeadSet         = _flcnCmdQueueHeadSet_IMPL;
4331739a20eSAndy Ritger     pHal->msgQueueHeadSet         = _flcnMsgQueueHeadSet_IMPL;
4341739a20eSAndy Ritger     pHal->cmdQueueTailSet         = _flcnCmdQueueTailSet_IMPL;
4351739a20eSAndy Ritger     pHal->msgQueueTailSet         = _flcnMsgQueueTailSet_IMPL;
4361739a20eSAndy Ritger 
4371739a20eSAndy Ritger     pHal->dmemCopyFrom            = _flcnDmemCopyFrom_IMPL;
4381739a20eSAndy Ritger     pHal->dmemCopyTo              = _flcnDmemCopyTo_IMPL;
4391739a20eSAndy Ritger     pHal->postDiscoveryInit       = _flcnPostDiscoveryInit_IMPL;
4401739a20eSAndy Ritger 
4411739a20eSAndy Ritger     flcnQueueSetupHal(pFlcn);
4421739a20eSAndy Ritger     flcnRtosSetupHal(pFlcn);
4431739a20eSAndy Ritger     flcnQueueRdSetupHal(pFlcn);
4441739a20eSAndy Ritger }
4451739a20eSAndy Ritger 
4461739a20eSAndy Ritger static void
flcnSetupIpHal(nvswitch_device * device,PFLCN pFlcn)4471739a20eSAndy Ritger flcnSetupIpHal
4481739a20eSAndy Ritger (
4491739a20eSAndy Ritger     nvswitch_device *device,
4501739a20eSAndy Ritger     PFLCN            pFlcn
4511739a20eSAndy Ritger )
4521739a20eSAndy Ritger {
4531739a20eSAndy Ritger     NvU8 coreRev = flcnableReadCoreRev(device, pFlcn->pFlcnable);
4541739a20eSAndy Ritger 
4551739a20eSAndy Ritger     switch (coreRev) {
4561739a20eSAndy Ritger         case NV_FLCN_CORE_REV_3_0:
4571739a20eSAndy Ritger         {
4581739a20eSAndy Ritger             flcnSetupHal_v03_00(pFlcn);
4591739a20eSAndy Ritger             break;
4601739a20eSAndy Ritger         }
4611739a20eSAndy Ritger         case NV_FLCN_CORE_REV_4_0:
4621739a20eSAndy Ritger         case NV_FLCN_CORE_REV_4_1:
4631739a20eSAndy Ritger         {
4641739a20eSAndy Ritger             flcnSetupHal_v04_00(pFlcn);
4651739a20eSAndy Ritger             break;
4661739a20eSAndy Ritger         }
4671739a20eSAndy Ritger         case NV_FLCN_CORE_REV_5_0:
4681739a20eSAndy Ritger         case NV_FLCN_CORE_REV_5_1:
4691739a20eSAndy Ritger         {
4701739a20eSAndy Ritger             flcnSetupHal_v05_01(pFlcn);
4711739a20eSAndy Ritger             break;
4721739a20eSAndy Ritger         }
4731739a20eSAndy Ritger         case NV_FLCN_CORE_REV_6_0:
4741739a20eSAndy Ritger         {
4751739a20eSAndy Ritger             flcnSetupHal_v06_00(pFlcn);
4761739a20eSAndy Ritger             break;
4771739a20eSAndy Ritger         }
4781739a20eSAndy Ritger         default:
4791739a20eSAndy Ritger         {
4801739a20eSAndy Ritger             NVSWITCH_PRINT(device, ERROR,
4811739a20eSAndy Ritger                 "%s: Unsupported falcon core revision: %hhu!\n",
4821739a20eSAndy Ritger                 __FUNCTION__, coreRev);
4831739a20eSAndy Ritger             NVSWITCH_ASSERT(0);
4841739a20eSAndy Ritger             break;
4851739a20eSAndy Ritger         }
4861739a20eSAndy Ritger     }
4871739a20eSAndy Ritger }
4881739a20eSAndy Ritger 
4891739a20eSAndy Ritger FLCN *
flcnAllocNew(void)4901739a20eSAndy Ritger flcnAllocNew(void)
4911739a20eSAndy Ritger {
4921739a20eSAndy Ritger     FLCN *pFlcn = nvswitch_os_malloc(sizeof(*pFlcn));
4931739a20eSAndy Ritger     if (pFlcn != NULL)
4941739a20eSAndy Ritger     {
4951739a20eSAndy Ritger         nvswitch_os_memset(pFlcn, 0, sizeof(*pFlcn));
4961739a20eSAndy Ritger     }
4971739a20eSAndy Ritger 
4981739a20eSAndy Ritger     return pFlcn;
4991739a20eSAndy Ritger }
5001739a20eSAndy Ritger 
5011739a20eSAndy Ritger NvlStatus
flcnInit(nvswitch_device * device,FLCN * pFlcn,NvU32 pci_device_id)5021739a20eSAndy Ritger flcnInit
5031739a20eSAndy Ritger (
5041739a20eSAndy Ritger     nvswitch_device    *device,
5051739a20eSAndy Ritger     FLCN               *pFlcn,
5061739a20eSAndy Ritger     NvU32               pci_device_id
5071739a20eSAndy Ritger )
5081739a20eSAndy Ritger {
5091739a20eSAndy Ritger     NvlStatus retval = NVL_SUCCESS;
5101739a20eSAndy Ritger 
5111739a20eSAndy Ritger     // allocate hal if a child class hasn't already
5121739a20eSAndy Ritger     if (pFlcn->pHal == NULL)
5131739a20eSAndy Ritger     {
5141739a20eSAndy Ritger         flcn_hal *pHal = pFlcn->pHal = nvswitch_os_malloc(sizeof(*pHal));
5151739a20eSAndy Ritger         if (pHal == NULL)
5161739a20eSAndy Ritger         {
5171739a20eSAndy Ritger             NVSWITCH_PRINT(device, ERROR, "Flcn allocation failed!\n");
5181739a20eSAndy Ritger             retval = -NVL_NO_MEM;
5191739a20eSAndy Ritger             goto flcn_init_fail;
5201739a20eSAndy Ritger         }
5211739a20eSAndy Ritger         nvswitch_os_memset(pHal, 0, sizeof(*pHal));
5221739a20eSAndy Ritger     }
5231739a20eSAndy Ritger 
5241739a20eSAndy Ritger     //don't have a parent class to init, go straight to setupHal
5251739a20eSAndy Ritger     flcnSetupHal(pFlcn, pci_device_id);
5261739a20eSAndy Ritger 
5271739a20eSAndy Ritger     return retval;
5281739a20eSAndy Ritger 
5291739a20eSAndy Ritger flcn_init_fail:
5301739a20eSAndy Ritger     flcnDestroy(device, pFlcn);
5311739a20eSAndy Ritger     return retval;
5321739a20eSAndy Ritger }
5331739a20eSAndy Ritger 
5341739a20eSAndy Ritger // reverse of flcnInit()
5351739a20eSAndy Ritger void
flcnDestroy(nvswitch_device * device,FLCN * pFlcn)5361739a20eSAndy Ritger flcnDestroy
5371739a20eSAndy Ritger (
5381739a20eSAndy Ritger     nvswitch_device    *device,
5391739a20eSAndy Ritger     FLCN               *pFlcn
5401739a20eSAndy Ritger )
5411739a20eSAndy Ritger {
5421739a20eSAndy Ritger     if (pFlcn->pHal != NULL)
5431739a20eSAndy Ritger     {
5441739a20eSAndy Ritger         nvswitch_os_free(pFlcn->pHal);
5451739a20eSAndy Ritger         pFlcn->pHal = NULL;
5461739a20eSAndy Ritger     }
5471739a20eSAndy Ritger }
548