drv_uart.c 5.8 KB
Newer Older
B
bigmagic 已提交
1 2 3 4 5 6 7 8
/*
 * Copyright (c) 2006-2020, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2020-04-05     bigmagic     Initial version
9
 * 2020-10-28     ma           Buadrate & Multi-Port support
B
bigmagic 已提交
10 11 12 13 14 15 16 17 18 19 20
 */
/**
 * @addtogroup ls2k
 */
/*@{*/
#include <rtthread.h>
#include <rtdevice.h>
#include <rthw.h>
#include "drv_uart.h"
#define TRUE 1
#define FALSE 0
21 22 23 24 25 26 27 28 29 30
const struct serial_configure config_uart0 = {                                          
    BAUD_RATE_115200, /* 921600 bits/s */  
    DATA_BITS_8,      /* 8 databits */     
    STOP_BITS_1,      /* 1 stopbit */      
    PARITY_NONE,      /* No parity  */     
    BIT_ORDER_LSB,    /* LSB first sent */ 
    NRZ_NORMAL,       /* Normal mode */    
    RT_SERIAL_RB_BUFSZ, /* Buffer size */  
    0                                      
};
B
bigmagic 已提交
31 32 33 34 35
struct rt_uart_ls2k
{
    void *base;
    rt_uint32_t IRQ;
};
0
0xcccccccccccc 已提交
36
static rt_err_t ls2k_uart_set_buad(struct rt_serial_device *serial, struct serial_configure *cfg)
37 38
{
    struct rt_uart_ls2k *uart_dev = RT_NULL;
0
0xcccccccccccc 已提交
39
    rt_err_t ret = RT_EOK;
40 41 42
    RT_ASSERT(serial != RT_NULL);
    RT_ASSERT(cfg != RT_NULL);
    uart_dev = (struct rt_uart_ls2k *)serial->parent.user_data;
0
0xcccccccccccc 已提交
43 44 45 46 47 48 49 50
    uint64_t brtc = (125000000U) / (16 * (cfg->baud_rate));
    UART_LCR(uart_dev->base) = 0x80; // Activate buadcfg
    UART_LSB(uart_dev->base) = brtc & 0xff;
    UART_MSB(uart_dev->base) = brtc >> 8;
    if (((((short)UART_MSB(uart_dev->base)) << 8) | UART_LSB(uart_dev->base)) != brtc) ret = RT_ERROR;
    UART_LCR(uart_dev->base) = CFCR_8BITS; // Back to normal
    UART_MCR(uart_dev->base) = MCR_IENABLE/* | MCR_DTR | MCR_RTS*/;
    UART_IER(uart_dev->base) = 0;
51
}
B
bigamgic 已提交
52
static rt_err_t ls2k_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
B
bigmagic 已提交
53 54 55 56
{
    struct rt_uart_ls2k *uart_dev = RT_NULL;
    RT_ASSERT(serial != RT_NULL);
    RT_ASSERT(cfg != RT_NULL);
0
0xcccccccccccc 已提交
57
    ls2k_uart_set_buad(serial, cfg);
B
bigmagic 已提交
58
    uart_dev = (struct rt_uart_ls2k *)serial->parent.user_data;
0
0xcccccccccccc 已提交
59
    HWREG8(0xffffffffbfe10428) = 0x1f; // Enable Multi-Port Support, by default it's 0x11 ,which means UART0 & UART4 Controller is in single port mode.
B
bigmagic 已提交
60 61 62 63 64 65 66 67 68
    UART_IER(uart_dev->base) = 0; /* clear interrupt */
    UART_FCR(uart_dev->base) = 0xc1; /* reset UART Rx/Tx */
    /* set databits, stopbits and parity. (8-bit data, 1 stopbit, no parity) */
    UART_LCR(uart_dev->base) = 0x3;
    UART_MCR(uart_dev->base) = 0x3;
    UART_LSR(uart_dev->base) = 0x60;
    UART_MSR(uart_dev->base) = 0xb0;
    return RT_EOK;
}
B
bigamgic 已提交
69
static rt_err_t ls2k_uart_control(struct rt_serial_device *serial, int cmd, void *arg)
B
bigmagic 已提交
70 71 72 73 74 75 76 77 78 79 80
{
    struct rt_uart_ls2k *uart_dev = RT_NULL;
    RT_ASSERT(serial != RT_NULL);
    uart_dev = (struct rt_uart_ls2k *)serial->parent.user_data;
    switch (cmd)
    {
    case RT_DEVICE_CTRL_CLR_INT: /* Disable RX IRQ */
        rt_hw_interrupt_mask(uart_dev->IRQ);
        break;
    case RT_DEVICE_CTRL_SET_INT: /* Enable RX IRQ */
        rt_hw_interrupt_umask(uart_dev->IRQ);
0
0xcccccccccccc 已提交
81
        UART_IER(uart_dev->base) |= (IER_IRxE | IER_ILE);
B
bigmagic 已提交
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
        break;
    default:
        break;
    }
    return RT_EOK;
}
static rt_bool_t uart_is_transmit_empty(struct rt_uart_ls2k *uart_dev)
{
    unsigned char status = UART_LSR(uart_dev->base);
    if (status & (UARTLSR_TE | UARTLSR_TFE))
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}
B
bigamgic 已提交
100
static int ls2k_uart_putc(struct rt_serial_device *serial, char c)
B
bigmagic 已提交
101 102 103 104 105 106 107 108 109
{
    struct rt_uart_ls2k *uart_dev = RT_NULL;
    RT_ASSERT(serial != RT_NULL);
    uart_dev = (struct rt_uart_ls2k *)serial->parent.user_data;
    while (FALSE == uart_is_transmit_empty(uart_dev))
        ;
    UART_DAT(uart_dev->base) = c;
    return 1;
}
B
bigamgic 已提交
110
static int ls2k_uart_getc(struct rt_serial_device *serial)
B
bigmagic 已提交
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
{
    struct rt_uart_ls2k *uart_dev = RT_NULL;
    RT_ASSERT(serial != RT_NULL);
    uart_dev = (struct rt_uart_ls2k *)serial->parent.user_data;
    if (LSR_RXRDY & UART_LSR(uart_dev->base))
    {
        return UART_DAT(uart_dev->base);
    }
    return -1;
}
/* UART interrupt handler */
static void uart_irq_handler(int vector, void *param)
{
    struct rt_serial_device *serial = (struct rt_serial_device *)param;
    struct rt_uart_ls2k *uart_dev = RT_NULL;
    RT_ASSERT(serial != RT_NULL);
    uart_dev = (struct rt_uart_ls2k *)serial->parent.user_data;
    unsigned char iir = UART_IIR(uart_dev->base);
    /* Find out interrupt reason */
    if ((IIR_RXTOUT & iir) || (IIR_RXRDY & iir))
    {
        rt_interrupt_enter();
        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
        rt_interrupt_leave();
    }
}
B
bigamgic 已提交
137
static const struct rt_uart_ops ls2k_uart_ops =
B
bigmagic 已提交
138
{
B
bigamgic 已提交
139 140 141 142
    ls2k_uart_configure,
    ls2k_uart_control,
    ls2k_uart_putc,
    ls2k_uart_getc,
B
bigmagic 已提交
143 144 145
};
struct rt_uart_ls2k uart_dev0 =
{
B
bigamgic 已提交
146 147
    (void *)UARTx_BASE(0),
    LS2K_UART_0_1_2_3_IRQ,
B
bigmagic 已提交
148
};
149 150 151
struct rt_uart_ls2k uart_dev4 =
{
    (void *)UARTx_BASE(4),
0
0xcccccccccccc 已提交
152
    LS2K_UART_4_5_6_7_IRQ,
153 154
};

