/**
 * flush_qmu - stop qmu and align qmu start ptr t0 current ptr
 * @args - arg1: ep number, arg2: dir
 */
void mu3d_hal_flush_qmu(DEV_INT32 Q_num, USB_DIR dir)
{
	TGPD *gpd_current;

	qmu_printk(K_CRIT, "%s flush QMU %s\n", __func__, ((dir == USB_TX) ? "TX" : "RX"));

	if (dir == USB_TX) {
		/*Stop QMU */
		mu3d_hal_stop_qmu(Q_num, USB_TX);

		/*Get TX Queue Current Pointer Register */
		gpd_current = (TGPD *) (os_readl(USB_QMU_TQCPR(Q_num)));

		/*If gpd_current = 0, it means QMU has not yet to execute GPD in QMU. */
		if (!gpd_current) {
			/*Get TX Queue Starting Address Register */
			gpd_current = (TGPD *) (os_readl(USB_QMU_TQSAR(Q_num)));
		}

		/*Switch physical to virtual address */
		qmu_printk(K_CRIT, "gpd_current(P) %p\n", gpd_current);
		gpd_current = phys_to_virt((unsigned long)gpd_current);
		qmu_printk(K_CRIT, "gpd_current(V) %p\n", (void *)gpd_current);

		/*Reset the TX GPD list state */
		Tx_gpd_end[Q_num] = Tx_gpd_last[Q_num] = gpd_current;
		gpd_ptr_align(dir, Q_num, Tx_gpd_end[Q_num]);
		free_gpd(dir, Q_num);

		/*FIXME: Do not know why... */
		os_writel(USB_QMU_TQSAR(Q_num), virt_to_phys(Tx_gpd_last[Q_num]));
		qmu_printk(K_ERR, "USB_QMU_TQSAR %x\n", os_readl(USB_QMU_TQSAR(Q_num)));
	} else if (dir == USB_RX) {
		/*Stop QMU */
		mu3d_hal_stop_qmu(Q_num, USB_RX);

		/*Get RX Queue Current Pointer Register */
		gpd_current = (TGPD *) (os_readl(USB_QMU_RQCPR(Q_num)));
		if (!gpd_current) {
			/*Get RX Queue Starting Address Register */
			gpd_current = (TGPD *) (os_readl(USB_QMU_RQSAR(Q_num)));
		}

		/*Switch physical to virtual address */
		qmu_printk(K_CRIT, "gpd_current(P) %p\n", gpd_current);
		gpd_current = phys_to_virt((unsigned long)gpd_current);
		qmu_printk(K_CRIT, "gpd_current(V) %p\n", (void *)gpd_current);

		/*Reset the RX GPD list state */
		Rx_gpd_end[Q_num] = Rx_gpd_last[Q_num] = gpd_current;
		gpd_ptr_align(dir, Q_num, Rx_gpd_end[Q_num]);
		free_gpd(dir, Q_num);

		/*FIXME: Do not know why... */
		os_writel(USB_QMU_RQSAR(Q_num), virt_to_phys(Rx_gpd_end[Q_num]));
		qmu_printk(K_ERR, "USB_QMU_RQSAR %x\n", os_readl(USB_QMU_RQSAR(Q_num)));
	}
}
void mu3d_hal_flush_qmu(DEV_INT32 Q_num,  USB_DIR dir)
{
	TGPD* gpd_current;

	struct USB_REQ *req = mu3d_hal_get_req(Q_num, dir);

	os_printk(K_CRIT,"%s flush QMU %s\n", __func__, ((dir==USB_TX)?"TX":"RX"));

	if (dir == USB_TX) {
		/*Stop QMU*/
		mu3d_hal_stop_qmu(Q_num, USB_TX);

		/*Get TX Queue Current Pointer Register*/
		gpd_current = (TGPD*)(uintptr_t)(os_readl(USB_QMU_TQCPR(Q_num))); //QMU GPD address --> CPU DMA address

		/*If gpd_current = 0, it means QMU has not yet to execute GPD in QMU.*/
		if(!gpd_current){
			/*Get TX Queue Starting Address Register*/
			gpd_current = (TGPD*)(uintptr_t)(os_readl(USB_QMU_TQSAR(Q_num))); //QMU GPD address --> CPU DMA address
		}

		/*Switch physical to virtual address*/
		os_printk(K_CRIT,"gpd_current(P) %p\n", gpd_current);
		gpd_current = gpd_phys_to_virt(gpd_current, USB_TX, Q_num);
		os_printk(K_CRIT,"gpd_current(V) %p\n", gpd_current);

		/*Reset the TX GPD list state*/
		Tx_gpd_end[Q_num] = Tx_gpd_last[Q_num] = gpd_current;
		gpd_ptr_align(dir,Q_num,Tx_gpd_end[Q_num]);
		free_gpd(dir,Q_num);

		/*FIXME: Do not know why...*/
		os_writel(USB_QMU_TQSAR(Q_num), mu3d_hal_gpd_virt_to_phys(Tx_gpd_last[Q_num], USB_TX, Q_num));
		os_printk(K_ERR,"USB_QMU_TQSAR %x\n", os_readl(USB_QMU_TQSAR(Q_num)));
		req->complete=true;
		//os_printk(K_ERR,"TxQ %d Flush Now!\n", Q_num);
	} else if(dir == USB_RX) {
		/*Stop QMU*/
		mu3d_hal_stop_qmu(Q_num, USB_RX);

		/*Get RX Queue Current Pointer Register*/
		gpd_current = (TGPD*)(uintptr_t)(os_readl(USB_QMU_RQCPR(Q_num))); //QMU GPD address --> CPU DMA address
		if(!gpd_current){
			/*Get RX Queue Starting Address Register*/
			gpd_current = (TGPD*)(uintptr_t)(os_readl(USB_QMU_RQSAR(Q_num))); //QMU GPD address --> CPU DMA address
		}

		/*Switch physical to virtual address*/
		os_printk(K_CRIT,"gpd_current(P) %p\n", gpd_current);
		gpd_current = gpd_phys_to_virt(gpd_current,USB_RX,Q_num);
		os_printk(K_CRIT,"gpd_current(V) %p\n", gpd_current);

		/*Reset the RX GPD list state*/
		Rx_gpd_end[Q_num] = Rx_gpd_last[Q_num] = gpd_current;
		gpd_ptr_align(dir,Q_num,Rx_gpd_end[Q_num]);
		free_gpd(dir,Q_num);

		/*FIXME: Do not know why...*/
		os_writel(USB_QMU_RQSAR(Q_num), mu3d_hal_gpd_virt_to_phys(Rx_gpd_end[Q_num], USB_RX, Q_num));
		os_printk(K_ERR,"USB_QMU_RQSAR %x\n", os_readl(USB_QMU_RQSAR(Q_num)));
		req->complete=true;
		//os_printk(K_ERR,"RxQ %d Flush Now!\n", Q_num);
	}
}
/**
 * flush_qmu - stop qmu and align qmu start ptr t0 current ptr
 * @args - arg1: ep number, arg2: dir
 */
