Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5a3aa2a8 authored by Joao Pinto's avatar Joao Pinto Committed by Bjorn Helgaas
Browse files

PCI: designware: Add driver for prototyping kits based on ARC SDP



Add a reference platform driver for PCI RC IP Protoyping Kits based on the
ARC SDP.

[bhelgaas: changelog, split patch up, MAINTAINERS update]
Signed-off-by: default avatarJoao Pinto <jpinto@synopsys.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Acked-by: default avatarPratyush Anand <pratyush.anand@gmail.com>
parent dac29e6c
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -28,3 +28,20 @@ Optional properties:
- clock-names: Must include the following entries:
	- "pcie"
	- "pcie_bus"

Example configuration:

	pcie: pcie@0xdffff000 {
		compatible = "snps,dw-pcie";
		reg = <0xdffff000 0x1000>, /* Controller registers */
		      <0xd0000000 0x2000>; /* PCI config space */
		reg-names = "ctrlreg", "config";
		#address-cells = <3>;
		#size-cells = <2>;
		device_type = "pci";
		ranges = <0x81000000 0 0x00000000 0xde000000 0 0x00010000
			  0x82000000 0 0xd0400000 0xd0400000 0 0x0d000000>;
		interrupts = <25>, <24>;
		#interrupt-cells = <1>;
		num-lanes = <1>;
	};
+7 −0
Original line number Diff line number Diff line
@@ -8367,6 +8367,13 @@ L: linux-pci@vger.kernel.org
S:	Maintained
F:	drivers/pci/host/*designware*

PCI DRIVER FOR SYNOPSYS PROTOTYPING DEVICE
M:	Joao Pinto <jpinto@synopsys.com>
L:	linux-pci@vger.kernel.org
S:	Maintained
F:	Documentation/devicetree/bindings/pci/designware-pcie.txt
F:	drivers/pci/host/pcie-designware-plat.c

PCI DRIVER FOR GENERIC OF HOSTS
M:	Will Deacon <will.deacon@arm.com>
L:	linux-pci@vger.kernel.org
+11 −0
Original line number Diff line number Diff line
@@ -16,6 +16,17 @@ config PCI_MVEBU
	depends on ARCH_MVEBU || ARCH_DOVE
	depends on OF

config PCIE_DW_PLAT
	bool "Platform bus based DesignWare PCIe Controller"
	select PCIE_DW
	---help---
	 This selects the DesignWare PCIe controller support. Select this if
	 you have a PCIe controller on Platform bus.

	 If you have a controller with this interface, say Y or M here.

	 If unsure, say N.

config PCIE_DW
	bool

+1 −0
Original line number Diff line number Diff line
obj-$(CONFIG_PCIE_DW) += pcie-designware.o
obj-$(CONFIG_PCIE_DW_PLAT) += pcie-designware-plat.o
obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o
obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
+138 −0
Original line number Diff line number Diff line
/*
 * PCIe RC driver for Synopsys DesignWare Core
 *
 * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
 *
 * Authors: Joao Pinto <jpinto@synopsys.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/resource.h>
#include <linux/signal.h>
#include <linux/types.h>

#include "pcie-designware.h"

struct dw_plat_pcie {
	void __iomem		*mem_base;
	struct pcie_port	pp;
};

static irqreturn_t dw_plat_pcie_msi_irq_handler(int irq, void *arg)
{
	struct pcie_port *pp = arg;

	return dw_handle_msi_irq(pp);
}

static void dw_plat_pcie_host_init(struct pcie_port *pp)
{
	dw_pcie_setup_rc(pp);
	dw_pcie_wait_for_link(pp);

	if (IS_ENABLED(CONFIG_PCI_MSI))
		dw_pcie_msi_init(pp);
}

static struct pcie_host_ops dw_plat_pcie_host_ops = {
	.host_init = dw_plat_pcie_host_init,
};

static int dw_plat_add_pcie_port(struct pcie_port *pp,
				 struct platform_device *pdev)
{
	int ret;

	pp->irq = platform_get_irq(pdev, 1);
	if (pp->irq < 0)
		return pp->irq;

	if (IS_ENABLED(CONFIG_PCI_MSI)) {
		pp->msi_irq = platform_get_irq(pdev, 0);
		if (pp->msi_irq < 0)
			return pp->msi_irq;

		ret = devm_request_irq(&pdev->dev, pp->msi_irq,
					dw_plat_pcie_msi_irq_handler,
					IRQF_SHARED, "dw-plat-pcie-msi", pp);
		if (ret) {
			dev_err(&pdev->dev, "failed to request MSI IRQ\n");
			return ret;
		}
	}

	pp->root_bus_nr = -1;
	pp->ops = &dw_plat_pcie_host_ops;

	ret = dw_pcie_host_init(pp);
	if (ret) {
		dev_err(&pdev->dev, "failed to initialize host\n");
		return ret;
	}

	return 0;
}

static int dw_plat_pcie_probe(struct platform_device *pdev)
{
	struct dw_plat_pcie *dw_plat_pcie;
	struct pcie_port *pp;
	struct resource *res;  /* Resource from DT */
	int ret;

	dw_plat_pcie = devm_kzalloc(&pdev->dev, sizeof(*dw_plat_pcie),
					GFP_KERNEL);
	if (!dw_plat_pcie)
		return -ENOMEM;

	pp = &dw_plat_pcie->pp;
	pp->dev = &pdev->dev;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
		return -ENODEV;

	dw_plat_pcie->mem_base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(dw_plat_pcie->mem_base))
		return PTR_ERR(dw_plat_pcie->mem_base);

	pp->dbi_base = dw_plat_pcie->mem_base;

	ret = dw_plat_add_pcie_port(pp, pdev);
	if (ret < 0)
		return ret;

	platform_set_drvdata(pdev, dw_plat_pcie);
	return 0;
}

static const struct of_device_id dw_plat_pcie_of_match[] = {
	{ .compatible = "snps,dw-pcie", },
	{},
};
MODULE_DEVICE_TABLE(of, dw_plat_pcie_of_match);

static struct platform_driver dw_plat_pcie_driver = {
	.driver = {
		.name	= "dw-pcie",
		.of_match_table = dw_plat_pcie_of_match,
	},
	.probe = dw_plat_pcie_probe,
};

module_platform_driver(dw_plat_pcie_driver);

MODULE_AUTHOR("Joao Pinto <Joao.Pinto@synopsys.com>");
MODULE_DESCRIPTION("Synopsys PCIe host controller glue platform driver");
MODULE_LICENSE("GPL v2");