/*
 * Copyright (c) 2013-2014,2016 The Linux Foundation. All rights reserved.
 *
 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
 *
 *
 * Permission to use, copy, modify, and/or distribute this software for
 * any purpose with or without fee is hereby granted, provided that the
 * above copyright notice and this permission notice appear in all
 * copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */

/*
 * This file was originally distributed by Qualcomm Atheros, Inc.
 * under proprietary terms before Copyright ownership was assigned
 * to the Linux Foundation.
 */

#define ATH_MODULE_NAME hif
#include "a_debug.h"

#include <adf_os_types.h>
#include <adf_os_dma.h>
#include <adf_os_timer.h>
#include <adf_os_time.h>
#include <adf_os_lock.h>
#include <adf_os_io.h>
#include <adf_os_mem.h>
#include <adf_os_module.h>
#include <adf_os_util.h>
#include <adf_os_stdtypes.h>
#include <adf_os_defer.h>
#include <adf_os_atomic.h>
#include <adf_nbuf.h>
#include <athdefs.h>
#include <adf_net_types.h>
#include <a_types.h>
#include <athdefs.h>
#include <a_osapi.h>
#include <hif.h>
#include <htc_services.h>
#include "hif_sdio_internal.h"
#include "if_ath_sdio.h"
#include "regtable.h"

/* under HL SDIO, with Interface Memory support, we have the following
 * reasons to support 2 mboxs: a) we need place different buffers in different
 * mempool, for example, data using Interface Memory, desc and other using
 * DRAM, they need different SDIO mbox channels; b) currently, tx mempool in
 * LL case is seperated from main mempool, the structure (descs at the beginning
 * of every pool buffer) is different, because they only need store tx desc from host.
 * To align with LL case, we also need 2 mbox support just as PCIe LL cases.
 */

A_UINT8 HIFDevMapPipeToMailBox(HIF_SDIO_DEVICE *pDev, A_UINT8 pipeid)
{
    // TODO: temp version, should not hardcoded here, will be updated after HIF design
    if (2 == pipeid || 3 == pipeid)
        return 1;
    else if (0 == pipeid || 1 == pipeid)
        return 0;
    else {
        printk("%s:--------------------pipeid=%d,should not happen\n",__func__,pipeid);
        adf_os_assert(0);
        return INVALID_MAILBOX_NUMBER;
    }
}

A_UINT8 HIFDevMapMailBoxToPipe(HIF_SDIO_DEVICE *pDev, A_UINT8 mboxIndex,
        A_BOOL upload)
{
    // TODO: temp version, should not hardcoded here, will be updated after HIF design
    if (mboxIndex == 0) {
        return upload ? 1 : 0;
    } else if (mboxIndex == 1) {
        return upload ? 3 : 2;
    } else {
        printk("%s:--------------------mboxIndex=%d,upload=%d,should not happen\n",__func__,mboxIndex,upload);
        adf_os_assert(0);
        return 0xff;
    }
}

A_STATUS HIFDevMapServiceToPipe(HIF_SDIO_DEVICE *pDev, A_UINT16 ServiceId,
        A_UINT8 *ULPipe, A_UINT8 *DLPipe, A_BOOL SwapMapping)
{
    A_STATUS status = EOK;
    switch (ServiceId) {
    case HTT_DATA_MSG_SVC:
        if (SwapMapping) {
            *ULPipe = 1;
            *DLPipe = 0;
        } else {
            *ULPipe = 3;
            *DLPipe = 2;
        }
        break;

    case HTC_CTRL_RSVD_SVC:
    case HTC_RAW_STREAMS_SVC:
        *ULPipe = 1;
        *DLPipe = 0;
        break;

    case WMI_DATA_BE_SVC:
    case WMI_DATA_BK_SVC:
    case WMI_DATA_VI_SVC:
    case WMI_DATA_VO_SVC:
        *ULPipe = 1;
        *DLPipe = 0;
        break;

    case WMI_CONTROL_SVC:
        if (SwapMapping) {
            *ULPipe = 3;
            *DLPipe = 2;
        } else {
            *ULPipe = 1;
            *DLPipe = 0;
        }
        break;

    default:
        status = !EOK;
        break;
    }
    return status;
}

