static int sysc_probe()

in ti-sysc.c [3251:3377]


static int sysc_probe(struct platform_device *pdev)
{
	struct ti_sysc_platform_data *pdata = dev_get_platdata(&pdev->dev);
	struct sysc *ddata;
	int error;

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

	ddata->offsets[SYSC_REVISION] = -ENODEV;
	ddata->offsets[SYSC_SYSCONFIG] = -ENODEV;
	ddata->offsets[SYSC_SYSSTATUS] = -ENODEV;
	ddata->dev = &pdev->dev;
	platform_set_drvdata(pdev, ddata);

	error = sysc_init_static_data(ddata);
	if (error)
		return error;

	error = sysc_init_match(ddata);
	if (error)
		return error;

	error = sysc_init_dts_quirks(ddata);
	if (error)
		return error;

	error = sysc_map_and_check_registers(ddata);
	if (error)
		return error;

	error = sysc_init_sysc_mask(ddata);
	if (error)
		return error;

	error = sysc_init_idlemodes(ddata);
	if (error)
		return error;

	error = sysc_init_syss_mask(ddata);
	if (error)
		return error;

	error = sysc_init_pdata(ddata);
	if (error)
		return error;

	sysc_init_early_quirks(ddata);

	error = sysc_check_disabled_devices(ddata);
	if (error)
		return error;

	error = sysc_check_active_timer(ddata);
	if (error == -ENXIO)
		ddata->reserved = true;
	else if (error)
		return error;

	error = sysc_get_clocks(ddata);
	if (error)
		return error;

	error = sysc_init_resets(ddata);
	if (error)
		goto unprepare;

	error = sysc_init_module(ddata);
	if (error)
		goto unprepare;

	pm_runtime_enable(ddata->dev);
	error = pm_runtime_resume_and_get(ddata->dev);
	if (error < 0) {
		pm_runtime_disable(ddata->dev);
		goto unprepare;
	}

	/* Balance use counts as PM runtime should have enabled these all */
	if (!(ddata->cfg.quirks &
	      (SYSC_QUIRK_NO_IDLE | SYSC_QUIRK_NO_IDLE_ON_INIT))) {
		sysc_disable_main_clocks(ddata);
		sysc_disable_opt_clocks(ddata);
		sysc_clkdm_allow_idle(ddata);
	}

	if (!(ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT))
		reset_control_assert(ddata->rsts);

	sysc_show_registers(ddata);

	ddata->dev->type = &sysc_device_type;

	if (!ddata->reserved) {
		error = of_platform_populate(ddata->dev->of_node,
					     sysc_match_table,
					     pdata ? pdata->auxdata : NULL,
					     ddata->dev);
		if (error)
			goto err;
	}

	INIT_DELAYED_WORK(&ddata->idle_work, ti_sysc_idle);

	/* At least earlycon won't survive without deferred idle */
	if (ddata->cfg.quirks & (SYSC_QUIRK_NO_IDLE |
				 SYSC_QUIRK_NO_IDLE_ON_INIT |
				 SYSC_QUIRK_NO_RESET_ON_INIT)) {
		schedule_delayed_work(&ddata->idle_work, 3000);
	} else {
		pm_runtime_put(&pdev->dev);
	}

	if (ddata->cfg.quirks & SYSC_QUIRK_REINIT_ON_CTX_LOST)
		sysc_add_restored(ddata);

	return 0;

err:
	pm_runtime_put_sync(&pdev->dev);
	pm_runtime_disable(&pdev->dev);
unprepare:
	sysc_unprepare(ddata);

	return error;
}