mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-10 01:34:12 +00:00
Remove hardcoded UART/WDT addresses
The M1 Pro/Max Macs use a different base address for the UART and the WDT than earlier models. Remove hardcoded base addresses constants and replace them with loads from the ADT. - The base address of the WDT is already retrieved in wdt_disable; also use this address when triggering a reboot. - Retrieve the base address of uart0 in uart_init. If the operation fails, the error will be signaled on the early uart (if not disabled). - The early debug UART can’t use the ADT (or shouldn’t) so it is now disabled by default. To enable it, add -DEARLY_UART -DEARLY_UART_BASE=0xuart_address to the CFLAGS. Signed-off-by: Vincent Duvert <vincent@duvert.net>
This commit is contained in:
parent
73180e29fa
commit
b15be6bcd7
6 changed files with 87 additions and 44 deletions
23
src/start.S
23
src/start.S
|
@ -1,14 +1,12 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#define UART_BASE 0x235200000
|
||||
#if defined(EARLY_UART) && !defined(EARLY_UART_BASE)
|
||||
#error EARLY_UART_BASE must be defined to the UART base address
|
||||
#endif
|
||||
|
||||
#define UTRSTAT 0x010
|
||||
#define UTXH 0x020
|
||||
|
||||
#define WDT_BASE 0x23d2b0000
|
||||
#define WDT_COUNT 0x10
|
||||
#define WDT_ALARM 0x14
|
||||
#define WDT_CTL 0x1c
|
||||
|
||||
.extern _start_c
|
||||
.extern _stack_bot
|
||||
.extern _v_sp0_sync
|
||||
|
@ -17,6 +15,7 @@
|
|||
.extern _v_sp0_serr
|
||||
.extern _reset_stack
|
||||
.extern _cpu_reset_c
|
||||
.extern wdt_reboot
|
||||
|
||||
.section .init, "ax"
|
||||
|
||||
|
@ -154,13 +153,15 @@ cpu_reset:
|
|||
.globl debug_putc
|
||||
.type debug_putc, @function
|
||||
debug_putc:
|
||||
ldr x1, =UART_BASE
|
||||
#ifdef EARLY_UART
|
||||
ldr x1, =EARLY_UART_BASE
|
||||
|
||||
1:
|
||||
ldr w2, [x1, UTRSTAT]
|
||||
tst w2, #2
|
||||
beq 1b
|
||||
str w0, [x1, UTXH]
|
||||
#endif
|
||||
ret
|
||||
|
||||
.globl reboot
|
||||
|
@ -171,13 +172,7 @@ reboot:
|
|||
beq 1f
|
||||
hvc #0
|
||||
1:
|
||||
ldr x1, =WDT_BASE
|
||||
mov w0, #0x100000
|
||||
str w0, [x1, #WDT_ALARM]
|
||||
mov w0, #0
|
||||
str w0, [x1, #WDT_COUNT]
|
||||
mov w0, #4
|
||||
str w0, [x1, #WDT_CTL]
|
||||
bl wdt_reboot
|
||||
b .
|
||||
|
||||
.pool
|
||||
|
|
|
@ -79,25 +79,27 @@ void _start_c(void *boot_args, void *base)
|
|||
msr(TPIDR_EL1, 0);
|
||||
|
||||
memset64(_bss_start, 0, _bss_end - _bss_start);
|
||||
uart_putchar('s');
|
||||
uart_init();
|
||||
uart_putchar('c');
|
||||
uart_puts(": Initializing");
|
||||
boot_args_addr = (u64)boot_args;
|
||||
memcpy(&cur_boot_args, boot_args, sizeof(cur_boot_args));
|
||||
|
||||
adt =
|
||||
(void *)(((u64)cur_boot_args.devtree) - cur_boot_args.virt_base + cur_boot_args.phys_base);
|
||||
|
||||
int ret = uart_init();
|
||||
if (ret < 0) {
|
||||
debug_putc('!');
|
||||
}
|
||||
|
||||
uart_puts("Initializing");
|
||||
printf("CPU init... ");
|
||||
const char *type = init_cpu();
|
||||
printf("CPU: %s\n\n", type);
|
||||
|
||||
printf("boot_args at %p\n", boot_args);
|
||||
|
||||
boot_args_addr = (u64)boot_args;
|
||||
memcpy(&cur_boot_args, boot_args, sizeof(cur_boot_args));
|
||||
|
||||
dump_boot_args(&cur_boot_args);
|
||||
printf("\n");
|
||||
|
||||
adt =
|
||||
(void *)(((u64)cur_boot_args.devtree) - cur_boot_args.virt_base + cur_boot_args.phys_base);
|
||||
|
||||
exception_initialize();
|
||||
gxf_init();
|
||||
m1n1_main();
|
||||
|
|
59
src/uart.c
59
src/uart.c
|
@ -2,38 +2,56 @@
|
|||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "uart.h"
|
||||
#include "adt.h"
|
||||
#include "iodev.h"
|
||||
#include "types.h"
|
||||
#include "uart.h"
|
||||
#include "uart_regs.h"
|
||||
#include "utils.h"
|
||||
#include "vsprintf.h"
|
||||
|
||||
#define UART_CLOCK 24000000
|
||||
|
||||
#define UART_BASE 0x235200000L
|
||||
static u64 uart_base = 0;
|
||||
|
||||
void *pxx = uart_init;
|
||||
|
||||
void uart_init(void)
|
||||
int uart_init(void)
|
||||
{
|
||||
/* keep UART config from iBoot */
|
||||
int path[8];
|
||||
int node = adt_path_offset_trace(adt, "/arm-io/uart0", path);
|
||||
|
||||
if (node < 0) {
|
||||
printf("!!! UART node not found!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (adt_get_reg(adt, path, "reg", 0, &uart_base, NULL)) {
|
||||
printf("!!! Failed to get UART reg property!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uart_putbyte(u8 c)
|
||||
{
|
||||
while (!(read32(UART_BASE + UTRSTAT) & UTRSTAT_TXBE))
|
||||
if (!uart_base)
|
||||
return;
|
||||
|
||||
while (!(read32(uart_base + UTRSTAT) & UTRSTAT_TXBE))
|
||||
;
|
||||
|
||||
write32(UART_BASE + UTXH, c);
|
||||
write32(uart_base + UTXH, c);
|
||||
}
|
||||
|
||||
u8 uart_getbyte(void)
|
||||
{
|
||||
while (!(read32(UART_BASE + UTRSTAT) & UTRSTAT_RXD))
|
||||
if (!uart_base)
|
||||
return 0;
|
||||
|
||||
while (!(read32(uart_base + UTRSTAT) & UTRSTAT_RXD))
|
||||
;
|
||||
|
||||
return read32(UART_BASE + URXH);
|
||||
return read32(uart_base + URXH);
|
||||
}
|
||||
|
||||
void uart_putchar(u8 c)
|
||||
|
@ -80,19 +98,28 @@ size_t uart_read(void *buf, size_t count)
|
|||
|
||||
void uart_setbaud(int baudrate)
|
||||
{
|
||||
if (!uart_base)
|
||||
return;
|
||||
|
||||
uart_flush();
|
||||
write32(UART_BASE + UBRDIV, ((UART_CLOCK / baudrate + 7) / 16) - 1);
|
||||
write32(uart_base + UBRDIV, ((UART_CLOCK / baudrate + 7) / 16) - 1);
|
||||
}
|
||||
|
||||
void uart_flush(void)
|
||||
{
|
||||
while (!(read32(UART_BASE + UTRSTAT) & UTRSTAT_TXE))
|
||||
if (!uart_base)
|
||||
return;
|
||||
|
||||
while (!(read32(uart_base + UTRSTAT) & UTRSTAT_TXE))
|
||||
;
|
||||
}
|
||||
|
||||
void uart_clear_irqs(void)
|
||||
{
|
||||
write32(UART_BASE + UTRSTAT, UTRSTAT_TXTHRESH | UTRSTAT_RXTHRESH | UTRSTAT_RXTO);
|
||||
if (!uart_base)
|
||||
return;
|
||||
|
||||
write32(uart_base + UTRSTAT, UTRSTAT_TXTHRESH | UTRSTAT_RXTHRESH | UTRSTAT_RXTO);
|
||||
}
|
||||
|
||||
int uart_printf(const char *fmt, ...)
|
||||
|
@ -119,7 +146,11 @@ static bool uart_iodev_can_write(void *opaque)
|
|||
static ssize_t uart_iodev_can_read(void *opaque)
|
||||
{
|
||||
UNUSED(opaque);
|
||||
return (read32(UART_BASE + UTRSTAT) & UTRSTAT_RXD) ? 1 : 0;
|
||||
|
||||
if (!uart_base)
|
||||
return 0;
|
||||
|
||||
return (read32(uart_base + UTRSTAT) & UTRSTAT_RXD) ? 1 : 0;
|
||||
}
|
||||
|
||||
static ssize_t uart_iodev_read(void *opaque, void *buf, size_t len)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#include "types.h"
|
||||
|
||||
void uart_init(void);
|
||||
int uart_init(void);
|
||||
|
||||
void uart_putbyte(u8 c);
|
||||
u8 uart_getbyte(void);
|
||||
|
|
24
src/wdt.c
24
src/wdt.c
|
@ -5,6 +5,12 @@
|
|||
#include "types.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define WDT_COUNT 0x10
|
||||
#define WDT_ALARM 0x14
|
||||
#define WDT_CTL 0x1c
|
||||
|
||||
static u64 wdt_base = 0;
|
||||
|
||||
void wdt_disable(void)
|
||||
{
|
||||
int path[8];
|
||||
|
@ -15,16 +21,24 @@ void wdt_disable(void)
|
|||
return;
|
||||
}
|
||||
|
||||
u64 wdt_regs;
|
||||
|
||||
if (adt_get_reg(adt, path, "reg", 0, &wdt_regs, NULL)) {
|
||||
if (adt_get_reg(adt, path, "reg", 0, &wdt_base, NULL)) {
|
||||
printf("Failed to get WDT reg property!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("WDT registers @ 0x%lx\n", wdt_regs);
|
||||
printf("WDT registers @ 0x%lx\n", wdt_base);
|
||||
|
||||
write32(wdt_regs + 0x1c, 0);
|
||||
write32(wdt_base + WDT_CTL, 0);
|
||||
|
||||
printf("WDT disabled\n");
|
||||
}
|
||||
|
||||
void wdt_reboot(void)
|
||||
{
|
||||
if (!wdt_base)
|
||||
return;
|
||||
|
||||
write32(wdt_base + WDT_ALARM, 0x100000);
|
||||
write32(wdt_base + WDT_COUNT, 0);
|
||||
write32(wdt_base + WDT_CTL, 4);
|
||||
}
|
||||
|
|
|
@ -4,5 +4,6 @@
|
|||
#define __WDT_H__
|
||||
|
||||
void wdt_disable(void);
|
||||
void wdt_reboot(void);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue