aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Boyd <stephen.boyd@linaro.org>2016-12-28 17:56:50 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-05-14 08:00:18 -0400
commit8eb8c9b16fddec79abc084b0e9b677f66de42fcf (patch)
tree12424e1796a5941a52548d07369739233f572d58
parent4a36b6a7ee882cd0ffdbfb8c9ce8097b8abea973 (diff)
usb: chipidea: Only read/write OTGSC from one place
commit f60f8ccd54e03c1afafb2b20ceb029a0eaf7a134 upstream. With the id and vbus detection done via extcon we need to make sure we poll the status of OTGSC properly by considering what the extcon is saying, and not just what the register is saying. Let's move this hw_wait_reg() function to the only place it's used and simplify it for polling the OTGSC register. Then we can make certain we only use the hw_read_otgsc() API to read OTGSC, which will make sure we properly handle extcon events. Acked-by: Peter Chen <peter.chen@nxp.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: "Ivan T. Ivanov" <iivanov.xz@gmail.com> Fixes: 3ecb3e09b042 ("usb: chipidea: Use extcon framework for VBUS and ID detect") Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org> Signed-off-by: Peter Chen <peter.chen@nxp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/chipidea/ci.h3
-rw-r--r--drivers/usb/chipidea/core.c32
-rw-r--r--drivers/usb/chipidea/otg.c34
3 files changed, 30 insertions, 39 deletions
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index cd414559040f..05bc4d631cb9 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -428,9 +428,6 @@ int hw_port_test_set(struct ci_hdrc *ci, u8 mode);
428 428
429u8 hw_port_test_get(struct ci_hdrc *ci); 429u8 hw_port_test_get(struct ci_hdrc *ci);
430 430
431int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask,
432 u32 value, unsigned int timeout_ms);
433
434void ci_platform_configure(struct ci_hdrc *ci); 431void ci_platform_configure(struct ci_hdrc *ci);
435 432
436int dbg_create_files(struct ci_hdrc *ci); 433int dbg_create_files(struct ci_hdrc *ci);
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 3dbb4a21ab44..6e0d614a8075 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -516,38 +516,6 @@ int hw_device_reset(struct ci_hdrc *ci)
516 return 0; 516 return 0;
517} 517}
518 518
519/**
520 * hw_wait_reg: wait the register value
521 *
522 * Sometimes, it needs to wait register value before going on.
523 * Eg, when switch to device mode, the vbus value should be lower
524 * than OTGSC_BSV before connects to host.
525 *
526 * @ci: the controller
527 * @reg: register index
528 * @mask: mast bit
529 * @value: the bit value to wait
530 * @timeout_ms: timeout in millisecond
531 *
532 * This function returns an error code if timeout
533 */
534int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask,
535 u32 value, unsigned int timeout_ms)
536{
537 unsigned long elapse = jiffies + msecs_to_jiffies(timeout_ms);
538
539 while (hw_read(ci, reg, mask) != value) {
540 if (time_after(jiffies, elapse)) {
541 dev_err(ci->dev, "timeout waiting for %08x in %d\n",
542 mask, reg);
543 return -ETIMEDOUT;
544 }
545 msleep(20);
546 }
547
548 return 0;
549}
550
551static irqreturn_t ci_irq(int irq, void *data) 519static irqreturn_t ci_irq(int irq, void *data)
552{ 520{
553 struct ci_hdrc *ci = data; 521 struct ci_hdrc *ci = data;
diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c
index 03b6743461d1..a829607c3e4d 100644
--- a/drivers/usb/chipidea/otg.c
+++ b/drivers/usb/chipidea/otg.c
@@ -104,7 +104,31 @@ void ci_handle_vbus_change(struct ci_hdrc *ci)
104 usb_gadget_vbus_disconnect(&ci->gadget); 104 usb_gadget_vbus_disconnect(&ci->gadget);
105} 105}
106 106
107#define CI_VBUS_STABLE_TIMEOUT_MS 5000 107/**
108 * When we switch to device mode, the vbus value should be lower
109 * than OTGSC_BSV before connecting to host.
110 *
111 * @ci: the controller
112 *
113 * This function returns an error code if timeout
114 */
115static int hw_wait_vbus_lower_bsv(struct ci_hdrc *ci)
116{
117 unsigned long elapse = jiffies + msecs_to_jiffies(5000);
118 u32 mask = OTGSC_BSV;
119
120 while (hw_read_otgsc(ci, mask)) {
121 if (time_after(jiffies, elapse)) {
122 dev_err(ci->dev, "timeout waiting for %08x in OTGSC\n",
123 mask);
124 return -ETIMEDOUT;
125 }
126 msleep(20);
127 }
128
129 return 0;
130}
131
108static void ci_handle_id_switch(struct ci_hdrc *ci) 132static void ci_handle_id_switch(struct ci_hdrc *ci)
109{ 133{
110 enum ci_role role = ci_otg_role(ci); 134 enum ci_role role = ci_otg_role(ci);
@@ -116,9 +140,11 @@ static void ci_handle_id_switch(struct ci_hdrc *ci)
116 ci_role_stop(ci); 140 ci_role_stop(ci);
117 141
118 if (role == CI_ROLE_GADGET) 142 if (role == CI_ROLE_GADGET)
119 /* wait vbus lower than OTGSC_BSV */ 143 /*
120 hw_wait_reg(ci, OP_OTGSC, OTGSC_BSV, 0, 144 * wait vbus lower than OTGSC_BSV before connecting
121 CI_VBUS_STABLE_TIMEOUT_MS); 145 * to host
146 */
147 hw_wait_vbus_lower_bsv(ci);
122 148
123 ci_role_start(ci, role); 149 ci_role_start(ci, role);
124 } 150 }