1 /*
2 * Copyright 2013 Google Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <libpayload.h>
29 #include <stdint.h>
30
31 struct s5p_uart
32 {
33 uint32_t ulcon; // line control
34 uint32_t ucon; // control
35 uint32_t ufcon; // FIFO control
36 uint32_t umcon; // modem control
37 uint32_t utrstat; // Tx/Rx status
38 uint32_t uerstat; // Rx error status
39 uint32_t ufstat; // FIFO status
40 uint32_t umstat; // modem status
41 uint32_t utxh; // transmit buffer
42 uint32_t urxh; // receive buffer
43 uint32_t ubrdiv; // baud rate divisor
44 uint32_t ufracval; // divisor fractional value
45 uint32_t uintp; // interrupt pending
46 uint32_t uints; // interrupt source
47 uint32_t uintm; // interrupt mask
48 };
49
50 static struct s5p_uart *uart_regs;
51
serial_putchar(unsigned int c)52 void serial_putchar(unsigned int c)
53 {
54 const uint32_t TxFifoFullBit = (0x1 << 24);
55
56 while (readl(&uart_regs->ufstat) & TxFifoFullBit)
57 {;}
58
59 writeb(c, &uart_regs->utxh);
60 if (c == '\n')
61 serial_putchar('\r');
62 }
63
serial_havechar(void)64 int serial_havechar(void)
65 {
66 const uint32_t DataReadyMask = (0xf << 0) | (0x1 << 8);
67
68 return (readl(&uart_regs->ufstat) & DataReadyMask) != 0;
69 }
70
serial_getchar(void)71 int serial_getchar(void)
72 {
73 while (!serial_havechar())
74 {;}
75
76 return readb(&uart_regs->urxh);
77 }
78
79 static struct console_output_driver s5p_serial_output =
80 {
81 .putchar = &serial_putchar
82 };
83
84 static struct console_input_driver s5p_serial_input =
85 {
86 .havekey = &serial_havechar,
87 .getchar = &serial_getchar,
88 .input_type = CONSOLE_INPUT_TYPE_UART,
89 };
90
serial_init(void)91 void serial_init(void)
92 {
93 const struct cb_serial *const serial = phys_to_virt(lib_sysinfo.cb_serial);
94
95 if (!lib_sysinfo.cb_serial || !serial->baseaddr)
96 return;
97
98 uart_regs = (struct s5p_uart *)serial->baseaddr;
99 }
100
serial_console_init(void)101 void serial_console_init(void)
102 {
103 serial_init();
104
105 if (uart_regs) {
106 console_add_output_driver(&s5p_serial_output);
107 console_add_input_driver(&s5p_serial_input);
108 }
109 }
110