static int rv8803_probe()

in rtc-rv8803.c [512:600]


static int rv8803_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	struct i2c_adapter *adapter = client->adapter;
	struct rv8803_data *rv8803;
	int err, flags;
	struct nvmem_config nvmem_cfg = {
		.name = "rv8803_nvram",
		.word_size = 1,
		.stride = 1,
		.size = 1,
		.reg_read = rv8803_nvram_read,
		.reg_write = rv8803_nvram_write,
		.priv = client,
	};

	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
				     I2C_FUNC_SMBUS_I2C_BLOCK)) {
		dev_err(&adapter->dev, "doesn't support I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK\n");
		return -EIO;
	}

	rv8803 = devm_kzalloc(&client->dev, sizeof(struct rv8803_data),
			      GFP_KERNEL);
	if (!rv8803)
		return -ENOMEM;

	mutex_init(&rv8803->flags_lock);
	rv8803->client = client;
	if (client->dev.of_node)
		rv8803->type = (enum rv8803_type)
			of_device_get_match_data(&client->dev);
	else
		rv8803->type = id->driver_data;
	i2c_set_clientdata(client, rv8803);

	flags = rv8803_read_reg(client, RV8803_FLAG);
	if (flags < 0)
		return flags;

	if (flags & RV8803_FLAG_V1F)
		dev_warn(&client->dev, "Voltage low, temperature compensation stopped.\n");

	if (flags & RV8803_FLAG_V2F)
		dev_warn(&client->dev, "Voltage low, data loss detected.\n");

	if (flags & RV8803_FLAG_AF)
		dev_warn(&client->dev, "An alarm maybe have been missed.\n");

	rv8803->rtc = devm_rtc_allocate_device(&client->dev);
	if (IS_ERR(rv8803->rtc))
		return PTR_ERR(rv8803->rtc);

	if (client->irq > 0) {
		err = devm_request_threaded_irq(&client->dev, client->irq,
						NULL, rv8803_handle_irq,
						IRQF_TRIGGER_LOW | IRQF_ONESHOT,
						"rv8803", client);
		if (err) {
			dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n");
			client->irq = 0;
		}
	}
	if (!client->irq)
		clear_bit(RTC_FEATURE_ALARM, rv8803->rtc->features);

	err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA);
	if (err)
		return err;

	err = rx8900_trickle_charger_init(rv8803);
	if (err) {
		dev_err(&client->dev, "failed to init charger\n");
		return err;
	}

	rv8803->rtc->ops = &rv8803_rtc_ops;
	rv8803->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
	rv8803->rtc->range_max = RTC_TIMESTAMP_END_2099;
	err = devm_rtc_register_device(rv8803->rtc);
	if (err)
		return err;

	devm_rtc_nvmem_register(rv8803->rtc, &nvmem_cfg);

	rv8803->rtc->max_user_freq = 1;

	return 0;
}