All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/9] USB host support for Raspberry Pi 4 board
       [not found] <CGME20200421165108eucas1p190b455fc38d44c3f768630c8e194cd9a@eucas1p1.samsung.com>
@ 2020-04-21 16:50 ` Sylwester Nawrocki
       [not found]   ` <CGME20200421165114eucas1p2baa595b46f7503331ab86163f69b7c0e@eucas1p2.samsung.com>
                     ` (8 more replies)
  0 siblings, 9 replies; 36+ messages in thread
From: Sylwester Nawrocki @ 2020-04-21 16:50 UTC (permalink / raw)
  To: u-boot

Hi all,

This patch series adds USB host support for Raspberry Pi 4 board. 
It includes the Broadcom STB PCIe driver ported from Linux kernel,
a memory mapping update for the xHCI controller behind the PCIe bridge
for 32-bit and 64-bit system builds and some related fixes and updates
in the usb/xhci and the pci driver core code.

One of the issues I run into with RPI4 was not working accesses to 
64-bit xHCI IO registers with readq/writeq.  I am not entirely sure 
if that limitation comes from the VL805 USB host controller or from the
BCM2711 PCI Express Root Complex, or if it's a matter of some missing 
configuration steps for one of these devices.
In Linux kernel quad word accesses for 64-bit xHCI registers are never
used, the best I could come up with so far is a Kconfig option which 
allows to disable readq/writeq for selected target.  Any suggestions 
on how to better solve this are appreciated.

This patch series is based on v2020.04 tag.

Regards,
Sylwester


Marek Szyprowski (4):
  rpi4: shorten a mapping for the DRAM
  rpi4: add a mapping for the PCIe XHCI controller MMIO registers (ARM
    64bit)
  rpi4: add a mapping for the PCIe XHCI controller MMIO registers (ARM
    32bit)
  config: Enable support for the XHCI controller on RPI4 board

Sylwester Nawrocki (5):
  usb: xhci: Add missing cache flush in the scratchpad array
    initialization
  pci: Move some PCIe register offset definitions to a common header
  usb: xhci: Allow accessing 64-bit registers with DWORD accesses only
  pci: Add some PCI Express capability register offset definitions
  pci: Add driver for Broadcom STB PCIe controller

 arch/arm/mach-bcm283x/Kconfig             |   1 +
 arch/arm/mach-bcm283x/include/mach/base.h |   7 +
 arch/arm/mach-bcm283x/init.c              |  72 ++-
 configs/rpi_4_32b_defconfig               |   9 +
 configs/rpi_4_defconfig                   |  10 +
 configs/rpi_arm64_defconfig               |   9 +-
 drivers/pci/Kconfig                       |   5 +
 drivers/pci/Makefile                      |   1 +
 drivers/pci/pci-rcar-gen3.c               |   8 -
 drivers/pci/pcie_brcmstb.c                | 844 ++++++++++++++++++++++++++++++
 drivers/pci/pcie_intel_fpga.c             |   3 -
 drivers/usb/host/Kconfig                  |   7 +
 drivers/usb/host/xhci-mem.c               |   3 +
 include/pci.h                             |  20 +
 include/usb/xhci.h                        |   4 +-
 15 files changed, 985 insertions(+), 18 deletions(-)
 create mode 100644 drivers/pci/pcie_brcmstb.c

-- 
2.7.4

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 1/9] usb: xhci: Add missing cache flush in the scratchpad array initialization
       [not found]   ` <CGME20200421165114eucas1p2baa595b46f7503331ab86163f69b7c0e@eucas1p2.samsung.com>
@ 2020-04-21 16:50     ` Sylwester Nawrocki
  2020-04-22  5:44       ` Bin Meng
  2020-04-22  8:53       ` Nicolas Saenz Julienne
  0 siblings, 2 replies; 36+ messages in thread
From: Sylwester Nawrocki @ 2020-04-21 16:50 UTC (permalink / raw)
  To: u-boot

In current code there is no cache flush after initializing the scratchpad
buffer array with the scratchpad buffer pointers. This leads to a failure
of the "slot enable" command on the rpi4 board (Broadcom STB PCIe
controller + VL805 USB hub) - the very first TRB transfer on the command
ring fails and there is a timeout while waiting for the command completion
event. After adding the missing cache flush everything seems to be working
as expected.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
 drivers/usb/host/xhci-mem.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 93450ee..729bdc3 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -393,6 +393,9 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
 		scratchpad->sp_array[i] = cpu_to_le64(ptr);
 	}
 
+	xhci_flush_cache((uintptr_t)scratchpad->sp_array,
+			 sizeof(u64) * num_sp);
+
 	return 0;
 
 fail_sp3:
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 2/9] pci: Move some PCIe register offset definitions to a common header
       [not found]   ` <CGME20200421165117eucas1p220b0a5f7820c7cf7bae20dc693584ad4@eucas1p2.samsung.com>
@ 2020-04-21 16:50     ` Sylwester Nawrocki
  2020-04-22  5:51       ` Bin Meng
  0 siblings, 1 reply; 36+ messages in thread
From: Sylwester Nawrocki @ 2020-04-21 16:50 UTC (permalink / raw)
  To: u-boot

Some PCI Express register offsets are currently defined in multiple
drivers, move them to a common header to avoid re-definitions and
as a pre-requisite for adding new PCIe driver.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
 drivers/pci/pci-rcar-gen3.c   |  8 --------
 drivers/pci/pcie_intel_fpga.c |  3 ---
 include/pci.h                 | 13 +++++++++++++
 3 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/pci/pci-rcar-gen3.c b/drivers/pci/pci-rcar-gen3.c
index 30eff67..393f1c9 100644
--- a/drivers/pci/pci-rcar-gen3.c
+++ b/drivers/pci/pci-rcar-gen3.c
@@ -117,14 +117,6 @@
 #define RCAR_PCI_MAX_RESOURCES	4
 #define MAX_NR_INBOUND_MAPS	6
 
-#define PCI_EXP_FLAGS		2		/* Capabilities register */
-#define PCI_EXP_FLAGS_TYPE	0x00f0		/* Device/Port type */
-#define PCI_EXP_TYPE_ROOT_PORT	0x4		/* Root Port */
-#define PCI_EXP_LNKCAP		12		/* Link Capabilities */
-#define PCI_EXP_LNKCAP_DLLLARC	0x00100000	/* Data Link Layer Link Active Reporting Capable */
-#define PCI_EXP_SLTCAP		20		/* Slot Capabilities */
-#define PCI_EXP_SLTCAP_PSN	0xfff80000	/* Physical Slot Number */
-
 enum {
 	RCAR_PCI_ACCESS_READ,
 	RCAR_PCI_ACCESS_WRITE,
diff --git a/drivers/pci/pcie_intel_fpga.c b/drivers/pci/pcie_intel_fpga.c
index 6a9f29c..69363a0 100644
--- a/drivers/pci/pcie_intel_fpga.c
+++ b/drivers/pci/pcie_intel_fpga.c
@@ -65,9 +65,6 @@
 #define IS_ROOT_PORT(pcie, bdf)				\
 		((PCI_BUS(bdf) == pcie->first_busno) ? true : false)
 
-#define PCI_EXP_LNKSTA		18	/* Link Status */
-#define PCI_EXP_LNKSTA_DLLLA	0x2000	/* Data Link Layer Link Active */
-
 /**
  * struct intel_fpga_pcie - Intel FPGA PCIe controller state
  * @bus: Pointer to the PCI bus
diff --git a/include/pci.h b/include/pci.h
index 174ddd4..3d7646d 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -471,11 +471,24 @@
 #define  PCI_EA_FIELD_MASK	0xfffffffc	/* For Base & Max Offset */
 
 /* PCI Express capabilities */
+#define PCI_EXP_FLAGS		2	/* Capabilities register */
+#define PCI_EXP_FLAGS_TYPE	0x00f0	/* Device/Port type */
+#define  PCI_EXP_TYPE_ROOT_PORT 0x4	/* Root Port */
+
 #define PCI_EXP_DEVCAP		4	/* Device capabilities */
 #define  PCI_EXP_DEVCAP_FLR     0x10000000 /* Function Level Reset */
 #define PCI_EXP_DEVCTL		8	/* Device Control */
 #define  PCI_EXP_DEVCTL_BCR_FLR 0x8000  /* Bridge Configuration Retry / FLR */
 
+#define PCI_EXP_LNKCAP		12	/* Link Capabilities */
+#define  PCI_EXP_LNKCAP_DLLLARC	0x00100000 /* Data Link Layer Link Active Reporting Capable */
+
+#define PCI_EXP_LNKSTA		18	/* Link Status */
+#define  PCI_EXP_LNKSTA_DLLLA	0x2000	/* Data Link Layer Link Active */
+
+#define PCI_EXP_SLTCAP		20	/* Slot Capabilities */
+#define  PCI_EXP_SLTCAP_PSN	0xfff80000 /* Physical Slot Number */
+
 /* Include the ID list */
 
 #include <pci_ids.h>
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 3/9] rpi4: shorten a mapping for the DRAM
       [not found]   ` <CGME20200421165118eucas1p1dc542f61cefcf53cdb1f17cc59baee5f@eucas1p1.samsung.com>
@ 2020-04-21 16:50     ` Sylwester Nawrocki
  0 siblings, 0 replies; 36+ messages in thread
From: Sylwester Nawrocki @ 2020-04-21 16:50 UTC (permalink / raw)
  To: u-boot

From: Marek Szyprowski <m.szyprowski@samsung.com>

