lkml.org 
[lkml]   [2020]   [May]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 11/14] PCI: brcmstb: Set internal memory viewport sizes
    Date
    BrcmSTB PCIe controllers are intimately connected to the memory
    controller(s) on the SOC. There is a "viewport" for each memory controller
    that allows inbound accesses to CPU memory. Each viewport's size must be
    set to a power of two, and that size must be equal to or larger than the
    amount of memory each controller supports.

    Signed-off-by: Jim Quinlan <james.quinlan@broadcom.com>
    ---
    drivers/pci/controller/pcie-brcmstb.c | 67 ++++++++++++++++++++-------
    1 file changed, 49 insertions(+), 18 deletions(-)

    diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
    index fa356bc149c3..338e9ed44230 100644
    --- a/drivers/pci/controller/pcie-brcmstb.c
    +++ b/drivers/pci/controller/pcie-brcmstb.c
    @@ -55,6 +55,8 @@
    #define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK 0x300000
    #define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_128 0x0
    #define PCIE_MISC_MISC_CTRL_SCB0_SIZE_MASK 0xf8000000
    +#define PCIE_MISC_MISC_CTRL_SCB1_SIZE_MASK 0x07c00000
    +#define PCIE_MISC_MISC_CTRL_SCB2_SIZE_MASK 0x0000001f

    #define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO 0x400c
    #define PCIE_MEM_WIN0_LO(win) \
    @@ -152,6 +154,7 @@
    #define SSC_STATUS_OFFSET 0x1
    #define SSC_STATUS_SSC_MASK 0x400
    #define SSC_STATUS_PLL_LOCK_MASK 0x800
    +#define PCIE_BRCM_MAX_MEMC 3

    /* Rescal registers */
    #define PCIE_DVT_PMU_PCIE_PHY_CTRL 0xc700
    @@ -261,6 +264,8 @@ struct brcm_pcie {
    const int *reg_field_info;
    enum pcie_type type;
    struct reset_control *rescal;
    + int num_memc;
    + u64 memc_size[PCIE_BRCM_MAX_MEMC];
    };

    /*
    @@ -717,22 +722,40 @@ static inline int brcm_pcie_get_rc_bar2_size_and_offset(struct brcm_pcie *pcie,
    u64 *rc_bar2_offset)
    {
    struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
    - struct device *dev = pcie->dev;
    struct resource_entry *entry;
    + struct device *dev = pcie->dev;
    + u64 lowest_pcie_addr = ~(u64)0;
    + int ret, i = 0;
    + u64 size = 0;

    - entry = resource_list_first_type(&bridge->dma_ranges, IORESOURCE_MEM);
    - if (!entry)
    - return -ENODEV;
    + resource_list_for_each_entry(entry, &bridge->dma_ranges) {
    + u64 pcie_beg = entry->res->start - entry->offset;

    + size += entry->res->end - entry->res->start + 1;
    + if (pcie_beg < lowest_pcie_addr)
    + lowest_pcie_addr = pcie_beg;
    + }

    - /*
    - * The controller expects the inbound window offset to be calculated as
    - * the difference between PCIe's address space and CPU's. The offset
    - * provided by the firmware is calculated the opposite way, so we
    - * negate it.
    - */
    - *rc_bar2_offset = -entry->offset;
    - *rc_bar2_size = 1ULL << fls64(entry->res->end - entry->res->start);
    + ret = of_property_read_variable_u64_array(
    + pcie->np, "brcm,scb-sizes", pcie->memc_size, 1,
    + PCIE_BRCM_MAX_MEMC);
    +
    + if (ret <= 0) {
    + /* Make an educated guess */
    + pcie->num_memc = 1;
    + pcie->memc_size[0] = 1 << fls64(size - 1);
    + } else {
    + pcie->num_memc = ret;
    + }
    +
    + /* Each memc is viewed through a "port" that is a power of 2 */
    + for (i = 0, size = 0; i < pcie->num_memc; i++)
    + size += pcie->memc_size[i];
    +
    + /* System memory starts at this address in PCIe-space */
    + *rc_bar2_offset = lowest_pcie_addr;
    + /* The sum of all memc views must also be a power of 2 */
    + *rc_bar2_size = 1ULL << fls64(size - 1);

    /*
    * We validate the inbound memory view even though we should trust
    @@ -784,12 +807,11 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
    void __iomem *base = pcie->base;
    struct device *dev = pcie->dev;
    struct resource_entry *entry;
    - unsigned int scb_size_val;
    bool ssc_good = false;
    struct resource *res;
    int num_out_wins = 0;
    u16 nlw, cls, lnksta;
    - int i, ret;
    + int i, ret, memc;
    u32 tmp, aspm_support;

    /* Reset the bridge */
    @@ -825,11 +847,20 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
    writel(upper_32_bits(rc_bar2_offset),
    base + PCIE_MISC_RC_BAR2_CONFIG_HI);

    - scb_size_val = rc_bar2_size ?
    - ilog2(rc_bar2_size) - 15 : 0xf; /* 0xf is 1GB */
    tmp = readl(base + PCIE_MISC_MISC_CTRL);
    - u32p_replace_bits(&tmp, scb_size_val,
    - PCIE_MISC_MISC_CTRL_SCB0_SIZE_MASK);
    + for (memc = 0; memc < pcie->num_memc; memc++) {
    + u32 scb_size_val = ilog2(pcie->memc_size[memc]) - 15;
    +
    + if (memc == 0)
    + u32p_replace_bits(&tmp, scb_size_val,
    + PCIE_MISC_MISC_CTRL_SCB0_SIZE_MASK);
    + else if (memc == 1)
    + u32p_replace_bits(&tmp, scb_size_val,
    + PCIE_MISC_MISC_CTRL_SCB1_SIZE_MASK);
    + else if (memc == 2)
    + u32p_replace_bits(&tmp, scb_size_val,
    + PCIE_MISC_MISC_CTRL_SCB2_SIZE_MASK);
    + }
    writel(tmp, base + PCIE_MISC_MISC_CTRL);

    /*
    --
    2.17.1
    \
     
     \ /
      Last update: 2020-05-26 21:19    [W:4.343 / U:0.016 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site