static int meson_rtc_probe()

in rtc-meson.c [282:381]


static int meson_rtc_probe(struct platform_device *pdev)
{
	struct nvmem_config meson_rtc_nvmem_config = {
		.name = "meson-rtc-regmem",
		.type = NVMEM_TYPE_BATTERY_BACKED,
		.word_size = 4,
		.stride = 4,
		.size = 4 * 4,
		.reg_read = meson_rtc_regmem_read,
		.reg_write = meson_rtc_regmem_write,
	};
	struct device *dev = &pdev->dev;
	struct meson_rtc *rtc;
	void __iomem *base;
	int ret;
	u32 tm;

	rtc = devm_kzalloc(dev, sizeof(struct meson_rtc), GFP_KERNEL);
	if (!rtc)
		return -ENOMEM;

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

	platform_set_drvdata(pdev, rtc);

	rtc->dev = dev;

	rtc->rtc->ops = &meson_rtc_ops;
	rtc->rtc->range_max = U32_MAX;

	base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(base))
		return PTR_ERR(base);

	rtc->peripheral = devm_regmap_init_mmio(dev, base,
					&meson_rtc_peripheral_regmap_config);
	if (IS_ERR(rtc->peripheral)) {
		dev_err(dev, "failed to create peripheral regmap\n");
		return PTR_ERR(rtc->peripheral);
	}

	rtc->reset = devm_reset_control_get(dev, NULL);
	if (IS_ERR(rtc->reset)) {
		dev_err(dev, "missing reset line\n");
		return PTR_ERR(rtc->reset);
	}

	rtc->vdd = devm_regulator_get(dev, "vdd");
	if (IS_ERR(rtc->vdd)) {
		dev_err(dev, "failed to get the vdd-supply\n");
		return PTR_ERR(rtc->vdd);
	}

	ret = regulator_enable(rtc->vdd);
	if (ret) {
		dev_err(dev, "failed to enable vdd-supply\n");
		return ret;
	}

	ret = meson_rtc_write_static(rtc, MESON_STATIC_DEFAULT);
	if (ret) {
		dev_err(dev, "failed to set static values\n");
		goto out_disable_vdd;
	}

	rtc->serial = devm_regmap_init(dev, &meson_rtc_serial_bus, rtc,
				       &meson_rtc_serial_regmap_config);
	if (IS_ERR(rtc->serial)) {
		dev_err(dev, "failed to create serial regmap\n");
		ret = PTR_ERR(rtc->serial);
		goto out_disable_vdd;
	}

	/*
	 * check if we can read RTC counter, if not then the RTC is probably
	 * not functional. If it isn't probably best to not bind.
	 */
	ret = regmap_read(rtc->serial, RTC_COUNTER, &tm);
	if (ret) {
		dev_err(dev, "cannot read RTC counter, RTC not functional\n");
		goto out_disable_vdd;
	}

	meson_rtc_nvmem_config.priv = rtc;
	ret = devm_rtc_nvmem_register(rtc->rtc, &meson_rtc_nvmem_config);
	if (ret)
		goto out_disable_vdd;

	ret = devm_rtc_register_device(rtc->rtc);
	if (ret)
		goto out_disable_vdd;

	return 0;

out_disable_vdd:
	regulator_disable(rtc->vdd);
	return ret;
}