Initial cut of the open ath9k htc firmware.
[open-ath9k-htc-firmware.git] / target_firmware / magpie_fw_dev / build / magpie_1_1 / sboot / cmnos / uart / src / uart_api.c
1 /*
2  * Copyright (c) 2000-2008 Atheros Communications, Inc., All Rights Reserved
3  *
4  * $Id: //depot/sw/branches/fusion_usb/target_firmware/magpie_fw_dev/build/magpie_1_1/sboot/cmnos/uart/src/uart_api.c#1 $
5  *
6  * This file contains UART functions
7  */
8 #include "sys_cfg.h"
9
10 #if SYSTEM_MODULE_UART
11
12 #include "athos_api.h"
13
14 //static global control block
15 //
16 static struct uart_blk uart_ctl_blk;    
17
18 static void _uart_hwinit(uint32_t freq, uint32_t baud);
19
20 /*!- Initialize UART
21  *
22  */
23 uint32_t
24 _uart_init(void)
25 {
26     /*! Initialize UART hardware */
27     uint32_t _lcr;
28
29     /* Disable port interrupts while changing hardware */
30     UART_REG_WRITE(IER_OFFSET, 0);
31
32     /* Set databits, stopbits and parity. */
33     _lcr = LCR_CLS_SET(3) | LCR_STOP_SET(0) | LCR_PEN_SET(0);
34     UART_REG_WRITE(LCR_OFFSET, _lcr);
35
36     /* Set baud rate. */
37     _uart_hwinit(A_REFCLK_SPEED_GET(), UART_DEFAULT_BAUD);
38 //    _uart_hwinit(A_REFCLK_SPEED_GET(), 115200);
39     //_uart_hwinit(SYSTEM_CLK, UART_DEFAULT_BAUD);
40
41     /* Don't allow interrupts. */
42     UART_REG_WRITE(IER_OFFSET, 0);
43
44     /*
45      * Enable and clear FIFO.
46      * We don't really use the FIFO for output, but it might still
47      * be useful for input.
48      */
49     UART_REG_WRITE(FCR_OFFSET,
50                     (FCR_FIFO_EN_SET(1) |
51                      FCR_RCVR_FIFO_RST_SET(1) |
52                      FCR_XMIT_FIFO_RST_SET(1)));
53
54     /*! Initialize UART software buffer */
55     uart_ctl_blk._tx.start_index = 0;
56     uart_ctl_blk._tx.end_index = 0;
57 }
58
59
60 /*!- dummy put character 
61  *
62  */
63 void
64 _uart_char_put_nothing(uint8_t ch)
65 {
66     // do nothing
67 }
68
69
70 /*!- dummy get character 
71  *
72  */
73 uint16_t
74 _uart_char_get_nothing(uint8_t* ch)
75 {
76     return 0;   //return FALSE;
77 }
78
79
80 /*!- Put a character 
81  *
82  */
83 void
84 _uart_char_put(uint8_t ch)
85 {
86 #if USE_POST_BUFFER
87     uint16_t index;
88     uint32_t count = 0; 
89
90     index = (uart_ctl_blk._tx.end_index+1) & (UART_FIFO_SIZE-1);
91         if(index == uart_ctl_blk._tx.start_index) {
92             while (1) {
93             _uart_task();
94             index = (uart_ctl_blk._tx.end_index+1) & (UART_FIFO_SIZE-1);
95                 if (index != uart_ctl_blk._tx.start_index) {
96                     break;
97             }
98             if (count++ > 100000) {
99                 /*! If Tx buffer is full, uart_underrun_t++, return FALSE */
100                         uart_ctl_blk._tx.overrun_err++;
101                         return;
102             }
103             }
104         }
105     uart_ctl_blk._tx.buf[uart_ctl_blk._tx.end_index] = ch;
106     uart_ctl_blk._tx.end_index = index;
107 #else
108     /*! If Tx buffer is full, uart_underrun_t++, return FALSE */
109     uint32_t lsr;
110     int i;
111
112     for (i=0; i<UART_RETRY_COUNT; i++) {
113         lsr = UART_REG_READ(LSR_OFFSET);
114         if (lsr & LSR_THRE_MASK) {
115             break;
116         }
117     } 
118
119     /*! Now, the transmit buffer is empty, put to tx buffer */
120     UART_REG_WRITE(THR_OFFSET, ch);
121
122     /*
123      * Hang around until the character has been safely sent.
124      * If we don't do this, the system could go to sleep, which
125      * causes the UART's clock to stop, and we won't see output
126      * that's stuck in the FIFO.
127      */
128     for (i=0; i<UART_RETRY_COUNT; i++) {
129         lsr = UART_REG_READ(LSR_OFFSET);
130         if (lsr & LSR_TEMT_MASK) {
131             break;
132         }
133     }
134 #endif
135
136 }
137
138 /*!- Put a character 
139  *
140  */
141 void
142 _uart_char_put_nowait(uint8_t ch)
143 {
144
145     /*! If Tx buffer is full, uart_underrun_t++, return FALSE */
146     uint32_t lsr;
147     int i;
148
149     for (i=0; i<UART_RETRY_COUNT; i++) {
150         lsr = UART_REG_READ(LSR_OFFSET);
151         if (lsr & LSR_THRE_MASK) {
152             break;
153         }
154     } 
155
156     /*! Now, the transmit buffer is empty, put to tx buffer */
157     UART_REG_WRITE(THR_OFFSET, ch);
158
159     /*
160      * Hang around until the character has been safely sent.
161      * If we don't do this, the system could go to sleep, which
162      * causes the UART's clock to stop, and we won't see output
163      * that's stuck in the FIFO.
164      */
165     for (i=0; i<UART_RETRY_COUNT; i++) {
166         lsr = UART_REG_READ(LSR_OFFSET);
167         if (lsr & LSR_TEMT_MASK) {
168             break;
169         }
170     }
171
172 }
173
174
175 /*!- Get a character 
176  *
177  */
178 uint16_t
179 _uart_char_get(uint8_t* ch)
180 {
181
182     /*! If Rx FIFO is not empty, get char from Rx buffer, reutnr TRUE */
183     if ((UART_REG_READ(LSR_OFFSET) & LSR_DR_MASK) != 0) 
184     {
185         *ch = UART_REG_READ(RBR_OFFSET);
186         return 1;
187     }
188     /*! Else return FALSE */
189     else 
190     { 
191         return 0;
192     }
193 }
194
195 /*!- UART task 
196  *
197  */
198 void
199 _uart_task(void)
200 {
201 #if USE_POST_BUFFER
202     uint16_t count;
203     volatile uint32_t lsr;
204
205     /*! If Tx FIFO almost empty, move chars from Tx buffer to Tx FIFO */
206     lsr = UART_REG_READ(LSR_OFFSET);
207     if ((lsr & LSR_THRE_MASK) != 0) { //Transmitter holding register empty
208         count = 0;
209         while (count<16) {
210             if (uart_ctl_blk._tx.start_index != uart_ctl_blk._tx.end_index) {
211                 UART_REG_WRITE(THR_OFFSET, uart_ctl_blk._tx.buf[uart_ctl_blk._tx.start_index]);
212                 uart_ctl_blk._tx.start_index = (uart_ctl_blk._tx.start_index+1)
213                     & (UART_FIFO_SIZE-1);
214             }
215             else
216             {
217                 break;
218             }
219             count++;
220         }
221     }
222 #endif
223     return;
224 }
225
226
227
228  uint32_t 
229 _uart_status()
230 {
231         return uart_ctl_blk._tx.overrun_err;
232 }
233
234 /*!- Output a string 
235  *
236  */
237 void
238 _uart_str_out(uint8_t* str)
239 {
240     uint32_t i = 0;
241
242     if( !uart_ctl_blk.debug_mode )
243         return;
244
245     while (str[i] != 0) {
246         _uart_char_put(str[i]);
247         i++;
248     }
249     return;
250 }
251
252 /*!- enable or disable put/get
253  *
254  */
255 void
256 _uart_config(uint16_t flag)
257 {    
258     if( uart_ctl_blk.debug_mode != flag )
259     {
260         uart_ctl_blk.debug_mode = !uart_ctl_blk.debug_mode;
261         
262         // debug mode enable
263         if( uart_ctl_blk.debug_mode ) 
264             uart_ctl_blk._uart->_uart_char_put = _uart_char_put;
265         else
266             // debug mode enable
267             uart_ctl_blk._uart->_uart_char_put = _uart_char_put_nothing;
268     }
269 }
270
271 /*!- Set baudrate 
272  *
273  */
274 void
275 _uart_hwinit(uint32_t freq, uint32_t baud)
276 {
277     uint32_t _lcr;
278     uint32_t baud_divisor = freq/16/baud;
279
280     _lcr = UART_REG_READ(LCR_OFFSET);
281     _lcr |= LCR_DLAB_SET(1);
282     UART_REG_WRITE(LCR_OFFSET, _lcr);
283
284     UART_REG_WRITE(DLH_OFFSET, baud_divisor >> 8);
285     UART_REG_WRITE(DLL_OFFSET, baud_divisor & 0xff);
286
287     _lcr &= ~LCR_DLAB_SET(1);
288     UART_REG_WRITE(LCR_OFFSET, _lcr);
289 }
290
291 /********** EXPORT function ***********/
292
293 /*!- Install the function table 
294  *
295  */
296 void cmnos_uart_module_install(struct uart_api *apis)
297 {    
298     /* hook in APIs */
299     apis->_uart_init = _uart_init;
300     apis->_uart_char_put = _uart_char_put;
301     apis->_uart_char_get = _uart_char_get;
302     apis->_uart_str_out = _uart_str_out;
303     apis->_uart_task = _uart_task;
304     apis->_uart_config = _uart_config;
305     apis->_uart_status = _uart_status;
306     apis->_uart_hwinit = _uart_hwinit;
307
308     uart_ctl_blk._uart = apis;
309     uart_ctl_blk.debug_mode = TRUE;
310     return;
311 }
312
313 #endif /* SYSTEM_MODULE_UART */
314