mirror of https://gitee.com/openkylin/linux.git
usb: dwc3: gadget: Implement setting of SSP rate
Implement gadget ops udc_set_ssp_rate(). This allows the gadget/core driver to select SSP signaling rate and number of lanes to for DWC_usb32 controller. Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Link: https://lore.kernel.org/r/8998b65fddfa02cab57bfc6aa35e9f101b252068.1611106162.git.Thinh.Nguyen@synopsys.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
678481467d
commit
072cab8a0f
|
@ -386,6 +386,8 @@
|
|||
#define DWC3_GUCTL3_SPLITDISABLE BIT(14)
|
||||
|
||||
/* Device Configuration Register */
|
||||
#define DWC3_DCFG_NUMLANES(n) (((n) & 0x3) << 30) /* DWC_usb32 only */
|
||||
|
||||
#define DWC3_DCFG_DEVADDR(addr) ((addr) << 3)
|
||||
#define DWC3_DCFG_DEVADDR_MASK DWC3_DCFG_DEVADDR(0x7f)
|
||||
|
||||
|
@ -966,6 +968,8 @@ struct dwc3_scratchpad_array {
|
|||
* @maximum_speed: maximum speed requested (mainly for testing purposes)
|
||||
* @max_ssp_rate: SuperSpeed Plus maximum signaling rate and lane count
|
||||
* @gadget_max_speed: maximum gadget speed requested
|
||||
* @gadget_ssp_rate: Gadget driver's maximum supported SuperSpeed Plus signaling
|
||||
* rate and lane count.
|
||||
* @ip: controller's ID
|
||||
* @revision: controller's version of an IP
|
||||
* @version_type: VERSIONTYPE register contents, a sub release of a revision
|
||||
|
@ -1130,6 +1134,7 @@ struct dwc3 {
|
|||
u32 maximum_speed;
|
||||
u32 gadget_max_speed;
|
||||
enum usb_ssp_rate max_ssp_rate;
|
||||
enum usb_ssp_rate gadget_ssp_rate;
|
||||
|
||||
u32 ip;
|
||||
|
||||
|
|
|
@ -2038,10 +2038,40 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc)
|
|||
}
|
||||
}
|
||||
|
||||
static void __dwc3_gadget_set_ssp_rate(struct dwc3 *dwc)
|
||||
{
|
||||
enum usb_ssp_rate ssp_rate = dwc->gadget_ssp_rate;
|
||||
u32 reg;
|
||||
|
||||
if (ssp_rate == USB_SSP_GEN_UNKNOWN)
|
||||
ssp_rate = dwc->max_ssp_rate;
|
||||
|
||||
reg = dwc3_readl(dwc->regs, DWC3_DCFG);
|
||||
reg &= ~DWC3_DCFG_SPEED_MASK;
|
||||
reg &= ~DWC3_DCFG_NUMLANES(~0);
|
||||
|
||||
if (ssp_rate == USB_SSP_GEN_1x2)
|
||||
reg |= DWC3_DCFG_SUPERSPEED;
|
||||
else if (dwc->max_ssp_rate != USB_SSP_GEN_1x2)
|
||||
reg |= DWC3_DCFG_SUPERSPEED_PLUS;
|
||||
|
||||
if (ssp_rate != USB_SSP_GEN_2x1 &&
|
||||
dwc->max_ssp_rate != USB_SSP_GEN_2x1)
|
||||
reg |= DWC3_DCFG_NUMLANES(1);
|
||||
|
||||
dwc3_writel(dwc->regs, DWC3_DCFG, reg);
|
||||
}
|
||||
|
||||
static void __dwc3_gadget_set_speed(struct dwc3 *dwc)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
if (dwc->gadget_max_speed == USB_SPEED_SUPER_PLUS &&
|
||||
DWC3_IP_IS(DWC32)) {
|
||||
__dwc3_gadget_set_ssp_rate(dwc);
|
||||
return;
|
||||
}
|
||||
|
||||
reg = dwc3_readl(dwc->regs, DWC3_DCFG);
|
||||
reg &= ~(DWC3_DCFG_SPEED_MASK);
|
||||
|
||||
|
@ -2475,6 +2505,17 @@ static void dwc3_gadget_set_speed(struct usb_gadget *g,
|
|||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
}
|
||||
|
||||
static void dwc3_gadget_set_ssp_rate(struct usb_gadget *g,
|
||||
enum usb_ssp_rate rate)
|
||||
{
|
||||
struct dwc3 *dwc = gadget_to_dwc(g);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
dwc->gadget_ssp_rate = rate;
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
}
|
||||
|
||||
static int dwc3_gadget_vbus_draw(struct usb_gadget *g, unsigned int mA)
|
||||
{
|
||||
struct dwc3 *dwc = gadget_to_dwc(g);
|
||||
|
@ -2493,6 +2534,7 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {
|
|||
.udc_start = dwc3_gadget_start,
|
||||
.udc_stop = dwc3_gadget_stop,
|
||||
.udc_set_speed = dwc3_gadget_set_speed,
|
||||
.udc_set_ssp_rate = dwc3_gadget_set_ssp_rate,
|
||||
.get_config_params = dwc3_gadget_config_params,
|
||||
.vbus_draw = dwc3_gadget_vbus_draw,
|
||||
};
|
||||
|
@ -3905,7 +3947,10 @@ int dwc3_gadget_init(struct dwc3 *dwc)
|
|||
goto err5;
|
||||
}
|
||||
|
||||
dwc3_gadget_set_speed(dwc->gadget, dwc->maximum_speed);
|
||||
if (DWC3_IP_IS(DWC32) && dwc->maximum_speed == USB_SPEED_SUPER_PLUS)
|
||||
dwc3_gadget_set_ssp_rate(dwc->gadget, dwc->max_ssp_rate);
|
||||
else
|
||||
dwc3_gadget_set_speed(dwc->gadget, dwc->maximum_speed);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
Loading…
Reference in New Issue