3 * Kamil Lulko, <kamil.lulko@gmail.com>
5 * SPDX-License-Identifier: GPL-2.0+
12 #include <asm/arch/stm32.h>
13 #include <dm/platform_data/serial_stm32.h>
25 #define USART_CR1_RE (1 << 2)
26 #define USART_CR1_TE (1 << 3)
27 #define USART_CR1_UE (1 << 13)
29 #define USART_SR_FLAG_RXNE (1 << 5)
30 #define USART_SR_FLAG_TXE (1 << 7)
32 #define USART_BRR_F_MASK 0xF
33 #define USART_BRR_M_SHIFT 4
34 #define USART_BRR_M_MASK 0xFFF0
36 DECLARE_GLOBAL_DATA_PTR
;
38 static int stm32_serial_setbrg(struct udevice
*dev
, int baudrate
)
40 struct stm32_serial_platdata
*plat
= dev
->platdata
;
41 struct stm32_usart
*const usart
= plat
->base
;
42 u32 clock
, int_div
, frac_div
, tmp
;
44 if (((u32
)usart
& STM32_BUS_MASK
) == STM32_APB1PERIPH_BASE
)
45 clock
= clock_get(CLOCK_APB1
);
46 else if (((u32
)usart
& STM32_BUS_MASK
) == STM32_APB2PERIPH_BASE
)
47 clock
= clock_get(CLOCK_APB2
);
51 int_div
= (25 * clock
) / (4 * baudrate
);
52 tmp
= ((int_div
/ 100) << USART_BRR_M_SHIFT
) & USART_BRR_M_MASK
;
53 frac_div
= int_div
- (100 * (tmp
>> USART_BRR_M_SHIFT
));
54 tmp
|= (((frac_div
* 16) + 50) / 100) & USART_BRR_F_MASK
;
55 writel(tmp
, &usart
->brr
);
60 static int stm32_serial_getc(struct udevice
*dev
)
62 struct stm32_serial_platdata
*plat
= dev
->platdata
;
63 struct stm32_usart
*const usart
= plat
->base
;
65 if ((readl(&usart
->sr
) & USART_SR_FLAG_RXNE
) == 0)
68 return readl(&usart
->dr
);
71 static int stm32_serial_putc(struct udevice
*dev
, const char c
)
73 struct stm32_serial_platdata
*plat
= dev
->platdata
;
74 struct stm32_usart
*const usart
= plat
->base
;
76 if ((readl(&usart
->sr
) & USART_SR_FLAG_TXE
) == 0)
79 writel(c
, &usart
->dr
);
84 static int stm32_serial_pending(struct udevice
*dev
, bool input
)
86 struct stm32_serial_platdata
*plat
= dev
->platdata
;
87 struct stm32_usart
*const usart
= plat
->base
;
90 return readl(&usart
->sr
) & USART_SR_FLAG_RXNE
? 1 : 0;
92 return readl(&usart
->sr
) & USART_SR_FLAG_TXE
? 0 : 1;
95 static int stm32_serial_probe(struct udevice
*dev
)
97 struct stm32_serial_platdata
*plat
= dev
->platdata
;
98 struct stm32_usart
*const usart
= plat
->base
;
99 setbits_le32(&usart
->cr1
, USART_CR1_RE
| USART_CR1_TE
| USART_CR1_UE
);
104 static const struct dm_serial_ops stm32_serial_ops
= {
105 .putc
= stm32_serial_putc
,
106 .pending
= stm32_serial_pending
,
107 .getc
= stm32_serial_getc
,
108 .setbrg
= stm32_serial_setbrg
,
111 U_BOOT_DRIVER(serial_stm32
) = {
112 .name
= "serial_stm32",
114 .ops
= &stm32_serial_ops
,
115 .probe
= stm32_serial_probe
,
116 .flags
= DM_FLAG_PRE_RELOC
,