From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: MIME-Version: 1.0 In-Reply-To: <20171212221642.GB95453@bhelgaas-glaptop.roam.corp.google.com> References: <1510697532-32828-1-git-send-email-jim2101024@gmail.com> <1510697532-32828-4-git-send-email-jim2101024@gmail.com> <20171212221642.GB95453@bhelgaas-glaptop.roam.corp.google.com> From: Jim Quinlan Date: Thu, 14 Dec 2017 15:30:42 -0500 Message-ID: Subject: Re: [PATCH v3 3/8] PCI: brcmstb: Add Broadcom STB PCIe host controller driver Content-Type: multipart/alternative; boundary="94eb2c1dffd8150aa8056052c206" To: Bjorn Helgaas Cc: Jim Quinlan , linux-kernel@vger.kernel.org, Bjorn Helgaas , Catalin Marinas , Will Deacon , Rob Herring , Brian Norris , Russell King , Robin Murphy , Christoph Hellwig , Florian Fainelli , Jonas Gorski , Mark Rutland , devicetree@vger.kernel.org, linux-mips@linux-mips.org, linux-pci@vger.kernel.org, Kevin Cernekee , Ralf Baechle , bcm-kernel-feedback-list@broadcom.com, Gregory Fong , linux-arm-kernel@lists.infradead.org List-ID: --94eb2c1dffd8150aa8056052c206 Content-Type: text/plain; charset="UTF-8" On Tue, Dec 12, 2017 at 5:16 PM, Bjorn Helgaas wrote: > On Tue, Nov 14, 2017 at 05:12:07PM -0500, Jim Quinlan wrote: > > This commit adds the basic Broadcom STB PCIe controller. Missing is > > the ability to process MSI and also handle dma-ranges for inbound > > memory accesses. These two functionalities are added in subsequent > > commits. > > > > The PCIe block contains an MDIO interface. This is a local interface > > only accessible by the PCIe controller. It cannot be used or shared > > by any other HW. As such, the small amount of code for this > > controller is included in this driver as there is little upside to put > > it elsewhere. > > > > Signed-off-by: Jim Quinlan > > --- > > drivers/pci/host/Kconfig | 9 + > > drivers/pci/host/Makefile | 1 + > > drivers/pci/host/pcie-brcmstb.c | 1124 ++++++++++++++++++++++++++++++ > +++++++++ > > 3 files changed, 1134 insertions(+) > > create mode 100644 drivers/pci/host/pcie-brcmstb.c > > > > diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig > > index b868803..751463e 100644 > > --- a/drivers/pci/host/Kconfig > > +++ b/drivers/pci/host/Kconfig > > @@ -220,4 +220,13 @@ config VMD > > To compile this driver as a module, choose M here: the > > module will be called vmd. > > > > +config PCIE_BRCMSTB > > + tristate "Broadcom Brcmstb PCIe platform host driver" > > + depends on ARCH_BRCMSTB || BMIPS_GENERIC > > + depends on OF > > + depends on SOC_BRCMSTB > > + default ARCH_BRCMSTB || BMIPS_GENERIC > > + help > > + Adds support for Broadcom Settop Box PCIe host controller. > > + > > endmenu > > diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile > > index 1238278..a8b9923 100644 > > --- a/drivers/pci/host/Makefile > > +++ b/drivers/pci/host/Makefile > > @@ -21,6 +21,7 @@ obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o > > obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o > > obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o > > obj-$(CONFIG_VMD) += vmd.o > > +obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o > > > > # The following drivers are for devices that use the generic ACPI > > # pci_root.c driver but don't support standard ECAM config access. > > diff --git a/drivers/pci/host/pcie-brcmstb.c b/drivers/pci/host/pcie- > brcmstb.c > > new file mode 100644 > > index 0000000..d8a8f7a > > --- /dev/null > > +++ b/drivers/pci/host/pcie-brcmstb.c > > @@ -0,0 +1,1124 @@ > > +/* > > + * Copyright (C) 2009 - 2017 Broadcom > > + * > > + * 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 > > + * published by the Free Software Foundation. > > + * > > + * This program is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +/* BRCM_PCIE_CAP_REGS - Offset for the mandatory capability config regs > */ > > +#define BRCM_PCIE_CAP_REGS 0x00ac > > Add a blank line before multi-line comments. > > > +/* > > + * Broadcom Settop Box PCIE Register Offsets. The names are from > > + * the chip's RDB and we use them here so that a script can correlate > > + * this code and the RDB to prevent discrepancies. > > Use "PCIe" capitalization in English text and messages. > > > + */ > > +#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1 0x0188 > > +#define PCIE_RC_CFG_PRIV1_ID_VAL3 0x043c > > +#define PCIE_RC_DL_MDIO_ADDR 0x1100 > > +#define PCIE_RC_DL_MDIO_WR_DATA 0x1104 > > +#define PCIE_RC_DL_MDIO_RD_DATA 0x1108 > > +#define PCIE_MISC_MISC_CTRL 0x4008 > > +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO 0x400c > > +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI 0x4010 > > +#define PCIE_MISC_RC_BAR1_CONFIG_LO 0x402c > > +#define PCIE_MISC_RC_BAR2_CONFIG_LO 0x4034 > > +#define PCIE_MISC_RC_BAR2_CONFIG_HI 0x4038 > > +#define PCIE_MISC_RC_BAR3_CONFIG_LO 0x403c > > +#define PCIE_MISC_PCIE_CTRL 0x4064 > > +#define PCIE_MISC_PCIE_STATUS 0x4068 > > +#define PCIE_MISC_REVISION 0x406c > > +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT 0x4070 > > +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI 0x4080 > > +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI 0x4084 > > +#define PCIE_MISC_HARD_PCIE_HARD_DEBUG 0x4204 > > +#define PCIE_INTR2_CPU_BASE 0x4300 > > + > > +/* > > + * Broadcom Settop Box PCIE Register Field shift and mask info. The > > + * names are from the chip's RDB and we use them here so that a script > > + * can correlate this code and the RDB to prevent discrepancies. > > + */ > > +#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK > 0xc > > +#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_SHIFT > 0x2 > > +#define PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK 0xffffff > > +#define PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_SHIFT 0x0 > > +#define PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_MASK > 0x1000 > > +#define PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_SHIFT > 0xc > > +#define PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_MASK 0x2000 > > +#define PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_SHIFT 0xd > > +#define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK > 0x300000 > > +#define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_SHIFT 0x14 > > +#define PCIE_MISC_MISC_CTRL_SCB0_SIZE_MASK 0xf8000000 > > +#define PCIE_MISC_MISC_CTRL_SCB0_SIZE_SHIFT 0x1b > > +#define PCIE_MISC_MISC_CTRL_SCB1_SIZE_MASK 0x7c00000 > > +#define PCIE_MISC_MISC_CTRL_SCB1_SIZE_SHIFT 0x16 > > +#define PCIE_MISC_MISC_CTRL_SCB2_SIZE_MASK 0x1f > > +#define PCIE_MISC_MISC_CTRL_SCB2_SIZE_SHIFT 0x0 > > +#define PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_MASK > 0x1f > > +#define PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_SHIFT > 0x0 > > +#define PCIE_MISC_RC_BAR2_CONFIG_LO_SIZE_MASK > 0x1f > > +#define PCIE_MISC_RC_BAR2_CONFIG_LO_SIZE_SHIFT > 0x0 > > +#define PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_MASK > 0x1f > > +#define PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_SHIFT > 0x0 > > +#define PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_MASK 0x4 > > +#define PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_SHIFT > 0x2 > > +#define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK 0x1 > > +#define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_SHIFT 0x0 > > +#define PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK 0x80 > > +#define PCIE_MISC_PCIE_STATUS_PCIE_PORT_SHIFT > 0x7 > > +#define PCIE_MISC_PCIE_STATUS_PCIE_DL_ACTIVE_MASK 0x20 > > +#define PCIE_MISC_PCIE_STATUS_PCIE_DL_ACTIVE_SHIFT 0x5 > > +#define PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_MASK 0x10 > > +#define PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_SHIFT 0x4 > > +#define PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_MASK 0x40 > > +#define PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_SHIFT 0x6 > > +#define PCIE_MISC_REVISION_MAJMIN_MASK > 0xffff > > +#define PCIE_MISC_REVISION_MAJMIN_SHIFT 0 > > +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_MASK 0xfff00000 > > +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_SHIFT 0x14 > > +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_MASK 0xfff0 > > +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_SHIFT 0x4 > > +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_NUM_MASK_BITS > 0xc > > +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI_BASE_MASK > 0xff > > +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI_BASE_SHIFT 0x0 > > +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI_LIMIT_MASK 0xff > > +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI_LIMIT_SHIFT 0x0 > > +#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK > 0x2 > > +#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_SHIFT 0x1 > > +#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK > 0x08000000 > > +#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_SHIFT 0x1b > > +#define PCIE_RGR1_SW_INIT_1_PERST_MASK 0x1 > > +#define PCIE_RGR1_SW_INIT_1_PERST_SHIFT > 0x0 > > + > > +#define BRCM_NUM_PCIE_OUT_WINS 0x4 > > +#define BRCM_MAX_SCB 0x4 > > + > > +#define BRCM_MSI_TARGET_ADDR_LT_4GB 0x0fffffffcULL > > +#define BRCM_MSI_TARGET_ADDR_GT_4GB 0xffffffffcULL > > + > > +#define BURST_SIZE_128 0 > > +#define BURST_SIZE_256 1 > > +#define BURST_SIZE_512 2 > > + > > +/* Offsets from PCIE_INTR2_CPU_BASE */ > > +#define STATUS 0x0 > > +#define SET 0x4 > > +#define CLR 0x8 > > +#define MASK_STATUS 0xc > > +#define MASK_SET 0x10 > > +#define MASK_CLR 0x14 > > + > > +#define PCIE_BUSNUM_SHIFT 20 > > +#define PCIE_SLOT_SHIFT 15 > > +#define PCIE_FUNC_SHIFT 12 > > + > > +#if defined(__BIG_ENDIAN) > > +#define DATA_ENDIAN 2 /* PCIe->DDR inbound > accesses */ > > +#define MMIO_ENDIAN 2 /* CPU->PCIe outbound accesses */ > > +#else > > +#define DATA_ENDIAN 0 > > +#define MMIO_ENDIAN 0 > > +#endif > > + > > +#define MDIO_PORT0 0x0 > > +#define MDIO_DATA_MASK 0x7fffffff > > +#define MDIO_DATA_SHIFT 0x0 > > +#define MDIO_PORT_MASK 0xf0000 > > +#define MDIO_PORT_SHIFT 0x16 > > +#define MDIO_REGAD_MASK 0xffff > > +#define MDIO_REGAD_SHIFT 0x0 > > +#define MDIO_CMD_MASK 0xfff00000 > > +#define MDIO_CMD_SHIFT 0x14 > > +#define MDIO_CMD_READ 0x1 > > +#define MDIO_CMD_WRITE 0x0 > > +#define MDIO_DATA_DONE_MASK 0x80000000 > > +#define MDIO_RD_DONE(x) (((x) & MDIO_DATA_DONE_MASK) ? 1 : > 0) > > +#define MDIO_WT_DONE(x) (((x) & MDIO_DATA_DONE_MASK) ? 0 : > 1) > > +#define SSC_REGS_ADDR 0x1100 > > +#define SET_ADDR_OFFSET 0x1f > > +#define SSC_CNTL_OFFSET 0x2 > > +#define SSC_CNTL_OVRD_EN_MASK 0x8000 > > +#define SSC_CNTL_OVRD_EN_SHIFT 0xf > > +#define SSC_CNTL_OVRD_VAL_MASK 0x4000 > > +#define SSC_CNTL_OVRD_VAL_SHIFT 0xe > > +#define SSC_STATUS_OFFSET 0x1 > > +#define SSC_STATUS_SSC_MASK 0x400 > > +#define SSC_STATUS_SSC_SHIFT 0xa > > +#define SSC_STATUS_PLL_LOCK_MASK 0x800 > > +#define SSC_STATUS_PLL_LOCK_SHIFT 0xb > > + > > +#define IDX_ADDR(pcie) \ > > + ((pcie)->reg_offsets[EXT_CFG_INDEX]) > > +#define DATA_ADDR(pcie) \ > > + ((pcie)->reg_offsets[EXT_CFG_DATA]) > > +#define PCIE_RGR1_SW_INIT_1(pcie) \ > > + ((pcie)->reg_offsets[RGR1_SW_INIT_1]) > > + > > +enum { > > + RGR1_SW_INIT_1, > > + EXT_CFG_INDEX, > > + EXT_CFG_DATA, > > +}; > > + > > +enum { > > + RGR1_SW_INIT_1_INIT_MASK, > > + RGR1_SW_INIT_1_INIT_SHIFT, > > + RGR1_SW_INIT_1_PERST_MASK, > > + RGR1_SW_INIT_1_PERST_SHIFT, > > +}; > > + > > +enum pcie_type { > > + BCM7425, > > + BCM7435, > > + GENERIC, > > + BCM7278, > > +}; > > + > > +struct brcm_window { > > + dma_addr_t pcie_addr; > > + phys_addr_t cpu_addr; > > + dma_addr_t size; > > +}; > > + > > +/* Internal PCIe Host Controller Information.*/ > > +struct brcm_pcie { > > + struct list_head list; > > + struct device *dev; > > + void __iomem *base; > > + struct list_head resources; > > + int irq; > > + struct clk *clk; > > + struct pci_bus *root_bus; > > + struct device_node *dn; > > + int id; > > + bool suspended; > > + int num_out_wins; > > + bool ssc; > > + int gen; > > + struct brcm_window out_wins[BRCM_NUM_PCIE_OUT_WINS]; > > + unsigned int rev; > > + const int *reg_offsets; > > + const int *reg_field_info; > > + enum pcie_type type; > > +}; > > + > > +struct pcie_cfg_data { > > + const int *reg_field_info; > > + const int *offsets; > > + const enum pcie_type type; > > +}; > > + > > +static const int pcie_reg_field_info[] = { > > + [RGR1_SW_INIT_1_INIT_MASK] = 0x2, > > + [RGR1_SW_INIT_1_INIT_SHIFT] = 0x1, > > +}; > > + > > +static const int pcie_reg_field_info_bcm7278[] = { > > + [RGR1_SW_INIT_1_INIT_MASK] = 0x1, > > + [RGR1_SW_INIT_1_INIT_SHIFT] = 0x0, > > +}; > > + > > +static const int pcie_offset_bcm7425[] = { > > + [RGR1_SW_INIT_1] = 0x8010, > > + [EXT_CFG_INDEX] = 0x8300, > > + [EXT_CFG_DATA] = 0x8304, > > +}; > > + > > +static const struct pcie_cfg_data bcm7425_cfg = { > > + .reg_field_info = pcie_reg_field_info, > > + .offsets = pcie_offset_bcm7425, > > + .type = BCM7425, > > +}; > > + > > +static const int pcie_offsets[] = { > > + [RGR1_SW_INIT_1] = 0x9210, > > + [EXT_CFG_INDEX] = 0x9000, > > + [EXT_CFG_DATA] = 0x9004, > > +}; > > + > > +static const struct pcie_cfg_data bcm7435_cfg = { > > + .reg_field_info = pcie_reg_field_info, > > + .offsets = pcie_offsets, > > + .type = BCM7435, > > +}; > > + > > +static const struct pcie_cfg_data generic_cfg = { > > + .reg_field_info = pcie_reg_field_info, > > + .offsets = pcie_offsets, > > + .type = GENERIC, > > +}; > > + > > +static const int pcie_offset_bcm7278[] = { > > + [RGR1_SW_INIT_1] = 0xc010, > > + [EXT_CFG_INDEX] = 0x9000, > > + [EXT_CFG_DATA] = 0x9004, > > +}; > > + > > +static const struct pcie_cfg_data bcm7278_cfg = { > > + .reg_field_info = pcie_reg_field_info_bcm7278, > > + .offsets = pcie_offset_bcm7278, > > + .type = BCM7278, > > +}; > > + > > +static void __iomem *brcm_pcie_map_conf(struct pci_bus *bus, unsigned > int devfn, > > + int where); > > + > > +static struct pci_ops brcm_pcie_ops = { > > + .map_bus = brcm_pcie_map_conf, > > + .read = pci_generic_config_read, > > + .write = pci_generic_config_write, > > +}; > > + > > +#if defined(CONFIG_MIPS) > > +/* Broadcom MIPs HW implicitly does the swapping if necessary */ > > +#define bcm_readl(a) __raw_readl(a) > > +#define bcm_writel(d, a) __raw_writel(d, a) > > +#define bcm_readw(a) __raw_readw(a) > > +#define bcm_writew(d, a) __raw_writew(d, a) > > +#else > > +#define bcm_readl(a) readl(a) > > +#define bcm_writel(d, a) writel(d, a) > > +#define bcm_readw(a) readw(a) > > +#define bcm_writew(d, a) writew(d, a) > > +#endif > > + > > +/* > > + * These macros are designed to sxtract/insert fields to host > controller's > > + * register set. > > s/are designed to s/ e/ (I assume they actually *do* extract/insert) > > > + */ > > +#define RD_FLD(base, reg, field) \ > > + rd_fld(base + reg, reg##_##field##_MASK, reg##_##field##_SHIFT) > > +#define WR_FLD(base, reg, field, val) \ > > + wr_fld(base + reg, reg##_##field##_MASK, reg##_##field##_SHIFT, > val) > > +#define WR_FLD_RB(base, reg, field, val) \ > > + wr_fld_rb(base + reg, reg##_##field##_MASK, reg##_##field##_SHIFT, > val) > > +#define WR_FLD_WITH_OFFSET(base, off, reg, field, val) \ > > + wr_fld(base + reg + off, reg##_##field##_MASK, \ > > + reg##_##field##_SHIFT, val) > > +#define EXTRACT_FIELD(val, reg, field) \ > > + ((val & reg##_##field##_MASK) >> reg##_##field##_SHIFT) > > +#define INSERT_FIELD(val, reg, field, field_val) \ > > + ((val & ~reg##_##field##_MASK) | \ > > + (reg##_##field##_MASK & (field_val << reg##_##field##_SHIFT))) > > + > > +static struct list_head brcm_pcie = LIST_HEAD_INIT(brcm_pcie); > > +static phys_addr_t scb_size[BRCM_MAX_SCB]; > > +static int num_memc; > > +static DEFINE_MUTEX(brcm_pcie_lock); > > + > > +static u32 rd_fld(void __iomem *p, u32 mask, int shift) > > +{ > > + return (bcm_readl(p) & mask) >> shift; > > +} > > + > > +static void wr_fld(void __iomem *p, u32 mask, int shift, u32 val) > > +{ > > + u32 reg = bcm_readl(p); > > + > > + reg = (reg & ~mask) | ((val << shift) & mask); > > + bcm_writel(reg, p); > > +} > > + > > +static void wr_fld_rb(void __iomem *p, u32 mask, int shift, u32 val) > > +{ > > + wr_fld(p, mask, shift, val); > > + (void)bcm_readl(p); > > +} > > + > > +static const char *link_speed_to_str(int s) > > +{ > > + switch (s) { > > + case 1: > > + return "2.5"; > > + case 2: > > + return "5.0"; > > + case 3: > > + return "8.0"; > > + default: > > + break; > > + } > > + return "???"; > > +} > > + > > +/* > > + * The roundup_pow_of_two() from log2.h invokes > > + * __roundup_pow_of_two(unsigned long), but we really need a > > + * such a function to take a native u64 since unsigned long > > + * is 32 bits on some configurations. So we provide this helper > > + * function below. > > + */ > > +static u64 roundup_pow_of_two_64(u64 n) > > +{ > > + return 1ULL << fls64(n - 1); > > +} > > + > > +/* > > + * This is to convert the size of the inbound bar region to the > > + * non-liniear values of PCIE_X_MISC_RC_BAR[123]_CONFIG_LO.SIZE > > s/bar/BAR/ (This doesn't sound like a BAR in the PCI spec sense, but if > that's what you call it, might as well spell it as the acronym) > > s/non-liniear/non-linear/ > > > + */ > > +int encode_ibar_size(u64 size) > > +{ > > + int log2_in = ilog2(size); > > + > > + if (log2_in >= 12 && log2_in <= 15) > > + /* Covers 4KB to 32KB (inclusive) */ > > + return (log2_in - 12) + 0x1c; > > + else if (log2_in >= 16 && log2_in <= 37) > > + /* Covers 64KB to 32GB, (inclusive) */ > > + return log2_in - 15; > > + /* Something is awry so disable */ > > + return 0; > > +} > > + > > +static u32 mdio_form_pkt(int port, int regad, int cmd) > > +{ > > + u32 pkt = 0; > > + > > + pkt |= (port << MDIO_PORT_SHIFT) & MDIO_PORT_MASK; > > + pkt |= (regad << MDIO_REGAD_SHIFT) & MDIO_REGAD_MASK; > > + pkt |= (cmd << MDIO_CMD_SHIFT) & MDIO_CMD_MASK; > > + > > + return pkt; > > +} > > + > > +/* negative return value indicates error */ > > +static int mdio_read(void __iomem *base, u8 port, u8 regad) > > +{ > > + int tries; > > + u32 data; > > + > > + bcm_writel(mdio_form_pkt(port, regad, MDIO_CMD_READ), > > + base + PCIE_RC_DL_MDIO_ADDR); > > + bcm_readl(base + PCIE_RC_DL_MDIO_ADDR); > > + > > + data = bcm_readl(base + PCIE_RC_DL_MDIO_RD_DATA); > > + for (tries = 0; !MDIO_RD_DONE(data) && tries < 10; tries++) { > > + udelay(10); > > + data = bcm_readl(base + PCIE_RC_DL_MDIO_RD_DATA); > > + } > > + > > + return MDIO_RD_DONE(data) > > + ? (data & MDIO_DATA_MASK) >> MDIO_DATA_SHIFT > > + : -EIO; > > +} > > + > > +/* negative return value indicates error */ > > +static int mdio_write(void __iomem *base, u8 port, u8 regad, u16 wrdata) > > +{ > > + int tries; > > + u32 data; > > + > > + bcm_writel(mdio_form_pkt(port, regad, MDIO_CMD_WRITE), > > + base + PCIE_RC_DL_MDIO_ADDR); > > + bcm_readl(base + PCIE_RC_DL_MDIO_ADDR); > > + bcm_writel(MDIO_DATA_DONE_MASK | wrdata, > > + base + PCIE_RC_DL_MDIO_WR_DATA); > > + > > + data = bcm_readl(base + PCIE_RC_DL_MDIO_WR_DATA); > > + for (tries = 0; !MDIO_WT_DONE(data) && tries < 10; tries++) { > > + udelay(10); > > + data = bcm_readl(base + PCIE_RC_DL_MDIO_WR_DATA); > > + } > > + > > + return MDIO_WT_DONE(data) ? 0 : -EIO; > > +} > > + > > +/* configures device for ssc mode; negative return value indicates > error */ > > I guess "ssc" means Spread Spectrum Clocking? Maybe spell out the > first occurrence and spell as acronym in English text? > > > +static int set_ssc(void __iomem *base) > > +{ > > + int tmp; > > + u16 wrdata; > > + int pll, ssc; > > + > > + tmp = mdio_write(base, MDIO_PORT0, SET_ADDR_OFFSET, SSC_REGS_ADDR); > > + if (tmp < 0) > > + return tmp; > > + > > + tmp = mdio_read(base, MDIO_PORT0, SSC_CNTL_OFFSET); > > + if (tmp < 0) > > + return tmp; > > + > > + wrdata = INSERT_FIELD(tmp, SSC_CNTL_OVRD, EN, 1); > > + wrdata = INSERT_FIELD(wrdata, SSC_CNTL_OVRD, VAL, 1); > > + tmp = mdio_write(base, MDIO_PORT0, SSC_CNTL_OFFSET, wrdata); > > + if (tmp < 0) > > + return tmp; > > + > > + usleep_range(1000, 2000); > > + tmp = mdio_read(base, MDIO_PORT0, SSC_STATUS_OFFSET); > > + if (tmp < 0) > > + return tmp; > > + > > + ssc = EXTRACT_FIELD(tmp, SSC_STATUS, SSC); > > + pll = EXTRACT_FIELD(tmp, SSC_STATUS, PLL_LOCK); > > + > > + return (ssc && pll) ? 0 : -EIO; > > +} > > + > > +/* limits operation to a specific generation (1, 2, or 3) */ > > +static void set_gen(void __iomem *base, int gen) > > +{ > > + u32 lnkcap = bcm_readl(base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP); > > + u16 lnkctl2 = bcm_readw(base + BRCM_PCIE_CAP_REGS + > PCI_EXP_LNKCTL2); > > + > > + lnkcap = (lnkcap & ~PCI_EXP_LNKCAP_SLS) | gen; > > + bcm_writel(lnkcap, base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP); > > + > > + lnkctl2 = (lnkctl2 & ~0xf) | gen; > > + bcm_writew(lnkctl2, base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCTL2); > > +} > > + > > +static void brcm_pcie_set_outbound_win(struct brcm_pcie *pcie, > > + unsigned int win, phys_addr_t > cpu_addr, > > + dma_addr_t pcie_addr, dma_addr_t > size) > > +{ > > + void __iomem *base = pcie->base; > > + phys_addr_t cpu_addr_mb, limit_addr_mb; > > + u32 tmp; > > + > > + /* Set the base of the pcie_addr window */ > > + bcm_writel(lower_32_bits(pcie_addr) + MMIO_ENDIAN, > > + base + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO + (win * 8)); > > + bcm_writel(upper_32_bits(pcie_addr), > > + base + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI + (win * 8)); > > + > > + cpu_addr_mb = cpu_addr >> 20; > > + limit_addr_mb = (cpu_addr + size - 1) >> 20; > > + > > + /* Write the addr base low register */ > > + WR_FLD_WITH_OFFSET(base, (win * 4), > > + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT, > > + BASE, cpu_addr_mb); > > + /* Write the addr limit low register */ > > + WR_FLD_WITH_OFFSET(base, (win * 4), > > + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT, > > + LIMIT, limit_addr_mb); > > + > > + if (pcie->type != BCM7435 && pcie->type != BCM7425) { > > + /* Write the cpu addr high register */ > > + tmp = (u32)(cpu_addr_mb >> > > + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_ > BASE_LIMIT_NUM_MASK_BITS); > > + WR_FLD_WITH_OFFSET(base, (win * 8), > > + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI, > > + BASE, tmp); > > + /* Write the cpu limit high register */ > > + tmp = (u32)(limit_addr_mb >> > > + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_ > BASE_LIMIT_NUM_MASK_BITS); > > + WR_FLD_WITH_OFFSET(base, (win * 8), > > + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI, > > + LIMIT, tmp); > > + } > > +} > > + > > +/* Configuration space read/write support */ > > +static int cfg_index(int busnr, int devfn, int reg) > > +{ > > + return ((PCI_SLOT(devfn) & 0x1f) << PCIE_SLOT_SHIFT) > > + | ((PCI_FUNC(devfn) & 0x07) << PCIE_FUNC_SHIFT) > > + | (busnr << PCIE_BUSNUM_SHIFT) > > + | (reg & ~3); > > +} > > + > > +static bool brcm_pcie_rc_mode(struct brcm_pcie *pcie) > > +{ > > + void __iomem *base = pcie->base; > > + u32 val = bcm_readl(base + PCIE_MISC_PCIE_STATUS); > > + > > + return !!EXTRACT_FIELD(val, PCIE_MISC_PCIE_STATUS, PCIE_PORT); > > +} > > + > > +static bool brcm_pcie_link_up(struct brcm_pcie *pcie) > > +{ > > + void __iomem *base = pcie->base; > > + u32 val = bcm_readl(base + PCIE_MISC_PCIE_STATUS); > > + u32 dla = EXTRACT_FIELD(val, PCIE_MISC_PCIE_STATUS, > PCIE_DL_ACTIVE); > > + u32 plu = EXTRACT_FIELD(val, PCIE_MISC_PCIE_STATUS, > PCIE_PHYLINKUP); > > + > > + return (dla && plu) ? true : false; > > +} > > + > > +static bool brcm_pcie_valid_device(struct brcm_pcie *pcie, struct > pci_bus *bus, > > + int dev) > > +{ > > + if (pci_is_root_bus(bus)) { > > + if (dev > 0) > > + return false; > > + } else { > > + /* If there is no link, then there is no device */ > > + if (!brcm_pcie_link_up(pcie)) > > + return false; > > This is racy, since the link can go down after you check but before > you do the config access. I assume your hardware can deal with a > config access that targets a link that is down? > > > + } > > + > > + return true; > > +} > > + > > +static void __iomem *brcm_pcie_map_conf(struct pci_bus *bus, unsigned > int devfn, > > + int where) > > +{ > > + struct brcm_pcie *pcie = bus->sysdata; > > + void __iomem *base = pcie->base; > > + int idx; > > + > > + if (!brcm_pcie_valid_device(pcie, bus, PCI_SLOT(devfn))) > > + return NULL; > > + > > + /* Accesses to the RC go right to the RC registers */ > > + if (pci_is_root_bus(bus)) > > + return base + where; > > + > > + /* For devices, write to the config space index register */ > > + idx = cfg_index(bus->number, devfn, where); > > + bcm_writel(idx, pcie->base + IDX_ADDR(pcie)); > > + return base + DATA_ADDR(pcie) + (where & 0x3); > > I guess this is protected by a higher-level config access lock? > All pci config space accessor functions -- pci_bus_{read,write}_{byte,word,dword}() -- use a spinlock (pci_lock). These routines, covered by the spinlock, call pci_generic_{read,write}(), and those two functions call ops->map_bus(), aka our brcm_pcie_map_conf(). Unless CONFIG_PCI_LOCKLESS_CONFIG is set to "y", which it is not. > > +} > > + > > +static inline void brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie, > > + unsigned int val) > > +{ > > + unsigned int offset; > > + unsigned int shift = pcie->reg_field_info[RGR1_SW_ > INIT_1_INIT_SHIFT]; > > + u32 mask = pcie->reg_field_info[RGR1_SW_INIT_1_INIT_MASK]; > > + > > + if (pcie->type != BCM7278) { > > + wr_fld_rb(pcie->base + PCIE_RGR1_SW_INIT_1(pcie), mask, > shift, > > + val); > > + } else if (of_machine_is_compatible("brcm,bcm7278a0")) { > > + /* > > + * The two PCIe instances on 7278a0 are not even > consistent with > > + * respect to each other for internal offsets, here we > offset > > + * by 0x14000 + RGR1_SW_INIT_1's relative offset to > account for > > + * that. > > + */ > > + offset = pcie->id ? 0x14010 : pcie->reg_offsets[RGR1_SW_ > INIT_1]; > > + wr_fld_rb(pcie->base + offset, mask, shift, val); > > + } else { > > + wr_fld_rb(pcie->base + PCIE_RGR1_SW_INIT_1(pcie), mask, > shift, > > + val); > > + } > > +} > > + > > +static inline void brcm_pcie_perst_set(struct brcm_pcie *pcie, > > + unsigned int val) > > +{ > > + if (pcie->type != BCM7278) > > + wr_fld_rb(pcie->base + PCIE_RGR1_SW_INIT_1(pcie), > > + PCIE_RGR1_SW_INIT_1_PERST_MASK, > > + PCIE_RGR1_SW_INIT_1_PERST_SHIFT, val); > > + else > > + /* Assert = 0, de-assert = 1 on 7278 */ > > + WR_FLD_RB(pcie->base, PCIE_MISC_PCIE_CTRL, PCIE_PERSTB, > !val); > > +} > > + > > +static int brcm_pcie_add_controller(struct brcm_pcie *pcie) > > +{ > > + mutex_lock(&brcm_pcie_lock); > > + list_add_tail(&pcie->list, &brcm_pcie); > > + mutex_unlock(&brcm_pcie_lock); > > + > > + return 0; > > +} > > + > > +static void brcm_pcie_remove_controller(struct brcm_pcie *pcie) > > +{ > > + struct list_head *pos, *q; > > + struct brcm_pcie *tmp; > > + > > + mutex_lock(&brcm_pcie_lock); > > + list_for_each_safe(pos, q, &brcm_pcie) { > > + tmp = list_entry(pos, struct brcm_pcie, list); > > + if (tmp == pcie) { > > + list_del(pos); > > + if (list_empty(&brcm_pcie)) > > + num_memc = 0; > > + break; > > + } > > + } > > + mutex_unlock(&brcm_pcie_lock); > > I'm missing something. I don't see that num_memc is ever set to > anything *other* than zero. > > This pattern of keeping a list of controllers is highly unusual and > needs some explanation. > > > +} > > + > > +static int brcm_pcie_parse_request_of_pci_ranges(struct brcm_pcie > *pcie) > > +{ > > + struct resource_entry *win; > > + int ret; > > + > > + ret = of_pci_get_host_bridge_resources(pcie->dn, 0, 0xff, > > + &pcie->resources, NULL); > > + if (ret) { > > + dev_err(pcie->dev, "failed to get host resources\n"); > > + return ret; > > + } > > + > > + resource_list_for_each_entry(win, &pcie->resources) { > > + struct resource *parent, *res = win->res; > > + dma_addr_t offset = (dma_addr_t)win->offset; > > + > > + if (resource_type(res) == IORESOURCE_IO) { > > + parent = &ioport_resource; > > + } else if (resource_type(res) == IORESOURCE_MEM) { > > + if (pcie->num_out_wins >= BRCM_NUM_PCIE_OUT_WINS) { > > + dev_err(pcie->dev, "too many outbound > wins\n"); > > + return -EINVAL; > > + } > > + pcie->out_wins[pcie->num_out_wins].cpu_addr > > + = (phys_addr_t)res->start; > > + pcie->out_wins[pcie->num_out_wins].pcie_addr > > + = (dma_addr_t)(res->start > > + - (phys_addr_t)offset); > > + pcie->out_wins[pcie->num_out_wins].size > > + = (dma_addr_t)(res->end - res->start + 1); > > + pcie->num_out_wins++; > > + parent = &iomem_resource; > > + } else { > > + continue; > > + } > > + > > + ret = devm_request_resource(pcie->dev, parent, res); > > + if (ret) { > > + dev_err(pcie->dev, "failed to get res %pR\n", res); > > + return ret; > > + } > > + } > > + return 0; > > +} > > + > > +static int brcm_pcie_setup(struct brcm_pcie *pcie) > > +{ > > + void __iomem *base = pcie->base; > > + unsigned int scb_size_val; > > + u64 rc_bar2_size = 0, rc_bar2_offset = 0, total_mem_size = 0; > > Unnecessary initializations (at least of rc_bar2_size, I didn't check > the rest). > > Add > > struct device *dev = pcie->dev; > > then use it below. > > > + u32 tmp, burst; > > + int i, j, ret, limit; > > + u16 nlw, cls, lnksta; > > + bool ssc_good = false; > > + > > + /* reset the bridge and the endpoint device */ > > + /* field: PCIE_BRIDGE_SW_INIT = 1 */ > > Not sure what these "field: ..." comments mean. Are they for some > automated tool? To a human, it looks like they repeat what the code > does. > > > + brcm_pcie_bridge_sw_init_set(pcie, 1); > > + > > + /* field: PCIE_SW_PERST = 1, on 7278, we start de-asserted already > */ > > + if (pcie->type != BCM7278) > > + brcm_pcie_perst_set(pcie, 1); > > + > > + usleep_range(100, 200); > > + > > + /* take the bridge out of reset */ > > + /* field: PCIE_BRIDGE_SW_INIT = 0 */ > > + brcm_pcie_bridge_sw_init_set(pcie, 0); > > + > > + WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEBUG, SERDES_IDDQ, 0); > > + /* wait for serdes to be stable */ > > + usleep_range(100, 200); > > + > > + /* Grab the PCIe hw revision number */ > > + tmp = bcm_readl(base + PCIE_MISC_REVISION); > > + pcie->rev = EXTRACT_FIELD(tmp, PCIE_MISC_REVISION, MAJMIN); > > + > > + /* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN */ > > + tmp = INSERT_FIELD(0, PCIE_MISC_MISC_CTRL, SCB_ACCESS_EN, 1); > > + tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, CFG_READ_UR_MODE, 1); > > + burst = (pcie->type == GENERIC || pcie->type == BCM7278) > > + ? BURST_SIZE_512 : BURST_SIZE_256; > > + tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, MAX_BURST_SIZE, > burst); > > + bcm_writel(tmp, base + PCIE_MISC_MISC_CTRL); > > + > > + /* > > + * Set up inbound memory view for the EP (called RC_BAR2, > > + * not to be confused with the BARs that are advertised by > > + * the EP). > > + */ > > + for (i = 0; i < num_memc; i++) > > + total_mem_size += scb_size[i]; > > + > > + /* > > + * The PCIe host controller by design must set the inbound > > + * viewport to be a contiguous arrangement of all of the > > + * system's memory. In addition, its size mut be a power of > > + * two. To further complicate matters, the viewport must > > + * start on a pcie-address that is aligned on a multiple of its > > + * size. If a portion of the viewport does not represent > > + * system memory -- e.g. 3GB of memory requires a 4GB viewport > > + * -- we can map the outbound memory in or after 3GB and even > > + * though the viewport will overlap the outbound memory the > > + * controller will know to send outbound memory downstream and > > + * everything else upstream. > > + */ > > + rc_bar2_size = roundup_pow_of_two_64(total_mem_size); > > + > > + /* > > + * Set simple configuration based on memory sizes > > + * only. We always start the viewport at address 0. > > + */ > > + rc_bar2_offset = 0; > > + > > + tmp = lower_32_bits(rc_bar2_offset); > > + tmp = INSERT_FIELD(tmp, PCIE_MISC_RC_BAR2_CONFIG_LO, SIZE, > > + encode_ibar_size(rc_bar2_size)); > > + bcm_writel(tmp, base + PCIE_MISC_RC_BAR2_CONFIG_LO); > > + bcm_writel(upper_32_bits(rc_bar2_offset), > > + base + PCIE_MISC_RC_BAR2_CONFIG_HI); > > + > > + /* field: SCB0_SIZE, default = 0xf (1 GB) */ > > + scb_size_val = scb_size[0] > > + ? ilog2(scb_size[0]) - 15 : 0xf; > > + WR_FLD(base, PCIE_MISC_MISC_CTRL, SCB0_SIZE, scb_size_val); > > + > > + /* field: SCB1_SIZE, default = 0xf (1 GB) */ > > + if (num_memc > 1) { > > + scb_size_val = scb_size[1] > > + ? ilog2(scb_size[1]) - 15 : 0xf; > > + WR_FLD(base, PCIE_MISC_MISC_CTRL, SCB1_SIZE, scb_size_val); > > + } > > + > > + /* field: SCB2_SIZE, default = 0xf (1 GB) */ > > + if (num_memc > 2) { > > + scb_size_val = scb_size[2] > > + ? ilog2(scb_size[2]) - 15 : 0xf; > > + WR_FLD(base, PCIE_MISC_MISC_CTRL, SCB2_SIZE, scb_size_val); > > + } > > + > > + /* disable the PCIe->GISB memory window (RC_BAR1) */ > > + WR_FLD(base, PCIE_MISC_RC_BAR1_CONFIG_LO, SIZE, 0); > > + > > + /* disable the PCIe->SCB memory window (RC_BAR3) */ > > + WR_FLD(base, PCIE_MISC_RC_BAR3_CONFIG_LO, SIZE, 0); > > + > > + if (!pcie->suspended) { > > + /* clear any interrupts we find on boot */ > > + bcm_writel(0xffffffff, base + PCIE_INTR2_CPU_BASE + CLR); > > + (void)bcm_readl(base + PCIE_INTR2_CPU_BASE + CLR); > > + } > > + > > + /* Mask all interrupts since we are not handling any yet */ > > + bcm_writel(0xffffffff, base + PCIE_INTR2_CPU_BASE + MASK_SET); > > + (void)bcm_readl(base + PCIE_INTR2_CPU_BASE + MASK_SET); > > + > > + if (pcie->gen) > > + set_gen(base, pcie->gen); > > + > > + /* take the EP device out of reset */ > > + /* field: PCIE_SW_PERST = 0 */ > > + brcm_pcie_perst_set(pcie, 0); > > Take the *EP* out of reset? The host controller > driver shouldn't be touching an EP directly. Maybe the comment > doesn't match what the code actually does. > > > + > > + /* > > + * Give the RC/EP time to wake up, before trying to configure RC. > > + * Intermittently check status for link-up, up to a total of 100ms > > + * when we don't know if the device is there, and up to 1000ms if > > + * we do know the device is there. > > + */ > > + limit = pcie->suspended ? 1000 : 100; > > + for (i = 1, j = 0; j < limit && !brcm_pcie_link_up(pcie); > > + j += i, i = i * 2) > > + msleep(i + j > limit ? limit - j : i); > > + > > + if (!brcm_pcie_link_up(pcie)) { > > + dev_info(pcie->dev, "link down\n"); > > + return -ENODEV; > > + } > > + > > + if (!brcm_pcie_rc_mode(pcie)) { > > + dev_err(pcie->dev, "PCIe misconfigured; is in EP mode\n"); > > + return -EINVAL; > > + } > > + > > + for (i = 0; i < pcie->num_out_wins; i++) > > + brcm_pcie_set_outbound_win(pcie, i, > pcie->out_wins[i].cpu_addr, > > + pcie->out_wins[i].pcie_addr, > > + pcie->out_wins[i].size); > > + > > + /* > > + * For config space accesses on the RC, show the right class for > > + * a PCIe-PCIe bridge (the default setting is to be EP mode). > > + */ > > + WR_FLD_RB(base, PCIE_RC_CFG_PRIV1_ID_VAL3, CLASS_CODE, 0x060400); > > + > > + if (pcie->ssc) { > > + ret = set_ssc(base); > > + if (ret == 0) > > + ssc_good = true; > > + else > > + dev_err(pcie->dev, > > + "failed attempt to enter ssc mode\n"); > > + } > > + > > + lnksta = bcm_readw(base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKSTA); > > + cls = lnksta & PCI_EXP_LNKSTA_CLS; > > + nlw = (lnksta & PCI_EXP_LNKSTA_NLW) >> PCI_EXP_LNKSTA_NLW_SHIFT; > > + dev_info(pcie->dev, "link up, %s Gbps x%u %s\n", > link_speed_to_str(cls), > > + nlw, ssc_good ? "(SSC)" : "(!SSC)"); > > + > > + /* PCIe->SCB endian mode for BAR */ > > + /* field ENDIAN_MODE_BAR2 = DATA_ENDIAN */ > > + WR_FLD_RB(base, PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1, > > + ENDIAN_MODE_BAR2, DATA_ENDIAN); > > + > > + /* > > + * Refclk from RC should be gated with CLKREQ# input when ASPM > L0s,L1 > > + * is enabled => setting the CLKREQ_DEBUG_ENABLE field to 1. > > + */ > > + WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEBUG, > CLKREQ_DEBUG_ENABLE, 1); > > + > > + return 0; > > +} > > + > > +static void enter_l23(struct brcm_pcie *pcie) > > +{ > > + void __iomem *base = pcie->base; > > + int tries, l23; > > + > > + /* assert request for L23 */ > > + WR_FLD_RB(base, PCIE_MISC_PCIE_CTRL, PCIE_L23_REQUEST, 1); > > + /* poll L23 status */ > > + for (tries = 0, l23 = 0; tries < 1000 && !l23; tries++) > > + l23 = RD_FLD(base, PCIE_MISC_PCIE_STATUS, > PCIE_LINK_IN_L23); > > + if (!l23) > > + dev_err(pcie->dev, "failed to enter L23\n"); > > What does "L23" mean? Some power management thing? > > > +} > > + > > +static void turn_off(struct brcm_pcie *pcie) > > +{ > > + void __iomem *base = pcie->base; > > + > > + if (brcm_pcie_link_up(pcie)) > > + enter_l23(pcie); > > + /* Reset endpoint device */ > > + brcm_pcie_perst_set(pcie, 1); > > + /* deassert request for L23 in case it was asserted */ > > + WR_FLD_RB(base, PCIE_MISC_PCIE_CTRL, PCIE_L23_REQUEST, 0); > > + /* SERDES_IDDQ = 1 */ > > + WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEBUG, SERDES_IDDQ, 1); > > + /* Shutdown PCIe bridge */ > > + brcm_pcie_bridge_sw_init_set(pcie, 1); > > +} > > + > > +static int brcm_pcie_suspend(struct device *dev) > > +{ > > + struct brcm_pcie *pcie = dev_get_drvdata(dev); > > + > > + turn_off(pcie); > > + clk_disable_unprepare(pcie->clk); > > + pcie->suspended = true; > > + > > + return 0; > > +} > > + > > +static int brcm_pcie_resume(struct device *dev) > > +{ > > + struct brcm_pcie *pcie = dev_get_drvdata(dev); > > + void __iomem *base; > > + int ret; > > + > > + base = pcie->base; > > + clk_prepare_enable(pcie->clk); > > + > > + /* Take bridge out of reset so we can access the SERDES reg */ > > Some comments above and below spell it "serdes"; here you spell it > "SERDES". > > > + brcm_pcie_bridge_sw_init_set(pcie, 0); > > + > > + /* SERDES_IDDQ = 0 */ > > + WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEBUG, SERDES_IDDQ, 0); > > + /* wait for serdes to be stable */ > > + usleep_range(100, 200); > > + > > + ret = brcm_pcie_setup(pcie); > > + if (ret) > > + return ret; > > + > > + pcie->suspended = false; > > + > > + return 0; > > +} > > + > > +static void _brcm_pcie_remove(struct brcm_pcie *pcie) > > +{ > > + turn_off(pcie); > > + clk_disable_unprepare(pcie->clk); > > + clk_put(pcie->clk); > > + brcm_pcie_remove_controller(pcie); > > +} > > + > > +static int brcm_pcie_remove(struct platform_device *pdev) > > +{ > > + struct brcm_pcie *pcie = platform_get_drvdata(pdev); > > + > > + pci_stop_root_bus(pcie->root_bus); > > + pci_remove_root_bus(pcie->root_bus); > > + _brcm_pcie_remove(pcie); > > + > > + return 0; > > +} > > + > > +static const struct of_device_id brcm_pcie_match[] = { > > + { .compatible = "brcm,bcm7425-pcie", .data = &bcm7425_cfg }, > > + { .compatible = "brcm,bcm7435-pcie", .data = &bcm7435_cfg }, > > + { .compatible = "brcm,bcm7278-pcie", .data = &bcm7278_cfg }, > > + { .compatible = "brcm,bcm7445-pcie", .data = &generic_cfg }, > > + {}, > > +}; > > +MODULE_DEVICE_TABLE(of, brcm_pcie_match); > > + > > +static int brcm_pcie_probe(struct platform_device *pdev) > > +{ > > + struct device_node *dn = pdev->dev.of_node; > > + const struct of_device_id *of_id; > > + const struct pcie_cfg_data *data; > > + int ret; > > + struct brcm_pcie *pcie; > > + struct resource *res; > > + void __iomem *base; > > + u32 tmp; > > + struct pci_host_bridge *bridge; > > + struct pci_bus *child; > > + > > + bridge = devm_pci_alloc_host_bridge(&pdev->dev, sizeof(*pcie)); > > + if (!bridge) > > + return -ENOMEM; > > + > > + pcie = pci_host_bridge_priv(bridge); > > + INIT_LIST_HEAD(&pcie->resources); > > + > > + of_id = of_match_node(brcm_pcie_match, dn); > > + if (!of_id) { > > + dev_err(&pdev->dev, "failed to look up compatible > string\n"); > > + return -EINVAL; > > + } > > + > > + if (of_property_read_u32(dn, "dma-ranges", &tmp) == 0) { > > + dev_err(&pdev->dev, "cannot yet handle dma-ranges\n"); > > + return -EINVAL; > > + } > > + > > + data = of_id->data; > > + pcie->reg_offsets = data->offsets; > > + pcie->reg_field_info = data->reg_field_info; > > + pcie->type = data->type; > > + pcie->dn = dn; > > + pcie->dev = &pdev->dev; > > + > > + pcie->id = of_get_pci_domain_nr(dn); > > Why do you call of_get_pci_domain_nr() directly? No other driver > does. > > > + if (pcie->id < 0) > > + return pcie->id; > > + > > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > > + if (!res) > > + return -EINVAL; > > + > > + base = devm_ioremap_resource(&pdev->dev, res); > > + if (IS_ERR(base)) > > + return PTR_ERR(base); > > + > > + pcie->clk = of_clk_get_by_name(dn, "sw_pcie"); > > + if (IS_ERR(pcie->clk)) { > > + dev_err(&pdev->dev, "could not get clock\n"); > > + pcie->clk = NULL; > > + } > > + pcie->base = base; > > + > > + ret = of_pci_get_max_link_speed(dn); > > + pcie->gen = (ret < 0) ? 0 : ret; > > + > > + pcie->ssc = of_property_read_bool(dn, "brcm,enable-ssc"); > > + > > + ret = irq_of_parse_and_map(pdev->dev.of_node, 0); > > + if (ret == 0) > > + /* keep going, as we don't use this intr yet */ > > + dev_warn(pcie->dev, "cannot get pcie interrupt\n"); > > + else > > + pcie->irq = ret; > > + > > + ret = brcm_pcie_parse_request_of_pci_ranges(pcie); > > + if (ret) > > + return ret; > > + > > + ret = clk_prepare_enable(pcie->clk); > > + if (ret) { > > + dev_err(&pdev->dev, "could not enable clock\n"); > > + return ret; > > + } > > + > > + ret = brcm_pcie_add_controller(pcie); > > + if (ret) > > + return ret; > > + > > + ret = brcm_pcie_setup(pcie); > > + if (ret) > > + goto fail; > > + > > + list_splice_init(&pcie->resources, &bridge->windows); > > + bridge->dev.parent = &pdev->dev; > > + bridge->busnr = 0; > > + bridge->ops = &brcm_pcie_ops; > > + bridge->sysdata = pcie; > > + bridge->map_irq = of_irq_parse_and_map_pci; > > + bridge->swizzle_irq = pci_common_swizzle; > > + > > + ret = pci_scan_root_bus_bridge(bridge); > > + if (ret < 0) { > > + dev_err(pcie->dev, "Scanning root bridge failed"); > > + goto fail; > > + } > > + > > + pci_assign_unassigned_bus_resources(bridge->bus); > > + list_for_each_entry(child, &bridge->bus->children, node) > > + pcie_bus_configure_settings(child); > > + pci_bus_add_devices(bridge->bus); > > + platform_set_drvdata(pdev, pcie); > > + pcie->root_bus = bridge->bus; > > + > > + return 0; > > + > > +fail: > > + _brcm_pcie_remove(pcie); > > + return ret; > > +} > > + > > +static const struct dev_pm_ops brcm_pcie_pm_ops = { > > + .suspend_noirq = brcm_pcie_suspend, > > + .resume_noirq = brcm_pcie_resume, > > +}; > > + > > +static struct platform_driver __refdata brcm_pcie_driver = { > > Why do you need __refdata? There's only only other occurrence in > drivers/pci, and I'm dubious about that one as well. > > > + .probe = brcm_pcie_probe, > > + .remove = brcm_pcie_remove, > > + .driver = { > > + .name = "brcm-pcie", > > + .owner = THIS_MODULE, > > + .of_match_table = brcm_pcie_match, > > + .pm = &brcm_pcie_pm_ops, > > + }, > > +}; > > + > > +module_platform_driver(brcm_pcie_driver); > > + > > +MODULE_LICENSE("GPL"); > > Copyright notice above says "GPL v2", which is not the same as the > "GPL" here. > > > +MODULE_DESCRIPTION("Broadcom STB PCIE RC driver"); > > +MODULE_AUTHOR("Broadcom"); > > -- > > 1.9.0.138.g2de3478 > > > > > > _______________________________________________ > > linux-arm-kernel mailing list > > linux-arm-kernel@lists.infradead.org > > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel > --94eb2c1dffd8150aa8056052c206 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable

