1427eba70SAlison Wang /* 2427eba70SAlison Wang * Copyright 2013 Freescale Semiconductor, Inc. 3427eba70SAlison Wang * 41a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 5427eba70SAlison Wang */ 6427eba70SAlison Wang 7427eba70SAlison Wang #include <common.h> 8427eba70SAlison Wang #include <watchdog.h> 9427eba70SAlison Wang #include <asm/io.h> 10427eba70SAlison Wang #include <serial.h> 11427eba70SAlison Wang #include <linux/compiler.h> 12427eba70SAlison Wang #include <asm/arch/imx-regs.h> 13427eba70SAlison Wang #include <asm/arch/clock.h> 14427eba70SAlison Wang 15427eba70SAlison Wang #define US1_TDRE (1 << 7) 16427eba70SAlison Wang #define US1_RDRF (1 << 5) 17*a3db78d8SStefan Agner #define US1_OR (1 << 3) 18427eba70SAlison Wang #define UC2_TE (1 << 3) 19427eba70SAlison Wang #define UC2_RE (1 << 2) 20427eba70SAlison Wang 21427eba70SAlison Wang DECLARE_GLOBAL_DATA_PTR; 22427eba70SAlison Wang 23427eba70SAlison Wang struct lpuart_fsl *base = (struct lpuart_fsl *)LPUART_BASE; 24427eba70SAlison Wang 25427eba70SAlison Wang static void lpuart_serial_setbrg(void) 26427eba70SAlison Wang { 27427eba70SAlison Wang u32 clk = mxc_get_clock(MXC_UART_CLK); 28427eba70SAlison Wang u16 sbr; 29427eba70SAlison Wang 30427eba70SAlison Wang if (!gd->baudrate) 31427eba70SAlison Wang gd->baudrate = CONFIG_BAUDRATE; 32427eba70SAlison Wang 33427eba70SAlison Wang sbr = (u16)(clk / (16 * gd->baudrate)); 34427eba70SAlison Wang /* place adjustment later - n/32 BRFA */ 35427eba70SAlison Wang 36427eba70SAlison Wang __raw_writeb(sbr >> 8, &base->ubdh); 37427eba70SAlison Wang __raw_writeb(sbr & 0xff, &base->ubdl); 38427eba70SAlison Wang } 39427eba70SAlison Wang 40427eba70SAlison Wang static int lpuart_serial_getc(void) 41427eba70SAlison Wang { 42*a3db78d8SStefan Agner while (!(__raw_readb(&base->us1) & (US1_RDRF | US1_OR))) 43427eba70SAlison Wang WATCHDOG_RESET(); 44427eba70SAlison Wang 45*a3db78d8SStefan Agner barrier(); 46427eba70SAlison Wang 47427eba70SAlison Wang return __raw_readb(&base->ud); 48427eba70SAlison Wang } 49427eba70SAlison Wang 50427eba70SAlison Wang static void lpuart_serial_putc(const char c) 51427eba70SAlison Wang { 52427eba70SAlison Wang if (c == '\n') 53427eba70SAlison Wang serial_putc('\r'); 54427eba70SAlison Wang 55427eba70SAlison Wang while (!(__raw_readb(&base->us1) & US1_TDRE)) 56427eba70SAlison Wang WATCHDOG_RESET(); 57427eba70SAlison Wang 58427eba70SAlison Wang __raw_writeb(c, &base->ud); 59427eba70SAlison Wang } 60427eba70SAlison Wang 61427eba70SAlison Wang /* 62427eba70SAlison Wang * Test whether a character is in the RX buffer 63427eba70SAlison Wang */ 64427eba70SAlison Wang static int lpuart_serial_tstc(void) 65427eba70SAlison Wang { 66427eba70SAlison Wang if (__raw_readb(&base->urcfifo) == 0) 67427eba70SAlison Wang return 0; 68427eba70SAlison Wang 69427eba70SAlison Wang return 1; 70427eba70SAlison Wang } 71427eba70SAlison Wang 72427eba70SAlison Wang /* 73427eba70SAlison Wang * Initialise the serial port with the given baudrate. The settings 74427eba70SAlison Wang * are always 8 data bits, no parity, 1 stop bit, no start bits. 75427eba70SAlison Wang */ 76427eba70SAlison Wang static int lpuart_serial_init(void) 77427eba70SAlison Wang { 78427eba70SAlison Wang u8 ctrl; 79427eba70SAlison Wang 80427eba70SAlison Wang ctrl = __raw_readb(&base->uc2); 81427eba70SAlison Wang ctrl &= ~UC2_RE; 82427eba70SAlison Wang ctrl &= ~UC2_TE; 83427eba70SAlison Wang __raw_writeb(ctrl, &base->uc2); 84427eba70SAlison Wang 85427eba70SAlison Wang __raw_writeb(0, &base->umodem); 86427eba70SAlison Wang __raw_writeb(0, &base->uc1); 87427eba70SAlison Wang 88427eba70SAlison Wang /* provide data bits, parity, stop bit, etc */ 89427eba70SAlison Wang 90427eba70SAlison Wang serial_setbrg(); 91427eba70SAlison Wang 92427eba70SAlison Wang __raw_writeb(UC2_RE | UC2_TE, &base->uc2); 93427eba70SAlison Wang 94427eba70SAlison Wang return 0; 95427eba70SAlison Wang } 96427eba70SAlison Wang 97427eba70SAlison Wang static struct serial_device lpuart_serial_drv = { 98427eba70SAlison Wang .name = "lpuart_serial", 99427eba70SAlison Wang .start = lpuart_serial_init, 100427eba70SAlison Wang .stop = NULL, 101427eba70SAlison Wang .setbrg = lpuart_serial_setbrg, 102427eba70SAlison Wang .putc = lpuart_serial_putc, 103427eba70SAlison Wang .puts = default_serial_puts, 104427eba70SAlison Wang .getc = lpuart_serial_getc, 105427eba70SAlison Wang .tstc = lpuart_serial_tstc, 106427eba70SAlison Wang }; 107427eba70SAlison Wang 108427eba70SAlison Wang void lpuart_serial_initialize(void) 109427eba70SAlison Wang { 110427eba70SAlison Wang serial_register(&lpuart_serial_drv); 111427eba70SAlison Wang } 112427eba70SAlison Wang 113427eba70SAlison Wang __weak struct serial_device *default_serial_console(void) 114427eba70SAlison Wang { 115427eba70SAlison Wang return &lpuart_serial_drv; 116427eba70SAlison Wang } 117