[PATCH] arm: apple: Add initial Apple M2 Ultra support

Apple's M2 Ultra SoC are somewhat similar to the M1 Ultra but needs a tweaked memory map as the M2 Pro/Max SoCs. USB, NVMe, UART, WDT and PCIe are working with the existing drivers.
Signed-off-by: Janne Grunau j@jannau.net --- arch/arm/mach-apple/board.c | 183 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+)
diff --git a/arch/arm/mach-apple/board.c b/arch/arm/mach-apple/board.c index d50194811843..47393babbc62 100644 --- a/arch/arm/mach-apple/board.c +++ b/arch/arm/mach-apple/board.c @@ -444,6 +444,187 @@ static struct mm_region t6020_mem_map[] = { } };
+/* Apple M2 Ultra */ + +static struct mm_region t6022_mem_map[] = { + { + /* I/O */ + .virt = 0x280000000, + .phys = 0x280000000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x340000000, + .phys = 0x340000000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x380000000, + .phys = 0x380000000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x580000000, + .phys = 0x580000000, + .size = SZ_512M, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* PCIE */ + .virt = 0x5a0000000, + .phys = 0x5a0000000, + .size = SZ_512M, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE) | + PTE_BLOCK_INNER_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* PCIE */ + .virt = 0x5c0000000, + .phys = 0x5c0000000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE) | + PTE_BLOCK_INNER_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x700000000, + .phys = 0x700000000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0xb00000000, + .phys = 0xb00000000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0xf00000000, + .phys = 0xf00000000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x1300000000, + .phys = 0x1300000000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x2280000000, + .phys = 0x2280000000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x2340000000, + .phys = 0x2340000000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x2380000000, + .phys = 0x2380000000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x2580000000, + .phys = 0x2580000000, + .size = SZ_512M, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* PCIE */ + .virt = 0x25a0000000, + .phys = 0x25a0000000, + .size = SZ_512M, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE) | + PTE_BLOCK_INNER_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* PCIE */ + .virt = 0x25c0000000, + .phys = 0x25c0000000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE) | + PTE_BLOCK_INNER_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x2700000000, + .phys = 0x2700000000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x2b00000000, + .phys = 0x2b00000000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x2f00000000, + .phys = 0x2f00000000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x3300000000, + .phys = 0x3300000000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* RAM */ + .virt = 0x10000000000, + .phys = 0x10000000000, + .size = 16UL * SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, { + /* Framebuffer */ + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) | + PTE_BLOCK_INNER_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* List terminator */ + 0, + } +}; + struct mm_region *mem_map;
int board_init(void) @@ -488,6 +669,8 @@ void build_mem_map(void) else if (of_machine_is_compatible("apple,t6020") || of_machine_is_compatible("apple,t6021")) mem_map = t6020_mem_map; + else if (of_machine_is_compatible("apple,t6022")) + mem_map = t6022_mem_map; else panic("Unsupported SoC\n");
--- base-commit: c0c08be5468cb26db597932bc69c4eda1129841d change-id: 20230906-apple_t6022_m2_ultra-9146e34619e6
Best regards,

