usb: cdns3: misc improvements
Subsystems (3)
cover usb: cdns3: misc improvements
Peter Chen (5):
usb: cdns3: core: quit if it uses role switch class
usb: cdns3: gadget: set fast access bit
usb: cdns3: gadget: clear the interrupt status when disconnect the
host
usb: cdns3: drd: call PHY .set_mode accordingly
usb: cdns3: gadget: move wait configuration operation
drivers/usb/cdns3/core.c | 4 ++++ drivers/usb/cdns3/drd.c | 5 +++++ drivers/usb/cdns3/ep0.c | 10 +++++++++- drivers/usb/cdns3/gadget.c | 15 ++++++++------- 4 files changed, 26 insertions(+), 8 deletions(-)
Signature · 1 line
2.17.1
PATCH 1/5 usb: cdns3: core: quit if it uses role switch class
If the board uses role switch class for switching the role, it should not depends on SoC OTG hardware siginal any more, so quit early.
--- drivers/usb/cdns3/core.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/usb/cdns3/core.c +4 -0
@@ -280,6 +280,10 @@ int cdns3_hw_role_switch(struct cdns3 *cdns)enum usb_role real_role, current_role;int ret =0 ; +/* Depends on role switch class */ +if (cdns->role_sw) +return 0 ; +pm_runtime_get_sync (cdns->dev); current_role = cdns->role;
Signature · 1 line
2.17.1
Re: [PATCH 1/5] usb: cdns3: core: quit if it uses role switch class
Peter/Felipe,
Quoted 13 lines · Peter Chen
If the board uses role switch class for switching the role, it should not depends on SoC OTG hardware siginal any more, so quit early.
Signed-off-by Peter Chen <[email protected]>--- drivers/usb/cdns3/core.c | 4 ++++ 1 file changed, 4 insertions(+)drivers/usb/cdns3/core.c +0
-0
drivers/usb/cdns3/core.c int cdns3_hw_role_switch(struct cdns3 *cdns) · line 286
Quoted 7 lines
drivers/usb/cdns3/core.c +4
-0@@ -280,6 +280,10 @@ int cdns3_hw_role_switch(struct cdns3 *cdns)enum usb_role real_role, current_role;int ret =0 ; +/* Depends on role switch class */ +if (cdns->role_sw) +return 0 ; +
This breaks h/w based role switching for us.
cdsn->role_sw would always be non zero, right, which means h/w based role swithching will be bypassed for all platforms.
drivers/usb/cdns3/core.c int cdns3_hw_role_switch(struct cdns3 *cdns) · line 289
Quoted 4 lines
drivers/usb/cdns3/core.c +0
-0pm_runtime_get_sync (cdns->dev); current_role = cdns->role;
cheers,
-roger
Signature · 2 lines
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
PATCH 2/5 usb: cdns3: gadget: set fast access bit
In reply to Peter ChenBelow is the recommendation from Cadence designer:
Using this bit to be sure that PHY clock is keeping up in active state. It's good to keep Fast Access bit enabled as long as there is any access to USB register.
It is used to fix the potential ARM core hang when visit controller register after DEVDS (.pullup is cleared) is set, the threaded irq may be scheduled at that time.
--- drivers/usb/cdns3/gadget.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/usb/cdns3/gadget.c +3 -0
@@ -2783,6 +2783,8 @@ static void cdns3_gadget_config(struct cdns3_device *priv_dev)/* enable generic interrupt*/ writel (USB_IEN_INIT , ®s->usb_ien);writel (USB_CONF_CLK2OFFDS |USB_CONF_L1DS , ®s->usb_conf); +/* keep Fast Access bit */ +writel (PUSB_PWR_FST_REG_ACCESS , &priv_dev->regs->usb_pwr);cdns3_configure_dmult (priv_dev,NULL ); }
@@ -2866,6 +2868,7 @@ static int cdns3_gadget_udc_stop(struct usb_gadget *gadget)/* disable interrupt for device */ writel (0 , &priv_dev->regs->usb_ien); +writel (0 , &priv_dev->regs->usb_pwr);writel (USB_CONF_DEVDS , &priv_dev->regs->usb_conf);return 0 ;
Signature · 1 line
2.17.1
PATCH 3/5 usb: cdns3: gadget: clear the interrupt status when disconnect the host
In reply to Peter ChenIt is meaningless to handle any interrupts after disconnecting with host
--- drivers/usb/cdns3/gadget.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/usb/cdns3/gadget.c +5 -2
@@ -2739,10 +2739,13 @@ static int cdns3_gadget_pullup(struct usb_gadget *gadget, int is_on) {struct cdns3_device *priv_dev =gadget_to_cdns3_device (gadget); -if (is_on) +if (is_on) {writel (USB_CONF_DEVEN , &priv_dev->regs->usb_conf); -else + }else { +writel (~0 , &priv_dev->regs->ep_ists); +writel (~0 , &priv_dev->regs->usb_ists);writel (USB_CONF_DEVDS , &priv_dev->regs->usb_conf); + }return 0 ; }
Signature · 1 line
2.17.1
PATCH 4/5 usb: cdns3: drd: call PHY .set_mode accordingly
In reply to Peter ChenSome PHYs may need to enter related mode, and do some settings.
--- drivers/usb/cdns3/drd.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/usb/cdns3/drd.c +5 -0
@@ -15,6 +15,7 @@#include <linux/delay.h> #include <linux/iopoll.h> #include <linux/usb/otg.h> +#include <linux/phy/phy.h> #include "gadget.h" #include "drd.h"
@@ -145,6 +146,7 @@ int cdns3_drd_host_on(struct cdns3 *cdns)if (ret)dev_err (cdns->dev,"timeout waiting for xhci_ready\n" ); +phy_set_mode (cdns->usb3_phy,PHY_MODE_USB_HOST );return ret; }
@@ -164,6 +166,7 @@ void cdns3_drd_host_off(struct cdns3 *cdns)readl_poll_timeout_atomic (&cdns->otg_regs->state, val, !(val &OTGSTATE_HOST_STATE_MASK ),1 ,2000000 ); +phy_set_mode (cdns->usb3_phy,PHY_MODE_INVALID ); }/**
@@ -190,6 +193,7 @@ int cdns3_drd_gadget_on(struct cdns3 *cdns)return ret; } +phy_set_mode (cdns->usb3_phy,PHY_MODE_USB_DEVICE );return 0 ; }
@@ -213,6 +217,7 @@ void cdns3_drd_gadget_off(struct cdns3 *cdns)readl_poll_timeout_atomic (&cdns->otg_regs->state, val, !(val &OTGSTATE_DEV_STATE_MASK ),1 ,2000000 ); +phy_set_mode (cdns->usb3_phy,PHY_MODE_INVALID ); }/**
Signature · 1 line
2.17.1
PATCH 5/5 usb: cdns3: gadget: move wait configuration operation
In reply to Peter ChenAfter commit f4cfe5ce607d ("usb: cdns3: gadget: improve the set_configuration handling"), the software will inform the hardware the request has finished at cdns3_ep0_complete_setup. The configuration set bit is only set after request has finished, so it needs to move waiting operation after that. Meanwhile, if it is timeout, it will show warning message and return error.
--- drivers/usb/cdns3/ep0.c | 10 +++++++++- drivers/usb/cdns3/gadget.c | 5 ----- 2 files changed, 9 insertions(+), 6 deletions(-)
drivers/usb/cdns3/ep0.c +9 -1
@@ -717,9 +717,17 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep,/* send STATUS stage. Should be called only for SET_CONFIGURATION */ if (priv_dev->ep0_stage ==CDNS3_STATUS_STAGE ) { +u32 val; +cdns3_select_ep (priv_dev,0x00 );cdns3_set_hw_configuration (priv_dev);cdns3_ep0_complete_setup (priv_dev,0 ,1 ); +/* wait until configuration set */ + ret =readl_poll_timeout_atomic (&priv_dev->regs->usb_sts, val, + val &USB_STS_CFGSTS_MASK ,1 ,100 ); +if (ret == -ETIMEDOUT ) +dev_warn (priv_dev->dev,"timeout for waiting configuration set\n" ); + request->actual =0 ; priv_dev->status_completion_no_call = true; priv_dev->pending_status_request = request;
@@ -731,7 +739,7 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep,* ep0_queue is back. */ queue_work (system_freezable_wq, &priv_dev->pending_status_wq); -return 0 ; +return ret; }if (!list_empty (&priv_ep->pending_req_list)) {
drivers/usb/cdns3/gadget.c +0 -5
@@ -1309,7 +1309,6 @@ void cdns3_set_hw_configuration(struct cdns3_device *priv_dev) {struct cdns3_endpoint *priv_ep;struct usb_ep *ep; -int val;if (priv_dev->hw_configured_flag)return ;
@@ -1319,10 +1318,6 @@ void cdns3_set_hw_configuration(struct cdns3_device *priv_dev)cdns3_set_register_bit (&priv_dev->regs->usb_conf,USB_CONF_U1EN |USB_CONF_U2EN ); -/* wait until configuration set */ -readl_poll_timeout_atomic (&priv_dev->regs->usb_sts, val, - val &USB_STS_CFGSTS_MASK ,1 ,100 ); - priv_dev->hw_configured_flag =1 ;list_for_each_entry (ep, &priv_dev->gadget.ep_list, ep_list) {
Signature · 1 line
2.17.1
Quoted 9 lines · Peter Chen
Peter Chen (5):
usb: cdns3: core: quit if it uses role switch class
usb: cdns3: gadget: set fast access bit
usb: cdns3: gadget: clear the interrupt status when disconnect the
host
usb: cdns3: drd: call PHY .set_mode accordingly
usb: cdns3: gadget: move wait configuration operation
Quoted 7 lines
drivers/usb/cdns3/core.c | 4 ++++ drivers/usb/cdns3/drd.c | 5 +++++ drivers/usb/cdns3/ep0.c | 10 +++++++++- drivers/usb/cdns3/gadget.c | 15 ++++++++------- 4 files changed, 26 insertions(+), 8 deletions(-)--
A gentle ping.
Peter