]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/drivers/uart/src/uart_sa1000.cc
90dcfb4e4d95b0091b02efb4f35323f70620bee1
[l4.git] / l4 / pkg / drivers / uart / src / uart_sa1000.cc
1 /*!
2  * \file   uart_sa1000.cc
3  * \brief  SA1000 Uart
4  *
5  * \date   2008-01-02
6  * \author Adam Lackorznynski <adam@os.inf.tu-dresden.de>
7  *         Alexander Warg <alexander.warg@os.inf.tu-dresden.de>
8  *
9  */
10 /*
11  * (c) 2008-2009 Author(s)
12  *     economic rights: Technische Universität Dresden (Germany)
13  *
14  * This file is part of TUD:OS and distributed under the terms of the
15  * GNU General Public License 2.
16  * Please see the COPYING-GPL-2 file for details.
17  */
18
19 #include "uart_sa1000.h"
20
21 namespace L4
22 {
23   enum {
24     PAR_NONE = 0x00,
25     PAR_EVEN = 0x03,
26     PAR_ODD  = 0x01,
27     DAT_5    = (unsigned)-1,
28     DAT_6    = (unsigned)-1,
29     DAT_7    = 0x00,
30     DAT_8    = 0x08,
31     STOP_1   = 0x00,
32     STOP_2   = 0x04,
33
34     MODE_8N1 = PAR_NONE | DAT_8 | STOP_1,
35     MODE_7E1 = PAR_EVEN | DAT_7 | STOP_1,
36
37     // these two values are to leave either mode
38     // or baud rate unchanged on a call to change_mode
39     MODE_NC  = 0x1000000,
40     BAUD_NC  = 0x1000000,
41   };
42
43   enum {
44     UTCR0 = 0x00,
45     UTCR1 = 0x04,
46     UTCR2 = 0x08,
47     UTCR3 = 0x0c,
48     UTCR4 = 0x10,
49     UTDR  = 0x14,
50     UTSR0 = 0x1c,
51     UTSR1 = 0x20,
52
53
54     UTCR0_PE  = 0x01,
55     UTCR0_OES = 0x02,
56     UTCR0_SBS = 0x04,
57     UTCR0_DSS = 0x08,
58     UTCR0_SCE = 0x10,
59     UTCR0_RCE = 0x20,
60     UTCR0_TCE = 0x40,
61
62     UTCR3_RXE = 0x01,
63     UTCR3_TXE = 0x02,
64     UTCR3_BRK = 0x04,
65     UTCR3_RIE = 0x08,
66     UTCR3_TIE = 0x10,
67     UTCR3_LBM = 0x20,
68
69
70     UTSR0_TFS = 0x01,
71     UTSR0_RFS = 0x02,
72     UTSR0_RID = 0x04,
73     UTSR0_RBB = 0x08,
74     UTSR0_REB = 0x10,
75     UTSR0_EIF = 0x20,
76
77     UTSR1_TBY = 0x01,
78     UTSR1_RNE = 0x02,
79     UTSR1_TNF = 0x04,
80    UTSR1_PRE = 0x08,
81     UTSR1_FRE = 0x10,
82     UTSR1_ROR = 0x20,
83
84     UARTCLK = 3686400,
85   };
86
87   unsigned long Uart_sa1000::rd(unsigned long reg) const
88   {
89     volatile unsigned long *r = (unsigned long*)(_base + reg);
90     return *r;
91   }
92
93   void Uart_sa1000::wr(unsigned long reg, unsigned long val) const
94   {
95     volatile unsigned long *r = (unsigned long*)(_base + reg);
96     *r = val;
97   }
98
99   bool Uart_sa1000::startup(unsigned long base)
100   {
101     _base = base;
102     wr(UTSR0, ~0UL); // clear pending status bits
103     wr(UTCR3, UTCR3_RXE | UTCR3_TXE); //enable transmitter and receiver
104     return true;
105   }
106
107   void Uart_sa1000::shutdown()
108   {
109     wr(UTCR3, 0);
110   }
111
112   bool Uart_sa1000::enable_rx_irq(bool /*enable*/)
113   {
114     return true;
115   }
116   bool Uart_sa1000::enable_tx_irq(bool /*enable*/) { return false; }
117   bool Uart_sa1000::change_mode(Transfer_mode m, Baud_rate baud)
118   {
119     unsigned old_utcr3, quot;
120     //proc_status st;
121
122     if (baud == (Baud_rate)-1)
123       return false;
124     if (baud != BAUD_NC && (baud>115200 || baud<96))
125       return false;
126     if (m == (Transfer_mode)-1)
127       return false;
128
129     //st = proc_cli_save();
130     old_utcr3 = rd(UTCR3);
131     wr(UTCR3, (old_utcr3 & ~(UTCR3_RIE|UTCR3_TIE)));
132     //proc_sti_restore(st);
133
134     while (rd(UTSR1) & UTSR1_TBY)
135       ;
136
137     /* disable all */
138     wr(UTCR3, 0);
139
140     /* set parity, data size, and stop bits */
141     if(m != MODE_NC)
142       wr(UTCR0, m & 0x0ff);
143
144     /* set baud rate */
145     if(baud!=BAUD_NC)
146       {
147         quot = (UARTCLK / (16*baud)) -1;
148         wr(UTCR1, (quot & 0xf00) >> 8);
149         wr(UTCR2, quot & 0x0ff);
150       }
151
152     wr(UTSR0, (unsigned)-1);
153     wr(UTCR3, old_utcr3);
154     return true;
155
156   }
157
158   int Uart_sa1000::get_char(bool blocking) const
159   {
160     int ch;
161     unsigned long old_utcr3 = rd(UTCR3);
162     wr(UTCR3, old_utcr3 & ~(UTCR3_RIE|UTCR3_TIE));
163
164     while (!(rd(UTSR1) & UTSR1_RNE))
165       if(!blocking)
166         return -1;
167
168     ch = rd(UTDR);
169     wr(UTCR3, old_utcr3);
170     return ch;
171
172   }
173
174   int Uart_sa1000::char_avail() const
175   {
176     return !!(rd(UTSR1) & UTSR1_RNE);
177   }
178
179   void Uart_sa1000::out_char(char c) const
180   {
181     // do UTCR3 thing here as well?
182     while(!(rd(UTSR1) & UTSR1_TNF))
183       ;
184     wr(UTDR, c);
185   }
186
187   int Uart_sa1000::write(char const *s, unsigned long count) const
188   {
189     unsigned old_utcr3;
190     //proc_status st;
191     unsigned i;
192
193     //st = proc_cli_save();
194     old_utcr3 = rd(UTCR3);
195     wr(UTCR3, (old_utcr3 & ~(UTCR3_RIE|UTCR3_TIE)) | UTCR3_TXE );
196
197     /* transmission */
198     for(i = 0; i < count; i++)
199       {
200         out_char(s[i]);
201         if (s[i] == '\n')
202           out_char('\r');
203       }
204
205     /* wait till everything is transmitted */
206     while (rd(UTSR1) & UTSR1_TBY)
207       ;
208
209     wr(UTCR3, old_utcr3);
210     //proc_sti_restore(st);
211     return count;
212   }
213 };