555 lines
11 KiB
C
555 lines
11 KiB
C
|
/*
|
||
|
* 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
|