stm32f2_usart.c 7.71 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
 * (C) Copyright 2011
 *
 * Yuri Tikhonov, Emcraft Systems, yur@emcraft.com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

/*
23
24
25
 * STM32 F2 USART driver; configured with the following options:
 * - CONFIG_STM32F2_USART_CONSOLE
 * - CONFIG_STM32F2_USART_PORT       (1..6)
26
27
28
29
 * - CONFIG_STM32F2_USART_TX_IO_PORT (0..8 <-> A..I)
 * - CONFIG_STM32F2_USART_RX_IO_PORT (0..8 <-> A..I)
 * - CONFIG_STM32F2_USART_TX_IO_PIN  (0..15)
 * - CONFIG_STM32F2_USART_RX_IO_PIN  (0..15)
30
31
32
33
 */

#include <common.h>

34
#include <asm/arch/stm32f2.h>
35
#include <asm/arch/stm32f2_gpio.h>
36
37
38
39
40
41
42
43
44
45
46

/*
 * Set up configuration
 */
#if (CONFIG_STM32F2_USART_PORT >= 1) && \
    (CONFIG_STM32F2_USART_PORT <= 6)
# define USART_PORT		(CONFIG_STM32F2_USART_PORT - 1)
#else
# error "Bad CONFIG_STM32F2_USART_PORT value."
#endif

47
48
49
#if (CONFIG_STM32F2_USART_TX_IO_PORT >= 0) && \
    (CONFIG_STM32F2_USART_TX_IO_PORT <= 8)
# define USART_TX_IO_PORT	(CONFIG_STM32F2_USART_TX_IO_PORT)
50
51
52
53
#else
# error "Bad CONFIG_STM32F2_USART_TX_IO_PORT value."
#endif

54
55
56
#if (CONFIG_STM32F2_USART_RX_IO_PORT >= 0) && \
    (CONFIG_STM32F2_USART_RX_IO_PORT <= 8)
# define USART_RX_IO_PORT	(CONFIG_STM32F2_USART_RX_IO_PORT)
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#else
# error "Bad CONFIG_STM32F2_USART_RX_IO_PORT value."
#endif

#if (CONFIG_STM32F2_USART_TX_IO_PIN >= 0) && \
    (CONFIG_STM32F2_USART_TX_IO_PIN <= 15)
# define USART_TX_IO_PIN	(CONFIG_STM32F2_USART_TX_IO_PIN)
#else
# error "Bad CONFIG_STM32F2_USART_TX_IO_PIN value."
#endif

#if (CONFIG_STM32F2_USART_RX_IO_PIN >= 0) && \
    (CONFIG_STM32F2_USART_RX_IO_PIN <= 15)
# define USART_RX_IO_PIN	(CONFIG_STM32F2_USART_RX_IO_PIN)
#else
# error "Bad CONFIG_STM32F2_USART_RX_IO_PIN value."
#endif

75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
 * STM32F USART definitions
 */
/*
 * USART registers bases
 */
#define STM32F2_USART1_BASE	(STM32F2_APB2PERITH_BASE + 0x1000)
#define STM32F2_USART2_BASE	(STM32F2_APB1PERITH_BASE + 0x4400)
#define STM32F2_USART3_BASE	(STM32F2_APB1PERITH_BASE + 0x4800)
#define STM32F2_USART4_BASE	(STM32F2_APB1PERITH_BASE + 0x4C00)
#define STM32F2_USART5_BASE	(STM32F2_APB1PERITH_BASE + 0x5000)
#define STM32F2_USART6_BASE	(STM32F2_APB2PERITH_BASE + 0x1400)

/*
 * SR bit masks
 */
#define STM32F2_USART_SR_TXE	(1 << 7)	/* Transmit data reg empty   */
#define STM32F2_USART_SR_RXNE	(1 << 5)	/* Read data reg not empty   */

/*
 * BRR reg fields
 */
#define STM32F2_USART_BRR_F_BIT	0		/* fraction of USARTDIV	     */
#define STM32F2_USART_BRR_F_MSK	0x0F

