1 /******************************************************************************
2 * mt_gpio.c - MTKLinux GPIO Device Driver
4 * Copyright 2008-2009 MediaTek Co.,Ltd.
7 * This file provid the other drivers GPIO relative functions
9 ******************************************************************************/
11 #include <linux/init.h>
12 #include <linux/module.h>
13 #include <linux/kernel.h>
14 #include <generated/autoconf.h>
15 #include <linux/platform_device.h>
17 #include <linux/ioctl.h>
19 #include <linux/types.h>
20 #include <linux/device.h>
21 #include <linux/slab.h>
22 #include <linux/spinlock.h>
23 #include <linux/cdev.h>
24 #include <asm/uaccess.h>
26 #include <asm/atomic.h>
27 #include <linux/miscdevice.h>
28 #include <linux/mtgpio.h> /* ioctl cmd */
30 #include <mach/mt_typedefs.h>
32 #include <mach/mt_gpio.h>
33 #include <mach/mt_gpio_core.h>
34 #include <mach/gpio_const.h>
36 /***********************/
38 /* char name[MT_GPIO_MAX_NAME]; */
39 int (*set_dir
) (unsigned long pin
, unsigned long dir
);
40 int (*get_dir
) (unsigned long pin
);
41 int (*set_pull_enable
) (unsigned long pin
, unsigned long enable
);
42 int (*get_pull_enable
) (unsigned long pin
);
43 int (*set_smt
) (unsigned long pin
, unsigned long enable
);
44 int (*get_smt
) (unsigned long pin
);
45 int (*set_ies
) (unsigned long pin
, unsigned long enable
);
46 int (*get_ies
) (unsigned long pin
);
47 int (*set_pull_select
) (unsigned long pin
, unsigned long select
);
48 int (*get_pull_select
) (unsigned long pin
);
49 int (*set_inversion
) (unsigned long pin
, unsigned long enable
);
50 int (*get_inversion
) (unsigned long pin
);
51 int (*set_out
) (unsigned long pin
, unsigned long output
);
52 int (*get_out
) (unsigned long pin
);
53 int (*get_in
) (unsigned long pin
);
54 int (*set_mode
) (unsigned long pin
, unsigned long mode
);
55 int (*get_mode
) (unsigned long pin
);
58 /*---------------------------------------------------------------------------*/
59 static struct mt_gpio_ops mt_base_ops
= {
60 .set_dir
= mt_set_gpio_dir_base
,
61 .get_dir
= mt_get_gpio_dir_base
,
62 .set_pull_enable
= mt_set_gpio_pull_enable_base
,
63 .get_pull_enable
= mt_get_gpio_pull_enable_base
,
64 .set_smt
= mt_set_gpio_smt_base
,
65 .get_smt
= mt_get_gpio_smt_base
,
66 .set_ies
= mt_set_gpio_ies_base
,
67 .get_ies
= mt_get_gpio_ies_base
,
68 .set_pull_select
= mt_set_gpio_pull_select_base
,
69 .get_pull_select
= mt_get_gpio_pull_select_base
,
70 .set_inversion
= mt_set_gpio_inversion_base
,
71 .get_inversion
= mt_get_gpio_inversion_base
,
72 .set_out
= mt_set_gpio_out_base
,
73 .get_out
= mt_get_gpio_out_base
,
74 .get_in
= mt_get_gpio_in_base
,
75 .set_mode
= mt_set_gpio_mode_base
,
76 .get_mode
= mt_get_gpio_mode_base
,
79 static struct mt_gpio_ops mt_ext_ops
= {
80 .set_dir
= mt_set_gpio_dir_ext
,
81 .get_dir
= mt_get_gpio_dir_ext
,
82 .set_pull_enable
= mt_set_gpio_pull_enable_ext
,
83 .get_pull_enable
= mt_get_gpio_pull_enable_ext
,
84 .set_smt
= mt_set_gpio_smt_ext
,
85 .get_smt
= mt_get_gpio_smt_ext
,
86 .set_ies
= mt_set_gpio_ies_ext
,
87 .get_ies
= mt_get_gpio_ies_ext
,
88 .set_pull_select
= mt_set_gpio_pull_select_ext
,
89 .get_pull_select
= mt_get_gpio_pull_select_ext
,
90 .set_inversion
= mt_set_gpio_inversion_ext
,
91 .get_inversion
= mt_get_gpio_inversion_ext
,
92 .set_out
= mt_set_gpio_out_ext
,
93 .get_out
= mt_get_gpio_out_ext
,
94 .get_in
= mt_get_gpio_in_ext
,
95 .set_mode
= mt_set_gpio_mode_ext
,
96 .get_mode
= mt_get_gpio_mode_ext
,
99 DEFINE_SPINLOCK(mt_gpio_lock
);
100 struct mt_gpio_obj_t
{
106 /* spinlock_t lock; */
107 struct miscdevice
*misc
;
108 struct mt_gpio_ops
*base_ops
;
109 struct mt_gpio_ops
*ext_ops
;
111 static struct mt_gpio_obj_t mt_gpio_obj
= {
112 .ref
= ATOMIC_INIT(0),
115 .base_ops
= &mt_base_ops
,
116 .ext_ops
= &mt_ext_ops
,
117 /* .lock = __SPIN_LOCK_UNLOCKED(die.lock), */
120 static struct mt_gpio_obj_t
*mt_gpio
= &mt_gpio_obj
;
122 #define MT_GPIO_OPS_SET(pin, operation, arg) \
123 ({ unsigned long flags;\
125 mt_gpio_pin_decrypt(&pin);\
126 spin_lock_irqsave(&mt_gpio_lock, flags);\
127 switch (MT_GPIO_PLACE(pin)) {\
129 if ((mt_gpio->base_ops == NULL) || (mt_gpio->base_ops->operation == NULL)) {\
130 GPIOERR("base access error, null point %d\n", (int)pin);\
133 retval = mt_gpio->base_ops->operation(pin, arg);\
135 GPIOERR("base operation fail %d\n", (int)retval);\
139 if ((mt_gpio->ext_ops == NULL) || (mt_gpio->ext_ops->operation == NULL)) {\
140 GPIOERR("extention access error, null point %d\n", (int)pin);\
141 retval = -ERWRAPPER;\
143 retval = mt_gpio->ext_ops->operation(pin, arg);\
145 GPIOERR("ext operation fail %d\n", (int)retval);\
149 GPIOERR("Parameter error: %d\n", (int)pin);\
153 spin_unlock_irqrestore(&mt_gpio_lock, flags);\
156 /* GPIOLOG("%s(%d)\n","operation",pin); */
157 #define MT_GPIO_OPS_GET(pin, operation) \
159 mt_gpio_pin_decrypt(&pin);\
160 switch (MT_GPIO_PLACE(pin)) {\
162 if ((mt_gpio->base_ops == NULL) || (mt_gpio->base_ops->operation == NULL)) {\
163 GPIOERR("base access error, null point %d\n", (int)pin);\
166 retval = mt_gpio->base_ops->operation(pin);\
168 GPIOERR("base operation fail %d\n", (int)retval);\
172 if ((mt_gpio->ext_ops == NULL) || (mt_gpio->ext_ops->operation == NULL)) {\
173 GPIOERR("extention access error, null point %d\n", (int)pin);\
174 retval = -ERWRAPPER;\
176 retval = mt_gpio->ext_ops->operation(pin);\
178 GPIOERR("ext operation fail %d\n", (int)retval);\
182 GPIOERR("Parameter pin number error: %d\n", (int)pin);\
188 int mt_set_gpio_dir(unsigned long pin
, unsigned long dir
)
191 if (dir
>= GPIO_DIR_MAX
) {
192 GPIOERR("Parameter dir error: %d\n", (int)dir
);
196 return MT_GPIO_OPS_SET(pin
, set_dir
, dir
);
198 EXPORT_SYMBOL(mt_set_gpio_dir
);
199 /*---------------------------------------------------------------------------*/
200 int mt_get_gpio_dir(unsigned long pin
)
202 return MT_GPIO_OPS_GET(pin
, get_dir
);
204 EXPORT_SYMBOL(mt_get_gpio_dir
);
205 /*---------------------------------------------------------------------------*/
206 int mt_set_gpio_pull_enable(unsigned long pin
, unsigned long enable
)
208 if (enable
>= GPIO_PULL_EN_MAX
) {
209 GPIOERR("Parameter enable error: %d\n", (int)enable
);
213 return MT_GPIO_OPS_SET(pin
, set_pull_enable
, enable
);
215 EXPORT_SYMBOL(mt_set_gpio_pull_enable
);
216 /*---------------------------------------------------------------------------*/
217 int mt_get_gpio_pull_enable(unsigned long pin
)
219 return MT_GPIO_OPS_GET(pin
, get_pull_enable
);
221 EXPORT_SYMBOL(mt_get_gpio_pull_enable
);
222 /*---------------------------------------------------------------------------*/
223 int mt_set_gpio_smt(unsigned long pin
, unsigned long enable
)
225 if (enable
>= GPIO_SMT_MAX
){
226 GPIOERR("Parameter enable error: %d\n",(int)enable
);
229 return MT_GPIO_OPS_SET(pin
,set_smt
,enable
);
231 EXPORT_SYMBOL(mt_set_gpio_smt
);
232 /*---------------------------------------------------------------------------*/
233 int mt_get_gpio_smt(unsigned long pin
)
235 return MT_GPIO_OPS_GET(pin
,get_smt
);
237 EXPORT_SYMBOL(mt_get_gpio_smt
);
238 /*---------------------------------------------------------------------------*/
239 int mt_set_gpio_ies(unsigned long pin
, unsigned long enable
)
241 if (enable
>= GPIO_IES_MAX
) {
242 GPIOERR("Parameter enable error: %d\n", (int)enable
);
245 return MT_GPIO_OPS_SET(pin
, set_ies
, enable
);
247 EXPORT_SYMBOL(mt_set_gpio_ies
);
248 /*---------------------------------------------------------------------------*/
249 int mt_get_gpio_ies(unsigned long pin
)
251 return MT_GPIO_OPS_GET(pin
, get_ies
);
253 EXPORT_SYMBOL(mt_get_gpio_ies
);
254 /*---------------------------------------------------------------------------*/
255 int mt_set_gpio_pull_select(unsigned long pin
, unsigned long select
)
257 if (select
>= GPIO_PULL_MAX
) {
258 GPIOERR("Parameter select error: %d\n", (int)select
);
261 return MT_GPIO_OPS_SET(pin
, set_pull_select
, select
);
263 EXPORT_SYMBOL(mt_get_gpio_pull_select
);
264 /*---------------------------------------------------------------------------*/
265 int mt_get_gpio_pull_select(unsigned long pin
)
267 return MT_GPIO_OPS_GET(pin
, get_pull_select
);
269 EXPORT_SYMBOL(mt_set_gpio_pull_select
);
270 /*---------------------------------------------------------------------------*/
271 int mt_set_gpio_inversion(unsigned long pin
, unsigned long enable
)
273 if (enable
>= GPIO_DATA_INV_MAX
) {
274 GPIOERR("Parameter enable error: %d\n", (int)enable
);
277 return MT_GPIO_OPS_SET(pin
, set_inversion
, enable
);
279 EXPORT_SYMBOL(mt_set_gpio_inversion
);
280 /*---------------------------------------------------------------------------*/
281 int mt_get_gpio_inversion(unsigned long pin
)
283 return MT_GPIO_OPS_GET(pin
, get_inversion
);
285 EXPORT_SYMBOL(mt_get_gpio_inversion
);
286 /*---------------------------------------------------------------------------*/
287 int mt_set_gpio_out(unsigned long pin
, unsigned long output
)
289 if (output
>= GPIO_OUT_MAX
) {
290 GPIOERR("Parameter output error: %d\n", (int)output
);
293 return MT_GPIO_OPS_SET(pin
, set_out
, output
);
295 EXPORT_SYMBOL(mt_set_gpio_out
);
296 /*---------------------------------------------------------------------------*/
297 int mt_get_gpio_out(unsigned long pin
)
299 return MT_GPIO_OPS_GET(pin
, get_out
);
301 EXPORT_SYMBOL(mt_get_gpio_out
);
302 /*---------------------------------------------------------------------------*/
303 int mt_get_gpio_in(unsigned long pin
)
305 return MT_GPIO_OPS_GET(pin
, get_in
);
307 EXPORT_SYMBOL(mt_get_gpio_in
);
308 /*---------------------------------------------------------------------------*/
309 int mt_set_gpio_mode(unsigned long pin
, unsigned long mode
)
311 if (mode
>= GPIO_MODE_MAX
) {
312 GPIOERR("Parameter mode error: %d\n", (int)mode
);
315 return MT_GPIO_OPS_SET(pin
, set_mode
, mode
);
317 EXPORT_SYMBOL(mt_set_gpio_mode
);
318 /*---------------------------------------------------------------------------*/
319 int mt_get_gpio_mode(unsigned long pin
)
321 return MT_GPIO_OPS_GET(pin
, get_mode
);
323 EXPORT_SYMBOL(mt_get_gpio_mode
);
325 /*****************************************************************************/
327 /*****************************************************************************/
328 static int mt_gpio_open(struct inode
*inode
, struct file
*file
)
330 struct mt_gpio_obj_t
*obj
= mt_gpio
;
334 GPIOERR("NULL pointer");
338 atomic_inc(&obj
->ref
);
339 file
->private_data
= obj
;
340 return nonseekable_open(inode
, file
);
343 /*---------------------------------------------------------------------------*/
344 static int mt_gpio_release(struct inode
*inode
, struct file
*file
)
346 struct mt_gpio_obj_t
*obj
= mt_gpio
;
351 GPIOERR("NULL pointer");
355 atomic_dec(&obj
->ref
);
359 /*---------------------------------------------------------------------------*/
360 static long mt_gpio_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
362 struct mt_gpio_obj_t
*obj
= mt_gpio
;
369 GPIOERR("NULL pointer");
376 pin
= (unsigned long)arg
;
377 res
= GIO_INVALID_OBJ(obj
) ? (-EACCES
) : mt_get_gpio_mode(pin
);
382 pin
= (unsigned long)arg
;
384 GIO_INVALID_OBJ(obj
) ? (-EACCES
) : mt_set_gpio_mode(pin
, GPIO_MODE_00
);
389 pin
= (unsigned long)arg
;
391 GIO_INVALID_OBJ(obj
) ? (-EACCES
) : mt_set_gpio_mode(pin
, GPIO_MODE_01
);
396 pin
= (unsigned long)arg
;
398 GIO_INVALID_OBJ(obj
) ? (-EACCES
) : mt_set_gpio_mode(pin
, GPIO_MODE_02
);
403 pin
= (unsigned long)arg
;
405 GIO_INVALID_OBJ(obj
) ? (-EACCES
) : mt_set_gpio_mode(pin
, GPIO_MODE_03
);
410 pin
= (unsigned long)arg
;
411 res
= GIO_INVALID_OBJ(obj
) ? (-EACCES
) : mt_get_gpio_dir(pin
);
416 pin
= (unsigned long)arg
;
417 res
= GIO_INVALID_OBJ(obj
) ? (-EACCES
) : mt_set_gpio_dir(pin
, GPIO_DIR_IN
);
420 case GPIO_IOCSDIROUT
:
422 pin
= (unsigned long)arg
;
423 res
= GIO_INVALID_OBJ(obj
) ? (-EACCES
) : mt_set_gpio_dir(pin
, GPIO_DIR_OUT
);
426 case GPIO_IOCQPULLEN
:
428 pin
= (unsigned long)arg
;
429 res
= GIO_INVALID_OBJ(obj
) ? (-EACCES
) : mt_get_gpio_pull_enable(pin
);
432 case GPIO_IOCSPULLENABLE
:
434 pin
= (unsigned long)arg
;
435 res
= GIO_INVALID_OBJ(obj
) ? (-EACCES
) : mt_set_gpio_pull_enable(pin
, TRUE
);
438 case GPIO_IOCSPULLDISABLE
:
440 pin
= (unsigned long)arg
;
442 GIO_INVALID_OBJ(obj
) ? (-EACCES
) : mt_set_gpio_pull_enable(pin
, FALSE
);
447 pin
= (unsigned long)arg
;
448 res
= GIO_INVALID_OBJ(obj
) ? (-EACCES
) : mt_get_gpio_pull_select(pin
);
451 case GPIO_IOCSPULLDOWN
:
453 pin
= (unsigned long)arg
;
455 GIO_INVALID_OBJ(obj
) ? (-EACCES
) : mt_set_gpio_pull_select(pin
,
459 case GPIO_IOCSPULLUP
:
461 pin
= (unsigned long)arg
;
463 GIO_INVALID_OBJ(obj
) ? (-EACCES
) : mt_set_gpio_pull_select(pin
,
469 pin
= (unsigned long)arg
;
470 res
= GIO_INVALID_OBJ(obj
) ? (-EACCES
) : mt_get_gpio_inversion(pin
);
473 case GPIO_IOCSINVENABLE
:
475 pin
= (unsigned long)arg
;
476 res
= GIO_INVALID_OBJ(obj
) ? (-EACCES
) : mt_set_gpio_inversion(pin
, TRUE
);
479 case GPIO_IOCSINVDISABLE
:
481 pin
= (unsigned long)arg
;
482 res
= GIO_INVALID_OBJ(obj
) ? (-EACCES
) : mt_set_gpio_inversion(pin
, FALSE
);
485 case GPIO_IOCQDATAIN
:
487 pin
= (unsigned long)arg
;
488 res
= GIO_INVALID_OBJ(obj
) ? (-EFAULT
) : mt_get_gpio_in(pin
);
491 case GPIO_IOCQDATAOUT
:
493 pin
= (unsigned long)arg
;
494 res
= GIO_INVALID_OBJ(obj
) ? (-EACCES
) : mt_get_gpio_out(pin
);
497 case GPIO_IOCSDATALOW
:
499 pin
= (unsigned long)arg
;
501 GIO_INVALID_OBJ(obj
) ? (-EACCES
) : mt_set_gpio_out(pin
, GPIO_OUT_ZERO
);
504 case GPIO_IOCSDATAHIGH
:
506 pin
= (unsigned long)arg
;
507 res
= GIO_INVALID_OBJ(obj
) ? (-EACCES
) : mt_set_gpio_out(pin
, GPIO_OUT_ONE
);
518 GPIOERR(" cmd = 0x%8X, invalid pointer\n", cmd
);
520 GPIOERR(" cmd = 0x%8X, err = %ld\n", cmd
, res
);
524 /*---------------------------------------------------------------------------*/
525 static struct file_operations mt_gpio_fops
= {
526 .owner
= THIS_MODULE
,
527 .unlocked_ioctl
= mt_gpio_ioctl
,
529 .compat_ioctl
= mt_gpio_ioctl
,
531 .open
= mt_gpio_open
,
532 .release
= mt_gpio_release
,
535 /*----------------------------------------------------------------------------*/
536 static struct miscdevice mt_gpio_device
= {
537 .minor
= MISC_DYNAMIC_MINOR
,
539 .fops
= &mt_gpio_fops
,
542 /*---------------------------------------------------------------------------*/
543 static int mt_gpio_probe(struct platform_device
*dev
)
546 struct miscdevice
*misc
= &mt_gpio_device
;
549 if (dev
->dev
.of_node
) {
550 /* Setup IO addresses */
551 get_gpio_vbase(dev
->dev
.of_node
);
556 #ifdef CONFIG_MD32_SUPPORT
557 md32_gpio_handle_init();
560 /* printk(KERN_ALERT"[GPIO]%5d,<%s> gpio devices probe\n", __LINE__, __func__); */
561 GPIOLOG("Registering GPIO device\n");
564 GPIO_RETERR(-EACCES
, "");
565 mt_gpio
->misc
= misc
;
567 if ((err
= misc_register(misc
)))
568 GPIOERR("register gpio\n");
570 if ((err
= mt_gpio_create_attr(misc
->this_device
)))
571 GPIOERR("create attribute\n");
573 dev_set_drvdata(misc
->this_device
, mt_gpio
);
578 /*---------------------------------------------------------------------------*/
579 static int mt_gpio_remove(struct platform_device
*dev
)
581 struct mt_gpio_obj_t
*obj
= platform_get_drvdata(dev
);
584 if ((err
= mt_gpio_delete_attr(obj
->misc
->this_device
)))
585 GPIOERR("delete attr\n");
587 if ((err
= misc_deregister(obj
->misc
)))
588 GPIOERR("deregister gpio\n");
593 /*---------------------------------------------------------------------------*/
595 /*---------------------------------------------------------------------------*/
596 static int mtk_gpio_suspend(struct platform_device
*pdev
, pm_message_t state
)
603 /*---------------------------------------------------------------------------*/
604 static int mtk_gpio_resume(struct platform_device
*pdev
)
611 /*---------------------------------------------------------------------------*/
612 #endif /*CONFIG_PM */
613 /*---------------------------------------------------------------------------*/
614 /*---------------------------------------------------------------------------*/
616 static const struct of_device_id apgpio_of_ids
[] = {
617 { .compatible
= "mediatek,GPIO", },
622 static struct platform_driver gpio_driver
= {
623 .probe
= mt_gpio_probe
,
624 .remove
= mt_gpio_remove
,
626 .suspend
= mtk_gpio_suspend
,
627 .resume
= mtk_gpio_resume
,
632 .of_match_table
= apgpio_of_ids
,
638 struct device_node
*get_gpio_np(void)
640 gpio_vbase
.gpio_regs
= NULL
;
641 struct device_node
*np_gpio
;
642 np_gpio
= of_find_compatible_node(NULL
, NULL
, apgpio_of_ids
[0].compatible
);
643 if(np_gpio
== NULL
) {
644 GPIOERR("GPIO device node is NULL\n");
651 /*---------------------------------------------------------------------------*/
653 /*---------------------------------------------------------------------------*/
654 static int __init
mt_gpio_init(void)
657 GPIOLOG("version: %s\n", VERSION
);
659 ret
= platform_driver_register(&gpio_driver
);
663 /*---------------------------------------------------------------------------*/
664 static void __exit
mt_gpio_exit(void)
666 platform_driver_unregister(&gpio_driver
);
670 /* void gpio_dump_regs(void) */
674 /*---------------------------------------------------------------------------*/
675 module_init(mt_gpio_init
);
676 module_exit(mt_gpio_exit
);
677 MODULE_AUTHOR("Ranran <ranran.lu@mediatek.com>");
678 MODULE_DESCRIPTION("MT General Purpose Driver (GPIO) $Revision$");
679 MODULE_LICENSE("GPL");
680 /*---------------------------------------------------------------------------*/