xref: /rk3399_rockchip-uboot/drivers/serial/atmel_usart.c (revision cfba4573f6cc2a888ae7ceab6bba3c3dab04f3dd)
11378df79SJean-Christophe PLAGNIOL-VILLARD /*
21378df79SJean-Christophe PLAGNIOL-VILLARD  * Copyright (C) 2004-2006 Atmel Corporation
31378df79SJean-Christophe PLAGNIOL-VILLARD  *
4125637c5SAndreas Bießmann  * Modified to support C structur SoC access by
5125637c5SAndreas Bießmann  * Andreas Bießmann <biessmann@corscience.de>
6125637c5SAndreas Bießmann  *
71378df79SJean-Christophe PLAGNIOL-VILLARD  * This program is free software; you can redistribute it and/or modify
81378df79SJean-Christophe PLAGNIOL-VILLARD  * it under the terms of the GNU General Public License as published by
91378df79SJean-Christophe PLAGNIOL-VILLARD  * the Free Software Foundation; either version 2 of the License, or
101378df79SJean-Christophe PLAGNIOL-VILLARD  * (at your option) any later version.
111378df79SJean-Christophe PLAGNIOL-VILLARD  *
121378df79SJean-Christophe PLAGNIOL-VILLARD  * This program is distributed in the hope that it will be useful,
131378df79SJean-Christophe PLAGNIOL-VILLARD  * but WITHOUT ANY WARRANTY; without even the implied warranty of
141378df79SJean-Christophe PLAGNIOL-VILLARD  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
151378df79SJean-Christophe PLAGNIOL-VILLARD  * GNU General Public License for more details.
161378df79SJean-Christophe PLAGNIOL-VILLARD  *
171378df79SJean-Christophe PLAGNIOL-VILLARD  * You should have received a copy of the GNU General Public License
181378df79SJean-Christophe PLAGNIOL-VILLARD  * along with this program; if not, write to the Free Software
191378df79SJean-Christophe PLAGNIOL-VILLARD  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
201378df79SJean-Christophe PLAGNIOL-VILLARD  */
211378df79SJean-Christophe PLAGNIOL-VILLARD #include <common.h>
22843a2654SJean-Christophe PLAGNIOL-VILLARD #include <watchdog.h>
23*cfba4573SMarek Vasut #include <serial.h>
24*cfba4573SMarek Vasut #include <linux/compiler.h>
251378df79SJean-Christophe PLAGNIOL-VILLARD 
261378df79SJean-Christophe PLAGNIOL-VILLARD #include <asm/io.h>
271378df79SJean-Christophe PLAGNIOL-VILLARD #include <asm/arch/clk.h>
28329f0f52SReinhard Meyer #include <asm/arch/hardware.h>
291378df79SJean-Christophe PLAGNIOL-VILLARD 
301378df79SJean-Christophe PLAGNIOL-VILLARD #include "atmel_usart.h"
311378df79SJean-Christophe PLAGNIOL-VILLARD 
321378df79SJean-Christophe PLAGNIOL-VILLARD DECLARE_GLOBAL_DATA_PTR;
331378df79SJean-Christophe PLAGNIOL-VILLARD 
34*cfba4573SMarek Vasut static void atmel_serial_setbrg(void)
351378df79SJean-Christophe PLAGNIOL-VILLARD {
36329f0f52SReinhard Meyer 	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
371378df79SJean-Christophe PLAGNIOL-VILLARD 	unsigned long divisor;
381378df79SJean-Christophe PLAGNIOL-VILLARD 	unsigned long usart_hz;
391378df79SJean-Christophe PLAGNIOL-VILLARD 
401378df79SJean-Christophe PLAGNIOL-VILLARD 	/*
411378df79SJean-Christophe PLAGNIOL-VILLARD 	 *              Master Clock
421378df79SJean-Christophe PLAGNIOL-VILLARD 	 * Baud Rate = --------------
431378df79SJean-Christophe PLAGNIOL-VILLARD 	 *                16 * CD
441378df79SJean-Christophe PLAGNIOL-VILLARD 	 */
45329f0f52SReinhard Meyer 	usart_hz = get_usart_clk_rate(CONFIG_USART_ID);
461378df79SJean-Christophe PLAGNIOL-VILLARD 	divisor = (usart_hz / 16 + gd->baudrate / 2) / gd->baudrate;
47125637c5SAndreas Bießmann 	writel(USART3_BF(CD, divisor), &usart->brgr);
481378df79SJean-Christophe PLAGNIOL-VILLARD }
491378df79SJean-Christophe PLAGNIOL-VILLARD 
50*cfba4573SMarek Vasut static int atmel_serial_init(void)
511378df79SJean-Christophe PLAGNIOL-VILLARD {
52329f0f52SReinhard Meyer 	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
53125637c5SAndreas Bießmann 
541f4faeddSXu, Hong 	/*
551f4faeddSXu, Hong 	 * Just in case: drain transmitter register
561f4faeddSXu, Hong 	 * 1000us is enough for baudrate >= 9600
571f4faeddSXu, Hong 	 */
581f4faeddSXu, Hong 	if (!(readl(&usart->csr) & USART3_BIT(TXEMPTY)))
591f4faeddSXu, Hong 		__udelay(1000);
601f4faeddSXu, Hong 
61125637c5SAndreas Bießmann 	writel(USART3_BIT(RSTRX) | USART3_BIT(RSTTX), &usart->cr);
621378df79SJean-Christophe PLAGNIOL-VILLARD 
631378df79SJean-Christophe PLAGNIOL-VILLARD 	serial_setbrg();
641378df79SJean-Christophe PLAGNIOL-VILLARD 
65125637c5SAndreas Bießmann 	writel((USART3_BF(USART_MODE, USART3_USART_MODE_NORMAL)
661378df79SJean-Christophe PLAGNIOL-VILLARD 			   | USART3_BF(USCLKS, USART3_USCLKS_MCK)
671378df79SJean-Christophe PLAGNIOL-VILLARD 			   | USART3_BF(CHRL, USART3_CHRL_8)
681378df79SJean-Christophe PLAGNIOL-VILLARD 			   | USART3_BF(PAR, USART3_PAR_NONE)
69125637c5SAndreas Bießmann 			   | USART3_BF(NBSTOP, USART3_NBSTOP_1)),
70125637c5SAndreas Bießmann 			   &usart->mr);
711f4faeddSXu, Hong 	writel(USART3_BIT(RXEN) | USART3_BIT(TXEN), &usart->cr);
721f4faeddSXu, Hong 	/* 100us is enough for the new settings to be settled */
731f4faeddSXu, Hong 	__udelay(100);
741378df79SJean-Christophe PLAGNIOL-VILLARD 
751378df79SJean-Christophe PLAGNIOL-VILLARD 	return 0;
761378df79SJean-Christophe PLAGNIOL-VILLARD }
771378df79SJean-Christophe PLAGNIOL-VILLARD 
78*cfba4573SMarek Vasut static void atmel_serial_putc(char c)
791378df79SJean-Christophe PLAGNIOL-VILLARD {
80329f0f52SReinhard Meyer 	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
81125637c5SAndreas Bießmann 
821378df79SJean-Christophe PLAGNIOL-VILLARD 	if (c == '\n')
831378df79SJean-Christophe PLAGNIOL-VILLARD 		serial_putc('\r');
841378df79SJean-Christophe PLAGNIOL-VILLARD 
85125637c5SAndreas Bießmann 	while (!(readl(&usart->csr) & USART3_BIT(TXRDY)));
86125637c5SAndreas Bießmann 	writel(c, &usart->thr);
871378df79SJean-Christophe PLAGNIOL-VILLARD }
881378df79SJean-Christophe PLAGNIOL-VILLARD 
89*cfba4573SMarek Vasut static void atmel_serial_puts(const char *s)
901378df79SJean-Christophe PLAGNIOL-VILLARD {
911378df79SJean-Christophe PLAGNIOL-VILLARD 	while (*s)
921378df79SJean-Christophe PLAGNIOL-VILLARD 		serial_putc(*s++);
931378df79SJean-Christophe PLAGNIOL-VILLARD }
941378df79SJean-Christophe PLAGNIOL-VILLARD 
95*cfba4573SMarek Vasut static int atmel_serial_getc(void)
961378df79SJean-Christophe PLAGNIOL-VILLARD {
97329f0f52SReinhard Meyer 	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
98125637c5SAndreas Bießmann 
99125637c5SAndreas Bießmann 	while (!(readl(&usart->csr) & USART3_BIT(RXRDY)))
100843a2654SJean-Christophe PLAGNIOL-VILLARD 		 WATCHDOG_RESET();
101125637c5SAndreas Bießmann 	return readl(&usart->rhr);
1021378df79SJean-Christophe PLAGNIOL-VILLARD }
1031378df79SJean-Christophe PLAGNIOL-VILLARD 
104*cfba4573SMarek Vasut static int atmel_serial_tstc(void)
1051378df79SJean-Christophe PLAGNIOL-VILLARD {
106329f0f52SReinhard Meyer 	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
107125637c5SAndreas Bießmann 	return (readl(&usart->csr) & USART3_BIT(RXRDY)) != 0;
1081378df79SJean-Christophe PLAGNIOL-VILLARD }
109*cfba4573SMarek Vasut 
110*cfba4573SMarek Vasut #ifdef CONFIG_SERIAL_MULTI
111*cfba4573SMarek Vasut static struct serial_device atmel_serial_drv = {
112*cfba4573SMarek Vasut 	.name	= "atmel_serial",
113*cfba4573SMarek Vasut 	.start	= atmel_serial_init,
114*cfba4573SMarek Vasut 	.stop	= NULL,
115*cfba4573SMarek Vasut 	.setbrg	= atmel_serial_setbrg,
116*cfba4573SMarek Vasut 	.putc	= atmel_serial_putc,
117*cfba4573SMarek Vasut 	.puts	= atmel_serial_puts,
118*cfba4573SMarek Vasut 	.getc	= atmel_serial_getc,
119*cfba4573SMarek Vasut 	.tstc	= atmel_serial_tstc,
120*cfba4573SMarek Vasut };
121*cfba4573SMarek Vasut 
122*cfba4573SMarek Vasut void atmel_serial_initialize(void)
123*cfba4573SMarek Vasut {
124*cfba4573SMarek Vasut 	serial_register(&atmel_serial_drv);
125*cfba4573SMarek Vasut }
126*cfba4573SMarek Vasut 
127*cfba4573SMarek Vasut __weak struct serial_device *default_serial_console(void)
128*cfba4573SMarek Vasut {
129*cfba4573SMarek Vasut 	return &atmel_serial_drv;
130*cfba4573SMarek Vasut }
131*cfba4573SMarek Vasut #else
132*cfba4573SMarek Vasut int serial_init(void)
133*cfba4573SMarek Vasut {
134*cfba4573SMarek Vasut 	return atmel_serial_init();
135*cfba4573SMarek Vasut }
136*cfba4573SMarek Vasut 
137*cfba4573SMarek Vasut void serial_setbrg(void)
138*cfba4573SMarek Vasut {
139*cfba4573SMarek Vasut 	atmel_serial_setbrg();
140*cfba4573SMarek Vasut }
141*cfba4573SMarek Vasut 
142*cfba4573SMarek Vasut void serial_putc(const char c)
143*cfba4573SMarek Vasut {
144*cfba4573SMarek Vasut 	atmel_serial_putc(c);
145*cfba4573SMarek Vasut }
146*cfba4573SMarek Vasut 
147*cfba4573SMarek Vasut void serial_puts(const char *s)
148*cfba4573SMarek Vasut {
149*cfba4573SMarek Vasut 	atmel_serial_puts(s);
150*cfba4573SMarek Vasut }
151*cfba4573SMarek Vasut 
152*cfba4573SMarek Vasut int serial_getc(void)
153*cfba4573SMarek Vasut {
154*cfba4573SMarek Vasut 	return atmel_serial_getc();
155*cfba4573SMarek Vasut }
156*cfba4573SMarek Vasut 
157*cfba4573SMarek Vasut int serial_tstc(void)
158*cfba4573SMarek Vasut {
159*cfba4573SMarek Vasut 	return atmel_serial_tstc();
160*cfba4573SMarek Vasut }
161*cfba4573SMarek Vasut #endif
162