@@ -413,6 +413,67 @@ static void dw_pcie_host_request_msg_tlp_res(struct dw_pcie_rp *pp)
413413 }
414414}
415415
416+ static int dw_pcie_config_ecam_iatu (struct dw_pcie_rp * pp )
417+ {
418+ struct dw_pcie * pci = to_dw_pcie_from_pp (pp );
419+ struct dw_pcie_ob_atu_cfg atu = {0 };
420+ resource_size_t bus_range_max ;
421+ struct resource_entry * bus ;
422+ int ret ;
423+
424+ bus = resource_list_first_type (& pp -> bridge -> windows , IORESOURCE_BUS );
425+
426+ /*
427+ * Root bus under the host bridge doesn't require any iATU configuration
428+ * as DBI region will be used to access root bus config space.
429+ * Immediate bus under Root Bus, needs type 0 iATU configuration and
430+ * remaining buses need type 1 iATU configuration.
431+ */
432+ atu .index = 0 ;
433+ atu .type = PCIE_ATU_TYPE_CFG0 ;
434+ atu .parent_bus_addr = pp -> cfg0_base + SZ_1M ;
435+ /* 1MiB is to cover 1 (bus) * 32 (devices) * 8 (functions) */
436+ atu .size = SZ_1M ;
437+ atu .ctrl2 = PCIE_ATU_CFG_SHIFT_MODE_ENABLE ;
438+ ret = dw_pcie_prog_outbound_atu (pci , & atu );
439+ if (ret )
440+ return ret ;
441+
442+ bus_range_max = resource_size (bus -> res );
443+
444+ if (bus_range_max < 2 )
445+ return 0 ;
446+
447+ /* Configure remaining buses in type 1 iATU configuration */
448+ atu .index = 1 ;
449+ atu .type = PCIE_ATU_TYPE_CFG1 ;
450+ atu .parent_bus_addr = pp -> cfg0_base + SZ_2M ;
451+ atu .size = (SZ_1M * bus_range_max ) - SZ_2M ;
452+ atu .ctrl2 = PCIE_ATU_CFG_SHIFT_MODE_ENABLE ;
453+
454+ return dw_pcie_prog_outbound_atu (pci , & atu );
455+ }
456+
457+ static int dw_pcie_create_ecam_window (struct dw_pcie_rp * pp , struct resource * res )
458+ {
459+ struct dw_pcie * pci = to_dw_pcie_from_pp (pp );
460+ struct device * dev = pci -> dev ;
461+ struct resource_entry * bus ;
462+
463+ bus = resource_list_first_type (& pp -> bridge -> windows , IORESOURCE_BUS );
464+ if (!bus )
465+ return - ENODEV ;
466+
467+ pp -> cfg = pci_ecam_create (dev , res , bus -> res , & pci_generic_ecam_ops );
468+ if (IS_ERR (pp -> cfg ))
469+ return PTR_ERR (pp -> cfg );
470+
471+ pci -> dbi_base = pp -> cfg -> win ;
472+ pci -> dbi_phys_addr = res -> start ;
473+
474+ return 0 ;
475+ }
476+
416477static int dw_pcie_host_get_resources (struct dw_pcie_rp * pp )
417478{
418479 struct dw_pcie * pci = to_dw_pcie_from_pp (pp );
@@ -422,10 +483,6 @@ static int dw_pcie_host_get_resources(struct dw_pcie_rp *pp)
422483 struct resource * res ;
423484 int ret ;
424485
425- ret = dw_pcie_get_resources (pci );
426- if (ret )
427- return ret ;
428-
429486 res = platform_get_resource_byname (pdev , IORESOURCE_MEM , "config" );
430487 if (!res ) {
431488 dev_err (dev , "Missing \"config\" reg space\n" );
@@ -435,9 +492,31 @@ static int dw_pcie_host_get_resources(struct dw_pcie_rp *pp)
435492 pp -> cfg0_size = resource_size (res );
436493 pp -> cfg0_base = res -> start ;
437494
438- pp -> va_cfg0_base = devm_pci_remap_cfg_resource (dev , res );
439- if (IS_ERR (pp -> va_cfg0_base ))
440- return PTR_ERR (pp -> va_cfg0_base );
495+ if (pp -> ecam_enabled ) {
496+ ret = dw_pcie_create_ecam_window (pp , res );
497+ if (ret )
498+ return ret ;
499+
500+ pp -> bridge -> ops = (struct pci_ops * )& pci_generic_ecam_ops .pci_ops ;
501+ pp -> bridge -> sysdata = pp -> cfg ;
502+ pp -> cfg -> priv = pp ;
503+ } else {
504+ pp -> va_cfg0_base = devm_pci_remap_cfg_resource (dev , res );
505+ if (IS_ERR (pp -> va_cfg0_base ))
506+ return PTR_ERR (pp -> va_cfg0_base );
507+
508+ /* Set default bus ops */
509+ pp -> bridge -> ops = & dw_pcie_ops ;
510+ pp -> bridge -> child_ops = & dw_child_pcie_ops ;
511+ pp -> bridge -> sysdata = pp ;
512+ }
513+
514+ ret = dw_pcie_get_resources (pci );
515+ if (ret ) {
516+ if (pp -> cfg )
517+ pci_ecam_free (pp -> cfg );
518+ return ret ;
519+ }
441520
442521 /* Get the I/O range from DT */
443522 win = resource_list_first_type (& pp -> bridge -> windows , IORESOURCE_IO );
@@ -476,14 +555,10 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
476555 if (ret )
477556 return ret ;
478557
479- /* Set default bus ops */
480- bridge -> ops = & dw_pcie_ops ;
481- bridge -> child_ops = & dw_child_pcie_ops ;
482-
483558 if (pp -> ops -> init ) {
484559 ret = pp -> ops -> init (pp );
485560 if (ret )
486- return ret ;
561+ goto err_free_ecam ;
487562 }
488563
489564 if (pci_msi_enabled ()) {
@@ -525,6 +600,14 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
525600 if (ret )
526601 goto err_free_msi ;
527602
603+ if (pp -> ecam_enabled ) {
604+ ret = dw_pcie_config_ecam_iatu (pp );
605+ if (ret ) {
606+ dev_err (dev , "Failed to configure iATU in ECAM mode\n" );
607+ goto err_free_msi ;
608+ }
609+ }
610+
528611 /*
529612 * Allocate the resource for MSG TLP before programming the iATU
530613 * outbound window in dw_pcie_setup_rc(). Since the allocation depends
@@ -560,8 +643,6 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
560643 /* Ignore errors, the link may come up later */
561644 dw_pcie_wait_for_link (pci );
562645
563- bridge -> sysdata = pp ;
564-
565646 ret = pci_host_probe (bridge );
566647 if (ret )
567648 goto err_stop_link ;
@@ -587,6 +668,10 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
587668 if (pp -> ops -> deinit )
588669 pp -> ops -> deinit (pp );
589670
671+ err_free_ecam :
672+ if (pp -> cfg )
673+ pci_ecam_free (pp -> cfg );
674+
590675 return ret ;
591676}
592677EXPORT_SYMBOL_GPL (dw_pcie_host_init );
@@ -609,6 +694,9 @@ void dw_pcie_host_deinit(struct dw_pcie_rp *pp)
609694
610695 if (pp -> ops -> deinit )
611696 pp -> ops -> deinit (pp );
697+
698+ if (pp -> cfg )
699+ pci_ecam_free (pp -> cfg );
612700}
613701EXPORT_SYMBOL_GPL (dw_pcie_host_deinit );
614702
0 commit comments