]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/lib/uart/arm/uart_imx.cc
cd1a88b292acd2a7d7a37df15ebd8b97383293f6
[l4.git] / kernel / fiasco / src / lib / uart / arm / uart_imx.cc
1 /*
2  * (c) 2008-2009 Technische Universität Dresden
3  * This file is part of TUD:OS and distributed under the terms of the
4  * GNU General Public License 2.
5  * Please see the COPYING-GPL-2 file for details.
6  */
7 #include "uart_imx.h"
8
9 namespace L4
10 {
11   enum {
12     URXD  = 0x00,   // Receiver
13     UTXD  = 0x40,   // Transmitter
14     UCR1  = 0x80,   // Control 1
15     UCR2  = 0x84,   // Control 2
16     UCR3  = 0x88,   // Control 3
17     UCR4  = 0x8c,   // Control 4
18     UFCR  = 0x90,   // FIFO Control
19     USR1  = 0x94,   // Status 1
20     USR2  = 0x98,   // Status 2
21     UESC  = 0x9c,   // Escape Charater
22     UTIM  = 0xa0,   // Escape Timer
23     UBIR  = 0xa4,   // BRM Incremental Registers
24     UBMR  = 0xa8,   // BRM Modulator Registers
25     UBRC  = 0xac,   // Baud Rate Count
26     ONEMS = 0xb0,   // One millisecond
27     UTS   = 0xb4,   // Test
28
29
30     UCR1_EN        = 1  <<  0, // Enable UART
31
32     UCR2_SRST      = 1  <<  0, // Software Reset
33     UCR2_RXEN      = 1  <<  1, // Receiver Enable
34     UCR2_TXEN      = 1  <<  2, // Transmitter Enable
35     UCR2_WS        = 1  <<  5, // 8-bit character length
36     UCR2_STPB      = 1  <<  6, // 0 = 1 Stop bit, 1 = 2 stop bits
37     UCR2_PROE      = 1  <<  7, // 0 = even parity, 1 = odd parity
38     UCR2_PREN      = 1  <<  8, // Parity enable
39     UCR2_RTEC_MASK = 3  <<  9, // Request to Send Edge Control mask
40     UCR2_RTEC_RISI = 0  <<  9, // Trigger IRQ on rising edge
41     UCR2_RTEC_FALL = 1  <<  9, // Trigger IRQ on falling edge
42     UCR2_RTEC_ANY  = 2  <<  9, // Trigger IRQ on any edge
43     UCR2_ESCEN     = 1  << 11, // Escape enable
44     UCR2_CTS       = 1  << 12, // Clear to Send: 0 = pin is high (inactive), 1 = pin is low (active)
45     UCR2_CTSC      = 1  << 13, // CTS Pin Control: 0 = pin controlled by CTS bit, 1 = pin controlled by the receiver
46     UCR2_IRTS      = 1  << 14, // Ignore RTS pin
47     UCR2_ESCI      = 1  << 15, // Escape Sequence Interrupt Enable
48
49     UCR3_ACIEN     = 1  <<  0, // Autobaud Counter Interrupt enable
50     UCR3_INVT      = 1  <<  1, // Inverted Infrared Transmission
51     UCR3_RXDMUXSEL = 1  <<  2, // RXD Muxed Input Selected: 0 = serial ist IPP_UART_RXD, IR is IPP_UART_RXD_IR, 1 = IPP_UART_RXD_MUX for both
52
53
54     UCR4_DREN      = 1  <<  0, // Receive Data Ready Interrupt Enable
55     UCR4_OREN      = 1  <<  1, // Receiver Overrun Interrupt enable
56     UCR4_BKEN      = 1  <<  2, // BREAK Condition Dected Interrupt enable
57     UCR4_TCEN      = 1  <<  3, // Transmit Complete Interrupt Enable
58     UCR4_LPBYP     = 1  <<  4, // Low Power Bypass
59     UCR4_IRSC      = 1  <<  5, // IR Special Case
60     // Bit 6 is reserve, should be written as 0
61     UCR4_WKEN      = 1  <<  7, // WAKE Interrupt Enable
62     UCR4_ENIRI     = 1  <<  8, // Serial Infrared Interrupt Enable
63     UCR4_INVR      = 1  <<  9, // Inverted Infrared Reception
64     UCR4_CTSTL_32  = 32 << 10, // CTS Trigger Level
65
66     UFCR_RXTL_MASK = 63 <<  0, // Receiver Trigger Level Mask
67     UFCR_RXTL_1    = 1  <<  0, // Receiver Trigger Level: 1 char
68     UFCR_RFDIV_2   = 4  <<  7, // Reference Frequency Divier: by 2
69     UFCR_TXTL_MASK = 63 << 10, // Trasmitter Trigger Level: 8 chars
70     UFCR_TXTL_8    = 8  << 10, // Trasmitter Trigger Level: 8 chars
71     UFCR_TXTL_32   = 32 << 10, // Trasmitter Trigger Level: 32 chars
72
73     USR1_TRDY      = 1  << 13, // Transmitter Ready
74
75     USR2_RDR       = 1  <<  0, // Receive Data Ready
76     USR2_ORE       = 1  <<  1, // Overrun Error
77     USR2_BRCD      = 1  <<  2, // Break Condition Detected
78     USR2_TXDC      = 1  <<  3, // Transmitter Complete
79     USR2_TXFE      = 1  << 14, // Transmit Buffer FIFO Empty
80
81   };
82
83   unsigned long Uart_imx::rd(unsigned long reg) const
84   { return *(volatile unsigned long *)(_base + reg); }
85   void Uart_imx::wr(unsigned long reg, unsigned long val) const
86   { *(volatile unsigned long *)(_base + reg) = val; }
87
88   bool Uart_imx::startup(unsigned long base)
89   {
90     _base = base;
91
92     // 115200Baud, 8n1
93     switch (_type)
94       {
95       case Type_imx21:
96         wr(UBIR, 0x0344);
97         wr(UBMR, 0x270f);
98         break;
99       case Type_imx51:
100         wr(UBIR, 0xf);
101         wr(UBMR, 0x120);
102         break;
103       }
104
105     wr(UCR1, UCR1_EN);
106     wr(UCR2, UCR2_SRST | UCR2_RXEN | UCR2_TXEN | UCR2_WS | UCR2_IRTS); // note: no IRQs enabled
107     wr(UCR3, UCR3_RXDMUXSEL);
108     wr(UCR4, UCR4_CTSTL_32);
109     wr(UFCR, UFCR_TXTL_8 | UFCR_RFDIV_2 | UFCR_RXTL_1);
110
111     return true;
112   }
113
114   void Uart_imx::shutdown()
115   {
116     wr(UCR1, 0); // Disable UART
117   }
118
119   bool Uart_imx::enable_rx_irq(bool enable)
120   {
121     if (enable)
122       {
123         wr(UCR2, rd(UCR2) | UCR2_RTEC_ANY);
124         wr(UCR4, rd(UCR4) | UCR4_DREN);
125       }
126     else
127       wr(UCR4, rd(UCR4) & ~UCR4_DREN);
128
129     return true;
130   }
131   bool Uart_imx::enable_tx_irq(bool /*enable*/) { return false; }
132   bool Uart_imx::change_mode(Transfer_mode, Baud_rate)
133   { return true; }
134
135   int Uart_imx::get_char(bool blocking) const
136   {
137     while (!char_avail())
138       if (!blocking) return -1;
139
140     return rd(URXD) & 0xff;
141   }
142
143   int Uart_imx::char_avail() const
144   {
145     return rd(USR2) & USR2_RDR;
146   }
147
148   void Uart_imx::out_char(char c) const
149   {
150     while (!(rd(USR1) & USR1_TRDY))
151      ;
152     wr(UTXD, c);
153   }
154
155   int Uart_imx::write(char const *s, unsigned long count) const
156   {
157     unsigned long c = count;
158     while (c)
159     {
160       if (*s == 10)
161         out_char(13);
162       out_char(*s++);
163       --c;
164     }
165     while (!(rd(USR2) & USR2_TXDC))
166       ;
167
168     return count;
169   }
170 };