#define STM32F2_USART_BRR_M_BIT	4		/* mantissa of USARTDIV	     */
#define STM32F2_USART_BRR_M_MSK	0xFFF

/*
 * CR1 bit masks
 */
#define STM32F2_USART_CR1_UE	(1 << 13)	/* USART enable		     */
#define STM32F2_USART_CR1_TE	(1 <<  3)	/* Transmitter enable	     */
#define STM32F2_USART_CR1_RE	(1 <<  2)	/* Receiver enable	     */

/*
 * STM32F2 RCC USART specific definitions
 */
#define STM32F2_RCC_ENR_USART1	offsetof(struct stm32f2_rcc_regs, apb2enr)
#define STM32F2_RCC_MSK_USART1	(1 <<  4)

#define STM32F2_RCC_ENR_USART2	offsetof(struct stm32f2_rcc_regs, apb1enr)
#define STM32F2_RCC_MSK_USART2	(1 << 17)

#define STM32F2_RCC_ENR_USART3	offsetof(struct stm32f2_rcc_regs, apb1enr)
#define STM32F2_RCC_MSK_USART3	(1 << 18)

#define STM32F2_RCC_ENR_USART4	offsetof(struct stm32f2_rcc_regs, apb1enr)
#define STM32F2_RCC_MSK_USART4	(1 << 19)

#define STM32F2_RCC_ENR_USART5	offsetof(struct stm32f2_rcc_regs, apb1enr)
#define STM32F2_RCC_MSK_USART5	(1 << 20)

#define STM32F2_RCC_ENR_USART6	offsetof(struct stm32f2_rcc_regs, apb2enr)
#define STM32F2_RCC_MSK_USART6	(1 <<  5)

131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
 * USART register map
 */
struct stm32f2_usart_regs {
	u16	sr;		/* Status				      */
	u16	rsv0;
	u16	dr;		/* Data					      */
	u16	rsv1;
	u16	brr;		/* Baud rate				      */
	u16	rsv2;
	u16	cr1;		/* Control 1				      */
	u16	rsv3;
	u16	cr2;		/* Control 2				      */
	u16	rsv4;
	u16	cr3;		/* Control 3				      */
	u16	rsv5;
	u16	gtpr;		/* Guard time and prescaler		      */
};

150
151
152
/*
 * U-Boot global data to get the baudrate from
 */
153
154
155
156
157
158
159
160
161
162
163
DECLARE_GLOBAL_DATA_PTR;

/*
 * Register map bases
 */
static const unsigned long usart_base[] = {
	STM32F2_USART1_BASE, STM32F2_USART2_BASE, STM32F2_USART3_BASE,
	STM32F2_USART4_BASE, STM32F2_USART5_BASE, STM32F2_USART6_BASE
};

/*
164
 * Register offsets
165
166
167
168
169
170
171
172
173
174
175
176
177
178
 */
static const unsigned long rcc_enr_offset[] = {
	STM32F2_RCC_ENR_USART1, STM32F2_RCC_ENR_USART2, STM32F2_RCC_ENR_USART3,
	STM32F2_RCC_ENR_USART4, STM32F2_RCC_ENR_USART5, STM32F2_RCC_ENR_USART6
};

/*
 * Different masks
 */
static const unsigned long rcc_msk[] = {
	STM32F2_RCC_MSK_USART1, STM32F2_RCC_MSK_USART2, STM32F2_RCC_MSK_USART3,
	STM32F2_RCC_MSK_USART4, STM32F2_RCC_MSK_USART5, STM32F2_RCC_MSK_USART6
};

179
180
181
182
183
184
185
/*
 * GPIO roles
 */
static const enum stm32f2_gpio_role gpio_role[] = {
	STM32F2_GPIO_ROLE_USART1, STM32F2_GPIO_ROLE_USART2,
	STM32F2_GPIO_ROLE_USART3, STM32F2_GPIO_ROLE_USART4,
	STM32F2_GPIO_ROLE_USART5, STM32F2_GPIO_ROLE_USART6
186
187
188
189
190
191
192
};

