static int jz4740_rtc_probe()

in rtc-jz4740.c [309:399]


static int jz4740_rtc_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct device_node *np = dev->of_node;
	struct jz4740_rtc *rtc;
	unsigned long rate;
	struct clk *clk;
	int ret, irq;

	rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL);
	if (!rtc)
		return -ENOMEM;

	rtc->type = (enum jz4740_rtc_type)device_get_match_data(dev);

	irq = platform_get_irq(pdev, 0);
	if (irq < 0)
		return irq;

	rtc->base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(rtc->base))
		return PTR_ERR(rtc->base);

	clk = devm_clk_get(dev, "rtc");
	if (IS_ERR(clk)) {
		dev_err(dev, "Failed to get RTC clock\n");
		return PTR_ERR(clk);
	}

	ret = clk_prepare_enable(clk);
	if (ret) {
		dev_err(dev, "Failed to enable clock\n");
		return ret;
	}

	ret = devm_add_action_or_reset(dev, jz4740_rtc_clk_disable, clk);
	if (ret) {
		dev_err(dev, "Failed to register devm action\n");
		return ret;
	}

	spin_lock_init(&rtc->lock);

	platform_set_drvdata(pdev, rtc);

	device_init_wakeup(dev, 1);

	ret = dev_pm_set_wake_irq(dev, irq);
	if (ret) {
		dev_err(dev, "Failed to set wake irq: %d\n", ret);
		return ret;
	}

	rtc->rtc = devm_rtc_allocate_device(dev);
	if (IS_ERR(rtc->rtc)) {
		ret = PTR_ERR(rtc->rtc);
		dev_err(dev, "Failed to allocate rtc device: %d\n", ret);
		return ret;
	}

	rtc->rtc->ops = &jz4740_rtc_ops;
	rtc->rtc->range_max = U32_MAX;

	rate = clk_get_rate(clk);
	jz4740_rtc_set_wakeup_params(rtc, np, rate);

	/* Each 1 Hz pulse should happen after (rate) ticks */
	jz4740_rtc_reg_write(rtc, JZ_REG_RTC_REGULATOR, rate - 1);

	ret = devm_rtc_register_device(rtc->rtc);
	if (ret)
		return ret;

	ret = devm_request_irq(dev, irq, jz4740_rtc_irq, 0,
			       pdev->name, rtc);
	if (ret) {
		dev_err(dev, "Failed to request rtc irq: %d\n", ret);
		return ret;
	}

	if (of_device_is_system_power_controller(np)) {
		dev_for_power_off = dev;

		if (!pm_power_off)
			pm_power_off = jz4740_rtc_power_off;
		else
			dev_warn(dev, "Poweroff handler already present!\n");
	}

	return 0;
}