usb: support different type of usb charger
authorlyz <lyz@rock-chips.com>
Fri, 10 Oct 2014 05:42:32 +0000 (13:42 +0800)
committerlyz <lyz@rock-chips.com>
Sat, 11 Oct 2014 02:20:39 +0000 (10:20 +0800)
drivers/usb/dwc_otg_310/dwc_otg_cil_intr.c
drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c
drivers/usb/dwc_otg_310/usbdev_bc.c
drivers/usb/dwc_otg_310/usbdev_bc.h
drivers/usb/dwc_otg_310/usbdev_rk.h
drivers/usb/dwc_otg_310/usbdev_rk30.c
drivers/usb/dwc_otg_310/usbdev_rk3036.c
drivers/usb/dwc_otg_310/usbdev_rk3126.c
drivers/usb/dwc_otg_310/usbdev_rk32.c

index a4327dc176f821a26260b7e88206330134de9f27..199765d6abecfd5ed60de675450bac1741d3b82f 100755 (executable)
@@ -109,8 +109,8 @@ int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t *core_if)
                                dctl.d32);
                dwc_otg_disable_global_interrupts(core_if);
                core_if->otg_dev->pcd->vbus_status = USB_BC_TYPE_DISCNT;
-               DWC_PRINTF
-                   ("********session end ,soft disconnect************************\n");
+
+               DWC_PRINTF("********session end ,soft disconnect***********\n");
 
                gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
 
index da339bfba07613cd857902b0293e887ad5b89d65..d4db1e73930f131ebd6209369eb597b457b72a67 100755 (executable)
@@ -1529,12 +1529,12 @@ static void dwc_otg_pcd_check_vbus_work(struct work_struct *work)
        } else if (pldata->get_status(USB_STATUS_BVABLID)) {
                /* 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 */
-                       _pcd->vbus_status = USB_BC_TYPE_SDP;
+                       printk("***************vbus detect*****************\n");
+                       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;
                        } else if (pldata->phy_status == USB_PHY_ENABLED) {
@@ -1545,7 +1545,7 @@ static void dwc_otg_pcd_check_vbus_work(struct work_struct *work)
                        }
                } else if ((_pcd->conn_en) && (_pcd->conn_status >= 0)
                           && (_pcd->conn_status < 2)) {
-                       printk("****************soft reconnect******************\n");
+                       printk("**************soft reconnect**************\n");
                        goto connect;
                } else if (_pcd->conn_status == 2) {
                        /* release pcd->wake_lock if fail to connect,
@@ -1554,12 +1554,10 @@ 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) {
-                               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) {
@@ -1571,7 +1569,7 @@ static void dwc_otg_pcd_check_vbus_work(struct work_struct *work)
        } else {
                if (pldata->bc_detect_cb != NULL)
                        pldata->bc_detect_cb(_pcd->vbus_status =
-                                            USB_BC_TYPE_DISCNT);
+                                            usb_battery_charger_detect(0));
                else
                        _pcd->vbus_status = USB_BC_TYPE_DISCNT;
 
@@ -1666,7 +1664,7 @@ static void dwc_otg_pcd_work_init(dwc_otg_pcd_t *pcd,
                        /* usb phy bypass to uart mode */
                        pldata->dwc_otg_uart_mode(pldata, PHY_UART_MODE);
                }
-               schedule_delayed_work(&pcd->check_vbus_work, (HZ << 4));
+               schedule_delayed_work(&pcd->check_vbus_work, (HZ << 3));
        }
        else if (pldata->dwc_otg_uart_mode != NULL)
                /* host mode,enter usb phy mode */
index 96f2234b112b656b2eaffc9522fb8edb30eb3fcd..a62c489d9cad81f070217c841f55617684f4bf5b 100755 (executable)
@@ -28,7 +28,9 @@ char *bc_string[USB_BC_TYPE_MAX] = {"DISCONNECT",
 
 uoc_field_t *pBC_UOC_FIELDS;
 static void *pGRF_BASE;
-int rk_usb_charger_status = USB_BC_TYPE_DISCNT;
+static struct mutex bc_mutex;
+
+static enum bc_port_type usb_charger_status = USB_BC_TYPE_DISCNT;
 
 /****** GET REGISTER FIELD INFO FROM Device Tree ******/
 
@@ -132,8 +134,16 @@ static inline void uoc_init_inno(struct device_node *np)
 }
 
 /****** BATTERY CHARGER DETECT FUNCTIONS ******/
+bool is_connected(void)
+{
+       if (!pGRF_BASE)
+               return false;
+       if (BC_GET(BC_BVALID) && BC_GET(BC_IDDIG))
+               return true;
+       return false;
+}
 
