1/** 2 * \file plat_apm88xxxx.c 3 * \brief 4 */ 5 6/* 7 * Copyright (c) 2016 ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <kernel.h> 16#include <offsets.h> 17#include <arch/arm/platform.h> 18#include <serial.h> 19#include <dev/apm88xxxx/apm88xxxx_pc16550_dev.h> 20#include <arch/arm/gic.h> 21#include <sysreg.h> 22#include <dev/armv8_dev.h> 23#include <barrelfish_kpi/arm_core_data.h> 24#include <psci.h> 25#include <arch/armv8/global.h> 26#include <paging_kernel_arch.h> 27 28/* the maximum number of UARTS supported */ 29#define MAX_NUM_UARTS 4 30 31static apm88xxxx_pc16550_t ports[MAX_NUM_UARTS]; 32 33 34errval_t serial_init(unsigned port, bool initialize_hw) 35{ 36 if (port >= MAX_NUM_UARTS) { 37 return SYS_ERR_SERIAL_PORT_INVALID; 38 } 39 40 if ((lpaddr_t)ports[port].base == (platform_uart_base[port] + KERNEL_OFFSET)) { 41 return SYS_ERR_OK; 42 } 43 44 apm88xxxx_pc16550_t *uart = &ports[port]; 45 apm88xxxx_pc16550_initialize(uart, (mackerel_addr_t)(platform_uart_base[port] + KERNEL_OFFSET)); 46 47 if (!initialize_hw) { 48 // hw initialized, this is for non-bsp cores, where hw has been 49 // initialized by bsp core and we come through here just to setup our 50 // local apm88xxxx_pc16550 struct for the port. 51 return SYS_ERR_OK; 52 } 53 54 panic("device init NYI"); 55 return SYS_ERR_OK; 56} 57 58errval_t serial_early_init(unsigned port) 59{ 60 if (port >= MAX_NUM_UARTS) { 61 return SYS_ERR_SERIAL_PORT_INVALID; 62 } 63 64 if ((lpaddr_t)ports[port].base == platform_uart_base[port]) { 65 return SYS_ERR_OK; 66 } 67 68 apm88xxxx_pc16550_t *uart = &ports[port]; 69 apm88xxxx_pc16550_initialize(uart, (mackerel_addr_t)platform_uart_base[port]); 70 return SYS_ERR_OK; 71} 72 73errval_t serial_early_init_mmu_enabled(unsigned port) 74{ 75 return serial_early_init(port); 76} 77 78 79/** 80 * \brief Prints a single character to a serial port. 81 */ 82void serial_putchar(unsigned port, char c) 83{ 84 assert(port < MAX_NUM_UARTS); 85 assert(ports[port].base != 0); 86 // Wait until FIFO can hold more characters 87 while(!apm88xxxx_pc16550_LSR_thre_rdf(&ports[port])); 88 // Write character 89 apm88xxxx_pc16550_THR_thr_wrf(&ports[port], c); 90} 91 92/** 93 * \brief Reads a single character from the default serial port. 94 * This function spins waiting for a character to arrive. 95 */ 96char serial_getchar(unsigned port) 97{ 98 assert(port < MAX_NUM_UARTS); 99 assert(ports[port].base != 0); 100 101 // Wait until character available 102 while(!apm88xxxx_pc16550_LSR_dr_rdf(&ports[port])); 103 // Read a character from FIFO 104 return apm88xxxx_pc16550_RBR_rbr_rdf(&ports[port]); 105} 106 107 108void platform_get_info(struct platform_info *pi) 109{ 110 pi->arch = PI_ARCH_ARMV8A; 111 pi->platform = PI_PLATFORM_APM88XXXX; 112} 113 114void armv8_get_info(struct arch_info_armv8 *ai) 115{ 116 117} 118 119void platform_revision_init(void) 120{ 121 122} 123 124errval_t platform_boot_core(hwid_t target, genpaddr_t gen_entry, genpaddr_t context) 125{ 126 printf("Invoking PSCI on: cpu=0x%lx, entry=0x%lx, context=0x%lx\n", target, gen_entry, context); 127 struct armv8_core_data *cd = (struct armv8_core_data *)local_phys_to_mem(context); 128 cd->page_table_root = armv8_TTBR1_EL1_rd(NULL); 129 cd->cpu_driver_globals_pointer = (uintptr_t)global; 130 __asm volatile("dsb sy\n" 131 "dmb sy\n" 132 "isb \n"); 133 134 /* 135 * An IRQ interrupt, even if the PSTATE I-bit is set. 136An FIQ interrupt, even if the PSTATE F-bit is set. 137 * 138 * 139 */ 140 141 gic_raise_softirq(target, 1); 142 143 return SYS_ERR_OK; 144} 145 146/* 147 * Return the core count 148 */ 149size_t platform_get_core_count(void) 150{ 151 return 0; 152} 153 154uint32_t platform_get_timer_interrupt(void){ 155 // TODO (LH): Untested 156 return 30; 157} 158