*
*/
-#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/dma-mapping.h>
#include <linux/irq.h>
#include <linux/kallsyms.h>
+#include <linux/device.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/platform_device.h>
+#include <linux/usb/composite.h>
+
#include "dwc_otg_driver.h"
#include "dwc_otg_pcd.h"
#include "dwc_otg_regs.h"
-#include <linux/usb/composite.h>
-#include <mach/cru.h>
-
+#include "usbdev_rk.h"
/**
* Static PCD pointer for use in usb_gadget_register_driver and
* usb_gadget_unregister_driver. Initialized in dwc_otg_pcd_init.
int _status)
{
unsigned stopped = _ep->stopped;
-
+
DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _ep);
list_del_init(&_req->queue);
-
+
if (_req->req.status == -EINPROGRESS)
{
_req->req.status = _status;
{
_status = _req->req.status;
}
-#if 0
-
- if (_req->mapped) {
- dma_unmap_single(_ep->pcd->gadget.dev.parent,
- _req->req.dma, _req->req.length,
- _ep->dwc_ep.is_in
- ? DMA_TO_DEVICE
- : DMA_FROM_DEVICE);
- _req->req.dma = DMA_ADDR_INVALID;
- _req->mapped = 0;
- } else
- dma_sync_single_for_cpu(_ep->pcd->gadget.dev.parent,
- _req->req.dma, _req->req.length,
- _ep->dwc_ep.is_in
- ? DMA_TO_DEVICE
- : DMA_FROM_DEVICE);
+#if 1
+ if (_req->req.dma != DMA_ADDR_INVALID){
+ if (_req->mapped) {
+ dma_unmap_single(_ep->pcd->gadget.dev.parent,
+ _req->req.dma, _req->req.length,
+ _ep->dwc_ep.is_in
+ ? DMA_TO_DEVICE
+ : DMA_FROM_DEVICE);
+ _req->req.dma = DMA_ADDR_INVALID;
+ _req->mapped = 0;
+ } else
+ dma_sync_single_for_cpu(_ep->pcd->gadget.dev.parent,
+ _req->req.dma, _req->req.length,
+ _ep->dwc_ep.is_in
+ ? DMA_TO_DEVICE
+ : DMA_FROM_DEVICE);
+ }
#endif
/* don't modify queue heads during completion callback */
_ep->stopped = 1;
* This function assigns periodic Tx FIFO to an periodic EP
* in shared Tx FIFO mode
*/
- #if 0
+#ifndef CONFIG_ARCH_RK29
static uint32_t assign_perio_tx_fifo(dwc_otg_core_if_t *core_if)
{
uint32_t PerTxMsk = 1;
}
/**
* This function assigns periodic Tx FIFO to an periodic EP
- * in shared Tx FIFO mode
+ * in Dedicated FIFOs mode
*/
-#if 0
+#ifndef CONFIG_ARCH_RK29
static uint32_t assign_tx_fifo(dwc_otg_core_if_t *core_if)
{
uint32_t TxMsk = 1;
#endif
/**
* This function releases periodic Tx FIFO
- * in shared Tx FIFO mode
+ * in Dedicated FIFOs mode
*/
static void release_tx_fifo(dwc_otg_core_if_t *core_if, uint32_t fifo_num)
{
if(ep->dwc_ep.is_in)
{
- #if 0
+#ifndef CONFIG_ARCH_RK29
if(!pcd->otg_dev->core_if->en_multiple_tx_fifo)
{
ep->dwc_ep.tx_fifo_num = 0;
*/
ep->dwc_ep.tx_fifo_num = assign_tx_fifo(pcd->otg_dev->core_if);
}
- #endif
+#else
/* yk@rk
* ep0 -- tx fifo 0
* ep1 -- tx fifo 1
- * ep3 -- tx fifo 2
- * ep5 -- tx fifo 3
+ * ep3 -- tx fifo 3
+ * ep5 -- tx fifo 2
*/
if(ep->dwc_ep.num == 0)
ep->dwc_ep.tx_fifo_num = 0;
ep->dwc_ep.tx_fifo_num = 1;
else if(ep->dwc_ep.num == 3)
ep->dwc_ep.tx_fifo_num = 3;
+ else if(ep->dwc_ep.num == 5)
+ ep->dwc_ep.tx_fifo_num = 2;
else
ep->dwc_ep.tx_fifo_num = (ep->dwc_ep.num>>1)+1 ; /* 1,3,5 */
+#endif
}
/* Set initial data PID. */
if ((_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
/* 20091226,HSL@RK */
if ( !list_empty(&req->queue) )
{
- while(!list_empty(&req->queue) ) {
- ep = container_of(_ep, dwc_otg_pcd_ep_t, ep);
- request_done(ep, req, -ECONNABORTED);
- DWC_PRINT("%s::ep %s req not empty,done it error!\n" , __func__, _ep->name);
- }
+ list_del_init(&req->queue);
+ ep = container_of(_ep, dwc_otg_pcd_ep_t, ep);
+ DWC_PRINT("%s::ep %s req not empty,done it error!\n" , __func__, _ep->name);
return -EINVAL;
}
}
}
- SPIN_LOCK_IRQSAVE(&ep->pcd->lock, flags);
#if defined(DEBUG) & defined(VERBOSE)
dump_msg(_req->buf, _req->length);
: DMA_FROM_DEVICE);
req->mapped = 0;
}
+ SPIN_LOCK_IRQSAVE(&pcd->lock, flags);
+
_req->status = -EINPROGRESS;
_req->actual = 0;
DWC_DEBUGPL(DBG_PCD,
"%s ep0: EP0_IN_DATA_PHASE\n",
__func__);
+ if((_req->length % MAX_EP0_SIZE) == 0){
+ if(_req->zero)
+ ep->dwc_ep.sent_zlp = 1;
+ }
break;
case EP0_OUT_DATA_PHASE:
pcd->ep0state = EP0_STATUS;
}
break;
-
+
+ case EP0_STATUS:
+ DWC_DEBUGPL(DBG_PCD,
+ "%s ep0: EP0_IN_STATUS_PHASE\n",
+ __func__);
+ break;
+
default:
DWC_DEBUGPL(DBG_ANY, "ep0: odd state %d\n",
pcd->ep0state);
ep->dwc_ep.xfer_buff = _req->buf;
ep->dwc_ep.xfer_len = _req->length;
ep->dwc_ep.xfer_count = 0;
- ep->dwc_ep.sent_zlp = 0;
ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
dwc_otg_ep0_start_transfer( GET_CORE_IF(pcd),
&ep->dwc_ep );
dwc_otg_pcd_ep_t *ep;
dwc_otg_pcd_t *pcd;
unsigned long flags;
+ volatile depctl_data_t depctl = {.d32 = 0};
+
+ dwc_otg_dev_out_ep_regs_t *out_regs;
DWC_DEBUGPL(DBG_PCDV,"%s(%p,%p)\n", __func__, _ep, _req);
pcd = ep->pcd;
if (!pcd->driver || pcd->gadget.speed == USB_SPEED_UNKNOWN)
{
- DWC_WARN("%s, bogus device state\n", __func__);
+ DWC_WARN("%s, bogus device state, %p, speed %d\n", __func__, pcd->driver, pcd->gadget.speed);
return -ESHUTDOWN;
}
{
req = 0;
}
-
+
+ // kevery@20120602 NAK out request before new queue request
+ if(!ep->dwc_ep.is_in){
+ out_regs = GET_CORE_IF(pcd)->dev_if->out_ep_regs[ep->dwc_ep.num];
+ depctl.d32 = dwc_read_reg32(&(out_regs->doepctl));
+ depctl.b.snak = 1;
+ dwc_write_reg32( &(out_regs->doepctl), depctl.d32 );
+ }
SPIN_UNLOCK_IRQRESTORE(&pcd->lock, flags);
return req ? 0 : -EOPNOTSUPP;
}
if(is_on) //connect
{
- dctl.d32 = dwc_read_reg32( &core_if->dev_if->dev_global_regs->dctl );
- dctl.b.sftdiscon = 0;
- dwc_write_reg32( &core_if->dev_if->dev_global_regs->dctl, dctl.d32 );
+#ifdef CONFIG_DWC_CONN_EN
+ pcd->conn_en = 1;
+#else
+ pcd->conn_en = 0;
+#endif
+ pcd->conn_status = 0;
}
else //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 );
+ pcd->conn_status = 3;
}
return 0;
}
//#endif
if (pcd->driver && pcd->driver->resume)
{
- SPIN_UNLOCK(&pcd->lock);
pcd->driver->suspend(&pcd->gadget);
- SPIN_LOCK(&pcd->lock);
}
return 1;
}
if (pcd->driver && pcd->driver->resume)
{
- SPIN_UNLOCK(&pcd->lock);
pcd->driver->resume(&pcd->gadget);
- SPIN_LOCK(&pcd->lock);
}
/* Stop the SRP timeout timer. */
"ep2in",
"ep3in",
"ep4in",
+#ifdef CONFIG_ARCH_RK29
+ "ep5in-int",
+#else
"ep5in",
+#endif
"ep6in",
"ep7in",
"ep8in",
* here? Before EP type is set?
*/
ep->ep.maxpacket = MAX_PACKET_SIZE;
-
+
+ INIT_LIST_HEAD (&ep->queue);
+
+ /**
+ * @yk@rk 20120329
+ * EP8&EP9 of rk30 are IN&OUT ep, we use ep8 as OUT EP default
+ */
+ #ifndef CONFIG_ARCH_RK29
+ if(i == 8)
+ continue;
+ #endif
list_add_tail (&ep->ep.ep_list, &_pcd->gadget.ep_list);
- INIT_LIST_HEAD (&ep->queue);
}
hwcfg1 >>= 2;
}
*/
ep->ep.maxpacket = MAX_PACKET_SIZE;
+ INIT_LIST_HEAD (&ep->queue);
+
+ /**
+ * @yk@rk 20120329
+ * EP8&EP9 of rk30 are IN&OUT ep, we use ep9 as IN EP default
+ */
+ #ifndef CONFIG_ARCH_RK29
+ if(i == 9)
+ continue;
+ #endif
list_add_tail (&ep->ep.ep_list, &_pcd->gadget.ep_list);
- INIT_LIST_HEAD (&ep->queue);
}
hwcfg1 >>= 2;
}
{
dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
dwc_otg_disable_global_interrupts( core_if );
- //
-
+#ifdef CONFIG_ARCH_RK29
cru_set_soft_reset(SOFT_RST_USB_OTG_2_0_AHB_BUS, true);
cru_set_soft_reset(SOFT_RST_USB_OTG_2_0_PHY, true);
cru_set_soft_reset(SOFT_RST_USB_OTG_2_0_CONTROLLER, true);
cru_set_soft_reset(SOFT_RST_USB_OTG_2_0_AHB_BUS, false);
cru_set_soft_reset(SOFT_RST_USB_OTG_2_0_PHY, false);
cru_set_soft_reset(SOFT_RST_USB_OTG_2_0_CONTROLLER, false);
-
+ mdelay(1);
+#endif
//rockchip_scu_reset_unit(12);
dwc_otg_pcd_reinit( pcd );
dwc_otg_core_dev_init(core_if);
return 0;
}
-/*
- * close usb phy , about 7ma--2.5v
- * 20090925,add vbus test code.500ms ¼ä¸ô.
- * 20100122,HSL@RK,hard reset usb controller and phy.
-*/
-int rk28_usb_suspend( int exitsuspend )
-{
- dwc_otg_pcd_t *pcd = s_pcd;
-
- unsigned int * otg_phy_con1 = (unsigned int*)(USB_GRF_CON);
- 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);
- *otg_phy_con1 |= (0x01<<3); // exit suspend.
- *otg_phy_con1 &= ~(0x01<<2);
-
- /* 20091011,reenable usb phy ,will raise reset intr */
- //debug_print("enable usb phy\n");
- DWC_DEBUGPL(DBG_PCDV, "enable usb phy\n");
- }
- if( !exitsuspend && (pcd->phy_suspend == 0)) {
- pcd->phy_suspend = 1;
- *otg_phy_con1 |= (0x01<<2);
- *otg_phy_con1 &= ~(0x01<<3); // enter suspend.
- udelay(3);
- clk_disable(pcd->otg_dev->phyclk);
- clk_disable(pcd->otg_dev->ahbclk);
- //*otg_phy_con1 &= ~(0x01<<2);
- //debug_print("disable usb phy\n");
- DWC_DEBUGPL(DBG_PCDV, "disable usb phy\n");
- }
-
- 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 )
{
unsigned long flags;
- spin_lock_irqsave(&pcd->lock, flags);
-
+ local_irq_save(flags);
wake_lock(&pcd->wake_lock);
-
- spin_unlock_irqrestore(&pcd->lock, flags);
+ local_irq_restore(flags);
}
void dwc_otg_msc_unlock(dwc_otg_pcd_t *pcd)
{
unsigned long flags;
- spin_lock_irqsave(&pcd->lock, flags);
+ local_irq_save(flags);
wake_unlock(&pcd->wake_lock);
- spin_unlock_irqrestore(&pcd->lock, flags);
+ local_irq_restore(flags);
}
static void dwc_phy_reconnect(struct work_struct *work)
{
DWC_PRINT("********soft connect!!!*****************************************\n");
}
}
-
+#if defined(CONFIG_ARCH_RK29)
static void dwc_otg_pcd_check_vbus_timer( unsigned long pdata )
{
- dwc_otg_pcd_t * _pcd = (dwc_otg_pcd_t *)pdata;
+ struct device *_dev = (struct device *)pdata;
+ struct dwc_otg_platform_data *pldata = _dev->platform_data;
+ dwc_otg_device_t *otg_dev = (dwc_otg_device_t *)(*((uint32_t *)_dev->platform_data));
+ dwc_otg_pcd_t * _pcd = otg_dev->pcd;
dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd);
gotgctl_data_t gctrl;
dctl_data_t dctl = {.d32=0};
//dsts_data_t gsts;
- unsigned long flags;
- local_irq_save(flags);
+ unsigned long flags;
+ local_irq_save(flags);
gctrl.d32 = dwc_read_reg32( &core_if->core_global_regs->gotgctl );
//gsts.d32 = dwc_read_reg32( &core_if->dev_if->dev_global_regs->dsts);
if( _pcd->vbus_status == 0 ) {
dwc_otg_msc_lock(_pcd);
DWC_PRINT("********vbus detect*********************************************\n");
- _pcd->vbus_status = 1;
+ _pcd->vbus_status = 1;
/* 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 */
- }
+ {
+ 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);
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 );
+ 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);
+ 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 */
- }
+ {
+ schedule_delayed_work( &_pcd->reconnect , 8 ); /* delay 1 jiffies */
+ _pcd->check_vbus_timer.expires = jiffies + (HZ<<1); /* 1 s */
+ }
}
else if((_pcd->conn_en)&&(_pcd->conn_status == 0))
{
-
- schedule_delayed_work( &_pcd->reconnect , 8 ); /* delay 1 jiffies */
- _pcd->check_vbus_timer.expires = jiffies + (HZ<<1); /* 1 s */
+
+ 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)
{
- //*Á¬½Ó²»ÉÏʱÊÍ·ÅËø£¬ÔÊÐíϵͳ½øÈë¶þ¼¶Ë¯Ãߣ¬yk@rk,20100331*//
+ //*????????,??????????,yk@rk,20100331*//
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_otg_msc_unlock(_pcd);
}
/* every 500 ms open usb phy power and start 1 jiffies timer to get vbus */
- if( _pcd->phy_suspend == 0 ) {
+ if( pldata->phy_status == 0 ) {
/* no vbus detect here , close usb phy for 500ms */
- rk28_usb_suspend( 0 );
+ pldata->phy_suspend(pldata, USB_PHY_SUSPEND);
+ //dwc_otg20phy_suspend( 0 );
_pcd->check_vbus_timer.expires = jiffies + (HZ/2); /* 500 ms */
- } else if( _pcd->phy_suspend == 1 ) {
- rk28_usb_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 */
-
+ } else if( pldata->phy_status == 1 ) {
+ pldata->phy_suspend(pldata, USB_PHY_ENABLED);
+ // 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 */
+
}
}
//DWC_PRINT("%s:restart check vbus timer\n" , __func__ );
+ add_timer(&_pcd->check_vbus_timer);
+ local_irq_restore(flags);
+}
+#else
+
+static void dwc_otg_pcd_check_vbus_timer( unsigned long data )
+{
+ struct device *_dev = (struct device *)data;
+ struct dwc_otg_platform_data *pldata = _dev->platform_data;
+ dwc_otg_device_t *otg_dev = (dwc_otg_device_t *)(*((uint32_t *)_dev->platform_data));
+ dwc_otg_pcd_t * _pcd = otg_dev->pcd;
+ unsigned long flags;
+ local_irq_save(flags);
+ _pcd->check_vbus_timer.expires = jiffies + (HZ); /* 1 s */
+ if(!pldata->get_status(USB_STATUS_ID))
+ { // id low
+ if( pldata->dwc_otg_uart_mode != NULL )
+ {//exit phy bypass to uart & enable usb phy
+ pldata->dwc_otg_uart_mode( pldata, PHY_USB_MODE);
+ }
+ if( pldata->phy_status)
+ {
+ pldata->clock_enable( pldata, 1);
+ pldata->phy_suspend(pldata, USB_PHY_ENABLED);
+ }
+ }
+ else if(pldata->get_status(USB_STATUS_BVABLID))
+ { // bvalid
+ /* if usb not connect before ,then start connect */
+ if( _pcd->vbus_status == 0 )
+ {
+ DWC_PRINT("********vbus detect*********************************************\n");
+ _pcd->vbus_status = 1;
+ if(_pcd->conn_en)
+ goto connect;
+ else if( pldata->phy_status == USB_PHY_ENABLED )
+ {
+ // not connect, suspend phy
+ pldata->phy_suspend(pldata, USB_PHY_SUSPEND);
+ udelay(3);
+ pldata->clock_enable( pldata, 0);
+ }
+ }
+ else if((_pcd->conn_en)&&(_pcd->conn_status>=0)&&(_pcd->conn_status <3))
+ {
+ DWC_PRINT("********soft reconnect******************************************\n");
+ goto connect;
+ }
+ else if(_pcd->conn_status ==3)
+ {
+ //*Á¬½Ó²»ÉÏʱÊÍ·ÅËø£¬ÔÊÐíϵͳ½øÈë¶þ¼¶Ë¯Ãߣ¬yk@rk,20100331*//
+ 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;
+
+ // not connect, suspend phy
+ if( pldata->phy_status == USB_PHY_ENABLED )
+ {
+ pldata->phy_suspend(pldata, USB_PHY_SUSPEND);
+ udelay(3);
+ pldata->clock_enable( pldata, 0);
+ }
+ }
+ }
+ else
+ {
+ _pcd->vbus_status = 0;
+ if(_pcd->conn_status)
+ {
+ _pcd->conn_status = 0;
+ }
+ else if( pldata->phy_status == USB_PHY_ENABLED )
+ {
+ /* no vbus detect here , close usb phy */
+ pldata->phy_suspend(pldata, USB_PHY_SUSPEND);
+ udelay(3);
+ pldata->clock_enable( pldata, 0);
+ /* usb phy bypass to uart mode */
+ if( pldata->dwc_otg_uart_mode != NULL )
+ pldata->dwc_otg_uart_mode( pldata, PHY_UART_MODE);
+ /* release wake lock */
+ dwc_otg_msc_unlock(_pcd);
+ }
+ }
add_timer(&_pcd->check_vbus_timer);
local_irq_restore(flags);
-}
+ return;
+connect:
+ if(_pcd->conn_status==0)
+ dwc_otg_msc_lock(_pcd);
+ if( pldata->phy_status)
+ {
+ pldata->clock_enable( pldata, 1);
+ pldata->phy_suspend(pldata, USB_PHY_ENABLED);
+ }
+ 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
void dwc_otg_pcd_start_vbus_timer( dwc_otg_pcd_t * _pcd )
{
struct timer_list *vbus_timer = &_pcd->check_vbus_timer;
int dwc_vbus_status( void )
{
dwc_otg_pcd_t *pcd = s_pcd;
- return pcd->vbus_status ;
+ if(!pcd)
+ return 0;
+ else
+ return pcd->vbus_status ;
}
EXPORT_SYMBOL(dwc_vbus_status);
{
static char pcd_name[] = "dwc_otg_pcd";
dwc_otg_pcd_t *pcd;
- dwc_otg_device_t *otg_dev = dev->platform_data;
- dwc_otg_core_if_t *core_if = otg_dev->core_if;
+ dwc_otg_device_t *otg_dev = (dwc_otg_device_t *)(*((uint32_t *)dev->platform_data));
+ dwc_otg_core_if_t *core_if = otg_dev->core_if;
+ struct dwc_otg_platform_data *pldata = dev->platform_data;
int retval = 0;
int irq;
/*
memset( pcd, 0, sizeof(dwc_otg_pcd_t));
spin_lock_init( &pcd->lock );
-
otg_dev->pcd = pcd;
s_pcd = pcd;
pcd->gadget.name = pcd_name;
pcd->gadget.is_dualspeed = 0;
pcd->gadget.is_otg = 0;
pcd->driver = 0;
-#ifdef CONFIG_DWC_CONN_EN
- pcd->conn_en = 1;
-#else
pcd->conn_en = 0;
-#endif
/* Register the gadget device */
retval = device_register( &pcd->gadget.dev );
if(retval != 0)
init_timer( &pcd->check_vbus_timer );
pcd->check_vbus_timer.function = dwc_otg_pcd_check_vbus_timer;
- pcd->check_vbus_timer.data = (unsigned long)(pcd);
+ pcd->check_vbus_timer.data = (unsigned long)(dev);
INIT_DELAYED_WORK(&pcd->reconnect , dwc_phy_reconnect);
pcd->vbus_status = 0;
- pcd->phy_suspend = 0;
- if(dwc_otg_is_device_mode(core_if))
- mod_timer(&pcd->check_vbus_timer, jiffies+(HZ<<4)); // delay 16 S
-// dwc_otg_pcd_start_vbus_timer( pcd );
+ pcd->phy_suspend = 0;
+ if(dwc_otg_is_device_mode(core_if)){
+#ifdef CONFIG_RK_USB_UART
+ if(pldata->get_status(USB_STATUS_BVABLID))
+ {
+ pldata->dwc_otg_uart_mode(pldata, PHY_USB_MODE);
+ }//phy usb mode
+ else
+ {
+ pldata->phy_suspend(pldata,USB_PHY_SUSPEND);
+ pldata->dwc_otg_uart_mode(pldata, PHY_UART_MODE);
+ }//phy bypass to uart mode
+#endif
+ mod_timer(&pcd->check_vbus_timer, jiffies+(HZ<<4)); // delay 16 S
+ }
+#ifdef CONFIG_RK_USB_UART
+ else if(pldata->dwc_otg_uart_mode != NULL)
+ pldata->dwc_otg_uart_mode(pldata, PHY_USB_MODE);//disable phy bypass uart
+#endif
+
return 0;
}
/**
*/
void dwc_otg_pcd_remove( struct device *dev )
{
- dwc_otg_device_t *otg_dev = dev->platform_data;
+ dwc_otg_device_t *otg_dev = (dwc_otg_device_t *)(*((uint32_t *)dev->platform_data));
dwc_otg_pcd_t *pcd = otg_dev->pcd;
DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, dev);
kfree( pcd );
otg_dev->pcd = 0;
- s_pcd = 0; // HSL@RK,20090901
+ s_pcd = 0;
}
/**
* @param _driver The driver being registered
*/
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+int usb_gadget_probe_driver(struct usb_gadget_driver *_driver,
+ int (*bind)(struct usb_gadget *))
+#else
int usb_gadget_register_driver(struct usb_gadget_driver *_driver)
+#endif
{
int retval;
DWC_DEBUGPL(DBG_PCD, "registering gadget driver '%s'\n", _driver->driver.name);
if (!_driver || _driver->speed == USB_SPEED_UNKNOWN ||
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+ !bind ||
+#else
!_driver->bind ||
+#endif
!_driver->unbind ||
!_driver->disconnect ||
!_driver->setup)
s_pcd->gadget.dev.driver = &_driver->driver;
DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", _driver->driver.name);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+ retval = bind(&s_pcd->gadget);
+#else
retval = _driver->bind(&s_pcd->gadget);
+#endif
if (retval)
{
DWC_ERROR("bind to driver %s --> error %d\n",
_driver->driver.name);
return 0;
}
-
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+EXPORT_SYMBOL(usb_gadget_probe_driver);
+#else
EXPORT_SYMBOL(usb_gadget_register_driver);
+#endif
/**
* This function unregisters a gadget driver