blob: 6223dc0fd44d0b4a31b7f4fcafa29ad753beb74f [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2018 Synaptics Incorporated */
#include "api_avio_dhub.h"
#include <linux/kernel.h>
#include <asm/bug.h>
HDL_dhub2d AG_dhubHandle;
#define MAX_CONTEXTS 10
struct dhubContext {
HDL_dhub2d *dhubHandle;
DHUB_channel_config *dhubConfig;
};
static struct dhubContext dhubCtx[MAX_CONTEXTS];
static int dhubContextCnt;
static void addDhubContext(HDL_dhub2d * dhubHandle, DHUB_channel_config * dhub_config)
{
int i;
for (i = 0; i < dhubContextCnt; i++) {
if (dhubCtx[i].dhubHandle == dhubHandle) {
return;
}
}
WARN_ON(i > MAX_CONTEXTS);
dhubContextCnt++;
dhubCtx[i].dhubHandle = dhubHandle;
dhubCtx[i].dhubConfig = dhub_config;
}
static DHUB_channel_config * getDhubContext(HDL_dhub2d * dhubHandle)
{
int i;
for (i = 0; i < dhubContextCnt; i++) {
if (dhubCtx[i].dhubHandle == dhubHandle) {
return dhubCtx[i].dhubConfig;
}
}
return NULL;
}
void DhubInitialization_128BytesAXIChannel(HDL_dhub2d * pdhubHandle,
DHUB_channel_config * dhub_config,
UNSG8 uchNumChannels,
UNSG32 uiBcmBuf)
{
}
void DhubInitialization_128BytesAXI(SIGN32 cpuId, UNSG32 dHubBaseAddr,
UNSG32 hboSramAddr,
HDL_dhub2d * pdhubHandle,
DHUB_channel_config * dhub_config,
UNSG8 numOfChans)
{
}
static int getDhubCMDDiv(HDL_dhub2d * pdhubHandle)
{
if (pdhubHandle == &AG_dhubHandle) {
return 8;
}
return 8;
}
/******************************************************************************************************************
* Function: GetChannelInfo
* Description: Get the Dhub configuration of requested channel.
* Parameter : pdhubHandle ----- pointer to 2D dhubHandle
* IChannel ----- Channel of the dhub
* cfg ----- Configuration need to be updated here.
* Return: 0 ---- Success
******************************************************************************************************************/
int getDhubChannelInfo(HDL_dhub2d * pdhubHandle, SIGN32 IChannel,
T32dHubChannel_CFG * cfg)
{
DHUB_channel_config *dhub_config;
//Get the Dhub Config array from the received handle
dhub_config = getDhubContext(pdhubHandle);
if (dhub_config == NULL) {
return 1;
}
//Update the MTU, QOS and self loop paramteres.
cfg->uCFG_MTU = dhub_config[IChannel].chanMtuSize;
cfg->uCFG_QoS = dhub_config[IChannel].chanQos;
cfg->uCFG_selfLoop = dhub_config[IChannel].chanSelfLoop;
return 0;
}
/******************************************************************************************************************
* Function: DhubInitialization
* Description: Initialize DHUB .
* Parameter : cpuId ------------- cpu ID
* dHubBaseAddr ------------- dHub Base address.
* hboSramAddr ----- Sram Address for HBO.
* pdhubHandle ----- pointer to 2D dhubHandle
* dhub_config ----- configuration of AG
* numOfChans ----- number of channels
* Return: void
******************************************************************************************************************/
void DhubInitialization(SIGN32 cpuId, UNSG32 dHubBaseAddr, UNSG32 hboSramAddr,
HDL_dhub2d * pdhubHandle,
DHUB_channel_config * dhub_config, SIGN32 numOfChans,
DHUB_TYPE dHubType)
{
HDL_semaphore *pSemHandle;
SIGN32 i;
SIGN32 chanId;
SIGN32 cmdDiv = 8;
addDhubContext(pdhubHandle, dhub_config);
if (dHubType == DHUB_TYPE_128BIT)
cmdDiv = 16;
else
cmdDiv = getDhubCMDDiv(pdhubHandle);
if (!cmdDiv) {
return;
}
//Initialize HDL_dhub with a $dHub BIU instance.
dhub2d_hdl(hboSramAddr, /*! Base address of dHub.HBO SRAM ! */
dHubBaseAddr, /*! Base address of a BIU instance of $dHub ! */
pdhubHandle /*! Handle to HDL_dhub2d ! */
);
//set up semaphore to trigger cmd done interrupt
//note that this set of semaphores are different from the HBO semaphores
//the ID must match the dhub ID because they are hardwired.
pSemHandle = dhub_semaphore(&pdhubHandle->dhub);
for (i = 0; i < numOfChans; i++) {
//Configurate a dHub channel
//note that in this function, it also configured right HBO channels(cmdQ and dataQ) and semaphores
chanId = dhub_config[i].chanId;
{
dhub_channel_cfg(&pdhubHandle->dhub, /*! Handle to HDL_dhub ! */
chanId, /*! Channel ID in $dHubReg ! */
dhub_config[i].chanCmdBase, //UNSG32 baseCmd, /*! Channel FIFO base address (byte address) for cmdQ !*/
dhub_config[i].chanDataBase, //UNSG32 baseData, /*! Channel FIFO base address (byte address) for dataQ !*/
dhub_config[i].chanCmdSize / cmdDiv, //SIGN32 depthCmd, /*! Channel FIFO depth for cmdQ, in 64b word !*/
dhub_config[i].chanDataSize / cmdDiv, //SIGN32 depthData, /*! Channel FIFO depth for dataQ, in 64b word !*/
dhub_config[i].chanMtuSize, /*! See 'dHubChannel.CFG.MTU', 0/1/2 for 8/32/128 bytes ! */
dhub_config[i].chanQos, /*! See 'dHubChannel.CFG.QoS' ! */
dhub_config[i].chanSelfLoop, /*! See 'dHubChannel.CFG.selfLoop' ! */
dhub_config[i].chanEnable, /*! 0 to disable, 1 to enable ! */
0 /*! Pass NULL to directly init dHub, or
Pass non-zero to receive programming sequence
in (adr,data) pairs
! */
);
// setup interrupt for channel chanId
//configure the semaphore depth to be 1
semaphore_cfg(pSemHandle, chanId, 1, 0);
#if 0
// enable interrupt from this semaphore
semaphore_intr_enable(pSemHandle, // semaphore handler
chanId, 0, // empty
1, // full
0, // almost_empty
0, // almost_full
cpuId // 0~2, depending on which CPU the interrupt is enabled for.
);
#endif
}
}
}
/******************************************************************************************************************
* Function: DhubChannelClear
* Description: Clear corresponding DHUB channel.
* Parameter: hdl ---------- handle to HDL_dhub
* id ---------- channel ID in dHubReg
* cfgQ ---------- pass null to directly init dhub, or pass non-zero to receive programming
* sequence in (adr, data) pairs
* Return: void
******************************************************************************************************************/
void DhubChannelClear(void *hdl, SIGN32 id, T64b cfgQ[])
{
UNSG32 cmdID = dhub_id2hbo_cmdQ(id);
UNSG32 dataID = dhub_id2hbo_data(id);
HDL_dhub *dhub = (HDL_dhub *) hdl;
HDL_hbo *hbo = &(dhub->hbo);
/* 1.Software stops the command queue in HBO (please refer to HBO.sxw for details) */
hbo_queue_enable(hbo, cmdID, 0, cfgQ);
/* 2.Software stops the channel in dHub by writing zero to dHubChannel.START.EN */
dhub_channel_enable(dhub, id, 0, cfgQ);
/* 3.Software clears the channel in dHub by writing one to dHubChannel.CLEAR.EN */
dhub_channel_clear(dhub, id);
/* 4.Software waits for the register bits dHubChannel.PENDING.ST and dHubChannel.BUSY.ST to be 0 */
dhub_channel_clear_done(dhub, id);
/* 5.Software stops and clears the command queue */
hbo_queue_enable(hbo, cmdID, 0, cfgQ);
hbo_queue_clear(hbo, cmdID);
/* 6.Software wait for the corresponding busy bit to be 0 */
hbo_queue_clear_done(hbo, cmdID);
/* 7.Software stops and clears the data queue */
hbo_queue_enable(hbo, dataID, 0, cfgQ);
hbo_queue_clear(hbo, dataID);
/* 8.Software wait for the corresponding data Q busy bit to be 0 */
hbo_queue_clear_done(hbo, dataID);
/* 9.Software enable dHub and HBO */
dhub_channel_enable(dhub, id, 1, cfgQ);
hbo_queue_enable(hbo, cmdID, 1, cfgQ);
hbo_queue_enable(hbo, dataID, 1, cfgQ);
}
#include <linux/export.h>
EXPORT_SYMBOL(DhubInitialization);
EXPORT_SYMBOL(AG_dhubHandle);
EXPORT_SYMBOL(DhubChannelClear);