1 /* 2 * Copyright (C) 2011 Vladimir Zapolskiy <vz@mleia.com> 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <asm/arch/cpu.h> 9 #include <asm/arch/clk.h> 10 #include <asm/arch/uart.h> 11 #include <asm/io.h> 12 #include <serial.h> 13 #include <linux/compiler.h> 14 15 DECLARE_GLOBAL_DATA_PTR; 16 17 static struct hsuart_regs *hsuart = (struct hsuart_regs *)HS_UART_BASE; 18 19 static void lpc32xx_serial_setbrg(void) 20 { 21 u32 div; 22 23 /* UART rate = PERIPH_CLK / ((HSU_RATE + 1) x 14) */ 24 div = (get_serial_clock() / 14 + gd->baudrate / 2) / gd->baudrate - 1; 25 if (div > 255) 26 div = 255; 27 28 writel(div, &hsuart->rate); 29 } 30 31 static int lpc32xx_serial_getc(void) 32 { 33 while (!(readl(&hsuart->level) & HSUART_LEVEL_RX)) 34 /* NOP */; 35 36 return readl(&hsuart->rx) & HSUART_RX_DATA; 37 } 38 39 static void lpc32xx_serial_putc(const char c) 40 { 41 if (c == '\n') 42 serial_putc('\r'); 43 44 writel(c, &hsuart->tx); 45 46 /* Wait for character to be sent */ 47 while (readl(&hsuart->level) & HSUART_LEVEL_TX) 48 /* NOP */; 49 } 50 51 static int lpc32xx_serial_tstc(void) 52 { 53 if (readl(&hsuart->level) & HSUART_LEVEL_RX) 54 return 1; 55 56 return 0; 57 } 58 59 static int lpc32xx_serial_init(void) 60 { 61 lpc32xx_serial_setbrg(); 62 63 /* Disable hardware RTS and CTS flow control, set up RX and TX FIFO */ 64 writel(HSUART_CTRL_TMO_16 | HSUART_CTRL_HSU_OFFSET(20) | 65 HSUART_CTRL_HSU_RX_TRIG_32 | HSUART_CTRL_HSU_TX_TRIG_0, 66 &hsuart->ctrl); 67 return 0; 68 } 69 70 static struct serial_device lpc32xx_serial_drv = { 71 .name = "lpc32xx_serial", 72 .start = lpc32xx_serial_init, 73 .stop = NULL, 74 .setbrg = lpc32xx_serial_setbrg, 75 .putc = lpc32xx_serial_putc, 76 .puts = default_serial_puts, 77 .getc = lpc32xx_serial_getc, 78 .tstc = lpc32xx_serial_tstc, 79 }; 80 81 void lpc32xx_serial_initialize(void) 82 { 83 serial_register(&lpc32xx_serial_drv); 84 } 85 86 __weak struct serial_device *default_serial_console(void) 87 { 88 return &lpc32xx_serial_drv; 89 } 90