4722
- 收藏
- 点赞
- 分享
- 举报
大牛帮我看看,我的uart2驱动哪里有问题?
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include /* IOADDRESS */
#include /* copy from user */
#include "uart2.h"
#define APB_CLK 155000000ul
#define UART_CLK APB_CLK
#define TX_FIFO_SIZE 16
/* mux ctrl reg */
#define MUXCTRL_REG_BASE 0x200F0000
#define MUXCTRL_REG1_OFFSET 0x04
#define MUXCTRL_REG20_OFFSET 0x50
#define PERI_CRG_REG_BASE 0x20030000
#define PERI_CRG10_OFFSET 0x28
#define PERI_CRG57_OFFSET 0xE4
#define WRITE_REG(Addr, Value) ((*(volatile unsigned int *)(Addr)) = (Value))
#define READ_REG(Addr) (*(volatile unsigned int *)(Addr))
#define UART2_BASE 0x200A0000
#define UART_DR 0x00
#define UART_RSR 0x04
#define UART_FR 0x18
#define UART_IBRD 0x24
#define UART_FBRD 0x28
#define UART_LCR_H 0x2c
#define UART_CR 0x30
#define UART_IFLS 0x34
#define UART_IMSC 0x38
#define UART_RIS 0x3C
#define UART_MIS 0x40
#define UART_ICR 0x44
#define UART_DMACR 0x48
#define UART_CR_UARTEN (1 << 0) /* UART enable */
#define UART_CR_RXE (1 << 9) /* receive enable */
#define UART_CR_TXE (1 << 8) /* transmit enable */
#define UART_CR_LBE (1 << 7) /* loopback enable */
#define UART_LCR_FIFO_EN (1 << 4)
#define UART_LCR_5_BIT (0 << 5)
#define UART_LCR_6_BIT (1 << 5)
#define UART_LCR_7_BIT (2 << 5)
#define UART_LCR_8_BIT (3 << 5)
#define UART_IFLS_RXFIFO_1_8 (0 << 3)
#define UART_IFLS_RXFIFO_1_4 (1 << 3)
#define UART_IFLS_RXFIFO_1_2 (2 << 3)
#define UART_IFLS_RXFIFO_3_4 (3 << 3)
#define UART_IFLS_RXFIFO_7_8 (4 << 3)
#define UART_IFLS_TXFIFO_1_8 (0 << 0)
#define UART_IFLS_TXFIFO_1_4 (1 << 0)
#define UART_IFLS_TXFIFO_1_2 (2 << 0)
#define UART_IFLS_TXFIFO_3_4 (3 << 0)
#define UART_IFLS_TXFIFO_7_8 (4 << 0)
#define UART_IMSC_OEIM (1 << 10)
#define UART_IMSC_BEIM (1 << 9)
#define UART_IMSC_PEIM (1 << 8)
#define UART_IMSC_FEIM (1 << 7)
#define UART_IMSC_RTIM (1 << 6)
#define UART_IMSC_TXIM (1 << 5)
#define UART_IMSC_RXIM (1 << 4)
#define UART_RIS_OERIS (1 << 10)
#define UART_RIS_BERIS (1 << 9)
#define UART_RIS_PERIS (1 << 8)
#define UART_RIS_FERIS (1 << 7)
#define UART_RIS_RTRIS (1 << 6)
#define UART_RIS_TXRIS (1 << 5)
#define UART_RIS_RXRIS (1 << 4)
#define UART_MIS_OEMIS (1 << 10)
#define UART_MIS_BEMIS (1 << 9)
#define UART_MIS_PEMIS (1 << 8)
#define UART_MIS_FEMIS (1 << 7)
#define UART_MIS_RTMIS (1 << 6)
#define UART_MIS_TXMIS (1 << 5)
#define UART_MIS_RXMIS (1 << 4)
#define UART_ICR_OEIC (1 << 10)
#define UART_ICR_BEIC (1 << 9)
#define UART_ICR_PEIC (1 << 8)
#define UART_ICR_FEIC (1 << 7)
#define UART_ICR_RTIC (1 << 6)
#define UART_ICR_TXIC (1 << 5)
#define UART_ICR_RXIC (1 << 4)
#define UART_TXIS (1 << 5) /* transmit interrupt status */
#define UART_RXIS (1 << 4) /* receive interrupt status */
#define UART_RTIS (1 << 6) /* receive timeout interrupt status */
#define UART_FR_TXFE (1 << 7)
#define UART_FR_RXFF (1 << 6)
#define UART_FR_TXFF (1 << 5)
#define UART_FR_RXFE (1 << 4)
#define UART_FR_BUSY (1 << 3)
#define UART_DR_OE (1 << 11)
#define UART_DR_BE (1 << 10)
#define UART_DR_PE (1 << 9)
#define UART_DR_FE (1 << 8)
#define UART_DR_ERROR (UART_DR_OE | UART_DR_BE | UART_DR_PE | UART_DR_FE)
#define UART_RSR_OE (1 << 3)
#define UART_RSR_BE (1 << 2)
#define UART_RSR_PE (1 << 1)
#define UART_RSR_FE (1 << 0)
#define DEVICE_NAME "uart2"
#define DELAY(us) time_delay_us(us)
#define DEF_UART_BUFFER_SIZE 256
static int baud_rate = 115200;
module_param(baud_rate, int, S_IRUGO);
static int buffer_size = DEF_UART_BUFFER_SIZE;
module_param(buffer_size, int, S_IRUGO);
struct ring_buffer
{
char *buffer;
int length;
int head;
int tail;
};
struct uart2
{
struct miscdevice dev;
struct ring_buffer rx_buffer;
char *rx_save_buffer;
int rx_save_buffer_length;
spinlock_t rx_buffer_spinlock;
wait_queue_head_t rx_wait_queue;
};
static struct uart2 uart2_dev;
static void time_delay_us(unsigned int usec)
{
volatile int i,j;
//ASIC: 155MHZ
//AP = 155/25 = 6.2
for(i=0;i
{
for(j=0;j<50*6;j++)
{;}
}
}
static irqreturn_t uart2_isr(int irq, void * dev_id)
{
unsigned int status;
struct uart2 *dev = dev_id;
unsigned int mis = READ_REG(IO_ADDRESS(UART2_BASE + UART_MIS));
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_ICR), mis);
if (mis & (UART_MIS_RXMIS | UART_MIS_RTMIS))
{
/* rx or receive timeout */
do
{
unsigned int dr = READ_REG(IO_ADDRESS(UART2_BASE + UART_DR));
if (unlikely(dr & UART_DR_ERROR))
{
if (dr & UART_DR_OE)
{
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_RSR), UART_RSR_OE);
printk("uart2 rx oe!\n");
}
if (dr & UART_DR_BE)
{
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_RSR), UART_RSR_BE);
printk("uart2 rx be!\n");
}
if (dr & UART_DR_PE)
{
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_RSR), UART_RSR_BE);
printk("uart2 rx pe!\n");
}
if (dr & UART_DR_FE)
{
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_RSR), UART_RSR_BE);
printk("uart2 rx fe!\n");
}
}
else
{
if ((dev->rx_buffer.tail + 1) % dev->rx_buffer.length != dev->rx_buffer.head)
{
spin_lock(&dev->rx_buffer_spinlock);
dev->rx_buffer.buffer[dev->rx_buffer.tail] = dr & 0xff;
dev->rx_buffer.tail++;
dev->rx_buffer.tail %= dev->rx_buffer.length;
spin_unlock(&dev->rx_buffer_spinlock);
}
else
{
break;
}
}
status = READ_REG(IO_ADDRESS(UART2_BASE + UART_FR));
} while (!(status & UART_FR_RXFE));
if (dev->rx_buffer.tail != dev->rx_buffer.head)
{
wake_up_interruptible(&dev->rx_wait_queue);
}
}
return IRQ_HANDLED;
}
static int uart2_open(struct inode *inode, struct file *filp)
{
int ret;
unsigned int status;
unsigned int dummy;
spin_lock(&uart2_dev.rx_buffer_spinlock);
uart2_dev.rx_buffer.head = 0;
uart2_dev.rx_buffer.tail = 0;
spin_unlock(&uart2_dev.rx_buffer_spinlock);
filp->private_data = &uart2_dev;
/* clear fifo */
status = READ_REG(IO_ADDRESS(UART2_BASE + UART_FR));
while (!(status & UART_FR_RXFE))
{
dummy = READ_REG(IO_ADDRESS(UART2_BASE + UART_DR));
status = READ_REG(IO_ADDRESS(UART2_BASE + UART_FR));
}
/* request interrupt */
ret = request_irq(UART2_IRQ, uart2_isr, 0, DEVICE_NAME, &uart2_dev);
if (ret)
{
printk("[uart2_init] request_irq err!\n");
return -EIO;
}
/* enable interrupt */
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_IMSC), UART_IMSC_RXIM | UART_IMSC_RTIM);
return 0;
}
static int uart2_close(struct inode *inode, struct file *filp)
{
/* disable interrupt */
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_IMSC), 0);
free_irq(UART2_IRQ, &uart2_dev);
return 0;
}
static ssize_t uart2_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
int i;
int ret;
struct uart2 *dev = filp->private_data;
if (count == 0)
{
return 0;
}
if (dev->rx_buffer.head == dev->rx_buffer.tail)
{
if (filp->f_flags & O_NONBLOCK)
{
return -EAGAIN;
}
else
{
wait_event_interruptible(dev->rx_wait_queue, dev->rx_buffer.head != dev->rx_buffer.tail);
}
}
/* read data */
spin_lock(&dev->rx_buffer_spinlock);
if (dev->rx_buffer.tail > dev->rx_buffer.head)
{
if (count > dev->rx_buffer.tail - dev->rx_buffer.head)
{
count = dev->rx_buffer.tail - dev->rx_buffer.head;
}
}
else
{
if (count > dev->rx_buffer.length - dev->rx_buffer.head + dev->rx_buffer.tail)
{
count = dev->rx_buffer.length - dev->rx_buffer.head + dev->rx_buffer.tail;
}
}
for (i = 0; i < count; i++)
{
dev->rx_save_buffer = dev->rx_buffer.buffer[dev->rx_buffer.head];
dev->rx_buffer.head++;
dev->rx_buffer.head %= dev->rx_buffer.length;
}
spin_unlock(&dev->rx_buffer_spinlock);
ret = copy_to_user(buf, dev->rx_save_buffer, count);
if (ret < 0)
{
printk("[uart2_read] copy_to_user err!\n");
return -ERESTARTSYS;
}
return count;
}
static int uart2_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
unsigned int status;
int ret;
int fifo_count;
int i;
struct uart2 *dev = filp->private_data;
if (count == 0)
{
return 0;
}
if (count > dev->rx_save_buffer_length)
{
count = dev->rx_save_buffer_length;
}
ret = copy_from_user(dev->rx_save_buffer, buf, count);
if (ret < 0)
{
printk("[uart3_write] copy_from_user err!\n");
return -ERESTARTSYS;
}
i = 0;
while (count > 0)
{
fifo_count = TX_FIFO_SIZE;
while (fifo_count > 0 && count > 0)
{
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_DR), dev->rx_save_buffer[i++]);
count--;
fifo_count--;
}
do
{
status = READ_REG(IO_ADDRESS(UART2_BASE + UART_FR));
} while (status & UART_FR_BUSY);
}
return i;
}
static void init_uart2_dev(int baud)
{
int reg;
int val;
int imsc_save = READ_REG(IO_ADDRESS(UART2_BASE + UART_IMSC));
/* reset */
reg = READ_REG(IO_ADDRESS(PERI_CRG_REG_BASE + PERI_CRG57_OFFSET));
reg |= (1 << 9);
WRITE_REG(IO_ADDRESS(PERI_CRG_REG_BASE + PERI_CRG57_OFFSET), reg);
DELAY(1);
reg = READ_REG(IO_ADDRESS(PERI_CRG_REG_BASE + PERI_CRG57_OFFSET));
reg &= ~(1 << 9);
WRITE_REG(IO_ADDRESS(PERI_CRG_REG_BASE + PERI_CRG57_OFFSET), reg);
/* init uart2 */
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_CR), 0);
/* baudrate */
val = UART_CLK / 16 * 64 / baud;
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_FBRD), val & 0x3f);
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_IBRD), val >> 6);
/* enable fifo */
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_LCR_H), UART_LCR_FIFO_EN | UART_LCR_8_BIT);
/* set fifo */
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_IFLS), UART_IFLS_RXFIFO_1_2);
/* restore interrupt */
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_IMSC), imsc_save);
/* enable */
#if 1
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_CR), UART_CR_UARTEN | UART_CR_TXE | UART_CR_RXE);
#else
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_CR), UART_CR_UARTEN | UART_CR_TXE | UART_CR_RXE | UART_CR_LBE);
#endif
#if 0
reg = READ_REG(IO_ADDRESS(PERI_CRG_REG_BASE + PERI_CRG10_OFFSET));
printk("PERI_CRG10:0x%X\n", reg);
#endif
}
static long uart2_ioctl (struct file *filp, unsigned int cmd, unsigned long arg)
{
int ret = -EINVAL;
struct uart2 *dev = filp->private_data;
if (_IOC_TYPE(cmd) != UART2_MAGIC)
{
printk("uart2_ioctl cmd invalid!\n");
return -EINVAL;
}
if (_IOC_NR(cmd) > UART2_MAX_NR)
{
printk("uart2_ioctl cmd invalid!\n");
return -EINVAL;
}
switch (cmd)
{
case UART2_BUFFER_RESET:
spin_lock(&dev->rx_buffer_spinlock);
dev->rx_buffer.head = 0;
dev->rx_buffer.tail = 0;
spin_unlock(&dev->rx_buffer_spinlock);
ret = 0;
break;
case UART2_GET_BAUDRATE:
*(int *)arg = baud_rate;
ret = 0;
break;
case UART2_SET_BAUDRATE:
baud_rate = *(int *)arg;
init_uart2_dev(baud_rate);
spin_lock(&dev->rx_buffer_spinlock);
dev->rx_buffer.head = 0;
dev->rx_buffer.tail = 0;
spin_unlock(&dev->rx_buffer_spinlock);
ret = 0;
break;
default:
printk("uart2 cmd invalid!\n");
return -EINVAL;
}
return ret;
}
static unsigned int uart2_poll(struct file *filp, poll_table *wait)
{
unsigned int mask = 0;
struct uart2 *dev = filp->private_data;
poll_wait(filp, &dev->rx_wait_queue, wait);
if (dev->rx_buffer.head != dev->rx_buffer.tail)
{
mask |= (POLLIN | POLLRDNORM);
}
return mask;
}
static struct file_operations uart2_fops =
{
.owner = THIS_MODULE,
.open = uart2_open,
.read = uart2_read,
.write = uart2_write,
.release = uart2_close,
.unlocked_ioctl = uart2_ioctl,
.poll = uart2_poll
};
static int __init uart2_init(void)
{
int ret;
int reg;
uart2_dev.dev.minor = MISC_DYNAMIC_MINOR;
uart2_dev.dev.name = DEVICE_NAME;
uart2_dev.dev.fops = &uart2_fops;
uart2_dev.rx_buffer.buffer = kmalloc(buffer_size, GFP_KERNEL);
if (uart2_dev.rx_buffer.buffer == NULL)
{
printk("kmalloc error\n");
return -1;
}
uart2_dev.rx_buffer.length = buffer_size;
uart2_dev.rx_buffer.head = 0;
uart2_dev.rx_buffer.tail = 0;
uart2_dev.rx_save_buffer = kmalloc(buffer_size, GFP_KERNEL);
if (uart2_dev.rx_save_buffer == NULL)
{
printk("kmalloc error\n");
return -1;
}
uart2_dev.rx_save_buffer_length = buffer_size;
spin_lock_init(&uart2_dev.rx_buffer_spinlock);
init_waitqueue_head(&uart2_dev.rx_wait_queue);
/* config pins */
/* pin UART2_TXD */
reg = READ_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG1_OFFSET));
reg &= ~0x03;
reg |= 0x02;
WRITE_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG1_OFFSET), reg);
/* pin UART2_RXD */
reg = READ_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG20_OFFSET));
reg &= ~0x03;
reg |= 0x02;
WRITE_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG20_OFFSET), reg);
reg = READ_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG1_OFFSET));
printk("uart2 tx %4x\n",reg);
/* pin UART2_RXD */
reg = READ_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG20_OFFSET));
printk("uart2 rxx %4x\n",reg);
init_uart2_dev(baud_rate);
ret = misc_register(&uart2_dev.dev);
if (ret)
{
printk("could not register uart2 devices\n");
return ret;
}
printk("uart2 device init OK, baud_rate:%d, buffer_size:%d\n", baud_rate, buffer_size);
return 0;
}
static void __exit uart2_exit(void)
{
misc_deregister(&uart2_dev.dev);
kfree(uart2_dev.rx_buffer.buffer);
kfree(uart2_dev.rx_save_buffer);
printk("uart2 device exit!\n");
}
module_init(uart2_init);
module_exit(uart2_exit);
MODULE_AUTHOR("Eddie Zhu");
MODULE_DESCRIPTION("uart2 driver");
MODULE_LICENSE("GPL");
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "uart2.h"
#define APB_CLK 155000000ul
#define UART_CLK APB_CLK
#define TX_FIFO_SIZE 16
/* mux ctrl reg */
#define MUXCTRL_REG_BASE 0x200F0000
#define MUXCTRL_REG1_OFFSET 0x04
#define MUXCTRL_REG20_OFFSET 0x50
#define PERI_CRG_REG_BASE 0x20030000
#define PERI_CRG10_OFFSET 0x28
#define PERI_CRG57_OFFSET 0xE4
#define WRITE_REG(Addr, Value) ((*(volatile unsigned int *)(Addr)) = (Value))
#define READ_REG(Addr) (*(volatile unsigned int *)(Addr))
#define UART2_BASE 0x200A0000
#define UART_DR 0x00
#define UART_RSR 0x04
#define UART_FR 0x18
#define UART_IBRD 0x24
#define UART_FBRD 0x28
#define UART_LCR_H 0x2c
#define UART_CR 0x30
#define UART_IFLS 0x34
#define UART_IMSC 0x38
#define UART_RIS 0x3C
#define UART_MIS 0x40
#define UART_ICR 0x44
#define UART_DMACR 0x48
#define UART_CR_UARTEN (1 << 0) /* UART enable */
#define UART_CR_RXE (1 << 9) /* receive enable */
#define UART_CR_TXE (1 << 8) /* transmit enable */
#define UART_CR_LBE (1 << 7) /* loopback enable */
#define UART_LCR_FIFO_EN (1 << 4)
#define UART_LCR_5_BIT (0 << 5)
#define UART_LCR_6_BIT (1 << 5)
#define UART_LCR_7_BIT (2 << 5)
#define UART_LCR_8_BIT (3 << 5)
#define UART_IFLS_RXFIFO_1_8 (0 << 3)
#define UART_IFLS_RXFIFO_1_4 (1 << 3)
#define UART_IFLS_RXFIFO_1_2 (2 << 3)
#define UART_IFLS_RXFIFO_3_4 (3 << 3)
#define UART_IFLS_RXFIFO_7_8 (4 << 3)
#define UART_IFLS_TXFIFO_1_8 (0 << 0)
#define UART_IFLS_TXFIFO_1_4 (1 << 0)
#define UART_IFLS_TXFIFO_1_2 (2 << 0)
#define UART_IFLS_TXFIFO_3_4 (3 << 0)
#define UART_IFLS_TXFIFO_7_8 (4 << 0)
#define UART_IMSC_OEIM (1 << 10)
#define UART_IMSC_BEIM (1 << 9)
#define UART_IMSC_PEIM (1 << 8)
#define UART_IMSC_FEIM (1 << 7)
#define UART_IMSC_RTIM (1 << 6)
#define UART_IMSC_TXIM (1 << 5)
#define UART_IMSC_RXIM (1 << 4)
#define UART_RIS_OERIS (1 << 10)
#define UART_RIS_BERIS (1 << 9)
#define UART_RIS_PERIS (1 << 8)
#define UART_RIS_FERIS (1 << 7)
#define UART_RIS_RTRIS (1 << 6)
#define UART_RIS_TXRIS (1 << 5)
#define UART_RIS_RXRIS (1 << 4)
#define UART_MIS_OEMIS (1 << 10)
#define UART_MIS_BEMIS (1 << 9)
#define UART_MIS_PEMIS (1 << 8)
#define UART_MIS_FEMIS (1 << 7)
#define UART_MIS_RTMIS (1 << 6)
#define UART_MIS_TXMIS (1 << 5)
#define UART_MIS_RXMIS (1 << 4)
#define UART_ICR_OEIC (1 << 10)
#define UART_ICR_BEIC (1 << 9)
#define UART_ICR_PEIC (1 << 8)
#define UART_ICR_FEIC (1 << 7)
#define UART_ICR_RTIC (1 << 6)
#define UART_ICR_TXIC (1 << 5)
#define UART_ICR_RXIC (1 << 4)
#define UART_TXIS (1 << 5) /* transmit interrupt status */
#define UART_RXIS (1 << 4) /* receive interrupt status */
#define UART_RTIS (1 << 6) /* receive timeout interrupt status */
#define UART_FR_TXFE (1 << 7)
#define UART_FR_RXFF (1 << 6)
#define UART_FR_TXFF (1 << 5)
#define UART_FR_RXFE (1 << 4)
#define UART_FR_BUSY (1 << 3)
#define UART_DR_OE (1 << 11)
#define UART_DR_BE (1 << 10)
#define UART_DR_PE (1 << 9)
#define UART_DR_FE (1 << 8)
#define UART_DR_ERROR (UART_DR_OE | UART_DR_BE | UART_DR_PE | UART_DR_FE)
#define UART_RSR_OE (1 << 3)
#define UART_RSR_BE (1 << 2)
#define UART_RSR_PE (1 << 1)
#define UART_RSR_FE (1 << 0)
#define DEVICE_NAME "uart2"
#define DELAY(us) time_delay_us(us)
#define DEF_UART_BUFFER_SIZE 256
static int baud_rate = 115200;
module_param(baud_rate, int, S_IRUGO);
static int buffer_size = DEF_UART_BUFFER_SIZE;
module_param(buffer_size, int, S_IRUGO);
struct ring_buffer
{
char *buffer;
int length;
int head;
int tail;
};
struct uart2
{
struct miscdevice dev;
struct ring_buffer rx_buffer;
char *rx_save_buffer;
int rx_save_buffer_length;
spinlock_t rx_buffer_spinlock;
wait_queue_head_t rx_wait_queue;
};
static struct uart2 uart2_dev;
static void time_delay_us(unsigned int usec)
{
volatile int i,j;
//ASIC: 155MHZ
//AP = 155/25 = 6.2
for(i=0;i
for(j=0;j<50*6;j++)
{;}
}
}
static irqreturn_t uart2_isr(int irq, void * dev_id)
{
unsigned int status;
struct uart2 *dev = dev_id;
unsigned int mis = READ_REG(IO_ADDRESS(UART2_BASE + UART_MIS));
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_ICR), mis);
if (mis & (UART_MIS_RXMIS | UART_MIS_RTMIS))
{
/* rx or receive timeout */
do
{
unsigned int dr = READ_REG(IO_ADDRESS(UART2_BASE + UART_DR));
if (unlikely(dr & UART_DR_ERROR))
{
if (dr & UART_DR_OE)
{
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_RSR), UART_RSR_OE);
printk("uart2 rx oe!\n");
}
if (dr & UART_DR_BE)
{
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_RSR), UART_RSR_BE);
printk("uart2 rx be!\n");
}
if (dr & UART_DR_PE)
{
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_RSR), UART_RSR_BE);
printk("uart2 rx pe!\n");
}
if (dr & UART_DR_FE)
{
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_RSR), UART_RSR_BE);
printk("uart2 rx fe!\n");
}
}
else
{
if ((dev->rx_buffer.tail + 1) % dev->rx_buffer.length != dev->rx_buffer.head)
{
spin_lock(&dev->rx_buffer_spinlock);
dev->rx_buffer.buffer[dev->rx_buffer.tail] = dr & 0xff;
dev->rx_buffer.tail++;
dev->rx_buffer.tail %= dev->rx_buffer.length;
spin_unlock(&dev->rx_buffer_spinlock);
}
else
{
break;
}
}
status = READ_REG(IO_ADDRESS(UART2_BASE + UART_FR));
} while (!(status & UART_FR_RXFE));
if (dev->rx_buffer.tail != dev->rx_buffer.head)
{
wake_up_interruptible(&dev->rx_wait_queue);
}
}
return IRQ_HANDLED;
}
static int uart2_open(struct inode *inode, struct file *filp)
{
int ret;
unsigned int status;
unsigned int dummy;
spin_lock(&uart2_dev.rx_buffer_spinlock);
uart2_dev.rx_buffer.head = 0;
uart2_dev.rx_buffer.tail = 0;
spin_unlock(&uart2_dev.rx_buffer_spinlock);
filp->private_data = &uart2_dev;
/* clear fifo */
status = READ_REG(IO_ADDRESS(UART2_BASE + UART_FR));
while (!(status & UART_FR_RXFE))
{
dummy = READ_REG(IO_ADDRESS(UART2_BASE + UART_DR));
status = READ_REG(IO_ADDRESS(UART2_BASE + UART_FR));
}
/* request interrupt */
ret = request_irq(UART2_IRQ, uart2_isr, 0, DEVICE_NAME, &uart2_dev);
if (ret)
{
printk("[uart2_init] request_irq err!\n");
return -EIO;
}
/* enable interrupt */
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_IMSC), UART_IMSC_RXIM | UART_IMSC_RTIM);
return 0;
}
static int uart2_close(struct inode *inode, struct file *filp)
{
/* disable interrupt */
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_IMSC), 0);
free_irq(UART2_IRQ, &uart2_dev);
return 0;
}
static ssize_t uart2_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
int i;
int ret;
struct uart2 *dev = filp->private_data;
if (count == 0)
{
return 0;
}
if (dev->rx_buffer.head == dev->rx_buffer.tail)
{
if (filp->f_flags & O_NONBLOCK)
{
return -EAGAIN;
}
else
{
wait_event_interruptible(dev->rx_wait_queue, dev->rx_buffer.head != dev->rx_buffer.tail);
}
}
/* read data */
spin_lock(&dev->rx_buffer_spinlock);
if (dev->rx_buffer.tail > dev->rx_buffer.head)
{
if (count > dev->rx_buffer.tail - dev->rx_buffer.head)
{
count = dev->rx_buffer.tail - dev->rx_buffer.head;
}
}
else
{
if (count > dev->rx_buffer.length - dev->rx_buffer.head + dev->rx_buffer.tail)
{
count = dev->rx_buffer.length - dev->rx_buffer.head + dev->rx_buffer.tail;
}
}
for (i = 0; i < count; i++)
{
dev->rx_save_buffer = dev->rx_buffer.buffer[dev->rx_buffer.head];
dev->rx_buffer.head++;
dev->rx_buffer.head %= dev->rx_buffer.length;
}
spin_unlock(&dev->rx_buffer_spinlock);
ret = copy_to_user(buf, dev->rx_save_buffer, count);
if (ret < 0)
{
printk("[uart2_read] copy_to_user err!\n");
return -ERESTARTSYS;
}
return count;
}
static int uart2_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
unsigned int status;
int ret;
int fifo_count;
int i;
struct uart2 *dev = filp->private_data;
if (count == 0)
{
return 0;
}
if (count > dev->rx_save_buffer_length)
{
count = dev->rx_save_buffer_length;
}
ret = copy_from_user(dev->rx_save_buffer, buf, count);
if (ret < 0)
{
printk("[uart3_write] copy_from_user err!\n");
return -ERESTARTSYS;
}
i = 0;
while (count > 0)
{
fifo_count = TX_FIFO_SIZE;
while (fifo_count > 0 && count > 0)
{
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_DR), dev->rx_save_buffer[i++]);
count--;
fifo_count--;
}
do
{
status = READ_REG(IO_ADDRESS(UART2_BASE + UART_FR));
} while (status & UART_FR_BUSY);
}
return i;
}
static void init_uart2_dev(int baud)
{
int reg;
int val;
int imsc_save = READ_REG(IO_ADDRESS(UART2_BASE + UART_IMSC));
/* reset */
reg = READ_REG(IO_ADDRESS(PERI_CRG_REG_BASE + PERI_CRG57_OFFSET));
reg |= (1 << 9);
WRITE_REG(IO_ADDRESS(PERI_CRG_REG_BASE + PERI_CRG57_OFFSET), reg);
DELAY(1);
reg = READ_REG(IO_ADDRESS(PERI_CRG_REG_BASE + PERI_CRG57_OFFSET));
reg &= ~(1 << 9);
WRITE_REG(IO_ADDRESS(PERI_CRG_REG_BASE + PERI_CRG57_OFFSET), reg);
/* init uart2 */
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_CR), 0);
/* baudrate */
val = UART_CLK / 16 * 64 / baud;
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_FBRD), val & 0x3f);
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_IBRD), val >> 6);
/* enable fifo */
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_LCR_H), UART_LCR_FIFO_EN | UART_LCR_8_BIT);
/* set fifo */
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_IFLS), UART_IFLS_RXFIFO_1_2);
/* restore interrupt */
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_IMSC), imsc_save);
/* enable */
#if 1
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_CR), UART_CR_UARTEN | UART_CR_TXE | UART_CR_RXE);
#else
WRITE_REG(IO_ADDRESS(UART2_BASE + UART_CR), UART_CR_UARTEN | UART_CR_TXE | UART_CR_RXE | UART_CR_LBE);
#endif
#if 0
reg = READ_REG(IO_ADDRESS(PERI_CRG_REG_BASE + PERI_CRG10_OFFSET));
printk("PERI_CRG10:0x%X\n", reg);
#endif
}
static long uart2_ioctl (struct file *filp, unsigned int cmd, unsigned long arg)
{
int ret = -EINVAL;
struct uart2 *dev = filp->private_data;
if (_IOC_TYPE(cmd) != UART2_MAGIC)
{
printk("uart2_ioctl cmd invalid!\n");
return -EINVAL;
}
if (_IOC_NR(cmd) > UART2_MAX_NR)
{
printk("uart2_ioctl cmd invalid!\n");
return -EINVAL;
}
switch (cmd)
{
case UART2_BUFFER_RESET:
spin_lock(&dev->rx_buffer_spinlock);
dev->rx_buffer.head = 0;
dev->rx_buffer.tail = 0;
spin_unlock(&dev->rx_buffer_spinlock);
ret = 0;
break;
case UART2_GET_BAUDRATE:
*(int *)arg = baud_rate;
ret = 0;
break;
case UART2_SET_BAUDRATE:
baud_rate = *(int *)arg;
init_uart2_dev(baud_rate);
spin_lock(&dev->rx_buffer_spinlock);
dev->rx_buffer.head = 0;
dev->rx_buffer.tail = 0;
spin_unlock(&dev->rx_buffer_spinlock);
ret = 0;
break;
default:
printk("uart2 cmd invalid!\n");
return -EINVAL;
}
return ret;
}
static unsigned int uart2_poll(struct file *filp, poll_table *wait)
{
unsigned int mask = 0;
struct uart2 *dev = filp->private_data;
poll_wait(filp, &dev->rx_wait_queue, wait);
if (dev->rx_buffer.head != dev->rx_buffer.tail)
{
mask |= (POLLIN | POLLRDNORM);
}
return mask;
}
static struct file_operations uart2_fops =
{
.owner = THIS_MODULE,
.open = uart2_open,
.read = uart2_read,
.write = uart2_write,
.release = uart2_close,
.unlocked_ioctl = uart2_ioctl,
.poll = uart2_poll
};
static int __init uart2_init(void)
{
int ret;
int reg;
uart2_dev.dev.minor = MISC_DYNAMIC_MINOR;
uart2_dev.dev.name = DEVICE_NAME;
uart2_dev.dev.fops = &uart2_fops;
uart2_dev.rx_buffer.buffer = kmalloc(buffer_size, GFP_KERNEL);
if (uart2_dev.rx_buffer.buffer == NULL)
{
printk("kmalloc error\n");
return -1;
}
uart2_dev.rx_buffer.length = buffer_size;
uart2_dev.rx_buffer.head = 0;
uart2_dev.rx_buffer.tail = 0;
uart2_dev.rx_save_buffer = kmalloc(buffer_size, GFP_KERNEL);
if (uart2_dev.rx_save_buffer == NULL)
{
printk("kmalloc error\n");
return -1;
}
uart2_dev.rx_save_buffer_length = buffer_size;
spin_lock_init(&uart2_dev.rx_buffer_spinlock);
init_waitqueue_head(&uart2_dev.rx_wait_queue);
/* config pins */
/* pin UART2_TXD */
reg = READ_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG1_OFFSET));
reg &= ~0x03;
reg |= 0x02;
WRITE_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG1_OFFSET), reg);
/* pin UART2_RXD */
reg = READ_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG20_OFFSET));
reg &= ~0x03;
reg |= 0x02;
WRITE_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG20_OFFSET), reg);
reg = READ_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG1_OFFSET));
printk("uart2 tx %4x\n",reg);
/* pin UART2_RXD */
reg = READ_REG(IO_ADDRESS(MUXCTRL_REG_BASE + MUXCTRL_REG20_OFFSET));
printk("uart2 rxx %4x\n",reg);
init_uart2_dev(baud_rate);
ret = misc_register(&uart2_dev.dev);
if (ret)
{
printk("could not register uart2 devices\n");
return ret;
}
printk("uart2 device init OK, baud_rate:%d, buffer_size:%d\n", baud_rate, buffer_size);
return 0;
}
static void __exit uart2_exit(void)
{
misc_deregister(&uart2_dev.dev);
kfree(uart2_dev.rx_buffer.buffer);
kfree(uart2_dev.rx_save_buffer);
printk("uart2 device exit!\n");
}
module_init(uart2_init);
module_exit(uart2_exit);
MODULE_AUTHOR("Eddie Zhu");
MODULE_DESCRIPTION("uart2 driver");
MODULE_LICENSE("GPL");
我来回答
回答7个
时间排序
认可量排序
认可0
认可0
认可0
认可0
认可0
认可0
认可0
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币
Markdown 语法
- 加粗**内容**
- 斜体*内容*
- 删除线~~内容~~
- 引用> 引用内容
- 代码`代码`
- 代码块```编程语言↵代码```
- 链接[链接标题](url)
- 无序列表- 内容
- 有序列表1. 内容
- 缩进内容
- 图片![alt](url)
相关问答
-
2016-09-01 14:09:58
-
2013-05-18 22:26:32
-
2015-07-13 09:04:42
-
2018-07-18 21:28:06
-
2016-08-31 11:14:58
-
2015-04-21 09:23:58
-
2015-04-20 13:17:14
-
2023-08-18 13:57:17
-
2018-12-18 14:02:08
-
2018-11-09 14:22:38
-
2021-02-19 14:57:13
-
2016-09-28 11:44:16
-
2016-08-12 14:30:53
-
2016-08-03 09:41:26
-
2015-01-16 10:50:01
-
2017-09-25 20:16:48
-
2017-04-06 22:42:41
-
2020-11-03 11:56:45
-
2023-04-17 17:22:54
无更多相似问答 去提问
点击登录
-- 积分
-- E币
提问
—
收益
—
被采纳
—
我要提问
切换马甲
上一页
下一页
悬赏问答
-
5Hi3516CV610 如何使用SD卡升级固件
-
5cat /dev/logmpp 报错 <3>[ vi] [func]:vi_send_frame_node [line]:99 [info]:vi pic queue is full!
-
50如何获取vpss chn的图像修改后发送至vo
-
5FPGA通过Bt1120传YUV422数据过来,vi接收不到数据——3516dv500
-
50SS928 运行PQtools 拼接 推到设备里有一半画面会异常
-
53536AV100的sample_vdec输出到CVBS显示
-
10海思板子mpp怎么在vi阶段改变视频数据尺寸
-
10HI3559AV100 多摄像头同步模式
-
9海思ss928单路摄像头vio中加入opencv处理并显示
-
10EB-RV1126-BC-191板子运行自己编码的程序
举报反馈
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明
提醒
你的问题还没有最佳答案,是否结题,结题后将扣除20%的悬赏金
取消
确认
提醒
你的问题还没有最佳答案,是否结题,结题后将根据回答情况扣除相应悬赏金(1回答=1E币)
取消
确认