Skip to content

Commit a0601a4

Browse files
Joao Pintobjorn-helgaas
Joao Pinto
authored andcommitted
PCI: designware: Add iATU Unroll feature
Add support for the new iATU Unroll mechanism that will be used from Core version 4.80. The new Cores can support either iATU Unroll or the "old" iATU method, now called Legacy Mode. The driver is perfectly capable of performing well for both. [bhelgaas: split ATU enable timeout to separate patch] Signed-off-by: Joao Pinto <jpinto@synopsys.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
1 parent d8bbeb3 commit a0601a4

File tree

2 files changed

+87
-11
lines changed

2 files changed

+87
-11
lines changed

drivers/pci/host/pcie-designware.c

Lines changed: 86 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,21 @@
8080
#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
8181
#define PCIE_ATU_UPPER_TARGET 0x91C
8282

83+
/*
84+
* iATU Unroll-specific register definitions
85+
* From 4.80 core version the address translation will be made by unroll
86+
*/
87+
#define PCIE_ATU_UNR_REGION_CTRL1 0x00
88+
#define PCIE_ATU_UNR_REGION_CTRL2 0x04
89+
#define PCIE_ATU_UNR_LOWER_BASE 0x08
90+
#define PCIE_ATU_UNR_UPPER_BASE 0x0C
91+
#define PCIE_ATU_UNR_LIMIT 0x10
92+
#define PCIE_ATU_UNR_LOWER_TARGET 0x14
93+
#define PCIE_ATU_UNR_UPPER_TARGET 0x18
94+
95+
/* Register address builder */
96+
#define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region) ((0x3 << 20) | (region << 9))
97+
8398
/* PCIe Port Logic registers */
8499
#define PLR_OFFSET 0x700
85100
#define PCIE_PHY_DEBUG_R1 (PLR_OFFSET + 0x2c)
@@ -141,6 +156,27 @@ static inline void dw_pcie_writel_rc(struct pcie_port *pp, u32 val, u32 reg)
141156
writel(val, pp->dbi_base + reg);
142157
}
143158

159+
static inline u32 dw_pcie_readl_unroll(struct pcie_port *pp, u32 index, u32 reg)
160+
{
161+
u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
162+
163+
if (pp->ops->readl_rc)
164+
return pp->ops->readl_rc(pp, pp->dbi_base + offset + reg);
165+
166+
return readl(pp->dbi_base + offset + reg);
167+
}
168+
169+
static inline void dw_pcie_writel_unroll(struct pcie_port *pp, u32 index,
170+
u32 val, u32 reg)
171+
{
172+
u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
173+
174+
if (pp->ops->writel_rc)
175+
pp->ops->writel_rc(pp, val, pp->dbi_base + offset + reg);
176+
else
177+
writel(val, pp->dbi_base + offset + reg);
178+
}
179+
144180
static int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
145181
u32 *val)
146182
{
@@ -164,23 +200,49 @@ static void dw_pcie_prog_outbound_atu(struct pcie_port *pp, int index,
164200
{
165201
u32 retries, val;
166202

167-
dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | index,
168-
PCIE_ATU_VIEWPORT);
169-
dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr), PCIE_ATU_LOWER_BASE);
170-
dw_pcie_writel_rc(pp, upper_32_bits(cpu_addr), PCIE_ATU_UPPER_BASE);
171-
dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr + size - 1),
172-
PCIE_ATU_LIMIT);
173-
dw_pcie_writel_rc(pp, lower_32_bits(pci_addr), PCIE_ATU_LOWER_TARGET);
174-
dw_pcie_writel_rc(pp, upper_32_bits(pci_addr), PCIE_ATU_UPPER_TARGET);
175-
dw_pcie_writel_rc(pp, type, PCIE_ATU_CR1);
176-
dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
203+
if (pp->iatu_unroll_enabled) {
204+
dw_pcie_writel_unroll(pp, index,
205+
lower_32_bits(cpu_addr), PCIE_ATU_UNR_LOWER_BASE);
206+
dw_pcie_writel_unroll(pp, index,
207+
upper_32_bits(cpu_addr), PCIE_ATU_UNR_UPPER_BASE);
208+
dw_pcie_writel_unroll(pp, index,
209+
lower_32_bits(cpu_addr + size - 1), PCIE_ATU_UNR_LIMIT);
210+
dw_pcie_writel_unroll(pp, index,
211+
lower_32_bits(pci_addr), PCIE_ATU_UNR_LOWER_TARGET);
212+
dw_pcie_writel_unroll(pp, index,
213+
upper_32_bits(pci_addr), PCIE_ATU_UNR_UPPER_TARGET);
214+
dw_pcie_writel_unroll(pp, index,
215+
type, PCIE_ATU_UNR_REGION_CTRL1);
216+
dw_pcie_writel_unroll(pp, index,
217+
PCIE_ATU_ENABLE, PCIE_ATU_UNR_REGION_CTRL2);
218+
} else {
219+
dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | index,
220+
PCIE_ATU_VIEWPORT);
221+
dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr),
222+
PCIE_ATU_LOWER_BASE);
223+
dw_pcie_writel_rc(pp, upper_32_bits(cpu_addr),
224+
PCIE_ATU_UPPER_BASE);
225+
dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr + size - 1),
226+
PCIE_ATU_LIMIT);
227+
dw_pcie_writel_rc(pp, lower_32_bits(pci_addr),
228+
PCIE_ATU_LOWER_TARGET);
229+
dw_pcie_writel_rc(pp, upper_32_bits(pci_addr),
230+
PCIE_ATU_UPPER_TARGET);
231+
dw_pcie_writel_rc(pp, type, PCIE_ATU_CR1);
232+
dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
233+
}
177234

178235
/*
179236
* Make sure ATU enable takes effect before any subsequent config
180237
* and I/O accesses.
181238
*/
182239
for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
183-
val = dw_pcie_readl_rc(pp, PCIE_ATU_CR2);
240+
if (pp->iatu_unroll_enabled)
241+
val = dw_pcie_readl_unroll(pp, index,
242+
PCIE_ATU_UNR_REGION_CTRL2);
243+
else
244+
val = dw_pcie_readl_rc(pp, PCIE_ATU_CR2);
245+
184246
if (val == PCIE_ATU_ENABLE)
185247
return;
186248

@@ -445,6 +507,17 @@ static const struct irq_domain_ops msi_domain_ops = {
445507
.map = dw_pcie_msi_map,
446508
};
447509

510+
static u8 dw_pcie_iatu_unroll_enabled(struct pcie_port *pp)
511+
{
512+
u32 val;
513+
514+
val = dw_pcie_readl_rc(pp, PCIE_ATU_VIEWPORT);
515+
if (val == 0xffffffff)
516+
return 1;
517+
518+
return 0;
519+
}
520+
448521
int dw_pcie_host_init(struct pcie_port *pp)
449522
{
450523
struct device_node *np = pp->dev->of_node;
@@ -561,6 +634,8 @@ int dw_pcie_host_init(struct pcie_port *pp)
561634
}
562635
}
563636

637+
pp->iatu_unroll_enabled = dw_pcie_iatu_unroll_enabled(pp);
638+
564639
if (pp->ops->host_init)
565640
pp->ops->host_init(pp);
566641

drivers/pci/host/pcie-designware.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ struct pcie_port {
4848
int msi_irq;
4949
struct irq_domain *irq_domain;
5050
unsigned long msi_data;
51+
u8 iatu_unroll_enabled;
5152
DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);
5253
};
5354

0 commit comments

Comments
 (0)