add clockgate for rk30 usb 2.0 otg

This commit is contained in:
yangkai
2012-04-01 12:42:18 +08:00
parent e211c10dc1
commit a89f841a2a
3 changed files with 127 additions and 72 deletions

View File

@@ -340,7 +340,7 @@ int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t *_core_if)
#ifdef DWC_BOTH_HOST_SLAVE
extern void dwc_otg_force_device(dwc_otg_core_if_t *core_if);
extern void dwc_otg_force_host(dwc_otg_core_if_t *core_if);
extern int rk28_usb_suspend( int exitsuspend );
extern int dwc_otg20phy_suspend( int exitsuspend );
#endif
int32_t dwc_otg_handle_conn_id_status_change_intr(dwc_otg_core_if_t *_core_if)
@@ -353,7 +353,7 @@ int32_t dwc_otg_handle_conn_id_status_change_intr(dwc_otg_core_if_t *_core_if)
gotgctl_data_t gotgctl = { .d32 = 0 };
if(pcd &&(pcd->phy_suspend == 1))
{
rk28_usb_suspend( 1 );
dwc_otg20phy_suspend( 1 );
}
/*

View File

@@ -68,9 +68,7 @@
#include "dwc_otg_cil.h"
#include "dwc_otg_pcd.h"
#include "dwc_otg_hcd.h"
#ifdef CONFIG_ARCH_RK29
#include <mach/cru.h>
#endif
//#define DWC_DRIVER_VERSION "2.60a 22-NOV-2006"
//#define DWC_DRIVER_VERSION "2.70 2009-12-31"
#define DWC_DRIVER_VERSION "3.00 2010-12-12 rockchip"
@@ -338,7 +336,7 @@ extern struct usb_hub *g_root_hub20;
#ifdef DWC_BOTH_HOST_SLAVE
extern void hcd_start( dwc_otg_core_if_t *_core_if );
extern int rk28_usb_suspend( int exitsuspend );
extern int dwc_otg20phy_suspend( int exitsuspend );
extern void hub_disconnect_device(struct usb_hub *hub);
static ssize_t force_usb_mode_show(struct device_driver *_drv, char *_buf)
@@ -376,7 +374,7 @@ void dwc_otg_force_host(dwc_otg_core_if_t *core_if)
}
if((otg_dev->pcd)&&(otg_dev->pcd->phy_suspend == 1))
{
rk28_usb_suspend( 1 );
dwc_otg20phy_suspend( 1 );
}
del_timer(&otg_dev->pcd->check_vbus_timer);
// force disconnect
@@ -503,7 +501,7 @@ static ssize_t force_usb_mode_store(struct device_driver *_drv, const char *_buf
core_if->usb_mode = new_mode;
if((otg_dev->pcd)&&(otg_dev->pcd->phy_suspend == 1))
{
rk28_usb_suspend( 1 );
dwc_otg20phy_suspend( 1 );
}
del_timer(&otg_dev->pcd->check_vbus_timer);
dwc_otg_set_gusbcfg(core_if, new_mode);
@@ -525,7 +523,7 @@ static ssize_t force_usb_mode_store(struct device_driver *_drv, const char *_buf
{
if((otg_dev->pcd)&&(otg_dev->pcd->phy_suspend == 1))
{
rk28_usb_suspend( 1 );
dwc_otg20phy_suspend( 1 );
}
core_if->usb_mode = new_mode;
dwc_otg_set_gusbcfg(core_if, new_mode);
@@ -1152,8 +1150,10 @@ static int dwc_otg_driver_remove(struct platform_device *pdev)
clk_disable(otg_dev->phyclk);
clk_put(otg_dev->ahbclk);
clk_disable(otg_dev->ahbclk);
#ifdef CONFIG_ARCH_RK29
clk_put(otg_dev->busclk);
clk_disable(otg_dev->busclk);
#endif
kfree(otg_dev);
/*
@@ -1195,11 +1195,11 @@ static __devinit int dwc_otg_driver_probe(struct platform_device *pdev)
unsigned int * otg_phy_con1 = (unsigned int*)(USB_GRF_CON);
#endif
#ifdef CONFIG_ARCH_RK30
unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC0_CON2);
unsigned int * otg_phy_con = (unsigned int*)(USBGRF_UOC0_CON2);
#endif
regval = * otg_phy_con1;
#ifdef CONFIG_ARCH_RK29
#ifdef CONFIG_ARCH_RK29
regval = * otg_phy_con1;
#ifndef CONFIG_USB11_HOST
/*
* disable usb host 1.1 controller if not support
@@ -1258,6 +1258,34 @@ static __devinit int dwc_otg_driver_probe(struct platform_device *pdev)
#endif
#endif
#ifdef CONFIG_ARCH_RK30
#ifndef CONFIG_USB20_HOST
otg_phy_con = (unsigned int*)(USBGRF_UOC1_CON2);
/*
* disable usb host 2.0 phy if not support
*/
phyclk = clk_get(NULL, "otgphy1");
if (IS_ERR(phyclk)) {
retval = PTR_ERR(phyclk);
DWC_ERROR("can't get USBPHY1 clock\n");
goto fail;
}
clk_enable(phyclk);
ahbclk = clk_get(NULL, "hclk_otg1");
if (IS_ERR(ahbclk)) {
retval = PTR_ERR(ahbclk);
DWC_ERROR("can't get USBOTG1 ahb bus clock\n");
goto fail;
}
clk_enable(ahbclk);
*otg_phy_con = ((0x01<<2)|(0x00<<3)|(0x05<<6))|(((0x01<<2)|(0x01<<3)|(0x07<<6))<<16); // enter suspend.
udelay(3);
clk_disable(phyclk);
clk_disable(ahbclk);
#endif
#endif
dwc_otg_device = kmalloc(sizeof(dwc_otg_device_t), GFP_KERNEL);
if (dwc_otg_device == 0)
@@ -1315,7 +1343,42 @@ static __devinit int dwc_otg_driver_probe(struct platform_device *pdev)
dwc_otg_device->phyclk = phyclk;
dwc_otg_device->ahbclk = ahbclk;
dwc_otg_device->busclk = busclk;
#endif
#endif
#ifdef CONFIG_ARCH_RK30
otg_phy_con = (unsigned int*)(USBGRF_UOC0_CON2);
cru_set_soft_reset(SOFT_RST_USBPHY0, true);
cru_set_soft_reset(SOFT_RST_OTGC0, true);
cru_set_soft_reset(SOFT_RST_USBOTG0, true);
udelay(1);
cru_set_soft_reset(SOFT_RST_USBOTG0, false);
cru_set_soft_reset(SOFT_RST_OTGC0, false);
cru_set_soft_reset(SOFT_RST_USBPHY0, false);
phyclk = clk_get(NULL, "otgphy0");
if (IS_ERR(phyclk)) {
retval = PTR_ERR(phyclk);
DWC_ERROR("can't get USBPHY0 clock\n");
goto fail;
}
clk_enable(phyclk);
ahbclk = clk_get(NULL, "hclk_otg0");
if (IS_ERR(ahbclk)) {
retval = PTR_ERR(ahbclk);
DWC_ERROR("can't get USB otg0 ahb bus clock\n");
goto fail;
}
clk_enable(ahbclk);
/*
* Enable usb phy 0
*/
*otg_phy_con = ((0x01<<2)<<16);
dwc_otg_device->phyclk = phyclk;
dwc_otg_device->ahbclk = ahbclk;
#endif
/*
* Map the DWC_otg Core memory into virtual address space.
*/
@@ -1324,8 +1387,7 @@ static __devinit int dwc_otg_driver_probe(struct platform_device *pdev)
if (!res_base)
goto fail;
dwc_otg_device->base =
ioremap(res_base->start,USBOTG_SIZE);
dwc_otg_device->base = ioremap(res_base->start,USBOTG_SIZE);
if (dwc_otg_device->base == NULL)
{
dev_err(dev, "ioremap() failed\n");
@@ -1498,7 +1560,7 @@ static __devinit int dwc_otg_driver_probe(struct platform_device *pdev)
}
#ifndef CONFIG_DWC_OTG_HOST_ONLY
extern int rk28_usb_suspend( int exitsuspend );
extern int dwc_otg20phy_suspend( int exitsuspend );
static int dwc_otg_driver_suspend(struct platform_device *_dev , pm_message_t state )
{
struct device *dev = &_dev->dev;
@@ -1512,7 +1574,7 @@ static int dwc_otg_driver_suspend(struct platform_device *_dev , pm_message_t st
/* 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);
dwc_otg20phy_suspend(0);
del_timer(&otg_dev->pcd->check_vbus_timer);
return 0;
@@ -1540,7 +1602,7 @@ static int dwc_otg_driver_resume(struct platform_device *_dev )
}
#ifndef CONFIG_DWC_OTG_HOST_ONLY
rk28_usb_suspend(1);
dwc_otg20phy_suspend(1);
/* soft disconnect */
/* 20100226,HSL@RK,if not disconnect,when usb cable in,will auto reconnect

View File

@@ -1603,15 +1603,11 @@ int dwc_pcd_reset(dwc_otg_pcd_t *pcd)
* 20090925,add vbus test code.500ms <20><><EFBFBD><EFBFBD>.
* 20100122,HSL@RK,hard reset usb controller and phy.
*/
int rk28_usb_suspend( int exitsuspend )
int dwc_otg20phy_suspend( int exitsuspend )
{
dwc_otg_pcd_t *pcd = s_pcd;
#ifdef CONFIG_ARCH_RK29
unsigned int * otg_phy_con1 = (unsigned int*)(USB_GRF_CON);
#endif
#ifdef CONFIG_ARCH_RK30
unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC0_CON2);
#endif
if(exitsuspend && (pcd->phy_suspend == 1)) {
clk_enable(pcd->otg_dev->ahbclk);
clk_enable(pcd->otg_dev->phyclk);
@@ -1635,23 +1631,35 @@ int rk28_usb_suspend( int exitsuspend )
//debug_print("disable usb phy\n");
DWC_DEBUGPL(DBG_PCDV, "disable usb phy\n");
}
#endif
#ifdef CONFIG_ARCH_RK30
unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC0_CON2);
if(exitsuspend && (pcd->phy_suspend == 1)) {
clk_enable(pcd->otg_dev->ahbclk);
clk_enable(pcd->otg_dev->phyclk);
pcd->phy_suspend = 0;
*otg_phy_con1 = ((0x01<<2)<<16); // exit suspend.
// *otg_phy_con1 |= (0x01<<3);
// *otg_phy_con1 &= ~(0x01<<2);
/* 20091011,reenable usb phy ,will raise reset intr */
// DWC_PRINT("enable usb phy 0x%x\n", *otg_phy_con1);
DWC_DEBUGPL(DBG_PCDV, "enable usb phy\n");
}
if( !exitsuspend && (pcd->phy_suspend == 0)) {
pcd->phy_suspend = 1;
*otg_phy_con1 = ((0x01<<2)|(0x00<<3)|(0x05<<6))|(((0x01<<2)|(0x01<<3)|(0x07<<6))<<16); // enter suspend.
udelay(3);
clk_disable(pcd->otg_dev->phyclk);
clk_disable(pcd->otg_dev->ahbclk);
//*otg_phy_con1 &= ~(0x01<<2);
// DWC_PRINT("disable usb phy 0x%x\n", *otg_phy_con1);
DWC_DEBUGPL(DBG_PCDV, "disable usb phy\n");
}
#endif
return pcd->phy_suspend;
}
void rk28_usb_force_resume( void )
{
dwc_otg_pcd_t *pcd = s_pcd;
if( pcd ) {
del_timer(&pcd->check_vbus_timer);
}
mdelay( 10 );
if( pcd ) {
pcd->phy_suspend = 1;
pcd->vbus_status = 0;
dwc_otg_pcd_start_vbus_timer(pcd);
}
}
int dwc_otg_reset( void )
{
@@ -1779,10 +1787,10 @@ static void dwc_otg_pcd_check_vbus_timer( unsigned long pdata )
/* every 500 ms open usb phy power and start 1 jiffies timer to get vbus */
if( _pcd->phy_suspend == 0 ) {
/* no vbus detect here , close usb phy for 500ms */
rk28_usb_suspend( 0 );
dwc_otg20phy_suspend( 0 );
_pcd->check_vbus_timer.expires = jiffies + (HZ/2); /* 500 ms */
} else if( _pcd->phy_suspend == 1 ) {
rk28_usb_suspend( 1 );
dwc_otg20phy_suspend( 1 );
/*20100325 yk@rk,delay 2-->8,for host connect id detect*/
_pcd->check_vbus_timer.expires = jiffies + 8; /* 20091127,HSL@RK,1-->2 */
@@ -1802,6 +1810,7 @@ static void dwc_otg_pcd_check_vbus_timer( unsigned long pdata )
dctl_data_t dctl = {.d32=0};
//dsts_data_t gsts;
unsigned long flags;
local_irq_save(flags);
#ifdef CONFIG_ARCH_RK30
unsigned int usbgrf_status = *(unsigned int*)(USBGRF_SOC_STATUS0);
#endif
@@ -1809,44 +1818,17 @@ static void dwc_otg_pcd_check_vbus_timer( unsigned long pdata )
if(usbgrf_status &0x20000){ // bvalid
/* if usb not connect before ,then start connect */
if( _pcd->vbus_status == 0 ) {
dwc_otg_msc_lock(_pcd);
DWC_PRINT("********vbus detect*********************************************\n");
dwc_otg_msc_lock(_pcd);
_pcd->vbus_status = 1;
if(_pcd->conn_en)
{
if( _pcd->phy_suspend == 1 ) {
// rk28_usb_suspend( 1 );
}
schedule_delayed_work( &_pcd->reconnect , 8 ); /* delay 1 jiffies */
_pcd->check_vbus_timer.expires = jiffies + (HZ<<1); /* 1 s */
}
} else if((_pcd->conn_status>0)&&(_pcd->conn_status <3)) {
//dwc_otg_msc_unlock(_pcd);
goto connect;
}
else if((_pcd->conn_en)&&(_pcd->conn_status>=0)&&(_pcd->conn_status <3)){
DWC_PRINT("********soft reconnect******************************************\n");
//_pcd->vbus_status =0;
/* soft disconnect */
dctl.d32 = dwc_read_reg32( &core_if->dev_if->dev_global_regs->dctl );
dctl.b.sftdiscon = 1;
dwc_write_reg32( &core_if->dev_if->dev_global_regs->dctl, dctl.d32 );
/* Clear any pending interrupts */
dwc_write_reg32( &core_if->core_global_regs->gintsts, 0xFFFFFFFF);
if(_pcd->conn_en)
{
schedule_delayed_work( &_pcd->reconnect , 8 ); /* delay 1 jiffies */
_pcd->check_vbus_timer.expires = jiffies + (HZ<<1); /* 1 s */
}
goto connect;
}
else if((_pcd->conn_en)&&(_pcd->conn_status == 0))
{
DWC_PRINT("********vbus detect ccccc*********************************************\n");
schedule_delayed_work( &_pcd->reconnect , 8 ); /* delay 1 jiffies */
_pcd->check_vbus_timer.expires = jiffies + (HZ<<1); /* 1 s */
}
else if(_pcd->conn_status ==3)
{
else if(_pcd->conn_status ==3){
//*<2A><><EFBFBD>Ӳ<EFBFBD><D3B2><EFBFBD>ʱ<EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˯<EFBFBD>ߣ<EFBFBD>yk@rk,20100331*//
dwc_otg_msc_unlock(_pcd);
_pcd->conn_status++;
@@ -1863,9 +1845,20 @@ static void dwc_otg_pcd_check_vbus_timer( unsigned long pdata )
/* every 500 ms open usb phy power and start 1 jiffies timer to get vbus */
if( _pcd->phy_suspend == 0 )
/* no vbus detect here , close usb phy */
rk28_usb_suspend( 0 );
dwc_otg20phy_suspend( 0 );
}
add_timer(&_pcd->check_vbus_timer);
local_irq_restore(flags);
return;
connect:
if( _pcd->phy_suspend == 1 )
dwc_otg20phy_suspend( 1 );
schedule_delayed_work( &_pcd->reconnect , 8 ); /* delay 1 jiffies */
_pcd->check_vbus_timer.expires = jiffies + (HZ<<1); /* 1 s */
add_timer(&_pcd->check_vbus_timer);
local_irq_restore(flags);
return;
}
#endif