static int hidma_mgmt_probe()

in qcom/hidma_mgmt.c [162:319]


static int hidma_mgmt_probe(struct platform_device *pdev)
{
	struct hidma_mgmt_dev *mgmtdev;
	struct resource *res;
	void __iomem *virtaddr;
	int irq;
	int rc;
	u32 val;

	pm_runtime_set_autosuspend_delay(&pdev->dev, HIDMA_AUTOSUSPEND_TIMEOUT);
	pm_runtime_use_autosuspend(&pdev->dev);
	pm_runtime_set_active(&pdev->dev);
	pm_runtime_enable(&pdev->dev);
	pm_runtime_get_sync(&pdev->dev);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	virtaddr = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(virtaddr)) {
		rc = -ENOMEM;
		goto out;
	}

	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		rc = irq;
		goto out;
	}

	mgmtdev = devm_kzalloc(&pdev->dev, sizeof(*mgmtdev), GFP_KERNEL);
	if (!mgmtdev) {
		rc = -ENOMEM;
		goto out;
	}

	mgmtdev->pdev = pdev;
	mgmtdev->addrsize = resource_size(res);
	mgmtdev->virtaddr = virtaddr;

	rc = device_property_read_u32(&pdev->dev, "dma-channels",
				      &mgmtdev->dma_channels);
	if (rc) {
		dev_err(&pdev->dev, "number of channels missing\n");
		goto out;
	}

	rc = device_property_read_u32(&pdev->dev,
				      "channel-reset-timeout-cycles",
				      &mgmtdev->chreset_timeout_cycles);
	if (rc) {
		dev_err(&pdev->dev, "channel reset timeout missing\n");
		goto out;
	}

	rc = device_property_read_u32(&pdev->dev, "max-write-burst-bytes",
				      &mgmtdev->max_write_request);
	if (rc) {
		dev_err(&pdev->dev, "max-write-burst-bytes missing\n");
		goto out;
	}

	if (max_write_request &&
			(max_write_request != mgmtdev->max_write_request)) {
		dev_info(&pdev->dev, "overriding max-write-burst-bytes: %d\n",
			max_write_request);
		mgmtdev->max_write_request = max_write_request;
	} else
		max_write_request = mgmtdev->max_write_request;

	rc = device_property_read_u32(&pdev->dev, "max-read-burst-bytes",
				      &mgmtdev->max_read_request);
	if (rc) {
		dev_err(&pdev->dev, "max-read-burst-bytes missing\n");
		goto out;
	}
	if (max_read_request &&
			(max_read_request != mgmtdev->max_read_request)) {
		dev_info(&pdev->dev, "overriding max-read-burst-bytes: %d\n",
			max_read_request);
		mgmtdev->max_read_request = max_read_request;
	} else
		max_read_request = mgmtdev->max_read_request;

	rc = device_property_read_u32(&pdev->dev, "max-write-transactions",
				      &mgmtdev->max_wr_xactions);
	if (rc) {
		dev_err(&pdev->dev, "max-write-transactions missing\n");
		goto out;
	}
	if (max_wr_xactions &&
			(max_wr_xactions != mgmtdev->max_wr_xactions)) {
		dev_info(&pdev->dev, "overriding max-write-transactions: %d\n",
			max_wr_xactions);
		mgmtdev->max_wr_xactions = max_wr_xactions;
	} else
		max_wr_xactions = mgmtdev->max_wr_xactions;

	rc = device_property_read_u32(&pdev->dev, "max-read-transactions",
				      &mgmtdev->max_rd_xactions);
	if (rc) {
		dev_err(&pdev->dev, "max-read-transactions missing\n");
		goto out;
	}
	if (max_rd_xactions &&
			(max_rd_xactions != mgmtdev->max_rd_xactions)) {
		dev_info(&pdev->dev, "overriding max-read-transactions: %d\n",
			max_rd_xactions);
		mgmtdev->max_rd_xactions = max_rd_xactions;
	} else
		max_rd_xactions = mgmtdev->max_rd_xactions;

	mgmtdev->priority = devm_kcalloc(&pdev->dev,
					 mgmtdev->dma_channels,
					 sizeof(*mgmtdev->priority),
					 GFP_KERNEL);
	if (!mgmtdev->priority) {
		rc = -ENOMEM;
		goto out;
	}

	mgmtdev->weight = devm_kcalloc(&pdev->dev,
				       mgmtdev->dma_channels,
				       sizeof(*mgmtdev->weight), GFP_KERNEL);
	if (!mgmtdev->weight) {
		rc = -ENOMEM;
		goto out;
	}

	rc = hidma_mgmt_setup(mgmtdev);
	if (rc) {
		dev_err(&pdev->dev, "setup failed\n");
		goto out;
	}

	/* start the HW */
	val = readl(mgmtdev->virtaddr + HIDMA_CFG_OFFSET);
	val |= 1;
	writel(val, mgmtdev->virtaddr + HIDMA_CFG_OFFSET);

	rc = hidma_mgmt_init_sys(mgmtdev);
	if (rc) {
		dev_err(&pdev->dev, "sysfs setup failed\n");
		goto out;
	}

	dev_info(&pdev->dev,
		 "HW rev: %d.%d @ %pa with %d physical channels\n",
		 mgmtdev->hw_version_major, mgmtdev->hw_version_minor,
		 &res->start, mgmtdev->dma_channels);

	platform_set_drvdata(pdev, mgmtdev);
	pm_runtime_mark_last_busy(&pdev->dev);
	pm_runtime_put_autosuspend(&pdev->dev);
	return 0;
out:
	pm_runtime_put_sync_suspend(&pdev->dev);
	pm_runtime_disable(&pdev->dev);
	return rc;
}