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