diff options
-rw-r--r-- | arch/arm/mach-bcm283x/include/mach/base.h | 5 | ||||
-rw-r--r-- | arch/arm/mach-bcm283x/include/mach/mbox.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-bcm283x/include/mach/sdhci.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-bcm283x/include/mach/timer.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-bcm283x/include/mach/wdog.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-bcm283x/init.c | 74 | ||||
-rw-r--r-- | board/raspberrypi/rpi/rpi.c | 22 | ||||
-rw-r--r-- | configs/rpi_arm64_defconfig | 3 | ||||
-rw-r--r-- | drivers/mmc/bcmstb_sdhci.c | 64 | ||||
-rw-r--r-- | drivers/video/bcm2835.c | 18 |
10 files changed, 171 insertions, 27 deletions
diff --git a/arch/arm/mach-bcm283x/include/mach/base.h b/arch/arm/mach-bcm283x/include/mach/base.h index 4ccaf69..6de99e7 100644 --- a/arch/arm/mach-bcm283x/include/mach/base.h +++ b/arch/arm/mach-bcm283x/include/mach/base.h @@ -6,7 +6,10 @@ #ifndef _BCM283x_BASE_H_ #define _BCM283x_BASE_H_ -extern unsigned long rpi_bcm283x_base; +extern unsigned long rpi_mbox_base; +extern unsigned long rpi_timer_base; +extern unsigned long rpi_sdhci_base; +extern unsigned long rpi_wdog_base; #ifdef CONFIG_ARMV7_LPAE #ifdef CONFIG_TARGET_RPI_4_32B diff --git a/arch/arm/mach-bcm283x/include/mach/mbox.h b/arch/arm/mach-bcm283x/include/mach/mbox.h index 490664f..35d4e2f 100644 --- a/arch/arm/mach-bcm283x/include/mach/mbox.h +++ b/arch/arm/mach-bcm283x/include/mach/mbox.h @@ -38,8 +38,7 @@ /* Raw mailbox HW */ -#define BCM2835_MBOX_PHYSADDR ({ BUG_ON(!rpi_bcm283x_base); \ - rpi_bcm283x_base + 0x0000b880; }) +#define BCM2835_MBOX_PHYSADDR rpi_mbox_base struct bcm2835_mbox_regs { u32 read; diff --git a/arch/arm/mach-bcm283x/include/mach/sdhci.h b/arch/arm/mach-bcm283x/include/mach/sdhci.h index 7323690..e837c67 100644 --- a/arch/arm/mach-bcm283x/include/mach/sdhci.h +++ b/arch/arm/mach-bcm283x/include/mach/sdhci.h @@ -8,8 +8,7 @@ #include <asm/arch/base.h> -#define BCM2835_SDHCI_PHYSADDR ({ BUG_ON(!rpi_bcm283x_base); \ - rpi_bcm283x_base + 0x00300000; }) +#define BCM2835_SDHCI_PHYSADDR rpi_sdhci_base int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq); diff --git a/arch/arm/mach-bcm283x/include/mach/timer.h b/arch/arm/mach-bcm283x/include/mach/timer.h index 5567dbd..60500a2 100644 --- a/arch/arm/mach-bcm283x/include/mach/timer.h +++ b/arch/arm/mach-bcm283x/include/mach/timer.h @@ -11,8 +11,7 @@ #include <linux/bug.h> #endif -#define BCM2835_TIMER_PHYSADDR ({ BUG_ON(!rpi_bcm283x_base); \ - rpi_bcm283x_base + 0x00003000; }) +#define BCM2835_TIMER_PHYSADDR rpi_timer_base #define BCM2835_TIMER_CS_M3 (1 << 3) #define BCM2835_TIMER_CS_M2 (1 << 2) diff --git a/arch/arm/mach-bcm283x/include/mach/wdog.h b/arch/arm/mach-bcm283x/include/mach/wdog.h index 9942666..b950560 100644 --- a/arch/arm/mach-bcm283x/include/mach/wdog.h +++ b/arch/arm/mach-bcm283x/include/mach/wdog.h @@ -8,8 +8,7 @@ #include <asm/arch/base.h> -#define BCM2835_WDOG_PHYSADDR ({ BUG_ON(!rpi_bcm283x_base); \ - rpi_bcm283x_base + 0x00100000; }) +#define BCM2835_WDOG_PHYSADDR rpi_wdog_base struct bcm2835_wdog_regs { u32 unknown0[7]; diff --git a/arch/arm/mach-bcm283x/init.c b/arch/arm/mach-bcm283x/init.c index 7265faf..016bc1e 100644 --- a/arch/arm/mach-bcm283x/init.c +++ b/arch/arm/mach-bcm283x/init.c @@ -68,6 +68,36 @@ static struct mm_region bcm2711_mem_map[MEM_MAP_MAX_ENTRIES] = { } }; +static struct mm_region bcm2712_mem_map[MEM_MAP_MAX_ENTRIES] = { + { + /* First 1GB of DRAM */ + .virt = 0x00000000UL, + .phys = 0x00000000UL, + .size = 0x40000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, { + /* Beginning of AXI bus where uSD controller lives */ + .virt = 0x1000000000UL, + .phys = 0x1000000000UL, + .size = 0x0002000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* SoC bus */ + .virt = 0x107c000000UL, + .phys = 0x107c000000UL, + .size = 0x0004000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* List terminator */ + 0, + } +}; + struct mm_region *mem_map = bcm283x_mem_map; /* @@ -78,6 +108,7 @@ static const struct udevice_id board_ids[] = { { .compatible = "brcm,bcm2837", .data = (ulong)&bcm283x_mem_map}, { .compatible = "brcm,bcm2838", .data = (ulong)&bcm2711_mem_map}, { .compatible = "brcm,bcm2711", .data = (ulong)&bcm2711_mem_map}, + { .compatible = "brcm,bcm2712", .data = (ulong)&bcm2712_mem_map}, { }, }; @@ -115,7 +146,11 @@ static void rpi_update_mem_map(void) static void rpi_update_mem_map(void) {} #endif -unsigned long rpi_bcm283x_base = 0x3f000000; +/* Default bcm283x devices addresses */ +unsigned long rpi_mbox_base = 0x3f00b880; +unsigned long rpi_sdhci_base = 0x3f300000; +unsigned long rpi_wdog_base = 0x3f100000; +unsigned long rpi_timer_base = 0x3f003000; int arch_cpu_init(void) { @@ -126,22 +161,45 @@ int arch_cpu_init(void) int mach_cpu_init(void) { - int ret, soc_offset; + int ret, soc, offset; u64 io_base, size; rpi_update_mem_map(); /* Get IO base from device tree */ - soc_offset = fdt_path_offset(gd->fdt_blob, "/soc"); - if (soc_offset < 0) - return soc_offset; + soc = fdt_path_offset(gd->fdt_blob, "/soc"); + if (soc < 0) + return soc; - ret = fdt_read_range((void *)gd->fdt_blob, soc_offset, 0, NULL, - &io_base, &size); + ret = fdt_read_range((void *)gd->fdt_blob, soc, 0, NULL, + &io_base, &size); if (ret) return ret; - rpi_bcm283x_base = io_base; + rpi_mbox_base = io_base + 0x00b880; + rpi_sdhci_base = io_base + 0x300000; + rpi_wdog_base = io_base + 0x100000; + rpi_timer_base = io_base + 0x003000; + + offset = fdt_node_offset_by_compatible(gd->fdt_blob, soc, + "brcm,bcm2835-mbox"); + if (offset > soc) + rpi_mbox_base = fdt_get_base_address(gd->fdt_blob, offset); + + offset = fdt_node_offset_by_compatible(gd->fdt_blob, soc, + "brcm,bcm2835-sdhci"); + if (offset > soc) + rpi_sdhci_base = fdt_get_base_address(gd->fdt_blob, offset); + + offset = fdt_node_offset_by_compatible(gd->fdt_blob, soc, + "brcm,bcm2835-system-timer"); + if (offset > soc) + rpi_timer_base = fdt_get_base_address(gd->fdt_blob, offset); + + offset = fdt_node_offset_by_compatible(gd->fdt_blob, soc, + "brcm,bcm2712-pm"); + if (offset > soc) + rpi_wdog_base = fdt_get_base_address(gd->fdt_blob, offset); return 0; } diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c index cd823ad..2851ebc 100644 --- a/board/raspberrypi/rpi/rpi.c +++ b/board/raspberrypi/rpi/rpi.c @@ -171,6 +171,11 @@ static const struct rpi_model rpi_models_new_scheme[] = { DTB_DIR "bcm2711-rpi-cm4.dtb", true, }, + [0x17] = { + "5 Model B", + DTB_DIR "bcm2712-rpi-5-b.dtb", + true, + }, }; static const struct rpi_model rpi_models_old_scheme[] = { @@ -429,15 +434,27 @@ static void get_board_revision(void) int ret; const struct rpi_model *models; uint32_t models_count; + ofnode node; BCM2835_MBOX_INIT_HDR(msg); BCM2835_MBOX_INIT_TAG(&msg->get_board_rev, GET_BOARD_REV); ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr); if (ret) { - printf("bcm2835: Could not query board revision\n"); /* Ignore error; not critical */ - return; + node = ofnode_path("/system"); + if (!ofnode_valid(node)) { + printf("bcm2835: Could not find /system node\n"); + return; + } + + ret = ofnode_read_u32(node, "linux,revision", &revision); + if (ret) { + printf("bcm2835: Could not find linux,revision\n"); + return; + } + } else { + revision = msg->get_board_rev.body.resp.rev; } /* @@ -451,7 +468,6 @@ static void get_board_revision(void) * http://www.raspberrypi.org/forums/viewtopic.php?f=63&t=98367&start=250 * http://www.raspberrypi.org/forums/viewtopic.php?f=31&t=20594 */ - revision = msg->get_board_rev.body.resp.rev; if (revision & 0x800000) { rev_scheme = 1; rev_type = (revision >> 4) & 0xff; diff --git a/configs/rpi_arm64_defconfig b/configs/rpi_arm64_defconfig index 08bb30b..e4c4aef 100644 --- a/configs/rpi_arm64_defconfig +++ b/configs/rpi_arm64_defconfig @@ -1,6 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_BCM283X=y -CONFIG_TEXT_BASE=0x00080000 +CONFIG_POSITION_INDEPENDENT=y CONFIG_TARGET_RPI_ARM64=y CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x7fffe30 @@ -33,6 +33,7 @@ CONFIG_BCM2835_GPIO=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_SDMA=y CONFIG_MMC_SDHCI_BCM2835=y +CONFIG_MMC_SDHCI_BCMSTB=y CONFIG_BCMGENET=y CONFIG_PCI_BRCMSTB=y CONFIG_PINCTRL=y diff --git a/drivers/mmc/bcmstb_sdhci.c b/drivers/mmc/bcmstb_sdhci.c index dc96818..49846ad 100644 --- a/drivers/mmc/bcmstb_sdhci.c +++ b/drivers/mmc/bcmstb_sdhci.c @@ -38,15 +38,52 @@ */ #define BCMSTB_SDHCI_MINIMUM_CLOCK_FREQUENCY 400000 -/* - * This driver has only been tested with eMMC devices; SD devices may - * not work. - */ +#define SDIO_CFG_CTRL 0x0 +#define SDIO_CFG_CTRL_SDCD_N_TEST_EN BIT(31) +#define SDIO_CFG_CTRL_SDCD_N_TEST_LEV BIT(30) + +#define SDIO_CFG_SD_PIN_SEL 0x44 +#define SDIO_CFG_SD_PIN_SEL_MASK 0x3 +#define SDIO_CFG_SD_PIN_SEL_CARD BIT(1) + struct sdhci_bcmstb_plat { struct mmc_config cfg; struct mmc mmc; }; +struct sdhci_brcmstb_dev_priv { + int (*init)(struct udevice *dev); +}; + +static int sdhci_brcmstb_init_2712(struct udevice *dev) +{ + struct sdhci_host *host = dev_get_priv(dev); + void *cfg_regs; + u32 reg; + + /* Map in the non-standard CFG registers */ + cfg_regs = dev_remap_addr_name(dev, "cfg"); + if (!cfg_regs) + return -ENOENT; + + if ((host->mmc->host_caps & MMC_CAP_NONREMOVABLE) || + (host->mmc->host_caps & MMC_CAP_NEEDS_POLL)) { + /* Force presence */ + reg = readl(cfg_regs + SDIO_CFG_CTRL); + reg &= ~SDIO_CFG_CTRL_SDCD_N_TEST_LEV; + reg |= SDIO_CFG_CTRL_SDCD_N_TEST_EN; + writel(reg, cfg_regs + SDIO_CFG_CTRL); + } else { + /* Enable card detection line */ + reg = readl(cfg_regs + SDIO_CFG_SD_PIN_SEL); + reg &= ~SDIO_CFG_SD_PIN_SEL_MASK; + reg |= SDIO_CFG_SD_PIN_SEL_CARD; + writel(reg, cfg_regs + SDIO_CFG_SD_PIN_SEL); + } + + return 0; +} + static int sdhci_bcmstb_bind(struct udevice *dev) { struct sdhci_bcmstb_plat *plat = dev_get_plat(dev); @@ -54,14 +91,20 @@ static int sdhci_bcmstb_bind(struct udevice *dev) return sdhci_bind(dev, &plat->mmc, &plat->cfg); } +/* No specific SDHCI operations are required */ +static const struct sdhci_ops bcmstb_sdhci_ops = { 0 }; + static int sdhci_bcmstb_probe(struct udevice *dev) { struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct sdhci_bcmstb_plat *plat = dev_get_plat(dev); struct sdhci_host *host = dev_get_priv(dev); + struct sdhci_brcmstb_dev_priv *dev_priv; fdt_addr_t base; int ret; + dev_priv = (struct sdhci_brcmstb_dev_priv *)dev_get_driver_data(dev); + base = dev_read_addr(dev); if (base == FDT_ADDR_T_NONE) return -EINVAL; @@ -75,6 +118,8 @@ static int sdhci_bcmstb_probe(struct udevice *dev) host->mmc = &plat->mmc; host->mmc->dev = dev; + host->ops = &bcmstb_sdhci_ops; + ret = sdhci_setup_cfg(&plat->cfg, host, BCMSTB_SDHCI_MAXIMUM_CLOCK_FREQUENCY, BCMSTB_SDHCI_MINIMUM_CLOCK_FREQUENCY); @@ -84,10 +129,21 @@ static int sdhci_bcmstb_probe(struct udevice *dev) upriv->mmc = &plat->mmc; host->mmc->priv = host; + if (dev_priv && dev_priv->init) { + ret = dev_priv->init(dev); + if (ret) + return ret; + } + return sdhci_probe(dev); } +static const struct sdhci_brcmstb_dev_priv match_priv_2712 = { + .init = sdhci_brcmstb_init_2712, +}; + static const struct udevice_id sdhci_bcmstb_match[] = { + { .compatible = "brcm,bcm2712-sdhci", .data = (ulong)&match_priv_2712 }, { .compatible = "brcm,bcm7425-sdhci" }, { .compatible = "brcm,sdhci-brcmstb" }, { } diff --git a/drivers/video/bcm2835.c b/drivers/video/bcm2835.c index 1494252..63efa76 100644 --- a/drivers/video/bcm2835.c +++ b/drivers/video/bcm2835.c @@ -16,7 +16,7 @@ static int bcm2835_video_probe(struct udevice *dev) struct video_uc_plat *plat = dev_get_uclass_plat(dev); struct video_priv *uc_priv = dev_get_uclass_priv(dev); int ret; - int w, h, pitch; + int w, h, pitch, bpp; ulong fb_base, fb_size, fb_start, fb_end; debug("bcm2835: Query resolution...\n"); @@ -41,9 +41,23 @@ static int bcm2835_video_probe(struct udevice *dev) DCACHE_WRITEBACK); video_set_flush_dcache(dev, true); + bpp = pitch / w; + switch (bpp) { + case 2: + uc_priv->bpix = VIDEO_BPP16; + break; + case 4: + uc_priv->bpix = VIDEO_BPP32; + break; + default: + printf("bcm2835: unexpected bpp %d, pitch %d, width %d\n", + bpp, pitch, w); + uc_priv->bpix = VIDEO_BPP32; + break; + } + uc_priv->xsize = w; uc_priv->ysize = h; - uc_priv->bpix = VIDEO_BPP32; plat->base = fb_base; plat->size = fb_size; |