in extcon-ptn5150.c [197:296]
static int ptn5150_i2c_probe(struct i2c_client *i2c)
{
struct device *dev = &i2c->dev;
struct device_node *np = i2c->dev.of_node;
struct ptn5150_info *info;
int ret;
if (!np)
return -EINVAL;
info = devm_kzalloc(&i2c->dev, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
i2c_set_clientdata(i2c, info);
info->dev = &i2c->dev;
info->i2c = i2c;
info->vbus_gpiod = devm_gpiod_get(&i2c->dev, "vbus", GPIOD_OUT_LOW);
if (IS_ERR(info->vbus_gpiod)) {
ret = PTR_ERR(info->vbus_gpiod);
if (ret == -ENOENT) {
dev_info(dev, "No VBUS GPIO, ignoring VBUS control\n");
info->vbus_gpiod = NULL;
} else {
return dev_err_probe(dev, ret, "failed to get VBUS GPIO\n");
}
}
mutex_init(&info->mutex);
INIT_WORK(&info->irq_work, ptn5150_irq_work);
info->regmap = devm_regmap_init_i2c(i2c, &ptn5150_regmap_config);
if (IS_ERR(info->regmap)) {
return dev_err_probe(info->dev, PTR_ERR(info->regmap),
"failed to allocate register map\n");
}
if (i2c->irq > 0) {
info->irq = i2c->irq;
} else {
info->int_gpiod = devm_gpiod_get(&i2c->dev, "int", GPIOD_IN);
if (IS_ERR(info->int_gpiod)) {
return dev_err_probe(dev, PTR_ERR(info->int_gpiod),
"failed to get INT GPIO\n");
}
info->irq = gpiod_to_irq(info->int_gpiod);
if (info->irq < 0) {
dev_err(dev, "failed to get INTB IRQ\n");
return info->irq;
}
}
ret = devm_request_threaded_irq(dev, info->irq, NULL,
ptn5150_irq_handler,
IRQF_TRIGGER_FALLING |
IRQF_ONESHOT,
i2c->name, info);
if (ret < 0) {
dev_err(dev, "failed to request handler for INTB IRQ\n");
return ret;
}
/* Allocate extcon device */
info->edev = devm_extcon_dev_allocate(info->dev, ptn5150_extcon_cable);
if (IS_ERR(info->edev)) {
dev_err(info->dev, "failed to allocate memory for extcon\n");
return -ENOMEM;
}
/* Register extcon device */
ret = devm_extcon_dev_register(info->dev, info->edev);
if (ret) {
dev_err(info->dev, "failed to register extcon device\n");
return ret;
}
extcon_set_property_capability(info->edev, EXTCON_USB,
EXTCON_PROP_USB_VBUS);
extcon_set_property_capability(info->edev, EXTCON_USB_HOST,
EXTCON_PROP_USB_VBUS);
extcon_set_property_capability(info->edev, EXTCON_USB_HOST,
EXTCON_PROP_USB_TYPEC_POLARITY);
/* Initialize PTN5150 device and print vendor id and version id */
ret = ptn5150_init_dev_type(info);
if (ret)
return -EINVAL;
/*
* Update current extcon state if for example OTG connection was there
* before the probe
*/
mutex_lock(&info->mutex);
ptn5150_check_state(info);
mutex_unlock(&info->mutex);
return 0;
}