1 /* 2 * Copyright 2022 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Oliver Ruiz Dorantes, oliver.ruiz.dorantes@gmail.com 7 */ 8 #ifndef __DEV_UART_LINFLEX_H 9 #define __DEV_UART_LINFLEX_H 10 11 12 #include <sys/types.h> 13 #include <ByteOrder.h> 14 #include <SupportDefs.h> 15 16 #include <arch/generic/debug_uart.h> 17 18 19 #define UART_KIND_LINFLEX "linflex" 20 21 namespace LINFlexRegisters { 22 typedef union { /* LINFLEX LIN Control 1 (Base+0x0000) */ 23 vuint32 R; 24 struct { 25 #if __BYTE_ORDER == __BIG_ENDIAN 26 vuint32 padding:16; 27 vuint32 CCD:1; 28 vuint32 CFD:1; 29 vuint32 LASE:1; 30 vuint32 AWUM:1; 31 vuint32 MBL:4; 32 vuint32 BF:1; 33 vuint32 SFTM:1; 34 vuint32 LBKM:1; 35 vuint32 MME:1; 36 vuint32 SBDT:1; 37 vuint32 RBLM:1; 38 vuint32 SLEEP:1; 39 vuint32 INIT:1; 40 #endif 41 #if __BYTE_ORDER == __LITTLE_ENDIAN 42 vuint32 INIT:1; 43 vuint32 SLEEP:1; 44 vuint32 RBLM:1; 45 vuint32 SBDT:1; 46 vuint32 MME:1; 47 vuint32 LBKM:1; 48 vuint32 SFTM:1; 49 vuint32 BF:1; 50 vuint32 MBL:4; 51 vuint32 AWUM:1; 52 vuint32 LASE:1; 53 vuint32 CFD:1; 54 vuint32 CCD:1; 55 vuint32 padding:16; 56 #endif 57 } B; 58 } LINCR1_register; 59 60 61 typedef union { /* LINFLEX LIN Interrupt Enable (Base+0x0004) */ 62 vuint32 R; 63 struct { 64 #if __BYTE_ORDER == __BIG_ENDIAN 65 vuint32 padding:16; 66 vuint32 SZIE:1; 67 vuint32 OCIE:1; 68 vuint32 BEIE:1; 69 vuint32 CEIE:1; 70 vuint32 HEIE:1; 71 vuint32 padding1:2; 72 vuint32 FEIE:1; 73 vuint32 BOIE:1; 74 vuint32 LSIE:1; 75 vuint32 WUIE:1; 76 vuint32 DBFIE:1; 77 vuint32 DBEIE:1; 78 vuint32 DRIE:1; 79 vuint32 DTIE:1; 80 vuint32 HRIE:1; 81 #endif 82 } B; 83 } LINIER_register; 84 85 86 typedef union { /* LINFLEX LIN Status (Base+0x0008) */ 87 vuint32 R; 88 struct { 89 #if __BYTE_ORDER == __BIG_ENDIAN 90 vuint32 padding:16; 91 vuint32 LINS:4; 92 vuint32 padding1:2; 93 vuint32 RMB:1; 94 vuint32 padding2:1; 95 vuint32 RBSY:1; 96 vuint32 RPS:1; 97 vuint32 WUF:1; 98 vuint32 DBFF:1; 99 vuint32 DBEF:1; 100 vuint32 DRF:1; 101 vuint32 DTF:1; 102 vuint32 HRF:1; 103 #endif 104 } B; 105 } LINSR_register; 106 107 108 typedef union { /* LINFLEX LIN Error Status (Base+0x000C) */ 109 vuint32 R; 110 struct { 111 #if __BYTE_ORDER == __BIG_ENDIAN 112 vuint32 padding:16; 113 vuint32 SZF:1; 114 vuint32 OCF:1; 115 vuint32 BEF:1; 116 vuint32 CEF:1; 117 vuint32 SFEF:1; 118 vuint32 BDEF:1; 119 vuint32 IDPEF:1; 120 vuint32 FEF:1; 121 vuint32 BOF:1; 122 vuint32 padding1:6; 123 vuint32 NF:1; 124 #endif 125 } B; 126 } LINESR_register; 127 128 129 typedef union { /* LINFLEX UART Mode Control (Base+0x0010) */ 130 vuint32 R; 131 struct { 132 #if __BYTE_ORDER == __BIG_ENDIAN 133 vuint32 padding:16; 134 vuint32 padding1:1; 135 vuint32 TDFL:2; 136 vuint32 padding2:1; 137 vuint32 RDFL:2; 138 vuint32 RFBM:1; 139 vuint32 TFBM:1; 140 vuint32 WL1:1; 141 vuint32 PC1:1; 142 vuint32 RXEN:1; 143 vuint32 TXEN:1; 144 vuint32 PC0:1; 145 vuint32 PCE:1; 146 vuint32 WL:1; 147 vuint32 UART:1; 148 #endif 149 #if __BYTE_ORDER == __LITTLE_ENDIAN 150 vuint32 UART:1; 151 vuint32 WL:1; 152 vuint32 PCE:1; 153 vuint32 PC0:1; 154 vuint32 TXEN:1; 155 vuint32 RXEN:1; 156 vuint32 PC1:1; 157 vuint32 WL1:1; 158 vuint32 TFBM:1; 159 vuint32 RFBM:1; 160 vuint32 RDFL:2; 161 vuint32 padding2:1; 162 vuint32 TDFL:2; 163 vuint32 padding1:1; 164 vuint32 padding:16; 165 #endif 166 } B; 167 } UARTCR_register; 168 169 170 typedef union { /* LINFLEX UART Mode Status (Base+0x0014) */ 171 vuint32 R; 172 struct { 173 #if __BYTE_ORDER == __BIG_ENDIAN 174 vuint32 padding:16; 175 vuint32 SZF:1; 176 vuint32 OCF:1; 177 vuint32 PE:4; /*Can check all 4 RX'd bytes at once with array*/ 178 vuint32 RMB:1; 179 vuint32 FEF:1; 180 vuint32 BOF:1; 181 vuint32 RPS:1; 182 vuint32 WUF:1; 183 vuint32 padding1:2; 184 vuint32 DRF:1; 185 vuint32 DTF:1; 186 vuint32 NF:1; 187 #endif 188 #if __BYTE_ORDER == __LITTLE_ENDIAN 189 vuint32 NF:1; 190 vuint32 DTF:1; 191 vuint32 DRF:1; 192 vuint32 padding1:2; 193 vuint32 WUF:1; 194 vuint32 RPS:1; 195 vuint32 BOF:1; 196 vuint32 FEF:1; 197 vuint32 RMB:1; 198 vuint32 PE:4; /*Can check all 4 RX'd bytes at once with array*/ 199 vuint32 OCF:1; 200 vuint32 SZF:1; 201 vuint32 padding:16; 202 #endif 203 } B; 204 } UARTSR_register; 205 206 207 typedef union { /* LINFLEX TimeOut Control Status ((Base+0x0018)*/ 208 vuint32 R; 209 struct { 210 #if __BYTE_ORDER == __BIG_ENDIAN 211 vuint32 padding:16; 212 vuint32 padding1:5; 213 vuint32 LTOM:1; 214 vuint32 IOT:1; 215 vuint32 TOCE:1; 216 vuint32 CNT:8; 217 #endif 218 } B; 219 } LINTCSR_register; 220 221 222 typedef union { /* LINFLEX LIN Output Compare (Base+0x001C) */ 223 vuint32 R; 224 struct { 225 #if __BYTE_ORDER == __BIG_ENDIAN 226 vuint32 padding:16; 227 vuint32 OC2:8; 228 vuint32 OC1:8; 229 #endif 230 } B; 231 } LINOCR_register; 232 233 234 typedef union { /* LINFLEX LIN Timeout Control (Base+0x0020) */ 235 vuint32 R; 236 struct { 237 #if __BYTE_ORDER == __BIG_ENDIAN 238 vuint32 padding:20; 239 vuint32 RTO:4; 240 vuint32 padding:1; 241 vuint32 HTO:7; 242 #endif 243 } B; 244 } LINTOCR_register; 245 246 247 typedef union { /* LINFLEX LIN Fractional Baud Rate (+0x0024) */ 248 vuint32 R; 249 struct { 250 #if __BYTE_ORDER == __BIG_ENDIAN 251 vuint32 padding:28; 252 vuint32 DIV_F:4; 253 #endif 254 } B; 255 } LINFBRR_register; 256 257 258 typedef union { /* LINFLEX LIN Integer Baud Rate (Base+0x0028) */ 259 vuint32 R; 260 struct { 261 #if __BYTE_ORDER == __BIG_ENDIAN 262 vuint32 padding:19; 263 vuint32 DIV_M:13; 264 #endif 265 } B; 266 } LINIBRR_register; 267 268 269 typedef union { /* LINFLEX LIN Checksum Field (Base+0x002C) */ 270 vuint32 R; 271 struct { 272 #if __BYTE_ORDER == __BIG_ENDIAN 273 vuint32 padding:24; 274 vuint32 CF:8; 275 #endif 276 } B; 277 } LINCFR_register; 278 279 280 typedef union { /* LINFLEX LIN Control 2 (Base+0x0030) */ 281 vuint32 R; 282 struct { 283 #if __BYTE_ORDER == __BIG_ENDIAN 284 vuint32 padding:17; 285 vuint32 IOBE:1; 286 vuint32 IOPE:1; 287 vuint32 WURQ:1; 288 vuint32 DDRQ:1; 289 vuint32 DTRQ:1; 290 vuint32 ABRQ:1; 291 vuint32 HTRQ:1; 292 vuint32:8; 293 #endif 294 } B; 295 } LINCR2_register; 296 297 298 typedef union { /* LINFLEX Buffer Identifier (Base+0x0034) */ 299 vuint32 R; 300 struct { 301 #if __BYTE_ORDER == __BIG_ENDIAN 302 vuint32 padding:16; 303 vuint32 DFL:6; 304 vuint32 DIR:1; 305 vuint32 CCS:1; 306 vuint32 padding1:2; 307 vuint32 ID:6; 308 #endif 309 } B; 310 } BIDR_register; 311 312 313 typedef union { /* LINFLEX Buffer Data LSB (Base+0x0038) */ 314 vuint32 R; 315 struct { 316 #if __BYTE_ORDER == __BIG_ENDIAN 317 vuint32 DATA3:8; 318 vuint32 DATA2:8; 319 vuint32 DATA1:8; 320 vuint32 DATA0:8; 321 #endif 322 } B; 323 } BDRL_register; 324 325 326 typedef union { /* LINFLEX Buffer Data MSB (Base+0x003C */ 327 vuint32 R; 328 struct { 329 #if __BYTE_ORDER == __BIG_ENDIAN 330 vuint32 DATA7:8; 331 vuint32 DATA6:8; 332 vuint32 DATA5:8; 333 vuint32 DATA4:8; 334 #endif 335 } B; 336 } BDRM_register; 337 338 339 typedef union { /* LINFLEX Identifier Filter Enable (+0x0040) */ 340 vuint32 R; 341 struct { 342 #if __BYTE_ORDER == __BIG_ENDIAN 343 vuint32 padding:24; 344 vuint32 FACT:8; 345 #endif 346 } B; 347 } IFER_register; 348 349 350 typedef union { /* LINFLEX Identifier Filter Match Index (+0x0044)*/ 351 vuint32 R; 352 struct { 353 #if __BYTE_ORDER == __BIG_ENDIAN 354 vuint32 padding:28; 355 vuint32 IFMI:4; 356 #endif 357 } B; 358 } IFMI_register; 359 360 361 typedef union { /* LINFLEX Identifier Filter Mode (Base+0x0048) */ 362 vuint32 R; 363 struct { 364 #if __BYTE_ORDER == __BIG_ENDIAN 365 vuint32 padding:28; 366 vuint32 IFM:4; 367 #endif 368 } B; 369 } IFMR_register; 370 371 372 typedef union { /* LINFLEX Identifier Filter Control 0..15 (+0x004C-0x0088)*/ 373 vuint32 R; 374 struct { 375 #if __BYTE_ORDER == __BIG_ENDIAN 376 vuint32 padding:16; 377 vuint32 padding1:3; 378 vuint32 DFL:3; 379 vuint32 DIR:1; 380 vuint32 CCS:1; 381 vuint32 padding2:2; 382 vuint32 ID:6; 383 #endif 384 } B; 385 } IFCR_register; 386 387 388 typedef union { /* LINFLEX Global Counter (+0x008C) */ 389 vuint32 R; 390 struct { 391 #if __BYTE_ORDER == __BIG_ENDIAN 392 vuint32 padding:26; 393 vuint32 TDFBM:1; 394 vuint32 RDFBM:1; 395 vuint32 TDLIS:1; 396 vuint32 RDLIS:1; 397 vuint32 STOP:1; 398 vuint32 SR:1; 399 #endif 400 } B; 401 } GCR_register; 402 403 404 typedef union { /* LINFLEX UART preset timeout (+0x0090) */ 405 vuint32 R; 406 struct { 407 #if __BYTE_ORDER == __BIG_ENDIAN 408 vuint32 padding:20; 409 vuint32 PTO:12; 410 #endif 411 } B; 412 } UARTPTO_register; 413 414 415 typedef union { /* LINFLEX UART current timeout (+0x0094) */ 416 vuint32 R; 417 struct { 418 #if __BYTE_ORDER == __BIG_ENDIAN 419 vuint32 padding:20; 420 vuint32 CTO:12; 421 #endif 422 } B; 423 } UARTCTO_register; 424 425 426 typedef union { /* LINFLEX DMA Tx Enable (+0x0098) */ 427 vuint32 R; 428 struct { 429 #if __BYTE_ORDER == __BIG_ENDIAN 430 vuint32 padding:16; 431 vuint32 DTE15:1; 432 vuint32 DTE14:1; 433 vuint32 DTE13:1; 434 vuint32 DTE12:1; 435 vuint32 DTE11:1; 436 vuint32 DTE10:1; 437 vuint32 DTE9:1; 438 vuint32 DTE8:1; 439 vuint32 DTE7:1; 440 vuint32 DTE6:1; 441 vuint32 DTE5:1; 442 vuint32 DTE4:1; 443 vuint32 DTE3:1; 444 vuint32 DTE2:1; 445 vuint32 DTE1:1; 446 vuint32 DTE0:1; 447 #endif 448 } B; 449 } DMATXE_register; 450 451 452 typedef union { /* LINFLEX DMA RX Enable (+0x009C) */ 453 vuint32 R; 454 struct { 455 #if __BYTE_ORDER == __BIG_ENDIAN 456 vuint32 padding:16; 457 vuint32 DRE15:1; 458 vuint32 DRE14:1; 459 vuint32 DRE13:1; 460 vuint32 DRE12:1; 461 vuint32 DRE11:1; 462 vuint32 DRE10:1; 463 vuint32 DRE9:1; 464 vuint32 DRE8:1; 465 vuint32 DRE7:1; 466 vuint32 DRE6:1; 467 vuint32 DRE5:1; 468 vuint32 DRE4:1; 469 vuint32 DRE3:1; 470 vuint32 DRE2:1; 471 vuint32 DRE1:1; 472 vuint32 DRE0:1; 473 #endif 474 } B; 475 } DMARXE_register; 476 477 // Helper to deal with w1c (Write 1 to clear) register fields 478 template<typename REG> 479 REG BitfieldRegister() { 480 REG reg; 481 reg.R = 0; 482 return reg; 483 } 484 485 typedef struct { 486 LINCR1_register LINCR1; /* LINFLEX LIN Control 1 (Base+0x0000) */ 487 LINIER_register LINIER; /* LINFLEX LIN Interrupt Enable (Base+0x0004) */ 488 LINSR_register LINSR; /* LINFLEX LIN Status (Base+0x0008) */ 489 LINESR_register LINESR; /* LINFLEX LIN Error Status (Base+0x000C) */ 490 UARTCR_register UARTCR; /* LINFLEX UART Mode Control (Base+0x0010) */ 491 UARTSR_register UARTSR; /* LINFLEX UART Mode Status (Base+0x0014) */ 492 LINTCSR_register LINTCSR; /* LINFLEX TimeOut Control Status ((Base+0x0018)*/ 493 LINOCR_register LINOCR; /* LINFLEX LIN Output Compare (Base+0x001C) */ 494 LINTOCR_register LINTOCR; /* LINFLEX LIN Timeout Control (Base+0x0020) */ 495 LINFBRR_register LINFBRR; /* LINFLEX LIN Fractional Baud Rate (+0x0024) */ 496 LINIBRR_register LINIBRR; /* LINFLEX LIN Integer Baud Rate (Base+0x0028) */ 497 LINCFR_register LINCFR; /* LINFLEX LIN Checksum Field (Base+0x002C) */ 498 LINCR2_register LINCR2; /* LINFLEX LIN Control 2 (Base+0x0030) */ 499 BIDR_register BIDR; /* LINFLEX Buffer Identifier (Base+0x0034) */ 500 BDRL_register BDRL; /* LINFLEX Buffer Data LSB (Base+0x0038) */ 501 BDRM_register BDRM; /* LINFLEX Buffer Data MSB (Base+0x003C */ 502 IFER_register IFER; /* LINFLEX Identifier Filter Enable (+0x0040) */ 503 IFMI_register IFMI; /* LINFLEX Identifier Filter Match Index (+0x0044)*/ 504 IFMR_register IFMR; /* LINFLEX Identifier Filter Mode (Base+0x0048) */ 505 IFCR_register IFCR[16]; /* LINFLEX Identifier Filter Control 0..15 (+0x004C-0x0088)*/ 506 GCR_register GCR; /* LINFLEX Global Counter (+0x008C) */ 507 UARTPTO_register UARTPTO; /* LINFLEX UART preset timeout (+0x0090) */ 508 UARTCTO_register UARTCTO; /* LINFLEX UART current timeout (+0x0094) */ 509 DMATXE_register DMATXE; /* LINFLEX DMA Tx Enable (+0x0098) */ 510 DMARXE_register DMARXE; /* LINFLEX DMA RX Enable (+0x009C) */ 511 } LINFlex; 512 } 513 514 515 class ArchUARTlinflex : public DebugUART { 516 517 public: 518 ArchUARTlinflex(addr_t base, int64 clock); 519 ~ArchUARTlinflex(); 520 521 void InitEarly(); 522 void InitPort(uint32 baud); 523 524 void Enable(); 525 void Disable(); 526 527 int PutChar(char c); 528 int GetChar(bool wait); 529 530 void FlushTx(); 531 void FlushRx(); 532 533 private: 534 template<typename TO, typename TA> 535 void Out(TA* reg, TO value) { 536 *(volatile TO*)(reg) = value; 537 } 538 539 template<typename TI, typename TA> 540 TI In(TA* reg) { 541 return *(volatile TI*)(reg); 542 } 543 544 virtual void Barrier(); 545 LINFlexRegisters::LINFlex* LinflexCell() { 546 return reinterpret_cast<LINFlexRegisters::LINFlex*>(Base()); 547 } 548 }; 549 550 551 ArchUARTlinflex *arch_get_uart_linflex(addr_t base, int64 clock); 552 553 554 #endif 555