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