From: Vardan Mikayelyan <mvar...@synopsys.com>

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 <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 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 393a962..61324d9 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to