Esempio n. 1
0
static int dwc3_omap_extcon_register(struct dwc3_omap *omap)
{
	int			ret;
	struct device_node	*node = omap->dev->of_node;
	struct extcon_dev	*edev;

	if (of_property_read_bool(node, "extcon")) {
		edev = extcon_get_edev_by_phandle(omap->dev, 0);
		if (IS_ERR(edev)) {
			dev_vdbg(omap->dev, "couldn't get extcon device\n");
			return -EPROBE_DEFER;
		}

		omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier;
		ret = extcon_register_notifier(edev, EXTCON_USB,
						&omap->vbus_nb);
		if (ret < 0)
			dev_vdbg(omap->dev, "failed to register notifier for USB\n");

		omap->id_nb.notifier_call = dwc3_omap_id_notifier;
		ret = extcon_register_notifier(edev, EXTCON_USB_HOST,
						&omap->id_nb);
		if (ret < 0)
			dev_vdbg(omap->dev, "failed to register notifier for USB-HOST\n");

		if (extcon_get_cable_state_(edev, EXTCON_USB) == true)
			dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
		if (extcon_get_cable_state_(edev, EXTCON_USB_HOST) == true)
			dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);

		omap->edev = edev;
	}

	return 0;
}
Esempio n. 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;
}
Esempio n. 3
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;
}
Esempio n. 4
0
static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg)
{
	struct msm_otg_platform_data *pdata;
	struct extcon_dev *ext_id, *ext_vbus;
	struct device_node *node = pdev->dev.of_node;
	struct property *prop;
	int len, ret, words;
	u32 val, tmp[3];

	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
	if (!pdata)
		return -ENOMEM;

	motg->pdata = pdata;

	pdata->phy_type = (enum msm_usb_phy_type)of_device_get_match_data(&pdev->dev);
	if (!pdata->phy_type)
		return 1;

	motg->link_rst = devm_reset_control_get(&pdev->dev, "link");
	if (IS_ERR(motg->link_rst))
		return PTR_ERR(motg->link_rst);

	motg->phy_rst = devm_reset_control_get(&pdev->dev, "phy");
	if (IS_ERR(motg->phy_rst))
		motg->phy_rst = NULL;

	pdata->mode = usb_get_dr_mode(&pdev->dev);
	if (pdata->mode == USB_DR_MODE_UNKNOWN)
		pdata->mode = USB_DR_MODE_OTG;

	pdata->otg_control = OTG_PHY_CONTROL;
	if (!of_property_read_u32(node, "qcom,otg-control", &val))
		if (val == OTG_PMIC_CONTROL)
			pdata->otg_control = val;

	if (!of_property_read_u32(node, "qcom,phy-num", &val) && val < 2)
		motg->phy_number = val;

	motg->vdd_levels[VDD_LEVEL_NONE] = USB_PHY_SUSP_DIG_VOL;
	motg->vdd_levels[VDD_LEVEL_MIN] = USB_PHY_VDD_DIG_VOL_MIN;
	motg->vdd_levels[VDD_LEVEL_MAX] = USB_PHY_VDD_DIG_VOL_MAX;

	if (of_get_property(node, "qcom,vdd-levels", &len) &&
	    len == sizeof(tmp)) {
		of_property_read_u32_array(node, "qcom,vdd-levels",
					   tmp, len / sizeof(*tmp));
		motg->vdd_levels[VDD_LEVEL_NONE] = tmp[VDD_LEVEL_NONE];
		motg->vdd_levels[VDD_LEVEL_MIN] = tmp[VDD_LEVEL_MIN];
		motg->vdd_levels[VDD_LEVEL_MAX] = tmp[VDD_LEVEL_MAX];
	}

	motg->manual_pullup = of_property_read_bool(node, "qcom,manual-pullup");

	motg->switch_gpio = devm_gpiod_get_optional(&pdev->dev, "switch",
						    GPIOD_OUT_LOW);
	if (IS_ERR(motg->switch_gpio))
		return PTR_ERR(motg->switch_gpio);

	ext_id = ERR_PTR(-ENODEV);
	ext_vbus = ERR_PTR(-ENODEV);
	if (of_property_read_bool(node, "extcon")) {

		/* Each one of them is not mandatory */
		ext_vbus = extcon_get_edev_by_phandle(&pdev->dev, 0);
		if (IS_ERR(ext_vbus) && PTR_ERR(ext_vbus) != -ENODEV)
			return PTR_ERR(ext_vbus);

		ext_id = extcon_get_edev_by_phandle(&pdev->dev, 1);
		if (IS_ERR(ext_id) && PTR_ERR(ext_id) != -ENODEV)
			return PTR_ERR(ext_id);
	}

	if (!IS_ERR(ext_vbus)) {
		motg->vbus.extcon = ext_vbus;
		motg->vbus.nb.notifier_call = msm_otg_vbus_notifier;
		ret = extcon_register_notifier(ext_vbus, EXTCON_USB,
						&motg->vbus.nb);
		if (ret < 0) {
			dev_err(&pdev->dev, "register VBUS notifier failed\n");
			return ret;
		}

		ret = extcon_get_cable_state_(ext_vbus, EXTCON_USB);
		if (ret)
			set_bit(B_SESS_VLD, &motg->inputs);
		else
			clear_bit(B_SESS_VLD, &motg->inputs);
	}

	if (!IS_ERR(ext_id)) {
		motg->id.extcon = ext_id;
		motg->id.nb.notifier_call = msm_otg_id_notifier;
		ret = extcon_register_notifier(ext_id, EXTCON_USB_HOST,
						&motg->id.nb);
		if (ret < 0) {
			dev_err(&pdev->dev, "register ID notifier failed\n");
			extcon_unregister_notifier(motg->vbus.extcon,
						   EXTCON_USB, &motg->vbus.nb);
			return ret;
		}

		ret = extcon_get_cable_state_(ext_id, EXTCON_USB_HOST);
		if (ret)
			clear_bit(ID, &motg->inputs);
		else
			set_bit(ID, &motg->inputs);
	}

	prop = of_find_property(node, "qcom,phy-init-sequence", &len);
	if (!prop || !len)
		return 0;

	words = len / sizeof(u32);

	if (words >= ULPI_EXT_VENDOR_SPECIFIC) {
		dev_warn(&pdev->dev, "Too big PHY init sequence %d\n", words);
		return 0;
	}

	pdata->phy_init_seq = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
	if (!pdata->phy_init_seq)
		return 0;

	ret = of_property_read_u32_array(node, "qcom,phy-init-sequence",
					 pdata->phy_init_seq, words);
	if (!ret)
		pdata->phy_init_sz = words;

	return 0;
}
Esempio n. 5
0
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;
}
Esempio n. 6
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;
}