static int s3c_rtc_probe()

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