1 /* 2 * (C) Copyright 2004-2007 Freescale Semiconductor, Inc. 3 * TsiChung Liew, Tsi-Chung.Liew@freescale.com. 4 * 5 * Modified to add device model (DM) support 6 * (C) Copyright 2015 Angelo Dureghello <angelo@sysam.it> 7 * 8 * SPDX-License-Identifier: GPL-2.0+ 9 */ 10 11 /* 12 * Minimal serial functions needed to use one of the uart ports 13 * as serial console interface. 14 */ 15 16 #include <common.h> 17 #include <dm.h> 18 #include <dm/platform_data/serial_coldfire.h> 19 #include <serial.h> 20 #include <linux/compiler.h> 21 #include <asm/immap.h> 22 #include <asm/uart.h> 23 24 DECLARE_GLOBAL_DATA_PTR; 25 26 extern void uart_port_conf(int port); 27 28 static int mcf_serial_init_common(uart_t *uart, int port_idx, int baudrate) 29 { 30 u32 counter; 31 32 uart_port_conf(port_idx); 33 34 /* write to SICR: SIM2 = uart mode,dcd does not affect rx */ 35 writeb(UART_UCR_RESET_RX, &uart->ucr); 36 writeb(UART_UCR_RESET_TX, &uart->ucr); 37 writeb(UART_UCR_RESET_ERROR, &uart->ucr); 38 writeb(UART_UCR_RESET_MR, &uart->ucr); 39 __asm__("nop"); 40 41 writeb(0, &uart->uimr); 42 43 /* write to CSR: RX/TX baud rate from timers */ 44 writeb(UART_UCSR_RCS_SYS_CLK | UART_UCSR_TCS_SYS_CLK, &uart->ucsr); 45 46 writeb(UART_UMR_BC_8 | UART_UMR_PM_NONE, &uart->umr); 47 writeb(UART_UMR_SB_STOP_BITS_1, &uart->umr); 48 49 /* Setting up BaudRate */ 50 counter = (u32) ((gd->bus_clk / 32) + (baudrate / 2)); 51 counter = counter / baudrate; 52 53 /* write to CTUR: divide counter upper byte */ 54 writeb((u8)((counter & 0xff00) >> 8), &uart->ubg1); 55 /* write to CTLR: divide counter lower byte */ 56 writeb((u8)(counter & 0x00ff), &uart->ubg2); 57 58 writeb(UART_UCR_RX_ENABLED | UART_UCR_TX_ENABLED, &uart->ucr); 59 60 return (0); 61 } 62 63 static void mcf_serial_setbrg_common(uart_t *uart, int baudrate) 64 { 65 u32 counter; 66 67 /* Setting up BaudRate */ 68 counter = (u32) ((gd->bus_clk / 32) + (baudrate / 2)); 69 counter = counter / baudrate; 70 71 /* write to CTUR: divide counter upper byte */ 72 writeb(((counter & 0xff00) >> 8), &uart->ubg1); 73 /* write to CTLR: divide counter lower byte */ 74 writeb((counter & 0x00ff), &uart->ubg2); 75 76 writeb(UART_UCR_RESET_RX, &uart->ucr); 77 writeb(UART_UCR_RESET_TX, &uart->ucr); 78 79 writeb(UART_UCR_RX_ENABLED | UART_UCR_TX_ENABLED, &uart->ucr); 80 } 81 82 #ifndef CONFIG_DM_SERIAL 83 84 static int mcf_serial_init(void) 85 { 86 uart_t *uart_base; 87 int port_idx; 88 89 uart_base = (uart_t *)CONFIG_SYS_UART_BASE; 90 port_idx = CONFIG_SYS_UART_PORT; 91 92 return mcf_serial_init_common(uart_base, port_idx, gd->baudrate); 93 } 94 95 static void mcf_serial_putc(const char c) 96 { 97 uart_t *uart = (uart_t *)CONFIG_SYS_UART_BASE; 98 99 if (c == '\n') 100 serial_putc('\r'); 101 102 /* Wait for last character to go. */ 103 while (!(readb(&uart->usr) & UART_USR_TXRDY)) 104 ; 105 106 writeb(c, &uart->utb); 107 } 108 109 static int mcf_serial_getc(void) 110 { 111 uart_t *uart = (uart_t *)CONFIG_SYS_UART_BASE; 112 113 /* Wait for a character to arrive. */ 114 while (!(readb(&uart->usr) & UART_USR_RXRDY)) 115 ; 116 117 return readb(&uart->urb); 118 } 119 120 static void mcf_serial_setbrg(void) 121 { 122 uart_t *uart = (uart_t *)CONFIG_SYS_UART_BASE; 123 124 mcf_serial_setbrg_common(uart, gd->baudrate); 125 } 126 127 static int mcf_serial_tstc(void) 128 { 129 uart_t *uart = (uart_t *)CONFIG_SYS_UART_BASE; 130 131 return readb(&uart->usr) & UART_USR_RXRDY; 132 } 133 134 static struct serial_device mcf_serial_drv = { 135 .name = "mcf_serial", 136 .start = mcf_serial_init, 137 .stop = NULL, 138 .setbrg = mcf_serial_setbrg, 139 .putc = mcf_serial_putc, 140 .puts = default_serial_puts, 141 .getc = mcf_serial_getc, 142 .tstc = mcf_serial_tstc, 143 }; 144 145 void mcf_serial_initialize(void) 146 { 147 serial_register(&mcf_serial_drv); 148 } 149 150 __weak struct serial_device *default_serial_console(void) 151 { 152 return &mcf_serial_drv; 153 } 154 155 #endif 156 157 #ifdef CONFIG_DM_SERIAL 158 159 static int coldfire_serial_probe(struct udevice *dev) 160 { 161 struct coldfire_serial_platdata *plat = dev->platdata; 162 163 return mcf_serial_init_common((uart_t *)plat->base, 164 plat->port, plat->baudrate); 165 } 166 167 static int coldfire_serial_putc(struct udevice *dev, const char ch) 168 { 169 struct coldfire_serial_platdata *plat = dev->platdata; 170 uart_t *uart = (uart_t *)plat->base; 171 172 /* Wait for last character to go. */ 173 if (!(readb(&uart->usr) & UART_USR_TXRDY)) 174 return -EAGAIN; 175 176 writeb(ch, &uart->utb); 177 178 return 0; 179 } 180 181 static int coldfire_serial_getc(struct udevice *dev) 182 { 183 struct coldfire_serial_platdata *plat = dev->platdata; 184 uart_t *uart = (uart_t *)(plat->base); 185 186 /* Wait for a character to arrive. */ 187 if (!(readb(&uart->usr) & UART_USR_RXRDY)) 188 return -EAGAIN; 189 190 return readb(&uart->urb); 191 } 192 193 int coldfire_serial_setbrg(struct udevice *dev, int baudrate) 194 { 195 struct coldfire_serial_platdata *plat = dev->platdata; 196 uart_t *uart = (uart_t *)(plat->base); 197 198 mcf_serial_setbrg_common(uart, baudrate); 199 200 return 0; 201 } 202 203 static int coldfire_serial_pending(struct udevice *dev, bool input) 204 { 205 struct coldfire_serial_platdata *plat = dev->platdata; 206 uart_t *uart = (uart_t *)(plat->base); 207 208 if (input) 209 return readb(&uart->usr) & UART_USR_RXRDY ? 1 : 0; 210 else 211 return readb(&uart->usr) & UART_USR_TXRDY ? 0 : 1; 212 213 return 0; 214 } 215 216 static const struct dm_serial_ops coldfire_serial_ops = { 217 .putc = coldfire_serial_putc, 218 .pending = coldfire_serial_pending, 219 .getc = coldfire_serial_getc, 220 .setbrg = coldfire_serial_setbrg, 221 }; 222 223 U_BOOT_DRIVER(serial_coldfire) = { 224 .name = "serial_coldfire", 225 .id = UCLASS_SERIAL, 226 .probe = coldfire_serial_probe, 227 .ops = &coldfire_serial_ops, 228 .flags = DM_FLAG_PRE_RELOC, 229 }; 230 #endif 231