aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/controller/dwc/pci-exynos.c
diff options
context:
space:
mode:
authorShawn Lin <shawn.lin@rock-chips.com>2018-05-30 21:12:37 -0400
committerBjorn Helgaas <bhelgaas@google.com>2018-06-08 08:50:11 -0400
commit6e0832fa432ec99c94caee733c8f5851cf85560b (patch)
treec4326f9e2d8ff1a6cb17e959fc5268c9e577ca94 /drivers/pci/controller/dwc/pci-exynos.c
parent3a3869f1c443383ef8354ffa0e5fb8df65d8b549 (diff)
PCI: Collect all native drivers under drivers/pci/controller/
Native PCI drivers for root complex devices were originally all in drivers/pci/host/. Some of these devices can also be operated in endpoint mode. Drivers for endpoint mode didn't seem to fit in the "host" directory, so we put both the root complex and endpoint drivers in per-device directories, e.g., drivers/pci/dwc/, drivers/pci/cadence/, etc. These per-device directories contain trivial Kconfig and Makefiles and clutter drivers/pci/. Make a new drivers/pci/controllers/ directory and collect all the device-specific drivers there. No functional change intended. Link: https://lkml.kernel.org/r/1520304202-232891-1-git-send-email-shawn.lin@rock-chips.com Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com> [bhelgaas: changelog] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/controller/dwc/pci-exynos.c')
-rw-r--r--drivers/pci/controller/dwc/pci-exynos.c539
1 files changed, 539 insertions, 0 deletions
diff --git a/drivers/pci/controller/dwc/pci-exynos.c b/drivers/pci/controller/dwc/pci-exynos.c
new file mode 100644
index 000000000000..4cc1e5df8c79
--- /dev/null
+++ b/drivers/pci/controller/dwc/pci-exynos.c
@@ -0,0 +1,539 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * PCIe host controller driver for Samsung EXYNOS SoCs
4 *
5 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
6 * http://www.samsung.com
7 *
8 * Author: Jingoo Han <jg1.han@samsung.com>
9 */
10
11#include <linux/clk.h>
12#include <linux/delay.h>
13#include <linux/gpio.h>
14#include <linux/interrupt.h>
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/of_device.h>
18#include <linux/of_gpio.h>
19#include <linux/pci.h>
20#include <linux/platform_device.h>
21#include <linux/phy/phy.h>
22#include <linux/resource.h>
23#include <linux/signal.h>
24#include <linux/types.h>
25
26#include "pcie-designware.h"
27
28#define to_exynos_pcie(x) dev_get_drvdata((x)->dev)
29
30/* PCIe ELBI registers */
31#define PCIE_IRQ_PULSE 0x000
32#define IRQ_INTA_ASSERT BIT(0)
33#define IRQ_INTB_ASSERT BIT(2)
34#define IRQ_INTC_ASSERT BIT(4)
35#define IRQ_INTD_ASSERT BIT(6)
36#define PCIE_IRQ_LEVEL 0x004
37#define PCIE_IRQ_SPECIAL 0x008
38#define PCIE_IRQ_EN_PULSE 0x00c
39#define PCIE_IRQ_EN_LEVEL 0x010
40#define IRQ_MSI_ENABLE BIT(2)
41#define PCIE_IRQ_EN_SPECIAL 0x014
42#define PCIE_PWR_RESET 0x018
43#define PCIE_CORE_RESET 0x01c
44#define PCIE_CORE_RESET_ENABLE BIT(0)
45#define PCIE_STICKY_RESET 0x020
46#define PCIE_NONSTICKY_RESET 0x024
47#define PCIE_APP_INIT_RESET 0x028
48#define PCIE_APP_LTSSM_ENABLE 0x02c
49#define PCIE_ELBI_RDLH_LINKUP 0x064
50#define PCIE_ELBI_LTSSM_ENABLE 0x1
51#define PCIE_ELBI_SLV_AWMISC 0x11c
52#define PCIE_ELBI_SLV_ARMISC 0x120
53#define PCIE_ELBI_SLV_DBI_ENABLE BIT(21)
54
55struct exynos_pcie_mem_res {
56 void __iomem *elbi_base; /* DT 0th resource: PCIe CTRL */
57};
58
59struct exynos_pcie_clk_res {
60 struct clk *clk;
61 struct clk *bus_clk;
62};
63
64struct exynos_pcie {
65 struct dw_pcie *pci;
66 struct exynos_pcie_mem_res *mem_res;
67 struct exynos_pcie_clk_res *clk_res;
68 const struct exynos_pcie_ops *ops;
69 int reset_gpio;
70
71 struct phy *phy;
72};
73
74struct exynos_pcie_ops {
75 int (*get_mem_resources)(struct platform_device *pdev,
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);
80};
81
82static int exynos5440_pcie_get_mem_resources(struct platform_device *pdev,
83 struct exynos_pcie *ep)
84{
85 struct dw_pcie *pci = ep->pci;
86 struct device *dev = pci->dev;
87 struct resource *res;
88
89 ep->mem_res = devm_kzalloc(dev, sizeof(*ep->mem_res), GFP_KERNEL);
90 if (!ep->mem_res)
91 return -ENOMEM;
92
93 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
94 ep->mem_res->elbi_base = devm_ioremap_resource(dev, res);
95 if (IS_ERR(ep->mem_res->elbi_base))
96 return PTR_ERR(ep->mem_res->elbi_base);
97
98 return 0;
99}
100
101static int exynos5440_pcie_get_clk_resources(struct exynos_pcie *ep)
102{
103 struct dw_pcie *pci = ep->pci;
104 struct device *dev = pci->dev;
105
106 ep->clk_res = devm_kzalloc(dev, sizeof(*ep->clk_res), GFP_KERNEL);
107 if (!ep->clk_res)
108 return -ENOMEM;
109
110 ep->clk_res->clk = devm_clk_get(dev, "pcie");
111 if (IS_ERR(ep->clk_res->clk)) {
112 dev_err(dev, "Failed to get pcie rc clock\n");
113 return PTR_ERR(ep->clk_res->clk);
114 }
115
116 ep->clk_res->bus_clk = devm_clk_get(dev, "pcie_bus");
117 if (IS_ERR(ep->clk_res->bus_clk)) {
118 dev_err(dev, "Failed to get pcie bus clock\n");
119 return PTR_ERR(ep->clk_res->bus_clk);
120 }
121
122 return 0;
123}
124
125static int exynos5440_pcie_init_clk_resources(struct exynos_pcie *ep)
126{
127 struct dw_pcie *pci = ep->pci;
128 struct device *dev = pci->dev;
129 int ret;
130
131 ret = clk_prepare_enable(ep->clk_res->clk);
132 if (ret) {
133 dev_err(dev, "cannot enable pcie rc clock");
134 return ret;
135 }
136
137 ret = clk_prepare_enable(ep->clk_res->bus_clk);
138 if (ret) {
139 dev_err(dev, "cannot enable pcie bus clock");
140 goto err_bus_clk;
141 }
142
143 return 0;
144
145err_bus_clk:
146 clk_disable_unprepare(ep->clk_res->clk);
147
148 return ret;
149}
150
151static void exynos5440_pcie_deinit_clk_resources(struct exynos_pcie *ep)
152{
153 clk_disable_unprepare(ep->clk_res->bus_clk);
154 clk_disable_unprepare(ep->clk_res->clk);
155}
156
157static const struct exynos_pcie_ops exynos5440_pcie_ops = {
158 .get_mem_resources = exynos5440_pcie_get_mem_resources,
159 .get_clk_resources = exynos5440_pcie_get_clk_resources,
160 .init_clk_resources = exynos5440_pcie_init_clk_resources,
161 .deinit_clk_resources = exynos5440_pcie_deinit_clk_resources,
162};
163
164static void exynos_pcie_writel(void __iomem *base, u32 val, u32 reg)
165{
166 writel(val, base + reg);
167}
168
169static u32 exynos_pcie_readl(void __iomem *base, u32 reg)
170{
171 return readl(base + reg);
172}
173
174static void exynos_pcie_sideband_dbi_w_mode(struct exynos_pcie *ep, bool on)
175{
176 u32 val;
177
178 val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_ELBI_SLV_AWMISC);
179 if (on)
180 val |= PCIE_ELBI_SLV_DBI_ENABLE;
181 else
182 val &= ~PCIE_ELBI_SLV_DBI_ENABLE;
183 exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_ELBI_SLV_AWMISC);
184}
185
186static void exynos_pcie_sideband_dbi_r_mode(struct exynos_pcie *ep, bool on)
187{
188 u32 val;
189
190 val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_ELBI_SLV_ARMISC);
191 if (on)
192 val |= PCIE_ELBI_SLV_DBI_ENABLE;
193 else
194 val &= ~PCIE_ELBI_SLV_DBI_ENABLE;
195 exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_ELBI_SLV_ARMISC);
196}
197
198static void exynos_pcie_assert_core_reset(struct exynos_pcie *ep)
199{
200 u32 val;
201
202 val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_CORE_RESET);
203 val &= ~PCIE_CORE_RESET_ENABLE;
204 exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_CORE_RESET);
205 exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_PWR_RESET);
206 exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_STICKY_RESET);
207 exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_NONSTICKY_RESET);
208}
209
210static void exynos_pcie_deassert_core_reset(struct exynos_pcie *ep)
211{
212 u32 val;
213
214 val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_CORE_RESET);
215 val |= PCIE_CORE_RESET_ENABLE;
216
217 exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_CORE_RESET);
218 exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_STICKY_RESET);
219 exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_NONSTICKY_RESET);
220 exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_APP_INIT_RESET);
221 exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_APP_INIT_RESET);
222}
223
224static void exynos_pcie_assert_reset(struct exynos_pcie *ep)
225{
226 struct dw_pcie *pci = ep->pci;
227 struct device *dev = pci->dev;
228
229 if (ep->reset_gpio >= 0)
230 devm_gpio_request_one(dev, ep->reset_gpio,
231 GPIOF_OUT_INIT_HIGH, "RESET");
232}
233
234static int exynos_pcie_establish_link(struct exynos_pcie *ep)
235{
236 struct dw_pcie *pci = ep->pci;
237 struct pcie_port *pp = &pci->pp;
238 struct device *dev = pci->dev;
239
240 if (dw_pcie_link_up(pci)) {
241 dev_err(dev, "Link already up\n");
242 return 0;
243 }
244
245 exynos_pcie_assert_core_reset(ep);
246
247 phy_reset(ep->phy);
248
249 exynos_pcie_writel(ep->mem_res->elbi_base, 1,
250 PCIE_PWR_RESET);
251
252 phy_power_on(ep->phy);
253 phy_init(ep->phy);
254
255 exynos_pcie_deassert_core_reset(ep);
256 dw_pcie_setup_rc(pp);
257 exynos_pcie_assert_reset(ep);
258
259 /* assert LTSSM enable */
260 exynos_pcie_writel(ep->mem_res->elbi_base, PCIE_ELBI_LTSSM_ENABLE,
261 PCIE_APP_LTSSM_ENABLE);
262
263 /* check if the link is up or not */
264 if (!dw_pcie_wait_for_link(pci))
265 return 0;
266
267 phy_power_off(ep->phy);
268 return -ETIMEDOUT;
269}
270
271static void exynos_pcie_clear_irq_pulse(struct exynos_pcie *ep)
272{
273 u32 val;
274
275 val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_IRQ_PULSE);
276 exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_PULSE);
277}
278
279static void exynos_pcie_enable_irq_pulse(struct exynos_pcie *ep)
280{
281 u32 val;
282
283 /* enable INTX interrupt */
284 val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT |
285 IRQ_INTC_ASSERT | IRQ_INTD_ASSERT;
286 exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_EN_PULSE);
287}
288
289static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg)
290{
291 struct exynos_pcie *ep = arg;
292
293 exynos_pcie_clear_irq_pulse(ep);
294 return IRQ_HANDLED;
295}
296
297static void exynos_pcie_msi_init(struct exynos_pcie *ep)
298{
299 struct dw_pcie *pci = ep->pci;
300 struct pcie_port *pp = &pci->pp;
301 u32 val;
302
303 dw_pcie_msi_init(pp);
304
305 /* enable MSI interrupt */
306 val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_IRQ_EN_LEVEL);
307 val |= IRQ_MSI_ENABLE;
308 exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_EN_LEVEL);
309}
310
311static void exynos_pcie_enable_interrupts(struct exynos_pcie *ep)
312{
313 exynos_pcie_enable_irq_pulse(ep);
314
315 if (IS_ENABLED(CONFIG_PCI_MSI))
316 exynos_pcie_msi_init(ep);
317}
318
319static u32 exynos_pcie_read_dbi(struct dw_pcie *pci, void __iomem *base,
320 u32 reg, size_t size)
321{
322 struct exynos_pcie *ep = to_exynos_pcie(pci);
323 u32 val;
324
325 exynos_pcie_sideband_dbi_r_mode(ep, true);
326 dw_pcie_read(base + reg, size, &val);
327 exynos_pcie_sideband_dbi_r_mode(ep, false);
328 return val;
329}
330
331static void exynos_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base,
332 u32 reg, size_t size, u32 val)
333{
334 struct exynos_pcie *ep = to_exynos_pcie(pci);
335
336 exynos_pcie_sideband_dbi_w_mode(ep, true);
337 dw_pcie_write(base + reg, size, val);
338 exynos_pcie_sideband_dbi_w_mode(ep, false);
339}
340
341static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
342 u32 *val)
343{
344 struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
345 struct exynos_pcie *ep = to_exynos_pcie(pci);
346 int ret;
347
348 exynos_pcie_sideband_dbi_r_mode(ep, true);
349 ret = dw_pcie_read(pci->dbi_base + where, size, val);
350 exynos_pcie_sideband_dbi_r_mode(ep, false);
351 return ret;
352}
353
354static int exynos_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,
355 u32 val)
356{
357 struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
358 struct exynos_pcie *ep = to_exynos_pcie(pci);
359 int ret;
360
361 exynos_pcie_sideband_dbi_w_mode(ep, true);
362 ret = dw_pcie_write(pci->dbi_base + where, size, val);
363 exynos_pcie_sideband_dbi_w_mode(ep, false);
364 return ret;
365}
366
367static int exynos_pcie_link_up(struct dw_pcie *pci)
368{
369 struct exynos_pcie *ep = to_exynos_pcie(pci);
370 u32 val;
371
372 val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_ELBI_RDLH_LINKUP);
373 if (val == PCIE_ELBI_LTSSM_ENABLE)
374 return 1;
375
376 return 0;
377}
378
379static int exynos_pcie_host_init(struct pcie_port *pp)
380{
381 struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
382 struct exynos_pcie *ep = to_exynos_pcie(pci);
383
384 exynos_pcie_establish_link(ep);
385 exynos_pcie_enable_interrupts(ep);
386
387 return 0;
388}
389
390static const struct dw_pcie_host_ops exynos_pcie_host_ops = {
391 .rd_own_conf = exynos_pcie_rd_own_conf,
392 .wr_own_conf = exynos_pcie_wr_own_conf,
393 .host_init = exynos_pcie_host_init,
394};
395
396static int __init exynos_add_pcie_port(struct exynos_pcie *ep,
397 struct platform_device *pdev)
398{
399 struct dw_pcie *pci = ep->pci;
400 struct pcie_port *pp = &pci->pp;
401 struct device *dev = &pdev->dev;
402 int ret;
403
404 pp->irq = platform_get_irq(pdev, 1);
405 if (pp->irq < 0) {
406 dev_err(dev, "failed to get irq\n");
407 return pp->irq;
408 }
409 ret = devm_request_irq(dev, pp->irq, exynos_pcie_irq_handler,
410 IRQF_SHARED, "exynos-pcie", ep);
411 if (ret) {
412 dev_err(dev, "failed to request irq\n");
413 return ret;
414 }
415
416 if (IS_ENABLED(CONFIG_PCI_MSI)) {
417 pp->msi_irq = platform_get_irq(pdev, 0);
418 if (pp->msi_irq < 0) {
419 dev_err(dev, "failed to get msi irq\n");
420 return pp->msi_irq;
421 }
422 }
423
424 pp->root_bus_nr = -1;
425 pp->ops = &exynos_pcie_host_ops;
426
427 ret = dw_pcie_host_init(pp);
428 if (ret) {
429 dev_err(dev, "failed to initialize host\n");
430 return ret;
431 }
432
433 return 0;
434}
435
436static const struct dw_pcie_ops dw_pcie_ops = {
437 .read_dbi = exynos_pcie_read_dbi,
438 .write_dbi = exynos_pcie_write_dbi,
439 .link_up = exynos_pcie_link_up,
440};
441
442static int __init exynos_pcie_probe(struct platform_device *pdev)
443{
444 struct device *dev = &pdev->dev;
445 struct dw_pcie *pci;
446 struct exynos_pcie *ep;
447 struct device_node *np = dev->of_node;
448 int ret;
449
450 ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL);
451 if (!ep)
452 return -ENOMEM;
453
454 pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
455 if (!pci)
456 return -ENOMEM;
457
458 pci->dev = dev;
459 pci->ops = &dw_pcie_ops;
460
461 ep->pci = pci;
462 ep->ops = (const struct exynos_pcie_ops *)
463 of_device_get_match_data(dev);
464
465 ep->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
466
467 ep->phy = devm_of_phy_get(dev, np, NULL);
468 if (IS_ERR(ep->phy)) {
469 if (PTR_ERR(ep->phy) == -EPROBE_DEFER)
470 return PTR_ERR(ep->phy);
471
472 ep->phy = NULL;
473 }
474
475 if (ep->ops && ep->ops->get_mem_resources) {
476 ret = ep->ops->get_mem_resources(pdev, ep);
477 if (ret)
478 return ret;
479 }
480
481 if (ep->ops && ep->ops->get_clk_resources &&
482 ep->ops->init_clk_resources) {
483 ret = ep->ops->get_clk_resources(ep);
484 if (ret)
485 return ret;
486 ret = ep->ops->init_clk_resources(ep);
487 if (ret)
488 return ret;
489 }
490
491 platform_set_drvdata(pdev, ep);
492
493 ret = exynos_add_pcie_port(ep, pdev);
494 if (ret < 0)
495 goto fail_probe;
496
497 return 0;
498
499fail_probe:
500 phy_exit(ep->phy);
501
502 if (ep->ops && ep->ops->deinit_clk_resources)
503 ep->ops->deinit_clk_resources(ep);
504 return ret;
505}
506
507static int __exit exynos_pcie_remove(struct platform_device *pdev)
508{
509 struct exynos_pcie *ep = platform_get_drvdata(pdev);
510
511 if (ep->ops && ep->ops->deinit_clk_resources)
512 ep->ops->deinit_clk_resources(ep);
513
514 return 0;
515}
516
517static const struct of_device_id exynos_pcie_of_match[] = {
518 {
519 .compatible = "samsung,exynos5440-pcie",
520 .data = &exynos5440_pcie_ops
521 },
522 {},
523};
524
525static struct platform_driver exynos_pcie_driver = {
526 .remove = __exit_p(exynos_pcie_remove),
527 .driver = {
528 .name = "exynos-pcie",
529 .of_match_table = exynos_pcie_of_match,
530 },
531};
532
533/* Exynos PCIe driver does not allow module unload */
534
535static int __init exynos_pcie_init(void)
536{
537 return platform_driver_probe(&exynos_pcie_driver, exynos_pcie_probe);
538}
539subsys_initcall(exynos_pcie_init);