1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
4 * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
12 #include <asm/arch/stm32.h>
13 #include "serial_stm32.h"
15 static int stm32_serial_setbrg(struct udevice
*dev
, int baudrate
)
17 struct stm32x7_serial_platdata
*plat
= dev_get_platdata(dev
);
18 bool stm32f4
= plat
->uart_info
->stm32f4
;
19 fdt_addr_t base
= plat
->base
;
20 u32 int_div
, mantissa
, fraction
, oversampling
;
22 int_div
= DIV_ROUND_CLOSEST(plat
->clock_rate
, baudrate
);
26 setbits_le32(base
+ CR1_OFFSET(stm32f4
), USART_CR1_OVER8
);
29 clrbits_le32(base
+ CR1_OFFSET(stm32f4
), USART_CR1_OVER8
);
32 mantissa
= (int_div
/ oversampling
) << USART_BRR_M_SHIFT
;
33 fraction
= int_div
% oversampling
;
35 writel(mantissa
| fraction
, base
+ BRR_OFFSET(stm32f4
));
40 static int stm32_serial_getc(struct udevice
*dev
)
42 struct stm32x7_serial_platdata
*plat
= dev_get_platdata(dev
);
43 bool stm32f4
= plat
->uart_info
->stm32f4
;
44 fdt_addr_t base
= plat
->base
;
45 u32 isr
= readl(base
+ ISR_OFFSET(stm32f4
));
47 if ((isr
& USART_ISR_FLAG_RXNE
) == 0)
50 if (isr
& USART_ISR_FLAG_ORE
) {
52 setbits_le32(base
+ ICR_OFFSET
, USART_ICR_OREF
);
54 readl(base
+ RDR_OFFSET(stm32f4
));
58 return readl(base
+ RDR_OFFSET(stm32f4
));
61 static int stm32_serial_putc(struct udevice
*dev
, const char c
)
63 struct stm32x7_serial_platdata
*plat
= dev_get_platdata(dev
);
64 bool stm32f4
= plat
->uart_info
->stm32f4
;
65 fdt_addr_t base
= plat
->base
;
67 if ((readl(base
+ ISR_OFFSET(stm32f4
)) & USART_ISR_FLAG_TXE
) == 0)
70 writel(c
, base
+ TDR_OFFSET(stm32f4
));
75 static int stm32_serial_pending(struct udevice
*dev
, bool input
)
77 struct stm32x7_serial_platdata
*plat
= dev_get_platdata(dev
);
78 bool stm32f4
= plat
->uart_info
->stm32f4
;
79 fdt_addr_t base
= plat
->base
;
82 return readl(base
+ ISR_OFFSET(stm32f4
)) &
83 USART_ISR_FLAG_RXNE
? 1 : 0;
85 return readl(base
+ ISR_OFFSET(stm32f4
)) &
86 USART_ISR_FLAG_TXE
? 0 : 1;
89 static int stm32_serial_probe(struct udevice
*dev
)
91 struct stm32x7_serial_platdata
*plat
= dev_get_platdata(dev
);
93 fdt_addr_t base
= plat
->base
;
98 plat
->uart_info
= (struct stm32_uart_info
*)dev_get_driver_data(dev
);
99 stm32f4
= plat
->uart_info
->stm32f4
;
100 uart_enable_bit
= plat
->uart_info
->uart_enable_bit
;
102 ret
= clk_get_by_index(dev
, 0, &clk
);
106 ret
= clk_enable(&clk
);
108 dev_err(dev
, "failed to enable clock\n");
112 plat
->clock_rate
= clk_get_rate(&clk
);
113 if (plat
->clock_rate
< 0) {
115 return plat
->clock_rate
;
118 /* Disable uart-> enable fifo-> enable uart */
119 clrbits_le32(base
+ CR1_OFFSET(stm32f4
), USART_CR1_RE
| USART_CR1_TE
|
120 BIT(uart_enable_bit
));
121 if (plat
->uart_info
->has_fifo
)
122 setbits_le32(base
+ CR1_OFFSET(stm32f4
), USART_CR1_FIFOEN
);
123 setbits_le32(base
+ CR1_OFFSET(stm32f4
), USART_CR1_RE
| USART_CR1_TE
|
124 BIT(uart_enable_bit
));
129 static const struct udevice_id stm32_serial_id
[] = {
130 { .compatible
= "st,stm32-uart", .data
= (ulong
)&stm32f4_info
},
131 { .compatible
= "st,stm32f7-uart", .data
= (ulong
)&stm32f7_info
},
132 { .compatible
= "st,stm32h7-uart", .data
= (ulong
)&stm32h7_info
},
136 static int stm32_serial_ofdata_to_platdata(struct udevice
*dev
)
138 struct stm32x7_serial_platdata
*plat
= dev_get_platdata(dev
);
140 plat
->base
= devfdt_get_addr(dev
);
141 if (plat
->base
== FDT_ADDR_T_NONE
)
147 static const struct dm_serial_ops stm32_serial_ops
= {
148 .putc
= stm32_serial_putc
,
149 .pending
= stm32_serial_pending
,
150 .getc
= stm32_serial_getc
,
151 .setbrg
= stm32_serial_setbrg
,
154 U_BOOT_DRIVER(serial_stm32
) = {
155 .name
= "serial_stm32",
157 .of_match
= of_match_ptr(stm32_serial_id
),
158 .ofdata_to_platdata
= of_match_ptr(stm32_serial_ofdata_to_platdata
),
159 .platdata_auto_alloc_size
= sizeof(struct stm32x7_serial_platdata
),
160 .ops
= &stm32_serial_ops
,
161 .probe
= stm32_serial_probe
,
162 .flags
= DM_FLAG_PRE_RELOC
,