= On Tue, Dec 12, 2017 at 5:16 PM, Bjorn Helgaas <helgaas@kernel.org>= ; wrote:
On Tue, Nov 14, 2017 at 05:12= :07PM -0500, Jim Quinlan wrote:
> This commit adds the basic Broadcom STB PCIe controller.=C2=A0 Missing= is
> the ability to process MSI and also handle dma-ranges for inbound
> memory accesses.=C2=A0 These two functionalities are added in subseque= nt
> commits.
>
> The PCIe block contains an MDIO interface.=C2=A0 This is a local inter= face
> only accessible by the PCIe controller.=C2=A0 It cannot be used or sha= red
> by any other HW.=C2=A0 As such, the small amount of code for this
> controller is included in this driver as there is little upside to put=
> it elsewhere.
>
> Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
> ---
>=C2=A0 drivers/pci/host/Kconfig=C2=A0 =C2=A0 =C2=A0 =C2=A0 |=C2=A0 =C2= =A0 9 +
>=C2=A0 drivers/pci/host/Makefile=C2=A0 =C2=A0 =C2=A0 =C2=A0|=C2=A0 =C2= =A0 1 +
>=C2=A0 drivers/pci/host/pcie-brcmstb.c | 1124 ++++++++++++++++++++= +++++++++++++++++++
>=C2=A0 3 files changed, 1134 insertions(+)
>=C2=A0 create mode 100644 drivers/pci/host/pcie-brcmstb.c
>
> diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
> index b868803..751463e 100644
> --- a/drivers/pci/host/Kconfig
> +++ b/drivers/pci/host/Kconfig
> @@ -220,4 +220,13 @@ config VMD
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0To compile this driver as a module, c= hoose M here: the
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0module will be called vmd.
>
> +config PCIE_BRCMSTB
> +=C2=A0 =C2=A0 =C2=A0tristate "Broadcom Brcmstb PCIe platform hos= t driver"
> +=C2=A0 =C2=A0 =C2=A0depends on ARCH_BRCMSTB || BMIPS_GENERIC
> +=C2=A0 =C2=A0 =C2=A0depends on OF
> +=C2=A0 =C2=A0 =C2=A0depends on SOC_BRCMSTB
> +=C2=A0 =C2=A0 =C2=A0default ARCH_BRCMSTB || BMIPS_GENERIC
> +=C2=A0 =C2=A0 =C2=A0help
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0Adds support for Broadcom Settop Box PCIe = host controller.
> +
>=C2=A0 endmenu
> diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
> index 1238278..a8b9923 100644
> --- a/drivers/pci/host/Makefile
> +++ b/drivers/pci/host/Makefile
> @@ -21,6 +21,7 @@ obj-$(CONFIG_PCIE_ROCKCHIP) +=3D pcie-rockchip.o
>=C2=A0 obj-$(CONFIG_PCIE_MEDIATEK) +=3D pcie-mediatek.o
>=C2=A0 obj-$(CONFIG_PCIE_TANGO_SMP8759) +=3D pcie-tango.o
>=C2=A0 obj-$(CONFIG_VMD) +=3D vmd.o
> +obj-$(CONFIG_PCIE_BRCMSTB) +=3D pcie-brcmstb.o
>
>=C2=A0 # The following drivers are for devices that use the generic ACP= I
>=C2=A0 # pci_root.c driver but don't support standard ECAM config a= ccess.
> diff --git a/drivers/pci/host/pcie-brcmstb.c b/drivers/pci/host/p= cie-brcmstb.c
> new file mode 100644
> index 0000000..d8a8f7a
> --- /dev/null
> +++ b/drivers/pci/host/pcie-brcmstb.c
> @@ -0,0 +1,1124 @@
> +/*
> + * Copyright (C) 2009 - 2017 Broadcom
> + *
> + * This program is free software; you can redistribute it and/or modi= fy
> + * it under the terms of the GNU General Public License version 2 as<= br> > + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/compiler.h>
> +#include <linux/delay.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/ioport.h>
> +#include <linux/irqdomain.h>
> +#include <linux/kernel.h>
> +#include <linux/list.h>
> +#include <linux/log2.h>
> +#include <linux/module.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_pci.h>
> +#include <linux/of_pci.h>
> +#include <linux/of_platform.h>
> +#include <linux/pci.h>
> +#include <linux/printk.h>
> +#include <linux/sizes.h>
> +#include <linux/slab.h>
> +#include <soc/brcmstb/memory_api.h>
> +#include <linux/string.h>
> +#include <linux/types.h>
> +
> +/* BRCM_PCIE_CAP_REGS - Offset for the mandatory capability config re= gs */
> +#define BRCM_PCIE_CAP_REGS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x00ac

