MLK-10085-5 usb: chipidea: Add usb charger detect notify
authorLi Jun <b47624@freescale.com>
Fri, 9 Jan 2015 07:35:07 +0000 (15:35 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 19:46:57 +0000 (14:46 -0500)
- Change .notify's return value from void to int, update msm notify_event
  return value accordingly.
- Add CI_HDRC_CONTROLLER_VBUS_EVENT and
  CI_HDRC_CONTROLLER_CHARGER_POST_EVENT to finish the USB charger
  detection flow.

Signed-off-by: Peter Chen <peter.chen@freescale.com>
Signed-off-by: Li Jun <jun.li@freescale.com>
drivers/usb/chipidea/ci_hdrc_msm.c
drivers/usb/chipidea/core.c
drivers/usb/chipidea/otg.c
drivers/usb/chipidea/otg.h
drivers/usb/chipidea/otg_fsm.c
drivers/usb/chipidea/udc.c
drivers/usb/chipidea/udc.h
include/linux/usb/chipidea.h

index 37591a4..6d5cf97 100644 (file)
@@ -17,7 +17,7 @@
 
 #define MSM_USB_BASE   (ci->hw_bank.abs)
 
-static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
+static int ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
 {
        struct device *dev = ci->gadget.dev.parent;
 
@@ -40,6 +40,8 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
                dev_dbg(dev, "unknown ci_hdrc event\n");
                break;
        }
+
+       return 0;
 }
 
 static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = {
index 6e0d614..fd19dc4 100644 (file)
@@ -982,11 +982,11 @@ static int ci_hdrc_probe(struct platform_device *pdev)
                        : CI_ROLE_GADGET;
        }
 
