]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/pci/host/pci-dra7xx.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
[karo-tx-linux.git] / drivers / pci / host / pci-dra7xx.c
1 /*
2  * pcie-dra7xx - PCIe controller driver for TI DRA7xx SoCs
3  *
4  * Copyright (C) 2013-2014 Texas Instruments Incorporated - http://www.ti.com
5  *
6  * Authors: Kishon Vijay Abraham I <kishon@ti.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12
13 #include <linux/delay.h>
14 #include <linux/err.h>
15 #include <linux/interrupt.h>
16 #include <linux/irq.h>
17 #include <linux/irqdomain.h>
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <linux/of_gpio.h>
21 #include <linux/pci.h>
22 #include <linux/phy/phy.h>
23 #include <linux/platform_device.h>
24 #include <linux/pm_runtime.h>
25 #include <linux/resource.h>
26 #include <linux/types.h>
27
28 #include "pcie-designware.h"
29
30 /* PCIe controller wrapper DRA7XX configuration registers */
31
32 #define PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN             0x0024
33 #define PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MAIN         0x0028
34 #define ERR_SYS                                         BIT(0)
35 #define ERR_FATAL                                       BIT(1)
36 #define ERR_NONFATAL                                    BIT(2)
37 #define ERR_COR                                         BIT(3)
38 #define ERR_AXI                                         BIT(4)
39 #define ERR_ECRC                                        BIT(5)
40 #define PME_TURN_OFF                                    BIT(8)
41 #define PME_TO_ACK                                      BIT(9)
42 #define PM_PME                                          BIT(10)
43 #define LINK_REQ_RST                                    BIT(11)
44 #define LINK_UP_EVT                                     BIT(12)
45 #define CFG_BME_EVT                                     BIT(13)
46 #define CFG_MSE_EVT                                     BIT(14)
47 #define INTERRUPTS (ERR_SYS | ERR_FATAL | ERR_NONFATAL | ERR_COR | ERR_AXI | \
48                         ERR_ECRC | PME_TURN_OFF | PME_TO_ACK | PM_PME | \
49                         LINK_REQ_RST | LINK_UP_EVT | CFG_BME_EVT | CFG_MSE_EVT)
50
51 #define PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI              0x0034
52 #define PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MSI          0x0038
53 #define INTA                                            BIT(0)
54 #define INTB                                            BIT(1)
55 #define INTC                                            BIT(2)
56 #define INTD                                            BIT(3)
57 #define MSI                                             BIT(4)
58 #define LEG_EP_INTERRUPTS (INTA | INTB | INTC | INTD)
59
60 #define PCIECTRL_DRA7XX_CONF_DEVICE_CMD                 0x0104
61 #define LTSSM_EN                                        0x1
62
63 #define PCIECTRL_DRA7XX_CONF_PHY_CS                     0x010C
64 #define LINK_UP                                         BIT(16)
65
66 struct dra7xx_pcie {
67         void __iomem            *base;
68         struct phy              **phy;
69         int                     phy_count;
70         struct device           *dev;
71         struct pcie_port        pp;
72 };
73
74 #define to_dra7xx_pcie(x)       container_of((x), struct dra7xx_pcie, pp)
75
76 static inline u32 dra7xx_pcie_readl(struct dra7xx_pcie *pcie, u32 offset)
77 {
78         return readl(pcie->base + offset);
79 }
80
81 static inline void dra7xx_pcie_writel(struct dra7xx_pcie *pcie, u32 offset,
82                                       u32 value)
83 {
84         writel(value, pcie->base + offset);
85 }
86
87 static inline u32 dra7xx_pcie_readl_rc(struct pcie_port *pp, u32 offset)
88 {
89         return readl(pp->dbi_base + offset);
90 }
91
92 static inline void dra7xx_pcie_writel_rc(struct pcie_port *pp, u32 offset,
93                                          u32 value)
94 {
95         writel(value, pp->dbi_base + offset);
96 }
97
98 static int dra7xx_pcie_link_up(struct pcie_port *pp)
99 {
100         struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp);
101         u32 reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_PHY_CS);
102
103         return !!(reg & LINK_UP);
104 }
105
106 static int dra7xx_pcie_establish_link(struct pcie_port *pp)
107 {
108         struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp);
109         u32 reg;
110         unsigned int retries;
111
112         if (dw_pcie_link_up(pp)) {
113                 dev_err(pp->dev, "link is already up\n");
114                 return 0;
115         }
116
117         reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD);
118         reg |= LTSSM_EN;
119         dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg);
120
121         for (retries = 0; retries < 1000; retries++) {
122                 if (dw_pcie_link_up(pp))
123                         return 0;
124                 usleep_range(10, 20);
125         }
126
127         dev_err(pp->dev, "link is not up\n");
128         return -EINVAL;
129 }
130
131 static void dra7xx_pcie_enable_interrupts(struct pcie_port *pp)
132 {
133         struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp);
134
135         dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN,
136                            ~INTERRUPTS);
137         dra7xx_pcie_writel(dra7xx,
138                            PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MAIN, INTERRUPTS);
139         dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI,
140                            ~LEG_EP_INTERRUPTS & ~MSI);
141
142         if (IS_ENABLED(CONFIG_PCI_MSI))
143                 dra7xx_pcie_writel(dra7xx,
144                                    PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MSI, MSI);
145         else
146                 dra7xx_pcie_writel(dra7xx,
147                                    PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MSI,
148                                    LEG_EP_INTERRUPTS);
149 }
150
151 static void dra7xx_pcie_host_init(struct pcie_port *pp)
152 {
153         dw_pcie_setup_rc(pp);
154         dra7xx_pcie_establish_link(pp);
155         if (IS_ENABLED(CONFIG_PCI_MSI))
156                 dw_pcie_msi_init(pp);
157         dra7xx_pcie_enable_interrupts(pp);
158 }
159
160 static struct pcie_host_ops dra7xx_pcie_host_ops = {
161         .link_up = dra7xx_pcie_link_up,
162         .host_init = dra7xx_pcie_host_init,
163 };
164
165 static int dra7xx_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
166                                 irq_hw_number_t hwirq)
167 {
168         irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
169         irq_set_chip_data(irq, domain->host_data);
170
171         return 0;
172 }
173
174 static const struct irq_domain_ops intx_domain_ops = {
175         .map = dra7xx_pcie_intx_map,
176 };
177
178 static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp)
179 {
180         struct device *dev = pp->dev;
181         struct device_node *node = dev->of_node;
182         struct device_node *pcie_intc_node =  of_get_next_child(node, NULL);
183
184         if (!pcie_intc_node) {
185                 dev_err(dev, "No PCIe Intc node found\n");
186                 return PTR_ERR(pcie_intc_node);
187         }
188
189         pp->irq_domain = irq_domain_add_linear(pcie_intc_node, 4,
190                                                &intx_domain_ops, pp);
191         if (!pp->irq_domain) {
192                 dev_err(dev, "Failed to get a INTx IRQ domain\n");
193                 return PTR_ERR(pp->irq_domain);
194         }
195
196         return 0;
197 }
198
199 static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)
200 {
201         struct pcie_port *pp = arg;
202         struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp);
203         u32 reg;
204
205         reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI);
206
207         switch (reg) {
208         case MSI:
209                 dw_handle_msi_irq(pp);
210                 break;
211         case INTA:
212         case INTB:
213         case INTC:
214         case INTD:
215                 generic_handle_irq(irq_find_mapping(pp->irq_domain, ffs(reg)));
216                 break;
217         }
218
219         dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI, reg);
220
221         return IRQ_HANDLED;
222 }
223
224
225 static irqreturn_t dra7xx_pcie_irq_handler(int irq, void *arg)
226 {
227         struct dra7xx_pcie *dra7xx = arg;
228         u32 reg;
229
230         reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN);
231
232         if (reg & ERR_SYS)
233                 dev_dbg(dra7xx->dev, "System Error\n");
234
235         if (reg & ERR_FATAL)
236                 dev_dbg(dra7xx->dev, "Fatal Error\n");
237
238         if (reg & ERR_NONFATAL)
239                 dev_dbg(dra7xx->dev, "Non Fatal Error\n");
240
241         if (reg & ERR_COR)
242                 dev_dbg(dra7xx->dev, "Correctable Error\n");
243
244         if (reg & ERR_AXI)
245                 dev_dbg(dra7xx->dev, "AXI tag lookup fatal Error\n");
246
247         if (reg & ERR_ECRC)
248                 dev_dbg(dra7xx->dev, "ECRC Error\n");
249
250         if (reg & PME_TURN_OFF)
251                 dev_dbg(dra7xx->dev,
252                         "Power Management Event Turn-Off message received\n");
253
254         if (reg & PME_TO_ACK)
255                 dev_dbg(dra7xx->dev,
256                         "Power Management Turn-Off Ack message received\n");
257
258         if (reg & PM_PME)
259                 dev_dbg(dra7xx->dev,
260                         "PM Power Management Event message received\n");
261
262         if (reg & LINK_REQ_RST)
263                 dev_dbg(dra7xx->dev, "Link Request Reset\n");
264
265         if (reg & LINK_UP_EVT)
266                 dev_dbg(dra7xx->dev, "Link-up state change\n");
267
268         if (reg & CFG_BME_EVT)
269                 dev_dbg(dra7xx->dev, "CFG 'Bus Master Enable' change\n");
270
271         if (reg & CFG_MSE_EVT)
272                 dev_dbg(dra7xx->dev, "CFG 'Memory Space Enable' change\n");
273
274         dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN, reg);
275
276         return IRQ_HANDLED;
277 }
278
279 static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
280                                        struct platform_device *pdev)
281 {
282         int ret;
283         struct pcie_port *pp;
284         struct resource *res;
285         struct device *dev = &pdev->dev;
286
287         pp = &dra7xx->pp;
288         pp->dev = dev;
289         pp->ops = &dra7xx_pcie_host_ops;
290
291         pp->irq = platform_get_irq(pdev, 1);
292         if (pp->irq < 0) {
293                 dev_err(dev, "missing IRQ resource\n");
294                 return -EINVAL;
295         }
296
297         ret = devm_request_irq(&pdev->dev, pp->irq,
298                                dra7xx_pcie_msi_irq_handler, IRQF_SHARED,
299                                "dra7-pcie-msi", pp);
300         if (ret) {
301                 dev_err(&pdev->dev, "failed to request irq\n");
302                 return ret;
303         }
304
305         if (!IS_ENABLED(CONFIG_PCI_MSI)) {
306                 ret = dra7xx_pcie_init_irq_domain(pp);
307                 if (ret < 0)
308                         return ret;
309         }
310
311         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbics");
312         pp->dbi_base = devm_ioremap(dev, res->start, resource_size(res));
313         if (!pp->dbi_base)
314                 return -ENOMEM;
315
316         ret = dw_pcie_host_init(pp);
317         if (ret) {
318                 dev_err(dra7xx->dev, "failed to initialize host\n");
319                 return ret;
320         }
321
322         return 0;
323 }
324
325 static int __init dra7xx_pcie_probe(struct platform_device *pdev)
326 {
327         u32 reg;
328         int ret;
329         int irq;
330         int i;
331         int phy_count;
332         struct phy **phy;
333         void __iomem *base;
334         struct resource *res;
335         struct dra7xx_pcie *dra7xx;
336         struct device *dev = &pdev->dev;
337         struct device_node *np = dev->of_node;
338         char name[10];
339         int gpio_sel;
340         enum of_gpio_flags flags;
341         unsigned long gpio_flags;
342
343         dra7xx = devm_kzalloc(dev, sizeof(*dra7xx), GFP_KERNEL);
344         if (!dra7xx)
345                 return -ENOMEM;
346
347         irq = platform_get_irq(pdev, 0);
348         if (irq < 0) {
349                 dev_err(dev, "missing IRQ resource\n");
350                 return -EINVAL;
351         }
352
353         ret = devm_request_irq(dev, irq, dra7xx_pcie_irq_handler,
354                                IRQF_SHARED, "dra7xx-pcie-main", dra7xx);
355         if (ret) {
356                 dev_err(dev, "failed to request irq\n");
357                 return ret;
358         }
359
360         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ti_conf");
361         base = devm_ioremap_nocache(dev, res->start, resource_size(res));
362         if (!base)
363                 return -ENOMEM;
364
365         phy_count = of_property_count_strings(np, "phy-names");
366         if (phy_count < 0) {
367                 dev_err(dev, "unable to find the strings\n");
368                 return phy_count;
369         }
370
371         phy = devm_kzalloc(dev, sizeof(*phy) * phy_count, GFP_KERNEL);
372         if (!phy)
373                 return -ENOMEM;
374
375         for (i = 0; i < phy_count; i++) {
376                 snprintf(name, sizeof(name), "pcie-phy%d", i);
377                 phy[i] = devm_phy_get(dev, name);
378                 if (IS_ERR(phy[i]))
379                         return PTR_ERR(phy[i]);
380
381                 ret = phy_init(phy[i]);
382                 if (ret < 0)
383                         goto err_phy;
384
385                 ret = phy_power_on(phy[i]);
386                 if (ret < 0) {
387                         phy_exit(phy[i]);
388                         goto err_phy;
389                 }
390         }
391
392         dra7xx->base = base;
393         dra7xx->phy = phy;
394         dra7xx->dev = dev;
395         dra7xx->phy_count = phy_count;
396
397         pm_runtime_enable(dev);
398         ret = pm_runtime_get_sync(dev);
399         if (ret < 0) {
400                 dev_err(dev, "pm_runtime_get_sync failed\n");
401                 goto err_get_sync;
402         }
403
404         gpio_sel = of_get_gpio_flags(dev->of_node, 0, &flags);
405         if (gpio_is_valid(gpio_sel)) {
406                 gpio_flags = (flags & OF_GPIO_ACTIVE_LOW) ?
407                                 GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH;
408                 ret = devm_gpio_request_one(dev, gpio_sel, gpio_flags,
409                                             "pcie_reset");
410                 if (ret) {
411                         dev_err(&pdev->dev, "gpio%d request failed, ret %d\n",
412                                 gpio_sel, ret);
413                         goto err_gpio;
414                 }
415         } else if (gpio_sel == -EPROBE_DEFER) {
416                 ret = -EPROBE_DEFER;
417                 goto err_gpio;
418         }
419
420         reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD);
421         reg &= ~LTSSM_EN;
422         dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg);
423
424         platform_set_drvdata(pdev, dra7xx);
425
426         ret = dra7xx_add_pcie_port(dra7xx, pdev);
427         if (ret < 0)
428                 goto err_gpio;
429
430         return 0;
431
432 err_gpio:
433         pm_runtime_put(dev);
434
435 err_get_sync:
436         pm_runtime_disable(dev);
437
438 err_phy:
439         while (--i >= 0) {
440                 phy_power_off(phy[i]);
441                 phy_exit(phy[i]);
442         }
443
444         return ret;
445 }
446
447 static int __exit dra7xx_pcie_remove(struct platform_device *pdev)
448 {
449         struct dra7xx_pcie *dra7xx = platform_get_drvdata(pdev);
450         struct pcie_port *pp = &dra7xx->pp;
451         struct device *dev = &pdev->dev;
452         int count = dra7xx->phy_count;
453
454         if (pp->irq_domain)
455                 irq_domain_remove(pp->irq_domain);
456         pm_runtime_put(dev);
457         pm_runtime_disable(dev);
458         while (count--) {
459                 phy_power_off(dra7xx->phy[count]);
460                 phy_exit(dra7xx->phy[count]);
461         }
462
463         return 0;
464 }
465
466 #ifdef CONFIG_PM_SLEEP
467 static int dra7xx_pcie_suspend(struct device *dev)
468 {
469         struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev);
470         struct pcie_port *pp = &dra7xx->pp;
471         u32 val;
472
473         /* clear MSE */
474         val = dra7xx_pcie_readl_rc(pp, PCI_COMMAND);
475         val &= ~PCI_COMMAND_MEMORY;
476         dra7xx_pcie_writel_rc(pp, PCI_COMMAND, val);
477
478         return 0;
479 }
480
481 static int dra7xx_pcie_resume(struct device *dev)
482 {
483         struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev);
484         struct pcie_port *pp = &dra7xx->pp;
485         u32 val;
486
487         /* set MSE */
488         val = dra7xx_pcie_readl_rc(pp, PCI_COMMAND);
489         val |= PCI_COMMAND_MEMORY;
490         dra7xx_pcie_writel_rc(pp, PCI_COMMAND, val);
491
492         return 0;
493 }
494
495 static int dra7xx_pcie_suspend_noirq(struct device *dev)
496 {
497         struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev);
498         int count = dra7xx->phy_count;
499
500         while (count--) {
501                 phy_power_off(dra7xx->phy[count]);
502                 phy_exit(dra7xx->phy[count]);
503         }
504
505         return 0;
506 }
507
508 static int dra7xx_pcie_resume_noirq(struct device *dev)
509 {
510         struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev);
511         int phy_count = dra7xx->phy_count;
512         int ret;
513         int i;
514
515         for (i = 0; i < phy_count; i++) {
516                 ret = phy_init(dra7xx->phy[i]);
517                 if (ret < 0)
518                         goto err_phy;
519
520                 ret = phy_power_on(dra7xx->phy[i]);
521                 if (ret < 0) {
522                         phy_exit(dra7xx->phy[i]);
523                         goto err_phy;
524                 }
525         }
526
527         return 0;
528
529 err_phy:
530         while (--i >= 0) {
531                 phy_power_off(dra7xx->phy[i]);
532                 phy_exit(dra7xx->phy[i]);
533         }
534
535         return ret;
536 }
537 #endif
538
539 static const struct dev_pm_ops dra7xx_pcie_pm_ops = {
540         SET_SYSTEM_SLEEP_PM_OPS(dra7xx_pcie_suspend, dra7xx_pcie_resume)
541         SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(dra7xx_pcie_suspend_noirq,
542                                       dra7xx_pcie_resume_noirq)
543 };
544
545 static const struct of_device_id of_dra7xx_pcie_match[] = {
546         { .compatible = "ti,dra7-pcie", },
547         {},
548 };
549 MODULE_DEVICE_TABLE(of, of_dra7xx_pcie_match);
550
551 static struct platform_driver dra7xx_pcie_driver = {
552         .remove         = __exit_p(dra7xx_pcie_remove),
553         .driver = {
554                 .name   = "dra7-pcie",
555                 .of_match_table = of_dra7xx_pcie_match,
556                 .pm     = &dra7xx_pcie_pm_ops,
557         },
558 };
559
560 module_platform_driver_probe(dra7xx_pcie_driver, dra7xx_pcie_probe);
561
562 MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
563 MODULE_DESCRIPTION("TI PCIe controller driver");
564 MODULE_LICENSE("GPL v2");