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
21namespace LINFlexRegisters {
22	typedef union { /* LINFLEX LIN Control 1 (Base+0x0000) */
23		vuint32 R;
24		struct {
25	#if __BYTE_ORDER == __BIG_ENDIAN
26			vuint32 :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 :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 :16;
66			vuint32 SZIE:1;
67			vuint32 OCIE:1;
68			vuint32 BEIE:1;
69			vuint32 CEIE:1;
70			vuint32 HEIE:1;
71			vuint32: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 :16;
91			vuint32 LINS:4;
92			vuint32:2;
93			vuint32 RMB:1;
94			vuint32: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 :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: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 :16;
134			vuint32:1;
135			vuint32 TDFL:2;
136			vuint32: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:1;
162			vuint32 TDFL:2;
163			vuint32:1;
164			vuint32 :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 :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: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: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 :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 :16;
212			vuint32: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 :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 :20;
239			vuint32 RTO:4;
240			vuint32: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: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: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: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: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:16;
303			vuint32 DFL:6;
304			vuint32 DIR:1;
305			vuint32 CCS:1;
306			vuint32: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: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: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: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:16;
377			vuint32:3;
378			vuint32 DFL:3;
379			vuint32 DIR:1;
380			vuint32 CCS:1;
381			vuint32: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: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: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: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: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: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
515class ArchUARTlinflex : public DebugUART {
516
517public:
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
533private:
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
551ArchUARTlinflex *arch_get_uart_linflex(addr_t base, int64 clock);
552
553
554#endif
555