123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350 |
- /*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2021-01-09 Lyons first version
- */
- #include <rtconfig.h>
- #ifdef RT_USING_SERIAL
- #include "board.h"
- #include "drv_uart.h"
- #include "drv_common.h"
- enum
- {
- #ifdef BSP_USING_UART1
- eDevUart_UART1,
- #endif
- #ifdef BSP_USING_UART2
- eDevUart_UART2,
- #endif
- #ifdef BSP_USING_UART3
- eDevUart_UART3,
- #endif
- #ifdef BSP_USING_UART4
- eDevUart_UART4,
- #endif
- #ifdef BSP_USING_UART5
- eDevUart_UART5,
- #endif
- #ifdef BSP_USING_UART6
- eDevUart_UART6,
- #endif
- #ifdef BSP_USING_UART7
- eDevUart_UART7,
- #endif
- #ifdef BSP_USING_UART8
- eDevUart_UART8,
- #endif
- eDevUart_Max,
- };
- _internal_rw struct imx_uart _s_uart[eDevUart_Max] = {
- #ifdef BSP_USING_UART1
- {
- .name = "uart0",
- .periph.paddr = IMX6ULL_UART1_BASE,
- .irqno = UART1_IRQn,
- .gpio = {
- {IOMUXC_UART1_TX_DATA_UART1_TX, 0, 0x10B0},
- {IOMUXC_UART1_RX_DATA_UART1_RX, 0, 0x10B0},
- },
- .flag = (RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX),
- .param = RT_SERIAL_CONFIG_115200N81,
- },
- #endif
- #ifdef BSP_USING_UART2
- {
- .name = "uart1",
- .periph.paddr = IMX6ULL_UART2_BASE,
- .irqno = UART2_IRQn,
- .gpio = {
- {IOMUXC_UART2_TX_DATA_UART2_TX, 0, 0x10B0},
- {IOMUXC_UART2_RX_DATA_UART2_RX, 0, 0x10B0},
- },
- .flag = (RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX),
- .param = RT_SERIAL_CONFIG_DEFAULT,
- },
- #endif
- #ifdef BSP_USING_UART3
- {
- .name = "uart2",
- .periph.paddr = IMX6ULL_UART3_BASE,
- .irqno = UART3_IRQn,
- .gpio = {
- {IOMUXC_UART3_TX_DATA_UART3_TX, 0, 0x10B0},
- {IOMUXC_UART3_RX_DATA_UART3_RX, 0, 0x10B0},
- },
- .flag = (RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX),
- .param = RT_SERIAL_CONFIG_DEFAULT,
- },
- #endif
- #ifdef BSP_USING_UART4
- {
- .name = "uart3",
- .periph.paddr = IMX6ULL_UART4_BASE,
- .irqno = UART4_IRQn,
- .gpio = {
- {IOMUXC_UART4_TX_DATA_UART4_TX, 0, 0x10B0},
- {IOMUXC_UART4_RX_DATA_UART4_RX, 0, 0x10B0},
- },
- .flag = (RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX),
- .param = RT_SERIAL_CONFIG_DEFAULT,
- },
- #endif
- #ifdef BSP_USING_UART5
- {
- .name = "uart4",
- .periph.paddr = IMX6ULL_UART5_BASE,
- .irqno = UART5_IRQn,
- .gpio = {
- {IOMUXC_UART5_TX_DATA_UART5_TX, 0, 0x10B0},
- {IOMUXC_UART5_RX_DATA_UART5_RX, 0, 0x10B0},
- },
- .flag = (RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX),
- .param = RT_SERIAL_CONFIG_DEFAULT,
- },
- #endif
- #ifdef BSP_USING_UART6
- {
- .name = "uart5",
- .periph.paddr = IMX6ULL_UART6_BASE,
- .irqno = UART6_IRQn,
- .gpio = {
- {IOMUXC_ENET2_RX_DATA1_UART6_TX, 0, 0x10B0},
- {IOMUXC_ENET2_RX_DATA0_UART6_RX, 0, 0x10B0},
- },
- .flag = (RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX),
- .param = RT_SERIAL_CONFIG_DEFAULT,
- },
- #endif
- #ifdef BSP_USING_UART7
- {
- .name = "uart6",
- .periph.paddr = IMX6ULL_UART7_BASE,
- .irqno = UART7_IRQn,
- .gpio = {
- {IOMUXC_ENET2_TX_DATA0_UART7_TX, 0, 0x10B0},
- {IOMUXC_ENET2_RX_EN_UART7_RX, 0, 0x10B0},
- },
- .flag = (RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX),
- .param = RT_SERIAL_CONFIG_DEFAULT,
- },
- #endif
- #ifdef BSP_USING_UART8
- {
- .name = "uart7",
- .periph.paddr = IMX6ULL_UART8_BASE,
- .irqno = UART8_IRQn,
- .gpio = {
- {IOMUXC_ENET2_TX_DATA1_UART8_TX, 0, 0x10B0},
- {IOMUXC_ENET2_TX_EN_UART8_RX, 0, 0x10B0},
- },
- .flag = (RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX),
- .param = RT_SERIAL_CONFIG_DEFAULT,
- },
- #endif
- };
- static void _uart_gpio_init( struct imx_uart *device )
- {
- for (int i=0; i<GET_ARRAY_NUM(device->gpio); i++)
- {
- imx6ull_gpio_init(&device->gpio[i]);
- }
- }
- static rt_err_t _uart_ops_configure( struct rt_serial_device *dev,
- struct serial_configure *cfg )
- {
- struct imx_uart *uart = RT_NULL;
- UART_Type *periph = RT_NULL;
- rt_uint32_t reg_value;
- RT_ASSERT(RT_NULL != dev);
- RT_ASSERT(RT_NULL != cfg);
- uart = (struct imx_uart*)dev;
- periph = (UART_Type*)uart->periph.vaddr;
- _uart_gpio_init(uart);
- periph->UCR1 &= ~UART_UCR1_UARTEN_MASK;
- periph->UFCR &= ~UART_UFCR_RFDIV_MASK;
- periph->UFCR |= UART_UFCR_RFDIV(5);
- RT_ASSERT(cfg->baud_rate <= BAUD_RATE_921600);
- periph->UBIR = UART_UBIR_INC(15);
- periph->UBMR = UART_UBMR_MOD(HW_UART_BUS_CLOCK / cfg->baud_rate - 1);
- reg_value = 0;
- switch (cfg->data_bits)
- {
- case DATA_BITS_7:
- reg_value |= UART_UCR2_WS(0);
- break;
- default:
- reg_value |= UART_UCR2_WS(1);
- break;
- }
- switch (cfg->stop_bits)
- {
- case STOP_BITS_2:
- reg_value |= UART_UCR2_STPB(1);
- break;
- default:
- reg_value |= UART_UCR2_STPB(0);
- break;
- }
- switch (cfg->parity)
- {
- case PARITY_ODD:
- reg_value |= UART_UCR2_PREN(1);
- reg_value |= UART_UCR2_PROE(1);
- break;
- case PARITY_EVEN:
- reg_value |= UART_UCR2_PREN(1);
- reg_value |= UART_UCR2_PROE(0);
- break;
- default:
- reg_value |= UART_UCR2_PREN(0);
- reg_value |= UART_UCR2_PROE(0);
- break;
- }
- periph->UCR3 |= UART_UCR3_RXDMUXSEL(1); //this bit should always be set!
- periph->UCR2 |= reg_value | UART_UCR2_IRTS(1) | UART_UCR2_TXEN(1) | UART_UCR2_RXEN(1);
- periph->UCR1 |= UART_UCR1_UARTEN(1);
- return RT_EOK;
- }
- static rt_err_t _uart_ops_control( struct rt_serial_device *dev,
- int cmd,
- void *arg )
- {
- struct imx_uart *uart = RT_NULL;
- UART_Type *periph = RT_NULL;
- rt_err_t result;
- RT_ASSERT(RT_NULL != dev);
- uart = (struct imx_uart*)dev;
- periph = (UART_Type*)uart->periph.vaddr;
- result = RT_EOK;
- switch (cmd)
- {
- case RT_DEVICE_CTRL_CLR_INT:
- periph->UCR4 &= ~UART_UCR4_DREN_MASK;
- periph->UCR4 |= UART_UCR4_DREN(0);
- break;
- case RT_DEVICE_CTRL_SET_INT:
- periph->UCR4 |= UART_UCR4_DREN(1);
- rt_hw_interrupt_umask(uart->irqno);
- break;
- default:
- result = -RT_EINVAL;
- break;
- }
- return result;
- }
- static int _uart_ops_putc( struct rt_serial_device *dev,
- char ch )
- {
- struct imx_uart *uart = RT_NULL;
- UART_Type *periph = RT_NULL;
- RT_ASSERT(RT_NULL != dev);
- uart = (struct imx_uart*)dev;
- periph = (UART_Type*)uart->periph.vaddr;
- while (0 == (periph->USR2 & UART_USR2_TXDC_MASK));
- periph->UTXD = ch;
- return 1;
- }
- static int _uart_ops_getc( struct rt_serial_device *dev )
- {
- struct imx_uart *uart = RT_NULL;
- UART_Type *periph = RT_NULL;
- int ch;
- RT_ASSERT(RT_NULL != dev);
- uart = (struct imx_uart*)dev;
- periph = (UART_Type*)uart->periph.vaddr;
- ch = (0 == (periph->USR2 & UART_USR2_RDR_MASK)) ? -1 : periph->URXD;
- return ch;
- }
- _internal_ro struct rt_uart_ops _k_uart_ops =
- {
- _uart_ops_configure, /* configure */
- _uart_ops_control, /* control */
- _uart_ops_putc, /* putc */
- _uart_ops_getc, /* getc */
- RT_NULL, /* dma_transmit */
- };
- static void _uart_isr( int irqno, void* parameter )
- {
- struct rt_serial_device *serial;
- rt_interrupt_enter();
- serial = (struct rt_serial_device *)parameter;
- rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
- rt_interrupt_leave();
- }
- int rt_hw_uart_init(void)
- {
- for (int idx=0; idx<GET_ARRAY_NUM(_s_uart); idx++)
- {
- _s_uart[idx].periph.vaddr = platform_get_periph_vaddr(_s_uart[idx].periph.paddr);
- _s_uart[idx].parent.ops = &_k_uart_ops;
- rt_memcpy(&_s_uart[idx].parent.config, &_s_uart[idx].param, sizeof(struct serial_configure));
- rt_hw_serial_register( &_s_uart[idx].parent,
- _s_uart[idx].name,
- _s_uart[idx].flag,
- RT_NULL );
- rt_hw_interrupt_install(_s_uart[idx].irqno, _uart_isr, &_s_uart[idx].parent, _s_uart[idx].name);
- }
- return RT_EOK;
- }
- INIT_BOARD_EXPORT(rt_hw_uart_init);
- #endif //#ifdef RT_USING_SERIAL
|