1 /*
2  * Copyright (c) 2015 MediaTek Inc.
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/debug.h>
9 #include <lk/reg.h>
10 #include <dev/uart.h>
11 #include <string.h>
12 
13 #include <platform/mt_typedefs.h>
14 #include <platform/mt_reg_base.h>
15 #include <platform/mt_uart.h>
16 #include <sync_write.h>
17 
18 // output uart port
19 static volatile unsigned int g_uart;
20 // output uart baudrate
21 static unsigned int g_brg;
22 
uart_setbrg(void)23 static void uart_setbrg(void) {
24     unsigned int byte,speed;
25     unsigned int highspeed;
26     unsigned int quot, divisor, remainder;
27     unsigned int uartclk;
28     unsigned short data, high_speed_div, sample_count, sample_point;
29     unsigned int tmp_div;
30 
31     speed = g_brg;
32     uartclk = UART_SRC_CLK;
33 
34     if (speed <= 115200 ) {
35         highspeed = 0;
36         quot = 16;
37     } else {
38         highspeed = 3;
39         quot = 1;
40     }
41 
42     if (highspeed < 3) { /*0~2*/
43         /* Set divisor DLL and DLH  */
44         divisor   =  uartclk / (quot * speed);
45         remainder =  uartclk % (quot * speed);
46 
47         if (remainder >= (quot / 2) * speed)
48             divisor += 1;
49 
50         mt_reg_sync_writew(highspeed, UART_HIGHSPEED(g_uart));
51         byte = DRV_Reg32(UART_LCR(g_uart));   /* DLAB start */
52         mt_reg_sync_writel((byte | UART_LCR_DLAB), UART_LCR(g_uart));
53         mt_reg_sync_writel((divisor & 0x00ff), UART_DLL(g_uart));
54         mt_reg_sync_writel(((divisor >> 8)&0x00ff), UART_DLH(g_uart));
55         mt_reg_sync_writel(byte, UART_LCR(g_uart));   /* DLAB end */
56     } else {
57         data=(unsigned short)(uartclk/speed);
58         high_speed_div = (data>>8) + 1; // divided by 256
59 
60         tmp_div=uartclk/(speed*high_speed_div);
61         divisor =  (unsigned short)tmp_div;
62 
63         remainder = (uartclk)%(high_speed_div*speed);
64         /*get (sample_count+1)*/
65         if (remainder >= ((speed)*(high_speed_div))>>1)
66             divisor =  (unsigned short)(tmp_div+1);
67         else
68             divisor =  (unsigned short)tmp_div;
69 
70         sample_count=divisor-1;
71 
72         /*get the sample point*/
73         sample_point=(sample_count-1)>>1;
74 
75         /*configure register*/
76         mt_reg_sync_writel(highspeed, UART_HIGHSPEED(g_uart));
77 
78         byte = DRV_Reg32(UART_LCR(g_uart));    /* DLAB start */
79         mt_reg_sync_writel((byte | UART_LCR_DLAB), UART_LCR(g_uart));
80         mt_reg_sync_writel((high_speed_div & 0x00ff), UART_DLL(g_uart));
81         mt_reg_sync_writel(((high_speed_div >> 8)&0x00ff), UART_DLH(g_uart));
82         mt_reg_sync_writel(sample_count, UART_SAMPLE_COUNT(g_uart));
83         mt_reg_sync_writel(sample_point, UART_SAMPLE_POINT(g_uart));
84         mt_reg_sync_writel(byte, UART_LCR(g_uart));   /* DLAB end */
85     }
86 }
87 
mtk_set_current_uart(MTK_UART uart_base)88 void mtk_set_current_uart(MTK_UART uart_base) {
89     g_uart = uart_base;
90 }
91 
mtk_get_current_uart(void)92 int mtk_get_current_uart(void) {
93     return g_uart;
94 }
95 
uart_init_early(void)96 void uart_init_early(void) {
97     mtk_set_current_uart(UART1);
98 
99     DRV_SetReg32(UART_FCR(g_uart), UART_FCR_FIFO_INIT); /* clear fifo */
100     mt_reg_sync_writew(UART_NONE_PARITY | UART_WLS_8 | UART_1_STOP, UART_LCR(g_uart));
101     g_brg = CONFIG_BAUDRATE;
102     uart_setbrg();
103 }
104 
uart_init(void)105 void uart_init(void) {
106 }
107 
uart_flush_tx(int port)108 void uart_flush_tx(int port) {
109 }
110 
uart_flush_rx(int port)111 void uart_flush_rx(int port) {
112 }
113 
uart_init_port(int port,uint baud)114 void uart_init_port(int port, uint baud) {
115 }
116 
uart_putc(int port,char c)117 int uart_putc(int port, char c) {
118     while (!(DRV_Reg32(UART_LSR(port)) & UART_LSR_THRE));
119 
120     if (c == '\n')
121         mt_reg_sync_writel((unsigned int)'\r', UART_THR(port));
122 
123     mt_reg_sync_writel((unsigned int)c, UART_THR(port));
124 
125     return 0;
126 }
127 
uart_getc(int port,bool wait)128 int uart_getc(int port, bool wait) {
129     while (!(DRV_Reg32(UART_LSR(port)) & UART_LSR_DR));
130     return (int)DRV_Reg32(UART_RBR(port));
131 }
132 
133