blob: 53d9c1e639defa094df50f8ee70fd111ba670507 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
|
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright (c) 2017-2018, STMicroelectronics
*/
#include <compiler.h>
#include <drivers/serial.h>
#include <drivers/stm32_uart.h>
#include <io.h>
#include <keep.h>
#include <kernel/delay.h>
#include <util.h>
#define UART_REG_CR1 0x00 /* Control register 1 */
#define UART_REG_CR2 0x04 /* Control register 2 */
#define UART_REG_CR3 0x08 /* Control register 3 */
#define UART_REG_BRR 0x0c /* Baud rate register */
#define UART_REG_RQR 0x18 /* Request register */
#define UART_REG_ISR 0x1c /* Interrupt & status reg. */
#define UART_REG_ICR 0x20 /* Interrupt flag clear reg. */
#define UART_REG_RDR 0x24 /* Receive data register */
#define UART_REG_TDR 0x28 /* Transmit data register */
#define UART_REG_PRESC 0x2c /* Prescaler register */
#define PUTC_TIMEOUT_US 1000
#define FLUSH_TIMEOUT_US 16000
/*
* Uart Interrupt & status register bits
*
* Bit 5 RXNE: Read data register not empty/RXFIFO not empty
* Bit 6 TC: Transmission complete
* Bit 7 TXE/TXFNF: Transmit data register empty/TXFIFO not full
* Bit 27 TXFE: TXFIFO threshold reached
*/
#define USART_ISR_RXNE_RXFNE BIT(5)
#define USART_ISR_TC BIT(6)
#define USART_ISR_TXE_TXFNF BIT(7)
#define USART_ISR_TXFE BIT(27)
static vaddr_t loc_chip_to_base(struct serial_chip *chip)
{
struct console_pdata *pd =
container_of(chip, struct console_pdata, chip);
return io_pa_or_va(&pd->base);
}
static void loc_flush(struct serial_chip *chip)
{
vaddr_t base = loc_chip_to_base(chip);
uint64_t timeout = timeout_init_us(FLUSH_TIMEOUT_US);
while (!(read32(base + UART_REG_ISR) & USART_ISR_TXFE))
if (timeout_elapsed(timeout))
return;
}
static void loc_putc(struct serial_chip *chip, int ch)
{
vaddr_t base = loc_chip_to_base(chip);
uint64_t timeout = timeout_init_us(PUTC_TIMEOUT_US);
while (!(read32(base + UART_REG_ISR) & USART_ISR_TXE_TXFNF))
if (timeout_elapsed(timeout))
return;
write32(ch, base + UART_REG_TDR);
}
static bool loc_have_rx_data(struct serial_chip *chip)
{
vaddr_t base = loc_chip_to_base(chip);
return read32(base + UART_REG_ISR) & USART_ISR_RXNE_RXFNE;
}
static int loc_getchar(struct serial_chip *chip)
{
vaddr_t base = loc_chip_to_base(chip);
while (!loc_have_rx_data(chip))
;
return read32(base + UART_REG_RDR) & 0xff;
}
static const struct serial_ops serial_ops = {
.flush = loc_flush,
.putc = loc_putc,
.have_rx_data = loc_have_rx_data,
.getchar = loc_getchar,
};
KEEP_PAGER(serial_ops);
void stm32_uart_init(struct console_pdata *pd, vaddr_t base)
{
pd->base.pa = base;
pd->chip.ops = &serial_ops;
}
|