static int pcf2127_probe()

in rtc-pcf2127.c [633:785]


static int pcf2127_probe(struct device *dev, struct regmap *regmap,
			 int alarm_irq, const char *name, bool is_pcf2127)
{
	struct pcf2127 *pcf2127;
	int ret = 0;
	unsigned int val;

	dev_dbg(dev, "%s\n", __func__);

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

	pcf2127->regmap = regmap;

	dev_set_drvdata(dev, pcf2127);

	pcf2127->rtc = devm_rtc_allocate_device(dev);
	if (IS_ERR(pcf2127->rtc))
		return PTR_ERR(pcf2127->rtc);

	pcf2127->rtc->ops = &pcf2127_rtc_ops;
	pcf2127->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
	pcf2127->rtc->range_max = RTC_TIMESTAMP_END_2099;
	pcf2127->rtc->set_start_time = true; /* Sets actual start to 1970 */
	pcf2127->rtc->uie_unsupported = 1;
	clear_bit(RTC_FEATURE_ALARM, pcf2127->rtc->features);

	if (alarm_irq > 0) {
		ret = devm_request_threaded_irq(dev, alarm_irq, NULL,
						pcf2127_rtc_irq,
						IRQF_TRIGGER_LOW | IRQF_ONESHOT,
						dev_name(dev), dev);
		if (ret) {
			dev_err(dev, "failed to request alarm irq\n");
			return ret;
		}
		pcf2127->irq_enabled = true;
	}

	if (alarm_irq > 0 || device_property_read_bool(dev, "wakeup-source")) {
		device_init_wakeup(dev, true);
		set_bit(RTC_FEATURE_ALARM, pcf2127->rtc->features);
	}

	if (is_pcf2127) {
		struct nvmem_config nvmem_cfg = {
			.priv = pcf2127,
			.reg_read = pcf2127_nvmem_read,
			.reg_write = pcf2127_nvmem_write,
			.size = 512,
		};

		ret = devm_rtc_nvmem_register(pcf2127->rtc, &nvmem_cfg);
	}

	/*
	 * The "Power-On Reset Override" facility prevents the RTC to do a reset
	 * after power on. For normal operation the PORO must be disabled.
	 */
	regmap_clear_bits(pcf2127->regmap, PCF2127_REG_CTRL1,
				PCF2127_BIT_CTRL1_POR_OVRD);

	ret = regmap_read(pcf2127->regmap, PCF2127_REG_CLKOUT, &val);
	if (ret < 0)
		return ret;

	if (!(val & PCF2127_BIT_CLKOUT_OTPR)) {
		ret = regmap_set_bits(pcf2127->regmap, PCF2127_REG_CLKOUT,
				      PCF2127_BIT_CLKOUT_OTPR);
		if (ret < 0)
			return ret;

		msleep(100);
	}

	/*
	 * Watchdog timer enabled and reset pin /RST activated when timed out.
	 * Select 1Hz clock source for watchdog timer.
	 * Note: Countdown timer disabled and not available.
	 * For pca2129, pcf2129, only bit[7] is for Symbol WD_CD
	 * of register watchdg_tim_ctl. The bit[6] is labeled
	 * as T. Bits labeled as T must always be written with
	 * logic 0.
	 */
	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_WD_CTL,
				 PCF2127_BIT_WD_CTL_CD1 |
				 PCF2127_BIT_WD_CTL_CD0 |
				 PCF2127_BIT_WD_CTL_TF1 |
				 PCF2127_BIT_WD_CTL_TF0,
				 PCF2127_BIT_WD_CTL_CD1 |
				 (is_pcf2127 ? PCF2127_BIT_WD_CTL_CD0 : 0) |
				 PCF2127_BIT_WD_CTL_TF1);
	if (ret) {
		dev_err(dev, "%s: watchdog config (wd_ctl) failed\n", __func__);
		return ret;
	}

	pcf2127_watchdog_init(dev, pcf2127);

	/*
	 * Disable battery low/switch-over timestamp and interrupts.
	 * Clear battery interrupt flags which can block new trigger events.
	 * Note: This is the default chip behaviour but added to ensure
	 * correct tamper timestamp and interrupt function.
	 */
	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3,
				 PCF2127_BIT_CTRL3_BTSE |
				 PCF2127_BIT_CTRL3_BIE |
				 PCF2127_BIT_CTRL3_BLIE, 0);
	if (ret) {
		dev_err(dev, "%s: interrupt config (ctrl3) failed\n",
			__func__);
		return ret;
	}

	/*
	 * Enable timestamp function and store timestamp of first trigger
	 * event until TSF1 and TFS2 interrupt flags are cleared.
	 */
	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_TS_CTRL,
				 PCF2127_BIT_TS_CTRL_TSOFF |
				 PCF2127_BIT_TS_CTRL_TSM,
				 PCF2127_BIT_TS_CTRL_TSM);
	if (ret) {
		dev_err(dev, "%s: tamper detection config (ts_ctrl) failed\n",
			__func__);
		return ret;
	}

	/*
	 * Enable interrupt generation when TSF1 or TSF2 timestamp flags
	 * are set. Interrupt signal is an open-drain output and can be
	 * left floating if unused.
	 */
	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2,
				 PCF2127_BIT_CTRL2_TSIE,
				 PCF2127_BIT_CTRL2_TSIE);
	if (ret) {
		dev_err(dev, "%s: tamper detection config (ctrl2) failed\n",
			__func__);
		return ret;
	}

	ret = rtc_add_group(pcf2127->rtc, &pcf2127_attr_group);
	if (ret) {
		dev_err(dev, "%s: tamper sysfs registering failed\n",
			__func__);
		return ret;
	}

	return devm_rtc_register_device(pcf2127->rtc);
}