Add a blank line before multi-line comments.

> +/*
> + * Broadcom Settop Box PCIE Register Offsets. The names are from
> + * the chip's RDB and we use them here so that a script can corre= late
> + * this code and the RDB to prevent discrepancies.

Use "PCIe" capitalization in English text and messages.

> + */
> +#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x0188
> +#define PCIE_RC_CFG_PRIV1_ID_VAL3=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x043c
> +#define PCIE_RC_DL_MDIO_ADDR=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x1100
> +#define PCIE_RC_DL_MDIO_WR_DATA=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x1104 > +#define PCIE_RC_DL_MDIO_RD_DATA=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x1108 > +#define PCIE_MISC_MISC_CTRL=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x4008
> +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A00x400c
> +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A00x4010
> +#define PCIE_MISC_RC_BAR1_CONFIG_LO=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x402c
> +#define PCIE_MISC_RC_BAR2_CONFIG_LO=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x4034
> +#define PCIE_MISC_RC_BAR2_CONFIG_HI=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x4038
> +#define PCIE_MISC_RC_BAR3_CONFIG_LO=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x403c
> +#define PCIE_MISC_PCIE_CTRL=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x4064
> +#define PCIE_MISC_PCIE_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0= x4068
> +#define PCIE_MISC_REVISION=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x406c
> +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT=C2=A0 =C2=A0 = =C2=A00x4070
> +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x4080
> +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x4084
> +#define PCIE_MISC_HARD_PCIE_HARD_DEBUG=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x4204
> +#define PCIE_INTR2_CPU_BASE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x4300
> +
> +/*
> + * Broadcom Settop Box PCIE Register Field shift and mask info. The > + * names are from the chip's RDB and we use them here so that a s= cript
> + * can correlate this code and the RDB to prevent discrepancies.
> + */
> +#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK=C2=A0 =C2=A0 =C2=A0 =C2=A0 0xc
> +#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_SHIFT=C2=A0 =C2=A0 =C2=A0 =C2=A00x2
> +#define PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 0xffffff
> +#define PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_SHIFT=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A00x0
> +#define PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_MASK=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x1000 > +#define PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_SHIFT=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0xc
> +#define PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_MASK=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x2000
> +#define PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_SHIFT=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A00xd
> +#define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x300000
> +#define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_SHIFT=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x14
> +#define PCIE_MISC_MISC_CTRL_SCB0_SIZE_MASK=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00xf8000000
> +#define PCIE_MISC_MISC_CTRL_SCB0_SIZE_SHIFT=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x1b
> +#define PCIE_MISC_MISC_CTRL_SCB1_SIZE_MASK=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x7c00000
> +#define PCIE_MISC_MISC_CTRL_SCB1_SIZE_SHIFT=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x16
> +#define PCIE_MISC_MISC_CTRL_SCB2_SIZE_MASK=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x1f
> +#define PCIE_MISC_MISC_CTRL_SCB2_SIZE_SHIFT=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x0
> +#define PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_MASK=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x1f
> +#define PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_SHIFT=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x0
> +#define PCIE_MISC_RC_BAR2_CONFIG_LO_SIZE_MASK=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x1f
> +#define PCIE_MISC_RC_BAR2_CONFIG_LO_SIZE_SHIFT=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x0
> +#define PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_MASK=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x1f
> +#define PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_SHIFT=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x0
> +#define PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_MASK=C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x4
> +#define PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_SHIFT=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x2
> +#define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x1
> +#define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_SHIFT=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A00x0
> +#define PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK=C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x80
> +#define PCIE_MISC_PCIE_STATUS_PCIE_PORT_SHIFT=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x7
> +#define PCIE_MISC_PCIE_STATUS_PCIE_DL_ACTIVE_MASK=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x20
> +#define PCIE_MISC_PCIE_STATUS_PCIE_DL_ACTIVE_SHIFT=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A00x5
> +#define PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_MASK=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x10
> +#define PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_SHIFT=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A00x4
> +#define PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_MASK=C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 0x40
> +#define PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_SHIFT=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A00x6
> +#define PCIE_MISC_REVISION_MAJMIN_MASK=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A00xffff
> +#define PCIE_MISC_REVISION_MAJMIN_SHIFT=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 0
> +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_MASK=C2= =A0 0xfff00000
> +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_SHIFT 0x1= 4
> +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_MASK=C2=A0= =C2=A00xfff0
> +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_SHIFT=C2= =A0 0x4
> +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_NUM_MASK_BITS= =C2=A0 =C2=A0 =C2=A0 =C2=A00xc
> +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI_BASE_MASK=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0xff
> +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI_BASE_SHIFT=C2=A0 = =C2=A0 =C2=A00x0
> +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI_LIMIT_MASK=C2=A0 = =C2=A0 0xff
> +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI_LIMIT_SHIFT=C2=A0= =C2=A00x0
> +#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK= =C2=A0 =C2=A0 =C2=A0 0x2
> +#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_= SHIFT 0x1
> +#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x08000000
> +#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_SHIFT=C2=A0 = =C2=A0 =C2=A00x1b
> +#define PCIE_RGR1_SW_INIT_1_PERST_MASK=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A00x1
> +#define PCIE_RGR1_SW_INIT_1_PERST_SHIFT=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 0x0
> +
> +#define BRCM_NUM_PCIE_OUT_WINS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A00x4
> +#define BRCM_MAX_SCB=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A00x4
> +
> +#define BRCM_MSI_TARGET_ADDR_LT_4GB=C2=A0 0x0fffffffcULL
> +#define BRCM_MSI_TARGET_ADDR_GT_4GB=C2=A0 0xffffffffcULL
> +
> +#define BURST_SIZE_128=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00
> +#define BURST_SIZE_256=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A01
> +#define BURST_SIZE_512=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A02
> +
> +/* Offsets from PCIE_INTR2_CPU_BASE */
> +#define STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x0
> +#define SET=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x4
> +#define CLR=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x8
> +#define MASK_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 0xc
> +#define MASK_SET=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A00x10
> +#define MASK_CLR=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A00x14
> +
> +#define PCIE_BUSNUM_SHIFT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 20=
> +#define PCIE_SLOT_SHIFT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 15
> +#define PCIE_FUNC_SHIFT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 12
> +
> +#if defined(__BIG_ENDIAN)
> +#define=C2=A0 =C2=A0 =C2=A0 DATA_ENDIAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A02=C2=A0 =C2=A0 =C2=A0 =C2=A0/* PCIe->DDR inbound acc= esses */
> +#define MMIO_ENDIAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 2=C2=A0 =C2=A0 = =C2=A0 =C2=A0/* CPU->PCIe outbound accesses */
> +#else
> +#define=C2=A0 =C2=A0 =C2=A0 DATA_ENDIAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A00
> +#define MMIO_ENDIAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0
> +#endif
> +
> +#define MDIO_PORT0=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x0
> +#define MDIO_DATA_MASK=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A00x7fffffff
> +#define MDIO_DATA_SHIFT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 0x0
> +#define MDIO_PORT_MASK=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A00xf0000
> +#define MDIO_PORT_SHIFT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 0x16
> +#define MDIO_REGAD_MASK=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 0xffff
> +#define MDIO_REGAD_SHIFT=C2=A0 =C2=A0 =C2=A00x0
> +#define MDIO_CMD_MASK=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 0xfff00000
> +#define MDIO_CMD_SHIFT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A00x14
> +#define MDIO_CMD_READ=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 0x1
> +#define MDIO_CMD_WRITE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A00x0
> +#define MDIO_DATA_DONE_MASK=C2=A0 0x80000000
> +#define MDIO_RD_DONE(x)=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 (((x) & MDIO_DATA_DONE_MASK) ? 1 : 0)
> +#define MDIO_WT_DONE(x)=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 (((x) & MDIO_DATA_DONE_MASK) ? 0 : 1)
> +#define SSC_REGS_ADDR=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 0x1100
> +#define SET_ADDR_OFFSET=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 0x1f
> +#define SSC_CNTL_OFFSET=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 0x2
> +#define SSC_CNTL_OVRD_EN_MASK=C2=A0 =C2=A0 =C2=A0 =C2=A0 0x8000
> +#define SSC_CNTL_OVRD_EN_SHIFT=C2=A0 =C2=A0 =C2=A0 =C2=A00xf
> +#define SSC_CNTL_OVRD_VAL_MASK=C2=A0 =C2=A0 =C2=A0 =C2=A00x4000
> +#define SSC_CNTL_OVRD_VAL_SHIFT=C2=A0 =C2=A0 =C2=A0 0xe
> +#define SSC_STATUS_OFFSET=C2=A0 =C2=A0 0x1
> +#define SSC_STATUS_SSC_MASK=C2=A0 0x400
> +#define SSC_STATUS_SSC_SHIFT 0xa
> +#define SSC_STATUS_PLL_LOCK_MASK=C2=A0 =C2=A0 =C2=A00x800
> +#define SSC_STATUS_PLL_LOCK_SHIFT=C2=A0 =C2=A0 0xb
> +
> +#define IDX_ADDR(pcie)=C2=A0 =C2=A0 =C2=A0 =C2=A0\
> +=C2=A0 =C2=A0 =C2=A0((pcie)->reg_offsets[EXT_CFG_INDEX])
> +#define DATA_ADDR(pcie)=C2=A0 =C2=A0 =C2=A0 \
> +=C2=A0 =C2=A0 =C2=A0((pcie)->reg_offsets[EXT_CFG_DATA])
> +#define PCIE_RGR1_SW_INIT_1(pcie) \
> +=C2=A0 =C2=A0 =C2=A0((pcie)->reg_offsets[RGR1_SW_INIT_1])
> +
> +enum {
> +=C2=A0 =C2=A0 =C2=A0RGR1_SW_INIT_1,
> +=C2=A0 =C2=A0 =C2=A0EXT_CFG_INDEX,
> +=C2=A0 =C2=A0 =C2=A0EXT_CFG_DATA,
> +};
> +
> +enum {
> +=C2=A0 =C2=A0 =C2=A0RGR1_SW_INIT_1_INIT_MASK,
> +=C2=A0 =C2=A0 =C2=A0RGR1_SW_INIT_1_INIT_SHIFT,
> +=C2=A0 =C2=A0 =C2=A0RGR1_SW_INIT_1_PERST_MASK,
> +=C2=A0 =C2=A0 =C2=A0RGR1_SW_INIT_1_PERST_SHIFT,
> +};
> +
> +enum pcie_type {
> +=C2=A0 =C2=A0 =C2=A0BCM7425,
> +=C2=A0 =C2=A0 =C2=A0BCM7435,
> +=C2=A0 =C2=A0 =C2=A0GENERIC,
> +=C2=A0 =C2=A0 =C2=A0BCM7278,
> +};
> +
> +struct brcm_window {
> +=C2=A0 =C2=A0 =C2=A0dma_addr_t pcie_addr;
> +=C2=A0 =C2=A0 =C2=A0phys_addr_t cpu_addr;
> +=C2=A0 =C2=A0 =C2=A0dma_addr_t size;
> +};
> +
> +/* Internal PCIe Host Controller Information.*/
> +struct brcm_pcie {
> +=C2=A0 =C2=A0 =C2=A0struct list_head=C2=A0 =C2=A0 =C2=A0 =C2=A0 list;=
> +=C2=A0 =C2=A0 =C2=A0struct device=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0*dev;
> +=C2=A0 =C2=A0 =C2=A0void __iomem=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 *base;
> +=C2=A0 =C2=A0 =C2=A0struct list_head=C2=A0 =C2=A0 =C2=A0 =C2=A0 resou= rces;
> +=C2=A0 =C2=A0 =C2=A0int=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0irq;
> +=C2=A0 =C2=A0 =C2=A0struct clk=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 *clk;
> +=C2=A0 =C2=A0 =C2=A0struct pci_bus=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = *root_bus;
> +=C2=A0 =C2=A0 =C2=A0struct device_node=C2=A0 =C2=A0 =C2=A0 *dn;
> +=C2=A0 =C2=A0 =C2=A0int=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0id;
> +=C2=A0 =C2=A0 =C2=A0bool=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 suspended;
> +=C2=A0 =C2=A0 =C2=A0int=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0num_out_wins;
> +=C2=A0 =C2=A0 =C2=A0bool=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 ssc;
> +=C2=A0 =C2=A0 =C2=A0int=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0gen;
> +=C2=A0 =C2=A0 =C2=A0struct brcm_window=C2=A0 =C2=A0 =C2=A0 out_wins[B= RCM_NUM_PCIE_OUT_WINS];
> +=C2=A0 =C2=A0 =C2=A0unsigned int=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 rev;
> +=C2=A0 =C2=A0 =C2=A0const int=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0*reg_offsets;
> +=C2=A0 =C2=A0 =C2=A0const int=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0*reg_field_info;
> +=C2=A0 =C2=A0 =C2=A0enum pcie_type=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = type;
> +};
> +
> +struct pcie_cfg_data {
> +=C2=A0 =C2=A0 =C2=A0const int *reg_field_info;
> +=C2=A0 =C2=A0 =C2=A0const int *offsets;
> +=C2=A0 =C2=A0 =C2=A0const enum pcie_type type;
> +};
> +
> +static const int pcie_reg_field_info[] =3D {
> +=C2=A0 =C2=A0 =C2=A0[RGR1_SW_INIT_1_INIT_MASK] =3D 0x2,
> +=C2=A0 =C2=A0 =C2=A0[RGR1_SW_INIT_1_INIT_SHIFT] =3D 0x1,
> +};
> +
> +static const int pcie_reg_field_info_bcm7278[] =3D {
> +=C2=A0 =C2=A0 =C2=A0[RGR1_SW_INIT_1_INIT_MASK] =3D 0x1,
> +=C2=A0 =C2=A0 =C2=A0[RGR1_SW_INIT_1_INIT_SHIFT] =3D 0x0,
> +};
> +
> +static const int pcie_offset_bcm7425[] =3D {
> +=C2=A0 =C2=A0 =C2=A0[RGR1_SW_INIT_1] =3D 0x8010,
> +=C2=A0 =C2=A0 =C2=A0[EXT_CFG_INDEX]=C2=A0 =3D 0x8300,
> +=C2=A0 =C2=A0 =C2=A0[EXT_CFG_DATA]=C2=A0 =C2=A0=3D 0x8304,
> +};
> +
> +static const struct pcie_cfg_data bcm7425_cfg =3D {
> +=C2=A0 =C2=A0 =C2=A0.reg_field_info =3D pcie_reg_field_info,
> +=C2=A0 =C2=A0 =C2=A0.offsets=C2=A0 =C2=A0 =C2=A0 =C2=A0 =3D pcie_offs= et_bcm7425,
> +=C2=A0 =C2=A0 =C2=A0.type=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D= BCM7425,
> +};
> +
> +static const int pcie_offsets[] =3D {
> +=C2=A0 =C2=A0 =C2=A0[RGR1_SW_INIT_1] =3D 0x9210,
> +=C2=A0 =C2=A0 =C2=A0[EXT_CFG_INDEX]=C2=A0 =3D 0x9000,
> +=C2=A0 =C2=A0 =C2=A0[EXT_CFG_DATA]=C2=A0 =C2=A0=3D 0x9004,
> +};
> +
> +static const struct pcie_cfg_data bcm7435_cfg =3D {
> +=C2=A0 =C2=A0 =C2=A0.reg_field_info =3D pcie_reg_field_info,
> +=C2=A0 =C2=A0 =C2=A0.offsets=C2=A0 =C2=A0 =C2=A0 =C2=A0 =3D pcie_offs= ets,
> +=C2=A0 =C2=A0 =C2=A0.type=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D= BCM7435,
> +};
> +
> +static const struct pcie_cfg_data generic_cfg =3D {
> +=C2=A0 =C2=A0 =C2=A0.reg_field_info =3D pcie_reg_field_info,
> +=C2=A0 =C2=A0 =C2=A0.offsets=C2=A0 =C2=A0 =C2=A0 =C2=A0 =3D pcie_offs= ets,
> +=C2=A0 =C2=A0 =C2=A0.type=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D= GENERIC,
> +};
> +
> +static const int pcie_offset_bcm7278[] =3D {
> +=C2=A0 =C2=A0 =C2=A0[RGR1_SW_INIT_1] =3D 0xc010,
> +=C2=A0 =C2=A0 =C2=A0[EXT_CFG_INDEX] =3D 0x9000,
> +=C2=A0 =C2=A0 =C2=A0[EXT_CFG_DATA] =3D 0x9004,
> +};
> +
> +static const struct pcie_cfg_data bcm7278_cfg =3D {
> +=C2=A0 =C2=A0 =C2=A0.reg_field_info =3D pcie_reg_field_info_bcm7278,<= br> > +=C2=A0 =C2=A0 =C2=A0.offsets=C2=A0 =C2=A0 =C2=A0 =C2=A0 =3D pcie_offs= et_bcm7278,
> +=C2=A0 =C2=A0 =C2=A0.type=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D= BCM7278,
> +};
> +
> +static void __iomem *brcm_pcie_map_conf(struct pci_bus *bus, unsigned= int devfn,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0int where);<= br> > +
> +static struct pci_ops brcm_pcie_ops =3D {
> +=C2=A0 =C2=A0 =C2=A0.map_bus =3D brcm_pcie_map_conf,
> +=C2=A0 =C2=A0 =C2=A0.read =3D pci_generic_config_read,
> +=C2=A0 =C2=A0 =C2=A0.write =3D pci_generic_config_write,
> +};
> +
> +#if defined(CONFIG_MIPS)
> +/* Broadcom MIPs HW implicitly does the swapping if necessary */
> +#define bcm_readl(a)=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0__raw_readl(a)<= br> > +#define bcm_writel(d, a)=C2=A0 =C2=A0 =C2=A0__raw_writel(d, a)
> +#define bcm_readw(a)=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0__raw_readw(a)<= br> > +#define bcm_writew(d, a)=C2=A0 =C2=A0 =C2=A0__raw_writew(d, a)
> +#else
> +#define bcm_readl(a)=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0readl(a)
> +#define bcm_writel(d, a)=C2=A0 =C2=A0 =C2=A0writel(d, a)
> +#define bcm_readw(a)=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0readw(a)
> +#define bcm_writew(d, a)=C2=A0 =C2=A0 =C2=A0writew(d, a)
> +#endif
> +
> +/*
> + * These macros are designed to sxtract/insert fields to host control= ler's
> + * register set.

s/are designed to s/ e/=C2=A0 (I assume they actually *do* extr= act/insert)

> + */
> +#define RD_FLD(base, reg, field) \
> +=C2=A0 =C2=A0 =C2=A0rd_fld(base + reg, reg##_##field##_MASK, reg##_##= field##_SHIFT)
> +#define WR_FLD(base, reg, field, val) \
> +=C2=A0 =C2=A0 =C2=A0wr_fld(base + reg, reg##_##field##_MASK, reg##_##= field##_SHIFT, val)
> +#define WR_FLD_RB(base, reg, field, val) \
> +=C2=A0 =C2=A0 =C2=A0wr_fld_rb(base + reg, reg##_##field##_MASK, reg##= _##field##_SHIFT, val)
> +#define WR_FLD_WITH_OFFSET(base, off, reg, field, val) \
> +=C2=A0 =C2=A0 =C2=A0wr_fld(base + reg + off, reg##_##field##_MASK, \<= br> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 reg##_##field##_SHIFT, val)=
> +#define EXTRACT_FIELD(val, reg, field) \
> +=C2=A0 =C2=A0 =C2=A0((val & reg##_##field##_MASK) >> reg##_= ##field##_SHIFT)
> +#define INSERT_FIELD(val, reg, field, field_val) \
> +=C2=A0 =C2=A0 =C2=A0((val & ~reg##_##field##_MASK) | \
> +=C2=A0 =C2=A0 =C2=A0 (reg##_##field##_MASK & (field_val << = reg##_##field##_SHIFT)))
> +
> +static struct list_head brcm_pcie =3D LIST_HEAD_INIT(brcm_pcie);
> +static phys_addr_t scb_size[BRCM_MAX_SCB];
> +static int num_memc;
> +static DEFINE_MUTEX(brcm_pcie_lock);
> +
> +static u32 rd_fld(void __iomem *p, u32 mask, int shift)
> +{
> +=C2=A0 =C2=A0 =C2=A0return (bcm_readl(p) & mask) >> shift;<= br> > +}
> +
> +static void wr_fld(void __iomem *p, u32 mask, int shift, u32 val)
> +{
> +=C2=A0 =C2=A0 =C2=A0u32 reg =3D bcm_readl(p);
> +
> +=C2=A0 =C2=A0 =C2=A0reg =3D (reg & ~mask) | ((val << shift)= & mask);
> +=C2=A0 =C2=A0 =C2=A0bcm_writel(reg, p);
> +}
> +
> +static void wr_fld_rb(void __iomem *p, u32 mask, int shift, u32 val)<= br> > +{
> +=C2=A0 =C2=A0 =C2=A0wr_fld(p, mask, shift, val);
> +=C2=A0 =C2=A0 =C2=A0(void)bcm_readl(p);
> +}
> +
> +static const char *link_speed_to_str(int s)
> +{
> +=C2=A0 =C2=A0 =C2=A0switch (s) {
> +=C2=A0 =C2=A0 =C2=A0case 1:
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return "2.5"= ;;
> +=C2=A0 =C2=A0 =C2=A0case 2:
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return "5.0"= ;;
> +=C2=A0 =C2=A0 =C2=A0case 3:
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return "8.0"= ;;
> +=C2=A0 =C2=A0 =C2=A0default:
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0break;
> +=C2=A0 =C2=A0 =C2=A0}
> +=C2=A0 =C2=A0 =C2=A0return "???";
> +}
> +
> +/*
> + * The roundup_pow_of_two() from log2.h invokes
> + * __roundup_pow_of_two(unsigned long), but we really need a
> + * such a function to take a native u64 since unsigned long
> + * is 32 bits on some configurations.=C2=A0 So we provide this helper=
> + * function below.
> + */
> +static u64 roundup_pow_of_two_64(u64 n)
> +{
> +=C2=A0 =C2=A0 =C2=A0return 1ULL << fls64(n - 1);
> +}
> +
> +/*
> + * This is to convert the size of the inbound bar region to the
> + * non-liniear values of PCIE_X_MISC_RC_BAR[123]_CONFIG_LO.SIZE<= br>
s/bar/BAR/=C2=A0 (This doesn't sound like a BAR in the PCI = spec sense, but if
that's what you call it, might as well spell it as the acronym)

s/non-liniear/non-linear/

> + */
> +int encode_ibar_size(u64 size)
> +{
> +=C2=A0 =C2=A0 =C2=A0int log2_in =3D ilog2(size);
> +
> +=C2=A0 =C2=A0 =C2=A0if (log2_in >=3D 12 && log2_in <=3D= 15)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* Covers 4KB to 32KB= (inclusive) */
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return (log2_in - 12)= + 0x1c;
> +=C2=A0 =C2=A0 =C2=A0else if (log2_in >=3D 16 && log2_in &l= t;=3D 37)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* Covers 64KB to 32G= B, (inclusive) */
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return log2_in - 15;<= br> > +=C2=A0 =C2=A0 =C2=A0/* Something is awry so disable */
> +=C2=A0 =C2=A0 =C2=A0return 0;
> +}
> +
> +static u32 mdio_form_pkt(int port, int regad, int cmd)
> +{
> +=C2=A0 =C2=A0 =C2=A0u32 pkt =3D 0;
> +
> +=C2=A0 =C2=A0 =C2=A0pkt |=3D (port << MDIO_PORT_SHIFT) & MD= IO_PORT_MASK;
> +=C2=A0 =C2=A0 =C2=A0pkt |=3D (regad << MDIO_REGAD_SHIFT) & = MDIO_REGAD_MASK;
> +=C2=A0 =C2=A0 =C2=A0pkt |=3D (cmd << MDIO_CMD_SHIFT) & MDIO= _CMD_MASK;
> +
> +=C2=A0 =C2=A0 =C2=A0return pkt;
> +}
> +
> +/* negative return value indicates error */
> +static int mdio_read(void __iomem *base, u8 port, u8 regad)
> +{
> +=C2=A0 =C2=A0 =C2=A0int tries;
> +=C2=A0 =C2=A0 =C2=A0u32 data;
> +
> +=C2=A0 =C2=A0 =C2=A0bcm_writel(mdio_form_pkt(port, regad, MDIO_CMD_RE= AD),
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 base + PCIE_R= C_DL_MDIO_ADDR);
> +=C2=A0 =C2=A0 =C2=A0bcm_readl(base + PCIE_RC_DL_MDIO_ADDR);
> +
> +=C2=A0 =C2=A0 =C2=A0data =3D bcm_readl(base + PCIE_RC_DL_MDIO_RD_DATA= );
> +=C2=A0 =C2=A0 =C2=A0for (tries =3D 0; !MDIO_RD_DONE(data) && = tries < 10; tries++) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0udelay(10);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0data =3D bcm_readl(ba= se + PCIE_RC_DL_MDIO_RD_DATA);
> +=C2=A0 =C2=A0 =C2=A0}
> +
> +=C2=A0 =C2=A0 =C2=A0return MDIO_RD_DONE(data)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0? (data & MDIO_DA= TA_MASK) >> MDIO_DATA_SHIFT
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0: -EIO;
> +}
> +
> +/* negative return value indicates error */
> +static int mdio_write(void __iomem *base, u8 port, u8 regad, u16 wrda= ta)
> +{
> +=C2=A0 =C2=A0 =C2=A0int tries;
> +=C2=A0 =C2=A0 =C2=A0u32 data;
> +
> +=C2=A0 =C2=A0 =C2=A0bcm_writel(mdio_form_pkt(port, regad, MDIO_CMD_WR= ITE),
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 base + PCIE_R= C_DL_MDIO_ADDR);
> +=C2=A0 =C2=A0 =C2=A0bcm_readl(base + PCIE_RC_DL_MDIO_ADDR);
> +=C2=A0 =C2=A0 =C2=A0bcm_writel(MDIO_DATA_DONE_MASK | wrdata,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 base + PCIE_R= C_DL_MDIO_WR_DATA);
> +
> +=C2=A0 =C2=A0 =C2=A0data =3D bcm_readl(base + PCIE_RC_DL_MDIO_WR_DATA= );
> +=C2=A0 =C2=A0 =C2=A0for (tries =3D 0; !MDIO_WT_DONE(data) && = tries < 10; tries++) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0udelay(10);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0data =3D bcm_readl(ba= se + PCIE_RC_DL_MDIO_WR_DATA);
> +=C2=A0 =C2=A0 =C2=A0}
> +
> +=C2=A0 =C2=A0 =C2=A0return MDIO_WT_DONE(data) ? 0 : -EIO;
> +}
> +
> +/* configures device for ssc mode; negative return value indicates er= ror */

I guess "ssc" means Spread Spectrum Clocking?=C2=A0 M= aybe spell out the
first occurrence and spell as acronym in English text?

> +static int set_ssc(void __iomem *base)
> +{
> +=C2=A0 =C2=A0 =C2=A0int tmp;
> +=C2=A0 =C2=A0 =C2=A0u16 wrdata;
> +=C2=A0 =C2=A0 =C2=A0int pll, ssc;
> +
> +=C2=A0 =C2=A0 =C2=A0tmp =3D mdio_write(base, MDIO_PORT0, SET_ADDR_OFF= SET, SSC_REGS_ADDR);
> +=C2=A0 =C2=A0 =C2=A0if (tmp < 0)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return tmp;
> +
> +=C2=A0 =C2=A0 =C2=A0tmp =3D mdio_read(base, MDIO_PORT0, SSC_CNTL_OFFS= ET);
> +=C2=A0 =C2=A0 =C2=A0if (tmp < 0)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return tmp;
> +
> +=C2=A0 =C2=A0 =C2=A0wrdata =3D INSERT_FIELD(tmp, SSC_CNTL_OVRD, EN, 1= );
> +=C2=A0 =C2=A0 =C2=A0wrdata =3D INSERT_FIELD(wrdata, SSC_CNTL_OVRD, VA= L, 1);
> +=C2=A0 =C2=A0 =C2=A0tmp =3D mdio_write(base, MDIO_PORT0, SSC_CNTL_OFF= SET, wrdata);
> +=C2=A0 =C2=A0 =C2=A0if (tmp < 0)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return tmp;
> +
> +=C2=A0 =C2=A0 =C2=A0usleep_range(1000, 2000);
> +=C2=A0 =C2=A0 =C2=A0tmp =3D mdio_read(base, MDIO_PORT0, SSC_STATUS_OF= FSET);
> +=C2=A0 =C2=A0 =C2=A0if (tmp < 0)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return tmp;
> +
> +=C2=A0 =C2=A0 =C2=A0ssc =3D EXTRACT_FIELD(tmp, SSC_STATUS, SSC);
> +=C2=A0 =C2=A0 =C2=A0pll =3D EXTRACT_FIELD(tmp, SSC_STATUS, PLL_LOCK);=
> +
> +=C2=A0 =C2=A0 =C2=A0return (ssc && pll) ? 0 : -EIO;
> +}
> +
> +/* limits operation to a specific generation (1, 2, or 3) */
> +static void set_gen(void __iomem *base, int gen)
> +{
> +=C2=A0 =C2=A0 =C2=A0u32 lnkcap =3D bcm_readl(base + BRCM_PCIE_CAP_REG= S + PCI_EXP_LNKCAP);
> +=C2=A0 =C2=A0 =C2=A0u16 lnkctl2 =3D bcm_readw(base + BRCM_PCIE_CAP_RE= GS + PCI_EXP_LNKCTL2);
> +
> +=C2=A0 =C2=A0 =C2=A0lnkcap =3D (lnkcap & ~PCI_EXP_LNKCAP_SLS) | g= en;
> +=C2=A0 =C2=A0 =C2=A0bcm_writel(lnkcap, base + BRCM_PCIE_CAP_REGS + PC= I_EXP_LNKCAP);
> +
> +=C2=A0 =C2=A0 =C2=A0lnkctl2 =3D (lnkctl2 & ~0xf) | gen;
> +=C2=A0 =C2=A0 =C2=A0bcm_writew(lnkctl2, base + BRCM_PCIE_CAP_REGS + P= CI_EXP_LNKCTL2);
> +}
> +
> +static void brcm_pcie_set_outbound_win(struct brcm_pcie *pcie, > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 unsigned int win, = phys_addr_t cpu_addr,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 dma_addr_t=C2=A0 p= cie_addr, dma_addr_t size)
> +{
> +=C2=A0 =C2=A0 =C2=A0void __iomem *base =3D pcie->base;
> +=C2=A0 =C2=A0 =C2=A0phys_addr_t cpu_addr_mb, limit_addr_mb;
> +=C2=A0 =C2=A0 =C2=A0u32 tmp;
> +
> +=C2=A0 =C2=A0 =C2=A0/* Set the base of the pcie_addr window */
> +=C2=A0 =C2=A0 =C2=A0bcm_writel(lower_32_bits(pcie_addr) + MMIO_E= NDIAN,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 base + PCIE_M= ISC_CPU_2_PCIE_MEM_WIN0_LO + (win * 8));
> +=C2=A0 =C2=A0 =C2=A0bcm_writel(upper_32_bits(pcie_addr),
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 base + PCIE_M= ISC_CPU_2_PCIE_MEM_WIN0_HI + (win * 8));
> +
> +=C2=A0 =C2=A0 =C2=A0cpu_addr_mb =3D cpu_addr >> 20;
> +=C2=A0 =C2=A0 =C2=A0limit_addr_mb =3D (cpu_addr + size - 1) >> = 20;
> +
> +=C2=A0 =C2=A0 =C2=A0/* Write the addr base low register */
> +=C2=A0 =C2=A0 =C2=A0WR_FLD_WITH_OFFSET(base, (win * 4),
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 BASE, cpu_addr_mb);
> +=C2=A0 =C2=A0 =C2=A0/* Write the addr limit low register */
> +=C2=A0 =C2=A0 =C2=A0WR_FLD_WITH_OFFSET(base, (win * 4),
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 LIMIT, limit_addr_mb);
> +
> +=C2=A0 =C2=A0 =C2=A0if (pcie->type !=3D BCM7435 && pcie-&g= t;type !=3D BCM7425) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* Write the cpu addr= high register */
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0tmp =3D (u32)(cpu_add= r_mb >>
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_NUM_MASK_BITS);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0WR_FLD_WITH_OFFSET(ba= se, (win * 8),
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 BASE, tmp);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* Write the cpu limi= t high register */
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0tmp =3D (u32)(limit_a= ddr_mb >>
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_NUM_MASK_BITS);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0WR_FLD_WITH_OFFSET(ba= se, (win * 8),
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 LIMIT, tmp);
> +=C2=A0 =C2=A0 =C2=A0}
> +}
> +
> +/* Configuration space read/write support */
> +static int cfg_index(int busnr, int devfn, int reg)
> +{
> +=C2=A0 =C2=A0 =C2=A0return ((PCI_SLOT(devfn) & 0x1f) << PCI= E_SLOT_SHIFT)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0| ((PCI_FUNC(devfn) &= amp; 0x07) << PCIE_FUNC_SHIFT)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0| (busnr << PCI= E_BUSNUM_SHIFT)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0| (reg & ~3);
> +}
> +
> +static bool brcm_pcie_rc_mode(struct brcm_pcie *pcie)
> +{
> +=C2=A0 =C2=A0 =C2=A0void __iomem *base =3D pcie->base;
> +=C2=A0 =C2=A0 =C2=A0u32 val =3D bcm_readl(base + PCIE_MISC_PCIE_STATU= S);
> +
> +=C2=A0 =C2=A0 =C2=A0return !!EXTRACT_FIELD(val, PCIE_MISC_PCIE_STATUS= , PCIE_PORT);
> +}
> +
> +static bool brcm_pcie_link_up(struct brcm_pcie *pcie)
> +{
> +=C2=A0 =C2=A0 =C2=A0void __iomem *base =3D pcie->base;
> +=C2=A0 =C2=A0 =C2=A0u32 val =3D bcm_readl(base + PCIE_MISC_PCIE_STATU= S);
> +=C2=A0 =C2=A0 =C2=A0u32 dla =3D EXTRACT_FIELD(val, PCIE_MISC_PCIE_STA= TUS, PCIE_DL_ACTIVE);
> +=C2=A0 =C2=A0 =C2=A0u32 plu =3D EXTRACT_FIELD(val, PCIE_MISC_PCIE_STA= TUS, PCIE_PHYLINKUP);
> +
> +=C2=A0 =C2=A0 =C2=A0return=C2=A0 (dla && plu) ? true : false;=
> +}
> +
> +static bool brcm_pcie_valid_device(struct brcm_pcie *pcie, struct pci= _bus *bus,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 int dev)
> +{
> +=C2=A0 =C2=A0 =C2=A0if (pci_is_root_bus(bus)) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (dev > 0)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0return false;
> +=C2=A0 =C2=A0 =C2=A0} else {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* If there is no lin= k, then there is no device */
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (!brcm_pcie_link_u= p(pcie))
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0return false;

This is racy, since the link can go down after you check but be= fore
you do the config access.=C2=A0 I assume your hardware can deal with a
config access that targets a link that is down?

> +=C2=A0 =C2=A0 =C2=A0}
> +
> +=C2=A0 =C2=A0 =C2=A0return true;
> +}
> +
> +static void __iomem *brcm_pcie_map_conf(struct pci_bus *bus, unsigned= int devfn,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0int where) > +{
> +=C2=A0 =C2=A0 =C2=A0struct brcm_pcie *pcie =3D bus->sysdata;
> +=C2=A0 =C2=A0 =C2=A0void __iomem *base =3D pcie->base;
> +=C2=A0 =C2=A0 =C2=A0int idx;
> +
> +=C2=A0 =C2=A0 =C2=A0if (!brcm_pcie_valid_device(pcie, bus, PCI_SLOT(d= evfn)))
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return NULL;
> +
> +=C2=A0 =C2=A0 =C2=A0/* Accesses to the RC go right to the RC register= s */
> +=C2=A0 =C2=A0 =C2=A0if (pci_is_root_bus(bus))
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return base + where;<= br> > +
> +=C2=A0 =C2=A0 =C2=A0/* For devices, write to the config space index r= egister */
> +=C2=A0 =C2=A0 =C2=A0idx =3D cfg_index(bus->number, devfn, where);<= br> > +=C2=A0 =C2=A0 =C2=A0bcm_writel(idx, pcie->base + IDX_ADDR(pcie));<= br> > +=C2=A0 =C2=A0 =C2=A0return base + DATA_ADDR(pcie) + (where & 0x3)= ;

I guess this is protected by a higher-level config access lock?
<= /blockquote>

All pci config space accessor functions -- = pci_bus_{read,write}_{byte,word,dword}() -- use a spinlock (pci_lock).=C2= =A0 These routines, covered by the spinlock, call pci_generic_{read,write}(= ), and those two functions call ops->map_bus(), aka our brcm_pcie_map_co= nf().

Unless=C2=A0CONFIG_PCI_LOCKLESS_CONFIG is se= t to "y", which it is not.


> +}
> +
> +static inline void brcm_pcie_bridge_sw_init_set(struct brcm_pcie= *pcie,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0unsigned int val)
> +{
> +=C2=A0 =C2=A0 =C2=A0unsigned int offset;
> +=C2=A0 =C2=A0 =C2=A0unsigned int shift =3D pcie->reg_field_info[RG= R1_SW_INIT_1_INIT_SHIFT];
> +=C2=A0 =C2=A0 =C2=A0u32 mask =3D=C2=A0 pcie->reg_field_info[RGR1_S= W_INIT_1_INIT_MASK];
> +
> +=C2=A0 =C2=A0 =C2=A0if (pcie->type !=3D BCM7278) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0wr_fld_rb(pcie->ba= se + PCIE_RGR1_SW_INIT_1(pcie), mask, shift,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0val);
> +=C2=A0 =C2=A0 =C2=A0} else if (of_machine_is_compatible("br= cm,bcm7278a0")) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/*
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 * The two PCIe insta= nces on 7278a0 are not even consistent with
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 * respect to each ot= her for internal offsets, here we offset
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 * by 0x14000 + RGR1_= SW_INIT_1's relative offset to account for
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 * that.
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 */
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0offset =3D pcie->i= d ? 0x14010 : pcie->reg_offsets[RGR1_SW_INIT_1];
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0wr_fld_rb(pcie->ba= se + offset, mask, shift, val);
> +=C2=A0 =C2=A0 =C2=A0} else {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0wr_fld_rb(pcie->ba= se + PCIE_RGR1_SW_INIT_1(pcie), mask, shift,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0val);
> +=C2=A0 =C2=A0 =C2=A0}
> +}
> +
> +static inline void brcm_pcie_perst_set(struct brcm_pcie *pcie,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 unsigned int val)<= br> > +{
> +=C2=A0 =C2=A0 =C2=A0if (pcie->type !=3D BCM7278)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0wr_fld_rb(pcie->ba= se + PCIE_RGR1_SW_INIT_1(pcie),
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0PCIE_RGR1_SW_INIT_1_PERST_MASK,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0PCIE_RGR1_SW_INIT_1_PERST_SHIFT, val);
> +=C2=A0 =C2=A0 =C2=A0else
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* Assert =3D 0, de-a= ssert =3D 1 on 7278 */
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0WR_FLD_RB(pcie->ba= se, PCIE_MISC_PCIE_CTRL, PCIE_PERSTB, !val);
> +}
> +
> +static int brcm_pcie_add_controller(struct brcm_pcie *pcie)
> +{
> +=C2=A0 =C2=A0 =C2=A0mutex_lock(&brcm_pcie_lock);
> +=C2=A0 =C2=A0 =C2=A0list_add_tail(&pcie->list, &brcm_pcie)= ;
> +=C2=A0 =C2=A0 =C2=A0mutex_unlock(&brcm_pcie_lock);
> +
> +=C2=A0 =C2=A0 =C2=A0return 0;
> +}
> +
> +static void brcm_pcie_remove_controller(struct brcm_pcie *pcie)<= br> > +{
> +=C2=A0 =C2=A0 =C2=A0struct list_head *pos, *q;
> +=C2=A0 =C2=A0 =C2=A0struct brcm_pcie *tmp;
> +
> +=C2=A0 =C2=A0 =C2=A0mutex_lock(&brcm_pcie_lock);
> +=C2=A0 =C2=A0 =C2=A0list_for_each_safe(pos, q, &brcm_pcie) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0tmp =3D list_entry(po= s, struct brcm_pcie, list);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (tmp =3D=3D pcie) = {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0list_del(pos);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0if (list_empty(&brcm_pcie))
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0num_memc =3D 0;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0break;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
> +=C2=A0 =C2=A0 =C2=A0}
> +=C2=A0 =C2=A0 =C2=A0mutex_unlock(&brcm_pcie_lock);

I'm missing something.=C2=A0 I don't see that num_memc = is ever set to
anything *other* than zero.

This pattern of keeping a list of controllers is highly unusual and
needs some explanation.

> +}
> +
> +static int brcm_pcie_parse_request_of_pci_ranges(struct brcm_pci= e *pcie)
> +{
> +=C2=A0 =C2=A0 =C2=A0struct resource_entry *win;
> +=C2=A0 =C2=A0 =C2=A0int ret;
> +
> +=C2=A0 =C2=A0 =C2=A0ret =3D of_pci_get_host_bridge_resources(pci= e->dn, 0, 0xff,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 &pcie->resources, NULL);
> +=C2=A0 =C2=A0 =C2=A0if (ret) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0dev_err(pcie->dev,= "failed to get host resources\n");
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return ret;
> +=C2=A0 =C2=A0 =C2=A0}
> +
> +=C2=A0 =C2=A0 =C2=A0resource_list_for_each_entry(win, &pcie-= >resources) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0struct resource *pare= nt, *res =3D win->res;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0dma_addr_t offset =3D= (dma_addr_t)win->offset;
> +
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (resource_type(res= ) =3D=3D IORESOURCE_IO) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0parent =3D &ioport_resource;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0} else if (resource_t= ype(res) =3D=3D IORESOURCE_MEM) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0if (pcie->num_out_wins >=3D BRCM_NUM_PCIE_OUT_WINS) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0dev_err(pcie->dev, "too many out= bound wins\n");
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return -EINVAL;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0}
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0pcie->out_wins[pcie->num_out_wins].cpu_addr
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D (phys_addr_t)res->start;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0pcie->out_wins[pcie->num_out_wins].pcie_addr
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D (dma_addr_t)(res->start
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 - (phys_addr_t)offset);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0pcie->out_wins[pcie->num_out_wins].size
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D (dma_addr_t)(res->end - res->s= tart + 1);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0pcie->num_out_wins++;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0parent =3D &iomem_resource;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0} else {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0continue;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
> +
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ret =3D devm_request_= resource(pcie->dev, parent, res);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (ret) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0dev_err(pcie->dev, "failed to get res %pR\n", res);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0return ret;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
> +=C2=A0 =C2=A0 =C2=A0}
> +=C2=A0 =C2=A0 =C2=A0return 0;
> +}
> +
> +static int brcm_pcie_setup(struct brcm_pcie *pcie)
> +{
> +=C2=A0 =C2=A0 =C2=A0void __iomem *base =3D pcie->base;
> +=C2=A0 =C2=A0 =C2=A0unsigned int scb_size_val;
> +=C2=A0 =C2=A0 =C2=A0u64 rc_bar2_size =3D 0, rc_bar2_offset =3D 0, tot= al_mem_size =3D 0;

Unnecessary initializations (at least of rc_bar2_size, I didn&#= 39;t check
the rest).

Add

=C2=A0 struct device *dev =3D pcie->dev;

then use it below.

> +=C2=A0 =C2=A0 =C2=A0u32 tmp, burst;
> +=C2=A0 =C2=A0 =C2=A0int i, j, ret, limit;
> +=C2=A0 =C2=A0 =C2=A0u16 nlw, cls, lnksta;
> +=C2=A0 =C2=A0 =C2=A0bool ssc_good =3D false;
> +
> +=C2=A0 =C2=A0 =C2=A0/* reset the bridge and the endpoint device */ > +=C2=A0 =C2=A0 =C2=A0/* field: PCIE_BRIDGE_SW_INIT =3D 1 */

Not sure what these "field: ..." comments mean.=C2=A0 Are = they for some
automated tool?=C2=A0 To a human, it looks like they repeat what the code does.

> +=C2=A0 =C2=A0 =C2=A0brcm_pcie_bridge_sw_init_set(pcie, 1);
> +
> +=C2=A0 =C2=A0 =C2=A0/* field: PCIE_SW_PERST =3D 1, on 7278, we start = de-asserted already */
> +=C2=A0 =C2=A0 =C2=A0if (pcie->type !=3D BCM7278)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0brcm_pcie_perst_set(p= cie, 1);
> +
> +=C2=A0 =C2=A0 =C2=A0usleep_range(100, 200);
> +
> +=C2=A0 =C2=A0 =C2=A0/* take the bridge out of reset */
> +=C2=A0 =C2=A0 =C2=A0/* field: PCIE_BRIDGE_SW_INIT =3D 0 */
> +=C2=A0 =C2=A0 =C2=A0brcm_pcie_bridge_sw_init_set(pcie, 0);
> +
> +=C2=A0 =C2=A0 =C2=A0WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEB= UG, SERDES_IDDQ, 0);
> +=C2=A0 =C2=A0 =C2=A0/* wait for serdes to be stable */
> +=C2=A0 =C2=A0 =C2=A0usleep_range(100, 200);
> +
> +=C2=A0 =C2=A0 =C2=A0/* Grab the PCIe hw revision number */
> +=C2=A0 =C2=A0 =C2=A0tmp =3D bcm_readl(base + PCIE_MISC_REVISION);
> +=C2=A0 =C2=A0 =C2=A0pcie->rev =3D EXTRACT_FIELD(tmp, PCIE_MISC_REV= ISION, MAJMIN);
> +
> +=C2=A0 =C2=A0 =C2=A0/* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_= ACCESS_EN */
> +=C2=A0 =C2=A0 =C2=A0tmp =3D INSERT_FIELD(0, PCIE_MISC_MISC_CTRL, SCB_= ACCESS_EN, 1);
> +=C2=A0 =C2=A0 =C2=A0tmp =3D INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, CF= G_READ_UR_MODE, 1);
> +=C2=A0 =C2=A0 =C2=A0burst =3D (pcie->type =3D=3D GENERIC || pcie-&= gt;type =3D=3D BCM7278)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0? BURST_SIZE_512 : BU= RST_SIZE_256;
> +=C2=A0 =C2=A0 =C2=A0tmp =3D INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, MA= X_BURST_SIZE, burst);
> +=C2=A0 =C2=A0 =C2=A0bcm_writel(tmp, base + PCIE_MISC_MISC_CTRL);
> +
> +=C2=A0 =C2=A0 =C2=A0/*
> +=C2=A0 =C2=A0 =C2=A0 * Set up inbound memory view for the EP (called = RC_BAR2,
> +=C2=A0 =C2=A0 =C2=A0 * not to be confused with the BARs that are adve= rtised by
> +=C2=A0 =C2=A0 =C2=A0 * the EP).
> +=C2=A0 =C2=A0 =C2=A0 */
> +=C2=A0 =C2=A0 =C2=A0for (i =3D 0; i < num_memc; i++)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0total_mem_size +=3D s= cb_size[i];
> +
> +=C2=A0 =C2=A0 =C2=A0/*
> +=C2=A0 =C2=A0 =C2=A0 * The PCIe host controller by design must set th= e inbound
> +=C2=A0 =C2=A0 =C2=A0 * viewport to be a contiguous arrangement of all= of the
> +=C2=A0 =C2=A0 =C2=A0 * system's memory.=C2=A0 In addition, its si= ze mut be a power of
> +=C2=A0 =C2=A0 =C2=A0 * two.=C2=A0 To further complicate matters, the = viewport must
> +=C2=A0 =C2=A0 =C2=A0 * start on a pcie-address that is aligned on a m= ultiple of its
> +=C2=A0 =C2=A0 =C2=A0 * size.=C2=A0 If a portion of the viewport does = not represent
> +=C2=A0 =C2=A0 =C2=A0 * system memory -- e.g. 3GB of memory requires a= 4GB viewport
> +=C2=A0 =C2=A0 =C2=A0 * -- we can map the outbound memory in or after = 3GB and even
> +=C2=A0 =C2=A0 =C2=A0 * though the viewport will overlap the outbound = memory the
> +=C2=A0 =C2=A0 =C2=A0 * controller will know to send outbound memory d= ownstream and
> +=C2=A0 =C2=A0 =C2=A0 * everything else upstream.
> +=C2=A0 =C2=A0 =C2=A0 */
> +=C2=A0 =C2=A0 =C2=A0rc_bar2_size =3D roundup_pow_of_two_64(total_mem_size);
> +
> +=C2=A0 =C2=A0 =C2=A0/*
> +=C2=A0 =C2=A0 =C2=A0 * Set simple configuration based on memory sizes=
> +=C2=A0 =C2=A0 =C2=A0 * only.=C2=A0 We always start the viewport at ad= dress 0.
> +=C2=A0 =C2=A0 =C2=A0 */
> +=C2=A0 =C2=A0 =C2=A0rc_bar2_offset =3D 0;
> +
> +=C2=A0 =C2=A0 =C2=A0tmp =3D lower_32_bits(rc_bar2_offset);
> +=C2=A0 =C2=A0 =C2=A0tmp =3D INSERT_FIELD(tmp, PCIE_MISC_RC_BAR2_CONFI= G_LO, SIZE,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 encode_ibar_size(rc_bar2_size));
> +=C2=A0 =C2=A0 =C2=A0bcm_writel(tmp, base + PCIE_MISC_RC_BAR2_CONFIG_L= O);
> +=C2=A0 =C2=A0 =C2=A0bcm_writel(upper_32_bits(rc_bar2_offset), > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 base + PCIE_M= ISC_RC_BAR2_CONFIG_HI);
> +
> +=C2=A0 =C2=A0 =C2=A0/* field: SCB0_SIZE, default =3D 0xf (1 GB) */ > +=C2=A0 =C2=A0 =C2=A0scb_size_val =3D scb_size[0]
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0? ilog2(scb_size[0]) = - 15 : 0xf;
> +=C2=A0 =C2=A0 =C2=A0WR_FLD(base, PCIE_MISC_MISC_CTRL, SCB0_SIZE, scb_= size_val);
> +
> +=C2=A0 =C2=A0 =C2=A0/* field: SCB1_SIZE, default =3D 0xf (1 GB) */ > +=C2=A0 =C2=A0 =C2=A0if (num_memc > 1) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0scb_size_val =3D scb_= size[1]
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0? ilog2(scb_size[1]) - 15 : 0xf;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0WR_FLD(base, PCIE_MIS= C_MISC_CTRL, SCB1_SIZE, scb_size_val);
> +=C2=A0 =C2=A0 =C2=A0}
> +
> +=C2=A0 =C2=A0 =C2=A0/* field: SCB2_SIZE, default =3D 0xf (1 GB) */ > +=C2=A0 =C2=A0 =C2=A0if (num_memc > 2) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0scb_size_val =3D scb_= size[2]
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0? ilog2(scb_size[2]) - 15 : 0xf;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0WR_FLD(base, PCIE_MIS= C_MISC_CTRL, SCB2_SIZE, scb_size_val);
> +=C2=A0 =C2=A0 =C2=A0}
> +
> +=C2=A0 =C2=A0 =C2=A0/* disable the PCIe->GISB memory window (RC_BA= R1) */
> +=C2=A0 =C2=A0 =C2=A0WR_FLD(base, PCIE_MISC_RC_BAR1_CONFIG_LO, SIZE, 0= );
> +
> +=C2=A0 =C2=A0 =C2=A0/* disable the PCIe->SCB memory window (RC_BAR= 3) */
> +=C2=A0 =C2=A0 =C2=A0WR_FLD(base, PCIE_MISC_RC_BAR3_CONFIG_LO, SIZE, 0= );
> +
> +=C2=A0 =C2=A0 =C2=A0if (!pcie->suspended) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* clear any interrup= ts we find on boot */
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0bcm_writel(0xffffffff= , base + PCIE_INTR2_CPU_BASE + CLR);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(void)bcm_readl(base = + PCIE_INTR2_CPU_BASE + CLR);
> +=C2=A0 =C2=A0 =C2=A0}
> +
> +=C2=A0 =C2=A0 =C2=A0/* Mask all interrupts since we are not handling = any yet */
> +=C2=A0 =C2=A0 =C2=A0bcm_writel(0xffffffff, base + PCIE_INTR2_CPU_BASE= + MASK_SET);
> +=C2=A0 =C2=A0 =C2=A0(void)bcm_readl(base + PCIE_INTR2_CPU_BASE + MASK= _SET);
> +
> +=C2=A0 =C2=A0 =C2=A0if (pcie->gen)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0set_gen(base, pcie-&g= t;gen);
> +
> +=C2=A0 =C2=A0 =C2=A0/* take the EP device out of reset */
> +=C2=A0 =C2=A0 =C2=A0/* field: PCIE_SW_PERST =3D 0 */
> +=C2=A0 =C2=A0 =C2=A0brcm_pcie_perst_set(pcie, 0);

