static int q6v5_probe()

in qcom_q6v5_mss.c [1846:2006]


static int q6v5_probe(struct platform_device *pdev)
{
	const struct rproc_hexagon_res *desc;
	struct q6v5 *qproc;
	struct rproc *rproc;
	const char *mba_image;
	int ret;

	desc = of_device_get_match_data(&pdev->dev);
	if (!desc)
		return -EINVAL;

	if (desc->need_mem_protection && !qcom_scm_is_available())
		return -EPROBE_DEFER;

	mba_image = desc->hexagon_mba_image;
	ret = of_property_read_string_index(pdev->dev.of_node, "firmware-name",
					    0, &mba_image);
	if (ret < 0 && ret != -EINVAL) {
		dev_err(&pdev->dev, "unable to read mba firmware-name\n");
		return ret;
	}

	rproc = rproc_alloc(&pdev->dev, pdev->name, &q6v5_ops,
			    mba_image, sizeof(*qproc));
	if (!rproc) {
		dev_err(&pdev->dev, "failed to allocate rproc\n");
		return -ENOMEM;
	}

	rproc->auto_boot = false;
	rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);

	qproc = (struct q6v5 *)rproc->priv;
	qproc->dev = &pdev->dev;
	qproc->rproc = rproc;
	qproc->hexagon_mdt_image = "modem.mdt";
	ret = of_property_read_string_index(pdev->dev.of_node, "firmware-name",
					    1, &qproc->hexagon_mdt_image);
	if (ret < 0 && ret != -EINVAL) {
		dev_err(&pdev->dev, "unable to read mpss firmware-name\n");
		goto free_rproc;
	}

	platform_set_drvdata(pdev, qproc);

	qproc->has_qaccept_regs = desc->has_qaccept_regs;
	qproc->has_ext_cntl_regs = desc->has_ext_cntl_regs;
	qproc->has_vq6 = desc->has_vq6;
	qproc->has_spare_reg = desc->has_spare_reg;
	ret = q6v5_init_mem(qproc, pdev);
	if (ret)
		goto free_rproc;

	ret = q6v5_alloc_memory_region(qproc);
	if (ret)
		goto free_rproc;

	ret = q6v5_init_clocks(&pdev->dev, qproc->proxy_clks,
			       desc->proxy_clk_names);
	if (ret < 0) {
		dev_err(&pdev->dev, "Failed to get proxy clocks.\n");
		goto free_rproc;
	}
	qproc->proxy_clk_count = ret;

	ret = q6v5_init_clocks(&pdev->dev, qproc->reset_clks,
			       desc->reset_clk_names);
	if (ret < 0) {
		dev_err(&pdev->dev, "Failed to get reset clocks.\n");
		goto free_rproc;
	}
	qproc->reset_clk_count = ret;

	ret = q6v5_init_clocks(&pdev->dev, qproc->active_clks,
			       desc->active_clk_names);
	if (ret < 0) {
		dev_err(&pdev->dev, "Failed to get active clocks.\n");
		goto free_rproc;
	}
	qproc->active_clk_count = ret;

	ret = q6v5_regulator_init(&pdev->dev, qproc->proxy_regs,
				  desc->proxy_supply);
	if (ret < 0) {
		dev_err(&pdev->dev, "Failed to get proxy regulators.\n");
		goto free_rproc;
	}
	qproc->proxy_reg_count = ret;

	ret = q6v5_regulator_init(&pdev->dev,  qproc->active_regs,
				  desc->active_supply);
	if (ret < 0) {
		dev_err(&pdev->dev, "Failed to get active regulators.\n");
		goto free_rproc;
	}
	qproc->active_reg_count = ret;

	ret = q6v5_pds_attach(&pdev->dev, qproc->proxy_pds,
			      desc->proxy_pd_names);
	/* Fallback to regulators for old device trees */
	if (ret == -ENODATA && desc->fallback_proxy_supply) {
		ret = q6v5_regulator_init(&pdev->dev,
					  qproc->fallback_proxy_regs,
					  desc->fallback_proxy_supply);
		if (ret < 0) {
			dev_err(&pdev->dev, "Failed to get fallback proxy regulators.\n");
			goto free_rproc;
		}
		qproc->fallback_proxy_reg_count = ret;
	} else if (ret < 0) {
		dev_err(&pdev->dev, "Failed to init power domains\n");
		goto free_rproc;
	} else {
		qproc->proxy_pd_count = ret;
	}

	qproc->has_alt_reset = desc->has_alt_reset;
	ret = q6v5_init_reset(qproc);
	if (ret)
		goto detach_proxy_pds;

	qproc->version = desc->version;
	qproc->need_mem_protection = desc->need_mem_protection;
	qproc->has_mba_logs = desc->has_mba_logs;

	ret = qcom_q6v5_init(&qproc->q6v5, pdev, rproc, MPSS_CRASH_REASON_SMEM, "modem",
			     qcom_msa_handover);
	if (ret)
		goto detach_proxy_pds;

	qproc->mpss_perm = BIT(QCOM_SCM_VMID_HLOS);
	qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
	qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss");
	qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
	qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
	qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
	if (IS_ERR(qproc->sysmon)) {
		ret = PTR_ERR(qproc->sysmon);
		goto remove_subdevs;
	}

	ret = rproc_add(rproc);
	if (ret)
		goto remove_sysmon_subdev;

	return 0;

remove_sysmon_subdev:
	qcom_remove_sysmon_subdev(qproc->sysmon);
remove_subdevs:
	qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
	qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
	qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
detach_proxy_pds:
	q6v5_pds_detach(qproc, qproc->proxy_pds, qproc->proxy_pd_count);
free_rproc:
	rproc_free(rproc);

	return ret;
}