Merge branch 'pci/host-layerscape' into next

* pci/host-layerscape:
  PCI: layerscape: Add support for ls1088a
  PCI: layerscape: Add support for ls2088a
  PCI: artpec6: Stop enabling writes to DBI read-only registers
  PCI: layerscape: Remove unnecessary class code fixup
  PCI: dwc: Enable write permission for Class Code, Interrupt Pin updates
  PCI: dwc: Add accessors for write permission of DBI read-only registers
  PCI: layerscape: Disable outbound windows configured by bootloader
  PCI: layerscape: Refactor ls1021_pcie_host_init()
  PCI: layerscape: Move generic init functions earlier in file
  PCI: layerscape: Add class code and multifunction fixups for ls1021a
  PCI: layerscape: Move STRFMR1 access out from the DBI write-enable bracket
  PCI: layerscape: Call dw_pcie_setup_rc() from ls_pcie_host_init()
This commit is contained in:
Bjorn Helgaas 2017-09-07 13:24:02 -05:00
commit 9857f12565
5 changed files with 92 additions and 49 deletions

View File

@ -15,6 +15,8 @@ Required properties:
- compatible: should contain the platform identifier such as:
"fsl,ls1021a-pcie", "snps,dw-pcie"
"fsl,ls2080a-pcie", "fsl,ls2085a-pcie", "snps,dw-pcie"
"fsl,ls2088a-pcie"
"fsl,ls1088a-pcie"
"fsl,ls1046a-pcie"
- reg: base addresses and lengths of the PCIe controller
- interrupts: A list of interrupt outputs of the controller. Must contain an

View File

