aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/chipidea/otg.c18
-rw-r--r--drivers/usb/chipidea/otg.h1
-rw-r--r--drivers/usb/chipidea/udc.c30
-rw-r--r--include/linux/usb/chipidea.h5
4 files changed, 51 insertions, 3 deletions
diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c
index 49b4e2513445..bdf3f41b6cc2 100644
--- a/drivers/usb/chipidea/otg.c
+++ b/drivers/usb/chipidea/otg.c
@@ -39,6 +39,24 @@ enum ci_role ci_otg_role(struct ci_hdrc *ci)
39 return role; 39 return role;
40} 40}
41 41
42void ci_handle_vbus_connected(struct ci_hdrc *ci)
43{
44 u32 otgsc;
45
46 /*
47 * TODO: if the platform does not supply 5v to udc, or use other way
48 * to supply 5v, it needs to use other conditions to call
49 * usb_gadget_vbus_connect.
50 */
51 if (!ci->is_otg)
52 return;
53
54 otgsc = hw_read(ci, OP_OTGSC, ~0);
55
56 if (otgsc & OTGSC_BSV)
57 usb_gadget_vbus_connect(&ci->gadget);
58}
59
42void ci_handle_vbus_change(struct ci_hdrc *ci) 60void ci_handle_vbus_change(struct ci_hdrc *ci)
43{ 61{
44 u32 otgsc; 62 u32 otgsc;
diff --git a/drivers/usb/chipidea/otg.h b/drivers/usb/chipidea/otg.h
index 2d9f090733bc..f171e6b9b6ba 100644
--- a/drivers/usb/chipidea/otg.h
+++ b/drivers/usb/chipidea/otg.h
@@ -31,5 +31,6 @@ int ci_hdrc_otg_init(struct ci_hdrc *ci);
31void ci_hdrc_otg_destroy(struct ci_hdrc *ci); 31void ci_hdrc_otg_destroy(struct ci_hdrc *ci);
32enum ci_role ci_otg_role(struct ci_hdrc *ci); 32enum ci_role ci_otg_role(struct ci_hdrc *ci);
33void ci_handle_vbus_change(struct ci_hdrc *ci); 33void ci_handle_vbus_change(struct ci_hdrc *ci);
34void ci_handle_vbus_connected(struct ci_hdrc *ci);
34 35
35#endif /* __DRIVERS_USB_CHIPIDEA_OTG_H */ 36#endif /* __DRIVERS_USB_CHIPIDEA_OTG_H */
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index b34c81969cba..2359ce526ef0 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -1448,6 +1448,7 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
1448 struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); 1448 struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget);
1449 unsigned long flags; 1449 unsigned long flags;
1450 int gadget_ready = 0; 1450 int gadget_ready = 0;
1451 int ret;
1451 1452
1452 spin_lock_irqsave(&ci->lock, flags); 1453 spin_lock_irqsave(&ci->lock, flags);
1453 ci->vbus_active = is_active; 1454 ci->vbus_active = is_active;
@@ -1455,6 +1456,31 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
1455 gadget_ready = 1; 1456 gadget_ready = 1;
1456 spin_unlock_irqrestore(&ci->lock, flags); 1457 spin_unlock_irqrestore(&ci->lock, flags);
1457 1458
1459 /* Charger Detection */
1460 if (ci->platdata->notify_event) {
1461 /*
1462 * Keep controller active when the cable is connected,
1463 * It can make disconnect interrupt (BSV 1->0) occur when
1464 * the cable is disconnected.
1465 */
1466 if (is_active)
1467 pm_runtime_get_sync(&_gadget->dev);
1468 else
1469 pm_runtime_put_sync(&_gadget->dev);
1470
1471 ret = ci->platdata->notify_event
1472 (ci, CI_HDRC_CONTROLLER_CHARGER_EVENT);
1473 if (ret == CI_HDRC_NOTIFY_RET_DEFER_EVENT) {
1474 hw_device_reset(ci, USBMODE_CM_DC);
1475 /* Pull up dp */
1476 hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS);
1477 ci->platdata->notify_event
1478 (ci, CI_HDRC_CONTROLLER_CHARGER_POST_EVENT);
1479 /* Pull down dp */
1480 hw_write(ci, OP_USBCMD, USBCMD_RS, 0);
1481 }
1482 }
1483
1458 if (gadget_ready) { 1484 if (gadget_ready) {
1459 if (is_active) { 1485 if (is_active) {
1460 pm_runtime_get_sync(&_gadget->dev); 1486 pm_runtime_get_sync(&_gadget->dev);
@@ -1795,8 +1821,8 @@ static int udc_start(struct ci_hdrc *ci)
1795 pm_runtime_no_callbacks(&ci->gadget.dev); 1821 pm_runtime_no_callbacks(&ci->gadget.dev);
1796 pm_runtime_enable(&ci->gadget.dev); 1822 pm_runtime_enable(&ci->gadget.dev);
1797 1823
1798 /* Update ci->vbus_active */ 1824 /* Notify vbus connected event if it is existed */
1799 ci_handle_vbus_change(ci); 1825 ci_handle_vbus_connected(ci);
1800 1826
1801 return retval; 1827 return retval;
1802 1828
diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h
index 8c3b7e2ec5a1..c75433e763e7 100644
--- a/include/linux/usb/chipidea.h
+++ b/include/linux/usb/chipidea.h
@@ -30,7 +30,10 @@ struct ci_hdrc_platform_data {
30 enum usb_dr_mode dr_mode; 30 enum usb_dr_mode dr_mode;
31#define CI_HDRC_CONTROLLER_RESET_EVENT 0 31#define CI_HDRC_CONTROLLER_RESET_EVENT 0
32#define CI_HDRC_CONTROLLER_STOPPED_EVENT 1 32#define CI_HDRC_CONTROLLER_STOPPED_EVENT 1
33 void (*notify_event) (struct ci_hdrc *ci, unsigned event); 33#define CI_HDRC_CONTROLLER_CHARGER_EVENT 2
34#define CI_HDRC_CONTROLLER_CHARGER_POST_EVENT 3
35 int (*notify_event) (struct ci_hdrc *ci, unsigned event);
36#define CI_HDRC_NOTIFY_RET_DEFER_EVENT 1
34 struct regulator *reg_vbus; 37 struct regulator *reg_vbus;
35}; 38};
36 39