static int __init ks_pcie_probe()

in controller/dwc/pci-keystone.c [1104:1304]


static int __init ks_pcie_probe(struct platform_device *pdev)
{
	const struct dw_pcie_host_ops *host_ops;
	const struct dw_pcie_ep_ops *ep_ops;
	struct device *dev = &pdev->dev;
	struct device_node *np = dev->of_node;
	const struct ks_pcie_of_data *data;
	enum dw_pcie_device_mode mode;
	struct dw_pcie *pci;
	struct keystone_pcie *ks_pcie;
	struct device_link **link;
	struct gpio_desc *gpiod;
	struct resource *res;
	unsigned int version;
	void __iomem *base;
	u32 num_viewport;
	struct phy **phy;
	u32 num_lanes;
	char name[10];
	int ret;
	int irq;
	int i;

	data = of_device_get_match_data(dev);
	if (!data)
		return -EINVAL;

	version = data->version;
	host_ops = data->host_ops;
	ep_ops = data->ep_ops;
	mode = data->mode;

	ks_pcie = devm_kzalloc(dev, sizeof(*ks_pcie), GFP_KERNEL);
	if (!ks_pcie)
		return -ENOMEM;

	pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
	if (!pci)
		return -ENOMEM;

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "app");
	ks_pcie->va_app_base = devm_ioremap_resource(dev, res);
	if (IS_ERR(ks_pcie->va_app_base))
		return PTR_ERR(ks_pcie->va_app_base);

	ks_pcie->app = *res;

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbics");
	base = devm_pci_remap_cfg_resource(dev, res);
	if (IS_ERR(base))
		return PTR_ERR(base);

	if (of_device_is_compatible(np, "ti,am654-pcie-rc"))
		ks_pcie->is_am6 = true;

	pci->dbi_base = base;
	pci->dbi_base2 = base;
	pci->dev = dev;
	pci->ops = &ks_pcie_dw_pcie_ops;
	pci->version = version;

	irq = platform_get_irq(pdev, 0);
	if (irq < 0)
		return irq;

	ret = request_irq(irq, ks_pcie_err_irq_handler, IRQF_SHARED,
			  "ks-pcie-error-irq", ks_pcie);
	if (ret < 0) {
		dev_err(dev, "failed to request error IRQ %d\n",
			irq);
		return ret;
	}

	ret = of_property_read_u32(np, "num-lanes", &num_lanes);
	if (ret)
		num_lanes = 1;

	phy = devm_kzalloc(dev, sizeof(*phy) * num_lanes, GFP_KERNEL);
	if (!phy)
		return -ENOMEM;

	link = devm_kzalloc(dev, sizeof(*link) * num_lanes, GFP_KERNEL);
	if (!link)
		return -ENOMEM;

	for (i = 0; i < num_lanes; i++) {
		snprintf(name, sizeof(name), "pcie-phy%d", i);
		phy[i] = devm_phy_optional_get(dev, name);
		if (IS_ERR(phy[i])) {
			ret = PTR_ERR(phy[i]);
			goto err_link;
		}

		if (!phy[i])
			continue;

		link[i] = device_link_add(dev, &phy[i]->dev, DL_FLAG_STATELESS);
		if (!link[i]) {
			ret = -EINVAL;
			goto err_link;
		}
	}

	ks_pcie->np = np;
	ks_pcie->pci = pci;
	ks_pcie->link = link;
	ks_pcie->num_lanes = num_lanes;
	ks_pcie->phy = phy;

	gpiod = devm_gpiod_get_optional(dev, "reset",
					GPIOD_OUT_LOW);
	if (IS_ERR(gpiod)) {
		ret = PTR_ERR(gpiod);
		if (ret != -EPROBE_DEFER)
			dev_err(dev, "Failed to get reset GPIO\n");
		goto err_link;
	}

	ret = ks_pcie_enable_phy(ks_pcie);
	if (ret) {
		dev_err(dev, "failed to enable phy\n");
		goto err_link;
	}

	platform_set_drvdata(pdev, ks_pcie);
	pm_runtime_enable(dev);
	ret = pm_runtime_get_sync(dev);
	if (ret < 0) {
		dev_err(dev, "pm_runtime_get_sync failed\n");
		goto err_get_sync;
	}

	if (pci->version >= 0x480A)
		ret = ks_pcie_am654_set_mode(dev, mode);
	else
		ret = ks_pcie_set_mode(dev);
	if (ret < 0)
		goto err_get_sync;

	switch (mode) {
	case DW_PCIE_RC_TYPE:
		if (!IS_ENABLED(CONFIG_PCI_KEYSTONE_HOST)) {
			ret = -ENODEV;
			goto err_get_sync;
		}

		ret = of_property_read_u32(np, "num-viewport", &num_viewport);
		if (ret < 0) {
			dev_err(dev, "unable to read *num-viewport* property\n");
			goto err_get_sync;
		}

		/*
		 * "Power Sequencing and Reset Signal Timings" table in
		 * PCI EXPRESS CARD ELECTROMECHANICAL SPECIFICATION, REV. 2.0
		 * indicates PERST# should be deasserted after minimum of 100us
		 * once REFCLK is stable. The REFCLK to the connector in RC
		 * mode is selected while enabling the PHY. So deassert PERST#
		 * after 100 us.
		 */
		if (gpiod) {
			usleep_range(100, 200);
			gpiod_set_value_cansleep(gpiod, 1);
		}

		ks_pcie->num_viewport = num_viewport;
		pci->pp.ops = host_ops;
		ret = dw_pcie_host_init(&pci->pp);
		if (ret < 0)
			goto err_get_sync;
		break;
	case DW_PCIE_EP_TYPE:
		if (!IS_ENABLED(CONFIG_PCI_KEYSTONE_EP)) {
			ret = -ENODEV;
			goto err_get_sync;
		}

		pci->ep.ops = ep_ops;
		ret = dw_pcie_ep_init(&pci->ep);
		if (ret < 0)
			goto err_get_sync;
		break;
	default:
		dev_err(dev, "INVALID device type %d\n", mode);
	}

	ks_pcie_enable_error_irq(ks_pcie);

	return 0;

err_get_sync:
	pm_runtime_put(dev);
	pm_runtime_disable(dev);
	ks_pcie_disable_phy(ks_pcie);

err_link:
	while (--i >= 0 && link[i])
		device_link_del(link[i]);

	return ret;
}