/*
 * Hardware resources
 */
static volatile struct stm32f2_usart_regs	*usart_regs;

193
194
195
196
197
/*
 * Initialize the serial port.
 */
int serial_init(void)
{
198
199
200
	static volatile u32			 *usart_enr;
	static volatile struct stm32f2_rcc_regs	 *rcc_regs;

201
202
	int	rv;

203
204
205
	/*
	 * Setup registers
	 */
206
207
	usart_regs = (struct stm32f2_usart_regs *)usart_base[USART_PORT];
	rcc_regs   = (struct stm32f2_rcc_regs *)STM32F2_RCC_BASE;
208
209
210
211

	usart_enr  = (u32 *)(STM32F2_RCC_BASE + rcc_enr_offset[USART_PORT]);

	/*
212
	 * Enable USART clocks
213
214
215
	 */
	*usart_enr |= rcc_msk[USART_PORT];

216
	/*
217
	 * Configure GPIOs
218
	 */
219
220
221
222
223
224
225
226
	rv = stm32f2_gpio_config(USART_TX_IO_PORT, USART_TX_IO_PIN,
				 gpio_role[USART_PORT]);
	if (rv != 0)
		goto out;
	rv = stm32f2_gpio_config(USART_RX_IO_PORT, USART_RX_IO_PIN,
				 gpio_role[USART_PORT]);
	if (rv != 0)
		goto out;
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256

	/*
	 * CR1:
	 * - 1 Start bit, 8 Data bits, n Stop bit
	 * - parity control disabled
	 */
	usart_regs->cr1 = STM32F2_USART_CR1_TE | STM32F2_USART_CR1_RE;

	/*
	 * CR2:
	 * - 1 Stop bit
	 */
	usart_regs->cr2 = 0;

	/*
	 * CR3:
	 * - flow control disabled
	 * - full duplex
	 */
	usart_regs->cr3 = 0;

	/*
	 * Set baudrate
	 */
	serial_setbrg();

	/*
	 * Enable USART
	 */
	usart_regs->cr1 |= STM32F2_USART_CR1_UE;
257

258
259
260
	rv = 0;
out:
	return rv;
261
262
263
264
265
266
267
}

/*
 * Set new baudrate.
 */
void serial_setbrg(void)
{
268
269
270
271
272
273
274
	u32	apb_clock, int_div, frac_div, tmp;

	if (USART_PORT == 0 || USART_PORT == 5)
		apb_clock = clock_get(CLOCK_PCLK2);
	else
		apb_clock = clock_get(CLOCK_PCLK1);

275
	/*
276
	 * Assume oversampling mode of 16 Samples
277
	 */
278
279
	int_div = (25 * apb_clock) / (4 * gd->baudrate);

280
	tmp = (int_div / 100) << STM32F2_USART_BRR_M_BIT;
281
	frac_div = int_div - (100 * (tmp >> 4));
282
	tmp |= (((frac_div * 16) + 50) / 100) & STM32F2_USART_BRR_F_MSK;
283
284

	usart_regs->brr = tmp;
285
286
287
288
289
290
291
292
293

	return;
}

/*
 * Read a single character from the serial port.
 */
int serial_getc(void)
{
294
	while (!(usart_regs->sr & STM32F2_USART_SR_RXNE));
295

296
	return usart_regs->dr & 0xFF;
297
298
299
300
301
302
303
}

/*
 * Put a single character to the serial port.
 */
void serial_putc(const char c)
{
304
305
	if (c == '\n')
		serial_putc('\r');
306

307
308
309
	while (!(usart_regs->sr & STM32F2_USART_SR_TXE));

	usart_regs->dr = c;
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
}

/*
 * Put a string ('\0'-terminated) to the serial port.
 */
void serial_puts(const char *s)
{
	while (*s)
		serial_putc(*s++);
}

/*
 * Test whether a character in in the RX buffer.
 */
int serial_tstc(void)
{
326
	return (usart_regs->sr & STM32F2_USART_SR_RXNE) ? 1 : 0;
327
}