[U-Boot] [PATCHv3 10/11] pci: ls_pcie_g4: Add Workaround for A-011451

Bin Meng bmeng.cn at gmail.com
Tue Feb 12 03:44:45 UTC 2019


Hi,

On Fri, Jan 25, 2019 at 6:07 PM Z.q. Hou <zhiqiang.hou at nxp.com> wrote:
>
> From: Hou Zhiqiang <Zhiqiang.Hou at nxp.com>
>
> When LAYERSCAPE Gen4 PCIe controller is sending multiple split
> completions and ACK latency expires indicating that ACK should
> be send at priority. But because of large number of split
> completions and FC update DLLP, the controller does not give
> priority to ACK transmission. This results into ACK latency
> timer timeout error at the link partner and the pending TLPs
> are replayed by the link partner again.
>
> Workaround:
> 1. Reduce the ACK latency timeout value to a very small value.
> 2. Restrict the number of completions from the PCIe controller
>    to 1, by changing the Max Read Request Size (MRRS) of link
>    partner to the same value as Max Packet size (MPS).
>
> This ERRATA is only for LX2160A Rev1.0 and will be fixed in Rev2.0.
>
> Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou at nxp.com>
> ---
> V3:
>  - New patch.
>
>  drivers/pci/pci_auto.c             | 34 ++++++++++++++++++++++++++++++
>  drivers/pci/pcie_layerscape_gen4.c |  8 +++++++
>  drivers/pci/pcie_layerscape_gen4.h |  4 ++++
>  include/pci.h                      |  9 ++++++++
>  include/pci_ids.h                  |  1 +
>  5 files changed, 56 insertions(+)
>
> diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c
> index d7237f6eee..37307bd54b 100644
> --- a/drivers/pci/pci_auto.c
> +++ b/drivers/pci/pci_auto.c
> @@ -22,6 +22,7 @@ void dm_pciauto_setup_device(struct udevice *dev, int bars_num,
>                              struct pci_region *prefetch, struct pci_region *io,
>                              bool enum_only)
>  {
> +       struct udevice *rp = pci_get_controller(dev);
>         u32 bar_response;
>         pci_size_t bar_size;
>         u16 cmdstat = 0;
> @@ -32,6 +33,9 @@ void dm_pciauto_setup_device(struct udevice *dev, int bars_num,
>         struct pci_region *bar_res = NULL;
>         int found_mem64 = 0;
>         u16 class;
> +       int pos;
> +       u16 val, vendor, dev_id;
> +       u8 rev;
>
>         dm_pci_read_config16(dev, PCI_COMMAND, &cmdstat);
>         cmdstat = (cmdstat & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) |
> @@ -161,6 +165,36 @@ void dm_pciauto_setup_device(struct udevice *dev, int bars_num,
>         dm_pci_write_config8(dev, PCI_CACHE_LINE_SIZE,
>                              CONFIG_SYS_PCI_CACHE_LINE_SIZE);
>         dm_pci_write_config8(dev, PCI_LATENCY_TIMER, 0x80);
> +
> +       /*
> +        * When NXP LAYERSCAPE Gen4 PCIe controller is sending multiple split
> +        * completions and ACK latency expires indicating that ACK should be
> +        * send at priority. But because of large number of split completions
> +        * and FC update DLLP, the controller does not give priority to ACK
> +        * transmission. This results into ACK latency timer timeout error at
> +        * the link partner and the pending TLPs are replayed by the link
> +        * partner again.
> +        *
> +        * The workaround:
> +        * Restrict the number of completions from the PCIe controller to 1,
> +        * by changing the Max Read Request Size (MRRS) of link partner to the
> +        * same value as Max Packet size (MPS).
> +        *
> +        * So, set both the MPS and MRRS to the minimum 128B.
> +        */
> +       dm_pci_read_config16(rp, PCI_VENDOR_ID, &vendor);
> +       dm_pci_read_config16(rp, PCI_DEVICE_ID, &dev_id);
> +       dm_pci_read_config8(rp, PCI_REVISION_ID, &rev);
> +       if (vendor == PCI_VENDOR_ID_FREESCALE &&
> +           dev_id == PCI_DEVICE_ID_LX2160A && rev == 0x10) {
> +               pos = dm_pci_find_capability(dev, PCI_CAP_ID_EXP);
> +               if (pos) {
> +                       dm_pci_read_config16(dev, pos + PCI_EXP_DEVCTL, &val);
> +                       val &= ~(PCI_EXP_DEVCTL_READRQ |
> +                                PCI_EXP_DEVCTL_PAYLOAD);
> +                       dm_pci_write_config16(dev, pos + PCI_EXP_DEVCTL, val);
> +               }
> +       }

Can this be done in the probe() routine of the driver codes?

>  }
>
>  void dm_pciauto_prescan_setup_bridge(struct udevice *dev, int sub_bus)
> diff --git a/drivers/pci/pcie_layerscape_gen4.c b/drivers/pci/pcie_layerscape_gen4.c
> index 799da2f7df..b530a9979c 100644
> --- a/drivers/pci/pcie_layerscape_gen4.c
> +++ b/drivers/pci/pcie_layerscape_gen4.c
> @@ -526,6 +526,14 @@ static int ls_pcie_g4_probe(struct udevice *dev)
>
>         pcie->rev = readb(pcie->ccsr + PCI_REVISION_ID);
>
> +       /* Set ACK latency timeout */
> +       if (pcie->rev == REV_1_0) {
> +               val = ccsr_readl(pcie, GPEX_ACK_REPLAY_TO);
> +               val &= ~(ACK_LAT_TO_VAL_MASK << ACK_LAT_TO_VAL_SHIFT);
> +               val |= (4 << ACK_LAT_TO_VAL_SHIFT);
> +               ccsr_writel(pcie, GPEX_ACK_REPLAY_TO, val);
> +       }
> +
>         pcie->mode = readb(pcie->ccsr + PCI_HEADER_TYPE) & 0x7f;
>
>         if (pcie->mode == PCI_HEADER_TYPE_NORMAL) {
> diff --git a/drivers/pci/pcie_layerscape_gen4.h b/drivers/pci/pcie_layerscape_gen4.h
> index 137768cae7..ebde52e49a 100644
> --- a/drivers/pci/pcie_layerscape_gen4.h
> +++ b/drivers/pci/pcie_layerscape_gen4.h
> @@ -58,6 +58,10 @@
>  #define INI_VF_SHIFT                           0
>  #define GPEX_SRIOV_VF_OFFSET_STRIDE(pf)                (0x704 + (pf) * 4)
>
> +#define GPEX_ACK_REPLAY_TO                     0x438
> +#define ACK_LAT_TO_VAL_SHIFT                   0
> +#define ACK_LAT_TO_VAL_MASK                    0x1fff
> +
>  /* PAB CSR */
>  #define PAB_CTRL                               0x808
>  #define PAB_CTRL_APIO_EN                       BIT(0)
> diff --git a/include/pci.h b/include/pci.h
> index 785d7d28b7..c4d3bccc5b 100644
> --- a/include/pci.h
> +++ b/include/pci.h
> @@ -414,6 +414,15 @@
>  #define PCI_MAX_PCI_DEVICES    32
>  #define PCI_MAX_PCI_FUNCTIONS  8
>
> +/* PCI Express capability registers */
> +#define PCI_EXP_DEVCTL                 8       /* Device Control */
> +#define  PCI_EXP_DEVCTL_PAYLOAD                0x00e0  /* Max_Payload_Size */
> +#define  PCI_EXP_DEVCTL_READRQ         0x7000  /* Max_Read_Request_Size */
> +#define  PCI_EXP_DEVCTL_READRQ_128B    0x0000  /* 128 Bytes */
> +#define  PCI_EXP_DEVCTL_READRQ_256B    0x1000  /* 256 Bytes */
> +#define  PCI_EXP_DEVCTL_READRQ_512B    0x2000  /* 512 Bytes */
> +#define  PCI_EXP_DEVCTL_READRQ_1024B   0x3000  /* 1024 Bytes */
> +
>  #define PCI_FIND_CAP_TTL 0x48
>  #define CAP_START_POS 0x40
>
> diff --git a/include/pci_ids.h b/include/pci_ids.h
> index fdda679cc0..92a4339e3e 100644
> --- a/include/pci_ids.h
> +++ b/include/pci_ids.h
> @@ -2481,6 +2481,7 @@
>  #define PCI_DEVICE_ID_MPC8641          0x7010
>  #define PCI_DEVICE_ID_MPC8641D         0x7011
>  #define PCI_DEVICE_ID_MPC8610          0x7018
> +#define PCI_DEVICE_ID_LX2160A          0x8D80
>
>  #define PCI_VENDOR_ID_PASEMI           0x1959
>
> --

Regards,
Bin


More information about the U-Boot mailing list