[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(®s->cfg_addr, val);
> +
> + sync();
> +
> + switch (size) {
> + case PCI_SIZE_8:
> + *valuep = in_8((u8 *)®s->cfg_data + (offset & 3));
> + break;
> + case PCI_SIZE_16:
> + *valuep = in_le16((u16 *)((u8 *)®s->cfg_data +
> + (offset & 2)));
> + break;
> + case PCI_SIZE_32:
> + *valuep = in_le32(®s->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(®s->cfg_addr, val);
> +
> + sync();
> +
> + switch (size) {
> + case PCI_SIZE_8:
> + val_8 = value;
> + out_8((u8 *)®s->cfg_data + (offset & 3), val_8);
> + break;
> + case PCI_SIZE_16:
> + val_16 = value;
> + out_le16((u16 *)((u8 *)®s->cfg_data + (offset & 2)), val_16);
> + break;
> + case PCI_SIZE_32:
> + val_32 = value;
> + out_le32(®s->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(®s->pex_csr0)
> + & PEX_CSR0_LTSSM_MASK) >> PEX_CSR0_LTSSM_SHIFT;
> + return ltssm == LTSSM_L0_REV3;
> + }
> +
> + fsl_pcie_hose_read_config_word(pcie, PCI_LTSSM, <ssm);
> +
> + 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(®s->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 = ®s->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 = ®s->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