xunlong-orangepi-zero3: new device

Part-of: <https://gitlab.postmarketos.org/postmarketOS/pmaports/-/merge_requests/7325>
This commit is contained in:
Pavel Zakopaylo 2025-11-09 21:27:12 +11:00 committed by The Friendly Merge Bot
parent 3deafab416
commit f34692d224
No known key found for this signature in database
13 changed files with 1890 additions and 0 deletions

View file

@ -0,0 +1,53 @@
# Reference: <https://postmarketos.org/devicepkg>
pkgname=device-xunlong-orangepi-zero3
pkgdesc="Xunlong Orange Pi Zero 3"
pkgver=1
pkgrel=0
url="https://postmarketos.org"
license="MIT"
arch="aarch64"
options="!check !archcheck"
depends="
linux-postmarketos-allwinner
postmarketos-base
"
makedepends="devicepkg-dev"
_pmb_select="$pkgname-u-boot-select"
subpackages="
$pkgname-u-boot-select-sunxi:u_boot_sunxi
$pkgname-u-boot-select-orangepi-zero3:u_boot_orangepi_zero3
"
source="deviceinfo"
build() {
devicepkg_build $startdir $pkgname
}
package() {
depends="$depends $pkgname-u-boot-select"
devicepkg_package $startdir $pkgname
}
u_boot_sunxi() {
pkgdesc="Use upstream U-Boot (u-boot-sunxi) (WARNING: does not support 1.5 GB models)"
depends="u-boot-sunxi"
provides="$pkgname-u-boot-select"
provider_priority=1
mkdir -p $subpkgdir
}
u_boot_orangepi_zero3() {
pkgdesc="Use downstream U-Boot package specifically for the Orange Pi Zero 3"
depends="u-boot-xunlong-orangepi-zero3"
provides="$pkgname-u-boot-select"
provider_priority=100
mkdir -p $subpkgdir
}
sha512sums="
2d95715655ec9569b071227345bc59eedf129f92fc0b77f0bdaf3e47728be94a3f389193a153a3da3385c96a8c3dcc11b034e98414da0c3f06c9d367f807dd23 deviceinfo
"

View file

@ -0,0 +1,25 @@
# Reference: <https://postmarketos.org/deviceinfo>
# Please use double quotes only. You can source this file in shell
# scripts.
deviceinfo_format_version="0"
deviceinfo_name="Xunlong Orange Pi Zero 3"
deviceinfo_manufacturer="Xunlong"
deviceinfo_codename="xunlong-orangepi-zero3"
deviceinfo_year="2023"
deviceinfo_dtb="allwinner/sun50i-h618-orangepi-zero3.dtb"
deviceinfo_arch="aarch64"
# Device related
deviceinfo_drm="true"
deviceinfo_chassis="embedded"
deviceinfo_external_storage="true"
deviceinfo_screen_width="1920"
deviceinfo_screen_height="1080"
deviceinfo_getty="ttyS0;115200"
# Bootloader related
deviceinfo_partition_type="msdos"
deviceinfo_sd_embed_firmware="u-boot/orangepi_zero3/u-boot-sunxi-with-spl.bin:8"
deviceinfo_generate_extlinux_config="true"
deviceinfo_kernel_cmdline="rw console=tty0 console=ttyS0,115200 earlycon no_console_suspend panic=10 consoleblank=0 loglevel=1"

View file

