1 /* 2 * Copyright 2013 Freescale Semiconductor, Inc. 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <watchdog.h> 9 #include <asm/io.h> 10 #include <serial.h> 11 #include <linux/compiler.h> 12 #include <asm/arch/imx-regs.h> 13 #include <asm/arch/clock.h> 14 15 #define US1_TDRE (1 << 7) 16 #define US1_RDRF (1 << 5) 17 #define US1_OR (1 << 3) 18 #define UC2_TE (1 << 3) 19 #define UC2_RE (1 << 2) 20 21 DECLARE_GLOBAL_DATA_PTR; 22 23 struct lpuart_fsl *base = (struct lpuart_fsl *)LPUART_BASE; 24 25 static void lpuart_serial_setbrg(void) 26 { 27 u32 clk = mxc_get_clock(MXC_UART_CLK); 28 u16 sbr; 29 30 if (!gd->baudrate) 31 gd->baudrate = CONFIG_BAUDRATE; 32 33 sbr = (u16)(clk / (16 * gd->baudrate)); 34 /* place adjustment later - n/32 BRFA */ 35 36 __raw_writeb(sbr >> 8, &base->ubdh); 37 __raw_writeb(sbr & 0xff, &base->ubdl); 38 } 39 40 static int lpuart_serial_getc(void) 41 { 42 while (!(__raw_readb(&base->us1) & (US1_RDRF | US1_OR))) 43 WATCHDOG_RESET(); 44 45 barrier(); 46 47 return __raw_readb(&base->ud); 48 } 49 50 static void lpuart_serial_putc(const char c) 51 { 52 if (c == '\n') 53 serial_putc('\r'); 54 55 while (!(__raw_readb(&base->us1) & US1_TDRE)) 56 WATCHDOG_RESET(); 57 58 __raw_writeb(c, &base->ud); 59 } 60 61 /* 62 * Test whether a character is in the RX buffer 63 */ 64 static int lpuart_serial_tstc(void) 65 { 66 if (__raw_readb(&base->urcfifo) == 0) 67 return 0; 68 69 return 1; 70 } 71 72 /* 73 * Initialise the serial port with the given baudrate. The settings 74 * are always 8 data bits, no parity, 1 stop bit, no start bits. 75 */ 76 static int lpuart_serial_init(void) 77 { 78 u8 ctrl; 79 80 ctrl = __raw_readb(&base->uc2); 81 ctrl &= ~UC2_RE; 82 ctrl &= ~UC2_TE; 83 __raw_writeb(ctrl, &base->uc2); 84 85 __raw_writeb(0, &base->umodem); 86 __raw_writeb(0, &base->uc1); 87 88 /* provide data bits, parity, stop bit, etc */ 89 90 serial_setbrg(); 91 92 __raw_writeb(UC2_RE | UC2_TE, &base->uc2); 93 94 return 0; 95 } 96 97 static struct serial_device lpuart_serial_drv = { 98 .name = "lpuart_serial", 99 .start = lpuart_serial_init, 100 .stop = NULL, 101 .setbrg = lpuart_serial_setbrg, 102 .putc = lpuart_serial_putc, 103 .puts = default_serial_puts, 104 .getc = lpuart_serial_getc, 105 .tstc = lpuart_serial_tstc, 106 }; 107 108 void lpuart_serial_initialize(void) 109 { 110 serial_register(&lpuart_serial_drv); 111 } 112 113 __weak struct serial_device *default_serial_console(void) 114 { 115 return &lpuart_serial_drv; 116 } 117