Raspberry Pi 4 project definition, Mini UART driver

Basic declaration of rpi4 target. Include in main build target for
the reference project (tests other than 'arch' not compiled yet).

Add driver for Mini UART, the main console of Raspberry Pi.

Bug: 140223574
Change-Id: I0450d3076656d81d7376fc168c51f0876af067cf
diff --git a/BUILD.gn b/BUILD.gn
index f18517e..16fa673 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -20,6 +20,7 @@
     "//src:hafnium(:aem_v8a_fvp_clang)",
     "//src:hafnium(:hikey_clang)",
     "//src:hafnium(:qemu_aarch64_clang)",
+    "//src:hafnium(:rpi4_clang)",
   ]
 }
 
@@ -30,6 +31,7 @@
     "//src:unit_tests(:host_fake_clang)",
     "//test/arch(:aem_v8a_fvp_clang)",
     "//test/arch(:qemu_aarch64_clang)",
+    "//test/arch(:rpi4_clang)",
     "//test/linux(:aem_v8a_fvp_vm_clang)",
     "//test/linux(:qemu_aarch64_vm_clang)",
     "//test/vmapi(:aem_v8a_fvp_vm_clang)",
@@ -93,3 +95,19 @@
     pl011_base_address = "0xf7113000"  # UART3
   }
 }
