/* *OnmanyCHTdevicesACPIevent(_AEI)handlersread/modify/ *writethecfg0register,justlikewedo.TaketheACPIlock *toavoidusracingwiththeAMLcode.
*/
status = acpi_acquire_global_lock(ACPI_WAIT_FOREVER, &glk); if (ACPI_FAILURE(status) && status != AE_NOT_CONFIGURED) {
dev_err(data->dev, "Error could not acquire lock\n"); return -EIO;
}
pm_runtime_get_sync(data->dev);
/* *Setidpinvalueasrequested. *SincesomedevicesrelyonfirmwaresettingDRD_CONFIGand *SW_SWITCH_ENbitstobezeroforroleswitch, *donotsetthesebitsforthosedevices.
*/
val = readl(data->base + DUAL_ROLE_CFG0); switch (role) { case USB_ROLE_NONE:
val |= SW_IDPIN;
val &= ~SW_VBUS_VALID;
drd_config = DRD_CONFIG_DYNAMIC; break; case USB_ROLE_HOST:
val &= ~SW_IDPIN;
val &= ~SW_VBUS_VALID;
drd_config = DRD_CONFIG_STATIC_HOST; break; case USB_ROLE_DEVICE:
val |= SW_IDPIN;
val |= SW_VBUS_VALID;
drd_config = DRD_CONFIG_STATIC_DEVICE; break;
}
val |= SW_IDPIN_EN; if (data->enable_sw_switch) {
val &= ~DRD_CONFIG_MASK;
val |= SW_SWITCH_EN | drd_config;
}
writel(val, data->base + DUAL_ROLE_CFG0);
acpi_release_global_lock(glk);
/* In most case it takes about 600ms to finish mode switching */
timeout = jiffies + msecs_to_jiffies(DUAL_ROLE_CFG1_POLL_TIMEOUT);
/* Polling on CFG1 register to confirm mode switch.*/ do {
val = readl(data->base + DUAL_ROLE_CFG1); if (!!(val & HOST_MODE) == (role == USB_ROLE_HOST)) {
pm_runtime_put(data->dev); return0;
}
/* Interval for polling is set to about 5 - 10 ms */
usleep_range(5000, 10000);
} while (time_before(jiffies, timeout));
pm_runtime_put(data->dev);
dev_warn(data->dev, "Timeout waiting for role-switch\n"); return -ETIMEDOUT;
}
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.