/*
*******************************************************************************
*                     sw_ohci_hcd_shutdown
*
* Description:
*    void
*
* Parameters:
*    void
*
* Return value:
*    void
*
* note:
*    void
*
*******************************************************************************
*/
void sw_ohci_hcd_shutdown(struct platform_device* pdev)
{
	struct sw_hci_hcd *sw_ohci = NULL;

	sw_ohci = pdev->dev.platform_data;
	if(sw_ohci == NULL){
		DMSG_PANIC("ERR: sw_ohci is null\n");
		return ;
	}

	if(sw_ohci->probe == 0){
    	DMSG_PANIC("ERR: sw_ohci is disable, need not shutdown\n");
    	return ;
	}

 	DMSG_INFO("[%s]: ohci shutdown start\n", sw_ohci->hci_name);

    usb_hcd_platform_shutdown(pdev);

    sw_stop_ohc(sw_ohci);

 	DMSG_INFO("[%s]: ohci shutdown end\n", sw_ohci->hci_name);

    return;
}
/*
*******************************************************************************
*                     sw_ohci_hcd_suspend
*
* Description:
*    void
*
* Parameters:
*    void
*
* Return value:
*    void
*
* note:
*    void
*
*******************************************************************************
*/
static int sw_ohci_hcd_suspend(struct device *dev)
{
	struct sw_hci_hcd *sw_ohci  = NULL;
	struct usb_hcd *hcd         = NULL;
	struct ohci_hcd	*ohci       = NULL;
	unsigned long flags         = 0;
	int rc                      = 0;

	if(dev == NULL){
		DMSG_PANIC("ERR: Argment is invalid\n");
		return 0;
	}

	hcd = dev_get_drvdata(dev);
	if(hcd == NULL){
		DMSG_PANIC("ERR: hcd is null\n");
		return 0;
	}

	sw_ohci = dev->platform_data;
	if(sw_ohci == NULL){
		DMSG_PANIC("ERR: sw_ohci is null\n");
		return 0;
	}

	if(sw_ohci->probe == 0){
		DMSG_PANIC("ERR: sw_ohci is disable, can not suspend\n");
		return 0;
	}

	ohci = hcd_to_ohci(hcd);
	if(ohci == NULL){
		DMSG_PANIC("ERR: ohci is null\n");
		return 0;
	}

 	DMSG_INFO("[%s]: sw_ohci_hcd_suspend\n", sw_ohci->hci_name);

	/* Root hub was already suspended. Disable irq emission and
	 * mark HW unaccessible, bail out if RH has been resumed. Use
	 * the spinlock to properly synchronize with possible pending
	 * RH suspend or resume activity.
	 *
	 * This is still racy as hcd->state is manipulated outside of
	 * any locks =P But that will be a different fix.
	 */
	spin_lock_irqsave(&ohci->lock, flags);

    ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
    (void)ohci_readl(ohci, &ohci->regs->intrdisable);

    clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);

    spin_unlock_irqrestore(&ohci->lock, flags);

    sw_stop_ohc(sw_ohci);

    return rc;
}
static int sw_ohci_hcd_remove(struct platform_device *pdev)
{
	struct usb_hcd *hcd = NULL;
	struct sw_hci_hcd *sw_ohci = NULL;

	if(pdev == NULL){
		DMSG_PANIC("ERR: Argment is invalid\n");
		return -1;
	}

	hcd = platform_get_drvdata(pdev);
	if(hcd == NULL){
		DMSG_PANIC("ERR: hcd is null\n");
		return -1;
	}

	sw_ohci = pdev->dev.platform_data;
	if(sw_ohci == NULL){
		DMSG_PANIC("ERR: sw_ohci is null\n");
		return -1;
	}

	DMSG_INFO("[%s%d]: remove, pdev->name: %s, pdev->id: %d, sw_ohci: 0x%p\n",
		      ohci_name, sw_ohci->usbc_no, pdev->name, pdev->id, sw_ohci);


	usb_remove_hcd(hcd);

	sw_stop_ohc(sw_ohci);
	sw_ohci->probe = 0;

	usb_put_hcd(hcd);

	sw_release_io_resource(pdev, sw_ohci);

	sw_ohci->hcd = NULL;

    if(sw_ohci->host_init_state){
	    g_sw_ohci[sw_ohci->usbc_no] = NULL;
	}

	platform_set_drvdata(pdev, NULL);

	return 0;
}
void sw_ohci_hcd_shutdown(struct platform_device *pdev)
{
	struct sw_hci_hcd *sw_ohci = NULL;

	if (pdev == NULL)
		return;

	sw_ohci = pdev->dev.platform_data;
	if (sw_ohci == NULL)
		return;

	if (sw_ohci->probe == 0)
		return;

	pr_info("[%s]: shutdown start\n", sw_ohci->hci_name);
	usb_hcd_platform_shutdown(pdev);
	sw_stop_ohc(sw_ohci);
	pr_info("[%s]: shutdown end\n", sw_ohci->hci_name);

	return;
}
static int sw_ohci_hcd_remove(struct platform_device *pdev)
{
	struct usb_hcd *hcd = NULL;
	struct sw_hci_hcd *sw_ohci = NULL;

	if (pdev == NULL)
		return -EINVAL;

	hcd = platform_get_drvdata(pdev);
	if (hcd == NULL)
		return -ENODATA;

	sw_ohci = pdev->dev.platform_data;
	if (sw_ohci == NULL)
		return -ENODATA;

	pr_debug("[%s%d]: remove, pdev->name: %s, pdev->id: %d, sw_ohci:"
		" 0x%p\n", SW_OHCI_NAME, sw_ohci->usbc_no, pdev->name, pdev->id,
		sw_ohci);

	usb_remove_hcd(hcd);

	sw_stop_ohc(sw_ohci);
	sw_ohci->probe = 0;

	iounmap(hcd->regs);

	usb_put_hcd(hcd);

	sw_ohci->hcd = NULL;

	if (sw_ohci->host_init_state)
		g_sw_ohci[sw_ohci->usbc_no] = NULL;

	platform_set_drvdata(pdev, NULL);

	return 0;
}