From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
To: Jim Quinlan <james.quinlan@broadcom.com>
Cc: linux-pci@vger.kernel.org,
"Nicolas Saenz Julienne" <nsaenz@kernel.org>,
"Bjorn Helgaas" <bhelgaas@google.com>,
"Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>,
"Cyril Brulebois" <kibi@debian.org>,
"Stanimir Varbanov" <svarbanov@suse.de>,
"Krzysztof Kozlowski" <krzk@kernel.org>,
bcm-kernel-feedback-list@broadcom.com, jim2101024@gmail.com,
"Florian Fainelli" <florian.fainelli@broadcom.com>,
"Lorenzo Pieralisi" <lpieralisi@kernel.org>,
"Krzysztof Wilczyński" <kw@linux.com>,
"Rob Herring" <robh@kernel.org>,
"moderated list:BROADCOM BCM2711/BCM2835 ARM ARCHITECTURE"
<linux-rpi-kernel@lists.infradead.org>,
"moderated list:BROADCOM BCM2711/BCM2835 ARM ARCHITECTURE"
<linux-arm-kernel@lists.infradead.org>,
"open list" <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v5 09/12] PCI: brcmstb: Refactor for chips with many regular inbound windows
Date: Wed, 7 Aug 2024 19:34:01 +0530 [thread overview]
Message-ID: <20240807140401.GJ3412@thinkpad> (raw)
In-Reply-To: <20240731222831.14895-10-james.quinlan@broadcom.com>
On Wed, Jul 31, 2024 at 06:28:23PM -0400, Jim Quinlan wrote:
> Provide support for new chips with multiple inbound windows while
> keeping the legacy support for the older chips.
>
> In existing chips there are three inbound windows with fixed purposes: the
> first was for mapping SoC internal registers, the second was for memory,
> and the third was for memory but with the endian swapped. Typically, only
> one window was used.
>
> Complicating the inbound window usage was the fact that the PCIe HW would
> do a baroque internal mapping of system memory, and concatenate the regions
> of multiple memory controllers.
>
> Newer chips such as the 7712 and Cable Modem SOCs take a step forward and
> drop the internal mapping while providing for multiple inbound windows.
> This works in concert with the dma-ranges property, where each provided
> range becomes an inbound window.
>
> Signed-off-by: Jim Quinlan <james.quinlan@broadcom.com>
> ---
> drivers/pci/controller/pcie-brcmstb.c | 228 ++++++++++++++++++++------
> 1 file changed, 177 insertions(+), 51 deletions(-)
>
> diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
> index 4659208ae8da..0ecca3d9576f 100644
> --- a/drivers/pci/controller/pcie-brcmstb.c
> +++ b/drivers/pci/controller/pcie-brcmstb.c
> @@ -75,15 +75,19 @@
> #define PCIE_MEM_WIN0_HI(win) \
> PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI + ((win) * 8)
>
> +/*
> + * NOTE: You may see the term "BAR" in a number of register names used by
> + * this driver. The term is an artifact of when the HW core was an
> + * endpoint device (EP). Now it is a root complex (RC) and anywhere a
> + * register has the term "BAR" it is related to an inbound window.
> + */
> +
> +#define PCIE_BRCM_MAX_INBOUND_WINS 16
> #define PCIE_MISC_RC_BAR1_CONFIG_LO 0x402c
> #define PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_MASK 0x1f
>
> -#define PCIE_MISC_RC_BAR2_CONFIG_LO 0x4034
> -#define PCIE_MISC_RC_BAR2_CONFIG_LO_SIZE_MASK 0x1f
> -#define PCIE_MISC_RC_BAR2_CONFIG_HI 0x4038
> +#define PCIE_MISC_RC_BAR4_CONFIG_LO 0x40d4
>
> -#define PCIE_MISC_RC_BAR3_CONFIG_LO 0x403c
> -#define PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_MASK 0x1f
>
> #define PCIE_MISC_MSI_BAR_CONFIG_LO 0x4044
> #define PCIE_MISC_MSI_BAR_CONFIG_HI 0x4048
> @@ -130,6 +134,10 @@
> (PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK | \
> PCIE_MISC_HARD_PCIE_HARD_DEBUG_L1SS_ENABLE_MASK)
>
> +#define PCIE_MISC_UBUS_BAR1_CONFIG_REMAP 0x40ac
> +#define PCIE_MISC_UBUS_BAR1_CONFIG_REMAP_ACCESS_EN_MASK BIT(0)
> +#define PCIE_MISC_UBUS_BAR4_CONFIG_REMAP 0x410c
> +
> #define PCIE_MSI_INTR2_BASE 0x4500
>
> /* Offsets from INTR2_CPU and MSI_INTR2 BASE offsets */
> @@ -217,12 +225,20 @@ enum pcie_type {
> BCM4908,
> BCM7278,
> BCM2711,
> + BCM7712,
> +};
> +
> +struct inbound_win {
> + u64 size;
> + u64 pci_offset;
> + u64 cpu_addr;
> };
>
> struct pcie_cfg_data {
> const int *offsets;
> const enum pcie_type type;
> const bool has_phy;
> + unsigned int num_inbound_wins;
> void (*perst_set)(struct brcm_pcie *pcie, u32 val);
> void (*bridge_sw_init_set)(struct brcm_pcie *pcie, u32 val);
> };
> @@ -274,6 +290,7 @@ struct brcm_pcie {
> struct subdev_regulators *sr;
> bool ep_wakeup_capable;
> bool has_phy;
> + int num_inbound_wins;
> };
>
> static inline bool is_bmips(const struct brcm_pcie *pcie)
> @@ -789,23 +806,61 @@ static void brcm_pcie_perst_set_generic(struct brcm_pcie *pcie, u32 val)
> writel(tmp, pcie->base + PCIE_RGR1_SW_INIT_1(pcie));
> }
>
> -static int brcm_pcie_get_rc_bar2_size_and_offset(struct brcm_pcie *pcie,
> - u64 *rc_bar2_size,
> - u64 *rc_bar2_offset)
> +static inline void set_bar(struct inbound_win *b, int *count, u64 size,
> + u64 cpu_addr, u64 pci_offset)
There is no need to pass 'inline' keyword in a .c file. Making a function inline
is upto the discretion of the compiler.
Also, set_bar() is quite misleading as you are not setting any BAR but just
populating the inbound_win struct. So how about, "add_inbound_window()"?
> +{
> + b->size = size;
> + b->cpu_addr = cpu_addr;
> + b->pci_offset = pci_offset;
> + (*count)++;
> +}
> +
> +static int brcm_pcie_get_inbound_wins(struct brcm_pcie *pcie,
> + struct inbound_win inbound_wins[])
> {
> struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
> + u64 pci_offset, cpu_addr, size = 0, tot_size = 0;
> struct resource_entry *entry;
> struct device *dev = pcie->dev;
> u64 lowest_pcie_addr = ~(u64)0;
> - int ret, i = 0;
> - u64 size = 0;
> + int ret, i = 0, n = 0;
> +
> + /*
> + * The HW registers (and PCIe) use order-1 numbering for BARs. As
> + * such, we have inbound_wins[0] unused and BAR1 starts at inbound_wins[1].
> + */
Instead of wasting one array entry, you can start the array from 0 and just
decrement the index where needed? Like,
reg_offset = brcm_bar_reg_offset(i - 1);
> + struct inbound_win *b_begin = &inbound_wins[1];
> + struct inbound_win *b = b_begin;
> +
> + /*
> + * STB chips beside 7712 disable the first inbound window default.
> + * Rather being mapped to system memory it is mapped to the
> + * internal registers of the SoC. This feature is deprecated, has
> + * security considerations, and is not implemented in our modern
> + * SoCs.
> + */
> + if (pcie->type != BCM7712)
> + set_bar(b++, &n, 0, 0, 0);
>
> resource_list_for_each_entry(entry, &bridge->dma_ranges) {
> u64 pcie_beg = entry->res->start - entry->offset;
> + u64 cpu_beg = entry->res->start;
What does 'beg' mean?
>
> - size += entry->res->end - entry->res->start + 1;
> + size = resource_size(entry->res);
> + tot_size += size;
> if (pcie_beg < lowest_pcie_addr)
> lowest_pcie_addr = pcie_beg;
> + /*
> + * 7712 and newer chips may have many BARs, with each
> + * offering a non-overlapping viewport to system memory.
> + * That being said, each BARs size must still be a power of
> + * two.
> + */
> + if (pcie->type == BCM7712)
> + set_bar(b++, &n, size, cpu_beg, pcie_beg);
> +
> + if (n > pcie->num_inbound_wins)
> + break;
> }
>
> if (lowest_pcie_addr == ~(u64)0) {
> @@ -813,13 +868,20 @@ static int brcm_pcie_get_rc_bar2_size_and_offset(struct brcm_pcie *pcie,
> return -EINVAL;
> }
>
> + /*
> + * 7712 and newer chips do not have an internal memory mapping system
> + * that enables multiple memory controllers. As such, it can return
> + * now w/o doing special configuration.
> + */
> + if (pcie->type == BCM7712)
> + return n;
> +
> 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] = 1ULL << fls64(size - 1);
> + pcie->memc_size[0] = 1ULL << fls64(tot_size - 1);
> } else {
> pcie->num_memc = ret;
> }
> @@ -828,10 +890,15 @@ static int brcm_pcie_get_rc_bar2_size_and_offset(struct brcm_pcie *pcie,
> 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);
> + /* Our HW mandates that the window size must be a power of 2 */
> + size = 1ULL << fls64(size - 1);
> +
> + /*
> + * For STB chips, the BAR2 cpu_addr is hardwired to the start
> + * of system memory, so we set it to 0.
> + */
> + cpu_addr = 0;
> + pci_offset = lowest_pcie_addr;
>
> /*
> * We validate the inbound memory view even though we should trust
> @@ -866,25 +933,90 @@ static int brcm_pcie_get_rc_bar2_size_and_offset(struct brcm_pcie *pcie,
> * outbound memory @ 3GB). So instead it will start at the 1x
> * multiple of its size
> */
> - if (!*rc_bar2_size || (*rc_bar2_offset & (*rc_bar2_size - 1)) ||
> - (*rc_bar2_offset < SZ_4G && *rc_bar2_offset > SZ_2G)) {
> - dev_err(dev, "Invalid rc_bar2_offset/size: size 0x%llx, off 0x%llx\n",
> - *rc_bar2_size, *rc_bar2_offset);
> + if (!size || (pci_offset & (size - 1)) ||
> + (pci_offset < SZ_4G && pci_offset > SZ_2G)) {
> + dev_err(dev, "Invalid inbound_win2_offset/size: size 0x%llx, off 0x%llx\n",
> + size, pci_offset);
> return -EINVAL;
> }
>
> - return 0;
> + /* Enable inbound window 2, the main inbound window for STB chips */
> + set_bar(b++, &n, size, cpu_addr, pci_offset);
> +
> + /*
> + * Disable inbound window 3. On some chips presents the same
> + * window as #2 but the data appears in a settable endianness.
> + */
> + set_bar(b++, &n, 0, 0, 0);
> +
> + return n;
> +}
> +
> +static u32 brcm_bar_reg_offset(int bar)
> +{
> + if (bar <= 3)
> + return PCIE_MISC_RC_BAR1_CONFIG_LO + 8 * (bar - 1);
> + else
> + return PCIE_MISC_RC_BAR4_CONFIG_LO + 8 * (bar - 4);
> +}
> +
> +static u32 brcm_ubus_reg_offset(int bar)
> +{
> + if (bar <= 3)
> + return PCIE_MISC_UBUS_BAR1_CONFIG_REMAP + 8 * (bar - 1);
> + else
> + return PCIE_MISC_UBUS_BAR4_CONFIG_REMAP + 8 * (bar - 4);
> +}
> +
> +static void set_inbound_win_registers(struct brcm_pcie *pcie,
> + const struct inbound_win *inbound_wins,
> + int num_inbound_wins)
> +{
> + void __iomem *base = pcie->base;
> + int i;
> +
> + for (i = 1; i <= num_inbound_wins; i++) {
> + u64 pci_offset = inbound_wins[i].pci_offset;
> + u64 cpu_addr = inbound_wins[i].cpu_addr;
> + u64 size = inbound_wins[i].size;
> + u32 reg_offset = brcm_bar_reg_offset(i);
> + u32 tmp = lower_32_bits(pci_offset);
> +
> + u32p_replace_bits(&tmp, brcm_pcie_encode_ibar_size(size),
> + PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_MASK);
> +
> + /* Write low */
> + writel(tmp, base + reg_offset);
Can you use writel_relaxed() instead? Here and below. I don't see a necessity to
use the barrier that comes with non-relaxed version of writel.
- Mani
--
மணிவண்ணன் சதாசிவம்
next prev parent reply other threads:[~2024-08-07 14:04 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-31 22:28 [PATCH v5 00/12] PCI: brcnstb: Enable STB 7712 SOC Jim Quinlan
2024-07-31 22:28 ` [PATCH v5 01/12] dt-bindings: PCI: Cleanup of brcmstb YAML and add 7712 SoC Jim Quinlan
2024-08-01 16:35 ` Florian Fainelli
2024-08-02 6:43 ` Krzysztof Kozlowski
2024-08-12 22:07 ` Jim Quinlan
2024-08-13 8:27 ` Krzysztof Kozlowski
2024-08-14 17:35 ` Jim Quinlan
2024-08-14 18:05 ` Krzysztof Kozlowski
2024-07-31 22:28 ` [PATCH v5 02/12] dt-bindings: PCI: brcmstb: Add 7712 SoC description Jim Quinlan
2024-08-01 16:36 ` Florian Fainelli
2024-08-02 7:18 ` Krzysztof Kozlowski
2024-07-31 22:28 ` [PATCH v5 03/12] PCI: brcmstb: Use common error handling code in brcm_pcie_probe() Jim Quinlan
2024-08-01 16:37 ` Florian Fainelli
2024-08-07 2:52 ` Manivannan Sadhasivam
2024-08-12 20:12 ` Jim Quinlan
2024-08-07 2:54 ` Manivannan Sadhasivam
2024-08-13 16:45 ` Stanimir Varbanov
2024-08-13 17:06 ` James Quinlan
2024-07-31 22:28 ` [PATCH v5 04/12] PCI: brcmstb: Use bridge reset if available Jim Quinlan
2024-08-01 16:37 ` Florian Fainelli
2024-08-07 2:59 ` Manivannan Sadhasivam
2024-08-09 11:16 ` Stanimir Varbanov
2024-08-12 15:13 ` Jim Quinlan
2024-08-12 15:46 ` Jim Quinlan
2024-08-12 22:28 ` Stanimir Varbanov
2024-08-13 15:46 ` James Quinlan
2024-07-31 22:28 ` [PATCH v5 05/12] PCI: brcmstb: Use swinit " Jim Quinlan
2024-08-01 16:37 ` Florian Fainelli
2024-08-07 3:03 ` Manivannan Sadhasivam
2024-08-12 17:54 ` Jim Quinlan
2024-08-09 9:53 ` Stanimir Varbanov
2024-08-12 13:43 ` Jim Quinlan
2024-08-12 15:57 ` Manivannan Sadhasivam
2024-08-12 22:05 ` Stanimir Varbanov
2024-07-31 22:28 ` [PATCH v5 06/12] PCI: brcmstb: PCI: brcmstb: Make HARD_DEBUG, INTR2_CPU_BASE offsets SoC-specific Jim Quinlan
2024-07-31 22:28 ` [PATCH v5 07/12] PCI: brcmstb: Remove two unused constants from driver Jim Quinlan
2024-07-31 22:28 ` [PATCH v5 08/12] PCI: brcmstb: Don't conflate the reset rescal with phy ctrl Jim Quinlan
2024-08-07 3:05 ` Manivannan Sadhasivam
2024-07-31 22:28 ` [PATCH v5 09/12] PCI: brcmstb: Refactor for chips with many regular inbound windows Jim Quinlan
2024-08-01 16:39 ` Florian Fainelli
2024-08-06 22:58 ` Stanimir Varbanov
2024-08-07 14:04 ` Manivannan Sadhasivam [this message]
2024-08-07 14:16 ` Florian Fainelli
2024-08-07 15:03 ` Manivannan Sadhasivam
2024-08-12 19:14 ` Jim Quinlan
2024-07-31 22:28 ` [PATCH v5 10/12] PCI: brcmstb: Check return value of all reset_control_xxx calls Jim Quinlan
2024-08-07 14:11 ` Manivannan Sadhasivam
2024-08-12 18:20 ` Jim Quinlan
2024-07-31 22:28 ` [PATCH v5 11/12] PCI: brcmstb: Change field name from 'type' to 'soc_base' Jim Quinlan
2024-08-01 16:34 ` Florian Fainelli
2024-07-31 22:28 ` [PATCH v5 12/12] PCI: brcmstb: Enable 7712 SOCs Jim Quinlan
2024-08-07 14:12 ` Manivannan Sadhasivam
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240807140401.GJ3412@thinkpad \
--to=manivannan.sadhasivam@linaro.org \
--cc=bcm-kernel-feedback-list@broadcom.com \
--cc=bhelgaas@google.com \
--cc=florian.fainelli@broadcom.com \
--cc=james.quinlan@broadcom.com \
--cc=jim2101024@gmail.com \
--cc=kibi@debian.org \
--cc=krzk@kernel.org \
--cc=kw@linux.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=linux-rpi-kernel@lists.infradead.org \
--cc=lorenzo.pieralisi@arm.com \
--cc=lpieralisi@kernel.org \
--cc=nsaenz@kernel.org \
--cc=robh@kernel.org \
--cc=svarbanov@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.