-int usb_battery_charger_detect_rk(bool wait)
+enum bc_port_type usb_battery_charger_detect_rk(bool wait)
 {
 
        enum bc_port_type port_type = USB_BC_TYPE_DISCNT;
@@ -170,15 +180,15 @@ int usb_battery_charger_detect_rk(bool wait)
        return port_type;
 }
 
-int usb_battery_charger_detect_inno(bool wait)
+enum bc_port_type usb_battery_charger_detect_inno(bool wait)
 {
        enum bc_port_type port_type = USB_BC_TYPE_DISCNT;
        int dcd_state = DCD_POSITIVE;
        int timeout = 0, i = 0;
 
        /* VBUS Valid detect */
-       if (BC_GET(SYNOP_BC_BVALID) &&
-               BC_GET(SYNOP_BC_IDDIG)) {
+       if (BC_GET(INNO_BC_BVALID) &&
+               BC_GET(INNO_BC_IDDIG)) {
                if (wait) {
                        /* Do DCD */
                        dcd_state = DCD_TIMEOUT;
@@ -247,7 +257,7 @@ out:
 
 /* When do BC detect PCD pull-up register should be disabled  */
 /* wait wait for dcd timeout 900ms */
-int usb_battery_charger_detect_synop(bool wait)
+enum bc_port_type usb_battery_charger_detect_synop(bool wait)
 {
        enum bc_port_type port_type = USB_BC_TYPE_DISCNT;
        int dcd_state = DCD_POSITIVE;
@@ -316,105 +326,91 @@ int usb_battery_charger_detect_synop(bool wait)
 
        }
 out:
+       /*
        printk("%s, Charger type %s, %s DCD, dcd_state = %d\n", __func__,
               bc_string[port_type], wait ? "wait" : "pass", dcd_state);
+       */
        return port_type;
 }
 
-int usb_battery_charger_detect(bool wait)
+enum bc_port_type usb_battery_charger_detect(bool wait)
 {
        static struct device_node *np;
+       enum bc_port_type ret = USB_BC_TYPE_DISCNT;
+
+       might_sleep();
+
        if (!np)
                np = of_find_node_by_name(NULL, "usb_bc");
        if (!np)
-               goto fail;
-       if (!pGRF_BASE)
+               return -1;
+       if (!pGRF_BASE) {
                pGRF_BASE = get_grf_base(np);
+               mutex_init(&bc_mutex);
+       }
 
+       mutex_lock(&bc_mutex);
        if (of_device_is_compatible(np, "rockchip,ctrl")) {
                if (!pBC_UOC_FIELDS)
                        uoc_init_rk(np);
-               return usb_battery_charger_detect_rk(wait);
+               ret = usb_battery_charger_detect_rk(wait);
        }
 
        else if (of_device_is_compatible(np, "synopsys,phy")) {
                if (!pBC_UOC_FIELDS)
                        uoc_init_synop(np);
-               return usb_battery_charger_detect_synop(wait);
+               ret = usb_battery_charger_detect_synop(wait);
        }
 
        else if (of_device_is_compatible(np, "inno,phy")) {
                if (!pBC_UOC_FIELDS)
                        uoc_init_inno(np);
-               return usb_battery_charger_detect_inno(wait);
+               ret = usb_battery_charger_detect_inno(wait);
        }
-fail:
-       return -1;
+       if (ret == USB_BC_TYPE_UNKNOW)
+               ret = USB_BC_TYPE_DCP;
+       mutex_unlock(&bc_mutex);
+       rk_battery_charger_detect_cb(ret);
+       return ret;
 }
 
-EXPORT_SYMBOL(usb_battery_charger_detect);
-
 int dwc_otg_check_dpdm(bool wait)
 {
-       static struct device_node *np;
-       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) ||
-                   !BC_GET(RK_BC_IDDIG))
-                       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) ||
-                   !BC_GET(SYNOP_BC_IDDIG))
-                       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;
+       return (is_connected() ? usb_charger_status : USB_BC_TYPE_DISCNT);
 }
 EXPORT_SYMBOL(dwc_otg_check_dpdm);
 
-/* CALL BACK FUNCTION for USB CHARGER TYPE CHANGED */
+/* Call back function for USB charger type changed */
+static ATOMIC_NOTIFIER_HEAD(rk_bc_notifier);
 
