netfilter: Fix wrong backporting
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / autotst / autotstdrv.c
1 // ****************************************** //
2 // access IIC, GPIO, etc. from user space by anli.wei
3 // 2012-11-25
4 // 2013-01-22 add key info anli.wei
5 // ****************************************** //
6
7 #include <linux/cdev.h>
8 #include <linux/device.h>
9 #include <linux/errno.h>
10 #include <linux/fcntl.h>
11 #include <linux/fs.h>
12 #include <linux/i2c.h>
13 #include <linux/init.h>
14 #include <linux/input.h>
15 #include <linux/interrupt.h>
16 #include <linux/kernel.h>
17 #include <linux/major.h>
18 #include <linux/module.h>
19 #include <linux/types.h>
20
21 #include <asm/io.h>
22 #include <asm/uaccess.h>
23 #include <soc/sprd/board.h>
24 #include <soc/sprd/gpio.h>
25 //
26 #include "autotstdrv.h"
27 #include "dispc.h"
28 //
29 #define DBG_ENABLE_FUN
30 #define DBG_ENABLE_INFO
31
32 #ifdef DBG_ENABLE_FUN
33 #define FUN_ENTER               printk(KERN_INFO "autotst-> %s ++.\n", __FUNCTION__)
34 #define FUN_LEAVE               printk(KERN_INFO "autotst-> %s --.\n", __FUNCTION__)
35 #else
36 #define FUN_ENTER               do {} while(0)
37 #define FUN_LEAVE               do {} while(0)
38 #endif // DBG_ENABLE_FUN
39
40 #ifdef DBG_ENABLE_INFO
41 #define DBG_INFO(fmt, arg...)   printk(KERN_INFO "autotst-> " fmt, ##arg)
42 #else
43 #define DBG_INFO(fmt, arg...)   do {} while(0)
44 #endif // DBG_ENABLE_INFO
45
46 //------------------------------------------------------------------------------
47 //------------------------------------------------------------------------------
48 #define SPRD_MAX_PIN                200
49 #define SPRD_GPIO_PIN_INVALID_VALUE 0xFFFFFFFF
50
51 //static uint32_t  sGpioPins[SPRD_MAX_PIN];
52
53 //------------------------------------------------------------------------------
54 //------------------------------------------------------------------------------
55 extern int     lcm_init( void );
56 extern int32_t lcm_send_data (uint32_t data);
57
58 //------------------------------------------------------------------------------
59 #define CDEV_NAME   "autotst"
60
61 static dev_t         s_devt;
62 static struct cdev   s_cdev;
63 static struct class *s_class;
64
65 //------------------------------------------------------------------------------
66
67 static int autotst_open (struct inode *inode, struct file *filp)
68 {
69         FUN_ENTER;
70         FUN_LEAVE;
71     return 0;
72 }
73
74 static int autotst_release (struct inode *inode, struct file *filp)
75 {
76         FUN_ENTER;
77         FUN_LEAVE;
78     return 0;
79 }
80
81 //------------------------------------------------------------------------------
82 //------------------------------------------------------------------------------
83
84 static int i2c_read( struct autotst_i2c_info_t * info )
85 {
86     struct i2c_msg xfer[2];
87     u8  reg[2], reg_len = 0;
88     u8  addr = (info->addr >> 1);
89     int ret;
90
91     struct i2c_adapter * adpt = i2c_get_adapter(info->bus);
92     if( NULL == adpt ) {
93         printk(KERN_ERR "get adapter(%d) fail!\n", info->bus);
94         return -ENXIO;
95     }
96
97     DBG_INFO("i2c read: bus = %d, addr = %X, reg = %X\n", info->bus, addr, info->reg);
98
99     if( 16 == info->regBits ) {
100         reg[reg_len++] = (u8)(info->reg >> 8);
101     }
102     reg[reg_len++] = (u8)(info->reg);
103
104         // Write address
105         xfer[0].addr  = addr;
106         xfer[0].flags = 0;
107         xfer[0].len   = reg_len;
108         xfer[0].buf   = reg;
109
110         /* Read data */
111         xfer[1].addr  = addr;
112         xfer[1].flags = I2C_M_RD;
113         xfer[1].len   = info->data_len;
114         xfer[1].buf   = info->data;
115
116         ret = i2c_transfer(adpt, xfer, 2);
117         if( ret < 0 ) {
118                 printk(KERN_ERR "i2c_transfer() returned %d\n", ret);
119
120         i2c_put_adapter(adpt);
121                 return ret;
122         }
123
124     DBG_INFO("i2c read done: bus = %d, addr = 0x%04X, reg = 0x%04X\n", 
125         info->bus, info->addr, info->reg);
126
127     i2c_put_adapter(adpt);
128     return 0;
129 }
130
131 //------------------------------------------------------------------------------
132 static int i2c_write( struct autotst_i2c_info_t * info )
133 {
134     u8  buf[64];
135     u8  num = 0;
136     int ret, i;
137
138     struct i2c_msg xfer;
139
140     struct i2c_adapter * adpt = i2c_get_adapter(info->bus);
141     if( NULL == adpt ) {
142         printk(KERN_ERR "get adapter(%d) fail!\n", info->bus);
143         return -ENXIO;
144     }
145
146     if( 16 == info->regBits ) {
147         buf[num++] = (u8)(info->reg >> 8);
148     }
149
150     buf[num++] = (u8)(info->reg);
151
152     for( i = 0; i < info->data_len; ++i )
153     {
154         buf[num++] = info->data[i];
155     }
156
157     xfer.addr  = info->addr;
158     xfer.flags = 0;
159     xfer.len   = num;
160     xfer.buf   = buf;
161
162     ret = i2c_transfer(adpt, &xfer, 1);
163         if( ret < 0 ) {
164                 printk(KERN_ERR "i2c_transfer() returned %d\n", ret);
165
166         i2c_put_adapter(adpt);
167                 return ret;
168         }
169
170     DBG_INFO("i2c write done: bus = %d, addr = 0x%04X, reg = 0x%04X\n",
171         info->bus, info->addr, info->reg);
172
173     i2c_put_adapter(adpt);
174         return 0;
175 }
176
177 //------------------------------------------------------------------------------
178 static int i2c_ioctl( unsigned int cmd, unsigned long arg )
179 {
180     int ret = 0;
181     struct autotst_i2c_info_t iit;
182
183     if( copy_from_user(&iit, (const void __user *)arg, sizeof(struct autotst_i2c_info_t)) ) {
184         printk(KERN_ERR "copy_from_user fail: arg = %lu\n", arg);
185         return -EFAULT;
186     }
187
188     switch( cmd ) {
189     case AUTOTST_IOCTL_I2C_READ:
190         ret = i2c_read( &iit );
191         if( ret == 0 ) {
192             if( copy_to_user((void __user *)arg, &iit, sizeof(struct autotst_i2c_info_t)) ) {
193                 printk(KERN_ERR "copy_to_user fail: arg = %lu\n", arg);
194                 ret = -EFAULT;
195             }
196         }
197         break;
198     case AUTOTST_IOCTL_I2C_WRITE:
199         ret = i2c_write( &iit );
200         break;
201     default:
202         ret = -EINVAL;
203         break;
204     }
205     return ret;
206 }
207
208 //------------------------------------------------------------------------------
209 //------------------------------------------------------------------------------
210
211 static int gpio_ioctl( unsigned int cmd, unsigned long arg )
212 {
213     int ret = 0;
214     struct autotst_gpio_info_t git;
215
216     if( copy_from_user(&git, (const void __user *)arg, sizeof(struct autotst_gpio_info_t)) ) {
217         printk(KERN_ERR "copy_from_user fail: arg = %lu\n", arg);
218         return -EFAULT;
219     }
220
221     switch( cmd ) {
222     case AUTOTST_IOCTL_GPIO_INIT:
223     {
224         char name[32];
225         snprintf(name, 32, "at_gio_%d", git.gpio);
226 /*      // not support, already config on platform
227         if( git.pup_enb ) {
228         }
229         if( git.pdwn_enb ) {
230         }
231 */
232         gpio_request(git.gpio, name);
233         if( AUTOTST_GPIO_DIR_IN == git.dir ) {
234             gpio_direction_input(git.gpio);
235         } else {
236             gpio_direction_output(git.gpio, git.val);
237         }
238     }
239         break;
240     case AUTOTST_IOCTL_GPIO_GET: {
241                 int gv = gpio_get_value(git.gpio);
242
243         git.val = (gv > 0) ? 1 : 0;
244         if( copy_to_user((void __user *)arg, &git, sizeof(struct autotst_gpio_info_t)) ) {
245             printk(KERN_ERR "copy_to_user fail: arg = %lu\n", arg);
246             ret = -EFAULT;
247         }
248         }
249         break;
250     case AUTOTST_IOCTL_GPIO_SET:
251         gpio_set_value(git.gpio, git.val);
252         break;
253     default:
254         ret = -EINVAL;
255         break;
256     }
257     return ret;
258 }
259
260 //------------------------------------------------------------------------------
261 //------------------------------------------------------------------------------
262
263 static int key_ioctl( unsigned int cmd, unsigned long arg )
264 {
265         int ret = 0;
266         struct autotst_key_info_t kit;
267
268     if( copy_from_user(&kit, (const void __user *)arg, sizeof(struct autotst_key_info_t)) ) {
269         printk(KERN_ERR "copy_from_user fail: arg = %lu\n", arg);
270         return -EFAULT;
271     }
272
273         if( KEY_POWER == kit.val ) {
274                 kit.row = AUTOTST_KEY_INVALID_ROW;
275                 kit.col = AUTOTST_KEY_INVALID_COL;
276                 kit.gio = EIC_KEY_POWER;
277         } else {
278                 unsigned char rc = (kit.val & 0xF7);
279
280                 kit.row = ((rc >> 4) & 0x0F);
281                 kit.col = ((rc >> 0) & 0x0F);
282                 kit.gio = 0;
283         }
284
285         if( 0 == ret ) {
286                 if( copy_to_user((void __user *)arg, &kit, sizeof(struct autotst_key_info_t)) ) {
287             printk(KERN_ERR "copy_to_user fail: arg = %lu\n", arg);
288             ret = -EFAULT;
289         }
290         }
291
292         return ret;
293 }
294
295 //------------------------------------------------------------------------------
296 //------------------------------------------------------------------------------
297
298 static long autotst_ioctl( struct file *filp, unsigned int cmd, unsigned long arg )
299 {
300     long ret = -1;
301
302         FUN_ENTER;
303
304         DBG_INFO("cmd = 0x%X\n", cmd);
305     switch( cmd ) {
306     case AUTOTST_IOCTL_I2C_READ:
307     case AUTOTST_IOCTL_I2C_WRITE:
308         ret = i2c_ioctl(cmd, arg);
309         break;
310     case AUTOTST_IOCTL_GPIO_INIT:
311     case AUTOTST_IOCTL_GPIO_GET:
312     case AUTOTST_IOCTL_GPIO_SET:
313         ret = gpio_ioctl(cmd, arg);
314         break;
315     case AUTOTST_IOCTL_LCD_DATA:
316     {
317         int i;
318         DBG_INFO("lcd data = 0x%X\n", (uint32_t)arg);
319 #if 0
320         lcm_init();
321         for( i = 0; i < 32; ++i ) {
322             lcm_send_data((uint32_t)arg);
323         }
324 #else
325         autotst_dispc_init(DISPLAY_TYPE_MCU);
326         for( i = 0; i < 32; ++i ) {
327             autotst_dispc_mcu_send_data((uint32_t)arg);
328         }
329         autotst_dispc_uninit(DISPLAY_TYPE_MCU);
330 #endif
331         ret = 0;
332     }
333         break;
334 #if 1
335         case AUTOTST_IOCTL_LCD_MIPI_ON:
336         {
337                  int i;
338                  DBG_INFO("lcd mipi on\n");
339                 autotst_dispc_init(DISPLAY_TYPE_MIPI);
340                 autotst_dispc_refresh();
341                    ret = 0;
342         }
343         break;
344         case AUTOTST_IOCTL_LCD_MIPI_OFF:
345         {
346                  int i;
347                 DBG_INFO("lcd mipi off\n");
348                 autotst_dispc_uninit(DISPLAY_TYPE_MIPI);
349                    ret = 0;
350         }
351         break;
352 #endif
353         case AUTOTST_IOCTL_GET_KEYINFO:
354                 ret = key_ioctl(cmd, arg);
355                 break;
356     default:
357         ret = -EINVAL;
358          DBG_INFO("lcd default \n");
359         break;
360     }
361
362         FUN_LEAVE;
363     return ret;
364 }
365
366 static struct file_operations autotst_fops =
367 {
368     .owner          = THIS_MODULE,
369     .unlocked_ioctl = autotst_ioctl,
370     .open           = autotst_open,
371     .release        = autotst_release,
372 };
373
374 //==============================================================================
375
376 static int __init autotst_init(void)
377 {
378     int ret;
379
380     FUN_ENTER;
381
382         // auto select a major
383     ret = alloc_chrdev_region(&s_devt, 0, 1, CDEV_NAME);
384         if( ret < 0 ) {
385         printk(KERN_ERR "ERROR: alloc_chrdev_region %d\n", ret);
386         return ret;
387     }
388
389         cdev_init(&s_cdev, &autotst_fops);
390         ret = cdev_add(&s_cdev, s_devt, 1);
391     if( ret < 0 )
392         {
393                 unregister_chrdev_region(s_devt, 1);
394         printk(KERN_ERR "ERROR: cdev_add %d\n", ret);
395         return ret;
396         }
397
398     s_class = class_create(THIS_MODULE, CDEV_NAME);
399     device_create(s_class, NULL, MKDEV(MAJOR(s_devt), MINOR(s_devt)), NULL, CDEV_NAME);
400
401 //      autotst_dispc_pin_ctrl(DISPC_PIN_FUNC3);
402
403     //for( i = 0; i < SPRD_MAX_PIN; ++i ) {
404     //    sGpioPins[i] = SPRD_GPIO_PIN_INVALID_VALUE;
405     //}
406     //sGpioPins[59] = MFP_CFG_X(SIMCLK3,        AF3,    DS1,    F_PULL_NONE,    S_PULL_NONE,    IO_OE);
407
408     FUN_LEAVE;
409     return 0;
410 }
411
412 static void __exit autotst_exit(void)
413 {
414         FUN_ENTER;
415
416     device_destroy(s_class, MKDEV(MAJOR(s_devt), MINOR(s_devt)));
417     class_destroy(s_class);
418
419     cdev_del(&s_cdev);
420     unregister_chrdev_region(s_devt, 1);
421
422 //      autotst_dispc_pin_ctrl(DISPC_PIN_FUNC0);
423
424     FUN_LEAVE;
425 }
426
427 module_init(autotst_init);
428 module_exit(autotst_exit);
429
430 MODULE_LICENSE("Dual BSD/GPL");
431 MODULE_AUTHOR("anli.wei");
432 MODULE_VERSION("0.0.1");