/*
* @file hv_drv_UsbUtils.c
* @brief Usb Gadget Billboard application.
*
* @author HiView SoC Software Team
* @version 1.0.0
* @date 2022-06-15
*/


/* FreeRTOS kernel includes. */
#include "FreeRTOS.h"
#include "task.h"

#include "hv_drv_UsbMusbCoreDev.h"
#include "hv_vos_Comm.h"

#ifdef CONFIG_USER_USB_BILLBOARD_ON
#include "hv_drv_UsbGadgetBillboard.h"
#include "hv_drv_UsbGadgetFuncBillboard.h"
#endif

/*************************************************************************/
static UCHAR8 s_ucAttachCnt = 0;

static int hv_drv_musb_init(struct musb *musb) 
{
    volatile unsigned int vbusReg = 0;

    pr_debug("-->hv_drv_musb_init\n");
    HAL_W32_MASK(0x11011008,0x3<<19,0x1<<19);
    Hv_Vos_MSleep(200);
    HAL_W32_MASK(0x11011008,0x3<<19,0x3<<19);
    Hv_Vos_MSleep(200);
    HAL_W32(0x11090414,0x82400000);//set IDDIG=0   set pre 

#ifdef CONFIG_USB_LOWSPEED
    HAL_W32(0x110900f4,0x00000001); // ls
    HAL_W32(0x11090000,0x00004000); // suspenM
#endif
#ifdef CONFIG_USB_FULLSPEED
    HAL_W32(0x11090000,0x00004000); // suspenM
#endif
#ifdef CONFIG_USB_HIGHSPEED
    HAL_W32(0x11090000,0x00006000); // suspenM
#endif

    Hv_Vos_MSleep(10);

    HAL_W32(0x11090414,0x81c00000);// set vbusvalid=1,avalid=1,sess=0

    HAL_R32(0x11090060);

    return 0;
}

static int hv_drv_musb_exit(struct musb *musb) 
{
    return 0;
}

static int hv_drv_musb_enable(struct musb *musb)
{
    return 0;
}

static void hv_drv_musb_disable(struct musb *musb)
{
    
}

const struct musb_platform_ops drv_usb_ops = {
    .init       = hv_drv_musb_init,
    .exit       = hv_drv_musb_exit,

    .enable     = hv_drv_musb_enable,
    .disable    = hv_drv_musb_disable,
};


static struct musb_hdrc_config musb_config = {
    .multipoint     = 1,
    .dyn_fifo       = 1,
    .num_eps        = 16,
    .ram_bits       = 12,
};

static struct musb_hdrc_platform_data musb_plat = {
    .mode           = MUSB_PERIPHERAL,
    .config         = &musb_config,
    .power          = 250,
    .platform_ops   = &drv_usb_ops,
    .board_data     = NULL,
};

#ifdef CONFIG_USER_USB_BILLBOARD_ON
int run_usb_billboard_gadget(int usbctrl_index, char *usb_dnl_gadget)
{
    bool dfu_reset = false;
    int ret = 0, i = 0;

    pr_debug("-->run_usb_billboard_gadget\n");
    ret = board_usb_init(usbctrl_index, USB_INIT_DEVICE);
    if (ret) {
        pr_err("board usb init failed\n");
        return -1;
    }
    ret = g_billboard_register(usb_dnl_gadget);//此处为前面传进来的usb_dnl_dfu
    if (ret) {
        pr_err("g_billboard_register failed common/dfu.c\n");
        return -1;
    }
    pr_info("g_billboard_register ok\n");

#ifndef CONFIG_USB_WITH_INTERRUPT
    while (1) {
        usb_gadget_handle_interrupts(usbctrl_index);
    }
exit:
    pr_info("////////////////////dfu exit, dnl_unregister\n");
    g_billboard_unregister();
    board_usb_cleanup(usbctrl_index, USB_INIT_DEVICE);

#endif

    return ret;
}


int Hv_Drv_Usb_RunBillboard(void)
{

    char *usb_controller = 0;

    int ret = 0;

#ifndef CONFIG_USB_WITH_INTERRUPT
    if (ret)
        goto done;
#endif
    ret = 0;
    //int controller_index = simple_strtoul(usb_controller, NULL, 0);
    int controller_index = 0;

    run_usb_billboard_gadget(controller_index, "usb_g_billboard");

#ifndef CONFIG_USB_WITH_INTERRUPT
done:
#endif


    return 0;
}


void Hv_Drv_Usb_BillboardInit(void)
{
    int ret;

    s_ucAttachCnt++;
    ret = musb_register(&musb_plat, NULL, (void *)0xB1090000);
    if (!ret){
        Hv_Drv_Usb_RunBillboard();
    }else {
        pr_info("musb_register(Peripheral) fail\n");
    }

}


void Hv_Drv_Usb_BillboardExit(void)
{
    if(s_ucAttachCnt > 0)
    {
        s_ucAttachCnt--;
        
        //remove musb isr
        musb_unregister();

        //remove g_billboard_driver
        g_billboard_unregister();
    }
    return;
}
#endif

