35
35
#define PF_MCR_PTOMR BIT(0)
36
36
#define PF_MCR_EXL2S BIT(1)
37
37
38
+ /* LS1021A PEXn PM Write Control Register */
39
+ #define SCFG_PEXPMWRCR (idx ) (0x5c + (idx) * 0x64)
40
+ #define PMXMTTURNOFF BIT(31)
41
+ #define SCFG_PEXSFTRSTCR 0x190
42
+ #define PEXSR (idx ) BIT(idx)
43
+
44
+ /* LS1043A PEX PME control register */
45
+ #define SCFG_PEXPMECR 0x144
46
+ #define PEXPME (idx ) BIT(31 - (idx) * 4)
47
+
48
+ /* LS1043A PEX LUT debug register */
49
+ #define LS_PCIE_LDBG 0x7fc
50
+ #define LDBG_SR BIT(30)
51
+ #define LDBG_WE BIT(31)
52
+
38
53
#define PCIE_IATU_NUM 6
39
54
40
55
struct ls_pcie_drvdata {
41
- const u32 pf_off ;
56
+ const u32 pf_lut_off ;
57
+ const struct dw_pcie_host_ops * ops ;
58
+ int (* exit_from_l2 )(struct dw_pcie_rp * pp );
59
+ bool scfg_support ;
42
60
bool pm_support ;
43
61
};
44
62
45
63
struct ls_pcie {
46
64
struct dw_pcie * pci ;
47
65
const struct ls_pcie_drvdata * drvdata ;
48
- void __iomem * pf_base ;
66
+ void __iomem * pf_lut_base ;
67
+ struct regmap * scfg ;
68
+ int index ;
49
69
bool big_endian ;
50
70
};
51
71
52
- #define ls_pcie_pf_readl_addr (addr ) ls_pcie_pf_readl (pcie, addr)
72
+ #define ls_pcie_pf_lut_readl_addr (addr ) ls_pcie_pf_lut_readl (pcie, addr)
53
73
#define to_ls_pcie (x ) dev_get_drvdata((x)->dev)
54
74
55
75
static bool ls_pcie_is_bridge (struct ls_pcie * pcie )
@@ -90,20 +110,20 @@ static void ls_pcie_fix_error_response(struct ls_pcie *pcie)
90
110
iowrite32 (PCIE_ABSERR_SETTING , pci -> dbi_base + PCIE_ABSERR );
91
111
}
92
112
93
- static u32 ls_pcie_pf_readl (struct ls_pcie * pcie , u32 off )
113
+ static u32 ls_pcie_pf_lut_readl (struct ls_pcie * pcie , u32 off )
94
114
{
95
115
if (pcie -> big_endian )
96
- return ioread32be (pcie -> pf_base + off );
116
+ return ioread32be (pcie -> pf_lut_base + off );
97
117
98
- return ioread32 (pcie -> pf_base + off );
118
+ return ioread32 (pcie -> pf_lut_base + off );
99
119
}
100
120
101
- static void ls_pcie_pf_writel (struct ls_pcie * pcie , u32 off , u32 val )
121
+ static void ls_pcie_pf_lut_writel (struct ls_pcie * pcie , u32 off , u32 val )
102
122
{
103
123
if (pcie -> big_endian )
104
- iowrite32be (val , pcie -> pf_base + off );
124
+ iowrite32be (val , pcie -> pf_lut_base + off );
105
125
else
106
- iowrite32 (val , pcie -> pf_base + off );
126
+ iowrite32 (val , pcie -> pf_lut_base + off );
107
127
}
108
128
109
129
static void ls_pcie_send_turnoff_msg (struct dw_pcie_rp * pp )
@@ -113,19 +133,19 @@ static void ls_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
113
133
u32 val ;
114
134
int ret ;
115
135
116
- val = ls_pcie_pf_readl (pcie , LS_PCIE_PF_MCR );
136
+ val = ls_pcie_pf_lut_readl (pcie , LS_PCIE_PF_MCR );
117
137
val |= PF_MCR_PTOMR ;
118
- ls_pcie_pf_writel (pcie , LS_PCIE_PF_MCR , val );
138
+ ls_pcie_pf_lut_writel (pcie , LS_PCIE_PF_MCR , val );
119
139
120
- ret = readx_poll_timeout (ls_pcie_pf_readl_addr , LS_PCIE_PF_MCR ,
140
+ ret = readx_poll_timeout (ls_pcie_pf_lut_readl_addr , LS_PCIE_PF_MCR ,
121
141
val , !(val & PF_MCR_PTOMR ),
122
142
PCIE_PME_TO_L2_TIMEOUT_US /10 ,
123
143
PCIE_PME_TO_L2_TIMEOUT_US );
124
144
if (ret )
125
145
dev_err (pcie -> pci -> dev , "PME_Turn_off timeout\n" );
126
146
}
127
147
128
- static void ls_pcie_exit_from_l2 (struct dw_pcie_rp * pp )
148
+ static int ls_pcie_exit_from_l2 (struct dw_pcie_rp * pp )
129
149
{
130
150
struct dw_pcie * pci = to_dw_pcie_from_pp (pp );
131
151
struct ls_pcie * pcie = to_ls_pcie (pci );
@@ -136,20 +156,22 @@ static void ls_pcie_exit_from_l2(struct dw_pcie_rp *pp)
136
156
* Set PF_MCR_EXL2S bit in LS_PCIE_PF_MCR register for the link
137
157
* to exit L2 state.
138
158
*/
139
- val = ls_pcie_pf_readl (pcie , LS_PCIE_PF_MCR );
159
+ val = ls_pcie_pf_lut_readl (pcie , LS_PCIE_PF_MCR );
140
160
val |= PF_MCR_EXL2S ;
141
- ls_pcie_pf_writel (pcie , LS_PCIE_PF_MCR , val );
161
+ ls_pcie_pf_lut_writel (pcie , LS_PCIE_PF_MCR , val );
142
162
143
163
/*
144
164
* L2 exit timeout of 10ms is not defined in the specifications,
145
165
* it was chosen based on empirical observations.
146
166
*/
147
- ret = readx_poll_timeout (ls_pcie_pf_readl_addr , LS_PCIE_PF_MCR ,
167
+ ret = readx_poll_timeout (ls_pcie_pf_lut_readl_addr , LS_PCIE_PF_MCR ,
148
168
val , !(val & PF_MCR_EXL2S ),
149
169
1000 ,
150
170
10000 );
151
171
if (ret )
152
172
dev_err (pcie -> pci -> dev , "L2 exit timeout\n" );
173
+
174
+ return ret ;
153
175
}
154
176
155
177
static int ls_pcie_host_init (struct dw_pcie_rp * pp )
@@ -168,25 +190,130 @@ static int ls_pcie_host_init(struct dw_pcie_rp *pp)
168
190
return 0 ;
169
191
}
170
192
193
+ static void scfg_pcie_send_turnoff_msg (struct regmap * scfg , u32 reg , u32 mask )
194
+ {
195
+ /* Send PME_Turn_Off message */
196
+ regmap_write_bits (scfg , reg , mask , mask );
197
+
198
+ /*
199
+ * There is no specific register to check for PME_To_Ack from endpoint.
200
+ * So on the safe side, wait for PCIE_PME_TO_L2_TIMEOUT_US.
201
+ */
202
+ mdelay (PCIE_PME_TO_L2_TIMEOUT_US /1000 );
203
+
204
+ /*
205
+ * Layerscape hardware reference manual recommends clearing the PMXMTTURNOFF bit
206
+ * to complete the PME_Turn_Off handshake.
207
+ */
208
+ regmap_write_bits (scfg , reg , mask , 0 );
209
+ }
210
+
211
+ static void ls1021a_pcie_send_turnoff_msg (struct dw_pcie_rp * pp )
212
+ {
213
+ struct dw_pcie * pci = to_dw_pcie_from_pp (pp );
214
+ struct ls_pcie * pcie = to_ls_pcie (pci );
215
+
216
+ scfg_pcie_send_turnoff_msg (pcie -> scfg , SCFG_PEXPMWRCR (pcie -> index ), PMXMTTURNOFF );
217
+ }
218
+
219
+ static int scfg_pcie_exit_from_l2 (struct regmap * scfg , u32 reg , u32 mask )
220
+ {
221
+ /* Reset the PEX wrapper to bring the link out of L2 */
222
+ regmap_write_bits (scfg , reg , mask , mask );
223
+ regmap_write_bits (scfg , reg , mask , 0 );
224
+
225
+ return 0 ;
226
+ }
227
+
228
+ static int ls1021a_pcie_exit_from_l2 (struct dw_pcie_rp * pp )
229
+ {
230
+ struct dw_pcie * pci = to_dw_pcie_from_pp (pp );
231
+ struct ls_pcie * pcie = to_ls_pcie (pci );
232
+
233
+ return scfg_pcie_exit_from_l2 (pcie -> scfg , SCFG_PEXSFTRSTCR , PEXSR (pcie -> index ));
234
+ }
235
+
236
+ static void ls1043a_pcie_send_turnoff_msg (struct dw_pcie_rp * pp )
237
+ {
238
+ struct dw_pcie * pci = to_dw_pcie_from_pp (pp );
239
+ struct ls_pcie * pcie = to_ls_pcie (pci );
240
+
241
+ scfg_pcie_send_turnoff_msg (pcie -> scfg , SCFG_PEXPMECR , PEXPME (pcie -> index ));
242
+ }
243
+
244
+ static int ls1043a_pcie_exit_from_l2 (struct dw_pcie_rp * pp )
245
+ {
246
+ struct dw_pcie * pci = to_dw_pcie_from_pp (pp );
247
+ struct ls_pcie * pcie = to_ls_pcie (pci );
248
+ u32 val ;
249
+
250
+ /*
251
+ * Reset the PEX wrapper to bring the link out of L2.
252
+ * LDBG_WE: allows the user to have write access to the PEXDBG[SR] for both setting and
253
+ * clearing the soft reset on the PEX module.
254
+ * LDBG_SR: When SR is set to 1, the PEX module enters soft reset.
255
+ */
256
+ val = ls_pcie_pf_lut_readl (pcie , LS_PCIE_LDBG );
257
+ val |= LDBG_WE ;
258
+ ls_pcie_pf_lut_writel (pcie , LS_PCIE_LDBG , val );
259
+
260
+ val = ls_pcie_pf_lut_readl (pcie , LS_PCIE_LDBG );
261
+ val |= LDBG_SR ;
262
+ ls_pcie_pf_lut_writel (pcie , LS_PCIE_LDBG , val );
263
+
264
+ val = ls_pcie_pf_lut_readl (pcie , LS_PCIE_LDBG );
265
+ val &= ~LDBG_SR ;
266
+ ls_pcie_pf_lut_writel (pcie , LS_PCIE_LDBG , val );
267
+
268
+ val = ls_pcie_pf_lut_readl (pcie , LS_PCIE_LDBG );
269
+ val &= ~LDBG_WE ;
270
+ ls_pcie_pf_lut_writel (pcie , LS_PCIE_LDBG , val );
271
+
272
+ return 0 ;
273
+ }
274
+
171
275
static const struct dw_pcie_host_ops ls_pcie_host_ops = {
172
276
.init = ls_pcie_host_init ,
173
277
.pme_turn_off = ls_pcie_send_turnoff_msg ,
174
278
};
175
279
280
+ static const struct dw_pcie_host_ops ls1021a_pcie_host_ops = {
281
+ .init = ls_pcie_host_init ,
282
+ .pme_turn_off = ls1021a_pcie_send_turnoff_msg ,
283
+ };
284
+
176
285
static const struct ls_pcie_drvdata ls1021a_drvdata = {
177
- .pm_support = false,
286
+ .pm_support = true,
287
+ .scfg_support = true,
288
+ .ops = & ls1021a_pcie_host_ops ,
289
+ .exit_from_l2 = ls1021a_pcie_exit_from_l2 ,
290
+ };
291
+
292
+ static const struct dw_pcie_host_ops ls1043a_pcie_host_ops = {
293
+ .init = ls_pcie_host_init ,
294
+ .pme_turn_off = ls1043a_pcie_send_turnoff_msg ,
295
+ };
296
+
297
+ static const struct ls_pcie_drvdata ls1043a_drvdata = {
298
+ .pf_lut_off = 0x10000 ,
299
+ .pm_support = true,
300
+ .scfg_support = true,
301
+ .ops = & ls1043a_pcie_host_ops ,
302
+ .exit_from_l2 = ls1043a_pcie_exit_from_l2 ,
178
303
};
179
304
180
305
static const struct ls_pcie_drvdata layerscape_drvdata = {
181
- .pf_off = 0xc0000 ,
306
+ .pf_lut_off = 0xc0000 ,
182
307
.pm_support = true,
308
+ .ops = & ls_pcie_host_ops ,
309
+ .exit_from_l2 = ls_pcie_exit_from_l2 ,
183
310
};
184
311
185
312
static const struct of_device_id ls_pcie_of_match [] = {
186
313
{ .compatible = "fsl,ls1012a-pcie" , .data = & layerscape_drvdata },
187
314
{ .compatible = "fsl,ls1021a-pcie" , .data = & ls1021a_drvdata },
188
315
{ .compatible = "fsl,ls1028a-pcie" , .data = & layerscape_drvdata },
189
- { .compatible = "fsl,ls1043a-pcie" , .data = & ls1021a_drvdata },
316
+ { .compatible = "fsl,ls1043a-pcie" , .data = & ls1043a_drvdata },
190
317
{ .compatible = "fsl,ls1046a-pcie" , .data = & layerscape_drvdata },
191
318
{ .compatible = "fsl,ls2080a-pcie" , .data = & layerscape_drvdata },
192
319
{ .compatible = "fsl,ls2085a-pcie" , .data = & layerscape_drvdata },
@@ -201,6 +328,8 @@ static int ls_pcie_probe(struct platform_device *pdev)
201
328
struct dw_pcie * pci ;
202
329
struct ls_pcie * pcie ;
203
330
struct resource * dbi_base ;
331
+ u32 index [2 ];
332
+ int ret ;
204
333
205
334
pcie = devm_kzalloc (dev , sizeof (* pcie ), GFP_KERNEL );
206
335
if (!pcie )
@@ -213,9 +342,8 @@ static int ls_pcie_probe(struct platform_device *pdev)
213
342
pcie -> drvdata = of_device_get_match_data (dev );
214
343
215
344
pci -> dev = dev ;
216
- pci -> pp .ops = & ls_pcie_host_ops ;
217
-
218
345
pcie -> pci = pci ;
346
+ pci -> pp .ops = pcie -> drvdata -> ops ;
219
347
220
348
dbi_base = platform_get_resource_byname (pdev , IORESOURCE_MEM , "regs" );
221
349
pci -> dbi_base = devm_pci_remap_cfg_resource (dev , dbi_base );
@@ -224,7 +352,21 @@ static int ls_pcie_probe(struct platform_device *pdev)
224
352
225
353
pcie -> big_endian = of_property_read_bool (dev -> of_node , "big-endian" );
226
354
227
- pcie -> pf_base = pci -> dbi_base + pcie -> drvdata -> pf_off ;
355
+ pcie -> pf_lut_base = pci -> dbi_base + pcie -> drvdata -> pf_lut_off ;
356
+
357
+ if (pcie -> drvdata -> scfg_support ) {
358
+ pcie -> scfg = syscon_regmap_lookup_by_phandle (dev -> of_node , "fsl,pcie-scfg" );
359
+ if (IS_ERR (pcie -> scfg )) {
360
+ dev_err (dev , "No syscfg phandle specified\n" );
361
+ return PTR_ERR (pcie -> scfg );
362
+ }
363
+
364
+ ret = of_property_read_u32_array (dev -> of_node , "fsl,pcie-scfg" , index , 2 );
365
+ if (ret )
366
+ return ret ;
367
+
368
+ pcie -> index = index [1 ];
369
+ }
228
370
229
371
if (!ls_pcie_is_bridge (pcie ))
230
372
return - ENODEV ;
@@ -247,11 +389,14 @@ static int ls_pcie_suspend_noirq(struct device *dev)
247
389
static int ls_pcie_resume_noirq (struct device * dev )
248
390
{
249
391
struct ls_pcie * pcie = dev_get_drvdata (dev );
392
+ int ret ;
250
393
251
394
if (!pcie -> drvdata -> pm_support )
252
395
return 0 ;
253
396
254
- ls_pcie_exit_from_l2 (& pcie -> pci -> pp );
397
+ ret = pcie -> drvdata -> exit_from_l2 (& pcie -> pci -> pp );
398
+ if (ret )
399
+ return ret ;
255
400
256
401
return dw_pcie_resume_noirq (pcie -> pci );
257
402
}
0 commit comments