xref: /rk3399_rockchip-uboot/drivers/serial/mcfuart.c (revision 1a4596601fd395f3afb8f82f3f840c5e00bdd57a)
12bd806feSTsiChungLiew /*
22bd806feSTsiChungLiew  * (C) Copyright 2004-2007 Freescale Semiconductor, Inc.
32bd806feSTsiChungLiew  * TsiChung Liew, Tsi-Chung.Liew@freescale.com.
42bd806feSTsiChungLiew  *
5*1a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
62bd806feSTsiChungLiew  */
72bd806feSTsiChungLiew 
82bd806feSTsiChungLiew /*
92bd806feSTsiChungLiew  * Minimal serial functions needed to use one of the uart ports
102bd806feSTsiChungLiew  * as serial console interface.
112bd806feSTsiChungLiew  */
122bd806feSTsiChungLiew 
132bd806feSTsiChungLiew #include <common.h>
1439c7a263SAlison Wang #include <serial.h>
1539c7a263SAlison Wang #include <linux/compiler.h>
163e66c078SWolfgang Denk 
172bd806feSTsiChungLiew #include <asm/immap.h>
182bd806feSTsiChungLiew #include <asm/uart.h>
192bd806feSTsiChungLiew 
202bd806feSTsiChungLiew DECLARE_GLOBAL_DATA_PTR;
212bd806feSTsiChungLiew 
22fa9da596STsiChung Liew extern void uart_port_conf(int port);
238d1d66afSTsiChungLiew 
24abaef69fSMarek Vasut static int mcf_serial_init(void)
252bd806feSTsiChungLiew {
262bd806feSTsiChungLiew 	volatile uart_t *uart;
272bd806feSTsiChungLiew 	u32 counter;
282bd806feSTsiChungLiew 
296d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 	uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE);
302bd806feSTsiChungLiew 
31fa9da596STsiChung Liew 	uart_port_conf(CONFIG_SYS_UART_PORT);
328d1d66afSTsiChungLiew 
332bd806feSTsiChungLiew 	/* write to SICR: SIM2 = uart mode,dcd does not affect rx */
342bd806feSTsiChungLiew 	uart->ucr = UART_UCR_RESET_RX;
352bd806feSTsiChungLiew 	uart->ucr = UART_UCR_RESET_TX;
362bd806feSTsiChungLiew 	uart->ucr = UART_UCR_RESET_ERROR;
372bd806feSTsiChungLiew 	uart->ucr = UART_UCR_RESET_MR;
382bd806feSTsiChungLiew 	__asm__("nop");
392bd806feSTsiChungLiew 
402bd806feSTsiChungLiew 	uart->uimr = 0;
412bd806feSTsiChungLiew 
422bd806feSTsiChungLiew 	/* write to CSR: RX/TX baud rate from timers */
432bd806feSTsiChungLiew 	uart->ucsr = (UART_UCSR_RCS_SYS_CLK | UART_UCSR_TCS_SYS_CLK);
442bd806feSTsiChungLiew 
452bd806feSTsiChungLiew 	uart->umr = (UART_UMR_BC_8 | UART_UMR_PM_NONE);
462bd806feSTsiChungLiew 	uart->umr = UART_UMR_SB_STOP_BITS_1;
472bd806feSTsiChungLiew 
482bd806feSTsiChungLiew 	/* Setting up BaudRate */
4981cc3232STsiChung Liew 	counter = (u32) ((gd->bus_clk / 32) + (gd->baudrate / 2));
5081cc3232STsiChung Liew 	counter = counter / gd->baudrate;
512bd806feSTsiChungLiew 
522bd806feSTsiChungLiew 	/* write to CTUR: divide counter upper byte */
532bd806feSTsiChungLiew 	uart->ubg1 = (u8) ((counter & 0xff00) >> 8);
542bd806feSTsiChungLiew 	/* write to CTLR: divide counter lower byte */
552bd806feSTsiChungLiew 	uart->ubg2 = (u8) (counter & 0x00ff);
562bd806feSTsiChungLiew 
572bd806feSTsiChungLiew 	uart->ucr = (UART_UCR_RX_ENABLED | UART_UCR_TX_ENABLED);
582bd806feSTsiChungLiew 
592bd806feSTsiChungLiew 	return (0);
602bd806feSTsiChungLiew }
612bd806feSTsiChungLiew 
62abaef69fSMarek Vasut static void mcf_serial_putc(const char c)
632bd806feSTsiChungLiew {
646d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 	volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE);
652bd806feSTsiChungLiew 
662bd806feSTsiChungLiew 	if (c == '\n')
672bd806feSTsiChungLiew 		serial_putc('\r');
682bd806feSTsiChungLiew 
692bd806feSTsiChungLiew 	/* Wait for last character to go. */
702bd806feSTsiChungLiew 	while (!(uart->usr & UART_USR_TXRDY)) ;
712bd806feSTsiChungLiew 
722bd806feSTsiChungLiew 	uart->utb = c;
732bd806feSTsiChungLiew }
742bd806feSTsiChungLiew 
75abaef69fSMarek Vasut static int mcf_serial_getc(void)
762bd806feSTsiChungLiew {
776d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 	volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE);
782bd806feSTsiChungLiew 
792bd806feSTsiChungLiew 	/* Wait for a character to arrive. */
802bd806feSTsiChungLiew 	while (!(uart->usr & UART_USR_RXRDY)) ;
812bd806feSTsiChungLiew 	return uart->urb;
822bd806feSTsiChungLiew }
832bd806feSTsiChungLiew 
84abaef69fSMarek Vasut static int mcf_serial_tstc(void)
852bd806feSTsiChungLiew {
866d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 	volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE);
872bd806feSTsiChungLiew 
882bd806feSTsiChungLiew 	return (uart->usr & UART_USR_RXRDY);
892bd806feSTsiChungLiew }
902bd806feSTsiChungLiew 
91abaef69fSMarek Vasut static void mcf_serial_setbrg(void)
922bd806feSTsiChungLiew {
936d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 	volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE);
942bd806feSTsiChungLiew 	u32 counter;
952bd806feSTsiChungLiew 
9692d3e6e0SRichard Retanubun 	/* Setting up BaudRate */
9792d3e6e0SRichard Retanubun 	counter = (u32) ((gd->bus_clk / 32) + (gd->baudrate / 2));
9892d3e6e0SRichard Retanubun 	counter = counter / gd->baudrate;
992bd806feSTsiChungLiew 
1002bd806feSTsiChungLiew 	/* write to CTUR: divide counter upper byte */
1012bd806feSTsiChungLiew 	uart->ubg1 = ((counter & 0xff00) >> 8);
1022bd806feSTsiChungLiew 	/* write to CTLR: divide counter lower byte */
1032bd806feSTsiChungLiew 	uart->ubg2 = (counter & 0x00ff);
1042bd806feSTsiChungLiew 
1052bd806feSTsiChungLiew 	uart->ucr = UART_UCR_RESET_RX;
1062bd806feSTsiChungLiew 	uart->ucr = UART_UCR_RESET_TX;
1072bd806feSTsiChungLiew 
1082bd806feSTsiChungLiew 	uart->ucr = UART_UCR_RX_ENABLED | UART_UCR_TX_ENABLED;
1092bd806feSTsiChungLiew }
110abaef69fSMarek Vasut 
111abaef69fSMarek Vasut static struct serial_device mcf_serial_drv = {
112abaef69fSMarek Vasut 	.name	= "mcf_serial",
113abaef69fSMarek Vasut 	.start	= mcf_serial_init,
114abaef69fSMarek Vasut 	.stop	= NULL,
115abaef69fSMarek Vasut 	.setbrg	= mcf_serial_setbrg,
116abaef69fSMarek Vasut 	.putc	= mcf_serial_putc,
117ec3fd689SMarek Vasut 	.puts	= default_serial_puts,
118abaef69fSMarek Vasut 	.getc	= mcf_serial_getc,
119abaef69fSMarek Vasut 	.tstc	= mcf_serial_tstc,
120abaef69fSMarek Vasut };
121abaef69fSMarek Vasut 
122abaef69fSMarek Vasut void mcf_serial_initialize(void)
123abaef69fSMarek Vasut {
124abaef69fSMarek Vasut 	serial_register(&mcf_serial_drv);
125abaef69fSMarek Vasut }
126abaef69fSMarek Vasut 
127abaef69fSMarek Vasut __weak struct serial_device *default_serial_console(void)
128abaef69fSMarek Vasut {
129abaef69fSMarek Vasut 	return &mcf_serial_drv;
130abaef69fSMarek Vasut }
131