123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561 |
- /*
- * Copyright (c) 2019 Winner Microelectronics Co., Ltd.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2018-09-15 flyingcys 1st version
- */
- #include <rtthread.h>
- #include <rtdevice.h>
- #include "board.h"
- #include "wm_io.h"
- #include "wm_uart.h"
- #include "wm_gpio_afsel.h"
- #include "wm_type_def.h"
- #include "wm_cpu.h"
- #include "drv_uart.h"
- #include "pin_map.h"
- #define WM600_UART0 (TLS_UART_REGS_T *) HR_UART0_BASE_ADDR
- #define WM600_UART1 (TLS_UART_REGS_T *) HR_UART1_BASE_ADDR
- #define WM600_UART2 (TLS_UART_REGS_T *) HR_UART2_BASE_ADDR
- static void wm_uart_reg_init(TLS_UART_REGS_T *UARTx)
- {
- RT_ASSERT(UARTx == WM600_UART0 || UARTx == WM600_UART1 || UARTx == WM600_UART2);
- if (UARTx == WM600_UART0)
- {
- /* disable auto flow control */
- tls_reg_write32(HR_UART0_FLOW_CTRL, 0);
- /* disable dma */
- tls_reg_write32(HR_UART0_DMA_CTRL, 0);
- /* one byte tx */
- tls_reg_write32(HR_UART0_FIFO_CTRL, 0);
- /* disable interrupt */
- tls_reg_write32(HR_UART0_INT_MASK, 0xFF);
- /* enable rx/timeout interrupt */
- tls_reg_write32(HR_UART0_INT_MASK, ~(3 << 2));
- }
- else if (UARTx == WM600_UART1)
- {
- /* 4 byte tx, 8 bytes rx */
- tls_reg_write32(HR_UART1_FIFO_CTRL, (0x01 << 2) | (0x02 << 4));
- /* enable rx timeout, disable rx dma, disable tx dma */
- tls_reg_write32(HR_UART1_DMA_CTRL, (8 << 3) | (1 << 2));
- /* enable rx/timeout interrupt */
- tls_reg_write32(HR_UART1_INT_MASK, ~(3 << 2));
- }
- else if (UARTx == WM600_UART2)
- {
- /* 4 byte tx, 8 bytes rx */
- tls_reg_write32(HR_UART2_FIFO_CTRL, (0x01 << 2) | (0x02 << 4));
- /* enable rx timeout, disable rx dma, disable tx dma */
- tls_reg_write32(HR_UART2_DMA_CTRL, (8 << 3) | (1 << 2));
- /* enable rx/timeout interrupt */
- tls_reg_write32(HR_UART2_INT_MASK, ~(3 << 2));
- UARTx->UR_LC &= ~(0x1000000);
- }
- }
- static void wm_uart_gpio_config(TLS_UART_REGS_T *UARTx)
- {
- #if defined(BSP_USING_UART1) || defined(BSP_USING_UART2)
- rt_int16_t gpio_pin;
- #endif
- RT_ASSERT(UARTx == WM600_UART0 || UARTx == WM600_UART1 || UARTx == WM600_UART2);
- if (UARTx == WM600_UART0)
- {
- /* UART0_TX-PA04 UART0_RX-PA05 */
- wm_uart0_tx_config(WM_IO_PA_04);
- wm_uart0_rx_config(WM_IO_PA_05);
- }
- #ifdef BSP_USING_UART1
- else if (UARTx == WM600_UART1)
- {
- gpio_pin = wm_get_pin(WM_UART1_RX_PIN);
- if (gpio_pin >= 0)
- {
- wm_uart1_rx_config((enum tls_io_name)gpio_pin);
- }
- gpio_pin = wm_get_pin(WM_UART1_TX_PIN);
- if (gpio_pin >= 0)
- {
- wm_uart1_tx_config((enum tls_io_name)gpio_pin);
- }
- }
- #endif
- #ifdef BSP_USING_UART2
- else if (UARTx == WM600_UART2)
- {
- gpio_pin = wm_get_pin(WM_UART2_RX_PIN);
- if (gpio_pin >= 0)
- {
- wm_uart2_rx_config((enum tls_io_name)gpio_pin);
- }
- gpio_pin = wm_get_pin(WM_UART2_TX_PIN);
- if (gpio_pin >= 0)
- {
- wm_uart2_tx_scio_config((enum tls_io_name)gpio_pin);
- }
- }
- #endif
- }
- static void wm_uart_irq_config(TLS_UART_REGS_T *UARTx)
- {
- RT_ASSERT(UARTx == WM600_UART0 || UARTx == WM600_UART1 || UARTx == WM600_UART2);
- /* config uart interrupt register */
- /* clear interrupt */
- UARTx->UR_INTS = 0xFFFFFFFF;
- /* enable interupt */
- UARTx->UR_INTM = 0x0;
- UARTx->UR_DMAC = (4UL << UDMA_RX_FIFO_TIMEOUT_SHIFT) | UDMA_RX_FIFO_TIMEOUT;
- /* config FIFO control */
- UARTx->UR_FIFOC = UFC_TX_FIFO_LVL_16_BYTE | UFC_RX_FIFO_LVL_16_BYTE | UFC_TX_FIFO_RESET | UFC_RX_FIFO_RESET;
- UARTx->UR_LC &= ~(ULCON_TX_EN | ULCON_RX_EN);
- UARTx->UR_LC |= ULCON_TX_EN | ULCON_RX_EN;
- }
- static int wm_uart_baudrate_set(TLS_UART_REGS_T *UARTx, u32 baudrate)
- {
- u32 value;
- u32 apbclk;
- tls_sys_clk sysclk;
- RT_ASSERT(UARTx == WM600_UART0 || UARTx == WM600_UART1 || UARTx == WM600_UART2);
- tls_sys_clk_get(&sysclk);
- apbclk = sysclk.apbclk * 1000000;
- value = (apbclk / (16 * baudrate) - 1) |
- (((apbclk % (baudrate * 16)) * 16 / (baudrate * 16)) << 16);
- UARTx->UR_BD = value;
- return WM_SUCCESS;
- }
- static int wm_uart_parity_set(TLS_UART_REGS_T *UARTx, TLS_UART_PMODE_T paritytype)
- {
- RT_ASSERT(UARTx == WM600_UART0 || UARTx == WM600_UART1 || UARTx == WM600_UART2);
- if (paritytype == TLS_UART_PMODE_DISABLED)
- UARTx->UR_LC &= ~ULCON_PMD_EN;
- else if (paritytype == TLS_UART_PMODE_EVEN)
- {
- UARTx->UR_LC &= ~ULCON_PMD_MASK;
- UARTx->UR_LC |= ULCON_PMD_EVEN;
- }
- else if (paritytype == TLS_UART_PMODE_ODD)
- {
- UARTx->UR_LC &= ~ULCON_PMD_MASK;
- UARTx->UR_LC |= ULCON_PMD_ODD;
- }
- else
- return WM_FAILED;
- return WM_SUCCESS;
- }
- static int wm_uart_stopbits_set(TLS_UART_REGS_T *UARTx, TLS_UART_STOPBITS_T stopbits)
- {
- RT_ASSERT(UARTx == WM600_UART0 || UARTx == WM600_UART1 || UARTx == WM600_UART2);
- if (stopbits == TLS_UART_TWO_STOPBITS)
- UARTx->UR_LC |= ULCON_STOP_2;
- else
- UARTx->UR_LC &= ~ULCON_STOP_2;
- return WM_SUCCESS;
- }
- static int wm_uart_databits_set(TLS_UART_REGS_T *UARTx, TLS_UART_CHSIZE_T charlength)
- {
- RT_ASSERT(UARTx == WM600_UART0 || UARTx == WM600_UART1 || UARTx == WM600_UART2);
- UARTx->UR_LC &= ~ULCON_WL_MASK;
- if (charlength == TLS_UART_CHSIZE_5BIT)
- UARTx->UR_LC |= ULCON_WL5;
- else if (charlength == TLS_UART_CHSIZE_6BIT)
- UARTx->UR_LC |= ULCON_WL6;
- else if (charlength == TLS_UART_CHSIZE_7BIT)
- UARTx->UR_LC |= ULCON_WL7;
- else if (charlength == TLS_UART_CHSIZE_8BIT)
- UARTx->UR_LC |= ULCON_WL8;
- else
- return WM_FAILED;
- return WM_SUCCESS;
- }
- static int wm_uart_flow_ctrl_set(TLS_UART_REGS_T *UARTx, TLS_UART_FLOW_CTRL_MODE_T flow_ctrl)
- {
- RT_ASSERT(UARTx == WM600_UART0 || UARTx == WM600_UART1 || UARTx == WM600_UART2);
- switch (flow_ctrl)
- {
- case TLS_UART_FLOW_CTRL_NONE:
- UARTx->UR_FC = 0;
- break;
- case TLS_UART_FLOW_CTRL_HARDWARE:
- UARTx->UR_FC = (1UL << 0) | (6UL << 2);
- break;
- default:
- break;
- }
- return WM_SUCCESS;
- }
- struct device_uart
- {
- TLS_UART_REGS_T volatile *uart_device;
- rt_uint32_t uart_irq_no;
- };
- static rt_err_t drv_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg);
- static rt_err_t drv_uart_control(struct rt_serial_device *serial, int cmd, void *arg);
- static int drv_uart_putc(struct rt_serial_device *serial, char c);
- static int drv_uart_getc(struct rt_serial_device *serial);
- static rt_size_t drv_uart_dma_transmit(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction);
- const struct rt_uart_ops _uart_ops =
- {
- drv_uart_configure,
- drv_uart_control,
- drv_uart_putc,
- drv_uart_getc,
- drv_uart_dma_transmit
- };
- /*
- * UART interface
- */
- static rt_err_t drv_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
- {
- struct device_uart *uart;
- u32 baud_rate;
- TLS_UART_PMODE_T parity;
- TLS_UART_STOPBITS_T stop_bits;
- TLS_UART_CHSIZE_T data_bits;
- RT_ASSERT(serial != RT_NULL && cfg != RT_NULL);
- serial->config = *cfg;
- uart = (struct device_uart *)serial->parent.user_data;
- RT_ASSERT(uart != RT_NULL);
- switch (cfg->baud_rate)
- {
- case BAUD_RATE_2000000:
- case BAUD_RATE_921600:
- case BAUD_RATE_460800:
- case BAUD_RATE_230400:
- case BAUD_RATE_115200:
- case BAUD_RATE_57600:
- case BAUD_RATE_38400:
- case BAUD_RATE_19200:
- case BAUD_RATE_9600:
- case BAUD_RATE_4800:
- case BAUD_RATE_2400:
- baud_rate = cfg->baud_rate;
- break;
- default:
- rt_kprintf("baudrate set failed... default rate:115200\r\n");
- baud_rate = BAUD_RATE_115200;
- break;
- }
- wm_uart_baudrate_set((TLS_UART_REGS_T *)uart->uart_device, baud_rate);
- switch (cfg->parity)
- {
- case PARITY_ODD:
- parity = TLS_UART_PMODE_ODD;
- break;
- case PARITY_EVEN:
- parity = TLS_UART_PMODE_EVEN;
- break;
- case PARITY_NONE:
- default:
- parity = TLS_UART_PMODE_DISABLED;
- break;
- }
- wm_uart_parity_set((TLS_UART_REGS_T *)uart->uart_device, parity);
- switch (cfg->stop_bits)
- {
- case STOP_BITS_2:
- stop_bits = TLS_UART_TWO_STOPBITS;
- break;
- case STOP_BITS_1:
- default:
- stop_bits = TLS_UART_ONE_STOPBITS;
- break;
- }
- wm_uart_stopbits_set((TLS_UART_REGS_T *)uart->uart_device, stop_bits);
- switch (cfg->data_bits)
- {
- case DATA_BITS_5:
- data_bits = TLS_UART_CHSIZE_5BIT;
- break;
- case DATA_BITS_6:
- data_bits = TLS_UART_CHSIZE_6BIT;
- break;
- case DATA_BITS_7:
- data_bits = TLS_UART_CHSIZE_7BIT;
- break;
- case DATA_BITS_8:
- default:
- data_bits = TLS_UART_CHSIZE_8BIT;
- break;
- }
- wm_uart_databits_set((TLS_UART_REGS_T *)uart->uart_device, data_bits);
- wm_uart_flow_ctrl_set((TLS_UART_REGS_T *)uart->uart_device, TLS_UART_FLOW_CTRL_NONE);
- return (RT_EOK);
- }
- static rt_err_t drv_uart_control(struct rt_serial_device *serial, int cmd, void *arg)
- {
- struct device_uart *uart;
- RT_ASSERT(serial != RT_NULL);
- uart = (struct device_uart *)serial->parent.user_data;
- RT_ASSERT(uart != RT_NULL);
- switch (cmd)
- {
- case RT_DEVICE_CTRL_CLR_INT:
- /* Disable the UART Interrupt */
- tls_irq_disable(uart->uart_irq_no);
- break;
- case RT_DEVICE_CTRL_SET_INT:
- /* Enable the UART Interrupt */
- tls_irq_enable(uart->uart_irq_no);
- break;
- }
- return (RT_EOK);
- }
- static int drv_uart_putc(struct rt_serial_device *serial, char c)
- {
- struct device_uart *uart;
- RT_ASSERT(serial != RT_NULL);
- uart = (struct device_uart *)serial->parent.user_data;
- RT_ASSERT(uart != RT_NULL);
- while (uart->uart_device->UR_FIFOS & 0x3F); /* wait THR is empty */
- uart->uart_device->UR_TXW = (char)c;
- return (1);
- }
- static int drv_uart_getc(struct rt_serial_device *serial)
- {
- int ch;
- struct device_uart *uart;
- RT_ASSERT(serial != RT_NULL);
- uart = (struct device_uart *)serial->parent.user_data;
- RT_ASSERT(uart != RT_NULL);
- ch = -1;
- if (uart->uart_device->UR_FIFOS & UFS_RX_FIFO_CNT_MASK)
- ch = (int)uart->uart_device->UR_RXW;
- return ch;
- }
- static rt_size_t drv_uart_dma_transmit(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction)
- {
- return (0);
- }
- static void drv_uart_irq_handler(struct rt_serial_device *serial)
- {
- u32 intr_src;
- struct device_uart *uart;
- RT_ASSERT(serial != RT_NULL);
- uart = (struct device_uart *)serial->parent.user_data;
- RT_ASSERT(uart != RT_NULL);
- /* check interrupt status */
- intr_src = uart->uart_device->UR_INTS;
- uart->uart_device->UR_INTS = intr_src;
- if ((intr_src & UART_RX_INT_FLAG) && (0 == (uart->uart_device->UR_INTM & UIS_RX_FIFO)))
- {
- rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
- }
- if (intr_src & UART_TX_INT_FLAG)
- {
- }
- if (intr_src & UIS_CTS_CHNG)
- {
- }
- }
- #ifdef BSP_USING_UART0
- static struct rt_serial_device serial0;
- static struct device_uart uart0 =
- {
- WM600_UART0,
- UART0_INT,
- };
- void UART0_IRQHandler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- drv_uart_irq_handler(&serial0);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- #ifdef BSP_USING_UART1
- static struct rt_serial_device serial1;
- static struct device_uart uart1 =
- {
- WM600_UART1,
- UART1_INT,
- };
- void UART1_IRQHandler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- drv_uart_irq_handler(&serial1);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- #ifdef BSP_USING_UART2
- static struct rt_serial_device serial2;
- static struct device_uart uart2 =
- {
- WM600_UART2,
- UART2_INT,
- };
- void UART2_IRQHandler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- drv_uart_irq_handler(&serial2);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- /*
- * UART Initiation
- */
- int wm_hw_uart_init(void)
- {
- struct rt_serial_device *serial;
- struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
- struct device_uart *uart;
- #ifdef BSP_USING_UART0
- {
- serial = &serial0;
- uart = &uart0;
- /* Init UART Hardware */
- wm_uart_gpio_config((TLS_UART_REGS_T *)uart->uart_device);
- wm_uart_reg_init((TLS_UART_REGS_T *)uart->uart_device);
- wm_uart_irq_config((TLS_UART_REGS_T *)uart->uart_device);
- serial->ops = &_uart_ops;
- serial->config = config;
- serial->config.baud_rate = 115200;
- rt_hw_serial_register(serial,
- "uart0",
- RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
- uart);
- }
- #endif /* BSP_USING_UART0 */
- #ifdef BSP_USING_UART1
- {
- serial = &serial1;
- uart = &uart1;
- /* Init UART Hardware */
- wm_uart_gpio_config((TLS_UART_REGS_T *)uart->uart_device);
- wm_uart_reg_init((TLS_UART_REGS_T *)uart->uart_device);
- wm_uart_irq_config((TLS_UART_REGS_T *)uart->uart_device);
- serial->ops = &_uart_ops;
- serial->config = config;
- serial->config.baud_rate = WM_UART1_BAUDRATE;
- rt_hw_serial_register(serial,
- "uart1",
- RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
- uart);
- }
- #endif /* BSP_USING_UART1 */
- #ifdef BSP_USING_UART2
- {
- serial = &serial2;
- uart = &uart2;
- /* Init UART Hardware */
- wm_uart_gpio_config((TLS_UART_REGS_T *)uart->uart_device);
- wm_uart_reg_init((TLS_UART_REGS_T *)uart->uart_device);
- wm_uart_irq_config((TLS_UART_REGS_T *)uart->uart_device);
- serial->ops = &_uart_ops;
- serial->config = config;
- serial->config.baud_rate = WM_UART2_BAUDRATE;
- rt_hw_serial_register(serial,
- "uart2",
- RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
- uart);
- }
- #endif /* BSP_USING_UART2 */
- return 0;
- }
- INIT_BOARD_EXPORT(wm_hw_uart_init);
|