99#include <rtdevice.h>
1010#include <lwp_user_mm.h>
1111#include <ioremap.h>
12-
12+ #include <rtdbg.h>
1313#include "board.h"
14+ #include "drv_pdma.h"
15+ #include <mmu.h>
1416#include "drv_uart.h"
1517#include "riscv_io.h"
1618
19+ typedef enum
20+ {
21+ TEST_PDMA_EVENT_NONE ,
22+ TEST_PDMA_EVENT_COMPLETE ,
23+ TEST_PDMA_EVENT_TIMEOUT
24+ } test_pdma_event_t ;
25+
26+ static rt_event_t uart_pdma_event = RT_NULL ;
27+
28+ void uart_pdma_call_back (rt_uint8_t ch , rt_bool_t is_done )
29+ {
30+ /* Send completion or timeout event based on callback status */
31+ test_pdma_event_t event_type = is_done ? TEST_PDMA_EVENT_COMPLETE : TEST_PDMA_EVENT_TIMEOUT ;
32+ rt_event_send (uart_pdma_event , event_type );
33+ }
34+
1735#define UART_DEFAULT_BAUDRATE 115200
1836#define UART_CLK 50000000
19- #define UART_ADDR UART0_BASE_ADDR
20- #define UART_IRQ K230_IRQ_UART0
21-
37+ #define UART0_IRQ K230_IRQ_UART0
38+ #define UART1_IRQ K230_IRQ_UART1
39+ #define UART2_IRQ K230_IRQ_UART2
40+ #define UART3_IRQ K230_IRQ_UART3
41+ #define UART4_IRQ K230_IRQ_UART4
2242
2343#define UART_RBR (0x00) /* receive buffer register */
2444#define UART_THR (0x00) /* transmit holding register */
@@ -95,25 +115,81 @@ struct device_uart
95115 rt_ubase_t hw_base ;
96116 void * pa_base ;
97117 rt_uint32_t irqno ;
118+
98119};
99120
100121static rt_err_t rt_uart_configure (struct rt_serial_device * serial , struct serial_configure * cfg );
101122static rt_err_t uart_control (struct rt_serial_device * serial , int cmd , void * arg );
102123static int drv_uart_putc (struct rt_serial_device * serial , char c );
103124static int drv_uart_getc (struct rt_serial_device * serial );
125+ static rt_ssize_t uart_dma_tran (struct rt_serial_device * serial , rt_uint8_t * buf , rt_size_t size , int direction );
104126
105- const struct rt_uart_ops _uart_ops =
127+ const struct rt_uart_ops _uart_ops =
106128{
107- rt_uart_configure ,
108- uart_control ,
109- drv_uart_putc ,
110- drv_uart_getc ,
111- //TODO: add DMA support
112- RT_NULL
129+ .configure = rt_uart_configure ,
130+ .control = uart_control ,
131+ .putc = drv_uart_putc ,
132+ .getc = drv_uart_getc ,
133+ .dma_transmit = uart_dma_tran
113134};
114135
115- struct rt_serial_device serial1 ;
116- struct device_uart uart1 ;
136+ struct k230_uart_dev
137+ {
138+ struct rt_serial_device serial ;
139+ struct device_uart uart ;
140+ const char * name ;
141+ rt_uint32_t pa_base ;
142+ rt_uint32_t uart_to_size ;
143+ rt_uint32_t irqno ;
144+ };
145+
146+ /* 支持的 UART 设备列表 */
147+ static struct k230_uart_dev uart_devs [] =
148+ {
149+ #ifdef BSP_USING_UART0
150+ {
151+ .name = "uart0" ,
152+ .pa_base = UART0_BASE_ADDR ,
153+ .uart_to_size = UART0_IO_SIZE ,
154+ .irqno = UART0_IRQ ,
155+ },
156+ #endif
157+ #ifdef BSP_USING_UART1
158+ {
159+ .name = "uart1" ,
160+ .pa_base = UART1_BASE_ADDR ,
161+ .uart_to_size = UART1_IO_SIZE ,
162+ .irqno = UART1_IRQ ,
163+ },
164+ #endif
165+ #ifdef BSP_USING_UART2
166+ {
167+ .name = "uart2" ,
168+ .pa_base = UART2_BASE_ADDR ,
169+ .uart_to_size = UART2_IO_SIZE ,
170+ .irqno = UART2_IRQ ,
171+ },
172+ #endif
173+ #ifdef BSP_USING_UART3
174+ {
175+ .name = "uart3" ,
176+ .pa_base = UART3_BASE_ADDR ,
177+ .uart_to_size = UART3_IO_SIZE ,
178+ .irqno = UART3_IRQ ,
179+ },
180+ #endif
181+ #ifdef BSP_USING_UART4
182+ {
183+ .name = "uart4" ,
184+ .pa_base = UART4_BASE_ADDR ,
185+ .uart_to_size = UART4_IO_SIZE ,
186+ .irqno = UART4_IRQ ,
187+ },
188+ #endif
189+ #if !defined (BSP_USING_UART0 ) && !defined (BSP_USING_UART1 ) && !defined (BSP_USING_UART2 ) && !defined (BSP_USING_UART3 ) && !defined (BSP_USING_UART4 )
190+ #error "No UART device defined!"
191+ #endif
192+ };
117193
118194#define write32 (addr , val ) writel(val, (void*)(addr))
119195#define read32 (addr ) readl((void*)(addr))
@@ -150,7 +226,8 @@ static void _uart_init(void *uart_base)
150226 write32 (uart_base + UART_IER , 0x00 );
151227 /* Enable DLAB */
152228 write32 (uart_base + UART_LCR , 0x80 );
153- if (bdiv ) {
229+ if (bdiv )
230+ {
154231 /* Set divisor low byte */
155232 write32 (uart_base + UART_DLL , dll );
156233 /* Set divisor high byte */
@@ -301,6 +378,109 @@ static int drv_uart_getc(struct rt_serial_device *serial)
301378 return (int )* rbr ;
302379}
303380
381+ static rt_ssize_t uart_dma_write (struct rt_serial_device * serial , const void * buffer , rt_size_t size )
382+ {
383+ rt_uint8_t ch ;
384+ rt_err_t err ;
385+ rt_uint32_t recv_event ;
386+
387+ struct k230_uart_dev * uart_dev = rt_container_of (serial , struct k230_uart_dev , serial );
388+ uint32_t len = RT_ALIGN (size , 64 );
389+ uint8_t * buf = rt_malloc_align (len , 64 );
390+ rt_memcpy (buf , buffer , size );
391+ rt_hw_cpu_dcache_clean ((void * )buf , len );
392+ void * buf_pa = rt_kmem_v2p (buf );
393+ rt_event_control (uart_pdma_event , RT_IPC_CMD_RESET , NULL );
394+
395+ /* Configure DMA transfer */
396+ err = k230_pdma_request_channel (& ch );
397+
398+ usr_pdma_cfg_t pdma_cfg ;
399+ /* Configure DMA parameters */
400+ if (!strcmp (uart_dev -> name , "uart0" ))
401+ {
402+ pdma_cfg .device = UART0_TX ;
403+ }
404+ else if (!strcmp (uart_dev -> name , "uart1" ))
405+ {
406+ pdma_cfg .device = UART1_TX ;
407+ }
408+ else if (!strcmp (uart_dev -> name , "uart2" ))
409+ {
410+ pdma_cfg .device = UART2_TX ;
411+ }
412+ else if (!strcmp (uart_dev -> name , "uart3" ))
413+ {
414+ pdma_cfg .device = UART3_TX ;
415+ }
416+ else if (!strcmp (uart_dev -> name , "uart4" ))
417+ {
418+ pdma_cfg .device = UART4_TX ;
419+ }
420+
421+ pdma_cfg .src_addr = buf_pa ;
422+ pdma_cfg .dst_addr = (rt_uint8_t * )uart_dev -> pa_base ;
423+ pdma_cfg .line_size = len ;
424+
425+ /* Set channel configuration */
426+ pdma_cfg .pdma_ch_cfg .ch_src_type = CONTINUE ;
427+ pdma_cfg .pdma_ch_cfg .ch_dev_hsize = PSBYTE1 ;
428+ pdma_cfg .pdma_ch_cfg .ch_dat_endian = PDEFAULT ;
429+ pdma_cfg .pdma_ch_cfg .ch_dev_blen = PBURST_LEN_16 ;
430+ pdma_cfg .pdma_ch_cfg .ch_priority = 7 ;
431+ pdma_cfg .pdma_ch_cfg .ch_dev_tout = 0xFFF ;
432+
433+ err = k230_pdma_set_callback (ch , uart_pdma_call_back );
434+ if (err != RT_EOK )
435+ {
436+ LOG_E ("pdma_set_callback failed, err=%d\n" , err );
437+ }
438+ err = k230_pdma_config (ch , & pdma_cfg );
439+ if (err != RT_EOK )
440+ {
441+ LOG_E ("pdma_config failed, err=%d\n" , err );
442+ }
443+ /* Start transfer and wait for completion */
444+ err = k230_pdma_start (ch );
445+ if (err != RT_EOK )
446+ {
447+ LOG_E ("pdma_start failed, err=%d\n" , err );
448+ }
449+ err = rt_event_recv (uart_pdma_event ,
450+ TEST_PDMA_EVENT_COMPLETE | TEST_PDMA_EVENT_TIMEOUT ,
451+ RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR ,
452+ RT_WAITING_FOREVER ,
453+ & recv_event );
454+ /* Cleanup */
455+ if (err != RT_EOK )
456+ {
457+ LOG_E ("event_recv failed, err=%d\n" , err );
458+ }
459+ err = k230_pdma_stop (ch );
460+ if (err != RT_EOK )
461+ {
462+ LOG_E ("pdma_stop failed, err=%d\n" , err );
463+ }
464+ err = k230_pdma_release_channel (ch );
465+ if (err != RT_EOK )
466+ {
467+ LOG_E ("pdma_release_channel failed, err=%d\n" , err );
468+ }
469+ rt_free_align (buf );
470+ return size ;
471+ }
472+
473+ static rt_ssize_t uart_dma_tran (struct rt_serial_device * serial , rt_uint8_t * buf , rt_size_t size , int direction )
474+ {
475+ rt_ssize_t len ;
476+ if (RT_SERIAL_DMA_TX == direction )
477+ {
478+ len = uart_dma_write (serial , (void * )buf , size );
479+ }
480+ rt_hw_serial_isr (serial , RT_SERIAL_EVENT_TX_DMADONE );
481+ return len ;
482+ }
483+
304484static void rt_hw_uart_isr (int irq , void * param )
305485{
306486 struct rt_serial_device * serial = (struct rt_serial_device * )param ;
@@ -331,7 +511,7 @@ static void rt_hw_uart_isr(int irq, void *param)
331511 }
332512 #ifdef RT_USING_SERIAL_V2
333513 uint8_t data ;
334-
514+
335515 do {
336516 data = readb ((void * )(uart_base + UART_RBR ));
337517 rt_ringbuffer_putchar (& (rx_fifo -> rb ), data );
@@ -354,32 +534,49 @@ static void rt_hw_uart_isr(int irq, void *param)
354534 */
355535int rt_hw_uart_init (void )
356536{
357- struct rt_serial_device * serial ;
358- struct device_uart * uart ;
359537 struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT ;
538+ rt_err_t ret ;
360539
540+ uart_pdma_event = (rt_event_t )rt_malloc (sizeof (struct rt_event ));
541+ if (uart_pdma_event == RT_NULL )
361542 {
362- serial = & serial1 ;
363- uart = & uart1 ;
543+ LOG_E ("Failed to allocate memory for pdma_event!" );
544+ return - RT_ENOMEM ;
545+ }
364546
365- serial -> ops = & _uart_ops ;
366- serial -> config = config ;
367- serial -> config .baud_rate = UART_DEFAULT_BAUDRATE ;
547+ if (rt_event_init (uart_pdma_event , "pdma_event" , RT_IPC_FLAG_FIFO ) != RT_EOK )
548+ {
549+ LOG_E ("Failed to init pdma_event!" );
550+ rt_free (uart_pdma_event );
551+ return - RT_ERROR ;
552+ }
368553
369- uart -> pa_base = ( void * ) UART_ADDR ;
370- uart -> hw_base = ( rt_base_t ) rt_ioremap ( uart -> pa_base , 0x1000 );
371- uart -> irqno = UART_IRQ ;
554+ for ( int i = 0 ; i < sizeof ( uart_devs )/ sizeof ( uart_devs [ 0 ]); i ++ )
555+ {
556+ struct k230_uart_dev * dev = & uart_devs [ i ] ;
372557
373- _uart_init ((void * )(uart -> hw_base ));
558+ dev -> serial .ops = & _uart_ops ;
559+ dev -> serial .config = config ;
560+ dev -> serial .config .baud_rate = UART_DEFAULT_BAUDRATE ;
374561
375- rt_hw_interrupt_install (uart -> irqno , rt_hw_uart_isr , serial , "uart1" );
376- rt_hw_interrupt_umask (uart -> irqno );
562+ dev -> uart .pa_base = (void * )dev -> pa_base ;
563+ dev -> uart .hw_base = (rt_base_t )rt_ioremap (dev -> uart .pa_base , dev -> uart_to_size );
564+ dev -> uart .irqno = dev -> irqno ;
377565
378- rt_hw_serial_register (serial ,
379- RT_CONSOLE_DEVICE_NAME ,
380- RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX ,
381- uart );
382- }
566+ _uart_init ((void * )(dev -> uart .hw_base ));
383567
384- return 0 ;
385- }
568+ rt_hw_interrupt_install (dev -> uart .irqno , rt_hw_uart_isr , & dev -> serial , dev -> name );
569+ rt_hw_interrupt_umask (dev -> uart .irqno );
570+
571+ ret = rt_hw_serial_register (& dev -> serial ,
572+ dev -> name ,
573+ RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_DMA_TX ,
574+ & dev -> uart );
575+ if (ret != RT_EOK )
576+ {
577+ LOG_E ("Failed to register %s, ret=%d\n" , dev -> name , ret );
578+ return ret ;
579+ }
580+ }
581+ return RT_EOK ;
582+ }
0 commit comments