HTC_PACKET *HIFDevAllocRxBuffer(HIF_SDIO_DEVICE *pDev, size_t length)
{
    HTC_PACKET *pPacket;
    adf_nbuf_t netbuf;
    A_UINT32 bufsize = 0, headsize = 0;

    bufsize = length + HIF_SDIO_RX_DATA_OFFSET;
    headsize = sizeof(HTC_PACKET);
    netbuf = adf_nbuf_alloc(NULL, bufsize + headsize, 0, 4, FALSE);
    if (netbuf == NULL) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                ("(%s)Allocate netbuf failed\n", __FUNCTION__));
        return NULL;
    }
    pPacket = (HTC_PACKET *) adf_nbuf_data(netbuf);
    adf_nbuf_reserve(netbuf, headsize);

    SET_HTC_PACKET_INFO_RX_REFILL(pPacket,
            pDev,
            adf_nbuf_data(netbuf),
            bufsize,
            ENDPOINT_0);
    SET_HTC_PACKET_NET_BUF_CONTEXT(pPacket, netbuf);
    return pPacket;
}

HIF_SDIO_DEVICE* HIFDevCreate(HIF_DEVICE *hif_device,
        MSG_BASED_HIF_CALLBACKS *callbacks,
        void *target)
{

    A_STATUS status;
    HIF_SDIO_DEVICE *pDev;

    pDev = A_MALLOC(sizeof(HIF_SDIO_DEVICE));
    if (!pDev) {
        A_ASSERT(FALSE);
        return NULL;
    }

    A_MEMZERO(pDev, sizeof(HIF_SDIO_DEVICE));
    A_MUTEX_INIT(&pDev->Lock);
    A_MUTEX_INIT(&pDev->TxLock);
    A_MUTEX_INIT(&pDev->RxLock);

    pDev->HIFDevice = hif_device;
    pDev->pTarget = target;
    status = HIFConfigureDevice(hif_device,
            HIF_DEVICE_SET_HTC_CONTEXT,
            (void*) pDev,
            sizeof(pDev));
    if (status != A_OK) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                ("(%s)HIF_DEVICE_SET_HTC_CONTEXT failed!!!\n", __FUNCTION__));
    }

    A_MEMCPY(&pDev->hif_callbacks, callbacks, sizeof(*callbacks));

    return pDev;
}

void HIFDevDestroy(HIF_SDIO_DEVICE *pDev)
{
    A_STATUS status;

    status = HIFConfigureDevice(pDev->HIFDevice,
            HIF_DEVICE_SET_HTC_CONTEXT,
            (void*) NULL,
            0);
    if (status != A_OK) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                ("(%s)HIF_DEVICE_SET_HTC_CONTEXT failed!!!\n", __FUNCTION__));
    }
    A_FREE(pDev);
}

HIF_SDIO_DEVICE *HIFDevFromHIF(HIF_DEVICE *hif_device)
{
    HIF_SDIO_DEVICE *pDev = NULL;
    A_STATUS status;
    status = HIFConfigureDevice(hif_device,
            HIF_DEVICE_GET_HTC_CONTEXT,
            (void**) &pDev,
            sizeof(HIF_SDIO_DEVICE));
    if (status != A_OK) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                ("(%s)HTC_SDIO_CONTEXT is NULL!!!\n", __FUNCTION__));
    }
    return pDev;
}

