34
34
#define to_rockchip_pcie (x ) dev_get_drvdata((x)->dev)
35
35
36
36
#define PCIE_CLIENT_RC_MODE HIWORD_UPDATE_BIT(0x40)
37
+ #define PCIE_CLIENT_EP_MODE HIWORD_UPDATE(0xf0, 0x0)
37
38
#define PCIE_CLIENT_ENABLE_LTSSM HIWORD_UPDATE_BIT(0xc)
39
+ #define PCIE_CLIENT_DISABLE_LTSSM HIWORD_UPDATE(0x0c, 0x8)
40
+ #define PCIE_CLIENT_INTR_STATUS_MISC 0x10
41
+ #define PCIE_CLIENT_INTR_MASK_MISC 0x24
38
42
#define PCIE_SMLH_LINKUP BIT(16)
39
43
#define PCIE_RDLH_LINKUP BIT(17)
40
44
#define PCIE_LINKUP (PCIE_SMLH_LINKUP | PCIE_RDLH_LINKUP)
45
+ #define PCIE_RDLH_LINK_UP_CHGED BIT(1)
46
+ #define PCIE_LINK_REQ_RST_NOT_INT BIT(2)
41
47
#define PCIE_L0S_ENTRY 0x11
42
48
#define PCIE_CLIENT_GENERAL_CONTROL 0x0
43
49
#define PCIE_CLIENT_INTR_STATUS_LEGACY 0x8
@@ -63,6 +69,7 @@ struct rockchip_pcie {
63
69
64
70
struct rockchip_pcie_of_data {
65
71
enum dw_pcie_device_mode mode ;
72
+ const struct pci_epc_features * epc_features ;
66
73
};
67
74
68
75
static int rockchip_pcie_readl_apb (struct rockchip_pcie * rockchip , u32 reg )
@@ -159,6 +166,12 @@ static void rockchip_pcie_enable_ltssm(struct rockchip_pcie *rockchip)
159
166
PCIE_CLIENT_GENERAL_CONTROL );
160
167
}
161
168
169
+ static void rockchip_pcie_disable_ltssm (struct rockchip_pcie * rockchip )
170
+ {
171
+ rockchip_pcie_writel_apb (rockchip , PCIE_CLIENT_DISABLE_LTSSM ,
172
+ PCIE_CLIENT_GENERAL_CONTROL );
173
+ }
174
+
162
175
static int rockchip_pcie_link_up (struct dw_pcie * pci )
163
176
{
164
177
struct rockchip_pcie * rockchip = to_rockchip_pcie (pci );
@@ -195,6 +208,13 @@ static int rockchip_pcie_start_link(struct dw_pcie *pci)
195
208
return 0 ;
196
209
}
197
210
211
+ static void rockchip_pcie_stop_link (struct dw_pcie * pci )
212
+ {
213
+ struct rockchip_pcie * rockchip = to_rockchip_pcie (pci );
214
+
215
+ rockchip_pcie_disable_ltssm (rockchip );
216
+ }
217
+
198
218
static int rockchip_pcie_host_init (struct dw_pcie_rp * pp )
199
219
{
200
220
struct dw_pcie * pci = to_dw_pcie_from_pp (pp );
@@ -220,6 +240,82 @@ static const struct dw_pcie_host_ops rockchip_pcie_host_ops = {
220
240
.init = rockchip_pcie_host_init ,
221
241
};
222
242
243
+ static void rockchip_pcie_ep_init (struct dw_pcie_ep * ep )
244
+ {
245
+ struct dw_pcie * pci = to_dw_pcie_from_ep (ep );
246
+ enum pci_barno bar ;
247
+
248
+ for (bar = 0 ; bar < PCI_STD_NUM_BARS ; bar ++ )
249
+ dw_pcie_ep_reset_bar (pci , bar );
250
+ };
251
+
252
+ static int rockchip_pcie_raise_irq (struct dw_pcie_ep * ep , u8 func_no ,
253
+ unsigned int type , u16 interrupt_num )
254
+ {
255
+ struct dw_pcie * pci = to_dw_pcie_from_ep (ep );
256
+
257
+ switch (type ) {
258
+ case PCI_IRQ_INTX :
259
+ return dw_pcie_ep_raise_intx_irq (ep , func_no );
260
+ case PCI_IRQ_MSI :
261
+ return dw_pcie_ep_raise_msi_irq (ep , func_no , interrupt_num );
262
+ case PCI_IRQ_MSIX :
263
+ return dw_pcie_ep_raise_msix_irq (ep , func_no , interrupt_num );
264
+ default :
265
+ dev_err (pci -> dev , "UNKNOWN IRQ type\n" );
266
+ }
267
+
268
+ return 0 ;
269
+ }
270
+
271
+ static const struct pci_epc_features rockchip_pcie_epc_features_rk3568 = {
272
+ .linkup_notifier = true,
273
+ .msi_capable = true,
274
+ .msix_capable = true,
275
+ .align = SZ_64K ,
276
+ .bar [BAR_0 ] = { .type = BAR_FIXED , .fixed_size = SZ_1M , },
277
+ .bar [BAR_1 ] = { .type = BAR_FIXED , .fixed_size = SZ_1M , },
278
+ .bar [BAR_2 ] = { .type = BAR_FIXED , .fixed_size = SZ_1M , },
279
+ .bar [BAR_3 ] = { .type = BAR_FIXED , .fixed_size = SZ_1M , },
280
+ .bar [BAR_4 ] = { .type = BAR_FIXED , .fixed_size = SZ_1M , },
281
+ .bar [BAR_5 ] = { .type = BAR_FIXED , .fixed_size = SZ_1M , },
282
+ };
283
+
284
+ /*
285
+ * BAR4 on rk3588 exposes the ATU Port Logic Structure to the host regardless of
286
+ * iATU settings for BAR4. This means that BAR4 cannot be used by an EPF driver,
287
+ * so mark it as RESERVED. (rockchip_pcie_ep_init() will disable all BARs by
288
+ * default.) If the host could write to BAR4, the iATU settings (for all other
289
+ * BARs) would be overwritten, resulting in (all other BARs) no longer working.
290
+ */
291
+ static const struct pci_epc_features rockchip_pcie_epc_features_rk3588 = {
292
+ .linkup_notifier = true,
293
+ .msi_capable = true,
294
+ .msix_capable = true,
295
+ .align = SZ_64K ,
296
+ .bar [BAR_0 ] = { .type = BAR_FIXED , .fixed_size = SZ_1M , },
297
+ .bar [BAR_1 ] = { .type = BAR_FIXED , .fixed_size = SZ_1M , },
298
+ .bar [BAR_2 ] = { .type = BAR_FIXED , .fixed_size = SZ_1M , },
299
+ .bar [BAR_3 ] = { .type = BAR_FIXED , .fixed_size = SZ_1M , },
300
+ .bar [BAR_4 ] = { .type = BAR_RESERVED , },
301
+ .bar [BAR_5 ] = { .type = BAR_FIXED , .fixed_size = SZ_1M , },
302
+ };
303
+
304
+ static const struct pci_epc_features *
305
+ rockchip_pcie_get_features (struct dw_pcie_ep * ep )
306
+ {
307
+ struct dw_pcie * pci = to_dw_pcie_from_ep (ep );
308
+ struct rockchip_pcie * rockchip = to_rockchip_pcie (pci );
309
+
310
+ return rockchip -> data -> epc_features ;
311
+ }
312
+
313
+ static const struct dw_pcie_ep_ops rockchip_pcie_ep_ops = {
314
+ .init = rockchip_pcie_ep_init ,
315
+ .raise_irq = rockchip_pcie_raise_irq ,
316
+ .get_features = rockchip_pcie_get_features ,
317
+ };
318
+
223
319
static int rockchip_pcie_clk_init (struct rockchip_pcie * rockchip )
224
320
{
225
321
struct device * dev = rockchip -> pci .dev ;
@@ -290,13 +386,46 @@ static void rockchip_pcie_phy_deinit(struct rockchip_pcie *rockchip)
290
386
static const struct dw_pcie_ops dw_pcie_ops = {
291
387
.link_up = rockchip_pcie_link_up ,
292
388
.start_link = rockchip_pcie_start_link ,
389
+ .stop_link = rockchip_pcie_stop_link ,
293
390
};
294
391
392
+ static irqreturn_t rockchip_pcie_ep_sys_irq_thread (int irq , void * arg )
393
+ {
394
+ struct rockchip_pcie * rockchip = arg ;
395
+ struct dw_pcie * pci = & rockchip -> pci ;
396
+ struct device * dev = pci -> dev ;
397
+ u32 reg , val ;
398
+
399
+ reg = rockchip_pcie_readl_apb (rockchip , PCIE_CLIENT_INTR_STATUS_MISC );
400
+ rockchip_pcie_writel_apb (rockchip , reg , PCIE_CLIENT_INTR_STATUS_MISC );
401
+
402
+ dev_dbg (dev , "PCIE_CLIENT_INTR_STATUS_MISC: %#x\n" , reg );
403
+ dev_dbg (dev , "LTSSM_STATUS: %#x\n" , rockchip_pcie_get_ltssm (rockchip ));
404
+
405
+ if (reg & PCIE_LINK_REQ_RST_NOT_INT ) {
406
+ dev_dbg (dev , "hot reset or link-down reset\n" );
407
+ dw_pcie_ep_linkdown (& pci -> ep );
408
+ }
409
+
410
+ if (reg & PCIE_RDLH_LINK_UP_CHGED ) {
411
+ val = rockchip_pcie_get_ltssm (rockchip );
412
+ if ((val & PCIE_LINKUP ) == PCIE_LINKUP ) {
413
+ dev_dbg (dev , "link up\n" );
414
+ dw_pcie_ep_linkup (& pci -> ep );
415
+ }
416
+ }
417
+
418
+ return IRQ_HANDLED ;
419
+ }
420
+
295
421
static int rockchip_pcie_configure_rc (struct rockchip_pcie * rockchip )
296
422
{
297
423
struct dw_pcie_rp * pp ;
298
424
u32 val ;
299
425
426
+ if (!IS_ENABLED (CONFIG_PCIE_ROCKCHIP_DW_HOST ))
427
+ return - ENODEV ;
428
+
300
429
/* LTSSM enable control mode */
301
430
val = HIWORD_UPDATE_BIT (PCIE_LTSSM_ENABLE_ENHANCE );
302
431
rockchip_pcie_writel_apb (rockchip , val , PCIE_CLIENT_HOT_RESET_CTRL );
@@ -310,6 +439,63 @@ static int rockchip_pcie_configure_rc(struct rockchip_pcie *rockchip)
310
439
return dw_pcie_host_init (pp );
311
440
}
312
441
442
+ static int rockchip_pcie_configure_ep (struct platform_device * pdev ,
443
+ struct rockchip_pcie * rockchip )
444
+ {
445
+ struct device * dev = & pdev -> dev ;
446
+ int irq , ret ;
447
+ u32 val ;
448
+
449
+ if (!IS_ENABLED (CONFIG_PCIE_ROCKCHIP_DW_EP ))
450
+ return - ENODEV ;
451
+
452
+ irq = platform_get_irq_byname (pdev , "sys" );
453
+ if (irq < 0 ) {
454
+ dev_err (dev , "missing sys IRQ resource\n" );
455
+ return irq ;
456
+ }
457
+
458
+ ret = devm_request_threaded_irq (dev , irq , NULL ,
459
+ rockchip_pcie_ep_sys_irq_thread ,
460
+ IRQF_ONESHOT , "pcie-sys" , rockchip );
461
+ if (ret ) {
462
+ dev_err (dev , "failed to request PCIe sys IRQ\n" );
463
+ return ret ;
464
+ }
465
+
466
+ /* LTSSM enable control mode */
467
+ val = HIWORD_UPDATE_BIT (PCIE_LTSSM_ENABLE_ENHANCE );
468
+ rockchip_pcie_writel_apb (rockchip , val , PCIE_CLIENT_HOT_RESET_CTRL );
469
+
470
+ rockchip_pcie_writel_apb (rockchip , PCIE_CLIENT_EP_MODE ,
471
+ PCIE_CLIENT_GENERAL_CONTROL );
472
+
473
+ rockchip -> pci .ep .ops = & rockchip_pcie_ep_ops ;
474
+ rockchip -> pci .ep .page_size = SZ_64K ;
475
+
476
+ dma_set_mask_and_coherent (dev , DMA_BIT_MASK (64 ));
477
+
478
+ ret = dw_pcie_ep_init (& rockchip -> pci .ep );
479
+ if (ret ) {
480
+ dev_err (dev , "failed to initialize endpoint\n" );
481
+ return ret ;
482
+ }
483
+
484
+ ret = dw_pcie_ep_init_registers (& rockchip -> pci .ep );
485
+ if (ret ) {
486
+ dev_err (dev , "failed to initialize DWC endpoint registers\n" );
487
+ dw_pcie_ep_deinit (& rockchip -> pci .ep );
488
+ return ret ;
489
+ }
490
+
491
+ dw_pcie_ep_init_notify (& rockchip -> pci .ep );
492
+
493
+ /* unmask DLL up/down indicator and hot reset/link-down reset */
494
+ rockchip_pcie_writel_apb (rockchip , 0x60000 , PCIE_CLIENT_INTR_MASK_MISC );
495
+
496
+ return ret ;
497
+ }
498
+
313
499
static int rockchip_pcie_probe (struct platform_device * pdev )
314
500
{
315
501
struct device * dev = & pdev -> dev ;
@@ -371,6 +557,11 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
371
557
if (ret )
372
558
goto deinit_clk ;
373
559
break ;
560
+ case DW_PCIE_EP_TYPE :
561
+ ret = rockchip_pcie_configure_ep (pdev , rockchip );
562
+ if (ret )
563
+ goto deinit_clk ;
564
+ break ;
374
565
default :
375
566
dev_err (dev , "INVALID device type %d\n" , data -> mode );
376
567
ret = - EINVAL ;
@@ -394,11 +585,29 @@ static const struct rockchip_pcie_of_data rockchip_pcie_rc_of_data_rk3568 = {
394
585
.mode = DW_PCIE_RC_TYPE ,
395
586
};
396
587
588
+ static const struct rockchip_pcie_of_data rockchip_pcie_ep_of_data_rk3568 = {
589
+ .mode = DW_PCIE_EP_TYPE ,
590
+ .epc_features = & rockchip_pcie_epc_features_rk3568 ,
591
+ };
592
+
593
+ static const struct rockchip_pcie_of_data rockchip_pcie_ep_of_data_rk3588 = {
594
+ .mode = DW_PCIE_EP_TYPE ,
595
+ .epc_features = & rockchip_pcie_epc_features_rk3588 ,
596
+ };
597
+
397
598
static const struct of_device_id rockchip_pcie_of_match [] = {
398
599
{
399
600
.compatible = "rockchip,rk3568-pcie" ,
400
601
.data = & rockchip_pcie_rc_of_data_rk3568 ,
401
602
},
603
+ {
604
+ .compatible = "rockchip,rk3568-pcie-ep" ,
605
+ .data = & rockchip_pcie_ep_of_data_rk3568 ,
606
+ },
607
+ {
608
+ .compatible = "rockchip,rk3588-pcie-ep" ,
609
+ .data = & rockchip_pcie_ep_of_data_rk3588 ,
610
+ },
402
611
{},
403
612
};
404
613
0 commit comments