2 * Copyright (c) 2000-2008 Atheros Communications, Inc., All Rights Reserved
4 * $Id: //depot/sw/branches/fusion_usb/target_firmware/magpie_fw_dev/build/magpie_1_1/sboot/cmnos/uart/src/uart_api.c#1 $
6 * This file contains UART functions
10 #if SYSTEM_MODULE_UART
12 #include "athos_api.h"
14 //static global control block
16 static struct uart_blk uart_ctl_blk;
18 static void _uart_hwinit(uint32_t freq, uint32_t baud);
26 /*! Initialize UART hardware */
29 /* Disable port interrupts while changing hardware */
30 UART_REG_WRITE(IER_OFFSET, 0);
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);
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);
41 /* Don't allow interrupts. */
42 UART_REG_WRITE(IER_OFFSET, 0);
45 * Enable and clear FIFO.
46 * We don't really use the FIFO for output, but it might still
47 * be useful for input.
49 UART_REG_WRITE(FCR_OFFSET,
51 FCR_RCVR_FIFO_RST_SET(1) |
52 FCR_XMIT_FIFO_RST_SET(1)));
54 /*! Initialize UART software buffer */
55 uart_ctl_blk._tx.start_index = 0;
56 uart_ctl_blk._tx.end_index = 0;
60 /*!- dummy put character
64 _uart_char_put_nothing(uint8_t ch)
70 /*!- dummy get character
74 _uart_char_get_nothing(uint8_t* ch)
76 return 0; //return FALSE;
84 _uart_char_put(uint8_t ch)
90 index = (uart_ctl_blk._tx.end_index+1) & (UART_FIFO_SIZE-1);
91 if(index == uart_ctl_blk._tx.start_index) {
94 index = (uart_ctl_blk._tx.end_index+1) & (UART_FIFO_SIZE-1);
95 if (index != uart_ctl_blk._tx.start_index) {
98 if (count++ > 100000) {
99 /*! If Tx buffer is full, uart_underrun_t++, return FALSE */
100 uart_ctl_blk._tx.overrun_err++;
105 uart_ctl_blk._tx.buf[uart_ctl_blk._tx.end_index] = ch;
106 uart_ctl_blk._tx.end_index = index;
108 /*! If Tx buffer is full, uart_underrun_t++, return FALSE */
112 for (i=0; i<UART_RETRY_COUNT; i++) {
113 lsr = UART_REG_READ(LSR_OFFSET);
114 if (lsr & LSR_THRE_MASK) {
119 /*! Now, the transmit buffer is empty, put to tx buffer */
120 UART_REG_WRITE(THR_OFFSET, ch);
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.
128 for (i=0; i<UART_RETRY_COUNT; i++) {
129 lsr = UART_REG_READ(LSR_OFFSET);
130 if (lsr & LSR_TEMT_MASK) {
142 _uart_char_put_nowait(uint8_t ch)
145 /*! If Tx buffer is full, uart_underrun_t++, return FALSE */
149 for (i=0; i<UART_RETRY_COUNT; i++) {
150 lsr = UART_REG_READ(LSR_OFFSET);
151 if (lsr & LSR_THRE_MASK) {
156 /*! Now, the transmit buffer is empty, put to tx buffer */
157 UART_REG_WRITE(THR_OFFSET, ch);
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.
165 for (i=0; i<UART_RETRY_COUNT; i++) {
166 lsr = UART_REG_READ(LSR_OFFSET);
167 if (lsr & LSR_TEMT_MASK) {
179 _uart_char_get(uint8_t* ch)
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)
185 *ch = UART_REG_READ(RBR_OFFSET);
188 /*! Else return FALSE */
203 volatile uint32_t lsr;
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
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);
231 return uart_ctl_blk._tx.overrun_err;
238 _uart_str_out(uint8_t* str)
242 if( !uart_ctl_blk.debug_mode )
245 while (str[i] != 0) {
246 _uart_char_put(str[i]);
252 /*!- enable or disable put/get
256 _uart_config(uint16_t flag)
258 if( uart_ctl_blk.debug_mode != flag )
260 uart_ctl_blk.debug_mode = !uart_ctl_blk.debug_mode;
263 if( uart_ctl_blk.debug_mode )
264 uart_ctl_blk._uart->_uart_char_put = _uart_char_put;
267 uart_ctl_blk._uart->_uart_char_put = _uart_char_put_nothing;
275 _uart_hwinit(uint32_t freq, uint32_t baud)
278 uint32_t baud_divisor = freq/16/baud;
280 _lcr = UART_REG_READ(LCR_OFFSET);
281 _lcr |= LCR_DLAB_SET(1);
282 UART_REG_WRITE(LCR_OFFSET, _lcr);
284 UART_REG_WRITE(DLH_OFFSET, baud_divisor >> 8);
285 UART_REG_WRITE(DLL_OFFSET, baud_divisor & 0xff);
287 _lcr &= ~LCR_DLAB_SET(1);
288 UART_REG_WRITE(LCR_OFFSET, _lcr);
291 /********** EXPORT function ***********/
293 /*!- Install the function table
296 void cmnos_uart_module_install(struct uart_api *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;
308 uart_ctl_blk._uart = apis;
309 uart_ctl_blk.debug_mode = TRUE;
313 #endif /* SYSTEM_MODULE_UART */