Remove the overlap between DRAM and device's IO area.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 arch/arm/mach-bcm283x/init.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-bcm283x/init.c b/arch/arm/mach-bcm283x/init.c
index 9966d6c..4295356 100644
--- a/arch/arm/mach-bcm283x/init.c
+++ b/arch/arm/mach-bcm283x/init.c
@@ -38,7 +38,7 @@ static struct mm_region bcm2711_mem_map[] = {
 	{
 		.virt = 0x00000000UL,
 		.phys = 0x00000000UL,
-		.size = 0xfe000000UL,
+		.size = 0xfc000000UL,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 			 PTE_BLOCK_INNER_SHARE
 	}, {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 4/9] rpi4: add a mapping for the PCIe XHCI controller MMIO registers (ARM 64bit)
       [not found]   ` <CGME20200421165119eucas1p19a1103b9f6b952bd83086a77df71e837@eucas1p1.samsung.com>
@ 2020-04-21 16:50     ` Sylwester Nawrocki
  2020-04-22  9:46       ` Nicolas Saenz Julienne
  0 siblings, 1 reply; 36+ messages in thread
From: Sylwester Nawrocki @ 2020-04-21 16:50 UTC (permalink / raw)
  To: u-boot

From: Marek Szyprowski <m.szyprowski@samsung.com>

Create a non-cacheable mapping for the 0x600000000 physical memory region,
where MMIO registers for the PCIe XHCI controller are instantiated by the
PCIe bridge.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 arch/arm/mach-bcm283x/init.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-bcm283x/init.c b/arch/arm/mach-bcm283x/init.c
index 4295356..6a748da 100644
--- a/arch/arm/mach-bcm283x/init.c
+++ b/arch/arm/mach-bcm283x/init.c
@@ -11,10 +11,15 @@
 #include <dm/device.h>
 #include <fdt_support.h>
 
+#define BCM2711_RPI4_PCIE_XHCI_MMIO_PHYS	0x600000000UL
+#define BCM2711_RPI4_PCIE_XHCI_MMIO_SIZE	0x800000UL
+
 #ifdef CONFIG_ARM64
 #include <asm/armv8/mmu.h>
 
-static struct mm_region bcm283x_mem_map[] = {
+#define MAX_MAP_MAX_ENTRIES (4)
+
+static struct mm_region bcm283x_mem_map[MAX_MAP_MAX_ENTRIES] = {
 	{
 		.virt = 0x00000000UL,
 		.phys = 0x00000000UL,
@@ -34,7 +39,7 @@ static struct mm_region bcm283x_mem_map[] = {
 	}
 };
 
-static struct mm_region bcm2711_mem_map[] = {
+static struct mm_region bcm2711_mem_map[MAX_MAP_MAX_ENTRIES] = {
 	{
 		.virt = 0x00000000UL,
 		.phys = 0x00000000UL,
@@ -49,6 +54,13 @@ static struct mm_region bcm2711_mem_map[] = {
 			 PTE_BLOCK_NON_SHARE |
 			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
 	}, {
+		.virt = BCM2711_RPI4_PCIE_XHCI_MMIO_PHYS,
+		.phys = BCM2711_RPI4_PCIE_XHCI_MMIO_PHYS,
+		.size = BCM2711_RPI4_PCIE_XHCI_MMIO_SIZE,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
 		/* List terminator */
 		0,
 	}
@@ -71,7 +83,7 @@ static void _rpi_update_mem_map(struct mm_region *pd)
 {
 	int i;
 
-	for (i = 0; i < 2; i++) {
+	for (i = 0; i < MAX_MAP_MAX_ENTRIES; i++) {
 		mem_map[i].virt = pd[i].virt;
 		mem_map[i].phys = pd[i].phys;
 		mem_map[i].size = pd[i].size;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 5/9] rpi4: add a mapping for the PCIe XHCI controller MMIO registers (ARM 32bit)
       [not found]   ` <CGME20200421165123eucas1p171701bd64ed84a9c740331ce87c7ff6c@eucas1p1.samsung.com>
@ 2020-04-21 16:50     ` Sylwester Nawrocki
  0 siblings, 0 replies; 36+ messages in thread
From: Sylwester Nawrocki @ 2020-04-21 16:50 UTC (permalink / raw)
  To: u-boot

From: Marek Szyprowski <m.szyprowski@samsung.com>

Create a non-cacheable mapping for the 0x600000000 physical memory region,
where MMIO registers for the PCIe XHCI controller are instantiated by the
PCIe bridge. Due to 32bit limit in the CPU virtual address space in ARM
32bit mode, this region is mapped at 0xff800000 CPU virtual address.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 arch/arm/mach-bcm283x/Kconfig             |  1 +
 arch/arm/mach-bcm283x/include/mach/base.h |  7 +++++
 arch/arm/mach-bcm283x/init.c              | 52 +++++++++++++++++++++++++++++++
 3 files changed, 60 insertions(+)

diff --git a/arch/arm/mach-bcm283x/Kconfig b/arch/arm/mach-bcm283x/Kconfig
index 00419bf..bcb7f1d 100644
--- a/arch/arm/mach-bcm283x/Kconfig
+++ b/arch/arm/mach-bcm283x/Kconfig
@@ -36,6 +36,7 @@ config BCM2711_32B
 	select BCM2711
 	select ARMV7_LPAE
 	select CPU_V7A
+	select PHYS_64BIT
 
 config BCM2711_64B
 	bool "Broadcom BCM2711 SoC 64-bit support"
diff --git a/arch/arm/mach-bcm283x/include/mach/base.h b/arch/arm/mach-bcm283x/include/mach/base.h
index c4ae398..1d10dc9 100644
--- a/arch/arm/mach-bcm283x/include/mach/base.h
+++ b/arch/arm/mach-bcm283x/include/mach/base.h
@@ -6,6 +6,13 @@
 #ifndef _BCM283x_BASE_H_
 #define _BCM283x_BASE_H_
 
+#include <linux/types.h>
+
 extern unsigned long rpi_bcm283x_base;
 
+#ifdef CONFIG_ARMV7_LPAE
+extern void *rpi4_phys_to_virt(phys_addr_t paddr);
+#define phys_to_virt(x) rpi4_phys_to_virt(x)
+#endif
+
 #endif
diff --git a/arch/arm/mach-bcm283x/init.c b/arch/arm/mach-bcm283x/init.c
index 6a748da..5d0d160 100644
--- a/arch/arm/mach-bcm283x/init.c
+++ b/arch/arm/mach-bcm283x/init.c
@@ -145,6 +145,58 @@ int mach_cpu_init(void)
 }
 
 #ifdef CONFIG_ARMV7_LPAE
+
+#define BCM2711_RPI4_PCIE_XHCI_MMIO_VIRT	0xff800000UL
+
+void *rpi4_phys_to_virt(phys_addr_t paddr)
+{
+	if (paddr >= BCM2711_RPI4_PCIE_XHCI_MMIO_PHYS)
+		paddr = paddr - BCM2711_RPI4_PCIE_XHCI_MMIO_PHYS +
+			BCM2711_RPI4_PCIE_XHCI_MMIO_VIRT;
+	return (void *)(unsigned long)paddr;
+}
+
+static void set_section_phys(unsigned int section, phys_addr_t phys,
+			     enum dcache_option option)
+{
+	u64 *page_table = (u64 *)gd->arch.tlb_addr;
+	/* Need to set the access flag to not fault */
+	u64 value = TTB_SECT_AP | TTB_SECT_AF;
+
+	/* Add the page offset */
+	value |= (phys);
+
+	/* Add caching bits */
+	value |= option;
+
+	/* Set PTE */
+	page_table[section] = value;
+}
+
+static void rpi4_create_pcie_xhci_mapping(void)
+{
+	unsigned sect = BCM2711_RPI4_PCIE_XHCI_MMIO_VIRT >> MMU_SECTION_SHIFT;
+	phys_addr_t phys_addr = BCM2711_RPI4_PCIE_XHCI_MMIO_PHYS;
+	unsigned int size = BCM2711_RPI4_PCIE_XHCI_MMIO_SIZE;
+
+	while (size) {
+		set_section_phys(sect, phys_addr, DCACHE_OFF);
+		sect++;
+		phys_addr += MMU_SECTION_SIZE;
+		size -= MMU_SECTION_SIZE;
+	}
+}
+
+void arm_init_domains(void)
+{
+	/*
+	 * Hijack this function to prepare a mappings for the PCIe MMIO
+	 * region for the XHCI controller on RPi4 board.
+	 * This code is called before enabling the MMU in ARM 32bit mode.
+	 */
+	rpi4_create_pcie_xhci_mapping();
+}
+
 void enable_caches(void)
 {
 	dcache_enable();
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 6/9] usb: xhci: Allow accessing 64-bit registers with DWORD accesses only
       [not found]   ` <CGME20200421165124eucas1p161d4049c0e136fc74ae2b00c2a1b3883@eucas1p1.samsung.com>
@ 2020-04-21 16:50     ` Sylwester Nawrocki
  2020-04-22  6:00       ` Bin Meng
  2020-04-22  8:58       ` Nicolas Saenz Julienne
  0 siblings, 2 replies; 36+ messages in thread
From: Sylwester Nawrocki @ 2020-04-21 16:50 UTC (permalink / raw)
  To: u-boot

This patch adds a Kconfig option which allows accessing 64-bit xHCI
IO registers only with 2 double word accesses rather than using
a single quad word access. There might be HW configurations where
single quad word access doesn't work, even though the CPU is 64-bit.
That seems to be the case on rpi4 board with Broadcom BCM2711 SoC,
where the VL805 USB xHCI hub is connected to the PCIe controller
behind the SCB bridge.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
So far I couldn't come up with anything better to make the xHCI host
controller working on the rpi4 board. For some reason dereferencing
a 64-bit pointer to access 64-bit registers doesn't work there,
might be a limitation of the PCIe bridge behind the SCB. In Linux
always 2 double word accesses are used.
---
 drivers/usb/host/Kconfig | 7 +++++++
 include/usb/xhci.h       | 4 ++--
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 0987ff2..3990b8a 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -15,6 +15,13 @@ config USB_XHCI_HCD
 
 if USB_XHCI_HCD
 
+config XHCI_64BIT_DWORD_ACCESS_ONLY
+	bool "Access xHCI 64-bit registers with double word accesses only"
+	help
+	  Choose this option if your hardware does not support quad word accesses
+	  for registers with 64-bit address pointers.
+	  If unsure, say Y.
+
 config USB_XHCI_DWC3
 	bool "DesignWare USB3 DRD Core Support"
 	help
diff --git a/include/usb/xhci.h b/include/usb/xhci.h
index 6017504..459e76b 100644
--- a/include/usb/xhci.h
+++ b/include/usb/xhci.h
@@ -1111,7 +1111,7 @@ static inline void xhci_writel(uint32_t volatile *regs, const unsigned int val)
  */
 static inline u64 xhci_readq(__le64 volatile *regs)
 {
-#if BITS_PER_LONG == 64
+#if BITS_PER_LONG == 64 && !defined(CONFIG_XHCI_64BIT_DWORD_ACCESS_ONLY)
 	return readq(regs);
 #else
 	__u32 *ptr = (__u32 *)regs;
@@ -1123,7 +1123,7 @@ static inline u64 xhci_readq(__le64 volatile *regs)
 
 static inline void xhci_writeq(__le64 volatile *regs, const u64 val)
 {
-#if BITS_PER_LONG == 64
+#if BITS_PER_LONG == 64 && !defined(CONFIG_XHCI_64BIT_DWORD_ACCESS_ONLY)
 	writeq(val, regs);
 #else
 	__u32 *ptr = (__u32 *)regs;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 7/9] pci: Add some PCI Express capability register offset definitions
       [not found]   ` <CGME20200421165124eucas1p2e7cbc2eea896a682961304de7ff53dc2@eucas1p2.samsung.com>
@ 2020-04-21 16:50     ` Sylwester Nawrocki
  2020-04-22  6:16       ` Bin Meng
  0 siblings, 1 reply; 36+ messages in thread
From: Sylwester Nawrocki @ 2020-04-21 16:50 UTC (permalink / raw)
  To: u-boot

Add PCI Express capability definitions required by the Broadcom STB PCIe
driver.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
 include/pci.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/include/pci.h b/include/pci.h
index 3d7646d..2b25a17 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -481,10 +481,17 @@
 #define  PCI_EXP_DEVCTL_BCR_FLR 0x8000  /* Bridge Configuration Retry / FLR */
 
 #define PCI_EXP_LNKCAP		12	/* Link Capabilities */
+#define  PCI_EXP_LNKCAP_SLS	0x0000000f /* Supported Link Speeds */
+#define  PCI_EXP_LNKCAP_MLW	0x000003f0 /* Maximum Link Width */
 #define  PCI_EXP_LNKCAP_DLLLARC	0x00100000 /* Data Link Layer Link Active Reporting Capable */
 
 #define PCI_EXP_LNKSTA		18	/* Link Status */
+#define  PCI_EXP_LNKSTA_CLS	0x000f	/* Current Link Speed */
+#define  PCI_EXP_LNKSTA_NLW	0x03f0	/* Negotiated Link Width */
+#define  PCI_EXP_LNKSTA_NLW_SHIFT 4	/* start of NLW mask in link status */
+
 #define  PCI_EXP_LNKSTA_DLLLA	0x2000	/* Data Link Layer Link Active */
+#define PCI_EXP_LNKCTL2		48	/* Link Control 2 */
 
 #define PCI_EXP_SLTCAP		20	/* Slot Capabilities */
 #define  PCI_EXP_SLTCAP_PSN	0xfff80000 /* Physical Slot Number */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 8/9] pci: Add driver for Broadcom STB PCIe controller
       [not found]   ` <CGME20200421165125eucas1p1a4cc19f4c58f449375e6d66b19d51e04@eucas1p1.samsung.com>
@ 2020-04-21 16:50     ` Sylwester Nawrocki
  2020-04-22  6:17       ` Bin Meng
  2020-04-22  9:16       ` Nicolas Saenz Julienne
  0 siblings, 2 replies; 36+ messages in thread
From: Sylwester Nawrocki @ 2020-04-21 16:50 UTC (permalink / raw)
  To: u-boot

This patch adds basic driver for the Broadcom STB PCIe host controller.
The code is based on Linux upstream driver (pcie-brcmtsb.c) with MSI
handling removed. The inbound access memory region is not currently
parsed from dma-ranges DT property and is fixed as a 1:1 mapping of
whole RAM.
The patch has been tested on rpi4 board, i.e. on BCM2711 SoC with VL805
USB Host Controller.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
 drivers/pci/Kconfig        |   5 +
 drivers/pci/Makefile       |   1 +
 drivers/pci/pcie_brcmstb.c | 844 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 850 insertions(+)
 create mode 100644 drivers/pci/pcie_brcmstb.c

diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 437cd9a..02dcc57 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -197,4 +197,9 @@ config PCIE_MEDIATEK
 	  Say Y here if you want to enable Gen2 PCIe controller,
 	  which could be found on MT7623 SoC family.
 
+config PCI_BRCMSTB
+	bool "Broadcom STB PCIe controller"
+	depends on DM_PCI
+	help
+	  Say Y here if you want to enable PCI controller support on BCM2711 SoC.
 endif
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index c051ecc..3e53b1f 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -43,3 +43,4 @@ obj-$(CONFIG_PCI_PHYTIUM) += pcie_phytium.o
 obj-$(CONFIG_PCIE_INTEL_FPGA) += pcie_intel_fpga.o
 obj-$(CONFIG_PCI_KEYSTONE) += pcie_dw_ti.o
 obj-$(CONFIG_PCIE_MEDIATEK) += pcie_mediatek.o
+obj-$(CONFIG_PCI_BRCMSTB) += pcie_brcmstb.o
diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c
new file mode 100644
index 0000000..e96e163
--- /dev/null
+++ b/drivers/pci/pcie_brcmstb.c
@@ -0,0 +1,844 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Broadcom STB PCIe controller driver
+ *
+ * Copyright (C) 2020 Samsung Electronics Co., Ltd.
+ * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
+ *
+ * Based on upstream Linux kernel driver:
+ *
+ *  drivers/pci/controller/pcie-brcmstb.c
+ *  Copyright (C) 2009 - 2017 Broadcom
+ */
+
+#include <asm/io.h>
+#include <common.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/of_access.h>
+#include <dm/of.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/log2.h>
+#include <linux/mbus.h>
+#include <pci.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* BRCM_PCIE_CAP_REGS - Offset for the mandatory capability config regs */
+#define BRCM_PCIE_CAP_REGS				0x00ac
+
+/*
+ * 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.
+ */
+#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_MSI_BAR_CONFIG_LO			0x4044
+#define PCIE_MISC_MSI_BAR_CONFIG_HI			0x4048
+#define PCIE_MISC_MSI_DATA_CONFIG			0x404c
+#define PCIE_MISC_EOI_CTRL				0x4060
+#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
+#define PCIE_MSI_INTR2_BASE				0x4500
+
+/*
+ * 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
+
+/* 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 BRCM_NUM_PCIE_OUT_WINS		0x4
+#define BRCM_MAX_SCB			0x4
+
+#define BURST_SIZE_128			0
+
+#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 traffic */
+#define MMIO_ENDIAN			2	/* CPU->PCIe outbound traffic */
+#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,
+	BCM2711,
+};
+
+struct brcm_window {
+	dma_addr_t pci_addr;
+	phys_addr_t phys_addr;
+	dma_addr_t size;
+};
+
+struct brcm_pcie {
+	struct resource		mem;
+	bool			ssc;
+
+	struct device_node	*dn;
+	void __iomem		*base;
+
+	int			num_out_wins;
+	struct brcm_window	out_wins[BRCM_NUM_PCIE_OUT_WINS];
+
+	int			gen;
+	unsigned int		rev;
+
+	const int		*reg_offsets;
+	const int		*reg_field_info;
+	u32			max_burst_size;
+	enum pcie_type		type;
+};
+
+struct pcie_cfg_data {
+	const int		*reg_field_info;
+	const int		*offsets;
+	const u32		max_burst_size;
+	const enum pcie_type	type;
+};
+
+static struct brcm_window dma_ranges[1];
+static int num_dma_ranges;
+
+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_offsets[] = {
+	[RGR1_SW_INIT_1] = 0x9210,
+	[EXT_CFG_INDEX]  = 0x9000,
+	[EXT_CFG_DATA]   = 0x8000,
+};
+
+static const struct pcie_cfg_data generic_cfg = {
+	.reg_field_info	= pcie_reg_field_info,
+	.offsets	= pcie_offsets,
+	.max_burst_size	= BURST_SIZE_128,
+	.type		= GENERIC,
+};
+
+static const struct pcie_cfg_data bcm2711_cfg = {
+	.reg_field_info	= pcie_reg_field_info,
+	.offsets	= pcie_offsets,
+	.max_burst_size	= BURST_SIZE_128,
+	.type		= BCM2711,
+};
+
+/* These macros extract/insert fields to host controller's register set */
+#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)))
+
+#define msleep(a) udelay((a) * 1000)
+
+/*
+ * The roundup_pow_of_two() from log2.h invokes
+ * __roundup_pow_of_two(unsigned long), but we really need
+ * 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-linear values of PCIE_X_MISC_RC_BAR[123]_CONFIG_LO.SIZE
+ */
+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;
+}
+
+/* Configuration space read/write support */
+static int cfg_index(int busnr, int devfn, int reg)
+{
+	return (PCI_DEV(devfn) << PCIE_SLOT_SHIFT)
+		| (PCI_FUNC(devfn) << PCIE_FUNC_SHIFT)
+		| (busnr << PCIE_BUSNUM_SHIFT)
+		| (reg & ~3);
+}
+
+/* The controller is capable of serving in both RC and EP roles */
+static bool brcm_pcie_rc_mode(struct brcm_pcie *pcie)
+{
+	void __iomem *base = pcie->base;
+	u32 val = 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 = 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 int brcm_pcie_config_address(const struct udevice *udev, pci_dev_t bdf,
+				    uint offset, void **paddress)
+{
+	struct brcm_pcie *pcie = dev_get_priv(udev);
+	unsigned int bus = PCI_BUS(bdf);
+	unsigned int dev = PCI_DEV(bdf);
+	int idx;
+
+	if (bus > 0 && !brcm_pcie_link_up(pcie))
+		return -ENODEV;
+
+	/*
+	 * Busses 0 (host PCIe bridge) and 1 (its immediate child)
+	 * are limited to a single device each
+	 */
+	if ((bus == (udev->seq + 1)) && dev > 0)
+		return -ENODEV;
+
+	/* Accesses to the RC go right to the RC registers if PCI device == 0 */
+	if (bus == udev->seq) {
+		if (PCI_DEV(bdf))
+			return -ENODEV;
+
+		*paddress = pcie->base + offset;
+		return 0;
+	}
+
+	/* For devices, write to the config space index register */
+	idx = cfg_index(bus, bdf, 0);
+
+	writel(idx, pcie->base + IDX_ADDR(pcie));
+	*paddress = pcie->base + DATA_ADDR(pcie) + offset;
+
+	return 0;
+}
+
+static int brcm_pcie_read_config(const struct udevice *bus, pci_dev_t bdf,
+				 uint offset, ulong *valuep,
+				 enum pci_size_t size)
+{
+	return pci_generic_mmap_read_config(bus, brcm_pcie_config_address,
+					    bdf, offset, valuep, size);
+}
+
+static int brcm_pcie_write_config(struct udevice *bus, pci_dev_t bdf,
+				  uint offset, ulong value,
+				  enum pci_size_t size)
+{
+	return pci_generic_mmap_write_config(bus, brcm_pcie_config_address,
+					     bdf, offset, value, size);
+}
+
+static void wr_fld(void __iomem *p, u32 mask, int shift, u32 val)
+{
+	u32 reg = readl(p);
+
+	reg = (reg & ~mask) | ((val << shift) & mask);
+	writel(reg, p);
+}
+
+static void wr_fld_rb(void __iomem *p, u32 mask, int shift, u32 val)
+{
+	wr_fld(p, mask, shift, val);
+	(void)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 "???";
+}
+
+static inline void brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie,
+						unsigned int val)
+{
+	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];
+
+	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 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;
+
+	writel(mdio_form_pkt(port, regad, MDIO_CMD_READ),
+	       base + PCIE_RC_DL_MDIO_ADDR);
+	readl(base + PCIE_RC_DL_MDIO_ADDR);
+
+	data = readl(base + PCIE_RC_DL_MDIO_RD_DATA);
+	for (tries = 0; !MDIO_RD_DONE(data) && tries < 10; tries++) {
+		udelay(10);
+		data = 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;
+
+	writel(mdio_form_pkt(port, regad, MDIO_CMD_WRITE),
+	       base + PCIE_RC_DL_MDIO_ADDR);
+	readl(base + PCIE_RC_DL_MDIO_ADDR);
+	writel(MDIO_DATA_DONE_MASK | wrdata,
+	       base + PCIE_RC_DL_MDIO_WR_DATA);
+
+	data = readl(base + PCIE_RC_DL_MDIO_WR_DATA);
+	for (tries = 0; !MDIO_WT_DONE(data) && tries < 10; tries++) {
+		udelay(10);
+		data = readl(base + PCIE_RC_DL_MDIO_WR_DATA);
+	}
+
+	return MDIO_WT_DONE(data) ? 0 : -EIO;
+}
+
+/*
+ * Configures device for Spread Spectrum Clocking (SSC) mode; negative
+ * return value indicates error.
+ */
+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;
+
+	udelay(1500);
+	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 = readl(base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP);
+	u16 lnkctl2 = readw(base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCTL2);
+
+	lnkcap = (lnkcap & ~PCI_EXP_LNKCAP_SLS) | gen;
+	writel(lnkcap, base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP);
+
+	lnkctl2 = (lnkctl2 & ~0xf) | gen;
+	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 phys_addr,
+				       dma_addr_t pcie_addr, dma_addr_t size)
+{
+	void __iomem *base = pcie->base;
+	phys_addr_t phys_addr_mb, limit_addr_mb;
+	u32 tmp;
+
+	/* Set the base of the pcie_addr window */
+	writel(lower_32_bits(pcie_addr) + MMIO_ENDIAN,
+	       base + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO + (win * 8));
+	writel(upper_32_bits(pcie_addr),
+	       base + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI + (win * 8));
+
+	phys_addr_mb = phys_addr >> 20;
+	limit_addr_mb = (phys_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, phys_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)(phys_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);
+	}
+}
+
+static int brcm_pcie_setup(struct brcm_pcie *pcie)
+{
+	phys_addr_t scb_size[BRCM_MAX_SCB] = {0};
+	void __iomem *base = pcie->base;
+	unsigned int scb_size_val;
+	u64 rc_bar2_offset, rc_bar2_size;
+	u64 total_mem_size = 0;
+	int i, j, ret, limit, num_memc;
+	u16 nlw, cls, lnksta;
+	bool ssc_good = false;
+	u32 tmp;
+
+	/* Reset the bridge */
+	brcm_pcie_bridge_sw_init_set(pcie, 1);
+
+	/*
+	 * Ensure that the fundamental reset is asserted, except for 7278,
+	 * which fails if we do this.
+	 */
+	if (pcie->type != BCM7278)
+		brcm_pcie_perst_set(pcie, 1);
+
+	udelay(150);
+
+	/* Take the bridge out of reset */
+	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 */
+	udelay(150);
+
+	/* Grab the PCIe hw revision number */
+	tmp = 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);
+	tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, MAX_BURST_SIZE,
+			   pcie->max_burst_size);
+	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).
+	 *
+	 * 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 must be a power of two.  Further, the MSI
+	 * target address must NOT be placed inside this region, as the
+	 * decoding logic will consider its address to be inbound memory
+	 * traffic.  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.
+	 */
+
+	if (num_dma_ranges) {
+		/*
+		 * Use the base address and size(s) provided in the dma-ranges
+		 * property.
+		 */
+		for (i = 0; i < num_dma_ranges; i++)
+			scb_size[i] = roundup_pow_of_two_64(dma_ranges[i].size);
+
+		num_memc = num_dma_ranges;
+		rc_bar2_offset = dma_ranges[0].pci_addr;
+	} else {
+		return -EINVAL;
+	}
+
+	for (i = 0; i < num_memc; i++)
+		total_mem_size += scb_size[i];
+
+	rc_bar2_size = roundup_pow_of_two_64(total_mem_size);
+
+	/* Verify the alignment is correct */
+	if (rc_bar2_offset & (rc_bar2_size - 1)) {
+		printf("PCIe BRCM: inbound window is misaligned\n");
+		return -EINVAL;
+	}
+
+	tmp = lower_32_bits(rc_bar2_offset);
+	tmp = INSERT_FIELD(tmp, PCIE_MISC_RC_BAR2_CONFIG_LO, SIZE,
+			   encode_ibar_size(rc_bar2_size));
+	writel(tmp, base + PCIE_MISC_RC_BAR2_CONFIG_LO);
+	writel(upper_32_bits(rc_bar2_offset),
+	       base + PCIE_MISC_RC_BAR2_CONFIG_HI);
+
+	scb_size_val = scb_size[0]
+		? ilog2(scb_size[0]) - 15 : 0xf; /* 0xf is 1GB */
+	WR_FLD(base, PCIE_MISC_MISC_CTRL, SCB0_SIZE, scb_size_val);
+
+	if (num_memc > 1) {
+		scb_size_val = scb_size[1]
+			? ilog2(scb_size[1]) - 15 : 0xf; /* 0xf is 1GB */
+		WR_FLD(base, PCIE_MISC_MISC_CTRL, SCB1_SIZE, scb_size_val);
+	}
+
+	if (num_memc > 2) {
+		scb_size_val = scb_size[2]
+			? ilog2(scb_size[2]) - 15 : 0xf; /* 0xf is 1GB */
+		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);
+
+	/* Clear any interrupts we find on boot */
+	writel(0xffffffff, base + PCIE_INTR2_CPU_BASE + CLR);
+	(void)readl(base + PCIE_INTR2_CPU_BASE + CLR);
+
+	/* Mask all interrupts since we are not handling any yet */
+	writel(0xffffffff, base + PCIE_INTR2_CPU_BASE + MASK_SET);
+	(void)readl(base + PCIE_INTR2_CPU_BASE + MASK_SET);
+
+	if (pcie->gen)
+		set_gen(base, pcie->gen);
+
+	/* Unassert the fundamental reset */
+	brcm_pcie_perst_set(pcie, 0);
+
+	/* Give the RC/EP time to wake up, before trying to configure RC. */
+	limit = 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)) {
+		printf("PCIe BRCM: link down\n");
+		return -ENODEV;
+	}
+
+	if (!brcm_pcie_rc_mode(pcie)) {
+		printf("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].phys_addr,
+					   pcie->out_wins[i].pci_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
+			printf("PCIe BRCM: failed attempt to enter ssc mode\n");
+	}
+
+	lnksta = 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;
+
+	printf("PCIe BRCM: 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 const struct udevice_id brcm_pcie_ids[] = {
+	{ .compatible = "brcm,bcm7445-pcie", .data = (ulong)&generic_cfg },
+	{ .compatible = "brcm,bcm2711-pcie", .data = (ulong)&bcm2711_cfg },
+	{ }
+};
+
+static int brcm_pcie_probe(struct udevice *dev)
+{
+	struct udevice *ctlr = pci_get_controller(dev);
+	struct pci_controller *hose = dev_get_uclass_priv(ctlr);
+	struct brcm_pcie *pcie = dev_get_priv(dev);
+	struct pcie_cfg_data *data = (struct pcie_cfg_data *)dev_get_driver_data(dev);
+	ofnode dn = dev_ofnode(dev);
+	u32 max_link_speed;
+	int i;
+
+	if (hose->region_count < 2) {
+		pr_err("PCIe BRCM: Missing PCI regions definition");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < hose->region_count; i++) {
+		if (hose->regions[i].flags == PCI_REGION_SYS_MEMORY)
+			continue;
+
+		pcie->out_wins[i].phys_addr = hose->regions[i].phys_start;
+		pcie->out_wins[i].pci_addr = hose->regions[i].bus_start;
+		pcie->out_wins[i].size = hose->regions[i].size;
+		pcie->num_out_wins++;
+	}
+
+	/* TODO: Parse inbound access mapping from dma-ranges DT property */
+	num_dma_ranges = 1;
+	for (i = 0; i < hose->region_count; i++) {
+		if (hose->regions[i].flags != PCI_REGION_SYS_MEMORY)
+			continue;
+
+		dma_ranges[0].pci_addr = hose->regions[i].bus_start;
+		dma_ranges[0].phys_addr = hose->regions[i].phys_start;
+		dma_ranges[0].size = hose->regions[i].size;
+		break;
+	}
+
+	pcie->reg_offsets = data->offsets;
+	pcie->reg_field_info = data->reg_field_info;
+	pcie->max_burst_size = data->max_burst_size;
+	pcie->type = data->type;
+
+	if (ofnode_read_u32(dn, "max-link-speed", &max_link_speed) ||
+	    max_link_speed > 4)
+		pcie->gen = 0;
+	else
+		pcie->gen = max_link_speed;
+
+	pcie->ssc = ofnode_read_bool(dn, "brcm,enable-ssc");
+
+	return brcm_pcie_setup(pcie);
+}
+
+static int brcm_pcie_ofdata_to_platdata(struct udevice *dev)
+{
+	struct brcm_pcie *pcie = dev_get_priv(dev);
+
+	/* Get the controller base address */
+	pcie->base = dev_read_addr_ptr(dev);
+	if (!pcie->base)
+		return -EINVAL;
+
+	return 0;
+}
+
+static const struct dm_pci_ops brcm_pcie_ops = {
+	.read_config	= brcm_pcie_read_config,
+	.write_config	= brcm_pcie_write_config,
+};
+
+U_BOOT_DRIVER(pcie_brcm_base) = {
+	.name			= "pcie_brcm",
+	.id			= UCLASS_PCI,
+	.ops			= &brcm_pcie_ops,
+	.of_match		= brcm_pcie_ids,
+	.probe			= brcm_pcie_probe,
+	.ofdata_to_platdata	= brcm_pcie_ofdata_to_platdata,
+	.priv_auto_alloc_size	= sizeof(struct brcm_pcie),
+};
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 9/9] config: Enable support for the XHCI controller on RPI4 board
       [not found]   ` <CGME20200421165125eucas1p12d7451082887a52073ba795aa0ee398a@eucas1p1.samsung.com>
@ 2020-04-21 16:50     ` Sylwester Nawrocki
  2020-04-22 10:44       ` Nicolas Saenz Julienne
  0 siblings, 1 reply; 36+ messages in thread
From: Sylwester Nawrocki @ 2020-04-21 16:50 UTC (permalink / raw)
  To: u-boot

From: Marek Szyprowski <m.szyprowski@samsung.com>

This requires enabling BRCMSTB PCIe and XHCI_PCI drivers as well as PCI
and USB commands. To get it working one has to call the following commands:
"pci enum; usb start;", thus such commands have been added to the default
"preboot" environment variable. One has to update his environment if it is
already configured to get this feature working out of the box.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 configs/rpi_4_32b_defconfig |  9 +++++++++
 configs/rpi_4_defconfig     | 10 ++++++++++
 configs/rpi_arm64_defconfig |  9 ++++++++-
 3 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/configs/rpi_4_32b_defconfig b/configs/rpi_4_32b_defconfig
index 72cda5d..0dd763f 100644
--- a/configs/rpi_4_32b_defconfig
+++ b/configs/rpi_4_32b_defconfig
@@ -8,6 +8,8 @@ CONFIG_NR_DRAM_BANKS=2
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
+CONFIG_USE_PREBOOT=y
+CONFIG_PREBOOT="pci enum; usb start;"
 CONFIG_MISC_INIT_R=y
 # CONFIG_DISPLAY_CPUINFO is not set
 # CONFIG_DISPLAY_BOARDINFO is not set
@@ -15,6 +17,8 @@ CONFIG_SYS_PROMPT="U-Boot> "
 CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_MMC=y
+CONFIG_CMD_PCI=y
+CONFIG_CMD_USB=y
 CONFIG_CMD_FS_UUID=y
 CONFIG_OF_BOARD=y
 CONFIG_ENV_FAT_INTERFACE="mmc"
@@ -28,12 +32,17 @@ CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_BCM2835=y
 CONFIG_DM_ETH=y
 CONFIG_BCMGENET=y
+CONFIG_PCI=y
+CONFIG_DM_PCI=y
+CONFIG_PCI_BRCMSTB=y
 CONFIG_PINCTRL=y
 # CONFIG_PINCTRL_GENERIC is not set
 # CONFIG_REQUIRE_SERIAL_CONSOLE is not set
 CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_DM_USB_GADGET=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_PCI=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="FSL"
 CONFIG_USB_GADGET_VENDOR_NUM=0x0525
diff --git a/configs/rpi_4_defconfig b/configs/rpi_4_defconfig
index 6d148da..f80e5da 100644
--- a/configs/rpi_4_defconfig
+++ b/configs/rpi_4_defconfig
@@ -8,6 +8,8 @@ CONFIG_NR_DRAM_BANKS=2
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
+CONFIG_USE_PREBOOT=y
+CONFIG_PREBOOT="pci enum; usb start;"
 CONFIG_MISC_INIT_R=y
 # CONFIG_DISPLAY_CPUINFO is not set
 # CONFIG_DISPLAY_BOARDINFO is not set
@@ -15,6 +17,8 @@ CONFIG_SYS_PROMPT="U-Boot> "
 CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_MMC=y
+CONFIG_CMD_PCI=y
+CONFIG_CMD_USB=y
 CONFIG_CMD_FS_UUID=y
 CONFIG_OF_BOARD=y
 CONFIG_ENV_FAT_INTERFACE="mmc"
@@ -28,12 +32,18 @@ CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_BCM2835=y
 CONFIG_DM_ETH=y
 CONFIG_BCMGENET=y
+CONFIG_PCI=y
+CONFIG_DM_PCI=y
+CONFIG_PCI_BRCMSTB=y
 CONFIG_PINCTRL=y
 # CONFIG_PINCTRL_GENERIC is not set
 # CONFIG_REQUIRE_SERIAL_CONSOLE is not set
 CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_DM_USB_GADGET=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_XHCI_64BIT_DWORD_ACCESS_ONLY=y
+CONFIG_USB_XHCI_PCI=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="FSL"
 CONFIG_USB_GADGET_VENDOR_NUM=0x0525
diff --git a/configs/rpi_arm64_defconfig b/configs/rpi_arm64_defconfig
index fea86be..926dfc3 100644
--- a/configs/rpi_arm64_defconfig
+++ b/configs/rpi_arm64_defconfig
@@ -7,13 +7,14 @@ CONFIG_NR_DRAM_BANKS=2
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_USE_PREBOOT=y
-CONFIG_PREBOOT="usb start"
+CONFIG_PREBOOT="pci enum; usb start;"
 CONFIG_MISC_INIT_R=y
 # CONFIG_DISPLAY_CPUINFO is not set
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_SYS_PROMPT="U-Boot> "
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_MMC=y
+CONFIG_CMD_PCI=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_FS_UUID=y
 CONFIG_OF_BOARD=y
@@ -26,11 +27,17 @@ CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_BCM2835=y
 CONFIG_DM_ETH=y
 CONFIG_BCMGENET=y
+CONFIG_PCI=y
+CONFIG_DM_PCI=y
+CONFIG_PCI_BRCMSTB=y
 CONFIG_PINCTRL=y
 # CONFIG_PINCTRL_GENERIC is not set
 # CONFIG_REQUIRE_SERIAL_CONSOLE is not set
 CONFIG_USB=y
 CONFIG_DM_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_XHCI_64BIT_DWORD_ACCESS_ONLY=y
+CONFIG_USB_XHCI_PCI=y
 CONFIG_USB_DWC2=y
 CONFIG_USB_KEYBOARD=y
 CONFIG_USB_HOST_ETHER=y
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 1/9] usb: xhci: Add missing cache flush in the scratchpad array initialization
  2020-04-21 16:50     ` [RFC PATCH 1/9] usb: xhci: Add missing cache flush in the scratchpad array initialization Sylwester Nawrocki
