]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/drivers/uart/src/uart_imx.cc
8208a1e550eb0f1405db08362f0418d1858e4bc7
[l4.git] / l4 / pkg / drivers / uart / src / uart_imx.cc
1 /*
2  * (c) 2008-2009 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_imx51:
102         wr(UBIR, 0xf);
103         wr(UBMR, 0x120);
104         break;
105       }
106
107     wr(UCR1, UCR1_EN);
108     wr(UCR2, UCR2_SRST | UCR2_RXEN | UCR2_TXEN | UCR2_WS | UCR2_IRTS); // note: no IRQs enabled
109     wr(UCR3, UCR3_RXDMUXSEL);
110     wr(UCR4, UCR4_CTSTL_32);
111     wr(UFCR, UFCR_TXTL_8 | UFCR_RFDIV_2 | UFCR_RXTL_1);
112
113     return true;
114   }
115
116   void Uart_imx::shutdown()
117   {
118     wr(UCR1, 0); // Disable UART
119   }
120
121   bool Uart_imx::enable_rx_irq(bool enable)
122   {
123     if (enable)
124       {
125         wr(UCR2, rd(UCR2) | UCR2_RTEC_ANY);
126         wr(UCR4, rd(UCR4) | UCR4_DREN);
127       }
128     else
129       wr(UCR4, rd(UCR4) & ~UCR4_DREN);
130
131     return true;
132   }
133   bool Uart_imx::enable_tx_irq(bool /*enable*/) { return false; }
134   bool Uart_imx::change_mode(Transfer_mode, Baud_rate)
135   { return true; }
136
137   int Uart_imx::get_char(bool blocking) const
138   {
139     while (!char_avail())
140       if (!blocking) return -1;
141
142     return rd(URXD) & 0xff;
143   }
144
145   int Uart_imx::char_avail() const
146   {
147     return rd(USR2) & USR2_RDR;
148   }
149
150   void Uart_imx::out_char(char c) const
151   {
152     while (!(rd(USR1) & USR1_TRDY))
153      ;
154     wr(UTXD, c);
155   }
156
157   int Uart_imx::write(char const *s, unsigned long count) const
158   {
159     unsigned long c = count;
160     while (c)
161     {
162       if (*s == 10)
163         out_char(13);
164       out_char(*s++);
165       --c;
166     }
167     while (!(rd(USR2) & USR2_TXDC))
168       ;
169
170     return count;
171   }
172 };