in rtc-s3c.c [401:504]
static int s3c_rtc_probe(struct platform_device *pdev)
{
struct s3c_rtc *info = NULL;
int ret;
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
info->dev = &pdev->dev;
info->data = of_device_get_match_data(&pdev->dev);
if (!info->data) {
dev_err(&pdev->dev, "failed getting s3c_rtc_data\n");
return -EINVAL;
}
spin_lock_init(&info->alarm_lock);
platform_set_drvdata(pdev, info);
info->irq_alarm = platform_get_irq(pdev, 0);
if (info->irq_alarm < 0)
return info->irq_alarm;
dev_dbg(&pdev->dev, "s3c2410_rtc: alarm irq %d\n", info->irq_alarm);
/* get the memory region */
info->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(info->base))
return PTR_ERR(info->base);
info->rtc_clk = devm_clk_get(&pdev->dev, "rtc");
if (IS_ERR(info->rtc_clk)) {
ret = PTR_ERR(info->rtc_clk);
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev, "failed to find rtc clock\n");
else
dev_dbg(&pdev->dev, "probe deferred due to missing rtc clk\n");
return ret;
}
ret = clk_prepare_enable(info->rtc_clk);
if (ret)
return ret;
if (info->data->needs_src_clk) {
info->rtc_src_clk = devm_clk_get(&pdev->dev, "rtc_src");
if (IS_ERR(info->rtc_src_clk)) {
ret = dev_err_probe(&pdev->dev, PTR_ERR(info->rtc_src_clk),
"failed to find rtc source clock\n");
goto err_src_clk;
}
ret = clk_prepare_enable(info->rtc_src_clk);
if (ret)
goto err_src_clk;
}
/* disable RTC enable bits potentially set by the bootloader */
if (info->data->disable)
info->data->disable(info);
/* check to see if everything is setup correctly */
if (info->data->enable)
info->data->enable(info);
dev_dbg(&pdev->dev, "s3c2410_rtc: RTCCON=%02x\n",
readw(info->base + S3C2410_RTCCON));
device_init_wakeup(&pdev->dev, 1);
info->rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(info->rtc)) {
ret = PTR_ERR(info->rtc);
goto err_nortc;
}
info->rtc->ops = &s3c_rtcops;
info->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
info->rtc->range_max = RTC_TIMESTAMP_END_2099;
ret = devm_rtc_register_device(info->rtc);
if (ret)
goto err_nortc;
ret = devm_request_irq(&pdev->dev, info->irq_alarm, s3c_rtc_alarmirq,
0, "s3c2410-rtc alarm", info);
if (ret) {
dev_err(&pdev->dev, "IRQ%d error %d\n", info->irq_alarm, ret);
goto err_nortc;
}
s3c_rtc_disable_clk(info);
return 0;
err_nortc:
if (info->data->disable)
info->data->disable(info);
if (info->data->needs_src_clk)
clk_disable_unprepare(info->rtc_src_clk);
err_src_clk:
clk_disable_unprepare(info->rtc_clk);
return ret;
}