if (version == USB2_PORT) { /* 1. power off and disable u2 port0 */
value = mtu3_readl(ibase, SSUSB_U2_CTRL(0));
value |= SSUSB_U2_PORT_PDN | SSUSB_U2_PORT_DIS;
mtu3_writel(ibase, SSUSB_U2_CTRL(0), value);
/* 2. power on, enable u2 port0 and select its mode */
value = mtu3_readl(ibase, SSUSB_U2_CTRL(0));
value &= ~(SSUSB_U2_PORT_PDN | SSUSB_U2_PORT_DIS);
value = tohost ? (value | SSUSB_U2_PORT_HOST_SEL) :
(value & (~SSUSB_U2_PORT_HOST_SEL));
mtu3_writel(ibase, SSUSB_U2_CTRL(0), value);
} else { /* 1. power off and disable u3 port0 */
value = mtu3_readl(ibase, SSUSB_U3_CTRL(0));
value |= SSUSB_U3_PORT_PDN | SSUSB_U3_PORT_DIS;
mtu3_writel(ibase, SSUSB_U3_CTRL(0), value);
/* 2. power on, enable u3 port0 and select its mode */
value = mtu3_readl(ibase, SSUSB_U3_CTRL(0));
value &= ~(SSUSB_U3_PORT_PDN | SSUSB_U3_PORT_DIS);
value = tohost ? (value | SSUSB_U3_PORT_HOST_SEL) :
(value & (~SSUSB_U3_PORT_HOST_SEL));
mtu3_writel(ibase, SSUSB_U3_CTRL(0), value);
}
if (desired_role == USB_ROLE_NONE) { /* the default mode is host as probe does */
desired_role = USB_ROLE_HOST; if (otg_sx->default_role == USB_ROLE_DEVICE)
desired_role = USB_ROLE_DEVICE;
}
if (current_role == desired_role) return;
dev_dbg(ssusb->dev, "set role : %s\n", usb_role_string(desired_role));
mtu3_dbg_trace(ssusb->dev, "set role : %s", usb_role_string(desired_role));
pm_runtime_get_sync(ssusb->dev);
otg_sx->id_nb.notifier_call = ssusb_id_notifier;
ret = devm_extcon_register_notifier(ssusb->dev, edev, EXTCON_USB_HOST,
&otg_sx->id_nb); if (ret < 0) {
dev_err(ssusb->dev, "failed to register notifier for USB-HOST\n"); return ret;
}
ret = extcon_get_state(edev, EXTCON_USB_HOST);
dev_dbg(ssusb->dev, "EXTCON_USB_HOST: %d\n", ret);
/* default as host, switch to device mode if needed */ if (!ret)
ssusb_set_mode(otg_sx, USB_ROLE_DEVICE);
return 0;
}
/* * We provide an interface via debugfs to switch between host and device modes * depending on user input. * This is useful in special cases, such as uses TYPE-A receptacle but also * wants to support dual-role mode.
*/ void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host)
{ struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
value = mtu3_readl(ssusb->ippc_base, SSUSB_U2_CTRL(0)); switch (mode) { case MTU3_DR_FORCE_DEVICE:
value |= SSUSB_U2_PORT_FORCE_IDDIG | SSUSB_U2_PORT_RG_IDDIG; break; case MTU3_DR_FORCE_HOST:
value |= SSUSB_U2_PORT_FORCE_IDDIG;
value &= ~SSUSB_U2_PORT_RG_IDDIG; break; case MTU3_DR_FORCE_NONE:
value &= ~(SSUSB_U2_PORT_FORCE_IDDIG | SSUSB_U2_PORT_RG_IDDIG); break; default: return;
}
mtu3_writel(ssusb->ippc_base, SSUSB_U2_CTRL(0), value);
}
int ssusb_otg_switch_init(struct ssusb_mtk *ssusb)
{ struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; int ret = 0;
INIT_WORK(&otg_sx->dr_work, ssusb_mode_sw_work);
if (otg_sx->manual_drd_enabled)
ssusb_dr_debugfs_init(ssusb); elseif (otg_sx->role_sw_used)
ret = ssusb_role_sw_register(otg_sx); else
ret = ssusb_extcon_register(otg_sx);
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.