1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * drd.c - DesignWare USB2 DRD Controller Dual-role support 4 * 5 * Copyright (C) 2020 STMicroelectronics 6 * 7 * Author(s): Amelie Delaunay <amelie.delaunay@st.com> 8 */ 9 10 #include <linux/clk.h> 11 #include <linux/iopoll.h> 12 #include <linux/platform_device.h> 13 #include <linux/usb/role.h> 14 #include "core.h" 15 16 #define dwc2_ovr_gotgctl(gotgctl) \ 17 ((gotgctl) |= GOTGCTL_BVALOEN | GOTGCTL_AVALOEN | GOTGCTL_VBVALOEN | \ 18 GOTGCTL_DBNCE_FLTR_BYPASS) 19 20 static void dwc2_ovr_init(struct dwc2_hsotg *hsotg) 21 { 22 unsigned long flags; 23 u32 gotgctl; 24 25 spin_lock_irqsave(&hsotg->lock, flags); 26 27 gotgctl = dwc2_readl(hsotg, GOTGCTL); 28 dwc2_ovr_gotgctl(gotgctl); 29 gotgctl &= ~(GOTGCTL_BVALOVAL | GOTGCTL_AVALOVAL | GOTGCTL_VBVALOVAL); 30 if (hsotg->role_sw_default_mode == USB_DR_MODE_HOST) 31 gotgctl |= GOTGCTL_AVALOVAL | GOTGCTL_VBVALOVAL; 32 else if (hsotg->role_sw_default_mode == USB_DR_MODE_PERIPHERAL) 33 gotgctl |= GOTGCTL_BVALOVAL | GOTGCTL_VBVALOVAL; 34 dwc2_writel(hsotg, gotgctl, GOTGCTL); 35 36 spin_unlock_irqrestore(&hsotg->lock, flags); 37 38 dwc2_force_mode(hsotg, (hsotg->dr_mode == USB_DR_MODE_HOST) || 39 (hsotg->role_sw_default_mode == USB_DR_MODE_HOST)); 40 } 41 42 static int dwc2_ovr_avalid(struct dwc2_hsotg *hsotg, bool valid) 43 { 44 u32 gotgctl = dwc2_readl(hsotg, GOTGCTL); 45 46 /* Check if A-Session is already in the right state */ 47 if ((valid && (gotgctl & GOTGCTL_ASESVLD)) || 48 (!valid && !(gotgctl & GOTGCTL_ASESVLD))) 49 return -EALREADY; 50 51 /* Always enable overrides to handle the resume case */ 52 dwc2_ovr_gotgctl(gotgctl); 53 54 gotgctl &= ~GOTGCTL_BVALOVAL; 55 if (valid) 56 gotgctl |= GOTGCTL_AVALOVAL | GOTGCTL_VBVALOVAL; 57 else 58 gotgctl &= ~(GOTGCTL_AVALOVAL | GOTGCTL_VBVALOVAL); 59 dwc2_writel(hsotg, gotgctl, GOTGCTL); 60 61 return 0; 62 } 63 64 static int dwc2_ovr_bvalid(struct dwc2_hsotg *hsotg, bool valid) 65 { 66 u32 gotgctl = dwc2_readl(hsotg, GOTGCTL); 67 68 /* Check if B-Session is already in the right state */ 69 if ((valid && (gotgctl & GOTGCTL_BSESVLD)) || 70 (!valid && !(gotgctl & GOTGCTL_BSESVLD))) 71 return -EALREADY; 72 73 /* Always enable overrides to handle the resume case */ 74 dwc2_ovr_gotgctl(gotgctl); 75 76 gotgctl &= ~GOTGCTL_AVALOVAL; 77 if (valid) 78 gotgctl |= GOTGCTL_BVALOVAL | GOTGCTL_VBVALOVAL; 79 else 80 gotgctl &= ~(GOTGCTL_BVALOVAL | GOTGCTL_VBVALOVAL); 81 dwc2_writel(hsotg, gotgctl, GOTGCTL); 82 83 return 0; 84 } 85 86 static int dwc2_drd_role_sw_set(struct usb_role_switch *sw, enum usb_role role) 87 { 88 struct dwc2_hsotg *hsotg = usb_role_switch_get_drvdata(sw); 89 unsigned long flags; 90 int already = 0; 91 92 /* Skip session not in line with dr_mode */ 93 if ((role == USB_ROLE_DEVICE && hsotg->dr_mode == USB_DR_MODE_HOST) || 94 (role == USB_ROLE_HOST && hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)) 95 return -EINVAL; 96 97 #if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \ 98 IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) 99 /* Skip session if core is in test mode */ 100 if (role == USB_ROLE_NONE && hsotg->test_mode) { 101 dev_dbg(hsotg->dev, "Core is in test mode\n"); 102 return -EBUSY; 103 } 104 #endif 105 106 /* 107 * In case of USB_DR_MODE_PERIPHERAL, clock is disabled at the end of 108 * the probe and enabled on udc_start. 109 * If role-switch set is called before the udc_start, we need to enable 110 * the clock to read/write GOTGCTL and GUSBCFG registers to override 111 * mode and sessions. It is the case if cable is plugged at boot. 112 */ 113 if (!hsotg->ll_hw_enabled && hsotg->clk) { 114 int ret = clk_prepare_enable(hsotg->clk); 115 116 if (ret) 117 return ret; 118 } 119 120 spin_lock_irqsave(&hsotg->lock, flags); 121 122 if (role == USB_ROLE_NONE) { 123 /* default operation mode when usb role is USB_ROLE_NONE */ 124 if (hsotg->role_sw_default_mode == USB_DR_MODE_HOST) 125 role = USB_ROLE_HOST; 126 else if (hsotg->role_sw_default_mode == USB_DR_MODE_PERIPHERAL) 127 role = USB_ROLE_DEVICE; 128 } 129 130 if ((IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || 131 IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)) && 132 dwc2_is_device_mode(hsotg) && 133 hsotg->lx_state == DWC2_L2 && 134 hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE && 135 hsotg->bus_suspended && 136 !hsotg->params.no_clock_gating) 137 dwc2_gadget_exit_clock_gating(hsotg, 0); 138 139 if (role == USB_ROLE_HOST) { 140 already = dwc2_ovr_avalid(hsotg, true); 141 } else if (role == USB_ROLE_DEVICE) { 142 already = dwc2_ovr_bvalid(hsotg, true); 143 if (dwc2_is_device_enabled(hsotg)) { 144 /* This clear DCTL.SFTDISCON bit */ 145 dwc2_hsotg_core_connect(hsotg); 146 } 147 } else { 148 if (dwc2_is_device_mode(hsotg)) { 149 if (!dwc2_ovr_bvalid(hsotg, false)) 150 /* This set DCTL.SFTDISCON bit */ 151 dwc2_hsotg_core_disconnect(hsotg); 152 } else { 153 dwc2_ovr_avalid(hsotg, false); 154 } 155 } 156 157 spin_unlock_irqrestore(&hsotg->lock, flags); 158 159 if (!already && hsotg->dr_mode == USB_DR_MODE_OTG) 160 /* This will raise a Connector ID Status Change Interrupt */ 161 dwc2_force_mode(hsotg, role == USB_ROLE_HOST); 162 163 if (!hsotg->ll_hw_enabled && hsotg->clk) 164 clk_disable_unprepare(hsotg->clk); 165 166 dev_dbg(hsotg->dev, "%s-session valid\n", 167 role == USB_ROLE_NONE ? "No" : 168 role == USB_ROLE_HOST ? "A" : "B"); 169 170 return 0; 171 } 172 173 int dwc2_drd_init(struct dwc2_hsotg *hsotg) 174 { 175 struct usb_role_switch_desc role_sw_desc = {0}; 176 struct usb_role_switch *role_sw; 177 int ret; 178 179 if (!device_property_read_bool(hsotg->dev, "usb-role-switch")) 180 return 0; 181 182 hsotg->role_sw_default_mode = usb_get_role_switch_default_mode(hsotg->dev); 183 role_sw_desc.driver_data = hsotg; 184 role_sw_desc.fwnode = dev_fwnode(hsotg->dev); 185 role_sw_desc.set = dwc2_drd_role_sw_set; 186 role_sw_desc.allow_userspace_control = true; 187 188 role_sw = usb_role_switch_register(hsotg->dev, &role_sw_desc); 189 if (IS_ERR(role_sw)) { 190 ret = PTR_ERR(role_sw); 191 dev_err(hsotg->dev, 192 "failed to register role switch: %d\n", ret); 193 return ret; 194 } 195 196 hsotg->role_sw = role_sw; 197 198 /* Enable override and initialize values */ 199 dwc2_ovr_init(hsotg); 200 201 return 0; 202 } 203 204 void dwc2_drd_suspend(struct dwc2_hsotg *hsotg) 205 { 206 u32 gintsts, gintmsk; 207 208 if (hsotg->role_sw && !hsotg->params.external_id_pin_ctl) { 209 gintmsk = dwc2_readl(hsotg, GINTMSK); 210 gintmsk &= ~GINTSTS_CONIDSTSCHNG; 211 dwc2_writel(hsotg, gintmsk, GINTMSK); 212 gintsts = dwc2_readl(hsotg, GINTSTS); 213 dwc2_writel(hsotg, gintsts | GINTSTS_CONIDSTSCHNG, GINTSTS); 214 } 215 } 216 217 void dwc2_drd_resume(struct dwc2_hsotg *hsotg) 218 { 219 u32 gintsts, gintmsk; 220 enum usb_role role; 221 222 if (hsotg->role_sw) { 223 /* get last known role (as the get ops isn't implemented by this driver) */ 224 role = usb_role_switch_get_role(hsotg->role_sw); 225 226 if (role == USB_ROLE_NONE) { 227 if (hsotg->role_sw_default_mode == USB_DR_MODE_HOST) 228 role = USB_ROLE_HOST; 229 else if (hsotg->role_sw_default_mode == USB_DR_MODE_PERIPHERAL) 230 role = USB_ROLE_DEVICE; 231 } 232 233 /* restore last role that may have been lost */ 234 if (role == USB_ROLE_HOST) 235 dwc2_ovr_avalid(hsotg, true); 236 else if (role == USB_ROLE_DEVICE) 237 dwc2_ovr_bvalid(hsotg, true); 238 239 dwc2_force_mode(hsotg, role == USB_ROLE_HOST); 240 241 dev_dbg(hsotg->dev, "resuming %s-session valid\n", 242 role == USB_ROLE_NONE ? "No" : 243 role == USB_ROLE_HOST ? "A" : "B"); 244 } 245 246 if (hsotg->role_sw && !hsotg->params.external_id_pin_ctl) { 247 gintsts = dwc2_readl(hsotg, GINTSTS); 248 dwc2_writel(hsotg, gintsts | GINTSTS_CONIDSTSCHNG, GINTSTS); 249 gintmsk = dwc2_readl(hsotg, GINTMSK); 250 gintmsk |= GINTSTS_CONIDSTSCHNG; 251 dwc2_writel(hsotg, gintmsk, GINTMSK); 252 } 253 } 254 255 void dwc2_drd_exit(struct dwc2_hsotg *hsotg) 256 { 257 if (hsotg->role_sw) 258 usb_role_switch_unregister(hsotg->role_sw); 259 } 260