Lines Matching +full:pcie +full:- +full:ep
1 // SPDX-License-Identifier: GPL-2.0
3 * PCIe host controller driver for Samsung EXYNOS SoCs
26 #include "pcie-designware.h"
28 #define to_exynos_pcie(x) dev_get_drvdata((x)->dev)
30 /* PCIe ELBI registers */
56 void __iomem *elbi_base; /* DT 0th resource: PCIe CTRL */
76 struct exynos_pcie *ep);
77 int (*get_clk_resources)(struct exynos_pcie *ep);
78 int (*init_clk_resources)(struct exynos_pcie *ep);
79 void (*deinit_clk_resources)(struct exynos_pcie *ep);
83 struct exynos_pcie *ep) in exynos5440_pcie_get_mem_resources() argument
85 struct dw_pcie *pci = ep->pci; in exynos5440_pcie_get_mem_resources()
86 struct device *dev = pci->dev; in exynos5440_pcie_get_mem_resources()
89 ep->mem_res = devm_kzalloc(dev, sizeof(*ep->mem_res), GFP_KERNEL); in exynos5440_pcie_get_mem_resources()
90 if (!ep->mem_res) in exynos5440_pcie_get_mem_resources()
91 return -ENOMEM; in exynos5440_pcie_get_mem_resources()
94 ep->mem_res->elbi_base = devm_ioremap_resource(dev, res); in exynos5440_pcie_get_mem_resources()
95 if (IS_ERR(ep->mem_res->elbi_base)) in exynos5440_pcie_get_mem_resources()
96 return PTR_ERR(ep->mem_res->elbi_base); in exynos5440_pcie_get_mem_resources()
101 static int exynos5440_pcie_get_clk_resources(struct exynos_pcie *ep) in exynos5440_pcie_get_clk_resources() argument
103 struct dw_pcie *pci = ep->pci; in exynos5440_pcie_get_clk_resources()
104 struct device *dev = pci->dev; in exynos5440_pcie_get_clk_resources()
106 ep->clk_res = devm_kzalloc(dev, sizeof(*ep->clk_res), GFP_KERNEL); in exynos5440_pcie_get_clk_resources()
107 if (!ep->clk_res) in exynos5440_pcie_get_clk_resources()
108 return -ENOMEM; in exynos5440_pcie_get_clk_resources()
110 ep->clk_res->clk = devm_clk_get(dev, "pcie"); in exynos5440_pcie_get_clk_resources()
111 if (IS_ERR(ep->clk_res->clk)) { in exynos5440_pcie_get_clk_resources()
112 dev_err(dev, "Failed to get pcie rc clock\n"); in exynos5440_pcie_get_clk_resources()
113 return PTR_ERR(ep->clk_res->clk); in exynos5440_pcie_get_clk_resources()
116 ep->clk_res->bus_clk = devm_clk_get(dev, "pcie_bus"); in exynos5440_pcie_get_clk_resources()
117 if (IS_ERR(ep->clk_res->bus_clk)) { in exynos5440_pcie_get_clk_resources()
118 dev_err(dev, "Failed to get pcie bus clock\n"); in exynos5440_pcie_get_clk_resources()
119 return PTR_ERR(ep->clk_res->bus_clk); in exynos5440_pcie_get_clk_resources()
125 static int exynos5440_pcie_init_clk_resources(struct exynos_pcie *ep) in exynos5440_pcie_init_clk_resources() argument
127 struct dw_pcie *pci = ep->pci; in exynos5440_pcie_init_clk_resources()
128 struct device *dev = pci->dev; in exynos5440_pcie_init_clk_resources()
131 ret = clk_prepare_enable(ep->clk_res->clk); in exynos5440_pcie_init_clk_resources()
133 dev_err(dev, "cannot enable pcie rc clock"); in exynos5440_pcie_init_clk_resources()
137 ret = clk_prepare_enable(ep->clk_res->bus_clk); in exynos5440_pcie_init_clk_resources()
139 dev_err(dev, "cannot enable pcie bus clock"); in exynos5440_pcie_init_clk_resources()
146 clk_disable_unprepare(ep->clk_res->clk); in exynos5440_pcie_init_clk_resources()
151 static void exynos5440_pcie_deinit_clk_resources(struct exynos_pcie *ep) in exynos5440_pcie_deinit_clk_resources() argument
153 clk_disable_unprepare(ep->clk_res->bus_clk); in exynos5440_pcie_deinit_clk_resources()
154 clk_disable_unprepare(ep->clk_res->clk); in exynos5440_pcie_deinit_clk_resources()
174 static void exynos_pcie_sideband_dbi_w_mode(struct exynos_pcie *ep, bool on) in exynos_pcie_sideband_dbi_w_mode() argument
178 val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_ELBI_SLV_AWMISC); in exynos_pcie_sideband_dbi_w_mode()
183 exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_ELBI_SLV_AWMISC); in exynos_pcie_sideband_dbi_w_mode()
186 static void exynos_pcie_sideband_dbi_r_mode(struct exynos_pcie *ep, bool on) in exynos_pcie_sideband_dbi_r_mode() argument
190 val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_ELBI_SLV_ARMISC); in exynos_pcie_sideband_dbi_r_mode()
195 exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_ELBI_SLV_ARMISC); in exynos_pcie_sideband_dbi_r_mode()
198 static void exynos_pcie_assert_core_reset(struct exynos_pcie *ep) in exynos_pcie_assert_core_reset() argument
202 val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_CORE_RESET); in exynos_pcie_assert_core_reset()
204 exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_CORE_RESET); in exynos_pcie_assert_core_reset()
205 exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_PWR_RESET); in exynos_pcie_assert_core_reset()
206 exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_STICKY_RESET); in exynos_pcie_assert_core_reset()
207 exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_NONSTICKY_RESET); in exynos_pcie_assert_core_reset()
210 static void exynos_pcie_deassert_core_reset(struct exynos_pcie *ep) in exynos_pcie_deassert_core_reset() argument
214 val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_CORE_RESET); in exynos_pcie_deassert_core_reset()
217 exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_CORE_RESET); in exynos_pcie_deassert_core_reset()
218 exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_STICKY_RESET); in exynos_pcie_deassert_core_reset()
219 exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_NONSTICKY_RESET); in exynos_pcie_deassert_core_reset()
220 exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_APP_INIT_RESET); in exynos_pcie_deassert_core_reset()
221 exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_APP_INIT_RESET); in exynos_pcie_deassert_core_reset()
224 static void exynos_pcie_assert_reset(struct exynos_pcie *ep) in exynos_pcie_assert_reset() argument
226 struct dw_pcie *pci = ep->pci; in exynos_pcie_assert_reset()
227 struct device *dev = pci->dev; in exynos_pcie_assert_reset()
229 if (ep->reset_gpio >= 0) in exynos_pcie_assert_reset()
230 devm_gpio_request_one(dev, ep->reset_gpio, in exynos_pcie_assert_reset()
234 static int exynos_pcie_establish_link(struct exynos_pcie *ep) in exynos_pcie_establish_link() argument
236 struct dw_pcie *pci = ep->pci; in exynos_pcie_establish_link()
237 struct pcie_port *pp = &pci->pp; in exynos_pcie_establish_link()
238 struct device *dev = pci->dev; in exynos_pcie_establish_link()
245 exynos_pcie_assert_core_reset(ep); in exynos_pcie_establish_link()
247 phy_reset(ep->phy); in exynos_pcie_establish_link()
249 exynos_pcie_writel(ep->mem_res->elbi_base, 1, in exynos_pcie_establish_link()
252 phy_power_on(ep->phy); in exynos_pcie_establish_link()
253 phy_init(ep->phy); in exynos_pcie_establish_link()
255 exynos_pcie_deassert_core_reset(ep); in exynos_pcie_establish_link()
257 exynos_pcie_assert_reset(ep); in exynos_pcie_establish_link()
260 exynos_pcie_writel(ep->mem_res->elbi_base, PCIE_ELBI_LTSSM_ENABLE, in exynos_pcie_establish_link()
267 phy_power_off(ep->phy); in exynos_pcie_establish_link()
268 return -ETIMEDOUT; in exynos_pcie_establish_link()
271 static void exynos_pcie_clear_irq_pulse(struct exynos_pcie *ep) in exynos_pcie_clear_irq_pulse() argument
275 val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_IRQ_PULSE); in exynos_pcie_clear_irq_pulse()
276 exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_PULSE); in exynos_pcie_clear_irq_pulse()
279 static void exynos_pcie_enable_irq_pulse(struct exynos_pcie *ep) in exynos_pcie_enable_irq_pulse() argument
286 exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_EN_PULSE); in exynos_pcie_enable_irq_pulse()
291 struct exynos_pcie *ep = arg; in exynos_pcie_irq_handler() local
293 exynos_pcie_clear_irq_pulse(ep); in exynos_pcie_irq_handler()
297 static void exynos_pcie_msi_init(struct exynos_pcie *ep) in exynos_pcie_msi_init() argument
299 struct dw_pcie *pci = ep->pci; in exynos_pcie_msi_init()
300 struct pcie_port *pp = &pci->pp; in exynos_pcie_msi_init()
306 val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_IRQ_EN_LEVEL); in exynos_pcie_msi_init()
308 exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_EN_LEVEL); in exynos_pcie_msi_init()
311 static void exynos_pcie_enable_interrupts(struct exynos_pcie *ep) in exynos_pcie_enable_interrupts() argument
313 exynos_pcie_enable_irq_pulse(ep); in exynos_pcie_enable_interrupts()
316 exynos_pcie_msi_init(ep); in exynos_pcie_enable_interrupts()
322 struct exynos_pcie *ep = to_exynos_pcie(pci); in exynos_pcie_read_dbi() local
325 exynos_pcie_sideband_dbi_r_mode(ep, true); in exynos_pcie_read_dbi()
327 exynos_pcie_sideband_dbi_r_mode(ep, false); in exynos_pcie_read_dbi()
334 struct exynos_pcie *ep = to_exynos_pcie(pci); in exynos_pcie_write_dbi() local
336 exynos_pcie_sideband_dbi_w_mode(ep, true); in exynos_pcie_write_dbi()
338 exynos_pcie_sideband_dbi_w_mode(ep, false); in exynos_pcie_write_dbi()
345 struct exynos_pcie *ep = to_exynos_pcie(pci); in exynos_pcie_rd_own_conf() local
348 exynos_pcie_sideband_dbi_r_mode(ep, true); in exynos_pcie_rd_own_conf()
349 ret = dw_pcie_read(pci->dbi_base + where, size, val); in exynos_pcie_rd_own_conf()
350 exynos_pcie_sideband_dbi_r_mode(ep, false); in exynos_pcie_rd_own_conf()
358 struct exynos_pcie *ep = to_exynos_pcie(pci); in exynos_pcie_wr_own_conf() local
361 exynos_pcie_sideband_dbi_w_mode(ep, true); in exynos_pcie_wr_own_conf()
362 ret = dw_pcie_write(pci->dbi_base + where, size, val); in exynos_pcie_wr_own_conf()
363 exynos_pcie_sideband_dbi_w_mode(ep, false); in exynos_pcie_wr_own_conf()
369 struct exynos_pcie *ep = to_exynos_pcie(pci); in exynos_pcie_link_up() local
372 val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_ELBI_RDLH_LINKUP); in exynos_pcie_link_up()
382 struct exynos_pcie *ep = to_exynos_pcie(pci); in exynos_pcie_host_init() local
384 exynos_pcie_establish_link(ep); in exynos_pcie_host_init()
385 exynos_pcie_enable_interrupts(ep); in exynos_pcie_host_init()
396 static int __init exynos_add_pcie_port(struct exynos_pcie *ep, in exynos_add_pcie_port() argument
399 struct dw_pcie *pci = ep->pci; in exynos_add_pcie_port()
400 struct pcie_port *pp = &pci->pp; in exynos_add_pcie_port()
401 struct device *dev = &pdev->dev; in exynos_add_pcie_port()
404 pp->irq = platform_get_irq(pdev, 1); in exynos_add_pcie_port()
405 if (pp->irq < 0) { in exynos_add_pcie_port()
407 return pp->irq; in exynos_add_pcie_port()
409 ret = devm_request_irq(dev, pp->irq, exynos_pcie_irq_handler, in exynos_add_pcie_port()
410 IRQF_SHARED, "exynos-pcie", ep); in exynos_add_pcie_port()
417 pp->msi_irq = platform_get_irq(pdev, 0); in exynos_add_pcie_port()
418 if (pp->msi_irq < 0) { in exynos_add_pcie_port()
420 return pp->msi_irq; in exynos_add_pcie_port()
424 pp->ops = &exynos_pcie_host_ops; in exynos_add_pcie_port()
443 struct device *dev = &pdev->dev; in exynos_pcie_probe()
445 struct exynos_pcie *ep; in exynos_pcie_probe() local
446 struct device_node *np = dev->of_node; in exynos_pcie_probe()
449 ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL); in exynos_pcie_probe()
450 if (!ep) in exynos_pcie_probe()
451 return -ENOMEM; in exynos_pcie_probe()
455 return -ENOMEM; in exynos_pcie_probe()
457 pci->dev = dev; in exynos_pcie_probe()
458 pci->ops = &dw_pcie_ops; in exynos_pcie_probe()
460 ep->pci = pci; in exynos_pcie_probe()
461 ep->ops = (const struct exynos_pcie_ops *) in exynos_pcie_probe()
464 ep->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); in exynos_pcie_probe()
466 ep->phy = devm_of_phy_get(dev, np, NULL); in exynos_pcie_probe()
467 if (IS_ERR(ep->phy)) { in exynos_pcie_probe()
468 if (PTR_ERR(ep->phy) != -ENODEV) in exynos_pcie_probe()
469 return PTR_ERR(ep->phy); in exynos_pcie_probe()
471 ep->phy = NULL; in exynos_pcie_probe()
474 if (ep->ops && ep->ops->get_mem_resources) { in exynos_pcie_probe()
475 ret = ep->ops->get_mem_resources(pdev, ep); in exynos_pcie_probe()
480 if (ep->ops && ep->ops->get_clk_resources && in exynos_pcie_probe()
481 ep->ops->init_clk_resources) { in exynos_pcie_probe()
482 ret = ep->ops->get_clk_resources(ep); in exynos_pcie_probe()
485 ret = ep->ops->init_clk_resources(ep); in exynos_pcie_probe()
490 platform_set_drvdata(pdev, ep); in exynos_pcie_probe()
492 ret = exynos_add_pcie_port(ep, pdev); in exynos_pcie_probe()
499 phy_exit(ep->phy); in exynos_pcie_probe()
501 if (ep->ops && ep->ops->deinit_clk_resources) in exynos_pcie_probe()
502 ep->ops->deinit_clk_resources(ep); in exynos_pcie_probe()
508 struct exynos_pcie *ep = platform_get_drvdata(pdev); in exynos_pcie_remove() local
510 if (ep->ops && ep->ops->deinit_clk_resources) in exynos_pcie_remove()
511 ep->ops->deinit_clk_resources(ep); in exynos_pcie_remove()
518 .compatible = "samsung,exynos5440-pcie",
527 .name = "exynos-pcie",
532 /* Exynos PCIe driver does not allow module unload */