static int qcom_smem_probe()

in qcom/smem.c [892:994]


static int qcom_smem_probe(struct platform_device *pdev)
{
	struct smem_header *header;
	struct reserved_mem *rmem;
	struct qcom_smem *smem;
	size_t array_size;
	int num_regions;
	int hwlock_id;
	u32 version;
	int ret;
	int i;

	num_regions = 1;
	if (of_find_property(pdev->dev.of_node, "qcom,rpm-msg-ram", NULL))
		num_regions++;

	array_size = num_regions * sizeof(struct smem_region);
	smem = devm_kzalloc(&pdev->dev, sizeof(*smem) + array_size, GFP_KERNEL);
	if (!smem)
		return -ENOMEM;

	smem->dev = &pdev->dev;
	smem->num_regions = num_regions;

	rmem = of_reserved_mem_lookup(pdev->dev.of_node);
	if (rmem) {
		smem->regions[0].aux_base = rmem->base;
		smem->regions[0].size = rmem->size;
	} else {
		/*
		 * Fall back to the memory-region reference, if we're not a
		 * reserved-memory node.
		 */
		ret = qcom_smem_resolve_mem(smem, "memory-region", &smem->regions[0]);
		if (ret)
			return ret;
	}

	if (num_regions > 1) {
		ret = qcom_smem_resolve_mem(smem, "qcom,rpm-msg-ram", &smem->regions[1]);
		if (ret)
			return ret;
	}

	for (i = 0; i < num_regions; i++) {
		smem->regions[i].virt_base = devm_ioremap_wc(&pdev->dev,
							     smem->regions[i].aux_base,
							     smem->regions[i].size);
		if (!smem->regions[i].virt_base) {
			dev_err(&pdev->dev, "failed to remap %pa\n", &smem->regions[i].aux_base);
			return -ENOMEM;
		}
	}

	header = smem->regions[0].virt_base;
	if (le32_to_cpu(header->initialized) != 1 ||
	    le32_to_cpu(header->reserved)) {
		dev_err(&pdev->dev, "SMEM is not initialized by SBL\n");
		return -EINVAL;
	}

	version = qcom_smem_get_sbl_version(smem);
	switch (version >> 16) {
	case SMEM_GLOBAL_PART_VERSION:
		ret = qcom_smem_set_global_partition(smem);
		if (ret < 0)
			return ret;
		smem->item_count = qcom_smem_get_item_count(smem);
		break;
	case SMEM_GLOBAL_HEAP_VERSION:
		smem->item_count = SMEM_ITEM_COUNT;
		break;
	default:
		dev_err(&pdev->dev, "Unsupported SMEM version 0x%x\n", version);
		return -EINVAL;
	}

	BUILD_BUG_ON(SMEM_HOST_APPS >= SMEM_HOST_COUNT);
	ret = qcom_smem_enumerate_partitions(smem, SMEM_HOST_APPS);
	if (ret < 0 && ret != -ENOENT)
		return ret;

	hwlock_id = of_hwspin_lock_get_id(pdev->dev.of_node, 0);
	if (hwlock_id < 0) {
		if (hwlock_id != -EPROBE_DEFER)
			dev_err(&pdev->dev, "failed to retrieve hwlock\n");
		return hwlock_id;
	}

	smem->hwlock = hwspin_lock_request_specific(hwlock_id);
	if (!smem->hwlock)
		return -ENXIO;

	__smem = smem;

	smem->socinfo = platform_device_register_data(&pdev->dev, "qcom-socinfo",
						      PLATFORM_DEVID_NONE, NULL,
						      0);
	if (IS_ERR(smem->socinfo))
		dev_dbg(&pdev->dev, "failed to register socinfo device\n");

	return 0;
}