#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));
没有合适的资源?快使用搜索试试~ 我知道了~
uart.zip_SOC_infineon_linux uart_linux uart driver_uart linux
共2个文件
txt:1个
c:1个
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 124 浏览量
2022-09-23
07:37:22
上传
评论
收藏 3KB ZIP 举报
温馨提示
Linux uart driver for Infineon ADM5120 SOC Uart port. This is good reference to operate the SOC uart port.
资源推荐
资源详情
资源评论
收起资源包目录
uart.zip (2个子文件)
www.pudn.com.txt 218B
uart.c 8KB
共 2 条
- 1
资源评论
御道御小黑
- 粉丝: 71
- 资源: 1万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功