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