2 * Copyright (C) 2004-2006 Atmel Corporation
4 * Modified to support C structur SoC access by
5 * Andreas Bießmann <biessmann@corscience.de>
7 * SPDX-License-Identifier: GPL-2.0+
14 #include <linux/compiler.h>
17 #ifdef CONFIG_DM_SERIAL
18 #include <asm/arch/atmel_serial.h>
20 #include <asm/arch/clk.h>
21 #include <asm/arch/hardware.h>
23 #include "atmel_usart.h"
25 DECLARE_GLOBAL_DATA_PTR
;
27 static void atmel_serial_setbrg_internal(atmel_usart3_t
*usart
, int id
,
30 unsigned long divisor
;
31 unsigned long usart_hz
;
35 * Baud Rate = --------------
38 usart_hz
= get_usart_clk_rate(id
);
39 divisor
= (usart_hz
/ 16 + baudrate
/ 2) / baudrate
;
40 writel(USART3_BF(CD
, divisor
), &usart
->brgr
);
43 static void atmel_serial_init_internal(atmel_usart3_t
*usart
)
46 * Just in case: drain transmitter register
47 * 1000us is enough for baudrate >= 9600
49 if (!(readl(&usart
->csr
) & USART3_BIT(TXEMPTY
)))
52 writel(USART3_BIT(RSTRX
) | USART3_BIT(RSTTX
), &usart
->cr
);
55 static void atmel_serial_activate(atmel_usart3_t
*usart
)
57 writel((USART3_BF(USART_MODE
, USART3_USART_MODE_NORMAL
)
58 | USART3_BF(USCLKS
, USART3_USCLKS_MCK
)
59 | USART3_BF(CHRL
, USART3_CHRL_8
)
60 | USART3_BF(PAR
, USART3_PAR_NONE
)
61 | USART3_BF(NBSTOP
, USART3_NBSTOP_1
)),
63 writel(USART3_BIT(RXEN
) | USART3_BIT(TXEN
), &usart
->cr
);
64 /* 100us is enough for the new settings to be settled */
68 #ifndef CONFIG_DM_SERIAL
69 static void atmel_serial_setbrg(void)
71 atmel_serial_setbrg_internal((atmel_usart3_t
*)CONFIG_USART_BASE
,
72 CONFIG_USART_ID
, gd
->baudrate
);
75 static int atmel_serial_init(void)
77 atmel_usart3_t
*usart
= (atmel_usart3_t
*)CONFIG_USART_BASE
;
79 atmel_serial_init_internal(usart
);
81 atmel_serial_activate(usart
);
86 static void atmel_serial_putc(char c
)
88 atmel_usart3_t
*usart
= (atmel_usart3_t
*)CONFIG_USART_BASE
;
93 while (!(readl(&usart
->csr
) & USART3_BIT(TXRDY
)));
94 writel(c
, &usart
->thr
);
97 static int atmel_serial_getc(void)
99 atmel_usart3_t
*usart
= (atmel_usart3_t
*)CONFIG_USART_BASE
;
101 while (!(readl(&usart
->csr
) & USART3_BIT(RXRDY
)))
103 return readl(&usart
->rhr
);
106 static int atmel_serial_tstc(void)
108 atmel_usart3_t
*usart
= (atmel_usart3_t
*)CONFIG_USART_BASE
;
109 return (readl(&usart
->csr
) & USART3_BIT(RXRDY
)) != 0;
112 static struct serial_device atmel_serial_drv
= {
113 .name
= "atmel_serial",
114 .start
= atmel_serial_init
,
116 .setbrg
= atmel_serial_setbrg
,
117 .putc
= atmel_serial_putc
,
118 .puts
= default_serial_puts
,
119 .getc
= atmel_serial_getc
,
120 .tstc
= atmel_serial_tstc
,
123 void atmel_serial_initialize(void)
125 serial_register(&atmel_serial_drv
);
128 __weak
struct serial_device
*default_serial_console(void)
130 return &atmel_serial_drv
;
134 #ifdef CONFIG_DM_SERIAL
136 struct atmel_serial_priv
{
137 atmel_usart3_t
*usart
;
140 int atmel_serial_setbrg(struct udevice
*dev
, int baudrate
)
142 struct atmel_serial_priv
*priv
= dev_get_priv(dev
);
144 atmel_serial_setbrg_internal(priv
->usart
, 0 /* ignored */, baudrate
);
145 atmel_serial_activate(priv
->usart
);
150 static int atmel_serial_getc(struct udevice
*dev
)
152 struct atmel_serial_priv
*priv
= dev_get_priv(dev
);
154 if (!(readl(&priv
->usart
->csr
) & USART3_BIT(RXRDY
)))
157 return readl(&priv
->usart
->rhr
);
160 static int atmel_serial_putc(struct udevice
*dev
, const char ch
)
162 struct atmel_serial_priv
*priv
= dev_get_priv(dev
);
164 if (!(readl(&priv
->usart
->csr
) & USART3_BIT(TXRDY
)))
167 writel(ch
, &priv
->usart
->thr
);
172 static int atmel_serial_pending(struct udevice
*dev
, bool input
)
174 struct atmel_serial_priv
*priv
= dev_get_priv(dev
);
175 uint32_t csr
= readl(&priv
->usart
->csr
);
178 return csr
& USART3_BIT(RXRDY
) ? 1 : 0;
180 return csr
& USART3_BIT(TXEMPTY
) ? 0 : 1;
183 static const struct dm_serial_ops atmel_serial_ops
= {
184 .putc
= atmel_serial_putc
,
185 .pending
= atmel_serial_pending
,
186 .getc
= atmel_serial_getc
,
187 .setbrg
= atmel_serial_setbrg
,
190 static int atmel_serial_probe(struct udevice
*dev
)
192 struct atmel_serial_platdata
*plat
= dev
->platdata
;
193 struct atmel_serial_priv
*priv
= dev_get_priv(dev
);
195 priv
->usart
= (atmel_usart3_t
*)plat
->base_addr
;
196 atmel_serial_init_internal(priv
->usart
);
201 U_BOOT_DRIVER(serial_atmel
) = {
202 .name
= "serial_atmel",
204 .probe
= atmel_serial_probe
,
205 .ops
= &atmel_serial_ops
,
206 .flags
= DM_FLAG_PRE_RELOC
,
207 .priv_auto_alloc_size
= sizeof(struct atmel_serial_priv
),