]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/drivers-frst/uart/src/uart_s3c2410.cc
update
[l4.git] / l4 / pkg / drivers-frst / uart / src / uart_s3c2410.cc
1 /*
2  * (c) 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_s3c2410.h"
10
11 namespace L4
12 {
13   enum {
14     ULCON   = 0x0,  // line control register
15     UCON    = 0x4,  // control register
16     UFCON   = 0x8,  // FIFO control register
17     UMCON   = 0xc,  // modem control register
18     UTRSTAT = 0x10, // Tx/Rx status register
19     UERSTAT = 0x14, // Rx error status register
20     UFSTAT  = 0x18, // FIFO status register
21     UMSTAT  = 0x1c, // modem status register
22     UTXH    = 0x20, // transmit buffer register (little endian, 0x23 for BE)
23     URXH    = 0x24, // receive buffer register (little endian, 0x27 for BE)
24     UBRDIV  = 0x28, // baud rate divisor register
25
26     ULCON_8N1_MODE = 0x3,
27
28     UCON_MODE = 0x245,
29
30     UFSTAT_Rx_COUNT_MASK = 0x00f,
31     UFSTAT_Tx_COUNT_MASK = 0x0f0,
32     UFSTAT_RxFULL        = 0x100,
33     UFSTAT_TxFULL        = 0x200,
34
35     UMCON_AFC = 1 << 4,
36
37     UTRSTAT_Rx_RDY = 1 << 0,
38     UTRSTAT_Tx_RDY = 1 << 1,
39   };
40
41
42   unsigned long Uart_s3c2410::rd(unsigned long reg) const
43   {
44     return *(volatile unsigned long*)(_base + reg);
45   }
46
47   void Uart_s3c2410::wr(unsigned long reg, unsigned long val) const
48   {
49     *(volatile unsigned long *)(_base + reg) = val;
50   }
51
52   void Uart_s3c2410::fifo_reset()
53   {
54     wr(UFCON, 7); // enable + fifo reset
55   }
56
57   bool Uart_s3c2410::startup(unsigned long base)
58   {
59     _base = base;
60
61     fifo_reset();
62     wr(UMCON, 0);
63
64     wr(ULCON, ULCON_8N1_MODE);
65     wr(UCON,  UCON_MODE);
66
67     wr(UBRDIV, 0x23);
68     for (int i=0; i < 1000; ++i)
69       ;
70
71     return true;
72   }
73
74   void Uart_s3c2410::shutdown()
75   {
76     // more
77   }
78
79   bool Uart_s3c2410::enable_rx_irq(bool /*enable*/)
80   {
81     return true;
82   }
83
84   bool Uart_s3c2410::enable_tx_irq(bool /*enable*/) { return false; }
85
86   bool Uart_s3c2410::change_mode(Transfer_mode, Baud_rate r)
87   {
88     if (r != 115200)
89       return false;
90
91     wr(ULCON, ULCON_8N1_MODE);
92     wr(UCON,  UCON_MODE);
93     wr(UFCON, 1);
94
95     wr(UBRDIV, 0x23);
96
97     return true;
98   }
99
100   int Uart_s3c2410::get_char(bool blocking) const
101   {
102     while (!char_avail())
103       if (!blocking)
104         return -1;
105
106     int uer = rd(UERSTAT);
107     int d = rd(URXH);
108
109     if (uer & 1)
110       d = '@';
111     else if (uer & 4)
112       d = '$';
113
114     return d;
115   }
116
117   int Uart_s3c2410::char_avail() const
118   {
119     //return rd(UTRSTAT) & UTRSTAT_Rx_RDY;
120     //return rd(UFSTAT) & UFSTAT_Rx_COUNT_MASK;
121     return rd(UFSTAT) & (UFSTAT_Rx_COUNT_MASK | UFSTAT_RxFULL);
122   }
123
124   void Uart_s3c2410::out_char(char c) const
125   {
126     //while (!(rd(UTRSTAT) & UTRSTAT_Tx_RDY))
127     while (rd(UFSTAT) & UFSTAT_TxFULL)
128       ;
129     //while (!(rd(UMSTAT) & 0x1))
130     //  ;
131     wr(UTXH, c);
132   }
133
134   int Uart_s3c2410::write(char const *s, unsigned long count) const
135   {
136     unsigned long c = count;
137     while (c)
138       {
139         if (*s == 10)
140           out_char(13);
141         out_char(*s++);
142         --c;
143       }
144     while (!(rd(UTRSTAT) & UTRSTAT_Tx_RDY))
145     //while (rd(UFSTAT) & UFSTAT_Tx_COUNT_MASK)
146       ;
147
148     return count;
149   }
150
151   void Uart_s3c2410::auto_flow_control(bool on)
152   {
153     wr(UMCON, (rd(UMCON) & ~UMCON_AFC) | (on ? UMCON_AFC : 0));
154   }
155
156 };
157