@ -33,7 +33,8 @@
/* PEX Internal Configuration Registers */
#define PCIE_STRFMR1 0x71c /* Symbol Timer & Filter Mask Register1 */
#define PCIE_DBI_RO_WR_EN 0x8bc /* DBI Read-Only Write Enable Register */
#define PCIE_IATU_NUM 6
struct ls_pcie_drvdata {
u32 lut_offset;
@ -72,14 +73,6 @@ static void ls_pcie_clear_multifunction(struct ls_pcie *pcie)
iowrite8(PCI_HEADER_TYPE_BRIDGE, pci->dbi_base + PCI_HEADER_TYPE);
}
/* Fix class value */
static void ls_pcie_fix_class(struct ls_pcie *pcie)
{
struct dw_pcie *pci = pcie->pci;
iowrite16(PCI_CLASS_BRIDGE_PCI, pci->dbi_base + PCI_CLASS_DEVICE);
}
/* Drop MSG TLP except for Vendor MSG */
static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie)
{
@ -91,6 +84,14 @@ static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie)
iowrite32(val, pci->dbi_base + PCIE_STRFMR1);
}
static void ls_pcie_disable_outbound_atus(struct ls_pcie *pcie)
{
int i;
for (i = 0; i < PCIE_IATU_NUM; i++)
dw_pcie_disable_atu(pcie->pci, DW_PCIE_REGION_OUTBOUND, i);
}
static int ls1021_pcie_link_up(struct dw_pcie *pci)
{
u32 state;
@ -108,6 +109,44 @@ static int ls1021_pcie_link_up(struct dw_pcie *pci)
return 1;
}
static int ls_pcie_link_up(struct dw_pcie *pci)
{
struct ls_pcie *pcie = to_ls_pcie(pci);
u32 state;
state = (ioread32(pcie->lut + pcie->drvdata->lut_dbg) >>
pcie->drvdata->ltssm_shift) &
LTSSM_STATE_MASK;
if (state < LTSSM_PCIE_L0)
return 0;
return 1;
}
static int ls_pcie_host_init(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct ls_pcie *pcie = to_ls_pcie(pci);
/*
* Disable outbound windows configured by the bootloader to avoid
* one transaction hitting multiple outbound windows.
* dw_pcie_setup_rc() will reconfigure the outbound windows.
*/
ls_pcie_disable_outbound_atus(pcie);
dw_pcie_dbi_ro_wr_en(pci);
ls_pcie_clear_multifunction(pcie);
dw_pcie_dbi_ro_wr_dis(pci);
ls_pcie_drop_msg_tlp(pcie);
dw_pcie_setup_rc(pp);
return 0;
}
static int ls1021_pcie_host_init(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
@ -132,40 +171,7 @@ static int ls1021_pcie_host_init(struct pcie_port *pp)
}
pcie->index = index[1];
dw_pcie_setup_rc(pp);
ls_pcie_drop_msg_tlp(pcie);
return 0;
}
static int ls_pcie_link_up(struct dw_pcie *pci)
{
struct ls_pcie *pcie = to_ls_pcie(pci);
u32 state;
state = (ioread32(pcie->lut + pcie->drvdata->lut_dbg) >>
pcie->drvdata->ltssm_shift) &
LTSSM_STATE_MASK;
if (state < LTSSM_PCIE_L0)
return 0;
return 1;
}
static int ls_pcie_host_init(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct ls_pcie *pcie = to_ls_pcie(pci);
iowrite32(1, pci->dbi_base + PCIE_DBI_RO_WR_EN);
ls_pcie_fix_class(pcie);
ls_pcie_clear_multifunction(pcie);
ls_pcie_drop_msg_tlp(pcie);
iowrite32(0, pci->dbi_base + PCIE_DBI_RO_WR_EN);
return 0;
return ls_pcie_host_init(pp);
}
static int ls_pcie_msi_host_init(struct pcie_port *pp,
@ -238,12 +244,22 @@ static struct ls_pcie_drvdata ls2080_drvdata = {
.dw_pcie_ops = &dw_ls_pcie_ops,
};
static struct ls_pcie_drvdata ls2088_drvdata = {
.lut_offset = 0x80000,
.ltssm_shift = 0,
.lut_dbg = 0x407fc,
.ops = &ls_pcie_host_ops,
.dw_pcie_ops = &dw_ls_pcie_ops,
};
static const struct of_device_id ls_pcie_of_match[] = {
{ .compatible = "fsl,ls1021a-pcie", .data = &ls1021_drvdata },
{ .compatible = "fsl,ls1043a-pcie", .data = &ls1043_drvdata },
{ .compatible = "fsl,ls1046a-pcie", .data = &ls1046_drvdata },
{ .compatible = "fsl,ls2080a-pcie", .data = &ls2080_drvdata },
{ .compatible = "fsl,ls2085a-pcie", .data = &ls2080_drvdata },
{ .compatible = "fsl,ls2088a-pcie", .data = &ls2088_drvdata },
{ .compatible = "fsl,ls1088a-pcie", .data = &ls2088_drvdata },
{ },
};

View File

@ -141,12 +141,6 @@ static int artpec6_pcie_establish_link(struct artpec6_pcie *artpec6_pcie)
artpec6_pcie_writel(artpec6_pcie, PCIECFG, val);
usleep_range(100, 200);
/*
* Enable writing to config regs. This is required as the Synopsys
* driver changes the class code. That register needs DBI write enable.
*/
dw_pcie_writel_dbi(pci, MISC_CONTROL_1_OFF, DBI_RO_WR_EN);
/* setup root complex */
dw_pcie_setup_rc(pp);

View File

@ -597,10 +597,12 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0x00000000);
/* setup interrupt pins */
dw_pcie_dbi_ro_wr_en(pci);
val = dw_pcie_readl_dbi(pci, PCI_INTERRUPT_LINE);
val &= 0xffff00ff;
val |= 0x00000100;
dw_pcie_writel_dbi(pci, PCI_INTERRUPT_LINE, val);
dw_pcie_dbi_ro_wr_dis(pci);
/* setup bus numbers */
val = dw_pcie_readl_dbi(pci, PCI_PRIMARY_BUS);
@ -637,8 +639,12 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
/* Enable write permission for the DBI read-only register */
dw_pcie_dbi_ro_wr_en(pci);
/* program correct class for RC */
dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI);
/* Better disable write permission right after the update */
dw_pcie_dbi_ro_wr_dis(pci);
dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val);
val |= PORT_LOGIC_SPEED_CHANGE;

View File

@ -76,6 +76,9 @@
#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
#define PCIE_ATU_UPPER_TARGET 0x91C
#define PCIE_MISC_CONTROL_1_OFF 0x8BC
#define PCIE_DBI_RO_WR_EN (0x1 << 0)
/*
* iATU Unroll-specific register definitions
* From 4.80 core version the address translation will be made by unroll
@ -279,6 +282,28 @@ static inline u32 dw_pcie_readl_dbi2(struct dw_pcie *pci, u32 reg)
return __dw_pcie_read_dbi(pci, pci->dbi_base2, reg, 0x4);
}
static inline void dw_pcie_dbi_ro_wr_en(struct dw_pcie *pci)
{
u32 reg;
u32 val;
reg = PCIE_MISC_CONTROL_1_OFF;
val = dw_pcie_readl_dbi(pci, reg);
val |= PCIE_DBI_RO_WR_EN;
dw_pcie_writel_dbi(pci, reg, val);
}
static inline void dw_pcie_dbi_ro_wr_dis(struct dw_pcie *pci)
{
u32 reg;
u32 val;
reg = PCIE_MISC_CONTROL_1_OFF;
val = dw_pcie_readl_dbi(pci, reg);
val &= ~PCIE_DBI_RO_WR_EN;
dw_pcie_writel_dbi(pci, reg, val);
}
#ifdef CONFIG_PCIE_DW_HOST
irqreturn_t dw_handle_msi_irq(struct pcie_port *pp);
void dw_pcie_msi_init(struct pcie_port *pp);