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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
/*
* Copyright (C) 2017-2024 Alibaba Group Holding Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <rthw.h>
#include <rtdevice.h>
#include <rtthread.h>
#include "board.h"
#include "drv_uart.h"
#ifdef RT_USING_SMART
#include <ioremap.h>
#endif
struct device_uart
{
rt_ubase_t hw_base;
rt_uint32_t irqno;
};
static void *uart0_base = (void *)XIAOHUI_UART0_PHY_ADDR;
static struct rt_serial_device serial0;
static struct device_uart uart0;
/* 32-bit stride register access */
rt_inline rt_uint32_t uart_read(int reg)
{
return *(volatile rt_uint32_t *)((rt_ubase_t)uart0_base + ((rt_ubase_t)reg << 2));
}
rt_inline void uart_write(int reg, rt_uint32_t val)
{
*(volatile rt_uint32_t *)((rt_ubase_t)uart0_base + ((rt_ubase_t)reg << 2)) = val;
}
static rt_err_t _uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
{
/* the boot firmware/QEMU model already configured the line; enable FIFO */
uart_write(UART_FCR, UART_FCR_FIFO_ENABLE | UART_FCR_FIFO_CLEAR);
return RT_EOK;
}
static rt_err_t _uart_control(struct rt_serial_device *serial, int cmd, void *arg)
{
switch (cmd)
{
case RT_DEVICE_CTRL_CLR_INT:
if ((size_t)arg == RT_DEVICE_FLAG_INT_RX)
{
uart_write(UART_IER, uart_read(UART_IER) & ~UART_IER_RX_ENABLE);
}
break;
case RT_DEVICE_CTRL_SET_INT:
if ((size_t)arg == RT_DEVICE_FLAG_INT_RX)
{
uart_write(UART_IER, uart_read(UART_IER) | UART_IER_RX_ENABLE);
}
break;
}
return RT_EOK;
}
static int _uart_putc(struct rt_serial_device *serial, char c)
{
while ((uart_read(UART_LSR) & UART_LSR_TX_IDLE) == 0);
uart_write(UART_THR, (rt_uint32_t)(rt_uint8_t)c);
return 1;
}
static int _uart_getc(struct rt_serial_device *serial)
{
int ch = -1;
if (uart_read(UART_LSR) & UART_LSR_RX_READY)
{
ch = (int)(uart_read(UART_RHR) & 0xFF);
}
return ch;
}
static const struct rt_uart_ops _uart_ops = {
_uart_configure,
_uart_control,
_uart_putc,
_uart_getc,
RT_NULL,
};
static void _uart_isr(int irqno, void *param)
{
struct rt_serial_device *serial = (struct rt_serial_device *)param;
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
}
/*
* UART Initiation
*/
int rt_hw_uart_init(void)
{
struct rt_serial_device *serial;
struct device_uart *uart;
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
#ifdef RT_USING_SMART
uart0_base = rt_ioremap((void *)XIAOHUI_UART0_PHY_ADDR, 4096);
#endif
serial = &serial0;
uart = &uart0;
serial->ops = &_uart_ops;
serial->config = config;
serial->config.baud_rate = 115200;
uart->hw_base = (rt_ubase_t)uart0_base;
uart->irqno = XIAOHUI_UART0_IRQ;
rt_hw_serial_register(serial,
RT_CONSOLE_DEVICE_NAME,
RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
uart);
rt_hw_interrupt_install(uart->irqno, _uart_isr, serial, RT_CONSOLE_DEVICE_NAME);
rt_hw_interrupt_umask(uart->irqno);
return 0;
}
|