@ 2020-04-22  5:44       ` Bin Meng
  2020-04-22  8:53       ` Nicolas Saenz Julienne
  1 sibling, 0 replies; 36+ messages in thread
From: Bin Meng @ 2020-04-22  5:44 UTC (permalink / raw)
  To: u-boot

On Wed, Apr 22, 2020 at 12:51 AM Sylwester Nawrocki
<s.nawrocki@samsung.com> wrote:
>
> In current code there is no cache flush after initializing the scratchpad
> buffer array with the scratchpad buffer pointers. This leads to a failure
> of the "slot enable" command on the rpi4 board (Broadcom STB PCIe
> controller + VL805 USB hub) - the very first TRB transfer on the command
> ring fails and there is a timeout while waiting for the command completion
> event. After adding the missing cache flush everything seems to be working
> as expected.
>
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> ---
>  drivers/usb/host/xhci-mem.c | 3 +++
>  1 file changed, 3 insertions(+)
>

Good catch!

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 2/9] pci: Move some PCIe register offset definitions to a common header
  2020-04-21 16:50     ` [RFC PATCH 2/9] pci: Move some PCIe register offset definitions to a common header Sylwester Nawrocki
@ 2020-04-22  5:51       ` Bin Meng
  0 siblings, 0 replies; 36+ messages in thread
From: Bin Meng @ 2020-04-22  5:51 UTC (permalink / raw)
  To: u-boot

On Wed, Apr 22, 2020 at 12:51 AM Sylwester Nawrocki
<s.nawrocki@samsung.com> wrote:
>
> Some PCI Express register offsets are currently defined in multiple
> drivers, move them to a common header to avoid re-definitions and
> as a pre-requisite for adding new PCIe driver.
>
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> ---
>  drivers/pci/pci-rcar-gen3.c   |  8 --------
>  drivers/pci/pcie_intel_fpga.c |  3 ---
>  include/pci.h                 | 13 +++++++++++++
>  3 files changed, 13 insertions(+), 11 deletions(-)
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 6/9] usb: xhci: Allow accessing 64-bit registers with DWORD accesses only
  2020-04-21 16:50     ` [RFC PATCH 6/9] usb: xhci: Allow accessing 64-bit registers with DWORD accesses only Sylwester Nawrocki
@ 2020-04-22  6:00       ` Bin Meng
  2020-04-22 13:37         ` Sylwester Nawrocki
  2020-04-22  8:58       ` Nicolas Saenz Julienne
  1 sibling, 1 reply; 36+ messages in thread
From: Bin Meng @ 2020-04-22  6:00 UTC (permalink / raw)
  To: u-boot

Hi Sylwester,

