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 writel(c, &hsuart->tx); 42 43 /* Wait for character to be sent */ 44 while (readl(&hsuart->level) & HSUART_LEVEL_TX) 45 /* NOP */; 46 } 47 48 static int lpc32xx_serial_tstc(void) 49 { 50 if (readl(&hsuart->level) & HSUART_LEVEL_RX) 51 return 1; 52 53 return 0; 54 } 55 56 static int lpc32xx_serial_init(void) 57 { 58 lpc32xx_serial_setbrg(); 59 60 /* Disable hardware RTS and CTS flow control, set up RX and TX FIFO */ 61 writel(HSUART_CTRL_TMO_16 | HSUART_CTRL_HSU_OFFSET(20) | 62 HSUART_CTRL_HSU_RX_TRIG_32 | HSUART_CTRL_HSU_TX_TRIG_0, 63 &hsuart->ctrl); 64 return 0; 65 } 66 67 static struct serial_device lpc32xx_serial_drv = { 68 .name = "lpc32xx_serial", 69 .start = lpc32xx_serial_init, 70 .stop = NULL, 71 .setbrg = lpc32xx_serial_setbrg, 72 .putc = lpc32xx_serial_putc, 73 .puts = default_serial_puts, 74 .getc = lpc32xx_serial_getc, 75 .tstc = lpc32xx_serial_tstc, 76 }; 77 78 void lpc32xx_serial_initialize(void) 79 { 80 serial_register(&lpc32xx_serial_drv); 81 } 82 83 __weak struct serial_device *default_serial_console(void) 84 { 85 return &lpc32xx_serial_drv; 86 } 87