usb: dwc2: gadget: Add LPM functionality
Subsystems (2)
cover usb: dwc2: gadget: Add LPM functionality
This series adds LPM functionality for gadget side. In USB 2 for LPM support 2.01 version and additional BOS descriptors needed to be sent to indicate LPM support so usb: gadget: composite: was patched to support that.
Tested on HAPS platform with DWC_hsotg IP version 3.30a from device side and from host side HAPS platform with DWC USB3 IP version 3.20a.
John Youn (3):
[HSLPM] usb: gadget: composite: Exclude SS Dev Cap Desc [HSLPM] usb: gadget: Allow a non-SuperSpeed gadget to support LPM [HSLPM] usb: dwc2: Enable LPM
Sevak Arakelyan (6):
usb: dwc2: Fix GLPMCFG... definitions
usb: dwc2: Add core parameters for LPM support
usb: dwc2: gadget: Add functionality to exit from LPM L1 state
usb: dwc2: gadget: LPM interrupt handler
usb: dwc2: Enable LPM Transaction Received interrupt.
usb: dwc2: gadget: Configure the core to enable LPM.
drivers/usb/dwc2/core.h | 22 ++++++++ drivers/usb/dwc2/core_intr.c | 113 ++++++++++++++++++++++++++++++++++++++++- drivers/usb/dwc2/debugfs.c | 5 ++ drivers/usb/dwc2/gadget.c | 28 +++++++++- drivers/usb/dwc2/hcd.c | 3 ++ drivers/usb/dwc2/hw.h | 38 +++++++------- drivers/usb/dwc2/params.c | 13 +++++ drivers/usb/gadget/composite.c | 59 ++++++++++++--------- include/linux/usb/gadget.h | 3 ++ 9 files changed, 239 insertions(+), 45 deletions(-)
Signature · 1 line
2.11.0
PATCH 1/9 usb: dwc2: Fix GLPMCFG... definitions
Make field names of GLPMCFG register in definitoins to be the same with the databook.
--- drivers/usb/dwc2/hw.h | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-)
drivers/usb/dwc2/hw.h +20 -18
@@ -319,28 +319,30 @@#define GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT 0#define GLPMCFG HSOTG_REG(0x0054) -#define GLPMCFG_INV_SEL_HSIC BIT(31) -#define GLPMCFG_HSIC_CONNECT BIT(30) -#define GLPMCFG_RETRY_COUNT_STS_MASK (0x7 << 25) -#define GLPMCFG_RETRY_COUNT_STS_SHIFT 25 -#define GLPMCFG_SEND_LPM BIT(24) -#define GLPMCFG_RETRY_COUNT_MASK (0x7 << 21) -#define GLPMCFG_RETRY_COUNT_SHIFT 21 -#define GLPMCFG_LPM_CHAN_INDEX_MASK (0xf << 17) -#define GLPMCFG_LPM_CHAN_INDEX_SHIFT 17 -#define GLPMCFG_SLEEP_STATE_RESUMEOK BIT(16) -#define GLPMCFG_PRT_SLEEP_STS BIT(15) -#define GLPMCFG_LPM_RESP_MASK (0x3 << 13) -#define GLPMCFG_LPM_RESP_SHIFT 13 +#define GLPMCFG_INVSELHSIC BIT(31) +#define GLPMCFG_HSICCON BIT(30) +#define GLPMCFG_RSTRSLPSTS BIT(29) +#define GLPMCFG_ENBESL BIT(28) +#define GLPMCFG_LPM_RETRYCNT_STS_MASK (0x7 << 25) +#define GLPMCFG_LPM_RETRYCNT_STS_SHIFT 25 +#define GLPMCFG_SNDLPM BIT(24) +#define GLPMCFG_RETRY_CNT_MASK (0x7 << 21) +#define GLPMCFG_RETRY_CNT_SHIFT 21 +#define GLPMCFG_LPM_CHNL_INDX_MASK (0xf << 17) +#define GLPMCFG_LPM_CHNL_INDX_SHIFT 17 +#define GLPMCFG_L1RESUMEOK BIT(16) +#define GLPMCFG_SLPSTS BIT(15) +#define GLPMCFG_COREL1RES_MASK (0x3 << 13) +#define GLPMCFG_COREL1RES_SHIFT 13#define GLPMCFG_HIRD_THRES_MASK (0x1f << 8)#define GLPMCFG_HIRD_THRES_SHIFT 8 -#define GLPMCFG_HIRD_THRES_EN (0x10 << 8) -#define GLPMCFG_EN_UTMI_SLEEP BIT(7) -#define GLPMCFG_REM_WKUP_EN BIT(6) +#define GLPMCFG_HIRD_THRES_EN (0x10 << 8) +#define GLPMCFG_ENBLSLPM (1 << 7) +#define GLPMCFG_BREMOTEWAKE (1 << 6)#define GLPMCFG_HIRD_MASK (0xf << 2)#define GLPMCFG_HIRD_SHIFT 2 -#define GLPMCFG_APPL_RESP BIT(1) -#define GLPMCFG_LPM_CAP_EN BIT(0) +#define GLPMCFG_APPL1RES BIT(1) +#define GLPMCFG_LPMCAP BIT(0)#define GPWRDN HSOTG_REG(0x0058)#define GPWRDN_MULT_VAL_ID_BC_MASK (0x1f << 24)
Signature · 1 line
2.11.0
PATCH 2/9 usb: dwc2: Add core parameters for LPM support
In reply to Sevak ArakelyanAdd lpm, lpm_clock_gating, besl, hird_threshold_en and hird_threshold core parameters. These will indicate LPM and LPM Errata support as well as chosen L1 sleeping mode for the core and PHY.
--- drivers/usb/dwc2/core.h | 20 ++++++++++++++++++++ drivers/usb/dwc2/debugfs.c | 5 +++++ drivers/usb/dwc2/params.c | 13 +++++++++++++ 3 files changed, 38 insertions(+)
drivers/usb/dwc2/core.h +20 -0
@@ -423,6 +423,19 @@ enum dwc2_ep0_state {* needed. * 0 - No (default) * 1 - Yes +* @lpm: Enable LPM support. +* 0 - No (default) +* 1 - Yes +* @lpm_clock_gating: Enable core PHY clock gating. +* 0 - No (default) +* 1 - Yes +* @besl: Enable LPM Errata support. +* 0 - No (default) +* 1 - Yes +* @hird_threshold_en: HIRD or HIRD Threshold enable. +* 0 - No (default) +* 1 - Yes +* @hird_threshold: Value of BESL or HIRD Threshold. * @activate_stm_fs_transceiver: Activate internal transceiver using GGPIO * register. * 0 - Deactivate the transceiver (default)
@@ -481,6 +494,11 @@ struct dwc2_core_params {bool uframe_sched;bool external_id_pin_ctl;bool hibernation; +bool lpm; +bool lpm_clock_gating; +bool besl; +bool hird_threshold_en; +u8 hird_threshold;bool activate_stm_fs_transceiver;u16 max_packet_count;u32 max_transfer_size;
@@ -585,6 +603,7 @@ struct dwc2_hw_params { unsigned total_fifo_size:16; unsigned power_optimized:1; unsigned utmi_phy_data_width:2; + unsigned lpm_mode:1;u32 snpsid;u32 dev_ep_dirs; };
@@ -937,6 +956,7 @@ struct dwc2_hsotg {/* DWC OTG HW Release versions */ #define DWC2_CORE_REV_2_71a 0x4f54271a +#define DWC2_CORE_REV_2_80a 0x4f54280a#define DWC2_CORE_REV_2_90a 0x4f54290a#define DWC2_CORE_REV_2_91a 0x4f54291a#define DWC2_CORE_REV_2_92a 0x4f54292a
drivers/usb/dwc2/debugfs.c +5 -0
@@ -763,6 +763,11 @@ static int params_show(struct seq_file *seq, void *v)print_param (seq, p, uframe_sched);print_param (seq, p, external_id_pin_ctl);print_param (seq, p, hibernation); +print_param (seq, p, lpm); +print_param (seq, p, lpm_clock_gating); +print_param (seq, p, besl); +print_param (seq, p, hird_threshold_en); +print_param (seq, p, hird_threshold);print_param (seq, p, host_dma);print_param (seq, p, g_dma);print_param (seq, p, g_dma_desc);
drivers/usb/dwc2/params.c +13 -0
@@ -264,6 +264,11 @@ static void dwc2_set_default_params(struct dwc2_hsotg *hsotg) p->uframe_sched = true; p->external_id_pin_ctl = false; p->hibernation = false; + p->lpm = false; + p->lpm_clock_gating = false; + p->besl = false; + p->hird_threshold_en = false; + p->hird_threshold =0 ; p->max_packet_count = hw->max_packet_count; p->max_transfer_size = hw->max_transfer_size; p->ahbcfg =GAHBCFG_HBSTLEN_INCR4 <<GAHBCFG_HBSTLEN_SHIFT ;
@@ -511,6 +516,13 @@ static void dwc2_check_params(struct dwc2_hsotg *hsotg)CHECK_BOOL (en_multiple_tx_fifo, hw->en_multiple_tx_fifo);CHECK_BOOL (i2c_enable, hw->i2c_enable);CHECK_BOOL (reload_ctl, (hsotg->hw_params.snpsid > DWC2_CORE_REV_2_92a)); +CHECK_BOOL (lpm, (hsotg->hw_params.snpsid >= DWC2_CORE_REV_2_80a)); +CHECK_BOOL (lpm, hw->lpm_mode); +CHECK_BOOL (lpm_clock_gating, hsotg->params.lpm); +CHECK_BOOL (besl, hsotg->params.lpm); +CHECK_BOOL (besl, (hsotg->hw_params.snpsid >= DWC2_CORE_REV_3_00a)); +CHECK_BOOL (hird_threshold_en, hsotg->params.lpm); +CHECK_RANGE (hird_threshold,0 , hsotg->params.besl ?12 :7 ,0 );CHECK_RANGE (max_packet_count,15 , hw->max_packet_count, hw->max_packet_count);
@@ -689,6 +701,7 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) hw->i2c_enable = !!(hwcfg3 &GHWCFG3_I2C ); hw->total_fifo_size = (hwcfg3 &GHWCFG3_DFIFO_DEPTH_MASK ) >>GHWCFG3_DFIFO_DEPTH_SHIFT ; + hw->lpm_mode = !!(hwcfg3 &GHWCFG3_OTG_LPM_EN );/* hwcfg4 */ hw->en_multiple_tx_fifo = !!(hwcfg4 &GHWCFG4_DED_FIFO_EN );
Signature · 1 line
2.11.0
PATCH 3/9 usb: dwc2: gadget: Add functionality to exit from LPM L1 state
In reply to Sevak ArakelyanAdd a function which will be called if device is in L1 sleep state and Resume/Remote Wakeup Detected interrupt is asserted.
--- drivers/usb/dwc2/core_intr.c | 49 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+)
drivers/usb/dwc2/core_intr.c +49 -0
@@ -334,6 +334,50 @@ static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg) } } +/** +* dwc2_wakeup_from_lpm_l1 - Exit the device from LPM L1 state +*/ +static void dwc2_wakeup_from_lpm_l1 (struct dwc2_hsotg *hsotg) +{ +u32 glpmcfg; +u32 i =0 ; + +if (hsotg->lx_state !=DWC2_L1 ) { +dev_err (hsotg->dev,"Core isn't in DWC2_L1 state\n" ); +return ; + } + + glpmcfg =dwc2_readl (hsotg->regs +GLPMCFG ); +if (dwc2_is_device_mode (hsotg)) { +dev_dbg (hsotg->dev,"Exit from L1 state\n" ); + glpmcfg &= ~GLPMCFG_ENBLSLPM ; + glpmcfg &= ~GLPMCFG_HIRD_THRES_EN ; +dwc2_writel (glpmcfg, hsotg->regs +GLPMCFG ); + +do { + glpmcfg =dwc2_readl (hsotg->regs +GLPMCFG ); + +if (!(glpmcfg & (GLPMCFG_COREL1RES_MASK | +GLPMCFG_L1RESUMEOK |GLPMCFG_SLPSTS ))) +break ; + +udelay (1 ); + }while (++i <200 ); + +if (i ==200 ) { +dev_err (hsotg->dev,"Failed to exit L1 sleep state in 200us.\n" ); +return ; + } + }else { +/* TODO */ +dev_err (hsotg->dev,"Host side LPM is not supported.\n" ); +return ; + } + +/* Change to L0 state */ + hsotg->lx_state =DWC2_L0 ; +} +/* * This interrupt indicates that the DWC_otg controller has detected a * resume or remote wakeup sequence. If the DWC_otg controller is in
@@ -351,6 +395,11 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)dev_dbg (hsotg->dev,"++Resume or Remote Wakeup Detected Interrupt++\n" );dev_dbg (hsotg->dev,"%s lxstate = %d\n" , __func__, hsotg->lx_state); +if (hsotg->lx_state ==DWC2_L1 ) { +dwc2_wakeup_from_lpm_l1 (hsotg); +return ; + } +if (dwc2_is_device_mode (hsotg)) {dev_dbg (hsotg->dev,"DSTS=0x%0x\n" ,dwc2_readl (hsotg->regs +DSTS ));
Signature · 1 line
2.11.0
PATCH 4/9 usb: dwc2: gadget: LPM interrupt handler
In reply to Sevak ArakelyanThis interrupt indicates that an LPM transaction
was received on the USB bus. After getting this
interrupt we are going from L0 state to L1 state.
--- drivers/usb/dwc2/core_intr.c | 60 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+)
drivers/usb/dwc2/core_intr.c +60 -0
@@ -527,6 +527,64 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg) } } +/** +* dwc2_handle_lpm_intr - GINTSTS_LPMTRANRCVD Interrupt handler +*/ +static void dwc2_handle_lpm_intr (struct dwc2_hsotg *hsotg) +{ +u32 glpmcfg; +u32 pcgcctl; +u32 hird; +u32 hird_thres; +u32 hird_thres_en; +u32 enslpm; + +/* Clear interrupt */ +dwc2_writel (GINTSTS_LPMTRANRCVD , hsotg->regs +GINTSTS ); + + glpmcfg =dwc2_readl (hsotg->regs +GLPMCFG ); + +if (!(glpmcfg &GLPMCFG_LPMCAP )) { +dev_err (hsotg->dev,"Unexpected LPM interrupt\n" ); +return ; + } + + hird = (glpmcfg &GLPMCFG_HIRD_MASK ) >>GLPMCFG_HIRD_SHIFT ; + hird_thres = (glpmcfg &GLPMCFG_HIRD_MASK & ~GLPMCFG_HIRD_THRES_EN ) >> +GLPMCFG_HIRD_THRES_SHIFT ; + hird_thres_en = glpmcfg &GLPMCFG_HIRD_THRES_EN ; + enslpm = glpmcfg &GLPMCFG_SNDLPM ; + +if (dwc2_is_device_mode (hsotg)) { +dev_dbg (hsotg->dev,"HIRD_THRES_EN = %d\n" , hird_thres_en); + +if (hird_thres_en && hird >= hird_thres) { +dev_dbg (hsotg->dev,"L1 with utmi_l1_suspend_n\n" ); + }else if (enslpm) { +dev_dbg (hsotg->dev,"L1 with utmi_sleep_n\n" ); + }else { +dev_dbg (hsotg->dev,"Entering Sleep with L1 Gating\n" ); + + pcgcctl =dwc2_readl (hsotg->regs +PCGCTL ); + pcgcctl |=PCGCTL_ENBL_SLEEP_GATING ; +dwc2_writel (pcgcctl, hsotg->regs +PCGCTL ); + } +/** +* Examine prt_sleep_sts after TL1TokenTetry period max (10 us) +*/ +udelay (10 ); + + glpmcfg =dwc2_readl (hsotg->regs +GLPMCFG ); + +if (glpmcfg &&GLPMCFG_SLPSTS ) { +/* Save the current state */ + hsotg->lx_state =DWC2_L1 ; +dev_dbg (hsotg->dev, +"Core is in L1 sleep glpmcfg=%08x\n" , glpmcfg); + } + } +} +#define GINTMSK_COMMON (GINTSTS_WKUPINT | GINTSTS_SESSREQINT | \ GINTSTS_CONIDSTSCHNG | GINTSTS_OTGINT | \ GINTSTS_MODEMIS | GINTSTS_DISCONNINT | \
@@ -601,6 +659,8 @@ irqreturn_t dwc2_handle_common_intr(int irq, void *dev)dwc2_handle_wakeup_detected_intr (hsotg);if (gintsts &GINTSTS_USBSUSP )dwc2_handle_usb_suspend_intr (hsotg); +if (gintsts &GINTSTS_LPMTRANRCVD ) +dwc2_handle_lpm_intr (hsotg);if (gintsts &GINTSTS_PRTINT ) {/*
Signature · 1 line
2.11.0
PATCH 5/9 usb: dwc2: Enable LPM Transaction Received interrupt.
In reply to Sevak ArakelyanEnable LPM Trasaction Received interrupt.
--- drivers/usb/dwc2/core_intr.c | 5 +++-- drivers/usb/dwc2/gadget.c | 3 ++- drivers/usb/dwc2/hcd.c | 3 +++ 3 files changed, 8 insertions(+), 3 deletions(-)
drivers/usb/dwc2/core_intr.c +3 -2
@@ -553,7 +553,7 @@ static void dwc2_handle_lpm_intr(struct dwc2_hsotg *hsotg) hird_thres = (glpmcfg &GLPMCFG_HIRD_MASK & ~GLPMCFG_HIRD_THRES_EN ) >>GLPMCFG_HIRD_THRES_SHIFT ; hird_thres_en = glpmcfg &GLPMCFG_HIRD_THRES_EN ; - enslpm = glpmcfg &GLPMCFG_SNDLPM ; + enslpm = glpmcfg &GLPMCFG_ENBLSLPM ;if (dwc2_is_device_mode (hsotg)) {dev_dbg (hsotg->dev,"HIRD_THRES_EN = %d\n" , hird_thres_en);
@@ -588,7 +588,8 @@ static void dwc2_handle_lpm_intr(struct dwc2_hsotg *hsotg)#define GINTMSK_COMMON (GINTSTS_WKUPINT | GINTSTS_SESSREQINT | \ GINTSTS_CONIDSTSCHNG | GINTSTS_OTGINT | \ GINTSTS_MODEMIS | GINTSTS_DISCONNINT | \ - GINTSTS_USBSUSP | GINTSTS_PRTINT) + GINTSTS_USBSUSP | GINTSTS_PRTINT | \ + GINTSTS_LPMTRANRCVD)/* * This function returns the Core Interrupt register
drivers/usb/dwc2/gadget.c +2 -1
@@ -3315,7 +3315,8 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,GINTSTS_GOUTNAKEFF |GINTSTS_GINNAKEFF |GINTSTS_USBRST |GINTSTS_RESETDET |GINTSTS_ENUMDONE |GINTSTS_OTGINT | -GINTSTS_USBSUSP |GINTSTS_WKUPINT ; +GINTSTS_USBSUSP |GINTSTS_WKUPINT | +GINTSTS_LPMTRANRCVD ;if (!using_desc_dma (hsotg)) intmsk |=GINTSTS_INCOMPL_SOIN |GINTSTS_INCOMPL_SOOUT ;
drivers/usb/dwc2/hcd.c +3 -0
@@ -90,6 +90,9 @@ static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg) intmsk |=GINTSTS_WKUPINT |GINTSTS_USBSUSP |GINTSTS_SESSREQINT ; +if (dwc2_is_device_mode (hsotg) && hsotg->params.lpm) + intmsk |=GINTSTS_LPMTRANRCVD ; +dwc2_writel (intmsk, hsotg->regs +GINTMSK ); }
Signature · 1 line
2.11.0
PATCH 6/9 usb: dwc2: gadget: Configure the core to enable LPM.
In reply to Sevak ArakelyanConfigure core in device mode to support LPM according to programming guide.
Device will start giving valid responses for LPM tokens. After this patch device side LPM will start working.
--- drivers/usb/dwc2/core.h | 2 ++ drivers/usb/dwc2/core_intr.c | 1 + drivers/usb/dwc2/gadget.c | 22 ++++++++++++++++++++++ 3 files changed, 25 insertions(+)
drivers/usb/dwc2/core.h +2 -0
@@ -1201,6 +1201,7 @@ int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg);int dwc2_hsotg_tx_fifo_count (struct dwc2_hsotg *hsotg);int dwc2_hsotg_tx_fifo_total_depth (struct dwc2_hsotg *hsotg);int dwc2_hsotg_tx_fifo_average_depth (struct dwc2_hsotg *hsotg); +void dwc2_gadget_init_lpm (struct dwc2_hsotg *hsotg);#else static inline int dwc2_hsotg_remove (struct dwc2_hsotg *dwc2) {return 0 ; }
@@ -1228,6 +1229,7 @@ static inline int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg) {return 0 ; }static inline int dwc2_hsotg_tx_fifo_average_depth (struct dwc2_hsotg *hsotg) {return 0 ; } +static inline void dwc2_gadget_init_lpm (struct dwc2_hsotg *hsotg) {}#endif #if IS_ENABLED (CONFIG_USB_DWC2_HOST ) ||IS_ENABLED (CONFIG_USB_DWC2_DUAL_ROLE )
drivers/usb/dwc2/core_intr.c +1 -0
@@ -368,6 +368,7 @@ static void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg)dev_err (hsotg->dev,"Failed to exit L1 sleep state in 200us.\n" );return ; } +dwc2_gadget_init_lpm (hsotg); }else {/* TODO */ dev_err (hsotg->dev,"Host side LPM is not supported.\n" );
drivers/usb/dwc2/gadget.c +22 -0
@@ -3427,6 +3427,9 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, val |=DCTL_SFTDISCON ;__orr32 (hsotg->regs +DCTL , val); +/* configure the core to support LPM */ +dwc2_gadget_init_lpm (hsotg); +/* must be at-least 3ms to allow bus to see disconnect */ mdelay (3 );
@@ -4648,6 +4651,7 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq) hsotg->gadget.max_speed =USB_SPEED_HIGH ; hsotg->gadget.ops = &dwc2_hsotg_gadget_ops; hsotg->gadget.name =dev_name (dev); +if (hsotg->dr_mode ==USB_DR_MODE_OTG ) hsotg->gadget.is_otg =1 ;else if (hsotg->dr_mode ==USB_DR_MODE_PERIPHERAL )
@@ -4886,3 +4890,21 @@ int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg)return 0 ; } + +/** +* dwc2_gadget_init_lpm - Configure the core to support LPM in device mode +*/ +void dwc2_gadget_init_lpm (struct dwc2_hsotg *hsotg) +{ +u32 val; + +if (!hsotg->params.lpm) +return ; + + val =GLPMCFG_LPMCAP |GLPMCFG_APPL1RES ; + val |= hsotg->params.hird_threshold_en ?GLPMCFG_HIRD_THRES_EN :0 ; + val |= hsotg->params.lpm_clock_gating ?GLPMCFG_ENBLSLPM :0 ; +dwc2_writel (val, hsotg->regs +GLPMCFG ); +dev_dbg (hsotg->dev,"GLPMCFG=0x%08x\n" ,dwc2_readl (hsotg->regs + +GLPMCFG )); +}
Signature · 1 line
2.11.0
PATCH 7/9 usb: gadget: composite: Exclude SS Dev Cap Desc
In reply to Sevak ArakelyanFrom: John Youn <[email protected]>
Don't send the SuperSpeed USB Device Capability descriptor if the gadget is not capable of SuperSpeed.
--- drivers/usb/gadget/composite.c | 51 +++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 23 deletions(-)
drivers/usb/gadget/composite.c +28 -23
@@ -607,7 +607,6 @@ static int count_configs(struct usb_composite_dev *cdev, unsigned type)static int bos_desc (struct usb_composite_dev *cdev) {struct usb_ext_cap_descriptor *usb_ext; -struct usb_ss_cap_descriptor *ss_cap;struct usb_dcd_config_params dcd_config_params;struct usb_bos_descriptor *bos = cdev->req->buf;
@@ -633,29 +632,35 @@ static int bos_desc(struct usb_composite_dev *cdev)* The Superspeed USB Capability descriptor shall be implemented by all * SuperSpeed devices. */ - ss_cap = cdev->req->buf +le16_to_cpu (bos->wTotalLength); - bos->bNumDeviceCaps++; -le16_add_cpu (&bos->wTotalLength,USB_DT_USB_SS_CAP_SIZE ); - ss_cap->bLength =USB_DT_USB_SS_CAP_SIZE ; - ss_cap->bDescriptorType =USB_DT_DEVICE_CAPABILITY ; - ss_cap->bDevCapabilityType =USB_SS_CAP_TYPE ; - ss_cap->bmAttributes =0 ;/* LTM is not supported yet */ - ss_cap->wSpeedSupported =cpu_to_le16 (USB_LOW_SPEED_OPERATION | -USB_FULL_SPEED_OPERATION | -USB_HIGH_SPEED_OPERATION | -USB_5GBPS_OPERATION ); - ss_cap->bFunctionalitySupport =USB_LOW_SPEED_OPERATION ; - -/* Get Controller configuration */ -if (cdev->gadget->ops->get_config_params) - cdev->gadget->ops->get_config_params (&dcd_config_params); -else { - dcd_config_params.bU1devExitLat =USB_DEFAULT_U1_DEV_EXIT_LAT ; - dcd_config_params.bU2DevExitLat = -cpu_to_le16 (USB_DEFAULT_U2_DEV_EXIT_LAT ); +if (gadget_is_superspeed (cdev->gadget)) { +struct usb_ss_cap_descriptor *ss_cap; + + ss_cap = cdev->req->buf +le16_to_cpu (bos->wTotalLength); + bos->bNumDeviceCaps++; +le16_add_cpu (&bos->wTotalLength,USB_DT_USB_SS_CAP_SIZE ); + ss_cap->bLength =USB_DT_USB_SS_CAP_SIZE ; + ss_cap->bDescriptorType =USB_DT_DEVICE_CAPABILITY ; + ss_cap->bDevCapabilityType =USB_SS_CAP_TYPE ; + ss_cap->bmAttributes =0 ;/* LTM is not supported yet */ + ss_cap->wSpeedSupported =cpu_to_le16 (USB_LOW_SPEED_OPERATION | +USB_FULL_SPEED_OPERATION | +USB_HIGH_SPEED_OPERATION | +USB_5GBPS_OPERATION ); + ss_cap->bFunctionalitySupport =USB_LOW_SPEED_OPERATION ; + +/* Get Controller configuration */ +if (cdev->gadget->ops->get_config_params) { + cdev->gadget->ops->get_config_params ( + &dcd_config_params); + }else { + dcd_config_params.bU1devExitLat = +USB_DEFAULT_U1_DEV_EXIT_LAT ; + dcd_config_params.bU2DevExitLat = +cpu_to_le16 (USB_DEFAULT_U2_DEV_EXIT_LAT ); + } + ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat; + ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat; } - ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat; - ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat;/* The SuperSpeedPlus USB Device Capability descriptor */ if (gadget_is_superspeed_plus (cdev->gadget)) {
Signature · 1 line
2.11.0
PATCH 8/9 usb: gadget: Allow a non-SuperSpeed gadget to support LPM
In reply to Sevak ArakelyanFrom: John Youn <[email protected]>
This commit allows a gadget that does not support SuperSpeed to indicate that it supports LPM. It does this by setting the 'lpm_capable' flag in the gadget structure.
If a gadget sets this, the composite gadget framework will set the bcdUSB to 0x0201 to indicate that this supports BOS descriptors, and also return a USB 2.0 Extension descriptor as part of the BOS descriptor set.
See USB 2.0 LPM ECN Section 3.
--- drivers/usb/gadget/composite.c | 8 ++++++-- include/linux/usb/gadget.h | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-)
drivers/usb/gadget/composite.c +6 -2
@@ -1608,7 +1608,10 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) cdev->desc.bcdUSB =cpu_to_le16 (0x0210 ); } }else { - cdev->desc.bcdUSB =cpu_to_le16 (0x0200 ); +if (gadget->lpm_capable) + cdev->desc.bcdUSB =cpu_to_le16 (0x0201 ); +else + cdev->desc.bcdUSB =cpu_to_le16 (0x0200 ); } value =min (w_length, (u16 )sizeof cdev->desc);
@@ -1639,7 +1642,8 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) value =min (w_length, (u16 ) value);break ;case USB_DT_BOS : -if (gadget_is_superspeed (gadget)) { +if (gadget_is_superspeed (gadget) || + gadget->lpm_capable) { value =bos_desc (cdev); value =min (w_length, (u16 ) value); }
include/linux/usb/gadget.h +3 -0
@@ -352,6 +352,8 @@ struct usb_gadget_ops {* @deactivated: True if gadget is deactivated - in deactivated state it cannot * be connected. * @connected: True if gadget is connected. +* @lpm_capable: If the gadget max_speed is FULL or HIGH, this flag +* indicates that it supports LPM as per the LPM ECN & errata. * * Gadgets have a mostly-portable "gadget driver" implementing device * functions, handling all usb configurations and interfaces. Gadget
@@ -404,6 +406,7 @@ struct usb_gadget { unsigned is_selfpowered:1; unsigned deactivated:1; unsigned connected:1; + unsigned lpm_capable:1; };#define work_to_gadget (w) (container_of((w), struct usb_gadget, work))
Signature · 1 line
2.11.0
PATCH 9/9 usb: dwc2: Enable LPM
In reply to Sevak ArakelyanFrom: John Youn <[email protected]>
Set 'lpm_capable' flag in the gadget structure so
indicating that LPM is supported.
--- drivers/usb/dwc2/gadget.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/usb/dwc2/gadget.c +3 -0
@@ -4652,6 +4652,9 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq) hsotg->gadget.ops = &dwc2_hsotg_gadget_ops; hsotg->gadget.name =dev_name (dev); +if (hsotg->params.lpm) + hsotg->gadget.lpm_capable = true; +if (hsotg->dr_mode ==USB_DR_MODE_OTG ) hsotg->gadget.is_otg =1 ;else if (hsotg->dr_mode ==USB_DR_MODE_PERIPHERAL )
Signature · 1 line
2.11.0
Greg Kroah-Hartman
maintainerRe: [PATCH 9/9] [HSLPM] usb: dwc2: Enable LPM
Quoted 6 lines · Sevak Arakelyan
From: John Youn <[email protected]>
Set '
lpm_capable' flag in the gadget structure so
indicating that LPM is supported.Signed-off-by Sevak Arakelyan <[email protected]>
No signed-off-by from John?
Re: [PATCH 9/9] [HSLPM] usb: dwc2: Enable LPM
Quoted 9 lines · Greg Kroah-Hartman
Quoted 6 lines · Sevak Arakelyan
From: John Youn <[email protected]>
Set '
lpm_capable' flag in the gadget structure so
indicating that LPM is supported.Signed-off-by Sevak Arakelyan <[email protected]>No signed-off-by from John?
right, I only took two patches from this series. Without John's acked-by, I can't take any dwc2 patches.
Signature · 1 line
balbi