static int qcom_ebi2_probe()

in qcom-ebi2.c [292:388]


static int qcom_ebi2_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct device_node *child;
	struct device *dev = &pdev->dev;
	struct resource *res;
	void __iomem *ebi2_base;
	void __iomem *ebi2_xmem;
	struct clk *ebi2xclk;
	struct clk *ebi2clk;
	bool have_children = false;
	u32 val;
	int ret;

	ebi2xclk = devm_clk_get(dev, "ebi2x");
	if (IS_ERR(ebi2xclk))
		return PTR_ERR(ebi2xclk);

	ret = clk_prepare_enable(ebi2xclk);
	if (ret) {
		dev_err(dev, "could not enable EBI2X clk (%d)\n", ret);
		return ret;
	}

	ebi2clk = devm_clk_get(dev, "ebi2");
	if (IS_ERR(ebi2clk)) {
		ret = PTR_ERR(ebi2clk);
		goto err_disable_2x_clk;
	}

	ret = clk_prepare_enable(ebi2clk);
	if (ret) {
		dev_err(dev, "could not enable EBI2 clk\n");
		goto err_disable_2x_clk;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	ebi2_base = devm_ioremap_resource(dev, res);
	if (IS_ERR(ebi2_base)) {
		ret = PTR_ERR(ebi2_base);
		goto err_disable_clk;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	ebi2_xmem = devm_ioremap_resource(dev, res);
	if (IS_ERR(ebi2_xmem)) {
		ret = PTR_ERR(ebi2_xmem);
		goto err_disable_clk;
	}

	/* Allegedly this turns the power save mode off */
	writel(0UL, ebi2_xmem + EBI2_XMEM_CFG);

	/* Disable all chipselects */
	val = readl(ebi2_base);
	val &= ~EBI2_CSN_MASK;
	writel(val, ebi2_base);

	/* Walk over the child nodes and see what chipselects we use */
	for_each_available_child_of_node(np, child) {
		u32 csindex;

		/* Figure out the chipselect */
		ret = of_property_read_u32(child, "reg", &csindex);
		if (ret) {
			of_node_put(child);
			return ret;
		}

		if (csindex > 5) {
			dev_err(dev,
				"invalid chipselect %u, we only support 0-5\n",
				csindex);
			continue;
		}

		qcom_ebi2_setup_chipselect(child,
					   dev,
					   ebi2_base,
					   ebi2_xmem,
					   csindex);

		/* We have at least one child */
		have_children = true;
	}

	if (have_children)
		return of_platform_default_populate(np, NULL, dev);
	return 0;

err_disable_clk:
	clk_disable_unprepare(ebi2clk);
err_disable_2x_clk:
	clk_disable_unprepare(ebi2xclk);

	return ret;
}