@ -0,0 +1,76 @@
From 3e51ab767091957ccfeb4ba778dd546234044a4b Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@gmail.com>
Date: Sun, 9 Mar 2025 07:31:42 +0100
Subject: sunxi: h616: dram: Rework size detection
Since there is quite a few possible DRAM configurations in terms of bus
width, rank and rows and columns count, size detection algorithm must be
very careful not to test combination which would be bigger than H616 is
actually capable of handling.
Ideally, we should always detect memory aliasing, even for 4 GB memory
size, which is the maximum amount of memory that H616 is capable of
handling. For this reason, we have to configure minimum amount of
supported rows when testing for columns and vice versa. This way test
code will never step out of 4 GB boundary.
While at it, check for 17 rows maximum. This aligns code with BSP DRAM
driver. There is probably no such configuration which would make sense
with 4 GB memory.
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
arch/arm/mach-sunxi/dram_sun50i_h616.c | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c
index b3554cc64bf5..6f84e59e39cd 100644
--- a/arch/arm/mach-sunxi/dram_sun50i_h616.c
+++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c
@@ -1363,7 +1363,7 @@ static void mctl_auto_detect_rank_width(const struct dram_para *para,
static void mctl_auto_detect_dram_size(const struct dram_para *para,
struct dram_config *config)
{
- unsigned int shift;
+ unsigned int shift, cols, rows;
/* max. config for columns, but not rows */
config->cols = 11;
@@ -1373,23 +1373,27 @@ static void mctl_auto_detect_dram_size(const struct dram_para *para,
shift = config->bus_full_width + 1;
/* detect column address bits */
- for (config->cols = 8; config->cols < 11; config->cols++) {
- if (mctl_mem_matches(1ULL << (config->cols + shift)))
+ for (cols = 8; cols < 11; cols++) {
+ if (mctl_mem_matches(1ULL << (cols + shift)))
break;
}
- debug("detected %u columns\n", config->cols);
+ debug("detected %u columns\n", cols);
/* reconfigure to make sure that all active rows are accessible */
- config->rows = 18;
+ config->cols = 8;
+ config->rows = 17;
mctl_core_init(para, config);
/* detect row address bits */
shift = config->bus_full_width + 4 + config->cols;
- for (config->rows = 13; config->rows < 18; config->rows++) {
- if (mctl_mem_matches(1ULL << (config->rows + shift)))
+ for (rows = 13; rows < 17; rows++) {
+ if (mctl_mem_matches(1ULL << (rows + shift)))
break;
}
- debug("detected %u rows\n", config->rows);
+ debug("detected %u rows\n", rows);
+
+ config->cols = cols;
+ config->rows = rows;
}
static unsigned long mctl_calc_size(const struct dram_config *config)
--
2.35.3

View file

@ -0,0 +1,121 @@
From c13c238328e1e4909330b96fba51705eba917748 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@gmail.com>
Date: Sun, 9 Mar 2025 07:31:43 +0100
Subject: sunxi: H616: dram: Improve address wrapping detection
It turns out that checking just one write is not enough. Due to
unexplained reasons scan procedure detected double the size.
By making 16 dword writes and comparisons that never happens.
New procedure is also inverted. Instead of writing two different values
to base address and some offset and then reading both and comparing
values, simplify this by writing pattern at the base address and then
search for this pattern at some offset.
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
arch/arm/mach-sunxi/dram_sun50i_h616.c | 58 +++++++++++++++++++++++++-
1 file changed, 56 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c
index 6f84e59e39cd..cd9d321a0185 100644
--- a/arch/arm/mach-sunxi/dram_sun50i_h616.c
+++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c
@@ -1360,38 +1360,92 @@ static void mctl_auto_detect_rank_width(const struct dram_para *para,
panic("This DRAM setup is currently not supported.\n");
}
+static void mctl_write_pattern(void)
+{
+ unsigned int i;
+ u32 *ptr, val;
+
+ ptr = (u32 *)CFG_SYS_SDRAM_BASE;
+ for (i = 0; i < 16; ptr++, i++) {
+ if (i & 1)
+ val = ~(ulong)ptr;
+ else
+ val = (ulong)ptr;
+ writel(val, ptr);
+ }
+}
+
+static bool mctl_check_pattern(ulong offset)
+{
+ unsigned int i;
+ u32 *ptr, val;
+
+ ptr = (u32 *)CFG_SYS_SDRAM_BASE;
+ for (i = 0; i < 16; ptr++, i++) {
+ if (i & 1)
+ val = ~(ulong)ptr;
+ else
+ val = (ulong)ptr;
+ if (val != *(ptr + offset / 4))
+ return false;
+ }
+
+ return true;
+}
+
static void mctl_auto_detect_dram_size(const struct dram_para *para,
struct dram_config *config)
{
unsigned int shift, cols, rows;
+ u32 buffer[16];
/* max. config for columns, but not rows */
config->cols = 11;
config->rows = 13;
mctl_core_init(para, config);
+ /*
+ * Store content so it can be restored later. This is important
+ * if controller was already initialized and holds any data
+ * which is important for restoring system.
+ */
+ memcpy(buffer, (u32 *)CFG_SYS_SDRAM_BASE, sizeof(buffer));
+
+ mctl_write_pattern();
+
shift = config->bus_full_width + 1;
/* detect column address bits */
for (cols = 8; cols < 11; cols++) {
- if (mctl_mem_matches(1ULL << (cols + shift)))
+ if (mctl_check_pattern(1ULL << (cols + shift)))
break;
}
debug("detected %u columns\n", cols);
+ /* restore data */
+ memcpy((u32 *)CFG_SYS_SDRAM_BASE, buffer, sizeof(buffer));
+
/* reconfigure to make sure that all active rows are accessible */
config->cols = 8;
config->rows = 17;
mctl_core_init(para, config);
+ /* store data again as it might be moved */
+ memcpy(buffer, (u32 *)CFG_SYS_SDRAM_BASE, sizeof(buffer));
+
+ mctl_write_pattern();
+
/* detect row address bits */
shift = config->bus_full_width + 4 + config->cols;
for (rows = 13; rows < 17; rows++) {
- if (mctl_mem_matches(1ULL << (rows + shift)))
+ if (mctl_check_pattern(1ULL << (rows + shift)))
break;
}
debug("detected %u rows\n", rows);
+ /* restore data again */
+ memcpy((u32 *)CFG_SYS_SDRAM_BASE, buffer, sizeof(buffer));
+
config->cols = cols;
config->rows = rows;
}
--
2.35.3

View file

@ -0,0 +1,116 @@
From e4768f280b975f8f5523d188350eb77cc55aad63 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@gmail.com>
Date: Sun, 9 Mar 2025 07:12:41 +0100
Subject: sunxi: mmc: Improve reset procedure
Cards should always be reset and threshold set. This fixes eMMC on H616.
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
drivers/mmc/sunxi_mmc.c | 28 ++++++++++++++++++++++------
drivers/mmc/sunxi_mmc.h | 15 +++++++++++++--
2 files changed, 35 insertions(+), 8 deletions(-)
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index 0b56d1405bee..335def4b9738 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -442,6 +442,26 @@ out:
return error;
}
+static void sunxi_mmc_reset(struct sunxi_mmc *regs)
+{
+ /* Reset controller */
+ writel(SUNXI_MMC_GCTRL_RESET, &regs->gctrl);
+ udelay(1000);
+
+ if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) || IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2)) {
+ /* Reset card */
+ writel(SUNXI_MMC_HWRST_ASSERT, &regs->hwrst);
+ udelay(10);
+ writel(SUNXI_MMC_HWRST_DEASSERT, &regs->hwrst);
+ udelay(300);
+
+ /* Setup FIFO R/W threshold. Needed on H616. */
+ writel(SUNXI_MMC_THLDC_READ_THLD(512) |
+ SUNXI_MMC_THLDC_WRITE_EN |
+ SUNXI_MMC_THLDC_READ_EN, &regs->thldc);
+ }
+}
+
/* non-DM code here is used by the (ARM) SPL only */
#if !CONFIG_IS_ENABLED(DM_MMC)
@@ -489,9 +509,7 @@ static int sunxi_mmc_core_init(struct mmc *mmc)
{
struct sunxi_mmc_priv *priv = mmc->priv;
- /* Reset controller */
- writel(SUNXI_MMC_GCTRL_RESET, &priv->reg->gctrl);
- udelay(1000);
+ sunxi_mmc_reset(priv->reg);
return 0;
}
@@ -684,9 +702,7 @@ static int sunxi_mmc_probe(struct udevice *dev)
upriv->mmc = &plat->mmc;
- /* Reset controller */
- writel(SUNXI_MMC_GCTRL_RESET, &priv->reg->gctrl);
- udelay(1000);
+ sunxi_mmc_reset(priv->reg);
return 0;
}
diff --git a/drivers/mmc/sunxi_mmc.h b/drivers/mmc/sunxi_mmc.h
index f4ae5a790c87..9d55904c213c 100644
--- a/drivers/mmc/sunxi_mmc.h
+++ b/drivers/mmc/sunxi_mmc.h
@@ -37,7 +37,9 @@ struct sunxi_mmc {
u32 res0; /* 0x54 reserved */
u32 a12a; /* 0x58 Auto command 12 argument */
u32 ntsr; /* 0x5c New timing set register */
- u32 res1[8];
+ u32 res1[6];
+ u32 hwrst; /* 0x78 Hardware Reset */
+ u32 res5;
u32 dmac; /* 0x80 internal DMA control */
u32 dlba; /* 0x84 internal DMA descr list base address */
u32 idst; /* 0x88 internal DMA status */
@@ -46,7 +48,8 @@ struct sunxi_mmc {
u32 cbda; /* 0x94 */
u32 res2[26];
#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
- u32 res3[17];
+ u32 thldc; /* 0x100 Threshold control */
+ u32 res3[16];
u32 samp_dl;
u32 res4[46];
#endif
@@ -123,6 +126,9 @@ struct sunxi_mmc {
#define SUNXI_MMC_NTSR_MODE_SEL_NEW (0x1 << 31)
+#define SUNXI_MMC_HWRST_ASSERT (0x0 << 0)
+#define SUNXI_MMC_HWRST_DEASSERT (0x1 << 0)
+
#define SUNXI_MMC_IDMAC_RESET (0x1 << 0)
#define SUNXI_MMC_IDMAC_FIXBURST (0x1 << 1)
#define SUNXI_MMC_IDMAC_ENABLE (0x1 << 7)
@@ -133,6 +139,11 @@ struct sunxi_mmc {
#define SUNXI_MMC_COMMON_CLK_GATE (1 << 16)
#define SUNXI_MMC_COMMON_RESET (1 << 18)
+#define SUNXI_MMC_THLDC_READ_EN (0x1 << 0)
+#define SUNXI_MMC_THLDC_BSY_CLR_INT_EN (0x1 << 1)
+#define SUNXI_MMC_THLDC_WRITE_EN (0x1 << 2)
+#define SUNXI_MMC_THLDC_READ_THLD(x) (((x) & 0xfff) << 16)
+
#define SUNXI_MMC_CAL_DL_SW_EN (0x1 << 7)
#endif /* _SUNXI_MMC_H */
--
2.35.3

View file

@ -0,0 +1,26 @@
From 202b992764421a6d96323c3abcdaa24e9082f53b Mon Sep 17 00:00:00 2001
From: leo <leo@localhost.localdomain>
Date: Sun, 15 Sep 2024 10:50:38 +0300
Subject: Add MACH_SUN8I_A83T to can calibrate
Add the A83T processor to the sunxi_mmc_can_calibrate
logic function for proper configuration.
---
drivers/mmc/sunxi_mmc.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index 335def4b9738..7fea7982a5d4 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -61,6 +61,7 @@ static bool sunxi_mmc_can_calibrate(void)
IS_ENABLED(CONFIG_MACH_SUN50I_H5) ||
IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2) ||
+ IS_ENABLED(CONFIG_MACH_SUN8I_A83T) ||
IS_ENABLED(CONFIG_MACH_SUN8I_R40);
}
--
2.35.3

View file

@ -0,0 +1,28 @@
From a34b6a50de81cc5cb1a82ea2196a198fb6719cb3 Mon Sep 17 00:00:00 2001
From: The-going <48602507+The-going@users.noreply.github.com>
Date: Tue, 1 Apr 2025 15:55:05 +0300
Subject: board: sunxi: The prefix is missing if we use OF_UPSTREAM
---
board/sunxi/board.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index c7a2205ed610..2797cf5e00da 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -826,7 +826,11 @@ int misc_init_r(void)
/* Set fdtfile to match the FIT configuration chosen in SPL. */
spl_dt_name = get_spl_dt_name();
if (spl_dt_name) {
+#ifdef CONFIG_OF_UPSTREAM
+ char *prefix = "";
+#else
char *prefix = IS_ENABLED(CONFIG_ARM64) ? "allwinner/" : "";
+#endif
char str[64];
snprintf(str, sizeof(str), "%s%s.dtb", prefix, spl_dt_name);
--
2.35.3

View file

@ -0,0 +1,671 @@
From 41657e210df86844b522e88cb1fba0239ea4bcd4 Mon Sep 17 00:00:00 2001
From: The-going <48602507+The-going@users.noreply.github.com>
Date: Wed, 2 Apr 2025 20:26:51 +0300
Subject: dts: upstream: arm64: sun50i-h616: sync with sunxi-6.12 kernel
---
.../src/arm64/allwinner/sun50i-h616.dtsi | 516 +++++++++++++++++-
1 file changed, 511 insertions(+), 5 deletions(-)
diff --git a/dts/upstream/src/arm64/allwinner/sun50i-h616.dtsi b/dts/upstream/src/arm64/allwinner/sun50i-h616.dtsi
index cdce3dcb8ec0..3fb5c6e25af4 100644
--- a/dts/upstream/src/arm64/allwinner/sun50i-h616.dtsi
+++ b/dts/upstream/src/arm64/allwinner/sun50i-h616.dtsi
@@ -7,8 +7,11 @@
#include <dt-bindings/clock/sun50i-h616-ccu.h>
#include <dt-bindings/clock/sun50i-h6-r-ccu.h>
#include <dt-bindings/clock/sun6i-rtc.h>
+#include <dt-bindings/clock/sun8i-de2.h>
+#include <dt-bindings/clock/sun8i-tcon-top.h>
#include <dt-bindings/reset/sun50i-h616-ccu.h>
#include <dt-bindings/reset/sun50i-h6-r-ccu.h>
+#include <dt-bindings/reset/sun8i-de2.h>
#include <dt-bindings/thermal/thermal.h>
/ {
@@ -94,18 +97,24 @@
};
};
+ de: display-engine {
+ compatible = "allwinner,sun50i-h6-display-engine";
+ allwinner,pipelines = <&mixer0>;
+ status = "disabled";
+ };
+
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
/*
- * 256 KiB reserved for Trusted Firmware-A (BL31).
+ * 512 KiB reserved for Trusted Firmware-A (BL31).
* This is added by BL31 itself, but some bootloaders fail
* to propagate this into the DTB handed to kernels.
*/
secmon@40000000 {
- reg = <0x0 0x40000000 0x0 0x40000>;
+ reg = <0x0 0x40000000 0x0 0x80000>;
no-map;
};
};
@@ -150,6 +159,65 @@
#size-cells = <1>;
ranges = <0x0 0x0 0x0 0x40000000>;
+ bus@1000000 {
+ compatible = "allwinner,sun50i-h616-de33",
+ "allwinner,sun50i-a64-de2";
+ reg = <0x1000000 0x400000>;
+ allwinner,sram = <&de3_sram 1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x1000000 0x400000>;
+
+ display_clocks: clock@8000 {
+ compatible = "allwinner,sun50i-h616-de33-clk";
+ reg = <0x8000 0x100>;
+ clocks = <&ccu CLK_DE>, <&ccu CLK_BUS_DE>;
+ clock-names = "mod", "bus";
+ resets = <&ccu RST_BUS_DE>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ mixer0: mixer@100000 {
+ compatible = "allwinner,sun50i-h616-de33-mixer-0";
+ reg = <0x100000 0x100000>,
+ <0x8100 0x40>,
+ <0x280000 0x20000>;
+ clocks = <&display_clocks CLK_BUS_MIXER0>,
+ <&display_clocks CLK_MIXER0>;
+ clock-names = "bus", "mod";
+ resets = <&display_clocks RST_MIXER0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mixer0_out: port@1 {
+ reg = <1>;
+
+ mixer0_out_tcon_top_mixer0: endpoint {
+ remote-endpoint = <&tcon_top_mixer0_in_mixer0>;
+ };
+ };
+ };
+ };
+ };
+
+ gpu: gpu@1800000 {
+ compatible = "allwinner,sun50i-h616-mali",
+ "arm,mali-bifrost";
+ reg = <0x1800000 0x40000>;
+ interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "job", "mmu", "gpu";
+ clocks = <&ccu CLK_GPU0>, <&ccu CLK_BUS_GPU>;
+ clock-names = "core", "bus";
+ power-domains = <&prcm_ppu 2>;
+ resets = <&ccu RST_BUS_GPU>;
+ status = "disabled";
+ };
+
crypto: crypto@1904000 {
compatible = "allwinner,sun50i-h616-crypto";
reg = <0x01904000 0x800>;
@@ -160,6 +228,17 @@
resets = <&ccu RST_BUS_CE>;
};
+ video-codec@1c0e000 {
+ compatible = "allwinner,sun50i-h616-video-engine";
+ reg = <0x01c0e000 0x2000>;
+ clocks = <&ccu CLK_BUS_VE>, <&ccu CLK_VE>,
+ <&ccu CLK_MBUS_VE>;
+ clock-names = "ahb", "mod", "ram";
+ resets = <&ccu RST_BUS_VE>;
+ interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
+ allwinner,sram = <&ve_sram 1>;
+ };
+
syscon: syscon@3000000 {
compatible = "allwinner,sun50i-h616-system-control";
reg = <0x03000000 0x1000>;
@@ -167,12 +246,44 @@
#size-cells = <1>;
ranges;
+ sram_a2: sram@100000 {
+ compatible = "mmio-sram";
+ reg = <0x00100000 0x18000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x00100000 0x18000>;
+
+ scpi_sram: scpi-sram@17c00 {
+ compatible = "arm,scp-shmem";
+ reg = <0x17c00 0x200>;
+ };
+ };
+
sram_c: sram@28000 {
compatible = "mmio-sram";
reg = <0x00028000 0x30000>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0x00028000 0x30000>;
+
+ de3_sram: sram-section@0 {
+ compatible = "allwinner,sun50i-h616-sram-c",
+ "allwinner,sun50i-a64-sram-c";
+ reg = <0x0000 0x1e000>;
+ };
+ };
+
+ sram_c1: sram@1a00000 {
+ compatible = "mmio-sram";
+ reg = <0x01a00000 0x200000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x01a00000 0x200000>;
+
+ ve_sram: sram-section@0 {
+ compatible = "allwinner,sun50i-h616-sram-c1";
+ reg = <0x000000 0x200000>;
+ };
};
};
@@ -248,16 +359,66 @@
drive-strength = <40>;
};
+ rmii_pins: rmii-pins {
+ pins = "PA0", "PA1", "PA2", "PA3", "PA4",
+ "PA5", "PA6", "PA7", "PA8", "PA9";
+ function = "emac1";
+ drive-strength = <40>;
+ };
+
i2c0_pins: i2c0-pins {
pins = "PI5", "PI6";
function = "i2c0";
};
+ /omit-if-no-ref/
+ i2c1_pi_pins: i2c1-pi-pins {
+ pins = "PI7", "PI8";
+ function = "i2c1";
+ };
+
+ /omit-if-no-ref/
+ i2c2_ph_pins: i2c2-ph-pins {
+ pins = "PH2", "PH3";
+ function = "i2c2";
+ };
+
+ /omit-if-no-ref/
+ i2c2_pi_pins: i2c2-pi-pins {
+ pins = "PI9", "PI10";
+ function = "i2c2";
+ };
+
+ i2c3_pa_pins: i2c3-pa-pins {
+ pins = "PA10", "PA11";
+ function = "i2c3";
+ bias-pull-up;
+ };
+
+ /omit-if-no-ref/
+ i2c3_pg_pins: i2c3-pg-pins {
+ pins = "PG17", "PG18";
+ function = "i2c3";
+ };
+
+ /omit-if-no-ref/
i2c3_ph_pins: i2c3-ph-pins {
pins = "PH4", "PH5";
function = "i2c3";
};
+ /omit-if-no-ref/
+ i2c4_pg_pins: i2c4-pg-pins {
+ pins = "PG15", "PG16";
+ function = "i2c4";
+ };
+
+ /omit-if-no-ref/
+ i2c4_ph_pins: i2c4-ph-pins {
+ pins = "PH6", "PH7";
+ function = "i2c4";
+ };
+
ir_rx_pin: ir-rx-pin {
pins = "PH10";
function = "ir_rx";
@@ -289,6 +450,48 @@
bias-pull-up;
};
+ /omit-if-no-ref/
+ pwm1_pg_pin: pwm1-pg-pin {
+ pins = "PG19";
+ function = "pwm1";
+ };
+
+ /omit-if-no-ref/
+ pwm1_ph_pin: pwm1-ph-pin {
+ pins = "PH3";
+ function = "pwm1";
+ };
+
+ /omit-if-no-ref/
+ pwm1_pi_pin: pwm1-pi-pin {
+ pins = "PI11";
+ function = "pwm1";
+ };
+
+ /omit-if-no-ref/
+ pwm2_ph_pin: pwm2-ph-pin {
+ pins = "PH2";
+ function = "pwm2";
+ };
+
+ /omit-if-no-ref/
+ pwm3_ph_pin: pwm3-ph-pin {
+ pins = "PH0";
+ function = "pwm3";
+ };
+
+ /omit-if-no-ref/
+ pwm4_ph_pin: pwm4-ph-pin {
+ pins = "PH1";
+ function = "pwm4";
+ };
+
+ pwm5_pin: pwm5-pin {
+ pins = "PA12";
+ function = "pwm5";
+ bias-pull-up;
+ };
+
/omit-if-no-ref/
spi0_pins: spi0-pins {
pins = "PC0", "PC2", "PC4";
@@ -313,6 +516,12 @@
function = "spi1";
};
+ /omit-if-no-ref/
+ spi1_cs1_pin: spi1-cs1-pin {
+ pins = "PH9";
+ function = "spi1";
+ };
+
spdif_tx_pin: spdif-tx-pin {
pins = "PH4";
function = "spdif";
@@ -335,6 +544,60 @@
function = "uart1";
};
+ /omit-if-no-ref/
+ uart2_pi_pins: uart2-pi-pins {
+ pins = "PI5", "PI6";
+ function = "uart2";
+ };
+
+ /omit-if-no-ref/
+ uart2_pg_pins: uart2-pg-pins {
+ pins = "PG15", "PG16";
+ function = "uart2";
+ };
+
+ /omit-if-no-ref/
+ uart2_pg_rts_cts_pins: uart2-pg-rts-cts-pins {
+ pins = "PG17", "PG18";
+ function = "uart2";
+ };
+
+ /omit-if-no-ref/
+ uart2_ph_pins: uart2-ph-pins {
+ pins = "PH5", "PH6";
+ function = "uart2";
+ };
+
+ /omit-if-no-ref/
+ uart2_ph_rts_cts_pins: uart2-ph-rts-cts-pins {
+ pins = "PH7", "PH8";
+ function = "uart2";
+ };
+
+ /omit-if-no-ref/
+ uart3_pi_pins: uart3-pi-pins {
+ pins = "PI9", "PI10";
+ function = "uart3";
+ };
+
+ /omit-if-no-ref/
+ uart4_pi_pins: uart4-pi-pins {
+ pins = "PI13", "PI14";
+ function = "uart4";
+ };
+
+ /omit-if-no-ref/
+ uart4_pi_rts_cts_pins: uart4-pi-rts-cts-pins {
+ pins = "PI15", "PI16";
+ function = "uart4";
+ };
+
+ /omit-if-no-ref/
+ uart5_pins: uart5-pins {
+ pins = "PH2", "PH3";
+ function = "uart5";
+ };
+
/omit-if-no-ref/
x32clk_fanout_pin: x32clk-fanout-pin {
pins = "PG10";
@@ -354,7 +617,8 @@
};
iommu: iommu@30f0000 {
- compatible = "allwinner,sun50i-h616-iommu";
+ compatible = "allwinner,sun50i-h616-iommu",
+ "allwinner,sun50i-h6-iommu";
reg = <0x030f0000 0x10000>;
interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_IOMMU>;
@@ -630,6 +894,25 @@
};
};
+ emac1: ethernet@5030000 {
+ compatible = "allwinner,sun50i-h616-emac";
+ syscon = <&syscon 1>;
+ reg = <0x05030000 0x10000>;
+ interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ resets = <&ccu RST_BUS_EMAC1>;
+ reset-names = "stmmaceth";
+ clocks = <&ccu CLK_BUS_EMAC1>;
+ clock-names = "stmmaceth";
+ status = "disabled";
+
+ mdio1: mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
gpadc: adc@5070000 {
compatible = "allwinner,sun50i-h616-gpadc",
"allwinner,sun20i-d1-gpadc";
@@ -685,14 +968,71 @@
reg = <0x05096000 0x31c>;
interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_AUDIO_CODEC>,
- <&ccu CLK_AUDIO_CODEC_1X>;
- clock-names = "apb", "codec";
+ <&ccu CLK_AUDIO_CODEC_1X>,
+ <&ccu CLK_AUDIO_CODEC_4X>;
+ clock-names = "apb", "audio-codec-1x", "audio-codec-4x";
resets = <&ccu RST_BUS_AUDIO_CODEC>;
dmas = <&dma 6>;
dma-names = "tx";
status = "disabled";
};
+ ahub_dam_plat:ahub_dam_plat@5097000 {
+ #sound-dai-cells = <0>;
+ /* sound card without pcm for hardware mix setting */
+ compatible = "allwinner,sunxi-snd-plat-ahub_dam";
+ reg = <0x05097000 0x1000>;
+ resets = <&ccu RST_BUS_AUDIO_HUB>;
+ clocks = <&ccu CLK_AUDIO_CODEC_1X>,
+ <&ccu CLK_AUDIO_CODEC_4X>,
+ <&ccu CLK_AUDIO_HUB>,
+ <&ccu CLK_BUS_AUDIO_HUB>;
+ clock-names = "clk_pll_audio",
+ "clk_pll_audio_4x",
+ "clk_audio_hub",
+ "clk_bus_audio_hub";
+ status = "disabled";
+ };
+
+ ahub1_plat:ahub1_plat {
+ #sound-dai-cells = <0>;
+ compatible = "allwinner,sunxi-snd-plat-ahub";
+ apb_num = <1>; /* for dma port 4 */
+ dmas = <&dma 4>, <&dma 4>;
+ dma-names = "tx", "rx";
+ playback_cma = <128>;
+ capture_cma = <128>;
+ tx_fifo_size = <128>;
+ rx_fifo_size = <128>;
+ tdm_num = <1>;
+ tx_pin = <0>;
+ rx_pin = <0>;
+ status = "disabled";
+ };
+
+ ahub1_mach:ahub1_mach {
+ compatible = "allwinner,sunxi-snd-mach";
+ soundcard-mach,name = "HDMI";
+
+ soundcard-mach,format = "i2s";
+ soundcard-mach,frame-master = <&ahub1_cpu>;
+ soundcard-mach,bitclock-master = <&ahub1_cpu>;
+ /* soundcard-mach,frame-inversion; */
+ /* soundcard-mach,bitclock-inversion; */
+ soundcard-mach,slot-num = <2>;
+ soundcard-mach,slot-width = <32>;
+ status = "disabled";
+ ahub1_cpu: soundcard-mach,cpu {
+ sound-dai = <&ahub1_plat>;
+ soundcard-mach,pll-fs = <4>;
+ soundcard-mach,mclk-fs = <0>;
+ };
+
+ ahub1_codec: soundcard-mach,codec {
+ sound-dai = <&hdmi>;
+ };
+ };
+
usbotg: usb@5100000 {
compatible = "allwinner,sun50i-h616-musb",
"allwinner,sun8i-h3-musb";
@@ -853,6 +1193,147 @@
status = "disabled";
};
+ hdmi: hdmi@6000000 {
+ #sound-dai-cells = <0>;
+ compatible = "allwinner,sun50i-h616-dw-hdmi",
+ "allwinner,sun50i-h6-dw-hdmi";
+ reg = <0x06000000 0x10000>;
+ reg-io-width = <1>;
+ interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_HDMI>, <&ccu CLK_HDMI_SLOW>,
+ <&ccu CLK_HDMI>, <&ccu CLK_HDMI_CEC>,
+ <&ccu CLK_HDCP>, <&ccu CLK_BUS_HDCP>;
+ clock-names = "iahb", "isfr", "tmds", "cec", "hdcp",
+ "hdcp-bus";
+ resets = <&ccu RST_BUS_HDMI>, <&ccu RST_BUS_HDCP>;
+ reset-names = "ctrl", "hdcp";
+ phys = <&hdmi_phy>;
+ phy-names = "phy";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hdmi_in: port@0 {
+ reg = <0>;
+
+ hdmi_in_tcon_top: endpoint {
+ remote-endpoint = <&tcon_top_hdmi_out_hdmi>;
+ };
+ };
+
+ hdmi_out: port@1 {
+ reg = <1>;
+ };
+ };
+ };
+
+ hdmi_phy: hdmi-phy@6010000 {
+ compatible = "allwinner,sun50i-h616-hdmi-phy";
+ reg = <0x06010000 0x10000>;
+ clocks = <&ccu CLK_BUS_HDMI>, <&ccu CLK_HDMI_SLOW>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_HDMI_SUB>;
+ reset-names = "phy";
+ #phy-cells = <0>;
+ };
+
+ tcon_top: tcon-top@6510000 {
+ compatible = "allwinner,sun50i-h6-tcon-top";
+ reg = <0x06510000 0x1000>;
+ clocks = <&ccu CLK_BUS_TCON_TOP>,
+ <&ccu CLK_TCON_TV0>;
+ clock-names = "bus",
+ "tcon-tv0";
+ clock-output-names = "tcon-top-tv0";
+ resets = <&ccu RST_BUS_TCON_TOP>;
+ #clock-cells = <1>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_top_mixer0_in: port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ tcon_top_mixer0_in_mixer0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&mixer0_out_tcon_top_mixer0>;
+ };
+ };
+
+ tcon_top_mixer0_out: port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ tcon_top_mixer0_out_tcon_tv: endpoint@2 {
+ reg = <2>;
+ remote-endpoint = <&tcon_tv_in_tcon_top_mixer0>;
+ };
+ };
+
+ tcon_top_hdmi_in: port@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+
+ tcon_top_hdmi_in_tcon_tv: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon_tv_out_tcon_top>;
+ };
+ };
+
+ tcon_top_hdmi_out: port@5 {
+ reg = <5>;
+
+ tcon_top_hdmi_out_hdmi: endpoint {
+ remote-endpoint = <&hdmi_in_tcon_top>;
+ };
+ };
+ };
+ };
+
+ tcon_tv: lcd-controller@6515000 {
+ compatible = "allwinner,sun50i-h6-tcon-tv",
+ "allwinner,sun8i-r40-tcon-tv";
+ reg = <0x06515000 0x1000>;
+ interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_TCON_TV0>,
+ <&tcon_top CLK_TCON_TOP_TV0>;
+ clock-names = "ahb",
+ "tcon-ch1";
+ resets = <&ccu RST_BUS_TCON_TV0>;
+ reset-names = "lcd";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_tv_in: port@0 {
+ reg = <0>;
+
+ tcon_tv_in_tcon_top_mixer0: endpoint {
+ remote-endpoint = <&tcon_top_mixer0_out_tcon_tv>;
+ };
+ };
+
+ tcon_tv_out: port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ tcon_tv_out_tcon_top: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&tcon_top_hdmi_in_tcon_tv>;
+ };
+ };
+ };
+ };
+
rtc: rtc@7000000 {
compatible = "allwinner,sun50i-h616-rtc";
reg = <0x07000000 0x400>;
@@ -874,6 +1355,12 @@
#reset-cells = <1>;
};
+ prcm_ppu: power-controller@7010250 {
+ compatible = "allwinner,sun50i-h616-prcm-ppu";
+ reg = <0x07010250 0x10>;
+ #power-domain-cells = <1>;
+ };
+
nmi_intc: interrupt-controller@7010320 {
compatible = "allwinner,sun50i-h616-nmi",
"allwinner,sun9i-a80-nmi";
@@ -949,6 +1436,25 @@
#address-cells = <1>;
#size-cells = <0>;
};
+
+ dump_reg: dump_reg@20000 {
+ compatible = "allwinner,sunxi-dump-reg";
+ reg = <0x0 0x03001000 0x0 0x0f20>;
+ status = "okay";
+ };
+
+ sunxi-info {
+ compatible = "allwinner,sun50i-h616-sys-info";
+ status = "okay";
+ };
+
+ addr_mgt: addr-mgt {
+ compatible = "allwinner,sunxi-addr_mgt";
+ type_addr_wifi = <0x2>;
+ type_addr_bt = <0x2>;
+ type_addr_eth = <0x2>;
+ status = "okay";
+ };
};
thermal-zones {
--
2.35.3

View file

@ -0,0 +1,419 @@
From 07306aba1fd53935ae6df436d4f71313f49614ac Mon Sep 17 00:00:00 2001
From: The-going <48602507+The-going@users.noreply.github.com>
Date: Sun, 30 Mar 2025 18:12:38 +0300
Subject: dts: upstream: arm64: Add sun50i-h618-bananapi-m4-berry.dts
---
dts/upstream/src/arm64/allwinner/axp313a.dtsi | 64 ++++
.../src/arm64/allwinner/sun50i-h616.dtsi | 4 +-
.../sun50i-h618-bananapi-m4-berry.dts | 312 ++++++++++++++++++
3 files changed, 378 insertions(+), 2 deletions(-)
create mode 100644 dts/upstream/src/arm64/allwinner/axp313a.dtsi
create mode 100644 dts/upstream/src/arm64/allwinner/sun50i-h618-bananapi-m4-berry.dts
diff --git a/dts/upstream/src/arm64/allwinner/axp313a.dtsi b/dts/upstream/src/arm64/allwinner/axp313a.dtsi
new file mode 100644
index 000000000000..99057e975574
--- /dev/null
+++ b/dts/upstream/src/arm64/allwinner/axp313a.dtsi
@@ -0,0 +1,64 @@
+
+&r_i2c {
+ status = "okay";
+
+ axp313a: pmic@36 {
+ compatible = "x-powers,axp313a";
+ reg = <0x36>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ interrupt-parent = <&pio>;
+
+ vin1-supply = <&reg_vcc5v>;
+ vin2-supply = <&reg_vcc5v>;
+ vin3-supply = <&reg_vcc5v>;
+
+ regulators {
+ reg_dcdc1: dcdc1 {
+ regulator-name = "vdd-gpu";
+ regulator-min-microvolt = <810000>;
+ regulator-max-microvolt = <990000>;
+ regulator-step-delay-us = <25>;
+ regulator-final-delay-us = <50>;
+ regulator-always-on;
+ };
+
+ reg_dcdc2: dcdc2 {
+ regulator-name = "vdd-cpu";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-step-delay-us = <25>;
+ regulator-final-delay-us = <50>;
+ regulator-ramp-delay = <200>;
+ regulator-always-on;
+ };
+
+ reg_dcdc3: dcdc3 {
+ regulator-name = "vcc-dram";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-step-delay-us = <25>;
+ regulator-final-delay-us = <50>;
+ regulator-always-on;
+ };
+
+ reg_aldo1: aldo1 {
+ regulator-name = "vcc-1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-step-delay-us = <25>;
+ regulator-final-delay-us = <50>;
+ regulator-always-on;
+ };
+
+ reg_dldo1: dldo1 {
+ regulator-name = "vcc-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-step-delay-us = <25>;
+ regulator-final-delay-us = <50>;
+ regulator-always-on;
+ };
+ };
+ };
+};
diff --git a/dts/upstream/src/arm64/allwinner/sun50i-h616.dtsi b/dts/upstream/src/arm64/allwinner/sun50i-h616.dtsi
index 3fb5c6e25af4..0573e208c855 100644
--- a/dts/upstream/src/arm64/allwinner/sun50i-h616.dtsi
+++ b/dts/upstream/src/arm64/allwinner/sun50i-h616.dtsi
@@ -353,8 +353,8 @@
ext_rgmii_pins: rgmii-pins {
pins = "PI0", "PI1", "PI2", "PI3", "PI4",
"PI5", "PI7", "PI8", "PI9", "PI10",
- "PI11", "PI12", "PI13", "PI14", "PI15",
- "PI16";
+ "PI11", "PI12", "PI13", "PI14", "PI15";
+ /* "PI16" Managed by mdio */
function = "emac0";
drive-strength = <40>;
};
diff --git a/dts/upstream/src/arm64/allwinner/sun50i-h618-bananapi-m4-berry.dts b/dts/upstream/src/arm64/allwinner/sun50i-h618-bananapi-m4-berry.dts
new file mode 100644
index 000000000000..2d3d8589eff4
--- /dev/null
+++ b/dts/upstream/src/arm64/allwinner/sun50i-h618-bananapi-m4-berry.dts
@@ -0,0 +1,312 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (C) 2020 Arm Ltd.
+ * Copyright 2025 Armbian community.
+ */
+
+/dts-v1/;
+
+#include "sun50i-h616.dtsi"
+#include "sun50i-h616-cpu-opp.dtsi"
+#include "axp313a.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+ model = "BananaPi M4 Berry";
+ compatible = "BiPai,bananapi-m4berry", "allwinner,sun50i-h616";
+
+ aliases {
+ ethernet0 = &emac0;
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ leds: leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ label = "red_led";
+ gpios = <&pio 2 12 GPIO_ACTIVE_HIGH>; /* PC12 */
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ key-sw3 {
+ label = "sw3";
+ linux,code = <BTN_0>;
+ gpios = <&pio 2 7 GPIO_ACTIVE_LOW>; /* PC7 */
+ };
+ };
+
+ reg_vcc5v: vcc5v {
+ /* board wide 5V supply directly from the USB-C socket */
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
+
+ reg_usb_vbus: regulator-usb-vbus {
+ /* separate discrete regulator for the USB ports */
+ compatible = "regulator-fixed";
+ regulator-name = "usb-vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&reg_vcc5v>;
+ };
+
+ reg_vcc3v3: vcc3v3 {
+ /* SY8089 DC/DC converter */
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&reg_dldo1>;
+ regulator-always-on;
+ };
+
+ reg_vcc1v8: vcc1v8 {
+ /* Always on 1.8V/300mA regulator for WiFi and BT IO */
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ vin-supply = <&reg_aldo1>;
+ };
+
+ reg_gmac_3v3: gmac-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "gmac-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ vin-supply = <&reg_vcc5v>;
+ };
+
+ wifi_usb {
+ compatible = "usb-wifi";
+ status = "okay";
+ reset-gpios = <&pio 2 2 GPIO_ACTIVE_HIGH>; /* PC2 */
+ vin-supply = <&reg_vcc1v8>;
+ };
+
+ soc {
+ pwm: pwm@300a000 {
+ compatible = "allwinner,sun50i-h616-pwm";
+ reg = <0x0300a000 0x400>;
+ clocks = <&osc24M>, <&ccu CLK_BUS_PWM>;
+ clock-names = "mod", "bus";
+ resets = <&ccu RST_BUS_PWM>;
+ pwm-number = <6>;
+ pwm-base = <0x0>;
+ sunxi-pwms = <&pwm0>, <&pwm1>, <&pwm2>,
+ <&pwm3>, <&pwm4>, <&pwm5>;
+ #pwm-cells = <3>;
+ status = "okay";
+ };
+
+ pwm0: pwm0@0300a000 {
+ compatible = "allwinner,sunxi-pwm0";
+ pinctrl-names = "default";
+ };
+
+ pwm1: pwm1@0300a000 {
+ compatible = "allwinner,sunxi-pwm1";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm1_ph_pin>;
+ };
+
+ pwm2: pwm2@0300a000 {
+ compatible = "allwinner,sunxi-pwm2";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm2_ph_pin>;
+ };
+
+ pwm3: pwm3@0300a000 {
+ compatible = "allwinner,sunxi-pwm3";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm3_ph_pin>;
+ };
+
+ pwm4: pwm4@0300a000 {
+ compatible = "allwinner,sunxi-pwm4";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm4_ph_pin>;
+ };
+
+ pwm5: pwm5@0300a000 {
+ compatible = "allwinner,sunxi-pwm5";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm5_pin>;
+ clk_bypass_output = <0x1>;
+ status = "okay";
+ };
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&reg_dcdc2>;
+ status = "okay";
+};
+
+&sid {
+ ephy_calibration: ephy-calibration@2c {
+ reg = <0x2c 0x2>;
+ };
+};
+
+&mmc0 {
+ vmmc-supply = <&reg_dldo1>;
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+ bus-width = <4>;
+ max-frequency = <50000000>;
+ status = "okay";
+};
+
+&mmc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc2_pins>;
+ vmmc-supply = <&reg_dldo1>;
+ bus-width = <8>;
+ max-frequency = <150000000>;
+ non-removable;
+ cap-mmc-hw-reset;
+ status = "okay";
+};
+
+&pio {
+ vcc-pc-supply = <&reg_aldo1>;
+ vcc-pf-supply = <&reg_dldo1>;
+ vcc-pg-supply = <&reg_dldo1>;
+ vcc-ph-supply = <&reg_dldo1>;
+ vcc-pi-supply = <&reg_dldo1>;
+};
+
+&emac0 {
+ compatible = "allwinner,sun50i-h616-emac";
+ pinctrl-names = "default";
+ pinctrl-0 = <&ext_rgmii_pins>;
+ phy-mode = "rgmii";
+ phy-handle = <&ext_rgmii_phy>;
+ phy-supply = <&reg_gmac_3v3>;
+ phy-io-supply = <&reg_dldo1>;
+ allwinner,rx-delay-ps = <3100>;
+ allwinner,tx-delay-ps = <700>;
+ use_ephy25m = <0x00>;
+ status = "okay";
+};
+
+&mdio0 {
+ ext_rgmii_phy: ethernet-phy@1 {
+ /* rtl8211F compatible string for mdio and phy */
+ compatible = "ethernet-phy-id001c.c916";
+ reg = <1>;
+ reset-assert-us = <20000>;
+ reset-deassert-us = <100000>;
+ reset-gpios = <&pio 8 16 GPIO_ACTIVE_LOW>; /* PI16 */
+ };
+};
+
+&emac1 {
+ status = "disabled";
+};
+
+&mdio1 {
+ rmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_ph_pins>;
+ status = "okay";
+};
+
+&usbotg {
+ /*
+ * PHY0 pins are connected to a USB-C socket, but a role switch
+ * is not implemented: both CC pins are pulled to GND.
+ * The VBUS pins power the device, so a fixed peripheral mode
+ * is the best choice.
+ * The board can be powered via GPIOs, in this case port0 *can*
+ * act as a host (with a cable/adapter ignoring CC), as VBUS is
+ * then provided by the GPIOs. Any user of this setup would
+ * need to adjust the DT accordingly: dr_mode set to "host",
+ * enabling OHCI0 and EHCI0.
+ */
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usbphy {
+ usb1_vbus-supply = <&reg_usb_vbus>;
+ status = "okay";
+};
+
+&ehci0 {
+ status = "disabled";
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&ehci2 {
+ status = "okay";
+};
+
+&ehci3 {
+ status = "okay";
+};
+
+&ohci0 {
+ status = "disabled";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&ohci2 {
+ status = "okay";
+};
+
+&ohci3 {
+ status = "okay";
+};
+
+&i2c1 {
+ status = "disabled";
+};
+
+&i2c2 {
+ status = "disabled";
+};
+
+&i2c3 {
+ status = "disabled";
+};
+
+&i2c4 {
+ status = "disabled";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>;
+ status = "disabled";
+};
--
2.35.3

View file

@ -0,0 +1,52 @@
From 33131f3e125f28b65fa9d0972030eda517983b54 Mon Sep 17 00:00:00 2001
From: The-going <48602507+The-going@users.noreply.github.com>
Date: Tue, 21 Jan 2025 23:04:54 +0300
Subject: u-boot: configs: Add sun50i-h618-bananapi-m4berry defconfig
---
configs/bananapi_m4_berry_defconfig | 33 +++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
create mode 100644 configs/bananapi_m4_berry_defconfig
diff --git a/configs/bananapi_m4_berry_defconfig b/configs/bananapi_m4_berry_defconfig
new file mode 100644
index 000000000000..94eb4bac7afb
--- /dev/null
+++ b/configs/bananapi_m4_berry_defconfig
@@ -0,0 +1,33 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_DEFAULT_DEVICE_TREE="allwinner/sun50i-h618-bananapi-m4-berry"
+CONFIG_OF_UPSTREAM=y
+CONFIG_SPL=y
+CONFIG_DRAM_SUNXI_DX_ODT=0x07070707
+CONFIG_DRAM_SUNXI_DX_DRI=0x0e0e0e0e
+CONFIG_DRAM_SUNXI_CA_DRI=0x0e0e
+CONFIG_DRAM_SUNXI_ODT_EN=0xaaaaeeee
+CONFIG_DRAM_SUNXI_TPR6=0x48808080
+CONFIG_DRAM_SUNXI_TPR10=0x402f6663
+CONFIG_DRAM_SUNXI_TPR11=0x26262524
+CONFIG_DRAM_SUNXI_TPR12=0x100f100f
+CONFIG_MACH_SUN50I_H616=y
+CONFIG_SUNXI_DRAM_H616_LPDDR4=y
+CONFIG_DRAM_CLK=792
+CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+CONFIG_MMC_HS400_SUPPORT=y
+CONFIG_SPL_MMC_HS400_SUPPORT=y
+CONFIG_R_I2C_ENABLE=y
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SPL_I2C=y
+CONFIG_SPL_SYS_I2C_LEGACY=y
+CONFIG_SYS_I2C_MVTWSI=y
+CONFIG_SYS_I2C_SLAVE=0x7f
+CONFIG_SYS_I2C_SPEED=400000
+CONFIG_SUN8I_EMAC=y
+CONFIG_PHY_REALTEK=y
+CONFIG_SUPPORT_EMMC_BOOT=y
+CONFIG_AXP313_POWER=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_MUSB_GADGET=y
--
2.35.3

View file

@ -0,0 +1,141 @@
From f9aa935084d24fbbe5e7b2c62948a8f08b228f18 Mon Sep 17 00:00:00 2001
From: voapilro <voapilro@gmail.com>
Date: Mon, 6 May 2024 11:36:47 +0200
Subject: [PATCH 1/3] Fix memory size detection for 1.5GB Orange Pi Zero 3
board
---
arch/arm/include/asm/arch-sunxi/dram.h | 1 +
arch/arm/mach-sunxi/dram_helpers.c | 20 ++++++++++++++++++++
arch/arm/mach-sunxi/dram_sun50i_h616.c | 9 ++++++++-
3 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
index 682daae6b1a..a1379631d62 100644
--- a/arch/arm/include/asm/arch-sunxi/dram.h
+++ b/arch/arm/include/asm/arch-sunxi/dram.h
@@ -41,5 +41,6 @@
void mctl_await_completion(u32 *reg, u32 mask, u32 val);
bool mctl_mem_matches(u32 offset);
bool mctl_mem_matches_base(u32 offset, ulong base);
+bool mctl_mem_matches_top(ulong offset);
#endif /* _SUNXI_DRAM_H */
diff --git a/arch/arm/mach-sunxi/dram_helpers.c b/arch/arm/mach-sunxi/dram_helpers.c
index 83dbe4ca98f..88edc5ccc7f 100644
--- a/arch/arm/mach-sunxi/dram_helpers.c
+++ b/arch/arm/mach-sunxi/dram_helpers.c
@@ -61,4 +61,29 @@ bool mctl_mem_matches(u32 offset)
{
return mctl_mem_matches_base(offset, CFG_SYS_SDRAM_BASE);
}
+
+/*
+ * Test if memory at offset matches memory at top of DRAM
+ */
+bool mctl_mem_matches_top(ulong offset)
+{
+ static const unsigned value= 0xaa55aa55;
+
+ /* Take last usable memory address */
+ offset -= sizeof(value);
+ dsb();
+ /* Set zero at last usable memory address */
+ writel(0, (ulong)CFG_SYS_SDRAM_BASE + offset);
+ dsb();
+ /* Set other value at last usable memory address */
+ writel(value, (ulong)CFG_SYS_SDRAM_BASE + offset);
+ dsb();
+ /* Check if the same value is actually observed when reading back */
+ return readl((ulong)CFG_SYS_SDRAM_BASE + offset) == value;
+}
+
+ulong mctl_mem_address(ulong offset)
+{
+ return (ulong)CFG_SYS_SDRAM_BASE + offset;
+}
#endif
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c
index c5c1331a4c3..5287ef79c43 100644
--- a/arch/arm/mach-sunxi/dram_sun50i_h616.c
+++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c
@@ -1350,9 +1350,16 @@ static void mctl_auto_detect_dram_size(const struct dram_para *para,
static unsigned long mctl_calc_size(const struct dram_config *config)
{
u8 width = config->bus_full_width ? 4 : 2;
+ unsigned long size;
/* 8 banks */
- return (1ULL << (config->cols + config->rows + 3)) * width * config->ranks;
+ size = (1ULL << (config->cols + config->rows + 3)) * width * config->ranks;
+
+ /* Fix size if last usable memory address is not valid */
+ if (!mctl_mem_matches_top(size))
+ size = (size * 3) / 4;
+
+ return size;
}
static const struct dram_para para = {
From 371388504b9b67459dfd13d2585090961ad51cc5 Mon Sep 17 00:00:00 2001
From: voapilro <voapilro@gmail.com>
Date: Mon, 6 May 2024 15:13:29 +0200
Subject: [PATCH 2/3] Added some logs regarding memory size detection
---
arch/arm/include/asm/arch-sunxi/dram.h | 1 +
arch/arm/mach-sunxi/dram_helpers.c | 10 +++++++++-
arch/arm/mach-sunxi/dram_sun50i_h616.c | 10 +++++++++-
board/sunxi/board.c | 3 +--
4 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
index a1379631d62..c7543d35698 100644
--- a/arch/arm/include/asm/arch-sunxi/dram.h
+++ b/arch/arm/include/asm/arch-sunxi/dram.h
@@ -42,5 +42,6 @@ unsigned long sunxi_dram_init(void);
bool mctl_mem_matches(u32 offset);
bool mctl_mem_matches_base(u32 offset, ulong base);
bool mctl_mem_matches_top(ulong offset);
+ulong mctl_mem_address(ulong offset);
#endif /* _SUNXI_DRAM_H */
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c
index 5287ef79c43..6a247ecaa05 100644
--- a/arch/arm/mach-sunxi/dram_sun50i_h616.c
+++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c
@@ -1355,9 +1355,17 @@ static unsigned long mctl_calc_size(const struct dram_config *config)
/* 8 banks */
size = (1ULL << (config->cols + config->rows + 3)) * width * config->ranks;
+ printf("DRAM base address is defined as 0x%lx\n", mctl_mem_address(0));
+ printf("DRAM has %u b/raw, %u b/col, %u B/width, %u #rank and 8 #bank\n",
+ (unsigned)config->rows, (unsigned)config->cols,
+ (unsigned)width, (unsigned)config->ranks);
+ printf("DRAM top address must be less than 0x%lx\n", size);
+
/* Fix size if last usable memory address is not valid */
- if (!mctl_mem_matches_top(size))
+ if (!mctl_mem_matches_top(size)) {
size = (size * 3) / 4;
+ printf("DRAM top address must be less than 0x%lx\n", size);
+ }
return size;
}
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 8c12c8deade..62228936774 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -632,9 +632,8 @@ void sunxi_board_init(void)
power_failed |= axp_set_sw(IS_ENABLED(CONFIG_AXP_SW_ON));
#endif
#endif /* CONFIG_AXPxxx_POWER */
- printf("DRAM:");
gd->ram_size = sunxi_dram_init();
- printf(" %d MiB\n", (int)(gd->ram_size >> 20));
+ printf("DRAM: %d MiB\n", (int)(gd->ram_size >> 20));
if (!gd->ram_size)
hang();

View file

@ -0,0 +1,72 @@
pkgname=u-boot-xunlong-orangepi-zero3
pkgver=2025.04
pkgrel=0
pkgdesc="U-Boot bootloader for the Xunlong Orage Pi Zero 3"
url="https://source.denx.de/u-boot"
arch="aarch64"
license="GPL-2.0-or-later OFL-1.1 BSD-2-Clause BSD-3-Clause eCos-2.0 IBM-pibs
ISC LGPL-2.0-only LGPL-2.1-only X11"
depends="linux-postmarketos-allwinner"
replaces="u-boot-sunxi"
makedepends="$depends_dev
arm-trusted-firmware>=2.12.8-r1
bc
bison
dtc
flex
openssl-dev
py3-setuptools
python3-dev
swig
gnutls
gnutls-dev
"
options="!check"
source="https://source.denx.de/u-boot/u-boot/-/archive/v$pkgver/u-boot-v$pkgver.tar.gz
0001-sunxi-h616-dram-Rework-size-detection.patch
0002-sunxi-H616-dram-Improve-address-wrapping-detection.patch
0003-sunxi-mmc-Improve-reset-procedure.patch
0004-Add-MACH_SUN8I_A83T-to-can-calibrate.patch
0005-board-sunxi-The-prefix-is-missing-if-we-use-OF_UPSTREAM.patch
0006-dts-upstream-arm64-sun50i-h616-sync-with-sunxi-6.12-kernel.patch
0007-dts-upstream-arm64-Add-sun50i-h618-bananapi-m4-berry.dts.patch
0008-u-boot-configs-Add-sun50i-h618-bananapi-m4berry-defconfig.patch
0009-sunxi-h616-dram-support-1.5GB-RAM-size-pmos.patch
update-u-boot
"
builddir="$srcdir/u-boot-v$pkgver"
build() {
touch include/config.h
LC_ALL=C date +'#define U_BOOT_DATE "%b %d %C%y"' > include/timestamp_autogenerated.h
LC_ALL=C date +'#define U_BOOT_TIME "%T"' >> include/timestamp_autogenerated.h
export BL31="/usr/share/arm-trusted-firmware/sun50i_h616/bl31.bin"
export BUILD_DIR="$builddir"/build
make O="$BUILD_DIR" HOSTCC=gcc ARCH=arm orangepi_zero3_defconfig
make O="$BUILD_DIR" HOSTCC=gcc ARCH=arm all
sha512sum -b "$BUILD_DIR/u-boot-sunxi-with-spl.bin" > "$BUILD_DIR/u-boot-sunxi-with-spl.bin.sha512"
}
package() {
install -D -m644 "build/u-boot-sunxi-with-spl.bin" \
"$pkgdir/usr/share/u-boot/orangepi_zero3/u-boot-sunxi-with-spl.bin"
install -D -m644 "build/u-boot-sunxi-with-spl.bin.sha512" \
"$pkgdir/usr/share/u-boot/orangepi_zero3/u-boot-sunxi-with-spl.bin.sha512"
install -D -m 755 "$srcdir"/update-u-boot "$pkgdir"/usr/sbin/update-u-boot
}
sha512sums="
5b6759bccffd586f8d79dc8ab286f0f98c46bb99a1c4250b6626b1bcd03ba287fd8a48b47667b53627435e8012a083150546825a303145b0163872ad918a4652 u-boot-v2025.04.tar.gz
f909011abe0dbb103502107ff1117a20ef527454743dc23b09cf8d158d228fd4265b8a961084a6813e90407e69776ea8a823c1400740a59fedf19a084f4120c3 0001-sunxi-h616-dram-Rework-size-detection.patch
7fc447ab96ac9681cf2e91d5dae14070bfb6723dfd6d2cb2d335d7524a3b6cf614d167ed479d149cee8aa3689bcd1984f1d3281d01dd7d077702e040326c8194 0002-sunxi-H616-dram-Improve-address-wrapping-detection.patch
10b4026461fb4df0e9538db8591d76138c397e6e18621f9f3265ea8f5fbade23d1710c18346928b925390f988c1bea5b8e0663076c00bd83261c40bc27f44f7c 0003-sunxi-mmc-Improve-reset-procedure.patch
99df087471645d5824a52fd2d594eacbdb5e3ea6f6bfed0a46eb2bf0c51155bf628daf25449b6d8b9d0dddc11933041e20eb1bfde69bd4bae3f7c7ea56ac30cf 0004-Add-MACH_SUN8I_A83T-to-can-calibrate.patch
5593bfebee96437807a27970e413506e35b308540923770737e6dc058e8e5720e0a07619849f9845d57b01c126d9fc9134f52d0c7ae9ff245af7c7ddd8ee14c2 0005-board-sunxi-The-prefix-is-missing-if-we-use-OF_UPSTREAM.patch
8cc29615d4c47bec4fb0ef9d576398554f8441b307ac44ab950ac549115d795d1cfbaacfbf8400815f1b36b191bcb5465b9732ed468b7cb9ca209fd84d7ffe91 0006-dts-upstream-arm64-sun50i-h616-sync-with-sunxi-6.12-kernel.patch
db734ef264b8bfa6eaabad946f049c790cd8f4970111b7e30d63c04450d93d17e39cabfb67817fef0fd22553c0780c174f0e11a847e7e7edc3140b5b4f084afd 0007-dts-upstream-arm64-Add-sun50i-h618-bananapi-m4-berry.dts.patch
4ea374c133a9ac274aec67cb2530e03eef019e9a6be5989d633525c58ab3900e38eb675777df84bbd7bd0345ec6e204c52c90b33d2dbc65474af0ee8b43d55d7 0008-u-boot-configs-Add-sun50i-h618-bananapi-m4berry-defconfig.patch
f967471c779b852a0db6dd7ebc200a936d8a2fe29d903c34f0735f7fb771dbed175db27e9c5b20f37855ed68ad72bb7d7a6eda4d6ad2dd8dfe434e70448b4d8e 0009-sunxi-h616-dram-support-1.5GB-RAM-size-pmos.patch
6c4cb066b1ec19b762ccbfbe906492afb4cf32cd1ffadc22ce4cfe254245d5b971f2cabb8a336585366bd329cdeab8b27e96d3bee40aa14ef72cc9ecf49a61c3 update-u-boot
"

View file

@ -0,0 +1,90 @@
#!/bin/sh
verbose=
board=oragepi-zero3
device=/dev/mmcblk0
dryrun=
imagedir=/usr/share/u-boot
die() {
echo "ERROR: $@"
exit 1
}
usage() {
get_defaults
cat <<EOF
usage: $0 [-n,--dry-run] [-i,--imagedir <imagedir>] [-b|--board <board-type>] [-d|--device <device>]
options:
-b,--board <board> Specify the board type: orangepi-zero3
(current default: ${board:-none})
-d,--device <device> Specify the device where to install u-boot
(current default: ${device:-none})
-i,--imagedir <imagedir> Specify u-boot image directory
(current default: ${imagedir:-none})
-n,--dry-run Print commands but don't execute them
EOF
}
while [ $# -gt 0 ]; do
opt="$1"
shift
case "$opt" in
-b|--board)
case "$1" in
orangepi-zero3) board="orangepi-zero3" ;;
*) usage; exit 1;;
esac
shift
;;
-d|--device)
device="$1"
shift
;;
-i|--imagedir)
imagedir="$1"
shift
;;
-n|--dry-run)
dryrun="echo"
;;
--)
break
;;
-*)
usage
exit 1
;;
esac
done
if [ -z "$board" -o -z "$device" -o -z "$imagedir" -o ! -e "$imagedir" ]; then
usage
exit 1
fi
if [ -z "$dryrun" ]; then
echo "Updating $board u-boot in $device in 3 seconds..."
sleep 3
fi
(
set -e
case "$board" in
orangepi-zero3)
[ -e "$imagedir/orangepi_zero3" ] || die "orangepi-zero3 images not installed, apk add u-boot-xunlong-orangepi-zero3"
$dryrun dd if=$imagedir/orangepi_zero3/u-boot-sunxi-with-spl.bin of=$device bs=1024 seek=8 status=none
;;
esac
$dryrun sync
) || die "U-Boot installation in $device failed"
[ -z "$dryrun" ] && echo "Completed successfully."