On Wed, Apr 22, 2020 at 12:51 AM Sylwester Nawrocki
<s.nawrocki@samsung.com> wrote:
>
> This patch adds a Kconfig option which allows accessing 64-bit xHCI
> IO registers only with 2 double word accesses rather than using
> a single quad word access. There might be HW configurations where
> single quad word access doesn't work, even though the CPU is 64-bit.
> That seems to be the case on rpi4 board with Broadcom BCM2711 SoC,
> where the VL805 USB xHCI hub is connected to the PCIe controller
> behind the SCB bridge.
>
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> ---
> So far I couldn't come up with anything better to make the xHCI host
> controller working on the rpi4 board. For some reason dereferencing
> a 64-bit pointer to access 64-bit registers doesn't work there,
> might be a limitation of the PCIe bridge behind the SCB. In Linux
> always 2 double word accesses are used.

If Linux always uses 2 double word accesses, let's simply do the same
in U-Boot by removing the readq/writeq.

> ---
>  drivers/usb/host/Kconfig | 7 +++++++
>  include/usb/xhci.h       | 4 ++--
>  2 files changed, 9 insertions(+), 2 deletions(-)
>

Regards,
Bin

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 7/9] pci: Add some PCI Express capability register offset definitions
  2020-04-21 16:50     ` [RFC PATCH 7/9] pci: Add some PCI Express capability register offset definitions Sylwester Nawrocki
@ 2020-04-22  6:16       ` Bin Meng
  2020-04-22 13:40         ` Sylwester Nawrocki
  0 siblings, 1 reply; 36+ messages in thread
From: Bin Meng @ 2020-04-22  6:16 UTC (permalink / raw)
  To: u-boot

Hi Sylwester,

On Wed, Apr 22, 2020 at 12:51 AM Sylwester Nawrocki
<s.nawrocki@samsung.com> wrote:
>
> Add PCI Express capability definitions required by the Broadcom STB PCIe
> driver.
>
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> ---
>  include/pci.h | 7 +++++++
>  1 file changed, 7 insertions(+)
>
> diff --git a/include/pci.h b/include/pci.h
> index 3d7646d..2b25a17 100644
> --- a/include/pci.h
> +++ b/include/pci.h
> @@ -481,10 +481,17 @@
>  #define  PCI_EXP_DEVCTL_BCR_FLR 0x8000  /* Bridge Configuration Retry / FLR */
>
>  #define PCI_EXP_LNKCAP         12      /* Link Capabilities */
> +#define  PCI_EXP_LNKCAP_SLS    0x0000000f /* Supported Link Speeds */
> +#define  PCI_EXP_LNKCAP_MLW    0x000003f0 /* Maximum Link Width */
>  #define  PCI_EXP_LNKCAP_DLLLARC        0x00100000 /* Data Link Layer Link Active Reporting Capable */
>
>  #define PCI_EXP_LNKSTA         18      /* Link Status */
> +#define  PCI_EXP_LNKSTA_CLS    0x000f  /* Current Link Speed */
> +#define  PCI_EXP_LNKSTA_NLW    0x03f0  /* Negotiated Link Width */
> +#define  PCI_EXP_LNKSTA_NLW_SHIFT 4    /* start of NLW mask in link status */
> +
>  #define  PCI_EXP_LNKSTA_DLLLA  0x2000  /* Data Link Layer Link Active */
> +#define PCI_EXP_LNKCTL2                48      /* Link Control 2 */

Please put PCI_EXP_LNKCTL2 after PCI_EXP_SLTCAP (sorted in order)

>
>  #define PCI_EXP_SLTCAP         20      /* Slot Capabilities */
>  #define  PCI_EXP_SLTCAP_PSN    0xfff80000 /* Physical Slot Number */
> --

Other than that,
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

Regards,
Bin

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 8/9] pci: Add driver for Broadcom STB PCIe controller
  2020-04-21 16:50     ` [RFC PATCH 8/9] pci: Add driver for Broadcom STB PCIe controller Sylwester Nawrocki
@ 2020-04-22  6:17       ` Bin Meng
  2020-04-22  9:16       ` Nicolas Saenz Julienne
  1 sibling, 0 replies; 36+ messages in thread
From: Bin Meng @ 2020-04-22  6:17 UTC (permalink / raw)
  To: u-boot

Hi Sylwester,

On Wed, Apr 22, 2020 at 12:51 AM Sylwester Nawrocki
<s.nawrocki@samsung.com> wrote:
>
> This patch adds basic driver for the Broadcom STB PCIe host controller.
> The code is based on Linux upstream driver (pcie-brcmtsb.c) with MSI

pcie-brcmstb.c

> handling removed. The inbound access memory region is not currently
> parsed from dma-ranges DT property and is fixed as a 1:1 mapping of
> whole RAM.
> The patch has been tested on rpi4 board, i.e. on BCM2711 SoC with VL805
> USB Host Controller.
>
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> ---
>  drivers/pci/Kconfig        |   5 +
>  drivers/pci/Makefile       |   1 +
>  drivers/pci/pcie_brcmstb.c | 844 +++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 850 insertions(+)
>  create mode 100644 drivers/pci/pcie_brcmstb.c
>
> diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
> index 437cd9a..02dcc57 100644
> --- a/drivers/pci/Kconfig
> +++ b/drivers/pci/Kconfig
> @@ -197,4 +197,9 @@ config PCIE_MEDIATEK
>           Say Y here if you want to enable Gen2 PCIe controller,
>           which could be found on MT7623 SoC family.
>
> +config PCI_BRCMSTB
> +       bool "Broadcom STB PCIe controller"
> +       depends on DM_PCI
> +       help
> +         Say Y here if you want to enable PCI controller support on BCM2711 SoC.
>  endif
> diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
> index c051ecc..3e53b1f 100644
> --- a/drivers/pci/Makefile
> +++ b/drivers/pci/Makefile
> @@ -43,3 +43,4 @@ obj-$(CONFIG_PCI_PHYTIUM) += pcie_phytium.o
>  obj-$(CONFIG_PCIE_INTEL_FPGA) += pcie_intel_fpga.o
>  obj-$(CONFIG_PCI_KEYSTONE) += pcie_dw_ti.o
>  obj-$(CONFIG_PCIE_MEDIATEK) += pcie_mediatek.o
> +obj-$(CONFIG_PCI_BRCMSTB) += pcie_brcmstb.o
> diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c
> new file mode 100644
> index 0000000..e96e163
> --- /dev/null
> +++ b/drivers/pci/pcie_brcmstb.c
> @@ -0,0 +1,844 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Broadcom STB PCIe controller driver
> + *
> + * Copyright (C) 2020 Samsung Electronics Co., Ltd.
> + * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
> + *
> + * Based on upstream Linux kernel driver:
> + *
> + *  drivers/pci/controller/pcie-brcmstb.c
> + *  Copyright (C) 2009 - 2017 Broadcom
> + */
> +
> +#include <asm/io.h>
> +#include <common.h>
> +#include <dm.h>
> +#include <dm/device-internal.h>
> +#include <dm/lists.h>
> +#include <dm/of_access.h>
> +#include <dm/of.h>
> +#include <linux/errno.h>
> +#include <linux/ioport.h>
> +#include <linux/log2.h>
> +#include <linux/mbus.h>
> +#include <pci.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;

This seems not be used by this driver

> +
> +/* BRCM_PCIE_CAP_REGS - Offset for the mandatory capability config regs */
> +#define BRCM_PCIE_CAP_REGS                             0x00ac
> +
> +/*
> + * 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.
> + */
> +#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_MSI_BAR_CONFIG_LO                    0x4044
> +#define PCIE_MISC_MSI_BAR_CONFIG_HI                    0x4048
> +#define PCIE_MISC_MSI_DATA_CONFIG                      0x404c
> +#define PCIE_MISC_EOI_CTRL                             0x4060
> +#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
> +#define PCIE_MSI_INTR2_BASE                            0x4500
> +
> +/*
> + * 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
> +
> +/* 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 BRCM_NUM_PCIE_OUT_WINS         0x4
> +#define BRCM_MAX_SCB                   0x4
> +
> +#define BURST_SIZE_128                 0
> +
> +#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 traffic */
> +#define MMIO_ENDIAN                    2       /* CPU->PCIe outbound traffic */
> +#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,
> +       BCM2711,
> +};
> +
> +struct brcm_window {
> +       dma_addr_t pci_addr;
> +       phys_addr_t phys_addr;
> +       dma_addr_t size;
> +};
> +
> +struct brcm_pcie {
> +       struct resource         mem;
> +       bool                    ssc;
> +
> +       struct device_node      *dn;
> +       void __iomem            *base;
> +
> +       int                     num_out_wins;
> +       struct brcm_window      out_wins[BRCM_NUM_PCIE_OUT_WINS];
> +
> +       int                     gen;
> +       unsigned int            rev;
> +
> +       const int               *reg_offsets;
> +       const int               *reg_field_info;
> +       u32                     max_burst_size;
> +       enum pcie_type          type;
> +};
> +
> +struct pcie_cfg_data {
> +       const int               *reg_field_info;
> +       const int               *offsets;
> +       const u32               max_burst_size;
> +       const enum pcie_type    type;
> +};
> +
> +static struct brcm_window dma_ranges[1];
> +static int num_dma_ranges;
> +
> +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_offsets[] = {
> +       [RGR1_SW_INIT_1] = 0x9210,
> +       [EXT_CFG_INDEX]  = 0x9000,
> +       [EXT_CFG_DATA]   = 0x8000,
> +};
> +
> +static const struct pcie_cfg_data generic_cfg = {
> +       .reg_field_info = pcie_reg_field_info,
> +       .offsets        = pcie_offsets,
> +       .max_burst_size = BURST_SIZE_128,
> +       .type           = GENERIC,
> +};
> +
> +static const struct pcie_cfg_data bcm2711_cfg = {
> +       .reg_field_info = pcie_reg_field_info,
> +       .offsets        = pcie_offsets,
> +       .max_burst_size = BURST_SIZE_128,
> +       .type           = BCM2711,
> +};
> +
> +/* These macros extract/insert fields to host controller's register set */
> +#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)))
> +
> +#define msleep(a) udelay((a) * 1000)
> +
> +/*
> + * The roundup_pow_of_two() from log2.h invokes
> + * __roundup_pow_of_two(unsigned long), but we really need
> + * 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-linear values of PCIE_X_MISC_RC_BAR[123]_CONFIG_LO.SIZE
> + */
> +int encode_ibar_size(u64 size)

This should be static

