coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
uart.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include <types.h>
4 #include <console/uart.h>
5 #include <device/mmio.h>
6 #include <boot/coreboot_tables.h>
7 #include <soc/ti/am335x/uart.h>
8 
9 #define EFR_ENHANCED_EN (1 << 4)
10 #define FCR_FIFO_EN (1 << 0)
11 #define MCR_TCR_TLR (1 << 6)
12 #define SYSC_SOFTRESET (1 << 1)
13 #define SYSS_RESETDONE (1 << 0)
14 
15 #define LSR_RXFIFOE (1 << 0)
16 #define LSR_TXFIFOE (1 << 5)
17 
18 /*
19  * Initialise the serial port with the given baudrate divisor. The settings
20  * are always 8 data bits, no parity, 1 stop bit, no start bits.
21  */
22 static void am335x_uart_init(struct am335x_uart *uart, uint16_t div)
23 {
24  uint16_t lcr_orig, efr_orig, mcr_orig;
25 
26  /* reset the UART */
27  write16(&uart->sysc, uart->sysc | SYSC_SOFTRESET);
28  while (!(read16(&uart->syss) & SYSS_RESETDONE))
29  ;
30 
31  /* 1. switch to register config mode B */
32  lcr_orig = read16(&uart->lcr);
33  write16(&uart->lcr, 0xbf);
34 
35  /*
36  * 2. Set EFR ENHANCED_EN bit. To access this bit, registers must
37  * be in TCR_TLR submode, meaning EFR[4] = 1 and MCR[6] = 1.
38  */
39  efr_orig = read16(&uart->efr);
40  write16(&uart->efr, efr_orig | EFR_ENHANCED_EN);
41 
42  /* 3. Switch to register config mode A */
43  write16(&uart->lcr, 0x80);
44 
45  /* 4. Enable register submode TCR_TLR to access the UARTi.UART_TLR */
46  mcr_orig = read16(&uart->mcr);
47  write16(&uart->mcr, mcr_orig | MCR_TCR_TLR);
48 
49  /* 5. Enable the FIFO. For now we'll ignore FIFO triggers and DMA */
50  write16(&uart->fcr, FCR_FIFO_EN);
51 
52  /* 6. Switch to configuration mode B */
53  write16(&uart->lcr, 0xbf);
54  /* Skip steps 7 and 8 (setting up FIFO triggers for DMA) */
55 
56  /* 9. Restore original EFR value */
57  write16(&uart->efr, efr_orig);
58 
59  /* 10. Switch to config mode A */
60  write16(&uart->lcr, 0x80);
61 
62  /* 11. Restore original MCR value */
63  write16(&uart->mcr, mcr_orig);
64 
65  /* 12. Restore original LCR value */
66  write16(&uart->lcr, lcr_orig);
67 
68  /* Protocol, baud rate and interrupt settings */
69 
70  /* 1. Disable UART access to DLL and DLH registers */
71  write16(&uart->mdr1, read16(&uart->mdr1) | 0x7);
72 
73  /* 2. Switch to config mode B */
74  write16(&uart->lcr, 0xbf);
75 
76  /* 3. Enable access to IER[7:4] */
77  write16(&uart->efr, efr_orig | EFR_ENHANCED_EN);
78 
79  /* 4. Switch to operational mode */
80  write16(&uart->lcr, 0x0);
81 
82  /* 5. Clear IER */
83  write16(&uart->ier, 0x0);
84 
85  /* 6. Switch to config mode B */
86  write16(&uart->lcr, 0xbf);
87 
88  /* 7. Set dll and dlh to the desired values (table 19-25) */
89  write16(&uart->dlh, (div >> 8));
90  write16(&uart->dll, (div & 0xff));
91 
92  /* 8. Switch to operational mode to access ier */
93  write16(&uart->lcr, 0x0);
94 
95  /* 9. Clear ier to disable all interrupts */
96  write16(&uart->ier, 0x0);
97 
98  /* 10. Switch to config mode B */
99  write16(&uart->lcr, 0xbf);
100 
101  /* 11. Restore efr */
102  write16(&uart->efr, efr_orig);
103 
104  /* 12. Set protocol formatting 8n1 (8 bit data, no parity, 1 stop bit) */
105  write16(&uart->lcr, 0x3);
106 
107  /* 13. Load the new UART mode */
108  write16(&uart->mdr1, 0x0);
109 }
110 
111 /*
112  * Read a single byte from the serial port. Returns 1 on success, 0
113  * otherwise. When the function is successful, the character read is
114  * written into its argument c.
115  */
116 static unsigned char am335x_uart_rx_byte(struct am335x_uart *uart)
117 {
118  while (!(read16(&uart->lsr) & LSR_RXFIFOE));
119 
120  return read8(&uart->rhr);
121 }
122 
123 /*
124  * Output a single byte to the serial port.
125  */
126 static void am335x_uart_tx_byte(struct am335x_uart *uart, unsigned char data)
127 {
128  while (!(read16(&uart->lsr) & LSR_TXFIFOE));
129 
130  return write8(&uart->thr, data);
131 }
132 
133 unsigned int uart_platform_refclk(void)
134 {
135  return 48000000;
136 }
137 
138 uintptr_t uart_platform_base(unsigned int idx)
139 {
140  const unsigned int bases[] = {
141  0x44e09000, 0x48022000, 0x48024000,
142  0x481a6000, 0x481a8000, 0x481aa000
143  };
144  if (idx < ARRAY_SIZE(bases))
145  return bases[idx];
146  return 0;
147 }
148 
149 void uart_init(unsigned int idx)
150 {
151  struct am335x_uart *uart = uart_platform_baseptr(idx);
154  am335x_uart_init(uart, div);
155 }
156 
157 unsigned char uart_rx_byte(unsigned int idx)
158 {
159  struct am335x_uart *uart = uart_platform_baseptr(idx);
160  return am335x_uart_rx_byte(uart);
161 }
162 
163 void uart_tx_byte(unsigned int idx, unsigned char data)
164 {
165  struct am335x_uart *uart = uart_platform_baseptr(idx);
166  am335x_uart_tx_byte(uart, data);
167 }
168 
169 void uart_tx_flush(unsigned int idx)
170 {
171 }
172 
173 void uart_fill_lb(void *data)
174 {
175  struct lb_serial serial;
177  serial.baseaddr = uart_platform_base(CONFIG_UART_FOR_CONSOLE);
178  serial.baud = get_uart_baudrate();
179  serial.regwidth = 2;
180  serial.input_hertz = uart_platform_refclk();
181  serial.uart_pci_addr = CONFIG_UART_PCI_ADDR;
182  lb_add_serial(&serial, data);
183 
185 }
static void write8(void *addr, uint8_t val)
Definition: mmio.h:30
static uint16_t read16(const void *addr)
Definition: mmio.h:17
static uint8_t read8(const void *addr)
Definition: mmio.h:12
static void write16(void *addr, uint16_t val)
Definition: mmio.h:35
unsigned int get_uart_baudrate(void)
Definition: bmcinfo.c:167
#define ARRAY_SIZE(a)
Definition: helpers.h:12
#define LB_TAG_CONSOLE_SERIAL8250MEM
#define LB_SERIAL_TYPE_MEMORY_MAPPED
unsigned int uart_baudrate_divisor(unsigned int baudrate, unsigned int refclk, unsigned int oversample)
Definition: util.c:8
void lb_add_console(uint16_t consoletype, void *data)
void lb_add_serial(struct lb_serial *serial, void *data)
static void * uart_platform_baseptr(unsigned int idx)
Definition: uart.h:57
unsigned int serial
Definition: edid.c:52
void uart_init(unsigned int idx)
Definition: uart.c:13
void uart_tx_flush(unsigned int idx)
Definition: uart.c:27
uintptr_t uart_platform_base(unsigned int idx)
Definition: uart.c:8
unsigned char uart_rx_byte(unsigned int idx)
Definition: uart.c:17
void uart_fill_lb(void *data)
Definition: uart.c:31
void uart_tx_byte(unsigned int idx, unsigned char data)
Definition: uart.c:22
unsigned int uart_platform_refclk(void)
Definition: uart.c:85
static unsigned char am335x_uart_rx_byte(struct am335x_uart *uart)
Definition: uart.c:116
#define MCR_TCR_TLR
Definition: uart.c:11
#define EFR_ENHANCED_EN
Definition: uart.c:9
static void am335x_uart_init(struct am335x_uart *uart, uint16_t div)
Definition: uart.c:22
#define SYSC_SOFTRESET
Definition: uart.c:12
#define LSR_TXFIFOE
Definition: uart.c:16
#define LSR_RXFIFOE
Definition: uart.c:15
static void am335x_uart_tx_byte(struct am335x_uart *uart, unsigned char data)
Definition: uart.c:126
#define SYSS_RESETDONE
Definition: uart.c:13
#define FCR_FIFO_EN
Definition: uart.c:10
unsigned short uint16_t
Definition: stdint.h:11
unsigned long uintptr_t
Definition: stdint.h:21
uint16_t dlh
Definition: uart.h:33
uint16_t efr
Definition: uart.h:41
uint16_t mcr
Definition: uart.h:50
uint16_t ier
Definition: uart.h:31
uint16_t fcr
Definition: uart.h:39
uint16_t sysc
Definition: uart.h:133
uint16_t rhr
Definition: uart.h:23
uint16_t dll
Definition: uart.h:26
uint16_t mdr1
Definition: uart.h:90
uint16_t syss
Definition: uart.h:135
uint16_t lcr
Definition: uart.h:44
uint16_t lsr
Definition: uart.h:58
uint16_t thr
Definition: uart.h:24
static const unsigned int bases[]
Definition: uart8250io.c:75