drivers/soc/qcom/rmtfs_mem.c

Source file repositories/reference/linux-study-clean/drivers/soc/qcom/rmtfs_mem.c

File Facts

System
Linux kernel
Corpus path
drivers/soc/qcom/rmtfs_mem.c
Extension
.c
Size
9239 bytes
Lines
367
Domain
Driver Families
Bucket
drivers/soc
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct file_operations qcom_rmtfs_mem_fops = {
	.owner = THIS_MODULE,
	.open = qcom_rmtfs_mem_open,
	.read = qcom_rmtfs_mem_read,
	.write = qcom_rmtfs_mem_write,
	.release = qcom_rmtfs_mem_release,
	.llseek = default_llseek,
	.mmap = qcom_rmtfs_mem_mmap,
};

static void qcom_rmtfs_mem_release_device(struct device *dev)
{
	struct qcom_rmtfs_mem *rmtfs_mem = container_of(dev,
							struct qcom_rmtfs_mem,
							dev);

	kfree(rmtfs_mem);
}

static int qcom_rmtfs_mem_probe(struct platform_device *pdev)
{
	struct device_node *node = pdev->dev.of_node;
	struct qcom_scm_vmperm perms[NUM_MAX_VMIDS + 1];
	struct reserved_mem *rmem;
	struct qcom_rmtfs_mem *rmtfs_mem;
	u32 client_id;
	u32 vmid[NUM_MAX_VMIDS];
	int num_vmids;
	int ret, i;

	rmem = of_reserved_mem_lookup(node);
	if (!rmem) {
		dev_err(&pdev->dev, "failed to acquire memory region\n");
		return -EINVAL;
	}

	ret = of_property_read_u32(node, "qcom,client-id", &client_id);
	if (ret) {
		dev_err(&pdev->dev, "failed to parse \"qcom,client-id\"\n");
		return ret;

	}

	rmtfs_mem = kzalloc_obj(*rmtfs_mem);
	if (!rmtfs_mem)
		return -ENOMEM;

	rmtfs_mem->addr = rmem->base;
	rmtfs_mem->client_id = client_id;
	rmtfs_mem->size = rmem->size;

	/*
	 * If requested, discard the first and last 4k block in order to ensure
	 * that the rmtfs region isn't adjacent to other protected regions.
	 */
	if (of_property_read_bool(node, "qcom,use-guard-pages")) {
		rmtfs_mem->addr += SZ_4K;
		rmtfs_mem->size -= 2 * SZ_4K;
	}

	device_initialize(&rmtfs_mem->dev);
	rmtfs_mem->dev.parent = &pdev->dev;
	rmtfs_mem->dev.groups = qcom_rmtfs_mem_groups;
	rmtfs_mem->dev.release = qcom_rmtfs_mem_release_device;

	rmtfs_mem->base = devm_memremap(&rmtfs_mem->dev, rmtfs_mem->addr,
					rmtfs_mem->size, MEMREMAP_WC);
	if (IS_ERR(rmtfs_mem->base)) {
		dev_err(&pdev->dev, "failed to remap rmtfs_mem region\n");
		ret = PTR_ERR(rmtfs_mem->base);
		goto put_device;
	}

	cdev_init(&rmtfs_mem->cdev, &qcom_rmtfs_mem_fops);
	rmtfs_mem->cdev.owner = THIS_MODULE;

	dev_set_name(&rmtfs_mem->dev, "qcom_rmtfs_mem%d", client_id);
	rmtfs_mem->dev.id = client_id;
	rmtfs_mem->dev.class = &rmtfs_class;
	rmtfs_mem->dev.devt = MKDEV(MAJOR(qcom_rmtfs_mem_major), client_id);

	ret = cdev_device_add(&rmtfs_mem->cdev, &rmtfs_mem->dev);
	if (ret) {
		dev_err(&pdev->dev, "failed to add cdev: %d\n", ret);
		goto put_device;
	}

	num_vmids = of_property_count_u32_elems(node, "qcom,vmid");
	if (num_vmids == -EINVAL) {
		/* qcom,vmid is optional */

Annotation

Implementation Notes