for (i = 0; i < sizeof(sig); i++) {
ret = regmap_read(priv->regmap, sizeof(sig) - 1 - i, &val); if (ret < 0) return ret; if (val != sig[i]) {
dev_err(priv->dev, "signature mismatch!\n"); return -ENODEV;
}
}
return 0;
}
staticint tusb320_set_mode(struct tusb320_priv *priv, enum tusb320_mode mode)
{ int ret;
/* Mode cannot be changed while cable is attached */ if (priv->state != TUSB320_ATTACHED_STATE_NONE) return -EBUSY;
/* Write mode */
ret = regmap_write_bits(priv->regmap, TUSB320_REGA,
TUSB320_REGA_MODE_SELECT_MASK << TUSB320_REGA_MODE_SELECT_SHIFT,
mode << TUSB320_REGA_MODE_SELECT_SHIFT); if (ret) {
dev_err(priv->dev, "failed to write mode: %d\n", ret); return ret;
}
return 0;
}
staticint tusb320l_set_mode(struct tusb320_priv *priv, enum tusb320_mode mode)
{ int ret;
/* Disable CC state machine */
ret = regmap_write_bits(priv->regmap, TUSB320_REGA,
TUSB320L_REGA_DISABLE_TERM, 1); if (ret) {
dev_err(priv->dev, "failed to disable CC state machine: %d\n", ret); return ret;
}
/* Write mode */
ret = regmap_write_bits(priv->regmap, TUSB320_REGA,
TUSB320_REGA_MODE_SELECT_MASK << TUSB320_REGA_MODE_SELECT_SHIFT,
mode << TUSB320_REGA_MODE_SELECT_SHIFT); if (ret) {
dev_err(priv->dev, "failed to write mode: %d\n", ret); goto err;
}
msleep(5);
err: /* Re-enable CC state machine */
ret = regmap_write_bits(priv->regmap, TUSB320_REGA,
TUSB320L_REGA_DISABLE_TERM, 0); if (ret)
dev_err(priv->dev, "failed to re-enable CC state machine: %d\n", ret);
return ret;
}
staticint tusb320_reset(struct tusb320_priv *priv)
{ int ret;
/* Set mode to default (follow PORT pin) */
ret = priv->ops->set_mode(priv, TUSB320_MODE_PORT); if (ret && ret != -EBUSY) {
dev_err(priv->dev, "failed to set mode to PORT: %d\n", ret); return ret;
}
/* Perform soft reset */
ret = regmap_write_bits(priv->regmap, TUSB320_REGA,
TUSB320_REGA_I2C_SOFT_RESET, 1); if (ret) {
dev_err(priv->dev, "failed to write soft reset bit: %d\n", ret); return ret;
}
/* Wait for chip to go through reset */
msleep(95);
if (regmap_read(priv->regmap, TUSB320_REG9, ®)) {
dev_err(priv->dev, "error during i2c read!\n"); return IRQ_NONE;
}
if (!force_update && !(reg & TUSB320_REG9_INTERRUPT_STATUS)) return IRQ_NONE;
tusb320_extcon_irq_handler(priv, reg);
/* * Type-C support is optional. Only call the Type-C handler if a * port had been registered previously.
*/ if (priv->port)
tusb320_typec_irq_handler(priv, reg);
/* The Type-C connector is optional, for backward compatibility. */
connector = device_get_named_child_node(&client->dev, "connector"); if (!connector) return 0;
/* Type-C connector found. */
ret = typec_get_fw_cap(&priv->cap, connector); if (ret) goto err_put;
priv->port_type = priv->cap.type;
/* This goes into register 0x8 field CURRENT_MODE_ADVERTISE */
ret = fwnode_property_read_string(connector, "typec-power-opmode", &cap_str); if (ret) goto err_put;
ret = typec_find_pwr_opmode(cap_str); if (ret < 0) goto err_put;
priv->pwr_opmode = ret;
/* Initialize the hardware with the devicetree settings. */
ret = tusb320_set_adv_pwr_mode(priv); if (ret) goto err_put;
priv->port = typec_register_port(&client->dev, &priv->cap); if (IS_ERR(priv->port)) {
ret = PTR_ERR(priv->port); goto err_put;
}
/* Find any optional USB role switch that needs reporting to */
priv->role_sw = fwnode_usb_role_switch_get(connector); if (IS_ERR(priv->role_sw)) {
ret = PTR_ERR(priv->role_sw); goto err_unreg;
}
priv->regmap = devm_regmap_init_i2c(client, &tusb320_regmap_config); if (IS_ERR(priv->regmap)) return PTR_ERR(priv->regmap);
ret = tusb320_check_signature(priv); if (ret) return ret;
match_data = device_get_match_data(&client->dev); if (!match_data) return -EINVAL;
priv->ops = (struct tusb320_ops*)match_data;
if (priv->ops->get_revision) {
ret = priv->ops->get_revision(priv, &revision); if (ret)
dev_warn(priv->dev, "failed to read revision register: %d\n", ret); else
dev_info(priv->dev, "chip revision %d\n", revision);
}
ret = tusb320_extcon_probe(priv); if (ret) return ret;
ret = tusb320_typec_probe(client, priv); if (ret) return ret;
/* update initial state */
tusb320_state_update_handler(priv, true);
/* Reset chip to its default state */
ret = tusb320_reset(priv); if (ret)
dev_warn(priv->dev, "failed to reset chip: %d\n", ret); else /* * State and polarity might change after a reset, so update * them again and make sure the interrupt status bit is cleared.
*/
tusb320_state_update_handler(priv, true);
irq_d = irq_get_irq_data(client->irq); if (irq_d)
irq_trigger_type = irqd_get_trigger_type(irq_d);
ret = devm_request_threaded_irq(priv->dev, client->irq, NULL,
tusb320_irq_handler,
IRQF_ONESHOT | irq_trigger_type,
client->name, priv); if (ret)
tusb320_typec_remove(priv);
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.