+
+aarch64_toolchains("rpi4") {
+  cpu = "cortex-a72"
+  origin_address = "0x80000"
+  boot_flow = "//src/boot_flow:linux"
+  console = "//project/reference/rpi:mini_uart"
+  gic_version = 2
+  heap_pages = 60
+  max_cpus = 4
+  max_vms = 16
+  toolchain_args = {
+    gpio_base_address = "0xfe200000"
+    aux_base_address = "0xfe215000"
+    core_freq_mhz = 500
+  }
+}
diff --git a/rpi/BUILD.gn b/rpi/BUILD.gn
new file mode 100644
index 0000000..fb7d701
--- /dev/null
+++ b/rpi/BUILD.gn
@@ -0,0 +1,36 @@
+# Copyright 2019 The Hafnium Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("args.gni")
+
+source_set("mini_uart") {
+  sources = [
+    "mini_uart.c",
+  ]
+
+  assert(gpio_base_address != 0,
+         "\"gpio_base_address\" must be defined for ${target_name}.")
+  assert(aux_base_address != 0,
+         "\"aux_base_address\" must be defined for ${target_name}.")
+  assert(core_freq_mhz != 0,
+         "\"core_freq_mhz\" must be defined for ${target_name}.")
+  assert(baudrate != 0, "\"baudrate\" must be defined for ${target_name}.")
+
+  defines = [
+    "GPIO_BASE=${gpio_base_address}",
+    "AUX_BASE=${aux_base_address}",
+    "CORE_FREQ_MHZ=${core_freq_mhz}",
+    "BAUDRATE=${baudrate}",
+  ]
+}
diff --git a/rpi/args.gni b/rpi/args.gni
new file mode 100644
index 0000000..c322192
--- /dev/null
+++ b/rpi/args.gni
@@ -0,0 +1,20 @@
+# Copyright 2019 The Hafnium Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+declare_args() {
+  gpio_base_address = 0
+  aux_base_address = 0
+  core_freq_mhz = 0
+  baudrate = 115200  # standard value
+}
diff --git a/rpi/mini_uart.c b/rpi/mini_uart.c
new file mode 100644
index 0000000..79d5a60
--- /dev/null
+++ b/rpi/mini_uart.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2019 The Hafnium Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "hf/io.h"
+#include "hf/mm.h"
+#include "hf/mpool.h"
+#include "hf/plat/console.h"
+
+/* clang-format off */
+
+#define GPFSEL1               IO32_C(GPIO_BASE + 0x4)
+
+#define AUX_ENABLES           IO32_C(AUX_BASE + 0x4)
+#define AUX_MU_IO_REG         IO32_C(AUX_BASE + 0x40)
+#define AUX_MU_IER_REG        IO32_C(AUX_BASE + 0x44)
+#define AUX_MU_LCR_REG        IO32_C(AUX_BASE + 0x4c)
+#define AUX_MU_MCR_REG        IO32_C(AUX_BASE + 0x50)
+#define AUX_MU_LSR_REG        IO32_C(AUX_BASE + 0x54)
+#define AUX_MU_CNTL_REG       IO32_C(AUX_BASE + 0x60)
+#define AUX_MU_BAUD_REG       IO32_C(AUX_BASE + 0x68)
+
+#define AUX_MU_LSR_TX_EMPTY   (UINT32_C(1) << 5)
+#define AUX_MU_LSR_TX_IDLE    (UINT32_C(1) << 6)
+
+#define MHZ_TO_HZ             UINT32_C(1000000)
+
+/* clang-format on */
+
+void plat_console_init(void)
+{
+	uint32_t selector;
+
+	selector = io_read32(GPFSEL1);
+	/* Set GPIO14 to function 5. */
+	selector &= ~(7 << 12);
+	selector |= 2 << 12;
+	/* Set GPIO15 to function 5 */
+	selector &= ~(7 << 15);
+	selector |= 2 << 15;
+	io_write32(GPFSEL1, selector);
+
+	/*
+	 * With 8-times oversampling, baudrate is calculated as:
+	 *   baudrate = system_clock_freq / (8 * (baudrate_reg + 1))
+	 * Therefore:
+	 *   baudrate_reg = (system_clock_freq / (8 * baudrate)) -1
+	 */
+	uint32_t system_clock_freq = UINT32_C(CORE_FREQ_MHZ) * MHZ_TO_HZ;
+	uint32_t oversampled_baudrate = UINT32_C(8) * UINT32_C(BAUDRATE);
+	uint32_t baudrate_reg =
+		(system_clock_freq / oversampled_baudrate) - UINT32_C(1);
+
+	/* Enable Mini UART and access to its registers. */
+	io_write32(AUX_ENABLES, 1);
+	/* Disable auto flow control and disable receiver and transmitter. */
+	io_write32(AUX_MU_CNTL_REG, 0);
+	/* Disable receive and transmit interrupts. */
+	io_write32(AUX_MU_IER_REG, 0);
+	/* Enable 8 bit mode. */
+	io_write32(AUX_MU_LCR_REG, 3);
+	/* Set RTS line to be always high. */
+	io_write32(AUX_MU_MCR_REG, 0);
+	/* Set baud rate. */
+	io_write32(AUX_MU_BAUD_REG, baudrate_reg);
+	/* Enable transmitter and receiver. */
+	io_write32(AUX_MU_CNTL_REG, 3);
+
+	memory_ordering_barrier();
+}
+
+void plat_console_mm_init(struct mm_stage1_locked stage1_locked,
+			  struct mpool *ppool)
+{
+	mm_identity_map(stage1_locked, pa_init(GPIO_BASE),
+			pa_add(pa_init(GPIO_BASE), PAGE_SIZE),
+			MM_MODE_R | MM_MODE_W | MM_MODE_D, ppool);
+	mm_identity_map(stage1_locked, pa_init(AUX_BASE),
+			pa_add(pa_init(AUX_BASE), PAGE_SIZE),
+			MM_MODE_R | MM_MODE_W | MM_MODE_D, ppool);
+}
+
+void plat_console_putchar(char c)
+{
+	/* Print a carriage-return as well. */
+	if (c == '\n') {
+		plat_console_putchar('\r');
+	}
+
+	/* Wait for the transmitter to be ready to accept a byte. */
+	while ((io_read32(AUX_MU_LSR_REG) & AUX_MU_LSR_TX_EMPTY) == 0) {
+	}
+
+	/* Write data to transmitter FIFO. */
+	memory_ordering_barrier();
+	io_write32(AUX_MU_IO_REG, c);
+	memory_ordering_barrier();
+
+	/* Wait until the transmitter is no longer busy. */
+	while ((io_read32(AUX_MU_LSR_REG) & AUX_MU_LSR_TX_IDLE) == 0) {
+	}
+}
diff --git a/rpi4/BUILD.gn b/rpi4/BUILD.gn
new file mode 100644
index 0000000..bf974e6
--- /dev/null
+++ b/rpi4/BUILD.gn
@@ -0,0 +1,16 @@
+# Copyright 2019 The Hafnium Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+source_set("rpi4") {
+}