static int cdns_rtc_probe()

in rtc-cadence.c [255:355]


static int cdns_rtc_probe(struct platform_device *pdev)
{
	struct cdns_rtc *crtc;
	int ret;
	unsigned long ref_clk_freq;

	crtc = devm_kzalloc(&pdev->dev, sizeof(*crtc), GFP_KERNEL);
	if (!crtc)
		return -ENOMEM;

	crtc->regs = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(crtc->regs))
		return PTR_ERR(crtc->regs);

	crtc->irq = platform_get_irq(pdev, 0);
	if (crtc->irq < 0)
		return -EINVAL;

	crtc->pclk = devm_clk_get(&pdev->dev, "pclk");
	if (IS_ERR(crtc->pclk)) {
		ret = PTR_ERR(crtc->pclk);
		dev_err(&pdev->dev,
			"Failed to retrieve the peripheral clock, %d\n", ret);
		return ret;
	}

	crtc->ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
	if (IS_ERR(crtc->ref_clk)) {
		ret = PTR_ERR(crtc->ref_clk);
		dev_err(&pdev->dev,
			"Failed to retrieve the reference clock, %d\n", ret);
		return ret;
	}

	crtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
	if (IS_ERR(crtc->rtc_dev))
		return PTR_ERR(crtc->rtc_dev);

	platform_set_drvdata(pdev, crtc);

	ret = clk_prepare_enable(crtc->pclk);
	if (ret) {
		dev_err(&pdev->dev,
			"Failed to enable the peripheral clock, %d\n", ret);
		return ret;
	}

	ret = clk_prepare_enable(crtc->ref_clk);
	if (ret) {
		dev_err(&pdev->dev,
			"Failed to enable the reference clock, %d\n", ret);
		goto err_disable_pclk;
	}

	ref_clk_freq = clk_get_rate(crtc->ref_clk);
	if ((ref_clk_freq != 1) && (ref_clk_freq != 100)) {
		dev_err(&pdev->dev,
			"Invalid reference clock frequency %lu Hz.\n",
			ref_clk_freq);
		ret = -EINVAL;
		goto err_disable_ref_clk;
	}

	ret = devm_request_irq(&pdev->dev, crtc->irq,
			       cdns_rtc_irq_handler, 0,
			       dev_name(&pdev->dev), &pdev->dev);
	if (ret) {
		dev_err(&pdev->dev,
			"Failed to request interrupt for the device, %d\n",
			ret);
		goto err_disable_ref_clk;
	}

	/* The RTC supports 01.01.1900 - 31.12.2999 */
	crtc->rtc_dev->range_min = mktime64(1900,  1,  1,  0,  0,  0);
	crtc->rtc_dev->range_max = mktime64(2999, 12, 31, 23, 59, 59);

	crtc->rtc_dev->ops = &cdns_rtc_ops;
	device_init_wakeup(&pdev->dev, true);

	/* Always use 24-hour mode and keep the RTC values */
	writel(0, crtc->regs + CDNS_RTC_HMR);
	writel(CDNS_RTC_KRTCR_KRTC, crtc->regs + CDNS_RTC_KRTCR);

	ret = devm_rtc_register_device(crtc->rtc_dev);
	if (ret)
		goto err_disable_wakeup;

	return 0;

err_disable_wakeup:
	device_init_wakeup(&pdev->dev, false);

err_disable_ref_clk:
	clk_disable_unprepare(crtc->ref_clk);

err_disable_pclk:
	clk_disable_unprepare(crtc->pclk);

	return ret;
}