2 * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
3 * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
5 * SPDX-License-Identifier: GPL-2.0+
13 #include <asm/arch/stm32.h>
14 #include "serial_stm32.h"
16 DECLARE_GLOBAL_DATA_PTR
;
18 static int stm32_serial_setbrg(struct udevice
*dev
, int baudrate
)
20 struct stm32x7_serial_platdata
*plat
= dev_get_platdata(dev
);
21 bool stm32f4
= plat
->uart_info
->stm32f4
;
22 fdt_addr_t base
= plat
->base
;
23 u32 int_div
, mantissa
, fraction
, oversampling
;
25 int_div
= DIV_ROUND_CLOSEST(plat
->clock_rate
, baudrate
);
29 setbits_le32(base
+ CR1_OFFSET(stm32f4
), USART_CR1_OVER8
);
32 clrbits_le32(base
+ CR1_OFFSET(stm32f4
), USART_CR1_OVER8
);
35 mantissa
= (int_div
/ oversampling
) << USART_BRR_M_SHIFT
;
36 fraction
= int_div
% oversampling
;
38 writel(mantissa
| fraction
, base
+ BRR_OFFSET(stm32f4
));
43 static int stm32_serial_getc(struct udevice
*dev
)
45 struct stm32x7_serial_platdata
*plat
= dev_get_platdata(dev
);
46 bool stm32f4
= plat
->uart_info
->stm32f4
;
47 fdt_addr_t base
= plat
->base
;
49 if ((readl(base
+ ISR_OFFSET(stm32f4
)) & USART_SR_FLAG_RXNE
) == 0)
52 return readl(base
+ RDR_OFFSET(stm32f4
));
55 static int stm32_serial_putc(struct udevice
*dev
, const char c
)
57 struct stm32x7_serial_platdata
*plat
= dev_get_platdata(dev
);
58 bool stm32f4
= plat
->uart_info
->stm32f4
;
59 fdt_addr_t base
= plat
->base
;
61 if ((readl(base
+ ISR_OFFSET(stm32f4
)) & USART_SR_FLAG_TXE
) == 0)
64 writel(c
, base
+ TDR_OFFSET(stm32f4
));
69 static int stm32_serial_pending(struct udevice
*dev
, bool input
)
71 struct stm32x7_serial_platdata
*plat
= dev_get_platdata(dev
);
72 bool stm32f4
= plat
->uart_info
->stm32f4
;
73 fdt_addr_t base
= plat
->base
;
76 return readl(base
+ ISR_OFFSET(stm32f4
)) &
77 USART_SR_FLAG_RXNE
? 1 : 0;
79 return readl(base
+ ISR_OFFSET(stm32f4
)) &
80 USART_SR_FLAG_TXE
? 0 : 1;
83 static int stm32_serial_probe(struct udevice
*dev
)
85 struct stm32x7_serial_platdata
*plat
= dev_get_platdata(dev
);
87 fdt_addr_t base
= plat
->base
;
92 plat
->uart_info
= (struct stm32_uart_info
*)dev_get_driver_data(dev
);
93 stm32f4
= plat
->uart_info
->stm32f4
;
94 uart_enable_bit
= plat
->uart_info
->uart_enable_bit
;
96 ret
= clk_get_by_index(dev
, 0, &clk
);
100 ret
= clk_enable(&clk
);
102 dev_err(dev
, "failed to enable clock\n");
106 plat
->clock_rate
= clk_get_rate(&clk
);
107 if (plat
->clock_rate
< 0) {
109 return plat
->clock_rate
;
112 /* Disable uart-> disable overrun-> enable uart */
113 clrbits_le32(base
+ CR1_OFFSET(stm32f4
), USART_CR1_RE
| USART_CR1_TE
|
114 BIT(uart_enable_bit
));
115 if (plat
->uart_info
->has_overrun_disable
)
116 setbits_le32(base
+ CR3_OFFSET(stm32f4
), USART_CR3_OVRDIS
);
117 if (plat
->uart_info
->has_fifo
)
118 setbits_le32(base
+ CR1_OFFSET(stm32f4
), USART_CR1_FIFOEN
);
119 setbits_le32(base
+ CR1_OFFSET(stm32f4
), USART_CR1_RE
| USART_CR1_TE
|
120 BIT(uart_enable_bit
));
125 static const struct udevice_id stm32_serial_id
[] = {
126 { .compatible
= "st,stm32-uart", .data
= (ulong
)&stm32f4_info
},
127 { .compatible
= "st,stm32f7-uart", .data
= (ulong
)&stm32f7_info
},
128 { .compatible
= "st,stm32h7-uart", .data
= (ulong
)&stm32h7_info
},
132 static int stm32_serial_ofdata_to_platdata(struct udevice
*dev
)
134 struct stm32x7_serial_platdata
*plat
= dev_get_platdata(dev
);
136 plat
->base
= devfdt_get_addr(dev
);
137 if (plat
->base
== FDT_ADDR_T_NONE
)
143 static const struct dm_serial_ops stm32_serial_ops
= {
144 .putc
= stm32_serial_putc
,
145 .pending
= stm32_serial_pending
,
146 .getc
= stm32_serial_getc
,
147 .setbrg
= stm32_serial_setbrg
,
150 U_BOOT_DRIVER(serial_stm32
) = {
151 .name
= "serial_stm32",
153 .of_match
= of_match_ptr(stm32_serial_id
),
154 .ofdata_to_platdata
= of_match_ptr(stm32_serial_ofdata_to_platdata
),
155 .platdata_auto_alloc_size
= sizeof(struct stm32x7_serial_platdata
),
156 .ops
= &stm32_serial_ops
,
157 .probe
= stm32_serial_probe
,
158 .flags
= DM_FLAG_PRE_RELOC
,