> +{
> +       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;
> +}
> +
> +/* Configuration space read/write support */
> +static int cfg_index(int busnr, int devfn, int reg)
> +{
> +       return (PCI_DEV(devfn) << PCIE_SLOT_SHIFT)
> +               | (PCI_FUNC(devfn) << PCIE_FUNC_SHIFT)
> +               | (busnr << PCIE_BUSNUM_SHIFT)
> +               | (reg & ~3);
> +}
> +
> +/* The controller is capable of serving in both RC and EP roles */
> +static bool brcm_pcie_rc_mode(struct brcm_pcie *pcie)
> +{
> +       void __iomem *base = pcie->base;
> +       u32 val = 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 = 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 int brcm_pcie_config_address(const struct udevice *udev, pci_dev_t bdf,
> +                                   uint offset, void **paddress)
> +{
> +       struct brcm_pcie *pcie = dev_get_priv(udev);
> +       unsigned int bus = PCI_BUS(bdf);
> +       unsigned int dev = PCI_DEV(bdf);
> +       int idx;
> +
> +       if (bus > 0 && !brcm_pcie_link_up(pcie))
> +               return -ENODEV;
> +
> +       /*
> +        * Busses 0 (host PCIe bridge) and 1 (its immediate child)
> +        * are limited to a single device each
> +        */
> +       if ((bus == (udev->seq + 1)) && dev > 0)
> +               return -ENODEV;
> +
> +       /* Accesses to the RC go right to the RC registers if PCI device == 0 */
> +       if (bus == udev->seq) {
> +               if (PCI_DEV(bdf))
> +                       return -ENODEV;
> +
> +               *paddress = pcie->base + offset;
> +               return 0;
> +       }
> +
> +       /* For devices, write to the config space index register */
> +       idx = cfg_index(bus, bdf, 0);
> +
> +       writel(idx, pcie->base + IDX_ADDR(pcie));
> +       *paddress = pcie->base + DATA_ADDR(pcie) + offset;
> +
> +       return 0;
> +}
> +
> +static int brcm_pcie_read_config(const struct udevice *bus, pci_dev_t bdf,
> +                                uint offset, ulong *valuep,
> +                                enum pci_size_t size)
> +{
> +       return pci_generic_mmap_read_config(bus, brcm_pcie_config_address,
> +                                           bdf, offset, valuep, size);
> +}
> +
> +static int brcm_pcie_write_config(struct udevice *bus, pci_dev_t bdf,
> +                                 uint offset, ulong value,
> +                                 enum pci_size_t size)
> +{
> +       return pci_generic_mmap_write_config(bus, brcm_pcie_config_address,
> +                                            bdf, offset, value, size);
> +}
> +
> +static void wr_fld(void __iomem *p, u32 mask, int shift, u32 val)
> +{
> +       u32 reg = readl(p);
> +
> +       reg = (reg & ~mask) | ((val << shift) & mask);
> +       writel(reg, p);
> +}
> +
> +static void wr_fld_rb(void __iomem *p, u32 mask, int shift, u32 val)
> +{
> +       wr_fld(p, mask, shift, val);
> +       (void)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 "???";
> +}
> +
> +static inline void brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie,
> +                                               unsigned int val)
> +{
> +       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];
> +
> +       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 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;
> +
> +       writel(mdio_form_pkt(port, regad, MDIO_CMD_READ),
> +              base + PCIE_RC_DL_MDIO_ADDR);
> +       readl(base + PCIE_RC_DL_MDIO_ADDR);
> +
> +       data = readl(base + PCIE_RC_DL_MDIO_RD_DATA);
> +       for (tries = 0; !MDIO_RD_DONE(data) && tries < 10; tries++) {
> +               udelay(10);
> +               data = 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;
> +
> +       writel(mdio_form_pkt(port, regad, MDIO_CMD_WRITE),
> +              base + PCIE_RC_DL_MDIO_ADDR);
> +       readl(base + PCIE_RC_DL_MDIO_ADDR);
> +       writel(MDIO_DATA_DONE_MASK | wrdata,
> +              base + PCIE_RC_DL_MDIO_WR_DATA);
> +
> +       data = readl(base + PCIE_RC_DL_MDIO_WR_DATA);
> +       for (tries = 0; !MDIO_WT_DONE(data) && tries < 10; tries++) {
> +               udelay(10);
> +               data = readl(base + PCIE_RC_DL_MDIO_WR_DATA);
> +       }
> +
> +       return MDIO_WT_DONE(data) ? 0 : -EIO;
> +}
> +
> +/*
> + * Configures device for Spread Spectrum Clocking (SSC) mode; negative
> + * return value indicates error.
> + */
> +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;
> +
> +       udelay(1500);
> +       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 = readl(base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP);
> +       u16 lnkctl2 = readw(base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCTL2);
> +
> +       lnkcap = (lnkcap & ~PCI_EXP_LNKCAP_SLS) | gen;
> +       writel(lnkcap, base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP);
> +
> +       lnkctl2 = (lnkctl2 & ~0xf) | gen;
> +       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 phys_addr,
> +                                      dma_addr_t pcie_addr, dma_addr_t size)
> +{
> +       void __iomem *base = pcie->base;
> +       phys_addr_t phys_addr_mb, limit_addr_mb;
> +       u32 tmp;
> +
> +       /* Set the base of the pcie_addr window */
> +       writel(lower_32_bits(pcie_addr) + MMIO_ENDIAN,
> +              base + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO + (win * 8));
> +       writel(upper_32_bits(pcie_addr),
> +              base + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI + (win * 8));
> +
> +       phys_addr_mb = phys_addr >> 20;
> +       limit_addr_mb = (phys_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, phys_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)(phys_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);
> +       }
> +}
> +
> +static int brcm_pcie_setup(struct brcm_pcie *pcie)
> +{
> +       phys_addr_t scb_size[BRCM_MAX_SCB] = {0};
> +       void __iomem *base = pcie->base;
> +       unsigned int scb_size_val;
> +       u64 rc_bar2_offset, rc_bar2_size;
> +       u64 total_mem_size = 0;
> +       int i, j, ret, limit, num_memc;
> +       u16 nlw, cls, lnksta;
> +       bool ssc_good = false;
> +       u32 tmp;
> +
> +       /* Reset the bridge */
> +       brcm_pcie_bridge_sw_init_set(pcie, 1);
> +
> +       /*
> +        * Ensure that the fundamental reset is asserted, except for 7278,
> +        * which fails if we do this.
> +        */
> +       if (pcie->type != BCM7278)
> +               brcm_pcie_perst_set(pcie, 1);
> +
> +       udelay(150);
> +
> +       /* Take the bridge out of reset */
> +       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 */
> +       udelay(150);
> +
> +       /* Grab the PCIe hw revision number */
> +       tmp = 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);
> +       tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, MAX_BURST_SIZE,
> +                          pcie->max_burst_size);
> +       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).
> +        *
> +        * 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 must be a power of two.  Further, the MSI
> +        * target address must NOT be placed inside this region, as the
> +        * decoding logic will consider its address to be inbound memory
> +        * traffic.  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.
> +        */
> +
> +       if (num_dma_ranges) {
> +               /*
> +                * Use the base address and size(s) provided in the dma-ranges
> +                * property.
> +                */
> +               for (i = 0; i < num_dma_ranges; i++)
> +                       scb_size[i] = roundup_pow_of_two_64(dma_ranges[i].size);
> +
> +               num_memc = num_dma_ranges;
> +               rc_bar2_offset = dma_ranges[0].pci_addr;
> +       } else {
> +               return -EINVAL;
> +       }
> +
> +       for (i = 0; i < num_memc; i++)
> +               total_mem_size += scb_size[i];
> +
> +       rc_bar2_size = roundup_pow_of_two_64(total_mem_size);
> +
> +       /* Verify the alignment is correct */
> +       if (rc_bar2_offset & (rc_bar2_size - 1)) {
> +               printf("PCIe BRCM: inbound window is misaligned\n");
> +               return -EINVAL;
> +       }
> +
> +       tmp = lower_32_bits(rc_bar2_offset);
> +       tmp = INSERT_FIELD(tmp, PCIE_MISC_RC_BAR2_CONFIG_LO, SIZE,
> +                          encode_ibar_size(rc_bar2_size));
> +       writel(tmp, base + PCIE_MISC_RC_BAR2_CONFIG_LO);
> +       writel(upper_32_bits(rc_bar2_offset),
> +              base + PCIE_MISC_RC_BAR2_CONFIG_HI);
> +
> +       scb_size_val = scb_size[0]
> +               ? ilog2(scb_size[0]) - 15 : 0xf; /* 0xf is 1GB */
> +       WR_FLD(base, PCIE_MISC_MISC_CTRL, SCB0_SIZE, scb_size_val);
> +
> +       if (num_memc > 1) {
> +               scb_size_val = scb_size[1]
> +                       ? ilog2(scb_size[1]) - 15 : 0xf; /* 0xf is 1GB */
> +               WR_FLD(base, PCIE_MISC_MISC_CTRL, SCB1_SIZE, scb_size_val);
> +       }
> +
> +       if (num_memc > 2) {
> +               scb_size_val = scb_size[2]
> +                       ? ilog2(scb_size[2]) - 15 : 0xf; /* 0xf is 1GB */
> +               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);
> +
> +       /* Clear any interrupts we find on boot */
> +       writel(0xffffffff, base + PCIE_INTR2_CPU_BASE + CLR);
> +       (void)readl(base + PCIE_INTR2_CPU_BASE + CLR);
> +
> +       /* Mask all interrupts since we are not handling any yet */
> +       writel(0xffffffff, base + PCIE_INTR2_CPU_BASE + MASK_SET);
> +       (void)readl(base + PCIE_INTR2_CPU_BASE + MASK_SET);
> +
> +       if (pcie->gen)
> +               set_gen(base, pcie->gen);
> +
> +       /* Unassert the fundamental reset */
> +       brcm_pcie_perst_set(pcie, 0);
> +
> +       /* Give the RC/EP time to wake up, before trying to configure RC. */
> +       limit = 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)) {
> +               printf("PCIe BRCM: link down\n");
> +               return -ENODEV;
> +       }
> +
> +       if (!brcm_pcie_rc_mode(pcie)) {
> +               printf("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].phys_addr,
> +                                          pcie->out_wins[i].pci_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
> +                       printf("PCIe BRCM: failed attempt to enter ssc mode\n");
> +       }
> +
> +       lnksta = 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;
> +
> +       printf("PCIe BRCM: 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 const struct udevice_id brcm_pcie_ids[] = {
> +       { .compatible = "brcm,bcm7445-pcie", .data = (ulong)&generic_cfg },
> +       { .compatible = "brcm,bcm2711-pcie", .data = (ulong)&bcm2711_cfg },
> +       { }
> +};
> +
> +static int brcm_pcie_probe(struct udevice *dev)
> +{
> +       struct udevice *ctlr = pci_get_controller(dev);
> +       struct pci_controller *hose = dev_get_uclass_priv(ctlr);
> +       struct brcm_pcie *pcie = dev_get_priv(dev);
> +       struct pcie_cfg_data *data = (struct pcie_cfg_data *)dev_get_driver_data(dev);
> +       ofnode dn = dev_ofnode(dev);
> +       u32 max_link_speed;
> +       int i;
> +
> +       if (hose->region_count < 2) {
> +               pr_err("PCIe BRCM: Missing PCI regions definition");
> +               return -EINVAL;
> +       }
> +
> +       for (i = 0; i < hose->region_count; i++) {
> +               if (hose->regions[i].flags == PCI_REGION_SYS_MEMORY)
> +                       continue;
> +
> +               pcie->out_wins[i].phys_addr = hose->regions[i].phys_start;
> +               pcie->out_wins[i].pci_addr = hose->regions[i].bus_start;
> +               pcie->out_wins[i].size = hose->regions[i].size;
> +               pcie->num_out_wins++;
> +       }
> +
> +       /* TODO: Parse inbound access mapping from dma-ranges DT property */
> +       num_dma_ranges = 1;
> +       for (i = 0; i < hose->region_count; i++) {
> +               if (hose->regions[i].flags != PCI_REGION_SYS_MEMORY)
> +                       continue;
> +
> +               dma_ranges[0].pci_addr = hose->regions[i].bus_start;
> +               dma_ranges[0].phys_addr = hose->regions[i].phys_start;
> +               dma_ranges[0].size = hose->regions[i].size;
> +               break;
> +       }
> +
> +       pcie->reg_offsets = data->offsets;
> +       pcie->reg_field_info = data->reg_field_info;
> +       pcie->max_burst_size = data->max_burst_size;
> +       pcie->type = data->type;
> +
> +       if (ofnode_read_u32(dn, "max-link-speed", &max_link_speed) ||
> +           max_link_speed > 4)
> +               pcie->gen = 0;
> +       else
> +               pcie->gen = max_link_speed;
> +
> +       pcie->ssc = ofnode_read_bool(dn, "brcm,enable-ssc");
> +
> +       return brcm_pcie_setup(pcie);
> +}
> +
> +static int brcm_pcie_ofdata_to_platdata(struct udevice *dev)
> +{
> +       struct brcm_pcie *pcie = dev_get_priv(dev);
> +
> +       /* Get the controller base address */
> +       pcie->base = dev_read_addr_ptr(dev);
> +       if (!pcie->base)
> +               return -EINVAL;
> +
> +       return 0;
> +}
> +
> +static const struct dm_pci_ops brcm_pcie_ops = {
> +       .read_config    = brcm_pcie_read_config,
> +       .write_config   = brcm_pcie_write_config,
> +};
> +
> +U_BOOT_DRIVER(pcie_brcm_base) = {
> +       .name                   = "pcie_brcm",
> +       .id                     = UCLASS_PCI,
> +       .ops                    = &brcm_pcie_ops,
> +       .of_match               = brcm_pcie_ids,
> +       .probe                  = brcm_pcie_probe,
> +       .ofdata_to_platdata     = brcm_pcie_ofdata_to_platdata,
> +       .priv_auto_alloc_size   = sizeof(struct brcm_pcie),
> +};
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 1/9] usb: xhci: Add missing cache flush in the scratchpad array initialization
  2020-04-21 16:50     ` [RFC PATCH 1/9] usb: xhci: Add missing cache flush in the scratchpad array initialization Sylwester Nawrocki
  2020-04-22  5:44       ` Bin Meng
@ 2020-04-22  8:53       ` Nicolas Saenz Julienne
  2020-04-22  9:21         ` Bin Meng
  2020-04-22 12:01         ` Sylwester Nawrocki
  1 sibling, 2 replies; 36+ messages in thread
From: Nicolas Saenz Julienne @ 2020-04-22  8:53 UTC (permalink / raw)
  To: u-boot

Hi Sylwester, Marek

On Tue, 2020-04-21 at 18:50 +0200, Sylwester Nawrocki wrote:
> In current code there is no cache flush after initializing the scratchpad
> buffer array with the scratchpad buffer pointers. This leads to a failure
> of the "slot enable" command on the rpi4 board (Broadcom STB PCIe
> controller + VL805 USB hub) - the very first TRB transfer on the command
> ring fails and there is a timeout while waiting for the command completion
> event. After adding the missing cache flush everything seems to be working
> as expected.
> 
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
> ---

I've been trying to get this working on my own and got stuck with this specific
issue. I'm glad you found a solution, it was driving me crazy.

Out of curiosity how did you found the solution?

>  drivers/usb/host/xhci-mem.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
> index 93450ee..729bdc3 100644
> --- a/drivers/usb/host/xhci-mem.c
> +++ b/drivers/usb/host/xhci-mem.c
> @@ -393,6 +393,9 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
>  		scratchpad->sp_array[i] = cpu_to_le64(ptr);
>  	}
>  
> +	xhci_flush_cache((uintptr_t)scratchpad->sp_array,
> +			 sizeof(u64) * num_sp);
> +

Marek, souldn't running 'dcache off; icache off' be equivalent to this (which
didn't do the trick for me)? or am I missing somthing?

Regards,
Nicolas

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: This is a digitally signed message part
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20200422/62601f47/attachment.sig>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 6/9] usb: xhci: Allow accessing 64-bit registers with DWORD accesses only
  2020-04-21 16:50     ` [RFC PATCH 6/9] usb: xhci: Allow accessing 64-bit registers with DWORD accesses only Sylwester Nawrocki
  2020-04-22  6:00       ` Bin Meng
@ 2020-04-22  8:58       ` Nicolas Saenz Julienne
  1 sibling, 0 replies; 36+ messages in thread
From: Nicolas Saenz Julienne @ 2020-04-22  8:58 UTC (permalink / raw)
  To: u-boot

On Tue, 2020-04-21 at 18:50 +0200, Sylwester Nawrocki wrote:
> This patch adds a Kconfig option which allows accessing 64-bit xHCI
> IO registers only with 2 double word accesses rather than using
> a single quad word access. There might be HW configurations where
> single quad word access doesn't work, even though the CPU is 64-bit.
> That seems to be the case on rpi4 board with Broadcom BCM2711 SoC,
> where the VL805 USB xHCI hub is connected to the PCIe controller
> behind the SCB bridge.
> 
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> ---
> So far I couldn't come up with anything better to make the xHCI host
> controller working on the rpi4 board. For some reason dereferencing
> a 64-bit pointer to access 64-bit registers doesn't work there,
> might be a limitation of the PCIe bridge behind the SCB. In Linux
> always 2 double word accesses are used.

Out of curiosity, what are the benefits of using 64bit accesses anyway? I'm
under the impression that 64 bit accesses are not used that much in xHCI
anyway. We could simply default Linux's behavior and save some maintenance
burden.

Regards,
Nicolas

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: This is a digitally signed message part
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20200422/f6d926d7/attachment.sig>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 8/9] pci: Add driver for Broadcom STB PCIe controller
  2020-04-21 16:50     ` [RFC PATCH 8/9] pci: Add driver for Broadcom STB PCIe controller Sylwester Nawrocki
  2020-04-22  6:17       ` Bin Meng
@ 2020-04-22  9:16       ` Nicolas Saenz Julienne
  2020-04-22 16:42         ` Sylwester Nawrocki
  1 sibling, 1 reply; 36+ messages in thread
From: Nicolas Saenz Julienne @ 2020-04-22  9:16 UTC (permalink / raw)
  To: u-boot

Hi Sylwester,

On Tue, 2020-04-21 at 18:50 +0200, Sylwester Nawrocki wrote:
> This patch adds basic driver for the Broadcom STB PCIe host controller.
> The code is based on Linux upstream driver (pcie-brcmtsb.c) with MSI
> handling removed. The inbound access memory region is not currently
> parsed from dma-ranges DT property and is fixed as a 1:1 mapping of
> whole RAM.
> The patch has been tested on rpi4 board, i.e. on BCM2711 SoC with VL805
> USB Host Controller.
> 
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> ---

I see that you based your code on the downstream PCIe driver (the one available
in the Raspberry Pi foundation kernel repos). There's a real upstream version
of it[1], It's properly reviewed and we made a point to remove all non bcm2711
specific stuff from it, as support for other platforms (like bcm7445) isn't
there yet (it depends on supporting multiple dma-ranges in Linux, which we
don't). Also note that the Raspberry Pi foundation is moving towards using this
driver, see for example their rpi-5.6.y branch, and I belive Broadcom is doing
the same.

So I strongly suggest you base this driver on the upstream version. As I was
working towards the same goal as you I already have an implementation for
u-boot myself[2]. Feel free to use that if you find it useful. Ultimately,
whether you base it on my version or the upstream Linux version it's half the
size and easier to follow.

Regards,
Nicolas

[1] 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/pci/controller/pcie-brcmstb.c?h=v5.7-rc2
[2] https://github.com/vianpl/u-boot/commits/brcm-pcie

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: This is a digitally signed message part
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20200422/d53649cb/attachment.sig>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 1/9] usb: xhci: Add missing cache flush in the scratchpad array initialization
  2020-04-22  8:53       ` Nicolas Saenz Julienne
@ 2020-04-22  9:21         ` Bin Meng
  2020-04-22  9:26           ` Nicolas Saenz Julienne
  2020-04-22 12:01         ` Sylwester Nawrocki
  1 sibling, 1 reply; 36+ messages in thread
From: Bin Meng @ 2020-04-22  9:21 UTC (permalink / raw)
  To: u-boot

Hi Nicolas,

On Wed, Apr 22, 2020 at 4:53 PM Nicolas Saenz Julienne
<nsaenzjulienne@suse.de> wrote:
>
> Hi Sylwester, Marek
>
> On Tue, 2020-04-21 at 18:50 +0200, Sylwester Nawrocki wrote:
> > In current code there is no cache flush after initializing the scratchpad
> > buffer array with the scratchpad buffer pointers. This leads to a failure
> > of the "slot enable" command on the rpi4 board (Broadcom STB PCIe
> > controller + VL805 USB hub) - the very first TRB transfer on the command
> > ring fails and there is a timeout while waiting for the command completion
> > event. After adding the missing cache flush everything seems to be working
> > as expected.
> >
> > Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> > Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
> > ---
>
> I've been trying to get this working on my own and got stuck with this specific
> issue. I'm glad you found a solution, it was driving me crazy.
>
> Out of curiosity how did you found the solution?
>
> >  drivers/usb/host/xhci-mem.c | 3 +++
> >  1 file changed, 3 insertions(+)
> >
> > diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
> > index 93450ee..729bdc3 100644
> > --- a/drivers/usb/host/xhci-mem.c
> > +++ b/drivers/usb/host/xhci-mem.c
> > @@ -393,6 +393,9 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
> >               scratchpad->sp_array[i] = cpu_to_le64(ptr);
> >       }
> >
> > +     xhci_flush_cache((uintptr_t)scratchpad->sp_array,
> > +                      sizeof(u64) * num_sp);
> > +
>
> Marek, souldn't running 'dcache off; icache off' be equivalent to this (which
> didn't do the trick for me)? or am I missing somthing?

I guess something is wrong with RPi4's "dcache off" command ..

Regards,
Bin

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 1/9] usb: xhci: Add missing cache flush in the scratchpad array initialization
  2020-04-22  9:21         ` Bin Meng
@ 2020-04-22  9:26           ` Nicolas Saenz Julienne
  2020-04-22 11:02             ` Nicolas Saenz Julienne
  0 siblings, 1 reply; 36+ messages in thread
From: Nicolas Saenz Julienne @ 2020-04-22  9:26 UTC (permalink / raw)
  To: u-boot

On Wed, 2020-04-22 at 17:21 +0800, Bin Meng wrote:
> Hi Nicolas,
> 
> On Wed, Apr 22, 2020 at 4:53 PM Nicolas Saenz Julienne
> <nsaenzjulienne@suse.de> wrote:
> > Hi Sylwester, Marek
> > 
> > On Tue, 2020-04-21 at 18:50 +0200, Sylwester Nawrocki wrote:
> > > In current code there is no cache flush after initializing the scratchpad
> > > buffer array with the scratchpad buffer pointers. This leads to a failure
> > > of the "slot enable" command on the rpi4 board (Broadcom STB PCIe
> > > controller + VL805 USB hub) - the very first TRB transfer on the command
> > > ring fails and there is a timeout while waiting for the command completion
> > > event. After adding the missing cache flush everything seems to be working
> > > as expected.
> > > 
> > > Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> > > Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
> > > ---
> > 
> > I've been trying to get this working on my own and got stuck with this
> > specific
> > issue. I'm glad you found a solution, it was driving me crazy.
> > 
> > Out of curiosity how did you found the solution?
> > 
> > >  drivers/usb/host/xhci-mem.c | 3 +++
> > >  1 file changed, 3 insertions(+)
> > > 
> > > diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
> > > index 93450ee..729bdc3 100644
> > > --- a/drivers/usb/host/xhci-mem.c
> > > +++ b/drivers/usb/host/xhci-mem.c
> > > @@ -393,6 +393,9 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl
> > > *ctrl)
> > >               scratchpad->sp_array[i] = cpu_to_le64(ptr);
> > >       }
> > > 
> > > +     xhci_flush_cache((uintptr_t)scratchpad->sp_array,
> > > +                      sizeof(u64) * num_sp);
> > > +
> > 
> > Marek, souldn't running 'dcache off; icache off' be equivalent to this
> > (which
> > didn't do the trick for me)? or am I missing somthing?
> 
> I guess something is wrong with RPi4's "dcache off" command ..

You can't trust anything these times :)

I'll look into it.

Regards,
Nicolas

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: This is a digitally signed message part
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20200422/35821d5b/attachment.sig>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 4/9] rpi4: add a mapping for the PCIe XHCI controller MMIO registers (ARM 64bit)
  2020-04-21 16:50     ` [RFC PATCH 4/9] rpi4: add a mapping for the PCIe XHCI controller MMIO registers (ARM 64bit) Sylwester Nawrocki
