Rename __attribute__((packed)) --> __packed
[coreboot.git] / src / cpu / ti / am335x / uart.c
blob45a693a95318545d1361c3e28a9845d878f928aa
1 /*
2 * Copyright 2013 Google Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #include <stdlib.h>
16 #include <types.h>
17 #include <console/uart.h>
18 #include <arch/io.h>
19 #include <boot/coreboot_tables.h>
20 #include <cpu/ti/am335x/uart.h>
22 #define EFR_ENHANCED_EN (1 << 4)
23 #define FCR_FIFO_EN (1 << 0)
24 #define MCR_TCR_TLR (1 << 6)
25 #define SYSC_SOFTRESET (1 << 1)
26 #define SYSS_RESETDONE (1 << 0)
28 #define LSR_RXFIFOE (1 << 0)
29 #define LSR_TXFIFOE (1 << 5)
32 * Initialise the serial port with the given baudrate divisor. The settings
33 * are always 8 data bits, no parity, 1 stop bit, no start bits.
35 static void am335x_uart_init(struct am335x_uart *uart, uint16_t div)
37 uint16_t lcr_orig, efr_orig, mcr_orig;
39 /* reset the UART */
40 write16(&uart->sysc, uart->sysc | SYSC_SOFTRESET);
41 while (!(read16(&uart->syss) & SYSS_RESETDONE))
44 /* 1. switch to register config mode B */
45 lcr_orig = read16(&uart->lcr);
46 write16(&uart->lcr, 0xbf);
49 * 2. Set EFR ENHANCED_EN bit. To access this bit, registers must
50 * be in TCR_TLR submode, meaning EFR[4] = 1 and MCR[6] = 1.
52 efr_orig = read16(&uart->efr);
53 write16(&uart->efr, efr_orig | EFR_ENHANCED_EN);
55 /* 3. Switch to register config mode A */
56 write16(&uart->lcr, 0x80);
58 /* 4. Enable register submode TCR_TLR to access the UARTi.UART_TLR */
59 mcr_orig = read16(&uart->mcr);
60 write16(&uart->mcr, mcr_orig | MCR_TCR_TLR);
62 /* 5. Enable the FIFO. For now we'll ignore FIFO triggers and DMA */
63 write16(&uart->fcr, FCR_FIFO_EN);
65 /* 6. Switch to configuration mode B */
66 write16(&uart->lcr, 0xbf);
67 /* Skip steps 7 and 8 (setting up FIFO triggers for DMA) */
69 /* 9. Restore original EFR value */
70 write16(&uart->efr, efr_orig);
72 /* 10. Switch to config mode A */
73 write16(&uart->lcr, 0x80);
75 /* 11. Restore original MCR value */
76 write16(&uart->mcr, mcr_orig);
78 /* 12. Restore original LCR value */
79 write16(&uart->lcr, lcr_orig);
81 /* Protocol, baud rate and interrupt settings */
83 /* 1. Disable UART access to DLL and DLH registers */
84 write16(&uart->mdr1, read16(&uart->mdr1) | 0x7);
86 /* 2. Switch to config mode B */
87 write16(&uart->lcr, 0xbf);
89 /* 3. Enable access to IER[7:4] */
90 write16(&uart->efr, efr_orig | EFR_ENHANCED_EN);
92 /* 4. Switch to operational mode */
93 write16(&uart->lcr, 0x0);
95 /* 5. Clear IER */
96 write16(&uart->ier, 0x0);
98 /* 6. Switch to config mode B */
99 write16(&uart->lcr, 0xbf);
101 /* 7. Set dll and dlh to the desired values (table 19-25) */
102 write16(&uart->dlh, (div >> 8));
103 write16(&uart->dll, (div & 0xff));
105 /* 8. Switch to operational mode to access ier */
106 write16(&uart->lcr, 0x0);
108 /* 9. Clear ier to disable all interrupts */
109 write16(&uart->ier, 0x0);
111 /* 10. Switch to config mode B */
112 write16(&uart->lcr, 0xbf);
114 /* 11. Restore efr */
115 write16(&uart->efr, efr_orig);
117 /* 12. Set protocol formatting 8n1 (8 bit data, no parity, 1 stop bit) */
118 write16(&uart->lcr, 0x3);
120 /* 13. Load the new UART mode */
121 write16(&uart->mdr1, 0x0);
125 * Read a single byte from the serial port. Returns 1 on success, 0
126 * otherwise. When the function is successful, the character read is
127 * written into its argument c.
129 static unsigned char am335x_uart_rx_byte(struct am335x_uart *uart)
131 while (!(read16(&uart->lsr) & LSR_RXFIFOE));
133 return read8(&uart->rhr);
137 * Output a single byte to the serial port.
139 static void am335x_uart_tx_byte(struct am335x_uart *uart, unsigned char data)
141 while (!(read16(&uart->lsr) & LSR_TXFIFOE));
143 return write8(&uart->thr, data);
146 unsigned int uart_platform_refclk(void)
148 return 48000000;
151 uintptr_t uart_platform_base(int idx)
153 const unsigned int bases[] = {
154 0x44e09000, 0x48022000, 0x48024000,
155 0x481a6000, 0x481a8000, 0x481aa000
157 if (idx < ARRAY_SIZE(bases))
158 return bases[idx];
159 return 0;
162 void uart_init(int idx)
164 struct am335x_uart *uart = uart_platform_baseptr(idx);
165 uint16_t div = (uint16_t) uart_baudrate_divisor(
166 default_baudrate(), uart_platform_refclk(), 16);
167 am335x_uart_init(uart, div);
170 unsigned char uart_rx_byte(int idx)
172 struct am335x_uart *uart = uart_platform_baseptr(idx);
173 return am335x_uart_rx_byte(uart);
176 void uart_tx_byte(int idx, unsigned char data)
178 struct am335x_uart *uart = uart_platform_baseptr(idx);
179 am335x_uart_tx_byte(uart, data);
182 void uart_tx_flush(int idx)
186 #ifndef __PRE_RAM__
187 void uart_fill_lb(void *data)
189 struct lb_serial serial;
190 serial.type = LB_SERIAL_TYPE_MEMORY_MAPPED;
191 serial.baseaddr = uart_platform_base(CONFIG_UART_FOR_CONSOLE);
192 serial.baud = default_baudrate();
193 serial.regwidth = 2;
194 lb_add_serial(&serial, data);
196 lb_add_console(LB_TAG_CONSOLE_SERIAL8250MEM, data);
198 #endif