/* u2-port0 should be powered on and enabled; */ int ssusb_check_clocks(struct ssusb_mtk *ssusb, u32 ex_clks)
{ void __iomem *ibase = ssusb->ippc_base;
u32 value, check_val; int ret;
/* * device ip may be powered on in firmware/BROM stage before entering * kernel stage; * power down device ip, otherwise ip-sleep will fail when working as * host only mode
*/
mtu3_setbits(ssusb->ippc_base, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN);
}
ssusb->vusb33 = devm_regulator_get(dev, "vusb33"); if (IS_ERR(ssusb->vusb33)) {
dev_err(dev, "failed to get vusb33\n"); return PTR_ERR(ssusb->vusb33);
}
for (i = 0; i < ssusb->num_phys; i++) {
ssusb->phys[i] = devm_of_phy_get_by_index(dev, node, i); if (IS_ERR(ssusb->phys[i])) {
dev_err(dev, "failed to get phy-%d\n", i); return PTR_ERR(ssusb->phys[i]);
}
}
ssusb->ippc_base = devm_platform_ioremap_resource_byname(pdev, "ippc"); if (IS_ERR(ssusb->ippc_base)) return PTR_ERR(ssusb->ippc_base);
ssusb->wakeup_irq = platform_get_irq_byname_optional(pdev, "wakeup"); if (ssusb->wakeup_irq == -EPROBE_DEFER) return ssusb->wakeup_irq;
ssusb->dr_mode = usb_get_dr_mode(dev); if (ssusb->dr_mode == USB_DR_MODE_UNKNOWN)
ssusb->dr_mode = USB_DR_MODE_OTG;
if (ssusb->dr_mode == USB_DR_MODE_PERIPHERAL) goto out;
/* if host role is supported */
ret = ssusb_wakeup_of_property_parse(ssusb, node); if (ret) {
dev_err(dev, "failed to parse uwk property\n"); return ret;
}
/* optional property, ignore the error if it does not exist */
of_property_read_u32(node, "mediatek,u2p-dis-msk",
&ssusb->u2p_dis_msk);
otg_sx->vbus = devm_regulator_get(dev, "vbus"); if (IS_ERR(otg_sx->vbus)) {
dev_err(dev, "failed to get vbus\n"); return PTR_ERR(otg_sx->vbus);
}
if (ssusb->dr_mode == USB_DR_MODE_HOST) goto out;
/* if dual-role mode is supported */
otg_sx->manual_drd_enabled =
of_property_read_bool(node, "enable-manual-drd");
otg_sx->role_sw_used = of_property_read_bool(node, "usb-role-switch");
/* can't disable port0 when use dual-role mode */
ssusb->u2p_dis_msk &= ~0x1;
if (otg_sx->role_sw_used || otg_sx->manual_drd_enabled) goto out;
if (of_property_present(node, "extcon")) {
otg_sx->edev = extcon_get_edev_by_phandle(ssusb->dev, 0); if (IS_ERR(otg_sx->edev)) { return dev_err_probe(dev, PTR_ERR(otg_sx->edev), "couldn't get extcon device\n");
}
}
if (IS_ENABLED(CONFIG_USB_MTU3_HOST))
ssusb->dr_mode = USB_DR_MODE_HOST; elseif (IS_ENABLED(CONFIG_USB_MTU3_GADGET))
ssusb->dr_mode = USB_DR_MODE_PERIPHERAL;
/* default as host */
ssusb->is_host = !(ssusb->dr_mode == USB_DR_MODE_PERIPHERAL);
switch (ssusb->dr_mode) { case USB_DR_MODE_PERIPHERAL:
ret = ssusb_gadget_init(ssusb); if (ret) {
dev_err(dev, "failed to initialize gadget\n"); goto comm_exit;
} break; case USB_DR_MODE_HOST:
ret = ssusb_host_init(ssusb, node); if (ret) {
dev_err(dev, "failed to initialize host\n"); goto comm_exit;
} break; case USB_DR_MODE_OTG:
ret = ssusb_gadget_init(ssusb); if (ret) {
dev_err(dev, "failed to initialize gadget\n"); goto comm_exit;
}
ret = ssusb_host_init(ssusb, node); if (ret) {
dev_err(dev, "failed to initialize host\n"); goto gadget_exit;
}
ret = ssusb_otg_switch_init(ssusb); if (ret) {
dev_err(dev, "failed to initialize switch\n"); goto host_exit;
} break; default:
dev_err(dev, "unsupported mode: %d\n", ssusb->dr_mode);
ret = -EINVAL; goto comm_exit;
}
switch (ssusb->dr_mode) { case USB_DR_MODE_PERIPHERAL:
ssusb_gadget_exit(ssusb); break; case USB_DR_MODE_HOST:
ssusb_host_exit(ssusb); break; case USB_DR_MODE_OTG:
ssusb_otg_switch_exit(ssusb);
ssusb_gadget_exit(ssusb);
ssusb_host_exit(ssusb); break; case USB_DR_MODE_UNKNOWN: /* * This cannot happen because with dr_mode == * USB_DR_MODE_UNKNOWN, .probe() doesn't succeed and so * .remove() wouldn't be called at all. However (little * surprising) the compiler isn't smart enough to see that, so * we explicitly have this case item to not make the compiler * wail about an unhandled enumeration value.
*/ break;
}
staticint resume_ip_and_ports(struct ssusb_mtk *ssusb, pm_message_t msg)
{ switch (ssusb->dr_mode) { case USB_DR_MODE_PERIPHERAL:
ssusb_gadget_resume(ssusb, msg); break; case USB_DR_MODE_HOST:
ssusb_host_resume(ssusb, false); break; case USB_DR_MODE_OTG:
ssusb_host_resume(ssusb, !ssusb->is_host); if (!ssusb->is_host)
ssusb_gadget_resume(ssusb, msg);
break; default: return -EINVAL;
}
return 0;
}
staticint mtu3_suspend_common(struct device *dev, pm_message_t msg)
{ struct ssusb_mtk *ssusb = dev_get_drvdata(dev); int ret = 0;
dev_dbg(dev, "%s\n", __func__);
switch (ssusb->dr_mode) { case USB_DR_MODE_PERIPHERAL:
ret = ssusb_gadget_suspend(ssusb, msg); if (ret) goto err;
break; case USB_DR_MODE_HOST:
ssusb_host_suspend(ssusb); break; case USB_DR_MODE_OTG: if (!ssusb->is_host) {
ret = ssusb_gadget_suspend(ssusb, msg); if (ret) goto err;
}
ssusb_host_suspend(ssusb); break; default: return -EINVAL;
}
ret = wait_for_ip_sleep(ssusb); if (ret) goto sleep_err;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.