示例#1
0
static int tps65217_charger_probe(struct platform_device *pdev)
{
	struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
	struct tps65217_charger *charger;
	struct power_supply_config cfg = {};
	int ret;

	dev_dbg(&pdev->dev, "%s\n", __func__);

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

	platform_set_drvdata(pdev, charger);
	charger->tps = tps;
	charger->dev = &pdev->dev;

	cfg.of_node = pdev->dev.of_node;
	cfg.drv_data = charger;

	charger->ac = devm_power_supply_register(&pdev->dev,
						 &tps65217_charger_desc,
						 &cfg);
	if (IS_ERR(charger->ac)) {
		dev_err(&pdev->dev, "failed: power supply register\n");
		return PTR_ERR(charger->ac);
	}

	ret = tps65217_config_charger(charger);
	if (ret < 0) {
		dev_err(charger->dev, "charger config failed, err %d\n", ret);
		return ret;
	}

	charger->poll_task = kthread_run(tps65217_charger_poll_task,
				      charger, "ktps65217charger");
	if (IS_ERR(charger->poll_task)) {
		ret = PTR_ERR(charger->poll_task);
		dev_err(charger->dev, "Unable to run kthread err %d\n", ret);
		return ret;
	}

	return 0;
}
示例#2
0
static int max8903_probe(struct platform_device *pdev)
{
	struct max8903_data *data;
	struct device *dev = &pdev->dev;
	struct max8903_pdata *pdata = pdev->dev.platform_data;
	struct power_supply_config psy_cfg = {};
	int ret = 0;
	int gpio;
	int ta_in = 0;
	int usb_in = 0;

	data = devm_kzalloc(dev, sizeof(struct max8903_data), GFP_KERNEL);
	if (data == NULL) {
		dev_err(dev, "Cannot allocate memory.\n");
		return -ENOMEM;
	}
	memcpy(&data->pdata, pdata, sizeof(struct max8903_pdata));
	data->dev = dev;
	platform_set_drvdata(pdev, data);

	if (pdata->dc_valid == false && pdata->usb_valid == false) {
		dev_err(dev, "No valid power sources.\n");
		return -EINVAL;
	}

	if (pdata->dc_valid) {
		if (pdata->dok && gpio_is_valid(pdata->dok) &&
				pdata->dcm && gpio_is_valid(pdata->dcm)) {
			gpio = pdata->dok; /* PULL_UPed Interrupt */
			ta_in = gpio_get_value(gpio) ? 0 : 1;

			gpio = pdata->dcm; /* Output */
			gpio_set_value(gpio, ta_in);
		} else {
			dev_err(dev, "When DC is wired, DOK and DCM should"
					" be wired as well.\n");
			return -EINVAL;
		}
	} else {
		if (pdata->dcm) {
			if (gpio_is_valid(pdata->dcm))
				gpio_set_value(pdata->dcm, 0);
			else {
				dev_err(dev, "Invalid pin: dcm.\n");
				return -EINVAL;
			}
		}
	}

	if (pdata->usb_valid) {
		if (pdata->uok && gpio_is_valid(pdata->uok)) {
			gpio = pdata->uok;
			usb_in = gpio_get_value(gpio) ? 0 : 1;
		} else {
			dev_err(dev, "When USB is wired, UOK should be wired."
					"as well.\n");
			return -EINVAL;
		}
	}

	if (pdata->cen) {
		if (gpio_is_valid(pdata->cen)) {
			gpio_set_value(pdata->cen, (ta_in || usb_in) ? 0 : 1);
		} else {
			dev_err(dev, "Invalid pin: cen.\n");
			return -EINVAL;
		}
	}

	if (pdata->chg) {
		if (!gpio_is_valid(pdata->chg)) {
			dev_err(dev, "Invalid pin: chg.\n");
			return -EINVAL;
		}
	}

	if (pdata->flt) {
		if (!gpio_is_valid(pdata->flt)) {
			dev_err(dev, "Invalid pin: flt.\n");
			return -EINVAL;
		}
	}

	if (pdata->usus) {
		if (!gpio_is_valid(pdata->usus)) {
			dev_err(dev, "Invalid pin: usus.\n");
			return -EINVAL;
		}
	}

	data->fault = false;
	data->ta_in = ta_in;
	data->usb_in = usb_in;

	data->psy_desc.name = "max8903_charger";
	data->psy_desc.type = (ta_in) ? POWER_SUPPLY_TYPE_MAINS :
			((usb_in) ? POWER_SUPPLY_TYPE_USB :
			 POWER_SUPPLY_TYPE_BATTERY);
	data->psy_desc.get_property = max8903_get_property;
	data->psy_desc.properties = max8903_charger_props;
	data->psy_desc.num_properties = ARRAY_SIZE(max8903_charger_props);

	psy_cfg.drv_data = data;

	data->psy = devm_power_supply_register(dev, &data->psy_desc, &psy_cfg);
	if (IS_ERR(data->psy)) {
		dev_err(dev, "failed: power supply register.\n");
		return PTR_ERR(data->psy);
	}

	if (pdata->dc_valid) {
		ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->dok),
					NULL, max8903_dcin,
					IRQF_TRIGGER_FALLING |
					IRQF_TRIGGER_RISING | IRQF_ONESHOT,
					"MAX8903 DC IN", data);
		if (ret) {
			dev_err(dev, "Cannot request irq %d for DC (%d)\n",
					gpio_to_irq(pdata->dok), ret);
			return ret;
		}
	}

	if (pdata->usb_valid) {
		ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->uok),
					NULL, max8903_usbin,
					IRQF_TRIGGER_FALLING |
					IRQF_TRIGGER_RISING | IRQF_ONESHOT,
					"MAX8903 USB IN", data);
		if (ret) {
			dev_err(dev, "Cannot request irq %d for USB (%d)\n",
					gpio_to_irq(pdata->uok), ret);
			return ret;
		}
	}

	if (pdata->flt) {
		ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->flt),
					NULL, max8903_fault,
					IRQF_TRIGGER_FALLING |
					IRQF_TRIGGER_RISING | IRQF_ONESHOT,
					"MAX8903 Fault", data);
		if (ret) {
			dev_err(dev, "Cannot request irq %d for Fault (%d)\n",
					gpio_to_irq(pdata->flt), ret);
			return ret;
		}
	}

	return 0;
}
示例#3
0
static int olpc_battery_probe(struct platform_device *pdev)
{
	struct power_supply_config bat_psy_cfg = {};
	struct power_supply_config ac_psy_cfg = {};
	struct olpc_battery_data *data;
	uint8_t status;
	uint8_t ecver;
	int ret;

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

	/* See if the EC is already there and get the EC revision */
	ret = olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0, &ecver, 1);
	if (ret)
		return ret;

	if (of_find_compatible_node(NULL, NULL, "olpc,xo1.75-ec")) {
		/* XO 1.75 */
		data->new_proto = true;
		data->little_endian = true;
	} else if (ecver > 0x44) {
		/* XO 1 or 1.5 with a new EC firmware. */
		data->new_proto = true;
	} else if (ecver < 0x44) {
		/*
		 * We've seen a number of EC protocol changes; this driver
		 * requires the latest EC protocol, supported by 0x44 and above.
		 */
		printk(KERN_NOTICE "OLPC EC version 0x%02x too old for "
			"battery driver.\n", ecver);
		return -ENXIO;
	}

	ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &status, 1);
	if (ret)
		return ret;

	/* Ignore the status. It doesn't actually matter */

	ac_psy_cfg.of_node = pdev->dev.of_node;
	ac_psy_cfg.drv_data = data;

	data->olpc_ac = devm_power_supply_register(&pdev->dev, &olpc_ac_desc,
								&ac_psy_cfg);
	if (IS_ERR(data->olpc_ac))
		return PTR_ERR(data->olpc_ac);

	if (of_device_is_compatible(pdev->dev.of_node, "olpc,xo1.5-battery")) {
		/* XO-1.5 */
		olpc_bat_desc.properties = olpc_xo15_bat_props;
		olpc_bat_desc.num_properties = ARRAY_SIZE(olpc_xo15_bat_props);
	} else {
		/* XO-1 */
		olpc_bat_desc.properties = olpc_xo1_bat_props;
		olpc_bat_desc.num_properties = ARRAY_SIZE(olpc_xo1_bat_props);
	}

	bat_psy_cfg.of_node = pdev->dev.of_node;
	bat_psy_cfg.drv_data = data;
	bat_psy_cfg.attr_grp = olpc_bat_sysfs_groups;

	data->olpc_bat = devm_power_supply_register(&pdev->dev, &olpc_bat_desc,
								&bat_psy_cfg);
	if (IS_ERR(data->olpc_bat))
		return PTR_ERR(data->olpc_bat);

	if (olpc_ec_wakeup_available()) {
		device_set_wakeup_capable(&data->olpc_ac->dev, true);
		device_set_wakeup_capable(&data->olpc_bat->dev, true);
	}

	return 0;
}
示例#4
0
static int bq24735_charger_probe(struct i2c_client *client,
				 const struct i2c_device_id *id)
{
	int ret;
	struct bq24735 *charger;
	struct power_supply_desc *supply_desc;
	struct power_supply_config psy_cfg = {};
	char *name;

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

	charger->pdata = client->dev.platform_data;

	if (IS_ENABLED(CONFIG_OF) && !charger->pdata && client->dev.of_node)
		charger->pdata = bq24735_parse_dt_data(client);

	if (!charger->pdata) {
		dev_err(&client->dev, "no platform data provided\n");
		return -EINVAL;
	}

	name = (char *)charger->pdata->name;
	if (!name) {
		name = devm_kasprintf(&client->dev, GFP_KERNEL,
				      "bq24735@%s",
				      dev_name(&client->dev));
		if (!name) {
			dev_err(&client->dev, "Failed to alloc device name\n");
			return -ENOMEM;
		}
	}

	charger->client = client;

	supply_desc = &charger->charger_desc;

	supply_desc->name = name;
	supply_desc->type = POWER_SUPPLY_TYPE_MAINS;
	supply_desc->properties = bq24735_charger_properties;
	supply_desc->num_properties = ARRAY_SIZE(bq24735_charger_properties);
	supply_desc->get_property = bq24735_charger_get_property;

	psy_cfg.supplied_to = charger->pdata->supplied_to;
	psy_cfg.num_supplicants = charger->pdata->num_supplicants;
	psy_cfg.of_node = client->dev.of_node;
	psy_cfg.drv_data = charger;

	i2c_set_clientdata(client, charger);

	ret = bq24735_read_word(client, BQ24735_MANUFACTURER_ID);
	if (ret < 0) {
		dev_err(&client->dev, "Failed to read manufacturer id : %d\n",
			ret);
		return ret;
	} else if (ret != 0x0040) {
		dev_err(&client->dev,
			"manufacturer id mismatch. 0x0040 != 0x%04x\n", ret);
		return -ENODEV;
	}

	ret = bq24735_read_word(client, BQ24735_DEVICE_ID);
	if (ret < 0) {
		dev_err(&client->dev, "Failed to read device id : %d\n", ret);
		return ret;
	} else if (ret != 0x000B) {
		dev_err(&client->dev,
			"device id mismatch. 0x000b != 0x%04x\n", ret);
		return -ENODEV;
	}

	if (gpio_is_valid(charger->pdata->status_gpio)) {
		ret = devm_gpio_request(&client->dev,
					charger->pdata->status_gpio,
					name);
		if (ret) {
			dev_err(&client->dev,
				"Failed GPIO request for GPIO %d: %d\n",
				charger->pdata->status_gpio, ret);
		}

		charger->pdata->status_gpio_valid = !ret;
	}

	ret = bq24735_config_charger(charger);
	if (ret < 0) {
		dev_err(&client->dev, "failed in configuring charger");
		return ret;
	}

	/* check for AC adapter presence */
	if (bq24735_charger_is_present(charger)) {
		ret = bq24735_enable_charging(charger);
		if (ret < 0) {
			dev_err(&client->dev, "Failed to enable charging\n");
			return ret;
		}
	}

	charger->charger = devm_power_supply_register(&client->dev, supply_desc,
						      &psy_cfg);
	if (IS_ERR(charger->charger)) {
		ret = PTR_ERR(charger->charger);
		dev_err(&client->dev, "Failed to register power supply: %d\n",
			ret);
		return ret;
	}

	if (client->irq) {
		ret = devm_request_threaded_irq(&client->dev, client->irq,
						NULL, bq24735_charger_isr,
						IRQF_TRIGGER_RISING |
						IRQF_TRIGGER_FALLING |
						IRQF_ONESHOT,
						supply_desc->name,
						charger->charger);
		if (ret) {
			dev_err(&client->dev,
				"Unable to register IRQ %d err %d\n",
				client->irq, ret);
			return ret;
		}
	}

	return 0;
}
示例#5
0
static int max77650_charger_probe(struct platform_device *pdev)
{
	struct power_supply_config pscfg = {};
	struct max77650_charger_data *chg;
	struct power_supply *battery;
	struct device *dev, *parent;
	int rv, chg_irq, chgin_irq;
	unsigned int prop;

	dev = &pdev->dev;
	parent = dev->parent;

	chg = devm_kzalloc(dev, sizeof(*chg), GFP_KERNEL);
	if (!chg)
		return -ENOMEM;

	platform_set_drvdata(pdev, chg);

	chg->map = dev_get_regmap(parent, NULL);
	if (!chg->map)
		return -ENODEV;

	chg->dev = dev;

	pscfg.of_node = dev->of_node;
	pscfg.drv_data = chg;

	chg_irq = platform_get_irq_byname(pdev, "CHG");
	if (chg_irq < 0)
		return chg_irq;

	chgin_irq = platform_get_irq_byname(pdev, "CHGIN");
	if (chgin_irq < 0)
		return chgin_irq;

	rv = devm_request_any_context_irq(dev, chg_irq,
					  max77650_charger_check_status,
					  IRQF_ONESHOT, "chg", chg);
	if (rv < 0)
		return rv;

	rv = devm_request_any_context_irq(dev, chgin_irq,
					  max77650_charger_check_status,
					  IRQF_ONESHOT, "chgin", chg);
	if (rv < 0)
		return rv;

	battery = devm_power_supply_register(dev,
					     &max77650_battery_desc, &pscfg);
	if (IS_ERR(battery))
		return PTR_ERR(battery);

	rv = of_property_read_u32(dev->of_node,
				  "input-voltage-min-microvolt", &prop);
	if (rv == 0) {
		rv = max77650_charger_set_vchgin_min(chg, prop);
		if (rv)
			return rv;
	}

	rv = of_property_read_u32(dev->of_node,
				  "input-current-limit-microamp", &prop);
	if (rv == 0) {
		rv = max77650_charger_set_ichgin_lim(chg, prop);
		if (rv)
			return rv;
	}

	return max77650_charger_enable(chg);
}
示例#6
0
static int gpio_charger_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	const struct gpio_charger_platform_data *pdata = dev->platform_data;
	struct power_supply_config psy_cfg = {};
	struct gpio_charger *gpio_charger;
	struct power_supply_desc *charger_desc;
	unsigned long flags;
	int irq, ret;

	if (!pdata && !dev->of_node) {
		dev_err(dev, "No platform data\n");
		return -ENOENT;
	}

	gpio_charger = devm_kzalloc(dev, sizeof(*gpio_charger), GFP_KERNEL);
	if (!gpio_charger)
		return -ENOMEM;

	/*
	 * This will fetch a GPIO descriptor from device tree, ACPI or
	 * boardfile descriptor tables. It's good to try this first.
	 */
	gpio_charger->gpiod = devm_gpiod_get(dev, NULL, GPIOD_IN);

	/*
	 * If this fails and we're not using device tree, try the
	 * legacy platform data method.
	 */
	if (IS_ERR(gpio_charger->gpiod) && !dev->of_node) {
		/* Non-DT: use legacy GPIO numbers */
		if (!gpio_is_valid(pdata->gpio)) {
			dev_err(dev, "Invalid gpio pin in pdata\n");
			return -EINVAL;
		}
		flags = GPIOF_IN;
		if (pdata->gpio_active_low)
			flags |= GPIOF_ACTIVE_LOW;
		ret = devm_gpio_request_one(dev, pdata->gpio, flags,
					    dev_name(dev));
		if (ret) {
			dev_err(dev, "Failed to request gpio pin: %d\n", ret);
			return ret;
		}
		/* Then convert this to gpiod for now */
		gpio_charger->gpiod = gpio_to_desc(pdata->gpio);
	} else if (IS_ERR(gpio_charger->gpiod)) {
		/* Just try again if this happens */
		if (PTR_ERR(gpio_charger->gpiod) == -EPROBE_DEFER)
			return -EPROBE_DEFER;
		dev_err(dev, "error getting GPIO descriptor\n");
		return PTR_ERR(gpio_charger->gpiod);
	}

	charger_desc = &gpio_charger->charger_desc;
	charger_desc->properties = gpio_charger_properties;
	charger_desc->num_properties = ARRAY_SIZE(gpio_charger_properties);
	charger_desc->get_property = gpio_charger_get_property;

	psy_cfg.of_node = dev->of_node;
	psy_cfg.drv_data = gpio_charger;

	if (pdata) {
		charger_desc->name = pdata->name;
		charger_desc->type = pdata->type;
		psy_cfg.supplied_to = pdata->supplied_to;
		psy_cfg.num_supplicants = pdata->num_supplicants;
	} else {
		charger_desc->name = dev->of_node->name;
		charger_desc->type = gpio_charger_get_type(dev);
	}

	if (!charger_desc->name)
		charger_desc->name = pdev->name;

	gpio_charger->charger = devm_power_supply_register(dev, charger_desc,
							   &psy_cfg);
	if (IS_ERR(gpio_charger->charger)) {
		ret = PTR_ERR(gpio_charger->charger);
		dev_err(dev, "Failed to register power supply: %d\n", ret);
		return ret;
	}

	irq = gpiod_to_irq(gpio_charger->gpiod);
	if (irq > 0) {
		ret = devm_request_any_context_irq(dev, irq, gpio_charger_irq,
				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
				dev_name(dev), gpio_charger->charger);
		if (ret < 0)
			dev_warn(dev, "Failed to request irq: %d\n", ret);
		else
			gpio_charger->irq = irq;
	}

	platform_set_drvdata(pdev, gpio_charger);

	device_init_wakeup(dev, 1);

	return 0;
}
示例#7
0
static int axp20x_usb_power_probe(struct platform_device *pdev)
{
	struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
	struct power_supply_config psy_cfg = {};
	struct axp20x_usb_power *power;
	static const char * const axp20x_irq_names[] = { "VBUS_PLUGIN",
		"VBUS_REMOVAL", "VBUS_VALID", "VBUS_NOT_VALID", NULL };
	static const char * const axp22x_irq_names[] = {
		"VBUS_PLUGIN", "VBUS_REMOVAL", NULL };
	const char * const *irq_names;
	const struct power_supply_desc *usb_power_desc;
	int i, irq, ret;

	if (!of_device_is_available(pdev->dev.of_node))
		return -ENODEV;

	if (!axp20x) {
		dev_err(&pdev->dev, "Parent drvdata not set\n");
		return -EINVAL;
	}

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

	power->axp20x_id = (enum axp20x_variants)of_device_get_match_data(
								&pdev->dev);

	power->np = pdev->dev.of_node;
	power->regmap = axp20x->regmap;

	if (power->axp20x_id == AXP202_ID) {
		/* Enable vbus valid checking */
		ret = regmap_update_bits(power->regmap, AXP20X_VBUS_MON,
					 AXP20X_VBUS_MON_VBUS_VALID,
					 AXP20X_VBUS_MON_VBUS_VALID);
		if (ret)
			return ret;

		if (IS_ENABLED(CONFIG_AXP20X_ADC))
			ret = configure_iio_channels(pdev, power);
		else
			ret = configure_adc_registers(power);

		if (ret)
			return ret;

		usb_power_desc = &axp20x_usb_power_desc;
		irq_names = axp20x_irq_names;
	} else if (power->axp20x_id == AXP221_ID ||
		   power->axp20x_id == AXP223_ID) {
		usb_power_desc = &axp22x_usb_power_desc;
		irq_names = axp22x_irq_names;
	} else {
		dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n",
			axp20x->variant);
		return -EINVAL;
	}

	psy_cfg.of_node = pdev->dev.of_node;
	psy_cfg.drv_data = power;

	power->supply = devm_power_supply_register(&pdev->dev, usb_power_desc,
						   &psy_cfg);
	if (IS_ERR(power->supply))
		return PTR_ERR(power->supply);

	/* Request irqs after registering, as irqs may trigger immediately */
	for (i = 0; irq_names[i]; i++) {
		irq = platform_get_irq_byname(pdev, irq_names[i]);
		if (irq < 0) {
			dev_warn(&pdev->dev, "No IRQ for %s: %d\n",
				 irq_names[i], irq);
			continue;
		}
		irq = regmap_irq_get_virq(axp20x->regmap_irqc, irq);
		ret = devm_request_any_context_irq(&pdev->dev, irq,
				axp20x_usb_power_irq, 0, DRVNAME, power);
		if (ret < 0)
			dev_warn(&pdev->dev, "Error requesting %s IRQ: %d\n",
				 irq_names[i], ret);
	}

	return 0;
}