From: Vardan Mikayelyan <mvardan@xxxxxxxxxxxx> Added new core param for low speed, which can be used only when SNPSID is equal to DWC2_CORE_FS_IOT. When LS mode is enabled, we are restricting ep types and providing to upper layer only INTR and CTRL endpoints. Signed-off-by: Vardan Mikayelyan <mvardan@xxxxxxxxxxxx> Signed-off-by: John Youn <johnyoun@xxxxxxxxxxxx> --- drivers/usb/dwc2/core.h | 1 + drivers/usb/dwc2/gadget.c | 27 +++++++++++++++++++++------ drivers/usb/dwc2/hcd.c | 8 +++++--- drivers/usb/dwc2/params.c | 8 ++++++-- 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 067e24b..9548d3e 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -467,6 +467,7 @@ struct dwc2_core_params { int speed; #define DWC2_SPEED_PARAM_HIGH 0 #define DWC2_SPEED_PARAM_FULL 1 +#define DWC2_SPEED_PARAM_LOW 2 int enable_dynamic_fifo; int en_multiple_tx_fifo; diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index e672832..ad0cd0e 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -3175,7 +3175,8 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, GUSBCFG_HNPCAP); if (hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS && - hsotg->params.speed == DWC2_SPEED_PARAM_FULL) { + (hsotg->params.speed == DWC2_SPEED_PARAM_FULL || + hsotg->params.speed == DWC2_SPEED_PARAM_LOW)) { /* FS/LS Dedicated Transceiver Interface */ usbcfg |= GUSBCFG_PHYSEL; } else { @@ -3192,14 +3193,21 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, __orr32(hsotg->regs + DCTL, DCTL_SFTDISCON); dcfg |= DCFG_EPMISCNT(1); - if (hsotg->params.speed == DWC2_SPEED_PARAM_FULL) { + + switch (hsotg->params.speed) { + case DWC2_SPEED_PARAM_LOW: + dcfg |= DCFG_DEVSPD_LS; + break; + case DWC2_SPEED_PARAM_FULL: if (hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS) dcfg |= DCFG_DEVSPD_FS48; else dcfg |= DCFG_DEVSPD_FS; - } else { + break; + default: dcfg |= DCFG_DEVSPD_HS; } + dwc2_writel(dcfg, hsotg->regs + DCFG); /* Clear any pending OTG interrupts */ @@ -4388,14 +4396,21 @@ static void dwc2_hsotg_initep(struct dwc2_hsotg *hsotg, hs_ep->parent = hsotg; hs_ep->ep.name = hs_ep->name; - usb_ep_set_maxpacket_limit(&hs_ep->ep, epnum ? 1024 : EP0_MPS_LIMIT); + + if (hsotg->params.speed == DWC2_SPEED_PARAM_LOW) + usb_ep_set_maxpacket_limit(&hs_ep->ep, 8); + else + usb_ep_set_maxpacket_limit(&hs_ep->ep, + epnum ? 1024 : EP0_MPS_LIMIT); hs_ep->ep.ops = &dwc2_hsotg_ep_ops; if (epnum == 0) { hs_ep->ep.caps.type_control = true; } else { - hs_ep->ep.caps.type_iso = true; - hs_ep->ep.caps.type_bulk = true; + if (hsotg->params.speed != DWC2_SPEED_PARAM_LOW) { + hs_ep->ep.caps.type_iso = true; + hs_ep->ep.caps.type_bulk = true; + } hs_ep->ep.caps.type_int = true; } diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 2f807cf..fb7f8e9 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -230,9 +230,10 @@ static int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) u32 usbcfg; int retval = 0; - if (hsotg->params.speed == DWC2_SPEED_PARAM_FULL && + if ((hsotg->params.speed == DWC2_SPEED_PARAM_FULL || + hsotg->params.speed == DWC2_SPEED_PARAM_LOW) && hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS) { - /* If FS mode with FS PHY */ + /* If FS/LS mode with FS/LS PHY */ retval = dwc2_fs_phy_init(hsotg, select_phy); if (retval) return retval; @@ -2277,7 +2278,8 @@ static void dwc2_core_host_init(struct dwc2_hsotg *hsotg) /* Initialize Host Configuration Register */ dwc2_init_fs_ls_pclk_sel(hsotg); - if (hsotg->params.speed == DWC2_SPEED_PARAM_FULL) { + if (hsotg->params.speed == DWC2_SPEED_PARAM_FULL || + hsotg->params.speed == DWC2_SPEED_PARAM_LOW) { hcfg = dwc2_readl(hsotg->regs + HCFG); hcfg |= HCFG_FSLSSUPP; dwc2_writel(hcfg, hsotg->regs + HCFG); diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index c294344..7b84c1e 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c @@ -742,14 +742,18 @@ static void dwc2_set_param_speed(struct dwc2_hsotg *hsotg, int val) { int valid = 1; - if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) { + if (DWC2_OUT_OF_BOUNDS(val, 0, 2)) { if (val >= 0) { dev_err(hsotg->dev, "Wrong value for speed parameter\n"); - dev_err(hsotg->dev, "max_speed parameter must be 0 or 1\n"); + dev_err(hsotg->dev, "max_speed parameter must be 0, 1, or 2\n"); } valid = 0; } + if (dwc2_is_hs_iot(hsotg) && + val == DWC2_SPEED_PARAM_LOW) + valid = 0; + if (val == DWC2_SPEED_PARAM_HIGH && dwc2_get_param_phy_type(hsotg) == DWC2_PHY_TYPE_PARAM_FS) valid = 0; -- 2.10.0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html