Commit 665624149a55f43e25e13ea50bd0015c31e6c6bb
Committed by
Tom Rini
1 parent
5076c64a08
Exists in
v2017.01-smarct4x
and in
30 other branches
stm32: Convert serial driver to DM
Signed-off-by: Kamil Lulko <kamil.lulko@gmail.com> Cc: Simon Glass <sjg@chromium.org> Reviewed-by: Simon Glass <sjg@chromium.org>
Showing 7 changed files with 136 additions and 119 deletions Side-by-side Diff
arch/arm/Kconfig
arch/arm/include/asm/arch-stm32f4/stm32.h
... | ... | @@ -3,7 +3,7 @@ |
3 | 3 | * Yuri Tikhonov, Emcraft Systems, yur@emcraft.com |
4 | 4 | * |
5 | 5 | * (C) Copyright 2015 |
6 | - * Kamil Lulko, <rev13@wp.pl> | |
6 | + * Kamil Lulko, <kamil.lulko@gmail.com> | |
7 | 7 | * |
8 | 8 | * SPDX-License-Identifier: GPL-2.0+ |
9 | 9 | */ |
... | ... | @@ -105,6 +105,14 @@ |
105 | 105 | #define STM32_FLASH_CR_LOCK (1 << 31) |
106 | 106 | #define STM32_FLASH_CR_SNB_OFFSET 3 |
107 | 107 | #define STM32_FLASH_CR_SNB_MASK (15 << STM32_FLASH_CR_SNB_OFFSET) |
108 | + | |
109 | +/* | |
110 | + * Peripheral base addresses | |
111 | + */ | |
112 | +#define STM32_USART1_BASE (STM32_APB2PERIPH_BASE + 0x1000) | |
113 | +#define STM32_USART2_BASE (STM32_APB1PERIPH_BASE + 0x4400) | |
114 | +#define STM32_USART3_BASE (STM32_APB1PERIPH_BASE + 0x4800) | |
115 | +#define STM32_USART6_BASE (STM32_APB2PERIPH_BASE + 0x1400) | |
108 | 116 | |
109 | 117 | enum clock { |
110 | 118 | CLOCK_CORE, |
board/st/stm32f429-discovery/stm32f429-discovery.c
... | ... | @@ -6,7 +6,7 @@ |
6 | 6 | * Pavel Boldin, Emcraft Systems, paboldin@emcraft.com |
7 | 7 | * |
8 | 8 | * (C) Copyright 2015 |
9 | - * Kamil Lulko, <rev13@wp.pl> | |
9 | + * Kamil Lulko, <kamil.lulko@gmail.com> | |
10 | 10 | * |
11 | 11 | * SPDX-License-Identifier: GPL-2.0+ |
12 | 12 | */ |
... | ... | @@ -17,6 +17,8 @@ |
17 | 17 | #include <asm/arch/stm32.h> |
18 | 18 | #include <asm/arch/gpio.h> |
19 | 19 | #include <asm/arch/fmc.h> |
20 | +#include <dm/platdata.h> | |
21 | +#include <dm/platform_data/serial_stm32.h> | |
20 | 22 | |
21 | 23 | DECLARE_GLOBAL_DATA_PTR; |
22 | 24 | |
... | ... | @@ -262,6 +264,15 @@ |
262 | 264 | |
263 | 265 | return rv; |
264 | 266 | } |
267 | + | |
268 | +static const struct stm32_serial_platdata serial_platdata = { | |
269 | + .base = (struct stm32_usart *)STM32_USART1_BASE, | |
270 | +}; | |
271 | + | |
272 | +U_BOOT_DEVICE(stm32_serials) = { | |
273 | + .name = "serial_stm32", | |
274 | + .platdata = &serial_platdata, | |
275 | +}; | |
265 | 276 | |
266 | 277 | u32 get_board_rev(void) |
267 | 278 | { |
doc/driver-model/serial-howto.txt
drivers/serial/serial_stm32.c
1 | 1 | /* |
2 | 2 | * (C) Copyright 2015 |
3 | - * Kamil Lulko, <rev13@wp.pl> | |
3 | + * Kamil Lulko, <kamil.lulko@gmail.com> | |
4 | 4 | * |
5 | 5 | * SPDX-License-Identifier: GPL-2.0+ |
6 | 6 | */ |
7 | 7 | |
8 | 8 | #include <common.h> |
9 | +#include <dm.h> | |
9 | 10 | #include <asm/io.h> |
10 | 11 | #include <serial.h> |
11 | 12 | #include <asm/arch/stm32.h> |
13 | +#include <dm/platform_data/serial_stm32.h> | |
12 | 14 | |
13 | -/* | |
14 | - * Set up the usart port | |
15 | - */ | |
16 | -#if (CONFIG_STM32_USART >= 1) && (CONFIG_STM32_USART <= 6) | |
17 | -#define USART_PORT (CONFIG_STM32_USART - 1) | |
18 | -#else | |
19 | -#define USART_PORT 0 | |
20 | -#endif | |
21 | -/* | |
22 | - * Set up the usart base address | |
23 | - * | |
24 | - * --STM32_USARTD_BASE means default setting | |
25 | - */ | |
26 | -#define STM32_USART1_BASE (STM32_APB2PERIPH_BASE + 0x1000) | |
27 | -#define STM32_USART2_BASE (STM32_APB1PERIPH_BASE + 0x4400) | |
28 | -#define STM32_USART3_BASE (STM32_APB1PERIPH_BASE + 0x4800) | |
29 | -#define STM32_USART6_BASE (STM32_APB2PERIPH_BASE + 0x1400) | |
30 | -#define STM32_USARTD_BASE STM32_USART1_BASE | |
31 | -/* | |
32 | - * RCC USART specific definitions | |
33 | - * | |
34 | - * --RCC_ENR_USARTDEN means default setting | |
35 | - */ | |
36 | -#define RCC_ENR_USART1EN (1 << 4) | |
37 | -#define RCC_ENR_USART2EN (1 << 17) | |
38 | -#define RCC_ENR_USART3EN (1 << 18) | |
39 | -#define RCC_ENR_USART6EN (1 << 5) | |
40 | -#define RCC_ENR_USARTDEN RCC_ENR_USART1EN | |
41 | - | |
42 | -struct stm32_serial { | |
15 | +struct stm32_usart { | |
43 | 16 | u32 sr; |
44 | 17 | u32 dr; |
45 | 18 | u32 brr; |
46 | 19 | |
47 | 20 | |
48 | 21 | |
49 | 22 | |
50 | 23 | |
51 | 24 | |
52 | 25 | |
53 | 26 | |
54 | 27 | |
55 | 28 | |
56 | 29 | |
57 | 30 | |
58 | 31 | |
59 | 32 | |
60 | 33 | |
61 | 34 | |
62 | 35 | |
63 | 36 | |
64 | 37 | |
65 | 38 | |
66 | 39 | |
67 | 40 | |
68 | 41 | |
69 | 42 | |
70 | 43 | |
71 | 44 | |
... | ... | @@ -49,121 +22,137 @@ |
49 | 22 | u32 gtpr; |
50 | 23 | }; |
51 | 24 | |
52 | -#define USART_CR1_RE (1 << 2) | |
53 | -#define USART_CR1_TE (1 << 3) | |
54 | -#define USART_CR1_UE (1 << 13) | |
25 | +#define USART_CR1_RE (1 << 2) | |
26 | +#define USART_CR1_TE (1 << 3) | |
27 | +#define USART_CR1_UE (1 << 13) | |
55 | 28 | |
56 | 29 | #define USART_SR_FLAG_RXNE (1 << 5) |
57 | -#define USART_SR_FLAG_TXE (1 << 7) | |
30 | +#define USART_SR_FLAG_TXE (1 << 7) | |
58 | 31 | |
59 | -#define USART_BRR_F_MASK 0xF | |
32 | +#define USART_BRR_F_MASK 0xF | |
60 | 33 | #define USART_BRR_M_SHIFT 4 |
61 | 34 | #define USART_BRR_M_MASK 0xFFF0 |
62 | 35 | |
63 | 36 | DECLARE_GLOBAL_DATA_PTR; |
64 | 37 | |
65 | -static const unsigned long usart_base[] = { | |
66 | - STM32_USART1_BASE, | |
67 | - STM32_USART2_BASE, | |
68 | - STM32_USART3_BASE, | |
69 | - STM32_USARTD_BASE, | |
70 | - STM32_USARTD_BASE, | |
71 | - STM32_USART6_BASE | |
72 | -}; | |
38 | +#define MAX_SERIAL_PORTS 4 | |
73 | 39 | |
74 | -static const unsigned long rcc_enr_en[] = { | |
75 | - RCC_ENR_USART1EN, | |
76 | - RCC_ENR_USART2EN, | |
77 | - RCC_ENR_USART3EN, | |
78 | - RCC_ENR_USARTDEN, | |
79 | - RCC_ENR_USARTDEN, | |
80 | - RCC_ENR_USART6EN | |
40 | +/* | |
41 | + * RCC USART specific definitions | |
42 | + */ | |
43 | +#define RCC_ENR_USART1EN (1 << 4) | |
44 | +#define RCC_ENR_USART2EN (1 << 17) | |
45 | +#define RCC_ENR_USART3EN (1 << 18) | |
46 | +#define RCC_ENR_USART6EN (1 << 5) | |
47 | + | |
48 | +/* Array used to figure out which RCC bit needs to be set */ | |
49 | +static const unsigned long usart_port_rcc_pairs[MAX_SERIAL_PORTS][2] = { | |
50 | + { STM32_USART1_BASE, RCC_ENR_USART1EN }, | |
51 | + { STM32_USART2_BASE, RCC_ENR_USART2EN }, | |
52 | + { STM32_USART3_BASE, RCC_ENR_USART3EN }, | |
53 | + { STM32_USART6_BASE, RCC_ENR_USART6EN } | |
81 | 54 | }; |
82 | 55 | |
83 | -static void stm32_serial_setbrg(void) | |
56 | +static int stm32_serial_setbrg(struct udevice *dev, int baudrate) | |
84 | 57 | { |
85 | - serial_init(); | |
86 | -} | |
58 | + struct stm32_serial_platdata *plat = dev->platdata; | |
59 | + struct stm32_usart *const usart = plat->base; | |
60 | + u32 clock, int_div, frac_div, tmp; | |
87 | 61 | |
88 | -static int stm32_serial_init(void) | |
89 | -{ | |
90 | - struct stm32_serial *usart = | |
91 | - (struct stm32_serial *)usart_base[USART_PORT]; | |
92 | - u32 clock, int_div, frac_div, tmp; | |
93 | - | |
94 | - if ((usart_base[USART_PORT] & STM32_BUS_MASK) == | |
95 | - STM32_APB1PERIPH_BASE) { | |
96 | - setbits_le32(&STM32_RCC->apb1enr, rcc_enr_en[USART_PORT]); | |
62 | + if (((u32)usart & STM32_BUS_MASK) == STM32_APB1PERIPH_BASE) | |
97 | 63 | clock = clock_get(CLOCK_APB1); |
98 | - } else if ((usart_base[USART_PORT] & STM32_BUS_MASK) == | |
99 | - STM32_APB2PERIPH_BASE) { | |
100 | - setbits_le32(&STM32_RCC->apb2enr, rcc_enr_en[USART_PORT]); | |
64 | + else if (((u32)usart & STM32_BUS_MASK) == STM32_APB2PERIPH_BASE) | |
101 | 65 | clock = clock_get(CLOCK_APB2); |
102 | - } else { | |
103 | - return -1; | |
104 | - } | |
66 | + else | |
67 | + return -EINVAL; | |
105 | 68 | |
106 | - int_div = (25 * clock) / (4 * gd->baudrate); | |
69 | + int_div = (25 * clock) / (4 * baudrate); | |
107 | 70 | tmp = ((int_div / 100) << USART_BRR_M_SHIFT) & USART_BRR_M_MASK; |
108 | 71 | frac_div = int_div - (100 * (tmp >> USART_BRR_M_SHIFT)); |
109 | 72 | tmp |= (((frac_div * 16) + 50) / 100) & USART_BRR_F_MASK; |
110 | - | |
111 | 73 | writel(tmp, &usart->brr); |
112 | - setbits_le32(&usart->cr1, USART_CR1_RE | USART_CR1_TE | USART_CR1_UE); | |
113 | 74 | |
114 | 75 | return 0; |
115 | 76 | } |
116 | 77 | |
117 | -static int stm32_serial_getc(void) | |
78 | +static int stm32_serial_getc(struct udevice *dev) | |
118 | 79 | { |
119 | - struct stm32_serial *usart = | |
120 | - (struct stm32_serial *)usart_base[USART_PORT]; | |
121 | - while ((readl(&usart->sr) & USART_SR_FLAG_RXNE) == 0) | |
122 | - ; | |
80 | + struct stm32_serial_platdata *plat = dev->platdata; | |
81 | + struct stm32_usart *const usart = plat->base; | |
82 | + | |
83 | + if ((readl(&usart->sr) & USART_SR_FLAG_RXNE) == 0) | |
84 | + return -EAGAIN; | |
85 | + | |
123 | 86 | return readl(&usart->dr); |
124 | 87 | } |
125 | 88 | |
126 | -static void stm32_serial_putc(const char c) | |
89 | +static int stm32_serial_putc(struct udevice *dev, const char c) | |
127 | 90 | { |
128 | - struct stm32_serial *usart = | |
129 | - (struct stm32_serial *)usart_base[USART_PORT]; | |
91 | + struct stm32_serial_platdata *plat = dev->platdata; | |
92 | + struct stm32_usart *const usart = plat->base; | |
130 | 93 | |
131 | - if (c == '\n') | |
132 | - stm32_serial_putc('\r'); | |
94 | + if ((readl(&usart->sr) & USART_SR_FLAG_TXE) == 0) | |
95 | + return -EAGAIN; | |
133 | 96 | |
134 | - while ((readl(&usart->sr) & USART_SR_FLAG_TXE) == 0) | |
135 | - ; | |
136 | 97 | writel(c, &usart->dr); |
98 | + | |
99 | + return 0; | |
137 | 100 | } |
138 | 101 | |
139 | -static int stm32_serial_tstc(void) | |
102 | +static int stm32_serial_pending(struct udevice *dev, bool input) | |
140 | 103 | { |
141 | - struct stm32_serial *usart = | |
142 | - (struct stm32_serial *)usart_base[USART_PORT]; | |
143 | - u8 ret; | |
104 | + struct stm32_serial_platdata *plat = dev->platdata; | |
105 | + struct stm32_usart *const usart = plat->base; | |
144 | 106 | |
145 | - ret = readl(&usart->sr) & USART_SR_FLAG_RXNE; | |
146 | - return ret; | |
107 | + if (input) | |
108 | + return readl(&usart->sr) & USART_SR_FLAG_RXNE ? 1 : 0; | |
109 | + else | |
110 | + return readl(&usart->sr) & USART_SR_FLAG_TXE ? 0 : 1; | |
147 | 111 | } |
148 | 112 | |
149 | -static struct serial_device stm32_serial_drv = { | |
150 | - .name = "stm32_serial", | |
151 | - .start = stm32_serial_init, | |
152 | - .stop = NULL, | |
153 | - .setbrg = stm32_serial_setbrg, | |
154 | - .putc = stm32_serial_putc, | |
155 | - .puts = default_serial_puts, | |
156 | - .getc = stm32_serial_getc, | |
157 | - .tstc = stm32_serial_tstc, | |
158 | -}; | |
159 | - | |
160 | -void stm32_serial_initialize(void) | |
113 | +static int stm32_serial_probe(struct udevice *dev) | |
161 | 114 | { |
162 | - serial_register(&stm32_serial_drv); | |
163 | -} | |
115 | + struct stm32_serial_platdata *plat = dev->platdata; | |
116 | + struct stm32_usart *const usart = plat->base; | |
117 | + int usart_port = -1; | |
118 | + int i; | |
164 | 119 | |
165 | -__weak struct serial_device *default_serial_console(void) | |
166 | -{ | |
167 | - return &stm32_serial_drv; | |
120 | + for (i = 0; i < MAX_SERIAL_PORTS; i++) { | |
121 | + if ((u32)usart == usart_port_rcc_pairs[i][0]) { | |
122 | + usart_port = i; | |
123 | + break; | |
124 | + } | |
125 | + } | |
126 | + | |
127 | + if (usart_port == -1) | |
128 | + return -EINVAL; | |
129 | + | |
130 | + if (((u32)usart & STM32_BUS_MASK) == STM32_APB1PERIPH_BASE) | |
131 | + setbits_le32(&STM32_RCC->apb1enr, | |
132 | + usart_port_rcc_pairs[usart_port][1]); | |
133 | + else if (((u32)usart & STM32_BUS_MASK) == STM32_APB2PERIPH_BASE) | |
134 | + setbits_le32(&STM32_RCC->apb2enr, | |
135 | + usart_port_rcc_pairs[usart_port][1]); | |
136 | + else | |
137 | + return -EINVAL; | |
138 | + | |
139 | + setbits_le32(&usart->cr1, USART_CR1_RE | USART_CR1_TE | USART_CR1_UE); | |
140 | + | |
141 | + return 0; | |
168 | 142 | } |
143 | + | |
144 | +static const struct dm_serial_ops stm32_serial_ops = { | |
145 | + .putc = stm32_serial_putc, | |
146 | + .pending = stm32_serial_pending, | |
147 | + .getc = stm32_serial_getc, | |
148 | + .setbrg = stm32_serial_setbrg, | |
149 | +}; | |
150 | + | |
151 | +U_BOOT_DRIVER(serial_stm32) = { | |
152 | + .name = "serial_stm32", | |
153 | + .id = UCLASS_SERIAL, | |
154 | + .ops = &stm32_serial_ops, | |
155 | + .probe = stm32_serial_probe, | |
156 | + .flags = DM_FLAG_PRE_RELOC, | |
157 | +}; |
include/configs/stm32f429-discovery.h
1 | 1 | /* |
2 | 2 | * (C) Copyright 2015 |
3 | - * Kamil Lulko, <rev13@wp.pl> | |
3 | + * Kamil Lulko, <kamil.lulko@gmail.com> | |
4 | 4 | * |
5 | 5 | * SPDX-License-Identifier: GPL-2.0+ |
6 | 6 | */ |
... | ... | @@ -51,14 +51,6 @@ |
51 | 51 | |
52 | 52 | #define CONFIG_STM32_GPIO |
53 | 53 | #define CONFIG_STM32_SERIAL |
54 | -/* | |
55 | - * Configuration of the USART | |
56 | - * 1: TX:PA9 RX:PA10 | |
57 | - * 2: TX:PD5 RX:PD6 | |
58 | - * 3: TX:PC10 RX:PC11 | |
59 | - * 6: TX:PG14 RX:PG9 | |
60 | - */ | |
61 | -#define CONFIG_STM32_USART 1 | |
62 | 54 | |
63 | 55 | #define CONFIG_STM32_HSE_HZ 8000000 |
64 | 56 |
include/dm/platform_data/serial_stm32.h
1 | +/* | |
2 | + * (C) Copyright 2015 | |
3 | + * Kamil Lulko, <kamil.lulko@gmail.com> | |
4 | + * | |
5 | + * SPDX-License-Identifier: GPL-2.0+ | |
6 | + */ | |
7 | + | |
8 | +#ifndef __SERIAL_STM32_H | |
9 | +#define __SERIAL_STM32_H | |
10 | + | |
11 | +/* Information about a serial port */ | |
12 | +struct stm32_serial_platdata { | |
13 | + struct stm32_usart *base; /* address of registers in physical memory */ | |
14 | +}; | |
15 | + | |
16 | +#endif /* __SERIAL_STM32_H */ |