static int max17042_probe()

in supply/max17042_battery.c [1040:1155]


static int max17042_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	struct i2c_adapter *adapter = client->adapter;
	const struct power_supply_desc *max17042_desc = &max17042_psy_desc;
	struct power_supply_config psy_cfg = {};
	const struct acpi_device_id *acpi_id = NULL;
	struct device *dev = &client->dev;
	struct max17042_chip *chip;
	int ret;
	int i;
	u32 val;

	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
		return -EIO;

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

	chip->client = client;
	if (id) {
		chip->chip_type = id->driver_data;
	} else {
		acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev);
		if (!acpi_id)
			return -ENODEV;

		chip->chip_type = acpi_id->driver_data;
	}
	chip->regmap = devm_regmap_init_i2c(client, &max17042_regmap_config);
	if (IS_ERR(chip->regmap)) {
		dev_err(&client->dev, "Failed to initialize regmap\n");
		return -EINVAL;
	}

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

	i2c_set_clientdata(client, chip);
	psy_cfg.drv_data = chip;
	psy_cfg.of_node = dev->of_node;

	/* When current is not measured,
	 * CURRENT_NOW and CURRENT_AVG properties should be invisible. */
	if (!chip->pdata->enable_current_sense)
		max17042_desc = &max17042_no_current_sense_psy_desc;

	if (chip->pdata->r_sns == 0)
		chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR;

	if (chip->pdata->init_data)
		for (i = 0; i < chip->pdata->num_init_data; i++)
			regmap_write(chip->regmap,
					chip->pdata->init_data[i].addr,
					chip->pdata->init_data[i].data);

	if (!chip->pdata->enable_current_sense) {
		regmap_write(chip->regmap, MAX17042_CGAIN, 0x0000);
		regmap_write(chip->regmap, MAX17042_MiscCFG, 0x0003);
		regmap_write(chip->regmap, MAX17042_LearnCFG, 0x0007);
	}

	chip->battery = devm_power_supply_register(&client->dev, max17042_desc,
						   &psy_cfg);
	if (IS_ERR(chip->battery)) {
		dev_err(&client->dev, "failed: power supply register\n");
		return PTR_ERR(chip->battery);
	}

	if (client->irq) {
		unsigned int flags = IRQF_ONESHOT;

		/*
		 * On ACPI systems the IRQ may be handled by ACPI-event code,
		 * so we need to share (if the ACPI code is willing to share).
		 */
		if (acpi_id)
			flags |= IRQF_SHARED | IRQF_PROBE_SHARED;

		ret = devm_request_threaded_irq(&client->dev, client->irq,
						NULL,
						max17042_thread_handler, flags,
						chip->battery->desc->name,
						chip);
		if (!ret) {
			regmap_update_bits(chip->regmap, MAX17042_CONFIG,
					CONFIG_ALRT_BIT_ENBL,
					CONFIG_ALRT_BIT_ENBL);
			max17042_set_soc_threshold(chip, 1);
		} else {
			client->irq = 0;
			if (ret != -EBUSY)
				dev_err(&client->dev, "Failed to get IRQ\n");
		}
	}
	/* Not able to update the charge threshold when exceeded? -> disable */
	if (!client->irq)
		regmap_write(chip->regmap, MAX17042_SALRT_Th, 0xff00);

	regmap_read(chip->regmap, MAX17042_STATUS, &val);
	if (val & STATUS_POR_BIT) {
		INIT_WORK(&chip->work, max17042_init_worker);
		ret = devm_add_action(&client->dev, max17042_stop_work, chip);
		if (ret)
			return ret;
		schedule_work(&chip->work);
	} else {
		chip->init_complete = 1;
	}

	return 0;
}