손지언

d

1 +#include <linux/kernel.h>
2 +#include <linux/module.h>
3 +#include <linux/init.h>
4 +#include <linux/fs.h>
5 +#include <linux/io.h>
6 +#include <linux/delay.h>
7 +#include <asm/io.h>
8 +#include <asm/uaccess.h>
9 +
10 +
11 +#define DRIVER_AUTHOR "KHU"
12 +#define DRIVER_DESC "Led Driver"
13 +#define DEVICE_NAME "led_dd"
14 +#define MAJOR_NUMBER 222
15 +
16 +#define GPIO_BASE 0x3F200000
17 +#define GPIO_SIZE 0xC0
18 +
19 +#define INPUT 0
20 +#define OUTPUT 1
21 +#define LOW 0
22 +#define HIGH 1
23 +
24 +void __iomem *gpioAddr;
25 +static unsigned long led_color[4] = {3, 7, 11, 15};
26 +static unsigned long cur = 0;
27 +volatile unsigned int gpioToGPFSEL[] = {
28 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
29 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
30 + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
31 +};
32 +volatile unsigned int gpioToShift[] = {
33 + 0, 3, 6, 9, 12, 15, 18, 21, 24, 27,
34 + 0, 3, 6, 9, 12, 15, 18, 21, 24, 27,
35 + 0, 3, 6, 9, 12, 15, 18, 21, 24, 27,
36 +};
37 +volatile unsigned int gpioToGPSET = 0x1C;
38 +volatile unsigned int gpioToGPCLR = 0x28;
39 +
40 +const int Led[16] = {
41 + 4, 17, 18, 27, 22, 23, 24, 25,
42 + 6, 12, 13, 16, 19, 20, 26, 21
43 +};
44 +
45 +static volatile void initGpioAddr(void) {
46 + if(gpioAddr == NULL) {
47 + gpioAddr = ioremap(GPIO_BASE, GPIO_SIZE);
48 + }
49 +}
50 +
51 +static void pinMode(int pin, int mode) {
52 + volatile unsigned int *gpio = (volatile unsigned int *)gpioAddr;
53 +
54 + unsigned int fsel = gpioToGPFSEL[pin]/sizeof(unsigned int);
55 + unsigned int shift = gpioToShift[pin];
56 +
57 + if(mode) {
58 + gpio[fsel] |= (1 << shift);
59 + }
60 + else {
61 + gpio[fsel] |= (0 << shift);
62 + }
63 +}
64 +
65 +static void digitalWrite(int pin, int value) {
66 + volatile unsigned int *gpio = (volatile unsigned int *)gpioAddr;
67 +
68 + unsigned int set = gpioToGPSET/sizeof(unsigned int);
69 + unsigned int clr = gpioToGPCLR/sizeof(unsigned int);
70 +
71 + if(value) {
72 + gpio[set] = (1 << pin);
73 + }
74 + else {
75 + gpio[clr] = (1 << pin);
76 + }
77 +}
78 +
79 +static int led_open(struct inode *inode, struct file *filp) {
80 + int i;
81 +
82 + initGpioAddr();
83 +
84 + for(i = 0; i < 16; i++) {
85 + pinMode(Led[i], OUTPUT);
86 + digitalWrite(Led[i], LOW);
87 + }
88 +
89 + printk("[led_dd] led_open\n");
90 +
91 + return 0;
92 +}
93 +
94 +static int led_release(struct inode *inode, struct file *filp) {
95 + iounmap(gpioAddr);
96 +
97 + printk("[led_dd] led_realse\n");
98 +
99 + return 0;
100 +}
101 +
102 +static int led_write(struct file *filp, const char *buf,
103 + size_t len, loff_t *f_pos) {
104 + int i;
105 + char state;
106 +
107 + printk("color is %lu\n",cur);
108 + for(i = 0; i < len; i++) {
109 + copy_from_user(&state, &buf[i], 1);
110 +
111 + if(state == '0') {
112 + digitalWrite(Led[led_color[cur]-i], LOW);
113 + }
114 + else {
115 + digitalWrite(Led[led_color[cur]-i], HIGH);
116 + }
117 + }
118 +
119 + printk("[led_dd] led_write\n");
120 +
121 + return len;
122 +}
123 +
124 +static int led_ioctl(struct file *filep, unsigned int cmd, unsigned long arg){
125 + printk("set cmd %ld\n",cmd);
126 + printk("set arg %ld\n",arg);
127 + if(copy_from_user(&cur, &arg ,sizeof(unsigned long))<1){
128 + printk("copy failed\n");
129 + }
130 +
131 + cur = arg;
132 +
133 + printk("set color %lu\n",cur);
134 + printk("[led_dd] led_ioctl\n");
135 +
136 + return 0;
137 +}
138 +
139 +static struct file_operations fops = {
140 + .owner = THIS_MODULE,
141 + .open = led_open,
142 + .release = led_release,
143 + .write = led_write,
144 + .unlocked_ioctl = led_ioctl
145 +};
146 +
147 +static int led_init(void) {
148 + printk("[led_dd] led_init()\n");
149 + register_chrdev(MAJOR_NUMBER, DEVICE_NAME, &fops);
150 +
151 + return 0;
152 +}
153 +
154 +static void led_exit(void) {
155 + printk("[led_dd] led_exit()\n");
156 + unregister_chrdev(MAJOR_NUMBER, DEVICE_NAME);
157 +}
158 +
159 +module_init(led_init);
160 +module_exit(led_exit);
161 +
162 +MODULE_LICENSE("Dual BSD/GPL");
163 +