A_STATUS HIFDevDisableInterrupts(HIF_SDIO_DEVICE *pDev)
{
    MBOX_IRQ_ENABLE_REGISTERS regs;
    A_STATUS    status = A_OK;
    ENTER();

    LOCK_HIF_DEV(pDev);
    /* Disable all interrupts */
    pDev->IrqEnableRegisters.int_status_enable = 0;
    pDev->IrqEnableRegisters.cpu_int_status_enable = 0;
    pDev->IrqEnableRegisters.error_status_enable = 0;
    pDev->IrqEnableRegisters.counter_int_status_enable = 0;
    /* copy into our temp area */
    A_MEMCPY(&regs,
            &pDev->IrqEnableRegisters,
            sizeof(pDev->IrqEnableRegisters));

    UNLOCK_HIF_DEV(pDev);

    /* always synchronous */
    status = HIFReadWrite(pDev->HIFDevice,
            INT_STATUS_ENABLE_ADDRESS,
            (A_UCHAR *)&regs,
            sizeof(MBOX_IRQ_ENABLE_REGISTERS),
            HIF_WR_SYNC_BYTE_INC,
            NULL);

    if (status != A_OK) {
        /* Can't write it for some reason */
        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to update interrupt control registers err: %d", status));
    }

    /* mask the host controller interrupts */
    HIFMaskInterrupt(pDev->HIFDevice);
    EXIT("status :%d",status);
    return status;
}

A_STATUS HIFDevEnableInterrupts(HIF_SDIO_DEVICE *pDev)
{
    A_STATUS status;
    MBOX_IRQ_ENABLE_REGISTERS regs;
    ENTER();


    /* for good measure, make sure interrupt are disabled before unmasking at the HIF
     * layer.
     * The rationale here is that between device insertion (where we clear the interrupts the first time)
     * and when HTC is finally ready to handle interrupts, other software can perform target "soft" resets.
     * The AR6K interrupt enables reset back to an "enabled" state when this happens.
     *  */
    HIFDevDisableInterrupts(pDev);

    /* Unmask the host controller interrupts */
    HIFUnMaskInterrupt(pDev->HIFDevice);

    LOCK_HIF_DEV(pDev);

    /* Enable all the interrupts except for the internal AR6000 CPU interrupt */
    pDev->IrqEnableRegisters.int_status_enable =
            INT_STATUS_ENABLE_ERROR_SET(0x01) | INT_STATUS_ENABLE_CPU_SET(0x01)
                    | INT_STATUS_ENABLE_COUNTER_SET(0x01);

    pDev->IrqEnableRegisters.int_status_enable |=
            INT_STATUS_ENABLE_MBOX_DATA_SET(0x01) | INT_STATUS_ENABLE_MBOX_DATA_SET(0x02); // enable 2 mboxs INT

    /* Set up the CPU Interrupt Status Register, enable CPU sourced interrupt #0, #1
     * #0 is used for report assertion from target
     * #1 is used for inform host that credit arrived
     * */
    pDev->IrqEnableRegisters.cpu_int_status_enable = 0x03;

    /* Set up the Error Interrupt Status Register */
    pDev->IrqEnableRegisters.error_status_enable =
            (ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(0x01)
                    | ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(0x01)) >> 16;

    /* Set up the Counter Interrupt Status Register (only for debug interrupt to catch fatal errors) */
    pDev->IrqEnableRegisters.counter_int_status_enable =
            (COUNTER_INT_STATUS_ENABLE_BIT_SET(AR6K_TARGET_DEBUG_INTR_MASK)) >> 24;

    /* copy into our temp area */
    A_MEMCPY(&regs,
            &pDev->IrqEnableRegisters,
            sizeof(MBOX_IRQ_ENABLE_REGISTERS));

    UNLOCK_HIF_DEV(pDev);


    /* always synchronous */
    status = HIFReadWrite(pDev->HIFDevice,
            INT_STATUS_ENABLE_ADDRESS,
            (A_UCHAR *)&regs,
            sizeof(MBOX_IRQ_ENABLE_REGISTERS),
            HIF_WR_SYNC_BYTE_INC,
            NULL);

    if (status != A_OK) {
        /* Can't write it for some reason */
        AR_DEBUG_PRINTF( ATH_DEBUG_ERR,
                ("Failed to update interrupt control registers err: %d\n", status));

    }
    EXIT();
    return status;
}

