3434#define to_rockchip_pcie (x ) dev_get_drvdata((x)->dev)
3535
3636#define PCIE_CLIENT_RC_MODE HIWORD_UPDATE_BIT(0x40)
37+ #define PCIE_CLIENT_EP_MODE HIWORD_UPDATE(0xf0, 0x0)
3738#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
3842#define PCIE_SMLH_LINKUP BIT(16)
3943#define PCIE_RDLH_LINKUP BIT(17)
4044#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)
4147#define PCIE_L0S_ENTRY 0x11
4248#define PCIE_CLIENT_GENERAL_CONTROL 0x0
4349#define PCIE_CLIENT_INTR_STATUS_LEGACY 0x8
@@ -63,6 +69,7 @@ struct rockchip_pcie {
6369
6470struct rockchip_pcie_of_data {
6571 enum dw_pcie_device_mode mode ;
72+ const struct pci_epc_features * epc_features ;
6673};
6774
6875static 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)
159166 PCIE_CLIENT_GENERAL_CONTROL );
160167}
161168
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+
162175static int rockchip_pcie_link_up (struct dw_pcie * pci )
163176{
164177 struct rockchip_pcie * rockchip = to_rockchip_pcie (pci );
@@ -195,6 +208,13 @@ static int rockchip_pcie_start_link(struct dw_pcie *pci)
195208 return 0 ;
196209}
197210
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+
198218static int rockchip_pcie_host_init (struct dw_pcie_rp * pp )
199219{
200220 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 = {
220240 .init = rockchip_pcie_host_init ,
221241};
222242
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+
223319static int rockchip_pcie_clk_init (struct rockchip_pcie * rockchip )
224320{
225321 struct device * dev = rockchip -> pci .dev ;
@@ -290,13 +386,46 @@ static void rockchip_pcie_phy_deinit(struct rockchip_pcie *rockchip)
290386static const struct dw_pcie_ops dw_pcie_ops = {
291387 .link_up = rockchip_pcie_link_up ,
292388 .start_link = rockchip_pcie_start_link ,
389+ .stop_link = rockchip_pcie_stop_link ,
293390};
294391
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+
295421static int rockchip_pcie_configure_rc (struct rockchip_pcie * rockchip )
296422{
297423 struct dw_pcie_rp * pp ;
298424 u32 val ;
299425
426+ if (!IS_ENABLED (CONFIG_PCIE_ROCKCHIP_DW_HOST ))
427+ return - ENODEV ;
428+
300429 /* LTSSM enable control mode */
301430 val = HIWORD_UPDATE_BIT (PCIE_LTSSM_ENABLE_ENHANCE );
302431 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)
310439 return dw_pcie_host_init (pp );
311440}
312441
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+
313499static int rockchip_pcie_probe (struct platform_device * pdev )
314500{
315501 struct device * dev = & pdev -> dev ;
@@ -371,6 +557,11 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
371557 if (ret )
372558 goto deinit_clk ;
373559 break ;
560+ case DW_PCIE_EP_TYPE :
561+ ret = rockchip_pcie_configure_ep (pdev , rockchip );
562+ if (ret )
563+ goto deinit_clk ;
564+ break ;
374565 default :
375566 dev_err (dev , "INVALID device type %d\n" , data -> mode );
376567 ret = - EINVAL ;
@@ -394,11 +585,29 @@ static const struct rockchip_pcie_of_data rockchip_pcie_rc_of_data_rk3568 = {
394585 .mode = DW_PCIE_RC_TYPE ,
395586};
396587
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+
397598static const struct of_device_id rockchip_pcie_of_match [] = {
398599 {
399600 .compatible = "rockchip,rk3568-pcie" ,
400601 .data = & rockchip_pcie_rc_of_data_rk3568 ,
401602 },
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+ },
402611 {},
403612};
404613
0 commit comments