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