⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uart.c

📁 Linux uart driver for Infineon ADM5120 SOC Uart port. This is good reference to operate the SOC uart
💻 C
字号:
#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>   /* printk() */#include <linux/slab.h>#include <linux/fs.h>       /* everything... */#include <linux/errno.h>    /* error codes */#include <linux/types.h>    /* size_t */#include <linux/init.h>#include <linux/proc_fs.h>#include <linux/poll.h>#include <linux/ioport.h>#include <linux/vmalloc.h>#include <linux/delay.h>#include <linux/sched.h>#include <linux/param.h>#include <linux/timer.h>#include <linux/interrupt.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/semaphore.h>#include <asm/irq.h>#include <asm/am5120/am5120.h> /* The maximum write buffer */#define _MAX_BUF_                       256/* The maximun size of the DECT Base frame */#define _MAX_DECT_                      30/* Byte data mask */#define _BYT_MASK_                      0xff/* Default UART baudrate */#define DEFAULT_BAUDRATE		        19200/* Read UART register */#define _UART_REG_READ_(base, _reg)		\	*((volatile unsigned long *)(base + (_reg)))/* Write UART register */	#define _UART_REG_WRITE_(base, _reg, _val)      \	*((volatile unsigned long *)(base + (_reg))) = (_val)/* Data structure for UART baudrate */typedef struct _UART_RATE_ENTRY_{	int	rate;	unsigned long div;} UART_RATE_ENTRY, *PUART_RATE_ENTRY;/* Function point */typedef void (*_FUNCPTR) (char *recvBuf, int cnt);/* Data structure for UART object */typedef struct _UART_OBJ_{	unsigned long status;	unsigned long io_base;	unsigned long ctrl;	int	baudrate;	int irq;    _FUNCPTR func;} UART_OBJ, *PUART_OBJ;/* Receiving buffer for UART I/O */typedef struct {    int 	cnt;    char 	buf[32];} UART_RECV;/* UART baudrate value */const UART_RATE_ENTRY rate_tab[] ={	{1200,		UART_1200bps_DIVISOR},	{2400,		UART_2400bps_DIVISOR},	{9600,		UART_9600bps_DIVISOR},	{14400,		UART_14400bps_DIVISOR},	{19200,		UART_19200bps_DIVISOR},	{38400,		UART_38400bps_DIVISOR},	{57600,		UART_57600bps_DIVISOR},	{115200,	UART_115200bps_DIVISOR}};/* Global variable declaration */const int rate_option = sizeof(rate_tab) / sizeof(UART_RATE_ENTRY);UART_OBJ uartObj[2] = {0};UART_RECV recv = {0};/*******************************************************************************Description:   Set baudrate for the UART device.Arguments:Note:*******************************************************************************/void uart_set_baudrate (PUART_OBJ uart){	unsigned long lcr_h, i;    for (i = 0; i < rate_option; i++)        if (rate_tab[i].rate == uart->baudrate)             break;			if (i == rate_option)	    printk("DECTBase Driver: UART1 Baudrate out of range!\n");	else	{    	/* Save lcr_h */    	lcr_h = _UART_REG_READ_(uart->io_base, UART_LCR_H_REG);        	_UART_REG_WRITE_(uart->io_base, UART_LCR_M_REG, rate_tab[i].div >> 8);    	_UART_REG_WRITE_(uart->io_base, UART_LCR_L_REG, rate_tab[i].div);        	/* Write lcr_h to update the lcr register */    	_UART_REG_WRITE_(uart->io_base, UART_LCR_H_REG, lcr_h);    }        return;}/*******************************************************************************Description:   Init UART device using the default value.Arguments:Note:*******************************************************************************/void uart_init(PUART_OBJ uart){	/* Set baudrate */	uart_set_baudrate(uart);	/* Set default line mode */	_UART_REG_WRITE_(uart->io_base, UART_LCR_H_REG, UART_WLEN_8BITS);			/* Enable uart port */	_UART_REG_WRITE_(uart->io_base, UART_CR_REG, UART_PORT_EN | UART_RX_INT_EN);		/* Enable interrupt controller */	ADM5120_INTC_REG(IRQ_ENABLE_REG) = ADM5120_INTC_REG(IRQ_ENABLE_REG) | (1 << uart->irq);}/*******************************************************************************Description:   Init UART device using the default value.Arguments:Note:*******************************************************************************/void uart_irq_hd(int irq, void *dev_id, struct pt_regs *regs){    PUART_OBJ uart = (PUART_OBJ)dev_id;    unsigned long status;              status = _UART_REG_READ_(uart->io_base, UART_IIR_REG);        if (status & UART_RX_INT)    {        recv.buf[recv.cnt++] = _UART_REG_READ_(uart->io_base, UART_DR_REG) & _BYT_MASK_;        #ifdef _DRV_DEBUG_        {            int db = recv.cnt - 1;            printk("[R:0x%.2x]\n", recv.buf[db]);        }#endif                /* If this is garbage, clean buffer, and do not thing. */        if (recv.cnt == 2 && (recv.buf[1] < 0 || recv.buf[1] > _MAX_DECT_))        {            memset(&recv, 0, sizeof(recv));            return;        }                /***************************************************************/        /* workaround for some error packets */        if (recv.cnt == 2)        {            switch (recv.buf[0])            {            case 0x02:            case 0x04:            case 0x05:            case 0x06:            case 0x13:            case 0x14:            case 0x15:            case 0x40:            case 0x42:            case 0x4f:            case 0x0d:                recv.buf[1] = 0;                break;            default:                break;            }        }        /***************************************************************/        /* After receive the last byte we will return dect buffer to upper layer. */        if ((recv.cnt - 2) == recv.buf[1])        {            /* Handle this DECT frame. */            uart->func(recv.buf, recv.cnt);            /* Reset the data buffer. */             memset(&recv, 0, sizeof(recv));        }    }}/*******************************************************************************Description:   Write the data to UART.Arguments:Note:*******************************************************************************/int uart_write(int uart_n, const char *buf, size_t count){    PUART_OBJ uart = &uartObj[uart_n];    unsigned long uartfr;    char tmp_buf[_MAX_BUF_] = {0};    int num, i = 0;        if (count > _MAX_BUF_)        num = _MAX_BUF_;    else        num = count;            memcpy(tmp_buf, buf, num);    while(1)    {	    uartfr = _UART_REG_READ_(uart->io_base, UART_FR_REG);	    if (!(uartfr & UART_TX_FIFO_EMPTY)) continue;            #ifdef _DRV_DEBUG_        printk("[W:0x%.2x]\n", tmp_buf[i]);#endif	    _UART_REG_WRITE_(uart->io_base, UART_DR_REG, (int)tmp_buf[i++]);	    	    if (i >= num) break;	}    return i;}/*******************************************************************************Description:   Open the UART device.Arguments:Note:*******************************************************************************/int uart_open(int num, _FUNCPTR callback){    PUART_OBJ uart;           if (num < 0 || num > 1)    {        printk("DECTBase Driver: UART1 major number error!\n");        return -1;    }        /* Already init */    if (uartObj[num].status)        return 0;            uart = &uartObj[num];  	uart->baudrate = DEFAULT_BAUDRATE;	uart->status = 1;	uart->ctrl = 0;	uart->func = callback;		if (num == 0)	{	    uart->irq = INT_LVL_UART0;	    uart->io_base = PA2VA(UART0_BASE);	}	else	{	    uart->irq = INT_LVL_UART1;	    uart->io_base = PA2VA(UART1_BASE);	}		/* Register irq routine */	request_irq(uart->irq, uart_irq_hd, SA_SHIRQ, NULL, uart);	uart_init(uart);	    return 0;}/*******************************************************************************Description:   Close the UART device.Arguments:Note:*******************************************************************************/int uart_close(int num){    PUART_OBJ uart = &uartObj[num];        /* Disable hardware interrupt */	ADM5120_INTC_REG(IRQ_DISABLE_REG) = ADM5120_INTC_REG(IRQ_DISABLE_REG) | (1 << uart->irq);	    /* Disable irq request */    free_irq(uart->irq, uart);    /* Reset data structure */    memset(uart, 0, sizeof(UART_OBJ));        return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -