fd597e5737bd11e72f182429ec02a7b14fa15632
[lede.git] / target / linux / layerscape / patches-4.4 / 8138-pci-layerscape-add-MSI-interrupt-support.patch
1 From b0e74277164b17bb0d207ffe16056e13e558f6ba Mon Sep 17 00:00:00 2001
2 From: Zhao Qiang <qiang.zhao@nxp.com>
3 Date: Tue, 11 Oct 2016 16:25:07 +0800
4 Subject: [PATCH 138/141] pci-layerscape: add MSI interrupt support
5
6 Signed-off-by: Zhao Qiang <qiang.zhao@nxp.com>
7 ---
8  drivers/iommu/amd_iommu.c         |    5 +++--
9  drivers/iommu/arm-smmu.c          |   21 ++++++++++++++++++
10  drivers/iommu/iommu.c             |    8 +++----
11  drivers/pci/host/pci-layerscape.c |   43 +++++++++++++++++++++++++++++++++++++
12  drivers/pci/host/pci-layerscape.h |   17 +++++++++++++++
13  drivers/pci/quirks.c              |   19 +++++++++-------
14  drivers/pci/search.c              |    5 ++---
15  include/linux/pci.h               |    6 +++---
16  8 files changed, 104 insertions(+), 20 deletions(-)
17  create mode 100644 drivers/pci/host/pci-layerscape.h
18
19 --- a/drivers/iommu/amd_iommu.c
20 +++ b/drivers/iommu/amd_iommu.c
21 @@ -222,8 +222,9 @@ static u16 get_alias(struct device *dev)
22          */
23         if (pci_alias == devid &&
24             PCI_BUS_NUM(ivrs_alias) == pdev->bus->number) {
25 -               pdev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN;
26 -               pdev->dma_alias_devfn = ivrs_alias & 0xff;
27 +               pdev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVID;
28 +               pdev->dma_alias_devid = PCI_DEVID(pdev->bus->number,
29 +                                                 ivrs_alias & 0xff);
30                 pr_info("AMD-Vi: Added PCI DMA alias %02x.%d for %s\n",
31                         PCI_SLOT(ivrs_alias), PCI_FUNC(ivrs_alias),
32                         dev_name(dev));
33 --- a/drivers/iommu/arm-smmu.c
34 +++ b/drivers/iommu/arm-smmu.c
35 @@ -45,6 +45,10 @@
36  
37  #include <linux/amba/bus.h>
38  
39 +#ifdef CONFIG_PCI_LAYERSCAPE
40 +#include <../drivers/pci/host/pci-layerscape.h>
41 +#endif
42 +
43  #include "io-pgtable.h"
44  
45  /* Maximum number of stream IDs assigned to a single device */
46 @@ -1352,6 +1356,23 @@ static int arm_smmu_init_platform_device
47  static int arm_smmu_add_device(struct device *dev)
48  {
49         struct iommu_group *group;
50 +#ifdef CONFIG_PCI_LAYERSCAPE
51 +       u16 sid;
52 +       u32 streamid;
53 +       struct pci_dev *pdev;
54 +       if (dev_is_pci(dev)) {
55 +               pdev = to_pci_dev(dev);
56 +
57 +               pci_for_each_dma_alias(pdev, __arm_smmu_get_pci_sid, &sid);
58 +               streamid = set_pcie_streamid_translation(pdev, sid);
59 +               if (~streamid == 0) {
60 +                       return -ENODEV;
61 +               }
62 +
63 +               pdev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVID;
64 +               pdev->dma_alias_devid = streamid;
65 +       }
66 +#endif
67  
68         group = iommu_group_get_for_dev(dev);
69         if (IS_ERR(group))
70 --- a/drivers/iommu/iommu.c
71 +++ b/drivers/iommu/iommu.c
72 @@ -686,10 +686,10 @@ static struct iommu_group *get_pci_alias
73                         continue;
74  
75                 /* We alias them or they alias us */
76 -               if (((pdev->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVFN) &&
77 -                    pdev->dma_alias_devfn == tmp->devfn) ||
78 -                   ((tmp->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVFN) &&
79 -                    tmp->dma_alias_devfn == pdev->devfn)) {
80 +               if (((pdev->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVID) &&
81 +                    (pdev->dma_alias_devid & 0xff) == tmp->devfn) ||
82 +                   ((tmp->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVID) &&
83 +                    (tmp->dma_alias_devid & 0xff) == pdev->devfn)) {
84  
85                         group = get_pci_alias_group(tmp, devfns);
86                         if (group) {
87 --- a/drivers/pci/host/pci-layerscape.c
88 +++ b/drivers/pci/host/pci-layerscape.c
89 @@ -37,6 +37,11 @@
90  
91  /* PEX LUT registers */
92  #define PCIE_LUT_DBG           0x7FC /* PEX LUT Debug Register */
93 +#define PCIE_LUT_UDR(n)                (0x800 + (n) * 8)
94 +#define PCIE_LUT_LDR(n)                (0x804 + (n) * 8)
95 +#define PCIE_LUT_MASK_ALL      0xffff
96 +#define PCIE_LUT_DR_NUM                32
97 +#define PCIE_LUT_ENABLE                (1 << 31)
98  
99  struct ls_pcie_drvdata {
100         u32 lut_offset;
101 @@ -52,10 +57,30 @@ struct ls_pcie {
102         struct pcie_port pp;
103         const struct ls_pcie_drvdata *drvdata;
104         int index;
105 +       const u32 *avail_streamids;
106 +       int streamid_index;
107  };
108  
109  #define to_ls_pcie(x)  container_of(x, struct ls_pcie, pp)
110  
111 +u32 set_pcie_streamid_translation(struct pci_dev *pdev, u32 devid)
112 +{
113 +       u32 index, streamid;
114 +       struct pcie_port *pp = pdev->bus->sysdata;
115 +       struct ls_pcie *pcie = to_ls_pcie(pp);
116 +
117 +       if (!pcie->avail_streamids || !pcie->streamid_index)
118 +               return ~(u32)0;
119 +
120 +       index = --pcie->streamid_index;
121 +       /* mask is set as all zeroes, want to match all bits */
122 +       iowrite32((devid << 16), pcie->lut + PCIE_LUT_UDR(index));
123 +       streamid = be32_to_cpup(&pcie->avail_streamids[index]);
124 +       iowrite32(streamid | PCIE_LUT_ENABLE, pcie->lut + PCIE_LUT_LDR(index));
125 +
126 +       return streamid;
127 +}
128 +
129  static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
130  {
131         u32 header_type;
132 @@ -283,10 +308,28 @@ static int __init ls_pcie_probe(struct p
133  
134         pcie->drvdata = match->data;
135         pcie->lut = pcie->dbi + pcie->drvdata->lut_offset;
136 +       /* Disable LDR zero */
137 +       iowrite32(0, pcie->lut + PCIE_LUT_LDR(0));
138  
139         if (!ls_pcie_is_bridge(pcie))
140                 return -ENODEV;
141  
142 +       if (of_device_is_compatible(pdev->dev.of_node, "fsl,ls2085a-pcie") ||
143 +       of_device_is_compatible(pdev->dev.of_node, "fsl,ls2080a-pcie") ||
144 +       of_device_is_compatible(pdev->dev.of_node, "fsl,ls1088a-pcie")) {
145 +               int len;
146 +               const u32 *prop;
147 +               struct device_node *np;
148 +
149 +               np = pdev->dev.of_node;
150 +               prop = (u32 *)of_get_property(np, "available-stream-ids", &len);
151 +               if (prop) {
152 +                       pcie->avail_streamids = prop;
153 +                       pcie->streamid_index = len/sizeof(u32);
154 +               } else
155 +                       dev_err(&pdev->dev, "PCIe endpoint partitioning not possible\n");
156 +       }
157 +
158         ret = ls_add_pcie_port(&pcie->pp, pdev);
159         if (ret < 0)
160                 return ret;
161 --- /dev/null
162 +++ b/drivers/pci/host/pci-layerscape.h
163 @@ -0,0 +1,17 @@
164 +/*
165 + * Copyright (C) 2015 Freescale Semiconductor.
166 + *
167 + * Author: Varun Sethi <Varun.Sethi@freescale.com>
168 + *
169 + * This program is free software; you can redistribute it and/or modify
170 + * it under the terms of the GNU General Public License version 2 as
171 + * published by the Free Software Foundation.
172 + */
173 +
174 +#ifndef _PCI_LAYERSCAPE_H
175 +#define _PCI_LAYERSCAPE_H
176 +
177 +/* function for setting up stream id to device id translation */
178 +u32 set_pcie_streamid_translation(struct pci_dev *pdev, u32 devid);
179 +
180 +#endif /* _PCI_LAYERSCAPE_H */
181 --- a/drivers/pci/quirks.c
182 +++ b/drivers/pci/quirks.c
183 @@ -3589,8 +3589,9 @@ int pci_dev_specific_reset(struct pci_de
184  static void quirk_dma_func0_alias(struct pci_dev *dev)
185  {
186         if (PCI_FUNC(dev->devfn) != 0) {
187 -               dev->dma_alias_devfn = PCI_DEVFN(PCI_SLOT(dev->devfn), 0);
188 -               dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN;
189 +               dev->dma_alias_devid = PCI_DEVID(dev->bus->number,
190 +                                      PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
191 +               dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVID;
192         }
193  }
194  
195 @@ -3605,8 +3606,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_R
196  static void quirk_dma_func1_alias(struct pci_dev *dev)
197  {
198         if (PCI_FUNC(dev->devfn) != 1) {
199 -               dev->dma_alias_devfn = PCI_DEVFN(PCI_SLOT(dev->devfn), 1);
200 -               dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN;
201 +               dev->dma_alias_devid = PCI_DEVID(dev->bus->number,
202 +                                      PCI_DEVFN(PCI_SLOT(dev->devfn), 1));
203 +               dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVID;
204         }
205  }
206  
207 @@ -3670,11 +3672,12 @@ static void quirk_fixed_dma_alias(struct
208  
209         id = pci_match_id(fixed_dma_alias_tbl, dev);
210         if (id) {
211 -               dev->dma_alias_devfn = id->driver_data;
212 -               dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN;
213 +               dev->dma_alias_devid = PCI_DEVID(dev->bus->number,
214 +                                                id->driver_data);
215 +               dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVID;
216                 dev_info(&dev->dev, "Enabling fixed DMA alias to %02x.%d\n",
217 -                        PCI_SLOT(dev->dma_alias_devfn),
218 -                        PCI_FUNC(dev->dma_alias_devfn));
219 +                        PCI_SLOT(dev->dma_alias_devid),
220 +                        PCI_FUNC(dev->dma_alias_devid));
221         }
222  }
223  
224 --- a/drivers/pci/search.c
225 +++ b/drivers/pci/search.c
226 @@ -40,9 +40,8 @@ int pci_for_each_dma_alias(struct pci_de
227          * If the device is broken and uses an alias requester ID for
228          * DMA, iterate over that too.
229          */
230 -       if (unlikely(pdev->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVFN)) {
231 -               ret = fn(pdev, PCI_DEVID(pdev->bus->number,
232 -                                        pdev->dma_alias_devfn), data);
233 +       if (unlikely(pdev->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVID)) {
234 +               ret = fn(pdev, pdev->dma_alias_devid, data);
235                 if (ret)
236                         return ret;
237         }
238 --- a/include/linux/pci.h
239 +++ b/include/linux/pci.h
240 @@ -172,8 +172,8 @@ enum pci_dev_flags {
241         PCI_DEV_FLAGS_ASSIGNED = (__force pci_dev_flags_t) (1 << 2),
242         /* Flag for quirk use to store if quirk-specific ACS is enabled */
243         PCI_DEV_FLAGS_ACS_ENABLED_QUIRK = (__force pci_dev_flags_t) (1 << 3),
244 -       /* Flag to indicate the device uses dma_alias_devfn */
245 -       PCI_DEV_FLAGS_DMA_ALIAS_DEVFN = (__force pci_dev_flags_t) (1 << 4),
246 +       /* Flag to indicate the device uses dma_alias_devid */
247 +       PCI_DEV_FLAGS_DMA_ALIAS_DEVID = (__force pci_dev_flags_t) (1 << 4),
248         /* Use a PCIe-to-PCI bridge alias even if !pci_is_pcie */
249         PCI_DEV_FLAG_PCIE_BRIDGE_ALIAS = (__force pci_dev_flags_t) (1 << 5),
250         /* Do not use bus resets for device */
251 @@ -279,7 +279,7 @@ struct pci_dev {
252         u8              rom_base_reg;   /* which config register controls the ROM */
253         u8              pin;            /* which interrupt pin this device uses */
254         u16             pcie_flags_reg; /* cached PCIe Capabilities Register */
255 -       u8              dma_alias_devfn;/* devfn of DMA alias, if any */
256 +       u32             dma_alias_devid;/* devid of DMA alias */
257  
258         struct pci_driver *driver;      /* which driver has allocated this device */
259         u64             dma_mask;       /* Mask of the bits of bus address this