]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/drivers-frst/uart/src/uart_sa1000.cc
update
[l4.git] / l4 / pkg / drivers-frst / 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   bool Uart_sa1000::startup(Io_register_block const *regs)
88   {
89     _regs = regs;
90     _regs->write<unsigned int>(UTSR0, ~0UL); // clear pending status bits
91     _regs->write<unsigned int>(UTCR3, UTCR3_RXE | UTCR3_TXE); //enable transmitter and receiver
92     return true;
93   }
94
95   void Uart_sa1000::shutdown()
96   {
97     _regs->write<unsigned int>(UTCR3, 0);
98   }
99
100   bool Uart_sa1000::change_mode(Transfer_mode m, Baud_rate baud)
101   {
102     unsigned old_utcr3, quot;
103     //proc_status st;
104
105     if (baud == (Baud_rate)-1)
106       return false;
107     if (baud != BAUD_NC && (baud>115200 || baud<96))
108       return false;
109     if (m == (Transfer_mode)-1)
110       return false;
111
112     //st = proc_cli_save();
113     old_utcr3 = _regs->read<unsigned int>(UTCR3);
114     _regs->write<unsigned int>(UTCR3, (old_utcr3 & ~(UTCR3_RIE|UTCR3_TIE)));
115     //proc_sti_restore(st);
116
117     while (_regs->read<unsigned int>(UTSR1) & UTSR1_TBY)
118       ;
119
120     /* disable all */
121     _regs->write<unsigned int>(UTCR3, 0);
122
123     /* set parity, data size, and stop bits */
124     if(m != MODE_NC)
125       _regs->write<unsigned int>(UTCR0, m & 0x0ff);
126
127     /* set baud rate */
128     if(baud!=BAUD_NC)
129       {
130         quot = (UARTCLK / (16*baud)) -1;
131         _regs->write<unsigned int>(UTCR1, (quot & 0xf00) >> 8);
132         _regs->write<unsigned int>(UTCR2, quot & 0x0ff);
133       }
134
135     _regs->write<unsigned int>(UTSR0, (unsigned)-1);
136     _regs->write<unsigned int>(UTCR3, old_utcr3);
137     return true;
138
139   }
140
141   int Uart_sa1000::get_char(bool blocking) const
142   {
143     int ch;
144     unsigned long old_utcr3 = _regs->read<unsigned int>(UTCR3);
145     _regs->write<unsigned int>(UTCR3, old_utcr3 & ~(UTCR3_RIE|UTCR3_TIE));
146
147     while (!(_regs->read<unsigned int>(UTSR1) & UTSR1_RNE))
148       if(!blocking)
149         return -1;
150
151     ch = _regs->read<unsigned int>(UTDR);
152     _regs->write<unsigned int>(UTCR3, old_utcr3);
153     return ch;
154
155   }
156
157   int Uart_sa1000::char_avail() const
158   {
159     return !!(_regs->read<unsigned int>(UTSR1) & UTSR1_RNE);
160   }
161
162   void Uart_sa1000::out_char(char c) const
163   {
164     // do UTCR3 thing here as well?
165     while(!(_regs->read<unsigned int>(UTSR1) & UTSR1_TNF))
166       ;
167     _regs->write<unsigned int>(UTDR, c);
168   }
169
170   int Uart_sa1000::write(char const *s, unsigned long count) const
171   {
172     unsigned old_utcr3;
173     unsigned i;
174
175     old_utcr3 = _regs->read<unsigned int>(UTCR3);
176     _regs->write<unsigned int>(UTCR3, (old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)) | UTCR3_TXE );
177
178     /* transmission */
179     for (i = 0; i < count; i++)
180       out_char(s[i]);
181
182     /* wait till everything is transmitted */
183     while (_regs->read<unsigned int>(UTSR1) & UTSR1_TBY)
184       ;
185
186     _regs->write<unsigned int>(UTCR3, old_utcr3);
187     return count;
188   }
189 };