From 78546c0544fbb283857cf26a42c86fb3f3cd3466 Mon Sep 17 00:00:00 2001 From: wlf Date: Sat, 22 Mar 2014 17:53:49 +0800 Subject: [PATCH] USB charger: Fix the bug that cause USB Reset continually. --- drivers/usb/dwc_otg_310/dwc_otg_pcd.c | 2 +- drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c | 15 ++++++----- drivers/usb/dwc_otg_310/usbdev_bc.c | 29 ++++++++++++++++++++- drivers/usb/dwc_otg_310/usbdev_rk.h | 2 ++ drivers/usb/dwc_otg_310/usbdev_rk32.c | 21 ++++++++++++--- 5 files changed, 57 insertions(+), 12 deletions(-) mode change 100644 => 100755 drivers/usb/dwc_otg_310/usbdev_bc.c diff --git a/drivers/usb/dwc_otg_310/dwc_otg_pcd.c b/drivers/usb/dwc_otg_310/dwc_otg_pcd.c index 320341b2fe15..a8897cb12758 100755 --- a/drivers/usb/dwc_otg_310/dwc_otg_pcd.c +++ b/drivers/usb/dwc_otg_310/dwc_otg_pcd.c @@ -2640,8 +2640,8 @@ void dwc_pcd_reset(dwc_otg_pcd_t *pcd) { dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); dwc_otg_disable_global_interrupts(core_if); + dwc_otg_core_init(core_if); dwc_otg_pcd_reinit(pcd); - msleep(100); dwc_otg_core_dev_init(core_if); dwc_otg_enable_global_interrupts(core_if); } diff --git a/drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c b/drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c index 3fac0abb6c11..f763e69b5420 100755 --- a/drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c +++ b/drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c @@ -1518,9 +1518,9 @@ static void dwc_otg_pcd_check_vbus_work( struct work_struct *work ) /* if usb not connect before ,then start connect */ if( _pcd->vbus_status == USB_BC_TYPE_DISCNT ) { printk("*******************vbus detect*********************\n"); - if( pldata->bc_detect_cb != NULL ) - pldata->bc_detect_cb( _pcd->vbus_status = usb_battery_charger_detect(1) ); - else +// if( pldata->bc_detect_cb != NULL ) +// pldata->bc_detect_cb( _pcd->vbus_status = usb_battery_charger_detect(1) ); +// else _pcd->vbus_status = USB_BC_TYPE_SDP; if(_pcd->conn_en){ goto connect; @@ -1540,10 +1540,13 @@ static void dwc_otg_pcd_check_vbus_work( struct work_struct *work ) */ dwc_otg_msc_unlock(_pcd); _pcd->conn_status++; - if( pldata->bc_detect_cb != NULL ) - pldata->bc_detect_cb( _pcd->vbus_status = USB_BC_TYPE_DCP ); - else + if( pldata->bc_detect_cb != NULL ){ + rk_usb_charger_status = USB_BC_TYPE_DCP; + pldata->bc_detect_cb( _pcd->vbus_status = USB_BC_TYPE_DCP ); + }else{ _pcd->vbus_status = USB_BC_TYPE_DCP; + rk_usb_charger_status = USB_BC_TYPE_DCP; + } /* fail to connect, suspend usb phy and disable clk */ if( pldata->phy_status == USB_PHY_ENABLED ){ pldata->phy_suspend(pldata, USB_PHY_SUSPEND); diff --git a/drivers/usb/dwc_otg_310/usbdev_bc.c b/drivers/usb/dwc_otg_310/usbdev_bc.c old mode 100644 new mode 100755 index c2e63f012ebe..d08d894336c3 --- a/drivers/usb/dwc_otg_310/usbdev_bc.c +++ b/drivers/usb/dwc_otg_310/usbdev_bc.c @@ -23,6 +23,7 @@ uoc_field_t *pBC_UOC_FIELDS = NULL; static void *pGRF_BASE = NULL; +int rk_usb_charger_status = USB_BC_TYPE_DISCNT; /****** GET REGISTER FIELD INFO FROM Device Tree ******/ @@ -223,7 +224,33 @@ EXPORT_SYMBOL(usb_battery_charger_detect); int dwc_otg_check_dpdm(bool wait) { - return usb_battery_charger_detect(wait); + static struct device_node *np = NULL; + if(!np) + np = of_find_node_by_name(NULL, "usb_bc"); + if(!np) + return -1; + if(!pGRF_BASE) { + pGRF_BASE = get_grf_base(np); + } + + if(of_device_is_compatible(np,"rockchip,ctrl")) { + if(!pBC_UOC_FIELDS) + uoc_init_rk(np); + if(!BC_GET(RK_BC_BVALID)) + rk_usb_charger_status = USB_BC_TYPE_DISCNT; + + }else if(of_device_is_compatible(np,"synopsys,phy")) { + if(!pBC_UOC_FIELDS) + uoc_init_synop(np); + if(!BC_GET(SYNOP_BC_BVALID)) + rk_usb_charger_status = USB_BC_TYPE_DISCNT; + + }else if(of_device_is_compatible(np,"inno,phy")) { + if(!pBC_UOC_FIELDS) + uoc_init_inno(np); + } + + return rk_usb_charger_status; } EXPORT_SYMBOL(dwc_otg_check_dpdm); diff --git a/drivers/usb/dwc_otg_310/usbdev_rk.h b/drivers/usb/dwc_otg_310/usbdev_rk.h index f459e0fdb8fa..288597760084 100755 --- a/drivers/usb/dwc_otg_310/usbdev_rk.h +++ b/drivers/usb/dwc_otg_310/usbdev_rk.h @@ -38,6 +38,7 @@ #define USB_REMOTE_WAKEUP (6) #define USB_IRQ_WAKEUP (7) +extern int rk_usb_charger_status; /* rk3188 platform data */ extern struct dwc_otg_platform_data usb20otg_pdata_rk3188; extern struct dwc_otg_platform_data usb20host_pdata_rk3188; @@ -96,6 +97,7 @@ struct dwc_otg_control_usb { struct gpio *otg_gpios; struct clk* hclk_usb_peri; struct delayed_work usb_det_wakeup_work; + struct delayed_work usb_charger_det_work; struct wake_lock usb_wakelock; int remote_wakeup; int usb_irq_wakeup; diff --git a/drivers/usb/dwc_otg_310/usbdev_rk32.c b/drivers/usb/dwc_otg_310/usbdev_rk32.c index faa058a2d292..731e5a49dd60 100755 --- a/drivers/usb/dwc_otg_310/usbdev_rk32.c +++ b/drivers/usb/dwc_otg_310/usbdev_rk32.c @@ -534,6 +534,10 @@ inline static void do_wakeup(struct work_struct *work) // rk28_send_wakeup_key(); } +static void usb_battery_charger_detect_work(struct work_struct *work) +{ + rk_usb_charger_status = usb_battery_charger_detect(0); +} /********** handler for bvalid irq **********/ static irqreturn_t bvalid_irq_handler(int irq, void *dev_id) { @@ -549,6 +553,10 @@ static irqreturn_t bvalid_irq_handler(int irq, void *dev_id) wake_lock_timeout(&control_usb->usb_wakelock, WAKE_LOCK_TIMEOUT); schedule_delayed_work(&control_usb->usb_det_wakeup_work, HZ/10); } + + rk_usb_charger_status = USB_BC_TYPE_SDP; + schedule_delayed_work(&control_usb->usb_charger_det_work, HZ/10); + return IRQ_HANDLED; } @@ -634,7 +642,7 @@ static int otg_irq_detect_init(struct platform_device *pdev) } } } - +#if 0 /*register otg_id irq*/ irq = platform_get_irq_byname(pdev, "otg_id"); if(irq > 0){ @@ -694,7 +702,7 @@ static int otg_irq_detect_init(struct platform_device *pdev) } } } - +#endif return ret; } @@ -829,6 +837,7 @@ static int dwc_otg_control_usb_probe(struct platform_device *pdev) control_usb->usb_irq_wakeup = of_property_read_bool(np, "rockchip,usb_irq_wakeup"); + INIT_DELAYED_WORK(&control_usb->usb_charger_det_work, usb_battery_charger_detect_work); /* disable for debug hclk_usb_peri = devm_clk_get(&pdev->dev, "hclk_usb_peri"); if (IS_ERR(hclk_usb_peri)) { @@ -894,11 +903,15 @@ static int dwc_otg_control_usb_probe(struct platform_device *pdev) } gpio_direction_output(control_usb->otg_gpios->gpio, 0); -/* disable for debug + if(usb20otg_get_status(USB_STATUS_BVABLID)){ + rk_usb_charger_status = USB_BC_TYPE_SDP; + schedule_delayed_work(&control_usb->usb_charger_det_work, HZ/10); + } + ret = otg_irq_detect_init(pdev); if (ret < 0) goto err2; -*/ + return 0; err2: -- 2.34.1