void _ex_mu3d_hal_flush_qmu(DEV_INT32 Q_num,  USB_DIR dir)
{
	TGPD* gpd_current;

	qmu_printk(K_CRIT, "%s flush QMU %s-EP[%d]\n", __func__, ((dir==USB_TX)?"TX":"RX"), Q_num);

	if (dir == USB_TX) {
		/*Stop QMU*/
		mu3d_hal_stop_qmu(Q_num, USB_TX);

		/*Get TX Queue Current Pointer Register*/
		gpd_current = (TGPD*)(uintptr_t)(os_readl(USB_QMU_TQCPR(Q_num))); //QMU GPD address --> CPU DMA address

		/*If gpd_current = 0, it means QMU has not yet to execute GPD in QMU.*/
		if(!gpd_current){
			/*Get TX Queue Starting Address Register*/
			gpd_current = (TGPD*)(uintptr_t)(os_readl(USB_QMU_TQSAR(Q_num))); //QMU GPD address --> CPU DMA address
		}

		/*
		 * Even if the GPD pointer got from SAR is corrupted. We should use the head of GPD list.
		 * We know that Tx_gpd_head[Q_num] is always correct.
		 */
		if(!gpd_current) {
			gpd_current = Tx_gpd_head[Q_num];
			qmu_printk(K_CRIT, "gpd is null, so use the head of GPD list %p\n", gpd_current);
		} else {
			/*Switch physical to virtual address*/
			qmu_printk(K_CRIT, "gpd_current(P) %p\n", gpd_current);
			gpd_current = gpd_phys_to_virt((void *)gpd_current,USB_TX, Q_num);
			qmu_printk(K_CRIT, "gpd_current(V) %p\n", (void *)gpd_current);
		}

		/*Reset the TX GPD list state*/
		Tx_gpd_end[Q_num] = Tx_gpd_last[Q_num] = gpd_current;
		gpd_ptr_align(dir,Q_num,Tx_gpd_end[Q_num]);
		free_gpd(dir,Q_num);

		/*FIXME: Do not know why...*/
		os_writel(USB_QMU_TQSAR(Q_num), mu3d_hal_gpd_virt_to_phys(Tx_gpd_last[Q_num], USB_TX, Q_num));
		qmu_printk(K_ERR, "USB_QMU_TQSAR %x\n", os_readl(USB_QMU_TQSAR(Q_num)));
	} else if(dir == USB_RX) {
		/*Stop QMU*/
		mu3d_hal_stop_qmu(Q_num, USB_RX);

		/*Get RX Queue Current Pointer Register*/
		gpd_current = (TGPD*)(uintptr_t)(os_readl(USB_QMU_RQCPR(Q_num))); //QMU GPD address --> CPU DMA address
		if(!gpd_current){
			/*Get RX Queue Starting Address Register*/
			gpd_current = (TGPD*)(uintptr_t)(os_readl(USB_QMU_RQSAR(Q_num))); //QMU GPD address --> CPU DMA address
		}

		/*
		 * Even if the GPD pointer got from SAR is corrupted. We should use the head of GPD list.
		 * We know that Rx_gpd_head[Q_num] is always correct.
		 */
		if(!gpd_current) {
			gpd_current = Rx_gpd_head[Q_num];
			qmu_printk(K_CRIT, "gpd is null, so use the head of GPD list %p\n", gpd_current);
		} else {
			/*Switch physical to virtual address*/
			qmu_printk(K_CRIT, "gpd_current(P) %p\n", gpd_current);
			gpd_current = gpd_phys_to_virt((void *)gpd_current, USB_RX, Q_num);
			qmu_printk(K_CRIT, "gpd_current(V) %p\n", (void *)gpd_current);
		}

		/*Reset the RX GPD list state*/
		Rx_gpd_end[Q_num] = Rx_gpd_last[Q_num] = gpd_current;
		gpd_ptr_align(dir,Q_num,Rx_gpd_end[Q_num]);
		free_gpd(dir,Q_num);

		/*FIXME: Do not know why...*/
		os_writel(USB_QMU_RQSAR(Q_num), mu3d_hal_gpd_virt_to_phys(Rx_gpd_end[Q_num], USB_RX, Q_num));
		qmu_printk(K_ERR,"USB_QMU_RQSAR %x\n", os_readl(USB_QMU_RQSAR(Q_num)));
	}
}