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;
}