diff options
Diffstat (limited to 'drivers/pci/controller/dwc/pci-exynos.c')
| -rw-r--r-- | drivers/pci/controller/dwc/pci-exynos.c | 389 | 
1 files changed, 148 insertions, 241 deletions
diff --git a/drivers/pci/controller/dwc/pci-exynos.c b/drivers/pci/controller/dwc/pci-exynos.c index 242683cde04a..c24dab383654 100644 --- a/drivers/pci/controller/dwc/pci-exynos.c +++ b/drivers/pci/controller/dwc/pci-exynos.c @@ -2,26 +2,23 @@  /*   * PCIe host controller driver for Samsung Exynos SoCs   * - * Copyright (C) 2013 Samsung Electronics Co., Ltd. + * Copyright (C) 2013-2020 Samsung Electronics Co., Ltd.   *		https://www.samsung.com   *   * Author: Jingoo Han <[email protected]> + *	   Jaehoon Chung <[email protected]>   */  #include <linux/clk.h>  #include <linux/delay.h> -#include <linux/gpio.h>  #include <linux/interrupt.h>  #include <linux/kernel.h>  #include <linux/init.h>  #include <linux/of_device.h> -#include <linux/of_gpio.h>  #include <linux/pci.h>  #include <linux/platform_device.h>  #include <linux/phy/phy.h> -#include <linux/resource.h> -#include <linux/signal.h> -#include <linux/types.h> +#include <linux/regulator/consumer.h>  #include "pcie-designware.h" @@ -37,102 +34,43 @@  #define PCIE_IRQ_SPECIAL		0x008  #define PCIE_IRQ_EN_PULSE		0x00c  #define PCIE_IRQ_EN_LEVEL		0x010 -#define IRQ_MSI_ENABLE			BIT(2)  #define PCIE_IRQ_EN_SPECIAL		0x014 -#define PCIE_PWR_RESET			0x018 +#define PCIE_SW_WAKE			0x018 +#define PCIE_BUS_EN			BIT(1)  #define PCIE_CORE_RESET			0x01c  #define PCIE_CORE_RESET_ENABLE		BIT(0)  #define PCIE_STICKY_RESET		0x020  #define PCIE_NONSTICKY_RESET		0x024  #define PCIE_APP_INIT_RESET		0x028  #define PCIE_APP_LTSSM_ENABLE		0x02c -#define PCIE_ELBI_RDLH_LINKUP		0x064 +#define PCIE_ELBI_RDLH_LINKUP		0x074 +#define PCIE_ELBI_XMLH_LINKUP		BIT(4)  #define PCIE_ELBI_LTSSM_ENABLE		0x1  #define PCIE_ELBI_SLV_AWMISC		0x11c  #define PCIE_ELBI_SLV_ARMISC		0x120  #define PCIE_ELBI_SLV_DBI_ENABLE	BIT(21) -struct exynos_pcie_mem_res { -	void __iomem *elbi_base;   /* DT 0th resource: PCIe CTRL */ -}; - -struct exynos_pcie_clk_res { -	struct clk *clk; -	struct clk *bus_clk; -}; -  struct exynos_pcie { -	struct dw_pcie			*pci; -	struct exynos_pcie_mem_res	*mem_res; -	struct exynos_pcie_clk_res	*clk_res; -	const struct exynos_pcie_ops	*ops; -	int				reset_gpio; - +	struct dw_pcie			pci; +	void __iomem			*elbi_base; +	struct clk			*clk; +	struct clk			*bus_clk;  	struct phy			*phy; +	struct regulator_bulk_data	supplies[2];  }; -struct exynos_pcie_ops { -	int (*get_mem_resources)(struct platform_device *pdev, -			struct exynos_pcie *ep); -	int (*get_clk_resources)(struct exynos_pcie *ep); -	int (*init_clk_resources)(struct exynos_pcie *ep); -	void (*deinit_clk_resources)(struct exynos_pcie *ep); -}; - -static int exynos5440_pcie_get_mem_resources(struct platform_device *pdev, -					     struct exynos_pcie *ep) -{ -	struct dw_pcie *pci = ep->pci; -	struct device *dev = pci->dev; - -	ep->mem_res = devm_kzalloc(dev, sizeof(*ep->mem_res), GFP_KERNEL); -	if (!ep->mem_res) -		return -ENOMEM; - -	ep->mem_res->elbi_base = devm_platform_ioremap_resource(pdev, 0); -	if (IS_ERR(ep->mem_res->elbi_base)) -		return PTR_ERR(ep->mem_res->elbi_base); - -	return 0; -} - -static int exynos5440_pcie_get_clk_resources(struct exynos_pcie *ep) +static int exynos_pcie_init_clk_resources(struct exynos_pcie *ep)  { -	struct dw_pcie *pci = ep->pci; -	struct device *dev = pci->dev; - -	ep->clk_res = devm_kzalloc(dev, sizeof(*ep->clk_res), GFP_KERNEL); -	if (!ep->clk_res) -		return -ENOMEM; - -	ep->clk_res->clk = devm_clk_get(dev, "pcie"); -	if (IS_ERR(ep->clk_res->clk)) { -		dev_err(dev, "Failed to get pcie rc clock\n"); -		return PTR_ERR(ep->clk_res->clk); -	} - -	ep->clk_res->bus_clk = devm_clk_get(dev, "pcie_bus"); -	if (IS_ERR(ep->clk_res->bus_clk)) { -		dev_err(dev, "Failed to get pcie bus clock\n"); -		return PTR_ERR(ep->clk_res->bus_clk); -	} - -	return 0; -} - -static int exynos5440_pcie_init_clk_resources(struct exynos_pcie *ep) -{ -	struct dw_pcie *pci = ep->pci; -	struct device *dev = pci->dev; +	struct device *dev = ep->pci.dev;  	int ret; -	ret = clk_prepare_enable(ep->clk_res->clk); +	ret = clk_prepare_enable(ep->clk);  	if (ret) {  		dev_err(dev, "cannot enable pcie rc clock");  		return ret;  	} -	ret = clk_prepare_enable(ep->clk_res->bus_clk); +	ret = clk_prepare_enable(ep->bus_clk);  	if (ret) {  		dev_err(dev, "cannot enable pcie bus clock");  		goto err_bus_clk; @@ -141,24 +79,17 @@ static int exynos5440_pcie_init_clk_resources(struct exynos_pcie *ep)  	return 0;  err_bus_clk: -	clk_disable_unprepare(ep->clk_res->clk); +	clk_disable_unprepare(ep->clk);  	return ret;  } -static void exynos5440_pcie_deinit_clk_resources(struct exynos_pcie *ep) +static void exynos_pcie_deinit_clk_resources(struct exynos_pcie *ep)  { -	clk_disable_unprepare(ep->clk_res->bus_clk); -	clk_disable_unprepare(ep->clk_res->clk); +	clk_disable_unprepare(ep->bus_clk); +	clk_disable_unprepare(ep->clk);  } -static const struct exynos_pcie_ops exynos5440_pcie_ops = { -	.get_mem_resources	= exynos5440_pcie_get_mem_resources, -	.get_clk_resources	= exynos5440_pcie_get_clk_resources, -	.init_clk_resources	= exynos5440_pcie_init_clk_resources, -	.deinit_clk_resources	= exynos5440_pcie_deinit_clk_resources, -}; -  static void exynos_pcie_writel(void __iomem *base, u32 val, u32 reg)  {  	writel(val, base + reg); @@ -173,115 +104,71 @@ static void exynos_pcie_sideband_dbi_w_mode(struct exynos_pcie *ep, bool on)  {  	u32 val; -	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_ELBI_SLV_AWMISC); +	val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_SLV_AWMISC);  	if (on)  		val |= PCIE_ELBI_SLV_DBI_ENABLE;  	else  		val &= ~PCIE_ELBI_SLV_DBI_ENABLE; -	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_ELBI_SLV_AWMISC); +	exynos_pcie_writel(ep->elbi_base, val, PCIE_ELBI_SLV_AWMISC);  }  static void exynos_pcie_sideband_dbi_r_mode(struct exynos_pcie *ep, bool on)  {  	u32 val; -	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_ELBI_SLV_ARMISC); +	val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_SLV_ARMISC);  	if (on)  		val |= PCIE_ELBI_SLV_DBI_ENABLE;  	else  		val &= ~PCIE_ELBI_SLV_DBI_ENABLE; -	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_ELBI_SLV_ARMISC); +	exynos_pcie_writel(ep->elbi_base, val, PCIE_ELBI_SLV_ARMISC);  }  static void exynos_pcie_assert_core_reset(struct exynos_pcie *ep)  {  	u32 val; -	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_CORE_RESET); +	val = exynos_pcie_readl(ep->elbi_base, PCIE_CORE_RESET);  	val &= ~PCIE_CORE_RESET_ENABLE; -	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_CORE_RESET); -	exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_PWR_RESET); -	exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_STICKY_RESET); -	exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_NONSTICKY_RESET); +	exynos_pcie_writel(ep->elbi_base, val, PCIE_CORE_RESET); +	exynos_pcie_writel(ep->elbi_base, 0, PCIE_STICKY_RESET); +	exynos_pcie_writel(ep->elbi_base, 0, PCIE_NONSTICKY_RESET);  }  static void exynos_pcie_deassert_core_reset(struct exynos_pcie *ep)  {  	u32 val; -	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_CORE_RESET); +	val = exynos_pcie_readl(ep->elbi_base, PCIE_CORE_RESET);  	val |= PCIE_CORE_RESET_ENABLE; -	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_CORE_RESET); -	exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_STICKY_RESET); -	exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_NONSTICKY_RESET); -	exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_APP_INIT_RESET); -	exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_APP_INIT_RESET); -} - -static void exynos_pcie_assert_reset(struct exynos_pcie *ep) -{ -	struct dw_pcie *pci = ep->pci; -	struct device *dev = pci->dev; - -	if (ep->reset_gpio >= 0) -		devm_gpio_request_one(dev, ep->reset_gpio, -				GPIOF_OUT_INIT_HIGH, "RESET"); +	exynos_pcie_writel(ep->elbi_base, val, PCIE_CORE_RESET); +	exynos_pcie_writel(ep->elbi_base, 1, PCIE_STICKY_RESET); +	exynos_pcie_writel(ep->elbi_base, 1, PCIE_NONSTICKY_RESET); +	exynos_pcie_writel(ep->elbi_base, 1, PCIE_APP_INIT_RESET); +	exynos_pcie_writel(ep->elbi_base, 0, PCIE_APP_INIT_RESET);  } -static int exynos_pcie_establish_link(struct exynos_pcie *ep) +static int exynos_pcie_start_link(struct dw_pcie *pci)  { -	struct dw_pcie *pci = ep->pci; -	struct pcie_port *pp = &pci->pp; -	struct device *dev = pci->dev; - -	if (dw_pcie_link_up(pci)) { -		dev_err(dev, "Link already up\n"); -		return 0; -	} - -	exynos_pcie_assert_core_reset(ep); - -	phy_reset(ep->phy); - -	exynos_pcie_writel(ep->mem_res->elbi_base, 1, -			PCIE_PWR_RESET); +	struct exynos_pcie *ep = to_exynos_pcie(pci); +	u32 val; -	phy_power_on(ep->phy); -	phy_init(ep->phy); - -	exynos_pcie_deassert_core_reset(ep); -	dw_pcie_setup_rc(pp); -	exynos_pcie_assert_reset(ep); +	val = exynos_pcie_readl(ep->elbi_base, PCIE_SW_WAKE); +	val &= ~PCIE_BUS_EN; +	exynos_pcie_writel(ep->elbi_base, val, PCIE_SW_WAKE);  	/* assert LTSSM enable */ -	exynos_pcie_writel(ep->mem_res->elbi_base, PCIE_ELBI_LTSSM_ENABLE, +	exynos_pcie_writel(ep->elbi_base, PCIE_ELBI_LTSSM_ENABLE,  			  PCIE_APP_LTSSM_ENABLE); - -	/* check if the link is up or not */ -	if (!dw_pcie_wait_for_link(pci)) -		return 0; - -	phy_power_off(ep->phy); -	return -ETIMEDOUT; +	return 0;  }  static void exynos_pcie_clear_irq_pulse(struct exynos_pcie *ep)  { -	u32 val; +	u32 val = exynos_pcie_readl(ep->elbi_base, PCIE_IRQ_PULSE); -	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_IRQ_PULSE); -	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_PULSE); -} - -static void exynos_pcie_enable_irq_pulse(struct exynos_pcie *ep) -{ -	u32 val; - -	/* enable INTX interrupt */ -	val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT | -		IRQ_INTC_ASSERT | IRQ_INTD_ASSERT; -	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_EN_PULSE); +	exynos_pcie_writel(ep->elbi_base, val, PCIE_IRQ_PULSE);  }  static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg) @@ -292,26 +179,14 @@ static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg)  	return IRQ_HANDLED;  } -static void exynos_pcie_msi_init(struct exynos_pcie *ep) -{ -	struct dw_pcie *pci = ep->pci; -	struct pcie_port *pp = &pci->pp; -	u32 val; - -	dw_pcie_msi_init(pp); - -	/* enable MSI interrupt */ -	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_IRQ_EN_LEVEL); -	val |= IRQ_MSI_ENABLE; -	exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_EN_LEVEL); -} - -static void exynos_pcie_enable_interrupts(struct exynos_pcie *ep) +static void exynos_pcie_enable_irq_pulse(struct exynos_pcie *ep)  { -	exynos_pcie_enable_irq_pulse(ep); +	u32 val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT | +		  IRQ_INTC_ASSERT | IRQ_INTD_ASSERT; -	if (IS_ENABLED(CONFIG_PCI_MSI)) -		exynos_pcie_msi_init(ep); +	exynos_pcie_writel(ep->elbi_base, val, PCIE_IRQ_EN_PULSE); +	exynos_pcie_writel(ep->elbi_base, 0, PCIE_IRQ_EN_LEVEL); +	exynos_pcie_writel(ep->elbi_base, 0, PCIE_IRQ_EN_SPECIAL);  }  static u32 exynos_pcie_read_dbi(struct dw_pcie *pci, void __iomem *base, @@ -370,13 +245,9 @@ static struct pci_ops exynos_pci_ops = {  static int exynos_pcie_link_up(struct dw_pcie *pci)  {  	struct exynos_pcie *ep = to_exynos_pcie(pci); -	u32 val; +	u32 val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_RDLH_LINKUP); -	val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_ELBI_RDLH_LINKUP); -	if (val == PCIE_ELBI_LTSSM_ENABLE) -		return 1; - -	return 0; +	return (val & PCIE_ELBI_XMLH_LINKUP);  }  static int exynos_pcie_host_init(struct pcie_port *pp) @@ -386,8 +257,14 @@ static int exynos_pcie_host_init(struct pcie_port *pp)  	pp->bridge->ops = &exynos_pci_ops; -	exynos_pcie_establish_link(ep); -	exynos_pcie_enable_interrupts(ep); +	exynos_pcie_assert_core_reset(ep); + +	phy_reset(ep->phy); +	phy_power_on(ep->phy); +	phy_init(ep->phy); + +	exynos_pcie_deassert_core_reset(ep); +	exynos_pcie_enable_irq_pulse(ep);  	return 0;  } @@ -396,32 +273,27 @@ static const struct dw_pcie_host_ops exynos_pcie_host_ops = {  	.host_init = exynos_pcie_host_init,  }; -static int __init exynos_add_pcie_port(struct exynos_pcie *ep, +static int exynos_add_pcie_port(struct exynos_pcie *ep,  				       struct platform_device *pdev)  { -	struct dw_pcie *pci = ep->pci; +	struct dw_pcie *pci = &ep->pci;  	struct pcie_port *pp = &pci->pp;  	struct device *dev = &pdev->dev;  	int ret; -	pp->irq = platform_get_irq(pdev, 1); +	pp->irq = platform_get_irq(pdev, 0);  	if (pp->irq < 0)  		return pp->irq;  	ret = devm_request_irq(dev, pp->irq, exynos_pcie_irq_handler, -				IRQF_SHARED, "exynos-pcie", ep); +			       IRQF_SHARED, "exynos-pcie", ep);  	if (ret) {  		dev_err(dev, "failed to request irq\n");  		return ret;  	} -	if (IS_ENABLED(CONFIG_PCI_MSI)) { -		pp->msi_irq = platform_get_irq(pdev, 0); -		if (pp->msi_irq < 0) -			return pp->msi_irq; -	} -  	pp->ops = &exynos_pcie_host_ops; +	pp->msi_irq = -ENODEV;  	ret = dw_pcie_host_init(pp);  	if (ret) { @@ -436,12 +308,12 @@ static const struct dw_pcie_ops dw_pcie_ops = {  	.read_dbi = exynos_pcie_read_dbi,  	.write_dbi = exynos_pcie_write_dbi,  	.link_up = exynos_pcie_link_up, +	.start_link = exynos_pcie_start_link,  }; -static int __init exynos_pcie_probe(struct platform_device *pdev) +static int exynos_pcie_probe(struct platform_device *pdev)  {  	struct device *dev = &pdev->dev; -	struct dw_pcie *pci;  	struct exynos_pcie *ep;  	struct device_node *np = dev->of_node;  	int ret; @@ -450,43 +322,45 @@ static int __init exynos_pcie_probe(struct platform_device *pdev)  	if (!ep)  		return -ENOMEM; -	pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); -	if (!pci) -		return -ENOMEM; - -	pci->dev = dev; -	pci->ops = &dw_pcie_ops; - -	ep->pci = pci; -	ep->ops = (const struct exynos_pcie_ops *) -		of_device_get_match_data(dev); - -	ep->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); +	ep->pci.dev = dev; +	ep->pci.ops = &dw_pcie_ops;  	ep->phy = devm_of_phy_get(dev, np, NULL); -	if (IS_ERR(ep->phy)) { -		if (PTR_ERR(ep->phy) != -ENODEV) -			return PTR_ERR(ep->phy); +	if (IS_ERR(ep->phy)) +		return PTR_ERR(ep->phy); -		ep->phy = NULL; -	} +	/* External Local Bus interface (ELBI) registers */ +	ep->elbi_base = devm_platform_ioremap_resource_byname(pdev, "elbi"); +	if (IS_ERR(ep->elbi_base)) +		return PTR_ERR(ep->elbi_base); -	if (ep->ops && ep->ops->get_mem_resources) { -		ret = ep->ops->get_mem_resources(pdev, ep); -		if (ret) -			return ret; +	ep->clk = devm_clk_get(dev, "pcie"); +	if (IS_ERR(ep->clk)) { +		dev_err(dev, "Failed to get pcie rc clock\n"); +		return PTR_ERR(ep->clk);  	} -	if (ep->ops && ep->ops->get_clk_resources && -			ep->ops->init_clk_resources) { -		ret = ep->ops->get_clk_resources(ep); -		if (ret) -			return ret; -		ret = ep->ops->init_clk_resources(ep); -		if (ret) -			return ret; +	ep->bus_clk = devm_clk_get(dev, "pcie_bus"); +	if (IS_ERR(ep->bus_clk)) { +		dev_err(dev, "Failed to get pcie bus clock\n"); +		return PTR_ERR(ep->bus_clk);  	} +	ep->supplies[0].supply = "vdd18"; +	ep->supplies[1].supply = "vdd10"; +	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ep->supplies), +				      ep->supplies); +	if (ret) +		return ret; + +	ret = exynos_pcie_init_clk_resources(ep); +	if (ret) +		return ret; + +	ret = regulator_bulk_enable(ARRAY_SIZE(ep->supplies), ep->supplies); +	if (ret) +		return ret; +  	platform_set_drvdata(pdev, ep);  	ret = exynos_add_pcie_port(ep, pdev); @@ -497,9 +371,9 @@ static int __init exynos_pcie_probe(struct platform_device *pdev)  fail_probe:  	phy_exit(ep->phy); +	exynos_pcie_deinit_clk_resources(ep); +	regulator_bulk_disable(ARRAY_SIZE(ep->supplies), ep->supplies); -	if (ep->ops && ep->ops->deinit_clk_resources) -		ep->ops->deinit_clk_resources(ep);  	return ret;  } @@ -507,32 +381,65 @@ static int __exit exynos_pcie_remove(struct platform_device *pdev)  {  	struct exynos_pcie *ep = platform_get_drvdata(pdev); -	if (ep->ops && ep->ops->deinit_clk_resources) -		ep->ops->deinit_clk_resources(ep); +	dw_pcie_host_deinit(&ep->pci.pp); +	exynos_pcie_assert_core_reset(ep); +	phy_power_off(ep->phy); +	phy_exit(ep->phy); +	exynos_pcie_deinit_clk_resources(ep); +	regulator_bulk_disable(ARRAY_SIZE(ep->supplies), ep->supplies);  	return 0;  } +static int __maybe_unused exynos_pcie_suspend_noirq(struct device *dev) +{ +	struct exynos_pcie *ep = dev_get_drvdata(dev); + +	exynos_pcie_assert_core_reset(ep); +	phy_power_off(ep->phy); +	phy_exit(ep->phy); +	regulator_bulk_disable(ARRAY_SIZE(ep->supplies), ep->supplies); + +	return 0; +} + +static int __maybe_unused exynos_pcie_resume_noirq(struct device *dev) +{ +	struct exynos_pcie *ep = dev_get_drvdata(dev); +	struct dw_pcie *pci = &ep->pci; +	struct pcie_port *pp = &pci->pp; +	int ret; + +	ret = regulator_bulk_enable(ARRAY_SIZE(ep->supplies), ep->supplies); +	if (ret) +		return ret; + +	/* exynos_pcie_host_init controls ep->phy */ +	exynos_pcie_host_init(pp); +	dw_pcie_setup_rc(pp); +	exynos_pcie_start_link(pci); +	return dw_pcie_wait_for_link(pci); +} + +static const struct dev_pm_ops exynos_pcie_pm_ops = { +	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(exynos_pcie_suspend_noirq, +				      exynos_pcie_resume_noirq) +}; +  static const struct of_device_id exynos_pcie_of_match[] = { -	{ -		.compatible = "samsung,exynos5440-pcie", -		.data = &exynos5440_pcie_ops -	}, -	{}, +	{ .compatible = "samsung,exynos5433-pcie", }, +	{ },  };  static struct platform_driver exynos_pcie_driver = { +	.probe		= exynos_pcie_probe,  	.remove		= __exit_p(exynos_pcie_remove),  	.driver = {  		.name	= "exynos-pcie",  		.of_match_table = exynos_pcie_of_match, +		.pm		= &exynos_pcie_pm_ops,  	},  }; - -/* Exynos PCIe driver does not allow module unload */ - -static int __init exynos_pcie_init(void) -{ -	return platform_driver_probe(&exynos_pcie_driver, exynos_pcie_probe); -} -subsys_initcall(exynos_pcie_init); +module_platform_driver(exynos_pcie_driver); +MODULE_LICENSE("GPL v2"); +MODULE_DEVICE_TABLE(of, exynos_pcie_of_match);  |