<raises eyebrows>=C2=A0 Take the *EP* out of reset?=C2=A0= The host controller
driver shouldn't be touching an EP directly.=C2=A0 Maybe the comment doesn't match what the code actually does.

> +
> +=C2=A0 =C2=A0 =C2=A0/*
> +=C2=A0 =C2=A0 =C2=A0 * Give the RC/EP time to wake up, before trying = to configure RC.
> +=C2=A0 =C2=A0 =C2=A0 * Intermittently check status for link-up, up to= a total of 100ms
> +=C2=A0 =C2=A0 =C2=A0 * when we don't know if the device is there,= and up to 1000ms if
> +=C2=A0 =C2=A0 =C2=A0 * we do know the device is there.
> +=C2=A0 =C2=A0 =C2=A0 */
> +=C2=A0 =C2=A0 =C2=A0limit =3D pcie->suspended ? 1000 : 100;
> +=C2=A0 =C2=A0 =C2=A0for (i =3D 1, j =3D 0; j < limit && !b= rcm_pcie_link_up(pcie);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 j +=3D i, i =3D i * 2)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0msleep(i + j > lim= it ? limit - j : i);
> +
> +=C2=A0 =C2=A0 =C2=A0if (!brcm_pcie_link_up(pcie)) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0dev_info(pcie->dev= , "link down\n");
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return -ENODEV;
> +=C2=A0 =C2=A0 =C2=A0}
> +
> +=C2=A0 =C2=A0 =C2=A0if (!brcm_pcie_rc_mode(pcie)) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0dev_err(pcie->dev,= "PCIe misconfigured; is in EP mode\n");
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return -EINVAL;
> +=C2=A0 =C2=A0 =C2=A0}
> +
> +=C2=A0 =C2=A0 =C2=A0for (i =3D 0; i < pcie->num_out_wins; i++)<= br> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0brcm_pcie_set_outboun= d_win(pcie, i, pcie->out_wins[i].cpu_addr,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 pcie= ->out_wins[i].pcie_addr,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 pcie= ->out_wins[i].size);
> +
> +=C2=A0 =C2=A0 =C2=A0/*
> +=C2=A0 =C2=A0 =C2=A0 * For config space accesses on the RC, show the = right class for
> +=C2=A0 =C2=A0 =C2=A0 * a PCIe-PCIe bridge (the default setting is to = be EP mode).
> +=C2=A0 =C2=A0 =C2=A0 */
> +=C2=A0 =C2=A0 =C2=A0WR_FLD_RB(base, PCIE_RC_CFG_PRIV1_ID_VAL3, CLASS_= CODE, 0x060400);
> +
> +=C2=A0 =C2=A0 =C2=A0if (pcie->ssc) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ret =3D set_ssc(base)= ;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (ret =3D=3D 0)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0ssc_good =3D true;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0else
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0dev_err(pcie->dev,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"failed attempt to enter ssc mode\n= ");
> +=C2=A0 =C2=A0 =C2=A0}
> +
> +=C2=A0 =C2=A0 =C2=A0lnksta =3D bcm_readw(base + BRCM_PCIE_CAP_REGS + = PCI_EXP_LNKSTA);
> +=C2=A0 =C2=A0 =C2=A0cls =3D lnksta & PCI_EXP_LNKSTA_CLS;
> +=C2=A0 =C2=A0 =C2=A0nlw =3D (lnksta & PCI_EXP_LNKSTA_NLW) >>= ; PCI_EXP_LNKSTA_NLW_SHIFT;
> +=C2=A0 =C2=A0 =C2=A0dev_info(pcie->dev, "link up, %s Gbps x%u= %s\n", link_speed_to_str(cls),
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 nlw, ssc_good ? &quo= t;(SSC)" : "(!SSC)");
> +
> +=C2=A0 =C2=A0 =C2=A0/* PCIe->SCB endian mode for BAR */
> +=C2=A0 =C2=A0 =C2=A0/* field ENDIAN_MODE_BAR2 =3D DATA_ENDIAN */
> +=C2=A0 =C2=A0 =C2=A0WR_FLD_RB(base, PCIE_RC_CFG_VENDOR_VENDOR_SP= ECIFIC_REG1,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ENDIAN_MODE_BA= R2, DATA_ENDIAN);
> +
> +=C2=A0 =C2=A0 =C2=A0/*
> +=C2=A0 =C2=A0 =C2=A0 * Refclk from RC should be gated with CLKREQ# in= put when ASPM L0s,L1
> +=C2=A0 =C2=A0 =C2=A0 * is enabled =3D>=C2=A0 setting the CLKREQ_DE= BUG_ENABLE field to 1.
> +=C2=A0 =C2=A0 =C2=A0 */
> +=C2=A0 =C2=A0 =C2=A0WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEB= UG, CLKREQ_DEBUG_ENABLE, 1);
> +
> +=C2=A0 =C2=A0 =C2=A0return 0;
> +}
> +
> +static void enter_l23(struct brcm_pcie *pcie)
> +{
> +=C2=A0 =C2=A0 =C2=A0void __iomem *base =3D pcie->base;
> +=C2=A0 =C2=A0 =C2=A0int tries, l23;
> +
> +=C2=A0 =C2=A0 =C2=A0/* assert request for L23 */
> +=C2=A0 =C2=A0 =C2=A0WR_FLD_RB(base, PCIE_MISC_PCIE_CTRL, PCIE_L23_REQ= UEST, 1);
> +=C2=A0 =C2=A0 =C2=A0/* poll L23 status */
> +=C2=A0 =C2=A0 =C2=A0for (tries =3D 0, l23 =3D 0; tries < 1000 &= ;& !l23; tries++)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0l23 =3D RD_FLD(base, = PCIE_MISC_PCIE_STATUS, PCIE_LINK_IN_L23);
> +=C2=A0 =C2=A0 =C2=A0if (!l23)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0dev_err(pcie->dev,= "failed to enter L23\n");

What does "L23" mean?=C2=A0 Some power management thi= ng?

> +}
> +
> +static void turn_off(struct brcm_pcie *pcie)
> +{
> +=C2=A0 =C2=A0 =C2=A0void __iomem *base =3D pcie->base;
> +
> +=C2=A0 =C2=A0 =C2=A0if (brcm_pcie_link_up(pcie))
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0enter_l23(pcie);
> +=C2=A0 =C2=A0 =C2=A0/* Reset endpoint device */
> +=C2=A0 =C2=A0 =C2=A0brcm_pcie_perst_set(pcie, 1);
> +=C2=A0 =C2=A0 =C2=A0/* deassert request for L23 in case it was assert= ed */
> +=C2=A0 =C2=A0 =C2=A0WR_FLD_RB(base, PCIE_MISC_PCIE_CTRL, PCIE_L23_REQ= UEST, 0);
> +=C2=A0 =C2=A0 =C2=A0/* SERDES_IDDQ =3D 1 */
> +=C2=A0 =C2=A0 =C2=A0WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEB= UG, SERDES_IDDQ, 1);
> +=C2=A0 =C2=A0 =C2=A0/* Shutdown PCIe bridge */
> +=C2=A0 =C2=A0 =C2=A0brcm_pcie_bridge_sw_init_set(pcie, 1);
> +}
> +
> +static int brcm_pcie_suspend(struct device *dev)
> +{
> +=C2=A0 =C2=A0 =C2=A0struct brcm_pcie *pcie =3D dev_get_drvdata(dev);<= br> > +
> +=C2=A0 =C2=A0 =C2=A0turn_off(pcie);
> +=C2=A0 =C2=A0 =C2=A0clk_disable_unprepare(pcie->clk);
> +=C2=A0 =C2=A0 =C2=A0pcie->suspended =3D true;
> +
> +=C2=A0 =C2=A0 =C2=A0return 0;
> +}
> +
> +static int brcm_pcie_resume(struct device *dev)
> +{
> +=C2=A0 =C2=A0 =C2=A0struct brcm_pcie *pcie =3D dev_get_drvdata(dev);<= br> > +=C2=A0 =C2=A0 =C2=A0void __iomem *base;
> +=C2=A0 =C2=A0 =C2=A0int ret;
> +
> +=C2=A0 =C2=A0 =C2=A0base =3D pcie->base;
> +=C2=A0 =C2=A0 =C2=A0clk_prepare_enable(pcie->clk);
> +
> +=C2=A0 =C2=A0 =C2=A0/* Take bridge out of reset so we can access the = SERDES reg */

Some comments above and below spell it "serdes"; here= you spell it
"SERDES".

> +=C2=A0 =C2=A0 =C2=A0brcm_pcie_bridge_sw_init_set(pcie, 0);
> +
> +=C2=A0 =C2=A0 =C2=A0/* SERDES_IDDQ =3D 0 */
> +=C2=A0 =C2=A0 =C2=A0WR_FLD_RB(base, PCIE_MISC_HARD_PCIE_HARD_DEB= UG, SERDES_IDDQ, 0);
> +=C2=A0 =C2=A0 =C2=A0/* wait for serdes to be stable */
> +=C2=A0 =C2=A0 =C2=A0usleep_range(100, 200);
> +
> +=C2=A0 =C2=A0 =C2=A0ret =3D brcm_pcie_setup(pcie);
> +=C2=A0 =C2=A0 =C2=A0if (ret)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return ret;
> +
> +=C2=A0 =C2=A0 =C2=A0pcie->suspended =3D false;
> +
> +=C2=A0 =C2=A0 =C2=A0return 0;
> +}
> +
> +static void _brcm_pcie_remove(struct brcm_pcie *pcie)
> +{
> +=C2=A0 =C2=A0 =C2=A0turn_off(pcie);
> +=C2=A0 =C2=A0 =C2=A0clk_disable_unprepare(pcie->clk);
> +=C2=A0 =C2=A0 =C2=A0clk_put(pcie->clk);
> +=C2=A0 =C2=A0 =C2=A0brcm_pcie_remove_controller(pcie);
> +}
> +
> +static int brcm_pcie_remove(struct platform_device *pdev)
> +{
> +=C2=A0 =C2=A0 =C2=A0struct brcm_pcie *pcie =3D platform_get_drvdata(p= dev);
> +
> +=C2=A0 =C2=A0 =C2=A0pci_stop_root_bus(pcie->root_bus);
> +=C2=A0 =C2=A0 =C2=A0pci_remove_root_bus(pcie->root_bus);
> +=C2=A0 =C2=A0 =C2=A0_brcm_pcie_remove(pcie);
> +
> +=C2=A0 =C2=A0 =C2=A0return 0;
> +}
> +
> +static const struct of_device_id brcm_pcie_match[] =3D {
> +=C2=A0 =C2=A0 =C2=A0{ .compatible =3D "brcm,bcm7425-pcie", = .data =3D &bcm7425_cfg },
> +=C2=A0 =C2=A0 =C2=A0{ .compatible =3D "brcm,bcm7435-pcie", = .data =3D &bcm7435_cfg },
> +=C2=A0 =C2=A0 =C2=A0{ .compatible =3D "brcm,bcm7278-pcie", = .data =3D &bcm7278_cfg },
> +=C2=A0 =C2=A0 =C2=A0{ .compatible =3D "brcm,bcm7445-pcie", = .data =3D &generic_cfg },
> +=C2=A0 =C2=A0 =C2=A0{},
> +};
> +MODULE_DEVICE_TABLE(of, brcm_pcie_match);
> +
> +static int brcm_pcie_probe(struct platform_device *pdev)
> +{
> +=C2=A0 =C2=A0 =C2=A0struct device_node *dn =3D pdev->dev.of_node;<= br> > +=C2=A0 =C2=A0 =C2=A0const struct of_device_id *of_id;
> +=C2=A0 =C2=A0 =C2=A0const struct pcie_cfg_data *data;
> +=C2=A0 =C2=A0 =C2=A0int ret;
> +=C2=A0 =C2=A0 =C2=A0struct brcm_pcie *pcie;
> +=C2=A0 =C2=A0 =C2=A0struct resource *res;
> +=C2=A0 =C2=A0 =C2=A0void __iomem *base;
> +=C2=A0 =C2=A0 =C2=A0u32 tmp;
> +=C2=A0 =C2=A0 =C2=A0struct pci_host_bridge *bridge;
> +=C2=A0 =C2=A0 =C2=A0struct pci_bus *child;
> +
> +=C2=A0 =C2=A0 =C2=A0bridge =3D devm_pci_alloc_host_bridge(&p= dev->dev, sizeof(*pcie));
> +=C2=A0 =C2=A0 =C2=A0if (!bridge)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return -ENOMEM;
> +
> +=C2=A0 =C2=A0 =C2=A0pcie =3D pci_host_bridge_priv(bridge);
> +=C2=A0 =C2=A0 =C2=A0INIT_LIST_HEAD(&pcie->resources);
> +
> +=C2=A0 =C2=A0 =C2=A0of_id =3D of_match_node(brcm_pcie_match, dn);
> +=C2=A0 =C2=A0 =C2=A0if (!of_id) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0dev_err(&pdev->= ;dev, "failed to look up compatible string\n");
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return -EINVAL;
> +=C2=A0 =C2=A0 =C2=A0}
> +
> +=C2=A0 =C2=A0 =C2=A0if (of_property_read_u32(dn, "dma-ranges&quo= t;, &tmp) =3D=3D 0) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0dev_err(&pdev->= ;dev, "cannot yet handle dma-ranges\n");
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return -EINVAL;
> +=C2=A0 =C2=A0 =C2=A0}
> +
> +=C2=A0 =C2=A0 =C2=A0data =3D of_id->data;
> +=C2=A0 =C2=A0 =C2=A0pcie->reg_offsets =3D data->offsets;
> +=C2=A0 =C2=A0 =C2=A0pcie->reg_field_info =3D data->reg_field_in= fo;
> +=C2=A0 =C2=A0 =C2=A0pcie->type =3D data->type;
> +=C2=A0 =C2=A0 =C2=A0pcie->dn =3D dn;
> +=C2=A0 =C2=A0 =C2=A0pcie->dev =3D &pdev->dev;
> +
> +=C2=A0 =C2=A0 =C2=A0pcie->id =3D of_get_pci_domain_nr(dn);

Why do you call of_get_pci_domain_nr() directly?=C2=A0 No other= driver
does.

> +=C2=A0 =C2=A0 =C2=A0if (pcie->id < 0)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return pcie->id; > +
> +=C2=A0 =C2=A0 =C2=A0res =3D platform_get_resource(pdev, IORESOURCE_ME= M, 0);
> +=C2=A0 =C2=A0 =C2=A0if (!res)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return -EINVAL;
> +
> +=C2=A0 =C2=A0 =C2=A0base =3D devm_ioremap_resource(&pdev->dev, res);
> +=C2=A0 =C2=A0 =C2=A0if (IS_ERR(base))
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return PTR_ERR(base);=
> +
> +=C2=A0 =C2=A0 =C2=A0pcie->clk =3D of_clk_get_by_name(dn, "sw_= pcie");
> +=C2=A0 =C2=A0 =C2=A0if (IS_ERR(pcie->clk)) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0dev_err(&pdev->= ;dev, "could not get clock\n");
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0pcie->clk =3D NULL= ;
> +=C2=A0 =C2=A0 =C2=A0}
> +=C2=A0 =C2=A0 =C2=A0pcie->base =3D base;
> +
> +=C2=A0 =C2=A0 =C2=A0ret =3D of_pci_get_max_link_speed(dn);
> +=C2=A0 =C2=A0 =C2=A0pcie->gen =3D (ret < 0) ? 0 : ret;
> +
> +=C2=A0 =C2=A0 =C2=A0pcie->ssc =3D of_property_read_bool(dn, "= brcm,enable-ssc");
> +
> +=C2=A0 =C2=A0 =C2=A0ret =3D irq_of_parse_and_map(pdev->dev.of= _node, 0);
> +=C2=A0 =C2=A0 =C2=A0if (ret =3D=3D 0)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* keep going, as we = don't use this intr yet */
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0dev_warn(pcie->dev= , "cannot get pcie interrupt\n");
> +=C2=A0 =C2=A0 =C2=A0else
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0pcie->irq =3D ret;=
> +
> +=C2=A0 =C2=A0 =C2=A0ret =3D brcm_pcie_parse_request_of_pci_range= s(pcie);
> +=C2=A0 =C2=A0 =C2=A0if (ret)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return ret;
> +
> +=C2=A0 =C2=A0 =C2=A0ret =3D clk_prepare_enable(pcie->clk);
> +=C2=A0 =C2=A0 =C2=A0if (ret) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0dev_err(&pdev->= ;dev, "could not enable clock\n");
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return ret;
> +=C2=A0 =C2=A0 =C2=A0}
> +
> +=C2=A0 =C2=A0 =C2=A0ret =3D brcm_pcie_add_controller(pcie);
> +=C2=A0 =C2=A0 =C2=A0if (ret)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return ret;
> +
> +=C2=A0 =C2=A0 =C2=A0ret =3D brcm_pcie_setup(pcie);
> +=C2=A0 =C2=A0 =C2=A0if (ret)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0goto fail;
> +
> +=C2=A0 =C2=A0 =C2=A0list_splice_init(&pcie->resources, &a= mp;bridge->windows);
> +=C2=A0 =C2=A0 =C2=A0bridge->dev.parent =3D &pdev->dev;
> +=C2=A0 =C2=A0 =C2=A0bridge->busnr =3D 0;
> +=C2=A0 =C2=A0 =C2=A0bridge->ops =3D &brcm_pcie_ops;
> +=C2=A0 =C2=A0 =C2=A0bridge->sysdata =3D pcie;
> +=C2=A0 =C2=A0 =C2=A0bridge->map_irq =3D of_irq_parse_and_map_pci;<= br> > +=C2=A0 =C2=A0 =C2=A0bridge->swizzle_irq =3D pci_common_swizzle; > +
> +=C2=A0 =C2=A0 =C2=A0ret =3D pci_scan_root_bus_bridge(bridge); > +=C2=A0 =C2=A0 =C2=A0if (ret < 0) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0dev_err(pcie->dev,= "Scanning root bridge failed");
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0goto fail;
> +=C2=A0 =C2=A0 =C2=A0}
> +
> +=C2=A0 =C2=A0 =C2=A0pci_assign_unassigned_bus_resources(bridge-&= gt;bus);
> +=C2=A0 =C2=A0 =C2=A0list_for_each_entry(child, &bridge->bus-&g= t;children, node)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0pcie_bus_configure_se= ttings(child);
> +=C2=A0 =C2=A0 =C2=A0pci_bus_add_devices(bridge->bus);
> +=C2=A0 =C2=A0 =C2=A0platform_set_drvdata(pdev, pcie);
> +=C2=A0 =C2=A0 =C2=A0pcie->root_bus =3D bridge->bus;
> +
> +=C2=A0 =C2=A0 =C2=A0return 0;
> +
> +fail:
> +=C2=A0 =C2=A0 =C2=A0_brcm_pcie_remove(pcie);
> +=C2=A0 =C2=A0 =C2=A0return ret;
> +}
> +
> +static const struct dev_pm_ops brcm_pcie_pm_ops =3D {
> +=C2=A0 =C2=A0 =C2=A0.suspend_noirq =3D brcm_pcie_suspend,
> +=C2=A0 =C2=A0 =C2=A0.resume_noirq =3D brcm_pcie_resume,
> +};
> +
> +static struct platform_driver __refdata brcm_pcie_driver =3D {

Why do you need __refdata?=C2=A0 There's only only other oc= currence in
drivers/pci, and I'm dubious about that one as well.

> +=C2=A0 =C2=A0 =C2=A0.probe =3D brcm_pcie_probe,
> +=C2=A0 =C2=A0 =C2=A0.remove =3D brcm_pcie_remove,
> +=C2=A0 =C2=A0 =C2=A0.driver =3D {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0.name =3D "brcm-= pcie",
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0.owner =3D THIS_MODUL= E,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0.of_match_table =3D b= rcm_pcie_match,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0.pm =3D &brcm_pci= e_pm_ops,
> +=C2=A0 =C2=A0 =C2=A0},
> +};
> +
> +module_platform_driver(brcm_pcie_driver);
> +
> +MODULE_LICENSE("GPL");

Copyright notice above says "GPL v2", which is not the sam= e as the
"GPL" here.

> +MODULE_DESCRIPTION("Broadcom STB PCIE RC driver");
> +MODULE_AUTHOR("Broadcom");
> --
> 1.9.0.138.g2de3478
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kern= el@lists.infradead.org
> http://lists.infradead.org/mai= lman/listinfo/linux-arm-kernel

--94eb2c1dffd8150aa8056052c206--