summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/include/asm/mmu.h8
-rw-r--r--arch/arm/include/asm/system.h36
-rw-r--r--arch/arm/lib/cache-cp15.c24
-rw-r--r--arch/arm/mach-bcm283x/Kconfig1
-rw-r--r--arch/arm/mach-bcm283x/include/mach/base.h8
-rw-r--r--arch/arm/mach-bcm283x/include/mach/mbox.h13
-rw-r--r--arch/arm/mach-bcm283x/include/mach/msg.h7
-rw-r--r--arch/arm/mach-bcm283x/init.c41
-rw-r--r--arch/arm/mach-bcm283x/msg.c46
9 files changed, 165 insertions, 19 deletions
diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h
new file mode 100644
index 0000000000..9ac16f599e
--- /dev/null
+++ b/arch/arm/include/asm/mmu.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef __ASM_ARM_MMU_H
+#define __ASM_ARM_MMU_H
+
+void init_addr_map(void);
+
+#endif
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index b8c1b4ea74..37c1bfd726 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -207,7 +207,7 @@ int __asm_invalidate_l3_icache(void);
void __asm_switch_ttbr(u64 new_ttbr);
/*
- * Switch from EL3 to EL2 for ARMv8
+ * armv8_switch_to_el2() - switch from EL3 to EL2 for ARMv8
*
* @args: For loading 64-bit OS, fdt address.
* For loading 32-bit OS, zero.
@@ -222,7 +222,7 @@ void __asm_switch_ttbr(u64 new_ttbr);
void __noreturn armv8_switch_to_el2(u64 args, u64 mach_nr, u64 fdt_addr,
u64 arg4, u64 entry_point, u64 es_flag);
/*
- * Switch from EL2 to EL1 for ARMv8
+ * armv8_switch_to_el1() - switch from EL2 to EL1 for ARMv8
*
* @args: For loading 64-bit OS, fdt address.
* For loading 32-bit OS, zero.
@@ -248,11 +248,12 @@ void flush_l3_cache(void);
void mmu_change_region_attr(phys_addr_t start, size_t size, u64 attrs);
/*
- *Issue a secure monitor call in accordance with ARM "SMC Calling convention",
+ * smc_call() - issue a secure monitor call
+ *
+ * Issue a secure monitor call in accordance with ARM "SMC Calling convention",
* DEN0028A
*
* @args: input and output arguments
- *
*/
void smc_call(struct pt_regs *args);
@@ -521,10 +522,12 @@ enum {
#endif
/**
+ * mmu_page_table_flush() - register an update to page tables
+ *
* Register an update to the page tables, and flush the TLB
*
- * \param start start address of update in page table
- * \param stop stop address of update in page table
+ * @start: start address of update in page table
+ * @stop: stop address of update in page table
*/
void mmu_page_table_flush(unsigned long start, unsigned long stop);
@@ -585,11 +588,26 @@ s32 psci_features(u32 function_id, u32 psci_fid);
void save_boot_params_ret(void);
/**
+ * mmu_set_region_dcache_behaviour_phys() - set virt/phys mapping
+ *
+ * Change the virt/phys mapping and cache settings for a region.
+ *
+ * @virt: virtual start address of memory region to change
+ * @phys: physical address for the memory region to set
+ * @size: size of memory region to change
+ * @option: dcache option to select
+ */
+void mmu_set_region_dcache_behaviour_phys(phys_addr_t virt, phys_addr_t phys,
+ size_t size, enum dcache_option option);
+
+/**
+ * mmu_set_region_dcache_behaviour() - set cache settings
+ *
* Change the cache settings for a region.
*
- * \param start start address of memory region to change
- * \param size size of memory region to change
- * \param option dcache option to select
+ * @start: start address of memory region to change
+ * @size: size of memory region to change
+ * @option: dcache option to select
*/
void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
enum dcache_option option);
diff --git a/arch/arm/lib/cache-cp15.c b/arch/arm/lib/cache-cp15.c
index 1da2e92fe2..39717610d4 100644
--- a/arch/arm/lib/cache-cp15.c
+++ b/arch/arm/lib/cache-cp15.c
@@ -25,7 +25,8 @@ __weak void arm_init_domains(void)
{
}
-void set_section_dcache(int section, enum dcache_option option)
+static void set_section_phys(int section, phys_addr_t phys,
+ enum dcache_option option)
{
#ifdef CONFIG_ARMV7_LPAE
u64 *page_table = (u64 *)gd->arch.tlb_addr;
@@ -37,7 +38,7 @@ void set_section_dcache(int section, enum dcache_option option)
#endif
/* Add the page offset */
- value |= ((u32)section << MMU_SECTION_SHIFT);
+ value |= phys;
/* Add caching bits */
value |= option;
@@ -46,13 +47,18 @@ void set_section_dcache(int section, enum dcache_option option)
page_table[section] = value;
}
+void set_section_dcache(int section, enum dcache_option option)
+{
+ set_section_phys(section, (u32)section << MMU_SECTION_SHIFT, option);
+}
+
__weak void mmu_page_table_flush(unsigned long start, unsigned long stop)
{
debug("%s: Warning: not implemented\n", __func__);
}
-void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
- enum dcache_option option)
+void mmu_set_region_dcache_behaviour_phys(phys_addr_t start, phys_addr_t phys,
+ size_t size, enum dcache_option option)
{
#ifdef CONFIG_ARMV7_LPAE
u64 *page_table = (u64 *)gd->arch.tlb_addr;
@@ -74,8 +80,8 @@ void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
debug("%s: start=%pa, size=%zu, option=0x%x\n", __func__, &start, size,
option);
#endif
- for (upto = start; upto < end; upto++)
- set_section_dcache(upto, option);
+ for (upto = start; upto < end; upto++, phys += MMU_SECTION_SIZE)
+ set_section_phys(upto, phys, option);
/*
* Make sure range is cache line aligned
@@ -90,6 +96,12 @@ void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
mmu_page_table_flush(startpt, stoppt);
}
+void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
+ enum dcache_option option)
+{
+ mmu_set_region_dcache_behaviour_phys(start, start, size, option);
+}
+
__weak void dram_bank_mmu_setup(int bank)
{
bd_t *bd = gd->bd;
diff --git a/arch/arm/mach-bcm283x/Kconfig b/arch/arm/mach-bcm283x/Kconfig
index e6eb904e7f..b3287ce8bc 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 c4ae39852f..4ccaf69693 100644
--- a/arch/arm/mach-bcm283x/include/mach/base.h
+++ b/arch/arm/mach-bcm283x/include/mach/base.h
@@ -8,4 +8,12 @@
extern unsigned long rpi_bcm283x_base;
+#ifdef CONFIG_ARMV7_LPAE
+#ifdef CONFIG_TARGET_RPI_4_32B
+#include <addr_map.h>
+#define phys_to_virt addrmap_phys_to_virt
+#define virt_to_phys addrmap_virt_to_phys
+#endif
+#endif
+
#endif
diff --git a/arch/arm/mach-bcm283x/include/mach/mbox.h b/arch/arm/mach-bcm283x/include/mach/mbox.h
index 60e226ce1d..2ae2d3d97c 100644
--- a/arch/arm/mach-bcm283x/include/mach/mbox.h
+++ b/arch/arm/mach-bcm283x/include/mach/mbox.h
@@ -491,6 +491,19 @@ struct bcm2835_mbox_tag_set_palette {
} body;
};
+#define BCM2835_MBOX_TAG_NOTIFY_XHCI_RESET 0x00030058
+
+struct bcm2835_mbox_tag_pci_dev_addr {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ u32 dev_addr;
+ } req;
+ struct {
+ } resp;
+ } body;
+};
+
/*
* Pass a raw u32 message to the VC, and receive a raw u32 back.
*
diff --git a/arch/arm/mach-bcm283x/include/mach/msg.h b/arch/arm/mach-bcm283x/include/mach/msg.h
index 4afb08631b..e45c1bf010 100644
--- a/arch/arm/mach-bcm283x/include/mach/msg.h
+++ b/arch/arm/mach-bcm283x/include/mach/msg.h
@@ -48,4 +48,11 @@ int bcm2835_set_video_params(int *widthp, int *heightp, int depth_bpp,
int pixel_order, int alpha_mode, ulong *fb_basep,
ulong *fb_sizep, int *pitchp);
+/**
+ * bcm2711_load_vl805_firmware() - get vl805's firmware loaded
+ *
+ * @return 0 if OK, -EIO on error
+ */
+int bcm2711_notify_vl805_reset(void);
+
#endif
diff --git a/arch/arm/mach-bcm283x/init.c b/arch/arm/mach-bcm283x/init.c
index f4d00d892d..f2a5411623 100644
--- a/arch/arm/mach-bcm283x/init.c
+++ b/arch/arm/mach-bcm283x/init.c
@@ -12,10 +12,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 MEM_MAP_MAX_ENTRIES (4)
+
+static struct mm_region bcm283x_mem_map[MEM_MAP_MAX_ENTRIES] = {
{
.virt = 0x00000000UL,
.phys = 0x00000000UL,
@@ -35,11 +40,11 @@ static struct mm_region bcm283x_mem_map[] = {
}
};
-static struct mm_region bcm2711_mem_map[] = {
+static struct mm_region bcm2711_mem_map[MEM_MAP_MAX_ENTRIES] = {
{
.virt = 0x00000000UL,
.phys = 0x00000000UL,
- .size = 0xfe000000UL,
+ .size = 0xfc000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
}, {
@@ -50,6 +55,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,
}
@@ -72,7 +84,7 @@ static void _rpi_update_mem_map(struct mm_region *pd)
{
int i;
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < MEM_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;
@@ -134,6 +146,27 @@ int mach_cpu_init(void)
}
#ifdef CONFIG_ARMV7_LPAE
+#ifdef CONFIG_TARGET_RPI_4_32B
+#define BCM2711_RPI4_PCIE_XHCI_MMIO_VIRT 0xff800000UL
+#include <addr_map.h>
+#include <asm/system.h>
+
+void init_addr_map(void)
+{
+ mmu_set_region_dcache_behaviour_phys(BCM2711_RPI4_PCIE_XHCI_MMIO_VIRT,
+ BCM2711_RPI4_PCIE_XHCI_MMIO_PHYS,
+ BCM2711_RPI4_PCIE_XHCI_MMIO_SIZE,
+ DCACHE_OFF);
+
+ /* identity mapping for 0..BCM2711_RPI4_PCIE_XHCI_MMIO_VIRT */
+ addrmap_set_entry(0, 0, BCM2711_RPI4_PCIE_XHCI_MMIO_VIRT, 0);
+ /* XHCI MMIO on PCIe at BCM2711_RPI4_PCIE_XHCI_MMIO_VIRT */
+ addrmap_set_entry(BCM2711_RPI4_PCIE_XHCI_MMIO_VIRT,
+ BCM2711_RPI4_PCIE_XHCI_MMIO_PHYS,
+ BCM2711_RPI4_PCIE_XHCI_MMIO_SIZE, 1);
+}
+#endif
+
void enable_caches(void)
{
dcache_enable();
diff --git a/arch/arm/mach-bcm283x/msg.c b/arch/arm/mach-bcm283x/msg.c
index 94b75283f8..347aece3cd 100644
--- a/arch/arm/mach-bcm283x/msg.c
+++ b/arch/arm/mach-bcm283x/msg.c
@@ -7,6 +7,7 @@
#include <memalign.h>
#include <phys2bus.h>
#include <asm/arch/mbox.h>
+#include <linux/delay.h>
struct msg_set_power_state {
struct bcm2835_mbox_hdr hdr;
@@ -40,6 +41,12 @@ struct msg_setup {
u32 end_tag;
};
+struct msg_notify_vl805_reset {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_pci_dev_addr dev_addr;
+ u32 end_tag;
+};
+
int bcm2835_power_on_module(u32 module)
{
ALLOC_CACHE_ALIGN_BUFFER(struct msg_set_power_state, msg_pwr, 1);
@@ -151,3 +158,42 @@ int bcm2835_set_video_params(int *widthp, int *heightp, int depth_bpp,
return 0;
}
+
+/*
+ * On the Raspberry Pi 4, after a PCI reset, VL805's (the xHCI chip) firmware
+ * may either be loaded directly from an EEPROM or, if not present, by the
+ * SoC's VideoCore. This informs VideoCore that VL805 needs its firmware
+ * loaded.
+ */
+int bcm2711_notify_vl805_reset(void)
+{
+ ALLOC_CACHE_ALIGN_BUFFER(struct msg_notify_vl805_reset,
+ msg_notify_vl805_reset, 1);
+ int ret;
+
+ BCM2835_MBOX_INIT_HDR(msg_notify_vl805_reset);
+ BCM2835_MBOX_INIT_TAG(&msg_notify_vl805_reset->dev_addr,
+ NOTIFY_XHCI_RESET);
+
+ /*
+ * The pci device address is expected like this:
+ *
+ * PCI_BUS << 20 | PCI_SLOT << 15 | PCI_FUNC << 12
+ *
+ * But since RPi4's PCIe setup is hardwired, we know the address in
+ * advance.
+ */
+ msg_notify_vl805_reset->dev_addr.body.req.dev_addr = 0x100000;
+
+ ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN,
+ &msg_notify_vl805_reset->hdr);
+ if (ret) {
+ printf("bcm2711: Faild to load vl805's firmware, %d\n", ret);
+ return -EIO;
+ }
+
+ udelay(200);
+
+ return 0;
+}
+