@@ -15,6 +15,8 @@
#include <asm/psci.h>
#include <asm/spinlock.h>
#include <asm/io.h>
+#include <asm/mmu.h>
+#include <asm/thread_info.h>
#include "io.h"
@@ -29,6 +31,29 @@ static struct spinlock uart_lock;
#define UART_EARLY_BASE (u8 *)(unsigned long)CONFIG_UART_EARLY_BASE
static volatile u8 *uart0_base = UART_EARLY_BASE;
+static void uart_unmap_early_base(void)
+{
+ pteval_t *ptevalp;
+ pgd_t *pgtable;
+
+ if (mmu_enabled()) {
+ pgtable = current_thread_info()->pgtable;
+ } else {
+ pgtable = mmu_idmap;
+ }
+
+ /*
+ * The UART has been mapped early in the boot process and the PTE has
+ * been allocated using the physical allocator, which means it cannot be
+ * freed.
+ */
+ ptevalp = follow_pte(pgtable, (uintptr_t)UART_EARLY_BASE);
+ if (ptevalp) {
+ WRITE_ONCE(*ptevalp, 0);
+ flush_tlb_page((uintptr_t)UART_EARLY_BASE);
+ }
+}
+
static void uart0_init_fdt(void)
{
/*
@@ -98,11 +123,17 @@ void io_init(void)
printf("WARNING: early print support may not work. "
"Found uart at %p, but early base is %p.\n",
uart0_base, UART_EARLY_BASE);
+ uart_unmap_early_base();
}
chr_testdev_init();
}
+void __iomem *uart_early_base(void)
+{
+ return UART_EARLY_BASE;
+}
+
void puts(const char *s)
{
spin_lock(&uart_lock);
@@ -7,6 +7,9 @@
#ifndef _ARM_IO_H_
#define _ARM_IO_H_
+#include <asm/io.h>
+
extern void io_init(void);
+extern void __iomem *uart_early_base(void);
#endif
@@ -15,6 +15,7 @@
#include <asm/pgtable.h>
#include <asm/pgtable-hwdef.h>
+#include "io.h"
#include "vmalloc.h"
#include <linux/compiler.h>
@@ -233,6 +234,8 @@ void mmu_setup_early(phys_addr_t phys_end)
}
}
+ ioremap((phys_addr_t)(unsigned long)uart_early_base(), PAGE_SIZE);
+
/*
* Open-code part of mmu_enabled(), because at this point thread_info
* hasn't been initialized. mmu_mark_enabled() cannot be called here