A_STATUS HIFDevSetup(HIF_SDIO_DEVICE *pDev)
{
    A_STATUS status;
    A_UINT32 blocksizes[MAILBOX_COUNT];
    HTC_CALLBACKS htcCallbacks;
    HIF_DEVICE *hif_device = pDev->HIFDevice;

    ENTER();

    status = HIFConfigureDevice(hif_device,
            HIF_DEVICE_GET_MBOX_ADDR,
            &pDev->MailBoxInfo,
            sizeof(pDev->MailBoxInfo));

    if (status != A_OK) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                ("(%s)HIF_DEVICE_GET_MBOX_ADDR failed!!!\n", __FUNCTION__));
        A_ASSERT(FALSE);
    }

    status = HIFConfigureDevice(hif_device,
            HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
            blocksizes,
            sizeof(blocksizes));
    if (status != A_OK) {
        AR_DEBUG_PRINTF( ATH_DEBUG_ERR,
                ("(%s)HIF_DEVICE_GET_MBOX_BLOCK_SIZE failed!!!\n", __FUNCTION__));
        A_ASSERT(FALSE);
    }

    pDev->BlockSize = blocksizes[MAILBOX_FOR_BLOCK_SIZE];
    pDev->BlockMask = pDev->BlockSize - 1;
    A_ASSERT((pDev->BlockSize & pDev->BlockMask) == 0);

    /* assume we can process HIF interrupt events asynchronously */
    pDev->HifIRQProcessingMode = HIF_DEVICE_IRQ_ASYNC_SYNC;

    /* see if the HIF layer overrides this assumption */
    HIFConfigureDevice(hif_device,
            HIF_DEVICE_GET_IRQ_PROC_MODE,
            &pDev->HifIRQProcessingMode,
            sizeof(pDev->HifIRQProcessingMode));

    switch (pDev->HifIRQProcessingMode) {
    case HIF_DEVICE_IRQ_SYNC_ONLY:
        AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
                ("HIF Interrupt processing is SYNC ONLY\n"));
        /* see if HIF layer wants HTC to yield */
        HIFConfigureDevice(hif_device,
                HIF_DEVICE_GET_IRQ_YIELD_PARAMS,
                &pDev->HifIRQYieldParams,
                sizeof(pDev->HifIRQYieldParams));

        if (pDev->HifIRQYieldParams.RecvPacketYieldCount > 0) {
            AR_DEBUG_PRINTF( ATH_DEBUG_WARN,
                    ("HIF requests that DSR yield per %d RECV packets \n", pDev->HifIRQYieldParams.RecvPacketYieldCount));
            pDev->DSRCanYield = TRUE;
        }
        break;
    case HIF_DEVICE_IRQ_ASYNC_SYNC:
        AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
                ("HIF Interrupt processing is ASYNC and SYNC\n"));
        break;
    default:
        A_ASSERT(FALSE);
        break;
    }

    pDev->HifMaskUmaskRecvEvent = NULL;

    /* see if the HIF layer implements the mask/unmask recv events function  */
    HIFConfigureDevice(hif_device,
            HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC,
            &pDev->HifMaskUmaskRecvEvent,
            sizeof(pDev->HifMaskUmaskRecvEvent));

    status = HIFDevDisableInterrupts(pDev);

    A_MEMZERO(&htcCallbacks, sizeof(HTC_CALLBACKS));
    /* the device layer handles these */
    htcCallbacks.rwCompletionHandler = HIFDevRWCompletionHandler;
    htcCallbacks.dsrHandler = HIFDevDsrHandler;
    htcCallbacks.context = pDev;
    status = HIFAttachHTC(pDev->HIFDevice, &htcCallbacks);

    EXIT();
    return status;
}

