1 /* SPDX-License-Identifier: GPL-2.0-or-later */
4 #include <console/uart.h>
5 #include <device/mmio.h>
6 #include <boot/coreboot_tables.h>
7 #include <soc/ti/am335x/uart.h>
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)
15 #define LSR_RXFIFOE (1 << 0)
16 #define LSR_TXFIFOE (1 << 5)
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.
22 static void am335x_uart_init(struct am335x_uart
*uart
, uint16_t div
)
24 uint16_t lcr_orig
, efr_orig
, mcr_orig
;
27 write16(&uart
->sysc
, uart
->sysc
| SYSC_SOFTRESET
);
28 while (!(read16(&uart
->syss
) & SYSS_RESETDONE
))
31 /* 1. switch to register config mode B */
32 lcr_orig
= read16(&uart
->lcr
);
33 write16(&uart
->lcr
, 0xbf);
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.
39 efr_orig
= read16(&uart
->efr
);
40 write16(&uart
->efr
, efr_orig
| EFR_ENHANCED_EN
);
42 /* 3. Switch to register config mode A */
43 write16(&uart
->lcr
, 0x80);
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
);
49 /* 5. Enable the FIFO. For now we'll ignore FIFO triggers and DMA */
50 write16(&uart
->fcr
, FCR_FIFO_EN
);
52 /* 6. Switch to configuration mode B */
53 write16(&uart
->lcr
, 0xbf);
54 /* Skip steps 7 and 8 (setting up FIFO triggers for DMA) */
56 /* 9. Restore original EFR value */
57 write16(&uart
->efr
, efr_orig
);
59 /* 10. Switch to config mode A */
60 write16(&uart
->lcr
, 0x80);
62 /* 11. Restore original MCR value */
63 write16(&uart
->mcr
, mcr_orig
);
65 /* 12. Restore original LCR value */
66 write16(&uart
->lcr
, lcr_orig
);
68 /* Protocol, baud rate and interrupt settings */
70 /* 1. Disable UART access to DLL and DLH registers */
71 write16(&uart
->mdr1
, read16(&uart
->mdr1
) | 0x7);
73 /* 2. Switch to config mode B */
74 write16(&uart
->lcr
, 0xbf);
76 /* 3. Enable access to IER[7:4] */
77 write16(&uart
->efr
, efr_orig
| EFR_ENHANCED_EN
);
79 /* 4. Switch to operational mode */
80 write16(&uart
->lcr
, 0x0);
83 write16(&uart
->ier
, 0x0);
85 /* 6. Switch to config mode B */
86 write16(&uart
->lcr
, 0xbf);
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));
92 /* 8. Switch to operational mode to access ier */
93 write16(&uart
->lcr
, 0x0);
95 /* 9. Clear ier to disable all interrupts */
96 write16(&uart
->ier
, 0x0);
98 /* 10. Switch to config mode B */
99 write16(&uart
->lcr
, 0xbf);
101 /* 11. Restore efr */
102 write16(&uart
->efr
, efr_orig
);
104 /* 12. Set protocol formatting 8n1 (8 bit data, no parity, 1 stop bit) */
105 write16(&uart
->lcr
, 0x3);
107 /* 13. Load the new UART mode */
108 write16(&uart
->mdr1
, 0x0);
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.
116 static unsigned char am335x_uart_rx_byte(struct am335x_uart
*uart
)
118 while (!(read16(&uart
->lsr
) & LSR_RXFIFOE
));
120 return read8(&uart
->rhr
);
124 * Output a single byte to the serial port.
126 static void am335x_uart_tx_byte(struct am335x_uart
*uart
, unsigned char data
)
128 while (!(read16(&uart
->lsr
) & LSR_TXFIFOE
));
130 return write8(&uart
->thr
, data
);
133 unsigned int uart_platform_refclk(void)
138 uintptr_t uart_platform_base(unsigned int idx
)
140 const unsigned int bases
[] = {
141 0x44e09000, 0x48022000, 0x48024000,
142 0x481a6000, 0x481a8000, 0x481aa000
144 if (idx
< ARRAY_SIZE(bases
))
149 void uart_init(unsigned int idx
)
151 struct am335x_uart
*uart
= uart_platform_baseptr(idx
);
152 uint16_t div
= (uint16_t)uart_baudrate_divisor(
153 get_uart_baudrate(), uart_platform_refclk(), 16);
154 am335x_uart_init(uart
, div
);
157 unsigned char uart_rx_byte(unsigned int idx
)
159 struct am335x_uart
*uart
= uart_platform_baseptr(idx
);
160 return am335x_uart_rx_byte(uart
);
163 void uart_tx_byte(unsigned int idx
, unsigned char data
)
165 struct am335x_uart
*uart
= uart_platform_baseptr(idx
);
166 am335x_uart_tx_byte(uart
, data
);
169 void uart_tx_flush(unsigned int idx
)
173 enum cb_err
fill_lb_serial(struct lb_serial
*serial
)
175 serial
->type
= LB_SERIAL_TYPE_MEMORY_MAPPED
;
176 serial
->baseaddr
= uart_platform_base(CONFIG_UART_FOR_CONSOLE
);
177 serial
->baud
= get_uart_baudrate();
178 serial
->regwidth
= 2;
179 serial
->input_hertz
= uart_platform_refclk();