static void local_put_char(int hub2, char ch) { int flags = 0; if (hub2 < 0 || hub2 > 1) { printk("Error: Invalid serial port requested.\n"); return; /* validate port op(UART 0|1) */ } save_flags(flags); cli(); while (!(UART_LSR(hub2) & UART_LSR_THRE)) { SYNC_ALL; } ACCESS_PORT_IER(hub2) UART_THR(hub2) = ch; SYNC_ALL; while (UART_LSR(hub2) & UART_LSR_THRE) { udelay(5); } restore_flags(flags); }
/* * This Function Wait until Data RX Ready, and return Data Read from UART. */ uint8_t uart_read_timeout(uart_num_t uart_num, uint32_t rx_timeout_nb_cycles, uart_error_t* error) { uint32_t uart_port; uint8_t uart_val; uint32_t counter; uart_port = uart_num; /* Wait Until Data Received (Rx Data Not Ready) */ counter = 0; while ((UART_LSR(uart_port) & UART_LSR_RDR) == 0) { if (rx_timeout_nb_cycles>0) { counter++; if (counter>=rx_timeout_nb_cycles) { *error = UART_TIMEOUT_ERROR; return 0; } } } uart_val = (UART_RBR(uart_port) & UART_RBR_MASKBIT); /* Clear error */ *error = UART_NO_ERROR; return uart_val; }
/* * This Function return if data are received or not received. */ uart_rx_data_ready_t uart_rx_data_ready(uart_num_t uart_num) { uint32_t uart_port; uint8_t uart_status; uart_rx_data_ready_t data_ready; uart_port = uart_num; uart_status = UART_LSR(uart_port) & 0xFF; /* Check Error */ if ((uart_status & UART_LSR_ERROR_MASK) == 0) { /* No errors check if data is ready */ if ((uart_status & UART_LSR_RDR) == 0) { data_ready = UART_RX_NO_DATA; } else { data_ready = UART_RX_DATA_READY; } } else { /* UART Error */ data_ready = UART_RX_DATA_ERROR; } return data_ready; }
/* * This is the serial driver's generic interrupt routine * Note: Generally it should be attached to general interrupt 10, responsile * for UART0&1 RCV and XMT interrupt, to make sure the invoked interrupt * source, look into bit 10-13 of SIC_ISR(peripheral interrupt status reg. * Finally, to see what can be done about request_irq(......) */ void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) { struct bf535_serial *info; // = &bf535_soft[CONFIG_SERIAL_CONSOLE_PORT]; unsigned short iir; /* Interrupt Identification Register */ unsigned short rx, idx; unsigned int sic_status = SIC_ISR; for (idx = 0; idx < NR_PORTS; idx++){ if (sic_status & (UART_INVOKED << 2*(idx + 5))){ /* test bit 10-11 and 12-13 */ iir = UART_IIR(idx); info = &bf535_soft[idx]; if (!(iir & UART_IIR_NOINT)){ switch (iir & UART_IIR_STATUS){ case UART_IIR_LSR: printk("Line status changed for serial port %d.\n", idx); break; case UART_IIR_RBR: /* Change access to IER & data port */ ACCESS_PORT_IER(idx) if (UART_LSR(idx) & UART_LSR_DR){ rx = UART_RBR(idx); receive_chars(info, regs, rx); } break; case UART_IIR_THR: /* Change access to IER & data port */ ACCESS_PORT_IER(idx) if (UART_LSR(idx) & UART_LSR_THRE){ transmit_chars(info); // do{ // transmit_chars(info); // }while(info->xmit_cnt > 0); } break; case UART_IIR_MSR: printk("Modem status changed for serial port.\n"); } } } }
void PutUARTByte (const char c) { while (!(UART_READ32 (UART_LSR(g_uart)) & UART_LSR_THRE)) { } if (c == '\n') UART_WRITE32 ((unsigned int) '\r', UART_THR(g_uart)); UART_WRITE32 ((unsigned int) c, UART_THR(g_uart)); }
/* This Function Wait Data TX Ready, and Write Data to UART if rx_timeout_nb_cycles = 0 Infinite wait */ void uart_write(uart_num_t uart_num, uint8_t data) { uint32_t uart_port; uart_port = uart_num; /* Wait Until FIFO not full */ while ((UART_LSR(uart_port) & UART_LSR_THRE) == 0); UART_THR(uart_port) = data; }
void rt_hw_console_output(const char* ptr) { /* stream mode */ while (*ptr) { if (*ptr == '\n') { /* FIFO status, contain valid data */ while (!(UART_LSR(UART0_BASE) & (UARTLSR_TE | UARTLSR_TFE))); /* write data */ UART_DAT(UART0_BASE) = '\r'; } /* FIFO status, contain valid data */ while (!(UART_LSR(UART0_BASE) & (UARTLSR_TE | UARTLSR_TFE))); /* write data */ UART_DAT(UART0_BASE) = *ptr; ptr ++; } }
/* * This Function Wait until Data RX Ready, and return Data Read from UART. */ uint8_t uart_read(uart_num_t uart_num) { uint32_t uart_port; uint8_t uart_val; uart_port = uart_num; /* Wait Until Data Received (Rx Data Not Ready) */ while ((UART_LSR(uart_port) & UART_LSR_RDR) == 0); uart_val = (UART_RBR(uart_port) & UART_RBR_MASKBIT); return uart_val; }
int GetUARTBytes(u8 *buf, u32 size, u32 tmo_ms) { u32 LSR; int tmo_en = (tmo_ms) ? 1 : 0; ulong start_time = get_timer(0); while (size) { if (tmo_en && (get_timer(start_time) > tmo_ms)) break; /* kick watchdog to avoid cpu reset */ if (!tmo_en) platform_wdt_kick(); LSR = UART_READ32(UART_LSR(g_uart)); if (LSR & UART_LSR_DR) { *buf++ = (u8)UART_READ32(UART_RBR(g_uart)); size--; } } return (0 == size) ? 0 : -1; }
/* * UART Init function */ void uart_init(uart_num_t uart_num, uart_databit_t data_nb_bits, uart_stopbit_t data_nb_stop, uart_parity_t data_parity, uint16_t uart_divisor, uint8_t uart_divaddval, uint8_t uart_mulval) { uint32_t lcr_config; uint32_t uart_port; uart_port = uart_num; switch(uart_num) { case UART0_NUM: /* use PLL1 as clock source for UART0 */ CGU_BASE_UART0_CLK = (CGU_SRC_PLL1<<UART_CGU_BASE_CLK_SEL_SHIFT) | (1<<UART_CGU_AUTOBLOCK_CLOCK_BIT); break; case UART1_NUM: /* use PLL1 as clock source for UART1 */ CGU_BASE_UART1_CLK = (CGU_SRC_PLL1<<UART_CGU_BASE_CLK_SEL_SHIFT) | (1<<UART_CGU_AUTOBLOCK_CLOCK_BIT); break; case UART2_NUM: /* use PLL1 as clock source for UART2 */ CGU_BASE_UART2_CLK = (CGU_SRC_PLL1<<UART_CGU_BASE_CLK_SEL_SHIFT) | (1<<UART_CGU_AUTOBLOCK_CLOCK_BIT); break; case UART3_NUM: /* use PLL1 as clock source for UART3 */ CGU_BASE_UART3_CLK = (CGU_SRC_PLL1<<UART_CGU_BASE_CLK_SEL_SHIFT) | (1<<UART_CGU_AUTOBLOCK_CLOCK_BIT); break; default: return; /* error */ } /* FIFOs RX/TX Enabled and Reset RX/TX FIFO (DMA Mode is also cleared) */ UART_FCR(uart_port) = ( UART_FCR_FIFO_EN | UART_FCR_RX_RS | UART_FCR_TX_RS); /* Disable FIFO */ UART_FCR(uart_port) = 0; // Dummy read (to clear existing data) while (UART_LSR(uart_port) & UART_LSR_RDR ) { dummy_read = UART_RBR(uart_port); } /* Wait end of TX & disable TX */ UART_TER(uart_port) = UART_TER_TXEN; /* Wait for current transmit complete */ while (!(UART_LSR(uart_port) & UART_LSR_THRE)); /* Disable Tx */ UART_TER(uart_port) = 0; /* Disable interrupt */ UART_IER(uart_port) = 0; /* Set LCR to default state */ UART_LCR(uart_port) = 0; /* Set ACR to default state */ UART_ACR(uart_port) = 0; /* Dummy Read to Clear Status */ dummy_read = UART_LSR(uart_port); /* Table 835. USART Fractional Divider Register: UARTbaudrate = PCLK / ( 16* (((256*DLM)+ DLL)*(1+(DivAddVal/MulVal))) ) The value of MULVAL and DIVADDVAL should comply to the following conditions: 1. 1 <= MULVAL <= 15 2. 0 <= DIVADDVAL <= 14 3. DIVADDVAL < MULVAL */ /* Set DLAB Bit */ UART_LCR(uart_port) |= UART_LCR_DLAB_EN; UART_DLM(uart_port) = UART_LOAD_DLM(uart_divisor); UART_DLL(uart_port) = UART_LOAD_DLL(uart_divisor); /* Clear DLAB Bit */ UART_LCR(uart_port) &= (~UART_LCR_DLAB_EN) & UART_LCR_BITMASK; UART_FDR(uart_port) = (UART_FDR_MULVAL(uart_mulval) | UART_FDR_DIVADDVAL(uart_divaddval)) & UART_FDR_BITMASK; /* Read LCR config & Force Enable of Divisor Latches Access */ lcr_config = (UART_LCR(uart_port) & UART_LCR_DLAB_EN) & UART_LCR_BITMASK; lcr_config |= data_nb_bits; /* Set Nb Data Bits */ lcr_config |= data_nb_stop; /* Set Nb Stop Bits */ lcr_config |= data_parity; /* Set Data Parity */ /* Write LCR (only 8bits) */ UART_LCR(uart_port) = (lcr_config & UART_LCR_BITMASK); /* Enable TX */ UART_TER(uart_port) = UART_TER_TXEN; }
static _INLINE_ void receive_chars(struct bf535_serial *info, struct pt_regs *regs, unsigned short rx) { struct tty_struct *tty = info->tty; unsigned char ch; int idx = info->hub2; /* * This do { } while() loop will get ALL chars out of Rx FIFO */ do { ch = (unsigned char) rx; if(info->is_cons) { if (UART_LSR(idx) & UART_LSR_BI){ /* break received */ status_handle(info, UART_LSR(idx)); return; } else if (ch == 0x10) { /* ^P */ show_state(); show_free_areas(); show_buffers(); /* show_net_buffers(); */ return; } else if (ch == 0x12) { /* ^R */ machine_restart(NULL); return; } } if(!tty){ printk("no tty\n"); goto clear_and_exit; } /* * Make sure that we do not overflow the buffer */ if (tty->flip.count >= TTY_FLIPBUF_SIZE) { queue_task(&tty->flip.tqueue, &tq_timer); return; } if(UART_LSR(idx) & UART_LSR_PE) { *tty->flip.flag_buf_ptr++ = TTY_PARITY; status_handle(info, UART_LSR(idx)); } else if(UART_LSR(idx) & UART_LSR_OE) { *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; status_handle(info, UART_LSR(idx)); } else if(UART_LSR(idx) & UART_LSR_FE) { *tty->flip.flag_buf_ptr++ = TTY_FRAME; status_handle(info, UART_LSR(idx)); } else { *tty->flip.flag_buf_ptr++ = 0; /* XXX */ } tty->flip.count++; *tty->flip.char_buf_ptr++ = ch; ACCESS_PORT_IER(idx) /* change access to port data */ rx = UART_RBR(idx); } while(UART_LSR(idx) & UART_LSR_DR); queue_task(&tty->flip.tqueue, &tq_timer); clear_and_exit: return; }