USB: musb: add two states to handle vbus error
PATCH 1/2 USB: musb: add two states to handle vbus error
When the MUSB is configured as host mode or OTG mode, the xceiv->state will be set to OTG_STATE_A_IDLE or OTG_STATE_B_IDLE unconditionally during init process. These init states can change to other states When the MUSB module detects id pin change, devices connect or disconnect.
But on some platforms(omap2, omap3), the id pin change can't raise IRQ request to the MUSB module, so on these platforms, the init xceiv->state will be A_IDLE or B_IDLE. Under this condition, when we want the MUSB to act as a host and hotplug a usb device in mini-B side of the cable, the MUSB will have a possibility to suffer power underrun under A_IDLE or B_IDLE state, So here adding these two states under which we can handle VBUSERROR IRQ.
--- drivers/usb/musb/musb_core.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
drivers/usb/musb/musb_core.c +2 -0
@@ -516,6 +516,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,* another reset is due (at least for high speed, * to redo the chirp etc), it might work OK... */ +case OTG_STATE_A_IDLE : +case OTG_STATE_B_IDLE :case OTG_STATE_A_WAIT_BCON :case OTG_STATE_A_WAIT_VRISE :if (musb->vbuserr_retry) {
Signature · 1 line
1.5.6.5
PATCH 1/2 USB: musb: add two states to handle vbus error
On omap platforms, when configuring the kernel, if we choose the musb work as host or OTG mode and we plug a mini-A cable into the socket, after the kernel boot up in host mode or insmod gadget driver in OTG mode, the state of musb's xceiv is A_IDLE or B_IDLE correspondingly because id change can't trigger ISR. Under this condition, if we hotplug a usb device(without self-powered) at the other side of the cable, the musb will suffer a vbus error, This patch can handle this vbus error.
Quoted 32 lines · Wang Hui
When the MUSB is configured as host mode or OTG mode, the
xceiv->statewill be set toOTG_STATE_A_IDLEorOTG_STATE_B_IDLEunconditionally during init process. These init states can change to other states When the MUSB module detects id pin change, devices connect or disconnect.
But on someplatforms(omap2, omap3), the id pin change can't raise IRQ request to the MUSB module, so on these platforms, the initxceiv->statewill beA_IDLEorB_IDLE. Under this condition, when we want the MUSB to act as a host and hotplug a usb device in mini-B side of the cable, the MUSB will have a possibility to suffer power underrun underA_IDLEorB_IDLEstate, So here adding these two states under which we can handle VBUSERROR IRQ.Signed-off-by Wang Hui <[email protected]>--- drivers/usb/musb/musb_core.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)drivers/usb/musb/musb_core.c +2
-0@@ -516,6 +516,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,* another reset is due (at least for high speed, * to redo the chirp etc), it might work OK... */ +case OTG_STATE_A_IDLE : +case OTG_STATE_B_IDLE :case OTG_STATE_A_WAIT_BCON :case OTG_STATE_A_WAIT_VRISE :if (musb->vbuserr_retry) {
PATCH 2/2 USB: musb: omap2430: add mode change from A to B
In reply to Wang HuiOn omap2/3 series platforms, the musb can't raise id pin change detection interrupt, so we must change otg mode through sysfs interface manually. Currently when the musb is in B mode, if we want musb to be changed to A mode, we should plug a mini-A cable and then execute echo host > /sys/devices/platform/musb_hdrc/mode. But if the musb is in A mode, we can't change it to B mode through this method.
To solve this problem, add a process for sending end session request. This process works like this, if the musb is in A mode, it will send an end session request first, then it will follow original routine:
start a new session, during this session, it will identify whether A or B is plugging in the socket, then it will init controller to A or B mode according to its identification.
Usage: change cable as you desired,
change musb mode by #>echo host[peripheral] > /sys/devices/\
platform/musb_hdrc/mode,
then you will get required musb mode.
--- drivers/usb/musb/omap2430.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
drivers/usb/musb/omap2430.c +5 -0
@@ -194,6 +194,11 @@ int musb_platform_set_mode(struct musb *musb, u8 musb_mode) {u8 devctl =musb_readb (musb->mregs,MUSB_DEVCTL ); +if ((devctl &MUSB_DEVCTL_BDEVICE ) ==0x0 ) { + devctl &= ~MUSB_DEVCTL_SESSION ; +musb_writeb (musb->mregs,MUSB_DEVCTL , devctl); + } + devctl |=MUSB_DEVCTL_SESSION ;musb_writeb (musb->mregs,MUSB_DEVCTL , devctl);
Signature · 1 line
1.5.6.5
PATCH 2/2 USB: musb: omap2430: add mode change from A to B
Hello.
Quoted 30 lines · Wang Hui
On omap2/3 series platforms, the musb can't raise id pin change detection interrupt, so we must change otg mode through sysfs interface manually. Currently when the musb is in B mode, if we want musb to be changed to A mode, we should plug a mini-A cable and then execute echo host >
/sys/devices/platform/musb_hdrc/mode. But if the musb is in A mode, we can't change it to B mode through this method.
To solve this problem, add a process for sending end session request. This process works like this, if the musb is in A mode, it will send an end session request first, then it will follow original routine:
start a new session, during this session, it will identify whether A or B is plugging in the socket, then it will init controller to A or B mode according to its identification.Usage: change cable as you desired,
change musb mode by #>echo host[peripheral] > /sys/devices/\
platform/musb_hdrc/mode,
then you will get required musb mode.Signed-off-by Wang Hui <[email protected]>--- drivers/usb/musb/omap2430.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)drivers/usb/musb/omap2430.c +0
-0@@ -194,6 +194,11 @@ int musb_platform_set_mode(struct musb *musb, u8 musb_mode) {
drivers/usb/musb/omap2430.c int musb_platform_set_mode(struct musb *musb, u8 musb_mode) · line 204
Quoted 10 lines
drivers/usb/musb/omap2430.c +5
-0u8 devctl =musb_readb (musb->mregs,MUSB_DEVCTL ); +if ((devctl &MUSB_DEVCTL_BDEVICE ) ==0x0 ) { + devctl &= ~MUSB_DEVCTL_SESSION ; +musb_writeb (musb->mregs,MUSB_DEVCTL , devctl); + } + devctl |=MUSB_DEVCTL_SESSION ;musb_writeb (musb->mregs,MUSB_DEVCTL , devctl);
The whole musb_platform_set_mode() seems to be implemented
incorrectly on OMAPs -- it shouldn't touch the DevCtl.Session bit. This function should control the ID pin override instead -- if the controller supports it. SRP must be initiated thru other means, i.e. 'srp' file in sysfs.
WBR, Sergei
PATCH 2/2 USB: musb: omap2430: add mode change from A to B
Quoted 2 lines · Sergei Shtylyov
The whole
musb_platform_set_mode()seems to be implemented
incorrectly on OMAPs -- it shouldn't touch the DevCtl.Session bit. This
correct. It should be changing the id pin rules just like in tusb6010.c
Quoted 3 lines
function should control the ID pin override instead -- if the controller supports it. SRP must be initiated thru other means, i.e. 'srp' file in sysfs.
via musb_gadget_wakeup()
Signature · 1 line
balbi
PATCH 2/2 USB: musb: omap2430: add mode change from A to B
Quoted 6 lines · Felipe Balbi
Quoted 3 lines · Sergei Shtylyov
The whole
musb_platform_set_mode()seems to be implemented
incorrectly on OMAPs -- it shouldn't touch the DevCtl.Session bit. This
Quoted 9 lines
correct. It should be changing the id pin rules just like in
tusb6010.cQuoted 2 lines
function should control the ID pin override instead -- if the controller supports it. SRP must be initiated thru other means, i.e. 'srp' file in sysfs.
via
musb_gadget_wakeup()
Thank you for your comments.
It is right that in this function, we should only change id pin rules according to user's choice, and
leave mode transition to the ISR.
But things are different on omap platforms, because the id pin change can't trigger ISR.
For example, when we configure the kernel, we choose musb working as OTG mode. Then we plug a mini-A or a mini-B cable in the socket, after that we execute insmod g_ether.ko, at this time, the musb will initialize to A or B working mode. how to change
its working mode from A to B or B to A at this time? I think if the platform can support id detection ISR, your method
is workable. But on omap platforms, we must change cable(id pin state) manually first, then let the controller to re-initiate a session forcibly. This action (clear/set session bit) don't 100% equal to send a SRP, and i don't really want to send a SRP too.
If without this function for omap platforms, we can change musb working mode only through rebooting kernel or rmmod/insmod gadget driver module.
PATCH 2/2 USB: musb: omap2430: add mode change from A to B
Hi,
Quoted 17 lines · wanghui
Thank you for your comments.
It is right that in this function, we should only change id pin rules according to user's choice, and
leave mode transition to the ISR.
But things are different on omap platforms, because the id pin change can't trigger ISR.
For example, when we configure the kernel, we choose musb working as OTG mode. Then we plug a mini-A or a mini-B cable in the socket, after that we execute insmod g_ether.ko, at this time, the musb will initialize to A or B working mode. how to change
its working mode from A to B or B to A at this time? I think if the platform can support id detection ISR, your method
is workable. But on omap platforms, we must change cable(id pin state) manually first, then let the controller to re-initiate a session forcibly. This action (clear/set session bit) don't 100% equal to send a SRP, and i don't really want to send a SRP too.
Quoted 2 lines
If without this function for omap platforms, we can change musb working mode only through rebooting kernel or rmmod/insmod gadget driver module.
it should be doable with the transceiver ISR. When you get id pin irq, you should put the transceiver into A_IDLE state and power up vbus. MUSB changes to host mode automatically.
Signature · 1 line
balbi
PATCH 2/2 USB: musb: omap2430: add mode change from A to B
In reply to Wang Hui--text follows this line--
Hi,
Quoted 5 lines · Wang Hui
On omap2/3 series platforms, the musb can't raise id pin change detection interrupt, so we must change otg mode through sysfs interface manually. Currently when the musb is in B mode, if we want musb to be changed to A mode, we should plug a mini-A cable and then execute echo host >
/sys/devices/platform/musb_hdrc/mode.
Quoted 8 lines
But if the musb is in A mode, we can't change it to B mode through this method.
To solve this problem, add a process for sending end session request. This process works like this, if the musb is in A mode, it will send an end session request first, then it will follow original routine:
start a new session, during this session, it will identify whether A or B is plugging in the socket, then it will init controller to A or B mode according to its identification.
Just curious about how to do this in a more automatic way.
I think setup a daemon to monitor the musb_hdrc mode and try to alter it's state via sysfs interface will work, but it may be error prone and not always desirable solution.
Can we query the id pin state periodically in the kernel and change to corresponding role?
Regards,
Kanru
Quoted 34 lines
Usage: change cable as you desired,
change musb mode by #>echo host[peripheral] > /sys/devices/\
platform/musb_hdrc/mode,
then you will get required musb mode.Signed-off-by Wang Hui <[email protected]>--- drivers/usb/musb/omap2430.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)drivers/usb/musb/omap2430.c +5
-0@@ -194,6 +194,11 @@ int musb_platform_set_mode(struct musb *musb, u8 musb_mode) {u8 devctl =musb_readb (musb->mregs,MUSB_DEVCTL ); +if ((devctl &MUSB_DEVCTL_BDEVICE ) ==0x0 ) { + devctl &= ~MUSB_DEVCTL_SESSION ; +musb_writeb (musb->mregs,MUSB_DEVCTL , devctl); + } + devctl |=MUSB_DEVCTL_SESSION ;musb_writeb (musb->mregs,MUSB_DEVCTL , devctl);Signature · 6 lines
1.5.6.5 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo at vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 2/2 USB: musb: omap2430: add mode change from A to B
Quoted 8 lines · Kan-Ru Chen
Just curious about how to do this in a more automatic way.
I think setup a daemon to monitor the
musb_hdrcmode and try to alter it's state via sysfs interface will work, but it may be error prone and not always desirable solution.Can we query the id pin state periodically in the kernel and change to corresponding role?
the transceiver has an interrupt for id pin changes. You can use that instead of polling.
Signature · 1 line
balbi
PATCH 2/2 USB: musb: omap2430: add mode change from A to B
Quoted 7 lines · Felipe Balbi
Quoted 6 lines · Kan-Ru Chen
Just curious about how to do this in a more automatic way.
I think setup a daemon to monitor the
musb_hdrcmode and try to alter it's state via sysfs interface will work, but it may be error prone and not always desirable solution.
Quoted 5 lines
Quoted 2 lines
Can we query the id pin state periodically in the kernel and change to corresponding role?
the transceiver has an interrupt for id pin changes. You can use that instead of polling.
Thanks, I see.
The twl4030_usb transceiver did get the id pin chanegs
<7>twl4030_usb twl4030_usb: HW_CONDITIONS 0x50/80; link 1
<7>twl4030_usb twl4030_usb: HW_CONDITIONS 0x54/84; link 3So the problem is when OTG enter a_host mode then disconnected, it becomes idle. Plug the peripheral device back would not trigger new session unless I do "echo otg > /sys/devices/platform/musb_hdrc/mode"