static int tegra_pmc_probe()

in tegra/pmc.c [2812:2964]


static int tegra_pmc_probe(struct platform_device *pdev)
{
	void __iomem *base;
	struct resource *res;
	int err;

	/*
	 * Early initialisation should have configured an initial
	 * register mapping and setup the soc data pointer. If these
	 * are not valid then something went badly wrong!
	 */
	if (WARN_ON(!pmc->base || !pmc->soc))
		return -ENODEV;

	err = tegra_pmc_parse_dt(pmc, pdev->dev.of_node);
	if (err < 0)
		return err;

	err = devm_add_action_or_reset(&pdev->dev, tegra_pmc_reset_suspend_mode,
				       NULL);
	if (err)
		return err;

	/* take over the memory region from the early initialization */
	base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(base))
		return PTR_ERR(base);

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wake");
	if (res) {
		pmc->wake = devm_ioremap_resource(&pdev->dev, res);
		if (IS_ERR(pmc->wake))
			return PTR_ERR(pmc->wake);
	} else {
		pmc->wake = base;
	}

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aotag");
	if (res) {
		pmc->aotag = devm_ioremap_resource(&pdev->dev, res);
		if (IS_ERR(pmc->aotag))
			return PTR_ERR(pmc->aotag);
	} else {
		pmc->aotag = base;
	}

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "scratch");
	if (res) {
		pmc->scratch = devm_ioremap_resource(&pdev->dev, res);
		if (IS_ERR(pmc->scratch))
			return PTR_ERR(pmc->scratch);
	} else {
		pmc->scratch = base;
	}

	pmc->clk = devm_clk_get(&pdev->dev, "pclk");
	if (IS_ERR(pmc->clk)) {
		err = PTR_ERR(pmc->clk);

		if (err != -ENOENT) {
			dev_err(&pdev->dev, "failed to get pclk: %d\n", err);
			return err;
		}

		pmc->clk = NULL;
	}

	/*
	 * PCLK clock rate can't be retrieved using CLK API because it
	 * causes lockup if CPU enters LP2 idle state from some other
	 * CLK notifier, hence we're caching the rate's value locally.
	 */
	if (pmc->clk) {
		pmc->clk_nb.notifier_call = tegra_pmc_clk_notify_cb;
		err = clk_notifier_register(pmc->clk, &pmc->clk_nb);
		if (err) {
			dev_err(&pdev->dev,
				"failed to register clk notifier\n");
			return err;
		}

		pmc->rate = clk_get_rate(pmc->clk);
	}

	pmc->dev = &pdev->dev;

	tegra_pmc_init(pmc);

	tegra_pmc_init_tsense_reset(pmc);

	tegra_pmc_reset_sysfs_init(pmc);

	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
		err = tegra_powergate_debugfs_init();
		if (err < 0)
			goto cleanup_sysfs;
	}

	err = devm_register_reboot_notifier(&pdev->dev,
					    &tegra_pmc_reboot_notifier);
	if (err) {
		dev_err(&pdev->dev, "unable to register reboot notifier, %d\n",
			err);
		goto cleanup_debugfs;
	}

	err = register_restart_handler(&tegra_pmc_restart_handler);
	if (err) {
		dev_err(&pdev->dev, "unable to register restart handler, %d\n",
			err);
		goto cleanup_debugfs;
	}

	err = tegra_pmc_pinctrl_init(pmc);
	if (err)
		goto cleanup_restart_handler;

	err = tegra_pmc_regmap_init(pmc);
	if (err < 0)
		goto cleanup_restart_handler;

	err = tegra_powergate_init(pmc, pdev->dev.of_node);
	if (err < 0)
		goto cleanup_powergates;

	err = tegra_pmc_irq_init(pmc);
	if (err < 0)
		goto cleanup_powergates;

	mutex_lock(&pmc->powergates_lock);
	iounmap(pmc->base);
	pmc->base = base;
	mutex_unlock(&pmc->powergates_lock);

	tegra_pmc_clock_register(pmc, pdev->dev.of_node);
	platform_set_drvdata(pdev, pmc);
	tegra_pm_init_suspend();

	return 0;

cleanup_powergates:
	tegra_powergate_remove_all(pdev->dev.of_node);
cleanup_restart_handler:
	unregister_restart_handler(&tegra_pmc_restart_handler);
cleanup_debugfs:
	debugfs_remove(pmc->debugfs);
cleanup_sysfs:
	device_remove_file(&pdev->dev, &dev_attr_reset_reason);
	device_remove_file(&pdev->dev, &dev_attr_reset_level);
	clk_notifier_unregister(pmc->clk, &pmc->clk_nb);

	return err;
}