-       if (!ci_otg_is_fsm_mode(ci)) {
-               /* only update vbus status for peripheral */
-               if (ci->role == CI_ROLE_GADGET)
-                       ci_handle_vbus_change(ci);
+       /* only update vbus status for peripheral */
+       if (ci->role == CI_ROLE_GADGET)
+               ci_handle_vbus_connected(ci);
 
+       if (!ci_otg_is_fsm_mode(ci)) {
                ret = ci_role_start(ci, ci->role);
                if (ret) {
                        dev_err(dev, "can't start %s role\n",
index f36a1ac..dad2a07 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * otg.c - ChipIdea USB IP core OTG driver
  *
- * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ * Copyright (C) 2013-2015 Freescale Semiconductor, Inc.
  *
  * Author: Peter Chen
  *
@@ -129,6 +129,20 @@ enum ci_role ci_otg_role(struct ci_hdrc *ci)
        return role;
 }
 
+void ci_handle_vbus_connected(struct ci_hdrc *ci)
+{
+       /*
+        * TODO: if the platform does not supply 5v to udc, or use other way
+        * to supply 5v, it needs to use other conditions to call
+        * usb_gadget_vbus_connect.
+        */
+       if (!ci->is_otg)
+               return;
+
+       if (hw_read_otgsc(ci, OTGSC_BSV))
+               usb_gadget_vbus_connect(&ci->gadget);
+}
+
 void ci_handle_vbus_change(struct ci_hdrc *ci)
 {
        if (!ci->is_otg)
index 9ecb598..1c9ad1a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2014 Freescale Semiconductor, Inc.
+ * Copyright (C) 2013-2015 Freescale Semiconductor, Inc.
  *
  * Author: Peter Chen
  *
@@ -17,6 +17,7 @@ int ci_hdrc_otg_init(struct ci_hdrc *ci);
 void ci_hdrc_otg_destroy(struct ci_hdrc *ci);
 enum ci_role ci_otg_role(struct ci_hdrc *ci);
 void ci_handle_vbus_change(struct ci_hdrc *ci);
+void ci_handle_vbus_connected(struct ci_hdrc *ci);
 static inline void ci_otg_queue_work(struct ci_hdrc *ci)
 {
        disable_irq_nosync(ci->irq);
index 7f9e800..2a2fe13 100644 (file)
@@ -28,6 +28,7 @@
 #include "ci.h"
 #include "bits.h"
 #include "otg.h"
+#include "udc.h"
 #include "otg_fsm.h"
 
 /* Add for otg: interact with user space app */
@@ -563,10 +564,7 @@ static int ci_otg_start_gadget(struct otg_fsm *fsm, int on)
 {
        struct ci_hdrc  *ci = container_of(fsm, struct ci_hdrc, fsm);
 
-       if (on)
-               usb_gadget_vbus_connect(&ci->gadget);
-       else
-               usb_gadget_vbus_disconnect(&ci->gadget);
+       ci_hdrc_gadget_connect(&ci->gadget, on);
 
        return 0;
 }
index 2baa017..caf2a73 100644 (file)
@@ -1539,26 +1539,11 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
                gadget_ready = 1;
        spin_unlock_irqrestore(&ci->lock, flags);
 
-       if (gadget_ready) {
-               if (is_active) {
-                       pm_runtime_get_sync(&_gadget->dev);
-                       hw_device_reset(ci);
-                       hw_device_state(ci, ci->ep0out->qh.dma);
-                       usb_gadget_set_state(_gadget, USB_STATE_POWERED);
-                       usb_udc_vbus_handler(_gadget, true);
-               } else {
-                       usb_udc_vbus_handler(_gadget, false);
-                       if (ci->driver)
-                               ci->driver->disconnect(&ci->gadget);
-                       hw_device_state(ci, 0);
-                       if (ci->platdata->notify_event)
-                               ci->platdata->notify_event(ci,
-                               CI_HDRC_CONTROLLER_STOPPED_EVENT);
-                       _gadget_stop_activity(&ci->gadget);
-                       pm_runtime_put_sync(&_gadget->dev);
-                       usb_gadget_set_state(_gadget, USB_STATE_NOTATTACHED);
-               }
-       }
+       /* Charger Detection */
+       ci_usb_charger_connect(ci, is_active);
+
+       if (gadget_ready)
+               ci_hdrc_gadget_connect(_gadget, is_active);
 
        return 0;
 }
@@ -1970,6 +1955,58 @@ void ci_hdrc_gadget_destroy(struct ci_hdrc *ci)
        dma_pool_destroy(ci->qh_pool);
 }
 
+int ci_usb_charger_connect(struct ci_hdrc *ci, int is_active)
+{
+       int ret = 0;
+
+       if (ci->platdata->notify_event) {
+               pm_runtime_get_sync(&ci->gadget.dev);
+               if (is_active)
+                       hw_write(ci, OP_USBCMD, USBCMD_RS, 0);
+
+               ret = ci->platdata->notify_event(ci,
+                               CI_HDRC_CONTROLLER_VBUS_EVENT);
+               if (ret == CI_HDRC_NOTIFY_RET_DEFER_EVENT) {
+                       hw_device_reset(ci);
+                       /* Pull up dp */
+                       hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS);
+                       ci->platdata->notify_event(ci,
+                               CI_HDRC_CONTROLLER_CHARGER_POST_EVENT);
+                       /* Pull down dp */
+                       hw_write(ci, OP_USBCMD, USBCMD_RS, 0);
+               }
+               pm_runtime_put_sync(&ci->gadget.dev);
+       }
+       return ret;
+}
+
+/**
+ * ci_hdrc_gadget_connect: caller make sure gadget driver is binded
+ */
+void ci_hdrc_gadget_connect(struct usb_gadget *gadget, int is_active)
+{
+       struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget);
+
+       if (is_active) {
+               pm_runtime_get_sync(&gadget->dev);
+               hw_device_reset(ci);
+               hw_device_state(ci, ci->ep0out->qh.dma);
+               usb_gadget_set_state(gadget, USB_STATE_POWERED);
+               usb_udc_vbus_handler(gadget, true);
+       } else {
+               usb_udc_vbus_handler(gadget, false);
+               if (ci->driver)
+                       ci->driver->disconnect(gadget);
+               hw_device_state(ci, 0);
+               if (ci->platdata->notify_event)
+                       ci->platdata->notify_event(ci,
+                       CI_HDRC_CONTROLLER_STOPPED_EVENT);
+               _gadget_stop_activity(gadget);
+               pm_runtime_put_sync(&gadget->dev);
+               usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
+       }
+}
+
 static int udc_id_switch_for_device(struct ci_hdrc *ci)
 {
        if (ci->is_otg)
index e66df00..7c3af66 100644 (file)
@@ -85,6 +85,8 @@ struct ci_hw_req {
 
 int ci_hdrc_gadget_init(struct ci_hdrc *ci);
 void ci_hdrc_gadget_destroy(struct ci_hdrc *ci);
+int ci_usb_charger_connect(struct ci_hdrc *ci, int is_active);
+void ci_hdrc_gadget_connect(struct usb_gadget *gadget, int is_active);
 
 #else
 
@@ -98,6 +100,17 @@ static inline void ci_hdrc_gadget_destroy(struct ci_hdrc *ci)
 
 }
 
+static inline int ci_usb_charger_connect(struct ci_hdrc *ci, int is_active)
+{
+       return 0;
+}
+
+static inline void ci_hdrc_gadget_connect(struct usb_gadget *gadget,
+                                                       int is_active)
+{
+
+}
+
 #endif
 
 #endif /* __DRIVERS_USB_CHIPIDEA_UDC_H */
index f9be467..3fcb7b3 100644 (file)
@@ -60,7 +60,10 @@ struct ci_hdrc_platform_data {
        enum usb_dr_mode        dr_mode;
 #define CI_HDRC_CONTROLLER_RESET_EVENT         0
 #define CI_HDRC_CONTROLLER_STOPPED_EVENT       1
-       void    (*notify_event) (struct ci_hdrc *ci, unsigned event);
+#define CI_HDRC_CONTROLLER_VBUS_EVENT          2
+#define CI_HDRC_NOTIFY_RET_DEFER_EVENT         3
+#define CI_HDRC_CONTROLLER_CHARGER_POST_EVENT  4
+       int     (*notify_event)(struct ci_hdrc *ci, unsigned event);
        struct regulator        *reg_vbus;
        struct usb_otg_caps     ci_otg_caps;
        bool                    tpl_support;