// SPDX-License-Identifier: GPL-2.0-only /* * Motorola CPCAP PMIC USB PHY driver * Copyright (C) 2017 Tony Lindgren <tony@atomide.com> * * Some parts based on earlier Motorola Linux kernel tree code in * board-mapphone-usb.c and cpcap-usb-det.c: * Copyright (C) 2007 - 2011 Motorola, Inc.
*/
error = cpcap_phy_get_ints_state(ddata, &s); if (error) return;
vbus = cpcap_usb_vbus_valid(ddata);
/* We need to kick the VBUS as USB A-host */ if (s.id_ground && ddata->vbus_provider) {
dev_dbg(ddata->dev, "still in USB A-host mode, kicking VBUS\n");
/* * Force check state again after musb has reoriented, * otherwise devices won't enumerate after loading PHY * driver.
*/
schedule_delayed_work(&ddata->detect_work,
msecs_to_jiffies(1000));
return;
}
if (s.id_ground && !ddata->docked) {
dev_dbg(ddata->dev, "id ground, USB host mode\n");
ddata->vbus_provider = true;
error = cpcap_usb_set_usb_mode(ddata); if (error) goto out_err;
/* Otherwise assume we're connected to a USB host */ if (vbus) {
dev_dbg(ddata->dev, "connected to USB host\n");
error = cpcap_usb_set_usb_mode(ddata); if (error) goto out_err;
cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_VALID);
staticint cpcap_usb_init_interrupts(struct platform_device *pdev, struct cpcap_phy_ddata *ddata)
{ int i, error;
for (i = 0; i < ARRAY_SIZE(cpcap_phy_irqs); i++) {
error = cpcap_usb_init_irq(pdev, ddata, cpcap_phy_irqs[i]); if (error) return error;
}
return 0;
}
/* * Optional pins and modes. At least Motorola mapphone devices * are using two GPIOs and dynamic pinctrl to multiplex PHY pins * to UART, ULPI or UTMI mode.
*/
staticint cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata)
{ int error;
/* Disable lines to prevent glitches from waking up mdm6600 */
error = cpcap_usb_gpio_set_mode(ddata, CPCAP_UNKNOWN_DISABLED); if (error) goto out_err;
if (ddata->pins_uart) {
error = pinctrl_select_state(ddata->pins, ddata->pins_uart); if (error) goto out_err;
}
error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC1,
CPCAP_BIT_VBUSPD,
CPCAP_BIT_VBUSPD); if (error) goto out_err;
out_err:
dev_err(ddata->dev, "%s failed with %i\n", __func__, error);
return error;
}
staticint cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata)
{ int error;
/* Disable lines to prevent glitches from waking up mdm6600 */
error = cpcap_usb_gpio_set_mode(ddata, CPCAP_UNKNOWN_DISABLED); if (error) return error;
if (ddata->pins_utmi) {
error = pinctrl_select_state(ddata->pins, ddata->pins_utmi); if (error) {
dev_err(ddata->dev, "could not set usb mode: %i\n",
error);
return error;
}
}
error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC1,
CPCAP_BIT_VBUSPD, 0); if (error) goto out_err;
ddata->pins_ulpi = pinctrl_lookup_state(ddata->pins, "ulpi"); if (IS_ERR(ddata->pins_ulpi)) {
dev_info(ddata->dev, "ulpi pins not configured\n");
ddata->pins_ulpi = NULL;
}
ddata->pins_utmi = pinctrl_lookup_state(ddata->pins, "utmi"); if (IS_ERR(ddata->pins_utmi)) {
dev_info(ddata->dev, "utmi pins not configured\n");
ddata->pins_utmi = NULL;
}
ddata->pins_uart = pinctrl_lookup_state(ddata->pins, "uart"); if (IS_ERR(ddata->pins_uart)) {
dev_info(ddata->dev, "uart pins not configured\n");
ddata->pins_uart = NULL;
}
if (ddata->pins_uart) return pinctrl_select_state(ddata->pins, ddata->pins_uart);
return 0;
}
staticvoid cpcap_usb_init_optional_gpios(struct cpcap_phy_ddata *ddata)
{ int i;
for (i = 0; i < 2; i++) {
ddata->gpio[i] = devm_gpiod_get_index(ddata->dev, "mode",
i, GPIOD_OUT_HIGH); if (IS_ERR(ddata->gpio[i])) {
dev_info(ddata->dev, "no mode change GPIO%i: %li\n",
i, PTR_ERR(ddata->gpio[i]));
ddata->gpio[i] = NULL;
}
}
}
staticint cpcap_usb_init_iio(struct cpcap_phy_ddata *ddata)
{ enum iio_chan_type type; int error;
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.