ipq806x: enable QCE hardware crypto inside the kernel
[oweals/openwrt.git] / target / linux / ipq806x / patches-4.9 / 0071-pcie-qcom-fixes.patch
1 --- a/drivers/pci/host/pcie-qcom.c
2 +++ b/drivers/pci/host/pcie-qcom.c
3 @@ -36,8 +36,50 @@
4  
5  #include "pcie-designware.h"
6  
7 +/* DBI registers */
8 +#define PCIE20_AXI_MSTR_RESP_COMP_CTRL0                0x818
9 +#define PCIE20_AXI_MSTR_RESP_COMP_CTRL1                0x81c
10 +
11 +#define PCIE20_PLR_IATU_VIEWPORT               0x900
12 +#define PCIE20_PLR_IATU_REGION_OUTBOUND                (0x0 << 31)
13 +#define PCIE20_PLR_IATU_REGION_INDEX(x)                (x << 0)
14 +
15 +#define PCIE20_PLR_IATU_CTRL1                  0x904
16 +#define PCIE20_PLR_IATU_TYPE_CFG0              (0x4 << 0)
17 +#define PCIE20_PLR_IATU_TYPE_MEM               (0x0 << 0)
18 +
19 +#define PCIE20_PLR_IATU_CTRL2                  0x908
20 +#define PCIE20_PLR_IATU_ENABLE                 BIT(31)
21 +
22 +#define PCIE20_PLR_IATU_LBAR                   0x90C
23 +#define PCIE20_PLR_IATU_UBAR                   0x910
24 +#define PCIE20_PLR_IATU_LAR                    0x914
25 +#define PCIE20_PLR_IATU_LTAR                   0x918
26 +#define PCIE20_PLR_IATU_UTAR                   0x91c
27 +
28 +#define MSM_PCIE_DEV_CFG_ADDR                  0x01000000
29 +
30 +/* PARF registers */
31 +#define PCIE20_PARF_PCS_DEEMPH                 0x34
32 +#define PCS_DEEMPH_TX_DEEMPH_GEN1(x)           (x << 16)
33 +#define PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(x)     (x << 8)
34 +#define PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(x)       (x << 0)
35 +
36 +#define PCIE20_PARF_PCS_SWING                  0x38
37 +#define PCS_SWING_TX_SWING_FULL(x)             (x << 8)
38 +#define PCS_SWING_TX_SWING_LOW(x)              (x << 0)
39 +
40  #define PCIE20_PARF_PHY_CTRL                   0x40
41 +#define PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK      (0x1f << 16)
42 +#define PHY_CTRL_PHY_TX0_TERM_OFFSET(x)                (x << 16)
43 +
44  #define PCIE20_PARF_PHY_REFCLK                 0x4C
45 +#define REF_SSP_EN                             BIT(16)
46 +#define REF_USE_PAD                            BIT(12)
47 +
48 +#define PCIE20_PARF_CONFIG_BITS                        0x50
49 +#define PHY_RX0_EQ(x)                          (x << 24)
50 +
51  #define PCIE20_PARF_DBI_BASE_ADDR              0x168
52  #define PCIE20_PARF_SLV_ADDR_SPACE_SIZE                0x16c
53  #define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT      0x178
54 @@ -53,14 +95,18 @@ struct qcom_pcie_resources_v0 {
55         struct clk *iface_clk;
56         struct clk *core_clk;
57         struct clk *phy_clk;
58 +       struct clk *aux_clk;
59 +       struct clk *ref_clk;
60         struct reset_control *pci_reset;
61         struct reset_control *axi_reset;
62         struct reset_control *ahb_reset;
63         struct reset_control *por_reset;
64         struct reset_control *phy_reset;
65 +       struct reset_control *ext_reset;
66         struct regulator *vdda;
67         struct regulator *vdda_phy;
68         struct regulator *vdda_refclk;
69 +       uint8_t phy_tx0_term_offset;
70  };
71  
72  struct qcom_pcie_resources_v1 {
73 @@ -82,6 +128,7 @@ struct qcom_pcie;
74  struct qcom_pcie_ops {
75         int (*get_resources)(struct qcom_pcie *pcie);
76         int (*init)(struct qcom_pcie *pcie);
77 +       void (*configure)(struct qcom_pcie *pcie);
78         void (*deinit)(struct qcom_pcie *pcie);
79  };
80  
81 @@ -160,6 +207,14 @@ static int qcom_pcie_get_resources_v0(st
82         if (IS_ERR(res->phy_clk))
83                 return PTR_ERR(res->phy_clk);
84  
85 +       res->aux_clk = devm_clk_get(dev, "aux");
86 +       if (IS_ERR(res->aux_clk))
87 +               return PTR_ERR(res->aux_clk);
88 +
89 +       res->ref_clk = devm_clk_get(dev, "ref");
90 +       if (IS_ERR(res->ref_clk))
91 +               return PTR_ERR(res->ref_clk);
92 +
93         res->pci_reset = devm_reset_control_get(dev, "pci");
94         if (IS_ERR(res->pci_reset))
95                 return PTR_ERR(res->pci_reset);
96 @@ -180,6 +235,14 @@ static int qcom_pcie_get_resources_v0(st
97         if (IS_ERR(res->phy_reset))
98                 return PTR_ERR(res->phy_reset);
99  
100 +       res->ext_reset = devm_reset_control_get(dev, "ext");
101 +       if (IS_ERR(res->ext_reset))
102 +               return PTR_ERR(res->ext_reset);
103 +
104 +       if (of_property_read_u8(dev->of_node, "phy-tx0-term-offset",
105 +                               &res->phy_tx0_term_offset))
106 +               res->phy_tx0_term_offset = 0;
107 +
108         return 0;
109  }
110  
111 @@ -223,15 +286,69 @@ static void qcom_pcie_deinit_v0(struct q
112         reset_control_assert(res->axi_reset);
113         reset_control_assert(res->ahb_reset);
114         reset_control_assert(res->por_reset);
115 -       reset_control_assert(res->pci_reset);
116 +       reset_control_assert(res->phy_reset);
117 +       reset_control_assert(res->ext_reset);
118         clk_disable_unprepare(res->iface_clk);
119         clk_disable_unprepare(res->core_clk);
120         clk_disable_unprepare(res->phy_clk);
121 +       clk_disable_unprepare(res->aux_clk);
122 +       clk_disable_unprepare(res->ref_clk);
123         regulator_disable(res->vdda);
124         regulator_disable(res->vdda_phy);
125         regulator_disable(res->vdda_refclk);
126  }
127  
128 +static void qcom_pcie_prog_viewport_cfg0(struct qcom_pcie *pcie, u32 busdev)
129 +{
130 +       struct pcie_port *pp = &pcie->pp;
131 +
132 +       /*
133 +        * program and enable address translation region 0 (device config
134 +        * address space); region type config;
135 +        * axi config address range to device config address range
136 +        */
137 +       writel(PCIE20_PLR_IATU_REGION_OUTBOUND |
138 +              PCIE20_PLR_IATU_REGION_INDEX(0),
139 +              pcie->pp.dbi_base + PCIE20_PLR_IATU_VIEWPORT);
140 +
141 +       writel(PCIE20_PLR_IATU_TYPE_CFG0, pcie->pp.dbi_base + PCIE20_PLR_IATU_CTRL1);
142 +       writel(PCIE20_PLR_IATU_ENABLE, pcie->pp.dbi_base + PCIE20_PLR_IATU_CTRL2);
143 +       writel(pp->cfg0_base, pcie->pp.dbi_base + PCIE20_PLR_IATU_LBAR);
144 +       writel((pp->cfg0_base >> 32), pcie->pp.dbi_base + PCIE20_PLR_IATU_UBAR);
145 +       writel((pp->cfg0_base + pp->cfg0_size - 1),
146 +              pcie->pp.dbi_base + PCIE20_PLR_IATU_LAR);
147 +       writel(busdev, pcie->pp.dbi_base + PCIE20_PLR_IATU_LTAR);
148 +       writel(0, pcie->pp.dbi_base + PCIE20_PLR_IATU_UTAR);
149 +}
150 +
151 +static void qcom_pcie_prog_viewport_mem2_outbound(struct qcom_pcie *pcie)
152 +{
153 +       struct pcie_port *pp = &pcie->pp;
154 +
155 +       /*
156 +        * program and enable address translation region 2 (device resource
157 +        * address space); region type memory;
158 +        * axi device bar address range to device bar address range
159 +        */
160 +       writel(PCIE20_PLR_IATU_REGION_OUTBOUND |
161 +              PCIE20_PLR_IATU_REGION_INDEX(2),
162 +              pcie->pp.dbi_base + PCIE20_PLR_IATU_VIEWPORT);
163 +
164 +       writel(PCIE20_PLR_IATU_TYPE_MEM, pcie->pp.dbi_base + PCIE20_PLR_IATU_CTRL1);
165 +       writel(PCIE20_PLR_IATU_ENABLE, pcie->pp.dbi_base + PCIE20_PLR_IATU_CTRL2);
166 +       writel(pp->mem_base, pcie->pp.dbi_base + PCIE20_PLR_IATU_LBAR);
167 +       writel((pp->mem_base >> 32), pcie->pp.dbi_base + PCIE20_PLR_IATU_UBAR);
168 +       writel(pp->mem_base + pp->mem_size - 1,
169 +              pcie->pp.dbi_base + PCIE20_PLR_IATU_LAR);
170 +       writel(pp->mem_bus_addr, pcie->pp.dbi_base + PCIE20_PLR_IATU_LTAR);
171 +       writel(upper_32_bits(pp->mem_bus_addr),
172 +              pcie->pp.dbi_base + PCIE20_PLR_IATU_UTAR);
173 +
174 +       /* 256B PCIE buffer setting */
175 +       writel(0x1, pcie->pp.dbi_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL0);
176 +       writel(0x1, pcie->pp.dbi_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL1);
177 +}
178 +
179  static int qcom_pcie_init_v0(struct qcom_pcie *pcie)
180  {
181         struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
182 @@ -260,13 +377,19 @@ static int qcom_pcie_init_v0(struct qcom
183         ret = reset_control_assert(res->ahb_reset);
184         if (ret) {
185                 dev_err(dev, "cannot assert ahb reset\n");
186 -               goto err_assert_ahb;
187 +               goto err_assert_reset;
188 +       }
189 +
190 +       ret = reset_control_deassert(res->ext_reset);
191 +       if (ret) {
192 +               dev_err(dev, "cannot deassert ext reset\n");
193 +               goto err_assert_reset;
194         }
195  
196         ret = clk_prepare_enable(res->iface_clk);
197         if (ret) {
198                 dev_err(dev, "cannot prepare/enable iface clock\n");
199 -               goto err_assert_ahb;
200 +               goto err_assert_reset;
201         }
202  
203         ret = clk_prepare_enable(res->phy_clk);
204 @@ -281,22 +404,53 @@ static int qcom_pcie_init_v0(struct qcom
205                 goto err_clk_core;
206         }
207  
208 +       ret = clk_prepare_enable(res->aux_clk);
209 +       if (ret) {
210 +               dev_err(dev, "cannot prepare/enable aux clock\n");
211 +               goto err_clk_aux;
212 +       }
213 +
214 +       ret = clk_prepare_enable(res->ref_clk);
215 +       if (ret) {
216 +               dev_err(dev, "cannot prepare/enable ref clock\n");
217 +               goto err_clk_ref;
218 +       }
219 +
220         ret = reset_control_deassert(res->ahb_reset);
221         if (ret) {
222                 dev_err(dev, "cannot deassert ahb reset\n");
223                 goto err_deassert_ahb;
224         }
225 +       udelay(1);
226  
227         /* enable PCIe clocks and resets */
228         val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
229         val &= ~BIT(0);
230         writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);
231  
232 -       /* enable external reference clock */
233 +       /* Set Tx termination offset */
234 +       val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
235 +       val &= ~PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK;
236 +       val |= PHY_CTRL_PHY_TX0_TERM_OFFSET(res->phy_tx0_term_offset);
237 +       writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);
238 +
239 +       /* PARF programming */
240 +       writel(PCS_DEEMPH_TX_DEEMPH_GEN1(0x18) |
241 +              PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(0x18) |
242 +              PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(0x22),
243 +              pcie->parf + PCIE20_PARF_PCS_DEEMPH);
244 +       writel(PCS_SWING_TX_SWING_FULL(0x78) |
245 +              PCS_SWING_TX_SWING_LOW(0x78),
246 +              pcie->parf + PCIE20_PARF_PCS_SWING);
247 +       writel(PHY_RX0_EQ(0x4), pcie->parf + PCIE20_PARF_CONFIG_BITS);
248 +
249 +       /* Enable reference clock */
250         val = readl(pcie->parf + PCIE20_PARF_PHY_REFCLK);
251 -       val |= BIT(16);
252 +       val &= ~REF_USE_PAD;
253 +       val |= REF_SSP_EN;
254         writel(val, pcie->parf + PCIE20_PARF_PHY_REFCLK);
255  
256 +       /* De-assert PHY, PCIe, POR and AXI resets */
257         ret = reset_control_deassert(res->phy_reset);
258         if (ret) {
259                 dev_err(dev, "cannot deassert phy reset\n");
260 @@ -327,12 +481,16 @@ static int qcom_pcie_init_v0(struct qcom
261         return 0;
262  
263  err_deassert_ahb:
264 +       clk_disable_unprepare(res->ref_clk);
265 +err_clk_ref:
266 +       clk_disable_unprepare(res->aux_clk);
267 +err_clk_aux:
268         clk_disable_unprepare(res->core_clk);
269  err_clk_core:
270         clk_disable_unprepare(res->phy_clk);
271  err_clk_phy:
272         clk_disable_unprepare(res->iface_clk);
273 -err_assert_ahb:
274 +err_assert_reset:
275         regulator_disable(res->vdda_phy);
276  err_vdda_phy:
277         regulator_disable(res->vdda_refclk);
278 @@ -342,6 +500,12 @@ err_refclk:
279         return ret;
280  }
281  
282 +static void qcom_pcie_configure_v0(struct qcom_pcie *pcie)
283 +{
284 +       qcom_pcie_prog_viewport_cfg0(pcie, MSM_PCIE_DEV_CFG_ADDR);
285 +       qcom_pcie_prog_viewport_mem2_outbound(pcie);
286 +}
287 +
288  static void qcom_pcie_deinit_v1(struct qcom_pcie *pcie)
289  {
290         struct qcom_pcie_resources_v1 *res = &pcie->res.v1;
291 @@ -455,6 +619,9 @@ static void qcom_pcie_host_init(struct p
292         if (ret)
293                 goto err;
294  
295 +       if (pcie->ops->init)
296 +               pcie->ops->init(pcie);
297 +
298         return;
299  err:
300         qcom_ep_reset_assert(pcie);
301 @@ -486,6 +653,7 @@ static struct pcie_host_ops qcom_pcie_dw
302  static const struct qcom_pcie_ops ops_v0 = {
303         .get_resources = qcom_pcie_get_resources_v0,
304         .init = qcom_pcie_init_v0,
305 +       .configure = qcom_pcie_configure_v0,
306         .deinit = qcom_pcie_deinit_v0,
307  };
308