0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/clk.h>
0011 #include <linux/iopoll.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/usb/role.h>
0014 #include "core.h"
0015
0016 #define dwc2_ovr_gotgctl(gotgctl) \
0017 ((gotgctl) |= GOTGCTL_BVALOEN | GOTGCTL_AVALOEN | GOTGCTL_VBVALOEN | \
0018 GOTGCTL_DBNCE_FLTR_BYPASS)
0019
0020 static void dwc2_ovr_init(struct dwc2_hsotg *hsotg)
0021 {
0022 unsigned long flags;
0023 u32 gotgctl;
0024
0025 spin_lock_irqsave(&hsotg->lock, flags);
0026
0027 gotgctl = dwc2_readl(hsotg, GOTGCTL);
0028 dwc2_ovr_gotgctl(gotgctl);
0029 gotgctl &= ~(GOTGCTL_BVALOVAL | GOTGCTL_AVALOVAL | GOTGCTL_VBVALOVAL);
0030 if (hsotg->role_sw_default_mode == USB_DR_MODE_HOST)
0031 gotgctl |= GOTGCTL_AVALOVAL | GOTGCTL_VBVALOVAL;
0032 else if (hsotg->role_sw_default_mode == USB_DR_MODE_PERIPHERAL)
0033 gotgctl |= GOTGCTL_BVALOVAL | GOTGCTL_VBVALOVAL;
0034 dwc2_writel(hsotg, gotgctl, GOTGCTL);
0035
0036 spin_unlock_irqrestore(&hsotg->lock, flags);
0037
0038 dwc2_force_mode(hsotg, (hsotg->dr_mode == USB_DR_MODE_HOST));
0039 }
0040
0041 static int dwc2_ovr_avalid(struct dwc2_hsotg *hsotg, bool valid)
0042 {
0043 u32 gotgctl = dwc2_readl(hsotg, GOTGCTL);
0044
0045
0046 if ((valid && (gotgctl & GOTGCTL_ASESVLD)) ||
0047 (!valid && !(gotgctl & GOTGCTL_ASESVLD)))
0048 return -EALREADY;
0049
0050
0051 dwc2_ovr_gotgctl(gotgctl);
0052
0053 gotgctl &= ~GOTGCTL_BVALOVAL;
0054 if (valid)
0055 gotgctl |= GOTGCTL_AVALOVAL | GOTGCTL_VBVALOVAL;
0056 else
0057 gotgctl &= ~(GOTGCTL_AVALOVAL | GOTGCTL_VBVALOVAL);
0058 dwc2_writel(hsotg, gotgctl, GOTGCTL);
0059
0060 return 0;
0061 }
0062
0063 static int dwc2_ovr_bvalid(struct dwc2_hsotg *hsotg, bool valid)
0064 {
0065 u32 gotgctl = dwc2_readl(hsotg, GOTGCTL);
0066
0067
0068 if ((valid && (gotgctl & GOTGCTL_BSESVLD)) ||
0069 (!valid && !(gotgctl & GOTGCTL_BSESVLD)))
0070 return -EALREADY;
0071
0072
0073 dwc2_ovr_gotgctl(gotgctl);
0074
0075 gotgctl &= ~GOTGCTL_AVALOVAL;
0076 if (valid)
0077 gotgctl |= GOTGCTL_BVALOVAL | GOTGCTL_VBVALOVAL;
0078 else
0079 gotgctl &= ~(GOTGCTL_BVALOVAL | GOTGCTL_VBVALOVAL);
0080 dwc2_writel(hsotg, gotgctl, GOTGCTL);
0081
0082 return 0;
0083 }
0084
0085 static int dwc2_drd_role_sw_set(struct usb_role_switch *sw, enum usb_role role)
0086 {
0087 struct dwc2_hsotg *hsotg = usb_role_switch_get_drvdata(sw);
0088 unsigned long flags;
0089 int already = 0;
0090
0091
0092 if ((role == USB_ROLE_DEVICE && hsotg->dr_mode == USB_DR_MODE_HOST) ||
0093 (role == USB_ROLE_HOST && hsotg->dr_mode == USB_DR_MODE_PERIPHERAL))
0094 return -EINVAL;
0095
0096 #if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \
0097 IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
0098
0099 if (role == USB_ROLE_NONE && hsotg->test_mode) {
0100 dev_dbg(hsotg->dev, "Core is in test mode\n");
0101 return -EBUSY;
0102 }
0103 #endif
0104
0105
0106
0107
0108
0109
0110
0111
0112 if (!hsotg->ll_hw_enabled && hsotg->clk) {
0113 int ret = clk_prepare_enable(hsotg->clk);
0114
0115 if (ret)
0116 return ret;
0117 }
0118
0119 spin_lock_irqsave(&hsotg->lock, flags);
0120
0121 if (role == USB_ROLE_NONE) {
0122
0123 if (hsotg->role_sw_default_mode == USB_DR_MODE_HOST)
0124 role = USB_ROLE_HOST;
0125 else if (hsotg->role_sw_default_mode == USB_DR_MODE_PERIPHERAL)
0126 role = USB_ROLE_DEVICE;
0127 }
0128
0129 if (role == USB_ROLE_HOST) {
0130 already = dwc2_ovr_avalid(hsotg, true);
0131 } else if (role == USB_ROLE_DEVICE) {
0132 already = dwc2_ovr_bvalid(hsotg, true);
0133 if (dwc2_is_device_enabled(hsotg)) {
0134
0135 dwc2_hsotg_core_connect(hsotg);
0136 }
0137 } else {
0138 if (dwc2_is_device_mode(hsotg)) {
0139 if (!dwc2_ovr_bvalid(hsotg, false))
0140
0141 dwc2_hsotg_core_disconnect(hsotg);
0142 } else {
0143 dwc2_ovr_avalid(hsotg, false);
0144 }
0145 }
0146
0147 spin_unlock_irqrestore(&hsotg->lock, flags);
0148
0149 if (!already && hsotg->dr_mode == USB_DR_MODE_OTG)
0150
0151 dwc2_force_mode(hsotg, role == USB_ROLE_HOST);
0152
0153 if (!hsotg->ll_hw_enabled && hsotg->clk)
0154 clk_disable_unprepare(hsotg->clk);
0155
0156 dev_dbg(hsotg->dev, "%s-session valid\n",
0157 role == USB_ROLE_NONE ? "No" :
0158 role == USB_ROLE_HOST ? "A" : "B");
0159
0160 return 0;
0161 }
0162
0163 int dwc2_drd_init(struct dwc2_hsotg *hsotg)
0164 {
0165 struct usb_role_switch_desc role_sw_desc = {0};
0166 struct usb_role_switch *role_sw;
0167 int ret;
0168
0169 if (!device_property_read_bool(hsotg->dev, "usb-role-switch"))
0170 return 0;
0171
0172 hsotg->role_sw_default_mode = usb_get_role_switch_default_mode(hsotg->dev);
0173 role_sw_desc.driver_data = hsotg;
0174 role_sw_desc.fwnode = dev_fwnode(hsotg->dev);
0175 role_sw_desc.set = dwc2_drd_role_sw_set;
0176 role_sw_desc.allow_userspace_control = true;
0177
0178 role_sw = usb_role_switch_register(hsotg->dev, &role_sw_desc);
0179 if (IS_ERR(role_sw)) {
0180 ret = PTR_ERR(role_sw);
0181 dev_err(hsotg->dev,
0182 "failed to register role switch: %d\n", ret);
0183 return ret;
0184 }
0185
0186 hsotg->role_sw = role_sw;
0187
0188
0189 dwc2_ovr_init(hsotg);
0190
0191 return 0;
0192 }
0193
0194 void dwc2_drd_suspend(struct dwc2_hsotg *hsotg)
0195 {
0196 u32 gintsts, gintmsk;
0197
0198 if (hsotg->role_sw && !hsotg->params.external_id_pin_ctl) {
0199 gintmsk = dwc2_readl(hsotg, GINTMSK);
0200 gintmsk &= ~GINTSTS_CONIDSTSCHNG;
0201 dwc2_writel(hsotg, gintmsk, GINTMSK);
0202 gintsts = dwc2_readl(hsotg, GINTSTS);
0203 dwc2_writel(hsotg, gintsts | GINTSTS_CONIDSTSCHNG, GINTSTS);
0204 }
0205 }
0206
0207 void dwc2_drd_resume(struct dwc2_hsotg *hsotg)
0208 {
0209 u32 gintsts, gintmsk;
0210 enum usb_role role;
0211
0212 if (hsotg->role_sw) {
0213
0214 role = usb_role_switch_get_role(hsotg->role_sw);
0215
0216 if (role == USB_ROLE_NONE) {
0217 if (hsotg->role_sw_default_mode == USB_DR_MODE_HOST)
0218 role = USB_ROLE_HOST;
0219 else if (hsotg->role_sw_default_mode == USB_DR_MODE_PERIPHERAL)
0220 role = USB_ROLE_DEVICE;
0221 }
0222
0223
0224 if (role == USB_ROLE_HOST)
0225 dwc2_ovr_avalid(hsotg, true);
0226 else if (role == USB_ROLE_DEVICE)
0227 dwc2_ovr_bvalid(hsotg, true);
0228
0229 dwc2_force_mode(hsotg, role == USB_ROLE_HOST);
0230
0231 dev_dbg(hsotg->dev, "resuming %s-session valid\n",
0232 role == USB_ROLE_NONE ? "No" :
0233 role == USB_ROLE_HOST ? "A" : "B");
0234 }
0235
0236 if (hsotg->role_sw && !hsotg->params.external_id_pin_ctl) {
0237 gintsts = dwc2_readl(hsotg, GINTSTS);
0238 dwc2_writel(hsotg, gintsts | GINTSTS_CONIDSTSCHNG, GINTSTS);
0239 gintmsk = dwc2_readl(hsotg, GINTMSK);
0240 gintmsk |= GINTSTS_CONIDSTSCHNG;
0241 dwc2_writel(hsotg, gintmsk, GINTMSK);
0242 }
0243 }
0244
0245 void dwc2_drd_exit(struct dwc2_hsotg *hsotg)
0246 {
0247 if (hsotg->role_sw)
0248 usb_role_switch_unregister(hsotg->role_sw);
0249 }