-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathserial-exynos.c
84 lines (70 loc) · 1.65 KB
/
serial-exynos.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include "types.h"
#include "register.h"
#include "serial.h"
#define EXYNOS_BASE_UART 0x13800000
#define TX_FIFO_FULL_MASK (1 << 24)
#define UART_BAUDRATE_115200 115200
union br_rest {
unsigned short slot; /* udivslot */
unsigned char value; /* ufracval */
};
struct s5p_uart {
unsigned int ulcon;
unsigned int ucon;
unsigned int ufcon;
unsigned int umcon;
unsigned int utrstat;
unsigned int uerstat;
unsigned int ufstat;
unsigned int umstat;
unsigned char utxh;
unsigned char res1[3];
unsigned char urxh;
unsigned char res2[3];
unsigned int ubrdiv;
union br_rest rest;
unsigned char res3[0xffd0];
};
static inline struct s5p_uart *s5p_get_base_uart(int dev_index)
{
u32 offset = dev_index * sizeof(struct s5p_uart);
return (struct s5p_uart *)(EXYNOS_BASE_UART + offset);
}
static inline int s5p_uart_divslot(void)
{
return 0;
}
static int serial_err_check(const int dev_index, int op)
{
struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
unsigned int mask;
/*
* UERSTAT
* Break Detect [3]
* Frame Err [2] : receive operation
* Parity Err [1] : receive operation
* Overrun Err [0] : receive operation
*/
if (op)
mask = 0x8;
else
mask = 0xf;
return readl((unsigned int)&uart->uerstat) & mask;
}
/*
* Output a single byte to the serial port.
*/
void __putch(char c)
{
const int dev_index = UART_PORT;
struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
/* wait for room in the tx FIFO */
while ((readl((unsigned int)&uart->ufstat) & TX_FIFO_FULL_MASK)) {
if (serial_err_check(dev_index, 1))
return;
}
writeb(c, (unsigned int)&uart->utxh);
/* If \n, also do \r */
if (c == '\n')
__putch('\r');
}