static int mxc_rtc_probe()

in rtc-mxc.c [302:413]


static int mxc_rtc_probe(struct platform_device *pdev)
{
	struct rtc_device *rtc;
	struct rtc_plat_data *pdata = NULL;
	u32 reg;
	unsigned long rate;
	int ret;

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

	pdata->devtype = (enum imx_rtc_type)of_device_get_match_data(&pdev->dev);

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

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

	pdata->rtc = rtc;
	rtc->ops = &mxc_rtc_ops;
	if (is_imx1_rtc(pdata)) {
		struct rtc_time tm;

		/* 9bit days + hours minutes seconds */
		rtc->range_max = (1 << 9) * 86400 - 1;

		/*
		 * Set the start date as beginning of the current year. This can
		 * be overridden using device tree.
		 */
		rtc_time64_to_tm(ktime_get_real_seconds(), &tm);
		rtc->start_secs =  mktime64(tm.tm_year, 1, 1, 0, 0, 0);
		rtc->set_start_time = true;
	} else {
		/* 16bit days + hours minutes seconds */
		rtc->range_max = (1 << 16) * 86400ULL - 1;
	}

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

	ret = clk_prepare_enable(pdata->clk_ipg);
	if (ret)
		return ret;

	pdata->clk_ref = devm_clk_get(&pdev->dev, "ref");
	if (IS_ERR(pdata->clk_ref)) {
		clk_disable_unprepare(pdata->clk_ipg);
		dev_err(&pdev->dev, "unable to get ref clock!\n");
		return PTR_ERR(pdata->clk_ref);
	}

	ret = clk_prepare_enable(pdata->clk_ref);
	if (ret) {
		clk_disable_unprepare(pdata->clk_ipg);
		return ret;
	}

	ret = devm_add_action_or_reset(&pdev->dev, mxc_rtc_action, pdata);
	if (ret)
		return ret;

	rate = clk_get_rate(pdata->clk_ref);

	if (rate == 32768)
		reg = RTC_INPUT_CLK_32768HZ;
	else if (rate == 32000)
		reg = RTC_INPUT_CLK_32000HZ;
	else if (rate == 38400)
		reg = RTC_INPUT_CLK_38400HZ;
	else {
		dev_err(&pdev->dev, "rtc clock is not valid (%lu)\n", rate);
		return -EINVAL;
	}

	reg |= RTC_ENABLE_BIT;
	writew(reg, (pdata->ioaddr + RTC_RTCCTL));
	if (((readw(pdata->ioaddr + RTC_RTCCTL)) & RTC_ENABLE_BIT) == 0) {
		dev_err(&pdev->dev, "hardware module can't be enabled!\n");
		return -EIO;
	}

	platform_set_drvdata(pdev, pdata);

	/* Configure and enable the RTC */
	pdata->irq = platform_get_irq(pdev, 0);

	if (pdata->irq >= 0 &&
	    devm_request_irq(&pdev->dev, pdata->irq, mxc_rtc_interrupt,
			     IRQF_SHARED, pdev->name, pdev) < 0) {
		dev_warn(&pdev->dev, "interrupt not available.\n");
		pdata->irq = -1;
	}

	if (pdata->irq >= 0) {
		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 = devm_rtc_register_device(rtc);

	return ret;
}