[U-Boot] [PATCH 4/6] dm: pci: add Freescale PowerPC PCIe driver

Simon Glass sjg at chromium.org
Mon May 6 17:06:14 UTC 2019


Hi,

On Fri, 3 May 2019 at 20:03, Z.q. Hou <zhiqiang.hou at nxp.com> wrote:
>
> From: Hou Zhiqiang <Zhiqiang.Hou at nxp.com>
>
> Add PCIe DM driver for Freescale PowerPC PCIe controllers.
>
> Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou at nxp.com>
> ---
>  drivers/pci/Kconfig          |   7 +
>  drivers/pci/Makefile         |   1 +
>  drivers/pci/pcie_fsl.c       | 612 +++++++++++++++++++++++++++++++++++
>  drivers/pci/pcie_fsl.h       |  60 ++++
>  drivers/pci/pcie_fsl_fixup.c |  40 +++
>  5 files changed, 720 insertions(+)
>  create mode 100644 drivers/pci/pcie_fsl.c
>  create mode 100644 drivers/pci/pcie_fsl.h
>  create mode 100644 drivers/pci/pcie_fsl_fixup.c
>
> diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
> index 1521885bde..36674db6c1 100644
> --- a/drivers/pci/Kconfig
> +++ b/drivers/pci/Kconfig
> @@ -60,6 +60,13 @@ config PCIE_DW_MVEBU
>           Armada-8K SoCs. The PCIe controller on Armada-8K is based on
>           DesignWare hardware.
>
> +config PCIE_FSL
> +       bool "FSL PowerPC PCIe support"
> +       depends on DM_PCI
> +       help
> +         Say Y here if you want to enable PCIe controller support on
> +         FSL PowerPC series SoCs.

Please add a bit more detail here. Which SoCs are supported? Which
hardware features are supported, and which not supported?

> +
>  config PCI_RCAR_GEN2
>         bool "Renesas RCar Gen2 PCIe driver"
>         depends on DM_PCI
> diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
> index 4923641895..d984848266 100644
> --- a/drivers/pci/Makefile
> +++ b/drivers/pci/Makefile
> @@ -30,6 +30,7 @@ obj-$(CONFIG_SH7780_PCI) +=pci_sh7780.o
>  obj-$(CONFIG_PCI_TEGRA) += pci_tegra.o
>  obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o
>  obj-$(CONFIG_PCIE_DW_MVEBU) += pcie_dw_mvebu.o
> +obj-$(CONFIG_PCIE_FSL) += pcie_fsl.o pcie_fsl_fixup.o
>  obj-$(CONFIG_PCIE_LAYERSCAPE) += pcie_layerscape.o
>  obj-$(CONFIG_PCIE_LAYERSCAPE) += pcie_layerscape_fixup.o
>  obj-$(CONFIG_PCI_XILINX) += pcie_xilinx.o
> diff --git a/drivers/pci/pcie_fsl.c b/drivers/pci/pcie_fsl.c
> new file mode 100644
> index 0000000000..95973fd8d9
> --- /dev/null
> +++ b/drivers/pci/pcie_fsl.c
> @@ -0,0 +1,612 @@
> +// SPDX-License-Identifier: GPL-2.0+ OR X11
> +/*
> + * Copyright 2019 NXP
> + * Copyright 2007-2012 Freescale Semiconductor, Inc.
> + *
> + * PCIe DM U-Boot driver for Freescale PowerPC SoCs
> + * Author: Hou Zhiqiang <Zhiqiang.Hou at nxp.com>
> + */
> +
> +#include <common.h>
> +#include <malloc.h>
> +#include <dm.h>
> +#include <pci.h>
> +#include <clk.h>
> +#include <mapmem.h>
> +#include <asm/io.h>
> +#include <asm/fsl_serdes.h>
> +#include "pcie_fsl.h"

Please sort these properly:

common
clk
dm
malloc
mapmem
pci
asm/fsl
asm/io
pcie_fsl

> +
> +LIST_HEAD(fsl_pcie_list);
> +
> +static inline int fsl_pcie_link_up(struct fsl_pcie *pcie);

Why is this inline? Do you need the forward declaration?


> +
> +static int fsl_pcie_addr_valid(struct fsl_pcie *pcie, pci_dev_t bdf)
> +{
> +       struct udevice *bus = pcie->bus;
> +
> +       if (!pcie->enabled)
> +               return -ENXIO;
> +
> +       if (PCI_BUS(bdf) < bus->seq)
> +               return -EINVAL;
> +
> +       if (PCI_BUS(bdf) > bus->seq && (!fsl_pcie_link_up(pcie) || pcie->mode))
> +               return -EINVAL;
> +
> +       if (PCI_BUS(bdf) == bus->seq && (PCI_DEV(bdf) > 0 || PCI_FUNC(bdf) > 0))
> +               return -EINVAL;
> +
> +       if (PCI_BUS(bdf) == (bus->seq + 1) && (PCI_DEV(bdf) > 0))
> +               return -EINVAL;
> +
> +       return 0;
> +}
> +
> +static int fsl_pcie_read_config(struct udevice *bus, pci_dev_t bdf,
> +                               uint offset, ulong *valuep,
> +                               enum pci_size_t size)
> +{
> +       struct fsl_pcie *pcie = dev_get_priv(bus);
> +       ccsr_fsl_pci_t *regs = pcie->regs;
> +       u32 val;
> +
> +       if (fsl_pcie_addr_valid(pcie, bdf)) {
> +               *valuep = pci_get_ff(size);
> +               return 0;
> +       }
> +
> +       bdf = bdf - PCI_BDF(bus->seq, 0, 0);
> +       val = bdf | (offset & 0xfc) | ((offset & 0xf00) << 16) | 0x80000000;
> +       out_be32(&regs->cfg_addr, val);
> +
> +       sync();
> +
> +       switch (size) {
> +       case PCI_SIZE_8:
> +               *valuep = in_8((u8 *)&regs->cfg_data + (offset & 3));
> +               break;
> +       case PCI_SIZE_16:
> +               *valuep = in_le16((u16 *)((u8 *)&regs->cfg_data +
> +                         (offset & 2)));
> +               break;
> +       case PCI_SIZE_32:
> +               *valuep = in_le32(&regs->cfg_data);
> +               break;
> +       }
> +
> +       return 0;
> +}
> +
> +static int fsl_pcie_write_config(struct udevice *bus, pci_dev_t bdf,
> +                                uint offset, ulong value,
> +                                enum pci_size_t size)
> +{
> +       struct fsl_pcie *pcie = dev_get_priv(bus);
> +       ccsr_fsl_pci_t *regs = pcie->regs;
> +       u32 val;
> +       u8 val_8;
> +       u16 val_16;
> +       u32 val_32;
> +
> +       if (fsl_pcie_addr_valid(pcie, bdf))
> +               return 0;
> +
> +       bdf = bdf - PCI_BDF(bus->seq, 0, 0);
> +       val = bdf | (offset & 0xfc) | ((offset & 0xf00) << 16) | 0x80000000;
> +       out_be32(&regs->cfg_addr, val);
> +
> +       sync();
> +
> +       switch (size) {
> +       case PCI_SIZE_8:
> +               val_8 = value;
> +               out_8((u8 *)&regs->cfg_data + (offset & 3), val_8);
> +               break;
> +       case PCI_SIZE_16:
> +               val_16 = value;
> +               out_le16((u16 *)((u8 *)&regs->cfg_data + (offset & 2)), val_16);
> +               break;
> +       case PCI_SIZE_32:
> +               val_32 = value;
> +               out_le32(&regs->cfg_data, val_32);
> +               break;
> +       }
> +
> +       return 0;
> +}
> +
> +static int fsl_pcie_hose_read_config(struct fsl_pcie *pcie, uint offset,
> +                                    ulong *valuep, enum pci_size_t size)
> +{
> +       int ret;
> +       struct udevice *bus = pcie->bus;
> +
> +       ret = fsl_pcie_read_config(bus, PCI_BDF(bus->seq, 0, 0),
> +                                  offset, valuep, size);
> +
> +       return ret;
> +}
> +
> +static int fsl_pcie_hose_write_config(struct fsl_pcie *pcie, uint offset,
> +                                     ulong value, enum pci_size_t size)
> +{
> +       struct udevice *bus = pcie->bus;
> +
> +       return fsl_pcie_write_config(bus, PCI_BDF(bus->seq, 0, 0),
> +                                    offset, value, size);
> +}
> +
> +static int fsl_pcie_hose_read_config_byte(struct fsl_pcie *pcie, uint offset,
> +                                         u8 *valuep)
> +{
> +       ulong val;
> +       int ret;
> +
> +       ret = fsl_pcie_hose_read_config(pcie, offset, &val, PCI_SIZE_8);
> +       *valuep = val;
> +
> +       return ret;
> +}
> +
> +static int fsl_pcie_hose_read_config_word(struct fsl_pcie *pcie, uint offset,
> +                                         u16 *valuep)
> +{
> +       ulong val;
> +       int ret;
> +
> +       ret = fsl_pcie_hose_read_config(pcie, offset, &val, PCI_SIZE_16);
> +       *valuep = val;
> +
> +       return ret;
> +}
> +
> +static int fsl_pcie_hose_read_config_dword(struct fsl_pcie *pcie, uint offset,
> +                                          u32 *valuep)
> +{
> +       ulong val;
> +       int ret;
> +
> +       ret = fsl_pcie_hose_read_config(pcie, offset, &val, PCI_SIZE_32);
> +       *valuep = val;
> +
> +       return ret;
> +}
> +
> +static int fsl_pcie_hose_write_config_byte(struct fsl_pcie *pcie, uint offset,
> +                                          u8 value)
> +{
> +       return fsl_pcie_hose_write_config(pcie, offset, value, PCI_SIZE_8);
> +}
> +
> +static int fsl_pcie_hose_write_config_word(struct fsl_pcie *pcie, uint offset,
> +                                          u16 value)
> +{
> +       return fsl_pcie_hose_write_config(pcie, offset, value, PCI_SIZE_16);
> +}
> +
> +static int fsl_pcie_hose_write_config_dword(struct fsl_pcie *pcie, uint offset,
> +                                           u32 value)
> +{
> +       return fsl_pcie_hose_write_config(pcie, offset, value, PCI_SIZE_32);
> +}
> +
> +static inline int fsl_pcie_link_up(struct fsl_pcie *pcie)
> +{
> +       ccsr_fsl_pci_t *regs = pcie->regs;
> +       u16 ltssm;
> +
> +       if (pcie->block_rev >= PEX_IP_BLK_REV_3_0) {
> +               ltssm = (in_be32(&regs->pex_csr0)
> +                       & PEX_CSR0_LTSSM_MASK) >> PEX_CSR0_LTSSM_SHIFT;
> +               return ltssm == LTSSM_L0_REV3;
> +       }
> +
> +       fsl_pcie_hose_read_config_word(pcie, PCI_LTSSM, &ltssm);
> +
> +       return ltssm == LTSSM_L0;
> +}
> +
> +static bool fsl_pcie_is_agent(struct fsl_pcie *pcie)
> +{
> +       u8 header_type;
> +
> +       fsl_pcie_hose_read_config_byte(pcie, PCI_HEADER_TYPE, &header_type);
> +
> +       return (header_type & 0x7f) == PCI_HEADER_TYPE_NORMAL;
> +}
> +
> +static int fsl_pcie_setup_law(struct fsl_pcie *pcie)
> +{
> +       struct pci_region *io, *mem, *pref;
> +
> +       pci_get_regions(pcie->bus, &io, &mem, &pref);
> +
> +       if (mem)
> +               set_next_law(mem->phys_start,
> +                            law_size_bits(mem->size),
> +                            pcie->law_trgt_if);
> +
> +       if (io)
> +               set_next_law(io->phys_start,
> +                            law_size_bits(io->size),
> +                            pcie->law_trgt_if);
> +
> +       return 0;
> +}
> +
> +static void fsl_pcie_config_ready(struct fsl_pcie *pcie)
> +{
> +       ccsr_fsl_pci_t *regs = pcie->regs;
> +
> +       if (pcie->block_rev >= PEX_IP_BLK_REV_3_0) {
> +               setbits_be32(&regs->config, FSL_PCIE_V3_CFG_RDY);
> +               return;
> +       }
> +
> +       fsl_pcie_hose_write_config_byte(pcie, FSL_PCIE_CFG_RDY, 0x1);
> +}
> +
> +static int fsl_pcie_setup_outbound_win(struct fsl_pcie *pcie, int idx,
> +                                      int type, u64 phys, u64 bus_addr,
> +                                      pci_size_t size)
> +{
> +       ccsr_fsl_pci_t *regs = pcie->regs;
> +       pot_t *po = &regs->pot[idx];
> +       u32 war, sz;
> +
> +       if (idx < 0)
> +               return -EINVAL;
> +
> +       out_be32(&po->powbar, phys >> 12);
> +       out_be32(&po->potar, bus_addr >> 12);
> +#ifdef CONFIG_SYS_PCI_64BIT
> +       out_be32(&po->potear, bus_addr >> 44);
> +#else
> +       out_be32(&po->potear, 0);
> +#endif
> +
> +       sz = (__ilog2_u64((u64)size) - 1);
> +       war = POWAR_EN | sz;
> +
> +       if (type == PCI_REGION_IO)
> +               war |= POWAR_IO_READ | POWAR_IO_WRITE;
> +       else
> +               war |= POWAR_MEM_READ | POWAR_MEM_WRITE;
> +
> +       out_be32(&po->powar, war);
> +
> +       return 0;
> +}
> +
> +static int fsl_pcie_setup_inbound_win(struct fsl_pcie *pcie, int idx,
> +                                     bool pf, u64 phys, u64 bus_addr,
> +                                     pci_size_t size)
> +{
> +       ccsr_fsl_pci_t *regs = pcie->regs;
> +       pit_t *pi = &regs->pit[idx];
> +       u32 sz = (__ilog2_u64(size) - 1);
> +#ifdef CONFIG_SYS_FSL_ERRATUM_A005434

This should be handled by the compatible string, not an #ifdef

Please fix this globally.

[...]
> diff --git a/drivers/pci/pcie_fsl.h b/drivers/pci/pcie_fsl.h
> new file mode 100644
> index 0000000000..ed089bfb71
> --- /dev/null
> +++ b/drivers/pci/pcie_fsl.h
> @@ -0,0 +1,60 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright 2019 NXP
> + * Copyright 2007-2012 Freescale Semiconductor, Inc.
> + *
> + * PCIe DM U-Boot driver for Freescale PowerPC SoCs
> + * Author: Hou Zhiqiang <Zhiqiang.Hou at nxp.com>
> + */
> +
> +#ifndef _PCIE_FSL_H_
> +#define _PCIE_FSL_H_
> +#include <pci.h>
> +#include <dm.h>
> +#include <asm/fsl_pci.h>

Please remove these includes. The C file has them alreadyy.

> +
> +#ifdef CONFIG_SYS_FSL_PCI_VER_3_X
> +#define FSL_PCIE_CAP_ID                        0x70
> +#else
> +#define FSL_PCIE_CAP_ID                        0x4c
> +#endif
> +/* PCIe Device Control Register */
> +#define PCI_DCR                                (FSL_PCIE_CAP_ID + 0x08)
> +/* PCIe Device Status Register */
> +#define PCI_DSR                                (FSL_PCIE_CAP_ID + 0x0a)
> +/* PCIe Link Control Register */
> +#define PCI_LCR                                (FSL_PCIE_CAP_ID + 0x10)
> +/* PCIe Link Status Register */
> +#define PCI_LSR                                (FSL_PCIE_CAP_ID + 0x12)
> +
> +#ifndef CONFIG_SYS_PCI_MEMORY_BUS
> +#define CONFIG_SYS_PCI_MEMORY_BUS      0
> +#endif
> +
> +#ifndef CONFIG_SYS_PCI_MEMORY_PHYS
> +#define CONFIG_SYS_PCI_MEMORY_PHYS     0
> +#endif
> +
> +#if defined(CONFIG_SYS_PCI_64BIT) && !defined(CONFIG_SYS_PCI64_MEMORY_BUS)
> +#define CONFIG_SYS_PCI64_MEMORY_BUS    (64ull * 1024 * 1024 * 1024)
> +#endif
> +
> +#define PEX_CSR0_LTSSM_MASK            0xFC
> +#define PEX_CSR0_LTSSM_SHIFT           2
> +#define LTSSM_L0_REV3                  0x11
> +#define LTSSM_L0                       0x16
> +
> +struct fsl_pcie {

Need struct/member docs.

> +       int idx;
> +       struct udevice *bus;
> +       void __iomem *regs;
> +       u32 law_trgt_if;
> +       u32 block_rev;
> +       bool mode;
> +       bool enabled;
> +       struct list_head list;
> +};
> +
> +extern struct list_head fsl_pcie_list;
> +
> +#endif /* _PCIE_FSL_H_ */
> diff --git a/drivers/pci/pcie_fsl_fixup.c b/drivers/pci/pcie_fsl_fixup.c
> new file mode 100644
> index 0000000000..c3cd1dc09a
> --- /dev/null
> +++ b/drivers/pci/pcie_fsl_fixup.c
> @@ -0,0 +1,40 @@
> +// SPDX-License-Identifier: GPL-2.0+ OR X11
> +/*
> + * Copyright 2019 NXP
> + * Copyright 2007-2012 Freescale Semiconductor, Inc.
> + *
> + * PCIe Kernel DT fixup of DM U-Boot driver for Freescale PowerPC SoCs
> + * Author: Hou Zhiqiang <Zhiqiang.Hou at nxp.com>
> + */
> +
> +#include <common.h>
> +#ifdef CONFIG_OF_BOARD_SETUP

Shouldn't need this.

> +#include <linux/libfdt.h>
> +#include <fdt_support.h>
> +#include "pcie_fsl.h"
> +
> +static void ft_fsl_pcie_setup(void *blob, struct fsl_pcie *pcie)
> +{
> +       struct pci_controller *hose = dev_get_uclass_priv(pcie->bus);
> +       int off;
> +
> +       off = fdt_node_offset_by_compat_reg(blob, FSL_PCIE_COMPAT,
> +                                           dev_read_addr(pcie->bus));
> +       if (off < 0)
> +               return;

Should return an error?

> +
> +       if (!hose || !pcie->enabled)
> +               fdt_del_node(blob, off);
> +       else
> +               fdt_pci_dma_ranges(blob, off, hose);
> +}
> +
> +/* Fixup Kernel DT for PCIe */
> +void pci_of_setup(void *blob, bd_t *bd)
> +{
> +       struct fsl_pcie *pcie;
> +
> +       list_for_each_entry(pcie, &fsl_pcie_list, list)
> +               ft_fsl_pcie_setup(blob, pcie);
> +}
> +#endif
> --
> 2.17.1
>

Regards,
Simon


More information about the U-Boot mailing list