-void usb20otg_battery_charger_detect_cb(int charger_type_new)
+int rk_bc_detect_notifier_register(struct notifier_block *nb,
+                                          int *type)
 {
-       static int charger_type = USB_BC_TYPE_DISCNT;
-       if (charger_type != charger_type_new) {
-               switch (charger_type_new) {
-               case USB_BC_TYPE_DISCNT:
-                       break;
-
-               case USB_BC_TYPE_SDP:
-                       break;
-
-               case USB_BC_TYPE_DCP:
-                       break;
+       *type = (int)usb_battery_charger_detect(0);
+       return atomic_notifier_chain_register(&rk_bc_notifier, nb);
+}
+EXPORT_SYMBOL(rk_bc_detect_notifier_register);
 
-               case USB_BC_TYPE_CDP:
-                       break;
+int rk_bc_detect_notifier_unregister(struct notifier_block *nb)
+{
+       return atomic_notifier_chain_unregister(&rk_bc_notifier, nb);
+}
+EXPORT_SYMBOL(rk_bc_detect_notifier_unregister);
 
-               case USB_BC_TYPE_UNKNOW:
-                       break;
+void rk_bc_detect_notifier_callback(int bc_mode)
+{
+       atomic_notifier_call_chain(&rk_bc_notifier,bc_mode, NULL);
+}
 
-               default:
-                       break;
-               }
+void rk_battery_charger_detect_cb(int new_type)
+{
+       might_sleep();
 
-               /* printk("%s , battery_charger_detect %d\n",
-                *        __func__, charger_type_new);*/
+       if (usb_charger_status != new_type) {
+               printk("%s , battery_charger_detect %d\n", __func__, new_type);
+               atomic_notifier_call_chain(&rk_bc_notifier, new_type, NULL);
        }
-       charger_type = charger_type_new;
+       mutex_lock(&bc_mutex);
+       usb_charger_status = new_type;
+       mutex_unlock(&bc_mutex);
 }
index 52898230b510bc0fb2afa890195c1ad9b391085b..b4891d72721a223ca99b7d44c95e3323a462d772 100755 (executable)
@@ -10,6 +10,10 @@ enum bc_port_type{
        USB_BC_TYPE_UNKNOW,
        USB_BC_TYPE_MAX,
 };
+enum {
+       BC_BVALID = 0,
+       BC_IDDIG,
+};
 
 enum {
        SYNOP_BC_BVALID = 0,
@@ -67,9 +71,11 @@ USB Port Type
 2 : DCP - charger
 3 : CDP - pc with big currect charge
 ***********************************/
-
 extern int dwc_otg_check_dpdm(bool wait);
-extern int usb_battery_charger_detect(bool wait);
-extern void usb20otg_battery_charger_detect_cb(int charger_type_new);
+extern enum bc_port_type usb_battery_charger_detect(bool wait);
+extern void rk_battery_charger_detect_cb(int charger_type_new);
+extern int rk_bc_detect_register_notifier(struct notifier_block *nb,
+                                                 enum bc_port_type *type);
+extern int rk_bc_detect_unregister_notifier(struct notifier_block *nb);
 
 #endif
index 06584dd516ca443b3e981a9a18a02af220870b0d..fba8eea5173c9ac589a9d3058a2ccdd84517e019 100755 (executable)
@@ -52,7 +52,6 @@ enum rkusb_rst_flag {
        RST_OTHER,
 };
 
-extern int rk_usb_charger_status;
 extern void rk_send_wakeup_key(void);
 /* rk3188 platform data */
 extern struct dwc_otg_platform_data usb20otg_pdata_rk3188;
index dcdfb7d38e24ab6ccc21a10456b31acf85a0439e..7e7465fbb464354d620dbae0547a9590f80f7e41 100755 (executable)
@@ -158,7 +158,7 @@ struct dwc_otg_platform_data usb20otg_pdata_rk3188 = {
 #ifdef CONFIG_RK_USB_UART
        .dwc_otg_uart_mode = dwc_otg_uart_mode,
 #endif
-       .bc_detect_cb = usb20otg_battery_charger_detect_cb,
+       .bc_detect_cb = rk_battery_charger_detect_cb,
 };
 
 #endif
index 6f2e197cf8a4f420b18650556fde284542029606..2d507af84da100f6dbadc5f15533b0d4f5fe82e8 100755 (executable)
@@ -204,7 +204,7 @@ struct dwc_otg_platform_data usb20otg_pdata_rk3036 = {
        .get_status = usb20otg_get_status,
        .power_enable = usb20otg_power_enable,
        .dwc_otg_uart_mode = dwc_otg_uart_mode,
-       .bc_detect_cb = usb20otg_battery_charger_detect_cb,
+       .bc_detect_cb = rk_battery_charger_detect_cb,
 };
 #endif
 
@@ -392,7 +392,7 @@ static inline void do_wakeup(struct work_struct *work)
 
 static void usb_battery_charger_detect_work(struct work_struct *work)
 {
-       rk_usb_charger_status = usb_battery_charger_detect(0);
+       rk_battery_charger_detect_cb(usb_battery_charger_detect(1));
 }
 
 /********** handler for bvalid irq **********/
@@ -413,7 +413,6 @@ static irqreturn_t bvalid_irq_handler(int irq, void *dev_id)
                                      HZ / 10);
        }
 