@ 2020-04-22  9:46       ` Nicolas Saenz Julienne
  2020-04-22  9:54         ` Marek Szyprowski
  0 siblings, 1 reply; 36+ messages in thread
From: Nicolas Saenz Julienne @ 2020-04-22  9:46 UTC (permalink / raw)
  To: u-boot

Hi Sylwester,

On Tue, 2020-04-21 at 18:50 +0200, Sylwester Nawrocki wrote:
> From: Marek Szyprowski <m.szyprowski@samsung.com>
> 
> Create a non-cacheable mapping for the 0x600000000 physical memory region,
> where MMIO registers for the PCIe XHCI controller are instantiated by the
> PCIe bridge.
> 
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
>  arch/arm/mach-bcm283x/init.c | 18 +++++++++++++++---
>  1 file changed, 15 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/arm/mach-bcm283x/init.c b/arch/arm/mach-bcm283x/init.c
> index 4295356..6a748da 100644
> --- a/arch/arm/mach-bcm283x/init.c
> +++ b/arch/arm/mach-bcm283x/init.c
> @@ -11,10 +11,15 @@
>  #include <dm/device.h>
>  #include <fdt_support.h>
>  
> +#define BCM2711_RPI4_PCIE_XHCI_MMIO_PHYS	0x600000000UL
> +#define BCM2711_RPI4_PCIE_XHCI_MMIO_SIZE	0x800000UL

Where did you got this size from? I read from the Linux device tree the
following:

	pcie0: pcie at 7d500000 {
		compatible = "brcm,bcm2711-pcie";
		[...]
		ranges = <0x02000000 0x0 0xf8000000 0x6 0x00000000
			  0x0 0x04000000>;
		[...]
	};

Shouldn't the size be 0x4000000 then?

Other than that the patch looks good to me.

Regards,
Nicolas

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: This is a digitally signed message part
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20200422/f49ed794/attachment.sig>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 4/9] rpi4: add a mapping for the PCIe XHCI controller MMIO registers (ARM 64bit)
  2020-04-22  9:46       ` Nicolas Saenz Julienne
@ 2020-04-22  9:54         ` Marek Szyprowski
  2020-04-22 10:26           ` Nicolas Saenz Julienne
  0 siblings, 1 reply; 36+ messages in thread
From: Marek Szyprowski @ 2020-04-22  9:54 UTC (permalink / raw)
  To: u-boot

Hi Nicolas,

On 22.04.2020 11:46, Nicolas Saenz Julienne wrote:
> On Tue, 2020-04-21 at 18:50 +0200, Sylwester Nawrocki wrote:
>> From: Marek Szyprowski <m.szyprowski@samsung.com>
>>
>> Create a non-cacheable mapping for the 0x600000000 physical memory region,
>> where MMIO registers for the PCIe XHCI controller are instantiated by the
>> PCIe bridge.
>>
>> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
>> ---
>>   arch/arm/mach-bcm283x/init.c | 18 +++++++++++++++---
>>   1 file changed, 15 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/arm/mach-bcm283x/init.c b/arch/arm/mach-bcm283x/init.c
>> index 4295356..6a748da 100644
>> --- a/arch/arm/mach-bcm283x/init.c
>> +++ b/arch/arm/mach-bcm283x/init.c
>> @@ -11,10 +11,15 @@
>>   #include <dm/device.h>
>>   #include <fdt_support.h>
>>   
>> +#define BCM2711_RPI4_PCIE_XHCI_MMIO_PHYS	0x600000000UL
>> +#define BCM2711_RPI4_PCIE_XHCI_MMIO_SIZE	0x800000UL
> Where did you got this size from? I read from the Linux device tree the
> following:
>
> 	pcie0: pcie at 7d500000 {
> 		compatible = "brcm,bcm2711-pcie";
> 		[...]
> 		ranges = <0x02000000 0x0 0xf8000000 0x6 0x00000000
> 			  0x0 0x04000000>;
> 		[...]
> 	};
>
> Shouldn't the size be 0x4000000 then?
>
> Other than that the patch looks good to me.

Well, I reduced the window to 0x800000 to make it fit somewhere nicely 
in the 32bit address space. We can limit it even to a single section 
(2MiB), that's more than needed by the XHCI controller anyway. I can add 
a comment about that.

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 4/9] rpi4: add a mapping for the PCIe XHCI controller MMIO registers (ARM 64bit)
  2020-04-22  9:54         ` Marek Szyprowski
@ 2020-04-22 10:26           ` Nicolas Saenz Julienne
  0 siblings, 0 replies; 36+ messages in thread
From: Nicolas Saenz Julienne @ 2020-04-22 10:26 UTC (permalink / raw)
  To: u-boot

On Wed, 2020-04-22 at 11:54 +0200, Marek Szyprowski wrote:
> Hi Nicolas,
> 
> On 22.04.2020 11:46, Nicolas Saenz Julienne wrote:
> > On Tue, 2020-04-21 at 18:50 +0200, Sylwester Nawrocki wrote:
> > > From: Marek Szyprowski <m.szyprowski@samsung.com>
> > > 
> > > Create a non-cacheable mapping for the 0x600000000 physical memory region,
> > > where MMIO registers for the PCIe XHCI controller are instantiated by the
> > > PCIe bridge.
> > > 
> > > Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> > > ---
> > >   arch/arm/mach-bcm283x/init.c | 18 +++++++++++++++---
> > >   1 file changed, 15 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/arch/arm/mach-bcm283x/init.c b/arch/arm/mach-bcm283x/init.c
> > > index 4295356..6a748da 100644
> > > --- a/arch/arm/mach-bcm283x/init.c
> > > +++ b/arch/arm/mach-bcm283x/init.c
> > > @@ -11,10 +11,15 @@
> > >   #include <dm/device.h>
> > >   #include <fdt_support.h>
> > >   
> > > +#define BCM2711_RPI4_PCIE_XHCI_MMIO_PHYS	0x600000000UL
> > > +#define BCM2711_RPI4_PCIE_XHCI_MMIO_SIZE	0x800000UL
> > Where did you got this size from? I read from the Linux device tree the
> > following:
> > 
> > 	pcie0: pcie at 7d500000 {
> > 		compatible = "brcm,bcm2711-pcie";
> > 		[...]
> > 		ranges = <0x02000000 0x0 0xf8000000 0x6 0x00000000
> > 			  0x0 0x04000000>;
> > 		[...]
> > 	};
> > 
> > Shouldn't the size be 0x4000000 then?
> > 
> > Other than that the patch looks good to me.
> 
> Well, I reduced the window to 0x800000 to make it fit somewhere nicely 
> in the 32bit address space. We can limit it even to a single section 
> (2MiB), that's more than needed by the XHCI controller anyway. I can add 
> a comment about that.

Fair enough.

Thanks,
Nicolas

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: This is a digitally signed message part
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20200422/f26dc25b/attachment.sig>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 9/9] config: Enable support for the XHCI controller on RPI4 board
  2020-04-21 16:50     ` [RFC PATCH 9/9] config: Enable support for the XHCI controller on RPI4 board Sylwester Nawrocki
@ 2020-04-22 10:44       ` Nicolas Saenz Julienne
  2020-04-22 10:50         ` Peter Robinson
  0 siblings, 1 reply; 36+ messages in thread
From: Nicolas Saenz Julienne @ 2020-04-22 10:44 UTC (permalink / raw)
  To: u-boot

On Tue, 2020-04-21 at 18:50 +0200, Sylwester Nawrocki wrote:
> From: Marek Szyprowski <m.szyprowski@samsung.com>
> 
> This requires enabling BRCMSTB PCIe and XHCI_PCI drivers as well as PCI
> and USB commands. To get it working one has to call the following commands:
> "pci enum; usb start;", thus such commands have been added to the default
> "preboot" environment variable. One has to update his environment if it is
> already configured to get this feature working out of the box.
> 
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---

Would you mind enabling USB keyboard support too? It's useful for people using
u-boot/UEFI.

If not I don't mind sending a separate patch.

Regards,
Nicolas

