1 /* 2 * Copyright (c) Linaro 2018 Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <stdint.h> 8 9 #include <platform_def.h> 10 11 #include <arch.h> 12 #include <lib/mmio.h> 13 14 #include <imx_uart.h> 15 16 /* TX/RX FIFO threshold */ 17 #define TX_RX_THRESH 2 18 19 struct clk_div_factors { 20 uint32_t fcr_div; 21 uint32_t bmr_div; 22 }; 23 24 static struct clk_div_factors clk_div[] = { 25 { 26 .fcr_div = IMX_UART_FCR_RFDIV1, 27 .bmr_div = 1, 28 }, 29 { 30 .fcr_div = IMX_UART_FCR_RFDIV2, 31 .bmr_div = 2, 32 }, 33 { 34 .fcr_div = IMX_UART_FCR_RFDIV3, 35 .bmr_div = 3, 36 }, 37 { 38 .fcr_div = IMX_UART_FCR_RFDIV4, 39 .bmr_div = 4, 40 }, 41 { 42 .fcr_div = IMX_UART_FCR_RFDIV5, 43 .bmr_div = 5, 44 }, 45 { 46 .fcr_div = IMX_UART_FCR_RFDIV6, 47 .bmr_div = 6, 48 }, 49 { 50 .fcr_div = IMX_UART_FCR_RFDIV7, 51 .bmr_div = 7, 52 }, 53 }; 54 55 static void write_reg(uintptr_t base, uint32_t offset, uint32_t val) 56 { 57 mmio_write_32(base + offset, val); 58 } 59 60 static uint32_t read_reg(uintptr_t base, uint32_t offset) 61 { 62 return mmio_read_32(base + offset); 63 } 64 65 int console_imx_uart_core_init(uintptr_t base_addr, unsigned int uart_clk, 66 unsigned int baud_rate) 67 { 68 uint32_t val; 69 uint8_t clk_idx = 1; 70 71 /* Reset UART */ 72 write_reg(base_addr, IMX_UART_CR2_OFFSET, 0); 73 do { 74 val = read_reg(base_addr, IMX_UART_CR2_OFFSET); 75 } while (!(val & IMX_UART_CR2_SRST)); 76 77 /* Enable UART */ 78 write_reg(base_addr, IMX_UART_CR1_OFFSET, IMX_UART_CR1_UARTEN); 79 80 /* Ignore RTS, 8N1, enable tx/rx, disable reset */ 81 val = (IMX_UART_CR2_IRTS | IMX_UART_CR2_WS | IMX_UART_CR2_TXEN | 82 IMX_UART_CR2_RXEN | IMX_UART_CR2_SRST); 83 write_reg(base_addr, IMX_UART_CR2_OFFSET, val); 84 85 /* No parity, autobaud detect-old, rxdmuxsel=1 (fixed i.mx7) */ 86 val = IMX_UART_CR3_ADNIMP | IMX_UART_CR3_RXDMUXSEL; 87 write_reg(base_addr, IMX_UART_CR3_OFFSET, val); 88 89 /* Set CTS FIFO trigger to 32 bytes bits 15:10 */ 90 write_reg(base_addr, IMX_UART_CR4_OFFSET, 0x8000); 91 92 /* TX/RX-thresh = 2 bytes, DTE (bit6 = 0), refclk @24MHz / 4 */ 93 val = IMX_UART_FCR_TXTL(TX_RX_THRESH) | IMX_UART_FCR_RXTL(TX_RX_THRESH) | 94 clk_div[clk_idx].fcr_div; 95 #ifdef IMX_UART_DTE 96 /* Set DTE (bit6 = 1) */ 97 val |= IMX_UART_FCR_DCEDTE; 98 #endif 99 write_reg(base_addr, IMX_UART_FCR_OFFSET, val); 100 101 /* 102 * The equation for BAUD rate calculation is 103 * RefClk = Supplied clock / FCR_DIVx 104 * 105 * BAUD = Refclk 106 * ------------ 107 * 16 x (UBMR + 1/ UBIR + 1) 108 * 109 * We write 0x0f into UBIR to remove the 16 mult 110 * BAUD = 6000000 111 * ------------ 112 * 16 x (UBMR + 1/ 15 + 1) 113 */ 114 115 write_reg(base_addr, IMX_UART_BIR_OFFSET, 0x0f); 116 val = ((uart_clk / clk_div[clk_idx].bmr_div) / baud_rate) - 1; 117 write_reg(base_addr, IMX_UART_BMR_OFFSET, val); 118 119 return 0; 120 } 121 122 /* -------------------------------------------------------- 123 * int console_core_putc(int c, uintptr_t base_addr) 124 * Function to output a character over the console. It 125 * returns the character printed on success or -1 on error. 126 * In : r0 - character to be printed 127 * r1 - console base address 128 * Out : return -1 on error else return character. 129 * Clobber list : r2 130 * -------------------------------------------------------- 131 */ 132 int console_imx_uart_core_putc(int c, uintptr_t base_addr) 133 { 134 uint32_t val; 135 136 if (c == '\n') 137 console_imx_uart_core_putc('\r', base_addr); 138 139 /* Write data */ 140 write_reg(base_addr, IMX_UART_TXD_OFFSET, c); 141 142 /* Wait for transmit */ 143 do { 144 val = read_reg(base_addr, IMX_UART_STAT2_OFFSET); 145 } while (!(val & IMX_UART_STAT2_TXDC)); 146 147 return 0; 148 } 149 150 /* 151 * Function to get a character from the console. 152 * It returns the character grabbed on success 153 * or -1 on error. 154 * In : r0 - console base address 155 * Clobber list : r0, r1 156 * --------------------------------------------- 157 */ 158 int console_imx_uart_core_getc(uintptr_t base_addr) 159 { 160 uint32_t val; 161 162 val = read_reg(base_addr, IMX_UART_TS_OFFSET); 163 if (val & IMX_UART_TS_RXEMPTY) 164 return -1; 165 166 val = read_reg(base_addr, IMX_UART_RXD_OFFSET); 167 return (int)(val & 0x000000FF); 168 } 169 170 /* 171 * Function to force a write of all buffered 172 * data that hasn't been output. 173 * In : r0 - console base address 174 * Out : void 175 * Clobber list : r0, r1 176 * --------------------------------------------- 177 */ 178 void console_imx_uart_core_flush(uintptr_t base_addr) 179 { 180 } 181 182