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