-       rk_usb_charger_status = USB_BC_TYPE_SDP;
        schedule_delayed_work(&control_usb->usb_charger_det_work, HZ / 10);
 
        return IRQ_HANDLED;
@@ -571,11 +570,9 @@ static int dwc_otg_control_usb_probe(struct platform_device *pdev)
        clk_prepare_enable(hclk_usb_peri);
 
 #ifdef CONFIG_USB20_OTG
-       if (usb20otg_get_status(USB_STATUS_BVABLID)) {
-               rk_usb_charger_status = USB_BC_TYPE_SDP;
+       if (usb20otg_get_status(USB_STATUS_BVABLID))
                schedule_delayed_work(&control_usb->usb_charger_det_work,
                                      HZ / 10);
-       }
 #endif
 
        ret = otg_irq_detect_init(pdev);
index 4f7326ff6eb952c311c14d30466eaea3c886952e..ccc817b7d25eb0301eed9a37f318ecb430d14078 100755 (executable)
@@ -206,7 +206,7 @@ struct dwc_otg_platform_data usb20otg_pdata_rk3126 = {
        .get_status = usb20otg_get_status,
        .power_enable = usb20otg_power_enable,
        .dwc_otg_uart_mode = dwc_otg_uart_mode,
-       .bc_detect_cb = usb20otg_battery_charger_detect_cb,
+       .bc_detect_cb = rk_battery_charger_detect_cb,
 };
 #endif
 
@@ -400,7 +400,7 @@ static inline void do_wakeup(struct work_struct *work)
 
 static void usb_battery_charger_detect_work(struct work_struct *work)
 {
-       rk_usb_charger_status = usb_battery_charger_detect(0);
+       rk_battery_charger_detect_cb(usb_battery_charger_detect(1));
 }
 
 /********** handler for bvalid irq **********/
@@ -421,7 +421,6 @@ static irqreturn_t bvalid_irq_handler(int irq, void *dev_id)
                                      HZ / 10);
        }
 
-       rk_usb_charger_status = USB_BC_TYPE_SDP;
        schedule_delayed_work(&control_usb->usb_charger_det_work, HZ / 10);
 
        return IRQ_HANDLED;
@@ -579,11 +578,9 @@ static int dwc_otg_control_usb_probe(struct platform_device *pdev)
        clk_prepare_enable(hclk_usb_peri);
 
 #ifdef CONFIG_USB20_OTG
-       if (usb20otg_get_status(USB_STATUS_BVABLID)) {
-               rk_usb_charger_status = USB_BC_TYPE_SDP;
+       if (usb20otg_get_status(USB_STATUS_BVABLID))
                schedule_delayed_work(&control_usb->usb_charger_det_work,
                                      HZ / 10);
-       }
 #endif
 
        ret = otg_irq_detect_init(pdev);
index 6d28789d758d1b892fa1314071700a605cd8f667..e0394614614afe430df67f98140c8f5af1a135dd 100755 (executable)
@@ -195,7 +195,7 @@ struct dwc_otg_platform_data usb20otg_pdata_rk3288 = {
        .get_status = usb20otg_get_status,
        .power_enable = usb20otg_power_enable,
        .dwc_otg_uart_mode = dwc_otg_uart_mode,
-       .bc_detect_cb = usb20otg_battery_charger_detect_cb,
+       .bc_detect_cb = rk_battery_charger_detect_cb,
 };
 
 #endif
@@ -682,7 +682,7 @@ static inline void do_wakeup(struct work_struct *work)
 
 static void usb_battery_charger_detect_work(struct work_struct *work)
 {
-       rk_usb_charger_status = usb_battery_charger_detect(0);
+       rk_battery_charger_detect_cb(usb_battery_charger_detect(1));
 }
 
 /********** handler for bvalid irq **********/
@@ -700,8 +700,6 @@ static irqreturn_t bvalid_irq_handler(int irq, void *dev_id)
                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;
@@ -771,7 +769,6 @@ static int otg_irq_detect_init(struct platform_device *pdev)
 {
        int ret = 0;
        int irq = 0;
-
        if (control_usb->usb_irq_wakeup) {
                wake_lock_init(&control_usb->usb_wakelock, WAKE_LOCK_SUSPEND,
                               "usb_detect");
@@ -1112,11 +1109,9 @@ static int dwc_otg_control_usb_probe(struct platform_device *pdev)
                goto err2;
        }
 #ifdef CONFIG_USB20_OTG
-       if (usb20otg_get_status(USB_STATUS_BVABLID)) {
-               rk_usb_charger_status = USB_BC_TYPE_SDP;
+       if (usb20otg_get_status(USB_STATUS_BVABLID))
                schedule_delayed_work(&control_usb->usb_charger_det_work,
                                      HZ / 10);
-       }
 #endif
 
        ret = otg_irq_detect_init(pdev);