xref: /haiku/headers/private/kernel/arch/arm64/arch_uart_linflex.h (revision fc7456e9b1ec38c941134ed6d01c438cf289381e)
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