| From 5bf5dbeda2454296f1984adfbfc8e6f5965ac389 Mon Sep 17 00:00:00 2001 |
| From: Matthieu CASTET <matthieu.castet@parrot.com> |
| Date: Wed, 19 Feb 2014 13:46:31 +0800 |
| Subject: usb: chipidea: need to mask when writting endptflush and endptprime |
| |
| From: Matthieu CASTET <matthieu.castet@parrot.com> |
| |
| commit 5bf5dbeda2454296f1984adfbfc8e6f5965ac389 upstream. |
| |
| ENDPTFLUSH and ENDPTPRIME registers are set by software and clear |
| by hardware. There is a bit for each endpoint. When we are setting |
| a bit for an endpoint we should make sure we do not touch other |
| endpoint bit. There is a race condition if the hardware clear the |
| bit between the read and the write in hw_write. |
| |
| Signed-off-by: Peter Chen <peter.chen@freescale.com> |
| Signed-off-by: Matthieu CASTET <matthieu.castet@parrot.com> |
| Tested-by: Michael Grzeschik <mgrzeschik@pengutronix.de> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/chipidea/udc.c | 4 ++-- |
| 1 file changed, 2 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/usb/chipidea/udc.c |
| +++ b/drivers/usb/chipidea/udc.c |
| @@ -105,7 +105,7 @@ static int hw_ep_flush(struct ci_hdrc *c |
| |
| do { |
| /* flush any pending transfer */ |
| - hw_write(ci, OP_ENDPTFLUSH, BIT(n), BIT(n)); |
| + hw_write(ci, OP_ENDPTFLUSH, ~0, BIT(n)); |
| while (hw_read(ci, OP_ENDPTFLUSH, BIT(n))) |
| cpu_relax(); |
| } while (hw_read(ci, OP_ENDPTSTAT, BIT(n))); |
| @@ -205,7 +205,7 @@ static int hw_ep_prime(struct ci_hdrc *c |
| if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num))) |
| return -EAGAIN; |
| |
| - hw_write(ci, OP_ENDPTPRIME, BIT(n), BIT(n)); |
| + hw_write(ci, OP_ENDPTPRIME, ~0, BIT(n)); |
| |
| while (hw_read(ci, OP_ENDPTPRIME, BIT(n))) |
| cpu_relax(); |