Skip to content

Commit

Permalink
PCI: layerscape: Add support for LS1043a and LS2080a
Browse files Browse the repository at this point in the history
Both LS1043a and LS2080a are based on ARMv8 64-bit architecture and have
similar PCIe implementation.  LUT is added to controller.

Add LS1043a and LS2080a support.

[bhelgaas: move unused field removal into separate patch, include DT update]
Signed-off-by: Bhupesh Sharma <bhupesh.sharma@freescale.com> (DT update)
Signed-off-by: Minghuan Lian <Minghuan.Lian@freescale.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Arnd Bergmann <arnd@arndb.de> (DT update)
  • Loading branch information
Minghuan Lian authored and Bjorn Helgaas committed Nov 2, 2015
1 parent 0f3cb32 commit 5192ec7
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 7 deletions.
14 changes: 12 additions & 2 deletions Documentation/devicetree/bindings/pci/layerscape-pci.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
Freescale Layerscape PCIe controller

This PCIe host controller is based on the Synopsis Designware PCIe IP
This PCIe host controller is based on the Synopsys DesignWare PCIe IP
and thus inherits all the common properties defined in designware-pcie.txt.

This controller derives its clocks from the Reset Configuration Word (RCW)
which is used to describe the PLL settings at the time of chip-reset.

Also as per the available Reference Manuals, there is no specific 'version'
register available in the Freescale PCIe controller register set,
which can allow determining the underlying DesignWare PCIe controller version
information.

Required properties:
- compatible: should contain the platform identifier such as "fsl,ls1021a-pcie"
- compatible: should contain the platform identifier such as:
"fsl,ls1021a-pcie", "snps,dw-pcie"
"fsl,ls2080a-pcie", "snps,dw-pcie"
- reg: base addresses and lengths of the PCIe controller
- interrupts: A list of interrupt outputs of the controller. Must contain an
entry for each entry in the interrupt-names property.
Expand Down
2 changes: 1 addition & 1 deletion drivers/pci/host/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ config PCI_XGENE_MSI

config PCI_LAYERSCAPE
bool "Freescale Layerscape PCIe controller"
depends on OF && ARM
depends on OF && (ARM || ARCH_LAYERSCAPE)
select PCIE_DW
select MFD_SYSCON
help
Expand Down
71 changes: 67 additions & 4 deletions drivers/pci/host/pci-layerscape.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* Copyright (C) 2014 Freescale Semiconductor.
*
* Author: Minghuan Lian <Minghuan.Lian@freescale.com>
* Author: Minghuan Lian <Minghuan.Lian@freescale.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
Expand Down Expand Up @@ -31,20 +31,26 @@
#define LTSSM_STATE_MASK 0x3f
#define LTSSM_PCIE_L0 0x11 /* L0 state */

/* Symbol Timer Register and Filter Mask Register 1 */
#define PCIE_STRFMR1 0x71c
/* 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 */

/* PEX LUT registers */
#define PCIE_LUT_DBG 0x7FC /* PEX LUT Debug Register */

struct ls_pcie_drvdata {
u32 lut_offset;
u32 ltssm_shift;
struct pcie_host_ops *ops;
};

struct ls_pcie {
void __iomem *dbi;
void __iomem *lut;
struct regmap *scfg;
struct pcie_port pp;
const struct ls_pcie_drvdata *drvdata;
int index;
int msi_irq;
};

#define to_ls_pcie(x) container_of(x, struct ls_pcie, pp)
Expand All @@ -59,6 +65,18 @@ static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
return header_type == PCI_HEADER_TYPE_BRIDGE;
}

/* Clear multi-function bit */
static void ls_pcie_clear_multifunction(struct ls_pcie *pcie)
{
iowrite8(PCI_HEADER_TYPE_BRIDGE, pcie->dbi + PCI_HEADER_TYPE);
}

/* Fix class value */
static void ls_pcie_fix_class(struct ls_pcie *pcie)
{
iowrite16(PCI_CLASS_BRIDGE_PCI, pcie->dbi + PCI_CLASS_DEVICE);
}

static int ls1021_pcie_link_up(struct pcie_port *pp)
{
u32 state;
Expand Down Expand Up @@ -107,17 +125,61 @@ static void ls1021_pcie_host_init(struct pcie_port *pp)
iowrite32(val, pcie->dbi + PCIE_STRFMR1);
}

static int ls_pcie_link_up(struct pcie_port *pp)
{
struct ls_pcie *pcie = to_ls_pcie(pp);
u32 state;

state = (ioread32(pcie->lut + PCIE_LUT_DBG) >>
pcie->drvdata->ltssm_shift) &
LTSSM_STATE_MASK;

if (state < LTSSM_PCIE_L0)
return 0;

return 1;
}

static void ls_pcie_host_init(struct pcie_port *pp)
{
struct ls_pcie *pcie = to_ls_pcie(pp);

iowrite32(1, pcie->dbi + PCIE_DBI_RO_WR_EN);
ls_pcie_fix_class(pcie);
ls_pcie_clear_multifunction(pcie);
iowrite32(0, pcie->dbi + PCIE_DBI_RO_WR_EN);
}

static struct pcie_host_ops ls1021_pcie_host_ops = {
.link_up = ls1021_pcie_link_up,
.host_init = ls1021_pcie_host_init,
};

static struct pcie_host_ops ls_pcie_host_ops = {
.link_up = ls_pcie_link_up,
.host_init = ls_pcie_host_init,
};

static struct ls_pcie_drvdata ls1021_drvdata = {
.ops = &ls1021_pcie_host_ops,
};

static struct ls_pcie_drvdata ls1043_drvdata = {
.lut_offset = 0x10000,
.ltssm_shift = 24,
.ops = &ls_pcie_host_ops,
};

static struct ls_pcie_drvdata ls2080_drvdata = {
.lut_offset = 0x80000,
.ltssm_shift = 0,
.ops = &ls_pcie_host_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,ls2080a-pcie", .data = &ls2080_drvdata },
{ },
};
MODULE_DEVICE_TABLE(of, ls_pcie_of_match);
Expand Down Expand Up @@ -164,6 +226,7 @@ static int __init ls_pcie_probe(struct platform_device *pdev)
}

pcie->drvdata = match->data;
pcie->lut = pcie->dbi + pcie->drvdata->lut_offset;

if (!ls_pcie_is_bridge(pcie))
return -ENODEV;
Expand Down

0 comments on commit 5192ec7

Please sign in to comment.