.. | .. |
---|
3 | 3 | * PCIe host controller driver for Freescale i.MX6 SoCs |
---|
4 | 4 | * |
---|
5 | 5 | * Copyright (C) 2013 Kosagi |
---|
6 | | - * http://www.kosagi.com |
---|
| 6 | + * https://www.kosagi.com |
---|
7 | 7 | * |
---|
8 | 8 | * Author: Sean Cross <xobs@kosagi.com> |
---|
9 | 9 | */ |
---|
10 | 10 | |
---|
| 11 | +#include <linux/bitfield.h> |
---|
11 | 12 | #include <linux/clk.h> |
---|
12 | 13 | #include <linux/delay.h> |
---|
13 | 14 | #include <linux/gpio.h> |
---|
.. | .. |
---|
18 | 19 | #include <linux/module.h> |
---|
19 | 20 | #include <linux/of_gpio.h> |
---|
20 | 21 | #include <linux/of_device.h> |
---|
| 22 | +#include <linux/of_address.h> |
---|
21 | 23 | #include <linux/pci.h> |
---|
22 | 24 | #include <linux/platform_device.h> |
---|
23 | 25 | #include <linux/regmap.h> |
---|
.. | .. |
---|
27 | 29 | #include <linux/types.h> |
---|
28 | 30 | #include <linux/interrupt.h> |
---|
29 | 31 | #include <linux/reset.h> |
---|
| 32 | +#include <linux/pm_domain.h> |
---|
| 33 | +#include <linux/pm_runtime.h> |
---|
30 | 34 | |
---|
31 | 35 | #include "pcie-designware.h" |
---|
| 36 | + |
---|
| 37 | +#define IMX8MQ_GPR_PCIE_REF_USE_PAD BIT(9) |
---|
| 38 | +#define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN BIT(10) |
---|
| 39 | +#define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE BIT(11) |
---|
| 40 | +#define IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE GENMASK(11, 8) |
---|
| 41 | +#define IMX8MQ_PCIE2_BASE_ADDR 0x33c00000 |
---|
32 | 42 | |
---|
33 | 43 | #define to_imx6_pcie(x) dev_get_drvdata((x)->dev) |
---|
34 | 44 | |
---|
.. | .. |
---|
37 | 47 | IMX6SX, |
---|
38 | 48 | IMX6QP, |
---|
39 | 49 | IMX7D, |
---|
| 50 | + IMX8MQ, |
---|
| 51 | +}; |
---|
| 52 | + |
---|
| 53 | +#define IMX6_PCIE_FLAG_IMX6_PHY BIT(0) |
---|
| 54 | +#define IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE BIT(1) |
---|
| 55 | +#define IMX6_PCIE_FLAG_SUPPORTS_SUSPEND BIT(2) |
---|
| 56 | + |
---|
| 57 | +struct imx6_pcie_drvdata { |
---|
| 58 | + enum imx6_pcie_variants variant; |
---|
| 59 | + u32 flags; |
---|
| 60 | + int dbi_length; |
---|
40 | 61 | }; |
---|
41 | 62 | |
---|
42 | 63 | struct imx6_pcie { |
---|
.. | .. |
---|
47 | 68 | struct clk *pcie_phy; |
---|
48 | 69 | struct clk *pcie_inbound_axi; |
---|
49 | 70 | struct clk *pcie; |
---|
| 71 | + struct clk *pcie_aux; |
---|
50 | 72 | struct regmap *iomuxc_gpr; |
---|
| 73 | + u32 controller_id; |
---|
51 | 74 | struct reset_control *pciephy_reset; |
---|
52 | 75 | struct reset_control *apps_reset; |
---|
53 | | - enum imx6_pcie_variants variant; |
---|
| 76 | + struct reset_control *turnoff_reset; |
---|
54 | 77 | u32 tx_deemph_gen1; |
---|
55 | 78 | u32 tx_deemph_gen2_3p5db; |
---|
56 | 79 | u32 tx_deemph_gen2_6db; |
---|
57 | 80 | u32 tx_swing_full; |
---|
58 | 81 | u32 tx_swing_low; |
---|
59 | | - int link_gen; |
---|
60 | 82 | struct regulator *vpcie; |
---|
| 83 | + void __iomem *phy_base; |
---|
| 84 | + |
---|
| 85 | + /* power domain for pcie */ |
---|
| 86 | + struct device *pd_pcie; |
---|
| 87 | + /* power domain for pcie phy */ |
---|
| 88 | + struct device *pd_pcie_phy; |
---|
| 89 | + const struct imx6_pcie_drvdata *drvdata; |
---|
61 | 90 | }; |
---|
62 | 91 | |
---|
63 | 92 | /* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */ |
---|
64 | | -#define PHY_PLL_LOCK_WAIT_MAX_RETRIES 2000 |
---|
65 | | -#define PHY_PLL_LOCK_WAIT_USLEEP_MIN 50 |
---|
66 | 93 | #define PHY_PLL_LOCK_WAIT_USLEEP_MAX 200 |
---|
67 | | - |
---|
68 | | -/* PCIe Root Complex registers (memory-mapped) */ |
---|
69 | | -#define PCIE_RC_IMX6_MSI_CAP 0x50 |
---|
70 | | -#define PCIE_RC_LCR 0x7c |
---|
71 | | -#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1 0x1 |
---|
72 | | -#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2 0x2 |
---|
73 | | -#define PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK 0xf |
---|
74 | | - |
---|
75 | | -#define PCIE_RC_LCSR 0x80 |
---|
| 94 | +#define PHY_PLL_LOCK_WAIT_TIMEOUT (2000 * PHY_PLL_LOCK_WAIT_USLEEP_MAX) |
---|
76 | 95 | |
---|
77 | 96 | /* PCIe Port Logic registers (memory-mapped) */ |
---|
78 | 97 | #define PL_OFFSET 0x700 |
---|
79 | | -#define PCIE_PL_PFLR (PL_OFFSET + 0x08) |
---|
80 | | -#define PCIE_PL_PFLR_LINK_STATE_MASK (0x3f << 16) |
---|
81 | | -#define PCIE_PL_PFLR_FORCE_LINK (1 << 15) |
---|
82 | | -#define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28) |
---|
83 | | -#define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c) |
---|
84 | 98 | |
---|
85 | 99 | #define PCIE_PHY_CTRL (PL_OFFSET + 0x114) |
---|
86 | | -#define PCIE_PHY_CTRL_DATA_LOC 0 |
---|
87 | | -#define PCIE_PHY_CTRL_CAP_ADR_LOC 16 |
---|
88 | | -#define PCIE_PHY_CTRL_CAP_DAT_LOC 17 |
---|
89 | | -#define PCIE_PHY_CTRL_WR_LOC 18 |
---|
90 | | -#define PCIE_PHY_CTRL_RD_LOC 19 |
---|
| 100 | +#define PCIE_PHY_CTRL_DATA(x) FIELD_PREP(GENMASK(15, 0), (x)) |
---|
| 101 | +#define PCIE_PHY_CTRL_CAP_ADR BIT(16) |
---|
| 102 | +#define PCIE_PHY_CTRL_CAP_DAT BIT(17) |
---|
| 103 | +#define PCIE_PHY_CTRL_WR BIT(18) |
---|
| 104 | +#define PCIE_PHY_CTRL_RD BIT(19) |
---|
91 | 105 | |
---|
92 | 106 | #define PCIE_PHY_STAT (PL_OFFSET + 0x110) |
---|
93 | | -#define PCIE_PHY_STAT_ACK_LOC 16 |
---|
94 | | - |
---|
95 | | -#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C |
---|
96 | | -#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17) |
---|
| 107 | +#define PCIE_PHY_STAT_ACK BIT(16) |
---|
97 | 108 | |
---|
98 | 109 | /* PHY registers (not memory-mapped) */ |
---|
| 110 | +#define PCIE_PHY_ATEOVRD 0x10 |
---|
| 111 | +#define PCIE_PHY_ATEOVRD_EN BIT(2) |
---|
| 112 | +#define PCIE_PHY_ATEOVRD_REF_CLKDIV_SHIFT 0 |
---|
| 113 | +#define PCIE_PHY_ATEOVRD_REF_CLKDIV_MASK 0x1 |
---|
| 114 | + |
---|
| 115 | +#define PCIE_PHY_MPLL_OVRD_IN_LO 0x11 |
---|
| 116 | +#define PCIE_PHY_MPLL_MULTIPLIER_SHIFT 2 |
---|
| 117 | +#define PCIE_PHY_MPLL_MULTIPLIER_MASK 0x7f |
---|
| 118 | +#define PCIE_PHY_MPLL_MULTIPLIER_OVRD BIT(9) |
---|
| 119 | + |
---|
99 | 120 | #define PCIE_PHY_RX_ASIC_OUT 0x100D |
---|
100 | 121 | #define PCIE_PHY_RX_ASIC_OUT_VALID (1 << 0) |
---|
101 | 122 | |
---|
102 | | -#define PHY_RX_OVRD_IN_LO 0x1005 |
---|
103 | | -#define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5) |
---|
104 | | -#define PHY_RX_OVRD_IN_LO_RX_PLL_EN (1 << 3) |
---|
| 123 | +/* iMX7 PCIe PHY registers */ |
---|
| 124 | +#define PCIE_PHY_CMN_REG4 0x14 |
---|
| 125 | +/* These are probably the bits that *aren't* DCC_FB_EN */ |
---|
| 126 | +#define PCIE_PHY_CMN_REG4_DCC_FB_EN 0x29 |
---|
105 | 127 | |
---|
106 | | -static int pcie_phy_poll_ack(struct imx6_pcie *imx6_pcie, int exp_val) |
---|
| 128 | +#define PCIE_PHY_CMN_REG15 0x54 |
---|
| 129 | +#define PCIE_PHY_CMN_REG15_DLY_4 BIT(2) |
---|
| 130 | +#define PCIE_PHY_CMN_REG15_PLL_PD BIT(5) |
---|
| 131 | +#define PCIE_PHY_CMN_REG15_OVRD_PLL_PD BIT(7) |
---|
| 132 | + |
---|
| 133 | +#define PCIE_PHY_CMN_REG24 0x90 |
---|
| 134 | +#define PCIE_PHY_CMN_REG24_RX_EQ BIT(6) |
---|
| 135 | +#define PCIE_PHY_CMN_REG24_RX_EQ_SEL BIT(3) |
---|
| 136 | + |
---|
| 137 | +#define PCIE_PHY_CMN_REG26 0x98 |
---|
| 138 | +#define PCIE_PHY_CMN_REG26_ATT_MODE 0xBC |
---|
| 139 | + |
---|
| 140 | +#define PHY_RX_OVRD_IN_LO 0x1005 |
---|
| 141 | +#define PHY_RX_OVRD_IN_LO_RX_DATA_EN BIT(5) |
---|
| 142 | +#define PHY_RX_OVRD_IN_LO_RX_PLL_EN BIT(3) |
---|
| 143 | + |
---|
| 144 | +static int pcie_phy_poll_ack(struct imx6_pcie *imx6_pcie, bool exp_val) |
---|
107 | 145 | { |
---|
108 | 146 | struct dw_pcie *pci = imx6_pcie->pci; |
---|
109 | | - u32 val; |
---|
| 147 | + bool val; |
---|
110 | 148 | u32 max_iterations = 10; |
---|
111 | 149 | u32 wait_counter = 0; |
---|
112 | 150 | |
---|
113 | 151 | do { |
---|
114 | | - val = dw_pcie_readl_dbi(pci, PCIE_PHY_STAT); |
---|
115 | | - val = (val >> PCIE_PHY_STAT_ACK_LOC) & 0x1; |
---|
| 152 | + val = dw_pcie_readl_dbi(pci, PCIE_PHY_STAT) & |
---|
| 153 | + PCIE_PHY_STAT_ACK; |
---|
116 | 154 | wait_counter++; |
---|
117 | 155 | |
---|
118 | 156 | if (val == exp_val) |
---|
.. | .. |
---|
130 | 168 | u32 val; |
---|
131 | 169 | int ret; |
---|
132 | 170 | |
---|
133 | | - val = addr << PCIE_PHY_CTRL_DATA_LOC; |
---|
| 171 | + val = PCIE_PHY_CTRL_DATA(addr); |
---|
134 | 172 | dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, val); |
---|
135 | 173 | |
---|
136 | | - val |= (0x1 << PCIE_PHY_CTRL_CAP_ADR_LOC); |
---|
| 174 | + val |= PCIE_PHY_CTRL_CAP_ADR; |
---|
137 | 175 | dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, val); |
---|
138 | 176 | |
---|
139 | | - ret = pcie_phy_poll_ack(imx6_pcie, 1); |
---|
| 177 | + ret = pcie_phy_poll_ack(imx6_pcie, true); |
---|
140 | 178 | if (ret) |
---|
141 | 179 | return ret; |
---|
142 | 180 | |
---|
143 | | - val = addr << PCIE_PHY_CTRL_DATA_LOC; |
---|
| 181 | + val = PCIE_PHY_CTRL_DATA(addr); |
---|
144 | 182 | dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, val); |
---|
145 | 183 | |
---|
146 | | - return pcie_phy_poll_ack(imx6_pcie, 0); |
---|
| 184 | + return pcie_phy_poll_ack(imx6_pcie, false); |
---|
147 | 185 | } |
---|
148 | 186 | |
---|
149 | 187 | /* Read from the 16-bit PCIe PHY control registers (not memory-mapped) */ |
---|
150 | | -static int pcie_phy_read(struct imx6_pcie *imx6_pcie, int addr, int *data) |
---|
| 188 | +static int pcie_phy_read(struct imx6_pcie *imx6_pcie, int addr, u16 *data) |
---|
151 | 189 | { |
---|
152 | 190 | struct dw_pcie *pci = imx6_pcie->pci; |
---|
153 | | - u32 val, phy_ctl; |
---|
| 191 | + u32 phy_ctl; |
---|
154 | 192 | int ret; |
---|
155 | 193 | |
---|
156 | 194 | ret = pcie_phy_wait_ack(imx6_pcie, addr); |
---|
.. | .. |
---|
158 | 196 | return ret; |
---|
159 | 197 | |
---|
160 | 198 | /* assert Read signal */ |
---|
161 | | - phy_ctl = 0x1 << PCIE_PHY_CTRL_RD_LOC; |
---|
| 199 | + phy_ctl = PCIE_PHY_CTRL_RD; |
---|
162 | 200 | dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, phy_ctl); |
---|
163 | 201 | |
---|
164 | | - ret = pcie_phy_poll_ack(imx6_pcie, 1); |
---|
| 202 | + ret = pcie_phy_poll_ack(imx6_pcie, true); |
---|
165 | 203 | if (ret) |
---|
166 | 204 | return ret; |
---|
167 | 205 | |
---|
168 | | - val = dw_pcie_readl_dbi(pci, PCIE_PHY_STAT); |
---|
169 | | - *data = val & 0xffff; |
---|
| 206 | + *data = dw_pcie_readl_dbi(pci, PCIE_PHY_STAT); |
---|
170 | 207 | |
---|
171 | 208 | /* deassert Read signal */ |
---|
172 | 209 | dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, 0x00); |
---|
173 | 210 | |
---|
174 | | - return pcie_phy_poll_ack(imx6_pcie, 0); |
---|
| 211 | + return pcie_phy_poll_ack(imx6_pcie, false); |
---|
175 | 212 | } |
---|
176 | 213 | |
---|
177 | | -static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, int data) |
---|
| 214 | +static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, u16 data) |
---|
178 | 215 | { |
---|
179 | 216 | struct dw_pcie *pci = imx6_pcie->pci; |
---|
180 | 217 | u32 var; |
---|
.. | .. |
---|
186 | 223 | if (ret) |
---|
187 | 224 | return ret; |
---|
188 | 225 | |
---|
189 | | - var = data << PCIE_PHY_CTRL_DATA_LOC; |
---|
| 226 | + var = PCIE_PHY_CTRL_DATA(data); |
---|
190 | 227 | dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var); |
---|
191 | 228 | |
---|
192 | 229 | /* capture data */ |
---|
193 | | - var |= (0x1 << PCIE_PHY_CTRL_CAP_DAT_LOC); |
---|
| 230 | + var |= PCIE_PHY_CTRL_CAP_DAT; |
---|
194 | 231 | dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var); |
---|
195 | 232 | |
---|
196 | | - ret = pcie_phy_poll_ack(imx6_pcie, 1); |
---|
| 233 | + ret = pcie_phy_poll_ack(imx6_pcie, true); |
---|
197 | 234 | if (ret) |
---|
198 | 235 | return ret; |
---|
199 | 236 | |
---|
200 | 237 | /* deassert cap data */ |
---|
201 | | - var = data << PCIE_PHY_CTRL_DATA_LOC; |
---|
| 238 | + var = PCIE_PHY_CTRL_DATA(data); |
---|
202 | 239 | dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var); |
---|
203 | 240 | |
---|
204 | 241 | /* wait for ack de-assertion */ |
---|
205 | | - ret = pcie_phy_poll_ack(imx6_pcie, 0); |
---|
| 242 | + ret = pcie_phy_poll_ack(imx6_pcie, false); |
---|
206 | 243 | if (ret) |
---|
207 | 244 | return ret; |
---|
208 | 245 | |
---|
209 | 246 | /* assert wr signal */ |
---|
210 | | - var = 0x1 << PCIE_PHY_CTRL_WR_LOC; |
---|
| 247 | + var = PCIE_PHY_CTRL_WR; |
---|
211 | 248 | dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var); |
---|
212 | 249 | |
---|
213 | 250 | /* wait for ack */ |
---|
214 | | - ret = pcie_phy_poll_ack(imx6_pcie, 1); |
---|
| 251 | + ret = pcie_phy_poll_ack(imx6_pcie, true); |
---|
215 | 252 | if (ret) |
---|
216 | 253 | return ret; |
---|
217 | 254 | |
---|
218 | 255 | /* deassert wr signal */ |
---|
219 | | - var = data << PCIE_PHY_CTRL_DATA_LOC; |
---|
| 256 | + var = PCIE_PHY_CTRL_DATA(data); |
---|
220 | 257 | dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var); |
---|
221 | 258 | |
---|
222 | 259 | /* wait for ack de-assertion */ |
---|
223 | | - ret = pcie_phy_poll_ack(imx6_pcie, 0); |
---|
| 260 | + ret = pcie_phy_poll_ack(imx6_pcie, false); |
---|
224 | 261 | if (ret) |
---|
225 | 262 | return ret; |
---|
226 | 263 | |
---|
.. | .. |
---|
231 | 268 | |
---|
232 | 269 | static void imx6_pcie_reset_phy(struct imx6_pcie *imx6_pcie) |
---|
233 | 270 | { |
---|
234 | | - u32 tmp; |
---|
| 271 | + u16 tmp; |
---|
| 272 | + |
---|
| 273 | + if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_IMX6_PHY)) |
---|
| 274 | + return; |
---|
235 | 275 | |
---|
236 | 276 | pcie_phy_read(imx6_pcie, PHY_RX_OVRD_IN_LO, &tmp); |
---|
237 | 277 | tmp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN | |
---|
.. | .. |
---|
246 | 286 | pcie_phy_write(imx6_pcie, PHY_RX_OVRD_IN_LO, tmp); |
---|
247 | 287 | } |
---|
248 | 288 | |
---|
| 289 | +#ifdef CONFIG_ARM |
---|
249 | 290 | /* Added for PCI abort handling */ |
---|
250 | 291 | static int imx6q_pcie_abort_handler(unsigned long addr, |
---|
251 | 292 | unsigned int fsr, struct pt_regs *regs) |
---|
.. | .. |
---|
279 | 320 | |
---|
280 | 321 | return 1; |
---|
281 | 322 | } |
---|
| 323 | +#endif |
---|
| 324 | + |
---|
| 325 | +static int imx6_pcie_attach_pd(struct device *dev) |
---|
| 326 | +{ |
---|
| 327 | + struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev); |
---|
| 328 | + struct device_link *link; |
---|
| 329 | + |
---|
| 330 | + /* Do nothing when in a single power domain */ |
---|
| 331 | + if (dev->pm_domain) |
---|
| 332 | + return 0; |
---|
| 333 | + |
---|
| 334 | + imx6_pcie->pd_pcie = dev_pm_domain_attach_by_name(dev, "pcie"); |
---|
| 335 | + if (IS_ERR(imx6_pcie->pd_pcie)) |
---|
| 336 | + return PTR_ERR(imx6_pcie->pd_pcie); |
---|
| 337 | + /* Do nothing when power domain missing */ |
---|
| 338 | + if (!imx6_pcie->pd_pcie) |
---|
| 339 | + return 0; |
---|
| 340 | + link = device_link_add(dev, imx6_pcie->pd_pcie, |
---|
| 341 | + DL_FLAG_STATELESS | |
---|
| 342 | + DL_FLAG_PM_RUNTIME | |
---|
| 343 | + DL_FLAG_RPM_ACTIVE); |
---|
| 344 | + if (!link) { |
---|
| 345 | + dev_err(dev, "Failed to add device_link to pcie pd.\n"); |
---|
| 346 | + return -EINVAL; |
---|
| 347 | + } |
---|
| 348 | + |
---|
| 349 | + imx6_pcie->pd_pcie_phy = dev_pm_domain_attach_by_name(dev, "pcie_phy"); |
---|
| 350 | + if (IS_ERR(imx6_pcie->pd_pcie_phy)) |
---|
| 351 | + return PTR_ERR(imx6_pcie->pd_pcie_phy); |
---|
| 352 | + |
---|
| 353 | + link = device_link_add(dev, imx6_pcie->pd_pcie_phy, |
---|
| 354 | + DL_FLAG_STATELESS | |
---|
| 355 | + DL_FLAG_PM_RUNTIME | |
---|
| 356 | + DL_FLAG_RPM_ACTIVE); |
---|
| 357 | + if (!link) { |
---|
| 358 | + dev_err(dev, "Failed to add device_link to pcie_phy pd.\n"); |
---|
| 359 | + return -EINVAL; |
---|
| 360 | + } |
---|
| 361 | + |
---|
| 362 | + return 0; |
---|
| 363 | +} |
---|
282 | 364 | |
---|
283 | 365 | static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie) |
---|
284 | 366 | { |
---|
285 | 367 | struct device *dev = imx6_pcie->pci->dev; |
---|
286 | 368 | |
---|
287 | | - switch (imx6_pcie->variant) { |
---|
| 369 | + switch (imx6_pcie->drvdata->variant) { |
---|
288 | 370 | case IMX7D: |
---|
| 371 | + case IMX8MQ: |
---|
289 | 372 | reset_control_assert(imx6_pcie->pciephy_reset); |
---|
290 | 373 | reset_control_assert(imx6_pcie->apps_reset); |
---|
291 | 374 | break; |
---|
.. | .. |
---|
318 | 401 | dev_err(dev, "failed to disable vpcie regulator: %d\n", |
---|
319 | 402 | ret); |
---|
320 | 403 | } |
---|
| 404 | + |
---|
| 405 | + /* Some boards don't have PCIe reset GPIO. */ |
---|
| 406 | + if (gpio_is_valid(imx6_pcie->reset_gpio)) |
---|
| 407 | + gpio_set_value_cansleep(imx6_pcie->reset_gpio, |
---|
| 408 | + imx6_pcie->gpio_active_high); |
---|
| 409 | +} |
---|
| 410 | + |
---|
| 411 | +static unsigned int imx6_pcie_grp_offset(const struct imx6_pcie *imx6_pcie) |
---|
| 412 | +{ |
---|
| 413 | + WARN_ON(imx6_pcie->drvdata->variant != IMX8MQ); |
---|
| 414 | + return imx6_pcie->controller_id == 1 ? IOMUXC_GPR16 : IOMUXC_GPR14; |
---|
321 | 415 | } |
---|
322 | 416 | |
---|
323 | 417 | static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie) |
---|
324 | 418 | { |
---|
325 | 419 | struct dw_pcie *pci = imx6_pcie->pci; |
---|
326 | 420 | struct device *dev = pci->dev; |
---|
| 421 | + unsigned int offset; |
---|
327 | 422 | int ret = 0; |
---|
328 | 423 | |
---|
329 | | - switch (imx6_pcie->variant) { |
---|
| 424 | + switch (imx6_pcie->drvdata->variant) { |
---|
330 | 425 | case IMX6SX: |
---|
331 | 426 | ret = clk_prepare_enable(imx6_pcie->pcie_inbound_axi); |
---|
332 | 427 | if (ret) { |
---|
.. | .. |
---|
337 | 432 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, |
---|
338 | 433 | IMX6SX_GPR12_PCIE_TEST_POWERDOWN, 0); |
---|
339 | 434 | break; |
---|
340 | | - case IMX6QP: /* FALLTHROUGH */ |
---|
| 435 | + case IMX6QP: |
---|
341 | 436 | case IMX6Q: |
---|
342 | 437 | /* power up core phy and enable ref clock */ |
---|
343 | 438 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, |
---|
.. | .. |
---|
348 | 443 | * reset time is too short, cannot meet the requirement. |
---|
349 | 444 | * add one ~10us delay here. |
---|
350 | 445 | */ |
---|
351 | | - udelay(10); |
---|
| 446 | + usleep_range(10, 100); |
---|
352 | 447 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, |
---|
353 | 448 | IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16); |
---|
354 | 449 | break; |
---|
355 | 450 | case IMX7D: |
---|
| 451 | + break; |
---|
| 452 | + case IMX8MQ: |
---|
| 453 | + ret = clk_prepare_enable(imx6_pcie->pcie_aux); |
---|
| 454 | + if (ret) { |
---|
| 455 | + dev_err(dev, "unable to enable pcie_aux clock\n"); |
---|
| 456 | + break; |
---|
| 457 | + } |
---|
| 458 | + |
---|
| 459 | + offset = imx6_pcie_grp_offset(imx6_pcie); |
---|
| 460 | + /* |
---|
| 461 | + * Set the over ride low and enabled |
---|
| 462 | + * make sure that REF_CLK is turned on. |
---|
| 463 | + */ |
---|
| 464 | + regmap_update_bits(imx6_pcie->iomuxc_gpr, offset, |
---|
| 465 | + IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE, |
---|
| 466 | + 0); |
---|
| 467 | + regmap_update_bits(imx6_pcie->iomuxc_gpr, offset, |
---|
| 468 | + IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN, |
---|
| 469 | + IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN); |
---|
356 | 470 | break; |
---|
357 | 471 | } |
---|
358 | 472 | |
---|
.. | .. |
---|
362 | 476 | static void imx7d_pcie_wait_for_phy_pll_lock(struct imx6_pcie *imx6_pcie) |
---|
363 | 477 | { |
---|
364 | 478 | u32 val; |
---|
365 | | - unsigned int retries; |
---|
366 | 479 | struct device *dev = imx6_pcie->pci->dev; |
---|
367 | 480 | |
---|
368 | | - for (retries = 0; retries < PHY_PLL_LOCK_WAIT_MAX_RETRIES; retries++) { |
---|
369 | | - regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR22, &val); |
---|
370 | | - |
---|
371 | | - if (val & IMX7D_GPR22_PCIE_PHY_PLL_LOCKED) |
---|
372 | | - return; |
---|
373 | | - |
---|
374 | | - usleep_range(PHY_PLL_LOCK_WAIT_USLEEP_MIN, |
---|
375 | | - PHY_PLL_LOCK_WAIT_USLEEP_MAX); |
---|
376 | | - } |
---|
377 | | - |
---|
378 | | - dev_err(dev, "PCIe PLL lock timeout\n"); |
---|
| 481 | + if (regmap_read_poll_timeout(imx6_pcie->iomuxc_gpr, |
---|
| 482 | + IOMUXC_GPR22, val, |
---|
| 483 | + val & IMX7D_GPR22_PCIE_PHY_PLL_LOCKED, |
---|
| 484 | + PHY_PLL_LOCK_WAIT_USLEEP_MAX, |
---|
| 485 | + PHY_PLL_LOCK_WAIT_TIMEOUT)) |
---|
| 486 | + dev_err(dev, "PCIe PLL lock timeout\n"); |
---|
379 | 487 | } |
---|
380 | 488 | |
---|
381 | 489 | static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) |
---|
.. | .. |
---|
420 | 528 | /* allow the clocks to stabilize */ |
---|
421 | 529 | usleep_range(200, 500); |
---|
422 | 530 | |
---|
423 | | - /* Some boards don't have PCIe reset GPIO. */ |
---|
424 | | - if (gpio_is_valid(imx6_pcie->reset_gpio)) { |
---|
425 | | - gpio_set_value_cansleep(imx6_pcie->reset_gpio, |
---|
426 | | - imx6_pcie->gpio_active_high); |
---|
427 | | - msleep(100); |
---|
428 | | - gpio_set_value_cansleep(imx6_pcie->reset_gpio, |
---|
429 | | - !imx6_pcie->gpio_active_high); |
---|
430 | | - } |
---|
431 | | - |
---|
432 | | - switch (imx6_pcie->variant) { |
---|
| 531 | + switch (imx6_pcie->drvdata->variant) { |
---|
| 532 | + case IMX8MQ: |
---|
| 533 | + reset_control_deassert(imx6_pcie->pciephy_reset); |
---|
| 534 | + break; |
---|
433 | 535 | case IMX7D: |
---|
434 | 536 | reset_control_deassert(imx6_pcie->pciephy_reset); |
---|
| 537 | + |
---|
| 538 | + /* Workaround for ERR010728, failure of PCI-e PLL VCO to |
---|
| 539 | + * oscillate, especially when cold. This turns off "Duty-cycle |
---|
| 540 | + * Corrector" and other mysterious undocumented things. |
---|
| 541 | + */ |
---|
| 542 | + if (likely(imx6_pcie->phy_base)) { |
---|
| 543 | + /* De-assert DCC_FB_EN */ |
---|
| 544 | + writel(PCIE_PHY_CMN_REG4_DCC_FB_EN, |
---|
| 545 | + imx6_pcie->phy_base + PCIE_PHY_CMN_REG4); |
---|
| 546 | + /* Assert RX_EQS and RX_EQS_SEL */ |
---|
| 547 | + writel(PCIE_PHY_CMN_REG24_RX_EQ_SEL |
---|
| 548 | + | PCIE_PHY_CMN_REG24_RX_EQ, |
---|
| 549 | + imx6_pcie->phy_base + PCIE_PHY_CMN_REG24); |
---|
| 550 | + /* Assert ATT_MODE */ |
---|
| 551 | + writel(PCIE_PHY_CMN_REG26_ATT_MODE, |
---|
| 552 | + imx6_pcie->phy_base + PCIE_PHY_CMN_REG26); |
---|
| 553 | + } else { |
---|
| 554 | + dev_warn(dev, "Unable to apply ERR010728 workaround. DT missing fsl,imx7d-pcie-phy phandle ?\n"); |
---|
| 555 | + } |
---|
| 556 | + |
---|
435 | 557 | imx7d_pcie_wait_for_phy_pll_lock(imx6_pcie); |
---|
436 | 558 | break; |
---|
437 | 559 | case IMX6SX: |
---|
.. | .. |
---|
446 | 568 | break; |
---|
447 | 569 | case IMX6Q: /* Nothing to do */ |
---|
448 | 570 | break; |
---|
| 571 | + } |
---|
| 572 | + |
---|
| 573 | + /* Some boards don't have PCIe reset GPIO. */ |
---|
| 574 | + if (gpio_is_valid(imx6_pcie->reset_gpio)) { |
---|
| 575 | + msleep(100); |
---|
| 576 | + gpio_set_value_cansleep(imx6_pcie->reset_gpio, |
---|
| 577 | + !imx6_pcie->gpio_active_high); |
---|
| 578 | + /* Wait for 100ms after PERST# deassertion (PCIe r5.0, 6.6.1) */ |
---|
| 579 | + msleep(100); |
---|
449 | 580 | } |
---|
450 | 581 | |
---|
451 | 582 | return; |
---|
.. | .. |
---|
465 | 596 | } |
---|
466 | 597 | } |
---|
467 | 598 | |
---|
| 599 | +static void imx6_pcie_configure_type(struct imx6_pcie *imx6_pcie) |
---|
| 600 | +{ |
---|
| 601 | + unsigned int mask, val; |
---|
| 602 | + |
---|
| 603 | + if (imx6_pcie->drvdata->variant == IMX8MQ && |
---|
| 604 | + imx6_pcie->controller_id == 1) { |
---|
| 605 | + mask = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE; |
---|
| 606 | + val = FIELD_PREP(IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE, |
---|
| 607 | + PCI_EXP_TYPE_ROOT_PORT); |
---|
| 608 | + } else { |
---|
| 609 | + mask = IMX6Q_GPR12_DEVICE_TYPE; |
---|
| 610 | + val = FIELD_PREP(IMX6Q_GPR12_DEVICE_TYPE, |
---|
| 611 | + PCI_EXP_TYPE_ROOT_PORT); |
---|
| 612 | + } |
---|
| 613 | + |
---|
| 614 | + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, mask, val); |
---|
| 615 | +} |
---|
| 616 | + |
---|
468 | 617 | static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie) |
---|
469 | 618 | { |
---|
470 | | - switch (imx6_pcie->variant) { |
---|
| 619 | + switch (imx6_pcie->drvdata->variant) { |
---|
| 620 | + case IMX8MQ: |
---|
| 621 | + /* |
---|
| 622 | + * TODO: Currently this code assumes external |
---|
| 623 | + * oscillator is being used |
---|
| 624 | + */ |
---|
| 625 | + regmap_update_bits(imx6_pcie->iomuxc_gpr, |
---|
| 626 | + imx6_pcie_grp_offset(imx6_pcie), |
---|
| 627 | + IMX8MQ_GPR_PCIE_REF_USE_PAD, |
---|
| 628 | + IMX8MQ_GPR_PCIE_REF_USE_PAD); |
---|
| 629 | + break; |
---|
471 | 630 | case IMX7D: |
---|
472 | 631 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, |
---|
473 | 632 | IMX7D_GPR12_PCIE_PHY_REFCLK_SEL, 0); |
---|
.. | .. |
---|
476 | 635 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, |
---|
477 | 636 | IMX6SX_GPR12_PCIE_RX_EQ_MASK, |
---|
478 | 637 | IMX6SX_GPR12_PCIE_RX_EQ_2); |
---|
479 | | - /* FALLTHROUGH */ |
---|
| 638 | + fallthrough; |
---|
480 | 639 | default: |
---|
481 | 640 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, |
---|
482 | 641 | IMX6Q_GPR12_PCIE_CTL_2, 0 << 10); |
---|
.. | .. |
---|
503 | 662 | break; |
---|
504 | 663 | } |
---|
505 | 664 | |
---|
506 | | - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, |
---|
507 | | - IMX6Q_GPR12_DEVICE_TYPE, PCI_EXP_TYPE_ROOT_PORT << 12); |
---|
| 665 | + imx6_pcie_configure_type(imx6_pcie); |
---|
508 | 666 | } |
---|
509 | 667 | |
---|
510 | | -static int imx6_pcie_wait_for_link(struct imx6_pcie *imx6_pcie) |
---|
| 668 | +static int imx6_setup_phy_mpll(struct imx6_pcie *imx6_pcie) |
---|
511 | 669 | { |
---|
512 | | - struct dw_pcie *pci = imx6_pcie->pci; |
---|
513 | | - struct device *dev = pci->dev; |
---|
| 670 | + unsigned long phy_rate = clk_get_rate(imx6_pcie->pcie_phy); |
---|
| 671 | + int mult, div; |
---|
| 672 | + u16 val; |
---|
514 | 673 | |
---|
515 | | - /* check if the link is up or not */ |
---|
516 | | - if (!dw_pcie_wait_for_link(pci)) |
---|
| 674 | + if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_IMX6_PHY)) |
---|
517 | 675 | return 0; |
---|
518 | 676 | |
---|
519 | | - dev_dbg(dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n", |
---|
520 | | - dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R0), |
---|
521 | | - dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1)); |
---|
522 | | - return -ETIMEDOUT; |
---|
| 677 | + switch (phy_rate) { |
---|
| 678 | + case 125000000: |
---|
| 679 | + /* |
---|
| 680 | + * The default settings of the MPLL are for a 125MHz input |
---|
| 681 | + * clock, so no need to reconfigure anything in that case. |
---|
| 682 | + */ |
---|
| 683 | + return 0; |
---|
| 684 | + case 100000000: |
---|
| 685 | + mult = 25; |
---|
| 686 | + div = 0; |
---|
| 687 | + break; |
---|
| 688 | + case 200000000: |
---|
| 689 | + mult = 25; |
---|
| 690 | + div = 1; |
---|
| 691 | + break; |
---|
| 692 | + default: |
---|
| 693 | + dev_err(imx6_pcie->pci->dev, |
---|
| 694 | + "Unsupported PHY reference clock rate %lu\n", phy_rate); |
---|
| 695 | + return -EINVAL; |
---|
| 696 | + } |
---|
| 697 | + |
---|
| 698 | + pcie_phy_read(imx6_pcie, PCIE_PHY_MPLL_OVRD_IN_LO, &val); |
---|
| 699 | + val &= ~(PCIE_PHY_MPLL_MULTIPLIER_MASK << |
---|
| 700 | + PCIE_PHY_MPLL_MULTIPLIER_SHIFT); |
---|
| 701 | + val |= mult << PCIE_PHY_MPLL_MULTIPLIER_SHIFT; |
---|
| 702 | + val |= PCIE_PHY_MPLL_MULTIPLIER_OVRD; |
---|
| 703 | + pcie_phy_write(imx6_pcie, PCIE_PHY_MPLL_OVRD_IN_LO, val); |
---|
| 704 | + |
---|
| 705 | + pcie_phy_read(imx6_pcie, PCIE_PHY_ATEOVRD, &val); |
---|
| 706 | + val &= ~(PCIE_PHY_ATEOVRD_REF_CLKDIV_MASK << |
---|
| 707 | + PCIE_PHY_ATEOVRD_REF_CLKDIV_SHIFT); |
---|
| 708 | + val |= div << PCIE_PHY_ATEOVRD_REF_CLKDIV_SHIFT; |
---|
| 709 | + val |= PCIE_PHY_ATEOVRD_EN; |
---|
| 710 | + pcie_phy_write(imx6_pcie, PCIE_PHY_ATEOVRD, val); |
---|
| 711 | + |
---|
| 712 | + return 0; |
---|
523 | 713 | } |
---|
524 | 714 | |
---|
525 | 715 | static int imx6_pcie_wait_for_speed_change(struct imx6_pcie *imx6_pcie) |
---|
.. | .. |
---|
538 | 728 | } |
---|
539 | 729 | |
---|
540 | 730 | dev_err(dev, "Speed change timeout\n"); |
---|
541 | | - return -EINVAL; |
---|
| 731 | + return -ETIMEDOUT; |
---|
| 732 | +} |
---|
| 733 | + |
---|
| 734 | +static void imx6_pcie_ltssm_enable(struct device *dev) |
---|
| 735 | +{ |
---|
| 736 | + struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev); |
---|
| 737 | + |
---|
| 738 | + switch (imx6_pcie->drvdata->variant) { |
---|
| 739 | + case IMX6Q: |
---|
| 740 | + case IMX6SX: |
---|
| 741 | + case IMX6QP: |
---|
| 742 | + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, |
---|
| 743 | + IMX6Q_GPR12_PCIE_CTL_2, |
---|
| 744 | + IMX6Q_GPR12_PCIE_CTL_2); |
---|
| 745 | + break; |
---|
| 746 | + case IMX7D: |
---|
| 747 | + case IMX8MQ: |
---|
| 748 | + reset_control_deassert(imx6_pcie->apps_reset); |
---|
| 749 | + break; |
---|
| 750 | + } |
---|
542 | 751 | } |
---|
543 | 752 | |
---|
544 | 753 | static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) |
---|
545 | 754 | { |
---|
546 | 755 | struct dw_pcie *pci = imx6_pcie->pci; |
---|
547 | 756 | struct device *dev = pci->dev; |
---|
| 757 | + u8 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); |
---|
548 | 758 | u32 tmp; |
---|
549 | 759 | int ret; |
---|
550 | 760 | |
---|
.. | .. |
---|
553 | 763 | * started in Gen2 mode, there is a possibility the devices on the |
---|
554 | 764 | * bus will not be detected at all. This happens with PCIe switches. |
---|
555 | 765 | */ |
---|
556 | | - tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCR); |
---|
557 | | - tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK; |
---|
558 | | - tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1; |
---|
559 | | - dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp); |
---|
| 766 | + tmp = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP); |
---|
| 767 | + tmp &= ~PCI_EXP_LNKCAP_SLS; |
---|
| 768 | + tmp |= PCI_EXP_LNKCAP_SLS_2_5GB; |
---|
| 769 | + dw_pcie_writel_dbi(pci, offset + PCI_EXP_LNKCAP, tmp); |
---|
560 | 770 | |
---|
561 | 771 | /* Start LTSSM. */ |
---|
562 | | - if (imx6_pcie->variant == IMX7D) |
---|
563 | | - reset_control_deassert(imx6_pcie->apps_reset); |
---|
564 | | - else |
---|
565 | | - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, |
---|
566 | | - IMX6Q_GPR12_PCIE_CTL_2, 1 << 10); |
---|
| 772 | + imx6_pcie_ltssm_enable(dev); |
---|
567 | 773 | |
---|
568 | | - ret = imx6_pcie_wait_for_link(imx6_pcie); |
---|
| 774 | + ret = dw_pcie_wait_for_link(pci); |
---|
569 | 775 | if (ret) |
---|
570 | 776 | goto err_reset_phy; |
---|
571 | 777 | |
---|
572 | | - if (imx6_pcie->link_gen == 2) { |
---|
| 778 | + if (pci->link_gen == 2) { |
---|
573 | 779 | /* Allow Gen2 mode after the link is up. */ |
---|
574 | | - tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCR); |
---|
575 | | - tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK; |
---|
576 | | - tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2; |
---|
577 | | - dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp); |
---|
| 780 | + tmp = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP); |
---|
| 781 | + tmp &= ~PCI_EXP_LNKCAP_SLS; |
---|
| 782 | + tmp |= PCI_EXP_LNKCAP_SLS_5_0GB; |
---|
| 783 | + dw_pcie_writel_dbi(pci, offset + PCI_EXP_LNKCAP, tmp); |
---|
578 | 784 | |
---|
579 | 785 | /* |
---|
580 | 786 | * Start Directed Speed Change so the best possible |
---|
.. | .. |
---|
584 | 790 | tmp |= PORT_LOGIC_SPEED_CHANGE; |
---|
585 | 791 | dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); |
---|
586 | 792 | |
---|
587 | | - if (imx6_pcie->variant != IMX7D) { |
---|
| 793 | + if (imx6_pcie->drvdata->flags & |
---|
| 794 | + IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE) { |
---|
588 | 795 | /* |
---|
589 | 796 | * On i.MX7, DIRECT_SPEED_CHANGE behaves differently |
---|
590 | 797 | * from i.MX6 family when no link speed transition |
---|
.. | .. |
---|
602 | 809 | } |
---|
603 | 810 | |
---|
604 | 811 | /* Make sure link training is finished as well! */ |
---|
605 | | - ret = imx6_pcie_wait_for_link(imx6_pcie); |
---|
| 812 | + ret = dw_pcie_wait_for_link(pci); |
---|
606 | 813 | if (ret) { |
---|
607 | 814 | dev_err(dev, "Failed to bring link up!\n"); |
---|
608 | 815 | goto err_reset_phy; |
---|
.. | .. |
---|
611 | 818 | dev_info(dev, "Link: Gen2 disabled\n"); |
---|
612 | 819 | } |
---|
613 | 820 | |
---|
614 | | - tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCSR); |
---|
615 | | - dev_info(dev, "Link up, Gen%i\n", (tmp >> 16) & 0xf); |
---|
| 821 | + tmp = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA); |
---|
| 822 | + dev_info(dev, "Link up, Gen%i\n", tmp & PCI_EXP_LNKSTA_CLS); |
---|
616 | 823 | return 0; |
---|
617 | 824 | |
---|
618 | 825 | err_reset_phy: |
---|
619 | 826 | dev_dbg(dev, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n", |
---|
620 | | - dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R0), |
---|
621 | | - dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1)); |
---|
| 827 | + dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG0), |
---|
| 828 | + dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG1)); |
---|
622 | 829 | imx6_pcie_reset_phy(imx6_pcie); |
---|
623 | 830 | return ret; |
---|
624 | 831 | } |
---|
.. | .. |
---|
631 | 838 | imx6_pcie_assert_core_reset(imx6_pcie); |
---|
632 | 839 | imx6_pcie_init_phy(imx6_pcie); |
---|
633 | 840 | imx6_pcie_deassert_core_reset(imx6_pcie); |
---|
| 841 | + imx6_setup_phy_mpll(imx6_pcie); |
---|
634 | 842 | dw_pcie_setup_rc(pp); |
---|
635 | 843 | imx6_pcie_establish_link(imx6_pcie); |
---|
636 | | - |
---|
637 | | - if (IS_ENABLED(CONFIG_PCI_MSI)) |
---|
638 | | - dw_pcie_msi_init(pp); |
---|
| 844 | + dw_pcie_msi_init(pp); |
---|
639 | 845 | |
---|
640 | 846 | return 0; |
---|
641 | 847 | } |
---|
.. | .. |
---|
654 | 860 | |
---|
655 | 861 | if (IS_ENABLED(CONFIG_PCI_MSI)) { |
---|
656 | 862 | pp->msi_irq = platform_get_irq_byname(pdev, "msi"); |
---|
657 | | - if (pp->msi_irq <= 0) { |
---|
658 | | - dev_err(dev, "failed to get MSI irq\n"); |
---|
659 | | - return -ENODEV; |
---|
660 | | - } |
---|
| 863 | + if (pp->msi_irq < 0) |
---|
| 864 | + return pp->msi_irq; |
---|
661 | 865 | } |
---|
662 | 866 | |
---|
663 | 867 | pp->ops = &imx6_pcie_host_ops; |
---|
.. | .. |
---|
675 | 879 | /* No special ops needed, but pcie-designware still expects this struct */ |
---|
676 | 880 | }; |
---|
677 | 881 | |
---|
| 882 | +#ifdef CONFIG_PM_SLEEP |
---|
| 883 | +static void imx6_pcie_ltssm_disable(struct device *dev) |
---|
| 884 | +{ |
---|
| 885 | + struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev); |
---|
| 886 | + |
---|
| 887 | + switch (imx6_pcie->drvdata->variant) { |
---|
| 888 | + case IMX6SX: |
---|
| 889 | + case IMX6QP: |
---|
| 890 | + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, |
---|
| 891 | + IMX6Q_GPR12_PCIE_CTL_2, 0); |
---|
| 892 | + break; |
---|
| 893 | + case IMX7D: |
---|
| 894 | + reset_control_assert(imx6_pcie->apps_reset); |
---|
| 895 | + break; |
---|
| 896 | + default: |
---|
| 897 | + dev_err(dev, "ltssm_disable not supported\n"); |
---|
| 898 | + } |
---|
| 899 | +} |
---|
| 900 | + |
---|
| 901 | +static void imx6_pcie_pm_turnoff(struct imx6_pcie *imx6_pcie) |
---|
| 902 | +{ |
---|
| 903 | + struct device *dev = imx6_pcie->pci->dev; |
---|
| 904 | + |
---|
| 905 | + /* Some variants have a turnoff reset in DT */ |
---|
| 906 | + if (imx6_pcie->turnoff_reset) { |
---|
| 907 | + reset_control_assert(imx6_pcie->turnoff_reset); |
---|
| 908 | + reset_control_deassert(imx6_pcie->turnoff_reset); |
---|
| 909 | + goto pm_turnoff_sleep; |
---|
| 910 | + } |
---|
| 911 | + |
---|
| 912 | + /* Others poke directly at IOMUXC registers */ |
---|
| 913 | + switch (imx6_pcie->drvdata->variant) { |
---|
| 914 | + case IMX6SX: |
---|
| 915 | + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, |
---|
| 916 | + IMX6SX_GPR12_PCIE_PM_TURN_OFF, |
---|
| 917 | + IMX6SX_GPR12_PCIE_PM_TURN_OFF); |
---|
| 918 | + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, |
---|
| 919 | + IMX6SX_GPR12_PCIE_PM_TURN_OFF, 0); |
---|
| 920 | + break; |
---|
| 921 | + default: |
---|
| 922 | + dev_err(dev, "PME_Turn_Off not implemented\n"); |
---|
| 923 | + return; |
---|
| 924 | + } |
---|
| 925 | + |
---|
| 926 | + /* |
---|
| 927 | + * Components with an upstream port must respond to |
---|
| 928 | + * PME_Turn_Off with PME_TO_Ack but we can't check. |
---|
| 929 | + * |
---|
| 930 | + * The standard recommends a 1-10ms timeout after which to |
---|
| 931 | + * proceed anyway as if acks were received. |
---|
| 932 | + */ |
---|
| 933 | +pm_turnoff_sleep: |
---|
| 934 | + usleep_range(1000, 10000); |
---|
| 935 | +} |
---|
| 936 | + |
---|
| 937 | +static void imx6_pcie_clk_disable(struct imx6_pcie *imx6_pcie) |
---|
| 938 | +{ |
---|
| 939 | + clk_disable_unprepare(imx6_pcie->pcie); |
---|
| 940 | + clk_disable_unprepare(imx6_pcie->pcie_phy); |
---|
| 941 | + clk_disable_unprepare(imx6_pcie->pcie_bus); |
---|
| 942 | + |
---|
| 943 | + switch (imx6_pcie->drvdata->variant) { |
---|
| 944 | + case IMX6SX: |
---|
| 945 | + clk_disable_unprepare(imx6_pcie->pcie_inbound_axi); |
---|
| 946 | + break; |
---|
| 947 | + case IMX7D: |
---|
| 948 | + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, |
---|
| 949 | + IMX7D_GPR12_PCIE_PHY_REFCLK_SEL, |
---|
| 950 | + IMX7D_GPR12_PCIE_PHY_REFCLK_SEL); |
---|
| 951 | + break; |
---|
| 952 | + case IMX8MQ: |
---|
| 953 | + clk_disable_unprepare(imx6_pcie->pcie_aux); |
---|
| 954 | + break; |
---|
| 955 | + default: |
---|
| 956 | + break; |
---|
| 957 | + } |
---|
| 958 | +} |
---|
| 959 | + |
---|
| 960 | +static int imx6_pcie_suspend_noirq(struct device *dev) |
---|
| 961 | +{ |
---|
| 962 | + struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev); |
---|
| 963 | + |
---|
| 964 | + if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_SUPPORTS_SUSPEND)) |
---|
| 965 | + return 0; |
---|
| 966 | + |
---|
| 967 | + imx6_pcie_pm_turnoff(imx6_pcie); |
---|
| 968 | + imx6_pcie_clk_disable(imx6_pcie); |
---|
| 969 | + imx6_pcie_ltssm_disable(dev); |
---|
| 970 | + |
---|
| 971 | + return 0; |
---|
| 972 | +} |
---|
| 973 | + |
---|
| 974 | +static int imx6_pcie_resume_noirq(struct device *dev) |
---|
| 975 | +{ |
---|
| 976 | + int ret; |
---|
| 977 | + struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev); |
---|
| 978 | + struct pcie_port *pp = &imx6_pcie->pci->pp; |
---|
| 979 | + |
---|
| 980 | + if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_SUPPORTS_SUSPEND)) |
---|
| 981 | + return 0; |
---|
| 982 | + |
---|
| 983 | + imx6_pcie_assert_core_reset(imx6_pcie); |
---|
| 984 | + imx6_pcie_init_phy(imx6_pcie); |
---|
| 985 | + imx6_pcie_deassert_core_reset(imx6_pcie); |
---|
| 986 | + dw_pcie_setup_rc(pp); |
---|
| 987 | + |
---|
| 988 | + ret = imx6_pcie_establish_link(imx6_pcie); |
---|
| 989 | + if (ret < 0) |
---|
| 990 | + dev_info(dev, "pcie link is down after resume.\n"); |
---|
| 991 | + |
---|
| 992 | + return 0; |
---|
| 993 | +} |
---|
| 994 | +#endif |
---|
| 995 | + |
---|
| 996 | +static const struct dev_pm_ops imx6_pcie_pm_ops = { |
---|
| 997 | + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx6_pcie_suspend_noirq, |
---|
| 998 | + imx6_pcie_resume_noirq) |
---|
| 999 | +}; |
---|
| 1000 | + |
---|
678 | 1001 | static int imx6_pcie_probe(struct platform_device *pdev) |
---|
679 | 1002 | { |
---|
680 | 1003 | struct device *dev = &pdev->dev; |
---|
681 | 1004 | struct dw_pcie *pci; |
---|
682 | 1005 | struct imx6_pcie *imx6_pcie; |
---|
| 1006 | + struct device_node *np; |
---|
683 | 1007 | struct resource *dbi_base; |
---|
684 | 1008 | struct device_node *node = dev->of_node; |
---|
685 | 1009 | int ret; |
---|
.. | .. |
---|
697 | 1021 | pci->ops = &dw_pcie_ops; |
---|
698 | 1022 | |
---|
699 | 1023 | imx6_pcie->pci = pci; |
---|
700 | | - imx6_pcie->variant = |
---|
701 | | - (enum imx6_pcie_variants)of_device_get_match_data(dev); |
---|
| 1024 | + imx6_pcie->drvdata = of_device_get_match_data(dev); |
---|
| 1025 | + |
---|
| 1026 | + /* Find the PHY if one is defined, only imx7d uses it */ |
---|
| 1027 | + np = of_parse_phandle(node, "fsl,imx7d-pcie-phy", 0); |
---|
| 1028 | + if (np) { |
---|
| 1029 | + struct resource res; |
---|
| 1030 | + |
---|
| 1031 | + ret = of_address_to_resource(np, 0, &res); |
---|
| 1032 | + if (ret) { |
---|
| 1033 | + dev_err(dev, "Unable to map PCIe PHY\n"); |
---|
| 1034 | + return ret; |
---|
| 1035 | + } |
---|
| 1036 | + imx6_pcie->phy_base = devm_ioremap_resource(dev, &res); |
---|
| 1037 | + if (IS_ERR(imx6_pcie->phy_base)) { |
---|
| 1038 | + dev_err(dev, "Unable to map PCIe PHY\n"); |
---|
| 1039 | + return PTR_ERR(imx6_pcie->phy_base); |
---|
| 1040 | + } |
---|
| 1041 | + } |
---|
702 | 1042 | |
---|
703 | 1043 | dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
704 | 1044 | pci->dbi_base = devm_ioremap_resource(dev, dbi_base); |
---|
.. | .. |
---|
725 | 1065 | |
---|
726 | 1066 | /* Fetch clocks */ |
---|
727 | 1067 | imx6_pcie->pcie_phy = devm_clk_get(dev, "pcie_phy"); |
---|
728 | | - if (IS_ERR(imx6_pcie->pcie_phy)) { |
---|
729 | | - dev_err(dev, "pcie_phy clock source missing or invalid\n"); |
---|
730 | | - return PTR_ERR(imx6_pcie->pcie_phy); |
---|
731 | | - } |
---|
| 1068 | + if (IS_ERR(imx6_pcie->pcie_phy)) |
---|
| 1069 | + return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_phy), |
---|
| 1070 | + "pcie_phy clock source missing or invalid\n"); |
---|
732 | 1071 | |
---|
733 | 1072 | imx6_pcie->pcie_bus = devm_clk_get(dev, "pcie_bus"); |
---|
734 | | - if (IS_ERR(imx6_pcie->pcie_bus)) { |
---|
735 | | - dev_err(dev, "pcie_bus clock source missing or invalid\n"); |
---|
736 | | - return PTR_ERR(imx6_pcie->pcie_bus); |
---|
737 | | - } |
---|
| 1073 | + if (IS_ERR(imx6_pcie->pcie_bus)) |
---|
| 1074 | + return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_bus), |
---|
| 1075 | + "pcie_bus clock source missing or invalid\n"); |
---|
738 | 1076 | |
---|
739 | 1077 | imx6_pcie->pcie = devm_clk_get(dev, "pcie"); |
---|
740 | | - if (IS_ERR(imx6_pcie->pcie)) { |
---|
741 | | - dev_err(dev, "pcie clock source missing or invalid\n"); |
---|
742 | | - return PTR_ERR(imx6_pcie->pcie); |
---|
743 | | - } |
---|
| 1078 | + if (IS_ERR(imx6_pcie->pcie)) |
---|
| 1079 | + return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie), |
---|
| 1080 | + "pcie clock source missing or invalid\n"); |
---|
744 | 1081 | |
---|
745 | | - switch (imx6_pcie->variant) { |
---|
| 1082 | + switch (imx6_pcie->drvdata->variant) { |
---|
746 | 1083 | case IMX6SX: |
---|
747 | 1084 | imx6_pcie->pcie_inbound_axi = devm_clk_get(dev, |
---|
748 | 1085 | "pcie_inbound_axi"); |
---|
749 | | - if (IS_ERR(imx6_pcie->pcie_inbound_axi)) { |
---|
750 | | - dev_err(dev, "pcie_inbound_axi clock missing or invalid\n"); |
---|
751 | | - return PTR_ERR(imx6_pcie->pcie_inbound_axi); |
---|
752 | | - } |
---|
| 1086 | + if (IS_ERR(imx6_pcie->pcie_inbound_axi)) |
---|
| 1087 | + return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_inbound_axi), |
---|
| 1088 | + "pcie_inbound_axi clock missing or invalid\n"); |
---|
753 | 1089 | break; |
---|
| 1090 | + case IMX8MQ: |
---|
| 1091 | + imx6_pcie->pcie_aux = devm_clk_get(dev, "pcie_aux"); |
---|
| 1092 | + if (IS_ERR(imx6_pcie->pcie_aux)) |
---|
| 1093 | + return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_aux), |
---|
| 1094 | + "pcie_aux clock source missing or invalid\n"); |
---|
| 1095 | + fallthrough; |
---|
754 | 1096 | case IMX7D: |
---|
| 1097 | + if (dbi_base->start == IMX8MQ_PCIE2_BASE_ADDR) |
---|
| 1098 | + imx6_pcie->controller_id = 1; |
---|
| 1099 | + |
---|
755 | 1100 | imx6_pcie->pciephy_reset = devm_reset_control_get_exclusive(dev, |
---|
756 | 1101 | "pciephy"); |
---|
757 | 1102 | if (IS_ERR(imx6_pcie->pciephy_reset)) { |
---|
.. | .. |
---|
768 | 1113 | break; |
---|
769 | 1114 | default: |
---|
770 | 1115 | break; |
---|
| 1116 | + } |
---|
| 1117 | + |
---|
| 1118 | + /* Grab turnoff reset */ |
---|
| 1119 | + imx6_pcie->turnoff_reset = devm_reset_control_get_optional_exclusive(dev, "turnoff"); |
---|
| 1120 | + if (IS_ERR(imx6_pcie->turnoff_reset)) { |
---|
| 1121 | + dev_err(dev, "Failed to get TURNOFF reset control\n"); |
---|
| 1122 | + return PTR_ERR(imx6_pcie->turnoff_reset); |
---|
771 | 1123 | } |
---|
772 | 1124 | |
---|
773 | 1125 | /* Grab GPR config register range */ |
---|
.. | .. |
---|
800 | 1152 | imx6_pcie->tx_swing_low = 127; |
---|
801 | 1153 | |
---|
802 | 1154 | /* Limit link speed */ |
---|
803 | | - ret = of_property_read_u32(node, "fsl,max-link-speed", |
---|
804 | | - &imx6_pcie->link_gen); |
---|
805 | | - if (ret) |
---|
806 | | - imx6_pcie->link_gen = 1; |
---|
| 1155 | + pci->link_gen = 1; |
---|
| 1156 | + ret = of_property_read_u32(node, "fsl,max-link-speed", &pci->link_gen); |
---|
807 | 1157 | |
---|
808 | 1158 | imx6_pcie->vpcie = devm_regulator_get_optional(&pdev->dev, "vpcie"); |
---|
809 | 1159 | if (IS_ERR(imx6_pcie->vpcie)) { |
---|
.. | .. |
---|
814 | 1164 | |
---|
815 | 1165 | platform_set_drvdata(pdev, imx6_pcie); |
---|
816 | 1166 | |
---|
| 1167 | + ret = imx6_pcie_attach_pd(dev); |
---|
| 1168 | + if (ret) |
---|
| 1169 | + return ret; |
---|
| 1170 | + |
---|
817 | 1171 | ret = imx6_add_pcie_port(imx6_pcie, pdev); |
---|
818 | 1172 | if (ret < 0) |
---|
819 | 1173 | return ret; |
---|
820 | 1174 | |
---|
821 | 1175 | if (pci_msi_enabled()) { |
---|
822 | | - val = dw_pcie_readw_dbi(pci, PCIE_RC_IMX6_MSI_CAP + |
---|
823 | | - PCI_MSI_FLAGS); |
---|
| 1176 | + u8 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_MSI); |
---|
| 1177 | + val = dw_pcie_readw_dbi(pci, offset + PCI_MSI_FLAGS); |
---|
824 | 1178 | val |= PCI_MSI_FLAGS_ENABLE; |
---|
825 | | - dw_pcie_writew_dbi(pci, PCIE_RC_IMX6_MSI_CAP + PCI_MSI_FLAGS, |
---|
826 | | - val); |
---|
| 1179 | + dw_pcie_writew_dbi(pci, offset + PCI_MSI_FLAGS, val); |
---|
827 | 1180 | } |
---|
828 | 1181 | |
---|
829 | 1182 | return 0; |
---|
.. | .. |
---|
837 | 1190 | imx6_pcie_assert_core_reset(imx6_pcie); |
---|
838 | 1191 | } |
---|
839 | 1192 | |
---|
| 1193 | +static const struct imx6_pcie_drvdata drvdata[] = { |
---|
| 1194 | + [IMX6Q] = { |
---|
| 1195 | + .variant = IMX6Q, |
---|
| 1196 | + .flags = IMX6_PCIE_FLAG_IMX6_PHY | |
---|
| 1197 | + IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE, |
---|
| 1198 | + .dbi_length = 0x200, |
---|
| 1199 | + }, |
---|
| 1200 | + [IMX6SX] = { |
---|
| 1201 | + .variant = IMX6SX, |
---|
| 1202 | + .flags = IMX6_PCIE_FLAG_IMX6_PHY | |
---|
| 1203 | + IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE | |
---|
| 1204 | + IMX6_PCIE_FLAG_SUPPORTS_SUSPEND, |
---|
| 1205 | + }, |
---|
| 1206 | + [IMX6QP] = { |
---|
| 1207 | + .variant = IMX6QP, |
---|
| 1208 | + .flags = IMX6_PCIE_FLAG_IMX6_PHY | |
---|
| 1209 | + IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE, |
---|
| 1210 | + }, |
---|
| 1211 | + [IMX7D] = { |
---|
| 1212 | + .variant = IMX7D, |
---|
| 1213 | + .flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND, |
---|
| 1214 | + }, |
---|
| 1215 | + [IMX8MQ] = { |
---|
| 1216 | + .variant = IMX8MQ, |
---|
| 1217 | + }, |
---|
| 1218 | +}; |
---|
| 1219 | + |
---|
840 | 1220 | static const struct of_device_id imx6_pcie_of_match[] = { |
---|
841 | | - { .compatible = "fsl,imx6q-pcie", .data = (void *)IMX6Q, }, |
---|
842 | | - { .compatible = "fsl,imx6sx-pcie", .data = (void *)IMX6SX, }, |
---|
843 | | - { .compatible = "fsl,imx6qp-pcie", .data = (void *)IMX6QP, }, |
---|
844 | | - { .compatible = "fsl,imx7d-pcie", .data = (void *)IMX7D, }, |
---|
| 1221 | + { .compatible = "fsl,imx6q-pcie", .data = &drvdata[IMX6Q], }, |
---|
| 1222 | + { .compatible = "fsl,imx6sx-pcie", .data = &drvdata[IMX6SX], }, |
---|
| 1223 | + { .compatible = "fsl,imx6qp-pcie", .data = &drvdata[IMX6QP], }, |
---|
| 1224 | + { .compatible = "fsl,imx7d-pcie", .data = &drvdata[IMX7D], }, |
---|
| 1225 | + { .compatible = "fsl,imx8mq-pcie", .data = &drvdata[IMX8MQ], } , |
---|
845 | 1226 | {}, |
---|
846 | 1227 | }; |
---|
847 | 1228 | |
---|
.. | .. |
---|
850 | 1231 | .name = "imx6q-pcie", |
---|
851 | 1232 | .of_match_table = imx6_pcie_of_match, |
---|
852 | 1233 | .suppress_bind_attrs = true, |
---|
| 1234 | + .pm = &imx6_pcie_pm_ops, |
---|
| 1235 | + .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
---|
853 | 1236 | }, |
---|
854 | 1237 | .probe = imx6_pcie_probe, |
---|
855 | 1238 | .shutdown = imx6_pcie_shutdown, |
---|
856 | 1239 | }; |
---|
857 | 1240 | |
---|
| 1241 | +static void imx6_pcie_quirk(struct pci_dev *dev) |
---|
| 1242 | +{ |
---|
| 1243 | + struct pci_bus *bus = dev->bus; |
---|
| 1244 | + struct pcie_port *pp = bus->sysdata; |
---|
| 1245 | + |
---|
| 1246 | + /* Bus parent is the PCI bridge, its parent is this platform driver */ |
---|
| 1247 | + if (!bus->dev.parent || !bus->dev.parent->parent) |
---|
| 1248 | + return; |
---|
| 1249 | + |
---|
| 1250 | + /* Make sure we only quirk devices associated with this driver */ |
---|
| 1251 | + if (bus->dev.parent->parent->driver != &imx6_pcie_driver.driver) |
---|
| 1252 | + return; |
---|
| 1253 | + |
---|
| 1254 | + if (pci_is_root_bus(bus)) { |
---|
| 1255 | + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); |
---|
| 1256 | + struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci); |
---|
| 1257 | + |
---|
| 1258 | + /* |
---|
| 1259 | + * Limit config length to avoid the kernel reading beyond |
---|
| 1260 | + * the register set and causing an abort on i.MX 6Quad |
---|
| 1261 | + */ |
---|
| 1262 | + if (imx6_pcie->drvdata->dbi_length) { |
---|
| 1263 | + dev->cfg_size = imx6_pcie->drvdata->dbi_length; |
---|
| 1264 | + dev_info(&dev->dev, "Limiting cfg_size to %d\n", |
---|
| 1265 | + dev->cfg_size); |
---|
| 1266 | + } |
---|
| 1267 | + } |
---|
| 1268 | +} |
---|
| 1269 | +DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, |
---|
| 1270 | + PCI_CLASS_BRIDGE_PCI, 8, imx6_pcie_quirk); |
---|
| 1271 | + |
---|
858 | 1272 | static int __init imx6_pcie_init(void) |
---|
859 | 1273 | { |
---|
| 1274 | +#ifdef CONFIG_ARM |
---|
| 1275 | + struct device_node *np; |
---|
| 1276 | + |
---|
| 1277 | + np = of_find_matching_node(NULL, imx6_pcie_of_match); |
---|
| 1278 | + if (!np) |
---|
| 1279 | + return -ENODEV; |
---|
| 1280 | + of_node_put(np); |
---|
| 1281 | + |
---|
860 | 1282 | /* |
---|
861 | 1283 | * Since probe() can be deferred we need to make sure that |
---|
862 | 1284 | * hook_fault_code is not called after __init memory is freed |
---|
.. | .. |
---|
866 | 1288 | */ |
---|
867 | 1289 | hook_fault_code(8, imx6q_pcie_abort_handler, SIGBUS, 0, |
---|
868 | 1290 | "external abort on non-linefetch"); |
---|
| 1291 | +#endif |
---|
869 | 1292 | |
---|
870 | 1293 | return platform_driver_register(&imx6_pcie_driver); |
---|
871 | 1294 | } |
---|