Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751725AbcL0GgN (ORCPT ); Tue, 27 Dec 2016 01:36:13 -0500 Received: from mailout1.samsung.com ([203.254.224.24]:60634 "EHLO mailout1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750827AbcL0GgD (ORCPT ); Tue, 27 Dec 2016 01:36:03 -0500 X-AuditID: b6c32a4b-f790b6d00000492f-c4-58620bd01b0e Message-id: <58620B5A.1060900@samsung.com> Date: Tue, 27 Dec 2016 12:04:02 +0530 From: Alim Akhtar User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.5.0 MIME-version: 1.0 To: Jaehoon Chung , Pankaj Dubey , linux-kernel@vger.kernel.org, linux-samsung-soc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-pci@vger.kernel.org Cc: krzk@kernel.org, kgene@kernel.org, jingoohan1@gmail.com, bhelgaas@google.com, sanath@samsung.com, Niyas Ahmed S T , CPGS Subject: Re: [PATCH] PCI: exynos: refactor exynos pcie driver In-reply-to: <6de4bc5b-05fb-793f-d3ab-b1c6ee19cfeb@samsung.com> Content-type: text/plain; charset=windows-1252; format=flowed Content-transfer-encoding: 7bit X-Brightmail-Tracker: H4sIAAAAAAAAA02Se0hTcRTH+e3uPrRuXJfZybLsUkSG043pbqU90GJgD6GC0QO96mWT3Ca7 W5QF9qJSomWI6VopkSSGGTcrNQrbKnv56GURzWhKj0UPemcP2nYL/O9zfuf7/Z1zfr9DYap6 Ip4qtjoEu5UvYYlo5XnfbH1y/5gCY2rANZM7sdPMvfbO5h6P7MG5ps91JOcaeoNxfX1nSE4a GsC5+50egus51k1wtX2XFdxwdQDnjp/7THI1p09ji2hDh9tPGhokp0FqriAMZ0+UGw60NSPD J2lqLrFWyDALfJFgTxSshbaiYqspk81ZlZeVl5aeqknWzOX0bKKVtwiZbPay3OSlxSWhLtnE TXyJM3SUy4sim7Igw25zOoREs010ZLLrNBqtWpOqV2u1WrVOu2GeNi0kyRfMUksNWVr1BW0+ 6rtHbkeB66gSRVHA6KDnyUNC5jjoH2yNsIppR9BTsb4SRYf4E4K6wUfK/4b+A7twOXEGQWNX EA8naCYJ+rztZJiVzEzwdzdEzglmDvgPtynCPIExgq/6FinrY+Bm3bAyfFEs40fwrP4DGQ4w pgXB/q4rkf7GM5lwu/JSxB3FLIQdF39iYcaYxfBryIvLPA0uvPVgYTMwvSR887hCCSoUJIDU hcltZ8OujuF/PB6C3W2kzPEQbB/4592LYPDgO1wOahFUtLxVyKqF0PXAo5SrjYN9vt+kXICG fXtUssQAnc/f4zIvhprGw4T8Rr8VENx9gTiIprpHje0eNYR71BANCGtGcUKpaDEJorZUrxZ5 i+i0mtSFNouEIsuZlNOOpN5lXsRQiB1Lfz/JG1U4v0ncYvEioDA2lvZFFxhVdBG/pUyw2/Ls zhJB9KK00LdUYfETCm2hVbc68jS6dI1Oq0vVp3Ocjp1IQ+t8o4ox8Q5hoyCUCvb/PgUVFb8d lR9bvfLpkkmBzgWq6S2H7h4d8K4vclNGcpsnZYySvuGKc1nnFpQ1XaNX0msejyUHb8X8evEm EMNupWds/CrudLYmUau733+sS7l0Z3KalJ81hY7Nr42e1dEwdPVUR3DV1puODSkPf5TpX+12 vfyzaCRhaW+tX7niyPKEYvTHlNG/jlWKZl6ThNlF/i9KWSBKsgMAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrFIsWRmVeSWpSXmKPExsWSneMpo3uBOynC4PgjAYslTRkWLw9pWtz4 1cZqseLLTHaL/sevmS3On9/AbrHp8TVWi8u75rBZnJ13nM1ixvl9TBZPpjxitVi09Qu7xbR1 65gdeD12zrrL7rFgU6nHplWdbB6bl9R79G1ZxejxeZNcAFuUm01GamJKapFCal5yfkpmXrqt UmiIm66FkkJeYm6qrVKErm9IkJJCWWJOKZBnZIAGHJwD3IOV9O0S3DI2rZ3GXjDxK2PF3MOX 2BsYHx1j7GLk5JAQMJG40NfMCmGLSVy4t56ti5GLQ0hgHaPEwo/3mEESvAJaEucP7WAHsVkE VCXuHl8A1sAmoC1xd/oWJhBbVCBM4uPRdWwQ9YISJ2c+YQEZJCJwF2jQr5XMIA6zwAZGiWPb HoNNEhawlTjdtZcJYt1HJokjhx6wgCQ4BewlGnf/BlvNDFR0Z+5uKFteYvvbOcwTGPlnIdky C0nZLCRlCxiZVzGKpRYU56bnFhcYGOkVJ+YWl+al6yXn525iBMbjtsNK4jsYZ63wOsQowMGo xMO7YXNihBBrYllxZe4hRgkOZiURXgG2pAgh3pTEyqrUovz4otKc1OJDjKbAUJjILCWanA9M FXkl8YYmphYWFiaWxsbGFiZK4ryx05+FCwmkJ5akZqemFqQWwfQxcXBKNTBO0Xqm1n963644 TZ4Tq44ocCjOebvao/m9y9ubsfUL9Y66y7Z+zVt+LraqYdXL0h9L6uOYtknmzLo677CYYm/j Vafti+t5RHuSnacte1jz/oyJYXPnhYuvgiocmreFr449ul6Kl6kudr4Bb6+5ta2vNI/tqwkn J6c/zS6ffvZVsvb08/OlBeWUWIozEg21mIuKEwGm4sQY3QIAAA== X-MTR: 20000000000000000@CPGS X-CMS-MailID: 20161227063600epcas2p11e4fd2c1fb627956fd27aa1d91db8cf3 X-Msg-Generator: CA X-Sender-IP: 182.195.34.23 X-Local-Sender: =?UTF-8?B?7JWM66a8G1NTSVItVHVybiBLZXkgU29sdXRpb25zG+yCvA==?= =?UTF-8?B?7ISx7KCE7J6QGy4vU2VuaW9yIENoaWVmIEVuZ2luZWVy?= X-Global-Sender: =?UTF-8?B?QUxJTSBBS0hUQVIbU1NJUi1UdXJuIEtleSBTb2x1dGlvbnMb?= =?UTF-8?B?U2Ftc3VuZyBFbGVjdHJvbmljcxsuL1NlbmlvciBDaGllZiBFbmdpbmVlcg==?= X-Sender-Code: =?UTF-8?B?QzEwG1NXQUhRG0MxMElEMDdJRDAxMDk5Nw==?= CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-HopCount: 7 X-CMS-RootMailID: 20161223105411epcas1p3727f726e757ec6c6d7bff04a9af40077 X-RootMTR: 20161223105411epcas1p3727f726e757ec6c6d7bff04a9af40077 References: <1482490587-13611-1-git-send-email-pankaj.dubey@samsung.com> <5860E6F7.2090703@samsung.com> <79b89c49-a9de-3daa-9afa-b8f36304a226@samsung.com> <5861CE23.9060202@samsung.com> <6de4bc5b-05fb-793f-d3ab-b1c6ee19cfeb@samsung.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 30709 Lines: 668 Hi Jaehoon, On 12/27/2016 08:00 AM, Jaehoon Chung wrote: > On 12/27/2016 11:12 AM, Alim Akhtar wrote: >> >> >> On 12/27/2016 06:39 AM, Jaehoon Chung wrote: >>> Dear Alim, >>> >>> On 12/26/2016 06:46 PM, Alim Akhtar wrote: >>>> Hello Jaehoon >>>> >>>> On 12/26/2016 02:32 PM, Jaehoon Chung wrote: >>>>> Hi Pankaj, >>>>> >>>>> On 12/23/2016 07:56 PM, Pankaj Dubey wrote: >>>>>> From: Niyas Ahmed S T >>>>>> >>>>>> Currently Exynos PCIe driver is only supported for Exynos5440 SoC. >>>>>> This patch does refactoring of Exynos PCIe driver to extend support >>>>>> for other Exynos SoC. >>>>>> >>>>>> Following are the main changes done via this patch: >>>>>> 1) It adds separate structs for memory, clock resources. >>>>>> 2) It add exynos_pcie_ops struct which will allow us to support the >>>>>> differences in resources in different Exynos SoC. >>>>> >>>>> It's nice to me for reusing this file. >>>>> but after considering too many times, i decided not to use this file. >>>>> >>>>> I'm not sure what block base is..actually this pci-exynos.c is really black-box. >>>>> (No one maintains this file, even Samsung didn't care.) >>>>> Who is using this? >>>>> If Someone can share the information about exynos5440, i can refactor everything. >>>>> Otherwise, there are two solution.. >>>>> >>>>> One is "adding the new pci-exynos.c" likes pci-exynos5433.c >>>>> Other is "refactor this file" under assuming the each register's usage. >>>>> >>>> Its alway good to reuse code as far as possible. >>>> I am yet to see the details of 5440, but since people are now going to support more Exynos variants, in my opinion, instead of adding pci-exynos5433.c, you can rename current pci-exynos.c to something like pci-exynos5440.c (only in case its too much changes needed to support 5433/exynos7) and lets have a common pci-exynos.c where we can add exynos7/5433 and others SoCs, AFAIK at least exynos7 and 5433 has similar pci controller. >>> >>> Yes, It's always good to reuse. but as you know, current pci-exynos.c file is really specific for only exynos5440. >>> I will try to check about combining. >>> >>>>> I want to use the PHY generic Framework for EXYNOS PCIe. >>>>> >>>> I don't think you have an option here, you should use generic PHY APIs, otherwise phy drive should go to drivers/misc. >>>> Other thoughts are welcome. >>> >>> Why go to drivers/misc? There is driver/phy/ for PHY generic Framework. >>> If i will touch this file, then i will put our phy-exynos-pcie file under driver/phy/ . >>> I already sent the patch for this. Could you check them? >>> >> My point was, if you are not going to use generic PHY APIs, then phy driver should go into drivers/misc. Anyway as you said you have already posted patches with generic phy framework, I will take a look. > > Ah. Right..And i'm doing the refactoring to reuse the current pci-exynos.c. There is a nice refactoring patch posted by Pankaj recently @ https://lkml.org/lkml/2016/12/23/73 I would suggest you to rebase your work on this top. > Maybe..Today or Tomorrow..I will send the patches..At that time, could you also check them? > Any comments might be helpful to me! :) > Will wait for you patches :-) > Best Regards, > Jaehoon Chung > >>> http://patchwork.ozlabs.org/patch/708738/ >>> http://patchwork.ozlabs.org/patch/708742/ >>> >> Thanks. >> >>> Best Regards, >>> Jaehoon Chung >>> >>>> >>>>> If you or other guys really want to use the pci-exynos.c for other exynos, >>>>> I will rework with PHY generic framework. Then i will resend the my patches as V2. >>>>> >>>>> One more thing..Does anyone know what the usage of block base is? >>>>> Can i use that register as "syscon"? >>>>> >>>>> Best Regards, >>>>> Jaehoon Chung >>>>> >>>>>> >>>>>> No functional change intended. >>>>>> >>>>>> Signed-off-by: Niyas Ahmed S T >>>>>> Signed-off-by: Pankaj Dubey >>>>>> --- >>>>>> This patch set is prepared on top of Krzysztof's for-next and >>>>>> PCIe driver cleanup patch [1] by Jaehoon Chung. >>>>>> >>>>>> [1]: https://lkml.org/lkml/2016/12/19/44 >>>>>> >>>>>> >>>>>> drivers/pci/host/pci-exynos.c | 346 ++++++++++++++++++++++++++---------------- >>>>>> 1 file changed, 217 insertions(+), 129 deletions(-) >>>>>> >>>>>> diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c >>>>>> index 33562cf..2dc54f7 100644 >>>>>> --- a/drivers/pci/host/pci-exynos.c >>>>>> +++ b/drivers/pci/host/pci-exynos.c >>>>>> @@ -17,6 +17,7 @@ >>>>>> #include >>>>>> #include >>>>>> #include >>>>>> +#include >>>>>> #include >>>>>> #include >>>>>> #include >>>>>> @@ -28,16 +29,6 @@ >>>>>> >>>>>> #define to_exynos_pcie(x) container_of(x, struct exynos_pcie, pp) >>>>>> >>>>>> -struct exynos_pcie { >>>>>> - struct pcie_port pp; >>>>>> - void __iomem *elbi_base; /* DT 0th resource */ >>>>>> - void __iomem *phy_base; /* DT 1st resource */ >>>>>> - void __iomem *block_base; /* DT 2nd resource */ >>>>>> - int reset_gpio; >>>>>> - struct clk *clk; >>>>>> - struct clk *bus_clk; >>>>>> -}; >>>>>> - >>>>>> /* PCIe ELBI registers */ >>>>>> #define PCIE_IRQ_PULSE 0x000 >>>>>> #define IRQ_INTA_ASSERT BIT(0) >>>>>> @@ -102,6 +93,122 @@ struct exynos_pcie { >>>>>> #define PCIE_PHY_TRSV3_PD_TSV BIT(7) >>>>>> #define PCIE_PHY_TRSV3_LVCC 0x31c >>>>>> >>>>>> +struct exynos_pcie_mem_res { >>>>>> + void __iomem *elbi_base; /* DT 0th resource: PCIE CTRL */ >>>>>> + void __iomem *phy_base; /* DT 1st resource: PHY CTRL */ >>>>>> + void __iomem *block_base; /* DT 2nd resource: PHY ADDITIONAL CTRL */ >>>>>> +}; >>>>>> + >>>>>> +struct exynos_pcie_clk_res { >>>>>> + struct clk *clk; >>>>>> + struct clk *bus_clk; >>>>>> +}; >>>>>> + >>>>>> +struct exynos_pcie { >>>>>> + struct pcie_port pp; >>>>>> + struct exynos_pcie_mem_res *mem_res; >>>>>> + struct exynos_pcie_clk_res *clk_res; >>>>>> + const struct exynos_pcie_ops *ops; >>>>>> + int reset_gpio; >>>>>> +}; >>>>>> + >>>>>> +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 resource *res; >>>>>> + struct device *dev = ep->pp.dev; >>>>>> + >>>>>> + ep->mem_res = devm_kzalloc(dev, sizeof(*ep->mem_res), GFP_KERNEL); >>>>>> + if (!ep->mem_res) >>>>>> + return -ENOMEM; >>>>>> + >>>>>> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); >>>>>> + ep->mem_res->elbi_base = devm_ioremap_resource(dev, res); >>>>>> + if (IS_ERR(ep->mem_res->elbi_base)) >>>>>> + return PTR_ERR(ep->mem_res->elbi_base); >>>>>> + >>>>>> + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); >>>>>> + ep->mem_res->phy_base = devm_ioremap_resource(dev, res); >>>>>> + if (IS_ERR(ep->mem_res->phy_base)) >>>>>> + return PTR_ERR(ep->mem_res->phy_base); >>>>>> + >>>>>> + res = platform_get_resource(pdev, IORESOURCE_MEM, 2); >>>>>> + ep->mem_res->block_base = devm_ioremap_resource(dev, res); >>>>>> + if (IS_ERR(ep->mem_res->block_base)) >>>>>> + return PTR_ERR(ep->mem_res->block_base); >>>>>> + >>>>>> + return 0; >>>>>> +} >>>>>> + >>>>>> +static int exynos5440_pcie_get_clk_resources(struct exynos_pcie *ep) >>>>>> +{ >>>>>> + struct device *dev = ep->pp.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 device *dev = ep->pp.dev; >>>>>> + int ret; >>>>>> + >>>>>> + ret = clk_prepare_enable(ep->clk_res->clk); >>>>>> + if (ret) { >>>>>> + dev_err(dev, "cannot enable pcie rc clock"); >>>>>> + return ret; >>>>>> + } >>>>>> + >>>>>> + ret = clk_prepare_enable(ep->clk_res->bus_clk); >>>>>> + if (ret) { >>>>>> + dev_err(dev, "cannot enable pcie bus clock"); >>>>>> + goto err_bus_clk; >>>>>> + } >>>>>> + >>>>>> + return 0; >>>>>> + >>>>>> +err_bus_clk: >>>>>> + clk_disable_unprepare(ep->clk_res->clk); >>>>>> + >>>>>> + return ret; >>>>>> +} >>>>>> + >>>>>> +static void exynos5440_pcie_deinit_clk_resources(struct exynos_pcie *ep) >>>>>> +{ >>>>>> + clk_disable_unprepare(ep->clk_res->bus_clk); >>>>>> + clk_disable_unprepare(ep->clk_res->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); >>>>>> @@ -116,155 +223,155 @@ static void exynos_pcie_sideband_dbi_w_mode(struct exynos_pcie *ep, bool on) >>>>>> { >>>>>> u32 val; >>>>>> >>>>>> - val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_SLV_AWMISC); >>>>>> + val = exynos_pcie_readl(ep->mem_res->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->elbi_base, val, PCIE_ELBI_SLV_AWMISC); >>>>>> + exynos_pcie_writel(ep->mem_res->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->elbi_base, PCIE_ELBI_SLV_ARMISC); >>>>>> + val = exynos_pcie_readl(ep->mem_res->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->elbi_base, val, PCIE_ELBI_SLV_ARMISC); >>>>>> + exynos_pcie_writel(ep->mem_res->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->elbi_base, PCIE_CORE_RESET); >>>>>> + val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_CORE_RESET); >>>>>> val &= ~PCIE_CORE_RESET_ENABLE; >>>>>> - exynos_pcie_writel(ep->elbi_base, val, PCIE_CORE_RESET); >>>>>> - exynos_pcie_writel(ep->elbi_base, 0, PCIE_PWR_RESET); >>>>>> - exynos_pcie_writel(ep->elbi_base, 0, PCIE_STICKY_RESET); >>>>>> - exynos_pcie_writel(ep->elbi_base, 0, PCIE_NONSTICKY_RESET); >>>>>> + 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); >>>>>> } >>>>>> >>>>>> static void exynos_pcie_deassert_core_reset(struct exynos_pcie *ep) >>>>>> { >>>>>> u32 val; >>>>>> >>>>>> - val = exynos_pcie_readl(ep->elbi_base, PCIE_CORE_RESET); >>>>>> + val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_CORE_RESET); >>>>>> val |= PCIE_CORE_RESET_ENABLE; >>>>>> >>>>>> - 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); >>>>>> - exynos_pcie_writel(ep->block_base, 1, PCIE_PHY_MAC_RESET); >>>>>> + 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); >>>>>> + exynos_pcie_writel(ep->mem_res->block_base, 1, PCIE_PHY_MAC_RESET); >>>>>> } >>>>>> >>>>>> static void exynos_pcie_assert_phy_reset(struct exynos_pcie *ep) >>>>>> { >>>>>> - exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_MAC_RESET); >>>>>> - exynos_pcie_writel(ep->block_base, 1, PCIE_PHY_GLOBAL_RESET); >>>>>> + exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_MAC_RESET); >>>>>> + exynos_pcie_writel(ep->mem_res->block_base, 1, PCIE_PHY_GLOBAL_RESET); >>>>>> } >>>>>> >>>>>> static void exynos_pcie_deassert_phy_reset(struct exynos_pcie *ep) >>>>>> { >>>>>> - exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_GLOBAL_RESET); >>>>>> - exynos_pcie_writel(ep->elbi_base, 1, PCIE_PWR_RESET); >>>>>> - exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_COMMON_RESET); >>>>>> - exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_CMN_REG); >>>>>> - exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_TRSVREG_RESET); >>>>>> - exynos_pcie_writel(ep->block_base, 0, PCIE_PHY_TRSV_RESET); >>>>>> + exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_GLOBAL_RESET); >>>>>> + exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_PWR_RESET); >>>>>> + exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_COMMON_RESET); >>>>>> + exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_CMN_REG); >>>>>> + exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_TRSVREG_RESET); >>>>>> + exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_TRSV_RESET); >>>>>> } >>>>>> >>>>>> static void exynos_pcie_power_on_phy(struct exynos_pcie *ep) >>>>>> { >>>>>> u32 val; >>>>>> >>>>>> - val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_COMMON_POWER); >>>>>> + val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_COMMON_POWER); >>>>>> val &= ~PCIE_PHY_COMMON_PD_CMN; >>>>>> - exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_COMMON_POWER); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_COMMON_POWER); >>>>>> >>>>>> - val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV0_POWER); >>>>>> + val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV0_POWER); >>>>>> val &= ~PCIE_PHY_TRSV0_PD_TSV; >>>>>> - exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV0_POWER); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV0_POWER); >>>>>> >>>>>> - val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV1_POWER); >>>>>> + val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV1_POWER); >>>>>> val &= ~PCIE_PHY_TRSV1_PD_TSV; >>>>>> - exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV1_POWER); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV1_POWER); >>>>>> >>>>>> - val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV2_POWER); >>>>>> + val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV2_POWER); >>>>>> val &= ~PCIE_PHY_TRSV2_PD_TSV; >>>>>> - exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV2_POWER); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV2_POWER); >>>>>> >>>>>> - val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV3_POWER); >>>>>> + val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV3_POWER); >>>>>> val &= ~PCIE_PHY_TRSV3_PD_TSV; >>>>>> - exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV3_POWER); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV3_POWER); >>>>>> } >>>>>> >>>>>> static void exynos_pcie_power_off_phy(struct exynos_pcie *ep) >>>>>> { >>>>>> u32 val; >>>>>> >>>>>> - val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_COMMON_POWER); >>>>>> + val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_COMMON_POWER); >>>>>> val |= PCIE_PHY_COMMON_PD_CMN; >>>>>> - exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_COMMON_POWER); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_COMMON_POWER); >>>>>> >>>>>> - val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV0_POWER); >>>>>> + val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV0_POWER); >>>>>> val |= PCIE_PHY_TRSV0_PD_TSV; >>>>>> - exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV0_POWER); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV0_POWER); >>>>>> >>>>>> - val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV1_POWER); >>>>>> + val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV1_POWER); >>>>>> val |= PCIE_PHY_TRSV1_PD_TSV; >>>>>> - exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV1_POWER); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV1_POWER); >>>>>> >>>>>> - val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV2_POWER); >>>>>> + val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV2_POWER); >>>>>> val |= PCIE_PHY_TRSV2_PD_TSV; >>>>>> - exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV2_POWER); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV2_POWER); >>>>>> >>>>>> - val = exynos_pcie_readl(ep->phy_base, PCIE_PHY_TRSV3_POWER); >>>>>> + val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV3_POWER); >>>>>> val |= PCIE_PHY_TRSV3_PD_TSV; >>>>>> - exynos_pcie_writel(ep->phy_base, val, PCIE_PHY_TRSV3_POWER); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV3_POWER); >>>>>> } >>>>>> >>>>>> static void exynos_pcie_init_phy(struct exynos_pcie *ep) >>>>>> { >>>>>> /* DCC feedback control off */ >>>>>> - exynos_pcie_writel(ep->phy_base, 0x29, PCIE_PHY_DCC_FEEDBACK); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, 0x29, PCIE_PHY_DCC_FEEDBACK); >>>>>> >>>>>> /* set TX/RX impedance */ >>>>>> - exynos_pcie_writel(ep->phy_base, 0xd5, PCIE_PHY_IMPEDANCE); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, 0xd5, PCIE_PHY_IMPEDANCE); >>>>>> >>>>>> /* set 50Mhz PHY clock */ >>>>>> - exynos_pcie_writel(ep->phy_base, 0x14, PCIE_PHY_PLL_DIV_0); >>>>>> - exynos_pcie_writel(ep->phy_base, 0x12, PCIE_PHY_PLL_DIV_1); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, 0x14, PCIE_PHY_PLL_DIV_0); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, 0x12, PCIE_PHY_PLL_DIV_1); >>>>>> >>>>>> /* set TX Differential output for lane 0 */ >>>>>> - exynos_pcie_writel(ep->phy_base, 0x7f, PCIE_PHY_TRSV0_DRV_LVL); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, 0x7f, PCIE_PHY_TRSV0_DRV_LVL); >>>>>> >>>>>> /* set TX Pre-emphasis Level Control for lane 0 to minimum */ >>>>>> - exynos_pcie_writel(ep->phy_base, 0x0, PCIE_PHY_TRSV0_EMP_LVL); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, 0x0, PCIE_PHY_TRSV0_EMP_LVL); >>>>>> >>>>>> /* set RX clock and data recovery bandwidth */ >>>>>> - exynos_pcie_writel(ep->phy_base, 0xe7, PCIE_PHY_PLL_BIAS); >>>>>> - exynos_pcie_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV0_RXCDR); >>>>>> - exynos_pcie_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV1_RXCDR); >>>>>> - exynos_pcie_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV2_RXCDR); >>>>>> - exynos_pcie_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV3_RXCDR); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, 0xe7, PCIE_PHY_PLL_BIAS); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV0_RXCDR); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV1_RXCDR); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV2_RXCDR); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV3_RXCDR); >>>>>> >>>>>> /* change TX Pre-emphasis Level Control for lanes */ >>>>>> - exynos_pcie_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV0_EMP_LVL); >>>>>> - exynos_pcie_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV1_EMP_LVL); >>>>>> - exynos_pcie_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV2_EMP_LVL); >>>>>> - exynos_pcie_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV3_EMP_LVL); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV0_EMP_LVL); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV1_EMP_LVL); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV2_EMP_LVL); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV3_EMP_LVL); >>>>>> >>>>>> /* set LVCC */ >>>>>> - exynos_pcie_writel(ep->phy_base, 0x20, PCIE_PHY_TRSV0_LVCC); >>>>>> - exynos_pcie_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV1_LVCC); >>>>>> - exynos_pcie_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV2_LVCC); >>>>>> - exynos_pcie_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV3_LVCC); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, 0x20, PCIE_PHY_TRSV0_LVCC); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, 0xa0, PCIE_PHY_TRSV1_LVCC); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, 0xa0, PCIE_PHY_TRSV2_LVCC); >>>>>> + exynos_pcie_writel(ep->mem_res->phy_base, 0xa0, PCIE_PHY_TRSV3_LVCC); >>>>>> } >>>>>> >>>>>> static void exynos_pcie_assert_reset(struct exynos_pcie *exynos_pcie) >>>>>> @@ -295,25 +402,27 @@ static int exynos_pcie_establish_link(struct exynos_pcie *exynos_pcie) >>>>>> exynos_pcie_init_phy(exynos_pcie); >>>>>> >>>>>> /* pulse for common reset */ >>>>>> - exynos_pcie_writel(exynos_pcie->block_base, 1, PCIE_PHY_COMMON_RESET); >>>>>> + exynos_pcie_writel(exynos_pcie->mem_res->block_base, 1, >>>>>> + PCIE_PHY_COMMON_RESET); >>>>>> udelay(500); >>>>>> - exynos_pcie_writel(exynos_pcie->block_base, 0, PCIE_PHY_COMMON_RESET); >>>>>> + exynos_pcie_writel(exynos_pcie->mem_res->block_base, 0, >>>>>> + PCIE_PHY_COMMON_RESET); >>>>>> >>>>>> exynos_pcie_deassert_core_reset(exynos_pcie); >>>>>> dw_pcie_setup_rc(pp); >>>>>> exynos_pcie_assert_reset(exynos_pcie); >>>>>> >>>>>> /* assert LTSSM enable */ >>>>>> - exynos_pcie_writel(exynos_pcie->elbi_base, PCIE_ELBI_LTSSM_ENABLE, >>>>>> - PCIE_APP_LTSSM_ENABLE); >>>>>> + exynos_pcie_writel(exynos_pcie->mem_res->elbi_base, >>>>>> + PCIE_ELBI_LTSSM_ENABLE, PCIE_APP_LTSSM_ENABLE); >>>>>> >>>>>> /* check if the link is up or not */ >>>>>> if (!dw_pcie_wait_for_link(pp)) >>>>>> return 0; >>>>>> >>>>>> - while (exynos_pcie_readl(exynos_pcie->phy_base, >>>>>> + while (exynos_pcie_readl(exynos_pcie->mem_res->phy_base, >>>>>> PCIE_PHY_PLL_LOCKED) == 0) { >>>>>> - val = exynos_pcie_readl(exynos_pcie->block_base, >>>>>> + val = exynos_pcie_readl(exynos_pcie->mem_res->block_base, >>>>>> PCIE_PHY_PLL_LOCKED); >>>>>> dev_info(dev, "PLL Locked: 0x%x\n", val); >>>>>> } >>>>>> @@ -325,8 +434,8 @@ static void exynos_pcie_clear_irq_pulse(struct exynos_pcie *ep) >>>>>> { >>>>>> u32 val; >>>>>> >>>>>> - val = exynos_pcie_readl(ep->elbi_base, PCIE_IRQ_PULSE); >>>>>> - exynos_pcie_writel(ep->elbi_base, val, 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) >>>>>> @@ -336,7 +445,7 @@ static void exynos_pcie_enable_irq_pulse(struct exynos_pcie *ep) >>>>>> /* enable INTX interrupt */ >>>>>> val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT | >>>>>> IRQ_INTC_ASSERT | IRQ_INTD_ASSERT; >>>>>> - exynos_pcie_writel(ep->elbi_base, val, PCIE_IRQ_EN_PULSE); >>>>>> + exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_EN_PULSE); >>>>>> } >>>>>> >>>>>> static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg) >>>>>> @@ -363,9 +472,9 @@ static void exynos_pcie_msi_init(struct exynos_pcie *ep) >>>>>> dw_pcie_msi_init(pp); >>>>>> >>>>>> /* enable MSI interrupt */ >>>>>> - val = exynos_pcie_readl(ep->elbi_base, PCIE_IRQ_EN_LEVEL); >>>>>> + val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_IRQ_EN_LEVEL); >>>>>> val |= IRQ_MSI_ENABLE; >>>>>> - exynos_pcie_writel(ep->elbi_base, val, PCIE_IRQ_EN_LEVEL); >>>>>> + exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_EN_LEVEL); >>>>>> } >>>>>> >>>>>> static void exynos_pcie_enable_interrupts(struct exynos_pcie *exynos_pcie) >>>>>> @@ -425,7 +534,8 @@ static int exynos_pcie_link_up(struct pcie_port *pp) >>>>>> struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); >>>>>> u32 val; >>>>>> >>>>>> - val = exynos_pcie_readl(exynos_pcie->elbi_base, PCIE_ELBI_RDLH_LINKUP); >>>>>> + val = exynos_pcie_readl(exynos_pcie->mem_res->elbi_base, >>>>>> + PCIE_ELBI_RDLH_LINKUP); >>>>>> if (val == PCIE_ELBI_LTSSM_ENABLE) >>>>>> return 1; >>>>>> >>>>>> @@ -503,7 +613,6 @@ static int __init exynos_pcie_probe(struct platform_device *pdev) >>>>>> struct exynos_pcie *exynos_pcie; >>>>>> struct pcie_port *pp; >>>>>> struct device_node *np = dev->of_node; >>>>>> - struct resource *res; >>>>>> int ret; >>>>>> >>>>>> exynos_pcie = devm_kzalloc(dev, sizeof(*exynos_pcie), GFP_KERNEL); >>>>>> @@ -513,59 +622,37 @@ static int __init exynos_pcie_probe(struct platform_device *pdev) >>>>>> pp = &exynos_pcie->pp; >>>>>> pp->dev = dev; >>>>>> >>>>>> - exynos_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); >>>>>> - >>>>>> - exynos_pcie->clk = devm_clk_get(dev, "pcie"); >>>>>> - if (IS_ERR(exynos_pcie->clk)) { >>>>>> - dev_err(dev, "Failed to get pcie rc clock\n"); >>>>>> - return PTR_ERR(exynos_pcie->clk); >>>>>> - } >>>>>> - ret = clk_prepare_enable(exynos_pcie->clk); >>>>>> - if (ret) >>>>>> - return ret; >>>>>> + exynos_pcie->ops = (const struct exynos_pcie_ops *) >>>>>> + of_device_get_match_data(dev); >>>>>> >>>>>> - exynos_pcie->bus_clk = devm_clk_get(dev, "pcie_bus"); >>>>>> - if (IS_ERR(exynos_pcie->bus_clk)) { >>>>>> - dev_err(dev, "Failed to get pcie bus clock\n"); >>>>>> - ret = PTR_ERR(exynos_pcie->bus_clk); >>>>>> - goto fail_clk; >>>>>> - } >>>>>> - ret = clk_prepare_enable(exynos_pcie->bus_clk); >>>>>> - if (ret) >>>>>> - goto fail_clk; >>>>>> + exynos_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); >>>>>> >>>>>> - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); >>>>>> - exynos_pcie->elbi_base = devm_ioremap_resource(dev, res); >>>>>> - if (IS_ERR(exynos_pcie->elbi_base)) { >>>>>> - ret = PTR_ERR(exynos_pcie->elbi_base); >>>>>> - goto fail_bus_clk; >>>>>> + if (exynos_pcie->ops && exynos_pcie->ops->get_mem_resources) { >>>>>> + ret = exynos_pcie->ops->get_mem_resources(pdev, exynos_pcie); >>>>>> + if (ret) >>>>>> + return ret; >>>>>> } >>>>>> >>>>>> - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); >>>>>> - exynos_pcie->phy_base = devm_ioremap_resource(dev, res); >>>>>> - if (IS_ERR(exynos_pcie->phy_base)) { >>>>>> - ret = PTR_ERR(exynos_pcie->phy_base); >>>>>> - goto fail_bus_clk; >>>>>> - } >>>>>> + if (exynos_pcie->ops && exynos_pcie->ops->get_clk_resources) { >>>>>> + ret = exynos_pcie->ops->get_clk_resources(exynos_pcie); >>>>>> + if (ret) >>>>>> + return ret; >>>>>> >>>>>> - res = platform_get_resource(pdev, IORESOURCE_MEM, 2); >>>>>> - exynos_pcie->block_base = devm_ioremap_resource(dev, res); >>>>>> - if (IS_ERR(exynos_pcie->block_base)) { >>>>>> - ret = PTR_ERR(exynos_pcie->block_base); >>>>>> - goto fail_bus_clk; >>>>>> + ret = exynos_pcie->ops->init_clk_resources(exynos_pcie); >>>>>> + if (ret) >>>>>> + return ret; >>>>>> } >>>>>> >>>>>> ret = exynos_add_pcie_port(exynos_pcie, pdev); >>>>>> if (ret < 0) >>>>>> - goto fail_bus_clk; >>>>>> + goto fail_probe; >>>>>> >>>>>> platform_set_drvdata(pdev, exynos_pcie); >>>>>> return 0; >>>>>> >>>>>> -fail_bus_clk: >>>>>> - clk_disable_unprepare(exynos_pcie->bus_clk); >>>>>> -fail_clk: >>>>>> - clk_disable_unprepare(exynos_pcie->clk); >>>>>> +fail_probe: >>>>>> + if (exynos_pcie->ops && exynos_pcie->ops->deinit_clk_resources) >>>>>> + exynos_pcie->ops->deinit_clk_resources(exynos_pcie); >>>>>> return ret; >>>>>> } >>>>>> >>>>>> @@ -573,14 +660,15 @@ static int __exit exynos_pcie_remove(struct platform_device *pdev) >>>>>> { >>>>>> struct exynos_pcie *exynos_pcie = platform_get_drvdata(pdev); >>>>>> >>>>>> - clk_disable_unprepare(exynos_pcie->bus_clk); >>>>>> - clk_disable_unprepare(exynos_pcie->clk); >>>>>> + if (exynos_pcie->ops && exynos_pcie->ops->deinit_clk_resources) >>>>>> + exynos_pcie->ops->deinit_clk_resources(exynos_pcie); >>>>>> >>>>>> return 0; >>>>>> } >>>>>> >>>>>> static const struct of_device_id exynos_pcie_of_match[] = { >>>>>> - { .compatible = "samsung,exynos5440-pcie", }, >>>>>> + { .compatible = "samsung,exynos5440-pcie", >>>>>> + .data = &exynos5440_pcie_ops }, >>>>>> {}, >>>>>> }; >>>>>> >>>>>> >>>>> >>>>> >>>>> >>>> >>>> >>> >>> >>> >> >> > > >