]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/lib/uart/arm/uart_s3c2410.cc
update
[l4.git] / kernel / fiasco / src / lib / uart / arm / uart_s3c2410.cc
1 #include "uart_s3c2410.h"
2
3 namespace L4
4 {
5   enum
6   {
7     OFFSET = 0x0000,
8     ULCON   = OFFSET + 0x0,  // line control register
9     UCON    = OFFSET + 0x4,  // control register
10     UFCON   = OFFSET + 0x8,  // FIFO control register
11     UMCON   = OFFSET + 0xc,  // modem control register
12     UTRSTAT = OFFSET + 0x10, // Tx/Rx status register
13     UERSTAT = OFFSET + 0x14, // Rx error status register
14     UFSTAT  = OFFSET + 0x18, // FIFO status register
15     UMSTAT  = OFFSET + 0x1c, // modem status register
16     UTXH    = OFFSET + 0x20, // transmit buffer register (little endian, 0x23 for BE)
17     URXH    = OFFSET + 0x24, // receive buffer register (little endian, 0x27 for BE)
18     UBRDIV  = OFFSET + 0x28, // baud rate divisor register
19
20     ULCON_8N1_MODE = 0x3,
21
22     UCON_MODE = 0x045 | (1 << 7),
23
24     UFSTAT_Rx_COUNT_MASK = 0x00f,
25     UFSTAT_Tx_COUNT_MASK = 0x0f0,
26     UFSTAT_RxFULL        = 0x100,
27     UFSTAT_TxFULL        = 0x200,
28   };
29
30
31   unsigned long Uart_s3c2410::rd(unsigned long reg) const
32   {
33     volatile unsigned long *r = (unsigned long*)(_base + reg);
34     return *r;
35   }
36
37   void Uart_s3c2410::wr(unsigned long reg, unsigned long val) const
38   {
39     volatile unsigned long *r = (unsigned long*)(_base + reg);
40     *r = val;
41   }
42
43   bool Uart_s3c2410::startup(unsigned long base)
44   {
45     _base = base;
46
47     wr(ULCON, ULCON_8N1_MODE);
48     wr(UCON,  UCON_MODE);
49     wr(UFCON, 1);
50
51     wr(UBRDIV, 0x23);
52     return true;
53   }
54
55   void Uart_s3c2410::shutdown()
56   {
57     // more
58   }
59
60   bool Uart_s3c2410::enable_rx_irq(bool enable)
61   { return true; }
62
63   bool Uart_s3c2410::enable_tx_irq(bool /*enable*/) { return false; }
64
65   bool Uart_s3c2410::change_mode(Transfer_mode, Baud_rate r)
66   {
67     if (r != 115200)
68       return false;
69
70     wr(ULCON, ULCON_8N1_MODE);
71     wr(UCON,  UCON_MODE);
72     wr(UFCON, 1);
73
74     wr(UBRDIV, 0x23);
75
76     return true;
77   }
78
79   int Uart_s3c2410::get_char(bool blocking) const
80   {
81     while (!char_avail())
82       if (!blocking) return -1;
83
84     int c = rd(URXH) & 0xff;
85     return c;
86   }
87
88   int Uart_s3c2410::char_avail() const
89   {
90     return rd(UFSTAT) & UFSTAT_Rx_COUNT_MASK;
91   }
92
93   void Uart_s3c2410::out_char(char c) const
94   {
95     while (rd(UFSTAT) & UFSTAT_TxFULL)
96       ;
97     wr(UTXH, c);
98   }
99
100   int Uart_s3c2410::write(char const *s, unsigned long count) const
101   {
102     unsigned long c = count;
103     while (c)
104       {
105         if (*s == 10)
106           out_char(13);
107         out_char(*s++);
108         --c;
109       }
110     while (rd(UFSTAT) & UFSTAT_Tx_COUNT_MASK)
111       ;
112
113     return count;
114   }
115
116 };
117