1 /*
2  * Copyright (c) 2015 Travis Geiselbrecht
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 #include <lk/reg.h>
9 #include <lk/trace.h>
10 #include <lib/cbuf.h>
11 #include <lk/init.h>
12 #include <kernel/thread.h>
13 #include <platform.h>
14 #include <platform/interrupts.h>
15 #include <sys/types.h>
16 #include <target/microblaze-config.h>
17 
18 #include "uartlite.h"
19 
20 #define LOCAL_TRACE 0
21 
22 #define R_RX            0
23 #define R_TX            1
24 #define R_STATUS        2
25 #define R_CTRL          3
26 #define R_MAX           4
27 
28 #define STATUS_RXVALID    0x01
29 #define STATUS_RXFULL     0x02
30 #define STATUS_TXEMPTY    0x04
31 #define STATUS_TXFULL     0x08
32 #define STATUS_IE         0x10
33 #define STATUS_OVERRUN    0x20
34 #define STATUS_FRAME      0x40
35 #define STATUS_PARITY     0x80
36 
37 #define CONTROL_RST_TX    0x01
38 #define CONTROL_RST_RX    0x02
39 #define CONTROL_IE        0x10
40 
41 #define UART_REG(reg) (*REG32(UARTLITE_BASEADDR + (reg) * 4))
42 
43 #define RXBUF_SIZE 128
44 static cbuf_t uart_rx_buf;
45 
uartlite_putc(char c)46 void uartlite_putc(char c) {
47     while (UART_REG(R_STATUS) & STATUS_TXFULL)
48         ;
49     UART_REG(R_TX) = c;
50 }
51 
uartlite_getc(bool wait)52 int uartlite_getc(bool wait) {
53 #if 0
54     char c;
55     if (cbuf_read_char(&uart_rx_buf, &c, wait) == 1)
56         return c;
57 #else
58     do {
59         if (UART_REG(R_STATUS) & STATUS_RXVALID) {
60             char c = UART_REG(R_RX);
61             return c;
62         }
63     } while (wait);
64 #endif
65 
66     return -1;
67 }
68 
uartlite_irq(void * arg)69 static enum handler_return uartlite_irq(void *arg) {
70     bool resched = false;
71 
72     /* while receive fifo not empty, read a char */
73     while (UART_REG(R_STATUS) & STATUS_RXVALID) {
74         char c = UART_REG(R_RX);
75         cbuf_write_char(&uart_rx_buf, c, false);
76 
77         resched = true;
78     }
79 
80     return resched ? INT_RESCHEDULE : INT_NO_RESCHEDULE;
81 }
82 
uartlite_init(uint level)83 static void uartlite_init(uint level) {
84     TRACE;
85 
86     //UART_REG(R_CTRL) = CONTROL_RST_TX | CONTROL_RST_RX;
87 //    UART_REG(R_CTRL) |= CONTROL_IE;
88 
89     cbuf_initialize(&uart_rx_buf, RXBUF_SIZE);
90 
91 //    register_int_handler(UARTLITE_IRQ, uartlite_irq, NULL);
92 //    unmask_interrupt(UARTLITE_IRQ);
93 }
94 
95 LK_INIT_HOOK(uartlite, uartlite_init, LK_INIT_LEVEL_PLATFORM);
96 
97