0
0xcccccccccccc 已提交
155
struct rt_serial_device serial, serial4;
B
bigmagic 已提交
156 157 158 159

void rt_hw_uart_init(void)
{
    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
0
0xcccccccccccc 已提交
160

M
michael 已提交
161 162 163
#ifdef RT_USING_UART0
    struct rt_uart_ls2k *uart0;
    uart0 = &uart_dev0;
B
bigamgic 已提交
164
    serial.ops    = &ls2k_uart_ops;
165
    serial.config = config_uart0;
B
bigmagic 已提交
166

M
michael 已提交
167
    rt_hw_interrupt_install(uart0->IRQ, uart_irq_handler, &serial, "UART0");
B
bigmagic 已提交
168 169
    /* register UART device */
    rt_hw_serial_register(&serial,
170
                          "uart0",
B
bigmagic 已提交
171
                          RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
M
michael 已提交
172 173 174 175 176 177 178 179 180
                          uart0);
#endif

#ifdef RT_USING_UART4
    struct rt_uart_ls2k *uart4;
    uart4 = &uart_dev4;
    serial4.ops = &ls2k_uart_ops;
    serial4.config = config;
    rt_hw_interrupt_install(uart4->IRQ, uart_irq_handler, &serial4, "UART4");
181 182
    rt_hw_serial_register(&serial4,
                          "uart4",
0
0xcccccccccccc 已提交
183
                          RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
184
                          &uart_dev4);
M
michael 已提交
185
#endif
B
bigmagic 已提交
186 187
}
/*@}*/