return retval;
}
+#ifndef DWC_HOST_ONLY
+extern int rk28_usb_suspend( int exitsuspend );
static int dwc_otg_driver_suspend(struct platform_device *_dev , pm_message_t state )
{
struct device *dev = &_dev->dev;
/* Clear any pending interrupts */
dwc_write_reg32( &core_if->core_global_regs->gintsts, 0xFFFFFFFF);
dwc_otg_disable_global_interrupts(core_if);
+ rk28_usb_suspend(0);
return 0;
}
+#else
+static int dwc_otg_driver_suspend(struct platform_device *_dev , pm_message_t state )
+{
+ return 0;
+}
+#endif
static int dwc_otg_driver_resume(struct platform_device *_dev )
{
return retval;
}
-static int host11_driver_suspend(struct platform_device *_dev , pm_message_t state )
-{
- //struct device *dev = &_dev->dev;
- //dwc_otg_device_t *otg_dev = dev->platform_data;
- //dwc_otg_core_if_t *core_if = otg_dev->core_if;
- return 0;
-}
-
-static int host11_driver_resume(struct platform_device *_dev )
-{
- //struct device *dev = &_dev->dev;
- //dwc_otg_device_t *otg_dev = dev->platform_data;
- //dwc_otg_core_if_t *core_if = otg_dev->core_if;
- return 0;
-}
-
static struct platform_driver host11_driver = {
.probe = host11_driver_probe,
.remove = host11_driver_remove,
- .suspend = host11_driver_suspend,
- .resume = host11_driver_resume,
.driver = {
.name = "usb11_host",
.owner = THIS_MODULE},
return retval;
}
-static int host20_driver_suspend(struct platform_device *_dev , pm_message_t state )
-{
- //struct device *dev = &_dev->dev;
- //dwc_otg_device_t *otg_dev = dev->platform_data;
- //dwc_otg_core_if_t *core_if = otg_dev->core_if;
- return 0;
-}
-
-static int host20_driver_resume(struct platform_device *_dev )
-{
- //struct device *dev = &_dev->dev;
- //dwc_otg_device_t *otg_dev = dev->platform_data;
- //dwc_otg_core_if_t *core_if = otg_dev->core_if;
- return 0;
-}
-
static struct platform_driver host20_driver = {
.probe = host20_driver_probe,
.remove = host20_driver_remove,
- .suspend = host20_driver_suspend,
- .resume = host20_driver_resume,
.driver = {
.name = "usb20_host",
.owner = THIS_MODULE},
* This file contains the implementation of the HCD. In Linux, the HCD
* implements the hc_driver API.
*/
+#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
static int dwc_otg_hcd_suspend(struct usb_hcd *hcd)
{
-#if 1
dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd (hcd);
dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
hprt0_data_t hprt0;
return 0;
}
hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
- DWC_PRINT("%s, HPRT0:0x%x\n",__func__,hprt0.d32);
- //partial power-down
- if(!hprt0.b.prtsusp)
+ DWC_PRINT("%s suspend, HPRT0:0x%x\n",hcd->self.bus_name,hprt0.d32);
+ if(hprt0.b.prtconnsts) // usb device connected
{
- //hprt0.d32 = 0;
- hprt0.b.prtsusp = 1;
- hprt0.b.prtena = 0;
- dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
+ //partial power-down
+ if(!hprt0.b.prtsusp)
+ {
+ //hprt0.d32 = 0;
+ hprt0.b.prtsusp = 1;
+ hprt0.b.prtena = 0;
+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
+ }
+ udelay(10);
+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
+ if(!hprt0.b.prtsusp)
+ {
+ //hprt0.d32 = 0;
+ hprt0.b.prtsusp = 1;
+ hprt0.b.prtena = 0;
+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
+ }
+ mdelay(5);
+ pcgcctl.d32 = dwc_read_reg32(core_if->pcgcctl);
+ pcgcctl.b.pwrclmp = 1;//power clamp
+ dwc_write_reg32(core_if->pcgcctl, pcgcctl.d32);
+ udelay(1);
+ //pcgcctl.b.rstpdwnmodule = 1;//reset PDM
+ pcgcctl.b.stoppclk = 1;//stop phy clk
+ dwc_write_reg32(core_if->pcgcctl, pcgcctl.d32);
}
- udelay(10);
- hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
- DWC_PRINT("%s, HPRT0:0x%x\n",__func__,hprt0.d32);
- if(!hprt0.b.prtsusp)
+ else //no device connect
{
- //hprt0.d32 = 0;
- hprt0.b.prtsusp = 1;
- hprt0.b.prtena = 0;
- dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
+ if (core_if->hcd_cb && core_if->hcd_cb->suspend) {
+ core_if->hcd_cb->suspend( core_if->hcd_cb->p, 0);
+ }
}
- mdelay(5);
-#if 1
- pcgcctl.d32 = dwc_read_reg32(core_if->pcgcctl);
- pcgcctl.b.pwrclmp = 1;//power clamp
- dwc_write_reg32(core_if->pcgcctl, pcgcctl.d32);
- udelay(1);
- //pcgcctl.b.rstpdwnmodule = 1;//reset PDM
- pcgcctl.b.stoppclk = 1;//stop phy clk
- dwc_write_reg32(core_if->pcgcctl, pcgcctl.d32);
-#endif
-#endif
+ clk_disable(core_if->otg_dev->phyclk);
+ clk_disable(core_if->otg_dev->ahbclk);
//power off
return 0;
}
static int dwc_otg_hcd_resume(struct usb_hcd *hcd)
{
-#if 1
dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd (hcd);
dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
hprt0_data_t hprt0;
DWC_PRINT("%s, usb device mode\n", __func__);
return 0;
}
-#if 1
+ clk_enable(core_if->otg_dev->phyclk);
+ clk_enable(core_if->otg_dev->ahbclk);
+
//partial power-down
//power on
pcgcctl.d32 = dwc_read_reg32(core_if->pcgcctl);;
pcgcctl.b.pwrclmp = 0;//power clamp
dwc_write_reg32(core_if->pcgcctl, pcgcctl.d32);
udelay(2);
-#endif
+
gintmsk.d32 = dwc_read_reg32(&core_if->core_global_regs->gintmsk);
gintmsk.b.portintr = 0;
dwc_write_reg32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
-
+
hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
- DWC_PRINT("%s, HPRT0:0x%x\n",__func__,hprt0.d32);
- hprt0.b.prtpwr = 1;
- hprt0.b.prtres = 1;
- hprt0.b.prtena = 0;
- dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
- mdelay(20);
- hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
- DWC_PRINT("%s, HPRT0:0x%x\n",__func__,hprt0.d32);
- //hprt0.d32 = 0;
- hprt0.b.prtpwr = 1;
- hprt0.b.prtres = 0;
- hprt0.b.prtena = 0;
- dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
- hprt0.d32 = 0;
- hprt0.b.prtpwr = 1;
- hprt0.b.prtena = 0;
- hprt0.b.prtconndet = 1;
- dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
-
- hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
- DWC_PRINT("%s, HPRT0:0x%x\n",__func__,hprt0.d32);
-
- gintmsk.b.portintr = 1;
- dwc_write_reg32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
- mdelay(10);
-#endif
+ DWC_PRINT("%s resume, HPRT0:0x%x\n",hcd->self.bus_name,hprt0.d32);
+ if(hprt0.b.prtconnsts)
+ {
+ //hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
+ //DWC_PRINT("%s, HPRT0:0x%x\n",hcd->self.bus_name,hprt0.d32);
+ hprt0.b.prtpwr = 1;
+ hprt0.b.prtres = 1;
+ hprt0.b.prtena = 0;
+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
+ mdelay(20);
+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
+ //DWC_PRINT("%s, HPRT0:0x%x\n",hcd->self.bus_name,hprt0.d32);
+ //hprt0.d32 = 0;
+ hprt0.b.prtpwr = 1;
+ hprt0.b.prtres = 0;
+ hprt0.b.prtena = 0;
+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
+ hprt0.d32 = 0;
+ hprt0.b.prtpwr = 1;
+ hprt0.b.prtena = 0;
+ hprt0.b.prtconndet = 1;
+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
+
+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
+ //DWC_PRINT("%s, HPRT0:0x%x\n",hcd->self.bus_name,hprt0.d32);
+
+ gintmsk.b.portintr = 1;
+ dwc_write_reg32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
+ mdelay(10);
+ }
+ else
+ {
+ if (core_if->hcd_cb && core_if->hcd_cb->suspend) {
+ core_if->hcd_cb->suspend( core_if->hcd_cb->p, 1);
+ }
+ }
+
return 0;
}
#include "dwc_otg_pcd.h"
#include "dwc_otg_regs.h"
-#ifdef CONFIG_ANDROID_POWER
#include <linux/usb/composite.h>
-#include <linux/android_power.h>
-android_suspend_lock_t usb_msc_lock;
-#endif
-
/**
* Static PCD pointer for use in usb_gadget_register_driver and
static int32_t dwc_otg_pcd_suspend_cb( void *_p ,int suspend)
{
dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *)_p;
-#ifdef CONFIG_ANDROID_POWER
+//#ifdef CONFIG_ANDROID_POWER
/* yk@rk 20100520
* PC disconnect the USB, unlock the msc_lock and
* system can enter level 2 sleep mode.
if(cdev->config)
pcd->conn_status = 3;
}
-#endif
+//#endif
if (pcd->driver && pcd->driver->resume)
{
SPIN_UNLOCK(&pcd->lock);
//DWC_PRINT("%s::otg reset connect!!!\n" , __func__ );
return 0;
}
-void dwc_otg_msc_lock(void)
+void dwc_otg_msc_lock(dwc_otg_pcd_t *pcd)
{
-#ifdef CONFIG_ANDROID_POWER
- android_lock_suspend(&usb_msc_lock);
-#endif
+ unsigned long flags;
+
+ spin_lock_irqsave(&pcd->lock, flags);
+
+ wake_lock(&pcd->wake_lock);
+
+ spin_unlock_irqrestore(&pcd->lock, flags);
+
}
-void dwc_otg_msc_unlock(void)
+void dwc_otg_msc_unlock(dwc_otg_pcd_t *pcd)
{
-#ifdef CONFIG_ANDROID_POWER
- android_unlock_suspend(&usb_msc_lock);
-#endif
+ unsigned long flags;
+ spin_lock_irqsave(&pcd->lock, flags);
+ wake_unlock(&pcd->wake_lock);
+ spin_unlock_irqrestore(&pcd->lock, flags);
}
static void dwc_phy_reconnect(struct work_struct *work)
{
core_if = GET_CORE_IF(pcd);
gctrl.d32 = dwc_read_reg32( &core_if->core_global_regs->gotgctl );
if( gctrl.b.bsesvld ) {
- dwc_otg_msc_lock();
+ dwc_otg_msc_lock(pcd);
pcd->conn_status++;
dwc_pcd_reset(pcd);
/*
}
} else if((_pcd->conn_status>0)&&(_pcd->conn_status <3)) {
- dwc_otg_msc_unlock();
+ dwc_otg_msc_unlock(_pcd);
DWC_PRINT("********soft reconnect******************************************\n");
_pcd->vbus_status =0;
else if(_pcd->conn_status ==3)
{
//*Á¬½Ó²»ÉÏʱÊÍ·ÅËø£¬ÔÊÐíϵͳ½øÈë¶þ¼¶Ë¯Ãߣ¬yk@rk,20100331*//
- dwc_otg_msc_unlock();
+ dwc_otg_msc_unlock(_pcd);
_pcd->conn_status++;
+ if((dwc_read_reg32((uint32_t*)((uint8_t *)_pcd->otg_dev->base + DWC_OTG_HOST_PORT_REGS_OFFSET))&0xc00) == 0xc00)
+ _pcd->vbus_status = 2;
}
} else {
//DWC_PRINT("new vbus=%d,old vbus=%d\n" , gctrl.b.bsesvld , _pcd->vbus_status );
if(_pcd->conn_status)
{
_pcd->conn_status = 0;
- dwc_otg_msc_unlock();
+ dwc_otg_msc_unlock(_pcd);
}
/* every 500 ms open usb phy power and start 1 jiffies timer to get vbus */
if( _pcd->phy_suspend == 0 ) {
* when receive reset int,the vbus state may not be update,so
* always start timer here.
*/
- mod_timer( vbus_timer , jiffies + (HZ+(HZ/2)));
+ mod_timer( vbus_timer , jiffies + (HZ<<2));
}
/*
return -EBUSY;
}
-#ifdef CONFIG_ANDROID_POWER
- usb_msc_lock.name = "usb_msc";
- android_init_suspend_lock(&usb_msc_lock);
-#endif
+ wake_lock_init(&pcd->wake_lock, WAKE_LOCK_SUSPEND,
+ "usb_pcd");
/*
* Initialize EP structures
DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, dev);
+ wake_lock_destroy(&pcd->wake_lock);
+
/*
* Free the IRQ
*/
#include <linux/usb/gadget.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
+#include <linux/wakelock.h>
struct dwc_otg_device;
* every 500 ms. */
struct timer_list check_vbus_timer;
struct delayed_work reconnect;
+
+ /** pervent device suspend while usb connected */
+ struct wake_lock wake_lock;
} dwc_otg_pcd_t;