static int __init midas_extcon_init(void) { int ret; midas_extcon = extcon_get_extcon_dev(EXTCON_DEV_NAME); if (!midas_extcon) { printk(KERN_ERR "Failed to get extcon device of %s\n", EXTCON_DEV_NAME); ret = -EINVAL; goto err_extcon; } INIT_WORK(&extcon_notifier_work, midas_extcon_notifier_work); extcon_nb.notifier_call = midas_extcon_notifier; ret = extcon_register_notifier(midas_extcon, &extcon_nb); if (ret < 0) { pr_err("Failed to register extcon device for mms_ts\n"); ret = -EINVAL; goto err_extcon; } /* TODO */ return 0; err_extcon: midas_extcon = NULL; return ret; }
static int omap_otg_probe(struct platform_device *pdev) { const struct omap_usb_config *config = pdev->dev.platform_data; struct otg_device *otg_dev; struct extcon_dev *extcon; int ret; u32 rev; if (!config || !config->extcon) return -ENODEV; extcon = extcon_get_extcon_dev(config->extcon); if (!extcon) return -EPROBE_DEFER; otg_dev = devm_kzalloc(&pdev->dev, sizeof(*otg_dev), GFP_KERNEL); if (!otg_dev) return -ENOMEM; otg_dev->base = devm_ioremap_resource(&pdev->dev, &pdev->resource[0]); if (IS_ERR(otg_dev->base)) return PTR_ERR(otg_dev->base); otg_dev->extcon = extcon; otg_dev->id_nb.notifier_call = omap_otg_id_notifier; otg_dev->vbus_nb.notifier_call = omap_otg_vbus_notifier; ret = extcon_register_notifier(extcon, EXTCON_USB_HOST, &otg_dev->id_nb); if (ret) return ret; ret = extcon_register_notifier(extcon, EXTCON_USB, &otg_dev->vbus_nb); if (ret) { extcon_unregister_notifier(extcon, EXTCON_USB_HOST, &otg_dev->id_nb); return ret; } otg_dev->id = extcon_get_cable_state_(extcon, EXTCON_USB_HOST); otg_dev->vbus = extcon_get_cable_state_(extcon, EXTCON_USB); omap_otg_set_mode(otg_dev); rev = readl(otg_dev->base); dev_info(&pdev->dev, "OMAP USB OTG controller rev %d.%d (%s, id=%d, vbus=%d)\n", (rev >> 4) & 0xf, rev & 0xf, config->extcon, otg_dev->id, otg_dev->vbus); return 0; }
int extcon_port_register( char *extcon_name, struct extcon_dev *edev, struct extcon_cable_block *cables, void (*fn)(struct extcon_cable_block *)) { struct extcon_cable_block *cable; int ret = 0, num_cables; int i; if (!extcon_name) return -EINVAL; edev = extcon_get_extcon_dev(extcon_name); if (!edev) return -ENODEV; num_cables = edev->max_supported; cables = kzalloc(sizeof(struct extcon_cable_block) * num_cables, GFP_KERNEL); if (!cables) { pr_err("failed to allocate array of extcon_cable_block(%s)\n", extcon_name); return -ENOMEM; } for (i = 0 ; i < num_cables ; i++) { cable = &cables[i]; strcpy(cable->extcon_name, extcon_name); strcpy(cable->name, edev->supported_cable[i]); cable->function = fn; INIT_WORK(&cable->wq, extcon_work); cable->nb.notifier_call = extcon_notifier; ret = extcon_register_interest(&cable->obj, cable->extcon_name, cable->name, &cable->nb); if (ret < 0) { pr_err("Cannot register extcon_dev for %s(cable: %s)\n", cable->extcon_name, cable->name); goto err_extcon; } } return 0; err_extcon: for (i = 0 ; i < num_cables ; i++) { cable = &cables[i]; /* Unregister only extcon device which is initialized */ if (cable->nb.notifier_call) { ret = extcon_unregister_interest(&cable->obj); pr_err("Unregister extcon_dev for %s(cable: %s)\n", cable->extcon_name, cable->name); } } kfree(cables); return ret; }
static int ulpmc_battery_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct ulpmc_chip_info *chip; struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); int ret = 0; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) { dev_err(&client->dev, "SM bus doesn't support BYTE transactions\n"); return -EIO; } if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { dev_err(&client->dev, "SM bus doesn't support WORD transactions\n"); return -EIO; } /* check if the device is accessible */ ret = ulpmc_read_reg16(client, ULPMC_FG_REG_CNTL); if (ret < 0) { dev_err(&client->dev, "I2C read error:%s error:%d\n", __func__, ret); return -EIO; } else { dev_err(&client->dev, "FG control reg:%x\n", ret); } chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (!chip) { dev_err(&client->dev, "failed to allocate memory\n"); return -ENOMEM; } chip->client = client; chip->pdata = client->dev.platform_data; i2c_set_clientdata(client, chip); INIT_DELAYED_WORK(&chip->work, ulpmc_battery_monitor); mutex_init(&chip->lock); chip->bat.name = "byt-battery"; chip->bat.type = POWER_SUPPLY_TYPE_BATTERY; chip->bat.properties = ulpmc_battery_props; chip->bat.num_properties = ARRAY_SIZE(ulpmc_battery_props); chip->bat.get_property = ulpmc_get_battery_property; ret = power_supply_register(&client->dev, &chip->bat); if (ret) { dev_err(&client->dev, "failed to register battery: %d\n", ret); goto probe_failed_1; } chip->chrg.name = "byt-charger"; chip->chrg.type = POWER_SUPPLY_TYPE_MAINS; chip->chrg.properties = ulpmc_charger_properties; chip->chrg.num_properties = ARRAY_SIZE(ulpmc_charger_properties); chip->chrg.get_property = ulpmc_get_charger_property; ret = power_supply_register(&client->dev, &chip->chrg); if (ret) { dev_err(&client->dev, "failed to register charger: %d\n", ret); goto probe_failed_2; } /* get extcon device */ chip->edev = extcon_get_extcon_dev(chip->pdata->extcon_devname); if (!chip->edev) { dev_err(&client->dev, "failed to get extcon device\n"); } else { chip->nb.notifier_call = &ulpmc_extcon_callback; ret = extcon_register_notifier(chip->edev, &chip->nb); if (ret) dev_err(&client->dev, "failed to register extcon notifier:%d\n", ret); } /* get irq and register */ ulpmc_init_irq(chip); /* schedule status monitoring worker */ schedule_delayed_work(&chip->work, STATUS_MON_JIFFIES); return 0; probe_failed_2: power_supply_unregister(&chip->bat); probe_failed_1: kfree(chip); return ret; }
static int axp288_charger_probe(struct platform_device *pdev) { int ret, i, pirq; struct axp288_chrg_info *info; struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); struct power_supply_config charger_cfg = {}; info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; info->pdev = pdev; info->regmap = axp20x->regmap; info->regmap_irqc = axp20x->regmap_irqc; info->pdata = pdev->dev.platform_data; if (!info->pdata) { /* Try ACPI provided pdata via device properties */ if (!device_property_present(&pdev->dev, "axp288_charger_data\n")) dev_err(&pdev->dev, "failed to get platform data\n"); return -ENODEV; } info->cable.edev = extcon_get_extcon_dev(AXP288_EXTCON_DEV_NAME); if (info->cable.edev == NULL) { dev_dbg(&pdev->dev, "%s is not ready, probe deferred\n", AXP288_EXTCON_DEV_NAME); return -EPROBE_DEFER; } /* Register for extcon notification */ INIT_WORK(&info->cable.work, axp288_charger_extcon_evt_worker); info->cable.nb.notifier_call = axp288_charger_handle_cable_evt; ret = extcon_register_notifier(info->cable.edev, EXTCON_CHG_USB_SDP, &info->cable.nb); if (ret) { dev_err(&info->pdev->dev, "failed to register extcon notifier for SDP %d\n", ret); return ret; } ret = extcon_register_notifier(info->cable.edev, EXTCON_CHG_USB_CDP, &info->cable.nb); if (ret) { dev_err(&info->pdev->dev, "failed to register extcon notifier for CDP %d\n", ret); extcon_unregister_notifier(info->cable.edev, EXTCON_CHG_USB_SDP, &info->cable.nb); return ret; } ret = extcon_register_notifier(info->cable.edev, EXTCON_CHG_USB_DCP, &info->cable.nb); if (ret) { dev_err(&info->pdev->dev, "failed to register extcon notifier for DCP %d\n", ret); extcon_unregister_notifier(info->cable.edev, EXTCON_CHG_USB_SDP, &info->cable.nb); extcon_unregister_notifier(info->cable.edev, EXTCON_CHG_USB_CDP, &info->cable.nb); return ret; } platform_set_drvdata(pdev, info); mutex_init(&info->lock); /* Register with power supply class */ charger_cfg.drv_data = info; info->psy_usb = power_supply_register(&pdev->dev, &axp288_charger_desc, &charger_cfg); if (IS_ERR(info->psy_usb)) { dev_err(&pdev->dev, "failed to register power supply charger\n"); ret = PTR_ERR(info->psy_usb); goto psy_reg_failed; } /* Register for OTG notification */ INIT_WORK(&info->otg.work, axp288_charger_otg_evt_worker); info->otg.id_nb.notifier_call = axp288_charger_handle_otg_evt; ret = extcon_register_notifier(info->otg.cable, EXTCON_USB_HOST, &info->otg.id_nb); if (ret) dev_warn(&pdev->dev, "failed to register otg notifier\n"); if (info->otg.cable) info->otg.id_short = extcon_get_cable_state_( info->otg.cable, EXTCON_USB_HOST); /* Register charger interrupts */ for (i = 0; i < CHRG_INTR_END; i++) { pirq = platform_get_irq(info->pdev, i); info->irq[i] = regmap_irq_get_virq(info->regmap_irqc, pirq); if (info->irq[i] < 0) { dev_warn(&info->pdev->dev, "failed to get virtual interrupt=%d\n", pirq); ret = info->irq[i]; goto intr_reg_failed; } ret = devm_request_threaded_irq(&info->pdev->dev, info->irq[i], NULL, axp288_charger_irq_thread_handler, IRQF_ONESHOT, info->pdev->name, info); if (ret) { dev_err(&pdev->dev, "failed to request interrupt=%d\n", info->irq[i]); goto intr_reg_failed; } } charger_init_hw_regs(info); return 0; intr_reg_failed: if (info->otg.cable) extcon_unregister_notifier(info->otg.cable, EXTCON_USB_HOST, &info->otg.id_nb); power_supply_unregister(info->psy_usb); psy_reg_failed: extcon_unregister_notifier(info->cable.edev, EXTCON_CHG_USB_SDP, &info->cable.nb); extcon_unregister_notifier(info->cable.edev, EXTCON_CHG_USB_CDP, &info->cable.nb); extcon_unregister_notifier(info->cable.edev, EXTCON_CHG_USB_DCP, &info->cable.nb); return ret; }