Skip to content

Commit f6fd357

Browse files
PCI: dwc: Prepare the driver for enabling ECAM mechanism using iATU 'CFG Shift Feature'
In order to enable PCIe ECAM mechanism in DWC driver as per the 'CFG Shift Feature' documented in Designware databook r5.20a, sec 3.10.10.3, prepare the driver to handle the one time iATU setup and creating ECAM window. Signed-off-by: Krishna Chaitanya Chundru <[email protected]> [mani: splitted the preparatory code into a separate commit for bisectability] Signed-off-by: Manivannan Sadhasivam <[email protected]> Link: https://patch.msgid.link/[email protected]
1 parent c96992a commit f6fd357

File tree

4 files changed

+109
-15
lines changed

4 files changed

+109
-15
lines changed

drivers/pci/controller/dwc/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ config PCIE_DW_HOST
2020
bool
2121
select PCIE_DW
2222
select IRQ_MSI_LIB
23+
select PCI_HOST_COMMON
2324

2425
config PCIE_DW_EP
2526
bool

drivers/pci/controller/dwc/pcie-designware-host.c

Lines changed: 102 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
416477
static 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
}
592677
EXPORT_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
}
613701
EXPORT_SYMBOL_GPL(dw_pcie_host_deinit);
614702

drivers/pci/controller/dwc/pcie-designware.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
575575
val = dw_pcie_enable_ecrc(val);
576576
dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_REGION_CTRL1, val);
577577

578-
val = PCIE_ATU_ENABLE;
578+
val = PCIE_ATU_ENABLE | atu->ctrl2;
579579
if (atu->type == PCIE_ATU_TYPE_MSG) {
580580
/* The data-less messages only for now */
581581
val |= PCIE_ATU_INHIBIT_PAYLOAD | atu->code;

drivers/pci/controller/dwc/pcie-designware.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/irq.h>
2121
#include <linux/msi.h>
2222
#include <linux/pci.h>
23+
#include <linux/pci-ecam.h>
2324
#include <linux/reset.h>
2425

2526
#include <linux/pci-epc.h>
@@ -168,6 +169,7 @@
168169
#define PCIE_ATU_REGION_CTRL2 0x004
169170
#define PCIE_ATU_ENABLE BIT(31)
170171
#define PCIE_ATU_BAR_MODE_ENABLE BIT(30)
172+
#define PCIE_ATU_CFG_SHIFT_MODE_ENABLE BIT(28)
171173
#define PCIE_ATU_INHIBIT_PAYLOAD BIT(22)
172174
#define PCIE_ATU_FUNC_NUM_MATCH_EN BIT(19)
173175
#define PCIE_ATU_LOWER_BASE 0x008
@@ -386,6 +388,7 @@ struct dw_pcie_ob_atu_cfg {
386388
u8 func_no;
387389
u8 code;
388390
u8 routing;
391+
u32 ctrl2;
389392
u64 parent_bus_addr;
390393
u64 pci_addr;
391394
u64 size;
@@ -424,6 +427,8 @@ struct dw_pcie_rp {
424427
struct resource *msg_res;
425428
bool use_linkup_irq;
426429
struct pci_eq_presets presets;
430+
struct pci_config_window *cfg;
431+
bool ecam_enabled;
427432
};
428433

429434
struct dw_pcie_ep_ops {

0 commit comments

Comments
 (0)