Hi,
On Wed, 6 Sept 2023 at 15:50, Janne Grunau j@jannau.net wrote:
Apple's M2 Ultra SoC are somewhat similar to the M1 Ultra but needs a tweaked memory map as the M2 Pro/Max SoCs. USB, NVMe, UART, WDT and PCIe are working with the existing drivers.
Signed-off-by: Janne Grunau j@jannau.net
arch/arm/mach-apple/board.c | 183 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+)
diff --git a/arch/arm/mach-apple/board.c b/arch/arm/mach-apple/board.c index d50194811843..47393babbc62 100644 --- a/arch/arm/mach-apple/board.c +++ b/arch/arm/mach-apple/board.c @@ -444,6 +444,187 @@ static struct mm_region t6020_mem_map[] = { } };
+/* Apple M2 Ultra */
+static struct mm_region t6022_mem_map[] = {
{
/* I/O */
.virt = 0x280000000,
.phys = 0x280000000,
.size = SZ_1G,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
}, {
Is there no devicetree binding for this information?
[..]
Regards, Simon

From: Simon Glass sjg@google.com Date: Sun, 10 Sep 2023 16:36:48 -0600
Hi,
On Wed, 6 Sept 2023 at 15:50, Janne Grunau j@jannau.net wrote:
Apple's M2 Ultra SoC are somewhat similar to the M1 Ultra but needs a tweaked memory map as the M2 Pro/Max SoCs. USB, NVMe, UART, WDT and PCIe are working with the existing drivers.
Signed-off-by: Janne Grunau j@jannau.net
arch/arm/mach-apple/board.c | 183 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+)
diff --git a/arch/arm/mach-apple/board.c b/arch/arm/mach-apple/board.c index d50194811843..47393babbc62 100644 --- a/arch/arm/mach-apple/board.c +++ b/arch/arm/mach-apple/board.c @@ -444,6 +444,187 @@ static struct mm_region t6020_mem_map[] = { } };
+/* Apple M2 Ultra */
+static struct mm_region t6022_mem_map[] = {
{
/* I/O */
.virt = 0x280000000,
.phys = 0x280000000,
.size = SZ_1G,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
}, {
Is there no devicetree binding for this information?
Not directly. The device tree does contain the addresses of the devices of course. But what we want here is a memory map that uses a few big ranges that cover all the devices in the device tree rather than lots of small ranges that cover the individual devices.
But yes, it sucks that every time Apple produces a new SoC we need to add another memory map.

Hi Mark,
On Mon, 11 Sept 2023 at 14:25, Mark Kettenis mark.kettenis@xs4all.nl wrote:
From: Simon Glass sjg@google.com Date: Sun, 10 Sep 2023 16:36:48 -0600
Hi,
On Wed, 6 Sept 2023 at 15:50, Janne Grunau j@jannau.net wrote:
Apple's M2 Ultra SoC are somewhat similar to the M1 Ultra but needs a tweaked memory map as the M2 Pro/Max SoCs. USB, NVMe, UART, WDT and PCIe are working with the existing drivers.
Signed-off-by: Janne Grunau j@jannau.net
arch/arm/mach-apple/board.c | 183 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+)
diff --git a/arch/arm/mach-apple/board.c b/arch/arm/mach-apple/board.c index d50194811843..47393babbc62 100644 --- a/arch/arm/mach-apple/board.c +++ b/arch/arm/mach-apple/board.c @@ -444,6 +444,187 @@ static struct mm_region t6020_mem_map[] = { } };
+/* Apple M2 Ultra */
+static struct mm_region t6022_mem_map[] = {
{
/* I/O */
.virt = 0x280000000,
.phys = 0x280000000,
.size = SZ_1G,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
}, {
Is there no devicetree binding for this information?
Not directly. The device tree does contain the addresses of the devices of course. But what we want here is a memory map that uses a few big ranges that cover all the devices in the device tree rather than lots of small ranges that cover the individual devices.
OK I see.
But yes, it sucks that every time Apple produces a new SoC we need to add another memory map.
Regards, Simon

From: Janne Grunau j@jannau.net Date: Wed, 06 Sep 2023 23:50:34 +0200
Apple's M2 Ultra SoC are somewhat similar to the M1 Ultra but needs a tweaked memory map as the M2 Pro/Max SoCs. USB, NVMe, UART, WDT and PCIe are working with the existing drivers.
Signed-off-by: Janne Grunau j@jannau.net
Reviewed-by: Mark Kettenis kettenis@openbsd.org
arch/arm/mach-apple/board.c | 183 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+)
diff --git a/arch/arm/mach-apple/board.c b/arch/arm/mach-apple/board.c index d50194811843..47393babbc62 100644 --- a/arch/arm/mach-apple/board.c +++ b/arch/arm/mach-apple/board.c @@ -444,6 +444,187 @@ static struct mm_region t6020_mem_map[] = { } };
+/* Apple M2 Ultra */
+static struct mm_region t6022_mem_map[] = {
- {
/* I/O */
.virt = 0x280000000,
.phys = 0x280000000,
.size = SZ_1G,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
/* I/O */
.virt = 0x340000000,
.phys = 0x340000000,
.size = SZ_1G,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
/* I/O */
.virt = 0x380000000,
.phys = 0x380000000,
.size = SZ_1G,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
/* I/O */
.virt = 0x580000000,
.phys = 0x580000000,
.size = SZ_512M,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
/* PCIE */
.virt = 0x5a0000000,
.phys = 0x5a0000000,
.size = SZ_512M,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE) |
PTE_BLOCK_INNER_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
/* PCIE */
.virt = 0x5c0000000,
.phys = 0x5c0000000,
.size = SZ_1G,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE) |
PTE_BLOCK_INNER_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
/* I/O */
.virt = 0x700000000,
.phys = 0x700000000,
.size = SZ_1G,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
/* I/O */
.virt = 0xb00000000,
.phys = 0xb00000000,
.size = SZ_1G,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
/* I/O */
.virt = 0xf00000000,
.phys = 0xf00000000,
.size = SZ_1G,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
/* I/O */
.virt = 0x1300000000,
.phys = 0x1300000000,
.size = SZ_1G,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
/* I/O */
.virt = 0x2280000000,
.phys = 0x2280000000,
.size = SZ_1G,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
/* I/O */
.virt = 0x2340000000,
.phys = 0x2340000000,
.size = SZ_1G,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
/* I/O */
.virt = 0x2380000000,
.phys = 0x2380000000,
.size = SZ_1G,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
/* I/O */
.virt = 0x2580000000,
.phys = 0x2580000000,
.size = SZ_512M,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
/* PCIE */
.virt = 0x25a0000000,
.phys = 0x25a0000000,
.size = SZ_512M,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE) |
PTE_BLOCK_INNER_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
/* PCIE */
.virt = 0x25c0000000,
.phys = 0x25c0000000,
.size = SZ_1G,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE) |
PTE_BLOCK_INNER_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
/* I/O */
.virt = 0x2700000000,
.phys = 0x2700000000,
.size = SZ_1G,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
/* I/O */
.virt = 0x2b00000000,
.phys = 0x2b00000000,
.size = SZ_1G,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
/* I/O */
.virt = 0x2f00000000,
.phys = 0x2f00000000,
.size = SZ_1G,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
/* I/O */
.virt = 0x3300000000,
.phys = 0x3300000000,
.size = SZ_1G,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
/* RAM */
.virt = 0x10000000000,
.phys = 0x10000000000,
.size = 16UL * SZ_1G,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
- }, {
/* Framebuffer */
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) |
PTE_BLOCK_INNER_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
- }, {
/* List terminator */
0,
- }
+};
struct mm_region *mem_map;
int board_init(void) @@ -488,6 +669,8 @@ void build_mem_map(void) else if (of_machine_is_compatible("apple,t6020") || of_machine_is_compatible("apple,t6021")) mem_map = t6020_mem_map;
- else if (of_machine_is_compatible("apple,t6022"))
else panic("Unsupported SoC\n");mem_map = t6022_mem_map;
base-commit: c0c08be5468cb26db597932bc69c4eda1129841d change-id: 20230906-apple_t6022_m2_ultra-9146e34619e6
Best regards,
Janne Grunau j@jannau.net

On Wed, Sep 06, 2023 at 11:50:34PM +0200, Janne Grunau wrote:
Apple's M2 Ultra SoC are somewhat similar to the M1 Ultra but needs a tweaked memory map as the M2 Pro/Max SoCs. USB, NVMe, UART, WDT and PCIe are working with the existing drivers.
Signed-off-by: Janne Grunau j@jannau.net Reviewed-by: Mark Kettenis kettenis@openbsd.org
Applied to u-boot/master, thanks!
participants (4)
-
Janne Grunau
-
Mark Kettenis
-
Simon Glass
-
Tom Rini