Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <asm/mach/map.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#define UART_MAJOR_NUMBER 504
#define UART_DEV_NAME "uart_ioctl"
#define GPIO_BASE_ADDR 0x3F200000
#define GPFSEL1 0x04
#define USRT_BASE_ADDR 0x3F201000
#define UART_DR 0x00
#define UART_FR 0x18
#define UART_CR 0x30
#define UART_LCRH 0X2C
#define IOCTL_MAGIC_NUMBER 'l'
#define IOCTL_CMD_DIRECTION _IOWR(IOCTL_MAGIC_NUMBER, 0, int)
#define IOCTL_CMD_RECEIVE _IOWR(IOCTL_MAGIC_NUMBER, 1, int)
#define IOCTL_CMD_TRANSMIT _IOWR(IOCTL_MAGIC_NUMBER, 2, int)
static void __iomem *gpio_base;
static void __iomem *usrt_base;
volatile unsigned int *gpsel1;
volatile unsigned int *uart_dr;
volatile unsigned int *uart_fr;
volatile unsigned int *uart_cr;
volatile unsigned int *uart_lcrh;
int uart_open(struct inode *inode, struct file *filp){
printk(KERN_ALERT "UART driver open!!\n");
gpio_base = ioremap(GPIO_BASE_ADDR, 0x60);
usrt_base = ioremap(USRT_BASE_ADDR, 0x60);
gpsel1 = (volatile unsigned int *)(gpio_base + GPFSEL1);
uart_dr = (volatile unsigned int *)(usrt_base + UART_DR);
uart_fr = (volatile unsigned int *)(usrt_base + UART_FR);
uart_cr = (volatile unsigned int *)(usrt_base + UART_CR); // 185PAGE
uart_lcrh = (volatile unsigned int *)(usrt_base + UART_LCRH);
return 0;
}
int uart_release(struct inode *inode, struct file *filp){
printk(KERN_ALERT "UART driver closed!!\n");
iounmap((void *)gpio_base);
return 0;
}
long uart_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
unsigned int txff, rxfe;
int kbuf=-1;
int i=0;
char cbuf[1024];
int writelen = 0;
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
switch (cmd){
case IOCTL_CMD_DIRECTION:
copy_from_user(&kbuf,(const void*)arg, 4);
*gpsel1 |= (1<<14); // gpio14 takes alt0 TXD0
*gpsel1 |= (1<<17); // gpio15 takes alt0 RXD0
if(kbuf==0){
// input
*uart_cr &= ~(1<<0); // disable uart.
*uart_lcrh &= ~(1<<4); // FEN <- 0.
*uart_cr &= ~(1<<8); // TXE <- 0
*uart_cr |= (1<<9); // RXE <- 1
*uart_lcrh |= (1<<4); // FEN <- 1.
*uart_cr |= (1<<0); // enable uart.
} else if(kbuf==1){
// output
*uart_cr &= ~(1<<0); // disable uart.
*uart_lcrh &= ~(1<<4); // FEN <- 0.
*uart_cr &= ~(1<<9); // RXE <- 0
*uart_cr |= (1<<8); // TXE <- 1
*uart_lcrh |= (1<<4); // FEN <- 1.
*uart_cr |= (1<<0); // enable uart.
} else{
// error.
printk(KERN_ALERT "ERR in DIRECTION: invalid operand\n");
}
break;
case IOCTL_CMD_RECEIVE:
printk(KERN_ALERT "receive called\n");
/*
rxfe = 0;
while(!rxfe){
rxfe = (*uart_fr>>4); // read RXFE
} // now rx is not empty
*/
singlechar = (*uart_dr); // read DATA
copy_to_user((void*)arg, (const void*)&singlechar, 4);
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
break;
case IOCTL_CMD_TRANSMIT:
printk(KERN_ALERT "transmit called\n");
copy_from_user(&cbuf,(const void*)arg, 1024);
writelen = strlen(cbuf);
for(i=0; i<writelen; i++){
singlechar = cbuf[i];
/*
txff = 1;
while(txff){
txff = (*uart_fr>>5); // read TXFF
} // now tx fifo is not full
* */
*uart_dr |= (int) singlechar; // write DATA
}
break;
}
return 0;
}
static struct file_operations uart_fops = {
.owner = THIS_MODULE,
.open = uart_open,
.release = uart_release,
.unlocked_ioctl = uart_ioctl
};
int __init uart_init(void){
if(register_chrdev(UART_MAJOR_NUMBER, UART_DEV_NAME, &uart_fops) < 0 )
printk(KERN_ALERT "UART driver initialization failed\n");
else
printk(KERN_ALERT "UART driver initialization successful\n");
return 0;
}
void __exit uart_exit(void){
unregister_chrdev(UART_MAJOR_NUMBER, UART_DEV_NAME);
printk(KERN_ALERT "UART driver exit done\n");
}
module_init(uart_init);
module_exit(uart_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Haeram");
MODULE_DESCRIPTION("des");