static int mxc_rtc_probe()

in rtc-mxc_v2.c [278:361]


static int mxc_rtc_probe(struct platform_device *pdev)
{
	struct mxc_rtc_data *pdata;
	void __iomem *ioaddr;
	int ret = 0;

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

	pdata->ioaddr = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(pdata->ioaddr))
		return PTR_ERR(pdata->ioaddr);

	ioaddr = pdata->ioaddr;

	pdata->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(pdata->clk)) {
		dev_err(&pdev->dev, "unable to get rtc clock!\n");
		return PTR_ERR(pdata->clk);
	}

	spin_lock_init(&pdata->lock);
	pdata->irq = platform_get_irq(pdev, 0);
	if (pdata->irq < 0)
		return pdata->irq;

	device_init_wakeup(&pdev->dev, 1);
	ret = dev_pm_set_wake_irq(&pdev->dev, pdata->irq);
	if (ret)
		dev_err(&pdev->dev, "failed to enable irq wake\n");

	ret = clk_prepare_enable(pdata->clk);
	if (ret)
		return ret;
	/* initialize glitch detect */
	writel(SRTC_LPPDR_INIT, ioaddr + SRTC_LPPDR);

	/* clear lp interrupt status */
	writel(0xFFFFFFFF, ioaddr + SRTC_LPSR);

	/* move out of init state */
	writel((SRTC_LPCR_IE | SRTC_LPCR_NSA), ioaddr + SRTC_LPCR);
	ret = mxc_rtc_wait_for_flag(ioaddr + SRTC_LPSR, SRTC_LPSR_IES);
	if (ret) {
		dev_err(&pdev->dev, "Timeout waiting for SRTC_LPSR_IES\n");
		clk_disable_unprepare(pdata->clk);
		return ret;
	}

	/* move out of non-valid state */
	writel((SRTC_LPCR_IE | SRTC_LPCR_NVE | SRTC_LPCR_NSA |
		SRTC_LPCR_EN_LP), ioaddr + SRTC_LPCR);
	ret = mxc_rtc_wait_for_flag(ioaddr + SRTC_LPSR, SRTC_LPSR_NVES);
	if (ret) {
		dev_err(&pdev->dev, "Timeout waiting for SRTC_LPSR_NVES\n");
		clk_disable_unprepare(pdata->clk);
		return ret;
	}

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

	pdata->rtc->ops = &mxc_rtc_ops;
	pdata->rtc->range_max = U32_MAX;

	clk_disable(pdata->clk);
	platform_set_drvdata(pdev, pdata);
	ret =
	    devm_request_irq(&pdev->dev, pdata->irq, mxc_rtc_interrupt, 0,
			     pdev->name, &pdev->dev);
	if (ret < 0) {
		dev_err(&pdev->dev, "interrupt not available.\n");
		clk_unprepare(pdata->clk);
		return ret;
	}

	ret = devm_rtc_register_device(pdata->rtc);
	if (ret < 0)
		clk_unprepare(pdata->clk);

	return ret;
}