usb: dwc2: gadget: Add new core parameter for low speed
authorVardan Mikayelyan <mvardan@synopsys.com>
Tue, 15 Nov 2016 03:17:03 +0000 (19:17 -0800)
committerFelipe Balbi <felipe.balbi@linux.intel.com>
Fri, 18 Nov 2016 11:54:50 +0000 (13:54 +0200)
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@synopsys.com>
Signed-off-by: John Youn <johnyoun@synopsys.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
drivers/usb/dwc2/core.h
drivers/usb/dwc2/gadget.c
drivers/usb/dwc2/hcd.c
drivers/usb/dwc2/params.c

index 067e24b7b4d643b2b5294f0f2cd6e033f1b5a265..9548d3e03453db062042600668840d5b4676e649 100644 (file)
@@ -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;
index e67283237fd44030a2337f278dc018bad2b0164e..ad0cd0e38f061d8674f2b457ebc6b8fa60d453cd 100644 (file)
@@ -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;
        }
 
index 2f807cff27e21dd4bd58263c3bdb7b890bf9b6ac..fb7f8e9784eea0d58229a53c909a10b572e921a9 100644 (file)
@@ -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);
index 2fd461de63a835b82799101b3a9283e914d9d14a..1bf3b0936d872675e63c6b7ee70b7a4f8a5cbbdf 100644 (file)
@@ -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;