>  configs/rpi_4_32b_defconfig |  9 +++++++++
>  configs/rpi_4_defconfig     | 10 ++++++++++
>  configs/rpi_arm64_defconfig |  9 ++++++++-
>  3 files changed, 27 insertions(+), 1 deletion(-)
> 
> diff --git a/configs/rpi_4_32b_defconfig b/configs/rpi_4_32b_defconfig
> index 72cda5d..0dd763f 100644
> --- a/configs/rpi_4_32b_defconfig
> +++ b/configs/rpi_4_32b_defconfig
> @@ -8,6 +8,8 @@ CONFIG_NR_DRAM_BANKS=2
>  CONFIG_DISTRO_DEFAULTS=y
>  CONFIG_OF_BOARD_SETUP=y
>  # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
> +CONFIG_USE_PREBOOT=y
> +CONFIG_PREBOOT="pci enum; usb start;"
>  CONFIG_MISC_INIT_R=y
>  # CONFIG_DISPLAY_CPUINFO is not set
>  # CONFIG_DISPLAY_BOARDINFO is not set
> @@ -15,6 +17,8 @@ CONFIG_SYS_PROMPT="U-Boot> "
>  CONFIG_CMD_DFU=y
>  CONFIG_CMD_GPIO=y
>  CONFIG_CMD_MMC=y
> +CONFIG_CMD_PCI=y
> +CONFIG_CMD_USB=y
>  CONFIG_CMD_FS_UUID=y
>  CONFIG_OF_BOARD=y
>  CONFIG_ENV_FAT_INTERFACE="mmc"
> @@ -28,12 +32,17 @@ CONFIG_MMC_SDHCI=y
>  CONFIG_MMC_SDHCI_BCM2835=y
>  CONFIG_DM_ETH=y
>  CONFIG_BCMGENET=y
> +CONFIG_PCI=y
> +CONFIG_DM_PCI=y
> +CONFIG_PCI_BRCMSTB=y
>  CONFIG_PINCTRL=y
>  # CONFIG_PINCTRL_GENERIC is not set
>  # CONFIG_REQUIRE_SERIAL_CONSOLE is not set
>  CONFIG_USB=y
>  CONFIG_DM_USB=y
>  CONFIG_DM_USB_GADGET=y
> +CONFIG_USB_XHCI_HCD=y
> +CONFIG_USB_XHCI_PCI=y
>  CONFIG_USB_GADGET=y
>  CONFIG_USB_GADGET_MANUFACTURER="FSL"
>  CONFIG_USB_GADGET_VENDOR_NUM=0x0525
> diff --git a/configs/rpi_4_defconfig b/configs/rpi_4_defconfig
> index 6d148da..f80e5da 100644
> --- a/configs/rpi_4_defconfig
> +++ b/configs/rpi_4_defconfig
> @@ -8,6 +8,8 @@ CONFIG_NR_DRAM_BANKS=2
>  CONFIG_DISTRO_DEFAULTS=y
>  CONFIG_OF_BOARD_SETUP=y
>  # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
> +CONFIG_USE_PREBOOT=y
> +CONFIG_PREBOOT="pci enum; usb start;"
>  CONFIG_MISC_INIT_R=y
>  # CONFIG_DISPLAY_CPUINFO is not set
>  # CONFIG_DISPLAY_BOARDINFO is not set
> @@ -15,6 +17,8 @@ CONFIG_SYS_PROMPT="U-Boot> "
>  CONFIG_CMD_DFU=y
>  CONFIG_CMD_GPIO=y
>  CONFIG_CMD_MMC=y
> +CONFIG_CMD_PCI=y
> +CONFIG_CMD_USB=y
>  CONFIG_CMD_FS_UUID=y
>  CONFIG_OF_BOARD=y
>  CONFIG_ENV_FAT_INTERFACE="mmc"
> @@ -28,12 +32,18 @@ CONFIG_MMC_SDHCI=y
>  CONFIG_MMC_SDHCI_BCM2835=y
>  CONFIG_DM_ETH=y
>  CONFIG_BCMGENET=y
> +CONFIG_PCI=y
> +CONFIG_DM_PCI=y
> +CONFIG_PCI_BRCMSTB=y
>  CONFIG_PINCTRL=y
>  # CONFIG_PINCTRL_GENERIC is not set
>  # CONFIG_REQUIRE_SERIAL_CONSOLE is not set
>  CONFIG_USB=y
>  CONFIG_DM_USB=y
>  CONFIG_DM_USB_GADGET=y
> +CONFIG_USB_XHCI_HCD=y
> +CONFIG_XHCI_64BIT_DWORD_ACCESS_ONLY=y
> +CONFIG_USB_XHCI_PCI=y
>  CONFIG_USB_GADGET=y
>  CONFIG_USB_GADGET_MANUFACTURER="FSL"
>  CONFIG_USB_GADGET_VENDOR_NUM=0x0525
> diff --git a/configs/rpi_arm64_defconfig b/configs/rpi_arm64_defconfig
> index fea86be..926dfc3 100644
> --- a/configs/rpi_arm64_defconfig
> +++ b/configs/rpi_arm64_defconfig
> @@ -7,13 +7,14 @@ CONFIG_NR_DRAM_BANKS=2
>  CONFIG_DISTRO_DEFAULTS=y
>  CONFIG_OF_BOARD_SETUP=y
>  CONFIG_USE_PREBOOT=y
> -CONFIG_PREBOOT="usb start"
> +CONFIG_PREBOOT="pci enum; usb start;"
>  CONFIG_MISC_INIT_R=y
>  # CONFIG_DISPLAY_CPUINFO is not set
>  # CONFIG_DISPLAY_BOARDINFO is not set
>  CONFIG_SYS_PROMPT="U-Boot> "
>  CONFIG_CMD_GPIO=y
>  CONFIG_CMD_MMC=y
> +CONFIG_CMD_PCI=y
>  CONFIG_CMD_USB=y
>  CONFIG_CMD_FS_UUID=y
>  CONFIG_OF_BOARD=y
> @@ -26,11 +27,17 @@ CONFIG_MMC_SDHCI=y
>  CONFIG_MMC_SDHCI_BCM2835=y
>  CONFIG_DM_ETH=y
>  CONFIG_BCMGENET=y
> +CONFIG_PCI=y
> +CONFIG_DM_PCI=y
> +CONFIG_PCI_BRCMSTB=y
>  CONFIG_PINCTRL=y
>  # CONFIG_PINCTRL_GENERIC is not set
>  # CONFIG_REQUIRE_SERIAL_CONSOLE is not set
>  CONFIG_USB=y
>  CONFIG_DM_USB=y
> +CONFIG_USB_XHCI_HCD=y
> +CONFIG_XHCI_64BIT_DWORD_ACCESS_ONLY=y
> +CONFIG_USB_XHCI_PCI=y
>  CONFIG_USB_DWC2=y
>  CONFIG_USB_KEYBOARD=y
>  CONFIG_USB_HOST_ETHER=y

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: This is a digitally signed message part
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20200422/607d0e28/attachment.sig>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 9/9] config: Enable support for the XHCI controller on RPI4 board
  2020-04-22 10:44       ` Nicolas Saenz Julienne
@ 2020-04-22 10:50         ` Peter Robinson
  2020-04-22 12:26           ` Nicolas Saenz Julienne
  0 siblings, 1 reply; 36+ messages in thread
From: Peter Robinson @ 2020-04-22 10:50 UTC (permalink / raw)
  To: u-boot

> > This requires enabling BRCMSTB PCIe and XHCI_PCI drivers as well as PCI
> > and USB commands. To get it working one has to call the following commands:
> > "pci enum; usb start;", thus such commands have been added to the default
> > "preboot" environment variable. One has to update his environment if it is
> > already configured to get this feature working out of the box.
> >
> > Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> > ---
>
> Would you mind enabling USB keyboard support too? It's useful for people using
> u-boot/UEFI.

And storage too:
CONFIG_USB_STORAGE=y
CONFIG_USB_KEYBOARD=y

In testing these patches I can see the devices with a "usb tree" but
even with the keyboard enabled it doesn't appear to work. AFAICT with
it enabled there should be support for usb keyboard via console in
include/configs/rpi.h but I couldn't see what else might be missing.

> If not I don't mind sending a separate patch.
>
> Regards,
> Nicolas
>
> >  configs/rpi_4_32b_defconfig |  9 +++++++++
> >  configs/rpi_4_defconfig     | 10 ++++++++++
> >  configs/rpi_arm64_defconfig |  9 ++++++++-
> >  3 files changed, 27 insertions(+), 1 deletion(-)
> >
> > diff --git a/configs/rpi_4_32b_defconfig b/configs/rpi_4_32b_defconfig
> > index 72cda5d..0dd763f 100644
> > --- a/configs/rpi_4_32b_defconfig
> > +++ b/configs/rpi_4_32b_defconfig
> > @@ -8,6 +8,8 @@ CONFIG_NR_DRAM_BANKS=2
> >  CONFIG_DISTRO_DEFAULTS=y
> >  CONFIG_OF_BOARD_SETUP=y
> >  # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
> > +CONFIG_USE_PREBOOT=y
> > +CONFIG_PREBOOT="pci enum; usb start;"
> >  CONFIG_MISC_INIT_R=y
> >  # CONFIG_DISPLAY_CPUINFO is not set
> >  # CONFIG_DISPLAY_BOARDINFO is not set
> > @@ -15,6 +17,8 @@ CONFIG_SYS_PROMPT="U-Boot> "
> >  CONFIG_CMD_DFU=y
> >  CONFIG_CMD_GPIO=y
> >  CONFIG_CMD_MMC=y
> > +CONFIG_CMD_PCI=y
> > +CONFIG_CMD_USB=y
> >  CONFIG_CMD_FS_UUID=y
> >  CONFIG_OF_BOARD=y
> >  CONFIG_ENV_FAT_INTERFACE="mmc"
> > @@ -28,12 +32,17 @@ CONFIG_MMC_SDHCI=y
> >  CONFIG_MMC_SDHCI_BCM2835=y
> >  CONFIG_DM_ETH=y
> >  CONFIG_BCMGENET=y
> > +CONFIG_PCI=y
> > +CONFIG_DM_PCI=y
> > +CONFIG_PCI_BRCMSTB=y
> >  CONFIG_PINCTRL=y
> >  # CONFIG_PINCTRL_GENERIC is not set
> >  # CONFIG_REQUIRE_SERIAL_CONSOLE is not set
> >  CONFIG_USB=y
> >  CONFIG_DM_USB=y
> >  CONFIG_DM_USB_GADGET=y
> > +CONFIG_USB_XHCI_HCD=y
> > +CONFIG_USB_XHCI_PCI=y
> >  CONFIG_USB_GADGET=y
> >  CONFIG_USB_GADGET_MANUFACTURER="FSL"
> >  CONFIG_USB_GADGET_VENDOR_NUM=0x0525
> > diff --git a/configs/rpi_4_defconfig b/configs/rpi_4_defconfig
> > index 6d148da..f80e5da 100644
> > --- a/configs/rpi_4_defconfig
> > +++ b/configs/rpi_4_defconfig
> > @@ -8,6 +8,8 @@ CONFIG_NR_DRAM_BANKS=2
> >  CONFIG_DISTRO_DEFAULTS=y
> >  CONFIG_OF_BOARD_SETUP=y
> >  # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
> > +CONFIG_USE_PREBOOT=y
> > +CONFIG_PREBOOT="pci enum; usb start;"
> >  CONFIG_MISC_INIT_R=y
> >  # CONFIG_DISPLAY_CPUINFO is not set
> >  # CONFIG_DISPLAY_BOARDINFO is not set
> > @@ -15,6 +17,8 @@ CONFIG_SYS_PROMPT="U-Boot> "
> >  CONFIG_CMD_DFU=y
> >  CONFIG_CMD_GPIO=y
> >  CONFIG_CMD_MMC=y
> > +CONFIG_CMD_PCI=y
> > +CONFIG_CMD_USB=y
> >  CONFIG_CMD_FS_UUID=y
> >  CONFIG_OF_BOARD=y
> >  CONFIG_ENV_FAT_INTERFACE="mmc"
> > @@ -28,12 +32,18 @@ CONFIG_MMC_SDHCI=y
> >  CONFIG_MMC_SDHCI_BCM2835=y
> >  CONFIG_DM_ETH=y
> >  CONFIG_BCMGENET=y
> > +CONFIG_PCI=y
> > +CONFIG_DM_PCI=y
> > +CONFIG_PCI_BRCMSTB=y
> >  CONFIG_PINCTRL=y
> >  # CONFIG_PINCTRL_GENERIC is not set
> >  # CONFIG_REQUIRE_SERIAL_CONSOLE is not set
> >  CONFIG_USB=y
> >  CONFIG_DM_USB=y
> >  CONFIG_DM_USB_GADGET=y
> > +CONFIG_USB_XHCI_HCD=y
> > +CONFIG_XHCI_64BIT_DWORD_ACCESS_ONLY=y
> > +CONFIG_USB_XHCI_PCI=y
> >  CONFIG_USB_GADGET=y
> >  CONFIG_USB_GADGET_MANUFACTURER="FSL"
> >  CONFIG_USB_GADGET_VENDOR_NUM=0x0525
> > diff --git a/configs/rpi_arm64_defconfig b/configs/rpi_arm64_defconfig
> > index fea86be..926dfc3 100644
> > --- a/configs/rpi_arm64_defconfig
> > +++ b/configs/rpi_arm64_defconfig
> > @@ -7,13 +7,14 @@ CONFIG_NR_DRAM_BANKS=2
> >  CONFIG_DISTRO_DEFAULTS=y
> >  CONFIG_OF_BOARD_SETUP=y
> >  CONFIG_USE_PREBOOT=y
> > -CONFIG_PREBOOT="usb start"
> > +CONFIG_PREBOOT="pci enum; usb start;"
> >  CONFIG_MISC_INIT_R=y
> >  # CONFIG_DISPLAY_CPUINFO is not set
> >  # CONFIG_DISPLAY_BOARDINFO is not set
> >  CONFIG_SYS_PROMPT="U-Boot> "
> >  CONFIG_CMD_GPIO=y
> >  CONFIG_CMD_MMC=y
> > +CONFIG_CMD_PCI=y
> >  CONFIG_CMD_USB=y
> >  CONFIG_CMD_FS_UUID=y
> >  CONFIG_OF_BOARD=y
> > @@ -26,11 +27,17 @@ CONFIG_MMC_SDHCI=y
> >  CONFIG_MMC_SDHCI_BCM2835=y
> >  CONFIG_DM_ETH=y
> >  CONFIG_BCMGENET=y
> > +CONFIG_PCI=y
> > +CONFIG_DM_PCI=y
> > +CONFIG_PCI_BRCMSTB=y
> >  CONFIG_PINCTRL=y
> >  # CONFIG_PINCTRL_GENERIC is not set
> >  # CONFIG_REQUIRE_SERIAL_CONSOLE is not set
> >  CONFIG_USB=y
> >  CONFIG_DM_USB=y
> > +CONFIG_USB_XHCI_HCD=y
> > +CONFIG_XHCI_64BIT_DWORD_ACCESS_ONLY=y
> > +CONFIG_USB_XHCI_PCI=y
> >  CONFIG_USB_DWC2=y
> >  CONFIG_USB_KEYBOARD=y
> >  CONFIG_USB_HOST_ETHER=y
>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 1/9] usb: xhci: Add missing cache flush in the scratchpad array initialization
  2020-04-22  9:26           ` Nicolas Saenz Julienne
@ 2020-04-22 11:02             ` Nicolas Saenz Julienne
  0 siblings, 0 replies; 36+ messages in thread
From: Nicolas Saenz Julienne @ 2020-04-22 11:02 UTC (permalink / raw)
  To: u-boot

On Wed, 2020-04-22 at 11:26 +0200, Nicolas Saenz Julienne wrote:
> On Wed, 2020-04-22 at 17:21 +0800, Bin Meng wrote:
> > Hi Nicolas,
> > 
> > On Wed, Apr 22, 2020 at 4:53 PM Nicolas Saenz Julienne
> > <nsaenzjulienne@suse.de> wrote:
> > > Hi Sylwester, Marek
> > > 
> > > On Tue, 2020-04-21 at 18:50 +0200, Sylwester Nawrocki wrote:
> > > > In current code there is no cache flush after initializing the
> > > > scratchpad
> > > > buffer array with the scratchpad buffer pointers. This leads to a
> > > > failure
> > > > of the "slot enable" command on the rpi4 board (Broadcom STB PCIe
> > > > controller + VL805 USB hub) - the very first TRB transfer on the command
> > > > ring fails and there is a timeout while waiting for the command
> > > > completion
> > > > event. After adding the missing cache flush everything seems to be
> > > > working
> > > > as expected.
> > > > 
> > > > Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> > > > Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
> > > > ---
> > > 
> > > I've been trying to get this working on my own and got stuck with this
> > > specific
> > > issue. I'm glad you found a solution, it was driving me crazy.
> > > 
> > > Out of curiosity how did you found the solution?
> > > 
> > > >  drivers/usb/host/xhci-mem.c | 3 +++
> > > >  1 file changed, 3 insertions(+)
> > > > 
> > > > diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
> > > > index 93450ee..729bdc3 100644
> > > > --- a/drivers/usb/host/xhci-mem.c
> > > > +++ b/drivers/usb/host/xhci-mem.c
> > > > @@ -393,6 +393,9 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl
> > > > *ctrl)
> > > >               scratchpad->sp_array[i] = cpu_to_le64(ptr);
> > > >       }
> > > > 
> > > > +     xhci_flush_cache((uintptr_t)scratchpad->sp_array,
> > > > +                      sizeof(u64) * num_sp);
> > > > +
> > > 
> > > Marek, souldn't running 'dcache off; icache off' be equivalent to this
> > > (which
> > > didn't do the trick for me)? or am I missing somthing?
> > 
> > I guess something is wrong with RPi4's "dcache off" command ..
> 
> You can't trust anything these times :)
> 
> I'll look into it.

Well it's not only that disabling the caches was needed, but also avoiding
64bit accesses, since I was missed that one, I didn't see the change in
behavior. In other words, dcache/icache commands are fine.

Sorry for the noise.

Regards,
Nicolas

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: This is a digitally signed message part
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20200422/efa8d4cb/attachment.sig>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 1/9] usb: xhci: Add missing cache flush in the scratchpad array initialization
  2020-04-22  8:53       ` Nicolas Saenz Julienne
  2020-04-22  9:21         ` Bin Meng
@ 2020-04-22 12:01         ` Sylwester Nawrocki
  2020-04-22 12:33           ` Nicolas Saenz Julienne
  1 sibling, 1 reply; 36+ messages in thread
From: Sylwester Nawrocki @ 2020-04-22 12:01 UTC (permalink / raw)
  To: u-boot

Hi Nicolas,

(fixed Simon's email address, apologies for mistyping it, I will make sure
it's correct in next iteration)

On 22.04.2020 10:53, Nicolas Saenz Julienne wrote:
> I've been trying to get this working on my own and got stuck with this specific
> issue. I'm glad you found a solution, it was driving me crazy.
> 
> Out of curiosity how did you found the solution?

It took me many days of debugging...given my nearly non existent previous
experience in u-boot development.In short, it started with a suggestion to map all memory for CPU as uncached.
As in such a case booting was failing I checked where the xhci shared buffer
allocation fall and created only a small uncached window to cover those
allocations. This was first thing that started working, after fixing the 
64-bit pointers setup in XHCI registers.
Then I discovered "dcache" command and that was also helpful. It was sufficient 
to run "dcache off; usb start; dcache on". Then USB worked even after "usb reset"
IIRC. But that was with my old development branch based on v2019.10-rc4 tag.
Marek tried the same with newer tree and dcache_disable() was not helping,
but dcache_flush_all() was.

By moving dcache_disable(), dcache_enable() around I found out that it was 
sufficient to disable dcache before xhci_start() call and to enable it right 
afterwards.

Then I just "bisected" the uncached memory region which narrowed it roughly 
to the scratchpad buffer allocations. By inspecting the code carefully again
it turned there is one more cache flush call needed.

>> diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
>> index 93450ee..729bdc3 100644
>> --- a/drivers/usb/host/xhci-mem.c
>> +++ b/drivers/usb/host/xhci-mem.c
>> @@ -393,6 +393,9 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
>>  		scratchpad->sp_array[i] = cpu_to_le64(ptr);
>>  	}
>>  
>> +	xhci_flush_cache((uintptr_t)scratchpad->sp_array,
>> +			 sizeof(u64) * num_sp);
>> +
> 
> Marek, souldn't running 'dcache off; icache off' be equivalent to this (which
> didn't do the trick for me)? or am I missing somthing?


Regards,
-- 
Sylwester Nawrocki
Samsung R&D Institute Poland

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 9/9] config: Enable support for the XHCI controller on RPI4 board
  2020-04-22 10:50         ` Peter Robinson
@ 2020-04-22 12:26           ` Nicolas Saenz Julienne
  2020-04-22 12:37             ` Peter Robinson
  2020-04-22 16:49             ` Sylwester Nawrocki
  0 siblings, 2 replies; 36+ messages in thread
From: Nicolas Saenz Julienne @ 2020-04-22 12:26 UTC (permalink / raw)
  To: u-boot

Hi Peter,

On Wed, 2020-04-22 at 11:50 +0100, Peter Robinson wrote:
> > > This requires enabling BRCMSTB PCIe and XHCI_PCI drivers as well as PCI
> > > and USB commands. To get it working one has to call the following
> > > commands:
> > > "pci enum; usb start;", thus such commands have been added to the default
> > > "preboot" environment variable. One has to update his environment if it is
> > > already configured to get this feature working out of the box.
> > > 
> > > Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> > > ---
> > 
> > Would you mind enabling USB keyboard support too? It's useful for people
> > using
> > u-boot/UEFI.
> 
> And storage too:
> CONFIG_USB_STORAGE=y
> CONFIG_USB_KEYBOARD=y
> 
> In testing these patches I can see the devices with a "usb tree" but
> even with the keyboard enabled it doesn't appear to work. AFAICT with
> it enabled there should be support for usb keyboard via console in
> include/configs/rpi.h but I couldn't see what else might be missing.

That's surprising, USB keyboard works fine in my case.

Regards,
Nicolas

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: This is a digitally signed message part
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20200422/80303ec7/attachment.sig>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 1/9] usb: xhci: Add missing cache flush in the scratchpad array initialization
  2020-04-22 12:01         ` Sylwester Nawrocki
@ 2020-04-22 12:33           ` Nicolas Saenz Julienne
  2020-04-22 16:32             ` Simon Glass
  0 siblings, 1 reply; 36+ messages in thread
From: Nicolas Saenz Julienne @ 2020-04-22 12:33 UTC (permalink / raw)
  To: u-boot

