arm64: Enable DTB handling, Introduce LINFlex UART driver
Change-Id: Ib643545271700e6ff4a4037d0e797355194927e7 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5149 Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org> Reviewed-by: David Karoly <karolyd577@gmail.com> Reviewed-by: Fredrik Holmqvist <fredrik.holmqvist@gmail.com>
This commit is contained in:
parent
955acf7e19
commit
476346ac62
@ -11,6 +11,7 @@
|
||||
|
||||
|
||||
#include <util/FixedWidthPointer.h>
|
||||
#include <boot/interrupt_controller.h>
|
||||
#include <boot/uart.h>
|
||||
|
||||
|
||||
@ -18,15 +19,16 @@
|
||||
|
||||
|
||||
typedef struct {
|
||||
// needed for UEFI, otherwise kernel acpi support can't find ACPI root
|
||||
FixedWidthPointer<void> acpi_root;
|
||||
// TODO: Deal with this later in the port
|
||||
// FixedWidthPointer<void> fdt;
|
||||
// uart_info uart;
|
||||
uint64 phys_pgdir;
|
||||
uint64 vir_pgdir;
|
||||
uint64 next_pagetable;
|
||||
|
||||
uint64 phys_pgdir;
|
||||
uint64 vir_pgdir;
|
||||
uint64 next_pagetable;
|
||||
// needed for UEFI, otherwise kernel acpi support can't find ACPI root
|
||||
FixedWidthPointer<void> acpi_root;
|
||||
FixedWidthPointer<void> fdt;
|
||||
|
||||
uart_info uart;
|
||||
intc_info interrupt_controller;
|
||||
|
||||
} _PACKED arch_kernel_args;
|
||||
|
||||
|
554
headers/private/kernel/arch/arm64/arch_uart_linflex.h
Normal file
554
headers/private/kernel/arch/arm64/arch_uart_linflex.h
Normal file
@ -0,0 +1,554 @@
|
||||
/*
|
||||
* Copyright 2022 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Oliver Ruiz Dorantes, oliver.ruiz.dorantes@gmail.com
|
||||
*/
|
||||
#ifndef __DEV_UART_LINFLEX_H
|
||||
#define __DEV_UART_LINFLEX_H
|
||||
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <ByteOrder.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include <arch/generic/debug_uart.h>
|
||||
|
||||
|
||||
#define UART_KIND_LINFLEX "linflex"
|
||||
|
||||
namespace LINFlexRegisters {
|
||||
typedef union { /* LINFLEX LIN Control 1 (Base+0x0000) */
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32 :16;
|
||||
vuint32 CCD:1;
|
||||
vuint32 CFD:1;
|
||||
vuint32 LASE:1;
|
||||
vuint32 AWUM:1;
|
||||
vuint32 MBL:4;
|
||||
vuint32 BF:1;
|
||||
vuint32 SFTM:1;
|
||||
vuint32 LBKM:1;
|
||||
vuint32 MME:1;
|
||||
vuint32 SBDT:1;
|
||||
vuint32 RBLM:1;
|
||||
vuint32 SLEEP:1;
|
||||
vuint32 INIT:1;
|
||||
#endif
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
vuint32 INIT:1;
|
||||
vuint32 SLEEP:1;
|
||||
vuint32 RBLM:1;
|
||||
vuint32 SBDT:1;
|
||||
vuint32 MME:1;
|
||||
vuint32 LBKM:1;
|
||||
vuint32 SFTM:1;
|
||||
vuint32 BF:1;
|
||||
vuint32 MBL:4;
|
||||
vuint32 AWUM:1;
|
||||
vuint32 LASE:1;
|
||||
vuint32 CFD:1;
|
||||
vuint32 CCD:1;
|
||||
vuint32 :16;
|
||||
#endif
|
||||
} B;
|
||||
} LINCR1_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX LIN Interrupt Enable (Base+0x0004) */
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32 :16;
|
||||
vuint32 SZIE:1;
|
||||
vuint32 OCIE:1;
|
||||
vuint32 BEIE:1;
|
||||
vuint32 CEIE:1;
|
||||
vuint32 HEIE:1;
|
||||
vuint32:2;
|
||||
vuint32 FEIE:1;
|
||||
vuint32 BOIE:1;
|
||||
vuint32 LSIE:1;
|
||||
vuint32 WUIE:1;
|
||||
vuint32 DBFIE:1;
|
||||
vuint32 DBEIE:1;
|
||||
vuint32 DRIE:1;
|
||||
vuint32 DTIE:1;
|
||||
vuint32 HRIE:1;
|
||||
#endif
|
||||
} B;
|
||||
} LINIER_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX LIN Status (Base+0x0008) */
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32 :16;
|
||||
vuint32 LINS:4;
|
||||
vuint32:2;
|
||||
vuint32 RMB:1;
|
||||
vuint32:1;
|
||||
vuint32 RBSY:1;
|
||||
vuint32 RPS:1;
|
||||
vuint32 WUF:1;
|
||||
vuint32 DBFF:1;
|
||||
vuint32 DBEF:1;
|
||||
vuint32 DRF:1;
|
||||
vuint32 DTF:1;
|
||||
vuint32 HRF:1;
|
||||
#endif
|
||||
} B;
|
||||
} LINSR_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX LIN Error Status (Base+0x000C) */
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32 :16;
|
||||
vuint32 SZF:1;
|
||||
vuint32 OCF:1;
|
||||
vuint32 BEF:1;
|
||||
vuint32 CEF:1;
|
||||
vuint32 SFEF:1;
|
||||
vuint32 BDEF:1;
|
||||
vuint32 IDPEF:1;
|
||||
vuint32 FEF:1;
|
||||
vuint32 BOF:1;
|
||||
vuint32:6;
|
||||
vuint32 NF:1;
|
||||
#endif
|
||||
} B;
|
||||
} LINESR_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX UART Mode Control (Base+0x0010) */
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32 :16;
|
||||
vuint32:1;
|
||||
vuint32 TDFL:2;
|
||||
vuint32:1;
|
||||
vuint32 RDFL:2;
|
||||
vuint32 RFBM:1;
|
||||
vuint32 TFBM:1;
|
||||
vuint32 WL1:1;
|
||||
vuint32 PC1:1;
|
||||
vuint32 RXEN:1;
|
||||
vuint32 TXEN:1;
|
||||
vuint32 PC0:1;
|
||||
vuint32 PCE:1;
|
||||
vuint32 WL:1;
|
||||
vuint32 UART:1;
|
||||
#endif
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
vuint32 UART:1;
|
||||
vuint32 WL:1;
|
||||
vuint32 PCE:1;
|
||||
vuint32 PC0:1;
|
||||
vuint32 TXEN:1;
|
||||
vuint32 RXEN:1;
|
||||
vuint32 PC1:1;
|
||||
vuint32 WL1:1;
|
||||
vuint32 TFBM:1;
|
||||
vuint32 RFBM:1;
|
||||
vuint32 RDFL:2;
|
||||
vuint32:1;
|
||||
vuint32 TDFL:2;
|
||||
vuint32:1;
|
||||
vuint32 :16;
|
||||
#endif
|
||||
} B;
|
||||
} UARTCR_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX UART Mode Status (Base+0x0014) */
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32 :16;
|
||||
vuint32 SZF:1;
|
||||
vuint32 OCF:1;
|
||||
vuint32 PE:4; /*Can check all 4 RX'd bytes at once with array*/
|
||||
vuint32 RMB:1;
|
||||
vuint32 FEF:1;
|
||||
vuint32 BOF:1;
|
||||
vuint32 RPS:1;
|
||||
vuint32 WUF:1;
|
||||
vuint32:2;
|
||||
vuint32 DRF:1;
|
||||
vuint32 DTF:1;
|
||||
vuint32 NF:1;
|
||||
#endif
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
vuint32 NF:1;
|
||||
vuint32 DTF:1;
|
||||
vuint32 DRF:1;
|
||||
vuint32:2;
|
||||
vuint32 WUF:1;
|
||||
vuint32 RPS:1;
|
||||
vuint32 BOF:1;
|
||||
vuint32 FEF:1;
|
||||
vuint32 RMB:1;
|
||||
vuint32 PE:4; /*Can check all 4 RX'd bytes at once with array*/
|
||||
vuint32 OCF:1;
|
||||
vuint32 SZF:1;
|
||||
vuint32 :16;
|
||||
#endif
|
||||
} B;
|
||||
} UARTSR_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX TimeOut Control Status ((Base+0x0018)*/
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32 :16;
|
||||
vuint32:5;
|
||||
vuint32 LTOM:1;
|
||||
vuint32 IOT:1;
|
||||
vuint32 TOCE:1;
|
||||
vuint32 CNT:8;
|
||||
#endif
|
||||
} B;
|
||||
} LINTCSR_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX LIN Output Compare (Base+0x001C) */
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32 :16;
|
||||
vuint32 OC2:8;
|
||||
vuint32 OC1:8;
|
||||
#endif
|
||||
} B;
|
||||
} LINOCR_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX LIN Timeout Control (Base+0x0020) */
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32 :20;
|
||||
vuint32 RTO:4;
|
||||
vuint32:1;
|
||||
vuint32 HTO:7;
|
||||
#endif
|
||||
} B;
|
||||
} LINTOCR_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX LIN Fractional Baud Rate (+0x0024) */
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32:28;
|
||||
vuint32 DIV_F:4;
|
||||
#endif
|
||||
} B;
|
||||
} LINFBRR_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX LIN Integer Baud Rate (Base+0x0028) */
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32:19;
|
||||
vuint32 DIV_M:13;
|
||||
#endif
|
||||
} B;
|
||||
} LINIBRR_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX LIN Checksum Field (Base+0x002C) */
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32:24;
|
||||
vuint32 CF:8;
|
||||
#endif
|
||||
} B;
|
||||
} LINCFR_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX LIN Control 2 (Base+0x0030) */
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32:17;
|
||||
vuint32 IOBE:1;
|
||||
vuint32 IOPE:1;
|
||||
vuint32 WURQ:1;
|
||||
vuint32 DDRQ:1;
|
||||
vuint32 DTRQ:1;
|
||||
vuint32 ABRQ:1;
|
||||
vuint32 HTRQ:1;
|
||||
vuint32:8;
|
||||
#endif
|
||||
} B;
|
||||
} LINCR2_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX Buffer Identifier (Base+0x0034) */
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32:16;
|
||||
vuint32 DFL:6;
|
||||
vuint32 DIR:1;
|
||||
vuint32 CCS:1;
|
||||
vuint32:2;
|
||||
vuint32 ID:6;
|
||||
#endif
|
||||
} B;
|
||||
} BIDR_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX Buffer Data LSB (Base+0x0038) */
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32 DATA3:8;
|
||||
vuint32 DATA2:8;
|
||||
vuint32 DATA1:8;
|
||||
vuint32 DATA0:8;
|
||||
#endif
|
||||
} B;
|
||||
} BDRL_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX Buffer Data MSB (Base+0x003C */
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32 DATA7:8;
|
||||
vuint32 DATA6:8;
|
||||
vuint32 DATA5:8;
|
||||
vuint32 DATA4:8;
|
||||
#endif
|
||||
} B;
|
||||
} BDRM_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX Identifier Filter Enable (+0x0040) */
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32:24;
|
||||
vuint32 FACT:8;
|
||||
#endif
|
||||
} B;
|
||||
} IFER_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX Identifier Filter Match Index (+0x0044)*/
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32:28;
|
||||
vuint32 IFMI:4;
|
||||
#endif
|
||||
} B;
|
||||
} IFMI_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX Identifier Filter Mode (Base+0x0048) */
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32:28;
|
||||
vuint32 IFM:4;
|
||||
#endif
|
||||
} B;
|
||||
} IFMR_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX Identifier Filter Control 0..15 (+0x004C-0x0088)*/
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32:16;
|
||||
vuint32:3;
|
||||
vuint32 DFL:3;
|
||||
vuint32 DIR:1;
|
||||
vuint32 CCS:1;
|
||||
vuint32:2;
|
||||
vuint32 ID:6;
|
||||
#endif
|
||||
} B;
|
||||
} IFCR_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX Global Counter (+0x008C) */
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32:26;
|
||||
vuint32 TDFBM:1;
|
||||
vuint32 RDFBM:1;
|
||||
vuint32 TDLIS:1;
|
||||
vuint32 RDLIS:1;
|
||||
vuint32 STOP:1;
|
||||
vuint32 SR:1;
|
||||
#endif
|
||||
} B;
|
||||
} GCR_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX UART preset timeout (+0x0090) */
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32:20;
|
||||
vuint32 PTO:12;
|
||||
#endif
|
||||
} B;
|
||||
} UARTPTO_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX UART current timeout (+0x0094) */
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32:20;
|
||||
vuint32 CTO:12;
|
||||
#endif
|
||||
} B;
|
||||
} UARTCTO_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX DMA Tx Enable (+0x0098) */
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32:16;
|
||||
vuint32 DTE15:1;
|
||||
vuint32 DTE14:1;
|
||||
vuint32 DTE13:1;
|
||||
vuint32 DTE12:1;
|
||||
vuint32 DTE11:1;
|
||||
vuint32 DTE10:1;
|
||||
vuint32 DTE9:1;
|
||||
vuint32 DTE8:1;
|
||||
vuint32 DTE7:1;
|
||||
vuint32 DTE6:1;
|
||||
vuint32 DTE5:1;
|
||||
vuint32 DTE4:1;
|
||||
vuint32 DTE3:1;
|
||||
vuint32 DTE2:1;
|
||||
vuint32 DTE1:1;
|
||||
vuint32 DTE0:1;
|
||||
#endif
|
||||
} B;
|
||||
} DMATXE_register;
|
||||
|
||||
|
||||
typedef union { /* LINFLEX DMA RX Enable (+0x009C) */
|
||||
vuint32 R;
|
||||
struct {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
vuint32:16;
|
||||
vuint32 DRE15:1;
|
||||
vuint32 DRE14:1;
|
||||
vuint32 DRE13:1;
|
||||
vuint32 DRE12:1;
|
||||
vuint32 DRE11:1;
|
||||
vuint32 DRE10:1;
|
||||
vuint32 DRE9:1;
|
||||
vuint32 DRE8:1;
|
||||
vuint32 DRE7:1;
|
||||
vuint32 DRE6:1;
|
||||
vuint32 DRE5:1;
|
||||
vuint32 DRE4:1;
|
||||
vuint32 DRE3:1;
|
||||
vuint32 DRE2:1;
|
||||
vuint32 DRE1:1;
|
||||
vuint32 DRE0:1;
|
||||
#endif
|
||||
} B;
|
||||
} DMARXE_register;
|
||||
|
||||
// Helper to deal with w1c (Write 1 to clear) register fields
|
||||
template<typename REG>
|
||||
REG BitfieldRegister() {
|
||||
REG reg;
|
||||
reg.R = 0;
|
||||
return reg;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
LINCR1_register LINCR1; /* LINFLEX LIN Control 1 (Base+0x0000) */
|
||||
LINIER_register LINIER; /* LINFLEX LIN Interrupt Enable (Base+0x0004) */
|
||||
LINSR_register LINSR; /* LINFLEX LIN Status (Base+0x0008) */
|
||||
LINESR_register LINESR; /* LINFLEX LIN Error Status (Base+0x000C) */
|
||||
UARTCR_register UARTCR; /* LINFLEX UART Mode Control (Base+0x0010) */
|
||||
UARTSR_register UARTSR; /* LINFLEX UART Mode Status (Base+0x0014) */
|
||||
LINTCSR_register LINTCSR; /* LINFLEX TimeOut Control Status ((Base+0x0018)*/
|
||||
LINOCR_register LINOCR; /* LINFLEX LIN Output Compare (Base+0x001C) */
|
||||
LINTOCR_register LINTOCR; /* LINFLEX LIN Timeout Control (Base+0x0020) */
|
||||
LINFBRR_register LINFBRR; /* LINFLEX LIN Fractional Baud Rate (+0x0024) */
|
||||
LINIBRR_register LINIBRR; /* LINFLEX LIN Integer Baud Rate (Base+0x0028) */
|
||||
LINCFR_register LINCFR; /* LINFLEX LIN Checksum Field (Base+0x002C) */
|
||||
LINCR2_register LINCR2; /* LINFLEX LIN Control 2 (Base+0x0030) */
|
||||
BIDR_register BIDR; /* LINFLEX Buffer Identifier (Base+0x0034) */
|
||||
BDRL_register BDRL; /* LINFLEX Buffer Data LSB (Base+0x0038) */
|
||||
BDRM_register BDRM; /* LINFLEX Buffer Data MSB (Base+0x003C */
|
||||
IFER_register IFER; /* LINFLEX Identifier Filter Enable (+0x0040) */
|
||||
IFMI_register IFMI; /* LINFLEX Identifier Filter Match Index (+0x0044)*/
|
||||
IFMR_register IFMR; /* LINFLEX Identifier Filter Mode (Base+0x0048) */
|
||||
IFCR_register IFCR[16]; /* LINFLEX Identifier Filter Control 0..15 (+0x004C-0x0088)*/
|
||||
GCR_register GCR; /* LINFLEX Global Counter (+0x008C) */
|
||||
UARTPTO_register UARTPTO; /* LINFLEX UART preset timeout (+0x0090) */
|
||||
UARTCTO_register UARTCTO; /* LINFLEX UART current timeout (+0x0094) */
|
||||
DMATXE_register DMATXE; /* LINFLEX DMA Tx Enable (+0x0098) */
|
||||
DMARXE_register DMARXE; /* LINFLEX DMA RX Enable (+0x009C) */
|
||||
} LINFlex;
|
||||
}
|
||||
|
||||
|
||||
class ArchUARTlinflex : public DebugUART {
|
||||
|
||||
public:
|
||||
ArchUARTlinflex(addr_t base, int64 clock);
|
||||
~ArchUARTlinflex();
|
||||
|
||||
void InitEarly();
|
||||
void InitPort(uint32 baud);
|
||||
|
||||
void Enable();
|
||||
void Disable();
|
||||
|
||||
int PutChar(char c);
|
||||
int GetChar(bool wait);
|
||||
|
||||
void FlushTx();
|
||||
void FlushRx();
|
||||
|
||||
private:
|
||||
template<typename TO, typename TA>
|
||||
void Out(TA* reg, TO value) {
|
||||
*(volatile TO*)(reg) = value;
|
||||
}
|
||||
|
||||
template<typename TI, typename TA>
|
||||
TI In(TA* reg) {
|
||||
return *(volatile TI*)(reg);
|
||||
}
|
||||
|
||||
virtual void Barrier();
|
||||
LINFlexRegisters::LINFlex* LinflexCell() {
|
||||
return reinterpret_cast<LINFlexRegisters::LINFlex*>(Base());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
ArchUARTlinflex *arch_get_uart_linflex(addr_t base, int64 clock);
|
||||
|
||||
|
||||
#endif
|
@ -4,6 +4,16 @@ local platform ;
|
||||
|
||||
local kernelArchSources =
|
||||
arch_elf.cpp
|
||||
arch_uart_linflex.cpp
|
||||
;
|
||||
|
||||
local kernelArchReusableSources =
|
||||
arch_uart_pl011.cpp
|
||||
;
|
||||
|
||||
local kernelGenericDriverSources =
|
||||
debug_uart.cpp
|
||||
debug_uart_8250.cpp
|
||||
;
|
||||
|
||||
kernelLibGenericSources =
|
||||
@ -23,16 +33,23 @@ for platform in [ MultiBootSubDirSetup efi ] {
|
||||
|
||||
|
||||
BootMergeObject [ FGristFiles boot_arch_$(TARGET_KERNEL_ARCH).o ] :
|
||||
$(kernelGenericDriverSources)
|
||||
$(kernelArchSources)
|
||||
$(kernelArchReusableSources)
|
||||
$(kernelLibArchSources)
|
||||
$(kernelLibGenericSources)
|
||||
$(librootOsArchSources)
|
||||
|
||||
arch_cpu.cpp
|
||||
: # additional flags
|
||||
;
|
||||
|
||||
SEARCH on [ FGristFiles $(kernelGenericDriverSources) ]
|
||||
= [ FDirName $(HAIKU_TOP) src system kernel arch generic ] ;
|
||||
SEARCH on [ FGristFiles $(kernelArchSources) ]
|
||||
= [ FDirName $(HAIKU_TOP) src system kernel arch arm64 ] ;
|
||||
= [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_KERNEL_ARCH_DIR) ] ;
|
||||
SEARCH on [ FGristFiles $(kernelArchReusableSources) ]
|
||||
= [ FDirName $(HAIKU_TOP) src system kernel arch arm ] ;
|
||||
SEARCH on [ FGristFiles $(kernelLibGenericSources) ]
|
||||
= [ FDirName $(HAIKU_TOP) src system libroot posix string arch generic ] ;
|
||||
SEARCH on [ FGristFiles $(kernelLibArchSources) ]
|
||||
|
@ -5,7 +5,7 @@ UsePrivateHeaders [ FDirName kernel platform ] ;
|
||||
UsePrivateHeaders [ FDirName kernel boot platform efi ] ;
|
||||
UsePrivateHeaders [ FDirName kernel boot arch $(TARGET_KERNEL_ARCH_DIR) ] ;
|
||||
|
||||
if $(TARGET_ARCH) != x86_64 && $(TARGET_ARCH) != x86 && $(TARGET_ARCH) != arm64 {
|
||||
if $(TARGET_ARCH) != x86_64 && $(TARGET_ARCH) != x86 {
|
||||
UseLibraryHeaders [ FDirName libfdt ] ;
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ SubDirHdrs $(HAIKU_TOP) src add-ons kernel partitioning_systems gpt ;
|
||||
{
|
||||
local defines = _BOOT_MODE _BOOT_PLATFORM_EFI ;
|
||||
|
||||
if $(TARGET_ARCH) != x86_64 && $(TARGET_ARCH) != x86 && $(TARGET_ARCH) != arm64 {
|
||||
if $(TARGET_ARCH) != x86_64 && $(TARGET_ARCH) != x86 {
|
||||
defines += _BOOT_FDT_SUPPORT ;
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ local platform_src =
|
||||
|
||||
local support_libs ;
|
||||
|
||||
if $(TARGET_ARCH) != x86_64 && $(TARGET_ARCH) != x86 && $(TARGET_ARCH) != arm64 {
|
||||
if $(TARGET_ARCH) != x86_64 && $(TARGET_ARCH) != x86 {
|
||||
support_libs += boot_fdt.a ;
|
||||
platform_src += dtb.cpp ;
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ SubDir HAIKU_TOP src system boot platform efi arch arm64 ;
|
||||
|
||||
SubDirHdrs $(HAIKU_TOP) src system boot platform efi ;
|
||||
|
||||
UseLibraryHeaders [ FDirName libfdt ] ;
|
||||
|
||||
UsePrivateHeaders [ FDirName kernel platform ] ;
|
||||
UsePrivateHeaders [ FDirName kernel boot platform efi ] ;
|
||||
|
||||
@ -27,6 +29,7 @@ for platform in [ MultiBootSubDirSetup efi ] {
|
||||
arch_start.cpp
|
||||
arch_timer.cpp
|
||||
arch_cache.cpp
|
||||
arch_dtb.cpp
|
||||
;
|
||||
|
||||
BootMergeObject boot_platform_efi_arm64.o :
|
||||
|
97
src/system/boot/platform/efi/arch/arm64/arch_dtb.cpp
Normal file
97
src/system/boot/platform/efi/arch/arm64/arch_dtb.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander von Gluck IV <kallisti5@unixzen.com>
|
||||
*/
|
||||
|
||||
#include <arch_cpu_defs.h>
|
||||
#include <arch_dtb.h>
|
||||
#include <arch_smp.h>
|
||||
#include <boot/platform.h>
|
||||
#include <boot/stage2.h>
|
||||
|
||||
extern "C" {
|
||||
#include <libfdt.h>
|
||||
}
|
||||
|
||||
#include "dtb.h"
|
||||
|
||||
/* TODO: Code taken from ARM port just for building purposes */
|
||||
|
||||
/* The potential interrupt controoller would be present in the dts as:
|
||||
* compatible = "arm,gic-v3";
|
||||
*/
|
||||
const struct supported_interrupt_controllers {
|
||||
const char* dtb_compat;
|
||||
const char* kind;
|
||||
} kSupportedInterruptControllers[] = {
|
||||
{ "arm,cortex-a9-gic", INTC_KIND_GICV1 },
|
||||
{ "arm,cortex-a15-gic", INTC_KIND_GICV2 },
|
||||
{ "ti,omap3-intc", INTC_KIND_OMAP3 },
|
||||
{ "marvell,pxa-intc", INTC_KIND_PXA },
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
arch_handle_fdt(const void* fdt, int node)
|
||||
{
|
||||
const char* deviceType = (const char*)fdt_getprop(fdt, node,
|
||||
"device_type", NULL);
|
||||
|
||||
if (deviceType != NULL) {
|
||||
if (strcmp(deviceType, "cpu") == 0) {
|
||||
platform_cpu_info* info = NULL;
|
||||
arch_smp_register_cpu(&info);
|
||||
if (info == NULL)
|
||||
return;
|
||||
info->id = fdt32_to_cpu(*(uint32*)fdt_getprop(fdt, node,
|
||||
"reg", NULL));
|
||||
dprintf("cpu\n");
|
||||
dprintf(" id: %" B_PRIu32 "\n", info->id);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int compatibleLen;
|
||||
const char* compatible = (const char*)fdt_getprop(fdt, node,
|
||||
"compatible", &compatibleLen);
|
||||
|
||||
if (compatible == NULL)
|
||||
return;
|
||||
|
||||
intc_info &interrupt_controller = gKernelArgs.arch_args.interrupt_controller;
|
||||
if (interrupt_controller.kind[0] == 0) {
|
||||
for (uint32 i = 0; i < B_COUNT_OF(kSupportedInterruptControllers); i++) {
|
||||
if (dtb_has_fdt_string(compatible, compatibleLen,
|
||||
kSupportedInterruptControllers[i].dtb_compat)) {
|
||||
|
||||
memcpy(interrupt_controller.kind, kSupportedInterruptControllers[i].kind,
|
||||
sizeof(interrupt_controller.kind));
|
||||
|
||||
dtb_get_reg(fdt, node, 0, interrupt_controller.regs1);
|
||||
dtb_get_reg(fdt, node, 1, interrupt_controller.regs2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_dtb_set_kernel_args(void)
|
||||
{
|
||||
intc_info &interrupt_controller = gKernelArgs.arch_args.interrupt_controller;
|
||||
dprintf("Chosen interrupt controller:\n");
|
||||
if (interrupt_controller.kind[0] == 0) {
|
||||
dprintf("kind: None!\n");
|
||||
} else {
|
||||
dprintf(" kind: %s\n", interrupt_controller.kind);
|
||||
dprintf(" regs: %#" B_PRIx64 ", %#" B_PRIx64 "\n",
|
||||
interrupt_controller.regs1.start,
|
||||
interrupt_controller.regs1.size);
|
||||
dprintf(" %#" B_PRIx64 ", %#" B_PRIx64 "\n",
|
||||
interrupt_controller.regs2.start,
|
||||
interrupt_controller.regs2.size);
|
||||
}
|
||||
}
|
@ -15,9 +15,14 @@
|
||||
#include <arch/generic/debug_uart_8250.h>
|
||||
#if defined(__riscv)
|
||||
# include <arch/riscv64/arch_uart_sifive.h>
|
||||
#elif defined(__ARM__) || defined(__aarch64__)
|
||||
#elif defined(__ARM__)
|
||||
# include <arch/arm/arch_uart_pl011.h>
|
||||
#elif defined(__aarch64__)
|
||||
# include <arch/arm/arch_uart_pl011.h>
|
||||
# include <arch/arm64/arch_uart_linflex.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include <boot/addr_range.h>
|
||||
#include <boot/platform.h>
|
||||
#include <boot/stage2.h>
|
||||
@ -64,10 +69,14 @@ const struct supported_uarts {
|
||||
{ "ns16550", UART_KIND_8250, &get_uart<DebugUART8250> },
|
||||
#if defined(__riscv)
|
||||
{ "sifive,uart0", UART_KIND_SIFIVE, &get_uart<ArchUARTSifive> },
|
||||
#elif defined(__ARM__) || defined(__aarch64__)
|
||||
#elif defined(__ARM__)
|
||||
{ "arm,pl011", UART_KIND_PL011, &get_uart<ArchUARTPL011> },
|
||||
{ "snps,dw-apb-uart", UART_KIND_8250, &get_uart<DebugUART8250> },
|
||||
{ "brcm,bcm2835-aux-uart", UART_KIND_8250, &get_uart<DebugUART8250> },
|
||||
{ "brcm,bcm2835-aux-uart", UART_KIND_8250, &get_uart<DebugUART8250> }
|
||||
#elif defined(__aarch64__)
|
||||
{ "arm,pl011", UART_KIND_PL011, &get_uart<ArchUARTPL011> },
|
||||
{ "fsl,s32-linflexuart", UART_KIND_LINFLEX, &get_uart<ArchUARTlinflex> },
|
||||
{ "brcm,bcm2835-aux-uart", UART_KIND_8250, &get_uart<DebugUART8250> }
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -3,6 +3,9 @@ SubDir HAIKU_TOP src system kernel arch arm64 ;
|
||||
SubDirHdrs $(SUBDIR) $(DOTDOT) generic ;
|
||||
UsePrivateKernelHeaders ;
|
||||
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) generic ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) arm ] ;
|
||||
|
||||
KernelMergeObject kernel_arch_arm64.o :
|
||||
arch_elf.cpp
|
||||
arch_int.cpp
|
||||
@ -20,7 +23,14 @@ KernelMergeObject kernel_arch_arm64.o :
|
||||
arch_real_time_clock.cpp
|
||||
arch_platform.cpp
|
||||
arch_asm.S
|
||||
|
||||
|
||||
# Serial UART and drivers
|
||||
debug_uart.cpp
|
||||
# debug_uart_8250.cpp
|
||||
# arch_uart_8250_omap.cpp
|
||||
arch_uart_pl011.cpp
|
||||
arch_uart_linflex.cpp
|
||||
|
||||
:
|
||||
$(TARGET_KERNEL_PIC_CCFLAGS) -Wno-unused
|
||||
:
|
||||
|
@ -4,12 +4,19 @@
|
||||
*/
|
||||
#include <arch/debug_console.h>
|
||||
#include <arch/generic/debug_uart.h>
|
||||
// #include <arch/generic/debug_uart_8250.h>
|
||||
// #include <arch/arm/arch_uart_8250_omap.h>
|
||||
#include <arch/arm/arch_uart_pl011.h>
|
||||
#include <arch/arm64/arch_uart_linflex.h>
|
||||
#include <boot/kernel_args.h>
|
||||
#include <kernel.h>
|
||||
#include <vm/vm.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static DebugUART *sArchDebugUART = NULL;
|
||||
|
||||
|
||||
void
|
||||
arch_debug_remove_interrupt_handler(uint32 line)
|
||||
{
|
||||
@ -25,34 +32,43 @@ arch_debug_install_interrupt_handlers(void)
|
||||
int
|
||||
arch_debug_blue_screen_try_getchar(void)
|
||||
{
|
||||
return -1;
|
||||
// TODO: Implement correctly!
|
||||
return arch_debug_blue_screen_getchar();
|
||||
}
|
||||
|
||||
|
||||
char
|
||||
arch_debug_blue_screen_getchar(void)
|
||||
{
|
||||
return -1;
|
||||
return arch_debug_serial_getchar();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
arch_debug_serial_try_getchar(void)
|
||||
{
|
||||
return -1;
|
||||
// TODO: Implement correctly!
|
||||
return arch_debug_serial_getchar();
|
||||
}
|
||||
|
||||
|
||||
char
|
||||
arch_debug_serial_getchar(void)
|
||||
{
|
||||
return -1;
|
||||
if (sArchDebugUART == NULL)
|
||||
return '\0';
|
||||
|
||||
return sArchDebugUART->GetChar(false);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
arch_debug_serial_putchar(const char c)
|
||||
{
|
||||
if (sArchDebugUART == NULL)
|
||||
return;
|
||||
|
||||
sArchDebugUART->PutChar(c);
|
||||
}
|
||||
|
||||
|
||||
@ -74,12 +90,38 @@ arch_debug_serial_puts(const char *s)
|
||||
void
|
||||
arch_debug_serial_early_boot_message(const char *string)
|
||||
{
|
||||
// this function will only be called in fatal situations
|
||||
arch_debug_serial_puts(string);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
arch_debug_console_init(kernel_args *args)
|
||||
{
|
||||
if (strncmp(args->arch_args.uart.kind, UART_KIND_PL011,
|
||||
sizeof(args->arch_args.uart.kind)) == 0) {
|
||||
sArchDebugUART = arch_get_uart_pl011(args->arch_args.uart.regs.start,
|
||||
args->arch_args.uart.clock);
|
||||
} else if (strncmp(args->arch_args.uart.kind, UART_KIND_LINFLEX,
|
||||
sizeof(args->arch_args.uart.kind)) == 0) {
|
||||
sArchDebugUART = arch_get_uart_linflex(args->arch_args.uart.regs.start,
|
||||
args->arch_args.uart.clock);
|
||||
}/* else if (strncmp(args->arch_args.uart.kind, UART_KIND_8250_OMAP,
|
||||
sizeof(args->arch_args.uart.kind)) == 0) {
|
||||
sArchDebugUART = arch_get_uart_8250_omap(args->arch_args.uart.regs.start,
|
||||
args->arch_args.uart.clock);
|
||||
} else if (strncmp(args->arch_args.uart.kind, UART_KIND_8250,
|
||||
sizeof(args->arch_args.uart.kind)) == 0) {
|
||||
sArchDebugUART = arch_get_uart_8250(args->arch_args.uart.regs.start,
|
||||
args->arch_args.uart.clock);
|
||||
}*/
|
||||
|
||||
// Oh well.
|
||||
if (sArchDebugUART == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
sArchDebugUART->InitEarly();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
200
src/system/kernel/arch/arm64/arch_uart_linflex.cpp
Normal file
200
src/system/kernel/arch/arm64/arch_uart_linflex.cpp
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright 2022 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Oliver Ruiz Dorantes, oliver.ruiz.dorantes@gmail.com
|
||||
*/
|
||||
|
||||
#include <debug.h>
|
||||
#include <arch/arm/reg.h>
|
||||
#include <arch/generic/debug_uart.h>
|
||||
#include <arch/arm64/arch_uart_linflex.h>
|
||||
#include <new>
|
||||
|
||||
|
||||
using namespace LINFlexRegisters;
|
||||
|
||||
|
||||
ArchUARTlinflex::ArchUARTlinflex(addr_t base, int64 clock)
|
||||
:
|
||||
DebugUART(base, clock)
|
||||
{
|
||||
Barrier();
|
||||
|
||||
if (LinflexCell()->LINCR1.B.SLEEP == 0) {
|
||||
// This periperal is initialized
|
||||
if ((LinflexCell()->UARTCR.B.TXEN == 1)
|
||||
&& (LinflexCell()->UARTCR.B.RXEN == 1)
|
||||
&& (LinflexCell()->UARTCR.B.UART == 1)) {
|
||||
// LinFlex already configured as UART mode
|
||||
// TODO: good to go
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ArchUARTlinflex::~ArchUARTlinflex()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ArchUARTlinflex::Barrier()
|
||||
{
|
||||
asm volatile ("" : : : "memory");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ArchUARTlinflex::InitPort(uint32 baud)
|
||||
{
|
||||
// Calculate baud divisor
|
||||
uint32 baudDivisor = Clock() / (16 * baud);
|
||||
uint32 remainder = Clock() % (16 * baud);
|
||||
uint32 baudFractional = ((8 * remainder) / baud >> 1)
|
||||
+ ((8 * remainder) / baud & 1);
|
||||
|
||||
// Disable UART
|
||||
Disable();
|
||||
|
||||
// Set baud divisor
|
||||
|
||||
// Set LCR 8n1, enable fifo
|
||||
|
||||
// Set FIFO levels
|
||||
|
||||
// Enable UART
|
||||
Enable();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ArchUARTlinflex::InitEarly()
|
||||
{
|
||||
// Perform special hardware UART configuration
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ArchUARTlinflex::Enable()
|
||||
{
|
||||
|
||||
DebugUART::Enable();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ArchUARTlinflex::Disable()
|
||||
{
|
||||
|
||||
DebugUART::Disable();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ArchUARTlinflex::PutChar(char c)
|
||||
{
|
||||
if (Enabled() == true) {
|
||||
// Wait until there is room in fifo
|
||||
bool fifo = LinflexCell()->UARTCR.B.TFBM == 1;
|
||||
|
||||
if (fifo) {
|
||||
// TFF is set by hardware in UART FIFO mode (TFBM = 1) when TX FIFO is full.
|
||||
while (LinflexCell()->UARTSR.B.DTF == 1) {
|
||||
Barrier();
|
||||
}
|
||||
}
|
||||
|
||||
Out<uint8, vuint32>(&LinflexCell()->BDRL.R, c);
|
||||
|
||||
if (!fifo) {
|
||||
// DTF is set by hardware in UART buffer mode (TFBM = 0) and
|
||||
// indicates that data transmission is completed. DTF should be cleared by software.
|
||||
while (LinflexCell()->UARTSR.B.DTF == 0) {
|
||||
Barrier();
|
||||
}
|
||||
|
||||
auto uartsr = BitfieldRegister<UARTSR_register>();
|
||||
uartsr.B.DTF = 1;
|
||||
LinflexCell()->UARTSR.R = uartsr.R;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ArchUARTlinflex::GetChar(bool wait)
|
||||
{
|
||||
int character;
|
||||
|
||||
if (Enabled() == true) {
|
||||
bool fifo = LinflexCell()->UARTCR.B.RFBM == 1;
|
||||
|
||||
if (fifo) {
|
||||
// RFE is set by hardware in UART FIFO mode (RFBM = 1) when the RX FIFO is empty.
|
||||
if (wait) {
|
||||
// Wait until a character is received
|
||||
while (LinflexCell()->UARTSR.B.DRF == 1) {
|
||||
Barrier();
|
||||
}
|
||||
} else {
|
||||
if (LinflexCell()->UARTSR.B.DRF == 1)
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
// DRF is set by hardware in UART buffer mode (RFBM = 0) and
|
||||
// indicates that the number of bytes programmed in RDFL have been received.
|
||||
// DRF should be cleared by software.
|
||||
if (wait) {
|
||||
while (LinflexCell()->UARTSR.B.DRF == 0) {
|
||||
Barrier();
|
||||
}
|
||||
} else {
|
||||
if (LinflexCell()->UARTSR.B.DRF == 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
character = In<uint8, vuint32>(&LinflexCell()->BDRM.R);
|
||||
|
||||
// Clear status
|
||||
auto uartsr = BitfieldRegister<UARTSR_register>();
|
||||
uartsr.B.RMB = 1;
|
||||
uartsr.B.DRF = 1;
|
||||
LinflexCell()->UARTSR.R = uartsr.R;
|
||||
|
||||
return character;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ArchUARTlinflex::FlushTx()
|
||||
{
|
||||
// Wait until transmit fifo empty
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ArchUARTlinflex::FlushRx()
|
||||
{
|
||||
// Wait until receive fifo empty
|
||||
}
|
||||
|
||||
|
||||
ArchUARTlinflex*
|
||||
arch_get_uart_linflex(addr_t base, int64 clock)
|
||||
{
|
||||
static char buffer[sizeof(ArchUARTlinflex)];
|
||||
ArchUARTlinflex *uart = new(buffer) ArchUARTlinflex(base, clock);
|
||||
return uart;
|
||||
}
|
Loading…
Reference in New Issue
Block a user