Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #5
0
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;
}