On Wed, 2020-04-22 at 14:01 +0200, Sylwester Nawrocki wrote:
> Hi Nicolas,
> 
> (fixed Simon's email address, apologies for mistyping it, I will make sure
> it's correct in next iteration)
> 
> On 22.04.2020 10:53, Nicolas Saenz Julienne wrote:
> > I've been trying to get this working on my own and got stuck with this
> > specific
> > issue. I'm glad you found a solution, it was driving me crazy.
> > 
> > Out of curiosity how did you found the solution?
> 
> It took me many days of debugging...given my nearly non existent previous
> experience in u-boot development.In short, it started with a suggestion to map
> all memory for CPU as uncached.
> As in such a case booting was failing I checked where the xhci shared buffer
> allocation fall and created only a small uncached window to cover those
> allocations. This was first thing that started working, after fixing the 
> 64-bit pointers setup in XHCI registers.
> Then I discovered "dcache" command and that was also helpful. It was
> sufficient 
> to run "dcache off; usb start; dcache on". Then USB worked even after "usb
> reset"
> IIRC. But that was with my old development branch based on v2019.10-rc4 tag.
> Marek tried the same with newer tree and dcache_disable() was not helping,
> but dcache_flush_all() was.
> 
> By moving dcache_disable(), dcache_enable() around I found out that it was 
> sufficient to disable dcache before xhci_start() call and to enable it right 
> afterwards.
> 
> Then I just "bisected" the uncached memory region which narrowed it roughly 
> to the scratchpad buffer allocations. By inspecting the code carefully again
> it turned there is one more cache flush call needed.

Thanks for the in-depth explanation, it's very much appreciated!

Regards,
Nicolas

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: This is a digitally signed message part
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20200422/74d3a662/attachment.sig>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 9/9] config: Enable support for the XHCI controller on RPI4 board
  2020-04-22 12:26           ` Nicolas Saenz Julienne
@ 2020-04-22 12:37             ` Peter Robinson
  2020-04-22 16:49             ` Sylwester Nawrocki
  1 sibling, 0 replies; 36+ messages in thread
From: Peter Robinson @ 2020-04-22 12:37 UTC (permalink / raw)
  To: u-boot

On Wed, Apr 22, 2020 at 1:26 PM Nicolas Saenz Julienne
<nsaenzjulienne@suse.de> wrote:
>
> Hi Peter,
>
> On Wed, 2020-04-22 at 11:50 +0100, Peter Robinson wrote:
> > > > This requires enabling BRCMSTB PCIe and XHCI_PCI drivers as well as PCI
> > > > and USB commands. To get it working one has to call the following
> > > > commands:
> > > > "pci enum; usb start;", thus such commands have been added to the default
> > > > "preboot" environment variable. One has to update his environment if it is
> > > > already configured to get this feature working out of the box.
> > > >
> > > > Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> > > > ---
> > >
> > > Would you mind enabling USB keyboard support too? It's useful for people
> > > using
> > > u-boot/UEFI.
> >
> > And storage too:
> > CONFIG_USB_STORAGE=y
> > CONFIG_USB_KEYBOARD=y
> >
> > In testing these patches I can see the devices with a "usb tree" but
> > even with the keyboard enabled it doesn't appear to work. AFAICT with
> > it enabled there should be support for usb keyboard via console in
> > include/configs/rpi.h but I couldn't see what else might be missing.
>
> That's surprising, USB keyboard works fine in my case.

I've tried 2 devices and 2 keyboards and someone else managed to
reproduce it. Another person got it working on the top USB3 port but
it was even intermittent there.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 6/9] usb: xhci: Allow accessing 64-bit registers with DWORD accesses only
  2020-04-22  6:00       ` Bin Meng
@ 2020-04-22 13:37         ` Sylwester Nawrocki
  0 siblings, 0 replies; 36+ messages in thread
From: Sylwester Nawrocki @ 2020-04-22 13:37 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On 22.04.2020 08:00, Bin Meng wrote:
> On Wed, Apr 22, 2020 at 12:51 AM Sylwester Nawrocki
> <s.nawrocki@samsung.com> wrote:
[...]
>> So far I couldn't come up with anything better to make the xHCI host
>> controller working on the rpi4 board. For some reason dereferencing
>> a 64-bit pointer to access 64-bit registers doesn't work there,
>> might be a limitation of the PCIe bridge behind the SCB. In Linux
>> always 2 double word accesses are used.
> 
> If Linux always uses 2 double word accesses, let's simply do the same
> in U-Boot by removing the readq/writeq.

Thanks for your review. That sounds good to me, I will do it that way
in next iteration.

--
Regards, 
Sylwester

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 7/9] pci: Add some PCI Express capability register offset definitions
  2020-04-22  6:16       ` Bin Meng
@ 2020-04-22 13:40         ` Sylwester Nawrocki
  0 siblings, 0 replies; 36+ messages in thread
From: Sylwester Nawrocki @ 2020-04-22 13:40 UTC (permalink / raw)
  To: u-boot

On 22.04.2020 08:16, Bin Meng wrote:
> On Wed, Apr 22, 2020 at 12:51 AM Sylwester Nawrocki
> <s.nawrocki@samsung.com> wrote:

>>  #define PCI_EXP_LNKCAP         12      /* Link Capabilities */
>> +#define  PCI_EXP_LNKCAP_SLS    0x0000000f /* Supported Link Speeds */
>> +#define  PCI_EXP_LNKCAP_MLW    0x000003f0 /* Maximum Link Width */
>>  #define  PCI_EXP_LNKCAP_DLLLARC        0x00100000 /* Data Link Layer Link Active Reporting Capable */
>>
>>  #define PCI_EXP_LNKSTA         18      /* Link Status */
>> +#define  PCI_EXP_LNKSTA_CLS    0x000f  /* Current Link Speed */
>> +#define  PCI_EXP_LNKSTA_NLW    0x03f0  /* Negotiated Link Width */
>> +#define  PCI_EXP_LNKSTA_NLW_SHIFT 4    /* start of NLW mask in link status */
>> +
>>  #define  PCI_EXP_LNKSTA_DLLLA  0x2000  /* Data Link Layer Link Active */
>> +#define PCI_EXP_LNKCTL2                48      /* Link Control 2 */
> 
> Please put PCI_EXP_LNKCTL2 after PCI_EXP_SLTCAP (sorted in order)

Thanks for pointing this out, will be corrected in next iteration.

>>  #define PCI_EXP_SLTCAP         20      /* Slot Capabilities */
>>  #define  PCI_EXP_SLTCAP_PSN    0xfff80000 /* Physical Slot Number */

--
Regards, 
Sylwester

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 1/9] usb: xhci: Add missing cache flush in the scratchpad array initialization
  2020-04-22 12:33           ` Nicolas Saenz Julienne
@ 2020-04-22 16:32             ` Simon Glass
  0 siblings, 0 replies; 36+ messages in thread
From: Simon Glass @ 2020-04-22 16:32 UTC (permalink / raw)
  To: u-boot

On Wed, 22 Apr 2020 at 06:33, Nicolas Saenz Julienne
<nsaenzjulienne@suse.de> wrote:
>
> On Wed, 2020-04-22 at 14:01 +0200, Sylwester Nawrocki wrote:
> > Hi Nicolas,
> >
> > (fixed Simon's email address, apologies for mistyping it, I will make sure
> > it's correct in next iteration)
> >
> > On 22.04.2020 10:53, Nicolas Saenz Julienne wrote:
> > > I've been trying to get this working on my own and got stuck with this
> > > specific
> > > issue. I'm glad you found a solution, it was driving me crazy.
> > >
> > > Out of curiosity how did you found the solution?
> >
> > It took me many days of debugging...given my nearly non existent previous
> > experience in u-boot development.In short, it started with a suggestion to map
> > all memory for CPU as uncached.
> > As in such a case booting was failing I checked where the xhci shared buffer
> > allocation fall and created only a small uncached window to cover those
> > allocations. This was first thing that started working, after fixing the
> > 64-bit pointers setup in XHCI registers.
> > Then I discovered "dcache" command and that was also helpful. It was
> > sufficient
> > to run "dcache off; usb start; dcache on". Then USB worked even after "usb
> > reset"
> > IIRC. But that was with my old development branch based on v2019.10-rc4 tag.
> > Marek tried the same with newer tree and dcache_disable() was not helping,
> > but dcache_flush_all() was.
> >
> > By moving dcache_disable(), dcache_enable() around I found out that it was
> > sufficient to disable dcache before xhci_start() call and to enable it right
> > afterwards.
> >
> > Then I just "bisected" the uncached memory region which narrowed it roughly
> > to the scratchpad buffer allocations. By inspecting the code carefully again
> > it turned there is one more cache flush call needed.
>
> Thanks for the in-depth explanation, it's very much appreciated!

Yes indeed, thank you!


- Simon

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 8/9] pci: Add driver for Broadcom STB PCIe controller
  2020-04-22  9:16       ` Nicolas Saenz Julienne
@ 2020-04-22 16:42         ` Sylwester Nawrocki
  2020-04-22 16:51           ` Nicolas Saenz Julienne
  0 siblings, 1 reply; 36+ messages in thread
From: Sylwester Nawrocki @ 2020-04-22 16:42 UTC (permalink / raw)
  To: u-boot

Hi Nicolas,

On 22.04.2020 11:16, Nicolas Saenz Julienne wrote:
 
> I see that you based your code on the downstream PCIe driver (the one available
> in the Raspberry Pi foundation kernel repos). There's a real upstream version
> of it[1], It's properly reviewed and we made a point to remove all non bcm2711
> specific stuff from it, as support for other platforms (like bcm7445) isn't
> there yet (it depends on supporting multiple dma-ranges in Linux, which we
> don't). Also note that the Raspberry Pi foundation is moving towards using this
> driver, see for example their rpi-5.6.y branch, and I belive Broadcom is doing
> the same.
> 
> So I strongly suggest you base this driver on the upstream version. As I was
> working towards the same goal as you I already have an implementation for
> u-boot myself[2]. Feel free to use that if you find it useful. Ultimately,
> whether you base it on my version or the upstream Linux version it's half the
> size and easier to follow.

Thanks, I'm going to reuse you code, it looks much cleaner.
I started working on this PCIe driver back at end of 2019, then that task was
postponed for few months. I should have been following better related Linux
mainline works. Now, when it all more or less works I will try reuse your code.
> [1] 
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/pci/controller/pcie-brcmstb.c?h=v5.7-rc2
> [2] https://protect2.fireeye.com/url?k=14361ea6-49a8854c-143795e9-0cc47a6cba04-df90fb3bfec30a2d&q=1&u=https%3A%2F%2Fgithub.com%2Fvianpl%2Fu-boot%2Fcommits%2Fbrcm-pcie
> 

-- 
Regards,
Sylwester

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 9/9] config: Enable support for the XHCI controller on RPI4 board
  2020-04-22 12:26           ` Nicolas Saenz Julienne
  2020-04-22 12:37             ` Peter Robinson
@ 2020-04-22 16:49             ` Sylwester Nawrocki
  1 sibling, 0 replies; 36+ messages in thread
From: Sylwester Nawrocki @ 2020-04-22 16:49 UTC (permalink / raw)
  To: u-boot

On 22.04.2020 14:26, Nicolas Saenz Julienne wrote:
> On Wed, 2020-04-22 at 11:50 +0100, Peter Robinson wrote:

>>> Would you mind enabling USB keyboard support too? It's useful for people
>>> using
>>> u-boot/UEFI.
>>
>> And storage too:
>> CONFIG_USB_STORAGE=y
>> CONFIG_USB_KEYBOARD=y
>>
>> In testing these patches I can see the devices with a "usb tree" but
>> even with the keyboard enabled it doesn't appear to work. AFAICT with
>> it enabled there should be support for usb keyboard via console in
>> include/configs/rpi.h but I couldn't see what else might be missing.
> 
> That's surprising, USB keyboard works fine in my case.

USB keyboard also works well for me (but not the one with a built-in 
touchpad). I could add those 2 additional options to the patch but perhaps 
it's better to leave it as is, i.e. enable PCIe/xHCI in one patch and all 
needed USB devices in another?
  
-- 
Regards,
Sylwester

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 8/9] pci: Add driver for Broadcom STB PCIe controller
  2020-04-22 16:42         ` Sylwester Nawrocki
@ 2020-04-22 16:51           ` Nicolas Saenz Julienne
  0 siblings, 0 replies; 36+ messages in thread
From: Nicolas Saenz Julienne @ 2020-04-22 16:51 UTC (permalink / raw)
  To: u-boot

On Wed, 2020-04-22 at 18:42 +0200, Sylwester Nawrocki wrote:
> Hi Nicolas,
> 
> On 22.04.2020 11:16, Nicolas Saenz Julienne wrote:
>  
> > I see that you based your code on the downstream PCIe driver (the one
> > available
> > in the Raspberry Pi foundation kernel repos). There's a real upstream
> > version
> > of it[1], It's properly reviewed and we made a point to remove all non
> > bcm2711
> > specific stuff from it, as support for other platforms (like bcm7445) isn't
> > there yet (it depends on supporting multiple dma-ranges in Linux, which we
> > don't). Also note that the Raspberry Pi foundation is moving towards using
> > this
> > driver, see for example their rpi-5.6.y branch, and I belive Broadcom is
> > doing
> > the same.
> > 
> > So I strongly suggest you base this driver on the upstream version. As I was
> > working towards the same goal as you I already have an implementation for
> > u-boot myself[2]. Feel free to use that if you find it useful. Ultimately,
> > whether you base it on my version or the upstream Linux version it's half
> > the
> > size and easier to follow.
> 
> Thanks, I'm going to reuse you code, it looks much cleaner.
> I started working on this PCIe driver back at end of 2019, then that task was
> postponed for few months. I should have been following better related Linux
> mainline works. Now, when it all more or less works I will try reuse your
> code.

Nice, FYI I replaced the driver as is and it worked out of the box, so it
should be relatively painless.

Regards,
Nicolas

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: This is a digitally signed message part
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20200422/585d2a1f/attachment.sig>

^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2020-04-22 16:51 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CGME20200421165108eucas1p190b455fc38d44c3f768630c8e194cd9a@eucas1p1.samsung.com>
2020-04-21 16:50 ` [RFC PATCH 0/9] USB host support for Raspberry Pi 4 board Sylwester Nawrocki
     [not found]   ` <CGME20200421165114eucas1p2baa595b46f7503331ab86163f69b7c0e@eucas1p2.samsung.com>
2020-04-21 16:50     ` [RFC PATCH 1/9] usb: xhci: Add missing cache flush in the scratchpad array initialization Sylwester Nawrocki
2020-04-22  5:44       ` Bin Meng
2020-04-22  8:53       ` Nicolas Saenz Julienne
2020-04-22  9:21         ` Bin Meng
2020-04-22  9:26           ` Nicolas Saenz Julienne
2020-04-22 11:02             ` Nicolas Saenz Julienne
2020-04-22 12:01         ` Sylwester Nawrocki
2020-04-22 12:33           ` Nicolas Saenz Julienne
2020-04-22 16:32             ` Simon Glass
     [not found]   ` <CGME20200421165117eucas1p220b0a5f7820c7cf7bae20dc693584ad4@eucas1p2.samsung.com>
2020-04-21 16:50     ` [RFC PATCH 2/9] pci: Move some PCIe register offset definitions to a common header Sylwester Nawrocki
2020-04-22  5:51       ` Bin Meng
     [not found]   ` <CGME20200421165118eucas1p1dc542f61cefcf53cdb1f17cc59baee5f@eucas1p1.samsung.com>
2020-04-21 16:50     ` [RFC PATCH 3/9] rpi4: shorten a mapping for the DRAM Sylwester Nawrocki
     [not found]   ` <CGME20200421165119eucas1p19a1103b9f6b952bd83086a77df71e837@eucas1p1.samsung.com>
2020-04-21 16:50     ` [RFC PATCH 4/9] rpi4: add a mapping for the PCIe XHCI controller MMIO registers (ARM 64bit) Sylwester Nawrocki
2020-04-22  9:46       ` Nicolas Saenz Julienne
2020-04-22  9:54         ` Marek Szyprowski
2020-04-22 10:26           ` Nicolas Saenz Julienne
     [not found]   ` <CGME20200421165123eucas1p171701bd64ed84a9c740331ce87c7ff6c@eucas1p1.samsung.com>
2020-04-21 16:50     ` [RFC PATCH 5/9] rpi4: add a mapping for the PCIe XHCI controller MMIO registers (ARM 32bit) Sylwester Nawrocki
     [not found]   ` <CGME20200421165124eucas1p161d4049c0e136fc74ae2b00c2a1b3883@eucas1p1.samsung.com>
2020-04-21 16:50     ` [RFC PATCH 6/9] usb: xhci: Allow accessing 64-bit registers with DWORD accesses only Sylwester Nawrocki
2020-04-22  6:00       ` Bin Meng
2020-04-22 13:37         ` Sylwester Nawrocki
2020-04-22  8:58       ` Nicolas Saenz Julienne
     [not found]   ` <CGME20200421165124eucas1p2e7cbc2eea896a682961304de7ff53dc2@eucas1p2.samsung.com>
2020-04-21 16:50     ` [RFC PATCH 7/9] pci: Add some PCI Express capability register offset definitions Sylwester Nawrocki
2020-04-22  6:16       ` Bin Meng
2020-04-22 13:40         ` Sylwester Nawrocki
     [not found]   ` <CGME20200421165125eucas1p1a4cc19f4c58f449375e6d66b19d51e04@eucas1p1.samsung.com>
2020-04-21 16:50     ` [RFC PATCH 8/9] pci: Add driver for Broadcom STB PCIe controller Sylwester Nawrocki
2020-04-22  6:17       ` Bin Meng
2020-04-22  9:16       ` Nicolas Saenz Julienne
2020-04-22 16:42         ` Sylwester Nawrocki
2020-04-22 16:51           ` Nicolas Saenz Julienne
     [not found]   ` <CGME20200421165125eucas1p12d7451082887a52073ba795aa0ee398a@eucas1p1.samsung.com>
2020-04-21 16:50     ` [RFC PATCH 9/9] config: Enable support for the XHCI controller on RPI4 board Sylwester Nawrocki
2020-04-22 10:44       ` Nicolas Saenz Julienne
2020-04-22 10:50         ` Peter Robinson
2020-04-22 12:26           ` Nicolas Saenz Julienne
2020-04-22 12:37             ` Peter Robinson
2020-04-22 16:49             ` Sylwester Nawrocki

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.