mirror of https://gitee.com/openkylin/linux.git
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:
commit
9857f12565
|
@ -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
|
||||
|
|
|
@ -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 },
|
||||
{ },
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue